ruby_tree_sitter 0.20.8.2-x86_64-darwin-20 → 1.0.0-x86_64-darwin-20

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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +2 -1
  3. data/README.md +32 -18
  4. data/ext/tree_sitter/extconf.rb +1 -43
  5. data/ext/tree_sitter/input.c +1 -0
  6. data/ext/tree_sitter/language.c +131 -46
  7. data/ext/tree_sitter/logger.c +28 -12
  8. data/ext/tree_sitter/node.c +438 -130
  9. data/ext/tree_sitter/parser.c +232 -37
  10. data/ext/tree_sitter/query.c +197 -72
  11. data/ext/tree_sitter/query_cursor.c +140 -28
  12. data/ext/tree_sitter/repo.rb +121 -0
  13. data/ext/tree_sitter/tree.c +118 -34
  14. data/ext/tree_sitter/tree_cursor.c +205 -33
  15. data/ext/tree_sitter/tree_sitter.c +12 -0
  16. data/lib/tree_sitter/node.rb +43 -9
  17. data/lib/tree_sitter/tree_sitter.bundle +0 -0
  18. data/lib/tree_sitter/version.rb +4 -2
  19. data/lib/tree_sitter.rb +1 -0
  20. data/lib/tree_stand/ast_modifier.rb +30 -0
  21. data/lib/tree_stand/breadth_first_visitor.rb +54 -0
  22. data/lib/tree_stand/config.rb +13 -0
  23. data/lib/tree_stand/node.rb +224 -0
  24. data/lib/tree_stand/parser.rb +67 -0
  25. data/lib/tree_stand/range.rb +55 -0
  26. data/lib/tree_stand/tree.rb +123 -0
  27. data/lib/tree_stand/utils/printer.rb +73 -0
  28. data/lib/tree_stand/version.rb +7 -0
  29. data/lib/tree_stand/visitor.rb +127 -0
  30. data/lib/tree_stand/visitors/tree_walker.rb +37 -0
  31. data/lib/tree_stand.rb +48 -0
  32. data/tree_sitter.gemspec +15 -12
  33. metadata +37 -107
  34. data/test/README.md +0 -15
  35. data/test/test_helper.rb +0 -9
  36. data/test/tree_sitter/js_test.rb +0 -48
  37. data/test/tree_sitter/language_test.rb +0 -73
  38. data/test/tree_sitter/logger_test.rb +0 -70
  39. data/test/tree_sitter/node_test.rb +0 -355
  40. data/test/tree_sitter/parser_test.rb +0 -140
  41. data/test/tree_sitter/query_test.rb +0 -153
  42. data/test/tree_sitter/tree_cursor_test.rb +0 -83
  43. data/test/tree_sitter/tree_test.rb +0 -51
@@ -1,355 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../test_helper'
4
-
5
- ruby = TreeSitter.lang('ruby')
6
- parser = TreeSitter::Parser.new
7
- parser.language = ruby
8
-
9
- program = <<~RUBY
10
- def mul(a, b)
11
- res = a * b
12
- puts res.inspect
13
- return res
14
- end
15
- RUBY
16
-
17
- tree = parser.parse_string(nil, program)
18
- root = tree.root_node
19
-
20
- describe 'type' do
21
- it 'must be a Symbol' do
22
- assert_instance_of Symbol, root.type
23
- end
24
-
25
- it 'must be "program" on root' do
26
- assert_equal :program, root.type
27
- end
28
- end
29
-
30
- describe 'symbol' do
31
- it 'must be an Integer' do
32
- assert_instance_of Integer, root.symbol
33
- end
34
- end
35
-
36
- describe 'start_byte' do
37
- it 'must be an Integer' do
38
- assert_instance_of Integer, root.start_byte
39
- end
40
-
41
- it 'must be an 0' do
42
- assert_equal 0, root.start_byte
43
- end
44
- end
45
-
46
- describe 'end_byte' do
47
- it 'must be an Integer' do
48
- assert_instance_of Integer, root.end_byte
49
- end
50
-
51
- it 'must not be 0' do
52
- refute_equal 0, root.end_byte
53
- end
54
- end
55
-
56
- describe 'start_point' do
57
- it 'must be an instance of point' do
58
- assert_instance_of TreeSitter::Point, root.start_point
59
- end
60
-
61
- it 'must be at row 0' do
62
- assert_equal 0, root.start_point.row
63
- end
64
-
65
- it 'must be at column 0' do
66
- assert_equal 0, root.start_point.row
67
- end
68
- end
69
-
70
- describe 'end_point' do
71
- it 'must be an instance of point' do
72
- assert_instance_of TreeSitter::Point, root.end_point
73
- end
74
-
75
- it 'must not be at row 0' do
76
- refute_equal 0, root.end_point.row
77
- end
78
-
79
- it 'must not be at column 0' do
80
- refute_equal 0, root.end_point.row
81
- end
82
- end
83
-
84
- describe 'string' do
85
- it 'must be an instance of string' do
86
- assert_instance_of String, root.to_s
87
- end
88
-
89
- it 'must be non-empty' do
90
- refute root.to_s.empty?
91
- end
92
- end
93
-
94
- describe 'predicates' do
95
- it 'must not be null' do
96
- refute_nil root.null?
97
- end
98
-
99
- it 'must be named' do
100
- assert root.named?
101
- end
102
-
103
- it 'must not be missing' do
104
- refute root.missing?
105
- end
106
-
107
- it 'must not be extra' do
108
- refute root.extra?
109
- end
110
-
111
- it 'must not have any changes' do
112
- # TODO: needs a more elaborate test to check for true changes?
113
- refute root.changed?
114
- end
115
-
116
- it 'must not have no errors' do
117
- refute root.error?
118
- end
119
- end
120
-
121
- describe 'parent' do
122
- # NOTE: never call parent on root. It will segfault.
123
- #
124
- # tree-sitter does not provide a way to check if a node has a parent.
125
-
126
- it 'must never be nil' do
127
- refute_nil root.child(0).parent
128
- end
129
-
130
- it 'must be root for its children' do
131
- assert_equal root, root.child(0).parent
132
- end
133
- end
134
-
135
- describe 'child' do
136
- before do
137
- @child = root.child(0)
138
- end
139
-
140
- it 'must return proper children count' do
141
- assert_equal 1, root.child_count
142
- end
143
-
144
- it 'must return proper name child count' do
145
- assert_equal 5, @child.named_child_count
146
- end
147
-
148
- it 'must return proper name child' do
149
- assert_equal @child.child(1), @child.named_child(0)
150
- end
151
-
152
- it 'must return proper child by field name' do
153
- assert_equal @child.child(1), @child.child_by_field_name('name')
154
- end
155
-
156
- it 'must return proper child by field id' do
157
- assert_equal @child.child(1), @child.child_by_field_id(ruby.field_id_for_name('name'))
158
- end
159
-
160
- it 'must return proper child for byte' do
161
- child = @child.child(0)
162
- assert_equal child, @child.first_child_for_byte(child.start_byte)
163
- end
164
-
165
- it 'must return proper named child for byte' do
166
- child = @child.child(1)
167
- assert_equal child, @child.first_named_child_for_byte(child.start_byte)
168
- end
169
-
170
- it 'must return proper descendant for byte range' do
171
- child = @child.child(1)
172
- assert_equal child, @child.descendant_for_byte_range(child.start_byte, child.end_byte)
173
- end
174
-
175
- it 'must return proper descendant for point range' do
176
- child = @child.child(1)
177
- assert_equal child, @child.descendant_for_point_range(child.start_point, child.end_point)
178
- end
179
-
180
- it 'must return proper named descendant for byte range' do
181
- child = @child.child(1)
182
- assert_equal child, @child.named_descendant_for_byte_range(child.start_byte, child.end_byte)
183
- end
184
-
185
- it 'must return proper named descendant for point range' do
186
- child = @child.child(1)
187
- assert_equal child, @child.named_descendant_for_point_range(child.start_point, child.end_point)
188
- end
189
-
190
- it 'must raise an exception for wrong ranges' do
191
- child = @child.child(0)
192
- assert_raises IndexError do
193
- @child.descendant_for_byte_range(child.end_byte, child.start_byte)
194
- end
195
- assert_raises IndexError do
196
- @child.named_descendant_for_byte_range(child.end_byte, child.start_byte)
197
- end
198
- assert_raises IndexError do
199
- p1 = TreeSitter::Point.new
200
- p1.row = @child.end_point.row
201
- p1.column = @child.end_point.column + 1
202
- @child.named_descendant_for_point_range(@child.start_point, p1)
203
- end
204
- assert_raises IndexError do
205
- p1 = TreeSitter::Point.new
206
- p1.row = @child.end_point.row
207
- p1.column = @child.end_point.column + 1
208
- @child.named_descendant_for_point_range(@child.start_point, p1)
209
- end
210
- end
211
- end
212
-
213
- describe 'field_name' do
214
- before do
215
- @child = root.child(0)
216
- end
217
-
218
- it 'must return proper field name' do
219
- assert_equal 'name', @child.field_name_for_child(1)
220
- end
221
- end
222
-
223
- describe 'siblings' do
224
- before do
225
- @child = root.child(0).child(0)
226
- end
227
-
228
- it 'must return proper next/previous siblings' do
229
- assert_equal @child, @child.next_sibling.prev_sibling
230
- end
231
-
232
- it 'must return proper next/previous named siblings' do
233
- assert_equal @child.parent.child(1), @child.next_named_sibling
234
- end
235
- end
236
-
237
- # TODO: edit
238
-
239
- # Tese are High-Level Ruby APIs that we designed.
240
- # They rely on the bindings.
241
-
242
- describe '[]' do
243
- before do
244
- @child = root.child(0)
245
- end
246
-
247
- it 'must return a named child by index when index is an Integer' do
248
- assert_equal @child.named_child(0), @child[0]
249
- end
250
-
251
- it 'must return a child by field name when index is a (String | Symbol)' do
252
- assert_equal @child.named_child(0), @child[:name]
253
- assert_equal @child.named_child(0), @child['name']
254
- end
255
-
256
- it 'must return an array of nodes when index is an Array' do
257
- arr = [@child.named_child(0)] * 3
258
- assert_equal arr, @child[0, :name, 'name']
259
- end
260
-
261
- it 'must throw an exception when out of index' do
262
- assert_raises { @child[255] }
263
- end
264
-
265
- it 'must throw an exception when field is not found (NO SIGSEGV ANYMORE!)' do
266
- assert_raises { @child[:randomzes] }
267
- end
268
- end
269
-
270
- describe 'each' do
271
- before do
272
- @child = root.child(0)
273
- end
274
-
275
- it 'must iterate over all children' do
276
- i = 0
277
- @child.each do |_|
278
- i += 1
279
- end
280
- assert @child.child_count, i
281
- end
282
-
283
- it 'must iterate ove named children attached to fields only' do
284
- @child.each_field do |f, c|
285
- refute f.nil?
286
- refute f.empty?
287
- assert_equal @child[f], c
288
- end
289
- end
290
-
291
- it 'must iterate over named children when `each_named_child`' do
292
- i = 0
293
- @child.each_named do |c|
294
- assert c.named?
295
- i += 1
296
- end
297
- assert @child.named_child_count, i
298
- end
299
- end
300
-
301
- describe 'method_missing' do
302
- before do
303
- @child = root.child(0)
304
- end
305
-
306
- it 'should act like the [] method when we pass (String | Symbol)' do
307
- assert_equal @child[:name], @child.name
308
- end
309
- end
310
-
311
- describe 'to_a' do
312
- before do
313
- @child = root.child(0)
314
- end
315
-
316
- it 'should return the list from each' do
317
- ll = @child.to_a
318
-
319
- refute ll.empty?
320
-
321
- @child.each.with_index do |c, i|
322
- assert_equal @child.child(i), c
323
- end
324
- end
325
- end
326
-
327
- describe 'fetch' do
328
- before do
329
- @child = root.child(0).child(4)
330
- end
331
-
332
- it 'should return all requested keys by order' do
333
- method = @child.child(0)
334
- arguments = @child.child(1)
335
-
336
- m, a = @child.fetch(:method, :arguments)
337
-
338
- assert_equal method, m
339
- assert_equal arguments, a
340
-
341
- a, m = @child.fetch(:arguments, :method)
342
-
343
- assert_equal method, m
344
- assert_equal arguments, a
345
- end
346
-
347
- it 'should return unique keys' do
348
- method = @child.child(0)
349
-
350
- m = @child.fetch(:method, :method)
351
-
352
- assert_equal 1, m.length
353
- assert_equal method, m.first
354
- end
355
- end
@@ -1,140 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../test_helper'
4
-
5
- ruby = TreeSitter.lang('ruby')
6
- parser = TreeSitter::Parser.new
7
- parser.language = ruby
8
-
9
- program = <<~RUBY
10
- def mul(a, b)
11
- res = a * b
12
- puts res.inspect
13
- return res
14
- end
15
- RUBY
16
-
17
- # NOTE: I was trying to parse invalid programs and see what happens.
18
- #
19
- # What happens = undefined behavior with the ruby parsers.
20
- #
21
- # Sometimes it would parse normally and return an instance of Tree, and
22
- # sometimes it would return nil. That goes for both `parse_string` and
23
- # `parse_string_encoded`.
24
- #
25
- # I suspect the same thing would happen with `parse`
26
-
27
- # margorp = <<~YBUR
28
- # fibfast n = fib' 0 1 n
29
- # where fib' a b n | n <= 1 = b
30
- # | otherwise = fib' b (a+b) (n-1)
31
- # YBUR
32
-
33
- program16 = program.encode('utf-16')
34
- # margorp_16 = margorp.encode('utf-16')
35
-
36
- describe 'loading a language' do
37
- before do
38
- parser.reset
39
- end
40
-
41
- it 'must set/get the same language' do
42
- parser.language = ruby
43
- assert_equal ruby, parser.language
44
- end
45
- end
46
-
47
- describe 'parse_string' do
48
- before do
49
- parser.reset
50
- end
51
-
52
- it 'must parse nil' do
53
- res = parser.parse_string(nil, nil)
54
- assert_nil res
55
- end
56
-
57
- [
58
- ['empty', '', 0],
59
- ['valid', program, 1],
60
- # ['invalid', margorp, 3]
61
- ].each do |q, p, c|
62
- it "must parse #{q} programs" do
63
- res = parser.parse_string(nil, p)
64
- assert_instance_of TreeSitter::Tree, res
65
-
66
- root = res.root_node
67
- assert_instance_of TreeSitter::Node, root
68
- assert_equal c, root.child_count
69
- end
70
- end
71
- end
72
-
73
- describe 'parse_string_encoding' do
74
- before do
75
- parser.reset
76
- end
77
-
78
- it 'must parse nil' do
79
- res = parser.parse_string_encoding(nil, nil, :utf8)
80
- assert_nil res
81
- res = parser.parse_string_encoding(nil, nil, :utf16)
82
- assert_nil res
83
- end
84
-
85
- [
86
- ['empty', '', 0, :utf8],
87
- ['valid', program, 1, :utf8],
88
- # ['invalid', margorp, 3, :utf8],
89
- ['empty', ''.encode('utf-16'), 0, :utf16],
90
- ['valid', program16, 1, :utf16],
91
- # ['invalid', margorp_16, 1, :utf16]
92
- ].each do |q, p, c, e|
93
- it "must parse #{q} programs in #{e}" do
94
- res = parser.parse_string_encoding(nil, p, e)
95
- assert_instance_of TreeSitter::Tree, res
96
-
97
- root = res.root_node
98
- assert_instance_of TreeSitter::Node, root
99
- assert_equal c, root.child_count
100
- end
101
- end
102
- end
103
-
104
- describe 'print_dot_graphs' do
105
- before do
106
- parser.reset
107
- end
108
-
109
- it 'must save its debug info to a file' do
110
- dot = File.expand_path('tmp/debug-dot.gv', FileUtils.getwd)
111
- parser.print_dot_graphs(dot)
112
- parser.parse_string(nil, program)
113
-
114
- assert File.exist?(dot), 'dot file must be exist'
115
- assert File.file?(dot), 'dot file must be a file'
116
- refute_equal 0, File.size(dot)
117
- end
118
- end
119
-
120
- describe 'canecalation_flags' do
121
- it 'must get/set cancellation_flah' do
122
- parser.cancellation_flag = 1
123
- assert_equal 1, parser.cancellation_flag
124
- end
125
- end
126
-
127
- describe 'timeout_micros' do
128
- it 'must get/set timeout_micros' do
129
- parser.timeout_micros = 1
130
- assert_equal 1, parser.timeout_micros
131
- end
132
- end
133
-
134
- # TODO: included_ranges for parsing partial documents.
135
-
136
- # TODO: parsing with non-nil tree.
137
-
138
- # TODO: parsing Input streams. We're currently just hading the callback from
139
- # C-space to Ruby-space At some point we might need to implement a
140
- # buffered input reader and we should test it here.
@@ -1,153 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../test_helper'
4
-
5
- ruby = TreeSitter.lang('ruby')
6
- parser = TreeSitter::Parser.new
7
- parser.language = ruby
8
-
9
- program = <<~RUBY
10
- def mul(a, b)
11
- res = a * b
12
- puts res.inspect
13
- return res
14
- end
15
- RUBY
16
-
17
- tree = parser.parse_string(nil, program)
18
- root = tree.root_node
19
-
20
- pattern = '(method_parameters)'
21
- capture = '(method_parameters (_)+ @args)'
22
- predicate = '(method_parameters (_)+ @args (#match? @args "\w"))'
23
- combined = "#{pattern} #{capture}"
24
- # string = '(method_parameters (_)+ @args)'
25
-
26
- # NOTE: It' still unclear to me what a captured string is.
27
-
28
- describe 'pattern/capture/string' do
29
- it 'must return an Integer for pattern count' do
30
- query = TreeSitter::Query.new(ruby, pattern)
31
- assert_equal 1, query.pattern_count
32
- assert_equal 0, query.capture_count
33
- assert_equal 0, query.string_count
34
- end
35
-
36
- it 'must return an Integer for pattern count' do
37
- query = TreeSitter::Query.new(ruby, capture)
38
- assert_equal 1, query.pattern_count
39
- assert_equal 1, query.capture_count
40
- assert_equal 0, query.string_count
41
- end
42
-
43
- it 'must return an Integer for combined patterns' do
44
- query = TreeSitter::Query.new(ruby, combined)
45
- assert_equal 2, query.pattern_count
46
- assert_equal 1, query.capture_count
47
- assert_equal 0, query.string_count
48
- end
49
-
50
- it 'must return an Integer for pattern start byte' do
51
- query = TreeSitter::Query.new(ruby, combined)
52
- assert_equal 0, query.start_byte_for_pattern(0)
53
- assert_equal pattern.bytesize + 1, query.start_byte_for_pattern(1)
54
- end
55
-
56
- it 'must return an array of predicates for a pattern' do
57
- query = TreeSitter::Query.new(ruby, combined)
58
-
59
- preds0 = query.predicates_for_pattern(0)
60
- assert_instance_of Array, preds0
61
- assert_equal 0, preds0.size
62
-
63
- preds1 = query.predicates_for_pattern(1)
64
- assert_instance_of Array, preds1
65
- assert_equal 0, preds1.size
66
-
67
- query = TreeSitter::Query.new(ruby, predicate)
68
- preds2 = query.predicates_for_pattern(0)
69
- assert_instance_of Array, preds2
70
- assert_equal 4, preds2.size
71
- end
72
-
73
- it 'must return string names, quanitfier, and string value for capture id' do
74
- query = TreeSitter::Query.new(ruby, predicate)
75
- query.predicates_for_pattern(0).each do |step|
76
- next if step.type != TreeSitter::QueryPredicateStep::CAPTURE
77
-
78
- assert_equal 'args', query.capture_name_for_id(step.value_id)
79
- assert_equal TreeSitter::Quantifier::ONE_OR_MORE, query.capture_quantifier_for_id(0, step.value_id)
80
- assert_equal 'match?', query.string_value_for_id(step.value_id)
81
- end
82
- end
83
-
84
- it 'must disable captures but keep it in count' do
85
- query = TreeSitter::Query.new(ruby, capture)
86
- query.disable_capture('@args')
87
- assert_equal 1, query.capture_count
88
- end
89
-
90
- it 'must disable captures but keep it in count' do
91
- query = TreeSitter::Query.new(ruby, capture)
92
- query.disable_pattern(0)
93
- assert_equal 1, query.pattern_count
94
- end
95
- # TODO: pattern guaranteed at step
96
- end
97
-
98
- describe 'query_cursor' do
99
- before do
100
- @query = TreeSitter::Query.new(ruby, capture)
101
- @cursor = TreeSitter::QueryCursor.exec(@query, root)
102
- end
103
-
104
- it 'must work with limits' do
105
- @cursor.match_limit = 1
106
- assert_equal 1, @cursor.match_limit
107
- refute @cursor.exceed_match_limit?
108
- refute_nil @cursor.next_capture
109
- assert @cursor.exceed_match_limit?
110
- end
111
-
112
- it 'must work with byte range' do
113
- child = root.child(0).child(0)
114
- @cursor.set_byte_range(child.start_byte, child.end_byte)
115
- assert_nil @cursor.next_capture
116
- end
117
-
118
- it 'must work with point range' do
119
- child = root.child(0).child(0)
120
- @cursor.set_point_range(child.start_point, child.end_point)
121
- assert_nil @cursor.next_capture
122
- end
123
-
124
- it 'must work with next/remove' do
125
- assert_equal 0, @cursor.next_match.id
126
- @cursor.remove_match(1)
127
- assert_nil @cursor.next_match
128
- end
129
- end
130
-
131
- describe 'querying anonymous nodes' do
132
- it 'must match & capture the correct nodes' do
133
- binary = '(binary left: (identifier) operator: "*" right: (identifier)) @binary'
134
- prog = <<~RUBY
135
- c + d
136
- a * b
137
- e / f
138
- RUBY
139
- prog_tree = parser.parse_string(nil, prog)
140
- prog_root = prog_tree.root_node
141
- query = TreeSitter::Query.new(ruby, binary)
142
- cursor = TreeSitter::QueryCursor.exec(query, prog_root)
143
-
144
- while match = cursor.next_match
145
- refute_nil(match)
146
- assert_equal(1, match.captures.size)
147
-
148
- node = match.captures.first.node
149
- assert_equal 'a * b', prog[node.start_byte...node.end_byte]
150
- end
151
- assert_nil(match)
152
- end
153
- end