Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.jetbrains.kotlin.fir.backend.ConversionUtils.kt Maven / Gradle / Ivy
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.backend
import com.intellij.psi.PsiCompiledElement
import org.jetbrains.kotlin.*
import org.jetbrains.kotlin.builtins.StandardNames.DATA_CLASS_COMPONENT_PREFIX
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.builder.buildPackageDirective
import org.jetbrains.kotlin.fir.caches.getValue
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.buildFile
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty
import org.jetbrains.kotlin.fir.declarations.utils.isInline
import org.jetbrains.kotlin.fir.declarations.utils.isJava
import org.jetbrains.kotlin.fir.declarations.utils.visibility
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
import org.jetbrains.kotlin.fir.extensions.FirExtensionApiInternals
import org.jetbrains.kotlin.fir.extensions.declarationGenerators
import org.jetbrains.kotlin.fir.extensions.extensionService
import org.jetbrains.kotlin.fir.extensions.generatedDeclarationsSymbolProvider
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirReference
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.references.FirThisReference
import org.jetbrains.kotlin.fir.references.impl.FirPropertyFromParameterResolvedNamedReference
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.calls.FirSimpleSyntheticPropertySymbol
import org.jetbrains.kotlin.fir.resolve.providers.FirProvider
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.declarations.UNDEFINED_PARAMETER_INDEX
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin.GeneratedByPlugin
import org.jetbrains.kotlin.ir.expressions.IrConst
import org.jetbrains.kotlin.ir.expressions.IrConstKind
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.IrErrorTypeImpl
import org.jetbrains.kotlin.ir.util.functions
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments
import org.jetbrains.kotlin.types.ConstantValueKind
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.util.OperatorNameConventions
internal fun FirElement.convertWithOffsets(
f: (startOffset: Int, endOffset: Int) -> T
): T {
return source.convertWithOffsets(f)
}
internal fun KtSourceElement?.convertWithOffsets(
f: (startOffset: Int, endOffset: Int) -> T
): T {
val psi = psi
if (psi is PsiCompiledElement) return f(UNDEFINED_OFFSET, UNDEFINED_OFFSET)
val startOffset = psi?.startOffsetSkippingComments ?: this?.startOffset ?: UNDEFINED_OFFSET
val endOffset = this?.endOffset ?: UNDEFINED_OFFSET
return f(startOffset, endOffset)
}
internal fun FirQualifiedAccess.convertWithOffsets(
f: (startOffset: Int, endOffset: Int) -> T
): T {
val psi = calleeReference.psi
if (psi is PsiCompiledElement) return f(UNDEFINED_OFFSET, UNDEFINED_OFFSET)
val startOffset = psi?.startOffsetSkippingComments ?: calleeReference.source ?.startOffset ?: UNDEFINED_OFFSET
val endOffset = source?.endOffset ?: UNDEFINED_OFFSET
return f(startOffset, endOffset)
}
internal fun createErrorType(): IrErrorType = IrErrorTypeImpl(null, emptyList(), Variance.INVARIANT)
internal enum class ConversionTypeOrigin {
DEFAULT,
SETTER
}
class ConversionTypeContext internal constructor(
internal val definitelyNotNull: Boolean,
internal val invariantProjection: Boolean = false,
internal val origin: ConversionTypeOrigin = ConversionTypeOrigin.DEFAULT,
) {
fun definitelyNotNull() = ConversionTypeContext(
definitelyNotNull = true,
invariantProjection = invariantProjection,
origin = origin
)
fun inSetter() = ConversionTypeContext(
definitelyNotNull = definitelyNotNull,
invariantProjection = invariantProjection,
origin = ConversionTypeOrigin.SETTER
)
fun withInvariantProjections() = ConversionTypeContext(
definitelyNotNull = definitelyNotNull,
invariantProjection = true,
origin = origin
)
companion object {
internal val DEFAULT = ConversionTypeContext(
definitelyNotNull = false, origin = ConversionTypeOrigin.DEFAULT, invariantProjection = false
)
internal val WITH_INVARIANT = DEFAULT.withInvariantProjections()
}
}
context(Fir2IrComponents)
fun FirClassifierSymbol<*>.toSymbol(
typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT,
handleAnnotations: ((List) -> Unit)? = null
): IrClassifierSymbol {
return when (this) {
is FirTypeParameterSymbol -> {
classifierStorage.getIrTypeParameterSymbol(this, typeContext)
}
is FirTypeAliasSymbol -> {
handleAnnotations?.invoke(fir.expandedTypeRef.annotations)
val coneClassLikeType = fir.expandedTypeRef.coneType as ConeClassLikeType
coneClassLikeType.lookupTag.toSymbol(session)
?.toSymbol(typeContext, handleAnnotations)
?: classifierStorage.getIrClassSymbolForNotFoundClass(coneClassLikeType.lookupTag)
}
is FirClassSymbol -> {
classifierStorage.getIrClassSymbol(this)
}
else -> error("Unknown symbol: $this")
}
}
context(Fir2IrComponents)
private fun FirBasedSymbol<*>.toSymbolForCall(
dispatchReceiver: FirExpression,
preferGetter: Boolean,
explicitReceiver: FirExpression? = null,
isDelegate: Boolean = false
): IrSymbol? = when (this) {
is FirCallableSymbol<*> -> unwrapCallRepresentative().toSymbolForCall(
dispatchReceiver,
preferGetter,
explicitReceiver,
isDelegate
)
is FirClassifierSymbol<*> -> toSymbol()
else -> error("Unknown symbol: $this")
}
context(Fir2IrComponents)
fun FirReference.toSymbolForCall(
dispatchReceiver: FirExpression,
conversionScope: Fir2IrConversionScope,
preferGetter: Boolean = true,
explicitReceiver: FirExpression? = null, // Actual only for callable references
isDelegate: Boolean = false
): IrSymbol? {
return when (this) {
is FirResolvedNamedReference ->
resolvedSymbol.toSymbolForCall(
dispatchReceiver,
preferGetter,
explicitReceiver,
isDelegate
)
is FirErrorNamedReference ->
candidateSymbol?.toSymbolForCall(
dispatchReceiver,
preferGetter,
explicitReceiver,
isDelegate
)
is FirThisReference -> {
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.getIrPropertySymbol(boundSymbol).owner as? IrProperty
property?.let { conversionScope.parentAccessorOfPropertyFromStack(it) }?.symbol
}
else -> null
}
}
else -> null
}
}
context(Fir2IrComponents)
private fun FirCallableSymbol<*>.toSymbolForCall(
dispatchReceiver: FirExpression,
preferGetter: Boolean,
explicitReceiver: FirExpression? = null,
isDelegate: Boolean = false
): IrSymbol? {
val dispatchReceiverLookupTag = when {
dispatchReceiver is FirExpressionWithSmartcastToNothing && dispatchReceiver.smartcastType.coneType is ConeDynamicType -> {
val coneType = dispatchReceiver.smartcastTypeWithoutNullableNothing.coneType
coneType.findClassRepresentation(coneType, declarationStorage.session)
}
dispatchReceiver is FirNoReceiverExpression -> {
val containingClass = containingClass()
if (containingClass != null && containingClass.classId != StandardClassIds.Any) {
// Make sure that symbol is not extension and is not from inline class
val coneType = ((explicitReceiver as? FirResolvedQualifier)?.symbol as? FirClassSymbol)?.defaultType()
coneType?.findClassRepresentation(coneType, declarationStorage.session)
} else {
null
}
}
else -> {
val coneType = dispatchReceiver.typeRef.coneType
dispatchReceiver.typeRef.coneType.findClassRepresentation(coneType, declarationStorage.session)
}
}
return when (this) {
is FirSimpleSyntheticPropertySymbol -> {
if (isDelegate) {
declarationStorage.getIrPropertySymbol(this)
} else {
(fir as? FirSyntheticProperty)?.let { syntheticProperty ->
val delegateSymbol = if (preferGetter) {
syntheticProperty.getter.delegate.symbol
} else {
syntheticProperty.setter?.delegate?.symbol
?: throw AssertionError("Written synthetic property must have a setter")
}
delegateSymbol.unwrapCallRepresentative()
.toSymbolForCall(dispatchReceiver, preferGetter, isDelegate = false)
} ?: declarationStorage.getIrPropertySymbol(this)
}
}
is FirFunctionSymbol<*> -> declarationStorage.getIrFunctionSymbol(this, dispatchReceiverLookupTag)
is FirPropertySymbol -> declarationStorage.getIrPropertySymbol(this, dispatchReceiverLookupTag)
is FirFieldSymbol -> declarationStorage.getIrFieldSymbol(this)
is FirBackingFieldSymbol -> declarationStorage.getIrBackingFieldSymbol(this)
is FirDelegateFieldSymbol -> declarationStorage.getIrDelegateFieldSymbol(this)
is FirVariableSymbol<*> -> declarationStorage.getIrValueSymbol(this)
else -> null
}
}
fun FirConstExpression<*>.getIrConstKind(): IrConstKind<*> = when (kind) {
ConstantValueKind.IntegerLiteral -> {
val type = typeRef.coneTypeUnsafe()
type.getApproximatedType().toConstKind()!!.toIrConstKind()
}
else -> kind.toIrConstKind()
}
fun FirConstExpression.toIrConst(irType: IrType): IrConst {
return convertWithOffsets { startOffset, endOffset ->
@Suppress("UNCHECKED_CAST")
val kind = getIrConstKind() as IrConstKind
@Suppress("UNCHECKED_CAST")
val value = (value as? Long)?.let {
when (kind) {
IrConstKind.Byte -> it.toByte()
IrConstKind.Short -> it.toShort()
IrConstKind.Int -> it.toInt()
IrConstKind.Float -> it.toFloat()
IrConstKind.Double -> it.toDouble()
else -> it
}
} as T ?: value
IrConstImpl(
startOffset, endOffset,
// Strip all annotations (including special annotations such as @EnhancedNullability) from constant type
irType.removeAnnotations(),
kind, value
)
}
}
private fun ConstantValueKind<*>.toIrConstKind(): IrConstKind<*> = when (this) {
ConstantValueKind.Null -> IrConstKind.Null
ConstantValueKind.Boolean -> IrConstKind.Boolean
ConstantValueKind.Char -> IrConstKind.Char
ConstantValueKind.Byte -> IrConstKind.Byte
ConstantValueKind.Short -> IrConstKind.Short
ConstantValueKind.Int -> IrConstKind.Int
ConstantValueKind.Long -> IrConstKind.Long
ConstantValueKind.UnsignedByte -> IrConstKind.Byte
ConstantValueKind.UnsignedShort -> IrConstKind.Short
ConstantValueKind.UnsignedInt -> IrConstKind.Int
ConstantValueKind.UnsignedLong -> IrConstKind.Long
ConstantValueKind.String -> IrConstKind.String
ConstantValueKind.Float -> IrConstKind.Float
ConstantValueKind.Double -> IrConstKind.Double
ConstantValueKind.IntegerLiteral, ConstantValueKind.UnsignedIntegerLiteral -> throw IllegalArgumentException()
ConstantValueKind.Error -> throw IllegalArgumentException()
}
internal tailrec fun FirCallableSymbol<*>.unwrapSubstitutionAndIntersectionOverrides(): FirCallableSymbol<*> {
val originalForSubstitutionOverride = originalForSubstitutionOverride
if (originalForSubstitutionOverride != null && originalForSubstitutionOverride != this) {
return originalForSubstitutionOverride.unwrapSubstitutionAndIntersectionOverrides()
}
val baseForIntersectionOverride = baseForIntersectionOverride
if (baseForIntersectionOverride != null) return baseForIntersectionOverride.unwrapSubstitutionAndIntersectionOverrides()
return this
}
context(Fir2IrComponents)
internal tailrec fun FirCallableSymbol<*>.unwrapCallRepresentative(root: FirCallableSymbol<*> = this): FirCallableSymbol<*> {
val fir = fir
if (fir is FirConstructor) {
val originalForTypeAlias = fir.originalConstructorIfTypeAlias
if (originalForTypeAlias != null) return originalForTypeAlias.symbol.unwrapCallRepresentative(this)
}
if (fir.isIntersectionOverride) {
// We've got IR declarations (fake overrides) for intersection overrides in classes, but not for intersection types
// interface A { fun foo() }
// interface B { fun foo() }
// interface C : A, B // for C.foo we've got an IR fake override
// for {A & B} we don't have such an IR declaration, so we're unwrapping it
if (fir.dispatchReceiverType is ConeIntersectionType) {
return fir.baseForIntersectionOverride!!.symbol.unwrapCallRepresentative(this)
}
return this
}
val overriddenSymbol = fir.originalForSubstitutionOverride?.takeIf {
it.containingClass() == root.containingClass()
}?.symbol ?: return this
return overriddenSymbol.unwrapCallRepresentative(this)
}
context(Fir2IrComponents)
internal fun FirSimpleFunction.processOverriddenFunctionSymbols(
containingClass: FirClass,
processor: (FirNamedFunctionSymbol) -> Unit
) {
val scope = containingClass.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = true)
scope.processFunctionsByName(name) {}
scope.processOverriddenFunctionsFromSuperClasses(symbol, containingClass) {
if (it.fir.visibility == Visibilities.Private) {
return@processOverriddenFunctionsFromSuperClasses ProcessorAction.NEXT
}
processor(it)
ProcessorAction.NEXT
}
}
context(Fir2IrComponents)
internal fun FirSimpleFunction.generateOverriddenFunctionSymbols(containingClass: FirClass): List {
val superClasses = containingClass.getSuperTypesAsIrClasses() ?: return emptyList()
val overriddenSet = mutableSetOf()
processOverriddenFunctionSymbols(containingClass) {
for (overridden in fakeOverrideGenerator.getOverriddenSymbolsInSupertypes(it, superClasses)) {
overriddenSet += overridden
}
}
return overriddenSet.toList()
}
fun FirTypeScope.processOverriddenFunctionsFromSuperClasses(
functionSymbol: FirNamedFunctionSymbol,
containingClass: FirClass,
processor: (FirNamedFunctionSymbol) -> ProcessorAction
): ProcessorAction =
processDirectOverriddenFunctionsWithBaseScope(functionSymbol) { overridden, _ ->
val unwrapped = if (overridden.fir.isSubstitutionOverride &&
overridden.dispatchReceiverClassOrNull() == containingClass.symbol.toLookupTag()
)
overridden.originalForSubstitutionOverride!!
else
overridden
processor(unwrapped)
}
fun FirTypeScope.processOverriddenPropertiesFromSuperClasses(
propertySymbol: FirPropertySymbol,
containingClass: FirClass,
processor: (FirPropertySymbol) -> ProcessorAction
): ProcessorAction =
processDirectOverriddenPropertiesWithBaseScope(propertySymbol) { overridden, _ ->
val unwrapped = if (overridden.fir.isSubstitutionOverride &&
overridden.dispatchReceiverClassOrNull() == containingClass.symbol.toLookupTag()
)
overridden.originalForSubstitutionOverride!!
else
overridden
processor(unwrapped)
}
context(Fir2IrComponents)
private fun FirClass.getSuperTypesAsIrClasses(): Set? {
val irClass =
declarationStorage.classifierStorage.getIrClassSymbol(symbol).owner as? IrClass ?: return null
return irClass.superTypes.mapNotNull { it.classifierOrNull?.owner as? IrClass }.toSet()
}
context(Fir2IrComponents)
internal fun FirProperty.processOverriddenPropertySymbols(
containingClass: FirClass,
processor: (FirPropertySymbol) -> Unit
): List {
val scope = containingClass.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = true)
scope.processPropertiesByName(name) {}
val overriddenSet = mutableSetOf()
scope.processOverriddenPropertiesFromSuperClasses(symbol, containingClass) {
if (it.fir.visibility == Visibilities.Private) {
return@processOverriddenPropertiesFromSuperClasses ProcessorAction.NEXT
}
processor(it)
ProcessorAction.NEXT
}
return overriddenSet.toList()
}
context(Fir2IrComponents)
internal fun FirProperty.generateOverriddenPropertySymbols(containingClass: FirClass): List {
val superClasses = containingClass.getSuperTypesAsIrClasses() ?: return emptyList()
val overriddenSet = mutableSetOf()
processOverriddenPropertySymbols(containingClass) {
for (overridden in fakeOverrideGenerator.getOverriddenSymbolsInSupertypes(it, superClasses)) {
overriddenSet += overridden
}
}
return overriddenSet.toList()
}
context(Fir2IrComponents)
internal fun FirProperty.generateOverriddenAccessorSymbols(containingClass: FirClass, isGetter: Boolean): List {
val scope = containingClass.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = true)
scope.processPropertiesByName(name) {}
val overriddenSet = mutableSetOf()
val superClasses = containingClass.getSuperTypesAsIrClasses() ?: return emptyList()
scope.processOverriddenPropertiesFromSuperClasses(symbol, containingClass) {
if (it.fir.visibility == Visibilities.Private) {
return@processOverriddenPropertiesFromSuperClasses ProcessorAction.NEXT
}
for (overriddenProperty in fakeOverrideGenerator.getOverriddenSymbolsInSupertypes(it, superClasses)) {
val overriddenAccessor = if (isGetter) overriddenProperty.owner.getter?.symbol else overriddenProperty.owner.setter?.symbol
if (overriddenAccessor != null) {
overriddenSet += overriddenAccessor
}
}
ProcessorAction.NEXT
}
return overriddenSet.toList()
}
private val nameToOperationConventionOrigin = mutableMapOf(
OperatorNameConventions.PLUS to IrStatementOrigin.PLUS,
OperatorNameConventions.MINUS to IrStatementOrigin.MINUS,
OperatorNameConventions.TIMES to IrStatementOrigin.MUL,
OperatorNameConventions.DIV to IrStatementOrigin.DIV,
OperatorNameConventions.MOD to IrStatementOrigin.PERC,
OperatorNameConventions.REM to IrStatementOrigin.PERC,
OperatorNameConventions.RANGE_TO to IrStatementOrigin.RANGE,
OperatorNameConventions.RANGE_UNTIL to IrStatementOrigin.RANGE_UNTIL,
OperatorNameConventions.CONTAINS to IrStatementOrigin.IN,
)
internal fun FirReference.statementOrigin(): IrStatementOrigin? {
return when (this) {
is FirPropertyFromParameterResolvedNamedReference -> IrStatementOrigin.INITIALIZE_PROPERTY_FROM_PARAMETER
is FirResolvedNamedReference -> when (val symbol = resolvedSymbol) {
is FirSyntheticPropertySymbol -> IrStatementOrigin.GET_PROPERTY
is FirNamedFunctionSymbol -> when {
symbol.callableId.isInvoke() ->
IrStatementOrigin.INVOKE
source?.elementType == KtNodeTypes.FOR && symbol.callableId.isIteratorNext() ->
IrStatementOrigin.FOR_LOOP_NEXT
source?.elementType == KtNodeTypes.FOR && symbol.callableId.isIteratorHasNext() ->
IrStatementOrigin.FOR_LOOP_HAS_NEXT
source?.elementType == KtNodeTypes.FOR && symbol.callableId.isIterator() ->
IrStatementOrigin.FOR_LOOP_ITERATOR
source?.elementType == KtNodeTypes.OPERATION_REFERENCE ->
nameToOperationConventionOrigin[symbol.callableId.callableName]
source?.kind is KtFakeSourceElementKind.DesugaredComponentFunctionCall ->
IrStatementOrigin.COMPONENT_N.withIndex(name.asString().removePrefix(DATA_CLASS_COMPONENT_PREFIX).toInt())
else ->
null
}
else -> null
}
else -> null
}
}
context(Fir2IrComponents)
internal fun IrDeclarationParent.declareThisReceiverParameter(
thisType: IrType,
thisOrigin: IrDeclarationOrigin,
startOffset: Int = this.startOffset,
endOffset: Int = this.endOffset,
name: Name = SpecialNames.THIS
): IrValueParameter {
return symbolTable.irFactory.createValueParameter(
startOffset, endOffset, thisOrigin, IrValueParameterSymbolImpl(),
name, UNDEFINED_PARAMETER_INDEX, thisType,
varargElementType = null, isCrossinline = false, isNoinline = false,
isHidden = false, isAssignable = false
).apply {
this.parent = this@declareThisReceiverParameter
}
}
fun FirClass.irOrigin(firProvider: FirProvider): IrDeclarationOrigin = when {
firProvider.getFirClassifierContainerFileIfAny(symbol) != null -> IrDeclarationOrigin.DEFINED
isJava -> IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB
else -> when (val origin = origin) {
is FirDeclarationOrigin.Plugin -> GeneratedByPlugin(origin.key)
else -> IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB
}
}
val IrType.isSamType: Boolean
get() {
val irClass = classOrNull ?: return false
if (irClass.owner.kind != ClassKind.INTERFACE) return false
val am = irClass.functions.singleOrNull { it.owner.modality == Modality.ABSTRACT }
return am != null
}
fun Fir2IrComponents.createSafeCallConstruction(
receiverVariable: IrVariable,
receiverVariableSymbol: IrValueSymbol,
expressionOnNotNull: IrExpression,
): IrExpression {
val startOffset = expressionOnNotNull.startOffset
val endOffset = expressionOnNotNull.endOffset
val resultType = expressionOnNotNull.type.makeNullable()
return IrBlockImpl(startOffset, endOffset, resultType, IrStatementOrigin.SAFE_CALL).apply {
statements += receiverVariable
statements += IrWhenImpl(startOffset, endOffset, resultType).apply {
val condition = IrCallImpl(
startOffset, endOffset, irBuiltIns.booleanType,
irBuiltIns.eqeqSymbol,
valueArgumentsCount = 2,
typeArgumentsCount = 0,
origin = IrStatementOrigin.EQEQ
).apply {
putValueArgument(0, IrGetValueImpl(startOffset, endOffset, receiverVariableSymbol))
putValueArgument(1, IrConstImpl.constNull(startOffset, endOffset, irBuiltIns.nothingNType))
}
branches += IrBranchImpl(
condition, IrConstImpl.constNull(startOffset, endOffset, irBuiltIns.nothingNType)
)
branches += IrElseBranchImpl(
IrConstImpl.boolean(startOffset, endOffset, irBuiltIns.booleanType, true),
expressionOnNotNull
)
}
}
}
fun Fir2IrComponents.createTemporaryVariable(
receiverExpression: IrExpression,
conversionScope: Fir2IrConversionScope,
nameHint: String? = null
): Pair {
val receiverVariable = declarationStorage.declareTemporaryVariable(receiverExpression, nameHint).apply {
parent = conversionScope.parentFromStack()
}
val variableSymbol = receiverVariable.symbol
return Pair(receiverVariable, variableSymbol)
}
fun Fir2IrComponents.createTemporaryVariableForSafeCallConstruction(
receiverExpression: IrExpression,
conversionScope: Fir2IrConversionScope
): Pair =
createTemporaryVariable(receiverExpression, conversionScope, "safe_receiver")
fun Fir2IrComponents.computeValueClassRepresentation(klass: FirRegularClass): ValueClassRepresentation? {
require((klass.valueClassRepresentation != null) == klass.isInline)
return klass.valueClassRepresentation?.mapUnderlyingType {
with(typeConverter) {
it.toIrType() as? IrSimpleType?: error("Value class underlying type is not a simple type: ${klass.render()}")
}
}
}
context(Fir2IrComponents)
fun FirRegularClass.getIrSymbolsForSealedSubclasses(): List {
val symbolProvider = session.symbolProvider
return getSealedClassInheritors(session).mapNotNull {
symbolProvider.getClassLikeSymbolByClassId(it)?.toSymbol()
}.filterIsInstance()
}
@OptIn(FirExtensionApiInternals::class)
fun FirSession.createFilesWithGeneratedDeclarations(): List {
val symbolProvider = generatedDeclarationsSymbolProvider ?: return emptyList()
val declarationGenerators = extensionService.declarationGenerators
val topLevelClasses = declarationGenerators.flatMap { it.topLevelClassIdsCache.getValue() }.groupBy { it.packageFqName }
val topLevelCallables = declarationGenerators.flatMap { it.topLevelCallableIdsCache.getValue() }.groupBy { it.packageName }
return buildList {
for (packageFqName in (topLevelClasses.keys + topLevelCallables.keys)) {
this += buildFile {
origin = FirDeclarationOrigin.Synthetic
moduleData = [email protected]
packageDirective = buildPackageDirective {
this.packageFqName = packageFqName
}
name = "__GENERATED DECLARATIONS__.kt"
declarations += topLevelCallables.getOrDefault(packageFqName, emptyList())
.flatMap { symbolProvider.getTopLevelCallableSymbols(packageFqName, it.callableName) }
.map { it.fir }
declarations += topLevelClasses.getOrDefault(packageFqName, emptyList())
.mapNotNull { symbolProvider.getClassLikeSymbolByClassId(it)?.fir }
}
}
}
}
fun FirDeclaration?.computeIrOrigin(predefinedOrigin: IrDeclarationOrigin? = null): IrDeclarationOrigin {
return predefinedOrigin
?: (this?.origin as? FirDeclarationOrigin.Plugin)?.let { GeneratedByPlugin(it.key) }
?: (this as? FirValueParameter)?.name?.let {
when (it) {
SpecialNames.UNDERSCORE_FOR_UNUSED_VAR -> IrDeclarationOrigin.UNDERSCORE_PARAMETER
SpecialNames.DESTRUCT -> IrDeclarationOrigin.DESTRUCTURED_OBJECT_PARAMETER
else -> null
}
}
?: IrDeclarationOrigin.DEFINED
}
fun FirVariableAssignment.getIrAssignmentOrigin(): IrStatementOrigin {
val calleeReferenceSymbol = calleeReference.toResolvedCallableSymbol() ?: return IrStatementOrigin.EQ
val rValue = rValue
if (rValue is FirFunctionCall && calleeReferenceSymbol.callableId.isLocal) {
val callableId = rValue.calleeReference.toResolvedCallableSymbol()?.callableId
if (callableId?.classId == StandardClassIds.Int) {
val callableName = callableId.callableName
if (callableName == OperatorNameConventions.INC) {
return if (source?.elementType == KtNodeTypes.PREFIX_EXPRESSION)
IrStatementOrigin.PREFIX_INCR
else
IrStatementOrigin.POSTFIX_INCR
} else if (callableName == OperatorNameConventions.DEC) {
return if (source?.elementType == KtNodeTypes.PREFIX_EXPRESSION)
IrStatementOrigin.PREFIX_DECR
else
IrStatementOrigin.POSTFIX_DECR
}
if (calleeReference.source?.kind is KtFakeSourceElementKind &&
calleeReferenceSymbol == rValue.explicitReceiver?.toResolvedCallableSymbol()
) {
if (callableName == OperatorNameConventions.PLUS) {
return IrStatementOrigin.PLUSEQ
} else if (callableName == OperatorNameConventions.MINUS) {
return IrStatementOrigin.MINUSEQ
}
}
}
}
return IrStatementOrigin.EQ
}
fun FirCallableDeclaration.contextReceiversForFunctionOrContainingProperty(): List =
if (this is FirPropertyAccessor)
this.propertySymbol?.fir?.contextReceivers.orEmpty()
else
this.contextReceivers