We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[AC] AC not showing up with a "decorated" trigger
Note: check if only DYNAMIC_COMPLETIONS are affected.

When I supplement the completion by typing more characters, the completion widget goes away.

![Peek 2020-03-28 13-19](https://user-images.githubusercontent.com/2431823/77822869-db326480-70f6-11ea-82fa-207d26bdb433.gif)
<hr>
I don't get a completion widget at all sometimes. In the gif below I expect to at least see a completion for the "time" variable:

![Peek 2020-03-28 13-31](https://user-images.githubusercontent.com/2431823/77823050-76780980-70f8-11ea-806a-009f3d56e58a.gif)

I'm guessing this is due to incomplete completions. I'm not sure what the dynamic is here.

_Originally posted by @rwols in https://github.com/sublimelsp/LSP/pull/866#issuecomment-605441312_

--- 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/completion.py`
Content:
```
1 import sublime
2 import sublime_plugin
3 
4 from .core.configurations import is_supported_syntax
5 from .core.edit import parse_text_edit
6 from .core.logging import debug
7 from .core.protocol import Request, Range, InsertTextFormat
8 from .core.registry import session_for_view, client_from_session, LSPViewEventListener
9 from .core.sessions import Session
10 from .core.settings import settings, client_configs
11 from .core.typing import Any, List, Dict, Optional, Union
12 from .core.views import range_to_region
13 from .core.views import text_document_position_params
14 
15 
16 completion_kinds = {
17     1: (sublime.KIND_ID_MARKUP, "Ξ", "Text"),
18     2: (sublime.KIND_ID_FUNCTION, "λ", "Method"),
19     3: (sublime.KIND_ID_FUNCTION, "λ", "Function"),
20     4: (sublime.KIND_ID_FUNCTION, "c", "Constructor"),
21     5: (sublime.KIND_ID_VARIABLE, "f", "Field"),
22     6: (sublime.KIND_ID_VARIABLE, "v", "Variable"),
23     7: (sublime.KIND_ID_TYPE, "c", "Class"),
24     8: (sublime.KIND_ID_TYPE, "i", "Interface"),
25     9: (sublime.KIND_ID_NAMESPACE, "◪", "Module"),
26     10: (sublime.KIND_ID_VARIABLE, "ρ", "Property"),
27     11: (sublime.KIND_ID_VARIABLE, "u", "Unit"),
28     12: (sublime.KIND_ID_VARIABLE, "ν", "Value"),
29     13: (sublime.KIND_ID_TYPE, "ε", "Enum"),
30     14: (sublime.KIND_ID_KEYWORD, "κ", "Keyword"),
31     15: (sublime.KIND_ID_SNIPPET, "s", "Snippet"),
32     16: (sublime.KIND_ID_AMBIGUOUS, "c", "Color"),
33     17: (sublime.KIND_ID_AMBIGUOUS, "#", "File"),
34     18: (sublime.KIND_ID_AMBIGUOUS, "⇢", "Reference"),
35     19: (sublime.KIND_ID_AMBIGUOUS, "ƒ", "Folder"),
36     20: (sublime.KIND_ID_TYPE, "ε", "EnumMember"),
37     21: (sublime.KIND_ID_VARIABLE, "π", "Constant"),
38     22: (sublime.KIND_ID_TYPE, "s", "Struct"),
39     23: (sublime.KIND_ID_FUNCTION, "e", "Event"),
40     24: (sublime.KIND_ID_KEYWORD, "ο", "Operator"),
41     25: (sublime.KIND_ID_TYPE, "τ", "Type Parameter")
42 }
43 
44 
45 class RestoreLines:
46     def __init__(self) -> None:
47         self.saved_lines = []  # type: List[dict]
48 
49     def save_lines(self, locations: List[int], view: sublime.View) -> None:
50         change_id = view.change_id()
51 
52         for point in locations:
53             line = view.line(point)
54             change_region = (line.begin(), line.end())
55             text = view.substr(line)
56 
57             self.saved_lines.append({
58                 "change_id": change_id,
59                 "change_region": change_region,
60                 "text": text,
61                 # cursor will be use retore the cursor the te exact position
62                 "cursor": point
63             })
64 
65     def to_dict(self) -> Dict[str, Any]:
66         return {
67             "saved_lines": self.saved_lines
68         }
69 
70     @staticmethod
71     def from_dict(dictionary: Dict[str, Any]) -> 'RestoreLines':
72         restore_lines = RestoreLines()
73         restore_lines.saved_lines = dictionary["saved_lines"]
74         return restore_lines
75 
76     def restore_lines(self, edit: sublime.Edit, view: sublime.View) -> None:
77         # restore lines contents
78         # insert back lines from the bottom to top
79         for saved_line in reversed(self.saved_lines):
80             change_id = saved_line['change_id']
81             begin, end = saved_line['change_region']
82             change_region = sublime.Region(begin, end)
83 
84             transform_region = view.transform_region_from(change_region, change_id)
85             view.erase(edit, transform_region)
86             view.insert(edit, transform_region.begin(), saved_line['text'])
87 
88         # restore old cursor position
89         view.sel().clear()
90         for saved_line in self.saved_lines:
91             view.sel().add(saved_line["cursor"])
92 
93 
94 def format_completion(item: dict, restore_lines: RestoreLines) -> sublime.CompletionItem:
95     kind = sublime.KIND_AMBIGUOUS
96 
97     item_kind = item.get("kind")
98     if item_kind:
99         kind = completion_kinds.get(item_kind, sublime.KIND_AMBIGUOUS)
100 
101     is_deprecated = item.get("deprecated", False)
102     if is_deprecated:
103         list_kind = list(kind)
104         list_kind[1] = '⚠'
105         list_kind[2] = "⚠ {} - Deprecated".format(list_kind[2])
106         kind = tuple(list_kind)  # type: ignore
107 
108     return sublime.CompletionItem.command_completion(
109         trigger=item["label"],
110         command="lsp_select_completion_item",
111         args={
112             "item": item,
113             "restore_lines_dict": restore_lines.to_dict()
114         },
115         annotation=item.get('detail') or "",
116         kind=kind
117     )
118 
119 
120 class LspSelectCompletionItemCommand(sublime_plugin.TextCommand):
121     def run(self, edit: sublime.Edit, item: Any, restore_lines_dict: dict) -> None:
122         insert_text_format = item.get("insertTextFormat")
123 
124         text_edit = item.get('textEdit')
125         if text_edit:
126             # restore the lines
127             # so we don't have to calculate the offset for the textEdit range
128             restore_lines = RestoreLines.from_dict(restore_lines_dict)
129             restore_lines.restore_lines(edit, self.view)
130 
131             new_text = text_edit.get('newText')
132 
133             range = Range.from_lsp(text_edit['range'])
134             edit_region = range_to_region(range, self.view)
135 
136             # calculate offset by comparing cursor position with edit_region.begin.
137             # by applying the offset to all selections
138             # the TextEdit becomes valid for all selections
139             cursor = self.view.sel()[0].begin()  # type: int
140 
141             offset_start = cursor - edit_region.begin()
142             offset_length = edit_region.end() - edit_region.begin()
143 
144             # erease regions from bottom to top
145             for sel in reversed(self.view.sel()):
146                 begin = sel.begin() - offset_start
147                 end = begin + offset_length
148                 r = sublime.Region(begin, end)
149                 self.view.erase(edit, r)
150 
151             if insert_text_format == InsertTextFormat.Snippet:
152                 self.view.run_command("insert_snippet", {"contents": new_text})
153             else:
154                 # insert text from bottom to top
155                 for sel in reversed(self.view.sel()):
156                     self.view.insert(edit, sel.begin(), new_text)
157         else:
158             completion = item.get('insertText') or item.get('label') or ""
159             if insert_text_format == InsertTextFormat.Snippet:
160                 self.view.run_command("insert_snippet", {"contents": completion})
161             else:
162                 for sel in self.view.sel():
163                     self.view.insert(edit, sel.begin(), completion)
164 
165         # import statements, etc. some servers only return these after a resolve.
166         additional_edits = item.get('additionalTextEdits')
167         if additional_edits:
168             self.apply_additional_edits(additional_edits)
169         else:
170             self.do_resolve(item)
171 
172     def do_resolve(self, item: dict) -> None:
173         session = session_for_view(self.view, 'completionProvider', self.view.sel()[0].begin())
174         if not session:
175             return
176 
177         client = client_from_session(session)
178         if not client:
179             return
180 
181         completion_provider = session.get_capability('completionProvider')
182         has_resolve_provider = completion_provider and completion_provider.get('resolveProvider', False)
183         if has_resolve_provider:
184             client.send_request(Request.resolveCompletionItem(item), self.handle_resolve_response)
185 
186     def handle_resolve_response(self, response: Optional[dict]) -> None:
187         if response:
188             additional_edits = response.get('additionalTextEdits')
189             if additional_edits:
190                 self.apply_additional_edits(additional_edits)
191 
192     def apply_additional_edits(self, additional_edits: List[dict]) -> None:
193         edits = list(parse_text_edit(additional_edit) for additional_edit in additional_edits)
194         debug('applying additional edits:', edits)
195         self.view.run_command("lsp_apply_document_edit", {'changes': edits})
196         sublime.status_message('Applied additional edits for completion')
197 
198 
199 class CompletionHandler(LSPViewEventListener):
200     def __init__(self, view: sublime.View) -> None:
201         super().__init__(view)
202         self.initialized = False
203         self.enabled = False
204 
205     @classmethod
206     def is_applicable(cls, view_settings: dict) -> bool:
207         if 'completion' in settings.disabled_capabilities:
208             return False
209 
210         syntax = view_settings.get('syntax')
211         return is_supported_syntax(syntax, client_configs.all) if syntax else False
212 
213     def initialize(self) -> None:
214         self.initialized = True
215         session = session_for_view(self.view, 'completionProvider')
216         if session:
217             completionProvider = session.get_capability('completionProvider') or dict()  # type: dict
218             # A language server may have an empty dict as CompletionOptions. In that case,
219             # no trigger characters will be registered but we'll still respond to Sublime's
220             # usual query for completions. So the explicit check for None is necessary.
221             self.enabled = True
222 
223             trigger_chars = completionProvider.get(
224                 'triggerCharacters') or []
225             if trigger_chars:
226                 self.register_trigger_chars(session, trigger_chars)
227 
228     def _view_language(self, config_name: str) -> Optional[str]:
229         languages = self.view.settings().get('lsp_language')
230         return languages.get(config_name) if languages else None
231 
232     def register_trigger_chars(self, session: Session, trigger_chars: List[str]) -> None:
233         completion_triggers = self.view.settings().get('auto_complete_triggers', []) or []  # type: List[Dict[str, str]]
234         view_language = self._view_language(session.config.name)
235         if view_language:
236             for language in session.config.languages:
237                 if language.id == view_language:
238                     for scope in language.scopes:
239                         # debug("registering", trigger_chars, "for", scope)
240                         scope_trigger = next(
241                             (trigger for trigger in completion_triggers if trigger.get('selector', None) == scope),
242                             None
243                         )
244                         if not scope_trigger:  # do not override user's trigger settings.
245                             completion_triggers.append({
246                                 'characters': "".join(trigger_chars),
247                                 'selector': scope
248                             })
249 
250             self.view.settings().set('auto_complete_triggers', completion_triggers)
251 
252     def on_query_completions(self, prefix: str, locations: List[int]) -> Optional[sublime.CompletionList]:
253         if not self.initialized:
254             self.initialize()
255         if not self.enabled:
256             return None
257         client = client_from_session(session_for_view(self.view, 'completionProvider', locations[0]))
258         if not client:
259             return None
260         restore_lines = RestoreLines()
261         restore_lines.save_lines(locations, self.view)
262         self.manager.documents.purge_changes(self.view)
263         completion_list = sublime.CompletionList()
264         client.send_request(
265             Request.complete(text_document_position_params(self.view, locations[0])),
266             lambda res: self.handle_response(res, completion_list, restore_lines),
267             lambda res: self.handle_error(res, completion_list))
268         return completion_list
269 
270     def handle_response(self, response: Optional[Union[dict, List]],
271                         completion_list: sublime.CompletionList, restore_lines: RestoreLines) -> None:
272         response_items = []  # type: List[Dict]
273         incomplete = False
274         if isinstance(response, dict):
275             response_items = response["items"] or []
276             incomplete = response.get("isIncomplete", False)
277         elif isinstance(response, list):
278             response_items = response
279         response_items = sorted(response_items, key=lambda item: item.get("sortText") or item["label"])
280 
281         flags = 0
282         if settings.only_show_lsp_completions:
283             flags |= sublime.INHIBIT_WORD_COMPLETIONS
284             flags |= sublime.INHIBIT_EXPLICIT_COMPLETIONS
285 
286         if incomplete:
287             flags |= sublime.DYNAMIC_COMPLETIONS
288         completion_list.set_completions([format_completion(i, restore_lines) for i in response_items], flags)
289 
290     def handle_error(self, error: dict, completion_list: sublime.CompletionList) -> None:
291         completion_list.set_completions([])
292         sublime.status_message('Completion error: ' + str(error.get('message')))
293
```
--- 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()

```

diff --git a/plugin/completion.py b/plugin/completion.py
--- a/plugin/completion.py
+++ b/plugin/completion.py
@@ -224,6 +224,8 @@
                 'triggerCharacters') or []
             if trigger_chars:
                 self.register_trigger_chars(session, trigger_chars)
+            # This is to make ST match with labels that have a weird prefix like a space character.
+            self.view.settings().set("auto_complete_preserve_order", "none")
 
     def _view_language(self, config_name: str) -> Optional[str]:
         languages = self.view.settings().get('lsp_language')

{"golden_diff": "diff --git a/plugin/completion.py b/plugin/completion.py\n--- a/plugin/completion.py\n+++ b/plugin/completion.py\n@@ -224,6 +224,8 @@\n                 'triggerCharacters') or []\n             if trigger_chars:\n                 self.register_trigger_chars(session, trigger_chars)\n+            # This is to make ST match with labels that have a weird prefix like a space character.\n+            self.view.settings().set(\"auto_complete_preserve_order\", \"none\")\n \n     def _view_language(self, config_name: str) -> Optional[str]:\n         languages = self.view.settings().get('lsp_language')\n", "issue": "[AC] AC not showing up with a \"decorated\" trigger\nNote: check if only DYNAMIC_COMPLETIONS are affected.\r\n\r\nWhen I supplement the completion by typing more characters, the completion widget goes away.\r\n\r\n![Peek 2020-03-28 13-19](https://user-images.githubusercontent.com/2431823/77822869-db326480-70f6-11ea-82fa-207d26bdb433.gif)\r\n<hr>\r\nI don't get a completion widget at all sometimes. In the gif below I expect to at least see a completion for the \"time\" variable:\r\n\r\n![Peek 2020-03-28 13-31](https://user-images.githubusercontent.com/2431823/77823050-76780980-70f8-11ea-806a-009f3d56e58a.gif)\r\n\r\nI'm guessing this is due to incomplete completions. I'm not sure what the dynamic is here.\r\n\r\n_Originally posted by @rwols in https://github.com/sublimelsp/LSP/pull/866#issuecomment-605441312_\n", "before_files": [{"content": "import sublime\nimport sublime_plugin\n\nfrom .core.configurations import is_supported_syntax\nfrom .core.edit import parse_text_edit\nfrom .core.logging import debug\nfrom .core.protocol import Request, Range, InsertTextFormat\nfrom .core.registry import session_for_view, client_from_session, LSPViewEventListener\nfrom .core.sessions import Session\nfrom .core.settings import settings, client_configs\nfrom .core.typing import Any, List, Dict, Optional, Union\nfrom .core.views import range_to_region\nfrom .core.views import text_document_position_params\n\n\ncompletion_kinds = {\n    1: (sublime.KIND_ID_MARKUP, \"\u039e\", \"Text\"),\n    2: (sublime.KIND_ID_FUNCTION, \"\u03bb\", \"Method\"),\n    3: (sublime.KIND_ID_FUNCTION, \"\u03bb\", \"Function\"),\n    4: (sublime.KIND_ID_FUNCTION, \"c\", \"Constructor\"),\n    5: (sublime.KIND_ID_VARIABLE, \"f\", \"Field\"),\n    6: (sublime.KIND_ID_VARIABLE, \"v\", \"Variable\"),\n    7: (sublime.KIND_ID_TYPE, \"c\", \"Class\"),\n    8: (sublime.KIND_ID_TYPE, \"i\", \"Interface\"),\n    9: (sublime.KIND_ID_NAMESPACE, \"\u25ea\", \"Module\"),\n    10: (sublime.KIND_ID_VARIABLE, \"\u03c1\", \"Property\"),\n    11: (sublime.KIND_ID_VARIABLE, \"u\", \"Unit\"),\n    12: (sublime.KIND_ID_VARIABLE, \"\u03bd\", \"Value\"),\n    13: (sublime.KIND_ID_TYPE, \"\u03b5\", \"Enum\"),\n    14: (sublime.KIND_ID_KEYWORD, \"\u03ba\", \"Keyword\"),\n    15: (sublime.KIND_ID_SNIPPET, \"s\", \"Snippet\"),\n    16: (sublime.KIND_ID_AMBIGUOUS, \"c\", \"Color\"),\n    17: (sublime.KIND_ID_AMBIGUOUS, \"#\", \"File\"),\n    18: (sublime.KIND_ID_AMBIGUOUS, \"\u21e2\", \"Reference\"),\n    19: (sublime.KIND_ID_AMBIGUOUS, \"\u0192\", \"Folder\"),\n    20: (sublime.KIND_ID_TYPE, \"\u03b5\", \"EnumMember\"),\n    21: (sublime.KIND_ID_VARIABLE, \"\u03c0\", \"Constant\"),\n    22: (sublime.KIND_ID_TYPE, \"s\", \"Struct\"),\n    23: (sublime.KIND_ID_FUNCTION, \"e\", \"Event\"),\n    24: (sublime.KIND_ID_KEYWORD, \"\u03bf\", \"Operator\"),\n    25: (sublime.KIND_ID_TYPE, \"\u03c4\", \"Type Parameter\")\n}\n\n\nclass RestoreLines:\n    def __init__(self) -> None:\n        self.saved_lines = []  # type: List[dict]\n\n    def save_lines(self, locations: List[int], view: sublime.View) -> None:\n        change_id = view.change_id()\n\n        for point in locations:\n            line = view.line(point)\n            change_region = (line.begin(), line.end())\n            text = view.substr(line)\n\n            self.saved_lines.append({\n                \"change_id\": change_id,\n                \"change_region\": change_region,\n                \"text\": text,\n                # cursor will be use retore the cursor the te exact position\n                \"cursor\": point\n            })\n\n    def to_dict(self) -> Dict[str, Any]:\n        return {\n            \"saved_lines\": self.saved_lines\n        }\n\n    @staticmethod\n    def from_dict(dictionary: Dict[str, Any]) -> 'RestoreLines':\n        restore_lines = RestoreLines()\n        restore_lines.saved_lines = dictionary[\"saved_lines\"]\n        return restore_lines\n\n    def restore_lines(self, edit: sublime.Edit, view: sublime.View) -> None:\n        # restore lines contents\n        # insert back lines from the bottom to top\n        for saved_line in reversed(self.saved_lines):\n            change_id = saved_line['change_id']\n            begin, end = saved_line['change_region']\n            change_region = sublime.Region(begin, end)\n\n            transform_region = view.transform_region_from(change_region, change_id)\n            view.erase(edit, transform_region)\n            view.insert(edit, transform_region.begin(), saved_line['text'])\n\n        # restore old cursor position\n        view.sel().clear()\n        for saved_line in self.saved_lines:\n            view.sel().add(saved_line[\"cursor\"])\n\n\ndef format_completion(item: dict, restore_lines: RestoreLines) -> sublime.CompletionItem:\n    kind = sublime.KIND_AMBIGUOUS\n\n    item_kind = item.get(\"kind\")\n    if item_kind:\n        kind = completion_kinds.get(item_kind, sublime.KIND_AMBIGUOUS)\n\n    is_deprecated = item.get(\"deprecated\", False)\n    if is_deprecated:\n        list_kind = list(kind)\n        list_kind[1] = '\u26a0'\n        list_kind[2] = \"\u26a0 {} - Deprecated\".format(list_kind[2])\n        kind = tuple(list_kind)  # type: ignore\n\n    return sublime.CompletionItem.command_completion(\n        trigger=item[\"label\"],\n        command=\"lsp_select_completion_item\",\n        args={\n            \"item\": item,\n            \"restore_lines_dict\": restore_lines.to_dict()\n        },\n        annotation=item.get('detail') or \"\",\n        kind=kind\n    )\n\n\nclass LspSelectCompletionItemCommand(sublime_plugin.TextCommand):\n    def run(self, edit: sublime.Edit, item: Any, restore_lines_dict: dict) -> None:\n        insert_text_format = item.get(\"insertTextFormat\")\n\n        text_edit = item.get('textEdit')\n        if text_edit:\n            # restore the lines\n            # so we don't have to calculate the offset for the textEdit range\n            restore_lines = RestoreLines.from_dict(restore_lines_dict)\n            restore_lines.restore_lines(edit, self.view)\n\n            new_text = text_edit.get('newText')\n\n            range = Range.from_lsp(text_edit['range'])\n            edit_region = range_to_region(range, self.view)\n\n            # calculate offset by comparing cursor position with edit_region.begin.\n            # by applying the offset to all selections\n            # the TextEdit becomes valid for all selections\n            cursor = self.view.sel()[0].begin()  # type: int\n\n            offset_start = cursor - edit_region.begin()\n            offset_length = edit_region.end() - edit_region.begin()\n\n            # erease regions from bottom to top\n            for sel in reversed(self.view.sel()):\n                begin = sel.begin() - offset_start\n                end = begin + offset_length\n                r = sublime.Region(begin, end)\n                self.view.erase(edit, r)\n\n            if insert_text_format == InsertTextFormat.Snippet:\n                self.view.run_command(\"insert_snippet\", {\"contents\": new_text})\n            else:\n                # insert text from bottom to top\n                for sel in reversed(self.view.sel()):\n                    self.view.insert(edit, sel.begin(), new_text)\n        else:\n            completion = item.get('insertText') or item.get('label') or \"\"\n            if insert_text_format == InsertTextFormat.Snippet:\n                self.view.run_command(\"insert_snippet\", {\"contents\": completion})\n            else:\n                for sel in self.view.sel():\n                    self.view.insert(edit, sel.begin(), completion)\n\n        # import statements, etc. some servers only return these after a resolve.\n        additional_edits = item.get('additionalTextEdits')\n        if additional_edits:\n            self.apply_additional_edits(additional_edits)\n        else:\n            self.do_resolve(item)\n\n    def do_resolve(self, item: dict) -> None:\n        session = session_for_view(self.view, 'completionProvider', self.view.sel()[0].begin())\n        if not session:\n            return\n\n        client = client_from_session(session)\n        if not client:\n            return\n\n        completion_provider = session.get_capability('completionProvider')\n        has_resolve_provider = completion_provider and completion_provider.get('resolveProvider', False)\n        if has_resolve_provider:\n            client.send_request(Request.resolveCompletionItem(item), self.handle_resolve_response)\n\n    def handle_resolve_response(self, response: Optional[dict]) -> None:\n        if response:\n            additional_edits = response.get('additionalTextEdits')\n            if additional_edits:\n                self.apply_additional_edits(additional_edits)\n\n    def apply_additional_edits(self, additional_edits: List[dict]) -> None:\n        edits = list(parse_text_edit(additional_edit) for additional_edit in additional_edits)\n        debug('applying additional edits:', edits)\n        self.view.run_command(\"lsp_apply_document_edit\", {'changes': edits})\n        sublime.status_message('Applied additional edits for completion')\n\n\nclass CompletionHandler(LSPViewEventListener):\n    def __init__(self, view: sublime.View) -> None:\n        super().__init__(view)\n        self.initialized = False\n        self.enabled = False\n\n    @classmethod\n    def is_applicable(cls, view_settings: dict) -> bool:\n        if 'completion' in settings.disabled_capabilities:\n            return False\n\n        syntax = view_settings.get('syntax')\n        return is_supported_syntax(syntax, client_configs.all) if syntax else False\n\n    def initialize(self) -> None:\n        self.initialized = True\n        session = session_for_view(self.view, 'completionProvider')\n        if session:\n            completionProvider = session.get_capability('completionProvider') or dict()  # type: dict\n            # A language server may have an empty dict as CompletionOptions. In that case,\n            # no trigger characters will be registered but we'll still respond to Sublime's\n            # usual query for completions. So the explicit check for None is necessary.\n            self.enabled = True\n\n            trigger_chars = completionProvider.get(\n                'triggerCharacters') or []\n            if trigger_chars:\n                self.register_trigger_chars(session, trigger_chars)\n\n    def _view_language(self, config_name: str) -> Optional[str]:\n        languages = self.view.settings().get('lsp_language')\n        return languages.get(config_name) if languages else None\n\n    def register_trigger_chars(self, session: Session, trigger_chars: List[str]) -> None:\n        completion_triggers = self.view.settings().get('auto_complete_triggers', []) or []  # type: List[Dict[str, str]]\n        view_language = self._view_language(session.config.name)\n        if view_language:\n            for language in session.config.languages:\n                if language.id == view_language:\n                    for scope in language.scopes:\n                        # debug(\"registering\", trigger_chars, \"for\", scope)\n                        scope_trigger = next(\n                            (trigger for trigger in completion_triggers if trigger.get('selector', None) == scope),\n                            None\n                        )\n                        if not scope_trigger:  # do not override user's trigger settings.\n                            completion_triggers.append({\n                                'characters': \"\".join(trigger_chars),\n                                'selector': scope\n                            })\n\n            self.view.settings().set('auto_complete_triggers', completion_triggers)\n\n    def on_query_completions(self, prefix: str, locations: List[int]) -> Optional[sublime.CompletionList]:\n        if not self.initialized:\n            self.initialize()\n        if not self.enabled:\n            return None\n        client = client_from_session(session_for_view(self.view, 'completionProvider', locations[0]))\n        if not client:\n            return None\n        restore_lines = RestoreLines()\n        restore_lines.save_lines(locations, self.view)\n        self.manager.documents.purge_changes(self.view)\n        completion_list = sublime.CompletionList()\n        client.send_request(\n            Request.complete(text_document_position_params(self.view, locations[0])),\n            lambda res: self.handle_response(res, completion_list, restore_lines),\n            lambda res: self.handle_error(res, completion_list))\n        return completion_list\n\n    def handle_response(self, response: Optional[Union[dict, List]],\n                        completion_list: sublime.CompletionList, restore_lines: RestoreLines) -> None:\n        response_items = []  # type: List[Dict]\n        incomplete = False\n        if isinstance(response, dict):\n            response_items = response[\"items\"] or []\n            incomplete = response.get(\"isIncomplete\", False)\n        elif isinstance(response, list):\n            response_items = response\n        response_items = sorted(response_items, key=lambda item: item.get(\"sortText\") or item[\"label\"])\n\n        flags = 0\n        if settings.only_show_lsp_completions:\n            flags |= sublime.INHIBIT_WORD_COMPLETIONS\n            flags |= sublime.INHIBIT_EXPLICIT_COMPLETIONS\n\n        if incomplete:\n            flags |= sublime.DYNAMIC_COMPLETIONS\n        completion_list.set_completions([format_completion(i, restore_lines) for i in response_items], flags)\n\n    def handle_error(self, error: dict, completion_list: sublime.CompletionList) -> None:\n        completion_list.set_completions([])\n        sublime.status_message('Completion error: ' + str(error.get('message')))\n", "path": "plugin/completion.py"}], "after_files": [{"content": "import sublime\nimport sublime_plugin\n\nfrom .core.configurations import is_supported_syntax\nfrom .core.edit import parse_text_edit\nfrom .core.logging import debug\nfrom .core.protocol import Request, Range, InsertTextFormat\nfrom .core.registry import session_for_view, client_from_session, LSPViewEventListener\nfrom .core.sessions import Session\nfrom .core.settings import settings, client_configs\nfrom .core.typing import Any, List, Dict, Optional, Union\nfrom .core.views import range_to_region\nfrom .core.views import text_document_position_params\n\n\ncompletion_kinds = {\n    1: (sublime.KIND_ID_MARKUP, \"\u039e\", \"Text\"),\n    2: (sublime.KIND_ID_FUNCTION, \"\u03bb\", \"Method\"),\n    3: (sublime.KIND_ID_FUNCTION, \"\u03bb\", \"Function\"),\n    4: (sublime.KIND_ID_FUNCTION, \"c\", \"Constructor\"),\n    5: (sublime.KIND_ID_VARIABLE, \"f\", \"Field\"),\n    6: (sublime.KIND_ID_VARIABLE, \"v\", \"Variable\"),\n    7: (sublime.KIND_ID_TYPE, \"c\", \"Class\"),\n    8: (sublime.KIND_ID_TYPE, \"i\", \"Interface\"),\n    9: (sublime.KIND_ID_NAMESPACE, \"\u25ea\", \"Module\"),\n    10: (sublime.KIND_ID_VARIABLE, \"\u03c1\", \"Property\"),\n    11: (sublime.KIND_ID_VARIABLE, \"u\", \"Unit\"),\n    12: (sublime.KIND_ID_VARIABLE, \"\u03bd\", \"Value\"),\n    13: (sublime.KIND_ID_TYPE, \"\u03b5\", \"Enum\"),\n    14: (sublime.KIND_ID_KEYWORD, \"\u03ba\", \"Keyword\"),\n    15: (sublime.KIND_ID_SNIPPET, \"s\", \"Snippet\"),\n    16: (sublime.KIND_ID_AMBIGUOUS, \"c\", \"Color\"),\n    17: (sublime.KIND_ID_AMBIGUOUS, \"#\", \"File\"),\n    18: (sublime.KIND_ID_AMBIGUOUS, \"\u21e2\", \"Reference\"),\n    19: (sublime.KIND_ID_AMBIGUOUS, \"\u0192\", \"Folder\"),\n    20: (sublime.KIND_ID_TYPE, \"\u03b5\", \"EnumMember\"),\n    21: (sublime.KIND_ID_VARIABLE, \"\u03c0\", \"Constant\"),\n    22: (sublime.KIND_ID_TYPE, \"s\", \"Struct\"),\n    23: (sublime.KIND_ID_FUNCTION, \"e\", \"Event\"),\n    24: (sublime.KIND_ID_KEYWORD, \"\u03bf\", \"Operator\"),\n    25: (sublime.KIND_ID_TYPE, \"\u03c4\", \"Type Parameter\")\n}\n\n\nclass RestoreLines:\n    def __init__(self) -> None:\n        self.saved_lines = []  # type: List[dict]\n\n    def save_lines(self, locations: List[int], view: sublime.View) -> None:\n        change_id = view.change_id()\n\n        for point in locations:\n            line = view.line(point)\n            change_region = (line.begin(), line.end())\n            text = view.substr(line)\n\n            self.saved_lines.append({\n                \"change_id\": change_id,\n                \"change_region\": change_region,\n                \"text\": text,\n                # cursor will be use retore the cursor the te exact position\n                \"cursor\": point\n            })\n\n    def to_dict(self) -> Dict[str, Any]:\n        return {\n            \"saved_lines\": self.saved_lines\n        }\n\n    @staticmethod\n    def from_dict(dictionary: Dict[str, Any]) -> 'RestoreLines':\n        restore_lines = RestoreLines()\n        restore_lines.saved_lines = dictionary[\"saved_lines\"]\n        return restore_lines\n\n    def restore_lines(self, edit: sublime.Edit, view: sublime.View) -> None:\n        # restore lines contents\n        # insert back lines from the bottom to top\n        for saved_line in reversed(self.saved_lines):\n            change_id = saved_line['change_id']\n            begin, end = saved_line['change_region']\n            change_region = sublime.Region(begin, end)\n\n            transform_region = view.transform_region_from(change_region, change_id)\n            view.erase(edit, transform_region)\n            view.insert(edit, transform_region.begin(), saved_line['text'])\n\n        # restore old cursor position\n        view.sel().clear()\n        for saved_line in self.saved_lines:\n            view.sel().add(saved_line[\"cursor\"])\n\n\ndef format_completion(item: dict, restore_lines: RestoreLines) -> sublime.CompletionItem:\n    kind = sublime.KIND_AMBIGUOUS\n\n    item_kind = item.get(\"kind\")\n    if item_kind:\n        kind = completion_kinds.get(item_kind, sublime.KIND_AMBIGUOUS)\n\n    is_deprecated = item.get(\"deprecated\", False)\n    if is_deprecated:\n        list_kind = list(kind)\n        list_kind[1] = '\u26a0'\n        list_kind[2] = \"\u26a0 {} - Deprecated\".format(list_kind[2])\n        kind = tuple(list_kind)  # type: ignore\n\n    return sublime.CompletionItem.command_completion(\n        trigger=item[\"label\"],\n        command=\"lsp_select_completion_item\",\n        args={\n            \"item\": item,\n            \"restore_lines_dict\": restore_lines.to_dict()\n        },\n        annotation=item.get('detail') or \"\",\n        kind=kind\n    )\n\n\nclass LspSelectCompletionItemCommand(sublime_plugin.TextCommand):\n    def run(self, edit: sublime.Edit, item: Any, restore_lines_dict: dict) -> None:\n        insert_text_format = item.get(\"insertTextFormat\")\n\n        text_edit = item.get('textEdit')\n        if text_edit:\n            # restore the lines\n            # so we don't have to calculate the offset for the textEdit range\n            restore_lines = RestoreLines.from_dict(restore_lines_dict)\n            restore_lines.restore_lines(edit, self.view)\n\n            new_text = text_edit.get('newText')\n\n            range = Range.from_lsp(text_edit['range'])\n            edit_region = range_to_region(range, self.view)\n\n            # calculate offset by comparing cursor position with edit_region.begin.\n            # by applying the offset to all selections\n            # the TextEdit becomes valid for all selections\n            cursor = self.view.sel()[0].begin()  # type: int\n\n            offset_start = cursor - edit_region.begin()\n            offset_length = edit_region.end() - edit_region.begin()\n\n            # erease regions from bottom to top\n            for sel in reversed(self.view.sel()):\n                begin = sel.begin() - offset_start\n                end = begin + offset_length\n                r = sublime.Region(begin, end)\n                self.view.erase(edit, r)\n\n            if insert_text_format == InsertTextFormat.Snippet:\n                self.view.run_command(\"insert_snippet\", {\"contents\": new_text})\n            else:\n                # insert text from bottom to top\n                for sel in reversed(self.view.sel()):\n                    self.view.insert(edit, sel.begin(), new_text)\n        else:\n            completion = item.get('insertText') or item.get('label') or \"\"\n            if insert_text_format == InsertTextFormat.Snippet:\n                self.view.run_command(\"insert_snippet\", {\"contents\": completion})\n            else:\n                for sel in self.view.sel():\n                    self.view.insert(edit, sel.begin(), completion)\n\n        # import statements, etc. some servers only return these after a resolve.\n        additional_edits = item.get('additionalTextEdits')\n        if additional_edits:\n            self.apply_additional_edits(additional_edits)\n        else:\n            self.do_resolve(item)\n\n    def do_resolve(self, item: dict) -> None:\n        session = session_for_view(self.view, 'completionProvider', self.view.sel()[0].begin())\n        if not session:\n            return\n\n        client = client_from_session(session)\n        if not client:\n            return\n\n        completion_provider = session.get_capability('completionProvider')\n        has_resolve_provider = completion_provider and completion_provider.get('resolveProvider', False)\n        if has_resolve_provider:\n            client.send_request(Request.resolveCompletionItem(item), self.handle_resolve_response)\n\n    def handle_resolve_response(self, response: Optional[dict]) -> None:\n        if response:\n            additional_edits = response.get('additionalTextEdits')\n            if additional_edits:\n                self.apply_additional_edits(additional_edits)\n\n    def apply_additional_edits(self, additional_edits: List[dict]) -> None:\n        edits = list(parse_text_edit(additional_edit) for additional_edit in additional_edits)\n        debug('applying additional edits:', edits)\n        self.view.run_command(\"lsp_apply_document_edit\", {'changes': edits})\n        sublime.status_message('Applied additional edits for completion')\n\n\nclass CompletionHandler(LSPViewEventListener):\n    def __init__(self, view: sublime.View) -> None:\n        super().__init__(view)\n        self.initialized = False\n        self.enabled = False\n\n    @classmethod\n    def is_applicable(cls, view_settings: dict) -> bool:\n        if 'completion' in settings.disabled_capabilities:\n            return False\n\n        syntax = view_settings.get('syntax')\n        return is_supported_syntax(syntax, client_configs.all) if syntax else False\n\n    def initialize(self) -> None:\n        self.initialized = True\n        session = session_for_view(self.view, 'completionProvider')\n        if session:\n            completionProvider = session.get_capability('completionProvider') or dict()  # type: dict\n            # A language server may have an empty dict as CompletionOptions. In that case,\n            # no trigger characters will be registered but we'll still respond to Sublime's\n            # usual query for completions. So the explicit check for None is necessary.\n            self.enabled = True\n\n            trigger_chars = completionProvider.get(\n                'triggerCharacters') or []\n            if trigger_chars:\n                self.register_trigger_chars(session, trigger_chars)\n            # This is to make ST match with labels that have a weird prefix like a space character.\n            self.view.settings().set(\"auto_complete_preserve_order\", \"none\")\n\n    def _view_language(self, config_name: str) -> Optional[str]:\n        languages = self.view.settings().get('lsp_language')\n        return languages.get(config_name) if languages else None\n\n    def register_trigger_chars(self, session: Session, trigger_chars: List[str]) -> None:\n        completion_triggers = self.view.settings().get('auto_complete_triggers', []) or []  # type: List[Dict[str, str]]\n        view_language = self._view_language(session.config.name)\n        if view_language:\n            for language in session.config.languages:\n                if language.id == view_language:\n                    for scope in language.scopes:\n                        # debug(\"registering\", trigger_chars, \"for\", scope)\n                        scope_trigger = next(\n                            (trigger for trigger in completion_triggers if trigger.get('selector', None) == scope),\n                            None\n                        )\n                        if not scope_trigger:  # do not override user's trigger settings.\n                            completion_triggers.append({\n                                'characters': \"\".join(trigger_chars),\n                                'selector': scope\n                            })\n\n            self.view.settings().set('auto_complete_triggers', completion_triggers)\n\n    def on_query_completions(self, prefix: str, locations: List[int]) -> Optional[sublime.CompletionList]:\n        if not self.initialized:\n            self.initialize()\n        if not self.enabled:\n            return None\n        client = client_from_session(session_for_view(self.view, 'completionProvider', locations[0]))\n        if not client:\n            return None\n        restore_lines = RestoreLines()\n        restore_lines.save_lines(locations, self.view)\n        self.manager.documents.purge_changes(self.view)\n        completion_list = sublime.CompletionList()\n        client.send_request(\n            Request.complete(text_document_position_params(self.view, locations[0])),\n            lambda res: self.handle_response(res, completion_list, restore_lines),\n            lambda res: self.handle_error(res, completion_list))\n        return completion_list\n\n    def handle_response(self, response: Optional[Union[dict, List]],\n                        completion_list: sublime.CompletionList, restore_lines: RestoreLines) -> None:\n        response_items = []  # type: List[Dict]\n        incomplete = False\n        if isinstance(response, dict):\n            response_items = response[\"items\"] or []\n            incomplete = response.get(\"isIncomplete\", False)\n        elif isinstance(response, list):\n            response_items = response\n        response_items = sorted(response_items, key=lambda item: item.get(\"sortText\") or item[\"label\"])\n\n        flags = 0\n        if settings.only_show_lsp_completions:\n            flags |= sublime.INHIBIT_WORD_COMPLETIONS\n            flags |= sublime.INHIBIT_EXPLICIT_COMPLETIONS\n\n        if incomplete:\n            flags |= sublime.DYNAMIC_COMPLETIONS\n        completion_list.set_completions([format_completion(i, restore_lines) for i in response_items], flags)\n\n    def handle_error(self, error: dict, completion_list: sublime.CompletionList) -> None:\n        completion_list.set_completions([])\n        sublime.status_message('Completion error: ' + str(error.get('message')))\n", "path": "plugin/completion.py"}]}