prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN 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!
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `plugin/core/completion.py`
  Content:
  ```
  1 from .protocol import CompletionItemKind, Range
  2 from .types import Settings
  3 from .logging import debug
  4 try:
  5     from typing import Tuple, Optional, Dict, List, Union
  6     assert Tuple and Optional and Dict and List and Union and Settings
  7 except ImportError:
  8     pass
  9 
  10 
  11 completion_item_kind_names = {v: k for k, v in CompletionItemKind.__dict__.items()}
  12 
  13 
  14 def get_completion_hint(item: dict, settings: 'Settings') -> 'Optional[str]':
  15     # choose hint based on availability and user preference
  16     hint = None
  17     if settings.completion_hint_type == "auto":
  18         hint = item.get("detail")
  19         if not hint:
  20             kind = item.get("kind")
  21             if kind:
  22                 hint = completion_item_kind_names[kind]
  23     elif settings.completion_hint_type == "detail":
  24         hint = item.get("detail")
  25     elif settings.completion_hint_type == "kind":
  26         kind = item.get("kind")
  27         if kind:
  28             hint = completion_item_kind_names.get(kind)
  29     return hint
  30 
  31 
  32 def format_completion(item: dict, word_col: int, settings: 'Settings') -> 'Tuple[str, str]':
  33     # Sublime handles snippets automatically, so we don't have to care about insertTextFormat.
  34     if settings.prefer_label_over_filter_text:
  35         trigger = item["label"]
  36     else:
  37         trigger = item.get("filterText") or item["label"]
  38 
  39     hint = get_completion_hint(item, settings)
  40 
  41     # label is an alternative for insertText if neither textEdit nor insertText is provided
  42     replacement = text_edit_text(item, word_col) or item.get("insertText") or trigger
  43 
  44     if replacement[0] != trigger[0]:
  45         # fix some common cases when server sends different start on label and replacement.
  46         if replacement[0] == '$':
  47             trigger = '$' + trigger  # add missing $
  48         elif replacement[0] == '-':
  49             trigger = '-' + trigger  # add missing -
  50         elif trigger[0] == ':':
  51             replacement = ':' + replacement  # add missing :
  52         elif trigger[0] == '$':
  53             trigger = trigger[1:]  # remove leading $
  54         elif trigger[0] == ' ' or trigger[0] == '•':
  55             trigger = trigger[1:]  # remove clangd insertion indicator
  56         else:
  57             debug("replacement prefix does not match trigger!")
  58             replacement = item.get("insertText") or trigger
  59 
  60     if len(replacement) > 0 and replacement[0] == '$':  # sublime needs leading '$' escaped.
  61         replacement = '\\$' + replacement[1:]
  62     # only return trigger with a hint if available
  63     return "\t  ".join((trigger, hint)) if hint else trigger, replacement
  64 
  65 
  66 def text_edit_text(item: dict, word_col: int) -> 'Optional[str]':
  67     text_edit = item.get('textEdit')
  68     if text_edit:
  69         edit_range, edit_text = text_edit.get("range"), text_edit.get("newText")
  70         if edit_range and edit_text:
  71             edit_range = Range.from_lsp(edit_range)
  72 
  73             # debug('textEdit from col {}, {} applied at col {}'.format(
  74             #     edit_range.start.col, edit_range.end.col, word_col))
  75 
  76             if edit_range.start.col <= word_col:
  77                 # if edit starts at current word, we can use it.
  78                 # if edit starts before current word, use the whole thing and we'll fix it up later.
  79                 return edit_text
  80 
  81     return None
  82 
  83 
  84 def parse_completion_response(response: 'Optional[Union[Dict,List]]') -> 'Tuple[List[Dict], bool]':
  85     items = []  # type: List[Dict]
  86     is_incomplete = False
  87     if isinstance(response, dict):
  88         items = response["items"] or []
  89         is_incomplete = response.get("isIncomplete", False)
  90     elif isinstance(response, list):
  91         items = response
  92     items = sorted(items, key=lambda item: item.get("sortText") or item["label"])
  93     return items, is_incomplete
  94
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: 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 @@
           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:]
  
verification_info: {"golden_diff": "diff --git a/plugin/core/completion.py b/plugin/core/completion.py\n--- a/plugin/core/completion.py\n+++ b/plugin/core/completion.py\n@@ -54,8 +54,7 @@\n         elif trigger[0] == ' ' or trigger[0] == '\u2022':\n             trigger = trigger[1:]  # remove clangd insertion indicator\n         else:\n-            debug(\"replacement prefix does not match trigger!\")\n-            replacement = item.get(\"insertText\") or trigger\n+            debug(\"WARNING: Replacement prefix does not match trigger '{}'\".format(trigger))\n \n     if len(replacement) > 0 and replacement[0] == '$':  # sublime needs leading '$' escaped.\n         replacement = '\\\\$' + replacement[1:]\n", "issue": "Completion inputs label instead of textEdit newText\nscalameta/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`.\r\n\r\nI'm on MacOS using the [Metals Language Server](https://github.com/scalameta/metals) with this SNAPSHOT `0.7.6+224-b3ea857f-SNAPSHOT`\r\n\r\nHere is a gif illustrating what I'm talking about\r\n\r\n![mygif](https://user-images.githubusercontent.com/13974112/68654280-db5a0b00-052d-11ea-8b86-5669621326cb.gif)\r\n\r\nAnd here is the snippet of lsp json that shows the completion item\r\n\r\n```\r\n[Trace - 08:54:53 AM] Received request 'completionItem/resolve - (30)'\r\nParams: {\r\n  \"label\": \"Implement all members\",\r\n  \"kind\": 12,\r\n  \"sortText\": \"00002\",\r\n  \"filterText\": \"e\",\r\n  \"insertTextFormat\": 2,\r\n  \"textEdit\": {\r\n    \"range\": {\r\n      \"start\": {\r\n        \"line\": 9,\r\n        \"character\": 3\r\n      },\r\n      \"end\": {\r\n        \"line\": 9,\r\n        \"character\": 4\r\n      }\r\n    },\r\n    \"newText\": \"def foo: Int \\u003d ${0:???}\\n   def boo: Int \\u003d ${0:???}\"\r\n  },\r\n  \"data\": {\r\n    \"target\": \"file:/Users/ckipp/Documents/scala-workspace/test-project/?id\\u003droot\",\r\n    \"symbol\": \"local6\"\r\n  }\r\n}\r\n\r\n\r\n[Trace - 08:54:53 AM] Sending response 'completionItem/resolve - (30)'. Processing request took 1ms\r\nResult: {\r\n  \"label\": \"Implement all members\",\r\n  \"kind\": 12,\r\n  \"sortText\": \"00002\",\r\n  \"filterText\": \"e\",\r\n  \"insertTextFormat\": 2,\r\n  \"textEdit\": {\r\n    \"range\": {\r\n      \"start\": {\r\n        \"line\": 9,\r\n        \"character\": 3\r\n      },\r\n      \"end\": {\r\n        \"line\": 9,\r\n        \"character\": 4\r\n      }\r\n    },\r\n    \"newText\": \"def foo: Int \\u003d ${0:???}\\n   def boo: Int \\u003d ${0:???}\"\r\n  },\r\n  \"data\": {\r\n    \"target\": \"file:/Users/ckipp/Documents/scala-workspace/test-project/?id\\u003droot\",\r\n    \"symbol\": \"local6\"\r\n  }\r\n}\r\n```\r\n\r\nIf I can provide any more details, just let me know!\n", "before_files": [{"content": "from .protocol import CompletionItemKind, Range\nfrom .types import Settings\nfrom .logging import debug\ntry:\n    from typing import Tuple, Optional, Dict, List, Union\n    assert Tuple and Optional and Dict and List and Union and Settings\nexcept ImportError:\n    pass\n\n\ncompletion_item_kind_names = {v: k for k, v in CompletionItemKind.__dict__.items()}\n\n\ndef get_completion_hint(item: dict, settings: 'Settings') -> 'Optional[str]':\n    # choose hint based on availability and user preference\n    hint = None\n    if settings.completion_hint_type == \"auto\":\n        hint = item.get(\"detail\")\n        if not hint:\n            kind = item.get(\"kind\")\n            if kind:\n                hint = completion_item_kind_names[kind]\n    elif settings.completion_hint_type == \"detail\":\n        hint = item.get(\"detail\")\n    elif settings.completion_hint_type == \"kind\":\n        kind = item.get(\"kind\")\n        if kind:\n            hint = completion_item_kind_names.get(kind)\n    return hint\n\n\ndef format_completion(item: dict, word_col: int, settings: 'Settings') -> 'Tuple[str, str]':\n    # Sublime handles snippets automatically, so we don't have to care about insertTextFormat.\n    if settings.prefer_label_over_filter_text:\n        trigger = item[\"label\"]\n    else:\n        trigger = item.get(\"filterText\") or item[\"label\"]\n\n    hint = get_completion_hint(item, settings)\n\n    # label is an alternative for insertText if neither textEdit nor insertText is provided\n    replacement = text_edit_text(item, word_col) or item.get(\"insertText\") or trigger\n\n    if replacement[0] != trigger[0]:\n        # fix some common cases when server sends different start on label and replacement.\n        if replacement[0] == '$':\n            trigger = '$' + trigger  # add missing $\n        elif replacement[0] == '-':\n            trigger = '-' + trigger  # add missing -\n        elif trigger[0] == ':':\n            replacement = ':' + replacement  # add missing :\n        elif trigger[0] == '$':\n            trigger = trigger[1:]  # remove leading $\n        elif trigger[0] == ' ' or trigger[0] == '\u2022':\n            trigger = trigger[1:]  # remove clangd insertion indicator\n        else:\n            debug(\"replacement prefix does not match trigger!\")\n            replacement = item.get(\"insertText\") or trigger\n\n    if len(replacement) > 0 and replacement[0] == '$':  # sublime needs leading '$' escaped.\n        replacement = '\\\\$' + replacement[1:]\n    # only return trigger with a hint if available\n    return \"\\t  \".join((trigger, hint)) if hint else trigger, replacement\n\n\ndef text_edit_text(item: dict, word_col: int) -> 'Optional[str]':\n    text_edit = item.get('textEdit')\n    if text_edit:\n        edit_range, edit_text = text_edit.get(\"range\"), text_edit.get(\"newText\")\n        if edit_range and edit_text:\n            edit_range = Range.from_lsp(edit_range)\n\n            # debug('textEdit from col {}, {} applied at col {}'.format(\n            #     edit_range.start.col, edit_range.end.col, word_col))\n\n            if edit_range.start.col <= word_col:\n                # if edit starts at current word, we can use it.\n                # if edit starts before current word, use the whole thing and we'll fix it up later.\n                return edit_text\n\n    return None\n\n\ndef parse_completion_response(response: 'Optional[Union[Dict,List]]') -> 'Tuple[List[Dict], bool]':\n    items = []  # type: List[Dict]\n    is_incomplete = False\n    if isinstance(response, dict):\n        items = response[\"items\"] or []\n        is_incomplete = response.get(\"isIncomplete\", False)\n    elif isinstance(response, list):\n        items = response\n    items = sorted(items, key=lambda item: item.get(\"sortText\") or item[\"label\"])\n    return items, is_incomplete\n", "path": "plugin/core/completion.py"}], "after_files": [{"content": "from .protocol import CompletionItemKind, Range\nfrom .types import Settings\nfrom .logging import debug\ntry:\n    from typing import Tuple, Optional, Dict, List, Union\n    assert Tuple and Optional and Dict and List and Union and Settings\nexcept ImportError:\n    pass\n\n\ncompletion_item_kind_names = {v: k for k, v in CompletionItemKind.__dict__.items()}\n\n\ndef get_completion_hint(item: dict, settings: 'Settings') -> 'Optional[str]':\n    # choose hint based on availability and user preference\n    hint = None\n    if settings.completion_hint_type == \"auto\":\n        hint = item.get(\"detail\")\n        if not hint:\n            kind = item.get(\"kind\")\n            if kind:\n                hint = completion_item_kind_names[kind]\n    elif settings.completion_hint_type == \"detail\":\n        hint = item.get(\"detail\")\n    elif settings.completion_hint_type == \"kind\":\n        kind = item.get(\"kind\")\n        if kind:\n            hint = completion_item_kind_names.get(kind)\n    return hint\n\n\ndef format_completion(item: dict, word_col: int, settings: 'Settings') -> 'Tuple[str, str]':\n    # Sublime handles snippets automatically, so we don't have to care about insertTextFormat.\n    if settings.prefer_label_over_filter_text:\n        trigger = item[\"label\"]\n    else:\n        trigger = item.get(\"filterText\") or item[\"label\"]\n\n    hint = get_completion_hint(item, settings)\n\n    # label is an alternative for insertText if neither textEdit nor insertText is provided\n    replacement = text_edit_text(item, word_col) or item.get(\"insertText\") or trigger\n\n    if replacement[0] != trigger[0]:\n        # fix some common cases when server sends different start on label and replacement.\n        if replacement[0] == '$':\n            trigger = '$' + trigger  # add missing $\n        elif replacement[0] == '-':\n            trigger = '-' + trigger  # add missing -\n        elif trigger[0] == ':':\n            replacement = ':' + replacement  # add missing :\n        elif trigger[0] == '$':\n            trigger = trigger[1:]  # remove leading $\n        elif trigger[0] == ' ' or trigger[0] == '\u2022':\n            trigger = trigger[1:]  # remove clangd insertion indicator\n        else:\n            debug(\"WARNING: Replacement prefix does not match trigger '{}'\".format(trigger))\n\n    if len(replacement) > 0 and replacement[0] == '$':  # sublime needs leading '$' escaped.\n        replacement = '\\\\$' + replacement[1:]\n    # only return trigger with a hint if available\n    return \"\\t  \".join((trigger, hint)) if hint else trigger, replacement\n\n\ndef text_edit_text(item: dict, word_col: int) -> 'Optional[str]':\n    text_edit = item.get('textEdit')\n    if text_edit:\n        edit_range, edit_text = text_edit.get(\"range\"), text_edit.get(\"newText\")\n        if edit_range and edit_text:\n            edit_range = Range.from_lsp(edit_range)\n\n            # debug('textEdit from col {}, {} applied at col {}'.format(\n            #     edit_range.start.col, edit_range.end.col, word_col))\n\n            if edit_range.start.col <= word_col:\n                # if edit starts at current word, we can use it.\n                # if edit starts before current word, use the whole thing and we'll fix it up later.\n                return edit_text\n\n    return None\n\n\ndef parse_completion_response(response: 'Optional[Union[Dict,List]]') -> 'Tuple[List[Dict], bool]':\n    items = []  # type: List[Dict]\n    is_incomplete = False\n    if isinstance(response, dict):\n        items = response[\"items\"] or []\n        is_incomplete = response.get(\"isIncomplete\", False)\n    elif isinstance(response, list):\n        items = response\n    items = sorted(items, key=lambda item: item.get(\"sortText\") or item[\"label\"])\n    return items, is_incomplete\n", "path": "plugin/core/completion.py"}]}