Fix enum entry class delegating constructor call generation

When the enum entry requires a specific class, its constructor should
invoke proper supertype constructor (from the corresponding enum class).
Corresponding resolved call should be passed from the front-end in
CONSTRUCTOR_RESOLVED_DELEGATION_CALL slice.
In case of enum entries without explicit supertype initializer, this
information was missing.
This commit is contained in:
Dmitry Petrov
2017-12-01 15:03:36 +03:00
parent d8c4d19152
commit 3431a1445c
7 changed files with 85 additions and 3 deletions
@@ -389,7 +389,10 @@ public class BodyResolver {
if (ktClass instanceof KtEnumEntry && DescriptorUtils.isEnumEntry(descriptor) && ktClass.getSuperTypeListEntries().isEmpty()) {
assert scopeForConstructor != null : "Scope for enum class constructor should be non-null: " + descriptor;
resolveConstructorCallForEnumEntryWithoutInitializer((KtEnumEntry) ktClass, descriptor, scopeForConstructor, outerDataFlowInfo);
resolveConstructorCallForEnumEntryWithoutInitializer(
(KtEnumEntry) ktClass, descriptor,
scopeForConstructor, outerDataFlowInfo, primaryConstructorDelegationCall
);
}
for (KtSuperTypeListEntry delegationSpecifier : ktClass.getSuperTypeListEntries()) {
@@ -430,7 +433,8 @@ public class BodyResolver {
@NotNull KtEnumEntry ktEnumEntry,
@NotNull ClassDescriptor enumEntryDescriptor,
@NotNull LexicalScope scopeForConstructor,
@NotNull DataFlowInfo outerDataFlowInfo
@NotNull DataFlowInfo outerDataFlowInfo,
@NotNull ResolvedCall<?>[] primaryConstructorDelegationCall
) {
assert enumEntryDescriptor.getKind() == ClassKind.ENUM_ENTRY : "Enum entry expected: " + enumEntryDescriptor;
ClassDescriptor enumClassDescriptor = (ClassDescriptor) enumEntryDescriptor.getContainingDeclaration();
@@ -448,7 +452,11 @@ public class BodyResolver {
Call call = CallMaker.makeConstructorCallWithoutTypeArguments(ktCallEntry);
trace.record(BindingContext.TYPE, ktCallEntry.getTypeReference(), enumClassDescriptor.getDefaultType());
trace.record(BindingContext.CALL, ktEnumEntry, call);
callResolver.resolveFunctionCall(trace, scopeForConstructor, call, NO_EXPECTED_TYPE, outerDataFlowInfo, false);
OverloadResolutionResults<FunctionDescriptor> results =
callResolver.resolveFunctionCall(trace, scopeForConstructor, call, NO_EXPECTED_TYPE, outerDataFlowInfo, false);
if (primaryConstructorDelegationCall[0] == null) {
primaryConstructorDelegationCall[0] = results.getResultingCall();
}
}
// Returns a set of enum or sealed types of which supertypeOwner is an entry or a member
@@ -0,0 +1,8 @@
enum class Test(val str: String = "OK") {
OK {
fun foo() {}
}
}
fun box(): String =
Test.OK.str
@@ -0,0 +1,12 @@
// IGNORE_BACKEND: JS
enum class Test(vararg xs: Int) {
OK {
fun foo() {}
};
val xs = xs
}
fun box(): String =
if (Test.OK.xs.size == 0) "OK" else "Fail"
@@ -8473,6 +8473,18 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
doTest(fileName);
}
@TestMetadata("entryClassConstructorWithDefaultArguments.kt")
public void testEntryClassConstructorWithDefaultArguments() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/defaultCtor/entryClassConstructorWithDefaultArguments.kt");
doTest(fileName);
}
@TestMetadata("entryClassConstructorWithVarargs.kt")
public void testEntryClassConstructorWithVarargs() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/defaultCtor/entryClassConstructorWithVarargs.kt");
doTest(fileName);
}
@TestMetadata("secondaryConstructorWithDefaultArguments.kt")
public void testSecondaryConstructorWithDefaultArguments() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/defaultCtor/secondaryConstructorWithDefaultArguments.kt");
@@ -8473,6 +8473,18 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest(fileName);
}
@TestMetadata("entryClassConstructorWithDefaultArguments.kt")
public void testEntryClassConstructorWithDefaultArguments() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/defaultCtor/entryClassConstructorWithDefaultArguments.kt");
doTest(fileName);
}
@TestMetadata("entryClassConstructorWithVarargs.kt")
public void testEntryClassConstructorWithVarargs() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/defaultCtor/entryClassConstructorWithVarargs.kt");
doTest(fileName);
}
@TestMetadata("secondaryConstructorWithDefaultArguments.kt")
public void testSecondaryConstructorWithDefaultArguments() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/defaultCtor/secondaryConstructorWithDefaultArguments.kt");
@@ -8473,6 +8473,18 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
doTest(fileName);
}
@TestMetadata("entryClassConstructorWithDefaultArguments.kt")
public void testEntryClassConstructorWithDefaultArguments() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/defaultCtor/entryClassConstructorWithDefaultArguments.kt");
doTest(fileName);
}
@TestMetadata("entryClassConstructorWithVarargs.kt")
public void testEntryClassConstructorWithVarargs() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/defaultCtor/entryClassConstructorWithVarargs.kt");
doTest(fileName);
}
@TestMetadata("secondaryConstructorWithDefaultArguments.kt")
public void testSecondaryConstructorWithDefaultArguments() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/defaultCtor/secondaryConstructorWithDefaultArguments.kt");
@@ -9145,6 +9145,24 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
doTest(fileName);
}
@TestMetadata("entryClassConstructorWithDefaultArguments.kt")
public void testEntryClassConstructorWithDefaultArguments() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/defaultCtor/entryClassConstructorWithDefaultArguments.kt");
doTest(fileName);
}
@TestMetadata("entryClassConstructorWithVarargs.kt")
public void testEntryClassConstructorWithVarargs() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/defaultCtor/entryClassConstructorWithVarargs.kt");
try {
doTest(fileName);
}
catch (Throwable ignore) {
return;
}
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
}
@TestMetadata("secondaryConstructorWithDefaultArguments.kt")
public void testSecondaryConstructorWithDefaultArguments() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/defaultCtor/secondaryConstructorWithDefaultArguments.kt");