Refactor ImplementationBodyCodegen.getTraitImplementations()

Make it static, extract a method which finds an implementation in a trait for a
fake override
This commit is contained in:
Alexander Udalov
2014-04-08 18:37:02 +04:00
parent 5967befa6a
commit fc838dbb53
16 changed files with 145 additions and 105 deletions
@@ -1815,58 +1815,63 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
* Return pairs of descriptors. First is member of this that should be implemented by delegating to trait,
* second is member of trait that contain implementation.
*/
private List<Pair<CallableMemberDescriptor, CallableMemberDescriptor>> getTraitImplementations(@NotNull ClassDescriptor classDescriptor) {
List<Pair<CallableMemberDescriptor, CallableMemberDescriptor>> r = Lists.newArrayList();
@NotNull
private static List<Pair<CallableMemberDescriptor, CallableMemberDescriptor>> getTraitImplementations(@NotNull ClassDescriptor classDescriptor) {
List<Pair<CallableMemberDescriptor, CallableMemberDescriptor>> result = Lists.newArrayList();
for (DeclarationDescriptor decl : classDescriptor.getDefaultType().getMemberScope().getAllDescriptors()) {
if (!(decl instanceof CallableMemberDescriptor)) {
continue;
}
for (DeclarationDescriptor declaration : classDescriptor.getDefaultType().getMemberScope().getAllDescriptors()) {
if (!(declaration instanceof CallableMemberDescriptor)) continue;
CallableMemberDescriptor callableMemberDescriptor = (CallableMemberDescriptor) decl;
if (callableMemberDescriptor.getKind() != CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
continue;
}
CallableMemberDescriptor callableMemberDescriptor = (CallableMemberDescriptor) declaration;
if (CallResolverUtil.isOrOverridesSynthesized(callableMemberDescriptor)) {
continue;
}
Collection<CallableMemberDescriptor> overriddenDeclarations =
OverridingUtil.getOverriddenDeclarations(callableMemberDescriptor);
Collection<CallableMemberDescriptor> filteredOverriddenDeclarations =
OverridingUtil.filterOutOverridden(Sets.newLinkedHashSet(overriddenDeclarations));
int count = 0;
CallableMemberDescriptor candidate = null;
for (CallableMemberDescriptor overriddenDeclaration : filteredOverriddenDeclarations) {
if (isTrait(overriddenDeclaration.getContainingDeclaration()) &&
overriddenDeclaration.getModality() != Modality.ABSTRACT) {
candidate = overriddenDeclaration;
count++;
}
}
if (candidate == null) {
continue;
}
assert count == 1 : "Ambiguous overridden declaration: " + callableMemberDescriptor.getName();
Collection<JetType> superTypesOfSuperClass =
superClassType != null ? TypeUtils.getAllSupertypes(superClassType) : Collections.<JetType>emptySet();
ReceiverParameterDescriptor expectedThisObject = candidate.getExpectedThisObject();
assert expectedThisObject != null;
JetType candidateType = expectedThisObject.getType();
boolean implementedInSuperClass = superTypesOfSuperClass.contains(candidateType);
if (!implementedInSuperClass) {
r.add(Pair.create(callableMemberDescriptor, candidate));
CallableMemberDescriptor implementation = findTraitImplementation(callableMemberDescriptor);
if (implementation != null) {
result.add(Pair.create(callableMemberDescriptor, implementation));
}
}
return r;
return result;
}
/**
* Given a fake override descriptor, returns an overridden non-abstract descriptor whose container is a trait
*/
@Nullable
private static CallableMemberDescriptor findTraitImplementation(@NotNull CallableMemberDescriptor descriptor) {
if (descriptor.getKind().isReal()) return null;
if (CallResolverUtil.isOrOverridesSynthesized(descriptor)) return null;
Collection<CallableMemberDescriptor> overriddenDeclarations = OverridingUtil.getOverriddenDeclarations(descriptor);
Collection<CallableMemberDescriptor> filteredOverriddenDeclarations =
OverridingUtil.filterOutOverridden(Sets.newLinkedHashSet(overriddenDeclarations));
int count = 0;
CallableMemberDescriptor implementation = null;
for (CallableMemberDescriptor overriddenDeclaration : filteredOverriddenDeclarations) {
if (isTrait(overriddenDeclaration.getContainingDeclaration()) && overriddenDeclaration.getModality() != Modality.ABSTRACT) {
implementation = overriddenDeclaration;
count++;
}
}
if (implementation == null) {
return null;
}
assert count == 1 : "Ambiguous overridden declaration: " + descriptor;
ClassDescriptor containingClass = (ClassDescriptor) descriptor.getContainingDeclaration();
for (JetType supertype : containingClass.getDefaultType().getConstructor().getSupertypes()) {
//noinspection ConstantConditions
if (!isTrait(supertype.getConstructor().getDeclarationDescriptor()) &&
TypeUtils.getAllSupertypes(supertype).contains(implementation.getExpectedThisObject().getType())) {
return null;
}
}
return implementation;
}
public void addClassObjectPropertyToCopy(PropertyDescriptor descriptor, Object defaultValue) {
@@ -0,0 +1,15 @@
trait A {
fun foo() = 42
}
open class B : A
open class C : B()
class D : C()
// Implementation of foo() should only be generated into B
// 1 INVOKESTATIC A\$\$TImpl.foo
// Only two declarations should be present: in A and B
// 2 foo\(\)I
@@ -122,6 +122,11 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
doTest("compiler/testData/codegen/bytecodeText/topLevelFunWithDefaultArgs.kt");
}
@TestMetadata("traitImplGeneratedOnce.kt")
public void testTraitImplGeneratedOnce() throws Exception {
doTest("compiler/testData/codegen/bytecodeText/traitImplGeneratedOnce.kt");
}
@TestMetadata("compiler/testData/codegen/bytecodeText/constants")
public static class Constants extends AbstractBytecodeTextTest {
public void testAllFilesPresentInConstants() throws Exception {
@@ -5075,6 +5075,7 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
}
@TestMetadata("compiler/testData/codegen/box/traits")
@InnerTestClasses({Traits.WithRequired.class})
public static class Traits extends AbstractBlackBoxCodegenTest {
public void testAllFilesPresentInTraits() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/codegen/box/traits"), Pattern.compile("^(.+)\\.kt$"), true);
@@ -5110,11 +5111,6 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest("compiler/testData/codegen/box/traits/kt1936_1.kt");
}
@TestMetadata("kt1936_2.kt")
public void testKt1936_2() throws Exception {
doTest("compiler/testData/codegen/box/traits/kt1936_2.kt");
}
@TestMetadata("kt2260.kt")
public void testKt2260() throws Exception {
doTest("compiler/testData/codegen/box/traits/kt2260.kt");
@@ -5130,26 +5126,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest("compiler/testData/codegen/box/traits/kt2541.kt");
}
@TestMetadata("kt2963.kt")
public void testKt2963() throws Exception {
doTest("compiler/testData/codegen/box/traits/kt2963.kt");
}
@TestMetadata("kt3315.kt")
public void testKt3315() throws Exception {
doTest("compiler/testData/codegen/box/traits/kt3315.kt");
}
@TestMetadata("kt3413.kt")
public void testKt3413() throws Exception {
doTest("compiler/testData/codegen/box/traits/kt3413.kt");
}
@TestMetadata("kt3429.kt")
public void testKt3429() throws Exception {
doTest("compiler/testData/codegen/box/traits/kt3429.kt");
}
@TestMetadata("kt3500.kt")
public void testKt3500() throws Exception {
doTest("compiler/testData/codegen/box/traits/kt3500.kt");
@@ -5160,51 +5141,85 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest("compiler/testData/codegen/box/traits/multiple.kt");
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
doTest("compiler/testData/codegen/box/traits/simple.kt");
}
@TestMetadata("stdlib.kt")
public void testStdlib() throws Exception {
doTest("compiler/testData/codegen/box/traits/stdlib.kt");
}
@TestMetadata("traitFuncCall.kt")
public void testTraitFuncCall() throws Exception {
doTest("compiler/testData/codegen/box/traits/traitFuncCall.kt");
@TestMetadata("compiler/testData/codegen/box/traits/withRequired")
public static class WithRequired extends AbstractBlackBoxCodegenTest {
public void testAllFilesPresentInWithRequired() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/codegen/box/traits/withRequired"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("generic.kt")
public void testGeneric() throws Exception {
doTest("compiler/testData/codegen/box/traits/withRequired/generic.kt");
}
@TestMetadata("genericProperty.kt")
public void testGenericProperty() throws Exception {
doTest("compiler/testData/codegen/box/traits/withRequired/genericProperty.kt");
}
@TestMetadata("kt1936_2.kt")
public void testKt1936_2() throws Exception {
doTest("compiler/testData/codegen/box/traits/withRequired/kt1936_2.kt");
}
@TestMetadata("kt2963.kt")
public void testKt2963() throws Exception {
doTest("compiler/testData/codegen/box/traits/withRequired/kt2963.kt");
}
@TestMetadata("kt3413.kt")
public void testKt3413() throws Exception {
doTest("compiler/testData/codegen/box/traits/withRequired/kt3413.kt");
}
@TestMetadata("kt3429.kt")
public void testKt3429() throws Exception {
doTest("compiler/testData/codegen/box/traits/withRequired/kt3429.kt");
}
@TestMetadata("property.kt")
public void testProperty() throws Exception {
doTest("compiler/testData/codegen/box/traits/withRequired/property.kt");
}
@TestMetadata("propertyViaBridge.kt")
public void testPropertyViaBridge() throws Exception {
doTest("compiler/testData/codegen/box/traits/withRequired/propertyViaBridge.kt");
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
doTest("compiler/testData/codegen/box/traits/withRequired/simple.kt");
}
@TestMetadata("super.kt")
public void testSuper() throws Exception {
doTest("compiler/testData/codegen/box/traits/withRequired/super.kt");
}
@TestMetadata("superViaBridge.kt")
public void testSuperViaBridge() throws Exception {
doTest("compiler/testData/codegen/box/traits/withRequired/superViaBridge.kt");
}
@TestMetadata("traitFuncCall.kt")
public void testTraitFuncCall() throws Exception {
doTest("compiler/testData/codegen/box/traits/withRequired/traitFuncCall.kt");
}
}
@TestMetadata("withRequired.kt")
public void testWithRequired() throws Exception {
doTest("compiler/testData/codegen/box/traits/withRequired.kt");
public static Test innerSuite() {
TestSuite suite = new TestSuite("Traits");
suite.addTestSuite(Traits.class);
suite.addTestSuite(WithRequired.class);
return suite;
}
@TestMetadata("withRequiredGenericProperty.kt")
public void testWithRequiredGenericProperty() throws Exception {
doTest("compiler/testData/codegen/box/traits/withRequiredGenericProperty.kt");
}
@TestMetadata("withRequiredProperty.kt")
public void testWithRequiredProperty() throws Exception {
doTest("compiler/testData/codegen/box/traits/withRequiredProperty.kt");
}
@TestMetadata("withRequiredPropertyViaBridge.kt")
public void testWithRequiredPropertyViaBridge() throws Exception {
doTest("compiler/testData/codegen/box/traits/withRequiredPropertyViaBridge.kt");
}
@TestMetadata("withRequiredSuper.kt")
public void testWithRequiredSuper() throws Exception {
doTest("compiler/testData/codegen/box/traits/withRequiredSuper.kt");
}
@TestMetadata("withRequiredSuperViaBridge.kt")
public void testWithRequiredSuperViaBridge() throws Exception {
doTest("compiler/testData/codegen/box/traits/withRequiredSuperViaBridge.kt");
}
}
@TestMetadata("compiler/testData/codegen/box/typeInfo")
@@ -5551,7 +5566,7 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
suite.addTestSuite(Strings.class);
suite.addTestSuite(Super.class);
suite.addTestSuite(ToArray.class);
suite.addTestSuite(Traits.class);
suite.addTest(Traits.innerSuite());
suite.addTestSuite(TypeInfo.class);
suite.addTestSuite(TypeMapping.class);
suite.addTestSuite(UnaryOp.class);