summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar jeff2014-08-12 00:24:11 -0400
committerGravatar jeff2014-08-12 00:24:11 -0400
commit52bb7ba51ceaf65f40e5e3e2de9d1ac3f7fc9c2e (patch)
tree52a89485240cb15318adb29a340ed5dc9056bc8c
parentfix keyboard shortcuts (diff)
downloadenigma-fork-52bb7ba51ceaf65f40e5e3e2de9d1ac3f7fc9c2e.tar.gz
enigma-fork-52bb7ba51ceaf65f40e5e3e2de9d1ac3f7fc9c2e.tar.xz
enigma-fork-52bb7ba51ceaf65f40e5e3e2de9d1ac3f7fc9c2e.zip
got simple method call graph working!
-rw-r--r--src/cuchaz/enigma/Deobfuscator.java34
-rw-r--r--src/cuchaz/enigma/analysis/JarIndex.java101
-rw-r--r--src/cuchaz/enigma/analysis/MethodCallsTreeNode.java96
-rw-r--r--src/cuchaz/enigma/gui/Gui.java93
-rw-r--r--src/cuchaz/enigma/gui/GuiController.java11
5 files changed, 284 insertions, 51 deletions
diff --git a/src/cuchaz/enigma/Deobfuscator.java b/src/cuchaz/enigma/Deobfuscator.java
index c35a483..33eef08 100644
--- a/src/cuchaz/enigma/Deobfuscator.java
+++ b/src/cuchaz/enigma/Deobfuscator.java
@@ -15,12 +15,9 @@ import java.io.FileInputStream;
15import java.io.IOException; 15import java.io.IOException;
16import java.io.InputStream; 16import java.io.InputStream;
17import java.io.StringWriter; 17import java.io.StringWriter;
18import java.util.Enumeration;
19import java.util.List; 18import java.util.List;
20import java.util.jar.JarEntry;
21import java.util.jar.JarFile; 19import java.util.jar.JarFile;
22 20
23import com.google.common.collect.Lists;
24import com.strobel.assembler.metadata.MetadataSystem; 21import com.strobel.assembler.metadata.MetadataSystem;
25import com.strobel.assembler.metadata.TypeDefinition; 22import com.strobel.assembler.metadata.TypeDefinition;
26import com.strobel.decompiler.DecompilerContext; 23import com.strobel.decompiler.DecompilerContext;
@@ -53,7 +50,6 @@ public class Deobfuscator
53 private JarIndex m_jarIndex; 50 private JarIndex m_jarIndex;
54 private Mappings m_mappings; 51 private Mappings m_mappings;
55 private Renamer m_renamer; 52 private Renamer m_renamer;
56 private List<String> m_obfClassNames;
57 53
58 public Deobfuscator( File file ) 54 public Deobfuscator( File file )
59 throws IOException 55 throws IOException
@@ -65,7 +61,7 @@ public class Deobfuscator
65 InputStream jarIn = null; 61 InputStream jarIn = null;
66 try 62 try
67 { 63 {
68 m_jarIndex = new JarIndex(); 64 m_jarIndex = new JarIndex( m_jar );
69 jarIn = new FileInputStream( m_file ); 65 jarIn = new FileInputStream( m_file );
70 m_jarIndex.indexJar( jarIn ); 66 m_jarIndex.indexJar( jarIn );
71 } 67 }
@@ -74,26 +70,6 @@ public class Deobfuscator
74 Util.closeQuietly( jarIn ); 70 Util.closeQuietly( jarIn );
75 } 71 }
76 72
77 // get the obf class names
78 m_obfClassNames = Lists.newArrayList();
79 {
80 Enumeration<JarEntry> entries = m_jar.entries();
81 while( entries.hasMoreElements() )
82 {
83 JarEntry entry = entries.nextElement();
84
85 // skip everything but class files
86 if( !entry.getName().endsWith( ".class" ) )
87 {
88 continue;
89 }
90
91 // get the class name from the file
92 String className = entry.getName().substring( 0, entry.getName().length() - 6 );
93 m_obfClassNames.add( className );
94 }
95 }
96
97 // config the decompiler 73 // config the decompiler
98 m_settings = DecompilerSettings.javaDefaults(); 74 m_settings = DecompilerSettings.javaDefaults();
99 m_settings.setShowSyntheticMembers( true ); 75 m_settings.setShowSyntheticMembers( true );
@@ -140,7 +116,7 @@ public class Deobfuscator
140 116
141 public void getSeparatedClasses( List<String> obfClasses, List<String> deobfClasses ) 117 public void getSeparatedClasses( List<String> obfClasses, List<String> deobfClasses )
142 { 118 {
143 for( String obfClassName : m_obfClassNames ) 119 for( String obfClassName : m_jarIndex.getObfClassNames() )
144 { 120 {
145 // separate the classes 121 // separate the classes
146 ClassMapping classMapping = m_mappings.getClassByObf( obfClassName ); 122 ClassMapping classMapping = m_mappings.getClassByObf( obfClassName );
@@ -302,15 +278,15 @@ public class Deobfuscator
302 if( obfEntry instanceof ClassEntry ) 278 if( obfEntry instanceof ClassEntry )
303 { 279 {
304 // obf classes must be in the list 280 // obf classes must be in the list
305 return m_obfClassNames.contains( obfEntry.getName() ); 281 return m_jarIndex.getObfClassNames().contains( obfEntry.getName() );
306 } 282 }
307 else if( obfEntry instanceof FieldEntry ) 283 else if( obfEntry instanceof FieldEntry )
308 { 284 {
309 return m_obfClassNames.contains( ((FieldEntry)obfEntry).getClassName() ); 285 return m_jarIndex.getObfClassNames().contains( ((FieldEntry)obfEntry).getClassName() );
310 } 286 }
311 else if( obfEntry instanceof MethodEntry ) 287 else if( obfEntry instanceof MethodEntry )
312 { 288 {
313 return m_obfClassNames.contains( ((MethodEntry)obfEntry).getClassName() ); 289 return m_jarIndex.getObfClassNames().contains( ((MethodEntry)obfEntry).getClassName() );
314 } 290 }
315 else if( obfEntry instanceof ArgumentEntry ) 291 else if( obfEntry instanceof ArgumentEntry )
316 { 292 {
diff --git a/src/cuchaz/enigma/analysis/JarIndex.java b/src/cuchaz/enigma/analysis/JarIndex.java
index 8a8384c..06b0173 100644
--- a/src/cuchaz/enigma/analysis/JarIndex.java
+++ b/src/cuchaz/enigma/analysis/JarIndex.java
@@ -14,19 +14,28 @@ import java.io.ByteArrayOutputStream;
14import java.io.IOException; 14import java.io.IOException;
15import java.io.InputStream; 15import java.io.InputStream;
16import java.util.Collection; 16import java.util.Collection;
17import java.util.Enumeration;
17import java.util.List; 18import java.util.List;
19import java.util.Set;
20import java.util.jar.JarEntry;
21import java.util.jar.JarFile;
18import java.util.zip.ZipEntry; 22import java.util.zip.ZipEntry;
19import java.util.zip.ZipInputStream; 23import java.util.zip.ZipInputStream;
20 24
21import com.google.common.collect.HashMultimap;
22import com.google.common.collect.Multimap;
23
24import javassist.ByteArrayClassPath; 25import javassist.ByteArrayClassPath;
26import javassist.CannotCompileException;
25import javassist.ClassPool; 27import javassist.ClassPool;
28import javassist.CtBehavior;
26import javassist.CtClass; 29import javassist.CtClass;
27import javassist.NotFoundException; 30import javassist.NotFoundException;
28import javassist.bytecode.Descriptor; 31import javassist.bytecode.Descriptor;
29import javassist.bytecode.MethodInfo; 32import javassist.expr.ExprEditor;
33import javassist.expr.MethodCall;
34
35import com.google.common.collect.HashMultimap;
36import com.google.common.collect.Multimap;
37import com.google.common.collect.Sets;
38
30import cuchaz.enigma.Constants; 39import cuchaz.enigma.Constants;
31import cuchaz.enigma.mapping.ClassEntry; 40import cuchaz.enigma.mapping.ClassEntry;
32import cuchaz.enigma.mapping.MethodEntry; 41import cuchaz.enigma.mapping.MethodEntry;
@@ -34,16 +43,35 @@ import cuchaz.enigma.mapping.Translator;
34 43
35public class JarIndex 44public class JarIndex
36{ 45{
46 private Set<String> m_obfClassNames;
37 private Ancestries m_ancestries; 47 private Ancestries m_ancestries;
38 private Multimap<String,String> m_methodImplementations; 48 private Multimap<String,MethodEntry> m_methodImplementations;
49 private Multimap<MethodEntry,MethodEntry> m_methodCalls;
39 50
40 public JarIndex( ) 51 public JarIndex( JarFile jar )
41 { 52 {
53 m_obfClassNames = Sets.newHashSet();
42 m_ancestries = new Ancestries(); 54 m_ancestries = new Ancestries();
43 m_methodImplementations = HashMultimap.create(); 55 m_methodImplementations = HashMultimap.create();
56 m_methodCalls = HashMultimap.create();
57
58 // read the class names
59 Enumeration<JarEntry> enumeration = jar.entries();
60 while( enumeration.hasMoreElements() )
61 {
62 JarEntry entry = enumeration.nextElement();
63
64 // filter out non-classes
65 if( entry.isDirectory() || !entry.getName().endsWith( ".class" ) )
66 {
67 continue;
68 }
69
70 String className = entry.getName().substring( 0, entry.getName().length() - 6 );
71 m_obfClassNames.add( Descriptor.toJvmName( className ) );
72 }
44 } 73 }
45 74
46 @SuppressWarnings( "unchecked" )
47 public void indexJar( InputStream in ) 75 public void indexJar( InputStream in )
48 throws IOException 76 throws IOException
49 { 77 {
@@ -89,7 +117,10 @@ public class JarIndex
89 { 117 {
90 CtClass c = classPool.get( className ); 118 CtClass c = classPool.get( className );
91 m_ancestries.addSuperclass( c.getName(), c.getClassFile().getSuperclass() ); 119 m_ancestries.addSuperclass( c.getName(), c.getClassFile().getSuperclass() );
92 addMethodImplementations( c.getName(), (List<MethodInfo>)c.getClassFile().getMethods() ); 120 for( CtBehavior behavior : c.getDeclaredBehaviors() )
121 {
122 indexBehavior( behavior );
123 }
93 } 124 }
94 catch( NotFoundException ex ) 125 catch( NotFoundException ex )
95 { 126 {
@@ -98,14 +129,55 @@ public class JarIndex
98 } 129 }
99 } 130 }
100 131
101 private void addMethodImplementations( String name, List<MethodInfo> methods ) 132 private void indexBehavior( CtBehavior behavior )
102 { 133 {
103 for( MethodInfo method : methods ) 134 // get the method entry
135 String className = Descriptor.toJvmName( behavior.getDeclaringClass().getName() );
136 final MethodEntry methodEntry = new MethodEntry(
137 new ClassEntry( className ),
138 behavior.getName(),
139 behavior.getSignature()
140 );
141
142 // index implementation
143 m_methodImplementations.put( className, methodEntry );
144
145 // index method calls
146 try
147 {
148 behavior.instrument( new ExprEditor( )
149 {
150 @Override
151 public void edit( MethodCall call )
152 {
153 // is this a jar class?
154 String className = Descriptor.toJvmName( call.getClassName() );
155 if( !m_obfClassNames.contains( className ) )
156 {
157 return;
158 }
159
160 // make entry for the called method
161 MethodEntry calledMethodEntry = new MethodEntry(
162 new ClassEntry( className ),
163 call.getMethodName(),
164 call.getSignature()
165 );
166 m_methodCalls.put( calledMethodEntry, methodEntry );
167 }
168 } );
169 }
170 catch( CannotCompileException ex )
104 { 171 {
105 m_methodImplementations.put( name, getMethodKey( method.getName(), method.getDescriptor() ) ); 172 throw new Error( ex );
106 } 173 }
107 } 174 }
108 175
176 public Set<String> getObfClassNames( )
177 {
178 return m_obfClassNames;
179 }
180
109 public Ancestries getAncestries( ) 181 public Ancestries getAncestries( )
110 { 182 {
111 return m_ancestries; 183 return m_ancestries;
@@ -118,7 +190,7 @@ public class JarIndex
118 190
119 public boolean isMethodImplemented( String className, String methodName, String methodSignature ) 191 public boolean isMethodImplemented( String className, String methodName, String methodSignature )
120 { 192 {
121 Collection<String> implementations = m_methodImplementations.get( className ); 193 Collection<MethodEntry> implementations = m_methodImplementations.get( className );
122 if( implementations == null ) 194 if( implementations == null )
123 { 195 {
124 return false; 196 return false;
@@ -169,6 +241,11 @@ public class JarIndex
169 return rootNode; 241 return rootNode;
170 } 242 }
171 243
244 public Collection<MethodEntry> getMethodCallers( MethodEntry methodEntry )
245 {
246 return m_methodCalls.get( methodEntry );
247 }
248
172 private String getMethodKey( String name, String signature ) 249 private String getMethodKey( String name, String signature )
173 { 250 {
174 return name + signature; 251 return name + signature;
diff --git a/src/cuchaz/enigma/analysis/MethodCallsTreeNode.java b/src/cuchaz/enigma/analysis/MethodCallsTreeNode.java
new file mode 100644
index 0000000..dedfb2e
--- /dev/null
+++ b/src/cuchaz/enigma/analysis/MethodCallsTreeNode.java
@@ -0,0 +1,96 @@
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 ******************************************************************************/
11package cuchaz.enigma.analysis;
12
13import java.util.List;
14
15import javax.swing.tree.DefaultMutableTreeNode;
16
17import com.google.common.collect.Lists;
18
19import cuchaz.enigma.mapping.MethodEntry;
20import cuchaz.enigma.mapping.Translator;
21
22public class MethodCallsTreeNode extends DefaultMutableTreeNode
23{
24 private static final long serialVersionUID = -3658163700783307520L;
25
26 private Translator m_deobfuscatingTranslator;
27 private MethodEntry m_entry;
28
29 public MethodCallsTreeNode( Translator deobfuscatingTranslator, MethodEntry entry )
30 {
31 m_deobfuscatingTranslator = deobfuscatingTranslator;
32 m_entry = entry;
33 }
34
35 public MethodEntry getMethodEntry( )
36 {
37 return m_entry;
38 }
39
40 public String getDeobfClassName( )
41 {
42 return m_deobfuscatingTranslator.translateClass( m_entry.getClassName() );
43 }
44
45 public String getDeobfMethodName( )
46 {
47 return m_deobfuscatingTranslator.translate( m_entry );
48 }
49
50 @Override
51 public String toString( )
52 {
53 String className = getDeobfClassName();
54 if( className == null )
55 {
56 className = m_entry.getClassName();
57 }
58
59 String methodName = getDeobfMethodName();
60 if( methodName == null )
61 {
62 methodName = m_entry.getName();
63 }
64 return className + "." + methodName + "()";
65 }
66
67 public void load( JarIndex index, boolean recurse )
68 {
69 // get all the child nodes
70 List<MethodCallsTreeNode> nodes = Lists.newArrayList();
71 for( MethodEntry entry : index.getMethodCallers( m_entry ) )
72 {
73 nodes.add( new MethodCallsTreeNode( m_deobfuscatingTranslator, entry ) );
74 }
75
76 // add them to this node
77 for( MethodCallsTreeNode node : nodes )
78 {
79 this.add( node );
80 }
81
82 if( recurse )
83 {
84 for( MethodCallsTreeNode node : nodes )
85 {
86 // don't recurse into self
87 if( node.getMethodEntry().equals( m_entry ) )
88 {
89 continue;
90 }
91
92 node.load( index, true );
93 }
94 }
95 }
96}
diff --git a/src/cuchaz/enigma/gui/Gui.java b/src/cuchaz/enigma/gui/Gui.java
index 3e8a18c..072fb3a 100644
--- a/src/cuchaz/enigma/gui/Gui.java
+++ b/src/cuchaz/enigma/gui/Gui.java
@@ -67,6 +67,7 @@ import com.google.common.collect.Lists;
67 67
68import cuchaz.enigma.Constants; 68import cuchaz.enigma.Constants;
69import cuchaz.enigma.analysis.ClassInheritanceTreeNode; 69import cuchaz.enigma.analysis.ClassInheritanceTreeNode;
70import cuchaz.enigma.analysis.MethodCallsTreeNode;
70import cuchaz.enigma.analysis.MethodInheritanceTreeNode; 71import cuchaz.enigma.analysis.MethodInheritanceTreeNode;
71import cuchaz.enigma.analysis.Token; 72import cuchaz.enigma.analysis.Token;
72import cuchaz.enigma.mapping.ArgumentEntry; 73import cuchaz.enigma.mapping.ArgumentEntry;
@@ -139,6 +140,8 @@ public class Gui
139 private BoxHighlightPainter m_obfuscatedHighlightPainter; 140 private BoxHighlightPainter m_obfuscatedHighlightPainter;
140 private BoxHighlightPainter m_deobfuscatedHighlightPainter; 141 private BoxHighlightPainter m_deobfuscatedHighlightPainter;
141 private JTree m_inheritanceTree; 142 private JTree m_inheritanceTree;
143 private JTree m_callsTree;
144 private JTabbedPane m_tabs;
142 145
143 // dynamic menu items 146 // dynamic menu items
144 private JMenuItem m_closeJarMenu; 147 private JMenuItem m_closeJarMenu;
@@ -147,9 +150,10 @@ public class Gui
147 private JMenuItem m_saveMappingsAsMenu; 150 private JMenuItem m_saveMappingsAsMenu;
148 private JMenuItem m_closeMappingsMenu; 151 private JMenuItem m_closeMappingsMenu;
149 private JMenuItem m_renameMenu; 152 private JMenuItem m_renameMenu;
150 private JMenuItem m_inheritanceMenu; 153 private JMenuItem m_showInheritanceMenu;
151 private JMenuItem m_openEntryMenu; 154 private JMenuItem m_openEntryMenu;
152 private JMenuItem m_openPreviousMenu; 155 private JMenuItem m_openPreviousMenu;
156 private JMenuItem m_showCallsMenu;
153 157
154 // state 158 // state
155 private EntryPair<Entry> m_selectedEntryPair; 159 private EntryPair<Entry> m_selectedEntryPair;
@@ -267,6 +271,10 @@ public class Gui
267 case KeyEvent.VK_P: 271 case KeyEvent.VK_P:
268 m_controller.openPreviousEntry(); 272 m_controller.openPreviousEntry();
269 break; 273 break;
274
275 case KeyEvent.VK_C:
276 showCalls();
277 break;
270 } 278 }
271 } 279 }
272 } ); 280 } );
@@ -306,7 +314,22 @@ public class Gui
306 menu.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_I, 0 ) ); 314 menu.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_I, 0 ) );
307 menu.setEnabled( false ); 315 menu.setEnabled( false );
308 popupMenu.add( menu ); 316 popupMenu.add( menu );
309 m_inheritanceMenu = menu; 317 m_showInheritanceMenu = menu;
318 }
319 {
320 JMenuItem menu = new JMenuItem( "Show Calls" );
321 menu.addActionListener( new ActionListener( )
322 {
323 @Override
324 public void actionPerformed( ActionEvent event )
325 {
326 showCalls();
327 }
328 } );
329 menu.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_C, 0 ) );
330 menu.setEnabled( false );
331 popupMenu.add( menu );
332 m_showCallsMenu = menu;
310 } 333 }
311 { 334 {
312 JMenuItem menu = new JMenuItem( "Go to Declaration" ); 335 JMenuItem menu = new JMenuItem( "Go to Declaration" );
@@ -350,12 +373,13 @@ public class Gui
350 if( event.getClickCount() == 2 ) 373 if( event.getClickCount() == 2 )
351 { 374 {
352 // get the selected node 375 // get the selected node
353 Object node = m_inheritanceTree.getSelectionPath().getLastPathComponent(); 376 TreePath path = m_inheritanceTree.getSelectionPath();
354 if( node == null ) 377 if( path == null )
355 { 378 {
356 return; 379 return;
357 } 380 }
358 381
382 Object node = path.getLastPathComponent();
359 if( node instanceof ClassInheritanceTreeNode ) 383 if( node instanceof ClassInheritanceTreeNode )
360 { 384 {
361 m_controller.openEntry( new ClassEntry( ((ClassInheritanceTreeNode)node).getObfClassName() ) ); 385 m_controller.openEntry( new ClassEntry( ((ClassInheritanceTreeNode)node).getObfClassName() ) );
@@ -375,17 +399,47 @@ public class Gui
375 inheritancePanel.setLayout( new BorderLayout() ); 399 inheritancePanel.setLayout( new BorderLayout() );
376 inheritancePanel.add( new JScrollPane( m_inheritanceTree ) ); 400 inheritancePanel.add( new JScrollPane( m_inheritanceTree ) );
377 401
402 // init call panel
403 m_callsTree = new JTree();
404 m_callsTree.setModel( null );
405 m_callsTree.addMouseListener( new MouseAdapter( )
406 {
407 @Override
408 public void mouseClicked( MouseEvent event )
409 {
410 if( event.getClickCount() == 2 )
411 {
412 // get the selected node
413 TreePath path = m_callsTree.getSelectionPath();
414 if( path == null )
415 {
416 return;
417 }
418
419 Object node = path.getLastPathComponent();
420 if( node instanceof MethodCallsTreeNode )
421 {
422 m_controller.openEntry( ((MethodCallsTreeNode)node).getMethodEntry() );
423 }
424 }
425 }
426 } );
427 JPanel callPanel = new JPanel();
428 callPanel.setLayout( new BorderLayout() );
429 callPanel.add( new JScrollPane( m_callsTree ) );
430
378 // layout controls 431 // layout controls
379 JSplitPane splitLeft = new JSplitPane( JSplitPane.VERTICAL_SPLIT, true, obfPanel, deobfPanel ); 432 JSplitPane splitLeft = new JSplitPane( JSplitPane.VERTICAL_SPLIT, true, obfPanel, deobfPanel );
380 splitLeft.setPreferredSize( new Dimension( 200, 0 ) ); 433 splitLeft.setPreferredSize( new Dimension( 250, 0 ) );
381 JPanel centerPanel = new JPanel(); 434 JPanel centerPanel = new JPanel();
382 centerPanel.setLayout( new BorderLayout() ); 435 centerPanel.setLayout( new BorderLayout() );
383 centerPanel.add( m_infoPanel, BorderLayout.NORTH ); 436 centerPanel.add( m_infoPanel, BorderLayout.NORTH );
384 centerPanel.add( sourceScroller, BorderLayout.CENTER ); 437 centerPanel.add( sourceScroller, BorderLayout.CENTER );
385 JTabbedPane tabbedPane = new JTabbedPane(); 438 m_tabs = new JTabbedPane();
386 tabbedPane.setPreferredSize( new Dimension( 200, 0 ) ); 439 m_tabs.setPreferredSize( new Dimension( 250, 0 ) );
387 tabbedPane.addTab( "Inheritance", inheritancePanel ); 440 m_tabs.addTab( "Inheritance", inheritancePanel );
388 JSplitPane splitRight = new JSplitPane( JSplitPane.HORIZONTAL_SPLIT, true, centerPanel, tabbedPane ); 441 m_tabs.addTab( "Method Calls", callPanel );
442 JSplitPane splitRight = new JSplitPane( JSplitPane.HORIZONTAL_SPLIT, true, centerPanel, m_tabs );
389 splitRight.setResizeWeight( 1 ); // let the left side take all the slack 443 splitRight.setResizeWeight( 1 ); // let the left side take all the slack
390 splitRight.resetToPreferredSizes(); 444 splitRight.resetToPreferredSizes();
391 JSplitPane splitCenter = new JSplitPane( JSplitPane.HORIZONTAL_SPLIT, true, splitLeft, splitRight ); 445 JSplitPane splitCenter = new JSplitPane( JSplitPane.HORIZONTAL_SPLIT, true, splitLeft, splitRight );
@@ -784,7 +838,8 @@ public class Gui
784 838
785 showEntryPair( m_selectedEntryPair ); 839 showEntryPair( m_selectedEntryPair );
786 840
787 m_inheritanceMenu.setEnabled( isClassEntry || isMethodEntry ); 841 m_showInheritanceMenu.setEnabled( isClassEntry || isMethodEntry );
842 m_showCallsMenu.setEnabled( isMethodEntry );
788 m_openEntryMenu.setEnabled( isClassEntry || isFieldEntry || isMethodEntry ); 843 m_openEntryMenu.setEnabled( isClassEntry || isFieldEntry || isMethodEntry );
789 m_openPreviousMenu.setEnabled( m_controller.hasPreviousEntry() ); 844 m_openPreviousMenu.setEnabled( m_controller.hasPreviousEntry() );
790 } 845 }
@@ -879,6 +934,24 @@ public class Gui
879 m_inheritanceTree.setSelectionRow( m_inheritanceTree.getRowForPath( path ) ); 934 m_inheritanceTree.setSelectionRow( m_inheritanceTree.getRowForPath( path ) );
880 } 935 }
881 936
937 m_tabs.setSelectedIndex( 0 );
938 redraw();
939 }
940
941 private void showCalls( )
942 {
943 if( m_selectedEntryPair == null )
944 {
945 return;
946 }
947
948 if( m_selectedEntryPair.obf instanceof MethodEntry )
949 {
950 MethodCallsTreeNode node = m_controller.getMethodCalls( (MethodEntry)m_selectedEntryPair.obf );
951 m_callsTree.setModel( new DefaultTreeModel( node ) );
952 }
953
954 m_tabs.setSelectedIndex( 1 );
882 redraw(); 955 redraw();
883 } 956 }
884 957
diff --git a/src/cuchaz/enigma/gui/GuiController.java b/src/cuchaz/enigma/gui/GuiController.java
index 880f001..b54aeba 100644
--- a/src/cuchaz/enigma/gui/GuiController.java
+++ b/src/cuchaz/enigma/gui/GuiController.java
@@ -21,6 +21,7 @@ import com.google.common.collect.Lists;
21 21
22import cuchaz.enigma.Deobfuscator; 22import cuchaz.enigma.Deobfuscator;
23import cuchaz.enigma.analysis.ClassInheritanceTreeNode; 23import cuchaz.enigma.analysis.ClassInheritanceTreeNode;
24import cuchaz.enigma.analysis.MethodCallsTreeNode;
24import cuchaz.enigma.analysis.MethodInheritanceTreeNode; 25import cuchaz.enigma.analysis.MethodInheritanceTreeNode;
25import cuchaz.enigma.analysis.SourceIndex; 26import cuchaz.enigma.analysis.SourceIndex;
26import cuchaz.enigma.analysis.Token; 27import cuchaz.enigma.analysis.Token;
@@ -148,6 +149,16 @@ public class GuiController
148 return MethodInheritanceTreeNode.findNode( rootNode, obfMethodEntry ); 149 return MethodInheritanceTreeNode.findNode( rootNode, obfMethodEntry );
149 } 150 }
150 151
152 public MethodCallsTreeNode getMethodCalls( MethodEntry obfMethodEntry )
153 {
154 MethodCallsTreeNode rootNode = new MethodCallsTreeNode(
155 m_deobfuscator.getTranslator( TranslationDirection.Deobfuscating ),
156 obfMethodEntry
157 );
158 rootNode.load( m_deobfuscator.getJarIndex(), true );
159 return rootNode;
160 }
161
151 public void rename( Entry obfEntry, String newName ) 162 public void rename( Entry obfEntry, String newName )
152 { 163 {
153 m_deobfuscator.rename( obfEntry, newName ); 164 m_deobfuscator.rename( obfEntry, newName );