4.2 KiB
4.2 KiB
Critical Regression Fix: LSP Project Settings Not Loading (2025-12-07)
Summary
gd (goto definition) stopped working for external library references in WORKSPACE_TEST/site/external.php. Even restoring to a git commit where it previously worked didn't fix it, indicating an environment change rather than a code regression.
Root Cause
Neovim 0.11+ removed support for the on_new_config callback in vim.lsp.config().
The previous implementation used on_new_config to load project-local settings from .nvim.lua:
vim.lsp.config(server_name, {
on_new_config = function(new_config, root_dir)
-- Load project settings and merge into new_config.settings
local project_settings = load_project_lsp_settings(server_name, root_dir)
if project_settings.settings then
new_config.settings = vim.tbl_deep_extend("force",
new_config.settings or {},
project_settings.settings)
end
end,
})
Problem: This callback was silently ignored in Neovim 0.11+, resulting in:
- Empty
client.settings(confirmed via:LspInfoshowingSettings: {}) - No
includePathssent to intelephense gdfailing with "No locations found" for external library symbols
Symptoms
:LspInfoshowedSettings: {}for intelephensegdon\ExtLib\Src\Util::greetExternal()returned "No locations found"- Local (workspace) symbol navigation worked fine
- Git history restore didn't help (environment issue, not code issue)
Solution
Use the LspAttach autocmd instead of on_new_config to load and apply project settings:
vim.api.nvim_create_autocmd('LspAttach', {
group = vim.api.nvim_create_augroup('lsp_project_settings', { clear = true }),
callback = function(args)
local client = vim.lsp.get_client_by_id(args.data.client_id)
if not client then return end
-- Load project-specific settings from .nvim.lua at client.root_dir
local project_settings = load_project_lsp_settings(client.name, client.root_dir)
if project_settings.settings then
-- Merge into client.settings
client.settings = vim.tbl_deep_extend("force",
client.settings or {},
project_settings.settings)
-- Notify server of updated settings
vim.schedule(function()
client.notify("workspace/didChangeConfiguration",
{ settings = client.settings })
end)
end
end,
})
Validation
After fix:
cd WORKSPACE_TEST
nvim --headless +'e site/external.php' +'lua vim.wait(3000); local clients = vim.lsp.get_clients({name="intelephense"}); if clients[1] then print("Settings:", vim.inspect(clients[1].settings)) end' +quit
Output:
Settings: {
intelephense = {
environment = {
includePaths = { "/home/ray/.config/nvim/EXTERNAL_TEST" }
}
}
}
✅ Settings now correctly loaded and gd works for external symbols.
Key Differences: Neovim 0.10 vs 0.11 LSP API
Old API (lspconfig plugin, Neovim < 0.11)
require('lspconfig').intelephense.setup({
on_new_config = function(new_config, root_dir)
-- Called when creating new client
end,
})
New API (native vim.lsp.config, Neovim 0.11+)
-- Define config
vim.lsp.config('intelephense', { ... })
-- Enable server
vim.lsp.enable('intelephense')
-- Handle dynamic settings via autocmd
vim.api.nvim_create_autocmd('LspAttach', {
callback = function(args)
-- Access client, load settings, notify server
end,
})
Documentation Updated
README.md: Added decision log entry for 2025-12-07.github/copilot-instructions.md: Documents LspAttach patternAGENTS.md: Already notes "Native exrc + vim.lsp.config migration done"
Prevention
- Always test LSP functionality after Neovim version upgrades
- Check
:help newsfor API changes - Validate
:LspInfosettings are populated correctly - Test with external library references, not just workspace files
Files Modified
lua/plugins/lsp.lua: Replacedon_new_configwithLspAttachautocmd
Timeline
- Before 2025-12-07:
on_new_configworked in older Neovim version - 2025-12-07: Neovim upgraded to 0.11.5,
on_new_configsilently ignored - 2025-12-07: Diagnosed via
:LspInfoshowing empty settings - 2025-12-07: Fixed with
LspAttachpattern, verified working