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

Issue:
ShowErrorMessage is spamming LanguageClient-neovim with message requests
I've been experiencing a very odd behavior of ocaml-language-server + LanguageClient-neovim. 

Messages such as the following appear when merlin has any sort of issue:

![ocaml-langserver-bug](https://user-images.githubusercontent.com/21299126/62419786-9f193380-b63d-11e9-9775-57e2a94e6b4b.png)

I have to dismiss 20+ of these messages by pressing enter repeatedly when this happens. 

I've determined that this stems from ocaml-language-server calls vscode-langserver-node's `showErrorMessage` method defined here:

https://github.com/freebroccolo/ocaml-language-server/blob/6310438abaaad6b79175e3443e82437d2b91f1cd/src/bin/server/processes/merlin.ts#L41-L43

 vscode-langserver-node then sends a LSP `ShowMessageRequest` message:

https://github.com/microsoft/vscode-languageserver-node/blob/58551741af1d90dd96d9c8a5b0069619884d8f22/server/src/main.ts#L837-L840

languageclient-neovim then handles this message:

https://github.com/autozimu/LanguageClient-neovim/blob/5491a64a07b259568e26981e5ec0d78ba8cec756/src/language_server_protocol.rs#L1862-L1883

... which finally calls from the Rust LSP client into the vimscript runtime code:

https://github.com/autozimu/LanguageClient-neovim/blob/0f171f5cef4f611bce3efc217fd83b021adbb3aa/autoload/LanguageClient.vim#L187-L192

 which triggers the vim built-in function `inputlist`, as documented:

```
inputlist({textlist})					*inputlist()*
		{textlist} must be a |List| of strings.  This |List| is
		displayed, one string per line.  The user will be prompted to
		enter a number, which is returned.
		The user can also select an item by clicking on it with the
		mouse.	For the first string 0 is returned.  When clicking
		above the first item a negative number is returned.  When
		clicking on the prompt one more than the length of {textlist}
		is returned.
		Make sure {textlist} has less than 'lines' entries, otherwise
		it won't work.	It's a good idea to put the entry number at
		the start of the string.  And put a prompt in the first item.
		Example: >
			let color = inputlist(['Select color:', '1. red',
				\ '2. green', '3. blue'])
```

`inputlist` basically displays the message (in this case an error message, not really a user input request message as it expects) as shown in the screenshot, which the user must then dismiss manually.

I am not sure as to which project is the culprit here, and thus where to file an issue, so I am opening this on all three projects.

- **ocaml-language-server**: should a merlin error really trigger a LSP error?
- **vscode-langserver-node**: should the `showErrorMessage` method  really send a `ShowMessageRequest`, or should it send a `ShowMessage`?  Is this a proper implementation of LSP?
- **LanguageClient-neovim**: should a ShowMessageRequest really require user input? Is this a proper implementation of LSP? Can a config option be added to disable the `inputlist` functionality?


Discussion / hints:
Other issues:
https://github.com/microsoft/vscode-languageserver-node/issues/507
https://github.com/freebroccolo/ocaml-language-server/issues/135

Fix patch:
diff --git a/src/language_server_protocol.rs b/src/language_server_protocol.rs
index cdcbe5da5..a7a5c44f8 100644
--- a/src/language_server_protocol.rs
+++ b/src/language_server_protocol.rs
@@ -1861,21 +1861,26 @@ impl LanguageClient {
 
     pub fn window_showMessageRequest(&self, params: &Value) -> Fallible<Value> {
         info!("Begin {}", lsp::request::ShowMessageRequest::METHOD);
+        let mut v = Value::Null;
         let msg_params: ShowMessageRequestParams = params.clone().to_lsp()?;
+        let msg = format!("[{:?}] {}", msg_params.typ, msg_params.message);
         let msg_actions = msg_params.actions.unwrap_or_default();
-        let mut options = Vec::with_capacity(msg_actions.len() + 1);
-        options.push(msg_params.message);
-        options.extend(
-            msg_actions
-                .iter()
-                .enumerate()
-                .map(|(i, item)| format!("{}) {}", i + 1, item.title)),
-        );
+        if msg_actions.is_empty() {
+            self.vim()?.echomsg(&msg)?;
+        } else {
+            let mut options = Vec::with_capacity(msg_actions.len() + 1);
+            options.push(msg);
+            options.extend(
+                msg_actions
+                    .iter()
+                    .enumerate()
+                    .map(|(i, item)| format!("{}) {}", i + 1, item.title)),
+            );
 
-        let mut v = Value::Null;
-        let index: Option<usize> = self.vim()?.rpcclient.call("s:inputlist", options)?;
-        if let Some(index) = index {
-            v = serde_json::to_value(msg_actions.get(index - 1))?;
+            let index: Option<usize> = self.vim()?.rpcclient.call("s:inputlist", options)?;
+            if let Some(index) = index {
+                v = serde_json::to_value(msg_actions.get(index - 1))?;
+            }
         }
 
         info!("End {}", lsp::request::ShowMessageRequest::METHOD);


Test patch: