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

Issue:
Semantic highlighting doesn't refresh state in second buffer
## Describe the bug
Semantic highlighting (i.e. `LanguageClient#textDocument_documentHighlight()`) does not refresh its state in the second (or greater) buffer opened with a given language server.

Semantic highlighting works correctly in the first buffer opened for a language. For instance, if I open `test.py` and run `:call LanguageClient#textDocument_documentHighlight()` with the cursor over a few different variables, those variables are highlighted, and when the command is re-run on another variable, the original highlights are correctly turned off and the new variable is correctly highlighted.

If I then open, for example, `test2.py` and repeat the experiment, I still get correct highlighting of the variables under my cursor, but the highlights **are never turned off**, i.e. if I repeat the command with the cursor over every single variable, then every variable will be highlighted at once (rather than only the variable under the cursor during the final run of the command).

I have reproduced this behavior with `ccls` and `pyls`, so I think it is a flaw with LCN and not the language servers themselves.

I can produce a gif of the behavior if desired.

## Environment
- neovim/vim version (`nvim --version` or `vim --version`):
```
NVIM v0.3.1
Build type: Release
LuaJIT 2.0.5
Compilation: /usr/bin/cc -march=x86-64 -mtune=generic -O2 -pipe -fstack-protector-strong -fno-plt -Wconversion -O2 -DNDEBUG -DMIN_LOG_LEVEL=3 -Wall -Wextra -pedantic -Wno-unused-parameter -Wstrict-prototypes -std=gnu99 -Wimplicit-fallthrough -Wvla -fstack-protector-strong -fdiagnostics-color=auto -Wno-array-bounds -DINCLUDE_GENERATED_DECLARATIONS -D_GNU_SOURCE -DNVIM_MSGPACK_HAS_FLOAT32 -DNVIM_UNIBI_HAS_VAR_FROM -I/build/neovim/src/build/config -I/build/neovim/src/neovim-0.3.1/src -I/usr/include -I/build/neovim/src/build/src/nvim/auto -I/build/neovim/src/build/include
Compiled by builduser

Features: +acl +iconv +jemalloc +tui
See ":help feature-compile"

   system vimrc file: "$VIM/sysinit.vim"
  fall-back for $VIM: "/usr/share/nvim"

Run :checkhealth for more info
```

- This plugin version (`git rev-parse --short HEAD`): `183fbf5`
- This plugin's binary version (`bin/languageclient --version`): `languageclient 0.1.120`
- Minimal vimrc content (A minimal vimrc is the smallest vimrc that could
  reproduce the issue. Refer to an example [here][min-vimrc.vim]): https://gist.github.com/wbthomason/2cf3f8dec63d183ce742bb1813f06523
- Language server link and version: [Pyls](https://github.com/palantir/python-language-server) version 0.21.2 and [ccls](https://github.com/MaskRay/ccls) commit `53496f1`.

[min-vimrc.vim]: https://github.com/autozimu/LanguageClient-neovim/blob/next/min-vimrc.vim

## To Reproduce
1. Download [minrc.vim](https://gist.github.com/wbthomason/2cf3f8dec63d183ce742bb1813f06523)
2. Run `nvim -u minrc.vim`
3. Open a new file `test.py` and type some variable definitions and uses
4. Place the cursor over the variables and run `:call LanguageClient#textDocument_documentHighlight()`. Observe that the highlights correctly update.
5. Open a new file `test2.py` and type some variable definitions and uses
6. Repeat step 4. Observe that the highlights persist forever.



## Current behavior
Highlights in the second buffer opened persist indefinitely.

## Expected behavior
Highlights should only persist until the next call to `documentHighlight()`

## Screenshots
![correct](https://user-images.githubusercontent.com/3729908/45832208-44017b00-bccf-11e8-8a4e-d0a4bb7ca181.png)
![incorrect](https://user-images.githubusercontent.com/3729908/45832207-44017b00-bccf-11e8-9638-3e60eea78faa.png)






Discussion / hints:
Same here :)
I think I see the cause of the issue: the document highlight buffer id is not updated if it already exists (as in there is already some active document highlight), which causes the plugin to try clearing the highlight in the wrong buffer.
@YaLTeR Do you know where in the code this is handled? I can poke through and make a PR when I have time, but I'm not familiar with the code, so it would take me a while to find the source of the problem.
I'll fix it today (I wrote the document highlight handling code).
Oh, thanks!

Fix patch:
diff --git a/src/languageclient.rs b/src/languageclient.rs
index 93667b781..d7a71b03f 100644
--- a/src/languageclient.rs
+++ b/src/languageclient.rs
@@ -343,20 +343,40 @@ impl State {
                     })
                 }).collect::<Result<Vec<_>>>()?;
 
-            let HighlightSource { buffer, source } =
-                if let Some(highlight_source) = self.document_highlight_source {
-                    highlight_source
+            let buffer = self.call(None, "nvim_win_get_buf", json!([0]))?;
+
+            let source = if let Some(hs) = self.document_highlight_source {
+                if hs.buffer == buffer {
+                    // If we want to highlight in the same buffer as last time, we can reuse
+                    // the previous source.
+                    Some(hs.source)
                 } else {
-                    let buffer = self.call(None, "nvim_win_get_buf", json!([0]))?;
+                    // Clear the highlight in the previous buffer.
+                    self.notify(
+                        None,
+                        "nvim_buf_clear_highlight",
+                        json!([hs.buffer, hs.source, 0, -1]),
+                    )?;
+
+                    None
+                }
+            } else {
+                None
+            };
+
+            let source = match source {
+                Some(source) => source,
+                None => {
+                    // Create a new source.
                     let source = self.call(
                         None,
                         "nvim_buf_add_highlight",
                         json!([buffer, 0, "Error", 1, 1, 1]),
                     )?;
-                    let highlight_source = HighlightSource { buffer, source };
-                    self.document_highlight_source = Some(highlight_source);
-                    highlight_source
-                };
+                    self.document_highlight_source = Some(HighlightSource { buffer, source });
+                    source
+                }
+            };
 
             self.notify(
                 None,


Test patch: