diff options
| author | 2014-08-26 00:27:44 -0400 | |
|---|---|---|
| committer | 2014-08-26 00:27:44 -0400 | |
| commit | 5f44aac70f59898197c2a7625b74f901c3b31106 (patch) | |
| tree | 7d2cc2e48201c92867786793966f356810b464fa /src | |
| parent | wrote CheckCastIterator to try to do generic type inference. It's too hard to... (diff) | |
| download | enigma-5f44aac70f59898197c2a7625b74f901c3b31106.tar.gz enigma-5f44aac70f59898197c2a7625b74f901c3b31106.tar.xz enigma-5f44aac70f59898197c2a7625b74f901c3b31106.zip | |
implemented proper support for interfaces
Diffstat (limited to 'src')
| -rw-r--r-- | src/cuchaz/enigma/TranslatingTypeLoader.java | 5 | ||||
| -rw-r--r-- | src/cuchaz/enigma/analysis/Ancestries.java | 89 | ||||
| -rw-r--r-- | src/cuchaz/enigma/analysis/ClassImplementationsTreeNode.java | 92 | ||||
| -rw-r--r-- | src/cuchaz/enigma/analysis/JarIndex.java | 107 | ||||
| -rw-r--r-- | src/cuchaz/enigma/analysis/MethodImplementationsTreeNode.java | 111 | ||||
| -rw-r--r-- | src/cuchaz/enigma/gui/Gui.java | 104 | ||||
| -rw-r--r-- | src/cuchaz/enigma/gui/GuiController.java | 25 | ||||
| -rw-r--r-- | src/cuchaz/enigma/mapping/Renamer.java | 21 |
8 files changed, 524 insertions, 30 deletions
diff --git a/src/cuchaz/enigma/TranslatingTypeLoader.java b/src/cuchaz/enigma/TranslatingTypeLoader.java index 83f0baa4..1e0e95a2 100644 --- a/src/cuchaz/enigma/TranslatingTypeLoader.java +++ b/src/cuchaz/enigma/TranslatingTypeLoader.java | |||
| @@ -13,7 +13,6 @@ package cuchaz.enigma; | |||
| 13 | import java.io.ByteArrayOutputStream; | 13 | import java.io.ByteArrayOutputStream; |
| 14 | import java.io.IOException; | 14 | import java.io.IOException; |
| 15 | import java.io.InputStream; | 15 | import java.io.InputStream; |
| 16 | import java.util.Arrays; | ||
| 17 | import java.util.Map; | 16 | import java.util.Map; |
| 18 | import java.util.jar.JarEntry; | 17 | import java.util.jar.JarEntry; |
| 19 | import java.util.jar.JarFile; | 18 | import java.util.jar.JarFile; |
| @@ -105,12 +104,12 @@ public class TranslatingTypeLoader implements ITypeLoader | |||
| 105 | return null; | 104 | return null; |
| 106 | } | 105 | } |
| 107 | 106 | ||
| 108 | // DEBUG | 107 | /* DEBUG |
| 109 | if( !Arrays.asList( "java", "org", "io" ).contains( deobfClassName.split( "/" )[0] ) ) | 108 | if( !Arrays.asList( "java", "org", "io" ).contains( deobfClassName.split( "/" )[0] ) ) |
| 110 | { | 109 | { |
| 111 | System.out.println( String.format( "Looking for %s (%s)", deobfClassEntry.getName(), obfClassEntry.getName() ) ); | 110 | System.out.println( String.format( "Looking for %s (%s)", deobfClassEntry.getName(), obfClassEntry.getName() ) ); |
| 112 | } | 111 | } |
| 113 | // | 112 | */ |
| 114 | 113 | ||
| 115 | // get the jar entry | 114 | // get the jar entry |
| 116 | String classFileName; | 115 | String classFileName; |
diff --git a/src/cuchaz/enigma/analysis/Ancestries.java b/src/cuchaz/enigma/analysis/Ancestries.java index b9d8cbf4..97241084 100644 --- a/src/cuchaz/enigma/analysis/Ancestries.java +++ b/src/cuchaz/enigma/analysis/Ancestries.java | |||
| @@ -11,24 +11,32 @@ | |||
| 11 | package cuchaz.enigma.analysis; | 11 | package cuchaz.enigma.analysis; |
| 12 | 12 | ||
| 13 | import java.io.Serializable; | 13 | import java.io.Serializable; |
| 14 | import java.util.AbstractMap; | ||
| 14 | import java.util.ArrayList; | 15 | import java.util.ArrayList; |
| 16 | import java.util.HashSet; | ||
| 15 | import java.util.List; | 17 | import java.util.List; |
| 16 | import java.util.Map; | 18 | import java.util.Map; |
| 19 | import java.util.Set; | ||
| 17 | 20 | ||
| 18 | import javassist.bytecode.Descriptor; | 21 | import javassist.bytecode.Descriptor; |
| 19 | 22 | ||
| 23 | import com.google.common.collect.HashMultimap; | ||
| 20 | import com.google.common.collect.Lists; | 24 | import com.google.common.collect.Lists; |
| 21 | import com.google.common.collect.Maps; | 25 | import com.google.common.collect.Maps; |
| 26 | import com.google.common.collect.Multimap; | ||
| 27 | import com.google.common.collect.Sets; | ||
| 22 | 28 | ||
| 23 | public class Ancestries implements Serializable | 29 | public class Ancestries implements Serializable |
| 24 | { | 30 | { |
| 25 | private static final long serialVersionUID = 738687982126844179L; | 31 | private static final long serialVersionUID = 738687982126844179L; |
| 26 | 32 | ||
| 27 | private Map<String,String> m_superclasses; | 33 | private Map<String,String> m_superclasses; |
| 34 | private Multimap<String,String> m_interfaces; | ||
| 28 | 35 | ||
| 29 | public Ancestries( ) | 36 | public Ancestries( ) |
| 30 | { | 37 | { |
| 31 | m_superclasses = Maps.newHashMap(); | 38 | m_superclasses = Maps.newHashMap(); |
| 39 | m_interfaces = HashMultimap.create(); | ||
| 32 | } | 40 | } |
| 33 | 41 | ||
| 34 | public void addSuperclass( String className, String superclassName ) | 42 | public void addSuperclass( String className, String superclassName ) |
| @@ -47,8 +55,25 @@ public class Ancestries implements Serializable | |||
| 47 | } | 55 | } |
| 48 | } | 56 | } |
| 49 | 57 | ||
| 58 | public void addInterface( String className, String interfaceName ) | ||
| 59 | { | ||
| 60 | className = Descriptor.toJvmName( className ); | ||
| 61 | interfaceName = Descriptor.toJvmName( interfaceName ); | ||
| 62 | |||
| 63 | if( className.equals( interfaceName ) ) | ||
| 64 | { | ||
| 65 | throw new IllegalArgumentException( "Class cannot be its own interface! " + className ); | ||
| 66 | } | ||
| 67 | |||
| 68 | if( !isJre( className ) && !isJre( interfaceName ) ) | ||
| 69 | { | ||
| 70 | m_interfaces.put( className, interfaceName ); | ||
| 71 | } | ||
| 72 | } | ||
| 73 | |||
| 50 | public void renameClasses( Map<String,String> renames ) | 74 | public void renameClasses( Map<String,String> renames ) |
| 51 | { | 75 | { |
| 76 | // rename superclasses | ||
| 52 | Map<String,String> newSuperclasses = Maps.newHashMap(); | 77 | Map<String,String> newSuperclasses = Maps.newHashMap(); |
| 53 | for( Map.Entry<String,String> entry : m_superclasses.entrySet() ) | 78 | for( Map.Entry<String,String> entry : m_superclasses.entrySet() ) |
| 54 | { | 79 | { |
| @@ -65,6 +90,28 @@ public class Ancestries implements Serializable | |||
| 65 | newSuperclasses.put( subclass, superclass ); | 90 | newSuperclasses.put( subclass, superclass ); |
| 66 | } | 91 | } |
| 67 | m_superclasses = newSuperclasses; | 92 | m_superclasses = newSuperclasses; |
| 93 | |||
| 94 | // rename interfaces | ||
| 95 | Set<Map.Entry<String,String>> entriesToAdd = Sets.newHashSet(); | ||
| 96 | for( Map.Entry<String,String> entry : m_interfaces.entries() ) | ||
| 97 | { | ||
| 98 | String className = renames.get( entry.getKey() ); | ||
| 99 | if( className == null ) | ||
| 100 | { | ||
| 101 | className = entry.getKey(); | ||
| 102 | } | ||
| 103 | String interfaceName = renames.get( entry.getValue() ); | ||
| 104 | if( interfaceName == null ) | ||
| 105 | { | ||
| 106 | interfaceName = entry.getValue(); | ||
| 107 | } | ||
| 108 | entriesToAdd.add( new AbstractMap.SimpleEntry<String,String>( className, interfaceName ) ); | ||
| 109 | } | ||
| 110 | m_interfaces.clear(); | ||
| 111 | for( Map.Entry<String,String> entry : entriesToAdd ) | ||
| 112 | { | ||
| 113 | m_interfaces.put( entry.getKey(), entry.getValue() ); | ||
| 114 | } | ||
| 68 | } | 115 | } |
| 69 | 116 | ||
| 70 | public String getSuperclassName( String className ) | 117 | public String getSuperclassName( String className ) |
| @@ -86,6 +133,17 @@ public class Ancestries implements Serializable | |||
| 86 | return ancestors; | 133 | return ancestors; |
| 87 | } | 134 | } |
| 88 | 135 | ||
| 136 | public Set<String> getInterfaces( String className ) | ||
| 137 | { | ||
| 138 | Set<String> interfaceNames = new HashSet<String>(); | ||
| 139 | interfaceNames.addAll( m_interfaces.get( className ) ); | ||
| 140 | for( String ancestor : getAncestry( className ) ) | ||
| 141 | { | ||
| 142 | interfaceNames.addAll( m_interfaces.get( ancestor ) ); | ||
| 143 | } | ||
| 144 | return interfaceNames; | ||
| 145 | } | ||
| 146 | |||
| 89 | public List<String> getSubclasses( String className ) | 147 | public List<String> getSubclasses( String className ) |
| 90 | { | 148 | { |
| 91 | // linear search is fast enough for now | 149 | // linear search is fast enough for now |
| @@ -102,6 +160,37 @@ public class Ancestries implements Serializable | |||
| 102 | return subclasses; | 160 | return subclasses; |
| 103 | } | 161 | } |
| 104 | 162 | ||
| 163 | public Set<String> getImplementingClasses( String targetInterfaceName ) | ||
| 164 | { | ||
| 165 | // linear search is fast enough for now | ||
| 166 | Set<String> classNames = Sets.newHashSet(); | ||
| 167 | for( Map.Entry<String,String> entry : m_interfaces.entries() ) | ||
| 168 | { | ||
| 169 | String className = entry.getKey(); | ||
| 170 | String interfaceName = entry.getValue(); | ||
| 171 | if( interfaceName.equals( targetInterfaceName ) ) | ||
| 172 | { | ||
| 173 | classNames.add( className ); | ||
| 174 | collectSubclasses( classNames, className ); | ||
| 175 | } | ||
| 176 | } | ||
| 177 | return classNames; | ||
| 178 | } | ||
| 179 | |||
| 180 | public boolean isInterface( String className ) | ||
| 181 | { | ||
| 182 | return m_interfaces.containsValue( className ); | ||
| 183 | } | ||
| 184 | |||
| 185 | private void collectSubclasses( Set<String> classNames, String className ) | ||
| 186 | { | ||
| 187 | for( String subclassName : getSubclasses( className ) ) | ||
| 188 | { | ||
| 189 | classNames.add( subclassName ); | ||
| 190 | collectSubclasses( classNames, subclassName ); | ||
| 191 | } | ||
| 192 | } | ||
| 193 | |||
| 105 | private boolean isJre( String className ) | 194 | private boolean isJre( String className ) |
| 106 | { | 195 | { |
| 107 | return className.startsWith( "java/" ) | 196 | return className.startsWith( "java/" ) |
diff --git a/src/cuchaz/enigma/analysis/ClassImplementationsTreeNode.java b/src/cuchaz/enigma/analysis/ClassImplementationsTreeNode.java new file mode 100644 index 00000000..98648305 --- /dev/null +++ b/src/cuchaz/enigma/analysis/ClassImplementationsTreeNode.java | |||
| @@ -0,0 +1,92 @@ | |||
| 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 javax.swing.tree.DefaultMutableTreeNode; | ||
| 16 | |||
| 17 | import com.google.common.collect.Lists; | ||
| 18 | |||
| 19 | import cuchaz.enigma.mapping.ClassEntry; | ||
| 20 | import cuchaz.enigma.mapping.MethodEntry; | ||
| 21 | import cuchaz.enigma.mapping.Translator; | ||
| 22 | |||
| 23 | public class ClassImplementationsTreeNode extends DefaultMutableTreeNode | ||
| 24 | { | ||
| 25 | private static final long serialVersionUID = 3112703459157851912L; | ||
| 26 | |||
| 27 | private Translator m_deobfuscatingTranslator; | ||
| 28 | private ClassEntry m_entry; | ||
| 29 | |||
| 30 | public ClassImplementationsTreeNode( Translator deobfuscatingTranslator, ClassEntry entry ) | ||
| 31 | { | ||
| 32 | m_deobfuscatingTranslator = deobfuscatingTranslator; | ||
| 33 | m_entry = entry; | ||
| 34 | } | ||
| 35 | |||
| 36 | public ClassEntry getClassEntry( ) | ||
| 37 | { | ||
| 38 | return m_entry; | ||
| 39 | } | ||
| 40 | |||
| 41 | public String getDeobfClassName( ) | ||
| 42 | { | ||
| 43 | return m_deobfuscatingTranslator.translateClass( m_entry.getClassName() ); | ||
| 44 | } | ||
| 45 | |||
| 46 | @Override | ||
| 47 | public String toString( ) | ||
| 48 | { | ||
| 49 | String className = getDeobfClassName(); | ||
| 50 | if( className == null ) | ||
| 51 | { | ||
| 52 | className = m_entry.getClassName(); | ||
| 53 | } | ||
| 54 | return className; | ||
| 55 | } | ||
| 56 | |||
| 57 | public void load( Ancestries ancestries ) | ||
| 58 | { | ||
| 59 | // get all method implementations | ||
| 60 | List<ClassImplementationsTreeNode> nodes = Lists.newArrayList(); | ||
| 61 | for( String implementingClassName : ancestries.getImplementingClasses( m_entry.getClassName() ) ) | ||
| 62 | { | ||
| 63 | nodes.add( new ClassImplementationsTreeNode( m_deobfuscatingTranslator, new ClassEntry( implementingClassName ) ) ); | ||
| 64 | } | ||
| 65 | |||
| 66 | // add them to this node | ||
| 67 | for( ClassImplementationsTreeNode node : nodes ) | ||
| 68 | { | ||
| 69 | this.add( node ); | ||
| 70 | } | ||
| 71 | } | ||
| 72 | |||
| 73 | public static ClassImplementationsTreeNode findNode( ClassImplementationsTreeNode node, MethodEntry entry ) | ||
| 74 | { | ||
| 75 | // is this the node? | ||
| 76 | if( node.m_entry.equals( entry ) ) | ||
| 77 | { | ||
| 78 | return node; | ||
| 79 | } | ||
| 80 | |||
| 81 | // recurse | ||
| 82 | for( int i=0; i<node.getChildCount(); i++ ) | ||
| 83 | { | ||
| 84 | ClassImplementationsTreeNode foundNode = findNode( (ClassImplementationsTreeNode)node.getChildAt( i ), entry ); | ||
| 85 | if( foundNode != null ) | ||
| 86 | { | ||
| 87 | return foundNode; | ||
| 88 | } | ||
| 89 | } | ||
| 90 | return null; | ||
| 91 | } | ||
| 92 | } | ||
diff --git a/src/cuchaz/enigma/analysis/JarIndex.java b/src/cuchaz/enigma/analysis/JarIndex.java index cb7508e1..eaf63528 100644 --- a/src/cuchaz/enigma/analysis/JarIndex.java +++ b/src/cuchaz/enigma/analysis/JarIndex.java | |||
| @@ -93,7 +93,12 @@ public class JarIndex | |||
| 93 | for( CtClass c : JarClassIterator.classes( jar ) ) | 93 | for( CtClass c : JarClassIterator.classes( jar ) ) |
| 94 | { | 94 | { |
| 95 | fixClass( c ); | 95 | fixClass( c ); |
| 96 | m_ancestries.addSuperclass( c.getName(), c.getClassFile().getSuperclass() ); | 96 | String className = Descriptor.toJvmName( c.getName() ); |
| 97 | m_ancestries.addSuperclass( className, Descriptor.toJvmName( c.getClassFile().getSuperclass() ) ); | ||
| 98 | for( String interfaceName : c.getClassFile().getInterfaces() ) | ||
| 99 | { | ||
| 100 | m_ancestries.addInterface( className, Descriptor.toJvmName( interfaceName ) ); | ||
| 101 | } | ||
| 97 | for( CtBehavior behavior : c.getDeclaredBehaviors() ) | 102 | for( CtBehavior behavior : c.getDeclaredBehaviors() ) |
| 98 | { | 103 | { |
| 99 | indexBehavior( behavior ); | 104 | indexBehavior( behavior ); |
| @@ -354,7 +359,6 @@ public class JarIndex | |||
| 354 | } | 359 | } |
| 355 | else if( callerClasses.size() > 1 ) | 360 | else if( callerClasses.size() > 1 ) |
| 356 | { | 361 | { |
| 357 | // TEMP | ||
| 358 | System.out.println( "WARNING: Illegal constructor called by more than one class!" + callerClasses ); | 362 | System.out.println( "WARNING: Illegal constructor called by more than one class!" + callerClasses ); |
| 359 | } | 363 | } |
| 360 | } | 364 | } |
| @@ -542,6 +546,13 @@ public class JarIndex | |||
| 542 | return rootNode; | 546 | return rootNode; |
| 543 | } | 547 | } |
| 544 | 548 | ||
| 549 | public ClassImplementationsTreeNode getClassImplementations( Translator deobfuscatingTranslator, ClassEntry obfClassEntry ) | ||
| 550 | { | ||
| 551 | ClassImplementationsTreeNode node = new ClassImplementationsTreeNode( deobfuscatingTranslator, obfClassEntry ); | ||
| 552 | node.load( m_ancestries ); | ||
| 553 | return node; | ||
| 554 | } | ||
| 555 | |||
| 545 | public MethodInheritanceTreeNode getMethodInheritance( Translator deobfuscatingTranslator, MethodEntry obfMethodEntry ) | 556 | public MethodInheritanceTreeNode getMethodInheritance( Translator deobfuscatingTranslator, MethodEntry obfMethodEntry ) |
| 546 | { | 557 | { |
| 547 | // travel to the ancestor implementation | 558 | // travel to the ancestor implementation |
| @@ -577,6 +588,90 @@ public class JarIndex | |||
| 577 | return rootNode; | 588 | return rootNode; |
| 578 | } | 589 | } |
| 579 | 590 | ||
| 591 | public MethodImplementationsTreeNode getMethodImplementations( Translator deobfuscatingTranslator, MethodEntry obfMethodEntry ) | ||
| 592 | { | ||
| 593 | MethodEntry interfaceMethodEntry; | ||
| 594 | |||
| 595 | // is this method on an interface? | ||
| 596 | if( m_ancestries.isInterface( obfMethodEntry.getClassName() ) ) | ||
| 597 | { | ||
| 598 | interfaceMethodEntry = obfMethodEntry; | ||
| 599 | } | ||
| 600 | else | ||
| 601 | { | ||
| 602 | // get the interface class | ||
| 603 | List<MethodEntry> methodInterfaces = Lists.newArrayList(); | ||
| 604 | for( String interfaceName : m_ancestries.getInterfaces( obfMethodEntry.getClassName() ) ) | ||
| 605 | { | ||
| 606 | // is this method defined in this interface? | ||
| 607 | MethodEntry methodInterface = new MethodEntry( | ||
| 608 | new ClassEntry( interfaceName ), | ||
| 609 | obfMethodEntry.getName(), | ||
| 610 | obfMethodEntry.getSignature() | ||
| 611 | ); | ||
| 612 | if( isMethodImplemented( methodInterface ) ) | ||
| 613 | { | ||
| 614 | methodInterfaces.add( methodInterface ); | ||
| 615 | } | ||
| 616 | } | ||
| 617 | if( methodInterfaces.isEmpty() ) | ||
| 618 | { | ||
| 619 | return null; | ||
| 620 | } | ||
| 621 | if( methodInterfaces.size() > 1 ) | ||
| 622 | { | ||
| 623 | throw new Error( "Too many interfaces define this method! This is not yet supported by Enigma!" ); | ||
| 624 | } | ||
| 625 | interfaceMethodEntry = methodInterfaces.get( 0 ); | ||
| 626 | } | ||
| 627 | |||
| 628 | MethodImplementationsTreeNode rootNode = new MethodImplementationsTreeNode( deobfuscatingTranslator, interfaceMethodEntry ); | ||
| 629 | rootNode.load( this ); | ||
| 630 | return rootNode; | ||
| 631 | } | ||
| 632 | |||
| 633 | public Set<MethodEntry> getRelatedMethodImplementations( MethodEntry obfMethodEntry ) | ||
| 634 | { | ||
| 635 | Set<MethodEntry> methodEntries = Sets.newHashSet(); | ||
| 636 | getRelatedMethodImplementations( methodEntries, getMethodInheritance( null, obfMethodEntry ) ); | ||
| 637 | return methodEntries; | ||
| 638 | } | ||
| 639 | |||
| 640 | private void getRelatedMethodImplementations( Set<MethodEntry> methodEntries, MethodInheritanceTreeNode node ) | ||
| 641 | { | ||
| 642 | MethodEntry methodEntry = node.getMethodEntry(); | ||
| 643 | if( isMethodImplemented( methodEntry ) ) | ||
| 644 | { | ||
| 645 | // collect the entry | ||
| 646 | methodEntries.add( methodEntry ); | ||
| 647 | } | ||
| 648 | |||
| 649 | // look at interface methods too | ||
| 650 | getRelatedMethodImplementations( methodEntries, getMethodImplementations( null, methodEntry ) ); | ||
| 651 | |||
| 652 | // recurse | ||
| 653 | for( int i=0; i<node.getChildCount(); i++ ) | ||
| 654 | { | ||
| 655 | getRelatedMethodImplementations( methodEntries, (MethodInheritanceTreeNode)node.getChildAt( i ) ); | ||
| 656 | } | ||
| 657 | } | ||
| 658 | |||
| 659 | private void getRelatedMethodImplementations( Set<MethodEntry> methodEntries, MethodImplementationsTreeNode node ) | ||
| 660 | { | ||
| 661 | MethodEntry methodEntry = node.getMethodEntry(); | ||
| 662 | if( isMethodImplemented( methodEntry ) ) | ||
| 663 | { | ||
| 664 | // collect the entry | ||
| 665 | methodEntries.add( methodEntry ); | ||
| 666 | } | ||
| 667 | |||
| 668 | // recurse | ||
| 669 | for( int i=0; i<node.getChildCount(); i++ ) | ||
| 670 | { | ||
| 671 | getRelatedMethodImplementations( methodEntries, (MethodImplementationsTreeNode)node.getChildAt( i ) ); | ||
| 672 | } | ||
| 673 | } | ||
| 674 | |||
| 580 | public Collection<EntryReference<FieldEntry,BehaviorEntry>> getFieldReferences( FieldEntry fieldEntry ) | 675 | public Collection<EntryReference<FieldEntry,BehaviorEntry>> getFieldReferences( FieldEntry fieldEntry ) |
| 581 | { | 676 | { |
| 582 | return m_fieldReferences.get( fieldEntry ); | 677 | return m_fieldReferences.get( fieldEntry ); |
| @@ -626,16 +721,14 @@ public class JarIndex | |||
| 626 | { | 721 | { |
| 627 | // for each key/value pair... | 722 | // for each key/value pair... |
| 628 | Set<Map.Entry<Key,Val>> entriesToAdd = Sets.newHashSet(); | 723 | Set<Map.Entry<Key,Val>> entriesToAdd = Sets.newHashSet(); |
| 629 | Iterator<Map.Entry<Key,Val>> iter = map.entries().iterator(); | 724 | for( Map.Entry<Key,Val> entry : map.entries() ) |
| 630 | while( iter.hasNext() ) | ||
| 631 | { | 725 | { |
| 632 | Map.Entry<Key,Val> entry = iter.next(); | ||
| 633 | iter.remove(); | ||
| 634 | entriesToAdd.add( new AbstractMap.SimpleEntry<Key,Val>( | 726 | entriesToAdd.add( new AbstractMap.SimpleEntry<Key,Val>( |
| 635 | renameClassesInThing( renames, entry.getKey() ), | 727 | renameClassesInThing( renames, entry.getKey() ), |
| 636 | renameClassesInThing( renames, entry.getValue() ) | 728 | renameClassesInThing( renames, entry.getValue() ) |
| 637 | ) ); | 729 | ) ); |
| 638 | } | 730 | } |
| 731 | map.clear(); | ||
| 639 | for( Map.Entry<Key,Val> entry : entriesToAdd ) | 732 | for( Map.Entry<Key,Val> entry : entriesToAdd ) |
| 640 | { | 733 | { |
| 641 | map.put( entry.getKey(), entry.getValue() ); | 734 | map.put( entry.getKey(), entry.getValue() ); |
| @@ -761,5 +854,5 @@ public class JarIndex | |||
| 761 | return thing; | 854 | return thing; |
| 762 | } | 855 | } |
| 763 | return thing; | 856 | return thing; |
| 764 | } | 857 | } |
| 765 | } | 858 | } |
diff --git a/src/cuchaz/enigma/analysis/MethodImplementationsTreeNode.java b/src/cuchaz/enigma/analysis/MethodImplementationsTreeNode.java new file mode 100644 index 00000000..b529f3f6 --- /dev/null +++ b/src/cuchaz/enigma/analysis/MethodImplementationsTreeNode.java | |||
| @@ -0,0 +1,111 @@ | |||
| 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 javax.swing.tree.DefaultMutableTreeNode; | ||
| 16 | |||
| 17 | import com.google.common.collect.Lists; | ||
| 18 | |||
| 19 | import cuchaz.enigma.mapping.ClassEntry; | ||
| 20 | import cuchaz.enigma.mapping.MethodEntry; | ||
| 21 | import cuchaz.enigma.mapping.Translator; | ||
| 22 | |||
| 23 | public class MethodImplementationsTreeNode extends DefaultMutableTreeNode | ||
| 24 | { | ||
| 25 | private static final long serialVersionUID = 3781080657461899915L; | ||
| 26 | |||
| 27 | private Translator m_deobfuscatingTranslator; | ||
| 28 | private MethodEntry m_entry; | ||
| 29 | |||
| 30 | public MethodImplementationsTreeNode( Translator deobfuscatingTranslator, MethodEntry entry ) | ||
| 31 | { | ||
| 32 | m_deobfuscatingTranslator = deobfuscatingTranslator; | ||
| 33 | m_entry = entry; | ||
| 34 | } | ||
| 35 | |||
| 36 | public MethodEntry getMethodEntry( ) | ||
| 37 | { | ||
| 38 | return m_entry; | ||
| 39 | } | ||
| 40 | |||
| 41 | public String getDeobfClassName( ) | ||
| 42 | { | ||
| 43 | return m_deobfuscatingTranslator.translateClass( m_entry.getClassName() ); | ||
| 44 | } | ||
| 45 | |||
| 46 | public String getDeobfMethodName( ) | ||
| 47 | { | ||
| 48 | return m_deobfuscatingTranslator.translate( m_entry ); | ||
| 49 | } | ||
| 50 | |||
| 51 | @Override | ||
| 52 | public String toString( ) | ||
| 53 | { | ||
| 54 | String className = getDeobfClassName(); | ||
| 55 | if( className == null ) | ||
| 56 | { | ||
| 57 | className = m_entry.getClassName(); | ||
| 58 | } | ||
| 59 | |||
| 60 | String methodName = getDeobfMethodName(); | ||
| 61 | if( methodName == null ) | ||
| 62 | { | ||
| 63 | methodName = m_entry.getName(); | ||
| 64 | } | ||
| 65 | return className + "." + methodName + "()"; | ||
| 66 | } | ||
| 67 | |||
| 68 | public void load( JarIndex index ) | ||
| 69 | { | ||
| 70 | // get all method implementations | ||
| 71 | List<MethodImplementationsTreeNode> nodes = Lists.newArrayList(); | ||
| 72 | for( String implementingClassName : index.getAncestries().getImplementingClasses( m_entry.getClassName() ) ) | ||
| 73 | { | ||
| 74 | MethodEntry methodEntry = new MethodEntry( | ||
| 75 | new ClassEntry( implementingClassName ), | ||
| 76 | m_entry.getName(), | ||
| 77 | m_entry.getSignature() | ||
| 78 | ); | ||
| 79 | if( index.isMethodImplemented( methodEntry ) ) | ||
| 80 | { | ||
| 81 | nodes.add( new MethodImplementationsTreeNode( m_deobfuscatingTranslator, methodEntry ) ); | ||
| 82 | } | ||
| 83 | } | ||
| 84 | |||
| 85 | // add them to this node | ||
| 86 | for( MethodImplementationsTreeNode node : nodes ) | ||
| 87 | { | ||
| 88 | this.add( node ); | ||
| 89 | } | ||
| 90 | } | ||
| 91 | |||
| 92 | public static MethodImplementationsTreeNode findNode( MethodImplementationsTreeNode node, MethodEntry entry ) | ||
| 93 | { | ||
| 94 | // is this the node? | ||
| 95 | if( node.getMethodEntry().equals( entry ) ) | ||
| 96 | { | ||
| 97 | return node; | ||
| 98 | } | ||
| 99 | |||
| 100 | // recurse | ||
| 101 | for( int i=0; i<node.getChildCount(); i++ ) | ||
| 102 | { | ||
| 103 | MethodImplementationsTreeNode foundNode = findNode( (MethodImplementationsTreeNode)node.getChildAt( i ), entry ); | ||
| 104 | if( foundNode != null ) | ||
| 105 | { | ||
| 106 | return foundNode; | ||
| 107 | } | ||
| 108 | } | ||
| 109 | return null; | ||
| 110 | } | ||
| 111 | } | ||
diff --git a/src/cuchaz/enigma/gui/Gui.java b/src/cuchaz/enigma/gui/Gui.java index 4e636064..3dcb4e24 100644 --- a/src/cuchaz/enigma/gui/Gui.java +++ b/src/cuchaz/enigma/gui/Gui.java | |||
| @@ -70,9 +70,11 @@ import com.google.common.collect.Lists; | |||
| 70 | 70 | ||
| 71 | import cuchaz.enigma.Constants; | 71 | import cuchaz.enigma.Constants; |
| 72 | import cuchaz.enigma.analysis.BehaviorReferenceTreeNode; | 72 | import cuchaz.enigma.analysis.BehaviorReferenceTreeNode; |
| 73 | import cuchaz.enigma.analysis.ClassImplementationsTreeNode; | ||
| 73 | import cuchaz.enigma.analysis.ClassInheritanceTreeNode; | 74 | import cuchaz.enigma.analysis.ClassInheritanceTreeNode; |
| 74 | import cuchaz.enigma.analysis.EntryReference; | 75 | import cuchaz.enigma.analysis.EntryReference; |
| 75 | import cuchaz.enigma.analysis.FieldReferenceTreeNode; | 76 | import cuchaz.enigma.analysis.FieldReferenceTreeNode; |
| 77 | import cuchaz.enigma.analysis.MethodImplementationsTreeNode; | ||
| 76 | import cuchaz.enigma.analysis.MethodInheritanceTreeNode; | 78 | import cuchaz.enigma.analysis.MethodInheritanceTreeNode; |
| 77 | import cuchaz.enigma.analysis.ReferenceTreeNode; | 79 | import cuchaz.enigma.analysis.ReferenceTreeNode; |
| 78 | import cuchaz.enigma.analysis.Token; | 80 | import cuchaz.enigma.analysis.Token; |
| @@ -148,6 +150,7 @@ public class Gui | |||
| 148 | private DeobfuscatedHighlightPainter m_deobfuscatedHighlightPainter; | 150 | private DeobfuscatedHighlightPainter m_deobfuscatedHighlightPainter; |
| 149 | private SelectionHighlightPainter m_selectionHighlightPainter; | 151 | private SelectionHighlightPainter m_selectionHighlightPainter; |
| 150 | private JTree m_inheritanceTree; | 152 | private JTree m_inheritanceTree; |
| 153 | private JTree m_implementationsTree; | ||
| 151 | private JTree m_callsTree; | 154 | private JTree m_callsTree; |
| 152 | private JList<Token> m_tokens; | 155 | private JList<Token> m_tokens; |
| 153 | private JTabbedPane m_tabs; | 156 | private JTabbedPane m_tabs; |
| @@ -163,6 +166,7 @@ public class Gui | |||
| 163 | private JMenuItem m_openEntryMenu; | 166 | private JMenuItem m_openEntryMenu; |
| 164 | private JMenuItem m_openPreviousMenu; | 167 | private JMenuItem m_openPreviousMenu; |
| 165 | private JMenuItem m_showCallsMenu; | 168 | private JMenuItem m_showCallsMenu; |
| 169 | private JMenuItem m_showImplementationsMenu; | ||
| 166 | 170 | ||
| 167 | // state | 171 | // state |
| 168 | private EntryReference<Entry,Entry> m_reference; | 172 | private EntryReference<Entry,Entry> m_reference; |
| @@ -285,6 +289,10 @@ public class Gui | |||
| 285 | showInheritance(); | 289 | showInheritance(); |
| 286 | break; | 290 | break; |
| 287 | 291 | ||
| 292 | case KeyEvent.VK_M: | ||
| 293 | showImplementations(); | ||
| 294 | break; | ||
| 295 | |||
| 288 | case KeyEvent.VK_N: | 296 | case KeyEvent.VK_N: |
| 289 | openDeclaration(); | 297 | openDeclaration(); |
| 290 | break; | 298 | break; |
| @@ -338,6 +346,21 @@ public class Gui | |||
| 338 | m_showInheritanceMenu = menu; | 346 | m_showInheritanceMenu = menu; |
| 339 | } | 347 | } |
| 340 | { | 348 | { |
| 349 | JMenuItem menu = new JMenuItem( "Show Implementations" ); | ||
| 350 | menu.addActionListener( new ActionListener( ) | ||
| 351 | { | ||
| 352 | @Override | ||
| 353 | public void actionPerformed( ActionEvent event ) | ||
| 354 | { | ||
| 355 | showImplementations(); | ||
| 356 | } | ||
| 357 | } ); | ||
| 358 | menu.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_M, 0 ) ); | ||
| 359 | menu.setEnabled( false ); | ||
| 360 | popupMenu.add( menu ); | ||
| 361 | m_showImplementationsMenu = menu; | ||
| 362 | } | ||
| 363 | { | ||
| 341 | JMenuItem menu = new JMenuItem( "Show Calls" ); | 364 | JMenuItem menu = new JMenuItem( "Show Calls" ); |
| 342 | menu.addActionListener( new ActionListener( ) | 365 | menu.addActionListener( new ActionListener( ) |
| 343 | { | 366 | { |
| @@ -428,6 +451,41 @@ public class Gui | |||
| 428 | inheritancePanel.setLayout( new BorderLayout() ); | 451 | inheritancePanel.setLayout( new BorderLayout() ); |
| 429 | inheritancePanel.add( new JScrollPane( m_inheritanceTree ) ); | 452 | inheritancePanel.add( new JScrollPane( m_inheritanceTree ) ); |
| 430 | 453 | ||
| 454 | // init implementations panel | ||
| 455 | m_implementationsTree = new JTree(); | ||
| 456 | m_implementationsTree.setModel( null ); | ||
| 457 | m_implementationsTree.addMouseListener( new MouseAdapter( ) | ||
| 458 | { | ||
| 459 | @Override | ||
| 460 | public void mouseClicked( MouseEvent event ) | ||
| 461 | { | ||
| 462 | if( event.getClickCount() == 2 ) | ||
| 463 | { | ||
| 464 | // get the selected node | ||
| 465 | TreePath path = m_implementationsTree.getSelectionPath(); | ||
| 466 | if( path == null ) | ||
| 467 | { | ||
| 468 | return; | ||
| 469 | } | ||
| 470 | |||
| 471 | Object node = path.getLastPathComponent(); | ||
| 472 | if( node instanceof ClassImplementationsTreeNode ) | ||
| 473 | { | ||
| 474 | ClassImplementationsTreeNode classNode = (ClassImplementationsTreeNode)node; | ||
| 475 | m_controller.openDeclaration( classNode.getClassEntry() ); | ||
| 476 | } | ||
| 477 | else if( node instanceof MethodImplementationsTreeNode ) | ||
| 478 | { | ||
| 479 | MethodImplementationsTreeNode methodNode = (MethodImplementationsTreeNode)node; | ||
| 480 | m_controller.openDeclaration( methodNode.getMethodEntry() ); | ||
| 481 | } | ||
| 482 | } | ||
| 483 | } | ||
| 484 | } ); | ||
| 485 | JPanel implementationsPanel = new JPanel(); | ||
| 486 | implementationsPanel.setLayout( new BorderLayout() ); | ||
| 487 | implementationsPanel.add( new JScrollPane( m_implementationsTree ) ); | ||
| 488 | |||
| 431 | // init call panel | 489 | // init call panel |
| 432 | m_callsTree = new JTree(); | 490 | m_callsTree = new JTree(); |
| 433 | m_callsTree.setModel( null ); | 491 | m_callsTree.setModel( null ); |
| @@ -501,6 +559,7 @@ public class Gui | |||
| 501 | m_tabs = new JTabbedPane(); | 559 | m_tabs = new JTabbedPane(); |
| 502 | m_tabs.setPreferredSize( new Dimension( 250, 0 ) ); | 560 | m_tabs.setPreferredSize( new Dimension( 250, 0 ) ); |
| 503 | m_tabs.addTab( "Inheritance", inheritancePanel ); | 561 | m_tabs.addTab( "Inheritance", inheritancePanel ); |
| 562 | m_tabs.addTab( "Implementations", implementationsPanel ); | ||
| 504 | m_tabs.addTab( "Call Graph", callPanel ); | 563 | m_tabs.addTab( "Call Graph", callPanel ); |
| 505 | JSplitPane splitRight = new JSplitPane( JSplitPane.HORIZONTAL_SPLIT, true, centerPanel, m_tabs ); | 564 | JSplitPane splitRight = new JSplitPane( JSplitPane.HORIZONTAL_SPLIT, true, centerPanel, m_tabs ); |
| 506 | splitRight.setResizeWeight( 1 ); // let the left side take all the slack | 565 | splitRight.setResizeWeight( 1 ); // let the left side take all the slack |
| @@ -1023,6 +1082,7 @@ public class Gui | |||
| 1023 | 1082 | ||
| 1024 | m_renameMenu.setEnabled( isToken ); | 1083 | m_renameMenu.setEnabled( isToken ); |
| 1025 | m_showInheritanceMenu.setEnabled( isClassEntry || isMethodEntry || isConstructorEntry ); | 1084 | m_showInheritanceMenu.setEnabled( isClassEntry || isMethodEntry || isConstructorEntry ); |
| 1085 | m_showImplementationsMenu.setEnabled( isClassEntry || isMethodEntry ); | ||
| 1026 | m_showCallsMenu.setEnabled( isFieldEntry || isMethodEntry || isConstructorEntry ); | 1086 | m_showCallsMenu.setEnabled( isFieldEntry || isMethodEntry || isConstructorEntry ); |
| 1027 | m_openEntryMenu.setEnabled( isClassEntry || isFieldEntry || isMethodEntry || isConstructorEntry ); | 1087 | m_openEntryMenu.setEnabled( isClassEntry || isFieldEntry || isMethodEntry || isConstructorEntry ); |
| 1028 | m_openPreviousMenu.setEnabled( m_controller.hasPreviousLocation() ); | 1088 | m_openPreviousMenu.setEnabled( m_controller.hasPreviousLocation() ); |
| @@ -1097,6 +1157,8 @@ public class Gui | |||
| 1097 | return; | 1157 | return; |
| 1098 | } | 1158 | } |
| 1099 | 1159 | ||
| 1160 | m_inheritanceTree.setModel( null ); | ||
| 1161 | |||
| 1100 | if( m_reference.entry instanceof ClassEntry ) | 1162 | if( m_reference.entry instanceof ClassEntry ) |
| 1101 | { | 1163 | { |
| 1102 | // get the class inheritance | 1164 | // get the class inheritance |
| @@ -1124,6 +1186,46 @@ public class Gui | |||
| 1124 | redraw(); | 1186 | redraw(); |
| 1125 | } | 1187 | } |
| 1126 | 1188 | ||
| 1189 | private void showImplementations( ) | ||
| 1190 | { | ||
| 1191 | if( m_reference == null ) | ||
| 1192 | { | ||
| 1193 | return; | ||
| 1194 | } | ||
| 1195 | |||
| 1196 | m_implementationsTree.setModel( null ); | ||
| 1197 | |||
| 1198 | if( m_reference.entry instanceof ClassEntry ) | ||
| 1199 | { | ||
| 1200 | // get the class implementations | ||
| 1201 | ClassImplementationsTreeNode node = m_controller.getClassImplementations( (ClassEntry)m_reference.entry ); | ||
| 1202 | if( node != null ) | ||
| 1203 | { | ||
| 1204 | // show the tree at the root | ||
| 1205 | TreePath path = getPathToRoot( node ); | ||
| 1206 | m_implementationsTree.setModel( new DefaultTreeModel( (TreeNode)path.getPathComponent( 0 ) ) ); | ||
| 1207 | m_implementationsTree.expandPath( path ); | ||
| 1208 | m_implementationsTree.setSelectionRow( m_implementationsTree.getRowForPath( path ) ); | ||
| 1209 | } | ||
| 1210 | } | ||
| 1211 | else if( m_reference.entry instanceof MethodEntry ) | ||
| 1212 | { | ||
| 1213 | // get the method implementations | ||
| 1214 | MethodImplementationsTreeNode node = m_controller.getMethodImplementations( (MethodEntry)m_reference.entry ); | ||
| 1215 | if( node != null ) | ||
| 1216 | { | ||
| 1217 | // show the tree at the root | ||
| 1218 | TreePath path = getPathToRoot( node ); | ||
| 1219 | m_implementationsTree.setModel( new DefaultTreeModel( (TreeNode)path.getPathComponent( 0 ) ) ); | ||
| 1220 | m_implementationsTree.expandPath( path ); | ||
| 1221 | m_implementationsTree.setSelectionRow( m_implementationsTree.getRowForPath( path ) ); | ||
| 1222 | } | ||
| 1223 | } | ||
| 1224 | |||
| 1225 | m_tabs.setSelectedIndex( 1 ); | ||
| 1226 | redraw(); | ||
| 1227 | } | ||
| 1228 | |||
| 1127 | private void showCalls( ) | 1229 | private void showCalls( ) |
| 1128 | { | 1230 | { |
| 1129 | if( m_reference == null ) | 1231 | if( m_reference == null ) |
| @@ -1147,7 +1249,7 @@ public class Gui | |||
| 1147 | m_callsTree.setModel( new DefaultTreeModel( node ) ); | 1249 | m_callsTree.setModel( new DefaultTreeModel( node ) ); |
| 1148 | } | 1250 | } |
| 1149 | 1251 | ||
| 1150 | m_tabs.setSelectedIndex( 1 ); | 1252 | m_tabs.setSelectedIndex( 2 ); |
| 1151 | redraw(); | 1253 | redraw(); |
| 1152 | } | 1254 | } |
| 1153 | 1255 | ||
diff --git a/src/cuchaz/enigma/gui/GuiController.java b/src/cuchaz/enigma/gui/GuiController.java index 90bce520..bd79e480 100644 --- a/src/cuchaz/enigma/gui/GuiController.java +++ b/src/cuchaz/enigma/gui/GuiController.java | |||
| @@ -24,9 +24,11 @@ import com.strobel.decompiler.languages.java.ast.CompilationUnit; | |||
| 24 | 24 | ||
| 25 | import cuchaz.enigma.Deobfuscator; | 25 | import cuchaz.enigma.Deobfuscator; |
| 26 | import cuchaz.enigma.analysis.BehaviorReferenceTreeNode; | 26 | import cuchaz.enigma.analysis.BehaviorReferenceTreeNode; |
| 27 | import cuchaz.enigma.analysis.ClassImplementationsTreeNode; | ||
| 27 | import cuchaz.enigma.analysis.ClassInheritanceTreeNode; | 28 | import cuchaz.enigma.analysis.ClassInheritanceTreeNode; |
| 28 | import cuchaz.enigma.analysis.EntryReference; | 29 | import cuchaz.enigma.analysis.EntryReference; |
| 29 | import cuchaz.enigma.analysis.FieldReferenceTreeNode; | 30 | import cuchaz.enigma.analysis.FieldReferenceTreeNode; |
| 31 | import cuchaz.enigma.analysis.MethodImplementationsTreeNode; | ||
| 30 | import cuchaz.enigma.analysis.MethodInheritanceTreeNode; | 32 | import cuchaz.enigma.analysis.MethodInheritanceTreeNode; |
| 31 | import cuchaz.enigma.analysis.SourceIndex; | 33 | import cuchaz.enigma.analysis.SourceIndex; |
| 32 | import cuchaz.enigma.analysis.Token; | 34 | import cuchaz.enigma.analysis.Token; |
| @@ -182,6 +184,15 @@ public class GuiController | |||
| 182 | return ClassInheritanceTreeNode.findNode( rootNode, obfClassEntry ); | 184 | return ClassInheritanceTreeNode.findNode( rootNode, obfClassEntry ); |
| 183 | } | 185 | } |
| 184 | 186 | ||
| 187 | public ClassImplementationsTreeNode getClassImplementations( ClassEntry deobfClassEntry ) | ||
| 188 | { | ||
| 189 | ClassEntry obfClassEntry = m_deobfuscator.obfuscateEntry( deobfClassEntry ); | ||
| 190 | return m_deobfuscator.getJarIndex().getClassImplementations( | ||
| 191 | m_deobfuscator.getTranslator( TranslationDirection.Deobfuscating ), | ||
| 192 | obfClassEntry | ||
| 193 | ); | ||
| 194 | } | ||
| 195 | |||
| 185 | public MethodInheritanceTreeNode getMethodInheritance( MethodEntry deobfMethodEntry ) | 196 | public MethodInheritanceTreeNode getMethodInheritance( MethodEntry deobfMethodEntry ) |
| 186 | { | 197 | { |
| 187 | MethodEntry obfMethodEntry = m_deobfuscator.obfuscateEntry( deobfMethodEntry ); | 198 | MethodEntry obfMethodEntry = m_deobfuscator.obfuscateEntry( deobfMethodEntry ); |
| @@ -192,6 +203,20 @@ public class GuiController | |||
| 192 | return MethodInheritanceTreeNode.findNode( rootNode, obfMethodEntry ); | 203 | return MethodInheritanceTreeNode.findNode( rootNode, obfMethodEntry ); |
| 193 | } | 204 | } |
| 194 | 205 | ||
| 206 | public MethodImplementationsTreeNode getMethodImplementations( MethodEntry deobfMethodEntry ) | ||
| 207 | { | ||
| 208 | MethodEntry obfMethodEntry = m_deobfuscator.obfuscateEntry( deobfMethodEntry ); | ||
| 209 | MethodImplementationsTreeNode rootNode = m_deobfuscator.getJarIndex().getMethodImplementations( | ||
| 210 | m_deobfuscator.getTranslator( TranslationDirection.Deobfuscating ), | ||
| 211 | obfMethodEntry | ||
| 212 | ); | ||
| 213 | if( rootNode == null ) | ||
| 214 | { | ||
| 215 | return null; | ||
| 216 | } | ||
| 217 | return MethodImplementationsTreeNode.findNode( rootNode, obfMethodEntry ); | ||
| 218 | } | ||
| 219 | |||
| 195 | public FieldReferenceTreeNode getFieldReferences( FieldEntry deobfFieldEntry ) | 220 | public FieldReferenceTreeNode getFieldReferences( FieldEntry deobfFieldEntry ) |
| 196 | { | 221 | { |
| 197 | FieldEntry obfFieldEntry = m_deobfuscator.obfuscateEntry( deobfFieldEntry ); | 222 | FieldEntry obfFieldEntry = m_deobfuscator.obfuscateEntry( deobfFieldEntry ); |
diff --git a/src/cuchaz/enigma/mapping/Renamer.java b/src/cuchaz/enigma/mapping/Renamer.java index 0bb8dc12..79cbd30d 100644 --- a/src/cuchaz/enigma/mapping/Renamer.java +++ b/src/cuchaz/enigma/mapping/Renamer.java | |||
| @@ -16,7 +16,6 @@ import java.io.OutputStream; | |||
| 16 | import java.util.zip.GZIPOutputStream; | 16 | import java.util.zip.GZIPOutputStream; |
| 17 | 17 | ||
| 18 | import cuchaz.enigma.analysis.JarIndex; | 18 | import cuchaz.enigma.analysis.JarIndex; |
| 19 | import cuchaz.enigma.analysis.MethodInheritanceTreeNode; | ||
| 20 | 19 | ||
| 21 | public class Renamer | 20 | public class Renamer |
| 22 | { | 21 | { |
| @@ -57,25 +56,9 @@ public class Renamer | |||
| 57 | 56 | ||
| 58 | public void setMethodTreeName( MethodEntry obf, String deobfName ) | 57 | public void setMethodTreeName( MethodEntry obf, String deobfName ) |
| 59 | { | 58 | { |
| 60 | // get the method tree | 59 | for( MethodEntry entry : m_index.getRelatedMethodImplementations( obf ) ) |
| 61 | setMethodTreeName( | ||
| 62 | m_index.getMethodInheritance( m_mappings.getTranslator( m_index.getAncestries(), TranslationDirection.Deobfuscating ), obf ), | ||
| 63 | deobfName | ||
| 64 | ); | ||
| 65 | } | ||
| 66 | |||
| 67 | private void setMethodTreeName( MethodInheritanceTreeNode node, String deobfName ) | ||
| 68 | { | ||
| 69 | if( node.isImplemented() ) | ||
| 70 | { | ||
| 71 | // apply the name here | ||
| 72 | setMethodName( node.getMethodEntry(), deobfName ); | ||
| 73 | } | ||
| 74 | |||
| 75 | // recurse | ||
| 76 | for( int i=0; i<node.getChildCount(); i++ ) | ||
| 77 | { | 60 | { |
| 78 | setMethodTreeName( (MethodInheritanceTreeNode)node.getChildAt( i ), deobfName ); | 61 | setMethodName( entry, deobfName ); |
| 79 | } | 62 | } |
| 80 | } | 63 | } |
| 81 | 64 | ||