Create mixin config AP

- Takes two compiler arguments: -ArootProject.name and an optional -Aproject.name
This commit is contained in:
Phoenix-Starlight 2023-11-22 20:41:09 -08:00 committed by Fury_Phoenix
parent 97ba361867
commit 64348c0bf6
No known key found for this signature in database
GPG Key ID: 0595F98084987DB8
6 changed files with 179 additions and 2 deletions

View File

@ -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'

View File

@ -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<String, String> aliases = Map.of(
"Mixin", "mixins",
"ClientOnlyMixin", "client"
);
private String rootProjectName;
private final Map<String, List<String>> mixinConfigList = new HashMap<>();
@Override
public void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
rootProjectName = processingEnv.getOptions().get("rootProject.name");
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
if(roundEnv.processingOver()){
// set difference of mixins and client
List<String> 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<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
for (TypeElement annotation : annotations) {
Set<? extends Element> annotatedMixins = roundEnv.getElementsAnnotatedWith(annotation);
List<String> 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]);
}
}
}

View File

@ -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<String> commonMixins,
@SerializedName("client")
List<String> clientMixins,
InjectorOptions injectors, OverwriteOptions overwrites
) {
public MixinConfig(String packageName, List<String> commonMixins, List<String> 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);
}
}

View File

@ -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
}

View File

@ -7,6 +7,7 @@ pluginManagement {
}
}
include("annotation-processor")
include("test_agent")
include("common")