Fix platform support
- Prefer TypeElements over TypeMirrors - Add debug option to log classes that couldn't be loaded - Reorganize exception logging
This commit is contained in:
parent
06a02dc445
commit
077f726bae
|
|
@ -17,7 +17,6 @@ dependencies {
|
||||||
compileOnly '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:sponge-mixin:0.12.5+"
|
||||||
implementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
|
|
||||||
implementation project(":annotations")
|
implementation project(":annotations")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -30,4 +29,4 @@ spotless {
|
||||||
removeUnusedImports()
|
removeUnusedImports()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
version = '1.1.0'
|
version = '1.1.1'
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,11 @@
|
||||||
package org.fury_phoenix.mixinAp.annotation;
|
package org.fury_phoenix.mixinAp.annotation;
|
||||||
|
|
||||||
|
import com.google.common.base.Throwables;
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.lang.invoke.*;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
@ -9,10 +13,10 @@ import java.util.stream.Stream;
|
||||||
|
|
||||||
import javax.annotation.processing.Messager;
|
import javax.annotation.processing.Messager;
|
||||||
import javax.annotation.processing.ProcessingEnvironment;
|
import javax.annotation.processing.ProcessingEnvironment;
|
||||||
import javax.lang.model.AnnotatedConstruct;
|
|
||||||
import javax.lang.model.element.TypeElement;
|
import javax.lang.model.element.TypeElement;
|
||||||
import javax.lang.model.type.TypeMirror;
|
import javax.lang.model.type.TypeMirror;
|
||||||
import javax.lang.model.util.Elements;
|
import javax.lang.model.util.Elements;
|
||||||
|
import javax.lang.model.util.Types;
|
||||||
import javax.tools.Diagnostic;
|
import javax.tools.Diagnostic;
|
||||||
|
|
||||||
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
|
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
|
||||||
|
|
@ -28,24 +32,50 @@ public class ClientMixinValidator {
|
||||||
|
|
||||||
private final ITypeHandleProvider typeHandleProvider;
|
private final ITypeHandleProvider typeHandleProvider;
|
||||||
|
|
||||||
private final ProcessingEnvironment processingEnv;
|
|
||||||
|
|
||||||
private final Messager messager;
|
private final Messager messager;
|
||||||
|
|
||||||
private final Elements elemUtils;
|
private final Elements elemUtils;
|
||||||
|
|
||||||
private final Class<? extends Annotation> markerClass = getMarkerClass();
|
private final Types types;
|
||||||
|
|
||||||
private static final Set<String> markers = Set.of(
|
private final boolean debug;
|
||||||
|
|
||||||
|
private final Class<? extends Annotation> markerClass = getMarkerClass(markers);
|
||||||
|
|
||||||
|
private final Class<? extends Enum<?>> markerEnumClass = getMarkerEnumClass(markerEnums);
|
||||||
|
|
||||||
|
private static final Collection<String> markers = Set.of(
|
||||||
"net.fabricmc.api.Environment",
|
"net.fabricmc.api.Environment",
|
||||||
"net.minecraftforge.api.distmarker.OnlyIn",
|
"net.minecraftforge.api.distmarker.OnlyIn",
|
||||||
"net.neoforged.api.distmarker.OnlyIn");
|
"net.neoforged.api.distmarker.OnlyIn");
|
||||||
|
|
||||||
public ClientMixinValidator(ProcessingEnvironment env) {
|
private static final Collection<String> markerEnums = Set.of(
|
||||||
|
"net.fabricmc.api.EnvType",
|
||||||
|
"net.minecraftforge.api.distmarker.Dist",
|
||||||
|
"net.neoforged.api.distmarker.Dist");
|
||||||
|
|
||||||
|
private static final Collection<String> 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);
|
typeHandleProvider = AnnotatedMixinsAccessor.getMixinAP(env);
|
||||||
processingEnv = env;
|
debug = Boolean.valueOf(env.getOptions().get("org.fury_phoenix.mixinAp.validator.debug"));
|
||||||
messager = env.getMessager();
|
messager = env.getMessager();
|
||||||
elemUtils = env.getElementUtils();
|
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) {
|
public boolean validateMixin(TypeElement annotatedMixinClass) {
|
||||||
|
|
@ -61,44 +91,52 @@ public class ClientMixinValidator {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean targetsClient(List<?> classTargets) {
|
private boolean targetsClient(List<?> classTargets) {
|
||||||
return classTargets.stream()
|
return classTargets.stream().anyMatch(this::targetsClient);
|
||||||
.anyMatch(this::targetsClient);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean targetsClient(Object classTarget) {
|
private boolean targetsClient(Object classTarget) {
|
||||||
return switch (classTarget) {
|
return switch (classTarget) {
|
||||||
case TypeMirror tm ->
|
case TypeElement te ->
|
||||||
isClientMarked(tm);
|
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
|
// If you're using a dollar sign in class names you are insane
|
||||||
case String s ->
|
case String s -> {
|
||||||
targetsClient(elemUtils.getTypeElement(toSourceString(s.split("\\$")[0])).asType());
|
var te =
|
||||||
|
elemUtils.getTypeElement(toSourceString(s.split("\\$")[0]));
|
||||||
|
yield te != null ? targetsClient(te) : warn(s);
|
||||||
|
}
|
||||||
default ->
|
default ->
|
||||||
throw new IllegalArgumentException("Unhandled type: " + classTarget.getClass() + "\n"
|
throw new IllegalArgumentException("Unhandled type: "
|
||||||
+ "Stringified contents: " + classTarget.toString());
|
+ classTarget.getClass() + "\n" + "Stringified contents: "
|
||||||
|
+ classTarget.toString());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isClientMarked(AnnotatedConstruct ac) {
|
private boolean isClientMarked(TypeElement te) {
|
||||||
TypeHandle handle = getTypeHandle(ac);
|
Annotation marker = te.getAnnotation(markerClass);
|
||||||
if(handle == null) {
|
if(marker == null) {
|
||||||
messager.printMessage(Diagnostic.Kind.WARNING, "Class can't be loaded! " + ac);
|
if(debug && unannotatedClasses.add(te.toString())) {
|
||||||
|
messager.printMessage(Diagnostic.Kind.WARNING,
|
||||||
|
"Missing " + markerClass.getCanonicalName() + " on " + te + "!");
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
IAnnotationHandle marker = handle.getAnnotation(markerClass);
|
try {
|
||||||
|
Object value = enumValueAccessor.invoke(marker);
|
||||||
if(marker == null) return false;
|
return value.toString().equals("CLIENT");
|
||||||
|
} catch (Throwable e) {
|
||||||
String[] markerEnum = marker.getValue("value");
|
messager.printMessage(Diagnostic.Kind.ERROR, "Fatal error:" +
|
||||||
|
Throwables.getStackTraceAsString(e));
|
||||||
if(markerEnum == null) return false;
|
}
|
||||||
|
return false;
|
||||||
String markerEnumValue = markerEnum[1];
|
|
||||||
return markerEnumValue.toString().equals("CLIENT");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private static Class<? extends Annotation> getMarkerClass() {
|
private static Class<? extends Annotation> getMarkerClass(Collection<String> markerSet) {
|
||||||
for(var annotation : markers) {
|
for(var annotation : markerSet) {
|
||||||
try {
|
try {
|
||||||
return (Class<Annotation>)Class.forName(annotation);
|
return (Class<Annotation>)Class.forName(annotation);
|
||||||
} catch (ClassNotFoundException e) {}
|
} catch (ClassNotFoundException e) {}
|
||||||
|
|
@ -106,8 +144,19 @@ public class ClientMixinValidator {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private static Class<? extends Enum<?>> getMarkerEnumClass(Collection<String> enumSet) {
|
||||||
|
for(var enumClass : enumSet) {
|
||||||
|
try {
|
||||||
|
return (Class<Enum<?>>)Class.forName(enumClass);
|
||||||
|
} catch (ClassNotFoundException e) {}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean warn(Object o) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -117,7 +166,8 @@ public class ClientMixinValidator {
|
||||||
annotatedMixinClass.getQualifiedName(),
|
annotatedMixinClass.getQualifiedName(),
|
||||||
ClientMixinValidator.getTargets(
|
ClientMixinValidator.getTargets(
|
||||||
getAnnotationHandle(annotatedMixinClass, Mixin.class)
|
getAnnotationHandle(annotatedMixinClass, Mixin.class)
|
||||||
).stream().filter(this::targetsClient)
|
).stream()
|
||||||
|
.filter(this::targetsClient)
|
||||||
.map(Object::toString)
|
.map(Object::toString)
|
||||||
.map(ClientMixinValidator::toSourceString)
|
.map(ClientMixinValidator::toSourceString)
|
||||||
.collect(Collectors.joining(", "))
|
.collect(Collectors.joining(", "))
|
||||||
|
|
@ -128,7 +178,8 @@ public class ClientMixinValidator {
|
||||||
return typeHandleProvider.getTypeHandle(annotatedClass);
|
return typeHandleProvider.getTypeHandle(annotatedClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IAnnotationHandle getAnnotationHandle(Object annotatedClass, Class<? extends Annotation> annotation) {
|
private IAnnotationHandle
|
||||||
|
getAnnotationHandle(Object annotatedClass, Class<? extends Annotation> annotation) {
|
||||||
return getTypeHandle(annotatedClass).getAnnotation(annotation);
|
return getTypeHandle(annotatedClass).getAnnotation(annotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package org.fury_phoenix.mixinAp.annotation;
|
package org.fury_phoenix.mixinAp.annotation;
|
||||||
|
|
||||||
import com.google.auto.service.AutoService;
|
import com.google.auto.service.AutoService;
|
||||||
|
import com.google.common.base.Throwables;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
@ -23,7 +24,7 @@ import javax.tools.Diagnostic;
|
||||||
import org.fury_phoenix.mixinAp.config.MixinConfig;
|
import org.fury_phoenix.mixinAp.config.MixinConfig;
|
||||||
|
|
||||||
@SupportedAnnotationTypes({"org.spongepowered.asm.mixin.Mixin", "org.embeddedt.modernfix.annotation.ClientOnlyMixin"})
|
@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)
|
@SupportedSourceVersion(SourceVersion.RELEASE_17)
|
||||||
@AutoService(Processor.class)
|
@AutoService(Processor.class)
|
||||||
public class MixinProcessor extends AbstractProcessor {
|
public class MixinProcessor extends AbstractProcessor {
|
||||||
|
|
@ -38,22 +39,28 @@ public class MixinProcessor extends AbstractProcessor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
|
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
|
||||||
if(roundEnv.processingOver()){
|
try {
|
||||||
filterMixinSets();
|
if(roundEnv.processingOver()){
|
||||||
// create record for serialization, compute package name
|
filterMixinSets();
|
||||||
String packageName = mixinConfigList.get("mixins").get(0).split("(?<=mixin)")[0];
|
// create record for serialization, compute package name
|
||||||
finalizeMixinConfig();
|
String packageName = mixinConfigList.get("mixins").get(0).split("(?<=mixin)")[0];
|
||||||
new MixinConfig(packageName,
|
finalizeMixinConfig();
|
||||||
mixinConfigList.get("mixins"),
|
new MixinConfig(packageName,
|
||||||
mixinConfigList.get("client")
|
mixinConfigList.get("mixins"),
|
||||||
).generateMixinConfig(processingEnv);
|
mixinConfigList.get("client")
|
||||||
} else {
|
).generateMixinConfig(processingEnv);
|
||||||
processMixins(annotations, roundEnv);
|
} else {
|
||||||
|
processMixins(annotations, roundEnv);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Fatal error:" +
|
||||||
|
Throwables.getStackTraceAsString(e));
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processMixins(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
|
private void processMixins(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv)
|
||||||
|
throws ReflectiveOperationException {
|
||||||
for (TypeElement annotation : annotations) {
|
for (TypeElement annotation : annotations) {
|
||||||
Set<? extends Element> annotatedMixins = roundEnv.getElementsAnnotatedWith(annotation);
|
Set<? extends Element> annotatedMixins = roundEnv.getElementsAnnotatedWith(annotation);
|
||||||
|
|
||||||
|
|
@ -78,7 +85,8 @@ public class MixinProcessor extends AbstractProcessor {
|
||||||
commonSet.removeAll(mixinConfigList.get("client"));
|
commonSet.removeAll(mixinConfigList.get("client"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateCommonMixins(TypeElement annotation, Stream<TypeElement> mixins) {
|
private void validateCommonMixins(TypeElement annotation, Stream<TypeElement> mixins)
|
||||||
|
throws ReflectiveOperationException {
|
||||||
if(!annotation.getSimpleName().toString().equals("Mixin"))
|
if(!annotation.getSimpleName().toString().equals("Mixin"))
|
||||||
return;
|
return;
|
||||||
ClientMixinValidator validator = new ClientMixinValidator(processingEnv);
|
ClientMixinValidator validator = new ClientMixinValidator(processingEnv);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
package org.fury_phoenix.mixinAp.config;
|
package org.fury_phoenix.mixinAp.config;
|
||||||
|
|
||||||
import com.google.common.base.Throwables;
|
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
import com.google.gson.annotations.SerializedName;
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
|
@ -10,7 +9,6 @@ import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import javax.annotation.processing.ProcessingEnvironment;
|
import javax.annotation.processing.ProcessingEnvironment;
|
||||||
import javax.tools.Diagnostic;
|
|
||||||
import javax.tools.StandardLocation;
|
import javax.tools.StandardLocation;
|
||||||
|
|
||||||
public record MixinConfig(
|
public record MixinConfig(
|
||||||
|
|
@ -37,12 +35,12 @@ public record MixinConfig(
|
||||||
public static final OverwriteOptions DEFAULT = new OverwriteOptions(true);
|
public static final OverwriteOptions DEFAULT = new OverwriteOptions(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void generateMixinConfig(ProcessingEnvironment env) {
|
public void generateMixinConfig(ProcessingEnvironment env) throws IOException {
|
||||||
try (
|
try (
|
||||||
Writer mixinConfigWriter = env.getFiler()
|
Writer mixinConfigWriter = env.getFiler()
|
||||||
.createResource(StandardLocation.SOURCE_OUTPUT, "",
|
.createResource(StandardLocation.SOURCE_OUTPUT, "",
|
||||||
MixinConfig.computeMixinConfigPath(
|
MixinConfig.computeMixinConfigPath(
|
||||||
env.getOptions().get("rootProject.name"),
|
Optional.of(env.getOptions().get("rootProject.name")),
|
||||||
Optional.ofNullable(env.getOptions().get("project.name"))
|
Optional.ofNullable(env.getOptions().get("project.name"))
|
||||||
)
|
)
|
||||||
).openWriter()
|
).openWriter()
|
||||||
|
|
@ -54,15 +52,12 @@ public record MixinConfig(
|
||||||
|
|
||||||
mixinConfigWriter.write(mixinConfig);
|
mixinConfigWriter.write(mixinConfig);
|
||||||
mixinConfigWriter.write("\n");
|
mixinConfigWriter.write("\n");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) { throw e; }
|
||||||
env.getMessager().printMessage(Diagnostic.Kind.ERROR, "Fatal error:" +
|
|
||||||
Throwables.getStackTraceAsString(e));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String computeMixinConfigPath(String rootProjectName, Optional<String> projectName) {
|
private static String computeMixinConfigPath(Optional<String> rootProjectName, Optional<String> projectName) {
|
||||||
return "resources/" +
|
return "resources/" +
|
||||||
rootProjectName +
|
rootProjectName.get() +
|
||||||
(projectName.isPresent() ? "-" : "") +
|
(projectName.isPresent() ? "-" : "") +
|
||||||
projectName.orElse("") +
|
projectName.orElse("") +
|
||||||
".mixins.json";
|
".mixins.json";
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user