Fix super call goto for multiple inheritance, fixes #1311

This commit is contained in:
Dave Halter
2019-06-24 09:53:56 +02:00
parent ebdae87821
commit 265abe1d08
3 changed files with 45 additions and 11 deletions

View File

@@ -241,7 +241,7 @@ class _ContextWrapperBase(HelperContextMixin):
return cls(*args, **kwargs)
def __getattr__(self, name):
assert name != '_wrapped_context'
assert name != '_wrapped_context', 'Problem with _get_wrapped_context'
return getattr(self._wrapped_context, name)

View File

@@ -19,10 +19,9 @@ from jedi.evaluate.arguments import ValuesArguments, \
repack_with_argument_clinic, AbstractArguments, TreeArgumentsWrapper
from jedi.evaluate import analysis
from jedi.evaluate import compiled
from jedi.evaluate.context.instance import \
AbstractInstanceContext, BoundMethod, InstanceArguments
from jedi.evaluate.context.instance import BoundMethod, InstanceArguments
from jedi.evaluate.base_context import ContextualizedNode, \
NO_CONTEXTS, ContextSet, ContextWrapper
NO_CONTEXTS, ContextSet, ContextWrapper, LazyContextWrapper
from jedi.evaluate.context import ClassContext, ModuleContext, \
FunctionExecutionContext
from jedi.evaluate.context import iterable
@@ -230,20 +229,38 @@ def builtins_type(objects, bases, dicts):
return objects.py__class__()
class SuperInstance(AbstractInstanceContext):
class SuperInstance(LazyContextWrapper):
"""To be used like the object ``super`` returns."""
def __init__(self, evaluator, cls):
su = cls.py_mro()[1]
super().__init__(evaluator, su and su[0] or self)
def __init__(self, evaluator, instance):
self.evaluator = evaluator
self._instance = instance # Corresponds to super().__self__
def _get_bases(self):
return self._instance.py__class__().py__bases__()
def _get_wrapped_context(self):
objs = self._get_bases()[0].infer().execute_evaluated()
if not objs:
# This is just a fallback and will only be used, if it's not
# possible to find a class
return self._instance
return next(iter(objs))
def get_filters(self, search_global=False, until_position=None, origin_scope=None):
for b in self._get_bases():
for obj in b.infer().execute_evaluated():
for f in obj.get_filters():
yield f
@argument_clinic('[type[, obj]], /', want_context=True)
def builtins_super(types, objects, context):
# TODO make this able to detect multiple inheritance super
if isinstance(context, FunctionExecutionContext):
if isinstance(context.var_args, InstanceArguments):
su = context.var_args.instance.py__class__().py__bases__()
return su[0].infer().execute_evaluated()
instance = context.var_args.instance
# TODO if a class is given it doesn't have to be the direct super
# class, it can be an anecestor from long ago.
return ContextSet({SuperInstance(instance.evaluator, instance)})
return NO_CONTEXTS

View File

@@ -109,6 +109,23 @@ class X():
#! 3 []
X(foo=x)
# Multiple inheritance
class Foo:
def foo(self):
print("foo")
class Bar:
def bar(self):
print("bar")
class Baz(Foo, Bar):
def baz(self):
#! ['def foo']
super().foo
#! ['def bar']
super().bar
#! ['instance Foo']
super()
# -----------------
# imports
# -----------------