Skip to content

Commit ac91446

Browse files
authored
Completions overhaul (#2010)
1 parent da960d5 commit ac91446

File tree

2 files changed

+50
-87
lines changed

2 files changed

+50
-87
lines changed

plugin/core/views.py

Lines changed: 38 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -939,66 +939,51 @@ def format_diagnostic_for_html(
939939
return "".join(formatted)
940940

941941

942-
def _is_completion_item_deprecated(item: CompletionItem) -> bool:
943-
if item.get("deprecated", False):
944-
return True
945-
tags = item.get("tags")
946-
if isinstance(tags, list):
947-
return CompletionItemTag.Deprecated in tags
948-
return False
949-
950-
951-
def _wrap_in_tags(tag: str, item: str) -> str:
952-
return "<{0}>{1}</{0}>".format(tag, html.escape(item))
953-
954-
955942
def format_completion(
956943
item: CompletionItem, index: int, can_resolve_completion_items: bool, session_name: str
957944
) -> sublime.CompletionItem:
958945
# This is a hot function. Don't do heavy computations or IO in this function.
959-
item_kind = item.get("kind")
960-
kind = COMPLETION_KINDS.get(item_kind, KIND_UNSPECIFIED) if item_kind else KIND_UNSPECIFIED
961-
962-
if _is_completion_item_deprecated(item):
963-
kind = (kind[0], '!', "⚠ {} - Deprecated".format(kind[2]))
964-
965-
lsp_label = item["label"]
966-
lsp_label_details = item.get("labelDetails")
967-
lsp_filter_text = item.get("filterText")
968-
st_annotation = (item.get("detail") or "").replace('\n', ' ')
969-
970-
st_details = ""
971-
if can_resolve_completion_items or item.get("documentation"):
972-
st_details += make_command_link("lsp_resolve_docs", "More", {"index": index, "session_name": session_name})
973-
if lsp_label_details:
974-
if st_details:
975-
st_details += " | "
976-
lsp_label_detail = lsp_label_details.get("detail")
977-
lsp_label_description = lsp_label_details.get("description")
978-
st_details += "<p>"
979-
# `label` should be rendered most prominent.
980-
st_details += _wrap_in_tags("b", lsp_label)
981-
if isinstance(lsp_label_detail, str):
982-
# `detail` should be rendered less prominent than `label`.
983-
# The string is appended directly after `label`, with no additional white space applied.
984-
st_details += html.escape(lsp_label_detail)
985-
if isinstance(lsp_label_description, str):
986-
# `description` should be rendered less prominent than `detail`.
987-
# Additional separation is added.
988-
st_details += " - {}".format(_wrap_in_tags("i", lsp_label_description))
989-
st_details += "</p>"
990-
elif lsp_filter_text and lsp_filter_text != lsp_label:
991-
if st_details:
992-
st_details += " | "
993-
st_details += _wrap_in_tags("p", lsp_label)
946+
947+
lsp_label = item['label']
948+
lsp_label_details = item.get('labelDetails') or {}
949+
lsp_label_detail = lsp_label_details.get('detail') or ""
950+
lsp_label_description = lsp_label_details.get('description') or ""
951+
lsp_filter_text = item.get('filterText') or ""
952+
lsp_detail = (item.get('detail') or "").replace("\n", " ")
953+
954+
kind = COMPLETION_KINDS.get(item.get('kind', -1), KIND_UNSPECIFIED)
955+
956+
details = [] # type: List[str]
957+
if can_resolve_completion_items or item.get('documentation'):
958+
details.append(make_command_link('lsp_resolve_docs', "More", {'index': index, 'session_name': session_name}))
959+
960+
if lsp_label_detail and (lsp_label + lsp_label_detail).startswith(lsp_filter_text):
961+
trigger = lsp_label + lsp_label_detail
962+
annotation = lsp_label_description or lsp_detail
963+
elif lsp_label.startswith(lsp_filter_text):
964+
trigger = lsp_label
965+
annotation = lsp_detail
966+
if lsp_label_detail:
967+
details.append(html.escape(lsp_label + lsp_label_detail))
968+
if lsp_label_description:
969+
details.append(html.escape(lsp_label_description))
970+
else:
971+
trigger = lsp_filter_text
972+
annotation = lsp_detail
973+
details.append(html.escape(lsp_label + lsp_label_detail))
974+
if lsp_label_description:
975+
details.append(html.escape(lsp_label_description))
976+
977+
if item.get('deprecated') or CompletionItemTag.Deprecated in item.get('tags', []):
978+
annotation = "DEPRECATED - " + annotation if annotation else "DEPRECATED"
994979

995980
completion = sublime.CompletionItem.command_completion(
996-
trigger=lsp_filter_text or lsp_label,
997-
command="lsp_select_completion_item",
981+
trigger=trigger,
982+
command='lsp_select_completion_item',
998983
args={"item": item, "session_name": session_name},
999-
annotation=st_annotation,
984+
annotation=annotation,
1000985
kind=kind,
1001-
details=st_details)
1002-
if item.get("textEdit"):
986+
details=" | ".join(details))
987+
if item.get('textEdit'):
1003988
completion.flags = sublime.COMPLETION_FLAG_KEEP_PREFIX
1004989
return completion

tests/test_completion.py

Lines changed: 12 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,6 @@ def test_var_prefix_added_in_insertText(self) -> 'Generator':
142142
'sortText': '0006USERPROFILE',
143143
'label': 'USERPROFILE',
144144
'additionalTextEdits': None,
145-
'detail': None,
146145
'data': None,
147146
'kind': 6,
148147
'command': None,
@@ -178,7 +177,6 @@ def test_pure_insertion_text_edit(self) -> 'Generator':
178177
}
179178
},
180179
'label': '$someParam',
181-
'filterText': None,
182180
'data': None,
183181
'command': None,
184182
'detail': 'null',
@@ -612,8 +610,7 @@ def test_show_deprecated_flag(self) -> None:
612610
"deprecated": True
613611
} # type: CompletionItem
614612
formatted_completion_item = format_completion(item_with_deprecated_flag, 0, False, "")
615-
self.assertEqual('!', formatted_completion_item.kind[1])
616-
self.assertEqual('⚠ Method - Deprecated', formatted_completion_item.kind[2])
613+
self.assertIn("DEPRECATED", formatted_completion_item.annotation)
617614

618615
def test_show_deprecated_tag(self) -> None:
619616
item_with_deprecated_tags = {
@@ -622,8 +619,7 @@ def test_show_deprecated_tag(self) -> None:
622619
"tags": [CompletionItemTag.Deprecated]
623620
} # type: CompletionItem
624621
formatted_completion_item = format_completion(item_with_deprecated_tags, 0, False, "")
625-
self.assertEqual('!', formatted_completion_item.kind[1])
626-
self.assertEqual('⚠ Method - Deprecated', formatted_completion_item.kind[2])
622+
self.assertIn("DEPRECATED", formatted_completion_item.annotation)
627623

628624
def test_strips_carriage_return_in_insert_text(self) -> 'Generator':
629625
yield from self.verify(
@@ -662,37 +658,37 @@ def check(
662658

663659
check(
664660
resolve_support=False,
665-
expected_regex=r"^<p>f</p>$",
661+
expected_regex=r"^f$",
666662
label="f",
667663
label_details=None
668664
)
669665
check(
670666
resolve_support=False,
671-
expected_regex=r"^<p><b>f</b>\(X&amp; x\)</p>$",
667+
expected_regex=r"^f\(X&amp; x\)$",
672668
label="f",
673669
label_details={"detail": "(X& x)"}
674670
)
675671
check(
676672
resolve_support=False,
677-
expected_regex=r"^<p><b>f</b>\(X&amp; x\) - <i>does things</i></p>$",
673+
expected_regex=r"^f\(X&amp; x\) \| does things$",
678674
label="f",
679675
label_details={"detail": "(X& x)", "description": "does things"}
680676
)
681677
check(
682678
resolve_support=True,
683-
expected_regex=r"^<a href='subl:lsp_resolve_docs {\S+}'>More</a> \| <p>f</p>$",
679+
expected_regex=r"^<a href='subl:lsp_resolve_docs {\S+}'>More</a> \| f$",
684680
label="f",
685681
label_details=None
686682
)
687683
check(
688684
resolve_support=True,
689-
expected_regex=r"^<a href='subl:lsp_resolve_docs {\S+}'>More</a> \| <p><b>f</b>\(X&amp; x\)</p>$",
685+
expected_regex=r"^<a href='subl:lsp_resolve_docs {\S+}'>More</a> \| f\(X&amp; x\)$",
690686
label="f",
691687
label_details={"detail": "(X& x)"}
692688
)
693689
check(
694690
resolve_support=True,
695-
expected_regex=r"^<a href='subl:lsp_resolve_docs {\S+}'>More</a> \| <p><b>f</b>\(X&amp; x\) - <i>does things</i></p>$", # noqa: E501
691+
expected_regex=r"^<a href='subl:lsp_resolve_docs {\S+}'>More</a> \| f\(X&amp; x\) \| does things$", # noqa: E501
696692
label="f",
697693
label_details={"detail": "(X& x)", "description": "does things"}
698694
)
@@ -709,41 +705,23 @@ def check(
709705
if label_details is not None:
710706
lsp["labelDetails"] = label_details
711707
native = format_completion(lsp, 0, resolve_support, "")
712-
self.assertRegex(native.details, expected_regex)
708+
self.assertRegex(native.trigger, expected_regex)
713709

714710
check(
715711
resolve_support=False,
716-
expected_regex=r"^$",
712+
expected_regex=r"^f$",
717713
label="f",
718714
label_details=None
719715
)
720716
check(
721717
resolve_support=False,
722-
expected_regex=r"^<p><b>f</b>\(X&amp; x\)</p>$",
718+
expected_regex=r"^f\(X& x\)$",
723719
label="f",
724720
label_details={"detail": "(X& x)"}
725721
)
726722
check(
727723
resolve_support=False,
728-
expected_regex=r"^<p><b>f</b>\(X&amp; x\) - <i>does things</i></p>$",
729-
label="f",
730-
label_details={"detail": "(X& x)", "description": "does things"}
731-
)
732-
check(
733-
resolve_support=True,
734-
expected_regex=r"^<a href='subl:lsp_resolve_docs {\S+}'>More</a>$",
735-
label="f",
736-
label_details=None
737-
)
738-
check(
739-
resolve_support=True,
740-
expected_regex=r"^<a href='subl:lsp_resolve_docs {\S+}'>More</a> \| <p><b>f</b>\(X&amp; x\)</p>$",
741-
label="f",
742-
label_details={"detail": "(X& x)"}
743-
)
744-
check(
745-
resolve_support=True,
746-
expected_regex=r"^<a href='subl:lsp_resolve_docs {\S+}'>More</a> \| <p><b>f</b>\(X&amp; x\) - <i>does things</i></p>$", # noqa: E501
724+
expected_regex=r"^f\(X& x\)$",
747725
label="f",
748726
label_details={"detail": "(X& x)", "description": "does things"}
749727
)

0 commit comments

Comments
 (0)