Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ dependencies {

// tinyfile management
implementation libs.fabric.tiny.remapper
implementation libs.fabric.access.widener
implementation libs.fabric.clazz.tweaker
implementation libs.fabric.mapping.io
implementation (libs.fabric.lorenz.tiny) {
transitive = false
Expand Down
4 changes: 2 additions & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ gson = "2.10.1"

stitch = "0.6.2"
tiny-remapper = "0.12.0"
access-widener = "2.1.0"
clazz-tweaker = "0.1.1"
mapping-io = "0.7.1"
lorenz-tiny = "4.0.2"
mercury = "0.4.2"
Expand All @@ -30,7 +30,7 @@ gson = { module = "com.google.code.gson:gson", version.ref = "gson" }

fabric-stitch = { module = "net.fabricmc:stitch", version.ref = "stitch" }
fabric-tiny-remapper = { module = "net.fabricmc:tiny-remapper", version.ref = "tiny-remapper" }
fabric-access-widener = { module = "net.fabricmc:access-widener", version.ref = "access-widener" }
fabric-clazz-tweaker = { module = "net.fabricmc:class-tweaker", version.ref = "clazz-tweaker" }
fabric-mapping-io = { module = "net.fabricmc:mapping-io", version.ref = "mapping-io" }
fabric-lorenz-tiny = { module = "net.fabricmc:lorenz-tiny", version.ref = "lorenz-tiny" }
fabric-mercury = { module = "net.fabricmc:mercury", version.ref = "mercury" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

import org.jetbrains.annotations.Nullable;

import net.fabricmc.accesswidener.AccessWidenerVisitor;
import net.fabricmc.classtweaker.api.visitor.ClassTweakerVisitor;
import net.fabricmc.loom.util.LazyCloseable;
import net.fabricmc.loom.util.fmj.ModEnvironment;
import net.fabricmc.tinyremapper.TinyRemapper;
Expand All @@ -44,5 +44,5 @@ public interface AccessWidenerEntry {

String getSortKey();

void read(AccessWidenerVisitor visitor, LazyCloseable<TinyRemapper> remapper) throws IOException;
void read(ClassTweakerVisitor visitor, LazyCloseable<TinyRemapper> remapper) throws IOException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
import org.gradle.api.file.RegularFileProperty;
import org.jetbrains.annotations.Nullable;

import net.fabricmc.accesswidener.AccessWidener;
import net.fabricmc.classtweaker.api.ClassTweaker;
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
import net.fabricmc.loom.api.processor.MinecraftJarProcessor;
import net.fabricmc.loom.api.processor.ProcessorContext;
Expand Down Expand Up @@ -131,7 +131,7 @@ private static boolean isSupported(ModEnvironment modEnvironment, ProcessorConte
public void processJar(Path jar, AccessWidenerJarProcessor.Spec spec, ProcessorContext context) throws IOException {
final List<AccessWidenerEntry> accessWideners = spec.accessWidenersForContext(context);

final var accessWidener = new AccessWidener();
final var accessWidener = ClassTweaker.newInstance();

try (LazyCloseable<TinyRemapper> remapper = context.createRemapper(MappingsNamespace.INTERMEDIARY, MappingsNamespace.NAMED)) {
for (AccessWidenerEntry widener : accessWideners) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,17 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.fabricmc.accesswidener.AccessWidener;
import net.fabricmc.accesswidener.AccessWidenerClassVisitor;
import net.fabricmc.classtweaker.api.ClassTweaker;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.Pair;
import net.fabricmc.loom.util.ZipUtils;

final class AccessWidenerTransformer {
private static final Logger LOGGER = LoggerFactory.getLogger(AccessWidenerTransformer.class);

private final AccessWidener accessWidener;
private final ClassTweaker accessWidener;

AccessWidenerTransformer(AccessWidener accessWidener) {
AccessWidenerTransformer(ClassTweaker accessWidener) {
this.accessWidener = accessWidener;
}

Expand All @@ -57,25 +56,37 @@ final class AccessWidenerTransformer {
*/
void apply(Path jarFile) {
try {
ZipUtils.transform(jarFile, getTransformers(accessWidener.getTargets()));
Set<String> targets = accessWidener.getTargets();
int transformed = ZipUtils.transform(jarFile, getTransformers(targets));

LOGGER.debug("Applied access wideners to {} classes in {}", transformed, jarFile);

if (targets.size() != transformed) {
LOGGER.debug("Access widener target count ({}) does not match transformed class count ({}).", targets.size(), transformed);
}
} catch (IOException e) {
throw new UncheckedIOException("Failed to apply access wideners to %s".formatted(jarFile), e);
}
}

private List<Pair<String, ZipUtils.UnsafeUnaryOperator<byte[]>>> getTransformers(Set<String> classes) {
return classes.stream()
.map(string -> new Pair<>(string.replaceAll("\\.", "/") + ".class", getTransformer(string)))
.map(string -> new Pair<>(string + ".class", getTransformer(string)))
.collect(Collectors.toList());
}

private ZipUtils.UnsafeUnaryOperator<byte[]> getTransformer(String className) {
return input -> {
ClassReader reader = new ClassReader(input);

if (!reader.getClassName().equals(className)) {
throw new IllegalStateException("Class name mismatch: expected %s but transforming %s".formatted(className, reader.getClassName()));
}

ClassWriter writer = new ClassWriter(0);
ClassVisitor classVisitor = AccessWidenerClassVisitor.createClassVisitor(Constants.ASM_VERSION, writer, accessWidener);
ClassVisitor classVisitor = accessWidener.createClassVisitor(Constants.ASM_VERSION, writer, null);

LOGGER.debug("Applying access widener to " + className);
LOGGER.debug("Applying access widener to {}", className);

reader.accept(classVisitor, 0);
return writer.toByteArray();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@

import org.jetbrains.annotations.Nullable;

import net.fabricmc.accesswidener.AccessWidenerReader;
import net.fabricmc.accesswidener.AccessWidenerVisitor;
import net.fabricmc.classtweaker.api.ClassTweakerReader;
import net.fabricmc.classtweaker.api.visitor.ClassTweakerVisitor;
import net.fabricmc.loom.util.Checksum;
import net.fabricmc.loom.util.LazyCloseable;
import net.fabricmc.loom.util.fmj.ModEnvironment;
Expand All @@ -43,9 +43,9 @@ public static LocalAccessWidenerEntry create(Path path) {
}

@Override
public void read(AccessWidenerVisitor visitor, LazyCloseable<TinyRemapper> remapper) throws IOException {
var reader = new AccessWidenerReader(visitor);
reader.read(Files.readAllBytes(path));
public void read(ClassTweakerVisitor visitor, LazyCloseable<TinyRemapper> remapper) throws IOException {
var reader = ClassTweakerReader.create(visitor);
reader.read(Files.readAllBytes(path), null);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@

import org.jetbrains.annotations.Nullable;

import net.fabricmc.accesswidener.AccessWidenerReader;
import net.fabricmc.accesswidener.AccessWidenerRemapper;
import net.fabricmc.accesswidener.AccessWidenerVisitor;
import net.fabricmc.accesswidener.TransitiveOnlyFilter;
import net.fabricmc.classtweaker.api.ClassTweakerReader;
import net.fabricmc.classtweaker.api.visitor.ClassTweakerVisitor;
import net.fabricmc.classtweaker.visitors.ClassTweakerRemapperVisitor;
import net.fabricmc.classtweaker.visitors.TransitiveOnlyFilter;
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
import net.fabricmc.loom.util.LazyCloseable;
import net.fabricmc.loom.util.fmj.FabricModJson;
Expand Down Expand Up @@ -67,26 +67,26 @@ public String getSortKey() {
}

@Override
public void read(AccessWidenerVisitor visitor, LazyCloseable<TinyRemapper> remapper) throws IOException {
public void read(ClassTweakerVisitor visitor, LazyCloseable<TinyRemapper> remapper) throws IOException {
if (transitiveOnly) {
// Filter for only transitive rules
visitor = new TransitiveOnlyFilter(visitor);
}

final byte[] data = readRaw();
final AccessWidenerReader.Header header = AccessWidenerReader.readHeader(data);
final ClassTweakerReader.Header header = ClassTweakerReader.readHeader(data);

if (!header.getNamespace().equals(MappingsNamespace.NAMED.toString())) {
// Remap the AW if needed
visitor = getRemapper(visitor, remapper.get());
}

var reader = new AccessWidenerReader(visitor);
reader.read(data);
var reader = ClassTweakerReader.create(visitor);
reader.read(data, mod.getId());
}

private static AccessWidenerRemapper getRemapper(AccessWidenerVisitor visitor, TinyRemapper tinyRemapper) {
return new AccessWidenerRemapper(
private static ClassTweakerRemapperVisitor getRemapper(ClassTweakerVisitor visitor, TinyRemapper tinyRemapper) {
return new ClassTweakerRemapperVisitor(
visitor,
tinyRemapper.getEnvironment().getRemapper(),
MappingsNamespace.INTERMEDIARY.toString(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.fabricmc.accesswidener.AccessWidenerReader;
import net.fabricmc.accesswidener.AccessWidenerVisitor;
import net.fabricmc.classtweaker.api.visitor.AccessWidenerVisitor;
import net.fabricmc.classtweaker.api.visitor.ClassTweakerVisitor;
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
import net.fabricmc.loom.api.processor.MappingProcessorContext;
import net.fabricmc.loom.api.processor.MinecraftJarProcessor;
Expand All @@ -44,6 +44,8 @@
public final class TransitiveAccessWidenerMappingsProcessor implements MinecraftJarProcessor.MappingsProcessor<AccessWidenerJarProcessor.Spec> {
public static final TransitiveAccessWidenerMappingsProcessor INSTANCE = new TransitiveAccessWidenerMappingsProcessor();

private static final Logger LOGGER = LoggerFactory.getLogger(TransitiveAccessWidenerMappingsProcessor.class);

private TransitiveAccessWidenerMappingsProcessor() {
}

Expand All @@ -63,7 +65,7 @@ public boolean transform(MemoryMappingTree mappings, AccessWidenerJarProcessor.S

try (LazyCloseable<TinyRemapper> remapper = context.createRemapper(MappingsNamespace.INTERMEDIARY, MappingsNamespace.NAMED)) {
for (AccessWidenerEntry accessWidener : accessWideners) {
var visitor = new MappingCommentVisitor(accessWidener.mappingId(), mappings);
var visitor = new MappingCommentClassTweakerVisitor(accessWidener.mappingId(), mappings);
accessWidener.read(visitor, remapper);
}
} catch (IOException e) {
Expand All @@ -73,80 +75,91 @@ public boolean transform(MemoryMappingTree mappings, AccessWidenerJarProcessor.S
return true;
}

private record MappingCommentVisitor(String modId, MemoryMappingTree mappingTree) implements AccessWidenerVisitor {
private static final Logger LOGGER = LoggerFactory.getLogger(MappingCommentVisitor.class);

private record MappingCommentClassTweakerVisitor(String modId, MemoryMappingTree mappingTree) implements ClassTweakerVisitor {
@Override
public void visitClass(String name, AccessWidenerReader.AccessType access, boolean transitive) {
MappingTree.ClassMapping classMapping = mappingTree.getClass(name);
public AccessWidenerVisitor visitAccessWidener(String owner) {
return new MappingCommentAccessWidenerVisitor(owner);
}

if (classMapping == null) {
LOGGER.info("Failed to find class ({}) to mark access widened by mod ({})", name, modId());
return;
}
private class MappingCommentAccessWidenerVisitor implements AccessWidenerVisitor {
private final String className;

classMapping.setComment(appendComment(classMapping.getComment(), access));
}
private MappingCommentAccessWidenerVisitor(String className) {
this.className = className;
}

@Override
public void visitMethod(String owner, String name, String descriptor, AccessWidenerReader.AccessType access, boolean transitive) {
// Access is also applied to the class, so also add the comment to the class
visitClass(owner, access, transitive);
@Override
public void visitClass(AccessType access, boolean transitive) {
MappingTree.ClassMapping classMapping = mappingTree.getClass(className);

MappingTree.ClassMapping classMapping = mappingTree.getClass(owner);
if (classMapping == null) {
LOGGER.info("Failed to find class ({}) to mark access widened by mod ({})", className, modId());
return;
}

if (classMapping == null) {
LOGGER.info("Failed to find class ({}) to mark access widened by mod ({})", owner, modId());
return;
classMapping.setComment(appendComment(classMapping.getComment(), access));
}

MappingTree.MethodMapping methodMapping = classMapping.getMethod(name, descriptor);
@Override
public void visitMethod(String name, String descriptor, AccessType access, boolean transitive) {
// Access is also applied to the class, so also add the comment to the class
visitClass(access, transitive);

if (methodMapping == null) {
LOGGER.info("Failed to find method ({}) in ({}) to mark access widened by mod ({})", name, owner, modId());
return;
}
MappingTree.ClassMapping classMapping = mappingTree.getClass(className);

methodMapping.setComment(appendComment(methodMapping.getComment(), access));
}
if (classMapping == null) {
LOGGER.info("Failed to find class ({}) to mark access widened by mod ({})", className, modId());
return;
}

@Override
public void visitField(String owner, String name, String descriptor, AccessWidenerReader.AccessType access, boolean transitive) {
// Access is also applied to the class, so also add the comment to the class
visitClass(owner, access, transitive);
MappingTree.MethodMapping methodMapping = classMapping.getMethod(name, descriptor);

MappingTree.ClassMapping classMapping = mappingTree.getClass(owner);
if (methodMapping == null) {
LOGGER.info("Failed to find method ({}) in ({}) to mark access widened by mod ({})", name, className, modId());
return;
}

if (classMapping == null) {
LOGGER.info("Failed to find class ({}) to mark access widened by mod ({})", name, modId());
return;
methodMapping.setComment(appendComment(methodMapping.getComment(), access));
}

MappingTree.FieldMapping fieldMapping = classMapping.getField(name, descriptor);
@Override
public void visitField(String name, String descriptor, AccessType access, boolean transitive) {
// Access is also applied to the class, so also add the comment to the class
visitClass(access, transitive);

if (fieldMapping == null) {
LOGGER.info("Failed to find field ({}) in ({}) to mark access widened by mod ({})", name, owner, modId());
return;
}
MappingTree.ClassMapping classMapping = mappingTree.getClass(className);

fieldMapping.setComment(appendComment(fieldMapping.getComment(), access));
}
if (classMapping == null) {
LOGGER.info("Failed to find class ({}) to mark access widened by mod ({})", name, modId());
return;
}

private String appendComment(String comment, AccessWidenerReader.AccessType access) {
if (comment == null) {
comment = "";
} else {
comment += "\n";
}
MappingTree.FieldMapping fieldMapping = classMapping.getField(name, descriptor);

String awComment = "Access widened by %s to %s".formatted(modId(), access);
if (fieldMapping == null) {
LOGGER.info("Failed to find field ({}) in ({}) to mark access widened by mod ({})", name, className, modId());
return;
}

if (!comment.contains(awComment)) {
// Ensure we don't comment the same thing twice. A bit of a cheap way to do this, but should work ok.
comment += awComment;
fieldMapping.setComment(appendComment(fieldMapping.getComment(), access));
}

return comment;
private String appendComment(String comment, AccessType access) {
if (comment == null) {
comment = "";
} else {
comment += "\n";
}

String awComment = "Access widened by %s to %s".formatted(modId(), access);

if (!comment.contains(awComment)) {
// Ensure we don't comment the same thing twice. A bit of a cheap way to do this, but should work ok.
comment += awComment;
}

return comment;
}
}
}
}
Loading