Repository: sublimelsp/LSP

Issue:
Intelephense v1.0 released with a few issues
I'm happy to announce Intelephense v1.0 is released. More info can be found [here](https://github.com/bmewburn/intelephense-docs)

I'm not entirely sure if this is an LSP issue or a server issue.

When autocompleting method names I have to manually type the parenthesis and tooltip information seems messed up.

![tooltip](https://i.imgur.com/ITBEn6a.png)


* OSX 10.14 - Intelephense 1.0
* Package Control


Discussion:
For people who want to try this new v1.0 PHP Intelephense LSP, I have it run with the following config.

I mean, just only running. There are still some other problems you may encounter like the OP here.
Note that `Clover` is my username on my PC.

```javascript
"intelephense": {
    // https://github.com/bmewburn/intelephense-docs
    // npm -g i intelephense
    // yarn global add intelephense
    "enabled": true,
    "command": [
        "node",
        // "C:/Users/Clover/AppData/Roaming/npm/node_modules/intelephense/lib/intelephense.js",
        "C:/Users/Clover/AppData/Local/Yarn/Data/global/node_modules/intelephense/lib/intelephense.js",
        "--stdio",
    ],
    "scopes": ["source.php", "embedding.php"],
    "syntaxes": ["Packages/PHP/PHP.sublime-syntax"],
    "languageId": "php",
    "initializationOptions": {
        "storagePath": "C:/Users/Clover/AppData/Local/Temp/intelephense-ls",
    },
},
```
v1.0.2 is the latest version of Intelephense, you can upgrade to the latest version by running this command.

```npm upgrade -g intelephense```
After upgrading to v1.0.2, I still having the following problem when I try to get method argument hinting.

![image](https://user-images.githubusercontent.com/6594915/53225216-4454d680-36b2-11e9-8bc8-629783c5502d.png)
When I type the `(`, ST auto adds `)` and my cursor is in the mid of `()`, it tries to provide the method signature but then a python exception is thrown.

<details><summary>Click to show console error log</summary>

```
LSP:  --> textDocument/signatureHelp
LSP:      {'activeSignature': 0, 'signatures': [{'parameters': [{'documentation': {'kind': 'markdown', 'value': '_@param_ `int $op`  \nthe operation code'}, 'label': 'int $op'}], 'label': '(int $op)'}], 'activeParameter': 0}
Error handling server payload
Traceback (most recent call last):
  File "C:\Users\Clover\AppData\Roaming\Sublime Text 3\Installed Packages\LSP.sublime-package\plugin/core/rpc.py", line 141, in receive_payload
    self.response_handler(payload)
  File "C:\Users\Clover\AppData\Roaming\Sublime Text 3\Installed Packages\LSP.sublime-package\plugin/core/rpc.py", line 160, in response_handler
    handler(response["result"])
  File "C:\Users\Clover\AppData\Roaming\Sublime Text 3\Installed Packages\LSP.sublime-package\plugin/signature_help.py", line 81, in <lambda>
    lambda response: self.handle_response(response, point))
  File "C:\Users\Clover\AppData\Roaming\Sublime Text 3\Installed Packages\LSP.sublime-package\plugin/signature_help.py", line 103, in handle_response
    self._show_popup(point)
  File "C:\Users\Clover\AppData\Roaming\Sublime Text 3\Installed Packages\LSP.sublime-package\plugin/signature_help.py", line 132, in _show_popup
    self._build_popup_content(),
  File "C:\Users\Clover\AppData\Roaming\Sublime Text 3\Installed Packages\LSP.sublime-package\plugin/signature_help.py", line 152, in _build_popup_content
    return self._build_popup_content_style_vscode()
  File "C:\Users\Clover\AppData\Roaming\Sublime Text 3\Installed Packages\LSP.sublime-package\plugin/signature_help.py", line 233, in _build_popup_content_style_vscode
    return "\n".join(formatted)
TypeError: sequence item 3: expected str instance, dict found
```

</details>
Maybe it's the value of the `documentation` key that's throwing things off? I seem to remember that we assume that `documentation` is always a `str`, but I may be wrong.
@rwols You're correct it seems to be returning a ```dict```instead of a ```str```

Is this something that should be changed in LSP or Intelephense?

@jfcherng What happens if you change the method so it isn't static? do you get signature help then?
> @jfcherng What happens if you change the method so it isn't static? do you get signature help then?

@carlevison Unfortunately nope. Things like `$this->xxx()` would trigger the same exception as well.
```
TypeError: sequence item 3: expected str instance, dict found
```


Resolving patch:
diff --git a/plugin/signature_help.py b/plugin/signature_help.py
--- a/plugin/signature_help.py
+++ b/plugin/signature_help.py
@@ -21,6 +21,22 @@
 from .core.settings import settings
 
 
+def get_documentation(d: 'Dict[str, Any]') -> 'Optional[str]':
+    docs = d.get('documentation', None)
+    if docs is None:
+        return None
+    elif isinstance(docs, str):
+        # In older version of the protocol, documentation was just a string.
+        return docs
+    elif isinstance(docs, dict):
+        # This can be either "plaintext" or "markdown" format. For now, we can dump it into the popup box. It would
+        # be nice to handle the markdown in a special way.
+        return docs.get('value', None)
+    else:
+        debug('unknown documentation type:', str(d))
+        return None
+
+
 class SignatureHelpListener(sublime_plugin.ViewEventListener):
 
     def __init__(self, view):
@@ -185,10 +201,10 @@ def _build_popup_content_style_sublime(self) -> str:
         params = signature.get('parameters')
         if params:
             for parameter in params:
-                paramDocs = parameter.get('documentation', None)
-                if paramDocs:
+                param_docs = get_documentation(parameter)
+                if param_docs:
                     formatted.append("**{}**\n".format(parameter.get('label')))
-                    formatted.append("* *{}*\n".format(paramDocs))
+                    formatted.append("* *{}*\n".format(param_docs))
         sigDocs = signature.get('documentation', None)
         if sigDocs:
             formatted.append(sigDocs)
@@ -197,18 +213,18 @@ def _build_popup_content_style_sublime(self) -> str:
     def _build_popup_content_style_vscode(self) -> str:
         # Fetch all the relevant data.
         signature_label = ""
-        signature_documentation = ""
+        signature_documentation = ""  # type: Optional[str]
         parameter_label = ""
-        parameter_documentation = ""
+        parameter_documentation = ""  # type: Optional[str]
         if self._active_signature in range(0, len(self._signatures)):
             signature = self._signatures[self._active_signature]
             signature_label = html.escape(signature["label"], quote=False)
-            signature_documentation = signature.get("documentation", "")  # Optional.
+            signature_documentation = get_documentation(signature)
             parameters = signature.get("parameters", None)
             if parameters and self._active_parameter in range(0, len(parameters)):
                 parameter = parameters[self._active_parameter]
                 parameter_label = html.escape(parameter["label"], quote=False)
-                parameter_documentation = parameter.get("documentation", "")  # Optional.
+                parameter_documentation = get_documentation(parameter)
 
         formatted = []
 


Test patch: