In the name of type-safety

More cleanup and change equality checks
This commit is contained in:
Fury_Phoenix 2023-12-18 20:50:09 -08:00
parent d3968e03a0
commit 0836ac6eef
No known key found for this signature in database
GPG Key ID: 0595F98084987DB8
2 changed files with 69 additions and 30 deletions

View File

@ -19,7 +19,10 @@ import javax.lang.model.util.Elements;
import javax.lang.model.util.Types; import javax.lang.model.util.Types;
import javax.tools.Diagnostic; import javax.tools.Diagnostic;
import net.fabricmc.api.Environment;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.fury_phoenix.mixinAp.util.TypedAccessorMap;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import static com.google.auto.common.AnnotationMirrors.getAnnotationValue; import static com.google.auto.common.AnnotationMirrors.getAnnotationValue;
@ -35,29 +38,32 @@ public class ClientMixinValidator {
private final boolean debug; private final boolean debug;
/* private static final TypedAccessorMap<Annotation> markers = new TypedAccessorMap<>();
* @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<net.fabricmc.api.Environment, ?>
EnvironmentAccessor = net.fabricmc.api.Environment::value;
private static final Function<net.minecraftforge.api.distmarker.OnlyIn, ?> private static final Map.Entry<Class<Environment>, Function<? super Environment, ?>>
ForgeAccessor = net.minecraftforge.api.distmarker.OnlyIn::value; FabricAccessor = new SimpleImmutableEntry<>(Environment.class, Environment::value);
private static final Function<net.neoforged.api.distmarker.OnlyIn, ?> private static final Map.Entry<
NeoForgeAccessor = net.neoforged.api.distmarker.OnlyIn::value; Class<net.minecraftforge.api.distmarker.OnlyIn>,
Function<? super net.minecraftforge.api.distmarker.OnlyIn, ?>>
ForgeAccessor = new SimpleImmutableEntry<>(
net.minecraftforge.api.distmarker.OnlyIn.class,
net.minecraftforge.api.distmarker.OnlyIn::value
);
/* private static final Map.Entry<
* @author Fury_Phoenix Class<net.neoforged.api.distmarker.OnlyIn>,
* @reason Partial duck-typing Function<? super net.neoforged.api.distmarker.OnlyIn, ?>>
*/ NeoForgeAccessor = new SimpleImmutableEntry<>(
private static final Map net.neoforged.api.distmarker.OnlyIn.class,
<Class<? extends Annotation>, Function<? extends Annotation, ?>> net.neoforged.api.distmarker.OnlyIn::value
markers = Map.of(net.fabricmc.api.Environment.class, EnvironmentAccessor, );
net.minecraftforge.api.distmarker.OnlyIn.class, ForgeAccessor,
net.neoforged.api.distmarker.OnlyIn.class, NeoForgeAccessor); static {
markers.put(FabricAccessor);
markers.put(ForgeAccessor);
markers.put(NeoForgeAccessor);
}
private static final Collection<String> unannotatedClasses = new HashSet<>(); private static final Collection<String> unannotatedClasses = new HashSet<>();
@ -107,11 +113,7 @@ public class ClientMixinValidator {
var marker = te.getAnnotation(entry.getKey()); var marker = te.getAnnotation(entry.getKey());
if(marker == null) continue; if(marker == null) continue;
// Pretend to accept Annotations return entry.getValue().apply(marker).toString().equals("CLIENT");
@SuppressWarnings("unchecked")
boolean isClient = ((Function<Annotation, ?>)entry.getValue())
.apply(marker).toString().equals("CLIENT");
return isClient;
} }
if(debug && unannotatedClasses.add(te.toString())) { if(debug && unannotatedClasses.add(te.toString())) {
messager.printMessage(Diagnostic.Kind.WARNING, messager.printMessage(Diagnostic.Kind.WARNING,
@ -139,17 +141,17 @@ public class ClientMixinValidator {
); );
} }
private Collection<Object> getTargets(TypeElement mixinAnnotatedClass) { private Collection<Object> getTargets(TypeElement annotatedMixinClass) {
Collection<? extends TypeMirror> clzsses = Set.of(); Collection<? extends TypeMirror> clzsses = Set.of();
Collection<? extends String> imaginaries = Set.of(); Collection<? extends String> imaginaries = Set.of();
TypeMirror MixinElement = elemUtils.getTypeElement(Mixin.class.getName()).asType(); TypeMirror MixinElement = elemUtils.getTypeElement(Mixin.class.getName()).asType();
for (var annotationMirror : mixinAnnotatedClass.getAnnotationMirrors()) { for (var mirror : annotatedMixinClass.getAnnotationMirrors()) {
if(!annotationMirror.getAnnotationType().equals(MixinElement)) if(!types.isSameType(mirror.getAnnotationType(), MixinElement))
continue; continue;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
var wrappedClzss = (List<? extends AnnotationValue>) var wrappedClzss = (List<? extends AnnotationValue>)
getAnnotationValue(annotationMirror, "value").getValue(); getAnnotationValue(mirror, "value").getValue();
clzsses = wrappedClzss.stream() clzsses = wrappedClzss.stream()
.map(AnnotationValue::getValue) .map(AnnotationValue::getValue)
@ -158,7 +160,7 @@ public class ClientMixinValidator {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
var wrappedStrings = (List<? extends AnnotationValue>) var wrappedStrings = (List<? extends AnnotationValue>)
getAnnotationValue(annotationMirror, "targets").getValue(); getAnnotationValue(mirror, "targets").getValue();
imaginaries = wrappedStrings.stream() imaginaries = wrappedStrings.stream()
.map(AnnotationValue::getValue) .map(AnnotationValue::getValue)

View File

@ -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 <SuperType> The supertype of desired types.
* This is useful in cases such as <A extends Annotation>.
*/
public class TypedAccessorMap<SuperType> {
private final Map<Class<? extends SuperType>, Function<Object, ?>> typedAccessors = new HashMap<>();
public <T extends SuperType> void put(Class<T> key, Function<? super T, ?> func) {
Objects.requireNonNull(func);
typedAccessors.put(Objects.requireNonNull(key), o -> func.apply(key.cast(o)));
}
public <T extends SuperType> void put(Entry<Class<T>, Function<? super T, ?>> entry) {
put(entry.getKey(), entry.getValue());
}
public <T extends SuperType> Function<Object, ?> get(Class<T> key) {
return typedAccessors.get(key);
}
public Set<Entry<Class<? extends SuperType>, Function<Object, ?>>> entrySet() {
return typedAccessors.entrySet();
}
}