Skip to content

Commit

Permalink
Fix: Use "filterText" (fallback to "label") for the trigger of the co…
Browse files Browse the repository at this point in the history
…mpletion item
  • Loading branch information
rwols committed Apr 4, 2019
1 parent bcada7c commit 495fb92
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 44 deletions.
5 changes: 5 additions & 0 deletions LSP.sublime-settings
Expand Up @@ -355,6 +355,11 @@
// Resolve completions and apply snippet if received.
"resolve_completion_for_snippets": false,

// When presenting completions, prefer the "label" over the "filterText" key
// in the CompletionItem. By default, the "filterText" is chosen over the
// "label". If the "filterText" is not present, fall back to the "label".
"prefer_label_over_filter_text": false,

// Show symbol references in Sublime's quick panel instead of the bottom panel.
"show_references_in_quick_panel": false,

Expand Down
1 change: 1 addition & 0 deletions docs/index.md
Expand Up @@ -10,6 +10,7 @@ Global plugin settings and settings defined at project level are merged together
* `only_show_lsp_completions` `false` *disable sublime word completion and snippets from autocomplete lists*
* `completion_hint_type` `"auto"` *override automatic completion hints with "detail", "kind" or "none"*
* `resolve_completion_for_snippets` `false` *resolve completions and apply snippet if received*
* `prefer_label_over_filter_text` `false` *always use the "label" key instead of the "filterText" key in CompletionItems*
* `show_references_in_quick_panel` `false` *show symbol references in Sublime's quick panel instead of the bottom panel*
* `show_status_messages` `true` *show messages in the status bar for a few seconds*
* `show_view_status` `true` *show permanent language server status in the status bar*
Expand Down
14 changes: 8 additions & 6 deletions plugin/completion.py
Expand Up @@ -258,7 +258,10 @@ def do_request(self, prefix: str, locations: 'List[int]'):

def format_completion(self, item: dict) -> 'Tuple[str, str]':
# Sublime handles snippets automatically, so we don't have to care about insertTextFormat.
label = item["label"]
if settings.prefer_label_over_filter_text:
trigger = item["label"]
else:
trigger = item.get("filterText", item["label"])
# choose hint based on availability and user preference
hint = None
if settings.completion_hint_type == "auto":
Expand All @@ -274,12 +277,11 @@ def format_completion(self, item: dict) -> 'Tuple[str, str]':
if kind:
hint = completion_item_kind_names.get(kind)
# label is an alternative for insertText if neither textEdit nor insertText is provided
insert_text = self.text_edit_text(item) or item.get("insertText") or label
trigger = insert_text
if len(insert_text) > 0 and insert_text[0] == '$': # sublime needs leading '$' escaped.
insert_text = '\\$' + insert_text[1:]
replacement = self.text_edit_text(item) or item.get("insertText") or trigger
if len(replacement) > 0 and replacement[0] == '$': # sublime needs leading '$' escaped.
replacement = '\\$' + replacement[1:]
# only return trigger with a hint if available
return "\t ".join((trigger, hint)) if hint else trigger, insert_text
return "\t ".join((trigger, hint)) if hint else trigger, replacement

def text_edit_text(self, item) -> 'Optional[str]':
text_edit = item.get("textEdit")
Expand Down
1 change: 1 addition & 0 deletions plugin/core/settings.py
Expand Up @@ -64,6 +64,7 @@ def update_settings(settings: Settings, settings_obj: sublime.Settings):
settings.complete_all_chars = read_bool_setting(settings_obj, "complete_all_chars", True)
settings.completion_hint_type = read_str_setting(settings_obj, "completion_hint_type", "auto")
settings.resolve_completion_for_snippets = read_bool_setting(settings_obj, "resolve_completion_for_snippets", False)
settings.prefer_label_over_filter_text = read_bool_setting(settings_obj, "prefer_label_over_filter_text", False)
settings.show_references_in_quick_panel = read_bool_setting(settings_obj, "show_references_in_quick_panel", False)
settings.log_debug = read_bool_setting(settings_obj, "log_debug", False)
settings.log_server = read_bool_setting(settings_obj, "log_server", True)
Expand Down
1 change: 1 addition & 0 deletions plugin/core/types.py
Expand Up @@ -34,6 +34,7 @@ def __init__(self) -> None:
self.complete_all_chars = False
self.completion_hint_type = "auto"
self.resolve_completion_for_snippets = False
self.prefer_label_over_filter_text = False
self.show_references_in_quick_panel = False
self.log_debug = True
self.log_server = True
Expand Down
79 changes: 41 additions & 38 deletions tests/test_completion.py
Expand Up @@ -7,6 +7,12 @@
from LSP.plugin.core.settings import client_configs, ClientConfig
from os.path import dirname, join

try:
from typing import Dict, Optional
assert Dict and Optional
except ImportError:
pass


def load_completion_sample(name: str) -> 'Dict':
return json.load(open(join(dirname(__file__), name + ".json")))
Expand All @@ -17,7 +23,7 @@ def load_completion_sample(name: str) -> 'Dict':
intelephense_completion_sample = load_completion_sample("intelephense_completion_sample")


def create_completion_item(item: str, insert_text: 'Optional[str]'=None) -> dict:
def create_completion_item(item: str, insert_text: 'Optional[str]' = None) -> dict:
return {
"label": item,
"insertText": insert_text
Expand Down Expand Up @@ -144,7 +150,7 @@ def test_prefers_insert_text(self):
handler = CompletionHandler(self.view)
result = handler.format_completion(create_completion_item("asdf", "Asdf"))
self.assertEqual(len(result), 2)
self.assertEqual("Asdf", result[0])
self.assertEqual("asdf", result[0])
self.assertEqual("Asdf", result[1])

def test_ignores_text_edit(self):
Expand All @@ -165,7 +171,7 @@ def test_ignores_text_edit(self):

result = handler.format_completion(item)
self.assertEqual(len(result), 2)
self.assertEqual("$true", result[0])
self.assertEqual("true", result[0])
self.assertEqual("\\$true", result[1])

def test_ignore_label(self):
Expand Down Expand Up @@ -235,27 +241,24 @@ def test_text_edit_clangd(self):
[
('argc\t int', 'argc'),
('argv\t const char **', 'argv'),
('alignas(${1:expression})\t Snippet', 'alignas(${1:expression})'),
('alignof(${1:type})\t size_t', 'alignof(${1:type})'),
('alignas\t Snippet', 'alignas(${1:expression})'),
('alignof\t size_t', 'alignof(${1:type})'),
('auto\t Keyword', 'auto'),
('static_assert(${1:expression}, ${2:message})\t Snippet',
'static_assert(${1:expression}, ${2:message})'),
('a64l(${1:const char *__s})\t long', 'a64l(${1:const char *__s})'),
('abort()\t void', 'abort()'),
('abs(${1:int __x})\t int', 'abs(${1:int __x})'),
('aligned_alloc(${1:size_t __alignment}, ${2:size_t __size})\t void *',
'aligned_alloc(${1:size_t __alignment}, ${2:size_t __size})'),
('alloca(${1:size_t __size})\t void *', 'alloca(${1:size_t __size})'),
('asctime(${1:const struct tm *__tp})\t char *', 'asctime(${1:const struct tm *__tp})'),
('asctime_r(${1:const struct tm *__restrict __tp}, ${2:char *__restrict __buf})\t char *',
'asctime_r(${1:const struct tm *__restrict __tp}, ${2:char *__restrict __buf})'),
('asprintf(${1:char **__restrict __ptr}, ${2:const char *__restrict __fmt, ...})\t int',
'asprintf(${1:char **__restrict __ptr}, ${2:const char *__restrict __fmt, ...})'),
('at_quick_exit(${1:void (*__func)()})\t int', 'at_quick_exit(${1:void (*__func)()})'),
('atexit(${1:void (*__func)()})\t int', 'atexit(${1:void (*__func)()})'),
('atof(${1:const char *__nptr})\t double', 'atof(${1:const char *__nptr})'),
('atoi(${1:const char *__nptr})\t int', 'atoi(${1:const char *__nptr})'),
('atol(${1:const char *__nptr})\t long', 'atol(${1:const char *__nptr})')
('static_assert\t Snippet', 'static_assert(${1:expression}, ${2:message})'),
('a64l\t long', 'a64l(${1:const char *__s})'),
('abort\t void', 'abort()'),
('abs\t int', 'abs(${1:int __x})'),
('aligned_alloc\t void *', 'aligned_alloc(${1:size_t __alignment}, ${2:size_t __size})'),
('alloca\t void *', 'alloca(${1:size_t __size})'),
('asctime\t char *', 'asctime(${1:const struct tm *__tp})'),
('asctime_r\t char *',
'asctime_r(${1:const struct tm *__restrict __tp}, ${2:char *__restrict __buf})'),
('asprintf\t int', 'asprintf(${1:char **__restrict __ptr}, ${2:const char *__restrict __fmt, ...})'),
('at_quick_exit\t int', 'at_quick_exit(${1:void (*__func)()})'),
('atexit\t int', 'atexit(${1:void (*__func)()})'),
('atof\t double', 'atof(${1:const char *__nptr})'),
('atoi\t int', 'atoi(${1:const char *__nptr})'),
('atol\t long', 'atol(${1:const char *__nptr})')
]
)

Expand All @@ -269,29 +272,29 @@ def test_missing_text_edit_but_we_do_have_insert_text_for_pyls(self):
result,
[
('abc\t os', 'abc'),
('abort\t os', 'abort'),
('access(${1:path}, ${2:mode}, ${3:dir_fd}, ${4:effective_ids}, ${5:follow_symlinks})$0\t os',
'access(${1:path}, ${2:mode}, ${3:dir_fd}, ${4:effective_ids}, ${5:follow_symlinks})$0'),
('abort()\t os', 'abort'),
('access(path, mode, dir_fd, effective_ids, follow_symlinks)\t os',
'access(${1:path}, ${2:mode}, ${3:dir_fd}, ${4:effective_ids}, ${5:follow_symlinks})$0'),
('altsep\t os', 'altsep'),
('chdir(${1:path})$0\t os', 'chdir(${1:path})$0'),
('chmod(${1:path}, ${2:mode}, ${3:dir_fd}, ${4:follow_symlinks})$0\t os',
'chmod(${1:path}, ${2:mode}, ${3:dir_fd}, ${4:follow_symlinks})$0'),
('chown(${1:path}, ${2:uid}, ${3:gid}, ${4:dir_fd}, ${5:follow_symlinks})$0\t os',
'chown(${1:path}, ${2:uid}, ${3:gid}, ${4:dir_fd}, ${5:follow_symlinks})$0'),
('chroot(${1:path})$0\t os', 'chroot(${1:path})$0'),
('chdir(path)\t os', 'chdir(${1:path})$0'),
('chmod(path, mode, dir_fd, follow_symlinks)\t os',
'chmod(${1:path}, ${2:mode}, ${3:dir_fd}, ${4:follow_symlinks})$0'),
('chown(path, uid, gid, dir_fd, follow_symlinks)\t os',
'chown(${1:path}, ${2:uid}, ${3:gid}, ${4:dir_fd}, ${5:follow_symlinks})$0'),
('chroot(path)\t os', 'chroot(${1:path})$0'),
('CLD_CONTINUED\t os', 'CLD_CONTINUED'),
('CLD_DUMPED\t os', 'CLD_DUMPED'),
('CLD_EXITED\t os', 'CLD_EXITED'),
('CLD_TRAPPED\t os', 'CLD_TRAPPED'),
('close(${1:fd})$0\t os', 'close(${1:fd})$0'),
('closerange(${1:fd_low}, ${2:fd_high})$0\t os', 'closerange(${1:fd_low}, ${2:fd_high})$0'),
('confstr(${1:name})$0\t os', 'confstr(${1:name})$0'),
('close(fd)\t os', 'close(${1:fd})$0'),
('closerange(fd_low, fd_high)\t os', 'closerange(${1:fd_low}, ${2:fd_high})$0'),
('confstr(name)\t os', 'confstr(${1:name})$0'),
('confstr_names\t os', 'confstr_names'),
('cpu_count\t os', 'cpu_count'),
('ctermid\t os', 'ctermid'),
('cpu_count()\t os', 'cpu_count'),
('ctermid()\t os', 'ctermid'),
('curdir\t os', 'curdir'),
('defpath\t os', 'defpath'),
('device_encoding(${1:fd})$0\t os', 'device_encoding(${1:fd})$0')
('device_encoding(fd)\t os', 'device_encoding(${1:fd})$0')
]
)

Expand Down

0 comments on commit 495fb92

Please sign in to comment.