ruby_tree_sitter 0.20.8.2-x86_64-linux → 1.0.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.
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.so +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
@@ -40,10 +40,63 @@ static VALUE parser_allocate(VALUE klass) {
40
40
  return res;
41
41
  }
42
42
 
43
+ /**
44
+ * Get the parser's current cancellation flag pointer.
45
+ *
46
+ * @return [Integer]
47
+ */
48
+ static VALUE parser_get_cancellation_flag(VALUE self) {
49
+ return SIZET2NUM(*ts_parser_cancellation_flag(SELF));
50
+ }
51
+
52
+ /**
53
+ * Set the parser's current cancellation flag pointer.
54
+ *
55
+ * If a non-null pointer is assigned, then the parser will periodically read
56
+ * from this pointer during parsing. If it reads a non-zero value, it will
57
+ * halt early, returning +nil+.
58
+ *
59
+ * @see parse
60
+ *
61
+ * @note This is not well-tested in the bindings.
62
+ *
63
+ * @return nil
64
+ */
65
+ static VALUE parser_set_cancellation_flag(VALUE self, VALUE flag) {
66
+ unwrap(self)->cancellation_flag = NUM2SIZET(flag);
67
+ ts_parser_set_cancellation_flag(SELF, &unwrap(self)->cancellation_flag);
68
+ return Qnil;
69
+ }
70
+
71
+ /**
72
+ * Get the parser's current language.
73
+ */
43
74
  static VALUE parser_get_language(VALUE self) {
44
75
  return new_language(ts_parser_language(SELF));
45
76
  }
46
77
 
78
+ /**
79
+ * Set the language that the parser should use for parsing.
80
+ *
81
+ * Returns a boolean indicating whether or not the language was successfully
82
+ * assigned. True means assignment succeeded. False means there was a version
83
+ * mismatch: the language was generated with an incompatible version of the
84
+ * Tree-sitter CLI. Check the language's version using {Language#version}
85
+ * and compare it to this library's {TreeSitter::LANGUAGE_VERSION} and
86
+ * {TreeSitter::MIN_COMPATIBLE_LANGUAGE_VERSION} constants.
87
+ *
88
+ * @return [Boolean]
89
+ */
90
+ static VALUE parser_set_language(VALUE self, VALUE language) {
91
+ return ts_parser_set_language(SELF, value_to_language(language)) ? Qtrue
92
+ : Qfalse;
93
+ }
94
+
95
+ /**
96
+ * Get the ranges of text that the parser will include when parsing.
97
+ *
98
+ * @return [Array<Range>]
99
+ */
47
100
  static VALUE parser_get_included_ranges(VALUE self) {
48
101
  uint32_t length;
49
102
  const TSRange *ranges = ts_parser_included_ranges(SELF, &length);
@@ -54,23 +107,33 @@ static VALUE parser_get_included_ranges(VALUE self) {
54
107
  return res;
55
108
  }
56
109
 
57
- static VALUE parser_get_timeout_micros(VALUE self) {
58
- return ULL2NUM(ts_parser_timeout_micros(SELF));
59
- }
60
-
61
- static VALUE parser_get_logger(VALUE self) {
62
- return new_logger_by_val(ts_parser_logger(SELF));
63
- }
64
-
65
- static VALUE parser_get_cancellation_flag(VALUE self) {
66
- return SIZET2NUM(*ts_parser_cancellation_flag(SELF));
67
- }
68
-
69
- static VALUE parser_set_language(VALUE self, VALUE language) {
70
- return ts_parser_set_language(SELF, value_to_language(language)) ? Qtrue
71
- : Qfalse;
72
- }
73
-
110
+ /**
111
+ * Set the ranges of text that the parser should include when parsing.
112
+ *
113
+ * By default, the parser will always include entire documents. This function
114
+ * allows you to parse only a *portion* of a document but still return a syntax
115
+ * tree whose ranges match up with the document as a whole. You can also pass
116
+ * multiple disjoint ranges.
117
+ *
118
+ * The second and third parameters specify the location and length of an array
119
+ * of ranges. The parser does *not* take ownership of these ranges; it copies
120
+ * the data, so it doesn't matter how these ranges are allocated.
121
+ *
122
+ * If +array+'s +length+ is zero, then the entire document will be parsed.
123
+ * Otherwise, the given ranges must be ordered from earliest to latest in the
124
+ * document, and they must not overlap. That is, the following must hold for
125
+ * all:
126
+ *
127
+ * i < length - 1: ranges[i].end_byte <= ranges[i + 1].start_byte
128
+ *
129
+ * If this requirement is not satisfied, the operation will fail, the ranges
130
+ * will not be assigned, and this function will return +false+. On success,
131
+ * this function returns +true+
132
+ *
133
+ * @param array [Array<Range>]
134
+ *
135
+ * @return [Boolean]
136
+ */
74
137
  static VALUE parser_set_included_ranges(VALUE self, VALUE array) {
75
138
  Check_Type(array, T_ARRAY);
76
139
 
@@ -86,22 +149,76 @@ static VALUE parser_set_included_ranges(VALUE self, VALUE array) {
86
149
  return res ? Qtrue : Qfalse;
87
150
  }
88
151
 
89
- static VALUE parser_set_timeout_micros(VALUE self, VALUE timeout) {
90
- ts_parser_set_timeout_micros(SELF, NUM2ULL(timeout));
91
- return Qnil;
92
- }
93
-
94
- static VALUE parser_set_cancellation_flag(VALUE self, VALUE flag) {
95
- unwrap(self)->cancellation_flag = NUM2SIZET(flag);
96
- ts_parser_set_cancellation_flag(SELF, &unwrap(self)->cancellation_flag);
97
- return Qnil;
152
+ /**
153
+ * Get the parser's current logger.
154
+ *
155
+ * @return [Logger]
156
+ */
157
+ static VALUE parser_get_logger(VALUE self) {
158
+ return new_logger_by_val(ts_parser_logger(SELF));
98
159
  }
99
160
 
161
+ /**
162
+ * Set the logger that a parser should use during parsing.
163
+ *
164
+ * The parser does not take ownership over the logger payload. If a logger was
165
+ * previously assigned, the caller is responsible for releasing any memory
166
+ * owned by the previous logger.
167
+ *
168
+ * @param logger [Logger] or any object that has a +printf+, +puts+, or +write+.
169
+ *
170
+ * @return nil
171
+ */
100
172
  static VALUE parser_set_logger(VALUE self, VALUE logger) {
101
173
  ts_parser_set_logger(SELF, value_to_logger(logger));
102
174
  return Qnil;
103
175
  }
104
176
 
177
+ /**
178
+ * Use the parser to parse some source code and create a syntax tree.
179
+ *
180
+ * If you are parsing this document for the first time, pass +nil+ for the
181
+ * +old_tree+ parameter. Otherwise, if you have already parsed an earlier
182
+ * version of this document and the document has since been edited, pass the
183
+ * previous syntax tree so that the unchanged parts of it can be reused.
184
+ * This will save time and memory. For this to work correctly, you must have
185
+ * already edited the old syntax tree using the {Tree#edit} function in a
186
+ * way that exactly matches the source code changes.
187
+ *
188
+ * The input parameter lets you specify how to read the text. It has the
189
+ * following three fields:
190
+ * 1. +read+: A function to retrieve a chunk of text at a given byte offset
191
+ * and (row, column) position. The function should return a pointer to the
192
+ * text and write its length to the +bytes_read+ pointer. The parser does
193
+ * not take ownership of this buffer; it just borrows it until it has
194
+ * finished reading it. The function should write a zero value to the
195
+ * +bytes_read+ pointer to indicate the end of the document.
196
+ * 2. +payload+: An arbitrary pointer that will be passed to each invocation
197
+ * of the +read+ function.
198
+ * 3. +encoding+: An indication of how the text is encoded. Either
199
+ * {Encoding::UTF8} or {Encoding::UTF16}.
200
+ *
201
+ * This function returns a syntax tree on success, and +nil+ on failure. There
202
+ * are three possible reasons for failure:
203
+ * 1. The parser does not have a language assigned. Check for this using the
204
+ * {Parser#language} function.
205
+ * 2. Parsing was cancelled due to a timeout that was set by an earlier call to
206
+ * the {Parser#timeout_micros=} function. You can resume parsing from
207
+ * where the parser left out by calling {Parser#parse} again with the
208
+ * same arguments. Or you can start parsing from scratch by first calling
209
+ * {Parser#reset}.
210
+ * 3. Parsing was cancelled using a cancellation flag that was set by an
211
+ * earlier call to {Parsert#cancellation_flag=}. You can resume parsing
212
+ * from where the parser left out by calling {Parser#parse} again with
213
+ * the same arguments.
214
+ *
215
+ * @note this is curently incomplete, as the {Input} class is incomplete.
216
+ *
217
+ * @param old_tree [Tree]
218
+ * @param input [Input]
219
+ *
220
+ * @return [Tree, nil] A parse tree if parsing was successful.
221
+ */
105
222
  static VALUE parser_parse(VALUE self, VALUE old_tree, VALUE input) {
106
223
  if (NIL_P(input)) {
107
224
  return Qnil;
@@ -120,6 +237,17 @@ static VALUE parser_parse(VALUE self, VALUE old_tree, VALUE input) {
120
237
  }
121
238
  }
122
239
 
240
+ /**
241
+ * Use the parser to parse some source code stored in one contiguous buffer.
242
+ * The first two parameters are the same as in the {Parser#parse} function
243
+ * above. The second two parameters indicate the location of the buffer and its
244
+ * length in bytes.
245
+ *
246
+ * @param old_tree [Tree]
247
+ * @param string [String]
248
+ *
249
+ * @return [Tree, nil] A parse tree if parsing was successful.
250
+ */
123
251
  static VALUE parser_parse_string(VALUE self, VALUE old_tree, VALUE string) {
124
252
  if (NIL_P(string)) {
125
253
  return Qnil;
@@ -140,6 +268,18 @@ static VALUE parser_parse_string(VALUE self, VALUE old_tree, VALUE string) {
140
268
  }
141
269
  }
142
270
 
271
+ /**
272
+ * Use the parser to parse some source code stored in one contiguous buffer with
273
+ * a given encoding. The first four parameters work the same as in the
274
+ * {Parser#parse_string} method above. The final parameter indicates whether
275
+ * the text is encoded as {Encoding::UTF8} or {Encoding::UTF16}.
276
+ *
277
+ * @param old_tree [Tree]
278
+ * @param string [String]
279
+ * @param encoding [Encoding]
280
+ *
281
+ * @return [Tree, nil] A parse tree if parsing was successful.
282
+ */
143
283
  static VALUE parser_parse_string_encoding(VALUE self, VALUE old_tree,
144
284
  VALUE string, VALUE encoding) {
145
285
  if (NIL_P(string)) {
@@ -163,11 +303,17 @@ static VALUE parser_parse_string_encoding(VALUE self, VALUE old_tree,
163
303
  }
164
304
  }
165
305
 
166
- static VALUE parser_reset(VALUE self) {
167
- ts_parser_reset(SELF);
168
- return Qnil;
169
- }
170
-
306
+ /**
307
+ * Set the file descriptor to which the parser should write debugging graphs
308
+ * during parsing. The graphs are formatted in the DOT language. You may want
309
+ * to pipe these graphs directly to a +dot(1)+ process in order to generate
310
+ * SVG output. You can turn off this logging by passing a negative number.
311
+ *
312
+ * @param file [Integer, String, nil] a file name to print, or turn off by
313
+ * passing +nil+ or +-1+
314
+ *
315
+ * @return nil
316
+ */
171
317
  static VALUE parser_print_dot_graphs(VALUE self, VALUE file) {
172
318
  if (NIL_P(file)) {
173
319
  ts_parser_print_dot_graphs(SELF, -1);
@@ -183,21 +329,70 @@ static VALUE parser_print_dot_graphs(VALUE self, VALUE file) {
183
329
  return Qnil;
184
330
  }
185
331
 
332
+ /**
333
+ * Instruct the parser to start the next parse from the beginning.
334
+ *
335
+ * If the parser previously failed because of a timeout or a cancellation, then
336
+ * by default, it will resume where it left off on the next call to
337
+ * {Parser#parse} or other parsing functions. If you don't want to resume,
338
+ * and instead intend to use this parser to parse some other document, you must
339
+ * call {Parser#reset} first.
340
+ *
341
+ * @return nil
342
+ */
343
+ static VALUE parser_reset(VALUE self) {
344
+ ts_parser_reset(SELF);
345
+ return Qnil;
346
+ }
347
+
348
+ /**
349
+ * Get the duration in microseconds that parsing is allowed to take.
350
+ *
351
+ * @return [Integer]
352
+ */
353
+ static VALUE parser_get_timeout_micros(VALUE self) {
354
+ return ULL2NUM(ts_parser_timeout_micros(SELF));
355
+ }
356
+
357
+ /**
358
+ * Set the maximum duration in microseconds that parsing should be allowed to
359
+ * take before halting.
360
+ *
361
+ * If parsing takes longer than this, it will halt early, returning +nil+.
362
+ *
363
+ * @see parse
364
+ *
365
+ * @param timeout [Integer]
366
+ *
367
+ * @return [nil]
368
+ */
369
+ static VALUE parser_set_timeout_micros(VALUE self, VALUE timeout) {
370
+ ts_parser_set_timeout_micros(SELF, NUM2ULL(timeout));
371
+ return Qnil;
372
+ }
373
+
186
374
  void init_parser(void) {
187
375
  cParser = rb_define_class_under(mTreeSitter, "Parser", rb_cObject);
188
376
 
189
377
  rb_define_alloc_func(cParser, parser_allocate);
190
378
 
191
379
  /* Class methods */
192
- DECLARE_ACCESSOR(cParser, parser, language)
193
- DECLARE_ACCESSOR(cParser, parser, included_ranges)
194
- DECLARE_ACCESSOR(cParser, parser, timeout_micros)
195
- DECLARE_ACCESSOR(cParser, parser, logger)
196
- DECLARE_ACCESSOR(cParser, parser, cancellation_flag)
380
+ rb_define_method(cParser, "cancellation_flag", parser_get_cancellation_flag,
381
+ 0);
382
+ rb_define_method(cParser, "cancellation_flag=", parser_set_cancellation_flag,
383
+ 1);
384
+ rb_define_method(cParser, "included_ranges", parser_get_included_ranges, 0);
385
+ rb_define_method(cParser, "included_ranges=", parser_set_included_ranges, 1);
386
+ rb_define_method(cParser, "language", parser_get_language, 0);
387
+ rb_define_method(cParser, "language=", parser_set_language, 1);
388
+ rb_define_method(cParser, "logger", parser_get_logger, 0);
389
+ rb_define_method(cParser, "logger=", parser_set_logger, 1);
197
390
  rb_define_method(cParser, "parse", parser_parse, 2);
198
391
  rb_define_method(cParser, "parse_string", parser_parse_string, 2);
199
392
  rb_define_method(cParser, "parse_string_encoding",
200
393
  parser_parse_string_encoding, 3);
201
- rb_define_method(cParser, "reset", parser_reset, 0);
202
394
  rb_define_method(cParser, "print_dot_graphs", parser_print_dot_graphs, 1);
395
+ rb_define_method(cParser, "reset", parser_reset, 0);
396
+ rb_define_method(cParser, "timeout_micros", parser_get_timeout_micros, 0);
397
+ rb_define_method(cParser, "timeout_micros=", parser_set_timeout_micros, 1);
203
398
  }
@@ -6,7 +6,125 @@ VALUE cQuery;
6
6
 
7
7
  DATA_PTR_WRAP(Query, query);
8
8
 
9
+ /**
10
+ * Get the number of captures literals in the query.
11
+ *
12
+ * @return [Integer]
13
+ */
14
+ static VALUE query_capture_count(VALUE self) {
15
+ return UINT2NUM(ts_query_capture_count(SELF));
16
+ }
17
+
18
+ /**
19
+ * Get the name and length of one of the query's captures, or one of the
20
+ * query's string literals. Each capture and string is associated with a
21
+ * numeric id based on the order that it appeared in the query's source.
22
+ *
23
+ * @raise [IndexError] if out of range.
24
+ *
25
+ * @param index [Integer]
26
+ *
27
+ * @return [String]
28
+ */
29
+ static VALUE query_capture_name_for_id(VALUE self, VALUE index) {
30
+ const TSQuery *query = SELF;
31
+ uint32_t idx = NUM2UINT(index);
32
+ uint32_t range = ts_query_capture_count(query);
33
+
34
+ if (idx >= range) {
35
+ rb_raise(rb_eIndexError, "Index %d out of range (len = %d)", idx, range);
36
+ } else {
37
+ uint32_t length;
38
+ const char *name = ts_query_capture_name_for_id(query, idx, &length);
39
+ return safe_str2(name, length);
40
+ }
41
+ }
42
+
43
+ /**
44
+ * Get the quantifier of the query's captures. Each capture is associated
45
+ * with a numeric id based on the order that it appeared in the query's source.
46
+ *
47
+ * @raise [IndexError] if out of range.
48
+ *
49
+ * @param query_idx [Integer]
50
+ * @param capture_idx [Integer]
51
+ *
52
+ * @return [Integer]
53
+ */
54
+ static VALUE query_capture_quantifier_for_id(VALUE self, VALUE query_idx,
55
+ VALUE capture_idx) {
56
+ const TSQuery *query = SELF;
57
+ uint32_t pattern = NUM2UINT(query_idx);
58
+ uint32_t index = NUM2UINT(capture_idx);
59
+ uint32_t range = ts_query_capture_count(query);
60
+
61
+ if (index >= range) {
62
+ rb_raise(rb_eIndexError, "Capture ID %d out of range (len = %d)", index,
63
+ range);
64
+ } else {
65
+ return UINT2NUM(ts_query_capture_quantifier_for_id(query, pattern, index));
66
+ }
67
+ }
68
+
69
+ /**
70
+ * Disable a certain capture within a query.
71
+ *
72
+ * This prevents the capture from being returned in matches, and also avoids
73
+ * any resource usage associated with recording the capture. Currently, there
74
+ * is no way to undo this.
75
+ *
76
+ * @param capture [String]
77
+ *
78
+ * @return [nil]
79
+ */
80
+ static VALUE query_disable_capture(VALUE self, VALUE capture) {
81
+ const char *cap = StringValuePtr(capture);
82
+ uint32_t length = (uint32_t)RSTRING_LEN(capture);
83
+ ts_query_disable_capture(SELF, cap, length);
84
+ return Qnil;
85
+ }
86
+
87
+ /**
88
+ * Disable a certain pattern within a query.
89
+ *
90
+ * This prevents the pattern from matching and removes most of the overhead
91
+ * associated with the pattern. Currently, there is no way to undo this.
92
+ *
93
+ * @raise [IndexError] if out of range.
94
+ *
95
+ * @param pattern [Integer]
96
+ *
97
+ * @return [nil]
98
+ */
99
+ static VALUE query_disable_pattern(VALUE self, VALUE pattern) {
100
+ TSQuery *query = SELF;
101
+ uint32_t index = NUM2UINT(pattern);
102
+ uint32_t range = ts_query_pattern_count(query);
103
+
104
+ if (index >= range) {
105
+ rb_raise(rb_eIndexError, "Index %d out of range (len = %d)", index, range);
106
+ } else {
107
+ ts_query_disable_pattern(query, index);
108
+ return Qnil;
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Create a new query from a string containing one or more S-expression
114
+ * patterns. The query is associated with a particular language, and can
115
+ * only be run on syntax nodes parsed with that language.
116
+ *
117
+ * If all of the given patterns are valid, this returns a {Query}.
118
+ *
119
+ * @raise [RuntimeError]
120
+ *
121
+ * @param language [Language]
122
+ * @param source [String]
123
+ *
124
+ * @return [Query]
125
+ */
9
126
  static VALUE query_initialize(VALUE self, VALUE language, VALUE source) {
127
+ // FIXME: should we raise an exception here?
10
128
  TSLanguage *lang = value_to_language(language);
11
129
  const char *src = StringValuePtr(source);
12
130
  uint32_t len = (uint32_t)RSTRING_LEN(source);
@@ -25,30 +143,48 @@ static VALUE query_initialize(VALUE self, VALUE language, VALUE source) {
25
143
  return self;
26
144
  }
27
145
 
146
+ /**
147
+ * Get the number of patterns in the query.
148
+ *
149
+ * @return [Integer]
150
+ */
28
151
  static VALUE query_pattern_count(VALUE self) {
29
152
  return UINT2NUM(ts_query_pattern_count(SELF));
30
153
  }
31
154
 
32
- static VALUE query_capture_count(VALUE self) {
33
- return UINT2NUM(ts_query_capture_count(SELF));
34
- }
35
-
36
- static VALUE query_string_count(VALUE self) {
37
- return UINT2NUM(ts_query_string_count(SELF));
38
- }
39
-
40
- static VALUE query_start_byte_for_pattern(VALUE self, VALUE pattern_index) {
41
- const TSQuery *query = SELF;
42
- uint32_t index = NUM2UINT(pattern_index);
43
- uint32_t range = ts_query_pattern_count(query);
44
-
45
- if (index >= range) {
46
- rb_raise(rb_eIndexError, "Index %d out of range (len = %d)", index, range);
47
- } else {
48
- return UINT2NUM(ts_query_start_byte_for_pattern(SELF, index));
49
- }
155
+ /**
156
+ * Check if a given pattern is guaranteed to match once a given step is reached.
157
+ * The step is specified by its byte offset in the query's source code.
158
+ *
159
+ * @param byte_offset [Integer]
160
+ *
161
+ * @return [Integer]
162
+ */
163
+ static VALUE query_pattern_guaranteed_at_step(VALUE self, VALUE byte_offset) {
164
+ return UINT2NUM(
165
+ ts_query_is_pattern_guaranteed_at_step(SELF, NUM2UINT(byte_offset)));
50
166
  }
51
167
 
168
+ /**
169
+ * Get all of the predicates for the given pattern in the query.
170
+ *
171
+ * The predicates are represented as a single array of steps. There are three
172
+ * types of steps in this array, which correspond to the three legal values for
173
+ * the +type+ field:
174
+ * - {QueryPredicateStep::CAPTURE}: Steps with this type represent names
175
+ * of captures. Their +value_id+ can be used with the
176
+ * {Query#capture_name_for_id} function to obtain the name of the capture.
177
+ * - {QueryPredicateStep::STRING}: Steps with this type represent literal
178
+ * strings. Their +value_id+ can be used with the
179
+ * {Query#string_value_for_id} function to obtain their string value.
180
+ * - {QueryPredicateStep::DONE}: Steps with this type are *sentinels*
181
+ * that represent the end of an individual predicate. If a pattern has two
182
+ * predicates, then there will be two steps with this +type+ in the array.
183
+ *
184
+ * @param pattern_index [Integer]
185
+ *
186
+ * @return [Array<QueryPredicateStep>]
187
+ */
52
188
  static VALUE query_predicates_for_pattern(VALUE self, VALUE pattern_index) {
53
189
  const TSQuery *query = SELF;
54
190
  uint32_t index = NUM2UINT(pattern_index);
@@ -64,40 +200,46 @@ static VALUE query_predicates_for_pattern(VALUE self, VALUE pattern_index) {
64
200
  return res;
65
201
  }
66
202
 
67
- static VALUE query_pattern_guaranteed_at_step(VALUE self, VALUE byte_offset) {
68
- return UINT2NUM(
69
- ts_query_is_pattern_guaranteed_at_step(SELF, NUM2UINT(byte_offset)));
70
- }
71
-
72
- static VALUE query_capture_name_for_id(VALUE self, VALUE id) {
203
+ /**
204
+ * Get the byte offset where the given pattern starts in the query's source.
205
+ *
206
+ * This can be useful when combining queries by concatenating their source
207
+ * code strings.
208
+ *
209
+ * @raise [IndexError] if out of range.
210
+ *
211
+ * @param pattern_index [Integer]
212
+ *
213
+ * @return [Integer]
214
+ */
215
+ static VALUE query_start_byte_for_pattern(VALUE self, VALUE pattern_index) {
73
216
  const TSQuery *query = SELF;
74
- uint32_t index = NUM2UINT(id);
75
- uint32_t range = ts_query_capture_count(query);
217
+ uint32_t index = NUM2UINT(pattern_index);
218
+ uint32_t range = ts_query_pattern_count(query);
76
219
 
77
220
  if (index >= range) {
78
221
  rb_raise(rb_eIndexError, "Index %d out of range (len = %d)", index, range);
79
222
  } else {
80
- uint32_t length;
81
- const char *name = ts_query_capture_name_for_id(query, index, &length);
82
- return safe_str2(name, length);
223
+ return UINT2NUM(ts_query_start_byte_for_pattern(SELF, index));
83
224
  }
84
225
  }
85
226
 
86
- static VALUE query_capture_quantifier_for_id(VALUE self, VALUE id,
87
- VALUE capture_id) {
88
- const TSQuery *query = SELF;
89
- uint32_t pattern = NUM2UINT(id);
90
- uint32_t index = NUM2UINT(capture_id);
91
- uint32_t range = ts_query_capture_count(query);
92
-
93
- if (index >= range) {
94
- rb_raise(rb_eIndexError, "Capture ID %d out of range (len = %d)", index,
95
- range);
96
- } else {
97
- return UINT2NUM(ts_query_capture_quantifier_for_id(query, pattern, index));
98
- }
227
+ /**
228
+ * Get the number of string literals in the query.
229
+ *
230
+ * @return [Integer]
231
+ */
232
+ static VALUE query_string_count(VALUE self) {
233
+ return UINT2NUM(ts_query_string_count(SELF));
99
234
  }
100
235
 
236
+ /**
237
+ * @raise [IndexError] if out of range.
238
+ *
239
+ * @param id [Integer]
240
+ *
241
+ * @return [String]
242
+ */
101
243
  static VALUE query_string_value_for_id(VALUE self, VALUE id) {
102
244
  const TSQuery *query = SELF;
103
245
  uint32_t index = NUM2UINT(id);
@@ -112,46 +254,29 @@ static VALUE query_string_value_for_id(VALUE self, VALUE id) {
112
254
  }
113
255
  }
114
256
 
115
- static VALUE query_disable_capture(VALUE self, VALUE capture) {
116
- const char *cap = StringValuePtr(capture);
117
- uint32_t length = (uint32_t)RSTRING_LEN(capture);
118
- ts_query_disable_capture(SELF, cap, length);
119
- return Qnil;
120
- }
121
-
122
- static VALUE query_disable_pattern(VALUE self, VALUE pattern) {
123
- TSQuery *query = SELF;
124
- uint32_t index = NUM2UINT(pattern);
125
- uint32_t range = ts_query_pattern_count(query);
126
-
127
- if (index >= range) {
128
- rb_raise(rb_eIndexError, "Index %d out of range (len = %d)", index, range);
129
- } else {
130
- ts_query_disable_pattern(query, index);
131
- return Qnil;
132
- }
133
- }
134
-
257
+ // FIXME: missing:
258
+ // 1. ts_query_is_pattern_rooted
259
+ // 1. ts_query_is_pattern_non_local
135
260
  void init_query(void) {
136
261
  cQuery = rb_define_class_under(mTreeSitter, "Query", rb_cObject);
137
262
 
138
263
  rb_define_alloc_func(cQuery, query_allocate);
139
264
 
140
265
  /* Class methods */
141
- rb_define_method(cQuery, "initialize", query_initialize, 2);
142
- rb_define_method(cQuery, "pattern_count", query_pattern_count, 0);
143
266
  rb_define_method(cQuery, "capture_count", query_capture_count, 0);
144
- rb_define_method(cQuery, "string_count", query_string_count, 0);
145
- rb_define_method(cQuery, "start_byte_for_pattern",
146
- query_start_byte_for_pattern, 1);
147
- rb_define_method(cQuery, "predicates_for_pattern",
148
- query_predicates_for_pattern, 1);
149
- rb_define_method(cQuery, "pattern_guaranteed_at_step?",
150
- query_pattern_guaranteed_at_step, 1);
151
267
  rb_define_method(cQuery, "capture_name_for_id", query_capture_name_for_id, 1);
152
268
  rb_define_method(cQuery, "capture_quantifier_for_id",
153
269
  query_capture_quantifier_for_id, 2);
154
- rb_define_method(cQuery, "string_value_for_id", query_string_value_for_id, 1);
155
270
  rb_define_method(cQuery, "disable_capture", query_disable_capture, 1);
156
271
  rb_define_method(cQuery, "disable_pattern", query_disable_pattern, 1);
272
+ rb_define_method(cQuery, "initialize", query_initialize, 2);
273
+ rb_define_method(cQuery, "pattern_count", query_pattern_count, 0);
274
+ rb_define_method(cQuery, "pattern_guaranteed_at_step?",
275
+ query_pattern_guaranteed_at_step, 1);
276
+ rb_define_method(cQuery, "predicates_for_pattern",
277
+ query_predicates_for_pattern, 1);
278
+ rb_define_method(cQuery, "start_byte_for_pattern",
279
+ query_start_byte_for_pattern, 1);
280
+ rb_define_method(cQuery, "string_count", query_string_count, 0);
281
+ rb_define_method(cQuery, "string_value_for_id", query_string_value_for_id, 1);
157
282
  }