sveltejs / language-tools

The Svelte Language Server, and official extensions which use it
MIT License
1.22k stars 195 forks source link

svelte-language-server watcher doesn't work in neovim lspconfig #2008

Closed ryoppippi closed 1 year ago

ryoppippi commented 1 year ago

I'm in the same problem with my sveltekit project. I'm using typescript-svelte-plugin. Although typescript files (like +page.server.ts) works realtime, diagnostics of .svelte file does not updated.

I'm configuring root_pattern( {"package.json", "tsconfig.json", "tsconfig.jsonc", "node_modules"}) for svelte language server

https://user-images.githubusercontent.com/1560508/237040552-0a1be152-0c2b-45ab-b98c-3e927ffeae34.mov

Originally posted by @ryoppippi in https://github.com/sveltejs/language-tools/issues/1415#issuecomment-1539681042

ryoppippi commented 1 year ago

Okay, this is a truly hacky things, but I solved this problem with this setting

function on_attach(on_attach)
  vim.api.nvim_create_autocmd("LspAttach", {
    callback = function(args)
      local buffer = args.buf
      local client = vim.lsp.get_client_by_id(args.data.client_id)
      on_attach(client, buffer)
    end,
  })
end

on_attach(function(client, bufnr)
      vim.api.nvim_create_autocmd("BufWritePost", {
        pattern = { "*.js", "*.ts" },
        callback = function(ctx)
          if client.name == "svelte" then
            client.notify("$/onDidChangeTsOrJsFile", { uri = ctx.file })
          end
        end,
      })
    end)
end)
kamalkech commented 1 year ago

@ryoppippi that s OK for me too, are u found another solution more better ??

jasonlyu123 commented 1 year ago

This is fixed in language-server 0.15.12. You don't need the workaround.

kamalkech commented 1 year ago

@jasonlyu123 i install the last version but not working and fixed using example of @ryoppippi

jasonlyu123 commented 1 year ago

The workaround only solves part of the problem. The API used in the workaround was meant to assist file watching instead of replacing it. What is your neovim version? This issue is about a compatibility problem introduced in neovim 0.9.0.

kamalkech commented 1 year ago

@jasonlyu123 NVIM v0.9.0 Build type: Release LuaJIT 2.1.0-beta3

ryoppippi commented 1 year ago

Not working in my env either

jasonlyu123 commented 1 year ago

Do keep in mind that "file watchers" require files to be saved. And the $/onDidChangeTsOrJsFile is for syncing changes without file saving. You still need the custom code if you want it to sync without file save. I am not sure which problem you are seeing. But I just tested it again and file watching does trigger on neovim with the latest version.

joriskoris commented 1 year ago

Can confirm, not working in latest neovim.

kamalkech commented 1 year ago

yeh that what i try to show, not working with last version of neovim

jasonlyu123 commented 1 year ago

Hmm. Turn out the fix doesn't work with 0.9.0 but works in nightly 0.10.0. The dynamic watcher registration isn't supported in 0.9.x. But that's the only way to register it in the language server. If file watch is supported, but dynamic registration isn't. I think it should be the client's responsibility to set up the watcher config. If we enable our fallback watcher and the client has already set up a watcher, There'll be two watchers running, which might cause performance problems. Especially if the watcher is polling-based.

In conclusion, It should work in the latest nightly version of neovim. But if you don't want to use the nightly version, You'll need to manually config the watcher, which I don't know how, sorry.

ryoppippi commented 1 year ago

|'m using HEAD of neovim, but not working without my hack

jasonlyu123 commented 1 year ago

I can reproduce with 0.9.0 and 0.9.1 but not v0.10.0-dev-552+g08db61b19. if you can reproduce it in the latest nightly version. You might need to debug yourself. Maybe the way neovim watch file doesn't work in your OS or something. But that would make it an upstream issue.

joriskoris commented 1 year ago

I can reproduce with 0.9.0 and 0.9.1 but not v0.10.0-dev-552+g08db61b19. if you can reproduce it in the latest nightly version. You might need to debug yourself. Maybe the way neovim watch file doesn't work in your OS or something. But that would make it an upstream issue.

Out of curiosity, which platform are you on?

domialbrecht commented 1 year ago

I am currently still experiencing the exact same bug with Nvim v0.10.0 on macOS Ventura:

NVIM v0.10.0-dev-585+g2e055e49a
Build type: RelWithDebInfo
LuaJIT 2.1.0-beta3
Compilation: /Applications/Xcode_13.2.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc -O2 -g -Og -g -Wall -Wextra -pedantic -Wno-unused-parameter -Wstrict-prototypes -std=gnu99 -Wshadow -Wconversion -Wvla -Wdouble-promotion -Wmissing-noreturn -Wmissing-format-attribute -Wmissing-prototypes -Wimplicit-fallthrough -fdiagnostics-color=always -fstack-protector-strong -DUNIT_TESTING -DINCLUDE_GENERATED_DECLARATIONS -DNVIM_TS_HAS_SET_MAX_START_DEPTH -I/Users/runner/work/neovim/neovim/.deps/usr/include/luajit-2.1 -I/usr/local/include -I/Users/runner/work/neovim/neovim/.deps/usr/include -I/Users/runner/work/neovim/neovim/build/src/nvim/auto -I/Users/runner/work/neovim/neovim/build/include -I/Users/runner/work/neovim/neovim/build/cmake.config -I/Users/runner/work/neovim/neovim/src -I/Applications/Xcode_13.2.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk/usr/include

   system vimrc file: "$VIM/sysinit.vim"
  fall-back for $VIM: "/usr/local/share/nvim"

Run :checkhealth for more info

What is very strange is that my same nvim/config is working on my linux machine.. I really cant figure this out. I also tried to set workspace dynamicRegistration true in capabilities, but without success. Unfortunately I dont understand LSP enought..

Here is a log from lsp about svelteserver

[WARN][2023-07-04 16:43:12] ...lsp/handlers.lua:137 "The language server eslint triggers a registerCapability handler despite dynamicRegistration set to false. Report upstream, this warning is harmless"
[ERROR][2023-07-04 16:43:12] .../vim/lsp/rpc.lua:734    "rpc"   "/Users/dominika/.local/share/nvim/mason/bin/svelteserver"  "stderr"    "Initialize language server at  file:///Users/dominika/Projects/mycura\n"
[ERROR][2023-07-04 16:43:12] .../vim/lsp/rpc.lua:734    "rpc"   "/Users/dominika/.local/share/nvim/mason/bin/svelteserver"  "stderr"    "Initialize new ts service at  /Users/dominika/Projects/mycura/tsconfig.json\n"
[ERROR][2023-07-04 16:43:12] .../vim/lsp/rpc.lua:734    "rpc"   "/Users/dominika/.local/share/nvim/mason/bin/svelteserver"  "stderr"    "Trying to load configs for /Users/dominika/Projects/mycura\n"
[ERROR][2023-07-04 16:43:12] .../vim/lsp/rpc.lua:734    "rpc"   "/Users/dominika/.local/share/nvim/mason/bin/svelteserver"  "stderr"    "Loaded config at  /Users/dominika/Projects/mycura/svelte.config.js\n"
[ERROR][2023-07-04 16:43:12] .../vim/lsp/rpc.lua:734    "rpc"   "/Users/dominika/.local/share/nvim/mason/bin/svelteserver"  "stderr"    "SnapshotManager File Statistics:\nProject files: 580\nSvelte files: 419\nFrom node_modules: 0\nTotal: 580\n"
[ERROR][2023-07-04 16:43:13] .../vim/lsp/rpc.lua:734    "rpc"   "/Users/dominika/.local/share/nvim/mason/bin/svelteserver"  "stderr"    "Initialize new ts service at  /Users/dominika/Projects/mycura/node_modules/@roxi/routify/tsconfig.json\n"
[ERROR][2023-07-04 16:43:13] .../vim/lsp/rpc.lua:734    "rpc"   "/Users/dominika/.local/share/nvim/mason/bin/svelteserver"  "stderr"    "Trying to load configs for /Users/dominika/Projects/mycura/node_modules/@roxi/routify\n"
[WARN][2023-07-04 16:43:13] ...lsp/handlers.lua:137 "The language server eslint triggers a registerCapability handler despite dynamicRegistration set to false. Report upstream, this warning is harmless"
[START][2023-07-04 16:46:20] LSP logging initiated
joriskoris commented 1 year ago

Anyone come up with a solution or at least figure out a cause for this?

jasonlyu123 commented 1 year ago

What is the OS for people having trouble with neovim 0.10.0? It's working for me in both Linux (Ubuntu) and Windows.

drocha87 commented 1 year ago

I'm on debian 12 and I can indeed confirm that upgrading to neovim

NVIM v0.10.0-dev-741+g996dd36c7
Build type: RelWithDebInfo
LuaJIT 2.1.0-beta3

and using

svelte-language-server 0.15.16

fixed the problem!

joriskoris commented 1 year ago
NVIM v0.10.0-dev-735+g8fe9f41f7-Homebrew
Build type: Release
LuaJIT 2.1.0-beta3

and

svelte-language-server 0.15.16

on latest macOS and problem persists.

jasonlyu123 commented 1 year ago

Then it probably is a macOS-only problem. You can try if Volar has the same problem. If so, You'll need to report to neovim.

alics1996 commented 1 year ago

NVIM v0.9.1 Build type: Release LuaJIT 2.1.0-beta3

macOs Ventura v13.2.1

same issue, added this to my on_attach function:

      if client.name == 'svelte' then
        vim.api.nvim_create_autocmd("BufWritePost", {
          pattern = { "*.js", "*.ts" },
          callback = function(ctx)
            client.notify("$/onDidChangeTsOrJsFile", { uri = ctx.file })
          end,
        })
      end
thenbe commented 10 months ago

We can update @ryoppippi's snippet to work without requiring the file to be saved to disk, replicating the behavior in the svelte-vscode extension. It would enable us to do the following:

  1. Assume foo.ts imports MyType from bar.svelte.
  2. Update MyType in foo.ts.
  3. Do not save foo.ts.
  4. bar.svelte is now aware of the latest changes made in step 2.
on_attach(function(client, bufnr)
-     vim.api.nvim_create_autocmd("BufWritePost", {
+     vim.api.nvim_create_autocmd({ "TextChanged", "TextChangedI", "TextChangedP" }, {
        pattern = { "*.js", "*.ts" },
        callback = function(ctx)
          if client.name == "svelte" then
            client.notify("$/onDidChangeTsOrJsFile", {
              uri = ctx.file,
+             changes = {
+               { text = table.concat(vim.api.nvim_buf_get_lines(ctx.buf, 0, -1, false), "\n") },
+             },
            })
          end
        end,
+       group = vim.api.nvim_create_augroup("svelte_ondidchangetsorjsfile", { clear = true }),
      })
    end)
end)

Some things I'm not sure of:

  1. In the original svelte-vscode implementation, the changes.range property is defined. However, I'm unsure as to how to define it in nvim. Nevertheless, this still works (maybe at the cost of some performance?) because "if only a text is provided it is considered to be the full content of the document." (source).

  2. What is the best autocmd event(s) to use to balance performance and convenience. TBH, I'm not sure if we need to worry ourselves with performance at this point. I'm only mentioning this point due to the note in TextChanged's description.


svelte-language-server: v0.16.1

$ nvim -v
NVIM v0.10.0-dev-7ca2d64
Build type: Release
LuaJIT 2.1.1693350652
ryoppippi commented 10 months ago

Hi! Today I found that we do not need these hacks for "zero-type-safety"

pierregoutheraud commented 10 months ago

For people for whom the hack is still not working it might be because you are using ctx.file which when using telescope for example will be a relative path and not an absolute path. You can use ctx.match instead, and it fixed it for me.

on_attach = function(client, bufnr)
  vim.api.nvim_create_autocmd("BufWritePost", {
    pattern = { "*.js", "*.ts" },
    callback = function(ctx)
      -- Here use ctx.match instead of ctx.file
      client.notify("$/onDidChangeTsOrJsFile", { uri = ctx.match })
    end,
  })
end,
alics1996 commented 10 months ago

Make sure you include:

group = vim.api.nvim_create_augroup("svelte_ondidchangetsorjsfile", { clear = true }),

inside the 2nd param for nvim_create_autocmd function. Otherwise, new autocmd is created on every new buffer svelte lsp get attached to.

ziontee113 commented 7 months ago

Thanks everyone for all the information. I got mine working by adding this into my on_attach() function:

                if client.name == "svelte" then
                    vim.api.nvim_create_autocmd("BufWritePost", {
                        pattern = { "*.js", "*.ts" },
                        group = svelte_augroup,
                        callback = function(ctx)
                            client.notify("$/onDidChangeTsOrJsFile", { uri = ctx.match })
                        end,
                    })
                end

I'm running

NVIM v0.9.5
Build type: Release
LuaJIT 2.1.1702233742
Elias-Graf commented 7 months ago

@jasonlyu123 so... is this not fixed? Could we re-open the issue? I think I'm experiencing this with the latest version of lunar vim, which is 1.3 AFAIK. Other versions:

C:\Users\Elias〉lvim -v                                                                                                                                                                                                                     03/02/2024 09:19:41 PM
NVIM v0.9.1
Build type: RelWithDebInfo
LuaJIT 2.1.0-beta3
Compilation: C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/VC/Tools/MSVC/14.29.30133/bin/Hostx64/x64/cl.exe /MD /Zi /O2 /Ob1  -W3 -wd4311 -wd4146 -DUNIT_TESTING -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE -D_WIN32_WINNT=0x0602 -DMSWIN -DINCLUDE_GENERATED_DECLARATIONS -ID:/a/neovim/neovim/.deps/usr/include/luajit-2.1 -ID:/a/neovim/neovim/.deps/usr/include -ID:/a/neovim/neovim/.deps/usr/include -ID:/a/neovim/neovim/build/src/nvim/auto -ID:/a/neovim/neovim/build/include -ID:/a/neovim/neovim/build/cmake.config -ID:/a/neovim/neovim/src -ID:/a/neovim/neovim/.deps/usr/include -ID:/a/neovim/neovim/.deps/usr/include -ID:/a/neovim/neovim/.deps/usr/include -ID:/a/neovim/neovim/.deps/usr/include -ID:/a/neovim/neovim/.deps/usr/include -ID:/a/neovim/neovim/.deps/usr/include -ID:/a/neovim/neovim/.deps/usr/include

   system vimrc file: "$VIM\sysinit.vim"
  fall-back for $VIM: "C:/Program Files (x86)/nvim/share/nvim"

Run :checkhealth for more info
    ◍ svelte-language-server svelte
      A language server (implementing the language server protocol) for Svelte.

      installed version 0.16.5                                     
      homepage          https://github.com/sveltejs/language-tools 
      languages         Svelte                                     
      categories        LSP                                        
      executables       svelteserver.cmd                           

      → LSP server configuration schema (press enter to expand)

And this is on windows, because at some point it was mentioned, it could be a MacOs only problem?

jasonlyu123 commented 7 months ago

Hmm. Turn out the fix doesn't work with 0.9.0 but works in nightly 0.10.0. The dynamic watcher registration isn't supported in 0.9.x. But that's the only way to register it in the language server.

If we enable our fallback watcher and the client has already set up a watcher, There'll be two watchers running, which might cause performance problems. Especially if the watcher is polling-based.

Slight corrections but the problem is the same. The client capability neovim 0.9.x returns doesn't include dynamic file watcher registration. But we want to avoid adding it unconditionally.

I won't reopen this since we have done what we can. We can't control when neovim releases the fix that includes the capability in stable. The watcher that potentially doesn't work in macOS is also out of our control.

Elias-Graf commented 7 months ago

@jasonlyu123 Thank you for your response. But, ignore my ignorance, does this mean this would not be an issue in an unstable build of Neovim?

We can't control when neovim releases the fix that includes the capability in stable.

And is there an issue in the Neovim repository about this? I don't see any mentioned in this thread.

Edit:

Is this it, by any chance: https://github.com/neovim/nvim-lspconfig/issues/725? Doesn't sound much like something will be fixed. Just skimming through it, the problem was simply attributed to the "core implementation" without further notice.

jasonlyu123 commented 6 months ago

Actually, you can just manually change the client capability in 0.9.x to have dynamicRegistration = true

local lsp_capabilities = vim.lsp.protocol.make_client_capabilities() --or whatever your setup requires
lsp_capabilities.workspace.didChangeWatchedFiles.dynamicRegistration = true

-- whatever your other plugin requires, for example:
-- lsp_capabilities.textDocument.completion = require('cmp_nvim_lsp').default_capabilities().textDocument.completion

lspconfig.svelte.setup {
    capabilities = lsp_capabilities,
}

If this still doesn't work, please prepare a reproduction and report to neovim. Also, to reiterate, $/onDidChangeTsOrJsFile is not a substitution for file watcher, They both exist for a reason.

amitgupta6 commented 5 months ago

For anyone still struggling, I used following configuration in Astrovim and it worked

    config = {
      svelte = {
        capabilities = {
          workspace = {
            didChangeWatchedFiles = {
              dynamicRegistration = true,
            },
          },
        },
      },
    },
kuechlerm commented 5 months ago

Hey @amitgupta6, I tried to add the following config nvim/lua/plugins/astrolsp.lua but still the svelte files do not react so a change in a ts file. I used the AstroNvim Docker image, so the basic setup should be ok. Any idea what I am missing?

return {
  "AstroNvim/astrolsp",
  opts = {
    config = {
      svelte = {
        capabilities = {
          workspace = {
            didChangeWatchedFiles = {
              dynamicRegistration = true,
            },
          },
        },
      },
    },
  },
}
amitgupta6 commented 5 months ago

Hey. Try following,

Open astrolsp.lua and add following code inside on_attach function and it should work.

      vim.api.nvim_create_autocmd("BufWritePost", {
        pattern = { "*.js", "*.ts" },
        callback = function(ctx)
          -- Here use ctx.match instead of ctx.file
          client.notify("$/onDidChangeTsOrJsFile", { uri = ctx.match })
        end,
      })
kuechlerm commented 5 months ago

Thank you @amitgupta6 ! I was not able to really test this in Astro because I cannot easily restart it in the container test setup that they provide.

But it gave me an idea for my LazyVim setup that finally does the trick.

I added a .config/nvim/lua/plugins/lspconfig.lua with

return {
  "neovim/nvim-lspconfig",
  opts = {
    setup = {
      svelte = function(_, opts)
        LazyVim.lsp.on_attach(function(client, buffer)
          if client.name == "svelte" then
            vim.api.nvim_create_autocmd("BufWritePost", {
              pattern = { "*.js", "*.ts" },
              callback = function(ctx)
                client.notify("$/onDidChangeTsOrJsFile", { uri = ctx.match })
              end,
            })
          end
        end)
      end,
    },
  },
 }
amitgupta6 commented 5 months ago

This should work. Please post here if it works for you.

ropez commented 4 months ago

Archlinux neovim 0.10.0 svelte-language-server 0.16.9

Solution with lsp_capabilities does not work: https://github.com/sveltejs/language-tools/issues/2008#issuecomment-1987497624

Workaround with BufWritePost and client.notify works as intended.

diegoulloao commented 4 months ago

This worked for me, nvim 0.10.0 on macOs, also working good for astro + svelte.

local on_attach = function(client, bufnr)
  if client.name == "svelte" then
    vim.api.nvim_create_autocmd("BufWritePost", {
      pattern = { "*.js", "*.ts" },
      group = vim.api.nvim_create_augroup("svelte_ondidchangetsorjsfile", { clear = true }),
      callback = function(ctx)
        -- Here use ctx.match instead of ctx.file
        client.notify("$/onDidChangeTsOrJsFile", { uri = ctx.match })
      end,
    })
  end

  -- attach keymaps if needed
end
codevogel commented 4 months ago

I have the same issue. I have to reload nvim before I get code action suggestions for newly added files.

I haven't got any of the workarounds in this thread to work. I tried on v0.10 nightly and v0.11 nightly: image

tmp

I use Mason. My config can be found here: https://github.com/codevogel/.dotfiles/blob/e9e45a3a640dae9f8e490d969fe69ead82582520/neovim/.config/nvim/init.lua

jasonlyu123 commented 4 months ago

So It seems like neovim intentionally disabled didChangeWatchedFiles.dynamicRegistration in Linux because the watcher capability is limited. Currently, only Mac and Windows have dynamicRegistration=true.

https://github.com/neovim/neovim/blob/f69937fdbd162630c35e119e67bbbf052558c0e0/runtime/doc/news-0.10.txt#L185

Setting it to true does trigger the watcher registration but the file watch itself never triggers. For Linux users with 0.10 stable, You can set lsp_capabilities.workspace.didChangeWatchedFiles to false. This will enable a fallback watcher with chokidar in the language server.

local lsp_capabilities = vim.lsp.protocol.make_client_capabilities() --or whatever your setup requires
lsp_capabilities.workspace.didChangeWatchedFiles = false

-- whatever your other plugin requires, for example:
-- lsp_capabilities.textDocument.completion = require('cmp_nvim_lsp').default_capabilities().textDocument.completion

lspconfig.svelte.setup {
    capabilities = lsp_capabilities,
}

Also, I probably have to repeat a thousand times in this kind of big thread. $/onDidChangeTsOrJsFile is for unsaved changes. And we don't add new files from $/onDidChangeTsOrJsFile. If you only use it, the new files won't be loaded.

ghost commented 2 months ago

Please repoen, this entire extension literally doesn't work, you install it copying/pasting the exact commands of the readme and nothing.

ryoppippi commented 2 months ago

For me it works fine. So please reopen another issue with your minimal config! @s1nistr4

ryoppippi commented 2 months ago

Also, you can check my Neovim config. This helps you how to make the svelte LSP work on your Neovim. Write config by yourself, and thank to be able to configure by yourself. That's what you need to use vim/neovim.

gabrieldechichi commented 2 weeks ago

For anyone still experiencing this issue (@s1nistr4) you may want to make sure to Neovim to >=0.10.0 and update all of your plugins. None of the workarounds were working for me until I updated my Neovim, than the workaround below worked

This worked for me, nvim 0.10.0 on macOs, also working good for astro + svelte.

local on_attach = function(client, bufnr)
  if client.name == "svelte" then
    vim.api.nvim_create_autocmd("BufWritePost", {
      pattern = { "*.js", "*.ts" },
      group = vim.api.nvim_create_augroup("svelte_ondidchangetsorjsfile", { clear = true }),
      callback = function(ctx)
        -- Here use ctx.match instead of ctx.file
        client.notify("$/onDidChangeTsOrJsFile", { uri = ctx.match })
      end,
    })
  end

  -- attach keymaps if needed
end