summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar jeff2015-03-16 12:29:17 -0400
committerGravatar jeff2015-03-16 12:29:17 -0400
commitc133e05b786ff5357931842581571c046f958c74 (patch)
tree9fc998ac7b85828f3b57f04600244c6a79b2b2e8 /src
parentAdded tag v0.9 beta for changeset 856528c00d1c (diff)
downloadenigma-c133e05b786ff5357931842581571c046f958c74.tar.gz
enigma-c133e05b786ff5357931842581571c046f958c74.tar.xz
enigma-c133e05b786ff5357931842581571c046f958c74.zip
fix a zillion issues with inner classes
Diffstat (limited to 'src')
-rw-r--r--src/cuchaz/enigma/Deobfuscator.java8
-rw-r--r--src/cuchaz/enigma/TranslatingTypeLoader.java2
-rw-r--r--src/cuchaz/enigma/analysis/EntryReference.java2
-rw-r--r--src/cuchaz/enigma/analysis/JarIndex.java2
-rw-r--r--src/cuchaz/enigma/bytecode/ClassRenamer.java2
-rw-r--r--src/cuchaz/enigma/bytecode/ClassTranslator.java17
-rw-r--r--src/cuchaz/enigma/bytecode/InnerClassWriter.java4
-rw-r--r--src/cuchaz/enigma/convert/ClassIdentity.java2
-rw-r--r--src/cuchaz/enigma/convert/MappingsConverter.java2
-rw-r--r--src/cuchaz/enigma/gui/CodeReader.java2
-rw-r--r--src/cuchaz/enigma/gui/GuiController.java2
-rw-r--r--src/cuchaz/enigma/mapping/ClassEntry.java31
-rw-r--r--src/cuchaz/enigma/mapping/ClassMapping.java79
-rw-r--r--src/cuchaz/enigma/mapping/Mappings.java28
-rw-r--r--src/cuchaz/enigma/mapping/MappingsRenamer.java128
-rw-r--r--src/cuchaz/enigma/mapping/Translator.java73
16 files changed, 198 insertions, 186 deletions
diff --git a/src/cuchaz/enigma/Deobfuscator.java b/src/cuchaz/enigma/Deobfuscator.java
index f5012bde..5a23ce5b 100644
--- a/src/cuchaz/enigma/Deobfuscator.java
+++ b/src/cuchaz/enigma/Deobfuscator.java
@@ -438,7 +438,13 @@ public class Deobfuscator {
438 public boolean hasDeobfuscatedName(Entry obfEntry) { 438 public boolean hasDeobfuscatedName(Entry obfEntry) {
439 Translator translator = getTranslator(TranslationDirection.Deobfuscating); 439 Translator translator = getTranslator(TranslationDirection.Deobfuscating);
440 if (obfEntry instanceof ClassEntry) { 440 if (obfEntry instanceof ClassEntry) {
441 return translator.translate((ClassEntry)obfEntry) != null; 441 ClassEntry obfClass = (ClassEntry)obfEntry;
442 ClassEntry translated = translator.translateEntry(obfClass);
443 if (obfClass.isInnerClass()) {
444 return !obfClass.getInnermostClassName().equals(translated.getInnermostClassName());
445 } else {
446 return !obfClass.equals(translated);
447 }
442 } else if (obfEntry instanceof FieldEntry) { 448 } else if (obfEntry instanceof FieldEntry) {
443 return translator.translate((FieldEntry)obfEntry) != null; 449 return translator.translate((FieldEntry)obfEntry) != null;
444 } else if (obfEntry instanceof MethodEntry) { 450 } else if (obfEntry instanceof MethodEntry) {
diff --git a/src/cuchaz/enigma/TranslatingTypeLoader.java b/src/cuchaz/enigma/TranslatingTypeLoader.java
index 7b57cfa7..ecd7d642 100644
--- a/src/cuchaz/enigma/TranslatingTypeLoader.java
+++ b/src/cuchaz/enigma/TranslatingTypeLoader.java
@@ -205,7 +205,7 @@ public class TranslatingTypeLoader implements ITypeLoader {
205 } 205 }
206 if (obfClassEntry.isInnerClass()) { 206 if (obfClassEntry.isInnerClass()) {
207 // try just the inner class name 207 // try just the inner class name
208 classNamesToTry.add(obfClassEntry.getInnerClassName()); 208 classNamesToTry.add(obfClassEntry.getInnermostClassName());
209 } 209 }
210 return classNamesToTry; 210 return classNamesToTry;
211 } 211 }
diff --git a/src/cuchaz/enigma/analysis/EntryReference.java b/src/cuchaz/enigma/analysis/EntryReference.java
index bb611df5..d0a5c6af 100644
--- a/src/cuchaz/enigma/analysis/EntryReference.java
+++ b/src/cuchaz/enigma/analysis/EntryReference.java
@@ -74,7 +74,7 @@ public class EntryReference<E extends Entry,C extends Entry> {
74 ClassEntry classEntry = (ClassEntry)getNameableEntry(); 74 ClassEntry classEntry = (ClassEntry)getNameableEntry();
75 if (classEntry.isInnerClass()) { 75 if (classEntry.isInnerClass()) {
76 // make sure we only rename the inner class name 76 // make sure we only rename the inner class name
77 return classEntry.getInnerClassName(); 77 return classEntry.getInnermostClassName();
78 } 78 }
79 } 79 }
80 80
diff --git a/src/cuchaz/enigma/analysis/JarIndex.java b/src/cuchaz/enigma/analysis/JarIndex.java
index 7ebbd974..a4a3abb8 100644
--- a/src/cuchaz/enigma/analysis/JarIndex.java
+++ b/src/cuchaz/enigma/analysis/JarIndex.java
@@ -312,7 +312,7 @@ public class JarIndex {
312 312
313 // does this class already have an outer class? 313 // does this class already have an outer class?
314 if (classEntry.isInnerClass()) { 314 if (classEntry.isInnerClass()) {
315 return classEntry.getOuterClassEntry(); 315 return classEntry.getOutermostClassEntry();
316 } 316 }
317 InnerClassesAttribute innerClassesAttribute = (InnerClassesAttribute)c.getClassFile().getAttribute(InnerClassesAttribute.tag); 317 InnerClassesAttribute innerClassesAttribute = (InnerClassesAttribute)c.getClassFile().getAttribute(InnerClassesAttribute.tag);
318 if (innerClassesAttribute != null) { 318 if (innerClassesAttribute != null) {
diff --git a/src/cuchaz/enigma/bytecode/ClassRenamer.java b/src/cuchaz/enigma/bytecode/ClassRenamer.java
index a5fea926..e9cdea3c 100644
--- a/src/cuchaz/enigma/bytecode/ClassRenamer.java
+++ b/src/cuchaz/enigma/bytecode/ClassRenamer.java
@@ -43,7 +43,7 @@ public class ClassRenamer {
43 for (int i = 0; i < attr.tableLength(); i++) { 43 for (int i = 0; i < attr.tableLength(); i++) {
44 ClassEntry classEntry = new ClassEntry(Descriptor.toJvmName(attr.innerClass(i))); 44 ClassEntry classEntry = new ClassEntry(Descriptor.toJvmName(attr.innerClass(i)));
45 if (attr.innerNameIndex(i) != 0) { 45 if (attr.innerNameIndex(i) != 0) {
46 attr.setInnerNameIndex(i, constants.addUtf8Info(classEntry.getInnerClassName())); 46 attr.setInnerNameIndex(i, constants.addUtf8Info(classEntry.getInnermostClassName()));
47 } 47 }
48 48
49 /* DEBUG 49 /* DEBUG
diff --git a/src/cuchaz/enigma/bytecode/ClassTranslator.java b/src/cuchaz/enigma/bytecode/ClassTranslator.java
index 4167731a..94ab2c4b 100644
--- a/src/cuchaz/enigma/bytecode/ClassTranslator.java
+++ b/src/cuchaz/enigma/bytecode/ClassTranslator.java
@@ -26,7 +26,6 @@ import cuchaz.enigma.mapping.BehaviorEntry;
26import cuchaz.enigma.mapping.ClassEntry; 26import cuchaz.enigma.mapping.ClassEntry;
27import cuchaz.enigma.mapping.EntryFactory; 27import cuchaz.enigma.mapping.EntryFactory;
28import cuchaz.enigma.mapping.FieldEntry; 28import cuchaz.enigma.mapping.FieldEntry;
29import cuchaz.enigma.mapping.MethodEntry;
30import cuchaz.enigma.mapping.Signature; 29import cuchaz.enigma.mapping.Signature;
31import cuchaz.enigma.mapping.Translator; 30import cuchaz.enigma.mapping.Translator;
32import cuchaz.enigma.mapping.Type; 31import cuchaz.enigma.mapping.Type;
@@ -101,26 +100,30 @@ public class ClassTranslator {
101 } 100 }
102 101
103 // translate the type 102 // translate the type
104 Type translatedType = m_translator.translateType(new Type(field.getFieldInfo().getDescriptor())); 103 Type translatedType = m_translator.translateType(entry.getType());
105 field.getFieldInfo().setDescriptor(translatedType.toString()); 104 field.getFieldInfo().setDescriptor(translatedType.toString());
106 } 105 }
107 106
108 // translate all the methods and constructors 107 // translate all the methods and constructors
109 for (CtBehavior behavior : c.getDeclaredBehaviors()) { 108 for (CtBehavior behavior : c.getDeclaredBehaviors()) {
109
110 BehaviorEntry entry = EntryFactory.getBehaviorEntry(behavior);
111
110 if (behavior instanceof CtMethod) { 112 if (behavior instanceof CtMethod) {
111 CtMethod method = (CtMethod)behavior; 113 CtMethod method = (CtMethod)behavior;
112 114
113 // translate the name 115 // translate the name
114 MethodEntry entry = EntryFactory.getMethodEntry(method);
115 String translatedName = m_translator.translate(entry); 116 String translatedName = m_translator.translate(entry);
116 if (translatedName != null) { 117 if (translatedName != null) {
117 method.setName(translatedName); 118 method.setName(translatedName);
118 } 119 }
119 } 120 }
120 121
121 // translate the type 122 if (entry.getSignature() != null) {
122 Signature translatedSignature = m_translator.translateSignature(new Signature(behavior.getMethodInfo().getDescriptor())); 123 // translate the type
123 behavior.getMethodInfo().setDescriptor(translatedSignature.toString()); 124 Signature translatedSignature = m_translator.translateSignature(entry.getSignature());
125 behavior.getMethodInfo().setDescriptor(translatedSignature.toString());
126 }
124 } 127 }
125 128
126 // translate all the class names referenced in the code 129 // translate all the class names referenced in the code
@@ -137,7 +140,7 @@ public class ClassTranslator {
137 // translate the source file attribute too 140 // translate the source file attribute too
138 ClassEntry deobfClassEntry = map.get(classEntry); 141 ClassEntry deobfClassEntry = map.get(classEntry);
139 if (deobfClassEntry != null) { 142 if (deobfClassEntry != null) {
140 String sourceFile = Descriptor.toJvmName(deobfClassEntry.getOuterClassName()) + ".java"; 143 String sourceFile = Descriptor.toJvmName(deobfClassEntry.getOutermostClassName()) + ".java";
141 c.getClassFile().addAttribute(new SourceFileAttribute(constants, sourceFile)); 144 c.getClassFile().addAttribute(new SourceFileAttribute(constants, sourceFile));
142 } 145 }
143 } 146 }
diff --git a/src/cuchaz/enigma/bytecode/InnerClassWriter.java b/src/cuchaz/enigma/bytecode/InnerClassWriter.java
index dd21a780..976028d2 100644
--- a/src/cuchaz/enigma/bytecode/InnerClassWriter.java
+++ b/src/cuchaz/enigma/bytecode/InnerClassWriter.java
@@ -93,7 +93,7 @@ public class InnerClassWriter {
93 93
94 // get the new inner class name 94 // get the new inner class name
95 ClassEntry obfInnerClassEntry = obfClassEntry.buildClassEntry(obfClassChain); 95 ClassEntry obfInnerClassEntry = obfClassEntry.buildClassEntry(obfClassChain);
96 ClassEntry obfOuterClassEntry = obfInnerClassEntry.getOuterClassEntry(); 96 ClassEntry obfOuterClassEntry = obfInnerClassEntry.getOutermostClassEntry();
97 97
98 // here's what the JVM spec says about the InnerClasses attribute 98 // here's what the JVM spec says about the InnerClasses attribute
99 // append(inner, parent, 0 if anonymous else simple name, flags); 99 // append(inner, parent, 0 if anonymous else simple name, flags);
@@ -105,7 +105,7 @@ public class InnerClassWriter {
105 int innerClassNameIndex = 0; 105 int innerClassNameIndex = 0;
106 int accessFlags = 0; 106 int accessFlags = 0;
107 if (!m_index.isAnonymousClass(obfClassEntry)) { 107 if (!m_index.isAnonymousClass(obfClassEntry)) {
108 innerClassNameIndex = constPool.addUtf8Info(obfInnerClassEntry.getInnerClassName()); 108 innerClassNameIndex = constPool.addUtf8Info(obfInnerClassEntry.getInnermostClassName());
109 } 109 }
110 110
111 attr.append(innerClassIndex, parentClassIndex, innerClassNameIndex, accessFlags); 111 attr.append(innerClassIndex, parentClassIndex, innerClassNameIndex, accessFlags);
diff --git a/src/cuchaz/enigma/convert/ClassIdentity.java b/src/cuchaz/enigma/convert/ClassIdentity.java
index 35667b05..d76cd63e 100644
--- a/src/cuchaz/enigma/convert/ClassIdentity.java
+++ b/src/cuchaz/enigma/convert/ClassIdentity.java
@@ -180,7 +180,7 @@ public class ClassIdentity {
180 } 180 }
181 } 181 }
182 182
183 m_outer = EntryFactory.getClassEntry(c).getOuterClassName(); 183 m_outer = EntryFactory.getClassEntry(c).getOutermostClassName();
184 } 184 }
185 185
186 private void addReference(EntryReference<? extends Entry,BehaviorEntry> reference) { 186 private void addReference(EntryReference<? extends Entry,BehaviorEntry> reference) {
diff --git a/src/cuchaz/enigma/convert/MappingsConverter.java b/src/cuchaz/enigma/convert/MappingsConverter.java
index ddd3a53c..2afa1208 100644
--- a/src/cuchaz/enigma/convert/MappingsConverter.java
+++ b/src/cuchaz/enigma/convert/MappingsConverter.java
@@ -169,7 +169,7 @@ public class MappingsConverter {
169 newMappings.addClassMapping(destMapping); 169 newMappings.addClassMapping(destMapping);
170 } 170 }
171 } else { 171 } else {
172 destMapping = destMapping.getInnerClassByObf(destChainClassEntry.getInnerClassName()); 172 destMapping = destMapping.getInnerClassByObfSimple(destChainClassEntry.getInnermostClassName());
173 if (destMapping == null) { 173 if (destMapping == null) {
174 destMapping = new ClassMapping(destChainClassEntry.getName()); 174 destMapping = new ClassMapping(destChainClassEntry.getName());
175 destMapping.addInnerClassMapping(destMapping); 175 destMapping.addInnerClassMapping(destMapping);
diff --git a/src/cuchaz/enigma/gui/CodeReader.java b/src/cuchaz/enigma/gui/CodeReader.java
index 743ef2e4..fb8e0825 100644
--- a/src/cuchaz/enigma/gui/CodeReader.java
+++ b/src/cuchaz/enigma/gui/CodeReader.java
@@ -106,7 +106,7 @@ public class CodeReader extends JEditorPane {
106 // get the outermost class 106 // get the outermost class
107 ClassEntry outermostClassEntry = classEntry; 107 ClassEntry outermostClassEntry = classEntry;
108 while (outermostClassEntry.isInnerClass()) { 108 while (outermostClassEntry.isInnerClass()) {
109 outermostClassEntry = outermostClassEntry.getOuterClassEntry(); 109 outermostClassEntry = outermostClassEntry.getOutermostClassEntry();
110 } 110 }
111 111
112 // decompile it 112 // decompile it
diff --git a/src/cuchaz/enigma/gui/GuiController.java b/src/cuchaz/enigma/gui/GuiController.java
index 9fa633eb..552ee47c 100644
--- a/src/cuchaz/enigma/gui/GuiController.java
+++ b/src/cuchaz/enigma/gui/GuiController.java
@@ -257,7 +257,7 @@ public class GuiController {
257 257
258 // get the reference target class 258 // get the reference target class
259 EntryReference<Entry,Entry> obfReference = m_deobfuscator.obfuscateReference(deobfReference); 259 EntryReference<Entry,Entry> obfReference = m_deobfuscator.obfuscateReference(deobfReference);
260 ClassEntry obfClassEntry = obfReference.getLocationClassEntry().getOuterClassEntry(); 260 ClassEntry obfClassEntry = obfReference.getLocationClassEntry().getOutermostClassEntry();
261 if (!m_deobfuscator.isObfuscatedIdentifier(obfClassEntry)) { 261 if (!m_deobfuscator.isObfuscatedIdentifier(obfClassEntry)) {
262 throw new IllegalArgumentException("Obfuscated class " + obfClassEntry + " was not found in the jar!"); 262 throw new IllegalArgumentException("Obfuscated class " + obfClassEntry + " was not found in the jar!");
263 } 263 }
diff --git a/src/cuchaz/enigma/mapping/ClassEntry.java b/src/cuchaz/enigma/mapping/ClassEntry.java
index 69e66bc0..5f3b5e23 100644
--- a/src/cuchaz/enigma/mapping/ClassEntry.java
+++ b/src/cuchaz/enigma/mapping/ClassEntry.java
@@ -13,6 +13,8 @@ package cuchaz.enigma.mapping;
13import java.io.Serializable; 13import java.io.Serializable;
14import java.util.List; 14import java.util.List;
15 15
16import com.beust.jcommander.internal.Lists;
17
16public class ClassEntry implements Entry, Serializable { 18public class ClassEntry implements Entry, Serializable {
17 19
18 private static final long serialVersionUID = 4235460580973955811L; 20 private static final long serialVersionUID = 4235460580973955811L;
@@ -29,7 +31,7 @@ public class ClassEntry implements Entry, Serializable {
29 31
30 m_name = className; 32 m_name = className;
31 33
32 if (isInnerClass() && getInnerClassName().indexOf('/') >= 0) { 34 if (isInnerClass() && getInnermostClassName().indexOf('/') >= 0) {
33 throw new IllegalArgumentException("Inner class must not have a package: " + className); 35 throw new IllegalArgumentException("Inner class must not have a package: " + className);
34 } 36 }
35 } 37 }
@@ -84,22 +86,39 @@ public class ClassEntry implements Entry, Serializable {
84 return m_name.lastIndexOf('$') >= 0; 86 return m_name.lastIndexOf('$') >= 0;
85 } 87 }
86 88
87 public String getOuterClassName() { 89 public List<String> getClassChainNames() {
90 return Lists.newArrayList(m_name.split("\\$"));
91 }
92
93 public List<ClassEntry> getClassChain() {
94 List<ClassEntry> entries = Lists.newArrayList();
95 StringBuilder buf = new StringBuilder();
96 for (String name : getClassChainNames()) {
97 if (buf.length() > 0) {
98 buf.append("$");
99 }
100 buf.append(name);
101 entries.add(new ClassEntry(buf.toString()));
102 }
103 return entries;
104 }
105
106 public String getOutermostClassName() {
88 if (isInnerClass()) { 107 if (isInnerClass()) {
89 return m_name.substring(0, m_name.lastIndexOf('$')); 108 return m_name.substring(0, m_name.lastIndexOf('$'));
90 } 109 }
91 return m_name; 110 return m_name;
92 } 111 }
93 112
94 public String getInnerClassName() { 113 public String getInnermostClassName() {
95 if (!isInnerClass()) { 114 if (!isInnerClass()) {
96 throw new Error("This is not an inner class!"); 115 throw new Error("This is not an inner class!");
97 } 116 }
98 return m_name.substring(m_name.lastIndexOf('$') + 1); 117 return m_name.substring(m_name.lastIndexOf('$') + 1);
99 } 118 }
100 119
101 public ClassEntry getOuterClassEntry() { 120 public ClassEntry getOutermostClassEntry() {
102 return new ClassEntry(getOuterClassName()); 121 return new ClassEntry(getOutermostClassName());
103 } 122 }
104 123
105 public boolean isInDefaultPackage() { 124 public boolean isInDefaultPackage() {
@@ -130,7 +149,7 @@ public class ClassEntry implements Entry, Serializable {
130 buf.append(chainEntry.getName()); 149 buf.append(chainEntry.getName());
131 } else { 150 } else {
132 buf.append("$"); 151 buf.append("$");
133 buf.append(chainEntry.isInnerClass() ? chainEntry.getInnerClassName() : chainEntry.getSimpleName()); 152 buf.append(chainEntry.isInnerClass() ? chainEntry.getInnermostClassName() : chainEntry.getSimpleName());
134 } 153 }
135 154
136 if (chainEntry == this) { 155 if (chainEntry == this) {
diff --git a/src/cuchaz/enigma/mapping/ClassMapping.java b/src/cuchaz/enigma/mapping/ClassMapping.java
index 38cd3d6d..6e7fd17b 100644
--- a/src/cuchaz/enigma/mapping/ClassMapping.java
+++ b/src/cuchaz/enigma/mapping/ClassMapping.java
@@ -23,22 +23,23 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping> {
23 private String m_obfFullName; 23 private String m_obfFullName;
24 private String m_obfSimpleName; 24 private String m_obfSimpleName;
25 private String m_deobfName; 25 private String m_deobfName;
26 private Map<String,ClassMapping> m_innerClassesByObf; 26 private Map<String,ClassMapping> m_innerClassesByObfSimple;
27 private Map<String,ClassMapping> m_innerClassesByDeobf; 27 private Map<String,ClassMapping> m_innerClassesByDeobf;
28 private Map<String,FieldMapping> m_fieldsByObf; 28 private Map<String,FieldMapping> m_fieldsByObf;
29 private Map<String,FieldMapping> m_fieldsByDeobf; 29 private Map<String,FieldMapping> m_fieldsByDeobf;
30 private Map<String,MethodMapping> m_methodsByObf; 30 private Map<String,MethodMapping> m_methodsByObf;
31 private Map<String,MethodMapping> m_methodsByDeobf; 31 private Map<String,MethodMapping> m_methodsByDeobf;
32 32
33 public ClassMapping(String obfName) { 33 public ClassMapping(String obfFullName) {
34 this(obfName, null); 34 this(obfFullName, null);
35 } 35 }
36 36
37 public ClassMapping(String obfName, String deobfName) { 37 public ClassMapping(String obfFullName, String deobfName) {
38 m_obfFullName = obfName; 38 m_obfFullName = obfFullName;
39 m_obfSimpleName = new ClassEntry(obfName).getSimpleName(); 39 ClassEntry classEntry = new ClassEntry(obfFullName);
40 m_obfSimpleName = classEntry.isInnerClass() ? classEntry.getInnermostClassName() : classEntry.getSimpleName();
40 m_deobfName = NameValidator.validateClassName(deobfName, false); 41 m_deobfName = NameValidator.validateClassName(deobfName, false);
41 m_innerClassesByObf = Maps.newHashMap(); 42 m_innerClassesByObfSimple = Maps.newHashMap();
42 m_innerClassesByDeobf = Maps.newHashMap(); 43 m_innerClassesByDeobf = Maps.newHashMap();
43 m_fieldsByObf = Maps.newHashMap(); 44 m_fieldsByObf = Maps.newHashMap();
44 m_fieldsByDeobf = Maps.newHashMap(); 45 m_fieldsByDeobf = Maps.newHashMap();
@@ -65,12 +66,12 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping> {
65 //// INNER CLASSES //////// 66 //// INNER CLASSES ////////
66 67
67 public Iterable<ClassMapping> innerClasses() { 68 public Iterable<ClassMapping> innerClasses() {
68 assert (m_innerClassesByObf.size() >= m_innerClassesByDeobf.size()); 69 assert (m_innerClassesByObfSimple.size() >= m_innerClassesByDeobf.size());
69 return m_innerClassesByObf.values(); 70 return m_innerClassesByObfSimple.values();
70 } 71 }
71 72
72 public void addInnerClassMapping(ClassMapping classMapping) { 73 public void addInnerClassMapping(ClassMapping classMapping) {
73 boolean obfWasAdded = m_innerClassesByObf.put(classMapping.getObfSimpleName(), classMapping) == null; 74 boolean obfWasAdded = m_innerClassesByObfSimple.put(classMapping.getObfSimpleName(), classMapping) == null;
74 assert (obfWasAdded); 75 assert (obfWasAdded);
75 if (classMapping.getDeobfName() != null) { 76 if (classMapping.getDeobfName() != null) {
76 assert (isSimpleClassName(classMapping.getDeobfName())); 77 assert (isSimpleClassName(classMapping.getDeobfName()));
@@ -80,7 +81,7 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping> {
80 } 81 }
81 82
82 public void removeInnerClassMapping(ClassMapping classMapping) { 83 public void removeInnerClassMapping(ClassMapping classMapping) {
83 boolean obfWasRemoved = m_innerClassesByObf.remove(classMapping.getObfSimpleName()) != null; 84 boolean obfWasRemoved = m_innerClassesByObfSimple.remove(classMapping.getObfSimpleName()) != null;
84 assert (obfWasRemoved); 85 assert (obfWasRemoved);
85 if (classMapping.getDeobfName() != null) { 86 if (classMapping.getDeobfName() != null) {
86 boolean deobfWasRemoved = m_innerClassesByDeobf.remove(classMapping.getDeobfName()) != null; 87 boolean deobfWasRemoved = m_innerClassesByDeobf.remove(classMapping.getDeobfName()) != null;
@@ -88,20 +89,19 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping> {
88 } 89 }
89 } 90 }
90 91
91 public ClassMapping getOrCreateInnerClass(String obfName) { 92 public ClassMapping getOrCreateInnerClass(ClassEntry obfInnerClass) {
92 assert (isSimpleClassName(obfName)); 93 ClassMapping classMapping = m_innerClassesByObfSimple.get(obfInnerClass.getInnermostClassName());
93 ClassMapping classMapping = m_innerClassesByObf.get(obfName);
94 if (classMapping == null) { 94 if (classMapping == null) {
95 classMapping = new ClassMapping(obfName); 95 classMapping = new ClassMapping(obfInnerClass.getName());
96 boolean wasAdded = m_innerClassesByObf.put(obfName, classMapping) == null; 96 boolean wasAdded = m_innerClassesByObfSimple.put(classMapping.getObfSimpleName(), classMapping) == null;
97 assert (wasAdded); 97 assert (wasAdded);
98 } 98 }
99 return classMapping; 99 return classMapping;
100 } 100 }
101 101
102 public ClassMapping getInnerClassByObf(String obfName) { 102 public ClassMapping getInnerClassByObfSimple(String obfSimpleName) {
103 assert (isSimpleClassName(obfName)); 103 assert (isSimpleClassName(obfSimpleName));
104 return m_innerClassesByObf.get(obfName); 104 return m_innerClassesByObfSimple.get(obfSimpleName);
105 } 105 }
106 106
107 public ClassMapping getInnerClassByDeobf(String deobfName) { 107 public ClassMapping getInnerClassByDeobf(String deobfName) {
@@ -109,35 +109,25 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping> {
109 return m_innerClassesByDeobf.get(deobfName); 109 return m_innerClassesByDeobf.get(deobfName);
110 } 110 }
111 111
112 public ClassMapping getInnerClassByDeobfThenObf(String name) { 112 public ClassMapping getInnerClassByDeobfThenObfSimple(String name) {
113 ClassMapping classMapping = getInnerClassByDeobf(name); 113 ClassMapping classMapping = getInnerClassByDeobf(name);
114 if (classMapping == null) { 114 if (classMapping == null) {
115 classMapping = getInnerClassByObf(name); 115 classMapping = getInnerClassByObfSimple(name);
116 } 116 }
117 return classMapping; 117 return classMapping;
118 } 118 }
119 119
120 public String getObfInnerClassSimpleName(String deobfName) { 120 public String getDeobfInnerClassName(String obfSimpleName) {
121 assert (isSimpleClassName(deobfName)); 121 assert (isSimpleClassName(obfSimpleName));
122 ClassMapping classMapping = m_innerClassesByDeobf.get(deobfName); 122 ClassMapping classMapping = m_innerClassesByObfSimple.get(obfSimpleName);
123 if (classMapping != null) {
124 return classMapping.getObfSimpleName();
125 }
126 return null;
127 }
128
129 public String getDeobfInnerClassName(String obfName) {
130 assert (isSimpleClassName(obfName));
131 ClassMapping classMapping = m_innerClassesByObf.get(obfName);
132 if (classMapping != null) { 123 if (classMapping != null) {
133 return classMapping.getDeobfName(); 124 return classMapping.getDeobfName();
134 } 125 }
135 return null; 126 return null;
136 } 127 }
137 128
138 public void setInnerClassName(String obfName, String deobfName) { 129 public void setInnerClassName(ClassEntry obfInnerClass, String deobfName) {
139 assert (isSimpleClassName(obfName)); 130 ClassMapping classMapping = getOrCreateInnerClass(obfInnerClass);
140 ClassMapping classMapping = getOrCreateInnerClass(obfName);
141 if (classMapping.getDeobfName() != null) { 131 if (classMapping.getDeobfName() != null) {
142 boolean wasRemoved = m_innerClassesByDeobf.remove(classMapping.getDeobfName()) != null; 132 boolean wasRemoved = m_innerClassesByDeobf.remove(classMapping.getDeobfName()) != null;
143 assert (wasRemoved); 133 assert (wasRemoved);
@@ -150,6 +140,15 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping> {
150 } 140 }
151 } 141 }
152 142
143 public boolean hasInnerClassByObfSimple(String obfSimpleName) {
144 return m_innerClassesByObfSimple.containsKey(obfSimpleName);
145 }
146
147 public boolean hasInnerClassByDeobf(String deobfName) {
148 return m_innerClassesByDeobf.containsKey(deobfName);
149 }
150
151
153 //// FIELDS //////// 152 //// FIELDS ////////
154 153
155 public Iterable<FieldMapping> fields() { 154 public Iterable<FieldMapping> fields() {
@@ -382,7 +381,7 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping> {
382 buf.append("\n"); 381 buf.append("\n");
383 } 382 }
384 buf.append("Inner Classes:\n"); 383 buf.append("Inner Classes:\n");
385 for (ClassMapping classMapping : m_innerClassesByObf.values()) { 384 for (ClassMapping classMapping : m_innerClassesByObfSimple.values()) {
386 buf.append("\t"); 385 buf.append("\t");
387 buf.append(classMapping.getObfSimpleName()); 386 buf.append(classMapping.getObfSimpleName());
388 buf.append(" <-> "); 387 buf.append(" <-> ");
@@ -404,11 +403,11 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping> {
404 public boolean renameObfClass(String oldObfClassName, String newObfClassName) { 403 public boolean renameObfClass(String oldObfClassName, String newObfClassName) {
405 404
406 // rename inner classes 405 // rename inner classes
407 for (ClassMapping innerClassMapping : new ArrayList<ClassMapping>(m_innerClassesByObf.values())) { 406 for (ClassMapping innerClassMapping : new ArrayList<ClassMapping>(m_innerClassesByObfSimple.values())) {
408 if (innerClassMapping.renameObfClass(oldObfClassName, newObfClassName)) { 407 if (innerClassMapping.renameObfClass(oldObfClassName, newObfClassName)) {
409 boolean wasRemoved = m_innerClassesByObf.remove(oldObfClassName) != null; 408 boolean wasRemoved = m_innerClassesByObfSimple.remove(oldObfClassName) != null;
410 assert (wasRemoved); 409 assert (wasRemoved);
411 boolean wasAdded = m_innerClassesByObf.put(newObfClassName, innerClassMapping) == null; 410 boolean wasAdded = m_innerClassesByObfSimple.put(newObfClassName, innerClassMapping) == null;
412 assert (wasAdded); 411 assert (wasAdded);
413 } 412 }
414 } 413 }
diff --git a/src/cuchaz/enigma/mapping/Mappings.java b/src/cuchaz/enigma/mapping/Mappings.java
index a85bcbf6..659d23ac 100644
--- a/src/cuchaz/enigma/mapping/Mappings.java
+++ b/src/cuchaz/enigma/mapping/Mappings.java
@@ -13,9 +13,11 @@ package cuchaz.enigma.mapping;
13import java.io.Serializable; 13import java.io.Serializable;
14import java.util.ArrayList; 14import java.util.ArrayList;
15import java.util.Collection; 15import java.util.Collection;
16import java.util.List;
16import java.util.Map; 17import java.util.Map;
17import java.util.Set; 18import java.util.Set;
18 19
20import com.beust.jcommander.internal.Lists;
19import com.google.common.collect.Maps; 21import com.google.common.collect.Maps;
20import com.google.common.collect.Sets; 22import com.google.common.collect.Sets;
21 23
@@ -89,6 +91,18 @@ public class Mappings implements Serializable {
89 return m_classesByDeobf.get(deobfName); 91 return m_classesByDeobf.get(deobfName);
90 } 92 }
91 93
94 public void setClassDeobfName(ClassMapping classMapping, String deobfName) {
95 if (classMapping.getDeobfName() != null) {
96 boolean wasRemoved = m_classesByDeobf.remove(classMapping.getDeobfName()) != null;
97 assert (wasRemoved);
98 }
99 classMapping.setDeobfName(deobfName);
100 if (deobfName != null) {
101 boolean wasAdded = m_classesByDeobf.put(deobfName, classMapping) == null;
102 assert (wasAdded);
103 }
104 }
105
92 public Translator getTranslator(TranslationDirection direction, TranslationIndex index) { 106 public Translator getTranslator(TranslationDirection direction, TranslationIndex index) {
93 switch (direction) { 107 switch (direction) {
94 case Deobfuscating: 108 case Deobfuscating:
@@ -185,4 +199,18 @@ public class Mappings implements Serializable {
185 } 199 }
186 return false; 200 return false;
187 } 201 }
202
203 public List<ClassMapping> getClassMappingChain(ClassEntry obfClass) {
204 List<ClassMapping> mappingChain = Lists.newArrayList();
205 ClassMapping classMapping = null;
206 for (ClassEntry obfClassEntry : obfClass.getClassChain()) {
207 if (mappingChain.isEmpty()) {
208 classMapping = m_classesByObf.get(obfClassEntry.getName());
209 } else if (classMapping != null) {
210 classMapping = classMapping.getInnerClassByObfSimple(obfClassEntry.getInnermostClassName());
211 }
212 mappingChain.add(classMapping);
213 }
214 return mappingChain;
215 }
188} 216}
diff --git a/src/cuchaz/enigma/mapping/MappingsRenamer.java b/src/cuchaz/enigma/mapping/MappingsRenamer.java
index 16f700d2..d7766dc8 100644
--- a/src/cuchaz/enigma/mapping/MappingsRenamer.java
+++ b/src/cuchaz/enigma/mapping/MappingsRenamer.java
@@ -13,10 +13,10 @@ package cuchaz.enigma.mapping;
13import java.io.IOException; 13import java.io.IOException;
14import java.io.ObjectOutputStream; 14import java.io.ObjectOutputStream;
15import java.io.OutputStream; 15import java.io.OutputStream;
16import java.util.List;
16import java.util.Set; 17import java.util.Set;
17import java.util.zip.GZIPOutputStream; 18import java.util.zip.GZIPOutputStream;
18 19
19import cuchaz.enigma.Constants;
20import cuchaz.enigma.analysis.JarIndex; 20import cuchaz.enigma.analysis.JarIndex;
21 21
22public class MappingsRenamer { 22public class MappingsRenamer {
@@ -30,48 +30,43 @@ public class MappingsRenamer {
30 } 30 }
31 31
32 public void setClassName(ClassEntry obf, String deobfName) { 32 public void setClassName(ClassEntry obf, String deobfName) {
33 deobfName = NameValidator.validateClassName(deobfName, !obf.isInnerClass());
34 ClassEntry targetEntry = new ClassEntry(deobfName);
35 if (m_mappings.containsDeobfClass(deobfName) || m_index.containsObfClass(targetEntry)) {
36 throw new IllegalNameException(deobfName, "There is already a class with that name");
37 }
38 33
39 ClassMapping classMapping = getOrCreateClassMapping(obf); 34 deobfName = NameValidator.validateClassName(deobfName, !obf.isInnerClass());
40 35
41 if (obf.isInnerClass()) { 36 List<ClassMapping> mappingChain = getOrCreateClassMappingChain(obf);
42 classMapping.setInnerClassName(obf.getInnerClassName(), deobfName); 37 if (mappingChain.size() == 1) {
38
39 if (deobfName != null) {
40 // make sure we don't rename to an existing obf or deobf class
41 if (m_mappings.containsDeobfClass(deobfName) || m_index.containsObfClass(new ClassEntry(deobfName))) {
42 throw new IllegalNameException(deobfName, "There is already a class with that name");
43 }
44 }
45
46 ClassMapping classMapping = mappingChain.get(0);
47 m_mappings.setClassDeobfName(classMapping, deobfName);
48
43 } else { 49 } else {
44 if (classMapping.getDeobfName() != null) { 50
45 boolean wasRemoved = m_mappings.m_classesByDeobf.remove(classMapping.getDeobfName()) != null; 51 ClassMapping outerClassMapping = mappingChain.get(mappingChain.size() - 2);
46 assert (wasRemoved); 52
53 if (deobfName != null) {
54 // make sure we don't rename to an existing obf or deobf inner class
55 if (outerClassMapping.hasInnerClassByDeobf(deobfName) || outerClassMapping.hasInnerClassByObfSimple(deobfName)) {
56 throw new IllegalNameException(deobfName, "There is already a class with that name");
57 }
47 } 58 }
48 classMapping.setDeobfName(deobfName); 59
49 boolean wasAdded = m_mappings.m_classesByDeobf.put(deobfName, classMapping) == null; 60 outerClassMapping.setInnerClassName(obf, deobfName);
50 assert (wasAdded);
51 } 61 }
52 } 62 }
53 63
54 public void removeClassMapping(ClassEntry obf) { 64 public void removeClassMapping(ClassEntry obf) {
55 ClassMapping classMapping = getClassMapping(obf); 65 setClassName(obf, null);
56 if (obf.isInnerClass()) {
57 classMapping.setInnerClassName(obf.getName(), null);
58 } else {
59 boolean wasRemoved = m_mappings.m_classesByDeobf.remove(classMapping.getDeobfName()) != null;
60 assert (wasRemoved);
61 classMapping.setDeobfName(null);
62 }
63 } 66 }
64 67
65 public void markClassAsDeobfuscated(ClassEntry obf) { 68 public void markClassAsDeobfuscated(ClassEntry obf) {
66 ClassMapping classMapping = getOrCreateClassMapping(obf); 69 setClassName(obf, obf.isInnerClass() ? obf.getInnermostClassName() : obf.getSimpleName());
67 if (obf.isInnerClass()) {
68 String innerClassName = Constants.NonePackage + "/" + obf.getInnerClassName();
69 classMapping.setInnerClassName(innerClassName, innerClassName);
70 } else {
71 classMapping.setDeobfName(obf.getName());
72 boolean wasAdded = m_mappings.m_classesByDeobf.put(obf.getName(), classMapping) == null;
73 assert (wasAdded);
74 }
75 } 70 }
76 71
77 public void setFieldName(FieldEntry obf, String deobfName) { 72 public void setFieldName(FieldEntry obf, String deobfName) {
@@ -81,17 +76,17 @@ public class MappingsRenamer {
81 throw new IllegalNameException(deobfName, "There is already a field with that name"); 76 throw new IllegalNameException(deobfName, "There is already a field with that name");
82 } 77 }
83 78
84 ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping(obf.getClassEntry()); 79 ClassMapping classMapping = getOrCreateClassMapping(obf.getClassEntry());
85 classMapping.setFieldName(obf.getName(), obf.getType(), deobfName); 80 classMapping.setFieldName(obf.getName(), obf.getType(), deobfName);
86 } 81 }
87 82
88 public void removeFieldMapping(FieldEntry obf) { 83 public void removeFieldMapping(FieldEntry obf) {
89 ClassMapping classMapping = getClassMappingOrInnerClassMapping(obf.getClassEntry()); 84 ClassMapping classMapping = getOrCreateClassMapping(obf.getClassEntry());
90 classMapping.removeFieldMapping(classMapping.getFieldByObf(obf.getName(), obf.getType())); 85 classMapping.removeFieldMapping(classMapping.getFieldByObf(obf.getName(), obf.getType()));
91 } 86 }
92 87
93 public void markFieldAsDeobfuscated(FieldEntry obf) { 88 public void markFieldAsDeobfuscated(FieldEntry obf) {
94 ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping(obf.getClassEntry()); 89 ClassMapping classMapping = getOrCreateClassMapping(obf.getClassEntry());
95 classMapping.setFieldName(obf.getName(), obf.getType(), obf.getName()); 90 classMapping.setFieldName(obf.getName(), obf.getType(), obf.getName());
96 } 91 }
97 92
@@ -121,7 +116,7 @@ public class MappingsRenamer {
121 throw new IllegalNameException(deobfName, "There is already a method with that name and signature in class " + deobfClassName); 116 throw new IllegalNameException(deobfName, "There is already a method with that name and signature in class " + deobfClassName);
122 } 117 }
123 118
124 ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping(obf.getClassEntry()); 119 ClassMapping classMapping = getOrCreateClassMapping(obf.getClassEntry());
125 classMapping.setMethodName(obf.getName(), obf.getSignature(), deobfName); 120 classMapping.setMethodName(obf.getName(), obf.getSignature(), deobfName);
126 } 121 }
127 122
@@ -132,7 +127,7 @@ public class MappingsRenamer {
132 } 127 }
133 128
134 public void removeMethodMapping(MethodEntry obf) { 129 public void removeMethodMapping(MethodEntry obf) {
135 ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping(obf.getClassEntry()); 130 ClassMapping classMapping = getOrCreateClassMapping(obf.getClassEntry());
136 classMapping.setMethodName(obf.getName(), obf.getSignature(), null); 131 classMapping.setMethodName(obf.getName(), obf.getSignature(), null);
137 } 132 }
138 133
@@ -143,7 +138,7 @@ public class MappingsRenamer {
143 } 138 }
144 139
145 public void markMethodAsDeobfuscated(MethodEntry obf) { 140 public void markMethodAsDeobfuscated(MethodEntry obf) {
146 ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping(obf.getClassEntry()); 141 ClassMapping classMapping = getOrCreateClassMapping(obf.getClassEntry());
147 classMapping.setMethodName(obf.getName(), obf.getSignature(), obf.getName()); 142 classMapping.setMethodName(obf.getName(), obf.getSignature(), obf.getName());
148 } 143 }
149 144
@@ -154,17 +149,17 @@ public class MappingsRenamer {
154 throw new IllegalNameException(deobfName, "There is already an argument with that name"); 149 throw new IllegalNameException(deobfName, "There is already an argument with that name");
155 } 150 }
156 151
157 ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping(obf.getClassEntry()); 152 ClassMapping classMapping = getOrCreateClassMapping(obf.getClassEntry());
158 classMapping.setArgumentName(obf.getMethodName(), obf.getMethodSignature(), obf.getIndex(), deobfName); 153 classMapping.setArgumentName(obf.getMethodName(), obf.getMethodSignature(), obf.getIndex(), deobfName);
159 } 154 }
160 155
161 public void removeArgumentMapping(ArgumentEntry obf) { 156 public void removeArgumentMapping(ArgumentEntry obf) {
162 ClassMapping classMapping = getClassMappingOrInnerClassMapping(obf.getClassEntry()); 157 ClassMapping classMapping = getOrCreateClassMapping(obf.getClassEntry());
163 classMapping.removeArgumentName(obf.getMethodName(), obf.getMethodSignature(), obf.getIndex()); 158 classMapping.removeArgumentName(obf.getMethodName(), obf.getMethodSignature(), obf.getIndex());
164 } 159 }
165 160
166 public void markArgumentAsDeobfuscated(ArgumentEntry obf) { 161 public void markArgumentAsDeobfuscated(ArgumentEntry obf) {
167 ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping(obf.getClassEntry()); 162 ClassMapping classMapping = getOrCreateClassMapping(obf.getClassEntry());
168 classMapping.setArgumentName(obf.getMethodName(), obf.getMethodSignature(), obf.getIndex(), obf.getName()); 163 classMapping.setArgumentName(obf.getMethodName(), obf.getMethodSignature(), obf.getIndex(), obf.getName());
169 } 164 }
170 165
@@ -204,34 +199,31 @@ public class MappingsRenamer {
204 gzipout.finish(); 199 gzipout.finish();
205 } 200 }
206 201
207 private ClassMapping getClassMapping(ClassEntry obfClassEntry) {
208 return m_mappings.m_classesByObf.get(obfClassEntry.getOuterClassName());
209 }
210
211 private ClassMapping getOrCreateClassMapping(ClassEntry obfClassEntry) { 202 private ClassMapping getOrCreateClassMapping(ClassEntry obfClassEntry) {
212 String obfClassName = obfClassEntry.getOuterClassName(); 203 List<ClassMapping> mappingChain = getOrCreateClassMappingChain(obfClassEntry);
213 ClassMapping classMapping = m_mappings.m_classesByObf.get(obfClassName); 204 return mappingChain.get(mappingChain.size() - 1);
214 if (classMapping == null) { 205 }
215 classMapping = new ClassMapping(obfClassName); 206
216 boolean obfWasAdded = m_mappings.m_classesByObf.put(classMapping.getObfFullName(), classMapping) == null; 207 private List<ClassMapping> getOrCreateClassMappingChain(ClassEntry obfClassEntry) {
217 assert (obfWasAdded); 208 List<ClassEntry> classChain = obfClassEntry.getClassChain();
218 } 209 List<ClassMapping> mappingChain = m_mappings.getClassMappingChain(obfClassEntry);
219 return classMapping; 210 for (int i=0; i<classChain.size(); i++) {
220 } 211 ClassEntry classEntry = classChain.get(i);
221 212 ClassMapping classMapping = mappingChain.get(i);
222 private ClassMapping getClassMappingOrInnerClassMapping(ClassEntry obfClassEntry) { 213 if (classMapping == null) {
223 ClassMapping classMapping = getClassMapping(obfClassEntry); 214
224 if (obfClassEntry.isInDefaultPackage()) { 215 // create it
225 classMapping = classMapping.getInnerClassByObf(obfClassEntry.getInnerClassName()); 216 classMapping = new ClassMapping(classEntry.getName());
226 } 217 mappingChain.set(i, classMapping);
227 return classMapping; 218
228 } 219 // add it to the right parent
229 220 if (i == 0) {
230 private ClassMapping getOrCreateClassMappingOrInnerClassMapping(ClassEntry obfClassEntry) { 221 m_mappings.addClassMapping(classMapping);
231 ClassMapping classMapping = getOrCreateClassMapping(obfClassEntry); 222 } else {
232 if (obfClassEntry.isInnerClass()) { 223 mappingChain.get(i-1).addInnerClassMapping(classMapping);
233 classMapping = classMapping.getOrCreateInnerClass(obfClassEntry.getInnerClassName()); 224 }
225 }
234 } 226 }
235 return classMapping; 227 return mappingChain;
236 } 228 }
237} 229}
diff --git a/src/cuchaz/enigma/mapping/Translator.java b/src/cuchaz/enigma/mapping/Translator.java
index d3b6e771..fb187b90 100644
--- a/src/cuchaz/enigma/mapping/Translator.java
+++ b/src/cuchaz/enigma/mapping/Translator.java
@@ -24,6 +24,13 @@ public class Translator {
24 private Map<String,ClassMapping> m_classes; 24 private Map<String,ClassMapping> m_classes;
25 private TranslationIndex m_index; 25 private TranslationIndex m_index;
26 26
27 private ClassNameReplacer m_classNameReplacer = new ClassNameReplacer() {
28 @Override
29 public String replace(String className) {
30 return translateEntry(new ClassEntry(className)).getName();
31 }
32 };
33
27 public Translator() { 34 public Translator() {
28 m_direction = null; 35 m_direction = null;
29 m_classes = Maps.newHashMap(); 36 m_classes = Maps.newHashMap();
@@ -69,48 +76,16 @@ public class Translator {
69 } 76 }
70 } 77 }
71 78
72 public String translateClass(String className) {
73 return translate(new ClassEntry(className));
74 }
75
76 public String translate(ClassEntry in) { 79 public String translate(ClassEntry in) {
77 80 ClassEntry translated = translateEntry(in);
78 if (in.isInnerClass()) { 81 if (translated.equals(in)) {
79 82 return null;
80 // translate everything in the class chain, or return null
81 List<ClassMapping> mappingsChain = getClassMappingChain(in);
82 StringBuilder buf = new StringBuilder();
83 for (ClassMapping classMapping : mappingsChain) {
84 if (classMapping == null) {
85 return null;
86 }
87 boolean isFirstClass = buf.length() == 0;
88 String name = m_direction.choose(
89 classMapping.getDeobfName(),
90 isFirstClass ? classMapping.getObfFullName() : classMapping.getObfSimpleName()
91 );
92 if (name == null) {
93 return null;
94 }
95 if (!isFirstClass) {
96 buf.append("$");
97 }
98 buf.append(name);
99 }
100 return buf.toString();
101
102 } else {
103
104 // normal classes are easier
105 ClassMapping classMapping = m_classes.get(in.getName());
106 if (classMapping == null) {
107 return null;
108 }
109 return m_direction.choose(
110 classMapping.getDeobfName(),
111 classMapping.getObfFullName()
112 );
113 } 83 }
84 return translated.getName();
85 }
86
87 public String translateClass(String className) {
88 return translate(new ClassEntry(className));
114 } 89 }
115 90
116 public ClassEntry translateEntry(ClassEntry in) { 91 public ClassEntry translateEntry(ClassEntry in) {
@@ -264,21 +239,11 @@ public class Translator {
264 } 239 }
265 240
266 public Type translateType(Type type) { 241 public Type translateType(Type type) {
267 return new Type(type, new ClassNameReplacer() { 242 return new Type(type, m_classNameReplacer);
268 @Override
269 public String replace(String className) {
270 return translateClass(className);
271 }
272 });
273 } 243 }
274 244
275 public Signature translateSignature(Signature signature) { 245 public Signature translateSignature(Signature signature) {
276 return new Signature(signature, new ClassNameReplacer() { 246 return new Signature(signature, m_classNameReplacer);
277 @Override
278 public String replace(String className) {
279 return translateClass(className);
280 }
281 });
282 } 247 }
283 248
284 private ClassMapping findClassMapping(ClassEntry in) { 249 private ClassMapping findClassMapping(ClassEntry in) {
@@ -302,8 +267,8 @@ public class Translator {
302 ClassMapping innerClassMapping = null; 267 ClassMapping innerClassMapping = null;
303 if (outerClassMapping != null) { 268 if (outerClassMapping != null) {
304 innerClassMapping = m_direction.choose( 269 innerClassMapping = m_direction.choose(
305 outerClassMapping.getInnerClassByObf(parts[i]), 270 outerClassMapping.getInnerClassByObfSimple(parts[i]),
306 outerClassMapping.getInnerClassByDeobfThenObf(parts[i]) 271 outerClassMapping.getInnerClassByDeobfThenObfSimple(parts[i])
307 ); 272 );
308 } 273 }
309 mappingsChain.add(innerClassMapping); 274 mappingsChain.add(innerClassMapping);