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

org.jetbrains.kotlin.codegen.state.inlineClassManglingUtils.kt Maven / Gradle / Ivy

There is a newer version: 2.0.0
Show newest version
/*
 * 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.codegen.state

import org.jetbrains.kotlin.codegen.coroutines.unwrapInitialDescriptorForSuspendFunction
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.InlineClassDescriptorResolver
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForParameterTypes
import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForReturnType
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound
import java.security.MessageDigest
import java.util.*

fun getManglingSuffixBasedOnKotlinSignature(
    descriptor: CallableMemberDescriptor,
    shouldMangleByReturnType: Boolean
): String? {
    if (descriptor !is FunctionDescriptor) return null
    if (descriptor is ConstructorDescriptor) return null
    if (InlineClassDescriptorResolver.isSynthesizedBoxOrUnboxMethod(descriptor)) return null

    // Don't mangle functions with '@JvmName' annotation.
    // Some stdlib functions ('Result.success', 'Result.failure') are annotated with '@JvmName' as a workaround for forward compatibility.
    if (DescriptorUtils.hasJvmNameAnnotation(descriptor)) return null

    // If a function accepts inline class parameters, mangle its name.
    if (requiresFunctionNameManglingForParameterTypes(descriptor)) {
        return "-" + md5base64(collectSignatureForMangling(descriptor))
    }

    // If a class member function returns inline class value, mangle its name.
    // NB here function can be a suspend function JVM view with return type replaced with 'Any',
    // should unwrap it and take original return type instead.
    if (shouldMangleByReturnType) {
        val unwrappedDescriptor = descriptor.unwrapInitialDescriptorForSuspendFunction()
        if (requiresFunctionNameManglingForReturnType(unwrappedDescriptor)) {
            return "-" + md5base64(":" + getSignatureElementForMangling(unwrappedDescriptor.returnType!!))
        }
    }
    return null
}

private fun collectSignatureForMangling(descriptor: CallableMemberDescriptor): String {
    val types = listOfNotNull(descriptor.extensionReceiverParameter?.type) + descriptor.valueParameters.map { it.type }
    return types.joinToString { getSignatureElementForMangling(it) }
}

private fun getSignatureElementForMangling(type: KotlinType): String = buildString {
    val descriptor = type.constructor.declarationDescriptor ?: return ""
    when (descriptor) {
        is ClassDescriptor -> {
            append('L')
            append(descriptor.fqNameUnsafe)
            if (type.isMarkedNullable) append('?')
            append(';')
        }

        is TypeParameterDescriptor -> {
            append(getSignatureElementForMangling(descriptor.representativeUpperBound))
        }
    }
}

fun md5base64(signatureForMangling: String): String {
    val d = MessageDigest.getInstance("MD5").digest(signatureForMangling.toByteArray()).copyOfRange(0, 5)
    // base64 URL encoder without padding uses exactly the characters allowed in both JVM bytecode and Dalvik bytecode names
    return Base64.getUrlEncoder().withoutPadding().encodeToString(d)
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy