Skip to content

Commit 958528d

Browse files
committed
Add snippet cache
1 parent 71e1b6f commit 958528d

File tree

2 files changed

+55
-31
lines changed

2 files changed

+55
-31
lines changed

pylsp/plugins/_resolvers.py

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
from jedi.api.classes import Completion
99

10+
from pylsp import lsp
11+
1012

1113
log = logging.getLogger(__name__)
1214

@@ -15,8 +17,9 @@
1517
# -----------------------------------------------------------------------------
1618
class Resolver:
1719

18-
def __init__(self, callback, time_to_live=60 * 30):
20+
def __init__(self, callback, resolve_on_error, time_to_live=60 * 30):
1921
self.callback = callback
22+
self.resolve_on_error = resolve_on_error
2023
self._cache = {}
2124
self._time_to_live = time_to_live
2225
self._cache_ttl = defaultdict(set)
@@ -82,7 +85,7 @@ def resolve(self, completion):
8285
'Something went wrong when resolving label for {completion}: {e}',
8386
completion=completion, e=e
8487
)
85-
return ''
88+
return self.resolve_on_error
8689

8790

8891
# ---- Label resolver
@@ -95,4 +98,38 @@ def format_label(completion, sig):
9598
return completion.name
9699

97100

98-
LABEL_RESOLVER = Resolver(format_label)
101+
LABEL_RESOLVER = Resolver(callback=format_label, resolve_on_error='')
102+
103+
104+
# ---- Snippets resolver
105+
# -----------------------------------------------------------------------------
106+
def format_snippet(completion, sig):
107+
if not sig:
108+
return {}
109+
110+
snippet_completion = {}
111+
112+
positional_args = [param for param in sig[0].params
113+
if '=' not in param.description and
114+
param.name not in {'/', '*'}]
115+
116+
if len(positional_args) > 1:
117+
# For completions with params, we can generate a snippet instead
118+
snippet_completion['insertTextFormat'] = lsp.InsertTextFormat.Snippet
119+
snippet = completion.name + '('
120+
for i, param in enumerate(positional_args):
121+
snippet += '${%s:%s}' % (i + 1, param.name)
122+
if i < len(positional_args) - 1:
123+
snippet += ', '
124+
snippet += ')$0'
125+
snippet_completion['insertText'] = snippet
126+
elif len(positional_args) == 1:
127+
snippet_completion['insertTextFormat'] = lsp.InsertTextFormat.Snippet
128+
snippet_completion['insertText'] = completion.name + '($0)'
129+
else:
130+
snippet_completion['insertText'] = completion.name + '()'
131+
132+
return snippet_completion
133+
134+
135+
SNIPPET_RESOLVER = Resolver(callback=format_snippet, resolve_on_error={})

pylsp/plugins/jedi_completion.py

Lines changed: 15 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import parso
88

99
from pylsp import _utils, hookimpl, lsp
10-
from pylsp.plugins._resolvers import LABEL_RESOLVER
10+
from pylsp.plugins._resolvers import LABEL_RESOLVER, SNIPPET_RESOLVER
1111

1212
log = logging.getLogger(__name__)
1313

@@ -59,6 +59,7 @@ def pylsp_completions(config, document, position):
5959
modules_to_cache_labels_for = settings.get('cache_labels_for', None)
6060
if modules_to_cache_labels_for is not None:
6161
LABEL_RESOLVER.cached_modules = modules_to_cache_labels_for
62+
SNIPPET_RESOLVER.cached_modules = modules_to_cache_labels_for
6263

6364
include_params = snippet_support and should_include_params and use_snippets(document, position)
6465
include_class_objects = snippet_support and should_include_class_objects and use_snippets(document, position)
@@ -68,7 +69,7 @@ def pylsp_completions(config, document, position):
6869
c,
6970
include_params,
7071
resolve=resolve_eagerly,
71-
resolve_label=(i < max_labels_resolve)
72+
resolve_label_or_snippet=(i < max_labels_resolve)
7273
)
7374
for i, c in enumerate(completions)
7475
]
@@ -81,7 +82,7 @@ def pylsp_completions(config, document, position):
8182
c,
8283
False,
8384
resolve=resolve_eagerly,
84-
resolve_label=(i < max_labels_resolve)
85+
resolve_label_or_snippet=(i < max_labels_resolve)
8586
)
8687
completion_dict['kind'] = lsp.CompletionItemKind.TypeParameter
8788
completion_dict['label'] += ' object'
@@ -173,9 +174,9 @@ def _resolve_completion(completion, d):
173174
return completion
174175

175176

176-
def _format_completion(d, include_params=True, resolve=False, resolve_label=False):
177+
def _format_completion(d, include_params=True, resolve=False, resolve_label_or_snippet=False):
177178
completion = {
178-
'label': _label(d, resolve_label),
179+
'label': _label(d, resolve_label_or_snippet),
179180
'kind': _TYPE_MAP.get(d.type),
180181
'sortText': _sort_text(d),
181182
'insertText': d.name
@@ -191,29 +192,8 @@ def _format_completion(d, include_params=True, resolve=False, resolve_label=Fals
191192
completion['insertText'] = path
192193

193194
if include_params and not is_exception_class(d.name):
194-
sig = d.get_signatures()
195-
if not sig:
196-
return completion
197-
198-
positional_args = [param for param in sig[0].params
199-
if '=' not in param.description and
200-
param.name not in {'/', '*'}]
201-
202-
if len(positional_args) > 1:
203-
# For completions with params, we can generate a snippet instead
204-
completion['insertTextFormat'] = lsp.InsertTextFormat.Snippet
205-
snippet = d.name + '('
206-
for i, param in enumerate(positional_args):
207-
snippet += '${%s:%s}' % (i + 1, param.name)
208-
if i < len(positional_args) - 1:
209-
snippet += ', '
210-
snippet += ')$0'
211-
completion['insertText'] = snippet
212-
elif len(positional_args) == 1:
213-
completion['insertTextFormat'] = lsp.InsertTextFormat.Snippet
214-
completion['insertText'] = d.name + '($0)'
215-
else:
216-
completion['insertText'] = d.name + '()'
195+
snippet = _snippet(d, resolve_label_or_snippet)
196+
completion.update(snippet)
217197

218198
return completion
219199

@@ -227,6 +207,13 @@ def _label(definition, resolve=False):
227207
return definition.name
228208

229209

210+
def _snippet(definition, resolve=False):
211+
if not resolve:
212+
return {}
213+
snippet = SNIPPET_RESOLVER.get_or_create(definition)
214+
return snippet
215+
216+
230217
def _detail(definition):
231218
try:
232219
return definition.parent().full_name or ''

0 commit comments

Comments
 (0)