summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar jeff2014-08-21 01:10:37 -0400
committerGravatar jeff2014-08-21 01:10:37 -0400
commit237b2ed2a6b6f537cdbdf9fc9c6d0c7743f34375 (patch)
treeebad059c7fa0bc7723858cb25eed0bb6e95fe42a
parentfixed recognition of inner class tokens (diff)
downloadenigma-237b2ed2a6b6f537cdbdf9fc9c6d0c7743f34375.tar.gz
enigma-237b2ed2a6b6f537cdbdf9fc9c6d0c7743f34375.tar.xz
enigma-237b2ed2a6b6f537cdbdf9fc9c6d0c7743f34375.zip
fixed call graph searching
added system to navigate multiple tokens for the same entry in a behavior
-rw-r--r--src/cuchaz/enigma/Deobfuscator.java18
-rw-r--r--src/cuchaz/enigma/analysis/EntryReference.java13
-rw-r--r--src/cuchaz/enigma/analysis/JarIndex.java30
-rw-r--r--src/cuchaz/enigma/analysis/SourceIndex.java37
-rw-r--r--src/cuchaz/enigma/analysis/SourceIndexBehaviorVisitor.java16
-rw-r--r--src/cuchaz/enigma/analysis/SourceIndexClassVisitor.java23
-rw-r--r--src/cuchaz/enigma/gui/Gui.java53
-rw-r--r--src/cuchaz/enigma/gui/GuiController.java75
-rw-r--r--src/cuchaz/enigma/gui/ReadableToken.java38
-rw-r--r--src/cuchaz/enigma/gui/TokenListCellRenderer.java40
-rw-r--r--src/cuchaz/enigma/mapping/ConstructorEntry.java54
-rw-r--r--src/cuchaz/enigma/mapping/Translator.java28
12 files changed, 302 insertions, 123 deletions
diff --git a/src/cuchaz/enigma/Deobfuscator.java b/src/cuchaz/enigma/Deobfuscator.java
index 34e6033b..a5feaa9f 100644
--- a/src/cuchaz/enigma/Deobfuscator.java
+++ b/src/cuchaz/enigma/Deobfuscator.java
@@ -181,7 +181,7 @@ public class Deobfuscator
181 return index; 181 return index;
182 } 182 }
183 183
184 public Entry obfuscateEntry( Entry deobfEntry ) 184 public <T extends Entry> T obfuscateEntry( T deobfEntry )
185 { 185 {
186 if( deobfEntry == null ) 186 if( deobfEntry == null )
187 { 187 {
@@ -190,7 +190,7 @@ public class Deobfuscator
190 return getTranslator( TranslationDirection.Obfuscating ).translateEntry( deobfEntry ); 190 return getTranslator( TranslationDirection.Obfuscating ).translateEntry( deobfEntry );
191 } 191 }
192 192
193 public Entry deobfuscateEntry( Entry obfEntry ) 193 public <T extends Entry> T deobfuscateEntry( T obfEntry )
194 { 194 {
195 if( obfEntry == null ) 195 if( obfEntry == null )
196 { 196 {
@@ -199,29 +199,27 @@ public class Deobfuscator
199 return getTranslator( TranslationDirection.Deobfuscating ).translateEntry( obfEntry ); 199 return getTranslator( TranslationDirection.Deobfuscating ).translateEntry( obfEntry );
200 } 200 }
201 201
202 public EntryReference<Entry,Entry> obfuscateReference( EntryReference<Entry,Entry> deobfReference ) 202 public <E extends Entry,C extends Entry> EntryReference<E,C> obfuscateReference( EntryReference<E,C> deobfReference )
203 { 203 {
204 if( deobfReference == null ) 204 if( deobfReference == null )
205 { 205 {
206 return null; 206 return null;
207 } 207 }
208 return new EntryReference<Entry,Entry>( 208 return new EntryReference<E,C>(
209 obfuscateEntry( deobfReference.entry ), 209 obfuscateEntry( deobfReference.entry ),
210 obfuscateEntry( deobfReference.context ), 210 obfuscateEntry( deobfReference.context )
211 deobfReference.pos
212 ); 211 );
213 } 212 }
214 213
215 public EntryReference<Entry,Entry> deobfuscateReference( EntryReference<Entry,Entry> obfReference ) 214 public <E extends Entry,C extends Entry> EntryReference<E,C> deobfuscateReference( EntryReference<E,C> obfReference )
216 { 215 {
217 if( obfReference == null ) 216 if( obfReference == null )
218 { 217 {
219 return null; 218 return null;
220 } 219 }
221 return new EntryReference<Entry,Entry>( 220 return new EntryReference<E,C>(
222 deobfuscateEntry( obfReference.entry ), 221 deobfuscateEntry( obfReference.entry ),
223 deobfuscateEntry( obfReference.context ), 222 deobfuscateEntry( obfReference.context )
224 obfReference.pos
225 ); 223 );
226 } 224 }
227 225
diff --git a/src/cuchaz/enigma/analysis/EntryReference.java b/src/cuchaz/enigma/analysis/EntryReference.java
index 869e08c1..768c1132 100644
--- a/src/cuchaz/enigma/analysis/EntryReference.java
+++ b/src/cuchaz/enigma/analysis/EntryReference.java
@@ -18,14 +18,13 @@ public class EntryReference<E extends Entry, C extends Entry>
18{ 18{
19 public E entry; 19 public E entry;
20 public C context; 20 public C context;
21 public int pos;
22 21
23 public EntryReference( E entry ) 22 public EntryReference( E entry )
24 { 23 {
25 this( entry, null, -1 ); 24 this( entry, null );
26 } 25 }
27 26
28 public EntryReference( E entry, C context, int pos ) 27 public EntryReference( E entry, C context )
29 { 28 {
30 if( entry == null ) 29 if( entry == null )
31 { 30 {
@@ -34,7 +33,6 @@ public class EntryReference<E extends Entry, C extends Entry>
34 33
35 this.entry = entry; 34 this.entry = entry;
36 this.context = context; 35 this.context = context;
37 this.pos = pos;
38 } 36 }
39 37
40 public ClassEntry getClassEntry( ) 38 public ClassEntry getClassEntry( )
@@ -51,7 +49,7 @@ public class EntryReference<E extends Entry, C extends Entry>
51 { 49 {
52 if( context != null ) 50 if( context != null )
53 { 51 {
54 return Util.combineHashesOrdered( entry.hashCode(), context.hashCode(), Integer.valueOf( pos ).hashCode() ); 52 return Util.combineHashesOrdered( entry.hashCode(), context.hashCode() );
55 } 53 }
56 return entry.hashCode(); 54 return entry.hashCode();
57 } 55 }
@@ -82,7 +80,7 @@ public class EntryReference<E extends Entry, C extends Entry>
82 } 80 }
83 else if( context != null && other.context != null ) 81 else if( context != null && other.context != null )
84 { 82 {
85 return context.equals( other.context ) && pos == other.pos; 83 return context.equals( other.context );
86 } 84 }
87 return false; 85 return false;
88 } 86 }
@@ -96,9 +94,6 @@ public class EntryReference<E extends Entry, C extends Entry>
96 { 94 {
97 buf.append( " called from " ); 95 buf.append( " called from " );
98 buf.append( context ); 96 buf.append( context );
99 buf.append( " (" );
100 buf.append( pos );
101 buf.append( ")" );
102 } 97 }
103 return buf.toString(); 98 return buf.toString();
104 } 99 }
diff --git a/src/cuchaz/enigma/analysis/JarIndex.java b/src/cuchaz/enigma/analysis/JarIndex.java
index f408d930..315a2864 100644
--- a/src/cuchaz/enigma/analysis/JarIndex.java
+++ b/src/cuchaz/enigma/analysis/JarIndex.java
@@ -146,10 +146,15 @@ public class JarIndex
146 } 146 }
147 else if( behavior instanceof CtConstructor ) 147 else if( behavior instanceof CtConstructor )
148 { 148 {
149 thisEntry = new ConstructorEntry( 149 boolean isStatic = behavior.getName().equals( "<clinit>" );
150 new ClassEntry( className ), 150 if( isStatic )
151 behavior.getSignature() 151 {
152 ); 152 thisEntry = new ConstructorEntry( new ClassEntry( className ) );
153 }
154 else
155 {
156 thisEntry = new ConstructorEntry( new ClassEntry( className ), behavior.getSignature() );
157 }
153 } 158 }
154 else 159 else
155 { 160 {
@@ -159,7 +164,6 @@ public class JarIndex
159 // index method calls 164 // index method calls
160 try 165 try
161 { 166 {
162 final Multiset<Entry> callNumbers = HashMultiset.create();
163 behavior.instrument( new ExprEditor( ) 167 behavior.instrument( new ExprEditor( )
164 { 168 {
165 @Override 169 @Override
@@ -171,11 +175,9 @@ public class JarIndex
171 call.getMethodName(), 175 call.getMethodName(),
172 call.getSignature() 176 call.getSignature()
173 ); 177 );
174 callNumbers.add( calledMethodEntry );
175 EntryReference<BehaviorEntry,BehaviorEntry> reference = new EntryReference<BehaviorEntry,BehaviorEntry>( 178 EntryReference<BehaviorEntry,BehaviorEntry> reference = new EntryReference<BehaviorEntry,BehaviorEntry>(
176 calledMethodEntry, 179 calledMethodEntry,
177 thisEntry, 180 thisEntry
178 callNumbers.count( calledMethodEntry ) - 1
179 ); 181 );
180 m_behaviorReferences.put( calledMethodEntry, reference ); 182 m_behaviorReferences.put( calledMethodEntry, reference );
181 } 183 }
@@ -188,11 +190,9 @@ public class JarIndex
188 new ClassEntry( className ), 190 new ClassEntry( className ),
189 call.getFieldName() 191 call.getFieldName()
190 ); 192 );
191 callNumbers.add( calledFieldEntry );
192 EntryReference<FieldEntry,BehaviorEntry> reference = new EntryReference<FieldEntry,BehaviorEntry>( 193 EntryReference<FieldEntry,BehaviorEntry> reference = new EntryReference<FieldEntry,BehaviorEntry>(
193 calledFieldEntry, 194 calledFieldEntry,
194 thisEntry, 195 thisEntry
195 callNumbers.count( calledFieldEntry ) - 1
196 ); 196 );
197 m_fieldReferences.put( calledFieldEntry, reference ); 197 m_fieldReferences.put( calledFieldEntry, reference );
198 } 198 }
@@ -208,11 +208,9 @@ public class JarIndex
208 new ClassEntry( className ), 208 new ClassEntry( className ),
209 call.getSignature() 209 call.getSignature()
210 ); 210 );
211 callNumbers.add( calledConstructorEntry );
212 EntryReference<BehaviorEntry,BehaviorEntry> reference = new EntryReference<BehaviorEntry,BehaviorEntry>( 211 EntryReference<BehaviorEntry,BehaviorEntry> reference = new EntryReference<BehaviorEntry,BehaviorEntry>(
213 calledConstructorEntry, 212 calledConstructorEntry,
214 thisEntry, 213 thisEntry
215 callNumbers.count( calledConstructorEntry ) - 1
216 ); 214 );
217 m_behaviorReferences.put( calledConstructorEntry, reference ); 215 m_behaviorReferences.put( calledConstructorEntry, reference );
218 } 216 }
@@ -225,11 +223,9 @@ public class JarIndex
225 new ClassEntry( className ), 223 new ClassEntry( className ),
226 call.getSignature() 224 call.getSignature()
227 ); 225 );
228 callNumbers.add( calledConstructorEntry );
229 EntryReference<BehaviorEntry,BehaviorEntry> reference = new EntryReference<BehaviorEntry,BehaviorEntry>( 226 EntryReference<BehaviorEntry,BehaviorEntry> reference = new EntryReference<BehaviorEntry,BehaviorEntry>(
230 calledConstructorEntry, 227 calledConstructorEntry,
231 thisEntry, 228 thisEntry
232 callNumbers.count( calledConstructorEntry ) - 1
233 ); 229 );
234 m_behaviorReferences.put( calledConstructorEntry, reference ); 230 m_behaviorReferences.put( calledConstructorEntry, reference );
235 } 231 }
diff --git a/src/cuchaz/enigma/analysis/SourceIndex.java b/src/cuchaz/enigma/analysis/SourceIndex.java
index bf890e30..960ec36f 100644
--- a/src/cuchaz/enigma/analysis/SourceIndex.java
+++ b/src/cuchaz/enigma/analysis/SourceIndex.java
@@ -10,13 +10,15 @@
10 ******************************************************************************/ 10 ******************************************************************************/
11package cuchaz.enigma.analysis; 11package cuchaz.enigma.analysis;
12 12
13import java.util.HashMap; 13import java.util.Collection;
14import java.util.List; 14import java.util.List;
15import java.util.Map; 15import java.util.Map;
16import java.util.TreeMap; 16import java.util.TreeMap;
17 17
18import com.google.common.collect.HashMultimap;
18import com.google.common.collect.Lists; 19import com.google.common.collect.Lists;
19import com.google.common.collect.Maps; 20import com.google.common.collect.Maps;
21import com.google.common.collect.Multimap;
20import com.strobel.decompiler.languages.Region; 22import com.strobel.decompiler.languages.Region;
21import com.strobel.decompiler.languages.java.ast.Identifier; 23import com.strobel.decompiler.languages.java.ast.Identifier;
22 24
@@ -26,7 +28,7 @@ public class SourceIndex
26{ 28{
27 private String m_source; 29 private String m_source;
28 private TreeMap<Token,EntryReference<Entry,Entry>> m_tokenToReference; 30 private TreeMap<Token,EntryReference<Entry,Entry>> m_tokenToReference;
29 private HashMap<EntryReference<Entry,Entry>,Token> m_referenceToToken; 31 private Multimap<EntryReference<Entry,Entry>,Token> m_referenceToTokens;
30 private Map<Entry,Token> m_declarationToToken; 32 private Map<Entry,Token> m_declarationToToken;
31 private List<Integer> m_lineOffsets; 33 private List<Integer> m_lineOffsets;
32 34
@@ -34,7 +36,7 @@ public class SourceIndex
34 { 36 {
35 m_source = source; 37 m_source = source;
36 m_tokenToReference = Maps.newTreeMap(); 38 m_tokenToReference = Maps.newTreeMap();
37 m_referenceToToken = Maps.newHashMap(); 39 m_referenceToTokens = HashMultimap.create();
38 m_declarationToToken = Maps.newHashMap(); 40 m_declarationToToken = Maps.newHashMap();
39 m_lineOffsets = Lists.newArrayList(); 41 m_lineOffsets = Lists.newArrayList();
40 42
@@ -96,7 +98,7 @@ public class SourceIndex
96 if( token != null ) 98 if( token != null )
97 { 99 {
98 m_tokenToReference.put( token, deobfReference ); 100 m_tokenToReference.put( token, deobfReference );
99 m_referenceToToken.put( deobfReference, token ); 101 m_referenceToTokens.put( deobfReference, token );
100 } 102 }
101 } 103 }
102 104
@@ -107,7 +109,7 @@ public class SourceIndex
107 { 109 {
108 EntryReference<Entry,Entry> reference = new EntryReference<Entry,Entry>( deobfEntry ); 110 EntryReference<Entry,Entry> reference = new EntryReference<Entry,Entry>( deobfEntry );
109 m_tokenToReference.put( token, reference ); 111 m_tokenToReference.put( token, reference );
110 m_referenceToToken.put( reference, token ); 112 m_referenceToTokens.put( reference, token );
111 m_declarationToToken.put( deobfEntry, token ); 113 m_declarationToToken.put( deobfEntry, token );
112 } 114 }
113 } 115 }
@@ -122,9 +124,9 @@ public class SourceIndex
122 return null; 124 return null;
123 } 125 }
124 126
125 public Token getReferenceToken( EntryReference<Entry,Entry> deobfReference ) 127 public Collection<Token> getReferenceTokens( EntryReference<Entry,Entry> deobfReference )
126 { 128 {
127 return m_referenceToToken.get( deobfReference ); 129 return m_referenceToTokens.get( deobfReference );
128 } 130 }
129 131
130 public EntryReference<Entry,Entry> getDeobfReference( Token token ) 132 public EntryReference<Entry,Entry> getDeobfReference( Token token )
@@ -151,6 +153,27 @@ public class SourceIndex
151 return m_declarationToToken.get( deobfEntry ); 153 return m_declarationToToken.get( deobfEntry );
152 } 154 }
153 155
156 public int getLineNumber( int pos )
157 {
158 // line number is 1-based
159 int line = 0;
160 for( Integer offset : m_lineOffsets )
161 {
162 if( offset > pos )
163 {
164 break;
165 }
166 line++;
167 }
168 return line;
169 }
170
171 public int getColumnNumber( int pos )
172 {
173 // column number is 1-based
174 return pos - m_lineOffsets.get( getLineNumber( pos ) - 1 ) + 1;
175 }
176
154 private int toPos( int line, int col ) 177 private int toPos( int line, int col )
155 { 178 {
156 // line and col are 1-based 179 // line and col are 1-based
diff --git a/src/cuchaz/enigma/analysis/SourceIndexBehaviorVisitor.java b/src/cuchaz/enigma/analysis/SourceIndexBehaviorVisitor.java
index d3386c51..a9438588 100644
--- a/src/cuchaz/enigma/analysis/SourceIndexBehaviorVisitor.java
+++ b/src/cuchaz/enigma/analysis/SourceIndexBehaviorVisitor.java
@@ -10,8 +10,6 @@
10 ******************************************************************************/ 10 ******************************************************************************/
11package cuchaz.enigma.analysis; 11package cuchaz.enigma.analysis;
12 12
13import com.google.common.collect.HashMultiset;
14import com.google.common.collect.Multiset;
15import com.strobel.assembler.metadata.MemberReference; 13import com.strobel.assembler.metadata.MemberReference;
16import com.strobel.assembler.metadata.MethodDefinition; 14import com.strobel.assembler.metadata.MethodDefinition;
17import com.strobel.assembler.metadata.ParameterDefinition; 15import com.strobel.assembler.metadata.ParameterDefinition;
@@ -36,12 +34,10 @@ import cuchaz.enigma.mapping.MethodEntry;
36public class SourceIndexBehaviorVisitor extends SourceIndexVisitor 34public class SourceIndexBehaviorVisitor extends SourceIndexVisitor
37{ 35{
38 private BehaviorEntry m_behaviorEntry; 36 private BehaviorEntry m_behaviorEntry;
39 private Multiset<Entry> m_indices;
40 37
41 public SourceIndexBehaviorVisitor( BehaviorEntry behaviorEntry ) 38 public SourceIndexBehaviorVisitor( BehaviorEntry behaviorEntry )
42 { 39 {
43 m_behaviorEntry = behaviorEntry; 40 m_behaviorEntry = behaviorEntry;
44 m_indices = HashMultiset.create();
45 } 41 }
46 42
47 @Override 43 @Override
@@ -64,10 +60,9 @@ public class SourceIndexBehaviorVisitor extends SourceIndexVisitor
64 MethodEntry methodEntry = new MethodEntry( classEntry, ref.getName(), ref.getSignature() ); 60 MethodEntry methodEntry = new MethodEntry( classEntry, ref.getName(), ref.getSignature() );
65 if( node.getTarget() instanceof MemberReferenceExpression ) 61 if( node.getTarget() instanceof MemberReferenceExpression )
66 { 62 {
67 m_indices.add( methodEntry );
68 index.addReference( 63 index.addReference(
69 ((MemberReferenceExpression)node.getTarget()).getMemberNameToken(), 64 ((MemberReferenceExpression)node.getTarget()).getMemberNameToken(),
70 new EntryReference<Entry,Entry>( methodEntry, m_behaviorEntry, m_indices.count( methodEntry ) ) 65 new EntryReference<Entry,Entry>( methodEntry, m_behaviorEntry )
71 ); 66 );
72 } 67 }
73 68
@@ -82,10 +77,9 @@ public class SourceIndexBehaviorVisitor extends SourceIndexVisitor
82 { 77 {
83 ClassEntry classEntry = new ClassEntry( ref.getDeclaringType().getInternalName() ); 78 ClassEntry classEntry = new ClassEntry( ref.getDeclaringType().getInternalName() );
84 FieldEntry fieldEntry = new FieldEntry( classEntry, ref.getName() ); 79 FieldEntry fieldEntry = new FieldEntry( classEntry, ref.getName() );
85 m_indices.add( fieldEntry );
86 index.addReference( 80 index.addReference(
87 node.getMemberNameToken(), 81 node.getMemberNameToken(),
88 new EntryReference<Entry,Entry>( fieldEntry, m_behaviorEntry, m_indices.count( fieldEntry ) ) 82 new EntryReference<Entry,Entry>( fieldEntry, m_behaviorEntry )
89 ); 83 );
90 } 84 }
91 85
@@ -99,10 +93,9 @@ public class SourceIndexBehaviorVisitor extends SourceIndexVisitor
99 if( node.getIdentifierToken().getStartLocation() != TextLocation.EMPTY ) 93 if( node.getIdentifierToken().getStartLocation() != TextLocation.EMPTY )
100 { 94 {
101 ClassEntry classEntry = new ClassEntry( ref.getInternalName() ); 95 ClassEntry classEntry = new ClassEntry( ref.getInternalName() );
102 m_indices.add( classEntry );
103 index.addReference( 96 index.addReference(
104 node.getIdentifierToken(), 97 node.getIdentifierToken(),
105 new EntryReference<Entry,Entry>( classEntry, m_behaviorEntry, m_indices.count( classEntry ) ) 98 new EntryReference<Entry,Entry>( classEntry, m_behaviorEntry )
106 ); 99 );
107 } 100 }
108 101
@@ -130,10 +123,9 @@ public class SourceIndexBehaviorVisitor extends SourceIndexVisitor
130 { 123 {
131 ClassEntry classEntry = new ClassEntry( ref.getDeclaringType().getInternalName() ); 124 ClassEntry classEntry = new ClassEntry( ref.getDeclaringType().getInternalName() );
132 FieldEntry fieldEntry = new FieldEntry( classEntry, ref.getName() ); 125 FieldEntry fieldEntry = new FieldEntry( classEntry, ref.getName() );
133 m_indices.add( fieldEntry );
134 index.addReference( 126 index.addReference(
135 node.getIdentifierToken(), 127 node.getIdentifierToken(),
136 new EntryReference<Entry,Entry>( fieldEntry, m_behaviorEntry, m_indices.count( fieldEntry ) ) 128 new EntryReference<Entry,Entry>( fieldEntry, m_behaviorEntry )
137 ); 129 );
138 } 130 }
139 131
diff --git a/src/cuchaz/enigma/analysis/SourceIndexClassVisitor.java b/src/cuchaz/enigma/analysis/SourceIndexClassVisitor.java
index 52570886..a1c82711 100644
--- a/src/cuchaz/enigma/analysis/SourceIndexClassVisitor.java
+++ b/src/cuchaz/enigma/analysis/SourceIndexClassVisitor.java
@@ -10,8 +10,6 @@
10 ******************************************************************************/ 10 ******************************************************************************/
11package cuchaz.enigma.analysis; 11package cuchaz.enigma.analysis;
12 12
13import com.google.common.collect.HashMultiset;
14import com.google.common.collect.Multiset;
15import com.strobel.assembler.metadata.FieldDefinition; 13import com.strobel.assembler.metadata.FieldDefinition;
16import com.strobel.assembler.metadata.MethodDefinition; 14import com.strobel.assembler.metadata.MethodDefinition;
17import com.strobel.assembler.metadata.TypeDefinition; 15import com.strobel.assembler.metadata.TypeDefinition;
@@ -26,6 +24,7 @@ import com.strobel.decompiler.languages.java.ast.SimpleType;
26import com.strobel.decompiler.languages.java.ast.TypeDeclaration; 24import com.strobel.decompiler.languages.java.ast.TypeDeclaration;
27import com.strobel.decompiler.languages.java.ast.VariableInitializer; 25import com.strobel.decompiler.languages.java.ast.VariableInitializer;
28 26
27import cuchaz.enigma.mapping.BehaviorEntry;
29import cuchaz.enigma.mapping.ClassEntry; 28import cuchaz.enigma.mapping.ClassEntry;
30import cuchaz.enigma.mapping.ConstructorEntry; 29import cuchaz.enigma.mapping.ConstructorEntry;
31import cuchaz.enigma.mapping.Entry; 30import cuchaz.enigma.mapping.Entry;
@@ -35,12 +34,10 @@ import cuchaz.enigma.mapping.MethodEntry;
35public class SourceIndexClassVisitor extends SourceIndexVisitor 34public class SourceIndexClassVisitor extends SourceIndexVisitor
36{ 35{
37 private ClassEntry m_classEntry; 36 private ClassEntry m_classEntry;
38 private Multiset<Entry> m_indices;
39 37
40 public SourceIndexClassVisitor( ClassEntry classEntry ) 38 public SourceIndexClassVisitor( ClassEntry classEntry )
41 { 39 {
42 m_classEntry = classEntry; 40 m_classEntry = classEntry;
43 m_indices = HashMultiset.create();
44 } 41 }
45 42
46 @Override 43 @Override
@@ -68,7 +65,7 @@ public class SourceIndexClassVisitor extends SourceIndexVisitor
68 ClassEntry classEntry = new ClassEntry( ref.getInternalName() ); 65 ClassEntry classEntry = new ClassEntry( ref.getInternalName() );
69 index.addReference( 66 index.addReference(
70 node.getIdentifierToken(), 67 node.getIdentifierToken(),
71 new EntryReference<Entry,Entry>( classEntry, m_classEntry, m_indices.count( classEntry ) ) 68 new EntryReference<Entry,Entry>( classEntry, m_classEntry )
72 ); 69 );
73 } 70 }
74 71
@@ -80,11 +77,17 @@ public class SourceIndexClassVisitor extends SourceIndexVisitor
80 { 77 {
81 MethodDefinition def = node.getUserData( Keys.METHOD_DEFINITION ); 78 MethodDefinition def = node.getUserData( Keys.METHOD_DEFINITION );
82 ClassEntry classEntry = new ClassEntry( def.getDeclaringType().getInternalName() ); 79 ClassEntry classEntry = new ClassEntry( def.getDeclaringType().getInternalName() );
83 MethodEntry methodEntry = new MethodEntry( classEntry, def.getName(), def.getSignature() ); 80 BehaviorEntry behaviorEntry;
84 index.addDeclaration( node.getNameToken(), methodEntry ); 81 if( def.getName().equals( "<clinit>" ) )
85 //if( !def.getName().equals( "<clinit>" ) ) 82 {
86 83 behaviorEntry = new ConstructorEntry( classEntry );
87 return node.acceptVisitor( new SourceIndexBehaviorVisitor( methodEntry ), index ); 84 }
85 else
86 {
87 behaviorEntry = new MethodEntry( classEntry, def.getName(), def.getSignature() );
88 }
89 index.addDeclaration( node.getNameToken(), behaviorEntry );
90 return node.acceptVisitor( new SourceIndexBehaviorVisitor( behaviorEntry ), index );
88 } 91 }
89 92
90 @Override 93 @Override
diff --git a/src/cuchaz/enigma/gui/Gui.java b/src/cuchaz/enigma/gui/Gui.java
index 341c1493..a5471a74 100644
--- a/src/cuchaz/enigma/gui/Gui.java
+++ b/src/cuchaz/enigma/gui/Gui.java
@@ -28,6 +28,7 @@ import java.awt.event.WindowAdapter;
28import java.awt.event.WindowEvent; 28import java.awt.event.WindowEvent;
29import java.io.File; 29import java.io.File;
30import java.io.IOException; 30import java.io.IOException;
31import java.util.Collection;
31import java.util.Collections; 32import java.util.Collections;
32import java.util.Comparator; 33import java.util.Comparator;
33import java.util.List; 34import java.util.List;
@@ -145,6 +146,7 @@ public class Gui
145 private BoxHighlightPainter m_deobfuscatedHighlightPainter; 146 private BoxHighlightPainter m_deobfuscatedHighlightPainter;
146 private JTree m_inheritanceTree; 147 private JTree m_inheritanceTree;
147 private JTree m_callsTree; 148 private JTree m_callsTree;
149 private JList<Token> m_tokens;
148 private JTabbedPane m_tabs; 150 private JTabbedPane m_tabs;
149 151
150 // dynamic menu items 152 // dynamic menu items
@@ -457,9 +459,29 @@ public class Gui
457 } 459 }
458 } 460 }
459 } ); 461 } );
460 JPanel callPanel = new JPanel(); 462 m_tokens = new JList<Token>();
461 callPanel.setLayout( new BorderLayout() ); 463 m_tokens.setCellRenderer( new TokenListCellRenderer( m_controller ) );
462 callPanel.add( new JScrollPane( m_callsTree ) ); 464 m_tokens.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
465 m_tokens.setLayoutOrientation( JList.VERTICAL );
466 m_tokens.addMouseListener( new MouseAdapter()
467 {
468 @Override
469 public void mouseClicked( MouseEvent event )
470 {
471 if( event.getClickCount() == 2 )
472 {
473 Token selected = m_tokens.getSelectedValue();
474 if( selected != null )
475 {
476 showToken( selected );
477 }
478 }
479 }
480 } );
481 m_tokens.setPreferredSize( new Dimension( 0, 200 ) );
482 JSplitPane callPanel = new JSplitPane( JSplitPane.VERTICAL_SPLIT, true, new JScrollPane( m_callsTree ), new JScrollPane( m_tokens ) );
483 callPanel.setResizeWeight( 1 ); // let the top side take all the slack
484 callPanel.resetToPreferredSizes();
463 485
464 // layout controls 486 // layout controls
465 JSplitPane splitLeft = new JSplitPane( JSplitPane.VERTICAL_SPLIT, true, obfPanel, deobfPanel ); 487 JSplitPane splitLeft = new JSplitPane( JSplitPane.VERTICAL_SPLIT, true, obfPanel, deobfPanel );
@@ -743,6 +765,21 @@ public class Gui
743 m_editor.grabFocus(); 765 m_editor.grabFocus();
744 } 766 }
745 767
768 public void showTokens( Collection<Token> tokens )
769 {
770 Vector<Token> sortedTokens = new Vector<Token>( tokens );
771 Collections.sort( sortedTokens );
772 if( sortedTokens.size() > 1 )
773 {
774 // sort the tokens and update the tokens panel
775 m_tokens.setListData( sortedTokens );
776 m_tokens.setSelectedIndex( 0 );
777 }
778
779 // show the first token
780 showToken( sortedTokens.get( 0 ) );
781 }
782
746 public void setHighlightedTokens( Iterable<Token> obfuscatedTokens, Iterable<Token> deobfuscatedTokens ) 783 public void setHighlightedTokens( Iterable<Token> obfuscatedTokens, Iterable<Token> deobfuscatedTokens )
747 { 784 {
748 // remove any old highlighters 785 // remove any old highlighters
@@ -900,17 +937,9 @@ public class Gui
900 937
901 private void startRename( ) 938 private void startRename( )
902 { 939 {
903 // get the class name
904 ClassEntry classEntry = m_reference.entry.getClassEntry();
905 String className = classEntry.getName();
906 if( classEntry.isInnerClass() )
907 {
908 className = classEntry.getInnerClassName();
909 }
910
911 // init the text box 940 // init the text box
912 final JTextField text = new JTextField(); 941 final JTextField text = new JTextField();
913 text.setText( className ); 942 text.setText( m_reference.entry.getName() );
914 text.setPreferredSize( new Dimension( 360, text.getPreferredSize().height ) ); 943 text.setPreferredSize( new Dimension( 360, text.getPreferredSize().height ) );
915 text.addKeyListener( new KeyAdapter( ) 944 text.addKeyListener( new KeyAdapter( )
916 { 945 {
diff --git a/src/cuchaz/enigma/gui/GuiController.java b/src/cuchaz/enigma/gui/GuiController.java
index dfa25576..a35db056 100644
--- a/src/cuchaz/enigma/gui/GuiController.java
+++ b/src/cuchaz/enigma/gui/GuiController.java
@@ -14,6 +14,7 @@ import java.io.File;
14import java.io.FileReader; 14import java.io.FileReader;
15import java.io.FileWriter; 15import java.io.FileWriter;
16import java.io.IOException; 16import java.io.IOException;
17import java.util.Collection;
17import java.util.Deque; 18import java.util.Deque;
18import java.util.List; 19import java.util.List;
19 20
@@ -45,7 +46,7 @@ public class GuiController
45 private SourceIndex m_index; 46 private SourceIndex m_index;
46 private ClassEntry m_currentObfClass; 47 private ClassEntry m_currentObfClass;
47 private boolean m_isDirty; 48 private boolean m_isDirty;
48 private Deque<EntryReference<Entry,Entry>> m_referenceStack; // TODO: make a location class, can be either Entry or EntryReference 49 private Deque<EntryReference<Entry,Entry>> m_referenceStack;
49 50
50 public GuiController( Gui gui ) 51 public GuiController( Gui gui )
51 { 52 {
@@ -111,7 +112,6 @@ public class GuiController
111 { 112 {
112 return null; 113 return null;
113 } 114 }
114
115 return m_index.getReferenceToken( pos ); 115 return m_index.getReferenceToken( pos );
116 } 116 }
117 117
@@ -124,6 +124,19 @@ public class GuiController
124 return m_index.getDeobfReference( token ); 124 return m_index.getDeobfReference( token );
125 } 125 }
126 126
127 public ReadableToken getReadableToken( Token token )
128 {
129 if( m_index == null )
130 {
131 return null;
132 }
133 return new ReadableToken(
134 m_index.getLineNumber( token.start ),
135 m_index.getColumnNumber( token.start ),
136 m_index.getColumnNumber( token.end )
137 );
138 }
139
127 public boolean entryHasMapping( Entry deobfEntry ) 140 public boolean entryHasMapping( Entry deobfEntry )
128 { 141 {
129 return m_deobfuscator.hasMapping( m_deobfuscator.obfuscateEntry( deobfEntry ) ); 142 return m_deobfuscator.hasMapping( m_deobfuscator.obfuscateEntry( deobfEntry ) );
@@ -134,8 +147,9 @@ public class GuiController
134 return m_deobfuscator.isObfuscatedIdentifier( m_deobfuscator.obfuscateEntry( deobfEntry ) ); 147 return m_deobfuscator.isObfuscatedIdentifier( m_deobfuscator.obfuscateEntry( deobfEntry ) );
135 } 148 }
136 149
137 public ClassInheritanceTreeNode getClassInheritance( ClassEntry obfClassEntry ) 150 public ClassInheritanceTreeNode getClassInheritance( ClassEntry deobfClassEntry )
138 { 151 {
152 ClassEntry obfClassEntry = m_deobfuscator.obfuscateEntry( deobfClassEntry );
139 ClassInheritanceTreeNode rootNode = m_deobfuscator.getJarIndex().getClassInheritance( 153 ClassInheritanceTreeNode rootNode = m_deobfuscator.getJarIndex().getClassInheritance(
140 m_deobfuscator.getTranslator( TranslationDirection.Deobfuscating ), 154 m_deobfuscator.getTranslator( TranslationDirection.Deobfuscating ),
141 obfClassEntry 155 obfClassEntry
@@ -143,8 +157,9 @@ public class GuiController
143 return ClassInheritanceTreeNode.findNode( rootNode, obfClassEntry ); 157 return ClassInheritanceTreeNode.findNode( rootNode, obfClassEntry );
144 } 158 }
145 159
146 public MethodInheritanceTreeNode getMethodInheritance( MethodEntry obfMethodEntry ) 160 public MethodInheritanceTreeNode getMethodInheritance( MethodEntry deobfMethodEntry )
147 { 161 {
162 MethodEntry obfMethodEntry = m_deobfuscator.obfuscateEntry( deobfMethodEntry );
148 MethodInheritanceTreeNode rootNode = m_deobfuscator.getJarIndex().getMethodInheritance( 163 MethodInheritanceTreeNode rootNode = m_deobfuscator.getJarIndex().getMethodInheritance(
149 m_deobfuscator.getTranslator( TranslationDirection.Deobfuscating ), 164 m_deobfuscator.getTranslator( TranslationDirection.Deobfuscating ),
150 obfMethodEntry 165 obfMethodEntry
@@ -152,8 +167,9 @@ public class GuiController
152 return MethodInheritanceTreeNode.findNode( rootNode, obfMethodEntry ); 167 return MethodInheritanceTreeNode.findNode( rootNode, obfMethodEntry );
153 } 168 }
154 169
155 public FieldReferenceTreeNode getFieldReferences( FieldEntry obfFieldEntry ) 170 public FieldReferenceTreeNode getFieldReferences( FieldEntry deobfFieldEntry )
156 { 171 {
172 FieldEntry obfFieldEntry = m_deobfuscator.obfuscateEntry( deobfFieldEntry );
157 FieldReferenceTreeNode rootNode = new FieldReferenceTreeNode( 173 FieldReferenceTreeNode rootNode = new FieldReferenceTreeNode(
158 m_deobfuscator.getTranslator( TranslationDirection.Deobfuscating ), 174 m_deobfuscator.getTranslator( TranslationDirection.Deobfuscating ),
159 obfFieldEntry 175 obfFieldEntry
@@ -162,11 +178,12 @@ public class GuiController
162 return rootNode; 178 return rootNode;
163 } 179 }
164 180
165 public BehaviorReferenceTreeNode getMethodReferences( BehaviorEntry obfEntry ) 181 public BehaviorReferenceTreeNode getMethodReferences( BehaviorEntry deobfBehaviorEntry )
166 { 182 {
183 BehaviorEntry obfBehaviorEntry = m_deobfuscator.obfuscateEntry( deobfBehaviorEntry );
167 BehaviorReferenceTreeNode rootNode = new BehaviorReferenceTreeNode( 184 BehaviorReferenceTreeNode rootNode = new BehaviorReferenceTreeNode(
168 m_deobfuscator.getTranslator( TranslationDirection.Deobfuscating ), 185 m_deobfuscator.getTranslator( TranslationDirection.Deobfuscating ),
169 obfEntry 186 obfBehaviorEntry
170 ); 187 );
171 rootNode.load( m_deobfuscator.getJarIndex(), true ); 188 rootNode.load( m_deobfuscator.getJarIndex(), true );
172 return rootNode; 189 return rootNode;
@@ -181,13 +198,13 @@ public class GuiController
181 refreshCurrentClass( obfReference ); 198 refreshCurrentClass( obfReference );
182 } 199 }
183 200
184 public void openDeclaration( Entry entry ) 201 public void openDeclaration( Entry deobfEntry )
185 { 202 {
186 if( entry == null ) 203 if( deobfEntry == null )
187 { 204 {
188 throw new IllegalArgumentException( "Entry cannot be null!" ); 205 throw new IllegalArgumentException( "Entry cannot be null!" );
189 } 206 }
190 openReference( new EntryReference<Entry,Entry>( entry ) ); 207 openReference( new EntryReference<Entry,Entry>( deobfEntry ) );
191 } 208 }
192 209
193 public void openReference( EntryReference<Entry,Entry> deobfReference ) 210 public void openReference( EntryReference<Entry,Entry> deobfReference )
@@ -208,8 +225,22 @@ public class GuiController
208 } 225 }
209 else 226 else
210 { 227 {
211 // the class file is already open, just navigate to the reference 228 showReference( obfReference );
212 m_gui.showToken( m_index.getReferenceToken( deobfReference ) ); 229 }
230 }
231
232 private void showReference( EntryReference<Entry,Entry> obfReference )
233 {
234 EntryReference<Entry,Entry> deobfReference = m_deobfuscator.deobfuscateReference( obfReference );
235 Collection<Token> tokens = m_index.getReferenceTokens( deobfReference );
236 if( tokens.isEmpty() )
237 {
238 // DEBUG
239 System.err.println( String.format( "WARNING: no tokens found for %s in %s", deobfReference, m_currentObfClass ) );
240 }
241 else
242 {
243 m_gui.showTokens( tokens );
213 } 244 }
214 } 245 }
215 246
@@ -245,15 +276,15 @@ public class GuiController
245 refreshCurrentClass( null ); 276 refreshCurrentClass( null );
246 } 277 }
247 278
248 private void refreshCurrentClass( EntryReference<Entry,Entry> obfReferenceToShow ) 279 private void refreshCurrentClass( EntryReference<Entry,Entry> obfReference )
249 { 280 {
250 if( m_currentObfClass != null ) 281 if( m_currentObfClass != null )
251 { 282 {
252 deobfuscate( m_currentObfClass, obfReferenceToShow ); 283 deobfuscate( m_currentObfClass, obfReference );
253 } 284 }
254 } 285 }
255 286
256 private void deobfuscate( final ClassEntry classEntry, final EntryReference<Entry,Entry> obfReferenceToShow ) 287 private void deobfuscate( final ClassEntry classEntry, final EntryReference<Entry,Entry> obfReference )
257 { 288 {
258 m_gui.setSource( "(deobfuscating...)" ); 289 m_gui.setSource( "(deobfuscating...)" );
259 290
@@ -266,19 +297,9 @@ public class GuiController
266 // decompile,deobfuscate the bytecode 297 // decompile,deobfuscate the bytecode
267 m_index = m_deobfuscator.getSource( classEntry.getClassName() ); 298 m_index = m_deobfuscator.getSource( classEntry.getClassName() );
268 m_gui.setSource( m_index.getSource() ); 299 m_gui.setSource( m_index.getSource() );
269 if( obfReferenceToShow != null ) 300 if( obfReference != null )
270 { 301 {
271 EntryReference<Entry,Entry> deobfReferenceToShow = m_deobfuscator.deobfuscateReference( obfReferenceToShow ); 302 showReference( obfReference );
272 Token token = m_index.getReferenceToken( deobfReferenceToShow );
273 if( token == null )
274 {
275 // DEBUG
276 System.out.println( "WARNING: can't find token for " + obfReferenceToShow + " -> " + deobfReferenceToShow );
277 }
278 else
279 {
280 m_gui.showToken( token );
281 }
282 } 303 }
283 304
284 // set the highlighted tokens 305 // set the highlighted tokens
diff --git a/src/cuchaz/enigma/gui/ReadableToken.java b/src/cuchaz/enigma/gui/ReadableToken.java
new file mode 100644
index 00000000..3f430453
--- /dev/null
+++ b/src/cuchaz/enigma/gui/ReadableToken.java
@@ -0,0 +1,38 @@
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.gui;
12
13public class ReadableToken
14{
15 public int line;
16 public int startColumn;
17 public int endColumn;
18
19 public ReadableToken( int line, int startColumn, int endColumn )
20 {
21 this.line = line;
22 this.startColumn = startColumn;
23 this.endColumn = endColumn;
24 }
25
26 @Override
27 public String toString( )
28 {
29 StringBuilder buf = new StringBuilder();
30 buf.append( "line " );
31 buf.append( line );
32 buf.append( " columns " );
33 buf.append( startColumn );
34 buf.append( "-" );
35 buf.append( endColumn );
36 return buf.toString();
37 }
38}
diff --git a/src/cuchaz/enigma/gui/TokenListCellRenderer.java b/src/cuchaz/enigma/gui/TokenListCellRenderer.java
new file mode 100644
index 00000000..9247c066
--- /dev/null
+++ b/src/cuchaz/enigma/gui/TokenListCellRenderer.java
@@ -0,0 +1,40 @@
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.gui;
12
13import java.awt.Component;
14
15import javax.swing.DefaultListCellRenderer;
16import javax.swing.JLabel;
17import javax.swing.JList;
18import javax.swing.ListCellRenderer;
19
20import cuchaz.enigma.analysis.Token;
21
22public class TokenListCellRenderer implements ListCellRenderer<Token>
23{
24 private GuiController m_controller;
25 private DefaultListCellRenderer m_defaultRenderer;
26
27 public TokenListCellRenderer( GuiController controller )
28 {
29 m_controller = controller;
30 m_defaultRenderer = new DefaultListCellRenderer();
31 }
32
33 @Override
34 public Component getListCellRendererComponent( JList<? extends Token> list, Token token, int index, boolean isSelected, boolean hasFocus )
35 {
36 JLabel label = (JLabel)m_defaultRenderer.getListCellRendererComponent( list, token, index, isSelected, hasFocus );
37 label.setText( m_controller.getReadableToken( token ).toString() );
38 return label;
39 }
40}
diff --git a/src/cuchaz/enigma/mapping/ConstructorEntry.java b/src/cuchaz/enigma/mapping/ConstructorEntry.java
index 0f7dab68..ad029e1c 100644
--- a/src/cuchaz/enigma/mapping/ConstructorEntry.java
+++ b/src/cuchaz/enigma/mapping/ConstructorEntry.java
@@ -21,16 +21,17 @@ public class ConstructorEntry implements BehaviorEntry, Serializable
21 private ClassEntry m_classEntry; 21 private ClassEntry m_classEntry;
22 private String m_signature; 22 private String m_signature;
23 23
24 public ConstructorEntry( ClassEntry classEntry )
25 {
26 this( classEntry, null );
27 }
28
24 public ConstructorEntry( ClassEntry classEntry, String signature ) 29 public ConstructorEntry( ClassEntry classEntry, String signature )
25 { 30 {
26 if( classEntry == null ) 31 if( classEntry == null )
27 { 32 {
28 throw new IllegalArgumentException( "Class cannot be null!" ); 33 throw new IllegalArgumentException( "Class cannot be null!" );
29 } 34 }
30 if( signature == null )
31 {
32 throw new IllegalArgumentException( "Method signature cannot be null!" );
33 }
34 35
35 m_classEntry = classEntry; 36 m_classEntry = classEntry;
36 m_signature = signature; 37 m_signature = signature;
@@ -47,11 +48,20 @@ public class ConstructorEntry implements BehaviorEntry, Serializable
47 { 48 {
48 return m_classEntry; 49 return m_classEntry;
49 } 50 }
50 51
51 @Override 52 @Override
52 public String getName( ) 53 public String getName( )
53 { 54 {
54 return m_classEntry.getName(); 55 if( isStatic() )
56 {
57 return "<clinit>";
58 }
59 return "<init>";
60 }
61
62 public boolean isStatic( )
63 {
64 return m_signature == null;
55 } 65 }
56 66
57 @Override 67 @Override
@@ -69,7 +79,14 @@ public class ConstructorEntry implements BehaviorEntry, Serializable
69 @Override 79 @Override
70 public int hashCode( ) 80 public int hashCode( )
71 { 81 {
72 return Util.combineHashesOrdered( m_classEntry, m_signature ); 82 if( isStatic() )
83 {
84 return Util.combineHashesOrdered( m_classEntry );
85 }
86 else
87 {
88 return Util.combineHashesOrdered( m_classEntry, m_signature );
89 }
73 } 90 }
74 91
75 @Override 92 @Override
@@ -84,12 +101,31 @@ public class ConstructorEntry implements BehaviorEntry, Serializable
84 101
85 public boolean equals( ConstructorEntry other ) 102 public boolean equals( ConstructorEntry other )
86 { 103 {
87 return m_classEntry.equals( other.m_classEntry ) && m_signature.equals( other.m_signature ); 104 if( isStatic() != other.isStatic() )
105 {
106 return false;
107 }
108
109 if( isStatic() )
110 {
111 return m_classEntry.equals( other.m_classEntry );
112 }
113 else
114 {
115 return m_classEntry.equals( other.m_classEntry ) && m_signature.equals( other.m_signature );
116 }
88 } 117 }
89 118
90 @Override 119 @Override
91 public String toString( ) 120 public String toString( )
92 { 121 {
93 return m_classEntry.getName() + m_signature; 122 if( isStatic() )
123 {
124 return m_classEntry.getName() + "." + getName();
125 }
126 else
127 {
128 return m_classEntry.getName() + "." + getName() + m_signature;
129 }
94 } 130 }
95} 131}
diff --git a/src/cuchaz/enigma/mapping/Translator.java b/src/cuchaz/enigma/mapping/Translator.java
index e34c31bf..a671c275 100644
--- a/src/cuchaz/enigma/mapping/Translator.java
+++ b/src/cuchaz/enigma/mapping/Translator.java
@@ -30,27 +30,28 @@ public class Translator
30 m_ancestries = ancestries; 30 m_ancestries = ancestries;
31 } 31 }
32 32
33 public Entry translateEntry( Entry entry ) 33 @SuppressWarnings( "unchecked" )
34 public <T extends Entry> T translateEntry( T entry )
34 { 35 {
35 if( entry instanceof ClassEntry ) 36 if( entry instanceof ClassEntry )
36 { 37 {
37 return translateEntry( (ClassEntry)entry ); 38 return (T)translateEntry( (ClassEntry)entry );
38 } 39 }
39 else if( entry instanceof FieldEntry ) 40 else if( entry instanceof FieldEntry )
40 { 41 {
41 return translateEntry( (FieldEntry)entry ); 42 return (T)translateEntry( (FieldEntry)entry );
42 } 43 }
43 else if( entry instanceof MethodEntry ) 44 else if( entry instanceof MethodEntry )
44 { 45 {
45 return translateEntry( (MethodEntry)entry ); 46 return (T)translateEntry( (MethodEntry)entry );
46 } 47 }
47 else if( entry instanceof ConstructorEntry ) 48 else if( entry instanceof ConstructorEntry )
48 { 49 {
49 return translateEntry( (ConstructorEntry)entry ); 50 return (T)translateEntry( (ConstructorEntry)entry );
50 } 51 }
51 else if( entry instanceof ArgumentEntry ) 52 else if( entry instanceof ArgumentEntry )
52 { 53 {
53 return translateEntry( (ArgumentEntry)entry ); 54 return (T)translateEntry( (ArgumentEntry)entry );
54 } 55 }
55 else 56 else
56 { 57 {
@@ -194,10 +195,17 @@ public class Translator
194 195
195 public ConstructorEntry translateEntry( ConstructorEntry in ) 196 public ConstructorEntry translateEntry( ConstructorEntry in )
196 { 197 {
197 return new ConstructorEntry( 198 if( in.isStatic() )
198 translateEntry( in.getClassEntry() ), 199 {
199 translateSignature( in.getSignature() ) 200 return new ConstructorEntry( translateEntry( in.getClassEntry() ) );
200 ); 201 }
202 else
203 {
204 return new ConstructorEntry(
205 translateEntry( in.getClassEntry() ),
206 translateSignature( in.getSignature() )
207 );
208 }
201 } 209 }
202 210
203 public BehaviorEntry translateEntry( BehaviorEntry in ) 211 public BehaviorEntry translateEntry( BehaviorEntry in )