Skip to content

Using typescript plugins through neovim-lsp #277

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

Closed
non25 opened this issue Oct 31, 2021 · 10 comments
Closed

Using typescript plugins through neovim-lsp #277

non25 opened this issue Oct 31, 2021 · 10 comments

Comments

@non25
Copy link

non25 commented Oct 31, 2021

Hi, thanks for the work. 🙂

It seems that I can't find a way to make plugins like typescript-plugin-css-modules, or typescript-svelte-plugin work through neovim-lsp.

I tried to configure them through tsconfig.json like this
{
  "compilerOptions": {
    "target": "esnext",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "baseUrl": "src",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "importHelpers": true,
    "isolatedModules": true,
    "module": "esnext",
    "moduleResolution": "node",
    "noEmitOnError": true,
    "noFallthroughCasesInSwitch": true,
    "resolveJsonModule": true,
    "skipLibCheck": false,
    "strict": true,
    "importsNotUsedAsValues": "error",
    "sourceMap": true,
    "typeRoots": [
      "./types",
      "./node_modules/@types"
    ],
    "types": [
      "svelte"
    ],
    "plugins": [{
      "name": "typescript-svelte-plugin"
    }],
  },
  "include": [
    "src/**/*"
  ],
  "exclude": [
    "node_modules/**/*"
  ],
}
and also through neovim lsp config
local on_attach = function(client, bufnr)
  local function buf_set_keymap(...) vim.api.nvim_buf_set_keymap(bufnr, ...) end
  local function buf_set_option(...) vim.api.nvim_buf_set_option(bufnr, ...) end

  require'completion'.on_attach();

  buf_set_option('omnifunc', 'v:lua.vim.lsp.omnifunc')

  local opts = { noremap=true, silent=true }
  buf_set_keymap('n', 'gd', '<Cmd>lua vim.lsp.buf.definition()<CR>', opts)
  buf_set_keymap('n', 'gD', '<cmd>lua vim.lsp.buf.type_definition()<CR>', opts)
  buf_set_keymap('n', 'ga', '<Cmd>lua vim.lsp.buf.code_action()<CR>', opts)
  buf_set_keymap('n', 'K', '<Cmd>lua vim.lsp.buf.hover()<CR>', opts)
  buf_set_keymap('n', 'gr', '<cmd>lua vim.lsp.buf.rename()<CR>', opts)
  buf_set_keymap('n', 'gR', '<cmd>lua vim.lsp.buf.references()<CR>', opts)
  buf_set_keymap('n', 'gc', '<cmd>lua vim.lsp.diagnostic.show_line_diagnostics()<CR>', opts)
end

local ts_utils_on_attach = function(client, bufnr)
  on_attach(client, bufnr)
  local ts_utils = require("nvim-lsp-ts-utils")

  ts_utils.setup {
    import_all_timeout = 15000,
    import_all_select_source = true,

    eslint_enable_code_actions = true,
    eslint_enable_disable_comments = true,
    eslint_bin = "eslint_d",
    eslint_enable_diagnostics = true,

    filter_out_diagnostics_by_code = { 80001 }
  }

  ts_utils.setup_client(client)
end

lspconfig.tsserver.setup{
  cmd = { "yarn", "typescript-language-server", "--stdio" };
  on_attach = ts_utils_on_attach;
  init_options = {
    plugins = {
      {
        name = "typescript-svelte-plugin";
      };
    };
  };
}

Can't see expected plugin functionality by doing that. Other LS functionality works fine.

Any help appreciated, thanks. 🙂

@rchl
Copy link
Member

rchl commented Oct 31, 2021

Haven't tried personally but README.md mentions that you need to specify the plugin location also:

Screenshot 2021-10-31 at 23 33 40

I believe it's a location of a directory and not the plugin itself.
The location corresponds to --pluginProbeLocations tsserver option so you could try to google that further if you still have problems.

@non25
Copy link
Author

non25 commented Oct 31, 2021

Having plugins in tsconfig.json shouldn't work, right?

I tried using name as location and yarn's location like this:

  init_options = {
    plugins = {
      {
        name = "typescript-svelte-plugin";
        location = "./.yarn/unplugged/typescript-svelte-plugin-npm-0.2.5-0efec0bddd/node_modules/typescript-svelte-plugin/";
      };
    };
  };

No success. Even with direct path to index.js as a location.

Googled pluginProbeLocations, results don't seem to be straightforward to use. 🤔

@rchl
Copy link
Member

rchl commented Nov 1, 2021

Can you provide a simple project that I can test this on?

@zhoudaxia2016
Copy link

try ./.yarn/unplugged/typescript-svelte-plugin-npm-0.2.5-0efec0bddd/ @non25

@non25
Copy link
Author

non25 commented Nov 7, 2021

Both plugins work fine in simple project which I made for testing.
And tsconfig.json is enough to start them. No explicit configuration in the editor for LS is needed.
Actually removing init_options from neovim configuration stopped plugins from working. Strange stuff.
The interesting part is that location is pointing to non-existing directory, and that make both plugins work somehow.
Even more interesting part is that I don't specify css-modules plugin in both neovim config and tsconfig.json and somehow it picks it up. 😮
Will post an update once I realize why it doesn't work in regular projects. 🤷‍♂️

@non25
Copy link
Author

non25 commented Nov 7, 2021

Here's my testbench: https://github.com/non25/typescript-ls-testbench
I feel like there's something fishy going on with tsconfig.json and editor-passed init_options. 🤔

My observation is that tsconfig.json plugins section works only if init_options.plugins is populated with at least one object like this:

{
  name: "anything-non-empty",
  location: "anything-non-empty"
}

Language server plugin can also work without being specified in tsconfig.json, name should be correctly specified and location can be any non-empty string.
I guess it looks it up using node's resolution.

@rchl
Copy link
Member

rchl commented Nov 7, 2021

I gues you've probably seen the code handling this in this server but if not I'll just mention that it passes names of the plugins through the --globalPlugins option and the locations through the --pluginProbeLocations option. So I would guess that some non-existing location might be OK if typescript anyway does some default lookup in node_modules.

Here is relevant typescript's code for loading the plugins: https://github.com/microsoft/TypeScript/blob/39ff1568e9676d40cf545477e9fd04077eff9b78/src/server/project.ts#L2277-L2295

With your example project, it works for me without having any plugin specified in init_options.

For example here is with only typescript-svelte-plugin enable in tsconfig.json:

Screenshot 2021-11-07 at 20 46 58

And with typescript-plugin-css-modules enabled I also get an error on style.class2 line.

@non25
Copy link
Author

non25 commented Nov 7, 2021

It is really strange that plugins stop working once I remove init_options, or even location with garbage path from neovim config:

lspconfig.tsserver.setup{
  handlers = {
    ["textDocument/definition"] = require('tsreact').handle_gtd
  };
  cmd = { "yarn", "typescript-language-server", "--stdio" };
  on_attach = ts_utils_on_attach;

  -- these guys
  init_options = {
    plugins = {
      {
        name = "anything";
        location = "anything";
      };
    };
  };
  --

}

https://asciinema.org/a/CLmXeVsYki4X5EJPlKwkwV7yW 🤷‍♂️

Feel free to close I guess, thanks for the help.
Will go with this strange workaround, at least it works for me now. 🙂

@rchl
Copy link
Member

rchl commented Nov 8, 2021

If there is a way to log the whole LSP communication with the server then that might reveal something.

Might be useful to log both the logs with and without init_options. Or at least without.

@rchl
Copy link
Member

rchl commented Nov 8, 2021

I don't use neovim but I did make an effort to set it up and test with your project and it's working for me even without init_options defined so I will close this issue.

For reference, I've tried with the options below. Tried both with and without init_options but removed the handlers configuration since I was missing some reference there.

syntax on

" Specify a directory for plugins
" - For Neovim: stdpath('data') . '/plugged'
" - Avoid using standard Vim directory names like 'plugin'
call plug#begin('~/.vim/plugged')

" Make sure you use single quotes

Plug 'neovim/nvim-lspconfig'

" Initialize plugin system
call plug#end()

lua << EOF
require'lspconfig'.tsserver.setup{}

vim.lsp.set_log_level("debug")

local lspconfig = require('lspconfig')

lspconfig.tsserver.setup{
  cmd = { "yarn", "typescript-language-server", "--stdio" };
  on_attach = ts_utils_on_attach;

  -- these guys
  init_options = {
    plugins = {
      {
        name = "anything";
        location = "anything";
      };
    };
  };
  --

}

EOF

@rchl rchl closed this as completed Nov 8, 2021
samhh added a commit to samhh/dotfiles that referenced this issue Dec 10, 2022
Seems like TS really wants it to exist in a node_modules/ dir. This is
the most useful info I found:
  typescript-language-server/typescript-language-server#277
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

3 participants