8000 Generate insert snippets for callables (#499) · lcheylus/python-lsp-server@ee71c1d · GitHub
[go: up one dir, main page]

Skip to content

Commit ee71c1d

Browse files
authored
Generate insert snippets for callables (python-lsp#499)
Fixes python-lsp#496
1 parent 50d03d5 commit ee71c1d

File tree

4 files changed

+77
-18
lines changed

4 files changed

+77
-18
lines changed

pyls/lsp.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ class DiagnosticSeverity(object):
3939
Hint = 4
4040

4141

42+
class InsertTextFormat(object):
43+
PlainText = 1
44+
Snippet = 2
45+
46+
4247
class MessageType(object):
4348
Error = 1
4449
Warning = 2

pyls/plugins/jedi_completion.py

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,39 @@
66

77

88
@hookimpl
9-
def pyls_completions(document, position):
9+
def pyls_completions(config, document, position):
1010
definitions = document.jedi_script(position).completions()
11-
return [{
12-
'label': _label(d),
13-
'kind': _kind(d),
14-
'detail': _detail(d),
15-
'documentation': _utils.format_docstring(d.docstring()),
16-
'sortText': _sort_text(d),
17-
'insertText': d.name
18-
} for d in definitions] or None
11+
if not definitions:
12+
return None
13+
14+
settings = config.plugin_settings('jedi_completion', document_path=document.path)
15+
include_params = settings.get('include_params', True)
16+
17+
completions = []
18+
for d in definitions:
19+
completion = {
20+
'label': _label(d),
21+
'kind': _kind(d),
22+
'detail': _detail(d),
23+
'documentation': _utils.format_docstring(d.docstring()),
24+
'sortText': _sort_text(d),
25+
'insertText': d.name
26+
}
27+
28+
if include_params and hasattr(d, 'params') and d.params:
29+
# For completions with params, we can generate a snippet instead
30+
completion['insertTextFormat'] = lsp.InsertTextFormat.Snippet
31+
snippet = d.name + '('
32+
for i, param in enumerate(d.params):
33+
snippet += '${%s:%s}' % (i + 1, param.name)
34+
if i < len(d.params) - 1:
35+
snippet += ', '
36+
snippet += ')$0'
37+
completion['insertText'] = snippet
38+
39+
completions.append(completion)
40+
41+
return completions or None
1942

2043

2144
def _label(definition):

test/plugins/test_completion.py

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Copyright 2017 Palantir Technologies, Inc.
22
import os
33

4-
from pyls import uris
4+
from pyls import uris, lsp
55
from pyls.workspace import Document
66
from pyls.plugins.jedi_completion import pyls_completions as pyls_jedi_completions
77
from pyls.plugins.rope_completion import pyls_completions as pyls_rope_completions
@@ -26,7 +26,12 @@ class Hello():
2626
def world(self):
2727
return None
2828
29+
def everyone(self, a, b, c=None, d=2):
30+
pass
31+
2932
print Hello().world
33+
34+
print Hello().every
3035
"""
3136

3237

@@ -37,17 +42,17 @@ def test_rope_import_completion(config, workspace):
3742
assert items is None
3843

3944

40-
def test_jedi_completion():
45+
def test_jedi_completion(config):
4146
# Over 'i' in os.path.isabs(...)
4247
com_position = {'line': 1, 'character': 15}
4348
doc = Document(DOC_URI, DOC)
44-
items = pyls_jedi_completions(doc, com_position)
49+
items = pyls_jedi_completions(config, doc, com_position)
4550

4651
assert items
4752
assert items[0]['label'] == 'isabs(s)'
4853

4954
# Test we don't throw with big character
50-
pyls_jedi_completions(doc, {'line': 1, 'character': 1000})
55+
pyls_jedi_completions(config, doc, {'line': 1, 'character': 1000})
5156

5257

5358
def test_rope_completion(config, workspace):
@@ -61,25 +66,46 @@ def test_rope_completion(config, workspace):
6166
assert items[0]['label'] == 'isabs'
6267

6368

64-
def test_jedi_completion_ordering():
69+
def test_jedi_completion_ordering(config):
6570
# Over the blank line
6671
com_position = {'line': 8, 'character': 0}
6772
doc = Document(DOC_URI, DOC)
68-
completions = pyls_jedi_completions(doc, com_position)
73+
completions = pyls_jedi_completions(config, doc, com_position)
6974

7075
items = {c['label']: c['sortText'] for c in completions}
7176

7277
# And that 'hidden' functions come after unhidden ones
7378
assert items['hello()'] < items['_a_hello()']
7479

7580

76-
def test_jedi_property_completion():
81+
def test_jedi_property_completion(config):
7782
# Over the 'w' in 'print Hello().world'
78-
com_position = {'line': 15, 'character': 15}
83+
com_position = {'line': 18, 'character': 15}
7984
doc = Document(DOC_URI, DOC)
80-
completions = pyls_jedi_completions(doc, com_position)
85+
completions = pyls_jedi_completions(config, doc, com_position)
8186

8287
items = {c['label']: c['sortText'] for c in completions}
8388

8489
# Ensure we can complete the 'world' property
8590
assert 'world' in items
91+
92+
93+
def test_jedi_method_completion(config):
94+
# Over the 'y' in 'print Hello().every'
95+
com_position = {'line': 20, 'character': 19}
96+
doc = Document(DOC_URI, DOC)
97+
98+
completions = pyls_jedi_completions(config, doc, com_position)
99+
everyone_method = [completion for completion in completions if completion['label'] == 'everyone(a, b, c, d)'][0]
100+
101+
assert everyone_method['insertTextFormat'] == lsp.InsertTextFormat.Snippet
102+
assert everyone_method['insertText'] == 'everyone(${1:a}, ${2:b}, ${3:c}, ${4:d})$0'
103+
104+
# Disable param snippets
105+
config.update({'plugins': {'jedi_completion': {'include_params': False}}})
106+
107+
completions = pyls_jedi_completions(config, doc, com_position)
108+
every A5C0 one_method = [completion for completion in completions if completion['label'] == 'everyone(a, b, c, d)'][0]
109+
110+
assert 'insertTextFormat' not in everyone_method
111+
assert everyone_method['insertText'] == 'everyone'

vscode-client/package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@
3535
"default": true,
3636
"description": "Enable or disable the plugin."
3737
},
38+
"pyls.plugins.jedi_completion.include_params": {
39+
"type": "boolean",
40+
"default": true,
41+
"description": "Auto-completes methods and classes with tabstops for each parameter."
42+
},
3843
"pyls.plugins.jedi_definition.enabled": {
3944
"type": "boolean",
4045
"default": true,

0 commit comments

Comments
 (0)
0