mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-07 06:24:27 +08:00
Start working on uniting parts of code of file path/dict completion
This commit is contained in:
@@ -10,7 +10,7 @@ from jedi import settings
|
|||||||
from jedi.api import classes
|
from jedi.api import classes
|
||||||
from jedi.api import helpers
|
from jedi.api import helpers
|
||||||
from jedi.api import keywords
|
from jedi.api import keywords
|
||||||
from jedi.api.dicts import completions_for_dicts
|
from jedi.api.strings import completions_for_dicts
|
||||||
from jedi.api.file_name import file_name_completions
|
from jedi.api.file_name import file_name_completions
|
||||||
from jedi.inference import imports
|
from jedi.inference import imports
|
||||||
from jedi.inference.helpers import infer_call_of_leaf, parse_dotted_names
|
from jedi.inference.helpers import infer_call_of_leaf, parse_dotted_names
|
||||||
@@ -93,7 +93,7 @@ class Completion:
|
|||||||
if string is None:
|
if string is None:
|
||||||
string = ''
|
string = ''
|
||||||
bracket_leaf = leaf
|
bracket_leaf = leaf
|
||||||
if bracket_leaf.type == 'number':
|
if bracket_leaf.type in ('number', 'error_leaf'):
|
||||||
string = bracket_leaf.value
|
string = bracket_leaf.value
|
||||||
bracket_leaf = bracket_leaf.get_previous_leaf()
|
bracket_leaf = bracket_leaf.get_previous_leaf()
|
||||||
|
|
||||||
@@ -113,6 +113,8 @@ class Completion:
|
|||||||
))
|
))
|
||||||
if completions:
|
if completions:
|
||||||
return completions
|
return completions
|
||||||
|
if string is not None:
|
||||||
|
return prefixed_completions
|
||||||
|
|
||||||
completion_names = self._get_context_completions(leaf)
|
completion_names = self._get_context_completions(leaf)
|
||||||
|
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
from jedi.inference.names import AbstractArbitraryName
|
|
||||||
from jedi.api.classes import Completion
|
|
||||||
|
|
||||||
_sentinel = object()
|
|
||||||
|
|
||||||
|
|
||||||
class F(AbstractArbitraryName):
|
|
||||||
api_type = u'path'
|
|
||||||
is_value_name = False
|
|
||||||
|
|
||||||
|
|
||||||
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:
|
|
||||||
if dct.array_type == 'dict':
|
|
||||||
for key in dct.get_key_values():
|
|
||||||
dict_key = key.get_safe_value(default=_sentinel)
|
|
||||||
if dict_key is not _sentinel:
|
|
||||||
yield dict_key
|
|
||||||
@@ -1,10 +1,13 @@
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
from jedi._compatibility import FileNotFoundError, force_unicode, scandir
|
from jedi._compatibility import FileNotFoundError, force_unicode, scandir
|
||||||
from jedi.inference.names import AbstractArbitraryName
|
|
||||||
from jedi.api import classes
|
from jedi.api import classes
|
||||||
|
from jedi.api.strings import StringName, get_quote_ending
|
||||||
from jedi.inference.helpers import get_str_or_none
|
from jedi.inference.helpers import get_str_or_none
|
||||||
from jedi.parser_utils import get_string_quote
|
|
||||||
|
|
||||||
|
class PathName(StringName):
|
||||||
|
api_type = u'path'
|
||||||
|
|
||||||
|
|
||||||
def file_name_completions(inference_state, module_context, start_leaf, string,
|
def file_name_completions(inference_state, module_context, start_leaf, string,
|
||||||
@@ -39,22 +42,13 @@ def file_name_completions(inference_state, module_context, start_leaf, string,
|
|||||||
name = entry.name
|
name = entry.name
|
||||||
if name.startswith(must_start_with):
|
if name.startswith(must_start_with):
|
||||||
if is_in_os_path_join or not entry.is_dir():
|
if is_in_os_path_join or not entry.is_dir():
|
||||||
if start_leaf.type == 'string':
|
name += get_quote_ending(start_leaf, code_lines, position)
|
||||||
quote = get_string_quote(start_leaf)
|
|
||||||
else:
|
|
||||||
assert start_leaf.type == 'error_leaf'
|
|
||||||
quote = start_leaf.value
|
|
||||||
potential_other_quote = \
|
|
||||||
code_lines[position[0] - 1][position[1]:position[1] + len(quote)]
|
|
||||||
# Add a quote if it's not already there.
|
|
||||||
if quote != potential_other_quote:
|
|
||||||
name += quote
|
|
||||||
else:
|
else:
|
||||||
name += os.path.sep
|
name += os.path.sep
|
||||||
|
|
||||||
yield classes.Completion(
|
yield classes.Completion(
|
||||||
inference_state,
|
inference_state,
|
||||||
FileName(inference_state, name[len(must_start_with) - like_name_length:]),
|
PathName(inference_state, name[len(must_start_with) - like_name_length:]),
|
||||||
stack=None,
|
stack=None,
|
||||||
like_name_length=like_name_length
|
like_name_length=like_name_length
|
||||||
)
|
)
|
||||||
@@ -99,11 +93,6 @@ def _add_strings(context, nodes, add_slash=False):
|
|||||||
return string
|
return string
|
||||||
|
|
||||||
|
|
||||||
class FileName(AbstractArbitraryName):
|
|
||||||
api_type = u'path'
|
|
||||||
is_value_name = False
|
|
||||||
|
|
||||||
|
|
||||||
def _add_os_path_join(module_context, start_leaf, bracket_start):
|
def _add_os_path_join(module_context, start_leaf, bracket_start):
|
||||||
def check(maybe_bracket, nodes):
|
def check(maybe_bracket, nodes):
|
||||||
if maybe_bracket.start_pos != bracket_start:
|
if maybe_bracket.start_pos != bracket_start:
|
||||||
|
|||||||
50
jedi/api/strings.py
Normal file
50
jedi/api/strings.py
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
"""
|
||||||
|
This module is here for string completions. This means mostly stuff where
|
||||||
|
strings are returned, like `foo = dict(bar=3); foo["ba` would complete to
|
||||||
|
`"bar"]`.
|
||||||
|
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
from jedi.inference.names import AbstractArbitraryName
|
||||||
|
from jedi.api.classes import Completion
|
||||||
|
from jedi.parser_utils import get_string_quote
|
||||||
|
|
||||||
|
_sentinel = object()
|
||||||
|
|
||||||
|
|
||||||
|
class StringName(AbstractArbitraryName):
|
||||||
|
api_type = u'string'
|
||||||
|
is_value_name = False
|
||||||
|
|
||||||
|
|
||||||
|
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 = StringName(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:
|
||||||
|
if dct.array_type == 'dict':
|
||||||
|
for key in dct.get_key_values():
|
||||||
|
dict_key = key.get_safe_value(default=_sentinel)
|
||||||
|
if dict_key is not _sentinel:
|
||||||
|
yield dict_key
|
||||||
|
|
||||||
|
|
||||||
|
def get_quote_ending(start_leaf, code_lines, position):
|
||||||
|
if start_leaf.type == 'string':
|
||||||
|
quote = get_string_quote(start_leaf)
|
||||||
|
else:
|
||||||
|
assert start_leaf.type == 'error_leaf'
|
||||||
|
quote = start_leaf.value
|
||||||
|
potential_other_quote = \
|
||||||
|
code_lines[position[0] - 1][position[1]:position[1] + len(quote)]
|
||||||
|
# Add a quote only if it's not already there.
|
||||||
|
if quote == potential_other_quote:
|
||||||
|
return ''
|
||||||
|
return quote
|
||||||
Reference in New Issue
Block a user