summaryrefslogtreecommitdiff
path: root/prism/templates/lib/prism/node.rb.erb
diff options
context:
space:
mode:
Diffstat (limited to 'prism/templates/lib/prism/node.rb.erb')
-rw-r--r--prism/templates/lib/prism/node.rb.erb72
1 files changed, 43 insertions, 29 deletions
diff --git a/prism/templates/lib/prism/node.rb.erb b/prism/templates/lib/prism/node.rb.erb
index ddbe53e594..f0ce226def 100644
--- a/prism/templates/lib/prism/node.rb.erb
+++ b/prism/templates/lib/prism/node.rb.erb
@@ -28,17 +28,14 @@ module Prism
location.is_a?(Location) ? location.end_offset : ((location >> 32) + (location & 0xFFFFFFFF))
end
- def newline? # :nodoc:
- @newline ? true : false
+ # Returns all of the lines of the source code associated with this node.
+ def source_lines
+ location.source_lines
end
- def set_newline_flag(newline_marked) # :nodoc:
- line = location.start_line
- unless newline_marked[line]
- newline_marked[line] = true
- @newline = true
- end
- end
+ # An alias for source_lines, used to mimic the API from
+ # RubyVM::AbstractSyntaxTree to make it easier to migrate.
+ alias script_lines source_lines
# Slice the location of the node from the source.
def slice
@@ -67,6 +64,43 @@ module Prism
DotVisitor.new.tap { |visitor| accept(visitor) }.to_dot
end
+ # 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.
+ 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
+
# 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.
@@ -135,7 +169,6 @@ module Prism
# def initialize: (<%= (node.fields.map { |field| "#{field.rbs_class} #{field.name}" } + ["Location location"]).join(", ") %>) -> void
def initialize(source, <%= (node.fields.map(&:name) + ["location"]).join(", ") %>)
@source = source
- @newline = false
@location = location
<%- node.fields.each do |field| -%>
<%- if Prism::Template::CHECK_FIELD_KIND && field.respond_to?(:check_field_kind) -%>
@@ -149,25 +182,6 @@ module Prism
def accept(visitor)
visitor.visit_<%= node.human %>(self)
end
- <%- if node.newline == false -%>
-
- def set_newline_flag(newline_marked) # :nodoc:
- # Never mark <%= node.name %> with a newline flag, mark children instead
- end
- <%- elsif node.newline.is_a?(String) -%>
-
- def set_newline_flag(newline_marked) # :nodoc:
- <%- field = node.fields.find { |f| f.name == node.newline } or raise node.newline -%>
- <%- case field -%>
- <%- when Prism::Template::NodeField -%>
- <%= field.name %>.set_newline_flag(newline_marked)
- <%- when Prism::Template::NodeListField -%>
- first = <%= field.name %>.first
- first.set_newline_flag(newline_marked) if first
- <%- else raise field.class.name -%>
- <%- end -%>
- end
- <%- end -%>
# def child_nodes: () -> Array[nil | Node]
def child_nodes