From 26b5405d181e8c9e75c4b4ec9aae963cc25f285f Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Sun, 28 Apr 2024 16:27:47 +0200 Subject: [PATCH] fix(treesitter): enforce lowercase language names (#28546) * fix(treesitter): enforce lowercase language names Problem: On case-insensitive file systems (e.g., macOS), `has_parser` will return `true` for uppercase aliases, which will then try to inject the uppercase language unsuccessfully. Solution: Enforce and assume parser names to be lowercase when resolving language names. --- runtime/doc/treesitter.txt | 3 +++ runtime/lua/vim/treesitter/language.lua | 3 +++ runtime/lua/vim/treesitter/languagetree.lua | 12 +----------- test/functional/treesitter/highlight_spec.lua | 2 +- 4 files changed, 8 insertions(+), 12 deletions(-) diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt index 67cbeda2a8..2b9eba1520 100644 --- a/runtime/doc/treesitter.txt +++ b/runtime/doc/treesitter.txt @@ -30,6 +30,9 @@ A parser can also be loaded manually using a full path: >lua vim.treesitter.language.add('python', { path = "/path/to/python.so" }) < +Parser names are assumed to be lower case if the file system is +case-sensitive. + To associate certain |filetypes| with a treesitter language (name of parser), use |vim.treesitter.language.register()|. For example, to use the `xml` treesitter parser for buffers with filetype `svg` or `xslt`, use: >lua diff --git a/runtime/lua/vim/treesitter/language.lua b/runtime/lua/vim/treesitter/language.lua index 47abf65332..d0a74daa6c 100644 --- a/runtime/lua/vim/treesitter/language.lua +++ b/runtime/lua/vim/treesitter/language.lua @@ -88,6 +88,9 @@ function M.add(lang, opts) filetype = { filetype, { 'string', 'table' }, true }, }) + -- parser names are assumed to be lowercase (consistent behavior on case-insensitive file systems) + lang = lang:lower() + if vim._ts_has_language(lang) then M.register(lang, filetype) return diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua index 990debc77b..e618f29f8f 100644 --- a/runtime/lua/vim/treesitter/languagetree.lua +++ b/runtime/lua/vim/treesitter/languagetree.lua @@ -758,7 +758,6 @@ local has_parser = vim.func._memoize(1, function(lang) end) --- 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 ---@return string? # resolved parser name @@ -772,19 +771,10 @@ local function resolve_lang(alias) return alias end - if has_parser(alias:lower()) then - return alias:lower() - end - local lang = vim.treesitter.language.get_lang(alias) if lang and has_parser(lang) then return lang end - - lang = vim.treesitter.language.get_lang(alias:lower()) - if lang and has_parser(lang) then - return lang - end end ---@private @@ -808,7 +798,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) + lang = resolve_lang(text:lower()) -- language names are always lower case 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/highlight_spec.lua b/test/functional/treesitter/highlight_spec.lua index 1d7ee00818..69984b3233 100644 --- a/test/functional/treesitter/highlight_spec.lua +++ b/test/functional/treesitter/highlight_spec.lua @@ -484,7 +484,7 @@ describe('treesitter highlighting (C)', function() exec_lua [[ vim.treesitter.language.register("c", "foo") local parser = vim.treesitter.get_parser(0, "c", { - injections = {c = '(preproc_def (preproc_arg) @injection.content (#set! injection.language "fOO")) (preproc_function_def value: (preproc_arg) @injection.content (#set! injection.language "fOO"))'} + injections = {c = '(preproc_def (preproc_arg) @injection.content (#set! injection.language "foo")) (preproc_function_def value: (preproc_arg) @injection.content (#set! injection.language "foo"))'} }) local highlighter = vim.treesitter.highlighter test_hl = highlighter.new(parser, {queries = {c = hl_query}})