Exchange the completion trailer evaluation logic. It's way more consistent now.

This commit is contained in:
Dave Halter
2016-06-23 08:47:31 +02:00
parent cbef4235ff
commit 1ab4eb3696
4 changed files with 24 additions and 32 deletions

View File

@@ -1,5 +1,4 @@
from itertools import chain
import re
from jedi.parser import token
from jedi.parser import tree
@@ -11,6 +10,7 @@ from jedi.api import inference
from jedi.evaluate import imports
from jedi.api import keywords
from jedi.evaluate import compiled
from jedi.evaluate.helpers import call_of_leaf
from jedi.evaluate.finder import global_names_dict_generator, filter_definition_names
@@ -65,13 +65,7 @@ class Completion:
def completions(self, path):
completion_parts = helpers.get_completion_parts(path)
user_stmt = self._parser.user_stmt_with_whitespace()
completion_names = self._get_context_completions(user_stmt, completion_parts)
if not completion_parts.has_dot:
call_signatures = self._call_signatures_method()
completion_names += get_call_signature_param_names(call_signatures)
completion_names = self._get_context_completions(completion_parts)
completions = filter_names(self._evaluator, completion_names,
completion_parts.name)
@@ -80,7 +74,7 @@ class Completion:
x.name.startswith('_'),
x.name.lower()))
def _get_context_completions(self, user_stmt, completion_parts):
def _get_context_completions(self, completion_parts):
"""
Analyzes the context that a completion is made in and decides what to
return.
@@ -147,11 +141,17 @@ class Completion:
# No completions for ``with x as foo`` and ``import x as foo``.
# Also true for defining names as a class or function.
return []
elif symbol_names[-1] == 'trailer' and '(' != nodes[-1]:
completion_names += self._trailer_completions(completion_parts)
elif symbol_names[-1] == 'trailer' and nodes[-1] == '.':
dot = self._module.get_leaf_for_position(pos)
atom_expr = call_of_leaf(dot.get_previous_leaf())
completion_names += self._trailer_completions(atom_expr)
else:
completion_names += self._global_completions()
if 'trailer' in symbol_names:
call_signatures = self._call_signatures_method()
completion_names += get_call_signature_param_names(call_signatures)
return completion_names
def _get_keyword_completion_names(self, keywords_):
@@ -177,11 +177,8 @@ class Completion:
)
return completion_names
def _trailer_completions(self, completion_parts):
scopes = list(inference.type_inference(
self._evaluator, self._parser,
self._pos, completion_parts.path
))
def _trailer_completions(self, atom_expr):
scopes = self._evaluator.eval_element(atom_expr)
completion_names = []
debug.dbg('possible completion scopes: %s', scopes)
for s in scopes:

View File

@@ -2,26 +2,10 @@
This module has helpers for doing type inference on strings. It is needed,
because we still want to infer types where the syntax is invalid.
"""
from jedi import debug
from jedi.parser import Parser, ParseError
from jedi.evaluate.cache import memoize_default
def type_inference(evaluator, parser, position, dotted_path):
"""
Base for completions/goto. Basically it returns the resolved scopes
under cursor.
"""
debug.dbg('start: %s in %s', dotted_path, parser.user_scope())
# Just parse one statement, take it and evaluate it.
eval_stmt = get_under_cursor_stmt(evaluator, parser, dotted_path, position)
if eval_stmt is None:
return []
return evaluator.eval_element(eval_stmt)
@memoize_default(evaluator_is_first_arg=True)
def get_under_cursor_stmt(evaluator, parser, cursor_txt, start_pos):
"""

View File

@@ -88,6 +88,8 @@ def call_of_leaf(leaf, cut_own_trailer=False):
# different trailers: `( x )`, `[ x ]` and `.x`. In the first two examples
# we should not match anything more than x.
if trailer.type != 'trailer' or leaf not in (trailer.children[0], trailer.children[-1]):
if trailer.type == 'atom':
return trailer
return leaf
power = trailer.parent

View File

@@ -20,3 +20,12 @@ a(some_args)
#? 13 []
a(some_kwargs)
def multiple(foo, bar):
pass
#? 17 ['bar']
multiple(foo, bar)
#? ['bar']
multiple(foo, bar