mirror of
https://github.com/tree-sitter/tree-sitter.git
synced 2026-09-10 07:26:23 -04:00
fix(query): forbid an anchor at the end of a group
A `.` at the end of a group, such as `((comment)+ @c .)`, was silently dropped during compilation. Reject rather than dropping.
This commit is contained in:
parent
6bfbd9d84d
commit
966dc52557
|
|
@ -256,6 +256,51 @@ fn test_query_errors_on_invalid_syntax() {
|
|||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_query_errors_on_anchor_at_group_edge() {
|
||||
allocations::record(|| {
|
||||
let language = get_language("javascript");
|
||||
|
||||
// Anchors between siblings, or at the first/last position of a *node*
|
||||
// pattern, are valid.
|
||||
assert!(Query::new(&language, "((_) . (_))").is_ok());
|
||||
assert!(Query::new(&language, "(program (_) (_) .)").is_ok());
|
||||
assert!(Query::new(&language, "(program (_)* @x . (_))").is_ok());
|
||||
|
||||
// A `.` at the edge of a *group* is rejected. A group is not a node, so it
|
||||
// has no last child to anchor, and there is no sibling within the group to
|
||||
// anchor to.
|
||||
assert_eq!(
|
||||
Query::new(&language, "((_) .)").unwrap_err(),
|
||||
QueryError {
|
||||
row: 0,
|
||||
offset: 5,
|
||||
column: 5,
|
||||
kind: QueryErrorKind::Syntax,
|
||||
message: [
|
||||
"((_) .)", //
|
||||
" ^"
|
||||
]
|
||||
.join("\n")
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
Query::new(&language, "(program ((_)+ .)? (_))").unwrap_err(),
|
||||
QueryError {
|
||||
row: 0,
|
||||
offset: 15,
|
||||
column: 15,
|
||||
kind: QueryErrorKind::Syntax,
|
||||
message: [
|
||||
"(program ((_)+ .)? (_))", //
|
||||
" ^"
|
||||
]
|
||||
.join("\n")
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_query_errors_on_invalid_symbols() {
|
||||
allocations::record(|| {
|
||||
|
|
|
|||
|
|
@ -2485,9 +2485,17 @@ static TSQueryError ts_query__parse_pattern(
|
|||
CaptureQuantifiers child_capture_quantifiers = capture_quantifiers_new();
|
||||
for (;;) {
|
||||
if (stream->next == '.') {
|
||||
const char *anchor_start = stream->input;
|
||||
child_is_immediate = true;
|
||||
stream_advance(stream);
|
||||
stream_skip_whitespace(stream);
|
||||
// A `.` at a group's end has no sibling to anchor, and a group is not a
|
||||
// node, so there is no last child to anchor against.
|
||||
if (stream->next == ')') {
|
||||
stream_reset(stream, anchor_start);
|
||||
capture_quantifiers_delete(&child_capture_quantifiers);
|
||||
return TSQueryErrorSyntax;
|
||||
}
|
||||
}
|
||||
TSQueryError e = ts_query__parse_pattern(
|
||||
self,
|
||||
|
|
|
|||
Loading…
Reference in a new issue