Skip to content

Commit

Permalink
Add a way to look up which sources specify a certain target
Browse files Browse the repository at this point in the history
  • Loading branch information
XFactHD committed Dec 25, 2024
1 parent 90f1408 commit 7ef846d
Show file tree
Hide file tree
Showing 10 changed files with 117 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,26 @@
public sealed interface Target {
String className();

/**
* Checks whether this target matches the given target description.
*
* @param className The FQN of the class containing the target
* @param type The type of the target
* @param targetName The name of the target (ignored for {@link TargetType#CLASS} and wildcard targets)
* @return whether this target matches the given target description
*/
boolean matches(final String className, final TargetType type, final String targetName);

record ClassTarget(String className) implements Target {
@Override
public String toString() {
return className() + " CLASS";
}

@Override
public boolean matches(final String className, final TargetType type, final String targetName) {
return type == TargetType.CLASS && this.className.equals(className);
}
}

record InnerClassTarget(String className, String innerName) implements Target {
Expand All @@ -16,33 +31,58 @@ public String toString() {
int idx = innerName().lastIndexOf('$');
return className() + " INNERCLASS " + innerName().substring(idx + 1);
}

@Override
public boolean matches(final String className, final TargetType type, final String targetName) {
return type == TargetType.CLASS && this.innerName.equals(className);
}
}

record FieldTarget(String className, String fieldName) implements Target {
@Override
public String toString() {
return className() + " FIELD " + fieldName();
}

@Override
public boolean matches(final String className, final TargetType type, final String targetName) {
return type == TargetType.FIELD && this.className.equals(className) && this.fieldName.equals(targetName);
}
}

record MethodTarget(String className, String methodName, String methodDescriptor) implements Target {
@Override
public String toString() {
return className() + " METHOD " + methodName() + methodDescriptor();
}

@Override
public boolean matches(final String className, final TargetType type, final String targetName) {
return type == TargetType.METHOD && this.className.equals(className) && targetName.equals(this.methodName + this.methodDescriptor);
}
}

record WildcardMethodTarget(String className) implements Target {
@Override
public String toString() {
return className() + " METHODWILDCARD";
}

@Override
public boolean matches(final String className, final TargetType type, final String targetName) {
return type == TargetType.METHOD && this.className.equals(className);
}
}

record WildcardFieldTarget(String className) implements Target {
@Override
public String toString() {
return className() + " FIELDWILDCARD";
}

@Override
public boolean matches(final String className, final TargetType type, final String targetName) {
return type == TargetType.FIELD && this.className.equals(className);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package net.neoforged.accesstransformer;
package net.neoforged.accesstransformer.parser;

public enum TargetType {
FIELD, METHOD, CLASS;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package net.neoforged.accesstransformer;

import net.neoforged.accesstransformer.parser.Target;
import net.neoforged.accesstransformer.parser.TargetType;
import net.neoforged.accesstransformer.parser.Transformation;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.Marker;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package net.neoforged.accesstransformer;

import net.neoforged.accesstransformer.api.AccessTransformerEngine;
import net.neoforged.accesstransformer.parser.TargetType;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.ClassNode;
Expand Down Expand Up @@ -82,4 +83,9 @@ public Set<Type> getTargets() {
public boolean containsClassTarget(Type type) {
return masterList.containsClassTarget(type);
}

@Override
public Set<String> getSourcesForTarget(final String className, final TargetType type, final String targetName) {
return masterList.getSourcesForTarget(className, type, targetName);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import net.neoforged.accesstransformer.parser.AccessTransformerFiles;
import net.neoforged.accesstransformer.parser.Target;
import net.neoforged.accesstransformer.parser.TargetType;
import net.neoforged.accesstransformer.parser.Transformation;
import org.objectweb.asm.Type;

Expand All @@ -10,6 +11,7 @@
import java.net.URISyntaxException;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
Expand Down Expand Up @@ -57,4 +59,19 @@ public Map<TargetType, Map<String, AccessTransformer<?>>> getTransformersForTarg
Collectors.toMap((Function<AccessTransformer<?>, String>) AccessTransformer::targetName, Function.<AccessTransformer<?>>identity())
));
}

public Set<String> getSourcesForTarget(final String className, final TargetType type, final String targetName) {
return atFiles.getAccessTransformers()
.entrySet()
.stream()
.filter(e -> e.getKey().matches(className, type, targetName))
.map(Map.Entry::getValue)
.map(Transformation::origins)
.map(HashSet::new)
.reduce((s1, s2) -> {
s1.addAll(s2);
return s1;
})
.orElse(null);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package net.neoforged.accesstransformer;

import net.neoforged.accesstransformer.parser.Target;
import net.neoforged.accesstransformer.parser.TargetType;
import net.neoforged.accesstransformer.parser.Transformation;
import org.objectweb.asm.tree.FieldNode;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package net.neoforged.accesstransformer;

import net.neoforged.accesstransformer.parser.Target;
import net.neoforged.accesstransformer.parser.TargetType;
import net.neoforged.accesstransformer.parser.Transformation;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.MethodNode;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package net.neoforged.accesstransformer;

import net.neoforged.accesstransformer.parser.Target;
import net.neoforged.accesstransformer.parser.TargetType;
import net.neoforged.accesstransformer.parser.Transformation;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.ClassNode;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package net.neoforged.accesstransformer.api;

import net.neoforged.accesstransformer.AccessTransformerEngineImpl;
import net.neoforged.accesstransformer.parser.TargetType;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.ClassNode;

Expand Down Expand Up @@ -51,6 +52,18 @@ public interface AccessTransformerEngine {
*/
boolean containsClassTarget(Type type);

/**
* Looks up AT file sources of entries matching the given target
*
* @param className the class containing the target
* @param type the type of the target
* @param targetName the target's name (null for class targets, full descriptor for method targets, name for field targets)
* @return The list of sources specifying the given target or null if none apply
*/
default Set<String> getSourcesForTarget(final String className, final TargetType type, final String targetName) {
return null;
}

/**
* Attempts to transform the given {@code classNode}, and apply ATs, if any.
* @param classNode the class to transform
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package net.neoforged.accesstransformer.test;

import net.neoforged.accesstransformer.AccessTransformerList;
import net.neoforged.accesstransformer.parser.TargetType;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Path;
import java.util.Set;

public class AccessTransformerPresenceTest {
@Test
public void testSourceLookup() throws IOException, URISyntaxException {
final AccessTransformerList atLoader = new AccessTransformerList();

Path filePath = Path.of(getClass().getClassLoader().getResource("forge_at.cfg").toURI());
atLoader.loadFromPath(filePath);

String sourcePrefix = filePath.toString();

// Class
Assertions.assertEquals(Set.of(sourcePrefix + ":99"), atLoader.getSourcesForTarget("net.minecraft.item.crafting.RecipeTippedArrow", TargetType.CLASS, null));
// Inner class
Assertions.assertEquals(Set.of(sourcePrefix + ":76"), atLoader.getSourcesForTarget("net.minecraft.world.gen.structure.StructureStrongholdPieces$Stronghold", TargetType.CLASS, null));
// Method
Assertions.assertEquals(Set.of(sourcePrefix + ":6"), atLoader.getSourcesForTarget("net.minecraft.block.Block", TargetType.METHOD, "func_149752_b(F)Lnet/minecraft/block/Block;"));
// Field
Assertions.assertEquals(Set.of(sourcePrefix + ":22"), atLoader.getSourcesForTarget("net.minecraft.entity.EntityTrackerEntry", TargetType.FIELD, "field_73134_o"));
// Method wildcard
Assertions.assertEquals(Set.of(sourcePrefix + ":29"), atLoader.getSourcesForTarget("net.minecraft.world.biome.Biome", TargetType.METHOD, "this_is_ignored(F)Ldoes/not/Matter;"));
// Field wildcard
Assertions.assertEquals(Set.of(sourcePrefix + ":51"), atLoader.getSourcesForTarget("net.minecraft.world.biome.BiomeDecorator", TargetType.FIELD, "this_is_ignored"));
}
}

0 comments on commit 7ef846d

Please sign in to comment.