All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jetbrains.kotlin.ir.declarations.IrFunction.kt Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2010-2024 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.declarations

import org.jetbrains.kotlin.CompilerVersionOfApiDeprecation
import org.jetbrains.kotlin.DeprecatedCompilerApi
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.expressions.IrBody
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.ir.util.transformIfNeeded
import org.jetbrains.kotlin.ir.util.transformInPlace
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.utils.addIfNotNull

// This class is not autogenerated to for the sake refactoring IR parameters - see KT-68003.
// However, it must be kept in sync with [org.jetbrains.kotlin.ir.generator.IrTree.function].
sealed class IrFunction : IrDeclarationBase(), IrPossiblyExternalDeclaration, IrDeclarationWithVisibility, IrTypeParametersContainer,
    IrSymbolOwner, IrDeclarationParent, IrReturnTarget, IrMemberWithContainerSource, IrMetadataSourceOwner {
    @ObsoleteDescriptorBasedAPI
    abstract override val descriptor: FunctionDescriptor

    abstract override val symbol: IrFunctionSymbol

    abstract var isInline: Boolean

    abstract var isExpect: Boolean

    abstract var returnType: IrType


    private val _parameters: MutableList = ArrayList()

    /**
     * All value parameters.
     *
     * Parameters must follow this order:
     *
     * [[dispatch receiver, context parameters, extension receiver, regular parameters]].
     */
    @OptIn(DelicateIrParameterIndexSetter::class)
    var parameters: List
        get() = _parameters
        set(value) {
            val newParameters = value.toList()

            val parameters = _parameters
            for (parameter in parameters) {
                parameter.indexInOldValueParameters = -1
                parameter.indexInParameters = -1
            }

            var newContextParametersCount = 0
            var oldIndex = 0
            for ((index, parameter) in newParameters.withIndex()) {
                val kind = requireNotNull(parameter._kind) { "Kind must be set explicitly when adding a parameter" }

                parameter.indexInParameters = index
                parameter.indexInOldValueParameters = when (kind) {
                    IrParameterKind.DispatchReceiver, IrParameterKind.ExtensionReceiver -> -1
                    IrParameterKind.Context, IrParameterKind.Regular -> oldIndex++
                }

                if (kind == IrParameterKind.Context) {
                    newContextParametersCount++
                }
            }

            parameters.clear()
            parameters.addAll(newParameters)
            _contextReceiverParametersCount = newContextParametersCount
        }

    /**
     * The first parameter of kind [IrParameterKind.DispatchReceiver] in [parameters], if present.
     */
    var dispatchReceiverParameter: IrValueParameter?
        get() = _parameters.firstOrNull { it.kind == IrParameterKind.DispatchReceiver }
        /**
         * ##### This is a deprecated API
         * Modify the [parameters] list directly.
         *
         * Details on the API migration: KT-68003
         */
        @DeprecatedCompilerApi(CompilerVersionOfApiDeprecation._2_1_20)
        set(value) {
            setReceiverParameter(IrParameterKind.DispatchReceiver, value)
        }

    /**
     * The first parameter of kind [IrParameterKind.ExtensionReceiver] in [parameters], if present.
     *
     * ##### This is a deprecated API
     * Drop-in replacement:
     * ```kotlin
     * parameters.firstOrNull { it.kind == IrParameterKind.ExtensionReceiver }
     * ```
     *
     * Details on the API migration: KT-68003
     */
    @DeprecatedCompilerApi(CompilerVersionOfApiDeprecation._2_1_20)
    var extensionReceiverParameter: IrValueParameter?
        get() = _parameters.firstOrNull { it.kind == IrParameterKind.ExtensionReceiver }
        set(value) {
            setReceiverParameter(IrParameterKind.ExtensionReceiver, value)
        }

    @OptIn(DelicateIrParameterIndexSetter::class)
    private fun setReceiverParameter(kind: IrParameterKind, value: IrValueParameter?) {
        val parameters = _parameters

        var index = parameters.indexOfFirst { it.kind == kind }
        var reindexSubsequent = false
        if (index >= 0) {
            val old = parameters[index]
            old.indexInOldValueParameters = -1
            old.indexInParameters = -1
            old._kind = null

            if (value != null) {
                parameters[index] = value
            } else {
                parameters.removeAt(index)
                reindexSubsequent = true
            }
        } else {
            if (value != null) {
                index = parameters.indexOfLast { it.kind < kind } + 1
                parameters.add(index, value)
                reindexSubsequent = true
            } else {
                // nothing
            }
        }

        if (value != null) {
            value.indexInOldValueParameters = -1
            value.indexInParameters = index
            value.kind = kind
        }

        if (reindexSubsequent) {
            for (i in index..
        get() = _parameters.filter { it.kind == IrParameterKind.Regular || it.kind == IrParameterKind.Context }
        set(value) {
            replaceRegularAndExtensionParameters(value, _contextReceiverParametersCount)
        }

    @OptIn(DelicateIrParameterIndexSetter::class)
    private fun replaceRegularAndExtensionParameters(newValueParameters: List?, newContextParametersCount: Int) {
        val parameters = _parameters

        if (newValueParameters != null) {
            for (param in newValueParameters) {
                if (param._kind.let { it == IrParameterKind.DispatchReceiver || it == IrParameterKind.ExtensionReceiver }) {
                    if (param === parameters.getOrNull(param.indexInParameters)) {
                        throw IllegalArgumentException(
                            "Adding a value parameter ${param.render()} to function ${this.render()}, when it's already present as a receiver.\n" +
                                    "This operation is not supported by the old<->new parameter API bridge."
                        )
                    }
                }
            }
        }

        var dispatchReceiver: IrValueParameter? = null
        var extensionReceiver: IrValueParameter? = null
        val oldValueParameters = if (newValueParameters == null)
            ArrayList(parameters.size)
        else null

        for (param in parameters) {
            when (param.kind) {
                IrParameterKind.DispatchReceiver -> dispatchReceiver = param
                IrParameterKind.ExtensionReceiver -> extensionReceiver = param
                else -> {
                    oldValueParameters?.add(param)
                    param.indexInParameters = -1
                    param.indexInOldValueParameters = -1
                    param._kind = null
                }
            }
        }

        val valueParameters = newValueParameters ?: oldValueParameters!!
        val actualContextParameterCount = newContextParametersCount.coerceAtMost(valueParameters.size)

        parameters.clear()
        parameters.addIfNotNull(dispatchReceiver)
        for (i in 0.. -1
                IrParameterKind.DispatchReceiver, IrParameterKind.ExtensionReceiver -> -1
                IrParameterKind.Context, IrParameterKind.Regular -> indexInOldValueParameters++
            }
        }
    }


    abstract var body: IrBody?

    override fun  acceptChildren(visitor: IrElementVisitor, data: D) {
        typeParameters.forEach { it.accept(visitor, data) }
        _parameters.forEach { it.accept(visitor, data) }
        body?.accept(visitor, data)
    }

    override fun  transformChildren(transformer: IrElementTransformer, data: D) {
        typeParameters = typeParameters.transformIfNeeded(transformer, data)
        _parameters.transformInPlace(transformer, data)
        body = body?.transform(transformer, data)
    }
}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy