Class: Prism::Node
| Relationships & Source Files | |
| Inherits: | Object |
| Defined in: | lib/prism/node.rb, ext/prism/extension.c, lib/prism/node_ext.rb, lib/prism/parse_result/newlines.rb |
Overview
This represents a node in the tree. It is the parent class of all of the various node types.
Class Method Summary
Instance Attribute Summary
-
#newline? ⇒ Boolean
readonly
Returns true if the node has the newline flag set.
-
#node_id
readonly
A unique identifier for this node.
-
#static_literal? ⇒ Boolean
readonly
Returns true if the node has the static literal flag set.
-
#flags
readonly
protected
An bitset of flags for this node.
-
#source
readonly
private
A pointer to the source that this node was created from.
- #newline_flag? ⇒ Boolean readonly Internal use only
Instance Method Summary
-
#accept(visitor)
Accepts a visitor and calls back into the specialized visit function.
-
#breadth_first_search(&block)
Returns the first node that matches the given block when visited in a depth-first search.
-
#child_nodes
(also: #deconstruct)
Returns an array of child nodes, including
nils in the place of optional nodes that were not present. -
#comment_targets
Returns an array of child nodes and locations that could potentially have comments attached to them.
-
#compact_child_nodes
Returns an array of child nodes, excluding any
nils in the place of optional nodes that were not present. -
#deconstruct
Alias for #child_nodes.
-
#end_offset
The end offset of the node in the source.
-
#inspect
Returns a string representation of the node.
-
#location
A Location instance that represents the location of this node in the source.
-
#pretty_print(q)
Similar to inspect, but respects the current level of indentation given by the pretty print object.
-
#script_lines
Alias for #source_lines.
-
#slice
Slice the location of the node from the source.
-
#slice_lines
Slice the location of the node from the source, starting at the beginning of the line that the location starts on, ending at the end of the line that the location ends on.
-
#source_lines
(also: #script_lines)
Returns all of the lines of the source code associated with this node.
-
#start_offset
The start offset of the node in the source.
-
#to_dot
Convert this node into a graphviz dot graph string.
-
#tunnel(line, column)
Returns a list of nodes that are descendants of this node that contain the given line and column.
-
#type
Sometimes you want to check an instance of a node against a list of classes to see what kind of behavior to perform.
- #deprecated(*replacements) Internal use only
- #newline_flag!(lines) Internal use only
Class Method Details
.fields
Returns a list of the fields that exist for this node class. Fields describe the structure of the node. This kind of reflection is useful for things like recursively visiting each node and field in the tree.
# File 'lib/prism/node.rb', line 153
def self.fields # This method should only be called on subclasses of Node, not Node # itself. raise NoMethodError, "undefined method `fields' for #{inspect}" if self == Node Reflection.fields_for(self) end
.type
# File 'lib/prism/node.rb', line 218
def self.type raise NoMethodError, "undefined method `type' for #{inspect}" end
Instance Attribute Details
#flags (readonly, protected)
An bitset of flags for this node. There are certain flags that are common for all nodes, and then some nodes have specific flags.
# File 'lib/prism/node.rb', line 68
attr_reader :flags
#newline? ⇒ Boolean (readonly)
Returns true if the node has the newline flag set.
#newline_flag? ⇒ Boolean (readonly)
# File 'lib/prism/parse_result/newlines.rb', line 66
def newline_flag? # :nodoc: !!defined?(@newline_flag) end
#node_id (readonly)
A unique identifier for this node. This is used in a very specific use case where you want to keep around a reference to a node without having to keep around the syntax tree in memory. This unique identifier will be consistent across multiple parses of the same source code.
# File 'lib/prism/node.rb', line 21
attr_reader :node_id
#source (readonly, private)
A pointer to the source that this node was created from.
# File 'lib/prism/node.rb', line 14
attr_reader :source
#static_literal? ⇒ Boolean (readonly)
Returns true if the node has the static literal flag set.
# File 'lib/prism/node.rb', line 77
def static_literal? flags.anybits?(NodeFlags::STATIC_LITERAL) end
Instance Method Details
#accept(visitor)
Accepts a visitor and calls back into the specialized visit function.
# File 'lib/prism/node.rb', line 169
def accept(visitor) raise NoMethodError, "undefined method `accept' for #{inspect}" end
#breadth_first_search(&block)
# File 'lib/prism/node.rb', line 139
def breadth_first_search(&block) queue = [self] #: Array[Prism::node] while (node = queue.shift) return node if yield node queue.concat(node.compact_child_nodes) end nil end
#child_nodes Also known as: #deconstruct
Returns an array of child nodes, including nils in the place of optional
nodes that were not present.
# File 'lib/prism/node.rb', line 175
def child_nodes raise NoMethodError, "undefined method `child_nodes' for #{inspect}" end
#comment_targets
Returns an array of child nodes and locations that could potentially have comments attached to them.
# File 'lib/prism/node.rb', line 189
def comment_targets raise NoMethodError, "undefined method `comment_targets' for #{inspect}" end
#compact_child_nodes
Returns an array of child nodes, excluding any nils in the place of
optional nodes that were not present.
# File 'lib/prism/node.rb', line 183
def compact_child_nodes raise NoMethodError, "undefined method `compact_child_nodes' for #{inspect}" end
#deconstruct
Alias for #child_nodes.
# File 'lib/prism/node.rb', line 179
alias deconstruct child_nodes
#deprecated(*replacements)
# File 'lib/prism/node_ext.rb', line 10
def deprecated(*replacements) # :nodoc: location = caller_locations(1, 1) location = location[0].label if location suggest = replacements.map { |replacement| "#{self.class}##{replacement}" } warn(<<~MSG, uplevel: 1, category: :deprecated) [deprecation]: #{self.class}##{location} is deprecated and will be \ removed in the next major version. Use #{suggest.join("/")} instead. #{(caller(1, 3) || []).join("\n")} MSG end
#end_offset
The end offset of the node in the source. This method is effectively a delegate method to the location object.
#inspect
Returns a string representation of the node.
# File 'lib/prism/node.rb', line 194
def inspect raise NoMethodError, "undefined method `inspect' for #{inspect}" end
#location
A Location instance that represents the location of this node in the source.
#newline_flag!(lines)
# File 'lib/prism/parse_result/newlines.rb', line 70
def newline_flag!(lines) # :nodoc: line = location.start_line unless lines[line] lines[line] = true @newline_flag = true end end
#pretty_print(q)
Similar to inspect, but respects the current level of indentation given by the pretty print object.
# File 'lib/prism/node.rb', line 83
def pretty_print(q) q.seplist(inspect.chomp.each_line, -> { q.breakable }) do |line| q.text(line.chomp) end q.current_group.break end
#script_lines
Alias for #source_lines.
# File 'lib/prism/node.rb', line 52
alias script_lines source_lines
#slice
Slice the location of the node from the source.
# File 'lib/prism/node.rb', line 55
def slice location.slice end
#slice_lines
Slice the location of the node from the source, starting at the beginning of the line that the location starts on, ending at the end of the line that the location ends on.
# File 'lib/prism/node.rb', line 62
def slice_lines location.slice_lines end
#source_lines Also known as: #script_lines
Returns all of the lines of the source code associated with this node.
# File 'lib/prism/node.rb', line 46
def source_lines location.source_lines end
#start_offset
The start offset of the node in the source. This method is effectively a delegate method to the location object.
#to_dot
Convert this node into a graphviz dot graph string.
# File 'lib/prism/node.rb', line 91
def to_dot # @type self: node DotVisitor.new.tap { |visitor| accept(visitor) }.to_dot end
#tunnel(line, column)
Returns a list of nodes that are descendants of this node that contain the given line and column. This is useful for locating a node that is selected based on the line and column of the source code.
Important to note is that the column given to this method should be in bytes, as opposed to characters or code units.
# File 'lib/prism/node.rb', line 102
def tunnel(line, column) queue = [self] #: Array[Prism::node] result = [] while (node = queue.shift) result << node node.compact_child_nodes.each do |child_node| child_location = child_node.location start_line = child_location.start_line end_line = child_location.end_line if start_line == end_line if line == start_line && column >= child_location.start_column && column < child_location.end_column queue << child_node break end elsif (line == start_line && column >= child_location.start_column) || (line == end_line && column < child_location.end_column) queue << child_node break elsif line > start_line && line < end_line queue << child_node break end end end result end
#type
Sometimes you want to check an instance of a node against a list of
classes to see what kind of behavior to perform. Usually this is done by
calling [cls1, cls2].include?(node.class) or putting the node into a
case statement and doing case node; when cls1; when cls2; end. Both of
these approaches are relatively slow because of the constant lookups,
method calls, and/or array allocations.
Instead, you can call #type, which will return to you a symbol that you
can use for comparison. This is faster than the other approaches because
it uses a single integer comparison, but also because if you're on CRuby
you can take advantage of the fact that case statements with all symbol
keys will use a jump table.
# File 'lib/prism/node.rb', line 210
def type raise NoMethodError, "undefined method `type' for #{inspect}" end