FIR2IR: add support for callable reference to Java field

#KT-42656 Fixed
This commit is contained in:
Jinseong Jeon
2020-10-14 11:29:33 -07:00
committed by Mikhail Glukhikh
parent 65545a10c4
commit 5f64d6ec76
16 changed files with 51 additions and 22 deletions
@@ -207,7 +207,7 @@ class Fir2IrConverter(
) )
} }
is FirProperty -> { is FirProperty -> {
declarationStorage.getOrCreateProperty( declarationStorage.getOrCreateIrProperty(
declaration, parent, isLocal = isLocal declaration, parent, isLocal = isLocal
) )
} }
@@ -636,7 +636,7 @@ class Fir2IrDeclarationStorage(
} }
} }
internal val FirProperty.fieldVisibility: Visibility private val FirProperty.fieldVisibility: Visibility
get() = when { get() = when {
isLateInit -> setter?.visibility ?: status.visibility isLateInit -> setter?.visibility ?: status.visibility
isConst -> status.visibility isConst -> status.visibility
@@ -660,7 +660,7 @@ class Fir2IrDeclarationStorage(
return symbolTable.declareProperty(signature, { Fir2IrPropertySymbol(signature, containerSource) }, factory) return symbolTable.declareProperty(signature, { Fir2IrPropertySymbol(signature, containerSource) }, factory)
} }
fun getOrCreateProperty( fun getOrCreateIrProperty(
property: FirProperty, property: FirProperty,
irParent: IrDeclarationParent?, irParent: IrDeclarationParent?,
isLocal: Boolean = false, isLocal: Boolean = false,
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.backend.generators
import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.backend.* import org.jetbrains.kotlin.fir.backend.*
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.buildProperty
import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
import org.jetbrains.kotlin.fir.psi import org.jetbrains.kotlin.fir.psi
@@ -53,6 +54,11 @@ class CallAndReferenceGenerator(
): IrExpression { ): IrExpression {
val symbol = callableReferenceAccess.calleeReference.toSymbol(session, classifierStorage, declarationStorage, conversionScope) val symbol = callableReferenceAccess.calleeReference.toSymbol(session, classifierStorage, declarationStorage, conversionScope)
val type = callableReferenceAccess.typeRef.toIrType() val type = callableReferenceAccess.typeRef.toIrType()
fun propertyOrigin(): IrStatementOrigin? =
when (callableReferenceAccess.source?.psi?.parent) {
is KtPropertyDelegate -> IrStatementOrigin.PROPERTY_REFERENCE_FOR_DELEGATE
else -> null
}
return callableReferenceAccess.convertWithOffsets { startOffset, endOffset -> return callableReferenceAccess.convertWithOffsets { startOffset, endOffset ->
when (symbol) { when (symbol) {
is IrPropertySymbol -> { is IrPropertySymbol -> {
@@ -62,17 +68,13 @@ class CallAndReferenceGenerator(
referencedPropertyGetter != null -> null referencedPropertyGetter != null -> null
else -> referencedProperty.backingField?.symbol else -> referencedProperty.backingField?.symbol
} }
val origin = when (callableReferenceAccess.source?.psi?.parent) {
is KtPropertyDelegate -> IrStatementOrigin.PROPERTY_REFERENCE_FOR_DELEGATE
else -> null
}
IrPropertyReferenceImpl( IrPropertyReferenceImpl(
startOffset, endOffset, type, symbol, startOffset, endOffset, type, symbol,
typeArgumentsCount = referencedPropertyGetter?.typeParameters?.size ?: 0, typeArgumentsCount = referencedPropertyGetter?.typeParameters?.size ?: 0,
backingFieldSymbol, backingFieldSymbol,
referencedPropertyGetter?.symbol, referencedPropertyGetter?.symbol,
referencedProperty.setter?.symbol, referencedProperty.setter?.symbol,
origin propertyOrigin()
) )
} }
is IrLocalDelegatedPropertySymbol -> { is IrLocalDelegatedPropertySymbol -> {
@@ -84,6 +86,28 @@ class CallAndReferenceGenerator(
IrStatementOrigin.PROPERTY_REFERENCE_FOR_DELEGATE IrStatementOrigin.PROPERTY_REFERENCE_FOR_DELEGATE
) )
} }
is IrFieldSymbol -> {
val referencedField = symbol.owner
val propertySymbol = referencedField.correspondingPropertySymbol
?: run {
// In case of [IrField] without the corresponding property, we've created it directly from [FirField].
// Since it's used as a field reference, we need a bogus property as a placeholder.
val firSymbol =
(callableReferenceAccess.calleeReference as FirResolvedNamedReference).resolvedSymbol as FirFieldSymbol
declarationStorage.getOrCreateIrProperty(
firSymbol.fir.toProperty(), referencedField.parent
).symbol
}
IrPropertyReferenceImpl(
startOffset, endOffset, type,
propertySymbol,
typeArgumentsCount = (type as? IrSimpleType)?.arguments?.size ?: 0,
symbol,
getter = if (referencedField.isStatic) null else propertySymbol.owner.getter?.symbol,
setter = if (referencedField.isStatic) null else propertySymbol.owner.setter?.symbol,
propertyOrigin()
)
}
is IrConstructorSymbol -> { is IrConstructorSymbol -> {
val constructor = symbol.owner val constructor = symbol.owner
val klass = constructor.parent as? IrClass val klass = constructor.parent as? IrClass
@@ -123,6 +147,21 @@ class CallAndReferenceGenerator(
}.applyTypeArguments(callableReferenceAccess).applyReceivers(callableReferenceAccess, explicitReceiverExpression) }.applyTypeArguments(callableReferenceAccess).applyReceivers(callableReferenceAccess, explicitReceiverExpression)
} }
private fun FirField.toProperty(): FirProperty =
buildProperty {
source = this@toProperty.source
session = this@toProperty.session
origin = this@toProperty.origin
returnTypeRef = this@toProperty.returnTypeRef
name = this@toProperty.name
isVar = this@toProperty.isVar
getter = this@toProperty.getter
setter = this@toProperty.setter
symbol = FirPropertySymbol(this@toProperty.symbol.callableId)
isLocal = false
status = this@toProperty.status
}
private fun FirQualifiedAccess.tryConvertToSamConstructorCall(type: IrType): IrTypeOperatorCall? { private fun FirQualifiedAccess.tryConvertToSamConstructorCall(type: IrType): IrTypeOperatorCall? {
val calleeReference = calleeReference as? FirResolvedNamedReference ?: return null val calleeReference = calleeReference as? FirResolvedNamedReference ?: return null
val fir = calleeReference.resolvedSymbol.fir val fir = calleeReference.resolvedSymbol.fir
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// FILE: JClass.java // FILE: JClass.java
public class JClass { public class JClass {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// WITH_RUNTIME // WITH_RUNTIME
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// WITH_REFLECT // WITH_REFLECT
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// WITH_REFLECT // WITH_REFLECT
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// FILE: J.java // FILE: J.java
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// WITH_REFLECT // WITH_REFLECT
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// FILE: J.java // FILE: J.java
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// FILE: A.java // FILE: A.java
public class A { public class A {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// FILE: A.java // FILE: A.java
public class A { public class A {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_REFLECT // WITH_REFLECT
// FULL_JDK // FULL_JDK
// FILE: J.java // FILE: J.java
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// FILE: JClass.java // FILE: JClass.java
public class JClass { public class JClass {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// FILE: JClass.java // FILE: JClass.java
public class JClass { public class JClass {
@@ -260,7 +260,8 @@ FILE fqName:<root> fileName:/propertyReferences.kt
PROPERTY name:test_J_CONST visibility:public modality:FINAL [val] PROPERTY name:test_J_CONST visibility:public modality:FINAL [val]
FIELD PROPERTY_BACKING_FIELD name:test_J_CONST type:kotlin.reflect.KProperty0<kotlin.Int> visibility:private [final,static] FIELD PROPERTY_BACKING_FIELD name:test_J_CONST type:kotlin.reflect.KProperty0<kotlin.Int> visibility:private [final,static]
EXPRESSION_BODY EXPRESSION_BODY
ERROR_CALL 'Unsupported callable reference: Q|J|::R|/J.CONST|' type=kotlin.reflect.KProperty0<kotlin.Int> PROPERTY_REFERENCE 'public final CONST: kotlin.Int [val]' field='FIELD IR_EXTERNAL_JAVA_DECLARATION_STUB name:CONST type:kotlin.Int visibility:public [final,static]' getter=null setter=null type=kotlin.reflect.KProperty0<kotlin.Int> origin=null
<1>: <none>
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test_J_CONST> visibility:public modality:FINAL <> () returnType:kotlin.reflect.KProperty0<kotlin.Int> FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test_J_CONST> visibility:public modality:FINAL <> () returnType:kotlin.reflect.KProperty0<kotlin.Int>
correspondingProperty: PROPERTY name:test_J_CONST visibility:public modality:FINAL [val] correspondingProperty: PROPERTY name:test_J_CONST visibility:public modality:FINAL [val]
BLOCK_BODY BLOCK_BODY
@@ -269,7 +270,8 @@ FILE fqName:<root> fileName:/propertyReferences.kt
PROPERTY name:test_J_nonConst visibility:public modality:FINAL [val] PROPERTY name:test_J_nonConst visibility:public modality:FINAL [val]
FIELD PROPERTY_BACKING_FIELD name:test_J_nonConst type:kotlin.reflect.KMutableProperty0<kotlin.Int> visibility:private [final,static] FIELD PROPERTY_BACKING_FIELD name:test_J_nonConst type:kotlin.reflect.KMutableProperty0<kotlin.Int> visibility:private [final,static]
EXPRESSION_BODY EXPRESSION_BODY
ERROR_CALL 'Unsupported callable reference: Q|J|::R|/J.nonConst|' type=kotlin.reflect.KMutableProperty0<kotlin.Int> PROPERTY_REFERENCE 'public open nonConst: kotlin.Int [var]' field='FIELD IR_EXTERNAL_JAVA_DECLARATION_STUB name:nonConst type:kotlin.Int visibility:public [static]' getter=null setter=null type=kotlin.reflect.KMutableProperty0<kotlin.Int> origin=null
<1>: <none>
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test_J_nonConst> visibility:public modality:FINAL <> () returnType:kotlin.reflect.KMutableProperty0<kotlin.Int> FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test_J_nonConst> visibility:public modality:FINAL <> () returnType:kotlin.reflect.KMutableProperty0<kotlin.Int>
correspondingProperty: PROPERTY name:test_J_nonConst visibility:public modality:FINAL [val] correspondingProperty: PROPERTY name:test_J_nonConst visibility:public modality:FINAL [val]
BLOCK_BODY BLOCK_BODY