nvim/REGRESSION_FIX_2025-12-07.md

130 lines
4.2 KiB
Markdown

# 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`:
```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 `:LspInfo` showing `Settings: {}`)
- No `includePaths` sent to intelephense
- `gd` failing with "No locations found" for external library symbols
## Symptoms
1. `:LspInfo` showed `Settings: {}` for intelephense
2. `gd` on `\ExtLib\Src\Util::greetExternal()` returned "No locations found"
3. Local (workspace) symbol navigation worked fine
4. 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:
```lua
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:
```bash
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:
```lua
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)
```lua
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+)
```lua
-- 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 pattern
- `AGENTS.md`: Already notes "Native exrc + vim.lsp.config migration done"
## Prevention
- Always test LSP functionality after Neovim version upgrades
- Check `:help news` for API changes
- Validate `:LspInfo` settings are populated correctly
- Test with external library references, not just workspace files
## Files Modified
- `lua/plugins/lsp.lua`: Replaced `on_new_config` with `LspAttach` autocmd
## Timeline
- **Before 2025-12-07**: `on_new_config` worked in older Neovim version
- **2025-12-07**: Neovim upgraded to 0.11.5, `on_new_config` silently ignored
- **2025-12-07**: Diagnosed via `:LspInfo` showing empty settings
- **2025-12-07**: Fixed with `LspAttach` pattern, verified working