diff options
-rw-r--r-- | runtime/doc/treesitter.txt | 16 | ||||
-rw-r--r-- | runtime/lua/vim/treesitter/query.lua | 33 | ||||
-rw-r--r-- | runtime/queries/c/highlights.scm | 17 | ||||
-rw-r--r-- | test/functional/treesitter/parser_spec.lua | 2 |
4 files changed, 63 insertions, 5 deletions
diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt index 483812b7c9..64b4730eee 100644 --- a/runtime/doc/treesitter.txt +++ b/runtime/doc/treesitter.txt @@ -221,8 +221,7 @@ The following predicates are built in: similar to `match?` `contains?` *treesitter-predicate-contains?* - Match a string against parts of the text corresponding to a node: - >query + Match a string against parts of the text corresponding to a node: >query ((identifier) @foo (#contains? @foo "foo")) ((identifier) @foo-bar (#contains? @foo-bar "foo" "bar")) < @@ -234,6 +233,19 @@ The following predicates are built in: This is the recommended way to check if the node matches one of many keywords, as it has been optimized for this. + `has-ancestor?` *treesitter-predicate-has-ancestor?* + Match any of the given node types against all ancestors of a node: >query + ((identifier) @variable.builtin + (#any-of? @variable.builtin "begin" "end") + (#has-ancestor? @variable.builtin range_expression)) +< + `has-parent?` *treesitter-predicate-has-parent?* + Match any of the given node types against the direct ancestor of a + node: >query + (((field_expression + (field_identifier) @method)) @_parent + (#has-parent? @_parent template_method function_declarator)) +< *lua-treesitter-not-predicate* Each predicate has a `not-` prefixed predicate that is just the negation of the predicate. diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua index 75e5bf8870..73b561c777 100644 --- a/runtime/lua/vim/treesitter/query.lua +++ b/runtime/lua/vim/treesitter/query.lua @@ -382,6 +382,39 @@ local predicate_handlers = { return string_set[node_text] end, + + ['has-ancestor?'] = function(match, _, _, predicate) + local node = match[predicate[2]] + if not node then + return true + end + + local ancestor_types = {} + for _, type in ipairs({ unpack(predicate, 3) }) do + ancestor_types[type] = true + end + + node = node:parent() + while node do + if ancestor_types[node:type()] then + return true + end + node = node:parent() + end + return false + end, + + ['has-parent?'] = function(match, _, _, predicate) + local node = match[predicate[2]] + if not node then + return true + end + + if vim.list_contains({ unpack(predicate, 3) }, node:parent():type()) then + return true + end + return false + end, } -- As we provide lua-match? also expose vim-match? diff --git a/runtime/queries/c/highlights.scm b/runtime/queries/c/highlights.scm index dee70f9cc7..523a792403 100644 --- a/runtime/queries/c/highlights.scm +++ b/runtime/queries/c/highlights.scm @@ -117,12 +117,19 @@ (preproc_defined) ] @function.macro -(field_identifier) @property +(((field_expression + (field_identifier) @property)) @_parent + (#not-has-parent? @_parent template_method function_declarator call_expression)) + +(field_designator) @property +(((field_identifier) @property) + (#has-ancestor? @property field_declaration) + (#not-has-ancestor? @property function_declarator)) + (statement_identifier) @label [ (type_identifier) - (sized_type_specifier) (type_descriptor) ] @type @@ -138,6 +145,8 @@ (primitive_type) @type.builtin +(sized_type_specifier _ @type.builtin type: _?) + ((identifier) @constant (#lua-match? @constant "^[A-Z][A-Z0-9_]+$")) (enumerator @@ -163,6 +172,10 @@ field: (field_identifier) @function.call)) (function_declarator declarator: (identifier) @function) +(function_declarator + declarator: (parenthesized_declarator + (pointer_declarator + declarator: (field_identifier) @function))) (preproc_function_def name: (identifier) @function.macro) diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua index 9afce0b3a0..60042ab2fd 100644 --- a/test/functional/treesitter/parser_spec.lua +++ b/test/functional/treesitter/parser_spec.lua @@ -483,7 +483,7 @@ end]] return list ]] - eq({ 'any-of?', 'contains?', 'eq?', 'is-main?', 'lua-match?', 'match?', 'vim-match?' }, res_list) + eq({ 'any-of?', 'contains?', 'eq?', 'has-ancestor?', 'has-parent?', 'is-main?', 'lua-match?', 'match?', 'vim-match?' }, res_list) end) |