summaryrefslogtreecommitdiff
path: root/src/cuchaz/enigma/mapping
diff options
context:
space:
mode:
authorGravatar jeff2015-01-13 23:25:04 -0500
committerGravatar jeff2015-01-13 23:25:04 -0500
commit959cb5fd4f9586ec3bd265b452fe25fe1db82e3f (patch)
treebdd8a2c52c2fe053ba3460614bde8542e5378dbe /src/cuchaz/enigma/mapping
parentgot rid of gradle in favor of ivy+ssjb (diff)
downloadenigma-fork-959cb5fd4f9586ec3bd265b452fe25fe1db82e3f.tar.gz
enigma-fork-959cb5fd4f9586ec3bd265b452fe25fe1db82e3f.tar.xz
enigma-fork-959cb5fd4f9586ec3bd265b452fe25fe1db82e3f.zip
source format change
don't hate me too much if you were planning a big merge. =P
Diffstat (limited to 'src/cuchaz/enigma/mapping')
-rw-r--r--src/cuchaz/enigma/mapping/ArgumentEntry.java85
-rw-r--r--src/cuchaz/enigma/mapping/ArgumentMapping.java26
-rw-r--r--src/cuchaz/enigma/mapping/BehaviorEntry.java3
-rw-r--r--src/cuchaz/enigma/mapping/BehaviorEntryFactory.java71
-rw-r--r--src/cuchaz/enigma/mapping/ClassEntry.java116
-rw-r--r--src/cuchaz/enigma/mapping/ClassMapping.java520
-rw-r--r--src/cuchaz/enigma/mapping/ConstructorEntry.java99
-rw-r--r--src/cuchaz/enigma/mapping/Entry.java11
-rw-r--r--src/cuchaz/enigma/mapping/EntryPair.java9
-rw-r--r--src/cuchaz/enigma/mapping/FieldEntry.java65
-rw-r--r--src/cuchaz/enigma/mapping/FieldMapping.java30
-rw-r--r--src/cuchaz/enigma/mapping/IllegalNameException.java29
-rw-r--r--src/cuchaz/enigma/mapping/MappingParseException.java10
-rw-r--r--src/cuchaz/enigma/mapping/Mappings.java230
-rw-r--r--src/cuchaz/enigma/mapping/MappingsReader.java218
-rw-r--r--src/cuchaz/enigma/mapping/MappingsRenamer.java308
-rw-r--r--src/cuchaz/enigma/mapping/MappingsWriter.java110
-rw-r--r--src/cuchaz/enigma/mapping/MethodEntry.java79
-rw-r--r--src/cuchaz/enigma/mapping/MethodMapping.java168
-rw-r--r--src/cuchaz/enigma/mapping/NameValidator.java79
-rw-r--r--src/cuchaz/enigma/mapping/SignatureUpdater.java88
-rw-r--r--src/cuchaz/enigma/mapping/TranslationDirection.java21
-rw-r--r--src/cuchaz/enigma/mapping/Translator.java280
23 files changed, 1050 insertions, 1605 deletions
diff --git a/src/cuchaz/enigma/mapping/ArgumentEntry.java b/src/cuchaz/enigma/mapping/ArgumentEntry.java
index 7ed3d32..2c15f4e 100644
--- a/src/cuchaz/enigma/mapping/ArgumentEntry.java
+++ b/src/cuchaz/enigma/mapping/ArgumentEntry.java
@@ -14,27 +14,23 @@ import java.io.Serializable;
14 14
15import cuchaz.enigma.Util; 15import cuchaz.enigma.Util;
16 16
17public class ArgumentEntry implements Entry, Serializable 17public 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 BehaviorEntry m_behaviorEntry; 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( BehaviorEntry behaviorEntry, int index, String name ) 25 public ArgumentEntry(BehaviorEntry behaviorEntry, int index, String name) {
26 { 26 if (behaviorEntry == null) {
27 if( behaviorEntry == null ) 27 throw new IllegalArgumentException("Behavior cannot be null!");
28 {
29 throw new IllegalArgumentException( "Behavior cannot be null!" );
30 } 28 }
31 if( index < 0 ) 29 if (index < 0) {
32 { 30 throw new IllegalArgumentException("Index must be non-negative!");
33 throw new IllegalArgumentException( "Index must be non-negative!" );
34 } 31 }
35 if( name == null ) 32 if (name == null) {
36 { 33 throw new IllegalArgumentException("Argument name cannot be null!");
37 throw new IllegalArgumentException( "Argument name cannot be null!" );
38 } 34 }
39 35
40 m_behaviorEntry = behaviorEntry; 36 m_behaviorEntry = behaviorEntry;
@@ -42,90 +38,79 @@ public class ArgumentEntry implements Entry, Serializable
42 m_name = name; 38 m_name = name;
43 } 39 }
44 40
45 public ArgumentEntry( ArgumentEntry other ) 41 public ArgumentEntry(ArgumentEntry other) {
46 { 42 m_behaviorEntry = (BehaviorEntry)m_behaviorEntry.cloneToNewClass(getClassEntry());
47 m_behaviorEntry = (BehaviorEntry)m_behaviorEntry.cloneToNewClass( getClassEntry() );
48 m_index = other.m_index; 43 m_index = other.m_index;
49 m_name = other.m_name; 44 m_name = other.m_name;
50 } 45 }
51 46
52 public ArgumentEntry( ArgumentEntry other, String newClassName ) 47 public ArgumentEntry(ArgumentEntry other, String newClassName) {
53 { 48 m_behaviorEntry = (BehaviorEntry)other.m_behaviorEntry.cloneToNewClass(new ClassEntry(newClassName));
54 m_behaviorEntry = (BehaviorEntry)other.m_behaviorEntry.cloneToNewClass( new ClassEntry( newClassName ) );
55 m_index = other.m_index; 49 m_index = other.m_index;
56 m_name = other.m_name; 50 m_name = other.m_name;
57 } 51 }
58 52
59 public BehaviorEntry getBehaviorEntry( ) 53 public BehaviorEntry getBehaviorEntry() {
60 {
61 return m_behaviorEntry; 54 return m_behaviorEntry;
62 } 55 }
63 56
64 public int getIndex( ) 57 public int getIndex() {
65 {
66 return m_index; 58 return m_index;
67 } 59 }
68 60
69 @Override 61 @Override
70 public String getName( ) 62 public String getName() {
71 {
72 return m_name; 63 return m_name;
73 } 64 }
74 65
75 @Override 66 @Override
76 public ClassEntry getClassEntry( ) 67 public ClassEntry getClassEntry() {
77 {
78 return m_behaviorEntry.getClassEntry(); 68 return m_behaviorEntry.getClassEntry();
79 } 69 }
80 70
81 @Override 71 @Override
82 public String getClassName( ) 72 public String getClassName() {
83 {
84 return m_behaviorEntry.getClassName(); 73 return m_behaviorEntry.getClassName();
85 } 74 }
86 75
87 @Override 76 @Override
88 public ArgumentEntry cloneToNewClass( ClassEntry classEntry ) 77 public ArgumentEntry cloneToNewClass(ClassEntry classEntry) {
89 { 78 return new ArgumentEntry(this, classEntry.getName());
90 return new ArgumentEntry( this, classEntry.getName() );
91 } 79 }
92 80
93 public String getMethodName( ) 81 public String getMethodName() {
94 {
95 return m_behaviorEntry.getName(); 82 return m_behaviorEntry.getName();
96 } 83 }
97 84
98 public String getMethodSignature( ) 85 public String getMethodSignature() {
99 {
100 return m_behaviorEntry.getSignature(); 86 return m_behaviorEntry.getSignature();
101 } 87 }
102 88
103 @Override 89 @Override
104 public int hashCode( ) 90 public int hashCode() {
105 { 91 return Util.combineHashesOrdered(
106 return Util.combineHashesOrdered( m_behaviorEntry, Integer.valueOf( m_index ).hashCode(), m_name.hashCode() ); 92 m_behaviorEntry,
93 Integer.valueOf(m_index).hashCode(),
94 m_name.hashCode()
95 );
107 } 96 }
108 97
109 @Override 98 @Override
110 public boolean equals( Object other ) 99 public boolean equals(Object other) {
111 { 100 if (other instanceof ArgumentEntry) {
112 if( other instanceof ArgumentEntry ) 101 return equals((ArgumentEntry)other);
113 {
114 return equals( (ArgumentEntry)other );
115 } 102 }
116 return false; 103 return false;
117 } 104 }
118 105
119 public boolean equals( ArgumentEntry other ) 106 public boolean equals(ArgumentEntry other) {
120 { 107 return m_behaviorEntry.equals(other.m_behaviorEntry)
121 return m_behaviorEntry.equals( other.m_behaviorEntry )
122 && m_index == other.m_index 108 && m_index == other.m_index
123 && m_name.equals( other.m_name ); 109 && m_name.equals(other.m_name);
124 } 110 }
125 111
126 @Override 112 @Override
127 public String toString( ) 113 public String toString() {
128 {
129 return m_behaviorEntry.toString() + "(" + m_index + ":" + m_name + ")"; 114 return m_behaviorEntry.toString() + "(" + m_index + ":" + m_name + ")";
130 } 115 }
131} 116}
diff --git a/src/cuchaz/enigma/mapping/ArgumentMapping.java b/src/cuchaz/enigma/mapping/ArgumentMapping.java
index 168306a..f4d8e77 100644
--- a/src/cuchaz/enigma/mapping/ArgumentMapping.java
+++ b/src/cuchaz/enigma/mapping/ArgumentMapping.java
@@ -12,37 +12,33 @@ package cuchaz.enigma.mapping;
12 12
13import java.io.Serializable; 13import java.io.Serializable;
14 14
15public class ArgumentMapping implements Serializable, Comparable<ArgumentMapping> 15public class ArgumentMapping implements Serializable, Comparable<ArgumentMapping> {
16{ 16
17 private static final long serialVersionUID = 8610742471440861315L; 17 private static final long serialVersionUID = 8610742471440861315L;
18 18
19 private int m_index; 19 private int m_index;
20 private String m_name; 20 private String m_name;
21 21
22 // NOTE: this argument order is important for the MethodReader/MethodWriter 22 // NOTE: this argument order is important for the MethodReader/MethodWriter
23 public ArgumentMapping( int index, String name ) 23 public ArgumentMapping(int index, String name) {
24 {
25 m_index = index; 24 m_index = index;
26 m_name = NameValidator.validateArgumentName( name ); 25 m_name = NameValidator.validateArgumentName(name);
27 } 26 }
28 27
29 public int getIndex( ) 28 public int getIndex() {
30 {
31 return m_index; 29 return m_index;
32 } 30 }
33 31
34 public String getName( ) 32 public String getName() {
35 {
36 return m_name; 33 return m_name;
37 } 34 }
38 public void setName( String val ) 35
39 { 36 public void setName(String val) {
40 m_name = NameValidator.validateArgumentName( val ); 37 m_name = NameValidator.validateArgumentName(val);
41 } 38 }
42 39
43 @Override 40 @Override
44 public int compareTo( ArgumentMapping other ) 41 public int compareTo(ArgumentMapping other) {
45 { 42 return Integer.compare(m_index, other.m_index);
46 return Integer.compare( m_index, other.m_index );
47 } 43 }
48} 44}
diff --git a/src/cuchaz/enigma/mapping/BehaviorEntry.java b/src/cuchaz/enigma/mapping/BehaviorEntry.java
index 8fc4eaf..f4200b8 100644
--- a/src/cuchaz/enigma/mapping/BehaviorEntry.java
+++ b/src/cuchaz/enigma/mapping/BehaviorEntry.java
@@ -10,7 +10,6 @@
10 ******************************************************************************/ 10 ******************************************************************************/
11package cuchaz.enigma.mapping; 11package cuchaz.enigma.mapping;
12 12
13public interface BehaviorEntry extends Entry 13public interface BehaviorEntry extends Entry {
14{
15 String getSignature(); 14 String getSignature();
16} 15}
diff --git a/src/cuchaz/enigma/mapping/BehaviorEntryFactory.java b/src/cuchaz/enigma/mapping/BehaviorEntryFactory.java
index d3cfb93..386faeb 100644
--- a/src/cuchaz/enigma/mapping/BehaviorEntryFactory.java
+++ b/src/cuchaz/enigma/mapping/BehaviorEntryFactory.java
@@ -15,62 +15,43 @@ import javassist.CtConstructor;
15import javassist.CtMethod; 15import javassist.CtMethod;
16import javassist.bytecode.Descriptor; 16import javassist.bytecode.Descriptor;
17 17
18 18public class BehaviorEntryFactory {
19public class BehaviorEntryFactory 19
20{ 20 public static BehaviorEntry create(String className, String name, String signature) {
21 public static BehaviorEntry create( String className, String name, String signature ) 21 return create(new ClassEntry(className), name, signature);
22 {
23 return create( new ClassEntry( className ), name, signature );
24 } 22 }
25 23
26 public static BehaviorEntry create( ClassEntry classEntry, String name, String signature ) 24 public static BehaviorEntry create(ClassEntry classEntry, String name, String signature) {
27 { 25 if (name.equals("<init>")) {
28 if( name.equals( "<init>" ) ) 26 return new ConstructorEntry(classEntry, signature);
29 { 27 } else if (name.equals("<clinit>")) {
30 return new ConstructorEntry( classEntry, signature ); 28 return new ConstructorEntry(classEntry);
31 } 29 } else {
32 else if( name.equals( "<clinit>" ) ) 30 return new MethodEntry(classEntry, name, signature);
33 {
34 return new ConstructorEntry( classEntry );
35 }
36 else
37 {
38 return new MethodEntry( classEntry, name, signature );
39 } 31 }
40 } 32 }
41 33
42 public static BehaviorEntry create( CtBehavior behavior ) 34 public static BehaviorEntry create(CtBehavior behavior) {
43 { 35 String className = Descriptor.toJvmName(behavior.getDeclaringClass().getName());
44 String className = Descriptor.toJvmName( behavior.getDeclaringClass().getName() ); 36 if (behavior instanceof CtMethod) {
45 if( behavior instanceof CtMethod ) 37 return create(className, behavior.getName(), behavior.getSignature());
46 { 38 } else if (behavior instanceof CtConstructor) {
47 return create( className, behavior.getName(), behavior.getSignature() );
48 }
49 else if( behavior instanceof CtConstructor )
50 {
51 CtConstructor constructor = (CtConstructor)behavior; 39 CtConstructor constructor = (CtConstructor)behavior;
52 if( constructor.isClassInitializer() ) 40 if (constructor.isClassInitializer()) {
53 { 41 return create(className, "<clinit>", null);
54 return create( className, "<clinit>", null ); 42 } else {
55 } 43 return create(className, "<init>", constructor.getSignature());
56 else
57 {
58 return create( className, "<init>", constructor.getSignature() );
59 } 44 }
60 } 45 } else {
61 else 46 throw new IllegalArgumentException("Unable to create BehaviorEntry from " + behavior);
62 {
63 throw new IllegalArgumentException( "Unable to create BehaviorEntry from " + behavior );
64 } 47 }
65 } 48 }
66 49
67 public static BehaviorEntry createObf( ClassEntry classEntry, MethodMapping methodMapping ) 50 public static BehaviorEntry createObf(ClassEntry classEntry, MethodMapping methodMapping) {
68 { 51 return create(classEntry, methodMapping.getObfName(), methodMapping.getObfSignature());
69 return create( classEntry, methodMapping.getObfName(), methodMapping.getObfSignature() );
70 } 52 }
71 53
72 public static BehaviorEntry createDeobf( ClassEntry classEntry, MethodMapping methodMapping ) 54 public static BehaviorEntry createDeobf(ClassEntry classEntry, MethodMapping methodMapping) {
73 { 55 return create(classEntry, methodMapping.getDeobfName(), methodMapping.getObfSignature());
74 return create( classEntry, methodMapping.getDeobfName(), methodMapping.getObfSignature() );
75 } 56 }
76} 57}
diff --git a/src/cuchaz/enigma/mapping/ClassEntry.java b/src/cuchaz/enigma/mapping/ClassEntry.java
index 2c708f2..cf41001 100644
--- a/src/cuchaz/enigma/mapping/ClassEntry.java
+++ b/src/cuchaz/enigma/mapping/ClassEntry.java
@@ -12,137 +12,111 @@ package cuchaz.enigma.mapping;
12 12
13import java.io.Serializable; 13import java.io.Serializable;
14 14
15 15public class ClassEntry implements Entry, Serializable {
16public class ClassEntry implements Entry, Serializable 16
17{
18 private static final long serialVersionUID = 4235460580973955811L; 17 private static final long serialVersionUID = 4235460580973955811L;
19 18
20 private String m_name; 19 private String m_name;
21 20
22 public ClassEntry( String className ) 21 public ClassEntry(String className) {
23 { 22 if (className == null) {
24 if( className == null ) 23 throw new IllegalArgumentException("Class name cannot be null!");
25 {
26 throw new IllegalArgumentException( "Class name cannot be null!" );
27 } 24 }
28 if( className.indexOf( '.' ) >= 0 ) 25 if (className.indexOf('.') >= 0) {
29 { 26 throw new IllegalArgumentException("Class name must be in JVM format. ie, path/to/package/class$inner : " + className);
30 throw new IllegalArgumentException( "Class name must be in JVM format. ie, path/to/package/class$inner : " + className );
31 } 27 }
32 28
33 m_name = className; 29 m_name = className;
34 30
35 if( isInnerClass() && getInnerClassName().indexOf( '/' ) >= 0 ) 31 if (isInnerClass() && getInnerClassName().indexOf('/') >= 0) {
36 { 32 throw new IllegalArgumentException("Inner class must not have a package: " + className);
37 throw new IllegalArgumentException( "Inner class must not have a package: " + className );
38 } 33 }
39 } 34 }
40 35
41 public ClassEntry( ClassEntry other ) 36 public ClassEntry(ClassEntry other) {
42 {
43 m_name = other.m_name; 37 m_name = other.m_name;
44 } 38 }
45 39
46 @Override 40 @Override
47 public String getName( ) 41 public String getName() {
48 {
49 return m_name; 42 return m_name;
50 } 43 }
51 44
52 @Override 45 @Override
53 public String getClassName( ) 46 public String getClassName() {
54 {
55 return m_name; 47 return m_name;
56 } 48 }
57 49
58 @Override 50 @Override
59 public ClassEntry getClassEntry( ) 51 public ClassEntry getClassEntry() {
60 {
61 return this; 52 return this;
62 } 53 }
63 54
64 @Override 55 @Override
65 public ClassEntry cloneToNewClass( ClassEntry classEntry ) 56 public ClassEntry cloneToNewClass(ClassEntry classEntry) {
66 {
67 return classEntry; 57 return classEntry;
68 } 58 }
69 59
70 @Override 60 @Override
71 public int hashCode( ) 61 public int hashCode() {
72 {
73 return m_name.hashCode(); 62 return m_name.hashCode();
74 } 63 }
75 64
76 @Override 65 @Override
77 public boolean equals( Object other ) 66 public boolean equals(Object other) {
78 { 67 if (other instanceof ClassEntry) {
79 if( other instanceof ClassEntry ) 68 return equals((ClassEntry)other);
80 {
81 return equals( (ClassEntry)other );
82 } 69 }
83 return false; 70 return false;
84 } 71 }
85 72
86 public boolean equals( ClassEntry other ) 73 public boolean equals(ClassEntry other) {
87 { 74 return m_name.equals(other.m_name);
88 return m_name.equals( other.m_name );
89 } 75 }
90 76
91 @Override 77 @Override
92 public String toString( ) 78 public String toString() {
93 {
94 return m_name; 79 return m_name;
95 } 80 }
96 81
97 public boolean isInnerClass( ) 82 public boolean isInnerClass() {
98 { 83 return m_name.lastIndexOf('$') >= 0;
99 return m_name.lastIndexOf( '$' ) >= 0;
100 } 84 }
101 85
102 public String getOuterClassName( ) 86 public String getOuterClassName() {
103 { 87 if (isInnerClass()) {
104 if( isInnerClass() ) 88 return m_name.substring(0, m_name.lastIndexOf('$'));
105 {
106 return m_name.substring( 0, m_name.lastIndexOf( '$' ) );
107 } 89 }
108 return m_name; 90 return m_name;
109 } 91 }
110 92
111 public String getInnerClassName( ) 93 public String getInnerClassName() {
112 { 94 if (!isInnerClass()) {
113 if( !isInnerClass() ) 95 throw new Error("This is not an inner class!");
114 {
115 throw new Error( "This is not an inner class!" );
116 } 96 }
117 return m_name.substring( m_name.lastIndexOf( '$' ) + 1 ); 97 return m_name.substring(m_name.lastIndexOf('$') + 1);
118 } 98 }
119 99
120 public ClassEntry getOuterClassEntry( ) 100 public ClassEntry getOuterClassEntry() {
121 { 101 return new ClassEntry(getOuterClassName());
122 return new ClassEntry( getOuterClassName() );
123 } 102 }
124 103
125 public boolean isInDefaultPackage( ) 104 public boolean isInDefaultPackage() {
126 { 105 return m_name.indexOf('/') < 0;
127 return m_name.indexOf( '/' ) < 0;
128 } 106 }
129 107
130 public String getPackageName( ) 108 public String getPackageName() {
131 { 109 int pos = m_name.lastIndexOf('/');
132 int pos = m_name.lastIndexOf( '/' ); 110 if (pos > 0) {
133 if( pos > 0 ) 111 return m_name.substring(0, pos);
134 {
135 return m_name.substring( 0, pos );
136 } 112 }
137 return null; 113 return null;
138 } 114 }
139 115
140 public String getSimpleName( ) 116 public String getSimpleName() {
141 { 117 int pos = m_name.lastIndexOf('/');
142 int pos = m_name.lastIndexOf( '/' ); 118 if (pos > 0) {
143 if( pos > 0 ) 119 return m_name.substring(pos + 1);
144 {
145 return m_name.substring( pos + 1 );
146 } 120 }
147 return m_name; 121 return m_name;
148 } 122 }
diff --git a/src/cuchaz/enigma/mapping/ClassMapping.java b/src/cuchaz/enigma/mapping/ClassMapping.java
index e084d4d..dbb8717 100644
--- a/src/cuchaz/enigma/mapping/ClassMapping.java
+++ b/src/cuchaz/enigma/mapping/ClassMapping.java
@@ -16,8 +16,8 @@ import java.util.Map;
16 16
17import com.google.common.collect.Maps; 17import com.google.common.collect.Maps;
18 18
19public class ClassMapping implements Serializable, Comparable<ClassMapping> 19public class ClassMapping implements Serializable, Comparable<ClassMapping> {
20{ 20
21 private static final long serialVersionUID = -5148491146902340107L; 21 private static final long serialVersionUID = -5148491146902340107L;
22 22
23 private String m_obfName; 23 private String m_obfName;
@@ -29,15 +29,13 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping>
29 private Map<String,MethodMapping> m_methodsByObf; 29 private Map<String,MethodMapping> m_methodsByObf;
30 private Map<String,MethodMapping> m_methodsByDeobf; 30 private Map<String,MethodMapping> m_methodsByDeobf;
31 31
32 public ClassMapping( String obfName ) 32 public ClassMapping(String obfName) {
33 { 33 this(obfName, null);
34 this( obfName, null );
35 } 34 }
36 35
37 public ClassMapping( String obfName, String deobfName ) 36 public ClassMapping(String obfName, String deobfName) {
38 {
39 m_obfName = obfName; 37 m_obfName = obfName;
40 m_deobfName = NameValidator.validateClassName( deobfName, false ); 38 m_deobfName = NameValidator.validateClassName(deobfName, false);
41 m_innerClassesByObf = Maps.newHashMap(); 39 m_innerClassesByObf = Maps.newHashMap();
42 m_innerClassesByDeobf = Maps.newHashMap(); 40 m_innerClassesByDeobf = Maps.newHashMap();
43 m_fieldsByObf = Maps.newHashMap(); 41 m_fieldsByObf = Maps.newHashMap();
@@ -45,439 +43,363 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping>
45 m_methodsByObf = Maps.newHashMap(); 43 m_methodsByObf = Maps.newHashMap();
46 m_methodsByDeobf = Maps.newHashMap(); 44 m_methodsByDeobf = Maps.newHashMap();
47 } 45 }
48 46
49 public String getObfName( ) 47 public String getObfName() {
50 {
51 return m_obfName; 48 return m_obfName;
52 } 49 }
53 50
54 public String getDeobfName( ) 51 public String getDeobfName() {
55 {
56 return m_deobfName; 52 return m_deobfName;
57 } 53 }
58 public void setDeobfName( String val ) 54
59 { 55 public void setDeobfName(String val) {
60 m_deobfName = NameValidator.validateClassName( val, false ); 56 m_deobfName = NameValidator.validateClassName(val, false);
61 } 57 }
62 58
63 //// INNER CLASSES //////// 59 //// INNER CLASSES ////////
64 60
65 public Iterable<ClassMapping> innerClasses( ) 61 public Iterable<ClassMapping> innerClasses() {
66 { 62 assert (m_innerClassesByObf.size() >= m_innerClassesByDeobf.size());
67 assert( m_innerClassesByObf.size() >= m_innerClassesByDeobf.size() );
68 return m_innerClassesByObf.values(); 63 return m_innerClassesByObf.values();
69 } 64 }
70 65
71 public void addInnerClassMapping( ClassMapping classMapping ) 66 public void addInnerClassMapping(ClassMapping classMapping) {
72 { 67 assert (isSimpleClassName(classMapping.getObfName()));
73 assert( isSimpleClassName( classMapping.getObfName() ) ); 68 boolean obfWasAdded = m_innerClassesByObf.put(classMapping.getObfName(), classMapping) == null;
74 boolean obfWasAdded = m_innerClassesByObf.put( classMapping.getObfName(), classMapping ) == null; 69 assert (obfWasAdded);
75 assert( obfWasAdded ); 70 if (classMapping.getDeobfName() != null) {
76 if( classMapping.getDeobfName() != null ) 71 assert (isSimpleClassName(classMapping.getDeobfName()));
77 { 72 boolean deobfWasAdded = m_innerClassesByDeobf.put(classMapping.getDeobfName(), classMapping) == null;
78 assert( isSimpleClassName( classMapping.getDeobfName() ) ); 73 assert (deobfWasAdded);
79 boolean deobfWasAdded = m_innerClassesByDeobf.put( classMapping.getDeobfName(), classMapping ) == null;
80 assert( deobfWasAdded );
81 } 74 }
82 } 75 }
83 76
84 public void removeInnerClassMapping( ClassMapping classMapping ) 77 public void removeInnerClassMapping(ClassMapping classMapping) {
85 { 78 boolean obfWasRemoved = m_innerClassesByObf.remove(classMapping.getObfName()) != null;
86 boolean obfWasRemoved = m_innerClassesByObf.remove( classMapping.getObfName() ) != null; 79 assert (obfWasRemoved);
87 assert( obfWasRemoved ); 80 if (classMapping.getDeobfName() != null) {
88 if( classMapping.getDeobfName() != null ) 81 boolean deobfWasRemoved = m_innerClassesByDeobf.remove(classMapping.getDeobfName()) != null;
89 { 82 assert (deobfWasRemoved);
90 boolean deobfWasRemoved = m_innerClassesByDeobf.remove( classMapping.getDeobfName() ) != null;
91 assert( deobfWasRemoved );
92 } 83 }
93 } 84 }
94 85
95 public ClassMapping getOrCreateInnerClass( String obfName ) 86 public ClassMapping getOrCreateInnerClass(String obfName) {
96 { 87 assert (isSimpleClassName(obfName));
97 assert( isSimpleClassName( obfName ) ); 88 ClassMapping classMapping = m_innerClassesByObf.get(obfName);
98 ClassMapping classMapping = m_innerClassesByObf.get( obfName ); 89 if (classMapping == null) {
99 if( classMapping == null ) 90 classMapping = new ClassMapping(obfName);
100 { 91 boolean wasAdded = m_innerClassesByObf.put(obfName, classMapping) == null;
101 classMapping = new ClassMapping( obfName ); 92 assert (wasAdded);
102 boolean wasAdded = m_innerClassesByObf.put( obfName, classMapping ) == null;
103 assert( wasAdded );
104 } 93 }
105 return classMapping; 94 return classMapping;
106 } 95 }
107 96
108 public ClassMapping getInnerClassByObf( String obfName ) 97 public ClassMapping getInnerClassByObf(String obfName) {
109 { 98 assert (isSimpleClassName(obfName));
110 assert( isSimpleClassName( obfName ) ); 99 return m_innerClassesByObf.get(obfName);
111 return m_innerClassesByObf.get( obfName );
112 } 100 }
113 101
114 public ClassMapping getInnerClassByDeobf( String deobfName ) 102 public ClassMapping getInnerClassByDeobf(String deobfName) {
115 { 103 assert (isSimpleClassName(deobfName));
116 assert( isSimpleClassName( deobfName ) ); 104 return m_innerClassesByDeobf.get(deobfName);
117 return m_innerClassesByDeobf.get( deobfName );
118 } 105 }
119 106
120 public ClassMapping getInnerClassByDeobfThenObf( String name ) 107 public ClassMapping getInnerClassByDeobfThenObf(String name) {
121 { 108 ClassMapping classMapping = getInnerClassByDeobf(name);
122 ClassMapping classMapping = getInnerClassByDeobf( name ); 109 if (classMapping == null) {
123 if( classMapping == null ) 110 classMapping = getInnerClassByObf(name);
124 {
125 classMapping = getInnerClassByObf( name );
126 } 111 }
127 return classMapping; 112 return classMapping;
128 } 113 }
129 114
130 public String getObfInnerClassName( String deobfName ) 115 public String getObfInnerClassName(String deobfName) {
131 { 116 assert (isSimpleClassName(deobfName));
132 assert( isSimpleClassName( deobfName ) ); 117 ClassMapping classMapping = m_innerClassesByDeobf.get(deobfName);
133 ClassMapping classMapping = m_innerClassesByDeobf.get( deobfName ); 118 if (classMapping != null) {
134 if( classMapping != null )
135 {
136 return classMapping.getObfName(); 119 return classMapping.getObfName();
137 } 120 }
138 return null; 121 return null;
139 } 122 }
140 123
141 public String getDeobfInnerClassName( String obfName ) 124 public String getDeobfInnerClassName(String obfName) {
142 { 125 assert (isSimpleClassName(obfName));
143 assert( isSimpleClassName( obfName ) ); 126 ClassMapping classMapping = m_innerClassesByObf.get(obfName);
144 ClassMapping classMapping = m_innerClassesByObf.get( obfName ); 127 if (classMapping != null) {
145 if( classMapping != null )
146 {
147 return classMapping.getDeobfName(); 128 return classMapping.getDeobfName();
148 } 129 }
149 return null; 130 return null;
150 } 131 }
151 132
152 public void setInnerClassName( String obfName, String deobfName ) 133 public void setInnerClassName(String obfName, String deobfName) {
153 { 134 assert (isSimpleClassName(obfName));
154 assert( isSimpleClassName( obfName ) ); 135 ClassMapping classMapping = getOrCreateInnerClass(obfName);
155 ClassMapping classMapping = getOrCreateInnerClass( obfName ); 136 if (classMapping.getDeobfName() != null) {
156 if( classMapping.getDeobfName() != null ) 137 boolean wasRemoved = m_innerClassesByDeobf.remove(classMapping.getDeobfName()) != null;
157 { 138 assert (wasRemoved);
158 boolean wasRemoved = m_innerClassesByDeobf.remove( classMapping.getDeobfName() ) != null;
159 assert( wasRemoved );
160 } 139 }
161 classMapping.setDeobfName( deobfName ); 140 classMapping.setDeobfName(deobfName);
162 if( deobfName != null ) 141 if (deobfName != null) {
163 { 142 assert (isSimpleClassName(deobfName));
164 assert( isSimpleClassName( deobfName ) ); 143 boolean wasAdded = m_innerClassesByDeobf.put(deobfName, classMapping) == null;
165 boolean wasAdded = m_innerClassesByDeobf.put( deobfName, classMapping ) == null; 144 assert (wasAdded);
166 assert( wasAdded );
167 } 145 }
168 } 146 }
169 147
170 //// FIELDS //////// 148 //// FIELDS ////////
171 149
172 public Iterable<FieldMapping> fields( ) 150 public Iterable<FieldMapping> fields() {
173 { 151 assert (m_fieldsByObf.size() == m_fieldsByDeobf.size());
174 assert( m_fieldsByObf.size() == m_fieldsByDeobf.size() );
175 return m_fieldsByObf.values(); 152 return m_fieldsByObf.values();
176 } 153 }
177 154
178 public boolean containsObfField( String obfName ) 155 public boolean containsObfField(String obfName) {
179 { 156 return m_fieldsByObf.containsKey(obfName);
180 return m_fieldsByObf.containsKey( obfName );
181 } 157 }
182 158
183 public boolean containsDeobfField( String deobfName ) 159 public boolean containsDeobfField(String deobfName) {
184 { 160 return m_fieldsByDeobf.containsKey(deobfName);
185 return m_fieldsByDeobf.containsKey( deobfName );
186 } 161 }
187 162
188 public void addFieldMapping( FieldMapping fieldMapping ) 163 public void addFieldMapping(FieldMapping fieldMapping) {
189 { 164 if (m_fieldsByObf.containsKey(fieldMapping.getObfName())) {
190 if( m_fieldsByObf.containsKey( fieldMapping.getObfName() ) ) 165 throw new Error("Already have mapping for " + m_obfName + "." + fieldMapping.getObfName());
191 {
192 throw new Error( "Already have mapping for " + m_obfName + "." + fieldMapping.getObfName() );
193 } 166 }
194 if( m_fieldsByDeobf.containsKey( fieldMapping.getDeobfName() ) ) 167 if (m_fieldsByDeobf.containsKey(fieldMapping.getDeobfName())) {
195 { 168 throw new Error("Already have mapping for " + m_deobfName + "." + fieldMapping.getDeobfName());
196 throw new Error( "Already have mapping for " + m_deobfName + "." + fieldMapping.getDeobfName() );
197 } 169 }
198 boolean obfWasAdded = m_fieldsByObf.put( fieldMapping.getObfName(), fieldMapping ) == null; 170 boolean obfWasAdded = m_fieldsByObf.put(fieldMapping.getObfName(), fieldMapping) == null;
199 assert( obfWasAdded ); 171 assert (obfWasAdded);
200 boolean deobfWasAdded = m_fieldsByDeobf.put( fieldMapping.getDeobfName(), fieldMapping ) == null; 172 boolean deobfWasAdded = m_fieldsByDeobf.put(fieldMapping.getDeobfName(), fieldMapping) == null;
201 assert( deobfWasAdded ); 173 assert (deobfWasAdded);
202 assert( m_fieldsByObf.size() == m_fieldsByDeobf.size() ); 174 assert (m_fieldsByObf.size() == m_fieldsByDeobf.size());
203 } 175 }
204 176
205 public void removeFieldMapping( FieldMapping fieldMapping ) 177 public void removeFieldMapping(FieldMapping fieldMapping) {
206 { 178 boolean obfWasRemoved = m_fieldsByObf.remove(fieldMapping.getObfName()) != null;
207 boolean obfWasRemoved = m_fieldsByObf.remove( fieldMapping.getObfName() ) != null; 179 assert (obfWasRemoved);
208 assert( obfWasRemoved ); 180 if (fieldMapping.getDeobfName() != null) {
209 if( fieldMapping.getDeobfName() != null ) 181 boolean deobfWasRemoved = m_fieldsByDeobf.remove(fieldMapping.getDeobfName()) != null;
210 { 182 assert (deobfWasRemoved);
211 boolean deobfWasRemoved = m_fieldsByDeobf.remove( fieldMapping.getDeobfName() ) != null;
212 assert( deobfWasRemoved );
213 } 183 }
214 } 184 }
215 185
216 public FieldMapping getFieldByObf( String obfName ) 186 public FieldMapping getFieldByObf(String obfName) {
217 { 187 return m_fieldsByObf.get(obfName);
218 return m_fieldsByObf.get( obfName );
219 } 188 }
220 189
221 public FieldMapping getFieldByDeobf( String deobfName ) 190 public FieldMapping getFieldByDeobf(String deobfName) {
222 { 191 return m_fieldsByDeobf.get(deobfName);
223 return m_fieldsByDeobf.get( deobfName );
224 } 192 }
225 193
226 public String getObfFieldName( String deobfName ) 194 public String getObfFieldName(String deobfName) {
227 { 195 FieldMapping fieldMapping = m_fieldsByDeobf.get(deobfName);
228 FieldMapping fieldMapping = m_fieldsByDeobf.get( deobfName ); 196 if (fieldMapping != null) {
229 if( fieldMapping != null )
230 {
231 return fieldMapping.getObfName(); 197 return fieldMapping.getObfName();
232 } 198 }
233 return null; 199 return null;
234 } 200 }
235 201
236 public String getDeobfFieldName( String obfName ) 202 public String getDeobfFieldName(String obfName) {
237 { 203 FieldMapping fieldMapping = m_fieldsByObf.get(obfName);
238 FieldMapping fieldMapping = m_fieldsByObf.get( obfName ); 204 if (fieldMapping != null) {
239 if( fieldMapping != null )
240 {
241 return fieldMapping.getDeobfName(); 205 return fieldMapping.getDeobfName();
242 } 206 }
243 return null; 207 return null;
244 } 208 }
245 209
246 public void setFieldName( String obfName, String deobfName ) 210 public void setFieldName(String obfName, String deobfName) {
247 { 211 FieldMapping fieldMapping = m_fieldsByObf.get(obfName);
248 FieldMapping fieldMapping = m_fieldsByObf.get( obfName ); 212 if (fieldMapping == null) {
249 if( fieldMapping == null ) 213 fieldMapping = new FieldMapping(obfName, deobfName);
250 { 214 boolean obfWasAdded = m_fieldsByObf.put(obfName, fieldMapping) == null;
251 fieldMapping = new FieldMapping( obfName, deobfName ); 215 assert (obfWasAdded);
252 boolean obfWasAdded = m_fieldsByObf.put( obfName, fieldMapping ) == null; 216 } else {
253 assert( obfWasAdded ); 217 boolean wasRemoved = m_fieldsByDeobf.remove(fieldMapping.getDeobfName()) != null;
218 assert (wasRemoved);
254 } 219 }
255 else 220 fieldMapping.setDeobfName(deobfName);
256 { 221 if (deobfName != null) {
257 boolean wasRemoved = m_fieldsByDeobf.remove( fieldMapping.getDeobfName() ) != null; 222 boolean wasAdded = m_fieldsByDeobf.put(deobfName, fieldMapping) == null;
258 assert( wasRemoved ); 223 assert (wasAdded);
259 }
260 fieldMapping.setDeobfName( deobfName );
261 if( deobfName != null )
262 {
263 boolean wasAdded = m_fieldsByDeobf.put( deobfName, fieldMapping ) == null;
264 assert( wasAdded );
265 } 224 }
266 } 225 }
267 226
268 //// METHODS //////// 227 //// METHODS ////////
269 228
270 public Iterable<MethodMapping> methods( ) 229 public Iterable<MethodMapping> methods() {
271 { 230 assert (m_methodsByObf.size() >= m_methodsByDeobf.size());
272 assert( m_methodsByObf.size() >= m_methodsByDeobf.size() );
273 return m_methodsByObf.values(); 231 return m_methodsByObf.values();
274 } 232 }
275 233
276 public boolean containsObfMethod( String obfName, String obfSignature ) 234 public boolean containsObfMethod(String obfName, String obfSignature) {
277 { 235 return m_methodsByObf.containsKey(getMethodKey(obfName, obfSignature));
278 return m_methodsByObf.containsKey( getMethodKey( obfName, obfSignature ) );
279 } 236 }
280 237
281 public boolean containsDeobfMethod( String deobfName, String deobfSignature ) 238 public boolean containsDeobfMethod(String deobfName, String deobfSignature) {
282 { 239 return m_methodsByDeobf.containsKey(getMethodKey(deobfName, deobfSignature));
283 return m_methodsByDeobf.containsKey( getMethodKey( deobfName, deobfSignature ) );
284 } 240 }
285 241
286 public void addMethodMapping( MethodMapping methodMapping ) 242 public void addMethodMapping(MethodMapping methodMapping) {
287 { 243 String obfKey = getMethodKey(methodMapping.getObfName(), methodMapping.getObfSignature());
288 String obfKey = getMethodKey( methodMapping.getObfName(), methodMapping.getObfSignature() ); 244 if (m_methodsByObf.containsKey(obfKey)) {
289 if( m_methodsByObf.containsKey( obfKey ) ) 245 throw new Error("Already have mapping for " + m_obfName + "." + obfKey);
290 {
291 throw new Error( "Already have mapping for " + m_obfName + "." + obfKey );
292 } 246 }
293 boolean wasAdded = m_methodsByObf.put( obfKey, methodMapping ) == null; 247 boolean wasAdded = m_methodsByObf.put(obfKey, methodMapping) == null;
294 assert( wasAdded ); 248 assert (wasAdded);
295 if( methodMapping.getDeobfName() != null ) 249 if (methodMapping.getDeobfName() != null) {
296 { 250 String deobfKey = getMethodKey(methodMapping.getDeobfName(), methodMapping.getObfSignature());
297 String deobfKey = getMethodKey( methodMapping.getDeobfName(), methodMapping.getObfSignature() ); 251 if (m_methodsByDeobf.containsKey(deobfKey)) {
298 if( m_methodsByDeobf.containsKey( deobfKey ) ) 252 throw new Error("Already have mapping for " + m_deobfName + "." + deobfKey);
299 {
300 throw new Error( "Already have mapping for " + m_deobfName + "." + deobfKey );
301 } 253 }
302 boolean deobfWasAdded = m_methodsByDeobf.put( deobfKey, methodMapping ) == null; 254 boolean deobfWasAdded = m_methodsByDeobf.put(deobfKey, methodMapping) == null;
303 assert( deobfWasAdded ); 255 assert (deobfWasAdded);
304 } 256 }
305 assert( m_methodsByObf.size() >= m_methodsByDeobf.size() ); 257 assert (m_methodsByObf.size() >= m_methodsByDeobf.size());
306 } 258 }
307 259
308 public void removeMethodMapping( MethodMapping methodMapping ) 260 public void removeMethodMapping(MethodMapping methodMapping) {
309 { 261 boolean obfWasRemoved = m_methodsByObf.remove(getMethodKey(methodMapping.getObfName(), methodMapping.getObfSignature())) != null;
310 boolean obfWasRemoved = m_methodsByObf.remove( getMethodKey( methodMapping.getObfName(), methodMapping.getObfSignature() ) ) != null; 262 assert (obfWasRemoved);
311 assert( obfWasRemoved ); 263 if (methodMapping.getDeobfName() != null) {
312 if( methodMapping.getDeobfName() != null ) 264 boolean deobfWasRemoved = m_methodsByDeobf.remove(getMethodKey(methodMapping.getDeobfName(), methodMapping.getObfSignature())) != null;
313 { 265 assert (deobfWasRemoved);
314 boolean deobfWasRemoved = m_methodsByDeobf.remove( getMethodKey( methodMapping.getDeobfName(), methodMapping.getObfSignature() ) ) != null;
315 assert( deobfWasRemoved );
316 } 266 }
317 } 267 }
318 268
319 public MethodMapping getMethodByObf( String obfName, String signature ) 269 public MethodMapping getMethodByObf(String obfName, String signature) {
320 { 270 return m_methodsByObf.get(getMethodKey(obfName, signature));
321 return m_methodsByObf.get( getMethodKey( obfName, signature ) );
322 } 271 }
323 272
324 public MethodMapping getMethodByDeobf( String deobfName, String signature ) 273 public MethodMapping getMethodByDeobf(String deobfName, String signature) {
325 { 274 return m_methodsByDeobf.get(getMethodKey(deobfName, signature));
326 return m_methodsByDeobf.get( getMethodKey( deobfName, signature ) );
327 } 275 }
328 276
329 private String getMethodKey( String name, String signature ) 277 private String getMethodKey(String name, String signature) {
330 { 278 if (name == null) {
331 if( name == null ) 279 throw new IllegalArgumentException("name cannot be null!");
332 {
333 throw new IllegalArgumentException( "name cannot be null!" );
334 } 280 }
335 if( signature == null ) 281 if (signature == null) {
336 { 282 throw new IllegalArgumentException("signature cannot be null!");
337 throw new IllegalArgumentException( "signature cannot be null!" );
338 } 283 }
339 return name + signature; 284 return name + signature;
340 } 285 }
341 286
342 public void setMethodName( String obfName, String obfSignature, String deobfName ) 287 public void setMethodName(String obfName, String obfSignature, String deobfName) {
343 { 288 MethodMapping methodMapping = m_methodsByObf.get(getMethodKey(obfName, obfSignature));
344 MethodMapping methodMapping = m_methodsByObf.get( getMethodKey( obfName, obfSignature ) ); 289 if (methodMapping == null) {
345 if( methodMapping == null ) 290 methodMapping = createMethodMapping(obfName, obfSignature);
346 { 291 } else if (methodMapping.getDeobfName() != null) {
347 methodMapping = createMethodMapping( obfName, obfSignature ); 292 boolean wasRemoved = m_methodsByDeobf.remove(getMethodKey(methodMapping.getDeobfName(), methodMapping.getObfSignature())) != null;
348 } 293 assert (wasRemoved);
349 else if( methodMapping.getDeobfName() != null )
350 {
351 boolean wasRemoved = m_methodsByDeobf.remove( getMethodKey( methodMapping.getDeobfName(), methodMapping.getObfSignature() ) ) != null;
352 assert( wasRemoved );
353 } 294 }
354 methodMapping.setDeobfName( deobfName ); 295 methodMapping.setDeobfName(deobfName);
355 if( deobfName != null ) 296 if (deobfName != null) {
356 { 297 boolean wasAdded = m_methodsByDeobf.put(getMethodKey(deobfName, obfSignature), methodMapping) == null;
357 boolean wasAdded = m_methodsByDeobf.put( getMethodKey( deobfName, obfSignature ), methodMapping ) == null; 298 assert (wasAdded);
358 assert( wasAdded );
359 } 299 }
360 } 300 }
361 301
362 //// ARGUMENTS //////// 302 //// ARGUMENTS ////////
363 303
364 public void setArgumentName( String obfMethodName, String obfMethodSignature, int argumentIndex, String argumentName ) 304 public void setArgumentName(String obfMethodName, String obfMethodSignature, int argumentIndex, String argumentName) {
365 { 305 MethodMapping methodMapping = m_methodsByObf.get(getMethodKey(obfMethodName, obfMethodSignature));
366 MethodMapping methodMapping = m_methodsByObf.get( getMethodKey( obfMethodName, obfMethodSignature ) ); 306 if (methodMapping == null) {
367 if( methodMapping == null ) 307 methodMapping = createMethodMapping(obfMethodName, obfMethodSignature);
368 {
369 methodMapping = createMethodMapping( obfMethodName, obfMethodSignature );
370 } 308 }
371 methodMapping.setArgumentName( argumentIndex, argumentName ); 309 methodMapping.setArgumentName(argumentIndex, argumentName);
372 } 310 }
373 311
374 public void removeArgumentName( String obfMethodName, String obfMethodSignature, int argumentIndex ) 312 public void removeArgumentName(String obfMethodName, String obfMethodSignature, int argumentIndex) {
375 { 313 m_methodsByObf.get(getMethodKey(obfMethodName, obfMethodSignature)).removeArgumentName(argumentIndex);
376 m_methodsByObf.get( getMethodKey( obfMethodName, obfMethodSignature ) ).removeArgumentName( argumentIndex );
377 } 314 }
378 315
379 private MethodMapping createMethodMapping( String obfName, String obfSignature ) 316 private MethodMapping createMethodMapping(String obfName, String obfSignature) {
380 { 317 MethodMapping methodMapping = new MethodMapping(obfName, obfSignature);
381 MethodMapping methodMapping = new MethodMapping( obfName, obfSignature ); 318 boolean wasAdded = m_methodsByObf.put(getMethodKey(obfName, obfSignature), methodMapping) == null;
382 boolean wasAdded = m_methodsByObf.put( getMethodKey( obfName, obfSignature ), methodMapping ) == null; 319 assert (wasAdded);
383 assert( wasAdded );
384 return methodMapping; 320 return methodMapping;
385 } 321 }
386 322
387 @Override 323 @Override
388 public String toString( ) 324 public String toString() {
389 {
390 StringBuilder buf = new StringBuilder(); 325 StringBuilder buf = new StringBuilder();
391 buf.append( m_obfName ); 326 buf.append(m_obfName);
392 buf.append( " <-> " ); 327 buf.append(" <-> ");
393 buf.append( m_deobfName ); 328 buf.append(m_deobfName);
394 buf.append( "\n" ); 329 buf.append("\n");
395 buf.append( "Fields:\n" ); 330 buf.append("Fields:\n");
396 for( FieldMapping fieldMapping : fields() ) 331 for (FieldMapping fieldMapping : fields()) {
397 { 332 buf.append("\t");
398 buf.append( "\t" ); 333 buf.append(fieldMapping.getObfName());
399 buf.append( fieldMapping.getObfName() ); 334 buf.append(" <-> ");
400 buf.append( " <-> " ); 335 buf.append(fieldMapping.getDeobfName());
401 buf.append( fieldMapping.getDeobfName() ); 336 buf.append("\n");
402 buf.append( "\n" ); 337 }
403 } 338 buf.append("Methods:\n");
404 buf.append( "Methods:\n" ); 339 for (MethodMapping methodMapping : m_methodsByObf.values()) {
405 for( MethodMapping methodMapping : m_methodsByObf.values() ) 340 buf.append(methodMapping.toString());
406 { 341 buf.append("\n");
407 buf.append( methodMapping.toString() ); 342 }
408 buf.append( "\n" ); 343 buf.append("Inner Classes:\n");
409 } 344 for (ClassMapping classMapping : m_innerClassesByObf.values()) {
410 buf.append( "Inner Classes:\n" ); 345 buf.append("\t");
411 for( ClassMapping classMapping : m_innerClassesByObf.values() ) 346 buf.append(classMapping.getObfName());
412 { 347 buf.append(" <-> ");
413 buf.append( "\t" ); 348 buf.append(classMapping.getDeobfName());
414 buf.append( classMapping.getObfName() ); 349 buf.append("\n");
415 buf.append( " <-> " );
416 buf.append( classMapping.getDeobfName() );
417 buf.append( "\n" );
418 } 350 }
419 return buf.toString(); 351 return buf.toString();
420 } 352 }
421 353
422 @Override 354 @Override
423 public int compareTo( ClassMapping other ) 355 public int compareTo(ClassMapping other) {
424 {
425 // sort by a, b, c, ... aa, ab, etc 356 // sort by a, b, c, ... aa, ab, etc
426 if( m_obfName.length() != other.m_obfName.length() ) 357 if (m_obfName.length() != other.m_obfName.length()) {
427 {
428 return m_obfName.length() - other.m_obfName.length(); 358 return m_obfName.length() - other.m_obfName.length();
429 } 359 }
430 return m_obfName.compareTo( other.m_obfName ); 360 return m_obfName.compareTo(other.m_obfName);
431 } 361 }
432 362
433 public boolean renameObfClass( String oldObfClassName, String newObfClassName ) 363 public boolean renameObfClass(String oldObfClassName, String newObfClassName) {
434 { 364
435 // rename inner classes 365 // rename inner classes
436 for( ClassMapping innerClassMapping : new ArrayList<ClassMapping>( m_innerClassesByObf.values() ) ) 366 for (ClassMapping innerClassMapping : new ArrayList<ClassMapping>(m_innerClassesByObf.values())) {
437 { 367 if (innerClassMapping.renameObfClass(oldObfClassName, newObfClassName)) {
438 if( innerClassMapping.renameObfClass( oldObfClassName, newObfClassName ) ) 368 boolean wasRemoved = m_innerClassesByObf.remove(oldObfClassName) != null;
439 { 369 assert (wasRemoved);
440 boolean wasRemoved = m_innerClassesByObf.remove( oldObfClassName ) != null; 370 boolean wasAdded = m_innerClassesByObf.put(newObfClassName, innerClassMapping) == null;
441 assert( wasRemoved ); 371 assert (wasAdded);
442 boolean wasAdded = m_innerClassesByObf.put( newObfClassName, innerClassMapping ) == null;
443 assert( wasAdded );
444 } 372 }
445 } 373 }
446 374
447 // rename method signatures 375 // rename method signatures
448 for( MethodMapping methodMapping : new ArrayList<MethodMapping>( m_methodsByObf.values() ) ) 376 for (MethodMapping methodMapping : new ArrayList<MethodMapping>(m_methodsByObf.values())) {
449 { 377 String oldMethodKey = getMethodKey(methodMapping.getObfName(), methodMapping.getObfSignature());
450 String oldMethodKey = getMethodKey( methodMapping.getObfName(), methodMapping.getObfSignature() ); 378 if (methodMapping.renameObfClass(oldObfClassName, newObfClassName)) {
451 if( methodMapping.renameObfClass( oldObfClassName, newObfClassName ) ) 379 boolean wasRemoved = m_methodsByObf.remove(oldMethodKey) != null;
452 { 380 assert (wasRemoved);
453 boolean wasRemoved = m_methodsByObf.remove( oldMethodKey ) != null; 381 boolean wasAdded = m_methodsByObf.put(getMethodKey(methodMapping.getObfName(), methodMapping.getObfSignature()), methodMapping) == null;
454 assert( wasRemoved ); 382 assert (wasAdded);
455 boolean wasAdded = m_methodsByObf.put( getMethodKey( methodMapping.getObfName(), methodMapping.getObfSignature() ), methodMapping ) == null;
456 assert( wasAdded );
457 } 383 }
458 } 384 }
459 385
460 if( m_obfName.equals( oldObfClassName ) ) 386 if (m_obfName.equals(oldObfClassName)) {
461 {
462 // rename this class 387 // rename this class
463 m_obfName = newObfClassName; 388 m_obfName = newObfClassName;
464 return true; 389 return true;
465 } 390 }
466 return false; 391 return false;
467 } 392 }
468 393
469 public boolean containsArgument( BehaviorEntry obfBehaviorEntry, String name ) 394 public boolean containsArgument(BehaviorEntry obfBehaviorEntry, String name) {
470 { 395 MethodMapping methodMapping = m_methodsByObf.get(getMethodKey(obfBehaviorEntry.getName(), obfBehaviorEntry.getSignature()));
471 MethodMapping methodMapping = m_methodsByObf.get( getMethodKey( obfBehaviorEntry.getName(), obfBehaviorEntry.getSignature() ) ); 396 if (methodMapping != null) {
472 if( methodMapping != null ) 397 return methodMapping.containsArgument(name);
473 {
474 return methodMapping.containsArgument( name );
475 } 398 }
476 return false; 399 return false;
477 } 400 }
478 401
479 public static boolean isSimpleClassName( String name ) 402 public static boolean isSimpleClassName(String name) {
480 { 403 return name.indexOf('/') < 0 && name.indexOf('$') < 0;
481 return name.indexOf( '/' ) < 0 && name.indexOf( '$' ) < 0;
482 } 404 }
483} 405}
diff --git a/src/cuchaz/enigma/mapping/ConstructorEntry.java b/src/cuchaz/enigma/mapping/ConstructorEntry.java
index d99d1c3..ea0535f 100644
--- a/src/cuchaz/enigma/mapping/ConstructorEntry.java
+++ b/src/cuchaz/enigma/mapping/ConstructorEntry.java
@@ -14,129 +14,102 @@ import java.io.Serializable;
14 14
15import cuchaz.enigma.Util; 15import cuchaz.enigma.Util;
16 16
17public class ConstructorEntry implements BehaviorEntry, Serializable 17public class ConstructorEntry implements BehaviorEntry, Serializable {
18{ 18
19 private static final long serialVersionUID = -868346075317366758L; 19 private static final long serialVersionUID = -868346075317366758L;
20 20
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 ) 24 public ConstructorEntry(ClassEntry classEntry) {
25 { 25 this(classEntry, null);
26 this( classEntry, null );
27 } 26 }
28 27
29 public ConstructorEntry( ClassEntry classEntry, String signature ) 28 public ConstructorEntry(ClassEntry classEntry, String signature) {
30 { 29 if (classEntry == null) {
31 if( classEntry == null ) 30 throw new IllegalArgumentException("Class cannot be null!");
32 {
33 throw new IllegalArgumentException( "Class cannot be null!" );
34 } 31 }
35 32
36 m_classEntry = classEntry; 33 m_classEntry = classEntry;
37 m_signature = signature; 34 m_signature = signature;
38 } 35 }
39 36
40 public ConstructorEntry( ConstructorEntry other ) 37 public ConstructorEntry(ConstructorEntry other) {
41 { 38 m_classEntry = new ClassEntry(other.m_classEntry);
42 m_classEntry = new ClassEntry( other.m_classEntry );
43 m_signature = other.m_signature; 39 m_signature = other.m_signature;
44 } 40 }
45 41
46 public ConstructorEntry( ConstructorEntry other, String newClassName ) 42 public ConstructorEntry(ConstructorEntry other, String newClassName) {
47 { 43 m_classEntry = new ClassEntry(newClassName);
48 m_classEntry = new ClassEntry( newClassName );
49 m_signature = other.m_signature; 44 m_signature = other.m_signature;
50 } 45 }
51 46
52 @Override 47 @Override
53 public ClassEntry getClassEntry( ) 48 public ClassEntry getClassEntry() {
54 {
55 return m_classEntry; 49 return m_classEntry;
56 } 50 }
57 51
58 @Override 52 @Override
59 public String getName( ) 53 public String getName() {
60 { 54 if (isStatic()) {
61 if( isStatic() )
62 {
63 return "<clinit>"; 55 return "<clinit>";
64 } 56 }
65 return "<init>"; 57 return "<init>";
66 } 58 }
67 59
68 public boolean isStatic( ) 60 public boolean isStatic() {
69 {
70 return m_signature == null; 61 return m_signature == null;
71 } 62 }
72 63
73 @Override 64 @Override
74 public String getSignature( ) 65 public String getSignature() {
75 {
76 return m_signature; 66 return m_signature;
77 } 67 }
78 68
79 @Override 69 @Override
80 public String getClassName( ) 70 public String getClassName() {
81 {
82 return m_classEntry.getName(); 71 return m_classEntry.getName();
83 } 72 }
84 73
85 @Override 74 @Override
86 public ConstructorEntry cloneToNewClass( ClassEntry classEntry ) 75 public ConstructorEntry cloneToNewClass(ClassEntry classEntry) {
87 { 76 return new ConstructorEntry(this, classEntry.getName());
88 return new ConstructorEntry( this, classEntry.getName() );
89 } 77 }
90 78
91 @Override 79 @Override
92 public int hashCode( ) 80 public int hashCode() {
93 { 81 if (isStatic()) {
94 if( isStatic() ) 82 return Util.combineHashesOrdered(m_classEntry);
95 { 83 } else {
96 return Util.combineHashesOrdered( m_classEntry ); 84 return Util.combineHashesOrdered(m_classEntry, m_signature);
97 }
98 else
99 {
100 return Util.combineHashesOrdered( m_classEntry, m_signature );
101 } 85 }
102 } 86 }
103 87
104 @Override 88 @Override
105 public boolean equals( Object other ) 89 public boolean equals(Object other) {
106 { 90 if (other instanceof ConstructorEntry) {
107 if( other instanceof ConstructorEntry ) 91 return equals((ConstructorEntry)other);
108 {
109 return equals( (ConstructorEntry)other );
110 } 92 }
111 return false; 93 return false;
112 } 94 }
113 95
114 public boolean equals( ConstructorEntry other ) 96 public boolean equals(ConstructorEntry other) {
115 { 97 if (isStatic() != other.isStatic()) {
116 if( isStatic() != other.isStatic() )
117 {
118 return false; 98 return false;
119 } 99 }
120 100
121 if( isStatic() ) 101 if (isStatic()) {
122 { 102 return m_classEntry.equals(other.m_classEntry);
123 return m_classEntry.equals( other.m_classEntry ); 103 } else {
124 } 104 return m_classEntry.equals(other.m_classEntry) && m_signature.equals(other.m_signature);
125 else
126 {
127 return m_classEntry.equals( other.m_classEntry ) && m_signature.equals( other.m_signature );
128 } 105 }
129 } 106 }
130 107
131 @Override 108 @Override
132 public String toString( ) 109 public String toString() {
133 { 110 if (isStatic()) {
134 if( isStatic() )
135 {
136 return m_classEntry.getName() + "." + getName(); 111 return m_classEntry.getName() + "." + getName();
137 } 112 } else {
138 else
139 {
140 return m_classEntry.getName() + "." + getName() + m_signature; 113 return m_classEntry.getName() + "." + getName() + m_signature;
141 } 114 }
142 } 115 }
diff --git a/src/cuchaz/enigma/mapping/Entry.java b/src/cuchaz/enigma/mapping/Entry.java
index 8524834..39e1507 100644
--- a/src/cuchaz/enigma/mapping/Entry.java
+++ b/src/cuchaz/enigma/mapping/Entry.java
@@ -10,10 +10,9 @@
10 ******************************************************************************/ 10 ******************************************************************************/
11package cuchaz.enigma.mapping; 11package cuchaz.enigma.mapping;
12 12
13public interface Entry 13public interface Entry {
14{ 14 String getName();
15 String getName( ); 15 String getClassName();
16 String getClassName( ); 16 ClassEntry getClassEntry();
17 ClassEntry getClassEntry( ); 17 Entry cloneToNewClass(ClassEntry classEntry);
18 Entry cloneToNewClass( ClassEntry classEntry );
19} 18}
diff --git a/src/cuchaz/enigma/mapping/EntryPair.java b/src/cuchaz/enigma/mapping/EntryPair.java
index f94d77e..60411c4 100644
--- a/src/cuchaz/enigma/mapping/EntryPair.java
+++ b/src/cuchaz/enigma/mapping/EntryPair.java
@@ -10,15 +10,12 @@
10 ******************************************************************************/ 10 ******************************************************************************/
11package cuchaz.enigma.mapping; 11package cuchaz.enigma.mapping;
12 12
13 13public class EntryPair<T extends Entry> {
14 14
15public class EntryPair<T extends Entry>
16{
17 public T obf; 15 public T obf;
18 public T deobf; 16 public T deobf;
19 17
20 public EntryPair( T obf, T deobf ) 18 public EntryPair(T obf, T deobf) {
21 {
22 this.obf = obf; 19 this.obf = obf;
23 this.deobf = deobf; 20 this.deobf = deobf;
24 } 21 }
diff --git a/src/cuchaz/enigma/mapping/FieldEntry.java b/src/cuchaz/enigma/mapping/FieldEntry.java
index 626af57..6cc9eb7 100644
--- a/src/cuchaz/enigma/mapping/FieldEntry.java
+++ b/src/cuchaz/enigma/mapping/FieldEntry.java
@@ -14,90 +14,75 @@ import java.io.Serializable;
14 14
15import cuchaz.enigma.Util; 15import cuchaz.enigma.Util;
16 16
17public class FieldEntry implements Entry, Serializable 17public class FieldEntry implements Entry, Serializable {
18{ 18
19 private static final long serialVersionUID = 3004663582802885451L; 19 private static final long serialVersionUID = 3004663582802885451L;
20 20
21 private ClassEntry m_classEntry; 21 private ClassEntry m_classEntry;
22 private String m_name; 22 private String m_name;
23 23
24 // NOTE: this argument order is important for the MethodReader/MethodWriter 24 // NOTE: this argument order is important for the MethodReader/MethodWriter
25 public FieldEntry( ClassEntry classEntry, String name ) 25 public FieldEntry(ClassEntry classEntry, String name) {
26 { 26 if (classEntry == null) {
27 if( classEntry == null ) 27 throw new IllegalArgumentException("Class cannot be null!");
28 {
29 throw new IllegalArgumentException( "Class cannot be null!" );
30 } 28 }
31 if( name == null ) 29 if (name == null) {
32 { 30 throw new IllegalArgumentException("Field name cannot be null!");
33 throw new IllegalArgumentException( "Field name cannot be null!" );
34 } 31 }
35 32
36 m_classEntry = classEntry; 33 m_classEntry = classEntry;
37 m_name = name; 34 m_name = name;
38 } 35 }
39 36
40 public FieldEntry( FieldEntry other ) 37 public FieldEntry(FieldEntry other) {
41 { 38 m_classEntry = new ClassEntry(other.m_classEntry);
42 m_classEntry = new ClassEntry( other.m_classEntry );
43 m_name = other.m_name; 39 m_name = other.m_name;
44 } 40 }
45 41
46 public FieldEntry( FieldEntry other, String newClassName ) 42 public FieldEntry(FieldEntry other, String newClassName) {
47 { 43 m_classEntry = new ClassEntry(newClassName);
48 m_classEntry = new ClassEntry( newClassName );
49 m_name = other.m_name; 44 m_name = other.m_name;
50 } 45 }
51 46
52 @Override 47 @Override
53 public ClassEntry getClassEntry( ) 48 public ClassEntry getClassEntry() {
54 {
55 return m_classEntry; 49 return m_classEntry;
56 } 50 }
57 51
58 @Override 52 @Override
59 public String getName( ) 53 public String getName() {
60 {
61 return m_name; 54 return m_name;
62 } 55 }
63 56
64 @Override 57 @Override
65 public String getClassName( ) 58 public String getClassName() {
66 {
67 return m_classEntry.getName(); 59 return m_classEntry.getName();
68 } 60 }
69 61
70 @Override 62 @Override
71 public FieldEntry cloneToNewClass( ClassEntry classEntry ) 63 public FieldEntry cloneToNewClass(ClassEntry classEntry) {
72 { 64 return new FieldEntry(this, classEntry.getName());
73 return new FieldEntry( this, classEntry.getName() );
74 } 65 }
75 66
76 @Override 67 @Override
77 public int hashCode( ) 68 public int hashCode() {
78 { 69 return Util.combineHashesOrdered(m_classEntry, m_name);
79 return Util.combineHashesOrdered( m_classEntry, m_name );
80 } 70 }
81 71
82 @Override 72 @Override
83 public boolean equals( Object other ) 73 public boolean equals(Object other) {
84 { 74 if (other instanceof FieldEntry) {
85 if( other instanceof FieldEntry ) 75 return equals((FieldEntry)other);
86 {
87 return equals( (FieldEntry)other );
88 } 76 }
89 return false; 77 return false;
90 } 78 }
91 79
92 public boolean equals( FieldEntry other ) 80 public boolean equals(FieldEntry other) {
93 { 81 return m_classEntry.equals(other.m_classEntry) && m_name.equals(other.m_name);
94 return m_classEntry.equals( other.m_classEntry )
95 && m_name.equals( other.m_name );
96 } 82 }
97 83
98 @Override 84 @Override
99 public String toString( ) 85 public String toString() {
100 {
101 return m_classEntry.getName() + "." + m_name; 86 return m_classEntry.getName() + "." + m_name;
102 } 87 }
103} 88}
diff --git a/src/cuchaz/enigma/mapping/FieldMapping.java b/src/cuchaz/enigma/mapping/FieldMapping.java
index ae0855a..5f5c270 100644
--- a/src/cuchaz/enigma/mapping/FieldMapping.java
+++ b/src/cuchaz/enigma/mapping/FieldMapping.java
@@ -12,36 +12,32 @@ package cuchaz.enigma.mapping;
12 12
13import java.io.Serializable; 13import java.io.Serializable;
14 14
15public class FieldMapping implements Serializable, Comparable<FieldMapping> 15public class FieldMapping implements Serializable, Comparable<FieldMapping> {
16{ 16
17 private static final long serialVersionUID = 8610742471440861315L; 17 private static final long serialVersionUID = 8610742471440861315L;
18 18
19 private String m_obfName; 19 private String m_obfName;
20 private String m_deobfName; 20 private String m_deobfName;
21 21
22 public FieldMapping( String obfName, String deobfName ) 22 public FieldMapping(String obfName, String deobfName) {
23 {
24 m_obfName = obfName; 23 m_obfName = obfName;
25 m_deobfName = NameValidator.validateFieldName( deobfName ); 24 m_deobfName = NameValidator.validateFieldName(deobfName);
26 } 25 }
27 26
28 public String getObfName( ) 27 public String getObfName() {
29 {
30 return m_obfName; 28 return m_obfName;
31 } 29 }
32 30
33 public String getDeobfName( ) 31 public String getDeobfName() {
34 {
35 return m_deobfName; 32 return m_deobfName;
36 } 33 }
37 public void setDeobfName( String val ) 34
38 { 35 public void setDeobfName(String val) {
39 m_deobfName = NameValidator.validateFieldName( val ); 36 m_deobfName = NameValidator.validateFieldName(val);
40 } 37 }
41 38
42 @Override 39 @Override
43 public int compareTo( FieldMapping other ) 40 public int compareTo(FieldMapping other) {
44 { 41 return m_obfName.compareTo(other.m_obfName);
45 return m_obfName.compareTo( other.m_obfName );
46 } 42 }
47} 43}
diff --git a/src/cuchaz/enigma/mapping/IllegalNameException.java b/src/cuchaz/enigma/mapping/IllegalNameException.java
index 830f05c..aacaf3b 100644
--- a/src/cuchaz/enigma/mapping/IllegalNameException.java
+++ b/src/cuchaz/enigma/mapping/IllegalNameException.java
@@ -10,39 +10,34 @@
10 ******************************************************************************/ 10 ******************************************************************************/
11package cuchaz.enigma.mapping; 11package cuchaz.enigma.mapping;
12 12
13public class IllegalNameException extends RuntimeException 13public class IllegalNameException extends RuntimeException {
14{ 14
15 private static final long serialVersionUID = -2279910052561114323L; 15 private static final long serialVersionUID = -2279910052561114323L;
16 16
17 private String m_name; 17 private String m_name;
18 private String m_reason; 18 private String m_reason;
19 19
20 public IllegalNameException( String name ) 20 public IllegalNameException(String name) {
21 { 21 this(name, null);
22 this( name, null );
23 } 22 }
24 23
25 public IllegalNameException( String name, String reason ) 24 public IllegalNameException(String name, String reason) {
26 {
27 m_name = name; 25 m_name = name;
28 m_reason = reason; 26 m_reason = reason;
29 } 27 }
30 28
31 public String getReason( ) 29 public String getReason() {
32 {
33 return m_reason; 30 return m_reason;
34 } 31 }
35 32
36 @Override 33 @Override
37 public String getMessage( ) 34 public String getMessage() {
38 {
39 StringBuilder buf = new StringBuilder(); 35 StringBuilder buf = new StringBuilder();
40 buf.append( "Illegal name: " ); 36 buf.append("Illegal name: ");
41 buf.append( m_name ); 37 buf.append(m_name);
42 if( m_reason != null ) 38 if (m_reason != null) {
43 { 39 buf.append(" because ");
44 buf.append( " because " ); 40 buf.append(m_reason);
45 buf.append( m_reason );
46 } 41 }
47 return buf.toString(); 42 return buf.toString();
48 } 43 }
diff --git a/src/cuchaz/enigma/mapping/MappingParseException.java b/src/cuchaz/enigma/mapping/MappingParseException.java
index 4fcc1f1..1974c22 100644
--- a/src/cuchaz/enigma/mapping/MappingParseException.java
+++ b/src/cuchaz/enigma/mapping/MappingParseException.java
@@ -10,22 +10,20 @@
10 ******************************************************************************/ 10 ******************************************************************************/
11package cuchaz.enigma.mapping; 11package cuchaz.enigma.mapping;
12 12
13public class MappingParseException extends Exception 13public class MappingParseException extends Exception {
14{ 14
15 private static final long serialVersionUID = -5487280332892507236L; 15 private static final long serialVersionUID = -5487280332892507236L;
16 16
17 private int m_line; 17 private int m_line;
18 private String m_message; 18 private String m_message;
19 19
20 public MappingParseException( int line, String message ) 20 public MappingParseException(int line, String message) {
21 {
22 m_line = line; 21 m_line = line;
23 m_message = message; 22 m_message = message;
24 } 23 }
25 24
26 @Override 25 @Override
27 public String getMessage( ) 26 public String getMessage() {
28 {
29 return "Line " + m_line + ": " + m_message; 27 return "Line " + m_line + ": " + m_message;
30 } 28 }
31} 29}
diff --git a/src/cuchaz/enigma/mapping/Mappings.java b/src/cuchaz/enigma/mapping/Mappings.java
index 3a39d10..c5e38f4 100644
--- a/src/cuchaz/enigma/mapping/Mappings.java
+++ b/src/cuchaz/enigma/mapping/Mappings.java
@@ -26,230 +26,182 @@ import com.google.common.collect.Sets;
26import cuchaz.enigma.Util; 26import cuchaz.enigma.Util;
27import cuchaz.enigma.mapping.SignatureUpdater.ClassNameUpdater; 27import cuchaz.enigma.mapping.SignatureUpdater.ClassNameUpdater;
28 28
29public class Mappings implements Serializable 29public class Mappings implements Serializable {
30{ 30
31 private static final long serialVersionUID = 4649790259460259026L; 31 private static final long serialVersionUID = 4649790259460259026L;
32 32
33 protected Map<String,ClassMapping> m_classesByObf; 33 protected Map<String,ClassMapping> m_classesByObf;
34 protected Map<String,ClassMapping> m_classesByDeobf; 34 protected Map<String,ClassMapping> m_classesByDeobf;
35 35
36 public Mappings( ) 36 public Mappings() {
37 {
38 m_classesByObf = Maps.newHashMap(); 37 m_classesByObf = Maps.newHashMap();
39 m_classesByDeobf = Maps.newHashMap(); 38 m_classesByDeobf = Maps.newHashMap();
40 } 39 }
41 40
42 public Mappings( Iterable<ClassMapping> classes ) 41 public Mappings(Iterable<ClassMapping> classes) {
43 {
44 this(); 42 this();
45 43
46 for( ClassMapping classMapping : classes ) 44 for (ClassMapping classMapping : classes) {
47 { 45 m_classesByObf.put(classMapping.getObfName(), classMapping);
48 m_classesByObf.put( classMapping.getObfName(), classMapping ); 46 if (classMapping.getDeobfName() != null) {
49 if( classMapping.getDeobfName() != null ) 47 m_classesByDeobf.put(classMapping.getDeobfName(), classMapping);
50 {
51 m_classesByDeobf.put( classMapping.getDeobfName(), classMapping );
52 } 48 }
53 } 49 }
54 } 50 }
55 51
56 public static Mappings newFromResource( String resource ) 52 public static Mappings newFromResource(String resource) throws IOException {
57 throws IOException
58 {
59 InputStream in = null; 53 InputStream in = null;
60 try 54 try {
61 { 55 in = Mappings.class.getResourceAsStream(resource);
62 in = Mappings.class.getResourceAsStream( resource ); 56 return newFromStream(in);
63 return newFromStream( in ); 57 } finally {
64 } 58 Util.closeQuietly(in);
65 finally
66 {
67 Util.closeQuietly( in );
68 } 59 }
69 } 60 }
70 61
71 public Collection<ClassMapping> classes( ) 62 public Collection<ClassMapping> classes() {
72 { 63 assert (m_classesByObf.size() >= m_classesByDeobf.size());
73 assert( m_classesByObf.size() >= m_classesByDeobf.size() );
74 return m_classesByObf.values(); 64 return m_classesByObf.values();
75 } 65 }
76 66
77 public void addClassMapping( ClassMapping classMapping ) 67 public void addClassMapping(ClassMapping classMapping) {
78 { 68 if (m_classesByObf.containsKey(classMapping.getObfName())) {
79 if( m_classesByObf.containsKey( classMapping.getObfName() ) ) 69 throw new Error("Already have mapping for " + classMapping.getObfName());
80 {
81 throw new Error( "Already have mapping for " + classMapping.getObfName() );
82 } 70 }
83 boolean obfWasAdded = m_classesByObf.put( classMapping.getObfName(), classMapping ) == null; 71 boolean obfWasAdded = m_classesByObf.put(classMapping.getObfName(), classMapping) == null;
84 assert( obfWasAdded ); 72 assert (obfWasAdded);
85 if( classMapping.getDeobfName() != null ) 73 if (classMapping.getDeobfName() != null) {
86 { 74 if (m_classesByDeobf.containsKey(classMapping.getDeobfName())) {
87 if( m_classesByDeobf.containsKey( classMapping.getDeobfName() ) ) 75 throw new Error("Already have mapping for " + classMapping.getDeobfName());
88 {
89 throw new Error( "Already have mapping for " + classMapping.getDeobfName() );
90 } 76 }
91 boolean deobfWasAdded = m_classesByDeobf.put( classMapping.getDeobfName(), classMapping ) == null; 77 boolean deobfWasAdded = m_classesByDeobf.put(classMapping.getDeobfName(), classMapping) == null;
92 assert( deobfWasAdded ); 78 assert (deobfWasAdded);
93 } 79 }
94 } 80 }
95 81
96 public void removeClassMapping( ClassMapping classMapping ) 82 public void removeClassMapping(ClassMapping classMapping) {
97 { 83 boolean obfWasRemoved = m_classesByObf.remove(classMapping.getObfName()) != null;
98 boolean obfWasRemoved = m_classesByObf.remove( classMapping.getObfName() ) != null; 84 assert (obfWasRemoved);
99 assert( obfWasRemoved ); 85 if (classMapping.getDeobfName() != null) {
100 if( classMapping.getDeobfName() != null ) 86 boolean deobfWasRemoved = m_classesByDeobf.remove(classMapping.getDeobfName()) != null;
101 { 87 assert (deobfWasRemoved);
102 boolean deobfWasRemoved = m_classesByDeobf.remove( classMapping.getDeobfName() ) != null;
103 assert( deobfWasRemoved );
104 } 88 }
105 } 89 }
106 90
107 public ClassMapping getClassByObf( ClassEntry entry ) 91 public ClassMapping getClassByObf(ClassEntry entry) {
108 { 92 return getClassByObf(entry.getName());
109 return getClassByObf( entry.getName() );
110 } 93 }
111 94
112 public ClassMapping getClassByObf( String obfName ) 95 public ClassMapping getClassByObf(String obfName) {
113 { 96 return m_classesByObf.get(obfName);
114 return m_classesByObf.get( obfName );
115 } 97 }
116 98
117 public ClassMapping getClassByDeobf( ClassEntry entry ) 99 public ClassMapping getClassByDeobf(ClassEntry entry) {
118 { 100 return getClassByDeobf(entry.getName());
119 return getClassByDeobf( entry.getName() );
120 } 101 }
121 102
122 public ClassMapping getClassByDeobf( String deobfName ) 103 public ClassMapping getClassByDeobf(String deobfName) {
123 { 104 return m_classesByDeobf.get(deobfName);
124 return m_classesByDeobf.get( deobfName );
125 } 105 }
126 106
127 public Translator getTranslator( TranslationDirection direction ) 107 public Translator getTranslator(TranslationDirection direction) {
128 { 108 switch (direction) {
129 switch( direction )
130 {
131 case Deobfuscating: 109 case Deobfuscating:
132 110
133 return new Translator( direction, m_classesByObf ); 111 return new Translator(direction, m_classesByObf);
134 112
135 case Obfuscating: 113 case Obfuscating:
136 114
137 // fill in the missing deobf class entries with obf entries 115 // fill in the missing deobf class entries with obf entries
138 Map<String,ClassMapping> classes = Maps.newHashMap(); 116 Map<String,ClassMapping> classes = Maps.newHashMap();
139 for( ClassMapping classMapping : classes() ) 117 for (ClassMapping classMapping : classes()) {
140 { 118 if (classMapping.getDeobfName() != null) {
141 if( classMapping.getDeobfName() != null ) 119 classes.put(classMapping.getDeobfName(), classMapping);
142 { 120 } else {
143 classes.put( classMapping.getDeobfName(), classMapping ); 121 classes.put(classMapping.getObfName(), classMapping);
144 }
145 else
146 {
147 classes.put( classMapping.getObfName(), classMapping );
148 } 122 }
149 } 123 }
150 124
151 return new Translator( direction, classes ); 125 return new Translator(direction, classes);
152 126
153 default: 127 default:
154 throw new Error( "Invalid translation direction!" ); 128 throw new Error("Invalid translation direction!");
155 } 129 }
156 } 130 }
157 131
158 public static Mappings newFromStream( InputStream in ) 132 public static Mappings newFromStream(InputStream in) throws IOException {
159 throws IOException 133 try {
160 { 134 return (Mappings)new ObjectInputStream(new GZIPInputStream(in)).readObject();
161 try 135 } catch (ClassNotFoundException ex) {
162 { 136 throw new Error(ex);
163 return (Mappings)new ObjectInputStream( new GZIPInputStream( in ) ).readObject();
164 }
165 catch( ClassNotFoundException ex )
166 {
167 throw new Error( ex );
168 } 137 }
169 } 138 }
170 139
171 @Override 140 @Override
172 public String toString( ) 141 public String toString() {
173 {
174 StringBuilder buf = new StringBuilder(); 142 StringBuilder buf = new StringBuilder();
175 for( ClassMapping classMapping : m_classesByObf.values() ) 143 for (ClassMapping classMapping : m_classesByObf.values()) {
176 { 144 buf.append(classMapping.toString());
177 buf.append( classMapping.toString() ); 145 buf.append("\n");
178 buf.append( "\n" );
179 } 146 }
180 return buf.toString(); 147 return buf.toString();
181 } 148 }
182 149
183 public void renameObfClass( String oldObfName, String newObfName ) 150 public void renameObfClass(String oldObfName, String newObfName) {
184 { 151 for (ClassMapping classMapping : new ArrayList<ClassMapping>(classes())) {
185 for( ClassMapping classMapping : new ArrayList<ClassMapping>( classes() ) ) 152 if (classMapping.renameObfClass(oldObfName, newObfName)) {
186 { 153 boolean wasRemoved = m_classesByObf.remove(oldObfName) != null;
187 if( classMapping.renameObfClass( oldObfName, newObfName ) ) 154 assert (wasRemoved);
188 { 155 boolean wasAdded = m_classesByObf.put(newObfName, classMapping) == null;
189 boolean wasRemoved = m_classesByObf.remove( oldObfName ) != null; 156 assert (wasAdded);
190 assert( wasRemoved );
191 boolean wasAdded = m_classesByObf.put( newObfName, classMapping ) == null;
192 assert( wasAdded );
193 } 157 }
194 } 158 }
195 } 159 }
196 160
197 public Set<String> getAllObfClassNames( ) 161 public Set<String> getAllObfClassNames() {
198 {
199 final Set<String> classNames = Sets.newHashSet(); 162 final Set<String> classNames = Sets.newHashSet();
200 for( ClassMapping classMapping : classes() ) 163 for (ClassMapping classMapping : classes()) {
201 {
202 // add the class name 164 // add the class name
203 classNames.add( classMapping.getObfName() ); 165 classNames.add(classMapping.getObfName());
204 166
205 // add classes from method signatures 167 // add classes from method signatures
206 for( MethodMapping methodMapping : classMapping.methods() ) 168 for (MethodMapping methodMapping : classMapping.methods()) {
207 { 169 SignatureUpdater.update(methodMapping.getObfSignature(), new ClassNameUpdater() {
208 SignatureUpdater.update( methodMapping.getObfSignature(), new ClassNameUpdater( )
209 {
210 @Override 170 @Override
211 public String update( String className ) 171 public String update(String className) {
212 { 172 classNames.add(className);
213 classNames.add( className );
214 return className; 173 return className;
215 } 174 }
216 } ); 175 });
217 } 176 }
218 } 177 }
219 return classNames; 178 return classNames;
220 } 179 }
221 180
222 public boolean containsDeobfClass( String deobfName ) 181 public boolean containsDeobfClass(String deobfName) {
223 { 182 return m_classesByDeobf.containsKey(deobfName);
224 return m_classesByDeobf.containsKey( deobfName );
225 } 183 }
226 184
227 public boolean containsDeobfField( ClassEntry obfClassEntry, String deobfName ) 185 public boolean containsDeobfField(ClassEntry obfClassEntry, String deobfName) {
228 { 186 ClassMapping classMapping = m_classesByObf.get(obfClassEntry.getName());
229 ClassMapping classMapping = m_classesByObf.get( obfClassEntry.getName() ); 187 if (classMapping != null) {
230 if( classMapping != null ) 188 return classMapping.containsDeobfField(deobfName);
231 {
232 return classMapping.containsDeobfField( deobfName );
233 } 189 }
234 return false; 190 return false;
235 } 191 }
236 192
237 public boolean containsDeobfMethod( ClassEntry obfClassEntry, String deobfName, String deobfSignature ) 193 public boolean containsDeobfMethod(ClassEntry obfClassEntry, String deobfName, String deobfSignature) {
238 { 194 ClassMapping classMapping = m_classesByObf.get(obfClassEntry.getName());
239 ClassMapping classMapping = m_classesByObf.get( obfClassEntry.getName() ); 195 if (classMapping != null) {
240 if( classMapping != null ) 196 return classMapping.containsDeobfMethod(deobfName, deobfSignature);
241 {
242 return classMapping.containsDeobfMethod( deobfName, deobfSignature );
243 } 197 }
244 return false; 198 return false;
245 } 199 }
246 200
247 public boolean containsArgument( BehaviorEntry obfBehaviorEntry, String name ) 201 public boolean containsArgument(BehaviorEntry obfBehaviorEntry, String name) {
248 { 202 ClassMapping classMapping = m_classesByObf.get(obfBehaviorEntry.getClassName());
249 ClassMapping classMapping = m_classesByObf.get( obfBehaviorEntry.getClassName() ); 203 if (classMapping != null) {
250 if( classMapping != null ) 204 return classMapping.containsArgument(obfBehaviorEntry, name);
251 {
252 return classMapping.containsArgument( obfBehaviorEntry, name );
253 } 205 }
254 return false; 206 return false;
255 } 207 }
diff --git a/src/cuchaz/enigma/mapping/MappingsReader.java b/src/cuchaz/enigma/mapping/MappingsReader.java
index 4bd9f12..72e829d 100644
--- a/src/cuchaz/enigma/mapping/MappingsReader.java
+++ b/src/cuchaz/enigma/mapping/MappingsReader.java
@@ -20,209 +20,157 @@ import com.google.common.collect.Queues;
20import cuchaz.enigma.Constants; 20import cuchaz.enigma.Constants;
21import cuchaz.enigma.mapping.SignatureUpdater.ClassNameUpdater; 21import cuchaz.enigma.mapping.SignatureUpdater.ClassNameUpdater;
22 22
23public class MappingsReader 23public class MappingsReader {
24{ 24
25 public Mappings read( Reader in ) 25 public Mappings read(Reader in) throws IOException, MappingParseException {
26 throws IOException, MappingParseException 26 return read(new BufferedReader(in));
27 {
28 return read( new BufferedReader( in ) );
29 } 27 }
30 28
31 public Mappings read( BufferedReader in ) 29 public Mappings read(BufferedReader in) throws IOException, MappingParseException {
32 throws IOException, MappingParseException
33 {
34 Mappings mappings = new Mappings(); 30 Mappings mappings = new Mappings();
35 Deque<Object> mappingStack = Queues.newArrayDeque(); 31 Deque<Object> mappingStack = Queues.newArrayDeque();
36 32
37 int lineNumber = 0; 33 int lineNumber = 0;
38 String line = null; 34 String line = null;
39 while( ( line = in.readLine() ) != null ) 35 while ( (line = in.readLine()) != null) {
40 {
41 lineNumber++; 36 lineNumber++;
42 37
43 // strip comments 38 // strip comments
44 int commentPos = line.indexOf( '#' ); 39 int commentPos = line.indexOf('#');
45 if( commentPos >= 0 ) 40 if (commentPos >= 0) {
46 { 41 line = line.substring(0, commentPos);
47 line = line.substring( 0, commentPos );
48 } 42 }
49 43
50 // skip blank lines 44 // skip blank lines
51 if( line.trim().length() <= 0 ) 45 if (line.trim().length() <= 0) {
52 {
53 continue; 46 continue;
54 } 47 }
55 48
56 // get the indent of this line 49 // get the indent of this line
57 int indent = 0; 50 int indent = 0;
58 for( int i=0; i<line.length(); i++ ) 51 for (int i = 0; i < line.length(); i++) {
59 { 52 if (line.charAt(i) != '\t') {
60 if( line.charAt( i ) != '\t' )
61 {
62 break; 53 break;
63 } 54 }
64 indent++; 55 indent++;
65 } 56 }
66 57
67 // handle stack pops 58 // handle stack pops
68 while( indent < mappingStack.size() ) 59 while (indent < mappingStack.size()) {
69 {
70 mappingStack.pop(); 60 mappingStack.pop();
71 } 61 }
72 62
73 String[] parts = line.trim().split( "\\s" ); 63 String[] parts = line.trim().split("\\s");
74 try 64 try {
75 {
76 // read the first token 65 // read the first token
77 String token = parts[0]; 66 String token = parts[0];
78 67
79 if( token.equalsIgnoreCase( "CLASS" ) ) 68 if (token.equalsIgnoreCase("CLASS")) {
80 {
81 ClassMapping classMapping; 69 ClassMapping classMapping;
82 if( indent == 0 ) 70 if (indent == 0) {
83 {
84 // outer class 71 // outer class
85 classMapping = readClass( parts, false ); 72 classMapping = readClass(parts, false);
86 mappings.addClassMapping( classMapping ); 73 mappings.addClassMapping(classMapping);
87 } 74 } else if (indent == 1) {
88 else if( indent == 1 )
89 {
90 // inner class 75 // inner class
91 if( !( mappingStack.getFirst() instanceof ClassMapping ) ) 76 if (! (mappingStack.getFirst() instanceof ClassMapping)) {
92 { 77 throw new MappingParseException(lineNumber, "Unexpected CLASS entry here!");
93 throw new MappingParseException( lineNumber, "Unexpected CLASS entry here!" );
94 } 78 }
95 79
96 classMapping = readClass( parts, true ); 80 classMapping = readClass(parts, true);
97 ((ClassMapping)mappingStack.getFirst()).addInnerClassMapping( classMapping ); 81 ((ClassMapping)mappingStack.getFirst()).addInnerClassMapping(classMapping);
82 } else {
83 throw new MappingParseException(lineNumber, "Unexpected CLASS entry nesting!");
98 } 84 }
99 else 85 mappingStack.push(classMapping);
100 { 86 } else if (token.equalsIgnoreCase("FIELD")) {
101 throw new MappingParseException( lineNumber, "Unexpected CLASS entry nesting!" ); 87 if (mappingStack.isEmpty() || ! (mappingStack.getFirst() instanceof ClassMapping)) {
88 throw new MappingParseException(lineNumber, "Unexpected FIELD entry here!");
102 } 89 }
103 mappingStack.push( classMapping ); 90 ((ClassMapping)mappingStack.getFirst()).addFieldMapping(readField(parts));
104 } 91 } else if (token.equalsIgnoreCase("METHOD")) {
105 else if( token.equalsIgnoreCase( "FIELD" ) ) 92 if (mappingStack.isEmpty() || ! (mappingStack.getFirst() instanceof ClassMapping)) {
106 { 93 throw new MappingParseException(lineNumber, "Unexpected METHOD entry here!");
107 if( mappingStack.isEmpty() || !(mappingStack.getFirst() instanceof ClassMapping) )
108 {
109 throw new MappingParseException( lineNumber, "Unexpected FIELD entry here!" );
110 }
111 ((ClassMapping)mappingStack.getFirst()).addFieldMapping( readField( parts ) );
112 }
113 else if( token.equalsIgnoreCase( "METHOD" ) )
114 {
115 if( mappingStack.isEmpty() || !(mappingStack.getFirst() instanceof ClassMapping) )
116 {
117 throw new MappingParseException( lineNumber, "Unexpected METHOD entry here!" );
118 } 94 }
119 MethodMapping methodMapping = readMethod( parts ); 95 MethodMapping methodMapping = readMethod(parts);
120 ((ClassMapping)mappingStack.getFirst()).addMethodMapping( methodMapping ); 96 ((ClassMapping)mappingStack.getFirst()).addMethodMapping(methodMapping);
121 mappingStack.push( methodMapping ); 97 mappingStack.push(methodMapping);
122 } 98 } else if (token.equalsIgnoreCase("ARG")) {
123 else if( token.equalsIgnoreCase( "ARG" ) ) 99 if (mappingStack.isEmpty() || ! (mappingStack.getFirst() instanceof MethodMapping)) {
124 { 100 throw new MappingParseException(lineNumber, "Unexpected ARG entry here!");
125 if( mappingStack.isEmpty() || !(mappingStack.getFirst() instanceof MethodMapping) )
126 {
127 throw new MappingParseException( lineNumber, "Unexpected ARG entry here!" );
128 } 101 }
129 ((MethodMapping)mappingStack.getFirst()).addArgumentMapping( readArgument( parts ) ); 102 ((MethodMapping)mappingStack.getFirst()).addArgumentMapping(readArgument(parts));
130 } 103 }
131 } 104 } catch (ArrayIndexOutOfBoundsException | NumberFormatException ex) {
132 catch( ArrayIndexOutOfBoundsException | NumberFormatException ex ) 105 throw new MappingParseException(lineNumber, "Malformed line!");
133 {
134 throw new MappingParseException( lineNumber, "Malformed line!" );
135 } 106 }
136 } 107 }
137 108
138 return mappings; 109 return mappings;
139 } 110 }
140 111
141 private ArgumentMapping readArgument( String[] parts ) 112 private ArgumentMapping readArgument(String[] parts) {
142 { 113 return new ArgumentMapping(Integer.parseInt(parts[1]), parts[2]);
143 return new ArgumentMapping( Integer.parseInt( parts[1] ), parts[2] );
144 } 114 }
145 115
146 private ClassMapping readClass( String[] parts, boolean makeSimple ) 116 private ClassMapping readClass(String[] parts, boolean makeSimple) {
147 { 117 if (parts.length == 2) {
148 if( parts.length == 2 ) 118 String obfName = processName(parts[1], makeSimple);
149 { 119 return new ClassMapping(obfName);
150 String obfName = processName( parts[1], makeSimple ); 120 } else {
151 return new ClassMapping( obfName ); 121 String obfName = processName(parts[1], makeSimple);
152 } 122 String deobfName = processName(parts[2], makeSimple);
153 else 123 return new ClassMapping(obfName, deobfName);
154 {
155 String obfName = processName( parts[1], makeSimple );
156 String deobfName = processName( parts[2], makeSimple );
157 return new ClassMapping( obfName, deobfName );
158 } 124 }
159 } 125 }
160 126
161 private String processName( String name, boolean makeSimple ) 127 private String processName(String name, boolean makeSimple) {
162 { 128 if (makeSimple) {
163 if( makeSimple ) 129 return new ClassEntry(name).getSimpleName();
164 { 130 } else {
165 return new ClassEntry( name ).getSimpleName(); 131 return moveClassOutOfDefaultPackage(name, Constants.NonePackage);
166 }
167 else
168 {
169 return moveClassOutOfDefaultPackage( name, Constants.NonePackage );
170 } 132 }
171 } 133 }
172 134
173 private String moveClassOutOfDefaultPackage( String className, String newPackageName ) 135 private String moveClassOutOfDefaultPackage(String className, String newPackageName) {
174 { 136 ClassEntry classEntry = new ClassEntry(className);
175 ClassEntry classEntry = new ClassEntry( className ); 137 if (classEntry.isInDefaultPackage()) {
176 if( classEntry.isInDefaultPackage() )
177 {
178 return newPackageName + "/" + classEntry.getName(); 138 return newPackageName + "/" + classEntry.getName();
179 } 139 }
180 return className; 140 return className;
181 } 141 }
182 142
183 private FieldMapping readField( String[] parts ) 143 private FieldMapping readField(String[] parts) {
184 { 144 return new FieldMapping(parts[1], parts[2]);
185 return new FieldMapping( parts[1], parts[2] );
186 } 145 }
187 146
188 private MethodMapping readMethod( String[] parts ) 147 private MethodMapping readMethod(String[] parts) {
189 { 148 if (parts.length == 3) {
190 if( parts.length == 3 )
191 {
192 String obfName = parts[1]; 149 String obfName = parts[1];
193 String obfSignature = moveSignatureOutOfDefaultPackage( parts[2], Constants.NonePackage ); 150 String obfSignature = moveSignatureOutOfDefaultPackage(parts[2], Constants.NonePackage);
194 return new MethodMapping( obfName, obfSignature ); 151 return new MethodMapping(obfName, obfSignature);
195 } 152 } else {
196 else
197 {
198 String obfName = parts[1]; 153 String obfName = parts[1];
199 String deobfName = parts[2]; 154 String deobfName = parts[2];
200 String obfSignature = moveSignatureOutOfDefaultPackage( parts[3], Constants.NonePackage ); 155 String obfSignature = moveSignatureOutOfDefaultPackage(parts[3], Constants.NonePackage);
201 if( obfName.equals( deobfName ) ) 156 if (obfName.equals(deobfName)) {
202 { 157 return new MethodMapping(obfName, obfSignature);
203 return new MethodMapping( obfName, obfSignature ); 158 } else {
204 } 159 return new MethodMapping(obfName, obfSignature, deobfName);
205 else
206 {
207 return new MethodMapping( obfName, obfSignature, deobfName );
208 } 160 }
209 } 161 }
210 } 162 }
211 163
212 private String moveSignatureOutOfDefaultPackage( String signature, final String newPackageName ) 164 private String moveSignatureOutOfDefaultPackage(String signature, final String newPackageName) {
213 { 165 return SignatureUpdater.update(signature, new ClassNameUpdater() {
214 return SignatureUpdater.update( signature, new ClassNameUpdater( )
215 {
216 @Override 166 @Override
217 public String update( String className ) 167 public String update(String className) {
218 { 168 ClassEntry classEntry = new ClassEntry(className);
219 ClassEntry classEntry = new ClassEntry( className ); 169 if (classEntry.isInDefaultPackage()) {
220 if( classEntry.isInDefaultPackage() )
221 {
222 return newPackageName + "/" + className; 170 return newPackageName + "/" + className;
223 } 171 }
224 return className; 172 return className;
225 } 173 }
226 } ); 174 });
227 } 175 }
228} 176}
diff --git a/src/cuchaz/enigma/mapping/MappingsRenamer.java b/src/cuchaz/enigma/mapping/MappingsRenamer.java
index 3e5f1a4..cb95f42 100644
--- a/src/cuchaz/enigma/mapping/MappingsRenamer.java
+++ b/src/cuchaz/enigma/mapping/MappingsRenamer.java
@@ -19,272 +19,218 @@ import java.util.zip.GZIPOutputStream;
19import cuchaz.enigma.Constants; 19import cuchaz.enigma.Constants;
20import cuchaz.enigma.analysis.JarIndex; 20import cuchaz.enigma.analysis.JarIndex;
21 21
22public class MappingsRenamer 22public class MappingsRenamer {
23{ 23
24 private JarIndex m_index; 24 private JarIndex m_index;
25 private Mappings m_mappings; 25 private Mappings m_mappings;
26 26
27 public MappingsRenamer( JarIndex index, Mappings mappings ) 27 public MappingsRenamer(JarIndex index, Mappings mappings) {
28 {
29 m_index = index; 28 m_index = index;
30 m_mappings = mappings; 29 m_mappings = mappings;
31 } 30 }
32 31
33 public void setClassName( ClassEntry obf, String deobfName ) 32 public void setClassName(ClassEntry obf, String deobfName) {
34 { 33 deobfName = NameValidator.validateClassName(deobfName, !obf.isInnerClass());
35 deobfName = NameValidator.validateClassName( deobfName, !obf.isInnerClass() ); 34 ClassEntry targetEntry = new ClassEntry(deobfName);
36 ClassEntry targetEntry = new ClassEntry( deobfName ); 35 if (m_mappings.containsDeobfClass(deobfName) || m_index.containsObfClass(targetEntry)) {
37 if( m_mappings.containsDeobfClass( deobfName ) || m_index.containsObfClass( targetEntry ) ) 36 throw new IllegalNameException(deobfName, "There is already a class with that name");
38 {
39 throw new IllegalNameException( deobfName, "There is already a class with that name" );
40 } 37 }
41 38
42 ClassMapping classMapping = getOrCreateClassMapping( obf ); 39 ClassMapping classMapping = getOrCreateClassMapping(obf);
43 40
44 if( obf.isInnerClass() ) 41 if (obf.isInnerClass()) {
45 { 42 classMapping.setInnerClassName(obf.getInnerClassName(), deobfName);
46 classMapping.setInnerClassName( obf.getInnerClassName(), deobfName ); 43 } else {
47 } 44 if (classMapping.getDeobfName() != null) {
48 else 45 boolean wasRemoved = m_mappings.m_classesByDeobf.remove(classMapping.getDeobfName()) != null;
49 { 46 assert (wasRemoved);
50 if( classMapping.getDeobfName() != null )
51 {
52 boolean wasRemoved = m_mappings.m_classesByDeobf.remove( classMapping.getDeobfName() ) != null;
53 assert( wasRemoved );
54 } 47 }
55 classMapping.setDeobfName( deobfName ); 48 classMapping.setDeobfName(deobfName);
56 boolean wasAdded = m_mappings.m_classesByDeobf.put( deobfName, classMapping ) == null; 49 boolean wasAdded = m_mappings.m_classesByDeobf.put(deobfName, classMapping) == null;
57 assert( wasAdded ); 50 assert (wasAdded);
58 } 51 }
59 } 52 }
60 53
61 public void removeClassMapping( ClassEntry obf ) 54 public void removeClassMapping(ClassEntry obf) {
62 { 55 ClassMapping classMapping = getClassMapping(obf);
63 ClassMapping classMapping = getClassMapping( obf ); 56 if (obf.isInnerClass()) {
64 if( obf.isInnerClass() ) 57 classMapping.setInnerClassName(obf.getName(), null);
65 { 58 } else {
66 classMapping.setInnerClassName( obf.getName(), null ); 59 boolean wasRemoved = m_mappings.m_classesByDeobf.remove(classMapping.getDeobfName()) != null;
67 } 60 assert (wasRemoved);
68 else 61 classMapping.setDeobfName(null);
69 {
70 boolean wasRemoved = m_mappings.m_classesByDeobf.remove( classMapping.getDeobfName() ) != null;
71 assert( wasRemoved );
72 classMapping.setDeobfName( null );
73 } 62 }
74 } 63 }
75 64
76 public void markClassAsDeobfuscated( ClassEntry obf ) 65 public void markClassAsDeobfuscated(ClassEntry obf) {
77 { 66 ClassMapping classMapping = getOrCreateClassMapping(obf);
78 ClassMapping classMapping = getOrCreateClassMapping( obf ); 67 if (obf.isInnerClass()) {
79 if( obf.isInnerClass() )
80 {
81 String innerClassName = Constants.NonePackage + "/" + obf.getInnerClassName(); 68 String innerClassName = Constants.NonePackage + "/" + obf.getInnerClassName();
82 classMapping.setInnerClassName( innerClassName, innerClassName ); 69 classMapping.setInnerClassName(innerClassName, innerClassName);
83 } 70 } else {
84 else 71 classMapping.setDeobfName(obf.getName());
85 { 72 boolean wasAdded = m_mappings.m_classesByDeobf.put(obf.getName(), classMapping) == null;
86 classMapping.setDeobfName( obf.getName() ); 73 assert (wasAdded);
87 boolean wasAdded = m_mappings.m_classesByDeobf.put( obf.getName(), classMapping ) == null;
88 assert( wasAdded );
89 } 74 }
90 } 75 }
91 76
92 public void setFieldName( FieldEntry obf, String deobfName ) 77 public void setFieldName(FieldEntry obf, String deobfName) {
93 { 78 deobfName = NameValidator.validateFieldName(deobfName);
94 deobfName = NameValidator.validateFieldName( deobfName ); 79 FieldEntry targetEntry = new FieldEntry(obf.getClassEntry(), deobfName);
95 FieldEntry targetEntry = new FieldEntry( obf.getClassEntry(), deobfName ); 80 if (m_mappings.containsDeobfField(obf.getClassEntry(), deobfName) || m_index.containsObfField(targetEntry)) {
96 if( m_mappings.containsDeobfField( obf.getClassEntry(), deobfName ) || m_index.containsObfField( targetEntry ) ) 81 throw new IllegalNameException(deobfName, "There is already a field with that name");
97 {
98 throw new IllegalNameException( deobfName, "There is already a field with that name" );
99 } 82 }
100 83
101 ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping( obf.getClassEntry() ); 84 ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping(obf.getClassEntry());
102 classMapping.setFieldName( obf.getName(), deobfName ); 85 classMapping.setFieldName(obf.getName(), deobfName);
103 } 86 }
104 87
105 public void removeFieldMapping( FieldEntry obf ) 88 public void removeFieldMapping(FieldEntry obf) {
106 { 89 ClassMapping classMapping = getClassMappingOrInnerClassMapping(obf.getClassEntry());
107 ClassMapping classMapping = getClassMappingOrInnerClassMapping( obf.getClassEntry() ); 90 classMapping.setFieldName(obf.getName(), null);
108 classMapping.setFieldName( obf.getName(), null );
109 } 91 }
110 92
111 public void markFieldAsDeobfuscated( FieldEntry obf ) 93 public void markFieldAsDeobfuscated(FieldEntry obf) {
112 { 94 ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping(obf.getClassEntry());
113 ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping( obf.getClassEntry() ); 95 classMapping.setFieldName(obf.getName(), obf.getName());
114 classMapping.setFieldName( obf.getName(), obf.getName() );
115 } 96 }
116 97
117 public void setMethodTreeName( MethodEntry obf, String deobfName ) 98 public void setMethodTreeName(MethodEntry obf, String deobfName) {
118 { 99 Set<MethodEntry> implementations = m_index.getRelatedMethodImplementations(obf);
119 Set<MethodEntry> implementations = m_index.getRelatedMethodImplementations( obf );
120 100
121 deobfName = NameValidator.validateMethodName( deobfName ); 101 deobfName = NameValidator.validateMethodName(deobfName);
122 for( MethodEntry entry : implementations ) 102 for (MethodEntry entry : implementations) {
123 { 103 String deobfSignature = m_mappings.getTranslator(TranslationDirection.Deobfuscating).translateSignature(obf.getSignature());
124 String deobfSignature = m_mappings.getTranslator( TranslationDirection.Deobfuscating ).translateSignature( obf.getSignature() ); 104 MethodEntry targetEntry = new MethodEntry(entry.getClassEntry(), deobfName, deobfSignature);
125 MethodEntry targetEntry = new MethodEntry( entry.getClassEntry(), deobfName, deobfSignature ); 105 if (m_mappings.containsDeobfMethod(entry.getClassEntry(), deobfName, entry.getSignature()) || m_index.containsObfBehavior(targetEntry)) {
126 if( m_mappings.containsDeobfMethod( entry.getClassEntry(), deobfName, entry.getSignature() ) || m_index.containsObfBehavior( targetEntry ) ) 106 String deobfClassName = m_mappings.getTranslator(TranslationDirection.Deobfuscating).translateClass(entry.getClassName());
127 { 107 throw new IllegalNameException(deobfName, "There is already a method with that name and signature in class " + deobfClassName);
128 String deobfClassName = m_mappings.getTranslator( TranslationDirection.Deobfuscating ).translateClass( entry.getClassName() );
129 throw new IllegalNameException( deobfName, "There is already a method with that name and signature in class " + deobfClassName );
130 } 108 }
131 } 109 }
132 110
133 for( MethodEntry entry : implementations ) 111 for (MethodEntry entry : implementations) {
134 { 112 setMethodName(entry, deobfName);
135 setMethodName( entry, deobfName );
136 } 113 }
137 } 114 }
138 115
139 public void setMethodName( MethodEntry obf, String deobfName ) 116 public void setMethodName(MethodEntry obf, String deobfName) {
140 { 117 deobfName = NameValidator.validateMethodName(deobfName);
141 deobfName = NameValidator.validateMethodName( deobfName ); 118 MethodEntry targetEntry = new MethodEntry(obf.getClassEntry(), deobfName, obf.getSignature());
142 MethodEntry targetEntry = new MethodEntry( obf.getClassEntry(), deobfName, obf.getSignature() ); 119 if (m_mappings.containsDeobfMethod(obf.getClassEntry(), deobfName, obf.getSignature()) || m_index.containsObfBehavior(targetEntry)) {
143 if( m_mappings.containsDeobfMethod( obf.getClassEntry(), deobfName, obf.getSignature() ) || m_index.containsObfBehavior( targetEntry ) ) 120 String deobfClassName = m_mappings.getTranslator(TranslationDirection.Deobfuscating).translateClass(obf.getClassName());
144 { 121 throw new IllegalNameException(deobfName, "There is already a method with that name and signature in class " + deobfClassName);
145 String deobfClassName = m_mappings.getTranslator( TranslationDirection.Deobfuscating ).translateClass( obf.getClassName() );
146 throw new IllegalNameException( deobfName, "There is already a method with that name and signature in class " + deobfClassName );
147 } 122 }
148 123
149 ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping( obf.getClassEntry() ); 124 ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping(obf.getClassEntry());
150 classMapping.setMethodName( obf.getName(), obf.getSignature(), deobfName ); 125 classMapping.setMethodName(obf.getName(), obf.getSignature(), deobfName);
151 } 126 }
152 127
153 public void removeMethodTreeMapping( MethodEntry obf ) 128 public void removeMethodTreeMapping(MethodEntry obf) {
154 { 129 for (MethodEntry implementation : m_index.getRelatedMethodImplementations(obf)) {
155 for( MethodEntry implementation : m_index.getRelatedMethodImplementations( obf ) ) 130 removeMethodMapping(implementation);
156 {
157 removeMethodMapping( implementation );
158 } 131 }
159 } 132 }
160 133
161 public void removeMethodMapping( MethodEntry obf ) 134 public void removeMethodMapping(MethodEntry obf) {
162 { 135 ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping(obf.getClassEntry());
163 ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping( obf.getClassEntry() ); 136 classMapping.setMethodName(obf.getName(), obf.getSignature(), null);
164 classMapping.setMethodName( obf.getName(), obf.getSignature(), null );
165 } 137 }
166 138
167 public void markMethodTreeAsDeobfuscated( MethodEntry obf ) 139 public void markMethodTreeAsDeobfuscated(MethodEntry obf) {
168 { 140 for (MethodEntry implementation : m_index.getRelatedMethodImplementations(obf)) {
169 for( MethodEntry implementation : m_index.getRelatedMethodImplementations( obf ) ) 141 markMethodAsDeobfuscated(implementation);
170 {
171 markMethodAsDeobfuscated( implementation );
172 } 142 }
173 } 143 }
174 144
175 public void markMethodAsDeobfuscated( MethodEntry obf ) 145 public void markMethodAsDeobfuscated(MethodEntry obf) {
176 { 146 ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping(obf.getClassEntry());
177 ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping( obf.getClassEntry() ); 147 classMapping.setMethodName(obf.getName(), obf.getSignature(), obf.getName());
178 classMapping.setMethodName( obf.getName(), obf.getSignature(), obf.getName() );
179 } 148 }
180 149
181 public void setArgumentName( ArgumentEntry obf, String deobfName ) 150 public void setArgumentName(ArgumentEntry obf, String deobfName) {
182 { 151 deobfName = NameValidator.validateArgumentName(deobfName);
183 deobfName = NameValidator.validateArgumentName( deobfName );
184 // NOTE: don't need to check arguments for name collisions with names determined by Procyon 152 // NOTE: don't need to check arguments for name collisions with names determined by Procyon
185 if( m_mappings.containsArgument( obf.getBehaviorEntry(), deobfName ) ) 153 if (m_mappings.containsArgument(obf.getBehaviorEntry(), deobfName)) {
186 { 154 throw new IllegalNameException(deobfName, "There is already an argument with that name");
187 throw new IllegalNameException( deobfName, "There is already an argument with that name" );
188 } 155 }
189 156
190 ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping( obf.getClassEntry() ); 157 ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping(obf.getClassEntry());
191 classMapping.setArgumentName( obf.getMethodName(), obf.getMethodSignature(), obf.getIndex(), deobfName ); 158 classMapping.setArgumentName(obf.getMethodName(), obf.getMethodSignature(), obf.getIndex(), deobfName);
192 } 159 }
193 160
194 public void removeArgumentMapping( ArgumentEntry obf ) 161 public void removeArgumentMapping(ArgumentEntry obf) {
195 { 162 ClassMapping classMapping = getClassMappingOrInnerClassMapping(obf.getClassEntry());
196 ClassMapping classMapping = getClassMappingOrInnerClassMapping( obf.getClassEntry() ); 163 classMapping.removeArgumentName(obf.getMethodName(), obf.getMethodSignature(), obf.getIndex());
197 classMapping.removeArgumentName( obf.getMethodName(), obf.getMethodSignature(), obf.getIndex() );
198 } 164 }
199 165
200 public void markArgumentAsDeobfuscated( ArgumentEntry obf ) 166 public void markArgumentAsDeobfuscated(ArgumentEntry obf) {
201 { 167 ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping(obf.getClassEntry());
202 ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping( obf.getClassEntry() ); 168 classMapping.setArgumentName(obf.getMethodName(), obf.getMethodSignature(), obf.getIndex(), obf.getName());
203 classMapping.setArgumentName( obf.getMethodName(), obf.getMethodSignature(), obf.getIndex(), obf.getName() );
204 } 169 }
205 170
206 public boolean moveFieldToObfClass( ClassMapping classMapping, FieldMapping fieldMapping, ClassEntry obfClass ) 171 public boolean moveFieldToObfClass(ClassMapping classMapping, FieldMapping fieldMapping, ClassEntry obfClass) {
207 { 172 classMapping.removeFieldMapping(fieldMapping);
208 classMapping.removeFieldMapping( fieldMapping ); 173 ClassMapping targetClassMapping = getOrCreateClassMapping(obfClass);
209 ClassMapping targetClassMapping = getOrCreateClassMapping( obfClass ); 174 if (!targetClassMapping.containsObfField(fieldMapping.getObfName())) {
210 if( !targetClassMapping.containsObfField( fieldMapping.getObfName() ) ) 175 if (!targetClassMapping.containsDeobfField(fieldMapping.getDeobfName())) {
211 { 176 targetClassMapping.addFieldMapping(fieldMapping);
212 if( !targetClassMapping.containsDeobfField( fieldMapping.getDeobfName() ) )
213 {
214 targetClassMapping.addFieldMapping( fieldMapping );
215 return true; 177 return true;
216 } 178 } else {
217 else 179 System.err.println("WARNING: deobf field was already there: " + obfClass + "." + fieldMapping.getDeobfName());
218 {
219 System.err.println( "WARNING: deobf field was already there: " + obfClass + "." + fieldMapping.getDeobfName() );
220 } 180 }
221 } 181 }
222 return false; 182 return false;
223 } 183 }
224 184
225 public boolean moveMethodToObfClass( ClassMapping classMapping, MethodMapping methodMapping, ClassEntry obfClass ) 185 public boolean moveMethodToObfClass(ClassMapping classMapping, MethodMapping methodMapping, ClassEntry obfClass) {
226 { 186 classMapping.removeMethodMapping(methodMapping);
227 classMapping.removeMethodMapping( methodMapping ); 187 ClassMapping targetClassMapping = getOrCreateClassMapping(obfClass);
228 ClassMapping targetClassMapping = getOrCreateClassMapping( obfClass ); 188 if (!targetClassMapping.containsObfMethod(methodMapping.getObfName(), methodMapping.getObfSignature())) {
229 if( !targetClassMapping.containsObfMethod( methodMapping.getObfName(), methodMapping.getObfSignature() ) ) 189 if (!targetClassMapping.containsDeobfMethod(methodMapping.getDeobfName(), methodMapping.getObfSignature())) {
230 { 190 targetClassMapping.addMethodMapping(methodMapping);
231 if( !targetClassMapping.containsDeobfMethod( methodMapping.getDeobfName(), methodMapping.getObfSignature() ) )
232 {
233 targetClassMapping.addMethodMapping( methodMapping );
234 return true; 191 return true;
235 } 192 } else {
236 else 193 System.err.println("WARNING: deobf method was already there: " + obfClass + "." + methodMapping.getDeobfName() + methodMapping.getObfSignature());
237 {
238 System.err.println( "WARNING: deobf method was already there: " + obfClass + "." + methodMapping.getDeobfName() + methodMapping.getObfSignature() );
239 } 194 }
240 } 195 }
241 return false; 196 return false;
242 } 197 }
243 198
244 public void write( OutputStream out ) 199 public void write(OutputStream out) throws IOException {
245 throws IOException
246 {
247 // TEMP: just use the object output for now. We can find a more efficient storage format later 200 // TEMP: just use the object output for now. We can find a more efficient storage format later
248 GZIPOutputStream gzipout = new GZIPOutputStream( out ); 201 GZIPOutputStream gzipout = new GZIPOutputStream(out);
249 ObjectOutputStream oout = new ObjectOutputStream( gzipout ); 202 ObjectOutputStream oout = new ObjectOutputStream(gzipout);
250 oout.writeObject( this ); 203 oout.writeObject(this);
251 gzipout.finish(); 204 gzipout.finish();
252 } 205 }
253 206
254 private ClassMapping getClassMapping( ClassEntry obfClassEntry ) 207 private ClassMapping getClassMapping(ClassEntry obfClassEntry) {
255 { 208 return m_mappings.m_classesByObf.get(obfClassEntry.getOuterClassName());
256 return m_mappings.m_classesByObf.get( obfClassEntry.getOuterClassName() );
257 } 209 }
258 210
259 private ClassMapping getOrCreateClassMapping( ClassEntry obfClassEntry ) 211 private ClassMapping getOrCreateClassMapping(ClassEntry obfClassEntry) {
260 {
261 String obfClassName = obfClassEntry.getOuterClassName(); 212 String obfClassName = obfClassEntry.getOuterClassName();
262 ClassMapping classMapping = m_mappings.m_classesByObf.get( obfClassName ); 213 ClassMapping classMapping = m_mappings.m_classesByObf.get(obfClassName);
263 if( classMapping == null ) 214 if (classMapping == null) {
264 { 215 classMapping = new ClassMapping(obfClassName);
265 classMapping = new ClassMapping( obfClassName ); 216 boolean obfWasAdded = m_mappings.m_classesByObf.put(classMapping.getObfName(), classMapping) == null;
266 boolean obfWasAdded = m_mappings.m_classesByObf.put( classMapping.getObfName(), classMapping ) == null; 217 assert (obfWasAdded);
267 assert( obfWasAdded );
268 } 218 }
269 return classMapping; 219 return classMapping;
270 } 220 }
271 221
272 private ClassMapping getClassMappingOrInnerClassMapping( ClassEntry obfClassEntry ) 222 private ClassMapping getClassMappingOrInnerClassMapping(ClassEntry obfClassEntry) {
273 { 223 ClassMapping classMapping = getClassMapping(obfClassEntry);
274 ClassMapping classMapping = getClassMapping( obfClassEntry ); 224 if (obfClassEntry.isInDefaultPackage()) {
275 if( obfClassEntry.isInDefaultPackage() ) 225 classMapping = classMapping.getInnerClassByObf(obfClassEntry.getInnerClassName());
276 {
277 classMapping = classMapping.getInnerClassByObf( obfClassEntry.getInnerClassName() );
278 } 226 }
279 return classMapping; 227 return classMapping;
280 } 228 }
281 229
282 private ClassMapping getOrCreateClassMappingOrInnerClassMapping( ClassEntry obfClassEntry ) 230 private ClassMapping getOrCreateClassMappingOrInnerClassMapping(ClassEntry obfClassEntry) {
283 { 231 ClassMapping classMapping = getOrCreateClassMapping(obfClassEntry);
284 ClassMapping classMapping = getOrCreateClassMapping( obfClassEntry ); 232 if (obfClassEntry.isInnerClass()) {
285 if( obfClassEntry.isInnerClass() ) 233 classMapping = classMapping.getOrCreateInnerClass(obfClassEntry.getInnerClassName());
286 {
287 classMapping = classMapping.getOrCreateInnerClass( obfClassEntry.getInnerClassName() );
288 } 234 }
289 return classMapping; 235 return classMapping;
290 } 236 }
diff --git a/src/cuchaz/enigma/mapping/MappingsWriter.java b/src/cuchaz/enigma/mapping/MappingsWriter.java
index 3c86dfc..5ac409f 100644
--- a/src/cuchaz/enigma/mapping/MappingsWriter.java
+++ b/src/cuchaz/enigma/mapping/MappingsWriter.java
@@ -17,105 +17,71 @@ import java.util.ArrayList;
17import java.util.Collections; 17import java.util.Collections;
18import java.util.List; 18import java.util.List;
19 19
20public class MappingsWriter 20public class MappingsWriter {
21{ 21
22 public void write( Writer out, Mappings mappings ) 22 public void write(Writer out, Mappings mappings) throws IOException {
23 throws IOException 23 write(new PrintWriter(out), mappings);
24 {
25 write( new PrintWriter( out ), mappings );
26 } 24 }
27 25
28 public void write( PrintWriter out, Mappings mappings ) 26 public void write(PrintWriter out, Mappings mappings) throws IOException {
29 throws IOException 27 for (ClassMapping classMapping : sorted(mappings.classes())) {
30 { 28 write(out, classMapping, 0);
31 for( ClassMapping classMapping : sorted( mappings.classes() ) )
32 {
33 write( out, classMapping, 0 );
34 } 29 }
35 } 30 }
36 31
37 private void write( PrintWriter out, ClassMapping classMapping, int depth ) 32 private void write(PrintWriter out, ClassMapping classMapping, int depth) throws IOException {
38 throws IOException 33 if (classMapping.getDeobfName() == null) {
39 { 34 out.format("%sCLASS %s\n", getIndent(depth), classMapping.getObfName());
40 if( classMapping.getDeobfName() == null ) 35 } else {
41 { 36 out.format("%sCLASS %s %s\n", getIndent(depth), classMapping.getObfName(), classMapping.getDeobfName());
42 out.format( "%sCLASS %s\n", getIndent( depth ), classMapping.getObfName() );
43 }
44 else
45 {
46 out.format( "%sCLASS %s %s\n", getIndent( depth ), classMapping.getObfName(), classMapping.getDeobfName() );
47 } 37 }
48 38
49 for( ClassMapping innerClassMapping : sorted( classMapping.innerClasses() ) ) 39 for (ClassMapping innerClassMapping : sorted(classMapping.innerClasses())) {
50 { 40 write(out, innerClassMapping, depth + 1);
51 write( out, innerClassMapping, depth + 1 );
52 } 41 }
53 42
54 for( FieldMapping fieldMapping : sorted( classMapping.fields() ) ) 43 for (FieldMapping fieldMapping : sorted(classMapping.fields())) {
55 { 44 write(out, fieldMapping, depth + 1);
56 write( out, fieldMapping, depth + 1 );
57 } 45 }
58 46
59 for( MethodMapping methodMapping : sorted( classMapping.methods() ) ) 47 for (MethodMapping methodMapping : sorted(classMapping.methods())) {
60 { 48 write(out, methodMapping, depth + 1);
61 write( out, methodMapping, depth + 1 );
62 } 49 }
63 } 50 }
64 51
65 private void write( PrintWriter out, FieldMapping fieldMapping, int depth ) 52 private void write(PrintWriter out, FieldMapping fieldMapping, int depth) throws IOException {
66 throws IOException 53 out.format("%sFIELD %s %s\n", getIndent(depth), fieldMapping.getObfName(), fieldMapping.getDeobfName());
67 {
68 out.format( "%sFIELD %s %s\n", getIndent( depth ), fieldMapping.getObfName(), fieldMapping.getDeobfName() );
69 } 54 }
70 55
71 private void write( PrintWriter out, MethodMapping methodMapping, int depth ) 56 private void write(PrintWriter out, MethodMapping methodMapping, int depth) throws IOException {
72 throws IOException 57 if (methodMapping.getDeobfName() == null) {
73 { 58 out.format("%sMETHOD %s %s\n", getIndent(depth), methodMapping.getObfName(), methodMapping.getObfSignature());
74 if( methodMapping.getDeobfName() == null ) 59 } else {
75 { 60 out.format("%sMETHOD %s %s %s\n", getIndent(depth), methodMapping.getObfName(), methodMapping.getDeobfName(), methodMapping.getObfSignature());
76 out.format( "%sMETHOD %s %s\n",
77 getIndent( depth ),
78 methodMapping.getObfName(), methodMapping.getObfSignature()
79 );
80 }
81 else
82 {
83 out.format( "%sMETHOD %s %s %s\n",
84 getIndent( depth ),
85 methodMapping.getObfName(), methodMapping.getDeobfName(),
86 methodMapping.getObfSignature()
87 );
88 } 61 }
89 62
90 for( ArgumentMapping argumentMapping : sorted( methodMapping.arguments() ) ) 63 for (ArgumentMapping argumentMapping : sorted(methodMapping.arguments())) {
91 { 64 write(out, argumentMapping, depth + 1);
92 write( out, argumentMapping, depth + 1 );
93 } 65 }
94 } 66 }
95 67
96 private void write( PrintWriter out, ArgumentMapping argumentMapping, int depth ) 68 private void write(PrintWriter out, ArgumentMapping argumentMapping, int depth) throws IOException {
97 throws IOException 69 out.format("%sARG %d %s\n", getIndent(depth), argumentMapping.getIndex(), argumentMapping.getName());
98 {
99 out.format( "%sARG %d %s\n", getIndent( depth ), argumentMapping.getIndex(), argumentMapping.getName() );
100 } 70 }
101 71
102 private <T extends Comparable<T>> List<T> sorted( Iterable<T> classes ) 72 private <T extends Comparable<T>> List<T> sorted(Iterable<T> classes) {
103 {
104 List<T> out = new ArrayList<T>(); 73 List<T> out = new ArrayList<T>();
105 for( T t : classes ) 74 for (T t : classes) {
106 { 75 out.add(t);
107 out.add( t );
108 } 76 }
109 Collections.sort( out ); 77 Collections.sort(out);
110 return out; 78 return out;
111 } 79 }
112 80
113 private String getIndent( int depth ) 81 private String getIndent(int depth) {
114 {
115 StringBuilder buf = new StringBuilder(); 82 StringBuilder buf = new StringBuilder();
116 for( int i=0; i<depth; i++ ) 83 for (int i = 0; i < depth; i++) {
117 { 84 buf.append("\t");
118 buf.append( "\t" );
119 } 85 }
120 return buf.toString(); 86 return buf.toString();
121 } 87 }
diff --git a/src/cuchaz/enigma/mapping/MethodEntry.java b/src/cuchaz/enigma/mapping/MethodEntry.java
index dbc1885..beb490d 100644
--- a/src/cuchaz/enigma/mapping/MethodEntry.java
+++ b/src/cuchaz/enigma/mapping/MethodEntry.java
@@ -14,31 +14,26 @@ import java.io.Serializable;
14 14
15import cuchaz.enigma.Util; 15import cuchaz.enigma.Util;
16 16
17public class MethodEntry implements BehaviorEntry, Serializable 17public class MethodEntry implements BehaviorEntry, Serializable {
18{ 18
19 private static final long serialVersionUID = 4770915224467247458L; 19 private static final long serialVersionUID = 4770915224467247458L;
20 20
21 private ClassEntry m_classEntry; 21 private ClassEntry m_classEntry;
22 private String m_name; 22 private String m_name;
23 private String m_signature; 23 private String m_signature;
24 24
25 public MethodEntry( ClassEntry classEntry, String name, String signature ) 25 public MethodEntry(ClassEntry classEntry, String name, String signature) {
26 { 26 if (classEntry == null) {
27 if( classEntry == null ) 27 throw new IllegalArgumentException("Class cannot be null!");
28 {
29 throw new IllegalArgumentException( "Class cannot be null!" );
30 } 28 }
31 if( name == null ) 29 if (name == null) {
32 { 30 throw new IllegalArgumentException("Method name cannot be null!");
33 throw new IllegalArgumentException( "Method name cannot be null!" );
34 } 31 }
35 if( signature == null ) 32 if (signature == null) {
36 { 33 throw new IllegalArgumentException("Method signature cannot be null!");
37 throw new IllegalArgumentException( "Method signature cannot be null!" );
38 } 34 }
39 if( name.startsWith( "<" ) ) 35 if (name.startsWith("<")) {
40 { 36 throw new IllegalArgumentException("Don't use MethodEntry for a constructor!");
41 throw new IllegalArgumentException( "Don't use MethodEntry for a constructor!" );
42 } 37 }
43 38
44 m_classEntry = classEntry; 39 m_classEntry = classEntry;
@@ -46,76 +41,64 @@ public class MethodEntry implements BehaviorEntry, Serializable
46 m_signature = signature; 41 m_signature = signature;
47 } 42 }
48 43
49 public MethodEntry( MethodEntry other ) 44 public MethodEntry(MethodEntry other) {
50 { 45 m_classEntry = new ClassEntry(other.m_classEntry);
51 m_classEntry = new ClassEntry( other.m_classEntry );
52 m_name = other.m_name; 46 m_name = other.m_name;
53 m_signature = other.m_signature; 47 m_signature = other.m_signature;
54 } 48 }
55 49
56 public MethodEntry( MethodEntry other, String newClassName ) 50 public MethodEntry(MethodEntry other, String newClassName) {
57 { 51 m_classEntry = new ClassEntry(newClassName);
58 m_classEntry = new ClassEntry( newClassName );
59 m_name = other.m_name; 52 m_name = other.m_name;
60 m_signature = other.m_signature; 53 m_signature = other.m_signature;
61 } 54 }
62 55
63 @Override 56 @Override
64 public ClassEntry getClassEntry( ) 57 public ClassEntry getClassEntry() {
65 {
66 return m_classEntry; 58 return m_classEntry;
67 } 59 }
68 60
69 @Override 61 @Override
70 public String getName( ) 62 public String getName() {
71 {
72 return m_name; 63 return m_name;
73 } 64 }
74 65
75 @Override 66 @Override
76 public String getSignature( ) 67 public String getSignature() {
77 {
78 return m_signature; 68 return m_signature;
79 } 69 }
80 70
81 @Override 71 @Override
82 public String getClassName( ) 72 public String getClassName() {
83 {
84 return m_classEntry.getName(); 73 return m_classEntry.getName();
85 } 74 }
86 75
87 @Override 76 @Override
88 public MethodEntry cloneToNewClass( ClassEntry classEntry ) 77 public MethodEntry cloneToNewClass(ClassEntry classEntry) {
89 { 78 return new MethodEntry(this, classEntry.getName());
90 return new MethodEntry( this, classEntry.getName() );
91 } 79 }
92 80
93 @Override 81 @Override
94 public int hashCode( ) 82 public int hashCode() {
95 { 83 return Util.combineHashesOrdered(m_classEntry, m_name, m_signature);
96 return Util.combineHashesOrdered( m_classEntry, m_name, m_signature );
97 } 84 }
98 85
99 @Override 86 @Override
100 public boolean equals( Object other ) 87 public boolean equals(Object other) {
101 { 88 if (other instanceof MethodEntry) {
102 if( other instanceof MethodEntry ) 89 return equals((MethodEntry)other);
103 {
104 return equals( (MethodEntry)other );
105 } 90 }
106 return false; 91 return false;
107 } 92 }
108 93
109 public boolean equals( MethodEntry other ) 94 public boolean equals(MethodEntry other) {
110 { 95 return m_classEntry.equals(other.m_classEntry)
111 return m_classEntry.equals( other.m_classEntry ) 96 && m_name.equals(other.m_name)
112 && m_name.equals( other.m_name ) 97 && m_signature.equals(other.m_signature);
113 && m_signature.equals( other.m_signature );
114 } 98 }
115 99
116 @Override 100 @Override
117 public String toString( ) 101 public String toString() {
118 {
119 return m_classEntry.getName() + "." + m_name + m_signature; 102 return m_classEntry.getName() + "." + m_name + m_signature;
120 } 103 }
121} 104}
diff --git a/src/cuchaz/enigma/mapping/MethodMapping.java b/src/cuchaz/enigma/mapping/MethodMapping.java
index c51b011..4dab3c6 100644
--- a/src/cuchaz/enigma/mapping/MethodMapping.java
+++ b/src/cuchaz/enigma/mapping/MethodMapping.java
@@ -16,8 +16,8 @@ import java.util.TreeMap;
16 16
17import cuchaz.enigma.mapping.SignatureUpdater.ClassNameUpdater; 17import cuchaz.enigma.mapping.SignatureUpdater.ClassNameUpdater;
18 18
19public class MethodMapping implements Serializable, Comparable<MethodMapping> 19public class MethodMapping implements Serializable, Comparable<MethodMapping> {
20{ 20
21 private static final long serialVersionUID = -4409570216084263978L; 21 private static final long serialVersionUID = -4409570216084263978L;
22 22
23 private String m_obfName; 23 private String m_obfName;
@@ -25,165 +25,135 @@ public class MethodMapping implements Serializable, Comparable<MethodMapping>
25 private String m_obfSignature; 25 private String m_obfSignature;
26 private Map<Integer,ArgumentMapping> m_arguments; 26 private Map<Integer,ArgumentMapping> m_arguments;
27 27
28 public MethodMapping( String obfName, String obfSignature ) 28 public MethodMapping(String obfName, String obfSignature) {
29 { 29 this(obfName, obfSignature, null);
30 this( obfName, obfSignature, null );
31 } 30 }
32 31
33 public MethodMapping( String obfName, String obfSignature, String deobfName ) 32 public MethodMapping(String obfName, String obfSignature, String deobfName) {
34 { 33 if (obfName == null) {
35 if( obfName == null ) 34 throw new IllegalArgumentException("obf name cannot be null!");
36 {
37 throw new IllegalArgumentException( "obf name cannot be null!" );
38 } 35 }
39 if( obfSignature == null ) 36 if (obfSignature == null) {
40 { 37 throw new IllegalArgumentException("obf signature cannot be null!");
41 throw new IllegalArgumentException( "obf signature cannot be null!" );
42 } 38 }
43 m_obfName = obfName; 39 m_obfName = obfName;
44 m_deobfName = NameValidator.validateMethodName( deobfName ); 40 m_deobfName = NameValidator.validateMethodName(deobfName);
45 m_obfSignature = obfSignature; 41 m_obfSignature = obfSignature;
46 m_arguments = new TreeMap<Integer,ArgumentMapping>(); 42 m_arguments = new TreeMap<Integer,ArgumentMapping>();
47 } 43 }
48 44
49 public String getObfName( ) 45 public String getObfName() {
50 {
51 return m_obfName; 46 return m_obfName;
52 } 47 }
53 48
54 public String getDeobfName( ) 49 public String getDeobfName() {
55 {
56 return m_deobfName; 50 return m_deobfName;
57 } 51 }
58 public void setDeobfName( String val ) 52
59 { 53 public void setDeobfName(String val) {
60 m_deobfName = NameValidator.validateMethodName( val ); 54 m_deobfName = NameValidator.validateMethodName(val);
61 } 55 }
62 56
63 public String getObfSignature( ) 57 public String getObfSignature() {
64 {
65 return m_obfSignature; 58 return m_obfSignature;
66 } 59 }
67 60
68 public Iterable<ArgumentMapping> arguments( ) 61 public Iterable<ArgumentMapping> arguments() {
69 {
70 return m_arguments.values(); 62 return m_arguments.values();
71 } 63 }
72 64
73 public boolean isConstructor( ) 65 public boolean isConstructor() {
74 { 66 return m_obfName.startsWith("<");
75 return m_obfName.startsWith( "<" );
76 } 67 }
77 68
78 public void addArgumentMapping( ArgumentMapping argumentMapping ) 69 public void addArgumentMapping(ArgumentMapping argumentMapping) {
79 { 70 boolean wasAdded = m_arguments.put(argumentMapping.getIndex(), argumentMapping) == null;
80 boolean wasAdded = m_arguments.put( argumentMapping.getIndex(), argumentMapping ) == null; 71 assert (wasAdded);
81 assert( wasAdded );
82 } 72 }
83 73
84 public String getObfArgumentName( int index ) 74 public String getObfArgumentName(int index) {
85 { 75 ArgumentMapping argumentMapping = m_arguments.get(index);
86 ArgumentMapping argumentMapping = m_arguments.get( index ); 76 if (argumentMapping != null) {
87 if( argumentMapping != null )
88 {
89 return argumentMapping.getName(); 77 return argumentMapping.getName();
90 } 78 }
91 79
92 return null; 80 return null;
93 } 81 }
94 82
95 public String getDeobfArgumentName( int index ) 83 public String getDeobfArgumentName(int index) {
96 { 84 ArgumentMapping argumentMapping = m_arguments.get(index);
97 ArgumentMapping argumentMapping = m_arguments.get( index ); 85 if (argumentMapping != null) {
98 if( argumentMapping != null )
99 {
100 return argumentMapping.getName(); 86 return argumentMapping.getName();
101 } 87 }
102 88
103 return null; 89 return null;
104 } 90 }
105 91
106 public void setArgumentName( int index, String name ) 92 public void setArgumentName(int index, String name) {
107 { 93 ArgumentMapping argumentMapping = m_arguments.get(index);
108 ArgumentMapping argumentMapping = m_arguments.get( index ); 94 if (argumentMapping == null) {
109 if( argumentMapping == null ) 95 argumentMapping = new ArgumentMapping(index, name);
110 { 96 boolean wasAdded = m_arguments.put(index, argumentMapping) == null;
111 argumentMapping = new ArgumentMapping( index, name ); 97 assert (wasAdded);
112 boolean wasAdded = m_arguments.put( index, argumentMapping ) == null; 98 } else {
113 assert( wasAdded ); 99 argumentMapping.setName(name);
114 }
115 else
116 {
117 argumentMapping.setName( name );
118 } 100 }
119 } 101 }
120 102
121 public void removeArgumentName( int index ) 103 public void removeArgumentName(int index) {
122 { 104 boolean wasRemoved = m_arguments.remove(index) != null;
123 boolean wasRemoved = m_arguments.remove( index ) != null; 105 assert (wasRemoved);
124 assert( wasRemoved );
125 } 106 }
126 107
127 @Override 108 @Override
128 public String toString( ) 109 public String toString() {
129 {
130 StringBuilder buf = new StringBuilder(); 110 StringBuilder buf = new StringBuilder();
131 buf.append( "\t" ); 111 buf.append("\t");
132 buf.append( m_obfName ); 112 buf.append(m_obfName);
133 buf.append( " <-> " ); 113 buf.append(" <-> ");
134 buf.append( m_deobfName ); 114 buf.append(m_deobfName);
135 buf.append( "\n" ); 115 buf.append("\n");
136 buf.append( "\t" ); 116 buf.append("\t");
137 buf.append( m_obfSignature ); 117 buf.append(m_obfSignature);
138 buf.append( "\n" ); 118 buf.append("\n");
139 buf.append( "\tArguments:\n" ); 119 buf.append("\tArguments:\n");
140 for( ArgumentMapping argumentMapping : m_arguments.values() ) 120 for (ArgumentMapping argumentMapping : m_arguments.values()) {
141 { 121 buf.append("\t\t");
142 buf.append( "\t\t" ); 122 buf.append(argumentMapping.getIndex());
143 buf.append( argumentMapping.getIndex() ); 123 buf.append(" -> ");
144 buf.append( " -> " ); 124 buf.append(argumentMapping.getName());
145 buf.append( argumentMapping.getName() ); 125 buf.append("\n");
146 buf.append( "\n" );
147 } 126 }
148 return buf.toString(); 127 return buf.toString();
149 } 128 }
150 129
151 @Override 130 @Override
152 public int compareTo( MethodMapping other ) 131 public int compareTo(MethodMapping other) {
153 { 132 return (m_obfName + m_obfSignature).compareTo(other.m_obfName + other.m_obfSignature);
154 return ( m_obfName + m_obfSignature ).compareTo( other.m_obfName + other.m_obfSignature );
155 } 133 }
156 134
157 public boolean renameObfClass( final String oldObfClassName, final String newObfClassName ) 135 public boolean renameObfClass(final String oldObfClassName, final String newObfClassName) {
158 {
159 // rename obf classes in the signature 136 // rename obf classes in the signature
160 String newSignature = SignatureUpdater.update( m_obfSignature, new ClassNameUpdater( ) 137 String newSignature = SignatureUpdater.update(m_obfSignature, new ClassNameUpdater() {
161 {
162 @Override 138 @Override
163 public String update( String className ) 139 public String update(String className) {
164 { 140 if (className.equals(oldObfClassName)) {
165 if( className.equals( oldObfClassName ) )
166 {
167 return newObfClassName; 141 return newObfClassName;
168 } 142 }
169 return className; 143 return className;
170 } 144 }
171 } ); 145 });
172 146
173 if( newSignature != m_obfSignature ) 147 if (newSignature != m_obfSignature) {
174 {
175 m_obfSignature = newSignature; 148 m_obfSignature = newSignature;
176 return true; 149 return true;
177 } 150 }
178 return false; 151 return false;
179 } 152 }
180 153
181 public boolean containsArgument( String name ) 154 public boolean containsArgument(String name) {
182 { 155 for (ArgumentMapping argumentMapping : m_arguments.values()) {
183 for( ArgumentMapping argumentMapping : m_arguments.values() ) 156 if (argumentMapping.getName().equals(name)) {
184 {
185 if( argumentMapping.getName().equals( name ) )
186 {
187 return true; 157 return true;
188 } 158 }
189 } 159 }
diff --git a/src/cuchaz/enigma/mapping/NameValidator.java b/src/cuchaz/enigma/mapping/NameValidator.java
index c6ae596..35a17f9 100644
--- a/src/cuchaz/enigma/mapping/NameValidator.java
+++ b/src/cuchaz/enigma/mapping/NameValidator.java
@@ -16,82 +16,65 @@ import java.util.regex.Pattern;
16 16
17import javassist.bytecode.Descriptor; 17import javassist.bytecode.Descriptor;
18 18
19public class NameValidator 19public class NameValidator {
20{ 20
21 private static final Pattern IdentifierPattern; 21 private static final Pattern IdentifierPattern;
22 private static final Pattern ClassPattern; 22 private static final Pattern ClassPattern;
23 private static final List<String> ReservedWords = Arrays.asList( 23 private static final List<String> ReservedWords = Arrays.asList(
24 "abstract", "continue", "for", "new", "switch", 24 "abstract", "continue", "for", "new", "switch", "assert", "default", "goto", "package", "synchronized",
25 "assert", "default", "goto", "package", "synchronized", 25 "boolean", "do", "if", "private", "this", "break", "double", "implements", "protected", "throw", "byte",
26 "boolean", "do", "if", "private", "this", 26 "else", "import", "public", "throws", "case", "enum", "instanceof", "return", "transient", "catch",
27 "break", "double", "implements", "protected", "throw", 27 "extends", "int", "short", "try", "char", "final", "interface", "static", "void", "class", "finally",
28 "byte", "else", "import", "public", "throws", 28 "long", "strictfp", "volatile", "const", "float", "native", "super", "while"
29 "case", "enum", "instanceof", "return", "transient",
30 "catch", "extends", "int", "short", "try",
31 "char", "final", "interface", "static", "void",
32 "class", "finally", "long", "strictfp", "volatile",
33 "const", "float", "native", "super", "while"
34 ); 29 );
35 30
36 static 31 static {
37 { 32
38 // java allows all kinds of weird characters... 33 // java allows all kinds of weird characters...
39 StringBuilder startChars = new StringBuilder(); 34 StringBuilder startChars = new StringBuilder();
40 StringBuilder partChars = new StringBuilder(); 35 StringBuilder partChars = new StringBuilder();
41 for( int i = Character.MIN_CODE_POINT; i <= Character.MAX_CODE_POINT; i++ ) 36 for (int i = Character.MIN_CODE_POINT; i <= Character.MAX_CODE_POINT; i++) {
42 { 37 if (Character.isJavaIdentifierStart(i)) {
43 if( Character.isJavaIdentifierStart( i ) ) 38 startChars.appendCodePoint(i);
44 {
45 startChars.appendCodePoint( i );
46 } 39 }
47 if( Character.isJavaIdentifierPart( i ) ) 40 if (Character.isJavaIdentifierPart(i)) {
48 { 41 partChars.appendCodePoint(i);
49 partChars.appendCodePoint( i );
50 } 42 }
51 } 43 }
52 44
53 String identifierRegex = "[A-Za-z_<][A-Za-z0-9_>]*"; 45 String identifierRegex = "[A-Za-z_<][A-Za-z0-9_>]*";
54 IdentifierPattern = Pattern.compile( identifierRegex ); 46 IdentifierPattern = Pattern.compile(identifierRegex);
55 ClassPattern = Pattern.compile( String.format( "^(%s(\\.|/))*(%s)$", identifierRegex, identifierRegex ) ); 47 ClassPattern = Pattern.compile(String.format("^(%s(\\.|/))*(%s)$", identifierRegex, identifierRegex));
56 } 48 }
57 49
58 public static String validateClassName( String name, boolean packageRequired ) 50 public static String validateClassName(String name, boolean packageRequired) {
59 { 51 if (name == null) {
60 if( name == null )
61 {
62 return null; 52 return null;
63 } 53 }
64 if( !ClassPattern.matcher( name ).matches() || ReservedWords.contains( name ) ) 54 if (!ClassPattern.matcher(name).matches() || ReservedWords.contains(name)) {
65 { 55 throw new IllegalNameException(name, "This doesn't look like a legal class name");
66 throw new IllegalNameException( name, "This doesn't look like a legal class name" );
67 } 56 }
68 if( packageRequired && new ClassEntry( name ).getPackageName() == null ) 57 if (packageRequired && new ClassEntry(name).getPackageName() == null) {
69 { 58 throw new IllegalNameException(name, "Class must be in a package");
70 throw new IllegalNameException( name, "Class must be in a package" );
71 } 59 }
72 return Descriptor.toJvmName( name ); 60 return Descriptor.toJvmName(name);
73 } 61 }
74 62
75 public static String validateFieldName( String name ) 63 public static String validateFieldName(String name) {
76 { 64 if (name == null) {
77 if( name == null )
78 {
79 return null; 65 return null;
80 } 66 }
81 if( !IdentifierPattern.matcher( name ).matches() || ReservedWords.contains( name ) ) 67 if (!IdentifierPattern.matcher(name).matches() || ReservedWords.contains(name)) {
82 { 68 throw new IllegalNameException(name, "This doesn't look like a legal identifier");
83 throw new IllegalNameException( name, "This doesn't look like a legal identifier" );
84 } 69 }
85 return name; 70 return name;
86 } 71 }
87 72
88 public static String validateMethodName( String name ) 73 public static String validateMethodName(String name) {
89 { 74 return validateFieldName(name);
90 return validateFieldName( name );
91 } 75 }
92 76
93 public static String validateArgumentName( String name ) 77 public static String validateArgumentName(String name) {
94 { 78 return validateFieldName(name);
95 return validateFieldName( name );
96 } 79 }
97} 80}
diff --git a/src/cuchaz/enigma/mapping/SignatureUpdater.java b/src/cuchaz/enigma/mapping/SignatureUpdater.java
index 809473e..3477cd5 100644
--- a/src/cuchaz/enigma/mapping/SignatureUpdater.java
+++ b/src/cuchaz/enigma/mapping/SignatureUpdater.java
@@ -16,84 +16,63 @@ import java.util.List;
16 16
17import com.google.common.collect.Lists; 17import com.google.common.collect.Lists;
18 18
19public class SignatureUpdater 19public class SignatureUpdater {
20{ 20
21 public interface ClassNameUpdater 21 public interface ClassNameUpdater {
22 { 22 String update(String className);
23 String update( String className );
24 } 23 }
25 24
26 public static String update( String signature, ClassNameUpdater updater ) 25 public static String update(String signature, ClassNameUpdater updater) {
27 { 26 try {
28 try
29 {
30 StringBuilder buf = new StringBuilder(); 27 StringBuilder buf = new StringBuilder();
31 28
32 // read the signature character-by-character 29 // read the signature character-by-character
33 StringReader reader = new StringReader( signature ); 30 StringReader reader = new StringReader(signature);
34 int i = -1; 31 int i = -1;
35 while( ( i = reader.read() ) != -1 ) 32 while ( (i = reader.read()) != -1) {
36 {
37 char c = (char)i; 33 char c = (char)i;
38 34
39 // does this character start a class name? 35 // does this character start a class name?
40 if( c == 'L' ) 36 if (c == 'L') {
41 {
42 // update the class name and add it to the buffer 37 // update the class name and add it to the buffer
43 buf.append( 'L' ); 38 buf.append('L');
44 String className = readClass( reader ); 39 String className = readClass(reader);
45 if( className == null ) 40 if (className == null) {
46 { 41 throw new IllegalArgumentException("Malformed signature: " + signature);
47 throw new IllegalArgumentException( "Malformed signature: " + signature );
48 } 42 }
49 buf.append( updater.update( className ) ); 43 buf.append(updater.update(className));
50 buf.append( ';' ); 44 buf.append(';');
51 } 45 } else {
52 else
53 {
54 // copy the character into the buffer 46 // copy the character into the buffer
55 buf.append( c ); 47 buf.append(c);
56 } 48 }
57 } 49 }
58 50
59 return buf.toString(); 51 return buf.toString();
60 } 52 } catch (IOException ex) {
61 catch( IOException ex )
62 {
63 // I'm pretty sure a StringReader will never throw one of these 53 // I'm pretty sure a StringReader will never throw one of these
64 throw new Error( ex ); 54 throw new Error(ex);
65 } 55 }
66 } 56 }
67 57
68 private static String readClass( StringReader reader ) 58 private static String readClass(StringReader reader) throws IOException {
69 throws IOException
70 {
71 // read all the characters in the buffer until we hit a ';' 59 // read all the characters in the buffer until we hit a ';'
72 // remember to treat generics correctly 60 // remember to treat generics correctly
73 StringBuilder buf = new StringBuilder(); 61 StringBuilder buf = new StringBuilder();
74 int depth = 0; 62 int depth = 0;
75 int i = -1; 63 int i = -1;
76 while( ( i = reader.read() ) != -1 ) 64 while ( (i = reader.read()) != -1) {
77 {
78 char c = (char)i; 65 char c = (char)i;
79 66
80 if( c == '<' ) 67 if (c == '<') {
81 {
82 depth++; 68 depth++;
83 } 69 } else if (c == '>') {
84 else if( c == '>' )
85 {
86 depth--; 70 depth--;
87 } 71 } else if (depth == 0) {
88 else if( depth == 0 ) 72 if (c == ';') {
89 {
90 if( c == ';' )
91 {
92 return buf.toString(); 73 return buf.toString();
93 } 74 } else {
94 else 75 buf.append(c);
95 {
96 buf.append( c );
97 } 76 }
98 } 77 }
99 } 78 }
@@ -101,18 +80,15 @@ public class SignatureUpdater
101 return null; 80 return null;
102 } 81 }
103 82
104 public static List<String> getClasses( String signature ) 83 public static List<String> getClasses(String signature) {
105 {
106 final List<String> classNames = Lists.newArrayList(); 84 final List<String> classNames = Lists.newArrayList();
107 update( signature, new ClassNameUpdater( ) 85 update(signature, new ClassNameUpdater() {
108 {
109 @Override 86 @Override
110 public String update( String className ) 87 public String update(String className) {
111 { 88 classNames.add(className);
112 classNames.add( className );
113 return className; 89 return className;
114 } 90 }
115 } ); 91 });
116 return classNames; 92 return classNames;
117 } 93 }
118} 94}
diff --git a/src/cuchaz/enigma/mapping/TranslationDirection.java b/src/cuchaz/enigma/mapping/TranslationDirection.java
index 79ae0d3..d1b14cd 100644
--- a/src/cuchaz/enigma/mapping/TranslationDirection.java
+++ b/src/cuchaz/enigma/mapping/TranslationDirection.java
@@ -10,25 +10,20 @@
10 ******************************************************************************/ 10 ******************************************************************************/
11package cuchaz.enigma.mapping; 11package cuchaz.enigma.mapping;
12 12
13 13public enum TranslationDirection {
14public enum TranslationDirection 14
15{ 15 Deobfuscating {
16 Deobfuscating
17 {
18 @Override 16 @Override
19 public <T> T choose( T deobfChoice, T obfChoice ) 17 public <T> T choose(T deobfChoice, T obfChoice) {
20 {
21 return deobfChoice; 18 return deobfChoice;
22 } 19 }
23 }, 20 },
24 Obfuscating 21 Obfuscating {
25 {
26 @Override 22 @Override
27 public <T> T choose( T deobfChoice, T obfChoice ) 23 public <T> T choose(T deobfChoice, T obfChoice) {
28 {
29 return obfChoice; 24 return obfChoice;
30 } 25 }
31 }; 26 };
32 27
33 public abstract <T> T choose( T deobfChoice, T obfChoice ); 28 public abstract <T> T choose(T deobfChoice, T obfChoice);
34} 29}
diff --git a/src/cuchaz/enigma/mapping/Translator.java b/src/cuchaz/enigma/mapping/Translator.java
index 6cb5240..d8d9f48 100644
--- a/src/cuchaz/enigma/mapping/Translator.java
+++ b/src/cuchaz/enigma/mapping/Translator.java
@@ -16,277 +16,203 @@ import com.google.common.collect.Maps;
16 16
17import cuchaz.enigma.mapping.SignatureUpdater.ClassNameUpdater; 17import cuchaz.enigma.mapping.SignatureUpdater.ClassNameUpdater;
18 18
19public class Translator 19public class Translator {
20{ 20
21 private TranslationDirection m_direction; 21 private TranslationDirection m_direction;
22 private Map<String,ClassMapping> m_classes; 22 private Map<String,ClassMapping> m_classes;
23 23
24 public Translator( ) 24 public Translator() {
25 {
26 m_direction = null; 25 m_direction = null;
27 m_classes = Maps.newHashMap(); 26 m_classes = Maps.newHashMap();
28 } 27 }
29 28
30 public Translator( TranslationDirection direction, Map<String,ClassMapping> classes ) 29 public Translator(TranslationDirection direction, Map<String,ClassMapping> classes) {
31 {
32 m_direction = direction; 30 m_direction = direction;
33 m_classes = classes; 31 m_classes = classes;
34 } 32 }
35 33
36 @SuppressWarnings( "unchecked" ) 34 @SuppressWarnings("unchecked")
37 public <T extends Entry> T translateEntry( T entry ) 35 public <T extends Entry> T translateEntry(T entry) {
38 { 36 if (entry instanceof ClassEntry) {
39 if( entry instanceof ClassEntry ) 37 return (T)translateEntry((ClassEntry)entry);
40 { 38 } else if (entry instanceof FieldEntry) {
41 return (T)translateEntry( (ClassEntry)entry ); 39 return (T)translateEntry((FieldEntry)entry);
42 } 40 } else if (entry instanceof MethodEntry) {
43 else if( entry instanceof FieldEntry ) 41 return (T)translateEntry((MethodEntry)entry);
44 { 42 } else if (entry instanceof ConstructorEntry) {
45 return (T)translateEntry( (FieldEntry)entry ); 43 return (T)translateEntry((ConstructorEntry)entry);
46 } 44 } else if (entry instanceof ArgumentEntry) {
47 else if( entry instanceof MethodEntry ) 45 return (T)translateEntry((ArgumentEntry)entry);
48 { 46 } else {
49 return (T)translateEntry( (MethodEntry)entry ); 47 throw new Error("Unknown entry type: " + entry.getClass().getName());
50 }
51 else if( entry instanceof ConstructorEntry )
52 {
53 return (T)translateEntry( (ConstructorEntry)entry );
54 }
55 else if( entry instanceof ArgumentEntry )
56 {
57 return (T)translateEntry( (ArgumentEntry)entry );
58 }
59 else
60 {
61 throw new Error( "Unknown entry type: " + entry.getClass().getName() );
62 } 48 }
63 } 49 }
64 50
65 public String translateClass( String className ) 51 public String translateClass(String className) {
66 { 52 return translate(new ClassEntry(className));
67 return translate( new ClassEntry( className ) );
68 } 53 }
69 54
70 public String translate( ClassEntry in ) 55 public String translate(ClassEntry in) {
71 { 56 ClassMapping classMapping = m_classes.get(in.getOuterClassName());
72 ClassMapping classMapping = m_classes.get( in.getOuterClassName() ); 57 if (classMapping != null) {
73 if( classMapping != null ) 58 if (in.isInnerClass()) {
74 {
75 if( in.isInnerClass() )
76 {
77 // translate the inner class 59 // translate the inner class
78 String translatedInnerClassName = m_direction.choose( 60 String translatedInnerClassName = m_direction.choose(
79 classMapping.getDeobfInnerClassName( in.getInnerClassName() ), 61 classMapping.getDeobfInnerClassName(in.getInnerClassName()),
80 classMapping.getObfInnerClassName( in.getInnerClassName() ) 62 classMapping.getObfInnerClassName(in.getInnerClassName())
81 ); 63 );
82 if( translatedInnerClassName != null ) 64 if (translatedInnerClassName != null) {
83 {
84 // try to translate the outer name 65 // try to translate the outer name
85 String translatedOuterClassName = m_direction.choose( 66 String translatedOuterClassName = m_direction.choose(classMapping.getDeobfName(), classMapping.getObfName());
86 classMapping.getDeobfName(), 67 if (translatedOuterClassName != null) {
87 classMapping.getObfName()
88 );
89 if( translatedOuterClassName != null )
90 {
91 return translatedOuterClassName + "$" + translatedInnerClassName; 68 return translatedOuterClassName + "$" + translatedInnerClassName;
92 } 69 } else {
93 else
94 {
95 return in.getOuterClassName() + "$" + translatedInnerClassName; 70 return in.getOuterClassName() + "$" + translatedInnerClassName;
96 } 71 }
97 } 72 }
98 } 73 } else {
99 else
100 {
101 // just return outer 74 // just return outer
102 return m_direction.choose( 75 return m_direction.choose(classMapping.getDeobfName(), classMapping.getObfName());
103 classMapping.getDeobfName(),
104 classMapping.getObfName()
105 );
106 } 76 }
107 } 77 }
108 return null; 78 return null;
109 } 79 }
110 80
111 public ClassEntry translateEntry( ClassEntry in ) 81 public ClassEntry translateEntry(ClassEntry in) {
112 { 82
113 // can we translate the inner class? 83 // can we translate the inner class?
114 String name = translate( in ); 84 String name = translate(in);
115 if( name != null ) 85 if (name != null) {
116 { 86 return new ClassEntry(name);
117 return new ClassEntry( name );
118 } 87 }
119 88
120 if( in.isInnerClass() ) 89 if (in.isInnerClass()) {
121 { 90
122 // guess not. just translate the outer class name then 91 // guess not. just translate the outer class name then
123 String outerClassName = translate( in.getOuterClassEntry() ); 92 String outerClassName = translate(in.getOuterClassEntry());
124 if( outerClassName != null ) 93 if (outerClassName != null) {
125 { 94 return new ClassEntry(outerClassName + "$" + in.getInnerClassName());
126 return new ClassEntry( outerClassName + "$" + in.getInnerClassName() );
127 } 95 }
128 } 96 }
129 97
130 return in; 98 return in;
131 } 99 }
132 100
133 public String translate( FieldEntry in ) 101 public String translate(FieldEntry in) {
134 { 102
135 // look for the class 103 // look for the class
136 ClassMapping classMapping = findClassMapping( in.getClassEntry() ); 104 ClassMapping classMapping = findClassMapping(in.getClassEntry());
137 if( classMapping != null ) 105 if (classMapping != null) {
138 { 106
139 // look for the field 107 // look for the field
140 String translatedName = m_direction.choose( 108 String translatedName = m_direction.choose(
141 classMapping.getDeobfFieldName( in.getName() ), 109 classMapping.getDeobfFieldName(in.getName()),
142 classMapping.getObfFieldName( in.getName() ) 110 classMapping.getObfFieldName(in.getName())
143 ); 111 );
144 if( translatedName != null ) 112 if (translatedName != null) {
145 {
146 return translatedName; 113 return translatedName;
147 } 114 }
148 } 115 }
149 return null; 116 return null;
150 } 117 }
151 118
152 public FieldEntry translateEntry( FieldEntry in ) 119 public FieldEntry translateEntry(FieldEntry in) {
153 { 120 String name = translate(in);
154 String name = translate( in ); 121 if (name == null) {
155 if( name == null )
156 {
157 name = in.getName(); 122 name = in.getName();
158 } 123 }
159 return new FieldEntry( 124 return new FieldEntry(translateEntry(in.getClassEntry()), name);
160 translateEntry( in.getClassEntry() ),
161 name
162 );
163 } 125 }
164 126
165 public String translate( MethodEntry in ) 127 public String translate(MethodEntry in) {
166 { 128
167 // look for class 129 // look for class
168 ClassMapping classMapping = findClassMapping( in.getClassEntry() ); 130 ClassMapping classMapping = findClassMapping(in.getClassEntry());
169 if( classMapping != null ) 131 if (classMapping != null) {
170 { 132
171 // look for the method 133 // look for the method
172 MethodMapping methodMapping = m_direction.choose( 134 MethodMapping methodMapping = m_direction.choose(classMapping.getMethodByObf(in.getName(), in.getSignature()),
173 classMapping.getMethodByObf( in.getName(), in.getSignature() ), 135 classMapping.getMethodByDeobf(in.getName(), translateSignature(in.getSignature())));
174 classMapping.getMethodByDeobf( in.getName(), translateSignature( in.getSignature() ) ) 136 if (methodMapping != null) {
175 ); 137 return m_direction.choose(methodMapping.getDeobfName(), methodMapping.getObfName());
176 if( methodMapping != null )
177 {
178 return m_direction.choose(
179 methodMapping.getDeobfName(),
180 methodMapping.getObfName()
181 );
182 } 138 }
183 } 139 }
184 return null; 140 return null;
185 } 141 }
186 142
187 public MethodEntry translateEntry( MethodEntry in ) 143 public MethodEntry translateEntry(MethodEntry in) {
188 { 144 String name = translate(in);
189 String name = translate( in ); 145 if (name == null) {
190 if( name == null )
191 {
192 name = in.getName(); 146 name = in.getName();
193 } 147 }
194 return new MethodEntry( 148 return new MethodEntry(translateEntry(in.getClassEntry()), name, translateSignature(in.getSignature()));
195 translateEntry( in.getClassEntry() ),
196 name,
197 translateSignature( in.getSignature() )
198 );
199 } 149 }
200 150
201 public ConstructorEntry translateEntry( ConstructorEntry in ) 151 public ConstructorEntry translateEntry(ConstructorEntry in) {
202 { 152 if (in.isStatic()) {
203 if( in.isStatic() ) 153 return new ConstructorEntry(translateEntry(in.getClassEntry()));
204 { 154 } else {
205 return new ConstructorEntry( translateEntry( in.getClassEntry() ) ); 155 return new ConstructorEntry(translateEntry(in.getClassEntry()), translateSignature(in.getSignature()));
206 }
207 else
208 {
209 return new ConstructorEntry(
210 translateEntry( in.getClassEntry() ),
211 translateSignature( in.getSignature() )
212 );
213 } 156 }
214 } 157 }
215 158
216 public BehaviorEntry translateEntry( BehaviorEntry in ) 159 public BehaviorEntry translateEntry(BehaviorEntry in) {
217 { 160 if (in instanceof MethodEntry) {
218 if( in instanceof MethodEntry ) 161 return translateEntry((MethodEntry)in);
219 { 162 } else if (in instanceof ConstructorEntry) {
220 return translateEntry( (MethodEntry)in ); 163 return translateEntry((ConstructorEntry)in);
221 } 164 }
222 else if( in instanceof ConstructorEntry ) 165 throw new Error("Wrong entry type!");
223 {
224 return translateEntry( (ConstructorEntry)in );
225 }
226 throw new Error( "Wrong entry type!" );
227 } 166 }
228 167
229 public String translate( ArgumentEntry in ) 168 public String translate(ArgumentEntry in) {
230 { 169
231 // look for the class 170 // look for the class
232 ClassMapping classMapping = findClassMapping( in.getClassEntry() ); 171 ClassMapping classMapping = findClassMapping(in.getClassEntry());
233 if( classMapping != null ) 172 if (classMapping != null) {
234 { 173
235 // look for the method 174 // look for the method
236 MethodMapping methodMapping = m_direction.choose( 175 MethodMapping methodMapping = m_direction.choose(
237 classMapping.getMethodByObf( in.getMethodName(), in.getMethodSignature() ), 176 classMapping.getMethodByObf(in.getMethodName(), in.getMethodSignature()),
238 classMapping.getMethodByDeobf( in.getMethodName(), translateSignature( in.getMethodSignature() ) ) 177 classMapping.getMethodByDeobf(in.getMethodName(), translateSignature(in.getMethodSignature()))
239 ); 178 );
240 if( methodMapping != null ) 179 if (methodMapping != null) {
241 {
242 return m_direction.choose( 180 return m_direction.choose(
243 methodMapping.getDeobfArgumentName( in.getIndex() ), 181 methodMapping.getDeobfArgumentName(in.getIndex()),
244 methodMapping.getObfArgumentName( in.getIndex() ) 182 methodMapping.getObfArgumentName(in.getIndex())
245 ); 183 );
246 } 184 }
247 } 185 }
248 return null; 186 return null;
249 } 187 }
250 188
251 public ArgumentEntry translateEntry( ArgumentEntry in ) 189 public ArgumentEntry translateEntry(ArgumentEntry in) {
252 { 190 String name = translate(in);
253 String name = translate( in ); 191 if (name == null) {
254 if( name == null )
255 {
256 name = in.getName(); 192 name = in.getName();
257 } 193 }
258 return new ArgumentEntry( 194 return new ArgumentEntry(translateEntry(in.getBehaviorEntry()), in.getIndex(), name);
259 translateEntry( in.getBehaviorEntry() ),
260 in.getIndex(),
261 name
262 );
263 } 195 }
264 196
265 public String translateSignature( String signature ) 197 public String translateSignature(String signature) {
266 { 198 return SignatureUpdater.update(signature, new ClassNameUpdater() {
267 return SignatureUpdater.update( signature, new ClassNameUpdater( )
268 {
269 @Override 199 @Override
270 public String update( String className ) 200 public String update(String className) {
271 { 201 String translatedName = translateClass(className);
272 String translatedName = translateClass( className ); 202 if (translatedName != null) {
273 if( translatedName != null )
274 {
275 return translatedName; 203 return translatedName;
276 } 204 }
277 return className; 205 return className;
278 } 206 }
279 } ); 207 });
280 } 208 }
281 209
282 private ClassMapping findClassMapping( ClassEntry classEntry ) 210 private ClassMapping findClassMapping(ClassEntry classEntry) {
283 { 211 ClassMapping classMapping = m_classes.get(classEntry.getOuterClassName());
284 ClassMapping classMapping = m_classes.get( classEntry.getOuterClassName() ); 212 if (classMapping != null && classEntry.isInnerClass()) {
285 if( classMapping != null && classEntry.isInnerClass() )
286 {
287 classMapping = m_direction.choose( 213 classMapping = m_direction.choose(
288 classMapping.getInnerClassByObf( classEntry.getInnerClassName() ), 214 classMapping.getInnerClassByObf(classEntry.getInnerClassName()),
289 classMapping.getInnerClassByDeobfThenObf( classEntry.getInnerClassName() ) 215 classMapping.getInnerClassByDeobfThenObf(classEntry.getInnerClassName())
290 ); 216 );
291 } 217 }
292 return classMapping; 218 return classMapping;