summaryrefslogtreecommitdiff
path: root/src/main/java/cuchaz/enigma/mapping/ClassMapping.java
diff options
context:
space:
mode:
authorGravatar Thog2017-03-08 08:17:04 +0100
committerGravatar Thog2017-03-08 08:17:04 +0100
commit6e464ea251cab63c776ece0b2a356f1498ffa294 (patch)
tree5ed30c03f5ac4cd2d6877874f5ede576049954f7 /src/main/java/cuchaz/enigma/mapping/ClassMapping.java
parentDrop unix case style and implement hashCode when equals is overrided (diff)
downloadenigma-fork-6e464ea251cab63c776ece0b2a356f1498ffa294.tar.gz
enigma-fork-6e464ea251cab63c776ece0b2a356f1498ffa294.tar.xz
enigma-fork-6e464ea251cab63c776ece0b2a356f1498ffa294.zip
Follow Fabric guidelines
Diffstat (limited to 'src/main/java/cuchaz/enigma/mapping/ClassMapping.java')
-rw-r--r--src/main/java/cuchaz/enigma/mapping/ClassMapping.java1042
1 files changed, 516 insertions, 526 deletions
diff --git a/src/main/java/cuchaz/enigma/mapping/ClassMapping.java b/src/main/java/cuchaz/enigma/mapping/ClassMapping.java
index a261c91..178dd3c 100644
--- a/src/main/java/cuchaz/enigma/mapping/ClassMapping.java
+++ b/src/main/java/cuchaz/enigma/mapping/ClassMapping.java
@@ -8,540 +8,530 @@
8 * Contributors: 8 * Contributors:
9 * Jeff Martin - initial API and implementation 9 * Jeff Martin - initial API and implementation
10 ******************************************************************************/ 10 ******************************************************************************/
11
11package cuchaz.enigma.mapping; 12package cuchaz.enigma.mapping;
12 13
13import com.google.common.collect.Maps; 14import com.google.common.collect.Maps;
15import cuchaz.enigma.throwables.MappingConflict;
14 16
15import java.util.ArrayList; 17import java.util.ArrayList;
16import java.util.Map; 18import java.util.Map;
17 19
18import cuchaz.enigma.throwables.MappingConflict;
19
20// FIXME: Enigma doesn't support inner classes of inner class????! 20// FIXME: Enigma doesn't support inner classes of inner class????!
21public class ClassMapping implements Comparable<ClassMapping> { 21public class ClassMapping implements Comparable<ClassMapping> {
22 22
23 private String obfFullName; 23 private String obfFullName;
24 private String obfSimpleName; 24 private String obfSimpleName;
25 private String deobfName; 25 private String deobfName;
26 private String previousDeobfName; 26 private String previousDeobfName;
27 private Map<String, ClassMapping> innerClassesByObfSimple; 27 private Map<String, ClassMapping> innerClassesByObfSimple;
28 private Map<String, ClassMapping> innerClassesByObfFull; 28 private Map<String, ClassMapping> innerClassesByObfFull;
29 private Map<String, ClassMapping> innerClassesByDeobf; 29 private Map<String, ClassMapping> innerClassesByDeobf;
30 private Map<String, FieldMapping> fieldsByObf; 30 private Map<String, FieldMapping> fieldsByObf;
31 private Map<String, FieldMapping> fieldsByDeobf; 31 private Map<String, FieldMapping> fieldsByDeobf;
32 private Map<String, MethodMapping> methodsByObf; 32 private Map<String, MethodMapping> methodsByObf;
33 private Map<String, MethodMapping> methodsByDeobf; 33 private Map<String, MethodMapping> methodsByDeobf;
34 private boolean isDirty; 34 private boolean isDirty;
35 private Mappings.EntryModifier modifier; 35 private Mappings.EntryModifier modifier;
36 36
37 public ClassMapping(String obfFullName) 37 public ClassMapping(String obfFullName) {
38 { 38 this(obfFullName, null, Mappings.EntryModifier.UNCHANGED);
39 this(obfFullName, null, Mappings.EntryModifier.UNCHANGED); 39 }
40 } 40
41 41 public ClassMapping(String obfFullName, String deobfName) {
42 public ClassMapping(String obfFullName, String deobfName) 42 this(obfFullName, deobfName, Mappings.EntryModifier.UNCHANGED);
43 { 43 }
44 this(obfFullName, deobfName, Mappings.EntryModifier.UNCHANGED); 44
45 } 45 public ClassMapping(String obfFullName, String deobfName, Mappings.EntryModifier modifier) {
46 46 this.obfFullName = obfFullName;
47 public ClassMapping(String obfFullName, String deobfName, Mappings.EntryModifier modifier) 47 ClassEntry classEntry = new ClassEntry(obfFullName);
48 { 48 obfSimpleName = classEntry.isInnerClass() ? classEntry.getInnermostClassName() : classEntry.getSimpleName();
49 this.obfFullName = obfFullName; 49 previousDeobfName = null;
50 ClassEntry classEntry = new ClassEntry(obfFullName); 50 this.deobfName = NameValidator.validateClassName(deobfName, false);
51 obfSimpleName = classEntry.isInnerClass() ? classEntry.getInnermostClassName() : classEntry.getSimpleName(); 51 innerClassesByObfSimple = Maps.newHashMap();
52 previousDeobfName = null; 52 innerClassesByObfFull = Maps.newHashMap();
53 this.deobfName = NameValidator.validateClassName(deobfName, false); 53 innerClassesByDeobf = Maps.newHashMap();
54 innerClassesByObfSimple = Maps.newHashMap(); 54 fieldsByObf = Maps.newHashMap();
55 innerClassesByObfFull = Maps.newHashMap(); 55 fieldsByDeobf = Maps.newHashMap();
56 innerClassesByDeobf = Maps.newHashMap(); 56 methodsByObf = Maps.newHashMap();
57 fieldsByObf = Maps.newHashMap(); 57 methodsByDeobf = Maps.newHashMap();
58 fieldsByDeobf = Maps.newHashMap(); 58 isDirty = true;
59 methodsByObf = Maps.newHashMap(); 59 this.modifier = modifier;
60 methodsByDeobf = Maps.newHashMap(); 60 }
61 isDirty = true; 61
62 this.modifier = modifier; 62 public static boolean isSimpleClassName(String name) {
63 } 63 return name.indexOf('/') < 0 && name.indexOf('$') < 0;
64 64 }
65 public String getObfFullName() { 65
66 return obfFullName; 66 public String getObfFullName() {
67 } 67 return obfFullName;
68 68 }
69 public String getObfSimpleName() { 69
70 return obfSimpleName; 70 public String getObfSimpleName() {
71 } 71 return obfSimpleName;
72 72 }
73 public String getPreviousDeobfName() { 73
74 return previousDeobfName; 74 public String getPreviousDeobfName() {
75 } 75 return previousDeobfName;
76 76 }
77 public String getDeobfName() { 77
78 return deobfName; 78 public String getDeobfName() {
79 } 79 return deobfName;
80 80 }
81 public void setDeobfName(String val) { 81
82 previousDeobfName = deobfName; 82 //// INNER CLASSES ////////
83 deobfName = NameValidator.validateClassName(val, false); 83
84 this.isDirty = true; 84 public void setDeobfName(String val) {
85 } 85 previousDeobfName = deobfName;
86 86 deobfName = NameValidator.validateClassName(val, false);
87 //// INNER CLASSES //////// 87 this.isDirty = true;
88 88 }
89 public Iterable<ClassMapping> innerClasses() { 89
90 assert (innerClassesByObfSimple.size() >= innerClassesByDeobf.size()); 90 public Iterable<ClassMapping> innerClasses() {
91 return innerClassesByObfSimple.values(); 91 assert (innerClassesByObfSimple.size() >= innerClassesByDeobf.size());
92 } 92 return innerClassesByObfSimple.values();
93 93 }
94 public void addInnerClassMapping(ClassMapping classMapping) throws MappingConflict { 94
95 // FIXME: dirty hack, that can get into issues, but it's a temp fix! 95 public void addInnerClassMapping(ClassMapping classMapping) throws MappingConflict {
96 if (this.innerClassesByObfFull.containsKey(classMapping.getObfSimpleName())) { 96 // FIXME: dirty hack, that can get into issues, but it's a temp fix!
97 throw new MappingConflict("classes", classMapping.getObfSimpleName(), this.innerClassesByObfSimple.get(classMapping.getObfSimpleName()).getObfSimpleName()); 97 if (this.innerClassesByObfFull.containsKey(classMapping.getObfSimpleName())) {
98 } 98 throw new MappingConflict("classes", classMapping.getObfSimpleName(), this.innerClassesByObfSimple.get(classMapping.getObfSimpleName()).getObfSimpleName());
99 innerClassesByObfFull.put(classMapping.getObfFullName(), classMapping); 99 }
100 innerClassesByObfSimple.put(classMapping.getObfSimpleName(), classMapping); 100 innerClassesByObfFull.put(classMapping.getObfFullName(), classMapping);
101 101 innerClassesByObfSimple.put(classMapping.getObfSimpleName(), classMapping);
102 if (classMapping.getDeobfName() != null) { 102
103 if (this.innerClassesByDeobf.containsKey(classMapping.getDeobfName())) { 103 if (classMapping.getDeobfName() != null) {
104 throw new MappingConflict("classes", classMapping.getDeobfName(), this.innerClassesByDeobf.get(classMapping.getDeobfName()).getDeobfName()); 104 if (this.innerClassesByDeobf.containsKey(classMapping.getDeobfName())) {
105 } 105 throw new MappingConflict("classes", classMapping.getDeobfName(), this.innerClassesByDeobf.get(classMapping.getDeobfName()).getDeobfName());
106 innerClassesByDeobf.put(classMapping.getDeobfName(), classMapping); 106 }
107 } 107 innerClassesByDeobf.put(classMapping.getDeobfName(), classMapping);
108 this.isDirty = true; 108 }
109 } 109 this.isDirty = true;
110 110 }
111 public void removeInnerClassMapping(ClassMapping classMapping) { 111
112 innerClassesByObfFull.remove(classMapping.getObfFullName()); 112 public void removeInnerClassMapping(ClassMapping classMapping) {
113 boolean obfWasRemoved = innerClassesByObfSimple.remove(classMapping.getObfSimpleName()) != null; 113 innerClassesByObfFull.remove(classMapping.getObfFullName());
114 assert (obfWasRemoved); 114 boolean obfWasRemoved = innerClassesByObfSimple.remove(classMapping.getObfSimpleName()) != null;
115 if (classMapping.getDeobfName() != null) { 115 assert (obfWasRemoved);
116 boolean deobfWasRemoved = innerClassesByDeobf.remove(classMapping.getDeobfName()) != null; 116 if (classMapping.getDeobfName() != null) {
117 assert (deobfWasRemoved); 117 boolean deobfWasRemoved = innerClassesByDeobf.remove(classMapping.getDeobfName()) != null;
118 } 118 assert (deobfWasRemoved);
119 this.isDirty = true; 119 }
120 } 120 this.isDirty = true;
121 121 }
122 public ClassMapping getOrCreateInnerClass(ClassEntry obfInnerClass) { 122
123 ClassMapping classMapping = innerClassesByObfSimple.get(obfInnerClass.getInnermostClassName()); 123 public ClassMapping getOrCreateInnerClass(ClassEntry obfInnerClass) {
124 if (classMapping == null) { 124 ClassMapping classMapping = innerClassesByObfSimple.get(obfInnerClass.getInnermostClassName());
125 classMapping = new ClassMapping(obfInnerClass.getName()); 125 if (classMapping == null) {
126 innerClassesByObfFull.put(classMapping.getObfFullName(), classMapping); 126 classMapping = new ClassMapping(obfInnerClass.getName());
127 boolean wasAdded = innerClassesByObfSimple.put(classMapping.getObfSimpleName(), classMapping) == null; 127 innerClassesByObfFull.put(classMapping.getObfFullName(), classMapping);
128 assert (wasAdded); 128 boolean wasAdded = innerClassesByObfSimple.put(classMapping.getObfSimpleName(), classMapping) == null;
129 this.isDirty = true; 129 assert (wasAdded);
130 } 130 this.isDirty = true;
131 return classMapping; 131 }
132 } 132 return classMapping;
133 133 }
134 public ClassMapping getInnerClassByObfSimple(String obfSimpleName) { 134
135 assert (isSimpleClassName(obfSimpleName)); 135 public ClassMapping getInnerClassByObfSimple(String obfSimpleName) {
136 return innerClassesByObfSimple.get(obfSimpleName); 136 assert (isSimpleClassName(obfSimpleName));
137 } 137 return innerClassesByObfSimple.get(obfSimpleName);
138 138 }
139 public ClassMapping getInnerClassByDeobf(String deobfName) { 139
140 assert (isSimpleClassName(deobfName)); 140 public ClassMapping getInnerClassByDeobf(String deobfName) {
141 return innerClassesByDeobf.get(deobfName); 141 assert (isSimpleClassName(deobfName));
142 } 142 return innerClassesByDeobf.get(deobfName);
143 143 }
144 public ClassMapping getInnerClassByDeobfThenObfSimple(String name) { 144
145 ClassMapping classMapping = getInnerClassByDeobf(name); 145 public ClassMapping getInnerClassByDeobfThenObfSimple(String name) {
146 if (classMapping == null) { 146 ClassMapping classMapping = getInnerClassByDeobf(name);
147 classMapping = getInnerClassByObfSimple(name); 147 if (classMapping == null) {
148 } 148 classMapping = getInnerClassByObfSimple(name);
149 return classMapping; 149 }
150 } 150 return classMapping;
151 151 }
152 public String getDeobfInnerClassName(String obfSimpleName) { 152
153 assert (isSimpleClassName(obfSimpleName)); 153 public String getDeobfInnerClassName(String obfSimpleName) {
154 ClassMapping classMapping = innerClassesByObfSimple.get(obfSimpleName); 154 assert (isSimpleClassName(obfSimpleName));
155 if (classMapping != null) { 155 ClassMapping classMapping = innerClassesByObfSimple.get(obfSimpleName);
156 return classMapping.getDeobfName(); 156 if (classMapping != null) {
157 } 157 return classMapping.getDeobfName();
158 return null; 158 }
159 } 159 return null;
160 160 }
161 public void setInnerClassName(ClassEntry obfInnerClass, String deobfName) { 161
162 ClassMapping classMapping = getOrCreateInnerClass(obfInnerClass); 162 public void setInnerClassName(ClassEntry obfInnerClass, String deobfName) {
163 if (classMapping.getDeobfName() != null) { 163 ClassMapping classMapping = getOrCreateInnerClass(obfInnerClass);
164 boolean wasRemoved = innerClassesByDeobf.remove(classMapping.getDeobfName()) != null; 164 if (classMapping.getDeobfName() != null) {
165 assert (wasRemoved); 165 boolean wasRemoved = innerClassesByDeobf.remove(classMapping.getDeobfName()) != null;
166 } 166 assert (wasRemoved);
167 classMapping.setDeobfName(deobfName); 167 }
168 if (deobfName != null) { 168 classMapping.setDeobfName(deobfName);
169 assert (isSimpleClassName(deobfName)); 169 if (deobfName != null) {
170 boolean wasAdded = innerClassesByDeobf.put(deobfName, classMapping) == null; 170 assert (isSimpleClassName(deobfName));
171 assert (wasAdded); 171 boolean wasAdded = innerClassesByDeobf.put(deobfName, classMapping) == null;
172 } 172 assert (wasAdded);
173 this.isDirty = true; 173 }
174 } 174 this.isDirty = true;
175 175 }
176 public boolean hasInnerClassByObfSimple(String obfSimpleName) { 176
177 return innerClassesByObfSimple.containsKey(obfSimpleName); 177 public boolean hasInnerClassByObfSimple(String obfSimpleName) {
178 } 178 return innerClassesByObfSimple.containsKey(obfSimpleName);
179 179 }
180 public boolean hasInnerClassByDeobf(String deobfName) { 180
181 return innerClassesByDeobf.containsKey(deobfName); 181 //// FIELDS ////////
182 } 182
183 183 public boolean hasInnerClassByDeobf(String deobfName) {
184 184 return innerClassesByDeobf.containsKey(deobfName);
185 //// FIELDS //////// 185 }
186 186
187 public Iterable<FieldMapping> fields() { 187 public Iterable<FieldMapping> fields() {
188 assert (fieldsByObf.size() == fieldsByDeobf.size()); 188 assert (fieldsByObf.size() == fieldsByDeobf.size());
189 return fieldsByObf.values(); 189 return fieldsByObf.values();
190 } 190 }
191 191
192 public boolean containsObfField(String obfName, Type obfType) { 192 public boolean containsObfField(String obfName, Type obfType) {
193 return fieldsByObf.containsKey(getFieldKey(obfName, obfType)); 193 return fieldsByObf.containsKey(getFieldKey(obfName, obfType));
194 } 194 }
195 195
196 public boolean containsDeobfField(String deobfName, Type deobfType) { 196 public boolean containsDeobfField(String deobfName, Type deobfType) {
197 return fieldsByDeobf.containsKey(getFieldKey(deobfName, deobfType)); 197 return fieldsByDeobf.containsKey(getFieldKey(deobfName, deobfType));
198 } 198 }
199 199
200 public void addFieldMapping(FieldMapping fieldMapping) { 200 public void addFieldMapping(FieldMapping fieldMapping) {
201 String obfKey = getFieldKey(fieldMapping.getObfName(), fieldMapping.getObfType()); 201 String obfKey = getFieldKey(fieldMapping.getObfName(), fieldMapping.getObfType());
202 if (fieldsByObf.containsKey(obfKey)) { 202 if (fieldsByObf.containsKey(obfKey)) {
203 throw new Error("Already have mapping for " + obfFullName + "." + obfKey); 203 throw new Error("Already have mapping for " + obfFullName + "." + obfKey);
204 } 204 }
205 if (fieldMapping.getDeobfName() != null) { 205 if (fieldMapping.getDeobfName() != null) {
206 String deobfKey = getFieldKey(fieldMapping.getDeobfName(), fieldMapping.getObfType()); 206 String deobfKey = getFieldKey(fieldMapping.getDeobfName(), fieldMapping.getObfType());
207 if (fieldsByDeobf.containsKey(deobfKey)) { 207 if (fieldsByDeobf.containsKey(deobfKey)) {
208 throw new Error("Already have mapping for " + deobfName + "." + deobfKey); 208 throw new Error("Already have mapping for " + deobfName + "." + deobfKey);
209 } 209 }
210 boolean deobfWasAdded = fieldsByDeobf.put(deobfKey, fieldMapping) == null; 210 boolean deobfWasAdded = fieldsByDeobf.put(deobfKey, fieldMapping) == null;
211 assert (deobfWasAdded); 211 assert (deobfWasAdded);
212 } 212 }
213 boolean obfWasAdded = fieldsByObf.put(obfKey, fieldMapping) == null; 213 boolean obfWasAdded = fieldsByObf.put(obfKey, fieldMapping) == null;
214 assert (obfWasAdded); 214 assert (obfWasAdded);
215 this.isDirty = true; 215 this.isDirty = true;
216 } 216 }
217 217
218 public void removeFieldMapping(FieldMapping fieldMapping) { 218 public void removeFieldMapping(FieldMapping fieldMapping) {
219 boolean obfWasRemoved = fieldsByObf.remove(getFieldKey(fieldMapping.getObfName(), fieldMapping.getObfType())) != null; 219 boolean obfWasRemoved = fieldsByObf.remove(getFieldKey(fieldMapping.getObfName(), fieldMapping.getObfType())) != null;
220 assert (obfWasRemoved); 220 assert (obfWasRemoved);
221 if (fieldMapping.getDeobfName() != null) { 221 if (fieldMapping.getDeobfName() != null) {
222 boolean deobfWasRemoved = fieldsByDeobf.remove(getFieldKey(fieldMapping.getDeobfName(), fieldMapping.getObfType())) != null; 222 boolean deobfWasRemoved = fieldsByDeobf.remove(getFieldKey(fieldMapping.getDeobfName(), fieldMapping.getObfType())) != null;
223 assert (deobfWasRemoved); 223 assert (deobfWasRemoved);
224 } 224 }
225 this.isDirty = true; 225 this.isDirty = true;
226 } 226 }
227 227
228 public FieldMapping getFieldByObf(String obfName, Type obfType) { 228 public FieldMapping getFieldByObf(String obfName, Type obfType) {
229 return fieldsByObf.get(getFieldKey(obfName, obfType)); 229 return fieldsByObf.get(getFieldKey(obfName, obfType));
230 } 230 }
231 231
232 public FieldMapping getFieldByDeobf(String deobfName, Type obfType) { 232 public FieldMapping getFieldByDeobf(String deobfName, Type obfType) {
233 return fieldsByDeobf.get(getFieldKey(deobfName, obfType)); 233 return fieldsByDeobf.get(getFieldKey(deobfName, obfType));
234 } 234 }
235 235
236 public String getObfFieldName(String deobfName, Type obfType) { 236 public String getObfFieldName(String deobfName, Type obfType) {
237 FieldMapping fieldMapping = fieldsByDeobf.get(getFieldKey(deobfName, obfType)); 237 FieldMapping fieldMapping = fieldsByDeobf.get(getFieldKey(deobfName, obfType));
238 if (fieldMapping != null) { 238 if (fieldMapping != null) {
239 return fieldMapping.getObfName(); 239 return fieldMapping.getObfName();
240 } 240 }
241 return null; 241 return null;
242 } 242 }
243 243
244 public String getDeobfFieldName(String obfName, Type obfType) { 244 public String getDeobfFieldName(String obfName, Type obfType) {
245 FieldMapping fieldMapping = fieldsByObf.get(getFieldKey(obfName, obfType)); 245 FieldMapping fieldMapping = fieldsByObf.get(getFieldKey(obfName, obfType));
246 if (fieldMapping != null) { 246 if (fieldMapping != null) {
247 return fieldMapping.getDeobfName(); 247 return fieldMapping.getDeobfName();
248 } 248 }
249 return null; 249 return null;
250 } 250 }
251 251
252 private String getFieldKey(String name, Type type) { 252 private String getFieldKey(String name, Type type) {
253 if (name == null) { 253 if (name == null) {
254 throw new IllegalArgumentException("name cannot be null!"); 254 throw new IllegalArgumentException("name cannot be null!");
255 } 255 }
256 if (type == null) { 256 if (type == null) {
257 throw new IllegalArgumentException("type cannot be null!"); 257 throw new IllegalArgumentException("type cannot be null!");
258 } 258 }
259 return name + ":" + type; 259 return name + ":" + type;
260 } 260 }
261 261
262 public void setFieldName(String obfName, Type obfType, String deobfName) { 262 public void setFieldName(String obfName, Type obfType, String deobfName) {
263 assert (deobfName != null); 263 assert (deobfName != null);
264 FieldMapping fieldMapping = fieldsByObf.get(getFieldKey(obfName, obfType)); 264 FieldMapping fieldMapping = fieldsByObf.get(getFieldKey(obfName, obfType));
265 if (fieldMapping == null) { 265 if (fieldMapping == null) {
266 fieldMapping = new FieldMapping(obfName, obfType, deobfName, Mappings.EntryModifier.UNCHANGED); 266 fieldMapping = new FieldMapping(obfName, obfType, deobfName, Mappings.EntryModifier.UNCHANGED);
267 boolean obfWasAdded = fieldsByObf.put(getFieldKey(obfName, obfType), fieldMapping) == null; 267 boolean obfWasAdded = fieldsByObf.put(getFieldKey(obfName, obfType), fieldMapping) == null;
268 assert (obfWasAdded); 268 assert (obfWasAdded);
269 } else { 269 } else {
270 boolean wasRemoved = fieldsByDeobf.remove(getFieldKey(fieldMapping.getDeobfName(), obfType)) != null; 270 boolean wasRemoved = fieldsByDeobf.remove(getFieldKey(fieldMapping.getDeobfName(), obfType)) != null;
271 assert (wasRemoved); 271 assert (wasRemoved);
272 } 272 }
273 fieldMapping.setDeobfName(deobfName); 273 fieldMapping.setDeobfName(deobfName);
274 if (deobfName != null) { 274 if (deobfName != null) {
275 boolean wasAdded = fieldsByDeobf.put(getFieldKey(deobfName, obfType), fieldMapping) == null; 275 boolean wasAdded = fieldsByDeobf.put(getFieldKey(deobfName, obfType), fieldMapping) == null;
276 assert (wasAdded); 276 assert (wasAdded);
277 } 277 }
278 this.isDirty = true; 278 this.isDirty = true;
279 } 279 }
280 280
281 public void setFieldObfNameAndType(String oldObfName, Type obfType, String newObfName, Type newObfType) { 281 //// METHODS ////////
282 assert(newObfName != null); 282
283 FieldMapping fieldMapping = fieldsByObf.remove(getFieldKey(oldObfName, obfType)); 283 public void setFieldObfNameAndType(String oldObfName, Type obfType, String newObfName, Type newObfType) {
284 assert(fieldMapping != null); 284 assert (newObfName != null);
285 fieldMapping.setObfName(newObfName); 285 FieldMapping fieldMapping = fieldsByObf.remove(getFieldKey(oldObfName, obfType));
286 fieldMapping.setObfType(newObfType); 286 assert (fieldMapping != null);
287 boolean obfWasAdded = fieldsByObf.put(getFieldKey(newObfName, newObfType), fieldMapping) == null; 287 fieldMapping.setObfName(newObfName);
288 assert(obfWasAdded); 288 fieldMapping.setObfType(newObfType);
289 this.isDirty = true; 289 boolean obfWasAdded = fieldsByObf.put(getFieldKey(newObfName, newObfType), fieldMapping) == null;
290 } 290 assert (obfWasAdded);
291 291 this.isDirty = true;
292 //// METHODS //////// 292 }
293 293
294 public Iterable<MethodMapping> methods() { 294 public Iterable<MethodMapping> methods() {
295 assert (methodsByObf.size() >= methodsByDeobf.size()); 295 assert (methodsByObf.size() >= methodsByDeobf.size());
296 return methodsByObf.values(); 296 return methodsByObf.values();
297 } 297 }
298 298
299 public boolean containsObfMethod(String obfName, Signature obfSignature) { 299 public boolean containsObfMethod(String obfName, Signature obfSignature) {
300 return methodsByObf.containsKey(getMethodKey(obfName, obfSignature)); 300 return methodsByObf.containsKey(getMethodKey(obfName, obfSignature));
301 } 301 }
302 302
303 public boolean containsDeobfMethod(String deobfName, Signature obfSignature) { 303 public boolean containsDeobfMethod(String deobfName, Signature obfSignature) {
304 return methodsByDeobf.containsKey(getMethodKey(deobfName, obfSignature)); 304 return methodsByDeobf.containsKey(getMethodKey(deobfName, obfSignature));
305 } 305 }
306 306
307 public void addMethodMapping(MethodMapping methodMapping) { 307 public void addMethodMapping(MethodMapping methodMapping) {
308 String obfKey = getMethodKey(methodMapping.getObfName(), methodMapping.getObfSignature()); 308 String obfKey = getMethodKey(methodMapping.getObfName(), methodMapping.getObfSignature());
309 if (methodsByObf.containsKey(obfKey)) { 309 if (methodsByObf.containsKey(obfKey)) {
310 throw new Error("Already have mapping for " + obfFullName + "." + obfKey); 310 throw new Error("Already have mapping for " + obfFullName + "." + obfKey);
311 } 311 }
312 boolean wasAdded = methodsByObf.put(obfKey, methodMapping) == null; 312 boolean wasAdded = methodsByObf.put(obfKey, methodMapping) == null;
313 assert (wasAdded); 313 assert (wasAdded);
314 if (methodMapping.getDeobfName() != null) { 314 if (methodMapping.getDeobfName() != null) {
315 String deobfKey = getMethodKey(methodMapping.getDeobfName(), methodMapping.getObfSignature()); 315 String deobfKey = getMethodKey(methodMapping.getDeobfName(), methodMapping.getObfSignature());
316 if (methodsByDeobf.containsKey(deobfKey)) { 316 if (methodsByDeobf.containsKey(deobfKey)) {
317 throw new Error("Already have mapping for " + deobfName + "." + deobfKey); 317 throw new Error("Already have mapping for " + deobfName + "." + deobfKey);
318 } 318 }
319 boolean deobfWasAdded = methodsByDeobf.put(deobfKey, methodMapping) == null; 319 boolean deobfWasAdded = methodsByDeobf.put(deobfKey, methodMapping) == null;
320 assert (deobfWasAdded); 320 assert (deobfWasAdded);
321 } 321 }
322 this.isDirty = true; 322 this.isDirty = true;
323 assert (methodsByObf.size() >= methodsByDeobf.size()); 323 assert (methodsByObf.size() >= methodsByDeobf.size());
324 } 324 }
325 325
326 public void removeMethodMapping(MethodMapping methodMapping) { 326 public void removeMethodMapping(MethodMapping methodMapping) {
327 boolean obfWasRemoved = methodsByObf.remove(getMethodKey(methodMapping.getObfName(), methodMapping.getObfSignature())) != null; 327 boolean obfWasRemoved = methodsByObf.remove(getMethodKey(methodMapping.getObfName(), methodMapping.getObfSignature())) != null;
328 assert (obfWasRemoved); 328 assert (obfWasRemoved);
329 if (methodMapping.getDeobfName() != null) { 329 if (methodMapping.getDeobfName() != null) {
330 boolean deobfWasRemoved = methodsByDeobf.remove(getMethodKey(methodMapping.getDeobfName(), methodMapping.getObfSignature())) != null; 330 boolean deobfWasRemoved = methodsByDeobf.remove(getMethodKey(methodMapping.getDeobfName(), methodMapping.getObfSignature())) != null;
331 assert (deobfWasRemoved); 331 assert (deobfWasRemoved);
332 } 332 }
333 this.isDirty = true; 333 this.isDirty = true;
334 } 334 }
335 335
336 public MethodMapping getMethodByObf(String obfName, Signature obfSignature) { 336 public MethodMapping getMethodByObf(String obfName, Signature obfSignature) {
337 return methodsByObf.get(getMethodKey(obfName, obfSignature)); 337 return methodsByObf.get(getMethodKey(obfName, obfSignature));
338 } 338 }
339 339
340 public MethodMapping getMethodByDeobf(String deobfName, Signature obfSignature) { 340 public MethodMapping getMethodByDeobf(String deobfName, Signature obfSignature) {
341 return methodsByDeobf.get(getMethodKey(deobfName, obfSignature)); 341 return methodsByDeobf.get(getMethodKey(deobfName, obfSignature));
342 } 342 }
343 343
344 private String getMethodKey(String name, Signature signature) { 344 private String getMethodKey(String name, Signature signature) {
345 if (name == null) { 345 if (name == null) {
346 throw new IllegalArgumentException("name cannot be null!"); 346 throw new IllegalArgumentException("name cannot be null!");
347 } 347 }
348 if (signature == null) { 348 if (signature == null) {
349 throw new IllegalArgumentException("signature cannot be null!"); 349 throw new IllegalArgumentException("signature cannot be null!");
350 } 350 }
351 return name + signature; 351 return name + signature;
352 } 352 }
353 353
354 public void setMethodName(String obfName, Signature obfSignature, String deobfName) { 354 public void setMethodName(String obfName, Signature obfSignature, String deobfName) {
355 MethodMapping methodMapping = methodsByObf.get(getMethodKey(obfName, obfSignature)); 355 MethodMapping methodMapping = methodsByObf.get(getMethodKey(obfName, obfSignature));
356 if (methodMapping == null) { 356 if (methodMapping == null) {
357 methodMapping = createMethodMapping(obfName, obfSignature); 357 methodMapping = createMethodMapping(obfName, obfSignature);
358 } else if (methodMapping.getDeobfName() != null) { 358 } else if (methodMapping.getDeobfName() != null) {
359 boolean wasRemoved = methodsByDeobf.remove(getMethodKey(methodMapping.getDeobfName(), methodMapping.getObfSignature())) != null; 359 boolean wasRemoved = methodsByDeobf.remove(getMethodKey(methodMapping.getDeobfName(), methodMapping.getObfSignature())) != null;
360 assert (wasRemoved); 360 assert (wasRemoved);
361 } 361 }
362 methodMapping.setDeobfName(deobfName); 362 methodMapping.setDeobfName(deobfName);
363 if (deobfName != null) { 363 if (deobfName != null) {
364 boolean wasAdded = methodsByDeobf.put(getMethodKey(deobfName, obfSignature), methodMapping) == null; 364 boolean wasAdded = methodsByDeobf.put(getMethodKey(deobfName, obfSignature), methodMapping) == null;
365 assert (wasAdded); 365 assert (wasAdded);
366 } 366 }
367 this.isDirty = true; 367 this.isDirty = true;
368 } 368 }
369 369
370 public void setMethodObfNameAndSignature(String oldObfName, Signature obfSignature, String newObfName, Signature newObfSignature) { 370 //// ARGUMENTS ////////
371 assert(newObfName != null); 371
372 MethodMapping methodMapping = methodsByObf.remove(getMethodKey(oldObfName, obfSignature)); 372 public void setMethodObfNameAndSignature(String oldObfName, Signature obfSignature, String newObfName, Signature newObfSignature) {
373 assert(methodMapping != null); 373 assert (newObfName != null);
374 methodMapping.setObfName(newObfName); 374 MethodMapping methodMapping = methodsByObf.remove(getMethodKey(oldObfName, obfSignature));
375 methodMapping.setObfSignature(newObfSignature); 375 assert (methodMapping != null);
376 boolean obfWasAdded = methodsByObf.put(getMethodKey(newObfName, newObfSignature), methodMapping) == null; 376 methodMapping.setObfName(newObfName);
377 assert(obfWasAdded); 377 methodMapping.setObfSignature(newObfSignature);
378 this.isDirty = true; 378 boolean obfWasAdded = methodsByObf.put(getMethodKey(newObfName, newObfSignature), methodMapping) == null;
379 } 379 assert (obfWasAdded);
380 380 this.isDirty = true;
381 //// ARGUMENTS //////// 381 }
382 382
383 public void setArgumentName(String obfMethodName, Signature obfMethodSignature, int argumentIndex, String argumentName) { 383 public void setArgumentName(String obfMethodName, Signature obfMethodSignature, int argumentIndex, String argumentName) {
384 assert (argumentName != null); 384 assert (argumentName != null);
385 MethodMapping methodMapping = methodsByObf.get(getMethodKey(obfMethodName, obfMethodSignature)); 385 MethodMapping methodMapping = methodsByObf.get(getMethodKey(obfMethodName, obfMethodSignature));
386 if (methodMapping == null) { 386 if (methodMapping == null) {
387 methodMapping = createMethodMapping(obfMethodName, obfMethodSignature); 387 methodMapping = createMethodMapping(obfMethodName, obfMethodSignature);
388 } 388 }
389 methodMapping.setArgumentName(argumentIndex, argumentName); 389 methodMapping.setArgumentName(argumentIndex, argumentName);
390 this.isDirty = true; 390 this.isDirty = true;
391 } 391 }
392 392
393 public void removeArgumentName(String obfMethodName, Signature obfMethodSignature, int argumentIndex) { 393 public void removeArgumentName(String obfMethodName, Signature obfMethodSignature, int argumentIndex) {
394 methodsByObf.get(getMethodKey(obfMethodName, obfMethodSignature)).removeArgumentName(argumentIndex); 394 methodsByObf.get(getMethodKey(obfMethodName, obfMethodSignature)).removeArgumentName(argumentIndex);
395 this.isDirty = true; 395 this.isDirty = true;
396 } 396 }
397 397
398 private MethodMapping createMethodMapping(String obfName, Signature obfSignature) { 398 private MethodMapping createMethodMapping(String obfName, Signature obfSignature) {
399 MethodMapping methodMapping = new MethodMapping(obfName, obfSignature); 399 MethodMapping methodMapping = new MethodMapping(obfName, obfSignature);
400 boolean wasAdded = methodsByObf.put(getMethodKey(obfName, obfSignature), methodMapping) == null; 400 boolean wasAdded = methodsByObf.put(getMethodKey(obfName, obfSignature), methodMapping) == null;
401 assert (wasAdded); 401 assert (wasAdded);
402 this.isDirty = true; 402 this.isDirty = true;
403 return methodMapping; 403 return methodMapping;
404 } 404 }
405 405
406 @Override 406 @Override
407 public String toString() { 407 public String toString() {
408 StringBuilder buf = new StringBuilder(); 408 StringBuilder buf = new StringBuilder();
409 buf.append(obfFullName); 409 buf.append(obfFullName);
410 buf.append(" <-> "); 410 buf.append(" <-> ");
411 buf.append(deobfName); 411 buf.append(deobfName);
412 buf.append("\n"); 412 buf.append("\n");
413 buf.append("Fields:\n"); 413 buf.append("Fields:\n");
414 for (FieldMapping fieldMapping : fields()) { 414 for (FieldMapping fieldMapping : fields()) {
415 buf.append("\t"); 415 buf.append("\t");
416 buf.append(fieldMapping.getObfName()); 416 buf.append(fieldMapping.getObfName());
417 buf.append(" <-> "); 417 buf.append(" <-> ");
418 buf.append(fieldMapping.getDeobfName()); 418 buf.append(fieldMapping.getDeobfName());
419 buf.append("\n"); 419 buf.append("\n");
420 } 420 }
421 buf.append("Methods:\n"); 421 buf.append("Methods:\n");
422 for (MethodMapping methodMapping : methodsByObf.values()) { 422 for (MethodMapping methodMapping : methodsByObf.values()) {
423 buf.append(methodMapping.toString()); 423 buf.append(methodMapping);
424 buf.append("\n"); 424 buf.append("\n");
425 } 425 }
426 buf.append("Inner Classes:\n"); 426 buf.append("Inner Classes:\n");
427 for (ClassMapping classMapping : innerClassesByObfSimple.values()) { 427 for (ClassMapping classMapping : innerClassesByObfSimple.values()) {
428 buf.append("\t"); 428 buf.append("\t");
429 buf.append(classMapping.getObfSimpleName()); 429 buf.append(classMapping.getObfSimpleName());
430 buf.append(" <-> "); 430 buf.append(" <-> ");
431 buf.append(classMapping.getDeobfName()); 431 buf.append(classMapping.getDeobfName());
432 buf.append("\n"); 432 buf.append("\n");
433 } 433 }
434 return buf.toString(); 434 return buf.toString();
435 } 435 }
436 436
437 @Override 437 @Override
438 public int compareTo(ClassMapping other) { 438 public int compareTo(ClassMapping other) {
439 // sort by a, b, c, ... aa, ab, etc 439 // sort by a, b, c, ... aa, ab, etc
440 if (obfFullName.length() != other.obfFullName.length()) { 440 if (obfFullName.length() != other.obfFullName.length()) {
441 return obfFullName.length() - other.obfFullName.length(); 441 return obfFullName.length() - other.obfFullName.length();
442 } 442 }
443 return obfFullName.compareTo(other.obfFullName); 443 return obfFullName.compareTo(other.obfFullName);
444 } 444 }
445 445
446 public boolean renameObfClass(String oldObfClassName, String newObfClassName) { 446 public boolean renameObfClass(String oldObfClassName, String newObfClassName) {
447 447
448 // rename inner classes 448 // rename inner classes
449 for (ClassMapping innerClassMapping : new ArrayList<>(innerClassesByObfSimple.values())) { 449 for (ClassMapping innerClassMapping : new ArrayList<>(innerClassesByObfSimple.values())) {
450 if (innerClassMapping.renameObfClass(oldObfClassName, newObfClassName)) { 450 if (innerClassMapping.renameObfClass(oldObfClassName, newObfClassName)) {
451 boolean wasRemoved = innerClassesByObfSimple.remove(oldObfClassName) != null; 451 boolean wasRemoved = innerClassesByObfSimple.remove(oldObfClassName) != null;
452 assert (wasRemoved); 452 assert (wasRemoved);
453 boolean wasAdded = innerClassesByObfSimple.put(newObfClassName, innerClassMapping) == null; 453 boolean wasAdded = innerClassesByObfSimple.put(newObfClassName, innerClassMapping) == null;
454 assert (wasAdded); 454 assert (wasAdded);
455 } 455 }
456 } 456 }
457 457
458 // rename field types 458 // rename field types
459 for (FieldMapping fieldMapping : new ArrayList<>(fieldsByObf.values())) { 459 for (FieldMapping fieldMapping : new ArrayList<>(fieldsByObf.values())) {
460 String oldFieldKey = getFieldKey(fieldMapping.getObfName(), fieldMapping.getObfType()); 460 String oldFieldKey = getFieldKey(fieldMapping.getObfName(), fieldMapping.getObfType());
461 if (fieldMapping.renameObfClass(oldObfClassName, newObfClassName)) { 461 if (fieldMapping.renameObfClass(oldObfClassName, newObfClassName)) {
462 boolean wasRemoved = fieldsByObf.remove(oldFieldKey) != null; 462 boolean wasRemoved = fieldsByObf.remove(oldFieldKey) != null;
463 assert (wasRemoved); 463 assert (wasRemoved);
464 boolean wasAdded = fieldsByObf 464 boolean wasAdded = fieldsByObf
465 .put(getFieldKey(fieldMapping.getObfName(), fieldMapping.getObfType()), fieldMapping) == null; 465 .put(getFieldKey(fieldMapping.getObfName(), fieldMapping.getObfType()), fieldMapping) == null;
466 assert (wasAdded); 466 assert (wasAdded);
467 } 467 }
468 } 468 }
469 469
470 // rename method signatures 470 // rename method signatures
471 for (MethodMapping methodMapping : new ArrayList<>(methodsByObf.values())) { 471 for (MethodMapping methodMapping : new ArrayList<>(methodsByObf.values())) {
472 String oldMethodKey = getMethodKey(methodMapping.getObfName(), methodMapping.getObfSignature()); 472 String oldMethodKey = getMethodKey(methodMapping.getObfName(), methodMapping.getObfSignature());
473 if (methodMapping.renameObfClass(oldObfClassName, newObfClassName)) { 473 if (methodMapping.renameObfClass(oldObfClassName, newObfClassName)) {
474 boolean wasRemoved = methodsByObf.remove(oldMethodKey) != null; 474 boolean wasRemoved = methodsByObf.remove(oldMethodKey) != null;
475 assert (wasRemoved); 475 assert (wasRemoved);
476 boolean wasAdded = methodsByObf 476 boolean wasAdded = methodsByObf
477 .put(getMethodKey(methodMapping.getObfName(), methodMapping.getObfSignature()), methodMapping) == null; 477 .put(getMethodKey(methodMapping.getObfName(), methodMapping.getObfSignature()), methodMapping) == null;
478 assert (wasAdded); 478 assert (wasAdded);
479 } 479 }
480 } 480 }
481 481
482 if (obfFullName.equals(oldObfClassName)) { 482 if (obfFullName.equals(oldObfClassName)) {
483 // rename this class 483 // rename this class
484 obfFullName = newObfClassName; 484 obfFullName = newObfClassName;
485 return true; 485 return true;
486 } 486 }
487 this.isDirty = true; 487 this.isDirty = true;
488 return false; 488 return false;
489 } 489 }
490 490
491 public boolean containsArgument(BehaviorEntry obfBehaviorEntry, String name) { 491 public boolean containsArgument(BehaviorEntry obfBehaviorEntry, String name) {
492 MethodMapping methodMapping = methodsByObf.get(getMethodKey(obfBehaviorEntry.getName(), obfBehaviorEntry.getSignature())); 492 MethodMapping methodMapping = methodsByObf.get(getMethodKey(obfBehaviorEntry.getName(), obfBehaviorEntry.getSignature()));
493 return methodMapping != null && methodMapping.containsArgument(name); 493 return methodMapping != null && methodMapping.containsArgument(name);
494 } 494 }
495 495
496 public static boolean isSimpleClassName(String name) { 496 public ClassEntry getObfEntry() {
497 return name.indexOf('/') < 0 && name.indexOf('$') < 0; 497 return new ClassEntry(obfFullName);
498 } 498 }
499 499
500 public ClassEntry getObfEntry() { 500 public boolean isDirty() {
501 return new ClassEntry(obfFullName); 501 return isDirty;
502 } 502 }
503 503
504 public boolean isDirty() 504 public void resetDirty() {
505 { 505 this.isDirty = false;
506 return isDirty; 506 }
507 } 507
508 508 public Mappings.EntryModifier getModifier() {
509 public void resetDirty() 509 return modifier;
510 { 510 }
511 this.isDirty = false; 511
512 } 512 public void setModifier(Mappings.EntryModifier modifier) {
513 513 if (this.modifier != modifier)
514 public void setModifier(Mappings.EntryModifier modifier) 514 this.isDirty = true;
515 { 515 this.modifier = modifier;
516 if (this.modifier != modifier) 516 }
517 this.isDirty = true; 517
518 this.modifier = modifier; 518 public void setFieldModifier(String obfName, Type obfType, Mappings.EntryModifier modifier) {
519 } 519 FieldMapping fieldMapping = fieldsByObf.computeIfAbsent(getFieldKey(obfName, obfType),
520 520 k -> new FieldMapping(obfName, obfType, null, Mappings.EntryModifier.UNCHANGED));
521 public Mappings.EntryModifier getModifier() 521
522 { 522 if (fieldMapping.getModifier() != modifier) {
523 return modifier; 523 fieldMapping.setModifier(modifier);
524 } 524 this.isDirty = true;
525 525 }
526 public void setFieldModifier(String obfName, Type obfType, Mappings.EntryModifier modifier) { 526 }
527 FieldMapping fieldMapping = fieldsByObf.computeIfAbsent(getFieldKey(obfName, obfType), 527
528 k -> new FieldMapping(obfName, obfType, null, Mappings.EntryModifier.UNCHANGED)); 528 public void setMethodModifier(String obfName, Signature sig, Mappings.EntryModifier modifier) {
529 529 MethodMapping methodMapping = methodsByObf.computeIfAbsent(getMethodKey(obfName, sig),
530 if (fieldMapping.getModifier() != modifier) 530 k -> new MethodMapping(obfName, sig, null, Mappings.EntryModifier.UNCHANGED));
531 { 531
532 fieldMapping.setModifier(modifier); 532 if (methodMapping.getModifier() != modifier) {
533 this.isDirty = true; 533 methodMapping.setModifier(modifier);
534 } 534 this.isDirty = true;
535 } 535 }
536 536 }
537 public void setMethodModifier(String obfName, Signature sig, Mappings.EntryModifier modifier) {
538 MethodMapping methodMapping = methodsByObf.computeIfAbsent(getMethodKey(obfName, sig),
539 k -> new MethodMapping(obfName, sig, null, Mappings.EntryModifier.UNCHANGED));
540
541 if (methodMapping.getModifier() != modifier)
542 {
543 methodMapping.setModifier(modifier);
544 this.isDirty = true;
545 }
546 }
547} 537}