Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support @vue/typescript-plugin #148

Open
mcchrish opened this issue Mar 21, 2024 · 13 comments
Open

Support @vue/typescript-plugin #148

mcchrish opened this issue Mar 21, 2024 · 13 comments

Comments

@mcchrish
Copy link

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
Copy link
Owner

yioneko commented Mar 21, 2024

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
Copy link
Owner

yioneko commented Mar 22, 2024

@mcchrish Could you test the version 0.2.2-alpha.1? An option vtsls.tsserver.globalPlugins is introduced for the vue plugin support:

vtsls/README.md

Lines 136 to 152 in 6cdfdac

### Vue Support via Hybrid Mode of [`volar >= 2.0`](https://github.com/vuejs/language-tools/tree/master/packages/typescript-plugin)
Suppose `@vue/language-server` has been installed through package manager, then set configuration option `vtsls.tsserver.globalPlugins` to:
```json
[
{
"name": "@vue/typescript-plugin",
"location": "/usr/local/lib/node_modules/@vue/language-server",
"languages": ["vue"],
"configNamespace": "typescript",
"enableForWorkspaceTypeScriptVersions": true,
}
]
```
`location` field can be omitted if it can be resolved globally through the `Node` used to run the server.

@mcchrish
Copy link
Author

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

@mcchrish
Copy link
Author

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
Copy link
Owner

yioneko commented Mar 28, 2024

@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
Copy link
Owner

yioneko commented Mar 28, 2024

Just FYI: The Vue language support seems to be suffering problems right now, as you can look into its issues and vuejs/language-tools#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): williamboman/mason-lspconfig.nvim#371 (comment).

@mcchrish
Copy link
Author

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

jordycoding commented Apr 22, 2024

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

sdvcrx commented Apr 23, 2024

@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
Copy link

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
Copy link
Author

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
Copy link
Owner

yioneko commented May 20, 2024

@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
Copy link
Author

mcchrish commented May 20, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants