ruby_tree_sitter 1.6.0-arm-linux-musl
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}
|