From 0acc5a8dbd3d2b670b9f72a38bc1072cdf8c741d Mon Sep 17 00:00:00 2001 From: Jake Potrebic Date: Tue, 27 Aug 2024 20:48:19 -0700 Subject: [PATCH] slightly refactor how matcher builders work for clarity --- .../BaseReflectionRules.java | 66 +++++---- .../papermc/reflectionrewriter/EnumRule.java | 6 +- .../rules/builder/ConfiguredRuleFactory.java | 4 +- .../builder/ConfiguredRuleFactoryImpl.java | 7 +- .../asm/rules/builder/RuleFactory.java | 50 +++---- .../asm/rules/builder/RuleFactoryImpl.java | 43 +++--- .../rules/builder/matcher/MethodMatcher.java | 132 ------------------ .../matcher/TargetedMethodMatcher.java | 71 ---------- .../matcher/{ => field}/FieldMatcher.java | 2 +- .../matcher/{ => field}/FieldMatcherImpl.java | 2 +- .../builder/matcher/method/MethodMatcher.java | 59 ++++++++ .../matcher/method/MethodMatcherBuilder.java | 45 ++++++ .../method/MethodMatcherBuilderImpl.java | 118 ++++++++++++++++ .../matcher/{ => method}/MethodType.java | 2 +- .../matcher/method/OpcodePredicate.java | 7 + .../targeted/TargetedMethodMatcher.java | 13 ++ .../TargetedMethodMatcherBuilder.java | 29 ++++ .../TargetedMethodMatcherBuilderImpl.java | 105 ++++++++++++++ .../targeted}/TargetedMethodMatcherImpl.java | 3 +- .../rules/classes/EnumToInterfaceRule.java | 16 +-- .../asm/rules/field/FieldToMethodRewrite.java | 2 +- .../rules/field/FilteredFieldRewriteRule.java | 2 +- .../asm/rules/method/DirectStaticRewrite.java | 2 +- .../asm/rules/method/MoveInstanceMethod.java | 2 +- .../method/OwnableMethodRewriteRule.java | 2 +- .../TargetedTypeGeneratedStaticRewrite.java | 2 +- .../method/params/DirectParameterRewrite.java | 2 +- .../method/params/FuzzyParameterRewrite.java | 2 +- .../method/params/SuperTypeParamRewrite.java | 2 +- .../method/returns/DirectReturnRewrite.java | 2 +- .../method/returns/SubTypeReturnRewrite.java | 2 +- .../asm/rules/methods/MethodRewritesTest.java | 19 ++- .../StaticMethodRewriteParamsTest.java | 19 ++- .../StaticMethodRewriteReturnsTest.java | 15 +- .../asm/rules/methods/StaticRewriteTest.java | 18 ++- 35 files changed, 546 insertions(+), 327 deletions(-) delete mode 100644 src/main/java/io/papermc/asm/rules/builder/matcher/MethodMatcher.java delete mode 100644 src/main/java/io/papermc/asm/rules/builder/matcher/TargetedMethodMatcher.java rename src/main/java/io/papermc/asm/rules/builder/matcher/{ => field}/FieldMatcher.java (96%) rename src/main/java/io/papermc/asm/rules/builder/matcher/{ => field}/FieldMatcherImpl.java (93%) create mode 100644 src/main/java/io/papermc/asm/rules/builder/matcher/method/MethodMatcher.java create mode 100644 src/main/java/io/papermc/asm/rules/builder/matcher/method/MethodMatcherBuilder.java create mode 100644 src/main/java/io/papermc/asm/rules/builder/matcher/method/MethodMatcherBuilderImpl.java rename src/main/java/io/papermc/asm/rules/builder/matcher/{ => method}/MethodType.java (91%) create mode 100644 src/main/java/io/papermc/asm/rules/builder/matcher/method/OpcodePredicate.java create mode 100644 src/main/java/io/papermc/asm/rules/builder/matcher/method/targeted/TargetedMethodMatcher.java create mode 100644 src/main/java/io/papermc/asm/rules/builder/matcher/method/targeted/TargetedMethodMatcherBuilder.java create mode 100644 src/main/java/io/papermc/asm/rules/builder/matcher/method/targeted/TargetedMethodMatcherBuilderImpl.java rename src/main/java/io/papermc/asm/rules/builder/matcher/{ => method/targeted}/TargetedMethodMatcherImpl.java (86%) diff --git a/reflection-rewriter/rewriter/src/main/java/io/papermc/reflectionrewriter/BaseReflectionRules.java b/reflection-rewriter/rewriter/src/main/java/io/papermc/reflectionrewriter/BaseReflectionRules.java index d72d821..642915b 100644 --- a/reflection-rewriter/rewriter/src/main/java/io/papermc/reflectionrewriter/BaseReflectionRules.java +++ b/reflection-rewriter/rewriter/src/main/java/io/papermc/reflectionrewriter/BaseReflectionRules.java @@ -1,12 +1,14 @@ package io.papermc.reflectionrewriter; import io.papermc.asm.rules.RewriteRule; +import io.papermc.asm.rules.builder.matcher.method.MethodMatcher; import java.lang.constant.ClassDesc; import java.lang.invoke.ConstantBootstraps; import java.lang.invoke.LambdaMetafactory; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.util.List; +import java.util.Set; public final class BaseReflectionRules { private final ClassDesc proxy; @@ -55,55 +57,65 @@ public List rules() { ); } + private static final MethodMatcher CLASS_RULE = MethodMatcher.builder() + .match("forName", b -> b.desc("(Ljava/lang/String;)Ljava/lang/Class;")) + .match(Set.of("getField", "getDeclaredField"), b -> b.desc("(Ljava/lang/String;)Ljava/lang/reflect/Field;")) + .match(Set.of("getMethod", "getDeclaredMethod"), b -> b.desc("(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;")) + .build(); + private RewriteRule createClassRule() { return RewriteRule.forOwnerClass(Class.class, rf -> { - rf.plainStaticRewrite(this.proxy, b -> b - .match("forName").desc("(Ljava/lang/String;)Ljava/lang/Class;") - .match("getField", "getDeclaredField").desc("(Ljava/lang/String;)Ljava/lang/reflect/Field;") - .match("getMethod", "getDeclaredMethod").desc("(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;") - ); + rf.plainStaticRewrite(this.proxy, CLASS_RULE); }); } + private static final MethodMatcher METHOD_HANDLE_LOOKUP_RULE = MethodMatcher.builder() + .match(Set.of("findStatic", "findVirtual"), b -> b.desc("(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle;")) + .match("findClass", b -> b.desc("(Ljava/lang/String;)Ljava/lang/Class;")) + .match("findSpecial", b -> b.desc("(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Class;)Ljava/lang/invoke/MethodHandle;")) + .match(Set.of("findGetter", "findSetter", "findStaticGetter", "findStaticSetter"), b -> b.desc("(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/invoke/MethodHandle;")) + .match(Set.of("findVarHandle", "findStaticVarHandle"), b -> b.desc("(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/invoke/VarHandle;")) + .match("bind", b -> b.desc("(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle;")) + .build(); + private RewriteRule createMethodHandlesLookupRule() { return RewriteRule.forOwnerClass(MethodHandles.Lookup.class, rf -> { - rf.plainStaticRewrite(this.proxy, b -> b - .match("findStatic", "findVirtual").desc("(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle;") - .match("findClass").desc("(Ljava/lang/String;)Ljava/lang/Class;") - .match("findSpecial").desc("(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Class;)Ljava/lang/invoke/MethodHandle;") - .match("findGetter", "findSetter", "findStaticGetter", "findStaticSetter").desc("(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/invoke/MethodHandle;") - .match("findVarHandle", "findStaticVarHandle").desc("(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/invoke/VarHandle;") - .match("bind").desc("(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle;") - ); + rf.plainStaticRewrite(this.proxy, METHOD_HANDLE_LOOKUP_RULE); }); } + private static final MethodMatcher LAMBDA_METAFACTORY_RULE = MethodMatcher.builder() + .match("metafactory", b -> b.desc("(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;")) + .match("altMetafactory", b -> b.desc("(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;")) + .build(); + private RewriteRule createLamdaMetafactoryRule() { return RewriteRule.forOwnerClass(LambdaMetafactory.class, rf -> { - rf.plainStaticRewrite(this.proxy, b -> b - .match("metafactory").desc("(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;") - .match("altMetafactory").desc("(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;") - ); + rf.plainStaticRewrite(this.proxy, LAMBDA_METAFACTORY_RULE); }); } + private static final MethodMatcher CONSTANT_BOOTSTRAPS_RULE = MethodMatcher.builder() + .match("getStaticFinal", b -> b.desc( + "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/Object;", + "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/Object;" + )) + .match(Set.of("fieldVarHandle", "staticFieldVarHandle"), b -> b.desc("(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/invoke/VarHandle;")) + .build(); + private RewriteRule createConstantBootstrapsRule() { return RewriteRule.forOwnerClass(ConstantBootstraps.class, rf -> { - rf.plainStaticRewrite(this.proxy, b -> b - .match("getStaticFinal").desc( - "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/Object;", - "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/Object;" - ) - .match("fieldVarHandle", "staticFieldVarHandle").desc("(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/invoke/VarHandle;") - ); + rf.plainStaticRewrite(this.proxy, CONSTANT_BOOTSTRAPS_RULE); }); } + private static final MethodMatcher METHOD_TYPE_RULE = MethodMatcher.builder() + .match("fromMethodDescriptorString", b -> b.desc("(Ljava/lang/String;Ljava/lang/ClassLoader;)Ljava/lang/invoke/MethodType;")) + .build(); + private RewriteRule createMethodTypeRule() { return RewriteRule.forOwnerClass(MethodType.class, rf -> { - rf.plainStaticRewrite(this.proxy, b -> b - .match("fromMethodDescriptorString").desc("(Ljava/lang/String;Ljava/lang/ClassLoader;)Ljava/lang/invoke/MethodType;") - ); + rf.plainStaticRewrite(this.proxy, METHOD_TYPE_RULE); }); } } diff --git a/reflection-rewriter/rewriter/src/main/java/io/papermc/reflectionrewriter/EnumRule.java b/reflection-rewriter/rewriter/src/main/java/io/papermc/reflectionrewriter/EnumRule.java index 2862957..fc288db 100644 --- a/reflection-rewriter/rewriter/src/main/java/io/papermc/reflectionrewriter/EnumRule.java +++ b/reflection-rewriter/rewriter/src/main/java/io/papermc/reflectionrewriter/EnumRule.java @@ -4,6 +4,7 @@ import io.papermc.asm.ClassInfoProvider; import io.papermc.asm.ClassProcessingContext; import io.papermc.asm.rules.RewriteRule; +import io.papermc.asm.rules.builder.matcher.method.MethodMatcher; import java.lang.constant.ClassDesc; import java.lang.invoke.ConstantBootstraps; import java.util.function.Predicate; @@ -54,8 +55,9 @@ public static RewriteRule create( final Predicate ownerPredicate ) { final RewriteRule rewrite = RewriteRule.forOwnerClass(ConstantBootstraps.class, rf -> { - rf.plainStaticRewrite(ClassDesc.of(proxyClassName), b -> b - .match("enumConstant").desc("(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/Enum;") + rf.plainStaticRewrite(ClassDesc.of(proxyClassName), MethodMatcher.builder() + .match("enumConstant", b -> b.desc("(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/Enum;")) + .build() ); }); final RewriteRule enumRule = new RewriteRule() { diff --git a/src/main/java/io/papermc/asm/rules/builder/ConfiguredRuleFactory.java b/src/main/java/io/papermc/asm/rules/builder/ConfiguredRuleFactory.java index a539d07..242f491 100644 --- a/src/main/java/io/papermc/asm/rules/builder/ConfiguredRuleFactory.java +++ b/src/main/java/io/papermc/asm/rules/builder/ConfiguredRuleFactory.java @@ -1,6 +1,6 @@ package io.papermc.asm.rules.builder; -import io.papermc.asm.rules.builder.matcher.MethodMatcher; +import io.papermc.asm.rules.builder.matcher.method.MethodMatcher; import java.lang.constant.ClassDesc; import java.util.Set; import java.util.function.Consumer; @@ -19,7 +19,7 @@ static ConfiguredRuleFactory.Factory combine(final ConfiguredRuleFactory.Factory }; } - void plainStaticRewrite(Consumer builderConsumer); + void plainStaticRewrite(MethodMatcher methodMatcher); @FunctionalInterface interface Factory extends Consumer { diff --git a/src/main/java/io/papermc/asm/rules/builder/ConfiguredRuleFactoryImpl.java b/src/main/java/io/papermc/asm/rules/builder/ConfiguredRuleFactoryImpl.java index fa27bf5..5a8385a 100644 --- a/src/main/java/io/papermc/asm/rules/builder/ConfiguredRuleFactoryImpl.java +++ b/src/main/java/io/papermc/asm/rules/builder/ConfiguredRuleFactoryImpl.java @@ -1,9 +1,8 @@ package io.papermc.asm.rules.builder; -import io.papermc.asm.rules.builder.matcher.MethodMatcher; +import io.papermc.asm.rules.builder.matcher.method.MethodMatcher; import java.lang.constant.ClassDesc; import java.util.Set; -import java.util.function.Consumer; public class ConfiguredRuleFactoryImpl extends RuleFactoryImpl implements ConfiguredRuleFactory { @@ -15,7 +14,7 @@ public class ConfiguredRuleFactoryImpl extends RuleFactoryImpl implements Config } @Override - public void plainStaticRewrite(final Consumer builderConsumer) { - this.plainStaticRewrite(this.config.delegateOwner(), builderConsumer); + public void plainStaticRewrite(final MethodMatcher methodMatcher) { + this.plainStaticRewrite(this.config.delegateOwner(), methodMatcher); } } diff --git a/src/main/java/io/papermc/asm/rules/builder/RuleFactory.java b/src/main/java/io/papermc/asm/rules/builder/RuleFactory.java index 074aa79..18cf037 100644 --- a/src/main/java/io/papermc/asm/rules/builder/RuleFactory.java +++ b/src/main/java/io/papermc/asm/rules/builder/RuleFactory.java @@ -1,9 +1,9 @@ package io.papermc.asm.rules.builder; import io.papermc.asm.rules.RewriteRule; -import io.papermc.asm.rules.builder.matcher.FieldMatcher; -import io.papermc.asm.rules.builder.matcher.MethodMatcher; -import io.papermc.asm.rules.builder.matcher.TargetedMethodMatcher; +import io.papermc.asm.rules.builder.matcher.field.FieldMatcher; +import io.papermc.asm.rules.builder.matcher.method.MethodMatcher; +import io.papermc.asm.rules.builder.matcher.method.targeted.TargetedMethodMatcher; import java.lang.constant.ClassDesc; import java.lang.reflect.Method; import java.util.Set; @@ -26,57 +26,57 @@ static RuleFactory.Factory combine(final RuleFactory.Factory... factories) { }; } - void plainStaticRewrite(ClassDesc newOwner, Consumer builderConsumer); + void plainStaticRewrite(ClassDesc newOwner, MethodMatcher methodMatcher); - default void changeParamToSuper(final Class oldParamType, final Class newParamType, final Consumer builderConsumer) { + default void changeParamToSuper(final Class oldParamType, final Class newParamType, final MethodMatcher methodMatcher) { if (!newParamType.isAssignableFrom(oldParamType)) { throw new IllegalArgumentException(newParamType + " is not a superclass of " + oldParamType); } - this.changeParamToSuper(desc(oldParamType), desc(newParamType), builderConsumer); + this.changeParamToSuper(desc(oldParamType), desc(newParamType), methodMatcher); } - void changeParamToSuper(ClassDesc legacyParamType, ClassDesc newParamType, Consumer builderConsumer); + void changeParamToSuper(ClassDesc legacyParamType, ClassDesc newParamType, MethodMatcher methodMatcher); - default void changeParamFuzzy(final Class newParamType, final Method staticHandler, final Consumer builderConsumer) { - this.changeParamFuzzy(desc(newParamType), staticHandler, builderConsumer); + default void changeParamFuzzy(final Class newParamType, final Method staticHandler, final TargetedMethodMatcher targetedMethodMatcher) { + this.changeParamFuzzy(desc(newParamType), staticHandler, targetedMethodMatcher); } - void changeParamFuzzy(ClassDesc newParamType, Method staticHandler, Consumer builderConsumer); + void changeParamFuzzy(ClassDesc newParamType, Method staticHandler, TargetedMethodMatcher targetedMethodMatcher); - default void changeParamDirect(final Class newParamType, final Method staticHandler, final Consumer builderConsumer) { - this.changeParamDirect(desc(newParamType), staticHandler, builderConsumer); + default void changeParamDirect(final Class newParamType, final Method staticHandler, final TargetedMethodMatcher targetedMethodMatcher) { + this.changeParamDirect(desc(newParamType), staticHandler, targetedMethodMatcher); } - void changeParamDirect(ClassDesc newParamType, Method staticHandler, Consumer builderConsumer); + void changeParamDirect(ClassDesc newParamType, Method staticHandler, TargetedMethodMatcher targetedMethodMatcher); - default void changeReturnTypeToSub(final Class oldReturnType, final Class newReturnType, final Consumer builderConsumer) { + default void changeReturnTypeToSub(final Class oldReturnType, final Class newReturnType, final MethodMatcher methodMatcher) { if (!oldReturnType.isAssignableFrom(newReturnType)) { throw new IllegalArgumentException(newReturnType + " is not a subclass of " + oldReturnType); } - this.changeReturnTypeToSub(desc(oldReturnType), desc(newReturnType), builderConsumer); + this.changeReturnTypeToSub(desc(oldReturnType), desc(newReturnType), methodMatcher); } - void changeReturnTypeToSub(ClassDesc oldReturnType, ClassDesc newReturnType, Consumer builderConsumer); + void changeReturnTypeToSub(ClassDesc oldReturnType, ClassDesc newReturnType, MethodMatcher methodMatcher); - default void changeReturnTypeDirect(final Class newReturnType, final Method staticHandler, final Consumer builderConsumer) { - this.changeReturnTypeDirect(desc(newReturnType), staticHandler, builderConsumer); + default void changeReturnTypeDirect(final Class newReturnType, final Method staticHandler, final TargetedMethodMatcher targetedMethodMatcher) { + this.changeReturnTypeDirect(desc(newReturnType), staticHandler, targetedMethodMatcher); } - void changeReturnTypeDirect(ClassDesc newReturnType, Method staticHandler, Consumer builderConsumer); + void changeReturnTypeDirect(ClassDesc newReturnType, Method staticHandler, TargetedMethodMatcher targetedMethodMatcher); - default void changeReturnTypeDirectWithContext(final Class newReturnType, final Method staticHandler, final Consumer builderConsumer) { - this.changeReturnTypeDirectWithContext(desc(newReturnType), staticHandler, builderConsumer); + default void changeReturnTypeDirectWithContext(final Class newReturnType, final Method staticHandler, final TargetedMethodMatcher targetedMethodMatcher) { + this.changeReturnTypeDirectWithContext(desc(newReturnType), staticHandler, targetedMethodMatcher); } - void changeReturnTypeDirectWithContext(ClassDesc newReturnType, Method staticHandler, Consumer builderConsumer); + void changeReturnTypeDirectWithContext(ClassDesc newReturnType, Method staticHandler, TargetedMethodMatcher targetedMethodMatcher); void changeFieldToMethod(@Nullable String getterName, @Nullable String setterName, boolean isInterfaceMethod, Consumer builderConsumer); - default void moveInstanceMethod(final Class newOwner, final String newMethodName, final Consumer builderConsumer) { - this.moveInstanceMethod(desc(newOwner), newMethodName, builderConsumer); + default void moveInstanceMethod(final Class newOwner, final String newMethodName, final MethodMatcher methodMatcher) { + this.moveInstanceMethod(desc(newOwner), newMethodName, methodMatcher); } - void moveInstanceMethod(ClassDesc newOwner, String newMethodName, Consumer builderConsumer); + void moveInstanceMethod(ClassDesc newOwner, String newMethodName, MethodMatcher methodMatcher); void addRule(RewriteRule rule); diff --git a/src/main/java/io/papermc/asm/rules/builder/RuleFactoryImpl.java b/src/main/java/io/papermc/asm/rules/builder/RuleFactoryImpl.java index e37e21d..55f1871 100644 --- a/src/main/java/io/papermc/asm/rules/builder/RuleFactoryImpl.java +++ b/src/main/java/io/papermc/asm/rules/builder/RuleFactoryImpl.java @@ -1,9 +1,9 @@ package io.papermc.asm.rules.builder; import io.papermc.asm.rules.RewriteRule; -import io.papermc.asm.rules.builder.matcher.FieldMatcher; -import io.papermc.asm.rules.builder.matcher.MethodMatcher; -import io.papermc.asm.rules.builder.matcher.TargetedMethodMatcher; +import io.papermc.asm.rules.builder.matcher.field.FieldMatcher; +import io.papermc.asm.rules.builder.matcher.method.MethodMatcher; +import io.papermc.asm.rules.builder.matcher.method.targeted.TargetedMethodMatcher; import io.papermc.asm.rules.field.FieldToMethodRewrite; import io.papermc.asm.rules.method.DirectStaticRewrite; import io.papermc.asm.rules.method.MoveInstanceMethod; @@ -39,43 +39,42 @@ private static > M build(final Consumer build } @Override - public void plainStaticRewrite(final ClassDesc newOwner, final Consumer builderConsumer) { - this.addRule(new DirectStaticRewrite(this.owners, build(builderConsumer, MethodMatcher::builder), newOwner)); + public void plainStaticRewrite(final ClassDesc newOwner, final MethodMatcher methodMatcher) { + this.addRule(new DirectStaticRewrite(this.owners, methodMatcher, newOwner)); } @Override - public void changeParamToSuper(final ClassDesc legacyParamType, final ClassDesc newParamType, final Consumer builderConsumer) { - this.addRule(new SuperTypeParamRewrite(this.owners, build(builderConsumer, MethodMatcher::builder), legacyParamType, newParamType)); + public void changeParamToSuper(final ClassDesc legacyParamType, final ClassDesc newParamType, final MethodMatcher methodMatcher) { + this.addRule(new SuperTypeParamRewrite(this.owners, methodMatcher, legacyParamType, newParamType)); } @Override - public void changeParamFuzzy(final ClassDesc newParamType, final Method staticHandler, final Consumer builderConsumer) { - this.addRule(new FuzzyParameterRewrite(this.owners, newParamType, build(builderConsumer, MethodMatcher::targeted), isStatic(staticHandler))); + public void changeParamFuzzy(final ClassDesc newParamType, final Method staticHandler, final TargetedMethodMatcher targetedMethodMatcher) { + this.addRule(new FuzzyParameterRewrite(this.owners, newParamType, targetedMethodMatcher, isStatic(staticHandler))); } @Override - public void changeParamDirect(final ClassDesc newParamType, final Method staticHandler, final Consumer builderConsumer) { - this.addRule(new DirectParameterRewrite(this.owners, newParamType, build(builderConsumer, MethodMatcher::targeted), isStatic(staticHandler))); + public void changeParamDirect(final ClassDesc newParamType, final Method staticHandler, final TargetedMethodMatcher targetedMethodMatcher) { + this.addRule(new DirectParameterRewrite(this.owners, newParamType, targetedMethodMatcher, isStatic(staticHandler))); } @Override - public void changeReturnTypeToSub(final ClassDesc oldReturnType, final ClassDesc newReturnType, final Consumer builderConsumer) { - this.addRule(new SubTypeReturnRewrite(this.owners, build(builderConsumer, MethodMatcher::builder), oldReturnType, newReturnType)); + public void changeReturnTypeToSub(final ClassDesc oldReturnType, final ClassDesc newReturnType, final MethodMatcher methodMatcher) { + this.addRule(new SubTypeReturnRewrite(this.owners, methodMatcher, oldReturnType, newReturnType)); } @Override - public void changeReturnTypeDirect(final ClassDesc newReturnType, final Method staticHandler, final Consumer builderConsumer) { - this.changeReturnTypeDirect(newReturnType, staticHandler, builderConsumer, false); + public void changeReturnTypeDirect(final ClassDesc newReturnType, final Method staticHandler, final TargetedMethodMatcher targetedMethodMatcher) { + this.changeReturnTypeDirect(newReturnType, staticHandler, targetedMethodMatcher, false); } @Override - public void changeReturnTypeDirectWithContext(final ClassDesc newReturnType, final Method staticHandler, final Consumer builderConsumer) { - this.changeReturnTypeDirect(newReturnType, staticHandler, builderConsumer, true); + public void changeReturnTypeDirectWithContext(final ClassDesc newReturnType, final Method staticHandler, final TargetedMethodMatcher targetedMethodMatcher) { + this.changeReturnTypeDirect(newReturnType, staticHandler, targetedMethodMatcher, true); } - private void changeReturnTypeDirect(final ClassDesc newReturnType, final Method staticHandler, final Consumer builderConsumer, final boolean includeOwnerContext) { - final TargetedMethodMatcher matcher = build(builderConsumer, MethodMatcher::targeted); - this.addRule(new DirectReturnRewrite(this.owners, newReturnType, matcher, isStatic(staticHandler), includeOwnerContext)); + private void changeReturnTypeDirect(final ClassDesc newReturnType, final Method staticHandler, final TargetedMethodMatcher targetedMethodMatcher, final boolean includeOwnerContext) { + this.addRule(new DirectReturnRewrite(this.owners, newReturnType, targetedMethodMatcher, isStatic(staticHandler), includeOwnerContext)); } @Override @@ -84,8 +83,8 @@ public void changeFieldToMethod(final @Nullable String getterName, final @Nullab } @Override - public void moveInstanceMethod(final ClassDesc newOwner, final String newMethodName, final Consumer builderConsumer) { - this.addRule(new MoveInstanceMethod(this.owners, build(builderConsumer, MethodMatcher::builder), newOwner, newMethodName)); + public void moveInstanceMethod(final ClassDesc newOwner, final String newMethodName, final MethodMatcher methodMatcher) { + this.addRule(new MoveInstanceMethod(this.owners, methodMatcher, newOwner, newMethodName)); } @Override diff --git a/src/main/java/io/papermc/asm/rules/builder/matcher/MethodMatcher.java b/src/main/java/io/papermc/asm/rules/builder/matcher/MethodMatcher.java deleted file mode 100644 index f106401..0000000 --- a/src/main/java/io/papermc/asm/rules/builder/matcher/MethodMatcher.java +++ /dev/null @@ -1,132 +0,0 @@ -package io.papermc.asm.rules.builder.matcher; - -import io.papermc.asm.rules.method.StaticRewrite; -import java.lang.constant.MethodTypeDesc; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Set; -import java.util.function.BiPredicate; -import java.util.function.Predicate; - -@FunctionalInterface -public interface MethodMatcher { - - boolean matches(int opcode, boolean isInvokeDynamic, String name, String descriptor); - - default boolean matches(final int opcode, final boolean isInvokeDynamic, final String name, final MethodTypeDesc descriptor) { - return this.matches(opcode, isInvokeDynamic, name, descriptor.descriptorString()); - } - - /** - * Creates a method matcher that matches if either matcher passes. - * - * @param other the other matcher - * @return a new "or" matcher - */ - default MethodMatcher or(final MethodMatcher other) { - return (opcode, isInvokeDynamic, name, descriptor) -> this.matches(opcode, isInvokeDynamic, name, descriptor) || other.matches(opcode, isInvokeDynamic, name, descriptor); - } - - /** - * Creates a method matcher that matches if both matcher pass. - * - * @param other the other matcher - * @return a new "and" matcher - */ - default MethodMatcher and(final MethodMatcher other) { - return (opcode, isInvokeDynamic, name, descriptor) -> this.matches(opcode, isInvokeDynamic, name, descriptor) && other.matches(opcode, isInvokeDynamic, name, descriptor); - } - - /** - * Creates a method matcher that is the inverse of this matcher. - * - * @return the inverse matcher - */ - default MethodMatcher negate() { - return (opcode, isInvokeDynamic, name, descriptor) -> !this.matches(opcode, isInvokeDynamic, name, descriptor); - } - - static Builder builder() { - return new Builder(); - } - - static TargetedMethodMatcher.Builder targeted() { - return new TargetedMethodMatcher.Builder(); - } - - final class Builder implements io.papermc.asm.util.Builder { - private MethodMatcher matcher = (o, isInvokeDynamic, n, d) -> false; - - private Builder() { - } - - public final class MatchBuilder { - - private final Collection names; - private Predicate bytecodeDescPredicate = $ -> false; - private BiPredicate opcodePredicate = ($, $$) -> true; - - private MatchBuilder(final Collection names) { - this.names = names; - } - - public MatchBuilder type(final MethodType...types) { - this.opcodePredicate = (o, b) -> Arrays.stream(types).anyMatch(type -> type.matches(o, b)); - return this; - } - - public MatchBuilder virtual() { - return this.type(MethodType.VIRTUAL); - } - - public MatchBuilder statik() { - return this.type(MethodType.STATIC); - } - - public Builder desc(final String...descriptors) { - return this.desc(desc -> Arrays.stream(descriptors).anyMatch(d -> desc.descriptorString().equals(d))); - } - - public Builder desc(final MethodTypeDesc...descriptors) { - return this.desc(desc -> Arrays.asList(descriptors).contains(desc)); - } - - public Builder desc(final Predicate descPredicate) { - this.bytecodeDescPredicate = descPredicate; - return this.build(); - } - - public Builder build() { - Builder.this.matcher = Builder.this.matcher.or((opcode, isInvokeDynamic, name, descriptor) -> - this.names.contains(name) && this.bytecodeDescPredicate.test(MethodTypeDesc.ofDescriptor(descriptor)) && this.opcodePredicate.test(opcode, isInvokeDynamic) - ); - return Builder.this; - } - } - - public MatchBuilder ctor() { - return this.match(StaticRewrite.CONSTRUCTOR_METHOD_NAME); - } - - public MatchBuilder match(final String name) { - return this.match(Collections.singleton(name)); - } - - public MatchBuilder match(final String...names) { - return this.match(Set.of(names)); - } - - public MatchBuilder match(final Collection names) { - return new MatchBuilder(names); - } - - // insert new helper methods as needed - - @Override - public MethodMatcher build() { - // copy to preserve immutability - return (opcode, isInvokeDynamic, name, descriptor) -> this.matcher.matches(opcode, isInvokeDynamic, name, descriptor); - } - } -} diff --git a/src/main/java/io/papermc/asm/rules/builder/matcher/TargetedMethodMatcher.java b/src/main/java/io/papermc/asm/rules/builder/matcher/TargetedMethodMatcher.java deleted file mode 100644 index a96610d..0000000 --- a/src/main/java/io/papermc/asm/rules/builder/matcher/TargetedMethodMatcher.java +++ /dev/null @@ -1,71 +0,0 @@ -package io.papermc.asm.rules.builder.matcher; - -import io.papermc.asm.rules.method.StaticRewrite; -import java.lang.constant.ClassDesc; -import java.lang.constant.MethodTypeDesc; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.function.IntPredicate; -import java.util.function.Predicate; -import org.checkerframework.checker.nullness.qual.MonotonicNonNull; - -import static java.util.Objects.requireNonNull; - -public interface TargetedMethodMatcher extends MethodMatcher { - - ClassDesc targetType(); - - class Builder implements io.papermc.asm.util.Builder { - - private Predicate byName = $ -> false; - private Predicate byDesc = $ -> false; - private IntPredicate opcodePredicate = $ -> true; - private @MonotonicNonNull ClassDesc oldType; - - Builder() { - } - - public Builder ctor() { - return this.names(StaticRewrite.CONSTRUCTOR_METHOD_NAME); - } - - public Builder names(final String... names) { - return this.names(List.of(names)); - } - - public Builder names(final Collection names) { - this.byName = this.byName.or(names::contains); - return this; - } - - public Builder opcode(final int...opcodes) { - this.opcodePredicate = o -> Arrays.stream(opcodes).anyMatch(opcode -> opcode == o); - return this; - } - - public Builder containsParam(final ClassDesc classDesc) { - this.oldType = classDesc; - this.byDesc = d -> d.parameterList().contains(classDesc); - return this; - } - - public Builder hasReturn(final ClassDesc classDesc) { - this.oldType = classDesc; - this.byDesc = d -> d.returnType().equals(classDesc); - return this; - } - - public Builder desc(final Predicate predicate) { - this.byDesc = this.byDesc.and(predicate); - return this; - } - - @Override - public TargetedMethodMatcher build() { - final MethodMatcher matcher = (opcode, isInvokeDynamic, name, descriptor) -> - this.opcodePredicate.test(opcode) && this.byName.test(name) && this.byDesc.test(MethodTypeDesc.ofDescriptor(descriptor)); - return new TargetedMethodMatcherImpl(matcher, requireNonNull(this.oldType)); - } - } -} diff --git a/src/main/java/io/papermc/asm/rules/builder/matcher/FieldMatcher.java b/src/main/java/io/papermc/asm/rules/builder/matcher/field/FieldMatcher.java similarity index 96% rename from src/main/java/io/papermc/asm/rules/builder/matcher/FieldMatcher.java rename to src/main/java/io/papermc/asm/rules/builder/matcher/field/FieldMatcher.java index d12b073..0eee7c4 100644 --- a/src/main/java/io/papermc/asm/rules/builder/matcher/FieldMatcher.java +++ b/src/main/java/io/papermc/asm/rules/builder/matcher/field/FieldMatcher.java @@ -1,4 +1,4 @@ -package io.papermc.asm.rules.builder.matcher; +package io.papermc.asm.rules.builder.matcher.field; import java.lang.constant.ClassDesc; import java.util.Collection; diff --git a/src/main/java/io/papermc/asm/rules/builder/matcher/FieldMatcherImpl.java b/src/main/java/io/papermc/asm/rules/builder/matcher/field/FieldMatcherImpl.java similarity index 93% rename from src/main/java/io/papermc/asm/rules/builder/matcher/FieldMatcherImpl.java rename to src/main/java/io/papermc/asm/rules/builder/matcher/field/FieldMatcherImpl.java index a424aee..e93a8de 100644 --- a/src/main/java/io/papermc/asm/rules/builder/matcher/FieldMatcherImpl.java +++ b/src/main/java/io/papermc/asm/rules/builder/matcher/field/FieldMatcherImpl.java @@ -1,4 +1,4 @@ -package io.papermc.asm.rules.builder.matcher; +package io.papermc.asm.rules.builder.matcher.field; import java.lang.constant.ClassDesc; import java.util.function.Predicate; diff --git a/src/main/java/io/papermc/asm/rules/builder/matcher/method/MethodMatcher.java b/src/main/java/io/papermc/asm/rules/builder/matcher/method/MethodMatcher.java new file mode 100644 index 0000000..f5f54ed --- /dev/null +++ b/src/main/java/io/papermc/asm/rules/builder/matcher/method/MethodMatcher.java @@ -0,0 +1,59 @@ +package io.papermc.asm.rules.builder.matcher.method; + +import java.lang.constant.MethodTypeDesc; +import java.util.function.Predicate; + +@FunctionalInterface +public interface MethodMatcher { + + static MethodMatcherBuilder builder() { + return new MethodMatcherBuilderImpl(); + } + + boolean matches(int opcode, boolean isInvokeDynamic, String name, String descriptor); + + default boolean matches(final int opcode, final boolean isInvokeDynamic, final String name, final MethodTypeDesc descriptor) { + return this.matches(opcode, isInvokeDynamic, name, descriptor.descriptorString()); + } + + /** + * Creates a method matcher that matches if either matcher passes. + * + * @param other the other matcher + * @return a new "or" matcher + */ + default MethodMatcher or(final MethodMatcher other) { + return (opcode, isInvokeDynamic, name, descriptor) -> this.matches(opcode, isInvokeDynamic, name, descriptor) || other.matches(opcode, isInvokeDynamic, name, descriptor); + } + + /** + * Creates a method matcher that matches if both matcher pass. + * + * @param other the other matcher + * @return a new "and" matcher + * @see #and(Predicate) + */ + default MethodMatcher and(final MethodMatcher other) { + return (opcode, isInvokeDynamic, name, descriptor) -> this.matches(opcode, isInvokeDynamic, name, descriptor) && other.matches(opcode, isInvokeDynamic, name, descriptor); + } + + /** + * Creates a method matcher tha matches if both this matcher + * and the method descriptor predicate pass. + * + * @param descPredicate the method descriptor predicate + * @return a new "and" matcher + */ + default MethodMatcher and(final Predicate descPredicate) { + return (opcode, isInvokeDynamic, name, descriptor) -> this.matches(opcode, isInvokeDynamic, name, descriptor) && descPredicate.test(MethodTypeDesc.ofDescriptor(descriptor)); + } + + /** + * Creates a method matcher that is the inverse of this matcher. + * + * @return the inverse matcher + */ + default MethodMatcher negate() { + return (opcode, isInvokeDynamic, name, descriptor) -> !this.matches(opcode, isInvokeDynamic, name, descriptor); + } +} diff --git a/src/main/java/io/papermc/asm/rules/builder/matcher/method/MethodMatcherBuilder.java b/src/main/java/io/papermc/asm/rules/builder/matcher/method/MethodMatcherBuilder.java new file mode 100644 index 0000000..edaa332 --- /dev/null +++ b/src/main/java/io/papermc/asm/rules/builder/matcher/method/MethodMatcherBuilder.java @@ -0,0 +1,45 @@ +package io.papermc.asm.rules.builder.matcher.method; + +import io.papermc.asm.util.Builder; +import java.lang.constant.ClassDesc; +import java.lang.constant.MethodTypeDesc; +import java.util.Collection; +import java.util.function.Consumer; +import java.util.function.Predicate; + +public interface MethodMatcherBuilder extends Builder { + + MethodMatcherBuilder ctor(final Consumer matchBuilderConsumer); + + MethodMatcherBuilder match(final String name, final Consumer matchBuilderConsumer); + + MethodMatcherBuilder match(final Collection names, final Consumer matchBuilderConsumer); + + MethodMatcherBuilder hasParam(final ClassDesc paramClassDesc); + + MethodMatcherBuilder hasReturn(final ClassDesc returnClassDesc); + + /** + * Used to match methods with specific names. + * + * @see MethodMatcherBuilder#match(String, Consumer) + */ + interface MatchBuilder { + + MatchBuilder virtual(); + + MatchBuilder statik(); + + MatchBuilder type(final MethodType... types); + + MatchBuilder hasParam(final ClassDesc paramClassDesc); + + MatchBuilder hasReturn(final ClassDesc returnClassDesc); + + MatchBuilder desc(final String... descriptors); + + MatchBuilder desc(final MethodTypeDesc... descriptors); + + MatchBuilder desc(final Predicate descPredicate); + } +} diff --git a/src/main/java/io/papermc/asm/rules/builder/matcher/method/MethodMatcherBuilderImpl.java b/src/main/java/io/papermc/asm/rules/builder/matcher/method/MethodMatcherBuilderImpl.java new file mode 100644 index 0000000..c080d66 --- /dev/null +++ b/src/main/java/io/papermc/asm/rules/builder/matcher/method/MethodMatcherBuilderImpl.java @@ -0,0 +1,118 @@ +package io.papermc.asm.rules.builder.matcher.method; + +import io.papermc.asm.rules.method.StaticRewrite; +import java.lang.constant.ClassDesc; +import java.lang.constant.MethodTypeDesc; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Set; +import java.util.function.BiPredicate; +import java.util.function.Consumer; +import java.util.function.Predicate; + +class MethodMatcherBuilderImpl implements MethodMatcherBuilder { + private MethodMatcher matcher = (o, isInvokeDynamic, n, d) -> false; + + MethodMatcherBuilderImpl() { + } + + @Override + public MethodMatcher build() { + return this.matcher; + } + + @Override + public MethodMatcherBuilder ctor(final Consumer matchBuilderConsumer) { + final Consumer ctorConsumer = b -> b.type(MethodType.SPECIAL); + return this.match(StaticRewrite.CONSTRUCTOR_METHOD_NAME, ctorConsumer.andThen(matchBuilderConsumer)); + } + + @Override + public MethodMatcherBuilder match(final String name, final Consumer matchBuilderConsumer) { + return this.match(Collections.singleton(name), matchBuilderConsumer); + } + + @Override + public MethodMatcherBuilder match(final Collection names, final Consumer matchBuilderConsumer) { + final Collection namesCopy = Set.copyOf(names); + final SpecificMatchBuilder matchBuilder = new SpecificMatchBuilder(namesCopy::contains); + matchBuilderConsumer.accept(matchBuilder); + matchBuilder.apply(); + return this; + } + + @Override + public MethodMatcherBuilder hasParam(final ClassDesc paramClassDesc) { + return this.desc(d -> d.parameterList().contains(paramClassDesc)); + } + + @Override + public MethodMatcherBuilder hasReturn(final ClassDesc returnClassDesc) { + return this.desc(d -> d.returnType().equals(returnClassDesc)); + } + + private MethodMatcherBuilder desc(final Predicate descPredicate) { + this.matcher = this.matcher.and(descPredicate); + return this; + } + + final class SpecificMatchBuilder implements MatchBuilder { + + private final Predicate namePredicate; + private Predicate bytecodeDescPredicate = $ -> true; + private BiPredicate opcodePredicate = ($, $$) -> true; + + private SpecificMatchBuilder(final Predicate namePredicate) { + this.namePredicate = namePredicate; + } + + private void apply() { + MethodMatcherBuilderImpl.this.matcher = MethodMatcherBuilderImpl.this.matcher.or((o, isInvokeDynamic, n, d) -> { + return this.namePredicate.test(n) && this.opcodePredicate.test(o, isInvokeDynamic) && this.bytecodeDescPredicate.test(MethodTypeDesc.ofDescriptor(d)); + }); + } + + @Override + public MatchBuilder virtual() { + return this.type(MethodType.VIRTUAL); + } + + @Override + public MatchBuilder statik() { + return this.type(MethodType.STATIC); + } + + @Override + public MatchBuilder type(final MethodType...types) { + this.opcodePredicate = (o, b) -> Arrays.stream(types).anyMatch(type -> type.matches(o, b)); + return this; + } + + @Override + public MatchBuilder hasParam(final ClassDesc paramClassDesc) { + return this.desc(d -> d.parameterList().contains(paramClassDesc)); + } + + @Override + public MatchBuilder hasReturn(final ClassDesc returnClassDesc) { + return this.desc(d -> d.returnType().equals(returnClassDesc)); + } + + @Override + public MatchBuilder desc(final String...descriptors) { + return this.desc(desc -> Arrays.stream(descriptors).anyMatch(d -> desc.descriptorString().equals(d))); + } + + @Override + public MatchBuilder desc(final MethodTypeDesc...descriptors) { + return this.desc(desc -> Arrays.asList(descriptors).contains(desc)); + } + + @Override + public MatchBuilder desc(final Predicate descPredicate) { + this.bytecodeDescPredicate = descPredicate; + return this; + } + } +} diff --git a/src/main/java/io/papermc/asm/rules/builder/matcher/MethodType.java b/src/main/java/io/papermc/asm/rules/builder/matcher/method/MethodType.java similarity index 91% rename from src/main/java/io/papermc/asm/rules/builder/matcher/MethodType.java rename to src/main/java/io/papermc/asm/rules/builder/matcher/method/MethodType.java index 8076674..64b577f 100644 --- a/src/main/java/io/papermc/asm/rules/builder/matcher/MethodType.java +++ b/src/main/java/io/papermc/asm/rules/builder/matcher/method/MethodType.java @@ -1,4 +1,4 @@ -package io.papermc.asm.rules.builder.matcher; +package io.papermc.asm.rules.builder.matcher.method; import io.papermc.asm.util.OpcodeUtils; import java.util.function.BiPredicate; diff --git a/src/main/java/io/papermc/asm/rules/builder/matcher/method/OpcodePredicate.java b/src/main/java/io/papermc/asm/rules/builder/matcher/method/OpcodePredicate.java new file mode 100644 index 0000000..683ca8d --- /dev/null +++ b/src/main/java/io/papermc/asm/rules/builder/matcher/method/OpcodePredicate.java @@ -0,0 +1,7 @@ +package io.papermc.asm.rules.builder.matcher.method; + +@FunctionalInterface +public interface OpcodePredicate { + + boolean matches(int opcode, boolean isInvokeDynamic); +} diff --git a/src/main/java/io/papermc/asm/rules/builder/matcher/method/targeted/TargetedMethodMatcher.java b/src/main/java/io/papermc/asm/rules/builder/matcher/method/targeted/TargetedMethodMatcher.java new file mode 100644 index 0000000..e6bf476 --- /dev/null +++ b/src/main/java/io/papermc/asm/rules/builder/matcher/method/targeted/TargetedMethodMatcher.java @@ -0,0 +1,13 @@ +package io.papermc.asm.rules.builder.matcher.method.targeted; + +import io.papermc.asm.rules.builder.matcher.method.MethodMatcher; +import java.lang.constant.ClassDesc; + +public interface TargetedMethodMatcher extends MethodMatcher { + + static TargetedMethodMatcherBuilder builder() { + return new TargetedMethodMatcherBuilderImpl(); + } + + ClassDesc targetType(); +} diff --git a/src/main/java/io/papermc/asm/rules/builder/matcher/method/targeted/TargetedMethodMatcherBuilder.java b/src/main/java/io/papermc/asm/rules/builder/matcher/method/targeted/TargetedMethodMatcherBuilder.java new file mode 100644 index 0000000..caba1cc --- /dev/null +++ b/src/main/java/io/papermc/asm/rules/builder/matcher/method/targeted/TargetedMethodMatcherBuilder.java @@ -0,0 +1,29 @@ +package io.papermc.asm.rules.builder.matcher.method.targeted; + +import io.papermc.asm.rules.builder.matcher.method.MethodType; +import io.papermc.asm.util.Builder; +import java.lang.constant.ClassDesc; +import java.util.Collection; +import java.util.function.Consumer; + +public interface TargetedMethodMatcherBuilder extends Builder { + + TargetedMethodMatcherBuilder ctor(); + + TargetedMethodMatcherBuilder match(final String name, final Consumer matchBuilderConsumer); + + TargetedMethodMatcherBuilder match(final Collection names, final Consumer matchBuilderConsumer); + + TargetedMethodMatcherBuilder hasParam(final ClassDesc paramClassDesc); + + TargetedMethodMatcherBuilder hasReturn(final ClassDesc returnClassDesc); + + interface MatchBuilder { + + MatchBuilder virtual(); + + MatchBuilder statik(); + + MatchBuilder type(final MethodType... types); + } +} diff --git a/src/main/java/io/papermc/asm/rules/builder/matcher/method/targeted/TargetedMethodMatcherBuilderImpl.java b/src/main/java/io/papermc/asm/rules/builder/matcher/method/targeted/TargetedMethodMatcherBuilderImpl.java new file mode 100644 index 0000000..bf8efdd --- /dev/null +++ b/src/main/java/io/papermc/asm/rules/builder/matcher/method/targeted/TargetedMethodMatcherBuilderImpl.java @@ -0,0 +1,105 @@ +package io.papermc.asm.rules.builder.matcher.method.targeted; + +import io.papermc.asm.rules.builder.matcher.method.MethodMatcher; +import io.papermc.asm.rules.builder.matcher.method.MethodType; +import io.papermc.asm.rules.builder.matcher.method.OpcodePredicate; +import io.papermc.asm.rules.method.StaticRewrite; +import java.lang.constant.ClassDesc; +import java.lang.constant.MethodTypeDesc; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Set; +import java.util.function.Consumer; +import java.util.function.Predicate; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; + +class TargetedMethodMatcherBuilderImpl implements TargetedMethodMatcherBuilder { + + private MethodMatcher matcher = (opcode, isInvokeDynamic, name, descriptor) -> false; + private @MonotonicNonNull Predicate byDesc; + private @MonotonicNonNull ClassDesc oldType; + + TargetedMethodMatcherBuilderImpl() { + } + + @Override + public TargetedMethodMatcherBuilder ctor() { + return this.match(StaticRewrite.CONSTRUCTOR_METHOD_NAME, b -> b.type(MethodType.SPECIAL)); + } + + @Override + public TargetedMethodMatcherBuilder match(final String name, final Consumer matchBuilderConsumer) { + return this.match(Collections.singleton(name), matchBuilderConsumer); + } + + @Override + public TargetedMethodMatcherBuilder match(final Collection names, final Consumer matchBuilderConsumer) { + final Collection namesCopy = Set.copyOf(names); + final SpecificMatchBuilder matchBuilder = new SpecificMatchBuilder(namesCopy::contains); + matchBuilderConsumer.accept(matchBuilder); + matchBuilder.apply(); + return this; + } + + @Override + public TargetedMethodMatcherBuilder hasParam(final ClassDesc classDesc) { + if (this.oldType != null) { + throw new IllegalArgumentException("Targeted type was already set to " + this.oldType); + } + this.oldType = classDesc; + this.byDesc = d -> d.parameterList().contains(classDesc); + return this; + } + + @Override + public TargetedMethodMatcherBuilder hasReturn(final ClassDesc classDesc) { + if (this.oldType != null) { + throw new IllegalArgumentException("Targeted type was already set to " + this.oldType); + } + this.oldType = classDesc; + this.byDesc = d -> d.returnType().equals(classDesc); + return this; + } + + @Override + public TargetedMethodMatcher build() { + if (this.oldType == null || this.byDesc == null) { + throw new IllegalStateException("Targeted type was not set"); + } + final MethodMatcher finalMatcher = this.matcher.and(this.byDesc); + return new TargetedMethodMatcherImpl(finalMatcher, this.oldType); + } + + final class SpecificMatchBuilder implements TargetedMethodMatcherBuilder.MatchBuilder { + + private final Predicate namePredicate; + private @MonotonicNonNull OpcodePredicate opcodePredicate; + + private SpecificMatchBuilder(final Predicate namePredicate) { + this.namePredicate = namePredicate; + } + + private void apply() { + TargetedMethodMatcherBuilderImpl.this.matcher = TargetedMethodMatcherBuilderImpl.this.matcher.or((o, isInvokeDynamic, n, d) -> { + return this.namePredicate.test(n) && this.opcodePredicate.matches(o, isInvokeDynamic); + }); + } + + @Override + public TargetedMethodMatcherBuilder.MatchBuilder virtual() { + return this.type(MethodType.VIRTUAL); + } + + @Override + public TargetedMethodMatcherBuilder.MatchBuilder statik() { + return this.type(MethodType.STATIC); + } + + @Override + public TargetedMethodMatcherBuilder.MatchBuilder type(final MethodType... types) { + this.opcodePredicate = (o, b) -> Arrays.stream(types).anyMatch(type -> type.matches(o, b)); + return this; + } + } +} diff --git a/src/main/java/io/papermc/asm/rules/builder/matcher/TargetedMethodMatcherImpl.java b/src/main/java/io/papermc/asm/rules/builder/matcher/method/targeted/TargetedMethodMatcherImpl.java similarity index 86% rename from src/main/java/io/papermc/asm/rules/builder/matcher/TargetedMethodMatcherImpl.java rename to src/main/java/io/papermc/asm/rules/builder/matcher/method/targeted/TargetedMethodMatcherImpl.java index b97d794..ff0cab7 100644 --- a/src/main/java/io/papermc/asm/rules/builder/matcher/TargetedMethodMatcherImpl.java +++ b/src/main/java/io/papermc/asm/rules/builder/matcher/method/targeted/TargetedMethodMatcherImpl.java @@ -1,5 +1,6 @@ -package io.papermc.asm.rules.builder.matcher; +package io.papermc.asm.rules.builder.matcher.method.targeted; +import io.papermc.asm.rules.builder.matcher.method.MethodMatcher; import java.lang.constant.ClassDesc; public class TargetedMethodMatcherImpl implements TargetedMethodMatcher { diff --git a/src/main/java/io/papermc/asm/rules/classes/EnumToInterfaceRule.java b/src/main/java/io/papermc/asm/rules/classes/EnumToInterfaceRule.java index 77639ce..5608b9d 100644 --- a/src/main/java/io/papermc/asm/rules/classes/EnumToInterfaceRule.java +++ b/src/main/java/io/papermc/asm/rules/classes/EnumToInterfaceRule.java @@ -2,7 +2,7 @@ import io.papermc.asm.ClassProcessingContext; import io.papermc.asm.rules.RewriteRule; -import io.papermc.asm.rules.builder.matcher.MethodMatcher; +import io.papermc.asm.rules.builder.matcher.method.MethodMatcher; import io.papermc.asm.rules.method.DirectStaticRewrite; import io.papermc.asm.rules.method.OwnableMethodRewriteRule; import io.papermc.asm.rules.method.generated.GeneratedStaticRewrite; @@ -30,11 +30,11 @@ public class EnumToInterfaceRule implements RewriteRule.Delegate { private static final MethodMatcher ENUM_VIRTUAL_METHODS = MethodMatcher.builder() - .match("name").virtual().desc(MethodTypeDesc.of(ConstantDescs.CD_String)) - .match("ordinal").virtual().desc(MethodTypeDesc.of(ConstantDescs.CD_int)) - .match("compareTo").virtual().desc(MethodTypeDesc.of(ConstantDescs.CD_int, ConstantDescs.CD_Enum)) - .match("getDeclaringClass").virtual().desc(MethodTypeDesc.of(ConstantDescs.CD_Class)) - .match("describeConstable").virtual().desc(MethodTypeDesc.of(desc(Optional.class))) + .match("name", b -> b.virtual().desc(MethodTypeDesc.of(ConstantDescs.CD_String))) + .match("ordinal", b -> b.virtual().desc(MethodTypeDesc.of(ConstantDescs.CD_int))) + .match("compareTo", b -> b.virtual().desc(MethodTypeDesc.of(ConstantDescs.CD_int, ConstantDescs.CD_Enum))) + .match("getDeclaringClass", b -> b.virtual().desc(MethodTypeDesc.of(ConstantDescs.CD_Class))) + .match("describeConstable", b -> b.virtual().desc(MethodTypeDesc.of(desc(Optional.class)))) .build(); private static final MethodMatcher NOT_ENUM_METHODS_BASE = ENUM_VIRTUAL_METHODS.negate(); @@ -66,8 +66,8 @@ public RewriteRule delegate() { private static MethodMatcher createStaticMatcher(final ClassDesc legacyEnumType) { return MethodMatcher.builder() - .match("values").statik().desc(MethodTypeDesc.of(legacyEnumType.arrayType())) - .match("valueOf").statik().desc(MethodTypeDesc.of(legacyEnumType, ConstantDescs.CD_String)) + .match("values", b -> b.statik().desc(MethodTypeDesc.of(legacyEnumType.arrayType()))) + .match("valueOf", b -> b.statik().desc(MethodTypeDesc.of(legacyEnumType, ConstantDescs.CD_String))) .build(); } diff --git a/src/main/java/io/papermc/asm/rules/field/FieldToMethodRewrite.java b/src/main/java/io/papermc/asm/rules/field/FieldToMethodRewrite.java index 43c3b58..c9cbdcb 100644 --- a/src/main/java/io/papermc/asm/rules/field/FieldToMethodRewrite.java +++ b/src/main/java/io/papermc/asm/rules/field/FieldToMethodRewrite.java @@ -1,7 +1,7 @@ package io.papermc.asm.rules.field; import io.papermc.asm.ClassProcessingContext; -import io.papermc.asm.rules.builder.matcher.FieldMatcher; +import io.papermc.asm.rules.builder.matcher.field.FieldMatcher; import java.lang.constant.ClassDesc; import java.lang.constant.ConstantDescs; import java.lang.constant.MethodTypeDesc; diff --git a/src/main/java/io/papermc/asm/rules/field/FilteredFieldRewriteRule.java b/src/main/java/io/papermc/asm/rules/field/FilteredFieldRewriteRule.java index 130ede2..165ad17 100644 --- a/src/main/java/io/papermc/asm/rules/field/FilteredFieldRewriteRule.java +++ b/src/main/java/io/papermc/asm/rules/field/FilteredFieldRewriteRule.java @@ -2,7 +2,7 @@ import io.papermc.asm.ClassProcessingContext; import io.papermc.asm.rules.OwnableRewriteRule; -import io.papermc.asm.rules.builder.matcher.FieldMatcher; +import io.papermc.asm.rules.builder.matcher.field.FieldMatcher; /** * A rule that targets specific fields and owners. diff --git a/src/main/java/io/papermc/asm/rules/method/DirectStaticRewrite.java b/src/main/java/io/papermc/asm/rules/method/DirectStaticRewrite.java index 7fa3d20..bd7133c 100644 --- a/src/main/java/io/papermc/asm/rules/method/DirectStaticRewrite.java +++ b/src/main/java/io/papermc/asm/rules/method/DirectStaticRewrite.java @@ -1,7 +1,7 @@ package io.papermc.asm.rules.method; import io.papermc.asm.ClassProcessingContext; -import io.papermc.asm.rules.builder.matcher.MethodMatcher; +import io.papermc.asm.rules.builder.matcher.method.MethodMatcher; import java.lang.constant.ClassDesc; import java.util.Set; diff --git a/src/main/java/io/papermc/asm/rules/method/MoveInstanceMethod.java b/src/main/java/io/papermc/asm/rules/method/MoveInstanceMethod.java index fcec8c5..fd57883 100644 --- a/src/main/java/io/papermc/asm/rules/method/MoveInstanceMethod.java +++ b/src/main/java/io/papermc/asm/rules/method/MoveInstanceMethod.java @@ -1,7 +1,7 @@ package io.papermc.asm.rules.method; import io.papermc.asm.ClassProcessingContext; -import io.papermc.asm.rules.builder.matcher.MethodMatcher; +import io.papermc.asm.rules.builder.matcher.method.MethodMatcher; import io.papermc.asm.rules.method.generated.GeneratedStaticRewrite; import io.papermc.asm.rules.method.rewrite.MethodRewrite; import java.lang.constant.ClassDesc; diff --git a/src/main/java/io/papermc/asm/rules/method/OwnableMethodRewriteRule.java b/src/main/java/io/papermc/asm/rules/method/OwnableMethodRewriteRule.java index bba0de6..f0ac6db 100644 --- a/src/main/java/io/papermc/asm/rules/method/OwnableMethodRewriteRule.java +++ b/src/main/java/io/papermc/asm/rules/method/OwnableMethodRewriteRule.java @@ -2,7 +2,7 @@ import io.papermc.asm.ClassProcessingContext; import io.papermc.asm.rules.OwnableRewriteRule; -import io.papermc.asm.rules.builder.matcher.MethodMatcher; +import io.papermc.asm.rules.builder.matcher.method.MethodMatcher; /** * A rule that targets specific owners. diff --git a/src/main/java/io/papermc/asm/rules/method/generated/TargetedTypeGeneratedStaticRewrite.java b/src/main/java/io/papermc/asm/rules/method/generated/TargetedTypeGeneratedStaticRewrite.java index 55925cd..1f628ab 100644 --- a/src/main/java/io/papermc/asm/rules/method/generated/TargetedTypeGeneratedStaticRewrite.java +++ b/src/main/java/io/papermc/asm/rules/method/generated/TargetedTypeGeneratedStaticRewrite.java @@ -1,6 +1,6 @@ package io.papermc.asm.rules.method.generated; -import io.papermc.asm.rules.builder.matcher.TargetedMethodMatcher; +import io.papermc.asm.rules.builder.matcher.method.targeted.TargetedMethodMatcher; import io.papermc.asm.rules.generate.StaticHandlerGeneratedMethodHolder; import java.lang.constant.ClassDesc; import java.lang.constant.MethodTypeDesc; diff --git a/src/main/java/io/papermc/asm/rules/method/params/DirectParameterRewrite.java b/src/main/java/io/papermc/asm/rules/method/params/DirectParameterRewrite.java index 4b8cc85..678dc32 100644 --- a/src/main/java/io/papermc/asm/rules/method/params/DirectParameterRewrite.java +++ b/src/main/java/io/papermc/asm/rules/method/params/DirectParameterRewrite.java @@ -1,6 +1,6 @@ package io.papermc.asm.rules.method.params; -import io.papermc.asm.rules.builder.matcher.TargetedMethodMatcher; +import io.papermc.asm.rules.builder.matcher.method.targeted.TargetedMethodMatcher; import io.papermc.asm.rules.method.generated.TargetedTypeGeneratedStaticRewrite; import java.lang.constant.ClassDesc; import java.lang.reflect.Method; diff --git a/src/main/java/io/papermc/asm/rules/method/params/FuzzyParameterRewrite.java b/src/main/java/io/papermc/asm/rules/method/params/FuzzyParameterRewrite.java index 315db1b..5d7ed34 100644 --- a/src/main/java/io/papermc/asm/rules/method/params/FuzzyParameterRewrite.java +++ b/src/main/java/io/papermc/asm/rules/method/params/FuzzyParameterRewrite.java @@ -1,7 +1,7 @@ package io.papermc.asm.rules.method.params; import io.papermc.asm.ClassProcessingContext; -import io.papermc.asm.rules.builder.matcher.TargetedMethodMatcher; +import io.papermc.asm.rules.builder.matcher.method.targeted.TargetedMethodMatcher; import io.papermc.asm.rules.method.generated.TargetedTypeGeneratedStaticRewrite; import io.papermc.asm.rules.method.rewrite.MethodRewrite; import java.lang.constant.ClassDesc; diff --git a/src/main/java/io/papermc/asm/rules/method/params/SuperTypeParamRewrite.java b/src/main/java/io/papermc/asm/rules/method/params/SuperTypeParamRewrite.java index 49b02ef..414136d 100644 --- a/src/main/java/io/papermc/asm/rules/method/params/SuperTypeParamRewrite.java +++ b/src/main/java/io/papermc/asm/rules/method/params/SuperTypeParamRewrite.java @@ -1,7 +1,7 @@ package io.papermc.asm.rules.method.params; import io.papermc.asm.ClassProcessingContext; -import io.papermc.asm.rules.builder.matcher.MethodMatcher; +import io.papermc.asm.rules.builder.matcher.method.MethodMatcher; import io.papermc.asm.rules.method.OwnableMethodRewriteRule; import io.papermc.asm.rules.method.rewrite.MethodRewrite; import io.papermc.asm.rules.method.rewrite.SimpleRewrite; diff --git a/src/main/java/io/papermc/asm/rules/method/returns/DirectReturnRewrite.java b/src/main/java/io/papermc/asm/rules/method/returns/DirectReturnRewrite.java index 835475b..d894125 100644 --- a/src/main/java/io/papermc/asm/rules/method/returns/DirectReturnRewrite.java +++ b/src/main/java/io/papermc/asm/rules/method/returns/DirectReturnRewrite.java @@ -1,6 +1,6 @@ package io.papermc.asm.rules.method.returns; -import io.papermc.asm.rules.builder.matcher.TargetedMethodMatcher; +import io.papermc.asm.rules.builder.matcher.method.targeted.TargetedMethodMatcher; import io.papermc.asm.rules.method.generated.TargetedTypeGeneratedStaticRewrite; import java.lang.constant.ClassDesc; import java.lang.reflect.Method; diff --git a/src/main/java/io/papermc/asm/rules/method/returns/SubTypeReturnRewrite.java b/src/main/java/io/papermc/asm/rules/method/returns/SubTypeReturnRewrite.java index 702c728..c8acfd7 100644 --- a/src/main/java/io/papermc/asm/rules/method/returns/SubTypeReturnRewrite.java +++ b/src/main/java/io/papermc/asm/rules/method/returns/SubTypeReturnRewrite.java @@ -1,7 +1,7 @@ package io.papermc.asm.rules.method.returns; import io.papermc.asm.ClassProcessingContext; -import io.papermc.asm.rules.builder.matcher.MethodMatcher; +import io.papermc.asm.rules.builder.matcher.method.MethodMatcher; import io.papermc.asm.rules.method.OwnableMethodRewriteRule; import io.papermc.asm.rules.method.rewrite.MethodRewrite; import io.papermc.asm.rules.method.rewrite.SimpleRewrite; diff --git a/src/test/java/io/papermc/asm/rules/methods/MethodRewritesTest.java b/src/test/java/io/papermc/asm/rules/methods/MethodRewritesTest.java index 799089c..68c7dde 100644 --- a/src/test/java/io/papermc/asm/rules/methods/MethodRewritesTest.java +++ b/src/test/java/io/papermc/asm/rules/methods/MethodRewritesTest.java @@ -6,6 +6,8 @@ import io.papermc.asm.TransformerTest; import io.papermc.asm.checks.TransformerCheck; import io.papermc.asm.rules.RewriteRule; +import io.papermc.asm.rules.builder.matcher.method.MethodMatcher; +import io.papermc.asm.rules.builder.matcher.method.MethodMatcherBuilder; import java.lang.constant.ClassDesc; class MethodRewritesTest { @@ -13,15 +15,18 @@ class MethodRewritesTest { static final ClassDesc PLAYER = Player.class.describeConstable().orElseThrow(); static final ClassDesc ENTITY = Entity.class.describeConstable().orElseThrow(); + @SuppressWarnings("Convert2MethodRef") @TransformerTest("data.methods.inplace.SuperTypeParamUser") void testSuperTypeParam(final TransformerCheck check) { final RewriteRule rule = RewriteRule.forOwnerClass(Methods.class, builder -> { builder.changeParamToSuper( Player.class, Entity.class, - b -> b - .match("consume", "consumeStatic") - .desc(d -> d.parameterList().contains(PLAYER)) + MethodMatcher.builder() + .match("consume", b -> b.virtual()) + .match("consumeStatic", b -> b.statik()) + .hasParam(PLAYER) + .build() ); }); check.run(rule); @@ -33,9 +38,11 @@ void testSubTypeReturn(final TransformerCheck check) { builder.changeReturnTypeToSub( Entity.class, Player.class, - b -> b - .match("get", "getStatic") - .desc(d -> d.returnType().equals(ENTITY)) + MethodMatcher.builder() + .match("get", MethodMatcherBuilder.MatchBuilder::virtual) + .match("getStatic", MethodMatcherBuilder.MatchBuilder::statik) + .hasReturn(ENTITY) + .build() ); }); check.run(rule); diff --git a/src/test/java/io/papermc/asm/rules/methods/StaticMethodRewriteParamsTest.java b/src/test/java/io/papermc/asm/rules/methods/StaticMethodRewriteParamsTest.java index 051bd27..255bb9a 100644 --- a/src/test/java/io/papermc/asm/rules/methods/StaticMethodRewriteParamsTest.java +++ b/src/test/java/io/papermc/asm/rules/methods/StaticMethodRewriteParamsTest.java @@ -7,6 +7,7 @@ import io.papermc.asm.TransformerTest; import io.papermc.asm.checks.TransformerCheck; import io.papermc.asm.rules.RewriteRule; +import io.papermc.asm.rules.builder.matcher.method.targeted.TargetedMethodMatcher; import java.lang.constant.ClassDesc; import java.lang.reflect.Method; @@ -15,6 +16,7 @@ class StaticMethodRewriteParamsTest { static final ClassDesc LOCATION = Location.class.describeConstable().orElseThrow(); static final ClassDesc POSITION = Position.class.describeConstable().orElseThrow(); + @SuppressWarnings("Convert2MethodRef") @TransformerTest("data.methods.statics.param.ParamDirectUser") void testParamDirectStaticRewrite(final TransformerCheck check) throws NoSuchMethodException { final Method handler = Redirects.class.getDeclaredMethod("toPosition", Location.class); @@ -22,19 +24,24 @@ void testParamDirectStaticRewrite(final TransformerCheck check) throws NoSuchMet builder.changeParamDirect( POSITION, handler, - b -> b.names("consumeLoc", "consumeLocStatic").containsParam(LOCATION) + TargetedMethodMatcher.builder() + .match("consumeLoc", b -> b.virtual()) + .match("consumeLocStatic", b -> b.statik()) + .hasParam(LOCATION) + .build() ) ); final RewriteRule ctorRule = RewriteRule.forOwnerClass(Methods.Wrapper.class, builder -> { builder.changeParamDirect( POSITION, handler, - b -> b.ctor().containsParam(LOCATION) + TargetedMethodMatcher.builder().ctor().hasParam(LOCATION).build() ); }); check.run(RewriteRule.chain(rule, ctorRule)); } + @SuppressWarnings("Convert2MethodRef") @TransformerTest("data.methods.statics.param.ParamFuzzyUser") void testParamFuzzyStaticRewrite(final TransformerCheck check) throws NoSuchMethodException { final Method handler = Redirects.class.getDeclaredMethod("toPositionFuzzy", Object.class); @@ -42,14 +49,18 @@ void testParamFuzzyStaticRewrite(final TransformerCheck check) throws NoSuchMeth builder.changeParamFuzzy( POSITION, handler, - b -> b.names("consumePos", "consumePosStatic").containsParam(POSITION) + TargetedMethodMatcher.builder() + .match("consumePos", b -> b.virtual()) + .match("consumePosStatic", b -> b.statik()) + .hasParam(POSITION) + .build() ); }); final RewriteRule ctorRule = RewriteRule.forOwnerClass(Methods.PosWrapper.class, builder -> { builder.changeParamFuzzy( POSITION, handler, - b -> b.ctor().containsParam(POSITION) + TargetedMethodMatcher.builder().ctor().hasParam(POSITION).build() ); }); check.run(RewriteRule.chain(rule, ctorRule)); diff --git a/src/test/java/io/papermc/asm/rules/methods/StaticMethodRewriteReturnsTest.java b/src/test/java/io/papermc/asm/rules/methods/StaticMethodRewriteReturnsTest.java index e6fcde8..3197b9b 100644 --- a/src/test/java/io/papermc/asm/rules/methods/StaticMethodRewriteReturnsTest.java +++ b/src/test/java/io/papermc/asm/rules/methods/StaticMethodRewriteReturnsTest.java @@ -7,6 +7,7 @@ import io.papermc.asm.TransformerTest; import io.papermc.asm.checks.TransformerCheck; import io.papermc.asm.rules.RewriteRule; +import io.papermc.asm.rules.builder.matcher.method.targeted.TargetedMethodMatcher; import java.lang.constant.ClassDesc; import java.lang.reflect.Method; @@ -15,6 +16,7 @@ class StaticMethodRewriteReturnsTest { static final ClassDesc LOCATION = Location.class.describeConstable().orElseThrow(); static final ClassDesc POSITION = Position.class.describeConstable().orElseThrow(); + @SuppressWarnings("Convert2MethodRef") @TransformerTest("data.methods.statics.returns.ReturnDirectUser") void testReturnDirectStaticRewrite(final TransformerCheck check) throws NoSuchMethodException { final Method handler = Redirects.class.getDeclaredMethod("wrapPosition", Position.class); @@ -22,12 +24,17 @@ void testReturnDirectStaticRewrite(final TransformerCheck check) throws NoSuchMe builder.changeReturnTypeDirect( POSITION, handler, - b -> b.names("getLoc", "getLocStatic").hasReturn(LOCATION) + TargetedMethodMatcher.builder() + .match("getLoc", b -> b.virtual()) + .match("getLocStatic", b -> b.statik()) + .hasReturn(LOCATION) + .build() ); }); check.run(rule); } + @SuppressWarnings("Convert2MethodRef") @TransformerTest("data.methods.statics.returns.ReturnDirectWithContextUser") void testReturnDirectWithContextStaticRewrite(final TransformerCheck check) throws NoSuchMethodException { final Method handler = Redirects.class.getDeclaredMethod("wrapPositionWithContext", Methods.class, Position.class); @@ -35,7 +42,11 @@ void testReturnDirectWithContextStaticRewrite(final TransformerCheck check) thro builder.changeReturnTypeDirectWithContext( POSITION, handler, - b -> b.names("getLoc", "getLocStatic").hasReturn(LOCATION) + TargetedMethodMatcher.builder() + .match("getLoc", b -> b.virtual()) + .match("getLocStatic", b -> b.statik()) + .hasReturn(LOCATION) + .build() ); }); check.run(rule); diff --git a/src/test/java/io/papermc/asm/rules/methods/StaticRewriteTest.java b/src/test/java/io/papermc/asm/rules/methods/StaticRewriteTest.java index bb09690..b92ebcd 100644 --- a/src/test/java/io/papermc/asm/rules/methods/StaticRewriteTest.java +++ b/src/test/java/io/papermc/asm/rules/methods/StaticRewriteTest.java @@ -9,8 +9,10 @@ import io.papermc.asm.TransformerTest; import io.papermc.asm.checks.TransformerCheck; import io.papermc.asm.rules.RewriteRule; +import io.papermc.asm.rules.builder.matcher.method.MethodMatcher; import java.lang.constant.ClassDesc; import java.lang.constant.ConstantDescs; +import java.util.Set; class StaticRewriteTest { @@ -23,17 +25,17 @@ void testPlainStaticRewrite(final TransformerCheck check) { final RewriteRule rule = RewriteRule.forOwnerClass(Player.class, builder -> { builder.plainStaticRewrite( REDIRECTS, - b -> b - .match("addEntity", "addEntityStatic") - .desc(d -> d.parameterList().contains(ENTITY)) + MethodMatcher.builder() + .match(Set.of("addEntity", "addEntityStatic"), b -> b.hasParam(ENTITY)) + .build() ); }); final RewriteRule ctorRule = RewriteRule.forOwnerClass(Methods.Wrapper.class, builder -> { builder.plainStaticRewrite( REDIRECTS, - b -> b - .ctor() - .desc(d -> d.parameterList().contains(PLAYER)) + MethodMatcher.builder() + .ctor(b -> b.hasParam(PLAYER)) + .build() ); }); check.run(RewriteRule.chain(rule, ctorRule)); @@ -45,7 +47,9 @@ void testMoveInstanceMethod(final TransformerCheck check) { builder.moveInstanceMethod( ApiInterfaceImpl.class, "get0", - b -> b.match("get").desc(d -> d.returnType().equals(ConstantDescs.CD_String)) + MethodMatcher.builder() + .match("get", b -> b.hasReturn(ConstantDescs.CD_String)) + .build() ); });