Skip to content

Commit e4d44e8

Browse files
Support versioning each rewrite rule (#32)
Co-authored-by: Jason Penilla <[email protected]>
1 parent bab3607 commit e4d44e8

File tree

47 files changed

+1343
-153
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+1343
-153
lines changed

build.gradle.kts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import org.incendo.cloudbuildlogic.javadoclinks.JavadocLinksExtension
12
import org.incendo.cloudbuildlogic.jmp
23
import java.nio.file.Files
34
import kotlin.io.path.copyTo
@@ -75,6 +76,11 @@ allprojects {
7576
testImplementation(rootProject.libs.jupiterParams)
7677
testRuntimeOnly(rootProject.libs.jupiterEngine)
7778
}
79+
80+
javadocLinks {
81+
override(startsWithAnyOf("org.ow2.asm:asm"), JavadocLinksExtension.LinkOverride.Simple("https://asm.ow2.io/javadoc"))
82+
override(rootProject.libs.checkerQual, "https://checkerframework.org/api/")
83+
}
7884
}
7985
val mainForNewTargets = sourceSets.create("mainForNewTargets")
8086

@@ -89,12 +95,13 @@ val filtered = tasks.register<FilterTestClasspath>("filteredTestClasspath") {
8995

9096
dependencies {
9197
implementation(mainForNewTargets.output)
92-
testImplementation(files(filtered.flatMap { it.outputDir }))
98+
testRuntimeOnly(files(filtered.flatMap { it.outputDir })) // only have access to old targets at runtime, don't use them in actual tests
9399
testImplementation(testDataNewTargets.output)
94100

95101
testDataNewTargets.implementationConfigurationName(mainForNewTargets.output)
96102
}
97103

104+
98105
abstract class FilterTestClasspath : DefaultTask() {
99106
@get:InputFiles
100107
abstract val old: ConfigurableFileCollection

src/main/java/io/papermc/asm/rules/RewriteRule.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ static RewriteRule chain(final RewriteRule... rules) {
4949
return chain(Arrays.asList(rules));
5050
}
5151

52+
static RewriteRule chain(final RewriteRule rule1, final RewriteRule rule2) {
53+
return chain(List.of(rule1, rule2));
54+
}
55+
5256
static RewriteRule chain(final Collection<? extends RewriteRule> rules) {
5357
final List<? extends RewriteRule> filteredRules = rules.stream().filter(r -> r != EMPTY).toList();
5458
if (filteredRules.isEmpty()) {

src/main/java/io/papermc/asm/rules/builder/RuleFactory.java

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,11 @@ static RuleFactory.Factory combine(final RuleFactory.Factory... factories) {
3030

3131
void plainStaticRewrite(ClassDesc newOwner, MethodMatcher methodMatcher, String staticMethodName);
3232

33-
default void changeParamToSuper(final Class<?> oldParamType, final Class<?> newParamType, final MethodMatcher methodMatcher) {
34-
if (!newParamType.isAssignableFrom(oldParamType)) {
35-
throw new IllegalArgumentException(newParamType + " is not a superclass of " + oldParamType);
36-
}
37-
this.changeParamToSuper(desc(oldParamType), desc(newParamType), methodMatcher);
33+
default void changeParamToSuper(final Class<?> newParamType, final TargetedMethodMatcher methodMatcher) {
34+
this.changeParamToSuper( desc(newParamType), methodMatcher);
3835
}
3936

40-
void changeParamToSuper(ClassDesc legacyParamType, ClassDesc newParamType, MethodMatcher methodMatcher);
37+
void changeParamToSuper(ClassDesc newParamType, TargetedMethodMatcher methodMatcher);
4138

4239
default void changeParamFuzzy(final Class<?> newParamType, final Method staticHandler, final TargetedMethodMatcher targetedMethodMatcher) {
4340
this.changeParamFuzzy(desc(newParamType), staticHandler, targetedMethodMatcher);
@@ -51,14 +48,11 @@ default void changeParamDirect(final Class<?> newParamType, final Method staticH
5148

5249
void changeParamDirect(ClassDesc newParamType, Method staticHandler, TargetedMethodMatcher targetedMethodMatcher);
5350

54-
default void changeReturnTypeToSub(final Class<?> oldReturnType, final Class<?> newReturnType, final MethodMatcher methodMatcher) {
55-
if (!oldReturnType.isAssignableFrom(newReturnType)) {
56-
throw new IllegalArgumentException(newReturnType + " is not a subclass of " + oldReturnType);
57-
}
58-
this.changeReturnTypeToSub(desc(oldReturnType), desc(newReturnType), methodMatcher);
51+
default void changeReturnTypeToSub(final Class<?> newReturnType, final TargetedMethodMatcher methodMatcher) {
52+
this.changeReturnTypeToSub(desc(newReturnType), methodMatcher);
5953
}
6054

61-
void changeReturnTypeToSub(ClassDesc oldReturnType, ClassDesc newReturnType, MethodMatcher methodMatcher);
55+
void changeReturnTypeToSub(ClassDesc newReturnType, TargetedMethodMatcher methodMatcher);
6256

6357
default void changeReturnTypeDirect(final Class<?> newReturnType, final Method staticHandler, final TargetedMethodMatcher targetedMethodMatcher) {
6458
this.changeReturnTypeDirect(desc(newReturnType), staticHandler, targetedMethodMatcher);

src/main/java/io/papermc/asm/rules/builder/RuleFactoryImpl.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ public void plainStaticRewrite(final ClassDesc newOwner, final MethodMatcher met
5050
}
5151

5252
@Override
53-
public void changeParamToSuper(final ClassDesc legacyParamType, final ClassDesc newParamType, final MethodMatcher methodMatcher) {
54-
this.addRule(new SuperTypeParamRewrite(this.owners, methodMatcher, legacyParamType, newParamType));
53+
public void changeParamToSuper(final ClassDesc newParamType, final TargetedMethodMatcher methodMatcher) {
54+
this.addRule(new SuperTypeParamRewrite(this.owners, methodMatcher, newParamType));
5555
}
5656

5757
@Override
@@ -65,8 +65,8 @@ public void changeParamDirect(final ClassDesc newParamType, final Method staticH
6565
}
6666

6767
@Override
68-
public void changeReturnTypeToSub(final ClassDesc oldReturnType, final ClassDesc newReturnType, final MethodMatcher methodMatcher) {
69-
this.addRule(new SubTypeReturnRewrite(this.owners, methodMatcher, oldReturnType, newReturnType));
68+
public void changeReturnTypeToSub(final ClassDesc newReturnType, final TargetedMethodMatcher methodMatcher) {
69+
this.addRule(new SubTypeReturnRewrite(this.owners, methodMatcher, newReturnType));
7070
}
7171

7272
@Override

src/main/java/io/papermc/asm/rules/field/FieldToMethodRewrite.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
package io.papermc.asm.rules.field;
22

33
import io.papermc.asm.ClassProcessingContext;
4+
import io.papermc.asm.rules.RewriteRule;
45
import io.papermc.asm.rules.builder.matcher.field.FieldMatcher;
6+
import io.papermc.asm.versioned.ApiVersion;
7+
import io.papermc.asm.versioned.VersionedRuleFactory;
8+
import io.papermc.asm.versioned.matcher.VersionedMatcher;
59
import java.lang.constant.ClassDesc;
610
import java.lang.constant.ConstantDescs;
711
import java.lang.constant.MethodTypeDesc;
@@ -91,4 +95,18 @@ MethodTypeDesc desc(final ClassDesc fieldTypeDesc) {
9195
delegate.visitMethodInsn(type.opcode(opcode), owner, methodName, type.desc(fieldTypeDesc).descriptorString(), this.isInterfaceMethod);
9296
};
9397
}
98+
99+
public record Versioned(Set<ClassDesc> owners, @Nullable String getterName, @Nullable String setterName, boolean isInterfaceMethod, VersionedMatcher<FieldMatcher> versions) implements VersionedRuleFactory {
100+
101+
public Versioned {
102+
if (getterName == null && setterName == null) {
103+
throw new IllegalArgumentException("At least one of getterName or setterName must be non-null");
104+
}
105+
}
106+
107+
@Override
108+
public RewriteRule createRule(final ApiVersion<?> apiVersion) {
109+
return this.versions.ruleForVersion(apiVersion, matcher -> new FieldToMethodRewrite(this.owners(), matcher, this.getterName(), this.setterName(), this.isInterfaceMethod()));
110+
}
111+
}
94112
}

src/main/java/io/papermc/asm/rules/method/DirectStaticRewrite.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
package io.papermc.asm.rules.method;
22

33
import io.papermc.asm.ClassProcessingContext;
4+
import io.papermc.asm.rules.RewriteRule;
45
import io.papermc.asm.rules.builder.matcher.method.MethodMatcher;
56
import io.papermc.asm.rules.generate.GeneratedMethodHolder;
67
import io.papermc.asm.rules.method.rewrite.ConstructorRewrite;
78
import io.papermc.asm.rules.method.rewrite.MethodRewrite;
89
import io.papermc.asm.rules.method.rewrite.SimpleRewrite;
10+
import io.papermc.asm.versioned.ApiVersion;
11+
import io.papermc.asm.versioned.VersionedRuleFactory;
12+
import io.papermc.asm.versioned.matcher.VersionedMatcher;
913
import java.lang.constant.ClassDesc;
1014
import java.lang.constant.MethodTypeDesc;
1115
import java.util.Set;
@@ -49,4 +53,12 @@ public MethodRewrite<GeneratedMethodHolder.ConstructorCallData> createConstructo
4953
public ClassDesc staticRedirectOwner(final ClassProcessingContext context) {
5054
return this.staticRedirectOwner;
5155
}
56+
57+
public record Versioned(Set<ClassDesc> owners, ClassDesc staticRedirectOwner, @Nullable String staticMethodName, VersionedMatcher<MethodMatcher> versions) implements VersionedRuleFactory {
58+
59+
@Override
60+
public RewriteRule createRule(final ApiVersion<?> apiVersion) {
61+
return this.versions.ruleForVersion(apiVersion, match -> new DirectStaticRewrite(this.owners(), this.staticMethodName(), match, this.staticRedirectOwner()));
62+
}
63+
}
5264
}

src/main/java/io/papermc/asm/rules/method/MoveInstanceMethod.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
package io.papermc.asm.rules.method;
22

33
import io.papermc.asm.ClassProcessingContext;
4+
import io.papermc.asm.rules.RewriteRule;
45
import io.papermc.asm.rules.builder.matcher.method.MethodMatcher;
56
import io.papermc.asm.rules.method.generated.GeneratedStaticRewrite;
67
import io.papermc.asm.rules.method.rewrite.MethodRewrite;
8+
import io.papermc.asm.versioned.ApiVersion;
9+
import io.papermc.asm.versioned.VersionedRuleFactory;
10+
import io.papermc.asm.versioned.matcher.VersionedMatcher;
711
import java.lang.constant.ClassDesc;
812
import java.lang.constant.MethodTypeDesc;
913
import java.util.Set;
@@ -56,4 +60,12 @@ public void generateMethod(final GeneratorAdapterFactory factory, final MethodCa
5660
public void generateConstructor(final GeneratorAdapterFactory factory, final MethodCallData modified, final ConstructorCallData original) {
5761
throw new UnsupportedOperationException("Doesn't work with constructors");
5862
}
63+
64+
public record Versioned(Set<ClassDesc> owners, ClassDesc newOwner, String newMethodName, VersionedMatcher<MethodMatcher> versions) implements VersionedRuleFactory {
65+
66+
@Override
67+
public RewriteRule createRule(final ApiVersion<?> apiVersion) {
68+
return this.versions.ruleForVersion(apiVersion, match -> new MoveInstanceMethod(this.owners(), match, this.newOwner(), this.newMethodName()));
69+
}
70+
}
5971
}

src/main/java/io/papermc/asm/rules/method/params/DirectParameterRewrite.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
package io.papermc.asm.rules.method.params;
22

3+
import io.papermc.asm.rules.RewriteRule;
34
import io.papermc.asm.rules.builder.matcher.method.targeted.TargetedMethodMatcher;
45
import io.papermc.asm.rules.method.OwnableMethodRewriteRule;
56
import io.papermc.asm.rules.method.generated.TargetedTypeGeneratedStaticRewrite;
7+
import io.papermc.asm.versioned.ApiVersion;
8+
import io.papermc.asm.versioned.VersionedRuleFactory;
9+
import io.papermc.asm.versioned.matcher.TargetedMethodMatcherWithHandler;
10+
import io.papermc.asm.versioned.matcher.VersionedMatcher;
611
import java.lang.constant.ClassDesc;
712
import java.lang.reflect.Method;
813
import java.util.Set;
@@ -17,4 +22,12 @@
1722
* @param staticHandler the method which will be used to convert the legacy type to the new type
1823
*/
1924
public record DirectParameterRewrite(Set<ClassDesc> owners, ClassDesc existingType, TargetedMethodMatcher methodMatcher, Method staticHandler) implements TargetedTypeGeneratedStaticRewrite.Parameter, OwnableMethodRewriteRule.Filtered {
25+
26+
public record Versioned(Set<ClassDesc> owners, ClassDesc existingType, VersionedMatcher<TargetedMethodMatcherWithHandler> versions) implements VersionedRuleFactory {
27+
28+
@Override
29+
public RewriteRule createRule(final ApiVersion<?> apiVersion) {
30+
return this.versions.ruleForVersion(apiVersion, pair -> new DirectParameterRewrite(this.owners, this.existingType, pair.matcher(), pair.staticHandler()));
31+
}
32+
}
2033
}

src/main/java/io/papermc/asm/rules/method/params/FuzzyParameterRewrite.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
package io.papermc.asm.rules.method.params;
22

33
import io.papermc.asm.ClassProcessingContext;
4+
import io.papermc.asm.rules.RewriteRule;
45
import io.papermc.asm.rules.builder.matcher.method.targeted.TargetedMethodMatcher;
56
import io.papermc.asm.rules.method.OwnableMethodRewriteRule;
67
import io.papermc.asm.rules.method.generated.TargetedTypeGeneratedStaticRewrite;
78
import io.papermc.asm.rules.method.rewrite.MethodRewrite;
9+
import io.papermc.asm.versioned.ApiVersion;
10+
import io.papermc.asm.versioned.VersionedRuleFactory;
11+
import io.papermc.asm.versioned.matcher.TargetedMethodMatcherWithHandler;
12+
import io.papermc.asm.versioned.matcher.VersionedMatcher;
813
import java.lang.constant.ClassDesc;
914
import java.lang.constant.ConstantDescs;
1015
import java.lang.constant.MethodTypeDesc;
@@ -54,4 +59,12 @@ public MethodRewrite<MethodCallData> createRewrite(final ClassProcessingContext
5459
arguments[MethodRewrite.DYNAMIC_TYPE_IDX] = Type.getMethodType(newDynamicMethodType.descriptorString());
5560
});
5661
}
62+
63+
public record Versioned(Set<ClassDesc> owners, ClassDesc existingType, VersionedMatcher<TargetedMethodMatcherWithHandler> versions) implements VersionedRuleFactory {
64+
65+
@Override
66+
public RewriteRule createRule(final ApiVersion<?> apiVersion) {
67+
return this.versions.ruleForVersion(apiVersion, pair -> new FuzzyParameterRewrite(this.owners, this.existingType, pair.matcher(), pair.staticHandler()));
68+
}
69+
}
5770
}
Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
package io.papermc.asm.rules.method.params;
22

33
import io.papermc.asm.ClassProcessingContext;
4-
import io.papermc.asm.rules.builder.matcher.method.MethodMatcher;
4+
import io.papermc.asm.rules.RewriteRule;
5+
import io.papermc.asm.rules.builder.matcher.method.targeted.TargetedMethodMatcher;
56
import io.papermc.asm.rules.method.OwnableMethodRewriteRule;
67
import io.papermc.asm.rules.method.rewrite.MethodRewrite;
78
import io.papermc.asm.rules.method.rewrite.SimpleRewrite;
9+
import io.papermc.asm.versioned.ApiVersion;
10+
import io.papermc.asm.versioned.VersionedRuleFactory;
11+
import io.papermc.asm.versioned.matcher.VersionedMatcher;
812
import java.lang.constant.ClassDesc;
913
import java.lang.constant.MethodTypeDesc;
1014
import java.util.Set;
@@ -17,18 +21,29 @@
1721
* offending parameter in the descriptor and move on.
1822
*
1923
* @param owners owners of the methods to change
20-
* @param methodMatcher method matcher to find methods with
21-
* @param oldParamType the parameter type that will be found in bytecode that needs to be transformed
24+
* @param methodMatcher method matcher to find methods with (target is the type to be found in bytecode that needs to be transformed)
2225
* @param newParamType the parameter type that is valid for existing method
2326
*/
24-
public record SuperTypeParamRewrite(Set<ClassDesc> owners, MethodMatcher methodMatcher, ClassDesc oldParamType, ClassDesc newParamType) implements OwnableMethodRewriteRule.Filtered {
27+
public record SuperTypeParamRewrite(Set<ClassDesc> owners, TargetedMethodMatcher methodMatcher, ClassDesc newParamType) implements OwnableMethodRewriteRule.Filtered {
28+
29+
public ClassDesc oldParamType() {
30+
return this.methodMatcher.targetType();
31+
}
2532

2633
@Override
2734
public MethodRewrite<?> rewrite(final ClassProcessingContext context, final boolean isInvokeDynamic, final int opcode, final ClassDesc owner, final String name, final MethodTypeDesc descriptor, final boolean isInterface) {
2835
return new SimpleRewrite(opcode, owner, name, this.modifyMethodDescriptor(descriptor), isInterface, isInvokeDynamic);
2936
}
3037

3138
private MethodTypeDesc modifyMethodDescriptor(final MethodTypeDesc methodDescriptor) {
32-
return replaceParameters(methodDescriptor, isEqual(this.oldParamType()), this.newParamType());
39+
return replaceParameters(methodDescriptor, isEqual(this.methodMatcher().targetType()), this.newParamType());
40+
}
41+
42+
public record Versioned(Set<ClassDesc> owners, ClassDesc newParamType, VersionedMatcher<TargetedMethodMatcher> versions) implements VersionedRuleFactory {
43+
44+
@Override
45+
public RewriteRule createRule(final ApiVersion<?> apiVersion) {
46+
return this.versions.ruleForVersion(apiVersion, matcher -> new SuperTypeParamRewrite(this.owners(), matcher, this.newParamType()));
47+
}
3348
}
3449
}

0 commit comments

Comments
 (0)