ruby_tree_sitter 1.2.0-x86_64-linux → 1.3.0-x86_64-linux
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/tree_sitter/query.c +7 -0
- data/ext/tree_sitter/query_cursor.c +18 -2
- data/lib/tree_sitter/helpers.rb +23 -0
- data/lib/tree_sitter/query.rb +191 -0
- data/lib/tree_sitter/query_captures.rb +28 -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 +25 -0
- data/lib/tree_sitter/query_predicate.rb +14 -0
- data/lib/tree_sitter/text_predicate_capture.rb +37 -0
- data/lib/tree_sitter/tree_sitter.so +0 -0
- data/lib/tree_sitter/version.rb +1 -1
- data/lib/tree_sitter.rb +8 -1
- data/lib/tree_stand/parser.rb +2 -2
- metadata +10 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a0f7c51b289e769ad5701be586b28d61f41f0979ee6fd3c08f87481ae307f146
|
4
|
+
data.tar.gz: 988052e5b5b5c41e9a9d974398c6c6cae401f2068a2ad4013d80198f3437c029
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9ef62c5ea3bd4451b03b43e6efc2c3501191ffcd9ea96dfe12d2e66b249d1f16f58e82d6127d833a6c8105e3f910dda2ba898a138d5e6d2756615bf69fcb2e05
|
7
|
+
data.tar.gz: 5bd46cc66e845c9091005a5eadeccb3db2984e0bbc5bf6d12e9fc4e3fd126f9ab6f1d37970fbe6760eee096ec2c011d4d328d5610a9e873ed313df3842caceb3
|
data/ext/tree_sitter/query.c
CHANGED
@@ -140,6 +140,13 @@ static VALUE query_initialize(VALUE self, VALUE language, VALUE source) {
|
|
140
140
|
SELF = res;
|
141
141
|
}
|
142
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
|
+
|
143
150
|
return self;
|
144
151
|
}
|
145
152
|
|
@@ -49,7 +49,7 @@ DATA_FROM_VALUE(TSQueryCursor *, query_cursor)
|
|
49
49
|
*
|
50
50
|
* @return [QueryCursor]
|
51
51
|
*/
|
52
|
-
static VALUE
|
52
|
+
static VALUE query_cursor_exec_static(VALUE self, VALUE query, VALUE node) {
|
53
53
|
VALUE res = query_cursor_allocate(cQueryCursor);
|
54
54
|
query_cursor_t *query_cursor = unwrap(res);
|
55
55
|
ts_query_cursor_exec(query_cursor->data, value_to_query(query),
|
@@ -57,6 +57,21 @@ static VALUE query_cursor_exec(VALUE self, VALUE query, VALUE node) {
|
|
57
57
|
return res;
|
58
58
|
}
|
59
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
|
+
|
60
75
|
/**
|
61
76
|
* Manage the maximum number of in-progress matches allowed by this query
|
62
77
|
* cursor.
|
@@ -190,13 +205,14 @@ void init_query_cursor(void) {
|
|
190
205
|
rb_define_alloc_func(cQueryCursor, query_cursor_allocate);
|
191
206
|
|
192
207
|
/* Module methods */
|
193
|
-
rb_define_module_function(cQueryCursor, "exec",
|
208
|
+
rb_define_module_function(cQueryCursor, "exec", query_cursor_exec_static, 2);
|
194
209
|
|
195
210
|
/* Class methods */
|
196
211
|
// Accessors
|
197
212
|
DECLARE_ACCESSOR(cQueryCursor, query_cursor, match_limit)
|
198
213
|
|
199
214
|
// Other
|
215
|
+
rb_define_method(cQueryCursor, "exec", query_cursor_exec, 2);
|
200
216
|
rb_define_method(cQueryCursor, "exceed_match_limit?",
|
201
217
|
query_cursor_did_exceed_match_limit, 0);
|
202
218
|
rb_define_method(cQueryCursor, "match_limit", query_cursor_get_match_limit,
|
@@ -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,191 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'helpers'
|
4
|
+
|
5
|
+
module TreeSitter
|
6
|
+
# Query is a wrapper around a tree-sitter query.
|
7
|
+
class Query
|
8
|
+
attr_reader :capture_names
|
9
|
+
attr_reader :capture_quantifiers
|
10
|
+
attr_reader :text_predicates
|
11
|
+
attr_reader :property_predicates
|
12
|
+
attr_reader :property_settings
|
13
|
+
attr_reader :general_predicates
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
# Called from query.c on initialize.
|
18
|
+
#
|
19
|
+
# Prepares all the predicates so we could process them in places like
|
20
|
+
# {QueryMatch#satisfies_text_predicate?}.
|
21
|
+
#
|
22
|
+
# This is translation from the [rust bindings](https://github.com/tree-sitter/tree-sitter/blob/e553578696fe86071846ed612ee476d0167369c1/lib/binding_rust/lib.rs#L1860)
|
23
|
+
# Because it's a direct translation, it's way too long and we need to shut up rubocop.
|
24
|
+
# TODO: refactor + simplify when stable.
|
25
|
+
def process(source) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
|
26
|
+
string_count = self.string_count
|
27
|
+
capture_count = self.capture_count
|
28
|
+
pattern_count = self.pattern_count
|
29
|
+
|
30
|
+
# Build a vector of strings to store the capture names.
|
31
|
+
capture_names = capture_count.times.map { |i| capture_name_for_id(i) }
|
32
|
+
|
33
|
+
# Build a vector to store capture qunatifiers.
|
34
|
+
capture_quantifiers =
|
35
|
+
pattern_count.times.map do |i|
|
36
|
+
capture_count.times.map do |j|
|
37
|
+
capture_quantifier_for_id(i, j)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Build a vector of strings to represent literal values used in predicates.
|
42
|
+
string_values = string_count.times.map { |i| string_value_for_id(i) }
|
43
|
+
|
44
|
+
# Build a vector of predicates for each pattern.
|
45
|
+
pattern_count.times do |i| # rubocop:disable Metrics/BlockLength
|
46
|
+
predicate_steps = predicates_for_pattern(i)
|
47
|
+
byte_offset = start_byte_for_pattern(i)
|
48
|
+
row =
|
49
|
+
source.chars.map.with_index
|
50
|
+
.take_while { |_, i| i < byte_offset } # rubocop:disable Lint/ShadowingOuterLocalVariable
|
51
|
+
.filter { |c, _| c == "\n" }
|
52
|
+
.size
|
53
|
+
text_predicates = []
|
54
|
+
property_predicates = []
|
55
|
+
property_settings = []
|
56
|
+
general_predicates = []
|
57
|
+
|
58
|
+
array_split_like_rust(predicate_steps) { |s| s.type == QueryPredicateStep::DONE } # rubocop:disable Metrics/BlockLength
|
59
|
+
.each do |p|
|
60
|
+
next if p.empty?
|
61
|
+
|
62
|
+
if p[0] == QueryPredicateStep::STRING
|
63
|
+
cap = capture_names[p[0].value_id]
|
64
|
+
raise ArgumentError, <<~MSG.chomp
|
65
|
+
L#{row}: Expected predicate to start with a function name. Got @#{cap}.
|
66
|
+
MSG
|
67
|
+
end
|
68
|
+
|
69
|
+
# Build a predicate for each of the known predicate function names.
|
70
|
+
operator_name = string_values[p[0].value_id]
|
71
|
+
|
72
|
+
case operator_name
|
73
|
+
in 'any-eq?' | 'any-not-eq?' | 'eq?' | 'not-eq?'
|
74
|
+
if p.size != 3
|
75
|
+
raise ArgumentError, <<~MSG.chomp
|
76
|
+
L#{row}: Wrong number of arguments to ##{operator_name} predicate. Expected 2, got #{p.size - 1}.
|
77
|
+
MSG
|
78
|
+
end
|
79
|
+
|
80
|
+
if p[1].type != QueryPredicateStep::CAPTURE
|
81
|
+
lit = string_values[p[1].value_id]
|
82
|
+
raise ArgumentError, <<~MSG.chomp
|
83
|
+
L#{row}: First argument to ##{operator_name} predicate must be a capture name. Got literal "#{lit}".
|
84
|
+
MSG
|
85
|
+
end
|
86
|
+
|
87
|
+
is_positive = %w[eq? any-eq?].include?(operator_name)
|
88
|
+
match_all = %w[eq? not-eq?].include?(operator_name)
|
89
|
+
# NOTE: in the rust impl, match_all can hit an unreachable! but I am simplifying
|
90
|
+
# for readability. Same applies for the other `in` branches.
|
91
|
+
text_predicates <<
|
92
|
+
if p[2].type == QueryPredicateStep::CAPTURE
|
93
|
+
TextPredicateCapture.eq_capture(p[1].value_id, p[2].value_id, is_positive, match_all)
|
94
|
+
else
|
95
|
+
TextPredicateCapture.eq_string(p[1].value_id, string_values[p[2].value_id], is_positive, match_all)
|
96
|
+
end
|
97
|
+
|
98
|
+
in 'match?' | 'not-match?' | 'any-match?' | 'any-not-match?'
|
99
|
+
if p.size != 3
|
100
|
+
raise ArgumentError, <<~MSG.chomp
|
101
|
+
L#{row}: Wrong number of arguments to ##{operator_name} predicate. Expected 2, got #{p.size - 1}.
|
102
|
+
MSG
|
103
|
+
end
|
104
|
+
|
105
|
+
if p[1].type != QueryPredicateStep::CAPTURE
|
106
|
+
lit = string_values[p[1].value_id]
|
107
|
+
raise ArgumentError, <<~MSG.chomp
|
108
|
+
L#{row}: First argument to ##{operator_name} predicate must be a capture name. Got literal "#{lit}".
|
109
|
+
MSG
|
110
|
+
end
|
111
|
+
|
112
|
+
if p[2].type == QueryPredicateStep::CAPTURE
|
113
|
+
cap = capture_names[p[2].value_id]
|
114
|
+
raise ArgumentError, <<~MSG.chomp
|
115
|
+
L#{row}: First argument to ##{operator_name} predicate must be a literal. Got capture @#{cap}".
|
116
|
+
MSG
|
117
|
+
end
|
118
|
+
|
119
|
+
is_positive = %w[match? any-match?].include?(operator_name)
|
120
|
+
match_all = %w[match? not-match?].include?(operator_name)
|
121
|
+
regex = /#{string_values[p[2].value_id]}/
|
122
|
+
|
123
|
+
text_predicates << TextPredicateCapture.match_string(p[1].value_id, regex, is_positive, match_all)
|
124
|
+
|
125
|
+
in 'set!'
|
126
|
+
property_settings << 'todo!'
|
127
|
+
|
128
|
+
in 'is?' | 'is-not?'
|
129
|
+
property_predicates << 'todo!'
|
130
|
+
|
131
|
+
in 'any-of?' | 'not-any-of?'
|
132
|
+
if p.size < 2
|
133
|
+
raise ArgumentError, <<~MSG.chomp
|
134
|
+
L#{row}: Wrong number of arguments to ##{operator_name} predicate. Expected at least 1, got #{p.size - 1}.
|
135
|
+
MSG
|
136
|
+
end
|
137
|
+
|
138
|
+
if p[1].type != QueryPredicateStep::CAPTURE
|
139
|
+
lit = string_values[p[1].value_id]
|
140
|
+
raise ArgumentError, <<~MSG.chomp
|
141
|
+
L#{row}: First argument to ##{operator_name} predicate must be a capture name. Got literal "#{lit}".
|
142
|
+
MSG
|
143
|
+
end
|
144
|
+
|
145
|
+
is_positive = operator_name == 'any_of'
|
146
|
+
values = []
|
147
|
+
|
148
|
+
p[2..].each do |arg|
|
149
|
+
if arg.type == QueryPredicateStep::CAPTURE
|
150
|
+
lit = string_values[arg.value_id]
|
151
|
+
raise ArgumentError, <<~MSG.chomp
|
152
|
+
L#{row}: First argument to ##{operator_name} predicate must be a capture name. Got literal "#{lit}".
|
153
|
+
MSG
|
154
|
+
end
|
155
|
+
values << string_values[arg.value_id]
|
156
|
+
end
|
157
|
+
|
158
|
+
# TODO: is the map to to_s necessary in ruby?
|
159
|
+
text_predicates <<
|
160
|
+
TextPredicateCapture.any_string(p[1].value_id, values.map(&:to_s), is_positive, match_all)
|
161
|
+
else
|
162
|
+
general_predicates <<
|
163
|
+
QueryPredicate.new(
|
164
|
+
operator_name,
|
165
|
+
p[1..].map do |a|
|
166
|
+
if a.type == QueryPredicateStep::CAPTURE
|
167
|
+
{ capture: a.value_id }
|
168
|
+
else
|
169
|
+
{ string: string_values[a.value_id] }
|
170
|
+
end
|
171
|
+
end,
|
172
|
+
)
|
173
|
+
end
|
174
|
+
|
175
|
+
@text_predicates << text_predicates
|
176
|
+
@property_predicates << property_predicates
|
177
|
+
@property_settings << property_settings
|
178
|
+
@general_predicates << general_predicates
|
179
|
+
end
|
180
|
+
|
181
|
+
@capture_names = capture_names
|
182
|
+
@capture_quantifiers = capture_quantifiers
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
# TODO
|
187
|
+
def parse_property
|
188
|
+
# todo
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TreeSitter
|
4
|
+
# A sequence of {TreeSitter::QueryCapture} associated with a given {TreeSitter::QueryCursor}.
|
5
|
+
class QueryCaptures
|
6
|
+
def initialize(cursor, query, src)
|
7
|
+
@cursor = cursor
|
8
|
+
@query = query
|
9
|
+
@src = src
|
10
|
+
end
|
11
|
+
|
12
|
+
# Iterator over captures.
|
13
|
+
#
|
14
|
+
# @yieldparam match [TreeSitter::QueryMatch]
|
15
|
+
# @yieldparam capture_index [Integer]
|
16
|
+
def each
|
17
|
+
return enum_for __method__ if !block_given?
|
18
|
+
|
19
|
+
while (capture_index, match = @cursor.next_capture)
|
20
|
+
next if !match.is_a?(TreeSitter::QueryMatch)
|
21
|
+
|
22
|
+
if match.satisfies_text_predicate?(@query, @src)
|
23
|
+
yield [match, capture_index]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TreeSitter
|
4
|
+
# A Cursor for {Query}.
|
5
|
+
class QueryCursor
|
6
|
+
# Iterate over all of the matches in the order that they were found.
|
7
|
+
#
|
8
|
+
# Each match contains the index of the pattern that matched, and a list of
|
9
|
+
# captures. Because multiple patterns can match the same set of nodes,
|
10
|
+
# one match may contain captures that appear *before* some of the
|
11
|
+
# captures from a previous match.
|
12
|
+
def matches(query, node, src)
|
13
|
+
self.exec(query, node)
|
14
|
+
QueryMatches.new(self, query, src)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Iterate over all of the individual captures in the order that they
|
18
|
+
# appear.
|
19
|
+
#
|
20
|
+
# This is useful if you don't care about which pattern matched, and just
|
21
|
+
# want a single, ordered sequence of captures.
|
22
|
+
def captures(query, node, src)
|
23
|
+
self.exec(query, node)
|
24
|
+
QueryCaptures.new(self, query, src)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'query_captures'
|
4
|
+
|
5
|
+
module TreeSitter
|
6
|
+
# A match for a {Query}.
|
7
|
+
class QueryMatch
|
8
|
+
# All nodes at a given capture index.
|
9
|
+
#
|
10
|
+
# @param index [Integer]
|
11
|
+
#
|
12
|
+
# @return [TreeSitter::Node]
|
13
|
+
def nodes_for_capture_index(index) = captures.filter_map { |capture| capture.node if capture.index == index }
|
14
|
+
|
15
|
+
# Whether the {QueryMatch} satisfies the text predicates in the query.
|
16
|
+
#
|
17
|
+
# This is a translation from the [rust bindings](https://github.com/tree-sitter/tree-sitter/blob/e553578696fe86071846ed612ee476d0167369c1/lib/binding_rust/lib.rs#L2502).
|
18
|
+
# Because it's a direct translation, it's way too long and we need to shut up rubocop.
|
19
|
+
# TODO: refactor + simplify when satable.
|
20
|
+
def satisfies_text_predicate?(query, src) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
|
21
|
+
return true if query.text_predicates[pattern_index].nil?
|
22
|
+
|
23
|
+
query # rubocop:disable Metrics/BlockLength
|
24
|
+
.text_predicates[pattern_index]
|
25
|
+
.all? do |predicate|
|
26
|
+
case predicate.type
|
27
|
+
in TextPredicateCapture::EQ_CAPTURE
|
28
|
+
fst_nodes = nodes_for_capture_index(predicate.fst)
|
29
|
+
snd_nodes = nodes_for_capture_index(predicate.snd)
|
30
|
+
res = nil
|
31
|
+
consumed = 0
|
32
|
+
fst_nodes.zip(snd_nodes).each do |node1, node2|
|
33
|
+
text1 = node_text(node1, src)
|
34
|
+
text2 = node_text(node2, src)
|
35
|
+
if (text1 == text2) != predicate.positive? && predicate.match_all?
|
36
|
+
res = false
|
37
|
+
break
|
38
|
+
end
|
39
|
+
if (text1 == text2) == predicate.positive? && !predicate.match_all?
|
40
|
+
res = true
|
41
|
+
break
|
42
|
+
end
|
43
|
+
consumed += 1
|
44
|
+
end
|
45
|
+
(res.nil? && consumed == fst_nodes.length && consumed == snd_nodes.length) \
|
46
|
+
|| res
|
47
|
+
|
48
|
+
in TextPredicateCapture::EQ_STRING
|
49
|
+
nodes = nodes_for_capture_index(predicate.fst)
|
50
|
+
res = true
|
51
|
+
nodes.each do |node|
|
52
|
+
text = node_text(node, src)
|
53
|
+
if (predicate.snd == text) != predicate.positive? && predicate.match_all?
|
54
|
+
res = false
|
55
|
+
break
|
56
|
+
end
|
57
|
+
if (predicate.snd == text) == predicate.positive? && !predicate.match_all?
|
58
|
+
res = true
|
59
|
+
break
|
60
|
+
end
|
61
|
+
end
|
62
|
+
res
|
63
|
+
|
64
|
+
in TextPredicateCapture::MATCH_STRING
|
65
|
+
nodes = nodes_for_capture_index(predicate.fst)
|
66
|
+
res = true
|
67
|
+
nodes.each do |node|
|
68
|
+
text = node_text(node, src)
|
69
|
+
if predicate.snd.match?(text) != predicate.positive? && predicate.match_all?
|
70
|
+
res = false
|
71
|
+
break
|
72
|
+
end
|
73
|
+
if predicate.snd.match?(text) == predicate.positive? && !predicate.match_all?
|
74
|
+
res = true
|
75
|
+
break
|
76
|
+
end
|
77
|
+
end
|
78
|
+
res
|
79
|
+
|
80
|
+
in TextPredicateCapture::ANY_STRING
|
81
|
+
nodes = nodes_for_capture_index(predicate.fst)
|
82
|
+
res = true
|
83
|
+
nodes.each do |node|
|
84
|
+
text = node_text(node, src)
|
85
|
+
if predicate.snd.any? { |v| v == text } != predicate.positive?
|
86
|
+
res = false
|
87
|
+
break
|
88
|
+
end
|
89
|
+
end
|
90
|
+
res
|
91
|
+
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
def node_text(node, text) = text.byteslice(node.start_byte...node.end_byte)
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TreeSitter
|
4
|
+
# A sequence of {QueryMatch} associated with a given {QueryCursor}.
|
5
|
+
class QueryMatches
|
6
|
+
def initialize(cursor, query, src)
|
7
|
+
@cursor = cursor
|
8
|
+
@query = query
|
9
|
+
@src = src
|
10
|
+
end
|
11
|
+
|
12
|
+
# Iterator over matches.
|
13
|
+
#
|
14
|
+
# @yieldparam match [TreeSitter::QueryMatch]
|
15
|
+
def each
|
16
|
+
return enum_for __method__ if !block_given?
|
17
|
+
|
18
|
+
while match = @cursor.next_match
|
19
|
+
if match.satisfies_text_predicate?(@query, @src)
|
20
|
+
yield match
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TreeSitter
|
4
|
+
# A {Query} predicate generic representation.
|
5
|
+
class QueryPredicate
|
6
|
+
attr_accessor :operator
|
7
|
+
attr_accessor :args
|
8
|
+
|
9
|
+
def initialize(operator, args)
|
10
|
+
@operator = operator
|
11
|
+
@args = args
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TreeSitter
|
4
|
+
# A representation for text predicates.
|
5
|
+
class TextPredicateCapture
|
6
|
+
EQ_CAPTURE = 0 # Equality Capture
|
7
|
+
EQ_STRING = 1 # Equality String
|
8
|
+
MATCH_STRING = 2 # Match String
|
9
|
+
ANY_STRING = 3 # Any String
|
10
|
+
|
11
|
+
attr_reader :fst
|
12
|
+
attr_reader :snd
|
13
|
+
attr_reader :type
|
14
|
+
|
15
|
+
# Create a TextPredicateCapture for {EQ_CAPTURE}.
|
16
|
+
def self.eq_capture(...) = new(EQ_CAPTURE, ...)
|
17
|
+
# Create a TextPredicateCapture for {EQ_STRING}.
|
18
|
+
def self.eq_string(...) = new(EQ_STRING, ...)
|
19
|
+
# Create a TextPredicateCapture for {MATCH_STRING}.
|
20
|
+
def self.match_string(...) = new(MATCH_STRING, ...)
|
21
|
+
# Create a TextPredicateCapture for {ANY_STRING}.
|
22
|
+
def self.any_string(...) = new(ANY_STRING, ...)
|
23
|
+
|
24
|
+
def initialize(type, fst, snd, positive, match_all)
|
25
|
+
@type = type
|
26
|
+
@fst = fst
|
27
|
+
@snd = snd
|
28
|
+
@positive = positive
|
29
|
+
@match_all = match_all
|
30
|
+
end
|
31
|
+
|
32
|
+
# `#eq` is positive, `#not-eq` is not.
|
33
|
+
def positive? = @positive
|
34
|
+
# `#any-` means don't match all.
|
35
|
+
def match_all? = @match_all
|
36
|
+
end
|
37
|
+
end
|
Binary file
|
data/lib/tree_sitter/version.rb
CHANGED
data/lib/tree_sitter.rb
CHANGED
@@ -6,9 +6,16 @@ end
|
|
6
6
|
|
7
7
|
require 'set'
|
8
8
|
|
9
|
+
require 'tree_sitter/tree_sitter'
|
9
10
|
require 'tree_sitter/version'
|
10
11
|
|
11
|
-
require 'tree_sitter/tree_sitter'
|
12
12
|
require 'tree_sitter/node'
|
13
|
+
require 'tree_sitter/query'
|
14
|
+
require 'tree_sitter/query_captures'
|
15
|
+
require 'tree_sitter/query_cursor'
|
16
|
+
require 'tree_sitter/query_match'
|
17
|
+
require 'tree_sitter/query_matches'
|
18
|
+
require 'tree_sitter/query_predicate'
|
19
|
+
require 'tree_sitter/text_predicate_capture'
|
13
20
|
|
14
21
|
ObjectSpace.define_finalizer(TreeSitter::Tree.class, proc { TreeSitter::Tree.finalizer })
|
data/lib/tree_stand/parser.rb
CHANGED
@@ -43,7 +43,7 @@ module TreeStand
|
|
43
43
|
.freeze
|
44
44
|
|
45
45
|
# The default paths we use to lookup parsers when no specific
|
46
|
-
# {TreeStand::Config#parser_path} is
|
46
|
+
# {TreeStand::Config#parser_path} is `nil`.
|
47
47
|
# Order matters.
|
48
48
|
LIBDIRS = [
|
49
49
|
'tree-sitter-parsers',
|
@@ -180,7 +180,7 @@ module TreeStand
|
|
180
180
|
|
181
181
|
# We know that the bindings will accept `lib`, but I don't know how to tell sorbet
|
182
182
|
# the types in ext/tree_sitter where `load` is defined.
|
183
|
-
TreeSitter::Language.load(name.
|
183
|
+
TreeSitter::Language.load(name.tr('-', '_'), T.unsafe(lib))
|
184
184
|
end
|
185
185
|
|
186
186
|
# @param language [String]
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby_tree_sitter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: x86_64-linux
|
6
6
|
authors:
|
7
7
|
- Firas al-Khalil
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2024-
|
12
|
+
date: 2024-06-26 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: sorbet-runtime
|
@@ -74,7 +74,15 @@ files:
|
|
74
74
|
- ext/tree_sitter/tree_sitter.c
|
75
75
|
- ext/tree_sitter/tree_sitter.h
|
76
76
|
- lib/tree_sitter.rb
|
77
|
+
- lib/tree_sitter/helpers.rb
|
77
78
|
- lib/tree_sitter/node.rb
|
79
|
+
- lib/tree_sitter/query.rb
|
80
|
+
- lib/tree_sitter/query_captures.rb
|
81
|
+
- lib/tree_sitter/query_cursor.rb
|
82
|
+
- lib/tree_sitter/query_match.rb
|
83
|
+
- lib/tree_sitter/query_matches.rb
|
84
|
+
- lib/tree_sitter/query_predicate.rb
|
85
|
+
- lib/tree_sitter/text_predicate_capture.rb
|
78
86
|
- lib/tree_sitter/tree_sitter.so
|
79
87
|
- lib/tree_sitter/version.rb
|
80
88
|
- lib/tree_stand.rb
|