From f713b03abceb6b3452275bcddcb17284a41236a3 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Thu, 11 Apr 2013 20:47:10 +0400 Subject: [PATCH] Fixed propagation for non-abstract methods inherited from traits. --- .../PropagationHeuristics.java | 25 +++++++++++++++++++ .../SignaturesPropagationData.java | 4 +-- .../SubclassFromTraitImplementation.txt | 18 +++++++++++++ .../Subclass.java | 8 ++++++ .../TraitAndImpl.kt | 10 ++++++++ .../loadKotlin/fun/PropagateDeepSubclass.kt | 14 +++++++++++ .../loadKotlin/fun/PropagateDeepSubclass.txt | 18 +++++++++++++ .../LoadCompiledKotlinTestGenerated.java | 5 ++++ .../jvm/compiler/LoadJavaTestGenerated.java | 13 +++++++++- ...esolveNamespaceComparingTestGenerated.java | 5 ++++ 10 files changed, 116 insertions(+), 4 deletions(-) create mode 100644 compiler/testData/loadJava/javaAgainstKotlin/signaturePropagation/SubclassFromTraitImplementation.txt create mode 100644 compiler/testData/loadJava/javaAgainstKotlin/signaturePropagation/SubclassFromTraitImplementation/Subclass.java create mode 100644 compiler/testData/loadJava/javaAgainstKotlin/signaturePropagation/SubclassFromTraitImplementation/TraitAndImpl.kt create mode 100644 compiler/testData/loadKotlin/fun/PropagateDeepSubclass.kt create mode 100644 compiler/testData/loadKotlin/fun/PropagateDeepSubclass.txt diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/PropagationHeuristics.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/PropagationHeuristics.java index 00cddedc32d..abe2a333b0d 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/PropagationHeuristics.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/PropagationHeuristics.java @@ -18,11 +18,16 @@ package org.jetbrains.jet.lang.resolve.java.kotlinSignature; import com.google.common.collect.Lists; import com.intellij.openapi.util.Condition; +import com.intellij.psi.HierarchicalMethodSignature; +import com.intellij.psi.PsiMethod; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor; import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor; import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; +import org.jetbrains.jet.lang.resolve.java.kt.DescriptorKindUtils; +import org.jetbrains.jet.lang.resolve.java.wrapper.PsiMethodWrapper; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetTypeImpl; @@ -114,6 +119,26 @@ class PropagationHeuristics { return null; } + @NotNull + static List getSuperMethods(@NotNull PsiMethod method) { + List superMethods = Lists.newArrayList(); + for (HierarchicalMethodSignature superSignature : method.getHierarchicalMethodSignature().getSuperSignatures()) { + PsiMethod superMethod = superSignature.getMethod(); + CallableMemberDescriptor.Kind kindFromFlags = + DescriptorKindUtils.flagsToKind(new PsiMethodWrapper(superMethod).getJetMethodAnnotation().kind()); + if (kindFromFlags == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { + // This is for the case when a Kotlin class inherits a non-abstract method from a trait: + // from Kotlin's point of view it is fake override, from Java's it is normal override. + // We replace this "fake override" method with original method from the trait. + superMethods.addAll(getSuperMethods(superMethod)); + } + else { + superMethods.add(superMethod); + } + } + return superMethods; + } + private PropagationHeuristics() { } } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/SignaturesPropagationData.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/SignaturesPropagationData.java index 9a77aa62d6a..27e2c3eec85 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/SignaturesPropagationData.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/SignaturesPropagationData.java @@ -209,9 +209,7 @@ public class SignaturesPropagationData { Multimap> superclassToFunctions = getSuperclassToFunctionsMultimap(method, trace.getBindingContext(), containingClass); - for (HierarchicalMethodSignature superSignature : method.getPsiMethod().getHierarchicalMethodSignature().getSuperSignatures()) { - PsiMethod superMethod = superSignature.getMethod(); - + for (PsiMethod superMethod : PropagationHeuristics.getSuperMethods(method.getPsiMethod())) { PsiClass psiClass = superMethod.getContainingClass(); assert psiClass != null; String classFqNameString = psiClass.getQualifiedName(); diff --git a/compiler/testData/loadJava/javaAgainstKotlin/signaturePropagation/SubclassFromTraitImplementation.txt b/compiler/testData/loadJava/javaAgainstKotlin/signaturePropagation/SubclassFromTraitImplementation.txt new file mode 100644 index 00000000000..97294682084 --- /dev/null +++ b/compiler/testData/loadJava/javaAgainstKotlin/signaturePropagation/SubclassFromTraitImplementation.txt @@ -0,0 +1,18 @@ +package test + +internal open class Impl : test.Trait { + public constructor Impl() + internal open override /*1*/ /*fake_override*/ fun bar() : jet.String + internal open override /*1*/ /*fake_override*/ fun foo() : jet.String +} + +public open class Subclass : test.Impl { + public constructor Subclass() + java.lang.Override() public open override /*1*/ fun bar() : jet.String + internal open override /*1*/ /*fake_override*/ fun foo() : jet.String +} + +internal trait Trait { + internal open fun bar() : jet.String + internal open fun foo() : jet.String +} diff --git a/compiler/testData/loadJava/javaAgainstKotlin/signaturePropagation/SubclassFromTraitImplementation/Subclass.java b/compiler/testData/loadJava/javaAgainstKotlin/signaturePropagation/SubclassFromTraitImplementation/Subclass.java new file mode 100644 index 00000000000..747a933d177 --- /dev/null +++ b/compiler/testData/loadJava/javaAgainstKotlin/signaturePropagation/SubclassFromTraitImplementation/Subclass.java @@ -0,0 +1,8 @@ +package test; + +public class Subclass extends Impl { + @Override + public String bar() { + return "bar bar"; + } +} \ No newline at end of file diff --git a/compiler/testData/loadJava/javaAgainstKotlin/signaturePropagation/SubclassFromTraitImplementation/TraitAndImpl.kt b/compiler/testData/loadJava/javaAgainstKotlin/signaturePropagation/SubclassFromTraitImplementation/TraitAndImpl.kt new file mode 100644 index 00000000000..8c22ca36e2e --- /dev/null +++ b/compiler/testData/loadJava/javaAgainstKotlin/signaturePropagation/SubclassFromTraitImplementation/TraitAndImpl.kt @@ -0,0 +1,10 @@ +package test + +trait Trait { + fun foo(): String = "foo" + + fun bar(): String = "bar" +} + +open class Impl : Trait { +} \ No newline at end of file diff --git a/compiler/testData/loadKotlin/fun/PropagateDeepSubclass.kt b/compiler/testData/loadKotlin/fun/PropagateDeepSubclass.kt new file mode 100644 index 00000000000..69cbb457ac8 --- /dev/null +++ b/compiler/testData/loadKotlin/fun/PropagateDeepSubclass.kt @@ -0,0 +1,14 @@ +package test + +trait A { + fun foo() {} + + fun bar() {} +} + +open class B : A { +} + +class C : B() { + override fun bar() {} +} \ No newline at end of file diff --git a/compiler/testData/loadKotlin/fun/PropagateDeepSubclass.txt b/compiler/testData/loadKotlin/fun/PropagateDeepSubclass.txt new file mode 100644 index 00000000000..d112a05650f --- /dev/null +++ b/compiler/testData/loadKotlin/fun/PropagateDeepSubclass.txt @@ -0,0 +1,18 @@ +package test + +internal trait A { + internal open fun bar() : jet.Unit + internal open fun foo() : jet.Unit +} + +internal open class B : test.A { + /*primary*/ public constructor B() + internal open override /*1*/ /*fake_override*/ fun bar() : jet.Unit + internal open override /*1*/ /*fake_override*/ fun foo() : jet.Unit +} + +internal final class C : test.B { + /*primary*/ public constructor C() + internal open override /*1*/ fun bar() : jet.Unit + internal open override /*1*/ /*fake_override*/ fun foo() : jet.Unit +} diff --git a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadCompiledKotlinTestGenerated.java b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadCompiledKotlinTestGenerated.java index babf01c3e3c..5c32db7fb29 100644 --- a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadCompiledKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadCompiledKotlinTestGenerated.java @@ -409,6 +409,11 @@ public class LoadCompiledKotlinTestGenerated extends AbstractLoadCompiledKotlinT JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/loadKotlin/fun"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("PropagateDeepSubclass.kt") + public void testPropagateDeepSubclass() throws Exception { + doTestWithAccessors("compiler/testData/loadKotlin/fun/PropagateDeepSubclass.kt"); + } + @TestMetadata("PropagateSubclassOfComparable.kt") public void testPropagateSubclassOfComparable() throws Exception { doTestWithAccessors("compiler/testData/loadKotlin/fun/PropagateSubclassOfComparable.kt"); diff --git a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java index 177e669ed1a..25123e2f0d7 100644 --- a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java @@ -1172,6 +1172,7 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest { } @TestMetadata("compiler/testData/loadJava/compiledJava/singleAbstractMethod") + @InnerTestClasses({}) public static class SingleAbstractMethod extends AbstractLoadJavaTest { public void testAllFilesPresentInSingleAbstractMethod() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/loadJava/compiledJava/singleAbstractMethod"), Pattern.compile("^(.+)\\.java$"), true); @@ -1217,6 +1218,11 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest { doTestCompiledJava("compiler/testData/loadJava/compiledJava/singleAbstractMethod/Runnable.java"); } + public static Test innerSuite() { + TestSuite suite = new TestSuite("SingleAbstractMethod"); + suite.addTestSuite(SingleAbstractMethod.class); + return suite; + } } @TestMetadata("compiler/testData/loadJava/compiledJava/static") @@ -1269,7 +1275,7 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest { suite.addTestSuite(ProtectedPackage.class); suite.addTestSuite(ProtectedStatic.class); suite.addTestSuite(SignaturePropagation.class); - suite.addTestSuite(SingleAbstractMethod.class); + suite.addTest(SingleAbstractMethod.innerSuite()); suite.addTestSuite(Static.class); return suite; } @@ -1322,6 +1328,11 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest { doTestJavaAgainstKotlin("compiler/testData/loadJava/javaAgainstKotlin/signaturePropagation/DeepSubclassingKotlinInJava.txt"); } + @TestMetadata("SubclassFromTraitImplementation.txt") + public void testSubclassFromTraitImplementation() throws Exception { + doTestJavaAgainstKotlin("compiler/testData/loadJava/javaAgainstKotlin/signaturePropagation/SubclassFromTraitImplementation.txt"); + } + @TestMetadata("SubclassingKotlinInJava.txt") public void testSubclassingKotlinInJava() throws Exception { doTestJavaAgainstKotlin("compiler/testData/loadJava/javaAgainstKotlin/signaturePropagation/SubclassingKotlinInJava.txt"); diff --git a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java index b6f7225a1dd..4c6570823c7 100644 --- a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java @@ -411,6 +411,11 @@ public class LazyResolveNamespaceComparingTestGenerated extends AbstractLazyReso JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/loadKotlin/fun"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("PropagateDeepSubclass.kt") + public void testPropagateDeepSubclass() throws Exception { + doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/fun/PropagateDeepSubclass.kt"); + } + @TestMetadata("PropagateSubclassOfComparable.kt") public void testPropagateSubclassOfComparable() throws Exception { doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/fun/PropagateSubclassOfComparable.kt");