diff options
| author | 2019-01-30 21:05:32 +0200 | |
|---|---|---|
| committer | 2019-01-30 21:05:32 +0200 | |
| commit | ba7a354efae7d49833c887cf147ac940c975a1fa (patch) | |
| tree | 02e14fda81dd5984e24f2df392c57c6e829fc875 /src/main/java/cuchaz/enigma/translation | |
| parent | Rewrite the Jenkinsfile to use the new declarative pipeline syntax, lets hope... (diff) | |
| download | enigma-fork-ba7a354efae7d49833c887cf147ac940c975a1fa.tar.gz enigma-fork-ba7a354efae7d49833c887cf147ac940c975a1fa.tar.xz enigma-fork-ba7a354efae7d49833c887cf147ac940c975a1fa.zip | |
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
Diffstat (limited to 'src/main/java/cuchaz/enigma/translation')
18 files changed, 179 insertions, 235 deletions
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 @@ | |||
| 1 | package cuchaz.enigma.translation; | ||
| 2 | |||
| 3 | import cuchaz.enigma.translation.mapping.NameValidator; | ||
| 4 | import cuchaz.enigma.translation.representation.TypeDescriptor; | ||
| 5 | |||
| 6 | import java.util.Collection; | ||
| 7 | import java.util.Locale; | ||
| 8 | |||
| 9 | public class LocalNameGenerator { | ||
| 10 | public static String generateArgumentName(int index, TypeDescriptor desc, Collection<TypeDescriptor> arguments) { | ||
| 11 | boolean uniqueType = arguments.stream().filter(desc::equals).count() <= 1; | ||
| 12 | String translatedName; | ||
| 13 | int nameIndex = index + 1; | ||
| 14 | StringBuilder nameBuilder = new StringBuilder(getTypeName(desc)); | ||
| 15 | if (!uniqueType || NameValidator.isReserved(nameBuilder.toString())) { | ||
| 16 | nameBuilder.append(nameIndex); | ||
| 17 | } | ||
| 18 | translatedName = nameBuilder.toString(); | ||
| 19 | return translatedName; | ||
| 20 | } | ||
| 21 | |||
| 22 | public static String generateLocalVariableName(int index, TypeDescriptor desc) { | ||
| 23 | int nameIndex = index + 1; | ||
| 24 | return getTypeName(desc) + nameIndex; | ||
| 25 | } | ||
| 26 | |||
| 27 | private static String getTypeName(TypeDescriptor desc) { | ||
| 28 | // Unfortunately each of these have different name getters, so they have different code paths | ||
| 29 | if (desc.isPrimitive()) { | ||
| 30 | TypeDescriptor.Primitive argCls = desc.getPrimitive(); | ||
| 31 | return argCls.name().toLowerCase(Locale.ROOT); | ||
| 32 | } else if (desc.isArray()) { | ||
| 33 | // List types would require this whole block again, so just go with aListx | ||
| 34 | return "arr"; | ||
| 35 | } else if (desc.isType()) { | ||
| 36 | String typeName = desc.getTypeEntry().getSimpleName().replace("$", ""); | ||
| 37 | typeName = typeName.substring(0, 1).toLowerCase(Locale.ROOT) + typeName.substring(1); | ||
| 38 | return typeName; | ||
| 39 | } else { | ||
| 40 | System.err.println("Encountered invalid argument type descriptor " + desc.toString()); | ||
| 41 | return "var"; | ||
| 42 | } | ||
| 43 | } | ||
| 44 | } | ||
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; | |||
| 6 | import cuchaz.enigma.translation.Translator; | 6 | import cuchaz.enigma.translation.Translator; |
| 7 | import cuchaz.enigma.translation.mapping.tree.DeltaTrackingTree; | 7 | import cuchaz.enigma.translation.mapping.tree.DeltaTrackingTree; |
| 8 | import cuchaz.enigma.translation.mapping.tree.EntryTree; | 8 | import cuchaz.enigma.translation.mapping.tree.EntryTree; |
| 9 | import cuchaz.enigma.translation.mapping.tree.EntryTreeNode; | ||
| 10 | import cuchaz.enigma.translation.mapping.tree.HashEntryTree; | 9 | import cuchaz.enigma.translation.mapping.tree.HashEntryTree; |
| 11 | import cuchaz.enigma.translation.representation.entry.Entry; | 10 | import cuchaz.enigma.translation.representation.entry.Entry; |
| 12 | 11 | ||
| @@ -14,59 +13,25 @@ import javax.annotation.Nullable; | |||
| 14 | import java.util.Collection; | 13 | import java.util.Collection; |
| 15 | 14 | ||
| 16 | public class EntryRemapper { | 15 | public class EntryRemapper { |
| 17 | private final EntryTree<EntryMapping> obfToDeobf; | 16 | private final DeltaTrackingTree<EntryMapping> obfToDeobf; |
| 18 | private final DeltaTrackingTree<EntryMapping> deobfToObf; | ||
| 19 | |||
| 20 | private final JarIndex obfIndex; | ||
| 21 | 17 | ||
| 22 | private final EntryResolver obfResolver; | 18 | private final EntryResolver obfResolver; |
| 23 | private EntryResolver deobfResolver; | ||
| 24 | |||
| 25 | private final Translator deobfuscator; | 19 | private final Translator deobfuscator; |
| 26 | private Translator obfuscator; | ||
| 27 | 20 | ||
| 28 | private final MappingValidator validator; | 21 | private final MappingValidator validator; |
| 29 | 22 | ||
| 30 | private EntryRemapper(JarIndex jarIndex, EntryTree<EntryMapping> obfToDeobf, EntryTree<EntryMapping> deobfToObf) { | 23 | public EntryRemapper(JarIndex jarIndex, EntryTree<EntryMapping> obfToDeobf) { |
| 31 | this.obfToDeobf = obfToDeobf; | 24 | this.obfToDeobf = new DeltaTrackingTree<>(obfToDeobf); |
| 32 | this.deobfToObf = new DeltaTrackingTree<>(deobfToObf); | ||
| 33 | 25 | ||
| 34 | this.obfIndex = jarIndex; | ||
| 35 | this.obfResolver = jarIndex.getEntryResolver(); | 26 | this.obfResolver = jarIndex.getEntryResolver(); |
| 36 | 27 | ||
| 37 | this.deobfuscator = new MappingTranslator(obfToDeobf, obfResolver); | 28 | this.deobfuscator = new MappingTranslator(obfToDeobf, obfResolver); |
| 38 | rebuildDeobfIndex(); | ||
| 39 | 29 | ||
| 40 | this.validator = new MappingValidator(this.deobfToObf, deobfuscator, obfResolver); | 30 | this.validator = new MappingValidator(obfToDeobf, deobfuscator, obfResolver); |
| 41 | } | 31 | } |
| 42 | 32 | ||
| 43 | public EntryRemapper(JarIndex jarIndex) { | 33 | public EntryRemapper(JarIndex jarIndex) { |
| 44 | this(jarIndex, new HashEntryTree<>(), new HashEntryTree<>()); | 34 | this(jarIndex, new HashEntryTree<>()); |
| 45 | } | ||
| 46 | |||
| 47 | public EntryRemapper(JarIndex jarIndex, EntryTree<EntryMapping> deobfuscationTrees) { | ||
| 48 | this(jarIndex, deobfuscationTrees, inverse(deobfuscationTrees)); | ||
| 49 | } | ||
| 50 | |||
| 51 | private static EntryTree<EntryMapping> inverse(EntryTree<EntryMapping> tree) { | ||
| 52 | Translator translator = new MappingTranslator(tree, VoidEntryResolver.INSTANCE); | ||
| 53 | EntryTree<EntryMapping> inverse = new HashEntryTree<>(); | ||
| 54 | |||
| 55 | // Naive approach, could operate on the nodes of the tree. However, this runs infrequently. | ||
| 56 | Collection<Entry<?>> entries = tree.getAllEntries(); | ||
| 57 | for (Entry<?> sourceEntry : entries) { | ||
| 58 | Entry<?> targetEntry = translator.translate(sourceEntry); | ||
| 59 | inverse.insert(targetEntry, new EntryMapping(sourceEntry.getName())); | ||
| 60 | } | ||
| 61 | |||
| 62 | return inverse; | ||
| 63 | } | ||
| 64 | |||
| 65 | private void rebuildDeobfIndex() { | ||
| 66 | JarIndex deobfIndex = obfIndex.remapped(deobfuscator); | ||
| 67 | |||
| 68 | this.deobfResolver = deobfIndex.getEntryResolver(); | ||
| 69 | this.obfuscator = new MappingTranslator(deobfToObf, deobfResolver); | ||
| 70 | } | 35 | } |
| 71 | 36 | ||
| 72 | public <E extends Entry<?>> void mapFromObf(E obfuscatedEntry, @Nullable EntryMapping deobfMapping) { | 37 | public <E extends Entry<?>> void mapFromObf(E obfuscatedEntry, @Nullable EntryMapping deobfMapping) { |
| @@ -76,84 +41,31 @@ public class EntryRemapper { | |||
| 76 | validator.validateRename(resolvedEntry, deobfMapping.getTargetName()); | 41 | validator.validateRename(resolvedEntry, deobfMapping.getTargetName()); |
| 77 | } | 42 | } |
| 78 | 43 | ||
| 79 | setObfToDeobf(resolvedEntry, deobfMapping); | 44 | obfToDeobf.insert(obfuscatedEntry, deobfMapping); |
| 80 | } | 45 | } |
| 81 | |||
| 82 | // Temporary hack, not very performant | ||
| 83 | rebuildDeobfIndex(); | ||
| 84 | } | ||
| 85 | |||
| 86 | public <E extends Entry<?>> void mapFromDeobf(E deobfuscatedEntry, @Nullable EntryMapping deobfMapping) { | ||
| 87 | E obfuscatedEntry = obfuscate(deobfuscatedEntry); | ||
| 88 | mapFromObf(obfuscatedEntry, deobfMapping); | ||
| 89 | } | 46 | } |
| 90 | 47 | ||
| 91 | public void removeByObf(Entry<?> obfuscatedEntry) { | 48 | public void removeByObf(Entry<?> obfuscatedEntry) { |
| 92 | mapFromObf(obfuscatedEntry, null); | 49 | mapFromObf(obfuscatedEntry, null); |
| 93 | } | 50 | } |
| 94 | 51 | ||
| 95 | public void removeByDeobf(Entry<?> deobfuscatedEntry) { | ||
| 96 | mapFromObf(obfuscate(deobfuscatedEntry), null); | ||
| 97 | } | ||
| 98 | |||
| 99 | private <E extends Entry<?>> void setObfToDeobf(E obfuscatedEntry, @Nullable EntryMapping deobfMapping) { | ||
| 100 | E prevDeobf = deobfuscate(obfuscatedEntry); | ||
| 101 | obfToDeobf.insert(obfuscatedEntry, deobfMapping); | ||
| 102 | |||
| 103 | E newDeobf = deobfuscate(obfuscatedEntry); | ||
| 104 | |||
| 105 | // Reconstruct the children of this node in the deobf -> obf tree with our new mapping | ||
| 106 | // We only need to do this for deobf -> obf because the obf tree is always consistent on the left hand side | ||
| 107 | // We lookup by obf, and the obf never changes. This is not the case for deobf so we need to update the tree. | ||
| 108 | |||
| 109 | EntryTreeNode<EntryMapping> node = deobfToObf.findNode(prevDeobf); | ||
| 110 | if (node != null) { | ||
| 111 | for (EntryTreeNode<EntryMapping> child : node.getNodesRecursively()) { | ||
| 112 | Entry<?> entry = child.getEntry(); | ||
| 113 | EntryMapping mapping = new EntryMapping(obfuscate(entry).getName()); | ||
| 114 | |||
| 115 | deobfToObf.insert(entry.replaceAncestor(prevDeobf, newDeobf), mapping); | ||
| 116 | deobfToObf.remove(entry); | ||
| 117 | } | ||
| 118 | } else { | ||
| 119 | deobfToObf.insert(newDeobf, new EntryMapping(obfuscatedEntry.getName())); | ||
| 120 | } | ||
| 121 | } | ||
| 122 | |||
| 123 | @Nullable | 52 | @Nullable |
| 124 | public EntryMapping getDeobfMapping(Entry<?> entry) { | 53 | public EntryMapping getDeobfMapping(Entry<?> entry) { |
| 125 | return obfToDeobf.get(entry); | 54 | return obfToDeobf.get(entry); |
| 126 | } | 55 | } |
| 127 | 56 | ||
| 128 | @Nullable | ||
| 129 | public EntryMapping getObfMapping(Entry<?> entry) { | ||
| 130 | return deobfToObf.get(entry); | ||
| 131 | } | ||
| 132 | |||
| 133 | public boolean hasDeobfMapping(Entry<?> obfEntry) { | 57 | public boolean hasDeobfMapping(Entry<?> obfEntry) { |
| 134 | return obfToDeobf.contains(obfEntry); | 58 | return obfToDeobf.contains(obfEntry); |
| 135 | } | 59 | } |
| 136 | 60 | ||
| 137 | public boolean hasObfMapping(Entry<?> deobfEntry) { | ||
| 138 | return deobfToObf.contains(deobfEntry); | ||
| 139 | } | ||
| 140 | |||
| 141 | public <T extends Translatable> T deobfuscate(T translatable) { | 61 | public <T extends Translatable> T deobfuscate(T translatable) { |
| 142 | return deobfuscator.translate(translatable); | 62 | return deobfuscator.translate(translatable); |
| 143 | } | 63 | } |
| 144 | 64 | ||
| 145 | public <T extends Translatable> T obfuscate(T translatable) { | ||
| 146 | return obfuscator.translate(translatable); | ||
| 147 | } | ||
| 148 | |||
| 149 | public Translator getDeobfuscator() { | 65 | public Translator getDeobfuscator() { |
| 150 | return deobfuscator; | 66 | return deobfuscator; |
| 151 | } | 67 | } |
| 152 | 68 | ||
| 153 | public Translator getObfuscator() { | ||
| 154 | return obfuscator; | ||
| 155 | } | ||
| 156 | |||
| 157 | public Collection<Entry<?>> getObfEntries() { | 69 | public Collection<Entry<?>> getObfEntries() { |
| 158 | return obfToDeobf.getAllEntries(); | 70 | return obfToDeobf.getAllEntries(); |
| 159 | } | 71 | } |
| @@ -162,40 +74,23 @@ public class EntryRemapper { | |||
| 162 | return obfToDeobf.getRootEntries(); | 74 | return obfToDeobf.getRootEntries(); |
| 163 | } | 75 | } |
| 164 | 76 | ||
| 165 | public Collection<Entry<?>> getDeobfEntries() { | ||
| 166 | return deobfToObf.getAllEntries(); | ||
| 167 | } | ||
| 168 | |||
| 169 | public Collection<Entry<?>> getObfChildren(Entry<?> obfuscatedEntry) { | 77 | public Collection<Entry<?>> getObfChildren(Entry<?> obfuscatedEntry) { |
| 170 | return obfToDeobf.getChildren(obfuscatedEntry); | 78 | return obfToDeobf.getChildren(obfuscatedEntry); |
| 171 | } | 79 | } |
| 172 | 80 | ||
| 173 | public Collection<Entry<?>> getDeobfChildren(Entry<?> deobfuscatedEntry) { | 81 | public DeltaTrackingTree<EntryMapping> getObfToDeobf() { |
| 174 | return deobfToObf.getChildren(deobfuscatedEntry); | ||
| 175 | } | ||
| 176 | |||
| 177 | public EntryTree<EntryMapping> getObfToDeobf() { | ||
| 178 | return obfToDeobf; | 82 | return obfToDeobf; |
| 179 | } | 83 | } |
| 180 | 84 | ||
| 181 | public DeltaTrackingTree<EntryMapping> getDeobfToObf() { | 85 | public MappingDelta<EntryMapping> takeMappingDelta() { |
| 182 | return deobfToObf; | 86 | return obfToDeobf.takeDelta(); |
| 183 | } | ||
| 184 | |||
| 185 | public MappingDelta takeMappingDelta() { | ||
| 186 | MappingDelta delta = deobfToObf.takeDelta(); | ||
| 187 | return delta.translate(obfuscator, VoidEntryResolver.INSTANCE, deobfToObf); | ||
| 188 | } | 87 | } |
| 189 | 88 | ||
| 190 | public boolean isDirty() { | 89 | public boolean isDirty() { |
| 191 | return deobfToObf.isDirty(); | 90 | return obfToDeobf.isDirty(); |
| 192 | } | 91 | } |
| 193 | 92 | ||
| 194 | public EntryResolver getObfResolver() { | 93 | public EntryResolver getObfResolver() { |
| 195 | return obfResolver; | 94 | return obfResolver; |
| 196 | } | 95 | } |
| 197 | |||
| 198 | public EntryResolver getDeobfResolver() { | ||
| 199 | return deobfResolver; | ||
| 200 | } | ||
| 201 | } | 96 | } |
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; | |||
| 6 | import cuchaz.enigma.translation.mapping.tree.EntryTree; | 6 | import cuchaz.enigma.translation.mapping.tree.EntryTree; |
| 7 | import cuchaz.enigma.translation.representation.entry.Entry; | 7 | import cuchaz.enigma.translation.representation.entry.Entry; |
| 8 | 8 | ||
| 9 | public class MappingDelta implements Translatable { | 9 | public class MappingDelta<T> implements Translatable { |
| 10 | public static final Object PLACEHOLDER = new Object(); | 10 | public static final Object PLACEHOLDER = new Object(); |
| 11 | 11 | ||
| 12 | private final EntryTree<T> baseMappings; | ||
| 13 | |||
| 12 | private final EntryTree<Object> additions; | 14 | private final EntryTree<Object> additions; |
| 13 | private final EntryTree<Object> deletions; | 15 | private final EntryTree<Object> deletions; |
| 14 | 16 | ||
| 15 | public MappingDelta(EntryTree<Object> additions, EntryTree<Object> deletions) { | 17 | public MappingDelta(EntryTree<T> baseMappings, EntryTree<Object> additions, EntryTree<Object> deletions) { |
| 18 | this.baseMappings = baseMappings; | ||
| 16 | this.additions = additions; | 19 | this.additions = additions; |
| 17 | this.deletions = deletions; | 20 | this.deletions = deletions; |
| 18 | } | 21 | } |
| 19 | 22 | ||
| 20 | public MappingDelta() { | 23 | public MappingDelta(EntryTree<T> baseMappings) { |
| 21 | this(new HashEntryTree<>(), new HashEntryTree<>()); | 24 | this(baseMappings, new HashEntryTree<>(), new HashEntryTree<>()); |
| 22 | } | 25 | } |
| 23 | 26 | ||
| 24 | public static MappingDelta added(EntryTree<EntryMapping> mappings) { | 27 | public static <T> MappingDelta<T> added(EntryTree<T> mappings) { |
| 25 | EntryTree<Object> additions = new HashEntryTree<>(); | 28 | EntryTree<Object> additions = new HashEntryTree<>(); |
| 26 | for (Entry<?> entry : mappings.getAllEntries()) { | 29 | for (Entry<?> entry : mappings.getAllEntries()) { |
| 27 | additions.insert(entry, PLACEHOLDER); | 30 | additions.insert(entry, PLACEHOLDER); |
| 28 | } | 31 | } |
| 29 | 32 | ||
| 30 | return new MappingDelta(additions, new HashEntryTree<>()); | 33 | return new MappingDelta<>(new HashEntryTree<>(), additions, new HashEntryTree<>()); |
| 34 | } | ||
| 35 | |||
| 36 | public EntryTree<T> getBaseMappings() { | ||
| 37 | return baseMappings; | ||
| 31 | } | 38 | } |
| 32 | 39 | ||
| 33 | public EntryTree<?> getAdditions() { | 40 | public EntryTree<?> getAdditions() { |
| @@ -39,18 +46,11 @@ public class MappingDelta implements Translatable { | |||
| 39 | } | 46 | } |
| 40 | 47 | ||
| 41 | @Override | 48 | @Override |
| 42 | public MappingDelta translate(Translator translator, EntryResolver resolver, EntryMap<EntryMapping> mappings) { | 49 | public MappingDelta<T> translate(Translator translator, EntryResolver resolver, EntryMap<EntryMapping> mappings) { |
| 43 | return new MappingDelta( | 50 | return new MappingDelta<>( |
| 44 | translate(translator, additions), | 51 | translator.translate(baseMappings), |
| 45 | translate(translator, deletions) | 52 | translator.translate(additions), |
| 53 | translator.translate(deletions) | ||
| 46 | ); | 54 | ); |
| 47 | } | 55 | } |
| 48 | |||
| 49 | private EntryTree<Object> translate(Translator translator, EntryTree<Object> tree) { | ||
| 50 | EntryTree<Object> translatedTree = new HashEntryTree<>(); | ||
| 51 | for (Entry<?> entry : tree.getAllEntries()) { | ||
| 52 | translatedTree.insert(translator.translate(entry), PLACEHOLDER); | ||
| 53 | } | ||
| 54 | return translatedTree; | ||
| 55 | } | ||
| 56 | } | 56 | } |
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; | |||
| 6 | import cuchaz.enigma.translation.representation.entry.Entry; | 6 | import cuchaz.enigma.translation.representation.entry.Entry; |
| 7 | 7 | ||
| 8 | import java.util.Collection; | 8 | import java.util.Collection; |
| 9 | import java.util.stream.Collectors; | ||
| 9 | 10 | ||
| 10 | public class MappingValidator { | 11 | public class MappingValidator { |
| 11 | private final EntryTree<EntryMapping> deobfToObf; | 12 | private final EntryTree<EntryMapping> obfToDeobf; |
| 12 | private final Translator deobfuscator; | 13 | private final Translator deobfuscator; |
| 13 | private final EntryResolver entryResolver; | 14 | private final EntryResolver entryResolver; |
| 14 | 15 | ||
| 15 | public MappingValidator(EntryTree<EntryMapping> deobfToObf, Translator deobfuscator, EntryResolver entryResolver) { | 16 | public MappingValidator(EntryTree<EntryMapping> obfToDeobf, Translator deobfuscator, EntryResolver entryResolver) { |
| 16 | this.deobfToObf = deobfToObf; | 17 | this.obfToDeobf = obfToDeobf; |
| 17 | this.deobfuscator = deobfuscator; | 18 | this.deobfuscator = deobfuscator; |
| 18 | this.entryResolver = entryResolver; | 19 | this.entryResolver = entryResolver; |
| 19 | } | 20 | } |
| @@ -28,8 +29,11 @@ public class MappingValidator { | |||
| 28 | 29 | ||
| 29 | private void validateUnique(Entry<?> entry, String name) { | 30 | private void validateUnique(Entry<?> entry, String name) { |
| 30 | Entry<?> translatedEntry = deobfuscator.translate(entry); | 31 | Entry<?> translatedEntry = deobfuscator.translate(entry); |
| 31 | Collection<Entry<?>> siblings = deobfToObf.getSiblings(translatedEntry); | 32 | Collection<Entry<?>> translatedSiblings = obfToDeobf.getSiblings(entry).stream() |
| 32 | if (!isUnique(translatedEntry, siblings, name)) { | 33 | .map(deobfuscator::translate) |
| 34 | .collect(Collectors.toList()); | ||
| 35 | |||
| 36 | if (!isUnique(translatedEntry, translatedSiblings, name)) { | ||
| 33 | throw new IllegalNameException(name, "Name is not unique in " + translatedEntry.getParent() + "!"); | 37 | throw new IllegalNameException(name, "Name is not unique in " + translatedEntry.getParent() + "!"); |
| 34 | } | 38 | } |
| 35 | } | 39 | } |
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; | |||
| 14 | import cuchaz.enigma.ProgressListener; | 14 | import cuchaz.enigma.ProgressListener; |
| 15 | import cuchaz.enigma.translation.MappingTranslator; | 15 | import cuchaz.enigma.translation.MappingTranslator; |
| 16 | import cuchaz.enigma.translation.Translator; | 16 | import cuchaz.enigma.translation.Translator; |
| 17 | import cuchaz.enigma.translation.mapping.AccessModifier; | 17 | import cuchaz.enigma.translation.mapping.*; |
| 18 | import cuchaz.enigma.translation.mapping.EntryMapping; | ||
| 19 | import cuchaz.enigma.translation.mapping.MappingDelta; | ||
| 20 | import cuchaz.enigma.translation.mapping.VoidEntryResolver; | ||
| 21 | import cuchaz.enigma.translation.mapping.tree.EntryTree; | 18 | import cuchaz.enigma.translation.mapping.tree.EntryTree; |
| 22 | import cuchaz.enigma.translation.mapping.tree.EntryTreeNode; | 19 | import cuchaz.enigma.translation.mapping.tree.EntryTreeNode; |
| 23 | import cuchaz.enigma.translation.representation.entry.*; | 20 | import cuchaz.enigma.translation.representation.entry.*; |
| @@ -37,7 +34,7 @@ import java.util.stream.Collectors; | |||
| 37 | public enum EnigmaMappingsWriter implements MappingsWriter { | 34 | public enum EnigmaMappingsWriter implements MappingsWriter { |
| 38 | FILE { | 35 | FILE { |
| 39 | @Override | 36 | @Override |
| 40 | public void write(EntryTree<EntryMapping> mappings, MappingDelta delta, Path path, ProgressListener progress) { | 37 | public void write(EntryTree<EntryMapping> mappings, MappingDelta<EntryMapping> delta, Path path, ProgressListener progress) { |
| 41 | Collection<ClassEntry> classes = mappings.getRootEntries().stream() | 38 | Collection<ClassEntry> classes = mappings.getRootEntries().stream() |
| 42 | .filter(entry -> entry instanceof ClassEntry) | 39 | .filter(entry -> entry instanceof ClassEntry) |
| 43 | .map(entry -> (ClassEntry) entry) | 40 | .map(entry -> (ClassEntry) entry) |
| @@ -58,8 +55,8 @@ public enum EnigmaMappingsWriter implements MappingsWriter { | |||
| 58 | }, | 55 | }, |
| 59 | DIRECTORY { | 56 | DIRECTORY { |
| 60 | @Override | 57 | @Override |
| 61 | public void write(EntryTree<EntryMapping> mappings, MappingDelta delta, Path path, ProgressListener progress) { | 58 | public void write(EntryTree<EntryMapping> mappings, MappingDelta<EntryMapping> delta, Path path, ProgressListener progress) { |
| 62 | applyDeletions(delta.getDeletions(), path); | 59 | applyDeletions(delta.getBaseMappings(), delta.getDeletions(), path); |
| 63 | 60 | ||
| 64 | Collection<ClassEntry> classes = delta.getAdditions().getRootEntries().stream() | 61 | Collection<ClassEntry> classes = delta.getAdditions().getRootEntries().stream() |
| 65 | .filter(entry -> entry instanceof ClassEntry) | 62 | .filter(entry -> entry instanceof ClassEntry) |
| @@ -76,8 +73,8 @@ public enum EnigmaMappingsWriter implements MappingsWriter { | |||
| 76 | 73 | ||
| 77 | try { | 74 | try { |
| 78 | Path classPath = resolve(path, translator.translate(classEntry)); | 75 | Path classPath = resolve(path, translator.translate(classEntry)); |
| 79 | Files.deleteIfExists(classPath); | ||
| 80 | Files.createDirectories(classPath.getParent()); | 76 | Files.createDirectories(classPath.getParent()); |
| 77 | Files.deleteIfExists(classPath); | ||
| 81 | 78 | ||
| 82 | try (PrintWriter writer = new LFPrintWriter(Files.newBufferedWriter(classPath))) { | 79 | try (PrintWriter writer = new LFPrintWriter(Files.newBufferedWriter(classPath))) { |
| 83 | writeRoot(writer, mappings, classEntry); | 80 | writeRoot(writer, mappings, classEntry); |
| @@ -89,10 +86,12 @@ public enum EnigmaMappingsWriter implements MappingsWriter { | |||
| 89 | }); | 86 | }); |
| 90 | } | 87 | } |
| 91 | 88 | ||
| 92 | private void applyDeletions(EntryTree<?> deletions, Path root) { | 89 | private void applyDeletions(EntryTree<EntryMapping> baseMappings, EntryTree<?> deletions, Path root) { |
| 90 | Translator oldMappingTranslator = new MappingTranslator(baseMappings, VoidEntryResolver.INSTANCE); | ||
| 91 | |||
| 93 | Collection<ClassEntry> deletedClasses = deletions.getRootEntries().stream() | 92 | Collection<ClassEntry> deletedClasses = deletions.getRootEntries().stream() |
| 94 | .filter(e -> e instanceof ClassEntry) | 93 | .filter(e -> e instanceof ClassEntry) |
| 95 | .map(e -> (ClassEntry) e) | 94 | .map(e -> oldMappingTranslator.translate((ClassEntry) e)) |
| 96 | .collect(Collectors.toList()); | 95 | .collect(Collectors.toList()); |
| 97 | 96 | ||
| 98 | for (ClassEntry classEntry : deletedClasses) { | 97 | 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 { | |||
| 28 | write(mappings, MappingDelta.added(mappings), path, progressListener); | 28 | write(mappings, MappingDelta.added(mappings), path, progressListener); |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | public void write(EntryTree<EntryMapping> mappings, MappingDelta delta, Path path, ProgressListener progressListener) { | 31 | public void write(EntryTree<EntryMapping> mappings, MappingDelta<EntryMapping> delta, Path path, ProgressListener progressListener) { |
| 32 | if (writer == null) { | 32 | if (writer == null) { |
| 33 | throw new IllegalStateException(name() + " does not support writing"); | 33 | throw new IllegalStateException(name() + " does not support writing"); |
| 34 | } | 34 | } |
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; | |||
| 8 | import java.nio.file.Path; | 8 | import java.nio.file.Path; |
| 9 | 9 | ||
| 10 | public interface MappingsWriter { | 10 | public interface MappingsWriter { |
| 11 | void write(EntryTree<EntryMapping> mappings, MappingDelta delta, Path path, ProgressListener progress); | 11 | void write(EntryTree<EntryMapping> mappings, MappingDelta<EntryMapping> delta, Path path, ProgressListener progress); |
| 12 | |||
| 13 | default void write(EntryTree<EntryMapping> mappings, Path path, ProgressListener progress) { | ||
| 14 | write(mappings, MappingDelta.added(mappings), path, progress); | ||
| 15 | } | ||
| 12 | } | 16 | } |
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 { | |||
| 29 | INSTANCE; | 29 | INSTANCE; |
| 30 | 30 | ||
| 31 | @Override | 31 | @Override |
| 32 | public void write(EntryTree<EntryMapping> mappings, MappingDelta delta, Path path, ProgressListener progress) { | 32 | public void write(EntryTree<EntryMapping> mappings, MappingDelta<EntryMapping> delta, Path path, ProgressListener progress) { |
| 33 | try { | 33 | try { |
| 34 | Files.deleteIfExists(path); | 34 | Files.deleteIfExists(path); |
| 35 | Files.createFile(path); | 35 | 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 @@ | |||
| 1 | package cuchaz.enigma.translation.mapping.tree; | 1 | package cuchaz.enigma.translation.mapping.tree; |
| 2 | 2 | ||
| 3 | import cuchaz.enigma.translation.Translator; | ||
| 4 | import cuchaz.enigma.translation.mapping.EntryMap; | ||
| 5 | import cuchaz.enigma.translation.mapping.EntryMapping; | ||
| 6 | import cuchaz.enigma.translation.mapping.EntryResolver; | ||
| 3 | import cuchaz.enigma.translation.mapping.MappingDelta; | 7 | import cuchaz.enigma.translation.mapping.MappingDelta; |
| 4 | import cuchaz.enigma.translation.representation.entry.Entry; | 8 | import cuchaz.enigma.translation.representation.entry.Entry; |
| 5 | 9 | ||
| @@ -10,11 +14,13 @@ import java.util.Iterator; | |||
| 10 | public class DeltaTrackingTree<T> implements EntryTree<T> { | 14 | public class DeltaTrackingTree<T> implements EntryTree<T> { |
| 11 | private final EntryTree<T> delegate; | 15 | private final EntryTree<T> delegate; |
| 12 | 16 | ||
| 17 | private EntryTree<T> deltaReference; | ||
| 13 | private EntryTree<Object> additions = new HashEntryTree<>(); | 18 | private EntryTree<Object> additions = new HashEntryTree<>(); |
| 14 | private EntryTree<Object> deletions = new HashEntryTree<>(); | 19 | private EntryTree<Object> deletions = new HashEntryTree<>(); |
| 15 | 20 | ||
| 16 | public DeltaTrackingTree(EntryTree<T> delegate) { | 21 | public DeltaTrackingTree(EntryTree<T> delegate) { |
| 17 | this.delegate = delegate; | 22 | this.delegate = delegate; |
| 23 | this.deltaReference = new HashEntryTree<>(delegate); | ||
| 18 | } | 24 | } |
| 19 | 25 | ||
| 20 | public DeltaTrackingTree() { | 26 | public DeltaTrackingTree() { |
| @@ -40,7 +46,7 @@ public class DeltaTrackingTree<T> implements EntryTree<T> { | |||
| 40 | } | 46 | } |
| 41 | 47 | ||
| 42 | public void trackAddition(Entry<?> entry) { | 48 | public void trackAddition(Entry<?> entry) { |
| 43 | deletions.remove(entry); | 49 | deletions.insert(entry, MappingDelta.PLACEHOLDER); |
| 44 | additions.insert(entry, MappingDelta.PLACEHOLDER); | 50 | additions.insert(entry, MappingDelta.PLACEHOLDER); |
| 45 | } | 51 | } |
| 46 | 52 | ||
| @@ -82,6 +88,14 @@ public class DeltaTrackingTree<T> implements EntryTree<T> { | |||
| 82 | } | 88 | } |
| 83 | 89 | ||
| 84 | @Override | 90 | @Override |
| 91 | public DeltaTrackingTree<T> translate(Translator translator, EntryResolver resolver, EntryMap<EntryMapping> mappings) { | ||
| 92 | DeltaTrackingTree<T> translatedTree = new DeltaTrackingTree<>(delegate.translate(translator, resolver, mappings)); | ||
| 93 | translatedTree.additions = additions.translate(translator, resolver, mappings); | ||
| 94 | translatedTree.deletions = deletions.translate(translator, resolver, mappings); | ||
| 95 | return translatedTree; | ||
| 96 | } | ||
| 97 | |||
| 98 | @Override | ||
| 85 | public Collection<Entry<?>> getAllEntries() { | 99 | public Collection<Entry<?>> getAllEntries() { |
| 86 | return delegate.getAllEntries(); | 100 | return delegate.getAllEntries(); |
| 87 | } | 101 | } |
| @@ -96,13 +110,14 @@ public class DeltaTrackingTree<T> implements EntryTree<T> { | |||
| 96 | return delegate.iterator(); | 110 | return delegate.iterator(); |
| 97 | } | 111 | } |
| 98 | 112 | ||
| 99 | public MappingDelta takeDelta() { | 113 | public MappingDelta<T> takeDelta() { |
| 100 | MappingDelta delta = new MappingDelta(additions, deletions); | 114 | MappingDelta<T> delta = new MappingDelta<>(deltaReference, additions, deletions); |
| 101 | resetDelta(); | 115 | resetDelta(); |
| 102 | return delta; | 116 | return delta; |
| 103 | } | 117 | } |
| 104 | 118 | ||
| 105 | private void resetDelta() { | 119 | private void resetDelta() { |
| 120 | deltaReference = new HashEntryTree<>(delegate); | ||
| 106 | additions = new HashEntryTree<>(); | 121 | additions = new HashEntryTree<>(); |
| 107 | deletions = new HashEntryTree<>(); | 122 | deletions = new HashEntryTree<>(); |
| 108 | } | 123 | } |
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 @@ | |||
| 1 | package cuchaz.enigma.translation.mapping.tree; | 1 | package cuchaz.enigma.translation.mapping.tree; |
| 2 | 2 | ||
| 3 | import cuchaz.enigma.translation.Translatable; | ||
| 4 | import cuchaz.enigma.translation.Translator; | ||
| 3 | import cuchaz.enigma.translation.mapping.EntryMap; | 5 | import cuchaz.enigma.translation.mapping.EntryMap; |
| 6 | import cuchaz.enigma.translation.mapping.EntryMapping; | ||
| 7 | import cuchaz.enigma.translation.mapping.EntryResolver; | ||
| 4 | import cuchaz.enigma.translation.representation.entry.Entry; | 8 | import cuchaz.enigma.translation.representation.entry.Entry; |
| 5 | 9 | ||
| 6 | import javax.annotation.Nullable; | 10 | import javax.annotation.Nullable; |
| 7 | import java.util.Collection; | 11 | import java.util.Collection; |
| 8 | 12 | ||
| 9 | public interface EntryTree<T> extends EntryMap<T>, Iterable<EntryTreeNode<T>> { | 13 | public interface EntryTree<T> extends EntryMap<T>, Iterable<EntryTreeNode<T>>, Translatable { |
| 10 | Collection<Entry<?>> getChildren(Entry<?> entry); | 14 | Collection<Entry<?>> getChildren(Entry<?> entry); |
| 11 | 15 | ||
| 12 | Collection<Entry<?>> getSiblings(Entry<?> entry); | 16 | Collection<Entry<?>> getSiblings(Entry<?> entry); |
| @@ -17,4 +21,7 @@ public interface EntryTree<T> extends EntryMap<T>, Iterable<EntryTreeNode<T>> { | |||
| 17 | Collection<EntryTreeNode<T>> getAllNodes(); | 21 | Collection<EntryTreeNode<T>> getAllNodes(); |
| 18 | 22 | ||
| 19 | Collection<Entry<?>> getRootEntries(); | 23 | Collection<Entry<?>> getRootEntries(); |
| 24 | |||
| 25 | @Override | ||
| 26 | EntryTree<T> translate(Translator translator, EntryResolver resolver, EntryMap<EntryMapping> mappings); | ||
| 20 | } | 27 | } |
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 @@ | |||
| 1 | package cuchaz.enigma.translation.mapping.tree; | 1 | package cuchaz.enigma.translation.mapping.tree; |
| 2 | 2 | ||
| 3 | import cuchaz.enigma.translation.Translator; | ||
| 4 | import cuchaz.enigma.translation.mapping.EntryMap; | ||
| 5 | import cuchaz.enigma.translation.mapping.EntryMapping; | ||
| 6 | import cuchaz.enigma.translation.mapping.EntryResolver; | ||
| 3 | import cuchaz.enigma.translation.representation.entry.Entry; | 7 | import cuchaz.enigma.translation.representation.entry.Entry; |
| 4 | 8 | ||
| 5 | import javax.annotation.Nullable; | 9 | import javax.annotation.Nullable; |
| @@ -9,6 +13,15 @@ import java.util.stream.Collectors; | |||
| 9 | public class HashEntryTree<T> implements EntryTree<T> { | 13 | public class HashEntryTree<T> implements EntryTree<T> { |
| 10 | private final Map<Entry<?>, HashTreeNode<T>> root = new HashMap<>(); | 14 | private final Map<Entry<?>, HashTreeNode<T>> root = new HashMap<>(); |
| 11 | 15 | ||
| 16 | public HashEntryTree() { | ||
| 17 | } | ||
| 18 | |||
| 19 | public HashEntryTree(EntryTree<T> tree) { | ||
| 20 | for (EntryTreeNode<T> node : tree.getAllNodes()) { | ||
| 21 | insert(node.getEntry(), node.getValue()); | ||
| 22 | } | ||
| 23 | } | ||
| 24 | |||
| 12 | @Override | 25 | @Override |
| 13 | public void insert(Entry<?> entry, T value) { | 26 | public void insert(Entry<?> entry, T value) { |
| 14 | List<HashTreeNode<T>> path = computePath(entry); | 27 | List<HashTreeNode<T>> path = computePath(entry); |
| @@ -156,4 +169,13 @@ public class HashEntryTree<T> implements EntryTree<T> { | |||
| 156 | public boolean isEmpty() { | 169 | public boolean isEmpty() { |
| 157 | return root.isEmpty(); | 170 | return root.isEmpty(); |
| 158 | } | 171 | } |
| 172 | |||
| 173 | @Override | ||
| 174 | public HashEntryTree<T> translate(Translator translator, EntryResolver resolver, EntryMap<EntryMapping> mappings) { | ||
| 175 | HashEntryTree<T> translatedTree = new HashEntryTree<>(); | ||
| 176 | for (EntryTreeNode<T> node : getAllNodes()) { | ||
| 177 | translatedTree.insert(translator.translate(node.getEntry()), node.getValue()); | ||
| 178 | } | ||
| 179 | return translatedTree; | ||
| 180 | } | ||
| 159 | } | 181 | } |
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; | |||
| 17 | import cuchaz.enigma.translation.representation.entry.*; | 17 | import cuchaz.enigma.translation.representation.entry.*; |
| 18 | 18 | ||
| 19 | public class ProcyonEntryFactory { | 19 | public class ProcyonEntryFactory { |
| 20 | private final ReferencedEntryPool entryPool; | ||
| 21 | |||
| 22 | public ProcyonEntryFactory(ReferencedEntryPool entryPool) { | ||
| 23 | this.entryPool = entryPool; | ||
| 24 | } | ||
| 25 | |||
| 26 | public FieldEntry getFieldEntry(MemberReference def) { | 20 | public FieldEntry getFieldEntry(MemberReference def) { |
| 27 | ClassEntry classEntry = entryPool.getClass(def.getDeclaringType().getInternalName()); | 21 | ClassEntry classEntry = new ClassEntry(def.getDeclaringType().getInternalName()); |
| 28 | return entryPool.getField(classEntry, def.getName(), def.getErasedSignature()); | 22 | return new FieldEntry(classEntry, def.getName(), new TypeDescriptor(def.getErasedSignature())); |
| 29 | } | 23 | } |
| 30 | 24 | ||
| 31 | public FieldDefEntry getFieldDefEntry(FieldDefinition def) { | 25 | public FieldDefEntry getFieldDefEntry(FieldDefinition def) { |
| 32 | ClassEntry classEntry = entryPool.getClass(def.getDeclaringType().getInternalName()); | 26 | ClassEntry classEntry = new ClassEntry(def.getDeclaringType().getInternalName()); |
| 33 | return new FieldDefEntry(classEntry, def.getName(), new TypeDescriptor(def.getErasedSignature()), Signature.createTypedSignature(def.getSignature()), new AccessFlags(def.getModifiers())); | 27 | return new FieldDefEntry(classEntry, def.getName(), new TypeDescriptor(def.getErasedSignature()), Signature.createTypedSignature(def.getSignature()), new AccessFlags(def.getModifiers())); |
| 34 | } | 28 | } |
| 35 | 29 | ||
| 36 | public MethodEntry getMethodEntry(MemberReference def) { | 30 | public MethodEntry getMethodEntry(MemberReference def) { |
| 37 | ClassEntry classEntry = entryPool.getClass(def.getDeclaringType().getInternalName()); | 31 | ClassEntry classEntry = new ClassEntry(def.getDeclaringType().getInternalName()); |
| 38 | return entryPool.getMethod(classEntry, def.getName(), def.getErasedSignature()); | 32 | return new MethodEntry(classEntry, def.getName(), new MethodDescriptor(def.getErasedSignature())); |
| 39 | } | 33 | } |
| 40 | 34 | ||
| 41 | public MethodDefEntry getMethodDefEntry(MethodDefinition def) { | 35 | public MethodDefEntry getMethodDefEntry(MethodDefinition def) { |
| 42 | ClassEntry classEntry = entryPool.getClass(def.getDeclaringType().getInternalName()); | 36 | ClassEntry classEntry = new ClassEntry(def.getDeclaringType().getInternalName()); |
| 43 | return new MethodDefEntry(classEntry, def.getName(), new MethodDescriptor(def.getErasedSignature()), Signature.createSignature(def.getSignature()), new AccessFlags(def.getModifiers())); | 37 | return new MethodDefEntry(classEntry, def.getName(), new MethodDescriptor(def.getErasedSignature()), Signature.createSignature(def.getSignature()), new AccessFlags(def.getModifiers())); |
| 44 | } | 38 | } |
| 45 | } | 39 | } |
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 @@ | |||
| 1 | /******************************************************************************* | ||
| 2 | * Copyright (c) 2015 Jeff Martin. | ||
| 3 | * All rights reserved. This program and the accompanying materials | ||
| 4 | * are made available under the terms of the GNU Lesser General Public | ||
| 5 | * License v3.0 which accompanies this distribution, and is available at | ||
| 6 | * http://www.gnu.org/licenses/lgpl.html | ||
| 7 | * <p> | ||
| 8 | * Contributors: | ||
| 9 | * Jeff Martin - initial API and implementation | ||
| 10 | ******************************************************************************/ | ||
| 11 | |||
| 12 | package cuchaz.enigma.translation.representation; | ||
| 13 | |||
| 14 | import cuchaz.enigma.translation.representation.entry.ClassEntry; | ||
| 15 | import cuchaz.enigma.translation.representation.entry.FieldEntry; | ||
| 16 | import cuchaz.enigma.translation.representation.entry.MethodEntry; | ||
| 17 | |||
| 18 | import java.util.HashMap; | ||
| 19 | import java.util.Map; | ||
| 20 | |||
| 21 | public class ReferencedEntryPool { | ||
| 22 | private final Map<String, ClassEntry> classEntries = new HashMap<>(); | ||
| 23 | private final Map<String, Map<String, MethodEntry>> methodEntries = new HashMap<>(); | ||
| 24 | private final Map<String, Map<String, FieldEntry>> fieldEntries = new HashMap<>(); | ||
| 25 | |||
| 26 | public ClassEntry getClass(String name) { | ||
| 27 | // TODO: FIXME - I'm a hack! | ||
| 28 | if ("[T".equals(name) || "[[T".equals(name) || "[[[T".equals(name)) { | ||
| 29 | name = name.replaceAll("T", "Ljava/lang/Object;"); | ||
| 30 | } | ||
| 31 | |||
| 32 | final String computeName = name; | ||
| 33 | return this.classEntries.computeIfAbsent(name, s -> new ClassEntry(computeName)); | ||
| 34 | } | ||
| 35 | |||
| 36 | public MethodEntry getMethod(ClassEntry ownerEntry, String name, String desc) { | ||
| 37 | return getMethod(ownerEntry, name, new MethodDescriptor(desc)); | ||
| 38 | } | ||
| 39 | |||
| 40 | public MethodEntry getMethod(ClassEntry ownerEntry, String name, MethodDescriptor desc) { | ||
| 41 | String key = name + desc.toString(); | ||
| 42 | return getClassMethods(ownerEntry.getFullName()).computeIfAbsent(key, s -> new MethodEntry(ownerEntry, name, desc)); | ||
| 43 | } | ||
| 44 | |||
| 45 | public FieldEntry getField(ClassEntry ownerEntry, String name, String desc) { | ||
| 46 | return getField(ownerEntry, name, new TypeDescriptor(desc)); | ||
| 47 | } | ||
| 48 | |||
| 49 | public FieldEntry getField(ClassEntry ownerEntry, String name, TypeDescriptor desc) { | ||
| 50 | return getClassFields(ownerEntry.getFullName()).computeIfAbsent(name, s -> new FieldEntry(ownerEntry, name, desc)); | ||
| 51 | } | ||
| 52 | |||
| 53 | private Map<String, MethodEntry> getClassMethods(String name) { | ||
| 54 | return methodEntries.computeIfAbsent(name, s -> new HashMap<>()); | ||
| 55 | } | ||
| 56 | |||
| 57 | private Map<String, FieldEntry> getClassFields(String name) { | ||
| 58 | return fieldEntries.computeIfAbsent(name, s -> new HashMap<>()); | ||
| 59 | } | ||
| 60 | } | ||
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; | |||
| 3 | import cuchaz.enigma.bytecode.translators.TranslationSignatureVisitor; | 3 | import cuchaz.enigma.bytecode.translators.TranslationSignatureVisitor; |
| 4 | import cuchaz.enigma.translation.Translatable; | 4 | import cuchaz.enigma.translation.Translatable; |
| 5 | import cuchaz.enigma.translation.Translator; | 5 | import cuchaz.enigma.translation.Translator; |
| 6 | import cuchaz.enigma.translation.mapping.EntryMap; | ||
| 6 | import cuchaz.enigma.translation.mapping.EntryMapping; | 7 | import cuchaz.enigma.translation.mapping.EntryMapping; |
| 7 | import cuchaz.enigma.translation.mapping.EntryResolver; | 8 | import cuchaz.enigma.translation.mapping.EntryResolver; |
| 8 | import cuchaz.enigma.translation.mapping.EntryMap; | ||
| 9 | import cuchaz.enigma.translation.representation.entry.ClassEntry; | 9 | import cuchaz.enigma.translation.representation.entry.ClassEntry; |
| 10 | import org.objectweb.asm.signature.SignatureReader; | 10 | import org.objectweb.asm.signature.SignatureReader; |
| 11 | import org.objectweb.asm.signature.SignatureVisitor; | 11 | import org.objectweb.asm.signature.SignatureVisitor; |
| @@ -78,7 +78,12 @@ public class Signature implements Translatable { | |||
| 78 | 78 | ||
| 79 | @Override | 79 | @Override |
| 80 | public int hashCode() { | 80 | public int hashCode() { |
| 81 | return signature.hashCode() | (isType ? 1 : 0) << 16; | 81 | int hash = (isType ? 1 : 0) << 16; |
| 82 | if (signature != null) { | ||
| 83 | hash |= signature.hashCode(); | ||
| 84 | } | ||
| 85 | |||
| 86 | return hash; | ||
| 82 | } | 87 | } |
| 83 | 88 | ||
| 84 | @Override | 89 | @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; | |||
| 13 | 13 | ||
| 14 | import com.google.common.base.Preconditions; | 14 | import com.google.common.base.Preconditions; |
| 15 | import com.google.common.collect.Maps; | 15 | import com.google.common.collect.Maps; |
| 16 | import com.strobel.assembler.metadata.TypeReference; | ||
| 16 | import cuchaz.enigma.translation.Translatable; | 17 | import cuchaz.enigma.translation.Translatable; |
| 17 | import cuchaz.enigma.translation.Translator; | 18 | import cuchaz.enigma.translation.Translator; |
| 18 | import cuchaz.enigma.translation.mapping.EntryMapping; | 19 | import cuchaz.enigma.translation.mapping.EntryMapping; |
| @@ -111,6 +112,10 @@ public class TypeDescriptor implements Translatable { | |||
| 111 | return new TypeDescriptor("L" + name + ";"); | 112 | return new TypeDescriptor("L" + name + ";"); |
| 112 | } | 113 | } |
| 113 | 114 | ||
| 115 | public static TypeDescriptor parse(TypeReference type) { | ||
| 116 | return new TypeDescriptor(type.getErasedSignature()); | ||
| 117 | } | ||
| 118 | |||
| 114 | @Override | 119 | @Override |
| 115 | public String toString() { | 120 | public String toString() { |
| 116 | return this.desc; | 121 | 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; | |||
| 17 | import cuchaz.enigma.translation.mapping.EntryMapping; | 17 | import cuchaz.enigma.translation.mapping.EntryMapping; |
| 18 | import cuchaz.enigma.translation.mapping.NameValidator; | 18 | import cuchaz.enigma.translation.mapping.NameValidator; |
| 19 | 19 | ||
| 20 | import javax.annotation.Nonnull; | ||
| 20 | import javax.annotation.Nullable; | 21 | import javax.annotation.Nullable; |
| 21 | import java.util.List; | 22 | import java.util.List; |
| 22 | import java.util.Objects; | 23 | import java.util.Objects; |
| @@ -125,6 +126,7 @@ public class ClassEntry extends ParentedEntry<ClassEntry> implements Comparable< | |||
| 125 | return parent; | 126 | return parent; |
| 126 | } | 127 | } |
| 127 | 128 | ||
| 129 | @Nonnull | ||
| 128 | public ClassEntry getOutermostClass() { | 130 | public ClassEntry getOutermostClass() { |
| 129 | if (parent == null) { | 131 | if (parent == null) { |
| 130 | return this; | 132 | return this; |
| @@ -181,6 +183,15 @@ public class ClassEntry extends ParentedEntry<ClassEntry> implements Comparable< | |||
| 181 | } | 183 | } |
| 182 | 184 | ||
| 183 | @Override | 185 | @Override |
| 186 | public String getSourceRemapName() { | ||
| 187 | ClassEntry outerClass = getOuterClass(); | ||
| 188 | if (outerClass != null) { | ||
| 189 | return outerClass.getSourceRemapName() + "." + name; | ||
| 190 | } | ||
| 191 | return getSimpleName(); | ||
| 192 | } | ||
| 193 | |||
| 194 | @Override | ||
| 184 | public int compareTo(ClassEntry entry) { | 195 | public int compareTo(ClassEntry entry) { |
| 185 | return name.compareTo(entry.name); | 196 | return name.compareTo(entry.name); |
| 186 | } | 197 | } |
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; | |||
| 22 | public interface Entry<P extends Entry<?>> extends Translatable { | 22 | public interface Entry<P extends Entry<?>> extends Translatable { |
| 23 | String getName(); | 23 | String getName(); |
| 24 | 24 | ||
| 25 | default String getSourceRemapName() { | ||
| 26 | return getName(); | ||
| 27 | } | ||
| 28 | |||
| 25 | @Nullable | 29 | @Nullable |
| 26 | P getParent(); | 30 | P getParent(); |
| 27 | 31 | ||
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<MethodEntry> implements Co | |||
| 17 | protected final int index; | 17 | protected final int index; |
| 18 | protected final boolean parameter; | 18 | protected final boolean parameter; |
| 19 | 19 | ||
| 20 | @Deprecated | ||
| 21 | public LocalVariableEntry(MethodEntry parent, int index, String name) { | ||
| 22 | this(parent, index, name, true); | ||
| 23 | } | ||
| 24 | |||
| 25 | public LocalVariableEntry(MethodEntry parent, int index, String name, boolean parameter) { | 20 | public LocalVariableEntry(MethodEntry parent, int index, String name, boolean parameter) { |
| 26 | super(parent, name); | 21 | super(parent, name); |
| 27 | 22 | ||
| @@ -37,7 +32,7 @@ public class LocalVariableEntry extends ParentedEntry<MethodEntry> implements Co | |||
| 37 | return MethodEntry.class; | 32 | return MethodEntry.class; |
| 38 | } | 33 | } |
| 39 | 34 | ||
| 40 | public boolean isParameter() { | 35 | public boolean isArgument() { |
| 41 | return this.parameter; | 36 | return this.parameter; |
| 42 | } | 37 | } |
| 43 | 38 | ||