Fix a few more file name completion cases

This commit is contained in:
Dave Halter
2019-08-04 22:43:23 +02:00
parent fd1e6afd07
commit e008a515e3
5 changed files with 43 additions and 18 deletions

View File

@@ -99,7 +99,14 @@ class Completion:
self._call_signatures_method = call_signatures_method self._call_signatures_method = call_signatures_method
def completions(self): def completions(self):
completion_names = self._get_context_completions() leaf = self._module_node.get_leaf_for_position(self._position, include_prefixes=True)
string = _extract_string_while_in_string(leaf, self._position)
if string is not None:
completions = list(file_name_completions(self._evaluator, string, self._like_name))
if completions:
return completions
completion_names = self._get_context_completions(leaf)
completions = filter_names(self._evaluator, completion_names, completions = filter_names(self._evaluator, completion_names,
self.stack, self._like_name) self.stack, self._like_name)
@@ -108,7 +115,7 @@ class Completion:
x.name.startswith('_'), x.name.startswith('_'),
x.name.lower())) x.name.lower()))
def _get_context_completions(self): def _get_context_completions(self, leaf):
""" """
Analyzes the context that a completion is made in and decides what to Analyzes the context that a completion is made in and decides what to
return. return.
@@ -126,13 +133,6 @@ class Completion:
grammar = self._evaluator.grammar grammar = self._evaluator.grammar
self.stack = stack = None self.stack = stack = None
leaf = self._module_node.get_leaf_for_position(self._position, include_prefixes=True)
string = _extract_string_while_in_string(leaf, self._position)
if string is not None:
completions = list(file_name_completions(self._evaluator, string, self._like_name))
if completions:
return completions
try: try:
self.stack = stack = helpers.get_stack_at_position( self.stack = stack = helpers.get_stack_at_position(
grammar, self._code_lines, leaf, self._position grammar, self._code_lines, leaf, self._position

View File

@@ -1,17 +1,32 @@
import os import os
from jedi._compatibility import FileNotFoundError
from jedi.evaluate.names import AbstractArbitraryName from jedi.evaluate.names import AbstractArbitraryName
from jedi.api import classes
def file_name_completions(evaluator, string, like_name): def file_name_completions(evaluator, string, like_name):
base_name = os.path.basename(string)
like_name = base_name + like_name
string = os.path.dirname(string)
base_path = os.path.join(evaluator.project._path, string) base_path = os.path.join(evaluator.project._path, string)
print(string, base_path) try:
for name in os.listdir(base_path): listed = os.listdir(base_path)
except FileNotFoundError:
return
for name in listed:
if name.startswith(like_name): if name.startswith(like_name):
path_for_name = os.path.join(base_path, name) path_for_name = os.path.join(base_path, name)
if os.path.isdir(path_for_name): if os.path.isdir(path_for_name):
name += os.path.sep name += os.path.sep
yield FileName(evaluator, name)
yield classes.Completion(
evaluator,
FileName(evaluator, name),
stack=None,
like_name_length=len(like_name),
)
class FileName(AbstractArbitraryName): class FileName(AbstractArbitraryName):

View File

@@ -1,7 +1,7 @@
import pydoc import pydoc
from jedi.evaluate.utils import ignored from jedi.evaluate.utils import ignored
from jedi.evaluate.names import AbstractNameDefinition from jedi.evaluate.names import AbstractArbitraryName
try: try:
from pydoc_data import topics as pydoc_topics from pydoc_data import topics as pydoc_topics
@@ -19,7 +19,7 @@ def get_operator(evaluator, string, pos):
return Keyword(evaluator, string, pos) return Keyword(evaluator, string, pos)
class KeywordName(AbstractNameDefinition): class KeywordName(AbstractArbitraryName):
api_type = u'keyword' api_type = u'keyword'
def infer(self): def infer(self):

View File

@@ -61,8 +61,8 @@ class AbstractNameDefinition(object):
class AbstractArbitraryName(AbstractNameDefinition): class AbstractArbitraryName(AbstractNameDefinition):
""" """
When you e.g. want to complete dicts keys, you probably want to complete When you e.g. want to complete dicts keys, you probably want to complete
string literals, which is not really a name, but for Jedi it works the same string literals, which is not really a name, but for Jedi we use this
way concept of Name for completions as well.
""" """
is_context_name = False is_context_name = False

View File

@@ -169,19 +169,29 @@ def test_keyword_completion(Script, code, has_keywords):
('example.py', 'r"comp"', None, ...), ('example.py', 'r"comp"', None, ...),
('example.py', 'r"tes"', None, ...), ('example.py', 'r"tes"', None, ...),
('example.py', 'r"tes"', 5, ['t' + s]), ('example.py', 'r"tes"', 5, ['t' + s]),
('example.py', 'r" tes"', 6, []),
('test%sexample.py' % s, 'r"tes"', 5, ['t' + s]), ('test%sexample.py' % s, 'r"tes"', 5, ['t' + s]),
('test%sexample.py' % s, 'r"test%scomp"' % s, 5, ['t' + s]), ('test%sexample.py' % s, 'r"test%scomp"' % s, 5, ['t' + s]),
('test%sexample.py' % s, 'r"test%scomp"' % s, 11, ['letion' + s]), ('test%sexample.py' % s, 'r"test%scomp"' % s, 11, ['letion' + s]),
('test%sexample.py' % s, 'r"%s"' % join('test', 'completion', 'basi'), 22, ['c.py']), ('test%sexample.py' % s, '"%s"' % join('test', 'completion', 'basi'), 21, ['c.py']),
('example.py', 'rb"' + join('..', 'jedi', 'tes'), None, ['t' + s]), ('example.py', 'rb"' + join('..', 'jedi', 'tes'), None, ['t' + s]),
# Absolute paths # Absolute paths
(None, '"' + join(root_dir, 'test', 'test_ca'), None, ['che.py']), (None, '"' + join(root_dir, 'test', 'test_ca'), None, ['che.py']),
(None, '"%s"' % join(root_dir, 'test', 'test_ca'), len(root_dir) + 14, ['che.py']), (None, '"%s"' % join(root_dir, 'test', 'test_ca'), len(root_dir) + 14, ['che.py']),
# Longer quotes
('example.py', 'r"""test', None, [s]),
('example.py', 'r"""\ntest', None, []),
('example.py', 'u"""tes\n', (1, 7), ['t' + s]),
('example.py', '"""test%stest_cache.p"""' % s, 20, ['y']),
] ]
) )
def test_file_path_completions(Script, file, code, column, expected): def test_file_path_completions(Script, file, code, column, expected):
comps = Script(code, path=file, column=column).completions() line = None
if isinstance(column, tuple):
line, column = column
comps = Script(code, path=file, line=line, column=column).completions()
if expected == ...: if expected == ...:
assert len(comps) > 100 # This is basically global completions. assert len(comps) > 100 # This is basically global completions.
else: else: