nvim-lspでtsserverとdenolsの競合を回避する
追記
本記事の設定ですが、公開後にnvim -c "edit #<1"
で直近のファイルを開いたとき正常に動作しない例があることが判明しました。不正確な内容で公開してしまい、申し訳ありません。
この記事は残しておきますが、ご利用の際は、エラーが出る場合があることをご認識ください。
また、エラーなく設定できる方法をご存じの方は、コメント等いただけると大変ありがたいです。
現代のコーディングにおいて、LSPの支援は非常に有用です。
筆者は、Neovim環境で、nvim-lspconfigとnvim-lsp-installerを使って各種LSPをインストールしています。
基本的には言語に対応したLSPを導入すれば問題なく動くのですが、TypeScriptではNode開発用のtsserverとDeno開発用のdenolsの2種類があり、これらを同時に入れると意図しないエラーが出る場合があります。
例えば、tsserverを有効にした状態でDenoプロジェクトのコードを開くと次のようにエラーが出てしまいます。
Deno環境では問題のないコード
- インポート指定に拡張子をつけちゃダメだよ
-
Deno
は定義されてないよ -
Object.hasOwn
は定義されてないよ -
await
はトップレベルでは使えないよ
これらのエラーを回避するためにLSPをアンインストールするのは現実的ではありません。
同じ.ts
ファイルでも、ディレクトリの状況によってtsserverとdenolsのいずれを使うか判定し、有効にするLSPを切り替えたいところです。
本記事ではこの設定を紹介します。
tsserverとdenolsを出し分ける設定
Nodeプロジェクトの配下ではtsserver(およびeslint)を、それ以外ではdenolsを起動するための設定がこちらです。
local nvim_lsp = require('lspconfig')
local lsp_installer = require("nvim-lsp-installer")
local node_root_dir = nvim_lsp.util.root_pattern("package.json", "node_modules")
local buf_name = vim.api.nvim_buf_get_name(0)
local current_buf = vim.api.nvim_get_current_buf()
local is_node_repo = node_root_dir(buf_name, current_buf) ~= nil
lsp_installer.on_server_ready(function(server)
local opts = {}
if server.name == "tsserver" or server.name == "eslint" then
opts.autostart = is_node_repo
elseif server.name == "denols" then
opts.autostart = not(is_node_repo)
-- 以下は出し分けとは関係ないが設定しておくのがオススメ
opts.init_options = { lint = true, unstable = true, }
end
server:setup(opts)
vim.cmd [[ do User LspAttachBuffers ]]
end)
nvim-lsp-installerを使っている場合、サーバーを起動させるためにon_server_ready()
を書いていると思うので、そこに上記の設定を組み込んでください。
なお、local
を使って逐一変数定義を行っていますが、これは記事上での見やすさを意識したものです。変数に代入せず一行で書いても問題ありません。
解説
nvim_lsp.util.root_pattern()
は、nvim-lspconfigにおいて各LSPの起動時のルートディレクトリを決めるために使われている関数です。
これは高階関数で、使用時には引数としてvim.api.nvim_buf_get_name(0)
とvim.api.nvim_get_current_buf()
を受け取ります。この使い方は実際のコードを参考にしました。
これにより、上記コードのnode_root_dir(buf_name, current_buf)
で、現在開いているファイルと同一ディレクトリまたは先祖ディレクトリにpackage.json
またはnode_modules
があればそのパスを、なければnil
が得られます。
さらに~= nil
で比較して真偽値に変え、各LSPのautostart
へ設定しています。
この際、片方にnot()
をつけることで、tsserverとdenolsのどちらかしか起動しないようにしています。
上記ではとりあえずpackage.json
とnode_modules
を基準にしていますが、package-lock.json
やyarn.lock
なども使えるでしょう。
また、逆にdenols側を基準にする場合は、deno.json
やdeps.ts
を使うと良いと思います。
おわりに
Neovim Builtin LSPでtsserverとdenolsの競合を回避する設定について解説しました。
Node.jsとDenoの両方の環境で開発する機会のある方はお試しください。
おまけ coc.nvimの場合
.vim/coc-settings.json
に設定を書くと読み込まれます。
Author And Source
この問題について(nvim-lspでtsserverとdenolsの競合を回避する), 我々は、より多くの情報をここで見つけました https://zenn.dev/kawarimidoll/articles/2b57745045b225著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Collection and Share based on the CC protocol