Fix de-obfuscated methods in vanilla not being remapped back to mojmap after being remapped to srg

Signed-off-by: shedaniel <daniel@shedaniel.me>
This commit is contained in:
shedaniel
2021-07-29 21:57:53 +08:00
parent 6d6e927e77
commit d5324c2c14
7 changed files with 274 additions and 57 deletions

View File

@@ -113,7 +113,7 @@ public class FieldMigratedMappingsProvider extends MappingsProvider {
if (getExtension().shouldGenerateSrgTiny()) {
if (Files.notExists(rawTinyMappingsWithSrg) || isRefreshDeps()) {
// Merge tiny mappings with srg
SrgMerger.mergeSrg(getRawSrgFile(), rawTinyMappings, rawTinyMappingsWithSrg, true);
SrgMerger.mergeSrg(this::getMojmapSrgFileIfPossible, getRawSrgFile(), rawTinyMappings, rawTinyMappingsWithSrg, true);
}
}

View File

@@ -24,16 +24,22 @@
package net.fabricmc.loom.configuration.providers.forge;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;
import java.util.function.Consumer;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import org.apache.commons.io.IOUtils;
import org.gradle.api.Project;
import org.zeroturnaround.zip.ZipUtil;
import net.fabricmc.loom.configuration.DependencyProvider;
import net.fabricmc.loom.util.Constants;
@@ -42,6 +48,7 @@ import net.fabricmc.loom.util.FileSystemUtil;
public class McpConfigProvider extends DependencyProvider {
private File mcp;
private Path configJson;
private Path mappings;
private Boolean official;
private String mappingsPath;
@@ -73,9 +80,28 @@ public class McpConfigProvider extends DependencyProvider {
mappingsPath = json.get("data").getAsJsonObject().get("mappings").getAsString();
}
private void init(String version) {
private void init(String version) throws IOException {
mcp = new File(getExtension().getUserCache(), "mcp-" + version + ".zip");
configJson = getExtension().getUserCache().toPath().resolve("mcp-config-" + version + ".json");
mappings = getExtension().getUserCache().toPath().resolve("mcp-config-mappings-" + version + ".txt");
if (isRefreshDeps()) {
Files.deleteIfExists(mappings);
}
}
public Path getMappings() {
if (Files.notExists(mappings)) {
if (!ZipUtil.handle(getMcp(), getMappingsPath(), (in, zipEntry) -> {
try (BufferedWriter writer = Files.newBufferedWriter(mappings, StandardCharsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)) {
IOUtils.copy(in, writer, StandardCharsets.UTF_8);
}
})) {
throw new IllegalStateException("Failed to find mappings '" + getMappingsPath() + "' in " + getMcp().getAbsolutePath() + "!");
}
}
return mappings;
}
public File getMcp() {

View File

@@ -94,6 +94,7 @@ import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.ClassNode;
import org.zeroturnaround.zip.ZipUtil;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.configuration.DependencyProvider;
import net.fabricmc.loom.configuration.providers.MinecraftProvider;
import net.fabricmc.loom.configuration.providers.mappings.MappingNamespace;
@@ -103,6 +104,7 @@ import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvid
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.DependencyDownloader;
import net.fabricmc.loom.util.FileSystemUtil;
import net.fabricmc.loom.util.MappingsProviderVerbose;
import net.fabricmc.loom.util.ThreadingUtils;
import net.fabricmc.loom.util.TinyRemapperMappingsHelper;
import net.fabricmc.loom.util.function.FsPathConsumer;
@@ -110,6 +112,7 @@ import net.fabricmc.loom.util.srg.InnerClassRemapper;
import net.fabricmc.loom.util.srg.SpecialSourceExecutor;
import net.fabricmc.loom.util.srg.Tsrg2Utils;
import net.fabricmc.mapping.tree.TinyTree;
import net.fabricmc.mappingio.MappingVisitor;
public class MinecraftPatchedProvider extends DependencyProvider {
private static final String LOOM_PATCH_VERSION_KEY = "Loom-Patch-Version";
@@ -297,13 +300,18 @@ public class MinecraftPatchedProvider extends DependencyProvider {
if (dirty) {
remapPatchedJar(getProject().getLogger());
fillClientExtraJar();
if (getExtension().isForgeAndOfficial()) {
fillClientExtraJar();
}
}
this.filesDirty = dirty;
this.dirty = false;
addDependency(minecraftClientExtra, Constants.Configurations.FORGE_EXTRA);
if (getExtension().isForgeAndOfficial()) {
addDependency(minecraftClientExtra, Constants.Configurations.FORGE_EXTRA);
}
}
private void fillClientExtraJar() throws IOException {
@@ -326,6 +334,10 @@ public class MinecraftPatchedProvider extends DependencyProvider {
.fixPackageAccess(true)
.build();
if (getProject().getGradle().getStartParameter().getLogLevel().compareTo(LogLevel.LIFECYCLE) < 0) {
MappingsProviderVerbose.saveFile(remapper);
}
remapper.readClassPath(libraries);
remapper.prepareClasses();
return remapper;
@@ -364,7 +376,7 @@ public class MinecraftPatchedProvider extends DependencyProvider {
// processTsrg2(file);
}
return getMcpConfigMappings();
return getExtension().getMcpConfigProvider().getMappings();
}
private void processTsrg2(Path[] srg) throws IOException {
@@ -379,49 +391,46 @@ public class MinecraftPatchedProvider extends DependencyProvider {
}
}
public Path getMcpConfigMappings() throws IOException {
if (mcpConfigMappings == null) {
Path configMappings = Files.createTempFile("mcp-config-mappings", null);
McpConfigProvider mcpProvider = getExtension().getMcpConfigProvider();
private static void visitMojmap(MappingVisitor visitor, LoomGradleExtension extension) {
try {
MojangMappingLayer layer = new MojangMappingsSpec(() -> true).createLayer(extension.createMappingContext(() -> "layered+mojang"));
layer.visit(visitor);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
if (!ZipUtil.handle(mcpProvider.getMcp(), mcpProvider.getMappingsPath(), (in, zipEntry) -> {
try (BufferedWriter writer = Files.newBufferedWriter(configMappings, StandardCharsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)) {
IOUtils.copy(in, writer, StandardCharsets.UTF_8);
}
})) {
throw new IllegalStateException("Failed to find mappings '" + mcpProvider.getMappingsPath() + "' in " + mcpProvider.getMcp().getAbsolutePath() + "!");
}
public static Path getMojmapTsrg(LoomGradleExtension extension) throws IOException {
Path mojmap = Files.createTempFile("mojang-in-tsrg", null);
return mcpConfigMappings = configMappings;
try (BufferedWriter writer = Files.newBufferedWriter(mojmap, StandardCharsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)) {
Tsrg2Utils.writeTsrg(visitor -> visitMojmap(visitor, extension), MappingNamespace.NAMED.stringValue(), false, writer);
}
return mcpConfigMappings;
return mojmap;
}
public static Path getMojmapTsrg2(LoomGradleExtension extension) throws IOException {
Path mojmap = Files.createTempFile("mojang-in-tsrg2", null);
try (BufferedWriter writer = Files.newBufferedWriter(mojmap, StandardCharsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)) {
Tsrg2Utils.writeTsrg2(visitor -> visitMojmap(visitor, extension), writer);
}
return mojmap;
}
public Path getMojmapTSrg2EpicWhyDoesThisExist(boolean hasParameters) throws IOException {
if (mojmapTSrg2EpicWhyDoesThisExist == null) {
Path mojmap = Files.createTempFile("mojang-in-srg", null);
try (BufferedWriter writer = Files.newBufferedWriter(mojmap, StandardCharsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)) {
Tsrg2Utils.writeTsrg(visitor -> {
try {
MojangMappingLayer layer = new MojangMappingsSpec(() -> true).createLayer(getExtension().createMappingContext(() -> "layered+mojang"));
layer.visit(visitor);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}, MappingNamespace.NAMED.stringValue(), false, writer);
}
Path out = Files.createTempFile("merged-mojang-tsrg2", null);
Path outTrimmed = Files.createTempFile("merged-mojang-tsrg2-trimmed", null);
net.minecraftforge.installertools.ConsoleTool.main(new String[]{
"--task",
"MERGE_MAPPING",
"--left",
getMcpConfigMappings().toAbsolutePath().toString(),
getExtension().getMcpConfigProvider().getMappings().toAbsolutePath().toString(),
"--right",
mojmap.toAbsolutePath().toString(),
getMojmapTsrg(getExtension()).toAbsolutePath().toString(),
"--classes",
"--output",
out.toAbsolutePath().toString()

View File

@@ -27,6 +27,7 @@ package net.fabricmc.loom.configuration.providers.mappings;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystem;
@@ -238,7 +239,7 @@ public class MappingsProvider extends DependencyProvider {
if (getExtension().shouldGenerateSrgTiny()) {
if (Files.notExists(tinyMappingsWithSrg) || isRefreshDeps()) {
// Merge tiny mappings with srg
SrgMerger.mergeSrg(getRawSrgFile(), tinyMappings.toPath(), tinyMappingsWithSrg, true);
SrgMerger.mergeSrg(this::getMojmapSrgFileIfPossible, getRawSrgFile(), tinyMappings.toPath(), tinyMappingsWithSrg, true);
}
}
@@ -311,6 +312,15 @@ public class MappingsProvider extends DependencyProvider {
return extension.getSrgProvider().getSrg().toPath();
}
protected Path getMojmapSrgFileIfPossible() {
try {
LoomGradleExtension extension = getExtension();
return MinecraftPatchedProvider.getMojmapTsrg2(extension);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void manipulateMappings(Path mappingsJar) throws IOException { }
private void storeMappings(Project project, MinecraftProvider minecraftProvider, Path yarnJar, Consumer<Runnable> postPopulationScheduler)

View File

@@ -1,19 +1,33 @@
package net.fabricmc.loom.util;
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Set;
import dev.architectury.mappingslayers.api.mutable.MutableTinyMetadata;
import dev.architectury.mappingslayers.api.mutable.MutableTinyTree;
import dev.architectury.mappingslayers.api.utils.MappingsUtils;
import dev.architectury.tinyremapper.IMappingProvider;
import dev.architectury.tinyremapper.TinyRemapper;
public class MappingsProviderVerbose {
public static void saveFile(TinyRemapper providers) throws IOException {
try {
Field field = TinyRemapper.class.getDeclaredField("mappingProviders");
field.setAccessible(true);
Set<IMappingProvider> mappingProviders = (Set<IMappingProvider>) field.get(providers);
saveFile(mappingProviders);
} catch (IllegalAccessException | NoSuchFieldException e) {
e.printStackTrace();
}
}
public static void saveFile(Iterable<IMappingProvider> providers) throws IOException {
MutableTinyTree tree = MappingsUtils.create(MutableTinyMetadata.create(2, 0, Arrays.asList("from", "to"), new HashMap<>()));
@@ -52,5 +66,6 @@ public class MappingsProviderVerbose {
Path check = Files.createTempFile("CHECK", null);
Files.write(check, MappingsUtils.serializeToString(tree).getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
System.out.println("Saved debug check mappings to " + check);
}
}

View File

@@ -27,14 +27,24 @@ package net.fabricmc.loom.util.srg;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Supplier;
import com.google.common.base.MoreObjects;
import dev.architectury.mappingslayers.api.mutable.MutableClassDef;
import dev.architectury.mappingslayers.api.mutable.MutableDescriptored;
import dev.architectury.mappingslayers.api.mutable.MutableFieldDef;
import dev.architectury.mappingslayers.api.mutable.MutableMethodDef;
import dev.architectury.mappingslayers.api.mutable.MutableTinyTree;
import dev.architectury.mappingslayers.api.utils.MappingsUtils;
import org.apache.commons.io.IOUtils;
import org.cadixdev.lorenz.MappingSet;
import org.cadixdev.lorenz.io.srg.tsrg.TSrgReader;
@@ -76,8 +86,9 @@ public final class SrgMerger {
* @throws MappingException if the input tiny tree's default namespace is not 'official'
* or if an element mentioned in the SRG file does not have tiny mappings
*/
public static void mergeSrg(Path srg, Path tiny, Path out, boolean lenient) throws IOException, MappingException {
MappingSet arr = readSrg(srg);
public static void mergeSrg(Supplier<Path> mojmap, Path srg, Path tiny, Path out, boolean lenient) throws IOException, MappingException {
Map<String, List<MutableDescriptored>> addRegardlessSrgs = new HashMap<>();
MappingSet arr = readSrg(srg, mojmap, addRegardlessSrgs);
TinyTree foss;
try (BufferedReader reader = Files.newBufferedReader(tiny)) {
@@ -96,19 +107,19 @@ public final class SrgMerger {
List<TinyClass> classes = new ArrayList<>();
for (TopLevelClassMapping klass : arr.getTopLevelClassMappings()) {
classToTiny(foss, namespaces, klass, classes::add, lenient);
classToTiny(addRegardlessSrgs, foss, namespaces, klass, classes::add, lenient);
}
TinyFile file = new TinyFile(header, classes);
TinyV2Writer.write(file, out);
}
private static MappingSet readSrg(Path srg) throws IOException {
private static MappingSet readSrg(Path srg, Supplier<Path> mojmap, Map<String, List<MutableDescriptored>> addRegardlessSrgs) throws IOException {
try (BufferedReader reader = Files.newBufferedReader(srg)) {
String content = IOUtils.toString(reader);
if (content.startsWith("tsrg2")) {
return readTsrg2(content);
return readTsrg2(content, mojmap, addRegardlessSrgs);
} else {
try (TSrgReader srgReader = new TSrgReader(new StringReader(content))) {
return srgReader.read();
@@ -117,18 +128,45 @@ public final class SrgMerger {
}
}
private static MappingSet readTsrg2(String content) throws IOException {
private static MappingSet readTsrg2(String content, Supplier<Path> mojmap, Map<String, List<MutableDescriptored>> addRegardlessSrgs) throws IOException {
MappingSet set;
try (Tsrg2Utils.MappingsIO2LorenzWriter lorenzWriter = new Tsrg2Utils.MappingsIO2LorenzWriter(0, false)) {
TsrgReader.read(new StringReader(content), lorenzWriter);
set = lorenzWriter.read();
MutableTinyTree mojmapTree = readTsrg2ToTinyTree(mojmap.get());
for (MutableClassDef classDef : mojmapTree.getClassesMutable()) {
for (MutableMethodDef methodDef : classDef.getMethodsMutable()) {
String name = methodDef.getName(0);
if (name.indexOf('<') != 0 && name.equals(methodDef.getName(1))) {
addRegardlessSrgs.computeIfAbsent(classDef.getName(0), $ -> new ArrayList<>()).add(methodDef);
}
}
for (MutableFieldDef fieldDef : classDef.getFieldsMutable()) {
if (fieldDef.getName(0).equals(fieldDef.getName(1))) {
addRegardlessSrgs.computeIfAbsent(classDef.getName(0), $ -> new ArrayList<>()).add(fieldDef);
}
}
}
}
return set;
}
private static void classToTiny(TinyTree foss, List<String> namespaces, ClassMapping<?, ?> klass, Consumer<TinyClass> classConsumer, boolean lenient) {
private static MutableTinyTree readTsrg2ToTinyTree(Path path) throws IOException {
MutableTinyTree tree;
try (BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {
tree = MappingsUtils.deserializeFromTsrg2(IOUtils.toString(reader));
}
return tree;
}
private static void classToTiny(Map<String, List<MutableDescriptored>> addRegardlessSrgs, TinyTree foss, List<String> namespaces, ClassMapping<?, ?> klass, Consumer<TinyClass> classConsumer, boolean lenient) {
String obf = klass.getFullObfuscatedName();
String srg = klass.getFullDeobfuscatedName();
ClassDef classDef = foss.getDefaultNamespaceClassMap().get(obf);
@@ -153,9 +191,17 @@ public final class SrgMerger {
MethodDef def = CollectionUtil.find(
classDef.getMethods(),
m -> m.getName("official").equals(method.getObfuscatedName()) && m.getDescriptor("official").equals(method.getObfuscatedDescriptor())
).orElse(nullOrThrow(lenient, () -> new MappingException("Missing method: " + method.getFullObfuscatedName() + " (srg: " + method.getFullDeobfuscatedName() + ")")));
).orElse(null);
if (def == null) continue;
if (def == null) {
if (tryMatchRegardlessSrgs(addRegardlessSrgs, namespaces, obf, methods, method)) continue;
if (!lenient) {
throw new MappingException("Missing method: " + method.getFullObfuscatedName() + " (srg: " + method.getFullDeobfuscatedName() + ")");
}
continue;
}
List<String> methodNames = CollectionUtil.map(
namespaces,
@@ -190,10 +236,36 @@ public final class SrgMerger {
classConsumer.accept(tinyClass);
for (InnerClassMapping innerKlass : klass.getInnerClassMappings()) {
classToTiny(foss, namespaces, innerKlass, classConsumer, lenient);
classToTiny(addRegardlessSrgs, foss, namespaces, innerKlass, classConsumer, lenient);
}
}
private static boolean tryMatchRegardlessSrgs(Map<String, List<MutableDescriptored>> addRegardlessSrgs, List<String> namespaces, String obf,
List<TinyMethod> methods, MethodMapping method) {
List<MutableDescriptored> mutableDescriptoredList = addRegardlessSrgs.get(obf);
if (!method.getDeobfuscatedName().equals(method.getObfuscatedName())) {
for (MutableDescriptored descriptored : MoreObjects.firstNonNull(mutableDescriptoredList, Collections.<MutableDescriptored>emptyList())) {
if (descriptored.isMethod() && descriptored.getName(0).equals(method.getObfuscatedName()) && descriptored.getDescriptor(0).equals(method.getObfuscatedDescriptor())) {
List<String> methodNames = CollectionUtil.map(
namespaces,
namespace -> "srg".equals(namespace) ? method.getDeobfuscatedName() : method.getObfuscatedName()
);
methods.add(new TinyMethod(
method.getObfuscatedDescriptor(), methodNames,
/* parameters */ Collections.emptyList(),
/* locals */ Collections.emptyList(),
/* comments */ Collections.emptyList()
));
return true;
}
}
}
return false;
}
@Nullable
private static <T, X extends Exception> T nullOrThrow(boolean lenient, Supplier<X> exception) throws X {
if (lenient) {

View File

@@ -5,9 +5,18 @@ import java.io.Reader;
import java.io.UncheckedIOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import dev.architectury.mappingslayers.api.mutable.MutableClassDef;
import dev.architectury.mappingslayers.api.mutable.MutableFieldDef;
import dev.architectury.mappingslayers.api.mutable.MutableMethodDef;
import dev.architectury.mappingslayers.api.mutable.MutableParameterDef;
import dev.architectury.mappingslayers.api.mutable.MutableTinyMetadata;
import dev.architectury.mappingslayers.api.mutable.MutableTinyTree;
import dev.architectury.mappingslayers.api.utils.MappingsUtils;
import org.cadixdev.lorenz.MappingSet;
import org.cadixdev.lorenz.io.srg.tsrg.TSrgWriter;
import org.cadixdev.lorenz.model.ClassMapping;
@@ -31,7 +40,8 @@ public class Tsrg2Utils {
}, "srg", false, writer);
}
public static void writeTsrg(Consumer<MappingVisitor> visitorConsumer, String dstNamespace, boolean applyParameterMappings, Writer writer) throws IOException {
public static void writeTsrg(Consumer<MappingVisitor> visitorConsumer, String dstNamespace, boolean applyParameterMappings, Writer writer)
throws IOException {
MappingSet set;
try (MappingsIO2LorenzWriter lorenzWriter = new MappingsIO2LorenzWriter(dstNamespace, applyParameterMappings)) {
@@ -44,20 +54,54 @@ public class Tsrg2Utils {
}
}
public static void writeTsrg2(Consumer<MappingVisitor> visitorConsumer, Writer writer)
throws IOException {
MutableTinyTree tree;
try (MappingsIO2MappingsUtils w = new MappingsIO2MappingsUtils()) {
visitorConsumer.accept(w);
tree = w.read();
}
writer.write(MappingsUtils.serializeToTsrg2(tree));
}
// TODO Move this elsewhere
public static class MappingsIO2LorenzWriter extends ForwardingMappingVisitor implements MappingWriter {
public abstract static class MappingsIO2Others extends ForwardingMappingVisitor implements MappingWriter {
public MappingsIO2Others() {
super(new MemoryMappingTree());
}
public MappingTree tree() {
return (MappingTree) next;
}
@Override
public void close() throws IOException {
MappingTree tree = tree();
List<String> names = new ArrayList<>();
for (MappingTree.ClassMapping aClass : tree.getClasses()) {
names.add(aClass.getSrcName());
}
for (String name : names) {
tree.removeClass(name);
}
}
}
public static class MappingsIO2LorenzWriter extends MappingsIO2Others {
private final Object dstNamespaceUnresolved;
private int dstNamespace;
private boolean applyParameterMappings;
public MappingsIO2LorenzWriter(int dstNamespace, boolean applyParameterMappings) {
super(new MemoryMappingTree());
this.dstNamespaceUnresolved = dstNamespace;
this.applyParameterMappings = applyParameterMappings;
}
public MappingsIO2LorenzWriter(String dstNamespace, boolean applyParameterMappings) {
super(new MemoryMappingTree());
this.dstNamespaceUnresolved = dstNamespace;
this.applyParameterMappings = applyParameterMappings;
}
@@ -73,7 +117,7 @@ public class Tsrg2Utils {
}
public MappingSet read(final MappingSet mappings) throws IOException {
MappingTree tree = (MappingTree) next;
MappingTree tree = tree();
for (MappingTree.ClassMapping aClass : tree.getClasses()) {
ClassMapping<?, ?> lClass = mappings.getOrCreateClassMapping(aClass.getSrcName())
@@ -106,19 +150,60 @@ public class Tsrg2Utils {
return mappings;
}
}
@Override
public void close() throws IOException {
MappingTree tree = (MappingTree) next;
List<String> names = new ArrayList<>();
public static class MappingsIO2MappingsUtils extends MappingsIO2Others {
public MutableTinyTree read() {
MappingTree tree = tree();
int dstNamesSize = tree.getDstNamespaces().size();
List<String> namespaces = new ArrayList<>();
namespaces.add(tree.getSrcNamespace());
namespaces.addAll(tree.getDstNamespaces());
Map<String, String> properties = new HashMap<>();
for (Map.Entry<String, String> entry : tree.getMetadata()) {
properties.put(entry.getKey(), entry.getValue());
}
MutableTinyTree out = MappingsUtils.create(MutableTinyMetadata.create(2, 0, namespaces, properties));
for (MappingTree.ClassMapping aClass : tree.getClasses()) {
names.add(aClass.getSrcName());
MutableClassDef classDef = out.getOrCreateClass(aClass.getSrcName());
classDef.setComment(aClass.getComment());
for (int i = 0; i < dstNamesSize; i++) {
classDef.setName(i + 1, aClass.getDstName(i));
}
for (MappingTree.MethodMapping aMethod : aClass.getMethods()) {
MutableMethodDef methodDef = classDef.getOrCreateMethod(aMethod.getSrcName(), aMethod.getSrcDesc());
methodDef.setComment(aMethod.getComment());
for (int i = 0; i < dstNamesSize; i++) {
methodDef.setName(i + 1, aMethod.getDstName(i));
}
for (MappingTree.MethodArgMapping aMethodArg : aMethod.getArgs()) {
MutableParameterDef parameterDef = methodDef.getOrCreateParameter(aMethodArg.getLvIndex(), aMethodArg.getSrcName());
parameterDef.setComment(aMethodArg.getComment());
for (int i = 0; i < dstNamesSize; i++) {
parameterDef.setName(i + 1, aMethodArg.getDstName(i));
}
}
}
for (MappingTree.FieldMapping aField : aClass.getFields()) {
MutableFieldDef fieldDef = classDef.getOrCreateField(aField.getSrcName(), aField.getSrcDesc());
fieldDef.setComment(aField.getComment());
for (int i = 0; i < dstNamesSize; i++) {
fieldDef.setName(i + 1, aField.getDstName(i));
}
}
}
for (String name : names) {
tree.removeClass(name);
}
return out;
}
}
}