diff --git a/boot.py b/boot.py
index 0a23d5e5f..cd9fe15c5 100644
--- a/boot.py
+++ b/boot.py
@@ -10,7 +10,7 @@
from .plugin.color import LspColorPresentationCommand
from .plugin.completion import LspCommitCompletionWithOppositeInsertMode
from .plugin.completion import LspResolveDocsCommand
-from .plugin.completion import LspSelectCompletionItemCommand
+from .plugin.completion import LspSelectCompletionCommand
from .plugin.configuration import LspDisableLanguageServerGloballyCommand
from .plugin.configuration import LspDisableLanguageServerInProjectCommand
from .plugin.configuration import LspEnableLanguageServerGloballyCommand
diff --git a/plugin/completion.py b/plugin/completion.py
index 68d43468d..4c915b9a7 100644
--- a/plugin/completion.py
+++ b/plugin/completion.py
@@ -90,7 +90,7 @@ def _on_completion_response_async(
def _resolve_completions_async(self, responses: List[ResolvedCompletions]) -> None:
if self._resolved:
return
- LspResolveDocsCommand.completions = {}
+ LspSelectCompletionCommand.completions = {}
items = [] # type: List[sublime.CompletionItem]
errors = [] # type: List[Error]
flags = 0 # int
@@ -117,7 +117,7 @@ def _resolve_completions_async(self, responses: List[ResolvedCompletions]) -> No
elif isinstance(response, list):
response_items = response
response_items = sorted(response_items, key=lambda item: item.get("sortText") or item["label"])
- LspResolveDocsCommand.completions[session.config.name] = response_items
+ LspSelectCompletionCommand.completions[session.config.name] = response_items
can_resolve_completion_items = session.has_capability('completionProvider.resolveProvider')
config_name = session.config.name
items.extend(
@@ -150,12 +150,10 @@ def _resolve_task_async(self, completions: List[sublime.CompletionItem], flags:
class LspResolveDocsCommand(LspTextCommand):
- completions = {} # type: Dict[SessionName, List[CompletionItem]]
-
def run(self, edit: sublime.Edit, index: int, session_name: str, event: Optional[dict] = None) -> None:
def run_async() -> None:
- item = self.completions[session_name][index]
+ item = LspSelectCompletionCommand.completions[session_name][index]
session = self.session_by_name(session_name, 'completionProvider.resolveProvider')
if session:
request = Request.resolveCompletionItem(item, self.view)
@@ -218,8 +216,12 @@ def run(self, edit: sublime.Edit, event: Optional[dict] = None) -> None:
LspCommitCompletionWithOppositeInsertMode.active = False
-class LspSelectCompletionItemCommand(LspTextCommand):
- def run(self, edit: sublime.Edit, item: CompletionItem, session_name: str) -> None:
+class LspSelectCompletionCommand(LspTextCommand):
+
+ completions = {} # type: Dict[SessionName, List[CompletionItem]]
+
+ def run(self, edit: sublime.Edit, index: int, session_name: str) -> None:
+ item = LspSelectCompletionCommand.completions[session_name][index]
text_edit = item.get("textEdit")
if text_edit:
new_text = text_edit["newText"].replace("\r", "")
diff --git a/plugin/core/views.py b/plugin/core/views.py
index a98f23dad..385cccb35 100644
--- a/plugin/core/views.py
+++ b/plugin/core/views.py
@@ -1030,22 +1030,21 @@ def format_completion(
item: CompletionItem, index: int, can_resolve_completion_items: bool, session_name: str, view_id: int
) -> sublime.CompletionItem:
# This is a hot function. Don't do heavy computations or IO in this function.
-
lsp_label = item['label']
lsp_label_details = item.get('labelDetails') or {}
lsp_label_detail = lsp_label_details.get('detail') or ""
lsp_label_description = lsp_label_details.get('description') or ""
lsp_filter_text = item.get('filterText') or ""
lsp_detail = (item.get('detail') or "").replace("\n", " ")
-
completion_kind = item.get('kind')
kind = COMPLETION_KINDS.get(completion_kind, sublime.KIND_AMBIGUOUS) if completion_kind else sublime.KIND_AMBIGUOUS
-
details = [] # type: List[str]
if can_resolve_completion_items or item.get('documentation'):
- details.append(make_command_link(
- 'lsp_resolve_docs', "More", {'index': index, 'session_name': session_name}, view_id=view_id))
-
+ # Not using "make_command_link" in a hot path to avoid slow json.dumps.
+ args = '{{"view_id":{},"command":"lsp_resolve_docs","args":{{"index":{},"session_name":"{}"}}}}'.format(
+ view_id, index, session_name)
+ href = 'subl:lsp_run_text_command_helper {}'.format(args)
+ details.append(make_link(href, 'More'))
if lsp_label_detail and (lsp_label + lsp_label_detail).startswith(lsp_filter_text):
trigger = lsp_label + lsp_label_detail
annotation = lsp_label_description or lsp_detail
@@ -1062,22 +1061,24 @@ def format_completion(
details.append(html.escape(lsp_label + lsp_label_detail))
if lsp_label_description:
details.append(html.escape(lsp_label_description))
-
if item.get('deprecated') or CompletionItemTag.Deprecated in item.get('tags', []):
annotation = "DEPRECATED - " + annotation if annotation else "DEPRECATED"
-
- insert_replace_support_html = get_insert_replace_support_html(item)
- if insert_replace_support_html:
- details.append(insert_replace_support_html)
-
- completion = sublime.CompletionItem.command_completion(
- trigger=trigger,
- command='lsp_select_completion_item',
- args={"item": item, "session_name": session_name},
- annotation=annotation,
- kind=kind,
- details=" | ".join(details))
- if item.get('textEdit'):
+ text_edit = item.get('textEdit')
+ if text_edit and 'insert' in text_edit and 'replace' in text_edit:
+ insert_mode = userprefs().completion_insert_mode
+ oposite_insert_mode = 'Replace' if insert_mode == 'insert' else 'Insert'
+ command_url = "subl:lsp_commit_completion_with_opposite_insert_mode"
+ details.append("{}".format(command_url, oposite_insert_mode))
+ completion = sublime.CompletionItem(
+ trigger,
+ annotation,
+ # Not using "sublime.format_command" in a hot path to avoid slow json.dumps.
+ 'lsp_select_completion {{"index":{},"session_name":"{}"}}'.format(index, session_name),
+ sublime.COMPLETION_FORMAT_COMMAND,
+ kind,
+ details=" | ".join(details)
+ )
+ if text_edit:
completion.flags = sublime.COMPLETION_FLAG_KEEP_PREFIX
return completion
@@ -1095,13 +1096,3 @@ def format_code_actions_for_quick_panel(
if code_action.get('isPreferred', False):
selected_index = idx
return items, selected_index
-
-
-def get_insert_replace_support_html(item: CompletionItem) -> Optional[str]:
- text_edit = item.get('textEdit')
- if text_edit and 'insert' in text_edit and 'replace' in text_edit:
- insert_mode = userprefs().completion_insert_mode
- oposite_insert_mode = 'Replace' if insert_mode == 'insert' else 'Insert'
- command_url = sublime.command_url("lsp_commit_completion_with_opposite_insert_mode")
- return "{}".format(command_url, oposite_insert_mode)
- return None
diff --git a/stubs/sublime.pyi b/stubs/sublime.pyi
index 2b2a9aee4..9c4e45efd 100644
--- a/stubs/sublime.pyi
+++ b/stubs/sublime.pyi
@@ -63,6 +63,7 @@ INHIBIT_EXPLICIT_COMPLETIONS = ... # type: int
INHIBIT_REORDER = ... # type: int
DYNAMIC_COMPLETIONS = ... # type: int
COMPLETION_FLAG_KEEP_PREFIX = ... # type: int
+COMPLETION_FORMAT_COMMAND = ... # type: int
DIALOG_CANCEL = ... # type: int
DIALOG_YES = ... # type: int
DIALOG_NO = ... # type: int