Module: Rigor::ModuleGraph::ConstantName
- Defined in:
- lib/rigor/module_graph/constant_name.rb
Overview
Resolves a fully-qualified constant name from Prism AST nodes and lexical ancestor chains.
Three things this module handles that the bare Prism API does not give you in one place:
- Owner from lexical nesting.
node.constant_path.full_nameon aclass Billing::Invoiceonly returns"Invoice"; the outermodule Billingdoes not enter unless we walk ancestors ourselves. - Absolute paths (
::Foo::Bar). Prism encodes the leading::as an empty-symbol:""infull_name_parts; we render it as"::Foo::Bar". - Mixed AST shapes.
ClassNode#constant_pathis either aConstantReadNode(single name) or aConstantPathNode(dotted path); same forsuperclassandincludeargs.
Class Method Summary collapse
- .full_name_for_path(node) ⇒ Object
-
.lexical_owner(context) ⇒ Object
Build the lexical-nesting owner string for a node, by walking
context.ancestorsfrom outer to inner and joining every enclosingClassNode/ModuleNodeconstant path with::. -
.lexical_owner_with(context, extra) ⇒ Object
Same as
#lexical_owner, but withextraappended as the innermost element. - .lexical_parts(ancestors) ⇒ Object
-
.render(node) ⇒ Object
Render a single Prism constant node into a string like
"Foo","Foo::Bar", or"::Foo::Bar".
Class Method Details
.full_name_for_path(node) ⇒ Object
74 75 76 77 78 79 80 81 82 83 |
# File 'lib/rigor/module_graph/constant_name.rb', line 74 def full_name_for_path(node) parts = node.full_name_parts # Prism encodes a leading `::` as an empty-symbol first # part. Render it as a literal `"::"` prefix. if parts.first == :"" "::" + parts.drop(1).join("::") else parts.join("::") end end |
.lexical_owner(context) ⇒ Object
Build the lexical-nesting owner string for a node, by
walking context.ancestors from outer to inner and joining
every enclosing ClassNode/ModuleNode constant path with
::. Returns nil when no class/module encloses the node.
43 44 45 46 47 48 |
# File 'lib/rigor/module_graph/constant_name.rb', line 43 def lexical_owner(context) parts = lexical_parts(context.ancestors) return nil if parts.empty? parts.join("::") end |
.lexical_owner_with(context, extra) ⇒ Object
Same as #lexical_owner, but with extra appended as the
innermost element. Used to build the owner of a class or
module decl itself: pass context.ancestors (which does NOT
include the node itself) plus the node's own constant path.
54 55 56 57 58 59 60 |
# File 'lib/rigor/module_graph/constant_name.rb', line 54 def lexical_owner_with(context, extra) parts = lexical_parts(context.ancestors) parts << extra unless extra.nil? || extra.empty? return nil if parts.empty? parts.join("::") end |
.lexical_parts(ancestors) ⇒ Object
62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/rigor/module_graph/constant_name.rb', line 62 def lexical_parts(ancestors) ancestors.flat_map do |ancestor| case ancestor when Prism::ClassNode, Prism::ModuleNode name = render(ancestor.constant_path) name ? [name] : [] else [] end end end |
.render(node) ⇒ Object
Render a single Prism constant node into a string like
"Foo", "Foo::Bar", or "::Foo::Bar". Returns nil when
the node is not a constant carrier (e.g. include SOME_VAR
where the arg is a CallNode).
30 31 32 33 34 35 36 37 |
# File 'lib/rigor/module_graph/constant_name.rb', line 30 def render(node) case node when Prism::ConstantReadNode node.name.to_s when Prism::ConstantPathNode full_name_for_path(node) end end |