Repository: autozimu/LanguageClient-neovim (language: rust)

Issue:
Ignore buffers without language servers
## Describe the bug
Running language client commands in buffers without language servers still tries to communicate the requests to the language client binary. This has two severe effects:
1. The buffer filename is fetched (`LSP#filename`). This takes _a really long while_ for files on slow network mounts.
1. The full text of the buffer is sent using JSON. This takes _a really long while_ for very large files (think strace logs).

I'm running into this because of `LanguageClient#handleCursorMoved` (set-up automatically and does `LSP#filename`) and because of my auto-hover on cursor moved setup. I can't even disable it for irrelevant buffers because there doesn't seem to be any way to check if the language client works for the current buffer (the autocommands are only fired on server start/stop so they aren't really useful here). Either way I think it should be done automatically.

Here's the profile for moving around a network file with stock min-vimrc:
```
FUNCTION  LSP#filename()
    Defined: ~/.config/nvim/plugged/LanguageClient-neovim/autoload/LSP.vim line 3
Called 198 times
Total time:   5.045398
 Self time:   5.045398

count  total (s)   self (s)
                                " When executing autocommand, `%` might have already changed.
  198              5.038637     let l:filename = expand('<afile>:p')
  198              0.000953     if !l:filename
  198              0.003873         let l:filename = expand('%:p')
  198              0.000377     endif
  198              0.000672     return l:filename

FUNCTIONS SORTED ON TOTAL TIME
count  total (s)   self (s)  function
  198   5.114235   0.024005  LanguageClient#handleCursorMoved()
  198   5.045398             LSP#filename()
  198   0.034872   0.020608  LanguageClient#Notify()
  198   0.033183             <SNR>15_Highlight_Matching_Pair()
  198   0.008365             LanguageClient#Write()
  198   0.007587   0.004934  LSP#position()
  198   0.005900             <SNR>31_SkipSendingMessage()
  198   0.002373             LSP#viewport()
  198   0.001383             LSP#line()
  198   0.001270             LSP#character()

FUNCTIONS SORTED ON SELF TIME
count  total (s)   self (s)  function
  198              5.045398  LSP#filename()
  198              0.033183  <SNR>15_Highlight_Matching_Pair()
  198   5.114235   0.024005  LanguageClient#handleCursorMoved()
  198   0.034872   0.020608  LanguageClient#Notify()
  198              0.008365  LanguageClient#Write()
  198              0.005900  <SNR>31_SkipSendingMessage()
  198   0.007587   0.004934  LSP#position()
  198              0.002373  LSP#viewport()
  198              0.001383  LSP#line()
  198              0.001270  LSP#character()
```

## Environment
- neovim/vim version (`nvim --version` or `vim --version`): 0.4.3
- This plugin version (`git rev-parse --short HEAD`): 7c741d0
- This plugin's binary version (`bin/languageclient --version`): 0.1.156
- Minimal vimrc content:
 [min-vimrc.vim] and open a network file, or add the following and open a network or a very large file
```vim
function! DoNothingHandler(output)
endfunction

autocmd CursorMoved * call LanguageClient_textDocument_hover({'handle': v:true}, 'DoNothingHandler')
```

[min-vimrc.vim]: https://github.com/autozimu/LanguageClient-neovim/blob/next/min-vimrc.vim

## To Reproduce
Steps to reproduce the behavior:
1. Make a very large file, like strace some program to get a 9 MB text file.
1. `nvim -u min-vimrc.vim that-file`
1. Try to move the cursor around.
1. It's really slow.

## Current behavior
The vimscript part of the language client tries to do things on all buffers.

## Expected behavior
It checks a buffer-local "is language server running here" variable and if that's false does nothing immediately.



Discussion / hints:

Fix patch:
diff --git a/autoload/LanguageClient.vim b/autoload/LanguageClient.vim
index c76b2a186..07fac5bee 100644
--- a/autoload/LanguageClient.vim
+++ b/autoload/LanguageClient.vim
@@ -786,12 +786,15 @@ function! s:SkipSendingMessage() abort
         return v:false
     endif
 
-    return &buftype !=# '' || &filetype ==# '' || expand('%') ==# ''
+    let l:commands = get(g:, 'LanguageClient_serverCommands', {})
+    let l:has_command = has_key(l:commands, &filetype)
+
+    return !l:has_command || &buftype !=# '' || &filetype ==# '' || expand('%') ==# ''
 endfunction
 
 function! LanguageClient#Call(method, params, callback, ...) abort
     if s:SkipSendingMessage()
-        " call s:Debug('Skip sending message')
+        echo '[LC] Server not configured for filetype ' . &filetype
         return
     endif
 
diff --git a/plugin/LanguageClient.vim b/plugin/LanguageClient.vim
index d094899b3..d3a184609 100644
--- a/plugin/LanguageClient.vim
+++ b/plugin/LanguageClient.vim
@@ -153,25 +153,31 @@ endfunction
 command! -nargs=* LanguageClientStart :call LanguageClient#startServer(<f-args>)
 command! LanguageClientStop call LanguageClient#shutdown()
 
-augroup languageClient
+function! s:ConfigureAutocmds()
+  let l:commands = get(g:, 'LanguageClient_serverCommands', {})
+  if !has_key(l:commands, &filetype)
+    " skip setting autocmds if the filetype doesn't have a configured server command
+    return
+  endif
+
+  call LanguageClient#handleFileType()
+  augroup languageClient
     autocmd!
-    autocmd FileType * call LanguageClient#handleFileType()
-    autocmd BufNewFile * call LanguageClient#handleBufNewFile()
-    autocmd BufEnter * call LanguageClient#handleBufEnter()
-    autocmd BufWritePost * call LanguageClient#handleBufWritePost()
-    autocmd BufDelete * call LanguageClient#handleBufDelete()
-    autocmd TextChanged * call LanguageClient#handleTextChanged()
-    autocmd TextChangedI * call LanguageClient#handleTextChanged()
+    autocmd BufNewFile <buffer> call LanguageClient#handleBufNewFile()
+    autocmd BufEnter <buffer> call LanguageClient#handleBufEnter()
+    autocmd BufWritePost <buffer> call LanguageClient#handleBufWritePost()
+    autocmd BufDelete <buffer> call LanguageClient#handleBufDelete()
+    autocmd TextChanged <buffer> call LanguageClient#handleTextChanged()
+    autocmd TextChangedI <buffer> call LanguageClient#handleTextChanged()
     if exists('##TextChangedP')
-        autocmd TextChangedP * call LanguageClient#handleTextChanged()
+        autocmd TextChangedP <buffer> call LanguageClient#handleTextChanged()
     endif
-    autocmd CursorMoved * call LanguageClient#handleCursorMoved()
-    autocmd VimLeavePre * call LanguageClient#handleVimLeavePre()
-
-    autocmd CompleteDone * call LanguageClient#handleCompleteDone()
+    autocmd CursorMoved <buffer> call LanguageClient#handleCursorMoved()
+    autocmd VimLeavePre <buffer> call LanguageClient#handleVimLeavePre()
 
+    autocmd CompleteDone <buffer> call LanguageClient#handleCompleteDone()
     if get(g:, 'LanguageClient_signatureHelpOnCompleteDone', 0)
-        autocmd CompleteDone *
+        autocmd CompleteDone <buffer>
                     \ call LanguageClient#textDocument_signatureHelp({}, 's:HandleOutputNothing')
     endif
 
@@ -192,4 +198,10 @@ augroup languageClient
     nnoremap <Plug>(lcn-format-sync)        :call LanguageClient_textDocument_formatting_sync()<CR>
     nnoremap <Plug>(lcn-diagnostics-next)   :call LanguageClient_diagnosticsNext()<CR>
     nnoremap <Plug>(lcn-diagnostics-prev)   :call LanguageClient_diagnosticsPrevious()<CR>
+  augroup END
+endfunction
+
+augroup languageClient_fileType
+    autocmd!
+    autocmd FileType * call s:ConfigureAutocmds()
 augroup END


Test patch: