Fixed propagation for non-abstract methods inherited from traits.

This commit is contained in:
Evgeny Gerashchenko
2013-04-11 20:47:10 +04:00
parent 068b4a4628
commit f713b03abc
10 changed files with 116 additions and 4 deletions
@@ -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<PsiMethod> getSuperMethods(@NotNull PsiMethod method) {
List<PsiMethod> 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() {
}
}
@@ -209,9 +209,7 @@ public class SignaturesPropagationData {
Multimap<FqName, Pair<FunctionDescriptor, PsiMethod>> 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();
@@ -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
}
@@ -0,0 +1,8 @@
package test;
public class Subclass extends Impl {
@Override
public String bar() {
return "bar bar";
}
}
@@ -0,0 +1,10 @@
package test
trait Trait {
fun foo(): String = "foo"
fun bar(): String = "bar"
}
open class Impl : Trait {
}
@@ -0,0 +1,14 @@
package test
trait A {
fun foo() {}
fun bar() {}
}
open class B : A {
}
class C : B() {
override fun bar() {}
}
@@ -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
}
@@ -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");
@@ -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");
@@ -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");