forked from VimPlug/jedi
Get a few more tests passing about dict key strings
This commit is contained in:
@@ -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.
|
||||||
|
|||||||
@@ -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):])
|
|
||||||
|
|||||||
@@ -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"']),
|
||||||
|
|||||||
Reference in New Issue
Block a user