yioneko / vtsls

LSP wrapper for typescript extension of vscode
Other
368 stars 6 forks source link

Support @vue/typescript-plugin #148

Open mcchrish opened 3 months ago

mcchrish commented 3 months ago

One issue I get is when I add vue to the filetypes table:

lspconfig.vtsls.setup {
  capabilities = capabilities,
  filetypes = { "typescript", "javascript", "javascriptreact", "typescriptreact", "vue" },
...

I get the error:

vtsls: -32603: Cannot find provider for the feature

Which blocks further attempts to try integrating the vue typescript plugin.

yioneko commented 3 months ago

It looks like volar monkey patched the vscode typescript extension to make it work for vue files: https://github.com/vuejs/language-tools/blob/ef908e2c4b0fadf17c50297bff56da2eecc2f25b/extensions/vscode/src/nodeClientMain.ts#L144-L150

So this is technically not a issue for vtsls. But I also think there is no better way for volar because the supported languages are hard coded in the extension. I'll try to add a way to let user add custom language ids.

yioneko commented 3 months ago

@mcchrish Could you test the version 0.2.2-alpha.1? An option vtsls.tsserver.globalPlugins is introduced for the vue plugin support: https://github.com/yioneko/vtsls/blob/6cdfdaccf7550beb89b7ea6b6ab163dc2dad4a40/README.md?plain=1#L136-L152

mcchrish commented 3 months ago

It's working! Amazing, thanks for the quick response!

mcchrish commented 3 months ago

Code action doesn't seem to work:

[Fzf-lua] "codeAction/resolve" failed with error -32603: Request codeAction/resolve failed with message: <semantic> TypeScript Server Error (5.4.3)             
Debug Failure. File /Users/mcchris/vimming/my-vue-app/src/App.vue has unknown extension.                                                                        
Error: Debug Failure. File /Users/mcchris/vimming/my-vue-app/src/App.vue has unknown extension.                                                                 
    at extensionFromPath (/Users/mcchris/Library/Application Support/nvim/mason/packages/vtsls/node_modules/@vtsls/language-server/node_modules/typescript/lib/t
sserver.js:21381:39)
yioneko commented 3 months ago

@mcchrish Did you see the Move to file action in the fzf-lua popup? I think your error is triggered by that, as I reproduced this error in VSCode with official Vue extension. It seems that fzf-lua will try to resolve all the code actions in advance despite that you don't select them.

yioneko commented 3 months ago

Just FYI: The Vue language support seems to be suffering problems right now, as you can look into its issues and https://github.com/vuejs/language-tools/pull/4119. So I would not merge the feature until it is stabilized so that we could see lesser such issue which is probably not caused by vtsls. Currently I recommend to stick to takeover mode (takeover mode is reintroduced from volar 2.0.7): https://github.com/williamboman/mason-lspconfig.nvim/issues/371#issuecomment-2018863753.

mcchrish commented 3 months ago

Did you see the Move to file action in the fzf-lua popup?

Yes, it's the only item I can see.

It's definitely very broken at the moment and went to downgrade to volar v1.8 instead. Thanks a lot for the support!

jordycoding commented 2 months ago

How does this work with nvim-lspconfig. I tried the suggested settings based on the tsserver settings for the vue plugin, but it seems to crash the lsp.

local util = require("lsp.util")

require("lspconfig").vtsls.setup({
    on_attach = util.on_attach,
    capabilities = util.capabilities,
    init_options = {
        vtsls = {
            tsserver = {
                globalPlugins = {
                    {
                        name = "@vue/typescript-plugin",
                        location = "/home/jordy/.npm-packages/lib/node_modules/@vue/typescript-plugin",
                        languages = { "typescript", "javascript", "vue" },
                        enableForWorkspaceTypeScriptVersions = true,
                        configNamespace = "typescript",
                    },
                },
            },
        },
    },
    filetypes = {
        "javascript",
        "javascriptreact",
        "javascript.jsx",
        "typescript",
        "typescriptreact",
        "typescript.tsx",
        "vue",
    },
})

I'm getting the following error message in my logs: [ERROR][2024-04-22 12:10:01] ...lsp/handlers.lua:535 "TSServer exited. Code: null. Signal: SIGTERM" Edit: got it working by setting configNamespace to typescript(see config)

sdvcrx commented 2 months ago

@jordycoding vtsls.tsserver.globalPlugins needs to be placed under settings too.

My example config:

lspconfig.volar.setup {
  on_attach = on_attach,
  capabilities = capabilities,
}

lspconfig.vtsls.setup {
  filetypes = { 'typescript', 'javascript', 'javascriptreact', 'typescriptreact', 'vue' },
  settings = {
    vtsls = {
      -- autoUseWorkspaceTsdk = true,
      tsserver = {
        globalPlugins = {
          {
            name = '@vue/typescript-plugin',
            location = vue_language_server_path,
            languages = { 'vue' },
            configNamespace = "typescript",
            enableForWorkspaceTypeScriptVersions = true,
          },
        },
      },
    },
  },
  on_attach = on_attach,
  capabilities = capabilities,
}
samerickson commented 2 months ago

For anyone looking for a LazyVim spec:

return {
  {
    "nvim-treesitter/nvim-treesitter",
    opts = function(_, opts)
      if type(opts.ensure_installed) == "table" then
        vim.list_extend(opts.ensure_installed, { "typescript", "tsx" })
      end
    end,
  },
  {
    "williamboman/mason.nvim",
    opts = function(_, opts)
      opts.ensure_installed = opts.ensure_installed or {}
      table.insert(opts.ensure_installed, "vue-language-server")

      require("mason").setup()
    end,
  },
  {
    "neovim/nvim-lspconfig",
    opts = function(_, opts)
      opts.servers["volar"] = {
        enabled = true,
      }

      opts.servers["vtsls"] = {
        enabled = true,
        filetypes = { "typescript", "javascript", "javascriptreact", "typescriptreact", "vue" },
        settings = {
          vtsls = {
            tsserver = {
              globalPlugins = {
                {
                  name = "@vue/typescript-plugin",
                  location = require("mason-registry").get_package("vue-language-server"):get_install_path()
                    .. "/node_modules/@vue/language-server",
                  languages = { "vue" },
                  configNamespace = "typescript",
                  enableForWorkspaceTypeScriptVersions = true,
                },
              },
            },
          },
        },
      }
    end,
  },
}
mcchrish commented 1 month ago

Some already made it work with project local settings?

I get the error vtsls: -32603: Cannot find provider for the feature.

My config:

lspconfig.vtsls.setup {
    filetypes = { "typescript", "javascript", "javascriptreact", "typescriptreact", "vue" },
    capabilities = capabilities,
    settings = {
        vtsls = { tsserver = { globalPlugins = {} } },
    },
    on_init = function(client)
        local result = vim.system(
            { "npm", "query", ":root" },
            { cwd = client.workspace_folders[1].name, text = true }
        ):wait()
        if result.stdout ~= "[]" then
            local vuePluginConfig = {
                name = "@vue/typescript-plugin",
                location = require("mason-registry").get_package("vue-language-server"):get_install_path()
                    .. "/node_modules/@vue/language-server",
                languages = { "vue" },
                configNamespace = "typescript",
                enableForWorkspaceTypeScriptVersions = true,
            }
            client.config.settings.vtsls.tsserver.globalPlugins = { vuePluginConfig }
            client.notify("workspace/didChangeConfiguration", { settings = client.config.settings })
        end
        return true
    end,
    on_attach = function(client)
        client.server_capabilities.documentFormattingProvider = false
        client.server_capabilities.documentRangeFormattingProvider = false
    end,
}
yioneko commented 1 month ago

@mcchrish Try to use before_init:

lspconfig.vtsls.setup {
    filetypes = { "typescript", "javascript", "javascriptreact", "typescriptreact", "vue" },
    capabilities = capabilities,
    settings = {
        vtsls = { tsserver = { globalPlugins = {} } },
    },
    before_init = function(_, config)
        local result = vim.system(
            { "npm", "query", ":root" },
            { cwd = client.workspace_folders[1].name, text = true }
        ):wait()
        if result.stdout ~= "[]" then
            local vuePluginConfig = {
                name = "@vue/typescript-plugin",
                location = require("mason-registry").get_package("vue-language-server"):get_install_path()
                    .. "/node_modules/@vue/language-server",
                languages = { "vue" },
                configNamespace = "typescript",
                enableForWorkspaceTypeScriptVersions = true,
            }
            config.settings.vtsls.tsserver.globalPlugins = { vuePluginConfig }
        end
    end
}

New language providers could not be correctly registered with new plugins updated from workspace/didChangeConfiguration, which is a known bug in upstream typescript extension.

mcchrish commented 1 month ago
lspconfig.vtsls.setup {
    filetypes = { "typescript", "javascript", "javascriptreact", "typescriptreact", "vue" },
    settings = {
        vtsls = { tsserver = { globalPlugins = {} } },
    },
    before_init = function(params, config)
        local result = vim.system(
            { "npm", "query", "#vue" },
            { cwd = params.workspaceFolders[1].name, text = true }
        ):wait()
        if result.stdout ~= "[]" then
            local vuePluginConfig = {
                name = "@vue/typescript-plugin",
                location = require("mason-registry").get_package("vue-language-server"):get_install_path()
                    .. "/node_modules/@vue/language-server",
                languages = { "vue" },
                configNamespace = "typescript",
                enableForWorkspaceTypeScriptVersions = true,
            }
            table.insert(config.settings.vtsls.tsserver.globalPlugins, vuePluginConfig)
        end
    end,
}

Thanks @yioneko! This now works.

For anyone interested, this setup checks whether vue is installed before adding the plugin.