KT-4107 Data objects
This commit is contained in:
+6
@@ -2438,6 +2438,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
|||||||
token,
|
token,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
add(FirErrors.DATA_OBJECT_CUSTOM_EQUALS_OR_HASH_CODE) { firDiagnostic ->
|
||||||
|
DataObjectCustomEqualsOrHashCodeImpl(
|
||||||
|
firDiagnostic as KtPsiDiagnostic,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
add(FirErrors.FUN_INTERFACE_CONSTRUCTOR_REFERENCE) { firDiagnostic ->
|
add(FirErrors.FUN_INTERFACE_CONSTRUCTOR_REFERENCE) { firDiagnostic ->
|
||||||
FunInterfaceConstructorReferenceImpl(
|
FunInterfaceConstructorReferenceImpl(
|
||||||
firDiagnostic as KtPsiDiagnostic,
|
firDiagnostic as KtPsiDiagnostic,
|
||||||
|
|||||||
+4
@@ -1729,6 +1729,10 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
|||||||
override val diagnosticClass get() = TailRecursionInTryIsNotSupported::class
|
override val diagnosticClass get() = TailRecursionInTryIsNotSupported::class
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class DataObjectCustomEqualsOrHashCode : KtFirDiagnostic<KtNamedFunction>() {
|
||||||
|
override val diagnosticClass get() = DataObjectCustomEqualsOrHashCode::class
|
||||||
|
}
|
||||||
|
|
||||||
abstract class FunInterfaceConstructorReference : KtFirDiagnostic<KtExpression>() {
|
abstract class FunInterfaceConstructorReference : KtFirDiagnostic<KtExpression>() {
|
||||||
override val diagnosticClass get() = FunInterfaceConstructorReference::class
|
override val diagnosticClass get() = FunInterfaceConstructorReference::class
|
||||||
}
|
}
|
||||||
|
|||||||
+5
@@ -2073,6 +2073,11 @@ internal class TailRecursionInTryIsNotSupportedImpl(
|
|||||||
override val token: KtLifetimeToken,
|
override val token: KtLifetimeToken,
|
||||||
) : KtFirDiagnostic.TailRecursionInTryIsNotSupported(), KtAbstractFirDiagnostic<PsiElement>
|
) : KtFirDiagnostic.TailRecursionInTryIsNotSupported(), KtAbstractFirDiagnostic<PsiElement>
|
||||||
|
|
||||||
|
internal class DataObjectCustomEqualsOrHashCodeImpl(
|
||||||
|
override val firDiagnostic: KtPsiDiagnostic,
|
||||||
|
override val token: KtLifetimeToken,
|
||||||
|
) : KtFirDiagnostic.DataObjectCustomEqualsOrHashCode(), KtAbstractFirDiagnostic<KtNamedFunction>
|
||||||
|
|
||||||
internal class FunInterfaceConstructorReferenceImpl(
|
internal class FunInterfaceConstructorReferenceImpl(
|
||||||
override val firDiagnostic: KtPsiDiagnostic,
|
override val firDiagnostic: KtPsiDiagnostic,
|
||||||
override val token: KtLifetimeToken,
|
override val token: KtLifetimeToken,
|
||||||
|
|||||||
+37
-3
@@ -6956,6 +6956,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
|
|||||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/dataClasses"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/dataClasses"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("companionDataObject.kt")
|
||||||
|
public void testCompanionDataObject() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/dataClasses/companionDataObject.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("componentNamedComponent1.kt")
|
@TestMetadata("componentNamedComponent1.kt")
|
||||||
public void testComponentNamedComponent1() throws Exception {
|
public void testComponentNamedComponent1() throws Exception {
|
||||||
@@ -7029,9 +7035,21 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("dataObject.kt")
|
@TestMetadata("dataObjectDisabled.kt")
|
||||||
public void testDataObject() throws Exception {
|
public void testDataObjectDisabled() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/dataClasses/dataObject.kt");
|
runTest("compiler/testData/diagnostics/tests/dataClasses/dataObjectDisabled.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("dataObjectEnabled.kt")
|
||||||
|
public void testDataObjectEnabled() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/dataClasses/dataObjectEnabled.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("dataObjectLiteral.kt")
|
||||||
|
public void testDataObjectLiteral() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/dataClasses/dataObjectLiteral.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -7655,6 +7673,22 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("compiler/testData/diagnostics/tests/dataObjects")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class DataObjects {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInDataObjects() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/dataObjects"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("overrideEqualsAndHashCode.kt")
|
||||||
|
public void testOverrideEqualsAndHashCode() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/dataObjects/overrideEqualsAndHashCode.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@TestMetadata("compiler/testData/diagnostics/tests/declarationChecks")
|
@TestMetadata("compiler/testData/diagnostics/tests/declarationChecks")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
|||||||
+5
-2
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.backend.common
|
|||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
|
import org.jetbrains.kotlin.psi.KtObjectDeclaration
|
||||||
import org.jetbrains.kotlin.psi.KtParameter
|
import org.jetbrains.kotlin.psi.KtParameter
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
|
||||||
@@ -33,8 +34,10 @@ abstract class DataClassMethodGenerator(
|
|||||||
) : FunctionsFromAnyGenerator(declaration, bindingContext) {
|
) : FunctionsFromAnyGenerator(declaration, bindingContext) {
|
||||||
|
|
||||||
override fun generate() {
|
override fun generate() {
|
||||||
generateComponentFunctionsForDataClasses()
|
if (declaration !is KtObjectDeclaration) {
|
||||||
generateCopyFunctionForDataClasses(primaryConstructorParameters)
|
generateComponentFunctionsForDataClasses()
|
||||||
|
generateCopyFunctionForDataClasses(primaryConstructorParameters)
|
||||||
|
}
|
||||||
|
|
||||||
super.generate()
|
super.generate()
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-5
@@ -21,11 +21,9 @@ abstract class FunctionsFromAnyGenerator(protected val declaration: KtClassOrObj
|
|||||||
|
|
||||||
open fun generate() {
|
open fun generate() {
|
||||||
val properties = primaryConstructorProperties
|
val properties = primaryConstructorProperties
|
||||||
if (properties.isNotEmpty()) {
|
generateToStringIfNeeded(properties)
|
||||||
generateToStringIfNeeded(properties)
|
generateHashCodeIfNeeded(properties)
|
||||||
generateHashCodeIfNeeded(properties)
|
generateEqualsIfNeeded(properties)
|
||||||
generateEqualsIfNeeded(properties)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract fun generateToStringMethod(function: FunctionDescriptor, properties: List<PropertyDescriptor>)
|
protected abstract fun generateToStringMethod(function: FunctionDescriptor, properties: List<PropertyDescriptor>)
|
||||||
|
|||||||
+71
-61
@@ -17,8 +17,10 @@ import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
|||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor;
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor;
|
||||||
|
import org.jetbrains.kotlin.name.FqName;
|
||||||
import org.jetbrains.kotlin.psi.KtClassOrObject;
|
import org.jetbrains.kotlin.psi.KtClassOrObject;
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||||
|
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||||
import org.jetbrains.kotlin.resolve.InlineClassesUtilsKt;
|
import org.jetbrains.kotlin.resolve.InlineClassesUtilsKt;
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
|
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
|
||||||
@@ -103,42 +105,46 @@ public class FunctionsFromAnyGeneratorImpl extends FunctionsFromAnyGenerator {
|
|||||||
|
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
|
|
||||||
StringConcatGenerator generator = StringConcatGenerator.Companion.create(generationState, iv);
|
if (properties.isEmpty()) {
|
||||||
generator.genStringBuilderConstructorIfNeded();
|
iv.aconst(classDescriptor.getName().asString());
|
||||||
boolean first = true;
|
} else {
|
||||||
|
StringConcatGenerator generator = StringConcatGenerator.Companion.create(generationState, iv);
|
||||||
|
generator.genStringBuilderConstructorIfNeded();
|
||||||
|
boolean first = true;
|
||||||
|
|
||||||
for (PropertyDescriptor propertyDescriptor : properties) {
|
for (PropertyDescriptor propertyDescriptor : properties) {
|
||||||
if (first) {
|
if (first) {
|
||||||
generator.addStringConstant(classDescriptor.getName() + "(" + propertyDescriptor.getName().asString() + "=");
|
generator.addStringConstant(classDescriptor.getName() + "(" + propertyDescriptor.getName().asString() + "=");
|
||||||
first = false;
|
first = false;
|
||||||
}
|
|
||||||
else {
|
|
||||||
generator.addStringConstant(", " + propertyDescriptor.getName().asString() + "=");
|
|
||||||
}
|
|
||||||
|
|
||||||
JvmKotlinType type = genOrLoadOnStack(iv, context, propertyDescriptor, 0);
|
|
||||||
Type asmType = type.getType();
|
|
||||||
KotlinType kotlinType = type.getKotlinType();
|
|
||||||
|
|
||||||
if (asmType.getSort() == Type.ARRAY) {
|
|
||||||
Type elementType = correctElementType(asmType);
|
|
||||||
if (elementType.getSort() == Type.OBJECT || elementType.getSort() == Type.ARRAY) {
|
|
||||||
iv.invokestatic("java/util/Arrays", "toString", "([Ljava/lang/Object;)Ljava/lang/String;", false);
|
|
||||||
asmType = JAVA_STRING_TYPE;
|
|
||||||
kotlinType = DescriptorUtilsKt.getBuiltIns(function).getStringType();
|
|
||||||
}
|
}
|
||||||
else if (elementType.getSort() != Type.CHAR) {
|
else {
|
||||||
iv.invokestatic("java/util/Arrays", "toString", "(" + asmType.getDescriptor() + ")Ljava/lang/String;", false);
|
generator.addStringConstant(", " + propertyDescriptor.getName().asString() + "=");
|
||||||
asmType = JAVA_STRING_TYPE;
|
|
||||||
kotlinType = DescriptorUtilsKt.getBuiltIns(function).getStringType();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JvmKotlinType type = genOrLoadOnStack(iv, context, propertyDescriptor, 0);
|
||||||
|
Type asmType = type.getType();
|
||||||
|
KotlinType kotlinType = type.getKotlinType();
|
||||||
|
|
||||||
|
if (asmType.getSort() == Type.ARRAY) {
|
||||||
|
Type elementType = correctElementType(asmType);
|
||||||
|
if (elementType.getSort() == Type.OBJECT || elementType.getSort() == Type.ARRAY) {
|
||||||
|
iv.invokestatic("java/util/Arrays", "toString", "([Ljava/lang/Object;)Ljava/lang/String;", false);
|
||||||
|
asmType = JAVA_STRING_TYPE;
|
||||||
|
kotlinType = DescriptorUtilsKt.getBuiltIns(function).getStringType();
|
||||||
|
}
|
||||||
|
else if (elementType.getSort() != Type.CHAR) {
|
||||||
|
iv.invokestatic("java/util/Arrays", "toString", "(" + asmType.getDescriptor() + ")Ljava/lang/String;", false);
|
||||||
|
asmType = JAVA_STRING_TYPE;
|
||||||
|
kotlinType = DescriptorUtilsKt.getBuiltIns(function).getStringType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
genInvokeAppendMethod(generator, asmType, kotlinType, typeMapper, StackValue.onStack(asmType));
|
||||||
}
|
}
|
||||||
genInvokeAppendMethod(generator, asmType, kotlinType, typeMapper, StackValue.onStack(asmType));
|
|
||||||
|
generator.addStringConstant(")");
|
||||||
|
|
||||||
|
generator.genToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
generator.addStringConstant(")");
|
|
||||||
|
|
||||||
generator.genToString();
|
|
||||||
iv.areturn(JAVA_STRING_TYPE);
|
iv.areturn(JAVA_STRING_TYPE);
|
||||||
|
|
||||||
FunctionCodegen.endVisit(mv, toStringMethodName, getDeclaration());
|
FunctionCodegen.endVisit(mv, toStringMethodName, getDeclaration());
|
||||||
@@ -175,41 +181,45 @@ public class FunctionsFromAnyGeneratorImpl extends FunctionsFromAnyGenerator {
|
|||||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||||
|
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
boolean first = true;
|
if (properties.isEmpty()) {
|
||||||
for (PropertyDescriptor propertyDescriptor : properties) {
|
iv.iconst(DescriptorUtils.getFqNameSafe(classDescriptor).asString().hashCode());
|
||||||
if (!first) {
|
} else {
|
||||||
iv.iconst(31);
|
boolean first = true;
|
||||||
iv.mul(Type.INT_TYPE);
|
for (PropertyDescriptor propertyDescriptor : properties) {
|
||||||
}
|
if (!first) {
|
||||||
|
iv.iconst(31);
|
||||||
|
iv.mul(Type.INT_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
JvmKotlinType propertyType = genOrLoadOnStack(iv, context, propertyDescriptor, 0);
|
JvmKotlinType propertyType = genOrLoadOnStack(iv, context, propertyDescriptor, 0);
|
||||||
KotlinType kotlinType = propertyDescriptor.getReturnType();
|
KotlinType kotlinType = propertyDescriptor.getReturnType();
|
||||||
Type asmType = typeMapper.mapType(kotlinType);
|
Type asmType = typeMapper.mapType(kotlinType);
|
||||||
StackValue.coerce(propertyType.getType(), propertyType.getKotlinType(), asmType, kotlinType, iv);
|
StackValue.coerce(propertyType.getType(), propertyType.getKotlinType(), asmType, kotlinType, iv);
|
||||||
|
|
||||||
Label ifNull = null;
|
Label ifNull = null;
|
||||||
if (!isPrimitive(asmType)) {
|
if (!isPrimitive(asmType)) {
|
||||||
ifNull = new Label();
|
ifNull = new Label();
|
||||||
iv.dup();
|
iv.dup();
|
||||||
iv.ifnull(ifNull);
|
iv.ifnull(ifNull);
|
||||||
}
|
}
|
||||||
|
|
||||||
genHashCode(mv, iv, asmType, generationState.getTarget());
|
genHashCode(mv, iv, asmType, generationState.getTarget());
|
||||||
|
|
||||||
if (ifNull != null) {
|
if (ifNull != null) {
|
||||||
Label end = new Label();
|
Label end = new Label();
|
||||||
iv.goTo(end);
|
iv.goTo(end);
|
||||||
iv.mark(ifNull);
|
iv.mark(ifNull);
|
||||||
iv.pop();
|
iv.pop();
|
||||||
iv.iconst(0);
|
iv.iconst(0);
|
||||||
iv.mark(end);
|
iv.mark(end);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (first) {
|
if (first) {
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
iv.add(Type.INT_TYPE);
|
iv.add(Type.INT_TYPE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+37
-3
@@ -6956,6 +6956,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
|||||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/dataClasses"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/dataClasses"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("companionDataObject.kt")
|
||||||
|
public void testCompanionDataObject() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/dataClasses/companionDataObject.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("componentNamedComponent1.kt")
|
@TestMetadata("componentNamedComponent1.kt")
|
||||||
public void testComponentNamedComponent1() throws Exception {
|
public void testComponentNamedComponent1() throws Exception {
|
||||||
@@ -7029,9 +7035,21 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("dataObject.kt")
|
@TestMetadata("dataObjectDisabled.kt")
|
||||||
public void testDataObject() throws Exception {
|
public void testDataObjectDisabled() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/dataClasses/dataObject.kt");
|
runTest("compiler/testData/diagnostics/tests/dataClasses/dataObjectDisabled.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("dataObjectEnabled.kt")
|
||||||
|
public void testDataObjectEnabled() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/dataClasses/dataObjectEnabled.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("dataObjectLiteral.kt")
|
||||||
|
public void testDataObjectLiteral() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/dataClasses/dataObjectLiteral.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -7655,6 +7673,22 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("compiler/testData/diagnostics/tests/dataObjects")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class DataObjects {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInDataObjects() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/dataObjects"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("overrideEqualsAndHashCode.kt")
|
||||||
|
public void testOverrideEqualsAndHashCode() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/dataObjects/overrideEqualsAndHashCode.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@TestMetadata("compiler/testData/diagnostics/tests/declarationChecks")
|
@TestMetadata("compiler/testData/diagnostics/tests/declarationChecks")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
|||||||
+37
-3
@@ -6956,6 +6956,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
|||||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/dataClasses"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/dataClasses"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("companionDataObject.kt")
|
||||||
|
public void testCompanionDataObject() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/dataClasses/companionDataObject.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("componentNamedComponent1.kt")
|
@TestMetadata("componentNamedComponent1.kt")
|
||||||
public void testComponentNamedComponent1() throws Exception {
|
public void testComponentNamedComponent1() throws Exception {
|
||||||
@@ -7029,9 +7035,21 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("dataObject.kt")
|
@TestMetadata("dataObjectDisabled.kt")
|
||||||
public void testDataObject() throws Exception {
|
public void testDataObjectDisabled() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/dataClasses/dataObject.kt");
|
runTest("compiler/testData/diagnostics/tests/dataClasses/dataObjectDisabled.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("dataObjectEnabled.kt")
|
||||||
|
public void testDataObjectEnabled() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/dataClasses/dataObjectEnabled.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("dataObjectLiteral.kt")
|
||||||
|
public void testDataObjectLiteral() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/dataClasses/dataObjectLiteral.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -7655,6 +7673,22 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("compiler/testData/diagnostics/tests/dataObjects")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class DataObjects {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInDataObjects() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/dataObjects"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("overrideEqualsAndHashCode.kt")
|
||||||
|
public void testOverrideEqualsAndHashCode() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/dataObjects/overrideEqualsAndHashCode.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@TestMetadata("compiler/testData/diagnostics/tests/declarationChecks")
|
@TestMetadata("compiler/testData/diagnostics/tests/declarationChecks")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
|||||||
+2
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.descriptors.EffectiveVisibility
|
|||||||
import org.jetbrains.kotlin.descriptors.Visibility
|
import org.jetbrains.kotlin.descriptors.Visibility
|
||||||
import org.jetbrains.kotlin.diagnostics.WhenMissingCase
|
import org.jetbrains.kotlin.diagnostics.WhenMissingCase
|
||||||
import org.jetbrains.kotlin.diagnostics.deprecationError2
|
import org.jetbrains.kotlin.diagnostics.deprecationError2
|
||||||
|
import org.jetbrains.kotlin.diagnostics.error0
|
||||||
import org.jetbrains.kotlin.fir.FirModuleData
|
import org.jetbrains.kotlin.fir.FirModuleData
|
||||||
import org.jetbrains.kotlin.fir.PrivateForInline
|
import org.jetbrains.kotlin.fir.PrivateForInline
|
||||||
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.*
|
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.*
|
||||||
@@ -901,6 +902,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
|||||||
val TAILREC_ON_VIRTUAL_MEMBER_ERROR by error<KtNamedFunction>(PositioningStrategy.TAILREC_MODIFIER)
|
val TAILREC_ON_VIRTUAL_MEMBER_ERROR by error<KtNamedFunction>(PositioningStrategy.TAILREC_MODIFIER)
|
||||||
val NON_TAIL_RECURSIVE_CALL by warning<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED)
|
val NON_TAIL_RECURSIVE_CALL by warning<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED)
|
||||||
val TAIL_RECURSION_IN_TRY_IS_NOT_SUPPORTED by warning<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED)
|
val TAIL_RECURSION_IN_TRY_IS_NOT_SUPPORTED by warning<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED)
|
||||||
|
val DATA_OBJECT_CUSTOM_EQUALS_OR_HASH_CODE by error<KtNamedFunction>(PositioningStrategy.OVERRIDE_MODIFIER)
|
||||||
}
|
}
|
||||||
|
|
||||||
val FUN_INTERFACES by object : DiagnosticGroup("Fun interfaces") {
|
val FUN_INTERFACES by object : DiagnosticGroup("Fun interfaces") {
|
||||||
|
|||||||
@@ -483,6 +483,7 @@ object FirErrors {
|
|||||||
val TAILREC_ON_VIRTUAL_MEMBER_ERROR by error0<KtNamedFunction>(SourceElementPositioningStrategies.TAILREC_MODIFIER)
|
val TAILREC_ON_VIRTUAL_MEMBER_ERROR by error0<KtNamedFunction>(SourceElementPositioningStrategies.TAILREC_MODIFIER)
|
||||||
val NON_TAIL_RECURSIVE_CALL by warning0<PsiElement>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
|
val NON_TAIL_RECURSIVE_CALL by warning0<PsiElement>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
|
||||||
val TAIL_RECURSION_IN_TRY_IS_NOT_SUPPORTED by warning0<PsiElement>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
|
val TAIL_RECURSION_IN_TRY_IS_NOT_SUPPORTED by warning0<PsiElement>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
|
||||||
|
val DATA_OBJECT_CUSTOM_EQUALS_OR_HASH_CODE by error0<KtNamedFunction>(SourceElementPositioningStrategies.OVERRIDE_MODIFIER)
|
||||||
|
|
||||||
// Fun interfaces
|
// Fun interfaces
|
||||||
val FUN_INTERFACE_CONSTRUCTOR_REFERENCE by error0<KtExpression>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
val FUN_INTERFACE_CONSTRUCTOR_REFERENCE by error0<KtExpression>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||||
|
|||||||
+1
@@ -54,6 +54,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
|||||||
FirTailrecFunctionChecker,
|
FirTailrecFunctionChecker,
|
||||||
FirTopLevelFunctionsChecker,
|
FirTopLevelFunctionsChecker,
|
||||||
FirMemberFunctionsChecker,
|
FirMemberFunctionsChecker,
|
||||||
|
FirDataObjectContentChecker,
|
||||||
)
|
)
|
||||||
|
|
||||||
override val propertyCheckers: Set<FirPropertyChecker>
|
override val propertyCheckers: Set<FirPropertyChecker>
|
||||||
|
|||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.KtFakeSourceElementKind
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
|
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||||
|
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.hasModifier
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||||
|
import org.jetbrains.kotlin.fir.types.isNullableAny
|
||||||
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
|
|
||||||
|
object FirDataObjectContentChecker : FirSimpleFunctionChecker() {
|
||||||
|
override fun check(declaration: FirSimpleFunction, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (!declaration.hasModifier(KtTokens.OVERRIDE_KEYWORD)) return
|
||||||
|
val source = declaration.source
|
||||||
|
if (source == null || source.kind is KtFakeSourceElementKind) return
|
||||||
|
|
||||||
|
val containingClass = context.containingDeclarations.lastOrNull() as? FirClass ?: return
|
||||||
|
if (containingClass.classKind != ClassKind.OBJECT || !containingClass.hasModifier(KtTokens.DATA_KEYWORD)) return
|
||||||
|
|
||||||
|
if (
|
||||||
|
(declaration.name == OperatorNameConventions.HASH_CODE && declaration.valueParameters.isEmpty()) ||
|
||||||
|
(declaration.name == OperatorNameConventions.EQUALS &&
|
||||||
|
declaration.valueParameters.singleOrNull()?.returnTypeRef?.isNullableAny == true)
|
||||||
|
) {
|
||||||
|
reporter.reportOn(source, FirErrors.DATA_OBJECT_CUSTOM_EQUALS_OR_HASH_CODE, context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
-1
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.KtFakeSourceElementKind
|
import org.jetbrains.kotlin.KtFakeSourceElementKind
|
||||||
import org.jetbrains.kotlin.KtSourceElement
|
import org.jetbrains.kotlin.KtSourceElement
|
||||||
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
|
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.Companion.classActualTargets
|
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.Companion.classActualTargets
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.FirModifier
|
import org.jetbrains.kotlin.fir.analysis.checkers.FirModifier
|
||||||
@@ -27,6 +28,7 @@ import org.jetbrains.kotlin.fir.declarations.utils.isLocal
|
|||||||
import org.jetbrains.kotlin.fir.languageVersionSettings
|
import org.jetbrains.kotlin.fir.languageVersionSettings
|
||||||
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
|
import org.jetbrains.kotlin.lexer.KtTokens.DATA_KEYWORD
|
||||||
import org.jetbrains.kotlin.resolve.*
|
import org.jetbrains.kotlin.resolve.*
|
||||||
|
|
||||||
object FirModifierChecker : FirBasicDeclarationChecker() {
|
object FirModifierChecker : FirBasicDeclarationChecker() {
|
||||||
@@ -182,7 +184,11 @@ object FirModifierChecker : FirBasicDeclarationChecker() {
|
|||||||
}
|
}
|
||||||
val set = map[modifierToken] ?: emptySet()
|
val set = map[modifierToken] ?: emptySet()
|
||||||
val checkResult = if (factory == FirErrors.WRONG_MODIFIER_TARGET) {
|
val checkResult = if (factory == FirErrors.WRONG_MODIFIER_TARGET) {
|
||||||
actualTargets.none { it in set }
|
actualTargets.none { it in set } ||
|
||||||
|
// TODO: Implement some generic feature-checking mechanism
|
||||||
|
(modifierToken == DATA_KEYWORD
|
||||||
|
&& actualTargets.contains(KotlinTarget.STANDALONE_OBJECT)
|
||||||
|
&& !context.languageVersionSettings.supportsFeature(LanguageFeature.DataObjects))
|
||||||
} else {
|
} else {
|
||||||
actualTargets.any { it in set }
|
actualTargets.any { it in set }
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -136,6 +136,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DATA_CLASS_NOT_PR
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DATA_CLASS_OVERRIDE_CONFLICT
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DATA_CLASS_OVERRIDE_CONFLICT
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DATA_CLASS_VARARG_PARAMETER
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DATA_CLASS_VARARG_PARAMETER
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DATA_CLASS_WITHOUT_PARAMETERS
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DATA_CLASS_WITHOUT_PARAMETERS
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DATA_OBJECT_CUSTOM_EQUALS_OR_HASH_CODE
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DECLARATION_CANT_BE_INLINED
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DECLARATION_CANT_BE_INLINED
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DELEGATED_PROPERTY_INSIDE_VALUE_CLASS
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DELEGATED_PROPERTY_INSIDE_VALUE_CLASS
|
||||||
@@ -579,7 +580,6 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_MODIFIER_TA
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_NUMBER_OF_TYPE_ARGUMENTS
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_NUMBER_OF_TYPE_ARGUMENTS
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_SETTER_PARAMETER_TYPE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_SETTER_PARAMETER_TYPE
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_SETTER_RETURN_TYPE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_SETTER_RETURN_TYPE
|
||||||
import org.jetbrains.kotlin.psi.KtReferenceExpression
|
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
||||||
@@ -1456,6 +1456,7 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
|||||||
map.put(TAILREC_ON_VIRTUAL_MEMBER_ERROR, "Tailrec is not allowed on open members")
|
map.put(TAILREC_ON_VIRTUAL_MEMBER_ERROR, "Tailrec is not allowed on open members")
|
||||||
map.put(NON_TAIL_RECURSIVE_CALL, "Recursive call is not a tail call")
|
map.put(NON_TAIL_RECURSIVE_CALL, "Recursive call is not a tail call")
|
||||||
map.put(TAIL_RECURSION_IN_TRY_IS_NOT_SUPPORTED, "Tail recursion optimization inside try/catch/finally is not supported")
|
map.put(TAIL_RECURSION_IN_TRY_IS_NOT_SUPPORTED, "Tail recursion optimization inside try/catch/finally is not supported")
|
||||||
|
map.put(DATA_OBJECT_CUSTOM_EQUALS_OR_HASH_CODE, "Data object cannot have a custom implementation of 'equals' or 'hashCode'")
|
||||||
|
|
||||||
// Fun interfaces
|
// Fun interfaces
|
||||||
map.put(FUN_INTERFACE_CONSTRUCTOR_REFERENCE, "Functional/SAM interface constructor references are prohibited")
|
map.put(FUN_INTERFACE_CONSTRUCTOR_REFERENCE, "Functional/SAM interface constructor references are prohibited")
|
||||||
|
|||||||
+1
-3
@@ -87,6 +87,7 @@ class DataClassMembersGenerator(val components: Fir2IrComponents) : Fir2IrCompon
|
|||||||
IrGeneratorContextBase(components.irBuiltIns),
|
IrGeneratorContextBase(components.irBuiltIns),
|
||||||
components.symbolTable,
|
components.symbolTable,
|
||||||
irClass,
|
irClass,
|
||||||
|
irClass.kotlinFqName,
|
||||||
origin
|
origin
|
||||||
) {
|
) {
|
||||||
override fun declareSimpleFunction(startOffset: Int, endOffset: Int, functionDescriptor: FunctionDescriptor): IrFunction {
|
override fun declareSimpleFunction(startOffset: Int, endOffset: Int, functionDescriptor: FunctionDescriptor): IrFunction {
|
||||||
@@ -183,9 +184,6 @@ class DataClassMembersGenerator(val components: Fir2IrComponents) : Fir2IrCompon
|
|||||||
fun generate(klass: FirClass): List<FirDeclaration> {
|
fun generate(klass: FirClass): List<FirDeclaration> {
|
||||||
val propertyParametersCount = irClass.primaryConstructor?.explicitParameters?.size ?: 0
|
val propertyParametersCount = irClass.primaryConstructor?.explicitParameters?.size ?: 0
|
||||||
val properties = irClass.properties.filter { it.backingField != null }.take(propertyParametersCount).toList()
|
val properties = irClass.properties.filter { it.backingField != null }.take(propertyParametersCount).toList()
|
||||||
if (properties.isEmpty()) {
|
|
||||||
return emptyList()
|
|
||||||
}
|
|
||||||
|
|
||||||
val result = mutableListOf<FirDeclaration>()
|
val result = mutableListOf<FirDeclaration>()
|
||||||
|
|
||||||
|
|||||||
+40
@@ -13648,6 +13648,46 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/dataObjects")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class DataObjects {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInDataObjects() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/dataObjects"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("equals.kt")
|
||||||
|
public void testEquals() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/dataObjects/equals.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("hashCode.kt")
|
||||||
|
public void testHashCode() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/dataObjects/hashCode.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("multipleInstances.kt")
|
||||||
|
public void testMultipleInstances() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/dataObjects/multipleInstances.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serialization.kt")
|
||||||
|
public void testSerialization() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/dataObjects/serialization.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("toString.kt")
|
||||||
|
public void testToString() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/dataObjects/toString.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@TestMetadata("compiler/testData/codegen/box/deadCodeElimination")
|
@TestMetadata("compiler/testData/codegen/box/deadCodeElimination")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
|||||||
+6
-2
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.builder
|
|||||||
import com.intellij.psi.tree.IElementType
|
import com.intellij.psi.tree.IElementType
|
||||||
import org.jetbrains.kotlin.*
|
import org.jetbrains.kotlin.*
|
||||||
import org.jetbrains.kotlin.KtNodeTypes.*
|
import org.jetbrains.kotlin.KtNodeTypes.*
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
import org.jetbrains.kotlin.fir.*
|
import org.jetbrains.kotlin.fir.*
|
||||||
@@ -38,6 +39,7 @@ import org.jetbrains.kotlin.name.FqName
|
|||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.name.SpecialNames
|
import org.jetbrains.kotlin.name.SpecialNames
|
||||||
import org.jetbrains.kotlin.parsing.*
|
import org.jetbrains.kotlin.parsing.*
|
||||||
|
import org.jetbrains.kotlin.psi.KtObjectDeclaration
|
||||||
import org.jetbrains.kotlin.psi.KtPsiUtil
|
import org.jetbrains.kotlin.psi.KtPsiUtil
|
||||||
import org.jetbrains.kotlin.types.ConstantValueKind
|
import org.jetbrains.kotlin.types.ConstantValueKind
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
@@ -1078,8 +1080,10 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
|
|||||||
private val createParameterTypeRefWithSourceKind: (FirProperty, KtFakeSourceElementKind) -> FirTypeRef,
|
private val createParameterTypeRefWithSourceKind: (FirProperty, KtFakeSourceElementKind) -> FirTypeRef,
|
||||||
) {
|
) {
|
||||||
fun generate() {
|
fun generate() {
|
||||||
generateComponentFunctions()
|
if (classBuilder.classKind != ClassKind.OBJECT) {
|
||||||
generateCopyFunction()
|
generateComponentFunctions()
|
||||||
|
generateCopyFunction()
|
||||||
|
}
|
||||||
// Refer to (IR utils or FIR backend) DataClassMembersGenerator for generating equals, hashCode, and toString
|
// Refer to (IR utils or FIR backend) DataClassMembersGenerator for generating equals, hashCode, and toString
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -737,6 +737,7 @@ public interface Errors {
|
|||||||
DiagnosticFactory0<PsiElement> DATA_CLASS_WITHOUT_PARAMETERS = DiagnosticFactory0.create(ERROR);
|
DiagnosticFactory0<PsiElement> DATA_CLASS_WITHOUT_PARAMETERS = DiagnosticFactory0.create(ERROR);
|
||||||
DiagnosticFactory0<KtParameter> DATA_CLASS_VARARG_PARAMETER = DiagnosticFactory0.create(ERROR);
|
DiagnosticFactory0<KtParameter> DATA_CLASS_VARARG_PARAMETER = DiagnosticFactory0.create(ERROR);
|
||||||
DiagnosticFactory0<KtParameter> DATA_CLASS_NOT_PROPERTY_PARAMETER = DiagnosticFactory0.create(ERROR);
|
DiagnosticFactory0<KtParameter> DATA_CLASS_NOT_PROPERTY_PARAMETER = DiagnosticFactory0.create(ERROR);
|
||||||
|
DiagnosticFactory0<PsiElement> DATA_OBJECT_CUSTOM_EQUALS_OR_HASH_CODE = DiagnosticFactory0.create(ERROR);
|
||||||
|
|
||||||
DiagnosticFactory0<KtParameter> CATCH_PARAMETER_WITH_DEFAULT_VALUE = DiagnosticFactory0.create(ERROR);
|
DiagnosticFactory0<KtParameter> CATCH_PARAMETER_WITH_DEFAULT_VALUE = DiagnosticFactory0.create(ERROR);
|
||||||
|
|
||||||
|
|||||||
+1
@@ -1058,6 +1058,7 @@ public class DefaultErrorMessages {
|
|||||||
MAP.put(DATA_CLASS_WITHOUT_PARAMETERS, "Data class must have at least one primary constructor parameter");
|
MAP.put(DATA_CLASS_WITHOUT_PARAMETERS, "Data class must have at least one primary constructor parameter");
|
||||||
MAP.put(DATA_CLASS_VARARG_PARAMETER, "Primary constructor vararg parameters are forbidden for data classes");
|
MAP.put(DATA_CLASS_VARARG_PARAMETER, "Primary constructor vararg parameters are forbidden for data classes");
|
||||||
MAP.put(DATA_CLASS_NOT_PROPERTY_PARAMETER, "Data class primary constructor must only have property (val / var) parameters");
|
MAP.put(DATA_CLASS_NOT_PROPERTY_PARAMETER, "Data class primary constructor must only have property (val / var) parameters");
|
||||||
|
MAP.put(DATA_OBJECT_CUSTOM_EQUALS_OR_HASH_CODE, "Data object cannot have a custom implementation of 'equals' or 'hashCode'");
|
||||||
|
|
||||||
MAP.put(CATCH_PARAMETER_WITH_DEFAULT_VALUE, "Catch clause parameter may not have a default value");
|
MAP.put(CATCH_PARAMETER_WITH_DEFAULT_VALUE, "Catch clause parameter may not have a default value");
|
||||||
|
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ private val DEFAULT_DECLARATION_CHECKERS = listOf(
|
|||||||
ValueParameterUsageInDefaultArgumentChecker,
|
ValueParameterUsageInDefaultArgumentChecker,
|
||||||
CyclicAnnotationsChecker,
|
CyclicAnnotationsChecker,
|
||||||
UnsupportedUntilRangeDeclarationChecker,
|
UnsupportedUntilRangeDeclarationChecker,
|
||||||
|
DataObjectContentChecker,
|
||||||
)
|
)
|
||||||
|
|
||||||
private val DEFAULT_CALL_CHECKERS = listOf(
|
private val DEFAULT_CALL_CHECKERS = listOf(
|
||||||
|
|||||||
+2
-1
@@ -17,6 +17,7 @@
|
|||||||
package org.jetbrains.kotlin.resolve.checkers
|
package org.jetbrains.kotlin.resolve.checkers
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors
|
import org.jetbrains.kotlin.diagnostics.Errors
|
||||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
@@ -27,7 +28,7 @@ class DataClassDeclarationChecker : DeclarationChecker {
|
|||||||
if (descriptor !is ClassDescriptor) return
|
if (descriptor !is ClassDescriptor) return
|
||||||
if (declaration !is KtClassOrObject) return
|
if (declaration !is KtClassOrObject) return
|
||||||
|
|
||||||
if (descriptor.isData) {
|
if (descriptor.isData && descriptor.kind == ClassKind.CLASS) {
|
||||||
if (descriptor.unsubstitutedPrimaryConstructor == null && descriptor.constructors.isNotEmpty()) {
|
if (descriptor.unsubstitutedPrimaryConstructor == null && descriptor.constructors.isNotEmpty()) {
|
||||||
declaration.nameIdentifier?.let { context.trace.report(Errors.PRIMARY_CONSTRUCTOR_REQUIRED_FOR_DATA_CLASS.on(it)) }
|
declaration.nameIdentifier?.let { context.trace.report(Errors.PRIMARY_CONSTRUCTOR_REQUIRED_FOR_DATA_CLASS.on(it)) }
|
||||||
}
|
}
|
||||||
|
|||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.resolve.checkers
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.diagnostics.Errors
|
||||||
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
|
|
||||||
|
object DataObjectContentChecker : DeclarationChecker {
|
||||||
|
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||||
|
if (descriptor !is FunctionDescriptor) return
|
||||||
|
if (descriptor.name != OperatorNameConventions.EQUALS && descriptor.name != OperatorNameConventions.HASH_CODE) return
|
||||||
|
|
||||||
|
val container = descriptor.containingDeclaration
|
||||||
|
if (container !is ClassDescriptor) return
|
||||||
|
if (!container.isData || container.kind != ClassKind.OBJECT) return
|
||||||
|
|
||||||
|
if (DescriptorUtils.getAllOverriddenDescriptors(descriptor).any(::isDeclaredInAny)) {
|
||||||
|
val target = declaration.modifierList?.getModifier(KtTokens.OVERRIDE_KEYWORD) ?: declaration
|
||||||
|
context.trace.report(Errors.DATA_OBJECT_CUSTOM_EQUALS_OR_HASH_CODE.on(target))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isDeclaredInAny(descriptor: FunctionDescriptor): Boolean {
|
||||||
|
val container = descriptor.containingDeclaration
|
||||||
|
return container is ClassDescriptor && KotlinBuiltIns.isAny(container)
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -482,7 +482,7 @@ open class LazyClassMemberScope(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun addDataClassMethods(result: MutableCollection<DeclarationDescriptor>, location: LookupLocation) {
|
private fun addDataClassMethods(result: MutableCollection<DeclarationDescriptor>, location: LookupLocation) {
|
||||||
if (!thisDescriptor.isData) return
|
if (!thisDescriptor.isData || thisDescriptor.kind != ClassKind.CLASS) return
|
||||||
|
|
||||||
if (getPrimaryConstructor() == null) return
|
if (getPrimaryConstructor() == null) return
|
||||||
|
|
||||||
|
|||||||
+2
-5
@@ -14,17 +14,13 @@ import org.jetbrains.kotlin.ir.builders.*
|
|||||||
import org.jetbrains.kotlin.ir.builders.declarations.addFunction
|
import org.jetbrains.kotlin.ir.builders.declarations.addFunction
|
||||||
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
|
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
|
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.IrType
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
import org.jetbrains.kotlin.ir.types.classOrNull
|
import org.jetbrains.kotlin.ir.types.classOrNull
|
||||||
import org.jetbrains.kotlin.ir.types.getClass
|
import org.jetbrains.kotlin.ir.types.getClass
|
||||||
import org.jetbrains.kotlin.ir.types.isArray
|
import org.jetbrains.kotlin.ir.types.isArray
|
||||||
import org.jetbrains.kotlin.ir.util.DataClassMembersGenerator
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.util.SYNTHETIC_OFFSET
|
|
||||||
import org.jetbrains.kotlin.ir.util.functions
|
|
||||||
import org.jetbrains.kotlin.ir.util.isPrimitiveArray
|
|
||||||
|
|
||||||
class MethodsFromAnyGeneratorForLowerings(val context: BackendContext, val irClass: IrClass, val origin: IrDeclarationOrigin) {
|
class MethodsFromAnyGeneratorForLowerings(val context: BackendContext, val irClass: IrClass, val origin: IrDeclarationOrigin) {
|
||||||
private fun IrClass.addSyntheticFunction(name: String, returnType: IrType) =
|
private fun IrClass.addSyntheticFunction(name: String, returnType: IrType) =
|
||||||
@@ -74,6 +70,7 @@ open class LoweringDataClassMemberGenerator(
|
|||||||
IrGeneratorContextBase(backendContext.irBuiltIns),
|
IrGeneratorContextBase(backendContext.irBuiltIns),
|
||||||
backendContext.ir.symbols.externalSymbolTable,
|
backendContext.ir.symbols.externalSymbolTable,
|
||||||
irClass,
|
irClass,
|
||||||
|
irClass.kotlinFqName,
|
||||||
origin,
|
origin,
|
||||||
forbidDirectFieldAccess
|
forbidDirectFieldAccess
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -353,6 +353,7 @@ private val jvmFilePhases = listOf(
|
|||||||
|
|
||||||
enumClassPhase,
|
enumClassPhase,
|
||||||
objectClassPhase,
|
objectClassPhase,
|
||||||
|
readResolveForDataObjectsPhase,
|
||||||
staticInitializersPhase,
|
staticInitializersPhase,
|
||||||
initializersPhase,
|
initializersPhase,
|
||||||
initializersCleanupPhase,
|
initializersCleanupPhase,
|
||||||
|
|||||||
+63
@@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.backend.jvm.lower
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
|
||||||
|
import org.jetbrains.kotlin.backend.common.ir.addDispatchReceiver
|
||||||
|
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.ir.createJvmIrBuilder
|
||||||
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
|
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||||
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
|
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
|
||||||
|
import org.jetbrains.kotlin.ir.builders.irExprBody
|
||||||
|
import org.jetbrains.kotlin.ir.builders.irGetField
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||||
|
import org.jetbrains.kotlin.ir.util.defaultType
|
||||||
|
import org.jetbrains.kotlin.ir.util.fields
|
||||||
|
import org.jetbrains.kotlin.ir.util.getAllSuperclasses
|
||||||
|
import org.jetbrains.kotlin.ir.util.hasEqualFqName
|
||||||
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
|
internal val readResolveForDataObjectsPhase = makeIrFilePhase(
|
||||||
|
::ReadResolveForDataObjectsLowering,
|
||||||
|
name = "ReadResolveForDataObjectsLowering",
|
||||||
|
description = "Generate readResolve for serializable data objects"
|
||||||
|
)
|
||||||
|
|
||||||
|
private class ReadResolveForDataObjectsLowering(val context: JvmBackendContext) : ClassLoweringPass {
|
||||||
|
override fun lower(irClass: IrClass) {
|
||||||
|
if (!context.state.languageVersionSettings.supportsFeature(LanguageFeature.DataObjects)) return
|
||||||
|
|
||||||
|
if (!irClass.isData || irClass.kind != ClassKind.OBJECT || !irClass.isSerializable()) return
|
||||||
|
|
||||||
|
context.irFactory.buildFun {
|
||||||
|
name = Name.identifier("readResolve")
|
||||||
|
modality = Modality.FINAL
|
||||||
|
origin = IrDeclarationOrigin.GENERATED_DATA_CLASS_MEMBER
|
||||||
|
returnType = context.irBuiltIns.anyType
|
||||||
|
visibility = DescriptorVisibilities.PRIVATE
|
||||||
|
}.apply {
|
||||||
|
addDispatchReceiver { type = irClass.defaultType }
|
||||||
|
parent = irClass
|
||||||
|
body = context.createJvmIrBuilder(symbol).run {
|
||||||
|
val instanceField = irClass.fields.single { it.name.asString() == JvmAbi.INSTANCE_FIELD }
|
||||||
|
irExprBody(irGetField(null, instanceField))
|
||||||
|
}
|
||||||
|
irClass.declarations.add(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val SERIALIZABLE_FQ_NAME = FqName("java.io.Serializable")
|
||||||
|
|
||||||
|
private fun IrClass.isSerializable(): Boolean =
|
||||||
|
getAllSuperclasses().any { it.hasEqualFqName(SERIALIZABLE_FQ_NAME) }
|
||||||
+3
-2
@@ -74,8 +74,9 @@ class DataClassMembersGenerator(
|
|||||||
val origin: IrDeclarationOrigin
|
val origin: IrDeclarationOrigin
|
||||||
) : DataClassMethodGenerator(ktClassOrObject, declarationGenerator.context.bindingContext) {
|
) : DataClassMethodGenerator(ktClassOrObject, declarationGenerator.context.bindingContext) {
|
||||||
|
|
||||||
private val irDataClassMembersGenerator =
|
private val irDataClassMembersGenerator = object : DataClassMembersGenerator(
|
||||||
object : DataClassMembersGenerator(context, context.symbolTable, irClass, origin, generateBodies = generateBodies) {
|
context, context.symbolTable, irClass, ktClassOrObject.fqName, origin, generateBodies = generateBodies
|
||||||
|
) {
|
||||||
override fun declareSimpleFunction(startOffset: Int, endOffset: Int, functionDescriptor: FunctionDescriptor): IrFunction =
|
override fun declareSimpleFunction(startOffset: Int, endOffset: Int, functionDescriptor: FunctionDescriptor): IrFunction =
|
||||||
declareSimpleFunction(startOffset, endOffset, origin, functionDescriptor)
|
declareSimpleFunction(startOffset, endOffset, origin, functionDescriptor)
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
|
|||||||
import org.jetbrains.kotlin.ir.types.IrType
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
import org.jetbrains.kotlin.ir.types.classifierOrNull
|
import org.jetbrains.kotlin.ir.types.classifierOrNull
|
||||||
import org.jetbrains.kotlin.ir.types.isNullable
|
import org.jetbrains.kotlin.ir.types.isNullable
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -32,6 +33,7 @@ abstract class DataClassMembersGenerator(
|
|||||||
val context: IrGeneratorContext,
|
val context: IrGeneratorContext,
|
||||||
val symbolTable: ReferenceSymbolTable,
|
val symbolTable: ReferenceSymbolTable,
|
||||||
val irClass: IrClass,
|
val irClass: IrClass,
|
||||||
|
val fqName: FqName?,
|
||||||
val origin: IrDeclarationOrigin,
|
val origin: IrDeclarationOrigin,
|
||||||
val forbidDirectFieldAccess: Boolean = false,
|
val forbidDirectFieldAccess: Boolean = false,
|
||||||
val generateBodies: Boolean = false
|
val generateBodies: Boolean = false
|
||||||
@@ -139,9 +141,9 @@ abstract class DataClassMembersGenerator(
|
|||||||
+irReturnTrue()
|
+irReturnTrue()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateHashCodeMethodBody(properties: List<IrProperty>) {
|
fun generateHashCodeMethodBody(properties: List<IrProperty>, constHashCode: Int) {
|
||||||
if (properties.isEmpty()) {
|
if (properties.isEmpty()) {
|
||||||
+irReturn(irInt(0))
|
+irReturn(irInt(constHashCode))
|
||||||
return
|
return
|
||||||
} else if (properties.size == 1) {
|
} else if (properties.size == 1) {
|
||||||
+irReturn(getHashCodeOfProperty(properties[0]))
|
+irReturn(getHashCodeOfProperty(properties[0]))
|
||||||
@@ -186,6 +188,10 @@ abstract class DataClassMembersGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun generateToStringMethodBody(properties: List<IrProperty>) {
|
fun generateToStringMethodBody(properties: List<IrProperty>) {
|
||||||
|
if (properties.isEmpty() && irClass.kind == ClassKind.OBJECT) {
|
||||||
|
+irReturn(irString(irClass.name.asString()))
|
||||||
|
return
|
||||||
|
}
|
||||||
val irConcat = irConcat()
|
val irConcat = irConcat()
|
||||||
irConcat.addArgument(irString(irClass.classNameForToString() + "("))
|
irConcat.addArgument(irString(irClass.classNameForToString() + "("))
|
||||||
var first = true
|
var first = true
|
||||||
@@ -259,6 +265,7 @@ abstract class DataClassMembersGenerator(
|
|||||||
) {
|
) {
|
||||||
MemberFunctionBuilder(startOffset, endOffset, declareSimpleFunction(startOffset, endOffset, function)).addToClass { irFunction ->
|
MemberFunctionBuilder(startOffset, endOffset, declareSimpleFunction(startOffset, endOffset, function)).addToClass { irFunction ->
|
||||||
irFunction.buildWithScope {
|
irFunction.buildWithScope {
|
||||||
|
irFunction.parent = irClass
|
||||||
generateSyntheticFunctionParameterDeclarations(irFunction)
|
generateSyntheticFunctionParameterDeclarations(irFunction)
|
||||||
body(irFunction)
|
body(irFunction)
|
||||||
}
|
}
|
||||||
@@ -344,14 +351,20 @@ abstract class DataClassMembersGenerator(
|
|||||||
// Entry for psi2ir
|
// Entry for psi2ir
|
||||||
fun generateHashCodeMethod(function: FunctionDescriptor, properties: List<PropertyDescriptor>) {
|
fun generateHashCodeMethod(function: FunctionDescriptor, properties: List<PropertyDescriptor>) {
|
||||||
buildMember(function) {
|
buildMember(function) {
|
||||||
generateHashCodeMethodBody(properties.map { getIrProperty(it) })
|
generateHashCodeMethodBody(
|
||||||
|
properties.map { getIrProperty(it) },
|
||||||
|
if (irClass.kind == ClassKind.OBJECT && irClass.isData) fqName.hashCode() else 0
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Entry for fir2ir
|
// Entry for fir2ir
|
||||||
fun generateHashCodeMethod(irFunction: IrFunction, properties: List<IrProperty>) {
|
fun generateHashCodeMethod(irFunction: IrFunction, properties: List<IrProperty>) {
|
||||||
buildMember(irFunction) {
|
buildMember(irFunction) {
|
||||||
generateHashCodeMethodBody(properties)
|
generateHashCodeMethodBody(
|
||||||
|
properties,
|
||||||
|
if (irClass.kind == ClassKind.OBJECT && irClass.isData) fqName.hashCode() else 0
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ open class KtClass : KtClassOrObject {
|
|||||||
_stub?.isInterface() ?: (findChildByType<PsiElement>(KtTokens.INTERFACE_KEYWORD) != null)
|
_stub?.isInterface() ?: (findChildByType<PsiElement>(KtTokens.INTERFACE_KEYWORD) != null)
|
||||||
|
|
||||||
fun isEnum(): Boolean = hasModifier(KtTokens.ENUM_KEYWORD)
|
fun isEnum(): Boolean = hasModifier(KtTokens.ENUM_KEYWORD)
|
||||||
fun isData(): Boolean = hasModifier(KtTokens.DATA_KEYWORD)
|
|
||||||
fun isSealed(): Boolean = hasModifier(KtTokens.SEALED_KEYWORD)
|
fun isSealed(): Boolean = hasModifier(KtTokens.SEALED_KEYWORD)
|
||||||
fun isInner(): Boolean = hasModifier(KtTokens.INNER_KEYWORD)
|
fun isInner(): Boolean = hasModifier(KtTokens.INNER_KEYWORD)
|
||||||
fun isInline(): Boolean = hasModifier(KtTokens.INLINE_KEYWORD)
|
fun isInline(): Boolean = hasModifier(KtTokens.INLINE_KEYWORD)
|
||||||
|
|||||||
@@ -100,6 +100,8 @@ abstract class KtClassOrObject :
|
|||||||
|
|
||||||
override fun isLocal(): Boolean = stub?.isLocal() ?: KtPsiUtil.isLocal(this)
|
override fun isLocal(): Boolean = stub?.isLocal() ?: KtPsiUtil.isLocal(this)
|
||||||
|
|
||||||
|
fun isData(): Boolean = hasModifier(KtTokens.DATA_KEYWORD)
|
||||||
|
|
||||||
override fun getDeclarations(): List<KtDeclaration> = getBody()?.declarations.orEmpty()
|
override fun getDeclarations(): List<KtDeclaration> = getBody()?.declarations.orEmpty()
|
||||||
|
|
||||||
override fun getPresentation(): ItemPresentation? = ItemPresentationProviders.getItemPresentation(this)
|
override fun getPresentation(): ItemPresentation? = ItemPresentationProviders.getItemPresentation(this)
|
||||||
|
|||||||
@@ -132,7 +132,8 @@ val featureDependencies = mapOf(
|
|||||||
EXPECT_KEYWORD to listOf(LanguageFeature.MultiPlatformProjects),
|
EXPECT_KEYWORD to listOf(LanguageFeature.MultiPlatformProjects),
|
||||||
ACTUAL_KEYWORD to listOf(LanguageFeature.MultiPlatformProjects),
|
ACTUAL_KEYWORD to listOf(LanguageFeature.MultiPlatformProjects),
|
||||||
LATEINIT_KEYWORD to listOf(LanguageFeature.LateinitTopLevelProperties, LanguageFeature.LateinitLocalVariables),
|
LATEINIT_KEYWORD to listOf(LanguageFeature.LateinitTopLevelProperties, LanguageFeature.LateinitLocalVariables),
|
||||||
FUN_KEYWORD to listOf(LanguageFeature.FunctionalInterfaceConversion)
|
FUN_KEYWORD to listOf(LanguageFeature.FunctionalInterfaceConversion),
|
||||||
|
DATA_KEYWORD to listOf(LanguageFeature.DataObjects)
|
||||||
)
|
)
|
||||||
|
|
||||||
val featureDependenciesTargets = mapOf(
|
val featureDependenciesTargets = mapOf(
|
||||||
@@ -141,7 +142,8 @@ val featureDependenciesTargets = mapOf(
|
|||||||
LanguageFeature.LateinitTopLevelProperties to setOf(KotlinTarget.TOP_LEVEL_PROPERTY),
|
LanguageFeature.LateinitTopLevelProperties to setOf(KotlinTarget.TOP_LEVEL_PROPERTY),
|
||||||
LanguageFeature.InlineClasses to setOf(KotlinTarget.CLASS_ONLY),
|
LanguageFeature.InlineClasses to setOf(KotlinTarget.CLASS_ONLY),
|
||||||
LanguageFeature.JvmInlineValueClasses to setOf(KotlinTarget.CLASS_ONLY),
|
LanguageFeature.JvmInlineValueClasses to setOf(KotlinTarget.CLASS_ONLY),
|
||||||
LanguageFeature.FunctionalInterfaceConversion to setOf(KotlinTarget.INTERFACE)
|
LanguageFeature.FunctionalInterfaceConversion to setOf(KotlinTarget.INTERFACE),
|
||||||
|
LanguageFeature.DataObjects to setOf(KotlinTarget.STANDALONE_OBJECT)
|
||||||
)
|
)
|
||||||
|
|
||||||
val defaultVisibilityTargets: EnumSet<KotlinTarget> = EnumSet.of(
|
val defaultVisibilityTargets: EnumSet<KotlinTarget> = EnumSet.of(
|
||||||
@@ -204,7 +206,7 @@ val possibleTargetMap = mapOf(
|
|||||||
KotlinTarget.LOCAL_VARIABLE,
|
KotlinTarget.LOCAL_VARIABLE,
|
||||||
KotlinTarget.BACKING_FIELD
|
KotlinTarget.BACKING_FIELD
|
||||||
),
|
),
|
||||||
DATA_KEYWORD to EnumSet.of(KotlinTarget.CLASS_ONLY, KotlinTarget.LOCAL_CLASS),
|
DATA_KEYWORD to EnumSet.of(KotlinTarget.CLASS_ONLY, KotlinTarget.LOCAL_CLASS, KotlinTarget.STANDALONE_OBJECT),
|
||||||
INLINE_KEYWORD to EnumSet.of(
|
INLINE_KEYWORD to EnumSet.of(
|
||||||
KotlinTarget.FUNCTION,
|
KotlinTarget.FUNCTION,
|
||||||
KotlinTarget.PROPERTY,
|
KotlinTarget.PROPERTY,
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
// LANGUAGE: +DataObjects
|
||||||
|
// WITH_STDLIB
|
||||||
|
|
||||||
|
package com.example
|
||||||
|
|
||||||
|
import kotlin.test.*
|
||||||
|
|
||||||
|
data object DataObject
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
assertEquals(DataObject, DataObject)
|
||||||
|
assertFalse(DataObject == null)
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
// LANGUAGE: +DataObjects
|
||||||
|
// WITH_STDLIB
|
||||||
|
|
||||||
|
package com.example
|
||||||
|
|
||||||
|
import kotlin.test.*
|
||||||
|
|
||||||
|
data object DataObject {
|
||||||
|
data object Inner
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
assertEquals(DataObject.hashCode(), DataObject.hashCode())
|
||||||
|
assertNotEquals(DataObject.hashCode(), DataObject.Inner.hashCode())
|
||||||
|
assertNotEquals(0, DataObject.hashCode())
|
||||||
|
assertNotEquals(0, DataObject.Inner.hashCode())
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
// LANGUAGE: +DataObjects
|
||||||
|
// WITH_STDLIB
|
||||||
|
// TARGET_BACKEND: JVM_IR
|
||||||
|
|
||||||
|
import kotlin.test.*
|
||||||
|
|
||||||
|
data object DataObject
|
||||||
|
|
||||||
|
val doppelganger = DataObject::class.java.declaredConstructors[0].apply { isAccessible = true }.newInstance()
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
assertFalse(DataObject === doppelganger)
|
||||||
|
assertEquals(DataObject, doppelganger)
|
||||||
|
assertEquals(DataObject.hashCode(), DataObject::class.java.cast(doppelganger).hashCode())
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
// LANGUAGE: +DataObjects
|
||||||
|
// WITH_STDLIB
|
||||||
|
// TARGET_BACKEND: JVM_IR
|
||||||
|
// FULL_JDK
|
||||||
|
// CHECK_BYTECODE_LISTING
|
||||||
|
|
||||||
|
import java.io.*
|
||||||
|
|
||||||
|
data object NonSerializableDataObject
|
||||||
|
|
||||||
|
data object SerializableDataObject: Serializable
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
ByteArrayOutputStream().use { baos ->
|
||||||
|
ObjectOutputStream(baos).use { oos -> oos.writeObject(SerializableDataObject) }
|
||||||
|
ByteArrayInputStream(baos.toByteArray()).use { bais -> assert(java.io.ObjectInputStream(bais).readObject() === SerializableDataObject) }
|
||||||
|
}
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
public final class NonSerializableDataObject {
|
||||||
|
// source: 'serialization.kt'
|
||||||
|
public final static @org.jetbrains.annotations.NotNull field INSTANCE: NonSerializableDataObject
|
||||||
|
static method <clinit>(): void
|
||||||
|
private method <init>(): void
|
||||||
|
public method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean
|
||||||
|
public method hashCode(): int
|
||||||
|
public @org.jetbrains.annotations.NotNull method toString(): java.lang.String
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class SerializableDataObject {
|
||||||
|
// source: 'serialization.kt'
|
||||||
|
public final static @org.jetbrains.annotations.NotNull field INSTANCE: SerializableDataObject
|
||||||
|
static method <clinit>(): void
|
||||||
|
private method <init>(): void
|
||||||
|
public method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean
|
||||||
|
public method hashCode(): int
|
||||||
|
private final method readResolve(): java.lang.Object
|
||||||
|
public @org.jetbrains.annotations.NotNull method toString(): java.lang.String
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class SerializationKt {
|
||||||
|
// source: 'serialization.kt'
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
// LANGUAGE: +DataObjects
|
||||||
|
// WITH_STDLIB
|
||||||
|
|
||||||
|
package com.example
|
||||||
|
|
||||||
|
import kotlin.test.*
|
||||||
|
|
||||||
|
data object DataObject {
|
||||||
|
data object Nested
|
||||||
|
}
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
data object Inner
|
||||||
|
}
|
||||||
|
|
||||||
|
data object Declared {
|
||||||
|
override fun toString() = "Overriden"
|
||||||
|
}
|
||||||
|
|
||||||
|
open class WithFinalToString {
|
||||||
|
final override fun toString() = "FinalToString"
|
||||||
|
}
|
||||||
|
|
||||||
|
data object InheritedFromClassWithFinalToString: WithFinalToString()
|
||||||
|
|
||||||
|
open class WithOpenToString {
|
||||||
|
override fun toString() = "OpenToString"
|
||||||
|
}
|
||||||
|
|
||||||
|
data object InheritedFromClassWithOpenToString: WithOpenToString()
|
||||||
|
|
||||||
|
abstract class WithAbstractToString {
|
||||||
|
abstract override fun toString(): String
|
||||||
|
}
|
||||||
|
|
||||||
|
data object InheritedFromClassWithAbstractToString : WithAbstractToString()
|
||||||
|
|
||||||
|
class C {
|
||||||
|
companion object CC
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
assertEquals("DataObject", DataObject.toString())
|
||||||
|
assertEquals("Nested", DataObject.Nested.toString())
|
||||||
|
assertEquals("Inner", Foo.Inner.toString())
|
||||||
|
assertEquals("Overriden", Declared.toString())
|
||||||
|
assertEquals("FinalToString", InheritedFromClassWithFinalToString.toString())
|
||||||
|
assertEquals("InheritedFromClassWithOpenToString", InheritedFromClassWithOpenToString.toString())
|
||||||
|
assertEquals("InheritedFromClassWithAbstractToString", InheritedFromClassWithAbstractToString.toString())
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
// LANGUAGE: +DataObjects
|
||||||
|
|
||||||
|
class C {
|
||||||
|
companion <!WRONG_MODIFIER_TARGET!>data<!> object Object
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public final class C {
|
||||||
|
public constructor C()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
|
||||||
|
public data companion object Object {
|
||||||
|
private constructor Object()
|
||||||
|
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// FIR_IDENTICAL
|
|
||||||
<!WRONG_MODIFIER_TARGET!>data<!> object Object<!CONSTRUCTOR_IN_OBJECT!>(val x: Int, val y: Int)<!>
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
package
|
|
||||||
|
|
||||||
public data object Object {
|
|
||||||
private constructor Object(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.Int)
|
|
||||||
public final val x: kotlin.Int
|
|
||||||
public final val y: kotlin.Int
|
|
||||||
public final operator /*synthesized*/ fun component1(): kotlin.Int
|
|
||||||
public final operator /*synthesized*/ fun component2(): kotlin.Int
|
|
||||||
public final /*synthesized*/ fun copy(/*0*/ x: kotlin.Int = ..., /*1*/ y: kotlin.Int = ...): Object
|
|
||||||
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
|
||||||
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
|
|
||||||
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
// LANGUAGE: -DataObjects
|
||||||
|
<!WRONG_MODIFIER_TARGET!>data<!> object Object
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
// LANGUAGE: -DataObjects
|
||||||
|
<!UNSUPPORTED_FEATURE!>data<!> object Object
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public data object Object {
|
||||||
|
private constructor Object()
|
||||||
|
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
// LANGUAGE: +DataObjects
|
||||||
|
// FIR_IDENTICAL
|
||||||
|
data object Object
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public data object Object {
|
||||||
|
private constructor Object()
|
||||||
|
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
// LANGUAGE: +DataObjects
|
||||||
|
|
||||||
|
interface I {
|
||||||
|
fun foo()
|
||||||
|
}
|
||||||
|
|
||||||
|
val o = <!UNRESOLVED_REFERENCE!>data<!><!SYNTAX!><!> object<!SYNTAX!><!>: I {
|
||||||
|
override fun foo() {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public val o: [Error type: Not found recorded type for data]
|
||||||
|
|
||||||
|
public object `<no name provided>` : I {
|
||||||
|
private constructor `<no name provided>`()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ fun foo(): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface I {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public abstract fun foo(): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
@@ -3,8 +3,8 @@
|
|||||||
B(2)
|
B(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
<!WRONG_MODIFIER_TARGET!>data<!> object <!DATA_CLASS_WITHOUT_PARAMETERS!>Second<!>
|
<!UNSUPPORTED_FEATURE!>data<!> object Second
|
||||||
|
|
||||||
<!WRONG_MODIFIER_TARGET!>data<!> interface <!DATA_CLASS_WITHOUT_PARAMETERS!>Third<!>
|
<!WRONG_MODIFIER_TARGET!>data<!> interface Third
|
||||||
|
|
||||||
<!WRONG_MODIFIER_TARGET!>data<!> annotation class Fourth(val x: Int)
|
<!WRONG_MODIFIER_TARGET!>data<!> annotation class Fourth(val x: Int)
|
||||||
|
|||||||
@@ -11,8 +11,6 @@ public final data enum class First : kotlin.Enum<First> {
|
|||||||
public final val x: kotlin.Int
|
public final val x: kotlin.Int
|
||||||
protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any
|
protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any
|
||||||
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: First): kotlin.Int
|
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: First): kotlin.Int
|
||||||
public final operator /*synthesized*/ fun component1(): kotlin.Int
|
|
||||||
public final /*synthesized*/ fun copy(/*0*/ x: kotlin.Int = ...): First
|
|
||||||
public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
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
|
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<First!>!
|
public final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class<First!>!
|
||||||
@@ -27,8 +25,6 @@ public final data enum class First : kotlin.Enum<First> {
|
|||||||
public final data annotation class Fourth : kotlin.Annotation {
|
public final data annotation class Fourth : kotlin.Annotation {
|
||||||
public constructor Fourth(/*0*/ x: kotlin.Int)
|
public constructor Fourth(/*0*/ x: kotlin.Int)
|
||||||
public final val x: kotlin.Int
|
public final val x: kotlin.Int
|
||||||
public final operator /*synthesized*/ fun component1(): kotlin.Int
|
|
||||||
public final /*synthesized*/ fun copy(/*0*/ x: kotlin.Int = ...): Fourth
|
|
||||||
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
|
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
|
||||||
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||||
@@ -36,7 +32,6 @@ public final data annotation class Fourth : kotlin.Annotation {
|
|||||||
|
|
||||||
public data object Second {
|
public data object Second {
|
||||||
private constructor Second()
|
private constructor Second()
|
||||||
public final /*synthesized*/ fun copy(): Second
|
|
||||||
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
|
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
|
||||||
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||||
@@ -47,3 +42,4 @@ public data interface Third {
|
|||||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
// LANGUAGE: +DataObjects
|
||||||
|
|
||||||
|
data object Override {
|
||||||
|
<!DATA_OBJECT_CUSTOM_EQUALS_OR_HASH_CODE!>override<!> fun equals(other: Any?): Boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
<!DATA_OBJECT_CUSTOM_EQUALS_OR_HASH_CODE!>override<!> fun hashCode(): Int {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open class Base {
|
||||||
|
open fun hashCode(x: Int) = x
|
||||||
|
}
|
||||||
|
|
||||||
|
data object NoOverride: Base() {
|
||||||
|
fun equals(other: Any?, tag: Int): Boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun hashCode(param: String): Int {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(x: Int) = x + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
open class Super {
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
return super.equals(other)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data object OverridenInSuper: Super() {
|
||||||
|
<!DATA_OBJECT_CUSTOM_EQUALS_OR_HASH_CODE!>override<!> fun equals(other: Any?): Boolean {
|
||||||
|
return super.equals(other)
|
||||||
|
}
|
||||||
|
}
|
||||||
+40
@@ -0,0 +1,40 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public open class Base {
|
||||||
|
public constructor Base()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open fun hashCode(/*0*/ x: kotlin.Int): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public data object NoOverride : Base {
|
||||||
|
private constructor NoOverride()
|
||||||
|
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public final fun equals(/*0*/ other: kotlin.Any?, /*1*/ tag: kotlin.Int): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ fun hashCode(/*0*/ x: kotlin.Int): kotlin.Int
|
||||||
|
public final fun hashCode(/*0*/ param: kotlin.String): kotlin.Int
|
||||||
|
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public data object Override {
|
||||||
|
private constructor Override()
|
||||||
|
public open override /*1*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public data object OverridenInSuper : Super {
|
||||||
|
private constructor OverridenInSuper()
|
||||||
|
public open override /*1*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public open class Super {
|
||||||
|
public constructor Super()
|
||||||
|
public open override /*1*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
// !LANGUAGE: +DataObjects
|
||||||
|
// TARGET_BACKEND: JVM_IR
|
||||||
|
|
||||||
|
import java.io.Serializable
|
||||||
|
|
||||||
|
data <!CONFLICTING_JVM_DECLARATIONS!>object A<!> : Serializable {
|
||||||
|
<!CONFLICTING_JVM_DECLARATIONS!>private fun readResolve(): Any<!> = this
|
||||||
|
}
|
||||||
|
|
||||||
|
data object B : Serializable {
|
||||||
|
private fun readResolve(): B = this
|
||||||
|
}
|
||||||
|
|
||||||
|
data object C {
|
||||||
|
private fun readResolve(): Any = this
|
||||||
|
}
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public data object A : java.io.Serializable {
|
||||||
|
private constructor A()
|
||||||
|
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
|
||||||
|
private final fun readResolve(): kotlin.Any
|
||||||
|
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public data object B : java.io.Serializable {
|
||||||
|
private constructor B()
|
||||||
|
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
|
||||||
|
private final fun readResolve(): B
|
||||||
|
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public data object C {
|
||||||
|
private constructor C()
|
||||||
|
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
|
||||||
|
private final fun readResolve(): kotlin.Any
|
||||||
|
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
+1
@@ -56,3 +56,4 @@ data class Test<T : Any?> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Generated
+37
-3
@@ -6962,6 +6962,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
|||||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/dataClasses"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/dataClasses"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("companionDataObject.kt")
|
||||||
|
public void testCompanionDataObject() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/dataClasses/companionDataObject.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("componentNamedComponent1.kt")
|
@TestMetadata("componentNamedComponent1.kt")
|
||||||
public void testComponentNamedComponent1() throws Exception {
|
public void testComponentNamedComponent1() throws Exception {
|
||||||
@@ -7035,9 +7041,21 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("dataObject.kt")
|
@TestMetadata("dataObjectDisabled.kt")
|
||||||
public void testDataObject() throws Exception {
|
public void testDataObjectDisabled() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/dataClasses/dataObject.kt");
|
runTest("compiler/testData/diagnostics/tests/dataClasses/dataObjectDisabled.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("dataObjectEnabled.kt")
|
||||||
|
public void testDataObjectEnabled() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/dataClasses/dataObjectEnabled.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("dataObjectLiteral.kt")
|
||||||
|
public void testDataObjectLiteral() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/dataClasses/dataObjectLiteral.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -7661,6 +7679,22 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("compiler/testData/diagnostics/tests/dataObjects")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class DataObjects {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInDataObjects() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/dataObjects"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("overrideEqualsAndHashCode.kt")
|
||||||
|
public void testOverrideEqualsAndHashCode() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/dataObjects/overrideEqualsAndHashCode.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@TestMetadata("compiler/testData/diagnostics/tests/declarationChecks")
|
@TestMetadata("compiler/testData/diagnostics/tests/declarationChecks")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
|||||||
+16
@@ -61,6 +61,22 @@ public class DiagnosticsTestWithJvmIrBackendGenerated extends AbstractDiagnostic
|
|||||||
runTest("compiler/testData/diagnostics/testsWithJvmBackend/suspendInlineCycle_ir.kt");
|
runTest("compiler/testData/diagnostics/testsWithJvmBackend/suspendInlineCycle_ir.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("compiler/testData/diagnostics/testsWithJvmBackend/dataObjects")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class DataObjects {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInDataObjects() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithJvmBackend/dataObjects"), Pattern.compile("^(.+)\\.kts?$"), null, TargetBackend.JVM_IR, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("customReadResolve.kt")
|
||||||
|
public void testCustomReadResolve() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/testsWithJvmBackend/dataObjects/customReadResolve.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@TestMetadata("compiler/testData/diagnostics/testsWithJvmBackend/duplicateJvmSignature")
|
@TestMetadata("compiler/testData/diagnostics/testsWithJvmBackend/duplicateJvmSignature")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
|||||||
+10
@@ -61,6 +61,16 @@ public class DiagnosticsTestWithOldJvmBackendGenerated extends AbstractDiagnosti
|
|||||||
runTest("compiler/testData/diagnostics/testsWithJvmBackend/suspendInlineCycle.kt");
|
runTest("compiler/testData/diagnostics/testsWithJvmBackend/suspendInlineCycle.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("compiler/testData/diagnostics/testsWithJvmBackend/dataObjects")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class DataObjects {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInDataObjects() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithJvmBackend/dataObjects"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_OLD, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@TestMetadata("compiler/testData/diagnostics/testsWithJvmBackend/duplicateJvmSignature")
|
@TestMetadata("compiler/testData/diagnostics/testsWithJvmBackend/duplicateJvmSignature")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
|||||||
+28
@@ -13528,6 +13528,34 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/dataObjects")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class DataObjects {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInDataObjects() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/dataObjects"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("equals.kt")
|
||||||
|
public void testEquals() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/dataObjects/equals.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("hashCode.kt")
|
||||||
|
public void testHashCode() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/dataObjects/hashCode.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("toString.kt")
|
||||||
|
public void testToString() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/dataObjects/toString.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@TestMetadata("compiler/testData/codegen/box/deadCodeElimination")
|
@TestMetadata("compiler/testData/codegen/box/deadCodeElimination")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
|||||||
+40
@@ -13648,6 +13648,46 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/dataObjects")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class DataObjects {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInDataObjects() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/dataObjects"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("equals.kt")
|
||||||
|
public void testEquals() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/dataObjects/equals.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("hashCode.kt")
|
||||||
|
public void testHashCode() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/dataObjects/hashCode.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("multipleInstances.kt")
|
||||||
|
public void testMultipleInstances() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/dataObjects/multipleInstances.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serialization.kt")
|
||||||
|
public void testSerialization() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/dataObjects/serialization.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("toString.kt")
|
||||||
|
public void testToString() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/dataObjects/toString.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@TestMetadata("compiler/testData/codegen/box/deadCodeElimination")
|
@TestMetadata("compiler/testData/codegen/box/deadCodeElimination")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
|||||||
+28
@@ -10981,6 +10981,34 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/dataObjects")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class DataObjects extends AbstractLightAnalysisModeTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInDataObjects() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/dataObjects"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("equals.kt")
|
||||||
|
public void testEquals() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/dataObjects/equals.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("hashCode.kt")
|
||||||
|
public void testHashCode() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/dataObjects/hashCode.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("toString.kt")
|
||||||
|
public void testToString() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/dataObjects/toString.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/deadCodeElimination")
|
@TestMetadata("compiler/testData/codegen/box/deadCodeElimination")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
@@ -263,6 +263,7 @@ enum class LanguageFeature(
|
|||||||
RefineTypeCheckingOnAssignmentsToJavaFields(KOTLIN_1_8, kind = BUG_FIX),
|
RefineTypeCheckingOnAssignmentsToJavaFields(KOTLIN_1_8, kind = BUG_FIX),
|
||||||
RangeUntilOperator(KOTLIN_1_8), // KT-15613
|
RangeUntilOperator(KOTLIN_1_8), // KT-15613
|
||||||
GenericInlineClassParameter(sinceVersion = KOTLIN_1_8, kind = UNSTABLE_FEATURE), // KT-32162
|
GenericInlineClassParameter(sinceVersion = KOTLIN_1_8, kind = UNSTABLE_FEATURE), // KT-32162
|
||||||
|
DataObjects(KOTLIN_1_8), // KT-4107
|
||||||
|
|
||||||
// 1.9
|
// 1.9
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -34,8 +34,9 @@ enum class KotlinTarget(val description: String, val isDefault: Boolean = true)
|
|||||||
// includes only top level classes and nested/inner classes (but not enums, objects, interfaces and local classes)
|
// includes only top level classes and nested/inner classes (but not enums, objects, interfaces and local classes)
|
||||||
CLASS_ONLY("class", false),
|
CLASS_ONLY("class", false),
|
||||||
|
|
||||||
// does not include OBJECT_LITERAL but DOES include COMPANION_OBJECT
|
// does not include OBJECT_LITERAL but DOES include both STANDALONE_OBJECT and COMPANION_OBJECT
|
||||||
OBJECT("object", false),
|
OBJECT("object", false),
|
||||||
|
STANDALONE_OBJECT("standalone object", false),
|
||||||
COMPANION_OBJECT("companion object", false),
|
COMPANION_OBJECT("companion object", false),
|
||||||
INTERFACE("interface", false),
|
INTERFACE("interface", false),
|
||||||
ENUM_CLASS("enum class", false),
|
ENUM_CLASS("enum class", false),
|
||||||
@@ -84,7 +85,7 @@ enum class KotlinTarget(val description: String, val isDefault: Boolean = true)
|
|||||||
val LOCAL_CLASS_LIST = listOf(LOCAL_CLASS, CLASS)
|
val LOCAL_CLASS_LIST = listOf(LOCAL_CLASS, CLASS)
|
||||||
val CLASS_LIST = listOf(CLASS_ONLY, CLASS)
|
val CLASS_LIST = listOf(CLASS_ONLY, CLASS)
|
||||||
val COMPANION_OBJECT_LIST = listOf(COMPANION_OBJECT, OBJECT, CLASS)
|
val COMPANION_OBJECT_LIST = listOf(COMPANION_OBJECT, OBJECT, CLASS)
|
||||||
val OBJECT_LIST = listOf(OBJECT, CLASS)
|
val OBJECT_LIST = listOf(STANDALONE_OBJECT, OBJECT, CLASS)
|
||||||
val INTERFACE_LIST = listOf(INTERFACE, CLASS)
|
val INTERFACE_LIST = listOf(INTERFACE, CLASS)
|
||||||
val ENUM_LIST = listOf(ENUM_CLASS, CLASS)
|
val ENUM_LIST = listOf(ENUM_CLASS, CLASS)
|
||||||
val ENUM_ENTRY_LIST = listOf(ENUM_ENTRY, PROPERTY, FIELD)
|
val ENUM_ENTRY_LIST = listOf(ENUM_ENTRY, PROPERTY, FIELD)
|
||||||
|
|||||||
+28
@@ -10116,6 +10116,34 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/dataObjects")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class DataObjects {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInDataObjects() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/dataObjects"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("equals.kt")
|
||||||
|
public void testEquals() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/dataObjects/equals.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("hashCode.kt")
|
||||||
|
public void testHashCode() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/dataObjects/hashCode.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("toString.kt")
|
||||||
|
public void testToString() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/dataObjects/toString.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@TestMetadata("compiler/testData/codegen/box/deadCodeElimination")
|
@TestMetadata("compiler/testData/codegen/box/deadCodeElimination")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
|||||||
+28
@@ -10158,6 +10158,34 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/dataObjects")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class DataObjects {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInDataObjects() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/dataObjects"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("equals.kt")
|
||||||
|
public void testEquals() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/dataObjects/equals.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("hashCode.kt")
|
||||||
|
public void testHashCode() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/dataObjects/hashCode.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("toString.kt")
|
||||||
|
public void testToString() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/dataObjects/toString.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@TestMetadata("compiler/testData/codegen/box/deadCodeElimination")
|
@TestMetadata("compiler/testData/codegen/box/deadCodeElimination")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
|||||||
+28
@@ -8996,6 +8996,34 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/dataObjects")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class DataObjects extends AbstractIrCodegenBoxWasmTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInDataObjects() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/dataObjects"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("equals.kt")
|
||||||
|
public void testEquals() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/dataObjects/equals.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("hashCode.kt")
|
||||||
|
public void testHashCode() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/dataObjects/hashCode.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("toString.kt")
|
||||||
|
public void testToString() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/dataObjects/toString.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/deadCodeElimination")
|
@TestMetadata("compiler/testData/codegen/box/deadCodeElimination")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
+17
-3
@@ -16,7 +16,9 @@ import org.jetbrains.kotlin.js.backend.ast.*;
|
|||||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
|
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
|
||||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
|
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
|
||||||
import org.jetbrains.kotlin.js.translate.utils.UtilsKt;
|
import org.jetbrains.kotlin.js.translate.utils.UtilsKt;
|
||||||
|
import org.jetbrains.kotlin.name.FqName;
|
||||||
import org.jetbrains.kotlin.psi.KtClassOrObject;
|
import org.jetbrains.kotlin.psi.KtClassOrObject;
|
||||||
|
import org.jetbrains.kotlin.psi.KtObjectDeclaration;
|
||||||
import org.jetbrains.kotlin.psi.KtParameter;
|
import org.jetbrains.kotlin.psi.KtParameter;
|
||||||
import org.jetbrains.kotlin.resolve.source.PsiSourceElementKt;
|
import org.jetbrains.kotlin.resolve.source.PsiSourceElementKt;
|
||||||
|
|
||||||
@@ -35,6 +37,11 @@ abstract class JsEqualsHashcodeToStringGenerator extends DataClassMethodGenerato
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void generateToStringMethod(@NotNull FunctionDescriptor function, @NotNull List<? extends PropertyDescriptor> classProperties) {
|
public void generateToStringMethod(@NotNull FunctionDescriptor function, @NotNull List<? extends PropertyDescriptor> classProperties) {
|
||||||
|
if (getDeclaration() instanceof KtObjectDeclaration) {
|
||||||
|
generateJsMethod(function).getBody().getStatements().add(new JsReturn(new JsStringLiteral(getDeclaration().getName())));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: relax this limitation, with the data generation logic fixed.
|
// TODO: relax this limitation, with the data generation logic fixed.
|
||||||
assert !classProperties.isEmpty();
|
assert !classProperties.isEmpty();
|
||||||
JsFunction functionObj = generateJsMethod(function);
|
JsFunction functionObj = generateJsMethod(function);
|
||||||
@@ -65,6 +72,14 @@ abstract class JsEqualsHashcodeToStringGenerator extends DataClassMethodGenerato
|
|||||||
@Override
|
@Override
|
||||||
public void generateHashCodeMethod(@NotNull FunctionDescriptor function, @NotNull List<? extends PropertyDescriptor> classProperties) {
|
public void generateHashCodeMethod(@NotNull FunctionDescriptor function, @NotNull List<? extends PropertyDescriptor> classProperties) {
|
||||||
JsFunction functionObj = generateJsMethod(function);
|
JsFunction functionObj = generateJsMethod(function);
|
||||||
|
if (classProperties.isEmpty()) {
|
||||||
|
FqName fqName = getDeclaration().getFqName();
|
||||||
|
JsExpression returnExpression = new JsIntLiteral(fqName != null ? fqName.hashCode() : 0);
|
||||||
|
JsReturn returnStatement = new JsReturn(returnExpression);
|
||||||
|
returnStatement.setSource(getDeclaration());
|
||||||
|
functionObj.getBody().getStatements().add(returnStatement);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
List<JsStatement> statements = functionObj.getBody().getStatements();
|
List<JsStatement> statements = functionObj.getBody().getStatements();
|
||||||
|
|
||||||
@@ -92,8 +107,8 @@ abstract class JsEqualsHashcodeToStringGenerator extends DataClassMethodGenerato
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void generateEqualsMethod(@NotNull FunctionDescriptor function, @NotNull List<? extends PropertyDescriptor> classProperties) {
|
public void generateEqualsMethod(@NotNull FunctionDescriptor function, @NotNull List<? extends PropertyDescriptor> classProperties) {
|
||||||
assert !classProperties.isEmpty();
|
|
||||||
JsFunction functionObj = generateJsMethod(function);
|
JsFunction functionObj = generateJsMethod(function);
|
||||||
|
|
||||||
JsFunctionScope funScope = functionObj.getScope();
|
JsFunctionScope funScope = functionObj.getScope();
|
||||||
|
|
||||||
JsName paramName = funScope.declareName("other");
|
JsName paramName = funScope.declareName("other");
|
||||||
@@ -120,9 +135,8 @@ abstract class JsEqualsHashcodeToStringGenerator extends DataClassMethodGenerato
|
|||||||
fieldChain = and(fieldChain, next);
|
fieldChain = and(fieldChain, next);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert fieldChain != null;
|
|
||||||
|
|
||||||
JsExpression returnExpression = or(referenceEqual, and(isNotNull, and(otherIsObject, and(prototypeEqual, fieldChain))));
|
JsExpression returnExpression = or(referenceEqual, and(isNotNull, and(otherIsObject, fieldChain != null ? and(prototypeEqual, fieldChain) : prototypeEqual)));
|
||||||
JsReturn returnStatement = new JsReturn(returnExpression);
|
JsReturn returnStatement = new JsReturn(returnExpression);
|
||||||
returnStatement.setSource(getDeclaration());
|
returnStatement.setSource(getDeclaration());
|
||||||
functionObj.getBody().getStatements().add(returnStatement);
|
functionObj.getBody().getStatements().add(returnStatement);
|
||||||
|
|||||||
+30
@@ -11102,6 +11102,36 @@ public class NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTest
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/dataObjects")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@Tag("codegen")
|
||||||
|
@UseExtTestCaseGroupProvider()
|
||||||
|
public class DataObjects {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInDataObjects() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/dataObjects"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.NATIVE, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("equals.kt")
|
||||||
|
public void testEquals() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/dataObjects/equals.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("hashCode.kt")
|
||||||
|
public void testHashCode() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/dataObjects/hashCode.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("toString.kt")
|
||||||
|
public void testToString() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/dataObjects/toString.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@TestMetadata("compiler/testData/codegen/box/deadCodeElimination")
|
@TestMetadata("compiler/testData/codegen/box/deadCodeElimination")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ class Experiment {
|
|||||||
annotation class Type
|
annotation class Type
|
||||||
|
|
||||||
@Type
|
@Type
|
||||||
data class Group(s: String)
|
data class Group(var s: String)
|
||||||
}
|
}
|
||||||
|
|
||||||
class Foo {
|
class Foo {
|
||||||
|
|||||||
@@ -100,6 +100,8 @@ public final class Experiment {
|
|||||||
@kotlin.Metadata()
|
@kotlin.Metadata()
|
||||||
@Experiment.Type()
|
@Experiment.Type()
|
||||||
public static final class Group {
|
public static final class Group {
|
||||||
|
@org.jetbrains.annotations.NotNull()
|
||||||
|
private java.lang.String s;
|
||||||
|
|
||||||
@org.jetbrains.annotations.NotNull()
|
@org.jetbrains.annotations.NotNull()
|
||||||
public final Experiment.Group copy(@org.jetbrains.annotations.NotNull()
|
public final Experiment.Group copy(@org.jetbrains.annotations.NotNull()
|
||||||
@@ -107,10 +109,41 @@ public final class Experiment {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@java.lang.Override()
|
||||||
|
public boolean equals(@org.jetbrains.annotations.Nullable()
|
||||||
|
java.lang.Object other) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@java.lang.Override()
|
||||||
|
public int hashCode() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@org.jetbrains.annotations.NotNull()
|
||||||
|
@java.lang.Override()
|
||||||
|
public java.lang.String toString() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public Group(@org.jetbrains.annotations.NotNull()
|
public Group(@org.jetbrains.annotations.NotNull()
|
||||||
java.lang.String s) {
|
java.lang.String s) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@org.jetbrains.annotations.NotNull()
|
||||||
|
public final java.lang.String component1() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@org.jetbrains.annotations.NotNull()
|
||||||
|
public final java.lang.String getS() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void setS(@org.jetbrains.annotations.NotNull()
|
||||||
|
java.lang.String p0) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -100,12 +100,28 @@ public final class Experiment {
|
|||||||
@kotlin.Metadata()
|
@kotlin.Metadata()
|
||||||
@Experiment.Type()
|
@Experiment.Type()
|
||||||
public static final class Group {
|
public static final class Group {
|
||||||
|
@org.jetbrains.annotations.NotNull()
|
||||||
|
private java.lang.String s;
|
||||||
|
|
||||||
public Group(@org.jetbrains.annotations.NotNull()
|
public Group(@org.jetbrains.annotations.NotNull()
|
||||||
java.lang.String s) {
|
java.lang.String s) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@org.jetbrains.annotations.NotNull()
|
||||||
|
public final java.lang.String getS() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void setS(@org.jetbrains.annotations.NotNull()
|
||||||
|
java.lang.String p0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@org.jetbrains.annotations.NotNull()
|
||||||
|
public final java.lang.String component1() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@org.jetbrains.annotations.NotNull()
|
@org.jetbrains.annotations.NotNull()
|
||||||
public final Experiment.Group copy(@org.jetbrains.annotations.NotNull()
|
public final Experiment.Group copy(@org.jetbrains.annotations.NotNull()
|
||||||
java.lang.String s) {
|
java.lang.String s) {
|
||||||
|
|||||||
+1
-1
@@ -38,7 +38,7 @@ class Experiment {
|
|||||||
annotation class Type
|
annotation class Type
|
||||||
|
|
||||||
@Type
|
@Type
|
||||||
data class Group(s: String)
|
data class Group(val s: String)
|
||||||
}
|
}
|
||||||
|
|
||||||
class Foo {
|
class Foo {
|
||||||
|
|||||||
+29
@@ -103,6 +103,8 @@ public final class Experiment {
|
|||||||
@kotlin.Metadata()
|
@kotlin.Metadata()
|
||||||
@test.Experiment.Type()
|
@test.Experiment.Type()
|
||||||
public static final class Group {
|
public static final class Group {
|
||||||
|
@org.jetbrains.annotations.NotNull()
|
||||||
|
private final java.lang.String s = null;
|
||||||
|
|
||||||
@org.jetbrains.annotations.NotNull()
|
@org.jetbrains.annotations.NotNull()
|
||||||
public final test.Experiment.Group copy(@org.jetbrains.annotations.NotNull()
|
public final test.Experiment.Group copy(@org.jetbrains.annotations.NotNull()
|
||||||
@@ -110,10 +112,37 @@ public final class Experiment {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@java.lang.Override()
|
||||||
|
public boolean equals(@org.jetbrains.annotations.Nullable()
|
||||||
|
java.lang.Object other) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@java.lang.Override()
|
||||||
|
public int hashCode() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@org.jetbrains.annotations.NotNull()
|
||||||
|
@java.lang.Override()
|
||||||
|
public java.lang.String toString() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public Group(@org.jetbrains.annotations.NotNull()
|
public Group(@org.jetbrains.annotations.NotNull()
|
||||||
java.lang.String s) {
|
java.lang.String s) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@org.jetbrains.annotations.NotNull()
|
||||||
|
public final java.lang.String component1() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@org.jetbrains.annotations.NotNull()
|
||||||
|
public final java.lang.String getS() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+12
@@ -103,12 +103,24 @@ public final class Experiment {
|
|||||||
@kotlin.Metadata()
|
@kotlin.Metadata()
|
||||||
@test.Experiment.Type()
|
@test.Experiment.Type()
|
||||||
public static final class Group {
|
public static final class Group {
|
||||||
|
@org.jetbrains.annotations.NotNull()
|
||||||
|
private final java.lang.String s = null;
|
||||||
|
|
||||||
public Group(@org.jetbrains.annotations.NotNull()
|
public Group(@org.jetbrains.annotations.NotNull()
|
||||||
java.lang.String s) {
|
java.lang.String s) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@org.jetbrains.annotations.NotNull()
|
||||||
|
public final java.lang.String getS() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@org.jetbrains.annotations.NotNull()
|
||||||
|
public final java.lang.String component1() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@org.jetbrains.annotations.NotNull()
|
@org.jetbrains.annotations.NotNull()
|
||||||
public final test.Experiment.Group copy(@org.jetbrains.annotations.NotNull()
|
public final test.Experiment.Group copy(@org.jetbrains.annotations.NotNull()
|
||||||
java.lang.String s) {
|
java.lang.String s) {
|
||||||
|
|||||||
Reference in New Issue
Block a user