A first iteration for file path completions

This commit is contained in:
Dave Halter
2019-08-04 13:50:23 +02:00
parent 9dd088f3db
commit fd1e6afd07
8 changed files with 121 additions and 20 deletions

View File

@@ -144,7 +144,6 @@ class Script(object):
'(0-%d) for line %d (%r).' % (
column, line_len, line, line_string))
self._pos = line, column
self._path = path
cache.clear_time_caches()
debug.reset_time()

View File

@@ -1,3 +1,5 @@
import re
from parso.python.token import PythonTokenTypes
from parso.python import tree
from parso.tree import search_ancestor, Leaf
@@ -7,12 +9,13 @@ from jedi import debug
from jedi import settings
from jedi.api import classes
from jedi.api import helpers
from jedi.evaluate import imports
from jedi.api import keywords
from jedi.api.file_name import file_name_completions
from jedi.evaluate import imports
from jedi.evaluate.helpers import evaluate_call_of_leaf, parse_dotted_names
from jedi.evaluate.filters import get_global_filters
from jedi.evaluate.gradual.conversion import convert_contexts
from jedi.parser_utils import get_statement_of_position
from jedi.parser_utils import get_statement_of_position, cut_value_at_position
def get_call_signature_param_names(call_signatures):
@@ -121,19 +124,27 @@ class Completion:
"""
grammar = self._evaluator.grammar
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:
self.stack = stack = helpers.get_stack_at_position(
grammar, self._code_lines, self._module_node, self._position
grammar, self._code_lines, leaf, self._position
)
except helpers.OnErrorLeaf as e:
self.stack = stack = None
if e.error_leaf.value == '.':
value = e.error_leaf.value
if value == '.':
# After ErrorLeaf's that are dots, we will not do any
# completions since this probably just confuses the user.
return []
# If we don't have a context, just use global completion.
# If we don't have a context, just use global completion.
return self._global_completions()
allowed_transitions = \
@@ -289,3 +300,22 @@ class Completion:
# TODO we should probably check here for properties
if (name.api_type == 'function') == is_function:
yield name
def _extract_string_while_in_string(leaf, position):
if leaf.type == 'string':
match = re.match(r'^\w*(\'{3}|"{3}|\'|")', leaf.value)
quote = match.group(1)
if leaf.line == position[0] and position[1] < leaf.column + match.end():
return None
if leaf.end_pos[0] == position[0] and position[1] > leaf.end_pos[1] - len(quote):
return None
return cut_value_at_position(leaf, position)[match.end():]
leaves = []
while leaf is not None and leaf.line == position[0]:
if leaf.type == 'error_leaf' and ('"' in leaf.value or "'" in leaf.value):
return ''.join(l.get_code() for l in leaves)
leaves.insert(0, leaf)
leaf = leaf.get_previous_leaf()
return None

19
jedi/api/file_name.py Normal file
View File

@@ -0,0 +1,19 @@
import os
from jedi.evaluate.names import AbstractArbitraryName
def file_name_completions(evaluator, string, like_name):
base_path = os.path.join(evaluator.project._path, string)
print(string, base_path)
for name in os.listdir(base_path):
if name.startswith(like_name):
path_for_name = os.path.join(base_path, name)
if os.path.isdir(path_for_name):
name += os.path.sep
yield FileName(evaluator, name)
class FileName(AbstractArbitraryName):
api_type = u'path'
is_context_name = False

View File

@@ -54,8 +54,7 @@ class OnErrorLeaf(Exception):
return self.args[0]
def _get_code_for_stack(code_lines, module_node, position):
leaf = module_node.get_leaf_for_position(position, include_prefixes=True)
def _get_code_for_stack(code_lines, leaf, position):
# It might happen that we're on whitespace or on a comment. This means
# that we would not get the right leaf.
if leaf.start_pos >= position:
@@ -95,7 +94,7 @@ def _get_code_for_stack(code_lines, module_node, position):
return _get_code(code_lines, user_stmt.get_start_pos_of_prefix(), position)
def get_stack_at_position(grammar, code_lines, module_node, pos):
def get_stack_at_position(grammar, code_lines, leaf, pos):
"""
Returns the possible node names (e.g. import_from, xor_test or yield_stmt).
"""
@@ -119,7 +118,7 @@ def get_stack_at_position(grammar, code_lines, module_node, pos):
yield token
# The code might be indedented, just remove it.
code = dedent(_get_code_for_stack(code_lines, module_node, pos))
code = dedent(_get_code_for_stack(code_lines, leaf, pos))
# We use a word to tell Jedi when we have reached the start of the
# completion.
# Use Z as a prefix because it's not part of a number suffix.

View File

@@ -21,12 +21,6 @@ def get_operator(evaluator, string, pos):
class KeywordName(AbstractNameDefinition):
api_type = u'keyword'
is_context_name = False
def __init__(self, evaluator, name):
self.evaluator = evaluator
self.string_name = name
self.parent_context = evaluator.builtins_module
def infer(self):
return [Keyword(self.evaluator, self.string_name, (0, 0))]