diff options
| author | 2019-02-23 19:42:00 +0200 | |
|---|---|---|
| committer | 2019-02-23 19:42:00 +0200 | |
| commit | bb20ce047a2e20866b9532c441c7433b1973ba5b (patch) | |
| tree | ed9f5bd596e43a1fffeef0b174c5370c039a9b62 /src | |
| parent | Tweak inheritance and implementation tree generation (diff) | |
| download | enigma-bb20ce047a2e20866b9532c441c7433b1973ba5b.tar.gz enigma-bb20ce047a2e20866b9532c441c7433b1973ba5b.tar.xz enigma-bb20ce047a2e20866b9532c441c7433b1973ba5b.zip | |
Fix #110 and remap indices with matched bridge method names
Diffstat (limited to 'src')
35 files changed, 289 insertions, 166 deletions
diff --git a/src/main/java/cuchaz/enigma/CommandMain.java b/src/main/java/cuchaz/enigma/CommandMain.java index 7c0a3d53..c9f83828 100644 --- a/src/main/java/cuchaz/enigma/CommandMain.java +++ b/src/main/java/cuchaz/enigma/CommandMain.java | |||
| @@ -74,7 +74,7 @@ public class CommandMain { | |||
| 74 | Deobfuscator deobfuscator = new Deobfuscator(jar); | 74 | Deobfuscator deobfuscator = new Deobfuscator(jar); |
| 75 | if (fileMappings != null) { | 75 | if (fileMappings != null) { |
| 76 | System.out.println("Reading mappings..."); | 76 | System.out.println("Reading mappings..."); |
| 77 | EntryTree<EntryMapping> mappings = chooseEnigmaFormat(fileMappings).read(fileMappings); | 77 | EntryTree<EntryMapping> mappings = chooseEnigmaFormat(fileMappings).read(fileMappings, new ConsoleProgressListener()); |
| 78 | deobfuscator.setMappings(mappings); | 78 | deobfuscator.setMappings(mappings); |
| 79 | } | 79 | } |
| 80 | return deobfuscator; | 80 | return deobfuscator; |
| @@ -94,7 +94,7 @@ public class CommandMain { | |||
| 94 | System.out.println("Reading mappings..."); | 94 | System.out.println("Reading mappings..."); |
| 95 | 95 | ||
| 96 | MappingFormat readFormat = chooseEnigmaFormat(fileMappings); | 96 | MappingFormat readFormat = chooseEnigmaFormat(fileMappings); |
| 97 | EntryTree<EntryMapping> mappings = readFormat.read(fileMappings); | 97 | EntryTree<EntryMapping> mappings = readFormat.read(fileMappings, new ConsoleProgressListener()); |
| 98 | System.out.println("Saving new mappings..."); | 98 | System.out.println("Saving new mappings..."); |
| 99 | 99 | ||
| 100 | saveFormat.write(mappings, result.toPath(), new ConsoleProgressListener()); | 100 | saveFormat.write(mappings, result.toPath(), new ConsoleProgressListener()); |
diff --git a/src/main/java/cuchaz/enigma/Deobfuscator.java b/src/main/java/cuchaz/enigma/Deobfuscator.java index 47cd05ce..b4736d8f 100644 --- a/src/main/java/cuchaz/enigma/Deobfuscator.java +++ b/src/main/java/cuchaz/enigma/Deobfuscator.java | |||
| @@ -126,23 +126,27 @@ public class Deobfuscator { | |||
| 126 | } | 126 | } |
| 127 | 127 | ||
| 128 | public void setMappings(EntryTree<EntryMapping> mappings) { | 128 | public void setMappings(EntryTree<EntryMapping> mappings) { |
| 129 | setMappings(mappings, ProgressListener.VOID); | ||
| 130 | } | ||
| 131 | |||
| 132 | public void setMappings(EntryTree<EntryMapping> mappings, ProgressListener progress) { | ||
| 129 | if (mappings != null) { | 133 | if (mappings != null) { |
| 130 | Collection<Entry<?>> dropped = dropMappings(mappings); | 134 | Collection<Entry<?>> dropped = dropMappings(mappings, progress); |
| 131 | mapper = new EntryRemapper(jarIndex, mappings); | 135 | mapper = new EntryRemapper(jarIndex, mappings); |
| 132 | 136 | ||
| 133 | DeltaTrackingTree<EntryMapping> obfToDeobf = mapper.getObfToDeobf(); | 137 | DeltaTrackingTree<EntryMapping> obfToDeobf = mapper.getObfToDeobf(); |
| 134 | for (Entry<?> entry : dropped) { | 138 | for (Entry<?> entry : dropped) { |
| 135 | obfToDeobf.trackDeletion(entry); | 139 | obfToDeobf.trackChange(entry); |
| 136 | } | 140 | } |
| 137 | } else { | 141 | } else { |
| 138 | mapper = new EntryRemapper(jarIndex); | 142 | mapper = new EntryRemapper(jarIndex); |
| 139 | } | 143 | } |
| 140 | } | 144 | } |
| 141 | 145 | ||
| 142 | private Collection<Entry<?>> dropMappings(EntryTree<EntryMapping> mappings) { | 146 | private Collection<Entry<?>> dropMappings(EntryTree<EntryMapping> mappings, ProgressListener progress) { |
| 143 | // drop mappings that don't match the jar | 147 | // drop mappings that don't match the jar |
| 144 | MappingsChecker checker = new MappingsChecker(jarIndex, mappings); | 148 | MappingsChecker checker = new MappingsChecker(jarIndex, mappings); |
| 145 | MappingsChecker.Dropped dropped = checker.dropBrokenMappings(); | 149 | MappingsChecker.Dropped dropped = checker.dropBrokenMappings(progress); |
| 146 | 150 | ||
| 147 | Map<Entry<?>, String> droppedMappings = dropped.getDroppedMappings(); | 151 | Map<Entry<?>, String> droppedMappings = dropped.getDroppedMappings(); |
| 148 | for (Map.Entry<Entry<?>, String> mapping : droppedMappings.entrySet()) { | 152 | for (Map.Entry<Entry<?>, String> mapping : droppedMappings.entrySet()) { |
diff --git a/src/main/java/cuchaz/enigma/analysis/index/BridgeMethodIndex.java b/src/main/java/cuchaz/enigma/analysis/index/BridgeMethodIndex.java index de2ba1e5..649ce254 100644 --- a/src/main/java/cuchaz/enigma/analysis/index/BridgeMethodIndex.java +++ b/src/main/java/cuchaz/enigma/analysis/index/BridgeMethodIndex.java | |||
| @@ -2,7 +2,6 @@ package cuchaz.enigma.analysis.index; | |||
| 2 | 2 | ||
| 3 | import com.google.common.collect.Maps; | 3 | import com.google.common.collect.Maps; |
| 4 | import com.google.common.collect.Sets; | 4 | import com.google.common.collect.Sets; |
| 5 | import cuchaz.enigma.translation.mapping.EntryResolver; | ||
| 6 | import cuchaz.enigma.translation.representation.AccessFlags; | 5 | import cuchaz.enigma.translation.representation.AccessFlags; |
| 7 | import cuchaz.enigma.translation.representation.MethodDescriptor; | 6 | import cuchaz.enigma.translation.representation.MethodDescriptor; |
| 8 | import cuchaz.enigma.translation.representation.TypeDescriptor; | 7 | import cuchaz.enigma.translation.representation.TypeDescriptor; |
| @@ -11,10 +10,7 @@ import cuchaz.enigma.translation.representation.entry.MethodDefEntry; | |||
| 11 | import cuchaz.enigma.translation.representation.entry.MethodEntry; | 10 | import cuchaz.enigma.translation.representation.entry.MethodEntry; |
| 12 | 11 | ||
| 13 | import javax.annotation.Nullable; | 12 | import javax.annotation.Nullable; |
| 14 | import java.util.Collection; | 13 | import java.util.*; |
| 15 | import java.util.List; | ||
| 16 | import java.util.Map; | ||
| 17 | import java.util.Set; | ||
| 18 | 14 | ||
| 19 | public class BridgeMethodIndex implements JarIndexer { | 15 | public class BridgeMethodIndex implements JarIndexer { |
| 20 | private final EntryIndex entryIndex; | 16 | private final EntryIndex entryIndex; |
| @@ -30,8 +26,7 @@ public class BridgeMethodIndex implements JarIndexer { | |||
| 30 | this.referenceIndex = referenceIndex; | 26 | this.referenceIndex = referenceIndex; |
| 31 | } | 27 | } |
| 32 | 28 | ||
| 33 | @Override | 29 | public void findBridgeMethods() { |
| 34 | public void processIndex(EntryResolver resolver) { | ||
| 35 | // look for access and bridged methods | 30 | // look for access and bridged methods |
| 36 | for (MethodEntry methodEntry : entryIndex.getMethods()) { | 31 | for (MethodEntry methodEntry : entryIndex.getMethods()) { |
| 37 | MethodDefEntry methodDefEntry = (MethodDefEntry) methodEntry; | 32 | MethodDefEntry methodDefEntry = (MethodDefEntry) methodEntry; |
| @@ -45,6 +40,23 @@ public class BridgeMethodIndex implements JarIndexer { | |||
| 45 | } | 40 | } |
| 46 | } | 41 | } |
| 47 | 42 | ||
| 43 | @Override | ||
| 44 | public void processIndex(JarIndex index) { | ||
| 45 | Map<MethodEntry, MethodEntry> copiedAccessToBridge = new HashMap<>(accessedToBridge); | ||
| 46 | |||
| 47 | for (Map.Entry<MethodEntry, MethodEntry> entry : copiedAccessToBridge.entrySet()) { | ||
| 48 | MethodEntry accessedEntry = entry.getKey(); | ||
| 49 | MethodEntry bridgeEntry = entry.getValue(); | ||
| 50 | if (bridgeEntry.getName().equals(accessedEntry.getName())) { | ||
| 51 | continue; | ||
| 52 | } | ||
| 53 | |||
| 54 | MethodEntry renamedAccessedEntry = accessedEntry.withName(bridgeEntry.getName()); | ||
| 55 | bridgeMethods.add(renamedAccessedEntry); | ||
| 56 | accessedToBridge.put(renamedAccessedEntry, accessedToBridge.get(accessedEntry)); | ||
| 57 | } | ||
| 58 | } | ||
| 59 | |||
| 48 | private void indexSyntheticMethod(MethodDefEntry syntheticMethod, AccessFlags access) { | 60 | private void indexSyntheticMethod(MethodDefEntry syntheticMethod, AccessFlags access) { |
| 49 | MethodEntry accessedMethod = findAccessMethod(syntheticMethod); | 61 | MethodEntry accessedMethod = findAccessMethod(syntheticMethod); |
| 50 | if (accessedMethod == null) { | 62 | if (accessedMethod == null) { |
| @@ -129,4 +141,8 @@ public class BridgeMethodIndex implements JarIndexer { | |||
| 129 | public MethodEntry getBridgeFromAccessed(MethodEntry entry) { | 141 | public MethodEntry getBridgeFromAccessed(MethodEntry entry) { |
| 130 | return accessedToBridge.get(entry); | 142 | return accessedToBridge.get(entry); |
| 131 | } | 143 | } |
| 144 | |||
| 145 | public Map<MethodEntry, MethodEntry> getAccessedToBridge() { | ||
| 146 | return Collections.unmodifiableMap(accessedToBridge); | ||
| 147 | } | ||
| 132 | } | 148 | } |
diff --git a/src/main/java/cuchaz/enigma/analysis/index/EntryIndex.java b/src/main/java/cuchaz/enigma/analysis/index/EntryIndex.java index 773eaf18..645110a7 100644 --- a/src/main/java/cuchaz/enigma/analysis/index/EntryIndex.java +++ b/src/main/java/cuchaz/enigma/analysis/index/EntryIndex.java | |||
| @@ -28,6 +28,18 @@ public class EntryIndex implements JarIndexer { | |||
| 28 | fields.put(fieldEntry, fieldEntry.getAccess()); | 28 | fields.put(fieldEntry, fieldEntry.getAccess()); |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | @Override | ||
| 32 | public void processIndex(JarIndex index) { | ||
| 33 | Map<MethodEntry, MethodEntry> accessedToBridge = index.getBridgeMethodIndex().getAccessedToBridge(); | ||
| 34 | for (Map.Entry<MethodEntry, MethodEntry> entry : accessedToBridge.entrySet()) { | ||
| 35 | MethodEntry accessedEntry = entry.getKey(); | ||
| 36 | MethodEntry bridgeEntry = entry.getValue(); | ||
| 37 | |||
| 38 | MethodEntry renamedAccessedEntry = accessedEntry.withName(bridgeEntry.getName()); | ||
| 39 | methods.put(renamedAccessedEntry, methods.remove(accessedEntry)); | ||
| 40 | } | ||
| 41 | } | ||
| 42 | |||
| 31 | public boolean hasClass(ClassEntry entry) { | 43 | public boolean hasClass(ClassEntry entry) { |
| 32 | return classes.containsKey(entry); | 44 | return classes.containsKey(entry); |
| 33 | } | 45 | } |
diff --git a/src/main/java/cuchaz/enigma/analysis/index/JarIndex.java b/src/main/java/cuchaz/enigma/analysis/index/JarIndex.java index cb58fced..a429ff6e 100644 --- a/src/main/java/cuchaz/enigma/analysis/index/JarIndex.java +++ b/src/main/java/cuchaz/enigma/analysis/index/JarIndex.java | |||
| @@ -53,19 +53,22 @@ public class JarIndex implements JarIndexer { | |||
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | public void indexJar(ParsedJar jar, Consumer<String> progress) { | 55 | public void indexJar(ParsedJar jar, Consumer<String> progress) { |
| 56 | progress.accept("Indexing entries (1/3)"); | 56 | progress.accept("Indexing entries (1/4)"); |
| 57 | jar.visitReader(name -> new IndexClassVisitor(this, Opcodes.ASM5), ClassReader.SKIP_CODE); | 57 | jar.visitReader(name -> new IndexClassVisitor(this, Opcodes.ASM5), ClassReader.SKIP_CODE); |
| 58 | 58 | ||
| 59 | progress.accept("Indexing entry references (2/3)"); | 59 | progress.accept("Indexing entry references (2/4)"); |
| 60 | jar.visitReader(name -> new IndexReferenceVisitor(this, Opcodes.ASM5), ClassReader.SKIP_FRAMES); | 60 | jar.visitReader(name -> new IndexReferenceVisitor(this, Opcodes.ASM5), ClassReader.SKIP_FRAMES); |
| 61 | 61 | ||
| 62 | progress.accept("Processing index (3/3)"); | 62 | progress.accept("Finding bridge methods (3/4)"); |
| 63 | processIndex(entryResolver); | 63 | bridgeMethodIndex.findBridgeMethods(); |
| 64 | |||
| 65 | progress.accept("Processing index (4/4)"); | ||
| 66 | processIndex(this); | ||
| 64 | } | 67 | } |
| 65 | 68 | ||
| 66 | @Override | 69 | @Override |
| 67 | public void processIndex(EntryResolver resolver) { | 70 | public void processIndex(JarIndex index) { |
| 68 | indexers.forEach(indexer -> indexer.processIndex(entryResolver)); | 71 | indexers.forEach(indexer -> indexer.processIndex(index)); |
| 69 | } | 72 | } |
| 70 | 73 | ||
| 71 | @Override | 74 | @Override |
diff --git a/src/main/java/cuchaz/enigma/analysis/index/JarIndexer.java b/src/main/java/cuchaz/enigma/analysis/index/JarIndexer.java index a087e598..457c2237 100644 --- a/src/main/java/cuchaz/enigma/analysis/index/JarIndexer.java +++ b/src/main/java/cuchaz/enigma/analysis/index/JarIndexer.java | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | package cuchaz.enigma.analysis.index; | 1 | package cuchaz.enigma.analysis.index; |
| 2 | 2 | ||
| 3 | import cuchaz.enigma.translation.mapping.EntryResolver; | ||
| 4 | import cuchaz.enigma.translation.representation.entry.*; | 3 | import cuchaz.enigma.translation.representation.entry.*; |
| 5 | 4 | ||
| 6 | public interface JarIndexer { | 5 | public interface JarIndexer { |
| @@ -19,6 +18,6 @@ public interface JarIndexer { | |||
| 19 | default void indexFieldReference(MethodDefEntry callerEntry, FieldEntry referencedEntry) { | 18 | default void indexFieldReference(MethodDefEntry callerEntry, FieldEntry referencedEntry) { |
| 20 | } | 19 | } |
| 21 | 20 | ||
| 22 | default void processIndex(EntryResolver resolver) { | 21 | default void processIndex(JarIndex index) { |
| 23 | } | 22 | } |
| 24 | } | 23 | } |
diff --git a/src/main/java/cuchaz/enigma/analysis/index/ReferenceIndex.java b/src/main/java/cuchaz/enigma/analysis/index/ReferenceIndex.java index ac11da46..ee28b3e7 100644 --- a/src/main/java/cuchaz/enigma/analysis/index/ReferenceIndex.java +++ b/src/main/java/cuchaz/enigma/analysis/index/ReferenceIndex.java | |||
| @@ -3,12 +3,12 @@ package cuchaz.enigma.analysis.index; | |||
| 3 | import com.google.common.collect.HashMultimap; | 3 | import com.google.common.collect.HashMultimap; |
| 4 | import com.google.common.collect.Multimap; | 4 | import com.google.common.collect.Multimap; |
| 5 | import cuchaz.enigma.analysis.EntryReference; | 5 | import cuchaz.enigma.analysis.EntryReference; |
| 6 | import cuchaz.enigma.translation.mapping.EntryResolver; | ||
| 7 | import cuchaz.enigma.translation.mapping.ResolutionStrategy; | 6 | import cuchaz.enigma.translation.mapping.ResolutionStrategy; |
| 8 | import cuchaz.enigma.translation.representation.entry.*; | 7 | import cuchaz.enigma.translation.representation.entry.*; |
| 9 | 8 | ||
| 10 | import java.util.Collection; | 9 | import java.util.Collection; |
| 11 | import java.util.Map; | 10 | import java.util.Map; |
| 11 | import java.util.Optional; | ||
| 12 | 12 | ||
| 13 | public class ReferenceIndex implements JarIndexer { | 13 | public class ReferenceIndex implements JarIndexer { |
| 14 | private Multimap<MethodEntry, MethodEntry> methodReferences = HashMultimap.create(); | 14 | private Multimap<MethodEntry, MethodEntry> methodReferences = HashMultimap.create(); |
| @@ -34,35 +34,54 @@ public class ReferenceIndex implements JarIndexer { | |||
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | @Override | 36 | @Override |
| 37 | public void processIndex(EntryResolver resolver) { | 37 | public void processIndex(JarIndex index) { |
| 38 | methodReferences = resolveReferences(resolver, methodReferences); | 38 | methodReferences = remapReferences(index, methodReferences); |
| 39 | referencesToMethods = resolveReferencesTo(resolver, referencesToMethods); | 39 | referencesToMethods = remapReferencesTo(index, referencesToMethods); |
| 40 | referencesToClasses = resolveReferencesTo(resolver, referencesToClasses); | 40 | referencesToClasses = remapReferencesTo(index, referencesToClasses); |
| 41 | referencesToFields = resolveReferencesTo(resolver, referencesToFields); | 41 | referencesToFields = remapReferencesTo(index, referencesToFields); |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | private <K extends Entry<?>, V extends Entry<?>> Multimap<K, V> resolveReferences(EntryResolver resolver, Multimap<K, V> multimap) { | 44 | private <K extends Entry<?>, V extends Entry<?>> Multimap<K, V> remapReferences(JarIndex index, Multimap<K, V> multimap) { |
| 45 | Multimap<K, V> resolved = HashMultimap.create(); | 45 | Multimap<K, V> resolved = HashMultimap.create(); |
| 46 | for (Map.Entry<K, V> entry : multimap.entries()) { | 46 | for (Map.Entry<K, V> entry : multimap.entries()) { |
| 47 | resolved.put(resolve(resolver, entry.getKey()), resolve(resolver, entry.getValue())); | 47 | resolved.put(remap(index, entry.getKey()), remap(index, entry.getValue())); |
| 48 | } | 48 | } |
| 49 | return resolved; | 49 | return resolved; |
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | private <E extends Entry<?>, C extends Entry<?>> Multimap<E, EntryReference<E, C>> resolveReferencesTo(EntryResolver resolver, Multimap<E, EntryReference<E, C>> multimap) { | 52 | private <E extends Entry<?>, C extends Entry<?>> Multimap<E, EntryReference<E, C>> remapReferencesTo(JarIndex index, Multimap<E, EntryReference<E, C>> multimap) { |
| 53 | Multimap<E, EntryReference<E, C>> resolved = HashMultimap.create(); | 53 | Multimap<E, EntryReference<E, C>> resolved = HashMultimap.create(); |
| 54 | for (Map.Entry<E, EntryReference<E, C>> entry : multimap.entries()) { | 54 | for (Map.Entry<E, EntryReference<E, C>> entry : multimap.entries()) { |
| 55 | resolved.put(resolve(resolver, entry.getKey()), resolve(resolver, entry.getValue())); | 55 | resolved.put(remap(index, entry.getKey()), remap(index, entry.getValue())); |
| 56 | } | 56 | } |
| 57 | return resolved; | 57 | return resolved; |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | private <E extends Entry<?>> E resolve(EntryResolver resolver, E entry) { | 60 | private <E extends Entry<?>> E remap(JarIndex index, E entry) { |
| 61 | return resolver.resolveFirstEntry(entry, ResolutionStrategy.RESOLVE_CLOSEST); | 61 | E resolvedEntry = index.getEntryResolver().resolveFirstEntry(entry, ResolutionStrategy.RESOLVE_CLOSEST); |
| 62 | |||
| 63 | Optional<E> remappedBridge = getRemappedBridge(index, resolvedEntry); | ||
| 64 | return remappedBridge.orElse(resolvedEntry); | ||
| 65 | } | ||
| 66 | |||
| 67 | private <E extends Entry<?>, C extends Entry<?>> EntryReference<E, C> remap(JarIndex index, EntryReference<E, C> reference) { | ||
| 68 | EntryReference<E, C> resolvedReference = index.getEntryResolver().resolveFirstReference(reference, ResolutionStrategy.RESOLVE_CLOSEST); | ||
| 69 | |||
| 70 | getRemappedBridge(index, resolvedReference.entry).ifPresent(e -> resolvedReference.entry = e); | ||
| 71 | getRemappedBridge(index, resolvedReference.context).ifPresent(e -> resolvedReference.context = e); | ||
| 72 | |||
| 73 | return resolvedReference; | ||
| 62 | } | 74 | } |
| 63 | 75 | ||
| 64 | private <E extends Entry<?>, C extends Entry<?>> EntryReference<E, C> resolve(EntryResolver resolver, EntryReference<E, C> reference) { | 76 | @SuppressWarnings("unchecked") |
| 65 | return resolver.resolveFirstReference(reference, ResolutionStrategy.RESOLVE_CLOSEST); | 77 | private <E extends Entry<?>> Optional<E> getRemappedBridge(JarIndex index, E entry) { |
| 78 | if (entry instanceof MethodEntry) { | ||
| 79 | MethodEntry bridgeEntry = index.getBridgeMethodIndex().getBridgeFromAccessed((MethodEntry) entry); | ||
| 80 | if (bridgeEntry != null) { | ||
| 81 | return Optional.of((E) entry.withName(bridgeEntry.getName())); | ||
| 82 | } | ||
| 83 | } | ||
| 84 | return Optional.empty(); | ||
| 66 | } | 85 | } |
| 67 | 86 | ||
| 68 | public Collection<MethodEntry> getMethodsReferencedBy(MethodEntry entry) { | 87 | public Collection<MethodEntry> getMethodsReferencedBy(MethodEntry entry) { |
diff --git a/src/main/java/cuchaz/enigma/gui/GuiController.java b/src/main/java/cuchaz/enigma/gui/GuiController.java index 45c61319..15211e01 100644 --- a/src/main/java/cuchaz/enigma/gui/GuiController.java +++ b/src/main/java/cuchaz/enigma/gui/GuiController.java | |||
| @@ -32,6 +32,7 @@ import cuchaz.enigma.translation.representation.entry.MethodEntry; | |||
| 32 | import cuchaz.enigma.utils.ReadableToken; | 32 | import cuchaz.enigma.utils.ReadableToken; |
| 33 | 33 | ||
| 34 | import javax.annotation.Nullable; | 34 | import javax.annotation.Nullable; |
| 35 | import javax.swing.*; | ||
| 35 | import java.awt.event.ItemEvent; | 36 | import java.awt.event.ItemEvent; |
| 36 | import java.io.File; | 37 | import java.io.File; |
| 37 | import java.io.IOException; | 38 | import java.io.IOException; |
| @@ -80,16 +81,22 @@ public class GuiController { | |||
| 80 | this.gui.onCloseJar(); | 81 | this.gui.onCloseJar(); |
| 81 | } | 82 | } |
| 82 | 83 | ||
| 83 | public void openMappings(MappingFormat format, Path path) throws IOException, MappingParseException { | 84 | public void openMappings(MappingFormat format, Path path) { |
| 84 | EntryTree<EntryMapping> mappings = format.read(path); | 85 | ProgressDialog.runInThread(this.gui.getFrame(), progress -> { |
| 85 | deobfuscator.setMappings(mappings); | 86 | try { |
| 87 | EntryTree<EntryMapping> mappings = format.read(path, progress); | ||
| 88 | deobfuscator.setMappings(mappings, progress); | ||
| 86 | 89 | ||
| 87 | gui.setMappingsFile(path); | 90 | gui.setMappingsFile(path); |
| 88 | loadedMappingFormat = format; | 91 | loadedMappingFormat = format; |
| 89 | loadedMappingPath = path; | 92 | loadedMappingPath = path; |
| 90 | 93 | ||
| 91 | refreshClasses(); | 94 | refreshClasses(); |
| 92 | refreshCurrentClass(); | 95 | refreshCurrentClass(); |
| 96 | } catch (MappingParseException e) { | ||
| 97 | JOptionPane.showMessageDialog(this.gui.getFrame(), e.getMessage()); | ||
| 98 | } | ||
| 99 | }); | ||
| 93 | } | 100 | } |
| 94 | 101 | ||
| 95 | public void saveMappings(Path path) { | 102 | public void saveMappings(Path path) { |
diff --git a/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java b/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java index 14ad53dc..d7be1a9d 100644 --- a/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java +++ b/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java | |||
| @@ -5,7 +5,6 @@ import cuchaz.enigma.config.Themes; | |||
| 5 | import cuchaz.enigma.gui.Gui; | 5 | import cuchaz.enigma.gui.Gui; |
| 6 | import cuchaz.enigma.gui.dialog.AboutDialog; | 6 | import cuchaz.enigma.gui.dialog.AboutDialog; |
| 7 | import cuchaz.enigma.gui.dialog.SearchDialog; | 7 | import cuchaz.enigma.gui.dialog.SearchDialog; |
| 8 | import cuchaz.enigma.throwables.MappingParseException; | ||
| 9 | import cuchaz.enigma.translation.mapping.serde.MappingFormat; | 8 | import cuchaz.enigma.translation.mapping.serde.MappingFormat; |
| 10 | 9 | ||
| 11 | import javax.swing.*; | 10 | import javax.swing.*; |
| @@ -68,15 +67,9 @@ public class MenuBar extends JMenuBar { | |||
| 68 | openMenu.add(item); | 67 | openMenu.add(item); |
| 69 | item.addActionListener(event -> { | 68 | item.addActionListener(event -> { |
| 70 | if (this.gui.enigmaMappingsFileChooser.showOpenDialog(this.gui.getFrame()) == JFileChooser.APPROVE_OPTION) { | 69 | if (this.gui.enigmaMappingsFileChooser.showOpenDialog(this.gui.getFrame()) == JFileChooser.APPROVE_OPTION) { |
| 71 | try { | 70 | File selectedFile = this.gui.enigmaMappingsFileChooser.getSelectedFile(); |
| 72 | File selectedFile = this.gui.enigmaMappingsFileChooser.getSelectedFile(); | 71 | MappingFormat format = selectedFile.isDirectory() ? MappingFormat.ENIGMA_DIRECTORY : MappingFormat.ENIGMA_FILE; |
| 73 | MappingFormat format = selectedFile.isDirectory() ? MappingFormat.ENIGMA_DIRECTORY : MappingFormat.ENIGMA_FILE; | 72 | this.gui.getController().openMappings(format, selectedFile.toPath()); |
| 74 | this.gui.getController().openMappings(format, selectedFile.toPath()); | ||
| 75 | } catch (IOException ex) { | ||
| 76 | throw new Error(ex); | ||
| 77 | } catch (MappingParseException ex) { | ||
| 78 | JOptionPane.showMessageDialog(this.gui.getFrame(), ex.getMessage()); | ||
| 79 | } | ||
| 80 | } | 73 | } |
| 81 | }); | 74 | }); |
| 82 | this.openEnigmaMappingsMenu = item; | 75 | this.openEnigmaMappingsMenu = item; |
| @@ -87,13 +80,7 @@ public class MenuBar extends JMenuBar { | |||
| 87 | this.gui.tinyMappingsFileChooser.setVisible(true); | 80 | this.gui.tinyMappingsFileChooser.setVisible(true); |
| 88 | File file = new File(this.gui.tinyMappingsFileChooser.getDirectory() + File.separator + this.gui.tinyMappingsFileChooser.getFile()); | 81 | File file = new File(this.gui.tinyMappingsFileChooser.getDirectory() + File.separator + this.gui.tinyMappingsFileChooser.getFile()); |
| 89 | if (file.exists()) { | 82 | if (file.exists()) { |
| 90 | try { | 83 | this.gui.getController().openMappings(MappingFormat.TINY_FILE, file.toPath()); |
| 91 | this.gui.getController().openMappings(MappingFormat.TINY_FILE, file.toPath()); | ||
| 92 | } catch (IOException ex) { | ||
| 93 | throw new Error(ex); | ||
| 94 | } catch (MappingParseException ex) { | ||
| 95 | JOptionPane.showMessageDialog(this.gui.getFrame(), ex.getMessage()); | ||
| 96 | } | ||
| 97 | } | 84 | } |
| 98 | }); | 85 | }); |
| 99 | this.openTinyMappingsMenu = item; | 86 | this.openTinyMappingsMenu = item; |
diff --git a/src/main/java/cuchaz/enigma/translation/Translator.java b/src/main/java/cuchaz/enigma/translation/Translator.java index de2003e8..c70141f2 100644 --- a/src/main/java/cuchaz/enigma/translation/Translator.java +++ b/src/main/java/cuchaz/enigma/translation/Translator.java | |||
| @@ -17,6 +17,7 @@ import com.google.common.collect.Multimap; | |||
| 17 | import java.util.Collection; | 17 | import java.util.Collection; |
| 18 | import java.util.HashMap; | 18 | import java.util.HashMap; |
| 19 | import java.util.Map; | 19 | import java.util.Map; |
| 20 | import java.util.Set; | ||
| 20 | import java.util.stream.Collectors; | 21 | import java.util.stream.Collectors; |
| 21 | 22 | ||
| 22 | public interface Translator { | 23 | public interface Translator { |
| @@ -28,6 +29,12 @@ public interface Translator { | |||
| 28 | .collect(Collectors.toList()); | 29 | .collect(Collectors.toList()); |
| 29 | } | 30 | } |
| 30 | 31 | ||
| 32 | default <T extends Translatable> Set<T> translate(Set<T> translatable) { | ||
| 33 | return translatable.stream() | ||
| 34 | .map(this::translate) | ||
| 35 | .collect(Collectors.toSet()); | ||
| 36 | } | ||
| 37 | |||
| 31 | default <T extends Translatable, V> Map<T, V> translateKeys(Map<T, V> translatable) { | 38 | default <T extends Translatable, V> Map<T, V> translateKeys(Map<T, V> translatable) { |
| 32 | Map<T, V> result = new HashMap<>(translatable.size()); | 39 | Map<T, V> result = new HashMap<>(translatable.size()); |
| 33 | for (Map.Entry<T, V> entry : translatable.entrySet()) { | 40 | for (Map.Entry<T, V> entry : translatable.entrySet()) { |
diff --git a/src/main/java/cuchaz/enigma/translation/mapping/EntryMap.java b/src/main/java/cuchaz/enigma/translation/mapping/EntryMap.java index 6af48466..e1a32533 100644 --- a/src/main/java/cuchaz/enigma/translation/mapping/EntryMap.java +++ b/src/main/java/cuchaz/enigma/translation/mapping/EntryMap.java | |||
| @@ -3,7 +3,7 @@ package cuchaz.enigma.translation.mapping; | |||
| 3 | import cuchaz.enigma.translation.representation.entry.Entry; | 3 | import cuchaz.enigma.translation.representation.entry.Entry; |
| 4 | 4 | ||
| 5 | import javax.annotation.Nullable; | 5 | import javax.annotation.Nullable; |
| 6 | import java.util.Collection; | 6 | import java.util.stream.Stream; |
| 7 | 7 | ||
| 8 | public interface EntryMap<T> { | 8 | public interface EntryMap<T> { |
| 9 | void insert(Entry<?> entry, T value); | 9 | void insert(Entry<?> entry, T value); |
| @@ -18,7 +18,7 @@ public interface EntryMap<T> { | |||
| 18 | return get(entry) != null; | 18 | return get(entry) != null; |
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | Collection<Entry<?>> getAllEntries(); | 21 | Stream<Entry<?>> getAllEntries(); |
| 22 | 22 | ||
| 23 | boolean isEmpty(); | 23 | boolean isEmpty(); |
| 24 | } | 24 | } |
diff --git a/src/main/java/cuchaz/enigma/translation/mapping/EntryMapping.java b/src/main/java/cuchaz/enigma/translation/mapping/EntryMapping.java index f11cdefb..b74cc0b3 100644 --- a/src/main/java/cuchaz/enigma/translation/mapping/EntryMapping.java +++ b/src/main/java/cuchaz/enigma/translation/mapping/EntryMapping.java | |||
| @@ -27,4 +27,21 @@ public class EntryMapping { | |||
| 27 | } | 27 | } |
| 28 | return accessModifier; | 28 | return accessModifier; |
| 29 | } | 29 | } |
| 30 | |||
| 31 | @Override | ||
| 32 | public boolean equals(Object obj) { | ||
| 33 | if (obj == this) return true; | ||
| 34 | |||
| 35 | if (obj instanceof EntryMapping) { | ||
| 36 | EntryMapping mapping = (EntryMapping) obj; | ||
| 37 | return mapping.targetName.equals(targetName) && mapping.accessModifier.equals(accessModifier); | ||
| 38 | } | ||
| 39 | |||
| 40 | return false; | ||
| 41 | } | ||
| 42 | |||
| 43 | @Override | ||
| 44 | public int hashCode() { | ||
| 45 | return targetName.hashCode() + accessModifier.hashCode() * 31; | ||
| 46 | } | ||
| 30 | } | 47 | } |
diff --git a/src/main/java/cuchaz/enigma/translation/mapping/EntryRemapper.java b/src/main/java/cuchaz/enigma/translation/mapping/EntryRemapper.java index fa421b9f..ed9f8202 100644 --- a/src/main/java/cuchaz/enigma/translation/mapping/EntryRemapper.java +++ b/src/main/java/cuchaz/enigma/translation/mapping/EntryRemapper.java | |||
| @@ -11,6 +11,7 @@ import cuchaz.enigma.translation.representation.entry.Entry; | |||
| 11 | 11 | ||
| 12 | import javax.annotation.Nullable; | 12 | import javax.annotation.Nullable; |
| 13 | import java.util.Collection; | 13 | import java.util.Collection; |
| 14 | import java.util.stream.Stream; | ||
| 14 | 15 | ||
| 15 | public class EntryRemapper { | 16 | public class EntryRemapper { |
| 16 | private final DeltaTrackingTree<EntryMapping> obfToDeobf; | 17 | private final DeltaTrackingTree<EntryMapping> obfToDeobf; |
| @@ -69,14 +70,10 @@ public class EntryRemapper { | |||
| 69 | return deobfuscator; | 70 | return deobfuscator; |
| 70 | } | 71 | } |
| 71 | 72 | ||
| 72 | public Collection<Entry<?>> getObfEntries() { | 73 | public Stream<Entry<?>> getObfEntries() { |
| 73 | return obfToDeobf.getAllEntries(); | 74 | return obfToDeobf.getAllEntries(); |
| 74 | } | 75 | } |
| 75 | 76 | ||
| 76 | public Collection<Entry<?>> getObfRootEntries() { | ||
| 77 | return obfToDeobf.getRootEntries(); | ||
| 78 | } | ||
| 79 | |||
| 80 | public Collection<Entry<?>> getObfChildren(Entry<?> obfuscatedEntry) { | 77 | public Collection<Entry<?>> getObfChildren(Entry<?> obfuscatedEntry) { |
| 81 | return obfToDeobf.getChildren(obfuscatedEntry); | 78 | return obfToDeobf.getChildren(obfuscatedEntry); |
| 82 | } | 79 | } |
diff --git a/src/main/java/cuchaz/enigma/translation/mapping/IndexEntryResolver.java b/src/main/java/cuchaz/enigma/translation/mapping/IndexEntryResolver.java index 1f2290a0..6c8ed76d 100644 --- a/src/main/java/cuchaz/enigma/translation/mapping/IndexEntryResolver.java +++ b/src/main/java/cuchaz/enigma/translation/mapping/IndexEntryResolver.java | |||
| @@ -91,6 +91,8 @@ public class IndexEntryResolver implements EntryResolver { | |||
| 91 | Set<Entry<ClassEntry>> resolvedBridge = resolveChildEntry(bridgeMethod, strategy); | 91 | Set<Entry<ClassEntry>> resolvedBridge = resolveChildEntry(bridgeMethod, strategy); |
| 92 | if (!resolvedBridge.isEmpty()) { | 92 | if (!resolvedBridge.isEmpty()) { |
| 93 | return resolvedBridge; | 93 | return resolvedBridge; |
| 94 | } else { | ||
| 95 | return Collections.singleton(bridgeMethod); | ||
| 94 | } | 96 | } |
| 95 | } | 97 | } |
| 96 | } | 98 | } |
diff --git a/src/main/java/cuchaz/enigma/translation/mapping/MappingDelta.java b/src/main/java/cuchaz/enigma/translation/mapping/MappingDelta.java index 9f1f468b..1407bb60 100644 --- a/src/main/java/cuchaz/enigma/translation/mapping/MappingDelta.java +++ b/src/main/java/cuchaz/enigma/translation/mapping/MappingDelta.java | |||
| @@ -2,55 +2,53 @@ package cuchaz.enigma.translation.mapping; | |||
| 2 | 2 | ||
| 3 | import cuchaz.enigma.translation.Translatable; | 3 | import cuchaz.enigma.translation.Translatable; |
| 4 | import cuchaz.enigma.translation.Translator; | 4 | import cuchaz.enigma.translation.Translator; |
| 5 | import cuchaz.enigma.translation.mapping.tree.HashEntryTree; | ||
| 6 | import cuchaz.enigma.translation.mapping.tree.EntryTree; | 5 | import cuchaz.enigma.translation.mapping.tree.EntryTree; |
| 6 | import cuchaz.enigma.translation.mapping.tree.EntryTreeNode; | ||
| 7 | import cuchaz.enigma.translation.mapping.tree.HashEntryTree; | ||
| 7 | import cuchaz.enigma.translation.representation.entry.Entry; | 8 | import cuchaz.enigma.translation.representation.entry.Entry; |
| 8 | 9 | ||
| 10 | import java.util.stream.Stream; | ||
| 11 | |||
| 9 | public class MappingDelta<T> implements Translatable { | 12 | public class MappingDelta<T> implements Translatable { |
| 10 | public static final Object PLACEHOLDER = new Object(); | 13 | public static final Object PLACEHOLDER = new Object(); |
| 11 | 14 | ||
| 12 | private final EntryTree<T> baseMappings; | 15 | private final EntryTree<T> baseMappings; |
| 13 | 16 | ||
| 14 | private final EntryTree<Object> additions; | 17 | private final EntryTree<Object> changes; |
| 15 | private final EntryTree<Object> deletions; | ||
| 16 | 18 | ||
| 17 | public MappingDelta(EntryTree<T> baseMappings, EntryTree<Object> additions, EntryTree<Object> deletions) { | 19 | public MappingDelta(EntryTree<T> baseMappings, EntryTree<Object> changes) { |
| 18 | this.baseMappings = baseMappings; | 20 | this.baseMappings = baseMappings; |
| 19 | this.additions = additions; | 21 | this.changes = changes; |
| 20 | this.deletions = deletions; | ||
| 21 | } | 22 | } |
| 22 | 23 | ||
| 23 | public MappingDelta(EntryTree<T> baseMappings) { | 24 | public MappingDelta(EntryTree<T> baseMappings) { |
| 24 | this(baseMappings, new HashEntryTree<>(), new HashEntryTree<>()); | 25 | this(baseMappings, new HashEntryTree<>()); |
| 25 | } | 26 | } |
| 26 | 27 | ||
| 27 | public static <T> MappingDelta<T> added(EntryTree<T> mappings) { | 28 | public static <T> MappingDelta<T> added(EntryTree<T> mappings) { |
| 28 | EntryTree<Object> additions = new HashEntryTree<>(); | 29 | EntryTree<Object> changes = new HashEntryTree<>(); |
| 29 | for (Entry<?> entry : mappings.getAllEntries()) { | 30 | mappings.getAllEntries().forEach(entry -> changes.insert(entry, PLACEHOLDER)); |
| 30 | additions.insert(entry, PLACEHOLDER); | ||
| 31 | } | ||
| 32 | 31 | ||
| 33 | return new MappingDelta<>(new HashEntryTree<>(), additions, new HashEntryTree<>()); | 32 | return new MappingDelta<>(new HashEntryTree<>(), changes); |
| 34 | } | 33 | } |
| 35 | 34 | ||
| 36 | public EntryTree<T> getBaseMappings() { | 35 | public EntryTree<T> getBaseMappings() { |
| 37 | return baseMappings; | 36 | return baseMappings; |
| 38 | } | 37 | } |
| 39 | 38 | ||
| 40 | public EntryTree<?> getAdditions() { | 39 | public EntryTree<?> getChanges() { |
| 41 | return additions; | 40 | return changes; |
| 42 | } | 41 | } |
| 43 | 42 | ||
| 44 | public EntryTree<?> getDeletions() { | 43 | public Stream<Entry<?>> getChangedRoots() { |
| 45 | return deletions; | 44 | return changes.getRootNodes().map(EntryTreeNode::getEntry); |
| 46 | } | 45 | } |
| 47 | 46 | ||
| 48 | @Override | 47 | @Override |
| 49 | public MappingDelta<T> translate(Translator translator, EntryResolver resolver, EntryMap<EntryMapping> mappings) { | 48 | public MappingDelta<T> translate(Translator translator, EntryResolver resolver, EntryMap<EntryMapping> mappings) { |
| 50 | return new MappingDelta<>( | 49 | return new MappingDelta<>( |
| 51 | translator.translate(baseMappings), | 50 | translator.translate(baseMappings), |
| 52 | translator.translate(additions), | 51 | translator.translate(changes) |
| 53 | translator.translate(deletions) | ||
| 54 | ); | 52 | ); |
| 55 | } | 53 | } |
| 56 | } | 54 | } |
diff --git a/src/main/java/cuchaz/enigma/translation/mapping/MappingsChecker.java b/src/main/java/cuchaz/enigma/translation/mapping/MappingsChecker.java index 77d75ecb..af9e63a2 100644 --- a/src/main/java/cuchaz/enigma/translation/mapping/MappingsChecker.java +++ b/src/main/java/cuchaz/enigma/translation/mapping/MappingsChecker.java | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | 11 | ||
| 12 | package cuchaz.enigma.translation.mapping; | 12 | package cuchaz.enigma.translation.mapping; |
| 13 | 13 | ||
| 14 | import cuchaz.enigma.ProgressListener; | ||
| 14 | import cuchaz.enigma.analysis.index.JarIndex; | 15 | import cuchaz.enigma.analysis.index.JarIndex; |
| 15 | import cuchaz.enigma.translation.mapping.tree.EntryTree; | 16 | import cuchaz.enigma.translation.mapping.tree.EntryTree; |
| 16 | import cuchaz.enigma.translation.mapping.tree.EntryTreeNode; | 17 | import cuchaz.enigma.translation.mapping.tree.EntryTreeNode; |
| @@ -22,6 +23,7 @@ import cuchaz.enigma.translation.representation.entry.MethodEntry; | |||
| 22 | import java.util.Collection; | 23 | import java.util.Collection; |
| 23 | import java.util.HashMap; | 24 | import java.util.HashMap; |
| 24 | import java.util.Map; | 25 | import java.util.Map; |
| 26 | import java.util.stream.Collectors; | ||
| 25 | 27 | ||
| 26 | public class MappingsChecker { | 28 | public class MappingsChecker { |
| 27 | private final JarIndex index; | 29 | private final JarIndex index; |
| @@ -32,14 +34,19 @@ public class MappingsChecker { | |||
| 32 | this.mappings = mappings; | 34 | this.mappings = mappings; |
| 33 | } | 35 | } |
| 34 | 36 | ||
| 35 | public Dropped dropBrokenMappings() { | 37 | public Dropped dropBrokenMappings(ProgressListener progress) { |
| 36 | Dropped dropped = new Dropped(); | 38 | Dropped dropped = new Dropped(); |
| 37 | 39 | ||
| 38 | Collection<Entry<?>> obfEntries = mappings.getAllEntries(); | 40 | Collection<Entry<?>> obfEntries = mappings.getAllEntries() |
| 41 | .filter(e -> e instanceof ClassEntry || e instanceof MethodEntry || e instanceof FieldEntry) | ||
| 42 | .collect(Collectors.toList()); | ||
| 43 | |||
| 44 | progress.init(obfEntries.size(), "Checking for dropped mappings"); | ||
| 45 | |||
| 46 | int steps = 0; | ||
| 39 | for (Entry<?> entry : obfEntries) { | 47 | for (Entry<?> entry : obfEntries) { |
| 40 | if (entry instanceof ClassEntry || entry instanceof MethodEntry || entry instanceof FieldEntry) { | 48 | progress.step(steps++, entry.toString()); |
| 41 | tryDropEntry(dropped, entry); | 49 | tryDropEntry(dropped, entry); |
| 42 | } | ||
| 43 | } | 50 | } |
| 44 | 51 | ||
| 45 | dropped.apply(mappings); | 52 | dropped.apply(mappings); |
diff --git a/src/main/java/cuchaz/enigma/translation/mapping/serde/EnigmaMappingsReader.java b/src/main/java/cuchaz/enigma/translation/mapping/serde/EnigmaMappingsReader.java index d36bc0bc..3f61325d 100644 --- a/src/main/java/cuchaz/enigma/translation/mapping/serde/EnigmaMappingsReader.java +++ b/src/main/java/cuchaz/enigma/translation/mapping/serde/EnigmaMappingsReader.java | |||
| @@ -1,12 +1,13 @@ | |||
| 1 | package cuchaz.enigma.translation.mapping.serde; | 1 | package cuchaz.enigma.translation.mapping.serde; |
| 2 | 2 | ||
| 3 | import com.google.common.base.Charsets; | 3 | import com.google.common.base.Charsets; |
| 4 | import cuchaz.enigma.ProgressListener; | ||
| 4 | import cuchaz.enigma.throwables.MappingParseException; | 5 | import cuchaz.enigma.throwables.MappingParseException; |
| 5 | import cuchaz.enigma.translation.mapping.AccessModifier; | 6 | import cuchaz.enigma.translation.mapping.AccessModifier; |
| 6 | import cuchaz.enigma.translation.mapping.EntryMapping; | 7 | import cuchaz.enigma.translation.mapping.EntryMapping; |
| 7 | import cuchaz.enigma.translation.mapping.MappingPair; | 8 | import cuchaz.enigma.translation.mapping.MappingPair; |
| 8 | import cuchaz.enigma.translation.mapping.tree.HashEntryTree; | ||
| 9 | import cuchaz.enigma.translation.mapping.tree.EntryTree; | 9 | import cuchaz.enigma.translation.mapping.tree.EntryTree; |
| 10 | import cuchaz.enigma.translation.mapping.tree.HashEntryTree; | ||
| 10 | import cuchaz.enigma.translation.representation.MethodDescriptor; | 11 | import cuchaz.enigma.translation.representation.MethodDescriptor; |
| 11 | import cuchaz.enigma.translation.representation.TypeDescriptor; | 12 | import cuchaz.enigma.translation.representation.TypeDescriptor; |
| 12 | import cuchaz.enigma.translation.representation.entry.*; | 13 | import cuchaz.enigma.translation.representation.entry.*; |
| @@ -24,22 +25,32 @@ import java.util.stream.Collectors; | |||
| 24 | public enum EnigmaMappingsReader implements MappingsReader { | 25 | public enum EnigmaMappingsReader implements MappingsReader { |
| 25 | FILE { | 26 | FILE { |
| 26 | @Override | 27 | @Override |
| 27 | public EntryTree<EntryMapping> read(Path path) throws IOException, MappingParseException { | 28 | public EntryTree<EntryMapping> read(Path path, ProgressListener progress) throws IOException, MappingParseException { |
| 29 | progress.init(1, "Loading mapping file"); | ||
| 30 | |||
| 28 | EntryTree<EntryMapping> mappings = new HashEntryTree<>(); | 31 | EntryTree<EntryMapping> mappings = new HashEntryTree<>(); |
| 29 | readFile(path, mappings); | 32 | readFile(path, mappings); |
| 33 | |||
| 34 | progress.step(1, "Done!"); | ||
| 35 | |||
| 30 | return mappings; | 36 | return mappings; |
| 31 | } | 37 | } |
| 32 | }, | 38 | }, |
| 33 | DIRECTORY { | 39 | DIRECTORY { |
| 34 | @Override | 40 | @Override |
| 35 | public EntryTree<EntryMapping> read(Path path) throws IOException, MappingParseException { | 41 | public EntryTree<EntryMapping> read(Path root, ProgressListener progress) throws IOException, MappingParseException { |
| 36 | EntryTree<EntryMapping> mappings = new HashEntryTree<>(); | 42 | EntryTree<EntryMapping> mappings = new HashEntryTree<>(); |
| 37 | 43 | ||
| 38 | List<Path> files = Files.walk(path) | 44 | List<Path> files = Files.walk(root) |
| 39 | .filter(f -> !Files.isDirectory(f)) | 45 | .filter(f -> !Files.isDirectory(f)) |
| 40 | .filter(f -> f.toString().endsWith(".mapping")) | 46 | .filter(f -> f.toString().endsWith(".mapping")) |
| 41 | .collect(Collectors.toList()); | 47 | .collect(Collectors.toList()); |
| 48 | |||
| 49 | progress.init(files.size(), "Loading mapping files"); | ||
| 50 | int step = 0; | ||
| 51 | |||
| 42 | for (Path file : files) { | 52 | for (Path file : files) { |
| 53 | progress.step(step++, root.relativize(file).toString()); | ||
| 43 | if (Files.isHidden(file)) { | 54 | if (Files.isHidden(file)) { |
| 44 | continue; | 55 | continue; |
| 45 | } | 56 | } |
diff --git a/src/main/java/cuchaz/enigma/translation/mapping/serde/EnigmaMappingsWriter.java b/src/main/java/cuchaz/enigma/translation/mapping/serde/EnigmaMappingsWriter.java index 8c55fa99..618bb0a7 100644 --- a/src/main/java/cuchaz/enigma/translation/mapping/serde/EnigmaMappingsWriter.java +++ b/src/main/java/cuchaz/enigma/translation/mapping/serde/EnigmaMappingsWriter.java | |||
| @@ -28,6 +28,7 @@ import java.nio.file.Path; | |||
| 28 | import java.nio.file.Paths; | 28 | import java.nio.file.Paths; |
| 29 | import java.util.ArrayList; | 29 | import java.util.ArrayList; |
| 30 | import java.util.Collection; | 30 | import java.util.Collection; |
| 31 | import java.util.Objects; | ||
| 31 | import java.util.concurrent.atomic.AtomicInteger; | 32 | import java.util.concurrent.atomic.AtomicInteger; |
| 32 | import java.util.stream.Collectors; | 33 | import java.util.stream.Collectors; |
| 33 | 34 | ||
| @@ -35,7 +36,7 @@ public enum EnigmaMappingsWriter implements MappingsWriter { | |||
| 35 | FILE { | 36 | FILE { |
| 36 | @Override | 37 | @Override |
| 37 | public void write(EntryTree<EntryMapping> mappings, MappingDelta<EntryMapping> delta, Path path, ProgressListener progress) { | 38 | public void write(EntryTree<EntryMapping> mappings, MappingDelta<EntryMapping> delta, Path path, ProgressListener progress) { |
| 38 | Collection<ClassEntry> classes = mappings.getRootEntries().stream() | 39 | Collection<ClassEntry> classes = mappings.getRootNodes() |
| 39 | .filter(entry -> entry instanceof ClassEntry) | 40 | .filter(entry -> entry instanceof ClassEntry) |
| 40 | .map(entry -> (ClassEntry) entry) | 41 | .map(entry -> (ClassEntry) entry) |
| 41 | .collect(Collectors.toList()); | 42 | .collect(Collectors.toList()); |
| @@ -56,19 +57,19 @@ public enum EnigmaMappingsWriter implements MappingsWriter { | |||
| 56 | DIRECTORY { | 57 | DIRECTORY { |
| 57 | @Override | 58 | @Override |
| 58 | public void write(EntryTree<EntryMapping> mappings, MappingDelta<EntryMapping> delta, Path path, ProgressListener progress) { | 59 | public void write(EntryTree<EntryMapping> mappings, MappingDelta<EntryMapping> delta, Path path, ProgressListener progress) { |
| 59 | applyDeletions(delta.getBaseMappings(), delta.getDeletions(), path); | 60 | Collection<ClassEntry> changedClasses = delta.getChangedRoots() |
| 60 | |||
| 61 | Collection<ClassEntry> classes = delta.getAdditions().getRootEntries().stream() | ||
| 62 | .filter(entry -> entry instanceof ClassEntry) | 61 | .filter(entry -> entry instanceof ClassEntry) |
| 63 | .map(entry -> (ClassEntry) entry) | 62 | .map(entry -> (ClassEntry) entry) |
| 64 | .collect(Collectors.toList()); | 63 | .collect(Collectors.toList()); |
| 65 | 64 | ||
| 66 | progress.init(classes.size(), "Writing classes"); | 65 | applyDeletions(path, changedClasses, mappings, delta.getBaseMappings()); |
| 66 | |||
| 67 | progress.init(changedClasses.size(), "Writing classes"); | ||
| 67 | 68 | ||
| 68 | Translator translator = new MappingTranslator(mappings, VoidEntryResolver.INSTANCE); | ||
| 69 | AtomicInteger steps = new AtomicInteger(); | 69 | AtomicInteger steps = new AtomicInteger(); |
| 70 | 70 | ||
| 71 | classes.parallelStream().forEach(classEntry -> { | 71 | Translator translator = new MappingTranslator(mappings, VoidEntryResolver.INSTANCE); |
| 72 | changedClasses.parallelStream().forEach(classEntry -> { | ||
| 72 | progress.step(steps.getAndIncrement(), classEntry.getFullName()); | 73 | progress.step(steps.getAndIncrement(), classEntry.getFullName()); |
| 73 | 74 | ||
| 74 | try { | 75 | try { |
| @@ -86,12 +87,12 @@ public enum EnigmaMappingsWriter implements MappingsWriter { | |||
| 86 | }); | 87 | }); |
| 87 | } | 88 | } |
| 88 | 89 | ||
| 89 | private void applyDeletions(EntryTree<EntryMapping> baseMappings, EntryTree<?> deletions, Path root) { | 90 | private void applyDeletions(Path root, Collection<ClassEntry> changedClasses, EntryTree<EntryMapping> mappings, EntryTree<EntryMapping> oldMappings) { |
| 90 | Translator oldMappingTranslator = new MappingTranslator(baseMappings, VoidEntryResolver.INSTANCE); | 91 | Translator oldMappingTranslator = new MappingTranslator(oldMappings, VoidEntryResolver.INSTANCE); |
| 91 | 92 | ||
| 92 | Collection<ClassEntry> deletedClasses = deletions.getRootEntries().stream() | 93 | Collection<ClassEntry> deletedClasses = changedClasses.stream() |
| 93 | .filter(e -> e instanceof ClassEntry) | 94 | .filter(e -> !Objects.equals(oldMappings.get(e), mappings.get(e))) |
| 94 | .map(e -> oldMappingTranslator.translate((ClassEntry) e)) | 95 | .map(oldMappingTranslator::translate) |
| 95 | .collect(Collectors.toList()); | 96 | .collect(Collectors.toList()); |
| 96 | 97 | ||
| 97 | for (ClassEntry classEntry : deletedClasses) { | 98 | for (ClassEntry classEntry : deletedClasses) { |
diff --git a/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingFormat.java b/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingFormat.java index 622a0e15..25283523 100644 --- a/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingFormat.java +++ b/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingFormat.java | |||
| @@ -35,11 +35,11 @@ public enum MappingFormat { | |||
| 35 | writer.write(mappings, delta, path, progressListener); | 35 | writer.write(mappings, delta, path, progressListener); |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | public EntryTree<EntryMapping> read(Path path) throws IOException, MappingParseException { | 38 | public EntryTree<EntryMapping> read(Path path, ProgressListener progressListener) throws IOException, MappingParseException { |
| 39 | if (reader == null) { | 39 | if (reader == null) { |
| 40 | throw new IllegalStateException(name() + " does not support reading"); | 40 | throw new IllegalStateException(name() + " does not support reading"); |
| 41 | } | 41 | } |
| 42 | return reader.read(path); | 42 | return reader.read(path, progressListener); |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | @Nullable | 45 | @Nullable |
diff --git a/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingsReader.java b/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingsReader.java index f239ee67..af0933f6 100644 --- a/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingsReader.java +++ b/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingsReader.java | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | package cuchaz.enigma.translation.mapping.serde; | 1 | package cuchaz.enigma.translation.mapping.serde; |
| 2 | 2 | ||
| 3 | import cuchaz.enigma.ProgressListener; | ||
| 3 | import cuchaz.enigma.throwables.MappingParseException; | 4 | import cuchaz.enigma.throwables.MappingParseException; |
| 4 | import cuchaz.enigma.translation.mapping.EntryMapping; | 5 | import cuchaz.enigma.translation.mapping.EntryMapping; |
| 5 | import cuchaz.enigma.translation.mapping.tree.EntryTree; | 6 | import cuchaz.enigma.translation.mapping.tree.EntryTree; |
| @@ -8,5 +9,5 @@ import java.io.IOException; | |||
| 8 | import java.nio.file.Path; | 9 | import java.nio.file.Path; |
| 9 | 10 | ||
| 10 | public interface MappingsReader { | 11 | public interface MappingsReader { |
| 11 | EntryTree<EntryMapping> read(Path path) throws MappingParseException, IOException; | 12 | EntryTree<EntryMapping> read(Path path, ProgressListener progress) throws MappingParseException, IOException; |
| 12 | } | 13 | } |
diff --git a/src/main/java/cuchaz/enigma/translation/mapping/serde/TinyMappingsReader.java b/src/main/java/cuchaz/enigma/translation/mapping/serde/TinyMappingsReader.java index e0afc3e8..69d82354 100644 --- a/src/main/java/cuchaz/enigma/translation/mapping/serde/TinyMappingsReader.java +++ b/src/main/java/cuchaz/enigma/translation/mapping/serde/TinyMappingsReader.java | |||
| @@ -1,11 +1,12 @@ | |||
| 1 | package cuchaz.enigma.translation.mapping.serde; | 1 | package cuchaz.enigma.translation.mapping.serde; |
| 2 | 2 | ||
| 3 | import com.google.common.base.Charsets; | 3 | import com.google.common.base.Charsets; |
| 4 | import cuchaz.enigma.ProgressListener; | ||
| 4 | import cuchaz.enigma.throwables.MappingParseException; | 5 | import cuchaz.enigma.throwables.MappingParseException; |
| 5 | import cuchaz.enigma.translation.mapping.EntryMapping; | 6 | import cuchaz.enigma.translation.mapping.EntryMapping; |
| 6 | import cuchaz.enigma.translation.mapping.MappingPair; | 7 | import cuchaz.enigma.translation.mapping.MappingPair; |
| 7 | import cuchaz.enigma.translation.mapping.tree.HashEntryTree; | ||
| 8 | import cuchaz.enigma.translation.mapping.tree.EntryTree; | 8 | import cuchaz.enigma.translation.mapping.tree.EntryTree; |
| 9 | import cuchaz.enigma.translation.mapping.tree.HashEntryTree; | ||
| 9 | import cuchaz.enigma.translation.representation.MethodDescriptor; | 10 | import cuchaz.enigma.translation.representation.MethodDescriptor; |
| 10 | import cuchaz.enigma.translation.representation.TypeDescriptor; | 11 | import cuchaz.enigma.translation.representation.TypeDescriptor; |
| 11 | import cuchaz.enigma.translation.representation.entry.ClassEntry; | 12 | import cuchaz.enigma.translation.representation.entry.ClassEntry; |
| @@ -22,15 +23,19 @@ public enum TinyMappingsReader implements MappingsReader { | |||
| 22 | INSTANCE; | 23 | INSTANCE; |
| 23 | 24 | ||
| 24 | @Override | 25 | @Override |
| 25 | public EntryTree<EntryMapping> read(Path path) throws IOException, MappingParseException { | 26 | public EntryTree<EntryMapping> read(Path path, ProgressListener progress) throws IOException, MappingParseException { |
| 26 | return read(path, Files.readAllLines(path, Charsets.UTF_8)); | 27 | return read(path, Files.readAllLines(path, Charsets.UTF_8), progress); |
| 27 | } | 28 | } |
| 28 | 29 | ||
| 29 | private EntryTree<EntryMapping> read(Path path, List<String> lines) throws MappingParseException { | 30 | private EntryTree<EntryMapping> read(Path path, List<String> lines, ProgressListener progress) throws MappingParseException { |
| 30 | EntryTree<EntryMapping> mappings = new HashEntryTree<>(); | 31 | EntryTree<EntryMapping> mappings = new HashEntryTree<>(); |
| 31 | lines.remove(0); | 32 | lines.remove(0); |
| 32 | 33 | ||
| 34 | progress.init(lines.size(), "Loading mapping file"); | ||
| 35 | |||
| 33 | for (int lineNumber = 0; lineNumber < lines.size(); lineNumber++) { | 36 | for (int lineNumber = 0; lineNumber < lines.size(); lineNumber++) { |
| 37 | progress.step(lineNumber, ""); | ||
| 38 | |||
| 34 | String line = lines.get(lineNumber); | 39 | String line = lines.get(lineNumber); |
| 35 | 40 | ||
| 36 | try { | 41 | try { |
diff --git a/src/main/java/cuchaz/enigma/translation/mapping/tree/DeltaTrackingTree.java b/src/main/java/cuchaz/enigma/translation/mapping/tree/DeltaTrackingTree.java index 36be5e1e..255fa5fb 100644 --- a/src/main/java/cuchaz/enigma/translation/mapping/tree/DeltaTrackingTree.java +++ b/src/main/java/cuchaz/enigma/translation/mapping/tree/DeltaTrackingTree.java | |||
| @@ -10,13 +10,13 @@ import cuchaz.enigma.translation.representation.entry.Entry; | |||
| 10 | import javax.annotation.Nullable; | 10 | import javax.annotation.Nullable; |
| 11 | import java.util.Collection; | 11 | import java.util.Collection; |
| 12 | import java.util.Iterator; | 12 | import java.util.Iterator; |
| 13 | import java.util.stream.Stream; | ||
| 13 | 14 | ||
| 14 | public class DeltaTrackingTree<T> implements EntryTree<T> { | 15 | public class DeltaTrackingTree<T> implements EntryTree<T> { |
| 15 | private final EntryTree<T> delegate; | 16 | private final EntryTree<T> delegate; |
| 16 | 17 | ||
| 17 | private EntryTree<T> deltaReference; | 18 | private EntryTree<T> deltaReference; |
| 18 | private EntryTree<Object> additions = new HashEntryTree<>(); | 19 | private EntryTree<Object> changes = new HashEntryTree<>(); |
| 19 | private EntryTree<Object> deletions = new HashEntryTree<>(); | ||
| 20 | 20 | ||
| 21 | public DeltaTrackingTree(EntryTree<T> delegate) { | 21 | public DeltaTrackingTree(EntryTree<T> delegate) { |
| 22 | this.delegate = delegate; | 22 | this.delegate = delegate; |
| @@ -29,30 +29,19 @@ public class DeltaTrackingTree<T> implements EntryTree<T> { | |||
| 29 | 29 | ||
| 30 | @Override | 30 | @Override |
| 31 | public void insert(Entry<?> entry, T value) { | 31 | public void insert(Entry<?> entry, T value) { |
| 32 | if (value != null) { | 32 | trackChange(entry); |
| 33 | trackAddition(entry); | ||
| 34 | } else { | ||
| 35 | trackDeletion(entry); | ||
| 36 | } | ||
| 37 | delegate.insert(entry, value); | 33 | delegate.insert(entry, value); |
| 38 | } | 34 | } |
| 39 | 35 | ||
| 40 | @Nullable | 36 | @Nullable |
| 41 | @Override | 37 | @Override |
| 42 | public T remove(Entry<?> entry) { | 38 | public T remove(Entry<?> entry) { |
| 43 | T value = delegate.remove(entry); | 39 | trackChange(entry); |
| 44 | trackDeletion(entry); | 40 | return delegate.remove(entry); |
| 45 | return value; | ||
| 46 | } | 41 | } |
| 47 | 42 | ||
| 48 | public void trackAddition(Entry<?> entry) { | 43 | public void trackChange(Entry<?> entry) { |
| 49 | deletions.insert(entry, MappingDelta.PLACEHOLDER); | 44 | changes.insert(entry, MappingDelta.PLACEHOLDER); |
| 50 | additions.insert(entry, MappingDelta.PLACEHOLDER); | ||
| 51 | } | ||
| 52 | |||
| 53 | public void trackDeletion(Entry<?> entry) { | ||
| 54 | additions.remove(entry); | ||
| 55 | deletions.insert(entry, MappingDelta.PLACEHOLDER); | ||
| 56 | } | 45 | } |
| 57 | 46 | ||
| 58 | @Nullable | 47 | @Nullable |
| @@ -78,25 +67,19 @@ public class DeltaTrackingTree<T> implements EntryTree<T> { | |||
| 78 | } | 67 | } |
| 79 | 68 | ||
| 80 | @Override | 69 | @Override |
| 81 | public Collection<EntryTreeNode<T>> getAllNodes() { | 70 | public Stream<EntryTreeNode<T>> getRootNodes() { |
| 82 | return delegate.getAllNodes(); | 71 | return delegate.getRootNodes(); |
| 83 | } | ||
| 84 | |||
| 85 | @Override | ||
| 86 | public Collection<Entry<?>> getRootEntries() { | ||
| 87 | return delegate.getRootEntries(); | ||
| 88 | } | 72 | } |
| 89 | 73 | ||
| 90 | @Override | 74 | @Override |
| 91 | public DeltaTrackingTree<T> translate(Translator translator, EntryResolver resolver, EntryMap<EntryMapping> mappings) { | 75 | public DeltaTrackingTree<T> translate(Translator translator, EntryResolver resolver, EntryMap<EntryMapping> mappings) { |
| 92 | DeltaTrackingTree<T> translatedTree = new DeltaTrackingTree<>(delegate.translate(translator, resolver, mappings)); | 76 | DeltaTrackingTree<T> translatedTree = new DeltaTrackingTree<>(delegate.translate(translator, resolver, mappings)); |
| 93 | translatedTree.additions = additions.translate(translator, resolver, mappings); | 77 | translatedTree.changes = changes.translate(translator, resolver, mappings); |
| 94 | translatedTree.deletions = deletions.translate(translator, resolver, mappings); | ||
| 95 | return translatedTree; | 78 | return translatedTree; |
| 96 | } | 79 | } |
| 97 | 80 | ||
| 98 | @Override | 81 | @Override |
| 99 | public Collection<Entry<?>> getAllEntries() { | 82 | public Stream<Entry<?>> getAllEntries() { |
| 100 | return delegate.getAllEntries(); | 83 | return delegate.getAllEntries(); |
| 101 | } | 84 | } |
| 102 | 85 | ||
| @@ -111,18 +94,17 @@ public class DeltaTrackingTree<T> implements EntryTree<T> { | |||
| 111 | } | 94 | } |
| 112 | 95 | ||
| 113 | public MappingDelta<T> takeDelta() { | 96 | public MappingDelta<T> takeDelta() { |
| 114 | MappingDelta<T> delta = new MappingDelta<>(deltaReference, additions, deletions); | 97 | MappingDelta<T> delta = new MappingDelta<>(deltaReference, changes); |
| 115 | resetDelta(); | 98 | resetDelta(); |
| 116 | return delta; | 99 | return delta; |
| 117 | } | 100 | } |
| 118 | 101 | ||
| 119 | private void resetDelta() { | 102 | private void resetDelta() { |
| 120 | deltaReference = new HashEntryTree<>(delegate); | 103 | deltaReference = new HashEntryTree<>(delegate); |
| 121 | additions = new HashEntryTree<>(); | 104 | changes = new HashEntryTree<>(); |
| 122 | deletions = new HashEntryTree<>(); | ||
| 123 | } | 105 | } |
| 124 | 106 | ||
| 125 | public boolean isDirty() { | 107 | public boolean isDirty() { |
| 126 | return !additions.isEmpty() || !deletions.isEmpty(); | 108 | return !changes.isEmpty(); |
| 127 | } | 109 | } |
| 128 | } | 110 | } |
diff --git a/src/main/java/cuchaz/enigma/translation/mapping/tree/EntryTree.java b/src/main/java/cuchaz/enigma/translation/mapping/tree/EntryTree.java index 4f341f45..daaefcc1 100644 --- a/src/main/java/cuchaz/enigma/translation/mapping/tree/EntryTree.java +++ b/src/main/java/cuchaz/enigma/translation/mapping/tree/EntryTree.java | |||
| @@ -9,6 +9,7 @@ import cuchaz.enigma.translation.representation.entry.Entry; | |||
| 9 | 9 | ||
| 10 | import javax.annotation.Nullable; | 10 | import javax.annotation.Nullable; |
| 11 | import java.util.Collection; | 11 | import java.util.Collection; |
| 12 | import java.util.stream.Stream; | ||
| 12 | 13 | ||
| 13 | public interface EntryTree<T> extends EntryMap<T>, Iterable<EntryTreeNode<T>>, Translatable { | 14 | public interface EntryTree<T> extends EntryMap<T>, Iterable<EntryTreeNode<T>>, Translatable { |
| 14 | Collection<Entry<?>> getChildren(Entry<?> entry); | 15 | Collection<Entry<?>> getChildren(Entry<?> entry); |
| @@ -18,9 +19,7 @@ public interface EntryTree<T> extends EntryMap<T>, Iterable<EntryTreeNode<T>>, T | |||
| 18 | @Nullable | 19 | @Nullable |
| 19 | EntryTreeNode<T> findNode(Entry<?> entry); | 20 | EntryTreeNode<T> findNode(Entry<?> entry); |
| 20 | 21 | ||
| 21 | Collection<EntryTreeNode<T>> getAllNodes(); | 22 | Stream<EntryTreeNode<T>> getRootNodes(); |
| 22 | |||
| 23 | Collection<Entry<?>> getRootEntries(); | ||
| 24 | 23 | ||
| 25 | @Override | 24 | @Override |
| 26 | EntryTree<T> translate(Translator translator, EntryResolver resolver, EntryMap<EntryMapping> mappings); | 25 | EntryTree<T> translate(Translator translator, EntryResolver resolver, EntryMap<EntryMapping> mappings); |
diff --git a/src/main/java/cuchaz/enigma/translation/mapping/tree/EntryTreeNode.java b/src/main/java/cuchaz/enigma/translation/mapping/tree/EntryTreeNode.java index 734b60ce..affcd504 100644 --- a/src/main/java/cuchaz/enigma/translation/mapping/tree/EntryTreeNode.java +++ b/src/main/java/cuchaz/enigma/translation/mapping/tree/EntryTreeNode.java | |||
| @@ -33,4 +33,8 @@ public interface EntryTreeNode<T> { | |||
| 33 | .map(EntryTreeNode::getEntry) | 33 | .map(EntryTreeNode::getEntry) |
| 34 | .collect(Collectors.toList()); | 34 | .collect(Collectors.toList()); |
| 35 | } | 35 | } |
| 36 | |||
| 37 | default boolean hasValue() { | ||
| 38 | return getValue() != null; | ||
| 39 | } | ||
| 36 | } | 40 | } |
diff --git a/src/main/java/cuchaz/enigma/translation/mapping/tree/HashEntryTree.java b/src/main/java/cuchaz/enigma/translation/mapping/tree/HashEntryTree.java index c5fc473d..bb21de6f 100644 --- a/src/main/java/cuchaz/enigma/translation/mapping/tree/HashEntryTree.java +++ b/src/main/java/cuchaz/enigma/translation/mapping/tree/HashEntryTree.java | |||
| @@ -8,7 +8,9 @@ import cuchaz.enigma.translation.representation.entry.Entry; | |||
| 8 | 8 | ||
| 9 | import javax.annotation.Nullable; | 9 | import javax.annotation.Nullable; |
| 10 | import java.util.*; | 10 | import java.util.*; |
| 11 | import java.util.stream.Collectors; | 11 | import java.util.function.Function; |
| 12 | import java.util.stream.Stream; | ||
| 13 | import java.util.stream.StreamSupport; | ||
| 12 | 14 | ||
| 13 | public class HashEntryTree<T> implements EntryTree<T> { | 15 | public class HashEntryTree<T> implements EntryTree<T> { |
| 14 | private final Map<Entry<?>, HashTreeNode<T>> root = new HashMap<>(); | 16 | private final Map<Entry<?>, HashTreeNode<T>> root = new HashMap<>(); |
| @@ -17,7 +19,7 @@ public class HashEntryTree<T> implements EntryTree<T> { | |||
| 17 | } | 19 | } |
| 18 | 20 | ||
| 19 | public HashEntryTree(EntryTree<T> tree) { | 21 | public HashEntryTree(EntryTree<T> tree) { |
| 20 | for (EntryTreeNode<T> node : tree.getAllNodes()) { | 22 | for (EntryTreeNode<T> node : tree) { |
| 21 | insert(node.getEntry(), node.getValue()); | 23 | insert(node.getEntry(), node.getValue()); |
| 22 | } | 24 | } |
| 23 | } | 25 | } |
| @@ -151,31 +153,24 @@ public class HashEntryTree<T> implements EntryTree<T> { | |||
| 151 | } | 153 | } |
| 152 | 154 | ||
| 153 | @Override | 155 | @Override |
| 154 | @SuppressWarnings("unchecked") | ||
| 155 | public Iterator<EntryTreeNode<T>> iterator() { | 156 | public Iterator<EntryTreeNode<T>> iterator() { |
| 156 | Collection<EntryTreeNode<T>> values = (Collection) root.values(); | ||
| 157 | return values.iterator(); | ||
| 158 | } | ||
| 159 | |||
| 160 | @Override | ||
| 161 | public Collection<EntryTreeNode<T>> getAllNodes() { | ||
| 162 | Collection<EntryTreeNode<T>> nodes = new ArrayList<>(); | 157 | Collection<EntryTreeNode<T>> nodes = new ArrayList<>(); |
| 163 | for (EntryTreeNode<T> node : root.values()) { | 158 | for (EntryTreeNode<T> node : root.values()) { |
| 164 | nodes.addAll(node.getNodesRecursively()); | 159 | nodes.addAll(node.getNodesRecursively()); |
| 165 | } | 160 | } |
| 166 | return nodes; | 161 | return nodes.iterator(); |
| 167 | } | 162 | } |
| 168 | 163 | ||
| 169 | @Override | 164 | @Override |
| 170 | public Collection<Entry<?>> getAllEntries() { | 165 | public Stream<Entry<?>> getAllEntries() { |
| 171 | return getAllNodes().stream() | 166 | return StreamSupport.stream(spliterator(), false) |
| 172 | .map(EntryTreeNode::getEntry) | 167 | .filter(EntryTreeNode::hasValue) |
| 173 | .collect(Collectors.toList()); | 168 | .map(EntryTreeNode::getEntry); |
| 174 | } | 169 | } |
| 175 | 170 | ||
| 176 | @Override | 171 | @Override |
| 177 | public Collection<Entry<?>> getRootEntries() { | 172 | public Stream<EntryTreeNode<T>> getRootNodes() { |
| 178 | return root.keySet(); | 173 | return root.values().stream().map(Function.identity()); |
| 179 | } | 174 | } |
| 180 | 175 | ||
| 181 | @Override | 176 | @Override |
| @@ -186,7 +181,7 @@ public class HashEntryTree<T> implements EntryTree<T> { | |||
| 186 | @Override | 181 | @Override |
| 187 | public HashEntryTree<T> translate(Translator translator, EntryResolver resolver, EntryMap<EntryMapping> mappings) { | 182 | public HashEntryTree<T> translate(Translator translator, EntryResolver resolver, EntryMap<EntryMapping> mappings) { |
| 188 | HashEntryTree<T> translatedTree = new HashEntryTree<>(); | 183 | HashEntryTree<T> translatedTree = new HashEntryTree<>(); |
| 189 | for (EntryTreeNode<T> node : getAllNodes()) { | 184 | for (EntryTreeNode<T> node : this) { |
| 190 | translatedTree.insert(translator.translate(node.getEntry()), node.getValue()); | 185 | translatedTree.insert(translator.translate(node.getEntry()), node.getValue()); |
| 191 | } | 186 | } |
| 192 | return translatedTree; | 187 | return translatedTree; |
diff --git a/src/main/java/cuchaz/enigma/translation/representation/entry/ClassDefEntry.java b/src/main/java/cuchaz/enigma/translation/representation/entry/ClassDefEntry.java index b9391b04..c4df891c 100644 --- a/src/main/java/cuchaz/enigma/translation/representation/entry/ClassDefEntry.java +++ b/src/main/java/cuchaz/enigma/translation/representation/entry/ClassDefEntry.java | |||
| @@ -86,6 +86,11 @@ public class ClassDefEntry extends ClassEntry implements DefEntry<ClassEntry> { | |||
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | @Override | 88 | @Override |
| 89 | public ClassDefEntry withName(String name) { | ||
| 90 | return new ClassDefEntry(parent, name, signature, access, superClass, interfaces); | ||
| 91 | } | ||
| 92 | |||
| 93 | @Override | ||
| 89 | public ClassDefEntry withParent(ClassEntry parent) { | 94 | public ClassDefEntry withParent(ClassEntry parent) { |
| 90 | return new ClassDefEntry(parent, name, signature, access, superClass, interfaces); | 95 | return new ClassDefEntry(parent, name, signature, access, superClass, interfaces); |
| 91 | } | 96 | } |
diff --git a/src/main/java/cuchaz/enigma/translation/representation/entry/ClassEntry.java b/src/main/java/cuchaz/enigma/translation/representation/entry/ClassEntry.java index 644658fd..9bfcd8a8 100644 --- a/src/main/java/cuchaz/enigma/translation/representation/entry/ClassEntry.java +++ b/src/main/java/cuchaz/enigma/translation/representation/entry/ClassEntry.java | |||
| @@ -96,6 +96,11 @@ public class ClassEntry extends ParentedEntry<ClassEntry> implements Comparable< | |||
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | @Override | 98 | @Override |
| 99 | public ClassEntry withName(String name) { | ||
| 100 | return new ClassEntry(parent, name); | ||
| 101 | } | ||
| 102 | |||
| 103 | @Override | ||
| 99 | public ClassEntry withParent(ClassEntry parent) { | 104 | public ClassEntry withParent(ClassEntry parent) { |
| 100 | return new ClassEntry(parent, name); | 105 | return new ClassEntry(parent, name); |
| 101 | } | 106 | } |
| @@ -193,6 +198,11 @@ public class ClassEntry extends ParentedEntry<ClassEntry> implements Comparable< | |||
| 193 | 198 | ||
| 194 | @Override | 199 | @Override |
| 195 | public int compareTo(ClassEntry entry) { | 200 | public int compareTo(ClassEntry entry) { |
| 196 | return name.compareTo(entry.name); | 201 | String fullName = getFullName(); |
| 202 | String otherFullName = entry.getFullName(); | ||
| 203 | if (fullName.length() != otherFullName.length()) { | ||
| 204 | return fullName.length() - otherFullName.length(); | ||
| 205 | } | ||
| 206 | return fullName.compareTo(otherFullName); | ||
| 197 | } | 207 | } |
| 198 | } | 208 | } |
diff --git a/src/main/java/cuchaz/enigma/translation/representation/entry/Entry.java b/src/main/java/cuchaz/enigma/translation/representation/entry/Entry.java index 227400eb..29a55d89 100644 --- a/src/main/java/cuchaz/enigma/translation/representation/entry/Entry.java +++ b/src/main/java/cuchaz/enigma/translation/representation/entry/Entry.java | |||
| @@ -31,6 +31,8 @@ public interface Entry<P extends Entry<?>> extends Translatable { | |||
| 31 | 31 | ||
| 32 | Class<P> getParentType(); | 32 | Class<P> getParentType(); |
| 33 | 33 | ||
| 34 | Entry<P> withName(String name); | ||
| 35 | |||
| 34 | Entry<P> withParent(P parent); | 36 | Entry<P> withParent(P parent); |
| 35 | 37 | ||
| 36 | boolean canConflictWith(Entry<?> entry); | 38 | boolean canConflictWith(Entry<?> entry); |
diff --git a/src/main/java/cuchaz/enigma/translation/representation/entry/FieldDefEntry.java b/src/main/java/cuchaz/enigma/translation/representation/entry/FieldDefEntry.java index d487f71f..27033015 100644 --- a/src/main/java/cuchaz/enigma/translation/representation/entry/FieldDefEntry.java +++ b/src/main/java/cuchaz/enigma/translation/representation/entry/FieldDefEntry.java | |||
| @@ -55,6 +55,11 @@ public class FieldDefEntry extends FieldEntry implements DefEntry<ClassEntry> { | |||
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | @Override | 57 | @Override |
| 58 | public FieldDefEntry withName(String name) { | ||
| 59 | return new FieldDefEntry(parent, name, desc, signature, access); | ||
| 60 | } | ||
| 61 | |||
| 62 | @Override | ||
| 58 | public FieldDefEntry withParent(ClassEntry owner) { | 63 | public FieldDefEntry withParent(ClassEntry owner) { |
| 59 | return new FieldDefEntry(owner, this.name, this.desc, signature, access); | 64 | return new FieldDefEntry(owner, this.name, this.desc, signature, access); |
| 60 | } | 65 | } |
diff --git a/src/main/java/cuchaz/enigma/translation/representation/entry/FieldEntry.java b/src/main/java/cuchaz/enigma/translation/representation/entry/FieldEntry.java index 2ec24719..700512e2 100644 --- a/src/main/java/cuchaz/enigma/translation/representation/entry/FieldEntry.java +++ b/src/main/java/cuchaz/enigma/translation/representation/entry/FieldEntry.java | |||
| @@ -45,6 +45,11 @@ public class FieldEntry extends ParentedEntry<ClassEntry> implements Comparable< | |||
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | @Override | 47 | @Override |
| 48 | public FieldEntry withName(String name) { | ||
| 49 | return new FieldEntry(parent, name, desc); | ||
| 50 | } | ||
| 51 | |||
| 52 | @Override | ||
| 48 | public FieldEntry withParent(ClassEntry parent) { | 53 | public FieldEntry withParent(ClassEntry parent) { |
| 49 | return new FieldEntry(parent, this.name, this.desc); | 54 | return new FieldEntry(parent, this.name, this.desc); |
| 50 | } | 55 | } |
diff --git a/src/main/java/cuchaz/enigma/translation/representation/entry/LocalVariableDefEntry.java b/src/main/java/cuchaz/enigma/translation/representation/entry/LocalVariableDefEntry.java index 86bdf61c..c6f32b62 100644 --- a/src/main/java/cuchaz/enigma/translation/representation/entry/LocalVariableDefEntry.java +++ b/src/main/java/cuchaz/enigma/translation/representation/entry/LocalVariableDefEntry.java | |||
| @@ -34,6 +34,11 @@ public class LocalVariableDefEntry extends LocalVariableEntry { | |||
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | @Override | 36 | @Override |
| 37 | public LocalVariableDefEntry withName(String name) { | ||
| 38 | return new LocalVariableDefEntry(parent, index, name, parameter, desc); | ||
| 39 | } | ||
| 40 | |||
| 41 | @Override | ||
| 37 | public LocalVariableDefEntry withParent(MethodEntry entry) { | 42 | public LocalVariableDefEntry withParent(MethodEntry entry) { |
| 38 | return new LocalVariableDefEntry(entry, index, name, parameter, desc); | 43 | return new LocalVariableDefEntry(entry, index, name, parameter, desc); |
| 39 | } | 44 | } |
diff --git a/src/main/java/cuchaz/enigma/translation/representation/entry/LocalVariableEntry.java b/src/main/java/cuchaz/enigma/translation/representation/entry/LocalVariableEntry.java index 0c12f1c8..6fdb79fe 100644 --- a/src/main/java/cuchaz/enigma/translation/representation/entry/LocalVariableEntry.java +++ b/src/main/java/cuchaz/enigma/translation/representation/entry/LocalVariableEntry.java | |||
| @@ -52,6 +52,11 @@ public class LocalVariableEntry extends ParentedEntry<MethodEntry> implements Co | |||
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | @Override | 54 | @Override |
| 55 | public LocalVariableEntry withName(String name) { | ||
| 56 | return new LocalVariableEntry(parent, index, name, parameter); | ||
| 57 | } | ||
| 58 | |||
| 59 | @Override | ||
| 55 | public LocalVariableEntry withParent(MethodEntry parent) { | 60 | public LocalVariableEntry withParent(MethodEntry parent) { |
| 56 | return new LocalVariableEntry(parent, index, name, parameter); | 61 | return new LocalVariableEntry(parent, index, name, parameter); |
| 57 | } | 62 | } |
diff --git a/src/main/java/cuchaz/enigma/translation/representation/entry/MethodDefEntry.java b/src/main/java/cuchaz/enigma/translation/representation/entry/MethodDefEntry.java index 3ecd470f..51842443 100644 --- a/src/main/java/cuchaz/enigma/translation/representation/entry/MethodDefEntry.java +++ b/src/main/java/cuchaz/enigma/translation/representation/entry/MethodDefEntry.java | |||
| @@ -55,6 +55,11 @@ public class MethodDefEntry extends MethodEntry implements DefEntry<ClassEntry> | |||
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | @Override | 57 | @Override |
| 58 | public MethodDefEntry withName(String name) { | ||
| 59 | return new MethodDefEntry(parent, name, descriptor, signature, access); | ||
| 60 | } | ||
| 61 | |||
| 62 | @Override | ||
| 58 | public MethodDefEntry withParent(ClassEntry parent) { | 63 | public MethodDefEntry withParent(ClassEntry parent) { |
| 59 | return new MethodDefEntry(new ClassEntry(parent.getFullName()), name, descriptor, signature, access); | 64 | return new MethodDefEntry(new ClassEntry(parent.getFullName()), name, descriptor, signature, access); |
| 60 | } | 65 | } |
diff --git a/src/main/java/cuchaz/enigma/translation/representation/entry/MethodEntry.java b/src/main/java/cuchaz/enigma/translation/representation/entry/MethodEntry.java index 3a1dbb32..f5d5c744 100644 --- a/src/main/java/cuchaz/enigma/translation/representation/entry/MethodEntry.java +++ b/src/main/java/cuchaz/enigma/translation/representation/entry/MethodEntry.java | |||
| @@ -56,6 +56,11 @@ public class MethodEntry extends ParentedEntry<ClassEntry> implements Comparable | |||
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | @Override | 58 | @Override |
| 59 | public MethodEntry withName(String name) { | ||
| 60 | return new MethodEntry(parent, name, descriptor); | ||
| 61 | } | ||
| 62 | |||
| 63 | @Override | ||
| 59 | public MethodEntry withParent(ClassEntry parent) { | 64 | public MethodEntry withParent(ClassEntry parent) { |
| 60 | return new MethodEntry(new ClassEntry(parent.getFullName()), name, descriptor); | 65 | return new MethodEntry(new ClassEntry(parent.getFullName()), name, descriptor); |
| 61 | } | 66 | } |
diff --git a/src/main/java/cuchaz/enigma/translation/representation/entry/ParentedEntry.java b/src/main/java/cuchaz/enigma/translation/representation/entry/ParentedEntry.java index 7ba7c196..834da8de 100644 --- a/src/main/java/cuchaz/enigma/translation/representation/entry/ParentedEntry.java +++ b/src/main/java/cuchaz/enigma/translation/representation/entry/ParentedEntry.java | |||
| @@ -35,6 +35,9 @@ public abstract class ParentedEntry<P extends Entry<?>> implements Entry<P> { | |||
| 35 | @Override | 35 | @Override |
| 36 | public abstract ParentedEntry<P> withParent(P parent); | 36 | public abstract ParentedEntry<P> withParent(P parent); |
| 37 | 37 | ||
| 38 | @Override | ||
| 39 | public abstract ParentedEntry<P> withName(String name); | ||
| 40 | |||
| 38 | protected abstract ParentedEntry<P> translate(Translator translator, @Nullable EntryMapping mapping); | 41 | protected abstract ParentedEntry<P> translate(Translator translator, @Nullable EntryMapping mapping); |
| 39 | 42 | ||
| 40 | @Override | 43 | @Override |