summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build.gradle2
-rw-r--r--src/main/java/cuchaz/enigma/analysis/TranslationIndex.java135
-rw-r--r--src/main/java/cuchaz/enigma/mapping/DirectionalTranslator.java4
-rw-r--r--src/main/java/cuchaz/enigma/mapping/MappingsRenamer.java4
-rw-r--r--src/main/java/cuchaz/enigma/mapping/entry/ClassDefEntry.java3
-rw-r--r--src/main/java/cuchaz/enigma/mapping/entry/DefEntry.java7
-rw-r--r--src/main/java/cuchaz/enigma/mapping/entry/FieldDefEntry.java3
-rw-r--r--src/main/java/cuchaz/enigma/mapping/entry/MethodDefEntry.java3
-rw-r--r--src/main/java/cuchaz/enigma/utils/Utils.java10
9 files changed, 82 insertions, 89 deletions
diff --git a/build.gradle b/build.gradle
index 8eae880d..54b574b3 100644
--- a/build.gradle
+++ b/build.gradle
@@ -19,7 +19,7 @@ apply plugin: 'com.github.johnrengelman.shadow'
19apply plugin: 'maven' 19apply plugin: 'maven'
20 20
21group = 'cuchaz' 21group = 'cuchaz'
22version = '0.12.1' 22version = '0.12.2'
23 23
24def ENV = System.getenv() 24def ENV = System.getenv()
25if (ENV.BUILD_NUMBER) { 25if (ENV.BUILD_NUMBER) {
diff --git a/src/main/java/cuchaz/enigma/analysis/TranslationIndex.java b/src/main/java/cuchaz/enigma/analysis/TranslationIndex.java
index b2ddc5fa..db116623 100644
--- a/src/main/java/cuchaz/enigma/analysis/TranslationIndex.java
+++ b/src/main/java/cuchaz/enigma/analysis/TranslationIndex.java
@@ -11,6 +11,8 @@
11 11
12package cuchaz.enigma.analysis; 12package cuchaz.enigma.analysis;
13 13
14import com.google.common.cache.Cache;
15import com.google.common.cache.CacheBuilder;
14import com.google.common.collect.HashMultimap; 16import com.google.common.collect.HashMultimap;
15import com.google.common.collect.Lists; 17import com.google.common.collect.Lists;
16import com.google.common.collect.Maps; 18import com.google.common.collect.Maps;
@@ -19,15 +21,13 @@ import cuchaz.enigma.bytecode.AccessFlags;
19import cuchaz.enigma.mapping.*; 21import cuchaz.enigma.mapping.*;
20import cuchaz.enigma.mapping.entry.*; 22import cuchaz.enigma.mapping.entry.*;
21 23
22import java.util.Collection; 24import java.util.*;
23import java.util.List;
24import java.util.Map;
25import java.util.Set;
26 25
27public class TranslationIndex { 26public class TranslationIndex {
28 27
29 private final ReferencedEntryPool entryPool; 28 private final ReferencedEntryPool entryPool;
30 private Map<ClassEntry, ClassEntry> superclasses; 29 private Map<ClassEntry, ClassEntry> superclasses;
30 private Map<Entry, DefEntry> defEntries = new HashMap<>();
31 private Multimap<ClassEntry, FieldDefEntry> fieldEntries; 31 private Multimap<ClassEntry, FieldDefEntry> fieldEntries;
32 private Multimap<ClassEntry, MethodDefEntry> methodEntries; 32 private Multimap<ClassEntry, MethodDefEntry> methodEntries;
33 private Multimap<ClassEntry, ClassEntry> interfaces; 33 private Multimap<ClassEntry, ClassEntry> interfaces;
@@ -38,6 +38,14 @@ public class TranslationIndex {
38 this.fieldEntries = HashMultimap.create(); 38 this.fieldEntries = HashMultimap.create();
39 this.methodEntries = HashMultimap.create(); 39 this.methodEntries = HashMultimap.create();
40 this.interfaces = HashMultimap.create(); 40 this.interfaces = HashMultimap.create();
41
42 for (FieldDefEntry entry : fieldEntries.values()) {
43 defEntries.put(entry, entry);
44 }
45
46 for (MethodDefEntry entry : methodEntries.values()) {
47 defEntries.put(entry, entry);
48 }
41 } 49 }
42 50
43 public TranslationIndex(TranslationIndex other, Translator translator) { 51 public TranslationIndex(TranslationIndex other, Translator translator) {
@@ -74,6 +82,14 @@ public class TranslationIndex {
74 translator.getTranslatedMethodDef(mapEntry.getValue()) 82 translator.getTranslatedMethodDef(mapEntry.getValue())
75 ); 83 );
76 } 84 }
85
86 for (FieldDefEntry entry : fieldEntries.values()) {
87 defEntries.put(entry, entry);
88 }
89
90 for (MethodDefEntry entry : methodEntries.values()) {
91 defEntries.put(entry, entry);
92 }
77 } 93 }
78 94
79 protected ClassDefEntry indexClass(int access, String name, String signature, String superName, String[] interfaces) { 95 protected ClassDefEntry indexClass(int access, String name, String signature, String superName, String[] interfaces) {
@@ -101,16 +117,27 @@ public class TranslationIndex {
101 117
102 protected void indexField(FieldDefEntry fieldEntry) { 118 protected void indexField(FieldDefEntry fieldEntry) {
103 this.fieldEntries.put(fieldEntry.getOwnerClassEntry(), fieldEntry); 119 this.fieldEntries.put(fieldEntry.getOwnerClassEntry(), fieldEntry);
120 this.defEntries.put(fieldEntry, fieldEntry);
104 } 121 }
105 122
106 protected void indexMethod(MethodDefEntry methodEntry) { 123 protected void indexMethod(MethodDefEntry methodEntry) {
107 this.methodEntries.put(methodEntry.getOwnerClassEntry(), methodEntry); 124 this.methodEntries.put(methodEntry.getOwnerClassEntry(), methodEntry);
125 this.defEntries.put(methodEntry, methodEntry);
108 } 126 }
109 127
110 public void renameClasses(Map<String, String> renames) { 128 public void renameClasses(Map<String, String> renames) {
111 EntryRenamer.renameClassesInMap(renames, this.superclasses); 129 EntryRenamer.renameClassesInMap(renames, this.superclasses);
112 EntryRenamer.renameClassesInMultimap(renames, this.fieldEntries); 130 EntryRenamer.renameClassesInMultimap(renames, this.fieldEntries);
113 EntryRenamer.renameClassesInMultimap(renames, this.methodEntries); 131 EntryRenamer.renameClassesInMultimap(renames, this.methodEntries);
132
133 this.defEntries.clear();
134 for (FieldDefEntry entry : fieldEntries.values()) {
135 defEntries.put(entry, entry);
136 }
137
138 for (MethodDefEntry entry : methodEntries.values()) {
139 defEntries.put(entry, entry);
140 }
114 } 141 }
115 142
116 public ClassEntry getSuperclass(ClassEntry classEntry) { 143 public ClassEntry getSuperclass(ClassEntry classEntry) {
@@ -171,6 +198,7 @@ public class TranslationIndex {
171 if (entry == null) { 198 if (entry == null) {
172 return false; 199 return false;
173 } 200 }
201
174 if (entry instanceof FieldEntry) { 202 if (entry instanceof FieldEntry) {
175 return fieldExists((FieldEntry) entry); 203 return fieldExists((FieldEntry) entry);
176 } else if (entry instanceof MethodEntry) { 204 } else if (entry instanceof MethodEntry) {
@@ -190,95 +218,42 @@ public class TranslationIndex {
190 } 218 }
191 219
192 public ClassEntry resolveEntryOwner(Entry entry) { 220 public ClassEntry resolveEntryOwner(Entry entry) {
193 return resolveEntryOwner(entry, false);
194 }
195
196 public ClassEntry resolveEntryOwner(Entry entry, boolean checkSuperclassBeforeChild) {
197 if (entry instanceof ClassEntry) { 221 if (entry instanceof ClassEntry) {
198 return (ClassEntry) entry; 222 return (ClassEntry) entry;
199 } 223 }
200 224
201 ClassEntry superclassEntry = resolveSuperclass(entry, checkSuperclassBeforeChild); 225 if (entryExists(entry)) {
202 if (superclassEntry != null) { 226 return entry.getOwnerClassEntry();
203 return superclassEntry;
204 }
205
206 ClassEntry interfaceEntry = resolveInterface(entry);
207 if (interfaceEntry != null) {
208 return interfaceEntry;
209 } 227 }
210 228
211 return null; 229 DefEntry def = defEntries.get(entry);
212 } 230 if (def != null && (def.getAccess().isPrivate())) {
213 231 return null;
214 public ClassEntry resolveSuperclass(Entry entry, boolean checkSuperclassBeforeChild) {
215
216 // Default case
217 if (!checkSuperclassBeforeChild)
218 return resolveSuperclass(entry);
219
220 // Save the original entry
221 Entry originalEntry = entry;
222
223 // Get all possible superclasses and reverse the list
224 List<ClassEntry> superclasses = Lists.reverse(getAncestry(originalEntry.getOwnerClassEntry()));
225
226 boolean existInEntry = false;
227
228 for (ClassEntry classEntry : superclasses) {
229 entry = entry.updateOwnership(classEntry);
230 existInEntry = entryExists(entry);
231
232 // Check for possible entry in interfaces of superclasses
233 ClassEntry interfaceEntry = resolveInterface(entry);
234 if (interfaceEntry != null)
235 return interfaceEntry;
236 if (existInEntry)
237 break;
238 } 232 }
239 233
240 // Doesn't exists in superclasses? check the child or return null 234 // if we're protected/public/non-static, chances are we're somewhere down
241 if (!existInEntry) 235 LinkedList<ClassEntry> classEntries = new LinkedList<>();
242 return !entryExists(originalEntry) ? null : originalEntry.getOwnerClassEntry(); 236 classEntries.add(entry.getOwnerClassEntry());
243 237 while (!classEntries.isEmpty()) {
244 return entry.getOwnerClassEntry(); 238 ClassEntry c = classEntries.remove();
245 } 239 Entry cEntry = entry.updateOwnership(c);
246 240
247 public ClassEntry resolveSuperclass(Entry entry) { 241 if (entryExists(cEntry)) {
248 // this entry could refer to a method on a class where the method is not actually implemented 242 def = defEntries.get(cEntry);
249 // travel up the inheritance tree to find the closest implementation 243 if (def == null || (!def.getAccess().isPrivate())) {
250 244 return cEntry.getOwnerClassEntry();
251 while (!entryExists(entry)) { 245 }
252 // is there a parent class?
253 ClassEntry superclassEntry = getSuperclass(entry.getOwnerClassEntry());
254 if (superclassEntry == null) {
255 // this is probably a method from a class in a library
256 // we can't trace the implementation up any higher unless we index the library
257 return null;
258 } 246 }
259 247
260 // move up to the parent class 248 ClassEntry superC = getSuperclass(c);
261 entry = entry.updateOwnership(superclassEntry); 249 if (superC != null) {
262 } 250 classEntries.add(superC);
263 return entry.getOwnerClassEntry();
264 }
265
266 public ClassEntry resolveInterface(Entry entry) {
267 // the interfaces for any class is a forest
268 // so let's look at all the trees
269
270 for (ClassEntry interfaceEntry : this.interfaces.get(entry.getOwnerClassEntry())) {
271 Collection<ClassEntry> subInterface = this.interfaces.get(interfaceEntry);
272 if (subInterface != null && !subInterface.isEmpty()) {
273 ClassEntry result = resolveInterface(entry.updateOwnership(interfaceEntry));
274 if (result != null)
275 return result;
276 } 251 }
277 ClassEntry resolvedClassEntry = resolveSuperclass(entry.updateOwnership(interfaceEntry)); 252 if (entry instanceof MethodEntry) {
278 if (resolvedClassEntry != null) { 253 classEntries.addAll(getInterfaces(c));
279 return resolvedClassEntry;
280 } 254 }
281 } 255 }
256
282 return null; 257 return null;
283 } 258 }
284 259
diff --git a/src/main/java/cuchaz/enigma/mapping/DirectionalTranslator.java b/src/main/java/cuchaz/enigma/mapping/DirectionalTranslator.java
index 10fb9215..388e7ac3 100644
--- a/src/main/java/cuchaz/enigma/mapping/DirectionalTranslator.java
+++ b/src/main/java/cuchaz/enigma/mapping/DirectionalTranslator.java
@@ -131,7 +131,7 @@ public class DirectionalTranslator implements Translator {
131 131
132 private String translateFieldName(FieldEntry entry) { 132 private String translateFieldName(FieldEntry entry) {
133 // resolve the class entry 133 // resolve the class entry
134 ClassEntry resolvedClassEntry = this.index.resolveEntryOwner(entry, true); 134 ClassEntry resolvedClassEntry = this.index.resolveEntryOwner(entry);
135 if (resolvedClassEntry != null) { 135 if (resolvedClassEntry != null) {
136 // look for the class 136 // look for the class
137 ClassMapping classMapping = findClassMapping(resolvedClassEntry); 137 ClassMapping classMapping = findClassMapping(resolvedClassEntry);
@@ -175,7 +175,7 @@ public class DirectionalTranslator implements Translator {
175 175
176 private String translateMethodName(MethodEntry entry) { 176 private String translateMethodName(MethodEntry entry) {
177 // resolve the class entry 177 // resolve the class entry
178 ClassEntry resolvedOwner = this.index.resolveEntryOwner(entry, true); 178 ClassEntry resolvedOwner = this.index.resolveEntryOwner(entry);
179 if (resolvedOwner != null) { 179 if (resolvedOwner != null) {
180 // look for class 180 // look for class
181 ClassMapping classMapping = findClassMapping(resolvedOwner); 181 ClassMapping classMapping = findClassMapping(resolvedOwner);
diff --git a/src/main/java/cuchaz/enigma/mapping/MappingsRenamer.java b/src/main/java/cuchaz/enigma/mapping/MappingsRenamer.java
index 72a12c26..8ef4f12b 100644
--- a/src/main/java/cuchaz/enigma/mapping/MappingsRenamer.java
+++ b/src/main/java/cuchaz/enigma/mapping/MappingsRenamer.java
@@ -92,9 +92,9 @@ public class MappingsRenamer {
92 deobfName = NameValidator.validateFieldName(deobfName); 92 deobfName = NameValidator.validateFieldName(deobfName);
93 FieldEntry targetEntry = entryPool.getField(obf.getOwnerClassEntry(), deobfName, obf.getDesc()); 93 FieldEntry targetEntry = entryPool.getField(obf.getOwnerClassEntry(), deobfName, obf.getDesc());
94 ClassEntry definedClass = null; 94 ClassEntry definedClass = null;
95 if (mappings.containsDeobfField(obf.getOwnerClassEntry(), deobfName) || index.containsEntryWithSameName(targetEntry)) 95 if (mappings.containsDeobfField(obf.getOwnerClassEntry(), deobfName) || index.containsEntryWithSameName(targetEntry)) {
96 definedClass = obf.getOwnerClassEntry(); 96 definedClass = obf.getOwnerClassEntry();
97 else { 97 } else {
98 for (ClassEntry ancestorEntry : this.index.getTranslationIndex().getAncestry(obf.getOwnerClassEntry())) { 98 for (ClassEntry ancestorEntry : this.index.getTranslationIndex().getAncestry(obf.getOwnerClassEntry())) {
99 if (mappings.containsDeobfField(ancestorEntry, deobfName) || index.containsEntryWithSameName(targetEntry.updateOwnership(ancestorEntry))) { 99 if (mappings.containsDeobfField(ancestorEntry, deobfName) || index.containsEntryWithSameName(targetEntry.updateOwnership(ancestorEntry))) {
100 definedClass = ancestorEntry; 100 definedClass = ancestorEntry;
diff --git a/src/main/java/cuchaz/enigma/mapping/entry/ClassDefEntry.java b/src/main/java/cuchaz/enigma/mapping/entry/ClassDefEntry.java
index ac1fe2ab..df72e7e9 100644
--- a/src/main/java/cuchaz/enigma/mapping/entry/ClassDefEntry.java
+++ b/src/main/java/cuchaz/enigma/mapping/entry/ClassDefEntry.java
@@ -15,7 +15,7 @@ import com.google.common.base.Preconditions;
15import cuchaz.enigma.bytecode.AccessFlags; 15import cuchaz.enigma.bytecode.AccessFlags;
16import cuchaz.enigma.mapping.Signature; 16import cuchaz.enigma.mapping.Signature;
17 17
18public class ClassDefEntry extends ClassEntry { 18public class ClassDefEntry extends ClassEntry implements DefEntry {
19 private final AccessFlags access; 19 private final AccessFlags access;
20 private final Signature signature; 20 private final Signature signature;
21 21
@@ -31,6 +31,7 @@ public class ClassDefEntry extends ClassEntry {
31 return signature; 31 return signature;
32 } 32 }
33 33
34 @Override
34 public AccessFlags getAccess() { 35 public AccessFlags getAccess() {
35 return access; 36 return access;
36 } 37 }
diff --git a/src/main/java/cuchaz/enigma/mapping/entry/DefEntry.java b/src/main/java/cuchaz/enigma/mapping/entry/DefEntry.java
new file mode 100644
index 00000000..43ad0274
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/mapping/entry/DefEntry.java
@@ -0,0 +1,7 @@
1package cuchaz.enigma.mapping.entry;
2
3import cuchaz.enigma.bytecode.AccessFlags;
4
5public interface DefEntry extends Entry {
6 AccessFlags getAccess();
7}
diff --git a/src/main/java/cuchaz/enigma/mapping/entry/FieldDefEntry.java b/src/main/java/cuchaz/enigma/mapping/entry/FieldDefEntry.java
index d18115bf..223410f5 100644
--- a/src/main/java/cuchaz/enigma/mapping/entry/FieldDefEntry.java
+++ b/src/main/java/cuchaz/enigma/mapping/entry/FieldDefEntry.java
@@ -16,7 +16,7 @@ import cuchaz.enigma.bytecode.AccessFlags;
16import cuchaz.enigma.mapping.Signature; 16import cuchaz.enigma.mapping.Signature;
17import cuchaz.enigma.mapping.TypeDescriptor; 17import cuchaz.enigma.mapping.TypeDescriptor;
18 18
19public class FieldDefEntry extends FieldEntry { 19public class FieldDefEntry extends FieldEntry implements DefEntry {
20 private final AccessFlags access; 20 private final AccessFlags access;
21 private final Signature signature; 21 private final Signature signature;
22 22
@@ -28,6 +28,7 @@ public class FieldDefEntry extends FieldEntry {
28 this.signature = signature; 28 this.signature = signature;
29 } 29 }
30 30
31 @Override
31 public AccessFlags getAccess() { 32 public AccessFlags getAccess() {
32 return access; 33 return access;
33 } 34 }
diff --git a/src/main/java/cuchaz/enigma/mapping/entry/MethodDefEntry.java b/src/main/java/cuchaz/enigma/mapping/entry/MethodDefEntry.java
index ec3af694..960b08d1 100644
--- a/src/main/java/cuchaz/enigma/mapping/entry/MethodDefEntry.java
+++ b/src/main/java/cuchaz/enigma/mapping/entry/MethodDefEntry.java
@@ -16,7 +16,7 @@ import cuchaz.enigma.bytecode.AccessFlags;
16import cuchaz.enigma.mapping.MethodDescriptor; 16import cuchaz.enigma.mapping.MethodDescriptor;
17import cuchaz.enigma.mapping.Signature; 17import cuchaz.enigma.mapping.Signature;
18 18
19public class MethodDefEntry extends MethodEntry { 19public class MethodDefEntry extends MethodEntry implements DefEntry {
20 20
21 private final AccessFlags access; 21 private final AccessFlags access;
22 private final Signature signature; 22 private final Signature signature;
@@ -29,6 +29,7 @@ public class MethodDefEntry extends MethodEntry {
29 this.signature = signature; 29 this.signature = signature;
30 } 30 }
31 31
32 @Override
32 public AccessFlags getAccess() { 33 public AccessFlags getAccess() {
33 return access; 34 return access;
34 } 35 }
diff --git a/src/main/java/cuchaz/enigma/utils/Utils.java b/src/main/java/cuchaz/enigma/utils/Utils.java
index 8e502d47..bd09c64f 100644
--- a/src/main/java/cuchaz/enigma/utils/Utils.java
+++ b/src/main/java/cuchaz/enigma/utils/Utils.java
@@ -27,7 +27,15 @@ import java.util.List;
27public class Utils { 27public class Utils {
28 28
29 public static int combineHashesOrdered(Object... objs) { 29 public static int combineHashesOrdered(Object... objs) {
30 return combineHashesOrdered(Arrays.asList(objs)); 30 final int prime = 67;
31 int result = 1;
32 for (Object obj : objs) {
33 result *= prime;
34 if (obj != null) {
35 result += obj.hashCode();
36 }
37 }
38 return result;
31 } 39 }
32 40
33 public static int combineHashesOrdered(List<Object> objs) { 41 public static int combineHashesOrdered(List<Object> objs) {