Skip to content

Commit

Permalink
Add split extract transformer
Browse files Browse the repository at this point in the history
  • Loading branch information
Su5eD committed May 1, 2024
1 parent d3d95f0 commit 93e8458
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,11 @@ public T extractMixin(String targetClass) {
return transform(ModifyVarUpgradeToModifyExprVal.INSTANCE).transform(new ExtractMixin(targetClass));
}

@Override
public T splitMixin(String targetClass) {
return transform(new SplitMixinTransform(targetClass));
}

@Override
public T improveModifyVar() {
return transform(ModifyVarUpgradeToModifyExprVal.INSTANCE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ interface Builder<T extends Builder<T>> {

T extractMixin(String targetClass);

T splitMixin(String targetClass);

T improveModifyVar();

T modifyMixinType(String newType, Consumer<ModifyMixinType.Builder> consumer);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@
import java.util.function.Consumer;
import java.util.stream.IntStream;

public record ExtractMixin(String targetClass) implements MethodTransform {
public record ExtractMixin(String targetClass, boolean remove) implements MethodTransform {
public ExtractMixin(String targetClass) {
this(targetClass, true);
}

@Override
public Collection<String> getAcceptedAnnotations() {
return Set.of(MixinConstants.WRAP_WITH_CONDITION, MixinConstants.WRAP_OPERATION, MixinConstants.MODIFY_CONST, MixinConstants.MODIFY_ARG, MixinConstants.INJECT, MixinConstants.REDIRECT, MixinConstants.MODIFY_VAR, MixinConstants.MODIFY_EXPR_VAL);
Expand All @@ -45,10 +49,19 @@ public Patch.Result apply(ClassNode classNode, MethodNode methodNode, MethodCont
// Get or generate new mixin class
ClassNode generatedTarget = context.environment().classGenerator().getOrGenerateMixinClass(classNode, this.targetClass, targetClass != null ? targetClass.superName : null);
context.environment().refmapHolder().copyEntries(classNode.name, generatedTarget.name);

// Add mixin methods from original to generated class
generatedTarget.methods.addAll(candidates.methods);
for (MethodNode method : candidates.methods()) {
MethodNode copy = new MethodNode(method.access, method.name, method.desc, method.signature, method.exceptions == null ? null : method.exceptions.toArray(new String[0]));
method.accept(copy);
generatedTarget.methods.add(copy);
updateOwnerRefereces(copy, classNode, this.targetClass);
if (!isStatic && copy.localVariables != null) {
copy.localVariables.stream().filter(l -> l.index == 0).findFirst().ifPresent(lvn -> lvn.desc = Type.getObjectType(generatedTarget.name).getDescriptor());
}
}

candidates.handleUpdates().forEach(c -> c.accept(generatedTarget));
candidates.methods().forEach(method -> updateOwnerRefereces(method, classNode, this.targetClass));

// Take care of captured locals
Patch.Result result = Patch.Result.PASS;
Expand All @@ -57,9 +70,8 @@ public Patch.Result apply(ClassNode classNode, MethodNode methodNode, MethodCont
}

// Remove original method
context.postApply(() -> classNode.methods.removeAll(candidates.methods));
if (!isStatic && methodNode.localVariables != null) {
methodNode.localVariables.stream().filter(l -> l.index == 0).findFirst().ifPresent(lvn -> lvn.desc = Type.getObjectType(generatedTarget.name).getDescriptor());
if (this.remove) {
context.postApply(() -> classNode.methods.removeAll(candidates.methods));
}
return result.or(Patch.Result.APPLY);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.sinytra.adapter.patch.transformer;

import org.objectweb.asm.Type;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode;
import org.sinytra.adapter.patch.api.*;

import java.util.Collection;
import java.util.Set;

public record SplitMixinTransform(String targetClass) implements MethodTransform {

@Override
public Collection<String> getAcceptedAnnotations() {
return Set.of(MixinConstants.WRAP_WITH_CONDITION, MixinConstants.WRAP_OPERATION, MixinConstants.MODIFY_CONST, MixinConstants.MODIFY_ARG, MixinConstants.INJECT, MixinConstants.REDIRECT, MixinConstants.MODIFY_VAR, MixinConstants.MODIFY_EXPR_VAL);
}

@Override
public Patch.Result apply(ClassNode classNode, MethodNode methodNode, MethodContext methodContext, PatchContext context) {
MethodTransform transform = new ExtractMixin(this.targetClass, false);
Patch.Result result = transform.apply(classNode, methodNode, methodContext, context);
if (methodContext.targetTypes().size() > 1) {
MethodTransform removeTarget = new ModifyTargetClasses(l -> l.remove(Type.getObjectType(this.targetClass)));
removeTarget.apply(classNode, methodNode, methodContext, context);
}
return result;
}
}

0 comments on commit 93e8458

Please sign in to comment.