Skip to content

Commit

Permalink
AP: Fix several cases of ASM TypeHandles breaking code that relies on…
Browse files Browse the repository at this point in the history
… Mirror.
  • Loading branch information
LlamaLad7 authored and modmuss50 committed Feb 15, 2023
1 parent c33a48b commit e5d9db4
Show file tree
Hide file tree
Showing 11 changed files with 110 additions and 104 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ public AnnotatedMixin(IMixinAnnotationProcessor ap, TypeElement type) {
this.mappings = this.obf.createMappingConsumer();
this.messager = ap;
this.mixin = type;
this.handle = new TypeHandle(type);
this.handle = new TypeHandle(type, ap.getTypeProvider());
this.methods = new ArrayList<MethodHandle>(this.handle.getMethods());
this.virtual = this.handle.getAnnotation(Pseudo.class).exists();
this.annotation = this.handle.getAnnotation(Mixin.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public void process(AnnotationHandle implementsAnnotation) {
}

try {
TypeHandle iface = new TypeHandle(interfaceAnnotation.<DeclaredType>getValue("iface"));
TypeHandle iface = this.ap.getTypeProvider().getTypeHandle(interfaceAnnotation.<DeclaredType>getValue("iface"));
String prefix = interfaceAnnotation.<String>getValue("prefix");
this.processSoftImplements(remap, iface, prefix);
} catch (Exception ex) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -371,17 +371,13 @@ public AnnotatedMixin getMixin(String mixinType) {
return this.mixins.get(mixinType);
}

public Collection<TypeMirror> getMixinsTargeting(TypeMirror targetType) {
return this.getMixinsTargeting((TypeElement)((DeclaredType)targetType).asElement());
}

public Collection<TypeMirror> getMixinsTargeting(TypeElement targetType) {
List<TypeMirror> minions = new ArrayList<TypeMirror>();
public Collection<TypeHandle> getMixinsTargeting(TypeHandle targetType) {
List<TypeHandle> minions = new ArrayList<TypeHandle>();

for (TypeReference mixin : this.targets.getMixinsTargeting(targetType)) {
TypeHandle handle = mixin.getHandle(this.processingEnv);
if (handle != null && handle.hasTypeMirror()) {
minions.add(handle.getTypeMirror());
TypeHandle handle = mixin.getHandle(this);
if (handle != null) {
minions.add(handle);
}
}

Expand Down Expand Up @@ -710,15 +706,15 @@ public TypeHandle getTypeHandle(String name) {
TypeElement element = this.getTypeElement(name, elements);
if (element != null) {
try {
return new TypeHandle(element);
return new TypeHandle(element, this);
} catch (NullPointerException ex) {
// probably bad package
}
}

if (pkg != null) {
// Couldn't resolve the class, but could resolve the package, so just return an imaginary handle.
return new TypeHandle(pkg, name);
return new TypeHandle(pkg, name, this);
}

// Couldn't even resolve the package, all hope is lost.
Expand Down Expand Up @@ -816,11 +812,11 @@ public TypeHandle getSimulatedHandle(String name, TypeMirror simulatedTarget) {
String pkg = name.substring(0, lastDotPos);
PackageElement packageElement = this.processingEnv.getElementUtils().getPackageElement(pkg);
if (packageElement != null) {
return new TypeHandleSimulated(packageElement, name, simulatedTarget);
return new TypeHandleSimulated(packageElement, name, simulatedTarget, this);
}
}

return new TypeHandleSimulated(name, simulatedTarget);
return new TypeHandleSimulated(name, simulatedTarget, this);
}

/* (non-Javadoc)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@

import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeMirror;

import org.spongepowered.asm.util.asm.IAnnotationHandle;
import org.spongepowered.tools.obfuscation.interfaces.IMessagerSuppressible;
import org.spongepowered.tools.obfuscation.interfaces.IMixinAnnotationProcessor;
import org.spongepowered.tools.obfuscation.interfaces.IMixinValidator;
import org.spongepowered.tools.obfuscation.interfaces.IOptionProvider;
import org.spongepowered.tools.obfuscation.interfaces.ITypeHandleProvider;
import org.spongepowered.tools.obfuscation.mirror.TypeHandle;

/**
Expand All @@ -57,7 +57,12 @@ public abstract class MixinValidator implements IMixinValidator {
* Option provider
*/
protected final IOptionProvider options;


/**
* Type handle provider
*/
protected final ITypeHandleProvider typeHandleProvider;

/**
* Pass to run this validator in
*/
Expand All @@ -73,6 +78,7 @@ public MixinValidator(IMixinAnnotationProcessor ap, ValidationPass pass) {
this.processingEnv = ap.getProcessingEnvironment();
this.messager = ap;
this.options = ap;
this.typeHandleProvider = ap.getTypeProvider();
this.pass = pass;
}

Expand All @@ -94,7 +100,7 @@ public final boolean validate(ValidationPass pass, TypeElement mixin, IAnnotatio

protected abstract boolean validate(TypeElement mixin, IAnnotationHandle annotation, Collection<TypeHandle> targets);

protected final Collection<TypeMirror> getMixinsTargeting(TypeMirror targetType) {
protected final Collection<TypeHandle> getMixinsTargeting(TypeHandle targetType) {
return AnnotatedMixins.getMixinsForEnvironment(this.processingEnv).getMixinsTargeting(targetType);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -196,13 +196,13 @@ public MappingMethod getObfMethod(ITargetSelectorRemappable method) {
}

// See if we can get the superclass from the reference
TypeMirror superClass = type.getElement().getSuperclass();
if (superClass.getKind() != TypeKind.DECLARED) {
TypeHandle superClass = type.getSuperclass();
if (superClass == null) {
return null;
}

// Well we found it, let's inflect the class name and recurse the search
String superClassName = ((TypeElement)((DeclaredType)superClass).asElement()).getQualifiedName().toString();
String superClassName = superClass.getSimpleName();
return this.getObfMethod(method.move(superClassName.replace('.', '/')));
}

Expand Down
10 changes: 0 additions & 10 deletions src/ap/java/org/spongepowered/tools/obfuscation/TargetMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -135,16 +135,6 @@ void addMixin(TypeReference target, TypeReference mixin) {
Set<TypeReference> mixins = this.getMixinsFor(target);
mixins.add(mixin);
}

/**
* Get mixin classes which target the specified class
*
* @param target Target class
* @return Collection of mixins registered as targetting the specified class
*/
Collection<TypeReference> getMixinsTargeting(TypeElement target) {
return this.getMixinsTargeting(new TypeHandle(target));
}

/**
* Get mixin classes which target the specified class
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import org.spongepowered.asm.obfuscation.mapping.common.MappingMethod;
import org.spongepowered.asm.util.Bytecode;
import org.spongepowered.asm.util.asm.IAnnotationHandle;
import org.spongepowered.tools.obfuscation.interfaces.ITypeHandleProvider;
import org.spongepowered.tools.obfuscation.mirror.mapping.MappingMethodResolvable;

import com.google.common.collect.ImmutableList;
Expand Down Expand Up @@ -71,6 +72,12 @@ public class TypeHandle {
* Actual type element, this is null for inaccessible classes
*/
private final TypeElement element;

/**
* Type handle provider, we need this since we have to resolve type handles
* for related classes (eg. superclass) without using mirror
*/
protected final ITypeHandleProvider typeProvider;

/**
* Reference to this handle, for serialisation
Expand All @@ -84,30 +91,32 @@ public class TypeHandle {
* @param pkg Package
* @param name FQ class name
*/
public TypeHandle(PackageElement pkg, String name) {
public TypeHandle(PackageElement pkg, String name, ITypeHandleProvider typeProvider) {
this.name = name.replace('.', '/');
this.pkg = pkg;
this.element = null;
this.typeProvider = typeProvider;
}

/**
* Ctor for real elements
*
* @param element ze element
*/
public TypeHandle(TypeElement element) {
public TypeHandle(TypeElement element, ITypeHandleProvider typeProvider) {
this.pkg = TypeUtils.getPackage(element);
this.name = TypeUtils.getInternalName(element);
this.element = element;
this.typeProvider = typeProvider;
}

/**
* Ctor for real elements, instanced via a type mirror
*
* @param type type
*/
public TypeHandle(DeclaredType type) {
this((TypeElement)type.asElement());
public TypeHandle(DeclaredType type, ITypeHandleProvider typeProvider) {
this((TypeElement)type.asElement(), typeProvider);
}

/* (non-Javadoc)
Expand Down Expand Up @@ -215,7 +224,7 @@ public TypeHandle getSuperclass() {
return null;
}

return new TypeHandle((DeclaredType)superClass);
return typeProvider.getTypeHandle(superClass);
}

/**
Expand All @@ -228,7 +237,7 @@ public List<TypeHandle> getInterfaces() {

Builder<TypeHandle> list = ImmutableList.<TypeHandle>builder();
for (TypeMirror iface : this.getTargetElement().getInterfaces()) {
list.add(new TypeHandle((DeclaredType)iface));
list.add(typeProvider.getTypeHandle(iface));
}
return list.build();
}
Expand Down Expand Up @@ -275,6 +284,34 @@ public boolean isImaginary() {
public boolean isSimulated() {
return false;
}

/**
* Gets whether this handle definitely does not represent an interface
*/
public boolean isNotInterface() {
TypeElement target = this.getTargetElement();
return target != null && !target.getKind().isInterface();
}

/**
* Gets whether this handle is the same as or a supertype of the other handle
*/
public boolean isAssignableFrom(TypeHandle other) {
if (this.getName().equals(other.getName())) {
return true;
}
List<TypeHandle> superTypes = new ArrayList<>();
if (other.getSuperclass() != null) {
superTypes.add(other.getSuperclass());
}
superTypes.addAll(other.getInterfaces());
for (TypeHandle superType : superTypes) {
if (this.isAssignableFrom(superType)) {
return true;
}
}
return false;
}

/**
* Get the TypeReference for this type, used for serialisation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,6 @@ public class TypeHandleASM extends TypeHandle {
* ClassNode used for accessing information when not accessible via mirror
*/
private final ClassNode classNode;

/**
* Type handle provider, we need this since we have to resolve type handles
* for related classes (eg. superclass) without using mirror
*/
private final ITypeHandleProvider typeProvider;

/**
* Ctor for imaginary elements, require the enclosing package and the FQ
Expand All @@ -91,9 +85,8 @@ public class TypeHandleASM extends TypeHandle {
* @param name FQ class name
*/
protected TypeHandleASM(PackageElement pkg, String name, ClassNode classNode, ITypeHandleProvider typeProvider) {
super(pkg, name);
super(pkg, name, typeProvider);
this.classNode = classNode;
this.typeProvider = typeProvider;
}

/* (non-Javadoc)
Expand Down Expand Up @@ -146,8 +139,10 @@ public TypeMirror getTypeMirror() {
*/
@Override
public TypeHandle getSuperclass() {
TypeHandle superClass = this.typeProvider.getTypeHandle(this.classNode.superName);
return superClass;
if (this.classNode.superName == null) {
return null;
}
return this.typeProvider.getTypeHandle(this.classNode.superName);
}

/* (non-Javadoc)
Expand Down Expand Up @@ -196,6 +191,14 @@ public boolean isImaginary() {
return false;
}

/* (non-Javadoc)
* @see org.spongepowered.tools.obfuscation.mirror.TypeHandle#isInterface()
*/
@Override
public boolean isNotInterface() {
return (this.classNode.access & Opcodes.ACC_INTERFACE) == 0;
}

/* (non-Javadoc)
* @see org.spongepowered.tools.obfuscation.mirror.TypeHandle#findDescriptor
* (org.spongepowered.asm.mixin.injection.selectors.ITargetSelectorByName)
Expand Down Expand Up @@ -272,7 +275,11 @@ public static TypeHandle of(PackageElement pkg, String name, IMixinAnnotationPro
InputStream is = null;
try {
Filer filer = ap.getProcessingEnvironment().getFiler();
is = filer.getResource(StandardLocation.CLASS_PATH, pkg.getQualifiedName(), name + ".class").openInputStream();
try {
is = filer.getResource(StandardLocation.CLASS_PATH, pkg.getQualifiedName(), name + ".class").openInputStream();
} catch (FileNotFoundException ignored) {
is = filer.getResource(StandardLocation.PLATFORM_CLASS_PATH, pkg.getQualifiedName(), name + ".class").openInputStream();
}
ClassNode classNode = new ClassNode();
new ClassReader(is).accept(classNode, 0);
TypeHandleASM typeHandle = new TypeHandleASM(pkg, fqName, classNode, ap.getTypeProvider());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.spongepowered.asm.mixin.injection.selectors.ITargetSelectorByName;
import org.spongepowered.asm.obfuscation.mapping.common.MappingMethod;
import org.spongepowered.asm.util.SignaturePrinter;
import org.spongepowered.tools.obfuscation.interfaces.ITypeHandleProvider;

/**
* A simulated type handle, used with virtual (pseudo) mixins. For obfuscation
Expand All @@ -48,12 +49,12 @@ public class TypeHandleSimulated extends TypeHandle {

private final TypeElement simulatedType;

public TypeHandleSimulated(String name, TypeMirror type) {
this(TypeUtils.getPackage(type), name, type);
public TypeHandleSimulated(String name, TypeMirror type, ITypeHandleProvider typeProvider) {
this(TypeUtils.getPackage(type), name, type, typeProvider);
}

public TypeHandleSimulated(PackageElement pkg, String name, TypeMirror type) {
super(pkg, name);
public TypeHandleSimulated(PackageElement pkg, String name, TypeMirror type, ITypeHandleProvider typeProvider) {
super(pkg, name, typeProvider);
this.simulatedType = (TypeElement)((DeclaredType)type).asElement();
}

Expand Down Expand Up @@ -152,14 +153,14 @@ public MappingMethod getMappingMethod(String name, String desc) {
String rawSignature = TypeUtils.stripGenerics(signature);

// Try to locate a member anywhere in the hierarchy which matches
MethodHandle method = TypeHandleSimulated.findMethodRecursive(this, name, signature, rawSignature, true);
MethodHandle method = TypeHandleSimulated.findMethodRecursive(this, name, signature, rawSignature, true, this.typeProvider);

// If we find one, return it otherwise just simulate the method
return method != null ? method.asMapping(true) : super.getMappingMethod(name, desc);

}

private static MethodHandle findMethodRecursive(TypeHandle target, String name, String signature, String rawSignature, boolean matchCase) {
private static MethodHandle findMethodRecursive(TypeHandle target, String name, String signature, String rawSignature, boolean matchCase, ITypeHandleProvider typeProvider) {
TypeElement elem = target.getTargetElement();
if (elem == null) {
return null;
Expand All @@ -171,7 +172,7 @@ private static MethodHandle findMethodRecursive(TypeHandle target, String name,
}

for (TypeMirror iface : elem.getInterfaces()) {
method = TypeHandleSimulated.findMethodRecursive(iface, name, signature, rawSignature, matchCase);
method = TypeHandleSimulated.findMethodRecursive(iface, name, signature, rawSignature, matchCase, typeProvider);
if (method != null) {
return method;
}
Expand All @@ -182,15 +183,14 @@ private static MethodHandle findMethodRecursive(TypeHandle target, String name,
return null;
}

return TypeHandleSimulated.findMethodRecursive(superClass, name, signature, rawSignature, matchCase);
return TypeHandleSimulated.findMethodRecursive(superClass, name, signature, rawSignature, matchCase, typeProvider);
}

private static MethodHandle findMethodRecursive(TypeMirror target, String name, String signature, String rawSignature, boolean matchCase) {
private static MethodHandle findMethodRecursive(TypeMirror target, String name, String signature, String rawSignature, boolean matchCase, ITypeHandleProvider typeProvider) {
if (!(target instanceof DeclaredType)) {
return null;
}
TypeElement element = (TypeElement)((DeclaredType)target).asElement();
return TypeHandleSimulated.findMethodRecursive(new TypeHandle(element), name, signature, rawSignature, matchCase);
return TypeHandleSimulated.findMethodRecursive(typeProvider.getTypeHandle(target), name, signature, rawSignature, matchCase, typeProvider);
}

}
Loading

0 comments on commit e5d9db4

Please sign in to comment.