diff --git a/build.gradle b/build.gradle index 305b659..6f989e2 100644 --- a/build.gradle +++ b/build.gradle @@ -79,15 +79,12 @@ dependencies { // tinyfile management implementation ('net.fabricmc:tiny-remapper:0.5.0') - implementation ('net.fabricmc:tiny-mappings-parser:0.3.0+build.17') - implementation 'net.fabricmc:access-widener:2.0.0' implementation 'net.fabricmc:mapping-io:0.2.1' - implementation ('net.fabricmc:lorenz-tiny:3.0.0') { + implementation ('net.fabricmc:lorenz-tiny:4.0.0') { transitive = false } - implementation ('org.cadixdev:lorenz-io-proguard:0.5.7') // decompilers implementation ('net.fabricmc:fabric-fernflower:1.4.1') diff --git a/src/main/java/net/fabricmc/loom/LoomGradleExtension.java b/src/main/java/net/fabricmc/loom/LoomGradleExtension.java index 5c7e2c0..e9624aa 100644 --- a/src/main/java/net/fabricmc/loom/LoomGradleExtension.java +++ b/src/main/java/net/fabricmc/loom/LoomGradleExtension.java @@ -25,6 +25,7 @@ package net.fabricmc.loom; import java.io.File; +import java.util.List; import java.util.Set; import java.util.function.Supplier; @@ -38,6 +39,7 @@ import org.gradle.api.file.ConfigurableFileCollection; import net.fabricmc.loom.api.LoomGradleExtensionAPI; import net.fabricmc.loom.configuration.InstallerData; import net.fabricmc.loom.configuration.LoomDependencyManager; +import net.fabricmc.loom.configuration.accesswidener.AccessWidenerFile; import net.fabricmc.loom.configuration.processors.JarProcessorManager; import net.fabricmc.loom.configuration.providers.MinecraftProviderImpl; import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl; @@ -103,4 +105,8 @@ public interface LoomGradleExtension extends LoomGradleExtensionAPI { @Override MixinExtension getMixin(); + + List getTransitiveAccessWideners(); + + void addTransitiveAccessWideners(List accessWidenerFiles); } diff --git a/src/main/java/net/fabricmc/loom/LoomGradlePlugin.java b/src/main/java/net/fabricmc/loom/LoomGradlePlugin.java index df3fe00..e5545b2 100644 --- a/src/main/java/net/fabricmc/loom/LoomGradlePlugin.java +++ b/src/main/java/net/fabricmc/loom/LoomGradlePlugin.java @@ -40,7 +40,6 @@ import net.fabricmc.loom.configuration.CompileConfiguration; import net.fabricmc.loom.configuration.FabricApiExtension; import net.fabricmc.loom.configuration.MavenPublication; import net.fabricmc.loom.configuration.ide.IdeConfiguration; -import net.fabricmc.loom.configuration.providers.mappings.MappingsCache; import net.fabricmc.loom.decompilers.DecompilerConfiguration; import net.fabricmc.loom.extension.LoomFiles; import net.fabricmc.loom.extension.LoomGradleExtensionImpl; @@ -68,7 +67,6 @@ public class LoomGradlePlugin implements BootstrappedPlugin { refreshDeps = project.getGradle().getStartParameter().isRefreshDependencies(); if (refreshDeps) { - MappingsCache.INSTANCE.invalidate(); project.getLogger().lifecycle("Refresh dependencies is in use, loom will be significantly slower."); } diff --git a/src/main/java/net/fabricmc/loom/configuration/accesswidener/TransitiveAccessWidenerJarProcessor.java b/src/main/java/net/fabricmc/loom/configuration/accesswidener/TransitiveAccessWidenerJarProcessor.java index 5412975..8ae9938 100644 --- a/src/main/java/net/fabricmc/loom/configuration/accesswidener/TransitiveAccessWidenerJarProcessor.java +++ b/src/main/java/net/fabricmc/loom/configuration/accesswidener/TransitiveAccessWidenerJarProcessor.java @@ -60,6 +60,8 @@ public class TransitiveAccessWidenerJarProcessor implements JarProcessor { this.extension = LoomGradleExtension.get(project); transitiveAccessWideners = getTransitiveAccessWideners(); + + extension.addTransitiveAccessWideners(transitiveAccessWideners); } @Override diff --git a/src/main/java/net/fabricmc/loom/configuration/accesswidener/TransitiveAccessWidenerMappingsProcessor.java b/src/main/java/net/fabricmc/loom/configuration/accesswidener/TransitiveAccessWidenerMappingsProcessor.java new file mode 100644 index 0000000..c96e814 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/accesswidener/TransitiveAccessWidenerMappingsProcessor.java @@ -0,0 +1,147 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2021 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom.configuration.accesswidener; + +import java.io.IOException; +import java.io.Reader; +import java.io.Writer; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; + +import org.gradle.api.logging.Logger; + +import net.fabricmc.accesswidener.AccessWidenerReader; +import net.fabricmc.accesswidener.AccessWidenerVisitor; +import net.fabricmc.accesswidener.TransitiveOnlyFilter; +import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; +import net.fabricmc.mappingio.MappingReader; +import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch; +import net.fabricmc.mappingio.format.Tiny2Writer; +import net.fabricmc.mappingio.tree.MappingTree; +import net.fabricmc.mappingio.tree.MemoryMappingTree; + +public final class TransitiveAccessWidenerMappingsProcessor { + private TransitiveAccessWidenerMappingsProcessor() { + } + + public static void process(Path inputMappings, Path outputMappings, List accessWideners, Logger logger) { + MemoryMappingTree mappingTree = new MemoryMappingTree(); + + try (Reader reader = Files.newBufferedReader(inputMappings, StandardCharsets.UTF_8)) { + MappingReader.read(reader, new MappingSourceNsSwitch(mappingTree, MappingsNamespace.INTERMEDIARY.toString())); + } catch (IOException e) { + throw new RuntimeException("Failed to read mappings", e); + } + + if (!MappingsNamespace.INTERMEDIARY.toString().equals(mappingTree.getSrcNamespace())) { + throw new IllegalStateException("Mapping tree must have intermediary src mappings not " + mappingTree.getSrcNamespace()); + } + + for (AccessWidenerFile accessWidener : accessWideners) { + MappingCommentVisitor mappingCommentVisitor = new MappingCommentVisitor(accessWidener.modId(), mappingTree, logger); + AccessWidenerReader accessWidenerReader = new AccessWidenerReader(new TransitiveOnlyFilter(mappingCommentVisitor)); + accessWidenerReader.read(accessWidener.content()); + } + + try (Writer writer = Files.newBufferedWriter(outputMappings, StandardCharsets.UTF_8)) { + Tiny2Writer tiny2Writer = new Tiny2Writer(writer, false); + mappingTree.accept(new MappingSourceNsSwitch(tiny2Writer, MappingsNamespace.NAMED.toString())); + } catch (IOException e) { + throw new RuntimeException("Failed to write mappings", e); + } + } + + private static record MappingCommentVisitor(String modId, MemoryMappingTree mappingTree, Logger logger) implements AccessWidenerVisitor { + @Override + public void visitClass(String name, AccessWidenerReader.AccessType access, boolean transitive) { + MappingTree.ClassMapping classMapping = mappingTree.getClass(name); + + if (classMapping == null) { + logger.warn("Failed to find class ({}) to mark access widened by mod ({})", name, modId()); + return; + } + + classMapping.setComment(appendComment(classMapping.getComment(), access)); + } + + @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); + + MappingTree.ClassMapping classMapping = mappingTree.getClass(owner); + + if (classMapping == null) { + logger.warn("Failed to find class ({}) to mark access widened by mod ({})", owner, modId()); + return; + } + + MappingTree.MethodMapping methodMapping = classMapping.getMethod(name, descriptor); + + if (methodMapping == null) { + logger.warn("Failed to find method ({}) in ({}) to mark access widened by mod ({})", name, owner, modId()); + return; + } + + methodMapping.setComment(appendComment(methodMapping.getComment(), access)); + } + + @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.ClassMapping classMapping = mappingTree.getClass(owner); + + if (classMapping == null) { + logger.warn("Failed to find class ({}) to mark access widened by mod ({})", name, modId()); + return; + } + + MappingTree.FieldMapping fieldMapping = classMapping.getField(name, descriptor); + + if (fieldMapping == null) { + logger.warn("Failed to find field ({}) in ({}) to mark access widened by mod ({})", name, owner, modId()); + return; + } + + fieldMapping.setComment(appendComment(fieldMapping.getComment(), access)); + } + + private String appendComment(String comment, AccessWidenerReader.AccessType access) { + if (comment == null) { + comment = ""; + } else { + comment += "\n"; + } + + comment += "Access widened by %s to %s".formatted(modId(), access); + + return comment; + } + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsCache.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsCache.java deleted file mode 100644 index 29eb594..0000000 --- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsCache.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * This file is part of fabric-loom, licensed under the MIT License (MIT). - * - * Copyright (c) 2016-2020 FabricMC - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.fabricmc.loom.configuration.providers.mappings; - -import java.io.BufferedReader; -import java.io.IOException; -import java.lang.ref.SoftReference; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.HashMap; -import java.util.Map; - -import net.fabricmc.loom.util.StaticPathWatcher; -import net.fabricmc.mapping.tree.TinyMappingFactory; -import net.fabricmc.mapping.tree.TinyTree; - -public final class MappingsCache { - public static final MappingsCache INSTANCE = new MappingsCache(); - - private final Map> mappingsCache = new HashMap<>(); - - // TODO: loom doesn't actually use new mappings when the mappings change until the gradle daemons are stopped - public TinyTree get(Path mappingsPath) throws IOException { - mappingsPath = mappingsPath.toAbsolutePath(); - - if (StaticPathWatcher.INSTANCE.hasFileChanged(mappingsPath)) { - mappingsCache.remove(mappingsPath); - } - - SoftReference ref = mappingsCache.get(mappingsPath); - - if (ref != null && ref.get() != null) { - return ref.get(); - } else { - try (BufferedReader reader = Files.newBufferedReader(mappingsPath)) { - TinyTree mappings = TinyMappingFactory.loadWithDetection(reader); - ref = new SoftReference<>(mappings); - mappingsCache.put(mappingsPath, ref); - return mappings; - } - } - } - - public void invalidate() { - mappingsCache.clear(); - } -} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProviderImpl.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProviderImpl.java index 603df94..47165bf 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProviderImpl.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProviderImpl.java @@ -35,6 +35,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; import java.util.Collections; +import java.util.Objects; import java.util.function.Consumer; import com.google.common.base.Stopwatch; @@ -59,10 +60,10 @@ import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvid import net.fabricmc.loom.util.Constants; import net.fabricmc.loom.util.DeletingFileVisitor; import net.fabricmc.loom.util.DownloadUtil; -import net.fabricmc.mapping.reader.v2.TinyV2Factory; -import net.fabricmc.mapping.tree.TinyTree; +import net.fabricmc.mappingio.MappingReader; import net.fabricmc.mappingio.adapter.MappingNsCompleter; import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch; +import net.fabricmc.mappingio.format.MappingFormat; import net.fabricmc.mappingio.format.Tiny2Reader; import net.fabricmc.mappingio.format.Tiny2Writer; import net.fabricmc.mappingio.tree.MemoryMappingTree; @@ -87,13 +88,14 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings private Path unpickDefinitions; private boolean hasUnpickDefinitions; private UnpickMetadata unpickMetadata; + private MemoryMappingTree mappingTree; public MappingsProviderImpl(Project project) { super(project); } - public TinyTree getMappings() throws IOException { - return MappingsCache.INSTANCE.get(tinyMappings); + public MemoryMappingTree getMappings() throws IOException { + return Objects.requireNonNull(mappingTree, "Cannot get mappings before they have been read"); } @Override @@ -119,6 +121,8 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings } } + mappingTree = readMappings(); + if (Files.notExists(tinyMappingsJar) || isRefreshDeps()) { ZipUtil.pack(new ZipEntrySource[] {new FileSource("mappings/mappings.tiny", tinyMappings.toFile())}, tinyMappingsJar.toFile()); } @@ -216,23 +220,22 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings } } + private MemoryMappingTree readMappings() throws IOException { + MemoryMappingTree mappingTree = new MemoryMappingTree(); + MappingReader.read(tinyMappings, mappingTree); + return mappingTree; + } + private static boolean areMappingsV2(Path path) throws IOException { try (BufferedReader reader = Files.newBufferedReader(path)) { - TinyV2Factory.readMetadata(reader); - return true; - } catch (IllegalArgumentException e) { - // TODO: just check the mappings version when Parser supports V1 in readMetadata() - return false; + return MappingReader.detectFormat(reader) == MappingFormat.TINY_2; } } private static boolean doesJarContainV2Mappings(Path path) throws IOException { try (FileSystem fs = FileSystems.newFileSystem(path, (ClassLoader) null)) { try (BufferedReader reader = Files.newBufferedReader(fs.getPath("mappings", "mappings.tiny"))) { - TinyV2Factory.readMetadata(reader); - return true; - } catch (IllegalArgumentException e) { - return false; + return MappingReader.detectFormat(reader) == MappingFormat.TINY_2; } } } diff --git a/src/main/java/net/fabricmc/loom/decompilers/fernflower/TinyJavadocProvider.java b/src/main/java/net/fabricmc/loom/decompilers/fernflower/TinyJavadocProvider.java index dee4820..f6f01e1 100644 --- a/src/main/java/net/fabricmc/loom/decompilers/fernflower/TinyJavadocProvider.java +++ b/src/main/java/net/fabricmc/loom/decompilers/fernflower/TinyJavadocProvider.java @@ -29,9 +29,7 @@ import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.jetbrains.java.decompiler.struct.StructClass; import org.jetbrains.java.decompiler.struct.StructField; @@ -40,48 +38,29 @@ import org.jetbrains.java.decompiler.struct.StructRecordComponent; import org.objectweb.asm.Opcodes; import net.fabricmc.fernflower.api.IFabricJavadocProvider; -import net.fabricmc.mapping.tree.ClassDef; -import net.fabricmc.mapping.tree.FieldDef; -import net.fabricmc.mapping.tree.MethodDef; -import net.fabricmc.mapping.tree.ParameterDef; -import net.fabricmc.mapping.tree.TinyMappingFactory; -import net.fabricmc.mapping.tree.TinyTree; -import net.fabricmc.mappings.EntryTriple; +import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; +import net.fabricmc.mappingio.MappingReader; +import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch; +import net.fabricmc.mappingio.tree.MappingTree; +import net.fabricmc.mappingio.tree.MemoryMappingTree; public class TinyJavadocProvider implements IFabricJavadocProvider { - private final Map classes = new HashMap<>(); - private final Map fields = new HashMap<>(); - private final Map methods = new HashMap<>(); - - private final String namespace = "named"; + private final MappingTree mappingTree; public TinyJavadocProvider(File tinyFile) { - final TinyTree mappings = readMappings(tinyFile); - - for (ClassDef classDef : mappings.getClasses()) { - final String className = classDef.getName(namespace); - classes.put(className, classDef); - - for (FieldDef fieldDef : classDef.getFields()) { - fields.put(new EntryTriple(className, fieldDef.getName(namespace), fieldDef.getDescriptor(namespace)), fieldDef); - } - - for (MethodDef methodDef : classDef.getMethods()) { - methods.put(new EntryTriple(className, methodDef.getName(namespace), methodDef.getDescriptor(namespace)), methodDef); - } - } + mappingTree = readMappings(tinyFile); } @Override public String getClassDoc(StructClass structClass) { - ClassDef classDef = classes.get(structClass.qualifiedName); + MappingTree.ClassMapping classMapping = mappingTree.getClass(structClass.qualifiedName); - if (classDef == null) { + if (classMapping == null) { return null; } if (!isRecord(structClass)) { - return classDef.getComment(); + return classMapping.getComment(); } /** @@ -91,30 +70,30 @@ public class TinyJavadocProvider implements IFabricJavadocProvider { */ List parts = new ArrayList<>(); - if (classDef.getComment() != null) { - parts.add(classDef.getComment()); + if (classMapping.getComment() != null) { + parts.add(classMapping.getComment()); } boolean addedParam = false; for (StructRecordComponent component : structClass.getRecordComponents()) { // The component will always match the field name and descriptor - FieldDef fieldDef = fields.get(new EntryTriple(structClass.qualifiedName, component.getName(), component.getDescriptor())); + MappingTree.FieldMapping fieldMapping = classMapping.getField(component.getName(), component.getDescriptor()); - if (fieldDef == null) { + if (fieldMapping == null) { continue; } - String comment = fieldDef.getComment(); + String comment = fieldMapping.getComment(); if (comment != null) { - if (!addedParam && classDef.getComment() != null) { + if (!addedParam && classMapping.getComment() != null) { //Add a blank line before components when the class has a comment parts.add(""); addedParam = true; } - parts.add(String.format("@param %s %s", fieldDef.getName(namespace), comment)); + parts.add(String.format("@param %s %s", fieldMapping.getName(MappingsNamespace.NAMED.toString()), comment)); } } @@ -132,34 +111,47 @@ public class TinyJavadocProvider implements IFabricJavadocProvider { return null; } - FieldDef fieldDef = fields.get(new EntryTriple(structClass.qualifiedName, structField.getName(), structField.getDescriptor())); - return fieldDef != null ? fieldDef.getComment() : null; + MappingTree.ClassMapping classMapping = mappingTree.getClass(structClass.qualifiedName); + + if (classMapping == null) { + return null; + } + + MappingTree.FieldMapping fieldMapping = classMapping.getField(structField.getName(), structField.getDescriptor()); + + return fieldMapping != null ? fieldMapping.getComment() : null; } @Override public String getMethodDoc(StructClass structClass, StructMethod structMethod) { - MethodDef methodDef = methods.get(new EntryTriple(structClass.qualifiedName, structMethod.getName(), structMethod.getDescriptor())); + MappingTree.ClassMapping classMapping = mappingTree.getClass(structClass.qualifiedName); - if (methodDef != null) { + if (classMapping == null) { + return null; + } + + MappingTree.MethodMapping methodMapping = classMapping.getMethod(structMethod.getName(), structMethod.getDescriptor()); + + if (methodMapping != null) { List parts = new ArrayList<>(); - if (methodDef.getComment() != null) { - parts.add(methodDef.getComment()); + if (methodMapping.getComment() != null) { + parts.add(methodMapping.getComment()); } boolean addedParam = false; - for (ParameterDef param : methodDef.getParameters()) { - String comment = param.getComment(); + for (MappingTree.MethodArgMapping argMapping : methodMapping.getArgs()) { + String comment = argMapping.getComment(); if (comment != null) { - if (!addedParam && methodDef.getComment() != null) { + if (!addedParam && methodMapping.getComment() != null) { //Add a blank line before params when the method has a comment parts.add(""); addedParam = true; } - parts.add(String.format("@param %s %s", param.getName(namespace), comment)); + parts.add(String.format("@param %s %s", methodMapping.getName(MappingsNamespace.NAMED.toString()), comment)); } } @@ -173,9 +165,13 @@ public class TinyJavadocProvider implements IFabricJavadocProvider { return null; } - private static TinyTree readMappings(File input) { + private static MappingTree readMappings(File input) { try (BufferedReader reader = Files.newBufferedReader(input.toPath())) { - return TinyMappingFactory.loadWithDetection(reader); + MemoryMappingTree mappingTree = new MemoryMappingTree(); + MappingSourceNsSwitch nsSwitch = new MappingSourceNsSwitch(mappingTree, MappingsNamespace.NAMED.toString()); + MappingReader.read(reader, nsSwitch); + + return mappingTree; } catch (IOException e) { throw new RuntimeException("Failed to read mappings", e); } diff --git a/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionImpl.java b/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionImpl.java index f35e793..da0fca7 100644 --- a/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionImpl.java +++ b/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionImpl.java @@ -25,9 +25,11 @@ package net.fabricmc.loom.extension; import java.io.File; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; @@ -43,6 +45,7 @@ import org.gradle.api.file.ConfigurableFileCollection; import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.configuration.InstallerData; import net.fabricmc.loom.configuration.LoomDependencyManager; +import net.fabricmc.loom.configuration.accesswidener.AccessWidenerFile; import net.fabricmc.loom.configuration.processors.JarProcessorManager; public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implements LoomGradleExtension { @@ -55,6 +58,7 @@ public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implemen private final MappingSet[] srcMappingCache = new MappingSet[2]; private final Mercury[] srcMercuryCache = new Mercury[2]; private final Map> lazyConfigurations = new HashMap<>(); + private final List transitiveAccessWideners = new ArrayList<>(); private LoomDependencyManager dependencyManager; private JarProcessorManager jarProcessorManager; @@ -168,4 +172,14 @@ public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implemen public MixinExtension getMixin() { return this.mixinApExtension; } + + @Override + public List getTransitiveAccessWideners() { + return transitiveAccessWideners; + } + + @Override + public void addTransitiveAccessWideners(List accessWidenerFiles) { + transitiveAccessWideners.addAll(accessWidenerFiles); + } } diff --git a/src/main/java/net/fabricmc/loom/task/GenerateSourcesTask.java b/src/main/java/net/fabricmc/loom/task/GenerateSourcesTask.java index 9bde07b..a19746b 100644 --- a/src/main/java/net/fabricmc/loom/task/GenerateSourcesTask.java +++ b/src/main/java/net/fabricmc/loom/task/GenerateSourcesTask.java @@ -30,6 +30,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; import java.util.Collection; +import java.util.List; import java.util.Locale; import java.util.stream.Collectors; @@ -41,6 +42,8 @@ import org.gradle.api.tasks.TaskAction; import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.api.decompilers.DecompilationMetadata; import net.fabricmc.loom.api.decompilers.LoomDecompiler; +import net.fabricmc.loom.configuration.accesswidener.AccessWidenerFile; +import net.fabricmc.loom.configuration.accesswidener.TransitiveAccessWidenerMappingsProcessor; import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl; import net.fabricmc.loom.decompilers.LineNumberRemapper; import net.fabricmc.loom.util.Constants; @@ -62,11 +65,10 @@ public class GenerateSourcesTask extends AbstractLoomTask { @TaskAction public void doTask() throws Throwable { int threads = Runtime.getRuntime().availableProcessors(); - Path javaDocs = getExtension().getMappingsProvider().tinyMappings; Collection libraries = getProject().getConfigurations().getByName(Constants.Configurations.MINECRAFT_DEPENDENCIES).getFiles() - .stream().map(File::toPath).collect(Collectors.toSet()); + .stream().map(File::toPath).collect(Collectors.toSet()); - DecompilationMetadata metadata = new DecompilationMetadata(threads, javaDocs, libraries); + DecompilationMetadata metadata = new DecompilationMetadata(threads, getMappings(), libraries); Path runtimeJar = getExtension().getMappingsProvider().mappedProvider.getMappedJar().toPath(); Path sourcesDestination = getMappedJarFileWithSuffix("-sources.jar").toPath(); Path linemap = getMappedJarFileWithSuffix("-sources.lmap").toPath(); @@ -92,7 +94,7 @@ public class GenerateSourcesTask extends AbstractLoomTask { progressLogger.start("Adjusting line numbers", "linemap"); try (StitchUtil.FileSystemDelegate inFs = StitchUtil.getJarFileSystem(oldCompiledJar.toFile(), true); - StitchUtil.FileSystemDelegate outFs = StitchUtil.getJarFileSystem(linemappedJarDestination.toFile(), true)) { + StitchUtil.FileSystemDelegate outFs = StitchUtil.getJarFileSystem(linemappedJarDestination.toFile(), true)) { remapper.process(progressLogger, inFs.get().getPath("/"), outFs.get().getPath("/")); } @@ -112,6 +114,32 @@ public class GenerateSourcesTask extends AbstractLoomTask { return new File(path.substring(0, path.length() - 4) + suffix); } + private Path getMappings() { + Path baseMappings = getExtension().getMappingsProvider().tinyMappings; + + if (getExtension().getEnableTransitiveAccessWideners().get()) { + List accessWideners = getExtension().getTransitiveAccessWideners(); + + if (accessWideners.isEmpty()) { + return baseMappings; + } + + Path outputMappings; + + try { + outputMappings = Files.createTempFile("loom-transitive-mappings", ".tiny"); + } catch (IOException e) { + throw new RuntimeException("Failed to create temp file", e); + } + + TransitiveAccessWidenerMappingsProcessor.process(baseMappings, outputMappings, accessWideners, getProject().getLogger()); + + return outputMappings; + } + + return baseMappings; + } + @InputFile public File getInputJar() { return inputJar; diff --git a/src/main/java/net/fabricmc/loom/task/MigrateMappingsTask.java b/src/main/java/net/fabricmc/loom/task/MigrateMappingsTask.java index 2afc276..c976dde 100644 --- a/src/main/java/net/fabricmc/loom/task/MigrateMappingsTask.java +++ b/src/main/java/net/fabricmc/loom/task/MigrateMappingsTask.java @@ -24,14 +24,12 @@ package net.fabricmc.loom.task; -import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.StandardCopyOption; import java.util.Set; import com.google.common.collect.ImmutableMap; @@ -49,15 +47,15 @@ import org.gradle.api.tasks.TaskAction; import org.gradle.api.tasks.options.Option; import net.fabricmc.loom.LoomGradleExtension; -import net.fabricmc.loom.api.mappings.layered.spec.LayeredMappingSpecBuilder; import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; +import net.fabricmc.loom.api.mappings.layered.spec.LayeredMappingSpecBuilder; import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingsDependency; import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl; import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider; import net.fabricmc.loom.util.SourceRemapper; import net.fabricmc.lorenztiny.TinyMappingsJoiner; -import net.fabricmc.mapping.tree.TinyMappingFactory; -import net.fabricmc.mapping.tree.TinyTree; +import net.fabricmc.mappingio.MappingReader; +import net.fabricmc.mappingio.tree.MemoryMappingTree; public class MigrateMappingsTask extends AbstractLoomTask { private Path inputDir; @@ -101,8 +99,8 @@ public class MigrateMappingsTask extends AbstractLoomTask { MappingsProviderImpl mappingsProvider = extension.getMappingsProvider(); try { - TinyTree currentMappings = mappingsProvider.getMappings(); - TinyTree targetMappings = getMappings(mappings); + MemoryMappingTree currentMappings = mappingsProvider.getMappings(); + MemoryMappingTree targetMappings = getMappings(mappings); migrateMappings(project, extension.getMinecraftMappedProvider(), inputDir, outputDir, currentMappings, targetMappings); project.getLogger().lifecycle(":remapped project written to " + outputDir.toAbsolutePath()); } catch (IOException e) { @@ -149,20 +147,18 @@ public class MigrateMappingsTask extends AbstractLoomTask { return Iterables.getOnlyElement(files); } - private static TinyTree getMappings(File mappings) throws IOException { - Path temp = Files.createTempFile("mappings", ".tiny"); + private static MemoryMappingTree getMappings(File mappings) throws IOException { + MemoryMappingTree mappingTree = new MemoryMappingTree(); try (FileSystem fileSystem = FileSystems.newFileSystem(mappings.toPath(), (ClassLoader) null)) { - Files.copy(fileSystem.getPath("mappings/mappings.tiny"), temp, StandardCopyOption.REPLACE_EXISTING); + MappingReader.read(fileSystem.getPath("mappings/mappings.tiny"), mappingTree); } - try (BufferedReader reader = Files.newBufferedReader(temp)) { - return TinyMappingFactory.loadWithDetection(reader); - } + return mappingTree; } private static void migrateMappings(Project project, MinecraftMappedProvider minecraftMappedProvider, - Path inputDir, Path outputDir, TinyTree currentMappings, TinyTree targetMappings + Path inputDir, Path outputDir, MemoryMappingTree currentMappings, MemoryMappingTree targetMappings ) throws IOException { project.getLogger().info(":joining mappings"); diff --git a/src/main/java/net/fabricmc/loom/util/SourceRemapper.java b/src/main/java/net/fabricmc/loom/util/SourceRemapper.java index 8f7bf89..ec1ce8a 100644 --- a/src/main/java/net/fabricmc/loom/util/SourceRemapper.java +++ b/src/main/java/net/fabricmc/loom/util/SourceRemapper.java @@ -45,7 +45,7 @@ import net.fabricmc.loom.configuration.RemappedConfigurationEntry; import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl; import net.fabricmc.loom.util.gradle.ProgressLogger; import net.fabricmc.lorenztiny.TinyMappingsReader; -import net.fabricmc.mapping.tree.TinyTree; +import net.fabricmc.mappingio.tree.MemoryMappingTree; import net.fabricmc.stitch.util.StitchUtil; public class SourceRemapper { @@ -165,7 +165,7 @@ public class SourceRemapper { MappingSet mappings = extension.getOrCreateSrcMappingCache(toNamed ? 1 : 0, () -> { try { - TinyTree m = mappingsProvider.getMappings(); + MemoryMappingTree m = mappingsProvider.getMappings(); project.getLogger().info(":loading " + (toNamed ? "intermediary -> named" : "named -> intermediary") + " source mappings"); return new TinyMappingsReader(m, toNamed ? MappingsNamespace.INTERMEDIARY.toString() : MappingsNamespace.NAMED.toString(), toNamed ? MappingsNamespace.NAMED.toString() : MappingsNamespace.INTERMEDIARY.toString()).read(); } catch (Exception e) { diff --git a/src/main/java/net/fabricmc/loom/util/TinyRemapperHelper.java b/src/main/java/net/fabricmc/loom/util/TinyRemapperHelper.java index bec7756..aa295f0 100644 --- a/src/main/java/net/fabricmc/loom/util/TinyRemapperHelper.java +++ b/src/main/java/net/fabricmc/loom/util/TinyRemapperHelper.java @@ -33,12 +33,7 @@ import com.google.common.collect.ImmutableMap; import org.gradle.api.Project; import net.fabricmc.loom.LoomGradleExtension; -import net.fabricmc.mapping.tree.ClassDef; -import net.fabricmc.mapping.tree.FieldDef; -import net.fabricmc.mapping.tree.LocalVariableDef; -import net.fabricmc.mapping.tree.MethodDef; -import net.fabricmc.mapping.tree.ParameterDef; -import net.fabricmc.mapping.tree.TinyTree; +import net.fabricmc.mappingio.tree.MappingTree; import net.fabricmc.tinyremapper.IMappingProvider; import net.fabricmc.tinyremapper.TinyRemapper; @@ -75,28 +70,34 @@ public final class TinyRemapperHelper { return new IMappingProvider.Member(className, memberName, descriptor); } - public static IMappingProvider create(TinyTree mappings, String from, String to, boolean remapLocalVariables) { + public static IMappingProvider create(MappingTree mappings, String from, String to, boolean remapLocalVariables) { return (acceptor) -> { - for (ClassDef classDef : mappings.getClasses()) { + for (MappingTree.ClassMapping classDef : mappings.getClasses()) { String className = classDef.getName(from); acceptor.acceptClass(className, classDef.getName(to)); - for (FieldDef field : classDef.getFields()) { - acceptor.acceptField(memberOf(className, field.getName(from), field.getDescriptor(from)), field.getName(to)); + for (MappingTree.FieldMapping field : classDef.getFields()) { + acceptor.acceptField(memberOf(className, field.getName(from), field.getDesc(from)), field.getName(to)); } - for (MethodDef method : classDef.getMethods()) { - IMappingProvider.Member methodIdentifier = memberOf(className, method.getName(from), method.getDescriptor(from)); + for (MappingTree.MethodMapping method : classDef.getMethods()) { + IMappingProvider.Member methodIdentifier = memberOf(className, method.getName(from), method.getDesc(from)); acceptor.acceptMethod(methodIdentifier, method.getName(to)); if (remapLocalVariables) { - for (ParameterDef parameter : method.getParameters()) { - acceptor.acceptMethodArg(methodIdentifier, parameter.getLocalVariableIndex(), parameter.getName(to)); + for (MappingTree.MethodArgMapping parameter : method.getArgs()) { + String name = parameter.getName(to); + + if (name == null) { + continue; + } + + acceptor.acceptMethodArg(methodIdentifier, parameter.getLvIndex(), name); } - for (LocalVariableDef localVariable : method.getLocalVariables()) { - acceptor.acceptMethodVar(methodIdentifier, localVariable.getLocalVariableIndex(), - localVariable.getLocalVariableStartOffset(), localVariable.getLocalVariableTableIndex(), + for (MappingTree.MethodVarMapping localVariable : method.getVars()) { + acceptor.acceptMethodVar(methodIdentifier, localVariable.getLvIndex(), + localVariable.getStartOpIdx(), localVariable.getLvtRowIndex(), localVariable.getName(to)); } }