[FIR2IR] Generate property extension receiver references properly

This commit is contained in:
Mikhail Glukhikh
2020-04-02 15:31:25 +03:00
parent 4234438d8d
commit f374c36cd2
44 changed files with 64 additions and 178 deletions
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.fir.symbols.AccessorSymbol
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrProperty
import org.jetbrains.kotlin.ir.expressions.IrConstKind
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.symbols.*
@@ -92,7 +93,8 @@ fun FirClassifierSymbol<*>.toSymbol(
fun FirReference.toSymbol(
session: FirSession,
classifierStorage: Fir2IrClassifierStorage,
declarationStorage: Fir2IrDeclarationStorage
declarationStorage: Fir2IrDeclarationStorage,
conversionScope: Fir2IrConversionScope
): IrSymbol? {
return when (this) {
is FirResolvedNamedReference -> {
@@ -114,6 +116,10 @@ fun FirReference.toSymbol(
when (val boundSymbol = boundSymbol) {
is FirClassSymbol<*> -> classifierStorage.getIrClassSymbol(boundSymbol).owner.thisReceiver?.symbol
is FirFunctionSymbol -> declarationStorage.getIrFunctionSymbol(boundSymbol).owner.extensionReceiverParameter?.symbol
is FirPropertySymbol -> {
val property = declarationStorage.getIrPropertyOrFieldSymbol(boundSymbol).owner as? IrProperty
property?.let { conversionScope.parentAccessorOfPropertyFromStack(it) }?.symbol
}
else -> null
}
}
@@ -23,6 +23,16 @@ class Fir2IrConversionScope {
fun parentFromStack(): IrDeclarationParent = parentStack.last()
fun parentAccessorOfPropertyFromStack(property: IrProperty): IrSimpleFunction? {
for (parent in parentStack.asReversed()) {
when (parent) {
property.getter -> return property.getter
property.setter -> return property.setter
}
}
return null
}
fun <T : IrDeclaration> applyParentFromStackTo(declaration: T): T {
declaration.parent = parentStack.last()
return declaration
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.fir.resolve.isIteratorNext
import org.jetbrains.kotlin.fir.resolve.transformers.IntegerLiteralTypeApproximationTransformer
import org.jetbrains.kotlin.fir.scopes.impl.FirIntegerOperator
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
@@ -32,10 +33,7 @@ import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.*
@@ -286,22 +284,32 @@ class Fir2IrVisitor(
override fun visitThisReceiverExpression(thisReceiverExpression: FirThisReceiverExpression, data: Any?): IrElement {
val calleeReference = thisReceiverExpression.calleeReference
val boundSymbol = calleeReference.boundSymbol
if (calleeReference.labelName == null && boundSymbol is FirClassSymbol) {
// Object case
val firClass = boundSymbol.fir as FirClass
val irClass = classifierStorage.getCachedIrClass(firClass)!!
if (firClass is FirAnonymousObject || firClass is FirRegularClass && firClass.classKind == ClassKind.OBJECT) {
if (irClass != conversionScope.lastClass()) {
return thisReceiverExpression.convertWithOffsets { startOffset, endOffset ->
IrGetObjectValueImpl(startOffset, endOffset, irClass.defaultType, irClass.symbol)
if (calleeReference.labelName == null) {
if (boundSymbol is FirClassSymbol) {
// Object case
val firClass = boundSymbol.fir as FirClass
val irClass = classifierStorage.getCachedIrClass(firClass)!!
if (firClass is FirAnonymousObject || firClass is FirRegularClass && firClass.classKind == ClassKind.OBJECT) {
if (irClass != conversionScope.lastClass()) {
return thisReceiverExpression.convertWithOffsets { startOffset, endOffset ->
IrGetObjectValueImpl(startOffset, endOffset, irClass.defaultType, irClass.symbol)
}
}
}
}
val dispatchReceiver = conversionScope.dispatchReceiverParameter(irClass)
if (dispatchReceiver != null) {
return thisReceiverExpression.convertWithOffsets { startOffset, endOffset ->
IrGetValueImpl(startOffset, endOffset, dispatchReceiver.type, dispatchReceiver.symbol)
val dispatchReceiver = conversionScope.dispatchReceiverParameter(irClass)
if (dispatchReceiver != null) {
return thisReceiverExpression.convertWithOffsets { startOffset, endOffset ->
IrGetValueImpl(startOffset, endOffset, dispatchReceiver.type, dispatchReceiver.symbol)
}
}
} else if (boundSymbol is FirCallableSymbol) {
val receiverSymbol = calleeReference.toSymbol(session, classifierStorage, declarationStorage, conversionScope)
val receiver = (receiverSymbol?.owner as? IrSimpleFunction)?.extensionReceiverParameter
if (receiver != null) {
return thisReceiverExpression.convertWithOffsets { startOffset, endOffset ->
IrGetValueImpl(startOffset, endOffset, receiver.type, receiver.symbol)
}
}
}
}
@@ -51,7 +51,7 @@ internal class CallAndReferenceGenerator(
private fun ConeKotlinType.toIrType(): IrType = with(typeConverter) { toIrType() }
fun convertToIrCallableReference(callableReferenceAccess: FirCallableReferenceAccess): IrExpression {
val symbol = callableReferenceAccess.calleeReference.toSymbol(session, classifierStorage, declarationStorage)
val symbol = callableReferenceAccess.calleeReference.toSymbol(session, classifierStorage, declarationStorage, conversionScope)
val type = callableReferenceAccess.typeRef.toIrType()
return callableReferenceAccess.convertWithOffsets { startOffset, endOffset ->
when (symbol) {
@@ -147,7 +147,8 @@ internal class CallAndReferenceGenerator(
val symbol = qualifiedAccess.calleeReference.toSymbol(
session,
classifierStorage,
declarationStorage
declarationStorage,
conversionScope
)
return typeRef.convertWithOffsets { startOffset, endOffset ->
if (qualifiedAccess.calleeReference is FirSuperReference) {
@@ -192,7 +193,7 @@ internal class CallAndReferenceGenerator(
fun convertToIrSetCall(variableAssignment: FirVariableAssignment): IrExpression {
val type = irBuiltIns.unitType
val calleeReference = variableAssignment.calleeReference
val symbol = calleeReference.toSymbol(session, classifierStorage, declarationStorage)
val symbol = calleeReference.toSymbol(session, classifierStorage, declarationStorage, conversionScope)
val origin = IrStatementOrigin.EQ
return variableAssignment.convertWithOffsets { startOffset, endOffset ->
val assignedValue = visitor.convertToIrExpression(variableAssignment.rValue)