Skip to content

Commit

Permalink
Allow name to match full descriptors and improve printing
Browse files Browse the repository at this point in the history
  • Loading branch information
Bawnorton committed Mar 21, 2024
1 parent 513b8fd commit aada49b
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 37 deletions.
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ allprojects {
apply(plugin = "maven-publish")

group = "com.bawnorton"
version = "0.1.2-beta.4"
version = "0.1.2-beta.5"

repositories {
mavenCentral()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,7 @@ public abstract class MixinCancellerRegistrar {
private static final ILogger LOGGER = MixinService.getService().getLogger("mixinsquared");

public static boolean shouldCancel(List<String> targetClassNames, String mixinClassName) {
return cancellers.stream().anyMatch(canceller -> {
if(canceller.shouldCancel(targetClassNames, mixinClassName)) {
return true;
} else if(canceller.shouldCancel(targetClassNames.stream().map(s -> s.replaceAll("\\.", "/")).collect(Collectors.toList()), "")) {
LOGGER.warn("Canceller {} is matching with a deprecated target class format, use \".\" instead of \"/\"", canceller.getClass().getName());
return true;
}
return false;
});
return cancellers.stream().anyMatch(canceller -> canceller.shouldCancel(targetClassNames, mixinClassName));
}

public static void register(MixinCanceller canceller) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,29 +26,38 @@

import com.bawnorton.mixinsquared.TargetHandler;
import org.objectweb.asm.tree.AnnotationNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode;
import org.spongepowered.asm.mixin.injection.selectors.*;
import org.spongepowered.asm.mixin.injection.struct.MemberInfo;
import org.spongepowered.asm.mixin.struct.SpecialMethodInfo;
import org.spongepowered.asm.mixin.transformer.ClassInfo;
import org.spongepowered.asm.mixin.transformer.meta.MixinMerged;
import org.spongepowered.asm.service.MixinService;
import org.spongepowered.asm.util.Annotations;
import org.spongepowered.asm.util.PrettyPrinter;
import org.spongepowered.asm.util.asm.IAnnotatedElement;
import org.spongepowered.asm.util.asm.MethodNodeEx;
import java.io.IOException;
import java.util.List;
import java.util.Set;

@ITargetSelectorDynamic.SelectorId("Handler")
public final class DynamicSelectorHandler implements ITargetSelectorDynamic {
private final String mixinName;

private final String name;

private final String desc;

private final String prefix;

private final boolean print;

private final PrettyPrinter printer = new PrettyPrinter();

public DynamicSelectorHandler(String mixinName, String name, String prefix, boolean print) {
public DynamicSelectorHandler(String mixinName, MemberInfo memberInfo, String prefix, boolean print) {
this.mixinName = mixinName;
this.name = name;
this.name = memberInfo.getName();
this.desc = memberInfo.getDesc();
this.prefix = prefix == null ? null : prefix.isEmpty() ? null : prefix;
this.print = print;
}
Expand All @@ -66,7 +75,15 @@ public static DynamicSelectorHandler parse(String input, ISelectorContext contex
} else {
throw new AssertionError("Could not get annotation for method");
}
return new DynamicSelectorHandler(Annotations.getValue(annotationNode, "mixin"), Annotations.getValue(annotationNode, "name"), Annotations.getValue(annotationNode, "prefix", ""), Annotations.getValue(annotationNode, "print", Boolean.FALSE));

String name = Annotations.getValue(annotationNode, "name");
MemberInfo memberInfo = MemberInfo.parse(name, context);

String mixin = Annotations.getValue(annotationNode, "mixin");
String prefix = Annotations.getValue(annotationNode, "prefix", "");
boolean print = Annotations.getValue(annotationNode, "print", Boolean.FALSE);

return new DynamicSelectorHandler(mixin, memberInfo, prefix, print);
}

@Override
Expand All @@ -89,14 +106,42 @@ public ITargetSelector attach(ISelectorContext context) throws InvalidSelectorEx
if (context.getMixin().getClassName().equals(mixinName)) {
throw new InvalidSelectorException("Dynamic selector targets self!");
}
if (print) {
printer.kvWidth(20)
.kv("Mixin", mixinName)
.kv("Name", name)
.kv("Prefix", prefix)
.add("%100s %-15s %-50s %s", "MIXIN", "PREFIX", "ORIGINAL NAME", "CANDIDATE")
.print(System.err);
if(!print) return this;

PrettyPrinter printer = new PrettyPrinter();
printer.kvWidth(20);
printer.kv("Target Mixin", mixinName);
printer.kv("Target Method", name);
printer.kv("Target Desc", desc == null ? "None" : desc);
printer.kv("Target Prefix", prefix == null ? "None" : prefix);
printer.kv("Print", "Print is enabled, matching disabled!");
printer.hr();

if(!(context instanceof SpecialMethodInfo)) return this;
SpecialMethodInfo specialMethodInfo = (SpecialMethodInfo) context;

ClassNode classNode = specialMethodInfo.getClassNode();
List<MethodNode> methods = classNode.methods;
for(MethodNode method : methods) {
if(!(method instanceof MethodNodeEx)) continue;
MethodNodeEx methodNodeEx = (MethodNodeEx) method;

String originalName = methodNodeEx.getOriginalName();
String prefix = method.name.split("\\$")[0];
String originalDesc = method.desc;
printer.kv("Name", originalName + ";" + originalDesc);
printer.kv("Prefix", prefix);
String candidateType = "NO";
MatchResult matchResult = matchInternal(mixinName, originalName, originalDesc, prefix);
if(matchResult == MatchResult.EXACT_MATCH) {
candidateType = "YES";
} else if(matchResult == MatchResult.MATCH) {
candidateType = "PARTIAL";
}
printer.kv("Candidate", candidateType);
printer.hr('-');
}
printer.print(System.err);
return this;
}

Expand All @@ -112,31 +157,28 @@ public int getMaxMatchCount() {

@Override
public <TNode> MatchResult match(ElementNode<TNode> node) {
if(print) return MatchResult.NONE;

MethodNode method = node.getMethod();
AnnotationNode annotation = Annotations.getVisible(method, MixinMerged.class);
if (annotation == null) return MatchResult.NONE;
if (!(method instanceof MethodNodeEx)) return MatchResult.NONE;

MethodNodeEx methodNodeEx = (MethodNodeEx) method;
String targetMixinName = Annotations.getValue(annotation, "mixin");
MatchResult result = matchInternal(targetMixinName, methodNodeEx);
if (print)
System.err.printf("/* %100s %-15s %-50s %9s */\n", targetMixinName, method.name.split("\\$")[0], methodNodeEx.getOriginalName(), result.isExactMatch() ? "YES" : "-");
return result;
String originalName = methodNodeEx.getOriginalName();
String desc = methodNodeEx.desc;
String prefix = methodNodeEx.name.split("\\$")[0];
return matchInternal(targetMixinName, originalName, desc, prefix);
}

private MatchResult matchInternal(String targetMixinName, MethodNodeEx method) {
private MatchResult matchInternal(String targetMixinName, String name, String desc, String prefix) {
if (!mixinName.equals(targetMixinName)) return MatchResult.NONE;
if (prefix != null) {
String methodPrefix = method.name.split("\\$")[0];
if (!methodPrefix.equalsIgnoreCase(prefix)) return MatchResult.NONE;
}
if (method.getOriginalName().equals(name)) {
return MatchResult.EXACT_MATCH;
}
if (method.getOriginalName().equalsIgnoreCase(name)) {
return MatchResult.MATCH;
}

if (this.desc != null && desc != null && !this.desc.equals(desc)) return MatchResult.NONE;
if (this.prefix != null && prefix != null && !this.prefix.equals(prefix)) return MatchResult.NONE;
if (this.name.equals(name)) return MatchResult.EXACT_MATCH;
if (this.name.equalsIgnoreCase(name)) return MatchResult.MATCH;
return MatchResult.NONE;
}

Expand Down

0 comments on commit aada49b

Please sign in to comment.