Skip to content

Commit

Permalink
fix a couple possible crashes in package renamer
Browse files Browse the repository at this point in the history
  • Loading branch information
ix0rai committed Oct 29, 2024
1 parent 01e2d66 commit 8247fe0
Show file tree
Hide file tree
Showing 20 changed files with 110 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ public CompletableFuture<Void> renamePackage(String path, String input) {
private void handleNode(int divergenceIndex, boolean rename, String[] oldPackageNames, String[] newPackageNames, Map<String, Runnable> renameStack, TreeNode node) {
if (node instanceof ClassSelectorClassNode classNode && rename) {
String oldName = classNode.getDeobfEntry().getFullName();
int finalPackageIndex = divergenceIndex - 1;
int finalPackageIndex = divergenceIndex == 0 ? 0 : divergenceIndex - 1;

// skips all classes that do not match the exact package being renamed
if (this.mode == Mode.MOVE) {
Expand Down Expand Up @@ -268,9 +268,9 @@ private void handleNode(int divergenceIndex, boolean rename, String[] oldPackage
}
}

if (packageName.equals(newPackageNames[index])) {
if (newPackageNames.length - 1 >= index && packageName.equals(newPackageNames[index])) {
this.handlePackage(index, false, oldPackageNames, newPackageNames, renameStack, packageNode);
} else if (packageName.equals(oldPackageNames[index])) {
} else if (oldPackageNames.length - 1 >= index && packageName.equals(oldPackageNames[index])) {
this.handlePackage(index, true, oldPackageNames, newPackageNames, renameStack, packageNode);
}
}
Expand Down
116 changes: 72 additions & 44 deletions enigma-swing/src/test/java/org/quiltmc/enigma/TestPackageRename.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.quiltmc.enigma;

import org.quiltmc.enigma.api.EnigmaProfile;
import org.quiltmc.enigma.api.EnigmaProject;
import org.quiltmc.enigma.gui.EditableType;
import org.quiltmc.enigma.gui.Gui;
import org.quiltmc.enigma.gui.docker.AllClassesDocker;
Expand All @@ -26,83 +27,96 @@
public class TestPackageRename {
public static final Path JAR = TestUtil.obfJar("complete");
public static final Path MAPPINGS = Path.of("src/test/resources/test_mappings");
private static Translator deobfuscator;
private static EnigmaProject project;

@Test
void testRemoveOnePackage() throws InterruptedException {
renamePackage("a/b/c", "a/c", PackageRenamer.Mode.REFACTOR);

assertMapping(TestEntryFactory.newClass("A"), TestEntryFactory.newClass("a/c/A"));
assertMapping(TestEntryFactory.newClass("B"), TestEntryFactory.newClass("a/c/B"));
assertMapping(TestEntryFactory.newClass("C"), TestEntryFactory.newClass("a/c/C"));
assertMapping(TestEntryFactory.newClass("D"), TestEntryFactory.newClass("a/D"));
assertMapping(TestEntryFactory.newClass("E"), TestEntryFactory.newClass("E"));
assertMapping("a","a/c/A");
assertMapping("b", "a/c/B");
assertMapping("c", "a/c/C");
assertMapping("d", "a/D");
assertMapping("e", "E");
}

@Test
void testRemoveTwoPackages() throws InterruptedException {
renamePackage("a/b/c", "a", PackageRenamer.Mode.REFACTOR);

assertMapping(TestEntryFactory.newClass("A"), TestEntryFactory.newClass("a/A"));
assertMapping(TestEntryFactory.newClass("B"), TestEntryFactory.newClass("a/B"));
assertMapping(TestEntryFactory.newClass("C"), TestEntryFactory.newClass("a/C"));
assertMapping(TestEntryFactory.newClass("D"), TestEntryFactory.newClass("a/D"));
assertMapping(TestEntryFactory.newClass("E"), TestEntryFactory.newClass("E"));
assertMapping("a", "a/A");
assertMapping("b", "a/B");
assertMapping("c", "a/C");
assertMapping("d", "a/D");
assertMapping("e", "E");
}

@Test
void testPackageConservation() throws InterruptedException {
renamePackage("a/b", "a", PackageRenamer.Mode.REFACTOR);

assertMapping(TestEntryFactory.newClass("A"), TestEntryFactory.newClass("a/c/A"));
assertMapping(TestEntryFactory.newClass("B"), TestEntryFactory.newClass("a/c/B"));
assertMapping(TestEntryFactory.newClass("C"), TestEntryFactory.newClass("a/C"));
assertMapping(TestEntryFactory.newClass("D"), TestEntryFactory.newClass("a/D"));
assertMapping(TestEntryFactory.newClass("E"), TestEntryFactory.newClass("E"));
assertMapping("a", "a/c/A");
assertMapping("b", "a/c/B");
assertMapping("c", "a/C");
assertMapping("d", "a/D");
assertMapping("e", "E");
}

@Test
void testAppendOnePackage() throws InterruptedException {
renamePackage("a/b/c", "a/b/c/d", PackageRenamer.Mode.REFACTOR);

assertMapping(TestEntryFactory.newClass("A"), TestEntryFactory.newClass("a/b/c/d/A"));
assertMapping(TestEntryFactory.newClass("B"), TestEntryFactory.newClass("a/b/c/d/B"));
assertMapping(TestEntryFactory.newClass("C"), TestEntryFactory.newClass("a/b/C"));
assertMapping(TestEntryFactory.newClass("D"), TestEntryFactory.newClass("a/D"));
assertMapping(TestEntryFactory.newClass("E"), TestEntryFactory.newClass("E"));
assertMapping("a", "a/b/c/d/A");
assertMapping("b", "a/b/c/d/B");
assertMapping("c", "a/b/C");
assertMapping("d", "a/D");
assertMapping("e", "E");
}

@Test
void testSimpleRename() throws InterruptedException {
renamePackage("a/b/c", "a/b/d", PackageRenamer.Mode.REFACTOR);

assertMapping(TestEntryFactory.newClass("A"), TestEntryFactory.newClass("a/b/d/A"));
assertMapping(TestEntryFactory.newClass("B"), TestEntryFactory.newClass("a/b/d/B"));
assertMapping(TestEntryFactory.newClass("C"), TestEntryFactory.newClass("a/b/C"));
assertMapping(TestEntryFactory.newClass("D"), TestEntryFactory.newClass("a/D"));
assertMapping(TestEntryFactory.newClass("E"), TestEntryFactory.newClass("E"));
assertMapping("a", "a/b/d/A");
assertMapping("b", "a/b/d/B");
assertMapping("c", "a/b/C");
assertMapping("d", "a/D");
assertMapping("e", "E");
}

@Test
void testFirstPackageRename() throws InterruptedException {
renamePackage("a", "b", PackageRenamer.Mode.REFACTOR);

assertMapping(TestEntryFactory.newClass("A"), TestEntryFactory.newClass("b/b/c/A"));
assertMapping(TestEntryFactory.newClass("B"), TestEntryFactory.newClass("b/b/c/B"));
assertMapping(TestEntryFactory.newClass("C"), TestEntryFactory.newClass("b/b/C"));
assertMapping(TestEntryFactory.newClass("D"), TestEntryFactory.newClass("b/D"));
assertMapping(TestEntryFactory.newClass("E"), TestEntryFactory.newClass("E"));
assertMapping("a", "b/b/c/A");
assertMapping("b", "b/b/c/B");
assertMapping("c", "b/b/C");
assertMapping("d", "b/D");
assertMapping("e", "E");
}

@Test
void testPackageMove() throws InterruptedException {
renamePackage("a/b/c", "a/c", PackageRenamer.Mode.MOVE);

assertMapping(TestEntryFactory.newClass("A"), TestEntryFactory.newClass("a/c/A"));
assertMapping(TestEntryFactory.newClass("B"), TestEntryFactory.newClass("a/c/B"));
assertMapping(TestEntryFactory.newClass("C"), TestEntryFactory.newClass("a/b/C"));
assertMapping(TestEntryFactory.newClass("D"), TestEntryFactory.newClass("a/D"));
assertMapping(TestEntryFactory.newClass("E"), TestEntryFactory.newClass("E"));
assertMapping("a", "a/c/A");
assertMapping("b", "a/c/B");
assertMapping("c", "a/b/C");
assertMapping("d", "a/D");
assertMapping("e", "E");
}

@Test
void testPackageMerge() throws InterruptedException {
renamePackage("b", "a", PackageRenamer.Mode.REFACTOR);

assertMapping("a", "a/b/c/A");
assertMapping("b", "a/b/c/B");
assertMapping("c", "a/b/C");
assertMapping("d", "a/D");
assertMapping("e", "E");
assertMapping("f", "a/F");
assertMapping("g", "a/c/G");
}

private static void renamePackage(String packageName, String newName, PackageRenamer.Mode mode) throws InterruptedException {
Expand All @@ -124,21 +138,35 @@ private static ClassSelectorPopupMenu setupMenu() throws InterruptedException {
gui.getController().openJar(JAR).thenRun(() -> gui.getController().openMappings(MAPPINGS).thenRun(latch::countDown));
latch.await();

deobfuscator = gui.getController().getProject().getRemapper().getDeobfuscator();
project = gui.getController().getProject();
return gui.getDockerManager().getDocker(AllClassesDocker.class).getPopupMenu();
}

private static void assertBaseMappings() {
// assert starting mappings
assertMapping(TestEntryFactory.newClass("A"), TestEntryFactory.newClass("a/b/c/A"));
assertMapping(TestEntryFactory.newClass("B"), TestEntryFactory.newClass("a/b/c/B"));
assertMapping(TestEntryFactory.newClass("C"), TestEntryFactory.newClass("a/b/C"));
assertMapping(TestEntryFactory.newClass("D"), TestEntryFactory.newClass("a/D"));
assertMapping(TestEntryFactory.newClass("E"), TestEntryFactory.newClass("E"));
// a
assertMapping("a", "a/b/c/A");
assertMapping("b", "a/b/c/B");
assertMapping("c", "a/b/C");
assertMapping("d", "a/D");

// lone
assertMapping("e", "E");

// b
assertMapping("f", "b/F");
assertMapping("g", "b/c/G");
}

private static void assertMapping(String obf, String deobf) {
assertMapping(TestEntryFactory.newClass(obf), TestEntryFactory.newClass(deobf));
}

private static void assertMapping(Entry<?> obf, Entry<?> deobf) {
TranslateResult<? extends Entry<?>> result = deobfuscator.extendedTranslate(obf);
if (!project.getRemapper().getMappings().contains(obf)) {
throw new RuntimeException("no mapping for " + obf.getFullName() + " !");
}

TranslateResult<? extends Entry<?>> result = project.getRemapper().getDeobfuscator().extendedTranslate(obf);
assertThat(result, is(notNullValue()));
assertThat(result.getValue(), is(deobf));

Expand Down
1 change: 0 additions & 1 deletion enigma-swing/src/test/resources/test_mappings/a/D.mapping

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CLASS c a/b/C

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CLASS a a/b/c/A
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CLASS b a/b/c/B
1 change: 1 addition & 0 deletions enigma-swing/src/test/resources/test_mappings/a/d.mapping
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CLASS d a/D
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CLASS g b/c/G
1 change: 1 addition & 0 deletions enigma-swing/src/test/resources/test_mappings/b/f.mapping
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CLASS f b/F
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
CLASS E E
CLASS e E
COMMENT a
4 changes: 4 additions & 0 deletions enigma/src/test/java/org/quiltmc/enigma/input/packages/E.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package org.quiltmc.enigma.input.packages;

public class E {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package org.quiltmc.enigma.input.packages.a;

public class D {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package org.quiltmc.enigma.input.packages.a.b;

public class C {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package org.quiltmc.enigma.input.packages.a.b.c;

public class A {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package org.quiltmc.enigma.input.packages.a.b.c;

public class B {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package org.quiltmc.enigma.input.packages.b;

public class F {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package org.quiltmc.enigma.input.packages.b.c;

public class G {
}

0 comments on commit 8247fe0

Please sign in to comment.