fix(languagetree): apply resolve_lang to metadata['injection.language']

`resolve_lang` is applied to `@injection.language` when it's supplied as a
capture:

f5953edbac/runtime/lua/vim/treesitter/languagetree.lua (L766-L768)

If we want to support `metadata['injection.language']` (as per #22518 and
[tree-sitter upstream](https://tree-sitter.github.io/tree-sitter/syntax-highlighting#language-injection))
then the behavior should be consistent.

Fixes: nvim-treesitter/nvim-treesitter#4918
This commit is contained in:
L Lllvvuu 2023-09-13 16:51:54 -07:00 committed by Lewis Russell
parent 40bfca744d
commit 908843df61
2 changed files with 84 additions and 50 deletions

View File

@ -734,7 +734,8 @@ local has_parser = function(lang)
or #vim.api.nvim_get_runtime_file('parser/' .. lang .. '.*', false) > 0 or #vim.api.nvim_get_runtime_file('parser/' .. lang .. '.*', false) > 0
end end
--- Return parser name for language (if exists) or filetype (if registered and exists) --- Return parser name for language (if exists) or filetype (if registered and exists).
--- Also attempts with the input lower-cased.
--- ---
---@param alias string language or filetype name ---@param alias string language or filetype name
---@return string? # resolved parser name ---@return string? # resolved parser name
@ -743,10 +744,19 @@ local function resolve_lang(alias)
return alias return alias
end end
if has_parser(alias:lower()) then
return alias:lower()
end
local lang = vim.treesitter.language.get_lang(alias) local lang = vim.treesitter.language.get_lang(alias)
if lang and has_parser(lang) then if lang and has_parser(lang) then
return lang return lang
end end
lang = vim.treesitter.language.get_lang(alias:lower())
if lang and has_parser(lang) then
return lang
end
end end
---@private ---@private
@ -758,9 +768,10 @@ end
function LanguageTree:_get_injection(match, metadata) function LanguageTree:_get_injection(match, metadata)
local ranges = {} ---@type Range6[] local ranges = {} ---@type Range6[]
local combined = metadata['injection.combined'] ~= nil local combined = metadata['injection.combined'] ~= nil
local injection_lang = metadata['injection.language'] --[[@as string?]]
local lang = metadata['injection.self'] ~= nil and self:lang() local lang = metadata['injection.self'] ~= nil and self:lang()
or metadata['injection.parent'] ~= nil and self._parent_lang or metadata['injection.parent'] ~= nil and self._parent_lang
or metadata['injection.language'] --[[@as string?]] or (injection_lang and resolve_lang(injection_lang))
local include_children = metadata['injection.include-children'] ~= nil local include_children = metadata['injection.include-children'] ~= nil
for id, node in pairs(match) do for id, node in pairs(match) do
@ -768,7 +779,7 @@ function LanguageTree:_get_injection(match, metadata)
-- Lang should override any other language tag -- Lang should override any other language tag
if name == 'injection.language' then if name == 'injection.language' then
local text = vim.treesitter.get_node_text(node, self._source, { metadata = metadata[id] }) local text = vim.treesitter.get_node_text(node, self._source, { metadata = metadata[id] })
lang = resolve_lang(text) or resolve_lang(text:lower()) lang = resolve_lang(text)
elseif name == 'injection.content' then elseif name == 'injection.content' then
ranges = get_node_ranges(node, self._source, metadata[id], include_children) ranges = get_node_ranges(node, self._source, metadata[id], include_children)
end end

View File

@ -85,6 +85,56 @@ void ui_refresh(void)
} }
}]] }]]
local injection_text_c = [[
int x = INT_MAX;
#define READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
#define foo void main() { \
return 42; \
}
]]
local injection_grid_c = [[
int x = INT_MAX; |
#define READ_STRING(x, y) (char *)read_string((x), (size_t)(y)) |
#define foo void main() { \ |
return 42; \ |
} |
^ |
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
|
]]
local injection_grid_expected_c = [[
{3:int} x = {5:INT_MAX}; |
#define {5:READ_STRING}(x, y) ({3:char} *)read_string((x), ({3:size_t})(y)) |
#define foo {3:void} main() { \ |
{4:return} {5:42}; \ |
} |
^ |
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
|
]]
describe('treesitter highlighting (C)', function() describe('treesitter highlighting (C)', function()
local screen local screen
@ -411,34 +461,9 @@ describe('treesitter highlighting (C)', function()
end) end)
it("supports injected languages", function() it("supports injected languages", function()
insert([[ insert(injection_text_c)
int x = INT_MAX;
#define READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
#define foo void main() { \
return 42; \
}
]])
screen:expect{grid=[[ screen:expect{grid=injection_grid_c}
int x = INT_MAX; |
#define READ_STRING(x, y) (char *)read_string((x), (size_t)(y)) |
#define foo void main() { \ |
return 42; \ |
} |
^ |
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
|
]]}
exec_lua [[ exec_lua [[
local parser = vim.treesitter.get_parser(0, "c", { local parser = vim.treesitter.get_parser(0, "c", {
@ -448,26 +473,24 @@ describe('treesitter highlighting (C)', function()
test_hl = highlighter.new(parser, {queries = {c = hl_query}}) test_hl = highlighter.new(parser, {queries = {c = hl_query}})
]] ]]
screen:expect{grid=[[ screen:expect{grid=injection_grid_expected_c}
{3:int} x = {5:INT_MAX}; | end)
#define {5:READ_STRING}(x, y) ({3:char} *)read_string((x), ({3:size_t})(y)) |
#define foo {3:void} main() { \ | it("supports injecting by ft name in metadata['injection.language']", function()
{4:return} {5:42}; \ | insert(injection_text_c)
} |
^ | screen:expect{grid=injection_grid_c}
{1:~ }|
{1:~ }| exec_lua [[
{1:~ }| vim.treesitter.language.register("c", "foo")
{1:~ }| local parser = vim.treesitter.get_parser(0, "c", {
{1:~ }| injections = {c = '(preproc_def (preproc_arg) @injection.content (#set! injection.language "fOO")) (preproc_function_def value: (preproc_arg) @injection.content (#set! injection.language "fOO"))'}
{1:~ }| })
{1:~ }| local highlighter = vim.treesitter.highlighter
{1:~ }| test_hl = highlighter.new(parser, {queries = {c = hl_query}})
{1:~ }| ]]
{1:~ }|
{1:~ }| screen:expect{grid=injection_grid_expected_c}
|
]]}
end) end)
it("supports overriding queries, like ", function() it("supports overriding queries, like ", function()