mirror of
https://github.com/fankes/unmeta-gradle-plugin.git
synced 2025-09-05 18:45:17 +08:00
Implement unmeta codes
- cited from io.github.izhangzhihao.unmeta
This commit is contained in:
@@ -4,5 +4,5 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unmeta {
|
unmeta {
|
||||||
message.set("Just trying this gradle plugin...")
|
isEnabled.set(true)
|
||||||
}
|
}
|
||||||
|
@@ -14,3 +14,5 @@ versionCheck = { id = "com.github.ben-manes.versions", version.ref = "versionChe
|
|||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
junit = "junit:junit:4.13.2"
|
junit = "junit:junit:4.13.2"
|
||||||
|
truth = "com.google.truth:truth:1.1.3"
|
||||||
|
asm = "org.ow2.asm:asm:9.4"
|
||||||
|
@@ -9,8 +9,10 @@ plugins {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation(kotlin("stdlib"))
|
implementation(kotlin("stdlib"))
|
||||||
implementation(gradleApi())
|
implementation(gradleApi())
|
||||||
|
implementation(libs.asm)
|
||||||
|
|
||||||
testImplementation(libs.junit)
|
testImplementation(libs.junit)
|
||||||
|
testImplementation(libs.truth)
|
||||||
}
|
}
|
||||||
|
|
||||||
java {
|
java {
|
||||||
|
@@ -0,0 +1,35 @@
|
|||||||
|
package com.axzae.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,
|
||||||
|
classVisitor: ClassVisitor,
|
||||||
|
private val logger: Logger,
|
||||||
|
) : ClassVisitor(Opcodes.ASM7, classVisitor), 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
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
super.visitAnnotation(desc, visible)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,26 +1,16 @@
|
|||||||
package com.axzae.unmeta
|
package com.axzae.unmeta
|
||||||
|
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.file.RegularFileProperty
|
|
||||||
import org.gradle.api.provider.Property
|
import org.gradle.api.provider.Property
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
const val DEFAULT_OUTPUT_FILE = "template-example.txt"
|
const val DEFAULT_IS_ENABLED = true
|
||||||
|
|
||||||
@Suppress("UnnecessaryAbstractClass")
|
@Suppress("UnnecessaryAbstractClass")
|
||||||
abstract class UnmetaExtension @Inject constructor(project: Project) {
|
abstract class UnmetaExtension @Inject constructor(project: Project) {
|
||||||
|
|
||||||
private val objects = project.objects
|
private val objects = project.objects
|
||||||
|
|
||||||
// Example of a property that is mandatory. The task will
|
val isEnabled: Property<Boolean> = objects.property(Boolean::class.java)
|
||||||
// fail if this property is not set as is annotated with @Optional.
|
.convention(DEFAULT_IS_ENABLED)
|
||||||
val message: Property<String> = objects.property(String::class.java)
|
|
||||||
|
|
||||||
// Example of a property that is optional.
|
|
||||||
val tag: Property<String> = objects.property(String::class.java)
|
|
||||||
|
|
||||||
// Example of a property with a default set with .convention
|
|
||||||
val outputFile: RegularFileProperty = objects.fileProperty().convention(
|
|
||||||
project.layout.buildDirectory.file(DEFAULT_OUTPUT_FILE),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
@@ -8,14 +8,10 @@ const val TASK_NAME = "unmetaTask"
|
|||||||
|
|
||||||
abstract class UnmetaPlugin : Plugin<Project> {
|
abstract class UnmetaPlugin : Plugin<Project> {
|
||||||
override fun apply(project: Project) {
|
override fun apply(project: Project) {
|
||||||
// Add the 'template' extension object
|
|
||||||
val extension = project.extensions.create(EXTENSION_NAME, UnmetaExtension::class.java, project)
|
val extension = project.extensions.create(EXTENSION_NAME, UnmetaExtension::class.java, project)
|
||||||
|
|
||||||
// Add a task that uses configuration from the extension object
|
|
||||||
project.tasks.register(TASK_NAME, UnmetaTask::class.java) {
|
project.tasks.register(TASK_NAME, UnmetaTask::class.java) {
|
||||||
it.tag.set(extension.tag)
|
it.isEnabled = extension.isEnabled.get()
|
||||||
it.message.set(extension.message)
|
|
||||||
it.outputFile.set(extension.outputFile)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,14 +1,11 @@
|
|||||||
package com.axzae.unmeta
|
package com.axzae.unmeta
|
||||||
|
|
||||||
import org.gradle.api.DefaultTask
|
import org.gradle.api.DefaultTask
|
||||||
import org.gradle.api.file.RegularFileProperty
|
|
||||||
import org.gradle.api.plugins.BasePlugin
|
import org.gradle.api.plugins.BasePlugin
|
||||||
import org.gradle.api.provider.Property
|
|
||||||
import org.gradle.api.tasks.Input
|
|
||||||
import org.gradle.api.tasks.Optional
|
|
||||||
import org.gradle.api.tasks.OutputFile
|
|
||||||
import org.gradle.api.tasks.TaskAction
|
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() {
|
abstract class UnmetaTask : DefaultTask() {
|
||||||
|
|
||||||
@@ -17,26 +14,29 @@ abstract class UnmetaTask : DefaultTask() {
|
|||||||
group = BasePlugin.BUILD_GROUP
|
group = BasePlugin.BUILD_GROUP
|
||||||
}
|
}
|
||||||
|
|
||||||
@get:Input
|
|
||||||
@get:Option(option = "message", description = "A message to be printed in the output file")
|
|
||||||
abstract val message: Property<String>
|
|
||||||
|
|
||||||
@get:Input
|
|
||||||
@get:Option(option = "tag", description = "A Tag to be used for debug and in the output file")
|
|
||||||
@get:Optional
|
|
||||||
abstract val tag: Property<String>
|
|
||||||
|
|
||||||
@get:OutputFile
|
|
||||||
abstract val outputFile: RegularFileProperty
|
|
||||||
|
|
||||||
@TaskAction
|
@TaskAction
|
||||||
fun unmetaAction() {
|
fun unmetaAction() {
|
||||||
val prettyTag = tag.orNull?.let { "[$it]" } ?: ""
|
if (!isEnabled) {
|
||||||
|
logger.warn("unmeta is disabled")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
logger.lifecycle("$prettyTag message is: ${message.orNull}")
|
logger.info("Start dropping @Metadata & @DebugMetadata from kotlin classes")
|
||||||
logger.lifecycle("$prettyTag tag is: ${tag.orNull}")
|
project.buildDir.listFiles()?.forEach { file -> if (file.isDirectory) dropMetadata(file) }
|
||||||
logger.lifecycle("$prettyTag outputFile is: ${outputFile.orNull}")
|
}
|
||||||
|
|
||||||
outputFile.get().asFile.writeText("$prettyTag ${message.get()}")
|
private fun dropMetadata(directory: File) {
|
||||||
|
directory.walk()
|
||||||
|
.filter { it.path.contains("classes") && it.path.endsWith(".class") && it.isFile }
|
||||||
|
.forEach {
|
||||||
|
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())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,10 +1,8 @@
|
|||||||
package com.axzae.unmeta
|
package com.axzae.unmeta
|
||||||
|
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
import org.gradle.testfixtures.ProjectBuilder
|
import org.gradle.testfixtures.ProjectBuilder
|
||||||
import org.junit.Assert.assertEquals
|
|
||||||
import org.junit.Assert.assertNotNull
|
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
class UnmetaPluginTest {
|
class UnmetaPluginTest {
|
||||||
|
|
||||||
@@ -13,7 +11,7 @@ class UnmetaPluginTest {
|
|||||||
val project = ProjectBuilder.builder().build()
|
val project = ProjectBuilder.builder().build()
|
||||||
project.pluginManager.apply("com.axzae.unmeta")
|
project.pluginManager.apply("com.axzae.unmeta")
|
||||||
|
|
||||||
assert(project.tasks.getByName("unmetaTask") is UnmetaTask)
|
assertThat(project.tasks.getByName("unmetaTask")).isInstanceOf(UnmetaTask::class.java)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -21,24 +19,18 @@ class UnmetaPluginTest {
|
|||||||
val project = ProjectBuilder.builder().build()
|
val project = ProjectBuilder.builder().build()
|
||||||
project.pluginManager.apply("com.axzae.unmeta")
|
project.pluginManager.apply("com.axzae.unmeta")
|
||||||
|
|
||||||
assertNotNull(project.extensions.getByName("unmeta"))
|
assertThat(project.extensions.getByName("unmeta")).isNotNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `parameters are passed correctly from extension to task`() {
|
fun `parameters are passed correctly from extension to task`() {
|
||||||
val project = ProjectBuilder.builder().build()
|
val project = ProjectBuilder.builder().build()
|
||||||
project.pluginManager.apply("com.axzae.unmeta")
|
project.pluginManager.apply("com.axzae.unmeta")
|
||||||
val aFile = File(project.projectDir, ".tmp")
|
|
||||||
(project.extensions.getByName("unmeta") as UnmetaExtension).apply {
|
(project.extensions.getByName("unmeta") as UnmetaExtension).apply {
|
||||||
tag.set("a-sample-tag")
|
isEnabled.set(false)
|
||||||
message.set("just-a-message")
|
|
||||||
outputFile.set(aFile)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val task = project.tasks.getByName("unmetaTask") as UnmetaTask
|
val task = project.tasks.getByName("unmetaTask") as UnmetaTask
|
||||||
|
assertThat(task.isEnabled).isFalse()
|
||||||
assertEquals("a-sample-tag", task.tag.get())
|
|
||||||
assertEquals("just-a-message", task.message.get())
|
|
||||||
assertEquals(aFile, task.outputFile.get().asFile)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user