From ba7a354efae7d49833c887cf147ac940c975a1fa Mon Sep 17 00:00:00 2001 From: Gegy Date: Wed, 30 Jan 2019 21:05:32 +0200 Subject: Remap sources (#106) * Source remapping beginnings * Fix navigation to remapped classes * Translate identifier info reference * Remap local variables with default names in source * Caching translator * Fix lack of highlighting for first opened class * Fix unicode variable names * Unicode checker shouldn't be checking just alphanumeric * Fix package tree being built from obf names * Don't index `this` as method call for method::reference * Apply proposed names * Fix source export issues * Replace unicode var names at bytecode level uniquely * Drop imports from editor source * Class selector fixes * Delta keep track of base mappings to enable lookup of old names * Optimize source remapping by remapping source with a StringBuffer instead of copying * Bump version --- .../enigma/translation/LocalNameGenerator.java | 44 ++++++++ .../enigma/translation/mapping/EntryRemapper.java | 125 ++------------------- .../enigma/translation/mapping/MappingDelta.java | 36 +++--- .../translation/mapping/MappingValidator.java | 14 ++- .../mapping/serde/EnigmaMappingsWriter.java | 19 ++-- .../translation/mapping/serde/MappingFormat.java | 2 +- .../translation/mapping/serde/MappingsWriter.java | 6 +- .../mapping/serde/SrgMappingsWriter.java | 2 +- .../mapping/tree/DeltaTrackingTree.java | 21 +++- .../enigma/translation/mapping/tree/EntryTree.java | 9 +- .../translation/mapping/tree/HashEntryTree.java | 22 ++++ .../representation/ProcyonEntryFactory.java | 18 +-- .../representation/ReferencedEntryPool.java | 60 ---------- .../translation/representation/Signature.java | 9 +- .../translation/representation/TypeDescriptor.java | 5 + .../representation/entry/ClassEntry.java | 11 ++ .../translation/representation/entry/Entry.java | 4 + .../representation/entry/LocalVariableEntry.java | 7 +- 18 files changed, 179 insertions(+), 235 deletions(-) create mode 100644 src/main/java/cuchaz/enigma/translation/LocalNameGenerator.java delete mode 100644 src/main/java/cuchaz/enigma/translation/representation/ReferencedEntryPool.java (limited to 'src/main/java/cuchaz/enigma/translation') diff --git a/src/main/java/cuchaz/enigma/translation/LocalNameGenerator.java b/src/main/java/cuchaz/enigma/translation/LocalNameGenerator.java new file mode 100644 index 0000000..18c966c --- /dev/null +++ b/src/main/java/cuchaz/enigma/translation/LocalNameGenerator.java @@ -0,0 +1,44 @@ +package cuchaz.enigma.translation; + +import cuchaz.enigma.translation.mapping.NameValidator; +import cuchaz.enigma.translation.representation.TypeDescriptor; + +import java.util.Collection; +import java.util.Locale; + +public class LocalNameGenerator { + public static String generateArgumentName(int index, TypeDescriptor desc, Collection arguments) { + boolean uniqueType = arguments.stream().filter(desc::equals).count() <= 1; + String translatedName; + int nameIndex = index + 1; + StringBuilder nameBuilder = new StringBuilder(getTypeName(desc)); + if (!uniqueType || NameValidator.isReserved(nameBuilder.toString())) { + nameBuilder.append(nameIndex); + } + translatedName = nameBuilder.toString(); + return translatedName; + } + + public static String generateLocalVariableName(int index, TypeDescriptor desc) { + int nameIndex = index + 1; + return getTypeName(desc) + nameIndex; + } + + private static String getTypeName(TypeDescriptor desc) { + // Unfortunately each of these have different name getters, so they have different code paths + if (desc.isPrimitive()) { + TypeDescriptor.Primitive argCls = desc.getPrimitive(); + return argCls.name().toLowerCase(Locale.ROOT); + } else if (desc.isArray()) { + // List types would require this whole block again, so just go with aListx + return "arr"; + } else if (desc.isType()) { + String typeName = desc.getTypeEntry().getSimpleName().replace("$", ""); + typeName = typeName.substring(0, 1).toLowerCase(Locale.ROOT) + typeName.substring(1); + return typeName; + } else { + System.err.println("Encountered invalid argument type descriptor " + desc.toString()); + return "var"; + } + } +} diff --git a/src/main/java/cuchaz/enigma/translation/mapping/EntryRemapper.java b/src/main/java/cuchaz/enigma/translation/mapping/EntryRemapper.java index b7d8d17..1203aba 100644 --- a/src/main/java/cuchaz/enigma/translation/mapping/EntryRemapper.java +++ b/src/main/java/cuchaz/enigma/translation/mapping/EntryRemapper.java @@ -6,7 +6,6 @@ import cuchaz.enigma.translation.Translatable; import cuchaz.enigma.translation.Translator; import cuchaz.enigma.translation.mapping.tree.DeltaTrackingTree; import cuchaz.enigma.translation.mapping.tree.EntryTree; -import cuchaz.enigma.translation.mapping.tree.EntryTreeNode; import cuchaz.enigma.translation.mapping.tree.HashEntryTree; import cuchaz.enigma.translation.representation.entry.Entry; @@ -14,59 +13,25 @@ import javax.annotation.Nullable; import java.util.Collection; public class EntryRemapper { - private final EntryTree obfToDeobf; - private final DeltaTrackingTree deobfToObf; - - private final JarIndex obfIndex; + private final DeltaTrackingTree obfToDeobf; private final EntryResolver obfResolver; - private EntryResolver deobfResolver; - private final Translator deobfuscator; - private Translator obfuscator; private final MappingValidator validator; - private EntryRemapper(JarIndex jarIndex, EntryTree obfToDeobf, EntryTree deobfToObf) { - this.obfToDeobf = obfToDeobf; - this.deobfToObf = new DeltaTrackingTree<>(deobfToObf); + public EntryRemapper(JarIndex jarIndex, EntryTree obfToDeobf) { + this.obfToDeobf = new DeltaTrackingTree<>(obfToDeobf); - this.obfIndex = jarIndex; this.obfResolver = jarIndex.getEntryResolver(); this.deobfuscator = new MappingTranslator(obfToDeobf, obfResolver); - rebuildDeobfIndex(); - this.validator = new MappingValidator(this.deobfToObf, deobfuscator, obfResolver); + this.validator = new MappingValidator(obfToDeobf, deobfuscator, obfResolver); } public EntryRemapper(JarIndex jarIndex) { - this(jarIndex, new HashEntryTree<>(), new HashEntryTree<>()); - } - - public EntryRemapper(JarIndex jarIndex, EntryTree deobfuscationTrees) { - this(jarIndex, deobfuscationTrees, inverse(deobfuscationTrees)); - } - - private static EntryTree inverse(EntryTree tree) { - Translator translator = new MappingTranslator(tree, VoidEntryResolver.INSTANCE); - EntryTree inverse = new HashEntryTree<>(); - - // Naive approach, could operate on the nodes of the tree. However, this runs infrequently. - Collection> entries = tree.getAllEntries(); - for (Entry sourceEntry : entries) { - Entry targetEntry = translator.translate(sourceEntry); - inverse.insert(targetEntry, new EntryMapping(sourceEntry.getName())); - } - - return inverse; - } - - private void rebuildDeobfIndex() { - JarIndex deobfIndex = obfIndex.remapped(deobfuscator); - - this.deobfResolver = deobfIndex.getEntryResolver(); - this.obfuscator = new MappingTranslator(deobfToObf, deobfResolver); + this(jarIndex, new HashEntryTree<>()); } public > void mapFromObf(E obfuscatedEntry, @Nullable EntryMapping deobfMapping) { @@ -76,84 +41,31 @@ public class EntryRemapper { validator.validateRename(resolvedEntry, deobfMapping.getTargetName()); } - setObfToDeobf(resolvedEntry, deobfMapping); + obfToDeobf.insert(obfuscatedEntry, deobfMapping); } - - // Temporary hack, not very performant - rebuildDeobfIndex(); - } - - public > void mapFromDeobf(E deobfuscatedEntry, @Nullable EntryMapping deobfMapping) { - E obfuscatedEntry = obfuscate(deobfuscatedEntry); - mapFromObf(obfuscatedEntry, deobfMapping); } public void removeByObf(Entry obfuscatedEntry) { mapFromObf(obfuscatedEntry, null); } - public void removeByDeobf(Entry deobfuscatedEntry) { - mapFromObf(obfuscate(deobfuscatedEntry), null); - } - - private > void setObfToDeobf(E obfuscatedEntry, @Nullable EntryMapping deobfMapping) { - E prevDeobf = deobfuscate(obfuscatedEntry); - obfToDeobf.insert(obfuscatedEntry, deobfMapping); - - E newDeobf = deobfuscate(obfuscatedEntry); - - // Reconstruct the children of this node in the deobf -> obf tree with our new mapping - // We only need to do this for deobf -> obf because the obf tree is always consistent on the left hand side - // We lookup by obf, and the obf never changes. This is not the case for deobf so we need to update the tree. - - EntryTreeNode node = deobfToObf.findNode(prevDeobf); - if (node != null) { - for (EntryTreeNode child : node.getNodesRecursively()) { - Entry entry = child.getEntry(); - EntryMapping mapping = new EntryMapping(obfuscate(entry).getName()); - - deobfToObf.insert(entry.replaceAncestor(prevDeobf, newDeobf), mapping); - deobfToObf.remove(entry); - } - } else { - deobfToObf.insert(newDeobf, new EntryMapping(obfuscatedEntry.getName())); - } - } - @Nullable public EntryMapping getDeobfMapping(Entry entry) { return obfToDeobf.get(entry); } - @Nullable - public EntryMapping getObfMapping(Entry entry) { - return deobfToObf.get(entry); - } - public boolean hasDeobfMapping(Entry obfEntry) { return obfToDeobf.contains(obfEntry); } - public boolean hasObfMapping(Entry deobfEntry) { - return deobfToObf.contains(deobfEntry); - } - public T deobfuscate(T translatable) { return deobfuscator.translate(translatable); } - public T obfuscate(T translatable) { - return obfuscator.translate(translatable); - } - public Translator getDeobfuscator() { return deobfuscator; } - public Translator getObfuscator() { - return obfuscator; - } - public Collection> getObfEntries() { return obfToDeobf.getAllEntries(); } @@ -162,40 +74,23 @@ public class EntryRemapper { return obfToDeobf.getRootEntries(); } - public Collection> getDeobfEntries() { - return deobfToObf.getAllEntries(); - } - public Collection> getObfChildren(Entry obfuscatedEntry) { return obfToDeobf.getChildren(obfuscatedEntry); } - public Collection> getDeobfChildren(Entry deobfuscatedEntry) { - return deobfToObf.getChildren(deobfuscatedEntry); - } - - public EntryTree getObfToDeobf() { + public DeltaTrackingTree getObfToDeobf() { return obfToDeobf; } - public DeltaTrackingTree getDeobfToObf() { - return deobfToObf; - } - - public MappingDelta takeMappingDelta() { - MappingDelta delta = deobfToObf.takeDelta(); - return delta.translate(obfuscator, VoidEntryResolver.INSTANCE, deobfToObf); + public MappingDelta takeMappingDelta() { + return obfToDeobf.takeDelta(); } public boolean isDirty() { - return deobfToObf.isDirty(); + return obfToDeobf.isDirty(); } public EntryResolver getObfResolver() { return obfResolver; } - - public EntryResolver getDeobfResolver() { - return deobfResolver; - } } diff --git a/src/main/java/cuchaz/enigma/translation/mapping/MappingDelta.java b/src/main/java/cuchaz/enigma/translation/mapping/MappingDelta.java index 4fba49d..9f1f468 100644 --- a/src/main/java/cuchaz/enigma/translation/mapping/MappingDelta.java +++ b/src/main/java/cuchaz/enigma/translation/mapping/MappingDelta.java @@ -6,28 +6,35 @@ import cuchaz.enigma.translation.mapping.tree.HashEntryTree; import cuchaz.enigma.translation.mapping.tree.EntryTree; import cuchaz.enigma.translation.representation.entry.Entry; -public class MappingDelta implements Translatable { +public class MappingDelta implements Translatable { public static final Object PLACEHOLDER = new Object(); + private final EntryTree baseMappings; + private final EntryTree additions; private final EntryTree deletions; - public MappingDelta(EntryTree additions, EntryTree deletions) { + public MappingDelta(EntryTree baseMappings, EntryTree additions, EntryTree deletions) { + this.baseMappings = baseMappings; this.additions = additions; this.deletions = deletions; } - public MappingDelta() { - this(new HashEntryTree<>(), new HashEntryTree<>()); + public MappingDelta(EntryTree baseMappings) { + this(baseMappings, new HashEntryTree<>(), new HashEntryTree<>()); } - public static MappingDelta added(EntryTree mappings) { + public static MappingDelta added(EntryTree mappings) { EntryTree additions = new HashEntryTree<>(); for (Entry entry : mappings.getAllEntries()) { additions.insert(entry, PLACEHOLDER); } - return new MappingDelta(additions, new HashEntryTree<>()); + return new MappingDelta<>(new HashEntryTree<>(), additions, new HashEntryTree<>()); + } + + public EntryTree getBaseMappings() { + return baseMappings; } public EntryTree getAdditions() { @@ -39,18 +46,11 @@ public class MappingDelta implements Translatable { } @Override - public MappingDelta translate(Translator translator, EntryResolver resolver, EntryMap mappings) { - return new MappingDelta( - translate(translator, additions), - translate(translator, deletions) + public MappingDelta translate(Translator translator, EntryResolver resolver, EntryMap mappings) { + return new MappingDelta<>( + translator.translate(baseMappings), + translator.translate(additions), + translator.translate(deletions) ); } - - private EntryTree translate(Translator translator, EntryTree tree) { - EntryTree translatedTree = new HashEntryTree<>(); - for (Entry entry : tree.getAllEntries()) { - translatedTree.insert(translator.translate(entry), PLACEHOLDER); - } - return translatedTree; - } } diff --git a/src/main/java/cuchaz/enigma/translation/mapping/MappingValidator.java b/src/main/java/cuchaz/enigma/translation/mapping/MappingValidator.java index 422bf38..9be48c3 100644 --- a/src/main/java/cuchaz/enigma/translation/mapping/MappingValidator.java +++ b/src/main/java/cuchaz/enigma/translation/mapping/MappingValidator.java @@ -6,14 +6,15 @@ import cuchaz.enigma.translation.mapping.tree.EntryTree; import cuchaz.enigma.translation.representation.entry.Entry; import java.util.Collection; +import java.util.stream.Collectors; public class MappingValidator { - private final EntryTree deobfToObf; + private final EntryTree obfToDeobf; private final Translator deobfuscator; private final EntryResolver entryResolver; - public MappingValidator(EntryTree deobfToObf, Translator deobfuscator, EntryResolver entryResolver) { - this.deobfToObf = deobfToObf; + public MappingValidator(EntryTree obfToDeobf, Translator deobfuscator, EntryResolver entryResolver) { + this.obfToDeobf = obfToDeobf; this.deobfuscator = deobfuscator; this.entryResolver = entryResolver; } @@ -28,8 +29,11 @@ public class MappingValidator { private void validateUnique(Entry entry, String name) { Entry translatedEntry = deobfuscator.translate(entry); - Collection> siblings = deobfToObf.getSiblings(translatedEntry); - if (!isUnique(translatedEntry, siblings, name)) { + Collection> translatedSiblings = obfToDeobf.getSiblings(entry).stream() + .map(deobfuscator::translate) + .collect(Collectors.toList()); + + if (!isUnique(translatedEntry, translatedSiblings, name)) { throw new IllegalNameException(name, "Name is not unique in " + translatedEntry.getParent() + "!"); } } 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 5acb1da..1d44b6e 100644 --- a/src/main/java/cuchaz/enigma/translation/mapping/serde/EnigmaMappingsWriter.java +++ b/src/main/java/cuchaz/enigma/translation/mapping/serde/EnigmaMappingsWriter.java @@ -14,10 +14,7 @@ package cuchaz.enigma.translation.mapping.serde; import cuchaz.enigma.ProgressListener; import cuchaz.enigma.translation.MappingTranslator; import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.mapping.AccessModifier; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.mapping.MappingDelta; -import cuchaz.enigma.translation.mapping.VoidEntryResolver; +import cuchaz.enigma.translation.mapping.*; import cuchaz.enigma.translation.mapping.tree.EntryTree; import cuchaz.enigma.translation.mapping.tree.EntryTreeNode; import cuchaz.enigma.translation.representation.entry.*; @@ -37,7 +34,7 @@ import java.util.stream.Collectors; public enum EnigmaMappingsWriter implements MappingsWriter { FILE { @Override - public void write(EntryTree mappings, MappingDelta delta, Path path, ProgressListener progress) { + public void write(EntryTree mappings, MappingDelta delta, Path path, ProgressListener progress) { Collection classes = mappings.getRootEntries().stream() .filter(entry -> entry instanceof ClassEntry) .map(entry -> (ClassEntry) entry) @@ -58,8 +55,8 @@ public enum EnigmaMappingsWriter implements MappingsWriter { }, DIRECTORY { @Override - public void write(EntryTree mappings, MappingDelta delta, Path path, ProgressListener progress) { - applyDeletions(delta.getDeletions(), path); + public void write(EntryTree mappings, MappingDelta delta, Path path, ProgressListener progress) { + applyDeletions(delta.getBaseMappings(), delta.getDeletions(), path); Collection classes = delta.getAdditions().getRootEntries().stream() .filter(entry -> entry instanceof ClassEntry) @@ -76,8 +73,8 @@ public enum EnigmaMappingsWriter implements MappingsWriter { try { Path classPath = resolve(path, translator.translate(classEntry)); - Files.deleteIfExists(classPath); Files.createDirectories(classPath.getParent()); + Files.deleteIfExists(classPath); try (PrintWriter writer = new LFPrintWriter(Files.newBufferedWriter(classPath))) { writeRoot(writer, mappings, classEntry); @@ -89,10 +86,12 @@ public enum EnigmaMappingsWriter implements MappingsWriter { }); } - private void applyDeletions(EntryTree deletions, Path root) { + private void applyDeletions(EntryTree baseMappings, EntryTree deletions, Path root) { + Translator oldMappingTranslator = new MappingTranslator(baseMappings, VoidEntryResolver.INSTANCE); + Collection deletedClasses = deletions.getRootEntries().stream() .filter(e -> e instanceof ClassEntry) - .map(e -> (ClassEntry) e) + .map(e -> oldMappingTranslator.translate((ClassEntry) e)) .collect(Collectors.toList()); 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 4db1645..622a0e1 100644 --- a/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingFormat.java +++ b/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingFormat.java @@ -28,7 +28,7 @@ public enum MappingFormat { write(mappings, MappingDelta.added(mappings), path, progressListener); } - public void write(EntryTree mappings, MappingDelta delta, Path path, ProgressListener progressListener) { + public void write(EntryTree mappings, MappingDelta delta, Path path, ProgressListener progressListener) { if (writer == null) { throw new IllegalStateException(name() + " does not support writing"); } diff --git a/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingsWriter.java b/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingsWriter.java index b519668..77f6ee0 100644 --- a/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingsWriter.java +++ b/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingsWriter.java @@ -8,5 +8,9 @@ import cuchaz.enigma.translation.mapping.tree.EntryTree; import java.nio.file.Path; public interface MappingsWriter { - void write(EntryTree mappings, MappingDelta delta, Path path, ProgressListener progress); + void write(EntryTree mappings, MappingDelta delta, Path path, ProgressListener progress); + + default void write(EntryTree mappings, Path path, ProgressListener progress) { + write(mappings, MappingDelta.added(mappings), path, progress); + } } diff --git a/src/main/java/cuchaz/enigma/translation/mapping/serde/SrgMappingsWriter.java b/src/main/java/cuchaz/enigma/translation/mapping/serde/SrgMappingsWriter.java index 5ff9141..40be136 100644 --- a/src/main/java/cuchaz/enigma/translation/mapping/serde/SrgMappingsWriter.java +++ b/src/main/java/cuchaz/enigma/translation/mapping/serde/SrgMappingsWriter.java @@ -29,7 +29,7 @@ public enum SrgMappingsWriter implements MappingsWriter { INSTANCE; @Override - public void write(EntryTree mappings, MappingDelta delta, Path path, ProgressListener progress) { + public void write(EntryTree mappings, MappingDelta delta, Path path, ProgressListener progress) { try { Files.deleteIfExists(path); Files.createFile(path); 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 98a01df..36be5e1 100644 --- a/src/main/java/cuchaz/enigma/translation/mapping/tree/DeltaTrackingTree.java +++ b/src/main/java/cuchaz/enigma/translation/mapping/tree/DeltaTrackingTree.java @@ -1,5 +1,9 @@ package cuchaz.enigma.translation.mapping.tree; +import cuchaz.enigma.translation.Translator; +import cuchaz.enigma.translation.mapping.EntryMap; +import cuchaz.enigma.translation.mapping.EntryMapping; +import cuchaz.enigma.translation.mapping.EntryResolver; import cuchaz.enigma.translation.mapping.MappingDelta; import cuchaz.enigma.translation.representation.entry.Entry; @@ -10,11 +14,13 @@ import java.util.Iterator; public class DeltaTrackingTree implements EntryTree { private final EntryTree delegate; + private EntryTree deltaReference; private EntryTree additions = new HashEntryTree<>(); private EntryTree deletions = new HashEntryTree<>(); public DeltaTrackingTree(EntryTree delegate) { this.delegate = delegate; + this.deltaReference = new HashEntryTree<>(delegate); } public DeltaTrackingTree() { @@ -40,7 +46,7 @@ public class DeltaTrackingTree implements EntryTree { } public void trackAddition(Entry entry) { - deletions.remove(entry); + deletions.insert(entry, MappingDelta.PLACEHOLDER); additions.insert(entry, MappingDelta.PLACEHOLDER); } @@ -81,6 +87,14 @@ public class DeltaTrackingTree implements EntryTree { return delegate.getRootEntries(); } + @Override + public DeltaTrackingTree translate(Translator translator, EntryResolver resolver, EntryMap mappings) { + DeltaTrackingTree translatedTree = new DeltaTrackingTree<>(delegate.translate(translator, resolver, mappings)); + translatedTree.additions = additions.translate(translator, resolver, mappings); + translatedTree.deletions = deletions.translate(translator, resolver, mappings); + return translatedTree; + } + @Override public Collection> getAllEntries() { return delegate.getAllEntries(); @@ -96,13 +110,14 @@ public class DeltaTrackingTree implements EntryTree { return delegate.iterator(); } - public MappingDelta takeDelta() { - MappingDelta delta = new MappingDelta(additions, deletions); + public MappingDelta takeDelta() { + MappingDelta delta = new MappingDelta<>(deltaReference, additions, deletions); resetDelta(); return delta; } private void resetDelta() { + deltaReference = new HashEntryTree<>(delegate); additions = new HashEntryTree<>(); deletions = new HashEntryTree<>(); } 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 73fe12d..4f341f4 100644 --- a/src/main/java/cuchaz/enigma/translation/mapping/tree/EntryTree.java +++ b/src/main/java/cuchaz/enigma/translation/mapping/tree/EntryTree.java @@ -1,12 +1,16 @@ package cuchaz.enigma.translation.mapping.tree; +import cuchaz.enigma.translation.Translatable; +import cuchaz.enigma.translation.Translator; import cuchaz.enigma.translation.mapping.EntryMap; +import cuchaz.enigma.translation.mapping.EntryMapping; +import cuchaz.enigma.translation.mapping.EntryResolver; import cuchaz.enigma.translation.representation.entry.Entry; import javax.annotation.Nullable; import java.util.Collection; -public interface EntryTree extends EntryMap, Iterable> { +public interface EntryTree extends EntryMap, Iterable>, Translatable { Collection> getChildren(Entry entry); Collection> getSiblings(Entry entry); @@ -17,4 +21,7 @@ public interface EntryTree extends EntryMap, Iterable> { Collection> getAllNodes(); Collection> getRootEntries(); + + @Override + EntryTree translate(Translator translator, EntryResolver resolver, EntryMap mappings); } 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 ff88bf9..551fb1c 100644 --- a/src/main/java/cuchaz/enigma/translation/mapping/tree/HashEntryTree.java +++ b/src/main/java/cuchaz/enigma/translation/mapping/tree/HashEntryTree.java @@ -1,5 +1,9 @@ package cuchaz.enigma.translation.mapping.tree; +import cuchaz.enigma.translation.Translator; +import cuchaz.enigma.translation.mapping.EntryMap; +import cuchaz.enigma.translation.mapping.EntryMapping; +import cuchaz.enigma.translation.mapping.EntryResolver; import cuchaz.enigma.translation.representation.entry.Entry; import javax.annotation.Nullable; @@ -9,6 +13,15 @@ import java.util.stream.Collectors; public class HashEntryTree implements EntryTree { private final Map, HashTreeNode> root = new HashMap<>(); + public HashEntryTree() { + } + + public HashEntryTree(EntryTree tree) { + for (EntryTreeNode node : tree.getAllNodes()) { + insert(node.getEntry(), node.getValue()); + } + } + @Override public void insert(Entry entry, T value) { List> path = computePath(entry); @@ -156,4 +169,13 @@ public class HashEntryTree implements EntryTree { public boolean isEmpty() { return root.isEmpty(); } + + @Override + public HashEntryTree translate(Translator translator, EntryResolver resolver, EntryMap mappings) { + HashEntryTree translatedTree = new HashEntryTree<>(); + for (EntryTreeNode node : getAllNodes()) { + translatedTree.insert(translator.translate(node.getEntry()), node.getValue()); + } + return translatedTree; + } } diff --git a/src/main/java/cuchaz/enigma/translation/representation/ProcyonEntryFactory.java b/src/main/java/cuchaz/enigma/translation/representation/ProcyonEntryFactory.java index 9c9fa3d..a9ec5fa 100644 --- a/src/main/java/cuchaz/enigma/translation/representation/ProcyonEntryFactory.java +++ b/src/main/java/cuchaz/enigma/translation/representation/ProcyonEntryFactory.java @@ -17,29 +17,23 @@ import com.strobel.assembler.metadata.MethodDefinition; import cuchaz.enigma.translation.representation.entry.*; public class ProcyonEntryFactory { - private final ReferencedEntryPool entryPool; - - public ProcyonEntryFactory(ReferencedEntryPool entryPool) { - this.entryPool = entryPool; - } - public FieldEntry getFieldEntry(MemberReference def) { - ClassEntry classEntry = entryPool.getClass(def.getDeclaringType().getInternalName()); - return entryPool.getField(classEntry, def.getName(), def.getErasedSignature()); + ClassEntry classEntry = new ClassEntry(def.getDeclaringType().getInternalName()); + return new FieldEntry(classEntry, def.getName(), new TypeDescriptor(def.getErasedSignature())); } public FieldDefEntry getFieldDefEntry(FieldDefinition def) { - ClassEntry classEntry = entryPool.getClass(def.getDeclaringType().getInternalName()); + ClassEntry classEntry = new ClassEntry(def.getDeclaringType().getInternalName()); return new FieldDefEntry(classEntry, def.getName(), new TypeDescriptor(def.getErasedSignature()), Signature.createTypedSignature(def.getSignature()), new AccessFlags(def.getModifiers())); } public MethodEntry getMethodEntry(MemberReference def) { - ClassEntry classEntry = entryPool.getClass(def.getDeclaringType().getInternalName()); - return entryPool.getMethod(classEntry, def.getName(), def.getErasedSignature()); + ClassEntry classEntry = new ClassEntry(def.getDeclaringType().getInternalName()); + return new MethodEntry(classEntry, def.getName(), new MethodDescriptor(def.getErasedSignature())); } public MethodDefEntry getMethodDefEntry(MethodDefinition def) { - ClassEntry classEntry = entryPool.getClass(def.getDeclaringType().getInternalName()); + ClassEntry classEntry = new ClassEntry(def.getDeclaringType().getInternalName()); return new MethodDefEntry(classEntry, def.getName(), new MethodDescriptor(def.getErasedSignature()), Signature.createSignature(def.getSignature()), new AccessFlags(def.getModifiers())); } } diff --git a/src/main/java/cuchaz/enigma/translation/representation/ReferencedEntryPool.java b/src/main/java/cuchaz/enigma/translation/representation/ReferencedEntryPool.java deleted file mode 100644 index 631b375..0000000 --- a/src/main/java/cuchaz/enigma/translation/representation/ReferencedEntryPool.java +++ /dev/null @@ -1,60 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.translation.representation; - -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.translation.representation.entry.FieldEntry; -import cuchaz.enigma.translation.representation.entry.MethodEntry; - -import java.util.HashMap; -import java.util.Map; - -public class ReferencedEntryPool { - private final Map classEntries = new HashMap<>(); - private final Map> methodEntries = new HashMap<>(); - private final Map> fieldEntries = new HashMap<>(); - - public ClassEntry getClass(String name) { - // TODO: FIXME - I'm a hack! - if ("[T".equals(name) || "[[T".equals(name) || "[[[T".equals(name)) { - name = name.replaceAll("T", "Ljava/lang/Object;"); - } - - final String computeName = name; - return this.classEntries.computeIfAbsent(name, s -> new ClassEntry(computeName)); - } - - public MethodEntry getMethod(ClassEntry ownerEntry, String name, String desc) { - return getMethod(ownerEntry, name, new MethodDescriptor(desc)); - } - - public MethodEntry getMethod(ClassEntry ownerEntry, String name, MethodDescriptor desc) { - String key = name + desc.toString(); - return getClassMethods(ownerEntry.getFullName()).computeIfAbsent(key, s -> new MethodEntry(ownerEntry, name, desc)); - } - - public FieldEntry getField(ClassEntry ownerEntry, String name, String desc) { - return getField(ownerEntry, name, new TypeDescriptor(desc)); - } - - public FieldEntry getField(ClassEntry ownerEntry, String name, TypeDescriptor desc) { - return getClassFields(ownerEntry.getFullName()).computeIfAbsent(name, s -> new FieldEntry(ownerEntry, name, desc)); - } - - private Map getClassMethods(String name) { - return methodEntries.computeIfAbsent(name, s -> new HashMap<>()); - } - - private Map getClassFields(String name) { - return fieldEntries.computeIfAbsent(name, s -> new HashMap<>()); - } -} diff --git a/src/main/java/cuchaz/enigma/translation/representation/Signature.java b/src/main/java/cuchaz/enigma/translation/representation/Signature.java index dc241b7..424088a 100644 --- a/src/main/java/cuchaz/enigma/translation/representation/Signature.java +++ b/src/main/java/cuchaz/enigma/translation/representation/Signature.java @@ -3,9 +3,9 @@ package cuchaz.enigma.translation.representation; import cuchaz.enigma.bytecode.translators.TranslationSignatureVisitor; import cuchaz.enigma.translation.Translatable; import cuchaz.enigma.translation.Translator; +import cuchaz.enigma.translation.mapping.EntryMap; import cuchaz.enigma.translation.mapping.EntryMapping; import cuchaz.enigma.translation.mapping.EntryResolver; -import cuchaz.enigma.translation.mapping.EntryMap; import cuchaz.enigma.translation.representation.entry.ClassEntry; import org.objectweb.asm.signature.SignatureReader; import org.objectweb.asm.signature.SignatureVisitor; @@ -78,7 +78,12 @@ public class Signature implements Translatable { @Override public int hashCode() { - return signature.hashCode() | (isType ? 1 : 0) << 16; + int hash = (isType ? 1 : 0) << 16; + if (signature != null) { + hash |= signature.hashCode(); + } + + return hash; } @Override diff --git a/src/main/java/cuchaz/enigma/translation/representation/TypeDescriptor.java b/src/main/java/cuchaz/enigma/translation/representation/TypeDescriptor.java index f7ba849..719d693 100644 --- a/src/main/java/cuchaz/enigma/translation/representation/TypeDescriptor.java +++ b/src/main/java/cuchaz/enigma/translation/representation/TypeDescriptor.java @@ -13,6 +13,7 @@ package cuchaz.enigma.translation.representation; import com.google.common.base.Preconditions; import com.google.common.collect.Maps; +import com.strobel.assembler.metadata.TypeReference; import cuchaz.enigma.translation.Translatable; import cuchaz.enigma.translation.Translator; import cuchaz.enigma.translation.mapping.EntryMapping; @@ -111,6 +112,10 @@ public class TypeDescriptor implements Translatable { return new TypeDescriptor("L" + name + ";"); } + public static TypeDescriptor parse(TypeReference type) { + return new TypeDescriptor(type.getErasedSignature()); + } + @Override public String toString() { return this.desc; 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 5904efe..644658f 100644 --- a/src/main/java/cuchaz/enigma/translation/representation/entry/ClassEntry.java +++ b/src/main/java/cuchaz/enigma/translation/representation/entry/ClassEntry.java @@ -17,6 +17,7 @@ import cuchaz.enigma.translation.Translator; import cuchaz.enigma.translation.mapping.EntryMapping; import cuchaz.enigma.translation.mapping.NameValidator; +import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.List; import java.util.Objects; @@ -125,6 +126,7 @@ public class ClassEntry extends ParentedEntry implements Comparable< return parent; } + @Nonnull public ClassEntry getOutermostClass() { if (parent == null) { return this; @@ -180,6 +182,15 @@ public class ClassEntry extends ParentedEntry implements Comparable< return name; } + @Override + public String getSourceRemapName() { + ClassEntry outerClass = getOuterClass(); + if (outerClass != null) { + return outerClass.getSourceRemapName() + "." + name; + } + return getSimpleName(); + } + @Override public int compareTo(ClassEntry entry) { return name.compareTo(entry.name); 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 1a2ca78..227400e 100644 --- a/src/main/java/cuchaz/enigma/translation/representation/entry/Entry.java +++ b/src/main/java/cuchaz/enigma/translation/representation/entry/Entry.java @@ -22,6 +22,10 @@ import java.util.List; public interface Entry

> extends Translatable { String getName(); + default String getSourceRemapName() { + return getName(); + } + @Nullable P getParent(); 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 df96b59..0c12f1c 100644 --- a/src/main/java/cuchaz/enigma/translation/representation/entry/LocalVariableEntry.java +++ b/src/main/java/cuchaz/enigma/translation/representation/entry/LocalVariableEntry.java @@ -17,11 +17,6 @@ public class LocalVariableEntry extends ParentedEntry implements Co protected final int index; protected final boolean parameter; - @Deprecated - public LocalVariableEntry(MethodEntry parent, int index, String name) { - this(parent, index, name, true); - } - public LocalVariableEntry(MethodEntry parent, int index, String name, boolean parameter) { super(parent, name); @@ -37,7 +32,7 @@ public class LocalVariableEntry extends ParentedEntry implements Co return MethodEntry.class; } - public boolean isParameter() { + public boolean isArgument() { return this.parameter; } -- cgit v1.2.3