fix: Engima mapping reader did not consider indentation levels of inner classes
@@ -7,6 +7,7 @@ import java.io.IOException;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
+import java.util.Stack;
import static me.coley.recaf.util.Log.*;
@@ -38,32 +39,59 @@ public class EnigmaMappings extends FileMappings {
Map<String, String> map = new HashMap<>();
String[] lines = StringUtil.splitNewline(text);
int line = 0;
- String currentClass = null;
+ Stack<String> currentClass = new Stack<>();
for(String lineStr : lines) {
line++;
- String[] args = lineStr.trim().split(" ");
+ String lineStrTrim = lineStr.trim();
+ int strIndent = lineStr.indexOf(lineStrTrim) + 1;
+ String[] args = lineStrTrim.split(" ");
String type = args[0];
try {
switch(type) {
case "CLASS":
- currentClass = args[1];
+ if (lineStr.matches("\\s+.+")) {
+ // Check for indentation, implies the class is an inner
+ currentClass.add(args[1]);
+ } else {
+ // Root level class
+ currentClass.clear();
+ currentClass.add(args[1]);
+ }
+ // Not all classes need to be renamed if they have child elements that are renamed
+ if (args.length >= 3) {
String renamedClass = args[2];
- map.put(currentClass, renamedClass);
+ map.put(currentClass.peek(), renamedClass);
+ }
break;
case "FIELD":
- if (currentClass == null)
+ // Check if no longer within inner-class scope
+ if (strIndent < currentClass.size()) {
+ currentClass.pop();
+ }
+ // Parse field
+ if (currentClass.empty())
throw new IllegalArgumentException(FAIL + "could not map field, no class context");
String currentField = args[1];
String renamedField = args[2];
- map.put(currentClass + "." + currentField, renamedField);
+ map.put(currentClass.peek() + "." + currentField, renamedField);
break;
case "METHOD":
- if (currentClass == null)
+ // Check if no longer within inner-class scope
+ if (strIndent < currentClass.size()) {
+ currentClass.pop();
+ }
+ // Parse method
+ if (currentClass.empty())
throw new IllegalArgumentException(FAIL + "could not map method, no class context");
String currentMethod = args[1];
+ if (currentMethod.equals("<init>"))
+ continue;
+ // Not all methods need to be renamed if they have child arg elements that are renamed
+ if (args.length >= 4) {
String renamedMethod = args[2];
String methodType = args[3];
- map.put(currentClass + "." + currentMethod + methodType, renamedMethod);
+ map.put(currentClass.peek() + "." + currentMethod + methodType, renamedMethod);
+ }
break;
case "ARG":
// Do nothing, mapper does not support arg names
