Class: Prism::Node
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.
-
#cached_end_code_units_column(cache)
Delegates to the cached_end_code_units_column of the associated location object.
-
#cached_end_code_units_offset(cache)
Delegates to the cached_end_code_units_offset of the associated location object.
-
#cached_start_code_units_column(cache)
Delegates to the cached_start_code_units_column of the associated location object.
-
#cached_start_code_units_offset(cache)
Delegates to the cached_start_code_units_offset of the associated location object.
-
#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.
-
#comments
Delegates to the comments of the associated location object.
-
#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.
-
#each_child_node
With a block given, yields each child node.
-
#end_character_column
Delegates to the end_character_column of the associated location object.
-
#end_character_offset
Delegates to the end_character_offset of the associated location object.
-
#end_column
Delegates to the end_column of the associated location object.
-
#end_line
Delegates to the end_line of the associated location object.
-
#end_offset
The end offset of the node in the source.
-
#inspect
Returns a string representation of the node.
-
#leading_comments
Delegates to the leading_comments of the associated location object.
-
#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.
-
#save(repository)
Save this node using a saved source so that it can be retrieved later.
-
#save_location(repository)
Save the location using a saved source so that it can be retrieved later.
-
#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_character_column
Delegates to the start_character_column of the associated location object.
-
#start_character_offset
Delegates to the start_character_offset of the associated location object.
-
#start_column
Delegates to the start_column of the associated location object.
-
#start_line
Delegates to the start_line of the associated location object.
-
#start_offset
The start offset of the node in the source.
-
#to_dot
Convert this node into a graphviz dot graph string.
-
#trailing_comments
Delegates to the trailing_comments of the associated location object.
-
#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 234
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 306
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 160
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 24
attr_reader :node_id
#source (readonly, private)
A pointer to the source that this node was created from.
# File 'lib/prism/node.rb', line 17
attr_reader :source
#static_literal? ⇒ Boolean (readonly)
Returns true if the node has the static literal flag set.
# File 'lib/prism/node.rb', line 169
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 250
def accept(visitor) raise NoMethodError, "undefined method `accept' for #{inspect}" end
#breadth_first_search(&block)
# File 'lib/prism/node.rb', line 220
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
#cached_end_code_units_column(cache)
Delegates to the cached_end_code_units_column of the associated location object.
# File 'lib/prism/node.rb', line 118
def cached_end_code_units_column(cache) location.cached_end_code_units_column(cache) end
#cached_end_code_units_offset(cache)
Delegates to the cached_end_code_units_offset of the associated location object.
# File 'lib/prism/node.rb', line 86
def cached_end_code_units_offset(cache) location.cached_end_code_units_offset(cache) end
#cached_start_code_units_column(cache)
Delegates to the cached_start_code_units_column of the associated location object.
# File 'lib/prism/node.rb', line 112
def cached_start_code_units_column(cache) location.cached_start_code_units_column(cache) end
#cached_start_code_units_offset(cache)
Delegates to the cached_start_code_units_offset of the associated location object.
# File 'lib/prism/node.rb', line 80
def cached_start_code_units_offset(cache) location.cached_start_code_units_offset(cache) 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 256
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 277
def comment_targets raise NoMethodError, "undefined method `comment_targets' for #{inspect}" end
#comments
Delegates to the comments of the associated location object.
# File 'lib/prism/node.rb', line 133
def comments location.comments 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 271
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 260
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
#each_child_node
With a block given, yields each child node. Without a block, returns an enumerator that contains each child node. Excludes any nils in the place of optional nodes that were not present.
# File 'lib/prism/node.rb', line 265
def each_child_node raise NoMethodError, "undefined method `each_child_node' for #{inspect}" end
#end_character_column
Delegates to the end_character_column of the associated location object.
# File 'lib/prism/node.rb', line 106
def end_character_column location.end_character_column end
#end_character_offset
Delegates to the end_character_offset of the associated location object.
# File 'lib/prism/node.rb', line 74
def end_character_offset location.end_character_offset end
#end_column
Delegates to the end_column of the associated location object.
# File 'lib/prism/node.rb', line 96
def end_column location.end_column end
#end_line
Delegates to the end_line of the associated location object.
# File 'lib/prism/node.rb', line 50
def end_line location.end_line 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 282
def inspect raise NoMethodError, "undefined method `inspect' for #{inspect}" end
#leading_comments
Delegates to the leading_comments of the associated location object.
# File 'lib/prism/node.rb', line 123
def leading_comments location.leading_comments 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 175
def pretty_print(q) q.seplist(inspect.chomp.each_line, -> { q.breakable }) do |line| q.text(line.chomp) end q.current_group.break end
#save(repository)
Save this node using a saved source so that it can be retrieved later.
# File 'lib/prism/node.rb', line 27
def save(repository) repository.enter(node_id, :itself) end
#save_location(repository)
Save the location using a saved source so that it can be retrieved later.
#script_lines
Alias for #source_lines.
# File 'lib/prism/node.rb', line 144
alias script_lines source_lines
#slice
Slice the location of the node from the source.
# File 'lib/prism/node.rb', line 147
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 154
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 138
def source_lines location.source_lines end
#start_character_column
Delegates to the start_character_column of the associated location object.
# File 'lib/prism/node.rb', line 101
def start_character_column location.start_character_column end
#start_character_offset
Delegates to the start_character_offset of the associated location object.
# File 'lib/prism/node.rb', line 69
def start_character_offset location.start_character_offset end
#start_column
Delegates to the start_column of the associated location object.
# File 'lib/prism/node.rb', line 91
def start_column location.start_column end
#start_line
Delegates to the start_line of the associated location object.
# File 'lib/prism/node.rb', line 45
def start_line location.start_line 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 183
def to_dot # @type self: node DotVisitor.new.tap { |visitor| accept(visitor) }.to_dot end
#trailing_comments
Delegates to the trailing_comments of the associated location object.
# File 'lib/prism/node.rb', line 128
def trailing_comments location.trailing_comments 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 194
def tunnel(line, column) queue = [self] #: Array[Prism::node] result = [] #: Array[Prism::node] search_offset = source.line_to_byte_offset(line) + column while (node = queue.shift) result << node node.each_child_node do |child_node| if child_node.start_offset <= search_offset && search_offset < child_node.end_offset 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 298
def type raise NoMethodError, "undefined method `type' for #{inspect}" end