Migrate fully to mapping-io + Add comments about transitive access widners to generated sources (#495)

* Add comments about transitive access widners to generated sources

* Migrate fully to mapping io

* Use release version of lorenz-tiny

* Review comment
This commit is contained in:
modmuss50 2021-09-16 15:28:06 +01:00 committed by GitHub
parent d48c74161e
commit 9d9be1b842
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 294 additions and 175 deletions

View file

@ -79,15 +79,12 @@ dependencies {
// tinyfile management
implementation ('net.fabricmc:tiny-remapper:0.5.0')
implementation ('net.fabricmc:tiny-mappings-parser:0.3.0+build.17')
implementation 'net.fabricmc:access-widener:2.0.0'
implementation 'net.fabricmc:mapping-io:0.2.1'
implementation ('net.fabricmc:lorenz-tiny:3.0.0') {
implementation ('net.fabricmc:lorenz-tiny:4.0.0') {
transitive = false
}
implementation ('org.cadixdev:lorenz-io-proguard:0.5.7')
// decompilers
implementation ('net.fabricmc:fabric-fernflower:1.4.1')

View file

@ -25,6 +25,7 @@
package net.fabricmc.loom;
import java.io.File;
import java.util.List;
import java.util.Set;
import java.util.function.Supplier;
@ -38,6 +39,7 @@ import org.gradle.api.file.ConfigurableFileCollection;
import net.fabricmc.loom.api.LoomGradleExtensionAPI;
import net.fabricmc.loom.configuration.InstallerData;
import net.fabricmc.loom.configuration.LoomDependencyManager;
import net.fabricmc.loom.configuration.accesswidener.AccessWidenerFile;
import net.fabricmc.loom.configuration.processors.JarProcessorManager;
import net.fabricmc.loom.configuration.providers.MinecraftProviderImpl;
import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl;
@ -103,4 +105,8 @@ public interface LoomGradleExtension extends LoomGradleExtensionAPI {
@Override
MixinExtension getMixin();
List<AccessWidenerFile> getTransitiveAccessWideners();
void addTransitiveAccessWideners(List<AccessWidenerFile> accessWidenerFiles);
}

View file

@ -40,7 +40,6 @@ import net.fabricmc.loom.configuration.CompileConfiguration;
import net.fabricmc.loom.configuration.FabricApiExtension;
import net.fabricmc.loom.configuration.MavenPublication;
import net.fabricmc.loom.configuration.ide.IdeConfiguration;
import net.fabricmc.loom.configuration.providers.mappings.MappingsCache;
import net.fabricmc.loom.decompilers.DecompilerConfiguration;
import net.fabricmc.loom.extension.LoomFiles;
import net.fabricmc.loom.extension.LoomGradleExtensionImpl;
@ -68,7 +67,6 @@ public class LoomGradlePlugin implements BootstrappedPlugin {
refreshDeps = project.getGradle().getStartParameter().isRefreshDependencies();
if (refreshDeps) {
MappingsCache.INSTANCE.invalidate();
project.getLogger().lifecycle("Refresh dependencies is in use, loom will be significantly slower.");
}

View file

@ -60,6 +60,8 @@ public class TransitiveAccessWidenerJarProcessor implements JarProcessor {
this.extension = LoomGradleExtension.get(project);
transitiveAccessWideners = getTransitiveAccessWideners();
extension.addTransitiveAccessWideners(transitiveAccessWideners);
}
@Override

View file

@ -0,0 +1,147 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2021 FabricMC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package net.fabricmc.loom.configuration.accesswidener;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import org.gradle.api.logging.Logger;
import net.fabricmc.accesswidener.AccessWidenerReader;
import net.fabricmc.accesswidener.AccessWidenerVisitor;
import net.fabricmc.accesswidener.TransitiveOnlyFilter;
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
import net.fabricmc.mappingio.MappingReader;
import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch;
import net.fabricmc.mappingio.format.Tiny2Writer;
import net.fabricmc.mappingio.tree.MappingTree;
import net.fabricmc.mappingio.tree.MemoryMappingTree;
public final class TransitiveAccessWidenerMappingsProcessor {
private TransitiveAccessWidenerMappingsProcessor() {
}
public static void process(Path inputMappings, Path outputMappings, List<AccessWidenerFile> accessWideners, Logger logger) {
MemoryMappingTree mappingTree = new MemoryMappingTree();
try (Reader reader = Files.newBufferedReader(inputMappings, StandardCharsets.UTF_8)) {
MappingReader.read(reader, new MappingSourceNsSwitch(mappingTree, MappingsNamespace.INTERMEDIARY.toString()));
} catch (IOException e) {
throw new RuntimeException("Failed to read mappings", e);
}
if (!MappingsNamespace.INTERMEDIARY.toString().equals(mappingTree.getSrcNamespace())) {
throw new IllegalStateException("Mapping tree must have intermediary src mappings not " + mappingTree.getSrcNamespace());
}
for (AccessWidenerFile accessWidener : accessWideners) {
MappingCommentVisitor mappingCommentVisitor = new MappingCommentVisitor(accessWidener.modId(), mappingTree, logger);
AccessWidenerReader accessWidenerReader = new AccessWidenerReader(new TransitiveOnlyFilter(mappingCommentVisitor));
accessWidenerReader.read(accessWidener.content());
}
try (Writer writer = Files.newBufferedWriter(outputMappings, StandardCharsets.UTF_8)) {
Tiny2Writer tiny2Writer = new Tiny2Writer(writer, false);
mappingTree.accept(new MappingSourceNsSwitch(tiny2Writer, MappingsNamespace.NAMED.toString()));
} catch (IOException e) {
throw new RuntimeException("Failed to write mappings", e);
}
}
private static record MappingCommentVisitor(String modId, MemoryMappingTree mappingTree, Logger logger) implements AccessWidenerVisitor {
@Override
public void visitClass(String name, AccessWidenerReader.AccessType access, boolean transitive) {
MappingTree.ClassMapping classMapping = mappingTree.getClass(name);
if (classMapping == null) {
logger.warn("Failed to find class ({}) to mark access widened by mod ({})", name, modId());
return;
}
classMapping.setComment(appendComment(classMapping.getComment(), access));
}
@Override
public void visitMethod(String owner, String name, String descriptor, AccessWidenerReader.AccessType access, boolean transitive) {
// Access is also applied to the class, so also add the comment to the class
visitClass(owner, access, transitive);
MappingTree.ClassMapping classMapping = mappingTree.getClass(owner);
if (classMapping == null) {
logger.warn("Failed to find class ({}) to mark access widened by mod ({})", owner, modId());
return;
}
MappingTree.MethodMapping methodMapping = classMapping.getMethod(name, descriptor);
if (methodMapping == null) {
logger.warn("Failed to find method ({}) in ({}) to mark access widened by mod ({})", name, owner, modId());
return;
}
methodMapping.setComment(appendComment(methodMapping.getComment(), access));
}
@Override
public void visitField(String owner, String name, String descriptor, AccessWidenerReader.AccessType access, boolean transitive) {
// Access is also applied to the class, so also add the comment to the class
visitClass(owner, access, transitive);
MappingTree.ClassMapping classMapping = mappingTree.getClass(owner);
if (classMapping == null) {
logger.warn("Failed to find class ({}) to mark access widened by mod ({})", name, modId());
return;
}
MappingTree.FieldMapping fieldMapping = classMapping.getField(name, descriptor);
if (fieldMapping == null) {
logger.warn("Failed to find field ({}) in ({}) to mark access widened by mod ({})", name, owner, modId());
return;
}
fieldMapping.setComment(appendComment(fieldMapping.getComment(), access));
}
private String appendComment(String comment, AccessWidenerReader.AccessType access) {
if (comment == null) {
comment = "";
} else {
comment += "\n";
}
comment += "Access widened by %s to %s".formatted(modId(), access);
return comment;
}
}
}

View file

@ -1,69 +0,0 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2016-2020 FabricMC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package net.fabricmc.loom.configuration.providers.mappings;
import java.io.BufferedReader;
import java.io.IOException;
import java.lang.ref.SoftReference;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
import net.fabricmc.loom.util.StaticPathWatcher;
import net.fabricmc.mapping.tree.TinyMappingFactory;
import net.fabricmc.mapping.tree.TinyTree;
public final class MappingsCache {
public static final MappingsCache INSTANCE = new MappingsCache();
private final Map<Path, SoftReference<TinyTree>> mappingsCache = new HashMap<>();
// TODO: loom doesn't actually use new mappings when the mappings change until the gradle daemons are stopped
public TinyTree get(Path mappingsPath) throws IOException {
mappingsPath = mappingsPath.toAbsolutePath();
if (StaticPathWatcher.INSTANCE.hasFileChanged(mappingsPath)) {
mappingsCache.remove(mappingsPath);
}
SoftReference<TinyTree> ref = mappingsCache.get(mappingsPath);
if (ref != null && ref.get() != null) {
return ref.get();
} else {
try (BufferedReader reader = Files.newBufferedReader(mappingsPath)) {
TinyTree mappings = TinyMappingFactory.loadWithDetection(reader);
ref = new SoftReference<>(mappings);
mappingsCache.put(mappingsPath, ref);
return mappings;
}
}
}
public void invalidate() {
mappingsCache.clear();
}
}

View file

@ -35,6 +35,7 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.Collections;
import java.util.Objects;
import java.util.function.Consumer;
import com.google.common.base.Stopwatch;
@ -59,10 +60,10 @@ import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvid
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.DeletingFileVisitor;
import net.fabricmc.loom.util.DownloadUtil;
import net.fabricmc.mapping.reader.v2.TinyV2Factory;
import net.fabricmc.mapping.tree.TinyTree;
import net.fabricmc.mappingio.MappingReader;
import net.fabricmc.mappingio.adapter.MappingNsCompleter;
import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch;
import net.fabricmc.mappingio.format.MappingFormat;
import net.fabricmc.mappingio.format.Tiny2Reader;
import net.fabricmc.mappingio.format.Tiny2Writer;
import net.fabricmc.mappingio.tree.MemoryMappingTree;
@ -87,13 +88,14 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings
private Path unpickDefinitions;
private boolean hasUnpickDefinitions;
private UnpickMetadata unpickMetadata;
private MemoryMappingTree mappingTree;
public MappingsProviderImpl(Project project) {
super(project);
}
public TinyTree getMappings() throws IOException {
return MappingsCache.INSTANCE.get(tinyMappings);
public MemoryMappingTree getMappings() throws IOException {
return Objects.requireNonNull(mappingTree, "Cannot get mappings before they have been read");
}
@Override
@ -119,6 +121,8 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings
}
}
mappingTree = readMappings();
if (Files.notExists(tinyMappingsJar) || isRefreshDeps()) {
ZipUtil.pack(new ZipEntrySource[] {new FileSource("mappings/mappings.tiny", tinyMappings.toFile())}, tinyMappingsJar.toFile());
}
@ -216,23 +220,22 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings
}
}
private MemoryMappingTree readMappings() throws IOException {
MemoryMappingTree mappingTree = new MemoryMappingTree();
MappingReader.read(tinyMappings, mappingTree);
return mappingTree;
}
private static boolean areMappingsV2(Path path) throws IOException {
try (BufferedReader reader = Files.newBufferedReader(path)) {
TinyV2Factory.readMetadata(reader);
return true;
} catch (IllegalArgumentException e) {
// TODO: just check the mappings version when Parser supports V1 in readMetadata()
return false;
return MappingReader.detectFormat(reader) == MappingFormat.TINY_2;
}
}
private static boolean doesJarContainV2Mappings(Path path) throws IOException {
try (FileSystem fs = FileSystems.newFileSystem(path, (ClassLoader) null)) {
try (BufferedReader reader = Files.newBufferedReader(fs.getPath("mappings", "mappings.tiny"))) {
TinyV2Factory.readMetadata(reader);
return true;
} catch (IllegalArgumentException e) {
return false;
return MappingReader.detectFormat(reader) == MappingFormat.TINY_2;
}
}
}

View file

@ -29,9 +29,7 @@ import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jetbrains.java.decompiler.struct.StructClass;
import org.jetbrains.java.decompiler.struct.StructField;
@ -40,48 +38,29 @@ import org.jetbrains.java.decompiler.struct.StructRecordComponent;
import org.objectweb.asm.Opcodes;
import net.fabricmc.fernflower.api.IFabricJavadocProvider;
import net.fabricmc.mapping.tree.ClassDef;
import net.fabricmc.mapping.tree.FieldDef;
import net.fabricmc.mapping.tree.MethodDef;
import net.fabricmc.mapping.tree.ParameterDef;
import net.fabricmc.mapping.tree.TinyMappingFactory;
import net.fabricmc.mapping.tree.TinyTree;
import net.fabricmc.mappings.EntryTriple;
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
import net.fabricmc.mappingio.MappingReader;
import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch;
import net.fabricmc.mappingio.tree.MappingTree;
import net.fabricmc.mappingio.tree.MemoryMappingTree;
public class TinyJavadocProvider implements IFabricJavadocProvider {
private final Map<String, ClassDef> classes = new HashMap<>();
private final Map<EntryTriple, FieldDef> fields = new HashMap<>();
private final Map<EntryTriple, MethodDef> methods = new HashMap<>();
private final String namespace = "named";
private final MappingTree mappingTree;
public TinyJavadocProvider(File tinyFile) {
final TinyTree mappings = readMappings(tinyFile);
for (ClassDef classDef : mappings.getClasses()) {
final String className = classDef.getName(namespace);
classes.put(className, classDef);
for (FieldDef fieldDef : classDef.getFields()) {
fields.put(new EntryTriple(className, fieldDef.getName(namespace), fieldDef.getDescriptor(namespace)), fieldDef);
}
for (MethodDef methodDef : classDef.getMethods()) {
methods.put(new EntryTriple(className, methodDef.getName(namespace), methodDef.getDescriptor(namespace)), methodDef);
}
}
mappingTree = readMappings(tinyFile);
}
@Override
public String getClassDoc(StructClass structClass) {
ClassDef classDef = classes.get(structClass.qualifiedName);
MappingTree.ClassMapping classMapping = mappingTree.getClass(structClass.qualifiedName);
if (classDef == null) {
if (classMapping == null) {
return null;
}
if (!isRecord(structClass)) {
return classDef.getComment();
return classMapping.getComment();
}
/**
@ -91,30 +70,30 @@ public class TinyJavadocProvider implements IFabricJavadocProvider {
*/
List<String> parts = new ArrayList<>();
if (classDef.getComment() != null) {
parts.add(classDef.getComment());
if (classMapping.getComment() != null) {
parts.add(classMapping.getComment());
}
boolean addedParam = false;
for (StructRecordComponent component : structClass.getRecordComponents()) {
// The component will always match the field name and descriptor
FieldDef fieldDef = fields.get(new EntryTriple(structClass.qualifiedName, component.getName(), component.getDescriptor()));
MappingTree.FieldMapping fieldMapping = classMapping.getField(component.getName(), component.getDescriptor());
if (fieldDef == null) {
if (fieldMapping == null) {
continue;
}
String comment = fieldDef.getComment();
String comment = fieldMapping.getComment();
if (comment != null) {
if (!addedParam && classDef.getComment() != null) {
if (!addedParam && classMapping.getComment() != null) {
//Add a blank line before components when the class has a comment
parts.add("");
addedParam = true;
}
parts.add(String.format("@param %s %s", fieldDef.getName(namespace), comment));
parts.add(String.format("@param %s %s", fieldMapping.getName(MappingsNamespace.NAMED.toString()), comment));
}
}
@ -132,34 +111,47 @@ public class TinyJavadocProvider implements IFabricJavadocProvider {
return null;
}
FieldDef fieldDef = fields.get(new EntryTriple(structClass.qualifiedName, structField.getName(), structField.getDescriptor()));
return fieldDef != null ? fieldDef.getComment() : null;
MappingTree.ClassMapping classMapping = mappingTree.getClass(structClass.qualifiedName);
if (classMapping == null) {
return null;
}
MappingTree.FieldMapping fieldMapping = classMapping.getField(structField.getName(), structField.getDescriptor());
return fieldMapping != null ? fieldMapping.getComment() : null;
}
@Override
public String getMethodDoc(StructClass structClass, StructMethod structMethod) {
MethodDef methodDef = methods.get(new EntryTriple(structClass.qualifiedName, structMethod.getName(), structMethod.getDescriptor()));
MappingTree.ClassMapping classMapping = mappingTree.getClass(structClass.qualifiedName);
if (methodDef != null) {
if (classMapping == null) {
return null;
}
MappingTree.MethodMapping methodMapping = classMapping.getMethod(structMethod.getName(), structMethod.getDescriptor());
if (methodMapping != null) {
List<String> parts = new ArrayList<>();
if (methodDef.getComment() != null) {
parts.add(methodDef.getComment());
if (methodMapping.getComment() != null) {
parts.add(methodMapping.getComment());
}
boolean addedParam = false;
for (ParameterDef param : methodDef.getParameters()) {
String comment = param.getComment();
for (MappingTree.MethodArgMapping argMapping : methodMapping.getArgs()) {
String comment = argMapping.getComment();
if (comment != null) {
if (!addedParam && methodDef.getComment() != null) {
if (!addedParam && methodMapping.getComment() != null) {
//Add a blank line before params when the method has a comment
parts.add("");
addedParam = true;
}
parts.add(String.format("@param %s %s", param.getName(namespace), comment));
parts.add(String.format("@param %s %s", methodMapping.getName(MappingsNamespace.NAMED.toString()), comment));
}
}
@ -173,9 +165,13 @@ public class TinyJavadocProvider implements IFabricJavadocProvider {
return null;
}
private static TinyTree readMappings(File input) {
private static MappingTree readMappings(File input) {
try (BufferedReader reader = Files.newBufferedReader(input.toPath())) {
return TinyMappingFactory.loadWithDetection(reader);
MemoryMappingTree mappingTree = new MemoryMappingTree();
MappingSourceNsSwitch nsSwitch = new MappingSourceNsSwitch(mappingTree, MappingsNamespace.NAMED.toString());
MappingReader.read(reader, nsSwitch);
return mappingTree;
} catch (IOException e) {
throw new RuntimeException("Failed to read mappings", e);
}

View file

@ -25,9 +25,11 @@
package net.fabricmc.loom.extension;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
@ -43,6 +45,7 @@ import org.gradle.api.file.ConfigurableFileCollection;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.configuration.InstallerData;
import net.fabricmc.loom.configuration.LoomDependencyManager;
import net.fabricmc.loom.configuration.accesswidener.AccessWidenerFile;
import net.fabricmc.loom.configuration.processors.JarProcessorManager;
public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implements LoomGradleExtension {
@ -55,6 +58,7 @@ public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implemen
private final MappingSet[] srcMappingCache = new MappingSet[2];
private final Mercury[] srcMercuryCache = new Mercury[2];
private final Map<String, NamedDomainObjectProvider<Configuration>> lazyConfigurations = new HashMap<>();
private final List<AccessWidenerFile> transitiveAccessWideners = new ArrayList<>();
private LoomDependencyManager dependencyManager;
private JarProcessorManager jarProcessorManager;
@ -168,4 +172,14 @@ public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implemen
public MixinExtension getMixin() {
return this.mixinApExtension;
}
@Override
public List<AccessWidenerFile> getTransitiveAccessWideners() {
return transitiveAccessWideners;
}
@Override
public void addTransitiveAccessWideners(List<AccessWidenerFile> accessWidenerFiles) {
transitiveAccessWideners.addAll(accessWidenerFiles);
}
}

View file

@ -30,6 +30,7 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;
@ -41,6 +42,8 @@ import org.gradle.api.tasks.TaskAction;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.api.decompilers.DecompilationMetadata;
import net.fabricmc.loom.api.decompilers.LoomDecompiler;
import net.fabricmc.loom.configuration.accesswidener.AccessWidenerFile;
import net.fabricmc.loom.configuration.accesswidener.TransitiveAccessWidenerMappingsProcessor;
import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl;
import net.fabricmc.loom.decompilers.LineNumberRemapper;
import net.fabricmc.loom.util.Constants;
@ -62,11 +65,10 @@ public class GenerateSourcesTask extends AbstractLoomTask {
@TaskAction
public void doTask() throws Throwable {
int threads = Runtime.getRuntime().availableProcessors();
Path javaDocs = getExtension().getMappingsProvider().tinyMappings;
Collection<Path> libraries = getProject().getConfigurations().getByName(Constants.Configurations.MINECRAFT_DEPENDENCIES).getFiles()
.stream().map(File::toPath).collect(Collectors.toSet());
.stream().map(File::toPath).collect(Collectors.toSet());
DecompilationMetadata metadata = new DecompilationMetadata(threads, javaDocs, libraries);
DecompilationMetadata metadata = new DecompilationMetadata(threads, getMappings(), libraries);
Path runtimeJar = getExtension().getMappingsProvider().mappedProvider.getMappedJar().toPath();
Path sourcesDestination = getMappedJarFileWithSuffix("-sources.jar").toPath();
Path linemap = getMappedJarFileWithSuffix("-sources.lmap").toPath();
@ -92,7 +94,7 @@ public class GenerateSourcesTask extends AbstractLoomTask {
progressLogger.start("Adjusting line numbers", "linemap");
try (StitchUtil.FileSystemDelegate inFs = StitchUtil.getJarFileSystem(oldCompiledJar.toFile(), true);
StitchUtil.FileSystemDelegate outFs = StitchUtil.getJarFileSystem(linemappedJarDestination.toFile(), true)) {
StitchUtil.FileSystemDelegate outFs = StitchUtil.getJarFileSystem(linemappedJarDestination.toFile(), true)) {
remapper.process(progressLogger, inFs.get().getPath("/"), outFs.get().getPath("/"));
}
@ -112,6 +114,32 @@ public class GenerateSourcesTask extends AbstractLoomTask {
return new File(path.substring(0, path.length() - 4) + suffix);
}
private Path getMappings() {
Path baseMappings = getExtension().getMappingsProvider().tinyMappings;
if (getExtension().getEnableTransitiveAccessWideners().get()) {
List<AccessWidenerFile> accessWideners = getExtension().getTransitiveAccessWideners();
if (accessWideners.isEmpty()) {
return baseMappings;
}
Path outputMappings;
try {
outputMappings = Files.createTempFile("loom-transitive-mappings", ".tiny");
} catch (IOException e) {
throw new RuntimeException("Failed to create temp file", e);
}
TransitiveAccessWidenerMappingsProcessor.process(baseMappings, outputMappings, accessWideners, getProject().getLogger());
return outputMappings;
}
return baseMappings;
}
@InputFile
public File getInputJar() {
return inputJar;

View file

@ -24,14 +24,12 @@
package net.fabricmc.loom.task;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.Set;
import com.google.common.collect.ImmutableMap;
@ -49,15 +47,15 @@ import org.gradle.api.tasks.TaskAction;
import org.gradle.api.tasks.options.Option;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.api.mappings.layered.spec.LayeredMappingSpecBuilder;
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
import net.fabricmc.loom.api.mappings.layered.spec.LayeredMappingSpecBuilder;
import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingsDependency;
import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider;
import net.fabricmc.loom.util.SourceRemapper;
import net.fabricmc.lorenztiny.TinyMappingsJoiner;
import net.fabricmc.mapping.tree.TinyMappingFactory;
import net.fabricmc.mapping.tree.TinyTree;
import net.fabricmc.mappingio.MappingReader;
import net.fabricmc.mappingio.tree.MemoryMappingTree;
public class MigrateMappingsTask extends AbstractLoomTask {
private Path inputDir;
@ -101,8 +99,8 @@ public class MigrateMappingsTask extends AbstractLoomTask {
MappingsProviderImpl mappingsProvider = extension.getMappingsProvider();
try {
TinyTree currentMappings = mappingsProvider.getMappings();
TinyTree targetMappings = getMappings(mappings);
MemoryMappingTree currentMappings = mappingsProvider.getMappings();
MemoryMappingTree targetMappings = getMappings(mappings);
migrateMappings(project, extension.getMinecraftMappedProvider(), inputDir, outputDir, currentMappings, targetMappings);
project.getLogger().lifecycle(":remapped project written to " + outputDir.toAbsolutePath());
} catch (IOException e) {
@ -149,20 +147,18 @@ public class MigrateMappingsTask extends AbstractLoomTask {
return Iterables.getOnlyElement(files);
}
private static TinyTree getMappings(File mappings) throws IOException {
Path temp = Files.createTempFile("mappings", ".tiny");
private static MemoryMappingTree getMappings(File mappings) throws IOException {
MemoryMappingTree mappingTree = new MemoryMappingTree();
try (FileSystem fileSystem = FileSystems.newFileSystem(mappings.toPath(), (ClassLoader) null)) {
Files.copy(fileSystem.getPath("mappings/mappings.tiny"), temp, StandardCopyOption.REPLACE_EXISTING);
MappingReader.read(fileSystem.getPath("mappings/mappings.tiny"), mappingTree);
}
try (BufferedReader reader = Files.newBufferedReader(temp)) {
return TinyMappingFactory.loadWithDetection(reader);
}
return mappingTree;
}
private static void migrateMappings(Project project, MinecraftMappedProvider minecraftMappedProvider,
Path inputDir, Path outputDir, TinyTree currentMappings, TinyTree targetMappings
Path inputDir, Path outputDir, MemoryMappingTree currentMappings, MemoryMappingTree targetMappings
) throws IOException {
project.getLogger().info(":joining mappings");

View file

@ -45,7 +45,7 @@ import net.fabricmc.loom.configuration.RemappedConfigurationEntry;
import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl;
import net.fabricmc.loom.util.gradle.ProgressLogger;
import net.fabricmc.lorenztiny.TinyMappingsReader;
import net.fabricmc.mapping.tree.TinyTree;
import net.fabricmc.mappingio.tree.MemoryMappingTree;
import net.fabricmc.stitch.util.StitchUtil;
public class SourceRemapper {
@ -165,7 +165,7 @@ public class SourceRemapper {
MappingSet mappings = extension.getOrCreateSrcMappingCache(toNamed ? 1 : 0, () -> {
try {
TinyTree m = mappingsProvider.getMappings();
MemoryMappingTree m = mappingsProvider.getMappings();
project.getLogger().info(":loading " + (toNamed ? "intermediary -> named" : "named -> intermediary") + " source mappings");
return new TinyMappingsReader(m, toNamed ? MappingsNamespace.INTERMEDIARY.toString() : MappingsNamespace.NAMED.toString(), toNamed ? MappingsNamespace.NAMED.toString() : MappingsNamespace.INTERMEDIARY.toString()).read();
} catch (Exception e) {

View file

@ -33,12 +33,7 @@ import com.google.common.collect.ImmutableMap;
import org.gradle.api.Project;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.mapping.tree.ClassDef;
import net.fabricmc.mapping.tree.FieldDef;
import net.fabricmc.mapping.tree.LocalVariableDef;
import net.fabricmc.mapping.tree.MethodDef;
import net.fabricmc.mapping.tree.ParameterDef;
import net.fabricmc.mapping.tree.TinyTree;
import net.fabricmc.mappingio.tree.MappingTree;
import net.fabricmc.tinyremapper.IMappingProvider;
import net.fabricmc.tinyremapper.TinyRemapper;
@ -75,28 +70,34 @@ public final class TinyRemapperHelper {
return new IMappingProvider.Member(className, memberName, descriptor);
}
public static IMappingProvider create(TinyTree mappings, String from, String to, boolean remapLocalVariables) {
public static IMappingProvider create(MappingTree mappings, String from, String to, boolean remapLocalVariables) {
return (acceptor) -> {
for (ClassDef classDef : mappings.getClasses()) {
for (MappingTree.ClassMapping classDef : mappings.getClasses()) {
String className = classDef.getName(from);
acceptor.acceptClass(className, classDef.getName(to));
for (FieldDef field : classDef.getFields()) {
acceptor.acceptField(memberOf(className, field.getName(from), field.getDescriptor(from)), field.getName(to));
for (MappingTree.FieldMapping field : classDef.getFields()) {
acceptor.acceptField(memberOf(className, field.getName(from), field.getDesc(from)), field.getName(to));
}
for (MethodDef method : classDef.getMethods()) {
IMappingProvider.Member methodIdentifier = memberOf(className, method.getName(from), method.getDescriptor(from));
for (MappingTree.MethodMapping method : classDef.getMethods()) {
IMappingProvider.Member methodIdentifier = memberOf(className, method.getName(from), method.getDesc(from));
acceptor.acceptMethod(methodIdentifier, method.getName(to));
if (remapLocalVariables) {
for (ParameterDef parameter : method.getParameters()) {
acceptor.acceptMethodArg(methodIdentifier, parameter.getLocalVariableIndex(), parameter.getName(to));
for (MappingTree.MethodArgMapping parameter : method.getArgs()) {
String name = parameter.getName(to);
if (name == null) {
continue;
}
acceptor.acceptMethodArg(methodIdentifier, parameter.getLvIndex(), name);
}
for (LocalVariableDef localVariable : method.getLocalVariables()) {
acceptor.acceptMethodVar(methodIdentifier, localVariable.getLocalVariableIndex(),
localVariable.getLocalVariableStartOffset(), localVariable.getLocalVariableTableIndex(),
for (MappingTree.MethodVarMapping localVariable : method.getVars()) {
acceptor.acceptMethodVar(methodIdentifier, localVariable.getLvIndex(),
localVariable.getStartOpIdx(), localVariable.getLvtRowIndex(),
localVariable.getName(to));
}
}