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.
- checksums.yaml +4 -4
- data/LICENSE +2 -1
- data/README.md +32 -18
- data/ext/tree_sitter/extconf.rb +1 -43
- data/ext/tree_sitter/input.c +1 -0
- data/ext/tree_sitter/language.c +131 -46
- data/ext/tree_sitter/logger.c +28 -12
- data/ext/tree_sitter/node.c +438 -130
- data/ext/tree_sitter/parser.c +232 -37
- data/ext/tree_sitter/query.c +197 -72
- data/ext/tree_sitter/query_cursor.c +140 -28
- data/ext/tree_sitter/repo.rb +121 -0
- data/ext/tree_sitter/tree.c +118 -34
- data/ext/tree_sitter/tree_cursor.c +205 -33
- data/ext/tree_sitter/tree_sitter.c +12 -0
- data/lib/tree_sitter/node.rb +43 -9
- data/lib/tree_sitter/tree_sitter.bundle +0 -0
- data/lib/tree_sitter/version.rb +4 -2
- data/lib/tree_sitter.rb +1 -0
- data/lib/tree_stand/ast_modifier.rb +30 -0
- data/lib/tree_stand/breadth_first_visitor.rb +54 -0
- data/lib/tree_stand/config.rb +13 -0
- data/lib/tree_stand/node.rb +224 -0
- data/lib/tree_stand/parser.rb +67 -0
- data/lib/tree_stand/range.rb +55 -0
- data/lib/tree_stand/tree.rb +123 -0
- data/lib/tree_stand/utils/printer.rb +73 -0
- data/lib/tree_stand/version.rb +7 -0
- data/lib/tree_stand/visitor.rb +127 -0
- data/lib/tree_stand/visitors/tree_walker.rb +37 -0
- data/lib/tree_stand.rb +48 -0
- data/tree_sitter.gemspec +15 -12
- metadata +37 -107
- data/test/README.md +0 -15
- data/test/test_helper.rb +0 -9
- data/test/tree_sitter/js_test.rb +0 -48
- data/test/tree_sitter/language_test.rb +0 -73
- data/test/tree_sitter/logger_test.rb +0 -70
- data/test/tree_sitter/node_test.rb +0 -355
- data/test/tree_sitter/parser_test.rb +0 -140
- data/test/tree_sitter/query_test.rb +0 -153
- data/test/tree_sitter/tree_cursor_test.rb +0 -83
- data/test/tree_sitter/tree_test.rb +0 -51
data/ext/tree_sitter/parser.c
CHANGED
@@ -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
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
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
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
static VALUE
|
95
|
-
|
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
|
-
|
167
|
-
|
168
|
-
|
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
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
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
|
}
|
data/ext/tree_sitter/query.c
CHANGED
@@ -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
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
static VALUE
|
41
|
-
|
42
|
-
|
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
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
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(
|
75
|
-
uint32_t range =
|
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
|
-
|
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
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
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
|
-
|
116
|
-
|
117
|
-
|
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
|
}
|