summaryrefslogtreecommitdiff
path: root/src/cuchaz/enigma/mapping
diff options
context:
space:
mode:
authorGravatar jeff2015-02-23 23:29:22 -0500
committerGravatar jeff2015-02-23 23:29:22 -0500
commit2dc7428e37bdd7a119f53d02ce157675509b0d63 (patch)
tree68f409ac726166e427eea3a199eb462130c53ccd /src/cuchaz/enigma/mapping
parentmake types serializable (diff)
downloadenigma-fork-2dc7428e37bdd7a119f53d02ce157675509b0d63.tar.gz
enigma-fork-2dc7428e37bdd7a119f53d02ce157675509b0d63.tar.xz
enigma-fork-2dc7428e37bdd7a119f53d02ce157675509b0d63.zip
lots of work in better handling of inner classes
also working on recognizing unobfuscated and deobfuscated jars (needed for M3L)
Diffstat (limited to 'src/cuchaz/enigma/mapping')
-rw-r--r--src/cuchaz/enigma/mapping/ClassMapping.java41
-rw-r--r--src/cuchaz/enigma/mapping/EntryFactory.java35
-rw-r--r--src/cuchaz/enigma/mapping/Mappings.java14
-rw-r--r--src/cuchaz/enigma/mapping/MappingsRenamer.java2
-rw-r--r--src/cuchaz/enigma/mapping/MappingsWriter.java4
-rw-r--r--src/cuchaz/enigma/mapping/Translator.java154
6 files changed, 164 insertions, 86 deletions
diff --git a/src/cuchaz/enigma/mapping/ClassMapping.java b/src/cuchaz/enigma/mapping/ClassMapping.java
index 885400b..3610e33 100644
--- a/src/cuchaz/enigma/mapping/ClassMapping.java
+++ b/src/cuchaz/enigma/mapping/ClassMapping.java
@@ -20,7 +20,8 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping> {
20 20
21 private static final long serialVersionUID = -5148491146902340107L; 21 private static final long serialVersionUID = -5148491146902340107L;
22 22
23 private String m_obfName; 23 private String m_obfFullName;
24 private String m_obfSimpleName;
24 private String m_deobfName; 25 private String m_deobfName;
25 private Map<String,ClassMapping> m_innerClassesByObf; 26 private Map<String,ClassMapping> m_innerClassesByObf;
26 private Map<String,ClassMapping> m_innerClassesByDeobf; 27 private Map<String,ClassMapping> m_innerClassesByDeobf;
@@ -34,7 +35,8 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping> {
34 } 35 }
35 36
36 public ClassMapping(String obfName, String deobfName) { 37 public ClassMapping(String obfName, String deobfName) {
37 m_obfName = obfName; 38 m_obfFullName = obfName;
39 m_obfSimpleName = new ClassEntry(obfName).getSimpleName();
38 m_deobfName = NameValidator.validateClassName(deobfName, false); 40 m_deobfName = NameValidator.validateClassName(deobfName, false);
39 m_innerClassesByObf = Maps.newHashMap(); 41 m_innerClassesByObf = Maps.newHashMap();
40 m_innerClassesByDeobf = Maps.newHashMap(); 42 m_innerClassesByDeobf = Maps.newHashMap();
@@ -44,8 +46,12 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping> {
44 m_methodsByDeobf = Maps.newHashMap(); 46 m_methodsByDeobf = Maps.newHashMap();
45 } 47 }
46 48
47 public String getObfName() { 49 public String getObfFullName() {
48 return m_obfName; 50 return m_obfFullName;
51 }
52
53 public String getObfSimpleName() {
54 return m_obfSimpleName;
49 } 55 }
50 56
51 public String getDeobfName() { 57 public String getDeobfName() {
@@ -64,8 +70,7 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping> {
64 } 70 }
65 71
66 public void addInnerClassMapping(ClassMapping classMapping) { 72 public void addInnerClassMapping(ClassMapping classMapping) {
67 assert (isSimpleClassName(classMapping.getObfName())); 73 boolean obfWasAdded = m_innerClassesByObf.put(classMapping.getObfSimpleName(), classMapping) == null;
68 boolean obfWasAdded = m_innerClassesByObf.put(classMapping.getObfName(), classMapping) == null;
69 assert (obfWasAdded); 74 assert (obfWasAdded);
70 if (classMapping.getDeobfName() != null) { 75 if (classMapping.getDeobfName() != null) {
71 assert (isSimpleClassName(classMapping.getDeobfName())); 76 assert (isSimpleClassName(classMapping.getDeobfName()));
@@ -75,7 +80,7 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping> {
75 } 80 }
76 81
77 public void removeInnerClassMapping(ClassMapping classMapping) { 82 public void removeInnerClassMapping(ClassMapping classMapping) {
78 boolean obfWasRemoved = m_innerClassesByObf.remove(classMapping.getObfName()) != null; 83 boolean obfWasRemoved = m_innerClassesByObf.remove(classMapping.getObfSimpleName()) != null;
79 assert (obfWasRemoved); 84 assert (obfWasRemoved);
80 if (classMapping.getDeobfName() != null) { 85 if (classMapping.getDeobfName() != null) {
81 boolean deobfWasRemoved = m_innerClassesByDeobf.remove(classMapping.getDeobfName()) != null; 86 boolean deobfWasRemoved = m_innerClassesByDeobf.remove(classMapping.getDeobfName()) != null;
@@ -112,11 +117,11 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping> {
112 return classMapping; 117 return classMapping;
113 } 118 }
114 119
115 public String getObfInnerClassName(String deobfName) { 120 public String getObfInnerClassSimpleName(String deobfName) {
116 assert (isSimpleClassName(deobfName)); 121 assert (isSimpleClassName(deobfName));
117 ClassMapping classMapping = m_innerClassesByDeobf.get(deobfName); 122 ClassMapping classMapping = m_innerClassesByDeobf.get(deobfName);
118 if (classMapping != null) { 123 if (classMapping != null) {
119 return classMapping.getObfName(); 124 return classMapping.getObfSimpleName();
120 } 125 }
121 return null; 126 return null;
122 } 127 }
@@ -163,7 +168,7 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping> {
163 public void addFieldMapping(FieldMapping fieldMapping) { 168 public void addFieldMapping(FieldMapping fieldMapping) {
164 String obfKey = getFieldKey(fieldMapping.getObfName(), fieldMapping.getObfType()); 169 String obfKey = getFieldKey(fieldMapping.getObfName(), fieldMapping.getObfType());
165 if (m_fieldsByObf.containsKey(obfKey)) { 170 if (m_fieldsByObf.containsKey(obfKey)) {
166 throw new Error("Already have mapping for " + m_obfName + "." + obfKey); 171 throw new Error("Already have mapping for " + m_obfFullName + "." + obfKey);
167 } 172 }
168 String deobfKey = getFieldKey(fieldMapping.getDeobfName(), fieldMapping.getObfType()); 173 String deobfKey = getFieldKey(fieldMapping.getDeobfName(), fieldMapping.getObfType());
169 if (m_fieldsByDeobf.containsKey(deobfKey)) { 174 if (m_fieldsByDeobf.containsKey(deobfKey)) {
@@ -257,7 +262,7 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping> {
257 public void addMethodMapping(MethodMapping methodMapping) { 262 public void addMethodMapping(MethodMapping methodMapping) {
258 String obfKey = getMethodKey(methodMapping.getObfName(), methodMapping.getObfSignature()); 263 String obfKey = getMethodKey(methodMapping.getObfName(), methodMapping.getObfSignature());
259 if (m_methodsByObf.containsKey(obfKey)) { 264 if (m_methodsByObf.containsKey(obfKey)) {
260 throw new Error("Already have mapping for " + m_obfName + "." + obfKey); 265 throw new Error("Already have mapping for " + m_obfFullName + "." + obfKey);
261 } 266 }
262 boolean wasAdded = m_methodsByObf.put(obfKey, methodMapping) == null; 267 boolean wasAdded = m_methodsByObf.put(obfKey, methodMapping) == null;
263 assert (wasAdded); 268 assert (wasAdded);
@@ -339,7 +344,7 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping> {
339 @Override 344 @Override
340 public String toString() { 345 public String toString() {
341 StringBuilder buf = new StringBuilder(); 346 StringBuilder buf = new StringBuilder();
342 buf.append(m_obfName); 347 buf.append(m_obfFullName);
343 buf.append(" <-> "); 348 buf.append(" <-> ");
344 buf.append(m_deobfName); 349 buf.append(m_deobfName);
345 buf.append("\n"); 350 buf.append("\n");
@@ -359,7 +364,7 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping> {
359 buf.append("Inner Classes:\n"); 364 buf.append("Inner Classes:\n");
360 for (ClassMapping classMapping : m_innerClassesByObf.values()) { 365 for (ClassMapping classMapping : m_innerClassesByObf.values()) {
361 buf.append("\t"); 366 buf.append("\t");
362 buf.append(classMapping.getObfName()); 367 buf.append(classMapping.getObfSimpleName());
363 buf.append(" <-> "); 368 buf.append(" <-> ");
364 buf.append(classMapping.getDeobfName()); 369 buf.append(classMapping.getDeobfName());
365 buf.append("\n"); 370 buf.append("\n");
@@ -370,10 +375,10 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping> {
370 @Override 375 @Override
371 public int compareTo(ClassMapping other) { 376 public int compareTo(ClassMapping other) {
372 // sort by a, b, c, ... aa, ab, etc 377 // sort by a, b, c, ... aa, ab, etc
373 if (m_obfName.length() != other.m_obfName.length()) { 378 if (m_obfFullName.length() != other.m_obfFullName.length()) {
374 return m_obfName.length() - other.m_obfName.length(); 379 return m_obfFullName.length() - other.m_obfFullName.length();
375 } 380 }
376 return m_obfName.compareTo(other.m_obfName); 381 return m_obfFullName.compareTo(other.m_obfFullName);
377 } 382 }
378 383
379 public boolean renameObfClass(String oldObfClassName, String newObfClassName) { 384 public boolean renameObfClass(String oldObfClassName, String newObfClassName) {
@@ -399,9 +404,9 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping> {
399 } 404 }
400 } 405 }
401 406
402 if (m_obfName.equals(oldObfClassName)) { 407 if (m_obfFullName.equals(oldObfClassName)) {
403 // rename this class 408 // rename this class
404 m_obfName = newObfClassName; 409 m_obfFullName = newObfClassName;
405 return true; 410 return true;
406 } 411 }
407 return false; 412 return false;
diff --git a/src/cuchaz/enigma/mapping/EntryFactory.java b/src/cuchaz/enigma/mapping/EntryFactory.java
index dceea29..bbdfa73 100644
--- a/src/cuchaz/enigma/mapping/EntryFactory.java
+++ b/src/cuchaz/enigma/mapping/EntryFactory.java
@@ -25,25 +25,19 @@ public class EntryFactory {
25 } 25 }
26 26
27 public static ClassEntry getObfClassEntry(JarIndex jarIndex, ClassMapping classMapping) { 27 public static ClassEntry getObfClassEntry(JarIndex jarIndex, ClassMapping classMapping) {
28 return new ClassEntry(getChainedOuterClassName(jarIndex, classMapping.getObfName())); 28 return getChainedOuterClassName(jarIndex, new ClassEntry(classMapping.getObfFullName()));
29 } 29 }
30 30
31 private static String getChainedOuterClassName(JarIndex jarIndex, String obfClassName) { 31 public static ClassEntry getChainedOuterClassName(JarIndex jarIndex, ClassEntry obfClassEntry) {
32 32
33 // lookup the chain of outer classes 33 // lookup the chain of outer classes
34 List<String> obfOuterClassNames = Lists.newArrayList(); 34 List<ClassEntry> obfClassChain = Lists.newArrayList(obfClassEntry);
35 String checkName = obfClassName; 35 ClassEntry checkClassEntry = obfClassEntry;
36 while (true) { 36 while (true) {
37 37 ClassEntry obfOuterClassEntry = jarIndex.getOuterClass(checkClassEntry);
38 // if this class name has a package, then it can't be an inner class 38 if (obfOuterClassEntry != null) {
39 if (!new ClassEntry(checkName).isInDefaultPackage()) { 39 obfClassChain.add(obfOuterClassEntry);
40 break; 40 checkClassEntry = obfOuterClassEntry;
41 }
42
43 String obfOuterClassName = jarIndex.getOuterClass(checkName);
44 if (obfOuterClassName != null) {
45 obfOuterClassNames.add(obfOuterClassName);
46 checkName = obfOuterClassName;
47 } else { 41 } else {
48 break; 42 break;
49 } 43 }
@@ -51,12 +45,15 @@ public class EntryFactory {
51 45
52 // build the chained class name 46 // build the chained class name
53 StringBuilder buf = new StringBuilder(); 47 StringBuilder buf = new StringBuilder();
54 for (int i=obfOuterClassNames.size()-1; i>=0; i--) { 48 for (int i=obfClassChain.size()-1; i>=0; i--) {
55 buf.append(obfOuterClassNames.get(i)); 49 if (buf.length() == 0) {
56 buf.append("$"); 50 buf.append(obfClassChain.get(i).getName());
51 } else {
52 buf.append("$");
53 buf.append(obfClassChain.get(i).getSimpleName());
54 }
57 } 55 }
58 buf.append(obfClassName); 56 return new ClassEntry(buf.toString());
59 return buf.toString();
60 } 57 }
61 58
62 public static ClassEntry getDeobfClassEntry(ClassMapping classMapping) { 59 public static ClassEntry getDeobfClassEntry(ClassMapping classMapping) {
diff --git a/src/cuchaz/enigma/mapping/Mappings.java b/src/cuchaz/enigma/mapping/Mappings.java
index 675fdf1..a85bcbf 100644
--- a/src/cuchaz/enigma/mapping/Mappings.java
+++ b/src/cuchaz/enigma/mapping/Mappings.java
@@ -37,7 +37,7 @@ public class Mappings implements Serializable {
37 this(); 37 this();
38 38
39 for (ClassMapping classMapping : classes) { 39 for (ClassMapping classMapping : classes) {
40 m_classesByObf.put(classMapping.getObfName(), classMapping); 40 m_classesByObf.put(classMapping.getObfFullName(), classMapping);
41 if (classMapping.getDeobfName() != null) { 41 if (classMapping.getDeobfName() != null) {
42 m_classesByDeobf.put(classMapping.getDeobfName(), classMapping); 42 m_classesByDeobf.put(classMapping.getDeobfName(), classMapping);
43 } 43 }
@@ -50,10 +50,10 @@ public class Mappings implements Serializable {
50 } 50 }
51 51
52 public void addClassMapping(ClassMapping classMapping) { 52 public void addClassMapping(ClassMapping classMapping) {
53 if (m_classesByObf.containsKey(classMapping.getObfName())) { 53 if (m_classesByObf.containsKey(classMapping.getObfFullName())) {
54 throw new Error("Already have mapping for " + classMapping.getObfName()); 54 throw new Error("Already have mapping for " + classMapping.getObfFullName());
55 } 55 }
56 boolean obfWasAdded = m_classesByObf.put(classMapping.getObfName(), classMapping) == null; 56 boolean obfWasAdded = m_classesByObf.put(classMapping.getObfFullName(), classMapping) == null;
57 assert (obfWasAdded); 57 assert (obfWasAdded);
58 if (classMapping.getDeobfName() != null) { 58 if (classMapping.getDeobfName() != null) {
59 if (m_classesByDeobf.containsKey(classMapping.getDeobfName())) { 59 if (m_classesByDeobf.containsKey(classMapping.getDeobfName())) {
@@ -65,7 +65,7 @@ public class Mappings implements Serializable {
65 } 65 }
66 66
67 public void removeClassMapping(ClassMapping classMapping) { 67 public void removeClassMapping(ClassMapping classMapping) {
68 boolean obfWasRemoved = m_classesByObf.remove(classMapping.getObfName()) != null; 68 boolean obfWasRemoved = m_classesByObf.remove(classMapping.getObfFullName()) != null;
69 assert (obfWasRemoved); 69 assert (obfWasRemoved);
70 if (classMapping.getDeobfName() != null) { 70 if (classMapping.getDeobfName() != null) {
71 boolean deobfWasRemoved = m_classesByDeobf.remove(classMapping.getDeobfName()) != null; 71 boolean deobfWasRemoved = m_classesByDeobf.remove(classMapping.getDeobfName()) != null;
@@ -103,7 +103,7 @@ public class Mappings implements Serializable {
103 if (classMapping.getDeobfName() != null) { 103 if (classMapping.getDeobfName() != null) {
104 classes.put(classMapping.getDeobfName(), classMapping); 104 classes.put(classMapping.getDeobfName(), classMapping);
105 } else { 105 } else {
106 classes.put(classMapping.getObfName(), classMapping); 106 classes.put(classMapping.getObfFullName(), classMapping);
107 } 107 }
108 } 108 }
109 109
@@ -144,7 +144,7 @@ public class Mappings implements Serializable {
144 for (ClassMapping classMapping : classes()) { 144 for (ClassMapping classMapping : classes()) {
145 145
146 // add the class name 146 // add the class name
147 classNames.add(classMapping.getObfName()); 147 classNames.add(classMapping.getObfFullName());
148 148
149 // add classes from method signatures 149 // add classes from method signatures
150 for (MethodMapping methodMapping : classMapping.methods()) { 150 for (MethodMapping methodMapping : classMapping.methods()) {
diff --git a/src/cuchaz/enigma/mapping/MappingsRenamer.java b/src/cuchaz/enigma/mapping/MappingsRenamer.java
index ea343c4..16f700d 100644
--- a/src/cuchaz/enigma/mapping/MappingsRenamer.java
+++ b/src/cuchaz/enigma/mapping/MappingsRenamer.java
@@ -213,7 +213,7 @@ public class MappingsRenamer {
213 ClassMapping classMapping = m_mappings.m_classesByObf.get(obfClassName); 213 ClassMapping classMapping = m_mappings.m_classesByObf.get(obfClassName);
214 if (classMapping == null) { 214 if (classMapping == null) {
215 classMapping = new ClassMapping(obfClassName); 215 classMapping = new ClassMapping(obfClassName);
216 boolean obfWasAdded = m_mappings.m_classesByObf.put(classMapping.getObfName(), classMapping) == null; 216 boolean obfWasAdded = m_mappings.m_classesByObf.put(classMapping.getObfFullName(), classMapping) == null;
217 assert (obfWasAdded); 217 assert (obfWasAdded);
218 } 218 }
219 return classMapping; 219 return classMapping;
diff --git a/src/cuchaz/enigma/mapping/MappingsWriter.java b/src/cuchaz/enigma/mapping/MappingsWriter.java
index c7c2cc0..8b62db8 100644
--- a/src/cuchaz/enigma/mapping/MappingsWriter.java
+++ b/src/cuchaz/enigma/mapping/MappingsWriter.java
@@ -31,9 +31,9 @@ public class MappingsWriter {
31 31
32 private void write(PrintWriter out, ClassMapping classMapping, int depth) throws IOException { 32 private void write(PrintWriter out, ClassMapping classMapping, int depth) throws IOException {
33 if (classMapping.getDeobfName() == null) { 33 if (classMapping.getDeobfName() == null) {
34 out.format("%sCLASS %s\n", getIndent(depth), classMapping.getObfName()); 34 out.format("%sCLASS %s\n", getIndent(depth), classMapping.getObfFullName());
35 } else { 35 } else {
36 out.format("%sCLASS %s %s\n", getIndent(depth), classMapping.getObfName(), classMapping.getDeobfName()); 36 out.format("%sCLASS %s %s\n", getIndent(depth), classMapping.getObfFullName(), classMapping.getDeobfName());
37 } 37 }
38 38
39 for (ClassMapping innerClassMapping : sorted(classMapping.innerClasses())) { 39 for (ClassMapping innerClassMapping : sorted(classMapping.innerClasses())) {
diff --git a/src/cuchaz/enigma/mapping/Translator.java b/src/cuchaz/enigma/mapping/Translator.java
index 759dddf..d985032 100644
--- a/src/cuchaz/enigma/mapping/Translator.java
+++ b/src/cuchaz/enigma/mapping/Translator.java
@@ -10,8 +10,10 @@
10 ******************************************************************************/ 10 ******************************************************************************/
11package cuchaz.enigma.mapping; 11package cuchaz.enigma.mapping;
12 12
13import java.util.List;
13import java.util.Map; 14import java.util.Map;
14 15
16import com.beust.jcommander.internal.Lists;
15import com.google.common.collect.Maps; 17import com.google.common.collect.Maps;
16 18
17import cuchaz.enigma.analysis.TranslationIndex; 19import cuchaz.enigma.analysis.TranslationIndex;
@@ -50,54 +52,106 @@ public class Translator {
50 } 52 }
51 } 53 }
52 54
55 public <T extends Entry> String translate(T entry) {
56 if (entry instanceof ClassEntry) {
57 return translate((ClassEntry)entry);
58 } else if (entry instanceof FieldEntry) {
59 return translate((FieldEntry)entry);
60 } else if (entry instanceof MethodEntry) {
61 return translate((MethodEntry)entry);
62 } else if (entry instanceof ConstructorEntry) {
63 return translate((ConstructorEntry)entry);
64 } else if (entry instanceof ArgumentEntry) {
65 return translate((ArgumentEntry)entry);
66 } else {
67 throw new Error("Unknown entry type: " + entry.getClass().getName());
68 }
69 }
70
53 public String translateClass(String className) { 71 public String translateClass(String className) {
54 return translate(new ClassEntry(className)); 72 return translate(new ClassEntry(className));
55 } 73 }
56 74
57 public String translate(ClassEntry in) { 75 public String translate(ClassEntry in) {
58 ClassMapping classMapping = m_classes.get(in.getOuterClassName()); 76
59 if (classMapping != null) { 77 if (in.isInnerClass()) {
60 if (in.isInnerClass()) { 78
61 // translate the inner class 79 // translate everything in the class chain, or return null
62 String translatedInnerClassName = m_direction.choose( 80 List<ClassMapping> mappingsChain = getClassMappingChain(in);
63 classMapping.getDeobfInnerClassName(in.getInnerClassName()), 81 StringBuilder buf = new StringBuilder();
64 classMapping.getObfInnerClassName(in.getInnerClassName()) 82 for (ClassMapping classMapping : mappingsChain) {
83 if (classMapping == null) {
84 return null;
85 }
86 boolean isFirstClass = buf.length() == 0;
87 String name = m_direction.choose(
88 classMapping.getDeobfName(),
89 isFirstClass ? classMapping.getObfFullName() : classMapping.getObfSimpleName()
65 ); 90 );
66 if (translatedInnerClassName != null) { 91 if (name == null) {
67 // try to translate the outer name 92 return null;
68 String translatedOuterClassName = m_direction.choose(classMapping.getDeobfName(), classMapping.getObfName()); 93 }
69 if (translatedOuterClassName != null) { 94 if (!isFirstClass) {
70 return translatedOuterClassName + "$" + translatedInnerClassName; 95 buf.append("$");
71 } else {
72 return in.getOuterClassName() + "$" + translatedInnerClassName;
73 }
74 } 96 }
75 } else { 97 buf.append(name);
76 // just return outer
77 return m_direction.choose(classMapping.getDeobfName(), classMapping.getObfName());
78 } 98 }
99 return buf.toString();
100
101 } else {
102
103 // normal classes are easier
104 ClassMapping classMapping = m_classes.get(in.getName());
105 if (classMapping == null) {
106 return null;
107 }
108 return m_direction.choose(
109 classMapping.getDeobfName(),
110 classMapping.getObfFullName()
111 );
79 } 112 }
80 return null;
81 } 113 }
82 114
83 public ClassEntry translateEntry(ClassEntry in) { 115 public ClassEntry translateEntry(ClassEntry in) {
84 116
85 // can we translate the inner class?
86 String name = translate(in);
87 if (name != null) {
88 return new ClassEntry(name);
89 }
90
91 if (in.isInnerClass()) { 117 if (in.isInnerClass()) {
92 118
93 // guess not. just translate the outer class name then 119 // translate as much of the class chain as we can
94 String outerClassName = translate(in.getOuterClassEntry()); 120 List<ClassMapping> mappingsChain = getClassMappingChain(in);
95 if (outerClassName != null) { 121 String[] obfClassNames = in.getName().split("\\$");
96 return new ClassEntry(outerClassName + "$" + in.getInnerClassName()); 122 StringBuilder buf = new StringBuilder();
123 for (int i=0; i<obfClassNames.length; i++) {
124 boolean isFirstClass = buf.length() == 0;
125 String className = null;
126 ClassMapping classMapping = mappingsChain.get(i);
127 if (classMapping != null) {
128 className = m_direction.choose(
129 classMapping.getDeobfName(),
130 isFirstClass ? classMapping.getObfFullName() : classMapping.getObfSimpleName()
131 );
132 }
133 if (className == null) {
134 className = obfClassNames[i];
135 }
136 if (!isFirstClass) {
137 buf.append("$");
138 }
139 buf.append(className);
97 } 140 }
141 return new ClassEntry(buf.toString());
142
143 } else {
144
145 // normal classes are easy
146 ClassMapping classMapping = m_classes.get(in.getName());
147 if (classMapping == null) {
148 return in;
149 }
150 return m_direction.choose(
151 classMapping.getDeobfName() != null ? new ClassEntry(classMapping.getDeobfName()) : in,
152 new ClassEntry(classMapping.getObfFullName())
153 );
98 } 154 }
99
100 return in;
101 } 155 }
102 156
103 public String translate(FieldEntry in) { 157 public String translate(FieldEntry in) {
@@ -226,14 +280,36 @@ public class Translator {
226 }); 280 });
227 } 281 }
228 282
229 private ClassMapping findClassMapping(ClassEntry classEntry) { 283 private ClassMapping findClassMapping(ClassEntry in) {
230 ClassMapping classMapping = m_classes.get(classEntry.getOuterClassName()); 284 List<ClassMapping> mappingChain = getClassMappingChain(in);
231 if (classMapping != null && classEntry.isInnerClass()) { 285 return mappingChain.get(mappingChain.size() - 1);
232 classMapping = m_direction.choose( 286 }
233 classMapping.getInnerClassByObf(classEntry.getInnerClassName()), 287
234 classMapping.getInnerClassByDeobfThenObf(classEntry.getInnerClassName()) 288 private List<ClassMapping> getClassMappingChain(ClassEntry in) {
235 ); 289
290 // get a list of all the classes in the hierarchy
291 String[] parts = in.getName().split("\\$");
292 List<ClassMapping> mappingsChain = Lists.newArrayList();
293
294 // get mappings for the outer class
295 ClassMapping outerClassMapping = m_classes.get(parts[0]);
296 mappingsChain.add(outerClassMapping);
297
298 for (int i=1; i<parts.length; i++) {
299
300 // get mappings for the inner class
301 ClassMapping innerClassMapping = null;
302 if (outerClassMapping != null) {
303 innerClassMapping = m_direction.choose(
304 outerClassMapping.getInnerClassByObf(parts[i]),
305 outerClassMapping.getInnerClassByDeobfThenObf(parts[i])
306 );
307 }
308 mappingsChain.add(innerClassMapping);
309 outerClassMapping = innerClassMapping;
236 } 310 }
237 return classMapping; 311
312 assert(mappingsChain.size() == parts.length);
313 return mappingsChain;
238 } 314 }
239} 315}