1
0
forked from VimPlug/jedi

Fix some more dict tests

This commit is contained in:
Dave Halter
2019-12-30 00:29:55 +01:00
parent c7296ade68
commit 7e769b87f3
5 changed files with 91 additions and 37 deletions

View File

@@ -10,7 +10,7 @@ from jedi import settings
from jedi.api import classes
from jedi.api import helpers
from jedi.api import keywords
from jedi.api.strings import completions_for_dicts
from jedi.api.strings import complete_dict
from jedi.api.file_name import complete_file_name
from jedi.inference import imports
from jedi.inference.base_value import ValueSet
@@ -105,21 +105,13 @@ class Completion:
leaf = self._module_node.get_leaf_for_position(self._position, include_prefixes=True)
string, start_leaf = _extract_string_while_in_string(leaf, self._position)
prefixed_completions = []
#if string is None:
#string = ''
bracket_leaf = leaf
#if bracket_leaf.type in ('number', 'error_leaf'):
#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, fuzzy=fuzzy)
prefixed_completions = complete_dict(
self._module_context,
leaf,
self._original_position,
string,
fuzzy=fuzzy,
)
if string is not None and not prefixed_completions:
prefixed_completions = list(complete_file_name(
@@ -128,8 +120,6 @@ class Completion:
self._code_lines, self._original_position,
fuzzy
))
if prefixed_completions:
return prefixed_completions
if string is not None:
return prefixed_completions

View File

@@ -7,9 +7,13 @@ It however does the same for numbers. The difference between string completions
and other completions is mostly that this module doesn't return defined
names in a module, but pretty much an arbitrary string.
"""
import re
from jedi._compatibility import unicode
from jedi.inference.names import AbstractArbitraryName
from jedi.inference.helpers import infer_call_of_leaf
from jedi.api.classes import Completion
from jedi.parser_utils import get_string_quote
from jedi.parser_utils import cut_value_at_position
_sentinel = object()
@@ -19,11 +23,46 @@ class StringName(AbstractArbitraryName):
is_value_name = False
def completions_for_dicts(inference_state, dicts, literal_string, fuzzy):
for dict_key in sorted(_get_python_keys(dicts)):
dict_key_str = repr(dict_key)
def complete_dict(module_context, leaf, position, string, fuzzy):
if string is None:
string = ''
bracket_leaf = leaf
end_quote = ''
if bracket_leaf.type in ('number', 'error_leaf'):
string = cut_value_at_position(bracket_leaf, position)
if bracket_leaf.end_pos > position:
end_quote = _get_string_quote(string) or ''
if end_quote:
ending = cut_value_at_position(
bracket_leaf,
(position[0], position[1] + len(end_quote))
)
if not ending.endswith(end_quote):
end_quote = ''
bracket_leaf = bracket_leaf.get_previous_leaf()
if bracket_leaf == '[':
context = 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)
return list(_completions_for_dicts(
module_context.inference_state,
values,
'' if string is None else string,
end_quote,
fuzzy=fuzzy,
))
return []
def _completions_for_dicts(inference_state, dicts, literal_string, end_quote, fuzzy):
for dict_key in sorted(_get_python_keys(dicts), key=lambda x: repr(x)):
dict_key_str = _create_repr_string(literal_string, dict_key)
if dict_key_str.startswith(literal_string):
name = StringName(inference_state, dict_key_str[len(literal_string):])
n = dict_key_str[len(literal_string):-len(end_quote) or None]
name = StringName(inference_state, n)
yield Completion(
inference_state,
name,
@@ -33,6 +72,17 @@ def completions_for_dicts(inference_state, dicts, literal_string, fuzzy):
)
def _create_repr_string(literal_string, dict_key):
if not isinstance(dict_key, (unicode, bytes)) or not literal_string:
return repr(dict_key)
r = repr(dict_key)
prefix, quote = _get_string_prefix_and_quote(literal_string)
if quote == r[0]:
return prefix + r
return prefix + quote + r[1:-1] + quote
def _get_python_keys(dicts):
for dct in dicts:
if dct.array_type == 'dict':
@@ -42,9 +92,20 @@ def _get_python_keys(dicts):
yield dict_key
def _get_string_prefix_and_quote(string):
match = re.match(r'(\w*)("""|\'{3}|"|\')', string)
if match is None:
return None, None
return match.group(1), match.group(2)
def _get_string_quote(string):
return _get_string_prefix_and_quote(string)[1]
def get_quote_ending(start_leaf, code_lines, position):
if start_leaf.type == 'string':
quote = get_string_quote(start_leaf)
quote = _get_string_quote(start_leaf)
else:
assert start_leaf.type == 'error_leaf'
quote = start_leaf.value