From 2f50208411e43ddd8ef0bb1e2e84ee1e8da40db3 Mon Sep 17 00:00:00 2001 From: ByMartrixx Date: Wed, 22 Sep 2021 00:09:28 -0300 Subject: [PATCH 1/5] Allow multiple input files and more than two namespaces --- .../commands/tinyv2/CommandMergeTinyV2.java | 187 +++++++++--------- .../net/fabricmc/stitch/tinyv2/MergeTest.java | 29 +++ src/test/resources/merge/expected.tiny | 6 + src/test/resources/merge/input-a.tiny | 6 + src/test/resources/merge/input-b.tiny | 6 + src/test/resources/merge/input-c.tiny | 6 + 6 files changed, 145 insertions(+), 95 deletions(-) create mode 100644 src/test/java/net/fabricmc/stitch/tinyv2/MergeTest.java create mode 100644 src/test/resources/merge/expected.tiny create mode 100644 src/test/resources/merge/input-a.tiny create mode 100644 src/test/resources/merge/input-b.tiny create mode 100644 src/test/resources/merge/input-c.tiny diff --git a/src/main/java/net/fabricmc/stitch/commands/tinyv2/CommandMergeTinyV2.java b/src/main/java/net/fabricmc/stitch/commands/tinyv2/CommandMergeTinyV2.java index 4257ec0..5321a1e 100644 --- a/src/main/java/net/fabricmc/stitch/commands/tinyv2/CommandMergeTinyV2.java +++ b/src/main/java/net/fabricmc/stitch/commands/tinyv2/CommandMergeTinyV2.java @@ -26,6 +26,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.function.Function; import java.util.regex.Pattern; @@ -38,6 +39,7 @@ import net.fabricmc.stitch.Command; import net.fabricmc.stitch.util.Pair; +// TODO: update javadoc /** * Merges a tiny file with 2 columns (namespaces) of mappings, with another tiny file that has * the same namespace as the first column and a different namespace as the second column. @@ -82,62 +84,59 @@ public CommandMergeTinyV2() { */ @Override public String getHelpString() { - return " "; + return " [...] "; } @Override public boolean isArgumentCountValid(int count) { - return count == 3; + return count >= 3; } @Override public void run(String[] args) throws IOException { - Path inputA = Paths.get(args[0]); - Path inputB = Paths.get(args[1]); - System.out.println("Reading " + inputA); - TinyFile tinyFileA = TinyV2Reader.read(inputA); - System.out.println("Reading " + inputB); - TinyFile tinyFileB = TinyV2Reader.read(inputB); - TinyHeader headerA = tinyFileA.getHeader(); - TinyHeader headerB = tinyFileB.getHeader(); - if (headerA.getNamespaces().size() != 2) { - throw new IllegalArgumentException(inputA + " must have exactly 2 namespaces."); - } - if (headerB.getNamespaces().size() != 2) { - throw new IllegalArgumentException(inputB + " must have exactly 2 namespaces."); + Path[] inputs = new Path[args.length - 1]; + for (int i = 0; i < args.length - 1; ++i) { + inputs[i] = Paths.get(args[i]); } + Path output = Paths.get(args[args.length - 1]); + + List tinyFiles = new ArrayList<>(); + TinyFile tinyFileA = TinyV2Reader.read(inputs[0]); + tinyFiles.add(tinyFileA); - if (!headerA.getNamespaces().get(0).equals(headerB.getNamespaces().get(0))) { - throw new IllegalArgumentException( - String.format("The input tiny files must have the same namespaces as the first column. " + - "(%s has %s while %s has %s)", - inputA, headerA.getNamespaces().get(0), inputB, headerB.getNamespaces().get(0)) - ); + TinyHeader headerA = tinyFileA.getHeader(); + String baseNamespace = headerA.getNamespaces().get(0); + for (int i = 1; i < inputs.length; ++i) { + Path input = inputs[i]; + TinyFile tinyFile = TinyV2Reader.read(input); + tinyFiles.add(tinyFile); + TinyHeader header = tinyFile.getHeader(); + List namespaces = header.getNamespaces(); + + if (!namespaces.get(0).equals(baseNamespace)) { + throw new IllegalArgumentException(String.format("The input tiny files must have the same namespaces as the first column. " + + "(%s has %s instead of %s)", input, namespaces.get(0), baseNamespace)); + } } - System.out.println("Merging " + inputA + " with " + inputB); - TinyFile mergedFile = merge(tinyFileA, tinyFileB); - TinyV2Writer.write(mergedFile, Paths.get(args[2])); - System.out.println("Merged mappings written to " + Paths.get(args[2])); - } + System.out.println("Merging " + inputs[0] + " with " + Arrays.stream(inputs).skip(1).map(Path::toString).collect(Collectors.joining(", "))); + TinyFile mergedFile = merge(tinyFiles); + TinyV2Writer.write(mergedFile, output); + System.out.println("Merged mappings written to " + output); + } - private TinyFile merge(TinyFile inputA, TinyFile inputB) { + private TinyFile merge(List inputs) { //TODO: how to merge properties? - TinyHeader mergedHeader = mergeHeaders(inputA.getHeader(), inputB.getHeader()); + TinyHeader mergedHeader = mergeHeaders(inputs.stream().map(TinyFile::getHeader).collect(Collectors.toList())); - List keyUnion = keyUnion(inputA.getClassEntries(), inputB.getClassEntries()); + List keyUnion = keyUnion(inputs.stream().map(TinyFile::getClassEntries).collect(Collectors.toList())); - Map inputAClasses = inputA.mapClassesByFirstNamespace(); - Map inputBClasses = inputB.mapClassesByFirstNamespace(); + List> inputsClasses = inputs.stream().map(TinyFile::mapClassesByFirstNamespace).collect(Collectors.toList()); List mergedClasses = map(keyUnion, key -> { - TinyClass classA = inputAClasses.get(key); - TinyClass classB = inputBClasses.get(key); - - classA = matchEnclosingClassIfNeeded(key, classA, inputAClasses); - classB = matchEnclosingClassIfNeeded(key, classB, inputBClasses); - return mergeClasses(key, classA, classB); + List classes = inputsClasses.stream().map(inputClasses -> matchEnclosingClassIfNeeded(key, inputClasses.get(key), inputClasses)).collect(Collectors.toList()); + return mergeClasses(key, classes); }); return new TinyFile(mergedHeader, mergedClasses); @@ -175,106 +174,101 @@ private String matchEnclosingClass(String sharedName, Map inp return sharedName; } + private TinyClass mergeClasses(String sharedClassName, List classes) { + List mergedNames = mergeNames(sharedClassName, classes); + List mergedComments = mergeComments(classes.stream().map(TinyClass::getComments).collect(Collectors.toList())); - private TinyClass mergeClasses(String sharedClassName, @Nonnull TinyClass classA, @Nonnull TinyClass classB) { - List mergedNames = mergeNames(sharedClassName, classA, classB); - List mergedComments = mergeComments(classA.getComments(), classB.getComments()); + List> methodKeyUnion = union(classes.stream().map(clazz -> mapToFirstNamespaceAndDescriptor(clazz).collect(Collectors.toList())).collect(Collectors.toList())); + List, TinyMethod>> methods = classes.stream().map(TinyClass::mapMethodsByFirstNamespaceAndDescriptor).collect(Collectors.toList()); + List mergedMethods = map(methodKeyUnion, (Pair k) -> + mergeMethods(k.getLeft(), methods.stream().map(method -> method.get(k)).collect(Collectors.toList()))); - List> methodKeyUnion = union(mapToFirstNamespaceAndDescriptor(classA), mapToFirstNamespaceAndDescriptor(classB)); - Map, TinyMethod> methodsA = classA.mapMethodsByFirstNamespaceAndDescriptor(); - Map, TinyMethod> methodsB = classB.mapMethodsByFirstNamespaceAndDescriptor(); - List mergedMethods = map(methodKeyUnion, - (Pair k) -> mergeMethods(k.getLeft(), methodsA.get(k), methodsB.get(k))); - - List fieldKeyUnion = keyUnion(classA.getFields(), classB.getFields()); - Map fieldsA = classA.mapFieldsByFirstNamespace(); - Map fieldsB = classB.mapFieldsByFirstNamespace(); - List mergedFields = map(fieldKeyUnion, k -> mergeFields(k, fieldsA.get(k), fieldsB.get(k))); + List fieldKeyUnion = keyUnion(classes.stream().map(TinyClass::getFields).collect(Collectors.toList())); + List> fields = classes.stream().map(TinyClass::mapFieldsByFirstNamespace).collect(Collectors.toList()); + List mergedFields = map(fieldKeyUnion, k -> mergeFields(k, fields.stream().map(map -> map.get(k)).collect(Collectors.toList()))); return new TinyClass(mergedNames, mergedMethods, mergedFields, mergedComments); } private static final TinyMethod EMPTY_METHOD = new TinyMethod(null, Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.emptyList()); + private TinyMethod mergeMethods(String sharedMethodName, List methods) { + List mergedNames = mergeNames(sharedMethodName, methods); + methods.replaceAll(method -> method == null ? EMPTY_METHOD : method); + List mergedComments = mergeComments(methods.stream().map(TinyMethod::getComments).collect(Collectors.toList())); - private TinyMethod mergeMethods(String sharedMethodName, @Nullable TinyMethod methodA, @Nullable TinyMethod methodB) { - List mergedNames = mergeNames(sharedMethodName, methodA, methodB); - if (methodA == null) methodA = EMPTY_METHOD; - if (methodB == null) methodB = EMPTY_METHOD; - List mergedComments = mergeComments(methodA.getComments(), methodB.getComments()); - - String descriptor = methodA.getMethodDescriptorInFirstNamespace() != null ? methodA.getMethodDescriptorInFirstNamespace() - : methodB.getMethodDescriptorInFirstNamespace(); + String descriptor = methods.get(0).getMethodDescriptorInFirstNamespace() != null ? methods.get(0).getMethodDescriptorInFirstNamespace() + : methods.get(1).getMethodDescriptorInFirstNamespace(); if (descriptor == null) throw new RuntimeException("no descriptor for key " + sharedMethodName); - - //TODO: this won't work too well when the first namespace is named or there is more than one named namespace (hack) List mergedParameters = new ArrayList<>(); - addParameters(methodA, mergedParameters, 2); - addParameters(methodB, mergedParameters, 1); + addParameters(methods, mergedParameters); List mergedLocalVariables = new ArrayList<>(); - addLocalVariables(methodA, mergedLocalVariables, 2); - addLocalVariables(methodB, mergedLocalVariables, 1); + addLocalVariables(methods, mergedLocalVariables); return new TinyMethod(descriptor, mergedNames, mergedParameters, mergedLocalVariables, mergedComments); } - private void addParameters(TinyMethod method, List addTo, int emptySpacePos) { - for (TinyMethodParameter localVariable : method.getParameters()) { - List names = new ArrayList<>(localVariable.getParameterNames()); - names.add(emptySpacePos, ""); - addTo.add(new TinyMethodParameter(localVariable.getLvIndex(), names, localVariable.getComments())); + private void addParameters(List methods, List addTo) { + for (TinyMethod method : methods) { + for (TinyMethodParameter localVariable : method.getParameters()) { + List names = new ArrayList<>(localVariable.getParameterNames()); + addTo.add(new TinyMethodParameter(localVariable.getLvIndex(), names, localVariable.getComments())); + } } } - private void addLocalVariables(TinyMethod method, List addTo, int emptySpacePos) { - for (TinyLocalVariable localVariable : method.getLocalVariables()) { - List names = new ArrayList<>(localVariable.getLocalVariableNames()); - names.add(emptySpacePos, ""); - addTo.add(new TinyLocalVariable(localVariable.getLvIndex(), localVariable.getLvStartOffset(), - localVariable.getLvTableIndex(), names, localVariable.getComments())); + private void addLocalVariables(List methods, List addTo) { + for (TinyMethod method : methods) { + for (TinyLocalVariable localVariable : method.getLocalVariables()) { + List names = new ArrayList<>(localVariable.getLocalVariableNames()); + addTo.add(new TinyLocalVariable(localVariable.getLvIndex(), localVariable.getLvStartOffset(), + localVariable.getLvTableIndex(), names, localVariable.getComments())); + } } } + private TinyField mergeFields(String sharedFieldName, List fields) { + List mergedNames = mergeNames(sharedFieldName, fields); + List mergedComments = mergeComments(fields.stream().map(field -> field != null ? field.getComments() : Collections.emptyList()).collect(Collectors.toList())); - private TinyField mergeFields(String sharedFieldName, @Nullable TinyField fieldA, @Nullable TinyField fieldB) { - List mergedNames = mergeNames(sharedFieldName, fieldA, fieldB); - List mergedComments = mergeComments(fieldA != null ? fieldA.getComments() : Collections.emptyList(), - fieldB != null ? fieldB.getComments() : Collections.emptyList()); - - String descriptor = fieldA != null ? fieldA.getFieldDescriptorInFirstNamespace() - : fieldB != null ? fieldB.getFieldDescriptorInFirstNamespace() : null; + String descriptor = fields.stream().filter(Objects::nonNull).findFirst().map(TinyField::getFieldDescriptorInFirstNamespace).orElse(null); if (descriptor == null) throw new RuntimeException("no descriptor for key " + sharedFieldName); return new TinyField(descriptor, mergedNames, mergedComments); } - private TinyHeader mergeHeaders(TinyHeader headerA, TinyHeader headerB) { + private TinyHeader mergeHeaders(List headers) { + TinyHeader headerA = headers.get(0); List namespaces = new ArrayList<>(headerA.getNamespaces()); - namespaces.add(headerB.getNamespaces().get(1)); + for (int i = 1; i < headers.size(); ++i) { + for (String namespace : headers.get(i).getNamespaces()) { + if (!namespaces.contains(namespace)) { + namespaces.add(namespace); + } + } + } // TODO: how should versions and properties be merged? return new TinyHeader(namespaces, headerA.getMajorVersion(), headerA.getMinorVersion(), headerA.getProperties()); } - private List mergeComments(Collection commentsA, Collection commentsB) { - return union(commentsA, commentsB); + private List mergeComments(List> comments) { + return union(comments); } - private List keyUnion(Collection mappingsA, Collection mappingB) { - return union(mappingsA.stream().map(m -> m.getMapping().get(0)), mappingB.stream().map(m -> m.getMapping().get(0))); + private List keyUnion(List> mappings) { + return union(mappings.stream().map(c -> c.stream().map(m -> m.getMapping().get(0)).collect(Collectors.toList())).collect(Collectors.toList())); } private Stream> mapToFirstNamespaceAndDescriptor(TinyClass tinyClass) { return tinyClass.getMethods().stream().map(m -> Pair.of(m.getMapping().get(0), m.getMethodDescriptorInFirstNamespace())); } - - private List mergeNames(String key, @Nullable Mapping mappingA, @Nullable Mapping mappingB) { + private List mergeNames(String key, List mappings) { List merged = new ArrayList<>(); merged.add(key); - merged.add(mappingExists(mappingA) ? mappingA.getMapping().get(1) : key); - merged.add(mappingExists(mappingB) ? mappingB.getMapping().get(1) : key); + mappings.forEach(mapping -> merged.add(mappingExists(mapping) ? mapping.getMapping().get(1) : key)); return merged; } @@ -283,8 +277,12 @@ private boolean mappingExists(@Nullable Mapping mapping) { return mapping != null && !mapping.getMapping().get(1).isEmpty(); } - private List union(Stream list1, Stream list2) { - return union(list1.collect(Collectors.toList()), list2.collect(Collectors.toList())); + private List union(List> lists) { + Set set = new HashSet<>(); + + lists.forEach(set::addAll); + + return new ArrayList<>(set); } private List union(Collection list1, Collection list2) { @@ -303,5 +301,4 @@ private static String escape(String str) { private List map(List from, Function mapper) { return from.stream().map(mapper).collect(Collectors.toList()); } - } diff --git a/src/test/java/net/fabricmc/stitch/tinyv2/MergeTest.java b/src/test/java/net/fabricmc/stitch/tinyv2/MergeTest.java new file mode 100644 index 0000000..da7a1a5 --- /dev/null +++ b/src/test/java/net/fabricmc/stitch/tinyv2/MergeTest.java @@ -0,0 +1,29 @@ +package net.fabricmc.stitch.tinyv2; + +import net.fabricmc.stitch.commands.tinyv2.CommandMergeTinyV2; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; + +import static org.junit.jupiter.api.Assertions.*; + +public class MergeTest { + private static final Path DIR = new File(MergeTest.class.getClassLoader().getResource("merge").getPath()).toPath().toAbsolutePath(); + + @Test + public void test() throws Exception { + Path expectedOutput = DIR.resolve("expected.tiny"); + Path output = Files.createTempFile("stitch-merge-result-", ".tiny"); + Path inputA = DIR.resolve("input-a.tiny"); + Path inputB = DIR.resolve("input-b.tiny"); + Path inputC = DIR.resolve("input-c.tiny"); + new CommandMergeTinyV2().run(new String[]{inputA.toString(), inputB.toString(), inputC.toString(), output.toString()}); + + String expectedOutputContent = new String(Files.readAllBytes(expectedOutput), StandardCharsets.UTF_8).replace("\r\n", "\n"); + String outputContent = new String(Files.readAllBytes(output), StandardCharsets.UTF_8).replace("\r\n", "\n"); + assertEquals(expectedOutputContent, outputContent); + } +} diff --git a/src/test/resources/merge/expected.tiny b/src/test/resources/merge/expected.tiny new file mode 100644 index 0000000..5f140fd --- /dev/null +++ b/src/test/resources/merge/expected.tiny @@ -0,0 +1,6 @@ +tiny 2 0 official hashed intermediary named +c a net/minecraft/unmapped/C_lctoxfsg net/minecraft/unmapped/C_lctoxfsg net/minecraft/util/math/MathConstants + f F a f_ygxirswm field_29658 PI + f F b f_ncoyhkkx field_29659 DEGREES_PER_RADIAN + f F c f_vaqzaaae field_29660 RADIANS_PER_DEGREE + f F d f_jhuobxwz field_29661 EPSILON diff --git a/src/test/resources/merge/input-a.tiny b/src/test/resources/merge/input-a.tiny new file mode 100644 index 0000000..03452f1 --- /dev/null +++ b/src/test/resources/merge/input-a.tiny @@ -0,0 +1,6 @@ +tiny 2 0 official hashed +c a net/minecraft/unmapped/C_lctoxfsg + f F a f_ygxirswm + f F b f_ncoyhkkx + f F c f_vaqzaaae + f F d f_jhuobxwz \ No newline at end of file diff --git a/src/test/resources/merge/input-b.tiny b/src/test/resources/merge/input-b.tiny new file mode 100644 index 0000000..fa50ee5 --- /dev/null +++ b/src/test/resources/merge/input-b.tiny @@ -0,0 +1,6 @@ +tiny 2 0 official intermediary +c a net/minecraft/unmapped/C_lctoxfsg + f F a field_29658 + f F b field_29659 + f F c field_29660 + f F d field_29661 \ No newline at end of file diff --git a/src/test/resources/merge/input-c.tiny b/src/test/resources/merge/input-c.tiny new file mode 100644 index 0000000..f4c6248 --- /dev/null +++ b/src/test/resources/merge/input-c.tiny @@ -0,0 +1,6 @@ +tiny 2 0 official named +c a net/minecraft/util/math/MathConstants + f F a PI + f F b DEGREES_PER_RADIAN + f F c RADIANS_PER_DEGREE + f F d EPSILON \ No newline at end of file From 6b6e38f23262c89b5b4f03416aa9770c0c57af05 Mon Sep 17 00:00:00 2001 From: ByMartrixx Date: Wed, 22 Sep 2021 00:15:30 -0300 Subject: [PATCH 2/5] Update MergeTest --- .../stitch/commands/tinyv2/CommandMergeTinyV2.java | 1 + src/test/resources/merge/expected.tiny | 10 ++++++++++ src/test/resources/merge/input-a.tiny | 8 +++++++- src/test/resources/merge/input-b.tiny | 8 +++++++- src/test/resources/merge/input-c.tiny | 12 +++++++++++- 5 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/main/java/net/fabricmc/stitch/commands/tinyv2/CommandMergeTinyV2.java b/src/main/java/net/fabricmc/stitch/commands/tinyv2/CommandMergeTinyV2.java index 5321a1e..96ea419 100644 --- a/src/main/java/net/fabricmc/stitch/commands/tinyv2/CommandMergeTinyV2.java +++ b/src/main/java/net/fabricmc/stitch/commands/tinyv2/CommandMergeTinyV2.java @@ -201,6 +201,7 @@ private TinyMethod mergeMethods(String sharedMethodName, List method : methods.get(1).getMethodDescriptorInFirstNamespace(); if (descriptor == null) throw new RuntimeException("no descriptor for key " + sharedMethodName); + // TODO: Fix parameters List mergedParameters = new ArrayList<>(); addParameters(methods, mergedParameters); diff --git a/src/test/resources/merge/expected.tiny b/src/test/resources/merge/expected.tiny index 5f140fd..b55ca2d 100644 --- a/src/test/resources/merge/expected.tiny +++ b/src/test/resources/merge/expected.tiny @@ -4,3 +4,13 @@ c a net/minecraft/unmapped/C_lctoxfsg net/minecraft/unmapped/C_lctoxfsg net/mine f F b f_ncoyhkkx field_29659 DEGREES_PER_RADIAN f F c f_vaqzaaae field_29660 RADIANS_PER_DEGREE f F d f_jhuobxwz field_29661 EPSILON +c c net/minecraft/unmapped/C_ffukturc net/minecraft/class_4581 net/minecraft/util/math/Matrix3f + m (Lc;)V + p 1 source + m (Ld;)V + p 1 matrix + m (Lg;)V + p 1 quaternion + m ()V a m_jdnetyjq method_22847 transpose + m (F)V a m_asnpwjdg method_23274 multiply + p 1 scalar diff --git a/src/test/resources/merge/input-a.tiny b/src/test/resources/merge/input-a.tiny index 03452f1..3037301 100644 --- a/src/test/resources/merge/input-a.tiny +++ b/src/test/resources/merge/input-a.tiny @@ -3,4 +3,10 @@ c a net/minecraft/unmapped/C_lctoxfsg f F a f_ygxirswm f F b f_ncoyhkkx f F c f_vaqzaaae - f F d f_jhuobxwz \ No newline at end of file + f F d f_jhuobxwz +c c net/minecraft/unmapped/C_ffukturc + m (Lc;)V + m (Ld;)V + m (Lg;)V + m ()V a m_jdnetyjq + m (F)V a m_asnpwjdg \ No newline at end of file diff --git a/src/test/resources/merge/input-b.tiny b/src/test/resources/merge/input-b.tiny index fa50ee5..68ed783 100644 --- a/src/test/resources/merge/input-b.tiny +++ b/src/test/resources/merge/input-b.tiny @@ -3,4 +3,10 @@ c a net/minecraft/unmapped/C_lctoxfsg f F a field_29658 f F b field_29659 f F c field_29660 - f F d field_29661 \ No newline at end of file + f F d field_29661 +c c net/minecraft/class_4581 + m (Lc;)V + m (Ld;)V + m (Lg;)V + m ()V a method_22847 + m (F)V a method_23274 \ No newline at end of file diff --git a/src/test/resources/merge/input-c.tiny b/src/test/resources/merge/input-c.tiny index f4c6248..6da8528 100644 --- a/src/test/resources/merge/input-c.tiny +++ b/src/test/resources/merge/input-c.tiny @@ -3,4 +3,14 @@ c a net/minecraft/util/math/MathConstants f F a PI f F b DEGREES_PER_RADIAN f F c RADIANS_PER_DEGREE - f F d EPSILON \ No newline at end of file + f F d EPSILON +c c net/minecraft/util/math/Matrix3f + m (Lc;)V + p 1 source + m (Ld;)V + p 1 matrix + m (Lg;)V + p 1 quaternion + m ()V a transpose + m (F)V a multiply + p 1 scalar \ No newline at end of file From 4be763c714ccd2b4af1941ee4ca47836af9eaff6 Mon Sep 17 00:00:00 2001 From: ByMartrixx Date: Wed, 22 Sep 2021 15:53:22 -0300 Subject: [PATCH 3/5] Fix merging names for more than two namespaces in a single file --- .../commands/tinyv2/CommandMergeTinyV2.java | 17 ++++++++++++- src/test/resources/merge/expected.tiny | 24 +++++++++---------- src/test/resources/merge/input-a.tiny | 24 +++++++++---------- src/test/resources/merge/input-b.tiny | 4 ++-- 4 files changed, 42 insertions(+), 27 deletions(-) diff --git a/src/main/java/net/fabricmc/stitch/commands/tinyv2/CommandMergeTinyV2.java b/src/main/java/net/fabricmc/stitch/commands/tinyv2/CommandMergeTinyV2.java index 96ea419..726f2d8 100644 --- a/src/main/java/net/fabricmc/stitch/commands/tinyv2/CommandMergeTinyV2.java +++ b/src/main/java/net/fabricmc/stitch/commands/tinyv2/CommandMergeTinyV2.java @@ -105,6 +105,10 @@ public void run(String[] args) throws IOException { tinyFiles.add(tinyFileA); TinyHeader headerA = tinyFileA.getHeader(); + if (headerA.getNamespaces().size() < 2) { + throw new IllegalArgumentException(inputs[0] + " must have at least 2 namespaces."); + } + String baseNamespace = headerA.getNamespaces().get(0); for (int i = 1; i < inputs.length; ++i) { Path input = inputs[i]; @@ -113,6 +117,10 @@ public void run(String[] args) throws IOException { TinyHeader header = tinyFile.getHeader(); List namespaces = header.getNamespaces(); + if (header.getNamespaces().size() < 2) { + throw new IllegalArgumentException(inputs[i] + " must have at least 2 namespaces."); + } + if (!namespaces.get(0).equals(baseNamespace)) { throw new IllegalArgumentException(String.format("The input tiny files must have the same namespaces as the first column. " + "(%s has %s instead of %s)", input, namespaces.get(0), baseNamespace)); @@ -269,7 +277,14 @@ private Stream> mapToFirstNamespaceAndDescriptor(TinyClass private List mergeNames(String key, List mappings) { List merged = new ArrayList<>(); merged.add(key); - mappings.forEach(mapping -> merged.add(mappingExists(mapping) ? mapping.getMapping().get(1) : key)); + mappings.forEach(mapping -> { + if (mapping != null) { + for (int i = 1; i < mapping.getMapping().size(); ++i) { + String m = mapping.getMapping().get(i); + merged.add(!m.isEmpty() ? m : key); + } + } + }); return merged; } diff --git a/src/test/resources/merge/expected.tiny b/src/test/resources/merge/expected.tiny index b55ca2d..9fc307c 100644 --- a/src/test/resources/merge/expected.tiny +++ b/src/test/resources/merge/expected.tiny @@ -1,16 +1,16 @@ -tiny 2 0 official hashed intermediary named -c a net/minecraft/unmapped/C_lctoxfsg net/minecraft/unmapped/C_lctoxfsg net/minecraft/util/math/MathConstants - f F a f_ygxirswm field_29658 PI - f F b f_ncoyhkkx field_29659 DEGREES_PER_RADIAN - f F c f_vaqzaaae field_29660 RADIANS_PER_DEGREE - f F d f_jhuobxwz field_29661 EPSILON -c c net/minecraft/unmapped/C_ffukturc net/minecraft/class_4581 net/minecraft/util/math/Matrix3f - m (Lc;)V +tiny 2 0 official hashed mojmap intermediary named +c a net/minecraft/unmapped/C_lctoxfsg com/mojang/math/Constants net/minecraft/class_5973 net/minecraft/util/math/MathConstants + f F a f_ygxirswm PI field_29658 PI + f F b f_ncoyhkkx RAD_TO_DEG field_29659 DEGREES_PER_RADIAN + f F c f_vaqzaaae DEG_TO_RAD field_29660 RADIANS_PER_DEGREE + f F d f_jhuobxwz EPSILON field_29661 EPSILON +c c net/minecraft/unmapped/C_ffukturc com/mojang/math/Matrix3f net/minecraft/class_4581 net/minecraft/util/math/Matrix3f + m (Lc;)V p 1 source - m (Ld;)V + m (Ld;)V p 1 matrix - m (Lg;)V + m (Lg;)V p 1 quaternion - m ()V a m_jdnetyjq method_22847 transpose - m (F)V a m_asnpwjdg method_23274 multiply + m ()V a m_jdnetyjq transpose method_22847 transpose + m (F)V a m_asnpwjdg mul method_23274 multiply p 1 scalar diff --git a/src/test/resources/merge/input-a.tiny b/src/test/resources/merge/input-a.tiny index 3037301..33609a1 100644 --- a/src/test/resources/merge/input-a.tiny +++ b/src/test/resources/merge/input-a.tiny @@ -1,12 +1,12 @@ -tiny 2 0 official hashed -c a net/minecraft/unmapped/C_lctoxfsg - f F a f_ygxirswm - f F b f_ncoyhkkx - f F c f_vaqzaaae - f F d f_jhuobxwz -c c net/minecraft/unmapped/C_ffukturc - m (Lc;)V - m (Ld;)V - m (Lg;)V - m ()V a m_jdnetyjq - m (F)V a m_asnpwjdg \ No newline at end of file +tiny 2 0 official hashed mojmap +c a net/minecraft/unmapped/C_lctoxfsg com/mojang/math/Constants + f F a f_ygxirswm PI + f F b f_ncoyhkkx RAD_TO_DEG + f F c f_vaqzaaae DEG_TO_RAD + f F d f_jhuobxwz EPSILON +c c net/minecraft/unmapped/C_ffukturc com/mojang/math/Matrix3f + m (Lc;)V + m (Ld;)V + m (Lg;)V + m ()V a m_jdnetyjq transpose + m (F)V a m_asnpwjdg mul diff --git a/src/test/resources/merge/input-b.tiny b/src/test/resources/merge/input-b.tiny index 68ed783..8443aaa 100644 --- a/src/test/resources/merge/input-b.tiny +++ b/src/test/resources/merge/input-b.tiny @@ -1,5 +1,5 @@ tiny 2 0 official intermediary -c a net/minecraft/unmapped/C_lctoxfsg +c a net/minecraft/class_5973 f F a field_29658 f F b field_29659 f F c field_29660 @@ -9,4 +9,4 @@ c c net/minecraft/class_4581 m (Ld;)V m (Lg;)V m ()V a method_22847 - m (F)V a method_23274 \ No newline at end of file + m (F)V a method_23274 From f339ef789dc12ec451a56a1bcb8e34e14c3a709f Mon Sep 17 00:00:00 2001 From: ByMartrixx Date: Wed, 22 Sep 2021 16:01:36 -0300 Subject: [PATCH 4/5] Update javadoc --- .../commands/tinyv2/CommandMergeTinyV2.java | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/main/java/net/fabricmc/stitch/commands/tinyv2/CommandMergeTinyV2.java b/src/main/java/net/fabricmc/stitch/commands/tinyv2/CommandMergeTinyV2.java index 726f2d8..4522937 100644 --- a/src/main/java/net/fabricmc/stitch/commands/tinyv2/CommandMergeTinyV2.java +++ b/src/main/java/net/fabricmc/stitch/commands/tinyv2/CommandMergeTinyV2.java @@ -41,11 +41,11 @@ // TODO: update javadoc /** - * Merges a tiny file with 2 columns (namespaces) of mappings, with another tiny file that has - * the same namespace as the first column and a different namespace as the second column. - * The first column of the output will contain the shared namespace, - * the second column of the output would be the second namespace of input a, - * and the third column of the output would be the second namespace of input b + * Merges a tiny file with at least 2 columns (namespaces) of mappings, with another tiny + * file that has the same namespace as the first column and different namespaces as the + * other columns. The first column of the output will contain the shared namespace, the + * next columns of the output would be the namespaces of all inputs, excluding the first + * column namespace *

* Descriptors will remain as-is (using the namespace of the first column) *

@@ -67,12 +67,6 @@ * intermediary named official * c net/minecraft/class_123 net/minecraft/somePackage/someClass a * m (Lnet/minecraft/class_124;)V method_1234 someMethod a - *

- *

- * After intermediary-named mappings are obtained, - * and official-intermediary mappings are obtained and swapped using CommandReorderTinyV2, Loom merges them using this command, - * and then reorders it to official-intermediary-named using CommandReorderTinyV2 again. - * This is a convenient way of storing all the mappings in Loom. */ public class CommandMergeTinyV2 extends Command { public CommandMergeTinyV2() { From 22394c5a799dff84d25a7193aa52713e63deb679 Mon Sep 17 00:00:00 2001 From: ByMartrixx Date: Wed, 22 Sep 2021 16:05:09 -0300 Subject: [PATCH 5/5] Remove a TODO --- .../net/fabricmc/stitch/commands/tinyv2/CommandMergeTinyV2.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/net/fabricmc/stitch/commands/tinyv2/CommandMergeTinyV2.java b/src/main/java/net/fabricmc/stitch/commands/tinyv2/CommandMergeTinyV2.java index 4522937..dbd4ba2 100644 --- a/src/main/java/net/fabricmc/stitch/commands/tinyv2/CommandMergeTinyV2.java +++ b/src/main/java/net/fabricmc/stitch/commands/tinyv2/CommandMergeTinyV2.java @@ -39,7 +39,6 @@ import net.fabricmc.stitch.Command; import net.fabricmc.stitch.util.Pair; -// TODO: update javadoc /** * Merges a tiny file with at least 2 columns (namespaces) of mappings, with another tiny * file that has the same namespace as the first column and different namespaces as the