## 事象 [[Vue3]]のREADMEに従って作成したプロジェクトを開いても、[[Volar]]が機能しない ([[LSP]]として何も反応しない)。ただ、`LspInfo`コマンドを実行すると、[[Volar]]がattachされていることは確認できる。 [[nvim-lspconfig]]に関する設定部分は以下。 ```lua { "neovim/nvim-lspconfig", dependencies = { { "hrsh7th/cmp-nvim-lsp" }, { "hrsh7th/nvim-cmp" }, { "hrsh7th/cmp-buffer" }, { "hrsh7th/cmp-path" }, { "hrsh7th/cmp-cmdline" }, { "b0o/schemastore.nvim" }, { "onsails/lspkind.nvim" }, { "L3MON4D3/LuaSnip" }, { "saadparwaiz1/cmp_luasnip" }, }, config = function() -- 中略 ---------------------------------- -- lspconfig ---------------------------------- local lspconfig = require("lspconfig") require("lspconfig.ui.windows").default_options.border = "single" local capabilities = require("cmp_nvim_lsp").default_capabilities() capabilities.textDocument.completion.completionItem.snippetSupport = true -- 中略 -- -- [Volar] localのnode_modulesを優先する local util = require("lspconfig.util") local function get_typescript_server_path(root_dir) local home = os.getenv("HOME") local global_ts = home .. "/.local/share/mise/installs/node/18/lib/node_modules/typescript/lib" local found_ts = "" local function check_dir(path) found_ts = util.path.join(path, "node_modules", "typescript", "lib") if util.path.exists(found_ts) then return path end end if util.search_ancestors(root_dir, check_dir) then return found_ts else return global_ts end end local function organize_imports() local params = { command = "_typescript.organizeImports", arguments = { vim.api.nvim_buf_get_name(0) }, title = "", } vim.lsp.buf.execute_command(params) end local function is_vue_or_nuxt() -- wxt.config.tsはvue以外もあるけど... return util.root_pattern("vite.config.ts", "nuxt.config.ts", "nuxt.config.js", "wxt.config.ts") end -- VueやNuxtのプロジェクトでのみ有効にする lspconfig.volar.setup({ filetypes = { "typescript", "javascript", "javascriptreact", "typescriptreact", "vue", "json" }, capabilities = capabilities, root_dir = is_vue_or_nuxt(), on_new_config = function(new_config, new_root_dir) new_config.init_options.typescript.tsdk = get_typescript_server_path(new_root_dir) end, }) -- VueやNuxtのプロジェクトでなければtsserverを使う lspconfig.tsserver.setup({ capabilities = capabilities, single_file_support = false, root_dir = function(fname) -- VueやNuxtのプロジェクトではVolarに任せるので無効にする if is_vue_or_nuxt()(fname) then return nil end return util.root_pattern("tsconfig.json")(fname) end, commands = { OrganizeImports = { organize_imports, }, }, }) ``` ## 原因 [[Volar]]がv2.0になり、[[TypeScript]]の[[LSP]]を内包しなくなったから。 ## 解決方法 ### [[Hybrid Mode]]を使用する場合 [[Volar]]をsetupしたあと、[[tsserver]]のsetupで`plugins`に[[@vue typescript-plugin]]を指定する。ここではグローバルにインストールした`@vue/language-server`が依存する`@vue/typescript-plugin`を指定している。そのため、別途`@vue/typescript-plugin`をインストールする必要はない。 ```lua { "neovim/nvim-lspconfig", config = function() -- 中略 ---------------------------------- -- lspconfig ---------------------------------- local lspconfig = require("lspconfig") require("lspconfig.ui.windows").default_options.border = "single" local capabilities = require("cmp_nvim_lsp").default_capabilities() capabilities.textDocument.completion.completionItem.snippetSupport = true -- 中略 -- local home = os.getenv("HOME") local function organize_imports() local params = { command = "_typescript.organizeImports", arguments = { vim.api.nvim_buf_get_name(0) }, title = "", } vim.lsp.buf.execute_command(params) end lspconfig.volar.setup({ capabilities = capabilities, }) lspconfig.tsserver.setup({ capabilities = capabilities, single_file_support = false, init_options = { plugins = { { name = "@vue/typescript-plugin", location = home .. "/.local/share/mise/installs/node/20/lib/node_modules/@vue/language-server", languages = { "javascript", "typescript", "vue" }, }, }, }, commands = { OrganizeImports = { organize_imports, }, }, filetypes = { "javascript", "typescript", "vue", }, }) ``` ### [[Hybrid Mode]]を使用しない場合 [[Volar]]だけで[[Vue]]も[[TypeScript]]も対応できる構成となり、設定は一番シンプル。気になるのは、[[tsserver]]の機能が先行したとき、[[Volar]]の対応が少し遅れるかもしれないくらい。 ```lua { "neovim/nvim-lspconfig", config = function() -- 中略 ---------------------------------- -- lspconfig ---------------------------------- local lspconfig = require("lspconfig") require("lspconfig.ui.windows").default_options.border = "single" local capabilities = require("cmp_nvim_lsp").default_capabilities() capabilities.textDocument.completion.completionItem.snippetSupport = true -- 中略 -- lspconfig.volar.setup({ capabilities = capabilities, filetypes = { "typescript", "javascript", "javascriptreact", "typescriptreact", "vue" }, init_options = { vue = { hybridMode = false, }, }, }) ``` ## 参考 - [Version 2 stop working with nvim lsp · Issue \#3925 · vuejs/language\-tools](https://github.com/vuejs/language-tools/issues/3925) - [nvim\-lspconfig/doc/server\_configurations\.md at master · neovim/nvim\-lspconfig](https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#tsserver) - [docs: update readme with neovim lspconfig setup by RayGuo-ergou · Pull Request #4134 · vuejs/language-tools](https://github.com/vuejs/language-tools/pull/4134/files)