Skip to content

Commit

Permalink
work on enum renames
Browse files Browse the repository at this point in the history
  • Loading branch information
Machine-Maker committed Sep 27, 2024
1 parent 4dd1120 commit 159ba64
Show file tree
Hide file tree
Showing 39 changed files with 845 additions and 197 deletions.
24 changes: 16 additions & 8 deletions src/main/java/io/papermc/asm/rules/RewriteRule.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import io.papermc.asm.ClassProcessingContext;
import io.papermc.asm.rules.builder.RuleFactory;
import io.papermc.asm.util.DescriptorUtils;
import java.lang.constant.ClassDesc;
import java.util.ArrayList;
import java.util.Arrays;
Expand All @@ -26,7 +27,7 @@ static RewriteRule forOwnerClass(final Class<?> owner, final Consumer<? super Ru

@SafeVarargs
static RewriteRule forOwnerClasses(final Set<Class<?>> owners, final Consumer<? super RuleFactory> firstFactoryConsumer, final Consumer<? super RuleFactory>... factoryConsumers) {
return forOwners(owners.stream().map(c -> c.describeConstable().orElseThrow()).collect(Collectors.toUnmodifiableSet()), firstFactoryConsumer, factoryConsumers);
return forOwners(owners.stream().map(DescriptorUtils::desc).collect(Collectors.toUnmodifiableSet()), firstFactoryConsumer, factoryConsumers);
}

@SafeVarargs
Expand All @@ -49,7 +50,13 @@ static RewriteRule chain(final RewriteRule... rules) {
}

static RewriteRule chain(final Collection<? extends RewriteRule> rules) {
return new Chain(List.copyOf(rules));
final List<? extends RewriteRule> filteredRules = rules.stream().filter(r -> r != EMPTY).toList();
if (filteredRules.isEmpty()) {
return EMPTY;
} else if (filteredRules.size() == 1) {
return filteredRules.iterator().next();
}
return new Chain(filteredRules);
}

static ChainBuilder chain() {
Expand All @@ -73,16 +80,17 @@ default ClassVisitor createVisitor(final int api, final ClassVisitor parent, fin
}
}

record Chain(List<RewriteRule> rules) implements RewriteRule {
public Chain(final List<RewriteRule> rules) {
this.rules = List.copyOf(rules);
record Chain(List<? extends RewriteRule> rules) implements RewriteRule {
public Chain {
rules = List.copyOf(rules);
}

@Override
public ClassVisitor createVisitor(final int api, final ClassVisitor parent, final ClassProcessingContext context) {
ClassVisitor visitor = parent;
for (final RewriteRule rule : this.rules) {
visitor = rule.createVisitor(api, visitor, context);
// iterate over this.rules backwards to ensure the first rule is the outermost visitor
for (int i = this.rules.size() - 1; i >= 0; i--) {
visitor = this.rules.get(i).createVisitor(api, visitor, context);
}
return visitor;
}
Expand All @@ -109,7 +117,7 @@ public ChainBuilder then(final RewriteRule... rules) {
}

public RewriteRule build() {
return new Chain(this.rules);
return RewriteRule.chain(this.rules);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,6 @@ private static Method isStatic(final Method staticHandler) {

@Override
public RewriteRule build() {
if (this.rules.size() == 1) {
return this.rules.get(0);
}
return RewriteRule.chain(this.rules);
}
}
14 changes: 11 additions & 3 deletions src/main/java/io/papermc/asm/rules/method/MethodRewriteRule.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
import io.papermc.asm.rules.method.rewrite.MethodRewrite;
import java.lang.constant.ClassDesc;
import java.lang.constant.MethodTypeDesc;
import java.util.LinkedHashMap;
import java.util.Comparator;
import java.util.Map;
import java.util.TreeMap;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Handle;
Expand Down Expand Up @@ -56,9 +57,16 @@ default boolean shouldProcess(final ClassProcessingContext context, final int op

@Override
default ClassVisitor createVisitor(final int api, final ClassVisitor parent, final ClassProcessingContext context) {
record MethodKey(String owner, String name, MethodTypeDesc descriptor) {
record MethodKey(String owner, String name, MethodTypeDesc descriptor) implements Comparable<MethodKey> {
private static final Comparator<MethodKey> COMPARATOR = Comparator.comparing(MethodKey::owner)
.thenComparing(MethodKey::name)
.thenComparing(key -> key.descriptor().descriptorString());
@Override
public int compareTo(final MethodKey o) {
return COMPARATOR.compare(this, o);
}
}
final Map<MethodKey, MethodRewrite.MethodGenerator> methodsToGenerate = new LinkedHashMap<>();
final Map<MethodKey, MethodRewrite.MethodGenerator> methodsToGenerate = new TreeMap<>();
return new ClassVisitor(api, parent) {

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
package io.papermc.asm.rules.method.params;

import io.papermc.asm.versioned.ApiVersion;
import io.papermc.asm.versioned.VersionedRuleFactory;
import io.papermc.asm.rules.RewriteRule;
import io.papermc.asm.rules.builder.matcher.method.targeted.TargetedMethodMatcher;
import io.papermc.asm.rules.method.generated.TargetedTypeGeneratedStaticRewrite;
import io.papermc.asm.versioned.ApiVersion;
import io.papermc.asm.versioned.VersionedRuleFactory;
import io.papermc.asm.versioned.matcher.targeted.VersionedTargetedMethodMatcher;
import java.lang.constant.ClassDesc;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.Map;
import java.util.NavigableMap;
import java.util.Set;
import java.util.TreeMap;
import org.checkerframework.checker.nullness.qual.Nullable;

/**
* Rewrites matching bytecode to a generated method which will invoke the static handler on all parameters that need to be converted. That
Expand All @@ -25,20 +21,11 @@
*/
public record DirectParameterRewrite(Set<ClassDesc> owners, ClassDesc existingType, TargetedMethodMatcher methodMatcher, Method staticHandler) implements TargetedTypeGeneratedStaticRewrite.Parameter {

public record Versioned(Set<ClassDesc> owners, ClassDesc existingType, NavigableMap<ApiVersion, Map.Entry<TargetedMethodMatcher, Method>> versions) implements VersionedRuleFactory {

public Versioned {
versions = Collections.unmodifiableNavigableMap(versions);
}
public record Versioned(Set<ClassDesc> owners, ClassDesc existingType, VersionedTargetedMethodMatcher versions) implements VersionedRuleFactory {

@Override
public @Nullable RewriteRule createRule(final ApiVersion apiVersion) {
final Map.@Nullable Entry<ApiVersion, Map.Entry<TargetedMethodMatcher, Method>> apiVersionEntryEntry = this.versions.ceilingEntry(apiVersion);
if (apiVersionEntryEntry == null) {
return null;
}
final Map.Entry<TargetedMethodMatcher, Method> entry = apiVersionEntryEntry.getValue();
return new DirectParameterRewrite(this.owners, this.existingType, entry.getKey(), entry.getValue());
public RewriteRule createRule(final ApiVersion apiVersion) {
return this.versions.ruleForVersion(apiVersion, pair -> new DirectParameterRewrite(this.owners, this.existingType, pair.matcher(), pair.staticHandler()));
}
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package io.papermc.asm.rules.method.params;

import io.papermc.asm.ClassProcessingContext;
import io.papermc.asm.rules.RewriteRule;
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 io.papermc.asm.versioned.ApiVersion;
import io.papermc.asm.versioned.VersionedRuleFactory;
import io.papermc.asm.versioned.matcher.targeted.VersionedTargetedMethodMatcher;
import java.lang.constant.ClassDesc;
import java.lang.constant.ConstantDescs;
import java.lang.constant.MethodTypeDesc;
Expand Down Expand Up @@ -53,4 +57,12 @@ public MethodRewrite<MethodCallData> createRewrite(final ClassProcessingContext
arguments[MethodRewrite.DYNAMIC_TYPE_IDX] = Type.getMethodType(newDynamicMethodType.descriptorString());
});
}

public record Versioned(Set<ClassDesc> owners, ClassDesc existingType, VersionedTargetedMethodMatcher versions) implements VersionedRuleFactory {

@Override
public RewriteRule createRule(final ApiVersion apiVersion) {
return this.versions.ruleForVersion(apiVersion, pair -> new FuzzyParameterRewrite(this.owners, this.existingType, pair.matcher(), pair.staticHandler()));
}
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package io.papermc.asm.rules.method.params;

import io.papermc.asm.ClassProcessingContext;
import io.papermc.asm.rules.RewriteRule;
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;
import io.papermc.asm.versioned.ApiVersion;
import io.papermc.asm.versioned.VersionedRuleFactory;
import io.papermc.asm.versioned.matcher.VersionedMethodMatcher;
import java.lang.constant.ClassDesc;
import java.lang.constant.MethodTypeDesc;
import java.util.Set;
Expand All @@ -31,4 +35,12 @@ public MethodRewrite<?> rewrite(final ClassProcessingContext context, final bool
private MethodTypeDesc modifyMethodDescriptor(final MethodTypeDesc methodDescriptor) {
return replaceParameters(methodDescriptor, isEqual(this.oldParamType()), this.newParamType());
}

public record Versioned(Set<ClassDesc> owners, ClassDesc newParamType, VersionedMethodMatcher versions) implements VersionedRuleFactory {

@Override
public RewriteRule createRule(final ApiVersion apiVersion) {
return this.versions.ruleForVersion(apiVersion, pair -> new SuperTypeParamRewrite(this.owners(), pair.matcher(), pair.legacyType(), this.newParamType()));
}
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package io.papermc.asm.rules.method.returns;

import io.papermc.asm.ClassProcessingContext;
import io.papermc.asm.rules.RewriteRule;
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;
import io.papermc.asm.versioned.ApiVersion;
import io.papermc.asm.versioned.VersionedRuleFactory;
import io.papermc.asm.versioned.matcher.VersionedMethodMatcher;
import java.lang.constant.ClassDesc;
import java.lang.constant.MethodTypeDesc;
import java.util.Set;
Expand Down Expand Up @@ -32,4 +36,12 @@ public record SubTypeReturnRewrite(Set<ClassDesc> owners, MethodMatcher methodMa
private MethodTypeDesc modifyMethodDescriptor(final MethodTypeDesc methodDescriptor) {
return methodDescriptor.changeReturnType(this.newReturnType());
}

public record Versioned(Set<ClassDesc> owners, ClassDesc newReturnType, VersionedMethodMatcher versions) implements VersionedRuleFactory {

@Override
public RewriteRule createRule(final ApiVersion apiVersion) {
return this.versions.ruleForVersion(apiVersion, pair -> new SubTypeReturnRewrite(this.owners(), pair.matcher(), pair.legacyType(), this.newReturnType()));
}
}
}
44 changes: 44 additions & 0 deletions src/main/java/io/papermc/asm/rules/rename/EnumRenameBuilder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package io.papermc.asm.rules.rename;

import java.lang.constant.ClassDesc;
import java.util.HashMap;
import java.util.Map;
import org.checkerframework.checker.nullness.qual.Nullable;

import static io.papermc.asm.util.DescriptorUtils.desc;

public final class EnumRenameBuilder {

private final ClassDesc enumTypeDesc;
private @Nullable ClassDesc optionalEnumReplacementImpl;
private final Map<String, String> enumFieldRenames = new HashMap<>();

EnumRenameBuilder(final ClassDesc enumTypeDesc) {
this.enumTypeDesc = enumTypeDesc;
}

public EnumRenameBuilder enumReplacementImpl(final Class<?> type) {
return this.enumReplacementImpl(desc(type));
}

public EnumRenameBuilder enumReplacementImpl(final ClassDesc type) {
if (this.enumTypeDesc.equals(type)) {
throw new IllegalArgumentException("Cannot replace an enum with itself");
}
this.optionalEnumReplacementImpl = type;
return this;
}

public EnumRenameBuilder rename(final String legacyName, final String newName) {
this.enumFieldRenames.put(legacyName, newName);
return this;
}

void apply(final RenameRuleBuilder renameRuleBuilder) {
this.enumFieldRenames.forEach((legacyName, newName) -> {
renameRuleBuilder.fieldByDesc(this.enumTypeDesc, legacyName, newName);
});
final Map<String, String> copy = Map.copyOf(this.enumFieldRenames);
renameRuleBuilder.enumValueOfFieldRenames.put(this.enumTypeDesc, new EnumRenamer(this.enumTypeDesc, this.optionalEnumReplacementImpl, copy));
}
}
8 changes: 8 additions & 0 deletions src/main/java/io/papermc/asm/rules/rename/EnumRenamer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package io.papermc.asm.rules.rename;

import java.lang.constant.ClassDesc;
import java.util.Map;
import org.checkerframework.checker.nullness.qual.Nullable;

public record EnumRenamer(ClassDesc typeDesc, @Nullable ClassDesc optionalReplacementImpl, Map<String, String> fieldRenames) {
}
Loading

0 comments on commit 159ba64

Please sign in to comment.