summaryrefslogtreecommitdiff
path: root/src/main/java/cuchaz/enigma/translation
diff options
context:
space:
mode:
authorGravatar Gegy2019-01-30 21:05:32 +0200
committerGravatar GitHub2019-01-30 21:05:32 +0200
commitba7a354efae7d49833c887cf147ac940c975a1fa (patch)
tree02e14fda81dd5984e24f2df392c57c6e829fc875 /src/main/java/cuchaz/enigma/translation
parentRewrite the Jenkinsfile to use the new declarative pipeline syntax, lets hope... (diff)
downloadenigma-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')
-rw-r--r--src/main/java/cuchaz/enigma/translation/LocalNameGenerator.java44
-rw-r--r--src/main/java/cuchaz/enigma/translation/mapping/EntryRemapper.java125
-rw-r--r--src/main/java/cuchaz/enigma/translation/mapping/MappingDelta.java36
-rw-r--r--src/main/java/cuchaz/enigma/translation/mapping/MappingValidator.java14
-rw-r--r--src/main/java/cuchaz/enigma/translation/mapping/serde/EnigmaMappingsWriter.java19
-rw-r--r--src/main/java/cuchaz/enigma/translation/mapping/serde/MappingFormat.java2
-rw-r--r--src/main/java/cuchaz/enigma/translation/mapping/serde/MappingsWriter.java6
-rw-r--r--src/main/java/cuchaz/enigma/translation/mapping/serde/SrgMappingsWriter.java2
-rw-r--r--src/main/java/cuchaz/enigma/translation/mapping/tree/DeltaTrackingTree.java21
-rw-r--r--src/main/java/cuchaz/enigma/translation/mapping/tree/EntryTree.java9
-rw-r--r--src/main/java/cuchaz/enigma/translation/mapping/tree/HashEntryTree.java22
-rw-r--r--src/main/java/cuchaz/enigma/translation/representation/ProcyonEntryFactory.java18
-rw-r--r--src/main/java/cuchaz/enigma/translation/representation/ReferencedEntryPool.java60
-rw-r--r--src/main/java/cuchaz/enigma/translation/representation/Signature.java9
-rw-r--r--src/main/java/cuchaz/enigma/translation/representation/TypeDescriptor.java5
-rw-r--r--src/main/java/cuchaz/enigma/translation/representation/entry/ClassEntry.java11
-rw-r--r--src/main/java/cuchaz/enigma/translation/representation/entry/Entry.java4
-rw-r--r--src/main/java/cuchaz/enigma/translation/representation/entry/LocalVariableEntry.java7
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 @@
1package cuchaz.enigma.translation;
2
3import cuchaz.enigma.translation.mapping.NameValidator;
4import cuchaz.enigma.translation.representation.TypeDescriptor;
5
6import java.util.Collection;
7import java.util.Locale;
8
9public 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;
6import cuchaz.enigma.translation.Translator; 6import cuchaz.enigma.translation.Translator;
7import cuchaz.enigma.translation.mapping.tree.DeltaTrackingTree; 7import cuchaz.enigma.translation.mapping.tree.DeltaTrackingTree;
8import cuchaz.enigma.translation.mapping.tree.EntryTree; 8import cuchaz.enigma.translation.mapping.tree.EntryTree;
9import cuchaz.enigma.translation.mapping.tree.EntryTreeNode;
10import cuchaz.enigma.translation.mapping.tree.HashEntryTree; 9import cuchaz.enigma.translation.mapping.tree.HashEntryTree;
11import cuchaz.enigma.translation.representation.entry.Entry; 10import cuchaz.enigma.translation.representation.entry.Entry;
12 11
@@ -14,59 +13,25 @@ import javax.annotation.Nullable;
14import java.util.Collection; 13import java.util.Collection;
15 14
16public class EntryRemapper { 15public 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;
6import cuchaz.enigma.translation.mapping.tree.EntryTree; 6import cuchaz.enigma.translation.mapping.tree.EntryTree;
7import cuchaz.enigma.translation.representation.entry.Entry; 7import cuchaz.enigma.translation.representation.entry.Entry;
8 8
9public class MappingDelta implements Translatable { 9public 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;
6import cuchaz.enigma.translation.representation.entry.Entry; 6import cuchaz.enigma.translation.representation.entry.Entry;
7 7
8import java.util.Collection; 8import java.util.Collection;
9import java.util.stream.Collectors;
9 10
10public class MappingValidator { 11public 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;
14import cuchaz.enigma.ProgressListener; 14import cuchaz.enigma.ProgressListener;
15import cuchaz.enigma.translation.MappingTranslator; 15import cuchaz.enigma.translation.MappingTranslator;
16import cuchaz.enigma.translation.Translator; 16import cuchaz.enigma.translation.Translator;
17import cuchaz.enigma.translation.mapping.AccessModifier; 17import cuchaz.enigma.translation.mapping.*;
18import cuchaz.enigma.translation.mapping.EntryMapping;
19import cuchaz.enigma.translation.mapping.MappingDelta;
20import cuchaz.enigma.translation.mapping.VoidEntryResolver;
21import cuchaz.enigma.translation.mapping.tree.EntryTree; 18import cuchaz.enigma.translation.mapping.tree.EntryTree;
22import cuchaz.enigma.translation.mapping.tree.EntryTreeNode; 19import cuchaz.enigma.translation.mapping.tree.EntryTreeNode;
23import cuchaz.enigma.translation.representation.entry.*; 20import cuchaz.enigma.translation.representation.entry.*;
@@ -37,7 +34,7 @@ import java.util.stream.Collectors;
37public enum EnigmaMappingsWriter implements MappingsWriter { 34public 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;
8import java.nio.file.Path; 8import java.nio.file.Path;
9 9
10public interface MappingsWriter { 10public 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 @@
1package cuchaz.enigma.translation.mapping.tree; 1package cuchaz.enigma.translation.mapping.tree;
2 2
3import cuchaz.enigma.translation.Translator;
4import cuchaz.enigma.translation.mapping.EntryMap;
5import cuchaz.enigma.translation.mapping.EntryMapping;
6import cuchaz.enigma.translation.mapping.EntryResolver;
3import cuchaz.enigma.translation.mapping.MappingDelta; 7import cuchaz.enigma.translation.mapping.MappingDelta;
4import cuchaz.enigma.translation.representation.entry.Entry; 8import cuchaz.enigma.translation.representation.entry.Entry;
5 9
@@ -10,11 +14,13 @@ import java.util.Iterator;
10public class DeltaTrackingTree<T> implements EntryTree<T> { 14public 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 @@
1package cuchaz.enigma.translation.mapping.tree; 1package cuchaz.enigma.translation.mapping.tree;
2 2
3import cuchaz.enigma.translation.Translatable;
4import cuchaz.enigma.translation.Translator;
3import cuchaz.enigma.translation.mapping.EntryMap; 5import cuchaz.enigma.translation.mapping.EntryMap;
6import cuchaz.enigma.translation.mapping.EntryMapping;
7import cuchaz.enigma.translation.mapping.EntryResolver;
4import cuchaz.enigma.translation.representation.entry.Entry; 8import cuchaz.enigma.translation.representation.entry.Entry;
5 9
6import javax.annotation.Nullable; 10import javax.annotation.Nullable;
7import java.util.Collection; 11import java.util.Collection;
8 12
9public interface EntryTree<T> extends EntryMap<T>, Iterable<EntryTreeNode<T>> { 13public 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 @@
1package cuchaz.enigma.translation.mapping.tree; 1package cuchaz.enigma.translation.mapping.tree;
2 2
3import cuchaz.enigma.translation.Translator;
4import cuchaz.enigma.translation.mapping.EntryMap;
5import cuchaz.enigma.translation.mapping.EntryMapping;
6import cuchaz.enigma.translation.mapping.EntryResolver;
3import cuchaz.enigma.translation.representation.entry.Entry; 7import cuchaz.enigma.translation.representation.entry.Entry;
4 8
5import javax.annotation.Nullable; 9import javax.annotation.Nullable;
@@ -9,6 +13,15 @@ import java.util.stream.Collectors;
9public class HashEntryTree<T> implements EntryTree<T> { 13public 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;
17import cuchaz.enigma.translation.representation.entry.*; 17import cuchaz.enigma.translation.representation.entry.*;
18 18
19public class ProcyonEntryFactory { 19public 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
12package cuchaz.enigma.translation.representation;
13
14import cuchaz.enigma.translation.representation.entry.ClassEntry;
15import cuchaz.enigma.translation.representation.entry.FieldEntry;
16import cuchaz.enigma.translation.representation.entry.MethodEntry;
17
18import java.util.HashMap;
19import java.util.Map;
20
21public 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;
3import cuchaz.enigma.bytecode.translators.TranslationSignatureVisitor; 3import cuchaz.enigma.bytecode.translators.TranslationSignatureVisitor;
4import cuchaz.enigma.translation.Translatable; 4import cuchaz.enigma.translation.Translatable;
5import cuchaz.enigma.translation.Translator; 5import cuchaz.enigma.translation.Translator;
6import cuchaz.enigma.translation.mapping.EntryMap;
6import cuchaz.enigma.translation.mapping.EntryMapping; 7import cuchaz.enigma.translation.mapping.EntryMapping;
7import cuchaz.enigma.translation.mapping.EntryResolver; 8import cuchaz.enigma.translation.mapping.EntryResolver;
8import cuchaz.enigma.translation.mapping.EntryMap;
9import cuchaz.enigma.translation.representation.entry.ClassEntry; 9import cuchaz.enigma.translation.representation.entry.ClassEntry;
10import org.objectweb.asm.signature.SignatureReader; 10import org.objectweb.asm.signature.SignatureReader;
11import org.objectweb.asm.signature.SignatureVisitor; 11import 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
14import com.google.common.base.Preconditions; 14import com.google.common.base.Preconditions;
15import com.google.common.collect.Maps; 15import com.google.common.collect.Maps;
16import com.strobel.assembler.metadata.TypeReference;
16import cuchaz.enigma.translation.Translatable; 17import cuchaz.enigma.translation.Translatable;
17import cuchaz.enigma.translation.Translator; 18import cuchaz.enigma.translation.Translator;
18import cuchaz.enigma.translation.mapping.EntryMapping; 19import 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;
17import cuchaz.enigma.translation.mapping.EntryMapping; 17import cuchaz.enigma.translation.mapping.EntryMapping;
18import cuchaz.enigma.translation.mapping.NameValidator; 18import cuchaz.enigma.translation.mapping.NameValidator;
19 19
20import javax.annotation.Nonnull;
20import javax.annotation.Nullable; 21import javax.annotation.Nullable;
21import java.util.List; 22import java.util.List;
22import java.util.Objects; 23import 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;
22public interface Entry<P extends Entry<?>> extends Translatable { 22public 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