1
0
forked from VimPlug/jedi

Super is now working. Still has the same flaws like the old implementation, but the tests are passing.

This commit is contained in:
Dave Halter
2014-10-28 16:22:59 +01:00
parent 500ac9b384
commit 4f2223ae7b
3 changed files with 21 additions and 15 deletions

View File

@@ -233,7 +233,7 @@ class Evaluator(object):
if trailer_op == '.': if trailer_op == '.':
new_types += self.find_types(typ, node) new_types += self.find_types(typ, node)
elif trailer_op == '(': elif trailer_op == '(':
new_types += self.execute(typ, node) new_types += self.execute(typ, node, trailer)
elif trailer_op == '[': elif trailer_op == '[':
try: try:
get = typ.get_index_types get = typ.get_index_types
@@ -245,8 +245,8 @@ class Evaluator(object):
return new_types return new_types
@debug.increase_indent @debug.increase_indent
def execute(self, obj, arguments=()): def execute(self, obj, arguments=(), trailer=None):
arguments = param.Arguments(self, arguments) arguments = param.Arguments(self, arguments, trailer)
if obj.isinstance(er.Function): if obj.isinstance(er.Function):
obj = obj.get_decorated_func() obj = obj.get_decorated_func()

View File

@@ -13,13 +13,14 @@ from jedi.evaluate import precedence
class Arguments(pr.Base): class Arguments(pr.Base):
def __init__(self, evaluator, argument_node): def __init__(self, evaluator, 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. objects.
""" """
self.argument_node = argument_node self.argument_node = argument_node
self._evaluator = evaluator self._evaluator = evaluator
self._trailer = trailer # Can be None, e.g. in a class definition.
def _split(self): def _split(self):
if isinstance(self.argument_node, (tuple, list)): if isinstance(self.argument_node, (tuple, list)):
@@ -110,10 +111,14 @@ class Arguments(pr.Base):
if not values and not optional: if not values and not optional:
# For the stdlib we always want values. If we don't get them, # For the stdlib we always want values. If we don't get them,
# that's ok, maybe something is too hard to resolve, however, # that's ok, maybe something is too hard to resolve, however,
# we will not proceed with the evaluation of that function. # we will not proceed with the evaluation of that function.
raise ValueError raise ValueError
yield values yield values
def scope(self):
# Returns the scope in which the arguments are used.
return (self._trailer or self.argument_node).get_parent_until(pr.IsScope)
def eval_args(self): def eval_args(self):
return [self._evaluator.eval_element(el) for stars, el in self._split()] return [self._evaluator.eval_element(el) for stars, el in self._split()]

View File

@@ -56,7 +56,7 @@ def _follow_param(evaluator, params, index):
return [stmt] # just some arbitrary object return [stmt] # just some arbitrary object
def argument_clinic(string, want_obj=False): def argument_clinic(string, want_obj=False, want_scope=False):
""" """
Works like Argument Clinic (PEP 436), to validate function params. Works like Argument Clinic (PEP 436), to validate function params.
""" """
@@ -83,10 +83,12 @@ def argument_clinic(string, want_obj=False):
except ValueError: except ValueError:
return [] return []
else: else:
kwargs = {}
if want_scope:
kwargs['scope'] = arguments.scope()
if want_obj: if want_obj:
return func(evaluator, obj, *lst) kwargs['obj'] = obj
else: return func(evaluator, *lst, **kwargs)
return func(evaluator, *lst)
return wrapper return wrapper
return f return f
@@ -127,15 +129,14 @@ class SuperInstance(er.Instance):
super().__init__(evaluator, su and su[0] or self) super().__init__(evaluator, su and su[0] or self)
@argument_clinic('[type[, obj]], /', want_obj=True) @argument_clinic('[type[, obj]], /', want_scope=True)
def builtins_super(evaluator, obj, types, objects): def builtins_super(evaluator, types, objects, scope):
# TODO make this able to detect multiple inheritance super # TODO make this able to detect multiple inheritance super
accept = (pr.Function, er.FunctionExecution) accept = (pr.Function, er.FunctionExecution)
func = obj.get_parent_until(accept) if scope.isinstance(*accept):
if func.isinstance(*accept):
wanted = (pr.Class, er.Instance) wanted = (pr.Class, er.Instance)
cls = func.get_parent_until(accept + wanted, cls = scope.get_parent_until(accept + wanted,
include_current=False) include_current=False)
if isinstance(cls, wanted): if isinstance(cls, wanted):
if isinstance(cls, pr.Class): if isinstance(cls, pr.Class):
cls = er.Class(evaluator, cls) cls = er.Class(evaluator, cls)