Several XHP autocomplete fixes
commitf022367bcea66d79af3d589039e5365b30dc7cd0
authorLucian Wischik <ljw@fb.com>
Fri, 9 Feb 2018 04:50:54 +0000 (8 20:50 -0800)
committerHhvm Bot <hhvm-bot@users.noreply.github.com>
Fri, 9 Feb 2018 05:07:40 +0000 (8 21:07 -0800)
tree433a203022ca9bdf3a618e5bf59195881efb9985
parent72528240c8c62284003d1f1731e56c1db95982a2
Several XHP autocomplete fixes

Summary:
This diff fixes several XHP autocomplete issues. Let's set the groundwork:

```
class :nt:text implements XHPChild {
  attribute int color;
}

$x1 = new :nt:text();
$x1->:color = 15;

$x2 = <nt:text color={15}/>
```

XHPChild is a magic built-in interface that tells Hack that folks can use the XHP construction syntax. I've constructed the same object in two equivalent ways. Observe that the true name of the class is `:nt:text` even though we must omit the leading colon in XHP construction syntax; and the true name of the property is ":color" though again we must omit the leading colon. (Actually, the syntax `$x1->:color` isn't an lvalue so the above doesn't work, but pretend like it does.)

The implication for autocomplete:

(1) If the user has typed a prefix e.g. "<nt" or "<nt:text col" and we're in an XHP context then we must add a leading colon before doing our internal filtering of which types/members satisfy that prefix.

(2) If the results of autocomplete started with colon and we're in an XHP context then we should strip off that leading colon before delivering them to the user.

That's what this diff does.

The question of "XHP context" is kind of thorny. It would be best addressed by FFP-autocomplete, but that's not enabled yet. In the meantime, we calculate it using a dumb regexp to detect "->..." and "<..." cases.

NOTE: this diff does not yet address the separate problem of language-identifier-regex... (1) If you write "new :" and accept the suggestion of ":class1" then it gets a double-colon "new ::class1". (2) If you write "$x->:" and accept the suggestion of ":attr1" then it gets a double-colon "$x->::attr1"

This is because it's the job of the editor to figure out what prefix has already been written, and then the LSP server says what to replace the prefix with. Both VSCode and Nuclide use regexps to determine the prefix, and they don't consider ":" to be part of a valid identifier (indeed it's not in e.g. Class1::staticMethod), and so they don't consider ":" as something that will be replaced by the suggestion ":class1" or ":attr1".

The solution for this problem lies elsewhere. Motivated by this precise example, the LSP powers that be have deprecated the "replace the editor-provided prefix with the insertText" model, and recommend that LSP servers instead use the "ignore the editor-provided prefix and instead perform an arbitrary textEdit" model.

I'll leave that for a future diff.

Differential Revision: D6922349

fbshipit-source-id: 8f961d35265627089f64c96f4f441233c86636e8
20 files changed:
hphp/hack/src/client/clientLsp.ml
hphp/hack/src/hh_single_type_check.ml
hphp/hack/src/server/autocompleteService.ml
hphp/hack/src/server/autocompleteService.mli
hphp/hack/src/server/autocompleteTypes.ml
hphp/hack/src/server/autocompleteTypes.mli
hphp/hack/src/server/serverAutoComplete.ml
hphp/hack/src/server/serverRpc.ml
hphp/hack/test/integration/data/lsp_exchanges/completion.expected [new file with mode: 0644]
hphp/hack/test/integration/data/lsp_exchanges/completion.json [new file with mode: 0644]
hphp/hack/test/integration/data/lsp_exchanges/completion.php [new file with mode: 0644]
hphp/hack/test/integration/data/lsp_exchanges/completion_extras.php [new file with mode: 0644]
hphp/hack/test/integration/data/lsp_exchanges/definition.expected
hphp/hack/test/integration/data/lsp_exchanges/didchange.expected
hphp/hack/test/integration/data/lsp_exchanges/formatting.expected
hphp/hack/test/integration/data/lsp_exchanges/highlight.expected
hphp/hack/test/integration/data/lsp_exchanges/hover.expected
hphp/hack/test/integration/data/lsp_exchanges/initialize_shutdown.expected
hphp/hack/test/integration/data/lsp_exchanges/nomethod.expected
hphp/hack/test/integration/test_lsp.py