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.
/*
* Copyright 2010-2018 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.ir.util
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
import org.jetbrains.kotlin.utils.DFS
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
/**
* Binds the arguments explicitly represented in the IR to the parameters of the accessed function.
* The arguments are to be evaluated in the same order as they appear in the resulting list.
*/
@ObsoleteDescriptorBasedAPI
fun IrMemberAccessExpression<*>.getArguments(): List> {
val res = mutableListOf>()
val descriptor = symbol.descriptor as CallableDescriptor
// TODO: ensure the order below corresponds to the one defined in Kotlin specs.
dispatchReceiver?.let {
res += (descriptor.dispatchReceiverParameter!! to it)
}
extensionReceiver?.let {
res += (descriptor.extensionReceiverParameter!! to it)
}
descriptor.valueParameters.forEach {
val arg = getValueArgument(it.index)
if (arg != null) {
res += (it to arg)
}
}
return res
}
/**
* Binds the arguments explicitly represented in the IR to the parameters of the accessed function.
* The arguments are to be evaluated in the same order as they appear in the resulting list.
*/
@ObsoleteDescriptorBasedAPI
@Suppress("unused") // Used in kotlin-native
fun IrFunctionAccessExpression.getArgumentsWithSymbols(): List> {
val res = mutableListOf>()
val irFunction = symbol.owner
dispatchReceiver?.let {
res += (irFunction.dispatchReceiverParameter!!.symbol to it)
}
extensionReceiver?.let {
res += (irFunction.extensionReceiverParameter!!.symbol to it)
}
irFunction.valueParameters.forEach {
val arg = getValueArgument(it.descriptor as ValueParameterDescriptor)
if (arg != null) {
res += (it.symbol to arg)
}
}
return res
}
/**
* Binds the arguments explicitly represented in the IR to the parameters of the accessed function.
* The arguments are to be evaluated in the same order as they appear in the resulting list.
*/
fun IrMemberAccessExpression<*>.getArgumentsWithIr(): List> {
val res = mutableListOf>()
val irFunction = when (this) {
is IrFunctionAccessExpression -> this.symbol.owner
is IrFunctionReference -> this.symbol.owner
is IrPropertyReference -> {
assert(this.field == null) { "Field should be null to use `getArgumentsWithIr` on IrPropertyReference: ${this.dump()}}" }
this.getter!!.owner
}
else -> error(this)
}
dispatchReceiver?.let {
res += (irFunction.dispatchReceiverParameter!! to it)
}
extensionReceiver?.let {
res += (irFunction.extensionReceiverParameter!! to it)
}
irFunction.valueParameters.forEachIndexed { index, it ->
val arg = getValueArgument(index)
if (arg != null) {
res += (it to arg)
}
}
return res
}
/**
* Sets arguments that are specified by given mapping of parameters.
*/
@ObsoleteDescriptorBasedAPI
fun IrMemberAccessExpression<*>.addArguments(args: Map) {
val descriptor = symbol.descriptor as CallableDescriptor
descriptor.dispatchReceiverParameter?.let {
val arg = args[it]
if (arg != null) {
this.dispatchReceiver = arg
}
}
descriptor.extensionReceiverParameter?.let {
val arg = args[it]
if (arg != null) {
this.extensionReceiver = arg
}
}
descriptor.valueParameters.forEach {
val arg = args[it]
if (arg != null) {
this.putValueArgument(it.index, arg)
}
}
}
@ObsoleteDescriptorBasedAPI
@Suppress("unused") // Used in kotlin-native
fun IrMemberAccessExpression<*>.addArguments(args: List>) =
this.addArguments(args.toMap())
fun IrExpression.isNullConst() = this is IrConst<*> && this.kind == IrConstKind.Null
fun IrExpression.isTrueConst() = this is IrConst<*> && this.kind == IrConstKind.Boolean && this.value == true
fun IrExpression.isFalseConst() = this is IrConst<*> && this.kind == IrConstKind.Boolean && this.value == false
fun IrExpression.isIntegerConst(value: Int) = this is IrConst<*> && this.kind == IrConstKind.Int && this.value == value
@OptIn(ObsoleteDescriptorBasedAPI::class)
fun IrExpression.coerceToUnit(builtins: IrBuiltIns): IrExpression {
return coerceToUnitIfNeeded(type.toKotlinType(), builtins)
}
@ObsoleteDescriptorBasedAPI
fun IrExpression.coerceToUnitIfNeeded(valueType: KotlinType, irBuiltIns: IrBuiltIns): IrExpression {
return if (KotlinTypeChecker.DEFAULT.isSubtypeOf(valueType, irBuiltIns.unitType.toKotlinType()))
this
else
IrTypeOperatorCallImpl(
startOffset, endOffset,
irBuiltIns.unitType,
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT,
irBuiltIns.unitType,
this
)
}
fun IrExpression.coerceToUnitIfNeeded(valueType: IrType, irBuiltIns: IrBuiltIns): IrExpression {
return if (valueType.isSubtypeOf(irBuiltIns.unitType, irBuiltIns))
this
else
IrTypeOperatorCallImpl(
startOffset, endOffset,
irBuiltIns.unitType,
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT,
irBuiltIns.unitType,
this
)
}
@ObsoleteDescriptorBasedAPI
fun IrMemberAccessExpression<*>.usesDefaultArguments(): Boolean =
(symbol.descriptor as CallableDescriptor).valueParameters.any { this.getValueArgument(it) == null }
val IrClass.functions: Sequence
get() = declarations.asSequence().filterIsInstance()
val IrClassSymbol.functions: Sequence
get() = owner.functions.map { it.symbol }
val IrClass.constructors: Sequence
get() = declarations.asSequence().filterIsInstance()
val IrClassSymbol.constructors: Sequence
get() = owner.constructors.map { it.symbol }
val IrClass.fields: Sequence
get() = declarations.asSequence().filterIsInstance()
val IrClassSymbol.fields: Sequence
get() = owner.fields.map { it.symbol }
val IrClass.primaryConstructor: IrConstructor?
get() = this.declarations.singleOrNull { it is IrConstructor && it.isPrimary } as IrConstructor?
val IrDeclarationContainer.properties: Sequence
get() = declarations.asSequence().filterIsInstance()
val IrFunction.explicitParameters: List
get() = (listOfNotNull(dispatchReceiverParameter, extensionReceiverParameter) + valueParameters)
val IrBody.statements: List
get() = when (this) {
is IrBlockBody -> statements
is IrExpressionBody -> listOf(expression)
is IrSyntheticBody -> error("Synthetic body contains no statements: $this")
else -> error("Unknown subclass of IrBody: $this")
}
val IrClass.defaultType: IrSimpleType
get() = this.thisReceiver!!.type as IrSimpleType
fun IrClass.isSubclassOf(ancestor: IrClass): Boolean {
val alreadyVisited = mutableSetOf()
fun IrClass.hasAncestorInSuperTypes(): Boolean = when {
this === ancestor -> true
this in alreadyVisited -> false
else -> {
alreadyVisited.add(this)
superTypes.mapNotNull { ((it as? IrSimpleType)?.classifier as? IrClassSymbol)?.owner }.any { it.hasAncestorInSuperTypes() }
}
}
return this.hasAncestorInSuperTypes()
}
fun IrSimpleFunction.findInterfaceImplementation(): IrSimpleFunction? {
if (isReal) return null
return resolveFakeOverride()?.run { if (parentAsClass.isInterface) this else null }
}
fun IrProperty.resolveFakeOverride(): IrProperty? = getter?.resolveFakeOverride()?.correspondingPropertySymbol?.owner
val IrClass.isAnnotationClass get() = kind == ClassKind.ANNOTATION_CLASS
val IrClass.isEnumClass get() = kind == ClassKind.ENUM_CLASS
val IrClass.isEnumEntry get() = kind == ClassKind.ENUM_ENTRY
val IrClass.isInterface get() = kind == ClassKind.INTERFACE
val IrClass.isClass get() = kind == ClassKind.CLASS
val IrClass.isObject get() = kind == ClassKind.OBJECT
val IrClass.isAnonymousObject get() = isClass && name == SpecialNames.NO_NAME_PROVIDED
val IrDeclarationWithName.fqNameWhenAvailable: FqName?
get() = when (val parent = parent) {
is IrDeclarationWithName -> parent.fqNameWhenAvailable?.child(name)
is IrPackageFragment -> parent.fqName.child(name)
else -> null
}
val IrDeclaration.parentAsClass: IrClass
get() = parent as? IrClass
?: error("Parent of this declaration is not a class: ${render()}")
tailrec fun IrElement.getPackageFragment(): IrPackageFragment? {
if (this is IrPackageFragment) return this
return when (val parent = (this as? IrDeclaration)?.parent) {
is IrPackageFragment -> parent
else -> parent?.getPackageFragment()
}
}
fun IrAnnotationContainer.getAnnotation(name: FqName): IrConstructorCall? =
annotations.find {
it.symbol.owner.parentAsClass.fqNameWhenAvailable == name
}
fun IrAnnotationContainer.hasAnnotation(name: FqName) =
annotations.any {
it.symbol.owner.parentAsClass.fqNameWhenAvailable == name
}
fun IrAnnotationContainer.hasAnnotation(symbol: IrClassSymbol) =
annotations.any {
it.symbol.owner.parentAsClass.symbol == symbol
}
val IrConstructor.constructedClassType get() = (parent as IrClass).thisReceiver?.type!!
fun IrFunction.isFakeOverriddenFromAny(): Boolean {
val simpleFunction = this as? IrSimpleFunction ?: return false
if (!simpleFunction.isFakeOverride) {
return (parent as? IrClass)?.thisReceiver?.type?.isAny() ?: false
}
return simpleFunction.overriddenSymbols.all { it.owner.isFakeOverriddenFromAny() }
}
fun IrCall.isSuperToAny() = superQualifierSymbol?.let { this.symbol.owner.isFakeOverriddenFromAny() } ?: false
fun IrDeclaration.hasInterfaceParent() =
parent.safeAs()?.isInterface == true
fun IrDeclaration.isEffectivelyExternal(): Boolean {
fun IrFunction.effectiveParentDeclaration(): IrDeclaration? =
when (this) {
is IrSimpleFunction -> correspondingPropertySymbol?.owner ?: parent as? IrDeclaration
else -> parent as? IrDeclaration
}
val parent = parent
return when (this) {
is IrFunction -> isExternal || (effectiveParentDeclaration()?.isEffectivelyExternal() ?: false)
is IrField -> isExternal || parent is IrDeclaration && parent.isEffectivelyExternal()
is IrProperty -> isExternal || parent is IrDeclaration && parent.isEffectivelyExternal()
is IrClass -> isExternal || parent is IrDeclaration && parent.isEffectivelyExternal()
else -> false
}
}
fun IrFunction.isExternalOrInheritedFromExternal(): Boolean {
fun isExternalOrInheritedFromExternalImpl(f: IrSimpleFunction): Boolean =
f.isEffectivelyExternal() || f.overriddenSymbols.any { isExternalOrInheritedFromExternalImpl(it.owner) }
return isEffectivelyExternal() || (this is IrSimpleFunction && isExternalOrInheritedFromExternalImpl(this))
}
inline fun IrDeclarationContainer.findDeclaration(predicate: (T) -> Boolean): T? =
declarations.find { it is T && predicate(it) } as? T
fun IrValueParameter.hasDefaultValue(): Boolean = DFS.ifAny(
listOf(this),
{ current -> (current.parent as? IrSimpleFunction)?.overriddenSymbols?.map { it.owner.valueParameters[current.index] } ?: listOf() },
{ current -> current.defaultValue != null }
)
fun ReferenceSymbolTable.referenceClassifier(classifier: ClassifierDescriptor): IrClassifierSymbol =
when (classifier) {
is TypeParameterDescriptor ->
referenceTypeParameter(classifier)
is ClassDescriptor ->
referenceClass(classifier)
else ->
throw IllegalArgumentException("Unexpected classifier descriptor: $classifier")
}
fun ReferenceSymbolTable.referenceFunction(callable: CallableDescriptor): IrFunctionSymbol =
when (callable) {
is ClassConstructorDescriptor ->
referenceConstructor(callable)
is FunctionDescriptor ->
referenceSimpleFunction(callable)
else ->
throw IllegalArgumentException("Unexpected callable descriptor: $callable")
}
/**
* Create new call based on given [call] and [newSymbol]
* [receiversAsArguments]: optionally convert call with dispatch receiver to static call
* [argumentsAsDispatchers]: optionally convert static call to call with dispatch receiver
*/
fun irConstructorCall(
call: IrFunctionAccessExpression,
newSymbol: IrConstructorSymbol,
receiversAsArguments: Boolean = false,
argumentsAsDispatchers: Boolean = false
): IrConstructorCall =
call.run {
IrConstructorCallImpl(
startOffset,
endOffset,
type,
newSymbol,
typeArgumentsCount,
0,
call.valueArgumentsCount,
origin
).apply {
copyTypeAndValueArgumentsFrom(
call,
receiversAsArguments,
argumentsAsDispatchers
)
}
}
fun irCall(
call: IrFunctionAccessExpression,
newFunction: IrSimpleFunction,
receiversAsArguments: Boolean = false,
argumentsAsReceivers: Boolean = false,
newSuperQualifierSymbol: IrClassSymbol? = null
): IrCall =
irCall(
call,
newFunction.symbol,
receiversAsArguments,
argumentsAsReceivers,
newSuperQualifierSymbol
)
fun irCall(
call: IrFunctionAccessExpression,
newSymbol: IrSimpleFunctionSymbol,
receiversAsArguments: Boolean = false,
argumentsAsReceivers: Boolean = false,
newSuperQualifierSymbol: IrClassSymbol? = null
): IrCall =
call.run {
IrCallImpl(
startOffset,
endOffset,
type,
newSymbol,
typeArgumentsCount,
valueArgumentsCount = newSymbol.owner.valueParameters.size,
origin = origin,
superQualifierSymbol = newSuperQualifierSymbol
).apply {
copyTypeAndValueArgumentsFrom(
call,
receiversAsArguments,
argumentsAsReceivers
)
}
}
fun IrMemberAccessExpression.copyTypeAndValueArgumentsFrom(
src: IrMemberAccessExpression,
receiversAsArguments: Boolean = false,
argumentsAsReceivers: Boolean = false
) {
copyTypeArgumentsFrom(src)
copyValueArgumentsFrom(src, symbol.owner, receiversAsArguments, argumentsAsReceivers)
}
fun IrMemberAccessExpression.copyValueArgumentsFrom(
src: IrMemberAccessExpression,
destFunction: IrFunction,
receiversAsArguments: Boolean = false,
argumentsAsReceivers: Boolean = false
) {
var destValueArgumentIndex = 0
var srcValueArgumentIndex = 0
val srcFunction = src.symbol.owner
when {
receiversAsArguments && srcFunction.dispatchReceiverParameter != null -> {
putValueArgument(destValueArgumentIndex++, src.dispatchReceiver)
}
argumentsAsReceivers && destFunction.dispatchReceiverParameter != null -> {
dispatchReceiver = src.getValueArgument(srcValueArgumentIndex++)
}
else -> {
dispatchReceiver = src.dispatchReceiver
}
}
when {
receiversAsArguments && srcFunction.extensionReceiverParameter != null -> {
putValueArgument(destValueArgumentIndex++, src.extensionReceiver)
}
argumentsAsReceivers && destFunction.extensionReceiverParameter != null -> {
extensionReceiver = src.getValueArgument(srcValueArgumentIndex++)
}
else -> {
extensionReceiver = src.extensionReceiver
}
}
while (srcValueArgumentIndex < src.valueArgumentsCount) {
putValueArgument(destValueArgumentIndex++, src.getValueArgument(srcValueArgumentIndex++))
}
}
val IrDeclaration.fileOrNull: IrFile?
get() = when (val parent = parent) {
is IrFile -> parent
is IrPackageFragment -> null
is IrDeclaration -> parent.fileOrNull
else -> TODO("Unexpected declaration parent")
}
val IrDeclaration.file: IrFile
get() = fileOrNull ?: TODO("Unknown file")
val IrDeclaration.parentClassOrNull: IrClass?
get() = parent.let {
when (it) {
is IrClass -> it
is IrDeclaration -> it.parentClassOrNull
else -> null
}
}
val IrFunction.allTypeParameters: List
get() = if (this is IrConstructor)
parentAsClass.typeParameters + typeParameters
else
typeParameters
fun IrMemberAccessExpression<*>.getTypeSubstitutionMap(irFunction: IrFunction): Map =
irFunction.allTypeParameters.withIndex().associate {
it.value.symbol to getTypeArgument(it.index)!!
}
val IrFunctionReference.typeSubstitutionMap: Map
get() = getTypeSubstitutionMap(symbol.owner)
val IrFunctionAccessExpression.typeSubstitutionMap: Map
get() = getTypeSubstitutionMap(symbol.owner)
val IrDeclaration.isFileClass: Boolean
get() = origin == IrDeclarationOrigin.FILE_CLASS || origin == IrDeclarationOrigin.SYNTHETIC_FILE_CLASS
val IrValueDeclaration.isImmutable: Boolean
get() = this is IrValueParameter || this is IrVariable && !isVar
fun IrExpression.isSafeToUseWithoutCopying() =
this is IrGetObjectValue ||
this is IrGetEnumValue ||
this is IrConst<*> ||
this is IrGetValue && symbol.isBound && symbol.owner.isImmutable
val IrStatementOrigin?.isLambda: Boolean
get() = this == IrStatementOrigin.LAMBDA || this == IrStatementOrigin.ANONYMOUS_FUNCTION
val IrFunction.originalFunction: IrFunction
get() = (this as? IrAttributeContainer)?.attributeOwnerId as? IrFunction ?: this
val IrProperty.originalProperty: IrProperty
get() = attributeOwnerId as? IrProperty ?: this