summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar jeff2014-09-28 15:20:54 -0400
committerGravatar jeff2014-09-28 15:20:54 -0400
commitcf3ffcee30083a71e68e3edb9ecbb936cc255992 (patch)
treef9a6415d7eef1e76640b07238d2d08daecedde17
parentimplemented mark-as-deobfuscated and reset-to-obfuscated (diff)
downloadenigma-cf3ffcee30083a71e68e3edb9ecbb936cc255992.tar.gz
enigma-cf3ffcee30083a71e68e3edb9ecbb936cc255992.tar.xz
enigma-cf3ffcee30083a71e68e3edb9ecbb936cc255992.zip
added proper support for renaming constructors
-rw-r--r--src/cuchaz/enigma/Deobfuscator.java70
-rw-r--r--src/cuchaz/enigma/analysis/EntryReference.java43
-rw-r--r--src/cuchaz/enigma/analysis/JarIndex.java7
-rw-r--r--src/cuchaz/enigma/analysis/SourceIndex.java29
-rw-r--r--src/cuchaz/enigma/analysis/SourceIndexBehaviorVisitor.java27
-rw-r--r--src/cuchaz/enigma/analysis/SourceIndexClassVisitor.java6
-rw-r--r--src/cuchaz/enigma/analysis/Token.java10
-rw-r--r--src/cuchaz/enigma/analysis/TreeDumpVisitor.java2
-rw-r--r--src/cuchaz/enigma/gui/Gui.java15
-rw-r--r--src/cuchaz/enigma/gui/GuiController.java34
-rw-r--r--test/cuchaz/enigma/EntryFactory.java8
11 files changed, 159 insertions, 92 deletions
diff --git a/src/cuchaz/enigma/Deobfuscator.java b/src/cuchaz/enigma/Deobfuscator.java
index 44845ba2..ff83d21a 100644
--- a/src/cuchaz/enigma/Deobfuscator.java
+++ b/src/cuchaz/enigma/Deobfuscator.java
@@ -40,6 +40,7 @@ import cuchaz.enigma.analysis.JarIndex;
40import cuchaz.enigma.analysis.SourceIndex; 40import cuchaz.enigma.analysis.SourceIndex;
41import cuchaz.enigma.analysis.SourceIndexVisitor; 41import cuchaz.enigma.analysis.SourceIndexVisitor;
42import cuchaz.enigma.analysis.Token; 42import cuchaz.enigma.analysis.Token;
43import cuchaz.enigma.analysis.TreeDumpVisitor;
43import cuchaz.enigma.mapping.ArgumentEntry; 44import cuchaz.enigma.mapping.ArgumentEntry;
44import cuchaz.enigma.mapping.BehaviorEntry; 45import cuchaz.enigma.mapping.BehaviorEntry;
45import cuchaz.enigma.mapping.BehaviorEntryFactory; 46import cuchaz.enigma.mapping.BehaviorEntryFactory;
@@ -337,7 +338,7 @@ public class Deobfuscator
337 338
338 // DEBUG 339 // DEBUG
339 //sourceTree.acceptVisitor( new TreeDumpVisitor( new File( "tree.txt" ) ), null ); 340 //sourceTree.acceptVisitor( new TreeDumpVisitor( new File( "tree.txt" ) ), null );
340 341
341 // resolve all the classes in the source references 342 // resolve all the classes in the source references
342 for( Token token : index.referenceTokens() ) 343 for( Token token : index.referenceTokens() )
343 { 344 {
@@ -454,7 +455,8 @@ public class Deobfuscator
454 } 455 }
455 return new EntryReference<E,C>( 456 return new EntryReference<E,C>(
456 obfuscateEntry( deobfReference.entry ), 457 obfuscateEntry( deobfReference.entry ),
457 obfuscateEntry( deobfReference.context ) 458 obfuscateEntry( deobfReference.context ),
459 deobfReference
458 ); 460 );
459 } 461 }
460 462
@@ -466,75 +468,83 @@ public class Deobfuscator
466 } 468 }
467 return new EntryReference<E,C>( 469 return new EntryReference<E,C>(
468 deobfuscateEntry( obfReference.entry ), 470 deobfuscateEntry( obfReference.entry ),
469 deobfuscateEntry( obfReference.context ) 471 deobfuscateEntry( obfReference.context ),
472 obfReference
470 ); 473 );
471 } 474 }
472 475
476 public boolean isObfuscatedIdentifier( Entry obfEntry )
477 {
478 return m_jarIndex.containsObfEntry( obfEntry );
479 }
480
481 public boolean isRenameable( EntryReference<Entry,Entry> obfReference )
482 {
483 return obfReference.isNamed() && isObfuscatedIdentifier( obfReference.getNameableEntry() );
484 }
485
486
473 // NOTE: these methods are a bit messy... oh well 487 // NOTE: these methods are a bit messy... oh well
474 488
475 public void rename( Entry obfEntry, String newName ) 489 public boolean hasDeobfuscatedName( Entry obfEntry )
476 { 490 {
491 Translator translator = getTranslator( TranslationDirection.Deobfuscating );
477 if( obfEntry instanceof ClassEntry ) 492 if( obfEntry instanceof ClassEntry )
478 { 493 {
479 m_renamer.setClassName( (ClassEntry)obfEntry, Descriptor.toJvmName( newName ) ); 494 return translator.translate( (ClassEntry)obfEntry ) != null;
480 } 495 }
481 else if( obfEntry instanceof FieldEntry ) 496 else if( obfEntry instanceof FieldEntry )
482 { 497 {
483 m_renamer.setFieldName( (FieldEntry)obfEntry, newName ); 498 return translator.translate( (FieldEntry)obfEntry ) != null;
484 } 499 }
485 else if( obfEntry instanceof MethodEntry ) 500 else if( obfEntry instanceof MethodEntry )
486 { 501 {
487 m_renamer.setMethodTreeName( (MethodEntry)obfEntry, newName ); 502 return translator.translate( (MethodEntry)obfEntry ) != null;
488 } 503 }
489 else if( obfEntry instanceof ConstructorEntry ) 504 else if( obfEntry instanceof ConstructorEntry )
490 { 505 {
491 m_renamer.setClassName( obfEntry.getClassEntry(), newName ); 506 // constructors have no names
507 return false;
492 } 508 }
493 else if( obfEntry instanceof ArgumentEntry ) 509 else if( obfEntry instanceof ArgumentEntry )
494 { 510 {
495 m_renamer.setArgumentName( (ArgumentEntry)obfEntry, newName ); 511 return translator.translate( (ArgumentEntry)obfEntry ) != null;
496 } 512 }
497 else 513 else
498 { 514 {
499 throw new Error( "Unknown entry type: " + obfEntry.getClass().getName() ); 515 throw new Error( "Unknown entry type: " + obfEntry.getClass().getName() );
500 } 516 }
501
502 // clear caches
503 m_translatorCache.clear();
504 } 517 }
505 518
506 public boolean hasMapping( Entry obfEntry ) 519 public void rename( Entry obfEntry, String newName )
507 { 520 {
508 Translator translator = getTranslator( TranslationDirection.Deobfuscating );
509 if( obfEntry instanceof ClassEntry ) 521 if( obfEntry instanceof ClassEntry )
510 { 522 {
511 return translator.translate( (ClassEntry)obfEntry ) != null; 523 m_renamer.setClassName( (ClassEntry)obfEntry, Descriptor.toJvmName( newName ) );
512 } 524 }
513 else if( obfEntry instanceof FieldEntry ) 525 else if( obfEntry instanceof FieldEntry )
514 { 526 {
515 return translator.translate( (FieldEntry)obfEntry ) != null; 527 m_renamer.setFieldName( (FieldEntry)obfEntry, newName );
516 } 528 }
517 else if( obfEntry instanceof MethodEntry ) 529 else if( obfEntry instanceof MethodEntry )
518 { 530 {
519 return translator.translate( (MethodEntry)obfEntry ) != null; 531 m_renamer.setMethodTreeName( (MethodEntry)obfEntry, newName );
520 } 532 }
521 else if( obfEntry instanceof ConstructorEntry ) 533 else if( obfEntry instanceof ConstructorEntry )
522 { 534 {
523 return translator.translate( obfEntry.getClassEntry() ) != null; 535 throw new IllegalArgumentException( "Cannot rename constructors" );
524 } 536 }
525 else if( obfEntry instanceof ArgumentEntry ) 537 else if( obfEntry instanceof ArgumentEntry )
526 { 538 {
527 return translator.translate( (ArgumentEntry)obfEntry ) != null; 539 m_renamer.setArgumentName( (ArgumentEntry)obfEntry, newName );
528 } 540 }
529 else 541 else
530 { 542 {
531 throw new Error( "Unknown entry type: " + obfEntry.getClass().getName() ); 543 throw new Error( "Unknown entry type: " + obfEntry.getClass().getName() );
532 } 544 }
533 } 545
534 546 // clear caches
535 public boolean isObfuscatedIdentifier( Entry obfEntry ) 547 m_translatorCache.clear();
536 {
537 return m_jarIndex.containsObfEntry( obfEntry );
538 } 548 }
539 549
540 public void removeMapping( Entry obfEntry ) 550 public void removeMapping( Entry obfEntry )
@@ -553,7 +563,7 @@ public class Deobfuscator
553 } 563 }
554 else if( obfEntry instanceof ConstructorEntry ) 564 else if( obfEntry instanceof ConstructorEntry )
555 { 565 {
556 m_renamer.removeClassMapping( obfEntry.getClassEntry() ); 566 throw new IllegalArgumentException( "Cannot rename constructors" );
557 } 567 }
558 else if( obfEntry instanceof ArgumentEntry ) 568 else if( obfEntry instanceof ArgumentEntry )
559 { 569 {
@@ -563,6 +573,9 @@ public class Deobfuscator
563 { 573 {
564 throw new Error( "Unknown entry type: " + obfEntry ); 574 throw new Error( "Unknown entry type: " + obfEntry );
565 } 575 }
576
577 // clear caches
578 m_translatorCache.clear();
566 } 579 }
567 580
568 public void markAsDeobfuscated( Entry obfEntry ) 581 public void markAsDeobfuscated( Entry obfEntry )
@@ -581,7 +594,7 @@ public class Deobfuscator
581 } 594 }
582 else if( obfEntry instanceof ConstructorEntry ) 595 else if( obfEntry instanceof ConstructorEntry )
583 { 596 {
584 m_renamer.markClassAsDeobfuscated( obfEntry.getClassEntry() ); 597 throw new IllegalArgumentException( "Cannot rename constructors" );
585 } 598 }
586 else if( obfEntry instanceof ArgumentEntry ) 599 else if( obfEntry instanceof ArgumentEntry )
587 { 600 {
@@ -591,5 +604,8 @@ public class Deobfuscator
591 { 604 {
592 throw new Error( "Unknown entry type: " + obfEntry ); 605 throw new Error( "Unknown entry type: " + obfEntry );
593 } 606 }
607
608 // clear caches
609 m_translatorCache.clear();
594 } 610 }
595} 611}
diff --git a/src/cuchaz/enigma/analysis/EntryReference.java b/src/cuchaz/enigma/analysis/EntryReference.java
index 768c1132..df977fb5 100644
--- a/src/cuchaz/enigma/analysis/EntryReference.java
+++ b/src/cuchaz/enigma/analysis/EntryReference.java
@@ -10,21 +10,28 @@
10 ******************************************************************************/ 10 ******************************************************************************/
11package cuchaz.enigma.analysis; 11package cuchaz.enigma.analysis;
12 12
13import java.util.Arrays;
14import java.util.List;
15
13import cuchaz.enigma.Util; 16import cuchaz.enigma.Util;
14import cuchaz.enigma.mapping.ClassEntry; 17import cuchaz.enigma.mapping.ClassEntry;
18import cuchaz.enigma.mapping.ConstructorEntry;
15import cuchaz.enigma.mapping.Entry; 19import cuchaz.enigma.mapping.Entry;
16 20
17public class EntryReference<E extends Entry, C extends Entry> 21public class EntryReference<E extends Entry, C extends Entry>
18{ 22{
23 private static final List<String> ConstructorNonNames = Arrays.asList( "this", "super" );
19 public E entry; 24 public E entry;
20 public C context; 25 public C context;
21 26
22 public EntryReference( E entry ) 27 private boolean m_isNamed;
28
29 public EntryReference( E entry, String sourceName )
23 { 30 {
24 this( entry, null ); 31 this( entry, sourceName, null );
25 } 32 }
26 33
27 public EntryReference( E entry, C context ) 34 public EntryReference( E entry, String sourceName, C context )
28 { 35 {
29 if( entry == null ) 36 if( entry == null )
30 { 37 {
@@ -33,9 +40,22 @@ public class EntryReference<E extends Entry, C extends Entry>
33 40
34 this.entry = entry; 41 this.entry = entry;
35 this.context = context; 42 this.context = context;
43
44 m_isNamed = sourceName != null && sourceName.length() > 0;
45 if( entry instanceof ConstructorEntry && ConstructorNonNames.contains( sourceName ) )
46 {
47 m_isNamed = false;
48 }
49 }
50
51 public EntryReference( E entry, C context, EntryReference<E,C> other )
52 {
53 this.entry = entry;
54 this.context = context;
55 m_isNamed = other.m_isNamed;
36 } 56 }
37 57
38 public ClassEntry getClassEntry( ) 58 public ClassEntry getLocationClassEntry( )
39 { 59 {
40 if( context != null ) 60 if( context != null )
41 { 61 {
@@ -44,6 +64,21 @@ public class EntryReference<E extends Entry, C extends Entry>
44 return entry.getClassEntry(); 64 return entry.getClassEntry();
45 } 65 }
46 66
67 public boolean isNamed( )
68 {
69 return m_isNamed;
70 }
71
72 public Entry getNameableEntry( )
73 {
74 if( entry instanceof ConstructorEntry )
75 {
76 // renaming a constructor really means renaming the class
77 return entry.getClassEntry();
78 }
79 return entry;
80 }
81
47 @Override 82 @Override
48 public int hashCode( ) 83 public int hashCode( )
49 { 84 {
diff --git a/src/cuchaz/enigma/analysis/JarIndex.java b/src/cuchaz/enigma/analysis/JarIndex.java
index a2f6bf34..604e4853 100644
--- a/src/cuchaz/enigma/analysis/JarIndex.java
+++ b/src/cuchaz/enigma/analysis/JarIndex.java
@@ -277,6 +277,7 @@ public class JarIndex
277 } 277 }
278 EntryReference<BehaviorEntry,BehaviorEntry> reference = new EntryReference<BehaviorEntry,BehaviorEntry>( 278 EntryReference<BehaviorEntry,BehaviorEntry> reference = new EntryReference<BehaviorEntry,BehaviorEntry>(
279 calledMethodEntry, 279 calledMethodEntry,
280 call.getMethodName(),
280 behaviorEntry 281 behaviorEntry
281 ); 282 );
282 m_behaviorReferences.put( calledMethodEntry, reference ); 283 m_behaviorReferences.put( calledMethodEntry, reference );
@@ -300,6 +301,7 @@ public class JarIndex
300 } 301 }
301 EntryReference<FieldEntry,BehaviorEntry> reference = new EntryReference<FieldEntry,BehaviorEntry>( 302 EntryReference<FieldEntry,BehaviorEntry> reference = new EntryReference<FieldEntry,BehaviorEntry>(
302 calledFieldEntry, 303 calledFieldEntry,
304 call.getFieldName(),
303 behaviorEntry 305 behaviorEntry
304 ); 306 );
305 m_fieldReferences.put( calledFieldEntry, reference ); 307 m_fieldReferences.put( calledFieldEntry, reference );
@@ -308,9 +310,6 @@ public class JarIndex
308 @Override 310 @Override
309 public void edit( ConstructorCall call ) 311 public void edit( ConstructorCall call )
310 { 312 {
311 // TODO: save isSuper in the reference somehow
312 boolean isSuper = call.getMethodName().equals( "super" );
313
314 String className = Descriptor.toJvmName( call.getClassName() ); 313 String className = Descriptor.toJvmName( call.getClassName() );
315 ConstructorEntry calledConstructorEntry = new ConstructorEntry( 314 ConstructorEntry calledConstructorEntry = new ConstructorEntry(
316 new ClassEntry( className ), 315 new ClassEntry( className ),
@@ -318,6 +317,7 @@ public class JarIndex
318 ); 317 );
319 EntryReference<BehaviorEntry,BehaviorEntry> reference = new EntryReference<BehaviorEntry,BehaviorEntry>( 318 EntryReference<BehaviorEntry,BehaviorEntry> reference = new EntryReference<BehaviorEntry,BehaviorEntry>(
320 calledConstructorEntry, 319 calledConstructorEntry,
320 call.getMethodName(),
321 behaviorEntry 321 behaviorEntry
322 ); 322 );
323 m_behaviorReferences.put( calledConstructorEntry, reference ); 323 m_behaviorReferences.put( calledConstructorEntry, reference );
@@ -333,6 +333,7 @@ public class JarIndex
333 ); 333 );
334 EntryReference<BehaviorEntry,BehaviorEntry> reference = new EntryReference<BehaviorEntry,BehaviorEntry>( 334 EntryReference<BehaviorEntry,BehaviorEntry> reference = new EntryReference<BehaviorEntry,BehaviorEntry>(
335 calledConstructorEntry, 335 calledConstructorEntry,
336 call.getClassName(),
336 behaviorEntry 337 behaviorEntry
337 ); 338 );
338 m_behaviorReferences.put( calledConstructorEntry, reference ); 339 m_behaviorReferences.put( calledConstructorEntry, reference );
diff --git a/src/cuchaz/enigma/analysis/SourceIndex.java b/src/cuchaz/enigma/analysis/SourceIndex.java
index 38d10daa..faae1a14 100644
--- a/src/cuchaz/enigma/analysis/SourceIndex.java
+++ b/src/cuchaz/enigma/analysis/SourceIndex.java
@@ -21,6 +21,7 @@ import com.google.common.collect.Maps;
21import com.google.common.collect.Multimap; 21import com.google.common.collect.Multimap;
22import com.strobel.decompiler.languages.Region; 22import com.strobel.decompiler.languages.Region;
23import com.strobel.decompiler.languages.java.ast.AstNode; 23import com.strobel.decompiler.languages.java.ast.AstNode;
24import com.strobel.decompiler.languages.java.ast.Identifier;
24 25
25import cuchaz.enigma.mapping.Entry; 26import cuchaz.enigma.mapping.Entry;
26 27
@@ -58,40 +59,54 @@ public class SourceIndex
58 59
59 public Token getToken( AstNode node ) 60 public Token getToken( AstNode node )
60 { 61 {
62 // get the text of the node
63 String name = "";
64 if( node instanceof Identifier )
65 {
66 name = ((Identifier)node).getName();
67 }
68
61 // get a token for this node's region 69 // get a token for this node's region
62 Region region = node.getRegion(); 70 Region region = node.getRegion();
63 if( region.getBeginLine() == 0 || region.getEndLine() == 0 ) 71 if( region.getBeginLine() == 0 || region.getEndLine() == 0 )
64 { 72 {
65 // DEBUG 73 // DEBUG
66 //System.err.println( "WARNING: " + node.getNodeType() + " node has invalid region: " + region ); 74 System.err.println( String.format( "WARNING: %s \"%s\" has invalid region: %s", node.getNodeType(), name, region ) );
67 return null; 75 return null;
68 } 76 }
69 Token token = new Token( 77 Token token = new Token(
70 toPos( region.getBeginLine(), region.getBeginColumn() ), 78 toPos( region.getBeginLine(), region.getBeginColumn() ),
71 toPos( region.getEndLine(), region.getEndColumn() ) 79 toPos( region.getEndLine(), region.getEndColumn() ),
80 m_source
72 ); 81 );
73 if( token.start == 0 ) 82 if( token.start == 0 )
74 { 83 {
75 // DEBUG 84 // DEBUG
76 //System.err.println( "WARNING: " + node.getNodeType() + " node has invalid start: " + region ); 85 System.err.println( String.format( "WARNING: %s \"%s\" has invalid start: %s", node.getNodeType(), name, region ) );
77 return null; 86 return null;
78 } 87 }
79 88
89 // DEBUG
90 //System.out.println( String.format( "%s \"%s\" region: %s", node.getNodeType(), name, region ) );
91
92 /* TODO: double check that we still need this
80 // for tokens representing inner classes, make sure we only get the simple name 93 // for tokens representing inner classes, make sure we only get the simple name
81 int pos = node.toString().lastIndexOf( '$' ); 94 int pos = node.getText().lastIndexOf( '$' );
82 if( pos >= 0 ) 95 if( pos >= 0 )
83 { 96 {
84 token.end -= pos + 1; 97 token.end -= pos + 1;
85 } 98 }
99 */
86 100
87 return token; 101 return token;
88 } 102 }
89 103
90 public void addReference( AstNode node, EntryReference<Entry,Entry> deobfReference ) 104 public void addReference( AstNode node, Entry deobfEntry, Entry deobfContext )
91 { 105 {
92 Token token = getToken( node ); 106 Token token = getToken( node );
93 if( token != null ) 107 if( token != null )
94 { 108 {
109 EntryReference<Entry,Entry> deobfReference = new EntryReference<Entry,Entry>( deobfEntry, token.text, deobfContext );
95 m_tokenToReference.put( token, deobfReference ); 110 m_tokenToReference.put( token, deobfReference );
96 m_referenceToTokens.put( deobfReference, token ); 111 m_referenceToTokens.put( deobfReference, token );
97 } 112 }
@@ -102,7 +117,7 @@ public class SourceIndex
102 Token token = getToken( node ); 117 Token token = getToken( node );
103 if( token != null ) 118 if( token != null )
104 { 119 {
105 EntryReference<Entry,Entry> reference = new EntryReference<Entry,Entry>( deobfEntry ); 120 EntryReference<Entry,Entry> reference = new EntryReference<Entry,Entry>( deobfEntry, token.text );
106 m_tokenToReference.put( token, reference ); 121 m_tokenToReference.put( token, reference );
107 m_referenceToTokens.put( reference, token ); 122 m_referenceToTokens.put( reference, token );
108 m_declarationToToken.put( deobfEntry, token ); 123 m_declarationToToken.put( deobfEntry, token );
@@ -111,7 +126,7 @@ public class SourceIndex
111 126
112 public Token getReferenceToken( int pos ) 127 public Token getReferenceToken( int pos )
113 { 128 {
114 Token token = m_tokenToReference.floorKey( new Token( pos, pos ) ); 129 Token token = m_tokenToReference.floorKey( new Token( pos, pos, null ) );
115 if( token != null && token.contains( pos ) ) 130 if( token != null && token.contains( pos ) )
116 { 131 {
117 return token; 132 return token;
diff --git a/src/cuchaz/enigma/analysis/SourceIndexBehaviorVisitor.java b/src/cuchaz/enigma/analysis/SourceIndexBehaviorVisitor.java
index f307c11d..b883087c 100644
--- a/src/cuchaz/enigma/analysis/SourceIndexBehaviorVisitor.java
+++ b/src/cuchaz/enigma/analysis/SourceIndexBehaviorVisitor.java
@@ -33,7 +33,6 @@ import cuchaz.enigma.mapping.ArgumentEntry;
33import cuchaz.enigma.mapping.BehaviorEntry; 33import cuchaz.enigma.mapping.BehaviorEntry;
34import cuchaz.enigma.mapping.ClassEntry; 34import cuchaz.enigma.mapping.ClassEntry;
35import cuchaz.enigma.mapping.ConstructorEntry; 35import cuchaz.enigma.mapping.ConstructorEntry;
36import cuchaz.enigma.mapping.Entry;
37import cuchaz.enigma.mapping.FieldEntry; 36import cuchaz.enigma.mapping.FieldEntry;
38import cuchaz.enigma.mapping.MethodEntry; 37import cuchaz.enigma.mapping.MethodEntry;
39 38
@@ -100,10 +99,7 @@ public class SourceIndexBehaviorVisitor extends SourceIndexVisitor
100 } 99 }
101 if( tokenNode != null ) 100 if( tokenNode != null )
102 { 101 {
103 index.addReference( 102 index.addReference( tokenNode, behaviorEntry, m_behaviorEntry );
104 tokenNode,
105 new EntryReference<Entry,Entry>( behaviorEntry, m_behaviorEntry )
106 );
107 } 103 }
108 } 104 }
109 105
@@ -124,10 +120,7 @@ public class SourceIndexBehaviorVisitor extends SourceIndexVisitor
124 120
125 ClassEntry classEntry = new ClassEntry( ref.getDeclaringType().getInternalName() ); 121 ClassEntry classEntry = new ClassEntry( ref.getDeclaringType().getInternalName() );
126 FieldEntry fieldEntry = new FieldEntry( classEntry, ref.getName() ); 122 FieldEntry fieldEntry = new FieldEntry( classEntry, ref.getName() );
127 index.addReference( 123 index.addReference( node.getMemberNameToken(), fieldEntry, m_behaviorEntry );
128 node.getMemberNameToken(),
129 new EntryReference<Entry,Entry>( fieldEntry, m_behaviorEntry )
130 );
131 } 124 }
132 125
133 return recurse( node, index ); 126 return recurse( node, index );
@@ -140,10 +133,7 @@ public class SourceIndexBehaviorVisitor extends SourceIndexVisitor
140 if( node.getIdentifierToken().getStartLocation() != TextLocation.EMPTY ) 133 if( node.getIdentifierToken().getStartLocation() != TextLocation.EMPTY )
141 { 134 {
142 ClassEntry classEntry = new ClassEntry( ref.getInternalName() ); 135 ClassEntry classEntry = new ClassEntry( ref.getInternalName() );
143 index.addReference( 136 index.addReference( node.getIdentifierToken(), classEntry, m_behaviorEntry );
144 node.getIdentifierToken(),
145 new EntryReference<Entry,Entry>( classEntry, m_behaviorEntry )
146 );
147 } 137 }
148 138
149 return recurse( node, index ); 139 return recurse( node, index );
@@ -178,10 +168,7 @@ public class SourceIndexBehaviorVisitor extends SourceIndexVisitor
178 { 168 {
179 ClassEntry classEntry = new ClassEntry( ref.getDeclaringType().getInternalName() ); 169 ClassEntry classEntry = new ClassEntry( ref.getDeclaringType().getInternalName() );
180 FieldEntry fieldEntry = new FieldEntry( classEntry, ref.getName() ); 170 FieldEntry fieldEntry = new FieldEntry( classEntry, ref.getName() );
181 index.addReference( 171 index.addReference( node.getIdentifierToken(), fieldEntry, m_behaviorEntry );
182 node.getIdentifierToken(),
183 new EntryReference<Entry,Entry>( fieldEntry, m_behaviorEntry )
184 );
185 } 172 }
186 173
187 return recurse( node, index ); 174 return recurse( node, index );
@@ -197,10 +184,8 @@ public class SourceIndexBehaviorVisitor extends SourceIndexVisitor
197 ConstructorEntry constructorEntry = new ConstructorEntry( classEntry, ref.getSignature() ); 184 ConstructorEntry constructorEntry = new ConstructorEntry( classEntry, ref.getSignature() );
198 if( node.getType() instanceof SimpleType ) 185 if( node.getType() instanceof SimpleType )
199 { 186 {
200 index.addReference( 187 SimpleType simpleTypeNode = (SimpleType)node.getType();
201 ((SimpleType)node.getType()).getIdentifierToken(), 188 index.addReference( simpleTypeNode.getIdentifierToken(), constructorEntry, m_behaviorEntry );
202 new EntryReference<Entry,Entry>( constructorEntry, m_behaviorEntry )
203 );
204 } 189 }
205 } 190 }
206 191
diff --git a/src/cuchaz/enigma/analysis/SourceIndexClassVisitor.java b/src/cuchaz/enigma/analysis/SourceIndexClassVisitor.java
index 5d8a3833..fc8cd665 100644
--- a/src/cuchaz/enigma/analysis/SourceIndexClassVisitor.java
+++ b/src/cuchaz/enigma/analysis/SourceIndexClassVisitor.java
@@ -28,7 +28,6 @@ import cuchaz.enigma.mapping.BehaviorEntry;
28import cuchaz.enigma.mapping.BehaviorEntryFactory; 28import cuchaz.enigma.mapping.BehaviorEntryFactory;
29import cuchaz.enigma.mapping.ClassEntry; 29import cuchaz.enigma.mapping.ClassEntry;
30import cuchaz.enigma.mapping.ConstructorEntry; 30import cuchaz.enigma.mapping.ConstructorEntry;
31import cuchaz.enigma.mapping.Entry;
32import cuchaz.enigma.mapping.FieldEntry; 31import cuchaz.enigma.mapping.FieldEntry;
33 32
34public class SourceIndexClassVisitor extends SourceIndexVisitor 33public class SourceIndexClassVisitor extends SourceIndexVisitor
@@ -63,10 +62,7 @@ public class SourceIndexClassVisitor extends SourceIndexVisitor
63 if( node.getIdentifierToken().getStartLocation() != TextLocation.EMPTY ) 62 if( node.getIdentifierToken().getStartLocation() != TextLocation.EMPTY )
64 { 63 {
65 ClassEntry classEntry = new ClassEntry( ref.getInternalName() ); 64 ClassEntry classEntry = new ClassEntry( ref.getInternalName() );
66 index.addReference( 65 index.addReference( node.getIdentifierToken(), classEntry, m_classEntry );
67 node.getIdentifierToken(),
68 new EntryReference<Entry,Entry>( classEntry, m_classEntry )
69 );
70 } 66 }
71 67
72 return recurse( node, index ); 68 return recurse( node, index );
diff --git a/src/cuchaz/enigma/analysis/Token.java b/src/cuchaz/enigma/analysis/Token.java
index d0f2b70b..5e70db71 100644
--- a/src/cuchaz/enigma/analysis/Token.java
+++ b/src/cuchaz/enigma/analysis/Token.java
@@ -14,11 +14,21 @@ public class Token implements Comparable<Token>
14{ 14{
15 public int start; 15 public int start;
16 public int end; 16 public int end;
17 public String text;
17 18
18 public Token( int start, int end ) 19 public Token( int start, int end )
19 { 20 {
21 this( start, end, null );
22 }
23
24 public Token( int start, int end, String source )
25 {
20 this.start = start; 26 this.start = start;
21 this.end = end; 27 this.end = end;
28 if( source != null )
29 {
30 this.text = source.substring( start, end );
31 }
22 } 32 }
23 33
24 public boolean contains( int pos ) 34 public boolean contains( int pos )
diff --git a/src/cuchaz/enigma/analysis/TreeDumpVisitor.java b/src/cuchaz/enigma/analysis/TreeDumpVisitor.java
index 12febefd..e6ecb10e 100644
--- a/src/cuchaz/enigma/analysis/TreeDumpVisitor.java
+++ b/src/cuchaz/enigma/analysis/TreeDumpVisitor.java
@@ -141,7 +141,7 @@ public class TreeDumpVisitor implements IAstVisitor<Void, Void>
141 { 141 {
142 if( node instanceof Identifier ) 142 if( node instanceof Identifier )
143 { 143 {
144 return "\"" + node.getText() + "\""; 144 return "\"" + ((Identifier)node).getName() + "\"";
145 } 145 }
146 return ""; 146 return "";
147 } 147 }
diff --git a/src/cuchaz/enigma/gui/Gui.java b/src/cuchaz/enigma/gui/Gui.java
index 8bf6ce95..920bc0b9 100644
--- a/src/cuchaz/enigma/gui/Gui.java
+++ b/src/cuchaz/enigma/gui/Gui.java
@@ -1038,6 +1038,7 @@ public class Gui
1038 boolean isMethodEntry = isToken && m_reference.entry instanceof MethodEntry; 1038 boolean isMethodEntry = isToken && m_reference.entry instanceof MethodEntry;
1039 boolean isConstructorEntry = isToken && m_reference.entry instanceof ConstructorEntry; 1039 boolean isConstructorEntry = isToken && m_reference.entry instanceof ConstructorEntry;
1040 boolean isInJar = isToken && m_controller.entryIsInJar( m_reference.entry ); 1040 boolean isInJar = isToken && m_controller.entryIsInJar( m_reference.entry );
1041 boolean isRenameable = isToken && m_controller.referenceIsRenameable( m_reference );
1041 1042
1042 if( isToken ) 1043 if( isToken )
1043 { 1044 {
@@ -1048,15 +1049,15 @@ public class Gui
1048 clearReference(); 1049 clearReference();
1049 } 1050 }
1050 1051
1051 m_renameMenu.setEnabled( isInJar && isToken ); 1052 m_renameMenu.setEnabled( isRenameable && isToken );
1052 m_showInheritanceMenu.setEnabled( isClassEntry || isMethodEntry || isConstructorEntry ); 1053 m_showInheritanceMenu.setEnabled( isClassEntry || isMethodEntry || isConstructorEntry );
1053 m_showImplementationsMenu.setEnabled( isClassEntry || isMethodEntry ); 1054 m_showImplementationsMenu.setEnabled( isClassEntry || isMethodEntry );
1054 m_showCallsMenu.setEnabled( isClassEntry || isFieldEntry || isMethodEntry || isConstructorEntry ); 1055 m_showCallsMenu.setEnabled( isClassEntry || isFieldEntry || isMethodEntry || isConstructorEntry );
1055 m_openEntryMenu.setEnabled( isInJar && ( isClassEntry || isFieldEntry || isMethodEntry || isConstructorEntry ) ); 1056 m_openEntryMenu.setEnabled( isInJar && ( isClassEntry || isFieldEntry || isMethodEntry || isConstructorEntry ) );
1056 m_openPreviousMenu.setEnabled( m_controller.hasPreviousLocation() ); 1057 m_openPreviousMenu.setEnabled( m_controller.hasPreviousLocation() );
1057 m_toggleMappingMenu.setEnabled( isInJar && isToken ); 1058 m_toggleMappingMenu.setEnabled( isRenameable && isToken );
1058 1059
1059 if( isToken && m_controller.entryHasMapping( m_reference.entry ) ) 1060 if( isToken && m_controller.entryHasDeobfuscatedName( m_reference.entry ) )
1060 { 1061 {
1061 m_toggleMappingMenu.setText( "Reset to obfuscated" ); 1062 m_toggleMappingMenu.setText( "Reset to obfuscated" );
1062 } 1063 }
@@ -1082,7 +1083,7 @@ public class Gui
1082 1083
1083 private void navigateTo( EntryReference<Entry,Entry> reference ) 1084 private void navigateTo( EntryReference<Entry,Entry> reference )
1084 { 1085 {
1085 if( !m_controller.entryIsInJar( reference.getClassEntry() ) ) 1086 if( !m_controller.entryIsInJar( reference.getLocationClassEntry() ) )
1086 { 1087 {
1087 // reference is not in the jar. Ignore it 1088 // reference is not in the jar. Ignore it
1088 return; 1089 return;
@@ -1098,7 +1099,7 @@ public class Gui
1098 { 1099 {
1099 // init the text box 1100 // init the text box
1100 final JTextField text = new JTextField(); 1101 final JTextField text = new JTextField();
1101 text.setText( m_reference.entry.getName() ); 1102 text.setText( m_reference.getNameableEntry().getName() );
1102 text.setPreferredSize( new Dimension( 360, text.getPreferredSize().height ) ); 1103 text.setPreferredSize( new Dimension( 360, text.getPreferredSize().height ) );
1103 text.addKeyListener( new KeyAdapter( ) 1104 text.addKeyListener( new KeyAdapter( )
1104 { 1105 {
@@ -1149,7 +1150,7 @@ public class Gui
1149 // abort the rename 1150 // abort the rename
1150 JPanel panel = (JPanel)m_infoPanel.getComponent( 0 ); 1151 JPanel panel = (JPanel)m_infoPanel.getComponent( 0 );
1151 panel.remove( panel.getComponentCount() - 1 ); 1152 panel.remove( panel.getComponentCount() - 1 );
1152 panel.add( GuiTricks.unboldLabel( new JLabel( m_reference.entry.getName(), JLabel.LEFT ) ) ); 1153 panel.add( GuiTricks.unboldLabel( new JLabel( m_reference.getNameableEntry().getName(), JLabel.LEFT ) ) );
1153 1154
1154 m_editor.grabFocus(); 1155 m_editor.grabFocus();
1155 1156
@@ -1268,7 +1269,7 @@ public class Gui
1268 1269
1269 private void toggleMapping() 1270 private void toggleMapping()
1270 { 1271 {
1271 if( m_controller.entryHasMapping( m_reference.entry ) ) 1272 if( m_controller.entryHasDeobfuscatedName( m_reference.entry ) )
1272 { 1273 {
1273 m_controller.removeMapping( m_reference ); 1274 m_controller.removeMapping( m_reference );
1274 } 1275 }
diff --git a/src/cuchaz/enigma/gui/GuiController.java b/src/cuchaz/enigma/gui/GuiController.java
index 3adaf91d..c7efbce6 100644
--- a/src/cuchaz/enigma/gui/GuiController.java
+++ b/src/cuchaz/enigma/gui/GuiController.java
@@ -165,9 +165,9 @@ public class GuiController
165 ); 165 );
166 } 166 }
167 167
168 public boolean entryHasMapping( Entry deobfEntry ) 168 public boolean entryHasDeobfuscatedName( Entry deobfEntry )
169 { 169 {
170 return m_deobfuscator.hasMapping( m_deobfuscator.obfuscateEntry( deobfEntry ) ); 170 return m_deobfuscator.hasDeobfuscatedName( m_deobfuscator.obfuscateEntry( deobfEntry ) );
171 } 171 }
172 172
173 public boolean entryIsInJar( Entry deobfEntry ) 173 public boolean entryIsInJar( Entry deobfEntry )
@@ -175,6 +175,11 @@ public class GuiController
175 return m_deobfuscator.isObfuscatedIdentifier( m_deobfuscator.obfuscateEntry( deobfEntry ) ); 175 return m_deobfuscator.isObfuscatedIdentifier( m_deobfuscator.obfuscateEntry( deobfEntry ) );
176 } 176 }
177 177
178 public boolean referenceIsRenameable( EntryReference<Entry,Entry> deobfReference )
179 {
180 return m_deobfuscator.isRenameable( m_deobfuscator.obfuscateReference( deobfReference ) );
181 }
182
178 public ClassInheritanceTreeNode getClassInheritance( ClassEntry deobfClassEntry ) 183 public ClassInheritanceTreeNode getClassInheritance( ClassEntry deobfClassEntry )
179 { 184 {
180 ClassEntry obfClassEntry = m_deobfuscator.obfuscateEntry( deobfClassEntry ); 185 ClassEntry obfClassEntry = m_deobfuscator.obfuscateEntry( deobfClassEntry );
@@ -243,7 +248,7 @@ public class GuiController
243 public void rename( EntryReference<Entry,Entry> deobfReference, String newName ) 248 public void rename( EntryReference<Entry,Entry> deobfReference, String newName )
244 { 249 {
245 EntryReference<Entry,Entry> obfReference = m_deobfuscator.obfuscateReference( deobfReference ); 250 EntryReference<Entry,Entry> obfReference = m_deobfuscator.obfuscateReference( deobfReference );
246 m_deobfuscator.rename( obfReference.entry, newName ); 251 m_deobfuscator.rename( obfReference.getNameableEntry(), newName );
247 m_isDirty = true; 252 m_isDirty = true;
248 refreshClasses(); 253 refreshClasses();
249 refreshCurrentClass( obfReference ); 254 refreshCurrentClass( obfReference );
@@ -252,7 +257,7 @@ public class GuiController
252 public void removeMapping( EntryReference<Entry,Entry> deobfReference ) 257 public void removeMapping( EntryReference<Entry,Entry> deobfReference )
253 { 258 {
254 EntryReference<Entry,Entry> obfReference = m_deobfuscator.obfuscateReference( deobfReference ); 259 EntryReference<Entry,Entry> obfReference = m_deobfuscator.obfuscateReference( deobfReference );
255 m_deobfuscator.removeMapping( obfReference.entry ); 260 m_deobfuscator.removeMapping( obfReference.getNameableEntry() );
256 m_isDirty = true; 261 m_isDirty = true;
257 refreshClasses(); 262 refreshClasses();
258 refreshCurrentClass( obfReference ); 263 refreshCurrentClass( obfReference );
@@ -261,7 +266,7 @@ public class GuiController
261 public void markAsDeobfuscated( EntryReference<Entry,Entry> deobfReference ) 266 public void markAsDeobfuscated( EntryReference<Entry,Entry> deobfReference )
262 { 267 {
263 EntryReference<Entry,Entry> obfReference = m_deobfuscator.obfuscateReference( deobfReference ); 268 EntryReference<Entry,Entry> obfReference = m_deobfuscator.obfuscateReference( deobfReference );
264 m_deobfuscator.markAsDeobfuscated( obfReference.entry ); 269 m_deobfuscator.markAsDeobfuscated( obfReference.getNameableEntry() );
265 m_isDirty = true; 270 m_isDirty = true;
266 refreshClasses(); 271 refreshClasses();
267 refreshCurrentClass( obfReference ); 272 refreshCurrentClass( obfReference );
@@ -273,7 +278,7 @@ public class GuiController
273 { 278 {
274 throw new IllegalArgumentException( "Entry cannot be null!" ); 279 throw new IllegalArgumentException( "Entry cannot be null!" );
275 } 280 }
276 openReference( new EntryReference<Entry,Entry>( deobfEntry ) ); 281 openReference( new EntryReference<Entry,Entry>( deobfEntry, deobfEntry.getName() ) );
277 } 282 }
278 283
279 public void openReference( EntryReference<Entry,Entry> deobfReference ) 284 public void openReference( EntryReference<Entry,Entry> deobfReference )
@@ -285,7 +290,7 @@ public class GuiController
285 290
286 // get the reference target class 291 // get the reference target class
287 EntryReference<Entry,Entry> obfReference = m_deobfuscator.obfuscateReference( deobfReference ); 292 EntryReference<Entry,Entry> obfReference = m_deobfuscator.obfuscateReference( deobfReference );
288 ClassEntry obfClassEntry = obfReference.getClassEntry().getOuterClassEntry(); 293 ClassEntry obfClassEntry = obfReference.getLocationClassEntry().getOuterClassEntry();
289 if( !m_deobfuscator.isObfuscatedIdentifier( obfClassEntry ) ) 294 if( !m_deobfuscator.isObfuscatedIdentifier( obfClassEntry ) )
290 { 295 {
291 throw new IllegalArgumentException( "Obfuscated class " + obfClassEntry + " was not found in the jar!" ); 296 throw new IllegalArgumentException( "Obfuscated class " + obfClassEntry + " was not found in the jar!" );
@@ -390,13 +395,16 @@ public class GuiController
390 for( Token token : m_index.referenceTokens() ) 395 for( Token token : m_index.referenceTokens() )
391 { 396 {
392 EntryReference<Entry,Entry> reference = m_index.getDeobfReference( token ); 397 EntryReference<Entry,Entry> reference = m_index.getDeobfReference( token );
393 if( entryHasMapping( reference.entry ) ) 398 if( referenceIsRenameable( reference ) )
394 {
395 deobfuscatedTokens.add( token );
396 }
397 else if( entryIsInJar( reference.entry ) )
398 { 399 {
399 obfuscatedTokens.add( token ); 400 if( entryHasDeobfuscatedName( reference.getNameableEntry() ) )
401 {
402 deobfuscatedTokens.add( token );
403 }
404 else
405 {
406 obfuscatedTokens.add( token );
407 }
400 } 408 }
401 else 409 else
402 { 410 {
diff --git a/test/cuchaz/enigma/EntryFactory.java b/test/cuchaz/enigma/EntryFactory.java
index 66f83dfd..5a8a4270 100644
--- a/test/cuchaz/enigma/EntryFactory.java
+++ b/test/cuchaz/enigma/EntryFactory.java
@@ -42,21 +42,21 @@ public class EntryFactory
42 42
43 public static EntryReference<FieldEntry,BehaviorEntry> newFieldReferenceByMethod( FieldEntry fieldEntry, String callerClassName, String callerName, String callerSignature ) 43 public static EntryReference<FieldEntry,BehaviorEntry> newFieldReferenceByMethod( FieldEntry fieldEntry, String callerClassName, String callerName, String callerSignature )
44 { 44 {
45 return new EntryReference<FieldEntry,BehaviorEntry>( fieldEntry, newMethod( callerClassName, callerName, callerSignature ) ); 45 return new EntryReference<FieldEntry,BehaviorEntry>( fieldEntry, "", newMethod( callerClassName, callerName, callerSignature ) );
46 } 46 }
47 47
48 public static EntryReference<FieldEntry,BehaviorEntry> newFieldReferenceByConstructor( FieldEntry fieldEntry, String callerClassName, String callerSignature ) 48 public static EntryReference<FieldEntry,BehaviorEntry> newFieldReferenceByConstructor( FieldEntry fieldEntry, String callerClassName, String callerSignature )
49 { 49 {
50 return new EntryReference<FieldEntry,BehaviorEntry>( fieldEntry, newConstructor( callerClassName, callerSignature ) ); 50 return new EntryReference<FieldEntry,BehaviorEntry>( fieldEntry, "", newConstructor( callerClassName, callerSignature ) );
51 } 51 }
52 52
53 public static EntryReference<BehaviorEntry,BehaviorEntry> newBehaviorReferenceByMethod( BehaviorEntry behaviorEntry, String callerClassName, String callerName, String callerSignature ) 53 public static EntryReference<BehaviorEntry,BehaviorEntry> newBehaviorReferenceByMethod( BehaviorEntry behaviorEntry, String callerClassName, String callerName, String callerSignature )
54 { 54 {
55 return new EntryReference<BehaviorEntry,BehaviorEntry>( behaviorEntry, newMethod( callerClassName, callerName, callerSignature ) ); 55 return new EntryReference<BehaviorEntry,BehaviorEntry>( behaviorEntry, "", newMethod( callerClassName, callerName, callerSignature ) );
56 } 56 }
57 57
58 public static EntryReference<BehaviorEntry,BehaviorEntry> newBehaviorReferenceByConstructor( BehaviorEntry behaviorEntry, String callerClassName, String callerSignature ) 58 public static EntryReference<BehaviorEntry,BehaviorEntry> newBehaviorReferenceByConstructor( BehaviorEntry behaviorEntry, String callerClassName, String callerSignature )
59 { 59 {
60 return new EntryReference<BehaviorEntry,BehaviorEntry>( behaviorEntry, newConstructor( callerClassName, callerSignature ) ); 60 return new EntryReference<BehaviorEntry,BehaviorEntry>( behaviorEntry, "", newConstructor( callerClassName, callerSignature ) );
61 } 61 }
62} 62}