mirror of
https://github.com/neovim/nvim-lspconfig.git
synced 2025-12-24 15:01:00 +01:00
156 lines
5.9 KiB
Lua
156 lines
5.9 KiB
Lua
---@brief
|
|
---
|
|
--- https://github.com/typescript-language-server/typescript-language-server
|
|
---
|
|
--- `ts_ls`, aka `typescript-language-server`, is a Language Server Protocol implementation for TypeScript wrapping `tsserver`. Note that `ts_ls` is not `tsserver`.
|
|
---
|
|
--- `typescript-language-server` depends on `typescript`. Both packages can be installed via `npm`:
|
|
--- ```sh
|
|
--- npm install -g typescript typescript-language-server
|
|
--- ```
|
|
---
|
|
--- To configure typescript language server, add a
|
|
--- [`tsconfig.json`](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) or
|
|
--- [`jsconfig.json`](https://code.visualstudio.com/docs/languages/jsconfig) to the root of your
|
|
--- project.
|
|
---
|
|
--- Here's an example that disables type checking in JavaScript files.
|
|
---
|
|
--- ```json
|
|
--- {
|
|
--- "compilerOptions": {
|
|
--- "module": "commonjs",
|
|
--- "target": "es6",
|
|
--- "checkJs": false
|
|
--- },
|
|
--- "exclude": [
|
|
--- "node_modules"
|
|
--- ]
|
|
--- }
|
|
--- ```
|
|
---
|
|
--- Use the `:LspTypescriptSourceAction` command to see "whole file" ("source") code-actions such as:
|
|
--- - organize imports
|
|
--- - remove unused code
|
|
---
|
|
--- Use the `:LspTypescriptGoToSourceDefinition` command to navigate to the source definition of a symbol (e.g., jump to the original implementation instead of type definitions).
|
|
---
|
|
--- ### Monorepo support
|
|
---
|
|
--- `ts_ls` supports monorepos by default. It will automatically find the `tsconfig.json` or `jsconfig.json` corresponding to the package you are working on.
|
|
--- This works without the need of spawning multiple instances of `ts_ls`, saving memory.
|
|
---
|
|
--- It is recommended to use the same version of TypeScript in all packages, and therefore have it available in your workspace root. The location of the TypeScript binary will be determined automatically, but only once.
|
|
---
|
|
|
|
---@type vim.lsp.Config
|
|
return {
|
|
init_options = { hostInfo = 'neovim' },
|
|
cmd = { 'typescript-language-server', '--stdio' },
|
|
filetypes = {
|
|
'javascript',
|
|
'javascriptreact',
|
|
'javascript.jsx',
|
|
'typescript',
|
|
'typescriptreact',
|
|
'typescript.tsx',
|
|
},
|
|
root_dir = function(bufnr, on_dir)
|
|
-- The project root is where the LSP can be started from
|
|
-- As stated in the documentation above, this LSP supports monorepos and simple projects.
|
|
-- We select then from the project root, which is identified by the presence of a package
|
|
-- manager lock file.
|
|
local root_markers = { 'package-lock.json', 'yarn.lock', 'pnpm-lock.yaml', 'bun.lockb', 'bun.lock' }
|
|
-- Give the root markers equal priority by wrapping them in a table
|
|
root_markers = vim.fn.has('nvim-0.11.3') == 1 and { root_markers, { '.git' } }
|
|
or vim.list_extend(root_markers, { '.git' })
|
|
-- exclude deno
|
|
local deno_path = vim.fs.root(bufnr, { 'deno.json', 'deno.jsonc', 'deno.lock' })
|
|
local project_root = vim.fs.root(bufnr, root_markers)
|
|
if deno_path and (not project_root or #deno_path >= #project_root) then
|
|
return
|
|
end
|
|
-- We fallback to the current working directory if no project root is found
|
|
on_dir(project_root or vim.fn.getcwd())
|
|
end,
|
|
handlers = {
|
|
-- handle rename request for certain code actions like extracting functions / types
|
|
['_typescript.rename'] = function(_, result, ctx)
|
|
local client = assert(vim.lsp.get_client_by_id(ctx.client_id))
|
|
vim.lsp.util.show_document({
|
|
uri = result.textDocument.uri,
|
|
range = {
|
|
start = result.position,
|
|
['end'] = result.position,
|
|
},
|
|
}, client.offset_encoding)
|
|
vim.lsp.buf.rename()
|
|
return vim.NIL
|
|
end,
|
|
},
|
|
commands = {
|
|
['editor.action.showReferences'] = function(command, ctx)
|
|
local client = assert(vim.lsp.get_client_by_id(ctx.client_id))
|
|
local file_uri, position, references = unpack(command.arguments)
|
|
|
|
local quickfix_items = vim.lsp.util.locations_to_items(references --[[@as any]], client.offset_encoding)
|
|
vim.fn.setqflist({}, ' ', {
|
|
title = command.title,
|
|
items = quickfix_items,
|
|
context = {
|
|
command = command,
|
|
bufnr = ctx.bufnr,
|
|
},
|
|
})
|
|
|
|
vim.lsp.util.show_document({
|
|
uri = file_uri --[[@as string]],
|
|
range = {
|
|
start = position --[[@as lsp.Position]],
|
|
['end'] = position --[[@as lsp.Position]],
|
|
},
|
|
}, client.offset_encoding)
|
|
---@diagnostic enable: assign-type-mismatch
|
|
|
|
vim.cmd('botright copen')
|
|
end,
|
|
},
|
|
on_attach = function(client, bufnr)
|
|
-- ts_ls provides `source.*` code actions that apply to the whole file. These only appear in
|
|
-- `vim.lsp.buf.code_action()` if specified in `context.only`.
|
|
vim.api.nvim_buf_create_user_command(bufnr, 'LspTypescriptSourceAction', function()
|
|
local source_actions = vim.tbl_filter(function(action)
|
|
return vim.startswith(action, 'source.')
|
|
end, client.server_capabilities.codeActionProvider.codeActionKinds)
|
|
|
|
vim.lsp.buf.code_action({
|
|
context = {
|
|
only = source_actions,
|
|
diagnostics = {},
|
|
},
|
|
})
|
|
end, {})
|
|
|
|
-- Go to source definition command
|
|
vim.api.nvim_buf_create_user_command(bufnr, 'LspTypescriptGoToSourceDefinition', function()
|
|
local win = vim.api.nvim_get_current_win()
|
|
local params = vim.lsp.util.make_position_params(win, client.offset_encoding)
|
|
client:exec_cmd({
|
|
command = '_typescript.goToSourceDefinition',
|
|
title = 'Go to source definition',
|
|
arguments = { params.textDocument.uri, params.position },
|
|
}, { bufnr = bufnr }, function(err, result)
|
|
if err then
|
|
vim.notify('Go to source definition failed: ' .. err.message, vim.log.levels.ERROR)
|
|
return
|
|
end
|
|
if not result or vim.tbl_isempty(result) then
|
|
vim.notify('No source definition found', vim.log.levels.INFO)
|
|
return
|
|
end
|
|
vim.lsp.util.show_document(result[1], client.offset_encoding, { focus = true })
|
|
end)
|
|
end, { desc = 'Go to source definition' })
|
|
end,
|
|
}
|