forked from VimPlug/jedi
Fix __call__.
This commit is contained in:
@@ -68,13 +68,14 @@ def get_user_scope(module, position):
|
|||||||
|
|
||||||
|
|
||||||
class Completion:
|
class Completion:
|
||||||
def __init__(self, evaluator, module, code_lines, position, call_signatures_method):
|
def __init__(self, evaluator, module_node, code_lines, position, call_signatures_method):
|
||||||
self._evaluator = evaluator
|
self._evaluator = evaluator
|
||||||
self._module = evaluator.wrap(module, parent_context=None)
|
self._module_node = module_node
|
||||||
|
self._module = evaluator.wrap(module_node, parent_context=None)
|
||||||
self._code_lines = code_lines
|
self._code_lines = code_lines
|
||||||
|
|
||||||
# The first step of completions is to get the name
|
# The first step of completions is to get the name
|
||||||
self._like_name = helpers.get_on_completion_name(module, code_lines, position)
|
self._like_name = helpers.get_on_completion_name(module_node, code_lines, position)
|
||||||
# The actual cursor position is not what we need to calculate
|
# The actual cursor position is not what we need to calculate
|
||||||
# everything. We want the start of the name we're on.
|
# everything. We want the start of the name we're on.
|
||||||
self._position = position[0], position[1] - len(self._like_name)
|
self._position = position[0], position[1] - len(self._like_name)
|
||||||
@@ -109,7 +110,7 @@ class Completion:
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
self.stack = helpers.get_stack_at_position(
|
self.stack = helpers.get_stack_at_position(
|
||||||
grammar, self._code_lines, self._module, self._position
|
grammar, self._code_lines, self._module_node, self._position
|
||||||
)
|
)
|
||||||
except helpers.OnErrorLeaf as e:
|
except helpers.OnErrorLeaf as e:
|
||||||
self.stack = None
|
self.stack = None
|
||||||
@@ -153,7 +154,7 @@ class Completion:
|
|||||||
# Also true for defining names as a class or function.
|
# Also true for defining names as a class or function.
|
||||||
return list(self._get_class_context_completions(is_function=True))
|
return list(self._get_class_context_completions(is_function=True))
|
||||||
elif symbol_names[-1] == 'trailer' and nodes[-1] == '.':
|
elif symbol_names[-1] == 'trailer' and nodes[-1] == '.':
|
||||||
dot = self._module.get_leaf_for_position(self._position)
|
dot = self._module_node.get_leaf_for_position(self._position)
|
||||||
atom_expr = call_of_leaf(dot.get_previous_leaf())
|
atom_expr = call_of_leaf(dot.get_previous_leaf())
|
||||||
completion_names += self._trailer_completions(atom_expr)
|
completion_names += self._trailer_completions(atom_expr)
|
||||||
else:
|
else:
|
||||||
@@ -171,7 +172,7 @@ class Completion:
|
|||||||
yield keywords.keyword(self._evaluator, k).name
|
yield keywords.keyword(self._evaluator, k).name
|
||||||
|
|
||||||
def _global_completions(self):
|
def _global_completions(self):
|
||||||
scope = get_user_scope(self._module, self._position)
|
scope = get_user_scope(self._module_node, self._position)
|
||||||
if not scope.is_scope(): # Might be a flow (if/while/etc).
|
if not scope.is_scope(): # Might be a flow (if/while/etc).
|
||||||
scope = scope.get_parent_scope()
|
scope = scope.get_parent_scope()
|
||||||
scope = self._evaluator.create_context(scope)
|
scope = self._evaluator.create_context(scope)
|
||||||
@@ -188,7 +189,7 @@ class Completion:
|
|||||||
return completion_names
|
return completion_names
|
||||||
|
|
||||||
def _trailer_completions(self, atom_expr):
|
def _trailer_completions(self, atom_expr):
|
||||||
user_scope = get_user_scope(self._module, self._position)
|
user_scope = get_user_scope(self._module_node, self._position)
|
||||||
contexts = self._evaluator.eval_element(self._evaluator.create_context(atom_expr), atom_expr)
|
contexts = self._evaluator.eval_element(self._evaluator.create_context(atom_expr), atom_expr)
|
||||||
completion_names = []
|
completion_names = []
|
||||||
debug.dbg('trailer completion contexts: %s', contexts)
|
debug.dbg('trailer completion contexts: %s', contexts)
|
||||||
@@ -222,7 +223,7 @@ class Completion:
|
|||||||
Autocomplete inherited methods when overriding in child class.
|
Autocomplete inherited methods when overriding in child class.
|
||||||
"""
|
"""
|
||||||
return
|
return
|
||||||
leaf = self._module.get_leaf_for_position(self._position, include_prefixes=True)
|
leaf = self._module_node.get_leaf_for_position(self._position, include_prefixes=True)
|
||||||
cls = leaf.get_parent_until(tree.Class)
|
cls = leaf.get_parent_until(tree.Class)
|
||||||
if isinstance(cls, (tree.Class, tree.Function)):
|
if isinstance(cls, (tree.Class, tree.Function)):
|
||||||
# Complete the methods that are defined in the super classes.
|
# Complete the methods that are defined in the super classes.
|
||||||
|
|||||||
@@ -64,8 +64,8 @@ def _is_on_comment(leaf, position):
|
|||||||
return '#' in line
|
return '#' in line
|
||||||
|
|
||||||
|
|
||||||
def _get_code_for_stack(code_lines, module, position):
|
def _get_code_for_stack(code_lines, module_node, position):
|
||||||
leaf = module.get_leaf_for_position(position, include_prefixes=True)
|
leaf = module_node.get_leaf_for_position(position, include_prefixes=True)
|
||||||
# It might happen that we're on whitespace or on a comment. This means
|
# It might happen that we're on whitespace or on a comment. This means
|
||||||
# that we would not get the right leaf.
|
# that we would not get the right leaf.
|
||||||
if leaf.start_pos >= position:
|
if leaf.start_pos >= position:
|
||||||
@@ -111,7 +111,7 @@ def _get_code_for_stack(code_lines, module, position):
|
|||||||
return _get_code(code_lines, user_stmt.get_start_pos_of_prefix(), position)
|
return _get_code(code_lines, user_stmt.get_start_pos_of_prefix(), position)
|
||||||
|
|
||||||
|
|
||||||
def get_stack_at_position(grammar, code_lines, module, pos):
|
def get_stack_at_position(grammar, code_lines, module_node, pos):
|
||||||
"""
|
"""
|
||||||
Returns the possible node names (e.g. import_from, xor_test or yield_stmt).
|
Returns the possible node names (e.g. import_from, xor_test or yield_stmt).
|
||||||
"""
|
"""
|
||||||
@@ -126,7 +126,7 @@ def get_stack_at_position(grammar, code_lines, module, pos):
|
|||||||
else:
|
else:
|
||||||
yield token_
|
yield token_
|
||||||
|
|
||||||
code = _get_code_for_stack(code_lines, module, pos)
|
code = _get_code_for_stack(code_lines, module_node, pos)
|
||||||
# We use a word to tell Jedi when we have reached the start of the
|
# We use a word to tell Jedi when we have reached the start of the
|
||||||
# completion.
|
# completion.
|
||||||
# Use Z as a prefix because it's not part of a number suffix.
|
# Use Z as a prefix because it's not part of a number suffix.
|
||||||
@@ -196,7 +196,7 @@ def evaluate_goto_definition(evaluator, context, leaf):
|
|||||||
if leaf.type == 'name':
|
if leaf.type == 'name':
|
||||||
# In case of a name we can just use goto_definition which does all the
|
# In case of a name we can just use goto_definition which does all the
|
||||||
# magic itself.
|
# magic itself.
|
||||||
return evaluator.goto_definitions(leaf)
|
return evaluator.goto_definitions(context, leaf)
|
||||||
|
|
||||||
node = None
|
node = None
|
||||||
parent = leaf.parent
|
parent = leaf.parent
|
||||||
|
|||||||
@@ -71,6 +71,9 @@ class KeywordName(AbstractNameDefinition):
|
|||||||
self.string_name = name
|
self.string_name = name
|
||||||
self.parent_context = evaluator.BUILTINS
|
self.parent_context = evaluator.BUILTINS
|
||||||
|
|
||||||
|
def eval(self):
|
||||||
|
return set()
|
||||||
|
|
||||||
|
|
||||||
class Keyword(object):
|
class Keyword(object):
|
||||||
type = 'completion_keyword'
|
type = 'completion_keyword'
|
||||||
|
|||||||
@@ -416,6 +416,7 @@ class Evaluator(object):
|
|||||||
@debug.increase_indent
|
@debug.increase_indent
|
||||||
def execute(self, obj, arguments=None):
|
def execute(self, obj, arguments=None):
|
||||||
if not isinstance(arguments, param.Arguments):
|
if not isinstance(arguments, param.Arguments):
|
||||||
|
raise NotImplementedError
|
||||||
arguments = param.Arguments(self, arguments)
|
arguments = param.Arguments(self, arguments)
|
||||||
|
|
||||||
if self.is_analysis:
|
if self.is_analysis:
|
||||||
|
|||||||
@@ -55,9 +55,8 @@ class CompiledObject(Context):
|
|||||||
@CheckAttribute
|
@CheckAttribute
|
||||||
def py__call__(self, params):
|
def py__call__(self, params):
|
||||||
if inspect.isclass(self.obj):
|
if inspect.isclass(self.obj):
|
||||||
from jedi.evaluate.representation import Instance
|
from jedi.evaluate.instance import CompiledInstance
|
||||||
return set([self])
|
return set([CompiledInstance(self._evaluator, self.parent_context, self, params)])
|
||||||
return set([Instance(self._evaluator, self.parent_context, self, params)])
|
|
||||||
else:
|
else:
|
||||||
return set(self._execute_function(params))
|
return set(self._execute_function(params))
|
||||||
|
|
||||||
@@ -261,22 +260,22 @@ class CompiledObject(Context):
|
|||||||
|
|
||||||
|
|
||||||
class CompiledName(AbstractNameDefinition):
|
class CompiledName(AbstractNameDefinition):
|
||||||
def __init__(self, evaluator, compiled_obj, name):
|
def __init__(self, evaluator, parent_context, name):
|
||||||
self._evaluator = evaluator
|
self._evaluator = evaluator
|
||||||
self._compiled_obj = compiled_obj
|
self.parent_context = parent_context
|
||||||
self.string_name = name
|
self.string_name = name
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
try:
|
try:
|
||||||
name = self._compiled_obj.name # __name__ is not defined all the time
|
name = self.parent_context.name # __name__ is not defined all the time
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
name = None
|
name = None
|
||||||
return '<%s: (%s).%s>' % (type(self).__name__, name, self.string_name)
|
return '<%s: (%s).%s>' % (type(self).__name__, name, self.string_name)
|
||||||
|
|
||||||
@underscore_memoization
|
@underscore_memoization
|
||||||
def infer(self):
|
def infer(self):
|
||||||
module = self._compiled_obj.get_root_context()
|
module = self.parent_context.get_root_context()
|
||||||
return [_create_from_name(self._evaluator, module, self._compiled_obj, self.string_name)]
|
return [_create_from_name(self._evaluator, module, self.parent_context, self.string_name)]
|
||||||
|
|
||||||
|
|
||||||
class CompiledContextName(AbstractNameDefinition):
|
class CompiledContextName(AbstractNameDefinition):
|
||||||
|
|||||||
30
jedi/evaluate/context.py
Normal file
30
jedi/evaluate/context.py
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
class Context(object):
|
||||||
|
type = None # TODO remove
|
||||||
|
|
||||||
|
def __init__(self, evaluator, parent_context=None):
|
||||||
|
self._evaluator = evaluator
|
||||||
|
self.parent_context = parent_context
|
||||||
|
|
||||||
|
def get_parent_flow_context(self):
|
||||||
|
return self.parent_context
|
||||||
|
|
||||||
|
def get_root_context(self):
|
||||||
|
context = self
|
||||||
|
while True:
|
||||||
|
if context.parent_context is None:
|
||||||
|
return context
|
||||||
|
context = context.parent_context
|
||||||
|
|
||||||
|
def execute(self, arguments=None):
|
||||||
|
return self._evaluator.execute(self, arguments)
|
||||||
|
|
||||||
|
|
||||||
|
class TreeContext(Context):
|
||||||
|
def eval_node(self, node):
|
||||||
|
return self._evaluator.eval_element(self, node)
|
||||||
|
|
||||||
|
|
||||||
|
class FlowContext(TreeContext):
|
||||||
|
def get_parent_flow_context(self):
|
||||||
|
if 1:
|
||||||
|
return self.parent_context
|
||||||
@@ -9,7 +9,7 @@ from jedi.evaluate import flow_analysis
|
|||||||
from jedi.common import to_list
|
from jedi.common import to_list
|
||||||
|
|
||||||
|
|
||||||
class AbstractNameDefinition(object):
|
class AbstractNameDefinition():
|
||||||
start_pos = None
|
start_pos = None
|
||||||
string_name = None
|
string_name = None
|
||||||
parent_context = None
|
parent_context = None
|
||||||
@@ -108,8 +108,8 @@ class AbstractUsedNamesFilter(AbstractFilter):
|
|||||||
return [TreeNameDefinition(self._context, name) for name in names]
|
return [TreeNameDefinition(self._context, name) for name in names]
|
||||||
|
|
||||||
def values(self):
|
def values(self):
|
||||||
return self._convert_to_names(name for name_list in self._used_names.values()
|
return self._convert_names(name for name_list in self._used_names.values()
|
||||||
for name in self._filter(name_list))
|
for name in self._filter(name_list))
|
||||||
|
|
||||||
|
|
||||||
class ParserTreeFilter(AbstractUsedNamesFilter):
|
class ParserTreeFilter(AbstractUsedNamesFilter):
|
||||||
@@ -150,6 +150,7 @@ class FunctionExecutionFilter(ParserTreeFilter):
|
|||||||
origin_scope
|
origin_scope
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@to_list
|
||||||
def _convert_names(self, names):
|
def _convert_names(self, names):
|
||||||
for name in names:
|
for name in names:
|
||||||
param = search_ancestor(name, 'param')
|
param = search_ancestor(name, 'param')
|
||||||
|
|||||||
@@ -442,7 +442,7 @@ def _eval_param(evaluator, context, param, scope):
|
|||||||
res_new.add(scope.instance)
|
res_new.add(scope.instance)
|
||||||
else:
|
else:
|
||||||
inst = er.Instance(evaluator, context.parent_context.parent_context, context.parent_context,
|
inst = er.Instance(evaluator, context.parent_context.parent_context, context.parent_context,
|
||||||
Arguments(evaluator, context, ()),
|
Arguments(evaluator, context),
|
||||||
is_generated=True)
|
is_generated=True)
|
||||||
res_new.add(inst)
|
res_new.add(inst)
|
||||||
return res_new
|
return res_new
|
||||||
|
|||||||
221
jedi/evaluate/instance.py
Normal file
221
jedi/evaluate/instance.py
Normal file
@@ -0,0 +1,221 @@
|
|||||||
|
from abc import abstractproperty
|
||||||
|
|
||||||
|
from jedi import debug
|
||||||
|
from jedi.evaluate import compiled
|
||||||
|
from jedi.evaluate.filters import ParserTreeFilter, ContextName
|
||||||
|
from jedi.evaluate.context import Context
|
||||||
|
|
||||||
|
|
||||||
|
class AbstractInstanceContext(Context):
|
||||||
|
"""
|
||||||
|
This class is used to evaluate instances.
|
||||||
|
"""
|
||||||
|
def __init__(self, evaluator, parent_context, class_context, var_args):
|
||||||
|
super(AbstractInstanceContext, self).__init__(evaluator, parent_context)
|
||||||
|
# Generated instances are classes that are just generated by self
|
||||||
|
# (No var_args) used.
|
||||||
|
self._class_context = class_context
|
||||||
|
self.var_args = var_args
|
||||||
|
|
||||||
|
#####
|
||||||
|
""""
|
||||||
|
if class_context.name.string_name in ['list', 'set'] \
|
||||||
|
and evaluator.BUILTINS == parent_context.get_root_context():
|
||||||
|
# compare the module path with the builtin name.
|
||||||
|
self.var_args = iterable.check_array_instances(evaluator, self)
|
||||||
|
elif not is_generated:
|
||||||
|
# Need to execute the __init__ function, because the dynamic param
|
||||||
|
# searching needs it.
|
||||||
|
try:
|
||||||
|
method = self.get_subscope_by_name('__init__')
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
self._init_execution = evaluator.execute(method, self.var_args)
|
||||||
|
"""
|
||||||
|
|
||||||
|
def is_class(self):
|
||||||
|
return False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def py__call__(self):
|
||||||
|
names = self._get_function_slot_names('__call__')
|
||||||
|
if not names:
|
||||||
|
# Means the Instance is not callable.
|
||||||
|
raise AttributeError
|
||||||
|
|
||||||
|
def execute(arguments):
|
||||||
|
contexts = set()
|
||||||
|
for name in names:
|
||||||
|
for context in name.infer():
|
||||||
|
context.execute(arguments)
|
||||||
|
return contexts
|
||||||
|
return execute
|
||||||
|
|
||||||
|
def py__class__(self):
|
||||||
|
return self.class_context
|
||||||
|
|
||||||
|
def py__bool__(self):
|
||||||
|
# Signalize that we don't know about the bool type.
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _get_function_slot_names(self, name):
|
||||||
|
# Python classes don't look at the dictionary of the instance when
|
||||||
|
# looking up `__call__`. This is something that has to do with Python's
|
||||||
|
# internal slot system (note: not __slots__, but C slots).
|
||||||
|
for filter in self.get_filters(include_self_names=False):
|
||||||
|
names = filter.get(name)
|
||||||
|
if names:
|
||||||
|
return names
|
||||||
|
return []
|
||||||
|
|
||||||
|
def execute_function_slot(self, name, *args):
|
||||||
|
raise NotImplementedError
|
||||||
|
method = self.get_subscope_by_name(name)
|
||||||
|
return self._evaluator.execute_evaluated(method, *args)
|
||||||
|
|
||||||
|
def get_descriptor_returns(self, obj):
|
||||||
|
""" Throws a KeyError if there's no method. """
|
||||||
|
raise NotImplementedError
|
||||||
|
# Arguments in __get__ descriptors are obj, class.
|
||||||
|
# `method` is the new parent of the array, don't know if that's good.
|
||||||
|
none_obj = compiled.create(self._evaluator, None)
|
||||||
|
args = [obj, obj.base] if isinstance(obj, Instance) else [none_obj, obj]
|
||||||
|
try:
|
||||||
|
return self.execute_subscope_by_name('__get__', *args)
|
||||||
|
except KeyError:
|
||||||
|
return set([self])
|
||||||
|
|
||||||
|
def get_filters(self, search_global=None, until_position=None,
|
||||||
|
origin_scope=None, include_self_names=True):
|
||||||
|
if include_self_names:
|
||||||
|
for cls in self._class_context.py__mro__():
|
||||||
|
if isinstance(cls, compiled.CompiledObject):
|
||||||
|
yield SelfNameFilter(self._evaluator, self, cls, origin_scope)
|
||||||
|
else:
|
||||||
|
yield SelfNameFilter(self._evaluator, self, cls.base, origin_scope)
|
||||||
|
|
||||||
|
for cls in self._class_context.py__mro__():
|
||||||
|
if isinstance(cls, compiled.CompiledObject):
|
||||||
|
yield CompiledInstanceClassFilter(self._evaluator, self, cls)
|
||||||
|
else:
|
||||||
|
yield InstanceClassFilter(self._evaluator, self, cls.base, origin_scope)
|
||||||
|
|
||||||
|
def py__getitem__(self, index):
|
||||||
|
try:
|
||||||
|
method = self.get_subscope_by_name('__getitem__')
|
||||||
|
except KeyError:
|
||||||
|
debug.warning('No __getitem__, cannot access the array.')
|
||||||
|
return set()
|
||||||
|
else:
|
||||||
|
index_obj = compiled.create(self._evaluator, index)
|
||||||
|
return self._evaluator.execute_evaluated(method, index_obj)
|
||||||
|
|
||||||
|
def py__iter__(self):
|
||||||
|
try:
|
||||||
|
method = self.get_subscope_by_name('__iter__')
|
||||||
|
except KeyError:
|
||||||
|
debug.warning('No __iter__ on %s.' % self)
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
iters = self._evaluator.execute(method)
|
||||||
|
for generator in iters:
|
||||||
|
if isinstance(generator, Instance):
|
||||||
|
# `__next__` logic.
|
||||||
|
name = '__next__' if is_py3 else 'next'
|
||||||
|
try:
|
||||||
|
yield generator.execute_subscope_by_name(name)
|
||||||
|
except KeyError:
|
||||||
|
debug.warning('Instance has no __next__ function in %s.', generator)
|
||||||
|
else:
|
||||||
|
for typ in generator.py__iter__():
|
||||||
|
yield typ
|
||||||
|
|
||||||
|
@abstractproperty
|
||||||
|
def name(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "<%s of %s(%s)>" % (type(self).__name__, self._class_context,
|
||||||
|
self.var_args)
|
||||||
|
|
||||||
|
|
||||||
|
class CompiledInstance(AbstractInstanceContext):
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
return compiled.CompiledContextName(self, self._class_context.name.string_name)
|
||||||
|
|
||||||
|
|
||||||
|
class TreeInstance(AbstractInstanceContext):
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
return ContextName(self, self._class_context.name)
|
||||||
|
|
||||||
|
|
||||||
|
class CompiledInstanceClassFilter(compiled.CompiledObjectFilter):
|
||||||
|
def __init__(self, evaluator, instance, compiled_object):
|
||||||
|
super(CompiledInstanceClassFilter, self).__init__(
|
||||||
|
evaluator,
|
||||||
|
compiled_object,
|
||||||
|
is_instance=True,
|
||||||
|
)
|
||||||
|
self._instance = instance
|
||||||
|
|
||||||
|
def _filter(self, names):
|
||||||
|
names = super(CompiledInstanceClassFilter, self)._filter(names)
|
||||||
|
return [get_instance_el(self._evaluator, self._instance, name, True)
|
||||||
|
for name in names]
|
||||||
|
|
||||||
|
|
||||||
|
class InstanceClassFilter(ParserTreeFilter):
|
||||||
|
def __init__(self, evaluator, context, parser_scope, origin_scope):
|
||||||
|
super(InstanceClassFilter, self).__init__(
|
||||||
|
evaluator=evaluator,
|
||||||
|
context=context,
|
||||||
|
parser_scope=parser_scope,
|
||||||
|
origin_scope=origin_scope
|
||||||
|
)
|
||||||
|
|
||||||
|
def _equals_origin_scope(self):
|
||||||
|
node = self._origin_scope
|
||||||
|
while node is not None:
|
||||||
|
if node == self._parser_scope or node == self._context:
|
||||||
|
return True
|
||||||
|
node = node.get_parent_scope()
|
||||||
|
return False
|
||||||
|
|
||||||
|
def _access_possible(self, name):
|
||||||
|
return not name.value.startswith('__') or name.value.endswith('__') \
|
||||||
|
or self._equals_origin_scope()
|
||||||
|
|
||||||
|
def _filter(self, names):
|
||||||
|
names = super(InstanceClassFilter, self)._filter(names)
|
||||||
|
return [get_instance_el(self._evaluator, self._context, name, True)
|
||||||
|
for name in names if self._access_possible(name)]
|
||||||
|
|
||||||
|
def _check_flows(self, names):
|
||||||
|
return names
|
||||||
|
|
||||||
|
|
||||||
|
class SelfNameFilter(InstanceClassFilter):
|
||||||
|
def _filter(self, names):
|
||||||
|
names = self._filter_self_names(names)
|
||||||
|
if isinstance(self._parser_scope, compiled.CompiledObject):
|
||||||
|
# This would be for builtin skeletons, which are not yet supported.
|
||||||
|
return []
|
||||||
|
start, end = self._parser_scope.start_pos, self._parser_scope.end_pos
|
||||||
|
return [n for n in names if start < n.start_pos < end]
|
||||||
|
|
||||||
|
def _filter_self_names(self, names):
|
||||||
|
for name in names:
|
||||||
|
trailer = name.parent
|
||||||
|
if tree.is_node(trailer, 'trailer') \
|
||||||
|
and len(trailer.children) == 2 \
|
||||||
|
and trailer.children[0] == '.':
|
||||||
|
if name.is_definition() and self._access_possible(name):
|
||||||
|
init_execution = self._context._get_init_execution()
|
||||||
|
# Hopefully we can somehow change this.
|
||||||
|
if init_execution is not None and \
|
||||||
|
init_execution.start_pos < name.start_pos < init_execution.end_pos:
|
||||||
|
name = init_execution.name_for_position(name.start_pos)
|
||||||
|
yield get_instance_el(self._evaluator, self._context, name)
|
||||||
@@ -680,7 +680,7 @@ def _check_array_additions(evaluator, compare_array, module, is_list):
|
|||||||
return set()
|
return set()
|
||||||
|
|
||||||
def check_additions(arglist, add_name):
|
def check_additions(arglist, add_name):
|
||||||
params = list(param.Arguments(evaluator, arglist).unpack())
|
params = list(param.Arguments(evaluator, context, arglist).unpack())
|
||||||
result = set()
|
result = set()
|
||||||
if add_name in ['insert']:
|
if add_name in ['insert']:
|
||||||
params = params[1:]
|
params = params[1:]
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ def try_iter_content(types, depth=0):
|
|||||||
|
|
||||||
|
|
||||||
class Arguments(tree.Base):
|
class Arguments(tree.Base):
|
||||||
def __init__(self, evaluator, context, argument_node, trailer):
|
def __init__(self, evaluator, context, argument_node, trailer=None):
|
||||||
"""
|
"""
|
||||||
The argument_node is either a parser node or a list of evaluated
|
The argument_node is either a parser node or a list of evaluated
|
||||||
objects. Those evaluated objects may be lists of evaluated objects
|
objects. Those evaluated objects may be lists of evaluated objects
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ from jedi.evaluate import imports
|
|||||||
from jedi.evaluate.filters import ParserTreeFilter, FunctionExecutionFilter, \
|
from jedi.evaluate.filters import ParserTreeFilter, FunctionExecutionFilter, \
|
||||||
GlobalNameFilter, DictFilter, ContextName
|
GlobalNameFilter, DictFilter, ContextName
|
||||||
from jedi.evaluate.context import TreeContext
|
from jedi.evaluate.context import TreeContext
|
||||||
|
from jedi.evaluate.instance import TreeInstance
|
||||||
|
|
||||||
|
|
||||||
class Executed(TreeContext):
|
class Executed(TreeContext):
|
||||||
@@ -77,15 +78,15 @@ class Instance(use_metaclass(CachedMetaClass, Executed)):
|
|||||||
"""
|
"""
|
||||||
This class is used to evaluate instances.
|
This class is used to evaluate instances.
|
||||||
"""
|
"""
|
||||||
def __init__(self, evaluator, parent_context, base, var_args, is_generated=False):
|
def __init__(self, evaluator, parent_context, class_context, var_args, is_generated=False):
|
||||||
super(Instance, self).__init__(evaluator, parent_context, base, var_args)
|
super(Instance, self).__init__(evaluator, parent_context, var_args)
|
||||||
self.decorates = None
|
|
||||||
# Generated instances are classes that are just generated by self
|
# Generated instances are classes that are just generated by self
|
||||||
# (No var_args) used.
|
# (No var_args) used.
|
||||||
self.is_generated = is_generated
|
self.is_generated = is_generated
|
||||||
|
self._class_context = class_context
|
||||||
|
|
||||||
self._init_execution = None
|
self._init_execution = None
|
||||||
if base.name.string_name in ['list', 'set'] \
|
if class_context.name.string_name in ['list', 'set'] \
|
||||||
and evaluator.BUILTINS == parent_context.get_root_context():
|
and evaluator.BUILTINS == parent_context.get_root_context():
|
||||||
# compare the module path with the builtin name.
|
# compare the module path with the builtin name.
|
||||||
self.var_args = iterable.check_array_instances(evaluator, self)
|
self.var_args = iterable.check_array_instances(evaluator, self)
|
||||||
@@ -116,7 +117,7 @@ class Instance(use_metaclass(CachedMetaClass, Executed)):
|
|||||||
return actual
|
return actual
|
||||||
|
|
||||||
def py__class__(self):
|
def py__class__(self):
|
||||||
return self.base
|
return self.class_context
|
||||||
|
|
||||||
def py__bool__(self):
|
def py__bool__(self):
|
||||||
# Signalize that we don't know about the bool type.
|
# Signalize that we don't know about the bool type.
|
||||||
@@ -174,7 +175,7 @@ class Instance(use_metaclass(CachedMetaClass, Executed)):
|
|||||||
return names
|
return names
|
||||||
|
|
||||||
def get_subscope_by_name(self, name):
|
def get_subscope_by_name(self, name):
|
||||||
sub = self.base.get_subscope_by_name(name)
|
sub = self._class_context.get_subscope_by_name(name)
|
||||||
return get_instance_el(self._evaluator, self, sub, True)
|
return get_instance_el(self._evaluator, self, sub, True)
|
||||||
|
|
||||||
def execute_subscope_by_name(self, name, *args):
|
def execute_subscope_by_name(self, name, *args):
|
||||||
@@ -196,7 +197,7 @@ class Instance(use_metaclass(CachedMetaClass, Executed)):
|
|||||||
def names_dicts(self, search_global):
|
def names_dicts(self, search_global):
|
||||||
yield self._self_names_dict()
|
yield self._self_names_dict()
|
||||||
|
|
||||||
for s in self.base.py__mro__()[1:]:
|
for s in self._class_context.py__mro__()[1:]:
|
||||||
if not isinstance(s, compiled.CompiledObject):
|
if not isinstance(s, compiled.CompiledObject):
|
||||||
# Compiled objects don't have `self.` names.
|
# Compiled objects don't have `self.` names.
|
||||||
for inst in self._evaluator.execute(s):
|
for inst in self._evaluator.execute(s):
|
||||||
@@ -206,13 +207,13 @@ class Instance(use_metaclass(CachedMetaClass, Executed)):
|
|||||||
yield LazyInstanceDict(self._evaluator, self, names_dict)
|
yield LazyInstanceDict(self._evaluator, self, names_dict)
|
||||||
|
|
||||||
def get_filters(self, search_global, until_position=None, origin_scope=None):
|
def get_filters(self, search_global, until_position=None, origin_scope=None):
|
||||||
for cls in self.base.py__mro__():
|
for cls in self._class_context.py__mro__():
|
||||||
if isinstance(cls, compiled.CompiledObject):
|
if isinstance(cls, compiled.CompiledObject):
|
||||||
yield SelfNameFilter(self._evaluator, self, cls, origin_scope)
|
yield SelfNameFilter(self._evaluator, self, cls, origin_scope)
|
||||||
else:
|
else:
|
||||||
yield SelfNameFilter(self._evaluator, self, cls.base, origin_scope)
|
yield SelfNameFilter(self._evaluator, self, cls.base, origin_scope)
|
||||||
|
|
||||||
for cls in self.base.py__mro__():
|
for cls in self._class_context.py__mro__():
|
||||||
if isinstance(cls, compiled.CompiledObject):
|
if isinstance(cls, compiled.CompiledObject):
|
||||||
yield CompiledInstanceClassFilter(self._evaluator, self, cls)
|
yield CompiledInstanceClassFilter(self._evaluator, self, cls)
|
||||||
else:
|
else:
|
||||||
@@ -251,83 +252,11 @@ class Instance(use_metaclass(CachedMetaClass, Executed)):
|
|||||||
@property
|
@property
|
||||||
@underscore_memoization
|
@underscore_memoization
|
||||||
def name(self):
|
def name(self):
|
||||||
return ContextName(self, self.base.name)
|
return ContextName(self, self._class_context.name.string_name)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
dec = ''
|
return "<%s of %s(%s)>" % (type(self).__name__, self._class_context,
|
||||||
if self.decorates is not None:
|
self.var_args)
|
||||||
dec = " decorates " + repr(self.decorates)
|
|
||||||
return "<%s of %s(%s)%s>" % (type(self).__name__, self.base,
|
|
||||||
self.var_args, dec)
|
|
||||||
|
|
||||||
|
|
||||||
class CompiledInstanceClassFilter(compiled.CompiledObjectFilter):
|
|
||||||
def __init__(self, evaluator, instance, compiled_object):
|
|
||||||
super(CompiledInstanceClassFilter, self).__init__(
|
|
||||||
evaluator,
|
|
||||||
compiled_object,
|
|
||||||
is_instance=True,
|
|
||||||
)
|
|
||||||
self._instance = instance
|
|
||||||
|
|
||||||
def _filter(self, names):
|
|
||||||
names = super(CompiledInstanceClassFilter, self)._filter(names)
|
|
||||||
return [get_instance_el(self._evaluator, self._instance, name, True)
|
|
||||||
for name in names]
|
|
||||||
|
|
||||||
|
|
||||||
class InstanceClassFilter(ParserTreeFilter):
|
|
||||||
def __init__(self, evaluator, context, parser_scope, origin_scope):
|
|
||||||
super(InstanceClassFilter, self).__init__(
|
|
||||||
evaluator=evaluator,
|
|
||||||
context=context,
|
|
||||||
parser_scope=parser_scope,
|
|
||||||
origin_scope=origin_scope
|
|
||||||
)
|
|
||||||
|
|
||||||
def _equals_origin_scope(self):
|
|
||||||
node = self._origin_scope
|
|
||||||
while node is not None:
|
|
||||||
if node == self._parser_scope or node == self._context:
|
|
||||||
return True
|
|
||||||
node = node.get_parent_scope()
|
|
||||||
return False
|
|
||||||
|
|
||||||
def _access_possible(self, name):
|
|
||||||
return not name.value.startswith('__') or name.value.endswith('__') \
|
|
||||||
or self._equals_origin_scope()
|
|
||||||
|
|
||||||
def _filter(self, names):
|
|
||||||
names = super(InstanceClassFilter, self)._filter(names)
|
|
||||||
return [get_instance_el(self._evaluator, self._context, name, True)
|
|
||||||
for name in names if self._access_possible(name)]
|
|
||||||
|
|
||||||
def _check_flows(self, names):
|
|
||||||
return names
|
|
||||||
|
|
||||||
|
|
||||||
class SelfNameFilter(InstanceClassFilter):
|
|
||||||
def _filter(self, names):
|
|
||||||
names = self._filter_self_names(names)
|
|
||||||
if isinstance(self._parser_scope, compiled.CompiledObject):
|
|
||||||
# This would be for builtin skeletons, which are not yet supported.
|
|
||||||
return []
|
|
||||||
start, end = self._parser_scope.start_pos, self._parser_scope.end_pos
|
|
||||||
return [n for n in names if start < n.start_pos < end]
|
|
||||||
|
|
||||||
def _filter_self_names(self, names):
|
|
||||||
for name in names:
|
|
||||||
trailer = name.parent
|
|
||||||
if tree.is_node(trailer, 'trailer') \
|
|
||||||
and len(trailer.children) == 2 \
|
|
||||||
and trailer.children[0] == '.':
|
|
||||||
if name.is_definition() and self._access_possible(name):
|
|
||||||
init_execution = self._context._get_init_execution()
|
|
||||||
# Hopefully we can somehow change this.
|
|
||||||
if init_execution is not None and \
|
|
||||||
init_execution.start_pos < name.start_pos < init_execution.end_pos:
|
|
||||||
name = init_execution.name_for_position(name.start_pos)
|
|
||||||
yield get_instance_el(self._evaluator, self._context, name)
|
|
||||||
|
|
||||||
|
|
||||||
class LazyInstanceDict(object):
|
class LazyInstanceDict(object):
|
||||||
@@ -535,7 +464,7 @@ class ClassContext(use_metaclass(CachedMetaClass, TreeContext, Wrapper)):
|
|||||||
return [compiled.create(self._evaluator, object)]
|
return [compiled.create(self._evaluator, object)]
|
||||||
|
|
||||||
def py__call__(self, params):
|
def py__call__(self, params):
|
||||||
return set([Instance(self._evaluator, self.parent_context, self, params)])
|
return set([TreeInstance(self._evaluator, self.parent_context, self, params)])
|
||||||
|
|
||||||
def py__class__(self):
|
def py__class__(self):
|
||||||
return compiled.create(self._evaluator, type)
|
return compiled.create(self._evaluator, type)
|
||||||
@@ -864,6 +793,7 @@ class ModuleContext(use_metaclass(CachedMetaClass, TreeContext, Wrapper)):
|
|||||||
self._evaluator = evaluator
|
self._evaluator = evaluator
|
||||||
self.base = self._module = module
|
self.base = self._module = module
|
||||||
self._parent_module = parent_module
|
self._parent_module = parent_module
|
||||||
|
self.path = None
|
||||||
|
|
||||||
def names_dicts(self, search_global):
|
def names_dicts(self, search_global):
|
||||||
yield self.base.names_dict
|
yield self.base.names_dict
|
||||||
|
|||||||
Reference in New Issue
Block a user