summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar jeff2014-08-19 00:25:32 -0400
committerGravatar jeff2014-08-19 00:25:32 -0400
commitc4e35f2d516ade27e8e1a863b4bc356f182f43c2 (patch)
tree6711cde39dcfaea30520b8ccabb6236872e0d756 /src
parentfixed type caching after rename (diff)
downloadenigma-fork-c4e35f2d516ade27e8e1a863b4bc356f182f43c2.tar.gz
enigma-fork-c4e35f2d516ade27e8e1a863b4bc356f182f43c2.tar.xz
enigma-fork-c4e35f2d516ade27e8e1a863b4bc356f182f43c2.zip
started new reference navigation system
Diffstat (limited to 'src')
-rw-r--r--src/cuchaz/enigma/analysis/BehaviorReferenceTreeNode.java105
-rw-r--r--src/cuchaz/enigma/analysis/EntryReference.java28
-rw-r--r--src/cuchaz/enigma/analysis/FieldCallsTreeNode.java82
-rw-r--r--src/cuchaz/enigma/analysis/FieldReferenceTreeNode.java92
-rw-r--r--src/cuchaz/enigma/analysis/JarIndex.java141
-rw-r--r--src/cuchaz/enigma/analysis/MethodCallsTreeNode.java144
-rw-r--r--src/cuchaz/enigma/analysis/ReferenceTreeNode.java19
-rw-r--r--src/cuchaz/enigma/analysis/SourceIndexVisitor.java20
-rw-r--r--src/cuchaz/enigma/analysis/TreeDumpVisitor.java11
-rw-r--r--src/cuchaz/enigma/gui/Gui.java46
-rw-r--r--src/cuchaz/enigma/gui/GuiController.java65
-rw-r--r--src/cuchaz/enigma/mapping/BehaviorEntry.java6
-rw-r--r--src/cuchaz/enigma/mapping/ConstructorEntry.java3
-rw-r--r--src/cuchaz/enigma/mapping/MethodEntry.java3
-rw-r--r--src/cuchaz/enigma/mapping/Translator.java13
15 files changed, 441 insertions, 337 deletions
diff --git a/src/cuchaz/enigma/analysis/BehaviorReferenceTreeNode.java b/src/cuchaz/enigma/analysis/BehaviorReferenceTreeNode.java
new file mode 100644
index 0000000..158aad7
--- /dev/null
+++ b/src/cuchaz/enigma/analysis/BehaviorReferenceTreeNode.java
@@ -0,0 +1,105 @@
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.Set;
14
15import javax.swing.tree.DefaultMutableTreeNode;
16import javax.swing.tree.TreeNode;
17
18import com.google.common.collect.Sets;
19
20import cuchaz.enigma.mapping.BehaviorEntry;
21import cuchaz.enigma.mapping.Entry;
22import cuchaz.enigma.mapping.Translator;
23
24public class BehaviorReferenceTreeNode extends DefaultMutableTreeNode implements ReferenceTreeNode<BehaviorEntry>
25{
26 private static final long serialVersionUID = -3658163700783307520L;
27
28 private Translator m_deobfuscatingTranslator;
29 private BehaviorEntry m_entry;
30 private EntryReference<BehaviorEntry> m_reference;
31
32 public BehaviorReferenceTreeNode( Translator deobfuscatingTranslator, BehaviorEntry entry )
33 {
34 m_deobfuscatingTranslator = deobfuscatingTranslator;
35 m_entry = entry;
36 m_reference = null;
37 }
38
39 public BehaviorReferenceTreeNode( Translator deobfuscatingTranslator, EntryReference<BehaviorEntry> reference )
40 {
41 m_deobfuscatingTranslator = deobfuscatingTranslator;
42 m_entry = reference.entry;
43 m_reference = reference;
44 }
45
46 @Override
47 public BehaviorEntry getEntry( )
48 {
49 return m_entry;
50 }
51
52 @Override
53 public EntryReference<BehaviorEntry> getReference( )
54 {
55 return m_reference;
56 }
57
58 @Override
59 public String toString( )
60 {
61 if( m_reference != null )
62 {
63 return m_deobfuscatingTranslator.translateEntry( m_reference.caller ).toString();
64 }
65 return m_deobfuscatingTranslator.translateEntry( m_entry ).toString();
66 }
67
68 public void load( JarIndex index, boolean recurse )
69 {
70 // get all the child nodes
71 for( EntryReference<BehaviorEntry> reference : index.getBehaviorReferences( m_entry ) )
72 {
73 add( new BehaviorReferenceTreeNode( m_deobfuscatingTranslator, reference ) );
74 }
75
76 if( recurse && children != null )
77 {
78 for( Object child : children )
79 {
80 if( child instanceof BehaviorReferenceTreeNode )
81 {
82 BehaviorReferenceTreeNode node = (BehaviorReferenceTreeNode)child;
83
84 // don't recurse into ancestor
85 Set<Entry> ancestors = Sets.newHashSet();
86 TreeNode n = (TreeNode)node;
87 while( n.getParent() != null )
88 {
89 n = n.getParent();
90 if( n instanceof BehaviorReferenceTreeNode )
91 {
92 ancestors.add( ((BehaviorReferenceTreeNode)n).getEntry() );
93 }
94 }
95 if( ancestors.contains( node.getEntry() ) )
96 {
97 continue;
98 }
99
100 node.load( index, true );
101 }
102 }
103 }
104 }
105}
diff --git a/src/cuchaz/enigma/analysis/EntryReference.java b/src/cuchaz/enigma/analysis/EntryReference.java
new file mode 100644
index 0000000..f462210
--- /dev/null
+++ b/src/cuchaz/enigma/analysis/EntryReference.java
@@ -0,0 +1,28 @@
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 cuchaz.enigma.mapping.BehaviorEntry;
14import cuchaz.enigma.mapping.Entry;
15
16public class EntryReference<T extends Entry>
17{
18 public T entry;
19 public BehaviorEntry caller;
20 public int pos;
21
22 public EntryReference( T entry, BehaviorEntry caller, int pos )
23 {
24 this.entry = entry;
25 this.caller = caller;
26 this.pos = pos;
27 }
28}
diff --git a/src/cuchaz/enigma/analysis/FieldCallsTreeNode.java b/src/cuchaz/enigma/analysis/FieldCallsTreeNode.java
deleted file mode 100644
index 0427b3b..0000000
--- a/src/cuchaz/enigma/analysis/FieldCallsTreeNode.java
+++ /dev/null
@@ -1,82 +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 ******************************************************************************/
11package cuchaz.enigma.analysis;
12
13import javax.swing.tree.DefaultMutableTreeNode;
14
15import cuchaz.enigma.mapping.ConstructorEntry;
16import cuchaz.enigma.mapping.Entry;
17import cuchaz.enigma.mapping.FieldEntry;
18import cuchaz.enigma.mapping.MethodEntry;
19import cuchaz.enigma.mapping.Translator;
20
21public class FieldCallsTreeNode extends DefaultMutableTreeNode
22{
23 private static final long serialVersionUID = -7934108091928699835L;
24
25 private Translator m_deobfuscatingTranslator;
26 private FieldEntry m_entry;
27
28 public FieldCallsTreeNode( Translator deobfuscatingTranslator, FieldEntry fieldEntry )
29 {
30 m_deobfuscatingTranslator = deobfuscatingTranslator;
31 m_entry = fieldEntry;
32 }
33
34 public FieldEntry getFieldEntry( )
35 {
36 return m_entry;
37 }
38
39 @Override
40 public String toString( )
41 {
42 String className = m_deobfuscatingTranslator.translateClass( m_entry.getClassName() );
43 if( className == null )
44 {
45 className = m_entry.getClassName();
46 }
47
48 String targetName = m_deobfuscatingTranslator.translate( m_entry );
49 if( targetName == null )
50 {
51 targetName = m_entry.getName();
52 }
53 return className + "." + targetName;
54 }
55
56 public void load( JarIndex index, boolean recurse )
57 {
58 // get all the child nodes
59 for( Entry entry : index.getFieldCallers( m_entry ) )
60 {
61 if( entry instanceof MethodEntry )
62 {
63 add( new MethodCallsTreeNode( m_deobfuscatingTranslator, (MethodEntry)entry ) );
64 }
65 else if( entry instanceof ConstructorEntry )
66 {
67 add( new MethodCallsTreeNode( m_deobfuscatingTranslator, (ConstructorEntry)entry ) );
68 }
69 }
70
71 if( recurse && children != null )
72 {
73 for( Object node : children )
74 {
75 if( node instanceof MethodCallsTreeNode )
76 {
77 ((MethodCallsTreeNode)node).load( index, true );
78 }
79 }
80 }
81 }
82}
diff --git a/src/cuchaz/enigma/analysis/FieldReferenceTreeNode.java b/src/cuchaz/enigma/analysis/FieldReferenceTreeNode.java
new file mode 100644
index 0000000..dd552d6
--- /dev/null
+++ b/src/cuchaz/enigma/analysis/FieldReferenceTreeNode.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 ******************************************************************************/
11package cuchaz.enigma.analysis;
12
13import javax.swing.tree.DefaultMutableTreeNode;
14
15import cuchaz.enigma.mapping.BehaviorEntry;
16import cuchaz.enigma.mapping.FieldEntry;
17import cuchaz.enigma.mapping.Translator;
18
19public class FieldReferenceTreeNode extends DefaultMutableTreeNode implements ReferenceTreeNode<FieldEntry>
20{
21 private static final long serialVersionUID = -7934108091928699835L;
22
23 private Translator m_deobfuscatingTranslator;
24 private FieldEntry m_entry;
25 private EntryReference<FieldEntry> m_reference;
26
27 public FieldReferenceTreeNode( Translator deobfuscatingTranslator, FieldEntry entry )
28 {
29 m_deobfuscatingTranslator = deobfuscatingTranslator;
30 m_entry = entry;
31 m_reference = null;
32 }
33
34 private FieldReferenceTreeNode( Translator deobfuscatingTranslator, EntryReference<FieldEntry> reference )
35 {
36 m_deobfuscatingTranslator = deobfuscatingTranslator;
37 m_entry = reference.entry;
38 m_reference = reference;
39 }
40
41 @Override
42 public FieldEntry getEntry( )
43 {
44 return m_entry;
45 }
46
47 @Override
48 public EntryReference<FieldEntry> getReference( )
49 {
50 return m_reference;
51 }
52
53 @Override
54 public String toString( )
55 {
56 if( m_reference != null )
57 {
58 return m_deobfuscatingTranslator.translateEntry( m_reference.caller ).toString();
59 }
60 return m_deobfuscatingTranslator.translateEntry( m_entry ).toString();
61 }
62
63 public void load( JarIndex index, boolean recurse )
64 {
65 // get all the child nodes
66 if( m_reference == null )
67 {
68 for( EntryReference<FieldEntry> reference : index.getFieldReferences( m_entry ) )
69 {
70 add( new FieldReferenceTreeNode( m_deobfuscatingTranslator, reference ) );
71 }
72 }
73 else
74 {
75 for( EntryReference<BehaviorEntry> reference : index.getBehaviorReferences( m_reference.caller ) )
76 {
77 add( new BehaviorReferenceTreeNode( m_deobfuscatingTranslator, reference ) );
78 }
79 }
80
81 if( recurse && children != null )
82 {
83 for( Object node : children )
84 {
85 if( node instanceof BehaviorReferenceTreeNode )
86 {
87 ((BehaviorReferenceTreeNode)node).load( index, true );
88 }
89 }
90 }
91 }
92}
diff --git a/src/cuchaz/enigma/analysis/JarIndex.java b/src/cuchaz/enigma/analysis/JarIndex.java
index 7d68c35..f1c29c5 100644
--- a/src/cuchaz/enigma/analysis/JarIndex.java
+++ b/src/cuchaz/enigma/analysis/JarIndex.java
@@ -35,12 +35,15 @@ import javassist.expr.MethodCall;
35import javassist.expr.NewExpr; 35import javassist.expr.NewExpr;
36 36
37import com.google.common.collect.HashMultimap; 37import com.google.common.collect.HashMultimap;
38import com.google.common.collect.HashMultiset;
38import com.google.common.collect.Lists; 39import com.google.common.collect.Lists;
39import com.google.common.collect.Maps; 40import com.google.common.collect.Maps;
40import com.google.common.collect.Multimap; 41import com.google.common.collect.Multimap;
42import com.google.common.collect.Multiset;
41import com.google.common.collect.Sets; 43import com.google.common.collect.Sets;
42 44
43import cuchaz.enigma.mapping.ArgumentEntry; 45import cuchaz.enigma.mapping.ArgumentEntry;
46import cuchaz.enigma.mapping.BehaviorEntry;
44import cuchaz.enigma.mapping.ClassEntry; 47import cuchaz.enigma.mapping.ClassEntry;
45import cuchaz.enigma.mapping.ConstructorEntry; 48import cuchaz.enigma.mapping.ConstructorEntry;
46import cuchaz.enigma.mapping.Entry; 49import cuchaz.enigma.mapping.Entry;
@@ -53,8 +56,8 @@ public class JarIndex
53 private Set<String> m_obfClassNames; 56 private Set<String> m_obfClassNames;
54 private Ancestries m_ancestries; 57 private Ancestries m_ancestries;
55 private Multimap<String,MethodEntry> m_methodImplementations; 58 private Multimap<String,MethodEntry> m_methodImplementations;
56 private Multimap<Entry,Entry> m_methodCalls; 59 private Multimap<BehaviorEntry,EntryReference<? extends Entry>> m_behaviorReferences;
57 private Multimap<FieldEntry,Entry> m_fieldCalls; 60 private Multimap<FieldEntry,EntryReference<? extends Entry>> m_fieldReferences;
58 private Multimap<String,String> m_innerClasses; 61 private Multimap<String,String> m_innerClasses;
59 private Map<String,String> m_outerClasses; 62 private Map<String,String> m_outerClasses;
60 private Set<String> m_anonymousClasses; 63 private Set<String> m_anonymousClasses;
@@ -64,8 +67,8 @@ public class JarIndex
64 m_obfClassNames = Sets.newHashSet(); 67 m_obfClassNames = Sets.newHashSet();
65 m_ancestries = new Ancestries(); 68 m_ancestries = new Ancestries();
66 m_methodImplementations = HashMultimap.create(); 69 m_methodImplementations = HashMultimap.create();
67 m_methodCalls = HashMultimap.create(); 70 m_behaviorReferences = HashMultimap.create();
68 m_fieldCalls = HashMultimap.create(); 71 m_fieldReferences = HashMultimap.create();
69 m_innerClasses = HashMultimap.create(); 72 m_innerClasses = HashMultimap.create();
70 m_outerClasses = Maps.newHashMap(); 73 m_outerClasses = Maps.newHashMap();
71 m_anonymousClasses = Sets.newHashSet(); 74 m_anonymousClasses = Sets.newHashSet();
@@ -128,7 +131,7 @@ public class JarIndex
128 { 131 {
129 // get the method entry 132 // get the method entry
130 String className = Descriptor.toJvmName( behavior.getDeclaringClass().getName() ); 133 String className = Descriptor.toJvmName( behavior.getDeclaringClass().getName() );
131 final Entry thisEntry; 134 final BehaviorEntry thisEntry;
132 if( behavior instanceof CtMethod ) 135 if( behavior instanceof CtMethod )
133 { 136 {
134 MethodEntry methodEntry = new MethodEntry( 137 MethodEntry methodEntry = new MethodEntry(
@@ -156,6 +159,7 @@ public class JarIndex
156 // index method calls 159 // index method calls
157 try 160 try
158 { 161 {
162 final Multiset<Entry> callNumbers = HashMultiset.create();
159 behavior.instrument( new ExprEditor( ) 163 behavior.instrument( new ExprEditor( )
160 { 164 {
161 @Override 165 @Override
@@ -167,7 +171,13 @@ public class JarIndex
167 call.getMethodName(), 171 call.getMethodName(),
168 call.getSignature() 172 call.getSignature()
169 ); 173 );
170 m_methodCalls.put( calledMethodEntry, thisEntry ); 174 callNumbers.add( calledMethodEntry );
175 EntryReference<MethodEntry> reference = new EntryReference<MethodEntry>(
176 calledMethodEntry,
177 thisEntry,
178 callNumbers.count( calledMethodEntry ) - 1
179 );
180 m_behaviorReferences.put( calledMethodEntry, reference );
171 } 181 }
172 182
173 @Override 183 @Override
@@ -178,22 +188,33 @@ public class JarIndex
178 new ClassEntry( className ), 188 new ClassEntry( className ),
179 call.getFieldName() 189 call.getFieldName()
180 ); 190 );
181 m_fieldCalls.put( calledFieldEntry, thisEntry ); 191 callNumbers.add( calledFieldEntry );
192 EntryReference<FieldEntry> reference = new EntryReference<FieldEntry>(
193 calledFieldEntry,
194 thisEntry,
195 callNumbers.count( calledFieldEntry ) - 1
196 );
197 m_fieldReferences.put( calledFieldEntry, reference );
182 } 198 }
183 199
184 @Override 200 @Override
185 public void edit( ConstructorCall call ) 201 public void edit( ConstructorCall call )
186 { 202 {
203 // TODO: save isSuper in the reference somehow
187 boolean isSuper = call.getMethodName().equals( "super" ); 204 boolean isSuper = call.getMethodName().equals( "super" );
188 // TODO: make method reference class, update method calls tree to use Invocation instances
189 // this might end up being a big refactor... =(
190 205
191 String className = Descriptor.toJvmName( call.getClassName() ); 206 String className = Descriptor.toJvmName( call.getClassName() );
192 ConstructorEntry calledConstructorEntry = new ConstructorEntry( 207 ConstructorEntry calledConstructorEntry = new ConstructorEntry(
193 new ClassEntry( className ), 208 new ClassEntry( className ),
194 call.getSignature() 209 call.getSignature()
195 ); 210 );
196 m_methodCalls.put( calledConstructorEntry, thisEntry ); 211 callNumbers.add( calledConstructorEntry );
212 EntryReference<ConstructorEntry> reference = new EntryReference<ConstructorEntry>(
213 calledConstructorEntry,
214 thisEntry,
215 callNumbers.count( calledConstructorEntry ) - 1
216 );
217 m_behaviorReferences.put( calledConstructorEntry, reference );
197 } 218 }
198 219
199 @Override 220 @Override
@@ -204,7 +225,13 @@ public class JarIndex
204 new ClassEntry( className ), 225 new ClassEntry( className ),
205 call.getSignature() 226 call.getSignature()
206 ); 227 );
207 m_methodCalls.put( calledConstructorEntry, thisEntry ); 228 callNumbers.add( calledConstructorEntry );
229 EntryReference<ConstructorEntry> reference = new EntryReference<ConstructorEntry>(
230 calledConstructorEntry,
231 thisEntry,
232 callNumbers.count( calledConstructorEntry ) - 1
233 );
234 m_behaviorReferences.put( calledConstructorEntry, reference );
208 } 235 }
209 } ); 236 } );
210 } 237 }
@@ -234,9 +261,9 @@ public class JarIndex
234 new ClassEntry( Descriptor.toJvmName( c.getName() ) ), 261 new ClassEntry( Descriptor.toJvmName( c.getName() ) ),
235 constructor.getMethodInfo().getDescriptor() 262 constructor.getMethodInfo().getDescriptor()
236 ); 263 );
237 for( Entry callerEntry : getMethodCallers( constructorEntry ) ) 264 for( EntryReference<BehaviorEntry> reference : getBehaviorReferences( constructorEntry ) )
238 { 265 {
239 callerClasses.add( callerEntry.getClassEntry() ); 266 callerClasses.add( reference.caller.getClassEntry() );
240 } 267 }
241 268
242 // is this called by exactly one class? 269 // is this called by exactly one class?
@@ -388,7 +415,7 @@ public class JarIndex
388 new ClassEntry( innerClassName ), 415 new ClassEntry( innerClassName ),
389 constructor.getMethodInfo().getDescriptor() 416 constructor.getMethodInfo().getDescriptor()
390 ); 417 );
391 if( getMethodCallers( constructorEntry ).size() != 1 ) 418 if( getBehaviorReferences( constructorEntry ).size() != 1 )
392 { 419 {
393 return false; 420 return false;
394 } 421 }
@@ -469,14 +496,26 @@ public class JarIndex
469 return rootNode; 496 return rootNode;
470 } 497 }
471 498
472 public Collection<Entry> getFieldCallers( FieldEntry fieldEntry ) 499 @SuppressWarnings( "unchecked" )
500 public Collection<EntryReference<FieldEntry>> getFieldReferences( FieldEntry fieldEntry )
473 { 501 {
474 return m_fieldCalls.get( fieldEntry ); 502 List<EntryReference<FieldEntry>> references = Lists.newArrayList();
503 for( EntryReference<? extends Entry> reference : m_fieldReferences.get( fieldEntry ) )
504 {
505 references.add( (EntryReference<FieldEntry>)reference );
506 }
507 return references;
475 } 508 }
476 509
477 public Collection<Entry> getMethodCallers( Entry entry ) 510 @SuppressWarnings( "unchecked" )
511 public Collection<EntryReference<BehaviorEntry>> getBehaviorReferences( BehaviorEntry behaviorEntry )
478 { 512 {
479 return m_methodCalls.get( entry ); 513 List<EntryReference<BehaviorEntry>> references = Lists.newArrayList();
514 for( EntryReference<? extends Entry> reference : m_behaviorReferences.get( behaviorEntry ) )
515 {
516 references.add( (EntryReference<BehaviorEntry>)reference );
517 }
518 return references;
480 } 519 }
481 520
482 public Collection<String> getInnerClasses( String obfOuterClassName ) 521 public Collection<String> getInnerClasses( String obfOuterClassName )
@@ -498,85 +537,91 @@ public class JarIndex
498 { 537 {
499 m_ancestries.renameClasses( renames ); 538 m_ancestries.renameClasses( renames );
500 renameMultimap( renames, m_methodImplementations ); 539 renameMultimap( renames, m_methodImplementations );
501 renameMultimap( renames, m_methodCalls ); 540 renameMultimap( renames, m_behaviorReferences );
502 renameMultimap( renames, m_fieldCalls ); 541 renameMultimap( renames, m_fieldReferences );
503 } 542 }
504 543
505 private <T,U> void renameMultimap( Map<String,String> renames, Multimap<T,U> map ) 544 private <Key,Val> void renameMultimap( Map<String,String> renames, Multimap<Key,Val> map )
506 { 545 {
507 // for each key/value pair... 546 // for each key/value pair...
508 Set<Map.Entry<T,U>> entriesToAdd = Sets.newHashSet(); 547 Set<Map.Entry<Key,Val>> entriesToAdd = Sets.newHashSet();
509 Iterator<Map.Entry<T,U>> iter = map.entries().iterator(); 548 Iterator<Map.Entry<Key,Val>> iter = map.entries().iterator();
510 while( iter.hasNext() ) 549 while( iter.hasNext() )
511 { 550 {
512 Map.Entry<T,U> entry = iter.next(); 551 Map.Entry<Key,Val> entry = iter.next();
513 iter.remove(); 552 iter.remove();
514 entriesToAdd.add( new AbstractMap.SimpleEntry<T,U>( 553 entriesToAdd.add( new AbstractMap.SimpleEntry<Key,Val>(
515 renameEntry( renames, entry.getKey() ), 554 renameThing( renames, entry.getKey() ),
516 renameEntry( renames, entry.getValue() ) 555 renameThing( renames, entry.getValue() )
517 ) ); 556 ) );
518 } 557 }
519 for( Map.Entry<T,U> entry : entriesToAdd ) 558 for( Map.Entry<Key,Val> entry : entriesToAdd )
520 { 559 {
521 map.put( entry.getKey(), entry.getValue() ); 560 map.put( entry.getKey(), entry.getValue() );
522 } 561 }
523 } 562 }
524 563
525 @SuppressWarnings( "unchecked" ) 564 @SuppressWarnings( "unchecked" )
526 private <T> T renameEntry( Map<String,String> renames, T entry ) 565 private <T> T renameThing( Map<String,String> renames, T thing )
527 { 566 {
528 if( entry instanceof String ) 567 if( thing instanceof String )
529 { 568 {
530 String stringEntry = (String)entry; 569 String stringEntry = (String)thing;
531 if( renames.containsKey( stringEntry ) ) 570 if( renames.containsKey( stringEntry ) )
532 { 571 {
533 return (T)renames.get( stringEntry ); 572 return (T)renames.get( stringEntry );
534 } 573 }
535 } 574 }
536 else if( entry instanceof ClassEntry ) 575 else if( thing instanceof ClassEntry )
537 { 576 {
538 ClassEntry classEntry = (ClassEntry)entry; 577 ClassEntry classEntry = (ClassEntry)thing;
539 return (T)new ClassEntry( renameEntry( renames, classEntry.getClassName() ) ); 578 return (T)new ClassEntry( renameThing( renames, classEntry.getClassName() ) );
540 } 579 }
541 else if( entry instanceof FieldEntry ) 580 else if( thing instanceof FieldEntry )
542 { 581 {
543 FieldEntry fieldEntry = (FieldEntry)entry; 582 FieldEntry fieldEntry = (FieldEntry)thing;
544 return (T)new FieldEntry( 583 return (T)new FieldEntry(
545 renameEntry( renames, fieldEntry.getClassEntry() ), 584 renameThing( renames, fieldEntry.getClassEntry() ),
546 fieldEntry.getName() 585 fieldEntry.getName()
547 ); 586 );
548 } 587 }
549 else if( entry instanceof ConstructorEntry ) 588 else if( thing instanceof ConstructorEntry )
550 { 589 {
551 ConstructorEntry constructorEntry = (ConstructorEntry)entry; 590 ConstructorEntry constructorEntry = (ConstructorEntry)thing;
552 return (T)new ConstructorEntry( 591 return (T)new ConstructorEntry(
553 renameEntry( renames, constructorEntry.getClassEntry() ), 592 renameThing( renames, constructorEntry.getClassEntry() ),
554 constructorEntry.getSignature() 593 constructorEntry.getSignature()
555 ); 594 );
556 } 595 }
557 else if( entry instanceof MethodEntry ) 596 else if( thing instanceof MethodEntry )
558 { 597 {
559 MethodEntry methodEntry = (MethodEntry)entry; 598 MethodEntry methodEntry = (MethodEntry)thing;
560 return (T)new MethodEntry( 599 return (T)new MethodEntry(
561 renameEntry( renames, methodEntry.getClassEntry() ), 600 renameThing( renames, methodEntry.getClassEntry() ),
562 methodEntry.getName(), 601 methodEntry.getName(),
563 methodEntry.getSignature() 602 methodEntry.getSignature()
564 ); 603 );
565 } 604 }
566 else if( entry instanceof ArgumentEntry ) 605 else if( thing instanceof ArgumentEntry )
567 { 606 {
568 ArgumentEntry argumentEntry = (ArgumentEntry)entry; 607 ArgumentEntry argumentEntry = (ArgumentEntry)thing;
569 return (T)new ArgumentEntry( 608 return (T)new ArgumentEntry(
570 renameEntry( renames, argumentEntry.getMethodEntry() ), 609 renameThing( renames, argumentEntry.getMethodEntry() ),
571 argumentEntry.getIndex(), 610 argumentEntry.getIndex(),
572 argumentEntry.getName() 611 argumentEntry.getName()
573 ); 612 );
574 } 613 }
614 else if( thing instanceof EntryReference )
615 {
616 EntryReference<Entry> reference = (EntryReference<Entry>)thing;
617 reference.entry = renameThing( renames, reference.entry );
618 return thing;
619 }
575 else 620 else
576 { 621 {
577 throw new Error( "Not an entry: " + entry ); 622 throw new Error( "Not an entry: " + thing );
578 } 623 }
579 624
580 return entry; 625 return thing;
581 } 626 }
582} 627}
diff --git a/src/cuchaz/enigma/analysis/MethodCallsTreeNode.java b/src/cuchaz/enigma/analysis/MethodCallsTreeNode.java
deleted file mode 100644
index b5cf4c3..0000000
--- a/src/cuchaz/enigma/analysis/MethodCallsTreeNode.java
+++ /dev/null
@@ -1,144 +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 ******************************************************************************/
11package cuchaz.enigma.analysis;
12
13import java.util.Set;
14
15import javax.swing.tree.DefaultMutableTreeNode;
16import javax.swing.tree.TreeNode;
17
18import com.google.common.collect.Sets;
19
20import cuchaz.enigma.mapping.ConstructorEntry;
21import cuchaz.enigma.mapping.Entry;
22import cuchaz.enigma.mapping.MethodEntry;
23import cuchaz.enigma.mapping.Translator;
24
25public class MethodCallsTreeNode extends DefaultMutableTreeNode
26{
27 private static final long serialVersionUID = -3658163700783307520L;
28
29 private Translator m_deobfuscatingTranslator;
30 private MethodEntry m_methodEntry;
31 private ConstructorEntry m_constructorEntry;
32
33 public MethodCallsTreeNode( Translator deobfuscatingTranslator, MethodEntry entry )
34 {
35 m_deobfuscatingTranslator = deobfuscatingTranslator;
36 m_methodEntry = entry;
37 m_constructorEntry = null;
38 }
39
40 public MethodCallsTreeNode( Translator deobfuscatingTranslator, ConstructorEntry entry )
41 {
42 m_deobfuscatingTranslator = deobfuscatingTranslator;
43 m_methodEntry = null;
44 m_constructorEntry = entry;
45 }
46
47 public MethodEntry getMethodEntry( )
48 {
49 return m_methodEntry;
50 }
51
52 public ConstructorEntry getConstructorEntry( )
53 {
54 return m_constructorEntry;
55 }
56
57 public Entry getEntry( )
58 {
59 if( m_methodEntry != null )
60 {
61 return m_methodEntry;
62 }
63 else if( m_constructorEntry != null )
64 {
65 return m_constructorEntry;
66 }
67 throw new Error( "Illegal state!" );
68 }
69
70 @Override
71 public String toString( )
72 {
73 if( m_methodEntry != null )
74 {
75 String className = m_deobfuscatingTranslator.translateClass( m_methodEntry.getClassName() );
76 if( className == null )
77 {
78 className = m_methodEntry.getClassName();
79 }
80
81 String methodName = m_deobfuscatingTranslator.translate( m_methodEntry );
82 if( methodName == null )
83 {
84 methodName = m_methodEntry.getName();
85 }
86 return className + "." + methodName + "()";
87 }
88 else if( m_constructorEntry != null )
89 {
90 String className = m_deobfuscatingTranslator.translateClass( m_constructorEntry.getClassName() );
91 if( className == null )
92 {
93 className = m_constructorEntry.getClassName();
94 }
95 return className + "()";
96 }
97 throw new Error( "Illegal state!" );
98 }
99
100 public void load( JarIndex index, boolean recurse )
101 {
102 // get all the child nodes
103 for( Entry entry : index.getMethodCallers( getEntry() ) )
104 {
105 if( entry instanceof MethodEntry )
106 {
107 add( new MethodCallsTreeNode( m_deobfuscatingTranslator, (MethodEntry)entry ) );
108 }
109 else if( entry instanceof ConstructorEntry )
110 {
111 add( new MethodCallsTreeNode( m_deobfuscatingTranslator, (ConstructorEntry)entry ) );
112 }
113 }
114
115 if( recurse && children != null )
116 {
117 for( Object child : children )
118 {
119 if( child instanceof MethodCallsTreeNode )
120 {
121 MethodCallsTreeNode node = (MethodCallsTreeNode)child;
122
123 // don't recurse into ancestor
124 Set<Entry> ancestors = Sets.newHashSet();
125 TreeNode n = (TreeNode)node;
126 while( n.getParent() != null )
127 {
128 n = n.getParent();
129 if( n instanceof MethodCallsTreeNode )
130 {
131 ancestors.add( ((MethodCallsTreeNode)n).getEntry() );
132 }
133 }
134 if( ancestors.contains( node.getEntry() ) )
135 {
136 continue;
137 }
138
139 node.load( index, true );
140 }
141 }
142 }
143 }
144}
diff --git a/src/cuchaz/enigma/analysis/ReferenceTreeNode.java b/src/cuchaz/enigma/analysis/ReferenceTreeNode.java
new file mode 100644
index 0000000..08ae39d
--- /dev/null
+++ b/src/cuchaz/enigma/analysis/ReferenceTreeNode.java
@@ -0,0 +1,19 @@
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 cuchaz.enigma.mapping.Entry;
14
15public interface ReferenceTreeNode<T extends Entry>
16{
17 T getEntry();
18 EntryReference<T> getReference();
19}
diff --git a/src/cuchaz/enigma/analysis/SourceIndexVisitor.java b/src/cuchaz/enigma/analysis/SourceIndexVisitor.java
index f31eb1a..841d176 100644
--- a/src/cuchaz/enigma/analysis/SourceIndexVisitor.java
+++ b/src/cuchaz/enigma/analysis/SourceIndexVisitor.java
@@ -213,6 +213,20 @@ public class SourceIndexVisitor implements IAstVisitor<SourceIndex, Void>
213 return recurse( node, index ); 213 return recurse( node, index );
214 } 214 }
215 215
216 @Override
217 public Void visitIdentifierExpression( IdentifierExpression node, SourceIndex index )
218 {
219 MemberReference ref = node.getUserData( Keys.MEMBER_REFERENCE );
220 if( ref != null )
221 {
222 ClassEntry classEntry = new ClassEntry( ref.getDeclaringType().getInternalName() );
223 FieldEntry fieldEntry = new FieldEntry( classEntry, ref.getName() );
224 index.add( node.getIdentifierToken(), fieldEntry );
225 }
226
227 return recurse( node, index );
228 }
229
216 private Void recurse( AstNode node, SourceIndex index ) 230 private Void recurse( AstNode node, SourceIndex index )
217 { 231 {
218 for( final AstNode child : node.getChildren() ) 232 for( final AstNode child : node.getChildren() )
@@ -477,12 +491,6 @@ public class SourceIndexVisitor implements IAstVisitor<SourceIndex, Void>
477 } 491 }
478 492
479 @Override 493 @Override
480 public Void visitIdentifierExpression( IdentifierExpression node, SourceIndex index )
481 {
482 return recurse( node, index );
483 }
484
485 @Override
486 public Void visitUnaryOperatorExpression( UnaryOperatorExpression node, SourceIndex index ) 494 public Void visitUnaryOperatorExpression( UnaryOperatorExpression node, SourceIndex index )
487 { 495 {
488 return recurse( node, index ); 496 return recurse( node, index );
diff --git a/src/cuchaz/enigma/analysis/TreeDumpVisitor.java b/src/cuchaz/enigma/analysis/TreeDumpVisitor.java
index ac3e92d..12febef 100644
--- a/src/cuchaz/enigma/analysis/TreeDumpVisitor.java
+++ b/src/cuchaz/enigma/analysis/TreeDumpVisitor.java
@@ -122,7 +122,7 @@ public class TreeDumpVisitor implements IAstVisitor<Void, Void>
122 // show the tree 122 // show the tree
123 try 123 try
124 { 124 {
125 m_out.write( getIndent( node ) + node.getClass().getSimpleName() + dumpUserData( node ) + " " + node.getRegion() + "\n" ); 125 m_out.write( getIndent( node ) + node.getClass().getSimpleName() + " " + getText( node ) + " " + dumpUserData( node ) + " " + node.getRegion() + "\n" );
126 } 126 }
127 catch( IOException ex ) 127 catch( IOException ex )
128 { 128 {
@@ -137,6 +137,15 @@ public class TreeDumpVisitor implements IAstVisitor<Void, Void>
137 return null; 137 return null;
138 } 138 }
139 139
140 private String getText( AstNode node )
141 {
142 if( node instanceof Identifier )
143 {
144 return "\"" + node.getText() + "\"";
145 }
146 return "";
147 }
148
140 private String dumpUserData( AstNode node ) 149 private String dumpUserData( AstNode node )
141 { 150 {
142 StringBuilder buf = new StringBuilder(); 151 StringBuilder buf = new StringBuilder();
diff --git a/src/cuchaz/enigma/gui/Gui.java b/src/cuchaz/enigma/gui/Gui.java
index 9ed6dd8..43a0cda 100644
--- a/src/cuchaz/enigma/gui/Gui.java
+++ b/src/cuchaz/enigma/gui/Gui.java
@@ -66,10 +66,11 @@ import jsyntaxpane.DefaultSyntaxKit;
66import com.google.common.collect.Lists; 66import com.google.common.collect.Lists;
67 67
68import cuchaz.enigma.Constants; 68import cuchaz.enigma.Constants;
69import cuchaz.enigma.analysis.BehaviorReferenceTreeNode;
69import cuchaz.enigma.analysis.ClassInheritanceTreeNode; 70import cuchaz.enigma.analysis.ClassInheritanceTreeNode;
70import cuchaz.enigma.analysis.FieldCallsTreeNode; 71import cuchaz.enigma.analysis.FieldReferenceTreeNode;
71import cuchaz.enigma.analysis.MethodCallsTreeNode;
72import cuchaz.enigma.analysis.MethodInheritanceTreeNode; 72import cuchaz.enigma.analysis.MethodInheritanceTreeNode;
73import cuchaz.enigma.analysis.ReferenceTreeNode;
73import cuchaz.enigma.analysis.Token; 74import cuchaz.enigma.analysis.Token;
74import cuchaz.enigma.mapping.ArgumentEntry; 75import cuchaz.enigma.mapping.ArgumentEntry;
75import cuchaz.enigma.mapping.ClassEntry; 76import cuchaz.enigma.mapping.ClassEntry;
@@ -191,7 +192,7 @@ public class Gui
191 String selected = m_obfClasses.getSelectedValue(); 192 String selected = m_obfClasses.getSelectedValue();
192 if( selected != null ) 193 if( selected != null )
193 { 194 {
194 m_controller.openEntry( new ClassEntry( selected ) ); 195 m_controller.openDeclaration( new ClassEntry( selected ) );
195 } 196 }
196 } 197 }
197 } 198 }
@@ -217,7 +218,7 @@ public class Gui
217 String selected = m_deobfClasses.getSelectedValue(); 218 String selected = m_deobfClasses.getSelectedValue();
218 if( selected != null ) 219 if( selected != null )
219 { 220 {
220 m_controller.openEntry( new ClassEntry( selected ) ); 221 m_controller.openDeclaration( new ClassEntry( selected ) );
221 } 222 }
222 } 223 }
223 } 224 }
@@ -268,11 +269,11 @@ public class Gui
268 break; 269 break;
269 270
270 case KeyEvent.VK_N: 271 case KeyEvent.VK_N:
271 openEntry(); 272 openDeclaration();
272 break; 273 break;
273 274
274 case KeyEvent.VK_P: 275 case KeyEvent.VK_P:
275 m_controller.openPreviousEntry(); 276 m_controller.openPreviousLocation();
276 break; 277 break;
277 278
278 case KeyEvent.VK_C: 279 case KeyEvent.VK_C:
@@ -341,7 +342,7 @@ public class Gui
341 @Override 342 @Override
342 public void actionPerformed( ActionEvent event ) 343 public void actionPerformed( ActionEvent event )
343 { 344 {
344 openEntry(); 345 openDeclaration();
345 } 346 }
346 } ); 347 } );
347 menu.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_N, 0 ) ); 348 menu.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_N, 0 ) );
@@ -356,7 +357,7 @@ public class Gui
356 @Override 357 @Override
357 public void actionPerformed( ActionEvent event ) 358 public void actionPerformed( ActionEvent event )
358 { 359 {
359 m_controller.openPreviousEntry(); 360 m_controller.openPreviousLocation();
360 } 361 }
361 } ); 362 } );
362 menu.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_P, 0 ) ); 363 menu.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_P, 0 ) );
@@ -385,14 +386,14 @@ public class Gui
385 Object node = path.getLastPathComponent(); 386 Object node = path.getLastPathComponent();
386 if( node instanceof ClassInheritanceTreeNode ) 387 if( node instanceof ClassInheritanceTreeNode )
387 { 388 {
388 m_controller.openEntry( new ClassEntry( ((ClassInheritanceTreeNode)node).getObfClassName() ) ); 389 m_controller.openDeclaration( new ClassEntry( ((ClassInheritanceTreeNode)node).getObfClassName() ) );
389 } 390 }
390 else if( node instanceof MethodInheritanceTreeNode ) 391 else if( node instanceof MethodInheritanceTreeNode )
391 { 392 {
392 MethodInheritanceTreeNode methodNode = (MethodInheritanceTreeNode)node; 393 MethodInheritanceTreeNode methodNode = (MethodInheritanceTreeNode)node;
393 if( methodNode.isImplemented() ) 394 if( methodNode.isImplemented() )
394 { 395 {
395 m_controller.openEntry( methodNode.getMethodEntry() ); 396 m_controller.openDeclaration( methodNode.getMethodEntry() );
396 } 397 }
397 } 398 }
398 } 399 }
@@ -407,6 +408,7 @@ public class Gui
407 m_callsTree.setModel( null ); 408 m_callsTree.setModel( null );
408 m_callsTree.addMouseListener( new MouseAdapter( ) 409 m_callsTree.addMouseListener( new MouseAdapter( )
409 { 410 {
411 @SuppressWarnings( "unchecked" )
410 @Override 412 @Override
411 public void mouseClicked( MouseEvent event ) 413 public void mouseClicked( MouseEvent event )
412 { 414 {
@@ -420,9 +422,17 @@ public class Gui
420 } 422 }
421 423
422 Object node = path.getLastPathComponent(); 424 Object node = path.getLastPathComponent();
423 if( node instanceof MethodCallsTreeNode ) 425 if( node instanceof ReferenceTreeNode )
424 { 426 {
425 m_controller.openEntry( ((MethodCallsTreeNode)node).getEntry() ); 427 ReferenceTreeNode<Entry> referenceNode = ((ReferenceTreeNode<Entry>)node);
428 if( referenceNode.getReference() != null )
429 {
430 m_controller.openReference( referenceNode.getReference() );
431 }
432 else
433 {
434 m_controller.openDeclaration( referenceNode.getEntry() );
435 }
426 } 436 }
427 } 437 }
428 } 438 }
@@ -862,7 +872,7 @@ public class Gui
862 m_showInheritanceMenu.setEnabled( isClassEntry || isMethodEntry || isConstructorEntry ); 872 m_showInheritanceMenu.setEnabled( isClassEntry || isMethodEntry || isConstructorEntry );
863 m_showCallsMenu.setEnabled( isFieldEntry || isMethodEntry || isConstructorEntry ); 873 m_showCallsMenu.setEnabled( isFieldEntry || isMethodEntry || isConstructorEntry );
864 m_openEntryMenu.setEnabled( isClassEntry || isFieldEntry || isMethodEntry || isConstructorEntry ); 874 m_openEntryMenu.setEnabled( isClassEntry || isFieldEntry || isMethodEntry || isConstructorEntry );
865 m_openPreviousMenu.setEnabled( m_controller.hasPreviousEntry() ); 875 m_openPreviousMenu.setEnabled( m_controller.hasPreviousLocation() );
866 } 876 }
867 877
868 private void startRename( ) 878 private void startRename( )
@@ -977,17 +987,17 @@ public class Gui
977 987
978 if( m_selectedEntryPair.obf instanceof FieldEntry ) 988 if( m_selectedEntryPair.obf instanceof FieldEntry )
979 { 989 {
980 FieldCallsTreeNode node = m_controller.getFieldCalls( (FieldEntry)m_selectedEntryPair.obf ); 990 FieldReferenceTreeNode node = m_controller.getFieldReferences( (FieldEntry)m_selectedEntryPair.obf );
981 m_callsTree.setModel( new DefaultTreeModel( node ) ); 991 m_callsTree.setModel( new DefaultTreeModel( node ) );
982 } 992 }
983 else if( m_selectedEntryPair.obf instanceof MethodEntry ) 993 else if( m_selectedEntryPair.obf instanceof MethodEntry )
984 { 994 {
985 MethodCallsTreeNode node = m_controller.getMethodCalls( (MethodEntry)m_selectedEntryPair.obf ); 995 BehaviorReferenceTreeNode node = m_controller.getMethodReferences( (MethodEntry)m_selectedEntryPair.obf );
986 m_callsTree.setModel( new DefaultTreeModel( node ) ); 996 m_callsTree.setModel( new DefaultTreeModel( node ) );
987 } 997 }
988 else if( m_selectedEntryPair.obf instanceof ConstructorEntry ) 998 else if( m_selectedEntryPair.obf instanceof ConstructorEntry )
989 { 999 {
990 MethodCallsTreeNode node = m_controller.getMethodCalls( (ConstructorEntry)m_selectedEntryPair.obf ); 1000 BehaviorReferenceTreeNode node = m_controller.getMethodReferences( (ConstructorEntry)m_selectedEntryPair.obf );
991 m_callsTree.setModel( new DefaultTreeModel( node ) ); 1001 m_callsTree.setModel( new DefaultTreeModel( node ) );
992 } 1002 }
993 1003
@@ -1009,13 +1019,13 @@ public class Gui
1009 return new TreePath( nodes.toArray() ); 1019 return new TreePath( nodes.toArray() );
1010 } 1020 }
1011 1021
1012 private void openEntry( ) 1022 private void openDeclaration( )
1013 { 1023 {
1014 if( m_selectedEntryPair == null ) 1024 if( m_selectedEntryPair == null )
1015 { 1025 {
1016 return; 1026 return;
1017 } 1027 }
1018 m_controller.openEntry( m_selectedEntryPair.obf ); 1028 m_controller.openDeclaration( m_selectedEntryPair.obf );
1019 } 1029 }
1020 1030
1021 private void close( ) 1031 private void close( )
diff --git a/src/cuchaz/enigma/gui/GuiController.java b/src/cuchaz/enigma/gui/GuiController.java
index f305e34..f80bec7 100644
--- a/src/cuchaz/enigma/gui/GuiController.java
+++ b/src/cuchaz/enigma/gui/GuiController.java
@@ -20,14 +20,15 @@ import java.util.Stack;
20import com.google.common.collect.Lists; 20import com.google.common.collect.Lists;
21 21
22import cuchaz.enigma.Deobfuscator; 22import cuchaz.enigma.Deobfuscator;
23import cuchaz.enigma.analysis.BehaviorReferenceTreeNode;
23import cuchaz.enigma.analysis.ClassInheritanceTreeNode; 24import cuchaz.enigma.analysis.ClassInheritanceTreeNode;
24import cuchaz.enigma.analysis.FieldCallsTreeNode; 25import cuchaz.enigma.analysis.EntryReference;
25import cuchaz.enigma.analysis.MethodCallsTreeNode; 26import cuchaz.enigma.analysis.FieldReferenceTreeNode;
26import cuchaz.enigma.analysis.MethodInheritanceTreeNode; 27import cuchaz.enigma.analysis.MethodInheritanceTreeNode;
27import cuchaz.enigma.analysis.SourceIndex; 28import cuchaz.enigma.analysis.SourceIndex;
28import cuchaz.enigma.analysis.Token; 29import cuchaz.enigma.analysis.Token;
30import cuchaz.enigma.mapping.BehaviorEntry;
29import cuchaz.enigma.mapping.ClassEntry; 31import cuchaz.enigma.mapping.ClassEntry;
30import cuchaz.enigma.mapping.ConstructorEntry;
31import cuchaz.enigma.mapping.Entry; 32import cuchaz.enigma.mapping.Entry;
32import cuchaz.enigma.mapping.EntryPair; 33import cuchaz.enigma.mapping.EntryPair;
33import cuchaz.enigma.mapping.FieldEntry; 34import cuchaz.enigma.mapping.FieldEntry;
@@ -44,7 +45,7 @@ public class GuiController
44 private SourceIndex m_index; 45 private SourceIndex m_index;
45 private ClassEntry m_currentClass; 46 private ClassEntry m_currentClass;
46 private boolean m_isDirty; 47 private boolean m_isDirty;
47 private Stack<Entry> m_entryStack; 48 private Stack<Entry> m_locationStack; // TODO: make a location class, can be either Entry or EntryReference
48 49
49 public GuiController( Gui gui ) 50 public GuiController( Gui gui )
50 { 51 {
@@ -53,7 +54,7 @@ public class GuiController
53 m_index = null; 54 m_index = null;
54 m_currentClass = null; 55 m_currentClass = null;
55 m_isDirty = false; 56 m_isDirty = false;
56 m_entryStack = new Stack<Entry>(); 57 m_locationStack = new Stack<Entry>();
57 } 58 }
58 59
59 public boolean isDirty( ) 60 public boolean isDirty( )
@@ -157,9 +158,9 @@ public class GuiController
157 return MethodInheritanceTreeNode.findNode( rootNode, obfMethodEntry ); 158 return MethodInheritanceTreeNode.findNode( rootNode, obfMethodEntry );
158 } 159 }
159 160
160 public FieldCallsTreeNode getFieldCalls( FieldEntry obfFieldEntry ) 161 public FieldReferenceTreeNode getFieldReferences( FieldEntry obfFieldEntry )
161 { 162 {
162 FieldCallsTreeNode rootNode = new FieldCallsTreeNode( 163 FieldReferenceTreeNode rootNode = new FieldReferenceTreeNode(
163 m_deobfuscator.getTranslator( TranslationDirection.Deobfuscating ), 164 m_deobfuscator.getTranslator( TranslationDirection.Deobfuscating ),
164 obfFieldEntry 165 obfFieldEntry
165 ); 166 );
@@ -167,27 +168,12 @@ public class GuiController
167 return rootNode; 168 return rootNode;
168 } 169 }
169 170
170 public MethodCallsTreeNode getMethodCalls( Entry obfEntry ) 171 public BehaviorReferenceTreeNode getMethodReferences( BehaviorEntry obfEntry )
171 { 172 {
172 MethodCallsTreeNode rootNode; 173 BehaviorReferenceTreeNode rootNode = new BehaviorReferenceTreeNode(
173 if( obfEntry instanceof MethodEntry ) 174 m_deobfuscator.getTranslator( TranslationDirection.Deobfuscating ),
174 { 175 obfEntry
175 rootNode = new MethodCallsTreeNode( 176 );
176 m_deobfuscator.getTranslator( TranslationDirection.Deobfuscating ),
177 (MethodEntry)obfEntry
178 );
179 }
180 else if( obfEntry instanceof ConstructorEntry )
181 {
182 rootNode = new MethodCallsTreeNode(
183 m_deobfuscator.getTranslator( TranslationDirection.Deobfuscating ),
184 (ConstructorEntry)obfEntry
185 );
186 }
187 else
188 {
189 throw new IllegalArgumentException( "entry must be a MethodEntry or a ConstructorEntry!" );
190 }
191 rootNode.load( m_deobfuscator.getJarIndex(), true ); 177 rootNode.load( m_deobfuscator.getJarIndex(), true );
192 return rootNode; 178 return rootNode;
193 } 179 }
@@ -200,7 +186,7 @@ public class GuiController
200 refreshCurrentClass( obfEntry ); 186 refreshCurrentClass( obfEntry );
201 } 187 }
202 188
203 public void openEntry( Entry entry ) 189 public void openDeclaration( Entry entry )
204 { 190 {
205 // go to the entry 191 // go to the entry
206 Entry obfEntry = m_deobfuscator.obfuscateEntry( entry ); 192 Entry obfEntry = m_deobfuscator.obfuscateEntry( entry );
@@ -214,25 +200,32 @@ public class GuiController
214 m_gui.showToken( m_index.getDeclarationToken( m_deobfuscator.deobfuscateEntry( obfEntry ) ) ); 200 m_gui.showToken( m_index.getDeclarationToken( m_deobfuscator.deobfuscateEntry( obfEntry ) ) );
215 } 201 }
216 202
217 if( m_entryStack.isEmpty() || !m_entryStack.peek().equals( obfEntry ) ) 203 if( m_locationStack.isEmpty() || !m_locationStack.peek().equals( obfEntry ) )
218 { 204 {
219 // update the stack 205 // update the stack
220 m_entryStack.push( obfEntry ); 206 m_locationStack.push( obfEntry );
221 } 207 }
222 } 208 }
223 209
224 public void openPreviousEntry( ) 210 public void openReference( EntryReference<Entry> reference )
211 {
212 // TODO: find out how to load the n-th reference in a caller
213 // TEMP: just go to the caller for now
214 openDeclaration( reference.caller );
215 }
216
217 public void openPreviousLocation( )
225 { 218 {
226 if( hasPreviousEntry() ) 219 if( hasPreviousLocation() )
227 { 220 {
228 m_entryStack.pop(); 221 m_locationStack.pop();
229 openEntry( m_entryStack.peek() ); 222 openDeclaration( m_locationStack.peek() );
230 } 223 }
231 } 224 }
232 225
233 public boolean hasPreviousEntry( ) 226 public boolean hasPreviousLocation( )
234 { 227 {
235 return m_entryStack.size() > 1; 228 return m_locationStack.size() > 1;
236 } 229 }
237 230
238 private void refreshClasses( ) 231 private void refreshClasses( )
diff --git a/src/cuchaz/enigma/mapping/BehaviorEntry.java b/src/cuchaz/enigma/mapping/BehaviorEntry.java
new file mode 100644
index 0000000..99fdd28
--- /dev/null
+++ b/src/cuchaz/enigma/mapping/BehaviorEntry.java
@@ -0,0 +1,6 @@
1package cuchaz.enigma.mapping;
2
3public interface BehaviorEntry extends Entry
4{
5 public String getSignature();
6}
diff --git a/src/cuchaz/enigma/mapping/ConstructorEntry.java b/src/cuchaz/enigma/mapping/ConstructorEntry.java
index e0fa7cf..0f7dab6 100644
--- a/src/cuchaz/enigma/mapping/ConstructorEntry.java
+++ b/src/cuchaz/enigma/mapping/ConstructorEntry.java
@@ -14,7 +14,7 @@ import java.io.Serializable;
14 14
15import cuchaz.enigma.Util; 15import cuchaz.enigma.Util;
16 16
17public class ConstructorEntry implements Entry, Serializable 17public class ConstructorEntry implements BehaviorEntry, Serializable
18{ 18{
19 private static final long serialVersionUID = -868346075317366758L; 19 private static final long serialVersionUID = -868346075317366758L;
20 20
@@ -54,6 +54,7 @@ public class ConstructorEntry implements Entry, Serializable
54 return m_classEntry.getName(); 54 return m_classEntry.getName();
55 } 55 }
56 56
57 @Override
57 public String getSignature( ) 58 public String getSignature( )
58 { 59 {
59 return m_signature; 60 return m_signature;
diff --git a/src/cuchaz/enigma/mapping/MethodEntry.java b/src/cuchaz/enigma/mapping/MethodEntry.java
index b4b9c9b..a311e63 100644
--- a/src/cuchaz/enigma/mapping/MethodEntry.java
+++ b/src/cuchaz/enigma/mapping/MethodEntry.java
@@ -14,7 +14,7 @@ import java.io.Serializable;
14 14
15import cuchaz.enigma.Util; 15import cuchaz.enigma.Util;
16 16
17public class MethodEntry implements Entry, Serializable 17public class MethodEntry implements BehaviorEntry, Serializable
18{ 18{
19 private static final long serialVersionUID = 4770915224467247458L; 19 private static final long serialVersionUID = 4770915224467247458L;
20 20
@@ -68,6 +68,7 @@ public class MethodEntry implements Entry, Serializable
68 return m_name; 68 return m_name;
69 } 69 }
70 70
71 @Override
71 public String getSignature( ) 72 public String getSignature( )
72 { 73 {
73 return m_signature; 74 return m_signature;
diff --git a/src/cuchaz/enigma/mapping/Translator.java b/src/cuchaz/enigma/mapping/Translator.java
index fc41f94..a1230db 100644
--- a/src/cuchaz/enigma/mapping/Translator.java
+++ b/src/cuchaz/enigma/mapping/Translator.java
@@ -172,6 +172,19 @@ public class Translator
172 ); 172 );
173 } 173 }
174 174
175 public BehaviorEntry translateEntry( BehaviorEntry in )
176 {
177 if( in instanceof MethodEntry )
178 {
179 return translateEntry( (MethodEntry)in );
180 }
181 else if( in instanceof ConstructorEntry )
182 {
183 return translateEntry( (ConstructorEntry)in );
184 }
185 throw new Error( "Wrong entry type!" );
186 }
187
175 public String translate( ArgumentEntry in ) 188 public String translate( ArgumentEntry in )
176 { 189 {
177 for( String className : getSelfAndAncestors( in.getClassName() ) ) 190 for( String className : getSelfAndAncestors( in.getClassName() ) )