summaryrefslogtreecommitdiff
path: root/src/cuchaz/enigma/analysis/TranslationIndex.java
diff options
context:
space:
mode:
authorGravatar Cuchaz2015-03-30 23:56:21 -0400
committerGravatar Cuchaz2015-03-30 23:56:21 -0400
commit2fc8ae770442ec3ab91cf0c16cc30917e0d048d3 (patch)
treea49e9ede649fb0f350fee1b8336f319df20f4973 /src/cuchaz/enigma/analysis/TranslationIndex.java
parentadd publifier (diff)
downloadenigma-fork-2fc8ae770442ec3ab91cf0c16cc30917e0d048d3.tar.gz
enigma-fork-2fc8ae770442ec3ab91cf0c16cc30917e0d048d3.tar.xz
enigma-fork-2fc8ae770442ec3ab91cf0c16cc30917e0d048d3.zip
resolve methods using interfaces as well as superclasses
Diffstat (limited to '')
-rw-r--r--src/cuchaz/enigma/analysis/TranslationIndex.java69
1 files changed, 67 insertions, 2 deletions
diff --git a/src/cuchaz/enigma/analysis/TranslationIndex.java b/src/cuchaz/enigma/analysis/TranslationIndex.java
index bd77344..e0e66bf 100644
--- a/src/cuchaz/enigma/analysis/TranslationIndex.java
+++ b/src/cuchaz/enigma/analysis/TranslationIndex.java
@@ -16,6 +16,7 @@ import java.io.ObjectInputStream;
16import java.io.ObjectOutputStream; 16import java.io.ObjectOutputStream;
17import java.io.OutputStream; 17import java.io.OutputStream;
18import java.io.Serializable; 18import java.io.Serializable;
19import java.util.Collection;
19import java.util.HashMap; 20import java.util.HashMap;
20import java.util.List; 21import java.util.List;
21import java.util.Map; 22import java.util.Map;
@@ -26,6 +27,7 @@ import java.util.zip.GZIPOutputStream;
26import javassist.CtBehavior; 27import javassist.CtBehavior;
27import javassist.CtClass; 28import javassist.CtClass;
28import javassist.CtField; 29import javassist.CtField;
30import javassist.bytecode.Descriptor;
29 31
30import com.google.common.collect.HashMultimap; 32import com.google.common.collect.HashMultimap;
31import com.google.common.collect.Lists; 33import com.google.common.collect.Lists;
@@ -36,8 +38,8 @@ import cuchaz.enigma.mapping.ArgumentEntry;
36import cuchaz.enigma.mapping.BehaviorEntry; 38import cuchaz.enigma.mapping.BehaviorEntry;
37import cuchaz.enigma.mapping.ClassEntry; 39import cuchaz.enigma.mapping.ClassEntry;
38import cuchaz.enigma.mapping.Entry; 40import cuchaz.enigma.mapping.Entry;
39import cuchaz.enigma.mapping.FieldEntry;
40import cuchaz.enigma.mapping.EntryFactory; 41import cuchaz.enigma.mapping.EntryFactory;
42import cuchaz.enigma.mapping.FieldEntry;
41import cuchaz.enigma.mapping.Translator; 43import cuchaz.enigma.mapping.Translator;
42 44
43public class TranslationIndex implements Serializable { 45public class TranslationIndex implements Serializable {
@@ -47,11 +49,13 @@ public class TranslationIndex implements Serializable {
47 private Map<ClassEntry,ClassEntry> m_superclasses; 49 private Map<ClassEntry,ClassEntry> m_superclasses;
48 private Multimap<ClassEntry,FieldEntry> m_fieldEntries; 50 private Multimap<ClassEntry,FieldEntry> m_fieldEntries;
49 private Multimap<ClassEntry,BehaviorEntry> m_behaviorEntries; 51 private Multimap<ClassEntry,BehaviorEntry> m_behaviorEntries;
52 private Multimap<ClassEntry,ClassEntry> m_interfaces;
50 53
51 public TranslationIndex() { 54 public TranslationIndex() {
52 m_superclasses = Maps.newHashMap(); 55 m_superclasses = Maps.newHashMap();
53 m_fieldEntries = HashMultimap.create(); 56 m_fieldEntries = HashMultimap.create();
54 m_behaviorEntries = HashMultimap.create(); 57 m_behaviorEntries = HashMultimap.create();
58 m_interfaces = HashMultimap.create();
55 } 59 }
56 60
57 public TranslationIndex(TranslationIndex other, Translator translator) { 61 public TranslationIndex(TranslationIndex other, Translator translator) {
@@ -65,6 +69,15 @@ public class TranslationIndex implements Serializable {
65 ); 69 );
66 } 70 }
67 71
72 // translate the interfaces
73 m_interfaces = HashMultimap.create();
74 for (Map.Entry<ClassEntry,ClassEntry> mapEntry : other.m_interfaces.entries()) {
75 m_interfaces.put(
76 translator.translateEntry(mapEntry.getKey()),
77 translator.translateEntry(mapEntry.getValue())
78 );
79 }
80
68 // translate the fields 81 // translate the fields
69 m_fieldEntries = HashMultimap.create(); 82 m_fieldEntries = HashMultimap.create();
70 for (Map.Entry<ClassEntry,FieldEntry> mapEntry : other.m_fieldEntries.entries()) { 83 for (Map.Entry<ClassEntry,FieldEntry> mapEntry : other.m_fieldEntries.entries()) {
@@ -90,13 +103,24 @@ public class TranslationIndex implements Serializable {
90 public void indexClass(CtClass c, boolean indexMembers) { 103 public void indexClass(CtClass c, boolean indexMembers) {
91 104
92 ClassEntry classEntry = EntryFactory.getClassEntry(c); 105 ClassEntry classEntry = EntryFactory.getClassEntry(c);
106 if (isJre(classEntry)) {
107 return;
108 }
93 109
94 // add the superclass 110 // add the superclass
95 ClassEntry superclassEntry = EntryFactory.getSuperclassEntry(c); 111 ClassEntry superclassEntry = EntryFactory.getSuperclassEntry(c);
96 if (!isJre(classEntry) && superclassEntry != null && !isJre(superclassEntry)) { 112 if (superclassEntry != null && !isJre(superclassEntry)) {
97 m_superclasses.put(classEntry, superclassEntry); 113 m_superclasses.put(classEntry, superclassEntry);
98 } 114 }
99 115
116 // add the interfaces
117 for (String interfaceClassName : c.getClassFile().getInterfaces()) {
118 ClassEntry interfaceClassEntry = new ClassEntry(Descriptor.toJvmName(interfaceClassName));
119 if (!isJre(interfaceClassEntry)) {
120 m_interfaces.put(classEntry, interfaceClassEntry);
121 }
122 }
123
100 if (indexMembers) { 124 if (indexMembers) {
101 // add fields 125 // add fields
102 for (CtField field : c.getDeclaredFields()) { 126 for (CtField field : c.getDeclaredFields()) {
@@ -134,6 +158,7 @@ public class TranslationIndex implements Serializable {
134 } 158 }
135 159
136 public List<ClassEntry> getSubclass(ClassEntry classEntry) { 160 public List<ClassEntry> getSubclass(ClassEntry classEntry) {
161
137 // linear search is fast enough for now 162 // linear search is fast enough for now
138 List<ClassEntry> subclasses = Lists.newArrayList(); 163 List<ClassEntry> subclasses = Lists.newArrayList();
139 for (Map.Entry<ClassEntry,ClassEntry> entry : m_superclasses.entrySet()) { 164 for (Map.Entry<ClassEntry,ClassEntry> entry : m_superclasses.entrySet()) {
@@ -160,6 +185,18 @@ public class TranslationIndex implements Serializable {
160 } 185 }
161 } 186 }
162 187
188 public Collection<Map.Entry<ClassEntry,ClassEntry>> getClassInterfaces() {
189 return m_interfaces.entries();
190 }
191
192 public Collection<ClassEntry> getInterfaces(ClassEntry classEntry) {
193 return m_interfaces.get(classEntry);
194 }
195
196 public boolean isInterface(ClassEntry classEntry) {
197 return m_interfaces.containsValue(classEntry);
198 }
199
163 public boolean entryExists(Entry entry) { 200 public boolean entryExists(Entry entry) {
164 if (entry instanceof FieldEntry) { 201 if (entry instanceof FieldEntry) {
165 return fieldExists((FieldEntry)entry); 202 return fieldExists((FieldEntry)entry);
@@ -185,6 +222,21 @@ public class TranslationIndex implements Serializable {
185 return (ClassEntry)entry; 222 return (ClassEntry)entry;
186 } 223 }
187 224
225 ClassEntry superclassEntry = resolveSuperclass(entry);
226 if (superclassEntry != null) {
227 return superclassEntry;
228 }
229
230 ClassEntry interfaceEntry = resolveInterface(entry);
231 if (interfaceEntry != null) {
232 return interfaceEntry;
233 }
234
235 return null;
236 }
237
238 public ClassEntry resolveSuperclass(Entry entry) {
239
188 // this entry could refer to a method on a class where the method is not actually implemented 240 // this entry could refer to a method on a class where the method is not actually implemented
189 // travel up the inheritance tree to find the closest implementation 241 // travel up the inheritance tree to find the closest implementation
190 while (!entryExists(entry)) { 242 while (!entryExists(entry)) {
@@ -203,6 +255,19 @@ public class TranslationIndex implements Serializable {
203 return entry.getClassEntry(); 255 return entry.getClassEntry();
204 } 256 }
205 257
258 public ClassEntry resolveInterface(Entry entry) {
259
260 // the interfaces for any class is a forest
261 // so let's look at all the trees
262 for (ClassEntry interfaceEntry : m_interfaces.get(entry.getClassEntry())) {
263 ClassEntry resolvedClassEntry = resolveSuperclass(entry.cloneToNewClass(interfaceEntry));
264 if (resolvedClassEntry != null) {
265 return resolvedClassEntry;
266 }
267 }
268 return null;
269 }
270
206 private boolean isJre(ClassEntry classEntry) { 271 private boolean isJre(ClassEntry classEntry) {
207 String packageName = classEntry.getPackageName(); 272 String packageName = classEntry.getPackageName();
208 return packageName != null && (packageName.startsWith("java") || packageName.startsWith("javax")); 273 return packageName != null && (packageName.startsWith("java") || packageName.startsWith("javax"));