Sanchayan Maity
0c9e0eb164
It produces somewhat bad syntax highlighting in some cases. For example, in typescript, the variable and it's type annotation get the same colour.
228 lines
7.5 KiB
Lua
228 lines
7.5 KiB
Lua
local protocol = require 'vim.lsp.protocol'
|
|
local lightbulb = require 'nvim-lightbulb'
|
|
local inlay_hint = require 'lsp-inlayhints'
|
|
|
|
-- Set up inlay hints
|
|
inlay_hint.setup({
|
|
inlay_hints = {
|
|
highlight = "Hint"
|
|
}
|
|
})
|
|
|
|
vim.lsp.set_log_level("off")
|
|
|
|
local function preview_location_callback(_, result)
|
|
if result == nil or vim.tbl_isempty(result) then
|
|
return nil
|
|
end
|
|
vim.lsp.util.preview_location(result[1])
|
|
end
|
|
|
|
function PeekDefinition()
|
|
local params = vim.lsp.util.make_position_params()
|
|
return vim.lsp.buf_request(0, 'textDocument/definition', params, preview_location_callback)
|
|
end
|
|
|
|
protocol.CompletionItemKind = {
|
|
' Text' ;
|
|
' Method' ;
|
|
' Function' ;
|
|
'全Constructor' ;
|
|
' Field' ;
|
|
' Variable' ;
|
|
' Class' ;
|
|
' Interface' ;
|
|
' Module' ;
|
|
' Property' ;
|
|
' Unit' ;
|
|
' Value' ;
|
|
' Enum' ;
|
|
' Keyword' ;
|
|
' Snippet' ;
|
|
' Color' ;
|
|
' File' ;
|
|
' Reference' ;
|
|
' Folder' ;
|
|
' EnumMember' ;
|
|
' Constant' ;
|
|
' Struct' ;
|
|
' Event' ;
|
|
' Operator' ;
|
|
' TypeParameter';
|
|
}
|
|
|
|
local lsp_augroup_id = vim.api.nvim_create_augroup("LSP", { clear = true })
|
|
|
|
local lsp_key_mappings = {
|
|
{ "definitionProvider" , 'n', 'pd' , '<cmd>lua PeekDefinition()<CR>' },
|
|
{ "definitionProvider" , 'n', 'gd' , '<cmd>lua vim.lsp.buf.definition()<CR>' },
|
|
{ "declarationProvider" , 'n', 'gD' , '<cmd>lua vim.lsp.buf.declaration()<CR>' },
|
|
{ "typeDefinitionProvider" , 'n', '<C-k>' , '<cmd>lua vim.lsp.buf.type_definition()<CR>' },
|
|
{ "referencesProvider" , 'n', 'gr' , '<cmd>lua vim.lsp.buf.references()<CR>' },
|
|
{ "implementationProvider" , 'n', 'gi' , '<cmd>lua vim.lsp.buf.implementation()<CR>' },
|
|
{ "documentSymbolProvider" , 'n', '1gd' , '<cmd>lua vim.lsp.buf.document_symbol()<CR>' },
|
|
{ "workspaceSymbolProvider", 'n', '1gD' , '<cmd>lua vim.lsp.buf.workspace_symbol()<CR>' },
|
|
{ "hoverProvider" , 'n', '<Leader>k', '<cmd>lua vim.lsp.buf.hover()<CR>' },
|
|
{ "signatureHelpProvider" , 'n', '<Leader>S', '<cmd>lua vim.lsp.buf.signature_help()<CR>' },
|
|
{ "renameProvider" , 'n', 'gR' , '<cmd>lua vim.lsp.buf.rename()<CR>' },
|
|
|
|
{ "documentRangeFormattingProvider", 'x', 'gq', '<cmd>lua vim.lsp.buf.format({async=true})<CR>' },
|
|
{ "documentFormattingProvider" , 'n', 'gq', '<cmd>lua vim.lsp.buf.format({async=true})<CR>' },
|
|
|
|
{ "codeActionProvider", 'n', 'ga' , '<cmd>lua vim.lsp.buf.code_action()<CR>' },
|
|
{ "codeActionProvider", 'v', 'ga' , '<cmd>lua vim.lsp.buf.code_action()<CR>' },
|
|
{ "codeActionProvider", 'n', '<Leader>r', '<cmd>lua vim.lsp.buf.code_action{only = \'refactor\' }<CR>' },
|
|
{ "codeActionProvider", 'v', '<Leader>r', '<cmd>lua vim.lsp.buf.code_action{only = \'refactor\' }<CR>' },
|
|
|
|
{ "codeLensProvider", 'n', '<LocalLeader>l', '<cmd>lua vim.lsp.codelens.run()<CR>' },
|
|
{ "codeLensProvider", 'n', '<LocalLeader>L', '<cmd>lua vim.lsp.codelens.clear()<CR>' },
|
|
}
|
|
|
|
local tsserver_setup = function(client)
|
|
if client.name == 'tsserver' then
|
|
-- Disable tsserver formatting, we want formatting via prettier
|
|
client.server_capabilities.documentFormattingProvider = false
|
|
client.server_capabilities.documentRangeFormattingProvider = false
|
|
end
|
|
end
|
|
|
|
local get_active_client_by_name = function(bufnr, servername)
|
|
for _, client in pairs(vim.lsp.buf_get_clients(bufnr)) do
|
|
if client.name == servername then
|
|
return client
|
|
end
|
|
end
|
|
end
|
|
|
|
local switch_source_header = function()
|
|
local clangd_client = get_active_client_by_name(0, 'clangd')
|
|
local params = { uri = vim.uri_from_bufnr(0) }
|
|
|
|
if clangd_client then
|
|
clangd_client.request('textDocument/switchSourceHeader', params, function(err, result)
|
|
if err then
|
|
vim.schedule(function()
|
|
vim.notify('Clangd: switchSourceHeader gave error: ' .. tostring(err), vim.log.levels.ERROR)
|
|
end)
|
|
end
|
|
|
|
if not result then
|
|
vim.schedule(function()
|
|
vim.notify('Clangd: switchSourceHeader, corresponding file not determined', vim.log.levels.ERROR)
|
|
end)
|
|
return
|
|
end
|
|
|
|
vim.cmd.edit(vim.uri_to_fname(result))
|
|
end, 0)
|
|
else
|
|
vim.schedule(function()
|
|
vim.notify('Clangd: switchSourceHeader is not supported', vim.log.levels.ERROR)
|
|
end)
|
|
end
|
|
end
|
|
|
|
local clangd_setup = function(client)
|
|
if client.name == 'clangd' then
|
|
vim.api.nvim_create_user_command("ClangdSwitchSourceHeader", switch_source_header, {desc = 'Switch between source/header'})
|
|
end
|
|
end
|
|
|
|
local clangd_cleanup = function(client)
|
|
if client.name == 'clangd' then
|
|
vim.api.nvim_del_user_command("ClangdSwitchSourceHeader")
|
|
end
|
|
end
|
|
|
|
local on_attach = function(client, bufnr)
|
|
vim.api.nvim_buf_set_option(bufnr, 'omnifunc', 'v:lua.vim.lsp.omnifunc')
|
|
|
|
if client.config.flags then
|
|
client.config.flags.allow_incremental_sync = true
|
|
client.config.flags.debounce_text_changes = 100
|
|
end
|
|
|
|
local opts = { noremap=true, silent=true }
|
|
|
|
-- This needs to be here, so we disable formatting with tsserver before
|
|
-- actually checking it below.
|
|
tsserver_setup(client)
|
|
|
|
clangd_setup(client)
|
|
|
|
for _, mappings in pairs(lsp_key_mappings) do
|
|
local capability, mode, lhs, rhs = unpack(mappings)
|
|
if client.server_capabilities[capability] then
|
|
vim.api.nvim_buf_set_keymap(bufnr, mode, lhs, rhs, opts)
|
|
end
|
|
end
|
|
|
|
-- Opt out of semantic highlighting
|
|
client.server_capabilities.semanticTokensProvider = nil
|
|
|
|
if client.server_capabilities.codeLensProvider or client.server_capabilities.documentHighlightProvider then
|
|
if client.server_capabilities.codeLensProvider then
|
|
vim.api.nvim_create_autocmd({"CursorHold", "CursorHoldI", "InsertLeave"}, {
|
|
group = lsp_augroup_id,
|
|
buffer = bufnr,
|
|
callback = vim.lsp.codelens.refresh,
|
|
})
|
|
vim.api.nvim_create_autocmd({"CursorHold", "CursorHoldI"}, {
|
|
group = lsp_augroup_id,
|
|
buffer = bufnr,
|
|
callback = lightbulb.update_lightbulb,
|
|
})
|
|
end
|
|
|
|
if client.server_capabilities.documentHighlightProvider then
|
|
vim.api.nvim_create_autocmd("CursorHold", {
|
|
group = lsp_augroup_id,
|
|
buffer = bufnr,
|
|
callback = vim.lsp.buf.document_highlight,
|
|
})
|
|
vim.api.nvim_create_autocmd("CursorMoved", {
|
|
group = lsp_augroup_id,
|
|
buffer = bufnr,
|
|
callback = vim.lsp.buf.clear_references,
|
|
})
|
|
end
|
|
end
|
|
|
|
inlay_hint.on_attach(client, bufnr)
|
|
end
|
|
|
|
vim.api.nvim_create_autocmd("LspAttach", {
|
|
group = lsp_augroup_id,
|
|
callback = function(args)
|
|
local bufnr = args.buf
|
|
local client = vim.lsp.get_client_by_id(args.data.client_id)
|
|
local opts = { noremap=true, silent=true }
|
|
|
|
for _, mappings in pairs(lsp_key_mappings) do
|
|
local capability, mode, lhs, rhs = unpack(mappings)
|
|
if client.server_capabilities[capability] then
|
|
vim.api.nvim_buf_set_keymap(bufnr, mode, lhs, rhs, opts)
|
|
end
|
|
end
|
|
|
|
on_attach(client, bufnr)
|
|
end,
|
|
})
|
|
|
|
vim.api.nvim_create_autocmd("LspDetach", {
|
|
group = lsp_augroup_id,
|
|
callback = function(args)
|
|
local bufnr = args.buf
|
|
local client = vim.lsp.get_client_by_id(args.data.client_id)
|
|
|
|
for _, mappings in pairs(lsp_key_mappings) do
|
|
local capability, mode, lhs, _ = unpack(mappings)
|
|
if client.server_capabilities and client.server_capabilities[capability] then
|
|
vim.api.nvim_buf_del_keymap(bufnr, mode, lhs)
|
|
end
|
|
end
|
|
|
|
clangd_cleanup(client)
|
|
end,
|
|
})
|