8000 Respect client capabilities snippet support (#529) · brandonwillard/python-lsp-server@dfff3c9 · GitHub
[go: up one dir, main page]

Skip to content

Commit dfff3c9

Browse files
authored
Respect client capabilities snippet support (python-lsp#529)
Fixes python-lsp#515 Fixes python-lsp#526 Also only generates snippets for positional args
1 parent 467471b commit dfff3c9

File tree

8 files changed

+33
-14
lines changed

8 files changed

+33
-14
lines changed

.pylintrc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,6 @@ reports = no
2323

2424
[TYPECHECK]
2525

26-
generated-members = pyls_*
26+
generated-members =
27+
pyls_*
28+
cache_clear

pyls/config/config.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,12 @@
1818

1919
class Config(object):
2020

21-
def __init__(self, root_uri, init_opts, process_id):
21+
def __init__(self, root_uri, init_opts, process_id, capabilities):
2222
self._root_path = uris.to_fs_path(root_uri)
2323
self._root_uri = root_uri
2424
self._init_opts = init_opts
2525
self._process_id = process_id
26+
self._capabilities = capabilities
2627

2728
self._settings = {}
2829
self._plugin_settings = {}
@@ -86,6 +87,10 @@ def root_uri(self):
8687
def process_id(self):
8788
return self._process_id
8889

90+
@property
91+
def capabilities(self):
92+
return self._capabilities
93+
8994
@lru_cache(maxsize=32)
9095
def settings(self, document_path=None):
9196
"""Settings are constructed from a few sources:

pyls/config/source.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ def project_config(self, document_path):
2525
"""Return project-level (i.e. workspace directory) configuration."""
2626
raise NotImplementedError()
2727

28-
def read_config_from_files(self, files):
28+
@staticmethod
29+
def read_config_from_files(files):
2930
config = configparser.RawConfigParser()
3031
for filename in files:
3132
if os.path.exists(filename) and not os.path.isdir(filename):

pyls/plugins/jedi_completion.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,13 @@ def pyls_completions(config, document, position):
4545
if not definitions:
4646
return None
4747

48+
completion_capabilities = config.capabilities.get('textDocument', {}).get('completion', {})
49+
snippet_support = completion_capabilities.get('completionItem', {}).get('snippetSupport')
50+
4851
settings = config.plugin_settings('jedi_completion', document_path=document.path)
49-
include_params = settings.get('include_params', True)
52+
should_include_params = settings.get('include_params')
5053

51-
return [_format_completion(d, include_params) for d in definitions] or None
54+
return [_format_completion(d, snippet_support and should_include_params) for d in definitions] or None
5255

5356

5457
def _format_completion(d, include_params=True):
@@ -62,15 +65,18 @@ def _format_completion(d, include_params=True):
6265
}
6366

6467
if include_params and hasattr(d, 'params') and d.params:
68+
positional_args = [param for param in d.params if '=' not in param.description]
69+
6570
# For completions with params, we can generate a snippet instead
6671
completion['insertTextFormat'] = lsp.InsertTextFormat.Snippet
6772
snippet = d.name + '('
68-
for i, param in enumerate(d.params):
73+
for i, param in enumerate(positional_args):
6974
snippet += '${%s:%s}' % (i + 1, param.name)
70-
if i < len(d.params) - 1:
75+
if i < len(positional_args) - 1:
7176
snippet += ', '
7277
snippet += ')$0'
7378
completion['insertText'] = snippet
79+
7480
return completion
7581

7682

pyls/python_ls.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,8 @@ def m_initialize(self, processId=None, rootUri=None, rootPath=None, initializati
157157
rootUri = uris.from_fs_path(rootPath) if rootPath is not None else ''
158158

159159
self.workspace = Workspace(rootUri, self._endpoint)
160-
self.config = config.Config(rootUri, initializationOptions or {}, processId)
160+
self.config = config.Config(rootUri, initializationOptions or {},
161+
processId, _kwargs.get('capabilities', {}))
161162
self._dispatchers = self._hook('pyls_dispatchers')
162163
self._hook('pyls_initialize')
163164

@@ -299,17 +300,17 @@ def m_workspace__did_change_configuration(self, settings=None):
299300
for doc_uri in self.workspace.documents:
300301
self.lint(doc_uri, is_saved=False)
301302

302-
def m_workspace__did_change_watched_files(self, changes=[], **_kwargs):
303+
def m_workspace__did_change_watched_files(self, changes=None, **_kwargs):
303304
changed_py_files = set()
304305
config_changed = False
305-
for d in changes:
306+
for d in (changes or []):
306307
if d['uri'].endswith(PYTHON_FILE_EXTENSIONS):
307308
changed_py_files.add(d['uri'])
308309
elif d['uri'].endswith(CONFIG_FILEs):
309310
config_changed = True
310311

311312
if config_changed:
312-
self.settings.cache_clear()
313+
self.config.settings.cache_clear()
313314
elif not changed_py_files:
314315
# Only externally changed python files and lint configs may result in changed diagnostics.
315316
return

test/fixtures.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def workspace(tmpdir):
4444
@pytest.fixture
4545
def config(workspace): # pylint: disable=redefined-outer-name
4646
"""Return a config object."""
47-
return Config(workspace.root_uri, {}, 0)
47+
return Config(workspace.root_uri, {}, 0, {})
4848

4949

5050
@pytest.fixture

test/plugins/test_completion.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,15 @@ def test_jedi_method_completion(config):
9595
com_position = {'line': 20, 'character': 19}
9696
doc = Document(DOC_URI, DOC)
9797

98+
config.capabilities['textDocument'] = {'completion': {'completionItem': {'snippetSupport': True}}}
99+
config.update({'plugins': {'jedi_completion': {'include_params': True}}})
100+
98101
completions = pyls_jedi_completions(config, doc, com_position)
99102
everyone_method = [completion for completion in completions if completion['label'] == 'everyone(a, b, c, d)'][0]
100103

104+
# Ensure we only generate snippets for positional args
101105
assert everyone_method['insertTextFormat'] == lsp.InsertTextFormat.Snippet
102-
assert everyone_method['insertText'] == 'everyone(${1:a}, ${2:b}, ${3:c}, ${4:d})$0'
106+
assert everyone_method['insertText'] == 'everyone(${1:a}, ${2:b})$0'
103107

104108
# Disable param snippets
105109
config.update({'plugins': {'jedi_completion': {'include_params': False}}})

test/plugins/test_pycodestyle_lint.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ def test_pycodestyle_config(workspace):
6767
doc_uri = uris.from_fs_path(os.path.join(workspace.root_path, 'test.py'))
6868
workspace.put_document(doc_uri, DOC)
6969
doc = workspace.get_document(doc_uri)
70-
config = Config(workspace.root_uri, {}, 1234)
70+
config = Config(workspace.root_uri, {}, 1234, {})
7171

7272
# Make sure we get a warning for 'indentation contains tabs'
7373
diags = pycodestyle_lint.pyls_lint(config, doc)

0 commit comments

Comments
 (0)
0