diff options
| author | 2014-08-25 00:04:47 -0400 | |
|---|---|---|
| committer | 2014-08-25 00:04:47 -0400 | |
| commit | 2e97f24a658aa897313cb7cf92ed2e4b4a986bfc (patch) | |
| tree | f5b97f28a913ecddf5c4902b331540b106a8b128 /src | |
| parent | minor bug fixes (diff) | |
| download | enigma-fork-2e97f24a658aa897313cb7cf92ed2e4b4a986bfc.tar.gz enigma-fork-2e97f24a658aa897313cb7cf92ed2e4b4a986bfc.tar.xz enigma-fork-2e97f24a658aa897313cb7cf92ed2e4b4a986bfc.zip | |
fixed issue with bridge methods so source export has fewer compile errors. =)
Diffstat (limited to 'src')
| -rw-r--r-- | src/cuchaz/enigma/Deobfuscator.java | 6 | ||||
| -rw-r--r-- | src/cuchaz/enigma/Main.java | 3 | ||||
| -rw-r--r-- | src/cuchaz/enigma/TranslatingTypeLoader.java | 2 | ||||
| -rw-r--r-- | src/cuchaz/enigma/analysis/BridgeFixer.java | 92 | ||||
| -rw-r--r-- | src/cuchaz/enigma/analysis/JarIndex.java | 172 |
5 files changed, 163 insertions, 112 deletions
diff --git a/src/cuchaz/enigma/Deobfuscator.java b/src/cuchaz/enigma/Deobfuscator.java index 0bc4a04..8a516b1 100644 --- a/src/cuchaz/enigma/Deobfuscator.java +++ b/src/cuchaz/enigma/Deobfuscator.java | |||
| @@ -219,6 +219,12 @@ public class Deobfuscator | |||
| 219 | continue; | 219 | continue; |
| 220 | } | 220 | } |
| 221 | 221 | ||
| 222 | // TEMP: skip the classes that won't decompile because of a procyon bug | ||
| 223 | if( obfClassEntry.getName().equals( "none/bgl" ) ) | ||
| 224 | { | ||
| 225 | continue; | ||
| 226 | } | ||
| 227 | |||
| 222 | ClassEntry deobfClassEntry = deobfuscateEntry( new ClassEntry( obfClassEntry ) ); | 228 | ClassEntry deobfClassEntry = deobfuscateEntry( new ClassEntry( obfClassEntry ) ); |
| 223 | if( progress != null ) | 229 | if( progress != null ) |
| 224 | { | 230 | { |
diff --git a/src/cuchaz/enigma/Main.java b/src/cuchaz/enigma/Main.java index fe4d6e3..c69b890 100644 --- a/src/cuchaz/enigma/Main.java +++ b/src/cuchaz/enigma/Main.java | |||
| @@ -13,6 +13,7 @@ package cuchaz.enigma; | |||
| 13 | import java.io.File; | 13 | import java.io.File; |
| 14 | 14 | ||
| 15 | import cuchaz.enigma.gui.Gui; | 15 | import cuchaz.enigma.gui.Gui; |
| 16 | import cuchaz.enigma.mapping.ClassEntry; | ||
| 16 | 17 | ||
| 17 | public class Main | 18 | public class Main |
| 18 | { | 19 | { |
| @@ -32,7 +33,7 @@ public class Main | |||
| 32 | } | 33 | } |
| 33 | 34 | ||
| 34 | // DEBUG | 35 | // DEBUG |
| 35 | //gui.getController().openDeclaration( new ClassEntry( "none/bgl" ) ); | 36 | gui.getController().openDeclaration( new ClassEntry( "none/bsp" ) ); |
| 36 | } | 37 | } |
| 37 | 38 | ||
| 38 | private static File getFile( String path ) | 39 | private static File getFile( String path ) |
diff --git a/src/cuchaz/enigma/TranslatingTypeLoader.java b/src/cuchaz/enigma/TranslatingTypeLoader.java index 763d767..83f0baa 100644 --- a/src/cuchaz/enigma/TranslatingTypeLoader.java +++ b/src/cuchaz/enigma/TranslatingTypeLoader.java | |||
| @@ -177,7 +177,7 @@ public class TranslatingTypeLoader implements ITypeLoader | |||
| 177 | assertClassName( c, obfClassEntry ); | 177 | assertClassName( c, obfClassEntry ); |
| 178 | 178 | ||
| 179 | // do all kinds of deobfuscating transformations on the class | 179 | // do all kinds of deobfuscating transformations on the class |
| 180 | new BridgeFixer().fixBridges( c ); | 180 | new BridgeFixer( m_jarIndex ).fixBridges( c ); |
| 181 | new MethodParameterWriter( m_deobfuscatingTranslator ).writeMethodArguments( c ); | 181 | new MethodParameterWriter( m_deobfuscatingTranslator ).writeMethodArguments( c ); |
| 182 | new ClassTranslator( m_deobfuscatingTranslator ).translate( c ); | 182 | new ClassTranslator( m_deobfuscatingTranslator ).translate( c ); |
| 183 | 183 | ||
diff --git a/src/cuchaz/enigma/analysis/BridgeFixer.java b/src/cuchaz/enigma/analysis/BridgeFixer.java deleted file mode 100644 index f13f68f..0000000 --- a/src/cuchaz/enigma/analysis/BridgeFixer.java +++ /dev/null | |||
| @@ -1,92 +0,0 @@ | |||
| 1 | /******************************************************************************* | ||
| 2 | * Copyright (c) 2014 Jeff Martin. | ||
| 3 | * All rights reserved. This program and the accompanying materials | ||
| 4 | * are made available under the terms of the GNU Public License v3.0 | ||
| 5 | * which accompanies this distribution, and is available at | ||
| 6 | * http://www.gnu.org/licenses/gpl.html | ||
| 7 | * | ||
| 8 | * Contributors: | ||
| 9 | * Jeff Martin - initial API and implementation | ||
| 10 | ******************************************************************************/ | ||
| 11 | package cuchaz.enigma.analysis; | ||
| 12 | |||
| 13 | import java.util.List; | ||
| 14 | |||
| 15 | import javassist.CannotCompileException; | ||
| 16 | import javassist.CtClass; | ||
| 17 | import javassist.CtMethod; | ||
| 18 | import javassist.NotFoundException; | ||
| 19 | import javassist.bytecode.AccessFlag; | ||
| 20 | import javassist.expr.ExprEditor; | ||
| 21 | import javassist.expr.MethodCall; | ||
| 22 | |||
| 23 | import com.beust.jcommander.internal.Lists; | ||
| 24 | |||
| 25 | public class BridgeFixer | ||
| 26 | { | ||
| 27 | public void fixBridges( CtClass c ) | ||
| 28 | { | ||
| 29 | // bridge methods are scrubbed and marked as synthetic methods by the obfuscator | ||
| 30 | // need to figure out which synthetics are bridge methods and restore them | ||
| 31 | for( CtMethod method : c.getDeclaredMethods() ) | ||
| 32 | { | ||
| 33 | // skip non-synthetic methods | ||
| 34 | if( ( method.getModifiers() & AccessFlag.SYNTHETIC ) == 0 ) | ||
| 35 | { | ||
| 36 | continue; | ||
| 37 | } | ||
| 38 | |||
| 39 | CtMethod bridgedMethod = getBridgedMethod( method ); | ||
| 40 | if( bridgedMethod != null ) | ||
| 41 | { | ||
| 42 | bridgedMethod.setName( method.getName() ); | ||
| 43 | method.setModifiers( method.getModifiers() | AccessFlag.BRIDGE ); | ||
| 44 | |||
| 45 | // TODO: rename all references to this method? | ||
| 46 | } | ||
| 47 | } | ||
| 48 | } | ||
| 49 | |||
| 50 | private CtMethod getBridgedMethod( CtMethod method ) | ||
| 51 | { | ||
| 52 | // bridge methods just call another method, cast it to the return type, and return the result | ||
| 53 | // let's see if we can detect this scenario | ||
| 54 | |||
| 55 | // get all the called methods | ||
| 56 | final List<MethodCall> methodCalls = Lists.newArrayList(); | ||
| 57 | try | ||
| 58 | { | ||
| 59 | method.instrument( new ExprEditor( ) | ||
| 60 | { | ||
| 61 | @Override | ||
| 62 | public void edit( MethodCall call ) | ||
| 63 | { | ||
| 64 | methodCalls.add( call ); | ||
| 65 | } | ||
| 66 | } ); | ||
| 67 | } | ||
| 68 | catch( CannotCompileException ex ) | ||
| 69 | { | ||
| 70 | // this is stupid... we're not even compiling anything | ||
| 71 | throw new Error( ex ); | ||
| 72 | } | ||
| 73 | |||
| 74 | // is there just one? | ||
| 75 | if( methodCalls.size() != 1 ) | ||
| 76 | { | ||
| 77 | return null; | ||
| 78 | } | ||
| 79 | MethodCall call = methodCalls.get( 0 ); | ||
| 80 | |||
| 81 | try | ||
| 82 | { | ||
| 83 | // we have a bridge method! | ||
| 84 | return call.getMethod(); | ||
| 85 | } | ||
| 86 | catch( NotFoundException ex ) | ||
| 87 | { | ||
| 88 | // can't find the type? not a bridge method | ||
| 89 | return null; | ||
| 90 | } | ||
| 91 | } | ||
| 92 | } | ||
diff --git a/src/cuchaz/enigma/analysis/JarIndex.java b/src/cuchaz/enigma/analysis/JarIndex.java index 2c4dec4..cb7508e 100644 --- a/src/cuchaz/enigma/analysis/JarIndex.java +++ b/src/cuchaz/enigma/analysis/JarIndex.java | |||
| @@ -24,6 +24,7 @@ import javassist.CtBehavior; | |||
| 24 | import javassist.CtClass; | 24 | import javassist.CtClass; |
| 25 | import javassist.CtConstructor; | 25 | import javassist.CtConstructor; |
| 26 | import javassist.CtMethod; | 26 | import javassist.CtMethod; |
| 27 | import javassist.NotFoundException; | ||
| 27 | import javassist.bytecode.AccessFlag; | 28 | import javassist.bytecode.AccessFlag; |
| 28 | import javassist.bytecode.Descriptor; | 29 | import javassist.bytecode.Descriptor; |
| 29 | import javassist.bytecode.FieldInfo; | 30 | import javassist.bytecode.FieldInfo; |
| @@ -60,6 +61,7 @@ public class JarIndex | |||
| 60 | private Multimap<String,String> m_innerClasses; | 61 | private Multimap<String,String> m_innerClasses; |
| 61 | private Map<String,String> m_outerClasses; | 62 | private Map<String,String> m_outerClasses; |
| 62 | private Set<String> m_anonymousClasses; | 63 | private Set<String> m_anonymousClasses; |
| 64 | private Map<MethodEntry,MethodEntry> m_bridgeMethods; | ||
| 63 | 65 | ||
| 64 | public JarIndex( ) | 66 | public JarIndex( ) |
| 65 | { | 67 | { |
| @@ -71,11 +73,12 @@ public class JarIndex | |||
| 71 | m_innerClasses = HashMultimap.create(); | 73 | m_innerClasses = HashMultimap.create(); |
| 72 | m_outerClasses = Maps.newHashMap(); | 74 | m_outerClasses = Maps.newHashMap(); |
| 73 | m_anonymousClasses = Sets.newHashSet(); | 75 | m_anonymousClasses = Sets.newHashSet(); |
| 76 | m_bridgeMethods = Maps.newHashMap(); | ||
| 74 | } | 77 | } |
| 75 | 78 | ||
| 76 | public void indexJar( JarFile jar ) | 79 | public void indexJar( JarFile jar ) |
| 77 | { | 80 | { |
| 78 | // pass 1: read the class names | 81 | // step 1: read the class names |
| 79 | for( ClassEntry classEntry : JarClassIterator.getClassEntries( jar ) ) | 82 | for( ClassEntry classEntry : JarClassIterator.getClassEntries( jar ) ) |
| 80 | { | 83 | { |
| 81 | if( classEntry.isInDefaultPackage() ) | 84 | if( classEntry.isInDefaultPackage() ) |
| @@ -86,7 +89,7 @@ public class JarIndex | |||
| 86 | m_obfClassEntries.add( classEntry ); | 89 | m_obfClassEntries.add( classEntry ); |
| 87 | } | 90 | } |
| 88 | 91 | ||
| 89 | // pass 2: index the types, methods | 92 | // step 2: index the types, methods |
| 90 | for( CtClass c : JarClassIterator.classes( jar ) ) | 93 | for( CtClass c : JarClassIterator.classes( jar ) ) |
| 91 | { | 94 | { |
| 92 | fixClass( c ); | 95 | fixClass( c ); |
| @@ -97,7 +100,7 @@ public class JarIndex | |||
| 97 | } | 100 | } |
| 98 | } | 101 | } |
| 99 | 102 | ||
| 100 | // pass 2: index inner classes and anonymous classes | 103 | // step 3: index inner classes and anonymous classes |
| 101 | for( CtClass c : JarClassIterator.classes( jar ) ) | 104 | for( CtClass c : JarClassIterator.classes( jar ) ) |
| 102 | { | 105 | { |
| 103 | fixClass( c ); | 106 | fixClass( c ); |
| @@ -124,13 +127,16 @@ public class JarIndex | |||
| 124 | } | 127 | } |
| 125 | } | 128 | } |
| 126 | 129 | ||
| 127 | // step 3: update other indicies with inner class info | 130 | // step 4: update other indices with inner class info |
| 128 | Map<String,String> renames = Maps.newHashMap(); | 131 | Map<String,String> renames = Maps.newHashMap(); |
| 129 | for( Map.Entry<String,String> entry : m_outerClasses.entrySet() ) | 132 | for( Map.Entry<String,String> entry : m_outerClasses.entrySet() ) |
| 130 | { | 133 | { |
| 131 | renames.put( entry.getKey(), entry.getValue() + "$" + entry.getKey() ); | 134 | renames.put( entry.getKey(), entry.getValue() + "$" + entry.getKey() ); |
| 132 | } | 135 | } |
| 133 | renameClasses( renames ); | 136 | renameClasses( renames ); |
| 137 | |||
| 138 | // step 5: update other indices with bridge method info | ||
| 139 | renameMethods( m_bridgeMethods ); | ||
| 134 | } | 140 | } |
| 135 | 141 | ||
| 136 | private void fixClass( CtClass c ) | 142 | private void fixClass( CtClass c ) |
| @@ -160,6 +166,18 @@ public class JarIndex | |||
| 160 | 166 | ||
| 161 | // index implementation | 167 | // index implementation |
| 162 | m_methodImplementations.put( className, methodEntry ); | 168 | m_methodImplementations.put( className, methodEntry ); |
| 169 | |||
| 170 | // look for bridge methods | ||
| 171 | CtMethod bridgedMethod = getBridgedMethod( (CtMethod)behavior ); | ||
| 172 | if( bridgedMethod != null ) | ||
| 173 | { | ||
| 174 | MethodEntry bridgedMethodEntry = new MethodEntry( | ||
| 175 | new ClassEntry( className ), | ||
| 176 | bridgedMethod.getName(), | ||
| 177 | bridgedMethod.getSignature() | ||
| 178 | ); | ||
| 179 | m_bridgeMethods.put( bridgedMethodEntry, methodEntry ); | ||
| 180 | } | ||
| 163 | } | 181 | } |
| 164 | else if( behavior instanceof CtConstructor ) | 182 | else if( behavior instanceof CtConstructor ) |
| 165 | { | 183 | { |
| @@ -254,6 +272,56 @@ public class JarIndex | |||
| 254 | } | 272 | } |
| 255 | } | 273 | } |
| 256 | 274 | ||
| 275 | |||
| 276 | private CtMethod getBridgedMethod( CtMethod method ) | ||
| 277 | { | ||
| 278 | // bridge methods just call another method, cast it to the return type, and return the result | ||
| 279 | // let's see if we can detect this scenario | ||
| 280 | |||
| 281 | // skip non-synthetic methods | ||
| 282 | if( ( method.getModifiers() & AccessFlag.SYNTHETIC ) == 0 ) | ||
| 283 | { | ||
| 284 | return null; | ||
| 285 | } | ||
| 286 | |||
| 287 | // get all the called methods | ||
| 288 | final List<MethodCall> methodCalls = Lists.newArrayList(); | ||
| 289 | try | ||
| 290 | { | ||
| 291 | method.instrument( new ExprEditor( ) | ||
| 292 | { | ||
| 293 | @Override | ||
| 294 | public void edit( MethodCall call ) | ||
| 295 | { | ||
| 296 | methodCalls.add( call ); | ||
| 297 | } | ||
| 298 | } ); | ||
| 299 | } | ||
| 300 | catch( CannotCompileException ex ) | ||
| 301 | { | ||
| 302 | // this is stupid... we're not even compiling anything | ||
| 303 | throw new Error( ex ); | ||
| 304 | } | ||
| 305 | |||
| 306 | // is there just one? | ||
| 307 | if( methodCalls.size() != 1 ) | ||
| 308 | { | ||
| 309 | return null; | ||
| 310 | } | ||
| 311 | MethodCall call = methodCalls.get( 0 ); | ||
| 312 | |||
| 313 | try | ||
| 314 | { | ||
| 315 | // we have a bridge method! | ||
| 316 | return call.getMethod(); | ||
| 317 | } | ||
| 318 | catch( NotFoundException ex ) | ||
| 319 | { | ||
| 320 | // can't find the type? not a bridge method | ||
| 321 | return null; | ||
| 322 | } | ||
| 323 | } | ||
| 324 | |||
| 257 | private String findOuterClass( CtClass c ) | 325 | private String findOuterClass( CtClass c ) |
| 258 | { | 326 | { |
| 259 | // inner classes: | 327 | // inner classes: |
| @@ -534,15 +602,27 @@ public class JarIndex | |||
| 534 | return m_anonymousClasses.contains( obfInnerClassName ); | 602 | return m_anonymousClasses.contains( obfInnerClassName ); |
| 535 | } | 603 | } |
| 536 | 604 | ||
| 605 | public MethodEntry getBridgeMethod( MethodEntry methodEntry ) | ||
| 606 | { | ||
| 607 | return m_bridgeMethods.get( methodEntry ); | ||
| 608 | } | ||
| 609 | |||
| 537 | private void renameClasses( Map<String,String> renames ) | 610 | private void renameClasses( Map<String,String> renames ) |
| 538 | { | 611 | { |
| 539 | m_ancestries.renameClasses( renames ); | 612 | m_ancestries.renameClasses( renames ); |
| 540 | renameMultimap( renames, m_methodImplementations ); | 613 | renameClassesInMultimap( renames, m_methodImplementations ); |
| 541 | renameMultimap( renames, m_behaviorReferences ); | 614 | renameClassesInMultimap( renames, m_behaviorReferences ); |
| 542 | renameMultimap( renames, m_fieldReferences ); | 615 | renameClassesInMultimap( renames, m_fieldReferences ); |
| 616 | } | ||
| 617 | |||
| 618 | private void renameMethods( Map<MethodEntry,MethodEntry> renames ) | ||
| 619 | { | ||
| 620 | renameMethodsInMultimap( renames, m_methodImplementations ); | ||
| 621 | renameMethodsInMultimap( renames, m_behaviorReferences ); | ||
| 622 | renameMethodsInMultimap( renames, m_fieldReferences ); | ||
| 543 | } | 623 | } |
| 544 | 624 | ||
| 545 | private <Key,Val> void renameMultimap( Map<String,String> renames, Multimap<Key,Val> map ) | 625 | private <Key,Val> void renameClassesInMultimap( Map<String,String> renames, Multimap<Key,Val> map ) |
| 546 | { | 626 | { |
| 547 | // for each key/value pair... | 627 | // for each key/value pair... |
| 548 | Set<Map.Entry<Key,Val>> entriesToAdd = Sets.newHashSet(); | 628 | Set<Map.Entry<Key,Val>> entriesToAdd = Sets.newHashSet(); |
| @@ -552,8 +632,8 @@ public class JarIndex | |||
| 552 | Map.Entry<Key,Val> entry = iter.next(); | 632 | Map.Entry<Key,Val> entry = iter.next(); |
| 553 | iter.remove(); | 633 | iter.remove(); |
| 554 | entriesToAdd.add( new AbstractMap.SimpleEntry<Key,Val>( | 634 | entriesToAdd.add( new AbstractMap.SimpleEntry<Key,Val>( |
| 555 | renameThing( renames, entry.getKey() ), | 635 | renameClassesInThing( renames, entry.getKey() ), |
| 556 | renameThing( renames, entry.getValue() ) | 636 | renameClassesInThing( renames, entry.getValue() ) |
| 557 | ) ); | 637 | ) ); |
| 558 | } | 638 | } |
| 559 | for( Map.Entry<Key,Val> entry : entriesToAdd ) | 639 | for( Map.Entry<Key,Val> entry : entriesToAdd ) |
| @@ -563,7 +643,7 @@ public class JarIndex | |||
| 563 | } | 643 | } |
| 564 | 644 | ||
| 565 | @SuppressWarnings( "unchecked" ) | 645 | @SuppressWarnings( "unchecked" ) |
| 566 | private <T> T renameThing( Map<String,String> renames, T thing ) | 646 | private <T> T renameClassesInThing( Map<String,String> renames, T thing ) |
| 567 | { | 647 | { |
| 568 | if( thing instanceof String ) | 648 | if( thing instanceof String ) |
| 569 | { | 649 | { |
| @@ -576,13 +656,13 @@ public class JarIndex | |||
| 576 | else if( thing instanceof ClassEntry ) | 656 | else if( thing instanceof ClassEntry ) |
| 577 | { | 657 | { |
| 578 | ClassEntry classEntry = (ClassEntry)thing; | 658 | ClassEntry classEntry = (ClassEntry)thing; |
| 579 | return (T)new ClassEntry( renameThing( renames, classEntry.getClassName() ) ); | 659 | return (T)new ClassEntry( renameClassesInThing( renames, classEntry.getClassName() ) ); |
| 580 | } | 660 | } |
| 581 | else if( thing instanceof FieldEntry ) | 661 | else if( thing instanceof FieldEntry ) |
| 582 | { | 662 | { |
| 583 | FieldEntry fieldEntry = (FieldEntry)thing; | 663 | FieldEntry fieldEntry = (FieldEntry)thing; |
| 584 | return (T)new FieldEntry( | 664 | return (T)new FieldEntry( |
| 585 | renameThing( renames, fieldEntry.getClassEntry() ), | 665 | renameClassesInThing( renames, fieldEntry.getClassEntry() ), |
| 586 | fieldEntry.getName() | 666 | fieldEntry.getName() |
| 587 | ); | 667 | ); |
| 588 | } | 668 | } |
| @@ -590,7 +670,7 @@ public class JarIndex | |||
| 590 | { | 670 | { |
| 591 | ConstructorEntry constructorEntry = (ConstructorEntry)thing; | 671 | ConstructorEntry constructorEntry = (ConstructorEntry)thing; |
| 592 | return (T)new ConstructorEntry( | 672 | return (T)new ConstructorEntry( |
| 593 | renameThing( renames, constructorEntry.getClassEntry() ), | 673 | renameClassesInThing( renames, constructorEntry.getClassEntry() ), |
| 594 | constructorEntry.getSignature() | 674 | constructorEntry.getSignature() |
| 595 | ); | 675 | ); |
| 596 | } | 676 | } |
| @@ -598,7 +678,7 @@ public class JarIndex | |||
| 598 | { | 678 | { |
| 599 | MethodEntry methodEntry = (MethodEntry)thing; | 679 | MethodEntry methodEntry = (MethodEntry)thing; |
| 600 | return (T)new MethodEntry( | 680 | return (T)new MethodEntry( |
| 601 | renameThing( renames, methodEntry.getClassEntry() ), | 681 | renameClassesInThing( renames, methodEntry.getClassEntry() ), |
| 602 | methodEntry.getName(), | 682 | methodEntry.getName(), |
| 603 | methodEntry.getSignature() | 683 | methodEntry.getSignature() |
| 604 | ); | 684 | ); |
| @@ -607,7 +687,7 @@ public class JarIndex | |||
| 607 | { | 687 | { |
| 608 | ArgumentEntry argumentEntry = (ArgumentEntry)thing; | 688 | ArgumentEntry argumentEntry = (ArgumentEntry)thing; |
| 609 | return (T)new ArgumentEntry( | 689 | return (T)new ArgumentEntry( |
| 610 | renameThing( renames, argumentEntry.getMethodEntry() ), | 690 | renameClassesInThing( renames, argumentEntry.getMethodEntry() ), |
| 611 | argumentEntry.getIndex(), | 691 | argumentEntry.getIndex(), |
| 612 | argumentEntry.getName() | 692 | argumentEntry.getName() |
| 613 | ); | 693 | ); |
| @@ -615,8 +695,8 @@ public class JarIndex | |||
| 615 | else if( thing instanceof EntryReference ) | 695 | else if( thing instanceof EntryReference ) |
| 616 | { | 696 | { |
| 617 | EntryReference<Entry,Entry> reference = (EntryReference<Entry,Entry>)thing; | 697 | EntryReference<Entry,Entry> reference = (EntryReference<Entry,Entry>)thing; |
| 618 | reference.entry = renameThing( renames, reference.entry ); | 698 | reference.entry = renameClassesInThing( renames, reference.entry ); |
| 619 | reference.context = renameThing( renames, reference.context ); | 699 | reference.context = renameClassesInThing( renames, reference.context ); |
| 620 | return thing; | 700 | return thing; |
| 621 | } | 701 | } |
| 622 | else | 702 | else |
| @@ -626,4 +706,60 @@ public class JarIndex | |||
| 626 | 706 | ||
| 627 | return thing; | 707 | return thing; |
| 628 | } | 708 | } |
| 709 | |||
| 710 | private <Key,Val> void renameMethodsInMultimap( Map<MethodEntry,MethodEntry> renames, Multimap<Key,Val> map ) | ||
| 711 | { | ||
| 712 | // for each key/value pair... | ||
| 713 | Set<Map.Entry<Key,Val>> entriesToAdd = Sets.newHashSet(); | ||
| 714 | Iterator<Map.Entry<Key,Val>> iter = map.entries().iterator(); | ||
| 715 | while( iter.hasNext() ) | ||
| 716 | { | ||
| 717 | Map.Entry<Key,Val> entry = iter.next(); | ||
| 718 | iter.remove(); | ||
| 719 | entriesToAdd.add( new AbstractMap.SimpleEntry<Key,Val>( | ||
| 720 | renameMethodsInThing( renames, entry.getKey() ), | ||
| 721 | renameMethodsInThing( renames, entry.getValue() ) | ||
| 722 | ) ); | ||
| 723 | } | ||
| 724 | for( Map.Entry<Key,Val> entry : entriesToAdd ) | ||
| 725 | { | ||
| 726 | map.put( entry.getKey(), entry.getValue() ); | ||
| 727 | } | ||
| 728 | } | ||
| 729 | |||
| 730 | @SuppressWarnings( "unchecked" ) | ||
| 731 | private <T> T renameMethodsInThing( Map<MethodEntry,MethodEntry> renames, T thing ) | ||
| 732 | { | ||
| 733 | if( thing instanceof MethodEntry ) | ||
| 734 | { | ||
| 735 | MethodEntry methodEntry = (MethodEntry)thing; | ||
| 736 | MethodEntry newMethodEntry = renames.get( methodEntry ); | ||
| 737 | if( newMethodEntry != null ) | ||
| 738 | { | ||
| 739 | return (T)new MethodEntry( | ||
| 740 | methodEntry.getClassEntry(), | ||
| 741 | newMethodEntry.getName(), | ||
| 742 | methodEntry.getSignature() | ||
| 743 | ); | ||
| 744 | } | ||
| 745 | return thing; | ||
| 746 | } | ||
| 747 | else if( thing instanceof ArgumentEntry ) | ||
| 748 | { | ||
| 749 | ArgumentEntry argumentEntry = (ArgumentEntry)thing; | ||
| 750 | return (T)new ArgumentEntry( | ||
| 751 | renameMethodsInThing( renames, argumentEntry.getMethodEntry() ), | ||
| 752 | argumentEntry.getIndex(), | ||
| 753 | argumentEntry.getName() | ||
| 754 | ); | ||
| 755 | } | ||
| 756 | else if( thing instanceof EntryReference ) | ||
| 757 | { | ||
| 758 | EntryReference<Entry,Entry> reference = (EntryReference<Entry,Entry>)thing; | ||
| 759 | reference.entry = renameMethodsInThing( renames, reference.entry ); | ||
| 760 | reference.context = renameMethodsInThing( renames, reference.context ); | ||
| 761 | return thing; | ||
| 762 | } | ||
| 763 | return thing; | ||
| 764 | } | ||
| 629 | } | 765 | } |