Skip to content

Commit 4301110

Browse files
committed
query: Indicate specific step that's impossible
1 parent d47346a commit 4301110

File tree

5 files changed

+103
-91
lines changed

5 files changed

+103
-91
lines changed

cli/src/tests/query_test.rs

Lines changed: 36 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,11 @@ fn test_query_errors_on_impossible_patterns() {
197197
),
198198
Err(QueryError::Pattern(
199199
1,
200-
"(binary_expression left: (identifier) left: (identifier))\n^".to_string(),
200+
[
201+
"(binary_expression left: (identifier) left: (identifier))",
202+
" ^"
203+
]
204+
.join("\n"),
201205
))
202206
);
203207

@@ -210,7 +214,11 @@ fn test_query_errors_on_impossible_patterns() {
210214
Query::new(js_lang, "(function_declaration name: (statement_block))"),
211215
Err(QueryError::Pattern(
212216
1,
213-
"(function_declaration name: (statement_block))\n^".to_string(),
217+
[
218+
"(function_declaration name: (statement_block))",
219+
" ^",
220+
]
221+
.join("\n")
214222
))
215223
);
216224

@@ -219,7 +227,11 @@ fn test_query_errors_on_impossible_patterns() {
219227
Query::new(rb_lang, "(call receiver:(binary))"),
220228
Err(QueryError::Pattern(
221229
1,
222-
"(call receiver:(binary))\n^".to_string(),
230+
[
231+
"(call receiver:(binary))", //
232+
" ^",
233+
]
234+
.join("\n")
223235
))
224236
);
225237
});
@@ -2307,55 +2319,52 @@ fn test_query_alternative_predicate_prefix() {
23072319
}
23082320

23092321
#[test]
2310-
fn test_query_is_definite() {
2322+
fn test_query_step_is_definite() {
23112323
struct Row {
23122324
language: Language,
23132325
pattern: &'static str,
2314-
results_by_symbol: &'static [(&'static str, bool)],
2326+
results_by_substring: &'static [(&'static str, bool)],
23152327
}
23162328

23172329
let rows = &[
23182330
Row {
23192331
language: get_language("python"),
23202332
pattern: r#"(expression_statement (string))"#,
2321-
results_by_symbol: &[("expression_statement", false), ("string", false)],
2333+
results_by_substring: &[("expression_statement", false), ("string", false)],
23222334
},
23232335
Row {
23242336
language: get_language("javascript"),
23252337
pattern: r#"(expression_statement (string))"#,
2326-
results_by_symbol: &[
2327-
("expression_statement", false),
2328-
("string", false), // string
2329-
],
2338+
results_by_substring: &[("expression_statement", false), ("string", false)],
23302339
},
23312340
Row {
23322341
language: get_language("javascript"),
23332342
pattern: r#"(object "{" "}")"#,
2334-
results_by_symbol: &[("object", false), ("{", true), ("}", true)],
2343+
results_by_substring: &[("object", false), ("{", true), ("}", true)],
23352344
},
23362345
Row {
23372346
language: get_language("javascript"),
23382347
pattern: r#"(pair (property_identifier) ":")"#,
2339-
results_by_symbol: &[("pair", false), ("property_identifier", false), (":", true)],
2348+
results_by_substring: &[("pair", false), ("property_identifier", false), (":", true)],
23402349
},
23412350
Row {
23422351
language: get_language("javascript"),
23432352
pattern: r#"(object "{" (_) "}")"#,
2344-
results_by_symbol: &[("object", false), ("{", false), ("", false), ("}", true)],
2353+
results_by_substring: &[("object", false), ("{", false), ("", false), ("}", true)],
23452354
},
23462355
Row {
23472356
language: get_language("javascript"),
23482357
pattern: r#"(binary_expression left: (identifier) right: (_))"#,
2349-
results_by_symbol: &[
2358+
results_by_substring: &[
23502359
("binary_expression", false),
2351-
("identifier", false),
2352-
("", true),
2360+
("(identifier)", false),
2361+
("(_)", true),
23532362
],
23542363
},
23552364
Row {
23562365
language: get_language("javascript"),
23572366
pattern: r#"(function_declaration name: (identifier) body: (statement_block))"#,
2358-
results_by_symbol: &[
2367+
results_by_substring: &[
23592368
("function_declaration", false),
23602369
("identifier", true),
23612370
("statement_block", true),
@@ -2367,7 +2376,7 @@ fn test_query_is_definite() {
23672376
(function_declaration
23682377
name: (identifier)
23692378
body: (statement_block "{" (expression_statement) "}"))"#,
2370-
results_by_symbol: &[
2379+
results_by_substring: &[
23712380
("function_declaration", false),
23722381
("identifier", false),
23732382
("statement_block", false),
@@ -2383,7 +2392,7 @@ fn test_query_is_definite() {
23832392
value: (constant)
23842393
"end")
23852394
"#,
2386-
results_by_symbol: &[
2395+
results_by_substring: &[
23872396
("singleton_class", false),
23882397
("constant", false),
23892398
("end", true),
@@ -2397,7 +2406,7 @@ fn test_query_is_definite() {
23972406
property: (property_identifier) @template-tag)
23982407
arguments: (template_string)) @template-call
23992408
"#,
2400-
results_by_symbol: &[("property_identifier", false), ("template_string", false)],
2409+
results_by_substring: &[("property_identifier", false), ("template_string", false)],
24012410
},
24022411
Row {
24032412
language: get_language("javascript"),
@@ -2408,7 +2417,7 @@ fn test_query_is_definite() {
24082417
property: (property_identifier) @prop)
24092418
"[")
24102419
"#,
2411-
results_by_symbol: &[
2420+
results_by_substring: &[
24122421
("identifier", false),
24132422
("property_identifier", true),
24142423
("[", true),
@@ -2424,7 +2433,7 @@ fn test_query_is_definite() {
24242433
"["
24252434
(#match? @prop "foo"))
24262435
"#,
2427-
results_by_symbol: &[
2436+
results_by_substring: &[
24282437
("identifier", false),
24292438
("property_identifier", false),
24302439
("[", true),
@@ -2435,23 +2444,17 @@ fn test_query_is_definite() {
24352444
allocations::record(|| {
24362445
for row in rows.iter() {
24372446
let query = Query::new(row.language, row.pattern).unwrap();
2438-
for (symbol_name, is_definite) in row.results_by_symbol {
2439-
let mut symbol = 0;
2440-
if !symbol_name.is_empty() {
2441-
symbol = row.language.id_for_node_kind(symbol_name, true);
2442-
if symbol == 0 {
2443-
symbol = row.language.id_for_node_kind(symbol_name, false);
2444-
}
2445-
}
2447+
for (substring, is_definite) in row.results_by_substring {
2448+
let offset = row.pattern.find(substring).unwrap();
24462449
assert_eq!(
2447-
query.pattern_is_definite(0, symbol, 0),
2450+
query.step_is_definite(offset),
24482451
*is_definite,
2449-
"Pattern: {:?}, symbol: {}, expected is_definite to be {}",
2452+
"Pattern: {:?}, substring: {:?}, expected is_definite to be {}",
24502453
row.pattern
24512454
.split_ascii_whitespace()
24522455
.collect::<Vec<_>>()
24532456
.join(" "),
2454-
symbol_name,
2457+
substring,
24552458
is_definite,
24562459
)
24572460
}

lib/binding_rust/bindings.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -651,12 +651,7 @@ extern "C" {
651651
) -> *const TSQueryPredicateStep;
652652
}
653653
extern "C" {
654-
pub fn ts_query_pattern_is_definite(
655-
self_: *const TSQuery,
656-
pattern_index: u32,
657-
symbol: TSSymbol,
658-
step_index: u32,
659-
) -> bool;
654+
pub fn ts_query_step_is_definite(self_: *const TSQuery, byte_offset: u32) -> bool;
660655
}
661656
extern "C" {
662657
#[doc = " Get the name and length of one of the query\'s captures, or one of the"]

lib/binding_rust/lib.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1467,12 +1467,12 @@ impl Query {
14671467
unsafe { ffi::ts_query_disable_pattern(self.ptr.as_ptr(), index as u32) }
14681468
}
14691469

1470-
/// Check if a pattern will definitely match after a certain number of steps
1471-
/// have matched.
1472-
pub fn pattern_is_definite(&self, pattern_index: usize, symbol: u16, step_index: usize) -> bool {
1473-
unsafe {
1474-
ffi::ts_query_pattern_is_definite(self.ptr.as_ptr(), pattern_index as u32, symbol, step_index as u32)
1475-
}
1470+
/// Check if a given step in a query is 'definite'.
1471+
///
1472+
/// A query step is 'definite' if its parent pattern will be guaranteed to match
1473+
/// successfully once it reaches the step.
1474+
pub fn step_is_definite(&self, byte_offset: usize) -> bool {
1475+
unsafe { ffi::ts_query_step_is_definite(self.ptr.as_ptr(), byte_offset as u32) }
14761476
}
14771477

14781478
fn parse_property(

lib/include/tree_sitter/api.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -719,11 +719,9 @@ const TSQueryPredicateStep *ts_query_predicates_for_pattern(
719719
uint32_t *length
720720
);
721721

722-
bool ts_query_pattern_is_definite(
722+
bool ts_query_step_is_definite(
723723
const TSQuery *self,
724-
uint32_t pattern_index,
725-
TSSymbol symbol,
726-
uint32_t step_index
724+
uint32_t byte_offset
727725
);
728726

729727
/**

0 commit comments

Comments
 (0)