diff options
Diffstat (limited to 'src/cuchaz/enigma/convert/MappingsConverter.java')
| -rw-r--r-- | src/cuchaz/enigma/convert/MappingsConverter.java | 125 |
1 files changed, 76 insertions, 49 deletions
diff --git a/src/cuchaz/enigma/convert/MappingsConverter.java b/src/cuchaz/enigma/convert/MappingsConverter.java index 59f3b5b..ddd3a53 100644 --- a/src/cuchaz/enigma/convert/MappingsConverter.java +++ b/src/cuchaz/enigma/convert/MappingsConverter.java | |||
| @@ -183,7 +183,7 @@ public class MappingsConverter { | |||
| 183 | return newMappings; | 183 | return newMappings; |
| 184 | } | 184 | } |
| 185 | 185 | ||
| 186 | private static ClassMapping migrateClassMapping(ClassEntry newObfClass, ClassMapping mapping, final ClassMatches matches, boolean useSimpleName) { | 186 | private static ClassMapping migrateClassMapping(ClassEntry newObfClass, ClassMapping oldClassMapping, final ClassMatches matches, boolean useSimpleName) { |
| 187 | 187 | ||
| 188 | ClassNameReplacer replacer = new ClassNameReplacer() { | 188 | ClassNameReplacer replacer = new ClassNameReplacer() { |
| 189 | @Override | 189 | @Override |
| @@ -196,30 +196,28 @@ public class MappingsConverter { | |||
| 196 | } | 196 | } |
| 197 | }; | 197 | }; |
| 198 | 198 | ||
| 199 | ClassMapping newMapping; | 199 | ClassMapping newClassMapping; |
| 200 | String deobfName = mapping.getDeobfName(); | 200 | String deobfName = oldClassMapping.getDeobfName(); |
| 201 | if (deobfName != null) { | 201 | if (deobfName != null) { |
| 202 | if (useSimpleName) { | 202 | if (useSimpleName) { |
| 203 | deobfName = new ClassEntry(deobfName).getSimpleName(); | 203 | deobfName = new ClassEntry(deobfName).getSimpleName(); |
| 204 | } | 204 | } |
| 205 | newMapping = new ClassMapping(newObfClass.getName(), deobfName); | 205 | newClassMapping = new ClassMapping(newObfClass.getName(), deobfName); |
| 206 | } else { | 206 | } else { |
| 207 | newMapping = new ClassMapping(newObfClass.getName()); | 207 | newClassMapping = new ClassMapping(newObfClass.getName()); |
| 208 | } | 208 | } |
| 209 | 209 | ||
| 210 | // copy fields | 210 | // copy fields |
| 211 | for (FieldMapping fieldMapping : mapping.fields()) { | 211 | for (FieldMapping fieldMapping : oldClassMapping.fields()) { |
| 212 | // TODO: map field obf names too... | 212 | newClassMapping.addFieldMapping(new FieldMapping(fieldMapping, replacer)); |
| 213 | newMapping.addFieldMapping(new FieldMapping(fieldMapping, replacer)); | ||
| 214 | } | 213 | } |
| 215 | 214 | ||
| 216 | // copy methods | 215 | // copy methods |
| 217 | for (MethodMapping methodMapping : mapping.methods()) { | 216 | for (MethodMapping methodMapping : oldClassMapping.methods()) { |
| 218 | // TODO: map method obf names too... | 217 | newClassMapping.addMethodMapping(new MethodMapping(methodMapping, replacer)); |
| 219 | newMapping.addMethodMapping(new MethodMapping(methodMapping, replacer)); | ||
| 220 | } | 218 | } |
| 221 | 219 | ||
| 222 | return newMapping; | 220 | return newClassMapping; |
| 223 | } | 221 | } |
| 224 | 222 | ||
| 225 | public static void convertMappings(Mappings mappings, BiMap<ClassEntry,ClassEntry> changes) { | 223 | public static void convertMappings(Mappings mappings, BiMap<ClassEntry,ClassEntry> changes) { |
| @@ -262,8 +260,9 @@ public class MappingsConverter { | |||
| 262 | Collection<T> getObfEntries(JarIndex jarIndex); | 260 | Collection<T> getObfEntries(JarIndex jarIndex); |
| 263 | Collection<? extends MemberMapping<T>> getMappings(ClassMapping destClassMapping); | 261 | Collection<? extends MemberMapping<T>> getMappings(ClassMapping destClassMapping); |
| 264 | Set<T> filterEntries(Collection<T> obfEntries, T obfSourceEntry, ClassMatches classMatches); | 262 | Set<T> filterEntries(Collection<T> obfEntries, T obfSourceEntry, ClassMatches classMatches); |
| 265 | void setMemberObfName(ClassMapping classMapping, MemberMapping<T> memberMapping, String newObfName); | 263 | void setUpdateObfMember(ClassMapping classMapping, MemberMapping<T> memberMapping, T newEntry); |
| 266 | boolean hasObfMember(ClassMapping classMapping, T obfEntry); | 264 | boolean hasObfMember(ClassMapping classMapping, T obfEntry); |
| 265 | void removeMemberByObf(ClassMapping classMapping, T obfEntry); | ||
| 267 | } | 266 | } |
| 268 | 267 | ||
| 269 | public static Doer<FieldEntry> getFieldDoer() { | 268 | public static Doer<FieldEntry> getFieldDoer() { |
| @@ -297,15 +296,20 @@ public class MappingsConverter { | |||
| 297 | } | 296 | } |
| 298 | 297 | ||
| 299 | @Override | 298 | @Override |
| 300 | public void setMemberObfName(ClassMapping classMapping, MemberMapping<FieldEntry> memberMapping, String newObfName) { | 299 | public void setUpdateObfMember(ClassMapping classMapping, MemberMapping<FieldEntry> memberMapping, FieldEntry newField) { |
| 301 | FieldMapping fieldMapping = (FieldMapping)memberMapping; | 300 | FieldMapping fieldMapping = (FieldMapping)memberMapping; |
| 302 | classMapping.setFieldObfName(fieldMapping.getObfName(), fieldMapping.getObfType(), newObfName); | 301 | classMapping.setFieldObfNameAndType(fieldMapping.getObfName(), fieldMapping.getObfType(), newField.getName(), newField.getType()); |
| 303 | } | 302 | } |
| 304 | 303 | ||
| 305 | @Override | 304 | @Override |
| 306 | public boolean hasObfMember(ClassMapping classMapping, FieldEntry obfField) { | 305 | public boolean hasObfMember(ClassMapping classMapping, FieldEntry obfField) { |
| 307 | return classMapping.getFieldByObf(obfField.getName(), obfField.getType()) != null; | 306 | return classMapping.getFieldByObf(obfField.getName(), obfField.getType()) != null; |
| 308 | } | 307 | } |
| 308 | |||
| 309 | @Override | ||
| 310 | public void removeMemberByObf(ClassMapping classMapping, FieldEntry obfField) { | ||
| 311 | classMapping.removeFieldMapping(classMapping.getFieldByObf(obfField.getName(), obfField.getType())); | ||
| 312 | } | ||
| 309 | }; | 313 | }; |
| 310 | } | 314 | } |
| 311 | 315 | ||
| @@ -344,15 +348,20 @@ public class MappingsConverter { | |||
| 344 | } | 348 | } |
| 345 | 349 | ||
| 346 | @Override | 350 | @Override |
| 347 | public void setMemberObfName(ClassMapping classMapping, MemberMapping<BehaviorEntry> memberMapping, String newObfName) { | 351 | public void setUpdateObfMember(ClassMapping classMapping, MemberMapping<BehaviorEntry> memberMapping, BehaviorEntry newBehavior) { |
| 348 | MethodMapping methodMapping = (MethodMapping)memberMapping; | 352 | MethodMapping methodMapping = (MethodMapping)memberMapping; |
| 349 | classMapping.setMethodObfName(methodMapping.getObfName(), methodMapping.getObfSignature(), newObfName); | 353 | classMapping.setMethodObfNameAndSignature(methodMapping.getObfName(), methodMapping.getObfSignature(), newBehavior.getName(), newBehavior.getSignature()); |
| 350 | } | 354 | } |
| 351 | 355 | ||
| 352 | @Override | 356 | @Override |
| 353 | public boolean hasObfMember(ClassMapping classMapping, BehaviorEntry obfBehavior) { | 357 | public boolean hasObfMember(ClassMapping classMapping, BehaviorEntry obfBehavior) { |
| 354 | return classMapping.getMethodByObf(obfBehavior.getName(), obfBehavior.getSignature()) != null; | 358 | return classMapping.getMethodByObf(obfBehavior.getName(), obfBehavior.getSignature()) != null; |
| 355 | } | 359 | } |
| 360 | |||
| 361 | @Override | ||
| 362 | public void removeMemberByObf(ClassMapping classMapping, BehaviorEntry obfBehavior) { | ||
| 363 | classMapping.removeMethodMapping(classMapping.getMethodByObf(obfBehavior.getName(), obfBehavior.getSignature())); | ||
| 364 | } | ||
| 356 | }; | 365 | }; |
| 357 | } | 366 | } |
| 358 | 367 | ||
| @@ -477,56 +486,74 @@ public class MappingsConverter { | |||
| 477 | }); | 486 | }); |
| 478 | } | 487 | } |
| 479 | 488 | ||
| 480 | public static <T extends Entry> void applyMemberMatches(Mappings mappings, MemberMatches<T> memberMatches, Doer<T> doer) { | 489 | public static <T extends Entry> void applyMemberMatches(Mappings mappings, ClassMatches classMatches, MemberMatches<T> memberMatches, Doer<T> doer) { |
| 481 | for (ClassMapping classMapping : mappings.classes()) { | 490 | for (ClassMapping classMapping : mappings.classes()) { |
| 482 | applyMemberMatches(classMapping, memberMatches, doer); | 491 | applyMemberMatches(classMapping, classMatches, memberMatches, doer); |
| 483 | } | 492 | } |
| 484 | } | 493 | } |
| 485 | 494 | ||
| 486 | private static <T extends Entry> void applyMemberMatches(ClassMapping classMapping, MemberMatches<T> memberMatches, Doer<T> doer) { | 495 | private static <T extends Entry> void applyMemberMatches(ClassMapping classMapping, ClassMatches classMatches, MemberMatches<T> memberMatches, Doer<T> doer) { |
| 487 | ClassEntry classEntry = classMapping.getObfEntry(); | 496 | |
| 497 | // get the classes | ||
| 498 | ClassEntry obfDestClass = classMapping.getObfEntry(); | ||
| 488 | 499 | ||
| 489 | // make a map of all the renames we need to make | 500 | // make a map of all the renames we need to make |
| 490 | Map<T,T> renames = Maps.newHashMap(); | 501 | Map<T,T> renames = Maps.newHashMap(); |
| 491 | for (MemberMapping<T> memberMapping : Lists.newArrayList(doer.getMappings(classMapping))) { | 502 | for (MemberMapping<T> memberMapping : Lists.newArrayList(doer.getMappings(classMapping))) { |
| 492 | T obfSourceEntry = memberMapping.getObfEntry(classEntry); | 503 | T obfOldDestEntry = memberMapping.getObfEntry(obfDestClass); |
| 493 | T obfDestEntry = memberMatches.matches().get(obfSourceEntry); | 504 | T obfSourceEntry = getSourceEntryFromDestMapping(memberMapping, obfDestClass, classMatches); |
| 494 | if (obfDestEntry != null) { | 505 | |
| 495 | if (obfDestEntry.getName().equals(obfSourceEntry.getName())) { | 506 | // but drop the unmatchable things |
| 496 | // same name, don't need to change anything | 507 | if (memberMatches.isUnmatchableSourceEntry(obfSourceEntry)) { |
| 497 | continue; | 508 | doer.removeMemberByObf(classMapping, obfOldDestEntry); |
| 498 | } | 509 | continue; |
| 499 | renames.put(obfSourceEntry, obfDestEntry); | 510 | } |
| 511 | |||
| 512 | T obfNewDestEntry = memberMatches.matches().get(obfSourceEntry); | ||
| 513 | if (obfNewDestEntry != null && !obfOldDestEntry.getName().equals(obfNewDestEntry.getName())) { | ||
| 514 | renames.put(obfOldDestEntry, obfNewDestEntry); | ||
| 500 | } | 515 | } |
| 501 | } | 516 | } |
| 502 | 517 | ||
| 503 | // apply to this class (should never need more than n passes) | 518 | if (!renames.isEmpty()) { |
| 504 | int numRenames = renames.size(); | 519 | |
| 505 | for (int i=0; i<numRenames && !renames.isEmpty(); i++) { | 520 | // apply to this class (should never need more than n passes) |
| 506 | for (MemberMapping<T> memberMapping : Lists.newArrayList(doer.getMappings(classMapping))) { | 521 | int numRenamesAppliedThisRound; |
| 507 | T obfSourceEntry = memberMapping.getObfEntry(classEntry); | 522 | do { |
| 508 | T obfDestEntry = renames.get(obfSourceEntry); | 523 | numRenamesAppliedThisRound = 0; |
| 509 | if (obfDestEntry != null) { | 524 | |
| 510 | // make sure this rename won't cause a collision | 525 | for (MemberMapping<T> memberMapping : Lists.newArrayList(doer.getMappings(classMapping))) { |
| 511 | if (!doer.hasObfMember(classMapping, obfDestEntry)) { | 526 | T obfOldDestEntry = memberMapping.getObfEntry(obfDestClass); |
| 512 | doer.setMemberObfName(classMapping, memberMapping, obfDestEntry.getName()); | 527 | T obfNewDestEntry = renames.get(obfOldDestEntry); |
| 513 | renames.remove(obfSourceEntry); | 528 | if (obfNewDestEntry != null) { |
| 529 | // make sure this rename won't cause a collision | ||
| 530 | // otherwise, save it for the next round and try again next time | ||
| 531 | if (!doer.hasObfMember(classMapping, obfNewDestEntry)) { | ||
| 532 | doer.setUpdateObfMember(classMapping, memberMapping, obfNewDestEntry); | ||
| 533 | renames.remove(obfOldDestEntry); | ||
| 534 | numRenamesAppliedThisRound++; | ||
| 535 | } | ||
| 514 | } | 536 | } |
| 515 | } | 537 | } |
| 516 | } | 538 | } while(numRenamesAppliedThisRound > 0); |
| 517 | } | 539 | |
| 518 | if (!renames.isEmpty()) { | 540 | if (!renames.isEmpty()) { |
| 519 | System.err.println(String.format("WARNING: Couldn't apply all the renames for class %s. %d/%d renames left.", | 541 | System.err.println(String.format("WARNING: Couldn't apply all the renames for class %s. %d renames left.", |
| 520 | classMapping.getObfFullName(), renames.size(), numRenames | 542 | classMapping.getObfFullName(), renames.size() |
| 521 | )); | 543 | )); |
| 522 | for (Map.Entry<T,T> entry : renames.entrySet()) { | 544 | for (Map.Entry<T,T> entry : renames.entrySet()) { |
| 523 | System.err.println(String.format("\t%s -> %s", entry.getKey(), entry.getValue())); | 545 | System.err.println(String.format("\t%s -> %s", entry.getKey().getName(), entry.getValue().getName())); |
| 546 | } | ||
| 524 | } | 547 | } |
| 525 | } | 548 | } |
| 526 | 549 | ||
| 527 | // recurse | 550 | // recurse |
| 528 | for (ClassMapping innerClassMapping : classMapping.innerClasses()) { | 551 | for (ClassMapping innerClassMapping : classMapping.innerClasses()) { |
| 529 | applyMemberMatches(innerClassMapping, memberMatches, doer); | 552 | applyMemberMatches(innerClassMapping, classMatches, memberMatches, doer); |
| 530 | } | 553 | } |
| 531 | } | 554 | } |
| 555 | |||
| 556 | private static <T extends Entry> T getSourceEntryFromDestMapping(MemberMapping<T> destMemberMapping, ClassEntry obfDestClass, ClassMatches classMatches) { | ||
| 557 | return translate(destMemberMapping.getObfEntry(obfDestClass), classMatches.getUniqueMatches().inverse()); | ||
| 558 | } | ||
| 532 | } | 559 | } |