diff --git a/cli/src/tests/query_test.rs b/cli/src/tests/query_test.rs index b9b28117..598a9792 100644 --- a/cli/src/tests/query_test.rs +++ b/cli/src/tests/query_test.rs @@ -291,6 +291,24 @@ fn test_query_errors_on_impossible_patterns() { .join("\n") )) ); + + Query::new( + js_lang, + "(if_statement + condition: (parenthesized_expression (_expression) @cond))", + ) + .unwrap(); + assert_eq!( + Query::new(js_lang, "(if_statement condition: (_expression))",), + Err(QueryError::Structure( + 1, + [ + "(if_statement condition: (_expression))", // + " ^", + ] + .join("\n") + )) + ); }); } diff --git a/lib/src/query.c b/lib/src/query.c index 0ca03782..288656ac 100644 --- a/lib/src/query.c +++ b/lib/src/query.c @@ -639,6 +639,13 @@ static inline AnalysisStateEntry *analysis_state__top(AnalysisState *self) { return &self->stack[self->depth - 1]; } +static inline bool analysis_state__has_supertype(AnalysisState *self, TSSymbol symbol) { + for (unsigned i = 0; i < self->depth; i++) { + if (self->stack[i].parent_symbol == symbol) return true; + } + return false; +} + /*********************** * AnalysisSubgraphNode ***********************/ @@ -1134,6 +1141,9 @@ static bool ts_query__analyze_patterns(TSQuery *self, unsigned *error_offset) { if (step->field && step->field != field_id) { does_match = false; } + if (step->supertype_symbol) { + if (!analysis_state__has_supertype(state, step->supertype_symbol)) does_match = false; + } } // If this is a hidden child, then push a new entry to the stack, in order to @@ -1673,7 +1683,7 @@ static TSQueryError ts_query__parse_pattern( if (ts_language_symbol_metadata(self->language, symbol).supertype) { QueryStep *step = array_back(&self->steps); step->supertype_symbol = step->symbol; - step->symbol = WILDCARD_SYMBOL; + step->symbol = NAMED_WILDCARD_SYMBOL; } stream_skip_whitespace(stream);