yegappan / lsp

Language Server Protocol (LSP) plugin for Vim9
MIT License
473 stars 57 forks source link

Fix adding server multiple times #531

Closed nv-quan closed 2 weeks ago

nv-quan commented 3 months ago

g:LspAddServer can be called multiple times for various reasons. This PR prevents that by checking if an LSP server with the same name has already been added for that filetype and returning early if one is found.

Reasons that LspAddServer might be called multiple times include being added in a filetype plugin or when the vimrc is sourced multiple times.

This possibly fixes #522 and some other performance issues. I accidentally found this when it bogged down vim and noticed that some lines are called hundreds of thousands of times in just a few keystrokes.

    Defined: ~/.vim/pack/downloads/opt/lsp/autoload/lsp/buffer.vim:66
Called 8067 times
Total time:  11.400077000
 Self time:   5.663494000

count     total (s)      self (s)
 8067                 0.001572000   if !bufnrToServers->has_key(bnr)
                                      return {}
                                    endif

 8066                 0.001701000   if bufnrToServers[bnr]->empty()
                                      return {}
                                    endif

 8066                 0.000926000   if feature == null_string
                                      return bufnrToServers[bnr][0]
                                    endif

 8064                 0.001146000   if !SupportedCheckFns->has_key(feature)
                                      # If this happns it is a programming error, and should be fixed in the
                                      # source code
                                      :throw $'Error: ''{feature}'' is not a valid feature'
                                    endif

 8064                 0.001081000   var SupportedCheckFn = SupportedCheckFns[feature]

 8064                 0.000535000   var possibleLSPs: list<dict<any>> = []

 8064                 0.001602000   for lspserver in bufnrToServers[bnr]
341376   5.660879000   0.051329000     if !lspserver.ready || !SupportedCheckFn(lspserver)
                                        continue
                                      endif

341376                 5.334354000     possibleLSPs->add(lspserver)
341376                 0.010544000   endfor

 8064                 0.000585000   if possibleLSPs->empty()
                                      return {}
                                    endif

                                    # LSP server is configured to be a provider for "feature"
 8064                 0.000394000   for lspserver in possibleLSPs
341376                 0.049017000     var has_feature: bool = lspserver.features->get(feature, false)
341376                 0.010424000     if has_feature
                                        return lspserver
                                      endif
341376                 0.008944000   endfor

                                    # Return the first LSP server that supports "feature" and doesn't have it
                                    # disabled
 8064                 0.000399000   for lspserver in possibleLSPs
 8064   0.261338000   0.134305000     if lspserver.featureEnabled(feature)
                                        return lspserver
                                      endif
                                    endfor

                                    return {}