PSI2IR KT-41284 use getters for open data class property values

'allopen' compiler plug-in can make data classes and their members open,
which is a compilation error in usual case, but makes sense for Spring
and other frameworks that generate proxy-classes.
This commit is contained in:
Dmitry Petrov
2020-12-08 17:13:39 +03:00
parent d8d30263d3
commit 69c88a8a0a
15 changed files with 503 additions and 30 deletions
@@ -17,8 +17,6 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
import org.jetbrains.kotlin.fir.symbols.CallableId
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.fir.types.ConeStarProjection
@@ -37,7 +35,6 @@ import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.util.DataClassMembersGenerator
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
/**
@@ -84,11 +81,11 @@ class DataClassMembersGenerator(val components: Fir2IrComponents) {
// TODO
}
override fun getBackingField(parameter: ValueParameterDescriptor?, irValueParameter: IrValueParameter?): IrField? =
override fun getProperty(parameter: ValueParameterDescriptor?, irValueParameter: IrValueParameter?): IrProperty? =
irValueParameter?.let {
irClass.properties.single { irProperty ->
irProperty.name == irValueParameter.name && irProperty.backingField?.type == irValueParameter.type
}.backingField
}
}
override fun transform(typeParameterDescriptor: TypeParameterDescriptor): IrType {
@@ -216,8 +213,8 @@ class DataClassMembersGenerator(val components: Fir2IrComponents) {
fun generateComponentBody(irFunction: IrFunction) {
val index = getComponentIndex(irFunction)!!
val valueParameter = irClass.primaryConstructor!!.valueParameters[index - 1]
val backingField = irDataClassMembersGenerator.getBackingField(null, valueParameter)!!
irDataClassMembersGenerator.generateComponentFunction(irFunction, backingField)
val irProperty = irDataClassMembersGenerator.getProperty(null, valueParameter)!!
irDataClassMembersGenerator.generateComponentFunction(irFunction, irProperty)
}
fun generateCopyBody(irFunction: IrFunction) =
@@ -4210,6 +4210,16 @@ public class FirBytecodeTextTestGenerated extends AbstractFirBytecodeTextTest {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/properties"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@TestMetadata("dataClass.kt")
public void testDataClass() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/properties/dataClass.kt");
}
@TestMetadata("openDataClass.kt")
public void testOpenDataClass() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/properties/openDataClass.kt");
}
@TestMetadata("compiler/testData/codegen/bytecodeText/properties/lateinit")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -221,6 +221,11 @@ public class Fir2IrTextTestGenerated extends AbstractFir2IrTextTest {
runTest("compiler/testData/ir/irText/classes/objectWithInitializers.kt");
}
@TestMetadata("openDataClass.kt")
public void testOpenDataClass() throws Exception {
runTest("compiler/testData/ir/irText/classes/openDataClass.kt");
}
@TestMetadata("outerClassAccess.kt")
public void testOuterClassAccess() throws Exception {
runTest("compiler/testData/ir/irText/classes/outerClassAccess.kt");
@@ -69,10 +69,10 @@ class DataClassMembersGenerator(
FunctionGenerator(declarationGenerator).generateSyntheticFunctionParameterDeclarations(irFunction)
}
override fun getBackingField(parameter: ValueParameterDescriptor?, irValueParameter: IrValueParameter?): IrField? =
override fun getProperty(parameter: ValueParameterDescriptor?, irValueParameter: IrValueParameter?): IrProperty? =
parameter?.let {
val property = getOrFail(BindingContext.VALUE_PARAMETER_AS_PROPERTY, parameter)
return getBackingField(property)
return getProperty(property)
}
override fun transform(typeParameterDescriptor: TypeParameterDescriptor): IrType =
@@ -86,8 +86,8 @@ class DataClassMembersGenerator(
override fun generateComponentFunction(function: FunctionDescriptor, parameter: ValueParameterDescriptor) {
if (!irClass.isData) return
val backingField = irDataClassMembersGenerator.getBackingField(parameter, null) ?: return
irDataClassMembersGenerator.generateComponentFunction(function, backingField)
val irProperty = irDataClassMembersGenerator.getProperty(parameter, null) ?: return
irDataClassMembersGenerator.generateComponentFunction(function, irProperty)
}
override fun generateCopyFunction(function: FunctionDescriptor, constructorParameters: List<KtParameter>) {
@@ -43,6 +43,8 @@ abstract class DataClassMembersGenerator(
val irClass: IrClass,
val origin: IrDeclarationOrigin
) {
private val irPropertiesByDescriptor: Map<PropertyDescriptor, IrProperty> =
irClass.properties.associateBy { it.descriptor }
inline fun <T : IrDeclaration> T.buildWithScope(builder: (T) -> Unit): T =
also { irDeclaration ->
@@ -87,12 +89,26 @@ abstract class DataClassMembersGenerator(
)
}
fun irGetProperty(receiver: IrExpression, property: IrProperty): IrExpression {
// In some JVM-specific cases, such as when 'allopen' compiler plugin is applied,
// data classes and corresponding properties can be non-final.
// We should use getters for such properties (see KT-41284).
val backingField = property.backingField
return if (property.modality == Modality.FINAL && backingField != null) {
irGetField(receiver, backingField)
} else {
irCall(property.getter!!).apply {
dispatchReceiver = receiver
}
}
}
fun putDefault(parameter: ValueParameterDescriptor, value: IrExpression) {
irFunction.putDefault(parameter, irExprBody(value))
}
fun generateComponentFunction(irField: IrField) {
+irReturn(irGetField(irThis(), irField))
fun generateComponentFunction(irProperty: IrProperty) {
+irReturn(irGetProperty(irThis(), irProperty))
}
fun generateCopyFunction(constructorSymbol: IrConstructorSymbol) {
@@ -120,9 +136,9 @@ abstract class DataClassMembersGenerator(
+irIfThenReturnFalse(irNotIs(irOther(), irType))
val otherWithCast = irTemporary(irAs(irOther(), irType), "other_with_cast")
for (property in properties) {
val field = getBackingField(property)
val arg1 = irGetField(irThis(), field)
val arg2 = irGetField(irGet(irType, otherWithCast.symbol), field)
val irProperty = getProperty(property)
val arg1 = irGetProperty(irThis(), irProperty)
val arg2 = irGetProperty(irGet(irType, otherWithCast.symbol), irProperty)
+irIfThenReturnFalse(irNotEquals(arg1, arg2))
}
+irReturnTrue()
@@ -176,17 +192,17 @@ abstract class DataClassMembersGenerator(
}
private fun getHashCodeOfProperty(property: PropertyDescriptor): IrExpression {
val field = getBackingField(property)
val irProperty = getProperty(property)
return when {
property.type.isNullable() ->
irIfNull(
context.irBuiltIns.intType,
irGetField(irThis(), field),
irGetProperty(irThis(), irProperty),
irInt(0),
getHashCodeOf(property, irGetField(irThis(), field))
getHashCodeOf(property, irGetProperty(irThis(), irProperty))
)
else ->
getHashCodeOf(property, irGetField(irThis(), field))
getHashCodeOf(property, irGetProperty(irThis(), irProperty))
}
}
@@ -222,7 +238,7 @@ abstract class DataClassMembersGenerator(
irConcat.addArgument(irString(property.name.asString() + "="))
val irPropertyValue = irGetField(irThis(), getBackingField(property))
val irPropertyValue = irGetProperty(irThis(), getProperty(property))
val typeConstructorDescriptor = property.type.constructor.declarationDescriptor
val irPropertyStringValue =
@@ -243,8 +259,9 @@ abstract class DataClassMembersGenerator(
}
}
fun getBackingField(property: PropertyDescriptor): IrField =
irClass.properties.single { it.descriptor == property }.backingField!!
fun getProperty(property: PropertyDescriptor): IrProperty =
irPropertiesByDescriptor[property]
?: throw AssertionError("Class: ${irClass.descriptor}: unexpected property descriptor: $property")
abstract fun declareSimpleFunction(startOffset: Int, endOffset: Int, functionDescriptor: FunctionDescriptor): IrFunction
@@ -281,20 +298,20 @@ abstract class DataClassMembersGenerator(
}
// Entry for psi2ir
fun generateComponentFunction(function: FunctionDescriptor, irField: IrField) {
fun generateComponentFunction(function: FunctionDescriptor, irProperty: IrProperty) {
buildMember(function) {
generateComponentFunction(irField)
generateComponentFunction(irProperty)
}
}
// Entry for fir2ir
fun generateComponentFunction(irFunction: IrFunction, irField: IrField) {
fun generateComponentFunction(irFunction: IrFunction, irProperty: IrProperty) {
buildMember(irFunction) {
generateComponentFunction(irField)
generateComponentFunction(irProperty)
}
}
abstract fun getBackingField(parameter: ValueParameterDescriptor?, irValueParameter: IrValueParameter?): IrField?
abstract fun getProperty(parameter: ValueParameterDescriptor?, irValueParameter: IrValueParameter?): IrProperty?
abstract fun transform(typeParameterDescriptor: TypeParameterDescriptor): IrType
@@ -302,7 +319,7 @@ abstract class DataClassMembersGenerator(
fun generateCopyFunction(function: FunctionDescriptor, constructorSymbol: IrConstructorSymbol) {
buildMember(function) {
function.valueParameters.forEach { parameter ->
putDefault(parameter, irGetField(irThis(), getBackingField(parameter, null)!!))
putDefault(parameter, irGetProperty(irThis(), getProperty(parameter, null)!!))
}
generateCopyFunction(constructorSymbol)
}
@@ -312,7 +329,7 @@ abstract class DataClassMembersGenerator(
fun generateCopyFunction(irFunction: IrFunction, constructorSymbol: IrConstructorSymbol) {
buildMember(irFunction) {
irFunction.valueParameters.forEach { irValueParameter ->
irValueParameter.defaultValue = irExprBody(irGetField(irThis(), getBackingField(null, irValueParameter)!!))
irValueParameter.defaultValue = irExprBody(irGetProperty(irThis(), getProperty(null, irValueParameter)!!))
}
generateCopyFunction(constructorSymbol)
}
@@ -0,0 +1,8 @@
data class Test(
val x: String,
val y: String
)
// 7 GETFIELD Test\.x
// 7 GETFIELD Test\.y
// - get, componentN, copy$default, toString, hashCode, 2 times in equals
@@ -0,0 +1,14 @@
// This test emulates 'allopen' compiler plugin.
@Suppress("INCOMPATIBLE_MODIFIERS")
open data class Test(
open val x: String,
open val y: String
)
// 1 GETFIELD Test\.x
// 1 GETFIELD Test\.y
// 6 INVOKEVIRTUAL Test\.getX
// 6 INVOKEVIRTUAL Test\.getY
// - componentN, copy$default, toString, hashCode, 2 times in equals
@@ -0,0 +1,56 @@
@Suppress(names = ["INCOMPATIBLE_MODIFIERS"])
open data class ValidatedProperties {
constructor(test1: String, test2: String) /* primary */ {
super/*Any*/()
/* <init>() */
}
open val test1: String
field = test1
open get
open val test2: String
field = test2
open get
fun component1(): String {
return <this>.<get-test1>()
}
fun component2(): String {
return <this>.<get-test2>()
}
fun copy(test1: String = <this>.<get-test1>(), test2: String = <this>.<get-test2>()): ValidatedProperties {
return ValidatedProperties(test1 = test1, test2 = test2)
}
override fun equals(other: Any?): Boolean {
when {
EQEQEQ(arg0 = <this>, arg1 = other) -> return true
}
when {
other !is ValidatedProperties -> return false
}
val tmp0_other_with_cast: ValidatedProperties = other as ValidatedProperties
when {
EQEQ(arg0 = <this>.<get-test1>(), arg1 = tmp0_other_with_cast.<get-test1>()).not() -> return false
}
when {
EQEQ(arg0 = <this>.<get-test2>(), arg1 = tmp0_other_with_cast.<get-test2>()).not() -> return false
}
return true
}
override fun hashCode(): Int {
var result: Int = <this>.<get-test1>().hashCode()
result = result.times(other = 31).plus(other = <this>.<get-test2>().hashCode())
return result
}
override fun toString(): String {
return "ValidatedProperties(" + "test1=" + <this>.<get-test1>() + ", " + "test2=" + <this>.<get-test2>() + ")"
}
}
@@ -0,0 +1,139 @@
FILE fqName:<root> fileName:/openDataClass.kt
CLASS CLASS name:ValidatedProperties modality:OPEN visibility:public [data] superTypes:[kotlin.Any]
annotations:
Suppress(names = ['INCOMPATIBLE_MODIFIERS'])
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.ValidatedProperties
CONSTRUCTOR visibility:public <> (test1:kotlin.String, test2:kotlin.String) returnType:<root>.ValidatedProperties [primary]
VALUE_PARAMETER name:test1 index:0 type:kotlin.String
VALUE_PARAMETER name:test2 index:1 type:kotlin.String
BLOCK_BODY
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in kotlin.Any'
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:ValidatedProperties modality:OPEN visibility:public [data] superTypes:[kotlin.Any]'
PROPERTY name:test1 visibility:public modality:OPEN [val]
FIELD PROPERTY_BACKING_FIELD name:test1 type:kotlin.String visibility:private [final]
EXPRESSION_BODY
GET_VAR 'test1: kotlin.String declared in <root>.ValidatedProperties.<init>' type=kotlin.String origin=INITIALIZE_PROPERTY_FROM_PARAMETER
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test1> visibility:public modality:OPEN <> ($this:<root>.ValidatedProperties) returnType:kotlin.String
correspondingProperty: PROPERTY name:test1 visibility:public modality:OPEN [val]
$this: VALUE_PARAMETER name:<this> type:<root>.ValidatedProperties
BLOCK_BODY
RETURN type=kotlin.Nothing from='public open fun <get-test1> (): kotlin.String declared in <root>.ValidatedProperties'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test1 type:kotlin.String visibility:private [final]' type=kotlin.String origin=null
receiver: GET_VAR '<this>: <root>.ValidatedProperties declared in <root>.ValidatedProperties.<get-test1>' type=<root>.ValidatedProperties origin=null
PROPERTY name:test2 visibility:public modality:OPEN [val]
FIELD PROPERTY_BACKING_FIELD name:test2 type:kotlin.String visibility:private [final]
EXPRESSION_BODY
GET_VAR 'test2: kotlin.String declared in <root>.ValidatedProperties.<init>' type=kotlin.String origin=INITIALIZE_PROPERTY_FROM_PARAMETER
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test2> visibility:public modality:OPEN <> ($this:<root>.ValidatedProperties) returnType:kotlin.String
correspondingProperty: PROPERTY name:test2 visibility:public modality:OPEN [val]
$this: VALUE_PARAMETER name:<this> type:<root>.ValidatedProperties
BLOCK_BODY
RETURN type=kotlin.Nothing from='public open fun <get-test2> (): kotlin.String declared in <root>.ValidatedProperties'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test2 type:kotlin.String visibility:private [final]' type=kotlin.String origin=null
receiver: GET_VAR '<this>: <root>.ValidatedProperties declared in <root>.ValidatedProperties.<get-test2>' type=<root>.ValidatedProperties origin=null
FUN name:component1 visibility:public modality:FINAL <> ($this:<root>.ValidatedProperties) returnType:kotlin.String
$this: VALUE_PARAMETER name:<this> type:<root>.ValidatedProperties
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun component1 (): kotlin.String declared in <root>.ValidatedProperties'
CALL 'public open fun <get-test1> (): kotlin.String declared in <root>.ValidatedProperties' type=kotlin.String origin=null
$this: GET_VAR '<this>: <root>.ValidatedProperties declared in <root>.ValidatedProperties.component1' type=<root>.ValidatedProperties origin=null
FUN name:component2 visibility:public modality:FINAL <> ($this:<root>.ValidatedProperties) returnType:kotlin.String
$this: VALUE_PARAMETER name:<this> type:<root>.ValidatedProperties
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun component2 (): kotlin.String declared in <root>.ValidatedProperties'
CALL 'public open fun <get-test2> (): kotlin.String declared in <root>.ValidatedProperties' type=kotlin.String origin=null
$this: GET_VAR '<this>: <root>.ValidatedProperties declared in <root>.ValidatedProperties.component2' type=<root>.ValidatedProperties origin=null
FUN name:copy visibility:public modality:FINAL <> ($this:<root>.ValidatedProperties, test1:kotlin.String, test2:kotlin.String) returnType:<root>.ValidatedProperties
$this: VALUE_PARAMETER name:<this> type:<root>.ValidatedProperties
VALUE_PARAMETER name:test1 index:0 type:kotlin.String
EXPRESSION_BODY
CALL 'public open fun <get-test1> (): kotlin.String declared in <root>.ValidatedProperties' type=kotlin.String origin=null
$this: GET_VAR '<this>: <root>.ValidatedProperties declared in <root>.ValidatedProperties.copy' type=<root>.ValidatedProperties origin=null
VALUE_PARAMETER name:test2 index:1 type:kotlin.String
EXPRESSION_BODY
CALL 'public open fun <get-test2> (): kotlin.String declared in <root>.ValidatedProperties' type=kotlin.String origin=null
$this: GET_VAR '<this>: <root>.ValidatedProperties declared in <root>.ValidatedProperties.copy' type=<root>.ValidatedProperties origin=null
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun copy (test1: kotlin.String, test2: kotlin.String): <root>.ValidatedProperties declared in <root>.ValidatedProperties'
CONSTRUCTOR_CALL 'public constructor <init> (test1: kotlin.String, test2: kotlin.String) [primary] declared in <root>.ValidatedProperties' type=<root>.ValidatedProperties origin=null
test1: GET_VAR 'test1: kotlin.String declared in <root>.ValidatedProperties.copy' type=kotlin.String origin=null
test2: GET_VAR 'test2: kotlin.String declared in <root>.ValidatedProperties.copy' type=kotlin.String origin=null
FUN GENERATED_DATA_CLASS_MEMBER name:equals visibility:public modality:OPEN <> ($this:<root>.ValidatedProperties, other:kotlin.Any?) returnType:kotlin.Boolean
overridden:
public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any
$this: VALUE_PARAMETER GENERATED_DATA_CLASS_MEMBER name:<this> type:<root>.ValidatedProperties
VALUE_PARAMETER GENERATED_DATA_CLASS_MEMBER name:other index:0 type:kotlin.Any?
BLOCK_BODY
WHEN type=kotlin.Unit origin=null
BRANCH
if: CALL 'public final fun EQEQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQEQ
arg0: GET_VAR '<this>: <root>.ValidatedProperties declared in <root>.ValidatedProperties.equals' type=<root>.ValidatedProperties origin=null
arg1: GET_VAR 'other: kotlin.Any? declared in <root>.ValidatedProperties.equals' type=kotlin.Any? origin=null
then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in <root>.ValidatedProperties'
CONST Boolean type=kotlin.Boolean value=true
WHEN type=kotlin.Unit origin=null
BRANCH
if: TYPE_OP type=kotlin.Boolean origin=NOT_INSTANCEOF typeOperand=<root>.ValidatedProperties
GET_VAR 'other: kotlin.Any? declared in <root>.ValidatedProperties.equals' type=kotlin.Any? origin=null
then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in <root>.ValidatedProperties'
CONST Boolean type=kotlin.Boolean value=false
VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:<root>.ValidatedProperties [val]
TYPE_OP type=<root>.ValidatedProperties origin=CAST typeOperand=<root>.ValidatedProperties
GET_VAR 'other: kotlin.Any? declared in <root>.ValidatedProperties.equals' type=kotlin.Any? origin=null
WHEN type=kotlin.Unit origin=null
BRANCH
if: CALL 'public final fun not (): kotlin.Boolean [operator] declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ
$this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ
arg0: CALL 'public open fun <get-test1> (): kotlin.String declared in <root>.ValidatedProperties' type=kotlin.String origin=null
$this: GET_VAR '<this>: <root>.ValidatedProperties declared in <root>.ValidatedProperties.equals' type=<root>.ValidatedProperties origin=null
arg1: CALL 'public open fun <get-test1> (): kotlin.String declared in <root>.ValidatedProperties' type=kotlin.String origin=null
$this: GET_VAR 'val tmp_0: <root>.ValidatedProperties [val] declared in <root>.ValidatedProperties.equals' type=<root>.ValidatedProperties origin=null
then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in <root>.ValidatedProperties'
CONST Boolean type=kotlin.Boolean value=false
WHEN type=kotlin.Unit origin=null
BRANCH
if: CALL 'public final fun not (): kotlin.Boolean [operator] declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ
$this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ
arg0: CALL 'public open fun <get-test2> (): kotlin.String declared in <root>.ValidatedProperties' type=kotlin.String origin=null
$this: GET_VAR '<this>: <root>.ValidatedProperties declared in <root>.ValidatedProperties.equals' type=<root>.ValidatedProperties origin=null
arg1: CALL 'public open fun <get-test2> (): kotlin.String declared in <root>.ValidatedProperties' type=kotlin.String origin=null
$this: GET_VAR 'val tmp_0: <root>.ValidatedProperties [val] declared in <root>.ValidatedProperties.equals' type=<root>.ValidatedProperties origin=null
then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in <root>.ValidatedProperties'
CONST Boolean type=kotlin.Boolean value=false
RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in <root>.ValidatedProperties'
CONST Boolean type=kotlin.Boolean value=true
FUN GENERATED_DATA_CLASS_MEMBER name:hashCode visibility:public modality:OPEN <> ($this:<root>.ValidatedProperties) returnType:kotlin.Int
overridden:
public open fun hashCode (): kotlin.Int declared in kotlin.Any
$this: VALUE_PARAMETER GENERATED_DATA_CLASS_MEMBER name:<this> type:<root>.ValidatedProperties
BLOCK_BODY
VAR name:result type:kotlin.Int [var]
CALL 'public open fun hashCode (): kotlin.Int [fake_override] declared in kotlin.String' type=kotlin.Int origin=null
$this: CALL 'public open fun <get-test1> (): kotlin.String declared in <root>.ValidatedProperties' type=kotlin.String origin=null
$this: GET_VAR '<this>: <root>.ValidatedProperties declared in <root>.ValidatedProperties.hashCode' type=<root>.ValidatedProperties origin=null
SET_VAR 'var result: kotlin.Int [var] declared in <root>.ValidatedProperties.hashCode' type=kotlin.Unit origin=EQ
CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: CALL 'public final fun times (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: GET_VAR 'var result: kotlin.Int [var] declared in <root>.ValidatedProperties.hashCode' type=kotlin.Int origin=null
other: CONST Int type=kotlin.Int value=31
other: CALL 'public open fun hashCode (): kotlin.Int [fake_override] declared in kotlin.String' type=kotlin.Int origin=null
$this: CALL 'public open fun <get-test2> (): kotlin.String declared in <root>.ValidatedProperties' type=kotlin.String origin=null
$this: GET_VAR '<this>: <root>.ValidatedProperties declared in <root>.ValidatedProperties.hashCode' type=<root>.ValidatedProperties origin=null
RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in <root>.ValidatedProperties'
GET_VAR 'var result: kotlin.Int [var] declared in <root>.ValidatedProperties.hashCode' type=kotlin.Int origin=null
FUN GENERATED_DATA_CLASS_MEMBER name:toString visibility:public modality:OPEN <> ($this:<root>.ValidatedProperties) returnType:kotlin.String
overridden:
public open fun toString (): kotlin.String declared in kotlin.Any
$this: VALUE_PARAMETER GENERATED_DATA_CLASS_MEMBER name:<this> type:<root>.ValidatedProperties
BLOCK_BODY
RETURN type=kotlin.Nothing from='public open fun toString (): kotlin.String declared in <root>.ValidatedProperties'
STRING_CONCATENATION type=kotlin.String
CONST String type=kotlin.String value="ValidatedProperties("
CONST String type=kotlin.String value="test1="
CALL 'public open fun <get-test1> (): kotlin.String declared in <root>.ValidatedProperties' type=kotlin.String origin=null
$this: GET_VAR '<this>: <root>.ValidatedProperties declared in <root>.ValidatedProperties.toString' type=<root>.ValidatedProperties origin=null
CONST String type=kotlin.String value=", "
CONST String type=kotlin.String value="test2="
CALL 'public open fun <get-test2> (): kotlin.String declared in <root>.ValidatedProperties' type=kotlin.String origin=null
$this: GET_VAR '<this>: <root>.ValidatedProperties declared in <root>.ValidatedProperties.toString' type=<root>.ValidatedProperties origin=null
CONST String type=kotlin.String value=")"
+7
View File
@@ -0,0 +1,7 @@
// This test emulates 'allopen' compiler plugin.
@Suppress("INCOMPATIBLE_MODIFIERS")
open data class ValidatedProperties(
open val test1: String,
open val test2: String
)
@@ -0,0 +1,56 @@
@Suppress(names = ["INCOMPATIBLE_MODIFIERS"])
open data class ValidatedProperties {
constructor(test1: String, test2: String) /* primary */ {
super/*Any*/()
/* <init>() */
}
open val test1: String
field = test1
open get
open val test2: String
field = test2
open get
operator fun component1(): String {
return <this>.<get-test1>()
}
operator fun component2(): String {
return <this>.<get-test2>()
}
fun copy(test1: String = <this>.<get-test1>(), test2: String = <this>.<get-test2>()): ValidatedProperties {
return ValidatedProperties(test1 = test1, test2 = test2)
}
override fun toString(): String {
return "ValidatedProperties(" + "test1=" + <this>.<get-test1>() + ", " + "test2=" + <this>.<get-test2>() + ")"
}
override fun hashCode(): Int {
var result: Int = <this>.<get-test1>().hashCode()
result = result.times(other = 31).plus(other = <this>.<get-test2>().hashCode())
return result
}
override operator fun equals(other: Any?): Boolean {
when {
EQEQEQ(arg0 = <this>, arg1 = other) -> return true
}
when {
other !is ValidatedProperties -> return false
}
val tmp0_other_with_cast: ValidatedProperties = other as ValidatedProperties
when {
EQEQ(arg0 = <this>.<get-test1>(), arg1 = tmp0_other_with_cast.<get-test1>()).not() -> return false
}
when {
EQEQ(arg0 = <this>.<get-test2>(), arg1 = tmp0_other_with_cast.<get-test2>()).not() -> return false
}
return true
}
}
+139
View File
@@ -0,0 +1,139 @@
FILE fqName:<root> fileName:/openDataClass.kt
CLASS CLASS name:ValidatedProperties modality:OPEN visibility:public [data] superTypes:[kotlin.Any]
annotations:
Suppress(names = ['INCOMPATIBLE_MODIFIERS'])
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.ValidatedProperties
CONSTRUCTOR visibility:public <> (test1:kotlin.String, test2:kotlin.String) returnType:<root>.ValidatedProperties [primary]
VALUE_PARAMETER name:test1 index:0 type:kotlin.String
VALUE_PARAMETER name:test2 index:1 type:kotlin.String
BLOCK_BODY
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in kotlin.Any'
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:ValidatedProperties modality:OPEN visibility:public [data] superTypes:[kotlin.Any]'
PROPERTY name:test1 visibility:public modality:OPEN [val]
FIELD PROPERTY_BACKING_FIELD name:test1 type:kotlin.String visibility:private [final]
EXPRESSION_BODY
GET_VAR 'test1: kotlin.String declared in <root>.ValidatedProperties.<init>' type=kotlin.String origin=INITIALIZE_PROPERTY_FROM_PARAMETER
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test1> visibility:public modality:OPEN <> ($this:<root>.ValidatedProperties) returnType:kotlin.String
correspondingProperty: PROPERTY name:test1 visibility:public modality:OPEN [val]
$this: VALUE_PARAMETER name:<this> type:<root>.ValidatedProperties
BLOCK_BODY
RETURN type=kotlin.Nothing from='public open fun <get-test1> (): kotlin.String declared in <root>.ValidatedProperties'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test1 type:kotlin.String visibility:private [final]' type=kotlin.String origin=null
receiver: GET_VAR '<this>: <root>.ValidatedProperties declared in <root>.ValidatedProperties.<get-test1>' type=<root>.ValidatedProperties origin=null
PROPERTY name:test2 visibility:public modality:OPEN [val]
FIELD PROPERTY_BACKING_FIELD name:test2 type:kotlin.String visibility:private [final]
EXPRESSION_BODY
GET_VAR 'test2: kotlin.String declared in <root>.ValidatedProperties.<init>' type=kotlin.String origin=INITIALIZE_PROPERTY_FROM_PARAMETER
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test2> visibility:public modality:OPEN <> ($this:<root>.ValidatedProperties) returnType:kotlin.String
correspondingProperty: PROPERTY name:test2 visibility:public modality:OPEN [val]
$this: VALUE_PARAMETER name:<this> type:<root>.ValidatedProperties
BLOCK_BODY
RETURN type=kotlin.Nothing from='public open fun <get-test2> (): kotlin.String declared in <root>.ValidatedProperties'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test2 type:kotlin.String visibility:private [final]' type=kotlin.String origin=null
receiver: GET_VAR '<this>: <root>.ValidatedProperties declared in <root>.ValidatedProperties.<get-test2>' type=<root>.ValidatedProperties origin=null
FUN GENERATED_DATA_CLASS_MEMBER name:component1 visibility:public modality:FINAL <> ($this:<root>.ValidatedProperties) returnType:kotlin.String [operator]
$this: VALUE_PARAMETER name:<this> type:<root>.ValidatedProperties
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun component1 (): kotlin.String [operator] declared in <root>.ValidatedProperties'
CALL 'public open fun <get-test1> (): kotlin.String declared in <root>.ValidatedProperties' type=kotlin.String origin=null
$this: GET_VAR '<this>: <root>.ValidatedProperties declared in <root>.ValidatedProperties.component1' type=<root>.ValidatedProperties origin=null
FUN GENERATED_DATA_CLASS_MEMBER name:component2 visibility:public modality:FINAL <> ($this:<root>.ValidatedProperties) returnType:kotlin.String [operator]
$this: VALUE_PARAMETER name:<this> type:<root>.ValidatedProperties
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun component2 (): kotlin.String [operator] declared in <root>.ValidatedProperties'
CALL 'public open fun <get-test2> (): kotlin.String declared in <root>.ValidatedProperties' type=kotlin.String origin=null
$this: GET_VAR '<this>: <root>.ValidatedProperties declared in <root>.ValidatedProperties.component2' type=<root>.ValidatedProperties origin=null
FUN GENERATED_DATA_CLASS_MEMBER name:copy visibility:public modality:FINAL <> ($this:<root>.ValidatedProperties, test1:kotlin.String, test2:kotlin.String) returnType:<root>.ValidatedProperties
$this: VALUE_PARAMETER name:<this> type:<root>.ValidatedProperties
VALUE_PARAMETER name:test1 index:0 type:kotlin.String
EXPRESSION_BODY
CALL 'public open fun <get-test1> (): kotlin.String declared in <root>.ValidatedProperties' type=kotlin.String origin=null
$this: GET_VAR '<this>: <root>.ValidatedProperties declared in <root>.ValidatedProperties.copy' type=<root>.ValidatedProperties origin=null
VALUE_PARAMETER name:test2 index:1 type:kotlin.String
EXPRESSION_BODY
CALL 'public open fun <get-test2> (): kotlin.String declared in <root>.ValidatedProperties' type=kotlin.String origin=null
$this: GET_VAR '<this>: <root>.ValidatedProperties declared in <root>.ValidatedProperties.copy' type=<root>.ValidatedProperties origin=null
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun copy (test1: kotlin.String, test2: kotlin.String): <root>.ValidatedProperties declared in <root>.ValidatedProperties'
CONSTRUCTOR_CALL 'public constructor <init> (test1: kotlin.String, test2: kotlin.String) [primary] declared in <root>.ValidatedProperties' type=<root>.ValidatedProperties origin=null
test1: GET_VAR 'test1: kotlin.String declared in <root>.ValidatedProperties.copy' type=kotlin.String origin=null
test2: GET_VAR 'test2: kotlin.String declared in <root>.ValidatedProperties.copy' type=kotlin.String origin=null
FUN GENERATED_DATA_CLASS_MEMBER name:toString visibility:public modality:OPEN <> ($this:<root>.ValidatedProperties) returnType:kotlin.String
overridden:
public open fun toString (): kotlin.String declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:<root>.ValidatedProperties
BLOCK_BODY
RETURN type=kotlin.Nothing from='public open fun toString (): kotlin.String declared in <root>.ValidatedProperties'
STRING_CONCATENATION type=kotlin.String
CONST String type=kotlin.String value="ValidatedProperties("
CONST String type=kotlin.String value="test1="
CALL 'public open fun <get-test1> (): kotlin.String declared in <root>.ValidatedProperties' type=kotlin.String origin=null
$this: GET_VAR '<this>: <root>.ValidatedProperties declared in <root>.ValidatedProperties.toString' type=<root>.ValidatedProperties origin=null
CONST String type=kotlin.String value=", "
CONST String type=kotlin.String value="test2="
CALL 'public open fun <get-test2> (): kotlin.String declared in <root>.ValidatedProperties' type=kotlin.String origin=null
$this: GET_VAR '<this>: <root>.ValidatedProperties declared in <root>.ValidatedProperties.toString' type=<root>.ValidatedProperties origin=null
CONST String type=kotlin.String value=")"
FUN GENERATED_DATA_CLASS_MEMBER name:hashCode visibility:public modality:OPEN <> ($this:<root>.ValidatedProperties) returnType:kotlin.Int
overridden:
public open fun hashCode (): kotlin.Int declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:<root>.ValidatedProperties
BLOCK_BODY
VAR name:result type:kotlin.Int [var]
CALL 'public open fun hashCode (): kotlin.Int [fake_override] declared in kotlin.String' type=kotlin.Int origin=null
$this: CALL 'public open fun <get-test1> (): kotlin.String declared in <root>.ValidatedProperties' type=kotlin.String origin=null
$this: GET_VAR '<this>: <root>.ValidatedProperties declared in <root>.ValidatedProperties.hashCode' type=<root>.ValidatedProperties origin=null
SET_VAR 'var result: kotlin.Int [var] declared in <root>.ValidatedProperties.hashCode' type=kotlin.Unit origin=EQ
CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: CALL 'public final fun times (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: GET_VAR 'var result: kotlin.Int [var] declared in <root>.ValidatedProperties.hashCode' type=kotlin.Int origin=null
other: CONST Int type=kotlin.Int value=31
other: CALL 'public open fun hashCode (): kotlin.Int [fake_override] declared in kotlin.String' type=kotlin.Int origin=null
$this: CALL 'public open fun <get-test2> (): kotlin.String declared in <root>.ValidatedProperties' type=kotlin.String origin=null
$this: GET_VAR '<this>: <root>.ValidatedProperties declared in <root>.ValidatedProperties.hashCode' type=<root>.ValidatedProperties origin=null
RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in <root>.ValidatedProperties'
GET_VAR 'var result: kotlin.Int [var] declared in <root>.ValidatedProperties.hashCode' type=kotlin.Int origin=null
FUN GENERATED_DATA_CLASS_MEMBER name:equals visibility:public modality:OPEN <> ($this:<root>.ValidatedProperties, other:kotlin.Any?) returnType:kotlin.Boolean [operator]
overridden:
public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:<root>.ValidatedProperties
VALUE_PARAMETER name:other index:0 type:kotlin.Any?
BLOCK_BODY
WHEN type=kotlin.Unit origin=null
BRANCH
if: CALL 'public final fun EQEQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQEQ
arg0: GET_VAR '<this>: <root>.ValidatedProperties declared in <root>.ValidatedProperties.equals' type=<root>.ValidatedProperties origin=null
arg1: GET_VAR 'other: kotlin.Any? declared in <root>.ValidatedProperties.equals' type=kotlin.Any? origin=null
then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in <root>.ValidatedProperties'
CONST Boolean type=kotlin.Boolean value=true
WHEN type=kotlin.Unit origin=null
BRANCH
if: TYPE_OP type=kotlin.Boolean origin=NOT_INSTANCEOF typeOperand=<root>.ValidatedProperties
GET_VAR 'other: kotlin.Any? declared in <root>.ValidatedProperties.equals' type=kotlin.Any? origin=null
then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in <root>.ValidatedProperties'
CONST Boolean type=kotlin.Boolean value=false
VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:<root>.ValidatedProperties [val]
TYPE_OP type=<root>.ValidatedProperties origin=CAST typeOperand=<root>.ValidatedProperties
GET_VAR 'other: kotlin.Any? declared in <root>.ValidatedProperties.equals' type=kotlin.Any? origin=null
WHEN type=kotlin.Unit origin=null
BRANCH
if: CALL 'public final fun not (): kotlin.Boolean [operator] declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ
$this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ
arg0: CALL 'public open fun <get-test1> (): kotlin.String declared in <root>.ValidatedProperties' type=kotlin.String origin=null
$this: GET_VAR '<this>: <root>.ValidatedProperties declared in <root>.ValidatedProperties.equals' type=<root>.ValidatedProperties origin=null
arg1: CALL 'public open fun <get-test1> (): kotlin.String declared in <root>.ValidatedProperties' type=kotlin.String origin=null
$this: GET_VAR 'val tmp_0: <root>.ValidatedProperties [val] declared in <root>.ValidatedProperties.equals' type=<root>.ValidatedProperties origin=null
then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in <root>.ValidatedProperties'
CONST Boolean type=kotlin.Boolean value=false
WHEN type=kotlin.Unit origin=null
BRANCH
if: CALL 'public final fun not (): kotlin.Boolean [operator] declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ
$this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ
arg0: CALL 'public open fun <get-test2> (): kotlin.String declared in <root>.ValidatedProperties' type=kotlin.String origin=null
$this: GET_VAR '<this>: <root>.ValidatedProperties declared in <root>.ValidatedProperties.equals' type=<root>.ValidatedProperties origin=null
arg1: CALL 'public open fun <get-test2> (): kotlin.String declared in <root>.ValidatedProperties' type=kotlin.String origin=null
$this: GET_VAR 'val tmp_0: <root>.ValidatedProperties [val] declared in <root>.ValidatedProperties.equals' type=<root>.ValidatedProperties origin=null
then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in <root>.ValidatedProperties'
CONST Boolean type=kotlin.Boolean value=false
RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in <root>.ValidatedProperties'
CONST Boolean type=kotlin.Boolean value=true
@@ -4282,6 +4282,16 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/properties"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
@TestMetadata("dataClass.kt")
public void testDataClass() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/properties/dataClass.kt");
}
@TestMetadata("openDataClass.kt")
public void testOpenDataClass() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/properties/openDataClass.kt");
}
@TestMetadata("compiler/testData/codegen/bytecodeText/properties/lateinit")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -4210,6 +4210,16 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/properties"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@TestMetadata("dataClass.kt")
public void testDataClass() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/properties/dataClass.kt");
}
@TestMetadata("openDataClass.kt")
public void testOpenDataClass() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/properties/openDataClass.kt");
}
@TestMetadata("compiler/testData/codegen/bytecodeText/properties/lateinit")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -220,6 +220,11 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase {
runTest("compiler/testData/ir/irText/classes/objectWithInitializers.kt");
}
@TestMetadata("openDataClass.kt")
public void testOpenDataClass() throws Exception {
runTest("compiler/testData/ir/irText/classes/openDataClass.kt");
}
@TestMetadata("outerClassAccess.kt")
public void testOuterClassAccess() throws Exception {
runTest("compiler/testData/ir/irText/classes/outerClassAccess.kt");