diff --git a/README.md b/README.md index 251dfff..2a22787 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ This plugin allows removing all Kotlin @Metadata / @DebugMetadata / @SourceDebug ```kotlin plugins { kotlin("jvm") - id("io.github.izhangzhihao.unmeta") version "1.0.1" + id("io.github.izhangzhihao.unmeta") version "1.0.2" } unmeta { @@ -43,7 +43,7 @@ gradle.taskGraph.whenReady { ```kotlin plugins { id 'org.jetbrains.kotlin.jvm' version '1.8.21' - id "io.github.izhangzhihao.unmeta" version "1.0.1" + id "io.github.izhangzhihao.unmeta" version "1.0.2" } unmeta { diff --git a/example/bin/main/com/github/izhangzhihao/unmeta/example/SampleCode.kt b/example/bin/main/com/github/izhangzhihao/unmeta/example/SampleCode.kt new file mode 100644 index 0000000..1128141 --- /dev/null +++ b/example/bin/main/com/github/izhangzhihao/unmeta/example/SampleCode.kt @@ -0,0 +1,9 @@ +package com.github.izhangzhihao.unmeta.example + +/** + * a tail-recursive function with keyword tailrec + */ +tailrec fun factorial(n: Long, a: Long = 1): Long { + return if (n == 1L) a + else factorial(n - 1, n * a) +} diff --git a/example/build.gradle.kts b/example/build.gradle.kts index 71d3c36..b712d1e 100644 --- a/example/build.gradle.kts +++ b/example/build.gradle.kts @@ -1,6 +1,6 @@ plugins { kotlin("jvm") - id("io.github.izhangzhihao.unmeta") version "1.0.1" + id("io.github.izhangzhihao.unmeta") version "1.0.2" } unmeta { diff --git a/plugin-build/gradle.properties b/plugin-build/gradle.properties index 39b3a54..9ad67b3 100644 --- a/plugin-build/gradle.properties +++ b/plugin-build/gradle.properties @@ -1,5 +1,5 @@ ID=io.github.izhangzhihao.unmeta -VERSION=1.0.1 +VERSION=1.0.2 GROUP=io.github.izhangzhihao DISPLAY_NAME=Unmeta Kotlin classes plugin DESCRIPTION=Remove @Metadata and @DebugMetadata annotation from your Kotlin classes diff --git a/plugin-build/plugin/bin/main/io/github/izhangzhihao/unmeta/UnmetaClassVisitor.kt b/plugin-build/plugin/bin/main/io/github/izhangzhihao/unmeta/UnmetaClassVisitor.kt new file mode 100644 index 0000000..e688904 --- /dev/null +++ b/plugin-build/plugin/bin/main/io/github/izhangzhihao/unmeta/UnmetaClassVisitor.kt @@ -0,0 +1,35 @@ +package io.github.izhangzhihao.unmeta + +import org.gradle.api.logging.Logger +import org.objectweb.asm.AnnotationVisitor +import org.objectweb.asm.ClassVisitor +import org.objectweb.asm.Opcodes + +class UnmetaClassVisitor(private val path: String, cv: ClassVisitor, private val logger: Logger) : + ClassVisitor(Opcodes.ASM9, cv), Opcodes { + + var modified = false + + override fun visitAnnotation(desc: String?, visible: Boolean): AnnotationVisitor? { + return when (desc) { + "Lkotlin/Metadata;" -> { + logger.debug("Removed @Metadata annotation from $path") + modified = true + null + } + "Lkotlin/coroutines/jvm/internal/DebugMetadata;" -> { + logger.debug("Removed @DebugMetadata annotation from $path") + modified = true + null + } + "Lkotlin/jvm/internal/SourceDebugExtension;" -> { + logger.debug("Removed @SourceDebugExtension annotation from $path") + modified = true + null + } + else -> { + super.visitAnnotation(desc, visible) + } + } + } +} diff --git a/plugin-build/plugin/bin/main/io/github/izhangzhihao/unmeta/UnmetaExtension.kt b/plugin-build/plugin/bin/main/io/github/izhangzhihao/unmeta/UnmetaExtension.kt new file mode 100644 index 0000000..0a86cdc --- /dev/null +++ b/plugin-build/plugin/bin/main/io/github/izhangzhihao/unmeta/UnmetaExtension.kt @@ -0,0 +1,11 @@ +package io.github.izhangzhihao.unmeta + +import org.gradle.api.Project +import org.gradle.api.provider.Property +import javax.inject.Inject + +open class UnmetaExtension @Inject constructor(project: Project) { + private val objects = project.objects + + val enable: Property<Boolean> = objects.property(Boolean::class.java) +} diff --git a/plugin-build/plugin/bin/main/io/github/izhangzhihao/unmeta/UnmetaPlugin.kt b/plugin-build/plugin/bin/main/io/github/izhangzhihao/unmeta/UnmetaPlugin.kt new file mode 100644 index 0000000..45626e0 --- /dev/null +++ b/plugin-build/plugin/bin/main/io/github/izhangzhihao/unmeta/UnmetaPlugin.kt @@ -0,0 +1,16 @@ +package io.github.izhangzhihao.unmeta + +import org.gradle.api.Plugin +import org.gradle.api.Project + +class UnmetaPlugin : Plugin<Project> { + + private lateinit var extension: UnmetaExtension + + override fun apply(project: Project) { + extension = project.extensions.create("unmeta", UnmetaExtension::class.java, project) + val unmetaTaskTask = project.tasks.create("unmeta", UnmetaTask::class.java) + unmetaTaskTask.enable.set(extension.enable) + project.tasks.getByName("compileKotlin").finalizedBy(unmetaTaskTask) + } +} diff --git a/plugin-build/plugin/bin/main/io/github/izhangzhihao/unmeta/UnmetaTask.kt b/plugin-build/plugin/bin/main/io/github/izhangzhihao/unmeta/UnmetaTask.kt new file mode 100644 index 0000000..8ef886c --- /dev/null +++ b/plugin-build/plugin/bin/main/io/github/izhangzhihao/unmeta/UnmetaTask.kt @@ -0,0 +1,56 @@ +package io.github.izhangzhihao.unmeta + +import org.gradle.api.DefaultTask +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Optional +import org.gradle.api.tasks.TaskAction +import org.gradle.api.tasks.options.Option +import org.objectweb.asm.ClassReader +import org.objectweb.asm.ClassWriter +import java.io.File + +abstract class UnmetaTask : DefaultTask() { + + init { + description = "Drop @Metadata & @DebugMetadata from kotlin classes" + group = "build" + } + + @get:Input + @get:Option(option = "enable", description = "is unmeta enabled") + @get:Optional + abstract val enable: Property<Boolean> + + @TaskAction + fun unmetaAction() { + if (!enable.get()) { + logger.warn("unmeta is disabled") + } else { + logger.info("Start drop @Metadata & @DebugMetadata from kotlin classes") + project.buildDir.listFiles() + ?.forEach { file -> + if (file.isDirectory) { + dropMetadata(file) + } + } + } + } + + private fun dropMetadata(file: File) { + file.walk() + .filter { it.path.contains("classes") && it.path.endsWith(".class") } + .forEach { + if (it.isFile) { + val sourceClassBytes = it.readBytes() + val classReader = ClassReader(sourceClassBytes) + val classWriter = ClassWriter(classReader, ClassWriter.COMPUTE_MAXS) + val unmetaClassVisitor = UnmetaClassVisitor(it.absolutePath, classWriter, logger) + classReader.accept(unmetaClassVisitor, ClassReader.SKIP_DEBUG) + if (unmetaClassVisitor.modified) { + it.writeBytes(classWriter.toByteArray()) + } + } + } + } +} diff --git a/plugin-build/plugin/build.gradle.kts b/plugin-build/plugin/build.gradle.kts index 5c5d39b..0e51cf6 100644 --- a/plugin-build/plugin/build.gradle.kts +++ b/plugin-build/plugin/build.gradle.kts @@ -5,7 +5,7 @@ plugins { } dependencies { - implementation("org.ow2.asm:asm:9.4") + implementation("org.ow2.asm:asm:9.6") implementation(gradleApi()) testImplementation(libs.junit) diff --git a/plugin-build/plugin/src/main/java/io/github/izhangzhihao/unmeta/UnmetaClassVisitor.kt b/plugin-build/plugin/src/main/java/io/github/izhangzhihao/unmeta/UnmetaClassVisitor.kt index 50f5496..e688904 100644 --- a/plugin-build/plugin/src/main/java/io/github/izhangzhihao/unmeta/UnmetaClassVisitor.kt +++ b/plugin-build/plugin/src/main/java/io/github/izhangzhihao/unmeta/UnmetaClassVisitor.kt @@ -6,7 +6,7 @@ import org.objectweb.asm.ClassVisitor import org.objectweb.asm.Opcodes class UnmetaClassVisitor(private val path: String, cv: ClassVisitor, private val logger: Logger) : - ClassVisitor(Opcodes.ASM7, cv), Opcodes { + ClassVisitor(Opcodes.ASM9, cv), Opcodes { var modified = false