diff --git a/definition/src/main/java/org/sinytra/adapter/patch/transformer/SoftMethodParamsPatch.java b/definition/src/main/java/org/sinytra/adapter/patch/transformer/SoftMethodParamsPatch.java index 5a21aab..34b4a26 100644 --- a/definition/src/main/java/org/sinytra/adapter/patch/transformer/SoftMethodParamsPatch.java +++ b/definition/src/main/java/org/sinytra/adapter/patch/transformer/SoftMethodParamsPatch.java @@ -9,6 +9,7 @@ import org.sinytra.adapter.patch.analysis.params.ParametersDiff; import org.sinytra.adapter.patch.api.*; import org.sinytra.adapter.patch.fixes.BytecodeFixerUpper; +import org.sinytra.adapter.patch.serialization.MethodTransformSerialization; import org.sinytra.adapter.patch.transformer.param.TransformParameters; import org.sinytra.adapter.patch.util.AdapterUtil; import org.sinytra.adapter.patch.util.MethodQualifier; @@ -17,9 +18,10 @@ import java.util.List; import java.util.Set; -public record SoftMethodParamsPatch(String replacementTarget) implements MethodTransform { +public record SoftMethodParamsPatch(String replacementTarget, MethodTransform targetTransform) implements MethodTransform { public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( - Codec.STRING.fieldOf("replacementTarget").forGetter(SoftMethodParamsPatch::replacementTarget) + Codec.STRING.fieldOf("replacementTarget").forGetter(SoftMethodParamsPatch::replacementTarget), + MethodTransformSerialization.METHOD_TRANSFORM_CODEC.fieldOf("targetTransform").forGetter(SoftMethodParamsPatch::targetTransform) ).apply(instance, SoftMethodParamsPatch::new)); @Override @@ -34,17 +36,24 @@ public Collection getAcceptedAnnotations() { @Override public Patch.Result apply(ClassNode classNode, MethodNode methodNode, MethodContext methodContext, PatchContext context) { + Patch.Result result = Patch.Result.PASS; MethodQualifier targetQualifier = methodContext.getTargetMethodQualifier(); if (targetQualifier != null) { + // In the case of constructor TAIL injection, it's safer to keep working with the original values + if (targetQualifier.name().equals("") && !methodContext.capturesLocals() && methodContext.injectionPointAnnotation().getValue("value").map(s -> s.get().equals("TAIL")).orElse(false)) { + return Patch.Result.PASS; + } + List> replacements = determineAutomaticReplacements(targetQualifier, methodNode, context, this.replacementTarget); if (!replacements.isEmpty()) { TransformParameters patch = TransformParameters.builder() .replacements(replacements) .build(); - return Patch.Result.APPLY.or(patch.apply(classNode, methodNode, methodContext, context)); + result = Patch.Result.APPLY.or(patch.apply(classNode, methodNode, methodContext, context)); } } - return Patch.Result.PASS; + // Modify the method target + return result.or(this.targetTransform.apply(classNode, methodNode, methodContext, context)); } private List> determineAutomaticReplacements(MethodQualifier targetQualifier, MethodNode methodNode, PatchContext context, String replacement) { diff --git a/plugin/src/main/java/org/sinytra/adapter/gradle/ClassAnalyzer.java b/plugin/src/main/java/org/sinytra/adapter/gradle/ClassAnalyzer.java index 5a9db10..e91d928 100644 --- a/plugin/src/main/java/org/sinytra/adapter/gradle/ClassAnalyzer.java +++ b/plugin/src/main/java/org/sinytra/adapter/gradle/ClassAnalyzer.java @@ -304,13 +304,13 @@ private void findOverloadedMethods(AnalysisContext context, Map " + dirtyQualifier); + LOGGER.info(" {}", overloaderQualifier); + LOGGER.info("=> {}", dirtyQualifier); LOGGER.info("==="); PatchInstance patch = Patch.builder() .targetClass(this.dirtyNode.name) .targetMethod(overloaderQualifier) - .chain(b -> overloader.applyPatchTargetModifier(b, method)) + .transform(overloader.getPatchTargetTransform(method)) .transformMethods(diff.createTransforms(ParamTransformTarget.METHOD)) .build(); context.addPatch(patch); @@ -320,15 +320,14 @@ private void findOverloadedMethods(AnalysisContext context, Map " + dirtyQualifier); + LOGGER.info(" {}", overloaderQualifier); + LOGGER.info("=> {}", dirtyQualifier); LOGGER.info("==="); PatchInstance patch = Patch.builder() .targetClass(this.dirtyNode.name) .targetMethod(overloaderQualifier) - .transform(new SoftMethodParamsPatch(method.name + method.desc)) - // IMPORTANT: Target modification must come AFTER soft params patch - .chain(b -> overloader.applyPatchTargetModifier(b, method)) + // IMPORTANT: Target modification must be applied AFTER soft params patch + .transform(new SoftMethodParamsPatch(method.name + method.desc, overloader.getPatchTargetTransform(method))) .build(); context.addPatch(patch); } diff --git a/plugin/src/main/java/org/sinytra/adapter/gradle/analysis/OverloadedMethods.java b/plugin/src/main/java/org/sinytra/adapter/gradle/analysis/OverloadedMethods.java index 8ff8121..c8d5eaa 100644 --- a/plugin/src/main/java/org/sinytra/adapter/gradle/analysis/OverloadedMethods.java +++ b/plugin/src/main/java/org/sinytra/adapter/gradle/analysis/OverloadedMethods.java @@ -3,7 +3,7 @@ import com.mojang.datafixers.util.Pair; import org.sinytra.adapter.gradle.util.MatchResult; import org.sinytra.adapter.patch.analysis.MethodCallAnalyzer; -import org.sinytra.adapter.patch.api.Patch; +import org.sinytra.adapter.patch.api.MethodTransform; import org.sinytra.adapter.patch.transformer.ModifyInjectionTarget; import org.sinytra.adapter.patch.transformer.filter.InjectionPointTransformerFilter; import org.jetbrains.annotations.Nullable; @@ -140,12 +140,10 @@ public static MatchResult checkParameters(Type[] parameterTypes, Type[] dirtyPar } public record MethodOverload(boolean isFullMatch, MethodNode methodNode, List excludedInjectionPoints) { - public void applyPatchTargetModifier(Patch.ClassPatchBuilder builder, MethodNode method) { - if (this.excludedInjectionPoints.isEmpty()) { - builder.modifyTarget(method.name + method.desc); - } else { - builder.transform(InjectionPointTransformerFilter.create(new ModifyInjectionTarget(List.of(method.name + method.desc)), this.excludedInjectionPoints)); - } + public MethodTransform getPatchTargetTransform(MethodNode method) { + return this.excludedInjectionPoints.isEmpty() + ? new ModifyInjectionTarget(List.of(method.name + method.desc)) + : InjectionPointTransformerFilter.create(new ModifyInjectionTarget(List.of(method.name + method.desc)), this.excludedInjectionPoints); } } }