summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar jeff2014-09-24 01:00:54 -0400
committerGravatar jeff2014-09-24 01:00:54 -0400
commit8776a8ba38123c822530e5f659c626c8db616217 (patch)
tree8138a4e4447552e598bb99cfd8fb23a5f27f840b /src
parenttrying to figure out why some mappings to correspond to anything in the jar f... (diff)
downloadenigma-8776a8ba38123c822530e5f659c626c8db616217.tar.gz
enigma-8776a8ba38123c822530e5f659c626c8db616217.tar.xz
enigma-8776a8ba38123c822530e5f659c626c8db616217.zip
HOW DO I WRITE SO MANY BUGS?!?
Diffstat (limited to 'src')
-rw-r--r--src/cuchaz/enigma/Deobfuscator.java102
-rw-r--r--src/cuchaz/enigma/analysis/EntryRenamer.java4
-rw-r--r--src/cuchaz/enigma/analysis/JarIndex.java102
-rw-r--r--src/cuchaz/enigma/analysis/MethodImplementationsTreeNode.java2
-rw-r--r--src/cuchaz/enigma/analysis/MethodInheritanceTreeNode.java2
-rw-r--r--src/cuchaz/enigma/analysis/SourceIndex.java9
-rw-r--r--src/cuchaz/enigma/analysis/SourceIndexBehaviorVisitor.java18
-rw-r--r--src/cuchaz/enigma/bytecode/MethodParameterWriter.java22
-rw-r--r--src/cuchaz/enigma/convert/ClassMatcher.java6
-rw-r--r--src/cuchaz/enigma/gui/Gui.java16
-rw-r--r--src/cuchaz/enigma/gui/GuiController.java3
-rw-r--r--src/cuchaz/enigma/mapping/ArgumentEntry.java43
-rw-r--r--src/cuchaz/enigma/mapping/ClassEntry.java18
-rw-r--r--src/cuchaz/enigma/mapping/ClassMapping.java34
-rw-r--r--src/cuchaz/enigma/mapping/ConstructorEntry.java12
-rw-r--r--src/cuchaz/enigma/mapping/Entry.java1
-rw-r--r--src/cuchaz/enigma/mapping/FieldEntry.java6
-rw-r--r--src/cuchaz/enigma/mapping/Mappings.java6
-rw-r--r--src/cuchaz/enigma/mapping/MappingsRenamer.java32
-rw-r--r--src/cuchaz/enigma/mapping/MethodEntry.java6
-rw-r--r--src/cuchaz/enigma/mapping/Translator.java2
21 files changed, 335 insertions, 111 deletions
diff --git a/src/cuchaz/enigma/Deobfuscator.java b/src/cuchaz/enigma/Deobfuscator.java
index 03c35113..f7f74480 100644
--- a/src/cuchaz/enigma/Deobfuscator.java
+++ b/src/cuchaz/enigma/Deobfuscator.java
@@ -39,6 +39,7 @@ import cuchaz.enigma.analysis.EntryReference;
39import cuchaz.enigma.analysis.JarIndex; 39import 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.mapping.ArgumentEntry; 43import cuchaz.enigma.mapping.ArgumentEntry;
43import cuchaz.enigma.mapping.ClassEntry; 44import cuchaz.enigma.mapping.ClassEntry;
44import cuchaz.enigma.mapping.ClassMapping; 45import cuchaz.enigma.mapping.ClassMapping;
@@ -115,7 +116,7 @@ public class Deobfuscator
115 val = new Mappings(); 116 val = new Mappings();
116 } 117 }
117 118
118 // look for any classes that got moved to inner classes 119 // pass 1: look for any classes that got moved to inner classes
119 Map<String,String> renames = Maps.newHashMap(); 120 Map<String,String> renames = Maps.newHashMap();
120 for( ClassMapping classMapping : val.classes() ) 121 for( ClassMapping classMapping : val.classes() )
121 { 122 {
@@ -136,6 +137,53 @@ public class Deobfuscator
136 val.renameObfClass( entry.getKey(), entry.getValue() ); 137 val.renameObfClass( entry.getKey(), entry.getValue() );
137 } 138 }
138 139
140 // pass 2: look for fields/methods that are actually declared in superclasses
141 MappingsRenamer renamer = new MappingsRenamer( m_jarIndex, val );
142 for( ClassMapping classMapping : val.classes() )
143 {
144 ClassEntry obfClassEntry = new ClassEntry( classMapping.getObfName() );
145
146 // fields
147 for( FieldMapping fieldMapping : Lists.newArrayList( classMapping.fields() ) )
148 {
149 FieldEntry fieldEntry = new FieldEntry( obfClassEntry, fieldMapping.getObfName() );
150 ClassEntry resolvedObfClassEntry = m_jarIndex.resolveEntryClass( fieldEntry );
151 if( resolvedObfClassEntry != null && !resolvedObfClassEntry.equals( fieldEntry.getClassEntry() ) )
152 {
153 boolean wasMoved = renamer.moveFieldToObfClass( classMapping, fieldMapping, resolvedObfClassEntry );
154 if( wasMoved )
155 {
156 System.out.println( String.format( "Moved field %s to class %s", fieldEntry, resolvedObfClassEntry ) );
157 }
158 else
159 {
160 System.err.println( String.format( "WARNING: Would move field %s to class %s but the field was already there. Dropping instead.", fieldEntry, resolvedObfClassEntry ) );
161 }
162 }
163 }
164
165 // methods
166 for( MethodMapping methodMapping : Lists.newArrayList( classMapping.methods() ) )
167 {
168 MethodEntry methodEntry = new MethodEntry( obfClassEntry, methodMapping.getObfName(), methodMapping.getObfSignature() );
169 ClassEntry resolvedObfClassEntry = m_jarIndex.resolveEntryClass( methodEntry );
170 if( resolvedObfClassEntry != null && !resolvedObfClassEntry.equals( methodEntry.getClassEntry() ) )
171 {
172 boolean wasMoved = renamer.moveMethodToObfClass( classMapping, methodMapping, resolvedObfClassEntry );
173 if( wasMoved )
174 {
175 System.out.println( String.format( "Moved method %s to class %s", methodEntry, resolvedObfClassEntry ) );
176 }
177 else
178 {
179 System.err.println( String.format( "WARNING: Would move method %s to class %s but the method was already there. Dropping instead.", methodEntry, resolvedObfClassEntry ) );
180 }
181 }
182 }
183
184 // TODO: recurse to inner classes?
185 }
186
139 // drop mappings that don't match the jar 187 // drop mappings that don't match the jar
140 List<ClassEntry> unknownClasses = Lists.newArrayList(); 188 List<ClassEntry> unknownClasses = Lists.newArrayList();
141 for( ClassMapping classMapping : val.classes() ) 189 for( ClassMapping classMapping : val.classes() )
@@ -148,7 +196,7 @@ public class Deobfuscator
148 } 196 }
149 197
150 m_mappings = val; 198 m_mappings = val;
151 m_renamer = new MappingsRenamer( m_jarIndex, m_mappings ); 199 m_renamer = renamer;
152 m_translatorCache.clear(); 200 m_translatorCache.clear();
153 } 201 }
154 202
@@ -170,7 +218,7 @@ public class Deobfuscator
170 for( FieldMapping fieldMapping : Lists.newArrayList( classMapping.fields() ) ) 218 for( FieldMapping fieldMapping : Lists.newArrayList( classMapping.fields() ) )
171 { 219 {
172 FieldEntry fieldEntry = new FieldEntry( classEntry, fieldMapping.getObfName() ); 220 FieldEntry fieldEntry = new FieldEntry( classEntry, fieldMapping.getObfName() );
173 if( m_jarIndex.getAccess( fieldEntry ) == null ) 221 if( !m_jarIndex.containsObfField( fieldEntry ) )
174 { 222 {
175 System.err.println( "WARNING: unable to find field " + fieldEntry + ". dropping mapping." ); 223 System.err.println( "WARNING: unable to find field " + fieldEntry + ". dropping mapping." );
176 classMapping.removeFieldMapping( fieldMapping ); 224 classMapping.removeFieldMapping( fieldMapping );
@@ -188,7 +236,7 @@ public class Deobfuscator
188 else if( methodMapping.getObfName().equals( "<init>" ) ) 236 else if( methodMapping.getObfName().equals( "<init>" ) )
189 { 237 {
190 ConstructorEntry constructorEntry = new ConstructorEntry( classEntry, methodMapping.getObfSignature() ); 238 ConstructorEntry constructorEntry = new ConstructorEntry( classEntry, methodMapping.getObfSignature() );
191 if( m_jarIndex.getAccess( constructorEntry ) == null ) 239 if( !m_jarIndex.containsObfBehavior( constructorEntry ) )
192 { 240 {
193 System.err.println( "WARNING: unable to find constructor " + constructorEntry + ". dropping mapping." ); 241 System.err.println( "WARNING: unable to find constructor " + constructorEntry + ". dropping mapping." );
194 classMapping.removeMethodMapping( methodMapping ); 242 classMapping.removeMethodMapping( methodMapping );
@@ -201,7 +249,7 @@ public class Deobfuscator
201 methodMapping.getObfName(), 249 methodMapping.getObfName(),
202 methodMapping.getObfSignature() 250 methodMapping.getObfSignature()
203 ); 251 );
204 if( m_jarIndex.getAccess( methodEntry ) == null ) 252 if( !m_jarIndex.containsObfBehavior( methodEntry ) )
205 { 253 {
206 System.err.println( "WARNING: unable to find method " + methodEntry + ". dropping mapping." ); 254 System.err.println( "WARNING: unable to find method " + methodEntry + ". dropping mapping." );
207 classMapping.removeMethodMapping( methodMapping ); 255 classMapping.removeMethodMapping( methodMapping );
@@ -257,19 +305,20 @@ public class Deobfuscator
257 } 305 }
258 } 306 }
259 307
260 public CompilationUnit getSourceTree( String className ) 308 public CompilationUnit getSourceTree( String obfClassName )
261 { 309 {
262 // is this class deobfuscated? 310 // is this class deobfuscated?
263 // we need to tell the decompiler the deobfuscated name so it doesn't get freaked out 311 // we need to tell the decompiler the deobfuscated name so it doesn't get freaked out
264 // the decompiler only sees the deobfuscated class, so we need to load it by the deobfuscated name 312 // the decompiler only sees the deobfuscated class, so we need to load it by the deobfuscated name
265 ClassMapping classMapping = m_mappings.getClassByObf( className ); 313 String lookupClassName = obfClassName;
314 ClassMapping classMapping = m_mappings.getClassByObf( obfClassName );
266 if( classMapping != null && classMapping.getDeobfName() != null ) 315 if( classMapping != null && classMapping.getDeobfName() != null )
267 { 316 {
268 className = classMapping.getDeobfName(); 317 lookupClassName = classMapping.getDeobfName();
269 } 318 }
270 319
271 // is this class even in the jar? 320 // is this class even in the jar?
272 if( !m_jarIndex.containsObfClass( new ClassEntry( className ) ) ) 321 if( !m_jarIndex.containsObfClass( new ClassEntry( obfClassName ) ) )
273 { 322 {
274 return null; 323 return null;
275 } 324 }
@@ -283,7 +332,7 @@ public class Deobfuscator
283 ) ); 332 ) );
284 333
285 // decompile it! 334 // decompile it!
286 TypeDefinition resolvedType = new MetadataSystem( m_settings.getTypeLoader() ).lookupType( className ).resolve(); 335 TypeDefinition resolvedType = new MetadataSystem( m_settings.getTypeLoader() ).lookupType( lookupClassName ).resolve();
287 DecompilerContext context = new DecompilerContext(); 336 DecompilerContext context = new DecompilerContext();
288 context.setCurrentType( resolvedType ); 337 context.setCurrentType( resolvedType );
289 context.setSettings( m_settings ); 338 context.setSettings( m_settings );
@@ -302,13 +351,29 @@ public class Deobfuscator
302 // DEBUG 351 // DEBUG
303 //sourceTree.acceptVisitor( new TreeDumpVisitor( new File( "tree.txt" ) ), null ); 352 //sourceTree.acceptVisitor( new TreeDumpVisitor( new File( "tree.txt" ) ), null );
304 353
305 /* DEBUG 354 // resolve all the classes in the source references
306 for( Token token : index.referenceTokens() ) 355 for( Token token : index.referenceTokens() )
307 { 356 {
308 EntryReference<Entry,Entry> reference = index.getDeobfReference( token ); 357 EntryReference<Entry,Entry> deobfReference = index.getDeobfReference( token );
309 System.out.println( token + " -> " + reference + " -> " + index.getReferenceToken( reference ) ); 358
359 // get the obfuscated entry
360 Entry obfEntry = obfuscateEntry( deobfReference.entry );
361
362 // try to resolve the class
363 ClassEntry resolvedObfClassEntry = m_jarIndex.resolveEntryClass( obfEntry );
364 if( resolvedObfClassEntry != null && !resolvedObfClassEntry.equals( obfEntry.getClassEntry() ) )
365 {
366 // change the class of the entry
367 obfEntry = obfEntry.cloneToNewClass( resolvedObfClassEntry );
368
369 // save the new deobfuscated reference
370 deobfReference.entry = deobfuscateEntry( obfEntry );
371 index.replaceDeobfReference( token, deobfReference );
372 }
373
374 // DEBUG
375 //System.out.println( token + " -> " + reference + " -> " + index.getReferenceToken( reference ) );
310 } 376 }
311 */
312 377
313 return index; 378 return index;
314 } 379 }
@@ -486,13 +551,6 @@ public class Deobfuscator
486 551
487 public boolean isObfuscatedIdentifier( Entry obfEntry ) 552 public boolean isObfuscatedIdentifier( Entry obfEntry )
488 { 553 {
489 if( obfEntry instanceof ClassEntry ) 554 return m_jarIndex.containsObfEntry( obfEntry );
490 {
491 return m_jarIndex.getObfClassEntries().contains( obfEntry );
492 }
493 else
494 {
495 return isObfuscatedIdentifier( obfEntry.getClassEntry() );
496 }
497 } 555 }
498} 556}
diff --git a/src/cuchaz/enigma/analysis/EntryRenamer.java b/src/cuchaz/enigma/analysis/EntryRenamer.java
index b82b2547..44e0220c 100644
--- a/src/cuchaz/enigma/analysis/EntryRenamer.java
+++ b/src/cuchaz/enigma/analysis/EntryRenamer.java
@@ -117,7 +117,7 @@ public class EntryRenamer
117 { 117 {
118 ArgumentEntry argumentEntry = (ArgumentEntry)thing; 118 ArgumentEntry argumentEntry = (ArgumentEntry)thing;
119 return (T)new ArgumentEntry( 119 return (T)new ArgumentEntry(
120 renameMethodsInThing( renames, argumentEntry.getMethodEntry() ), 120 renameMethodsInThing( renames, argumentEntry.getBehaviorEntry() ),
121 argumentEntry.getIndex(), 121 argumentEntry.getIndex(),
122 argumentEntry.getName() 122 argumentEntry.getName()
123 ); 123 );
@@ -177,7 +177,7 @@ public class EntryRenamer
177 { 177 {
178 ArgumentEntry argumentEntry = (ArgumentEntry)thing; 178 ArgumentEntry argumentEntry = (ArgumentEntry)thing;
179 return (T)new ArgumentEntry( 179 return (T)new ArgumentEntry(
180 renameClassesInThing( renames, argumentEntry.getMethodEntry() ), 180 renameClassesInThing( renames, argumentEntry.getBehaviorEntry() ),
181 argumentEntry.getIndex(), 181 argumentEntry.getIndex(),
182 argumentEntry.getName() 182 argumentEntry.getName()
183 ); 183 );
diff --git a/src/cuchaz/enigma/analysis/JarIndex.java b/src/cuchaz/enigma/analysis/JarIndex.java
index b51428a2..9f309cec 100644
--- a/src/cuchaz/enigma/analysis/JarIndex.java
+++ b/src/cuchaz/enigma/analysis/JarIndex.java
@@ -42,6 +42,7 @@ import com.google.common.collect.Sets;
42 42
43import cuchaz.enigma.Constants; 43import cuchaz.enigma.Constants;
44import cuchaz.enigma.bytecode.ClassRenamer; 44import cuchaz.enigma.bytecode.ClassRenamer;
45import cuchaz.enigma.mapping.ArgumentEntry;
45import cuchaz.enigma.mapping.BehaviorEntry; 46import cuchaz.enigma.mapping.BehaviorEntry;
46import cuchaz.enigma.mapping.ClassEntry; 47import cuchaz.enigma.mapping.ClassEntry;
47import cuchaz.enigma.mapping.ConstructorEntry; 48import cuchaz.enigma.mapping.ConstructorEntry;
@@ -264,7 +265,15 @@ public class JarIndex
264 call.getMethodName(), 265 call.getMethodName(),
265 call.getSignature() 266 call.getSignature()
266 ); 267 );
267 calledMethodEntry = resolveMethodClass( calledMethodEntry ); 268 ClassEntry resolvedClassEntry = resolveEntryClass( calledMethodEntry );
269 if( resolvedClassEntry != null && !resolvedClassEntry.equals( calledMethodEntry.getClassEntry() ) )
270 {
271 calledMethodEntry = new MethodEntry(
272 resolvedClassEntry,
273 call.getMethodName(),
274 call.getSignature()
275 );
276 }
268 EntryReference<BehaviorEntry,BehaviorEntry> reference = new EntryReference<BehaviorEntry,BehaviorEntry>( 277 EntryReference<BehaviorEntry,BehaviorEntry> reference = new EntryReference<BehaviorEntry,BehaviorEntry>(
269 calledMethodEntry, 278 calledMethodEntry,
270 behaviorEntry 279 behaviorEntry
@@ -280,6 +289,14 @@ public class JarIndex
280 new ClassEntry( className ), 289 new ClassEntry( className ),
281 call.getFieldName() 290 call.getFieldName()
282 ); 291 );
292 ClassEntry resolvedClassEntry = resolveEntryClass( calledFieldEntry );
293 if( resolvedClassEntry != null && !resolvedClassEntry.equals( calledFieldEntry.getClassEntry() ) )
294 {
295 calledFieldEntry = new FieldEntry(
296 resolvedClassEntry,
297 call.getFieldName()
298 );
299 }
283 EntryReference<FieldEntry,BehaviorEntry> reference = new EntryReference<FieldEntry,BehaviorEntry>( 300 EntryReference<FieldEntry,BehaviorEntry> reference = new EntryReference<FieldEntry,BehaviorEntry>(
284 calledFieldEntry, 301 calledFieldEntry,
285 behaviorEntry 302 behaviorEntry
@@ -355,30 +372,26 @@ public class JarIndex
355 throw new IllegalArgumentException( "behavior must be a method or a constructor!" ); 372 throw new IllegalArgumentException( "behavior must be a method or a constructor!" );
356 } 373 }
357 } 374 }
358 375
359 private MethodEntry resolveMethodClass( MethodEntry methodEntry ) 376 public ClassEntry resolveEntryClass( Entry obfEntry )
360 { 377 {
361 // this entry could refer to a method on a class where the method is not actually implemented 378 // this entry could refer to a method on a class where the method is not actually implemented
362 // travel up the inheritance tree to find the closest implementation 379 // travel up the inheritance tree to find the closest implementation
363 while( !isMethodImplemented( methodEntry ) ) 380 while( !containsObfEntry( obfEntry ) )
364 { 381 {
365 // is there a parent class? 382 // is there a parent class?
366 String superclassName = m_translationIndex.getSuperclassName( methodEntry.getClassName() ); 383 String superclassName = m_translationIndex.getSuperclassName( obfEntry.getClassName() );
367 if( superclassName == null ) 384 if( superclassName == null )
368 { 385 {
369 // this is probably a method from a class in a library 386 // this is probably a method from a class in a library
370 // we can't trace the implementation up any higher unless we index the library 387 // we can't trace the implementation up any higher unless we index the library
371 return methodEntry; 388 return null;
372 } 389 }
373 390
374 // move up to the parent class 391 // move up to the parent class
375 methodEntry = new MethodEntry( 392 obfEntry = obfEntry.cloneToNewClass( new ClassEntry( superclassName ) );
376 new ClassEntry( superclassName ),
377 methodEntry.getName(),
378 methodEntry.getSignature()
379 );
380 } 393 }
381 return methodEntry; 394 return obfEntry.getClassEntry();
382 } 395 }
383 396
384 private CtMethod getBridgedMethod( CtMethod method ) 397 private CtMethod getBridgedMethod( CtMethod method )
@@ -704,16 +717,6 @@ public class JarIndex
704 return m_fieldClasses.get( fieldEntry ); 717 return m_fieldClasses.get( fieldEntry );
705 } 718 }
706 719
707 public boolean isMethodImplemented( MethodEntry methodEntry )
708 {
709 Collection<MethodEntry> implementations = m_methodImplementations.get( methodEntry.getClassName() );
710 if( implementations == null )
711 {
712 return false;
713 }
714 return implementations.contains( methodEntry );
715 }
716
717 public ClassInheritanceTreeNode getClassInheritance( Translator deobfuscatingTranslator, ClassEntry obfClassEntry ) 720 public ClassInheritanceTreeNode getClassInheritance( Translator deobfuscatingTranslator, ClassEntry obfClassEntry )
718 { 721 {
719 // get the root node 722 // get the root node
@@ -751,7 +754,7 @@ public class JarIndex
751 obfMethodEntry.getName(), 754 obfMethodEntry.getName(),
752 obfMethodEntry.getSignature() 755 obfMethodEntry.getSignature()
753 ); 756 );
754 if( isMethodImplemented( ancestorMethodEntry ) ) 757 if( containsObfBehavior( ancestorMethodEntry ) )
755 { 758 {
756 baseImplementationClassName = ancestorClassName; 759 baseImplementationClassName = ancestorClassName;
757 } 760 }
@@ -766,7 +769,7 @@ public class JarIndex
766 MethodInheritanceTreeNode rootNode = new MethodInheritanceTreeNode( 769 MethodInheritanceTreeNode rootNode = new MethodInheritanceTreeNode(
767 deobfuscatingTranslator, 770 deobfuscatingTranslator,
768 methodEntry, 771 methodEntry,
769 isMethodImplemented( methodEntry ) 772 containsObfBehavior( methodEntry )
770 ); 773 );
771 774
772 // expand the full tree 775 // expand the full tree
@@ -796,7 +799,7 @@ public class JarIndex
796 obfMethodEntry.getName(), 799 obfMethodEntry.getName(),
797 obfMethodEntry.getSignature() 800 obfMethodEntry.getSignature()
798 ); 801 );
799 if( isMethodImplemented( methodInterface ) ) 802 if( containsObfBehavior( methodInterface ) )
800 { 803 {
801 methodInterfaces.add( methodInterface ); 804 methodInterfaces.add( methodInterface );
802 } 805 }
@@ -827,7 +830,7 @@ public class JarIndex
827 private void getRelatedMethodImplementations( Set<MethodEntry> methodEntries, MethodInheritanceTreeNode node ) 830 private void getRelatedMethodImplementations( Set<MethodEntry> methodEntries, MethodInheritanceTreeNode node )
828 { 831 {
829 MethodEntry methodEntry = node.getMethodEntry(); 832 MethodEntry methodEntry = node.getMethodEntry();
830 if( isMethodImplemented( methodEntry ) ) 833 if( containsObfBehavior( methodEntry ) )
831 { 834 {
832 // collect the entry 835 // collect the entry
833 methodEntries.add( methodEntry ); 836 methodEntries.add( methodEntry );
@@ -850,7 +853,7 @@ public class JarIndex
850 private void getRelatedMethodImplementations( Set<MethodEntry> methodEntries, MethodImplementationsTreeNode node ) 853 private void getRelatedMethodImplementations( Set<MethodEntry> methodEntries, MethodImplementationsTreeNode node )
851 { 854 {
852 MethodEntry methodEntry = node.getMethodEntry(); 855 MethodEntry methodEntry = node.getMethodEntry();
853 if( isMethodImplemented( methodEntry ) ) 856 if( containsObfBehavior( methodEntry ) )
854 { 857 {
855 // collect the entry 858 // collect the entry
856 methodEntries.add( methodEntry ); 859 methodEntries.add( methodEntry );
@@ -969,8 +972,49 @@ public class JarIndex
969 return m_access.containsKey( obfFieldEntry ); 972 return m_access.containsKey( obfFieldEntry );
970 } 973 }
971 974
972 public boolean containsObfMethod( MethodEntry obfMethodEntry ) 975 public boolean containsObfBehavior( BehaviorEntry obfBehaviorEntry )
976 {
977 return m_access.containsKey( obfBehaviorEntry );
978 }
979
980 public boolean containsObfArgument( ArgumentEntry obfArgumentEntry )
981 {
982 // check the behavior
983 if( !containsObfBehavior( obfArgumentEntry.getBehaviorEntry() ) )
984 {
985 return false;
986 }
987
988 // check the argument
989 if( obfArgumentEntry.getIndex() >= Descriptor.numOfParameters( obfArgumentEntry.getBehaviorEntry().getSignature() ) )
990 {
991 return false;
992 }
993
994 return true;
995 }
996
997 public boolean containsObfEntry( Entry obfEntry )
973 { 998 {
974 return m_access.containsKey( obfMethodEntry ); 999 if( obfEntry instanceof ClassEntry )
1000 {
1001 return containsObfClass( (ClassEntry)obfEntry );
1002 }
1003 else if( obfEntry instanceof FieldEntry )
1004 {
1005 return containsObfField( (FieldEntry)obfEntry );
1006 }
1007 else if( obfEntry instanceof BehaviorEntry )
1008 {
1009 return containsObfBehavior( (BehaviorEntry)obfEntry );
1010 }
1011 else if( obfEntry instanceof ArgumentEntry )
1012 {
1013 return containsObfArgument( (ArgumentEntry)obfEntry );
1014 }
1015 else
1016 {
1017 throw new Error( "Entry type not supported: " + obfEntry.getClass().getName() );
1018 }
975 } 1019 }
976} 1020}
diff --git a/src/cuchaz/enigma/analysis/MethodImplementationsTreeNode.java b/src/cuchaz/enigma/analysis/MethodImplementationsTreeNode.java
index 8b9dd2d8..a050282b 100644
--- a/src/cuchaz/enigma/analysis/MethodImplementationsTreeNode.java
+++ b/src/cuchaz/enigma/analysis/MethodImplementationsTreeNode.java
@@ -81,7 +81,7 @@ public class MethodImplementationsTreeNode extends DefaultMutableTreeNode
81 m_entry.getName(), 81 m_entry.getName(),
82 m_entry.getSignature() 82 m_entry.getSignature()
83 ); 83 );
84 if( index.isMethodImplemented( methodEntry ) ) 84 if( index.containsObfBehavior( methodEntry ) )
85 { 85 {
86 nodes.add( new MethodImplementationsTreeNode( m_deobfuscatingTranslator, methodEntry ) ); 86 nodes.add( new MethodImplementationsTreeNode( m_deobfuscatingTranslator, methodEntry ) );
87 } 87 }
diff --git a/src/cuchaz/enigma/analysis/MethodInheritanceTreeNode.java b/src/cuchaz/enigma/analysis/MethodInheritanceTreeNode.java
index d77fd858..bd919518 100644
--- a/src/cuchaz/enigma/analysis/MethodInheritanceTreeNode.java
+++ b/src/cuchaz/enigma/analysis/MethodInheritanceTreeNode.java
@@ -93,7 +93,7 @@ public class MethodInheritanceTreeNode extends DefaultMutableTreeNode
93 nodes.add( new MethodInheritanceTreeNode( 93 nodes.add( new MethodInheritanceTreeNode(
94 m_deobfuscatingTranslator, 94 m_deobfuscatingTranslator,
95 methodEntry, 95 methodEntry,
96 index.isMethodImplemented( methodEntry ) 96 index.containsObfBehavior( methodEntry )
97 ) ); 97 ) );
98 } 98 }
99 99
diff --git a/src/cuchaz/enigma/analysis/SourceIndex.java b/src/cuchaz/enigma/analysis/SourceIndex.java
index 49451b90..a5d1460f 100644
--- a/src/cuchaz/enigma/analysis/SourceIndex.java
+++ b/src/cuchaz/enigma/analysis/SourceIndex.java
@@ -126,6 +126,15 @@ public class SourceIndex
126 return m_tokenToReference.get( token ); 126 return m_tokenToReference.get( token );
127 } 127 }
128 128
129 public void replaceDeobfReference( Token token, EntryReference<Entry,Entry> newDeobfReference )
130 {
131 EntryReference<Entry,Entry> oldDeobfReference = m_tokenToReference.get( token );
132 m_tokenToReference.put( token, newDeobfReference );
133 Collection<Token> tokens = m_referenceToTokens.get( oldDeobfReference );
134 m_referenceToTokens.removeAll( oldDeobfReference );
135 m_referenceToTokens.putAll( newDeobfReference, tokens );
136 }
137
129 public Iterable<Token> referenceTokens( ) 138 public Iterable<Token> referenceTokens( )
130 { 139 {
131 return m_tokenToReference.keySet(); 140 return m_tokenToReference.keySet();
diff --git a/src/cuchaz/enigma/analysis/SourceIndexBehaviorVisitor.java b/src/cuchaz/enigma/analysis/SourceIndexBehaviorVisitor.java
index 6238b1e7..f307c11d 100644
--- a/src/cuchaz/enigma/analysis/SourceIndexBehaviorVisitor.java
+++ b/src/cuchaz/enigma/analysis/SourceIndexBehaviorVisitor.java
@@ -116,6 +116,12 @@ public class SourceIndexBehaviorVisitor extends SourceIndexVisitor
116 MemberReference ref = node.getUserData( Keys.MEMBER_REFERENCE ); 116 MemberReference ref = node.getUserData( Keys.MEMBER_REFERENCE );
117 if( ref != null ) 117 if( ref != null )
118 { 118 {
119 // make sure this is actually a field
120 if( ref.getSignature().indexOf( '(' ) >= 0 )
121 {
122 throw new Error( "Expected a field here! got " + ref );
123 }
124
119 ClassEntry classEntry = new ClassEntry( ref.getDeclaringType().getInternalName() ); 125 ClassEntry classEntry = new ClassEntry( ref.getDeclaringType().getInternalName() );
120 FieldEntry fieldEntry = new FieldEntry( classEntry, ref.getName() ); 126 FieldEntry fieldEntry = new FieldEntry( classEntry, ref.getName() );
121 index.addReference( 127 index.addReference(
@@ -149,8 +155,16 @@ public class SourceIndexBehaviorVisitor extends SourceIndexVisitor
149 ParameterDefinition def = node.getUserData( Keys.PARAMETER_DEFINITION ); 155 ParameterDefinition def = node.getUserData( Keys.PARAMETER_DEFINITION );
150 ClassEntry classEntry = new ClassEntry( def.getDeclaringType().getInternalName() ); 156 ClassEntry classEntry = new ClassEntry( def.getDeclaringType().getInternalName() );
151 MethodDefinition methodDef = (MethodDefinition)def.getMethod(); 157 MethodDefinition methodDef = (MethodDefinition)def.getMethod();
152 MethodEntry methodEntry = new MethodEntry( classEntry, methodDef.getName(), methodDef.getSignature() ); 158 BehaviorEntry behaviorEntry;
153 ArgumentEntry argumentEntry = new ArgumentEntry( methodEntry, def.getPosition(), def.getName() ); 159 if( methodDef.isConstructor() )
160 {
161 behaviorEntry = new ConstructorEntry( classEntry, methodDef.getSignature() );
162 }
163 else
164 {
165 behaviorEntry = new MethodEntry( classEntry, methodDef.getName(), methodDef.getSignature() );
166 }
167 ArgumentEntry argumentEntry = new ArgumentEntry( behaviorEntry, def.getPosition(), def.getName() );
154 index.addDeclaration( node.getNameToken(), argumentEntry ); 168 index.addDeclaration( node.getNameToken(), argumentEntry );
155 169
156 return recurse( node, index ); 170 return recurse( node, index );
diff --git a/src/cuchaz/enigma/bytecode/MethodParameterWriter.java b/src/cuchaz/enigma/bytecode/MethodParameterWriter.java
index a8d3983f..adea7eae 100644
--- a/src/cuchaz/enigma/bytecode/MethodParameterWriter.java
+++ b/src/cuchaz/enigma/bytecode/MethodParameterWriter.java
@@ -15,9 +15,13 @@ import java.util.List;
15 15
16import javassist.CtBehavior; 16import javassist.CtBehavior;
17import javassist.CtClass; 17import javassist.CtClass;
18import javassist.CtConstructor;
19import javassist.CtMethod;
18import javassist.bytecode.Descriptor; 20import javassist.bytecode.Descriptor;
19import cuchaz.enigma.mapping.ArgumentEntry; 21import cuchaz.enigma.mapping.ArgumentEntry;
22import cuchaz.enigma.mapping.BehaviorEntry;
20import cuchaz.enigma.mapping.ClassEntry; 23import cuchaz.enigma.mapping.ClassEntry;
24import cuchaz.enigma.mapping.ConstructorEntry;
21import cuchaz.enigma.mapping.MethodEntry; 25import cuchaz.enigma.mapping.MethodEntry;
22import cuchaz.enigma.mapping.Translator; 26import cuchaz.enigma.mapping.Translator;
23 27
@@ -42,12 +46,26 @@ public class MethodParameterWriter
42 continue; 46 continue;
43 } 47 }
44 48
49 // get the behavior entry
50 BehaviorEntry behaviorEntry;
51 if( behavior instanceof CtMethod )
52 {
53 behaviorEntry = new MethodEntry( classEntry, behavior.getMethodInfo().getName(), behavior.getSignature() );
54 }
55 else if( behavior instanceof CtConstructor )
56 {
57 behaviorEntry = new ConstructorEntry( classEntry, behavior.getSignature() );
58 }
59 else
60 {
61 throw new Error( "Unsupported behavior type: " + behavior.getClass().getName() );
62 }
63
45 // get the list of parameter names 64 // get the list of parameter names
46 MethodEntry methodEntry = new MethodEntry( classEntry, behavior.getMethodInfo().getName(), behavior.getSignature() );
47 List<String> names = new ArrayList<String>( numParams ); 65 List<String> names = new ArrayList<String>( numParams );
48 for( int i=0; i<numParams; i++ ) 66 for( int i=0; i<numParams; i++ )
49 { 67 {
50 names.add( m_translator.translate( new ArgumentEntry( methodEntry, i, "" ) ) ); 68 names.add( m_translator.translate( new ArgumentEntry( behaviorEntry, i, "" ) ) );
51 } 69 }
52 70
53 // save the mappings to the class 71 // save the mappings to the class
diff --git a/src/cuchaz/enigma/convert/ClassMatcher.java b/src/cuchaz/enigma/convert/ClassMatcher.java
index eb7a31df..290d90a7 100644
--- a/src/cuchaz/enigma/convert/ClassMatcher.java
+++ b/src/cuchaz/enigma/convert/ClassMatcher.java
@@ -57,8 +57,8 @@ public class ClassMatcher
57 // TEMP 57 // TEMP
58 JarFile sourceJar = new JarFile( new File( "input/1.8-pre3.jar" ) ); 58 JarFile sourceJar = new JarFile( new File( "input/1.8-pre3.jar" ) );
59 JarFile destJar = new JarFile( new File( "input/1.8.jar" ) ); 59 JarFile destJar = new JarFile( new File( "input/1.8.jar" ) );
60 File inMappingsFile = new File( "../minecraft-mappings/1.8-pre3.mappings" ); 60 File inMappingsFile = new File( "../Enigma Mappings/1.8-pre3.mappings" );
61 File outMappingsFile = new File( "../minecraft-mappings/1.8.mappings" ); 61 File outMappingsFile = new File( "../Enigma Mappings/1.8.mappings" );
62 62
63 // define a matching to use when the automated system cannot find a match 63 // define a matching to use when the automated system cannot find a match
64 Map<String,String> fallbackMatching = Maps.newHashMap(); 64 Map<String,String> fallbackMatching = Maps.newHashMap();
@@ -271,7 +271,7 @@ public class ClassMatcher
271 methodMapping.getObfName(), 271 methodMapping.getObfName(),
272 methodMapping.getObfSignature() 272 methodMapping.getObfSignature()
273 ); 273 );
274 if( !destIndex.isMethodImplemented( methodEntry ) ) 274 if( !destIndex.containsObfBehavior( methodEntry ) )
275 { 275 {
276 System.err.println( "WARNING: method doesn't match: " + methodEntry ); 276 System.err.println( "WARNING: method doesn't match: " + methodEntry );
277 277
diff --git a/src/cuchaz/enigma/gui/Gui.java b/src/cuchaz/enigma/gui/Gui.java
index 5eed728a..1f04aa35 100644
--- a/src/cuchaz/enigma/gui/Gui.java
+++ b/src/cuchaz/enigma/gui/Gui.java
@@ -229,27 +229,27 @@ public class Gui
229 switch( event.getKeyCode() ) 229 switch( event.getKeyCode() )
230 { 230 {
231 case KeyEvent.VK_R: 231 case KeyEvent.VK_R:
232 startRename(); 232 m_renameMenu.doClick();
233 break; 233 break;
234 234
235 case KeyEvent.VK_I: 235 case KeyEvent.VK_I:
236 showInheritance(); 236 m_showInheritanceMenu.doClick();
237 break; 237 break;
238 238
239 case KeyEvent.VK_M: 239 case KeyEvent.VK_M:
240 showImplementations(); 240 m_showImplementationsMenu.doClick();
241 break; 241 break;
242 242
243 case KeyEvent.VK_N: 243 case KeyEvent.VK_N:
244 navigateTo( m_reference.entry ); 244 m_openEntryMenu.doClick();
245 break; 245 break;
246 246
247 case KeyEvent.VK_P: 247 case KeyEvent.VK_P:
248 m_controller.openPreviousReference(); 248 m_openPreviousMenu.doClick();
249 break; 249 break;
250 250
251 case KeyEvent.VK_C: 251 case KeyEvent.VK_C:
252 showCalls(); 252 m_showCallsMenu.doClick();
253 break; 253 break;
254 } 254 }
255 } 255 }
@@ -987,7 +987,7 @@ public class Gui
987 { 987 {
988 addNameValue( m_infoPanel, "Argument", entry.getName() ); 988 addNameValue( m_infoPanel, "Argument", entry.getName() );
989 addNameValue( m_infoPanel, "Class", entry.getClassEntry().getName() ); 989 addNameValue( m_infoPanel, "Class", entry.getClassEntry().getName() );
990 addNameValue( m_infoPanel, "Method", entry.getMethodEntry().getName() ); 990 addNameValue( m_infoPanel, "Method", entry.getBehaviorEntry().getName() );
991 addNameValue( m_infoPanel, "Index", Integer.toString( entry.getIndex() ) ); 991 addNameValue( m_infoPanel, "Index", Integer.toString( entry.getIndex() ) );
992 } 992 }
993 993
@@ -1014,7 +1014,7 @@ public class Gui
1014 boolean isFieldEntry = isToken && m_reference.entry instanceof FieldEntry; 1014 boolean isFieldEntry = isToken && m_reference.entry instanceof FieldEntry;
1015 boolean isMethodEntry = isToken && m_reference.entry instanceof MethodEntry; 1015 boolean isMethodEntry = isToken && m_reference.entry instanceof MethodEntry;
1016 boolean isConstructorEntry = isToken && m_reference.entry instanceof ConstructorEntry; 1016 boolean isConstructorEntry = isToken && m_reference.entry instanceof ConstructorEntry;
1017 boolean isInJar = isToken && m_controller.entryIsInJar( m_reference.entry.getClassEntry() ); 1017 boolean isInJar = isToken && m_controller.entryIsInJar( m_reference.entry );
1018 1018
1019 if( isToken ) 1019 if( isToken )
1020 { 1020 {
diff --git a/src/cuchaz/enigma/gui/GuiController.java b/src/cuchaz/enigma/gui/GuiController.java
index bbefe606..098e065d 100644
--- a/src/cuchaz/enigma/gui/GuiController.java
+++ b/src/cuchaz/enigma/gui/GuiController.java
@@ -270,7 +270,7 @@ public class GuiController
270 ClassEntry obfClassEntry = obfReference.getClassEntry().getOuterClassEntry(); 270 ClassEntry obfClassEntry = obfReference.getClassEntry().getOuterClassEntry();
271 if( !m_deobfuscator.isObfuscatedIdentifier( obfClassEntry ) ) 271 if( !m_deobfuscator.isObfuscatedIdentifier( obfClassEntry ) )
272 { 272 {
273 throw new IllegalArgumentException( "Entry must be in the jar!" ); 273 throw new IllegalArgumentException( "Obfuscated class " + obfClassEntry + " was not found in the jar!" );
274 } 274 }
275 if( m_currentObfClass == null || !m_currentObfClass.equals( obfClassEntry ) ) 275 if( m_currentObfClass == null || !m_currentObfClass.equals( obfClassEntry ) )
276 { 276 {
@@ -354,6 +354,7 @@ public class GuiController
354 if( sourceTree == null ) 354 if( sourceTree == null )
355 { 355 {
356 // decompilation of this class is not supported 356 // decompilation of this class is not supported
357 m_gui.setSource("Unable to find class: " + classEntry);
357 return; 358 return;
358 } 359 }
359 String source = m_deobfuscator.getSource( sourceTree ); 360 String source = m_deobfuscator.getSource( sourceTree );
diff --git a/src/cuchaz/enigma/mapping/ArgumentEntry.java b/src/cuchaz/enigma/mapping/ArgumentEntry.java
index 27dcc41d..7ed3d328 100644
--- a/src/cuchaz/enigma/mapping/ArgumentEntry.java
+++ b/src/cuchaz/enigma/mapping/ArgumentEntry.java
@@ -18,15 +18,15 @@ public class ArgumentEntry implements Entry, Serializable
18{ 18{
19 private static final long serialVersionUID = 4472172468162696006L; 19 private static final long serialVersionUID = 4472172468162696006L;
20 20
21 private MethodEntry m_methodEntry; 21 private BehaviorEntry m_behaviorEntry;
22 private int m_index; 22 private int m_index;
23 private String m_name; 23 private String m_name;
24 24
25 public ArgumentEntry( MethodEntry methodEntry, int index, String name ) 25 public ArgumentEntry( BehaviorEntry behaviorEntry, int index, String name )
26 { 26 {
27 if( methodEntry == null ) 27 if( behaviorEntry == null )
28 { 28 {
29 throw new IllegalArgumentException( "Method cannot be null!" ); 29 throw new IllegalArgumentException( "Behavior cannot be null!" );
30 } 30 }
31 if( index < 0 ) 31 if( index < 0 )
32 { 32 {
@@ -37,21 +37,28 @@ public class ArgumentEntry implements Entry, Serializable
37 throw new IllegalArgumentException( "Argument name cannot be null!" ); 37 throw new IllegalArgumentException( "Argument name cannot be null!" );
38 } 38 }
39 39
40 m_methodEntry = methodEntry; 40 m_behaviorEntry = behaviorEntry;
41 m_index = index; 41 m_index = index;
42 m_name = name; 42 m_name = name;
43 } 43 }
44 44
45 public ArgumentEntry( ArgumentEntry other ) 45 public ArgumentEntry( ArgumentEntry other )
46 { 46 {
47 m_methodEntry = new MethodEntry( other.m_methodEntry ); 47 m_behaviorEntry = (BehaviorEntry)m_behaviorEntry.cloneToNewClass( getClassEntry() );
48 m_index = other.m_index; 48 m_index = other.m_index;
49 m_name = other.m_name; 49 m_name = other.m_name;
50 } 50 }
51 51
52 public MethodEntry getMethodEntry( ) 52 public ArgumentEntry( ArgumentEntry other, String newClassName )
53 { 53 {
54 return m_methodEntry; 54 m_behaviorEntry = (BehaviorEntry)other.m_behaviorEntry.cloneToNewClass( new ClassEntry( newClassName ) );
55 m_index = other.m_index;
56 m_name = other.m_name;
57 }
58
59 public BehaviorEntry getBehaviorEntry( )
60 {
61 return m_behaviorEntry;
55 } 62 }
56 63
57 public int getIndex( ) 64 public int getIndex( )
@@ -68,29 +75,35 @@ public class ArgumentEntry implements Entry, Serializable
68 @Override 75 @Override
69 public ClassEntry getClassEntry( ) 76 public ClassEntry getClassEntry( )
70 { 77 {
71 return m_methodEntry.getClassEntry(); 78 return m_behaviorEntry.getClassEntry();
72 } 79 }
73 80
74 @Override 81 @Override
75 public String getClassName( ) 82 public String getClassName( )
76 { 83 {
77 return m_methodEntry.getClassName(); 84 return m_behaviorEntry.getClassName();
85 }
86
87 @Override
88 public ArgumentEntry cloneToNewClass( ClassEntry classEntry )
89 {
90 return new ArgumentEntry( this, classEntry.getName() );
78 } 91 }
79 92
80 public String getMethodName( ) 93 public String getMethodName( )
81 { 94 {
82 return m_methodEntry.getName(); 95 return m_behaviorEntry.getName();
83 } 96 }
84 97
85 public String getMethodSignature( ) 98 public String getMethodSignature( )
86 { 99 {
87 return m_methodEntry.getSignature(); 100 return m_behaviorEntry.getSignature();
88 } 101 }
89 102
90 @Override 103 @Override
91 public int hashCode( ) 104 public int hashCode( )
92 { 105 {
93 return Util.combineHashesOrdered( m_methodEntry, Integer.valueOf( m_index ).hashCode(), m_name.hashCode() ); 106 return Util.combineHashesOrdered( m_behaviorEntry, Integer.valueOf( m_index ).hashCode(), m_name.hashCode() );
94 } 107 }
95 108
96 @Override 109 @Override
@@ -105,7 +118,7 @@ public class ArgumentEntry implements Entry, Serializable
105 118
106 public boolean equals( ArgumentEntry other ) 119 public boolean equals( ArgumentEntry other )
107 { 120 {
108 return m_methodEntry.equals( other.m_methodEntry ) 121 return m_behaviorEntry.equals( other.m_behaviorEntry )
109 && m_index == other.m_index 122 && m_index == other.m_index
110 && m_name.equals( other.m_name ); 123 && m_name.equals( other.m_name );
111 } 124 }
@@ -113,6 +126,6 @@ public class ArgumentEntry implements Entry, Serializable
113 @Override 126 @Override
114 public String toString( ) 127 public String toString( )
115 { 128 {
116 return m_methodEntry.toString() + "(" + m_index + ":" + m_name + ")"; 129 return m_behaviorEntry.toString() + "(" + m_index + ":" + m_name + ")";
117 } 130 }
118} 131}
diff --git a/src/cuchaz/enigma/mapping/ClassEntry.java b/src/cuchaz/enigma/mapping/ClassEntry.java
index c6faa506..2c708f2a 100644
--- a/src/cuchaz/enigma/mapping/ClassEntry.java
+++ b/src/cuchaz/enigma/mapping/ClassEntry.java
@@ -44,12 +44,6 @@ public class ClassEntry implements Entry, Serializable
44 } 44 }
45 45
46 @Override 46 @Override
47 public ClassEntry getClassEntry( )
48 {
49 return this;
50 }
51
52 @Override
53 public String getName( ) 47 public String getName( )
54 { 48 {
55 return m_name; 49 return m_name;
@@ -62,6 +56,18 @@ public class ClassEntry implements Entry, Serializable
62 } 56 }
63 57
64 @Override 58 @Override
59 public ClassEntry getClassEntry( )
60 {
61 return this;
62 }
63
64 @Override
65 public ClassEntry cloneToNewClass( ClassEntry classEntry )
66 {
67 return classEntry;
68 }
69
70 @Override
65 public int hashCode( ) 71 public int hashCode( )
66 { 72 {
67 return m_name.hashCode(); 73 return m_name.hashCode();
diff --git a/src/cuchaz/enigma/mapping/ClassMapping.java b/src/cuchaz/enigma/mapping/ClassMapping.java
index 88006cff..b551d71c 100644
--- a/src/cuchaz/enigma/mapping/ClassMapping.java
+++ b/src/cuchaz/enigma/mapping/ClassMapping.java
@@ -139,6 +139,16 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping>
139 return m_fieldsByObf.values(); 139 return m_fieldsByObf.values();
140 } 140 }
141 141
142 public boolean containsObfField( String obfName )
143 {
144 return m_fieldsByObf.containsKey( obfName );
145 }
146
147 public boolean containsDeobfField( String deobfName )
148 {
149 return m_fieldsByDeobf.containsKey( deobfName );
150 }
151
142 public void addFieldMapping( FieldMapping fieldMapping ) 152 public void addFieldMapping( FieldMapping fieldMapping )
143 { 153 {
144 if( m_fieldsByObf.containsKey( fieldMapping.getObfName() ) ) 154 if( m_fieldsByObf.containsKey( fieldMapping.getObfName() ) )
@@ -214,6 +224,16 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping>
214 return m_methodsByObf.values(); 224 return m_methodsByObf.values();
215 } 225 }
216 226
227 public boolean containsObfMethod( String obfName, String obfSignature )
228 {
229 return m_methodsByObf.containsKey( getMethodKey( obfName, obfSignature ) );
230 }
231
232 public boolean containsDeobfMethod( String deobfName, String deobfSignature )
233 {
234 return m_methodsByDeobf.containsKey( getMethodKey( deobfName, deobfSignature ) );
235 }
236
217 public void addMethodMapping( MethodMapping methodMapping ) 237 public void addMethodMapping( MethodMapping methodMapping )
218 { 238 {
219 String obfKey = getMethodKey( methodMapping.getObfName(), methodMapping.getObfSignature() ); 239 String obfKey = getMethodKey( methodMapping.getObfName(), methodMapping.getObfSignature() );
@@ -375,19 +395,9 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping>
375 return false; 395 return false;
376 } 396 }
377 397
378 public boolean containsDeobfField( String name ) 398 public boolean containsArgument( BehaviorEntry obfBehaviorEntry, String name )
379 {
380 return m_fieldsByDeobf.containsKey( name );
381 }
382
383 public boolean containsDeobfMethod( String name, String signature )
384 {
385 return m_methodsByDeobf.containsKey( getMethodKey( name, signature ) );
386 }
387
388 public boolean containsArgument( MethodEntry obfMethodEntry, String name )
389 { 399 {
390 MethodMapping methodMapping = m_methodsByObf.get( getMethodKey( obfMethodEntry.getName(), obfMethodEntry.getSignature() ) ); 400 MethodMapping methodMapping = m_methodsByObf.get( getMethodKey( obfBehaviorEntry.getName(), obfBehaviorEntry.getSignature() ) );
391 if( methodMapping != null ) 401 if( methodMapping != null )
392 { 402 {
393 return methodMapping.containsArgument( name ); 403 return methodMapping.containsArgument( name );
diff --git a/src/cuchaz/enigma/mapping/ConstructorEntry.java b/src/cuchaz/enigma/mapping/ConstructorEntry.java
index ad029e1c..d99d1c35 100644
--- a/src/cuchaz/enigma/mapping/ConstructorEntry.java
+++ b/src/cuchaz/enigma/mapping/ConstructorEntry.java
@@ -43,6 +43,12 @@ public class ConstructorEntry implements BehaviorEntry, Serializable
43 m_signature = other.m_signature; 43 m_signature = other.m_signature;
44 } 44 }
45 45
46 public ConstructorEntry( ConstructorEntry other, String newClassName )
47 {
48 m_classEntry = new ClassEntry( newClassName );
49 m_signature = other.m_signature;
50 }
51
46 @Override 52 @Override
47 public ClassEntry getClassEntry( ) 53 public ClassEntry getClassEntry( )
48 { 54 {
@@ -77,6 +83,12 @@ public class ConstructorEntry implements BehaviorEntry, Serializable
77 } 83 }
78 84
79 @Override 85 @Override
86 public ConstructorEntry cloneToNewClass( ClassEntry classEntry )
87 {
88 return new ConstructorEntry( this, classEntry.getName() );
89 }
90
91 @Override
80 public int hashCode( ) 92 public int hashCode( )
81 { 93 {
82 if( isStatic() ) 94 if( isStatic() )
diff --git a/src/cuchaz/enigma/mapping/Entry.java b/src/cuchaz/enigma/mapping/Entry.java
index e1591f02..8524834c 100644
--- a/src/cuchaz/enigma/mapping/Entry.java
+++ b/src/cuchaz/enigma/mapping/Entry.java
@@ -15,4 +15,5 @@ public interface Entry
15 String getName( ); 15 String getName( );
16 String getClassName( ); 16 String getClassName( );
17 ClassEntry getClassEntry( ); 17 ClassEntry getClassEntry( );
18 Entry cloneToNewClass( ClassEntry classEntry );
18} 19}
diff --git a/src/cuchaz/enigma/mapping/FieldEntry.java b/src/cuchaz/enigma/mapping/FieldEntry.java
index 435490bd..626af576 100644
--- a/src/cuchaz/enigma/mapping/FieldEntry.java
+++ b/src/cuchaz/enigma/mapping/FieldEntry.java
@@ -68,6 +68,12 @@ public class FieldEntry implements Entry, Serializable
68 } 68 }
69 69
70 @Override 70 @Override
71 public FieldEntry cloneToNewClass( ClassEntry classEntry )
72 {
73 return new FieldEntry( this, classEntry.getName() );
74 }
75
76 @Override
71 public int hashCode( ) 77 public int hashCode( )
72 { 78 {
73 return Util.combineHashesOrdered( m_classEntry, m_name ); 79 return Util.combineHashesOrdered( m_classEntry, m_name );
diff --git a/src/cuchaz/enigma/mapping/Mappings.java b/src/cuchaz/enigma/mapping/Mappings.java
index f855f580..0b4e7f3c 100644
--- a/src/cuchaz/enigma/mapping/Mappings.java
+++ b/src/cuchaz/enigma/mapping/Mappings.java
@@ -253,12 +253,12 @@ public class Mappings implements Serializable
253 return false; 253 return false;
254 } 254 }
255 255
256 public boolean containsArgument( MethodEntry obfMethodEntry, String name ) 256 public boolean containsArgument( BehaviorEntry obfBehaviorEntry, String name )
257 { 257 {
258 ClassMapping classMapping = m_classesByObf.get( obfMethodEntry.getClassName() ); 258 ClassMapping classMapping = m_classesByObf.get( obfBehaviorEntry.getClassName() );
259 if( classMapping != null ) 259 if( classMapping != null )
260 { 260 {
261 return classMapping.containsArgument( obfMethodEntry, name ); 261 return classMapping.containsArgument( obfBehaviorEntry, name );
262 } 262 }
263 return false; 263 return false;
264 } 264 }
diff --git a/src/cuchaz/enigma/mapping/MappingsRenamer.java b/src/cuchaz/enigma/mapping/MappingsRenamer.java
index 49e7b5fd..dcceefbd 100644
--- a/src/cuchaz/enigma/mapping/MappingsRenamer.java
+++ b/src/cuchaz/enigma/mapping/MappingsRenamer.java
@@ -79,7 +79,7 @@ public class MappingsRenamer
79 { 79 {
80 String deobfSignature = getTranslator( TranslationDirection.Deobfuscating ).translateSignature( obf.getSignature() ); 80 String deobfSignature = getTranslator( TranslationDirection.Deobfuscating ).translateSignature( obf.getSignature() );
81 MethodEntry targetEntry = new MethodEntry( entry.getClassEntry(), deobfName, deobfSignature ); 81 MethodEntry targetEntry = new MethodEntry( entry.getClassEntry(), deobfName, deobfSignature );
82 if( m_mappings.containsDeobfMethod( entry.getClassEntry(), deobfName, entry.getSignature() ) || m_index.containsObfMethod( targetEntry ) ) 82 if( m_mappings.containsDeobfMethod( entry.getClassEntry(), deobfName, entry.getSignature() ) || m_index.containsObfBehavior( targetEntry ) )
83 { 83 {
84 String deobfClassName = getTranslator( TranslationDirection.Deobfuscating ).translateClass( entry.getClassName() ); 84 String deobfClassName = getTranslator( TranslationDirection.Deobfuscating ).translateClass( entry.getClassName() );
85 throw new IllegalNameException( deobfName, "There is already a method with that name and signature in class " + deobfClassName ); 85 throw new IllegalNameException( deobfName, "There is already a method with that name and signature in class " + deobfClassName );
@@ -96,7 +96,7 @@ public class MappingsRenamer
96 { 96 {
97 deobfName = NameValidator.validateMethodName( deobfName ); 97 deobfName = NameValidator.validateMethodName( deobfName );
98 MethodEntry targetEntry = new MethodEntry( obf.getClassEntry(), deobfName, obf.getSignature() ); 98 MethodEntry targetEntry = new MethodEntry( obf.getClassEntry(), deobfName, obf.getSignature() );
99 if( m_mappings.containsDeobfMethod( obf.getClassEntry(), deobfName, obf.getSignature() ) || m_index.containsObfMethod( targetEntry ) ) 99 if( m_mappings.containsDeobfMethod( obf.getClassEntry(), deobfName, obf.getSignature() ) || m_index.containsObfBehavior( targetEntry ) )
100 { 100 {
101 String deobfClassName = getTranslator( TranslationDirection.Deobfuscating ).translateClass( obf.getClassName() ); 101 String deobfClassName = getTranslator( TranslationDirection.Deobfuscating ).translateClass( obf.getClassName() );
102 throw new IllegalNameException( deobfName, "There is already a method with that name and signature in class " + deobfClassName ); 102 throw new IllegalNameException( deobfName, "There is already a method with that name and signature in class " + deobfClassName );
@@ -110,7 +110,7 @@ public class MappingsRenamer
110 { 110 {
111 deobfName = NameValidator.validateArgumentName( deobfName ); 111 deobfName = NameValidator.validateArgumentName( deobfName );
112 // NOTE: don't need to check arguments for name collisions with names determined by Procyon 112 // NOTE: don't need to check arguments for name collisions with names determined by Procyon
113 if( m_mappings.containsArgument( obf.getMethodEntry(), deobfName ) ) 113 if( m_mappings.containsArgument( obf.getBehaviorEntry(), deobfName ) )
114 { 114 {
115 throw new IllegalNameException( deobfName, "There is already an argument with that name" ); 115 throw new IllegalNameException( deobfName, "There is already an argument with that name" );
116 } 116 }
@@ -119,6 +119,32 @@ public class MappingsRenamer
119 classMapping.setArgumentName( obf.getMethodName(), obf.getMethodSignature(), obf.getIndex(), deobfName ); 119 classMapping.setArgumentName( obf.getMethodName(), obf.getMethodSignature(), obf.getIndex(), deobfName );
120 } 120 }
121 121
122 public boolean moveFieldToObfClass( ClassMapping classMapping, FieldMapping fieldMapping, ClassEntry obfClass )
123 {
124 classMapping.removeFieldMapping( fieldMapping );
125 ClassMapping targetClassMapping = getOrCreateClassMapping( obfClass );
126 if( !targetClassMapping.containsObfField( fieldMapping.getObfName() )
127 && !targetClassMapping.containsDeobfField( fieldMapping.getDeobfName() ) )
128 {
129 targetClassMapping.addFieldMapping( fieldMapping );
130 return true;
131 }
132 return false;
133 }
134
135 public boolean moveMethodToObfClass( ClassMapping classMapping, MethodMapping methodMapping, ClassEntry obfClass )
136 {
137 classMapping.removeMethodMapping( methodMapping );
138 ClassMapping targetClassMapping = getOrCreateClassMapping( obfClass );
139 if( !targetClassMapping.containsObfMethod( methodMapping.getObfName(), methodMapping.getObfSignature() )
140 && !targetClassMapping.containsDeobfMethod( methodMapping.getDeobfName(), methodMapping.getObfSignature() ) )
141 {
142 targetClassMapping.addMethodMapping( methodMapping );
143 return true;
144 }
145 return false;
146 }
147
122 public void write( OutputStream out ) 148 public void write( OutputStream out )
123 throws IOException 149 throws IOException
124 { 150 {
diff --git a/src/cuchaz/enigma/mapping/MethodEntry.java b/src/cuchaz/enigma/mapping/MethodEntry.java
index a311e636..8adbfe9c 100644
--- a/src/cuchaz/enigma/mapping/MethodEntry.java
+++ b/src/cuchaz/enigma/mapping/MethodEntry.java
@@ -81,6 +81,12 @@ public class MethodEntry implements BehaviorEntry, Serializable
81 } 81 }
82 82
83 @Override 83 @Override
84 public MethodEntry cloneToNewClass( ClassEntry classEntry )
85 {
86 return new MethodEntry( this, classEntry.getName() );
87 }
88
89 @Override
84 public int hashCode( ) 90 public int hashCode( )
85 { 91 {
86 return Util.combineHashesOrdered( m_classEntry, m_name, m_signature ); 92 return Util.combineHashesOrdered( m_classEntry, m_name, m_signature );
diff --git a/src/cuchaz/enigma/mapping/Translator.java b/src/cuchaz/enigma/mapping/Translator.java
index b438e08d..7904ef53 100644
--- a/src/cuchaz/enigma/mapping/Translator.java
+++ b/src/cuchaz/enigma/mapping/Translator.java
@@ -271,7 +271,7 @@ public class Translator
271 name = in.getName(); 271 name = in.getName();
272 } 272 }
273 return new ArgumentEntry( 273 return new ArgumentEntry(
274 translateEntry( in.getMethodEntry() ), 274 translateEntry( in.getBehaviorEntry() ),
275 in.getIndex(), 275 in.getIndex(),
276 name 276 name
277 ); 277 );