Skip to content

Commit

Permalink
Re-add upgradeWrapOperation
Browse files Browse the repository at this point in the history
  • Loading branch information
Su5eD committed Mar 2, 2024
1 parent e9aed8a commit 8fe46dd
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@ public static ParametersDiff create(List<Type> clean, List<Type> dirty) {
List<TypeWithContext> compareClean = extract(cleanQueue, 2);
List<TypeWithContext> compareDirty = extract(dirtyQueue, dirtyTypeIndex + offset);

compare(builder, compareClean, compareDirty);
}
// If there is no match for the first available type, look further ahead. This is good for handling cases
// where the sizes of both sets are equal and the first couple types have been replaced / modified
else if (cleanQueue.size() == dirtyQueue.size() && (dirtyTypeIndex = findClosestMatch(cleanQueue, dirtyQueue)) > 1) {
List<TypeWithContext> compareClean = extract(cleanQueue, dirtyTypeIndex);
List<TypeWithContext> compareDirty = extract(dirtyQueue, dirtyTypeIndex);

compare(builder, compareClean, compareDirty);
} else if (cleanQueue.size() > 1) {
TypeWithContext type = cleanQueue.remove(1);
Expand All @@ -71,6 +79,16 @@ public static ParametersDiff create(List<Type> clean, List<Type> dirty) {
return builder.build(clean.size());
}

private static int findClosestMatch(List<TypeWithContext> cleanQueue, List<TypeWithContext> dirtyQueue) {
for (TypeWithContext typeWithContext : cleanQueue) {
int pos = lookAhead(dirtyQueue, typeWithContext);
if (pos != -1) {
return pos;
}
}
return -1;
}

private static boolean replaceType(ParamDiffBuilder builder, int index, List<TypeWithContext> cleanQueue, List<TypeWithContext> dirtyQueue) {
if (index >= cleanQueue.size() || index >= dirtyQueue.size()) {
return false;
Expand All @@ -97,7 +115,7 @@ private static boolean replaceType(ParamDiffBuilder builder, int index, List<Typ
private static boolean isPossiblyInjected(int index, List<TypeWithContext> cleanQueue, List<TypeWithContext> dirtyQueue) {
for (int i = index; i < cleanQueue.size(); i++) {
if (!cleanQueue.get(i).equals(dirtyQueue.get(i))) {
return true;
return true;
}
}
return false;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
package dev.su5ed.sinytra.adapter.patch.fixes;

import com.google.common.collect.ImmutableList;
import dev.su5ed.sinytra.adapter.patch.analysis.EnhancedParamsDiff;
import dev.su5ed.sinytra.adapter.patch.analysis.ParametersDiff;
import dev.su5ed.sinytra.adapter.patch.api.MethodContext;
import dev.su5ed.sinytra.adapter.patch.api.MixinConstants;
import dev.su5ed.sinytra.adapter.patch.transformer.ModifyArgsOffsetTransformer;
import dev.su5ed.sinytra.adapter.patch.transformer.ModifyMethodParams;
import dev.su5ed.sinytra.adapter.patch.util.MethodQualifier;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode;

import java.util.List;

public final class MethodUpgrader {

public static void upgradeMethod(ClassNode classNode, MethodNode methodNode, MethodContext methodContext, String originalDesc, String modifiedDesc) {
Expand All @@ -20,7 +27,31 @@ public static void upgradeMethod(ClassNode classNode, MethodNode methodNode, Met
}
if (methodContext.methodAnnotation().matchesDesc(MixinConstants.MODIFY_ARGS)) {
ModifyArgsOffsetTransformer.handleModifiedDesc(methodNode, cleanQualifier.desc(), dirtyQualifier.desc());
} else if (methodContext.methodAnnotation().matchesDesc(MixinConstants.WRAP_OPERATION)) {
upgradeWrapOperation(classNode, methodNode, methodContext, cleanQualifier, dirtyQualifier);
}
}

private static void upgradeWrapOperation(ClassNode classNode, MethodNode methodNode, MethodContext methodContext, MethodQualifier cleanQualifier, MethodQualifier dirtyQualifier) {
if (dirtyQualifier.owner() == null || cleanQualifier.desc() == null) {
return;
}
List<Type> originalTargetDesc = List.of(Type.getArgumentTypes(cleanQualifier.desc()));
List<Type> modifiedTargetDesc = List.of(Type.getArgumentTypes(dirtyQualifier.desc()));
List<Type> originalDesc = List.of(Type.getArgumentTypes(methodNode.desc));
List<Type> modifiedDesc = ImmutableList.<Type>builder()
// Add instance parameter
.add(Type.getType(dirtyQualifier.owner()))
// Add target parameters
.addAll(modifiedTargetDesc)
// Add everything after the original owner and target args (such as captured locals)
.addAll(originalDesc.subList(1 + originalTargetDesc.size(), originalDesc.size()))
.build();
// Create diff
ParametersDiff diff = EnhancedParamsDiff.create(originalDesc, modifiedDesc);
if (!diff.isEmpty()) {
ModifyMethodParams patch = ModifyMethodParams.create(diff, ModifyMethodParams.TargetType.ALL);
patch.apply(classNode, methodNode, methodContext, methodContext.patchContext());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,28 @@ void testMovedParameter() {
assertEquals(1, diff.moves().size());
}

@Test
void testReplacedParameters() {
List<Type> clean = List.of(
Type.getObjectType("net/minecraft/world/item/enchantment/EnchantmentCategory"),
Type.getObjectType("net/minecraft/world/item/Item"),
Type.getObjectType("com/llamalad7/mixinextras/injector/wrapoperation/Operation"),
Type.getObjectType("com/llamalad7/mixinextras/sugar/ref/LocalRef")
);
List<Type> dirty = List.of(
Type.getObjectType("net/minecraft/world/item/enchantment/Enchantment"),
Type.getObjectType("net/minecraft/world/item/ItemStack"),
Type.getObjectType("com/llamalad7/mixinextras/injector/wrapoperation/Operation"),
Type.getObjectType("com/llamalad7/mixinextras/sugar/ref/LocalRef")
);

ParametersDiff diff = EnhancedParamsDiff.create(clean, dirty);
assertTrue(diff.insertions().isEmpty());
assertEquals(2, diff.replacements().size());
assertTrue(diff.removals().isEmpty());
assertTrue(diff.swaps().isEmpty());
}

@Test
void testRemovedParameter() {
List<Type> clean = List.of(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.assertj.core.api.Assertions;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.tree.*;
import org.spongepowered.asm.mixin.FabricUtil;

import java.io.IOException;
import java.io.InputStream;
Expand Down Expand Up @@ -41,7 +42,8 @@ public void copyEntries(String from, String to) {
return Optional.empty();
}
},
null
null,
FabricUtil.COMPATIBILITY_LATEST
);
patch.apply(patched, env);
return new LoadResult(patched, load(className));
Expand Down

0 comments on commit 8fe46dd

Please sign in to comment.