From 43e6f3a7e37feb797727a61aa86afde22e86e40a Mon Sep 17 00:00:00 2001 From: Yegappan Lakshmanan Date: Mon, 4 Jan 2021 22:05:03 -0800 Subject: [PATCH] Update comments --- README.md | 11 +++++++- autoload/handlers.vim | 58 +++++++++++++++++++++++++++++--------- autoload/lsp.vim | 5 ++-- autoload/lspserver.vim | 63 ++++++++++++++++++++++++++++++++++++++---- 4 files changed, 116 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 66a968d..e56c569 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ args|a list of command-line arguments passed to the LSP server. Each argument is The LSP servers are added using the lsp#addServer() function. This function accepts a list of LSP servers with the above information. -## Commands +## Supported Commands Command|Description -------|----------- :LspShowServers|Display the list of registered LSP servers @@ -77,3 +77,12 @@ Command|Description :LspWorkspaceAddFolder `{folder}`| Add a folder to the workspace :LspWorkspaceRemoveFolder `{folder}`|Remove a folder from the workspace :LspWorkspaceListFolders|Show the list of folders in the workspace + +## Similar Vim LSP Plugins + +1. [vim-lsp](https://github.com/prabirshrestha/vim-lsp) +1. [Coc](https://github.com/neoclide/coc.nvim) +1. [vim-lsc](https://github.com/natebosch/vim-lsc) +1. [LanguageClient-neovim](https://github.com/autozimu/LanguageClient-neovim) +1. [Neovim built-in LSP client](https://neovim.io/doc/user/lsp.html) +1. [ALE](https://github.com/dense-analysis/ale) diff --git a/autoload/handlers.vim b/autoload/handlers.vim index 4c589fc..4cfe3ab 100644 --- a/autoload/handlers.vim +++ b/autoload/handlers.vim @@ -1,14 +1,18 @@ vim9script -import {WarnMsg, ErrMsg, LspUriToFile} from './util.vim' +# Handlers for messages from the LSP server +# Refer to https://microsoft.github.io/language-server-protocol/specification +# for the Language Server Protocol (LSP) specificaiton. + +import {WarnMsg, ErrMsg, TraceLog, LspUriToFile} from './util.vim' # process the 'initialize' method reply from the LSP server +# Result: InitializeResult def s:processInitializeReply(lspserver: dict, req: dict, reply: dict): void if reply.result->len() <= 0 return endif - # interface 'InitializeResult' var caps: dict = reply.result.capabilities lspserver.caps = caps @@ -38,6 +42,7 @@ enddef # process the 'textDocument/definition' / 'textDocument/declaration' / # 'textDocument/typeDefinition' and 'textDocument/implementation' replies from # the LSP server +# 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") @@ -64,6 +69,7 @@ def s:processDefDeclReply(lspserver: dict, req: dict, reply: dict enddef # process the 'textDocument/signatureHelp' reply from the LSP server +# Result: SignatureHelp | null def s:processSignaturehelpReply(lspserver: dict, req: dict, reply: dict): void var result: dict = reply.result if result.signatures->len() <= 0 @@ -126,6 +132,7 @@ def LspCompleteItemKindChar(kind: number): string enddef # process the 'textDocument/completion' reply from the LSP server +# Result: CompletionItem[] | CompletionList | null def s:processCompletionReply(lspserver: dict, req: dict, reply: dict): void var items: list> @@ -168,6 +175,7 @@ def s:processCompletionReply(lspserver: dict, req: dict, reply: dict, req: dict, reply: dict): void if type(reply.result) == v:t_none return @@ -215,6 +223,7 @@ def s:processHoverReply(lspserver: dict, req: dict, reply: dict): enddef # process the 'textDocument/references' reply from the LSP server +# Result: Location[] | null def s:processReferencesReply(lspserver: dict, req: dict, reply: dict): void if type(reply.result) == v:t_none || reply.result->empty() WarnMsg('Error: No references found') @@ -247,6 +256,7 @@ def s:processReferencesReply(lspserver: dict, req: dict, reply: dict, req: dict, reply: dict): void if reply.result->empty() return @@ -353,6 +363,7 @@ enddef # process the 'textDocument/documentSymbol' reply from the LSP server # Open a symbols window and display the symbols as a tree +# Result: DocumentSymbol[] | SymbolInformation[] | null def s:processDocSymbolReply(lspserver: dict, req: dict, reply: dict): void if reply.result->empty() WarnMsg('No symbols are found') @@ -623,6 +634,7 @@ def s:applyWorkspaceEdit(workspaceEdit: dict) enddef # process the 'textDocument/formatting' reply from the LSP server +# Result: TextEdit[] | null def s:processFormatReply(lspserver: dict, req: dict, reply: dict) if reply.result->empty() # nothing to format @@ -645,7 +657,9 @@ def s:processFormatReply(lspserver: dict, req: dict, reply: dict) save_cursor->setpos('.') enddef -# process the 'textDocument/rename' reply from the LSP server +# Reply: 'textDocument/rename' +# Result: Range | { range: Range, placeholder: string } +# | { defaultBehavior: boolean } | null def s:processRenameReply(lspserver: dict, req: dict, reply: dict) if reply.result->empty() # nothing to rename @@ -656,7 +670,9 @@ def s:processRenameReply(lspserver: dict, req: dict, reply: dict) s:applyWorkspaceEdit(reply.result) enddef -# interface ExecuteCommandParams +# Request the LSP server to execute a command +# Request: workspace/executeCommand +# Params: ExecuteCommandParams def s:executeCommand(lspserver: dict, cmd: dict) var req = lspserver.createRequest('workspace/executeCommand') req.params->extend(cmd) @@ -664,7 +680,7 @@ def s:executeCommand(lspserver: dict, cmd: dict) enddef # process the 'textDocument/codeAction' reply from the LSP server -# params: interface Command[] | interface CodeAction[] +# Result: (Command | CodeAction)[] | null def s:processCodeActionReply(lspserver: dict, req: dict, reply: dict) if reply.result->empty() # no action can be performed @@ -705,7 +721,8 @@ def s:processCodeActionReply(lspserver: dict, req: dict, reply: dict, req: dict, reply: dict) if reply.result->empty() return @@ -718,7 +735,8 @@ def s:processSelectionRangeReply(lspserver: dict, req: dict, reply: di :normal gv enddef -# process the 'textDocument/foldingRange' reply from the LSP server +# Reply: 'textDocument/foldingRange' +# Result: FoldingRange[] | null def s:processFoldingRangeReply(lspserver: dict, req: dict, reply: dict) if reply.result->empty() return @@ -762,7 +780,7 @@ def s:makeMenuName(popupWidth: number, fname: string): string # keep some characters at the beginning and end (equally). # 6 spaces are used for "..." and " ()" var dirsz = (popupWidth - flen - 6) / 2 - dirname = dirname[:dirsz] .. '...' .. dirname[-dirsz:] + dirname = dirname[: dirsz] .. '...' .. dirname[-dirsz : ] endif var str: string = filename if dirname != '.' @@ -772,6 +790,7 @@ def s:makeMenuName(popupWidth: number, fname: string): string enddef # process the 'workspace/symbol' reply from the LSP server +# Result: SymbolInformation[] | null def s:processWorkspaceSymbolReply(lspserver: dict, req: dict, reply: dict) if reply.result->empty() return @@ -845,7 +864,7 @@ export def ProcessReply(lspserver: dict, req: dict, reply: dict): enddef # process a diagnostic notification message from the LSP server -# params: interface PublishDiagnosticsParams +# Param: PublishDiagnosticsParams def s:processDiagNotif(lspserver: dict, reply: dict): void var fname: string = LspUriToFile(reply.params.uri) @@ -858,9 +877,9 @@ def s:processDiagNotif(lspserver: dict, reply: dict): void lspserver.diagsMap->extend({[fname]: diag_by_lnum}) enddef -# process a log notification message from the LSP server -def s:processLogMsgNotif(lspserver: dict, reply: dict) - # interface LogMessageParams +# process a show notification message from the LSP server +# Param: ShowMessageParams +def s:processShowMsgNotif(lspserver: dict, reply: dict) var msgType: list = ['', 'Error: ', 'Warning: ', 'Info: ', 'Log: '] if reply.params.type == 4 # ignore log messages from the LSP server (too chatty) @@ -877,12 +896,24 @@ def s:processLogMsgNotif(lspserver: dict, reply: dict) :echomsg 'Lsp ' .. mtype .. reply.params.message enddef +# process a log notification message from the LSP server +# Param: LogMessageParams +def s:processLogMsgNotif(lspserver: dict, reply: dict) + var msgType: list = ['', 'Error: ', 'Warning: ', 'Info: ', 'Log: '] + var mtype: string = 'Log: ' + if reply.params.type > 0 && reply.params.type < 5 + mtype = msgType[reply.params.type] + endif + + TraceLog(false, '[' .. mtype .. ']: ' .. reply.params.message) +enddef + # process notification messages from the LSP server export def ProcessNotif(lspserver: dict, reply: dict): void var lsp_notif_handlers: dict = { 'textDocument/publishDiagnostics': function('s:processDiagNotif'), - 'window/showMessage': function('s:processLogMsgNotif'), + 'window/showMessage': function('s:processShowMsgNotif'), 'window/logMessage': function('s:processLogMsgNotif') } @@ -894,6 +925,7 @@ export def ProcessNotif(lspserver: dict, reply: dict): void enddef # process the workspace/applyEdit LSP server request +# Param: ApplyWorkspaceEditParams def s:processApplyEditReq(lspserver: dict, request: dict) # interface ApplyWorkspaceEditParams if !request->has_key('params') diff --git a/autoload/lsp.vim b/autoload/lsp.vim index ff0cc96..f983c2f 100644 --- a/autoload/lsp.vim +++ b/autoload/lsp.vim @@ -304,6 +304,7 @@ def lsp#addServer(serverList: list>) enddef # set the LSP server trace level for the current buffer +# Params: SetTraceParams def lsp#setTraceServer(traceVal: string) if ['off', 'message', 'verbose']->index(traceVal) == -1 ErrMsg("Error: Unsupported LSP server trace value " .. traceVal) @@ -949,7 +950,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.workspaceSymbols(query) + lspserver.workspaceQuery(query) endif echo 'Symbol: ' .. query endif @@ -1060,7 +1061,7 @@ def lsp#symbolSearch(queryArg: string) s:showSymbolMenu(lspserver, query) - if !lspserver.workspaceSymbols(query) + if !lspserver.workspaceQuery(query) lspserver.workspaceSymbolPopup->popup_close() endif enddef diff --git a/autoload/lspserver.vim b/autoload/lspserver.vim index c82f731..6e29885 100644 --- a/autoload/lspserver.vim +++ b/autoload/lspserver.vim @@ -1,6 +1,8 @@ vim9script # LSP server functions +# Refer to https://microsoft.github.io/language-server-protocol/specification +# for the Language Server Protocol (LSP) specificaiton. import {ProcessReply, ProcessNotif, ProcessRequest, ProcessMessages} from './handlers.vim' import {WarnMsg, ErrMsg, ClearTraceLogs, TraceLog, LspUriToFile, LspFileToUri} from './util.vim' @@ -68,7 +70,8 @@ def s:startServer(lspserver: dict): number return 0 enddef -# Send a "initialize" LSP request +# Request: 'initialize' +# Param: InitializeParams def s:initServer(lspserver: dict) var req = lspserver.createRequest('initialize') @@ -121,18 +124,21 @@ def s:initServer(lspserver: dict) enddef # Send a "initialized" LSP notification +# Params: InitializedParams def s:sendInitializedNotif(lspserver: dict) var notif: dict = lspserver.createNotification('initialized') lspserver.sendMessage(notif) enddef -# Send a 'shutdown' request to the LSP server +# Request: shutdown +# Param: void def s:shutdownServer(lspserver: dict): void var req = lspserver.createRequest('shutdown') lspserver.sendMessage(req) enddef # Send a 'exit' notification to the LSP server +# Params: void def s:exitServer(lspserver: dict): void var notif: dict = lspserver.createNotification('exit') lspserver.sendMessage(notif) @@ -227,6 +233,7 @@ def s:sendMessage(lspserver: dict, content: dict): void enddef # Send a LSP "textDocument/didOpen" notification +# Params: DidOpenTextDocumentParams def s:textdocDidOpen(lspserver: dict, bnr: number, ftype: string): void var notif: dict = lspserver.createNotification('textDocument/didOpen') @@ -256,6 +263,7 @@ def s:textdocDidClose(lspserver: dict, bnr: number): void enddef # Send a LSP "textDocument/didChange" notification +# Params: DidChangeTextDocumentParams def s:textdocDidChange(lspserver: dict, bnr: number, start: number, end: number, added: number, changes: list>): void @@ -332,6 +340,9 @@ def s:getLspTextDocPosition(): dict> position: s:getLspPosition()} enddef +# Get a list of completion items. +# Request: "textDocument/completion" +# Param: CompletionParams def s:getCompletion(lspserver: dict): void # Check whether LSP server supports completion if !lspserver.caps->has_key('completionProvider') @@ -366,6 +377,8 @@ def s:pushCursorToTagStack() }]}, 'a') enddef +# Request: "textDocument/definition" +# Param: DefinitionParams def s:gotoDefinition(lspserver: dict): void # Check whether LSP server supports jumping to a definition if !lspserver.caps->has_key('definitionProvider') @@ -382,6 +395,8 @@ def s:gotoDefinition(lspserver: dict): void lspserver.sendMessage(req) enddef +# Request: "textDocument/declaration" +# Param: DeclarationParams def s:gotoDeclaration(lspserver: dict): void # Check whether LSP server supports jumping to a declaration if !lspserver.caps->has_key('declarationProvider') @@ -400,6 +415,8 @@ def s:gotoDeclaration(lspserver: dict): void lspserver.sendMessage(req) enddef +# Request: "textDocument/typeDefinition" +# Param: TypeDefinitionParams def s:gotoTypeDef(lspserver: dict): void # Check whether LSP server supports jumping to a type definition if !lspserver.caps->has_key('typeDefinitionProvider') @@ -418,6 +435,8 @@ def s:gotoTypeDef(lspserver: dict): void lspserver.sendMessage(req) enddef +# Request: "textDocument/implementation" +# Param: ImplementationParams def s:gotoImplementation(lspserver: dict): void # Check whether LSP server supports jumping to a implementation if !lspserver.caps->has_key('implementationProvider') @@ -436,6 +455,9 @@ def s:gotoImplementation(lspserver: dict): void lspserver.sendMessage(req) enddef +# get symbol signature help. +# Request: "textDocument/signatureHelp" +# Param: SignatureHelpParams def s:showSignature(lspserver: dict): void # Check whether LSP server supports signature help if !lspserver.caps->has_key('signatureHelpProvider') @@ -467,6 +489,9 @@ def s:didSaveFile(lspserver: dict, bnr: number): void lspserver.sendMessage(notif) enddef +# get the hover information +# Request: "textDocument/hover" +# Param: HoverParams def s:hover(lspserver: dict): void # Check whether LSP server supports getting hover information if !lspserver.caps->has_key('hoverProvider') @@ -481,6 +506,8 @@ def s:hover(lspserver: dict): void lspserver.sendMessage(req) enddef +# Request: "textDocument/references" +# Param: ReferenceParams def s:showReferences(lspserver: dict): void # Check whether LSP server supports getting reference information if !lspserver.caps->has_key('referencesProvider') @@ -498,6 +525,8 @@ def s:showReferences(lspserver: dict): void lspserver.sendMessage(req) enddef +# Request: "textDocument/documentHighlight" +# Param: DocumentHighlightParams def s:docHighlight(lspserver: dict): void # Check whether LSP server supports getting highlight information if !lspserver.caps->has_key('documentHighlightProvider') @@ -513,6 +542,8 @@ def s:docHighlight(lspserver: dict): void lspserver.sendMessage(req) enddef +# Request: "textDocument/documentSymbol" +# Param: DocumentSymbolParams def s:getDocSymbols(lspserver: dict, fname: string): void # Check whether LSP server supports getting document symbol information if !lspserver.caps->has_key('documentSymbolProvider') @@ -528,6 +559,11 @@ def s:getDocSymbols(lspserver: dict, fname: string): void lspserver.sendMessage(req) enddef +# Request: "textDocument/formatting" +# Param: DocumentFormattingParams +# or +# Request: "textDocument/rangeFormatting" +# Param: DocumentRangeFormattingParams def s:textDocFormat(lspserver: dict, fname: string, rangeFormat: bool, start_lnum: number, end_lnum: number) # Check whether LSP server supports formatting documents @@ -572,6 +608,8 @@ def s:textDocFormat(lspserver: dict, fname: string, rangeFormat: bool, lspserver.sendMessage(req) enddef +# Request: "textDocument/rename" +# Param: RenameParams def s:renameSymbol(lspserver: dict, newName: string) # Check whether LSP server supports rename operation if !lspserver.caps->has_key('renameProvider') @@ -588,6 +626,8 @@ def s:renameSymbol(lspserver: dict, newName: string) lspserver.sendMessage(req) enddef +# Request: "textDocument/codeAction" +# Param: CodeActionParams def s:codeAction(lspserver: dict, fname_arg: string) # Check whether LSP server supports code action operation if !lspserver.caps->has_key('codeActionProvider') @@ -616,7 +656,10 @@ def s:codeAction(lspserver: dict, fname_arg: string) lspserver.sendMessage(req) enddef -def s:workspaceSymbols(lspserver: dict, sym: string): bool +# List project-wide symbols matching query string +# Request: "workspace/symbol" +# Param: WorkspaceSymbolParams +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 @@ -625,12 +668,15 @@ def s:workspaceSymbols(lspserver: dict, sym: string): bool endif var req = lspserver.createRequest('workspace/symbol') - req.params->extend({query: sym}) + req.params->extend({query: query}) lspserver.sendMessage(req) return true enddef +# Add a workspace folder to the LSP server. +# Request: "workspace/didChangeWorkspaceFolders" +# Param: DidChangeWorkspaceFoldersParams def s:addWorkspaceFolder(lspserver: dict, dirName: string): void if !lspserver.caps->has_key('workspace') || !lspserver.caps.workspace->has_key('workspaceFolders') @@ -654,6 +700,9 @@ def s:addWorkspaceFolder(lspserver: dict, dirName: string): void lspserver.workspaceFolders->add(dirName) enddef +# Remove a workspace folder from the LSP server. +# Request: "workspace/didChangeWorkspaceFolders" +# Param: DidChangeWorkspaceFoldersParams def s:removeWorkspaceFolder(lspserver: dict, dirName: string): void if !lspserver.caps->has_key('workspace') || !lspserver.caps.workspace->has_key('workspaceFolders') @@ -679,6 +728,8 @@ def s:removeWorkspaceFolder(lspserver: dict, dirName: string): void enddef # select the text around the current cursor location +# Request: "textDocument/selectionRange" +# Param: SelectionRangeParams def s:selectionRange(lspserver: dict, fname: string) # Check whether LSP server supports selection ranges if !lspserver.caps->has_key('selectionRangeProvider') @@ -696,6 +747,8 @@ def s:selectionRange(lspserver: dict, fname: string) enddef # fold the entire document +# Request: "textDocument/foldingRange" +# Param: FoldingRangeParams def s:foldRange(lspserver: dict, fname: string) # Check whether LSP server supports fold ranges if !lspserver.caps->has_key('foldingRangeProvider') @@ -762,7 +815,7 @@ export def NewLspServer(path: string, args: list): dict textDocFormat: function('s:textDocFormat', [lspserver]), renameSymbol: function('s:renameSymbol', [lspserver]), codeAction: function('s:codeAction', [lspserver]), - workspaceSymbols: function('s:workspaceSymbols', [lspserver]), + workspaceQuery: function('s:workspaceQuerySymbols', [lspserver]), addWorkspaceFolder: function('s:addWorkspaceFolder', [lspserver]), removeWorkspaceFolder: function('s:removeWorkspaceFolder', [lspserver]), selectionRange: function('s:selectionRange', [lspserver]), -- 2.48.1