From 99a71b9ecc0db4bb404a3c77daab6da14d4e978d Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Wed, 18 Jul 2018 14:08:14 +0300 Subject: [PATCH] Desugar synthetic Java properties in psi2ir --- .../src/org/jetbrains/kotlin/psi2ir/KotlinUtils.kt | 8 +++++--- .../kotlin/psi2ir/generators/AssignmentGenerator.kt | 10 ++++++---- .../kotlin/psi2ir/generators/CallGenerator.kt | 6 ++++-- .../generators/OperatorExpressionGenerator.kt | 4 ++-- .../expressions/javaSyntheticPropertyAccess.kt | 12 ++++++++++++ .../expressions/javaSyntheticPropertyAccess.txt | 13 +++++++++++++ .../ir/irText/stubs/javaSyntheticProperty.txt | 2 +- .../ir/irText/stubs/jdkClassSyntheticProperty.txt | 2 +- .../kotlin/ir/IrTextTestCaseGenerated.java | 5 +++++ 9 files changed, 49 insertions(+), 13 deletions(-) create mode 100644 compiler/testData/ir/irText/expressions/javaSyntheticPropertyAccess.kt create mode 100644 compiler/testData/ir/irText/expressions/javaSyntheticPropertyAccess.txt diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/KotlinUtils.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/KotlinUtils.kt index 6e603b09e77..d9c59ce9810 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/KotlinUtils.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/KotlinUtils.kt @@ -18,9 +18,7 @@ package org.jetbrains.kotlin.psi2ir import com.intellij.psi.PsiElement import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.name.Name @@ -82,4 +80,8 @@ fun KotlinBuiltIns.findSingleFunction(name: Name): FunctionDescriptor = val PsiElement?.startOffsetOrUndefined get() = this?.startOffset ?: UNDEFINED_OFFSET val PsiElement?.endOffsetOrUndefined get() = this?.endOffset ?: UNDEFINED_OFFSET +val PropertyDescriptor.unwrappedGetMethod: FunctionDescriptor? + get() = if (this is SyntheticPropertyDescriptor) this.getMethod else getter +val PropertyDescriptor.unwrappedSetMethod: FunctionDescriptor? + get() = if (this is SyntheticPropertyDescriptor) this.setMethod else setter diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/AssignmentGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/AssignmentGenerator.kt index 47006ecbfd3..80e8ed36c5c 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/AssignmentGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/AssignmentGenerator.kt @@ -29,6 +29,8 @@ import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset import org.jetbrains.kotlin.psi2ir.intermediate.* +import org.jetbrains.kotlin.psi2ir.unwrappedGetMethod +import org.jetbrains.kotlin.psi2ir.unwrappedSetMethod import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall @@ -102,7 +104,7 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen } } - fun generateAssignmentReceiver(ktLeft: KtExpression, origin: IrStatementOrigin): AssignmentReceiver { + private fun generateAssignmentReceiver(ktLeft: KtExpression, origin: IrStatementOrigin): AssignmentReceiver { if (ktLeft is KtArrayAccessExpression) { return generateArrayAccessAssignmentReceiver(ktLeft, origin) } @@ -204,10 +206,10 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen ): PropertyLValueBase { val superQualifierSymbol = superQualifier?.let { context.symbolTable.referenceClass(it) } - val getterDescriptor = descriptor.getter - val getterSymbol = getterDescriptor?.let { context.symbolTable.referenceFunction(it.original) } + val getterDescriptor = descriptor.unwrappedGetMethod + val setterDescriptor = descriptor.unwrappedSetMethod - val setterDescriptor = descriptor.setter + val getterSymbol = getterDescriptor?.let { context.symbolTable.referenceFunction(it.original) } val setterSymbol = setterDescriptor?.let { context.symbolTable.referenceFunction(it.original) } val propertyIrType = descriptor.type.toIrType() diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt index 8290cd7b493..9bd30248df0 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset import org.jetbrains.kotlin.psi2ir.intermediate.* +import org.jetbrains.kotlin.psi2ir.unwrappedGetMethod import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject @@ -103,7 +104,7 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator fun generateDelegatingConstructorCall(startOffset: Int, endOffset: Int, call: CallBuilder): IrExpression = call.callReceiver.call { dispatchReceiver, extensionReceiver -> val descriptor = call.descriptor as? ClassConstructorDescriptor - ?: throw AssertionError("Class constructor expected: ${call.descriptor}") + ?: throw AssertionError("Class constructor expected: ${call.descriptor}") val constructorSymbol = context.symbolTable.referenceConstructor(descriptor.original) val irCall = IrDelegatingConstructorCallImpl( startOffset, endOffset, @@ -142,7 +143,8 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator return call.callReceiver.call { dispatchReceiverValue, extensionReceiverValue -> val superQualifierSymbol = call.superQualifier?.let { context.symbolTable.referenceClass(it) } - val getterDescriptor = descriptor.getter + val getterDescriptor = descriptor.unwrappedGetMethod + if (getterDescriptor != null) { val getterSymbol = context.symbolTable.referenceFunction(getterDescriptor.original) IrGetterCallImpl( diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt index cd0731defe3..8e0c6f3891b 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt @@ -236,7 +236,7 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat val comparisonType = comparisonInfo?.comparisonType val eqeqSymbol = context.irBuiltIns.ieee754equalsFunByOperandType[comparisonType]?.symbol - ?: context.irBuiltIns.eqeqSymbol + ?: context.irBuiltIns.eqeqSymbol val irEquals = IrBinaryPrimitiveImpl( expression.startOffset, expression.endOffset, @@ -275,7 +275,7 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat val comparisonType = comparisonInfo.comparisonType val eqeqSymbol = context.irBuiltIns.ieee754equalsFunByOperandType[comparisonType]?.symbol - ?: context.irBuiltIns.eqeqSymbol + ?: context.irBuiltIns.eqeqSymbol IrBinaryPrimitiveImpl( startOffset, endOffset, context.irBuiltIns.booleanType, diff --git a/compiler/testData/ir/irText/expressions/javaSyntheticPropertyAccess.kt b/compiler/testData/ir/irText/expressions/javaSyntheticPropertyAccess.kt new file mode 100644 index 00000000000..6a384159108 --- /dev/null +++ b/compiler/testData/ir/irText/expressions/javaSyntheticPropertyAccess.kt @@ -0,0 +1,12 @@ +// FILE: javaSyntheticPropertyAccess.kt +fun test(j: J) { + j.foo += 1 +} + +// FILE: J.java +public class J { + private int foo = 42; + + public int getFoo() { return foo; } + public void setFoo(int x) {} +} \ No newline at end of file diff --git a/compiler/testData/ir/irText/expressions/javaSyntheticPropertyAccess.txt b/compiler/testData/ir/irText/expressions/javaSyntheticPropertyAccess.txt new file mode 100644 index 00000000000..17cbc83d4b3 --- /dev/null +++ b/compiler/testData/ir/irText/expressions/javaSyntheticPropertyAccess.txt @@ -0,0 +1,13 @@ +FILE fqName: fileName:/javaSyntheticPropertyAccess.kt + FUN name:test visibility:public modality:FINAL <> (j:J) returnType:kotlin.Unit flags: + VALUE_PARAMETER name:j index:0 type:J flags: + BLOCK_BODY + BLOCK type=kotlin.Unit origin=PLUSEQ + VAR IR_TEMPORARY_VARIABLE name:tmp0_receiver type:J flags:val + GET_VAR 'value-parameter j: J' type=J origin=null + CALL 'setFoo(Int): Unit' type=kotlin.Unit origin=PLUSEQ + $receiver: GET_VAR 'tmp0_receiver: J' type=J origin=null + x: CALL 'plus(Int): Int' type=kotlin.Int origin=PLUSEQ + $this: CALL 'getFoo(): Int' type=kotlin.Int origin=PLUSEQ + $receiver: GET_VAR 'tmp0_receiver: J' type=J origin=null + other: CONST Int type=kotlin.Int value=1 diff --git a/compiler/testData/ir/irText/stubs/javaSyntheticProperty.txt b/compiler/testData/ir/irText/stubs/javaSyntheticProperty.txt index 88b41d96054..da3ca80b303 100644 --- a/compiler/testData/ir/irText/stubs/javaSyntheticProperty.txt +++ b/compiler/testData/ir/irText/stubs/javaSyntheticProperty.txt @@ -2,7 +2,7 @@ FILE fqName: fileName:/javaSyntheticProperty.kt PROPERTY name:test visibility:public modality:FINAL flags:val FIELD PROPERTY_BACKING_FIELD name:test type:kotlin.String? visibility:public flags:final EXPRESSION_BODY - CALL '() on J: String!' type=kotlin.String? origin=GET_PROPERTY + CALL 'getFoo(): String!' type=kotlin.String? origin=GET_PROPERTY $receiver: CALL 'constructor J()' type=J origin=null FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:kotlin.String? flags: correspondingProperty: PROPERTY name:test visibility:public modality:FINAL flags:val diff --git a/compiler/testData/ir/irText/stubs/jdkClassSyntheticProperty.txt b/compiler/testData/ir/irText/stubs/jdkClassSyntheticProperty.txt index 1697e1e0bc3..ea0ca002b3e 100644 --- a/compiler/testData/ir/irText/stubs/jdkClassSyntheticProperty.txt +++ b/compiler/testData/ir/irText/stubs/jdkClassSyntheticProperty.txt @@ -5,6 +5,6 @@ FILE fqName: fileName:/jdkClassSyntheticProperty.kt $receiver: VALUE_PARAMETER name: type:java.lang.Class<*> flags: BLOCK_BODY RETURN type=kotlin.Nothing from='() on Class<*>: Array<(out) Field!>!' - CALL '() on Class: Array<(out) Field!>!' type=kotlin.Array? origin=GET_PROPERTY + CALL 'getDeclaredFields(): Array<(out) Field!>!' type=kotlin.Array? origin=GET_PROPERTY <`0>: kotlin.Any? $receiver: GET_VAR 'this@test: Class<*>' type=java.lang.Class<*> origin=null diff --git a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java index 2f0eb7ebd00..f9a6474c8bf 100644 --- a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java @@ -902,6 +902,11 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase { runTest("compiler/testData/ir/irText/expressions/interfaceThisRef.kt"); } + @TestMetadata("javaSyntheticPropertyAccess.kt") + public void testJavaSyntheticPropertyAccess() throws Exception { + runTest("compiler/testData/ir/irText/expressions/javaSyntheticPropertyAccess.kt"); + } + @TestMetadata("jvmInstanceFieldReference.kt") public void testJvmInstanceFieldReference() throws Exception { runTest("compiler/testData/ir/irText/expressions/jvmInstanceFieldReference.kt");