From 64348c0bf6bc01c9252b2d9ae29d64ed62cb6c54 Mon Sep 17 00:00:00 2001 From: Phoenix-Starlight Date: Wed, 22 Nov 2023 20:41:09 -0800 Subject: [PATCH 01/45] Create mixin config AP - Takes two compiler arguments: -ArootProject.name and an optional -Aproject.name --- annotation-processor/build.gradle | 21 +++ .../mixinAp/annotation/MixinProcessor.java | 126 ++++++++++++++++++ .../mixinAp/config/MixinConfig.java | 29 ++++ build.gradle | 2 +- buildSrc/build.gradle | 2 +- settings.gradle | 1 + 6 files changed, 179 insertions(+), 2 deletions(-) create mode 100644 annotation-processor/build.gradle create mode 100644 annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java create mode 100644 annotation-processor/src/main/java/org/fury_phoenix/mixinAp/config/MixinConfig.java diff --git a/annotation-processor/build.gradle b/annotation-processor/build.gradle new file mode 100644 index 000000000..8d8df01d2 --- /dev/null +++ b/annotation-processor/build.gradle @@ -0,0 +1,21 @@ +plugins { + id 'java-library' + id 'com.diffplug.spotless' +} + +repositories { + mavenCentral() +} + +dependencies { + implementation 'com.google.code.gson:gson:2.10.1' + annotationProcessor 'com.google.auto.service:auto-service:1.1.1' + compileOnly 'com.google.auto.service:auto-service:1.1.1' +} + +spotless { + java { + removeUnusedImports() + } +} +version = '1.0' \ No newline at end of file diff --git a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java new file mode 100644 index 000000000..c8e4dd9a0 --- /dev/null +++ b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java @@ -0,0 +1,126 @@ +package org.fury_phoenix.mixinAp.annotation; + +import com.google.auto.service.AutoService; +import com.google.common.base.Throwables; +import com.google.common.collect.ListMultimap; +import com.google.common.collect.ArrayListMultimap; + +import com.google.gson.GsonBuilder; + +import java.io.IOException; +import java.io.Writer; +import java.lang.annotation.ElementType; +import java.util.List; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.Processor; +import javax.annotation.processing.ProcessingEnvironment; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; +import javax.annotation.processing.SupportedOptions; +import javax.annotation.processing.SupportedSourceVersion; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.TypeElement; +import javax.tools.Diagnostic; +import javax.tools.StandardLocation; + +import org.fury_phoenix.mixinAp.config.MixinConfig; + +import static java.util.function.Predicate.not; + +@SupportedAnnotationTypes({"org.spongepowered.asm.mixin.Mixin", "org.embeddedt.modernfix.annotation.ClientOnlyMixin"}) +@SupportedOptions({"rootProject.name", "project.name"}) +@SupportedSourceVersion(SourceVersion.RELEASE_17) +@AutoService(Processor.class) +public class MixinProcessor extends AbstractProcessor { + + // Remember to call toString when using aliases + private static final Map aliases = Map.of( + "Mixin", "mixins", + "ClientOnlyMixin", "client" + ); + + private String rootProjectName; + + private final Map> mixinConfigList = new HashMap<>(); + + @Override + public void init(ProcessingEnvironment processingEnv) { + super.init(processingEnv); + rootProjectName = processingEnv.getOptions().get("rootProject.name"); + } + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + if(roundEnv.processingOver()){ + // set difference of mixins and client + List commonSet = mixinConfigList.get("mixins"); + commonSet.removeAll(mixinConfigList.get("client")); + // create record for serialization, compute package name + String packageName = commonSet.get(0).split("(?<=mixin)")[0]; + finalizeMixinConfig(); + generateMixinConfig( + new MixinConfig(packageName, + mixinConfigList.get("mixins"), + mixinConfigList.get("client") + ) + ); + } else { + processMixins(annotations, roundEnv); + } + return false; + } + + private void generateMixinConfig(Object config) { + try (Writer mixinConfigWriter = processingEnv.getFiler() + .createResource(StandardLocation.SOURCE_OUTPUT, "", computeMixinConfigPath()) + .openWriter()) { + String mixinConfig = new GsonBuilder() + .setPrettyPrinting() + .create() + .toJson(config); + + mixinConfigWriter.write(mixinConfig); + mixinConfigWriter.write("\n"); + } catch (IOException e) { + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Fatal error:" + + Throwables.getStackTraceAsString(e)); + } + } + + private String computeMixinConfigPath() { + var projectName = processingEnv.getOptions().get("project.name"); + return "resources/" + + rootProjectName + + (projectName != null ? "-" + projectName : "") + + ".mixins.json"; + } + + private void processMixins(Set annotations, RoundEnvironment roundEnv) { + for (TypeElement annotation : annotations) { + Set annotatedMixins = roundEnv.getElementsAnnotatedWith(annotation); + + List mixins = annotatedMixins.stream() + .filter(TypeElement.class::isInstance) + .map(TypeElement.class::cast) + .map(TypeElement::toString) + .collect(Collectors.toList()); + + mixinConfigList.putIfAbsent(aliases.get(annotation.getSimpleName().toString()), mixins); + } + } + + private void finalizeMixinConfig() { + // relativize class names + for(var list : mixinConfigList.values()) { + list.replaceAll(className -> className.split("(?<=mixin.)")[1]); + } + } +} \ No newline at end of file diff --git a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/config/MixinConfig.java b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/config/MixinConfig.java new file mode 100644 index 000000000..269c03ebc --- /dev/null +++ b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/config/MixinConfig.java @@ -0,0 +1,29 @@ +package org.fury_phoenix.mixinAp.config; + +import java.util.List; +import com.google.gson.annotations.SerializedName; + +public record MixinConfig( + boolean required, + String minVersion, + @SerializedName("package") + String packageName, + String plugin, + String compatabilityLevel, + @SerializedName("mixins") + List commonMixins, + @SerializedName("client") + List clientMixins, + InjectorOptions injectors, OverwriteOptions overwrites + ) { + public MixinConfig(String packageName, List commonMixins, List clientMixins) { + this(true, "0.8", packageName, "org.embeddedt.modernfix.core.ModernFixMixinPlugin", "JAVA_8", + commonMixins, clientMixins, InjectorOptions.DEFAULT, OverwriteOptions.DEFAULT); + } + public record InjectorOptions(int defaultRequire) { + public static final InjectorOptions DEFAULT = new InjectorOptions(1); + } + public record OverwriteOptions(boolean conformVisibility) { + public static final OverwriteOptions DEFAULT = new OverwriteOptions(true); + } +} \ No newline at end of file diff --git a/build.gradle b/build.gradle index f943a7a36..0390ec975 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { id 'org.ajoberstar.grgit' version '5.2.0' id 'se.bjurr.gitchangelog.git-changelog-gradle-plugin' version '1.79.0' id "com.modrinth.minotaur" version "2.+" apply false - id("com.diffplug.spotless") version "6.18.0" apply false + id("com.diffplug.spotless") version "6.18.0" apply false id 'modernfix.common-conventions' apply false } diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index 1957c3393..678405245 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -1,3 +1,3 @@ plugins { id 'groovy-gradle-plugin' -} \ No newline at end of file +} diff --git a/settings.gradle b/settings.gradle index c5b39d7cf..e17315075 100644 --- a/settings.gradle +++ b/settings.gradle @@ -7,6 +7,7 @@ pluginManagement { } } +include("annotation-processor") include("test_agent") include("common") From 08078c8a95b4f83537c4ce44f2c3ca248156fd40 Mon Sep 17 00:00:00 2001 From: Phoenix-Starlight Date: Wed, 22 Nov 2023 20:42:53 -0800 Subject: [PATCH 02/45] Integrate AP --- .../modernfix.mod-common-conventions.gradle | 38 ++++++------------- .../resources/modernfix-common.mixins.json | 16 -------- .../resources/modernfix-fabric.mixins.json | 16 -------- .../resources/modernfix-forge.mixins.json | 16 -------- 4 files changed, 11 insertions(+), 75 deletions(-) delete mode 100644 common/src/main/resources/modernfix-common.mixins.json delete mode 100644 fabric/src/main/resources/modernfix-fabric.mixins.json delete mode 100644 forge/src/main/resources/modernfix-forge.mixins.json diff --git a/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle b/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle index 3362ce37e..662b54152 100644 --- a/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle +++ b/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle @@ -16,37 +16,21 @@ dependencies { parchment("org.parchmentmc.data:parchment-${minecraft_version}:${parchment_version}@zip") } } + annotationProcessor project(":annotation-processor") } +project.sourceSets { + main.resources.srcDirs += [layout.buildDirectory.dir("generated/sources/annotationProcessor/java/main/resources")] +} +// hack to shut up gradle about the hack to include generated resources tasks { processResources { - def mixinFileList = [] - def mixinDirectory = file("src/main/java/org/embeddedt/modernfix/" + project.name + "/mixin") - fileTree(mixinDirectory).visit { FileVisitDetails details -> - if(details.file.isFile()) { - def fileName = mixinDirectory.relativePath(details.file).toString().replaceFirst(/\.java$/, "").replace('/', '.') - mixinFileList << fileName - } - } - - def mixinClassesStringB = new StringBuilder() - for(int i = 0; i < mixinFileList.size(); i++) { - mixinClassesStringB.append(" \"") - mixinClassesStringB.append(mixinFileList.get(i)) - mixinClassesStringB.append('"') - if(i < (mixinFileList.size() - 1)) - mixinClassesStringB.append(',') - mixinClassesStringB.append('\n') - } - - def replacements = [ - mixin_classes: mixinClassesStringB.toString() - ] + dependsOn compileJava + } +} - inputs.properties replacements - def filePattern = "modernfix-" + project.name + ".mixins.json" - filesMatching(filePattern) { - expand replacements - } +tasks.withType(JavaCompile) { + configure(options) { + options.compilerArgs << "-ArootProject.name=${rootProject.name}" << "-Aproject.name=${project.name}" } } \ No newline at end of file diff --git a/common/src/main/resources/modernfix-common.mixins.json b/common/src/main/resources/modernfix-common.mixins.json deleted file mode 100644 index 94a4e091e..000000000 --- a/common/src/main/resources/modernfix-common.mixins.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "required": true, - "minVersion": "0.8", - "package": "org.embeddedt.modernfix.common.mixin", - "plugin": "org.embeddedt.modernfix.core.ModernFixMixinPlugin", - "compatibilityLevel": "JAVA_8", - "mixins": [ -${mixin_classes} - ], - "injectors": { - "defaultRequire": 1 - }, - "overwrites": { - "conformVisibility": true - } -} diff --git a/fabric/src/main/resources/modernfix-fabric.mixins.json b/fabric/src/main/resources/modernfix-fabric.mixins.json deleted file mode 100644 index 3d94ea0d8..000000000 --- a/fabric/src/main/resources/modernfix-fabric.mixins.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "required": true, - "package": "org.embeddedt.modernfix.fabric.mixin", - "plugin": "org.embeddedt.modernfix.core.ModernFixMixinPlugin", - "compatibilityLevel": "JAVA_8", - "minVersion": "0.8", - "mixins": [ -${mixin_classes} - ], - "injectors": { - "defaultRequire": 1 - }, - "overwrites": { - "conformVisibility": true - } -} \ No newline at end of file diff --git a/forge/src/main/resources/modernfix-forge.mixins.json b/forge/src/main/resources/modernfix-forge.mixins.json deleted file mode 100644 index f63f1dfc3..000000000 --- a/forge/src/main/resources/modernfix-forge.mixins.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "required": true, - "package": "org.embeddedt.modernfix.forge.mixin", - "plugin": "org.embeddedt.modernfix.core.ModernFixMixinPlugin", - "compatibilityLevel": "JAVA_8", - "minVersion": "0.8", - "mixins": [ -${mixin_classes} - ], - "injectors": { - "defaultRequire": 1 - }, - "overwrites": { - "conformVisibility": true - } -} \ No newline at end of file From 73fdafdfd4c19946236707cdd88dd7a599e5469d Mon Sep 17 00:00:00 2001 From: Phoenix-Starlight Date: Wed, 22 Nov 2023 21:34:57 -0800 Subject: [PATCH 03/45] Spotless --- .../fury_phoenix/mixinAp/annotation/MixinProcessor.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java index c8e4dd9a0..dfeecbe1c 100644 --- a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java +++ b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java @@ -2,20 +2,16 @@ import com.google.auto.service.AutoService; import com.google.common.base.Throwables; -import com.google.common.collect.ListMultimap; -import com.google.common.collect.ArrayListMultimap; import com.google.gson.GsonBuilder; import java.io.IOException; import java.io.Writer; -import java.lang.annotation.ElementType; import java.util.List; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; -import java.util.stream.Stream; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.Processor; @@ -26,15 +22,12 @@ import javax.annotation.processing.SupportedSourceVersion; import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; import javax.lang.model.element.TypeElement; import javax.tools.Diagnostic; import javax.tools.StandardLocation; import org.fury_phoenix.mixinAp.config.MixinConfig; -import static java.util.function.Predicate.not; - @SupportedAnnotationTypes({"org.spongepowered.asm.mixin.Mixin", "org.embeddedt.modernfix.annotation.ClientOnlyMixin"}) @SupportedOptions({"rootProject.name", "project.name"}) @SupportedSourceVersion(SourceVersion.RELEASE_17) From 631913cbf9a5fbf3b7db1201f7c3d2d00996a07d Mon Sep 17 00:00:00 2001 From: Phoenix-Starlight Date: Sat, 25 Nov 2023 11:47:40 -0800 Subject: [PATCH 04/45] Cleanup --- .../mixinAp/annotation/MixinProcessor.java | 58 ++++++++++--------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java index dfeecbe1c..8baafe1ec 100644 --- a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java +++ b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java @@ -53,11 +53,9 @@ public void init(ProcessingEnvironment processingEnv) { @Override public boolean process(Set annotations, RoundEnvironment roundEnv) { if(roundEnv.processingOver()){ - // set difference of mixins and client - List commonSet = mixinConfigList.get("mixins"); - commonSet.removeAll(mixinConfigList.get("client")); + filterMixinSets(); // create record for serialization, compute package name - String packageName = commonSet.get(0).split("(?<=mixin)")[0]; + String packageName = mixinConfigList.get("mixins").get(0).split("(?<=mixin)")[0]; finalizeMixinConfig(); generateMixinConfig( new MixinConfig(packageName, @@ -71,6 +69,34 @@ public boolean process(Set annotations, RoundEnvironment return false; } + private void processMixins(Set annotations, RoundEnvironment roundEnv) { + for (TypeElement annotation : annotations) { + Set annotatedMixins = roundEnv.getElementsAnnotatedWith(annotation); + + List mixins = annotatedMixins.stream() + .filter(TypeElement.class::isInstance) + .map(TypeElement.class::cast) + .map(TypeElement::toString) + .collect(Collectors.toList()); + + mixinConfigList.putIfAbsent(aliases.get(annotation.getSimpleName().toString()), mixins); + } + } + + private void filterMixinSets() { + // set difference of mixins and client + List commonSet = mixinConfigList.get("mixins"); + commonSet.removeAll(mixinConfigList.get("client")); + } + + private String computeMixinConfigPath() { + var projectName = processingEnv.getOptions().get("project.name"); + return "resources/" + + rootProjectName + + (projectName != null ? "-" + projectName : "") + + ".mixins.json"; + } + private void generateMixinConfig(Object config) { try (Writer mixinConfigWriter = processingEnv.getFiler() .createResource(StandardLocation.SOURCE_OUTPUT, "", computeMixinConfigPath()) @@ -88,32 +114,10 @@ private void generateMixinConfig(Object config) { } } - private String computeMixinConfigPath() { - var projectName = processingEnv.getOptions().get("project.name"); - return "resources/" + - rootProjectName + - (projectName != null ? "-" + projectName : "") + - ".mixins.json"; - } - - private void processMixins(Set annotations, RoundEnvironment roundEnv) { - for (TypeElement annotation : annotations) { - Set annotatedMixins = roundEnv.getElementsAnnotatedWith(annotation); - - List mixins = annotatedMixins.stream() - .filter(TypeElement.class::isInstance) - .map(TypeElement.class::cast) - .map(TypeElement::toString) - .collect(Collectors.toList()); - - mixinConfigList.putIfAbsent(aliases.get(annotation.getSimpleName().toString()), mixins); - } - } - private void finalizeMixinConfig() { // relativize class names for(var list : mixinConfigList.values()) { list.replaceAll(className -> className.split("(?<=mixin.)")[1]); } } -} \ No newline at end of file +} From 4645c2622742d62ecf9fd08028897edb40512be3 Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Sun, 3 Dec 2023 11:11:10 -0800 Subject: [PATCH 05/45] Split annotations to separate project Use fabric mixin dependency Enable preview features for annotation processor only --- annotation-processor/build.gradle | 14 +++++++++++++- annotations/build.gradle | 6 ++++++ .../modernfix/annotation/ClientOnlyMixin.java | 0 .../modernfix/annotation/IgnoreOutsideDev.java | 0 .../modernfix/annotation/RequiresMod.java | 0 .../groovy/modernfix.mod-common-conventions.gradle | 5 ++++- gradle.properties | 2 +- settings.gradle | 1 + 8 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 annotations/build.gradle rename {common => annotations}/src/main/java/org/embeddedt/modernfix/annotation/ClientOnlyMixin.java (100%) rename {common => annotations}/src/main/java/org/embeddedt/modernfix/annotation/IgnoreOutsideDev.java (100%) rename {common => annotations}/src/main/java/org/embeddedt/modernfix/annotation/RequiresMod.java (100%) diff --git a/annotation-processor/build.gradle b/annotation-processor/build.gradle index 8d8df01d2..bcb4cfbc1 100644 --- a/annotation-processor/build.gradle +++ b/annotation-processor/build.gradle @@ -5,12 +5,24 @@ plugins { repositories { mavenCentral() + maven { + name "Fabric" + url uri("https://maven.fabricmc.net") + } } dependencies { implementation 'com.google.code.gson:gson:2.10.1' annotationProcessor 'com.google.auto.service:auto-service:1.1.1' compileOnly 'com.google.auto.service:auto-service:1.1.1' + + implementation "net.fabricmc:sponge-mixin:0.12.5+" + implementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" + implementation project(":annotations") +} + +tasks.withType(JavaCompile) { + options.compilerArgs += '--enable-preview' } spotless { @@ -18,4 +30,4 @@ spotless { removeUnusedImports() } } -version = '1.0' \ No newline at end of file +version = '1.1.0' diff --git a/annotations/build.gradle b/annotations/build.gradle new file mode 100644 index 000000000..55eb0c786 --- /dev/null +++ b/annotations/build.gradle @@ -0,0 +1,6 @@ +plugins { + id 'modernfix.common-conventions' + id 'java-library' +} + +version = '1.0.0' diff --git a/common/src/main/java/org/embeddedt/modernfix/annotation/ClientOnlyMixin.java b/annotations/src/main/java/org/embeddedt/modernfix/annotation/ClientOnlyMixin.java similarity index 100% rename from common/src/main/java/org/embeddedt/modernfix/annotation/ClientOnlyMixin.java rename to annotations/src/main/java/org/embeddedt/modernfix/annotation/ClientOnlyMixin.java diff --git a/common/src/main/java/org/embeddedt/modernfix/annotation/IgnoreOutsideDev.java b/annotations/src/main/java/org/embeddedt/modernfix/annotation/IgnoreOutsideDev.java similarity index 100% rename from common/src/main/java/org/embeddedt/modernfix/annotation/IgnoreOutsideDev.java rename to annotations/src/main/java/org/embeddedt/modernfix/annotation/IgnoreOutsideDev.java diff --git a/common/src/main/java/org/embeddedt/modernfix/annotation/RequiresMod.java b/annotations/src/main/java/org/embeddedt/modernfix/annotation/RequiresMod.java similarity index 100% rename from common/src/main/java/org/embeddedt/modernfix/annotation/RequiresMod.java rename to annotations/src/main/java/org/embeddedt/modernfix/annotation/RequiresMod.java diff --git a/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle b/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle index 662b54152..7c398a1f0 100644 --- a/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle +++ b/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle @@ -16,6 +16,7 @@ dependencies { parchment("org.parchmentmc.data:parchment-${minecraft_version}:${parchment_version}@zip") } } + implementation project(":annotations") annotationProcessor project(":annotation-processor") } @@ -30,7 +31,9 @@ tasks { } tasks.withType(JavaCompile) { + options.fork = true + options.forkOptions.jvmArgs << '--enable-preview' configure(options) { options.compilerArgs << "-ArootProject.name=${rootProject.name}" << "-Aproject.name=${project.name}" } -} \ No newline at end of file +} diff --git a/gradle.properties b/gradle.properties index 1cb73b923..0777bd13d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -25,4 +25,4 @@ modmenu_version=1.16.23 spark_forge_version=3767277 spark_fabric_version=3337642 -use_fabric_api_at_runtime=true \ No newline at end of file +use_fabric_api_at_runtime=true diff --git a/settings.gradle b/settings.gradle index e17315075..762143525 100644 --- a/settings.gradle +++ b/settings.gradle @@ -8,6 +8,7 @@ pluginManagement { } include("annotation-processor") +include("annotations") include("test_agent") include("common") From 2660df6db3b77a0de3aab253b4c41c2bc55badb9 Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Sun, 3 Dec 2023 11:15:43 -0800 Subject: [PATCH 06/45] Emit compile-time errors for mislabeled mixins that targets client side classes --- .../annotation/ClientMixinValidator.java | 114 ++++++++++++++++++ .../mixinAp/annotation/MixinProcessor.java | 71 ++++------- .../mixinAp/config/MixinConfig.java | 44 ++++++- .../obfuscation/AnnotatedMixinsAccessor.java | 11 ++ 4 files changed, 192 insertions(+), 48 deletions(-) create mode 100644 annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java create mode 100644 annotation-processor/src/main/java/org/spongepowered/tools/obfuscation/AnnotatedMixinsAccessor.java diff --git a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java new file mode 100644 index 000000000..49699837d --- /dev/null +++ b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java @@ -0,0 +1,114 @@ +package org.fury_phoenix.mixinAp.annotation; + +import java.lang.annotation.Annotation; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.TypeMirror; + +import javax.tools.Diagnostic; + +import net.fabricmc.api.Environment; +import net.fabricmc.api.EnvType; + +import org.embeddedt.modernfix.annotation.ClientOnlyMixin; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.util.asm.IAnnotationHandle; +import org.spongepowered.tools.obfuscation.AnnotatedMixinsAccessor; +import org.spongepowered.tools.obfuscation.interfaces.ITypeHandleProvider; +import org.spongepowered.tools.obfuscation.mirror.TypeHandle; + +import static java.util.AbstractMap.SimpleImmutableEntry; + +public class ClientMixinValidator { + + private final ITypeHandleProvider typeHandleProvider; + + private final ProcessingEnvironment processingEnv; + + public ClientMixinValidator(ProcessingEnvironment env) { + typeHandleProvider = AnnotatedMixinsAccessor.getMixinAP(env); + processingEnv = env; + } + // some sort of javac bug with method reference resolution for mixed staticness + public boolean targetsClient(TypeElement annotatedMixinClass) { + return targetsClient( + ClientMixinValidator.getTargets( + getAnnotationHandle(annotatedMixinClass, Mixin.class) + )) && !getAnnotationHandle(annotatedMixinClass, ClientOnlyMixin.class).exists(); + } + + private boolean targetsClient(List classTargets) { + return classTargets.stream() + .anyMatch(this::targetsClient); + } + + private boolean targetsClient(Object classTarget) { + return switch (classTarget) { + case null -> throw new IllegalArgumentException("Can't be empty!"); + case TypeMirror tm -> + EnvType.CLIENT == getEnvType(tm); + // If you're using a dollar sign in class names you are insane + case String s && (getEnvType(s) != null) -> + EnvType.CLIENT == getEnvType(s); + case String s -> warn(s); + default -> + throw new IllegalArgumentException("Unhandled type: " + classTarget.getClass() + "\n" + + "Stringified contents: " + classTarget.toString()); + }; + } + + private EnvType getEnvType(Object o) { + TypeHandle handle = getTypeHandle(o); + if(handle.isImaginary()) + return null; + Environment env = handle.getElement().getAnnotation(Environment.class); + if(env == null) + return null; + return env.value(); + } + + private boolean warn(String s) { + processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, s + "can't be loaded, so it is skipped!"); + return false; + } + + public SimpleImmutableEntry + getEntry(TypeElement annotatedMixinClass) { + return new SimpleImmutableEntry<>( + annotatedMixinClass.getQualifiedName(), + ClientMixinValidator.getTargets( + getAnnotationHandle(annotatedMixinClass, Mixin.class) + ).stream().filter(this::targetsClient) + .map(Object::toString) + .map(ClientMixinValidator::toSourceString) + .collect(Collectors.joining(", ")) + ); + } + + private TypeHandle getTypeHandle(Object annotatedClass) { + return typeHandleProvider.getTypeHandle(annotatedClass); + } + + private IAnnotationHandle getAnnotationHandle(Object annotatedClass, Class annotation) { + return getTypeHandle(annotatedClass).getAnnotation(annotation); + } + + public static String toSourceString(String bytecodeName) { + return bytecodeName.replaceAll("\\/", "."); + } + + private static List getTargets(IAnnotationHandle mixinAnnotation) { + Collection clzss = mixinAnnotation.getList("value"); + Collection imaginary = mixinAnnotation.getList("targets"); + List targets = + Stream.of(clzss, imaginary) + .flatMap(Collection::stream) + .collect(Collectors.toList()); + return targets; + } +} diff --git a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java index 8baafe1ec..4cecea9b3 100644 --- a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java +++ b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java @@ -1,21 +1,16 @@ package org.fury_phoenix.mixinAp.annotation; import com.google.auto.service.AutoService; -import com.google.common.base.Throwables; -import com.google.gson.GsonBuilder; - -import java.io.IOException; -import java.io.Writer; import java.util.List; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.Processor; -import javax.annotation.processing.ProcessingEnvironment; import javax.annotation.processing.RoundEnvironment; import javax.annotation.processing.SupportedAnnotationTypes; import javax.annotation.processing.SupportedOptions; @@ -24,7 +19,6 @@ import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; import javax.tools.Diagnostic; -import javax.tools.StandardLocation; import org.fury_phoenix.mixinAp.config.MixinConfig; @@ -40,16 +34,8 @@ public class MixinProcessor extends AbstractProcessor { "ClientOnlyMixin", "client" ); - private String rootProjectName; - private final Map> mixinConfigList = new HashMap<>(); - @Override - public void init(ProcessingEnvironment processingEnv) { - super.init(processingEnv); - rootProjectName = processingEnv.getOptions().get("rootProject.name"); - } - @Override public boolean process(Set annotations, RoundEnvironment roundEnv) { if(roundEnv.processingOver()){ @@ -57,12 +43,10 @@ public boolean process(Set annotations, RoundEnvironment // create record for serialization, compute package name String packageName = mixinConfigList.get("mixins").get(0).split("(?<=mixin)")[0]; finalizeMixinConfig(); - generateMixinConfig( - new MixinConfig(packageName, - mixinConfigList.get("mixins"), - mixinConfigList.get("client") - ) - ); + new MixinConfig(packageName, + mixinConfigList.get("mixins"), + mixinConfigList.get("client") + ).generateMixinConfig(processingEnv); } else { processMixins(annotations, roundEnv); } @@ -73,8 +57,14 @@ private void processMixins(Set annotations, RoundEnvironm for (TypeElement annotation : annotations) { Set annotatedMixins = roundEnv.getElementsAnnotatedWith(annotation); - List mixins = annotatedMixins.stream() - .filter(TypeElement.class::isInstance) + Stream mixinStream = + annotatedMixins.stream() + .map(TypeElement.class::cast); + + validateCommonMixins(annotation, mixinStream); + + List mixins = + annotatedMixins.stream() .map(TypeElement.class::cast) .map(TypeElement::toString) .collect(Collectors.toList()); @@ -84,36 +74,25 @@ private void processMixins(Set annotations, RoundEnvironm } private void filterMixinSets() { - // set difference of mixins and client List commonSet = mixinConfigList.get("mixins"); commonSet.removeAll(mixinConfigList.get("client")); } - private String computeMixinConfigPath() { - var projectName = processingEnv.getOptions().get("project.name"); - return "resources/" + - rootProjectName + - (projectName != null ? "-" + projectName : "") + - ".mixins.json"; + private void validateCommonMixins(TypeElement annotation, Stream mixins) { + if(!annotation.getSimpleName().toString().equals("Mixin")) + return; + ClientMixinValidator validator = new ClientMixinValidator(processingEnv); + mixins.parallel() + .filter(validator::targetsClient) + .map(validator::getEntry) + .forEach(this::logClientClassTarget); } - private void generateMixinConfig(Object config) { - try (Writer mixinConfigWriter = processingEnv.getFiler() - .createResource(StandardLocation.SOURCE_OUTPUT, "", computeMixinConfigPath()) - .openWriter()) { - String mixinConfig = new GsonBuilder() - .setPrettyPrinting() - .create() - .toJson(config); - - mixinConfigWriter.write(mixinConfig); - mixinConfigWriter.write("\n"); - } catch (IOException e) { - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Fatal error:" + - Throwables.getStackTraceAsString(e)); - } + private void logClientClassTarget(Map.Entry mixin) { + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, + "Mixin " + mixin.getKey() + " targets client-side classes: " + mixin.getValue()); } - + private void finalizeMixinConfig() { // relativize class names for(var list : mixinConfigList.values()) { diff --git a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/config/MixinConfig.java b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/config/MixinConfig.java index 269c03ebc..62e46828e 100644 --- a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/config/MixinConfig.java +++ b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/config/MixinConfig.java @@ -1,8 +1,18 @@ package org.fury_phoenix.mixinAp.config; -import java.util.List; +import com.google.common.base.Throwables; +import com.google.gson.GsonBuilder; import com.google.gson.annotations.SerializedName; +import java.io.IOException; +import java.io.Writer; +import java.util.List; +import java.util.Optional; + +import javax.annotation.processing.ProcessingEnvironment; +import javax.tools.Diagnostic; +import javax.tools.StandardLocation; + public record MixinConfig( boolean required, String minVersion, @@ -26,4 +36,34 @@ public record InjectorOptions(int defaultRequire) { public record OverwriteOptions(boolean conformVisibility) { public static final OverwriteOptions DEFAULT = new OverwriteOptions(true); } -} \ No newline at end of file + + public void generateMixinConfig(ProcessingEnvironment env) { + try ( + Writer mixinConfigWriter = env.getFiler() + .createResource(StandardLocation.SOURCE_OUTPUT, "", + MixinConfig.computeMixinConfigPath( + env.getOptions().get("rootProject.name"), + Optional.ofNullable(env.getOptions().get("project.name")) + ) + ).openWriter() + ) { + String mixinConfig = new GsonBuilder() + .setPrettyPrinting() + .create() + .toJson(this); + + mixinConfigWriter.write(mixinConfig); + mixinConfigWriter.write("\n"); + } catch (IOException e) { + env.getMessager().printMessage(Diagnostic.Kind.ERROR, "Fatal error:" + + Throwables.getStackTraceAsString(e)); + } + } + + private static String computeMixinConfigPath(String rootProjectName, Optional projectName) { + return "resources/" + + rootProjectName + + projectName.orElse("") + + ".mixins.json"; + } +} diff --git a/annotation-processor/src/main/java/org/spongepowered/tools/obfuscation/AnnotatedMixinsAccessor.java b/annotation-processor/src/main/java/org/spongepowered/tools/obfuscation/AnnotatedMixinsAccessor.java new file mode 100644 index 000000000..cea621fc8 --- /dev/null +++ b/annotation-processor/src/main/java/org/spongepowered/tools/obfuscation/AnnotatedMixinsAccessor.java @@ -0,0 +1,11 @@ +package org.spongepowered.tools.obfuscation; + +import javax.annotation.processing.ProcessingEnvironment; + +import org.spongepowered.tools.obfuscation.interfaces.ITypeHandleProvider; + +public class AnnotatedMixinsAccessor { + public static ITypeHandleProvider getMixinAP(ProcessingEnvironment processingEnv) { + return AnnotatedMixins.getMixinsForEnvironment(processingEnv); + } +} From ecfc4ebc39878e07a30fdbbab59ce55d9d8cd828 Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Sun, 3 Dec 2023 15:50:17 -0800 Subject: [PATCH 07/45] Fix NPEs Apparently class retained annotations are not available in AnnotatedConstruct#getAnnotation --- .../annotation/ClientMixinValidator.java | 34 ++++++++++++------- .../mixinAp/annotation/MixinProcessor.java | 2 +- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java index 49699837d..b1d6b331c 100644 --- a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java +++ b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java @@ -6,10 +6,10 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import javax.annotation.processing.Messager; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; - import javax.tools.Diagnostic; import net.fabricmc.api.Environment; @@ -30,16 +30,25 @@ public class ClientMixinValidator { private final ProcessingEnvironment processingEnv; + private final Messager messager; + public ClientMixinValidator(ProcessingEnvironment env) { typeHandleProvider = AnnotatedMixinsAccessor.getMixinAP(env); processingEnv = env; + messager = env.getMessager(); + } + + public boolean validateMixin(TypeElement annotatedMixinClass) { + return targetsClient(annotatedMixinClass) && + !getAnnotationHandle(annotatedMixinClass, ClientOnlyMixin.class).exists(); } + // some sort of javac bug with method reference resolution for mixed staticness public boolean targetsClient(TypeElement annotatedMixinClass) { return targetsClient( ClientMixinValidator.getTargets( getAnnotationHandle(annotatedMixinClass, Mixin.class) - )) && !getAnnotationHandle(annotatedMixinClass, ClientOnlyMixin.class).exists(); + )); } private boolean targetsClient(List classTargets) { @@ -49,13 +58,11 @@ private boolean targetsClient(List classTargets) { private boolean targetsClient(Object classTarget) { return switch (classTarget) { - case null -> throw new IllegalArgumentException("Can't be empty!"); case TypeMirror tm -> EnvType.CLIENT == getEnvType(tm); // If you're using a dollar sign in class names you are insane - case String s && (getEnvType(s) != null) -> - EnvType.CLIENT == getEnvType(s); - case String s -> warn(s); + case String s -> + EnvType.CLIENT == getEnvType(s.split("\\$")[0]); default -> throw new IllegalArgumentException("Unhandled type: " + classTarget.getClass() + "\n" + "Stringified contents: " + classTarget.toString()); @@ -64,16 +71,17 @@ private boolean targetsClient(Object classTarget) { private EnvType getEnvType(Object o) { TypeHandle handle = getTypeHandle(o); - if(handle.isImaginary()) - return null; - Environment env = handle.getElement().getAnnotation(Environment.class); - if(env == null) + if(handle == null) { + processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, o + " can't be found, skipping!"); return null; - return env.value(); + } + String[] stringEnum = handle.getAnnotation(Environment.class).getValue("value"); + if(stringEnum == null) return null; + return Enum.valueOf(EnvType.class, stringEnum[1]); } - private boolean warn(String s) { - processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, s + "can't be loaded, so it is skipped!"); + private boolean warn(Object o) { + messager.printMessage(Diagnostic.Kind.WARNING, o + " can't be loaded, so it is skipped!"); return false; } diff --git a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java index 4cecea9b3..4d4b728d7 100644 --- a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java +++ b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java @@ -83,7 +83,7 @@ private void validateCommonMixins(TypeElement annotation, Stream mi return; ClientMixinValidator validator = new ClientMixinValidator(processingEnv); mixins.parallel() - .filter(validator::targetsClient) + .filter(validator::validateMixin) .map(validator::getEntry) .forEach(this::logClientClassTarget); } From cff63f8223b937a4705720034f8346ecb343f84a Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Sun, 3 Dec 2023 15:58:58 -0800 Subject: [PATCH 08/45] Cleanup --- .../mixinAp/annotation/ClientMixinValidator.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java index b1d6b331c..1bac50da7 100644 --- a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java +++ b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java @@ -27,9 +27,9 @@ public class ClientMixinValidator { private final ITypeHandleProvider typeHandleProvider; - + private final ProcessingEnvironment processingEnv; - + private final Messager messager; public ClientMixinValidator(ProcessingEnvironment env) { @@ -37,13 +37,12 @@ public ClientMixinValidator(ProcessingEnvironment env) { processingEnv = env; messager = env.getMessager(); } - + public boolean validateMixin(TypeElement annotatedMixinClass) { return targetsClient(annotatedMixinClass) && !getAnnotationHandle(annotatedMixinClass, ClientOnlyMixin.class).exists(); } - - // some sort of javac bug with method reference resolution for mixed staticness + public boolean targetsClient(TypeElement annotatedMixinClass) { return targetsClient( ClientMixinValidator.getTargets( From fe7532a1ff694259790447cf4973456b7998c872 Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Tue, 5 Dec 2023 07:50:52 -0800 Subject: [PATCH 09/45] Fix compile-time errors --- .../mixin/perf/dynamic_resources/ItemModelShaperMixin.java | 2 ++ .../mixin/perf/faster_item_rendering/GameRendererMixin.java | 2 ++ .../mixin/perf/faster_item_rendering/ItemRendererMixin.java | 2 ++ 3 files changed, 6 insertions(+) diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ItemModelShaperMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ItemModelShaperMixin.java index 9e31ecd75..dfe8c84d3 100644 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ItemModelShaperMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ItemModelShaperMixin.java @@ -6,6 +6,7 @@ import net.minecraft.client.resources.model.ModelManager; import net.minecraft.client.resources.model.ModelResourceLocation; import net.minecraft.world.item.Item; +import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.embeddedt.modernfix.dynamicresources.DynamicModelCache; import org.embeddedt.modernfix.dynamicresources.ModelLocationCache; import org.embeddedt.modernfix.util.DynamicInt2ObjectMap; @@ -18,6 +19,7 @@ import java.util.Map; @Mixin(ItemModelShaper.class) +@ClientOnlyMixin public abstract class ItemModelShaperMixin { @Shadow public abstract ModelManager getModelManager(); diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_item_rendering/GameRendererMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_item_rendering/GameRendererMixin.java index ee3a0f9d9..d457b5d40 100644 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_item_rendering/GameRendererMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_item_rendering/GameRendererMixin.java @@ -1,6 +1,7 @@ package org.embeddedt.modernfix.common.mixin.perf.faster_item_rendering; import net.minecraft.client.renderer.GameRenderer; +import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.embeddedt.modernfix.render.RenderState; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -8,6 +9,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(GameRenderer.class) +@ClientOnlyMixin public class GameRendererMixin { @Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GameRenderer;renderLevel(FJLcom/mojang/blaze3d/vertex/PoseStack;)V", shift = At.Shift.BEFORE)) private void markRenderingLevel(CallbackInfo ci) { diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_item_rendering/ItemRendererMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_item_rendering/ItemRendererMixin.java index 7e2ddd69b..972014579 100644 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_item_rendering/ItemRendererMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_item_rendering/ItemRendererMixin.java @@ -11,6 +11,7 @@ import net.minecraft.client.resources.model.SimpleBakedModel; import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.ItemStack; +import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.embeddedt.modernfix.render.FastItemRenderType; import org.embeddedt.modernfix.render.RenderState; import org.embeddedt.modernfix.render.SimpleItemModelView; @@ -21,6 +22,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(value = ItemRenderer.class, priority = 600) +@ClientOnlyMixin public abstract class ItemRendererMixin { private ItemTransforms.TransformType transformType; private final SimpleItemModelView modelView = new SimpleItemModelView(); From 1d88e1b1e6577b70f819588778fc36e0ac06919d Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Tue, 5 Dec 2023 09:43:27 -0800 Subject: [PATCH 10/45] Fix file naming --- .../main/java/org/fury_phoenix/mixinAp/config/MixinConfig.java | 1 + 1 file changed, 1 insertion(+) diff --git a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/config/MixinConfig.java b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/config/MixinConfig.java index 62e46828e..e8b59df05 100644 --- a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/config/MixinConfig.java +++ b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/config/MixinConfig.java @@ -63,6 +63,7 @@ public void generateMixinConfig(ProcessingEnvironment env) { private static String computeMixinConfigPath(String rootProjectName, Optional projectName) { return "resources/" + rootProjectName + + (projectName.isPresent() ? "-" : "") + projectName.orElse("") + ".mixins.json"; } From 587fb08ce2e727cffbba3c1edc89c2fbf40d7418 Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Tue, 5 Dec 2023 09:43:54 -0800 Subject: [PATCH 11/45] Exclude tests --- .../src/main/groovy/modernfix.mod-common-conventions.gradle | 2 ++ 1 file changed, 2 insertions(+) diff --git a/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle b/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle index 7c398a1f0..09ec817d8 100644 --- a/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle +++ b/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle @@ -34,6 +34,8 @@ tasks.withType(JavaCompile) { options.fork = true options.forkOptions.jvmArgs << '--enable-preview' configure(options) { + if (!name.toLowerCase().contains('test')) { options.compilerArgs << "-ArootProject.name=${rootProject.name}" << "-Aproject.name=${project.name}" + } } } From 06a02dc445fd6ad065e1f8e3d6cd68f8599ed2fc Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Thu, 7 Dec 2023 21:47:10 -0800 Subject: [PATCH 12/45] Add platform support and rework detection logic --- .../annotation/ClientMixinValidator.java | 53 ++++++++++++++----- 1 file changed, 40 insertions(+), 13 deletions(-) diff --git a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java index 1bac50da7..c2f77ee70 100644 --- a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java +++ b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java @@ -3,18 +3,18 @@ import java.lang.annotation.Annotation; import java.util.Collection; import java.util.List; +import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; import javax.annotation.processing.Messager; import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.AnnotatedConstruct; import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.Elements; import javax.tools.Diagnostic; -import net.fabricmc.api.Environment; -import net.fabricmc.api.EnvType; - import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.util.asm.IAnnotationHandle; @@ -31,11 +31,21 @@ public class ClientMixinValidator { private final ProcessingEnvironment processingEnv; private final Messager messager; - + + private final Elements elemUtils; + + private final Class markerClass = getMarkerClass(); + + private static final Set markers = Set.of( + "net.fabricmc.api.Environment", + "net.minecraftforge.api.distmarker.OnlyIn", + "net.neoforged.api.distmarker.OnlyIn"); + public ClientMixinValidator(ProcessingEnvironment env) { typeHandleProvider = AnnotatedMixinsAccessor.getMixinAP(env); processingEnv = env; messager = env.getMessager(); + elemUtils = env.getElementUtils(); } public boolean validateMixin(TypeElement annotatedMixinClass) { @@ -58,25 +68,42 @@ private boolean targetsClient(List classTargets) { private boolean targetsClient(Object classTarget) { return switch (classTarget) { case TypeMirror tm -> - EnvType.CLIENT == getEnvType(tm); + isClientMarked(tm); // If you're using a dollar sign in class names you are insane case String s -> - EnvType.CLIENT == getEnvType(s.split("\\$")[0]); + targetsClient(elemUtils.getTypeElement(toSourceString(s.split("\\$")[0])).asType()); default -> throw new IllegalArgumentException("Unhandled type: " + classTarget.getClass() + "\n" + "Stringified contents: " + classTarget.toString()); }; } - private EnvType getEnvType(Object o) { - TypeHandle handle = getTypeHandle(o); + private boolean isClientMarked(AnnotatedConstruct ac) { + TypeHandle handle = getTypeHandle(ac); if(handle == null) { - processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, o + " can't be found, skipping!"); - return null; + messager.printMessage(Diagnostic.Kind.WARNING, "Class can't be loaded! " + ac); + return false; + } + IAnnotationHandle marker = handle.getAnnotation(markerClass); + + if(marker == null) return false; + + String[] markerEnum = marker.getValue("value"); + + if(markerEnum == null) return false; + + String markerEnumValue = markerEnum[1]; + return markerEnumValue.toString().equals("CLIENT"); + } + + @SuppressWarnings("unchecked") + private static Class getMarkerClass() { + for(var annotation : markers) { + try { + return (Class)Class.forName(annotation); + } catch (ClassNotFoundException e) {} } - String[] stringEnum = handle.getAnnotation(Environment.class).getValue("value"); - if(stringEnum == null) return null; - return Enum.valueOf(EnvType.class, stringEnum[1]); + return null; } private boolean warn(Object o) { From 077f726baef67ed5472ae3c3deab87df22323332 Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Sat, 9 Dec 2023 19:03:45 -0800 Subject: [PATCH 13/45] Fix platform support - Prefer TypeElements over TypeMirrors - Add debug option to log classes that couldn't be loaded - Reorganize exception logging --- annotation-processor/build.gradle | 3 +- .../annotation/ClientMixinValidator.java | 119 +++++++++++++----- .../mixinAp/annotation/MixinProcessor.java | 36 +++--- .../mixinAp/config/MixinConfig.java | 15 +-- 4 files changed, 113 insertions(+), 60 deletions(-) diff --git a/annotation-processor/build.gradle b/annotation-processor/build.gradle index bcb4cfbc1..1ae88ed82 100644 --- a/annotation-processor/build.gradle +++ b/annotation-processor/build.gradle @@ -17,7 +17,6 @@ dependencies { compileOnly 'com.google.auto.service:auto-service:1.1.1' implementation "net.fabricmc:sponge-mixin:0.12.5+" - implementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" implementation project(":annotations") } @@ -30,4 +29,4 @@ spotless { removeUnusedImports() } } -version = '1.1.0' +version = '1.1.1' diff --git a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java index c2f77ee70..b36b9f2a5 100644 --- a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java +++ b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java @@ -1,7 +1,11 @@ package org.fury_phoenix.mixinAp.annotation; +import com.google.common.base.Throwables; + import java.lang.annotation.Annotation; +import java.lang.invoke.*; import java.util.Collection; +import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.stream.Collectors; @@ -9,10 +13,10 @@ import javax.annotation.processing.Messager; import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.AnnotatedConstruct; import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; import javax.lang.model.util.Elements; +import javax.lang.model.util.Types; import javax.tools.Diagnostic; import org.embeddedt.modernfix.annotation.ClientOnlyMixin; @@ -28,24 +32,50 @@ public class ClientMixinValidator { private final ITypeHandleProvider typeHandleProvider; - private final ProcessingEnvironment processingEnv; - private final Messager messager; private final Elements elemUtils; - private final Class markerClass = getMarkerClass(); + private final Types types; + + private final boolean debug; + + private final Class markerClass = getMarkerClass(markers); - private static final Set markers = Set.of( + private final Class> markerEnumClass = getMarkerEnumClass(markerEnums); + + private static final Collection markers = Set.of( "net.fabricmc.api.Environment", "net.minecraftforge.api.distmarker.OnlyIn", "net.neoforged.api.distmarker.OnlyIn"); - public ClientMixinValidator(ProcessingEnvironment env) { + private static final Collection markerEnums = Set.of( + "net.fabricmc.api.EnvType", + "net.minecraftforge.api.distmarker.Dist", + "net.neoforged.api.distmarker.Dist"); + + private static final Collection unannotatedClasses = new HashSet<>(); + + private static final MethodHandles.Lookup lookup = MethodHandles.publicLookup(); + + private final MethodType enumValueAccessorType = MethodType.methodType(markerEnumClass); + + private final MethodHandle enumValueAccessor; + + public ClientMixinValidator(ProcessingEnvironment env) + throws ReflectiveOperationException { typeHandleProvider = AnnotatedMixinsAccessor.getMixinAP(env); - processingEnv = env; + debug = Boolean.valueOf(env.getOptions().get("org.fury_phoenix.mixinAp.validator.debug")); messager = env.getMessager(); elemUtils = env.getElementUtils(); + types = env.getTypeUtils(); + try { enumValueAccessor = getMethod(markerClass); } + catch (ReflectiveOperationException e) { throw e; } + } + + private MethodHandle getMethod(Class clz) + throws ReflectiveOperationException { + return lookup.findVirtual(clz, "value", enumValueAccessorType); } public boolean validateMixin(TypeElement annotatedMixinClass) { @@ -61,44 +91,52 @@ public boolean targetsClient(TypeElement annotatedMixinClass) { } private boolean targetsClient(List classTargets) { - return classTargets.stream() - .anyMatch(this::targetsClient); + return classTargets.stream().anyMatch(this::targetsClient); } private boolean targetsClient(Object classTarget) { return switch (classTarget) { - case TypeMirror tm -> - isClientMarked(tm); + case TypeElement te -> + isClientMarked(te); + case TypeMirror tm -> { + var el = types.asElement(tm); + yield el != null ? targetsClient(el) : warn("TypeMirror of " + tm); + } // If you're using a dollar sign in class names you are insane - case String s -> - targetsClient(elemUtils.getTypeElement(toSourceString(s.split("\\$")[0])).asType()); + case String s -> { + var te = + elemUtils.getTypeElement(toSourceString(s.split("\\$")[0])); + yield te != null ? targetsClient(te) : warn(s); + } default -> - throw new IllegalArgumentException("Unhandled type: " + classTarget.getClass() + "\n" - + "Stringified contents: " + classTarget.toString()); + throw new IllegalArgumentException("Unhandled type: " + + classTarget.getClass() + "\n" + "Stringified contents: " + + classTarget.toString()); }; } - private boolean isClientMarked(AnnotatedConstruct ac) { - TypeHandle handle = getTypeHandle(ac); - if(handle == null) { - messager.printMessage(Diagnostic.Kind.WARNING, "Class can't be loaded! " + ac); + private boolean isClientMarked(TypeElement te) { + Annotation marker = te.getAnnotation(markerClass); + if(marker == null) { + if(debug && unannotatedClasses.add(te.toString())) { + messager.printMessage(Diagnostic.Kind.WARNING, + "Missing " + markerClass.getCanonicalName() + " on " + te + "!"); + } return false; } - IAnnotationHandle marker = handle.getAnnotation(markerClass); - - if(marker == null) return false; - - String[] markerEnum = marker.getValue("value"); - - if(markerEnum == null) return false; - - String markerEnumValue = markerEnum[1]; - return markerEnumValue.toString().equals("CLIENT"); + try { + Object value = enumValueAccessor.invoke(marker); + return value.toString().equals("CLIENT"); + } catch (Throwable e) { + messager.printMessage(Diagnostic.Kind.ERROR, "Fatal error:" + + Throwables.getStackTraceAsString(e)); + } + return false; } @SuppressWarnings("unchecked") - private static Class getMarkerClass() { - for(var annotation : markers) { + private static Class getMarkerClass(Collection markerSet) { + for(var annotation : markerSet) { try { return (Class)Class.forName(annotation); } catch (ClassNotFoundException e) {} @@ -106,8 +144,19 @@ private static Class getMarkerClass() { return null; } + @SuppressWarnings("unchecked") + private static Class> getMarkerEnumClass(Collection enumSet) { + for(var enumClass : enumSet) { + try { + return (Class>)Class.forName(enumClass); + } catch (ClassNotFoundException e) {} + } + return null; + } + private boolean warn(Object o) { - messager.printMessage(Diagnostic.Kind.WARNING, o + " can't be loaded, so it is skipped!"); + messager.printMessage(Diagnostic.Kind.WARNING, + toSourceString(o.toString()) + " can't be loaded, so it is skipped!"); return false; } @@ -117,7 +166,8 @@ private boolean warn(Object o) { annotatedMixinClass.getQualifiedName(), ClientMixinValidator.getTargets( getAnnotationHandle(annotatedMixinClass, Mixin.class) - ).stream().filter(this::targetsClient) + ).stream() + .filter(this::targetsClient) .map(Object::toString) .map(ClientMixinValidator::toSourceString) .collect(Collectors.joining(", ")) @@ -128,7 +178,8 @@ private TypeHandle getTypeHandle(Object annotatedClass) { return typeHandleProvider.getTypeHandle(annotatedClass); } - private IAnnotationHandle getAnnotationHandle(Object annotatedClass, Class annotation) { + private IAnnotationHandle + getAnnotationHandle(Object annotatedClass, Class annotation) { return getTypeHandle(annotatedClass).getAnnotation(annotation); } diff --git a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java index 4d4b728d7..9c584f502 100644 --- a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java +++ b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java @@ -1,6 +1,7 @@ package org.fury_phoenix.mixinAp.annotation; import com.google.auto.service.AutoService; +import com.google.common.base.Throwables; import java.util.List; import java.util.HashMap; @@ -23,7 +24,7 @@ import org.fury_phoenix.mixinAp.config.MixinConfig; @SupportedAnnotationTypes({"org.spongepowered.asm.mixin.Mixin", "org.embeddedt.modernfix.annotation.ClientOnlyMixin"}) -@SupportedOptions({"rootProject.name", "project.name"}) +@SupportedOptions({"rootProject.name", "project.name", "org.fury_phoenix.mixinAp.validator.debug"}) @SupportedSourceVersion(SourceVersion.RELEASE_17) @AutoService(Processor.class) public class MixinProcessor extends AbstractProcessor { @@ -38,22 +39,28 @@ public class MixinProcessor extends AbstractProcessor { @Override public boolean process(Set annotations, RoundEnvironment roundEnv) { - if(roundEnv.processingOver()){ - filterMixinSets(); - // create record for serialization, compute package name - String packageName = mixinConfigList.get("mixins").get(0).split("(?<=mixin)")[0]; - finalizeMixinConfig(); - new MixinConfig(packageName, - mixinConfigList.get("mixins"), - mixinConfigList.get("client") - ).generateMixinConfig(processingEnv); - } else { - processMixins(annotations, roundEnv); + try { + if(roundEnv.processingOver()){ + filterMixinSets(); + // create record for serialization, compute package name + String packageName = mixinConfigList.get("mixins").get(0).split("(?<=mixin)")[0]; + finalizeMixinConfig(); + new MixinConfig(packageName, + mixinConfigList.get("mixins"), + mixinConfigList.get("client") + ).generateMixinConfig(processingEnv); + } else { + processMixins(annotations, roundEnv); + } + } catch (Exception e) { + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Fatal error:" + + Throwables.getStackTraceAsString(e)); } return false; } - private void processMixins(Set annotations, RoundEnvironment roundEnv) { + private void processMixins(Set annotations, RoundEnvironment roundEnv) + throws ReflectiveOperationException { for (TypeElement annotation : annotations) { Set annotatedMixins = roundEnv.getElementsAnnotatedWith(annotation); @@ -78,7 +85,8 @@ private void filterMixinSets() { commonSet.removeAll(mixinConfigList.get("client")); } - private void validateCommonMixins(TypeElement annotation, Stream mixins) { + private void validateCommonMixins(TypeElement annotation, Stream mixins) + throws ReflectiveOperationException { if(!annotation.getSimpleName().toString().equals("Mixin")) return; ClientMixinValidator validator = new ClientMixinValidator(processingEnv); diff --git a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/config/MixinConfig.java b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/config/MixinConfig.java index e8b59df05..9d1e6c918 100644 --- a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/config/MixinConfig.java +++ b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/config/MixinConfig.java @@ -1,6 +1,5 @@ package org.fury_phoenix.mixinAp.config; -import com.google.common.base.Throwables; import com.google.gson.GsonBuilder; import com.google.gson.annotations.SerializedName; @@ -10,7 +9,6 @@ import java.util.Optional; import javax.annotation.processing.ProcessingEnvironment; -import javax.tools.Diagnostic; import javax.tools.StandardLocation; public record MixinConfig( @@ -37,12 +35,12 @@ public record OverwriteOptions(boolean conformVisibility) { public static final OverwriteOptions DEFAULT = new OverwriteOptions(true); } - public void generateMixinConfig(ProcessingEnvironment env) { + public void generateMixinConfig(ProcessingEnvironment env) throws IOException { try ( Writer mixinConfigWriter = env.getFiler() .createResource(StandardLocation.SOURCE_OUTPUT, "", MixinConfig.computeMixinConfigPath( - env.getOptions().get("rootProject.name"), + Optional.of(env.getOptions().get("rootProject.name")), Optional.ofNullable(env.getOptions().get("project.name")) ) ).openWriter() @@ -54,15 +52,12 @@ public void generateMixinConfig(ProcessingEnvironment env) { mixinConfigWriter.write(mixinConfig); mixinConfigWriter.write("\n"); - } catch (IOException e) { - env.getMessager().printMessage(Diagnostic.Kind.ERROR, "Fatal error:" + - Throwables.getStackTraceAsString(e)); - } + } catch (IOException e) { throw e; } } - private static String computeMixinConfigPath(String rootProjectName, Optional projectName) { + private static String computeMixinConfigPath(Optional rootProjectName, Optional projectName) { return "resources/" + - rootProjectName + + rootProjectName.get() + (projectName.isPresent() ? "-" : "") + projectName.orElse("") + ".mixins.json"; From 0396d431e0779f1aa64aba79b2fbf9463bcddf3c Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Sat, 9 Dec 2023 20:55:49 -0800 Subject: [PATCH 14/45] Fix platform detection again Halt AP on exception --- annotation-processor/build.gradle | 2 + .../annotation/ClientMixinValidator.java | 81 +++++++++---------- .../mixinAp/annotation/MixinProcessor.java | 2 + 3 files changed, 41 insertions(+), 44 deletions(-) diff --git a/annotation-processor/build.gradle b/annotation-processor/build.gradle index 1ae88ed82..6164c2293 100644 --- a/annotation-processor/build.gradle +++ b/annotation-processor/build.gradle @@ -17,6 +17,8 @@ dependencies { compileOnly 'com.google.auto.service:auto-service:1.1.1' implementation "net.fabricmc:sponge-mixin:0.12.5+" + // Out of necessity + implementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" implementation project(":annotations") } diff --git a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java index b36b9f2a5..8992dc755 100644 --- a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java +++ b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java @@ -40,10 +40,6 @@ public class ClientMixinValidator { private final boolean debug; - private final Class markerClass = getMarkerClass(markers); - - private final Class> markerEnumClass = getMarkerEnumClass(markerEnums); - private static final Collection markers = Set.of( "net.fabricmc.api.Environment", "net.minecraftforge.api.distmarker.OnlyIn", @@ -58,10 +54,6 @@ public class ClientMixinValidator { private static final MethodHandles.Lookup lookup = MethodHandles.publicLookup(); - private final MethodType enumValueAccessorType = MethodType.methodType(markerEnumClass); - - private final MethodHandle enumValueAccessor; - public ClientMixinValidator(ProcessingEnvironment env) throws ReflectiveOperationException { typeHandleProvider = AnnotatedMixinsAccessor.getMixinAP(env); @@ -69,13 +61,6 @@ public ClientMixinValidator(ProcessingEnvironment env) messager = env.getMessager(); elemUtils = env.getElementUtils(); types = env.getTypeUtils(); - try { enumValueAccessor = getMethod(markerClass); } - catch (ReflectiveOperationException e) { throw e; } - } - - private MethodHandle getMethod(Class clz) - throws ReflectiveOperationException { - return lookup.findVirtual(clz, "value", enumValueAccessorType); } public boolean validateMixin(TypeElement annotatedMixinClass) { @@ -116,16 +101,16 @@ private boolean targetsClient(Object classTarget) { } private boolean isClientMarked(TypeElement te) { - Annotation marker = te.getAnnotation(markerClass); + Annotation marker = te.getAnnotation(getMarkerClass(markers)); if(marker == null) { if(debug && unannotatedClasses.add(te.toString())) { messager.printMessage(Diagnostic.Kind.WARNING, - "Missing " + markerClass.getCanonicalName() + " on " + te + "!"); + "Missing " + getMarkerClass(markers).getCanonicalName() + " on " + te + "!"); } return false; } try { - Object value = enumValueAccessor.invoke(marker); + Object value = getAccessor().invoke(marker); return value.toString().equals("CLIENT"); } catch (Throwable e) { messager.printMessage(Diagnostic.Kind.ERROR, "Fatal error:" + @@ -134,32 +119,19 @@ private boolean isClientMarked(TypeElement te) { return false; } - @SuppressWarnings("unchecked") - private static Class getMarkerClass(Collection markerSet) { - for(var annotation : markerSet) { - try { - return (Class)Class.forName(annotation); - } catch (ClassNotFoundException e) {} - } - return null; - } - - @SuppressWarnings("unchecked") - private static Class> getMarkerEnumClass(Collection enumSet) { - for(var enumClass : enumSet) { - try { - return (Class>)Class.forName(enumClass); - } catch (ClassNotFoundException e) {} - } - return null; - } - private boolean warn(Object o) { messager.printMessage(Diagnostic.Kind.WARNING, toSourceString(o.toString()) + " can't be loaded, so it is skipped!"); return false; } + private MethodHandle getAccessor() throws ReflectiveOperationException { + Class markerClass = getMarkerClass(markers); + Class> markerEnumClass = getMarkerEnumClass(markerEnums); + MethodType enumValueAccessorType = MethodType.methodType(markerEnumClass); + return lookup.findVirtual(markerClass, "value", enumValueAccessorType); + } + public SimpleImmutableEntry getEntry(TypeElement annotatedMixinClass) { return new SimpleImmutableEntry<>( @@ -178,15 +150,11 @@ private TypeHandle getTypeHandle(Object annotatedClass) { return typeHandleProvider.getTypeHandle(annotatedClass); } - private IAnnotationHandle - getAnnotationHandle(Object annotatedClass, Class annotation) { + private IAnnotationHandle getAnnotationHandle + (Object annotatedClass, Class annotation) { return getTypeHandle(annotatedClass).getAnnotation(annotation); } - public static String toSourceString(String bytecodeName) { - return bytecodeName.replaceAll("\\/", "."); - } - private static List getTargets(IAnnotationHandle mixinAnnotation) { Collection clzss = mixinAnnotation.getList("value"); Collection imaginary = mixinAnnotation.getList("targets"); @@ -196,4 +164,29 @@ private static List getTargets(IAnnotationHandle mixinAnnotation) { .collect(Collectors.toList()); return targets; } + + @SuppressWarnings("unchecked") + private static Class getMarkerClass(Collection markerSet) { + for(var annotation : markerSet) { + try { + return (Class)Class.forName(annotation); + } catch (ClassNotFoundException e) {} + } + throw new RuntimeException(); + } + + @SuppressWarnings("unchecked") + private static Class> getMarkerEnumClass(Collection enumSet) { + for(var enumClass : enumSet) { + try { + return (Class>)Class.forName(enumClass); + } catch (ClassNotFoundException e) {} + } + throw new RuntimeException(); + } + + public static String toSourceString(String bytecodeName) { + return bytecodeName.replaceAll("\\/", "."); + } + } diff --git a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java index 9c584f502..bbce94900 100644 --- a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java +++ b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java @@ -55,6 +55,8 @@ public boolean process(Set annotations, RoundEnvironment } catch (Exception e) { processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Fatal error:" + Throwables.getStackTraceAsString(e)); + throw new RuntimeException(e); + // Halt the AP to prevent nonsense errors } return false; } From 35880b3f2913b95c70efbc8f0a0a4aedfa565ce1 Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Sat, 9 Dec 2023 20:59:50 -0800 Subject: [PATCH 15/45] Enable debug --- buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle b/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle index 09ec817d8..09d524f58 100644 --- a/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle +++ b/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle @@ -36,6 +36,7 @@ tasks.withType(JavaCompile) { configure(options) { if (!name.toLowerCase().contains('test')) { options.compilerArgs << "-ArootProject.name=${rootProject.name}" << "-Aproject.name=${project.name}" + << "-Aorg.fury_phoenix.mixinAp.validator.debug=true" } } } From f6cba4336504d66e1bfd9a08040a2c8e793926ff Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Sat, 9 Dec 2023 21:02:08 -0800 Subject: [PATCH 16/45] Revert debug --- buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle b/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle index 09d524f58..09ec817d8 100644 --- a/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle +++ b/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle @@ -36,7 +36,6 @@ tasks.withType(JavaCompile) { configure(options) { if (!name.toLowerCase().contains('test')) { options.compilerArgs << "-ArootProject.name=${rootProject.name}" << "-Aproject.name=${project.name}" - << "-Aorg.fury_phoenix.mixinAp.validator.debug=true" } } } From 52293cbc50aaadfb81512f0ca7c857d36ab78052 Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Sun, 10 Dec 2023 16:00:05 -0800 Subject: [PATCH 17/45] Brute force all markers --- .../annotation/ClientMixinValidator.java | 101 ++++++++++-------- 1 file changed, 58 insertions(+), 43 deletions(-) diff --git a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java index 8992dc755..7a6ef535f 100644 --- a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java +++ b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java @@ -6,8 +6,10 @@ import java.lang.invoke.*; import java.util.Collection; import java.util.HashSet; +import java.util.HashMap; import java.util.List; -import java.util.Set; +import java.util.Map; +import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -40,15 +42,10 @@ public class ClientMixinValidator { private final boolean debug; - private static final Collection markers = Set.of( - "net.fabricmc.api.Environment", - "net.minecraftforge.api.distmarker.OnlyIn", - "net.neoforged.api.distmarker.OnlyIn"); - - private static final Collection markerEnums = Set.of( - "net.fabricmc.api.EnvType", - "net.minecraftforge.api.distmarker.Dist", - "net.neoforged.api.distmarker.Dist"); + private static final Map markers = Map.of( + "net.fabricmc.api.Environment", "net.fabricmc.api.EnvType", + "net.minecraftforge.api.distmarker.OnlyIn", "net.minecraftforge.api.distmarker.Dist", + "net.neoforged.api.distmarker.OnlyIn", "net.neoforged.api.distmarker.Dist"); private static final Collection unannotatedClasses = new HashSet<>(); @@ -101,20 +98,20 @@ private boolean targetsClient(Object classTarget) { } private boolean isClientMarked(TypeElement te) { - Annotation marker = te.getAnnotation(getMarkerClass(markers)); - if(marker == null) { - if(debug && unannotatedClasses.add(te.toString())) { - messager.printMessage(Diagnostic.Kind.WARNING, - "Missing " + getMarkerClass(markers).getCanonicalName() + " on " + te + "!"); - } + for (var entry : getPlatformClasses(markers).entrySet()) { + Annotation marker = te.getAnnotation(entry.getKey()); + if(marker == null) continue; + + Optional accessor = getAccessor(entry.getKey(), entry.getValue()); + Optional enumValue = accessor.map((mh) -> this.invoke(mh, marker)) + .map(Object::toString); + if(enumValue.isPresent()) + return enumValue.orElseThrow().equals("CLIENT"); return false; } - try { - Object value = getAccessor().invoke(marker); - return value.toString().equals("CLIENT"); - } catch (Throwable e) { - messager.printMessage(Diagnostic.Kind.ERROR, "Fatal error:" + - Throwables.getStackTraceAsString(e)); + if(debug && unannotatedClasses.add(te.toString())) { + messager.printMessage(Diagnostic.Kind.WARNING, + "No marker annotations present on " + te + "!"); } return false; } @@ -125,11 +122,13 @@ private boolean warn(Object o) { return false; } - private MethodHandle getAccessor() throws ReflectiveOperationException { - Class markerClass = getMarkerClass(markers); - Class> markerEnumClass = getMarkerEnumClass(markerEnums); - MethodType enumValueAccessorType = MethodType.methodType(markerEnumClass); - return lookup.findVirtual(markerClass, "value", enumValueAccessorType); + private static Optional getAccessor(Class markerClass, + Class> enumClass) { + MethodType enumValueAccessorType = MethodType.methodType(enumClass); + try { + return Optional.of(lookup.findVirtual(markerClass, "value", enumValueAccessorType)); + } catch (ReflectiveOperationException e) {} + return Optional.empty(); } public SimpleImmutableEntry @@ -155,38 +154,54 @@ private TypeHandle getTypeHandle(Object annotatedClass) { return getTypeHandle(annotatedClass).getAnnotation(annotation); } - private static List getTargets(IAnnotationHandle mixinAnnotation) { + private static Collection getTargets(IAnnotationHandle mixinAnnotation) { Collection clzss = mixinAnnotation.getList("value"); Collection imaginary = mixinAnnotation.getList("targets"); - List targets = + Collection targets = Stream.of(clzss, imaginary) .flatMap(Collection::stream) .collect(Collectors.toList()); return targets; } - @SuppressWarnings("unchecked") - private static Class getMarkerClass(Collection markerSet) { - for(var annotation : markerSet) { - try { - return (Class)Class.forName(annotation); - } catch (ClassNotFoundException e) {} + private static Map, Class>> + getPlatformClasses(Map map) { + Map, Class>> platformClasses = new HashMap<>(); + for(var entry : map.entrySet()) { + Optional> annotation = getMarkerClass(entry.getKey()); + Optional>> enumClz = getMarkerEnumClass(entry.getValue()); + if(!annotation.isEmpty() && !enumClz.isEmpty()) + platformClasses.put(annotation.orElseThrow(), enumClz.orElseThrow()); } - throw new RuntimeException(); + return platformClasses; } @SuppressWarnings("unchecked") - private static Class> getMarkerEnumClass(Collection enumSet) { - for(var enumClass : enumSet) { - try { - return (Class>)Class.forName(enumClass); - } catch (ClassNotFoundException e) {} - } - throw new RuntimeException(); + private static Optional> getMarkerClass(String marker) { + try { + return Optional.of((Class)Class.forName(marker)); + } catch (ClassNotFoundException e) {} + return Optional.empty(); + } + + @SuppressWarnings("unchecked") + private static Optional>> getMarkerEnumClass(String enumClz) { + try { + Optional.of((Class>)Class.forName(enumClz)); + } catch (ClassNotFoundException e) {} + return Optional.empty(); } public static String toSourceString(String bytecodeName) { return bytecodeName.replaceAll("\\/", "."); } + private Object invoke(MethodHandle mh, Annotation marker) { + try { return mh.invoke(marker); } + catch (Throwable e) { + messager.printMessage(Diagnostic.Kind.ERROR, "Fatal error:" + + Throwables.getStackTraceAsString(e)); + } + return null; + } } From e190a713278a3e8d45e6cf3f2fb98d7cb70614e7 Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Sun, 10 Dec 2023 16:21:26 -0800 Subject: [PATCH 18/45] Fix overloads --- .../mixinAp/annotation/ClientMixinValidator.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java index 7a6ef535f..46c421fc7 100644 --- a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java +++ b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java @@ -7,7 +7,6 @@ import java.util.Collection; import java.util.HashSet; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; @@ -72,7 +71,7 @@ public boolean targetsClient(TypeElement annotatedMixinClass) { )); } - private boolean targetsClient(List classTargets) { + private boolean targetsClient(Collection classTargets) { return classTargets.stream().anyMatch(this::targetsClient); } @@ -157,11 +156,9 @@ private TypeHandle getTypeHandle(Object annotatedClass) { private static Collection getTargets(IAnnotationHandle mixinAnnotation) { Collection clzss = mixinAnnotation.getList("value"); Collection imaginary = mixinAnnotation.getList("targets"); - Collection targets = - Stream.of(clzss, imaginary) + return Stream.of(clzss, imaginary) .flatMap(Collection::stream) .collect(Collectors.toList()); - return targets; } private static Map, Class>> From 85dbaed7d380c95d71e2799773a4e75fcfffe654 Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Sun, 10 Dec 2023 16:24:38 -0800 Subject: [PATCH 19/45] Debug again --- buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle b/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle index 09ec817d8..09d524f58 100644 --- a/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle +++ b/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle @@ -36,6 +36,7 @@ tasks.withType(JavaCompile) { configure(options) { if (!name.toLowerCase().contains('test')) { options.compilerArgs << "-ArootProject.name=${rootProject.name}" << "-Aproject.name=${project.name}" + << "-Aorg.fury_phoenix.mixinAp.validator.debug=true" } } } From 96b84af9faf30460c1b2c31131e3343737e8d177 Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Sun, 10 Dec 2023 16:37:19 -0800 Subject: [PATCH 20/45] Bring in platform classes --- annotation-processor/build.gradle | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/annotation-processor/build.gradle b/annotation-processor/build.gradle index 6164c2293..54560e1e4 100644 --- a/annotation-processor/build.gradle +++ b/annotation-processor/build.gradle @@ -9,6 +9,10 @@ repositories { name "Fabric" url uri("https://maven.fabricmc.net") } + maven { + name "neoforged" + url "https://maven.neoforged.net/releases" + } } dependencies { @@ -17,8 +21,10 @@ dependencies { compileOnly 'com.google.auto.service:auto-service:1.1.1' implementation "net.fabricmc:sponge-mixin:0.12.5+" - // Out of necessity + // Platform classes implementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" + implementation "net.minecraftforge:mergetool:1.1.0" + implementation "net.neoforged:mergetool:2.0.0" implementation project(":annotations") } From 1936deab408d0b36d951f0c22002cfefd4f8da12 Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Sun, 10 Dec 2023 16:40:59 -0800 Subject: [PATCH 21/45] Retry --- annotation-processor/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/annotation-processor/build.gradle b/annotation-processor/build.gradle index 54560e1e4..5882f0b25 100644 --- a/annotation-processor/build.gradle +++ b/annotation-processor/build.gradle @@ -10,8 +10,8 @@ repositories { url uri("https://maven.fabricmc.net") } maven { - name "neoforged" - url "https://maven.neoforged.net/releases" + name "neoforged" + url "https://maven.neoforged.net/releases" } } From 81d30d595bef4614bf88870834fe8f3d69641ae2 Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Sun, 10 Dec 2023 16:44:43 -0800 Subject: [PATCH 22/45] Add in neoforge maven --- annotation-processor/build.gradle | 10 ++-------- .../main/groovy/modernfix.common-conventions.gradle | 3 ++- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/annotation-processor/build.gradle b/annotation-processor/build.gradle index 5882f0b25..741235a94 100644 --- a/annotation-processor/build.gradle +++ b/annotation-processor/build.gradle @@ -5,14 +5,8 @@ plugins { repositories { mavenCentral() - maven { - name "Fabric" - url uri("https://maven.fabricmc.net") - } - maven { - name "neoforged" - url "https://maven.neoforged.net/releases" - } + maven { url uri("https://maven.fabricmc.net") } + maven { url "https://maven.neoforged.net/releases" } } dependencies { diff --git a/buildSrc/src/main/groovy/modernfix.common-conventions.gradle b/buildSrc/src/main/groovy/modernfix.common-conventions.gradle index ebce0241e..126f3b076 100644 --- a/buildSrc/src/main/groovy/modernfix.common-conventions.gradle +++ b/buildSrc/src/main/groovy/modernfix.common-conventions.gradle @@ -78,4 +78,5 @@ repositories { url 'https://maven.terraformersmc.com/releases' } maven { url = "https://jitpack.io" } -} \ No newline at end of file + maven { url "https://maven.neoforged.net/releases" } +} From 47b614e0efb1f5386120f7f374627f2d511399e5 Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Sun, 10 Dec 2023 16:57:29 -0800 Subject: [PATCH 23/45] Rework platform detection logic again --- annotation-processor/build.gradle | 1 - .../mixinAp/annotation/ClientMixinValidator.java | 16 +++++++--------- .../groovy/modernfix.common-conventions.gradle | 1 - 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/annotation-processor/build.gradle b/annotation-processor/build.gradle index 741235a94..432847e02 100644 --- a/annotation-processor/build.gradle +++ b/annotation-processor/build.gradle @@ -18,7 +18,6 @@ dependencies { // Platform classes implementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" implementation "net.minecraftforge:mergetool:1.1.0" - implementation "net.neoforged:mergetool:2.0.0" implementation project(":annotations") } diff --git a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java index 46c421fc7..84cf122f9 100644 --- a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java +++ b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java @@ -98,15 +98,13 @@ private boolean targetsClient(Object classTarget) { private boolean isClientMarked(TypeElement te) { for (var entry : getPlatformClasses(markers).entrySet()) { - Annotation marker = te.getAnnotation(entry.getKey()); - if(marker == null) continue; - - Optional accessor = getAccessor(entry.getKey(), entry.getValue()); - Optional enumValue = accessor.map((mh) -> this.invoke(mh, marker)) - .map(Object::toString); - if(enumValue.isPresent()) - return enumValue.orElseThrow().equals("CLIENT"); - return false; + IAnnotationHandle marker = getAnnotationHandle(te, entry.getKey()); + if(!marker.exists()) continue; + + String[] enumValue = marker.getValue("value"); + if(enumValue==null) continue; + + return enumValue[1].equals("CLIENT"); } if(debug && unannotatedClasses.add(te.toString())) { messager.printMessage(Diagnostic.Kind.WARNING, diff --git a/buildSrc/src/main/groovy/modernfix.common-conventions.gradle b/buildSrc/src/main/groovy/modernfix.common-conventions.gradle index 126f3b076..ecf68ba0c 100644 --- a/buildSrc/src/main/groovy/modernfix.common-conventions.gradle +++ b/buildSrc/src/main/groovy/modernfix.common-conventions.gradle @@ -78,5 +78,4 @@ repositories { url 'https://maven.terraformersmc.com/releases' } maven { url = "https://jitpack.io" } - maven { url "https://maven.neoforged.net/releases" } } From 6f769066c589f8a078a631411615a64c9a50fbac Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Sun, 10 Dec 2023 17:26:33 -0800 Subject: [PATCH 24/45] Don't rely on enums being present --- annotation-processor/build.gradle | 1 - .../annotation/ClientMixinValidator.java | 64 +++++-------------- 2 files changed, 15 insertions(+), 50 deletions(-) diff --git a/annotation-processor/build.gradle b/annotation-processor/build.gradle index 432847e02..afd75192e 100644 --- a/annotation-processor/build.gradle +++ b/annotation-processor/build.gradle @@ -17,7 +17,6 @@ dependencies { implementation "net.fabricmc:sponge-mixin:0.12.5+" // Platform classes implementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" - implementation "net.minecraftforge:mergetool:1.1.0" implementation project(":annotations") } diff --git a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java index 84cf122f9..ce7a72021 100644 --- a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java +++ b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java @@ -1,14 +1,10 @@ package org.fury_phoenix.mixinAp.annotation; -import com.google.common.base.Throwables; - import java.lang.annotation.Annotation; -import java.lang.invoke.*; import java.util.Collection; import java.util.HashSet; -import java.util.HashMap; -import java.util.Map; import java.util.Optional; +import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -41,15 +37,13 @@ public class ClientMixinValidator { private final boolean debug; - private static final Map markers = Map.of( - "net.fabricmc.api.Environment", "net.fabricmc.api.EnvType", - "net.minecraftforge.api.distmarker.OnlyIn", "net.minecraftforge.api.distmarker.Dist", - "net.neoforged.api.distmarker.OnlyIn", "net.neoforged.api.distmarker.Dist"); + private static final Iterable markers = Set.of( + "net.fabricmc.api.Environment", + "net.minecraftforge.api.distmarker.OnlyIn", + "net.neoforged.api.distmarker.OnlyIn"); private static final Collection unannotatedClasses = new HashSet<>(); - private static final MethodHandles.Lookup lookup = MethodHandles.publicLookup(); - public ClientMixinValidator(ProcessingEnvironment env) throws ReflectiveOperationException { typeHandleProvider = AnnotatedMixinsAccessor.getMixinAP(env); @@ -97,11 +91,12 @@ private boolean targetsClient(Object classTarget) { } private boolean isClientMarked(TypeElement te) { - for (var entry : getPlatformClasses(markers).entrySet()) { - IAnnotationHandle marker = getAnnotationHandle(te, entry.getKey()); - if(!marker.exists()) continue; + for (var marker : getPlatformMarkers(markers)) { + messager.printMessage(Diagnostic.Kind.WARNING, marker.toString()); + IAnnotationHandle handle = getAnnotationHandle(te, marker); + if(!handle.exists()) continue; - String[] enumValue = marker.getValue("value"); + String[] enumValue = handle.getValue("value"); if(enumValue==null) continue; return enumValue[1].equals("CLIENT"); @@ -119,15 +114,6 @@ private boolean warn(Object o) { return false; } - private static Optional getAccessor(Class markerClass, - Class> enumClass) { - MethodType enumValueAccessorType = MethodType.methodType(enumClass); - try { - return Optional.of(lookup.findVirtual(markerClass, "value", enumValueAccessorType)); - } catch (ReflectiveOperationException e) {} - return Optional.empty(); - } - public SimpleImmutableEntry getEntry(TypeElement annotatedMixinClass) { return new SimpleImmutableEntry<>( @@ -159,14 +145,11 @@ private static Collection getTargets(IAnnotationHandle mixinAnnotation) .collect(Collectors.toList()); } - private static Map, Class>> - getPlatformClasses(Map map) { - Map, Class>> platformClasses = new HashMap<>(); - for(var entry : map.entrySet()) { - Optional> annotation = getMarkerClass(entry.getKey()); - Optional>> enumClz = getMarkerEnumClass(entry.getValue()); - if(!annotation.isEmpty() && !enumClz.isEmpty()) - platformClasses.put(annotation.orElseThrow(), enumClz.orElseThrow()); + private static Iterable> + getPlatformMarkers(Iterable markers) { + Set> platformClasses = new HashSet<>(); + for(var marker : markers) { + getMarkerClass(marker).ifPresent(platformClasses::add); } return platformClasses; } @@ -179,24 +162,7 @@ private static Optional> getMarkerClass(String marke return Optional.empty(); } - @SuppressWarnings("unchecked") - private static Optional>> getMarkerEnumClass(String enumClz) { - try { - Optional.of((Class>)Class.forName(enumClz)); - } catch (ClassNotFoundException e) {} - return Optional.empty(); - } - public static String toSourceString(String bytecodeName) { return bytecodeName.replaceAll("\\/", "."); } - - private Object invoke(MethodHandle mh, Annotation marker) { - try { return mh.invoke(marker); } - catch (Throwable e) { - messager.printMessage(Diagnostic.Kind.ERROR, "Fatal error:" + - Throwables.getStackTraceAsString(e)); - } - return null; - } } From 050bb438edb472de4c837e7c036b8532c5af1dce Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Sun, 10 Dec 2023 17:29:43 -0800 Subject: [PATCH 25/45] Runtime only classes --- annotation-processor/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/annotation-processor/build.gradle b/annotation-processor/build.gradle index afd75192e..48dbc0fd9 100644 --- a/annotation-processor/build.gradle +++ b/annotation-processor/build.gradle @@ -16,7 +16,7 @@ dependencies { implementation "net.fabricmc:sponge-mixin:0.12.5+" // Platform classes - implementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" + runtimeOnly "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" implementation project(":annotations") } From c6d830392c37879b18fdc037ddf84192ee535f89 Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Sun, 10 Dec 2023 17:30:11 -0800 Subject: [PATCH 26/45] Disable debug This reverts commit 1105830e2ee64b5b33bd481e50fd1fd7628e2e86. --- buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle b/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle index 09d524f58..09ec817d8 100644 --- a/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle +++ b/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle @@ -36,7 +36,6 @@ tasks.withType(JavaCompile) { configure(options) { if (!name.toLowerCase().contains('test')) { options.compilerArgs << "-ArootProject.name=${rootProject.name}" << "-Aproject.name=${project.name}" - << "-Aorg.fury_phoenix.mixinAp.validator.debug=true" } } } From 6876f37a618cf0ce77e4c5387e38fc71f26d9ea4 Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Sun, 10 Dec 2023 20:17:30 -0800 Subject: [PATCH 27/45] Prevent CME --- .../org/fury_phoenix/mixinAp/annotation/MixinProcessor.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java index bbce94900..c24ff5ce4 100644 --- a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java +++ b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java @@ -92,7 +92,8 @@ private void validateCommonMixins(TypeElement annotation, Stream mi if(!annotation.getSimpleName().toString().equals("Mixin")) return; ClientMixinValidator validator = new ClientMixinValidator(processingEnv); - mixins.parallel() + // The implementation may throw a CME + mixins.sequential() .filter(validator::validateMixin) .map(validator::getEntry) .forEach(this::logClientClassTarget); From 244fb8b4ee74440f0a9534b559a5734c69126eb0 Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Sun, 10 Dec 2023 22:30:38 -0800 Subject: [PATCH 28/45] Fix Forge mixins --- .../perf/async_jei/InputConstantsMixin.java | 2 + .../perf/async_locator/EyeOfEnderAccess.java | 6 ++- .../perf/async_locator/EyeOfEnderMixin.java | 48 ++++++++++--------- 3 files changed, 31 insertions(+), 25 deletions(-) diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/async_jei/InputConstantsMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/async_jei/InputConstantsMixin.java index e5b49c662..5b632f72a 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/async_jei/InputConstantsMixin.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/async_jei/InputConstantsMixin.java @@ -2,6 +2,7 @@ import com.mojang.blaze3d.platform.InputConstants; import com.mojang.blaze3d.systems.RenderSystem; +import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.embeddedt.modernfix.annotation.RequiresMod; import org.lwjgl.glfw.GLFW; import org.spongepowered.asm.mixin.Mixin; @@ -9,6 +10,7 @@ import org.spongepowered.asm.mixin.injection.Redirect; @Mixin(InputConstants.class) +@ClientOnlyMixin @RequiresMod("jei") public class InputConstantsMixin { @Redirect(method = "isKeyDown", at = @At(value = "INVOKE", target = "Lorg/lwjgl/glfw/GLFW;glfwGetKey(JI)I", remap = false)) diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/async_locator/EyeOfEnderAccess.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/async_locator/EyeOfEnderAccess.java index c35be48b0..f9750aed7 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/async_locator/EyeOfEnderAccess.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/async_locator/EyeOfEnderAccess.java @@ -1,11 +1,13 @@ package org.embeddedt.modernfix.forge.mixin.perf.async_locator; import net.minecraft.world.entity.projectile.EyeOfEnder; +import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; @Mixin(EyeOfEnder.class) +@ClientOnlyMixin public interface EyeOfEnderAccess { - @Accessor - void setLife(int life); + @Accessor + void setLife(int life); } diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/async_locator/EyeOfEnderMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/async_locator/EyeOfEnderMixin.java index 74205bf34..8c29370a3 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/async_locator/EyeOfEnderMixin.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/async_locator/EyeOfEnderMixin.java @@ -1,6 +1,7 @@ package org.embeddedt.modernfix.forge.mixin.perf.async_locator; import net.minecraft.world.entity.projectile.EyeOfEnder; +import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.embeddedt.modernfix.forge.structure.logic.EyeOfEnderData; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -8,30 +9,31 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(EyeOfEnder.class) +@ClientOnlyMixin public class EyeOfEnderMixin implements EyeOfEnderData { - private boolean locateTaskOngoing = false; + private boolean locateTaskOngoing = false; - @Override - public void setLocateTaskOngoing(boolean locateTaskOngoing) { - this.locateTaskOngoing = locateTaskOngoing; - } + @Override + public void setLocateTaskOngoing(boolean locateTaskOngoing) { + this.locateTaskOngoing = locateTaskOngoing; + } - /* - Intercept EyeOfEnder#tick call and return after the super call if there's an ongoing locate task. This is to - prevent the entity from moving or dying until we have a location result. - */ - @Inject( - method = "tick", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/world/entity/Entity;tick()V", - shift = At.Shift.AFTER - ), - cancellable = true - ) - public void skipTick(CallbackInfo ci) { - if (locateTaskOngoing) { - ci.cancel(); - } - } + /* + Intercept EyeOfEnder#tick call and return after the super call if there's an ongoing locate task. This is to + prevent the entity from moving or dying until we have a location result. + */ + @Inject( + method = "tick", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/entity/Entity;tick()V", + shift = At.Shift.AFTER + ), + cancellable = true + ) + public void skipTick(CallbackInfo ci) { + if (locateTaskOngoing) { + ci.cancel(); + } + } } From 53c96d33f0338dd3a4fde3dd5fb0f433c8e575a2 Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Sun, 10 Dec 2023 23:00:07 -0800 Subject: [PATCH 29/45] Remove brute force debug --- .../fury_phoenix/mixinAp/annotation/ClientMixinValidator.java | 1 - 1 file changed, 1 deletion(-) diff --git a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java index ce7a72021..7f534710b 100644 --- a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java +++ b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java @@ -92,7 +92,6 @@ private boolean targetsClient(Object classTarget) { private boolean isClientMarked(TypeElement te) { for (var marker : getPlatformMarkers(markers)) { - messager.printMessage(Diagnostic.Kind.WARNING, marker.toString()); IAnnotationHandle handle = getAnnotationHandle(te, marker); if(!handle.exists()) continue; From da5e64280ba4ddfcf39b24e53ec5d69af8e40830 Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Tue, 12 Dec 2023 21:11:52 -0800 Subject: [PATCH 30/45] Shadow relocate Fabric Mixin and intentionally override Mixin AP --- annotation-processor/build.gradle | 13 ++ .../MixinObfuscationProcessorTargets.java | 194 ++++++++++++++++++ .../modernfix.mod-common-conventions.gradle | 2 +- 3 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 annotation-processor/src/main/java/org/spongepowered/tools/obfuscation/MixinObfuscationProcessorTargets.java diff --git a/annotation-processor/build.gradle b/annotation-processor/build.gradle index 48dbc0fd9..3fc479ce7 100644 --- a/annotation-processor/build.gradle +++ b/annotation-processor/build.gradle @@ -1,4 +1,5 @@ plugins { + id "com.github.johnrengelman.shadow" version "7.1.2" id 'java-library' id 'com.diffplug.spotless' } @@ -14,6 +15,7 @@ dependencies { annotationProcessor 'com.google.auto.service:auto-service:1.1.1' compileOnly 'com.google.auto.service:auto-service:1.1.1' + shadow "net.fabricmc:sponge-mixin:0.12.5+" implementation "net.fabricmc:sponge-mixin:0.12.5+" // Platform classes runtimeOnly "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" @@ -24,6 +26,17 @@ tasks.withType(JavaCompile) { options.compilerArgs += '--enable-preview' } +shadowJar { + dependencies { + include(dependency('net.fabricmc:sponge-mixin:.*')) + } + exclude 'META-INF/services/org.spongepowered*' + exclude 'META-INF/services/cpw*' + relocate ('org.spongepowered', 'shadow.org.fury_phoenix.shadow.spongepowered') { + exclude 'org.spongepowered.tools.obfuscation.MixinObfuscationProcessorTargets' + } +} + spotless { java { removeUnusedImports() diff --git a/annotation-processor/src/main/java/org/spongepowered/tools/obfuscation/MixinObfuscationProcessorTargets.java b/annotation-processor/src/main/java/org/spongepowered/tools/obfuscation/MixinObfuscationProcessorTargets.java new file mode 100644 index 000000000..e3e4b98fd --- /dev/null +++ b/annotation-processor/src/main/java/org/spongepowered/tools/obfuscation/MixinObfuscationProcessorTargets.java @@ -0,0 +1,194 @@ +/* + * This file is part of Mixin, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.tools.obfuscation; + +import java.util.Set; + +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; + +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.asm.mixin.gen.Invoker; +import org.spongepowered.tools.obfuscation.interfaces.IMessagerEx.MessageType; +import org.spongepowered.tools.obfuscation.mirror.AnnotationHandle; +import org.spongepowered.tools.obfuscation.mirror.TypeUtils; + +/** + * Annotation processor which finds {@link Shadow} and {@link Overwrite} + * annotations in mixin classes and generates new obfuscation mappings + */ +@SupportedAnnotationTypes({ + "org.spongepowered.asm.mixin.Mixin", + "org.spongepowered.asm.mixin.Shadow", + "org.spongepowered.asm.mixin.Overwrite", + "org.spongepowered.asm.mixin.gen.Accessor", + "org.spongepowered.asm.mixin.Implements" +}) +public class MixinObfuscationProcessorTargets extends MixinObfuscationProcessor { + // Abuse classpath ordering so that the Mixin annotation remains consumable - Fury_Phoenix + /* (non-Javadoc) + * @see javax.annotation.processing.AbstractProcessor + * #process(java.util.Set, + * javax.annotation.processing.RoundEnvironment) + */ + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + if (roundEnv.processingOver()) { + this.postProcess(roundEnv); + return false; + } + + this.processMixins(roundEnv); + this.processShadows(roundEnv); + this.processOverwrites(roundEnv); + this.processAccessors(roundEnv); + this.processInvokers(roundEnv); + this.processImplements(roundEnv); + this.postProcess(roundEnv); + + return false; + } + + @Override + protected void postProcess(RoundEnvironment roundEnv) { + super.postProcess(roundEnv); + + try { + this.mixins.writeReferences(); + this.mixins.writeMappings(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + /** + * Searches for {@link Shadow} annotations and registers them with their + * parent mixins + */ + private void processShadows(RoundEnvironment roundEnv) { + for (Element elem : roundEnv.getElementsAnnotatedWith(Shadow.class)) { + Element parent = elem.getEnclosingElement(); + if (!(parent instanceof TypeElement)) { + this.mixins.printMessage(MessageType.ERROR, "Unexpected parent with type " + TypeUtils.getElementType(parent), elem); + continue; + } + + AnnotationHandle shadow = AnnotationHandle.of(elem, Shadow.class); + + if (elem.getKind() == ElementKind.FIELD) { + this.mixins.registerShadow((TypeElement)parent, (VariableElement)elem, shadow); + } else if (elem.getKind() == ElementKind.METHOD) { + this.mixins.registerShadow((TypeElement)parent, (ExecutableElement)elem, shadow); + } else { + this.mixins.printMessage(MessageType.SHADOW_ON_INVALID_ELEMENT, "Element is not a method or field", elem); + } + } + } + + /** + * Searches for {@link Overwrite} annotations and registers them with their + * parent mixins + */ + private void processOverwrites(RoundEnvironment roundEnv) { + for (Element elem : roundEnv.getElementsAnnotatedWith(Overwrite.class)) { + Element parent = elem.getEnclosingElement(); + if (!(parent instanceof TypeElement)) { + this.mixins.printMessage(MessageType.ERROR, "Unexpected parent with type " + TypeUtils.getElementType(parent), elem); + continue; + } + + if (elem.getKind() == ElementKind.METHOD) { + this.mixins.registerOverwrite((TypeElement)parent, (ExecutableElement)elem); + } else { + this.mixins.printMessage(MessageType.OVERWRITE_ON_NON_METHOD_ELEMENT, "Element is not a method", elem); + } + } + } + + /** + * Searches for {@link Accessor} annotations and registers them with their + * parent mixins + */ + private void processAccessors(RoundEnvironment roundEnv) { + for (Element elem : roundEnv.getElementsAnnotatedWith(Accessor.class)) { + Element parent = elem.getEnclosingElement(); + if (!(parent instanceof TypeElement)) { + this.mixins.printMessage(MessageType.ERROR, "Unexpected parent with type " + TypeUtils.getElementType(parent), elem); + continue; + } + + if (elem.getKind() == ElementKind.METHOD) { + this.mixins.registerAccessor((TypeElement)parent, (ExecutableElement)elem); + } else { + this.mixins.printMessage(MessageType.ACCESSOR_ON_NON_METHOD_ELEMENT, "Element is not a method", elem); + } + } + } + + /** + * Searches for {@link Invoker} annotations and registers them with their + * parent mixins + */ + private void processInvokers(RoundEnvironment roundEnv) { + for (Element elem : roundEnv.getElementsAnnotatedWith(Invoker.class)) { + Element parent = elem.getEnclosingElement(); + if (!(parent instanceof TypeElement)) { + this.mixins.printMessage(MessageType.ERROR, "Unexpected parent with type " + TypeUtils.getElementType(parent), elem); + continue; + } + + if (elem.getKind() == ElementKind.METHOD) { + this.mixins.registerInvoker((TypeElement)parent, (ExecutableElement)elem); + } else { + this.mixins.printMessage(MessageType.ACCESSOR_ON_NON_METHOD_ELEMENT, "Element is not a method", elem); + } + } + } + + /** + * Searches for {@link Implements} annotations and registers them with their + * parent mixins + */ + private void processImplements(RoundEnvironment roundEnv) { + for (Element elem : roundEnv.getElementsAnnotatedWith(Implements.class)) { + if (elem.getKind() == ElementKind.CLASS || elem.getKind() == ElementKind.INTERFACE) { + AnnotationHandle implementsAnnotation = AnnotationHandle.of(elem, Implements.class); + this.mixins.registerSoftImplements((TypeElement)elem, implementsAnnotation); + } else { + this.mixins.printMessage(MessageType.SOFT_IMPLEMENTS_ON_INVALID_TYPE, + "Found an @Implements annotation on an element which is not a class or interface", elem); + } + } + } + +} diff --git a/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle b/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle index 09ec817d8..498a21ed7 100644 --- a/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle +++ b/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle @@ -17,7 +17,7 @@ dependencies { } } implementation project(":annotations") - annotationProcessor project(":annotation-processor") + annotationProcessor project(path: ":annotation-processor", configuration: "shadow") } project.sourceSets { From 8a349ce684075ef0d7354893e2761a89ac6255e6 Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Tue, 12 Dec 2023 21:13:13 -0800 Subject: [PATCH 31/45] Don't assume common mixins is always present --- .../org/fury_phoenix/mixinAp/annotation/MixinProcessor.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java index c24ff5ce4..307016244 100644 --- a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java +++ b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java @@ -6,6 +6,7 @@ import java.util.List; import java.util.HashMap; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -43,7 +44,9 @@ public boolean process(Set annotations, RoundEnvironment if(roundEnv.processingOver()){ filterMixinSets(); // create record for serialization, compute package name - String packageName = mixinConfigList.get("mixins").get(0).split("(?<=mixin)")[0]; + String packageName = Optional.ofNullable(mixinConfigList.get("mixins")) + .orElse(mixinConfigList.get("client")) + .get(0).split("(?<=mixin)")[0]; finalizeMixinConfig(); new MixinConfig(packageName, mixinConfigList.get("mixins"), @@ -84,6 +87,7 @@ private void processMixins(Set annotations, RoundEnvironm private void filterMixinSets() { List commonSet = mixinConfigList.get("mixins"); + if(commonSet == null) return; commonSet.removeAll(mixinConfigList.get("client")); } From 7319e08e2837b5c1209428cc380a406b9f2d49f5 Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Tue, 12 Dec 2023 21:30:50 -0800 Subject: [PATCH 32/45] Rework shadowing --- annotation-processor-hack/build.gradle | 20 +++++++++++++++++++ .../MixinObfuscationProcessorTargets.java | 0 annotation-processor/build.gradle | 6 +++--- settings.gradle | 1 + 4 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 annotation-processor-hack/build.gradle rename {annotation-processor => annotation-processor-hack}/src/main/java/org/spongepowered/tools/obfuscation/MixinObfuscationProcessorTargets.java (100%) diff --git a/annotation-processor-hack/build.gradle b/annotation-processor-hack/build.gradle new file mode 100644 index 000000000..288850a5e --- /dev/null +++ b/annotation-processor-hack/build.gradle @@ -0,0 +1,20 @@ +plugins { + id 'java-library' + id 'com.diffplug.spotless' +} + +repositories { + mavenCentral() + maven { url uri("https://maven.fabricmc.net") } +} + +dependencies { + implementation "net.fabricmc:sponge-mixin:0.12.5+" +} + +spotless { + java { + removeUnusedImports() + } +} +version = '1.0.0' diff --git a/annotation-processor/src/main/java/org/spongepowered/tools/obfuscation/MixinObfuscationProcessorTargets.java b/annotation-processor-hack/src/main/java/org/spongepowered/tools/obfuscation/MixinObfuscationProcessorTargets.java similarity index 100% rename from annotation-processor/src/main/java/org/spongepowered/tools/obfuscation/MixinObfuscationProcessorTargets.java rename to annotation-processor-hack/src/main/java/org/spongepowered/tools/obfuscation/MixinObfuscationProcessorTargets.java diff --git a/annotation-processor/build.gradle b/annotation-processor/build.gradle index 3fc479ce7..eb9914015 100644 --- a/annotation-processor/build.gradle +++ b/annotation-processor/build.gradle @@ -20,6 +20,7 @@ dependencies { // Platform classes runtimeOnly "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" implementation project(":annotations") + implementation project(":annotation-processor-hack") } tasks.withType(JavaCompile) { @@ -32,9 +33,8 @@ shadowJar { } exclude 'META-INF/services/org.spongepowered*' exclude 'META-INF/services/cpw*' - relocate ('org.spongepowered', 'shadow.org.fury_phoenix.shadow.spongepowered') { - exclude 'org.spongepowered.tools.obfuscation.MixinObfuscationProcessorTargets' - } + relocate ('org.spongepowered', 'shadow.org.fury_phoenix.shadow.spongepowered') + minimize() } spotless { diff --git a/settings.gradle b/settings.gradle index 762143525..3e6ed6b69 100644 --- a/settings.gradle +++ b/settings.gradle @@ -8,6 +8,7 @@ pluginManagement { } include("annotation-processor") +include("annotation-processor-hack") include("annotations") include("test_agent") include("common") From 94e9c63abd4ba04e0fe0cfe64e73702988b87ca7 Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Wed, 13 Dec 2023 21:28:23 -0800 Subject: [PATCH 33/45] Unify shadow version Dependency rework Remove class shunting hack --- annotation-processor-hack/build.gradle | 20 -- .../MixinObfuscationProcessorTargets.java | 194 ------------------ annotation-processor/build.gradle | 7 +- fabric/build.gradle | 4 +- forge/build.gradle | 4 +- gradle.properties | 1 + 6 files changed, 8 insertions(+), 222 deletions(-) delete mode 100644 annotation-processor-hack/build.gradle delete mode 100644 annotation-processor-hack/src/main/java/org/spongepowered/tools/obfuscation/MixinObfuscationProcessorTargets.java diff --git a/annotation-processor-hack/build.gradle b/annotation-processor-hack/build.gradle deleted file mode 100644 index 288850a5e..000000000 --- a/annotation-processor-hack/build.gradle +++ /dev/null @@ -1,20 +0,0 @@ -plugins { - id 'java-library' - id 'com.diffplug.spotless' -} - -repositories { - mavenCentral() - maven { url uri("https://maven.fabricmc.net") } -} - -dependencies { - implementation "net.fabricmc:sponge-mixin:0.12.5+" -} - -spotless { - java { - removeUnusedImports() - } -} -version = '1.0.0' diff --git a/annotation-processor-hack/src/main/java/org/spongepowered/tools/obfuscation/MixinObfuscationProcessorTargets.java b/annotation-processor-hack/src/main/java/org/spongepowered/tools/obfuscation/MixinObfuscationProcessorTargets.java deleted file mode 100644 index e3e4b98fd..000000000 --- a/annotation-processor-hack/src/main/java/org/spongepowered/tools/obfuscation/MixinObfuscationProcessorTargets.java +++ /dev/null @@ -1,194 +0,0 @@ -/* - * This file is part of Mixin, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.tools.obfuscation; - -import java.util.Set; - -import javax.annotation.processing.RoundEnvironment; -import javax.annotation.processing.SupportedAnnotationTypes; -import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.TypeElement; -import javax.lang.model.element.VariableElement; - -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.gen.Accessor; -import org.spongepowered.asm.mixin.gen.Invoker; -import org.spongepowered.tools.obfuscation.interfaces.IMessagerEx.MessageType; -import org.spongepowered.tools.obfuscation.mirror.AnnotationHandle; -import org.spongepowered.tools.obfuscation.mirror.TypeUtils; - -/** - * Annotation processor which finds {@link Shadow} and {@link Overwrite} - * annotations in mixin classes and generates new obfuscation mappings - */ -@SupportedAnnotationTypes({ - "org.spongepowered.asm.mixin.Mixin", - "org.spongepowered.asm.mixin.Shadow", - "org.spongepowered.asm.mixin.Overwrite", - "org.spongepowered.asm.mixin.gen.Accessor", - "org.spongepowered.asm.mixin.Implements" -}) -public class MixinObfuscationProcessorTargets extends MixinObfuscationProcessor { - // Abuse classpath ordering so that the Mixin annotation remains consumable - Fury_Phoenix - /* (non-Javadoc) - * @see javax.annotation.processing.AbstractProcessor - * #process(java.util.Set, - * javax.annotation.processing.RoundEnvironment) - */ - @Override - public boolean process(Set annotations, RoundEnvironment roundEnv) { - if (roundEnv.processingOver()) { - this.postProcess(roundEnv); - return false; - } - - this.processMixins(roundEnv); - this.processShadows(roundEnv); - this.processOverwrites(roundEnv); - this.processAccessors(roundEnv); - this.processInvokers(roundEnv); - this.processImplements(roundEnv); - this.postProcess(roundEnv); - - return false; - } - - @Override - protected void postProcess(RoundEnvironment roundEnv) { - super.postProcess(roundEnv); - - try { - this.mixins.writeReferences(); - this.mixins.writeMappings(); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - - /** - * Searches for {@link Shadow} annotations and registers them with their - * parent mixins - */ - private void processShadows(RoundEnvironment roundEnv) { - for (Element elem : roundEnv.getElementsAnnotatedWith(Shadow.class)) { - Element parent = elem.getEnclosingElement(); - if (!(parent instanceof TypeElement)) { - this.mixins.printMessage(MessageType.ERROR, "Unexpected parent with type " + TypeUtils.getElementType(parent), elem); - continue; - } - - AnnotationHandle shadow = AnnotationHandle.of(elem, Shadow.class); - - if (elem.getKind() == ElementKind.FIELD) { - this.mixins.registerShadow((TypeElement)parent, (VariableElement)elem, shadow); - } else if (elem.getKind() == ElementKind.METHOD) { - this.mixins.registerShadow((TypeElement)parent, (ExecutableElement)elem, shadow); - } else { - this.mixins.printMessage(MessageType.SHADOW_ON_INVALID_ELEMENT, "Element is not a method or field", elem); - } - } - } - - /** - * Searches for {@link Overwrite} annotations and registers them with their - * parent mixins - */ - private void processOverwrites(RoundEnvironment roundEnv) { - for (Element elem : roundEnv.getElementsAnnotatedWith(Overwrite.class)) { - Element parent = elem.getEnclosingElement(); - if (!(parent instanceof TypeElement)) { - this.mixins.printMessage(MessageType.ERROR, "Unexpected parent with type " + TypeUtils.getElementType(parent), elem); - continue; - } - - if (elem.getKind() == ElementKind.METHOD) { - this.mixins.registerOverwrite((TypeElement)parent, (ExecutableElement)elem); - } else { - this.mixins.printMessage(MessageType.OVERWRITE_ON_NON_METHOD_ELEMENT, "Element is not a method", elem); - } - } - } - - /** - * Searches for {@link Accessor} annotations and registers them with their - * parent mixins - */ - private void processAccessors(RoundEnvironment roundEnv) { - for (Element elem : roundEnv.getElementsAnnotatedWith(Accessor.class)) { - Element parent = elem.getEnclosingElement(); - if (!(parent instanceof TypeElement)) { - this.mixins.printMessage(MessageType.ERROR, "Unexpected parent with type " + TypeUtils.getElementType(parent), elem); - continue; - } - - if (elem.getKind() == ElementKind.METHOD) { - this.mixins.registerAccessor((TypeElement)parent, (ExecutableElement)elem); - } else { - this.mixins.printMessage(MessageType.ACCESSOR_ON_NON_METHOD_ELEMENT, "Element is not a method", elem); - } - } - } - - /** - * Searches for {@link Invoker} annotations and registers them with their - * parent mixins - */ - private void processInvokers(RoundEnvironment roundEnv) { - for (Element elem : roundEnv.getElementsAnnotatedWith(Invoker.class)) { - Element parent = elem.getEnclosingElement(); - if (!(parent instanceof TypeElement)) { - this.mixins.printMessage(MessageType.ERROR, "Unexpected parent with type " + TypeUtils.getElementType(parent), elem); - continue; - } - - if (elem.getKind() == ElementKind.METHOD) { - this.mixins.registerInvoker((TypeElement)parent, (ExecutableElement)elem); - } else { - this.mixins.printMessage(MessageType.ACCESSOR_ON_NON_METHOD_ELEMENT, "Element is not a method", elem); - } - } - } - - /** - * Searches for {@link Implements} annotations and registers them with their - * parent mixins - */ - private void processImplements(RoundEnvironment roundEnv) { - for (Element elem : roundEnv.getElementsAnnotatedWith(Implements.class)) { - if (elem.getKind() == ElementKind.CLASS || elem.getKind() == ElementKind.INTERFACE) { - AnnotationHandle implementsAnnotation = AnnotationHandle.of(elem, Implements.class); - this.mixins.registerSoftImplements((TypeElement)elem, implementsAnnotation); - } else { - this.mixins.printMessage(MessageType.SOFT_IMPLEMENTS_ON_INVALID_TYPE, - "Found an @Implements annotation on an element which is not a class or interface", elem); - } - } - } - -} diff --git a/annotation-processor/build.gradle b/annotation-processor/build.gradle index eb9914015..05286a891 100644 --- a/annotation-processor/build.gradle +++ b/annotation-processor/build.gradle @@ -1,5 +1,5 @@ plugins { - id "com.github.johnrengelman.shadow" version "7.1.2" + id "com.github.johnrengelman.shadow" version "${rootProject.shadow_version}" id 'java-library' id 'com.diffplug.spotless' } @@ -11,16 +11,15 @@ repositories { } dependencies { + implementation 'com.google.guava:guava:21.0' implementation 'com.google.code.gson:gson:2.10.1' annotationProcessor 'com.google.auto.service:auto-service:1.1.1' compileOnly 'com.google.auto.service:auto-service:1.1.1' - shadow "net.fabricmc:sponge-mixin:0.12.5+" implementation "net.fabricmc:sponge-mixin:0.12.5+" // Platform classes - runtimeOnly "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" +// "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" implementation project(":annotations") - implementation project(":annotation-processor-hack") } tasks.withType(JavaCompile) { diff --git a/fabric/build.gradle b/fabric/build.gradle index 6eefad324..bde01797a 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -1,5 +1,5 @@ plugins { - id "com.github.johnrengelman.shadow" version "7.1.2" + id "com.github.johnrengelman.shadow" version "${rootProject.shadow_version}" id 'com.adarshr.test-logger' version '3.2.0' id "modernfix.mod-common-conventions" id "modernfix.platform-conventions" @@ -122,4 +122,4 @@ publishing { repositories { // Add repositories to publish to here. } -} \ No newline at end of file +} diff --git a/forge/build.gradle b/forge/build.gradle index 5d783901a..c064f5611 100644 --- a/forge/build.gradle +++ b/forge/build.gradle @@ -1,5 +1,5 @@ plugins { - id "com.github.johnrengelman.shadow" version "7.1.2" + id "com.github.johnrengelman.shadow" version "${rootProject.shadow_version}" id "modernfix.mod-common-conventions" id "modernfix.platform-conventions" } @@ -141,4 +141,4 @@ publishing { repositories { // Add repositories to publish to here. } -} \ No newline at end of file +} diff --git a/gradle.properties b/gradle.properties index 0777bd13d..8dee0a7c4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -16,6 +16,7 @@ refined_storage_version=3807951 kubejs_version=1605.3.19-build.299 ctm_version=MC1.16.1-1.1.2.6 supported_minecraft_versions=1.16.4,1.16.5 +shadow_version=7.1.2 fabric_loader_version=0.14.21 fabric_api_version=0.42.0+1.16 From 542ae3e97922474ebcdb302b7ed2a402e148b9c9 Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Thu, 14 Dec 2023 14:16:34 -0800 Subject: [PATCH 34/45] Fix property substitution --- annotation-processor/build.gradle | 4 ++-- fabric/build.gradle | 2 +- forge/build.gradle | 2 +- settings.gradle | 7 +++++++ 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/annotation-processor/build.gradle b/annotation-processor/build.gradle index 05286a891..e01ae2493 100644 --- a/annotation-processor/build.gradle +++ b/annotation-processor/build.gradle @@ -1,5 +1,5 @@ plugins { - id "com.github.johnrengelman.shadow" version "${rootProject.shadow_version}" + id "com.github.johnrengelman.shadow" id 'java-library' id 'com.diffplug.spotless' } @@ -41,4 +41,4 @@ spotless { removeUnusedImports() } } -version = '1.1.1' +version = '1.1.2' diff --git a/fabric/build.gradle b/fabric/build.gradle index bde01797a..c20477319 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -1,5 +1,5 @@ plugins { - id "com.github.johnrengelman.shadow" version "${rootProject.shadow_version}" + id "com.github.johnrengelman.shadow" id 'com.adarshr.test-logger' version '3.2.0' id "modernfix.mod-common-conventions" id "modernfix.platform-conventions" diff --git a/forge/build.gradle b/forge/build.gradle index c064f5611..ea515fab5 100644 --- a/forge/build.gradle +++ b/forge/build.gradle @@ -1,5 +1,5 @@ plugins { - id "com.github.johnrengelman.shadow" version "${rootProject.shadow_version}" + id "com.github.johnrengelman.shadow" id "modernfix.mod-common-conventions" id "modernfix.platform-conventions" } diff --git a/settings.gradle b/settings.gradle index 3e6ed6b69..6a137b839 100644 --- a/settings.gradle +++ b/settings.gradle @@ -5,6 +5,13 @@ pluginManagement { maven { url "https://maven.architectury.dev/" } maven { url "https://maven.minecraftforge.net/" } } + resolutionStrategy { + eachPlugin { + if (requested.id.id == "com.github.johnrengelman.shadow") { + useModule("gradle.plugin.com.github.johnrengelman:shadow:${shadow_version}") + } + } + } } include("annotation-processor") From 0c4912b771f368558f76ae3b72220de079583f9c Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Thu, 14 Dec 2023 14:22:49 -0800 Subject: [PATCH 35/45] Unshadow mixin processor There is no way to prevent the relocator transformation so we depend on the unshadowed project that pulls the shadowed project Cleanup client validator shadow jar --- annotation-processor-unshadow/build.gradle | 27 +++++++++++++++++++ .../mixinAp/annotation/MixinProcessor.java | 0 annotation-processor/build.gradle | 6 ++--- .../modernfix.mod-common-conventions.gradle | 2 +- gradle.properties | 1 + settings.gradle | 2 +- 6 files changed, 32 insertions(+), 6 deletions(-) create mode 100644 annotation-processor-unshadow/build.gradle rename {annotation-processor => annotation-processor-unshadow}/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java (100%) diff --git a/annotation-processor-unshadow/build.gradle b/annotation-processor-unshadow/build.gradle new file mode 100644 index 000000000..101a5c08e --- /dev/null +++ b/annotation-processor-unshadow/build.gradle @@ -0,0 +1,27 @@ +plugins { + id 'java-library' + id 'com.diffplug.spotless' +} + +repositories { + mavenCentral() +} + +dependencies { + implementation 'com.google.guava:guava:21.0' + annotationProcessor 'com.google.auto.service:auto-service:1.1.1' + compileOnly 'com.google.auto.service:auto-service:1.1.1' + + implementation project(":annotation-processor") +} + +tasks.withType(JavaCompile) { + options.compilerArgs += '--enable-preview' +} + +spotless { + java { + removeUnusedImports() + } +} +version = '1.1.2' diff --git a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java b/annotation-processor-unshadow/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java similarity index 100% rename from annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java rename to annotation-processor-unshadow/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java diff --git a/annotation-processor/build.gradle b/annotation-processor/build.gradle index e01ae2493..7da8f5e2f 100644 --- a/annotation-processor/build.gradle +++ b/annotation-processor/build.gradle @@ -11,11 +11,7 @@ repositories { } dependencies { - implementation 'com.google.guava:guava:21.0' implementation 'com.google.code.gson:gson:2.10.1' - annotationProcessor 'com.google.auto.service:auto-service:1.1.1' - compileOnly 'com.google.auto.service:auto-service:1.1.1' - implementation "net.fabricmc:sponge-mixin:0.12.5+" // Platform classes // "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" @@ -32,6 +28,8 @@ shadowJar { } exclude 'META-INF/services/org.spongepowered*' exclude 'META-INF/services/cpw*' + exclude 'META-INF/maven*' + exclude 'LICENSE.txt' relocate ('org.spongepowered', 'shadow.org.fury_phoenix.shadow.spongepowered') minimize() } diff --git a/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle b/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle index 498a21ed7..782ba2c93 100644 --- a/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle +++ b/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle @@ -17,7 +17,7 @@ dependencies { } } implementation project(":annotations") - annotationProcessor project(path: ":annotation-processor", configuration: "shadow") + annotationProcessor project(":annotation-processor-unshadow") } project.sourceSets { diff --git a/gradle.properties b/gradle.properties index 8dee0a7c4..a66571673 100644 --- a/gradle.properties +++ b/gradle.properties @@ -16,6 +16,7 @@ refined_storage_version=3807951 kubejs_version=1605.3.19-build.299 ctm_version=MC1.16.1-1.1.2.6 supported_minecraft_versions=1.16.4,1.16.5 +// Look up maven coordinates when changing shadow_version shadow_version=7.1.2 fabric_loader_version=0.14.21 diff --git a/settings.gradle b/settings.gradle index 6a137b839..508e8db8f 100644 --- a/settings.gradle +++ b/settings.gradle @@ -15,7 +15,7 @@ pluginManagement { } include("annotation-processor") -include("annotation-processor-hack") +include("annotation-processor-unshadow") include("annotations") include("test_agent") include("common") From 68952d87bc37a01d995f311a13eb05b7ccf65caa Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Thu, 14 Dec 2023 15:17:59 -0800 Subject: [PATCH 36/45] Depend on shadow config Fix shadowed unbundled dependencies --- annotation-processor-unshadow/build.gradle | 2 +- annotation-processor/build.gradle | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/annotation-processor-unshadow/build.gradle b/annotation-processor-unshadow/build.gradle index 101a5c08e..f3e5ee48b 100644 --- a/annotation-processor-unshadow/build.gradle +++ b/annotation-processor-unshadow/build.gradle @@ -12,7 +12,7 @@ dependencies { annotationProcessor 'com.google.auto.service:auto-service:1.1.1' compileOnly 'com.google.auto.service:auto-service:1.1.1' - implementation project(":annotation-processor") + implementation project(path: ":annotation-processor", configuration: 'shadow') } tasks.withType(JavaCompile) { diff --git a/annotation-processor/build.gradle b/annotation-processor/build.gradle index 7da8f5e2f..924ad0e56 100644 --- a/annotation-processor/build.gradle +++ b/annotation-processor/build.gradle @@ -11,6 +11,7 @@ repositories { } dependencies { + shadow 'com.google.code.gson:gson:2.10.1' implementation 'com.google.code.gson:gson:2.10.1' implementation "net.fabricmc:sponge-mixin:0.12.5+" // Platform classes From 2870a42e8e6d520089ce17d71da877024552888d Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Thu, 14 Dec 2023 21:16:20 -0800 Subject: [PATCH 37/45] Manually shadow Mixin --- annotation-processor-unshadow/build.gradle | 2 +- annotation-processor/build.gradle | 19 +-- .../org/spongepowered/asm/mixin/Mixin.java | 119 ++++++++++++++++++ 3 files changed, 123 insertions(+), 17 deletions(-) create mode 100644 annotation-processor/src/main/java/org/spongepowered/asm/mixin/Mixin.java diff --git a/annotation-processor-unshadow/build.gradle b/annotation-processor-unshadow/build.gradle index f3e5ee48b..d0396fbd9 100644 --- a/annotation-processor-unshadow/build.gradle +++ b/annotation-processor-unshadow/build.gradle @@ -12,7 +12,7 @@ dependencies { annotationProcessor 'com.google.auto.service:auto-service:1.1.1' compileOnly 'com.google.auto.service:auto-service:1.1.1' - implementation project(path: ":annotation-processor", configuration: 'shadow') + implementation project(path: ":annotation-processor") } tasks.withType(JavaCompile) { diff --git a/annotation-processor/build.gradle b/annotation-processor/build.gradle index 924ad0e56..0ef5aafd6 100644 --- a/annotation-processor/build.gradle +++ b/annotation-processor/build.gradle @@ -1,5 +1,4 @@ plugins { - id "com.github.johnrengelman.shadow" id 'java-library' id 'com.diffplug.spotless' } @@ -11,9 +10,8 @@ repositories { } dependencies { - shadow 'com.google.code.gson:gson:2.10.1' implementation 'com.google.code.gson:gson:2.10.1' - implementation "net.fabricmc:sponge-mixin:0.12.5+" + implementation 'com.google.auto:auto-common:1.2.1' // Platform classes // "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" implementation project(":annotations") @@ -21,18 +19,7 @@ dependencies { tasks.withType(JavaCompile) { options.compilerArgs += '--enable-preview' -} - -shadowJar { - dependencies { - include(dependency('net.fabricmc:sponge-mixin:.*')) - } - exclude 'META-INF/services/org.spongepowered*' - exclude 'META-INF/services/cpw*' - exclude 'META-INF/maven*' - exclude 'LICENSE.txt' - relocate ('org.spongepowered', 'shadow.org.fury_phoenix.shadow.spongepowered') - minimize() + options.release = 17 } spotless { @@ -40,4 +27,4 @@ spotless { removeUnusedImports() } } -version = '1.1.2' +version = '1.1.4' diff --git a/annotation-processor/src/main/java/org/spongepowered/asm/mixin/Mixin.java b/annotation-processor/src/main/java/org/spongepowered/asm/mixin/Mixin.java new file mode 100644 index 000000000..f7861c1c9 --- /dev/null +++ b/annotation-processor/src/main/java/org/spongepowered/asm/mixin/Mixin.java @@ -0,0 +1,119 @@ +/* + * This file is part of Mixin, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.asm.mixin; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * The main decorator for mixin classes, this annotation denotes a class as a + * mixin and specifies two key attributes: + * + *
+ *
The target classes
+ *
Every mixin requires at least one target class in order to be valid. + * The target classes should be specified via {@link #value} where possible + * using class literals. However for anonymous inner classes, + * package-private classes, or unavailable classes (eg. synthetic classes) + * being targetted via {@link Pseudo @Pseudo}, the targets should be + * specified via the {@link #targets} instead.
+ *
The priority
+ *
The mixin {@link #priority} is used to express the mixin's desired + * ordering with respect to other mixins being applied to the same target + * class.
+ *
+ */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.CLASS) +public @interface Mixin { + + /** + * Target class(es) for this mixin + * + * @return classes this mixin targets + */ + public Class[] value() default { }; + + /** + * Since specifying targets in {@link #value} requires that the classes be + * publicly visible, this property is provided to allow package-private, + * anonymous innner, and private inner, or unavailable ({@link Pseudo + * @Pseudo} classes to be referenced. Referencing an otherwise public + * class using this property is an error condition and will raise a warning + * at runtime or an error if {@link MixinEnvironment.Option#DEBUG_STRICT + * strict checks} are enabled. It is completely fine to specify both publi + * and private targets for the same mixin however. + * + *

Note that unlike class literals specified in {@link #value}, imports + * are not supported and therefore the class specified here must be + * fully-qualified with the package name.

+ * + * @return protected, package-private, or {@link Pseudo pseudo} classes this + * mixin targets + */ + public String[] targets() default { }; + + /** + * Priority for the mixin, relative to other mixins targetting the same + * classes. By default mixins inherit their priority from the parent + * configuration that contains them, setting this value allows the priority + * to be overridden on a per-mixin basis. + * + *

Priorities sort mixins into natural order with lower priority + * mixins being applied first. This changes the nature of priority based on + * your intentions. Especially with respect to injectors, which must be + * considered on a case-by-case basis since the semantics of priority vary + * by injector because of first-come-first-served versus implied ordering of + * injectors such as inject-at-HEAD.

+ * + * @return the mixin priority (relative to other mixins targetting the same + * class) + */ + public int priority() default 1000; + + /** + * By default, the annotation processor will attempt to locate an + * obfuscation mapping for all {@link Overwrite}, {@link Shadow} and + * {@link org.spongepowered.asm.mixin.injection.Inject} annotated members + * since it is anticipated that in general the target of a {@link Mixin} + * will be an obfuscated class and all annotated members will need to be + * added to the obfuscation table. However since it is possible to also + * apply mixins to non-obfuscated targets it may be desirable to suppress + * the compiler warnings which would otherwise be generated. This can be + * done on an individual member basis by setting remap to + * false on the individual annotations, or disabled for the entire + * mixin by setting the value here to false. Doing so will cause + * the annotation processor to skip all annotations in this mixin when + * building the obfuscation table unless the individual annotation is + * explicitly decorated with remap = true. + * + * @return True to instruct the annotation processor to search for + * obfuscation mappings for this annotation (default true). + */ + public boolean remap() default true; + +} From 6a12f72311bd1014d732fb2d53aeef98962da9ac Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Sat, 16 Dec 2023 16:37:01 -0800 Subject: [PATCH 38/45] Unshadow mixin again, wean off dependency --- .../org/spongepowered/asm/mixin/Mixin.java | 119 ------------------ .../obfuscation/AnnotatedMixinsAccessor.java | 11 -- 2 files changed, 130 deletions(-) delete mode 100644 annotation-processor/src/main/java/org/spongepowered/asm/mixin/Mixin.java delete mode 100644 annotation-processor/src/main/java/org/spongepowered/tools/obfuscation/AnnotatedMixinsAccessor.java diff --git a/annotation-processor/src/main/java/org/spongepowered/asm/mixin/Mixin.java b/annotation-processor/src/main/java/org/spongepowered/asm/mixin/Mixin.java deleted file mode 100644 index f7861c1c9..000000000 --- a/annotation-processor/src/main/java/org/spongepowered/asm/mixin/Mixin.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * This file is part of Mixin, licensed under the MIT License (MIT). - * - * Copyright (c) SpongePowered - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.spongepowered.asm.mixin; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * The main decorator for mixin classes, this annotation denotes a class as a - * mixin and specifies two key attributes: - * - *
- *
The target classes
- *
Every mixin requires at least one target class in order to be valid. - * The target classes should be specified via {@link #value} where possible - * using class literals. However for anonymous inner classes, - * package-private classes, or unavailable classes (eg. synthetic classes) - * being targetted via {@link Pseudo @Pseudo}, the targets should be - * specified via the {@link #targets} instead.
- *
The priority
- *
The mixin {@link #priority} is used to express the mixin's desired - * ordering with respect to other mixins being applied to the same target - * class.
- *
- */ -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.CLASS) -public @interface Mixin { - - /** - * Target class(es) for this mixin - * - * @return classes this mixin targets - */ - public Class[] value() default { }; - - /** - * Since specifying targets in {@link #value} requires that the classes be - * publicly visible, this property is provided to allow package-private, - * anonymous innner, and private inner, or unavailable ({@link Pseudo - * @Pseudo} classes to be referenced. Referencing an otherwise public - * class using this property is an error condition and will raise a warning - * at runtime or an error if {@link MixinEnvironment.Option#DEBUG_STRICT - * strict checks} are enabled. It is completely fine to specify both publi - * and private targets for the same mixin however. - * - *

Note that unlike class literals specified in {@link #value}, imports - * are not supported and therefore the class specified here must be - * fully-qualified with the package name.

- * - * @return protected, package-private, or {@link Pseudo pseudo} classes this - * mixin targets - */ - public String[] targets() default { }; - - /** - * Priority for the mixin, relative to other mixins targetting the same - * classes. By default mixins inherit their priority from the parent - * configuration that contains them, setting this value allows the priority - * to be overridden on a per-mixin basis. - * - *

Priorities sort mixins into natural order with lower priority - * mixins being applied first. This changes the nature of priority based on - * your intentions. Especially with respect to injectors, which must be - * considered on a case-by-case basis since the semantics of priority vary - * by injector because of first-come-first-served versus implied ordering of - * injectors such as inject-at-HEAD.

- * - * @return the mixin priority (relative to other mixins targetting the same - * class) - */ - public int priority() default 1000; - - /** - * By default, the annotation processor will attempt to locate an - * obfuscation mapping for all {@link Overwrite}, {@link Shadow} and - * {@link org.spongepowered.asm.mixin.injection.Inject} annotated members - * since it is anticipated that in general the target of a {@link Mixin} - * will be an obfuscated class and all annotated members will need to be - * added to the obfuscation table. However since it is possible to also - * apply mixins to non-obfuscated targets it may be desirable to suppress - * the compiler warnings which would otherwise be generated. This can be - * done on an individual member basis by setting remap to - * false on the individual annotations, or disabled for the entire - * mixin by setting the value here to false. Doing so will cause - * the annotation processor to skip all annotations in this mixin when - * building the obfuscation table unless the individual annotation is - * explicitly decorated with remap = true. - * - * @return True to instruct the annotation processor to search for - * obfuscation mappings for this annotation (default true). - */ - public boolean remap() default true; - -} diff --git a/annotation-processor/src/main/java/org/spongepowered/tools/obfuscation/AnnotatedMixinsAccessor.java b/annotation-processor/src/main/java/org/spongepowered/tools/obfuscation/AnnotatedMixinsAccessor.java deleted file mode 100644 index cea621fc8..000000000 --- a/annotation-processor/src/main/java/org/spongepowered/tools/obfuscation/AnnotatedMixinsAccessor.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.spongepowered.tools.obfuscation; - -import javax.annotation.processing.ProcessingEnvironment; - -import org.spongepowered.tools.obfuscation.interfaces.ITypeHandleProvider; - -public class AnnotatedMixinsAccessor { - public static ITypeHandleProvider getMixinAP(ProcessingEnvironment processingEnv) { - return AnnotatedMixins.getMixinsForEnvironment(processingEnv); - } -} From 83625bdfa2bccac74f46e7f4a9256a0d70044f22 Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Sat, 16 Dec 2023 16:42:09 -0800 Subject: [PATCH 39/45] Reunify AP --- annotation-processor-unshadow/build.gradle | 27 ------------------- annotation-processor/build.gradle | 16 +++++++++-- .../mixinAp/annotation/MixinProcessor.java | 0 .../modernfix.mod-common-conventions.gradle | 2 +- settings.gradle | 1 - 5 files changed, 15 insertions(+), 31 deletions(-) delete mode 100644 annotation-processor-unshadow/build.gradle rename {annotation-processor-unshadow => annotation-processor}/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java (100%) diff --git a/annotation-processor-unshadow/build.gradle b/annotation-processor-unshadow/build.gradle deleted file mode 100644 index d0396fbd9..000000000 --- a/annotation-processor-unshadow/build.gradle +++ /dev/null @@ -1,27 +0,0 @@ -plugins { - id 'java-library' - id 'com.diffplug.spotless' -} - -repositories { - mavenCentral() -} - -dependencies { - implementation 'com.google.guava:guava:21.0' - annotationProcessor 'com.google.auto.service:auto-service:1.1.1' - compileOnly 'com.google.auto.service:auto-service:1.1.1' - - implementation project(path: ":annotation-processor") -} - -tasks.withType(JavaCompile) { - options.compilerArgs += '--enable-preview' -} - -spotless { - java { - removeUnusedImports() - } -} -version = '1.1.2' diff --git a/annotation-processor/build.gradle b/annotation-processor/build.gradle index 0ef5aafd6..776dfa723 100644 --- a/annotation-processor/build.gradle +++ b/annotation-processor/build.gradle @@ -1,4 +1,5 @@ plugins { + id 'com.github.johnrengelman.shadow' id 'java-library' id 'com.diffplug.spotless' } @@ -10,11 +11,18 @@ repositories { } dependencies { + annotationProcessor 'com.google.auto.service:auto-service:1.1.1' + compileOnly 'com.google.auto.service:auto-service:1.1.1' + implementation 'com.google.code.gson:gson:2.10.1' + shadow 'com.google.code.gson:gson:2.10.1' implementation 'com.google.auto:auto-common:1.2.1' - // Platform classes -// "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" + shadow 'com.google.auto:auto-common:1.2.1' + implementation 'com.google.guava:guava:21.0' + shadow 'com.google.guava:guava:21.0' + implementation project(":annotations") + shadow project(":annotations") } tasks.withType(JavaCompile) { @@ -22,6 +30,10 @@ tasks.withType(JavaCompile) { options.release = 17 } +shadowJar { + include 'META-INF/services/javax.annotation.processing.Processor' +} + spotless { java { removeUnusedImports() diff --git a/annotation-processor-unshadow/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java similarity index 100% rename from annotation-processor-unshadow/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java rename to annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java diff --git a/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle b/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle index 782ba2c93..2997c5cd5 100644 --- a/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle +++ b/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle @@ -17,7 +17,7 @@ dependencies { } } implementation project(":annotations") - annotationProcessor project(":annotation-processor-unshadow") + annotationProcessor project(path: ":annotation-processor", configuration: 'shadow') } project.sourceSets { diff --git a/settings.gradle b/settings.gradle index 508e8db8f..37fd13682 100644 --- a/settings.gradle +++ b/settings.gradle @@ -15,7 +15,6 @@ pluginManagement { } include("annotation-processor") -include("annotation-processor-unshadow") include("annotations") include("test_agent") include("common") From e69ab1fef28cf32f55627f02e40d29d13cda6ac0 Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Sat, 16 Dec 2023 16:45:13 -0800 Subject: [PATCH 40/45] Customize reshadowing of dependencies Refactor AP detection --- annotation-processor/build.gradle | 18 +++ .../annotation/ClientMixinValidator.java | 129 ++++++++++-------- 2 files changed, 87 insertions(+), 60 deletions(-) diff --git a/annotation-processor/build.gradle b/annotation-processor/build.gradle index 776dfa723..223d94bc7 100644 --- a/annotation-processor/build.gradle +++ b/annotation-processor/build.gradle @@ -23,6 +23,11 @@ dependencies { implementation project(":annotations") shadow project(":annotations") + // Shadow annotations + implementation 'net.fabricmc:sponge-mixin:0.12.5+' + implementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" + implementation 'net.minecraftforge:mergetool:1.1.7' + implementation 'net.neoforged:mergetool:2.0.2' } tasks.withType(JavaCompile) { @@ -31,7 +36,20 @@ tasks.withType(JavaCompile) { } shadowJar { + dependencies { + include(dependency('net.fabricmc:sponge-mixin:')) + include(dependency('net.fabricmc:fabric-loader:')) + include(dependency(':mergetool:')) + } + // shadowJar bug + include '*.jar' include 'META-INF/services/javax.annotation.processing.Processor' + include 'org/spongepowered/asm/mixin/Mixin.class' + include 'org/fury_phoenix/**/*' + include {it.getName() == 'OnlyIn.class'} + include {it.getName() == 'Dist.class'} + include {it.getName() == 'Environment.class'} + include {it.getName() == 'EnvType.class'} } spotless { diff --git a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java index 7f534710b..e21b4b791 100644 --- a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java +++ b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java @@ -3,13 +3,16 @@ import java.lang.annotation.Annotation; import java.util.Collection; import java.util.HashSet; -import java.util.Optional; +import java.util.List; +import java.util.Map; import java.util.Set; +import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; import javax.annotation.processing.Messager; import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.AnnotationValue; import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; import javax.lang.model.util.Elements; @@ -18,17 +21,12 @@ import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.util.asm.IAnnotationHandle; -import org.spongepowered.tools.obfuscation.AnnotatedMixinsAccessor; -import org.spongepowered.tools.obfuscation.interfaces.ITypeHandleProvider; -import org.spongepowered.tools.obfuscation.mirror.TypeHandle; +import static com.google.auto.common.AnnotationMirrors.getAnnotationValue; import static java.util.AbstractMap.SimpleImmutableEntry; public class ClientMixinValidator { - private final ITypeHandleProvider typeHandleProvider; - private final Messager messager; private final Elements elemUtils; @@ -37,16 +35,33 @@ public class ClientMixinValidator { private final boolean debug; - private static final Iterable markers = Set.of( - "net.fabricmc.api.Environment", - "net.minecraftforge.api.distmarker.OnlyIn", - "net.neoforged.api.distmarker.OnlyIn"); + /* + * @author Fury_Phoenix + * @reason This is covariant for ClientMixinValidator.markers + * whilst the direct reference is not as it doesn't cover Annotation + */ + private static final Function + EnvironmentAccessor = net.fabricmc.api.Environment::value; + + private static final Function + ForgeAccessor = net.minecraftforge.api.distmarker.OnlyIn::value; + + private static final Function + NeoForgeAccessor = net.neoforged.api.distmarker.OnlyIn::value; + + /* + * @author Fury_Phoenix + * @reason Partial duck-typing + */ + private static final Map + , Function> + markers = Map.of(net.fabricmc.api.Environment.class, EnvironmentAccessor, + net.minecraftforge.api.distmarker.OnlyIn.class, ForgeAccessor, + net.neoforged.api.distmarker.OnlyIn.class, NeoForgeAccessor); private static final Collection unannotatedClasses = new HashSet<>(); - public ClientMixinValidator(ProcessingEnvironment env) - throws ReflectiveOperationException { - typeHandleProvider = AnnotatedMixinsAccessor.getMixinAP(env); + public ClientMixinValidator(ProcessingEnvironment env) { debug = Boolean.valueOf(env.getOptions().get("org.fury_phoenix.mixinAp.validator.debug")); messager = env.getMessager(); elemUtils = env.getElementUtils(); @@ -55,14 +70,11 @@ public ClientMixinValidator(ProcessingEnvironment env) public boolean validateMixin(TypeElement annotatedMixinClass) { return targetsClient(annotatedMixinClass) && - !getAnnotationHandle(annotatedMixinClass, ClientOnlyMixin.class).exists(); + (annotatedMixinClass.getAnnotation(ClientOnlyMixin.class) == null); } public boolean targetsClient(TypeElement annotatedMixinClass) { - return targetsClient( - ClientMixinValidator.getTargets( - getAnnotationHandle(annotatedMixinClass, Mixin.class) - )); + return targetsClient(getTargets(annotatedMixinClass)); } private boolean targetsClient(Collection classTargets) { @@ -91,14 +103,15 @@ private boolean targetsClient(Object classTarget) { } private boolean isClientMarked(TypeElement te) { - for (var marker : getPlatformMarkers(markers)) { - IAnnotationHandle handle = getAnnotationHandle(te, marker); - if(!handle.exists()) continue; - - String[] enumValue = handle.getValue("value"); - if(enumValue==null) continue; - - return enumValue[1].equals("CLIENT"); + for (var entry : markers.entrySet()) { + var marker = te.getAnnotation(entry.getKey()); + if(marker == null) continue; + + // Pretend to accept Annotations + @SuppressWarnings("unchecked") + boolean isClient = ((Function)entry.getValue()) + .apply(marker).toString().equals("CLIENT"); + return isClient; } if(debug && unannotatedClasses.add(te.toString())) { messager.printMessage(Diagnostic.Kind.WARNING, @@ -117,9 +130,8 @@ private boolean warn(Object o) { getEntry(TypeElement annotatedMixinClass) { return new SimpleImmutableEntry<>( annotatedMixinClass.getQualifiedName(), - ClientMixinValidator.getTargets( - getAnnotationHandle(annotatedMixinClass, Mixin.class) - ).stream() + getTargets(annotatedMixinClass) + .stream() .filter(this::targetsClient) .map(Object::toString) .map(ClientMixinValidator::toSourceString) @@ -127,40 +139,37 @@ private boolean warn(Object o) { ); } - private TypeHandle getTypeHandle(Object annotatedClass) { - return typeHandleProvider.getTypeHandle(annotatedClass); - } - - private IAnnotationHandle getAnnotationHandle - (Object annotatedClass, Class annotation) { - return getTypeHandle(annotatedClass).getAnnotation(annotation); - } - - private static Collection getTargets(IAnnotationHandle mixinAnnotation) { - Collection clzss = mixinAnnotation.getList("value"); - Collection imaginary = mixinAnnotation.getList("targets"); - return Stream.of(clzss, imaginary) + private Collection getTargets(TypeElement mixinAnnotatedClass) { + Collection clzsses = Set.of(); + Collection imaginaries = Set.of(); + TypeMirror MixinElement = elemUtils.getTypeElement(Mixin.class.getName()).asType(); + for (var annotationMirror : mixinAnnotatedClass.getAnnotationMirrors()) { + if(!annotationMirror.getAnnotationType().equals(MixinElement)) + continue; + + @SuppressWarnings("unchecked") + var wrappedClzss = (List) + getAnnotationValue(annotationMirror, "value").getValue(); + + clzsses = wrappedClzss.stream() + .map(AnnotationValue::getValue) + .map(TypeMirror.class::cast) + .collect(Collectors.toSet()); + + @SuppressWarnings("unchecked") + var wrappedStrings = (List) + getAnnotationValue(annotationMirror, "targets").getValue(); + + imaginaries = wrappedStrings.stream() + .map(AnnotationValue::getValue) + .map(String.class::cast) + .collect(Collectors.toSet()); + } + return Stream.of(clzsses, imaginaries) .flatMap(Collection::stream) .collect(Collectors.toList()); } - private static Iterable> - getPlatformMarkers(Iterable markers) { - Set> platformClasses = new HashSet<>(); - for(var marker : markers) { - getMarkerClass(marker).ifPresent(platformClasses::add); - } - return platformClasses; - } - - @SuppressWarnings("unchecked") - private static Optional> getMarkerClass(String marker) { - try { - return Optional.of((Class)Class.forName(marker)); - } catch (ClassNotFoundException e) {} - return Optional.empty(); - } - public static String toSourceString(String bytecodeName) { return bytecodeName.replaceAll("\\/", "."); } From d3968e03a0ff7c2911a2d1c194c9138347a5081e Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Sat, 16 Dec 2023 22:06:33 -0800 Subject: [PATCH 41/45] Tidy up --- .../mixinAp/annotation/ClientMixinValidator.java | 6 +++--- .../org/fury_phoenix/mixinAp/annotation/MixinProcessor.java | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java index e21b4b791..22e72ecff 100644 --- a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java +++ b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java @@ -126,8 +126,8 @@ private boolean warn(Object o) { return false; } - public SimpleImmutableEntry - getEntry(TypeElement annotatedMixinClass) { + public Map.Entry + getClientMixinEntry(TypeElement annotatedMixinClass) { return new SimpleImmutableEntry<>( annotatedMixinClass.getQualifiedName(), getTargets(annotatedMixinClass) @@ -167,7 +167,7 @@ private Collection getTargets(TypeElement mixinAnnotatedClass) { } return Stream.of(clzsses, imaginaries) .flatMap(Collection::stream) - .collect(Collectors.toList()); + .collect(Collectors.toSet()); } public static String toSourceString(String bytecodeName) { diff --git a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java index 307016244..a1ea79839 100644 --- a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java +++ b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java @@ -99,7 +99,7 @@ private void validateCommonMixins(TypeElement annotation, Stream mi // The implementation may throw a CME mixins.sequential() .filter(validator::validateMixin) - .map(validator::getEntry) + .map(validator::getClientMixinEntry) .forEach(this::logClientClassTarget); } From 0836ac6eefefa643018020652664aedde14b8b42 Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Mon, 18 Dec 2023 20:50:09 -0800 Subject: [PATCH 42/45] In the name of type-safety More cleanup and change equality checks --- .../annotation/ClientMixinValidator.java | 68 ++++++++++--------- .../mixinAp/util/TypedAccessorMap.java | 37 ++++++++++ 2 files changed, 72 insertions(+), 33 deletions(-) create mode 100644 annotation-processor/src/main/java/org/fury_phoenix/mixinAp/util/TypedAccessorMap.java diff --git a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java index 22e72ecff..70ddb7523 100644 --- a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java +++ b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java @@ -19,7 +19,10 @@ import javax.lang.model.util.Types; import javax.tools.Diagnostic; +import net.fabricmc.api.Environment; + import org.embeddedt.modernfix.annotation.ClientOnlyMixin; +import org.fury_phoenix.mixinAp.util.TypedAccessorMap; import org.spongepowered.asm.mixin.Mixin; import static com.google.auto.common.AnnotationMirrors.getAnnotationValue; @@ -35,29 +38,32 @@ public class ClientMixinValidator { private final boolean debug; - /* - * @author Fury_Phoenix - * @reason This is covariant for ClientMixinValidator.markers - * whilst the direct reference is not as it doesn't cover Annotation - */ - private static final Function - EnvironmentAccessor = net.fabricmc.api.Environment::value; - - private static final Function - ForgeAccessor = net.minecraftforge.api.distmarker.OnlyIn::value; - - private static final Function - NeoForgeAccessor = net.neoforged.api.distmarker.OnlyIn::value; - - /* - * @author Fury_Phoenix - * @reason Partial duck-typing - */ - private static final Map - , Function> - markers = Map.of(net.fabricmc.api.Environment.class, EnvironmentAccessor, - net.minecraftforge.api.distmarker.OnlyIn.class, ForgeAccessor, - net.neoforged.api.distmarker.OnlyIn.class, NeoForgeAccessor); + private static final TypedAccessorMap markers = new TypedAccessorMap<>(); + + private static final Map.Entry, Function> + FabricAccessor = new SimpleImmutableEntry<>(Environment.class, Environment::value); + + private static final Map.Entry< + Class, + Function> + ForgeAccessor = new SimpleImmutableEntry<>( + net.minecraftforge.api.distmarker.OnlyIn.class, + net.minecraftforge.api.distmarker.OnlyIn::value + ); + + private static final Map.Entry< + Class, + Function> + NeoForgeAccessor = new SimpleImmutableEntry<>( + net.neoforged.api.distmarker.OnlyIn.class, + net.neoforged.api.distmarker.OnlyIn::value + ); + + static { + markers.put(FabricAccessor); + markers.put(ForgeAccessor); + markers.put(NeoForgeAccessor); + } private static final Collection unannotatedClasses = new HashSet<>(); @@ -107,11 +113,7 @@ private boolean isClientMarked(TypeElement te) { var marker = te.getAnnotation(entry.getKey()); if(marker == null) continue; - // Pretend to accept Annotations - @SuppressWarnings("unchecked") - boolean isClient = ((Function)entry.getValue()) - .apply(marker).toString().equals("CLIENT"); - return isClient; + return entry.getValue().apply(marker).toString().equals("CLIENT"); } if(debug && unannotatedClasses.add(te.toString())) { messager.printMessage(Diagnostic.Kind.WARNING, @@ -139,17 +141,17 @@ private boolean warn(Object o) { ); } - private Collection getTargets(TypeElement mixinAnnotatedClass) { + private Collection getTargets(TypeElement annotatedMixinClass) { Collection clzsses = Set.of(); Collection imaginaries = Set.of(); TypeMirror MixinElement = elemUtils.getTypeElement(Mixin.class.getName()).asType(); - for (var annotationMirror : mixinAnnotatedClass.getAnnotationMirrors()) { - if(!annotationMirror.getAnnotationType().equals(MixinElement)) + for (var mirror : annotatedMixinClass.getAnnotationMirrors()) { + if(!types.isSameType(mirror.getAnnotationType(), MixinElement)) continue; @SuppressWarnings("unchecked") var wrappedClzss = (List) - getAnnotationValue(annotationMirror, "value").getValue(); + getAnnotationValue(mirror, "value").getValue(); clzsses = wrappedClzss.stream() .map(AnnotationValue::getValue) @@ -158,7 +160,7 @@ private Collection getTargets(TypeElement mixinAnnotatedClass) { @SuppressWarnings("unchecked") var wrappedStrings = (List) - getAnnotationValue(annotationMirror, "targets").getValue(); + getAnnotationValue(mirror, "targets").getValue(); imaginaries = wrappedStrings.stream() .map(AnnotationValue::getValue) diff --git a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/util/TypedAccessorMap.java b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/util/TypedAccessorMap.java new file mode 100644 index 000000000..5632a9175 --- /dev/null +++ b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/util/TypedAccessorMap.java @@ -0,0 +1,37 @@ +package org.fury_phoenix.mixinAp.util; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.function.Function; + +import static java.util.Map.Entry; + +/** + * Type-safe heterogenous map of accessors + * @author Fury_Phoenix + * @reason Type-safety since K, V of Map are non-identical + * @param The supertype of desired types. + * This is useful in cases such as . + */ +public class TypedAccessorMap { + private final Map, Function> typedAccessors = new HashMap<>(); + + public void put(Class key, Function func) { + Objects.requireNonNull(func); + typedAccessors.put(Objects.requireNonNull(key), o -> func.apply(key.cast(o))); + } + + public void put(Entry, Function> entry) { + put(entry.getKey(), entry.getValue()); + } + + public Function get(Class key) { + return typedAccessors.get(key); + } + + public Set, Function>> entrySet() { + return typedAccessors.entrySet(); + } +} From 65ecdd623138653aad892701ad89dff328a3004f Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Sat, 23 Dec 2023 15:54:55 -0800 Subject: [PATCH 43/45] Add annotation to ignore mixins --- .../mixinAp/annotation/ClientMixinValidator.java | 14 +++++++++++++- annotations/build.gradle | 2 +- .../modernfix/annotation/IgnoreMixin.java | 11 +++++++++++ .../mixin/perf/async_locator/EyeOfEnderAccess.java | 4 ++-- .../mixin/perf/async_locator/EyeOfEnderMixin.java | 4 ++-- 5 files changed, 29 insertions(+), 6 deletions(-) create mode 100644 annotations/src/main/java/org/embeddedt/modernfix/annotation/IgnoreMixin.java diff --git a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java index 70ddb7523..274f69c2d 100644 --- a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java +++ b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java @@ -22,11 +22,13 @@ import net.fabricmc.api.Environment; import org.embeddedt.modernfix.annotation.ClientOnlyMixin; +import org.embeddedt.modernfix.annotation.IgnoreMixin; import org.fury_phoenix.mixinAp.util.TypedAccessorMap; import org.spongepowered.asm.mixin.Mixin; import static com.google.auto.common.AnnotationMirrors.getAnnotationValue; import static java.util.AbstractMap.SimpleImmutableEntry; +import static java.util.function.Predicate.not; public class ClientMixinValidator { @@ -80,7 +82,8 @@ public boolean validateMixin(TypeElement annotatedMixinClass) { } public boolean targetsClient(TypeElement annotatedMixinClass) { - return targetsClient(getTargets(annotatedMixinClass)); + return targetsClient(getTargets(annotatedMixinClass)) && + !isIgnored(annotatedMixinClass); } private boolean targetsClient(Collection classTargets) { @@ -122,6 +125,15 @@ private boolean isClientMarked(TypeElement te) { return false; } + private boolean isIgnored(TypeElement te) { + if(te.getAnnotation(IgnoreMixin.class) != null) { + messager.printMessage(Diagnostic.Kind.WARNING, + toSourceString(te.toString()) + " is ignored!"); + return true; + } + return false; + } + private boolean warn(Object o) { messager.printMessage(Diagnostic.Kind.WARNING, toSourceString(o.toString()) + " can't be loaded, so it is skipped!"); diff --git a/annotations/build.gradle b/annotations/build.gradle index 55eb0c786..5271e5b3d 100644 --- a/annotations/build.gradle +++ b/annotations/build.gradle @@ -3,4 +3,4 @@ plugins { id 'java-library' } -version = '1.0.0' +version = '1.1.0' diff --git a/annotations/src/main/java/org/embeddedt/modernfix/annotation/IgnoreMixin.java b/annotations/src/main/java/org/embeddedt/modernfix/annotation/IgnoreMixin.java new file mode 100644 index 000000000..00ae1fb7a --- /dev/null +++ b/annotations/src/main/java/org/embeddedt/modernfix/annotation/IgnoreMixin.java @@ -0,0 +1,11 @@ +package org.embeddedt.modernfix.annotation; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.SOURCE) +@Target(ElementType.TYPE) +public @interface IgnoreMixin { +} + diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/async_locator/EyeOfEnderAccess.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/async_locator/EyeOfEnderAccess.java index f9750aed7..5f24fa1cd 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/async_locator/EyeOfEnderAccess.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/async_locator/EyeOfEnderAccess.java @@ -1,12 +1,12 @@ package org.embeddedt.modernfix.forge.mixin.perf.async_locator; import net.minecraft.world.entity.projectile.EyeOfEnder; -import org.embeddedt.modernfix.annotation.ClientOnlyMixin; +import org.embeddedt.modernfix.annotation.IgnoreMixin; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; @Mixin(EyeOfEnder.class) -@ClientOnlyMixin +@IgnoreMixin public interface EyeOfEnderAccess { @Accessor void setLife(int life); diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/async_locator/EyeOfEnderMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/async_locator/EyeOfEnderMixin.java index 8c29370a3..7b1463f88 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/async_locator/EyeOfEnderMixin.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/async_locator/EyeOfEnderMixin.java @@ -1,7 +1,7 @@ package org.embeddedt.modernfix.forge.mixin.perf.async_locator; import net.minecraft.world.entity.projectile.EyeOfEnder; -import org.embeddedt.modernfix.annotation.ClientOnlyMixin; +import org.embeddedt.modernfix.annotation.IgnoreMixin; import org.embeddedt.modernfix.forge.structure.logic.EyeOfEnderData; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -9,7 +9,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(EyeOfEnder.class) -@ClientOnlyMixin +@IgnoreMixin public class EyeOfEnderMixin implements EyeOfEnderData { private boolean locateTaskOngoing = false; From cfae648209f72966928e73c7ab42f4f983b43540 Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Sun, 24 Dec 2023 13:59:40 -0800 Subject: [PATCH 44/45] Remove throws declaration --- .../org/fury_phoenix/mixinAp/annotation/MixinProcessor.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java index a1ea79839..747f8865f 100644 --- a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java +++ b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java @@ -64,8 +64,7 @@ public boolean process(Set annotations, RoundEnvironment return false; } - private void processMixins(Set annotations, RoundEnvironment roundEnv) - throws ReflectiveOperationException { + private void processMixins(Set annotations, RoundEnvironment roundEnv) { for (TypeElement annotation : annotations) { Set annotatedMixins = roundEnv.getElementsAnnotatedWith(annotation); @@ -91,8 +90,7 @@ private void filterMixinSets() { commonSet.removeAll(mixinConfigList.get("client")); } - private void validateCommonMixins(TypeElement annotation, Stream mixins) - throws ReflectiveOperationException { + private void validateCommonMixins(TypeElement annotation, Stream mixins) { if(!annotation.getSimpleName().toString().equals("Mixin")) return; ClientMixinValidator validator = new ClientMixinValidator(processingEnv); From bf9d45f5ec112b38e4130188f38799c55a0a9bec Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Sun, 24 Dec 2023 14:23:29 -0800 Subject: [PATCH 45/45] Spotless --- .../fury_phoenix/mixinAp/annotation/ClientMixinValidator.java | 1 - 1 file changed, 1 deletion(-) diff --git a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java index 274f69c2d..139c6b20e 100644 --- a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java +++ b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java @@ -28,7 +28,6 @@ import static com.google.auto.common.AnnotationMirrors.getAnnotationValue; import static java.util.AbstractMap.SimpleImmutableEntry; -import static java.util.function.Predicate.not; public class ClientMixinValidator {