Repository: sublimelsp/LSP

Issue:
Completion inputs label instead of textEdit newText
scalameta/metals#1031 was recently merged which adds an "implement all members" completion option. However, in Sublime it seems to not show up in the same order in the completions as the other editors. It seems to be triggered by e for some reason. Apart from that, if you do decide to use that completion, the completion seems to instead of implementing the `newText` it implements the `label`.

I'm on MacOS using the [Metals Language Server](https://github.com/scalameta/metals) with this SNAPSHOT `0.7.6+224-b3ea857f-SNAPSHOT`

Here is a gif illustrating what I'm talking about

![mygif](https://user-images.githubusercontent.com/13974112/68654280-db5a0b00-052d-11ea-8b86-5669621326cb.gif)

And here is the snippet of lsp json that shows the completion item

```
[Trace - 08:54:53 AM] Received request 'completionItem/resolve - (30)'
Params: {
  "label": "Implement all members",
  "kind": 12,
  "sortText": "00002",
  "filterText": "e",
  "insertTextFormat": 2,
  "textEdit": {
    "range": {
      "start": {
        "line": 9,
        "character": 3
      },
      "end": {
        "line": 9,
        "character": 4
      }
    },
    "newText": "def foo: Int \u003d ${0:???}\n   def boo: Int \u003d ${0:???}"
  },
  "data": {
    "target": "file:/Users/ckipp/Documents/scala-workspace/test-project/?id\u003droot",
    "symbol": "local6"
  }
}


[Trace - 08:54:53 AM] Sending response 'completionItem/resolve - (30)'. Processing request took 1ms
Result: {
  "label": "Implement all members",
  "kind": 12,
  "sortText": "00002",
  "filterText": "e",
  "insertTextFormat": 2,
  "textEdit": {
    "range": {
      "start": {
        "line": 9,
        "character": 3
      },
      "end": {
        "line": 9,
        "character": 4
      }
    },
    "newText": "def foo: Int \u003d ${0:???}\n   def boo: Int \u003d ${0:???}"
  },
  "data": {
    "target": "file:/Users/ckipp/Documents/scala-workspace/test-project/?id\u003droot",
    "symbol": "local6"
  }
}
```

If I can provide any more details, just let me know!


Discussion:

Resolving patch:
diff --git a/plugin/core/completion.py b/plugin/core/completion.py
--- a/plugin/core/completion.py
+++ b/plugin/core/completion.py
@@ -54,8 +54,7 @@ def format_completion(item: dict, word_col: int, settings: 'Settings') -> 'Tuple
         elif trigger[0] == ' ' or trigger[0] == '•':
             trigger = trigger[1:]  # remove clangd insertion indicator
         else:
-            debug("replacement prefix does not match trigger!")
-            replacement = item.get("insertText") or trigger
+            debug("WARNING: Replacement prefix does not match trigger '{}'".format(trigger))
 
     if len(replacement) > 0 and replacement[0] == '$':  # sublime needs leading '$' escaped.
         replacement = '\\$' + replacement[1:]


Test patch:
diff --git a/tests/test_completion.py b/tests/test_completion.py
--- a/tests/test_completion.py
+++ b/tests/test_completion.py
@@ -105,6 +105,23 @@
          })
 ]
 
+metals_implement_all_members = [
+    dict(label='Implement all members',
+         textEdit={
+             'newText': 'def foo: Int \u003d ${0:???}\n   def boo: Int \u003d ${0:???}',
+             'range': {
+                 'start': {
+                     'line': 0,
+                     'character': 0
+                 },
+                 'end': {
+                     'line': 0,
+                     'character': 1
+                 }
+             }
+         })
+]
+
 
 class InitializationTests(DeferrableTestCase):
     def setUp(self):
@@ -324,6 +341,27 @@ def test_edit_after_nonword(self):
                 self.view.substr(sublime.Region(0, self.view.size())),
                 'List.apply()')
 
+    def test_implement_all_members_quirk(self):
+        """
+        Metals: "Implement all members" should just select the newText.
+        https://github.com/tomv564/LSP/issues/771
+        """
+        yield OPEN_DOCUMENT_DELAY
+        self.view.run_command('append', {'characters': 'I'})
+        self.view.run_command('move_to', {'to': 'eol'})
+        self.client.responses['textDocument/completion'] = metals_implement_all_members
+        handler = self.get_view_event_listener('on_query_completions')
+        self.assertIsNotNone(handler)
+        if handler:
+            handler.on_query_completions("", [1])
+            yield 100
+            handler.on_text_command('insert_best_completion', {})
+            self.view.run_command('insert_best_completion', {})
+            yield AFTER_INSERT_COMPLETION_DELAY
+            self.assertEquals(
+                self.view.substr(sublime.Region(0, self.view.size())),
+                'def foo: Int = ???\n   def boo: Int = ???')
+
     def test_additional_edits(self):
         yield OPEN_DOCUMENT_DELAY
         self.client.responses[