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

name.remal.gradle_plugins.dsl.internal.PluginClassesProcessor.kt Maven / Gradle / Ivy

package name.remal.gradle_plugins.dsl.internal

import name.remal.ASM_API
import name.remal.get
import name.remal.gradle_plugins.api.AutoService
import name.remal.gradle_plugins.api.classes_processing.BytecodeModifier
import name.remal.gradle_plugins.api.classes_processing.ClassesProcessor
import name.remal.gradle_plugins.api.classes_processing.ClassesProcessor.COLLECTION_STAGE
import name.remal.gradle_plugins.api.classes_processing.ClassesProcessorsGradleTaskFactory
import name.remal.gradle_plugins.api.classes_processing.ProcessContext
import name.remal.gradle_plugins.dsl.*
import name.remal.gradle_plugins.dsl.extensions.toHasEntries
import name.remal.storeAsString
import org.gradle.api.tasks.compile.AbstractCompile
import org.objectweb.asm.AnnotationVisitor
import org.objectweb.asm.ClassReader
import org.objectweb.asm.ClassReader.*
import org.objectweb.asm.ClassVisitor
import org.objectweb.asm.Type
import org.objectweb.asm.tree.AnnotationNode
import java.util.*

class PluginClassesProcessor : ClassesProcessor {

    companion object {
        private val pluginDesc: String = Type.getDescriptor(Plugin::class.java)
    }

    override fun process(bytecode: ByteArray, bytecodeModifier: BytecodeModifier, className: String, resourceName: String, context: ProcessContext) {
        val pluginAnnotationNodes = mutableListOf()
        ClassReader(bytecode).accept(
            object : ClassVisitor(ASM_API) {
                override fun visitAnnotation(desc: String?, visible: Boolean): AnnotationVisitor? {
                    if (pluginDesc == desc) return AnnotationNode(desc).also { pluginAnnotationNodes.add(it) }
                    return null
                }
            },
            SKIP_DEBUG or SKIP_FRAMES or SKIP_CODE
        )

        pluginAnnotationNodes.forEach { pluginAnnotationNode ->
            pluginAnnotationNode[Plugin::id]?.let { pluginId ->
                context.writeTextResource(
                    "META-INF/gradle-plugins/$pluginId.properties",
                    Properties().apply {
                        setProperty(IMPLEMENTATION_CLASS_PLUGIN_DESCRIPTOR_KEY, className)
                        pluginAnnotationNode[Plugin::description]?.let { setProperty(DESCRIPTION_PLUGIN_DESCRIPTOR_KEY, it) }
                        pluginAnnotationNode[Plugin::tags]?.let { setProperty(TAGS_PLUGIN_DESCRIPTOR_KEY, it.joinToString(";")) }
                        pluginAnnotationNode[Plugin::isHidden]?.let { setProperty(IS_HIDDEN_DESCRIPTOR_KEY, it.toString()) }
                    }.storeAsString()
                )
            }
        }
    }

    override fun getStage() = COLLECTION_STAGE

}

@AutoService
class PluginClassesProcessorFactory : ClassesProcessorsGradleTaskFactory {

    override fun createClassesProcessors(compileTask: AbstractCompile): List {
        if (!compileTask.classpath.toHasEntries().containsClass(Plugin::class.java)) return emptyList()
        return listOf(PluginClassesProcessor())
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy