From 7384e7149e79365c96dc623d9fa3444737776982 Mon Sep 17 00:00:00 2001 From: Emilio Ziniades Date: Sat, 18 Nov 2023 09:40:13 +0200 Subject: [PATCH] fix: util.root_pattern prioritises pattern order (#2885) * fix: util.root_pattern prioritises pattern order Instead of traversing the filesystem upwards once and returning the first match of all the patterns, it traverses the filesystem upwards once for each pattern. This means that the order of the patterns provided matters, and the highest priority patterns should be put first. Also updated corresponding tests. * docs: update util.root_pattern description --- doc/lspconfig.txt | 3 ++- lua/lspconfig/util.lua | 23 +++++++++++++---------- test/lspconfig_spec.lua | 2 +- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/doc/lspconfig.txt b/doc/lspconfig.txt index 5a1da207..4a5cce19 100644 --- a/doc/lspconfig.txt +++ b/doc/lspconfig.txt @@ -371,7 +371,8 @@ below returns a function that takes as its argument the current buffer path. - `util.root_pattern`: function which takes multiple arguments, each corresponding to a different root pattern against which the contents of the current directory are matched using |vim.fn.glob()| while traversing up the - filesystem. + filesystem. Parent directories are traversed once per pattern, in the order + the patterns are specified. > root_dir = util.root_pattern('pyproject.toml', 'requirements.txt') < diff --git a/lua/lspconfig/util.lua b/lua/lspconfig/util.lua index 364bf9a8..176365d1 100644 --- a/lua/lspconfig/util.lua +++ b/lua/lspconfig/util.lua @@ -250,18 +250,21 @@ end function M.root_pattern(...) local patterns = vim.tbl_flatten { ... } - local function matcher(path) - for _, pattern in ipairs(patterns) do - for _, p in ipairs(vim.fn.glob(M.path.join(M.path.escape_wildcards(path), pattern), true, true)) do - if M.path.exists(p) then - return path - end - end - end - end return function(startpath) startpath = M.strip_archive_subpath(startpath) - return M.search_ancestors(startpath, matcher) + for _, pattern in ipairs(patterns) do + local match = M.search_ancestors(startpath, function(path) + for _, p in ipairs(vim.fn.glob(M.path.join(M.path.escape_wildcards(path), pattern), true, true)) do + if M.path.exists(p) then + return path + end + end + end) + + if match ~= nil then + return match + end + end end end diff --git a/test/lspconfig_spec.lua b/test/lspconfig_spec.lua index aab4f4ba..36eca3bc 100644 --- a/test/lspconfig_spec.lua +++ b/test/lspconfig_spec.lua @@ -136,7 +136,7 @@ describe('lspconfig', function() -- change the working directory to test directory vim.api.nvim_command 'cd ./test/test_dir/a' local cwd = vim.fn.getcwd() - eq(true, cwd == lspconfig.util.root_pattern { 'root_marker.txt', 'a_marker.txt' }(cwd)) + eq(true, cwd == lspconfig.util.root_pattern { 'a_marker.txt', 'root_marker.txt' }(cwd)) end) it('resolves to root_marker.txt', function()