diff options
author | shedaniel <daniel@shedaniel.me> | 2021-09-17 02:23:45 +0800 |
---|---|---|
committer | shedaniel <daniel@shedaniel.me> | 2021-09-17 02:23:45 +0800 |
commit | eff1f8ba523a777b4e0ad660458dd04abf363f36 (patch) | |
tree | ecaef55f557d9fba0941561fa50169c0a151314a | |
parent | 848a6a548f59161bbb7037965c366d167ce9be30 (diff) | |
parent | 2a040d03d7a8b7b67989a8ef986e374cffb72332 (diff) | |
download | architectury-loom-eff1f8ba523a777b4e0ad660458dd04abf363f36.tar.gz architectury-loom-eff1f8ba523a777b4e0ad660458dd04abf363f36.tar.bz2 architectury-loom-eff1f8ba523a777b4e0ad660458dd04abf363f36.zip |
Merge remote-tracking branch 'FabricMC/dev/0.10' into dev/0.10.0
# Conflicts:
# build.gradle
# src/main/java/net/fabricmc/loom/LoomGradleExtension.java
# src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java
# src/main/java/net/fabricmc/loom/configuration/accesswidener/AccessWidenerJarProcessor.java
# src/main/java/net/fabricmc/loom/configuration/mods/ModProcessor.java
# src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingSpecBuilderImpl.java
# src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProviderImpl.java
# src/main/java/net/fabricmc/loom/configuration/providers/mappings/mojmap/MojangMappingLayer.java
# src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftMappedProvider.java
# src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java
# src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionImpl.java
# src/main/java/net/fabricmc/loom/extension/MinecraftGradleExtension.java
# src/main/java/net/fabricmc/loom/task/MigrateMappingsTask.java
# src/main/java/net/fabricmc/loom/task/RemapJarTask.java
# src/main/java/net/fabricmc/loom/task/RemapSourcesJarTask.java
# src/main/java/net/fabricmc/loom/util/SourceRemapper.java
# src/main/java/net/fabricmc/loom/util/TinyRemapperMappingsHelper.java
# src/test/groovy/net/fabricmc/loom/test/unit/layeredmappings/LayeredMappingSpecBuilderTest.groovy
57 files changed, 1441 insertions, 505 deletions
diff --git a/build.gradle b/build.gradle index 33c5bc40..c67fd507 100644 --- a/build.gradle +++ b/build.gradle @@ -94,15 +94,12 @@ dependencies { // tinyfile management implementation ('dev.architectury:tiny-remapper:1.3.11') implementation ('dev.architectury:mappings-layers-core:1.4.9') - implementation ('net.fabricmc:tiny-mappings-parser:0.3.0+build.17') - - implementation 'net.fabricmc:access-widener:1.1.0' + 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') implementation "dev.architectury:refmap-remapper:1.0.5" // decompilers diff --git a/src/main/java/net/fabricmc/loom/LoomGradleExtension.java b/src/main/java/net/fabricmc/loom/LoomGradleExtension.java index 9c1a4047..d94aeffa 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.forge.FieldMigratedMappingsProvider; @@ -111,6 +113,10 @@ public interface LoomGradleExtension extends LoomGradleExtensionAPI { @Override MixinExtension getMixin(); + List<AccessWidenerFile> getTransitiveAccessWideners(); + + void addTransitiveAccessWideners(List<AccessWidenerFile> accessWidenerFiles); + // =================== // Architectury Loom // =================== diff --git a/src/main/java/net/fabricmc/loom/LoomGradlePlugin.java b/src/main/java/net/fabricmc/loom/LoomGradlePlugin.java index be8a5f24..cf0b5424 100644 --- a/src/main/java/net/fabricmc/loom/LoomGradlePlugin.java +++ b/src/main/java/net/fabricmc/loom/LoomGradlePlugin.java @@ -43,7 +43,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; @@ -78,7 +77,6 @@ public class LoomGradlePlugin implements BootstrappedPlugin { refreshDeps = project.getGradle().getStartParameter().isRefreshDependencies() || "true".equals(System.getProperty("loom.refresh")); 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/api/LoomGradleExtensionAPI.java b/src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java index eea65bf5..e8d724be 100644 --- a/src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java +++ b/src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java @@ -43,11 +43,11 @@ import org.gradle.api.publish.maven.MavenPublication; import org.jetbrains.annotations.ApiStatus; import net.fabricmc.loom.api.decompilers.LoomDecompiler; +import net.fabricmc.loom.api.mappings.layered.spec.LayeredMappingSpecBuilder; import net.fabricmc.loom.configuration.ide.RunConfig; import net.fabricmc.loom.configuration.ide.RunConfigSettings; import net.fabricmc.loom.configuration.launch.LaunchProviderSettings; import net.fabricmc.loom.configuration.processors.JarProcessor; -import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpecBuilder; import net.fabricmc.loom.util.DeprecationHelper; import net.fabricmc.loom.util.ModPlatform; @@ -213,6 +213,13 @@ public interface LoomGradleExtensionAPI { */ String getModVersion(); + /** + * When true loom will apply transitive access wideners from compile dependencies. + * + * @return the property controlling the transitive access wideners + */ + Property<Boolean> getEnableTransitiveAccessWideners(); + // =================== // Architectury Loom // =================== diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingContext.java b/src/main/java/net/fabricmc/loom/api/mappings/layered/MappingContext.java index 3fbfb655..cbc7d3ab 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingContext.java +++ b/src/main/java/net/fabricmc/loom/api/mappings/layered/MappingContext.java @@ -22,16 +22,22 @@ * SOFTWARE. */ -package net.fabricmc.loom.configuration.providers.mappings; +package net.fabricmc.loom.api.mappings.layered; -import java.io.File; +import java.nio.file.Path; +import org.gradle.api.artifacts.Dependency; import org.gradle.api.logging.Logger; +import org.jetbrains.annotations.ApiStatus; import net.fabricmc.loom.configuration.providers.MinecraftProvider; +import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider; +@ApiStatus.Experimental /* Very Experimental and not cleanly separated from the impl atm */ public interface MappingContext { - File mavenFile(String mavenNotation); + Path resolveDependency(Dependency dependency); + + Path resolveMavenDependency(String mavenNotation); MappingsProvider mappingsProvider(); @@ -44,7 +50,7 @@ public interface MappingContext { /** * Creates a temporary working dir to be used to store working files. */ - File workingDirectory(String name); + Path workingDirectory(String name); Logger getLogger(); } diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingLayer.java b/src/main/java/net/fabricmc/loom/api/mappings/layered/MappingLayer.java index f3717894..1f28d65a 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingLayer.java +++ b/src/main/java/net/fabricmc/loom/api/mappings/layered/MappingLayer.java @@ -22,21 +22,28 @@ * SOFTWARE. */ -package net.fabricmc.loom.configuration.providers.mappings; +package net.fabricmc.loom.api.mappings.layered; import java.io.IOException; import java.util.Collections; import java.util.List; +import org.jetbrains.annotations.ApiStatus; + import net.fabricmc.mappingio.MappingVisitor; +@ApiStatus.Experimental public interface MappingLayer { void visit(MappingVisitor mappingVisitor) throws IOException; - default MappingNamespace getSourceNamespace() { - return MappingNamespace.NAMED; + default MappingsNamespace getSourceNamespace() { + return MappingsNamespace.NAMED; } + /** + * Provides a list of layer classes that this mapping layer depends on. If such a layer is not present an Exception will be thrown when trying to resolve the layer. + * @return A list of MappingLayer classes to depend on. + */ default List<Class<? extends MappingLayer>> dependsOn() { return Collections.emptyList(); } diff --git a/src/main/java/net/fabricmc/loom/api/mappings/layered/MappingsNamespace.java b/src/main/java/net/fabricmc/loom/api/mappings/layered/MappingsNamespace.java new file mode 100644 index 00000000..ae32f7f9 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/api/mappings/layered/MappingsNamespace.java @@ -0,0 +1,56 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016-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.api.mappings.layered; + +import java.util.Locale; + +/** + * The standard namespaces used by loom. + */ +public enum MappingsNamespace { + /** + * Official mappings are the names that are used in the vanilla Minecraft game jars, these are usually obfuscated. + */ + OFFICIAL, + + /** + * Intermediary mappings have been generated to provide a stable set of names across minecraft versions. + * + * <p>Intermediary is used in a production runtime (outside a dev env) allowing mods to run across multiple versions of the game. Mods are remapped from "named" at build time. + * + * @see <a href="https://github.com/FabricMC/intermediary/">github.com/FabricMC/intermediary/</a> + */ + INTERMEDIARY, + + /** + * Named mappings are the developer friendly names used to develop mods against. + */ + NAMED; + + @Override + public String toString() { + return name().toLowerCase(Locale.ROOT); + } +} diff --git a/src/main/java/net/fabricmc/loom/api/mappings/layered/spec/FileSpec.java b/src/main/java/net/fabricmc/loom/api/mappings/layered/spec/FileSpec.java new file mode 100644 index 00000000..19129e5d --- /dev/null +++ b/src/main/java/net/fabricmc/loom/api/mappings/layered/spec/FileSpec.java @@ -0,0 +1,79 @@ +/* + * 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.api.mappings.layered.spec; + +import java.io.File; +import java.nio.file.Path; +import java.util.Objects; + +import org.gradle.api.artifacts.Dependency; +import org.gradle.api.file.RegularFileProperty; +import org.jetbrains.annotations.ApiStatus; + +import net.fabricmc.loom.api.mappings.layered.MappingContext; +import net.fabricmc.loom.configuration.providers.mappings.utils.DependencyFileSpec; +import net.fabricmc.loom.configuration.providers.mappings.utils.LocalFileSpec; +import net.fabricmc.loom.configuration.providers.mappings.utils.MavenFileSpec; + +/** + * FileSpec should be used in MappingsSpec's that take an input file. The input file can either be a local file or a gradle dep. + */ +@ApiStatus.Experimental +public interface FileSpec { + static FileSpec create(Object o) { + Objects.requireNonNull(o, "Object cannot be null"); + + if (o instanceof String s) { + return createFromMavenDependency(s); + } else if (o instanceof Dependency d) { + return createFromDependency(d); + } else if (o instanceof File f) { + return createFromFile(f); + } else if (o instanceof RegularFileProperty rfp) { + return createFromFile(rfp); + } + + throw new UnsupportedOperationException("Cannot create FileSpec from object of type:" + o.getClass().getCanonicalName()); + } + + static FileSpec createFromMavenDependency(String dependencyNotation) { + return new MavenFileSpec(dependencyNotation); + } + + static FileSpec createFromDependency(Dependency dependency) { + return new DependencyFileSpec(dependency); + } + + static FileSpec createFromFile(File file) { + return new LocalFileSpec(file); + } + + // Note resolved instantly, this is not lazy + static FileSpec createFromFile(RegularFileProperty regularFileProperty) { + return createFromFile(regularFileProperty.getAsFile().get()); + } + + Path get(MappingContext context); +} diff --git a/src/main/java/net/fabricmc/loom/api/mappings/layered/spec/LayeredMappingSpecBuilder.java b/src/main/java/net/fabricmc/loom/api/mappings/layered/spec/LayeredMappingSpecBuilder.java new file mode 100644 index 00000000..05180172 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/api/mappings/layered/spec/LayeredMappingSpecBuilder.java @@ -0,0 +1,50 @@ +/* + * 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.api.mappings.layered.spec; + +import org.gradle.api.Action; +import org.jetbrains.annotations.ApiStatus; + +/** + * Used to configure a layered mapping spec. + */ +@ApiStatus.Experimental +public interface LayeredMappingSpecBuilder { + /** + * Add a MappingsSpec layer. + */ + LayeredMappingSpecBuilder addLayer(MappingsSpec<?> mappingSpec); + + /** + * Add a layer that uses the official mappings provided by Mojang. + */ + LayeredMappingSpecBuilder officialMojangMappings(); + + default LayeredMappingSpecBuilder parchment(Object object) { + return parchment(object, parchmentMappingsSpecBuilder -> parchmentMappingsSpecBuilder.setRemovePrefix(true)); + } + + LayeredMappingSpecBuilder parchment(Object object, Action<ParchmentMappingsSpecBuilder> action); +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsSpec.java b/src/main/java/net/fabricmc/loom/api/mappings/layered/spec/MappingsSpec.java index 8b6adcea..8511614e 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsSpec.java +++ b/src/main/java/net/fabricmc/loom/api/mappings/layered/spec/MappingsSpec.java @@ -22,8 +22,21 @@ * SOFTWARE. */ -package net.fabricmc.loom.configuration.providers.mappings; +package net.fabricmc.loom.api.mappings.layered.spec; +import org.jetbrains.annotations.ApiStatus; + +import net.fabricmc.loom.api.mappings.layered.MappingContext; +import net.fabricmc.loom.api.mappings.layered.MappingLayer; + +/** + * A MappingsSpec is an immutable set of data used to create the MappingLayer. + * + * <p>The hashCode is used to generate a hash of the full layered mapping spec, used to cache. + * + * <p>Commonly implemented as a record + */ +@ApiStatus.Experimental public interface MappingsSpec<L extends MappingLayer> { L createLayer(MappingContext context); } diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingNamespace.java b/src/main/java/net/fabricmc/loom/api/mappings/layered/spec/ParchmentMappingsSpecBuilder.java index 991cdc79..ee3e07a0 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingNamespace.java +++ b/src/main/java/net/fabricmc/loom/api/mappings/layered/spec/ParchmentMappingsSpecBuilder.java @@ -1,7 +1,7 @@ /* * This file is part of fabric-loom, licensed under the MIT License (MIT). * - * Copyright (c) 2016-2021 FabricMC + * 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 @@ -22,16 +22,14 @@ * SOFTWARE. */ -package net.fabricmc.loom.configuration.providers.mappings; +package net.fabricmc.loom.api.mappings.layered.spec; -import java.util.Locale; +import org.jetbrains.annotations.ApiStatus; -public enum MappingNamespace { - OFFICIAL, - INTERMEDIARY, - NAMED; - - public String stringValue() { - return name().toLowerCase(Locale.ROOT); - } +@ApiStatus.Experimental +public interface ParchmentMappingsSpecBuilder { + /** + * When enabled the "p" prefix will be stripped from parameter names. + */ + ParchmentMappingsSpecBuilder setRemovePrefix(boolean removePrefix); } diff --git a/src/main/java/net/fabricmc/loom/configuration/accesswidener/AccessWidenerFile.java b/src/main/java/net/fabricmc/loom/configuration/accesswidener/AccessWidenerFile.java new file mode 100644 index 00000000..680aae92 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/accesswidener/AccessWidenerFile.java @@ -0,0 +1,66 @@ +/* + * 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.nio.charset.StandardCharsets; +import java.nio.file.Path; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import org.zeroturnaround.zip.ZipUtil; + +public record AccessWidenerFile( + String name, + String modId, + byte[] content +) { + /** + * Reads the access-widener contained in a mod jar, or returns null if there is none. + */ + public static AccessWidenerFile fromModJar(Path modJarPath) { + byte[] modJsonBytes = ZipUtil.unpackEntry(modJarPath.toFile(), "fabric.mod.json"); + + if (modJsonBytes == null) { + return null; + } + + JsonObject jsonObject = new Gson().fromJson(new String(modJsonBytes, StandardCharsets.UTF_8), JsonObject.class); + + if (!jsonObject.has("accessWidener")) { + return null; + } + + String awPath = jsonObject.get("accessWidener").getAsString(); + String modId = jsonObject.get("id").getAsString(); + + byte[] content = ZipUtil.unpackEntry(modJarPath.toFile(), awPath); + + return new AccessWidenerFile( + awPath, + modId, + content + ); + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/accesswidener/AccessWidenerJarProcessor.java b/src/main/java/net/fabricmc/loom/configuration/accesswidener/AccessWidenerJarProcessor.java index cecf4d34..bb7717bd 100644 --- a/src/main/java/net/fabricmc/loom/configuration/accesswidener/AccessWidenerJarProcessor.java +++ b/src/main/java/net/fabricmc/loom/configuration/accesswidener/AccessWidenerJarProcessor.java @@ -24,46 +24,38 @@ package net.fabricmc.loom.configuration.accesswidener; -import java.io.BufferedReader; import java.io.File; -import java.io.FileReader; import java.io.IOException; -import java.io.StringWriter; -import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; import java.nio.file.Path; import java.util.Arrays; -import java.util.List; -import java.util.Set; -import java.util.zip.ZipEntry; -import com.google.gson.Gson; -import com.google.gson.JsonObject; +import com.google.common.hash.Hashing; import dev.architectury.tinyremapper.TinyRemapper; import org.gradle.api.Project; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.ClassWriter; import org.objectweb.asm.commons.Remapper; import org.zeroturnaround.zip.ZipUtil; -import org.zeroturnaround.zip.transform.ByteArrayZipEntryTransformer; -import org.zeroturnaround.zip.transform.ZipEntryTransformer; -import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry; import net.fabricmc.accesswidener.AccessWidener; import net.fabricmc.accesswidener.AccessWidenerReader; import net.fabricmc.accesswidener.AccessWidenerRemapper; -import net.fabricmc.accesswidener.AccessWidenerVisitor; import net.fabricmc.accesswidener.AccessWidenerWriter; import net.fabricmc.loom.LoomGradleExtension; +import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; import net.fabricmc.loom.configuration.processors.JarProcessor; import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider; import net.fabricmc.loom.util.Checksum; import net.fabricmc.loom.util.Constants; public class AccessWidenerJarProcessor implements JarProcessor { - private AccessWidener accessWidener = new AccessWidener(); - private AccessWidenerReader accessWidenerReader = new AccessWidenerReader(accessWidener); + // Filename used to store hash of input access widener in processed jar file + private static final String HASH_FILENAME = "aw.sha256"; + // The mod's own access widener file + private byte[] modAccessWidener; + private final AccessWidener accessWidener = new AccessWidener(); private final Project project; + // This is a SHA256 hash across the mod's and all transitive AWs private byte[] inputHash; public AccessWidenerJarProcessor(Project project) { @@ -77,121 +69,53 @@ public class AccessWidenerJarProcessor implements JarProcessor { @Override public void setup() { - LoomGradleExtension loomGradleExtension = LoomGradleExtension.get(project); - File awPath = loomGradleExtension.getAccessWidenerPath().get().getAsFile(); - - if (!awPath.exists()) { - throw new RuntimeException("Could not find access widener file @ " + awPath.getAbsolutePath()); - } - - inputHash = Checksum.sha256(awPath); - - try (BufferedReader reader = new BufferedReader(new FileReader(awPath))) { - accessWidenerReader.read(reader); + LoomGradleExtension extension = LoomGradleExtension.get(project); + Path awPath = extension.getAccessWidenerPath().get().getAsFile().toPath(); + + // Read our own mod's access widener, used later for producing a version remapped to intermediary + try { + modAccessWidener = Files.readAllBytes(awPath); + } catch (NoSuchFileException e) { + throw new RuntimeException("Could not find access widener file @ " + awPath.toAbsolutePath()); } catch (IOException e) { - throw new RuntimeException("Failed to read project access widener file"); + throw new RuntimeException("Failed to read access widener: " + awPath); } - //Remap accessWidener if its not named, allows for AE's to be written in intermediary - if (!accessWidener.getNamespace().equals("named")) { - try { - List<String> validNamespaces = loomGradleExtension.getMappingsProvider().getMappings().getMetadata().getNamespaces(); + AccessWidenerReader reader = new AccessWidenerReader(accessWidener); + reader.read(modAccessWidener); - if (!validNamespaces.contains(accessWidener.getNamespace())) { - throw new UnsupportedOperationException(String.format("Access Widener namespace '%s' is not a valid namespace, it must be one of: '%s'", accessWidener.getNamespace(), String.join(", ", validNamespaces))); - } - - TinyRemapper tinyRemapper = loomGradleExtension.getMinecraftMappedProvider().getTinyRemapper(); - tinyRemapper.replaceMappings(loomGradleExtension.getMinecraftMappedProvider().getMappings(null, "official", "named")); - loomGradleExtension.getMinecraftMappedProvider(); - tinyRemapper.readClassPath(MinecraftMappedProvider.getRemapClasspath(project)); - - AccessWidenerRemapper remapper = new AccessWidenerRemapper(accessWidener, tinyRemapper.getRemapper(), "named"); - accessWidener = remapper.remap(); - - tinyRemapper.finish(); - } catch (IOException e) { - throw new RuntimeException("Failed to remap access widener", e); - } - } + inputHash = Hashing.sha256().hashBytes(modAccessWidener).asBytes(); } @Override public void process(File file) { - project.getLogger().lifecycle("Processing file: " + file.getName()); - ZipUtil.transformEntries(file, getTransformers(accessWidener.getTargets())); - ZipUtil.addEntry(file, "aw.sha256", inputHash); - } - - private ZipEntryTransformerEntry[] getTransformers(Set<String> classes) { - return classes.stream() - .map(string -> new ZipEntryTransformerEntry(string.replaceAll("\\.", "/") + ".class", getTransformer(string))) - .toArray(ZipEntryTransformerEntry[]::new); - } - - private ZipEntryTransformer getTransformer(String className) { - return new ByteArrayZipEntryTransformer() { - @Override - protected byte[] transform(ZipEntry zipEntry, byte[] input) { - ClassReader reader = new ClassReader(input); - ClassWriter writer = new ClassWriter(0); - ClassVisitor classVisitor = AccessWidenerVisitor.createClassVisitor(Constants.ASM_VERSION, writer, accessWidener); - - project.getLogger().lifecycle("Applying access widener to " + className); - - reader.accept(classVisitor, 0); - return writer.toByteArray(); - } - }; - } - - //Called when remapping the mod - public void remapAccessWidener(Path modJarPath, Remapper asmRemapper) throws IOException { - byte[] bytes = getRemappedAccessWidener(asmRemapper); - - String path = getAccessWidenerPath(modJarPath); - - if (path == null) { - throw new RuntimeException("Failed to find accessWidener in fabric.mod.json"); - } - - boolean replaced = ZipUtil.replaceEntry(modJarPath.toFile(), path, bytes); - - if (!replaced) { - project.getLogger().warn("Failed to replace access widener file at " + path); - } - } - - public byte[] getRemappedAccessWidener(Remapper asmRemapper) throws IOException { - AccessWidenerRemapper remapper = new AccessWidenerRemapper(accessWidener, asmRemapper, "intermediary"); - AccessWidener remapped = remapper.remap(); - AccessWidenerWriter accessWidenerWriter = new AccessWidenerWriter(remapped); - - try (StringWriter writer = new StringWriter()) { - accessWidenerWriter.write(writer); - return writer.toString().getBytes(); - } + AccessWidenerTransformer applier = new AccessWidenerTransformer(project.getLogger(), accessWidener); + applier.apply(file); + ZipUtil.addEntry(file, HASH_FILENAME, inputHash); } - public String getAccessWidenerPath(Path modJarPath) { - byte[] modJsonBytes = ZipUtil.unpackEntry(modJarPath.toFile(), "fabric.mod.json"); - - if (modJsonBytes == null) { - return null; - } - - JsonObject jsonObject = new Gson().fromJson(new String(modJsonBytes, StandardCharsets.UTF_8), JsonObject.class); - - if (!jsonObject.has("accessWidener")) { - return null; - } - - return jsonObject.get("accessWidener").getAsString(); + /** + * Get this mods access widener remapped to the intermediary namespace. + */ + public byte[] getRemappedAccessWidener(Remapper asmRemapper, String targetNamespace) throws IOException { + int version = AccessWidenerReader.readVersion(modAccessWidener); + + AccessWidenerWriter writer = new AccessWidenerWriter(version); + AccessWidenerRemapper remapper = new AccessWidenerRemapper( + writer, + asmRemapper, + MappingsNamespace.NAMED.toString(), + targetNamespace + ); + AccessWidenerReader reader = new AccessWidenerReader(remapper); + reader.read(modAccessWidener); + + return writer.write(); } @Override public boolean isInvalid(File file) { - byte[] hash = ZipUtil.unpackEntry(file, "aw.sha256"); + byte[] hash = ZipUtil.unpackEntry(file, HASH_FILENAME); if (hash == null) { return true; diff --git a/src/main/java/net/fabricmc/loom/configuration/accesswidener/AccessWidenerTransformer.java b/src/main/java/net/fabricmc/loom/configuration/accesswidener/AccessWidenerTransformer.java new file mode 100644 index 00000000..bdde7403 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/accesswidener/AccessWidenerTransformer.java @@ -0,0 +1,82 @@ +/* + * 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.File; +import java.util.Set; +import java.util.zip.ZipEntry; + +import org.gradle.api.logging.Logger; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ClassWriter; +import org.zeroturnaround.zip.ZipUtil; +import org.zeroturnaround.zip.transform.ByteArrayZipEntryTransformer; +import org.zeroturnaround.zip.transform.ZipEntryTransformer; +import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry; + +import net.fabricmc.accesswidener.AccessWidener; +import net.fabricmc.accesswidener.AccessWidenerClassVisitor; +import net.fabricmc.loom.util.Constants; + +final class AccessWidenerTransformer { + private final Logger logger; + private final AccessWidener accessWidener; + + AccessWidenerTransformer(Logger logger, AccessWidener accessWidener) { + this.logger = logger; + this.accessWidener = accessWidener; + } + + /** + * Apply the rules from an access-widener to the given jar or zip file. + */ + void apply(File jarFile) { + logger.lifecycle("Processing file: " + jarFile.getName()); + ZipUtil.transformEntries(jarFile, getTransformers(accessWidener.getTargets())); + } + + private ZipEntryTransformerEntry[] getTransformers(Set<String> classes) { + return classes.stream() + .map(string -> new ZipEntryTransformerEntry(string.replaceAll("\\.", "/") + ".class", getTransformer(string))) + .toArray(ZipEntryTransformerEntry[]::new); + } + + private ZipEntryTransformer getTransformer(String className) { + return new ByteArrayZipEntryTransformer() { + @Override + protected byte[] transform(ZipEntry zipEntry, byte[] input) { + ClassReader reader = new ClassReader(input); + ClassWriter writer = new ClassWriter(0); + ClassVisitor classVisitor = AccessWidenerClassVisitor.createClassVisitor(Constants.ASM_VERSION, writer, accessWidener); + + logger.info("Applying access widener to " + className); + + reader.accept(classVisitor, 0); + return writer.toByteArray(); + } + }; + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/accesswidener/TransitiveAccessWidenerJarProcessor.java b/src/main/java/net/fabricmc/loom/configuration/accesswidener/TransitiveAccessWidenerJarProcessor.java new file mode 100644 index 00000000..8ae99383 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/accesswidener/TransitiveAccessWidenerJarProcessor.java @@ -0,0 +1,202 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2020-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.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import com.google.common.base.Preconditions; +import org.gradle.api.Project; + +import net.fabricmc.accesswidener.AccessWidener; +import net.fabricmc.accesswidener.AccessWidenerReader; +import net.fabricmc.accesswidener.AccessWidenerRemapper; +import net.fabricmc.accesswidener.AccessWidenerVisitor; +import net.fabricmc.accesswidener.TransitiveOnlyFilter; +import net.fabricmc.loom.LoomGradleExtension; +import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; +import net.fabricmc.loom.configuration.RemappedConfigurationEntry; +import net.fabricmc.loom.configuration.processors.JarProcessor; +import net.fabricmc.loom.util.Constants; +import net.fabricmc.loom.util.TinyRemapperHelper; +import net.fabricmc.tinyremapper.TinyRemapper; + +/** + * Applies transitive access wideners that are inherited from mod and api dependencies. + */ +public class TransitiveAccessWidenerJarProcessor implements JarProcessor { + private final Project project; + private final LoomGradleExtension extension; + + private final List<AccessWidenerFile> transitiveAccessWideners; + + public TransitiveAccessWidenerJarProcessor(Project project) { + this.project = project; + this.extension = LoomGradleExtension.get(project); + + transitiveAccessWideners = getTransitiveAccessWideners(); + + extension.addTransitiveAccessWideners(transitiveAccessWideners); + } + + @Override + public void setup() { + } + + public boolean isEmpty() { + return transitiveAccessWideners.isEmpty(); + } + + @Override + public String getId() { + Preconditions.checkArgument(!isEmpty()); + + return "loom:transitive_access_wideners:" + transitiveAccessWideners.hashCode(); + } + + private List<AccessWidenerFile> getTransitiveAccessWideners() { + List<AccessWidenerFile> accessWideners = new ArrayList<>(); + + for (RemappedConfigurationEntry entry : Constants.MOD_COMPILE_ENTRIES) { + // Only apply global AWs from mods that are part of the compile classpath + if (!entry.compileClasspath()) { + continue; + } + + Set<File> artifacts = extension.getLazyConfigurationProvider(entry.sourceConfiguration()) + .get() + .resolve(); + + for (File artifact : artifacts) { + AccessWidenerFile accessWidener = AccessWidenerFile.fromModJar(artifact.toPath()); + + if (accessWidener == null) { + continue; + } + + if (!TransitiveDetectorVisitor.isTransitive(accessWidener.content())) { + // AW does not contain anything transitive, skip over it + continue; + } + + accessWideners.add(accessWidener); + } + } + + return accessWideners; + } + + @Override + public void process(File file) { + Preconditions.checkArgument(!isEmpty()); + + AccessWidener accessWidener = createAccessWidener(); + AccessWidenerTransformer transformer = new AccessWidenerTransformer(project.getLogger(), accessWidener); + transformer.apply(file); + } + + private AccessWidener createAccessWidener() { + AccessWidener accessWidener = new AccessWidener(); + // For other mods, only consider transitive AWs and remap from intermediary->named + TinyRemapper tinyRemapper = createTinyRemapper(); + + try { + AccessWidenerRemapper remappingVisitor = new AccessWidenerRemapper( + accessWidener, + tinyRemapper.getRemapper(), + MappingsNamespace.INTERMEDIARY.toString(), + MappingsNamespace.NAMED.toString() + ); + AccessWidenerReader transitiveReader = new AccessWidenerReader(new TransitiveOnlyFilter(remappingVisitor)); + + for (AccessWidenerFile accessWidenerFile : transitiveAccessWideners) { + project.getLogger().info("Reading transitive access widener from {}", accessWidenerFile.modId()); + transitiveReader.read(accessWidenerFile.content()); + } + } finally { + tinyRemapper.finish(); + } + + return accessWidener; + } + + private TinyRemapper createTinyRemapper() { + try { + TinyRemapper tinyRemapper = TinyRemapperHelper.getTinyRemapper(project, "intermediary", "named"); + + tinyRemapper.readClassPath(TinyRemapperHelper.getMinecraftDependencies(project)); + tinyRemapper.readClassPath(extension.getMinecraftMappedProvider().getIntermediaryJar().toPath()); + + return tinyRemapper; + } catch (IOException e) { + throw new RuntimeException("Failed to create tiny remapper for intermediary->named", e); + } + } + + @Override + public boolean isInvalid(File file) { + // The hash is handled by getId() + return false; + } + + private static class TransitiveDetectorVisitor implements AccessWidenerVisitor { + private boolean transitive = false; + + @Override + public void visitClass(String name, AccessWidenerReader.AccessType access, boolean transitive) { + if (transitive) { + this.transitive = true; + } + } + + @Override + public void visitMethod(String owner, String name, String descriptor, AccessWidenerReader.AccessType access, boolean transitive) { + if (transitive) { + this.transitive = true; + } + } + + @Override + public void visitField(String owner, String name, String descriptor, AccessWidenerReader.AccessType access, boolean transitive) { + if (transitive) { + this.transitive = true; + } + } + + public static boolean isTransitive(byte[] content) { + if (AccessWidenerReader.readVersion(content) < 2) { + // Transitive AWs are only in v2 or higher, so we can save parsing the file to find out... + return false; + } + + TransitiveDetectorVisitor transitiveDetector = new TransitiveDetectorVisitor(); + new AccessWidenerReader(transitiveDetector).read(content); + return transitiveDetector.transitive; + } + } +} 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 00000000..c96e8141 --- /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<AccessWidenerFile> 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/mods/ModProcessor.java b/src/main/java/net/fabricmc/loom/configuration/mods/ModProcessor.java index 46d2e2ae..54a7903f 100644 --- a/src/main/java/net/fabricmc/loom/configuration/mods/ModProcessor.java +++ b/src/main/java/net/fabricmc/loom/configuration/mods/ModProcessor.java @@ -24,13 +24,9 @@ package net.fabricmc.loom.configuration.mods; -import java.io.BufferedReader; -import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.StringWriter; import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.ArrayList; @@ -56,19 +52,19 @@ import org.zeroturnaround.zip.ZipUtil; import org.zeroturnaround.zip.transform.StringZipEntryTransformer; import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry; -import net.fabricmc.accesswidener.AccessWidener; import net.fabricmc.accesswidener.AccessWidenerReader; import net.fabricmc.accesswidener.AccessWidenerRemapper; import net.fabricmc.accesswidener.AccessWidenerWriter; import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.LoomGradlePlugin; +import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; import net.fabricmc.loom.configuration.RemappedConfigurationEntry; import net.fabricmc.loom.configuration.processors.dependency.ModDependencyInfo; import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl; import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider; import net.fabricmc.loom.util.Constants; import net.fabricmc.loom.util.LoggerFilter; -import net.fabricmc.loom.util.TinyRemapperMappingsHelper; +import net.fabricmc.loom.util.TinyRemapperHelper; import net.fabricmc.loom.util.srg.AtRemapper; import net.fabricmc.loom.util.srg.CoreModClassRemapper; import net.fabricmc.mapping.tree.TinyTree; @@ -107,7 +103,7 @@ public class ModProcessor { private static void stripNestedJars(File file) { if (!ZipUtil.containsEntry(file, "fabric.mod.json")) return; // Strip out all contained jar info as we dont want loader to try and load the jars contained in dev. - ZipUtil.transformEntries(file, new ZipEntryTransformerEntry[] {(new ZipEntryTransformerEntry("fabric.mod.json", new StringZipEntryTransformer() { + ZipUtil.transformEntries(file, new ZipEntryTransformerEntry[]{(new ZipEntryTransformerEntry("fabric.mod.json", new StringZipEntryTransformer() { @Override protected String transform(ZipEntry zipEntry, String input) { JsonObject json = LoomGradlePlugin.GSON.fromJson(input, JsonObject.class); @@ -117,29 +113,28 @@ public class ModProcessor { }))}); } + /** + * Remap another mod's access widener from intermediary to named, so that loader can apply it in our dev-env. + */ private static byte[] remapAccessWidener(byte[] input, Remapper remapper) { - try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(input), StandardCharsets.UTF_8))) { - AccessWidener accessWidener = new AccessWidener(); - AccessWidenerReader accessWidenerReader = new AccessWidenerReader(accessWidener); - accessWidenerReader.read(bufferedReader); - - AccessWidenerRemapper accessWidenerRemapper = new AccessWidenerRemapper(accessWidener, remapper, "named"); - AccessWidener remapped = accessWidenerRemapper.remap(); - AccessWidenerWriter accessWidenerWriter = new AccessWidenerWriter(remapped); - - try (StringWriter writer = new StringWriter()) { - accessWidenerWriter.write(writer); - return writer.toString().getBytes(StandardCharsets.UTF_8); - } - } catch (IOException e) { - throw new RuntimeException(e); - } + int version = AccessWidenerReader.readVersion(input); + + AccessWidenerWriter writer = new AccessWidenerWriter(version); + AccessWidenerRemapper awRemapper = new AccessWidenerRemapper( + writer, + remapper, + MappingsNamespace.INTERMEDIARY.toString(), + MappingsNamespace.NAMED.toString() + ); + AccessWidenerReader reader = new AccessWidenerReader(awRemapper); + reader.read(input); + return writer.write(); } private static void remapJars(Project project, List<ModDependencyInfo> processList) throws IOException { LoomGradleExtension extension = LoomGradleExtension.get(project); - String fromM = extension.isForge() ? "srg" : "intermediary"; - String toM = "named"; + String fromM = extension.isForge() ? MappingsNamespace.SRG.toString() : MappingsNamespace.INTERMEDIARY.toString(); + String toM = MappingsNamespace.NAMED.toString(); MinecraftMappedProvider mappedProvider = extension.getMinecraftMappedProvider(); MappingsProviderImpl mappingsProvider = extension.getMappingsProvider(); @@ -158,7 +153,7 @@ public class ModProcessor { TinyRemapper remapper = TinyRemapper.newRemapper() .logger(project.getLogger()::lifecycle) .logUnknownInvokeDynamic(false) - .withMappings(TinyRemapperMappingsHelper.create(mappings, fromM, toM, false)) + .withMappings(TinyRemapperHelper.create(mappings, fromM, toM, false)) .renameInvalidLocals(false) .build(); diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/GradleMappingContext.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/GradleMappingContext.java index e62e9e91..0d780f16 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/GradleMappingContext.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/GradleMappingContext.java @@ -25,12 +25,15 @@ package net.fabricmc.loom.configuration.providers.mappings; import java.io.File; +import java.nio.file.Path; import org.gradle.api.Project; import org.gradle.api.artifacts.Configuration; +import org.gradle.api.artifacts.Dependency; import org.gradle.api.logging.Logger; import net.fabricmc.loom.LoomGradleExtension; +import net.fabricmc.loom.api.mappings.layered.MappingContext; import net.fabricmc.loom.configuration.providers.MinecraftProvider; public class GradleMappingContext implements MappingContext { @@ -45,9 +48,14 @@ public class GradleMappingContext implements MappingContext { } @Override - public File mavenFile(String mavenNotation) { - Configuration configuration = project.getConfigurations().detachedConfiguration(project.getDependencies().create(mavenNotation)); - return configuration.getSingleFile(); + public Path resolveDependency(Dependency dependency) { + Configuration configuration = project.getConfigurations().detachedConfiguration(dependency); + return configuration.getSingleFile().toPath(); + } + + @Override + public Path resolveMavenDependency(String mavenNotation) { + return resolveDependency(project.getDependencies().create(mavenNotation)); } @Override @@ -61,8 +69,8 @@ public class GradleMappingContext implements MappingContext { } @Override - public File workingDirectory(String name) { - return new File(minecraftProvider().dir("layered/working_dir/" + workingDirName), name); + public Path workingDirectory(String name) { + return new File(minecraftProvider().dir("layered/working_dir/" + workingDirName), name).toPath(); } @Override diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingSpec.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingSpec.java index 2e47af39..cb09d71f 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingSpec.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingSpec.java @@ -26,6 +26,8 @@ package net.fabricmc.loom.configuration.providers.mappings; import java.util.List; +import net.fabricmc.loom.api.mappings.layered.spec.MappingsSpec; + public record LayeredMappingSpec(List<MappingsSpec<?>> layers) { public String getVersion() { // TODO something better? diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingSpecBuilder.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingSpecBuilderImpl.java index 3524b7e6..fdd14127 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingSpecBuilder.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingSpecBuilderImpl.java @@ -31,13 +31,17 @@ import java.util.List; import org.gradle.api.Action; import org.jetbrains.annotations.Nullable; +import net.fabricmc.loom.api.mappings.layered.spec.FileSpec; +import net.fabricmc.loom.api.mappings.layered.spec.LayeredMappingSpecBuilder; +import net.fabricmc.loom.api.mappings.layered.spec.MappingsSpec; +import net.fabricmc.loom.api.mappings.layered.spec.ParchmentMappingsSpecBuilder; import net.fabricmc.loom.api.LoomGradleExtensionAPI; import net.fabricmc.loom.configuration.providers.mappings.crane.CraneMappingsSpec; import net.fabricmc.loom.configuration.providers.mappings.intermediary.IntermediaryMappingsSpec; import net.fabricmc.loom.configuration.providers.mappings.mojmap.MojangMappingsSpec; -import net.fabricmc.loom.configuration.providers.mappings.parchment.ParchmentMappingsSpecBuilder; +import net.fabricmc.loom.configuration.providers.mappings.parchment.ParchmentMappingsSpecBuilderImpl; -public class LayeredMappingSpecBuilder { +public class LayeredMappingSpecBuilderImpl implements LayeredMappingSpecBuilder { private final List<MappingsSpec<?>> layers = new LinkedList<>(); @Nullable private final LoomGradleExtensionAPI extension; @@ -46,6 +50,9 @@ public class LayeredMappingSpecBuilder { this.extension = extension; } + @Override + public LayeredMappingSpecBuilder addLayer(MappingsSpec<?> mappingSpec) { + layers.add(mappingSpec); public LayeredMappingSpecBuilder officialMojangMappings() { layers.add(new MojangMappingsSpec(() -> extension != null && extension.isSilentMojangMappingsLicenseEnabled())); return this; @@ -56,11 +63,16 @@ public class LayeredMappingSpecBuilder { return this; } - public LayeredMappingSpecBuilder parchment(String mavenNotation, Action<ParchmentMappingsSpecBuilder> action) { - ParchmentMappingsSpecBuilder builder = ParchmentMappingsSpecBuilder.builder(mavenNotation); + @Override + public LayeredMappingSpecBuilder officialMojangMappings() { + return addLayer(new MojangMappingsSpec()); + } + + @Override + public LayeredMappingSpecBuilder parchment(Object object, Action<ParchmentMappingsSpecBuilder> action) { + ParchmentMappingsSpecBuilderImpl builder = ParchmentMappingsSpecBuilderImpl.builder(FileSpec.create(object)); action.execute(builder); - layers.add(builder.build()); - return this; + return addLayer(builder.build()); } public LayeredMappingSpecBuilder crane(String mavenNotation) { diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingsDependency.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingsDependency.java index ff48a5cf..84c9370d 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingsDependency.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingsDependency.java @@ -54,6 +54,8 @@ import org.zeroturnaround.zip.ZipEntrySource; import org.zeroturnaround.zip.ZipUtil; import net.fabricmc.loom.LoomGradlePlugin; +import net.fabricmc.loom.api.mappings.layered.MappingContext; +import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; import net.fabricmc.mappingio.adapter.MappingDstNsReorder; import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch; import net.fabricmc.mappingio.format.Tiny2Writer; @@ -87,8 +89,8 @@ public class LayeredMappingsDependency extends AbstractModuleDependency implemen try (Writer writer = new StringWriter()) { Tiny2Writer tiny2Writer = new Tiny2Writer(writer, false); - MappingDstNsReorder nsReorder = new MappingDstNsReorder(tiny2Writer, Collections.singletonList(MappingNamespace.NAMED.stringValue())); - MappingSourceNsSwitch nsSwitch = new MappingSourceNsSwitch(nsReorder, MappingNamespace.INTERMEDIARY.stringValue(), true); + MappingDstNsReorder nsReorder = new MappingDstNsReorder(tiny2Writer, Collections.singletonList(MappingsNamespace.NAMED.toString())); + MappingSourceNsSwitch nsSwitch = new MappingSourceNsSwitch(nsReorder, MappingsNamespace.INTERMEDIARY.toString(), true); mappings.accept(nsSwitch); Files.deleteIfExists(mappingsFile); diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingsProcessor.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingsProcessor.java index a3fa5294..b14902c5 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingsProcessor.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/LayeredMappingsProcessor.java @@ -28,6 +28,10 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; +import net.fabricmc.loom.api.mappings.layered.MappingContext; +import net.fabricmc.loom.api.mappings.layered.MappingLayer; +import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; +import net.fabricmc.loom.api.mappings.layered.spec.MappingsSpec; import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch; import net.fabricmc.mappingio.tree.MemoryMappingTree; @@ -55,7 +59,7 @@ public class LayeredMappingsProcessor { visitedLayers.add(layer.getClass()); // We have to rebuild a new tree to work on when a layer doesnt merge into layered - boolean rebuild = layer.getSourceNamespace() != MappingNamespace.NAMED; + boolean rebuild = layer.getSourceNamespace() != MappingsNamespace.NAMED; MemoryMappingTree workingTree; if (rebuild) { @@ -63,7 +67,7 @@ public class LayeredMappingsProcessor { // This can be null on the first layer if (mappingTree.getSrcNamespace() != null) { - var sourceNsSwitch = new MappingSourceNsSwitch(tempTree, layer.getSourceNamespace().stringValue()); + var sourceNsSwitch = new MappingSourceNsSwitch(tempTree, layer.getSourceNamespace().toString()); mappingTree.accept(sourceNsSwitch); } @@ -80,7 +84,7 @@ public class LayeredMappingsProcessor { if (rebuild) { mappingTree = new MemoryMappingTree(); - workingTree.accept(new MappingSourceNsSwitch(mappingTree, MappingNamespace.NAMED.stringValue())); + workingTree.accept(new MappingSourceNsSwitch(mappingTree, MappingsNamespace.NAMED.toString())); } } 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 29eb5949..00000000 --- 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<Path, SoftReference<TinyTree>> 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<TinyTree> 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 902b4cff..f08bf774 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 @@ -40,6 +40,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Objects; import java.util.function.Consumer; import com.google.common.base.Stopwatch; @@ -54,8 +55,10 @@ import org.zeroturnaround.zip.ZipUtil; import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.LoomGradlePlugin; +import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; import net.fabricmc.loom.configuration.DependencyProvider; import net.fabricmc.loom.configuration.accesswidener.AccessWidenerJarProcessor; +import net.fabricmc.loom.configuration.accesswidener.TransitiveAccessWidenerJarProcessor; import net.fabricmc.loom.configuration.processors.JarProcessorManager; import net.fabricmc.loom.configuration.processors.MinecraftProcessedProvider; import net.fabricmc.loom.configuration.providers.MinecraftProviderImpl; @@ -69,10 +72,10 @@ import net.fabricmc.loom.util.srg.MCPReader; import net.fabricmc.loom.util.srg.SrgMerger; import net.fabricmc.loom.util.srg.SrgNamedWriter; import net.fabricmc.mapping.reader.v2.TinyMetadata; -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; @@ -103,13 +106,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"); } public TinyTree getMappingsWithSrg() throws IOException { @@ -148,6 +152,7 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings patchedProvider.provide(dependency, postPopulationScheduler); } + mappingTree = readMappings(); manipulateMappings(mappingsJar.toPath()); if (getExtension().shouldGenerateSrgTiny()) { @@ -197,6 +202,14 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings extension.getGameJarProcessors().add(new AccessWidenerJarProcessor(getProject())); } + if (extension.getEnableTransitiveAccessWideners().get()) { + TransitiveAccessWidenerJarProcessor transitiveAccessWidenerJarProcessor = new TransitiveAccessWidenerJarProcessor(getProject()); + + if (!transitiveAccessWidenerJarProcessor.isEmpty()) { + extension.getGameJarProcessors().add(transitiveAccessWidenerJarProcessor); + } + } + extension.getAccessWidenerPath().finalizeValue(); extension.getGameJarProcessors().finalizeValue(); JarProcessorManager processorManager = new JarProcessorManager(extension.getGameJarProcessors().get()); @@ -305,6 +318,12 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings } } + private MemoryMappingTree readMappings() throws IOException { + MemoryMappingTree mappingTree = new MemoryMappingTree(); + MappingReader.read(tinyMappings, mappingTree); + return mappingTree; + } + private void readAndMergeMCP(Path mcpJar, Consumer<Runnable> postPopulationScheduler) throws Exception { Path intermediaryTinyPath = getIntermediaryTiny(); SrgProvider provider = getExtension().getSrgProvider(); @@ -334,9 +353,8 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings private static boolean areMappingsV2(Path path) throws IOException { try (BufferedReader reader = Files.newBufferedReader(path)) { - TinyV2Factory.readMetadata(reader); - return true; - } catch (IllegalArgumentException | NoSuchFileException e) { + return MappingReader.detectFormat(reader) == MappingFormat.TINY_2; + } catch (NoSuchFileException e) { // TODO: just check the mappings version when Parser supports V1 in readMetadata() return false; } @@ -354,10 +372,7 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings 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; } } } @@ -411,7 +426,7 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings project.getLogger().info(":merging mappings"); MemoryMappingTree tree = new MemoryMappingTree(); - MappingSourceNsSwitch sourceNsSwitch = new MappingSourceNsSwitch(tree, MappingNamespace.OFFICIAL.stringValue()); + MappingSourceNsSwitch sourceNsSwitch = new MappingSourceNsSwitch(tree, MappingsNamespace.OFFICIAL.toString()); readIntermediaryTree().accept(sourceNsSwitch); try (BufferedReader reader = Files.newBufferedReader(from, StandardCharsets.UTF_8)) { @@ -427,7 +442,7 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings private MemoryMappingTree readIntermediaryTree() throws IOException { MemoryMappingTree tree = new MemoryMappingTree(); - MappingNsCompleter nsCompleter = new MappingNsCompleter(tree, Collections.singletonMap(MappingNamespace.NAMED.stringValue(), MappingNamespace.INTERMEDIARY.stringValue()), true); + MappingNsCompleter nsCompleter = new MappingNsCompleter(tree, Collections.singletonMap(MappingsNamespace.NAMED.toString(), MappingsNamespace.INTERMEDIARY.toString()), true); try (BufferedReader reader = Files.newBufferedReader(getIntermediaryTiny(), StandardCharsets.UTF_8)) { Tiny2Reader.read(reader, nsCompleter); @@ -451,7 +466,7 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings runCommand(command, intermediaryMappings.toAbsolutePath().toString(), yarnMappings.toAbsolutePath().toString(), newMergedMappings.toAbsolutePath().toString(), - "intermediary", "official"); + MappingsNamespace.INTERMEDIARY.toString(), MappingsNamespace.OFFICIAL.toString()); } catch (Exception e) { throw new RuntimeException("Could not merge mappings from " + intermediaryMappings.toString() + " with mappings from " + yarnMappings, e); diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/intermediary/IntermediaryMappingLayer.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/intermediary/IntermediaryMappingLayer.java index abfc3685..83b3c5da 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/intermediary/IntermediaryMappingLayer.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/intermediary/IntermediaryMappingLayer.java @@ -32,22 +32,22 @@ import java.nio.file.Files; import java.util.Collections; import java.util.function.Supplier; -import net.fabricmc.loom.configuration.providers.mappings.MappingLayer; -import net.fabricmc.loom.configuration.providers.mappings.MappingNamespace; +import net.fabricmc.loom.api.mappings.layered.MappingLayer; +import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; import net.fabricmc.mappingio.MappingVisitor; import net.fabricmc.mappingio.adapter.MappingNsCompleter; import net.fabricmc.mappingio.format.Tiny2Reader; public record IntermediaryMappingLayer(Supplier<File> tinyFile) implements MappingLayer { @Override - public MappingNamespace getSourceNamespace() { - return MappingNamespace.OFFICIAL; + public MappingsNamespace getSourceNamespace() { + return MappingsNamespace.OFFICIAL; } @Override public void visit(MappingVisitor mappingVisitor) throws IOException { // Populate named with intermediary and add Add a "named" namespace - MappingNsCompleter nsCompleter = new MappingNsCompleter(mappingVisitor, Collections.singletonMap(MappingNamespace.NAMED.stringValue(), MappingNamespace.INTERMEDIARY.stringValue()), true); + MappingNsCompleter nsCompleter = new MappingNsCompleter(mappingVisitor, Collections.singletonMap(MappingsNamespace.NAMED.toString(), MappingsNamespace.INTERMEDIARY.toString()), true); try (BufferedReader reader = Files.newBufferedReader(tinyFile().get().toPath(), StandardCharsets.UTF_8)) { Tiny2Reader.read(reader, nsCompleter); diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/intermediary/IntermediaryMappingsSpec.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/intermediary/IntermediaryMappingsSpec.java index 4daf64f5..95277f52 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/intermediary/IntermediaryMappingsSpec.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/intermediary/IntermediaryMappingsSpec.java @@ -24,8 +24,8 @@ package net.fabricmc.loom.configuration.providers.mappings.intermediary; -import net.fabricmc.loom.configuration.providers.mappings.MappingContext; -import net.fabricmc.loom.configuration.providers.mappings.MappingsSpec; +import net.fabricmc.loom.api.mappings.layered.MappingContext; +import net.fabricmc.loom.api.mappings.layered.spec.MappingsSpec; public record IntermediaryMappingsSpec() implements MappingsSpec<IntermediaryMappingLayer> { @Override diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/mojmap/MojangMappingLayer.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/mojmap/MojangMappingLayer.java index 4b4d407b..ebf5d063 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/mojmap/MojangMappingLayer.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/mojmap/MojangMappingLayer.java @@ -25,7 +25,6 @@ package net.fabricmc.loom.configuration.providers.mappings.mojmap; import java.io.BufferedReader; -import java.io.File; import java.io.IOException; import java.net.URL; import java.nio.charset.StandardCharsets; @@ -35,8 +34,8 @@ import java.util.List; import org.gradle.api.logging.Logger; -import net.fabricmc.loom.configuration.providers.mappings.MappingLayer; -import net.fabricmc.loom.configuration.providers.mappings.MappingNamespace; +import net.fabricmc.loom.api.mappings.layered.MappingLayer; +import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionMeta; import net.fabricmc.loom.configuration.providers.mappings.intermediary.IntermediaryMappingLayer; import net.fabricmc.loom.util.HashedDownloadUtil; @@ -47,33 +46,33 @@ import net.fabricmc.mappingio.format.ProGuardReader; public record MojangMappingLayer(String minecraftVersion, MinecraftVersionMeta.Download clientDownload, MinecraftVersionMeta.Download serverDownload, - File workingDir, + Path workingDir, Logger logger, MojangMappingsSpec.SilenceLicenseOption silenceLicense) implements MappingLayer { @Override public void visit(MappingVisitor mappingVisitor) throws IOException { - var clientMappings = new File(workingDir(), "%s.client.txt".formatted(minecraftVersion)); - var serverMappings = new File(workingDir(), "%s.server.txt".formatted(minecraftVersion)); + Path clientMappings = workingDir().resolve("%s.client.txt".formatted(minecraftVersion)); + Path serverMappings = workingDir().resolve("%s.server.txt".formatted(minecraftVersion)); download(clientMappings, serverMappings); if (!silenceLicense.isSilent()) { - printMappingsLicense(clientMappings.toPath()); + printMappingsLicense(clientMappings); } // Make official the source namespace - MappingSourceNsSwitch nsSwitch = new MappingSourceNsSwitch(mappingVisitor, MappingNamespace.OFFICIAL.stringValue()); + MappingSourceNsSwitch nsSwitch = new MappingSourceNsSwitch(mappingVisitor, MappingsNamespace.OFFICIAL.toString()); - try (BufferedReader clientBufferedReader = Files.newBufferedReader(clientMappings.toPath(), StandardCharsets.UTF_8); - BufferedReader serverBufferedReader = Files.newBufferedReader(serverMappings.toPath(), StandardCharsets.UTF_8)) { - ProGuardReader.read(clientBufferedReader, MappingNamespace.NAMED.stringValue(), MappingNamespace.OFFICIAL.stringValue(), nsSwitch); - ProGuardReader.read(serverBufferedReader, MappingNamespace.NAMED.stringValue(), MappingNamespace.OFFICIAL.stringValue(), nsSwitch); + try (BufferedReader clientBufferedReader = Files.newBufferedReader(clientMappings, StandardCharsets.UTF_8); + BufferedReader serverBufferedReader = Files.newBufferedReader(serverMappings, StandardCharsets.UTF_8)) { + ProGuardReader.read(clientBufferedReader, MappingsNamespace.NAMED.toString(), MappingsNamespace.OFFICIAL.toString(), nsSwitch); + ProGuardReader.read(serverBufferedReader, MappingsNamespace.NAMED.toString(), MappingsNamespace.OFFICIAL.toString(), nsSwitch); } } - private void download(File clientMappings, File serverMappings) throws IOException { - HashedDownloadUtil.downloadIfInvalid(new URL(clientDownload().url()), clientMappings, clientDownload().sha1(), logger(), false); - HashedDownloadUtil.downloadIfInvalid(new URL(serverDownload().url()), serverMappings, serverDownload().sha1(), logger(), false); + private void download(Path clientMappings, Path serverMappings) throws IOException { + HashedDownloadUtil.downloadIfInvalid(new URL(clientDownload().url()), clientMappings.toFile(), clientDownload().sha1(), logger(), false); + HashedDownloadUtil.downloadIfInvalid(new URL(serverDownload().url()), serverMappings.toFile(), serverDownload().sha1(), logger(), false); } private void printMappingsLicense(Path clientMappings) { @@ -95,8 +94,8 @@ public record MojangMappingLayer(String minecraftVersion, } @Override - public MappingNamespace getSourceNamespace() { - return MappingNamespace.OFFICIAL; + public MappingsNamespace getSourceNamespace() { + return MappingsNamespace.OFFICIAL; } @Override diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/mojmap/MojangMappingsSpec.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/mojmap/MojangMappingsSpec.java index f304530f..9654ddca 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/mojmap/MojangMappingsSpec.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/mojmap/MojangMappingsSpec.java @@ -24,8 +24,8 @@ package net.fabricmc.loom.configuration.providers.mappings.mojmap; -import net.fabricmc.loom.configuration.providers.mappings.MappingContext; -import net.fabricmc.loom.configuration.providers.mappings.MappingsSpec; +import net.fabricmc.loom.api.mappings.layered.MappingContext; +import net.fabricmc.loom.api.mappings.layered.spec.MappingsSpec; import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionMeta; public record MojangMappingsSpec(SilenceLicenseOption silenceLicense) implements MappingsSpec<MojangMappingLayer> { diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/parchment/ParchmentMappingLayer.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/parchment/ParchmentMappingLayer.java index 448a33a1..f6b602e8 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/parchment/ParchmentMappingLayer.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/parchment/ParchmentMappingLayer.java @@ -24,19 +24,19 @@ package net.fabricmc.loom.configuration.providers.mappings.parchment; -import java.io.File; import java.io.IOException; import java.io.InputStreamReader; +import java.nio.file.Path; import java.util.Objects; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import net.fabricmc.loom.LoomGradlePlugin; -import net.fabricmc.loom.configuration.providers.mappings.MappingLayer; -import net.fabricmc.loom.configuration.providers.mappings.MappingNamespace; +import net.fabricmc.loom.api.mappings.layered.MappingLayer; +import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; import net.fabricmc.mappingio.MappingVisitor; -public record ParchmentMappingLayer(File parchmentFile, boolean removePrefix) implements MappingLayer { +public record ParchmentMappingLayer(Path parchmentFile, boolean removePrefix) implements MappingLayer { private static final String PARCHMENT_DATA_FILE_NAME = "parchment.json"; @Override @@ -47,11 +47,11 @@ public record ParchmentMappingLayer(File parchmentFile, boolean removePrefix) im mappingVisitor = new ParchmentPrefixStripingMappingVisitor(mappingVisitor); } - parchmentData.visit(mappingVisitor, MappingNamespace.NAMED.stringValue()); + parchmentData.visit(mappingVisitor, MappingsNamespace.NAMED.toString()); } private ParchmentTreeV1 getParchmentData() throws IOException { - try (var zipFile = new ZipFile(parchmentFile())) { + try (var zipFile = new ZipFile(parchmentFile().toFile())) { ZipEntry zipFileEntry = zipFile.getEntry(PARCHMENT_DATA_FILE_NAME); Objects.requireNonNull(zipFileEntry, "Could not find %s in parchment data file".formatted(PARCHMENT_DATA_FILE_NAME)); diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/parchment/ParchmentMappingsSpec.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/parchment/ParchmentMappingsSpec.java index 2b3f48b2..5af9503f 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/parchment/ParchmentMappingsSpec.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/parchment/ParchmentMappingsSpec.java @@ -24,12 +24,13 @@ package net.fabricmc.loom.configuration.providers.mappings.parchment; -import net.fabricmc.loom.configuration.providers.mappings.MappingContext; -import net.fabricmc.loom.configuration.providers.mappings.MappingsSpec; +import net.fabricmc.loom.api.mappings.layered.spec.FileSpec; +import net.fabricmc.loom.api.mappings.layered.MappingContext; +import net.fabricmc.loom.api.mappings.layered.spec.MappingsSpec; -public record ParchmentMappingsSpec(String mavenNotation, boolean removePrefix) implements MappingsSpec<ParchmentMappingLayer> { +public record ParchmentMappingsSpec(FileSpec fileSpec, boolean removePrefix) implements MappingsSpec<ParchmentMappingLayer> { @Override public ParchmentMappingLayer createLayer(MappingContext context) { - return new ParchmentMappingLayer(context.mavenFile(mavenNotation()), removePrefix()); + return new ParchmentMappingLayer(fileSpec.get(context), removePrefix()); } } diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/parchment/ParchmentMappingsSpecBuilder.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/parchment/ParchmentMappingsSpecBuilderImpl.java index 1fff3195..4830cad7 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/parchment/ParchmentMappingsSpecBuilder.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/parchment/ParchmentMappingsSpecBuilderImpl.java @@ -24,25 +24,29 @@ package net.fabricmc.loom.configuration.providers.mappings.parchment; -public class ParchmentMappingsSpecBuilder { - private final String mavenNotation; +import net.fabricmc.loom.api.mappings.layered.spec.FileSpec; +import net.fabricmc.loom.api.mappings.layered.spec.ParchmentMappingsSpecBuilder; + +public class ParchmentMappingsSpecBuilderImpl implements ParchmentMappingsSpecBuilder { + private final FileSpec fileSpec; private boolean removePrefix; - private ParchmentMappingsSpecBuilder(String mavenNotation) { - this.mavenNotation = mavenNotation; + private ParchmentMappingsSpecBuilderImpl(FileSpec fileSpec) { + this.fileSpec = fileSpec; } - public static ParchmentMappingsSpecBuilder builder(String depNotation) { - return new ParchmentMappingsSpecBuilder(depNotation); + public static ParchmentMappingsSpecBuilderImpl builder(FileSpec fileSpec) { + return new ParchmentMappingsSpecBuilderImpl(fileSpec); } + @Override public ParchmentMappingsSpecBuilder setRemovePrefix(boolean removePrefix) { this.removePrefix = removePrefix; return this; } public ParchmentMappingsSpec build() { - return new ParchmentMappingsSpec(mavenNotation, removePrefix); + return new ParchmentMappingsSpec(fileSpec, removePrefix); } } diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/utils/DependencyFileSpec.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/utils/DependencyFileSpec.java new file mode 100644 index 00000000..99c9d7d3 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/utils/DependencyFileSpec.java @@ -0,0 +1,69 @@ +/* + * 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.providers.mappings.utils; + +import java.io.File; +import java.nio.file.Path; +import java.util.Objects; +import java.util.Set; + +import org.gradle.api.artifacts.Dependency; +import org.gradle.api.artifacts.SelfResolvingDependency; + +import net.fabricmc.loom.api.mappings.layered.MappingContext; +import net.fabricmc.loom.api.mappings.layered.spec.FileSpec; + +public record DependencyFileSpec(Dependency dependency) implements FileSpec { + @Override + public Path get(MappingContext context) { + if (dependency instanceof SelfResolvingDependency selfResolvingDependency) { + Set<File> files = selfResolvingDependency.resolve(); + + if (files.size() == 0) { + throw new RuntimeException("SelfResolvingDependency (%s) resolved no files".formatted(selfResolvingDependency.toString())); + } else if (files.size() > 1) { + throw new RuntimeException("SelfResolvingDependency (%s) resolved too many files (%d) only 1 is expected".formatted(selfResolvingDependency.toString(), files.size())); + } + + return files.iterator().next().toPath(); + } + + return context.resolveDependency(dependency); + } + + @Override + public int hashCode() { + return Objects.hash(dependency.getGroup(), dependency.getName(), dependency.getVersion()); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof DependencyFileSpec other) { + return other.dependency().contentEquals(this.dependency()); + } + + return false; + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/utils/LocalFileSpec.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/utils/LocalFileSpec.java new file mode 100644 index 00000000..d870d691 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/utils/LocalFileSpec.java @@ -0,0 +1,63 @@ +/* + * 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.providers.mappings.utils; + +import java.io.File; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.Objects; + +import net.fabricmc.loom.api.mappings.layered.spec.FileSpec; +import net.fabricmc.loom.api.mappings.layered.MappingContext; +import net.fabricmc.loom.util.Checksum; + +public class LocalFileSpec implements FileSpec { + private final File file; + private final int hash; + + public LocalFileSpec(File file) { + this.file = file; + this.hash = calculateHashCode(); + } + + private int calculateHashCode() { + if (!file.exists()) { + throw new RuntimeException("Could not find %s, it must be present at spec creation time to calculate mappings hash".formatted(file.getAbsolutePath())); + } + + // Use the file hash as part of the spec, this means if the input file changes the mappings will be re-generated. + return Objects.hash(Arrays.hashCode(Checksum.sha256(file)), file.getAbsolutePath()); + } + + @Override + public Path get(MappingContext context) { + return file.toPath(); + } + + @Override + public int hashCode() { + return hash; + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/utils/MavenFileSpec.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/utils/MavenFileSpec.java new file mode 100644 index 00000000..f833fe15 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/utils/MavenFileSpec.java @@ -0,0 +1,37 @@ +/* + * 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.providers.mappings.utils; + +import java.nio.file.Path; + +import net.fabricmc.loom.api.mappings.layered.spec.FileSpec; +import net.fabricmc.loom.api.mappings.layered.MappingContext; + +public record MavenFileSpec(String dependencyNotation) implements FileSpec { + @Override + public Path get(MappingContext context) { + return context.resolveMavenDependency(dependencyNotation); + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftMappedProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftMappedProvider.java index f80e10f7..757d0355 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftMappedProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftMappedProvider.java @@ -46,6 +46,7 @@ import dev.architectury.tinyremapper.TinyRemapper; import org.gradle.api.Project; import org.jetbrains.annotations.Nullable; +import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; import net.fabricmc.loom.configuration.DependencyProvider; import net.fabricmc.loom.configuration.providers.MinecraftProviderImpl; import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl; @@ -56,7 +57,7 @@ import net.fabricmc.loom.util.DownloadUtil; import net.fabricmc.loom.util.FileSystemUtil; import net.fabricmc.loom.util.OperatingSystem; import net.fabricmc.loom.util.ThreadingUtils; -import net.fabricmc.loom.util.TinyRemapperMappingsHelper; +import net.fabricmc.loom.util.TinyRemapperHelper; import net.fabricmc.loom.util.srg.AtRemapper; import net.fabricmc.loom.util.srg.CoreModClassRemapper; import net.fabricmc.loom.util.srg.InnerClassRemapper; @@ -251,7 +252,7 @@ public class MinecraftMappedProvider extends DependencyProvider { assetsOut(inputForge, forgeAssets); } - remap(remapper, vanilla, forge, "official"); + remap(remapper, vanilla, forge, MappingsNamespace.OFFICIAL.toString()); } public static class Info { @@ -273,9 +274,9 @@ public class MinecraftMappedProvider extends DependencyProvider { public void remap(TinyRemapper remapper, Info vanilla, @Nullable Info forge, String fromM) throws IOException { Set<String> classNames = getExtension().isForge() ? InnerClassRemapper.readClassNames(vanilla.input) : null; - for (String toM : getExtension().isForge() ? Arrays.asList("intermediary", "srg", "named") : Arrays.asList("intermediary", "named")) { - Path output = "named".equals(toM) ? vanilla.outputMapped : "srg".equals(toM) ? vanilla.outputSrg : vanilla.outputIntermediary; - Path outputForge = forge == null ? null : "named".equals(toM) ? forge.outputMapped : "srg".equals(toM) ? forge.outputSrg : forge.outputIntermediary; + for (String toM : getExtension().isForge() ? Arrays.asList(MappingsNamespace.INTERMEDIARY.toString(), MappingsNamespace.SRG.toString(), MappingsNamespace.NAMED.toString()) : Arrays.asList(MappingsNamespace.INTERMEDIARY.toString(), MappingsNamespace.NAMED.toString())) { + Path output = MappingsNamespace.NAMED.toString().equals(toM) ? vanilla.outputMapped : MappingsNamespace.SRG.toString().equals(toM) ? vanilla.outputSrg : vanilla.outputIntermediary; + Path outputForge = forge == null ? null : MappingsNamespace.NAMED.toString().equals(toM) ? forge.outputMapped : MappingsNamespace.SRG.toString().equals(toM) ? forge.outputSrg : forge.outputIntermediary; InputTag vanillaTag = remapper.createInputTag(); InputTag forgeTag = remapper.createInputTag(); Stopwatch stopwatch = Stopwatch.createStarted(); @@ -294,6 +295,7 @@ public class MinecraftMappedProvider extends DependencyProvider { OutputRemappingHandler.remap(remapper, forge.assets, outputForge, null, forgeTag); } + // TODO TinyRemapperHelper getProject().getLogger().lifecycle(":remapped minecraft (TinyRemapper, " + fromM + " -> " + toM + ") in " + stopwatch); remapper.removeInput(); diff --git a/src/main/java/net/fabricmc/loom/decompilers/LineNumberRemapper.java b/src/main/java/net/fabricmc/loom/decompilers/LineNumberRemapper.java index c2cb4d06..7e500301 100644 --- a/src/main/java/net/fabricmc/loom/decompilers/LineNumberRemapper.java +++ b/src/main/java/net/fabricmc/loom/decompilers/LineNumberRemapper.java @@ -126,12 +126,12 @@ public class LineNumberRemapper { reader.accept(new LineNumberVisitor(Constants.ASM_VERSION, writer, lineMap.get(idx)), 0); Files.write(dst, writer.toByteArray()); + return FileVisitResult.CONTINUE; } } - } else { - Files.copy(file, dst, StandardCopyOption.REPLACE_EXISTING); } + Files.copy(file, dst, StandardCopyOption.REPLACE_EXISTING); return FileVisitResult.CONTINUE; } }); 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 dee4820e..f6f01e1f 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<String, ClassDef> classes = new HashMap<>(); - private final Map<EntryTriple, FieldDef> fields = new HashMap<>(); - private final Map<EntryTriple, MethodDef> 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<String> 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 (classMapping == null) { + return null; + } - if (methodDef != null) { + MappingTree.MethodMapping methodMapping = classMapping.getMethod(structMethod.getName(), structMethod.getDescriptor()); + + if (methodMapping != null) { List<String> 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/LoomGradleExtensionApiImpl.java b/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java index 4cbf8d23..4abb717b 100644 --- a/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java +++ b/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java @@ -53,6 +53,7 @@ import org.gradle.api.tasks.SourceSet; import net.fabricmc.loom.api.LoomGradleExtensionAPI; import net.fabricmc.loom.api.MixinExtensionAPI; import net.fabricmc.loom.api.decompilers.LoomDecompiler; +import net.fabricmc.loom.api.mappings.layered.spec.LayeredMappingSpecBuilder; import net.fabricmc.loom.api.ForgeExtensionAPI; import net.fabricmc.loom.configuration.ide.RunConfig; import net.fabricmc.loom.configuration.ide.RunConfigSettings; @@ -61,7 +62,7 @@ import net.fabricmc.loom.configuration.launch.LaunchProviderSettings; import net.fabricmc.loom.configuration.processors.JarProcessor; import net.fabricmc.loom.configuration.providers.mappings.GradleMappingContext; import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpec; -import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpecBuilder; +import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpecBuilderImpl; import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingsDependency; import net.fabricmc.loom.util.DeprecationHelper; import net.fabricmc.loom.util.ModPlatform; @@ -84,6 +85,7 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA protected final Property<Boolean> remapArchives; protected final Property<String> customManifest; protected final Property<Boolean> setupRemappedVariants; + protected final Property<Boolean> transitiveAccessWideners; private final ModVersionParser versionParser; @@ -122,6 +124,9 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA this.customManifest = project.getObjects().property(String.class); this.setupRemappedVariants = project.getObjects().property(Boolean.class) .convention(true); + this.transitiveAccessWideners = project.getObjects().property(Boolean.class) + .convention(true); + this.transitiveAccessWideners.finalizeValueOnRead(); this.versionParser = new ModVersionParser(project); @@ -174,7 +179,7 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA @Override public Dependency layered(Action<LayeredMappingSpecBuilder> action) { - LayeredMappingSpecBuilder builder = new LayeredMappingSpecBuilder(this); + LayeredMappingSpecBuilderImpl builder = new LayeredMappingSpecBuilderImpl(this); action.execute(builder); LayeredMappingSpec builtSpec = builder.build(); return new LayeredMappingsDependency(new GradleMappingContext(getProject(), builtSpec.getVersion().replace("+", "_").replace(".", "_")), builtSpec, builtSpec.getVersion()); @@ -222,6 +227,11 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA return versionParser.getModVersion(); } + @Override + public Property<Boolean> getEnableTransitiveAccessWideners() { + return transitiveAccessWideners; + } + protected abstract Project getProject(); protected abstract LoomFiles getFiles(); diff --git a/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionImpl.java b/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionImpl.java index ec1c5351..7728bde6 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; @@ -45,6 +47,7 @@ import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.api.ForgeExtensionAPI; 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.util.ModPlatform; @@ -59,6 +62,7 @@ public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implemen private final MappingSet[] srcMappingCache = new MappingSet[2]; private final Mercury[] srcMercuryCache = new Mercury[2]; private final Map<String, NamedDomainObjectProvider<Configuration>> lazyConfigurations = new HashMap<>(); + private final List<AccessWidenerFile> transitiveAccessWideners = new ArrayList<>(); private LoomDependencyManager dependencyManager; private JarProcessorManager jarProcessorManager; @@ -177,6 +181,16 @@ public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implemen } @Override + public List<AccessWidenerFile> getTransitiveAccessWideners() { + return transitiveAccessWideners; + } + + @Override + public void addTransitiveAccessWideners(List<AccessWidenerFile> accessWidenerFiles) { + transitiveAccessWideners.addAll(accessWidenerFiles); + } + + @Override protected String getMinecraftVersion() { return getMinecraftProvider().minecraftVersion(); } diff --git a/src/main/java/net/fabricmc/loom/extension/MinecraftGradleExtension.java b/src/main/java/net/fabricmc/loom/extension/MinecraftGradleExtension.java index 9397e17c..a525bbf8 100644 --- a/src/main/java/net/fabricmc/loom/extension/MinecraftGradleExtension.java +++ b/src/main/java/net/fabricmc/loom/extension/MinecraftGradleExtension.java @@ -45,11 +45,11 @@ import net.fabricmc.loom.api.ForgeExtensionAPI; import net.fabricmc.loom.api.LoomGradleExtensionAPI; import net.fabricmc.loom.api.MixinExtensionAPI; import net.fabricmc.loom.api.decompilers.LoomDecompiler; +import net.fabricmc.loom.api.mappings.layered.spec.LayeredMappingSpecBuilder; import net.fabricmc.loom.configuration.ide.RunConfig; import net.fabricmc.loom.configuration.ide.RunConfigSettings; import net.fabricmc.loom.configuration.launch.LaunchProviderSettings; import net.fabricmc.loom.configuration.processors.JarProcessor; -import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpecBuilder; import net.fabricmc.loom.util.DeprecationHelper; import net.fabricmc.loom.util.ModPlatform; @@ -164,6 +164,12 @@ public class MinecraftGradleExtension implements LoomGradleExtensionAPI { } @Override + public Property<Boolean> getEnableTransitiveAccessWideners() { + reportDeprecation(); + throw new UnsupportedOperationException(); + } + + @Override public void silentMojangMappingsLicense() { reportDeprecation(); parent.silentMojangMappingsLicense(); diff --git a/src/main/java/net/fabricmc/loom/task/GenerateSourcesTask.java b/src/main/java/net/fabricmc/loom/task/GenerateSourcesTask.java index c8dbb0ef..e644cb31 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; @@ -42,6 +43,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; @@ -63,11 +66,10 @@ public class GenerateSourcesTask extends AbstractLoomTask { @TaskAction public void doTask() throws Throwable { int threads = Runtime.getRuntime().availableProcessors(); - Path javaDocs = getExtension().getMappingsProvider().tinyMappings; Collection<Path> 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(); @@ -93,7 +95,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("/")); } @@ -121,6 +123,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<AccessWidenerFile> 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 84cee1c9..f7181637 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,14 +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.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.configuration.providers.mappings.LayeredMappingSpecBuilder; -import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingsDependency; 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; @@ -100,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, extension.getMinecraftMappedProvider(), inputDir, outputDir, currentMappings, targetMappings); project.getLogger().lifecycle(":remapped project written to " + outputDir.toAbsolutePath()); } catch (IOException e) { @@ -148,27 +147,25 @@ 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, LoomGradleExtension extension, 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"); MappingSet mappingSet = new TinyMappingsJoiner( - currentMappings, "named", - targetMappings, "named", - "intermediary" + currentMappings, MappingsNamespace.NAMED.toString(), + targetMappings, MappingsNamespace.NAMED.toString(), + MappingsNamespace.INTERMEDIARY.toString() ).read(); project.getLogger().lifecycle(":remapping"); diff --git a/src/main/java/net/fabricmc/loom/task/RemapJarTask.java b/src/main/java/net/fabricmc/loom/task/RemapJarTask.java index 48b9e9bd..5e395a02 100644 --- a/src/main/java/net/fabricmc/loom/task/RemapJarTask.java +++ b/src/main/java/net/fabricmc/loom/task/RemapJarTask.java @@ -86,6 +86,7 @@ import org.zeroturnaround.zip.transform.StreamZipEntryTransformer; import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry; import net.fabricmc.loom.LoomGradleExtension; +import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; import net.fabricmc.loom.build.JarRemapper; import net.fabricmc.loom.build.MixinRefmapHelper; import net.fabricmc.loom.build.nesting.EmptyNestedJarProvider; @@ -95,12 +96,13 @@ import net.fabricmc.loom.build.nesting.NestedDependencyProvider; import net.fabricmc.loom.build.nesting.NestedJarPathProvider; import net.fabricmc.loom.build.nesting.NestedJarProvider; import net.fabricmc.loom.configuration.JarManifestConfiguration; +import net.fabricmc.loom.configuration.accesswidener.AccessWidenerFile; import net.fabricmc.loom.configuration.accesswidener.AccessWidenerJarProcessor; import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl; import net.fabricmc.loom.util.Constants; import net.fabricmc.loom.util.FileSystemUtil; import net.fabricmc.loom.util.SourceRemapper; -import net.fabricmc.loom.util.TinyRemapperMappingsHelper; +import net.fabricmc.loom.util.TinyRemapperHelper; import net.fabricmc.loom.util.ZipReprocessorUtil; import net.fabricmc.loom.util.aw2at.Aw2At; import net.fabricmc.lorenztiny.TinyMappingsReader; @@ -247,7 +249,7 @@ public class RemapJarTask extends Jar { if (isMainRemapTask) { jarRemapper.addToClasspath(getRemapClasspath()); - jarRemapper.addMappings(TinyRemapperMappingsHelper.create(extension.shouldGenerateSrgTiny() ? mappingsProvider.getMappingsWithSrg() : mappingsProvider.getMappings(), fromM, toM, false)); + jarRemapper.addMappings(TinyRemapperHelper.create(extension.shouldGenerateSrgTiny() ? mappingsProvider.getMappingsWithSrg() : mappingsProvider.getMappings(), fromM, toM, false)); } for (File mixinMapFile : extension.getAllMixinMappings()) { @@ -272,15 +274,15 @@ public class RemapJarTask extends Jar { byte[] data; try { - data = accessWidenerJarProcessor.getRemappedAccessWidener(remapper); + data = accessWidenerJarProcessor.getRemappedAccessWidener(remapper, toM); } catch (IOException e) { - throw new RuntimeException("Failed to remap access widener"); + throw new RuntimeException("Failed to remap access widener", e); } - String awPath = accessWidenerJarProcessor.getAccessWidenerPath(remapData.input); - Preconditions.checkNotNull(awPath, "Failed to find accessWidener in fabric.mod.json: " + remapData.input); + AccessWidenerFile awFile = AccessWidenerFile.fromModJar(remapData.input); + Preconditions.checkNotNull(awFile, "Failed to find accessWidener in fabric.mod.json: " + remapData.input); - return Pair.of(awPath, data); + return Pair.of(awFile.name(), data); } return null; @@ -559,7 +561,8 @@ public class RemapJarTask extends Jar { return this; } - @ApiStatus.Experimental // This only allows mod jars, proceed with care when trying to pass in configurations with projects, or something that depends on a task. + @ApiStatus.Experimental + // This only allows mod jars, proceed with care when trying to pass in configurations with projects, or something that depends on a task. public RemapJarTask include(Object... paths) { Collections.addAll(nestedPaths, paths); this.addNestedDependencies.set(true); diff --git a/src/main/java/net/fabricmc/loom/task/RemapSourcesJarTask.java b/src/main/java/net/fabricmc/loom/task/RemapSourcesJarTask.java index d8cb2e13..97556c13 100644 --- a/src/main/java/net/fabricmc/loom/task/RemapSourcesJarTask.java +++ b/src/main/java/net/fabricmc/loom/task/RemapSourcesJarTask.java @@ -32,6 +32,7 @@ import org.gradle.api.tasks.Internal; import org.gradle.api.tasks.OutputFile; import org.gradle.api.tasks.TaskAction; +import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; import net.fabricmc.loom.util.SourceRemapper; public class RemapSourcesJarTask extends AbstractLoomTask { @@ -53,7 +54,7 @@ public class RemapSourcesJarTask extends AbstractLoomTask { if (sourceRemapper == null) { if (sourceNamespace.get().equals(targetNamespace.get())) { SourceRemapper.remapSources(getProject(), getInput().get().getAsFile(), getOutput().get().getAsFile(), - targetNamespace.get().equals("named") ? SourceRemapper.intermediary(getProject()) : "named", targetNamespace.get(), reproducibleFileOrder.get(), preserveFileTimestamps.get()); + targetNamespace.get().equals(MappingsNamespace.NAMED.toString()) ? SourceRemapper.intermediary(getProject()) : "named", targetNamespace.get(), reproducibleFileOrder.get(), preserveFileTimestamps.get()); } else { SourceRemapper.remapSources(getProject(), getInput().get().getAsFile(), getOutput().get().getAsFile(), sourceNamespace.get(), targetNamespace.get(), reproducibleFileOrder.get(), preserveFileTimestamps.get()); } diff --git a/src/main/java/net/fabricmc/loom/util/Constants.java b/src/main/java/net/fabricmc/loom/util/Constants.java index d38cadae..b5ab3798 100644 --- a/src/main/java/net/fabricmc/loom/util/Constants.java +++ b/src/main/java/net/fabricmc/loom/util/Constants.java @@ -53,8 +53,6 @@ public class Constants { new RemappedConfigurationEntry("modRuntimeOnly", JavaPlugin.RUNTIME_ONLY_CONFIGURATION_NAME, false, true, JavaPlugin.RUNTIME_ELEMENTS_CONFIGURATION_NAME) ); - public static final String SOFTWARE_COMPONENT_NAME = "loom"; - private Constants() { } diff --git a/src/main/java/net/fabricmc/loom/util/SourceRemapper.java b/src/main/java/net/fabricmc/loom/util/SourceRemapper.java index 2b2fa943..145bb82f 100644 --- a/src/main/java/net/fabricmc/loom/util/SourceRemapper.java +++ b/src/main/java/net/fabricmc/loom/util/SourceRemapper.java @@ -40,11 +40,12 @@ import org.gradle.api.Project; import org.zeroturnaround.zip.ZipUtil; import net.fabricmc.loom.LoomGradleExtension; +import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; 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 { @@ -184,7 +185,7 @@ public class SourceRemapper { MappingSet mappings = extension.getOrCreateSrcMappingCache(id, () -> { try { - TinyTree m = extension.shouldGenerateSrgTiny() ? mappingsProvider.getMappingsWithSrg() : mappingsProvider.getMappings(); + MemoryMappingTree m = extension.shouldGenerateSrgTiny() ? mappingsProvider.getMappingsWithSrg() : mappingsProvider.getMappings(); project.getLogger().info(":loading " + from + " -> " + to + " source mappings"); return new TinyMappingsReader(m, from, to).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 new file mode 100644 index 00000000..aa295f0c --- /dev/null +++ b/src/main/java/net/fabricmc/loom/util/TinyRemapperHelper.java @@ -0,0 +1,108 @@ +/* + * 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.util; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.util.Map; + +import com.google.common.collect.ImmutableMap; +import org.gradle.api.Project; + +import net.fabricmc.loom.LoomGradleExtension; +import net.fabricmc.mappingio.tree.MappingTree; +import net.fabricmc.tinyremapper.IMappingProvider; +import net.fabricmc.tinyremapper.TinyRemapper; + +/** + * Contains shortcuts to create tiny remappers using the mappings accessibly to the project. + */ +public final class TinyRemapperHelper { + private static final Map<String, String> JSR_TO_JETBRAINS = new ImmutableMap.Builder<String, String>() + .put("javax/annotation/Nullable", "org/jetbrains/annotations/Nullable") + .put("javax/annotation/Nonnull", "org/jetbrains/annotations/NotNull") + .put("javax/annotation/concurrent/Immutable", "org/jetbrains/annotations/Unmodifiable") + .build(); + + private TinyRemapperHelper() { + } + + public static TinyRemapper getTinyRemapper(Project project, String fromM, String toM) throws IOException { + LoomGradleExtension extension = LoomGradleExtension.get(project); + + return TinyRemapper.newRemapper() + .withMappings(create(extension.getMappingsProvider().getMappings(), fromM, toM, true)) + .withMappings(out -> JSR_TO_JETBRAINS.forEach(out::acceptClass)) + .renameInvalidLocals(true) + .rebuildSourceFilenames(true) + .build(); + } + + public static Path[] getMinecraftDependencies(Project project) { + return project.getConfigurations().getByName(Constants.Configurations.MINECRAFT_DEPENDENCIES).getFiles() + .stream().map(File::toPath).toArray(Path[]::new); + } + + private static IMappingProvider.Member memberOf(String className, String memberName, String descriptor) { + return new IMappingProvider.Member(className, memberName, descriptor); + } + + public static IMappingProvider create(MappingTree mappings, String from, String to, boolean remapLocalVariables) { + return (acceptor) -> { + for (MappingTree.ClassMapping classDef : mappings.getClasses()) { + String className = classDef.getName(from); + acceptor.acceptClass(className, classDef.getName(to)); + + for (MappingTree.FieldMapping field : classDef.getFields()) { + acceptor.acceptField(memberOf(className, field.getName(from), field.getDesc(from)), field.getName(to)); + } + + 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 (MappingTree.MethodArgMapping parameter : method.getArgs()) { + String name = parameter.getName(to); + + if (name == null) { + continue; + } + + acceptor.acceptMethodArg(methodIdentifier, parameter.getLvIndex(), name); + } + + for (MappingTree.MethodVarMapping localVariable : method.getVars()) { + acceptor.acceptMethodVar(methodIdentifier, localVariable.getLvIndex(), + localVariable.getStartOpIdx(), localVariable.getLvtRowIndex(), + localVariable.getName(to)); + } + } + } + } + }; + } +} diff --git a/src/main/java/net/fabricmc/loom/util/TinyRemapperMappingsHelper.java b/src/main/java/net/fabricmc/loom/util/TinyRemapperMappingsHelper.java deleted file mode 100644 index f5b9b911..00000000 --- a/src/main/java/net/fabricmc/loom/util/TinyRemapperMappingsHelper.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * This file is part of fabric-loom, licensed under the MIT License (MIT). - * - * Copyright (c) 2016-2019 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.util; - -import dev.architectury.tinyremapper.IMappingProvider; - -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; - -public class TinyRemapperMappingsHelper { - private TinyRemapperMappingsHelper() { } - - private static IMappingProvider.Member memberOf(String className, String memberName, String descriptor) { - return new IMappingProvider.Member(className, memberName, descriptor); - } - - public static IMappingProvider create(TinyTree mappings, String from, String to, boolean remapLocalVariables) { - return (acceptor) -> { - for (ClassDef 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 (MethodDef method : classDef.getMethods()) { - IMappingProvider.Member methodIdentifier = memberOf(className, method.getName(from), method.getDescriptor(from)); - acceptor.acceptMethod(methodIdentifier, method.getName(to)); - - if (remapLocalVariables) { - for (ParameterDef parameter : method.getParameters()) { - acceptor.acceptMethodArg(methodIdentifier, parameter.getLocalVariableIndex(), parameter.getName(to)); - } - - for (LocalVariableDef localVariable : method.getLocalVariables()) { - acceptor.acceptMethodVar(methodIdentifier, localVariable.getLocalVariableIndex(), - localVariable.getLocalVariableStartOffset(), localVariable.getLocalVariableTableIndex(), - localVariable.getName(to)); - } - } - } - } - }; - } -} diff --git a/src/test/groovy/net/fabricmc/loom/test/integration/AccessWidenerTest.groovy b/src/test/groovy/net/fabricmc/loom/test/integration/AccessWidenerTest.groovy index 8fed624d..43c793cb 100644 --- a/src/test/groovy/net/fabricmc/loom/test/integration/AccessWidenerTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/integration/AccessWidenerTest.groovy @@ -25,6 +25,7 @@ package net.fabricmc.loom.test.integration import net.fabricmc.loom.test.util.GradleProjectTestTrait +import org.zeroturnaround.zip.ZipUtil import spock.lang.Specification import spock.lang.Unroll @@ -48,4 +49,20 @@ class AccessWidenerTest extends Specification implements GradleProjectTestTrait String expected() { new File("src/test/resources/accesswidener/expected.accesswidener").text } + + @Unroll + def "transitive accesswidener (gradle #version)"() { + setup: + def gradle = gradleProject(project: "transitiveAccesswidener", version: version) + ZipUtil.pack(new File(gradle.projectDir, "dummyDependency"), new File(gradle.projectDir, "dummy.jar")) + + when: + def result = gradle.run(task: "build") + + then: + result.task(":build").outcome == SUCCESS + + where: + version << STANDARD_TEST_VERSIONS + } } diff --git a/src/test/groovy/net/fabricmc/loom/test/unit/layeredmappings/LayeredMappingSpecBuilderTest.groovy b/src/test/groovy/net/fabricmc/loom/test/unit/layeredmappings/LayeredMappingSpecBuilderTest.groovy index cfcb8a2e..0b583071 100644 --- a/src/test/groovy/net/fabricmc/loom/test/unit/layeredmappings/LayeredMappingSpecBuilderTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/unit/layeredmappings/LayeredMappingSpecBuilderTest.groovy @@ -24,8 +24,9 @@ package net.fabricmc.loom.test.unit.layeredmappings +import net.fabricmc.loom.configuration.providers.mappings.utils.MavenFileSpec import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpec -import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpecBuilder +import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpecBuilderImpl import net.fabricmc.loom.configuration.providers.mappings.intermediary.IntermediaryMappingsSpec import net.fabricmc.loom.configuration.providers.mappings.mojmap.MojangMappingsSpec import net.fabricmc.loom.configuration.providers.mappings.parchment.ParchmentMappingsSpec @@ -60,7 +61,7 @@ class LayeredMappingSpecBuilderTest extends LayeredMappingsSpecification { layers[0].class == IntermediaryMappingsSpec layers[1].class == MojangMappingsSpec layers[2].class == ParchmentMappingsSpec - parchment.mavenNotation() == "I like cake" + (parchment.fileSpec() as MavenFileSpec).dependencyNotation() == "I like cake" parchment.removePrefix() == true } @@ -80,7 +81,7 @@ class LayeredMappingSpecBuilderTest extends LayeredMappingsSpecification { layers[0].class == IntermediaryMappingsSpec layers[1].class == MojangMappingsSpec layers[2].class == ParchmentMappingsSpec - parchment.mavenNotation() == "I like cake" + (parchment.fileSpec() as MavenFileSpec).dependencyNotation() == "I like cake" parchment.removePrefix() == false } @@ -100,17 +101,17 @@ class LayeredMappingSpecBuilderTest extends LayeredMappingsSpecification { layers[0].class == IntermediaryMappingsSpec layers[1].class == MojangMappingsSpec layers[2].class == ParchmentMappingsSpec - parchment.mavenNotation() == "I really like cake" + (parchment.fileSpec() as MavenFileSpec).dependencyNotation() == "I really like cake" parchment.removePrefix() == false } // Gradle does this big of magic behind the scenes - LayeredMappingSpec layered(@DelegatesTo(LayeredMappingSpecBuilder) Closure cl) { + LayeredMappingSpec layered(@DelegatesTo(LayeredMappingSpecBuilderImpl) Closure cl) { return layeredAction(ConfigureUtil.configureUsing(cl)) } - LayeredMappingSpec layeredAction(Action<LayeredMappingSpecBuilder> action) { - LayeredMappingSpecBuilder builder = new LayeredMappingSpecBuilder(null) + LayeredMappingSpec layeredAction(Action<LayeredMappingSpecBuilderImpl> action) { + LayeredMappingSpecBuilderImpl builder = new LayeredMappingSpecBuilderImpl(null) action.execute(builder) return builder.build() } diff --git a/src/test/groovy/net/fabricmc/loom/test/unit/layeredmappings/LayeredMappingsSpecification.groovy b/src/test/groovy/net/fabricmc/loom/test/unit/layeredmappings/LayeredMappingsSpecification.groovy index 10429120..1fba03dc 100644 --- a/src/test/groovy/net/fabricmc/loom/test/unit/layeredmappings/LayeredMappingsSpecification.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/unit/layeredmappings/LayeredMappingsSpecification.groovy @@ -28,18 +28,20 @@ import groovy.transform.CompileStatic import net.fabricmc.loom.configuration.providers.MinecraftProvider import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpec import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingsProcessor -import net.fabricmc.loom.configuration.providers.mappings.MappingContext -import net.fabricmc.loom.configuration.providers.mappings.MappingLayer -import net.fabricmc.loom.configuration.providers.mappings.MappingNamespace +import net.fabricmc.loom.api.mappings.layered.MappingContext +import net.fabricmc.loom.api.mappings.layered.MappingLayer +import net.fabricmc.loom.api.mappings.layered.MappingsNamespace import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider -import net.fabricmc.loom.configuration.providers.mappings.MappingsSpec +import net.fabricmc.loom.api.mappings.layered.spec.MappingsSpec import net.fabricmc.mappingio.adapter.MappingDstNsReorder import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch import net.fabricmc.mappingio.format.Tiny2Writer import net.fabricmc.mappingio.tree.MemoryMappingTree +import org.gradle.api.artifacts.Dependency import org.gradle.api.logging.Logger import spock.lang.Specification +import java.nio.file.Path import java.util.zip.ZipFile abstract class LayeredMappingsSpecification extends Specification implements LayeredMappingsTestConstants { @@ -94,8 +96,8 @@ abstract class LayeredMappingsSpecification extends Specification implements Lay MemoryMappingTree reorder(MemoryMappingTree mappingTree) { def reorderedMappings = new MemoryMappingTree() - def nsReorder = new MappingDstNsReorder(reorderedMappings, Collections.singletonList(MappingNamespace.NAMED.stringValue())) - def nsSwitch = new MappingSourceNsSwitch(nsReorder, MappingNamespace.INTERMEDIARY.stringValue(), true) + def nsReorder = new MappingDstNsReorder(reorderedMappings, Collections.singletonList(MappingsNamespace.NAMED.toString())) + def nsSwitch = new MappingSourceNsSwitch(nsReorder, MappingsNamespace.INTERMEDIARY.toString(), true) mappingTree.accept(nsSwitch) return reorderedMappings } @@ -103,9 +105,14 @@ abstract class LayeredMappingsSpecification extends Specification implements Lay @CompileStatic class TestMappingContext implements MappingContext { @Override - File mavenFile(String mavenNotation) { + Path resolveDependency(Dependency dependency) { + throw new UnsupportedOperationException("TODO") + } + + @Override + Path resolveMavenDependency(String mavenNotation) { assert mavenFiles.containsKey(mavenNotation) - return mavenFiles.get(mavenNotation) + return mavenFiles.get(mavenNotation).toPath() } @Override @@ -119,8 +126,8 @@ abstract class LayeredMappingsSpecification extends Specification implements Lay } @Override - File workingDirectory(String name) { - return new File(tempDir, name) + Path workingDirectory(String name) { + return new File(tempDir, name).toPath() } @Override diff --git a/src/test/groovy/net/fabricmc/loom/test/unit/layeredmappings/ParchmentMappingLayerTest.groovy b/src/test/groovy/net/fabricmc/loom/test/unit/layeredmappings/ParchmentMappingLayerTest.groovy index ac9592cf..73e2a259 100644 --- a/src/test/groovy/net/fabricmc/loom/test/unit/layeredmappings/ParchmentMappingLayerTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/unit/layeredmappings/ParchmentMappingLayerTest.groovy @@ -24,6 +24,7 @@ package net.fabricmc.loom.test.unit.layeredmappings +import net.fabricmc.loom.api.mappings.layered.spec.FileSpec import net.fabricmc.loom.configuration.providers.mappings.intermediary.IntermediaryMappingsSpec import net.fabricmc.loom.configuration.providers.mappings.mojmap.MojangMappingsSpec import net.fabricmc.loom.configuration.providers.mappings.parchment.ParchmentMappingsSpec @@ -38,7 +39,7 @@ class ParchmentMappingLayerTest extends LayeredMappingsSpecification { def mappings = getLayeredMappings( new IntermediaryMappingsSpec(), new MojangMappingsSpec(), - new ParchmentMappingsSpec(PARCHMENT_NOTATION, false) + new ParchmentMappingsSpec(FileSpec.create(PARCHMENT_NOTATION), false) ) def tiny = getTiny(mappings) def reorderedMappings = reorder(mappings) @@ -61,7 +62,7 @@ class ParchmentMappingLayerTest extends LayeredMappingsSpecification { def mappings = getLayeredMappings( new IntermediaryMappingsSpec(), new MojangMappingsSpec(), - new ParchmentMappingsSpec(PARCHMENT_NOTATION, true) + new ParchmentMappingsSpec(FileSpec.create(PARCHMENT_NOTATION), true) ) def tiny = getTiny(mappings) def reorderedMappings = reorder(mappings) diff --git a/src/test/resources/accesswidener/expected.accesswidener b/src/test/resources/accesswidener/expected.accesswidener index 53bf68a7..66f55429 100644 --- a/src/test/resources/accesswidener/expected.accesswidener +++ b/src/test/resources/accesswidener/expected.accesswidener @@ -1,9 +1,6 @@ accessWidener v1 intermediary -accessible class net/minecraft/class_1928$class_5199 -accessible class net/minecraft/class_1735 -accessible class net/minecraft/class_1928$class_4314 -extendable class net/minecraft/class_1928$class_4314 -accessible class net/minecraft/class_5235$class_5238 accessible method net/minecraft/class_1928$class_4314 <init> (Ljava/util/function/Supplier;Ljava/util/function/Function;Ljava/util/function/BiConsumer;Lnet/minecraft/class_1928$class_5199;)V extendable method net/minecraft/class_1928$class_4314 <init> (Ljava/util/function/Supplier;Ljava/util/function/Function;Ljava/util/function/BiConsumer;Lnet/minecraft/class_1928$class_5199;)V +accessible class net/minecraft/class_1928$class_5199 +accessible class net/minecraft/class_5235$class_5238 accessible field net/minecraft/class_1735 field_7873 I diff --git a/src/test/resources/projects/transitiveAccesswidener/build.gradle b/src/test/resources/projects/transitiveAccesswidener/build.gradle new file mode 100644 index 00000000..52f1fc39 --- /dev/null +++ b/src/test/resources/projects/transitiveAccesswidener/build.gradle @@ -0,0 +1,18 @@ +// This is used by a range of tests that append to this file before running the gradle tasks. +// Can be used for tests that require minimal custom setup +plugins { + id 'fabric-loom' + id 'maven-publish' +} + +archivesBaseName = "fabric-example-mod" +version = "1.0.0" +group = "com.example" + +dependencies { + minecraft "com.mojang:minecraft:1.17.1" + mappings "net.fabricmc:yarn:1.17.1+build.59:v2" + modImplementation "net.fabricmc:fabric-loader:0.11.6" + + modImplementation files("dummy.jar") +}
\ No newline at end of file diff --git a/src/test/resources/projects/transitiveAccesswidener/dummyDependency/dummy.accesswidener b/src/test/resources/projects/transitiveAccesswidener/dummyDependency/dummy.accesswidener new file mode 100644 index 00000000..05537ad1 --- /dev/null +++ b/src/test/resources/projects/transitiveAccesswidener/dummyDependency/dummy.accesswidener @@ -0,0 +1,3 @@ +accessWidener v2 intermediary + +transitive-accessible method net/minecraft/class_1972 method_8775 (Ljava/lang/String;)Lnet/minecraft/class_5321;
\ No newline at end of file diff --git a/src/test/resources/projects/transitiveAccesswidener/dummyDependency/fabric.mod.json b/src/test/resources/projects/transitiveAccesswidener/dummyDependency/fabric.mod.json new file mode 100644 index 00000000..b89a826e --- /dev/null +++ b/src/test/resources/projects/transitiveAccesswidener/dummyDependency/fabric.mod.json @@ -0,0 +1,7 @@ +{ + "schemaVersion": 1, + "id": "dummy", + "version": "1", + "name": "Dummy Mod", + "accessWidener" : "dummy.accesswidener" +} diff --git a/src/test/resources/projects/transitiveAccesswidener/src/main/java/ExampleMod.java b/src/test/resources/projects/transitiveAccesswidener/src/main/java/ExampleMod.java new file mode 100644 index 00000000..e5442d2d --- /dev/null +++ b/src/test/resources/projects/transitiveAccesswidener/src/main/java/ExampleMod.java @@ -0,0 +1,13 @@ +import net.minecraft.world.biome.BiomeKeys; +import net.minecraft.world.biome.Biome; +import net.minecraft.util.registry.RegistryKey; + +import net.fabricmc.api.ModInitializer; + +public class ExampleMod implements ModInitializer { + @Override + public void onInitialize() { + // BiomeKeys.register has been made public by a transitive AW + RegistryKey<Biome> biomeRegistryKey = BiomeKeys.register("dummy"); + } +} |