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

com.anatawa12.javaStabGen.SignatureVisitors.kt Maven / Gradle / Ivy

The newest version!
package com.anatawa12.javaStabGen

import com.squareup.javapoet.*
import org.objectweb.asm.Opcodes
import org.objectweb.asm.TypeReference.*
import org.objectweb.asm.signature.SignatureVisitor
import org.objectweb.asm.tree.ClassNode
import org.objectweb.asm.tree.TypeAnnotationNode

internal class MethodSignatureVisitor(classNode: ClassNode, typeAnnotations: List) :
    TypeParametersSignatureVisitor(classNode, typeAnnotations, METHOD_TYPE_PARAMETER) {
    val parameters = mutableListOf()
    var returns: TypeName? = null
        private set
    val throws = mutableListOf()

    override fun visitParameterType(): SignatureVisitor {
        finishVisitParameter()
        return TypeNameSignatureVisitor(classNode,
            typeAnnotations.filterWith(newFormalParameterReference(parameters.size), classNode)) { typeName ->
            parameters += typeName
        }
    }

    override fun visitReturnType(): SignatureVisitor {
        finishVisitParameter()
        return TypeNameSignatureVisitor(classNode,
            typeAnnotations.filterWith(newTypeReference(METHOD_RETURN), classNode)) { typeName ->
            returns = typeName
        }
    }

    override fun visitExceptionType(): SignatureVisitor {
        return TypeNameSignatureVisitor(classNode,
            typeAnnotations.filterWith(newExceptionReference(throws.size), classNode)) { typeName ->
            throws += typeName
        }
    }
}

internal class ClassSignatureVisitor(classNode: ClassNode, typeAnnotations: List) :
    TypeParametersSignatureVisitor(classNode, typeAnnotations, CLASS_TYPE_PARAMETER) {
    var superClass: TypeName? = null
        private set
    val superInterfaces = mutableListOf()

    override fun visitSuperclass(): SignatureVisitor {
        finishVisitParameter()
        return TypeNameSignatureVisitor(classNode,
            typeAnnotations.filterWith(newSuperTypeReference(-1), classNode)) { typeName ->
            superClass = typeName
        }
    }

    override fun visitInterface(): SignatureVisitor {
        finishVisitParameter()
        return TypeNameSignatureVisitor(classNode,
            typeAnnotations.filterWith(newSuperTypeReference(superInterfaces.size), classNode)) { typeName ->
            superInterfaces += typeName
        }
    }
}

internal class FieldSignatureVisitor(classNode: ClassNode, typeAnnotations: List)
    : TypeNameSignatureVisitor(classNode, typeAnnotations.filterWith(newTypeReference(FIELD), classNode), {}) {
    var type: TypeName? = null
        private set
    init {
        process = { type = it }
    }
}

internal abstract class TypeParametersSignatureVisitor(
    val classNode: ClassNode,
    val typeAnnotations: List,
    private val typeParamSort: Int,
) : SignatureVisitor(Opcodes.ASM5) {
    private var typeVariableName: String? = null
    private var bounds = mutableListOf()
    private var boundCount = 0
    var typeParameters = mutableListOf()

    override fun visitFormalTypeParameter(name: String) {
        finishVisitParameter()
        typeVariableName = name
    }

    override fun visitClassBound(): SignatureVisitor {
        val annotations = typeAnnotations.filterWith(
            newTypeParameterBoundReference(CLASS_TYPE_PARAMETER_BOUND + typeParamSort,
                typeParameters.size, boundCount++), classNode)
        return TypeNameSignatureVisitor(classNode, annotations) { typeName ->
            bounds.add(typeName)
        }
    }

    override fun visitInterfaceBound(): SignatureVisitor {
        if (boundCount == 0) boundCount++
        val annotations = typeAnnotations.filterWith(
            newTypeParameterBoundReference(CLASS_TYPE_PARAMETER_BOUND + typeParamSort,
                typeParameters.size, boundCount++), classNode)
        return TypeNameSignatureVisitor(classNode, annotations) { typeName ->
            bounds.add(typeName)
        }
    }

    protected fun finishVisitParameter() {
        val typeVariableName = typeVariableName ?: return
        if (bounds.any { it == null }) {
            typeParameters.add(null)
        } else {
            typeParameters.add(TypeVariableName.get(typeVariableName, *bounds.toTypedArray())
                ?.let { typeAnnotations.filterWith(newTypeParameterReference(typeParamSort, typeParameters.size),
                    classNode).annotate(it) }
            )
        }
        this.typeVariableName = null
        bounds = mutableListOf()
        boundCount = 0
    }
}

internal open class TypeNameSignatureVisitor(
    val classNode: ClassNode,
    var typeAnnotations: TypeAnnotations,
    var process: (TypeName?) -> Unit,
) : SignatureVisitor(Opcodes.ASM5) {
    var dimensions = 0

    private fun TypeName.computeArray(): TypeName {
        var type = this
        repeat(dimensions) {
            type = ArrayTypeName.of(type)
            typeAnnotations = typeAnnotations.outArray()
            type = typeAnnotations.annotate(type)
        }
        return type
    }

    override fun visitArrayType(): SignatureVisitor {
        dimensions++
        typeAnnotations = typeAnnotations.inArray()
        return this
    }

    override fun visitBaseType(descriptor: Char) {
        process(primitiveTypeFromDescriptor(descriptor)
            .let(typeAnnotations::annotate)
            .computeArray())
    }

    override fun visitTypeVariable(name: String) {
        process(name.asJavaIdentifierOrNull()
            ?.let(TypeVariableName::get)
            ?.let(typeAnnotations::annotate)
            ?.computeArray())
    }

    // classType
    var baseType: TypeNameBuilder? = null
    var typeVariables: MutableList? = null
    var rootAnnotations: TypeAnnotations? = null

    override fun visitClassType(name: String) {
        val (className, annotations) = classNameFromInternalName(name, classNode, typeAnnotations) ?: kotlin.run {
            baseType = null
            return
        }
        rootAnnotations = typeAnnotations
        baseType = TypeNameBuilder.Class(className)
        typeAnnotations = annotations
    }

    override fun visitInnerClassType(name: String) {
        baseType = baseType?.computeTypeVariables(typeVariables)?.nested(name)
            ?.also { it.typeAnnotations = typeAnnotations }
        typeAnnotations = typeAnnotations.nested()
        typeVariables = null
    }

    private fun typeVariables(): MutableList = typeVariables ?: mutableListOf().also { typeVariables = it }

    override fun visitTypeArgument() {
        typeVariables().add(WildcardTypeName.subtypeOf(TypeName.OBJECT))
    }

    override fun visitTypeArgument(wildcard: Char): SignatureVisitor {
        var annotations = typeAnnotations.outer().typeParam(typeVariables().size)
        if (wildcard != '=') annotations = annotations.wildcardBound()
        return TypeNameSignatureVisitor(classNode, annotations) { name ->
            when (wildcard) {
                '=' -> typeVariables().add(name)
                // +: ? extends TYPE
                '+' -> typeVariables().add(WildcardTypeName.subtypeOf(name))
                // -: ? super TYPE
                '-' -> typeVariables().add(WildcardTypeName.supertypeOf(name))
            }
        }
    }

    override fun visitEnd() {
        typeAnnotations = rootAnnotations!!
        process(baseType?.computeTypeVariables(typeVariables)?.toTypeName()?.computeArray())
    }
}

internal sealed class TypeNameBuilder {
    var typeAnnotations: TypeAnnotations? = null

    abstract fun computeTypeVariables(typeVariables: MutableList?): TypeNameBuilder?
    abstract fun nested(name: String): TypeNameBuilder?
    abstract fun toTypeName(): TypeName

    class Class(val className: ClassName) : TypeNameBuilder() {
        override fun computeTypeVariables(typeVariables: MutableList?): TypeNameBuilder? {
            if (typeVariables == null) return this
            if (typeVariables.any { it == null }) return null
            return Parameterized(ParameterizedTypeName.get(toTypeName(), *typeVariables.toTypedArray()))
        }

        override fun nested(name: String): TypeNameBuilder? =
            name.asJavaIdentifierOrNull()
                ?.let { toTypeName().nestedClass(it) }
                ?.let(::Class)

        override fun toTypeName(): ClassName = typeAnnotations?.annotate(className) ?: className
    }

    class Parameterized(val className: ParameterizedTypeName, val name: String? = null): TypeNameBuilder() {
        override fun computeTypeVariables(typeVariables: MutableList?): TypeNameBuilder? {
            if (typeVariables == null) return this
            if (typeVariables.any { it == null }) return null
            val name = checkNotNull(name) { "must be nested parameterized type" }
            return Parameterized(className.nestedClass(name, typeVariables).let { typeAnnotations?.annotate(it) ?: it })
        }

        override fun nested(name: String): TypeNameBuilder? {
            val className = toTypeName()
            return name.asJavaIdentifierOrNull()
                ?.let { Parameterized(className, it) }
        }

        override fun toTypeName(): ParameterizedTypeName =
            this.name?.let { thisName -> className.nestedClass(thisName) }
                ?.let { typeAnnotations?.annotate(it) ?: it }
                ?: className
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy