nvim/REGRESSION_FIX_2025-12-07.md

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 :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:

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 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