From 89d60abfe3116fbd3c8bd207a7d3afe9e8975e17 Mon Sep 17 00:00:00 2001 From: krassowski Date: Sun, 25 Apr 2021 19:08:42 +0100 Subject: [PATCH 1/2] Fix Jedi type map (use types offered by modern Jedi) --- pylsp/plugins/jedi_completion.py | 40 +++++------------ test/plugins/test_completion.py | 77 ++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 29 deletions(-) diff --git a/pylsp/plugins/jedi_completion.py b/pylsp/plugins/jedi_completion.py index 1e3c80e7..5b07f56b 100644 --- a/pylsp/plugins/jedi_completion.py +++ b/pylsp/plugins/jedi_completion.py @@ -10,39 +10,21 @@ log = logging.getLogger(__name__) -# Map to the VSCode type +# Map to the LSP type +# > Valid values for type are ``module``, `` class ``, ``instance``, ``function``, +# > ``param``, ``path``, ``keyword``, ``property`` and ``statement``. +# see: https://jedi.readthedocs.io/en/latest/docs/api-classes.html#jedi.api.classes.BaseName.type _TYPE_MAP = { - 'none': lsp.CompletionItemKind.Value, - 'type': lsp.CompletionItemKind.Class, - 'tuple': lsp.CompletionItemKind.Class, - 'dict': lsp.CompletionItemKind.Class, - 'dictionary': lsp.CompletionItemKind.Class, - 'function': lsp.CompletionItemKind.Function, - 'lambda': lsp.CompletionItemKind.Function, - 'generator': lsp.CompletionItemKind.Function, + 'module': lsp.CompletionItemKind.Module, + 'namespace': lsp.CompletionItemKind.Module, # to be added in Jedi 0.18+ 'class': lsp.CompletionItemKind.Class, 'instance': lsp.CompletionItemKind.Reference, - 'method': lsp.CompletionItemKind.Method, - 'builtin': lsp.CompletionItemKind.Class, - 'builtinfunction': lsp.CompletionItemKind.Function, - 'module': lsp.CompletionItemKind.Module, - 'file': lsp.CompletionItemKind.File, - 'path': lsp.CompletionItemKind.Text, - 'xrange': lsp.CompletionItemKind.Class, - 'slice': lsp.CompletionItemKind.Class, - 'traceback': lsp.CompletionItemKind.Class, - 'frame': lsp.CompletionItemKind.Class, - 'buffer': lsp.CompletionItemKind.Class, - 'dictproxy': lsp.CompletionItemKind.Class, - 'funcdef': lsp.CompletionItemKind.Function, - 'property': lsp.CompletionItemKind.Property, - 'import': lsp.CompletionItemKind.Module, - 'keyword': lsp.CompletionItemKind.Keyword, - 'constant': lsp.CompletionItemKind.Variable, - 'variable': lsp.CompletionItemKind.Variable, - 'value': lsp.CompletionItemKind.Value, + 'function': lsp.CompletionItemKind.Function, 'param': lsp.CompletionItemKind.Variable, - 'statement': lsp.CompletionItemKind.Keyword, + 'path': lsp.CompletionItemKind.File, + 'keyword': lsp.CompletionItemKind.Keyword, + 'property': lsp.CompletionItemKind.Property, # added in Jedi 0.18 + 'statement': lsp.CompletionItemKind.Variable } # Types of parso nodes for which snippet is not included in the completion diff --git a/test/plugins/test_completion.py b/test/plugins/test_completion.py index 258b2288..3ac494bd 100644 --- a/test/plugins/test_completion.py +++ b/test/plugins/test_completion.py @@ -4,6 +4,9 @@ import os import sys +from pathlib import Path +from typing import NamedTuple, Dict + import pytest from pylsp import uris, lsp @@ -50,6 +53,80 @@ def test_rope_import_completion(config, workspace): assert items is None +class TypeCase(NamedTuple): + document: str + position: dict + label: str + expected: lsp.CompletionItemKind + + +TYPE_CASES: Dict[str, TypeCase] = { + 'variable': TypeCase( + document='test = 1\ntes', + position={'line': 1, 'character': 3}, + label='test', + expected=lsp.CompletionItemKind.Variable + ), + 'function': TypeCase( + document='def test():\n pass\ntes', + position={'line': 2, 'character': 3}, + label='test()', + expected=lsp.CompletionItemKind.Function + ), + 'keyword': TypeCase( + document='fro', + position={'line': 0, 'character': 3}, + label='from', + expected=lsp.CompletionItemKind.Keyword + ), + 'file': TypeCase( + document='"' + __file__[:-2].replace('"', '\\"') + '"', + position={'line': 0, 'character': len(__file__) - 2}, + label=Path(__file__).name + '"', + expected=lsp.CompletionItemKind.File + ), + 'module': TypeCase( + document='import statis', + position={'line': 0, 'character': 13}, + label='statistics', + expected=lsp.CompletionItemKind.Module + ), + 'class': TypeCase( + document='KeyErr', + position={'line': 0, 'character': 6}, + label='KeyError', + expected=lsp.CompletionItemKind.Class + ), + 'property': TypeCase( + document=( + 'class A:\n' + ' @property\n' + ' def test(self):\n' + ' pass\n' + 'A().tes' + ), + position={'line': 4, 'character': 5}, + label='test', + expected=lsp.CompletionItemKind.Property + ) +} + + +@pytest.mark.parametrize('case', list(TYPE_CASES.values()), ids=list(TYPE_CASES.keys())) +def test_jedi_completion_type(case, config, workspace): + # pylint: disable=C0415 + import jedi + + # property support was introduced in 0.18 + if case.expected == lsp.CompletionItemKind.Property and jedi.__version__.startswith('0.17'): + return + + doc = Document(DOC_URI, workspace, case.document) + items = pylsp_jedi_completions(config, doc, case.position) + items = {i['label']: i for i in items} + assert items[case.label]['kind'] == case.expected + + def test_jedi_completion(config, workspace): # Over 'i' in os.path.isabs(...) com_position = {'line': 1, 'character': 15} From e81594cec9478c39cc8918e9241d9d451f4c0973 Mon Sep 17 00:00:00 2001 From: krassowski Date: Sun, 25 Apr 2021 20:16:24 +0100 Subject: [PATCH 2/2] Use JEDI_VERSION --- test/plugins/test_completion.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/test/plugins/test_completion.py b/test/plugins/test_completion.py index 3ac494bd..df197248 100644 --- a/test/plugins/test_completion.py +++ b/test/plugins/test_completion.py @@ -13,6 +13,7 @@ from pylsp.workspace import Document from pylsp.plugins.jedi_completion import pylsp_completions as pylsp_jedi_completions from pylsp.plugins.rope_completion import pylsp_completions as pylsp_rope_completions +from pylsp._utils import JEDI_VERSION PY2 = sys.version[0] == '2' @@ -114,11 +115,8 @@ class TypeCase(NamedTuple): @pytest.mark.parametrize('case', list(TYPE_CASES.values()), ids=list(TYPE_CASES.keys())) def test_jedi_completion_type(case, config, workspace): - # pylint: disable=C0415 - import jedi - # property support was introduced in 0.18 - if case.expected == lsp.CompletionItemKind.Property and jedi.__version__.startswith('0.17'): + if case.expected == lsp.CompletionItemKind.Property and JEDI_VERSION.startswith('0.17'): return doc = Document(DOC_URI, workspace, case.document)