KT-7897 Do not require to call enum constructor for each entry if all parameters have default values

Do not report an error on enum entry without initializer if all parameters have default values
(error is still reported if there is no such constructor, or if the constructor call is ambiguous).

Record resolved call on KtEnumEntry.

NB is the enum entry has a corresponding subclass, we still have to generate the "default" constructor call,
because FE doesn't know about the platform-specific representation of that class and its constructors.

See also KT-14097, KT-15900
This commit is contained in:
Dmitry Petrov
2017-01-20 14:47:42 +03:00
parent d13c34200b
commit ee9a174c1f
23 changed files with 539 additions and 16 deletions
@@ -29,6 +29,7 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.backend.common.CodegenUtil;
import org.jetbrains.kotlin.backend.common.DataClassMethodGenerator;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
import org.jetbrains.kotlin.codegen.binding.MutableClosure;
import org.jetbrains.kotlin.codegen.context.*;
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension;
@@ -1593,6 +1594,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
iv.iconst(ordinal);
List<KtSuperTypeListEntry> delegationSpecifiers = enumEntry.getSuperTypeListEntries();
ResolvedCall<?> defaultArgumentsConstructorCall = CallUtilKt.getResolvedCall(enumEntry, bindingContext);
boolean enumEntryHasSubclass = CodegenBinding.enumEntryNeedSubclass(bindingContext, classDescriptor);
if (delegationSpecifiers.size() == 1 && !enumEntryNeedSubclass(bindingContext, enumEntry)) {
ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCallWithAssert(delegationSpecifiers.get(0), bindingContext);
@@ -1600,6 +1603,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
codegen.invokeMethodWithArguments(method, resolvedCall, StackValue.none());
}
else if (defaultArgumentsConstructorCall != null && !enumEntryHasSubclass) {
codegen.invokeFunction(defaultArgumentsConstructorCall, StackValue.none()).put(Type.VOID_TYPE, iv);
}
else {
iv.invokespecial(implClass.getInternalName(), "<init>", "(Ljava/lang/String;I)V", false);
}
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.resolve;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.util.containers.Queue;
import kotlin.Unit;
@@ -39,6 +40,7 @@ import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
import org.jetbrains.kotlin.resolve.calls.util.CallMaker;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil;
import org.jetbrains.kotlin.resolve.scopes.*;
import org.jetbrains.kotlin.types.*;
@@ -58,6 +60,7 @@ import static org.jetbrains.kotlin.resolve.BindingContext.*;
import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
public class BodyResolver {
@NotNull private final Project project;
@NotNull private final AnnotationChecker annotationChecker;
@NotNull private final ExpressionTypingServices expressionTypingServices;
@NotNull private final CallResolver callResolver;
@@ -74,6 +77,7 @@ public class BodyResolver {
@NotNull private final LanguageVersionSettings languageVersionSettings;
public BodyResolver(
@NotNull Project project,
@NotNull AnnotationResolver annotationResolver,
@NotNull BodyResolveCache bodyResolveCache,
@NotNull CallResolver callResolver,
@@ -89,6 +93,7 @@ public class BodyResolver {
@NotNull OverloadChecker overloadChecker,
@NotNull LanguageVersionSettings languageVersionSettings
) {
this.project = project;
this.annotationResolver = annotationResolver;
this.bodyResolveCache = bodyResolveCache;
this.callResolver = callResolver;
@@ -262,7 +267,7 @@ public class BodyResolver {
public void resolveSuperTypeEntryList(
@NotNull final DataFlowInfo outerDataFlowInfo,
@NotNull KtClassOrObject jetClass,
@NotNull KtClassOrObject ktClass,
@NotNull final ClassDescriptor descriptor,
@Nullable final ConstructorDescriptor primaryConstructor,
@NotNull LexicalScope scopeForConstructorResolution,
@@ -380,19 +385,49 @@ public class BodyResolver {
}
};
for (KtSuperTypeListEntry delegationSpecifier : jetClass.getSuperTypeListEntries()) {
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);
}
for (KtSuperTypeListEntry delegationSpecifier : ktClass.getSuperTypeListEntries()) {
delegationSpecifier.accept(visitor);
}
if (DescriptorUtils.isAnnotationClass(descriptor) && jetClass.getSuperTypeList() != null) {
trace.report(SUPERTYPES_FOR_ANNOTATION_CLASS.on(jetClass.getSuperTypeList()));
if (DescriptorUtils.isAnnotationClass(descriptor) && ktClass.getSuperTypeList() != null) {
trace.report(SUPERTYPES_FOR_ANNOTATION_CLASS.on(ktClass.getSuperTypeList()));
}
if (primaryConstructorDelegationCall[0] != null && primaryConstructor != null) {
recordConstructorDelegationCall(trace, primaryConstructor, primaryConstructorDelegationCall[0]);
}
checkSupertypeList(descriptor, supertypes, jetClass);
checkSupertypeList(descriptor, supertypes, ktClass);
}
private void resolveConstructorCallForEnumEntryWithoutInitializer(
@NotNull KtEnumEntry ktEnumEntry,
@NotNull ClassDescriptor enumEntryDescriptor,
@NotNull LexicalScope scopeForConstructor,
@NotNull DataFlowInfo outerDataFlowInfo
) {
assert enumEntryDescriptor.getKind() == ClassKind.ENUM_ENTRY : "Enum entry expected: " + enumEntryDescriptor;
ClassDescriptor enumClassDescriptor = (ClassDescriptor) enumEntryDescriptor.getContainingDeclaration();
if (enumClassDescriptor.getKind() != ClassKind.ENUM_CLASS) return;
if (enumClassDescriptor.isHeader()) return;
List<ClassConstructorDescriptor> applicableConstructors = DescriptorUtilsKt.getConstructorForEmptyArgumentsList(enumClassDescriptor);
if (applicableConstructors.size() != 1) {
trace.report(ENUM_ENTRY_SHOULD_BE_INITIALIZED.on(ktEnumEntry));
return;
}
KtInitializerList ktInitializerList = new KtPsiFactory(project).createEnumEntryInitializerList();
KtSuperTypeCallEntry ktCallEntry = (KtSuperTypeCallEntry) ktInitializerList.getInitializers().get(0);
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);
}
// Returns a set of enum or sealed types of which supertypeOwner is an entry or a member
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.resolve.BindingContext.*
import org.jetbrains.kotlin.resolve.DescriptorUtils.classCanHaveAbstractMembers
import org.jetbrains.kotlin.resolve.DescriptorUtils.classCanHaveOpenMembers
import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator
import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
import org.jetbrains.kotlin.types.*
@@ -882,9 +883,6 @@ class DeclarationsChecker(
trace.report(HEADER_ENUM_ENTRY_WITH_BODY.on(enumEntry))
}
}
else if (!enumEntry.hasInitializer() && !hasDefaultConstructor(enumClass)) {
trace.report(ENUM_ENTRY_SHOULD_BE_INITIALIZED.on(enumEntry))
}
}
else {
assert(DescriptorUtils.isInterface(enumClass)) { "Enum entry should be declared in enum class: " + enumEntryClass }
@@ -969,9 +967,6 @@ class DeclarationsChecker(
return !modifierList.hasModifier(KtTokens.OVERRIDE_KEYWORD)
}
private fun hasDefaultConstructor(classDescriptor: ClassDescriptor) =
classDescriptor.constructors.any { it.valueParameters.isEmpty() }
private fun PropertyDescriptor.hasAccessorImplementation(): Boolean {
getter?.let { if (it.hasBody()) return true }
setter?.let { if (it.hasBody()) return true }
@@ -282,6 +282,77 @@ public class CallMaker {
};
}
@NotNull
public static Call makeConstructorCallForEnumEntryWithoutInitializer(@NotNull final KtSuperTypeCallEntry callElement) {
return new Call() {
@Nullable
@Override
public ASTNode getCallOperationNode() {
return null;
}
@Nullable
@Override
public Receiver getExplicitReceiver() {
return null;
}
@Nullable
@Override
public ReceiverValue getDispatchReceiver() {
return null;
}
@Nullable
@Override
public KtExpression getCalleeExpression() {
return callElement.getCalleeExpression();
}
@Nullable
@Override
public KtValueArgumentList getValueArgumentList() {
return callElement.getValueArgumentList();
}
@NotNull
@Override
public List<? extends ValueArgument> getValueArguments() {
return callElement.getValueArguments();
}
@NotNull
@Override
public List<? extends LambdaArgument> getFunctionLiteralArguments() {
return Collections.emptyList();
}
@NotNull
@Override
public List<KtTypeProjection> getTypeArguments() {
return Collections.emptyList();
}
@Nullable
@Override
public KtTypeArgumentList getTypeArgumentList() {
return null;
}
@NotNull
@Override
public KtElement getCallElement() {
return callElement;
}
@NotNull
@Override
public CallType getCallType() {
return CallType.DEFAULT;
}
};
}
@NotNull
public static Call makeCall(@Nullable final Receiver explicitReceiver, @Nullable final ASTNode callOperationNode, @NotNull final KtCallElement callElement) {
return new Call() {
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
import java.lang.AssertionError
import java.util.*
@@ -267,18 +268,25 @@ class BodyGenerator(val scopeOwner: DeclarationDescriptor, override val context:
val statementGenerator = createStatementGenerator()
// Entry constructor with argument(s)
ktEnumEntry.getSuperTypeListEntries().firstOrNull()?.let { ktSuperCallElement ->
val enumConstructorCall = statementGenerator.pregenerateCall(getResolvedCall(ktSuperCallElement)!!)
return CallGenerator(statementGenerator).generateEnumConstructorSuperCall(
ktEnumEntry.startOffset, ktEnumEntry.endOffset,
enumConstructorCall)
val ktSuperCallElement = ktEnumEntry.superTypeListEntries.firstOrNull()
if (ktSuperCallElement != null) {
return statementGenerator.generateEnumConstructorCall(getResolvedCall(ktSuperCallElement)!!, ktEnumEntry)
}
val enumDefaultConstructorCall = getResolvedCall(ktEnumEntry)
if (enumDefaultConstructorCall != null) {
return statementGenerator.generateEnumConstructorCall(enumDefaultConstructorCall, ktEnumEntry)
}
// No-argument enum entry constructor
val enumClassConstructor = enumClassDescriptor.constructors.find { it.valueParameters.isEmpty() }!!
return IrEnumConstructorCallImpl(ktEnumEntry.startOffset, ktEnumEntry.endOffset, enumClassConstructor)
}
private fun StatementGenerator.generateEnumConstructorCall(constructorCall: ResolvedCall<out CallableDescriptor>, ktEnumEntry: KtEnumEntry) =
CallGenerator(this).generateEnumConstructorSuperCall(ktEnumEntry.startOffset, ktEnumEntry.endOffset,
pregenerateCall(constructorCall))
}
@@ -0,0 +1,6 @@
enum class Test(val str: String = "OK") {
OK
}
fun box(): String =
Test.OK.str
@@ -0,0 +1,9 @@
// IGNORE_BACKEND: JS
enum class Test(vararg xs: Int) {
OK;
val values = xs
}
fun box(): String =
if (Test.OK.values.size == 0) "OK" else "Fail"
@@ -0,0 +1,10 @@
// IGNORE_BACKEND: JS
// see KT-14097
enum class Test(val x: Int, val str: String) {
OK;
constructor(x: Int = 0) : this(x, "OK")
}
fun box(): String =
Test.OK.str
@@ -0,0 +1,13 @@
// IGNORE_BACKEND: JS
// see KT-14097
enum class Test(val x: Int, val str: String) {
OK;
constructor(vararg xs: Int) : this(xs.size + 42, "OK")
}
fun box(): String =
if (Test.OK.x == 42)
Test.OK.str
else
"Fail"
@@ -0,0 +1,15 @@
@kotlin.Metadata
public final class ConstructorWithDefaultArgumentsKt {
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
}
@kotlin.Metadata
public enum class Test {
public final static field OK: Test
private final @org.jetbrains.annotations.NotNull field str: java.lang.String
protected method <init>(@java.lang.Synthetic p0: java.lang.String, @java.lang.Synthetic p1: int, @org.jetbrains.annotations.NotNull p2: java.lang.String): void
synthetic method <init>(p0: java.lang.String, p1: int, p2: java.lang.String, p3: int, p4: kotlin.jvm.internal.DefaultConstructorMarker): void
public final @org.jetbrains.annotations.NotNull method getStr(): java.lang.String
public static method valueOf(p0: java.lang.String): Test
public static method values(): Test[]
}
@@ -0,0 +1,14 @@
@kotlin.Metadata
public final class ConstructorWithVarargKt {
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
}
@kotlin.Metadata
public enum class Test {
public final static field OK: Test
private final @org.jetbrains.annotations.NotNull field values: int[]
protected method <init>(@java.lang.Synthetic p0: java.lang.String, @java.lang.Synthetic p1: int, @org.jetbrains.annotations.NotNull p2: int[]): void
public final @org.jetbrains.annotations.NotNull method getValues(): int[]
public static method valueOf(p0: java.lang.String): Test
public static method values(): Test[]
}
@@ -0,0 +1,18 @@
@kotlin.Metadata
public final class SecondaryConstructorWithDefaultArgumentsKt {
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
}
@kotlin.Metadata
public enum class Test {
public final static field OK: Test
private final @org.jetbrains.annotations.NotNull field str: java.lang.String
private final field x: int
protected method <init>(@java.lang.Synthetic p0: java.lang.String, @java.lang.Synthetic p1: int, p2: int, @org.jetbrains.annotations.NotNull p3: java.lang.String): void
protected method <init>(p0: java.lang.String, p1: int, p2: int): void
synthetic method <init>(p0: java.lang.String, p1: int, p2: int, p3: int, p4: kotlin.jvm.internal.DefaultConstructorMarker): void
public final @org.jetbrains.annotations.NotNull method getStr(): java.lang.String
public final method getX(): int
public static method valueOf(p0: java.lang.String): Test
public static method values(): Test[]
}
@@ -0,0 +1,17 @@
@kotlin.Metadata
public final class SecondaryConstructorWithVarargKt {
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
}
@kotlin.Metadata
public enum class Test {
public final static field OK: Test
private final @org.jetbrains.annotations.NotNull field str: java.lang.String
private final field x: int
protected method <init>(@java.lang.Synthetic p0: java.lang.String, @java.lang.Synthetic p1: int, @org.jetbrains.annotations.NotNull p2: int[]): void
protected method <init>(@java.lang.Synthetic p0: java.lang.String, @java.lang.Synthetic p1: int, p2: int, @org.jetbrains.annotations.NotNull p3: java.lang.String): void
public final @org.jetbrains.annotations.NotNull method getStr(): java.lang.String
public final method getX(): int
public static method valueOf(p0: java.lang.String): Test
public static method values(): Test[]
}
@@ -0,0 +1,21 @@
enum class TestOk(val x: String = "OK") {
TEST1,
TEST2(),
TEST3("Hello")
}
enum class TestErrors(val x: String) {
<!ENUM_ENTRY_SHOULD_BE_INITIALIZED!>TEST1,<!>
TEST2(<!NO_VALUE_FOR_PARAMETER!>)<!>,
TEST3("Hello")
}
enum class TestMultipleConstructors(val x: String = "", val y: Int = 0) {
<!ENUM_ENTRY_SHOULD_BE_INITIALIZED!>TEST;<!>
constructor(x: String = "") : this(x, 0)
}
enum class TestVarargs(val x: Int) {
TEST;
constructor(vararg xs: Any) : this(xs.size)
}
@@ -0,0 +1,92 @@
package
public final enum class TestErrors : kotlin.Enum<TestErrors> {
enum entry TEST1
enum entry TEST2
enum entry TEST3
private constructor TestErrors(/*0*/ x: kotlin.String)
public final override /*1*/ /*fake_override*/ val name: kotlin.String
public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int
public final val x: kotlin.String
protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: TestErrors): kotlin.Int
public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
protected/*protected and package*/ final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit
public final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class<TestErrors!>!
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
// Static members
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): TestErrors
public final /*synthesized*/ fun values(): kotlin.Array<TestErrors>
}
public final enum class TestMultipleConstructors : kotlin.Enum<TestMultipleConstructors> {
enum entry TEST
private constructor TestMultipleConstructors(/*0*/ x: kotlin.String = ...)
private constructor TestMultipleConstructors(/*0*/ x: kotlin.String = ..., /*1*/ y: kotlin.Int = ...)
public final override /*1*/ /*fake_override*/ val name: kotlin.String
public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int
public final val x: kotlin.String
public final val y: kotlin.Int
protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: TestMultipleConstructors): kotlin.Int
public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
protected/*protected and package*/ final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit
public final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class<TestMultipleConstructors!>!
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
// Static members
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): TestMultipleConstructors
public final /*synthesized*/ fun values(): kotlin.Array<TestMultipleConstructors>
}
public final enum class TestOk : kotlin.Enum<TestOk> {
enum entry TEST1
enum entry TEST2
enum entry TEST3
private constructor TestOk(/*0*/ x: kotlin.String = ...)
public final override /*1*/ /*fake_override*/ val name: kotlin.String
public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int
public final val x: kotlin.String
protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: TestOk): kotlin.Int
public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
protected/*protected and package*/ final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit
public final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class<TestOk!>!
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
// Static members
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): TestOk
public final /*synthesized*/ fun values(): kotlin.Array<TestOk>
}
public final enum class TestVarargs : kotlin.Enum<TestVarargs> {
enum entry TEST
private constructor TestVarargs(/*0*/ vararg xs: kotlin.Any /*kotlin.Array<out kotlin.Any>*/)
private constructor TestVarargs(/*0*/ x: kotlin.Int)
public final override /*1*/ /*fake_override*/ val name: kotlin.String
public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int
public final val x: kotlin.Int
protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: TestVarargs): kotlin.Int
public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
protected/*protected and package*/ final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit
public final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class<TestVarargs!>!
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
// Static members
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): TestVarargs
public final /*synthesized*/ fun values(): kotlin.Array<TestVarargs>
}
+4
View File
@@ -37,4 +37,8 @@ enum class TestEnum4(val x: Int) {
}
;
abstract fun foo()
}
enum class TestEnum5(val x: Int = 0) {
TEST1, TEST2(), TEST3(0)
}
+27
View File
@@ -116,3 +116,30 @@ FILE /enum.kt
SYNTHETIC_BODY kind=ENUM_VALUES
FUN ENUM_CLASS_SPECIAL_MEMBER public final fun valueOf(value: kotlin.String): TestEnum4
SYNTHETIC_BODY kind=ENUM_VALUEOF
CLASS ENUM_CLASS TestEnum5
CONSTRUCTOR private constructor TestEnum5(x: kotlin.Int = ...)
x: EXPRESSION_BODY
CONST Int type=kotlin.Int value='0'
BLOCK_BODY
ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)'
INSTANCE_INITIALIZER_CALL classDescriptor='TestEnum5'
PROPERTY public final val x: kotlin.Int
FIELD PROPERTY_BACKING_FIELD public final val x: kotlin.Int
EXPRESSION_BODY
GET_VAR 'value-parameter x: Int = ...' type=kotlin.Int origin=INITIALIZE_PROPERTY_FROM_PARAMETER
FUN DEFAULT_PROPERTY_ACCESSOR public final fun <get-x>(): kotlin.Int
BLOCK_BODY
RETURN type=kotlin.Nothing from='<get-x>(): Int'
GET_FIELD 'x: Int' type=kotlin.Int origin=null
receiver: GET_VAR '<receiver: TestEnum5>' type=TestEnum5 origin=null
ENUM_ENTRY enum entry TEST1
init: ENUM_CONSTRUCTOR_CALL 'constructor TestEnum5(Int = ...)'
ENUM_ENTRY enum entry TEST2
init: ENUM_CONSTRUCTOR_CALL 'constructor TestEnum5(Int = ...)'
ENUM_ENTRY enum entry TEST3
init: ENUM_CONSTRUCTOR_CALL 'constructor TestEnum5(Int = ...)'
x: CONST Int type=kotlin.Int value='0'
FUN ENUM_CLASS_SPECIAL_MEMBER public final fun values(): kotlin.Array<TestEnum5>
SYNTHETIC_BODY kind=ENUM_VALUES
FUN ENUM_CLASS_SPECIAL_MEMBER public final fun valueOf(value: kotlin.String): TestEnum5
SYNTHETIC_BODY kind=ENUM_VALUEOF
@@ -7018,6 +7018,39 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/valueof.kt");
doTest(fileName);
}
@TestMetadata("compiler/testData/codegen/box/enum/defaultCtor")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class DefaultCtor extends AbstractIrBlackBoxCodegenTest {
public void testAllFilesPresentInDefaultCtor() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/enum/defaultCtor"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
}
@TestMetadata("constructorWithDefaultArguments.kt")
public void testConstructorWithDefaultArguments() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/defaultCtor/constructorWithDefaultArguments.kt");
doTest(fileName);
}
@TestMetadata("constructorWithVararg.kt")
public void testConstructorWithVararg() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/defaultCtor/constructorWithVararg.kt");
doTest(fileName);
}
@TestMetadata("secondaryConstructorWithDefaultArguments.kt")
public void testSecondaryConstructorWithDefaultArguments() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/defaultCtor/secondaryConstructorWithDefaultArguments.kt");
doTest(fileName);
}
@TestMetadata("secondaryConstructorWithVararg.kt")
public void testSecondaryConstructorWithVararg() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/defaultCtor/secondaryConstructorWithVararg.kt");
doTest(fileName);
}
}
}
@TestMetadata("compiler/testData/codegen/box/evaluate")
@@ -7327,6 +7327,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("constructorWithDefaultParametersOnly.kt")
public void testConstructorWithDefaultParametersOnly() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/enum/constructorWithDefaultParametersOnly.kt");
doTest(fileName);
}
@TestMetadata("dontCreatePackageTypeForEnumEntry.kt")
public void testDontCreatePackageTypeForEnumEntry() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/enum/dontCreatePackageTypeForEnumEntry.kt");
@@ -7018,6 +7018,39 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/valueof.kt");
doTest(fileName);
}
@TestMetadata("compiler/testData/codegen/box/enum/defaultCtor")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class DefaultCtor extends AbstractBlackBoxCodegenTest {
public void testAllFilesPresentInDefaultCtor() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/enum/defaultCtor"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
}
@TestMetadata("constructorWithDefaultArguments.kt")
public void testConstructorWithDefaultArguments() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/defaultCtor/constructorWithDefaultArguments.kt");
doTest(fileName);
}
@TestMetadata("constructorWithVararg.kt")
public void testConstructorWithVararg() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/defaultCtor/constructorWithVararg.kt");
doTest(fileName);
}
@TestMetadata("secondaryConstructorWithDefaultArguments.kt")
public void testSecondaryConstructorWithDefaultArguments() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/defaultCtor/secondaryConstructorWithDefaultArguments.kt");
doTest(fileName);
}
@TestMetadata("secondaryConstructorWithVararg.kt")
public void testSecondaryConstructorWithVararg() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/defaultCtor/secondaryConstructorWithVararg.kt");
doTest(fileName);
}
}
}
@TestMetadata("compiler/testData/codegen/box/evaluate")
@@ -7018,6 +7018,39 @@ public class LightAnalysisModeCodegenTestGenerated extends AbstractLightAnalysis
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/valueof.kt");
doTest(fileName);
}
@TestMetadata("compiler/testData/codegen/box/enum/defaultCtor")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class DefaultCtor extends AbstractLightAnalysisModeCodegenTest {
public void testAllFilesPresentInDefaultCtor() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/enum/defaultCtor"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
}
@TestMetadata("constructorWithDefaultArguments.kt")
public void testConstructorWithDefaultArguments() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/defaultCtor/constructorWithDefaultArguments.kt");
doTest(fileName);
}
@TestMetadata("constructorWithVararg.kt")
public void testConstructorWithVararg() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/defaultCtor/constructorWithVararg.kt");
doTest(fileName);
}
@TestMetadata("secondaryConstructorWithDefaultArguments.kt")
public void testSecondaryConstructorWithDefaultArguments() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/defaultCtor/secondaryConstructorWithDefaultArguments.kt");
doTest(fileName);
}
@TestMetadata("secondaryConstructorWithVararg.kt")
public void testSecondaryConstructorWithVararg() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/defaultCtor/secondaryConstructorWithVararg.kt");
doTest(fileName);
}
}
}
@TestMetadata("compiler/testData/codegen/box/evaluate")
@@ -391,3 +391,9 @@ fun computeSealedSubclasses(sealedClass: ClassDescriptor): Collection<ClassDescr
collectSubclasses(sealedClass.unsubstitutedInnerClassesScope, collectNested = true)
return result
}
fun ClassDescriptor.getNoArgsConstructor(): ClassConstructorDescriptor? =
constructors.find { it.valueParameters.isEmpty() }
fun ClassDescriptor.getConstructorForEmptyArgumentsList(): List<ClassConstructorDescriptor> =
constructors.filter { it.valueParameters.all { it.hasDefaultValue() || it.varargElementType != null } }
@@ -7937,6 +7937,57 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/valueof.kt");
doTest(fileName);
}
@TestMetadata("compiler/testData/codegen/box/enum/defaultCtor")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class DefaultCtor extends AbstractJsCodegenBoxTest {
public void testAllFilesPresentInDefaultCtor() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/enum/defaultCtor"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
}
@TestMetadata("constructorWithDefaultArguments.kt")
public void testConstructorWithDefaultArguments() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/defaultCtor/constructorWithDefaultArguments.kt");
doTest(fileName);
}
@TestMetadata("constructorWithVararg.kt")
public void testConstructorWithVararg() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/defaultCtor/constructorWithVararg.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");
try {
doTest(fileName);
}
catch (Throwable ignore) {
return;
}
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
}
@TestMetadata("secondaryConstructorWithVararg.kt")
public void testSecondaryConstructorWithVararg() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/defaultCtor/secondaryConstructorWithVararg.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("compiler/testData/codegen/box/evaluate")