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

proguard.classfile.util.kotlin.KotlinAnnotationUtil.kt Maven / Gradle / Ivy

Go to download

ProGuardCORE is a free library to read, analyze, modify, and write Java class files.

There is a newer version: 9.1.6
Show newest version
/*
 * ProGuardCORE -- library to process Java bytecode.
 *
 * Copyright (c) 2002-2024 Guardsquare NV
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package proguard.classfile.util.kotlin

import proguard.classfile.Clazz
import proguard.classfile.kotlin.visitor.KotlinAnnotationArgumentVisitor
import proguard.classfile.kotlin.visitor.KotlinAnnotationVisitor
import java.util.function.BiConsumer
import java.util.function.Consumer
import kotlin.metadata.KmAnnotation
import kotlin.metadata.KmAnnotationArgument
import kotlin.metadata.KmAnnotationArgument.AnnotationValue
import kotlin.metadata.KmAnnotationArgument.ArrayKClassValue
import kotlin.metadata.KmAnnotationArgument.ArrayValue
import kotlin.metadata.KmAnnotationArgument.BooleanValue
import kotlin.metadata.KmAnnotationArgument.ByteValue
import kotlin.metadata.KmAnnotationArgument.CharValue
import kotlin.metadata.KmAnnotationArgument.DoubleValue
import kotlin.metadata.KmAnnotationArgument.EnumValue
import kotlin.metadata.KmAnnotationArgument.FloatValue
import kotlin.metadata.KmAnnotationArgument.IntValue
import kotlin.metadata.KmAnnotationArgument.KClassValue
import kotlin.metadata.KmAnnotationArgument.LongValue
import kotlin.metadata.KmAnnotationArgument.ShortValue
import kotlin.metadata.KmAnnotationArgument.StringValue
import kotlin.metadata.KmAnnotationArgument.UByteValue
import kotlin.metadata.KmAnnotationArgument.UIntValue
import kotlin.metadata.KmAnnotationArgument.ULongValue
import kotlin.metadata.KmAnnotationArgument.UShortValue
import proguard.classfile.kotlin.KotlinAnnotatable as ProGuardKotlinAnnotatable
import proguard.classfile.kotlin.KotlinAnnotation as ProGuardKotlinAnnotation
import proguard.classfile.kotlin.KotlinAnnotationArgument as ProGuardAnnotationArgument
import proguard.classfile.kotlin.KotlinAnnotationArgument.AnnotationValue as ProGuardAnnotationValue
import proguard.classfile.kotlin.KotlinAnnotationArgument.ArrayValue as ProGuardArrayValue
import proguard.classfile.kotlin.KotlinAnnotationArgument.BooleanValue as ProGuardBooleanValue
import proguard.classfile.kotlin.KotlinAnnotationArgument.ByteValue as ProGuardByteValue
import proguard.classfile.kotlin.KotlinAnnotationArgument.CharValue as ProGuardCharValue
import proguard.classfile.kotlin.KotlinAnnotationArgument.ClassValue as ProGuardClassValue
import proguard.classfile.kotlin.KotlinAnnotationArgument.DoubleValue as ProGuardDoubleValue
import proguard.classfile.kotlin.KotlinAnnotationArgument.EnumValue as ProGuardEnumValue
import proguard.classfile.kotlin.KotlinAnnotationArgument.FloatValue as ProGuardFloatValue
import proguard.classfile.kotlin.KotlinAnnotationArgument.IntValue as ProGuardIntValue
import proguard.classfile.kotlin.KotlinAnnotationArgument.LongValue as ProGuardLongValue
import proguard.classfile.kotlin.KotlinAnnotationArgument.ShortValue as ProGuardShortValue
import proguard.classfile.kotlin.KotlinAnnotationArgument.StringValue as ProGuardStringValue
import proguard.classfile.kotlin.KotlinAnnotationArgument.UByteValue as ProGuardUByteValue
import proguard.classfile.kotlin.KotlinAnnotationArgument.UIntValue as ProGuardUIntValue
import proguard.classfile.kotlin.KotlinAnnotationArgument.ULongValue as ProGuardULongValue
import proguard.classfile.kotlin.KotlinAnnotationArgument.UShortValue as ProGuardUShortValue
import proguard.classfile.kotlin.KotlinAnnotationArgument.Value as ProGuardKotlinAnnotationArgumentValue

// Helper methods to convert between kotlinx metadata annotations and ProGuardCORE model Kotlin annotations

@ExperimentalUnsignedTypes
fun convertAnnotation(kmAnnotation: KmAnnotation): ProGuardKotlinAnnotation = kmAnnotation.toProGuardKotlinAnnotation()

@ExperimentalUnsignedTypes
private fun KmAnnotation.toProGuardKotlinAnnotation(): ProGuardKotlinAnnotation =
    ProGuardKotlinAnnotation(
        className,
        arguments.map { (key, value) ->
            ProGuardAnnotationArgument(key, value.toProGuardKotlinAnnotationArgumentValue())
        },
    )

@ExperimentalUnsignedTypes
private fun KmAnnotationArgument.toProGuardKotlinAnnotationArgumentValue(): ProGuardKotlinAnnotationArgumentValue =
    when (this) {
        is ByteValue -> ProGuardByteValue(value)
        is CharValue -> ProGuardCharValue(value)
        is ShortValue -> ProGuardShortValue(value)
        is IntValue -> ProGuardIntValue(value)
        is LongValue -> ProGuardLongValue(value)
        is FloatValue -> ProGuardFloatValue(value)
        is DoubleValue -> ProGuardDoubleValue(value)
        is BooleanValue -> ProGuardBooleanValue(value)
        is UByteValue -> ProGuardUByteValue(value.toByte())
        is UShortValue -> ProGuardUShortValue(value.toShort())
        is UIntValue -> ProGuardUIntValue(value.toInt())
        is ULongValue -> ProGuardULongValue(value.toLong())
        is StringValue -> ProGuardStringValue(value)
        is KClassValue -> ProGuardClassValue(className)
        is ArrayKClassValue -> ProGuardClassValue(className, arrayDimensionCount)
        is EnumValue -> ProGuardEnumValue(enumClassName, enumEntryName)
        is AnnotationValue -> ProGuardAnnotationValue(annotation.toProGuardKotlinAnnotation())
        is ArrayValue -> ProGuardArrayValue(elements.map { it.toProGuardKotlinAnnotationArgumentValue() })
    }

@ExperimentalUnsignedTypes
class AnnotationConstructor(private val consumer: Consumer) : KotlinAnnotationVisitor {
    override fun visitAnyAnnotation(
        clazz: Clazz,
        annotatable: ProGuardKotlinAnnotatable,
        annotation: ProGuardKotlinAnnotation,
    ) =
        with(mutableMapOf()) {
            // collect the arguments in a Map
            annotation.argumentsAccept(
                clazz,
                annotatable,
                AnnotationArgumentConstructor { key, value -> this[key] = value },
            )
            // Create the KmAnnotation with the arguments
            consumer.accept(KmAnnotation(annotation.className, this))
        }
}

@ExperimentalUnsignedTypes
private class AnnotationArgumentConstructor(private val consumer: BiConsumer) :
    KotlinAnnotationArgumentVisitor {

    override fun visitAnyArgument(
        clazz: Clazz,
        annotatable: ProGuardKotlinAnnotatable,
        annotation: ProGuardKotlinAnnotation,
        argument: ProGuardAnnotationArgument,
        value: ProGuardKotlinAnnotationArgumentValue,
    ) {
    }

    override fun visitUByteArgument(
        clazz: Clazz,
        annotatable: ProGuardKotlinAnnotatable,
        annotation: ProGuardKotlinAnnotation,
        argument: ProGuardAnnotationArgument,
        value: ProGuardUByteValue,
    ) = consumer.accept(argument.name, UByteValue(value.value.toUByte()))

    override fun visitUIntArgument(
        clazz: Clazz,
        annotatable: ProGuardKotlinAnnotatable,
        annotation: ProGuardKotlinAnnotation,
        argument: ProGuardAnnotationArgument,
        value: ProGuardUIntValue,
    ) = consumer.accept(argument.name, UIntValue(value.value.toUInt()))

    override fun visitULongArgument(
        clazz: Clazz,
        annotatable: ProGuardKotlinAnnotatable,
        annotation: ProGuardKotlinAnnotation,
        argument: ProGuardAnnotationArgument,
        value: ProGuardULongValue,
    ) = consumer.accept(argument.name, ULongValue(value.value.toULong()))

    override fun visitUShortArgument(
        clazz: Clazz,
        annotatable: ProGuardKotlinAnnotatable,
        annotation: ProGuardKotlinAnnotation,
        argument: ProGuardAnnotationArgument,
        value: ProGuardUShortValue,
    ) = consumer.accept(argument.name, UShortValue(value.value.toUShort()))

    override fun visitByteArgument(
        clazz: Clazz,
        annotatable: ProGuardKotlinAnnotatable,
        annotation: ProGuardKotlinAnnotation,
        argument: ProGuardAnnotationArgument,
        value: ProGuardByteValue,
    ) = consumer.accept(argument.name, ByteValue(value.value))

    override fun visitCharArgument(
        clazz: Clazz,
        annotatable: ProGuardKotlinAnnotatable,
        annotation: ProGuardKotlinAnnotation,
        argument: ProGuardAnnotationArgument,
        value: ProGuardCharValue,
    ) = consumer.accept(argument.name, CharValue(value.value))

    override fun visitShortArgument(
        clazz: Clazz,
        annotatable: ProGuardKotlinAnnotatable,
        annotation: ProGuardKotlinAnnotation,
        argument: ProGuardAnnotationArgument,
        value: ProGuardShortValue,
    ) = consumer.accept(argument.name, ShortValue(value.value))

    override fun visitIntArgument(
        clazz: Clazz,
        annotatable: ProGuardKotlinAnnotatable,
        annotation: ProGuardKotlinAnnotation,
        argument: ProGuardAnnotationArgument,
        value: ProGuardIntValue,
    ) = consumer.accept(argument.name, IntValue(value.value))

    override fun visitLongArgument(
        clazz: Clazz,
        annotatable: ProGuardKotlinAnnotatable,
        annotation: ProGuardKotlinAnnotation,
        argument: ProGuardAnnotationArgument,
        value: ProGuardLongValue,
    ) = consumer.accept(argument.name, LongValue(value.value))

    override fun visitFloatArgument(
        clazz: Clazz,
        annotatable: ProGuardKotlinAnnotatable,
        annotation: ProGuardKotlinAnnotation,
        argument: ProGuardAnnotationArgument,
        value: ProGuardFloatValue,
    ) = consumer.accept(argument.name, FloatValue(value.value))

    override fun visitDoubleArgument(
        clazz: Clazz,
        annotatable: ProGuardKotlinAnnotatable,
        annotation: ProGuardKotlinAnnotation,
        argument: ProGuardAnnotationArgument,
        value: ProGuardDoubleValue,
    ) = consumer.accept(argument.name, DoubleValue(value.value))

    override fun visitBooleanArgument(
        clazz: Clazz,
        annotatable: ProGuardKotlinAnnotatable,
        annotation: ProGuardKotlinAnnotation,
        argument: ProGuardAnnotationArgument,
        value: ProGuardBooleanValue,
    ) = consumer.accept(argument.name, BooleanValue(value.value))

    override fun visitStringArgument(
        clazz: Clazz,
        annotatable: ProGuardKotlinAnnotatable,
        annotation: ProGuardKotlinAnnotation,
        argument: ProGuardAnnotationArgument,
        value: ProGuardStringValue,
    ) = consumer.accept(argument.name, StringValue(value.value))

    override fun visitClassArgument(
        clazz: Clazz,
        annotatable: ProGuardKotlinAnnotatable,
        annotation: ProGuardKotlinAnnotation,
        argument: ProGuardAnnotationArgument,
        value: ProGuardClassValue,
    ) = run {
        if (value.arrayDimensionsCount == 0) {
            consumer.accept(argument.name, KClassValue(value.className))
        } else {
            consumer.accept(argument.name, ArrayKClassValue(value.className, value.arrayDimensionsCount))
        }
    }

    override fun visitEnumArgument(
        clazz: Clazz,
        annotatable: ProGuardKotlinAnnotatable,
        annotation: ProGuardKotlinAnnotation,
        argument: ProGuardAnnotationArgument,
        value: ProGuardEnumValue,
    ) = consumer.accept(argument.name, EnumValue(value.className, value.enumEntryName))

    override fun visitAnnotationArgument(
        clazz: Clazz,
        annotatable: ProGuardKotlinAnnotatable,
        annotation: ProGuardKotlinAnnotation,
        argument: ProGuardAnnotationArgument,
        value: ProGuardAnnotationValue,
    ) = value.annotationAccept(
        clazz,
        annotatable,
        AnnotationConstructor { consumer.accept(argument.name, AnnotationValue(it)) },
    )

    override fun visitArrayArgument(
        clazz: Clazz,
        annotatable: ProGuardKotlinAnnotatable,
        annotation: ProGuardKotlinAnnotation,
        argument: ProGuardAnnotationArgument,
        value: ProGuardArrayValue,
    ) = with(mutableListOf()) {
        // Collect the elements
        value.elementsAccept(
            clazz,
            annotatable,
            annotation,
            argument,
            AnnotationArgumentConstructor { _, element -> add(element) },
        )
        // Create the ArrayValue with the elements
        consumer.accept(argument.name, ArrayValue(this))
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy