diff --git a/README.md b/README.md
index 404f9fd3..6db6d8e2 100644
--- a/README.md
+++ b/README.md
@@ -31,7 +31,7 @@ Lorenz releases can be obtained through Maven Central:
### Gradle
```groovy
-implementation 'org.cadixdev:lorenz:0.5.6'
+implementation 'org.cadixdev:lorenz:0.5.7'
```
### Maven
@@ -40,7 +40,7 @@ implementation 'org.cadixdev:lorenz:0.5.6'
org.cadixdev
lorenz
- 0.5.6
+ 0.5.7
```
diff --git a/build.gradle.kts b/build.gradle.kts
index a65ae902..b8412107 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -15,7 +15,7 @@ val isSnapshot = version.toString().endsWith("-SNAPSHOT")
allprojects {
group = "org.cadixdev"
- version = "0.5.6"
+ version = "0.5.7"
}
subprojects {
diff --git a/changelogs/0.5.7.md b/changelogs/0.5.7.md
new file mode 100644
index 00000000..fe2867c4
--- /dev/null
+++ b/changelogs/0.5.7.md
@@ -0,0 +1,14 @@
+Lorenz 0.5.7
+===
+
+## Fixes
+
+- CSRG and TSRG now ignore package mappings, rather than erroneously reading them
+ as class mappings.
+- `MappingSet#deobfuscate(FieldType)` will now correctly de-obfuscate object types
+ of inner classes, where the parent class has a mapping - but the inner class
+ does not.
+- [GH-29]\: Avoid inheriting field mappings from a parent where the child class has
+ a field of its own, of the same signature.
+
+[GH-29]: https://github.com/CadixDev/Lorenz/issues/29
diff --git a/lorenz/src/main/java/org/cadixdev/lorenz/MappingSet.java b/lorenz/src/main/java/org/cadixdev/lorenz/MappingSet.java
index bf6f40b2..62847337 100644
--- a/lorenz/src/main/java/org/cadixdev/lorenz/MappingSet.java
+++ b/lorenz/src/main/java/org/cadixdev/lorenz/MappingSet.java
@@ -36,6 +36,7 @@
import org.cadixdev.lorenz.model.TopLevelClassMapping;
import org.cadixdev.lorenz.model.jar.CascadingFieldTypeProvider;
import org.cadixdev.lorenz.model.jar.FieldTypeProvider;
+import org.cadixdev.lorenz.util.BinaryTool;
import org.cadixdev.lorenz.util.Reversible;
import java.util.Collection;
@@ -265,9 +266,27 @@ default FieldType deobfuscate(final FieldType type) {
}
else if (type instanceof ObjectType) {
final ObjectType obj = (ObjectType) type;
- return this.getClassMapping(obj.getClassName())
- .map(m -> new ObjectType(m.getFullDeobfuscatedName()))
- .orElse(obj);
+
+ final String[] name = BinaryTool.from(obj.getClassName());
+
+ ClassMapping, ?> currentClass = this.getClassMapping(name[0]).orElse(null);
+ if (currentClass == null) {
+ return type;
+ }
+
+ for (int i = 1; i < name.length; i++) {
+ final ClassMapping, ?> thisClass = currentClass.getInnerClassMapping(name[i]).orElse(null);
+ if (thisClass == null) {
+ final String[] result = new String[name.length - i + 1];
+ result[0] = currentClass.getFullDeobfuscatedName();
+ System.arraycopy(name, i, result, 1, name.length - i);
+
+ return new ObjectType(BinaryTool.to(result));
+ }
+ currentClass = thisClass;
+ }
+
+ return new ObjectType(currentClass.getFullDeobfuscatedName());
}
return type;
}
diff --git a/lorenz/src/main/java/org/cadixdev/lorenz/impl/model/AbstractClassMappingImpl.java b/lorenz/src/main/java/org/cadixdev/lorenz/impl/model/AbstractClassMappingImpl.java
index e9084243..e8d0f5cc 100644
--- a/lorenz/src/main/java/org/cadixdev/lorenz/impl/model/AbstractClassMappingImpl.java
+++ b/lorenz/src/main/java/org/cadixdev/lorenz/impl/model/AbstractClassMappingImpl.java
@@ -226,6 +226,12 @@ public void complete(final InheritanceProvider provider, final InheritanceProvid
parentMappings.complete(provider, parent);
for (final FieldMapping mapping : parentMappings.getFieldMappings()) {
+ // If the class has its own field that satisfies the parent's signature,
+ // then we shouldn't inherit the mapping
+ if (this.computeFieldMapping(mapping.getSignature()).isPresent()) {
+ continue;
+ }
+
if (parent.canInherit(info, mapping.getSignature())) {
this.fields.putIfAbsent(mapping.getSignature(), mapping);
}
diff --git a/lorenz/src/main/java/org/cadixdev/lorenz/io/TextMappingsReader.java b/lorenz/src/main/java/org/cadixdev/lorenz/io/TextMappingsReader.java
index de06e032..c9160218 100644
--- a/lorenz/src/main/java/org/cadixdev/lorenz/io/TextMappingsReader.java
+++ b/lorenz/src/main/java/org/cadixdev/lorenz/io/TextMappingsReader.java
@@ -107,6 +107,16 @@ protected Processor(final MappingSet mappings) {
this.mappings = mappings;
}
+ /**
+ * Gets the mapping set being read into by the processor.
+ *
+ * @return The mappings
+ * @since 0.5.7
+ */
+ public MappingSet getMappings() {
+ return this.mappings;
+ }
+
}
}
diff --git a/lorenz/src/main/java/org/cadixdev/lorenz/io/srg/csrg/CSrgReader.java b/lorenz/src/main/java/org/cadixdev/lorenz/io/srg/csrg/CSrgReader.java
index 36fd40d2..8ab21419 100644
--- a/lorenz/src/main/java/org/cadixdev/lorenz/io/srg/csrg/CSrgReader.java
+++ b/lorenz/src/main/java/org/cadixdev/lorenz/io/srg/csrg/CSrgReader.java
@@ -87,14 +87,22 @@ public void accept(final String rawLine) {
final String[] split = SPACE.split(line);
final int len = split.length;
- // Process class mappings
+ // Process class/package mappings
if (len == CLASS_MAPPING_ELEMENT_COUNT) {
final String obfuscatedName = split[0];
final String deobfuscatedName = split[1];
- // Get mapping, and set de-obfuscated name
- this.mappings.getOrCreateClassMapping(obfuscatedName)
- .setDeobfuscatedName(deobfuscatedName);
+ // Package mappings
+ if (obfuscatedName.endsWith("/")) {
+ // Lorenz doesn't currently support package mappings, though they are an SRG feature.
+ // For now, Lorenz will just silently ignore those mappings.
+ }
+ // Class mappings
+ else {
+ // Get mapping, and set de-obfuscated name
+ this.mappings.getOrCreateClassMapping(obfuscatedName)
+ .setDeobfuscatedName(deobfuscatedName);
+ }
}
// Process field mapping
else if (len == FIELD_MAPPING_ELEMENT_COUNT) {
diff --git a/lorenz/src/main/java/org/cadixdev/lorenz/io/srg/tsrg/TSrgReader.java b/lorenz/src/main/java/org/cadixdev/lorenz/io/srg/tsrg/TSrgReader.java
index 7eb96752..2b96cb4f 100644
--- a/lorenz/src/main/java/org/cadixdev/lorenz/io/srg/tsrg/TSrgReader.java
+++ b/lorenz/src/main/java/org/cadixdev/lorenz/io/srg/tsrg/TSrgReader.java
@@ -90,14 +90,22 @@ public void accept(final String rawLine) {
final String[] split = SPACE.split(line);
final int len = split.length;
- // Process class mappings
+ // Process class/package mappings
if (!split[0].startsWith("\t") && len == CLASS_MAPPING_ELEMENT_COUNT) {
final String obfuscatedName = split[0];
final String deobfuscatedName = split[1];
- // Get mapping, and set de-obfuscated name
- this.currentClass = this.mappings.getOrCreateClassMapping(obfuscatedName);
- this.currentClass.setDeobfuscatedName(deobfuscatedName);
+ // Package mappings
+ if (obfuscatedName.endsWith("/")) {
+ // Lorenz doesn't currently support package mappings, though they are an SRG feature.
+ // For now, Lorenz will just silently ignore those mappings.
+ }
+ // Class mappings
+ else {
+ // Get mapping, and set de-obfuscated name
+ this.currentClass = this.mappings.getOrCreateClassMapping(obfuscatedName);
+ this.currentClass.setDeobfuscatedName(deobfuscatedName);
+ }
}
else if (split[0].startsWith("\t") && this.currentClass != null) {
final String obfuscatedName = split[0].replace("\t", "");
diff --git a/lorenz/src/main/java/org/cadixdev/lorenz/util/BinaryTool.java b/lorenz/src/main/java/org/cadixdev/lorenz/util/BinaryTool.java
new file mode 100644
index 00000000..bd2a5b83
--- /dev/null
+++ b/lorenz/src/main/java/org/cadixdev/lorenz/util/BinaryTool.java
@@ -0,0 +1,72 @@
+/*
+ * This file is part of Lorenz, licensed under the MIT License (MIT).
+ *
+ * Copyright (c) Jamie Mansfield
+ * Copyright (c) contributors
+ *
+ * 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 org.cadixdev.lorenz.util;
+
+/**
+ * A utility for working with binary names in Lorenz.
+ *
+ * @author Jamie Mansfield
+ * @since 0.5.7
+ */
+public final class BinaryTool {
+
+ /**
+ * Gets the split hierarchy of a binary name.
+ *
+ * For example, calling {@code from("a$b$c"}} would produce
+ * {@code ["a", "b", "c"]}.
+ *
+ * @param binaryName The binary name
+ * @return The name hierarchy
+ */
+ public static String[] from(final String binaryName) {
+ return binaryName.split("\\$");
+ }
+
+ /**
+ * Gets the binary name for a split hierarchy.
+ *
+ * @param name The hierarchy
+ * @return The binary name
+ */
+ public static String to(final String[] name) {
+ final StringBuilder builder = new StringBuilder();
+
+ for (int i = 0; i < name.length; i++) {
+ builder.append(name[i]);
+
+ if (i != name.length - 1) {
+ builder.append('$');
+ }
+ }
+
+ return builder.toString();
+ }
+
+ private BinaryTool() {
+ }
+
+}
diff --git a/lorenz/src/test/java/org/cadixdev/lorenz/test/CompletionTest.java b/lorenz/src/test/java/org/cadixdev/lorenz/test/CompletionTest.java
new file mode 100644
index 00000000..35c1a517
--- /dev/null
+++ b/lorenz/src/test/java/org/cadixdev/lorenz/test/CompletionTest.java
@@ -0,0 +1,182 @@
+/*
+ * This file is part of Lorenz, licensed under the MIT License (MIT).
+ *
+ * Copyright (c) Jamie Mansfield
+ * Copyright (c) contributors
+ *
+ * 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 org.cadixdev.lorenz.test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.cadixdev.bombe.analysis.InheritanceProvider;
+import org.cadixdev.bombe.analysis.InheritanceType;
+import org.cadixdev.bombe.type.BaseType;
+import org.cadixdev.bombe.type.signature.FieldSignature;
+import org.cadixdev.lorenz.MappingSet;
+import org.cadixdev.lorenz.model.FieldMapping;
+import org.cadixdev.lorenz.model.TopLevelClassMapping;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Optional;
+
+public final class CompletionTest {
+
+ @Test
+ @DisplayName("inherits field mapping")
+ public void inheritsFieldMapping() {
+ // given:
+ final MappingSet mappings = mappings();
+ final TopLevelClassMapping Parent = mappings.getOrCreateTopLevelClassMapping("Parent");
+ final TopLevelClassMapping Child2 = mappings.getOrCreateTopLevelClassMapping("Child2");
+ final InheritanceProvider inheritanceProvider = inheritanceProvider();
+
+ // when:
+ Parent.complete(inheritanceProvider);
+ Parent.computeFieldMapping(
+ new FieldSignature("a", BaseType.INT)
+ );
+ Child2.complete(inheritanceProvider);
+
+ // then:
+ final Optional mapping = Child2.computeFieldMapping(
+ new FieldSignature("a", BaseType.INT)
+ );
+ assertTrue(mapping.isPresent(), "Child2 hasn't inherited Parent/a");
+ assertEquals("parentField", mapping.get().getDeobfuscatedName());
+ }
+
+ @Test
+ @DisplayName("use correct field mapping")
+ public void useCorrectFieldMapping() {
+ // given:
+ final MappingSet mappings = mappings();
+ final TopLevelClassMapping Parent = mappings.getOrCreateTopLevelClassMapping("Parent");
+ final TopLevelClassMapping Child1 = mappings.getOrCreateTopLevelClassMapping("Child1");
+ final InheritanceProvider inheritanceProvider = inheritanceProvider();
+
+ // when:
+ Parent.complete(inheritanceProvider);
+ Parent.computeFieldMapping(
+ new FieldSignature("a", BaseType.INT)
+ );
+ Child1.complete(inheritanceProvider);
+
+ // then:
+ final Optional mapping = Child1.computeFieldMapping(
+ new FieldSignature("a", BaseType.INT)
+ );
+ assertTrue(mapping.isPresent());
+ assertEquals("childField", mapping.get().getDeobfuscatedName());
+ }
+
+ /*
+ This is representing the following:
+
+ Parent Parent
+ a parentField
+
+ Child1 Child1
+ a childField
+ */
+ private static MappingSet mappings() {
+ final MappingSet mappings = MappingSet.create();
+
+ final TopLevelClassMapping Parent =
+ mappings.getOrCreateTopLevelClassMapping("Parent");
+ Parent.getOrCreateFieldMapping("a")
+ .setDeobfuscatedName("parentField");
+
+ final TopLevelClassMapping Child1 =
+ mappings.getOrCreateTopLevelClassMapping("Child1");
+ Child1.getOrCreateFieldMapping("a")
+ .setDeobfuscatedName("childField");
+
+ final TopLevelClassMapping Child2 =
+ mappings.getOrCreateTopLevelClassMapping("Child2");
+
+ return mappings;
+ }
+
+ /*
+ This is representing the following:
+
+ class Parent {
+ int a;
+ }
+ class Child1 extends Parent {
+ int a;
+ }
+ class Child2 extends Parent {
+ }
+ */
+ private static InheritanceProvider inheritanceProvider() {
+ return klass -> {
+ switch (klass) {
+ case "Parent": {
+ final Map fields = Collections.singletonMap(
+ new FieldSignature("a", BaseType.INT), InheritanceType.PACKAGE_PRIVATE
+ );
+ final Map fieldsByName = Collections.singletonMap(
+ "a", InheritanceType.PACKAGE_PRIVATE
+ );
+
+ return Optional.of(new InheritanceProvider.ClassInfo.Impl(
+ "Parent", false,
+ "java/lang/Object", Collections.emptyList(),
+ fields, fieldsByName,
+ Collections.emptyMap()
+ ));
+ }
+ case "Child1": {
+ final Map fields = Collections.singletonMap(
+ new FieldSignature("a", BaseType.INT), InheritanceType.PACKAGE_PRIVATE
+ );
+ final Map fieldsByName = Collections.singletonMap(
+ "a", InheritanceType.PACKAGE_PRIVATE
+ );
+
+ return Optional.of(new InheritanceProvider.ClassInfo.Impl(
+ "Child1", false,
+ "Parent", Collections.emptyList(),
+ fields, fieldsByName,
+ Collections.emptyMap()
+ ));
+ }
+ case "Child2": {
+ return Optional.of(new InheritanceProvider.ClassInfo.Impl(
+ "Child2", false,
+ "Parent", Collections.emptyList(),
+ Collections.emptyMap(), Collections.emptyMap(),
+ Collections.emptyMap()
+ ));
+ }
+ }
+
+ return Optional.empty();
+ };
+ }
+
+}
diff --git a/lorenz/src/test/java/org/cadixdev/lorenz/test/MappingSetTest.java b/lorenz/src/test/java/org/cadixdev/lorenz/test/MappingSetTest.java
new file mode 100644
index 00000000..913b208a
--- /dev/null
+++ b/lorenz/src/test/java/org/cadixdev/lorenz/test/MappingSetTest.java
@@ -0,0 +1,167 @@
+/*
+ * This file is part of Lorenz, licensed under the MIT License (MIT).
+ *
+ * Copyright (c) Jamie Mansfield
+ * Copyright (c) contributors
+ *
+ * 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 org.cadixdev.lorenz.test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.cadixdev.bombe.type.ArrayType;
+import org.cadixdev.bombe.type.MethodDescriptor;
+import org.cadixdev.bombe.type.ObjectType;
+import org.cadixdev.lorenz.MappingSet;
+import org.cadixdev.lorenz.model.TopLevelClassMapping;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+public final class MappingSetTest {
+
+ @Test
+ @DisplayName("de-obfuscate object type")
+ public void deobfObjectType() {
+ final MappingSet mappings = mappings();
+
+ final ObjectType obfIn = new ObjectType("a");
+ final ObjectType deobfOut = new ObjectType("Demo");
+
+ assertEquals(deobfOut, mappings.deobfuscate(obfIn));
+ }
+
+ @Test
+ @DisplayName("de-obfuscate object type of mapped inner class")
+ public void deobfObjectTypeOfMappedInnerClass() {
+ final MappingSet mappings = mappings();
+
+ final ObjectType obfIn = new ObjectType("a$a");
+ final ObjectType deobfOut = new ObjectType("Demo$Inner");
+
+ assertEquals(deobfOut, mappings.deobfuscate(obfIn));
+ }
+
+ @Test
+ @DisplayName("de-obfuscate object type of unmapped inner class")
+ public void deobfObjectTypeOfUnmappedInnerClass() {
+ final MappingSet mappings = mappings();
+
+ final ObjectType obfIn = new ObjectType("a$b");
+ final ObjectType deobfOut = new ObjectType("Demo$b");
+
+ assertEquals(deobfOut, mappings.deobfuscate(obfIn));
+ }
+
+ @Test
+ @DisplayName("de-obfuscate array of object type")
+ public void deobfArrayOfObjectType() {
+ final MappingSet mappings = mappings();
+
+ final ArrayType in = new ArrayType(2,
+ new ObjectType("a"));
+ final ArrayType out = new ArrayType(2,
+ new ObjectType("Demo"));
+
+ assertEquals(out, mappings.deobfuscate(in));
+ }
+
+ @Test
+ @DisplayName("de-obfuscate array of object type of mapped inner class")
+ public void deobfArrayOfObjectTypeOfMappedInnerClass() {
+ final MappingSet mappings = mappings();
+
+ final ArrayType in = new ArrayType(2,
+ new ObjectType("a$a"));
+ final ArrayType out = new ArrayType(2,
+ new ObjectType("Demo$Inner"));
+
+ assertEquals(out, mappings.deobfuscate(in));
+ }
+
+ @Test
+ @DisplayName("de-obfuscate array of object type of unmapped inner class")
+ public void deobfArrayOfObjectTypeOfUnmappedInnerClass() {
+ final MappingSet mappings = mappings();
+
+ final ArrayType in = new ArrayType(2,
+ new ObjectType("a$b"));
+ final ArrayType out = new ArrayType(2,
+ new ObjectType("Demo$b"));
+
+ assertEquals(out, mappings.deobfuscate(in));
+ }
+
+ @Test
+ @DisplayName("de-obfuscate method descriptor single object param")
+ public void deobfMethodDescriptorSingleObjectParam() {
+ final MappingSet mappings = mappings();
+
+ final MethodDescriptor obf = MethodDescriptor.of("(La;)V");
+ final MethodDescriptor deobf = MethodDescriptor.of("(LDemo;)V");
+
+ assertEquals(deobf, mappings.deobfuscate(obf));
+ }
+
+ @Test
+ @DisplayName("de-obfuscate method descriptor multiple object param")
+ public void deobfMethodDescriptorMultipleObjectParam() {
+ final MappingSet mappings = mappings();
+
+ final MethodDescriptor obf = MethodDescriptor.of("(La;La;)V");
+ final MethodDescriptor deobf = MethodDescriptor.of("(LDemo;LDemo;)V");
+
+ assertEquals(deobf, mappings.deobfuscate(obf));
+ }
+
+ @Test
+ @DisplayName("de-obfuscate method descriptor object return")
+ public void deobfMethodDescriptorObjectReturn() {
+ final MappingSet mappings = mappings();
+
+ final MethodDescriptor obf = MethodDescriptor.of("()La;");
+ final MethodDescriptor deobf = MethodDescriptor.of("()LDemo;");
+
+ assertEquals(deobf, mappings.deobfuscate(obf));
+ }
+
+ @Test
+ @DisplayName("de-obfuscate method descriptor object return and params")
+ public void deobfMethodDescriptorObjectReturnAndParams() {
+ final MappingSet mappings = mappings();
+
+ final MethodDescriptor obf = MethodDescriptor.of("(La;La;)La;");
+ final MethodDescriptor deobf = MethodDescriptor.of("(LDemo;LDemo;)LDemo;");
+
+ assertEquals(deobf, mappings.deobfuscate(obf));
+ }
+
+ private static MappingSet mappings() {
+ final MappingSet mappings = MappingSet.create();
+
+ final TopLevelClassMapping a = mappings.getOrCreateTopLevelClassMapping("a")
+ .setDeobfuscatedName("Demo");
+ a.getOrCreateInnerClassMapping("a")
+ .setDeobfuscatedName("Inner");
+
+ return mappings;
+ }
+
+}
diff --git a/lorenz/src/test/java/org/cadixdev/lorenz/test/io/srg/CSrgReaderTest.java b/lorenz/src/test/java/org/cadixdev/lorenz/test/io/srg/CSrgReaderTest.java
index 7a837e6c..7cfd03f1 100644
--- a/lorenz/src/test/java/org/cadixdev/lorenz/test/io/srg/CSrgReaderTest.java
+++ b/lorenz/src/test/java/org/cadixdev/lorenz/test/io/srg/CSrgReaderTest.java
@@ -25,6 +25,7 @@
package org.cadixdev.lorenz.test.io.srg;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.cadixdev.lorenz.io.MappingFormats;
@@ -39,6 +40,16 @@ public CSrgReaderTest() throws Exception {
super(MappingFormats.CSRG, "/test.csrg");
}
+ @Test
+ public void ignoresPackages() throws IOException {
+ // This test ensures that package mappings won't erroneously be read as
+ // class mappings. No exceptions should be thrown either.
+ final CSrgReader.Processor parser = new CSrgReader.Processor();
+ parser.accept("abc/ uk/jamierocks/Example");
+
+ assertEquals(0, parser.getMappings().getTopLevelClassMappings().size());
+ }
+
@Test
public void tooLongInput() throws IOException {
// This test should set off the first case where IllegalArgumentException
diff --git a/lorenz/src/test/java/org/cadixdev/lorenz/test/io/srg/TSrgReaderTest.java b/lorenz/src/test/java/org/cadixdev/lorenz/test/io/srg/TSrgReaderTest.java
index 82297e43..51450ee4 100644
--- a/lorenz/src/test/java/org/cadixdev/lorenz/test/io/srg/TSrgReaderTest.java
+++ b/lorenz/src/test/java/org/cadixdev/lorenz/test/io/srg/TSrgReaderTest.java
@@ -25,6 +25,7 @@
package org.cadixdev.lorenz.test.io.srg;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.cadixdev.lorenz.io.MappingFormats;
@@ -39,6 +40,16 @@ public TSrgReaderTest() throws Exception {
super(MappingFormats.TSRG, "/test.tsrg");
}
+ @Test
+ public void ignoresPackages() throws IOException {
+ // This test ensures that package mappings won't erroneously be read as
+ // class mappings. No exceptions should be thrown either.
+ final TSrgReader.Processor parser = new TSrgReader.Processor();
+ parser.accept("abc/ uk/jamierocks/Example");
+
+ assertEquals(0, parser.getMappings().getTopLevelClassMappings().size());
+ }
+
@Test
public void tooLongInput() throws IOException {
// This test should set off the first case where IllegalArgumentException
diff --git a/lorenz/src/test/java/org/cadixdev/lorenz/test/io/srg/XSrgReaderTest.java b/lorenz/src/test/java/org/cadixdev/lorenz/test/io/srg/XSrgReaderTest.java
index 93b4d6cf..82f88966 100644
--- a/lorenz/src/test/java/org/cadixdev/lorenz/test/io/srg/XSrgReaderTest.java
+++ b/lorenz/src/test/java/org/cadixdev/lorenz/test/io/srg/XSrgReaderTest.java
@@ -28,7 +28,7 @@
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.cadixdev.lorenz.io.MappingFormats;
-import org.cadixdev.lorenz.io.srg.SrgReader;
+import org.cadixdev.lorenz.io.srg.xsrg.XSrgReader;
import org.junit.jupiter.api.Test;
import java.io.IOException;
@@ -43,7 +43,7 @@ public XSrgReaderTest() throws Exception {
public void ignoresPackages() throws IOException {
// This test ensures that package mappings won't set off any exceptions
// as they are valid input - even though Lorenz won't parse them :p
- final SrgReader.Processor parser = new SrgReader.Processor();
+ final XSrgReader.Processor parser = new XSrgReader.Processor();
parser.accept("PK: abc uk/jamierocks/Example");
}
@@ -51,7 +51,7 @@ public void ignoresPackages() throws IOException {
public void tooLongInput() throws IOException {
// This test should set off the first case where IllegalArgumentException
// is thrown
- final SrgReader.Processor parser = new SrgReader.Processor();
+ final XSrgReader.Processor parser = new XSrgReader.Processor();
assertThrows(IllegalArgumentException.class, () -> {
parser.accept("this is a faulty mapping because it is too long");
});
@@ -61,7 +61,7 @@ public void tooLongInput() throws IOException {
public void invalidInput() throws IOException {
// This test should set off the first case where IllegalArgumentException
// is thrown
- final SrgReader.Processor parser = new SrgReader.Processor();
+ final XSrgReader.Processor parser = new XSrgReader.Processor();
assertThrows(IllegalArgumentException.class, () -> {
parser.accept("PK: TooShort");
});
diff --git a/lorenz/src/test/java/org/cadixdev/lorenz/test/util/BinaryToolTest.java b/lorenz/src/test/java/org/cadixdev/lorenz/test/util/BinaryToolTest.java
new file mode 100644
index 00000000..d3c41e8d
--- /dev/null
+++ b/lorenz/src/test/java/org/cadixdev/lorenz/test/util/BinaryToolTest.java
@@ -0,0 +1,65 @@
+/*
+ * This file is part of Lorenz, licensed under the MIT License (MIT).
+ *
+ * Copyright (c) Jamie Mansfield
+ * Copyright (c) contributors
+ *
+ * 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 org.cadixdev.lorenz.test.util;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.cadixdev.lorenz.util.BinaryTool;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+public final class BinaryToolTest {
+
+ @Test
+ @DisplayName("reads top level class binary name")
+ public void readsTopLevelClass() {
+ final String[] result = BinaryTool.from("a");
+
+ assertArrayEquals(new String[]{
+ "a"
+ }, result);
+ }
+
+ @Test
+ @DisplayName("reads inner class binary name")
+ public void readsInnerClass() {
+ final String[] result = BinaryTool.from("a$b$c");
+
+ assertArrayEquals(new String[]{
+ "a", "b", "c"
+ }, result);
+ }
+
+ @Test
+ @DisplayName("writes binary name")
+ public void writeBinaryName() {
+ assertEquals("a$b", BinaryTool.to(new String[] {
+ "a", "b"
+ }));
+ }
+
+}