1
0
forked from VimPlug/jedi

Get a few more tests passing about dict key strings

This commit is contained in:
Dave Halter
2019-09-23 21:04:52 +02:00
parent 954fd56fcc
commit 88ebb3e140
3 changed files with 42 additions and 26 deletions

View File

@@ -88,7 +88,24 @@ class Completion:
def completions(self): def completions(self):
leaf = self._module_node.get_leaf_for_position(self._position, include_prefixes=True) leaf = self._module_node.get_leaf_for_position(self._position, include_prefixes=True)
string, start_leaf = _extract_string_while_in_string(leaf, self._position) string, start_leaf = _extract_string_while_in_string(leaf, self._position)
if string is not None:
prefixed_completions = []
if string is None:
string = ''
bracket_leaf = leaf
if bracket_leaf.type == 'number':
string = bracket_leaf.value
bracket_leaf = bracket_leaf.get_previous_leaf()
if bracket_leaf == '[':
context = self._module_context.create_context(bracket_leaf)
before_bracket_leaf = bracket_leaf.get_previous_leaf()
if before_bracket_leaf.type in ('atom', 'trailer', 'name'):
values = infer_call_of_leaf(context, before_bracket_leaf)
prefixed_completions += completions_for_dicts(
self._inference_state, values, string)
if string is not None and not prefixed_completions:
completions = list(file_name_completions( completions = list(file_name_completions(
self._inference_state, self._module_context, start_leaf, string, self._inference_state, self._module_context, start_leaf, string,
self._like_name, self._call_signatures_callback, self._like_name, self._call_signatures_callback,
@@ -102,9 +119,12 @@ class Completion:
completions = filter_names(self._inference_state, completion_names, completions = filter_names(self._inference_state, completion_names,
self.stack, self._like_name) self.stack, self._like_name)
return sorted(completions, key=lambda x: (x.name.startswith('__'), return (
x.name.startswith('_'), prefixed_completions +
x.name.lower())) sorted(completions, key=lambda x: (x.name.startswith('__'),
x.name.startswith('_'),
x.name.lower()))
)
def _get_context_completions(self, leaf): def _get_context_completions(self, leaf):
""" """
@@ -178,24 +198,13 @@ class Completion:
if not current_line or current_line[-1] in ' \t.;': if not current_line or current_line[-1] in ' \t.;':
completion_names += self._get_keyword_completion_names(allowed_transitions) completion_names += self._get_keyword_completion_names(allowed_transitions)
nodes = _gather_nodes(stack)
if any(n.nonterminal == 'trailer' and n.nodes[0] == '[' for n in stack):
bracket = self._module_node.get_leaf_for_position(self._position, include_prefixes=True)
string = ''
if bracket.type == 'number':
string = bracket.value
bracket = bracket.get_previous_leaf()
context = self._module_context.create_context(bracket)
values = infer_call_of_leaf(context, bracket.get_previous_leaf())
completion_names += completions_for_dicts(values, string)
if any(t in allowed_transitions for t in (PythonTokenTypes.NAME, if any(t in allowed_transitions for t in (PythonTokenTypes.NAME,
PythonTokenTypes.INDENT)): PythonTokenTypes.INDENT)):
# This means that we actually have to do type inference. # This means that we actually have to do type inference.
nonterminals = [stack_node.nonterminal for stack_node in stack] nonterminals = [stack_node.nonterminal for stack_node in stack]
nodes = _gather_nodes(stack)
if nodes and nodes[-1] in ('as', 'def', 'class'): if nodes and nodes[-1] in ('as', 'def', 'class'):
# No completions for ``with x as foo`` and ``import x as foo``. # No completions for ``with x as foo`` and ``import x as foo``.
# Also true for defining names as a class or function. # Also true for defining names as a class or function.

View File

@@ -1,4 +1,5 @@
from jedi.inference.names import AbstractArbitraryName from jedi.inference.names import AbstractArbitraryName
from jedi.api.classes import Completion
_sentinel = object() _sentinel = object()
@@ -8,12 +9,18 @@ class F(AbstractArbitraryName):
is_value_name = False is_value_name = False
def completions_for_dicts(dicts, literal_string): def completions_for_dicts(inference_state, dicts, literal_string):
for dict_key in sorted(_get_python_keys(dicts)):
dict_key_str = repr(dict_key)
if dict_key_str.startswith(literal_string):
name = F(inference_state, dict_key_str[len(literal_string):])
yield Completion(inference_state, name, stack=None, like_name_length=0)
def _get_python_keys(dicts):
for dct in dicts: for dct in dicts:
if dct.array_type == 'dict': if dct.array_type == 'dict':
for key in dct.get_key_values(): for key in dct.get_key_values():
dict_key = key.get_safe_value(default=_sentinel) dict_key = key.get_safe_value(default=_sentinel)
if dict_key is not _sentinel: if dict_key is not _sentinel:
dict_key_str = str(dict_key) yield dict_key
if dict_key_str.startswith(literal_string):
yield F(dct.inference_state, dict_key_str[len(literal_string):])

View File

@@ -283,12 +283,12 @@ def test_file_path_completions(Script, file, code, column, expected):
('ints[50', 6, ['']),#TODO ['0']), ('ints[50', 6, ['']),#TODO ['0']),
('ints[50', 7, ['']), ('ints[50', 7, ['']),
('strs[', 5, ["'asdf'", "'foo'", "'fbar'", Ellipsis]), ('strs[', 5, ["'asdf'", "'fbar'", "'foo'", Ellipsis]),
('strs[]', 5, ["'asdf'", "'foo'", "'fbar'", Ellipsis]), ('strs[]', 5, ["'asdf'", "'fbar'", "'foo'", Ellipsis]),
("strs[']", 6, ["asdf'", "foo'", "fbar'"]), ("strs[']", 6, ["asdf'", "fbar'", "foo'"]),
('strs["]', 6, ['asdf"', 'foo"', 'fbar"']), ('strs["]', 6, ['asdf"', 'fbar"', 'foo"']),
('strs["""]', 6, ['asdf', 'foo', 'fbar']), ('strs["""]', 6, ['asdf', 'bar', 'foo']),
('strs["""]', 8, ['asdf"""', 'foo"""', 'fbar"""']), ('strs["""]', 8, ['asdf"""', 'fbar"""', 'foo"""']),
('strs[b"]', 8, []), ('strs[b"]', 8, []),
('strs[r"asd', 11, ['f"']), ('strs[r"asd', 11, ['f"']),
('strs[R"asd', 11, ['f"']), ('strs[R"asd', 11, ['f"']),