diff --git a/cli/src/tests/query_test.rs b/cli/src/tests/query_test.rs index 945b3b1f..5c98c959 100644 --- a/cli/src/tests/query_test.rs +++ b/cli/src/tests/query_test.rs @@ -381,8 +381,8 @@ fn test_query_matches_with_named_wildcard() { let query = Query::new( language, " - (return_statement (*) @the-return-value) - (binary_expression operator: * @the-operator) + (return_statement (_) @the-return-value) + (binary_expression operator: _ @the-operator) ", ) .unwrap(); @@ -413,7 +413,7 @@ fn test_query_matches_with_wildcard_at_the_root() { let query = Query::new( language, " - (* + (_ (comment) @doc . (function_declaration @@ -432,10 +432,10 @@ fn test_query_matches_with_wildcard_at_the_root() { let query = Query::new( language, " - (* (string) @a) - (* (number) @b) - (* (true) @c) - (* (false) @d) + (_ (string) @a) + (_ (number) @b) + (_ (true) @c) + (_ (false) @d) ", ) .unwrap(); @@ -477,7 +477,7 @@ fn test_query_matches_with_immediate_siblings() { .) (list . - (*) @first-element) + (_) @first-element) ", ) .unwrap(); @@ -506,17 +506,19 @@ fn test_query_matches_with_repeated_leaf_nodes() { let query = Query::new( language, " - (* + ( (comment)+ @doc . (class_declaration - name: (identifier) @name)) + name: (identifier) @name) + ) - (* + ( (comment)+ @doc . (function_declaration - name: (identifier) @name)) + name: (identifier) @name) + ) ", ) .unwrap(); @@ -618,7 +620,7 @@ fn test_query_matches_with_non_terminal_repetitions_within_root() { let query = Query::new( language, r#" - (* + (_ (expression_statement (identifier) @id)+) "#, @@ -673,18 +675,19 @@ fn test_query_matches_with_nested_repetitions() { } #[test] -fn test_query_matches_with_leading_optional_repeated_leaf_nodes() { +fn test_query_matches_with_leading_zero_or_more_repeated_leaf_nodes() { allocations::record(|| { let language = get_language("javascript"); let query = Query::new( language, " - (* - (comment)+? @doc + ( + (comment)* @doc . (function_declaration - name: (identifier) @name)) + name: (identifier) @name) + ) ", ) .unwrap(); @@ -808,7 +811,7 @@ fn test_query_matches_with_repeated_internal_nodes() { let query = Query::new( language, " - (* + (_ (method_definition (decorator (identifier) @deco)+ name: (property_identifier) @name)) @@ -1099,12 +1102,12 @@ fn test_query_captures_basic() { language, r#" (pair - key: * @method.def + key: _ @method.def (function name: (identifier) @method.alias)) (variable_declarator - name: * @function.def + name: _ @function.def value: (function name: (identifier) @function.alias)) @@ -1352,7 +1355,7 @@ fn test_query_captures_with_many_nested_results_without_fields() { language, r#" (pair - key: * @method-def + key: _ @method-def (arrow_function)) ":" @colon @@ -1612,7 +1615,7 @@ fn test_query_captures_with_matches_removed() { r#" (binary_expression left: (identifier) @left - operator: * @op + operator: _ @op right: (identifier) @right) "#, ) @@ -1735,13 +1738,13 @@ fn test_query_capture_names() { r#" (if_statement condition: (binary_expression - left: * @left-operand + left: _ @left-operand operator: "||" - right: * @right-operand) + right: _ @right-operand) consequence: (statement_block) @body) (while_statement - condition:* @loop-condition) + condition: _ @loop-condition) "#, ) .unwrap(); diff --git a/cli/src/tests/tags_test.rs b/cli/src/tests/tags_test.rs index 9bfd1f56..fad8ebd8 100644 --- a/cli/src/tests/tags_test.rs +++ b/cli/src/tests/tags_test.rs @@ -33,7 +33,7 @@ const PYTHON_TAG_QUERY: &'static str = r#" const JS_TAG_QUERY: &'static str = r#" ( - (comment)+ @doc . + (comment)* @doc . (class_declaration name: (identifier) @name) @class (#select-adjacent! @doc @class) @@ -41,7 +41,7 @@ const JS_TAG_QUERY: &'static str = r#" ) ( - (comment)+ @doc . + (comment)* @doc . (method_definition name: (property_identifier) @name) @method (#select-adjacent! @doc @method) @@ -49,14 +49,15 @@ const JS_TAG_QUERY: &'static str = r#" ) ( - (comment)+ @doc . + (comment)* @doc . (function_declaration name: (identifier) @name) @function (#select-adjacent! @doc @function) (#strip! @doc "(^[/\\*\\s]*)|([/\\*\\s]*$)") ) -(call_expression function: (identifier) @name) @call +(call_expression + function: (identifier) @name) @call "#; const RUBY_TAG_QUERY: &'static str = r#" diff --git a/lib/src/query.c b/lib/src/query.c index 49cbb92f..9c5677bf 100644 --- a/lib/src/query.c +++ b/lib/src/query.c @@ -27,7 +27,7 @@ typedef struct { * represented as a sequence of these steps. Fields: * * - `symbol` - The grammar symbol to match. A zero value represents the - * wildcard symbol, '*'. + * wildcard symbol, '_'. * - `field` - The field name to match. A zero value means that a field name * was not specified. * - `capture_id` - An integer representing the name of the capture associated @@ -761,7 +761,7 @@ static TSQueryError ts_query__parse_pattern( TSSymbol symbol; // Parse the wildcard symbol - if (stream->next == '*') { + if (stream->next == '_') { symbol = depth > 0 ? NAMED_WILDCARD_SYMBOL : WILDCARD_SYMBOL; stream_advance(stream); } @@ -821,6 +821,15 @@ static TSQueryError ts_query__parse_pattern( } } + // Parse a wildcard pattern + else if (stream->next == '_') { + stream_advance(stream); + stream_skip_whitespace(stream); + + // Add a step that matches any kind of node + array_push(&self->steps, query_step__new(WILDCARD_SYMBOL, depth, is_immediate)); + } + // Parse a double-quoted anonymous leaf node expression else if (stream->next == '"') { stream_advance(stream); @@ -892,15 +901,6 @@ static TSQueryError ts_query__parse_pattern( self->steps.contents[step_index].field = field_id; } - // Parse a wildcard pattern - else if (stream->next == '*') { - stream_advance(stream); - stream_skip_whitespace(stream); - - // Add a step that matches any kind of node - array_push(&self->steps, query_step__new(WILDCARD_SYMBOL, depth, is_immediate)); - } - else { return TSQueryErrorSyntax; } @@ -913,18 +913,29 @@ static TSQueryError ts_query__parse_pattern( if (stream->next == '+') { stream_advance(stream); + stream_skip_whitespace(stream); QueryStep repeat_step = query_step__new(WILDCARD_SYMBOL, depth, false); repeat_step.alternative_index = starting_step_index; repeat_step.is_placeholder = true; repeat_step.alternative_is_immediate = true; array_push(&self->steps, repeat_step); - stream_skip_whitespace(stream); } else if (stream->next == '?') { stream_advance(stream); - step->alternative_index = self->steps.size; stream_skip_whitespace(stream); + step->alternative_index = self->steps.size; + } + + else if (stream->next == '*') { + stream_advance(stream); + stream_skip_whitespace(stream); + QueryStep repeat_step = query_step__new(WILDCARD_SYMBOL, depth, false); + repeat_step.alternative_index = starting_step_index; + repeat_step.is_placeholder = true; + repeat_step.alternative_is_immediate = true; + array_push(&self->steps, repeat_step); + step->alternative_index = self->steps.size; } // Parse an '@'-prefixed capture pattern