Skip to content

Commit

Permalink
0.7.9 - Allow certain injectors to target mixin methods, closes #251
Browse files Browse the repository at this point in the history
  • Loading branch information
Mumfrey committed Apr 20, 2018
1 parent 1f936ba commit ba0c777
Show file tree
Hide file tree
Showing 13 changed files with 100 additions and 17 deletions.
7 changes: 2 additions & 5 deletions checkstyle.xml
Expand Up @@ -12,7 +12,6 @@
<property name="severity" value="warning"/>
<property name="charset" value="UTF-8"/>
<module name="TreeWalker">
<module name="FileContentsHolder"/>
<module name="OuterTypeFilename"/>
<module name="IllegalTokenText">
<property name="tokens" value="STRING_LITERAL, CHAR_LITERAL"/>
Expand All @@ -31,9 +30,7 @@
<property name="tokens" value="LITERAL_TRY, LITERAL_CATCH, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH"/>
</module>
<module name="NeedBraces"/>
<module name="LeftCurly">
<property name="maxLineLength" value="150"/>
</module>
<module name="LeftCurly"/>
<module name="RightCurly"/>
<module name="RightCurly">
<property name="option" value="alone"/>
Expand Down Expand Up @@ -146,9 +143,9 @@
</module>
<module name="MethodName"/>
<module name="UncommentedMain"/>
<module name="SuppressionCommentFilter"/>
</module>
<module name="FileTabCharacter">
<property name="eachLine" value="true"/>
</module>
<module name="SuppressionCommentFilter"/>
</module>
2 changes: 1 addition & 1 deletion gradle.properties
Expand Up @@ -4,5 +4,5 @@ packaging=jar
description=Mixin
url=https://www.spongepowered.org
organization=SpongePowered
buildVersion=0.7.8
buildVersion=0.7.9
buildType=SNAPSHOT
Expand Up @@ -156,6 +156,11 @@ public AnnotatedMixinElementHandlerAccessor(IMixinAnnotationProcessor ap, Annota
public ReferenceMapper getReferenceMapper() {
return null;
}

@Override
public String getClassName() {
return this.mixin.getClassRef().replace('/', '.');
}

@Override
public String getClassRef() {
Expand Down
Expand Up @@ -60,7 +60,7 @@ public abstract class MixinBootstrap {
/**
* Subsystem version
*/
public static final String VERSION = "0.7.8";
public static final String VERSION = "0.7.9";

/**
* Log all the things
Expand Down
Expand Up @@ -215,6 +215,22 @@ public Selector getSelector() {
public String getId() {
return this.id;
}

/**
* Runs a priority check in the context of this injection point. A priority
* check should return <tt>true</tt> if the injection point is allowed to
* inject given the relative priorities of the <em>target</em> (a method
* merged by another mixin with <tt>targetPriority</tt>) and the incoming
* mixin with priority <tt>mixinPriority</tt>.
*
* @param targetPriority Priority of the mixin which originally merged the
* target method in question
* @param mixinPriority Priority of the mixin which owns the owning injector
* @return true if the priority check succeeds
*/
public boolean checkPriority(int targetPriority, int mixinPriority) {
return targetPriority < mixinPriority;
}

/**
* Find injection points in the supplied insn list
Expand Down
Expand Up @@ -51,6 +51,7 @@
import org.spongepowered.asm.mixin.injection.struct.Target;
import org.spongepowered.asm.mixin.injection.struct.InjectionNodes.InjectionNode;
import org.spongepowered.asm.mixin.injection.throwables.InvalidInjectionException;
import org.spongepowered.asm.mixin.refmap.IMixinContext;
import org.spongepowered.asm.mixin.transformer.ClassInfo;
import org.spongepowered.asm.util.Bytecode;

Expand Down Expand Up @@ -214,12 +215,21 @@ public final void inject(Target target, List<InjectionNode> nodes) {
* @return Target insn nodes in the target method
*/
private Collection<TargetNode> findTargetNodes(InjectorTarget injectorTarget, List<InjectionPoint> injectionPoints) {
IMixinContext mixin = this.info.getContext();
MethodNode method = injectorTarget.getMethod();
Map<Integer, TargetNode> targetNodes = new TreeMap<Integer, TargetNode>();
Collection<AbstractInsnNode> nodes = new ArrayList<AbstractInsnNode>(32);

for (InjectionPoint injectionPoint : injectionPoints) {
nodes.clear();

if (injectorTarget.isMerged()
&& !mixin.getClassName().equals(injectorTarget.getMergedBy())
&& !injectionPoint.checkPriority(injectorTarget.getMergedPriority(), mixin.getPriority())) {
throw new InvalidInjectionException(this.info, String.format(
"%s on %s with priority %d cannot inject into %s merged by %s with priority %d", injectionPoint, this, mixin.getPriority(),
injectorTarget, injectorTarget.getMergedBy(), injectorTarget.getMergedPriority()));
}

if (this.findTargetNodes(method, injectionPoint, injectorTarget.getSlice(injectionPoint), nodes)) {
for (AbstractInsnNode insn : nodes) {
Expand Down
Expand Up @@ -27,10 +27,14 @@
import java.util.HashMap;
import java.util.Map;

import org.spongepowered.asm.lib.tree.AnnotationNode;
import org.spongepowered.asm.lib.tree.InsnList;
import org.spongepowered.asm.lib.tree.MethodNode;
import org.spongepowered.asm.mixin.extensibility.IMixinConfig;
import org.spongepowered.asm.mixin.injection.InjectionPoint;
import org.spongepowered.asm.mixin.injection.struct.Target;
import org.spongepowered.asm.mixin.transformer.meta.MixinMerged;
import org.spongepowered.asm.util.Annotations;

/**
* Couples {@link MethodSlice method slices} to a {@link Target} for injection
Expand All @@ -52,6 +56,10 @@ public class InjectorTarget {
* Target method data
*/
private final Target target;

private final String mergedBy;

private final int mergedPriority;

/**
* ctor
Expand All @@ -62,6 +70,15 @@ public class InjectorTarget {
public InjectorTarget(ISliceContext context, Target target) {
this.context = context;
this.target = target;

AnnotationNode merged = Annotations.getVisible(target.method, MixinMerged.class);
this.mergedBy = Annotations.<String>getValue(merged, "mixin");
this.mergedPriority = Annotations.<Integer>getValue(merged, "priority", IMixinConfig.DEFAULT_PRIORITY);
}

@Override
public String toString() {
return this.target.toString();
}

/**
Expand All @@ -78,6 +95,29 @@ public MethodNode getMethod() {
return this.target.method;
}

/**
* Get whether this target method was merged by another mixin
*/
public boolean isMerged() {
return this.mergedBy != null;
}

/**
* Get the name of the mixin which merged this method, returns null for non-
* mixin methods
*/
public String getMergedBy() {
return this.mergedBy;
}

/**
* Get the priority of the mixin which merged this method, or default
* priority for non-mixin methods
*/
public int getMergedPriority() {
return this.mergedPriority;
}

/**
* Get the slice instructions for the specified slice id
*
Expand Down
Expand Up @@ -65,6 +65,11 @@ public BeforeFinalReturn(InjectionPointData data) {

this.context = data.getContext();
}

@Override
public boolean checkPriority(int targetPriority, int ownerPriority) {
return true;
}

@Override
public boolean find(String desc, InsnList insns, Collection<AbstractInsnNode> nodes) {
Expand Down
Expand Up @@ -78,6 +78,11 @@ public BeforeReturn(InjectionPointData data) {

this.ordinal = data.getOrdinal();
}

@Override
public boolean checkPriority(int targetPriority, int ownerPriority) {
return true;
}

@Override
public boolean find(String desc, InsnList insns, Collection<AbstractInsnNode> nodes) {
Expand Down
Expand Up @@ -49,6 +49,11 @@ public class MethodHead extends InjectionPoint {
public MethodHead(InjectionPointData data) {
super(data);
}

@Override
public boolean checkPriority(int targetPriority, int ownerPriority) {
return true;
}

@Override
public boolean find(String desc, InsnList insns, Collection<AbstractInsnNode> nodes) {
Expand Down
Expand Up @@ -430,17 +430,9 @@ private void checkTarget(MethodNode target) {
return;
}

String owner = Annotations.<String>getValue(merged, "mixin");
int priority = Annotations.<Integer>getValue(merged, "priority");

if (priority >= this.mixin.getPriority() && !owner.equals(this.mixin.getClassName())) {
throw new InvalidInjectionException(this, String.format("%s cannot inject into %s::%s%s merged by %s with priority %d", this,
this.classNode.name, target.name, target.desc, owner, priority));
}

if (Annotations.getVisible(target, Final.class) != null) {
throw new InvalidInjectionException(this, String.format("%s cannot inject into @Final method %s::%s%s merged by %s", this,
this.classNode.name, target.name, target.desc, owner));
this.classNode.name, target.name, target.desc, Annotations.<String>getValue(merged, "mixin")));
}
}

Expand Down
Expand Up @@ -44,6 +44,13 @@ public interface IMixinContext {
* Get the mixin transformer extension manager
*/
public abstract Extensions getExtensions();

/**
* Get the mixin class name
*
* @return the mixin class name
*/
public abstract String getClassName();

/**
* Get the internal mixin class name
Expand Down
Expand Up @@ -288,6 +288,7 @@ public ClassNode getClassNode() {
*
* @return the mixin class name
*/
@Override
public String getClassName() {
return this.mixin.getClassName();
}
Expand Down

0 comments on commit ba0c777

Please sign in to comment.