diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DataClassMembersGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DataClassMembersGenerator.kt index 6b022765582..3a271f36762 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DataClassMembersGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DataClassMembersGenerator.kt @@ -121,7 +121,7 @@ class DataClassMembersGenerator(declarationGenerator: DeclarationGenerator) : De throw AssertionError("Data class should have a primary constructor: $classDescriptor") val constructorSymbol = context.symbolTable.referenceConstructor(dataClassConstructor) - buildMember(function) { irFunction -> + buildMember(function, declaration) { irFunction -> function.valueParameters.forEach { parameter -> putDefault(parameter, irGet(irThis(), getPropertyGetterSymbol(parameter))) } @@ -132,7 +132,7 @@ class DataClassMembersGenerator(declarationGenerator: DeclarationGenerator) : De } override fun generateEqualsMethod(function: FunctionDescriptor, properties: List) { - buildMember(function) { + buildMember(function, declaration) { +irIfThenReturnTrue(irEqeqeq(irThis(), irOther())) +irIfThenReturnFalse(irNotIs(irOther(), classDescriptor.defaultType)) val otherWithCast = irTemporary(irAs(irOther(), classDescriptor.defaultType), "other_with_cast") @@ -178,7 +178,7 @@ class DataClassMembersGenerator(declarationGenerator: DeclarationGenerator) : De } override fun generateHashCodeMethod(function: FunctionDescriptor, properties: List) { - buildMember(function) { + buildMember(function, declaration) { val result = irTemporaryVar(irInt(0), "result").symbol var first = true for (property in properties) { @@ -216,7 +216,7 @@ class DataClassMembersGenerator(declarationGenerator: DeclarationGenerator) : De } override fun generateToStringMethod(function: FunctionDescriptor, properties: List) { - buildMember(function) { + buildMember(function, declaration) { val irConcat = irConcat() irConcat.addArgument(irString(classDescriptor.name.asString() + "(")) var first = true diff --git a/compiler/testData/ir/sourceRanges/synthesizedDataClassMembers.kt b/compiler/testData/ir/sourceRanges/synthesizedDataClassMembers.kt new file mode 100644 index 00000000000..b03e2f9aa7a --- /dev/null +++ b/compiler/testData/ir/sourceRanges/synthesizedDataClassMembers.kt @@ -0,0 +1,5 @@ +data class C( + val x: Int, + val y: String, + val z: Any +) \ No newline at end of file diff --git a/compiler/testData/ir/sourceRanges/synthesizedDataClassMembers.txt b/compiler/testData/ir/sourceRanges/synthesizedDataClassMembers.txt new file mode 100644 index 00000000000..46249e18c7b --- /dev/null +++ b/compiler/testData/ir/sourceRanges/synthesizedDataClassMembers.txt @@ -0,0 +1,175 @@ +@0:0..4:1 FILE /synthesizedDataClassMembers.kt + @0:0..4:1 CLASS CLASS C + @0:0..4:1 VALUE_PARAMETER this@C: C + @0:0..4:1 CONSTRUCTOR public constructor C(x: kotlin.Int, y: kotlin.String, z: kotlin.Any) + @1:8..18 VALUE_PARAMETER value-parameter x: kotlin.Int + @2:8..21 VALUE_PARAMETER value-parameter y: kotlin.String + @3:8..18 VALUE_PARAMETER value-parameter z: kotlin.Any + @0:0..4:1 BLOCK_BODY + @0:0..4:1 DELEGATING_CONSTRUCTOR_CALL 'constructor Any()' + @0:0..4:1 INSTANCE_INITIALIZER_CALL classDescriptor='C' + @1:8..18 PROPERTY public final val x: kotlin.Int + @1:8..18 FIELD PROPERTY_BACKING_FIELD public final val x: kotlin.Int + @1:8..18 EXPRESSION_BODY + @1:8..18 GET_VAR 'value-parameter x: Int' type=kotlin.Int origin=INITIALIZE_PROPERTY_FROM_PARAMETER + @1:8..18 FUN DEFAULT_PROPERTY_ACCESSOR public final fun (): kotlin.Int + @-1:-1..-1 VALUE_PARAMETER this@C: C + @1:8..18 BLOCK_BODY + @1:8..18 RETURN type=kotlin.Nothing from='(): Int' + @1:8..18 GET_FIELD 'x: Int' type=kotlin.Int origin=null + @1:8..18 GET_VAR 'this@C: C' type=C origin=null + @2:8..21 PROPERTY public final val y: kotlin.String + @2:8..21 FIELD PROPERTY_BACKING_FIELD public final val y: kotlin.String + @2:8..21 EXPRESSION_BODY + @2:8..21 GET_VAR 'value-parameter y: String' type=kotlin.String origin=INITIALIZE_PROPERTY_FROM_PARAMETER + @2:8..21 FUN DEFAULT_PROPERTY_ACCESSOR public final fun (): kotlin.String + @-1:-1..-1 VALUE_PARAMETER this@C: C + @2:8..21 BLOCK_BODY + @2:8..21 RETURN type=kotlin.Nothing from='(): String' + @2:8..21 GET_FIELD 'y: String' type=kotlin.String origin=null + @2:8..21 GET_VAR 'this@C: C' type=C origin=null + @3:8..18 PROPERTY public final val z: kotlin.Any + @3:8..18 FIELD PROPERTY_BACKING_FIELD public final val z: kotlin.Any + @3:8..18 EXPRESSION_BODY + @3:8..18 GET_VAR 'value-parameter z: Any' type=kotlin.Any origin=INITIALIZE_PROPERTY_FROM_PARAMETER + @3:8..18 FUN DEFAULT_PROPERTY_ACCESSOR public final fun (): kotlin.Any + @-1:-1..-1 VALUE_PARAMETER this@C: C + @3:8..18 BLOCK_BODY + @3:8..18 RETURN type=kotlin.Nothing from='(): Any' + @3:8..18 GET_FIELD 'z: Any' type=kotlin.Any origin=null + @3:8..18 GET_VAR 'this@C: C' type=C origin=null + @1:8..18 FUN GENERATED_DATA_CLASS_MEMBER public final operator fun component1(): kotlin.Int + @-1:-1..-1 VALUE_PARAMETER this@C: C + @1:8..18 BLOCK_BODY + @1:8..18 RETURN type=kotlin.Nothing from='component1(): Int' + @1:8..18 CALL '(): Int' type=kotlin.Int origin=GET_PROPERTY + @1:8..18 GET_VAR 'this@C: C' type=C origin=null + @2:8..21 FUN GENERATED_DATA_CLASS_MEMBER public final operator fun component2(): kotlin.String + @-1:-1..-1 VALUE_PARAMETER this@C: C + @2:8..21 BLOCK_BODY + @2:8..21 RETURN type=kotlin.Nothing from='component2(): String' + @2:8..21 CALL '(): String' type=kotlin.String origin=GET_PROPERTY + @2:8..21 GET_VAR 'this@C: C' type=C origin=null + @3:8..18 FUN GENERATED_DATA_CLASS_MEMBER public final operator fun component3(): kotlin.Any + @-1:-1..-1 VALUE_PARAMETER this@C: C + @3:8..18 BLOCK_BODY + @3:8..18 RETURN type=kotlin.Nothing from='component3(): Any' + @3:8..18 CALL '(): Any' type=kotlin.Any origin=GET_PROPERTY + @3:8..18 GET_VAR 'this@C: C' type=C origin=null + @0:0..4:1 FUN GENERATED_DATA_CLASS_MEMBER public final fun copy(x: kotlin.Int = ..., y: kotlin.String = ..., z: kotlin.Any = ...): C + @-1:-1..-1 VALUE_PARAMETER this@C: C + @1:8..18 VALUE_PARAMETER value-parameter x: kotlin.Int = ... + @0:0..4:1 EXPRESSION_BODY + @0:0..4:1 CALL '(): Int' type=kotlin.Int origin=GET_PROPERTY + @0:0..4:1 GET_VAR 'this@C: C' type=C origin=null + @2:8..21 VALUE_PARAMETER value-parameter y: kotlin.String = ... + @0:0..4:1 EXPRESSION_BODY + @0:0..4:1 CALL '(): String' type=kotlin.String origin=GET_PROPERTY + @0:0..4:1 GET_VAR 'this@C: C' type=C origin=null + @3:8..18 VALUE_PARAMETER value-parameter z: kotlin.Any = ... + @0:0..4:1 EXPRESSION_BODY + @0:0..4:1 CALL '(): Any' type=kotlin.Any origin=GET_PROPERTY + @0:0..4:1 GET_VAR 'this@C: C' type=C origin=null + @0:0..4:1 BLOCK_BODY + @0:0..4:1 RETURN type=kotlin.Nothing from='copy(Int = ..., String = ..., Any = ...): C' + @0:0..4:1 CALL 'constructor C(Int, String, Any)' type=C origin=null + @0:0..4:1 GET_VAR 'value-parameter x: Int = ...' type=kotlin.Int origin=null + @0:0..4:1 GET_VAR 'value-parameter y: String = ...' type=kotlin.String origin=null + @0:0..4:1 GET_VAR 'value-parameter z: Any = ...' type=kotlin.Any origin=null + @0:0..4:1 FUN GENERATED_DATA_CLASS_MEMBER public open override fun toString(): kotlin.String + @-1:-1..-1 VALUE_PARAMETER this@C: C + @0:0..4:1 BLOCK_BODY + @0:0..4:1 RETURN type=kotlin.Nothing from='toString(): String' + @0:0..4:1 STRING_CONCATENATION type=kotlin.String + @0:0..4:1 CONST String type=kotlin.String value='C(' + @0:0..4:1 CONST String type=kotlin.String value='x=' + @0:0..4:1 CALL '(): Int' type=kotlin.Int origin=GET_PROPERTY + @0:0..4:1 GET_VAR 'this@C: C' type=C origin=null + @0:0..4:1 CONST String type=kotlin.String value=', ' + @0:0..4:1 CONST String type=kotlin.String value='y=' + @0:0..4:1 CALL '(): String' type=kotlin.String origin=GET_PROPERTY + @0:0..4:1 GET_VAR 'this@C: C' type=C origin=null + @0:0..4:1 CONST String type=kotlin.String value=', ' + @0:0..4:1 CONST String type=kotlin.String value='z=' + @0:0..4:1 CALL '(): Any' type=kotlin.Any origin=GET_PROPERTY + @0:0..4:1 GET_VAR 'this@C: C' type=C origin=null + @0:0..4:1 CONST String type=kotlin.String value=')' + @0:0..4:1 FUN GENERATED_DATA_CLASS_MEMBER public open override fun hashCode(): kotlin.Int + @-1:-1..-1 VALUE_PARAMETER this@C: C + @0:0..4:1 BLOCK_BODY + @0:0..4:1 VAR IR_TEMPORARY_VARIABLE var tmp0_result: kotlin.Int + @0:0..4:1 CONST Int type=kotlin.Int value='0' + @0:0..4:1 SET_VAR 'tmp0_result: Int' type=kotlin.Unit origin=EQ + @0:0..4:1 CALL 'hashCode(): Int' type=kotlin.Int origin=null + @0:0..4:1 CALL '(): Int' type=kotlin.Int origin=GET_PROPERTY + @0:0..4:1 GET_VAR 'this@C: C' type=C origin=null + @0:0..4:1 SET_VAR 'tmp0_result: Int' type=kotlin.Unit origin=EQ + @0:0..4:1 CALL 'plus(Int): Int' type=kotlin.Int origin=null + @0:0..4:1 CALL 'times(Int): Int' type=kotlin.Int origin=null + @0:0..4:1 GET_VAR 'tmp0_result: Int' type=kotlin.Int origin=null + @0:0..4:1 CONST Int type=kotlin.Int value='31' + @0:0..4:1 CALL 'hashCode(): Int' type=kotlin.Int origin=null + @0:0..4:1 CALL '(): String' type=kotlin.String origin=GET_PROPERTY + @0:0..4:1 GET_VAR 'this@C: C' type=C origin=null + @0:0..4:1 SET_VAR 'tmp0_result: Int' type=kotlin.Unit origin=EQ + @0:0..4:1 CALL 'plus(Int): Int' type=kotlin.Int origin=null + @0:0..4:1 CALL 'times(Int): Int' type=kotlin.Int origin=null + @0:0..4:1 GET_VAR 'tmp0_result: Int' type=kotlin.Int origin=null + @0:0..4:1 CONST Int type=kotlin.Int value='31' + @0:0..4:1 CALL 'hashCode(): Int' type=kotlin.Int origin=null + @0:0..4:1 CALL '(): Any' type=kotlin.Any origin=GET_PROPERTY + @0:0..4:1 GET_VAR 'this@C: C' type=C origin=null + @0:0..4:1 RETURN type=kotlin.Nothing from='hashCode(): Int' + @0:0..4:1 GET_VAR 'tmp0_result: Int' type=kotlin.Int origin=null + @0:0..4:1 FUN GENERATED_DATA_CLASS_MEMBER public open override fun equals(other: kotlin.Any?): kotlin.Boolean + @-1:-1..-1 VALUE_PARAMETER this@C: C + @-1:-1..-1 VALUE_PARAMETER value-parameter other: kotlin.Any? + @0:0..4:1 BLOCK_BODY + @0:0..4:1 WHEN type=kotlin.Unit origin=null + @0:0..4:1 BRANCH + @0:0..4:1 CALL 'EQEQEQ(Any?, Any?): Boolean' type=kotlin.Boolean origin=EQEQEQ + @0:0..4:1 GET_VAR 'this@C: C' type=C origin=null + @0:0..4:1 GET_VAR 'value-parameter other: Any?' type=kotlin.Any? origin=null + @0:0..4:1 RETURN type=kotlin.Nothing from='equals(Any?): Boolean' + @0:0..4:1 CONST Boolean type=kotlin.Boolean value='true' + @0:0..4:1 WHEN type=kotlin.Unit origin=null + @0:0..4:1 BRANCH + @0:0..4:1 TYPE_OP type=kotlin.Boolean origin=NOT_INSTANCEOF typeOperand=C + @0:0..4:1 GET_VAR 'value-parameter other: Any?' type=kotlin.Any? origin=null + @0:0..4:1 RETURN type=kotlin.Nothing from='equals(Any?): Boolean' + @0:0..4:1 CONST Boolean type=kotlin.Boolean value='false' + @0:0..4:1 VAR IR_TEMPORARY_VARIABLE val tmp0_other_with_cast: C + @0:0..4:1 TYPE_OP type=C origin=CAST typeOperand=C + @0:0..4:1 GET_VAR 'value-parameter other: Any?' type=kotlin.Any? origin=null + @0:0..4:1 WHEN type=kotlin.Unit origin=null + @0:0..4:1 BRANCH + @0:0..4:1 CALL 'NOT(Boolean): Boolean' type=kotlin.Boolean origin=EXCLEQ + @0:0..4:1 CALL 'EQEQ(Any?, Any?): Boolean' type=kotlin.Boolean origin=EXCLEQ + @0:0..4:1 CALL '(): Int' type=kotlin.Int origin=GET_PROPERTY + @0:0..4:1 GET_VAR 'this@C: C' type=C origin=null + @0:0..4:1 CALL '(): Int' type=kotlin.Int origin=GET_PROPERTY + @0:0..4:1 GET_VAR 'tmp0_other_with_cast: C' type=C origin=null + @0:0..4:1 RETURN type=kotlin.Nothing from='equals(Any?): Boolean' + @0:0..4:1 CONST Boolean type=kotlin.Boolean value='false' + @0:0..4:1 WHEN type=kotlin.Unit origin=null + @0:0..4:1 BRANCH + @0:0..4:1 CALL 'NOT(Boolean): Boolean' type=kotlin.Boolean origin=EXCLEQ + @0:0..4:1 CALL 'EQEQ(Any?, Any?): Boolean' type=kotlin.Boolean origin=EXCLEQ + @0:0..4:1 CALL '(): String' type=kotlin.String origin=GET_PROPERTY + @0:0..4:1 GET_VAR 'this@C: C' type=C origin=null + @0:0..4:1 CALL '(): String' type=kotlin.String origin=GET_PROPERTY + @0:0..4:1 GET_VAR 'tmp0_other_with_cast: C' type=C origin=null + @0:0..4:1 RETURN type=kotlin.Nothing from='equals(Any?): Boolean' + @0:0..4:1 CONST Boolean type=kotlin.Boolean value='false' + @0:0..4:1 WHEN type=kotlin.Unit origin=null + @0:0..4:1 BRANCH + @0:0..4:1 CALL 'NOT(Boolean): Boolean' type=kotlin.Boolean origin=EXCLEQ + @0:0..4:1 CALL 'EQEQ(Any?, Any?): Boolean' type=kotlin.Boolean origin=EXCLEQ + @0:0..4:1 CALL '(): Any' type=kotlin.Any origin=GET_PROPERTY + @0:0..4:1 GET_VAR 'this@C: C' type=C origin=null + @0:0..4:1 CALL '(): Any' type=kotlin.Any origin=GET_PROPERTY + @0:0..4:1 GET_VAR 'tmp0_other_with_cast: C' type=C origin=null + @0:0..4:1 RETURN type=kotlin.Nothing from='equals(Any?): Boolean' + @0:0..4:1 CONST Boolean type=kotlin.Boolean value='false' + @0:0..4:1 RETURN type=kotlin.Nothing from='equals(Any?): Boolean' + @0:0..4:1 CONST Boolean type=kotlin.Boolean value='true' diff --git a/compiler/tests/org/jetbrains/kotlin/ir/IrSourceRangesTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/ir/IrSourceRangesTestCaseGenerated.java index 6223f2a7389..444c4c8a019 100644 --- a/compiler/tests/org/jetbrains/kotlin/ir/IrSourceRangesTestCaseGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/ir/IrSourceRangesTestCaseGenerated.java @@ -47,4 +47,10 @@ public class IrSourceRangesTestCaseGenerated extends AbstractIrSourceRangesTestC String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/sourceRanges/kt17108.kt"); doTest(fileName); } + + @TestMetadata("synthesizedDataClassMembers.kt") + public void testSynthesizedDataClassMembers() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/sourceRanges/synthesizedDataClassMembers.kt"); + doTest(fileName); + } }