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

org.jetbrains.kotlin.backend.jvm.codegen.irCodegenUtils.kt Maven / Gradle / Ivy

/*
 * 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.backend.jvm.codegen

import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.backend.common.ir.ir2string
import org.jetbrains.kotlin.backend.common.lower.allOverridden
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.FQ_NAMES
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.AsmUtil.LABELED_THIS_PARAMETER
import org.jetbrains.kotlin.codegen.AsmUtil.RECEIVER_PARAMETER_NAME
import org.jetbrains.kotlin.codegen.inline.DefaultSourceMapper
import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrGetEnumValue
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.load.java.JavaVisibilities
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
import org.jetbrains.kotlin.resolve.inline.INLINE_ONLY_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmClassSignature
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.jetbrains.org.objectweb.asm.MethodVisitor
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type

class IrFrameMap : FrameMapBase() {
    private val typeMap = mutableMapOf()

    override fun enter(descriptor: IrSymbol, type: Type): Int {
        typeMap[descriptor] = type
        return super.enter(descriptor, type)
    }

    override fun leave(descriptor: IrSymbol): Int {
        typeMap.remove(descriptor)
        return super.leave(descriptor)
    }

    fun typeOf(descriptor: IrSymbol): Type = typeMap.getValue(descriptor)
}

internal val IrFunction.isStatic
    get() = (this.dispatchReceiverParameter == null && this !is IrConstructor)

fun IrFrameMap.enter(irDeclaration: IrSymbolOwner, type: Type): Int {
    return enter(irDeclaration.symbol, type)
}

fun IrFrameMap.leave(irDeclaration: IrSymbolOwner): Int {
    return leave(irDeclaration.symbol)
}

val IrClass.isJvmInterface get() = isAnnotationClass || isInterface

internal val IrDeclaration.fileParent: IrFile
    get() {
        val myParent = parent
        return when (myParent) {
            is IrFile -> myParent
            else -> (myParent as IrDeclaration).fileParent
        }
    }

internal val DeclarationDescriptorWithSource.psiElement: PsiElement?
    get() = (source as? PsiSourceElement)?.psi

fun JvmBackendContext.getSourceMapper(declaration: IrClass): DefaultSourceMapper {
    val sourceManager = this.psiSourceManager
    val fileEntry = sourceManager.getFileEntry(declaration.fileParent)
    check(fileEntry != null) { "No PSI file entry found for class: ${declaration.dump()}" }
    // NOTE: apparently inliner requires the source range to cover the
    //       whole file the class is declared in rather than the class only.
    // TODO: revise
    val endLineNumber = fileEntry.getSourceRangeInfo(0, fileEntry.maxOffset).endLineNumber
    return DefaultSourceMapper(
        SourceInfo.createInfoForIr(
            endLineNumber + 1,
            typeMapper.mapClass(declaration).internalName,
            declaration.fileParent.name
        )
    )
}

val IrType.isExtensionFunctionType: Boolean
    get() = isFunctionTypeOrSubtype() && hasAnnotation(KotlinBuiltIns.FQ_NAMES.extensionFunctionType)


/* Borrowed from MemberCodegen.java */

fun writeInnerClass(innerClass: IrClass, typeMapper: IrTypeMapper, context: JvmBackendContext, v: ClassBuilder) {
    val outerClassInternalName = innerClass.parent.safeAs()?.let { typeMapper.classInternalName(it) }
    val innerName = innerClass.name.takeUnless { it.isSpecial }?.asString()
    val innerClassInternalName = typeMapper.classInternalName(innerClass)
    v.visitInnerClass(innerClassInternalName, outerClassInternalName, innerName, innerClass.calculateInnerClassAccessFlags(context))
}

/* Borrowed with modifications from AsmUtil.java */

private val NO_FLAG_LOCAL = 0

private val visibilityToAccessFlag = mapOf(
    Visibilities.PRIVATE to Opcodes.ACC_PRIVATE,
    Visibilities.PRIVATE_TO_THIS to Opcodes.ACC_PRIVATE,
    Visibilities.PROTECTED to Opcodes.ACC_PROTECTED,
    JavaVisibilities.PROTECTED_STATIC_VISIBILITY to Opcodes.ACC_PROTECTED,
    JavaVisibilities.PROTECTED_AND_PACKAGE to Opcodes.ACC_PROTECTED,
    Visibilities.PUBLIC to Opcodes.ACC_PUBLIC,
    Visibilities.INTERNAL to Opcodes.ACC_PUBLIC,
    Visibilities.LOCAL to NO_FLAG_LOCAL,
    JavaVisibilities.PACKAGE_VISIBILITY to AsmUtil.NO_FLAG_PACKAGE_PRIVATE
)

private fun IrDeclaration.getVisibilityAccessFlagForAnonymous(): Int =
    if (isInlineOrContainedInInline(parent as? IrDeclaration)) Opcodes.ACC_PUBLIC else AsmUtil.NO_FLAG_PACKAGE_PRIVATE

fun IrClass.calculateInnerClassAccessFlags(context: JvmBackendContext): Int {
    val isLambda = superTypes.any { it.safeAs()?.classifier === context.ir.symbols.lambdaClass }
    val visibility = when {
        isLambda -> getVisibilityAccessFlagForAnonymous()
        visibility === Visibilities.LOCAL -> Opcodes.ACC_PUBLIC
        else -> getVisibilityAccessFlag()
    }
    return visibility or
            if (origin.isSynthetic) Opcodes.ACC_SYNTHETIC else 0 or
                    innerAccessFlagsForModalityAndKind() or
                    if (isInner) 0 else Opcodes.ACC_STATIC
}

private fun IrClass.innerAccessFlagsForModalityAndKind(): Int {
    when (kind) {
        ClassKind.INTERFACE -> return Opcodes.ACC_ABSTRACT or Opcodes.ACC_INTERFACE
        ClassKind.ENUM_CLASS -> return Opcodes.ACC_FINAL or Opcodes.ACC_ENUM
        ClassKind.ANNOTATION_CLASS -> return Opcodes.ACC_ABSTRACT or Opcodes.ACC_ANNOTATION or Opcodes.ACC_INTERFACE
        else -> {
            if (modality === Modality.FINAL) {
                return Opcodes.ACC_FINAL
            } else if (modality === Modality.ABSTRACT || modality === Modality.SEALED) {
                return Opcodes.ACC_ABSTRACT
            }
        }
    }
    return 0
}

fun IrDeclarationWithVisibility.getVisibilityAccessFlag(kind: OwnerKind? = null): Int =
    specialCaseVisibility(kind)
        ?: visibilityToAccessFlag[visibility]
        ?: throw IllegalStateException("$visibility is not a valid visibility in backend for ${ir2string(this)}")


private fun IrDeclarationWithVisibility.specialCaseVisibility(kind: OwnerKind?): Int? {
//    if (JvmCodegenUtil.isNonIntrinsicPrivateCompanionObjectInInterface(memberDescriptor)) {
//        return ACC_PUBLIC
//    }
    if (this is IrClass && Visibilities.isPrivate(visibility) &&
        parent.safeAs()?.isInterface ?: false
    ) { // TODO: non-intrinsic
        return Opcodes.ACC_PUBLIC
    }

//    if (memberDescriptor is FunctionDescriptor && isInlineClassWrapperConstructor(memberDescriptor, kind))
    if (this is IrConstructor && parentAsClass.isInline && kind === OwnerKind.IMPLEMENTATION) {
        return Opcodes.ACC_PRIVATE
    }

//    if (kind !== OwnerKind.ERASED_INLINE_CLASS &&
//        memberDescriptor is ConstructorDescriptor &&
//        memberDescriptor !is AccessorForConstructorDescriptor &&
//        shouldHideConstructorDueToInlineClassTypeValueParameters(memberDescriptor)
//    ) {
    if (kind !== OwnerKind.ERASED_INLINE_CLASS &&
        this is IrConstructor &&
        shouldHideDueToInlineClassTypeValueParameters()
    ) {
        return Opcodes.ACC_PRIVATE
    }

//    if (memberDescriptor.isEffectivelyInlineOnly()) {
    if (isEffectivelyInlineOnly()) {
        return Opcodes.ACC_PRIVATE
    }

//    if (memberVisibility === Visibilities.LOCAL && memberDescriptor is CallableMemberDescriptor) {
    if (visibility === Visibilities.LOCAL && this is IrFunction) {
        return Opcodes.ACC_PUBLIC
    }

//    if (isEnumEntry(memberDescriptor)) {
    if (this is IrClass && this.kind === ClassKind.ENUM_ENTRY) {
        return AsmUtil.NO_FLAG_PACKAGE_PRIVATE
    }

//    These ones should be public anyway after ToArrayLowering.
//    if (memberDescriptor.isToArrayFromCollection()) {
//        return ACC_PUBLIC
//    }

//    if (memberDescriptor is ConstructorDescriptor && isAnonymousObject(memberDescriptor.containingDeclaration)) {
//        return getVisibilityAccessFlagForAnonymous(memberDescriptor.containingDeclaration as ClassDescriptor)
//    }
//    if (this is IrConstructor && parentAsClass.isAnonymousObject) {
//        return parentAsClass.getVisibilityAccessFlagForAnonymous()
//    }

//    TODO: when is this applicable?
//    if (memberDescriptor is SyntheticJavaPropertyDescriptor) {
//        return getVisibilityAccessFlag((memberDescriptor as SyntheticJavaPropertyDescriptor).getMethod)
//    }


//    if (memberDescriptor is PropertyAccessorDescriptor) {
//        val property = memberDescriptor.correspondingProperty
//        if (property is SyntheticJavaPropertyDescriptor) {
//            val method = (if (memberDescriptor === property.getGetter())
//                (property as SyntheticJavaPropertyDescriptor).getMethod
//            else
//                (property as SyntheticJavaPropertyDescriptor).setMethod)
//                ?: error("No get/set method in SyntheticJavaPropertyDescriptor: $property")
//            return getVisibilityAccessFlag(method)
//        }
//    }
    if (this is IrField && correspondingPropertySymbol?.owner?.isExternal == true) {
        val method = correspondingPropertySymbol?.owner?.getter ?: correspondingPropertySymbol?.owner?.setter
        ?: error("No get/set method in SyntheticJavaPropertyDescriptor: ${ir2string(correspondingPropertySymbol?.owner)}")
        return method.getVisibilityAccessFlag()
    }

//    if (memberDescriptor is CallableDescriptor && memberVisibility === Visibilities.PROTECTED) {
//        for (overridden in DescriptorUtils.getAllOverriddenDescriptors(memberDescriptor as CallableDescriptor)) {
//            if (isJvmInterface(overridden.containingDeclaration)) {
//                return ACC_PUBLIC
//            }
//        }
//    }
    if (this is IrSimpleFunction && visibility === Visibilities.PROTECTED &&
        allOverridden().any { it.parentAsClass.isJvmInterface }
    ) {
        return Opcodes.ACC_PUBLIC
    }

    if (!Visibilities.isPrivate(visibility)) {
        return null
    }

    if (this is IrSimpleFunction && isSuspend) {
        return AsmUtil.NO_FLAG_PACKAGE_PRIVATE
    }

//  Should be taken care of in IR
//    if (memberDescriptor is AccessorForCompanionObjectInstanceFieldDescriptor) {
//        return NO_FLAG_PACKAGE_PRIVATE
//    }

//    return if (memberDescriptor is ConstructorDescriptor && isEnumEntry(containingDeclaration)) {
//        NO_FLAG_PACKAGE_PRIVATE
//    } else null
    if (this is IrConstructor && parentAsClass.kind === ClassKind.ENUM_ENTRY) {
        return AsmUtil.NO_FLAG_PACKAGE_PRIVATE
    }

    return null
}

/* From inlineClassManglingRules.kt */
fun IrConstructor.shouldHideDueToInlineClassTypeValueParameters() =
    !Visibilities.isPrivate(visibility) &&
            !parentAsClass.isInline &&
            parentAsClass.modality !== Modality.SEALED &&
            valueParameters.any { it.type.requiresFunctionNameMangling() }

fun IrType.requiresFunctionNameMangling(): Boolean =
    isInlineClassThatRequiresMangling() || isTypeParameterWithUpperBoundThatRequiresMangling()

fun IrType.isInlineClassThatRequiresMangling() =
    safeAs()?.classifier?.owner?.safeAs()?.let {
        it.isInline && !it.isDontMangleClass()
    } ?: false

fun IrClass.isDontMangleClass() =
    fqNameWhenAvailable != DescriptorUtils.RESULT_FQ_NAME

fun IrType.isTypeParameterWithUpperBoundThatRequiresMangling() =
    safeAs()?.classifier?.owner.safeAs()?.let { param ->
        param.superTypes.any { it.requiresFunctionNameMangling() }
    } ?: false


/* Borrowed from InlineUtil. */
private tailrec fun isInlineOrContainedInInline(declaration: IrDeclaration?): Boolean = when {
    declaration === null -> false
    declaration is IrFunction && declaration.isInline -> true
    else -> isInlineOrContainedInInline(declaration.parent as? IrDeclaration)
}

/* Borrowed from inlineOnly.kt */

fun IrDeclarationWithVisibility.isInlineOnlyOrReifiable(): Boolean =
    this is IrFunction && (isReifiable() || isInlineOnly())

fun IrDeclarationWithVisibility.isEffectivelyInlineOnly(): Boolean =
    isInlineOnlyOrReifiable() ||
            (this is IrSimpleFunction && isSuspend && isInline &&
                    (valueParameters.any { it.isCrossinline } || visibility === Visibilities.PRIVATE))

private fun IrFunction.isInlineOnly() =
    isInline && hasAnnotation(INLINE_ONLY_ANNOTATION_FQ_NAME)

private fun IrFunction.isReifiable() = typeParameters.any { it.isReified }


// Borrowed with modifications from ImplementationBodyCodegen.java

private val KOTLIN_MARKER_INTERFACES: Map = run {
    val kotlinMarkerInterfaces = mutableMapOf()
    for (platformMutabilityMapping in JavaToKotlinClassMap.mutabilityMappings) {
        kotlinMarkerInterfaces[platformMutabilityMapping.kotlinReadOnly.asSingleFqName()] = "kotlin/jvm/internal/markers/KMappedMarker"

        val mutableClassId = platformMutabilityMapping.kotlinMutable
        kotlinMarkerInterfaces[mutableClassId.asSingleFqName()] =
            "kotlin/jvm/internal/markers/K" + mutableClassId.relativeClassName.asString()
                .replace("MutableEntry", "Entry") // kotlin.jvm.internal.markers.KMutableMap.Entry for some reason
                .replace(".", "$")
    }
    kotlinMarkerInterfaces
}

internal class IrSuperClassInfo(val type: Type, val irType: IrType?)

internal fun getSignature(
    irClass: IrClass,
    classAsmType: Type,
    superClassInfo: IrSuperClassInfo,
    typeMapper: IrTypeMapper
): JvmClassSignature {
    val sw = BothSignatureWriter(BothSignatureWriter.Mode.CLASS)

    typeMapper.writeFormalTypeParameters(irClass.typeParameters, sw)

    sw.writeSuperclass()
    val irType = superClassInfo.irType
    if (irType == null) {
        sw.writeClassBegin(superClassInfo.type)
        sw.writeClassEnd()
    } else {
        typeMapper.mapSupertype(irType, sw)
    }
    sw.writeSuperclassEnd()

    val superInterfaces = LinkedHashSet()
    val kotlinMarkerInterfaces = LinkedHashSet()

    for (superType in irClass.superTypes) {
        val superClass = superType.safeAs()?.classifier?.safeAs()?.owner ?: continue
        if (superClass.isJvmInterface) {
            val kotlinInterfaceName = superClass.fqNameWhenAvailable!!

            sw.writeInterface()
            val jvmInterfaceType = typeMapper.mapSupertype(superType, sw)
            sw.writeInterfaceEnd()

            superInterfaces.add(jvmInterfaceType.internalName)
            kotlinMarkerInterfaces.addIfNotNull(KOTLIN_MARKER_INTERFACES[kotlinInterfaceName])
        }
    }

    for (kotlinMarkerInterface in kotlinMarkerInterfaces) {
        sw.writeInterface()
        sw.writeAsmType(Type.getObjectType(kotlinMarkerInterface))
        sw.writeInterfaceEnd()
    }

    superInterfaces.addAll(kotlinMarkerInterfaces)

    return JvmClassSignature(
        classAsmType.internalName, superClassInfo.type.internalName,
        ArrayList(superInterfaces), sw.makeJavaGenericSignature()
    )
}

/* Copied with modifications from AsmUtil.getVisibilityAccessFlagForClass */
/*
   Use this method to get visibility flag for class to define it in byte code (v.defineClass method).
   For other cases use getVisibilityAccessFlag(MemberDescriptor descriptor)
   Classes in byte code should be public or package private
*/
fun IrClass.getVisibilityAccessFlagForClass(): Int {
    /* Original had a check for SyntheticClassDescriptorForJava, never invoked in th IR backend. */
    if (isOptionalAnnotationClass()) {
        return AsmUtil.NO_FLAG_PACKAGE_PRIVATE
    }
    if (kind == ClassKind.ENUM_ENTRY) {
        return AsmUtil.NO_FLAG_PACKAGE_PRIVATE
    }
    return if (visibility === Visibilities.PUBLIC ||
        visibility === Visibilities.PROTECTED ||
        // TODO: should be package private, but for now Kotlin's reflection can't access members of such classes
        visibility === Visibilities.LOCAL ||
        visibility === Visibilities.INTERNAL
    ) {
        Opcodes.ACC_PUBLIC
    } else AsmUtil.NO_FLAG_PACKAGE_PRIVATE
}

/* Borrowed and translated from ExpectedActualDeclarationChecker */
// TODO: Descriptor-based code also checks for `descriptor.isExpect`; we don't represent expect/actual distinction in IR thus far.
fun IrClass.isOptionalAnnotationClass(): Boolean =
    isAnnotationClass &&
            hasAnnotation(ExpectedActualDeclarationChecker.OPTIONAL_EXPECTATION_FQ_NAME)

//@JvmOverloads
//fun OtherOriginForIr(element: PsiElement?, descriptor: DeclarationDescriptor? = null) =
//    if (element == null && descriptor == null)
//        JvmDeclarationOrigin.NO_ORIGIN
//    else
//        object : JvmDeclarationOrigin(JvmDeclarationOriginKind.OTHER, element, descriptor) {
//            override val element get() =
//                error("Access to PsiElement")
//            override val descriptor get() =
//                error("Access to descriptor")
//        }

//        JvmDeclarationOrigin(OTHER, element, descriptor)

/* From generateJava8ParameterNames.kt */

fun generateParameterNames(
    irFunction: IrFunction,
    mv: MethodVisitor,
    jvmSignature: JvmMethodSignature,
    state: GenerationState
) {
    val iterator = irFunction.valueParameters.iterator()
    val kotlinParameterTypes = jvmSignature.valueParameters
    var isEnumName = true

    kotlinParameterTypes.forEachIndexed { index, parameterSignature ->
        val kind = parameterSignature.kind

        val name = when (kind) {
            JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL -> {
                isEnumName = !isEnumName
                if (!isEnumName) "\$enum\$name" else "\$enum\$ordinal"
            }
            JvmMethodParameterKind.RECEIVER -> {
                getNameForReceiverParameter(irFunction, state.languageVersionSettings)
            }
            JvmMethodParameterKind.OUTER -> AsmUtil.CAPTURED_THIS_FIELD
            JvmMethodParameterKind.VALUE -> iterator.next().name.asString()

            JvmMethodParameterKind.CONSTRUCTOR_MARKER,
            JvmMethodParameterKind.SUPER_CALL_PARAM,
            JvmMethodParameterKind.CAPTURED_LOCAL_VARIABLE,
            JvmMethodParameterKind.THIS -> {
                //we can't generate null name cause of jdk problem #9045294
                "arg" + index
            }
        }

        //A construct emitted by a Java compiler must be marked as synthetic if it does not correspond to a construct declared explicitly or
        // implicitly in source code, unless the emitted construct is a class initialization method (JVMS §2.9).
        //A construct emitted by a Java compiler must be marked as mandated if it corresponds to a formal parameter
        // declared implicitly in source code (§8.8.1, §8.8.9, §8.9.3, §15.9.5.1).
        val access = when (kind) {
            JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL -> Opcodes.ACC_SYNTHETIC
            JvmMethodParameterKind.RECEIVER -> Opcodes.ACC_MANDATED
            JvmMethodParameterKind.OUTER -> Opcodes.ACC_MANDATED
            JvmMethodParameterKind.VALUE -> 0

            JvmMethodParameterKind.CONSTRUCTOR_MARKER,
            JvmMethodParameterKind.SUPER_CALL_PARAM,
            JvmMethodParameterKind.CAPTURED_LOCAL_VARIABLE,
            JvmMethodParameterKind.THIS -> Opcodes.ACC_SYNTHETIC
        }

        mv.visitParameter(name, access)
    }
}

/* From AsmUtil.java */

fun getNameForReceiverParameter(
    irFunction: IrFunction,
    languageVersionSettings: LanguageVersionSettings
): String {
    return getLabeledThisNameForReceiver(
        irFunction, languageVersionSettings, LABELED_THIS_PARAMETER, RECEIVER_PARAMETER_NAME
    )
}

private fun getLabeledThisNameForReceiver(
    irFunction: IrFunction,
    languageVersionSettings: LanguageVersionSettings,
    prefix: String,
    defaultName: String
): String {
    if (!languageVersionSettings.supportsFeature(LanguageFeature.NewCapturedReceiverFieldNamingConvention)) {
        return defaultName
    }

    // Current codegen never touches CALL_LABEL_FOR_LAMBDA_ARGUMENT
//    if (irFunction is IrSimpleFunction) {
//        val labelName = bindingContext.get(CodegenBinding.CALL_LABEL_FOR_LAMBDA_ARGUMENT, irFunction.descriptor)
//        if (labelName != null) {
//            return getLabeledThisName(labelName, prefix, defaultName)
//        }
//    }

//    val callableName = irFunction.descriptor.safeAs()?.correspondingVariable?.name ?: irFunction.descriptor.name
    val callableName = irFunction.safeAs()?.correspondingPropertySymbol?.owner?.name ?: irFunction.name

    return if (callableName.isSpecial) {
        defaultName
    } else getLabeledThisName(callableName.asString(), prefix, defaultName)

}

fun getLabeledThisName(callableName: String, prefix: String, defaultName: String): String {
    return if (!Name.isValidIdentifier(callableName)) {
        defaultName
    } else prefix + mangleNameIfNeeded(callableName)
}

val IrAnnotationContainer.deprecationFlags: Int
    get() {
        val annotation = annotations.findAnnotation(FQ_NAMES.deprecated) ?: return 0
        val isHidden = (annotation.getValueArgument(2) as? IrGetEnumValue)?.symbol?.owner
            ?.name?.asString() == DeprecationLevel.HIDDEN.name
        return Opcodes.ACC_DEPRECATED or if (isHidden) Opcodes.ACC_SYNTHETIC else 0
    }

// We can't check for JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_ANNOTATIONS because for interface methods
// moved to DefaultImpls, origin is changed to DEFAULT_IMPLS
// TODO: Fix origin somehow
val IrFunction.isSyntheticMethodForProperty: Boolean
    get() = name.asString().endsWith(JvmAbi.ANNOTATED_PROPERTY_METHOD_NAME_SUFFIX)

val IrFunction.deprecationFlags: Int
    get() {
        val originFlags = if (isSyntheticMethodForProperty) Opcodes.ACC_DEPRECATED else 0
        val propertyFlags = (this as? IrSimpleFunction)?.correspondingPropertySymbol?.owner?.deprecationFlags ?: 0
        return originFlags or propertyFlags or (this as IrAnnotationContainer).deprecationFlags
    }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy