From 942dd8a67c8ecda23dc1ea4298aa6f5ce0f92b3a Mon Sep 17 00:00:00 2001 From: Mikhael Bogdanov Date: Thu, 5 Apr 2018 16:44:03 +0200 Subject: [PATCH] Properly calculate this for super call --- .../InterfaceDefaultMethodCallChecker.kt | 20 +++- .../diagnostics/tests/j+k/defaultMethods.kt | 100 +++++++++++++++++- .../diagnostics/tests/j+k/defaultMethods.txt | 9 ++ .../tests/j+k/defaultMethods_warning.kt | 96 +++++++++++++++++ .../tests/j+k/defaultMethods_warning.txt | 9 ++ 5 files changed, 227 insertions(+), 7 deletions(-) diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/InterfaceDefaultMethodCallChecker.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/InterfaceDefaultMethodCallChecker.kt index 335b8af4b53..74904f9a00b 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/InterfaceDefaultMethodCallChecker.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/InterfaceDefaultMethodCallChecker.kt @@ -19,10 +19,10 @@ package org.jetbrains.kotlin.resolve.jvm.checkers import com.intellij.psi.PsiElement import org.jetbrains.kotlin.config.JvmTarget import org.jetbrains.kotlin.config.LanguageFeature -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.ClassifierDescriptor -import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor +import org.jetbrains.kotlin.psi.KtSuperExpression +import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils.* import org.jetbrains.kotlin.resolve.calls.callResolverUtil.getSuperCallExpression @@ -46,7 +46,7 @@ class InterfaceDefaultMethodCallChecker(val jvmTarget: JvmTarget) : CallChecker context.trace.report(diagnostic.on(reportOn)) } - if (getSuperCallExpression(resolvedCall.call) == null) return + val superCallExpression = getSuperCallExpression(resolvedCall.call) ?: return if (!isInterface(descriptor.original.containingDeclaration)) return @@ -54,7 +54,7 @@ class InterfaceDefaultMethodCallChecker(val jvmTarget: JvmTarget) : CallChecker val realDescriptorOwner = realDescriptor.containingDeclaration as? ClassDescriptor ?: return if (isInterface(realDescriptorOwner) && realDescriptor is JavaCallableMemberDescriptor) { - val classifier = DescriptorUtils.getParentOfType(context.scope.ownerDescriptor, ClassifierDescriptor::class.java) + val classifier = getSuperCallLabelTarget(context.trace.bindingContext, superCallExpression) //is java interface default method called from trait if (classifier != null && DescriptorUtils.isInterface(classifier)) { context.trace.report(INTERFACE_CANT_CALL_DEFAULT_METHOD_VIA_SUPER.on(reportOn)) @@ -68,4 +68,14 @@ class InterfaceDefaultMethodCallChecker(val jvmTarget: JvmTarget) : CallChecker private fun isDefaultCallsProhibited(context: CallCheckerContext) = context.languageVersionSettings.supportsFeature(LanguageFeature.DefaultMethodsCallFromJava6TargetError) + + private fun getSuperCallLabelTarget( + bindingContext: BindingContext, + expression: KtSuperExpression + ): ClassDescriptor? { + val thisTypeForSuperCall = bindingContext.get(BindingContext.THIS_TYPE_FOR_SUPER_EXPRESSION, expression) ?: return null + val descriptor = thisTypeForSuperCall.constructor.declarationDescriptor + return descriptor as? ClassDescriptor + } + } diff --git a/compiler/testData/diagnostics/tests/j+k/defaultMethods.kt b/compiler/testData/diagnostics/tests/j+k/defaultMethods.kt index b229c78c8b3..8d68fcbaea6 100644 --- a/compiler/testData/diagnostics/tests/j+k/defaultMethods.kt +++ b/compiler/testData/diagnostics/tests/j+k/defaultMethods.kt @@ -21,8 +21,26 @@ interface KotlinInterface : JavaInterface { fun fooo() { testStatic() super.test() + + object { + fun run () { + super@KotlinInterface.test() + } + } } + val propertyy: String + get() { + super.test() + + object { + fun run () { + super@KotlinInterface.test() + } + } + return "" + } + override fun testOverride(): String { return "OK"; } @@ -32,15 +50,52 @@ interface KotlinInterfaceInderectInheritance : KotlinInterface { fun foooo() { testStatic() super.test() + + object { + fun run () { + super@KotlinInterfaceInderectInheritance.test() + } + } } + + val propertyyy: String + get() { + super.test() + + object { + fun run () { + super@KotlinInterfaceInderectInheritance.test() + } + } + return "" + } } open class KotlinClass : JavaInterface { - fun foo(){ + fun foo() { testStatic() super.test() super.testOverride() + + object { + fun run () { + super@KotlinClass.test() + } + } } + + val property: String + get() { + super.test() + super.testOverride() + + object { + fun run () { + super@KotlinClass.test() + } + } + return "" + } } class KotlinClassInderectInheritance : KotlinClass() { @@ -48,23 +103,64 @@ class KotlinClassInderectInheritance : KotlinClass() { testStatic() super.test() super.testOverride() + + object { + fun run () { + super@KotlinClassInderectInheritance.test() + } + } } + + val property2: String + get() { + super.test() + super.testOverride() + + object { + fun run () { + super@KotlinClassInderectInheritance.test() + } + } + return "" + } } class KotlinClassInderectInheritance2 : KotlinInterfaceInderectInheritance { - fun foo(){ + fun foo() { testStatic() super.test() super.testOverride() + + object { + fun run () { + super@KotlinClassInderectInheritance2.test() + } + } } + + val property: String + get() { + super.test() + super.testOverride() + + object { + fun run () { + super@KotlinClassInderectInheritance2.test() + } + } + return "" + } } fun test() { JavaInterface.testStatic() KotlinClass().foo() + KotlinClass().property KotlinClassInderectInheritance2().foo() + KotlinClassInderectInheritance2().property KotlinClass().test() + KotlinClass().property KotlinClass().testOverride() KotlinClassInderectInheritance().testOverride() } diff --git a/compiler/testData/diagnostics/tests/j+k/defaultMethods.txt b/compiler/testData/diagnostics/tests/j+k/defaultMethods.txt index e46b079c6e2..fd4c9917a62 100644 --- a/compiler/testData/diagnostics/tests/j+k/defaultMethods.txt +++ b/compiler/testData/diagnostics/tests/j+k/defaultMethods.txt @@ -15,6 +15,7 @@ public interface JavaInterface { public open class KotlinClass : JavaInterface { public constructor KotlinClass() + public final val property: kotlin.String public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public final fun foo(): kotlin.Unit public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int @@ -25,6 +26,8 @@ public open class KotlinClass : JavaInterface { public final class KotlinClassInderectInheritance : KotlinClass { public constructor KotlinClassInderectInheritance() + public final override /*1*/ /*fake_override*/ val property: kotlin.String + public final val property2: kotlin.String public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public final override /*1*/ /*fake_override*/ fun foo(): kotlin.Unit public final fun foo2(): kotlin.Unit @@ -36,6 +39,9 @@ public final class KotlinClassInderectInheritance : KotlinClass { public final class KotlinClassInderectInheritance2 : KotlinInterfaceInderectInheritance { public constructor KotlinClassInderectInheritance2() + public final val property: kotlin.String + public open override /*1*/ /*fake_override*/ val propertyy: kotlin.String + public open override /*1*/ /*fake_override*/ val propertyyy: kotlin.String public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public final fun foo(): kotlin.Unit public open override /*1*/ /*fake_override*/ fun fooo(): kotlin.Unit @@ -47,6 +53,7 @@ public final class KotlinClassInderectInheritance2 : KotlinInterfaceInderectInhe } public interface KotlinInterface : JavaInterface { + public open val propertyy: kotlin.String public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open fun fooo(): kotlin.Unit public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int @@ -56,6 +63,8 @@ public interface KotlinInterface : JavaInterface { } public interface KotlinInterfaceInderectInheritance : KotlinInterface { + public open override /*1*/ /*fake_override*/ val propertyy: kotlin.String + public open val propertyyy: kotlin.String public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun fooo(): kotlin.Unit public open fun foooo(): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/j+k/defaultMethods_warning.kt b/compiler/testData/diagnostics/tests/j+k/defaultMethods_warning.kt index e9b718ae71c..e5e04215bfa 100644 --- a/compiler/testData/diagnostics/tests/j+k/defaultMethods_warning.kt +++ b/compiler/testData/diagnostics/tests/j+k/defaultMethods_warning.kt @@ -23,8 +23,26 @@ interface KotlinInterface : JavaInterface { fun fooo() { testStatic() super.test() + + object { + fun run () { + super@KotlinInterface.test() + } + } } + val propertyy: String + get() { + super.test() + + object { + fun run () { + super@KotlinInterface.test() + } + } + return "" + } + override fun testOverride(): String { return "OK"; } @@ -34,7 +52,25 @@ interface KotlinInterfaceInderectInheritance : KotlinInterface { fun foooo() { testStatic() super.test() + + object { + fun run () { + super@KotlinInterfaceInderectInheritance.test() + } + } } + + val propertyyy: String + get() { + super.test() + + object { + fun run () { + super@KotlinInterfaceInderectInheritance.test() + } + } + return "" + } } open class KotlinClass : JavaInterface { @@ -42,7 +78,26 @@ open class KotlinClass : JavaInterface { testStatic() super.test() super.testOverride() + + object { + fun run () { + super@KotlinClass.test() + } + } } + + val property: String + get() { + super.test() + super.testOverride() + + object { + fun run () { + super@KotlinClass.test() + } + } + return "" + } } class KotlinClassInderectInheritance : KotlinClass() { @@ -50,7 +105,26 @@ class KotlinClassInderectInheritance : KotlinClass() { testStatic() super.test() super.testOverride() + + object { + fun run () { + super@KotlinClassInderectInheritance.test() + } + } } + + val property2: String + get() { + super.test() + super.testOverride() + + object { + fun run () { + super@KotlinClassInderectInheritance.test() + } + } + return "" + } } class KotlinClassInderectInheritance2 : KotlinInterfaceInderectInheritance { @@ -58,15 +132,37 @@ class KotlinClassInderectInheritance2 : KotlinInterfaceInderectInheritance { testStatic() super.test() super.testOverride() + + object { + fun run () { + super@KotlinClassInderectInheritance2.test() + } + } } + + val property: String + get() { + super.test() + super.testOverride() + + object { + fun run () { + super@KotlinClassInderectInheritance2.test() + } + } + return "" + } } fun test() { JavaInterface.testStatic() KotlinClass().foo() + KotlinClass().property KotlinClassInderectInheritance2().foo() + KotlinClassInderectInheritance2().property KotlinClass().test() + KotlinClass().property KotlinClass().testOverride() KotlinClassInderectInheritance().testOverride() } diff --git a/compiler/testData/diagnostics/tests/j+k/defaultMethods_warning.txt b/compiler/testData/diagnostics/tests/j+k/defaultMethods_warning.txt index e46b079c6e2..fd4c9917a62 100644 --- a/compiler/testData/diagnostics/tests/j+k/defaultMethods_warning.txt +++ b/compiler/testData/diagnostics/tests/j+k/defaultMethods_warning.txt @@ -15,6 +15,7 @@ public interface JavaInterface { public open class KotlinClass : JavaInterface { public constructor KotlinClass() + public final val property: kotlin.String public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public final fun foo(): kotlin.Unit public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int @@ -25,6 +26,8 @@ public open class KotlinClass : JavaInterface { public final class KotlinClassInderectInheritance : KotlinClass { public constructor KotlinClassInderectInheritance() + public final override /*1*/ /*fake_override*/ val property: kotlin.String + public final val property2: kotlin.String public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public final override /*1*/ /*fake_override*/ fun foo(): kotlin.Unit public final fun foo2(): kotlin.Unit @@ -36,6 +39,9 @@ public final class KotlinClassInderectInheritance : KotlinClass { public final class KotlinClassInderectInheritance2 : KotlinInterfaceInderectInheritance { public constructor KotlinClassInderectInheritance2() + public final val property: kotlin.String + public open override /*1*/ /*fake_override*/ val propertyy: kotlin.String + public open override /*1*/ /*fake_override*/ val propertyyy: kotlin.String public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public final fun foo(): kotlin.Unit public open override /*1*/ /*fake_override*/ fun fooo(): kotlin.Unit @@ -47,6 +53,7 @@ public final class KotlinClassInderectInheritance2 : KotlinInterfaceInderectInhe } public interface KotlinInterface : JavaInterface { + public open val propertyy: kotlin.String public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open fun fooo(): kotlin.Unit public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int @@ -56,6 +63,8 @@ public interface KotlinInterface : JavaInterface { } public interface KotlinInterfaceInderectInheritance : KotlinInterface { + public open override /*1*/ /*fake_override*/ val propertyy: kotlin.String + public open val propertyyy: kotlin.String public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun fooo(): kotlin.Unit public open fun foooo(): kotlin.Unit