From 3443db38a7555a0f45eff09b245faa54482ffba0 Mon Sep 17 00:00:00 2001 From: Cesar Munoz Date: Sat, 24 Jan 2026 11:31:05 +0100 Subject: [PATCH 1/8] Using java toolchains --- asmifier-plugin/build.gradle.kts | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/asmifier-plugin/build.gradle.kts b/asmifier-plugin/build.gradle.kts index d17a9db..f15d1eb 100644 --- a/asmifier-plugin/build.gradle.kts +++ b/asmifier-plugin/build.gradle.kts @@ -16,10 +16,10 @@ dependencies { testImplementation(libs.assertj) } -val javaVersion = JavaVersion.VERSION_11 java { - sourceCompatibility = javaVersion - targetCompatibility = javaVersion + toolchain { + languageVersion = JavaLanguageVersion.of(17) + } } gradlePlugin { @@ -31,17 +31,15 @@ gradlePlugin { } } -tasks.withType(Test::class.java) { +tasks.withType { useJUnitPlatform() systemProperty("asm_version", libs.versions.asm.get()) } -tasks.withType(JavaCompile::class.java) { +tasks.withType { if (name.contains("test", true)) { options.errorprone.isEnabled.set(false) - val testJavaVersion = JavaVersion.VERSION_15.toString() - sourceCompatibility = testJavaVersion - targetCompatibility = testJavaVersion } else { + options.release = 11 // Ensuring deliverable jvm compatibility options.errorprone { check("NullAway", CheckSeverity.ERROR) option("NullAway:AnnotatedPackages", "com.likethesalad.asm") From da9cc8bde1acf8ca5d88b588cccdbb53752d8bb7 Mon Sep 17 00:00:00 2001 From: Cesar Munoz Date: Sat, 24 Jan 2026 11:38:43 +0100 Subject: [PATCH 2/8] Updating heap size --- gradle.properties | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 800797c..63cec08 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,5 @@ #Wed Mar 05 06:05:03 UTC 2025 +org.gradle.jvmargs=-Xmx1024M description=Convert Java code to ASM instructions version=1.3.0 -group=com.likethesalad.asm +group=com.likethesalad.asm \ No newline at end of file From 78c9600d5735028ee0853ab3571832319960b880 Mon Sep 17 00:00:00 2001 From: Cesar Munoz Date: Sat, 24 Jan 2026 11:49:29 +0100 Subject: [PATCH 3/8] Using java 21 for compilation --- .github/workflows/pr-check.yml | 4 ++-- asmifier-plugin/build.gradle.kts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 3502930..a51b4c1 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -13,10 +13,10 @@ jobs: contents: read steps: - uses: actions/checkout@v6 - - name: Set up JDK 17 + - name: Set up JDK 21 uses: actions/setup-java@v5 with: - java-version: '17' + java-version: '21' distribution: 'temurin' - name: Build and check with Gradle Wrapper run: ./gradlew check diff --git a/asmifier-plugin/build.gradle.kts b/asmifier-plugin/build.gradle.kts index f15d1eb..8c244cd 100644 --- a/asmifier-plugin/build.gradle.kts +++ b/asmifier-plugin/build.gradle.kts @@ -18,7 +18,7 @@ dependencies { java { toolchain { - languageVersion = JavaLanguageVersion.of(17) + languageVersion = JavaLanguageVersion.of(21) } } From 8c2a792d2a9f2e315a574977057ee4e6c7c5ff9e Mon Sep 17 00:00:00 2001 From: Cesar Munoz Date: Sat, 24 Jan 2026 12:01:37 +0100 Subject: [PATCH 4/8] Added non java source test --- .../likethesalad/asm/AsmifierPluginTest.java | 185 ++++++++++-------- 1 file changed, 104 insertions(+), 81 deletions(-) diff --git a/asmifier-plugin/src/test/java/com/likethesalad/asm/AsmifierPluginTest.java b/asmifier-plugin/src/test/java/com/likethesalad/asm/AsmifierPluginTest.java index 9184745..d9f43df 100644 --- a/asmifier-plugin/src/test/java/com/likethesalad/asm/AsmifierPluginTest.java +++ b/asmifier-plugin/src/test/java/com/likethesalad/asm/AsmifierPluginTest.java @@ -1,6 +1,12 @@ package com.likethesalad.asm; -import static org.assertj.core.api.Assertions.assertThat; +import org.gradle.testkit.runner.BuildResult; +import org.gradle.testkit.runner.GradleRunner; +import org.gradle.testkit.runner.TaskOutcome; +import org.jetbrains.annotations.NotNull; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import java.io.File; import java.io.IOException; @@ -11,13 +17,8 @@ import java.nio.file.attribute.BasicFileAttributes; import java.util.HashMap; import java.util.Map; -import org.gradle.testkit.runner.BuildResult; -import org.gradle.testkit.runner.GradleRunner; -import org.gradle.testkit.runner.TaskOutcome; -import org.jetbrains.annotations.NotNull; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.io.TempDir; + +import static org.assertj.core.api.Assertions.assertThat; class AsmifierPluginTest { @TempDir File projectDir; @@ -30,15 +31,15 @@ void setUp() throws IOException { createFile( "settings.gradle.kts", """ - import org.gradle.api.initialization.resolve.RepositoriesMode - - dependencyResolutionManagement { - repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) - repositories { - mavenCentral() - } - } - """); + import org.gradle.api.initialization.resolve.RepositoriesMode + + dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + mavenCentral() + } + } + """); } @Test @@ -46,25 +47,25 @@ void verifyFileOutput() throws IOException { createAsmifierSourceFile( "com/test/MyClass.java", """ - package com.test; - - public class MyClass { - public void someMethod() { - System.out.println("Hello World!"); - } - } - """); + package com.test; + + public class MyClass { + public void someMethod() { + System.out.println("Hello World!"); + } + } + """); createAsmifierSourceFile( "com/test/MyOtherClass.java", """ - package com.test; + package com.test; - public class MyOtherClass { - public void someOtherMethod() { - System.out.println("Hello Other World!"); - } - } - """); + public class MyOtherClass { + public void someOtherMethod() { + System.out.println("Hello Other World!"); + } + } + """); BuildResult result = asmifierRunner().build(); @@ -80,22 +81,22 @@ void verifyFileOutputWithAnonymousClass() throws IOException { createAsmifierSourceFile( "com/test/MyClass.java", """ - package com.test; - - import java.util.function.Supplier; - - public class MyClass { - public void someMethod() { - Supplier supplier = new Supplier() { - @Override - public String get() { - return "Hello World!"; - } - }; - System.out.println(supplier.get()); + package com.test; + + import java.util.function.Supplier; + + public class MyClass { + public void someMethod() { + Supplier supplier = new Supplier() { + @Override + public String get() { + return "Hello World!"; + } + }; + System.out.println(supplier.get()); + } } - } - """); + """); BuildResult result = asmifierRunner().build(); assertThat(getAsmifierOutcome(result)).isEqualTo(TaskOutcome.SUCCESS); @@ -105,31 +106,52 @@ public String get() { "asm/com/test/MyClassDump.java", "asm/com/test/MyClass$1Dump.java"); } + @Test + void verifyFileFromNonJavaSourceOutput() throws IOException { + createAsmifierSourceFile( + "com/test/MyClass.kt", + """ + package com.test + + class MyClass { + fun someMethod() { + println("Hello World!") + } + } + """); + + BuildResult result = asmifierRunner().build(); + + assertThat(getAsmifierOutcome(result)).isEqualTo(TaskOutcome.SUCCESS); + Map generatedFiles = getGeneratedFiles(); + assertThat(generatedFiles.keySet()).containsExactlyInAnyOrder("asm/com/test/MyClassDump.java"); + } + @Test void verifyIncrementalCompilation() throws IOException { Path myClassFile = createAsmifierSourceFile( "com/test/MyClass.java", """ - package com.test; + package com.test; - public class MyClass { - public void someMethod() { - System.out.println("Hello World!"); - } - } - """); + public class MyClass { + public void someMethod() { + System.out.println("Hello World!"); + } + } + """); createAsmifierSourceFile( "com/test/MySecondClass.java", """ - package com.test; + package com.test; - public class MySecondClass { - public void someSecondMethod() { - System.out.println("Hello World!"); + public class MySecondClass { + public void someSecondMethod() { + System.out.println("Hello World!"); + } } - } - """); + """); createAsmifierSourceFile( "com/test/MyThirdClass.java", """ @@ -167,26 +189,26 @@ public void someThirdMethod() { createAsmifierSourceFile( "com/test/MyThirdClass.java", """ - package com.test; + package com.test; - public class MyThirdClass { - public void someThirdMethod() { - System.out.println("Hello Changed World!"); - } + public class MyThirdClass { + public void someThirdMethod() { + System.out.println("Hello Changed World!"); } - """); + } + """); // Adding input createAsmifierSourceFile( "com/test/MyFourthClass.java", """ - package com.test; + package com.test; - public class MyFourthClass { - public void someFourthMethod() { - System.out.println("Hello World!"); - } + public class MyFourthClass { + public void someFourthMethod() { + System.out.println("Hello World!"); } - """); + } + """); // Rerun BuildResult secondResult = asmifierRunner().build(); @@ -257,15 +279,16 @@ private void createBuildFile() throws IOException { createFile( "build.gradle.kts", """ - plugins { - id("java") - id("com.likethesalad.asmifier") - } - - dependencies { - asmifier("org.ow2.asm:asm-util:%s") - } - """ + plugins { + id("java") + id("org.jetbrains.kotlin.jvm") version "2.0.0" + id("com.likethesalad.asmifier") + } + + dependencies { + asmifier("org.ow2.asm:asm-util:%s") + } + """ .formatted(System.getProperty("asm_version"))); } From 0b6d1a5a0ba277cb4d6d713531e91485d0d326ca Mon Sep 17 00:00:00 2001 From: Cesar Munoz Date: Sat, 24 Jan 2026 12:16:14 +0100 Subject: [PATCH 5/8] Improving exception messages --- .../likethesalad/asm/tasks/AsmifierTask.java | 2 +- .../likethesalad/asm/AsmifierPluginTest.java | 17 ++++++++--------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/asmifier-plugin/src/main/java/com/likethesalad/asm/tasks/AsmifierTask.java b/asmifier-plugin/src/main/java/com/likethesalad/asm/tasks/AsmifierTask.java index dd0f52e..48f2228 100644 --- a/asmifier-plugin/src/main/java/com/likethesalad/asm/tasks/AsmifierTask.java +++ b/asmifier-plugin/src/main/java/com/likethesalad/asm/tasks/AsmifierTask.java @@ -80,7 +80,7 @@ public void execute(InputChanges inputChanges) { private void asmifyToFile(File outputFile, FileCollection classpath, String relativeSourcePath) { try (FileOutputStream outputStream = new FileOutputStream(outputFile)) { asmify(classpath, relativeSourcePath, outputStream); - } catch (IOException e) { + } catch (Exception e) { throw new RuntimeException( "Exception during asmifier run where the source is: " + relativeSourcePath diff --git a/asmifier-plugin/src/test/java/com/likethesalad/asm/AsmifierPluginTest.java b/asmifier-plugin/src/test/java/com/likethesalad/asm/AsmifierPluginTest.java index d9f43df..d17a99f 100644 --- a/asmifier-plugin/src/test/java/com/likethesalad/asm/AsmifierPluginTest.java +++ b/asmifier-plugin/src/test/java/com/likethesalad/asm/AsmifierPluginTest.java @@ -1,12 +1,6 @@ package com.likethesalad.asm; -import org.gradle.testkit.runner.BuildResult; -import org.gradle.testkit.runner.GradleRunner; -import org.gradle.testkit.runner.TaskOutcome; -import org.jetbrains.annotations.NotNull; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.io.TempDir; +import static org.assertj.core.api.Assertions.assertThat; import java.io.File; import java.io.IOException; @@ -17,8 +11,13 @@ import java.nio.file.attribute.BasicFileAttributes; import java.util.HashMap; import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; +import org.gradle.testkit.runner.BuildResult; +import org.gradle.testkit.runner.GradleRunner; +import org.gradle.testkit.runner.TaskOutcome; +import org.jetbrains.annotations.NotNull; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; class AsmifierPluginTest { @TempDir File projectDir; From a4f9fcb6b24fc5e70804389bc88335c4ab19ff1d Mon Sep 17 00:00:00 2001 From: Cesar Munoz Date: Sat, 24 Jan 2026 12:38:49 +0100 Subject: [PATCH 6/8] Supporting non-java sources --- .../com/likethesalad/asm/AsmifierPlugin.java | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/asmifier-plugin/src/main/java/com/likethesalad/asm/AsmifierPlugin.java b/asmifier-plugin/src/main/java/com/likethesalad/asm/AsmifierPlugin.java index e95e0ef..d95be56 100644 --- a/asmifier-plugin/src/main/java/com/likethesalad/asm/AsmifierPlugin.java +++ b/asmifier-plugin/src/main/java/com/likethesalad/asm/AsmifierPlugin.java @@ -1,15 +1,16 @@ package com.likethesalad.asm; import com.likethesalad.asm.tasks.AsmifierTask; +import java.util.List; import org.gradle.api.Plugin; import org.gradle.api.Project; import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.ConfigurationContainer; import org.gradle.api.file.Directory; -import org.gradle.api.file.FileCollection; import org.gradle.api.plugins.JavaPluginExtension; import org.gradle.api.provider.Provider; import org.gradle.api.tasks.SourceSet; +import org.gradle.api.tasks.Sync; import org.gradle.api.tasks.TaskProvider; import org.jetbrains.annotations.NotNull; @@ -25,6 +26,16 @@ public void apply(Project project) { Configuration asmifierClasspath = getAsmifierClasspath(project, asmifierSourceSet); + TaskProvider asmifierTargetCollector = + project.getTasks().register("asmifierCollector", Sync.class); + asmifierTargetCollector.configure( + sync -> { + sync.from( + asmifierSourceSet.getOutput(), + copySpec -> copySpec.setIncludes(List.of("**/*.class"))); + sync.into(project.getLayout().getBuildDirectory().dir("intermediates/" + sync.getName())); + }); + TaskProvider asmifierTaskTaskProvider = project.getTasks().register(ASMIFIER_TASK_NAME, AsmifierTask.class); asmifierTaskTaskProvider.configure( @@ -36,9 +47,7 @@ public void apply(Project project) { .getLayout() .getBuildDirectory() .dir("generated/sources/" + ASMIFIER_OUTPUT_DIR_NAME)); - asmifierTask - .getTargetClasses() - .from(getTargetClassesCollection(project, asmifierSourceSet)); + asmifierTask.getTargetClasses().from(asmifierTargetCollector); asmifierTask.getClasspath().from(asmifierClasspath); }); @@ -49,13 +58,6 @@ public void apply(Project project) { asmifierTaskTaskProvider.flatMap(AsmifierTask::getOutputDir)); } - private static @NotNull FileCollection getTargetClassesCollection( - Project project, SourceSet asmifierSourceSet) { - return project - .files(asmifierSourceSet.getOutput()) - .filter(element -> !element.getName().endsWith(".class")); - } - private static void configureDumpSourceSet( Project project, SourceSet asmifierSourceSet, From f35e0e1e5c2590f8eaa7f5b0f4533fe4baa01be1 Mon Sep 17 00:00:00 2001 From: Cesar Munoz Date: Sat, 24 Jan 2026 13:16:15 +0100 Subject: [PATCH 7/8] Updating changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b6b092..fae6c09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Gradle ASMifier Changelog +## Unreleased + +- Adding support for any non-Java sources (tested with Kotlin). + ## Version 1.2.0 (2025-03-05) - Adding support for anonymous classes. From e12d8e12a95a082ff74d0766cf5e860609f27043 Mon Sep 17 00:00:00 2001 From: Cesar Munoz Date: Sat, 24 Jan 2026 13:26:38 +0100 Subject: [PATCH 8/8] Updating readme --- README.md | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index a1dc8ea..beefa63 100644 --- a/README.md +++ b/README.md @@ -3,19 +3,21 @@ What it is --- -Convenience tool that converts `.java` files to [ASM](https://asm.ow2.io/) instructions by wrapping +Convenience tool that converts `.java` source files (and non-Java ones that still compile into JVM bytecode, such as +Kotlin's (`.kt`) ones, for example) to [ASM](https://asm.ow2.io/) instructions by wrapping the [ASMifier](https://asm.ow2.io/javadoc/org/objectweb/asm/util/ASMifier.html) tool around a Gradle incremental task -that can convert multiple `.java` files at once. +that can convert multiple source files at once. This tool, as well as [the one it's built upon](https://asm.ow2.io/javadoc/org/objectweb/asm/util/ASMifier.html), is -meant to be used as a development tool for anyone who'd like to check how does Java code translate into bytecode +meant to be used as a development tool for anyone who'd like to check how does source code translate into bytecode instructions using [ASM](https://asm.ow2.io/). What it is not --- -This is not a tool to generate production code. Its `.java` target files are in a separate location from the production -source files (similarly to the test sources, which are in a separate dir that isn't packaged into the production app). +This is not a tool to generate production code. Its source target files are in a separate location from the +production source files (similarly to the test sources, which are in a separate dir that isn't packaged into the +production app). How to use --- @@ -47,13 +49,16 @@ dependencies { } ``` -The `asmifier` dependency type is added by this plugin to ensure that its dependencies are separated from those of your -app (similarly to configurations such as `testImplementation` are only used for a specific purpose and not to get -packaged with your production code). +You can find the latest ASMifier version [here](https://central.sonatype.com/artifact/org.ow2.asm/asm-util). + +> [!NOTE] +> The `asmifier` dependency type is added by this plugin to ensure that its dependencies are separated from those +> of your app (similarly to configurations such as `testImplementation` are only used for a specific purpose and not +> to get packaged with your production code). ### Add sources to transform -The `.java` sources that will be transformed by this plugin must be placed in a src dir named `asmifier`, as +The sources that will be transformed by this plugin must be placed in a src dir named `asmifier`, as shown below. ```text @@ -63,12 +68,12 @@ app/ │ ├─ main/ │ │ ├─ java/ │ ├─ asmifier/ -│ │ ├─ java/ <-- Here is where the asmifier .java target files must be placed +│ │ ├─ java/ <-- Here is where the asmifier .java (or other JVM-supported) target files must be placed ``` ### Run the Gradle task -To transform the `.java` target files you must run the gradle task named `asmifier`, like so: +To transform the source files you must run the Gradle task named `asmifier`, like so: ```shell ./gradlew asmifier