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 -> {
declarationStorage.getOrCreateProperty(
declarationStorage.getOrCreateIrProperty(
declaration, parent, isLocal = isLocal
)
}
@@ -636,7 +636,7 @@ class Fir2IrDeclarationStorage(
}
}
internal val FirProperty.fieldVisibility: Visibility
private val FirProperty.fieldVisibility: Visibility
get() = when {
isLateInit -> setter?.visibility ?: status.visibility
isConst -> status.visibility
@@ -660,7 +660,7 @@ class Fir2IrDeclarationStorage(
return symbolTable.declareProperty(signature, { Fir2IrPropertySymbol(signature, containerSource) }, factory)
}
fun getOrCreateProperty(
fun getOrCreateIrProperty(
property: FirProperty,
irParent: IrDeclarationParent?,
isLocal: Boolean = false,
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.backend.generators
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.backend.*
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.impl.FirNoReceiverExpression
import org.jetbrains.kotlin.fir.psi
@@ -53,6 +54,11 @@ class CallAndReferenceGenerator(
): IrExpression {
val symbol = callableReferenceAccess.calleeReference.toSymbol(session, classifierStorage, declarationStorage, conversionScope)
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 ->
when (symbol) {
is IrPropertySymbol -> {
@@ -62,17 +68,13 @@ class CallAndReferenceGenerator(
referencedPropertyGetter != null -> null
else -> referencedProperty.backingField?.symbol
}
val origin = when (callableReferenceAccess.source?.psi?.parent) {
is KtPropertyDelegate -> IrStatementOrigin.PROPERTY_REFERENCE_FOR_DELEGATE
else -> null
}
IrPropertyReferenceImpl(
startOffset, endOffset, type, symbol,
typeArgumentsCount = referencedPropertyGetter?.typeParameters?.size ?: 0,
backingFieldSymbol,
referencedPropertyGetter?.symbol,
referencedProperty.setter?.symbol,
origin
propertyOrigin()
)
}
is IrLocalDelegatedPropertySymbol -> {
@@ -84,6 +86,28 @@ class CallAndReferenceGenerator(
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 -> {
val constructor = symbol.owner
val klass = constructor.parent as? IrClass
@@ -123,6 +147,21 @@ class CallAndReferenceGenerator(
}.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? {
val calleeReference = calleeReference as? FirResolvedNamedReference ?: return null
val fir = calleeReference.resolvedSymbol.fir
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// FILE: JClass.java
public class JClass {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_RUNTIME
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_REFLECT
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_REFLECT
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// FILE: J.java
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_REFLECT
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// FILE: J.java
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// FILE: A.java
public class A {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// FILE: A.java
public class A {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_REFLECT
// FULL_JDK
// FILE: J.java
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// FILE: JClass.java
public class JClass {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// FILE: JClass.java
public class JClass {
@@ -260,7 +260,8 @@ FILE fqName:<root> fileName:/propertyReferences.kt
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]
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>
correspondingProperty: PROPERTY name:test_J_CONST visibility:public modality:FINAL [val]
BLOCK_BODY
@@ -269,7 +270,8 @@ FILE fqName:<root> fileName:/propertyReferences.kt
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]
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>
correspondingProperty: PROPERTY name:test_J_nonConst visibility:public modality:FINAL [val]
BLOCK_BODY