summaryrefslogtreecommitdiff
path: root/src/main/java/cuchaz/enigma/analysis/TranslationIndex.java
diff options
context:
space:
mode:
authorGravatar Modmuss502018-07-18 13:46:00 +0100
committerGravatar GitHub2018-07-18 13:46:00 +0100
commit1ebe691c12f68beea378b133ddc4bcbde7f3f795 (patch)
treefb051d9fde5644bd144a7e9d7bcecc70a256359c /src/main/java/cuchaz/enigma/analysis/TranslationIndex.java
parentRecursively rebuild method names (diff)
parentUpdate version number (diff)
downloadenigma-fork-1ebe691c12f68beea378b133ddc4bcbde7f3f795.tar.gz
enigma-fork-1ebe691c12f68beea378b133ddc4bcbde7f3f795.tar.xz
enigma-fork-1ebe691c12f68beea378b133ddc4bcbde7f3f795.zip
Merge pull request #62 from OpenModLoader/asm
ASM based class translator
Diffstat (limited to 'src/main/java/cuchaz/enigma/analysis/TranslationIndex.java')
-rw-r--r--src/main/java/cuchaz/enigma/analysis/TranslationIndex.java122
1 files changed, 58 insertions, 64 deletions
diff --git a/src/main/java/cuchaz/enigma/analysis/TranslationIndex.java b/src/main/java/cuchaz/enigma/analysis/TranslationIndex.java
index 26be05b..b2ddc5f 100644
--- a/src/main/java/cuchaz/enigma/analysis/TranslationIndex.java
+++ b/src/main/java/cuchaz/enigma/analysis/TranslationIndex.java
@@ -15,11 +15,9 @@ import com.google.common.collect.HashMultimap;
15import com.google.common.collect.Lists; 15import com.google.common.collect.Lists;
16import com.google.common.collect.Maps; 16import com.google.common.collect.Maps;
17import com.google.common.collect.Multimap; 17import com.google.common.collect.Multimap;
18import cuchaz.enigma.bytecode.AccessFlags;
18import cuchaz.enigma.mapping.*; 19import cuchaz.enigma.mapping.*;
19import javassist.CtBehavior; 20import cuchaz.enigma.mapping.entry.*;
20import javassist.CtClass;
21import javassist.CtField;
22import javassist.bytecode.Descriptor;
23 21
24import java.util.Collection; 22import java.util.Collection;
25import java.util.List; 23import java.util.List;
@@ -28,96 +26,91 @@ import java.util.Set;
28 26
29public class TranslationIndex { 27public class TranslationIndex {
30 28
29 private final ReferencedEntryPool entryPool;
31 private Map<ClassEntry, ClassEntry> superclasses; 30 private Map<ClassEntry, ClassEntry> superclasses;
32 private Multimap<ClassEntry, FieldEntry> fieldEntries; 31 private Multimap<ClassEntry, FieldDefEntry> fieldEntries;
33 private Multimap<ClassEntry, BehaviorEntry> behaviorEntries; 32 private Multimap<ClassEntry, MethodDefEntry> methodEntries;
34 private Multimap<ClassEntry, ClassEntry> interfaces; 33 private Multimap<ClassEntry, ClassEntry> interfaces;
35 34
36 public TranslationIndex() { 35 public TranslationIndex(ReferencedEntryPool entryPool) {
36 this.entryPool = entryPool;
37 this.superclasses = Maps.newHashMap(); 37 this.superclasses = Maps.newHashMap();
38 this.fieldEntries = HashMultimap.create(); 38 this.fieldEntries = HashMultimap.create();
39 this.behaviorEntries = HashMultimap.create(); 39 this.methodEntries = HashMultimap.create();
40 this.interfaces = HashMultimap.create(); 40 this.interfaces = HashMultimap.create();
41 } 41 }
42 42
43 public TranslationIndex(TranslationIndex other, Translator translator) { 43 public TranslationIndex(TranslationIndex other, Translator translator) {
44 this.entryPool = other.entryPool;
45
44 // translate the superclasses 46 // translate the superclasses
45 this.superclasses = Maps.newHashMap(); 47 this.superclasses = Maps.newHashMap();
46 for (Map.Entry<ClassEntry, ClassEntry> mapEntry : other.superclasses.entrySet()) { 48 for (Map.Entry<ClassEntry, ClassEntry> mapEntry : other.superclasses.entrySet()) {
47 this.superclasses.put(translator.translateEntry(mapEntry.getKey()), translator.translateEntry(mapEntry.getValue())); 49 this.superclasses.put(translator.getTranslatedClass(mapEntry.getKey()), translator.getTranslatedClass(mapEntry.getValue()));
48 } 50 }
49 51
50 // translate the interfaces 52 // translate the interfaces
51 this.interfaces = HashMultimap.create(); 53 this.interfaces = HashMultimap.create();
52 for (Map.Entry<ClassEntry, ClassEntry> mapEntry : other.interfaces.entries()) { 54 for (Map.Entry<ClassEntry, ClassEntry> mapEntry : other.interfaces.entries()) {
53 this.interfaces.put( 55 this.interfaces.put(
54 translator.translateEntry(mapEntry.getKey()), 56 translator.getTranslatedClass(mapEntry.getKey()),
55 translator.translateEntry(mapEntry.getValue()) 57 translator.getTranslatedClass(mapEntry.getValue())
56 ); 58 );
57 } 59 }
58 60
59 // translate the fields 61 // translate the fields
60 this.fieldEntries = HashMultimap.create(); 62 this.fieldEntries = HashMultimap.create();
61 for (Map.Entry<ClassEntry, FieldEntry> mapEntry : other.fieldEntries.entries()) { 63 for (Map.Entry<ClassEntry, FieldDefEntry> mapEntry : other.fieldEntries.entries()) {
62 this.fieldEntries.put( 64 this.fieldEntries.put(
63 translator.translateEntry(mapEntry.getKey()), 65 translator.getTranslatedClass(mapEntry.getKey()),
64 translator.translateEntry(mapEntry.getValue()) 66 translator.getTranslatedFieldDef(mapEntry.getValue())
65 ); 67 );
66 } 68 }
67 69
68 this.behaviorEntries = HashMultimap.create(); 70 this.methodEntries = HashMultimap.create();
69 for (Map.Entry<ClassEntry, BehaviorEntry> mapEntry : other.behaviorEntries.entries()) { 71 for (Map.Entry<ClassEntry, MethodDefEntry> mapEntry : other.methodEntries.entries()) {
70 this.behaviorEntries.put( 72 this.methodEntries.put(
71 translator.translateEntry(mapEntry.getKey()), 73 translator.getTranslatedClass(mapEntry.getKey()),
72 translator.translateEntry(mapEntry.getValue()) 74 translator.getTranslatedMethodDef(mapEntry.getValue())
73 ); 75 );
74 } 76 }
75 } 77 }
76 78
77 public void indexClass(CtClass c) { 79 protected ClassDefEntry indexClass(int access, String name, String signature, String superName, String[] interfaces) {
78 indexClass(c, true); 80 ClassDefEntry classEntry = new ClassDefEntry(name, Signature.createSignature(signature), new AccessFlags(access));
79 }
80
81 public void indexClass(CtClass c, boolean indexMembers) {
82 ClassEntry classEntry = EntryFactory.getClassEntry(c);
83 if (isJre(classEntry)) { 81 if (isJre(classEntry)) {
84 return; 82 return null;
85 } 83 }
86 84
87 // add the superclass 85 // add the superclass
88 ClassEntry superclassEntry = EntryFactory.getSuperclassEntry(c); 86 ClassEntry superclassEntry = entryPool.getClass(superName);
89 if (superclassEntry != null) { 87 if (superclassEntry != null) {
90 this.superclasses.put(classEntry, superclassEntry); 88 this.superclasses.put(classEntry, superclassEntry);
91 } 89 }
92 90
93 // add the interfaces 91 // add the interfaces
94 for (String interfaceClassName : c.getClassFile().getInterfaces()) { 92 for (String interfaceClassName : interfaces) {
95 ClassEntry interfaceClassEntry = new ClassEntry(Descriptor.toJvmName(interfaceClassName)); 93 ClassEntry interfaceClassEntry = entryPool.getClass(interfaceClassName);
96 if (!isJre(interfaceClassEntry)) { 94 if (!isJre(interfaceClassEntry)) {
97
98 this.interfaces.put(classEntry, interfaceClassEntry); 95 this.interfaces.put(classEntry, interfaceClassEntry);
99 } 96 }
100 } 97 }
101 98
102 if (indexMembers) { 99 return classEntry;
103 // add fields 100 }
104 for (CtField field : c.getDeclaredFields()) {
105 FieldEntry fieldEntry = EntryFactory.getFieldEntry(field);
106 this.fieldEntries.put(fieldEntry.getClassEntry(), fieldEntry);
107 }
108 101
109 // add behaviors 102 protected void indexField(FieldDefEntry fieldEntry) {
110 for (CtBehavior behavior : c.getDeclaredBehaviors()) { 103 this.fieldEntries.put(fieldEntry.getOwnerClassEntry(), fieldEntry);
111 BehaviorEntry behaviorEntry = EntryFactory.getBehaviorEntry(behavior); 104 }
112 this.behaviorEntries.put(behaviorEntry.getClassEntry(), behaviorEntry); 105
113 } 106 protected void indexMethod(MethodDefEntry methodEntry) {
114 } 107 this.methodEntries.put(methodEntry.getOwnerClassEntry(), methodEntry);
115 } 108 }
116 109
117 public void renameClasses(Map<String, String> renames) { 110 public void renameClasses(Map<String, String> renames) {
118 EntryRenamer.renameClassesInMap(renames, this.superclasses); 111 EntryRenamer.renameClassesInMap(renames, this.superclasses);
119 EntryRenamer.renameClassesInMultimap(renames, this.fieldEntries); 112 EntryRenamer.renameClassesInMultimap(renames, this.fieldEntries);
120 EntryRenamer.renameClassesInMultimap(renames, this.behaviorEntries); 113 EntryRenamer.renameClassesInMultimap(renames, this.methodEntries);
121 } 114 }
122 115
123 public ClassEntry getSuperclass(ClassEntry classEntry) { 116 public ClassEntry getSuperclass(ClassEntry classEntry) {
@@ -175,31 +168,32 @@ public class TranslationIndex {
175 } 168 }
176 169
177 public boolean entryExists(Entry entry) { 170 public boolean entryExists(Entry entry) {
171 if (entry == null) {
172 return false;
173 }
178 if (entry instanceof FieldEntry) { 174 if (entry instanceof FieldEntry) {
179 return fieldExists((FieldEntry) entry); 175 return fieldExists((FieldEntry) entry);
180 } else if (entry instanceof BehaviorEntry) { 176 } else if (entry instanceof MethodEntry) {
181 return behaviorExists((BehaviorEntry) entry); 177 return methodExists((MethodEntry) entry);
182 } else if (entry instanceof ArgumentEntry) {
183 return behaviorExists(((ArgumentEntry) entry).getBehaviorEntry());
184 } else if (entry instanceof LocalVariableEntry) { 178 } else if (entry instanceof LocalVariableEntry) {
185 return behaviorExists(((LocalVariableEntry) entry).getBehaviorEntry()); 179 return methodExists(((LocalVariableEntry) entry).getOwnerEntry());
186 } 180 }
187 throw new IllegalArgumentException("Cannot check existence for " + entry.getClass()); 181 throw new IllegalArgumentException("Cannot check existence for " + entry.getClass());
188 } 182 }
189 183
190 public boolean fieldExists(FieldEntry fieldEntry) { 184 public boolean fieldExists(FieldEntry fieldEntry) {
191 return this.fieldEntries.containsEntry(fieldEntry.getClassEntry(), fieldEntry); 185 return this.fieldEntries.containsEntry(fieldEntry.getOwnerClassEntry(), fieldEntry);
192 } 186 }
193 187
194 public boolean behaviorExists(BehaviorEntry behaviorEntry) { 188 public boolean methodExists(MethodEntry methodEntry) {
195 return this.behaviorEntries.containsEntry(behaviorEntry.getClassEntry(), behaviorEntry); 189 return this.methodEntries.containsEntry(methodEntry.getOwnerClassEntry(), methodEntry);
196 } 190 }
197 191
198 public ClassEntry resolveEntryClass(Entry entry) { 192 public ClassEntry resolveEntryOwner(Entry entry) {
199 return resolveEntryClass(entry, false); 193 return resolveEntryOwner(entry, false);
200 } 194 }
201 195
202 public ClassEntry resolveEntryClass(Entry entry, boolean checkSuperclassBeforeChild) { 196 public ClassEntry resolveEntryOwner(Entry entry, boolean checkSuperclassBeforeChild) {
203 if (entry instanceof ClassEntry) { 197 if (entry instanceof ClassEntry) {
204 return (ClassEntry) entry; 198 return (ClassEntry) entry;
205 } 199 }
@@ -227,12 +221,12 @@ public class TranslationIndex {
227 Entry originalEntry = entry; 221 Entry originalEntry = entry;
228 222
229 // Get all possible superclasses and reverse the list 223 // Get all possible superclasses and reverse the list
230 List<ClassEntry> superclasses = Lists.reverse(getAncestry(originalEntry.getClassEntry())); 224 List<ClassEntry> superclasses = Lists.reverse(getAncestry(originalEntry.getOwnerClassEntry()));
231 225
232 boolean existInEntry = false; 226 boolean existInEntry = false;
233 227
234 for (ClassEntry classEntry : superclasses) { 228 for (ClassEntry classEntry : superclasses) {
235 entry = entry.cloneToNewClass(classEntry); 229 entry = entry.updateOwnership(classEntry);
236 existInEntry = entryExists(entry); 230 existInEntry = entryExists(entry);
237 231
238 // Check for possible entry in interfaces of superclasses 232 // Check for possible entry in interfaces of superclasses
@@ -245,9 +239,9 @@ public class TranslationIndex {
245 239
246 // Doesn't exists in superclasses? check the child or return null 240 // Doesn't exists in superclasses? check the child or return null
247 if (!existInEntry) 241 if (!existInEntry)
248 return !entryExists(originalEntry) ? null : originalEntry.getClassEntry(); 242 return !entryExists(originalEntry) ? null : originalEntry.getOwnerClassEntry();
249 243
250 return entry.getClassEntry(); 244 return entry.getOwnerClassEntry();
251 } 245 }
252 246
253 public ClassEntry resolveSuperclass(Entry entry) { 247 public ClassEntry resolveSuperclass(Entry entry) {
@@ -256,7 +250,7 @@ public class TranslationIndex {
256 250
257 while (!entryExists(entry)) { 251 while (!entryExists(entry)) {
258 // is there a parent class? 252 // is there a parent class?
259 ClassEntry superclassEntry = getSuperclass(entry.getClassEntry()); 253 ClassEntry superclassEntry = getSuperclass(entry.getOwnerClassEntry());
260 if (superclassEntry == null) { 254 if (superclassEntry == null) {
261 // this is probably a method from a class in a library 255 // this is probably a method from a class in a library
262 // we can't trace the implementation up any higher unless we index the library 256 // we can't trace the implementation up any higher unless we index the library
@@ -264,23 +258,23 @@ public class TranslationIndex {
264 } 258 }
265 259
266 // move up to the parent class 260 // move up to the parent class
267 entry = entry.cloneToNewClass(superclassEntry); 261 entry = entry.updateOwnership(superclassEntry);
268 } 262 }
269 return entry.getClassEntry(); 263 return entry.getOwnerClassEntry();
270 } 264 }
271 265
272 public ClassEntry resolveInterface(Entry entry) { 266 public ClassEntry resolveInterface(Entry entry) {
273 // the interfaces for any class is a forest 267 // the interfaces for any class is a forest
274 // so let's look at all the trees 268 // so let's look at all the trees
275 269
276 for (ClassEntry interfaceEntry : this.interfaces.get(entry.getClassEntry())) { 270 for (ClassEntry interfaceEntry : this.interfaces.get(entry.getOwnerClassEntry())) {
277 Collection<ClassEntry> subInterface = this.interfaces.get(interfaceEntry); 271 Collection<ClassEntry> subInterface = this.interfaces.get(interfaceEntry);
278 if (subInterface != null && !subInterface.isEmpty()) { 272 if (subInterface != null && !subInterface.isEmpty()) {
279 ClassEntry result = resolveInterface(entry.cloneToNewClass(interfaceEntry)); 273 ClassEntry result = resolveInterface(entry.updateOwnership(interfaceEntry));
280 if (result != null) 274 if (result != null)
281 return result; 275 return result;
282 } 276 }
283 ClassEntry resolvedClassEntry = resolveSuperclass(entry.cloneToNewClass(interfaceEntry)); 277 ClassEntry resolvedClassEntry = resolveSuperclass(entry.updateOwnership(interfaceEntry));
284 if (resolvedClassEntry != null) { 278 if (resolvedClassEntry != null) {
285 return resolvedClassEntry; 279 return resolvedClassEntry;
286 } 280 }