Module: Rigor::Source::Literals

Defined in:
lib/rigor/source/literals.rb

Overview

Extracts literal Symbol/String values from Prism call arguments.

The “is this argument a literal ‘:sym` or `”str“`, and if so what Symbol does it name?” question recurs across the analyzer (sig-gen observation, attr-accessor generation, synthetic-method scanning) and across nearly every DSL plugin (`state :draft`, `has_one_attached :avatar`, `validate_presence_of(:name)`, …). This module is the one place that answers it, so the `node.unescaped.to_sym if SymbolNode || StringNode` shape is written once rather than copied per call site.

‘#unescaped` (not `#value`) is used deliberately so an interpolation- free `“foo”` / `:foo` round-trips to `:foo` consistently for both node kinds.

The surface is a small grid over two axes — which node kinds are accepted (‘SymbolNode` only, or `SymbolNode`/`StringNode`) and what the caller wants back (the interned `Symbol`, or the raw `String` name). The SymbolNode-only forms (Literals.symbol / Literals.symbol_name) exist so a DSL that distinguishes `state :draft` from `state “draft”` keeps that distinction instead of silently widening to accept the string literal.

| accepts | → Symbol | → String | | —————— | ——————- | ———————— | | ‘:sym` only | Literals.symbol | Literals.symbol_name | | `:sym` or `“str”` | Literals.symbol_or_string | Literals.symbol_or_string_name |

Class Method Summary collapse

Class Method Details

.symbol(node) ⇒ Symbol?

The Symbol a literal ‘Prism::SymbolNode` names, or `nil` for any other node (including a `Prism::StringNode` and `nil`). Stricter than symbol_or_string: a DSL that accepts only `:draft` and not `“draft”` keeps that distinction by reaching for this rather than the Symbol-or-String form.

Parameters:

  • node (Prism::Node, nil)

Returns:

  • (Symbol, nil)


71
72
73
74
75
# File 'lib/rigor/source/literals.rb', line 71

def symbol(node)
  return nil unless node.is_a?(Prism::SymbolNode)

  node.unescaped.to_sym
end

.symbol_arg(call_node, index) ⇒ Symbol?

The literal Symbol/String at positional ‘index`, or `nil` when the call has no argument list, the index is out of range, or the argument there is not a literal Symbol/String.

Parameters:

  • call_node (Prism::CallNode, nil)
  • index (Integer)

Returns:

  • (Symbol, nil)


110
111
112
113
114
115
# File 'lib/rigor/source/literals.rb', line 110

def symbol_arg(call_node, index)
  args = call_node&.arguments&.arguments
  return nil if args.nil?

  symbol_or_string(args[index])
end

.symbol_arguments(call_node) ⇒ Array<Symbol>

Every literal Symbol/String positional argument of a call, in source order. Non-literal arguments are dropped. Returns ‘[]` when the call has no argument list.

Parameters:

  • call_node (Prism::CallNode, nil)

Returns:

  • (Array<Symbol>)


96
97
98
99
100
101
# File 'lib/rigor/source/literals.rb', line 96

def symbol_arguments(call_node)
  args = call_node&.arguments&.arguments
  return [] if args.nil?

  args.filter_map { |arg| symbol_or_string(arg) }
end

.symbol_name(node) ⇒ String?

The String a literal ‘Prism::SymbolNode` names, or `nil` for any other node (including a `Prism::StringNode` and `nil`). The String-returning sibling of symbol — SymbolNode-only, but the caller wants the raw name rather than the interned Symbol.

Parameters:

  • node (Prism::Node, nil)

Returns:

  • (String, nil)


84
85
86
87
88
# File 'lib/rigor/source/literals.rb', line 84

def symbol_name(node)
  return nil unless node.is_a?(Prism::SymbolNode)

  node.unescaped
end

.symbol_or_string(node) ⇒ Symbol?

The Symbol a literal ‘Prism::SymbolNode` / `Prism::StringNode` names, or `nil` for any other node (including `nil`).

Parameters:

  • node (Prism::Node, nil)

Returns:

  • (Symbol, nil)


42
43
44
45
46
# File 'lib/rigor/source/literals.rb', line 42

def symbol_or_string(node)
  return nil unless node.is_a?(Prism::SymbolNode) || node.is_a?(Prism::StringNode)

  node.unescaped.to_sym
end

.symbol_or_string_name(node) ⇒ String?

The String a literal ‘Prism::SymbolNode` / `Prism::StringNode` names, or `nil` for any other node (including `nil`). The String-returning sibling of symbol_or_string — for callers that key on the raw name rather than the interned Symbol (route helpers, factory names, filter targets). `#unescaped` round-trips an interpolation-free `:foo` / `“foo”` to `“foo”` for both kinds.

Parameters:

  • node (Prism::Node, nil)

Returns:

  • (String, nil)


57
58
59
60
61
# File 'lib/rigor/source/literals.rb', line 57

def symbol_or_string_name(node)
  return nil unless node.is_a?(Prism::SymbolNode) || node.is_a?(Prism::StringNode)

  node.unescaped
end