mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-07 06:24:27 +08:00
Fix a few more file name completion cases
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
Reference in New Issue
Block a user