diff options
| author | 2014-08-30 14:14:54 -0400 | |
|---|---|---|
| committer | 2014-08-30 14:14:54 -0400 | |
| commit | 63172120a39a315e29bc38ea6634741797b3dcab (patch) | |
| tree | 9030b8678aaca06982ae4d1032298f52ab833e09 /src/cuchaz | |
| parent | got a decent class matcher working (diff) | |
| download | enigma-63172120a39a315e29bc38ea6634741797b3dcab.tar.gz enigma-63172120a39a315e29bc38ea6634741797b3dcab.tar.xz enigma-63172120a39a315e29bc38ea6634741797b3dcab.zip | |
finished class matching for now, need to work on class member matching
Diffstat (limited to 'src/cuchaz')
| -rw-r--r-- | src/cuchaz/enigma/convert/ClassIdentity.java | 40 | ||||
| -rw-r--r-- | src/cuchaz/enigma/convert/ClassMapper.java | 229 | ||||
| -rw-r--r-- | src/cuchaz/enigma/convert/ClassMatching.java | 33 | ||||
| -rw-r--r-- | src/cuchaz/enigma/mapping/ClassMapping.java | 29 | ||||
| -rw-r--r-- | src/cuchaz/enigma/mapping/Mappings.java | 25 | ||||
| -rw-r--r-- | src/cuchaz/enigma/mapping/MethodMapping.java | 20 |
6 files changed, 319 insertions, 57 deletions
diff --git a/src/cuchaz/enigma/convert/ClassIdentity.java b/src/cuchaz/enigma/convert/ClassIdentity.java index 0a3a4497..980f31f5 100644 --- a/src/cuchaz/enigma/convert/ClassIdentity.java +++ b/src/cuchaz/enigma/convert/ClassIdentity.java | |||
| @@ -60,6 +60,7 @@ import cuchaz.enigma.mapping.SignatureUpdater.ClassNameUpdater; | |||
| 60 | public class ClassIdentity | 60 | public class ClassIdentity |
| 61 | { | 61 | { |
| 62 | private ClassEntry m_classEntry; | 62 | private ClassEntry m_classEntry; |
| 63 | private String m_rawName; | ||
| 63 | private SidedClassNamer m_namer; | 64 | private SidedClassNamer m_namer; |
| 64 | private Set<String> m_fields; | 65 | private Set<String> m_fields; |
| 65 | private Set<String> m_methods; | 66 | private Set<String> m_methods; |
| @@ -70,13 +71,18 @@ public class ClassIdentity | |||
| 70 | private Set<String> m_implementations; | 71 | private Set<String> m_implementations; |
| 71 | private Set<String> m_references; | 72 | private Set<String> m_references; |
| 72 | 73 | ||
| 73 | public ClassIdentity( CtClass c, SidedClassNamer namer, JarIndex index, boolean useReferences ) | 74 | public ClassIdentity( CtClass c, SidedClassNamer namer, JarIndex index, boolean useReferences, boolean useRawNames ) |
| 74 | { | 75 | { |
| 75 | m_namer = namer; | 76 | m_namer = namer; |
| 76 | 77 | ||
| 77 | // stuff from the bytecode | 78 | // stuff from the bytecode |
| 78 | 79 | ||
| 79 | m_classEntry = new ClassEntry( Descriptor.toJvmName( c.getName() ) ); | 80 | m_classEntry = new ClassEntry( Descriptor.toJvmName( c.getName() ) ); |
| 81 | m_rawName = ""; | ||
| 82 | if( useRawNames ) | ||
| 83 | { | ||
| 84 | m_rawName = m_classEntry.getName(); | ||
| 85 | } | ||
| 80 | m_fields = Sets.newHashSet(); | 86 | m_fields = Sets.newHashSet(); |
| 81 | for( CtField field : c.getDeclaredFields() ) | 87 | for( CtField field : c.getDeclaredFields() ) |
| 82 | { | 88 | { |
| @@ -176,8 +182,16 @@ public class ClassIdentity | |||
| 176 | { | 182 | { |
| 177 | StringBuilder buf = new StringBuilder(); | 183 | StringBuilder buf = new StringBuilder(); |
| 178 | buf.append( "class: " ); | 184 | buf.append( "class: " ); |
| 185 | buf.append( m_classEntry.getName() ); | ||
| 186 | buf.append( " " ); | ||
| 179 | buf.append( hashCode() ); | 187 | buf.append( hashCode() ); |
| 180 | buf.append( "\n" ); | 188 | buf.append( "\n" ); |
| 189 | if( m_rawName.length() > 0 ) | ||
| 190 | { | ||
| 191 | buf.append( "\traw name: " ); | ||
| 192 | buf.append( m_rawName ); | ||
| 193 | buf.append( "\n" ); | ||
| 194 | } | ||
| 181 | for( String field : m_fields ) | 195 | for( String field : m_fields ) |
| 182 | { | 196 | { |
| 183 | buf.append( "\tfield " ); | 197 | buf.append( "\tfield " ); |
| @@ -425,7 +439,8 @@ public class ClassIdentity | |||
| 425 | 439 | ||
| 426 | public boolean equals( ClassIdentity other ) | 440 | public boolean equals( ClassIdentity other ) |
| 427 | { | 441 | { |
| 428 | return m_fields.equals( other.m_fields ) | 442 | return m_rawName.equals( other.m_rawName ) |
| 443 | && m_fields.equals( other.m_fields ) | ||
| 429 | && m_methods.equals( other.m_methods ) | 444 | && m_methods.equals( other.m_methods ) |
| 430 | && m_constructors.equals( other.m_constructors ) | 445 | && m_constructors.equals( other.m_constructors ) |
| 431 | && m_staticInitializer.equals( other.m_staticInitializer ) | 446 | && m_staticInitializer.equals( other.m_staticInitializer ) |
| @@ -439,6 +454,7 @@ public class ClassIdentity | |||
| 439 | public int hashCode( ) | 454 | public int hashCode( ) |
| 440 | { | 455 | { |
| 441 | List<Object> objs = Lists.newArrayList(); | 456 | List<Object> objs = Lists.newArrayList(); |
| 457 | objs.add( m_rawName ); | ||
| 442 | objs.addAll( m_fields ); | 458 | objs.addAll( m_fields ); |
| 443 | objs.addAll( m_methods ); | 459 | objs.addAll( m_methods ); |
| 444 | objs.addAll( m_constructors ); | 460 | objs.addAll( m_constructors ); |
| @@ -449,4 +465,24 @@ public class ClassIdentity | |||
| 449 | objs.addAll( m_references ); | 465 | objs.addAll( m_references ); |
| 450 | return Util.combineHashesOrdered( objs ); | 466 | return Util.combineHashesOrdered( objs ); |
| 451 | } | 467 | } |
| 468 | |||
| 469 | public int getMatchScore( ClassIdentity other ) | ||
| 470 | { | ||
| 471 | return getNumMatches( m_fields, other.m_fields ) | ||
| 472 | + getNumMatches( m_methods, other.m_methods ) | ||
| 473 | + getNumMatches( m_constructors, other.m_constructors ); | ||
| 474 | } | ||
| 475 | |||
| 476 | private int getNumMatches( Set<String> a, Set<String> b ) | ||
| 477 | { | ||
| 478 | int numMatches = 0; | ||
| 479 | for( String val : a ) | ||
| 480 | { | ||
| 481 | if( b.contains( val ) ) | ||
| 482 | { | ||
| 483 | numMatches++; | ||
| 484 | } | ||
| 485 | } | ||
| 486 | return numMatches; | ||
| 487 | } | ||
| 452 | } | 488 | } |
diff --git a/src/cuchaz/enigma/convert/ClassMapper.java b/src/cuchaz/enigma/convert/ClassMapper.java index fe48c505..fd6ab922 100644 --- a/src/cuchaz/enigma/convert/ClassMapper.java +++ b/src/cuchaz/enigma/convert/ClassMapper.java | |||
| @@ -11,32 +11,130 @@ | |||
| 11 | package cuchaz.enigma.convert; | 11 | package cuchaz.enigma.convert; |
| 12 | 12 | ||
| 13 | import java.io.File; | 13 | import java.io.File; |
| 14 | import java.io.FileReader; | ||
| 15 | import java.io.FileWriter; | ||
| 14 | import java.io.IOException; | 16 | import java.io.IOException; |
| 15 | import java.util.Arrays; | 17 | import java.util.Arrays; |
| 18 | import java.util.Collections; | ||
| 19 | import java.util.Iterator; | ||
| 16 | import java.util.List; | 20 | import java.util.List; |
| 17 | import java.util.Map; | 21 | import java.util.Map; |
| 18 | import java.util.Set; | 22 | import java.util.Set; |
| 23 | import java.util.TreeMap; | ||
| 19 | import java.util.jar.JarFile; | 24 | import java.util.jar.JarFile; |
| 20 | 25 | ||
| 21 | import javassist.CtClass; | 26 | import javassist.CtClass; |
| 27 | |||
| 28 | import com.beust.jcommander.internal.Sets; | ||
| 29 | import com.google.common.collect.Maps; | ||
| 30 | |||
| 31 | import cuchaz.enigma.Constants; | ||
| 22 | import cuchaz.enigma.TranslatingTypeLoader; | 32 | import cuchaz.enigma.TranslatingTypeLoader; |
| 23 | import cuchaz.enigma.analysis.JarIndex; | 33 | import cuchaz.enigma.analysis.JarIndex; |
| 24 | import cuchaz.enigma.convert.ClassNamer.SidedClassNamer; | 34 | import cuchaz.enigma.convert.ClassNamer.SidedClassNamer; |
| 25 | import cuchaz.enigma.mapping.ClassEntry; | 35 | import cuchaz.enigma.mapping.ClassEntry; |
| 36 | import cuchaz.enigma.mapping.ClassMapping; | ||
| 37 | import cuchaz.enigma.mapping.MappingParseException; | ||
| 38 | import cuchaz.enigma.mapping.Mappings; | ||
| 39 | import cuchaz.enigma.mapping.MappingsReader; | ||
| 40 | import cuchaz.enigma.mapping.MappingsWriter; | ||
| 26 | 41 | ||
| 27 | public class ClassMapper | 42 | public class ClassMapper |
| 28 | { | 43 | { |
| 29 | public static void main( String[] args ) | 44 | public static void main( String[] args ) |
| 30 | throws IOException | 45 | throws IOException, MappingParseException |
| 31 | { | 46 | { |
| 32 | // TEMP | 47 | // TEMP |
| 33 | JarFile fromJar = new JarFile( new File( "input/1.8-pre1.jar" ) ); | 48 | JarFile fromJar = new JarFile( new File( "input/1.8-pre1.jar" ) ); |
| 34 | JarFile toJar = new JarFile( new File( "input/1.8-pre2.jar" ) ); | 49 | JarFile toJar = new JarFile( new File( "input/1.8-pre3.jar" ) ); |
| 50 | File inMappingsFile = new File( "../minecraft-mappings/1.8-pre.mappings" ); | ||
| 51 | File outMappingsFile = new File( "../minecraft-mappings/1.8-pre3.mappings" ); | ||
| 35 | 52 | ||
| 36 | // compute the matching | 53 | // compute the matching |
| 37 | ClassMatching matching = ClassMapper.computeMatching( fromJar, toJar ); | 54 | ClassMatching matching = ClassMapper.computeMatching( fromJar, toJar ); |
| 38 | 55 | ||
| 39 | // TODO: use the matching to convert the mappings | 56 | // use the matching to convert the mappings |
| 57 | Mappings mappings = new MappingsReader().read( new FileReader( inMappingsFile ) ); | ||
| 58 | Map<String,Map.Entry<ClassIdentity,List<ClassIdentity>>> conversionMap = matching.getConversionMap(); | ||
| 59 | Map<String,String> finalConversion = Maps.newHashMap(); | ||
| 60 | Set<String> unmatchedSourceClasses = Sets.newHashSet(); | ||
| 61 | for( ClassMapping classMapping : mappings.classes() ) | ||
| 62 | { | ||
| 63 | // is there a match for this class? | ||
| 64 | Map.Entry<ClassIdentity,List<ClassIdentity>> entry = conversionMap.get( classMapping.getObfName() ); | ||
| 65 | ClassIdentity sourceClass = entry.getKey(); | ||
| 66 | List<ClassIdentity> matches = entry.getValue(); | ||
| 67 | |||
| 68 | if( matches.isEmpty() ) | ||
| 69 | { | ||
| 70 | // no match! =( | ||
| 71 | System.out.println( "No exact match for source class " + classMapping.getObfName() ); | ||
| 72 | |||
| 73 | // find the closest classes | ||
| 74 | TreeMap<Integer,ClassIdentity> scoredMatches = Maps.newTreeMap( Collections.reverseOrder() ); | ||
| 75 | for( ClassIdentity c : matching.getUnmatchedDestClasses() ) | ||
| 76 | { | ||
| 77 | scoredMatches.put( sourceClass.getMatchScore( c ), c ); | ||
| 78 | } | ||
| 79 | Iterator<Map.Entry<Integer,ClassIdentity>> iter = scoredMatches.entrySet().iterator(); | ||
| 80 | for( int i=0; i<10 && iter.hasNext(); i++ ) | ||
| 81 | { | ||
| 82 | Map.Entry<Integer,ClassIdentity> score = iter.next(); | ||
| 83 | System.out.println( String.format( "\tScore: %3d %s", score.getKey(), score.getValue().getClassEntry().getName() ) ); | ||
| 84 | } | ||
| 85 | |||
| 86 | // does the best match have a non-zero score and the same name? | ||
| 87 | Map.Entry<Integer,ClassIdentity> bestMatch = scoredMatches.firstEntry(); | ||
| 88 | if( bestMatch.getKey() > 0 && bestMatch.getValue().getClassEntry().equals( sourceClass.getClassEntry() ) ) | ||
| 89 | { | ||
| 90 | // use it | ||
| 91 | System.out.println( "\tAutomatically choosing likely match: " + bestMatch.getValue().getClassEntry().getName() ); | ||
| 92 | addFinalConversion( finalConversion, sourceClass, bestMatch.getValue() ); | ||
| 93 | } | ||
| 94 | else | ||
| 95 | { | ||
| 96 | unmatchedSourceClasses.add( classMapping.getObfName() ); | ||
| 97 | } | ||
| 98 | } | ||
| 99 | if( matches.size() == 1 ) | ||
| 100 | { | ||
| 101 | // unique match! We're good to go! | ||
| 102 | addFinalConversion( finalConversion, sourceClass, matches.get( 0 ) ); | ||
| 103 | } | ||
| 104 | else if( matches.size() > 1 ) | ||
| 105 | { | ||
| 106 | // too many matches! =( | ||
| 107 | unmatchedSourceClasses.add( classMapping.getObfName() ); | ||
| 108 | } | ||
| 109 | } | ||
| 110 | |||
| 111 | // remove (and warn about) unmatched classes | ||
| 112 | if( !unmatchedSourceClasses.isEmpty() ) | ||
| 113 | { | ||
| 114 | System.err.println( "WARNING: there were unmatched classes!" ); | ||
| 115 | for( String className : unmatchedSourceClasses ) | ||
| 116 | { | ||
| 117 | System.err.println( "\t" + className ); | ||
| 118 | mappings.removeClassByObfName( className ); | ||
| 119 | } | ||
| 120 | System.err.println( "Mappings for these classes have been removed." ); | ||
| 121 | } | ||
| 122 | |||
| 123 | // show the class name changes | ||
| 124 | for( Map.Entry<String,String> entry : finalConversion.entrySet() ) | ||
| 125 | { | ||
| 126 | if( !entry.getKey().equals( entry.getValue() ) ) | ||
| 127 | { | ||
| 128 | System.out.println( String.format( "Class change: %s -> %s", entry.getKey(), entry.getValue() ) ); | ||
| 129 | } | ||
| 130 | } | ||
| 131 | |||
| 132 | // do the final conversion | ||
| 133 | mappings.renameObfClasses( finalConversion ); | ||
| 134 | FileWriter writer = new FileWriter( outMappingsFile ); | ||
| 135 | new MappingsWriter().write( writer, mappings ); | ||
| 136 | writer.close(); | ||
| 137 | System.out.println( "Wrote converted mappings to:\n\t" + outMappingsFile.getAbsolutePath() ); | ||
| 40 | } | 138 | } |
| 41 | 139 | ||
| 42 | public static ClassMatching computeMatching( JarFile sourceJar, JarFile destJar ) | 140 | public static ClassMatching computeMatching( JarFile sourceJar, JarFile destJar ) |
| @@ -55,78 +153,81 @@ public class ClassMapper | |||
| 55 | TranslatingTypeLoader destLoader = new TranslatingTypeLoader( destJar, destIndex ); | 153 | TranslatingTypeLoader destLoader = new TranslatingTypeLoader( destJar, destIndex ); |
| 56 | 154 | ||
| 57 | ClassMatching matching = null; | 155 | ClassMatching matching = null; |
| 58 | for( boolean useReferences : Arrays.asList( false, true ) ) | 156 | for( boolean useRawNames : Arrays.asList( false, true ) ) |
| 59 | { | 157 | { |
| 60 | int numMatches = 0; | 158 | for( boolean useReferences : Arrays.asList( false, true ) ) |
| 61 | do | ||
| 62 | { | 159 | { |
| 63 | SidedClassNamer sourceNamer = null; | 160 | int numMatches = 0; |
| 64 | SidedClassNamer destNamer = null; | 161 | do |
| 65 | if( matching != null ) | ||
| 66 | { | 162 | { |
| 67 | // build a class namer | 163 | SidedClassNamer sourceNamer = null; |
| 68 | ClassNamer namer = new ClassNamer( matching.getUniqueMatches() ); | 164 | SidedClassNamer destNamer = null; |
| 69 | sourceNamer = namer.getSourceNamer(); | 165 | if( matching != null ) |
| 70 | destNamer = namer.getDestNamer(); | 166 | { |
| 167 | // build a class namer | ||
| 168 | ClassNamer namer = new ClassNamer( matching.getUniqueMatches() ); | ||
| 169 | sourceNamer = namer.getSourceNamer(); | ||
| 170 | destNamer = namer.getDestNamer(); | ||
| 171 | |||
| 172 | // note the number of matches | ||
| 173 | numMatches = matching.getUniqueMatches().size(); | ||
| 174 | } | ||
| 71 | 175 | ||
| 72 | // note the number of matches | 176 | // get the entries left to match |
| 73 | numMatches = matching.getUniqueMatches().size(); | 177 | Set<ClassEntry> sourceClassEntries = sourceIndex.getObfClassEntries(); |
| 74 | } | 178 | Set<ClassEntry> destClassEntries = destIndex.getObfClassEntries(); |
| 75 | 179 | if( matching != null ) | |
| 76 | // get the entries left to match | ||
| 77 | Set<ClassEntry> sourceClassEntries = sourceIndex.getObfClassEntries(); | ||
| 78 | Set<ClassEntry> destClassEntries = destIndex.getObfClassEntries(); | ||
| 79 | if( matching != null ) | ||
| 80 | { | ||
| 81 | sourceClassEntries.clear(); | ||
| 82 | destClassEntries.clear(); | ||
| 83 | for( Map.Entry<List<ClassIdentity>,List<ClassIdentity>> entry : matching.getAmbiguousMatches().entrySet() ) | ||
| 84 | { | 180 | { |
| 85 | for( ClassIdentity c : entry.getKey() ) | 181 | sourceClassEntries.clear(); |
| 182 | destClassEntries.clear(); | ||
| 183 | for( Map.Entry<List<ClassIdentity>,List<ClassIdentity>> entry : matching.getAmbiguousMatches().entrySet() ) | ||
| 184 | { | ||
| 185 | for( ClassIdentity c : entry.getKey() ) | ||
| 186 | { | ||
| 187 | sourceClassEntries.add( c.getClassEntry() ); | ||
| 188 | matching.removeSource( c ); | ||
| 189 | } | ||
| 190 | for( ClassIdentity c : entry.getValue() ) | ||
| 191 | { | ||
| 192 | destClassEntries.add( c.getClassEntry() ); | ||
| 193 | matching.removeDest( c ); | ||
| 194 | } | ||
| 195 | } | ||
| 196 | for( ClassIdentity c : matching.getUnmatchedSourceClasses() ) | ||
| 86 | { | 197 | { |
| 87 | sourceClassEntries.add( c.getClassEntry() ); | 198 | sourceClassEntries.add( c.getClassEntry() ); |
| 88 | matching.removeSource( c ); | 199 | matching.removeSource( c ); |
| 89 | } | 200 | } |
| 90 | for( ClassIdentity c : entry.getValue() ) | 201 | for( ClassIdentity c : matching.getUnmatchedDestClasses() ) |
| 91 | { | 202 | { |
| 92 | destClassEntries.add( c.getClassEntry() ); | 203 | destClassEntries.add( c.getClassEntry() ); |
| 93 | matching.removeDest( c ); | 204 | matching.removeDest( c ); |
| 94 | } | 205 | } |
| 95 | } | 206 | } |
| 96 | for( ClassIdentity c : matching.getUnmatchedSourceClasses() ) | 207 | else |
| 97 | { | 208 | { |
| 98 | sourceClassEntries.add( c.getClassEntry() ); | 209 | matching = new ClassMatching(); |
| 99 | matching.removeSource( c ); | ||
| 100 | } | 210 | } |
| 101 | for( ClassIdentity c : matching.getUnmatchedDestClasses() ) | 211 | |
| 212 | // compute a matching for the classes | ||
| 213 | for( ClassEntry classEntry : sourceClassEntries ) | ||
| 102 | { | 214 | { |
| 103 | destClassEntries.add( c.getClassEntry() ); | 215 | CtClass c = sourceLoader.loadClass( classEntry.getName() ); |
| 104 | matching.removeDest( c ); | 216 | ClassIdentity sourceClass = new ClassIdentity( c, sourceNamer, sourceIndex, useReferences, useRawNames ); |
| 217 | matching.addSource( sourceClass ); | ||
| 105 | } | 218 | } |
| 219 | for( ClassEntry classEntry : destClassEntries ) | ||
| 220 | { | ||
| 221 | CtClass c = destLoader.loadClass( classEntry.getName() ); | ||
| 222 | ClassIdentity destClass = new ClassIdentity( c, destNamer, destIndex, useReferences, useRawNames ); | ||
| 223 | matching.matchDestClass( destClass ); | ||
| 224 | } | ||
| 225 | |||
| 226 | // TEMP | ||
| 227 | System.out.println( matching ); | ||
| 106 | } | 228 | } |
| 107 | else | 229 | while( matching.getUniqueMatches().size() - numMatches > 0 ); |
| 108 | { | ||
| 109 | matching = new ClassMatching(); | ||
| 110 | } | ||
| 111 | |||
| 112 | // compute a matching for the classes | ||
| 113 | for( ClassEntry classEntry : sourceClassEntries ) | ||
| 114 | { | ||
| 115 | CtClass c = sourceLoader.loadClass( classEntry.getName() ); | ||
| 116 | ClassIdentity sourceClass = new ClassIdentity( c, sourceNamer, sourceIndex, useReferences ); | ||
| 117 | matching.addSource( sourceClass ); | ||
| 118 | } | ||
| 119 | for( ClassEntry classEntry : destClassEntries ) | ||
| 120 | { | ||
| 121 | CtClass c = destLoader.loadClass( classEntry.getName() ); | ||
| 122 | ClassIdentity destClass = new ClassIdentity( c, destNamer, destIndex, useReferences ); | ||
| 123 | matching.matchDestClass( destClass ); | ||
| 124 | } | ||
| 125 | |||
| 126 | // TEMP | ||
| 127 | System.out.println( matching ); | ||
| 128 | } | 230 | } |
| 129 | while( matching.getUniqueMatches().size() - numMatches > 0 ); | ||
| 130 | } | 231 | } |
| 131 | 232 | ||
| 132 | /* DEBUG: show some ambiguous matches | 233 | /* DEBUG: show some ambiguous matches |
| @@ -163,6 +264,24 @@ public class ClassMapper | |||
| 163 | return matching; | 264 | return matching; |
| 164 | } | 265 | } |
| 165 | 266 | ||
| 267 | private static void addFinalConversion( Map<String,String> finalConversion, ClassIdentity sourceClass, ClassIdentity destClass ) | ||
| 268 | { | ||
| 269 | // flatten inner classes since these are all obf classes in the none package | ||
| 270 | String sourceClassName = sourceClass.getClassEntry().getName(); | ||
| 271 | if( sourceClass.getClassEntry().isInnerClass() ) | ||
| 272 | { | ||
| 273 | sourceClassName = Constants.NonePackage + "/" + sourceClass.getClassEntry().getInnerClassName(); | ||
| 274 | } | ||
| 275 | |||
| 276 | String destClassName = destClass.getClassEntry().getName(); | ||
| 277 | if( destClass.getClassEntry().isInnerClass() ) | ||
| 278 | { | ||
| 279 | destClassName = Constants.NonePackage + "/" + destClass.getClassEntry().getInnerClassName(); | ||
| 280 | } | ||
| 281 | |||
| 282 | finalConversion.put( sourceClassName, destClassName ); | ||
| 283 | } | ||
| 284 | |||
| 166 | /* DEBUG | 285 | /* DEBUG |
| 167 | private static String decompile( TranslatingTypeLoader loader, ClassEntry classEntry ) | 286 | private static String decompile( TranslatingTypeLoader loader, ClassEntry classEntry ) |
| 168 | { | 287 | { |
diff --git a/src/cuchaz/enigma/convert/ClassMatching.java b/src/cuchaz/enigma/convert/ClassMatching.java index fea84386..4e9fe398 100644 --- a/src/cuchaz/enigma/convert/ClassMatching.java +++ b/src/cuchaz/enigma/convert/ClassMatching.java | |||
| @@ -10,12 +10,15 @@ | |||
| 10 | ******************************************************************************/ | 10 | ******************************************************************************/ |
| 11 | package cuchaz.enigma.convert; | 11 | package cuchaz.enigma.convert; |
| 12 | 12 | ||
| 13 | import java.util.AbstractMap; | ||
| 13 | import java.util.ArrayList; | 14 | import java.util.ArrayList; |
| 15 | import java.util.Arrays; | ||
| 14 | import java.util.Collection; | 16 | import java.util.Collection; |
| 15 | import java.util.List; | 17 | import java.util.List; |
| 16 | import java.util.Map; | 18 | import java.util.Map; |
| 17 | 19 | ||
| 18 | import com.beust.jcommander.internal.Lists; | 20 | import com.beust.jcommander.internal.Lists; |
| 21 | import com.beust.jcommander.internal.Maps; | ||
| 19 | import com.google.common.collect.ArrayListMultimap; | 22 | import com.google.common.collect.ArrayListMultimap; |
| 20 | import com.google.common.collect.BiMap; | 23 | import com.google.common.collect.BiMap; |
| 21 | import com.google.common.collect.HashBiMap; | 24 | import com.google.common.collect.HashBiMap; |
| @@ -156,6 +159,36 @@ public class ClassMatching | |||
| 156 | return new ArrayList<ClassIdentity>( m_unmatchedDestClasses ); | 159 | return new ArrayList<ClassIdentity>( m_unmatchedDestClasses ); |
| 157 | } | 160 | } |
| 158 | 161 | ||
| 162 | public Map<String,Map.Entry<ClassIdentity,List<ClassIdentity>>> getConversionMap( ) | ||
| 163 | { | ||
| 164 | Map<String,Map.Entry<ClassIdentity,List<ClassIdentity>>> conversion = Maps.newHashMap(); | ||
| 165 | for( Map.Entry<ClassIdentity,ClassIdentity> entry : getUniqueMatches().entrySet() ) | ||
| 166 | { | ||
| 167 | conversion.put( | ||
| 168 | entry.getKey().getClassEntry().getName(), | ||
| 169 | new AbstractMap.SimpleEntry<ClassIdentity,List<ClassIdentity>>( entry.getKey(), Arrays.asList( entry.getValue() ) ) | ||
| 170 | ); | ||
| 171 | } | ||
| 172 | for( Map.Entry<List<ClassIdentity>,List<ClassIdentity>> entry : getAmbiguousMatches().entrySet() ) | ||
| 173 | { | ||
| 174 | for( ClassIdentity sourceClass : entry.getKey() ) | ||
| 175 | { | ||
| 176 | conversion.put( | ||
| 177 | sourceClass.getClassEntry().getName(), | ||
| 178 | new AbstractMap.SimpleEntry<ClassIdentity,List<ClassIdentity>>( sourceClass, entry.getValue() ) | ||
| 179 | ); | ||
| 180 | } | ||
| 181 | } | ||
| 182 | for( ClassIdentity sourceClass : getUnmatchedSourceClasses() ) | ||
| 183 | { | ||
| 184 | conversion.put( | ||
| 185 | sourceClass.getClassEntry().getName(), | ||
| 186 | new AbstractMap.SimpleEntry<ClassIdentity,List<ClassIdentity>>( sourceClass, new ArrayList<ClassIdentity>() ) | ||
| 187 | ); | ||
| 188 | } | ||
| 189 | return conversion; | ||
| 190 | } | ||
| 191 | |||
| 159 | @Override | 192 | @Override |
| 160 | public String toString( ) | 193 | public String toString( ) |
| 161 | { | 194 | { |
diff --git a/src/cuchaz/enigma/mapping/ClassMapping.java b/src/cuchaz/enigma/mapping/ClassMapping.java index 59365129..095cb385 100644 --- a/src/cuchaz/enigma/mapping/ClassMapping.java +++ b/src/cuchaz/enigma/mapping/ClassMapping.java | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | package cuchaz.enigma.mapping; | 11 | package cuchaz.enigma.mapping; |
| 12 | 12 | ||
| 13 | import java.io.Serializable; | 13 | import java.io.Serializable; |
| 14 | import java.util.ArrayList; | ||
| 14 | import java.util.Map; | 15 | import java.util.Map; |
| 15 | 16 | ||
| 16 | import com.google.common.collect.Maps; | 17 | import com.google.common.collect.Maps; |
| @@ -299,4 +300,32 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping> | |||
| 299 | { | 300 | { |
| 300 | return m_obfName.compareTo( other.m_obfName ); | 301 | return m_obfName.compareTo( other.m_obfName ); |
| 301 | } | 302 | } |
| 303 | |||
| 304 | public void renameObfClasses( Map<String,String> nameMap ) | ||
| 305 | { | ||
| 306 | // rename self | ||
| 307 | { | ||
| 308 | String newName = nameMap.get( m_obfName ); | ||
| 309 | if( newName != null ) | ||
| 310 | { | ||
| 311 | m_obfName = newName; | ||
| 312 | } | ||
| 313 | } | ||
| 314 | |||
| 315 | // rename inner classes | ||
| 316 | for( ClassMapping classMapping : new ArrayList<ClassMapping>( m_innerClassesByObf.values() ) ) | ||
| 317 | { | ||
| 318 | m_innerClassesByObf.remove( classMapping.getObfName() ); | ||
| 319 | classMapping.renameObfClasses( nameMap ); | ||
| 320 | m_innerClassesByObf.put( classMapping.getObfName(), classMapping ); | ||
| 321 | } | ||
| 322 | |||
| 323 | // rename method signatures | ||
| 324 | for( MethodMapping methodMapping : new ArrayList<MethodMapping>( m_methodsByObf.values() ) ) | ||
| 325 | { | ||
| 326 | m_methodsByObf.remove( getMethodKey( methodMapping.getObfName(), methodMapping.getObfSignature() ) ); | ||
| 327 | methodMapping.renameObfClasses( nameMap ); | ||
| 328 | m_methodsByObf.put( getMethodKey( methodMapping.getObfName(), methodMapping.getObfSignature() ), methodMapping ); | ||
| 329 | } | ||
| 330 | } | ||
| 302 | } | 331 | } |
diff --git a/src/cuchaz/enigma/mapping/Mappings.java b/src/cuchaz/enigma/mapping/Mappings.java index f3b8fad1..70bea25f 100644 --- a/src/cuchaz/enigma/mapping/Mappings.java +++ b/src/cuchaz/enigma/mapping/Mappings.java | |||
| @@ -14,6 +14,7 @@ import java.io.IOException; | |||
| 14 | import java.io.InputStream; | 14 | import java.io.InputStream; |
| 15 | import java.io.ObjectInputStream; | 15 | import java.io.ObjectInputStream; |
| 16 | import java.io.Serializable; | 16 | import java.io.Serializable; |
| 17 | import java.util.ArrayList; | ||
| 17 | import java.util.Map; | 18 | import java.util.Map; |
| 18 | import java.util.zip.GZIPInputStream; | 19 | import java.util.zip.GZIPInputStream; |
| 19 | 20 | ||
| @@ -136,4 +137,28 @@ public class Mappings implements Serializable | |||
| 136 | } | 137 | } |
| 137 | return buf.toString(); | 138 | return buf.toString(); |
| 138 | } | 139 | } |
| 140 | |||
| 141 | public void renameObfClasses( Map<String,String> nameMap ) | ||
| 142 | { | ||
| 143 | for( ClassMapping classMapping : new ArrayList<ClassMapping>( m_classesByObf.values() ) ) | ||
| 144 | { | ||
| 145 | String newName = nameMap.get( classMapping.getObfName() ); | ||
| 146 | if( newName != null ) | ||
| 147 | { | ||
| 148 | m_classesByObf.remove( classMapping.getObfName() ); | ||
| 149 | classMapping.renameObfClasses( nameMap ); | ||
| 150 | m_classesByObf.put( classMapping.getObfName(), classMapping ); | ||
| 151 | } | ||
| 152 | } | ||
| 153 | } | ||
| 154 | |||
| 155 | public void removeClassByObfName( String obfName ) | ||
| 156 | { | ||
| 157 | ClassMapping classMapping = m_classesByObf.get( obfName ); | ||
| 158 | if( classMapping != null ) | ||
| 159 | { | ||
| 160 | m_classesByObf.remove( classMapping.getObfName() ); | ||
| 161 | m_classesByDeobf.remove( classMapping.getDeobfName() ); | ||
| 162 | } | ||
| 163 | } | ||
| 139 | } | 164 | } |
diff --git a/src/cuchaz/enigma/mapping/MethodMapping.java b/src/cuchaz/enigma/mapping/MethodMapping.java index 6e6bec46..fe4e29b2 100644 --- a/src/cuchaz/enigma/mapping/MethodMapping.java +++ b/src/cuchaz/enigma/mapping/MethodMapping.java | |||
| @@ -14,6 +14,8 @@ import java.io.Serializable; | |||
| 14 | import java.util.Map; | 14 | import java.util.Map; |
| 15 | import java.util.TreeMap; | 15 | import java.util.TreeMap; |
| 16 | 16 | ||
| 17 | import cuchaz.enigma.mapping.SignatureUpdater.ClassNameUpdater; | ||
| 18 | |||
| 17 | public class MethodMapping implements Serializable, Comparable<MethodMapping> | 19 | public class MethodMapping implements Serializable, Comparable<MethodMapping> |
| 18 | { | 20 | { |
| 19 | private static final long serialVersionUID = -4409570216084263978L; | 21 | private static final long serialVersionUID = -4409570216084263978L; |
| @@ -139,4 +141,22 @@ public class MethodMapping implements Serializable, Comparable<MethodMapping> | |||
| 139 | { | 141 | { |
| 140 | return ( m_obfName + m_obfSignature ).compareTo( ( other.m_obfName + other.m_obfSignature ) ); | 142 | return ( m_obfName + m_obfSignature ).compareTo( ( other.m_obfName + other.m_obfSignature ) ); |
| 141 | } | 143 | } |
| 144 | |||
| 145 | public void renameObfClasses( final Map<String,String> nameMap ) | ||
| 146 | { | ||
| 147 | // rename obf classes in the signature | ||
| 148 | m_obfSignature = SignatureUpdater.update( m_obfSignature, new ClassNameUpdater( ) | ||
| 149 | { | ||
| 150 | @Override | ||
| 151 | public String update( String className ) | ||
| 152 | { | ||
| 153 | String newName = nameMap.get( className ); | ||
| 154 | if( newName != null ) | ||
| 155 | { | ||
| 156 | return newName; | ||
| 157 | } | ||
| 158 | return className; | ||
| 159 | } | ||
| 160 | } ); | ||
| 161 | } | ||
| 142 | } | 162 | } |