Move access widener jar processor for new processor API. (#787)

This commit is contained in:
modmuss50
2023-01-10 23:19:21 +00:00
committed by GitHub
parent af21d602e9
commit da4b01427f
22 changed files with 598 additions and 389 deletions

View File

@@ -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

View File

@@ -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<TinyRemapper> createRemapper(MappingsNamespace from, MappingsNamespace to);
}

View File

@@ -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<TinyRemapper> createRemapper(MappingsNamespace from, MappingsNamespace to);
}

View File

@@ -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");

View File

@@ -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<TinyRemapper> remapper) throws IOException;
}

View File

@@ -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<AccessWidenerJarProcessor.Spec> {
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<AccessWidenerEntry> 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<AccessWidenerEntry> accessWideners) implements MinecraftJarProcessor.Spec {
List<AccessWidenerEntry> 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<AccessWidenerEntry> accessWideners = spec.accessWidenersForContext(context);
final var accessWidener = new AccessWidener();
try (LazyCloseable<TinyRemapper> 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<Spec> processMappings() {
return TransitiveAccessWidenerMappingsProcessor.INSTANCE;
}
}

View File

@@ -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();

View File

@@ -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<TinyRemapper> 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;
}
}

View File

@@ -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<ModAccessWidenerEntry> readAll(FabricModJson modJson, boolean transitiveOnly) {
var entries = new ArrayList<ModAccessWidenerEntry>();
for (Map.Entry<String, ModEnvironment> 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<TinyRemapper> remapper) throws IOException {
if (transitiveOnly) {
// Filter for only transitive rules
visitor = new TransitiveOnlyFilter(visitor);
}
final byte[] data = readRaw();
final AccessWidenerReader.Header header = AccessWidenerReader.readHeader(data);
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);
}
}

View File

@@ -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<AccessWidenerFile> 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<AccessWidenerFile> getTransitiveAccessWideners() {
final List<AccessWidenerFile> accessWideners = new ArrayList<>();
final Set<Path> 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;
}
}
}

View File

@@ -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<AccessWidenerJarProcessor.Spec> {
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<AccessWidenerFile> accessWideners = extension.getTransitiveAccessWideners();
public boolean transform(MemoryMappingTree mappings, AccessWidenerJarProcessor.Spec spec, MappingProcessorContext context) {
final List<AccessWidenerEntry> 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<TinyRemapper> 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;
}

View File

@@ -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<InterfaceInjectionProcessor.Spec> {
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<InjectedInterface> 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 {

View File

@@ -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<TinyRemapper> 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);
}
}

View File

@@ -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<TinyRemapper> createRemapper(MappingsNamespace from, MappingsNamespace to) {
return ContextImplHelper.createRemapper(configContext, from, to);
}
}

View File

@@ -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<TinyRemapper> createRemapper(MappingsNamespace from, MappingsNamespace to) {
return ContextImplHelper.createRemapper(configContext, from, to);
}
}

View File

@@ -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<FabricModJson> modDependencies, List<FabricModJson> localMods, List<FabricModJson> 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<FabricModJson> modDependencies, List<FabricMo
if (!GradleUtils.getBooleanProperty(project, Constants.Properties.DISABLE_PROJECT_DEPENDENT_MODS)) {
// Add all the dependent projects
for (Project dependentProject : getDependentProjects(project).toList()) {
mods.addAll(getModsInProject(dependentProject));
mods.addAll(FabricModJsonHelpers.getModsInProject(dependentProject));
}
}
@@ -97,35 +94,12 @@ public record SpecContextImpl(List<FabricModJson> modDependencies, List<FabricMo
.distinct();
}
// Returns a list of Mods found in the provided project
private static List<FabricModJson> getModsInProject(Project project) {
final LoomGradleExtension extension = LoomGradleExtension.get(project);
var sourceSets = new ArrayList<SourceSet>();
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<FabricModJson> 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);

View File

@@ -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();
});
}

View File

@@ -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<MappingsProcessor> 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 {
}
}

View File

@@ -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);

View File

@@ -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<T> implements Closeable {
private final Supplier<T> valueSupplier;
private final Consumer<T> closeConsumer;
private T value;
public LazyCloseable(Supplier<T> valueSupplier, Consumer<T> 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;
}
}
}

View File

@@ -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<FabricModJson> getModsInProject(Project project) {
final LoomGradleExtension extension = LoomGradleExtension.get(project);
var sourceSets = new ArrayList<SourceSet>();
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();
}
}

View File

@@ -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;
}
}
}