mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-08 14:54:47 +08:00
Exchange the completion trailer evaluation logic. It's way more consistent now.
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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):
|
||||
"""
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user