DEV Community

Davide Cavaliere
Davide Cavaliere

Posted on • Edited on

Avoid conflicts between denols and tsserver in Neovim

Recently I've been working on a project in a monorepo were I've got nodejs/typescript and deno projects. This is notoriously annoying because any ts file will start both tsserver and denols language services.

If you've got here you know what I'm talking about πŸ˜“

I'm setting up my lsp with lspconfig.

This is how denols is configured

lspconfig.denols.setup({
  root_dir = lspconfig.util.root_pattern("deno.json", "deno.jsonc"),
  init_options = {
    lint = true,
    unstable = true,
    suggest = {
      imports = {
        hosts = {
          ["https://deno.land"] = true,
          ["https://cdn.nest.land"] = true,
          ["https://crux.land"] = true,
        },
      },
    },
  },

  on_attach = on_attach,
})

Enter fullscreen mode Exit fullscreen mode

And this is the hack to avoid tsserver to start on a file that belongs to a deno project.

spconfig.tsserver.setup({
  on_attach = function (client, bufnr)
    on_attach(client, bufnr);
    vim.keymap.set('n', '<leader>ro', function()
      vim.lsp.buf.execute_command({
        command = "_typescript.organizeImports",
        arguments = { vim.fn.expand("%:p") }
      })
    end, { buffer = bufnr,  remap = false });
  end,
  root_dir = function (filename, bufnr)
    local denoRootDir = lspconfig.util.root_pattern("deno.json", "deno.json")(filename);
    if denoRootDir then
      -- print('this seems to be a deno project; returning nil so that tsserver does not attach');
      return nil;
    -- else
      -- print('this seems to be a ts project; return root dir based on package.json')
    end

    return lspconfig.util.root_pattern("package.json")(filename);
  end,
  single_file_support = false,
})
Enter fullscreen mode Exit fullscreen mode

This leverage the fact that if root_dir function returns nil then lspconfig wont's start a language service for that file. πŸŽ‰

Top comments (0)