]> Sergey Matveev's repositories - vim-lsp.git/commitdiff
LSP plugin doesn't work after the change to the Vim9 import mechanism (patch 8.2...
authorYegappan Lakshmanan <yegappan@yahoo.com>
Sun, 9 Jan 2022 16:42:28 +0000 (08:42 -0800)
committerYegappan Lakshmanan <yegappan@yahoo.com>
Sun, 9 Jan 2022 16:44:22 +0000 (08:44 -0800)
autoload/buf.vim
autoload/handlers.vim
autoload/lsp.vim
autoload/lspoptions.vim
autoload/lspserver.vim
autoload/util.vim
test/test_lsp.vim

index 92ab8a44ad45bfda943e0ba7510e93455f228b44..763645b45a5a7dd4912a3684e2a305f88d1745a0 100644 (file)
@@ -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<string> = ['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<any>, bnr: number)
-  if !lspOptions.autoHighlightDiags
+  if !opt.lspOptions.autoHighlightDiags
     return
   endif
 
index 23264feb21a20a0f02fbf8c29bbedde2d2ac4bc8..402ba3e15b46733cfb4efb0b0cc1411a93bf9ad9 100644 (file)
@@ -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<any>, req: dict<any>, reply: dict<a
   # and then setup the below mapping for those buffers.
 
   # map characters that trigger signature help
-  if lspOptions.showSignature && caps->has_key('signatureHelpProvider')
+  if opt.lspOptions.showSignature && caps->has_key('signatureHelpProvider')
     var triggers = caps.signatureHelpProvider.triggerCharacters
     for ch in triggers
       exe 'inoremap <buffer> <silent> ' .. ch .. ' ' .. ch .. "<C-R>=lsp#showSignature()<CR>"
     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<any>, req: dict<any>, reply: dict<any>): 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<any> = gettagstack()
     if tagstack.length > 0
@@ -76,7 +102,7 @@ def s:processDefDeclReply(lspserver: dict<any>, req: dict<any>, reply: dict<any>
   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<any>, req: dict<any>, reply: dic
 
   var result: dict<any> = 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<any>, req: dict<any>, 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<any>, req: dict<any>, 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<any>, req: dict<any>, reply: dict<a
     completeItems->add(d)
   endfor
 
-  if lspOptions.autoComplete
+  if opt.lspOptions.autoComplete
     if completeItems->empty()
       # no matches
       return
@@ -305,14 +331,14 @@ def s:processHoverReply(lspserver: dict<any>, req: dict<any>, reply: dict<any>):
         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<any>, req: dict<any>, reply: dict<any>):
     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<any>, req: dict<any>, reply: dict<any>): 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<any>, req: dict<any>, reply: dict<a
   var locations: list<dict<any>> = reply.result
   var qflist: list<dict<any>> = []
   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<any>, req: dict<any>, reply: dict<a
                                                ->trim("\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<any>, req: dict<any>, 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<any>, req: dict<any>, 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<dict<any>>,
   var symInfo: dict<any>
 
   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<any>, req: dict<any>, reply: dict<an
   var symbolLineTable: list<dict<any>> = []
 
   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<string>, A: list<number>, B: list<number>,
   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<dict<any>>): 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<any>)
-  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<any>)
   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<any>)
 
   var save_cursor: list<number> = 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<any>, req: dict<any>, reply: dict<any>)
 
   # 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<any>, req: dict<any>, reply: dict<any>)
   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<any>, req: dict<any>, reply: di
 
   var r: dict<dict<number>> = 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<any>, req: dict<any>, 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<any>, req: dict<any>, reply: dict<any>):
   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<any>, reply: dict<any>): 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<any>, reply: dict<any>): 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<any>, reply: dict<any>)
     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<any>, reply: dict<any>)
-  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<any>, reply: dict<any>): 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<any>, request: dict<any>)
   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<any>, request: dict<any>)
-  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<any>, request: dict<any>)
   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<any>): 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<any>): 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<any>): 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<any>): 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 :]
index 932aa95e48ca7900e07d4c64b0e055a301bf25b1..4c66326ce10f4968a78f208286a729ad55f4a1e6 100644 (file)
@@ -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<any>)
-  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<any>
 enddef
 
 # Add a LSP server for a filetype
-def s:lspAddServer(ftype: string, lspserver: dict<any>)
-  ftypeServerMap->extend({[ftype]: lspserver})
+def s:lspAddServer(ftype: string, lspsrv: dict<any>)
+  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<any> = 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<any> = 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<any> = 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<any> = 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<any> = 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')
     # <Enter> in insert mode stops completion and inserts a <Enter>
@@ -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 <buffer=' .. bnr .. '> call s:lspSavedFile()'
 
-    if lspOptions.autoComplete
+    if opt.lspOptions.autoComplete
       # Trigger 24x7 insert mode completion when text is changed
       exe 'autocmd TextChangedI <buffer=' .. bnr .. '> 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 <buffer=' .. bnr .. '> 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<dict<any>>)
   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<dict<any>>)
     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<any> = NewLspServer(server.path, server.args)
+    var lspserver: dict<any> = 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<dict<any>>)
         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<any> = 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<any> = 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<any> = 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<any> = 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<number>
 enddef
 
 # sort the diaganostics messages for a buffer by line number
-def s:getSortedDiagLines(lspserver: dict<any>, bnr: number): list<number>
+def s:getSortedDiagLines(lspsrv: dict<any>, bnr: number): list<number>
   # create a list of line numbers from the diag map keys
   var lnums: list<number> =
-               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<any> = 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<any> = 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<any> = 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<any> = 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<any> = 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<any> = 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<any> = 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<any>, popupID: number, key: string): bool
+def s:filterSymbols(lspsrv: dict<any>, 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 == "\<BS>" || key == "\<C-H>"
     # Erase one character from the filter text
@@ -1248,7 +1280,7 @@ def s:filterSymbols(lspserver: dict<any>, 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<any>, 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<any>, query: string)
+def s:showSymbolMenu(lspsrv: dict<any>, query: string)
   # Create the popup menu
   var lnum = &lines - &cmdheight - 2 - 10
   var popupAttr = {
@@ -1322,13 +1354,13 @@ def s:showSymbolMenu(lspserver: dict<any>, 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<any> = 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<any> = 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<any> = 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<any> = 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<any> = 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<any> = 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
 
index 6edd8b14d37be61cac5b2cb8ffab2bdc00c21540..82984366a63167ddc4b540c7860ae274d5aca141 100644 (file)
@@ -18,3 +18,10 @@ export var lspOptions: dict<any> = {
   # 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<any>)
+  for key in opts->keys()
+    lspOptions[key] = opts[key]
+  endfor
+enddef
index cae1d2c760d22ed73b416b3f07d7acb81c5ee82d..c91021acb3f2750cc050ac475767f464376284ab 100644 (file)
@@ -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<any>, 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<any>, chan: channel, emsg: string,): void
-  TraceLog(true, emsg)
+  util.TraceLog(true, emsg)
 enddef
 
 # LSP server exit callback
 def s:exit_cb(lspserver: dict<any>, 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<any>): 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<any>): 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<any>)
       }
   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<any>): 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<any>, 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<any>, 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<any>, bnr: number, start: number,
   # interface DidChangeTextDocumentParams
   #   interface VersionedTextDocumentIdentifier
   var vtdid: dict<any> = {}
-  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<dict<any>>
   # 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<any>, 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<any>): 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<any>): 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<any>): 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<any>): 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<any>): 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<any>, bnr: number): void
 
   var notif: dict<any> = 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<any>): 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<any>): 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<any>, 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<any>, 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<any>, 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<dict<number>> = {
@@ -616,7 +646,7 @@ def s:incomingCalls(lspserver: dict<any>, 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<any>, 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<any>, 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<any>, fname_arg: string)
   var r: dict<dict<number>> = {
                  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<dict<any>> = []
   var lnum = line('.')
   var diagInfo: dict<any> = lspserver.getDiagByLine(bnr, lnum)
@@ -693,7 +723,7 @@ def s:workspaceQuerySymbols(lspserver: dict<any>, 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<any>, 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<any>, 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<any>, 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<any>, 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<string>): dict<any>
     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]),
index 38ece443b8524de84ccda0eec4df019d9c4ee12b..735febccf23a98ce054a6554730851ab5f94e2dc 100644 (file)
@@ -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.
index d8330fc55dbf389d342ede62ad2c7424f7101850..40367128751c8403b1329cceba86a9131cbba428 100644 (file)
@@ -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])