Skip to content

Commit e355c2f

Browse files
committed
refactor(query): move predicate handling to dedicated methods
1 parent 07a8052 commit e355c2f

File tree

1 file changed

+138
-91
lines changed
  • src/main/java/io/github/treesitter/jtreesitter

1 file changed

+138
-91
lines changed

src/main/java/io/github/treesitter/jtreesitter/Query.java

Lines changed: 138 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,6 @@ private static boolean invalidPredicateChar(char c) {
139139
return !(Character.isLetterOrDigit(c) || c == '_' || c == '-' || c == '.' || c == '?' || c == '!');
140140
}
141141

142-
@SuppressWarnings("DuplicatedCode")
143142
private void handlePredicates(String source, MemorySegment query, @Unsigned int patternCount)
144143
throws QueryError.Predicate {
145144
try (var alloc = Arena.ofConfined()) {
@@ -149,6 +148,8 @@ private void handlePredicates(String source, MemorySegment query, @Unsigned int
149148
if ((steps = count.get(C_INT, 0)) == 0) continue;
150149
int offset = ts_query_start_byte_for_pattern(query, i);
151150
long row = source.chars().limit(offset).filter(c -> c == '\n').count();
151+
var predicates = this.predicates.get(i);
152+
152153
for (long j = 0; j < steps; ++j) {
153154
long nargs = 0;
154155
for (; ; ++nargs) {
@@ -160,99 +161,20 @@ private void handlePredicates(String source, MemorySegment query, @Unsigned int
160161
var name = captureNames.get(TSQueryPredicateStep.value_id(t0));
161162
throw new QueryError.Predicate(row, "@%s".formatted(name));
162163
}
164+
163165
var predicate = stringValues.get(TSQueryPredicateStep.value_id(t0));
164166
if (QueryPredicate.Eq.NAMES.contains(predicate)) {
165-
if (nargs != 3) {
166-
var error = "#%s expects 2 arguments, got %d";
167-
throw new QueryError.Predicate(row, error, predicate, nargs - 1);
168-
}
169-
var t1 = TSQueryPredicateStep.asSlice(tokens, 1);
170-
if (TSQueryPredicateStep.type(t1) != TSQueryPredicateStepTypeCapture()) {
171-
var value = stringValues.get(TSQueryPredicateStep.value_id(t1));
172-
var error = "first argument to #%s must be a capture name, got \"%s\"";
173-
throw new QueryError.Predicate(row, error, predicate, value);
174-
}
175-
var capture = captureNames.get(TSQueryPredicateStep.value_id(t1));
176-
var t2 = TSQueryPredicateStep.asSlice(tokens, 2);
177-
var id = TSQueryPredicateStep.value_id(t2);
178-
var isCapture = TSQueryPredicateStep.type(t2) == TSQueryPredicateStepTypeCapture();
179-
var value = isCapture ? captureNames.get(id) : stringValues.get(id);
180-
predicates.get(i).add(new QueryPredicate.Eq(predicate, capture, value, isCapture));
167+
predicates.add(handlePredicateEq(predicate, tokens, nargs, row));
181168
} else if (QueryPredicate.Match.NAMES.contains(predicate)) {
182-
if (nargs != 3) {
183-
var error = "#%s expects 2 arguments, got %d";
184-
throw new QueryError.Predicate(row, error, predicate, nargs - 1);
185-
}
186-
var t1 = TSQueryPredicateStep.asSlice(tokens, 1);
187-
if (TSQueryPredicateStep.type(t1) != TSQueryPredicateStepTypeCapture()) {
188-
var value = stringValues.get(TSQueryPredicateStep.value_id(t1));
189-
var error = "first argument to #%s must be a capture name, got \"%s\"";
190-
throw new QueryError.Predicate(row, error, predicate, value);
191-
}
192-
var t2 = TSQueryPredicateStep.asSlice(tokens, 2);
193-
if (TSQueryPredicateStep.type(t2) != TSQueryPredicateStepTypeString()) {
194-
var value = captureNames.get(TSQueryPredicateStep.value_id(t2));
195-
var error = "second argument to #%s must be a string literal, got @%s";
196-
throw new QueryError.Predicate(row, error, predicate, value);
197-
}
198-
try {
199-
var capture = captureNames.get(TSQueryPredicateStep.value_id(t1));
200-
var pattern = Pattern.compile(stringValues.get(TSQueryPredicateStep.value_id(t2)));
201-
predicates.get(i).add(new QueryPredicate.Match(predicate, capture, pattern));
202-
} catch (PatternSyntaxException e) {
203-
throw new QueryError.Predicate(row, "pattern error", e);
204-
}
169+
predicates.add(handlePredicateMatch(predicate, tokens, nargs, row));
205170
} else if (QueryPredicate.AnyOf.NAMES.contains(predicate)) {
206-
if (nargs < 3) {
207-
var error = "#%s expects at least 2 arguments, got %d";
208-
throw new QueryError.Predicate(row, error, predicate, nargs - 1);
209-
}
210-
var t1 = TSQueryPredicateStep.asSlice(tokens, 1);
211-
if (TSQueryPredicateStep.type(t1) != TSQueryPredicateStepTypeCapture()) {
212-
var value = stringValues.get(TSQueryPredicateStep.value_id(t1));
213-
var error = "first argument to #%s must be a capture name, got \"%s\"";
214-
throw new QueryError.Predicate(row, error, predicate, value);
215-
}
216-
List<String> values = new ArrayList<>((int) nargs - 2);
217-
for (long k = 2; k < nargs; ++k) {
218-
var t = TSQueryPredicateStep.asSlice(tokens, k);
219-
if (TSQueryPredicateStep.type(t) != TSQueryPredicateStepTypeString()) {
220-
var value = captureNames.get(TSQueryPredicateStep.value_id(t));
221-
var error = "arguments to #%s must be string literals, got @%s";
222-
throw new QueryError.Predicate(row, error, predicate, value);
223-
}
224-
values.add(stringValues.get(TSQueryPredicateStep.value_id(t)));
225-
}
226-
var capture = captureNames.get(TSQueryPredicateStep.value_id(t1));
227-
predicates.get(i).add(new QueryPredicate.AnyOf(predicate, capture, values));
228-
} else if (predicate.equals("is?") || predicate.equals("is-not?") || predicate.equals("set!")) {
229-
if (nargs == 1 || nargs > 3) {
230-
var error = "#%s expects 1-2 arguments, got %d";
231-
throw new QueryError.Predicate(row, error, predicate, nargs - 1);
232-
}
233-
var t1 = TSQueryPredicateStep.asSlice(tokens, 1);
234-
if (TSQueryPredicateStep.type(t1) != TSQueryPredicateStepTypeString()) {
235-
var value = captureNames.get(TSQueryPredicateStep.value_id(t1));
236-
var error = "first argument to #%s must be a string literal, got @%s";
237-
throw new QueryError.Predicate(row, error, predicate, value);
238-
}
239-
String key = stringValues.get(TSQueryPredicateStep.value_id(t1)), value = null;
240-
if (nargs == 3) {
241-
var t2 = TSQueryPredicateStep.asSlice(tokens, 2);
242-
if (TSQueryPredicateStep.type(t2) != TSQueryPredicateStepTypeString()) {
243-
var capture = captureNames.get(TSQueryPredicateStep.value_id(t2));
244-
var error = "second argument to #%s must be a string literal, got @%s";
245-
throw new QueryError.Predicate(row, error, predicate, capture);
246-
}
247-
value = stringValues.get(TSQueryPredicateStep.value_id(t2));
248-
}
249-
if (predicate.equals("is?")) {
250-
positiveAssertions.get(i).put(key, Optional.ofNullable(value));
251-
} else if (predicate.equals("is-not?")) {
252-
negativeAssertions.get(i).put(key, Optional.ofNullable(value));
253-
} else {
254-
settings.get(i).put(key, Optional.ofNullable(value));
255-
}
171+
predicates.add(handlePredicateAnyOf(predicate, tokens, nargs, row));
172+
} else if (predicate.equals("is?") || predicate.equals("is-not?")) {
173+
var assertions = (predicate.equals("is?") ? positiveAssertions : negativeAssertions).get(i);
174+
handlePredicateAssertion(predicate, tokens, nargs, row, assertions);
175+
} else if (predicate.equals("set!")) {
176+
var settings = this.settings.get(i);
177+
handleDirectiveSet(predicate, tokens, nargs, row, settings);
256178
} else {
257179
List<QueryPredicateArg> values = new ArrayList<>((int) nargs - 1);
258180
for (long k = 1; k < nargs; ++k) {
@@ -265,7 +187,7 @@ private void handlePredicates(String source, MemorySegment query, @Unsigned int
265187
values.add(new QueryPredicateArg.Capture(capture));
266188
}
267189
}
268-
predicates.get(i).add(new QueryPredicate(predicate, values));
190+
predicates.add(new QueryPredicate(predicate, values));
269191
}
270192
j += nargs;
271193
tokens = TSQueryPredicateStep.asSlice(tokens, nargs + 1);
@@ -274,6 +196,131 @@ private void handlePredicates(String source, MemorySegment query, @Unsigned int
274196
}
275197
}
276198

199+
/** {@code #eq?} predicate */
200+
private QueryPredicate handlePredicateEq(String name, MemorySegment tokens, long nargs, long row) {
201+
if (nargs != 3) {
202+
var error = "#%s expects 2 arguments, got %d";
203+
throw new QueryError.Predicate(row, error, name, nargs - 1);
204+
}
205+
var t1 = TSQueryPredicateStep.asSlice(tokens, 1);
206+
if (TSQueryPredicateStep.type(t1) != TSQueryPredicateStepTypeCapture()) {
207+
var value = stringValues.get(TSQueryPredicateStep.value_id(t1));
208+
var error = "first argument to #%s must be a capture name, got \"%s\"";
209+
throw new QueryError.Predicate(row, error, name, value);
210+
}
211+
var capture = captureNames.get(TSQueryPredicateStep.value_id(t1));
212+
var t2 = TSQueryPredicateStep.asSlice(tokens, 2);
213+
var id = TSQueryPredicateStep.value_id(t2);
214+
var isCapture = TSQueryPredicateStep.type(t2) == TSQueryPredicateStepTypeCapture();
215+
var value = isCapture ? captureNames.get(id) : stringValues.get(id);
216+
return new QueryPredicate.Eq(name, capture, value, isCapture);
217+
}
218+
219+
/** {@code #match?} predicate */
220+
private QueryPredicate handlePredicateMatch(String name, MemorySegment tokens, long nargs, long row) {
221+
if (nargs != 3) {
222+
var error = "#%s expects 2 arguments, got %d";
223+
throw new QueryError.Predicate(row, error, name, nargs - 1);
224+
}
225+
var t1 = TSQueryPredicateStep.asSlice(tokens, 1);
226+
if (TSQueryPredicateStep.type(t1) != TSQueryPredicateStepTypeCapture()) {
227+
var value = stringValues.get(TSQueryPredicateStep.value_id(t1));
228+
var error = "first argument to #%s must be a capture name, got \"%s\"";
229+
throw new QueryError.Predicate(row, error, name, value);
230+
}
231+
var t2 = TSQueryPredicateStep.asSlice(tokens, 2);
232+
if (TSQueryPredicateStep.type(t2) != TSQueryPredicateStepTypeString()) {
233+
var value = captureNames.get(TSQueryPredicateStep.value_id(t2));
234+
var error = "second argument to #%s must be a string literal, got @%s";
235+
throw new QueryError.Predicate(row, error, name, value);
236+
}
237+
try {
238+
var capture = captureNames.get(TSQueryPredicateStep.value_id(t1));
239+
var pattern = Pattern.compile(stringValues.get(TSQueryPredicateStep.value_id(t2)));
240+
return new QueryPredicate.Match(name, capture, pattern);
241+
} catch (PatternSyntaxException e) {
242+
throw new QueryError.Predicate(row, "pattern error", e);
243+
}
244+
}
245+
246+
/** {@code #any-of?} predicate */
247+
private QueryPredicate handlePredicateAnyOf(String name, MemorySegment tokens, long nargs, long row) {
248+
if (nargs < 3) {
249+
var error = "#%s expects at least 2 arguments, got %d";
250+
throw new QueryError.Predicate(row, error, name, nargs - 1);
251+
}
252+
var t1 = TSQueryPredicateStep.asSlice(tokens, 1);
253+
if (TSQueryPredicateStep.type(t1) != TSQueryPredicateStepTypeCapture()) {
254+
var value = stringValues.get(TSQueryPredicateStep.value_id(t1));
255+
var error = "first argument to #%s must be a capture name, got \"%s\"";
256+
throw new QueryError.Predicate(row, error, name, value);
257+
}
258+
List<String> values = new ArrayList<>((int) nargs - 2);
259+
for (long k = 2; k < nargs; ++k) {
260+
var t = TSQueryPredicateStep.asSlice(tokens, k);
261+
if (TSQueryPredicateStep.type(t) != TSQueryPredicateStepTypeString()) {
262+
var value = captureNames.get(TSQueryPredicateStep.value_id(t));
263+
var error = "arguments to #%s must be string literals, got @%s";
264+
throw new QueryError.Predicate(row, error, name, value);
265+
}
266+
values.add(stringValues.get(TSQueryPredicateStep.value_id(t)));
267+
}
268+
var capture = captureNames.get(TSQueryPredicateStep.value_id(t1));
269+
return new QueryPredicate.AnyOf(name, capture, values);
270+
}
271+
272+
/** {@code #is?} predicate */
273+
private void handlePredicateAssertion(
274+
String name, MemorySegment tokens, long nargs, long row, Map<String, Optional<String>> assertions) {
275+
if (nargs == 1 || nargs > 3) {
276+
var error = "#%s expects 1-2 arguments, got %d";
277+
throw new QueryError.Predicate(row, error, name, nargs - 1);
278+
}
279+
var t1 = TSQueryPredicateStep.asSlice(tokens, 1);
280+
if (TSQueryPredicateStep.type(t1) != TSQueryPredicateStepTypeString()) {
281+
var value = captureNames.get(TSQueryPredicateStep.value_id(t1));
282+
var error = "first argument to #%s must be a string literal, got @%s";
283+
throw new QueryError.Predicate(row, error, name, value);
284+
}
285+
String key = stringValues.get(TSQueryPredicateStep.value_id(t1)), value = null;
286+
if (nargs == 3) {
287+
var t2 = TSQueryPredicateStep.asSlice(tokens, 2);
288+
if (TSQueryPredicateStep.type(t2) != TSQueryPredicateStepTypeString()) {
289+
var capture = captureNames.get(TSQueryPredicateStep.value_id(t2));
290+
var error = "second argument to #%s must be a string literal, got @%s";
291+
throw new QueryError.Predicate(row, error, name, capture);
292+
}
293+
value = stringValues.get(TSQueryPredicateStep.value_id(t2));
294+
}
295+
assertions.put(key, Optional.ofNullable(value));
296+
}
297+
298+
/** {@code #set!} directive */
299+
private void handleDirectiveSet(
300+
String name, MemorySegment tokens, long nargs, long row, Map<String, Optional<String>> settings) {
301+
if (nargs == 1 || nargs > 3) {
302+
var error = "#%s expects 1-2 arguments, got %d";
303+
throw new QueryError.Predicate(row, error, name, nargs - 1);
304+
}
305+
var t1 = TSQueryPredicateStep.asSlice(tokens, 1);
306+
if (TSQueryPredicateStep.type(t1) != TSQueryPredicateStepTypeString()) {
307+
var value = captureNames.get(TSQueryPredicateStep.value_id(t1));
308+
var error = "first argument to #%s must be a string literal, got @%s";
309+
throw new QueryError.Predicate(row, error, name, value);
310+
}
311+
String key = stringValues.get(TSQueryPredicateStep.value_id(t1)), value = null;
312+
if (nargs == 3) {
313+
var t2 = TSQueryPredicateStep.asSlice(tokens, 2);
314+
if (TSQueryPredicateStep.type(t2) != TSQueryPredicateStepTypeString()) {
315+
var capture = captureNames.get(TSQueryPredicateStep.value_id(t2));
316+
var error = "second argument to #%s must be a string literal, got @%s";
317+
throw new QueryError.Predicate(row, error, name, capture);
318+
}
319+
value = stringValues.get(TSQueryPredicateStep.value_id(t2));
320+
}
321+
settings.put(key, Optional.ofNullable(value));
322+
}
323+
277324
MemorySegment segment() {
278325
return self;
279326
}

0 commit comments

Comments
 (0)