Class: TreeStand::Tree
- Inherits:
-
Object
- Object
- TreeStand::Tree
- Extended by:
- Forwardable, T::Sig
- Includes:
- Enumerable
- Defined in:
- lib/tree_stand/tree.rb
Overview
Wrapper around a TreeSitter tree.
This class exposes a convient API for working with the tree. There are dangers in using this class. The tree is mutable and the document can be changed. This class does not protect against that.
Some of the moetods on this class edit and re-parse the document updating the tree. Because the document is re-parsed, the tree will be different. Which means all outstanding nodes & ranges will be invalid.
Methods that edit the document are suffixed with ‘!`, e.g. `#edit!`.
It’s often the case that you will want perfrom multiple edits. One such pattern is to call #query & #edit on all matches in a loop. It’s important to keep the destructive nature of #edit in mind and re-issue the query after each edit.
Another thing to keep in mind is that edits done later in the document will likely not affect the ranges that occur earlier in the document. This can be a convient property that could allow you to apply edits in a reverse order. This is not always possible and depends on the edits you make, beware that the tree will be different after each edit and this approach may cause bugs.
Instance Attribute Summary collapse
- #document ⇒ String readonly
- #parser ⇒ TreeStand::Parser readonly
- #ts_tree ⇒ TreeSitter::Tree readonly
Instance Method Summary collapse
-
#delete!(range) ⇒ void
This method deletes the section of the document specified by range.
-
#edit!(range, replacement) ⇒ void
This method replaces the section of the document specified by range and replaces it with the provided text.
-
#find_node(query_string) ⇒ TreeStand::Node?
Returns the first captured node that matches the query string or nil if there was no captured node.
-
#find_node!(query_string) ⇒ TreeStand::Node
Like #find_node, except that if no node is found, raises an NodeNotFound error.
- #initialize(parser, tree, document) ⇒ void constructor private
-
#query(query_string) ⇒ Array<Hash{String => TreeStand::Node}>
TreeSitter uses a ‘TreeSitter::Cursor` to iterate over matches by calling `curser#next_match` repeatedly until it returns `nil`.
- #root_node ⇒ TreeStand::Node
-
#text ⇒ String
A convenience method for getting the text of the node.
-
#walk(&block) {|node| ... } ⇒ T::Enumerator[TreeStand::Node]
(also: #each)
Backed by Visitors::TreeWalker.
Constructor Details
#initialize(parser, tree, document) ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
80 81 82 83 84 |
# File 'lib/tree_stand/tree.rb', line 80 def initialize(parser, tree, document) @parser = parser @ts_tree = tree @document = document end |
Instance Attribute Details
#document ⇒ String (readonly)
33 34 35 |
# File 'lib/tree_stand/tree.rb', line 33 def document @document end |
#parser ⇒ TreeStand::Parser (readonly)
37 38 39 |
# File 'lib/tree_stand/tree.rb', line 37 def parser @parser end |
#ts_tree ⇒ TreeSitter::Tree (readonly)
35 36 37 |
# File 'lib/tree_stand/tree.rb', line 35 def ts_tree @ts_tree end |
Instance Method Details
#delete!(range) ⇒ void
This method returns an undefined value.
This method deletes the section of the document specified by range. Then it will reparse the document and update the tree!
106 107 108 109 110 111 |
# File 'lib/tree_stand/tree.rb', line 106 def delete!(range) new_document = +"" new_document << @document[0...range.start_byte] new_document << @document[range.end_byte..-1] replace_with_new_doc(new_document) end |
#edit!(range, replacement) ⇒ void
This method returns an undefined value.
This method replaces the section of the document specified by range and replaces it with the provided text. Then it will reparse the document and update the tree!
95 96 97 98 99 100 101 |
# File 'lib/tree_stand/tree.rb', line 95 def edit!(range, replacement) new_document = +"" new_document << @document[0...range.start_byte] new_document << replacement new_document << @document[range.end_byte..-1] replace_with_new_doc(new_document) end |
#find_node(query_string) ⇒ TreeStand::Node?
This is a convenience method that calls Node#find_node on #root_node.
Returns the first captured node that matches the query string or nil if there was no captured node.
67 68 69 70 71 72 73 74 |
# File 'lib/tree_stand/tree.rb', line 67 def_delegators( :root_node, :query, :find_node, :find_node!, :walk, :text, ) |
#find_node!(query_string) ⇒ TreeStand::Node
This is a convenience method that calls Node#find_node! on #root_node.
Like #find_node, except that if no node is found, raises an NodeNotFound error.
67 68 69 70 71 72 73 74 |
# File 'lib/tree_stand/tree.rb', line 67 def_delegators( :root_node, :query, :find_node, :find_node!, :walk, :text, ) |
#query(query_string) ⇒ Array<Hash{String => TreeStand::Node}>
This is a convenience method that calls Node#query on #root_node.
TreeSitter uses a ‘TreeSitter::Cursor` to iterate over matches by calling `curser#next_match` repeatedly until it returns `nil`.
This method does all of that for you and collects all of the matches into an array and each corresponding capture into a hash.
67 68 69 70 71 72 73 74 |
# File 'lib/tree_stand/tree.rb', line 67 def_delegators( :root_node, :query, :find_node, :find_node!, :walk, :text, ) |
#root_node ⇒ TreeStand::Node
87 88 89 |
# File 'lib/tree_stand/tree.rb', line 87 def root_node TreeStand::Node.new(self, @ts_tree.root_node) end |
#text ⇒ String
This is a convenience method that calls Node#text on #root_node.
A convenience method for getting the text of the node. Each Node wraps the parent #tree and has access to the source document.
67 68 69 70 71 72 73 74 |
# File 'lib/tree_stand/tree.rb', line 67 def_delegators( :root_node, :query, :find_node, :find_node!, :walk, :text, ) |
#walk(&block) {|node| ... } ⇒ T::Enumerator[TreeStand::Node] Also known as: each
This is a convenience method that calls Node#walk on #root_node.
Backed by Visitors::TreeWalker.
67 68 69 70 71 72 73 74 |
# File 'lib/tree_stand/tree.rb', line 67 def_delegators( :root_node, :query, :find_node, :find_node!, :walk, :text, ) |