[FIR2IR] Provide object receivers for callable references

This commit is contained in:
Mikhail Glukhikh
2020-03-30 12:41:54 +03:00
parent 51de319cc4
commit 282509b0da
9 changed files with 24 additions and 89 deletions
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrProperty
@@ -78,12 +79,7 @@ internal class CallAndReferenceGenerator(
)
}
}
}.apply {
applyTypeArguments(callableReferenceAccess)
if (callableReferenceAccess.explicitReceiver !is FirResolvedQualifier) {
applyReceivers(callableReferenceAccess)
}
}
}.applyTypeArguments(callableReferenceAccess).applyReceivers(callableReferenceAccess)
}
fun convertToIrCall(qualifiedAccess: FirQualifiedAccess, typeRef: FirTypeRef): IrExpression {
@@ -237,9 +233,18 @@ internal class CallAndReferenceGenerator(
}
fun convertToGetObject(qualifier: FirResolvedQualifier): IrExpression {
val irType = qualifier.typeRef.toIrType()
return convertToGetObject(qualifier, callableReferenceMode = false)!!
}
private fun convertToGetObject(qualifier: FirResolvedQualifier, callableReferenceMode: Boolean): IrExpression? {
val typeRef = qualifier.typeRef as? FirResolvedTypeRef
val classSymbol = (typeRef?.type as? ConeClassLikeType)?.lookupTag?.toSymbol(session)
if (callableReferenceMode && classSymbol is FirRegularClassSymbol) {
if (classSymbol.classId != qualifier.classId) {
return null
}
}
val irType = qualifier.typeRef.toIrType()
return qualifier.convertWithOffsets { startOffset, endOffset ->
if (classSymbol != null) {
IrGetObjectValueImpl(
@@ -331,9 +336,16 @@ internal class CallAndReferenceGenerator(
private fun FirQualifiedAccess.findIrReceiver(isDispatch: Boolean): IrExpression? {
val firReceiver = if (isDispatch) dispatchReceiver else extensionReceiver
if (firReceiver is FirResolvedQualifier) return convertToGetObject(firReceiver)
if (firReceiver is FirResolvedQualifier) {
return convertToGetObject(firReceiver, callableReferenceMode = this is FirCallableReferenceAccess)
}
return firReceiver.takeIf { it !is FirNoReceiverExpression }?.let { visitor.convertToIrExpression(it) }
?: explicitReceiver?.let { visitor.convertToIrExpression(it) } // NB: this applies to the situation when call is unresolved
?: explicitReceiver?.let {
if (it is FirResolvedQualifier) {
return convertToGetObject(it, callableReferenceMode = this is FirCallableReferenceAccess)
}
visitor.convertToIrExpression(it)
}
?: run {
// Object case
val callableReference = calleeReference as? FirResolvedNamedReference