]> Sergey Matveev's repositories - vim-lsp.git/commitdiff
Report didOpen, didSave and didClose to all servers for a buffer
authorAndreas Louv <andreas@louv.dk>
Tue, 11 Apr 2023 14:40:02 +0000 (16:40 +0200)
committerAndreas Louv <andreas@louv.dk>
Thu, 13 Apr 2023 05:41:48 +0000 (07:41 +0200)
autoload/lsp/buffer.vim
autoload/lsp/lsp.vim
doc/lsp.txt

index aa41dfda2b83a9d98d52a9b3818b2a4e93c9b5b8..26897b02423081494497888e46c9608b9f15487e 100644 (file)
@@ -45,6 +45,22 @@ export def BufLspServerGet(bnr: number): dict<any>
   return bufnrToServers[bnr][0]
 enddef
 
+# Returns the LSP server for the buffer 'bnr' and with ID 'id'. Returns an empty
+# dict if the server is not found.
+export def BufLspServerGetById(bnr: number, id: number): dict<any>
+  if !bufnrToServers->has_key(bnr)
+    return {}
+  endif
+
+  for lspserver in bufnrToServers[bnr]
+    if lspserver.id == id
+      return lspserver
+    endif
+  endfor
+
+  return {}
+enddef
+
 # Returns the LSP servers for the buffer 'bnr'. Returns an empty list if the
 # servers are not found.
 export def BufLspServersGet(bnr: number): list<dict<any>>
index 8eb97a27625b7bd9a25728f614c1d6a74429c8bf..c8db52cc58acc064ec66d7202dde3bc0d8df6ecd 100644 (file)
@@ -43,36 +43,41 @@ def LspInitOnce()
   lspInitializedOnce = true
 enddef
 
-# Returns the LSP server for the a specific filetype. Returns an empty dict if
-# the server is not found.
-def LspGetServer(bnr: number, ftype: string): dict<any>
-  if ftypeServerMap->has_key(ftype)
-    var lspservers = ftypeServerMap[ftype]
+# Returns the LSP servers for the a specific filetype. Based on how well there
+# score, LSP servers with the same score are being returned.
+# Returns an empty list if the servers is not found.
+def LspGetServers(bnr: number, ftype: string): list<dict<any>>
+  if !ftypeServerMap->has_key(ftype)
+    return []
+  endif
 
-    # The best language server for the current buffer
-    var bestMatch: dict<any> = {}
-    var bestScore: number = -1
+  var lspservers = ftypeServerMap[ftype]
 
-    var bufDir = bnr->bufname()->fnamemodify(':p:h')
+  # All the langauge servers with the same score are being used
+  var bestMatches: list<dict<any>> = []
+  var bestScore: number = 0
 
-    for lspserver in lspservers
-      var score: number = 0
-      if !lspserver.rootSearchFiles->empty()
-        # The score is calculated by how deep the workspace root dir is, the
-        # deeper the better.
-        var path = util.FindNearestRootDir(bufDir, lspserver.rootSearchFiles)
-        score = path->strcharlen()
-      endif
-      if score > bestScore
-        bestMatch = lspserver
-        bestScore = score
-      endif
-    endfor
+  var bufDir = bnr->bufname()->fnamemodify(':p:h')
 
-    return bestMatch
-  endif
+  for lspserver in lspservers
+    var score: number = 0
+
+    if !lspserver.rootSearchFiles->empty()
+      # The score is calculated by how deep the workspace root dir is, the
+      # deeper the better.
+      var path = util.FindNearestRootDir(bufDir, lspserver.rootSearchFiles)
+      score = path->strcharlen()
+    endif
+
+    if score > bestScore
+      bestMatches = [lspserver]
+      bestScore = score
+    elseif score == bestScore
+      bestMatches->add(lspserver)
+    endif
+  endfor
 
-  return {}
+  return bestMatches
 enddef
 
 # Add a LSP server for a filetype
@@ -295,25 +300,20 @@ def g:LspShowSignature(): string
   return ''
 enddef
 
-# buffer change notification listener
-def Bufchange_listener(bnr: number, start: number, end: number, added: number, changes: list<dict<number>>)
-  var lspserver: dict<any> = buf.CurbufGetServer()
-  if lspserver->empty() || !lspserver.running
-    return
-  endif
-
-  lspserver.textdocDidChange(bnr, start, end, added, changes)
-enddef
-
 # A buffer is saved. Send the "textDocument/didSave" LSP notification
 def LspSavedFile()
   var bnr: number = expand('<abuf>')->str2nr()
-  var lspserver: dict<any> = buf.BufLspServerGet(bnr)
-  if lspserver->empty() || !lspserver.running
+  var lspservers: list<dict<any>> = buf.BufLspServersGet(bnr)->filter(
+    (key, lspsrv) => !lspsrv->empty() && lspsrv.running
+  )
+
+  if lspservers->empty()
     return
   endif
 
-  lspserver.didSaveFile(bnr)
+  for lspserver in lspservers
+    lspserver.didSaveFile(bnr)
+  endfor
 enddef
 
 # Return the diagnostic text from the LSP server for the current mouse line to
@@ -401,8 +401,8 @@ def AddBufLocalAutocmds(lspserver: dict<any>, bnr: number): void
   autocmd_add(acmds)
 enddef
 
-def BufferInit(bnr: number): void
-  var lspserver: dict<any> = buf.BufLspServerGet(bnr)
+def BufferInit(lspserverId: number, bnr: number): void
+  var lspserver = buf.BufLspServerGetById(bnr, lspserverId)
   if lspserver->empty() || !lspserver.running
     return
   endif
@@ -411,7 +411,9 @@ def BufferInit(bnr: number): void
   lspserver.textdocDidOpen(bnr, ftype)
 
   # add a listener to track changes to this buffer
-  listener_add(Bufchange_listener, bnr)
+  listener_add((_bnr: number, start: number, end: number, added: number, changes: list<dict<number>>) => {
+    lspserver.textdocDidChange(bnr, start, end, added, changes)
+  }, bnr)
 
   AddBufLocalAutocmds(lspserver, bnr)
 
@@ -442,39 +444,42 @@ export def AddFile(bnr: number): void
   if ftype == ''
     return
   endif
-  var lspserver: dict<any> = LspGetServer(bnr, ftype)
-  if lspserver->empty()
+  var lspservers: list<dict<any>> = LspGetServers(bnr, ftype)
+  if lspservers->empty()
     return
   endif
-  if !lspserver.running
-    if !lspInitializedOnce
-      LspInitOnce()
+  for lspserver in lspservers
+    if !lspserver.running
+      if !lspInitializedOnce
+        LspInitOnce()
+      endif
+      lspserver.startServer(bnr)
     endif
-    lspserver.startServer(bnr)
-  endif
-  buf.BufLspServerSet(bnr, lspserver)
-
-  if lspserver.ready
-    BufferInit(bnr)
-  else
-    augroup LSPBufferAutocmds
-      exe $'autocmd User LspServerReady{lspserver.name} ++once BufferInit({bnr})'
-    augroup END
-  endif
+    buf.BufLspServerSet(bnr, lspserver)
 
+    if lspserver.ready
+      BufferInit(lspserver.id, bnr)
+    else
+      augroup LSPBufferAutocmds
+        exe $'autocmd User LspServerReady{lspserver.name} ++once BufferInit({lspserver.id}, {bnr})'
+      augroup END
+    endif
+  endfor
 enddef
 
 # Notify LSP server to remove a file
 export def RemoveFile(bnr: number): void
-  var lspserver: dict<any> = buf.BufLspServerGet(bnr)
-  if lspserver->empty()
-    return
-  endif
-  if lspserver.running
-    lspserver.textdocDidClose(bnr)
-  endif
-  diag.DiagRemoveFile(lspserver, bnr)
-  buf.BufLspServerRemove(bnr)
+  var lspservers: list<dict<any>> = buf.BufLspServersGet(bnr)
+  for lspserver in lspservers->copy()
+    if lspserver->empty()
+      continue
+    endif
+    if lspserver.running
+      lspserver.textdocDidClose(bnr)
+    endif
+    diag.DiagRemoveFile(lspserver, bnr)
+    buf.BufLspServerRemove(bnr, lspserver)
+  endfor
 enddef
 
 # Stop all the LSP servers
index 291936ea1d590c907a6711a1eccad152aaf96bc3..0ae3e000bf70248417e46756f3d6e6c86fbb970d 100644 (file)
@@ -267,8 +267,8 @@ To add a language server, the following information is needed:
 
                        This option is also used to decide which server to run
                        when multiple servers are defined for a filetype. The
-                       server with the longest found workspace root will be
-                       selected as the relevant language server for a given
+                       servers that share the longest found workspace root will
+                       be selected as the relevant language servers for a given
                        file.
 
                        If this parameter is not specified or the files are not