ruby_tree_sitter 1.2.0-x86_64-linux → 1.3.0-x86_64-linux

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cfbfdfc0c297585fe24e04c4b9822ff404baa795182b7a7b144f56a3941db672
4
- data.tar.gz: 010faa21be194e40cdf7f5f00986c16ee5d51d64f377097bfb307a4245ba61b6
3
+ metadata.gz: a0f7c51b289e769ad5701be586b28d61f41f0979ee6fd3c08f87481ae307f146
4
+ data.tar.gz: 988052e5b5b5c41e9a9d974398c6c6cae401f2068a2ad4013d80198f3437c029
5
5
  SHA512:
6
- metadata.gz: b98898e1a8b801de3599e6daebd2adaa27b2ea729a46ebe730095d31e053dfb84c48a83712364a09fd58bac236f1b499f16ced6dcf4640902d0d4c12ac4ac7be
7
- data.tar.gz: 4dd45cf49030a553819febb05cc8a0755ed549c413d44ea1c88836d4e2fad3c55138db3a3079776f2e14a828c38fd7d7b11664366ea8e84083098910528950b3
6
+ metadata.gz: 9ef62c5ea3bd4451b03b43e6efc2c3501191ffcd9ea96dfe12d2e66b249d1f16f58e82d6127d833a6c8105e3f910dda2ba898a138d5e6d2756615bf69fcb2e05
7
+ data.tar.gz: 5bd46cc66e845c9091005a5eadeccb3db2984e0bbc5bf6d12e9fc4e3fd126f9ab6f1d37970fbe6760eee096ec2c011d4d328d5610a9e873ed313df3842caceb3
@@ -140,6 +140,13 @@ static VALUE query_initialize(VALUE self, VALUE language, VALUE source) {
140
140
  SELF = res;
141
141
  }
142
142
 
143
+ rb_iv_set(self, "@text_predicates", rb_ary_new());
144
+ rb_iv_set(self, "@property_predicates", rb_ary_new());
145
+ rb_iv_set(self, "@property_settings", rb_ary_new());
146
+ rb_iv_set(self, "@general_predicates", rb_ary_new());
147
+
148
+ rb_funcall(self, rb_intern("process"), 1, source);
149
+
143
150
  return self;
144
151
  }
145
152
 
@@ -49,7 +49,7 @@ DATA_FROM_VALUE(TSQueryCursor *, query_cursor)
49
49
  *
50
50
  * @return [QueryCursor]
51
51
  */
52
- static VALUE query_cursor_exec(VALUE self, VALUE query, VALUE node) {
52
+ static VALUE query_cursor_exec_static(VALUE self, VALUE query, VALUE node) {
53
53
  VALUE res = query_cursor_allocate(cQueryCursor);
54
54
  query_cursor_t *query_cursor = unwrap(res);
55
55
  ts_query_cursor_exec(query_cursor->data, value_to_query(query),
@@ -57,6 +57,21 @@ static VALUE query_cursor_exec(VALUE self, VALUE query, VALUE node) {
57
57
  return res;
58
58
  }
59
59
 
60
+ /**
61
+ * Start running a given query on a given node.
62
+ *
63
+ * @param query [Query]
64
+ * @param node [Node]
65
+ *
66
+ * @return [QueryCursor]
67
+ */
68
+ static VALUE query_cursor_exec(VALUE self, VALUE query, VALUE node) {
69
+ query_cursor_t *query_cursor = unwrap(self);
70
+ ts_query_cursor_exec(query_cursor->data, value_to_query(query),
71
+ value_to_node(node));
72
+ return self;
73
+ }
74
+
60
75
  /**
61
76
  * Manage the maximum number of in-progress matches allowed by this query
62
77
  * cursor.
@@ -190,13 +205,14 @@ void init_query_cursor(void) {
190
205
  rb_define_alloc_func(cQueryCursor, query_cursor_allocate);
191
206
 
192
207
  /* Module methods */
193
- rb_define_module_function(cQueryCursor, "exec", query_cursor_exec, 2);
208
+ rb_define_module_function(cQueryCursor, "exec", query_cursor_exec_static, 2);
194
209
 
195
210
  /* Class methods */
196
211
  // Accessors
197
212
  DECLARE_ACCESSOR(cQueryCursor, query_cursor, match_limit)
198
213
 
199
214
  // Other
215
+ rb_define_method(cQueryCursor, "exec", query_cursor_exec, 2);
200
216
  rb_define_method(cQueryCursor, "exceed_match_limit?",
201
217
  query_cursor_did_exceed_match_limit, 0);
202
218
  rb_define_method(cQueryCursor, "match_limit", query_cursor_get_match_limit,
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ # splits an array like [rust](https://doc.rust-lang.org/std/primitive.slice.html#method.split)
4
+ def array_split_like_rust(array, &block)
5
+ return enum_for(__method__, array) if !block_given?
6
+
7
+ return [] if array.empty?
8
+
9
+ result = []
10
+ current_slice = []
11
+
12
+ array.each do |element|
13
+ if yield(element)
14
+ result << current_slice
15
+ current_slice = []
16
+ else
17
+ current_slice << element
18
+ end
19
+ end
20
+
21
+ result << current_slice
22
+ result
23
+ end
@@ -0,0 +1,191 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'helpers'
4
+
5
+ module TreeSitter
6
+ # Query is a wrapper around a tree-sitter query.
7
+ class Query
8
+ attr_reader :capture_names
9
+ attr_reader :capture_quantifiers
10
+ attr_reader :text_predicates
11
+ attr_reader :property_predicates
12
+ attr_reader :property_settings
13
+ attr_reader :general_predicates
14
+
15
+ private
16
+
17
+ # Called from query.c on initialize.
18
+ #
19
+ # Prepares all the predicates so we could process them in places like
20
+ # {QueryMatch#satisfies_text_predicate?}.
21
+ #
22
+ # This is translation from the [rust bindings](https://github.com/tree-sitter/tree-sitter/blob/e553578696fe86071846ed612ee476d0167369c1/lib/binding_rust/lib.rs#L1860)
23
+ # Because it's a direct translation, it's way too long and we need to shut up rubocop.
24
+ # TODO: refactor + simplify when stable.
25
+ def process(source) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
26
+ string_count = self.string_count
27
+ capture_count = self.capture_count
28
+ pattern_count = self.pattern_count
29
+
30
+ # Build a vector of strings to store the capture names.
31
+ capture_names = capture_count.times.map { |i| capture_name_for_id(i) }
32
+
33
+ # Build a vector to store capture qunatifiers.
34
+ capture_quantifiers =
35
+ pattern_count.times.map do |i|
36
+ capture_count.times.map do |j|
37
+ capture_quantifier_for_id(i, j)
38
+ end
39
+ end
40
+
41
+ # Build a vector of strings to represent literal values used in predicates.
42
+ string_values = string_count.times.map { |i| string_value_for_id(i) }
43
+
44
+ # Build a vector of predicates for each pattern.
45
+ pattern_count.times do |i| # rubocop:disable Metrics/BlockLength
46
+ predicate_steps = predicates_for_pattern(i)
47
+ byte_offset = start_byte_for_pattern(i)
48
+ row =
49
+ source.chars.map.with_index
50
+ .take_while { |_, i| i < byte_offset } # rubocop:disable Lint/ShadowingOuterLocalVariable
51
+ .filter { |c, _| c == "\n" }
52
+ .size
53
+ text_predicates = []
54
+ property_predicates = []
55
+ property_settings = []
56
+ general_predicates = []
57
+
58
+ array_split_like_rust(predicate_steps) { |s| s.type == QueryPredicateStep::DONE } # rubocop:disable Metrics/BlockLength
59
+ .each do |p|
60
+ next if p.empty?
61
+
62
+ if p[0] == QueryPredicateStep::STRING
63
+ cap = capture_names[p[0].value_id]
64
+ raise ArgumentError, <<~MSG.chomp
65
+ L#{row}: Expected predicate to start with a function name. Got @#{cap}.
66
+ MSG
67
+ end
68
+
69
+ # Build a predicate for each of the known predicate function names.
70
+ operator_name = string_values[p[0].value_id]
71
+
72
+ case operator_name
73
+ in 'any-eq?' | 'any-not-eq?' | 'eq?' | 'not-eq?'
74
+ if p.size != 3
75
+ raise ArgumentError, <<~MSG.chomp
76
+ L#{row}: Wrong number of arguments to ##{operator_name} predicate. Expected 2, got #{p.size - 1}.
77
+ MSG
78
+ end
79
+
80
+ if p[1].type != QueryPredicateStep::CAPTURE
81
+ lit = string_values[p[1].value_id]
82
+ raise ArgumentError, <<~MSG.chomp
83
+ L#{row}: First argument to ##{operator_name} predicate must be a capture name. Got literal "#{lit}".
84
+ MSG
85
+ end
86
+
87
+ is_positive = %w[eq? any-eq?].include?(operator_name)
88
+ match_all = %w[eq? not-eq?].include?(operator_name)
89
+ # NOTE: in the rust impl, match_all can hit an unreachable! but I am simplifying
90
+ # for readability. Same applies for the other `in` branches.
91
+ text_predicates <<
92
+ if p[2].type == QueryPredicateStep::CAPTURE
93
+ TextPredicateCapture.eq_capture(p[1].value_id, p[2].value_id, is_positive, match_all)
94
+ else
95
+ TextPredicateCapture.eq_string(p[1].value_id, string_values[p[2].value_id], is_positive, match_all)
96
+ end
97
+
98
+ in 'match?' | 'not-match?' | 'any-match?' | 'any-not-match?'
99
+ if p.size != 3
100
+ raise ArgumentError, <<~MSG.chomp
101
+ L#{row}: Wrong number of arguments to ##{operator_name} predicate. Expected 2, got #{p.size - 1}.
102
+ MSG
103
+ end
104
+
105
+ if p[1].type != QueryPredicateStep::CAPTURE
106
+ lit = string_values[p[1].value_id]
107
+ raise ArgumentError, <<~MSG.chomp
108
+ L#{row}: First argument to ##{operator_name} predicate must be a capture name. Got literal "#{lit}".
109
+ MSG
110
+ end
111
+
112
+ if p[2].type == QueryPredicateStep::CAPTURE
113
+ cap = capture_names[p[2].value_id]
114
+ raise ArgumentError, <<~MSG.chomp
115
+ L#{row}: First argument to ##{operator_name} predicate must be a literal. Got capture @#{cap}".
116
+ MSG
117
+ end
118
+
119
+ is_positive = %w[match? any-match?].include?(operator_name)
120
+ match_all = %w[match? not-match?].include?(operator_name)
121
+ regex = /#{string_values[p[2].value_id]}/
122
+
123
+ text_predicates << TextPredicateCapture.match_string(p[1].value_id, regex, is_positive, match_all)
124
+
125
+ in 'set!'
126
+ property_settings << 'todo!'
127
+
128
+ in 'is?' | 'is-not?'
129
+ property_predicates << 'todo!'
130
+
131
+ in 'any-of?' | 'not-any-of?'
132
+ if p.size < 2
133
+ raise ArgumentError, <<~MSG.chomp
134
+ L#{row}: Wrong number of arguments to ##{operator_name} predicate. Expected at least 1, got #{p.size - 1}.
135
+ MSG
136
+ end
137
+
138
+ if p[1].type != QueryPredicateStep::CAPTURE
139
+ lit = string_values[p[1].value_id]
140
+ raise ArgumentError, <<~MSG.chomp
141
+ L#{row}: First argument to ##{operator_name} predicate must be a capture name. Got literal "#{lit}".
142
+ MSG
143
+ end
144
+
145
+ is_positive = operator_name == 'any_of'
146
+ values = []
147
+
148
+ p[2..].each do |arg|
149
+ if arg.type == QueryPredicateStep::CAPTURE
150
+ lit = string_values[arg.value_id]
151
+ raise ArgumentError, <<~MSG.chomp
152
+ L#{row}: First argument to ##{operator_name} predicate must be a capture name. Got literal "#{lit}".
153
+ MSG
154
+ end
155
+ values << string_values[arg.value_id]
156
+ end
157
+
158
+ # TODO: is the map to to_s necessary in ruby?
159
+ text_predicates <<
160
+ TextPredicateCapture.any_string(p[1].value_id, values.map(&:to_s), is_positive, match_all)
161
+ else
162
+ general_predicates <<
163
+ QueryPredicate.new(
164
+ operator_name,
165
+ p[1..].map do |a|
166
+ if a.type == QueryPredicateStep::CAPTURE
167
+ { capture: a.value_id }
168
+ else
169
+ { string: string_values[a.value_id] }
170
+ end
171
+ end,
172
+ )
173
+ end
174
+
175
+ @text_predicates << text_predicates
176
+ @property_predicates << property_predicates
177
+ @property_settings << property_settings
178
+ @general_predicates << general_predicates
179
+ end
180
+
181
+ @capture_names = capture_names
182
+ @capture_quantifiers = capture_quantifiers
183
+ end
184
+ end
185
+
186
+ # TODO
187
+ def parse_property
188
+ # todo
189
+ end
190
+ end
191
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TreeSitter
4
+ # A sequence of {TreeSitter::QueryCapture} associated with a given {TreeSitter::QueryCursor}.
5
+ class QueryCaptures
6
+ def initialize(cursor, query, src)
7
+ @cursor = cursor
8
+ @query = query
9
+ @src = src
10
+ end
11
+
12
+ # Iterator over captures.
13
+ #
14
+ # @yieldparam match [TreeSitter::QueryMatch]
15
+ # @yieldparam capture_index [Integer]
16
+ def each
17
+ return enum_for __method__ if !block_given?
18
+
19
+ while (capture_index, match = @cursor.next_capture)
20
+ next if !match.is_a?(TreeSitter::QueryMatch)
21
+
22
+ if match.satisfies_text_predicate?(@query, @src)
23
+ yield [match, capture_index]
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TreeSitter
4
+ # A Cursor for {Query}.
5
+ class QueryCursor
6
+ # Iterate over all of the matches in the order that they were found.
7
+ #
8
+ # Each match contains the index of the pattern that matched, and a list of
9
+ # captures. Because multiple patterns can match the same set of nodes,
10
+ # one match may contain captures that appear *before* some of the
11
+ # captures from a previous match.
12
+ def matches(query, node, src)
13
+ self.exec(query, node)
14
+ QueryMatches.new(self, query, src)
15
+ end
16
+
17
+ # Iterate over all of the individual captures in the order that they
18
+ # appear.
19
+ #
20
+ # This is useful if you don't care about which pattern matched, and just
21
+ # want a single, ordered sequence of captures.
22
+ def captures(query, node, src)
23
+ self.exec(query, node)
24
+ QueryCaptures.new(self, query, src)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'query_captures'
4
+
5
+ module TreeSitter
6
+ # A match for a {Query}.
7
+ class QueryMatch
8
+ # All nodes at a given capture index.
9
+ #
10
+ # @param index [Integer]
11
+ #
12
+ # @return [TreeSitter::Node]
13
+ def nodes_for_capture_index(index) = captures.filter_map { |capture| capture.node if capture.index == index }
14
+
15
+ # Whether the {QueryMatch} satisfies the text predicates in the query.
16
+ #
17
+ # This is a translation from the [rust bindings](https://github.com/tree-sitter/tree-sitter/blob/e553578696fe86071846ed612ee476d0167369c1/lib/binding_rust/lib.rs#L2502).
18
+ # Because it's a direct translation, it's way too long and we need to shut up rubocop.
19
+ # TODO: refactor + simplify when satable.
20
+ def satisfies_text_predicate?(query, src) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
21
+ return true if query.text_predicates[pattern_index].nil?
22
+
23
+ query # rubocop:disable Metrics/BlockLength
24
+ .text_predicates[pattern_index]
25
+ .all? do |predicate|
26
+ case predicate.type
27
+ in TextPredicateCapture::EQ_CAPTURE
28
+ fst_nodes = nodes_for_capture_index(predicate.fst)
29
+ snd_nodes = nodes_for_capture_index(predicate.snd)
30
+ res = nil
31
+ consumed = 0
32
+ fst_nodes.zip(snd_nodes).each do |node1, node2|
33
+ text1 = node_text(node1, src)
34
+ text2 = node_text(node2, src)
35
+ if (text1 == text2) != predicate.positive? && predicate.match_all?
36
+ res = false
37
+ break
38
+ end
39
+ if (text1 == text2) == predicate.positive? && !predicate.match_all?
40
+ res = true
41
+ break
42
+ end
43
+ consumed += 1
44
+ end
45
+ (res.nil? && consumed == fst_nodes.length && consumed == snd_nodes.length) \
46
+ || res
47
+
48
+ in TextPredicateCapture::EQ_STRING
49
+ nodes = nodes_for_capture_index(predicate.fst)
50
+ res = true
51
+ nodes.each do |node|
52
+ text = node_text(node, src)
53
+ if (predicate.snd == text) != predicate.positive? && predicate.match_all?
54
+ res = false
55
+ break
56
+ end
57
+ if (predicate.snd == text) == predicate.positive? && !predicate.match_all?
58
+ res = true
59
+ break
60
+ end
61
+ end
62
+ res
63
+
64
+ in TextPredicateCapture::MATCH_STRING
65
+ nodes = nodes_for_capture_index(predicate.fst)
66
+ res = true
67
+ nodes.each do |node|
68
+ text = node_text(node, src)
69
+ if predicate.snd.match?(text) != predicate.positive? && predicate.match_all?
70
+ res = false
71
+ break
72
+ end
73
+ if predicate.snd.match?(text) == predicate.positive? && !predicate.match_all?
74
+ res = true
75
+ break
76
+ end
77
+ end
78
+ res
79
+
80
+ in TextPredicateCapture::ANY_STRING
81
+ nodes = nodes_for_capture_index(predicate.fst)
82
+ res = true
83
+ nodes.each do |node|
84
+ text = node_text(node, src)
85
+ if predicate.snd.any? { |v| v == text } != predicate.positive?
86
+ res = false
87
+ break
88
+ end
89
+ end
90
+ res
91
+
92
+ end
93
+ end
94
+ end
95
+
96
+ private
97
+
98
+ def node_text(node, text) = text.byteslice(node.start_byte...node.end_byte)
99
+ end
100
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TreeSitter
4
+ # A sequence of {QueryMatch} associated with a given {QueryCursor}.
5
+ class QueryMatches
6
+ def initialize(cursor, query, src)
7
+ @cursor = cursor
8
+ @query = query
9
+ @src = src
10
+ end
11
+
12
+ # Iterator over matches.
13
+ #
14
+ # @yieldparam match [TreeSitter::QueryMatch]
15
+ def each
16
+ return enum_for __method__ if !block_given?
17
+
18
+ while match = @cursor.next_match
19
+ if match.satisfies_text_predicate?(@query, @src)
20
+ yield match
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TreeSitter
4
+ # A {Query} predicate generic representation.
5
+ class QueryPredicate
6
+ attr_accessor :operator
7
+ attr_accessor :args
8
+
9
+ def initialize(operator, args)
10
+ @operator = operator
11
+ @args = args
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TreeSitter
4
+ # A representation for text predicates.
5
+ class TextPredicateCapture
6
+ EQ_CAPTURE = 0 # Equality Capture
7
+ EQ_STRING = 1 # Equality String
8
+ MATCH_STRING = 2 # Match String
9
+ ANY_STRING = 3 # Any String
10
+
11
+ attr_reader :fst
12
+ attr_reader :snd
13
+ attr_reader :type
14
+
15
+ # Create a TextPredicateCapture for {EQ_CAPTURE}.
16
+ def self.eq_capture(...) = new(EQ_CAPTURE, ...)
17
+ # Create a TextPredicateCapture for {EQ_STRING}.
18
+ def self.eq_string(...) = new(EQ_STRING, ...)
19
+ # Create a TextPredicateCapture for {MATCH_STRING}.
20
+ def self.match_string(...) = new(MATCH_STRING, ...)
21
+ # Create a TextPredicateCapture for {ANY_STRING}.
22
+ def self.any_string(...) = new(ANY_STRING, ...)
23
+
24
+ def initialize(type, fst, snd, positive, match_all)
25
+ @type = type
26
+ @fst = fst
27
+ @snd = snd
28
+ @positive = positive
29
+ @match_all = match_all
30
+ end
31
+
32
+ # `#eq` is positive, `#not-eq` is not.
33
+ def positive? = @positive
34
+ # `#any-` means don't match all.
35
+ def match_all? = @match_all
36
+ end
37
+ end
Binary file
@@ -4,5 +4,5 @@ module TreeSitter
4
4
  # The version of the tree-sitter library.
5
5
  TREESITTER_VERSION = '0.22.6'
6
6
  # The current version of the gem.
7
- VERSION = '1.2.0'
7
+ VERSION = '1.3.0'
8
8
  end
data/lib/tree_sitter.rb CHANGED
@@ -6,9 +6,16 @@ end
6
6
 
7
7
  require 'set'
8
8
 
9
+ require 'tree_sitter/tree_sitter'
9
10
  require 'tree_sitter/version'
10
11
 
11
- require 'tree_sitter/tree_sitter'
12
12
  require 'tree_sitter/node'
13
+ require 'tree_sitter/query'
14
+ require 'tree_sitter/query_captures'
15
+ require 'tree_sitter/query_cursor'
16
+ require 'tree_sitter/query_match'
17
+ require 'tree_sitter/query_matches'
18
+ require 'tree_sitter/query_predicate'
19
+ require 'tree_sitter/text_predicate_capture'
13
20
 
14
21
  ObjectSpace.define_finalizer(TreeSitter::Tree.class, proc { TreeSitter::Tree.finalizer })
@@ -43,7 +43,7 @@ module TreeStand
43
43
  .freeze
44
44
 
45
45
  # The default paths we use to lookup parsers when no specific
46
- # {TreeStand::Config#parser_path} is {nil}.
46
+ # {TreeStand::Config#parser_path} is `nil`.
47
47
  # Order matters.
48
48
  LIBDIRS = [
49
49
  'tree-sitter-parsers',
@@ -180,7 +180,7 @@ module TreeStand
180
180
 
181
181
  # We know that the bindings will accept `lib`, but I don't know how to tell sorbet
182
182
  # the types in ext/tree_sitter where `load` is defined.
183
- TreeSitter::Language.load(name.gsub(/-/, '_'), T.unsafe(lib))
183
+ TreeSitter::Language.load(name.tr('-', '_'), T.unsafe(lib))
184
184
  end
185
185
 
186
186
  # @param language [String]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_tree_sitter
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.3.0
5
5
  platform: x86_64-linux
6
6
  authors:
7
7
  - Firas al-Khalil
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2024-05-27 00:00:00.000000000 Z
12
+ date: 2024-06-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: sorbet-runtime
@@ -74,7 +74,15 @@ files:
74
74
  - ext/tree_sitter/tree_sitter.c
75
75
  - ext/tree_sitter/tree_sitter.h
76
76
  - lib/tree_sitter.rb
77
+ - lib/tree_sitter/helpers.rb
77
78
  - lib/tree_sitter/node.rb
79
+ - lib/tree_sitter/query.rb
80
+ - lib/tree_sitter/query_captures.rb
81
+ - lib/tree_sitter/query_cursor.rb
82
+ - lib/tree_sitter/query_match.rb
83
+ - lib/tree_sitter/query_matches.rb
84
+ - lib/tree_sitter/query_predicate.rb
85
+ - lib/tree_sitter/text_predicate_capture.rb
78
86
  - lib/tree_sitter/tree_sitter.so
79
87
  - lib/tree_sitter/version.rb
80
88
  - lib/tree_stand.rb