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:
@@ -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 {
|
||||
|
||||
+73
-58
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user