ruby_tree_sitter 1.6.0-arm-linux-gnu
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 +7 -0
- data/LICENSE +22 -0
- data/README.md +213 -0
- data/ext/tree_sitter/encoding.c +29 -0
- data/ext/tree_sitter/extconf.rb +149 -0
- data/ext/tree_sitter/input.c +127 -0
- data/ext/tree_sitter/input_edit.c +42 -0
- data/ext/tree_sitter/language.c +219 -0
- data/ext/tree_sitter/logger.c +228 -0
- data/ext/tree_sitter/macros.h +163 -0
- data/ext/tree_sitter/node.c +623 -0
- data/ext/tree_sitter/parser.c +398 -0
- data/ext/tree_sitter/point.c +26 -0
- data/ext/tree_sitter/quantifier.c +43 -0
- data/ext/tree_sitter/query.c +289 -0
- data/ext/tree_sitter/query_capture.c +28 -0
- data/ext/tree_sitter/query_cursor.c +231 -0
- data/ext/tree_sitter/query_error.c +41 -0
- data/ext/tree_sitter/query_match.c +44 -0
- data/ext/tree_sitter/query_predicate_step.c +83 -0
- data/ext/tree_sitter/range.c +35 -0
- data/ext/tree_sitter/repo.rb +128 -0
- data/ext/tree_sitter/symbol_type.c +46 -0
- data/ext/tree_sitter/tree.c +234 -0
- data/ext/tree_sitter/tree_cursor.c +269 -0
- data/ext/tree_sitter/tree_sitter.c +44 -0
- data/ext/tree_sitter/tree_sitter.h +107 -0
- data/lib/tree_sitter/3.0/tree_sitter.so +0 -0
- data/lib/tree_sitter/3.1/tree_sitter.so +0 -0
- data/lib/tree_sitter/3.2/tree_sitter.so +0 -0
- data/lib/tree_sitter/3.3/tree_sitter.so +0 -0
- data/lib/tree_sitter/helpers.rb +23 -0
- data/lib/tree_sitter/mixins/language.rb +167 -0
- data/lib/tree_sitter/node.rb +167 -0
- data/lib/tree_sitter/query.rb +191 -0
- data/lib/tree_sitter/query_captures.rb +30 -0
- data/lib/tree_sitter/query_cursor.rb +27 -0
- data/lib/tree_sitter/query_match.rb +100 -0
- data/lib/tree_sitter/query_matches.rb +39 -0
- data/lib/tree_sitter/query_predicate.rb +14 -0
- data/lib/tree_sitter/text_predicate_capture.rb +37 -0
- data/lib/tree_sitter/version.rb +8 -0
- data/lib/tree_sitter.rb +34 -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 +19 -0
- data/lib/tree_stand/node.rb +351 -0
- data/lib/tree_stand/parser.rb +87 -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 +34 -0
- metadata +135 -0
@@ -0,0 +1,289 @@
|
|
1
|
+
#include "tree_sitter.h"
|
2
|
+
|
3
|
+
extern VALUE mTreeSitter;
|
4
|
+
|
5
|
+
VALUE cQuery;
|
6
|
+
|
7
|
+
DATA_PTR_WRAP(Query, query);
|
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
|
+
*/
|
126
|
+
static VALUE query_initialize(VALUE self, VALUE language, VALUE source) {
|
127
|
+
// FIXME: should we raise an exception here?
|
128
|
+
TSLanguage *lang = value_to_language(language);
|
129
|
+
const char *src = StringValuePtr(source);
|
130
|
+
uint32_t len = (uint32_t)RSTRING_LEN(source);
|
131
|
+
uint32_t error_offset = 0;
|
132
|
+
TSQueryError error_type;
|
133
|
+
|
134
|
+
TSQuery *res = ts_query_new(lang, src, len, &error_offset, &error_type);
|
135
|
+
|
136
|
+
if (res == NULL || error_offset > 0) {
|
137
|
+
rb_raise(rb_eRuntimeError, "Could not create query: TSQueryError%s",
|
138
|
+
query_error_str(error_type));
|
139
|
+
} else {
|
140
|
+
SELF = res;
|
141
|
+
}
|
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
|
+
|
150
|
+
return self;
|
151
|
+
}
|
152
|
+
|
153
|
+
/**
|
154
|
+
* Get the number of patterns in the query.
|
155
|
+
*
|
156
|
+
* @return [Integer]
|
157
|
+
*/
|
158
|
+
static VALUE query_pattern_count(VALUE self) {
|
159
|
+
return UINT2NUM(ts_query_pattern_count(SELF));
|
160
|
+
}
|
161
|
+
|
162
|
+
/**
|
163
|
+
* Check if a given pattern is guaranteed to match once a given step is reached.
|
164
|
+
* The step is specified by its byte offset in the query's source code.
|
165
|
+
*
|
166
|
+
* @param byte_offset [Integer]
|
167
|
+
*
|
168
|
+
* @return [Integer]
|
169
|
+
*/
|
170
|
+
static VALUE query_pattern_guaranteed_at_step(VALUE self, VALUE byte_offset) {
|
171
|
+
return UINT2NUM(
|
172
|
+
ts_query_is_pattern_guaranteed_at_step(SELF, NUM2UINT(byte_offset)));
|
173
|
+
}
|
174
|
+
|
175
|
+
/**
|
176
|
+
* Get all of the predicates for the given pattern in the query.
|
177
|
+
*
|
178
|
+
* The predicates are represented as a single array of steps. There are three
|
179
|
+
* types of steps in this array, which correspond to the three legal values for
|
180
|
+
* the +type+ field:
|
181
|
+
* - {QueryPredicateStep::CAPTURE}: Steps with this type represent names
|
182
|
+
* of captures. Their +value_id+ can be used with the
|
183
|
+
* {Query#capture_name_for_id} function to obtain the name of the capture.
|
184
|
+
* - {QueryPredicateStep::STRING}: Steps with this type represent literal
|
185
|
+
* strings. Their +value_id+ can be used with the
|
186
|
+
* {Query#string_value_for_id} function to obtain their string value.
|
187
|
+
* - {QueryPredicateStep::DONE}: Steps with this type are *sentinels*
|
188
|
+
* that represent the end of an individual predicate. If a pattern has two
|
189
|
+
* predicates, then there will be two steps with this +type+ in the array.
|
190
|
+
*
|
191
|
+
* @param pattern_index [Integer]
|
192
|
+
*
|
193
|
+
* @return [Array<QueryPredicateStep>]
|
194
|
+
*/
|
195
|
+
static VALUE query_predicates_for_pattern(VALUE self, VALUE pattern_index) {
|
196
|
+
const TSQuery *query = SELF;
|
197
|
+
uint32_t index = NUM2UINT(pattern_index);
|
198
|
+
uint32_t length;
|
199
|
+
const TSQueryPredicateStep *steps =
|
200
|
+
ts_query_predicates_for_pattern(query, index, &length);
|
201
|
+
VALUE res = rb_ary_new_capa(length);
|
202
|
+
|
203
|
+
for (uint32_t i = 0; i < length; i++) {
|
204
|
+
rb_ary_push(res, new_query_predicate_step(&steps[i]));
|
205
|
+
}
|
206
|
+
|
207
|
+
return res;
|
208
|
+
}
|
209
|
+
|
210
|
+
/**
|
211
|
+
* Get the byte offset where the given pattern starts in the query's source.
|
212
|
+
*
|
213
|
+
* This can be useful when combining queries by concatenating their source
|
214
|
+
* code strings.
|
215
|
+
*
|
216
|
+
* @raise [IndexError] if out of range.
|
217
|
+
*
|
218
|
+
* @param pattern_index [Integer]
|
219
|
+
*
|
220
|
+
* @return [Integer]
|
221
|
+
*/
|
222
|
+
static VALUE query_start_byte_for_pattern(VALUE self, VALUE pattern_index) {
|
223
|
+
const TSQuery *query = SELF;
|
224
|
+
uint32_t index = NUM2UINT(pattern_index);
|
225
|
+
uint32_t range = ts_query_pattern_count(query);
|
226
|
+
|
227
|
+
if (index >= range) {
|
228
|
+
rb_raise(rb_eIndexError, "Index %d out of range (len = %d)", index, range);
|
229
|
+
} else {
|
230
|
+
return UINT2NUM(ts_query_start_byte_for_pattern(SELF, index));
|
231
|
+
}
|
232
|
+
}
|
233
|
+
|
234
|
+
/**
|
235
|
+
* Get the number of string literals in the query.
|
236
|
+
*
|
237
|
+
* @return [Integer]
|
238
|
+
*/
|
239
|
+
static VALUE query_string_count(VALUE self) {
|
240
|
+
return UINT2NUM(ts_query_string_count(SELF));
|
241
|
+
}
|
242
|
+
|
243
|
+
/**
|
244
|
+
* @raise [IndexError] if out of range.
|
245
|
+
*
|
246
|
+
* @param id [Integer]
|
247
|
+
*
|
248
|
+
* @return [String]
|
249
|
+
*/
|
250
|
+
static VALUE query_string_value_for_id(VALUE self, VALUE id) {
|
251
|
+
const TSQuery *query = SELF;
|
252
|
+
uint32_t index = NUM2UINT(id);
|
253
|
+
uint32_t range = ts_query_string_count(query);
|
254
|
+
|
255
|
+
if (index >= range) {
|
256
|
+
rb_raise(rb_eIndexError, "Index %d out of range (len = %d)", index, range);
|
257
|
+
} else {
|
258
|
+
uint32_t length;
|
259
|
+
const char *string = ts_query_string_value_for_id(query, index, &length);
|
260
|
+
return safe_str2(string, length);
|
261
|
+
}
|
262
|
+
}
|
263
|
+
|
264
|
+
// FIXME: missing:
|
265
|
+
// 1. ts_query_is_pattern_rooted
|
266
|
+
// 1. ts_query_is_pattern_non_local
|
267
|
+
void init_query(void) {
|
268
|
+
cQuery = rb_define_class_under(mTreeSitter, "Query", rb_cObject);
|
269
|
+
|
270
|
+
rb_define_alloc_func(cQuery, query_allocate);
|
271
|
+
|
272
|
+
/* Class methods */
|
273
|
+
rb_define_method(cQuery, "capture_count", query_capture_count, 0);
|
274
|
+
rb_define_method(cQuery, "capture_name_for_id", query_capture_name_for_id, 1);
|
275
|
+
rb_define_method(cQuery, "capture_quantifier_for_id",
|
276
|
+
query_capture_quantifier_for_id, 2);
|
277
|
+
rb_define_method(cQuery, "disable_capture", query_disable_capture, 1);
|
278
|
+
rb_define_method(cQuery, "disable_pattern", query_disable_pattern, 1);
|
279
|
+
rb_define_method(cQuery, "initialize", query_initialize, 2);
|
280
|
+
rb_define_method(cQuery, "pattern_count", query_pattern_count, 0);
|
281
|
+
rb_define_method(cQuery, "pattern_guaranteed_at_step?",
|
282
|
+
query_pattern_guaranteed_at_step, 1);
|
283
|
+
rb_define_method(cQuery, "predicates_for_pattern",
|
284
|
+
query_predicates_for_pattern, 1);
|
285
|
+
rb_define_method(cQuery, "start_byte_for_pattern",
|
286
|
+
query_start_byte_for_pattern, 1);
|
287
|
+
rb_define_method(cQuery, "string_count", query_string_count, 0);
|
288
|
+
rb_define_method(cQuery, "string_value_for_id", query_string_value_for_id, 1);
|
289
|
+
}
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#include "tree_sitter.h"
|
2
|
+
|
3
|
+
extern VALUE mTreeSitter;
|
4
|
+
|
5
|
+
VALUE cQueryCapture;
|
6
|
+
|
7
|
+
DATA_WRAP(QueryCapture, query_capture)
|
8
|
+
DATA_DEFINE_GETTER(query_capture, index, UINT2NUM)
|
9
|
+
DATA_DEFINE_GETTER(query_capture, node, new_node_by_val)
|
10
|
+
|
11
|
+
static VALUE query_capture_inspect(VALUE self) {
|
12
|
+
TSQueryCapture query_capture = SELF;
|
13
|
+
return rb_sprintf("{index=%d, node=%+" PRIsVALUE "}", query_capture.index,
|
14
|
+
new_node(&query_capture.node));
|
15
|
+
}
|
16
|
+
|
17
|
+
void init_query_capture(void) {
|
18
|
+
cQueryCapture =
|
19
|
+
rb_define_class_under(mTreeSitter, "QueryCapture", rb_cObject);
|
20
|
+
|
21
|
+
rb_define_alloc_func(cQueryCapture, query_capture_allocate);
|
22
|
+
|
23
|
+
/* Class methods */
|
24
|
+
DECLARE_GETTER(cQueryCapture, query_capture, index)
|
25
|
+
DECLARE_GETTER(cQueryCapture, query_capture, node)
|
26
|
+
rb_define_method(cQueryCapture, "inspect", query_capture_inspect, 0);
|
27
|
+
rb_define_method(cQueryCapture, "to_s", query_capture_inspect, 0);
|
28
|
+
}
|
@@ -0,0 +1,231 @@
|
|
1
|
+
#include "tree_sitter.h"
|
2
|
+
|
3
|
+
extern VALUE mTreeSitter;
|
4
|
+
|
5
|
+
VALUE cQueryCursor;
|
6
|
+
|
7
|
+
DATA_TYPE(TSQueryCursor *, query_cursor)
|
8
|
+
DATA_FREE_PTR(query_cursor)
|
9
|
+
DATA_MEMSIZE(query_cursor)
|
10
|
+
DATA_DECLARE_DATA_TYPE(query_cursor)
|
11
|
+
static VALUE query_cursor_allocate(VALUE klass) {
|
12
|
+
query_cursor_t *query_cursor;
|
13
|
+
VALUE res = TypedData_Make_Struct(klass, query_cursor_t,
|
14
|
+
&query_cursor_data_type, query_cursor);
|
15
|
+
query_cursor->data = ts_query_cursor_new();
|
16
|
+
return res;
|
17
|
+
}
|
18
|
+
DATA_UNWRAP(query_cursor)
|
19
|
+
/**
|
20
|
+
* Create a new cursor for executing a given query.
|
21
|
+
*
|
22
|
+
* The cursor stores the state that is needed to iteratively search
|
23
|
+
* for matches. To use the query cursor, first call {QueryCursor#exec}
|
24
|
+
* to start running a given query on a given syntax node. Then, there are
|
25
|
+
* two options for consuming the results of the query:
|
26
|
+
* 1. Repeatedly call {QueryCursor#next_match} to iterate over all of the
|
27
|
+
* *matches* in the order that they were found. Each match contains the
|
28
|
+
* index of the pattern that matched, and an array of captures. Because
|
29
|
+
* multiple patterns can match the same set of nodes, one match may contain
|
30
|
+
* captures that appear *before* some of the captures from a previous match.
|
31
|
+
* 2. Repeatedly call {QueryCursor#next_capture} to iterate over all of the
|
32
|
+
* individual *captures* in the order that they appear. This is useful if
|
33
|
+
* don't care about which pattern matched, and just want a single ordered
|
34
|
+
* sequence of captures.
|
35
|
+
*
|
36
|
+
* If you don't care about consuming all of the results, you can stop calling
|
37
|
+
* {QueryCursor#next_match} or {QueryCursor#next_capture} at any point.
|
38
|
+
* You can then start executing another query on another node by calling
|
39
|
+
* {QueryCursor#exec} again.
|
40
|
+
*/
|
41
|
+
DATA_PTR_NEW(cQueryCursor, TSQueryCursor, query_cursor)
|
42
|
+
DATA_FROM_VALUE(TSQueryCursor *, query_cursor)
|
43
|
+
|
44
|
+
/**
|
45
|
+
* Start running a given query on a given node.
|
46
|
+
*
|
47
|
+
* @param query [Query]
|
48
|
+
* @param node [Node]
|
49
|
+
*
|
50
|
+
* @return [QueryCursor]
|
51
|
+
*/
|
52
|
+
static VALUE query_cursor_exec_static(VALUE self, VALUE query, VALUE node) {
|
53
|
+
VALUE res = query_cursor_allocate(cQueryCursor);
|
54
|
+
query_cursor_t *query_cursor = unwrap(res);
|
55
|
+
ts_query_cursor_exec(query_cursor->data, value_to_query(query),
|
56
|
+
value_to_node(node));
|
57
|
+
return res;
|
58
|
+
}
|
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
|
+
|
75
|
+
/**
|
76
|
+
* Manage the maximum number of in-progress matches allowed by this query
|
77
|
+
* cursor.
|
78
|
+
*
|
79
|
+
* Query cursors have an optional maximum capacity for storing lists of
|
80
|
+
* in-progress captures. If this capacity is exceeded, then the
|
81
|
+
* earliest-starting match will silently be dropped to make room for further
|
82
|
+
* matches. This maximum capacity is optional — by default, query cursors allow
|
83
|
+
* any number of pending matches, dynamically allocating new space for them as
|
84
|
+
* needed as the query is executed.
|
85
|
+
*/
|
86
|
+
static VALUE query_cursor_did_exceed_match_limit(VALUE self) {
|
87
|
+
return ts_query_cursor_did_exceed_match_limit(SELF) ? Qtrue : Qfalse;
|
88
|
+
}
|
89
|
+
|
90
|
+
/**
|
91
|
+
* @param limit [Integer]
|
92
|
+
*
|
93
|
+
* @return [nil]
|
94
|
+
*/
|
95
|
+
static VALUE query_cursor_set_match_limit(VALUE self, VALUE limit) {
|
96
|
+
ts_query_cursor_set_match_limit(SELF, NUM2UINT(limit));
|
97
|
+
return Qnil;
|
98
|
+
}
|
99
|
+
|
100
|
+
/**
|
101
|
+
* @return [Integer]
|
102
|
+
*/
|
103
|
+
static VALUE query_cursor_get_match_limit(VALUE self) {
|
104
|
+
return UINT2NUM(ts_query_cursor_match_limit(SELF));
|
105
|
+
}
|
106
|
+
|
107
|
+
/**
|
108
|
+
* Set the maximum start depth for a query cursor.
|
109
|
+
*
|
110
|
+
* This prevents cursors from exploring children nodes at a certain depth.
|
111
|
+
* Note if a pattern includes many children, then they will still be checked.
|
112
|
+
*
|
113
|
+
* The zero max start depth value can be used as a special behavior and
|
114
|
+
* it helps to destructure a subtree by staying on a node and using captures
|
115
|
+
* for interested parts. Note that the zero max start depth only limit a search
|
116
|
+
* depth for a pattern's root node but other nodes that are parts of the pattern
|
117
|
+
* may be searched at any depth what defined by the pattern structure.
|
118
|
+
*
|
119
|
+
* @param max_start_depth [Integer|nil] set to nil to remove the maximum start
|
120
|
+
* depth.
|
121
|
+
*
|
122
|
+
* @return [nil]
|
123
|
+
*/
|
124
|
+
static VALUE query_cursor_set_max_start_depth(VALUE self,
|
125
|
+
VALUE max_start_depth) {
|
126
|
+
uint32_t max = UINT32_MAX;
|
127
|
+
if (!NIL_P(max_start_depth)) {
|
128
|
+
max = NUM2UINT(max_start_depth);
|
129
|
+
}
|
130
|
+
ts_query_cursor_set_max_start_depth(SELF, max);
|
131
|
+
return Qnil;
|
132
|
+
}
|
133
|
+
|
134
|
+
// FIXME: maybe this is the limit of how "transparent" the bindings need to be.
|
135
|
+
// Pending benchmarks, this can be very inefficient because obviously
|
136
|
+
// ts_query_cursor_next_capture is intended to be used in a loop. Creating an
|
137
|
+
// array of two values and returning them, intuitively speaking, seem very
|
138
|
+
// inefficient.
|
139
|
+
// FIXME: maybe this needs to return an empty array to make for a nicer ruby
|
140
|
+
// API?
|
141
|
+
/**
|
142
|
+
* Advance to the next capture of the currently running query.
|
143
|
+
*
|
144
|
+
* @return [Array<Integer|Boolean>|nil] If there is a capture, return a tuple
|
145
|
+
* [Integer, Boolean], otherwise return +nil+.
|
146
|
+
*/
|
147
|
+
static VALUE query_cursor_next_capture(VALUE self) {
|
148
|
+
TSQueryMatch match;
|
149
|
+
uint32_t index;
|
150
|
+
if (ts_query_cursor_next_capture(SELF, &match, &index)) {
|
151
|
+
VALUE res = rb_ary_new_capa(2);
|
152
|
+
rb_ary_push(res, UINT2NUM(index));
|
153
|
+
rb_ary_push(res, new_query_match(&match));
|
154
|
+
return res;
|
155
|
+
} else {
|
156
|
+
return Qnil;
|
157
|
+
}
|
158
|
+
}
|
159
|
+
|
160
|
+
/**
|
161
|
+
* Advance to the next match of the currently running query.
|
162
|
+
*
|
163
|
+
* @return [Boolean] Whether there's a match.
|
164
|
+
*/
|
165
|
+
static VALUE query_cursor_next_match(VALUE self) {
|
166
|
+
TSQueryMatch match;
|
167
|
+
if (ts_query_cursor_next_match(SELF, &match)) {
|
168
|
+
return new_query_match(&match);
|
169
|
+
} else {
|
170
|
+
return Qnil;
|
171
|
+
}
|
172
|
+
}
|
173
|
+
|
174
|
+
static VALUE query_cursor_remove_match(VALUE self, VALUE id) {
|
175
|
+
ts_query_cursor_remove_match(SELF, NUM2UINT(id));
|
176
|
+
return Qnil;
|
177
|
+
}
|
178
|
+
|
179
|
+
/**
|
180
|
+
* @param from [Integer]
|
181
|
+
* @param to [Integer]
|
182
|
+
*
|
183
|
+
* @return [nil]
|
184
|
+
*/
|
185
|
+
static VALUE query_cursor_set_byte_range(VALUE self, VALUE from, VALUE to) {
|
186
|
+
ts_query_cursor_set_byte_range(SELF, NUM2UINT(from), NUM2UINT(to));
|
187
|
+
return Qnil;
|
188
|
+
}
|
189
|
+
|
190
|
+
/**
|
191
|
+
* @param from [Point]
|
192
|
+
* @param to [Point]
|
193
|
+
*
|
194
|
+
* @return [nil]
|
195
|
+
*/
|
196
|
+
static VALUE query_cursor_set_point_range(VALUE self, VALUE from, VALUE to) {
|
197
|
+
ts_query_cursor_set_point_range(SELF, value_to_point(from),
|
198
|
+
value_to_point(to));
|
199
|
+
return Qnil;
|
200
|
+
}
|
201
|
+
|
202
|
+
void init_query_cursor(void) {
|
203
|
+
cQueryCursor = rb_define_class_under(mTreeSitter, "QueryCursor", rb_cObject);
|
204
|
+
|
205
|
+
rb_define_alloc_func(cQueryCursor, query_cursor_allocate);
|
206
|
+
|
207
|
+
/* Module methods */
|
208
|
+
rb_define_module_function(cQueryCursor, "exec", query_cursor_exec_static, 2);
|
209
|
+
|
210
|
+
/* Class methods */
|
211
|
+
// Accessors
|
212
|
+
DECLARE_ACCESSOR(cQueryCursor, query_cursor, match_limit)
|
213
|
+
|
214
|
+
// Other
|
215
|
+
rb_define_method(cQueryCursor, "exec", query_cursor_exec, 2);
|
216
|
+
rb_define_method(cQueryCursor, "exceed_match_limit?",
|
217
|
+
query_cursor_did_exceed_match_limit, 0);
|
218
|
+
rb_define_method(cQueryCursor, "match_limit", query_cursor_get_match_limit,
|
219
|
+
0);
|
220
|
+
rb_define_method(cQueryCursor, "match_limit=", query_cursor_set_match_limit,
|
221
|
+
1);
|
222
|
+
rb_define_method(cQueryCursor,
|
223
|
+
"max_start_depth=", query_cursor_set_max_start_depth, 1);
|
224
|
+
rb_define_method(cQueryCursor, "next_capture", query_cursor_next_capture, 0);
|
225
|
+
rb_define_method(cQueryCursor, "next_match", query_cursor_next_match, 0);
|
226
|
+
rb_define_method(cQueryCursor, "remove_match", query_cursor_remove_match, 1);
|
227
|
+
rb_define_method(cQueryCursor, "set_byte_range", query_cursor_set_byte_range,
|
228
|
+
2);
|
229
|
+
rb_define_method(cQueryCursor, "set_point_range",
|
230
|
+
query_cursor_set_point_range, 2);
|
231
|
+
}
|
@@ -0,0 +1,41 @@
|
|
1
|
+
#include "tree_sitter.h"
|
2
|
+
|
3
|
+
extern VALUE mTreeSitter;
|
4
|
+
|
5
|
+
VALUE mQueryError;
|
6
|
+
|
7
|
+
TSQueryError value_to_query_error(VALUE query_error) {
|
8
|
+
return NUM2UINT(query_error);
|
9
|
+
}
|
10
|
+
|
11
|
+
const char *query_error_str(TSQueryError error) {
|
12
|
+
switch (error) {
|
13
|
+
case TSQueryErrorNone:
|
14
|
+
return "None";
|
15
|
+
case TSQueryErrorSyntax:
|
16
|
+
return "Syntax";
|
17
|
+
case TSQueryErrorNodeType:
|
18
|
+
return "Node Type";
|
19
|
+
case TSQueryErrorField:
|
20
|
+
return "Field";
|
21
|
+
case TSQueryErrorCapture:
|
22
|
+
return "Capture";
|
23
|
+
case TSQueryErrorStructure:
|
24
|
+
return "Structure";
|
25
|
+
case TSQueryErrorLanguage:
|
26
|
+
return "Language";
|
27
|
+
default:
|
28
|
+
return "??";
|
29
|
+
}
|
30
|
+
}
|
31
|
+
|
32
|
+
void init_query_error(void) {
|
33
|
+
mQueryError = rb_define_module_under(mTreeSitter, "QueryError");
|
34
|
+
rb_define_const(mQueryError, "NONE", UINT2NUM(0));
|
35
|
+
rb_define_const(mQueryError, "Syntax", UINT2NUM(1));
|
36
|
+
rb_define_const(mQueryError, "NodeType", UINT2NUM(2));
|
37
|
+
rb_define_const(mQueryError, "Field", UINT2NUM(3));
|
38
|
+
rb_define_const(mQueryError, "Capture", UINT2NUM(4));
|
39
|
+
rb_define_const(mQueryError, "Structure", UINT2NUM(5));
|
40
|
+
rb_define_const(mQueryError, "Language", UINT2NUM(6));
|
41
|
+
}
|
@@ -0,0 +1,44 @@
|
|
1
|
+
#include "tree_sitter.h"
|
2
|
+
|
3
|
+
extern VALUE mTreeSitter;
|
4
|
+
|
5
|
+
VALUE cQueryMatch;
|
6
|
+
|
7
|
+
DATA_WRAP(QueryMatch, query_match)
|
8
|
+
DATA_DEFINE_GETTER(query_match, id, UINT2NUM)
|
9
|
+
DATA_DEFINE_GETTER(query_match, pattern_index, INT2FIX)
|
10
|
+
DATA_DEFINE_GETTER(query_match, capture_count, INT2FIX)
|
11
|
+
|
12
|
+
static VALUE query_match_get_captures(VALUE self) {
|
13
|
+
query_match_t *query_match = unwrap(self);
|
14
|
+
|
15
|
+
uint16_t length = query_match->data.capture_count;
|
16
|
+
VALUE res = rb_ary_new_capa(length);
|
17
|
+
const TSQueryCapture *captures = query_match->data.captures;
|
18
|
+
for (int i = 0; i < length; i++) {
|
19
|
+
rb_ary_push(res, new_query_capture(&captures[i]));
|
20
|
+
}
|
21
|
+
|
22
|
+
return res;
|
23
|
+
}
|
24
|
+
|
25
|
+
static VALUE query_match_inspect(VALUE self) {
|
26
|
+
TSQueryMatch query_match = SELF;
|
27
|
+
return rb_sprintf("{id=%d, pattern_inex=%d, capture_count=%d}",
|
28
|
+
query_match.id, query_match.pattern_index,
|
29
|
+
query_match.capture_count);
|
30
|
+
}
|
31
|
+
|
32
|
+
void init_query_match(void) {
|
33
|
+
cQueryMatch = rb_define_class_under(mTreeSitter, "QueryMatch", rb_cObject);
|
34
|
+
|
35
|
+
rb_define_alloc_func(cQueryMatch, query_match_allocate);
|
36
|
+
|
37
|
+
/* Class methods */
|
38
|
+
DECLARE_GETTER(cQueryMatch, query_match, id)
|
39
|
+
DECLARE_GETTER(cQueryMatch, query_match, pattern_index)
|
40
|
+
DECLARE_GETTER(cQueryMatch, query_match, capture_count)
|
41
|
+
DECLARE_GETTER(cQueryMatch, query_match, captures)
|
42
|
+
rb_define_method(cQueryMatch, "inspect", query_match_inspect, 0);
|
43
|
+
rb_define_method(cQueryMatch, "to_s", query_match_inspect, 0);
|
44
|
+
}
|