Desugar synthetic Java properties in psi2ir
This commit is contained in:
@@ -18,9 +18,7 @@ package org.jetbrains.kotlin.psi2ir
|
|||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
import org.jetbrains.kotlin.name.Name
|
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?.startOffsetOrUndefined get() = this?.startOffset ?: UNDEFINED_OFFSET
|
||||||
val PsiElement?.endOffsetOrUndefined get() = this?.endOffset ?: 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
|
||||||
|
|||||||
+6
-4
@@ -29,6 +29,8 @@ import org.jetbrains.kotlin.psi.*
|
|||||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||||
import org.jetbrains.kotlin.psi2ir.intermediate.*
|
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.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall
|
import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
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) {
|
if (ktLeft is KtArrayAccessExpression) {
|
||||||
return generateArrayAccessAssignmentReceiver(ktLeft, origin)
|
return generateArrayAccessAssignmentReceiver(ktLeft, origin)
|
||||||
}
|
}
|
||||||
@@ -204,10 +206,10 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen
|
|||||||
): PropertyLValueBase {
|
): PropertyLValueBase {
|
||||||
val superQualifierSymbol = superQualifier?.let { context.symbolTable.referenceClass(it) }
|
val superQualifierSymbol = superQualifier?.let { context.symbolTable.referenceClass(it) }
|
||||||
|
|
||||||
val getterDescriptor = descriptor.getter
|
val getterDescriptor = descriptor.unwrappedGetMethod
|
||||||
val getterSymbol = getterDescriptor?.let { context.symbolTable.referenceFunction(it.original) }
|
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 setterSymbol = setterDescriptor?.let { context.symbolTable.referenceFunction(it.original) }
|
||||||
|
|
||||||
val propertyIrType = descriptor.type.toIrType()
|
val propertyIrType = descriptor.type.toIrType()
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.psi.KtElement
|
|||||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||||
import org.jetbrains.kotlin.psi2ir.intermediate.*
|
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.ResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument
|
||||||
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
|
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 =
|
fun generateDelegatingConstructorCall(startOffset: Int, endOffset: Int, call: CallBuilder): IrExpression =
|
||||||
call.callReceiver.call { dispatchReceiver, extensionReceiver ->
|
call.callReceiver.call { dispatchReceiver, extensionReceiver ->
|
||||||
val descriptor = call.descriptor as? ClassConstructorDescriptor
|
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 constructorSymbol = context.symbolTable.referenceConstructor(descriptor.original)
|
||||||
val irCall = IrDelegatingConstructorCallImpl(
|
val irCall = IrDelegatingConstructorCallImpl(
|
||||||
startOffset, endOffset,
|
startOffset, endOffset,
|
||||||
@@ -142,7 +143,8 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
|||||||
return call.callReceiver.call { dispatchReceiverValue, extensionReceiverValue ->
|
return call.callReceiver.call { dispatchReceiverValue, extensionReceiverValue ->
|
||||||
val superQualifierSymbol = call.superQualifier?.let { context.symbolTable.referenceClass(it) }
|
val superQualifierSymbol = call.superQualifier?.let { context.symbolTable.referenceClass(it) }
|
||||||
|
|
||||||
val getterDescriptor = descriptor.getter
|
val getterDescriptor = descriptor.unwrappedGetMethod
|
||||||
|
|
||||||
if (getterDescriptor != null) {
|
if (getterDescriptor != null) {
|
||||||
val getterSymbol = context.symbolTable.referenceFunction(getterDescriptor.original)
|
val getterSymbol = context.symbolTable.referenceFunction(getterDescriptor.original)
|
||||||
IrGetterCallImpl(
|
IrGetterCallImpl(
|
||||||
|
|||||||
+2
-2
@@ -236,7 +236,7 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
|
|||||||
val comparisonType = comparisonInfo?.comparisonType
|
val comparisonType = comparisonInfo?.comparisonType
|
||||||
|
|
||||||
val eqeqSymbol = context.irBuiltIns.ieee754equalsFunByOperandType[comparisonType]?.symbol
|
val eqeqSymbol = context.irBuiltIns.ieee754equalsFunByOperandType[comparisonType]?.symbol
|
||||||
?: context.irBuiltIns.eqeqSymbol
|
?: context.irBuiltIns.eqeqSymbol
|
||||||
|
|
||||||
val irEquals = IrBinaryPrimitiveImpl(
|
val irEquals = IrBinaryPrimitiveImpl(
|
||||||
expression.startOffset, expression.endOffset,
|
expression.startOffset, expression.endOffset,
|
||||||
@@ -275,7 +275,7 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
|
|||||||
val comparisonType = comparisonInfo.comparisonType
|
val comparisonType = comparisonInfo.comparisonType
|
||||||
val eqeqSymbol =
|
val eqeqSymbol =
|
||||||
context.irBuiltIns.ieee754equalsFunByOperandType[comparisonType]?.symbol
|
context.irBuiltIns.ieee754equalsFunByOperandType[comparisonType]?.symbol
|
||||||
?: context.irBuiltIns.eqeqSymbol
|
?: context.irBuiltIns.eqeqSymbol
|
||||||
IrBinaryPrimitiveImpl(
|
IrBinaryPrimitiveImpl(
|
||||||
startOffset, endOffset,
|
startOffset, endOffset,
|
||||||
context.irBuiltIns.booleanType,
|
context.irBuiltIns.booleanType,
|
||||||
|
|||||||
@@ -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) {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
FILE fqName:<root> 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
|
||||||
@@ -2,7 +2,7 @@ FILE fqName:<root> fileName:/javaSyntheticProperty.kt
|
|||||||
PROPERTY name:test visibility:public modality:FINAL flags:val
|
PROPERTY name:test visibility:public modality:FINAL flags:val
|
||||||
FIELD PROPERTY_BACKING_FIELD name:test type:kotlin.String? visibility:public flags:final
|
FIELD PROPERTY_BACKING_FIELD name:test type:kotlin.String? visibility:public flags:final
|
||||||
EXPRESSION_BODY
|
EXPRESSION_BODY
|
||||||
CALL '<get-foo>() 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
|
$receiver: CALL 'constructor J()' type=J origin=null
|
||||||
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test> visibility:public modality:FINAL <> () returnType:kotlin.String? flags:
|
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test> visibility:public modality:FINAL <> () returnType:kotlin.String? flags:
|
||||||
correspondingProperty: PROPERTY name:test visibility:public modality:FINAL flags:val
|
correspondingProperty: PROPERTY name:test visibility:public modality:FINAL flags:val
|
||||||
|
|||||||
@@ -5,6 +5,6 @@ FILE fqName:<root> fileName:/jdkClassSyntheticProperty.kt
|
|||||||
$receiver: VALUE_PARAMETER name:<this> type:java.lang.Class<*> flags:
|
$receiver: VALUE_PARAMETER name:<this> type:java.lang.Class<*> flags:
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
RETURN type=kotlin.Nothing from='<get-test>() on Class<*>: Array<(out) Field!>!'
|
RETURN type=kotlin.Nothing from='<get-test>() on Class<*>: Array<(out) Field!>!'
|
||||||
CALL '<get-declaredFields>() on Class<out Any!>: Array<(out) Field!>!' type=kotlin.Array<out java.lang.reflect.Field!>? origin=GET_PROPERTY
|
CALL 'getDeclaredFields(): Array<(out) Field!>!' type=kotlin.Array<out java.lang.reflect.Field!>? origin=GET_PROPERTY
|
||||||
<`0>: kotlin.Any?
|
<`0>: kotlin.Any?
|
||||||
$receiver: GET_VAR 'this@test: Class<*>' type=java.lang.Class<*> origin=null
|
$receiver: GET_VAR 'this@test: Class<*>' type=java.lang.Class<*> origin=null
|
||||||
|
|||||||
@@ -902,6 +902,11 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase {
|
|||||||
runTest("compiler/testData/ir/irText/expressions/interfaceThisRef.kt");
|
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")
|
@TestMetadata("jvmInstanceFieldReference.kt")
|
||||||
public void testJvmInstanceFieldReference() throws Exception {
|
public void testJvmInstanceFieldReference() throws Exception {
|
||||||
runTest("compiler/testData/ir/irText/expressions/jvmInstanceFieldReference.kt");
|
runTest("compiler/testData/ir/irText/expressions/jvmInstanceFieldReference.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user