From 01817eb6f335a3713fe1a1993d4ea62accc33cfc Mon Sep 17 00:00:00 2001 From: Stefan VanBuren Date: Tue, 3 Mar 2026 13:18:55 -0500 Subject: [PATCH] fix(treesitter): normalize language aliases Hyphenated language names are silently dropped when used as injections (see #38132). This combines the normalization of language aliases into `resolve_lang`, and also adds the normalization of hyphens to underscores, which allows for handling of injected language tags with hyphens in their names. Fixes #38132. --- runtime/lua/vim/treesitter/languagetree.lua | 4 +++- test/functional/treesitter/parser_spec.lua | 17 +++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua index fffddd9f7b..1fd174c9b3 100644 --- a/runtime/lua/vim/treesitter/languagetree.lua +++ b/runtime/lua/vim/treesitter/languagetree.lua @@ -1022,6 +1022,8 @@ end) ---@param alias string language or filetype name ---@return string? # resolved parser name local function resolve_lang(alias) + -- normalize: treesitter language names are always lower case and use underscores + alias = alias and alias:lower():gsub('-', '_') -- validate that `alias` is a legal language if not (alias and alias:match('[%w_]+') == alias) then return @@ -1058,7 +1060,7 @@ function LanguageTree:_get_injection(match, metadata) -- Lang should override any other language tag if name == 'injection.language' then local text = vim.treesitter.get_node_text(node, self._source, { metadata = metadata[id] }) - lang = resolve_lang(text:lower()) -- language names are always lower case + lang = resolve_lang(text) elseif name == 'injection.filename' then local text = vim.treesitter.get_node_text(node, self._source, { metadata = metadata[id] }) local ft = vim.filetype.match({ filename = text }) diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua index f4bde239c7..9a35febc8f 100644 --- a/test/functional/treesitter/parser_spec.lua +++ b/test/functional/treesitter/parser_spec.lua @@ -938,6 +938,23 @@ int x = INT_MAX; eq({ 'gsub!', 'offset!', 'set!', 'trim!' }, res_list) end) end) + + it('normalizes hyphens to underscores in injection.language', function() + exec_lua(function() + -- register "c" as the parser for "shell_session" (normalized form of "shell-session") + vim.treesitter.language.register('c', 'shell_session') + _G.parser = vim.treesitter.get_parser(0, 'c', { + injections = { + c = '(preproc_def (preproc_arg) @injection.content (#set! injection.language "shell-session"))', + }, + }) + _G.parser:parse(true) + end) + + -- injection.language "shell-session" should normalize to "shell_session", + -- which resolves via the registered alias to the "c" parser + eq('table', exec_lua('return type(parser:children().c)')) + end) end) it('clips nested injections #34098', function()