forked from VimPlug/jedi
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
|
from itertools import chain
|
||||||
import re
|
|
||||||
|
|
||||||
from jedi.parser import token
|
from jedi.parser import token
|
||||||
from jedi.parser import tree
|
from jedi.parser import tree
|
||||||
@@ -11,6 +10,7 @@ from jedi.api import inference
|
|||||||
from jedi.evaluate import imports
|
from jedi.evaluate import imports
|
||||||
from jedi.api import keywords
|
from jedi.api import keywords
|
||||||
from jedi.evaluate import compiled
|
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
|
from jedi.evaluate.finder import global_names_dict_generator, filter_definition_names
|
||||||
|
|
||||||
|
|
||||||
@@ -65,13 +65,7 @@ class Completion:
|
|||||||
def completions(self, path):
|
def completions(self, path):
|
||||||
completion_parts = helpers.get_completion_parts(path)
|
completion_parts = helpers.get_completion_parts(path)
|
||||||
|
|
||||||
user_stmt = self._parser.user_stmt_with_whitespace()
|
completion_names = self._get_context_completions(completion_parts)
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
completions = filter_names(self._evaluator, completion_names,
|
completions = filter_names(self._evaluator, completion_names,
|
||||||
completion_parts.name)
|
completion_parts.name)
|
||||||
@@ -80,7 +74,7 @@ class Completion:
|
|||||||
x.name.startswith('_'),
|
x.name.startswith('_'),
|
||||||
x.name.lower()))
|
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
|
Analyzes the context that a completion is made in and decides what to
|
||||||
return.
|
return.
|
||||||
@@ -147,11 +141,17 @@ class Completion:
|
|||||||
# No completions for ``with x as foo`` and ``import x as foo``.
|
# No completions for ``with x as foo`` and ``import x as foo``.
|
||||||
# Also true for defining names as a class or function.
|
# Also true for defining names as a class or function.
|
||||||
return []
|
return []
|
||||||
elif symbol_names[-1] == 'trailer' and '(' != nodes[-1]:
|
elif symbol_names[-1] == 'trailer' and nodes[-1] == '.':
|
||||||
completion_names += self._trailer_completions(completion_parts)
|
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:
|
else:
|
||||||
completion_names += self._global_completions()
|
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
|
return completion_names
|
||||||
|
|
||||||
def _get_keyword_completion_names(self, keywords_):
|
def _get_keyword_completion_names(self, keywords_):
|
||||||
@@ -177,11 +177,8 @@ class Completion:
|
|||||||
)
|
)
|
||||||
return completion_names
|
return completion_names
|
||||||
|
|
||||||
def _trailer_completions(self, completion_parts):
|
def _trailer_completions(self, atom_expr):
|
||||||
scopes = list(inference.type_inference(
|
scopes = self._evaluator.eval_element(atom_expr)
|
||||||
self._evaluator, self._parser,
|
|
||||||
self._pos, completion_parts.path
|
|
||||||
))
|
|
||||||
completion_names = []
|
completion_names = []
|
||||||
debug.dbg('possible completion scopes: %s', scopes)
|
debug.dbg('possible completion scopes: %s', scopes)
|
||||||
for s in scopes:
|
for s in scopes:
|
||||||
|
|||||||
@@ -2,26 +2,10 @@
|
|||||||
This module has helpers for doing type inference on strings. It is needed,
|
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.
|
because we still want to infer types where the syntax is invalid.
|
||||||
"""
|
"""
|
||||||
from jedi import debug
|
|
||||||
from jedi.parser import Parser, ParseError
|
from jedi.parser import Parser, ParseError
|
||||||
from jedi.evaluate.cache import memoize_default
|
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)
|
@memoize_default(evaluator_is_first_arg=True)
|
||||||
def get_under_cursor_stmt(evaluator, parser, cursor_txt, start_pos):
|
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
|
# different trailers: `( x )`, `[ x ]` and `.x`. In the first two examples
|
||||||
# we should not match anything more than x.
|
# 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 != 'trailer' or leaf not in (trailer.children[0], trailer.children[-1]):
|
||||||
|
if trailer.type == 'atom':
|
||||||
|
return trailer
|
||||||
return leaf
|
return leaf
|
||||||
|
|
||||||
power = trailer.parent
|
power = trailer.parent
|
||||||
|
|||||||
@@ -20,3 +20,12 @@ a(some_args)
|
|||||||
|
|
||||||
#? 13 []
|
#? 13 []
|
||||||
a(some_kwargs)
|
a(some_kwargs)
|
||||||
|
|
||||||
|
def multiple(foo, bar):
|
||||||
|
pass
|
||||||
|
|
||||||
|
#? 17 ['bar']
|
||||||
|
multiple(foo, bar)
|
||||||
|
|
||||||
|
#? ['bar']
|
||||||
|
multiple(foo, bar
|
||||||
|
|||||||
Reference in New Issue
Block a user