feat(lsp): root_markers can control priority #33485

Problem:
root_markers cannot specify "equal priority filenames.

Solution:
Support nesting:

    {
      ...
      root_markers = { { ".stylua.toml", ".luarc.json" }, { ".git "} }
      ...
    }


Co-authored-by: Maria José Solano <majosolano99@gmail.com>
Co-authored-by: Gregory Anders <github@gpanders.com>
Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
This commit is contained in:
Lorenzo Bellina
2025-04-30 15:43:32 +02:00
committed by GitHub
parent f27fb737ce
commit 6577d72d81
4 changed files with 155 additions and 10 deletions

View File

@ -293,9 +293,37 @@ end
--- example at |vim.lsp.enable()|.
--- @field root_dir? string|fun(bufnr: integer, on_dir:fun(root_dir?:string))
---
--- Directory markers (e.g. ".git/", "package.json") used to decide `root_dir`. Unused if `root_dir`
--- is provided.
--- @field root_markers? string[]
--- Directory markers (.e.g. '.git/') where the LSP server will base its workspaceFolders,
--- rootUri, and rootPath on initialization. Unused if `root_dir` is provided.
---
--- The list order decides the priority. To indicate "equal priority", specify names in a nested list (`{ { 'a', 'b' }, ... }`)
--- Each entry in this list is a set of one or more markers. For each set, Nvim
--- will search upwards for each marker contained in the set. If a marker is
--- found, the directory which contains that marker is used as the root
--- directory. If no markers from the set are found, the process is repeated
--- with the next set in the list.
---
--- Example:
---
--- ```lua
--- root_markers = { 'stylua.toml', '.git' }
--- ```
---
--- Find the first parent directory containing the file `stylua.toml`. If not
--- found, find the first parent directory containing the file or directory
--- `.git`.
---
--- Example:
---
--- ```lua
--- root_markers = { { 'stylua.toml', '.luarc.json' }, '.git' }
--- ```
---
--- Find the first parent directory containing EITHER `stylua.toml` or
--- `.luarc.json`. If not found, find the first parent directory containing the
--- file or directory `.git`.
---
--- @field root_markers? (string|string[])[]
--- Sets the default configuration for an LSP client (or _all_ clients if the special name "*" is
--- used).
@ -613,7 +641,7 @@ end
--- Suppress error reporting if the LSP server fails to start (default false).
--- @field silent? boolean
---
--- @field package _root_markers? string[]
--- @field package _root_markers? (string|string[])[]
--- Create a new LSP client and start a language server or reuses an already
--- running client if one is found matching `name` and `root_dir`.
@ -662,8 +690,16 @@ function lsp.start(config, opts)
local bufnr = vim._resolve_bufnr(opts.bufnr)
if not config.root_dir and opts._root_markers then
validate('root_markers', opts._root_markers, 'table')
config = vim.deepcopy(config)
config.root_dir = vim.fs.root(bufnr, opts._root_markers)
for _, marker in ipairs(opts._root_markers) do
local root = vim.fs.root(bufnr, marker)
if root ~= nil then
config.root_dir = root
break
end
end
end
if