ruby_tree_sitter 1.6.0-x86_64-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,269 @@
|
|
1
|
+
#include "tree_sitter.h"
|
2
|
+
|
3
|
+
extern VALUE mTreeSitter;
|
4
|
+
|
5
|
+
VALUE cTreeCursor;
|
6
|
+
|
7
|
+
DATA_TYPE(TSTreeCursor, tree_cursor)
|
8
|
+
static void tree_cursor_free(void *ptr) {
|
9
|
+
tree_cursor_t *type = (tree_cursor_t *)ptr;
|
10
|
+
ts_tree_cursor_delete(&type->data);
|
11
|
+
xfree(ptr);
|
12
|
+
}
|
13
|
+
DATA_MEMSIZE(tree_cursor)
|
14
|
+
DATA_DECLARE_DATA_TYPE(tree_cursor)
|
15
|
+
DATA_ALLOCATE(tree_cursor)
|
16
|
+
DATA_UNWRAP(tree_cursor)
|
17
|
+
DATA_NEW(cTreeCursor, TSTreeCursor, tree_cursor)
|
18
|
+
DATA_FROM_VALUE(TSTreeCursor, tree_cursor)
|
19
|
+
|
20
|
+
/**
|
21
|
+
* Safely copy a tree cursor.
|
22
|
+
*
|
23
|
+
* @return [TreeCursor]
|
24
|
+
*/
|
25
|
+
static VALUE tree_cursor_copy(VALUE self) {
|
26
|
+
VALUE res = tree_cursor_allocate(cTreeCursor);
|
27
|
+
tree_cursor_t *ptr = unwrap(res);
|
28
|
+
ptr->data = ts_tree_cursor_copy(&SELF);
|
29
|
+
return res;
|
30
|
+
}
|
31
|
+
|
32
|
+
/**
|
33
|
+
* Get the depth of the cursor's current node relative to the original
|
34
|
+
* node that the cursor was constructed with.
|
35
|
+
*
|
36
|
+
* @return [Integer]
|
37
|
+
*/
|
38
|
+
static VALUE tree_cursor_current_depth(VALUE self) {
|
39
|
+
return UINT2NUM(ts_tree_cursor_current_depth(&SELF));
|
40
|
+
}
|
41
|
+
|
42
|
+
/**
|
43
|
+
* Get the index of the cursor's current node out of all of the
|
44
|
+
* descendants of the original node that the cursor was constructed with.
|
45
|
+
*
|
46
|
+
* @return [Integer]
|
47
|
+
*/
|
48
|
+
static VALUE tree_cursor_current_descendant_index(VALUE self) {
|
49
|
+
return UINT2NUM(ts_tree_cursor_current_descendant_index(&SELF));
|
50
|
+
}
|
51
|
+
|
52
|
+
/**
|
53
|
+
* Get the field id of the tree cursor's current node.
|
54
|
+
*
|
55
|
+
* This returns zero if the current node doesn't have a field.
|
56
|
+
*
|
57
|
+
* @see Node#child_by_field_id
|
58
|
+
* @see Node#field_id_for_name
|
59
|
+
*
|
60
|
+
* @return [Integer]
|
61
|
+
*/
|
62
|
+
static VALUE tree_cursor_current_field_id(VALUE self) {
|
63
|
+
return UINT2NUM(ts_tree_cursor_current_field_id(&SELF));
|
64
|
+
}
|
65
|
+
|
66
|
+
/**
|
67
|
+
* Get the field name of the tree cursor's current node.
|
68
|
+
*
|
69
|
+
* This returns +nil+ if the current node doesn't have a field.
|
70
|
+
*
|
71
|
+
* @see Node#child_by_field_name
|
72
|
+
*
|
73
|
+
* @return [String]
|
74
|
+
*/
|
75
|
+
static VALUE tree_cursor_current_field_name(VALUE self) {
|
76
|
+
return safe_str(ts_tree_cursor_current_field_name(&SELF));
|
77
|
+
}
|
78
|
+
|
79
|
+
/**
|
80
|
+
* Get the tree cursor's current node.
|
81
|
+
*
|
82
|
+
* @return [Node]
|
83
|
+
*/
|
84
|
+
static VALUE tree_cursor_current_node(VALUE self) {
|
85
|
+
TSNode node = ts_tree_cursor_current_node(&SELF);
|
86
|
+
return new_node(&node);
|
87
|
+
}
|
88
|
+
|
89
|
+
/**
|
90
|
+
* Move the cursor to the node that is the nth descendant of
|
91
|
+
* the original node that the cursor was constructed with, where
|
92
|
+
* zero represents the original node itself.
|
93
|
+
*
|
94
|
+
* @return [nil]
|
95
|
+
*/
|
96
|
+
static VALUE tree_cursor_goto_descendant(VALUE self, VALUE descendant_idx) {
|
97
|
+
uint32_t idx = NUM2UINT(descendant_idx);
|
98
|
+
ts_tree_cursor_goto_descendant(&SELF, idx);
|
99
|
+
return Qnil;
|
100
|
+
}
|
101
|
+
|
102
|
+
/**
|
103
|
+
* Move the cursor to the first child of its current node.
|
104
|
+
*
|
105
|
+
* This returns +true+ if the cursor successfully moved, and returns +false+
|
106
|
+
* if there were no children.
|
107
|
+
*
|
108
|
+
* @return [Boolean]
|
109
|
+
*/
|
110
|
+
static VALUE tree_cursor_goto_first_child(VALUE self) {
|
111
|
+
return ts_tree_cursor_goto_first_child(&SELF) ? Qtrue : Qfalse;
|
112
|
+
}
|
113
|
+
|
114
|
+
/**
|
115
|
+
* Move the cursor to the first child of its current node that extends beyond
|
116
|
+
* the given byte offset.
|
117
|
+
*
|
118
|
+
* This returns the index of the child node if one was found, and returns -1
|
119
|
+
* if no such child was found.
|
120
|
+
*
|
121
|
+
* @return [Integer]
|
122
|
+
*/
|
123
|
+
static VALUE tree_cursor_goto_first_child_for_byte(VALUE self, VALUE byte) {
|
124
|
+
return LL2NUM(
|
125
|
+
ts_tree_cursor_goto_first_child_for_byte(&SELF, NUM2UINT(byte)));
|
126
|
+
}
|
127
|
+
|
128
|
+
/**
|
129
|
+
* Move the cursor to the first child of its current node that extends beyond
|
130
|
+
* the given or point.
|
131
|
+
*
|
132
|
+
* This returns the index of the child node if one was found, and returns -1
|
133
|
+
* if no such child was found.
|
134
|
+
*
|
135
|
+
* @return [Integer]
|
136
|
+
*/
|
137
|
+
static VALUE tree_cursor_goto_first_child_for_point(VALUE self, VALUE point) {
|
138
|
+
return LL2NUM(
|
139
|
+
ts_tree_cursor_goto_first_child_for_point(&SELF, value_to_point(point)));
|
140
|
+
}
|
141
|
+
|
142
|
+
/**
|
143
|
+
* Move the cursor to the last child of its current node.
|
144
|
+
*
|
145
|
+
* This returns +true+ if the cursor successfully moved, and returns +false+ if
|
146
|
+
* there were no children.
|
147
|
+
*
|
148
|
+
* Note that this function may be slower than {#goto_first_child}
|
149
|
+
* because it needs to iterate through all the children to compute the child's
|
150
|
+
* position.
|
151
|
+
*/
|
152
|
+
static VALUE tree_cursor_goto_last_child(VALUE self) {
|
153
|
+
return ts_tree_cursor_goto_last_child(&SELF) ? Qtrue : Qfalse;
|
154
|
+
}
|
155
|
+
|
156
|
+
/**
|
157
|
+
* Move the cursor to the next sibling of its current node.
|
158
|
+
*
|
159
|
+
* This returns +true+ if the cursor successfully moved, and returns +false+
|
160
|
+
* if there was no next sibling node.
|
161
|
+
*
|
162
|
+
* @return Boolean
|
163
|
+
*/
|
164
|
+
static VALUE tree_cursor_goto_next_sibling(VALUE self) {
|
165
|
+
return ts_tree_cursor_goto_next_sibling(&SELF) ? Qtrue : Qfalse;
|
166
|
+
}
|
167
|
+
|
168
|
+
/**
|
169
|
+
* Move the cursor to the parent of its current node.
|
170
|
+
*
|
171
|
+
* This returns +true+ if the cursor successfully moved, and returns +false+
|
172
|
+
* if there was no parent node (the cursor was already on the root node).
|
173
|
+
*
|
174
|
+
* @return [Boolean]
|
175
|
+
*/
|
176
|
+
static VALUE tree_cursor_goto_parent(VALUE self) {
|
177
|
+
return ts_tree_cursor_goto_parent(&SELF) ? Qtrue : Qfalse;
|
178
|
+
}
|
179
|
+
|
180
|
+
/**
|
181
|
+
* Move the cursor to the previous sibling of its current node.
|
182
|
+
*
|
183
|
+
* This returns +true+ if the cursor successfully moved, and returns +false+ if
|
184
|
+
* there was no previous sibling node.
|
185
|
+
*
|
186
|
+
* Note, that this function may be slower than
|
187
|
+
* {#goto_next_sibling} due to how node positions are stored. In
|
188
|
+
* the worst case, this will need to iterate through all the children upto the
|
189
|
+
* previous sibling node to recalculate its position.
|
190
|
+
*
|
191
|
+
* @return [Boolean]
|
192
|
+
*/
|
193
|
+
static VALUE tree_cursor_goto_previous_sibling(VALUE self) {
|
194
|
+
return ts_tree_cursor_goto_previous_sibling(&SELF) ? Qtrue : Qfalse;
|
195
|
+
}
|
196
|
+
|
197
|
+
/**
|
198
|
+
* Create a new tree cursor starting from the given node.
|
199
|
+
*
|
200
|
+
* A tree cursor allows you to walk a syntax tree more efficiently than is
|
201
|
+
* possible using the {Node} functions. It is a mutable object that is always
|
202
|
+
* on a certain syntax node, and can be moved imperatively to different nodes.
|
203
|
+
*
|
204
|
+
* @return [TreeCursor]
|
205
|
+
*/
|
206
|
+
static VALUE tree_cursor_initialize(VALUE self, VALUE node) {
|
207
|
+
TSNode n = value_to_node(node);
|
208
|
+
tree_cursor_t *ptr = unwrap(self);
|
209
|
+
ptr->data = ts_tree_cursor_new(n);
|
210
|
+
return self;
|
211
|
+
}
|
212
|
+
|
213
|
+
/**
|
214
|
+
* Re-initialize a tree cursor to start at a different node.
|
215
|
+
*
|
216
|
+
* @return [nil]
|
217
|
+
*/
|
218
|
+
static VALUE tree_cursor_reset(VALUE self, VALUE node) {
|
219
|
+
ts_tree_cursor_reset(&SELF, value_to_node(node));
|
220
|
+
return Qnil;
|
221
|
+
}
|
222
|
+
|
223
|
+
/**
|
224
|
+
* Re-initialize a tree cursor to the same position as another cursor.
|
225
|
+
*
|
226
|
+
* Unlike {#reset}, this will not lose parent information and allows reusing
|
227
|
+
* already created cursors.
|
228
|
+
*
|
229
|
+
* @return [nil]
|
230
|
+
*/
|
231
|
+
VALUE tree_cursor_reset_to(VALUE self, VALUE src) {
|
232
|
+
ts_tree_cursor_reset_to(&SELF, &unwrap(src)->data);
|
233
|
+
return Qnil;
|
234
|
+
}
|
235
|
+
|
236
|
+
void init_tree_cursor(void) {
|
237
|
+
cTreeCursor = rb_define_class_under(mTreeSitter, "TreeCursor", rb_cObject);
|
238
|
+
|
239
|
+
rb_define_alloc_func(cTreeCursor, tree_cursor_allocate);
|
240
|
+
|
241
|
+
/* Class methods */
|
242
|
+
rb_define_method(cTreeCursor, "copy", tree_cursor_copy, 0);
|
243
|
+
rb_define_method(cTreeCursor, "current_depth", tree_cursor_current_depth, 0);
|
244
|
+
rb_define_method(cTreeCursor, "current_descendant_index",
|
245
|
+
tree_cursor_current_descendant_index, 0);
|
246
|
+
rb_define_method(cTreeCursor, "current_field_id",
|
247
|
+
tree_cursor_current_field_id, 0);
|
248
|
+
rb_define_method(cTreeCursor, "current_field_name",
|
249
|
+
tree_cursor_current_field_name, 0);
|
250
|
+
rb_define_method(cTreeCursor, "current_node", tree_cursor_current_node, 0);
|
251
|
+
rb_define_method(cTreeCursor, "goto_descendant", tree_cursor_goto_descendant,
|
252
|
+
1);
|
253
|
+
rb_define_method(cTreeCursor, "goto_first_child",
|
254
|
+
tree_cursor_goto_first_child, 0);
|
255
|
+
rb_define_method(cTreeCursor, "goto_first_child_for_byte",
|
256
|
+
tree_cursor_goto_first_child_for_byte, 1);
|
257
|
+
rb_define_method(cTreeCursor, "goto_first_child_for_point",
|
258
|
+
tree_cursor_goto_first_child_for_point, 1);
|
259
|
+
rb_define_method(cTreeCursor, "goto_last_child", tree_cursor_goto_last_child,
|
260
|
+
0);
|
261
|
+
rb_define_method(cTreeCursor, "goto_next_sibling",
|
262
|
+
tree_cursor_goto_next_sibling, 0);
|
263
|
+
rb_define_method(cTreeCursor, "goto_parent", tree_cursor_goto_parent, 0);
|
264
|
+
rb_define_method(cTreeCursor, "goto_previous_sibling",
|
265
|
+
tree_cursor_goto_previous_sibling, 0);
|
266
|
+
rb_define_method(cTreeCursor, "initialize", tree_cursor_initialize, 1);
|
267
|
+
rb_define_method(cTreeCursor, "reset", tree_cursor_reset, 1);
|
268
|
+
rb_define_method(cTreeCursor, "reset_to", tree_cursor_reset_to, 1);
|
269
|
+
}
|
@@ -0,0 +1,44 @@
|
|
1
|
+
#include "tree_sitter.h"
|
2
|
+
|
3
|
+
VALUE mTreeSitter;
|
4
|
+
|
5
|
+
void Init_tree_sitter() {
|
6
|
+
mTreeSitter = rb_define_module("TreeSitter");
|
7
|
+
|
8
|
+
/**
|
9
|
+
* The latest ABI version that is supported by the current version of the
|
10
|
+
* library. When Languages are generated by the Tree-sitter CLI, they are
|
11
|
+
* assigned an ABI version number that corresponds to the current CLI version.
|
12
|
+
* The Tree-sitter library is generally backwards-compatible with languages
|
13
|
+
* generated using older CLI versions, but is not forwards-compatible.
|
14
|
+
*/
|
15
|
+
rb_define_const(mTreeSitter, "LANGUAGE_VERSION",
|
16
|
+
INT2NUM(TREE_SITTER_LANGUAGE_VERSION));
|
17
|
+
|
18
|
+
/**
|
19
|
+
* The earliest ABI version that is supported by the current version of the
|
20
|
+
* library.
|
21
|
+
*/
|
22
|
+
rb_define_const(mTreeSitter, "MIN_COMPATIBLE_LANGUAGE_VERSION",
|
23
|
+
TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION);
|
24
|
+
|
25
|
+
init_encoding();
|
26
|
+
init_input();
|
27
|
+
init_input_edit();
|
28
|
+
init_language();
|
29
|
+
init_logger();
|
30
|
+
init_node();
|
31
|
+
init_parser();
|
32
|
+
init_point();
|
33
|
+
init_quantifier();
|
34
|
+
init_query();
|
35
|
+
init_query_capture();
|
36
|
+
init_query_cursor();
|
37
|
+
init_query_error();
|
38
|
+
init_query_match();
|
39
|
+
init_query_predicate_step();
|
40
|
+
init_range();
|
41
|
+
init_symbol_type();
|
42
|
+
init_tree();
|
43
|
+
init_tree_cursor();
|
44
|
+
}
|
@@ -0,0 +1,107 @@
|
|
1
|
+
#ifndef _RB_TREE_SITTER_H
|
2
|
+
#define _RB_TREE_SITTER_H
|
3
|
+
|
4
|
+
#include "macros.h"
|
5
|
+
#include <dlfcn.h>
|
6
|
+
#include <fcntl.h>
|
7
|
+
#include <ruby.h>
|
8
|
+
#include <stdio.h>
|
9
|
+
#include <string.h>
|
10
|
+
#include <tree_sitter/api.h>
|
11
|
+
|
12
|
+
static inline VALUE safe_str(const char *str) {
|
13
|
+
if (str == NULL) {
|
14
|
+
return Qnil;
|
15
|
+
} else {
|
16
|
+
return rb_utf8_str_new_cstr(str);
|
17
|
+
}
|
18
|
+
}
|
19
|
+
|
20
|
+
static inline VALUE safe_str2(const char *str, uint32_t len) {
|
21
|
+
if (str == NULL) {
|
22
|
+
return Qnil;
|
23
|
+
} else if (len == 0) {
|
24
|
+
return rb_utf8_str_new_cstr("");
|
25
|
+
} else {
|
26
|
+
return rb_utf8_str_new(str, len);
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
static inline VALUE safe_symbol(const char *str) {
|
31
|
+
if (str == NULL) {
|
32
|
+
return Qnil;
|
33
|
+
} else {
|
34
|
+
return ID2SYM(rb_intern(str));
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
// VALUE to TS* converters
|
39
|
+
|
40
|
+
TSInput value_to_input(VALUE);
|
41
|
+
TSInputEdit value_to_input_edit(VALUE);
|
42
|
+
TSInputEncoding value_to_encoding(VALUE);
|
43
|
+
TSLanguage *value_to_language(VALUE);
|
44
|
+
TSLogger value_to_logger(VALUE);
|
45
|
+
TSNode value_to_node(VALUE);
|
46
|
+
TSPoint value_to_point(VALUE);
|
47
|
+
TSQuantifier value_to_quantifier(VALUE);
|
48
|
+
TSQuery *value_to_query(VALUE);
|
49
|
+
TSQueryCursor *value_to_query_cursor(VALUE);
|
50
|
+
TSQueryError value_to_query_error(VALUE);
|
51
|
+
TSQueryMatch value_to_query_match(VALUE);
|
52
|
+
TSQueryPredicateStep value_to_query_predicate_step(VALUE);
|
53
|
+
TSQueryPredicateStepType value_to_query_predicate_step_type(VALUE);
|
54
|
+
TSRange value_to_range(VALUE);
|
55
|
+
TSSymbolType value_to_symbol_type(VALUE);
|
56
|
+
TSTree *value_to_tree(VALUE);
|
57
|
+
TSTreeCursor value_to_tree_cursor(VALUE);
|
58
|
+
|
59
|
+
// TS* to VALUE converters
|
60
|
+
VALUE new_input(const TSInput *);
|
61
|
+
VALUE new_language(const TSLanguage *);
|
62
|
+
VALUE new_logger(const TSLogger *);
|
63
|
+
VALUE new_logger_by_val(TSLogger);
|
64
|
+
VALUE new_node(const TSNode *);
|
65
|
+
VALUE new_node_by_val(TSNode);
|
66
|
+
VALUE new_point(const TSPoint *);
|
67
|
+
VALUE new_point_by_val(TSPoint);
|
68
|
+
VALUE new_query_capture(const TSQueryCapture *);
|
69
|
+
VALUE new_query_match(const TSQueryMatch *);
|
70
|
+
VALUE new_query_predicate_step(const TSQueryPredicateStep *);
|
71
|
+
VALUE new_range(const TSRange *);
|
72
|
+
VALUE new_symbol_type(TSSymbolType);
|
73
|
+
VALUE new_tree(TSTree *);
|
74
|
+
|
75
|
+
// All init_* functions are called from Init_tree_sitter
|
76
|
+
void init_encoding(void);
|
77
|
+
void init_input(void);
|
78
|
+
void init_input_edit(void);
|
79
|
+
void init_language(void);
|
80
|
+
void init_logger(void);
|
81
|
+
void init_node(void);
|
82
|
+
void init_parser(void);
|
83
|
+
void init_point(void);
|
84
|
+
void init_quantifier(void);
|
85
|
+
void init_query(void);
|
86
|
+
void init_query_capture(void);
|
87
|
+
void init_query_cursor(void);
|
88
|
+
void init_query_error(void);
|
89
|
+
void init_query_match(void);
|
90
|
+
void init_query_predicate_step(void);
|
91
|
+
void init_range(void);
|
92
|
+
void init_symbol_type(void);
|
93
|
+
void init_tree(void);
|
94
|
+
void init_tree_cursor(void);
|
95
|
+
|
96
|
+
// Other helpers
|
97
|
+
const char *quantifier_str(TSQuantifier);
|
98
|
+
const char *query_error_str(TSQueryError);
|
99
|
+
|
100
|
+
// TSTree reference counting
|
101
|
+
int tree_rc_free(const TSTree *);
|
102
|
+
void tree_rc_new(const TSTree *);
|
103
|
+
|
104
|
+
// This is a special entry-point for the extension
|
105
|
+
void Init_tree_sitter(void);
|
106
|
+
|
107
|
+
#endif
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# splits an array like [rust](https://doc.rust-lang.org/std/primitive.slice.html#method.split)
|
4
|
+
def array_split_like_rust(array, &block)
|
5
|
+
return enum_for(__method__, array) if !block_given?
|
6
|
+
|
7
|
+
return [] if array.empty?
|
8
|
+
|
9
|
+
result = []
|
10
|
+
current_slice = []
|
11
|
+
|
12
|
+
array.each do |element|
|
13
|
+
if yield(element)
|
14
|
+
result << current_slice
|
15
|
+
current_slice = []
|
16
|
+
else
|
17
|
+
current_slice << element
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
result << current_slice
|
22
|
+
result
|
23
|
+
end
|
@@ -0,0 +1,167 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TreeSitter
|
4
|
+
# A colon-separated list of paths pointing to directories that can contain parsers.
|
5
|
+
# Order matters.
|
6
|
+
# Takes precedence over default lookup paths.
|
7
|
+
ENV_PARSERS =
|
8
|
+
ENV['TREE_SITTER_PARSERS']
|
9
|
+
&.split(':')
|
10
|
+
&.map { |v| Pathname(v) }
|
11
|
+
.freeze
|
12
|
+
|
13
|
+
# The default paths we use to lookup parsers.
|
14
|
+
# Order matters.
|
15
|
+
LIBDIRS = [
|
16
|
+
'.vendor/parsers',
|
17
|
+
'.vendor/tree-sitter-parsers',
|
18
|
+
'vendor/parsers',
|
19
|
+
'vendor/tree-sitter-parsers',
|
20
|
+
'parsers',
|
21
|
+
'tree-sitter-parsers',
|
22
|
+
'.',
|
23
|
+
'/opt/local/lib',
|
24
|
+
'/opt/lib',
|
25
|
+
'/usr/local/lib',
|
26
|
+
'/usr/lib',
|
27
|
+
].map { |p| Pathname(p) }.freeze
|
28
|
+
|
29
|
+
# Mixins.
|
30
|
+
module Mixins
|
31
|
+
# Language Mixin.
|
32
|
+
module Language
|
33
|
+
# Load a language from configuration or default lookup paths.
|
34
|
+
#
|
35
|
+
# @example Load java from default paths
|
36
|
+
# # This will look for:
|
37
|
+
# #
|
38
|
+
# # .vendor/tree-sitter-parsers/(java/)?(libtree-sitter-)?java.{ext}
|
39
|
+
# # .vendor/parsers/(java/)?(libtree-sitter-)?java.{ext}
|
40
|
+
# # vendor/tree-sitter-parsers/(java/)?(libtree-sitter-)?java.{ext}
|
41
|
+
# # vendor/parsers/(java/)?(libtree-sitter-)?java.{ext}
|
42
|
+
# # parsers/(java/)?(libtree-sitter-)?java.{ext}
|
43
|
+
# # tree-sitter-parsers/(java/)?(libtree-sitter-)?java.{ext}
|
44
|
+
# # /opt/local/lib/(java/)?(libtree-sitter-)?java.{ext}
|
45
|
+
# # /opt/lib/(java/)?(libtree-sitter-)?java.{ext}
|
46
|
+
# # /usr/local/lib/(java/)?(libtree-sitter-)?java.{ext}
|
47
|
+
# # /usr/lib/(java/)?(libtree-sitter-)?java.{ext}
|
48
|
+
# #
|
49
|
+
# java = TreeSitter.language('java')
|
50
|
+
#
|
51
|
+
# @example (TreeStand) Load java from a configured path
|
52
|
+
# # This will look for:
|
53
|
+
# #
|
54
|
+
# # /my/path/(java/)?(libtree-sitter-)?java.{ext}
|
55
|
+
# #
|
56
|
+
# TreeStand.config.parser_path = '/my/path'
|
57
|
+
# java = TreeStand::Parser.language('java')
|
58
|
+
#
|
59
|
+
# @example (TreeStand) Load java from environment variables
|
60
|
+
# # This will look for:
|
61
|
+
# #
|
62
|
+
# # /my/forced/env/path/(java/)?(libtree-sitter-)?java.{ext}
|
63
|
+
# # /my/path/(java/)?(libtree-sitter-)?java.{ext}
|
64
|
+
# #
|
65
|
+
# # … and the same works for the default paths if `TreeStand.config.parser_path`
|
66
|
+
# # was `nil`
|
67
|
+
# ENV['TREE_SITTER_PARSERS'] = '/my/forced/env/path'
|
68
|
+
# TreeStand.config.parser_path = '/my/path'
|
69
|
+
# java = TreeStand::Parser.language('java')
|
70
|
+
#
|
71
|
+
# @note the name is case sensitive, but library lookup is not: if your parser is defined as `COBOL`,
|
72
|
+
# then you have to call `language('COBOL')`, but the parser can be `cobol.so/COBOL.so/…`.
|
73
|
+
#
|
74
|
+
# @param name [String] the name of the parser.
|
75
|
+
# This name is used to load the symbol from the compiled parser, replacing `-` with `_`.
|
76
|
+
#
|
77
|
+
# @return [TreeSitter:language] a language object to use in your parsers.
|
78
|
+
#
|
79
|
+
# @raise [RuntimeError] if the parser was not found.
|
80
|
+
#
|
81
|
+
# @see search_for_lib
|
82
|
+
def language(name)
|
83
|
+
lib = search_for_lib(name)
|
84
|
+
|
85
|
+
if lib.nil?
|
86
|
+
raise <<~MSG.chomp
|
87
|
+
Failed to load a parser for #{name}.
|
88
|
+
|
89
|
+
#{search_lib_message}
|
90
|
+
MSG
|
91
|
+
end
|
92
|
+
|
93
|
+
# We know that the bindings will accept `lib`, but I don't know how to tell sorbet
|
94
|
+
# the types in ext/tree_sitter where `load` is defined.
|
95
|
+
TreeSitter::Language.load(name.tr('-', '_'), lib)
|
96
|
+
end
|
97
|
+
|
98
|
+
# The platform-specific extension of the parser.
|
99
|
+
# @return [String] `dylib` or `so` for mac or linux.
|
100
|
+
def ext
|
101
|
+
case Gem::Platform.local.os
|
102
|
+
in /darwin/ then 'dylib'
|
103
|
+
else 'so'
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
private
|
108
|
+
|
109
|
+
# The library directories we need to look into.
|
110
|
+
#
|
111
|
+
# @return [Array<Pathname>] the list of candidate places to use when searching for parsers.
|
112
|
+
#
|
113
|
+
# @see ENV_PARSERS
|
114
|
+
# @see LIBDIRS
|
115
|
+
def lib_dirs = [*TreeSitter::ENV_PARSERS, *TreeSitter::LIBDIRS]
|
116
|
+
|
117
|
+
# Lookup a parser by name.
|
118
|
+
#
|
119
|
+
# Precedence:
|
120
|
+
# 1. `Env['TREE_SITTER_PARSERS]`.
|
121
|
+
# 2. {TreeStand::Config#parser_path} if using {TreeStand}.
|
122
|
+
# 3. {LIBDIRS}.
|
123
|
+
#
|
124
|
+
# If a {TreeStand::Config#parser_path} is `nil`, {LIBDIRS} is used.
|
125
|
+
# If a {TreeStand::Config#parser_path} is a {::Pathname}, {LIBDIRS} is ignored.
|
126
|
+
def search_for_lib(name)
|
127
|
+
files =
|
128
|
+
[name, name.upcase, name.downcase]
|
129
|
+
.uniq
|
130
|
+
.flat_map do |n|
|
131
|
+
base = "#{n}.#{ext}"
|
132
|
+
[base, "tree-sitter-#{base}", "libtree-sitter-#{base}"]
|
133
|
+
end
|
134
|
+
|
135
|
+
lib_dirs
|
136
|
+
.product(files)
|
137
|
+
.find do |dir, so|
|
138
|
+
path = dir / so
|
139
|
+
path = dir / name / so if !path.exist?
|
140
|
+
break path.expand_path if path.exist?
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
# Generates a string message on where parser lookup happens.
|
145
|
+
#
|
146
|
+
# @return [String] A pretty message.
|
147
|
+
def search_lib_message
|
148
|
+
indent = 2
|
149
|
+
pretty = ->(arr) {
|
150
|
+
if arr
|
151
|
+
arr
|
152
|
+
.compact
|
153
|
+
.map { |v| "#{' ' * indent}#{v.expand_path}" }
|
154
|
+
.join("\n")
|
155
|
+
end
|
156
|
+
}
|
157
|
+
<<~MSG.chomp
|
158
|
+
From ENV['TREE_SITTER_PARSERS']:
|
159
|
+
#{pretty.call(ENV_PARSERS)}
|
160
|
+
|
161
|
+
From Defaults:
|
162
|
+
#{pretty.call(lib_dirs)}
|
163
|
+
MSG
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|