From d7105d210391ad8fe3733d81f048df7a970b2488 Mon Sep 17 00:00:00 2001 From: Yegappan Lakshmanan Date: Sun, 9 Jan 2022 08:42:28 -0800 Subject: [PATCH] LSP plugin doesn't work after the change to the Vim9 import mechanism (patch 8.2.4019) --- autoload/buf.vim | 12 ++- autoload/handlers.vim | 124 +++++++++++++--------- autoload/lsp.vim | 220 +++++++++++++++++++++++----------------- autoload/lspoptions.vim | 7 ++ autoload/lspserver.vim | 126 ++++++++++++++--------- autoload/util.vim | 7 +- test/test_lsp.vim | 2 +- 7 files changed, 303 insertions(+), 195 deletions(-) diff --git a/autoload/buf.vim b/autoload/buf.vim index 92ab8a4..763645b 100644 --- a/autoload/buf.vim +++ b/autoload/buf.vim @@ -1,6 +1,14 @@ vim9script -import lspOptions from './lspoptions.vim' +var opt = {} + +if has('patch-8.2.4019') + import './lspoptions.vim' as opt_import + opt.lspOptions = opt_import.lspOptions +else + import lspOptions from './lspoptions.vim' + opt.lspOptions = lspOptions +endif def s:lspDiagSevToSignName(severity: number): string var typeMap: list = ['LspDiagError', 'LspDiagWarning', @@ -14,7 +22,7 @@ enddef # New LSP diagnostic messages received from the server for a file. # Update the signs placed in the buffer for this file export def LspDiagsUpdated(lspserver: dict, bnr: number) - if !lspOptions.autoHighlightDiags + if !opt.lspOptions.autoHighlightDiags return endif diff --git a/autoload/handlers.vim b/autoload/handlers.vim index 23264fe..402ba3e 100644 --- a/autoload/handlers.vim +++ b/autoload/handlers.vim @@ -4,13 +4,39 @@ vim9script # Refer to https://microsoft.github.io/language-server-protocol/specification # for the Language Server Protocol (LSP) specificaiton. -import lspOptions from './lspoptions.vim' -import {WarnMsg, +var opt = {} +var util = {} +var buf = {} + +if has('patch-8.2.4019') + import './lspoptions.vim' as opt_import + import './util.vim' as util_import + import './buf.vim' as buf_import + + opt.lspOptions = opt_import.lspOptions + util.WarnMsg = util_import.WarnMsg + util.ErrMsg = util_import.ErrMsg + util.TraceLog = util_import.TraceLog + util.LspUriToFile = util_import.LspUriToFile + util.GetLineByteFromPos = util_import.GetLineByteFromPos + buf.LspDiagsUpdated = buf_import.LspDiagsUpdated +else + import lspOptions from './lspoptions.vim' + import {WarnMsg, ErrMsg, TraceLog, LspUriToFile, GetLineByteFromPos} from './util.vim' -import {LspDiagsUpdated} from './buf.vim' + import {LspDiagsUpdated} from './buf.vim' + + opt.lspOptions = lspOptions + util.WarnMsg = WarnMsg + util.ErrMsg = ErrMsg + util.TraceLog = TraceLog + util.LspUriToFile = LspUriToFile + util.GetLineByteFromPos = GetLineByteFromPos + buf.LspDiagsUpdated = LspDiagsUpdated +endif # process the 'initialize' method reply from the LSP server # Result: InitializeResult @@ -26,19 +52,19 @@ def s:processInitializeReply(lspserver: dict, req: dict, reply: dicthas_key('signatureHelpProvider') + if opt.lspOptions.showSignature && caps->has_key('signatureHelpProvider') var triggers = caps.signatureHelpProvider.triggerCharacters for ch in triggers exe 'inoremap ' .. ch .. ' ' .. ch .. "=lsp#showSignature()" endfor endif - if lspOptions.autoComplete && caps->has_key('completionProvider') + if opt.lspOptions.autoComplete && caps->has_key('completionProvider') var triggers = caps.completionProvider.triggerCharacters lspserver.completionTriggerChars = triggers endif - if lspOptions.autoHighlight && caps->has_key('documentHighlightProvider') + if opt.lspOptions.autoHighlight && caps->has_key('documentHighlightProvider') && caps.documentHighlightProvider # Highlight all the occurrences of the current keyword augroup LSPBufferAutocmds @@ -61,7 +87,7 @@ enddef # Result: Location | Location[] | LocationLink[] | null def s:processDefDeclReply(lspserver: dict, req: dict, reply: dict): void if reply.result->empty() - WarnMsg("Error: definition is not found") + util.WarnMsg("Error: definition is not found") # pop the tag stack var tagstack: dict = gettagstack() if tagstack.length > 0 @@ -76,7 +102,7 @@ def s:processDefDeclReply(lspserver: dict, req: dict, reply: dict else location = reply.result endif - var fname = LspUriToFile(location.uri) + var fname = util.LspUriToFile(location.uri) var wid = fname->bufwinid() if wid != -1 wid->win_gotoid() @@ -114,7 +140,7 @@ def s:processSignaturehelpReply(lspserver: dict, req: dict, reply: dic var result: dict = reply.result if result.signatures->len() <= 0 - WarnMsg('No signature help available') + util.WarnMsg('No signature help available') return endif @@ -133,7 +159,7 @@ def s:processSignaturehelpReply(lspserver: dict, req: dict, reply: dic var label = '' if sig.parameters[result.activeParameter]->has_key('documentation') if sig.parameters[result.activeParameter].documentation->type() - == v:t_string + == v:t_string label = sig.parameters[result.activeParameter].documentation endif else @@ -143,7 +169,7 @@ def s:processSignaturehelpReply(lspserver: dict, req: dict, reply: dic startcol = text->stridx(label) endif endif - if lspOptions.echoSignature + if opt.lspOptions.echoSignature echon "\r\r" echon '' echon strpart(text, 0, startcol) @@ -240,7 +266,7 @@ def s:processCompletionReply(lspserver: dict, req: dict, reply: dictadd(d) endfor - if lspOptions.autoComplete + if opt.lspOptions.autoComplete if completeItems->empty() # no matches return @@ -305,14 +331,14 @@ def s:processHoverReply(lspserver: dict, req: dict, reply: dict): hoverText = reply.result.contents.value->split("\n") hoverKind = 'markdown' else - ErrMsg('Error: Unsupported hover contents type (' .. reply.result.contents.kind .. ')') + util.ErrMsg('Error: Unsupported hover contents type (' .. reply.result.contents.kind .. ')') return endif elseif reply.result.contents->has_key('value') # MarkedString hoverText = reply.result.contents.value->split("\n") else - ErrMsg('Error: Unsupported hover contents (' .. reply.result.contents .. ')') + util.ErrMsg('Error: Unsupported hover contents (' .. reply.result.contents .. ')') return endif elseif reply.result.contents->type() == v:t_list @@ -330,10 +356,10 @@ def s:processHoverReply(lspserver: dict, req: dict, reply: dict): endif hoverText->extend(reply.result.contents->split("\n")) else - ErrMsg('Error: Unsupported hover contents (' .. reply.result.contents .. ')') + util.ErrMsg('Error: Unsupported hover contents (' .. reply.result.contents .. ')') return endif - if lspOptions.hoverInPreview + if opt.lspOptions.hoverInPreview silent! pedit HoverReply wincmd P setlocal buftype=nofile @@ -352,7 +378,7 @@ enddef # Result: Location[] | null def s:processReferencesReply(lspserver: dict, req: dict, reply: dict): void if reply.result->empty() - WarnMsg('Error: No references found') + util.WarnMsg('Error: No references found') return endif @@ -360,7 +386,7 @@ def s:processReferencesReply(lspserver: dict, req: dict, reply: dict> = reply.result var qflist: list> = [] for loc in locations - var fname: string = LspUriToFile(loc.uri) + var fname: string = util.LspUriToFile(loc.uri) var bnr: number = fname->bufnr() if bnr == -1 bnr = fname->bufadd() @@ -372,7 +398,7 @@ def s:processReferencesReply(lspserver: dict, req: dict, reply: dicttrim("\t ", 1) qflist->add({filename: fname, lnum: loc.range.start.line + 1, - col: GetLineByteFromPos(bnr, loc.range.start) + 1, + col: util.GetLineByteFromPos(bnr, loc.range.start) + 1, text: text}) endfor setloclist(0, [], ' ', {title: 'Symbol Reference', items: qflist}) @@ -388,7 +414,7 @@ def s:processDocHighlightReply(lspserver: dict, req: dict, reply: dict return endif - var fname: string = LspUriToFile(req.params.textDocument.uri) + var fname: string = util.LspUriToFile(req.params.textDocument.uri) var bnr = fname->bufnr() for docHL in reply.result @@ -405,9 +431,9 @@ def s:processDocHighlightReply(lspserver: dict, req: dict, reply: dict propName = 'LspTextRef' endif prop_add(docHL.range.start.line + 1, - GetLineByteFromPos(bnr, docHL.range.start) + 1, + util.GetLineByteFromPos(bnr, docHL.range.start) + 1, {end_lnum: docHL.range.end.line + 1, - end_col: GetLineByteFromPos(bnr, docHL.range.end) + 1, + end_col: util.GetLineByteFromPos(bnr, docHL.range.end) + 1, bufnr: bnr, type: propName}) endfor @@ -437,7 +463,7 @@ def s:processSymbolInfoTable(symbolInfoTable: list>, var symInfo: dict for symbol in symbolInfoTable - fname = LspUriToFile(symbol.location.uri) + fname = util.LspUriToFile(symbol.location.uri) symbolType = LspSymbolKindToName(symbol.kind) name = symbol.name if symbol->has_key('containerName') @@ -497,7 +523,7 @@ def s:processDocSymbolReply(lspserver: dict, req: dict, reply: dict> = [] if req.params.textDocument.uri != '' - fname = LspUriToFile(req.params.textDocument.uri) + fname = util.LspUriToFile(req.params.textDocument.uri) endif if reply.result->empty() @@ -557,7 +583,7 @@ def s:set_lines(lines: list, A: list, B: list, var i_n = [B[0], numlines - 1]->min() if i_0 < 0 || i_0 >= numlines || i_n < 0 || i_n >= numlines - WarnMsg("set_lines: Invalid range, A = " .. A->string() + util.WarnMsg("set_lines: Invalid range, A = " .. A->string() .. ", B = " .. B->string() .. ", numlines = " .. numlines .. ", new lines = " .. new_lines->string()) return lines @@ -633,9 +659,9 @@ def s:applyTextEdits(bnr: number, text_edits: list>): void for e in text_edits # Adjust the start and end columns for multibyte characters start_row = e.range.start.line - start_col = GetLineByteFromPos(bnr, e.range.start) + start_col = util.GetLineByteFromPos(bnr, e.range.start) end_row = e.range.end.line - end_col = GetLineByteFromPos(bnr, e.range.end) + end_col = util.GetLineByteFromPos(bnr, e.range.end) start_line = [e.range.start.line, start_line]->min() finish_line = [e.range.end.line, finish_line]->max() @@ -696,9 +722,9 @@ enddef # interface TextDocumentEdit def s:applyTextDocumentEdit(textDocEdit: dict) - var bnr: number = bufnr(LspUriToFile(textDocEdit.textDocument.uri)) + var bnr: number = bufnr(util.LspUriToFile(textDocEdit.textDocument.uri)) if bnr == -1 - ErrMsg('Error: Text Document edit, buffer ' .. textDocEdit.textDocument.uri .. ' is not found') + util.ErrMsg('Error: Text Document edit, buffer ' .. textDocEdit.textDocument.uri .. ' is not found') return endif s:applyTextEdits(bnr, textDocEdit.edits) @@ -709,7 +735,7 @@ def s:applyWorkspaceEdit(workspaceEdit: dict) if workspaceEdit->has_key('documentChanges') for change in workspaceEdit.documentChanges if change->has_key('kind') - ErrMsg('Error: Unsupported change in workspace edit [' .. change.kind .. ']') + util.ErrMsg('Error: Unsupported change in workspace edit [' .. change.kind .. ']') else s:applyTextDocumentEdit(change) endif @@ -723,7 +749,7 @@ def s:applyWorkspaceEdit(workspaceEdit: dict) var save_cursor: list = getcurpos() for [uri, changes] in workspaceEdit.changes->items() - var fname: string = LspUriToFile(uri) + var fname: string = util.LspUriToFile(uri) var bnr: number = fname->bufnr() if bnr == -1 # file is already removed @@ -747,7 +773,7 @@ def s:processFormatReply(lspserver: dict, req: dict, reply: dict) # result: TextEdit[] - var fname: string = LspUriToFile(req.params.textDocument.uri) + var fname: string = util.LspUriToFile(req.params.textDocument.uri) var bnr: number = fname->bufnr() if bnr == -1 # file is already removed @@ -788,7 +814,7 @@ enddef def s:processCodeActionReply(lspserver: dict, req: dict, reply: dict) if reply.result->empty() # no action can be performed - WarnMsg('No code action is available') + util.WarnMsg('No code action is available') return endif @@ -834,8 +860,8 @@ def s:processSelectionRangeReply(lspserver: dict, req: dict, reply: di var r: dict> = reply.result[0].range var bnr: number = bufnr() - var start_col: number = GetLineByteFromPos(bnr, r.start) + 1 - var end_col: number = GetLineByteFromPos(bnr, r.end) + var start_col: number = util.GetLineByteFromPos(bnr, r.start) + 1 + var end_col: number = util.GetLineByteFromPos(bnr, r.end) setcharpos("'<", [0, r.start.line + 1, start_col, 0]) setcharpos("'>", [0, r.end.line + 1, end_col, 0]) @@ -919,7 +945,7 @@ def s:processWorkspaceSymbolReply(lspserver: dict, req: dict, reply: d endif # interface SymbolInformation - fileName = LspUriToFile(symbol.location.uri) + fileName = util.LspUriToFile(symbol.location.uri) r = symbol.location.range symName = symbol.name @@ -988,7 +1014,7 @@ export def ProcessReply(lspserver: dict, req: dict, reply: dict): if lsp_reply_handlers->has_key(req.method) lsp_reply_handlers[req.method](lspserver, req, reply) else - ErrMsg("Error: Unsupported reply received from LSP server: " .. reply->string()) + util.ErrMsg("Error: Unsupported reply received from LSP server: " .. reply->string()) endif enddef @@ -996,7 +1022,7 @@ enddef # Notification: textDocument/publishDiagnostics # Param: PublishDiagnosticsParams def s:processDiagNotif(lspserver: dict, reply: dict): void - var fname: string = LspUriToFile(reply.params.uri) + var fname: string = util.LspUriToFile(reply.params.uri) var bnr: number = fname->bufnr() if bnr == -1 # Is this condition possible? @@ -1019,7 +1045,7 @@ def s:processDiagNotif(lspserver: dict, reply: dict): void endfor lspserver.diagsMap->extend({['' .. bnr]: diag_by_lnum}) - LspDiagsUpdated(lspserver, bnr) + buf.LspDiagsUpdated(lspserver, bnr) enddef # process a show notification message from the LSP server @@ -1052,12 +1078,12 @@ def s:processLogMsgNotif(lspserver: dict, reply: dict) mtype = msgType[reply.params.type] endif - TraceLog(false, '[' .. mtype .. ']: ' .. reply.params.message) + util.TraceLog(false, '[' .. mtype .. ']: ' .. reply.params.message) enddef # process unsupported notification messages def s:processUnsupportedNotif(lspserver: dict, reply: dict) - ErrMsg('Error: Unsupported notification message received from the LSP server (' .. lspserver.path .. '), message = ' .. reply->string()) + util.ErrMsg('Error: Unsupported notification message received from the LSP server (' .. lspserver.path .. '), message = ' .. reply->string()) enddef # ignore unsupported notification message @@ -1081,7 +1107,7 @@ export def ProcessNotif(lspserver: dict, reply: dict): void if lsp_notif_handlers->has_key(reply.method) lsp_notif_handlers[reply.method](lspserver, reply) else - ErrMsg('Error: Unsupported notification received from LSP server ' .. reply->string()) + util.ErrMsg('Error: Unsupported notification received from LSP server ' .. reply->string()) endif enddef @@ -1099,11 +1125,11 @@ def s:processApplyEditReq(lspserver: dict, request: dict) endif s:applyWorkspaceEdit(workspaceEditParams.edit) # TODO: Need to return the proper result of the edit operation - lspserver.sendResponse(request, {applied: true}, v:null) + lspserver.sendResponse(request, {applied: true}, {}) enddef def s:processUnsupportedReq(lspserver: dict, request: dict) - ErrMsg('Error: Unsupported request message received from the LSP server (' .. lspserver.path .. '), message = ' .. request->string()) + util.ErrMsg('Error: Unsupported request message received from the LSP server (' .. lspserver.path .. '), message = ' .. request->string()) enddef # process a request message from the server @@ -1123,7 +1149,7 @@ export def ProcessRequest(lspserver: dict, request: dict) if lspRequestHandlers->has_key(request.method) lspRequestHandlers[request.method](lspserver, request) else - ErrMsg('Error: Unsupported request received from LSP server ' .. + util.ErrMsg('Error: Unsupported request received from LSP server ' .. request->string()) endif enddef @@ -1149,7 +1175,7 @@ export def ProcessMessages(lspserver: dict): void len = str2nr(lspserver.data[idx + 16 : ]) if len == 0 - ErrMsg("Error(LSP): Invalid content length") + util.ErrMsg("Error(LSP): Invalid content length") # Discard the header lspserver.data = lspserver.data[idx + 16 :] return @@ -1175,7 +1201,7 @@ export def ProcessMessages(lspserver: dict): void try msg = content->json_decode() catch - ErrMsg("Error(LSP): Malformed content (" .. content .. ")") + util.ErrMsg("Error(LSP): Malformed content (" .. content .. ")") lspserver.data = lspserver.data[idx + len :] continue endtry @@ -1196,7 +1222,7 @@ export def ProcessMessages(lspserver: dict): void if msg.error->has_key('data') emsg = emsg .. ', data = ' .. msg.error.data->string() endif - ErrMsg("Error(LSP): request " .. req.method .. " failed (" + util.ErrMsg("Error(LSP): request " .. req.method .. " failed (" .. emsg .. ")") endif endif @@ -1207,7 +1233,7 @@ export def ProcessMessages(lspserver: dict): void # notification message from the server lspserver.processNotif(msg) else - ErrMsg("Error(LSP): Unsupported message (" .. msg->string() .. ")") + util.ErrMsg("Error(LSP): Unsupported message (" .. msg->string() .. ")") endif lspserver.data = lspserver.data[idx + len :] diff --git a/autoload/lsp.vim b/autoload/lsp.vim index 932aa95..4c66326 100644 --- a/autoload/lsp.vim +++ b/autoload/lsp.vim @@ -2,15 +2,49 @@ vim9script # Vim9 LSP client -import lspOptions from './lspoptions.vim' -import NewLspServer from './lspserver.vim' -import {WarnMsg, - ErrMsg, - lsp_server_trace, - ClearTraceLogs, - GetLineByteFromPos, - PushCursorToTagStack} from './util.vim' -import {LspDiagsUpdated} from './buf.vim' +var opt = {} +var lserver = {} +var util = {} +var buf = {} + +if has('patch-8.2.4019') + import './lspoptions.vim' as opt_import + import './lspserver.vim' as server_import + import './util.vim' as util_import + import './buf.vim' as buf_import + + opt.LspOptionsSet = opt_import.LspOptionsSet + opt.lspOptions = opt_import.lspOptions + lserver.NewLspServer = server_import.NewLspServer + util.WarnMsg = util_import.WarnMsg + util.ErrMsg = util_import.ErrMsg + util.ServerTrace = util_import.ServerTrace + util.ClearTraceLogs = util_import.ClearTraceLogs + util.GetLineByteFromPos = util_import.GetLineByteFromPos + util.PushCursorToTagStack = util_import.PushCursorToTagStack + buf.LspDiagsUpdated = buf_import.LspDiagsUpdated +else + import {lspOptions, LspOptionsSet} from './lspoptions.vim' + import NewLspServer from './lspserver.vim' + import {WarnMsg, + ErrMsg, + ServerTrace, + ClearTraceLogs, + GetLineByteFromPos, + PushCursorToTagStack} from './util.vim' + import {LspDiagsUpdated} from './buf.vim' + + opt.LspOptionsSet = LspOptionsSet + opt.lspOptions = lspOptions + lserver.NewLspServer = NewLspServer + util.WarnMsg = WarnMsg + util.ErrMsg = ErrMsg + util.ServerTrace = ServerTrace + util.ClearTraceLogs = ClearTraceLogs + util.GetLineByteFromPos = GetLineByteFromPos + util.PushCursorToTagStack = PushCursorToTagStack + buf.LspDiagsUpdated = LspDiagsUpdated +endif # Needs Vim 8.2.2342 and higher if v:version < 802 || !has('patch-8.2.2342') @@ -33,9 +67,7 @@ var lspInitializedOnce = false # Set user configurable LSP options def lsp#setOptions(lspOpts: dict) - for key in lspOpts->keys() - lspOptions[key] = lspOpts[key] - endfor + opt.LspOptionsSet(lspOpts) enddef def s:lspInitOnce() @@ -63,8 +95,8 @@ def s:lspGetServer(ftype: string): dict enddef # Add a LSP server for a filetype -def s:lspAddServer(ftype: string, lspserver: dict) - ftypeServerMap->extend({[ftype]: lspserver}) +def s:lspAddServer(ftype: string, lspsrv: dict) + ftypeServerMap->extend({[ftype]: lspsrv}) enddef # Returns true if omni-completion is enabled for filetype 'ftype'. @@ -79,8 +111,8 @@ def s:lspOmniComplSet(ftype: string, enabled: bool) enddef def lsp#enableServerTrace() - ClearTraceLogs() - lsp_server_trace = true + util.ClearTraceLogs() + util.ServerTrace(true) enddef # Show information about all the LSP servers @@ -106,11 +138,11 @@ def lsp#gotoDefinition() var lspserver: dict = s:lspGetServer(ftype) if lspserver->empty() - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') return endif if !lspserver.running - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') return endif @@ -126,11 +158,11 @@ def lsp#gotoDeclaration() var lspserver: dict = s:lspGetServer(ftype) if lspserver->empty() - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') return endif if !lspserver.running - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') return endif @@ -146,11 +178,11 @@ def lsp#gotoTypedef() var lspserver: dict = s:lspGetServer(ftype) if lspserver->empty() - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') return endif if !lspserver.running - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') return endif @@ -166,11 +198,11 @@ def lsp#gotoImplementation() var lspserver: dict = s:lspGetServer(ftype) if lspserver->empty() - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') return endif if !lspserver.running - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') return endif @@ -187,11 +219,11 @@ def lsp#showSignature(): string var lspserver: dict = s:lspGetServer(ftype) if lspserver->empty() - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') return '' endif if !lspserver.running - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') return '' endif @@ -271,7 +303,7 @@ def lsp#leftInsertMode() if lspserver->empty() || !lspserver.running return endif - LspDiagsUpdated(lspserver, bufnr()) + buf.LspDiagsUpdated(lspserver, bufnr()) enddef # A new buffer is opened. If LSP is supported for this buffer, then add it @@ -301,7 +333,7 @@ def lsp#addFile(bnr: number): void listener_add(function('lsp#bufchange_listener'), bnr) # set options for insert mode completion - if lspOptions.autoComplete + if opt.lspOptions.autoComplete setbufvar(bnr, '&completeopt', 'menuone,popup,noinsert,noselect') setbufvar(bnr, '&completepopup', 'border:off') # in insert mode stops completion and inserts a @@ -315,7 +347,7 @@ def lsp#addFile(bnr: number): void setbufvar(bnr, '&balloonexpr', 'LspDiagExpr()') # map characters that trigger signature help - if lspOptions.showSignature && + if opt.lspOptions.showSignature && lspserver.caps->has_key('signatureHelpProvider') var triggers = lspserver.caps.signatureHelpProvider.triggerCharacters for ch in triggers @@ -329,7 +361,7 @@ def lsp#addFile(bnr: number): void # file saved notification handler exe 'autocmd BufWritePost call s:lspSavedFile()' - if lspOptions.autoComplete + if opt.lspOptions.autoComplete # Trigger 24x7 insert mode completion when text is changed exe 'autocmd TextChangedI call lsp#complete()' endif @@ -337,7 +369,7 @@ def lsp#addFile(bnr: number): void # Update the diagnostics when insert mode is stopped exe 'autocmd InsertLeave call lsp#leftInsertMode()' - if lspOptions.autoHighlight && + if opt.lspOptions.autoHighlight && lspserver.caps->has_key('documentHighlightProvider') && lspserver.caps.documentHighlightProvider # Highlight all the occurrences of the current keyword @@ -385,7 +417,7 @@ enddef def lsp#addServer(serverList: list>) for server in serverList if !server->has_key('filetype') || !server->has_key('path') || !server->has_key('args') - ErrMsg('Error: LSP server information is missing filetype or path or args') + util.ErrMsg('Error: LSP server information is missing filetype or path or args') continue endif if !server->has_key('omnicompl') @@ -394,19 +426,19 @@ def lsp#addServer(serverList: list>) endif if !server.path->filereadable() - ErrMsg('Error: LSP server ' .. server.path .. ' is not found') + util.ErrMsg('Error: LSP server ' .. server.path .. ' is not found') return endif if server.args->type() != v:t_list - ErrMsg('Error: Arguments for LSP server ' .. server.args .. ' is not a List') + util.ErrMsg('Error: Arguments for LSP server ' .. server.args .. ' is not a List') return endif if server.omnicompl->type() != v:t_bool - ErrMsg('Error: Setting of omnicompl ' .. server.omnicompl .. ' is not a Boolean') + util.ErrMsg('Error: Setting of omnicompl ' .. server.omnicompl .. ' is not a Boolean') return endif - var lspserver: dict = NewLspServer(server.path, server.args) + var lspserver: dict = lserver.NewLspServer(server.path, server.args) if server.filetype->type() == v:t_string s:lspAddServer(server.filetype, lspserver) @@ -417,7 +449,7 @@ def lsp#addServer(serverList: list>) s:lspOmniComplSet(ftype, server.omnicompl) endfor else - ErrMsg('Error: Unsupported file type information "' .. + util.ErrMsg('Error: Unsupported file type information "' .. server.filetype->string() .. '" in LSP server registration') continue endif @@ -428,7 +460,7 @@ enddef # Params: SetTraceParams def lsp#setTraceServer(traceVal: string) if ['off', 'message', 'verbose']->index(traceVal) == -1 - ErrMsg("Error: Unsupported LSP server trace value " .. traceVal) + util.ErrMsg("Error: Unsupported LSP server trace value " .. traceVal) return endif @@ -439,11 +471,11 @@ def lsp#setTraceServer(traceVal: string) var lspserver: dict = s:lspGetServer(ftype) if lspserver->empty() - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') return endif if !lspserver.running - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') return endif @@ -471,11 +503,11 @@ def lsp#showDiagnostics(): void var lspserver: dict = s:lspGetServer(ftype) if lspserver->empty() - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') return endif if !lspserver.running - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') return endif @@ -486,7 +518,7 @@ def lsp#showDiagnostics(): void var bnr: number = bufnr() if !lspserver.diagsMap->has_key(bnr) || lspserver.diagsMap[bnr]->empty() - WarnMsg('No diagnostic messages found for ' .. fname) + util.WarnMsg('No diagnostic messages found for ' .. fname) return endif @@ -497,7 +529,7 @@ def lsp#showDiagnostics(): void text = diag.message->substitute("\n\\+", "\n", 'g') qflist->add({'filename': fname, 'lnum': diag.range.start.line + 1, - 'col': GetLineByteFromPos(bnr, diag.range.start) + 1, + 'col': util.GetLineByteFromPos(bnr, diag.range.start) + 1, 'text': text, 'type': s:lspDiagSevToQfType(diag.severity)}) endfor @@ -515,11 +547,11 @@ def lsp#showCurrentDiag() var lspserver: dict = s:lspGetServer(ftype) if lspserver->empty() - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') return endif if !lspserver.running - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') return endif @@ -527,7 +559,7 @@ def lsp#showCurrentDiag() var lnum: number = line('.') var diag: dict = lspserver.getDiagByLine(bnr, lnum) if diag->empty() - WarnMsg('No diagnostic messages found for current line') + util.WarnMsg('No diagnostic messages found for current line') else echo diag.message endif @@ -567,10 +599,10 @@ def lsp#errorCount(): dict enddef # sort the diaganostics messages for a buffer by line number -def s:getSortedDiagLines(lspserver: dict, bnr: number): list +def s:getSortedDiagLines(lspsrv: dict, bnr: number): list # create a list of line numbers from the diag map keys var lnums: list = - lspserver.diagsMap[bnr]->keys()->mapnew((_, v) => v->str2nr()) + lspsrv.diagsMap[bnr]->keys()->mapnew((_, v) => v->str2nr()) return lnums->sort((a, b) => a - b) enddef @@ -583,11 +615,11 @@ def lsp#jumpToDiag(which: string): void var lspserver: dict = s:lspGetServer(ftype) if lspserver->empty() - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') return endif if !lspserver.running - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') return endif @@ -598,7 +630,7 @@ def lsp#jumpToDiag(which: string): void var bnr: number = bufnr() if !lspserver.diagsMap->has_key(bnr) || lspserver.diagsMap[bnr]->empty() - WarnMsg('No diagnostic messages found for ' .. fname) + util.WarnMsg('No diagnostic messages found for ' .. fname) return endif @@ -620,7 +652,7 @@ def lsp#jumpToDiag(which: string): void endif endfor - WarnMsg('Error: No more diagnostics found') + util.WarnMsg('Error: No more diagnostics found') enddef # Insert mode completion handler. Used when 24x7 completion is enabled @@ -668,11 +700,11 @@ def lsp#omniFunc(findstart: number, base: string): any if findstart if lspserver->empty() - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') return -2 endif if !lspserver.running - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') return -2 endif @@ -737,11 +769,11 @@ def lsp#showReferences() var lspserver: dict = s:lspGetServer(ftype) if lspserver->empty() - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') return endif if !lspserver.running - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') return endif @@ -762,11 +794,11 @@ def lsp#docHighlight() var lspserver: dict = s:lspGetServer(ftype) if lspserver->empty() - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') return endif if !lspserver.running - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') return endif @@ -858,7 +890,7 @@ def s:addSymbolText(bnr: number, for s in symbols text->add(prefix .. s.name) # remember the line number for the symbol - var start_col: number = GetLineByteFromPos(bnr, s.range.start) + 1 + var start_col: number = util.GetLineByteFromPos(bnr, s.range.start) + 1 lnumMap->add({name: s.name, lnum: s.range.start.line + 1, col: start_col}) s.outlineLine = lnumMap->len() @@ -1081,7 +1113,7 @@ enddef # Format the entire file def lsp#textDocFormat(range_args: number, line1: number, line2: number) if !&modifiable - ErrMsg('Error: Current file is not a modifiable file') + util.ErrMsg('Error: Current file is not a modifiable file') return endif @@ -1092,11 +1124,11 @@ def lsp#textDocFormat(range_args: number, line1: number, line2: number) var lspserver: dict = s:lspGetServer(ftype) if lspserver->empty() - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') return endif if !lspserver.running - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') return endif @@ -1125,11 +1157,11 @@ def lsp#incomingCalls() var lspserver: dict = s:lspGetServer(ftype) if lspserver->empty() - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') return endif if !lspserver.running - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') return endif @@ -1157,11 +1189,11 @@ def lsp#rename() var lspserver: dict = s:lspGetServer(ftype) if lspserver->empty() - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') return endif if !lspserver.running - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') return endif @@ -1188,11 +1220,11 @@ def lsp#codeAction() var lspserver: dict = s:lspGetServer(ftype) if lspserver->empty() - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') return endif if !lspserver.running - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') return endif @@ -1205,10 +1237,10 @@ def lsp#codeAction() enddef # Handle keys pressed when the workspace symbol popup menu is displayed -def s:filterSymbols(lspserver: dict, popupID: number, key: string): bool +def s:filterSymbols(lspsrv: dict, popupID: number, key: string): bool var key_handled: bool = false var update_popup: bool = false - var query: string = lspserver.workspaceSymbolQuery + var query: string = lspsrv.workspaceSymbolQuery if key == "\" || key == "\" # Erase one character from the filter text @@ -1248,7 +1280,7 @@ def s:filterSymbols(lspserver: dict, popupID: number, key: string): bool # Update the popup with the new list of symbol names popupID->popup_settext('') if query != '' - lspserver.workspaceQuery(query) + lspsrv.workspaceQuery(query) else []->setwinvar(popupID, 'LspSymbolTable') endif @@ -1256,7 +1288,7 @@ def s:filterSymbols(lspserver: dict, popupID: number, key: string): bool endif # Update the workspace symbol query string - lspserver.workspaceSymbolQuery = query + lspsrv.workspaceSymbolQuery = query if key_handled return true @@ -1281,7 +1313,7 @@ def s:jumpToWorkspaceSymbol(popupID: number, result: number): void endif try # Save the current location in the tag stack - PushCursorToTagStack() + util.PushCursorToTagStack() # if the selected file is already present in a window, then jump to it var fname: string = symTbl[result - 1].file @@ -1306,7 +1338,7 @@ def s:jumpToWorkspaceSymbol(popupID: number, result: number): void enddef # display a list of symbols from the workspace -def s:showSymbolMenu(lspserver: dict, query: string) +def s:showSymbolMenu(lspsrv: dict, query: string) # Create the popup menu var lnum = &lines - &cmdheight - 2 - 10 var popupAttr = { @@ -1322,13 +1354,13 @@ def s:showSymbolMenu(lspserver: dict, query: string) mapping: false, fixed: 1, close: "button", - filter: function('s:filterSymbols', [lspserver]), + filter: function('s:filterSymbols', [lspsrv]), callback: function('s:jumpToWorkspaceSymbol') } - lspserver.workspaceSymbolPopup = popup_menu([], popupAttr) - lspserver.workspaceSymbolQuery = query + lspsrv.workspaceSymbolPopup = popup_menu([], popupAttr) + lspsrv.workspaceSymbolQuery = query prop_type_add('lspworkspacesymbol', - {bufnr: lspserver.workspaceSymbolPopup->winbufnr(), + {bufnr: lspsrv.workspaceSymbolPopup->winbufnr(), highlight: 'Title'}) echo 'Symbol: ' .. query enddef @@ -1343,11 +1375,11 @@ def lsp#symbolSearch(queryArg: string) var lspserver: dict = s:lspGetServer(ftype) if lspserver->empty() - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') return endif if !lspserver.running - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') return endif @@ -1381,11 +1413,11 @@ def lsp#listWorkspaceFolders() var lspserver: dict = s:lspGetServer(ftype) if lspserver->empty() - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') return endif if !lspserver.running - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') return endif @@ -1401,11 +1433,11 @@ def lsp#addWorkspaceFolder(dirArg: string) var lspserver: dict = s:lspGetServer(ftype) if lspserver->empty() - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') return endif if !lspserver.running - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') return endif @@ -1418,7 +1450,7 @@ def lsp#addWorkspaceFolder(dirArg: string) endif :redraw! if !dirName->isdirectory() - ErrMsg('Error: ' .. dirName .. ' is not a directory') + util.ErrMsg('Error: ' .. dirName .. ' is not a directory') return endif @@ -1434,11 +1466,11 @@ def lsp#removeWorkspaceFolder(dirArg: string) var lspserver: dict = s:lspGetServer(ftype) if lspserver->empty() - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') return endif if !lspserver.running - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') return endif @@ -1451,7 +1483,7 @@ def lsp#removeWorkspaceFolder(dirArg: string) endif :redraw! if !dirName->isdirectory() - ErrMsg('Error: ' .. dirName .. ' is not a directory') + util.ErrMsg('Error: ' .. dirName .. ' is not a directory') return endif @@ -1467,11 +1499,11 @@ def lsp#selectionRange() var lspserver: dict = s:lspGetServer(ftype) if lspserver->empty() - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') return endif if !lspserver.running - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') return endif @@ -1493,11 +1525,11 @@ def lsp#foldDocument() var lspserver: dict = s:lspGetServer(ftype) if lspserver->empty() - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') return endif if !lspserver.running - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') + util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') return endif @@ -1507,7 +1539,7 @@ def lsp#foldDocument() endif if &foldmethod != 'manual' - ErrMsg("Error: Only works when 'foldmethod' is 'manual'") + util.ErrMsg("Error: Only works when 'foldmethod' is 'manual'") return endif diff --git a/autoload/lspoptions.vim b/autoload/lspoptions.vim index 6edd8b1..8298436 100644 --- a/autoload/lspoptions.vim +++ b/autoload/lspoptions.vim @@ -18,3 +18,10 @@ export var lspOptions: dict = { # Show the symbol documentation in the preview window instead of in a popup hoverInPreview: false, } + +# set LSP options from user provided options +export def LspOptionsSet(opts: dict) + for key in opts->keys() + lspOptions[key] = opts[key] + endfor +enddef diff --git a/autoload/lspserver.vim b/autoload/lspserver.vim index cae1d2c..c91021a 100644 --- a/autoload/lspserver.vim +++ b/autoload/lspserver.vim @@ -4,33 +4,63 @@ vim9script # Refer to https://microsoft.github.io/language-server-protocol/specification # for the Language Server Protocol (LSP) specificaiton. -import {ProcessReply, +var handlers = {} +var util = {} + +if has('patch-8.2.4019') + import './handlers.vim' as handlers_import + import './util.vim' as util_import + handlers.ProcessReply = handlers_import.ProcessReply + handlers.ProcessNotif = handlers_import.ProcessNotif + handlers.ProcessRequest = handlers_import.ProcessRequest + handlers.ProcessMessages = handlers_import.ProcessMessages + util.WarnMsg = util_import.WarnMsg + util.ErrMsg = util_import.ErrMsg + util.TraceLog = util_import.TraceLog + util.LspUriToFile = util_import.LspUriToFile + util.LspBufnrToUri = util_import.LspBufnrToUri + util.LspFileToUri = util_import.LspFileToUri + util.PushCursorToTagStack = util_import.PushCursorToTagStack +else + import {ProcessReply, ProcessNotif, ProcessRequest, ProcessMessages} from './handlers.vim' -import {WarnMsg, + import {WarnMsg, ErrMsg, TraceLog, LspUriToFile, LspBufnrToUri, LspFileToUri, PushCursorToTagStack} from './util.vim' + handlers.ProcessReply = ProcessReply + handlers.ProcessNotif = ProcessNotif + handlers.ProcessRequest = ProcessRequest + handlers.ProcessMessages = ProcessMessages + util.WarnMsg = WarnMsg + util.ErrMsg = ErrMsg + util.TraceLog = TraceLog + util.LspUriToFile = LspUriToFile + util.LspBufnrToUri = LspBufnrToUri + util.LspFileToUri = LspFileToUri + util.PushCursorToTagStack = PushCursorToTagStack +endif # LSP server standard output handler def s:output_cb(lspserver: dict, chan: channel, msg: string): void - TraceLog(false, msg) + util.TraceLog(false, msg) lspserver.data = lspserver.data .. msg lspserver.processMessages() enddef # LSP server error output handler def s:error_cb(lspserver: dict, chan: channel, emsg: string,): void - TraceLog(true, emsg) + util.TraceLog(true, emsg) enddef # LSP server exit callback def s:exit_cb(lspserver: dict, job: job, status: number): void - WarnMsg("LSP server exited with status " .. status) + util.WarnMsg("LSP server exited with status " .. status) lspserver.job = v:none lspserver.running = false lspserver.requests = {} @@ -39,7 +69,7 @@ enddef # Start a LSP server def s:startServer(lspserver: dict): number if lspserver.running - WarnMsg("LSP server for is already running") + util.WarnMsg("LSP server for is already running") return 0 endif @@ -64,7 +94,7 @@ def s:startServer(lspserver: dict): number var job = job_start(cmd, opts) if job->job_status() == 'fail' - ErrMsg("Error: Failed to start LSP server " .. lspserver.path) + util.ErrMsg("Error: Failed to start LSP server " .. lspserver.path) return 1 endif @@ -120,10 +150,10 @@ def s:initServer(lspserver: dict) } var curdir: string = getcwd() initparams.rootPath = curdir - initparams.rootUri = LspFileToUri(curdir) + initparams.rootUri = util.LspFileToUri(curdir) initparams.workspaceFolders = [{ name: fnamemodify(curdir, ':t'), - uri: LspFileToUri(curdir) + uri: util.LspFileToUri(curdir) }] initparams.trace = 'off' initparams.capabilities = clientCaps @@ -156,7 +186,7 @@ enddef # Stop a LSP server def s:stopServer(lspserver: dict): number if !lspserver.running - WarnMsg("LSP server is not running") + util.WarnMsg("LSP server is not running") return 0 endif @@ -253,7 +283,7 @@ def s:textdocDidOpen(lspserver: dict, bnr: number, ftype: string): void # interface DidOpenTextDocumentParams # interface TextDocumentItem var tdi = {} - tdi.uri = LspBufnrToUri(bnr) + tdi.uri = util.LspBufnrToUri(bnr) tdi.languageId = ftype tdi.version = 1 tdi.text = getbufline(bnr, 1, '$')->join("\n") .. "\n" @@ -269,7 +299,7 @@ def s:textdocDidClose(lspserver: dict, bnr: number): void # interface DidCloseTextDocumentParams # interface TextDocumentIdentifier var tdid = {} - tdid.uri = LspBufnrToUri(bnr) + tdid.uri = util.LspBufnrToUri(bnr) notif.params->extend({textDocument: tdid}) lspserver.sendMessage(notif) @@ -285,7 +315,7 @@ def s:textdocDidChange(lspserver: dict, bnr: number, start: number, # interface DidChangeTextDocumentParams # interface VersionedTextDocumentIdentifier var vtdid: dict = {} - vtdid.uri = LspBufnrToUri(bnr) + vtdid.uri = util.LspBufnrToUri(bnr) # Use Vim 'changedtick' as the LSP document version number vtdid.version = bnr->getbufvar('changedtick') @@ -349,7 +379,7 @@ enddef def s:getLspTextDocPosition(): dict> # interface TextDocumentIdentifier # interface Position - return {textDocument: {uri: LspFileToUri(@%)}, + return {textDocument: {uri: util.LspFileToUri(@%)}, position: s:getLspPosition()} enddef @@ -359,7 +389,7 @@ enddef def s:getCompletion(lspserver: dict, triggerKind_arg: number): void # Check whether LSP server supports completion if !lspserver.caps->has_key('completionProvider') - ErrMsg("Error: LSP server does not support completion") + util.ErrMsg("Error: LSP server does not support completion") return endif @@ -385,11 +415,11 @@ def s:gotoDefinition(lspserver: dict): void # Check whether LSP server supports jumping to a definition if !lspserver.caps->has_key('definitionProvider') || !lspserver.caps.definitionProvider - ErrMsg("Error: LSP server does not support jumping to a definition") + util.ErrMsg("Error: LSP server does not support jumping to a definition") return endif - PushCursorToTagStack() + util.PushCursorToTagStack() var req = lspserver.createRequest('textDocument/definition') # interface DefinitionParams # interface TextDocumentPositionParams @@ -403,11 +433,11 @@ def s:gotoDeclaration(lspserver: dict): void # Check whether LSP server supports jumping to a declaration if !lspserver.caps->has_key('declarationProvider') || !lspserver.caps.declarationProvider - ErrMsg("Error: LSP server does not support jumping to a declaration") + util.ErrMsg("Error: LSP server does not support jumping to a declaration") return endif - PushCursorToTagStack() + util.PushCursorToTagStack() var req = lspserver.createRequest('textDocument/declaration') # interface DeclarationParams @@ -423,11 +453,11 @@ def s:gotoTypeDef(lspserver: dict): void # Check whether LSP server supports jumping to a type definition if !lspserver.caps->has_key('typeDefinitionProvider') || !lspserver.caps.typeDefinitionProvider - ErrMsg("Error: LSP server does not support jumping to a type definition") + util.ErrMsg("Error: LSP server does not support jumping to a type definition") return endif - PushCursorToTagStack() + util.PushCursorToTagStack() var req = lspserver.createRequest('textDocument/typeDefinition') # interface TypeDefinitionParams @@ -443,11 +473,11 @@ def s:gotoImplementation(lspserver: dict): void # Check whether LSP server supports jumping to a implementation if !lspserver.caps->has_key('implementationProvider') || !lspserver.caps.implementationProvider - ErrMsg("Error: LSP server does not support jumping to an implementation") + util.ErrMsg("Error: LSP server does not support jumping to an implementation") return endif - PushCursorToTagStack() + util.PushCursorToTagStack() var req = lspserver.createRequest('textDocument/implementation') # interface ImplementationParams @@ -463,7 +493,7 @@ enddef def s:showSignature(lspserver: dict): void # Check whether LSP server supports signature help if !lspserver.caps->has_key('signatureHelpProvider') - ErrMsg("Error: LSP server does not support signature help") + util.ErrMsg("Error: LSP server does not support signature help") return endif @@ -487,7 +517,7 @@ def s:didSaveFile(lspserver: dict, bnr: number): void var notif: dict = lspserver.createNotification('textDocument/didSave') # interface: DidSaveTextDocumentParams - notif.params->extend({textDocument: {uri: LspBufnrToUri(bnr)}}) + notif.params->extend({textDocument: {uri: util.LspBufnrToUri(bnr)}}) lspserver.sendMessage(notif) enddef @@ -514,7 +544,7 @@ def s:showReferences(lspserver: dict): void # Check whether LSP server supports getting reference information if !lspserver.caps->has_key('referencesProvider') || !lspserver.caps.referencesProvider - ErrMsg("Error: LSP server does not support showing references") + util.ErrMsg("Error: LSP server does not support showing references") return endif @@ -533,7 +563,7 @@ def s:docHighlight(lspserver: dict): void # Check whether LSP server supports getting highlight information if !lspserver.caps->has_key('documentHighlightProvider') || !lspserver.caps.documentHighlightProvider - ErrMsg("Error: LSP server does not support document highlight") + util.ErrMsg("Error: LSP server does not support document highlight") return endif @@ -550,14 +580,14 @@ def s:getDocSymbols(lspserver: dict, fname: string): void # Check whether LSP server supports getting document symbol information if !lspserver.caps->has_key('documentSymbolProvider') || !lspserver.caps.documentSymbolProvider - ErrMsg("Error: LSP server does not support getting list of symbols") + util.ErrMsg("Error: LSP server does not support getting list of symbols") return endif var req = lspserver.createRequest('textDocument/documentSymbol') # interface DocumentSymbolParams # interface TextDocumentIdentifier - req.params->extend({textDocument: {uri: LspFileToUri(fname)}}) + req.params->extend({textDocument: {uri: util.LspFileToUri(fname)}}) lspserver.sendMessage(req) enddef @@ -571,7 +601,7 @@ def s:textDocFormat(lspserver: dict, fname: string, rangeFormat: bool, # Check whether LSP server supports formatting documents if !lspserver.caps->has_key('documentFormattingProvider') || !lspserver.caps.documentFormattingProvider - ErrMsg("Error: LSP server does not support formatting documents") + util.ErrMsg("Error: LSP server does not support formatting documents") return endif @@ -598,7 +628,7 @@ def s:textDocFormat(lspserver: dict, fname: string, rangeFormat: bool, tabSize: tabsz, insertSpaces: &expandtab ? true : false, } - req.params->extend({textDocument: {uri: LspFileToUri(fname)}, + req.params->extend({textDocument: {uri: util.LspFileToUri(fname)}, options: fmtopts}) if rangeFormat var r: dict> = { @@ -616,7 +646,7 @@ def s:incomingCalls(lspserver: dict, fname: string) # Check whether LSP server supports incoming calls if !lspserver.caps->has_key('callHierarchyProvider') || !lspserver.caps.callHierarchyProvider - ErrMsg("Error: LSP server does not support call hierarchy") + util.ErrMsg("Error: LSP server does not support call hierarchy") return endif @@ -634,7 +664,7 @@ def s:renameSymbol(lspserver: dict, newName: string) # Check whether LSP server supports rename operation if !lspserver.caps->has_key('renameProvider') || !lspserver.caps.renameProvider - ErrMsg("Error: LSP server does not support rename operation") + util.ErrMsg("Error: LSP server does not support rename operation") return endif @@ -662,7 +692,7 @@ def s:codeAction(lspserver: dict, fname_arg: string) # Check whether LSP server supports code action operation if !lspserver.caps->has_key('codeActionProvider') || !lspserver.caps.codeActionProvider - ErrMsg("Error: LSP server does not support code action operation") + util.ErrMsg("Error: LSP server does not support code action operation") return endif @@ -674,7 +704,7 @@ def s:codeAction(lspserver: dict, fname_arg: string) var r: dict> = { start: {line: line('.') - 1, character: charcol('.') - 1}, end: {line: line('.') - 1, character: charcol('.') - 1}} - req.params->extend({textDocument: {uri: LspFileToUri(fname)}, range: r}) + req.params->extend({textDocument: {uri: util.LspFileToUri(fname)}, range: r}) var diag: list> = [] var lnum = line('.') var diagInfo: dict = lspserver.getDiagByLine(bnr, lnum) @@ -693,7 +723,7 @@ def s:workspaceQuerySymbols(lspserver: dict, query: string): bool # Check whether the LSP server supports listing workspace symbols if !lspserver.caps->has_key('workspaceSymbolProvider') || !lspserver.caps.workspaceSymbolProvider - ErrMsg("Error: LSP server does not support listing workspace symbols") + util.ErrMsg("Error: LSP server does not support listing workspace symbols") return false endif @@ -712,12 +742,12 @@ def s:addWorkspaceFolder(lspserver: dict, dirName: string): void || !lspserver.caps.workspace->has_key('workspaceFolders') || !lspserver.caps.workspace.workspaceFolders->has_key('supported') || !lspserver.caps.workspace.workspaceFolders.supported - ErrMsg('Error: LSP server does not support workspace folders') + util.ErrMsg('Error: LSP server does not support workspace folders') return endif if lspserver.workspaceFolders->index(dirName) != -1 - ErrMsg('Error: ' .. dirName .. ' is already part of this workspace') + util.ErrMsg('Error: ' .. dirName .. ' is already part of this workspace') return endif @@ -738,13 +768,13 @@ def s:removeWorkspaceFolder(lspserver: dict, dirName: string): void || !lspserver.caps.workspace->has_key('workspaceFolders') || !lspserver.caps.workspace.workspaceFolders->has_key('supported') || !lspserver.caps.workspace.workspaceFolders.supported - ErrMsg('Error: LSP server does not support workspace folders') + util.ErrMsg('Error: LSP server does not support workspace folders') return endif var idx: number = lspserver.workspaceFolders->index(dirName) if idx == -1 - ErrMsg('Error: ' .. dirName .. ' is not currently part of this workspace') + util.ErrMsg('Error: ' .. dirName .. ' is not currently part of this workspace') return endif @@ -764,14 +794,14 @@ def s:selectionRange(lspserver: dict, fname: string) # Check whether LSP server supports selection ranges if !lspserver.caps->has_key('selectionRangeProvider') || !lspserver.caps.selectionRangeProvider - ErrMsg("Error: LSP server does not support selection ranges") + util.ErrMsg("Error: LSP server does not support selection ranges") return endif var req = lspserver.createRequest('textDocument/selectionRange') # interface SelectionRangeParams # interface TextDocumentIdentifier - req.params->extend({textDocument: {uri: LspFileToUri(fname)}, + req.params->extend({textDocument: {uri: util.LspFileToUri(fname)}, positions: [s:getLspPosition()]}) lspserver.sendMessage(req) enddef @@ -783,14 +813,14 @@ def s:foldRange(lspserver: dict, fname: string) # Check whether LSP server supports fold ranges if !lspserver.caps->has_key('foldingRangeProvider') || !lspserver.caps.foldingRangeProvider - ErrMsg("Error: LSP server does not support folding") + util.ErrMsg("Error: LSP server does not support folding") return endif var req = lspserver.createRequest('textDocument/foldingRange') # interface FoldingRangeParams # interface TextDocumentIdentifier - req.params->extend({textDocument: {uri: LspFileToUri(fname)}}) + req.params->extend({textDocument: {uri: util.LspFileToUri(fname)}}) lspserver.sendMessage(req) enddef @@ -824,10 +854,10 @@ export def NewLspServer(path: string, args: list): dict createNotification: function('s:createNotification', [lspserver]), sendResponse: function('s:sendResponse', [lspserver]), sendMessage: function('s:sendMessage', [lspserver]), - processReply: function('ProcessReply', [lspserver]), - processNotif: function('ProcessNotif', [lspserver]), - processRequest: function('ProcessRequest', [lspserver]), - processMessages: function('ProcessMessages', [lspserver]), + processReply: function(handlers.ProcessReply, [lspserver]), + processNotif: function(handlers.ProcessNotif, [lspserver]), + processRequest: function(handlers.ProcessRequest, [lspserver]), + processMessages: function(handlers.ProcessMessages, [lspserver]), getDiagByLine: function('s:getDiagByLine', [lspserver]), textdocDidOpen: function('s:textdocDidOpen', [lspserver]), textdocDidClose: function('s:textdocDidClose', [lspserver]), diff --git a/autoload/util.vim b/autoload/util.vim index 38ece44..735febc 100644 --- a/autoload/util.vim +++ b/autoload/util.vim @@ -21,7 +21,12 @@ if has('unix') else lsp_log_dir = $TEMP .. '\\' endif -export var lsp_server_trace: bool = false +var lsp_server_trace: bool = false + +# Enable or disable LSP server trace messages +export def ServerTrace(trace_enable: bool) + lsp_server_trace = trace_enable +enddef # Log a message from the LSP server. stderr is true for logging messages # from the standard error and false for stdout. diff --git a/test/test_lsp.vim b/test/test_lsp.vim index d8330fc..4036712 100644 --- a/test/test_lsp.vim +++ b/test/test_lsp.vim @@ -131,7 +131,7 @@ def Test_lsp_show_references() cursor(1, 5) :LspShowReferences :sleep 1 - qfl = getloclist() + qfl = getloclist(0) assert_equal(1, qfl->len()) assert_equal([1, 5], [qfl[0].lnum, qfl[0].col]) -- 2.48.1