From da4b01427fcbff703b071b0d6f5cd72d1370806a Mon Sep 17 00:00:00 2001 From: modmuss50 Date: Tue, 10 Jan 2023 23:19:21 +0000 Subject: [PATCH] Move access widener jar processor for new processor API. (#787) --- .../loom/api/LoomGradleExtensionAPI.java | 2 +- .../processor/MappingProcessorContext.java | 7 +- .../loom/api/processor/ProcessorContext.java | 5 +- .../configuration/CompileConfiguration.java | 16 +- .../accesswidener/AccessWidenerEntry.java | 46 ++++ .../AccessWidenerJarProcessor.java | 145 ++++++++---- .../AccessWidenerTransformer.java | 17 +- .../LocalAccessWidenerEntry.java | 55 +++++ .../accesswidener/ModAccessWidenerEntry.java | 95 ++++++++ .../TransitiveAccessWidenerJarProcessor.java | 221 ------------------ ...nsitiveAccessWidenerMappingsProcessor.java | 54 +++-- .../InterfaceInjectionProcessor.java | 11 +- .../processors/ContextImplHelper.java | 57 +++++ .../MappingProcessorContextImpl.java | 38 +++ .../processors/ProcessorContextImpl.java | 23 +- .../processors/SpecContextImpl.java | 36 +-- .../extension/LoomGradleExtensionApiImpl.java | 4 - .../loom/task/GenerateSourcesTask.java | 19 +- .../fabricmc/loom/util/DeprecationHelper.java | 10 +- .../net/fabricmc/loom/util/LazyCloseable.java | 58 +++++ .../loom/util/fmj/FabricModJsonHelpers.java | 62 +++++ .../loom/util/fmj/FabricModJsonSource.java | 6 +- 22 files changed, 598 insertions(+), 389 deletions(-) create mode 100644 src/main/java/net/fabricmc/loom/configuration/accesswidener/AccessWidenerEntry.java create mode 100644 src/main/java/net/fabricmc/loom/configuration/accesswidener/LocalAccessWidenerEntry.java create mode 100644 src/main/java/net/fabricmc/loom/configuration/accesswidener/ModAccessWidenerEntry.java delete mode 100644 src/main/java/net/fabricmc/loom/configuration/accesswidener/TransitiveAccessWidenerJarProcessor.java create mode 100644 src/main/java/net/fabricmc/loom/configuration/processors/ContextImplHelper.java create mode 100644 src/main/java/net/fabricmc/loom/configuration/processors/MappingProcessorContextImpl.java create mode 100644 src/main/java/net/fabricmc/loom/util/LazyCloseable.java create mode 100644 src/main/java/net/fabricmc/loom/util/fmj/FabricModJsonHelpers.java diff --git a/src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java b/src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java index 432b5dc9..45587d96 100644 --- a/src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java +++ b/src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java @@ -1,7 +1,7 @@ /* * This file is part of fabric-loom, licensed under the MIT License (MIT). * - * Copyright (c) 2021-2022 FabricMC + * Copyright (c) 2021-2023 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 diff --git a/src/main/java/net/fabricmc/loom/api/processor/MappingProcessorContext.java b/src/main/java/net/fabricmc/loom/api/processor/MappingProcessorContext.java index 3c4aad66..ff2d3fca 100644 --- a/src/main/java/net/fabricmc/loom/api/processor/MappingProcessorContext.java +++ b/src/main/java/net/fabricmc/loom/api/processor/MappingProcessorContext.java @@ -1,7 +1,7 @@ /* * This file is part of fabric-loom, licensed under the MIT License (MIT). * - * Copyright (c) 2022 FabricMC + * Copyright (c) 2022-2023 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 @@ -24,5 +24,10 @@ package net.fabricmc.loom.api.processor; +import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; +import net.fabricmc.loom.util.LazyCloseable; +import net.fabricmc.tinyremapper.TinyRemapper; + public interface MappingProcessorContext { + LazyCloseable createRemapper(MappingsNamespace from, MappingsNamespace to); } diff --git a/src/main/java/net/fabricmc/loom/api/processor/ProcessorContext.java b/src/main/java/net/fabricmc/loom/api/processor/ProcessorContext.java index 5f934e65..a5152f9b 100644 --- a/src/main/java/net/fabricmc/loom/api/processor/ProcessorContext.java +++ b/src/main/java/net/fabricmc/loom/api/processor/ProcessorContext.java @@ -1,7 +1,7 @@ /* * This file is part of fabric-loom, licensed under the MIT License (MIT). * - * Copyright (c) 2022 FabricMC + * Copyright (c) 2022-2023 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 @@ -26,6 +26,7 @@ package net.fabricmc.loom.api.processor; import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; import net.fabricmc.loom.configuration.providers.minecraft.MinecraftJarConfiguration; +import net.fabricmc.loom.util.LazyCloseable; import net.fabricmc.tinyremapper.TinyRemapper; public interface ProcessorContext { @@ -37,5 +38,5 @@ public interface ProcessorContext { boolean includesServer(); - TinyRemapper createRemapper(MappingsNamespace from, MappingsNamespace to); + LazyCloseable createRemapper(MappingsNamespace from, MappingsNamespace to); } diff --git a/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java b/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java index 7cdb5846..2548d62e 100644 --- a/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java +++ b/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java @@ -1,7 +1,7 @@ /* * This file is part of fabric-loom, licensed under the MIT License (MIT). * - * Copyright (c) 2016-2022 FabricMC + * Copyright (c) 2016-2023 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 @@ -49,7 +49,6 @@ import net.fabricmc.loom.build.mixin.JavaApInvoker; import net.fabricmc.loom.build.mixin.KaptApInvoker; import net.fabricmc.loom.build.mixin.ScalaApInvoker; import net.fabricmc.loom.configuration.accesswidener.AccessWidenerJarProcessor; -import net.fabricmc.loom.configuration.accesswidener.TransitiveAccessWidenerJarProcessor; import net.fabricmc.loom.configuration.ifaceinject.InterfaceInjectionProcessor; import net.fabricmc.loom.configuration.processors.MinecraftJarProcessorManager; import net.fabricmc.loom.configuration.processors.ModJavadocProcessor; @@ -221,17 +220,8 @@ public final class CompileConfiguration { private static void registerGameProcessors(ConfigContext configContext) { final LoomGradleExtension extension = configContext.extension(); - if (extension.getAccessWidenerPath().isPresent()) { - extension.getGameJarProcessors().add(new AccessWidenerJarProcessor(configContext)); - } - - if (extension.getEnableTransitiveAccessWideners().get()) { - TransitiveAccessWidenerJarProcessor transitiveAccessWidenerJarProcessor = new TransitiveAccessWidenerJarProcessor(configContext); - - if (!transitiveAccessWidenerJarProcessor.isEmpty()) { - extension.getGameJarProcessors().add(transitiveAccessWidenerJarProcessor); - } - } + final boolean enableTransitiveAccessWideners = extension.getEnableTransitiveAccessWideners().get(); + extension.addMinecraftJarProcessor(AccessWidenerJarProcessor.class, "fabric-loom:access-widener", enableTransitiveAccessWideners, extension.getAccessWidenerPath()); if (extension.getEnableModProvidedJavadoc().get()) { extension.addMinecraftJarProcessor(ModJavadocProcessor.class, "fabric-loom:mod-javadoc"); diff --git a/src/main/java/net/fabricmc/loom/configuration/accesswidener/AccessWidenerEntry.java b/src/main/java/net/fabricmc/loom/configuration/accesswidener/AccessWidenerEntry.java new file mode 100644 index 00000000..7dd2d2d1 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/accesswidener/AccessWidenerEntry.java @@ -0,0 +1,46 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2023 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 org.jetbrains.annotations.Nullable; + +import net.fabricmc.accesswidener.AccessWidenerVisitor; +import net.fabricmc.loom.util.LazyCloseable; +import net.fabricmc.loom.util.fmj.ModEnvironment; +import net.fabricmc.tinyremapper.TinyRemapper; + +public interface AccessWidenerEntry { + ModEnvironment environment(); + + /** + * @return The mod id to be used in {@link TransitiveAccessWidenerMappingsProcessor} or null when this entry does not contain transitive entries. + */ + @Nullable + String mappingId(); + + void read(AccessWidenerVisitor visitor, LazyCloseable remapper) throws IOException; +} 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 daacaf4b..b56cb9d5 100644 --- a/src/main/java/net/fabricmc/loom/configuration/accesswidener/AccessWidenerJarProcessor.java +++ b/src/main/java/net/fabricmc/loom/configuration/accesswidener/AccessWidenerJarProcessor.java @@ -1,7 +1,7 @@ /* * This file is part of fabric-loom, licensed under the MIT License (MIT). * - * Copyright (c) 2020-2021 FabricMC + * Copyright (c) 2023 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 @@ -24,73 +24,118 @@ package net.fabricmc.loom.configuration.accesswidener; -import java.io.File; import java.io.IOException; -import java.io.UncheckedIOException; -import java.nio.file.Files; -import java.nio.file.NoSuchFileException; import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; -import com.google.common.hash.Hashing; -import org.gradle.api.Project; +import javax.inject.Inject; + +import org.gradle.api.file.RegularFileProperty; +import org.jetbrains.annotations.Nullable; import net.fabricmc.accesswidener.AccessWidener; -import net.fabricmc.accesswidener.AccessWidenerReader; -import net.fabricmc.loom.LoomGradleExtension; -import net.fabricmc.loom.configuration.ConfigContext; -import net.fabricmc.loom.configuration.processors.JarProcessor; -import net.fabricmc.loom.util.Checksum; -import net.fabricmc.loom.util.ZipUtils; +import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; +import net.fabricmc.loom.api.processor.MinecraftJarProcessor; +import net.fabricmc.loom.api.processor.ProcessorContext; +import net.fabricmc.loom.api.processor.SpecContext; +import net.fabricmc.loom.util.LazyCloseable; +import net.fabricmc.loom.util.fmj.FabricModJson; +import net.fabricmc.loom.util.fmj.ModEnvironment; +import net.fabricmc.tinyremapper.TinyRemapper; -public class AccessWidenerJarProcessor implements JarProcessor { - // Filename used to store hash of input access widener in processed jar file - private static final String HASH_FILENAME = "aw.sha256"; - 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 class AccessWidenerJarProcessor implements MinecraftJarProcessor { + private final String name; + private final boolean includeTransitive; + private final RegularFileProperty localAccessWidenerProperty; - public AccessWidenerJarProcessor(ConfigContext configContext) { - this.project = configContext.project(); + @Inject + public AccessWidenerJarProcessor(String name, boolean includeTransitive, RegularFileProperty localAccessWidenerProperty) { + this.name = name; + this.includeTransitive = includeTransitive; + this.localAccessWidenerProperty = localAccessWidenerProperty; } @Override - public String getId() { - return "loom:access_widener:" + Checksum.toHex(inputHash); - } + public @Nullable AccessWidenerJarProcessor.Spec buildSpec(SpecContext context) { + List accessWideners = new ArrayList<>(); - @Override - public void setup() { - 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 - // The mod's own access widener file - byte[] modAccessWidener; - - 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 access widener: " + awPath); + if (localAccessWidenerProperty.isPresent()) { + // Add the access widener specified in the extension + accessWideners.add(new LocalAccessWidenerEntry(localAccessWidenerProperty.get().getAsFile().toPath())); } - AccessWidenerReader reader = new AccessWidenerReader(accessWidener); - reader.read(modAccessWidener); + /* Uncomment to read all access wideners from local mods. - inputHash = Hashing.sha256().hashBytes(modAccessWidener).asBytes(); + for (FabricModJson fabricModJson : context.localMods()) { + accessWideners.addAll(ModAccessWidenerEntry.readAll(fabricModJson, false)); + } + + */ + + if (includeTransitive) { + for (FabricModJson fabricModJson : context.modDependencies()) { + accessWideners.addAll(ModAccessWidenerEntry.readAll(fabricModJson, true)); + } + } + + if (accessWideners.isEmpty()) { + return null; + } + + return new Spec(Collections.unmodifiableList(accessWideners)); } @Override - public void process(File file) { - AccessWidenerTransformer applier = new AccessWidenerTransformer(project.getLogger(), accessWidener); - applier.apply(file); + public String getName() { + return name; + } - try { - ZipUtils.add(file.toPath(), HASH_FILENAME, inputHash); - } catch (IOException e) { - throw new UncheckedIOException("Failed to write aw jar hash", e); + public record Spec(List accessWideners) implements MinecraftJarProcessor.Spec { + List accessWidenersForContext(ProcessorContext context) { + return accessWideners.stream() + .filter(entry -> isSupported(entry.environment(), context)) + .toList(); } + + private static boolean isSupported(ModEnvironment modEnvironment, ProcessorContext context) { + if (context.isMerged()) { + // All envs are supported wth a merged jar + return true; + } + + if (context.includesClient() && modEnvironment.isClient()) { + return true; + } + + if (context.includesServer() && modEnvironment.isServer()) { + return true; + } + + // Universal supports all jars + return modEnvironment == ModEnvironment.UNIVERSAL; + } + } + + @Override + public void processJar(Path jar, AccessWidenerJarProcessor.Spec spec, ProcessorContext context) throws IOException { + final List accessWideners = spec.accessWidenersForContext(context); + + final var accessWidener = new AccessWidener(); + + try (LazyCloseable remapper = context.createRemapper(MappingsNamespace.INTERMEDIARY, MappingsNamespace.NAMED)) { + for (AccessWidenerEntry widener : accessWideners) { + widener.read(accessWidener, remapper); + } + } + + AccessWidenerTransformer transformer = new AccessWidenerTransformer(accessWidener); + transformer.apply(jar); + } + + @Override + public @Nullable MappingsProcessor processMappings() { + return TransitiveAccessWidenerMappingsProcessor.INSTANCE; } } diff --git a/src/main/java/net/fabricmc/loom/configuration/accesswidener/AccessWidenerTransformer.java b/src/main/java/net/fabricmc/loom/configuration/accesswidener/AccessWidenerTransformer.java index 69376e0a..0eb195af 100644 --- a/src/main/java/net/fabricmc/loom/configuration/accesswidener/AccessWidenerTransformer.java +++ b/src/main/java/net/fabricmc/loom/configuration/accesswidener/AccessWidenerTransformer.java @@ -24,17 +24,18 @@ package net.fabricmc.loom.configuration.accesswidener; -import java.io.File; import java.io.IOException; import java.io.UncheckedIOException; +import java.nio.file.Path; import java.util.List; import java.util.Set; import java.util.stream.Collectors; -import org.gradle.api.logging.Logger; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassWriter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import net.fabricmc.accesswidener.AccessWidener; import net.fabricmc.accesswidener.AccessWidenerClassVisitor; @@ -43,20 +44,20 @@ import net.fabricmc.loom.util.Pair; import net.fabricmc.loom.util.ZipUtils; final class AccessWidenerTransformer { - private final Logger logger; + private static final Logger LOGGER = LoggerFactory.getLogger(AccessWidenerTransformer.class); + private final AccessWidener accessWidener; - AccessWidenerTransformer(Logger logger, AccessWidener accessWidener) { - this.logger = logger; + AccessWidenerTransformer(AccessWidener accessWidener) { this.accessWidener = accessWidener; } /** * Apply the rules from an access-widener to the given jar or zip file. */ - void apply(File jarFile) { + void apply(Path jarFile) { try { - ZipUtils.transform(jarFile.toPath(), getTransformers(accessWidener.getTargets())); + ZipUtils.transform(jarFile, getTransformers(accessWidener.getTargets())); } catch (IOException e) { throw new UncheckedIOException("Failed to apply access wideners to %s".formatted(jarFile), e); } @@ -74,7 +75,7 @@ final class AccessWidenerTransformer { ClassWriter writer = new ClassWriter(0); ClassVisitor classVisitor = AccessWidenerClassVisitor.createClassVisitor(Constants.ASM_VERSION, writer, accessWidener); - logger.info("Applying access widener to " + className); + LOGGER.debug("Applying access widener to " + className); reader.accept(classVisitor, 0); return writer.toByteArray(); diff --git a/src/main/java/net/fabricmc/loom/configuration/accesswidener/LocalAccessWidenerEntry.java b/src/main/java/net/fabricmc/loom/configuration/accesswidener/LocalAccessWidenerEntry.java new file mode 100644 index 00000000..01546046 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/accesswidener/LocalAccessWidenerEntry.java @@ -0,0 +1,55 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2023 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.nio.file.Files; +import java.nio.file.Path; + +import org.jetbrains.annotations.Nullable; + +import net.fabricmc.accesswidener.AccessWidenerReader; +import net.fabricmc.accesswidener.AccessWidenerVisitor; +import net.fabricmc.loom.util.LazyCloseable; +import net.fabricmc.loom.util.fmj.ModEnvironment; +import net.fabricmc.tinyremapper.TinyRemapper; + +public record LocalAccessWidenerEntry(Path path) implements AccessWidenerEntry { + @Override + public void read(AccessWidenerVisitor visitor, LazyCloseable remapper) throws IOException { + var reader = new AccessWidenerReader(visitor); + reader.read(Files.readAllBytes(path)); + } + + @Override + public ModEnvironment environment() { + return ModEnvironment.UNIVERSAL; + } + + @Override + public @Nullable String mappingId() { + return null; + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/accesswidener/ModAccessWidenerEntry.java b/src/main/java/net/fabricmc/loom/configuration/accesswidener/ModAccessWidenerEntry.java new file mode 100644 index 00000000..14e84872 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/accesswidener/ModAccessWidenerEntry.java @@ -0,0 +1,95 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2023 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.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.jetbrains.annotations.Nullable; + +import net.fabricmc.accesswidener.AccessWidenerReader; +import net.fabricmc.accesswidener.AccessWidenerRemapper; +import net.fabricmc.accesswidener.AccessWidenerVisitor; +import net.fabricmc.accesswidener.TransitiveOnlyFilter; +import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; +import net.fabricmc.loom.util.LazyCloseable; +import net.fabricmc.loom.util.fmj.FabricModJson; +import net.fabricmc.loom.util.fmj.ModEnvironment; +import net.fabricmc.tinyremapper.TinyRemapper; + +/** + * {@link AccessWidenerEntry} implementation for a {@link FabricModJson}. + */ +public record ModAccessWidenerEntry(FabricModJson mod, String path, ModEnvironment environment, boolean transitiveOnly) implements AccessWidenerEntry { + public static List readAll(FabricModJson modJson, boolean transitiveOnly) { + var entries = new ArrayList(); + + for (Map.Entry entry : modJson.getClassTweakers().entrySet()) { + entries.add(new ModAccessWidenerEntry(modJson, entry.getKey(), entry.getValue(), transitiveOnly)); + } + + return Collections.unmodifiableList(entries); + } + + @Override + public @Nullable String mappingId() { + return transitiveOnly ? mod.getId() : null; + } + + @Override + public void read(AccessWidenerVisitor visitor, LazyCloseable remapper) throws IOException { + if (transitiveOnly) { + // Filter for only transitive rules + visitor = new TransitiveOnlyFilter(visitor); + } + + final byte[] data = readRaw(); + final AccessWidenerReader.Header header = AccessWidenerReader.readHeader(data); + + if (!header.getNamespace().equals(MappingsNamespace.NAMED.toString())) { + // Remap the AW if needed + visitor = getRemapper(visitor, remapper.get()); + } + + var reader = new AccessWidenerReader(visitor); + reader.read(data); + } + + private static AccessWidenerRemapper getRemapper(AccessWidenerVisitor visitor, TinyRemapper tinyRemapper) { + return new AccessWidenerRemapper( + visitor, + tinyRemapper.getEnvironment().getRemapper(), + MappingsNamespace.INTERMEDIARY.toString(), + MappingsNamespace.NAMED.toString() + ); + } + + private byte[] readRaw() throws IOException { + return mod.getSource().read(path); + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/accesswidener/TransitiveAccessWidenerJarProcessor.java b/src/main/java/net/fabricmc/loom/configuration/accesswidener/TransitiveAccessWidenerJarProcessor.java deleted file mode 100644 index 21b1fd74..00000000 --- a/src/main/java/net/fabricmc/loom/configuration/accesswidener/TransitiveAccessWidenerJarProcessor.java +++ /dev/null @@ -1,221 +0,0 @@ -/* - * 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.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import com.google.common.base.Preconditions; -import org.gradle.api.Project; -import org.gradle.api.artifacts.Configuration; -import org.gradle.api.artifacts.FileCollectionDependency; -import org.gradle.api.artifacts.ResolvedArtifact; -import org.gradle.api.file.FileCollection; - -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.RemapConfigurationSettings; -import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; -import net.fabricmc.loom.configuration.ConfigContext; -import net.fabricmc.loom.configuration.processors.JarProcessor; -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 ConfigContext configContext; - private final Project project; - private final LoomGradleExtension extension; - - private final List transitiveAccessWideners; - - public TransitiveAccessWidenerJarProcessor(ConfigContext configContext) { - this.configContext = configContext; - this.project = configContext.project(); - this.extension = configContext.extension(); - - 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 getTransitiveAccessWideners() { - final List accessWideners = new ArrayList<>(); - final Set possibleModJars = new HashSet<>(); - - // Only apply global AWs from mods that are part of the compile classpath - for (RemapConfigurationSettings entry : extension.getCompileRemapConfigurations()) { - final Configuration configuration = entry.getSourceConfiguration().get(); - - // Based off the logic in ModCompileRemapper. - for (ResolvedArtifact artifact : configuration.getResolvedConfiguration().getResolvedArtifacts()) { - possibleModJars.add(artifact.getFile().toPath()); - } - - for (FileCollectionDependency dependency : configuration.getAllDependencies().withType(FileCollectionDependency.class)) { - FileCollection files = dependency.getFiles(); - - for (File artifact : files) { - possibleModJars.add(artifact.toPath()); - } - } - } - - for (Path path : possibleModJars) { - if (!Files.exists(path)) { - project.getLogger().debug("Could not find transitive access widener in {} as it does not exist", path.toAbsolutePath()); - continue; - } - - AccessWidenerFile accessWidener = AccessWidenerFile.fromModJar(path); - - 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.getEnvironment().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, configContext.serviceManager(), "intermediary", "named"); - - tinyRemapper.readClassPath(TinyRemapperHelper.getMinecraftDependencies(project)); - - for (Path minecraftJar : extension.getMinecraftJars(MappingsNamespace.INTERMEDIARY)) { - tinyRemapper.readClassPath(minecraftJar); - } - - return tinyRemapper; - } catch (IOException e) { - throw new RuntimeException("Failed to create tiny remapper for intermediary->named", e); - } - } - - 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 index da82d8f1..e7197b7b 100644 --- a/src/main/java/net/fabricmc/loom/configuration/accesswidener/TransitiveAccessWidenerMappingsProcessor.java +++ b/src/main/java/net/fabricmc/loom/configuration/accesswidener/TransitiveAccessWidenerMappingsProcessor.java @@ -1,7 +1,7 @@ /* * This file is part of fabric-loom, licensed under the MIT License (MIT). * - * Copyright (c) 2021-2022 FabricMC + * Copyright (c) 2021-2023 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 @@ -24,25 +24,34 @@ package net.fabricmc.loom.configuration.accesswidener; +import java.io.IOException; +import java.io.UncheckedIOException; import java.util.List; -import org.gradle.api.Project; -import org.gradle.api.logging.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import net.fabricmc.accesswidener.AccessWidenerReader; 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.task.GenerateSourcesTask; +import net.fabricmc.loom.api.processor.MappingProcessorContext; +import net.fabricmc.loom.api.processor.MinecraftJarProcessor; +import net.fabricmc.loom.util.LazyCloseable; import net.fabricmc.mappingio.tree.MappingTree; import net.fabricmc.mappingio.tree.MemoryMappingTree; +import net.fabricmc.tinyremapper.TinyRemapper; + +public final class TransitiveAccessWidenerMappingsProcessor implements MinecraftJarProcessor.MappingsProcessor { + public static final TransitiveAccessWidenerMappingsProcessor INSTANCE = new TransitiveAccessWidenerMappingsProcessor(); + + private TransitiveAccessWidenerMappingsProcessor() { + } -public record TransitiveAccessWidenerMappingsProcessor(Project project) implements GenerateSourcesTask.MappingsProcessor { @Override - public boolean transform(MemoryMappingTree mappings) { - final LoomGradleExtension extension = LoomGradleExtension.get(project); - List accessWideners = extension.getTransitiveAccessWideners(); + public boolean transform(MemoryMappingTree mappings, AccessWidenerJarProcessor.Spec spec, MappingProcessorContext context) { + final List accessWideners = spec.accessWideners().stream() + .filter(entry -> entry.mappingId() != null) + .toList(); if (accessWideners.isEmpty()) { return false; @@ -52,22 +61,27 @@ public record TransitiveAccessWidenerMappingsProcessor(Project project) implemen throw new IllegalStateException("Mapping tree must have intermediary src mappings not " + mappings.getSrcNamespace()); } - for (AccessWidenerFile accessWidener : accessWideners) { - MappingCommentVisitor mappingCommentVisitor = new MappingCommentVisitor(accessWidener.modId(), mappings, project.getLogger()); - AccessWidenerReader accessWidenerReader = new AccessWidenerReader(new TransitiveOnlyFilter(mappingCommentVisitor)); - accessWidenerReader.read(accessWidener.content()); + try (LazyCloseable remapper = context.createRemapper(MappingsNamespace.INTERMEDIARY, MappingsNamespace.NAMED)) { + for (AccessWidenerEntry accessWidener : accessWideners) { + var visitor = new MappingCommentVisitor(accessWidener.mappingId(), mappings); + accessWidener.read(visitor, remapper); + } + } catch (IOException e) { + throw new UncheckedIOException("Failed to transform access widener mappings", e); } return true; } - private record MappingCommentVisitor(String modId, MemoryMappingTree mappingTree, Logger logger) implements AccessWidenerVisitor { + private record MappingCommentVisitor(String modId, MemoryMappingTree mappingTree) implements AccessWidenerVisitor { + private static final Logger LOGGER = LoggerFactory.getLogger(MappingCommentVisitor.class); + @Override public void visitClass(String name, AccessWidenerReader.AccessType access, boolean transitive) { MappingTree.ClassMapping classMapping = mappingTree.getClass(name); if (classMapping == null) { - logger.info("Failed to find class ({}) to mark access widened by mod ({})", name, modId()); + LOGGER.info("Failed to find class ({}) to mark access widened by mod ({})", name, modId()); return; } @@ -82,14 +96,14 @@ public record TransitiveAccessWidenerMappingsProcessor(Project project) implemen MappingTree.ClassMapping classMapping = mappingTree.getClass(owner); if (classMapping == null) { - logger.info("Failed to find class ({}) to mark access widened by mod ({})", owner, modId()); + LOGGER.info("Failed to find class ({}) to mark access widened by mod ({})", owner, modId()); return; } MappingTree.MethodMapping methodMapping = classMapping.getMethod(name, descriptor); if (methodMapping == null) { - logger.info("Failed to find method ({}) in ({}) to mark access widened by mod ({})", name, owner, modId()); + LOGGER.info("Failed to find method ({}) in ({}) to mark access widened by mod ({})", name, owner, modId()); return; } @@ -104,14 +118,14 @@ public record TransitiveAccessWidenerMappingsProcessor(Project project) implemen MappingTree.ClassMapping classMapping = mappingTree.getClass(owner); if (classMapping == null) { - logger.info("Failed to find class ({}) to mark access widened by mod ({})", name, modId()); + LOGGER.info("Failed to find class ({}) to mark access widened by mod ({})", name, modId()); return; } MappingTree.FieldMapping fieldMapping = classMapping.getField(name, descriptor); if (fieldMapping == null) { - logger.info("Failed to find field ({}) in ({}) to mark access widened by mod ({})", name, owner, modId()); + LOGGER.info("Failed to find field ({}) in ({}) to mark access widened by mod ({})", name, owner, modId()); return; } diff --git a/src/main/java/net/fabricmc/loom/configuration/ifaceinject/InterfaceInjectionProcessor.java b/src/main/java/net/fabricmc/loom/configuration/ifaceinject/InterfaceInjectionProcessor.java index 585e2c1f..77ba7403 100644 --- a/src/main/java/net/fabricmc/loom/configuration/ifaceinject/InterfaceInjectionProcessor.java +++ b/src/main/java/net/fabricmc/loom/configuration/ifaceinject/InterfaceInjectionProcessor.java @@ -56,7 +56,6 @@ import net.fabricmc.loom.util.Pair; import net.fabricmc.loom.util.ZipUtils; import net.fabricmc.loom.util.fmj.FabricModJson; import net.fabricmc.mappingio.tree.MappingTree; -import net.fabricmc.tinyremapper.TinyRemapper; public abstract class InterfaceInjectionProcessor implements MinecraftJarProcessor { private static final Logger LOGGER = LoggerFactory.getLogger(InterfaceInjectionProcessor.class); @@ -99,17 +98,15 @@ public abstract class InterfaceInjectionProcessor implements MinecraftJarProcess @Override public void processJar(Path jar, Spec spec, ProcessorContext context) throws IOException { - // Remap from intermediary->named - final TinyRemapper tinyRemapper = context.createRemapper(MappingsNamespace.INTERMEDIARY, MappingsNamespace.NAMED); - final Remapper remapper = tinyRemapper.getEnvironment().getRemapper(); final List remappedInjectedInterfaces; - try { + // Remap from intermediary->named + try (var tinyRemapper = context.createRemapper(MappingsNamespace.INTERMEDIARY, MappingsNamespace.NAMED)) { + final Remapper remapper = tinyRemapper.get().getEnvironment().getRemapper(); + remappedInjectedInterfaces = spec.injectedInterfaces().stream() .map(injectedInterface -> remap(injectedInterface, remapper)) .toList(); - } finally { - tinyRemapper.finish(); } try { diff --git a/src/main/java/net/fabricmc/loom/configuration/processors/ContextImplHelper.java b/src/main/java/net/fabricmc/loom/configuration/processors/ContextImplHelper.java new file mode 100644 index 00000000..37fe9c26 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/processors/ContextImplHelper.java @@ -0,0 +1,57 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2022-2023 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.processors; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.file.Path; + +import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; +import net.fabricmc.loom.configuration.ConfigContext; +import net.fabricmc.loom.util.LazyCloseable; +import net.fabricmc.loom.util.TinyRemapperHelper; +import net.fabricmc.tinyremapper.TinyRemapper; + +public final class ContextImplHelper { + private ContextImplHelper() { + } + + public static LazyCloseable createRemapper(ConfigContext configContext, MappingsNamespace from, MappingsNamespace to) { + return new LazyCloseable<>(() -> { + try { + TinyRemapper tinyRemapper = TinyRemapperHelper.getTinyRemapper(configContext.project(), configContext.serviceManager(), from.toString(), to.toString()); + tinyRemapper.readClassPath(TinyRemapperHelper.getMinecraftDependencies(configContext.project())); + + for (Path minecraftJar : configContext.extension().getMinecraftJars(MappingsNamespace.INTERMEDIARY)) { + tinyRemapper.readClassPath(minecraftJar); + } + + return tinyRemapper; + } catch (IOException e) { + throw new UncheckedIOException("Failed to create tiny remapper", e); + } + }, TinyRemapper::finish); + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/processors/MappingProcessorContextImpl.java b/src/main/java/net/fabricmc/loom/configuration/processors/MappingProcessorContextImpl.java new file mode 100644 index 00000000..6a1ba3a5 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/processors/MappingProcessorContextImpl.java @@ -0,0 +1,38 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2022-2023 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.processors; + +import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; +import net.fabricmc.loom.api.processor.MappingProcessorContext; +import net.fabricmc.loom.configuration.ConfigContext; +import net.fabricmc.loom.util.LazyCloseable; +import net.fabricmc.tinyremapper.TinyRemapper; + +public record MappingProcessorContextImpl(ConfigContext configContext) implements MappingProcessorContext { + @Override + public LazyCloseable createRemapper(MappingsNamespace from, MappingsNamespace to) { + return ContextImplHelper.createRemapper(configContext, from, to); + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/processors/ProcessorContextImpl.java b/src/main/java/net/fabricmc/loom/configuration/processors/ProcessorContextImpl.java index f8a2e116..15f2d3ca 100644 --- a/src/main/java/net/fabricmc/loom/configuration/processors/ProcessorContextImpl.java +++ b/src/main/java/net/fabricmc/loom/configuration/processors/ProcessorContextImpl.java @@ -1,7 +1,7 @@ /* * This file is part of fabric-loom, licensed under the MIT License (MIT). * - * Copyright (c) 2022 FabricMC + * Copyright (c) 2022-2023 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 @@ -24,16 +24,12 @@ package net.fabricmc.loom.configuration.processors; -import java.io.IOException; -import java.io.UncheckedIOException; -import java.nio.file.Path; - import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; import net.fabricmc.loom.api.processor.ProcessorContext; import net.fabricmc.loom.configuration.ConfigContext; import net.fabricmc.loom.configuration.providers.minecraft.MinecraftJar; import net.fabricmc.loom.configuration.providers.minecraft.MinecraftJarConfiguration; -import net.fabricmc.loom.util.TinyRemapperHelper; +import net.fabricmc.loom.util.LazyCloseable; import net.fabricmc.tinyremapper.TinyRemapper; public record ProcessorContextImpl(ConfigContext configContext, MinecraftJar minecraftJar) implements ProcessorContext { @@ -58,18 +54,7 @@ public record ProcessorContextImpl(ConfigContext configContext, MinecraftJar min } @Override - public TinyRemapper createRemapper(MappingsNamespace from, MappingsNamespace to) { - try { - TinyRemapper tinyRemapper = TinyRemapperHelper.getTinyRemapper(configContext().project(), configContext().serviceManager(), from.toString(), to.toString()); - tinyRemapper.readClassPath(TinyRemapperHelper.getMinecraftDependencies(configContext.project())); - - for (Path minecraftJar : configContext.extension().getMinecraftJars(MappingsNamespace.INTERMEDIARY)) { - tinyRemapper.readClassPath(minecraftJar); - } - - return tinyRemapper; - } catch (IOException e) { - throw new UncheckedIOException("Failed to create tiny remapper", e); - } + public LazyCloseable createRemapper(MappingsNamespace from, MappingsNamespace to) { + return ContextImplHelper.createRemapper(configContext, from, to); } } diff --git a/src/main/java/net/fabricmc/loom/configuration/processors/SpecContextImpl.java b/src/main/java/net/fabricmc/loom/configuration/processors/SpecContextImpl.java index 1ad69b72..cc23c801 100644 --- a/src/main/java/net/fabricmc/loom/configuration/processors/SpecContextImpl.java +++ b/src/main/java/net/fabricmc/loom/configuration/processors/SpecContextImpl.java @@ -1,7 +1,7 @@ /* * This file is part of fabric-loom, licensed under the MIT License (MIT). * - * Copyright (c) 2022 FabricMC + * Copyright (c) 2022-2023 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 @@ -25,8 +25,6 @@ package net.fabricmc.loom.configuration.processors; import java.io.File; -import java.io.IOException; -import java.io.UncheckedIOException; import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; @@ -41,7 +39,6 @@ import org.gradle.api.Project; import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.ProjectDependency; import org.gradle.api.plugins.JavaPlugin; -import org.gradle.api.tasks.SourceSet; import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.api.RemapConfigurationSettings; @@ -49,8 +46,8 @@ import net.fabricmc.loom.api.processor.SpecContext; import net.fabricmc.loom.util.Constants; import net.fabricmc.loom.util.fmj.FabricModJson; import net.fabricmc.loom.util.fmj.FabricModJsonFactory; +import net.fabricmc.loom.util.fmj.FabricModJsonHelpers; import net.fabricmc.loom.util.gradle.GradleUtils; -import net.fabricmc.loom.util.gradle.SourceSetHelper; /** * @param modDependencies External mods that are depended on @@ -59,7 +56,7 @@ import net.fabricmc.loom.util.gradle.SourceSetHelper; */ public record SpecContextImpl(List modDependencies, List localMods, List compileRuntimeMods) implements SpecContext { public static SpecContextImpl create(Project project) { - return new SpecContextImpl(getDependentMods(project), getModsInProject(project), getCompileRuntimeMods(project)); + return new SpecContextImpl(getDependentMods(project), FabricModJsonHelpers.getModsInProject(project), getCompileRuntimeMods(project)); } // Reruns a list of mods found on both the compile and/or runtime classpaths @@ -82,7 +79,7 @@ public record SpecContextImpl(List modDependencies, List modDependencies, List getModsInProject(Project project) { - final LoomGradleExtension extension = LoomGradleExtension.get(project); - var sourceSets = new ArrayList(); - sourceSets.add(SourceSetHelper.getMainSourceSet(project)); - - if (extension.areEnvironmentSourceSetsSplit()) { - sourceSets.add(SourceSetHelper.getSourceSetByName("client", project)); - } - - try { - final FabricModJson fabricModJson = FabricModJsonFactory.createFromSourceSetsNullable(sourceSets.toArray(SourceSet[]::new)); - - if (fabricModJson != null) { - return List.of(fabricModJson); - } - } catch (IOException e) { - throw new UncheckedIOException(e); - } - - return Collections.emptyList(); - } - // Returns a list of mods that are on both to compile and runtime classpath private static List getCompileRuntimeMods(Project project) { var mods = new ArrayList<>(getCompileRuntimeModsFromRemapConfigs(project).toList()); for (Project dependentProject : getCompileRuntimeProjectDependencies(project).toList()) { - mods.addAll(getModsInProject(dependentProject)); + mods.addAll(FabricModJsonHelpers.getModsInProject(dependentProject)); } return Collections.unmodifiableList(mods); diff --git a/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java b/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java index cebfaf08..847fd3b5 100644 --- a/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java +++ b/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java @@ -143,10 +143,6 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA // Add main source set by default interfaceInjection(interfaceInjection -> { - final SourceSet main = SourceSetHelper.getMainSourceSet(project); - interfaceInjection.getInterfaceInjectionSourceSets().add(main); - - interfaceInjection.getInterfaceInjectionSourceSets().finalizeValueOnRead(); interfaceInjection.getEnableDependencyInterfaceInjection().convention(true).finalizeValueOnRead(); }); } diff --git a/src/main/java/net/fabricmc/loom/task/GenerateSourcesTask.java b/src/main/java/net/fabricmc/loom/task/GenerateSourcesTask.java index 45a60488..1c2fec3c 100644 --- a/src/main/java/net/fabricmc/loom/task/GenerateSourcesTask.java +++ b/src/main/java/net/fabricmc/loom/task/GenerateSourcesTask.java @@ -64,8 +64,8 @@ import net.fabricmc.loom.api.decompilers.DecompilationMetadata; import net.fabricmc.loom.api.decompilers.DecompilerOptions; import net.fabricmc.loom.api.decompilers.LoomDecompiler; import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; -import net.fabricmc.loom.api.processor.MappingProcessorContext; -import net.fabricmc.loom.configuration.accesswidener.TransitiveAccessWidenerMappingsProcessor; +import net.fabricmc.loom.configuration.ConfigContextImpl; +import net.fabricmc.loom.configuration.processors.MappingProcessorContextImpl; import net.fabricmc.loom.configuration.processors.MinecraftJarProcessorManager; import net.fabricmc.loom.decompilers.LineNumberRemapper; import net.fabricmc.loom.util.Constants; @@ -77,6 +77,7 @@ import net.fabricmc.loom.util.gradle.ThreadedSimpleProgressLogger; import net.fabricmc.loom.util.gradle.WorkerDaemonClientsManagerHelper; import net.fabricmc.loom.util.ipc.IPCClient; import net.fabricmc.loom.util.ipc.IPCServer; +import net.fabricmc.loom.util.service.ScopedSharedServiceManager; import net.fabricmc.mappingio.MappingReader; import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch; import net.fabricmc.mappingio.format.Tiny2Writer; @@ -330,14 +331,15 @@ public abstract class GenerateSourcesTask extends AbstractLoomTask { final List mappingsProcessors = new ArrayList<>(); - if (getExtension().getEnableTransitiveAccessWideners().get()) { - mappingsProcessors.add(new TransitiveAccessWidenerMappingsProcessor(getProject())); - } - MinecraftJarProcessorManager minecraftJarProcessorManager = MinecraftJarProcessorManager.create(getProject()); if (minecraftJarProcessorManager != null) { - mappingsProcessors.add(mappings -> minecraftJarProcessorManager.processMappings(mappings, new MappingProcessorContextImpl())); + mappingsProcessors.add(mappings -> { + try (var serviceManager = new ScopedSharedServiceManager()) { + final var configContext = new ConfigContextImpl(getProject(), serviceManager, getExtension()); + return minecraftJarProcessorManager.processMappings(mappings, new MappingProcessorContextImpl(configContext)); + } + }); } if (mappingsProcessors.isEmpty()) { @@ -388,7 +390,4 @@ public abstract class GenerateSourcesTask extends AbstractLoomTask { throw new RuntimeException(e); } } - - private static class MappingProcessorContextImpl implements MappingProcessorContext { - } } diff --git a/src/main/java/net/fabricmc/loom/util/DeprecationHelper.java b/src/main/java/net/fabricmc/loom/util/DeprecationHelper.java index 9ddbfb69..ea1f8f46 100644 --- a/src/main/java/net/fabricmc/loom/util/DeprecationHelper.java +++ b/src/main/java/net/fabricmc/loom/util/DeprecationHelper.java @@ -1,7 +1,7 @@ /* * This file is part of fabric-loom, licensed under the MIT License (MIT). * - * Copyright (c) 2021 FabricMC + * Copyright (c) 2021-2023 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 @@ -35,10 +35,18 @@ public interface DeprecationHelper { toBeRemovedIn(currentName, newName, "Loom 2.0"); } + default void removedInLoom2_0(String currentName) { + toBeRemovedIn(currentName, "Loom 2.0"); + } + default void toBeRemovedIn(String currentName, String newName, String removalVersion) { warn("The '%s' property has been deprecated, and has been replaced with '%s'. This is scheduled to be removed in %s.".formatted(currentName, newName, removalVersion)); } + default void toBeRemovedIn(String currentName, String removalVersion) { + warn("The '%s' property has been deprecated, and can be removed. This is scheduled to be removed in %s.".formatted(currentName, removalVersion)); + } + Project getProject(); void warn(String warning); diff --git a/src/main/java/net/fabricmc/loom/util/LazyCloseable.java b/src/main/java/net/fabricmc/loom/util/LazyCloseable.java new file mode 100644 index 00000000..50c7f7e8 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/util/LazyCloseable.java @@ -0,0 +1,58 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2023 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.Closeable; +import java.io.IOException; +import java.util.function.Consumer; +import java.util.function.Supplier; + +// Not thread safe +public class LazyCloseable implements Closeable { + private final Supplier valueSupplier; + private final Consumer closeConsumer; + private T value; + + public LazyCloseable(Supplier valueSupplier, Consumer closeConsumer) { + this.valueSupplier = valueSupplier; + this.closeConsumer = closeConsumer; + } + + public T get() { + if (value == null) { + value = valueSupplier.get(); + } + + return value; + } + + @Override + public void close() throws IOException { + if (value != null) { + closeConsumer.accept(value); + value = null; + } + } +} diff --git a/src/main/java/net/fabricmc/loom/util/fmj/FabricModJsonHelpers.java b/src/main/java/net/fabricmc/loom/util/fmj/FabricModJsonHelpers.java new file mode 100644 index 00000000..923c7a30 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/util/fmj/FabricModJsonHelpers.java @@ -0,0 +1,62 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2023 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.fmj; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.gradle.api.Project; +import org.gradle.api.tasks.SourceSet; + +import net.fabricmc.loom.LoomGradleExtension; +import net.fabricmc.loom.util.gradle.SourceSetHelper; + +public class FabricModJsonHelpers { + // Returns a list of Mods found in the provided project's main or client sourcesets + public static List getModsInProject(Project project) { + final LoomGradleExtension extension = LoomGradleExtension.get(project); + var sourceSets = new ArrayList(); + sourceSets.add(SourceSetHelper.getMainSourceSet(project)); + + if (extension.areEnvironmentSourceSetsSplit()) { + sourceSets.add(SourceSetHelper.getSourceSetByName("client", project)); + } + + try { + final FabricModJson fabricModJson = FabricModJsonFactory.createFromSourceSetsNullable(sourceSets.toArray(SourceSet[]::new)); + + if (fabricModJson != null) { + return List.of(fabricModJson); + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } + + return Collections.emptyList(); + } +} diff --git a/src/main/java/net/fabricmc/loom/util/fmj/FabricModJsonSource.java b/src/main/java/net/fabricmc/loom/util/fmj/FabricModJsonSource.java index 0da5fe98..9ff5a7d6 100644 --- a/src/main/java/net/fabricmc/loom/util/fmj/FabricModJsonSource.java +++ b/src/main/java/net/fabricmc/loom/util/fmj/FabricModJsonSource.java @@ -59,13 +59,17 @@ public interface FabricModJsonSource { record SourceSetSource(SourceSet... sourceSets) implements FabricModJsonSource { @Override public byte[] read(String path) throws IOException { + return Files.readAllBytes(findFile(path).toPath()); + } + + private File findFile(String path) throws IOException { final File file = SourceSetHelper.findFirstFileInResource(path, sourceSets); if (file == null) { throw new FileNotFoundException("Could not find: " + path); } - return Files.readAllBytes(file.toPath()); + return file; } } }