summaryrefslogtreecommitdiff
path: root/src/main/java/cuchaz/enigma/mapping/ClassMapping.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/cuchaz/enigma/mapping/ClassMapping.java')
-rw-r--r--src/main/java/cuchaz/enigma/mapping/ClassMapping.java627
1 files changed, 0 insertions, 627 deletions
diff --git a/src/main/java/cuchaz/enigma/mapping/ClassMapping.java b/src/main/java/cuchaz/enigma/mapping/ClassMapping.java
deleted file mode 100644
index 9c193ef..0000000
--- a/src/main/java/cuchaz/enigma/mapping/ClassMapping.java
+++ /dev/null
@@ -1,627 +0,0 @@
1/*******************************************************************************
2 * Copyright (c) 2015 Jeff Martin.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the GNU Lesser General Public
5 * License v3.0 which accompanies this distribution, and is available at
6 * http://www.gnu.org/licenses/lgpl.html
7 * <p>
8 * Contributors:
9 * Jeff Martin - initial API and implementation
10 ******************************************************************************/
11
12package cuchaz.enigma.mapping;
13
14import com.google.common.collect.Maps;
15import cuchaz.enigma.mapping.entry.ClassEntry;
16import cuchaz.enigma.mapping.entry.FieldEntry;
17import cuchaz.enigma.mapping.entry.MethodEntry;
18import cuchaz.enigma.throwables.MappingConflict;
19
20import java.util.ArrayList;
21import java.util.Map;
22
23// FIXME: Enigma doesn't support inner classes of inner class????!
24public class ClassMapping implements Comparable<ClassMapping> {
25
26 private String obfFullName;
27 private String obfSimpleName;
28 private String deobfName;
29 private String deobfFullName;
30 private String previousDeobfName;
31 private Map<String, ClassMapping> innerClassesByObfSimple;
32 private Map<String, ClassMapping> innerClassesByObfFull;
33 private Map<String, ClassMapping> innerClassesByDeobf;
34 private Map<String, FieldMapping> fieldsByObf;
35 private Map<String, FieldMapping> fieldsByDeobf;
36 private Map<String, MethodMapping> methodsByObf;
37 private Map<String, MethodMapping> methodsByDeobf;
38 private boolean isDirty;
39 private Mappings.EntryModifier modifier;
40
41 public ClassMapping(String obfFullName) {
42 this(obfFullName, null, Mappings.EntryModifier.UNCHANGED);
43 }
44
45 public ClassMapping(String obfFullName, String deobfName) {
46 this(obfFullName, deobfName, Mappings.EntryModifier.UNCHANGED);
47 }
48
49 public ClassMapping(String obfFullName, String deobfName, Mappings.EntryModifier modifier) {
50 this.obfFullName = obfFullName;
51 ClassEntry classEntry = new ClassEntry(obfFullName);
52 obfSimpleName = classEntry.isInnerClass() ? classEntry.getInnermostClassName() : classEntry.getSimpleName();
53 previousDeobfName = null;
54 this.deobfName = NameValidator.validateClassName(deobfName, false);
55 innerClassesByObfSimple = Maps.newHashMap();
56 innerClassesByObfFull = Maps.newHashMap();
57 innerClassesByDeobf = Maps.newHashMap();
58 fieldsByObf = Maps.newHashMap();
59 fieldsByDeobf = Maps.newHashMap();
60 methodsByObf = Maps.newHashMap();
61 methodsByDeobf = Maps.newHashMap();
62 isDirty = true;
63 this.modifier = modifier;
64 }
65
66 public static boolean isSimpleClassName(String name) {
67 return name.indexOf('/') < 0 && name.indexOf('$') < 0;
68 }
69
70 public String getObfFullName() {
71 return obfFullName;
72 }
73
74 public String getObfSimpleName() {
75 return obfSimpleName;
76 }
77
78 public String getPreviousDeobfName() {
79 return previousDeobfName;
80 }
81
82 public String getDeobfName() {
83 return deobfName;
84 }
85
86 public String getTranslatedName(TranslationDirection direction) {
87 return direction.choose(deobfName, obfFullName);
88 }
89
90 //// INNER CLASSES ////////
91
92 public void setDeobfName(String val) {
93 previousDeobfName = deobfName;
94 deobfName = NameValidator.validateClassName(val, false);
95 this.isDirty = true;
96 }
97
98 public Iterable<ClassMapping> innerClasses() {
99 assert (innerClassesByObfSimple.size() >= innerClassesByDeobf.size());
100 return innerClassesByObfSimple.values();
101 }
102
103 public void addInnerClassMapping(ClassMapping classMapping) throws MappingConflict {
104 // FIXME: dirty hack, that can get into issues, but it's a temp fix!
105 if (this.innerClassesByObfFull.containsKey(classMapping.getObfSimpleName())) {
106 throw new MappingConflict("classes", classMapping.getObfSimpleName(), this.innerClassesByObfSimple.get(classMapping.getObfSimpleName()).getObfSimpleName());
107 }
108 innerClassesByObfFull.put(classMapping.getObfFullName(), classMapping);
109 innerClassesByObfSimple.put(classMapping.getObfSimpleName(), classMapping);
110
111 if (classMapping.getDeobfName() != null) {
112 if (this.innerClassesByDeobf.containsKey(classMapping.getDeobfName())) {
113 throw new MappingConflict("classes", classMapping.getDeobfName(), this.innerClassesByDeobf.get(classMapping.getDeobfName()).getDeobfName());
114 }
115 innerClassesByDeobf.put(classMapping.getDeobfName(), classMapping);
116 }
117 this.isDirty = true;
118 }
119
120 public void removeInnerClassMapping(ClassMapping classMapping) {
121 innerClassesByObfFull.remove(classMapping.getObfFullName());
122 boolean obfWasRemoved = innerClassesByObfSimple.remove(classMapping.getObfSimpleName()) != null;
123 assert (obfWasRemoved);
124 if (classMapping.getDeobfName() != null) {
125 boolean deobfWasRemoved = innerClassesByDeobf.remove(classMapping.getDeobfName()) != null;
126 assert (deobfWasRemoved);
127 }
128 this.isDirty = true;
129 }
130
131 public ClassMapping getOrCreateInnerClass(ClassEntry obfInnerClass) {
132 ClassMapping classMapping = innerClassesByObfSimple.get(obfInnerClass.getInnermostClassName());
133 if (classMapping == null) {
134 classMapping = new ClassMapping(obfInnerClass.getName());
135 innerClassesByObfFull.put(classMapping.getObfFullName(), classMapping);
136 boolean wasAdded = innerClassesByObfSimple.put(classMapping.getObfSimpleName(), classMapping) == null;
137 assert (wasAdded);
138 this.isDirty = true;
139 }
140 return classMapping;
141 }
142
143 public ClassMapping getInnerClassByObfSimple(String obfSimpleName) {
144 assert (isSimpleClassName(obfSimpleName));
145 return innerClassesByObfSimple.get(obfSimpleName);
146 }
147
148 public ClassMapping getInnerClassByDeobf(String deobfName) {
149 assert (isSimpleClassName(deobfName));
150 return innerClassesByDeobf.get(deobfName);
151 }
152
153 public ClassMapping getInnerClassByDeobfThenObfSimple(String name) {
154 ClassMapping classMapping = getInnerClassByDeobf(name);
155 if (classMapping == null) {
156 classMapping = getInnerClassByObfSimple(name);
157 }
158 return classMapping;
159 }
160
161 public String getDeobfInnerClassName(String obfSimpleName) {
162 assert (isSimpleClassName(obfSimpleName));
163 ClassMapping classMapping = innerClassesByObfSimple.get(obfSimpleName);
164 if (classMapping != null) {
165 return classMapping.getDeobfName();
166 }
167 return null;
168 }
169
170 public void setInnerClassName(ClassEntry obfInnerClass, String deobfName) {
171 ClassMapping classMapping = getOrCreateInnerClass(obfInnerClass);
172 if (classMapping.getDeobfName() != null) {
173 boolean wasRemoved = innerClassesByDeobf.remove(classMapping.getDeobfName()) != null;
174 assert (wasRemoved);
175 }
176 classMapping.setDeobfName(deobfName);
177 if (deobfName != null) {
178 assert (isSimpleClassName(deobfName));
179 boolean wasAdded = innerClassesByDeobf.put(deobfName, classMapping) == null;
180 assert (wasAdded);
181 }
182 this.isDirty = true;
183 }
184
185 public boolean hasInnerClassByObfSimple(String obfSimpleName) {
186 return innerClassesByObfSimple.containsKey(obfSimpleName);
187 }
188
189 //// FIELDS ////////
190
191 public boolean hasInnerClassByDeobf(String deobfName) {
192 return innerClassesByDeobf.containsKey(deobfName);
193 }
194
195 public Iterable<FieldMapping> fields() {
196 assert (fieldsByObf.size() == fieldsByDeobf.size());
197 return fieldsByObf.values();
198 }
199
200 public boolean containsObfField(String obfName, TypeDescriptor obfDesc) {
201 return fieldsByObf.containsKey(getFieldKey(obfName, obfDesc));
202 }
203
204 public boolean containsDeobfField(String deobfName, TypeDescriptor deobfDesc) {
205 return fieldsByDeobf.containsKey(getFieldKey(deobfName, deobfDesc));
206 }
207
208 public void addFieldMapping(FieldMapping fieldMapping) {
209 String obfKey = getFieldKey(fieldMapping.getObfName(), fieldMapping.getObfDesc());
210 if (fieldsByObf.containsKey(obfKey)) {
211 throw new Error("Already have mapping for " + obfFullName + "." + obfKey);
212 }
213 if (fieldMapping.getDeobfName() != null) {
214 String deobfKey = getFieldKey(fieldMapping.getDeobfName(), fieldMapping.getObfDesc());
215 if (fieldsByDeobf.containsKey(deobfKey)) {
216 throw new Error("Already have mapping for " + deobfName + "." + deobfKey);
217 }
218 boolean deobfWasAdded = fieldsByDeobf.put(deobfKey, fieldMapping) == null;
219 assert (deobfWasAdded);
220 }
221 boolean obfWasAdded = fieldsByObf.put(obfKey, fieldMapping) == null;
222 assert (obfWasAdded);
223 this.isDirty = true;
224 }
225
226 public void removeFieldMapping(FieldMapping fieldMapping) {
227 boolean obfWasRemoved = fieldsByObf.remove(getFieldKey(fieldMapping.getObfName(), fieldMapping.getObfDesc())) != null;
228 assert (obfWasRemoved);
229 if (fieldMapping.getDeobfName() != null) {
230 boolean deobfWasRemoved = fieldsByDeobf.remove(getFieldKey(fieldMapping.getDeobfName(), fieldMapping.getObfDesc())) != null;
231 assert (deobfWasRemoved);
232 }
233 this.isDirty = true;
234 }
235
236 public FieldMapping getFieldByObf(String obfName, TypeDescriptor obfDesc) {
237 return fieldsByObf.get(getFieldKey(obfName, obfDesc));
238 }
239
240 public FieldMapping getFieldByObf(FieldEntry field) {
241 return getFieldByObf(field.getName(), field.getDesc());
242 }
243
244 public FieldMapping getFieldByDeobf(String deobfName, TypeDescriptor obfDesc) {
245 return fieldsByDeobf.get(getFieldKey(deobfName, obfDesc));
246 }
247
248 public String getObfFieldName(String deobfName, TypeDescriptor obfDesc) {
249 FieldMapping fieldMapping = fieldsByDeobf.get(getFieldKey(deobfName, obfDesc));
250 if (fieldMapping != null) {
251 return fieldMapping.getObfName();
252 }
253 return null;
254 }
255
256 public String getDeobfFieldName(String obfName, TypeDescriptor obfDesc) {
257 FieldMapping fieldMapping = fieldsByObf.get(getFieldKey(obfName, obfDesc));
258 if (fieldMapping != null) {
259 return fieldMapping.getDeobfName();
260 }
261 return null;
262 }
263
264 private String getFieldKey(String name, TypeDescriptor desc) {
265 if (name == null) {
266 throw new IllegalArgumentException("name cannot be null!");
267 }
268 if (desc == null) {
269 throw new IllegalArgumentException("desc cannot be null!");
270 }
271 return name + ":" + desc;
272 }
273
274 public void setFieldName(String obfName, TypeDescriptor obfDesc, String deobfName) {
275 assert (deobfName != null);
276 FieldMapping fieldMapping = fieldsByObf.get(getFieldKey(obfName, obfDesc));
277 if (fieldMapping == null) {
278 fieldMapping = new FieldMapping(obfName, obfDesc, deobfName, Mappings.EntryModifier.UNCHANGED);
279 boolean obfWasAdded = fieldsByObf.put(getFieldKey(obfName, obfDesc), fieldMapping) == null;
280 assert (obfWasAdded);
281 } else {
282 boolean wasRemoved = fieldsByDeobf.remove(getFieldKey(fieldMapping.getDeobfName(), obfDesc)) != null;
283 assert (wasRemoved);
284 }
285 fieldMapping.setDeobfName(deobfName);
286 if (deobfName != null) {
287 boolean wasAdded = fieldsByDeobf.put(getFieldKey(deobfName, obfDesc), fieldMapping) == null;
288 assert (wasAdded);
289 }
290 this.isDirty = true;
291 }
292
293 //// METHODS ////////
294
295 public void setFieldObfNameAndType(String oldObfName, TypeDescriptor obfDesc, String newObfName, TypeDescriptor newObfDesc) {
296 assert (newObfName != null);
297 FieldMapping fieldMapping = fieldsByObf.remove(getFieldKey(oldObfName, obfDesc));
298 assert (fieldMapping != null);
299 fieldMapping.setObfName(newObfName);
300 fieldMapping.setObfDesc(newObfDesc);
301 boolean obfWasAdded = fieldsByObf.put(getFieldKey(newObfName, newObfDesc), fieldMapping) == null;
302 assert (obfWasAdded);
303 this.isDirty = true;
304 }
305
306 public Iterable<MethodMapping> methods() {
307 assert (methodsByObf.size() >= methodsByDeobf.size());
308 return methodsByObf.values();
309 }
310
311 public boolean containsObfMethod(String obfName, MethodDescriptor obfDescriptor) {
312 return methodsByObf.containsKey(getMethodKey(obfName, obfDescriptor));
313 }
314
315 public boolean containsDeobfMethod(String deobfName, MethodDescriptor obfDescriptor) {
316 return methodsByDeobf.containsKey(getMethodKey(deobfName, obfDescriptor));
317 }
318
319 public void addMethodMapping(MethodMapping methodMapping) {
320 String obfKey = getMethodKey(methodMapping.getObfName(), methodMapping.getObfDesc());
321 if (methodsByObf.containsKey(obfKey)) {
322 throw new Error("Already have mapping for " + obfFullName + "." + obfKey);
323 }
324 boolean wasAdded = methodsByObf.put(obfKey, methodMapping) == null;
325 assert (wasAdded);
326 if (!methodMapping.isObfuscated()) {
327 String deobfKey = getMethodKey(methodMapping.getDeobfName(), methodMapping.getObfDesc());
328 if (methodsByDeobf.containsKey(deobfKey)) {
329 throw new Error("Already have mapping for " + deobfName + "." + deobfKey);
330 }
331 boolean deobfWasAdded = methodsByDeobf.put(deobfKey, methodMapping) == null;
332 assert (deobfWasAdded);
333 }
334 this.isDirty = true;
335 assert (methodsByObf.size() >= methodsByDeobf.size());
336 }
337
338 public void removeMethodMapping(MethodMapping methodMapping) {
339 boolean obfWasRemoved = methodsByObf.remove(getMethodKey(methodMapping.getObfName(), methodMapping.getObfDesc())) != null;
340 assert (obfWasRemoved);
341 if (!methodMapping.isObfuscated()) {
342 boolean deobfWasRemoved = methodsByDeobf.remove(getMethodKey(methodMapping.getDeobfName(), methodMapping.getObfDesc())) != null;
343 assert (deobfWasRemoved);
344 }
345 this.isDirty = true;
346 }
347
348 public MethodMapping getMethodByObf(String obfName, MethodDescriptor obfDescriptor) {
349 return methodsByObf.get(getMethodKey(obfName, obfDescriptor));
350 }
351
352 public MethodMapping getMethodByObf(MethodEntry method) {
353 return getMethodByObf(method.getName(), method.getDesc());
354 }
355
356 public MethodMapping getMethodByDeobf(String deobfName, MethodDescriptor obfDescriptor) {
357 return methodsByDeobf.get(getMethodKey(deobfName, obfDescriptor));
358 }
359
360 private String getMethodKey(String name, MethodDescriptor descriptor) {
361 if (name == null) {
362 throw new IllegalArgumentException("name cannot be null!");
363 }
364 if (descriptor == null) {
365 throw new IllegalArgumentException("descriptor cannot be null!");
366 }
367 return name + descriptor;
368 }
369
370 public void setMethodName(String obfName, MethodDescriptor obfDescriptor, String deobfName) {
371 MethodMapping methodMapping = methodsByObf.get(getMethodKey(obfName, obfDescriptor));
372 if (methodMapping == null) {
373 methodMapping = createMethodMapping(obfName, obfDescriptor);
374 } else if (!methodMapping.isObfuscated()) {
375 boolean wasRemoved = methodsByDeobf.remove(getMethodKey(methodMapping.getDeobfName(), methodMapping.getObfDesc())) != null;
376 assert (wasRemoved);
377 }
378 methodMapping.setDeobfName(deobfName);
379 if (deobfName != null) {
380 boolean wasAdded = methodsByDeobf.put(getMethodKey(deobfName, obfDescriptor), methodMapping) == null;
381 assert (wasAdded);
382 }
383 this.isDirty = true;
384 }
385
386 //// ARGUMENTS ////////
387
388 public void setMethodObfNameAndSignature(String oldObfName, MethodDescriptor obfDescriptor, String newObfName, MethodDescriptor newObfDescriptor) {
389 assert (newObfName != null);
390 MethodMapping methodMapping = methodsByObf.remove(getMethodKey(oldObfName, obfDescriptor));
391 assert (methodMapping != null);
392 methodMapping.setObfName(newObfName);
393 methodMapping.setObfDescriptor(newObfDescriptor);
394 boolean obfWasAdded = methodsByObf.put(getMethodKey(newObfName, newObfDescriptor), methodMapping) == null;
395 assert (obfWasAdded);
396 this.isDirty = true;
397 }
398
399 public void setArgumentName(String obfMethodName, MethodDescriptor obfMethodDescriptor, int argumentIndex, String argumentName) {
400 assert (argumentName != null);
401 MethodMapping methodMapping = methodsByObf.get(getMethodKey(obfMethodName, obfMethodDescriptor));
402 if (methodMapping == null) {
403 methodMapping = createMethodMapping(obfMethodName, obfMethodDescriptor);
404 }
405 methodMapping.setLocalVariableName(argumentIndex, argumentName);
406 this.isDirty = true;
407 }
408
409 public void removeArgumentName(String obfMethodName, MethodDescriptor obfMethodDescriptor, int argumentIndex) {
410 methodsByObf.get(getMethodKey(obfMethodName, obfMethodDescriptor)).removeLocalVariableName(argumentIndex);
411 this.isDirty = true;
412 }
413
414 private MethodMapping createMethodMapping(String obfName, MethodDescriptor obfDescriptor) {
415 MethodMapping methodMapping = new MethodMapping(obfName, obfDescriptor);
416 boolean wasAdded = methodsByObf.put(getMethodKey(obfName, obfDescriptor), methodMapping) == null;
417 assert (wasAdded);
418 this.isDirty = true;
419 return methodMapping;
420 }
421
422 @Override
423 public String toString() {
424 StringBuilder buf = new StringBuilder();
425 buf.append(obfFullName);
426 buf.append(" <-> ");
427 buf.append(deobfName);
428 buf.append("\n");
429 buf.append("Fields:\n");
430 for (FieldMapping fieldMapping : fields()) {
431 buf.append("\t");
432 buf.append(fieldMapping.getObfName());
433 buf.append(" <-> ");
434 buf.append(fieldMapping.getDeobfName());
435 buf.append("\n");
436 }
437 buf.append("Methods:\n");
438 for (MethodMapping methodMapping : methodsByObf.values()) {
439 buf.append(methodMapping);
440 buf.append("\n");
441 }
442 buf.append("Inner Classes:\n");
443 for (ClassMapping classMapping : innerClassesByObfSimple.values()) {
444 buf.append("\t");
445 buf.append(classMapping.getObfSimpleName());
446 buf.append(" <-> ");
447 buf.append(classMapping.getDeobfName());
448 buf.append("\n");
449 }
450 return buf.toString();
451 }
452
453 @Override
454 public int compareTo(ClassMapping other) {
455 // sort by a, b, c, ... aa, ab, etc
456 if (obfFullName.length() != other.obfFullName.length()) {
457 return obfFullName.length() - other.obfFullName.length();
458 }
459 return obfFullName.compareTo(other.obfFullName);
460 }
461
462 public boolean renameObfClass(String oldObfClassName, String newObfClassName) {
463
464 // rename inner classes
465 for (ClassMapping innerClassMapping : new ArrayList<>(innerClassesByObfSimple.values())) {
466 if (innerClassMapping.renameObfClass(oldObfClassName, newObfClassName)) {
467 boolean wasRemoved = innerClassesByObfSimple.remove(oldObfClassName) != null;
468 assert (wasRemoved);
469 boolean wasAdded = innerClassesByObfSimple.put(newObfClassName, innerClassMapping) == null;
470 assert (wasAdded);
471 }
472 }
473
474 // rename field types
475 for (FieldMapping fieldMapping : new ArrayList<>(fieldsByObf.values())) {
476 String oldFieldKey = getFieldKey(fieldMapping.getObfName(), fieldMapping.getObfDesc());
477 if (fieldMapping.renameObfClass(oldObfClassName, newObfClassName)) {
478 boolean wasRemoved = fieldsByObf.remove(oldFieldKey) != null;
479 assert (wasRemoved);
480 boolean wasAdded = fieldsByObf
481 .put(getFieldKey(fieldMapping.getObfName(), fieldMapping.getObfDesc()), fieldMapping) == null;
482 assert (wasAdded);
483 }
484 }
485
486 // rename method signatures
487 for (MethodMapping methodMapping : new ArrayList<>(methodsByObf.values())) {
488 String oldMethodKey = getMethodKey(methodMapping.getObfName(), methodMapping.getObfDesc());
489 if (methodMapping.renameObfClass(oldObfClassName, newObfClassName)) {
490 boolean wasRemoved = methodsByObf.remove(oldMethodKey) != null;
491 assert (wasRemoved);
492 boolean wasAdded = methodsByObf
493 .put(getMethodKey(methodMapping.getObfName(), methodMapping.getObfDesc()), methodMapping) == null;
494 assert (wasAdded);
495 }
496 }
497
498 if (obfFullName.equals(oldObfClassName)) {
499 // rename this class
500 obfFullName = newObfClassName;
501 return true;
502 }
503 this.isDirty = true;
504 return false;
505 }
506
507 public boolean containsArgument(MethodEntry obfMethodEntry, String name) {
508 MethodMapping methodMapping = methodsByObf.get(getMethodKey(obfMethodEntry.getName(), obfMethodEntry.getDesc()));
509 return methodMapping != null && methodMapping.containsLocalVariable(name);
510 }
511
512 public ClassEntry getObfEntry() {
513 return new ClassEntry(obfFullName);
514 }
515
516 public ClassEntry getDeObfEntry() {
517 return deobfFullName != null ? new ClassEntry(deobfFullName) : null;
518 }
519
520 public boolean isObfuscated() {
521 return this.deobfName == null || this.deobfName.equals(this.obfFullName);
522 }
523
524 public String getSaveName() {
525 return this.isObfuscated() ? this.obfFullName : this.deobfName;
526 }
527
528 public boolean isDirty() {
529 return isDirty || areInnersDirty();
530 }
531
532 private boolean areInnersDirty(){
533 for (ClassMapping c : this.innerClasses()){
534 if (c.isDirty()){
535 return true;
536 }
537 }
538 return false;
539 }
540
541 public void resetDirty() {
542 this.isDirty = false;
543 }
544
545 public void markDirty() {
546 this.isDirty = true;
547 }
548
549 public Mappings.EntryModifier getModifier() {
550 return modifier;
551 }
552
553 public void setModifier(Mappings.EntryModifier modifier) {
554 if (this.modifier != modifier)
555 this.isDirty = true;
556 this.modifier = modifier;
557 }
558
559 public void setFieldModifier(String obfName, TypeDescriptor obfDesc, Mappings.EntryModifier modifier) {
560 FieldMapping fieldMapping = fieldsByObf.computeIfAbsent(getFieldKey(obfName, obfDesc),
561 k -> new FieldMapping(obfName, obfDesc, null, Mappings.EntryModifier.UNCHANGED));
562
563 if (fieldMapping.getModifier() != modifier) {
564 fieldMapping.setModifier(modifier);
565 this.isDirty = true;
566 }
567 }
568
569 public void setMethodModifier(String obfName, MethodDescriptor sig, Mappings.EntryModifier modifier) {
570 MethodMapping methodMapping = methodsByObf.computeIfAbsent(getMethodKey(obfName, sig),
571 k -> new MethodMapping(obfName, sig, null, Mappings.EntryModifier.UNCHANGED));
572
573 if (methodMapping.getModifier() != modifier) {
574 methodMapping.setModifier(modifier);
575 this.isDirty = true;
576 }
577 }
578
579 // Used for tiny parsing to keep track of deobfuscate inner classes
580 public ClassMapping setDeobfInner(String deobName) {
581 this.deobfFullName = deobName;
582 return this;
583 }
584
585 public ClassMapping copy() {
586 ClassMapping copied = new ClassMapping(this.obfFullName);
587 copied.obfSimpleName= this.obfSimpleName;
588 copied.modifier = this.modifier;
589 copied.deobfFullName = this.deobfFullName;
590 copied.deobfName = this.deobfName;
591 copied.innerClassesByDeobf = this.innerClassesByDeobf;
592 copied.innerClassesByObfFull = this.innerClassesByObfFull;
593 copied.innerClassesByObfSimple = this.innerClassesByObfSimple;
594 copied.fieldsByObf = this.fieldsByObf;
595 copied.fieldsByDeobf = this.fieldsByDeobf;
596 copied.methodsByObf = this.methodsByObf;
597 copied.methodsByDeobf = this.methodsByDeobf;
598 return copied;
599 }
600
601 @Override
602 public int hashCode() {
603 return this.obfFullName.hashCode();
604 }
605
606 @Override
607 public boolean equals(Object obj) {
608 return obj instanceof ClassMapping && ((ClassMapping) obj).obfFullName.equals(this.obfFullName);
609 }
610
611 public boolean isEmpty() {
612 if (fieldsByDeobf.isEmpty() && methodsByDeobf.isEmpty() && deobfFullName == null && deobfName == null
613 && innerClassesByObfSimple.values().stream().allMatch(ClassMapping::isEmpty)) {
614
615 // check args
616 for (MethodMapping mapping : methodsByObf.values()) {
617 if (mapping.arguments().iterator().hasNext()) {
618 return false;
619 }
620 }
621
622 return true;
623 }
624
625 return false;
626 }
627}