summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--enigma-server/src/main/java/cuchaz/enigma/network/packet/EntryChangeC2SPacket.java2
-rw-r--r--enigma-swing/src/main/java/cuchaz/enigma/gui/GuiController.java2
-rw-r--r--enigma/src/main/java/cuchaz/enigma/EnigmaProject.java57
-rw-r--r--enigma/src/main/java/cuchaz/enigma/api/view/ProjectView.java7
-rw-r--r--enigma/src/main/java/cuchaz/enigma/translation/ObfuscatingTranslator.java115
-rw-r--r--enigma/src/main/java/cuchaz/enigma/translation/Translator.java2
-rw-r--r--enigma/src/main/java/cuchaz/enigma/translation/mapping/EntryRemapper.java10
-rw-r--r--enigma/src/main/java/cuchaz/enigma/translation/mapping/EntryUtil.java10
-rw-r--r--enigma/src/main/java/cuchaz/enigma/translation/representation/entry/FieldEntry.java4
-rw-r--r--enigma/src/main/java/cuchaz/enigma/translation/representation/entry/MethodEntry.java4
10 files changed, 198 insertions, 15 deletions
diff --git a/enigma-server/src/main/java/cuchaz/enigma/network/packet/EntryChangeC2SPacket.java b/enigma-server/src/main/java/cuchaz/enigma/network/packet/EntryChangeC2SPacket.java
index 6a7ffe99..f45ac997 100644
--- a/enigma-server/src/main/java/cuchaz/enigma/network/packet/EntryChangeC2SPacket.java
+++ b/enigma-server/src/main/java/cuchaz/enigma/network/packet/EntryChangeC2SPacket.java
@@ -39,7 +39,7 @@ public class EntryChangeC2SPacket implements Packet<ServerPacketHandler> {
39 boolean valid = handler.getServer().canModifyEntry(handler.getClient(), this.change.getTarget()); 39 boolean valid = handler.getServer().canModifyEntry(handler.getClient(), this.change.getTarget());
40 40
41 if (valid) { 41 if (valid) {
42 EntryUtil.applyChange(vc, handler.getServer().getMappings(), this.change); 42 EntryUtil.applyChange(vc, null, handler.getServer().getMappings(), this.change);
43 valid = vc.canProceed(); 43 valid = vc.canProceed();
44 } 44 }
45 45
diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/GuiController.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/GuiController.java
index 7691f39c..5ea9ab1c 100644
--- a/enigma-swing/src/main/java/cuchaz/enigma/gui/GuiController.java
+++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/GuiController.java
@@ -583,7 +583,7 @@ public class GuiController implements ClientPacketHandler, GuiView, DataInvalida
583 583
584 Entry<?> target = change.getTarget(); 584 Entry<?> target = change.getTarget();
585 EntryMapping prev = this.project.getMapper().getDeobfMapping(target); 585 EntryMapping prev = this.project.getMapper().getDeobfMapping(target);
586 EntryMapping mapping = EntryUtil.applyChange(vc, this.project.getMapper(), change); 586 EntryMapping mapping = EntryUtil.applyChange(vc, this.project, this.project.getMapper(), change);
587 587
588 boolean renamed = !change.getDeobfName().isUnchanged(); 588 boolean renamed = !change.getDeobfName().isUnchanged();
589 589
diff --git a/enigma/src/main/java/cuchaz/enigma/EnigmaProject.java b/enigma/src/main/java/cuchaz/enigma/EnigmaProject.java
index 4a528a7b..86a70372 100644
--- a/enigma/src/main/java/cuchaz/enigma/EnigmaProject.java
+++ b/enigma/src/main/java/cuchaz/enigma/EnigmaProject.java
@@ -38,9 +38,11 @@ import cuchaz.enigma.classprovider.ObfuscationFixClassProvider;
38import cuchaz.enigma.source.Decompiler; 38import cuchaz.enigma.source.Decompiler;
39import cuchaz.enigma.source.DecompilerService; 39import cuchaz.enigma.source.DecompilerService;
40import cuchaz.enigma.source.SourceSettings; 40import cuchaz.enigma.source.SourceSettings;
41import cuchaz.enigma.translation.ObfuscatingTranslator;
41import cuchaz.enigma.translation.ProposingTranslator; 42import cuchaz.enigma.translation.ProposingTranslator;
42import cuchaz.enigma.translation.Translatable; 43import cuchaz.enigma.translation.Translatable;
43import cuchaz.enigma.translation.Translator; 44import cuchaz.enigma.translation.Translator;
45import cuchaz.enigma.translation.mapping.EntryChange;
44import cuchaz.enigma.translation.mapping.EntryMapping; 46import cuchaz.enigma.translation.mapping.EntryMapping;
45import cuchaz.enigma.translation.mapping.EntryRemapper; 47import cuchaz.enigma.translation.mapping.EntryRemapper;
46import cuchaz.enigma.translation.mapping.MappingsChecker; 48import cuchaz.enigma.translation.mapping.MappingsChecker;
@@ -63,6 +65,9 @@ public class EnigmaProject implements ProjectView {
63 private final Set<String> projectClasses; 65 private final Set<String> projectClasses;
64 66
65 private EntryRemapper mapper; 67 private EntryRemapper mapper;
68 private Translator proposingTranslator;
69 @Nullable
70 private ObfuscatingTranslator inverseTranslator;
66 71
67 private final List<DataInvalidationListener> dataInvalidationListeners = new ArrayList<>(); 72 private final List<DataInvalidationListener> dataInvalidationListeners = new ArrayList<>();
68 73
@@ -78,7 +83,7 @@ public class EnigmaProject implements ProjectView {
78 this.jarChecksum = jarChecksum; 83 this.jarChecksum = jarChecksum;
79 this.projectClasses = projectClasses; 84 this.projectClasses = projectClasses;
80 85
81 this.mapper = EntryRemapper.empty(jarIndex); 86 setMappings(null);
82 } 87 }
83 88
84 public void setMappings(EntryTree<EntryMapping> mappings) { 89 public void setMappings(EntryTree<EntryMapping> mappings) {
@@ -87,6 +92,13 @@ public class EnigmaProject implements ProjectView {
87 } else { 92 } else {
88 mapper = EntryRemapper.empty(jarIndex); 93 mapper = EntryRemapper.empty(jarIndex);
89 } 94 }
95
96 NameProposalService[] nameProposalServices = enigma.getServices().get(NameProposalService.TYPE).toArray(new NameProposalService[0]);
97 proposingTranslator = nameProposalServices.length == 0 ? mapper.getDeobfuscator() : new ProposingTranslator(mapper, nameProposalServices);
98
99 if (inverseTranslator != null) {
100 inverseTranslator.refreshAll(proposingTranslator);
101 }
90 } 102 }
91 103
92 public Enigma getEnigma() { 104 public Enigma getEnigma() {
@@ -121,6 +133,10 @@ public class EnigmaProject implements ProjectView {
121 for (Entry<?> entry : dropped) { 133 for (Entry<?> entry : dropped) {
122 mappings.trackChange(entry); 134 mappings.trackChange(entry);
123 } 135 }
136
137 if (inverseTranslator != null) {
138 inverseTranslator.refreshAll(proposingTranslator);
139 }
124 } 140 }
125 141
126 private Collection<Entry<?>> dropMappings(EntryTree<EntryMapping> mappings, ProgressListener progress) { 142 private Collection<Entry<?>> dropMappings(EntryTree<EntryMapping> mappings, ProgressListener progress) {
@@ -224,21 +240,18 @@ public class EnigmaProject implements ProjectView {
224 Collection<ClassEntry> classEntries = jarIndex.getEntryIndex().getClasses(); 240 Collection<ClassEntry> classEntries = jarIndex.getEntryIndex().getClasses();
225 ClassProvider fixingClassProvider = new ObfuscationFixClassProvider(classProvider, jarIndex); 241 ClassProvider fixingClassProvider = new ObfuscationFixClassProvider(classProvider, jarIndex);
226 242
227 NameProposalService[] nameProposalServices = getEnigma().getServices().get(NameProposalService.TYPE).toArray(new NameProposalService[0]);
228 Translator deobfuscator = nameProposalServices.length == 0 ? mapper.getDeobfuscator() : new ProposingTranslator(mapper, nameProposalServices);
229
230 AtomicInteger count = new AtomicInteger(); 243 AtomicInteger count = new AtomicInteger();
231 progress.init(classEntries.size(), I18n.translate("progress.classes.deobfuscating")); 244 progress.init(classEntries.size(), I18n.translate("progress.classes.deobfuscating"));
232 245
233 Map<String, ClassNode> compiled = classEntries.parallelStream().map(entry -> { 246 Map<String, ClassNode> compiled = classEntries.parallelStream().map(entry -> {
234 ClassEntry translatedEntry = deobfuscator.translate(entry); 247 ClassEntry translatedEntry = proposingTranslator.translate(entry);
235 progress.step(count.getAndIncrement(), translatedEntry.toString()); 248 progress.step(count.getAndIncrement(), translatedEntry.toString());
236 249
237 ClassNode node = fixingClassProvider.get(entry.getFullName()); 250 ClassNode node = fixingClassProvider.get(entry.getFullName());
238 251
239 if (node != null) { 252 if (node != null) {
240 ClassNode translatedNode = new ClassNode(); 253 ClassNode translatedNode = new ClassNode();
241 node.accept(new TranslationClassVisitor(deobfuscator, Enigma.ASM_VERSION, translatedNode)); 254 node.accept(new TranslationClassVisitor(proposingTranslator, Enigma.ASM_VERSION, translatedNode));
242 return translatedNode; 255 return translatedNode;
243 } 256 }
244 257
@@ -348,7 +361,37 @@ public class EnigmaProject implements ProjectView {
348 @Override 361 @Override
349 @SuppressWarnings("unchecked") 362 @SuppressWarnings("unchecked")
350 public <T extends EntryView> T deobfuscate(T entry) { 363 public <T extends EntryView> T deobfuscate(T entry) {
351 return (T) mapper.extendedDeobfuscate((Translatable) entry).getValue(); 364 return (T) proposingTranslator.extendedTranslate((Translatable) entry).getValue();
365 }
366
367 @Override
368 @SuppressWarnings("unchecked")
369 public <T extends EntryView> T obfuscate(T entry) {
370 if (inverseTranslator == null) {
371 throw new IllegalStateException("Must call registerForInverseMappings before calling obfuscate");
372 }
373
374 return (T) inverseTranslator.extendedTranslate((Entry<?>) entry).getValue();
375 }
376
377 @Override
378 public void registerForInverseMappings() {
379 if (inverseTranslator == null) {
380 inverseTranslator = new ObfuscatingTranslator(jarIndex);
381 inverseTranslator.refreshAll(proposingTranslator);
382 }
383 }
384
385 public void onEntryChange(EntryMapping prevMapping, EntryChange<?> change) {
386 if (inverseTranslator == null || change.getDeobfName().isUnchanged()) {
387 return;
388 }
389
390 String newName = change.getDeobfName().isSet() ? change.getDeobfName().getNewValue() : proposingTranslator.extendedTranslate(change.getTarget()).getValue().getName();
391
392 for (Entry<?> equivalentEntry : mapper.getObfResolver().resolveEquivalentEntries(change.getTarget())) {
393 inverseTranslator.refreshName(equivalentEntry, prevMapping.targetName(), newName);
394 }
352 } 395 }
353 396
354 @Override 397 @Override
diff --git a/enigma/src/main/java/cuchaz/enigma/api/view/ProjectView.java b/enigma/src/main/java/cuchaz/enigma/api/view/ProjectView.java
index b8760e29..8f53d118 100644
--- a/enigma/src/main/java/cuchaz/enigma/api/view/ProjectView.java
+++ b/enigma/src/main/java/cuchaz/enigma/api/view/ProjectView.java
@@ -13,6 +13,13 @@ import cuchaz.enigma.api.view.entry.EntryView;
13public interface ProjectView { 13public interface ProjectView {
14 <T extends EntryView> T deobfuscate(T entry); 14 <T extends EntryView> T deobfuscate(T entry);
15 15
16 /**
17 * Must call {@link #registerForInverseMappings()} before using this method.
18 */
19 <T extends EntryView> T obfuscate(T entry);
20
21 void registerForInverseMappings();
22
16 Collection<String> getProjectClasses(); 23 Collection<String> getProjectClasses();
17 24
18 @Nullable 25 @Nullable
diff --git a/enigma/src/main/java/cuchaz/enigma/translation/ObfuscatingTranslator.java b/enigma/src/main/java/cuchaz/enigma/translation/ObfuscatingTranslator.java
new file mode 100644
index 00000000..27220e0c
--- /dev/null
+++ b/enigma/src/main/java/cuchaz/enigma/translation/ObfuscatingTranslator.java
@@ -0,0 +1,115 @@
1package cuchaz.enigma.translation;
2
3import java.util.ArrayList;
4import java.util.Collection;
5import java.util.List;
6import java.util.Set;
7
8import org.jetbrains.annotations.Nullable;
9
10import cuchaz.enigma.analysis.index.JarIndex;
11import cuchaz.enigma.translation.mapping.EntryMapping;
12import cuchaz.enigma.translation.mapping.EntryResolver;
13import cuchaz.enigma.translation.mapping.ResolutionStrategy;
14import cuchaz.enigma.translation.mapping.tree.EntryTree;
15import cuchaz.enigma.translation.mapping.tree.HashEntryTree;
16import cuchaz.enigma.translation.representation.entry.ClassEntry;
17import cuchaz.enigma.translation.representation.entry.Entry;
18import cuchaz.enigma.translation.representation.entry.FieldEntry;
19import cuchaz.enigma.translation.representation.entry.MethodEntry;
20import cuchaz.enigma.translation.representation.entry.ParentedEntry;
21
22public class ObfuscatingTranslator implements Translator {
23 private final JarIndex jarIndex;
24
25 private final EntryTree<EntryMapping> inverseMappings = new HashEntryTree<>();
26 private final EntryResolver resolver = new ObfuscatingResolver();
27
28 public ObfuscatingTranslator(JarIndex jarIndex) {
29 this.jarIndex = jarIndex;
30 }
31
32 @Override
33 @Nullable
34 @SuppressWarnings("unchecked")
35 public <T extends Translatable> TranslateResult<T> extendedTranslate(@Nullable T translatable) {
36 if (translatable == null) {
37 return null;
38 }
39
40 if (translatable instanceof FieldEntry || translatable instanceof MethodEntry) {
41 ParentedEntry<ClassEntry> key = obfOwnerAndDesc((ParentedEntry<ClassEntry>) translatable);
42 EntryMapping mapping = inverseMappings.get(key);
43 return mapping == null ? TranslateResult.obfuscated((T) key) : TranslateResult.deobfuscated((T) key.withName(mapping.targetName()));
44 }
45
46 return (TranslateResult<T>) translatable.extendedTranslate(this, resolver, inverseMappings);
47 }
48
49 public void refreshAll(Translator deobfuscator) {
50 inverseMappings.clear();
51
52 for (ClassEntry clazz : jarIndex.getEntryIndex().getClasses()) {
53 inverseMappings.insert(deobfuscator.extendedTranslate(clazz).getValue(), new EntryMapping(clazz.getName()));
54 }
55
56 for (FieldEntry field : jarIndex.getEntryIndex().getFields()) {
57 inverseMappings.insert(obfOwnerAndDesc(deobfuscator.extendedTranslate(field).getValue()), new EntryMapping(field.getName()));
58 }
59
60 for (MethodEntry method : jarIndex.getEntryIndex().getMethods()) {
61 inverseMappings.insert(obfOwnerAndDesc(deobfuscator.extendedTranslate(method).getValue()), new EntryMapping(method.getName()));
62 }
63 }
64
65 public void refreshName(Entry<?> entry, String oldDeobfName, String newDeobfName) {
66 inverseMappings.remove(entry.withName(oldDeobfName));
67 inverseMappings.insert(entry.withName(newDeobfName), new EntryMapping(entry.getName()));
68 }
69
70 @SuppressWarnings("unchecked")
71 private <T extends ParentedEntry<ClassEntry>> T obfOwnerAndDesc(T translatable) {
72 if (translatable.getParent() != null) {
73 translatable = (T) translatable.withParent(extendedTranslate(translatable.getParent()).getValue());
74 }
75
76 if (translatable instanceof FieldEntry field) {
77 translatable = (T) field.withDesc(extendedTranslate(field.getDesc()).getValue());
78 } else if (translatable instanceof MethodEntry method) {
79 translatable = (T) method.withDesc(extendedTranslate(method.getDesc()).getValue());
80 }
81
82 return translatable;
83 }
84
85 private class ObfuscatingResolver implements EntryResolver {
86 @Override
87 @SuppressWarnings("unchecked")
88 public <E extends Entry<?>> Collection<E> resolveEntry(E entry, ResolutionStrategy strategy) {
89 ClassEntry containingClass;
90
91 if (entry instanceof ClassEntry || (containingClass = entry.findAncestor(ClassEntry.class)) == null) {
92 return List.of(entry);
93 }
94
95 List<E> result = new ArrayList<>();
96 result.add(entry);
97
98 for (ClassEntry parentClass : jarIndex.getInheritanceIndex().getAncestors(containingClass)) {
99 result.add((E) entry.replaceAncestor(containingClass, parentClass));
100 }
101
102 return result;
103 }
104
105 @Override
106 public Set<Entry<?>> resolveEquivalentEntries(Entry<?> entry) {
107 return Set.of(entry);
108 }
109
110 @Override
111 public Set<MethodEntry> resolveEquivalentMethods(MethodEntry methodEntry) {
112 return Set.of(methodEntry);
113 }
114 }
115}
diff --git a/enigma/src/main/java/cuchaz/enigma/translation/Translator.java b/enigma/src/main/java/cuchaz/enigma/translation/Translator.java
index 56889908..593b4efa 100644
--- a/enigma/src/main/java/cuchaz/enigma/translation/Translator.java
+++ b/enigma/src/main/java/cuchaz/enigma/translation/Translator.java
@@ -18,10 +18,12 @@ import java.util.Map;
18import java.util.Set; 18import java.util.Set;
19import java.util.stream.Collectors; 19import java.util.stream.Collectors;
20 20
21import org.jetbrains.annotations.Contract;
21import org.jetbrains.annotations.Nullable; 22import org.jetbrains.annotations.Nullable;
22 23
23public interface Translator { 24public interface Translator {
24 @Nullable 25 @Nullable
26 @Contract("null -> null; !null -> !null")
25 <T extends Translatable> TranslateResult<T> extendedTranslate(@Nullable T translatable); 27 <T extends Translatable> TranslateResult<T> extendedTranslate(@Nullable T translatable);
26 28
27 @Deprecated 29 @Deprecated
diff --git a/enigma/src/main/java/cuchaz/enigma/translation/mapping/EntryRemapper.java b/enigma/src/main/java/cuchaz/enigma/translation/mapping/EntryRemapper.java
index 12ed7b1d..dea2d151 100644
--- a/enigma/src/main/java/cuchaz/enigma/translation/mapping/EntryRemapper.java
+++ b/enigma/src/main/java/cuchaz/enigma/translation/mapping/EntryRemapper.java
@@ -54,11 +54,11 @@ public class EntryRemapper {
54 doPutMapping(vc, obfuscatedEntry, deobfMapping, true); 54 doPutMapping(vc, obfuscatedEntry, deobfMapping, true);
55 } 55 }
56 56
57 public void putMapping(ValidationContext vc, Entry<?> obfuscatedEntry, @NotNull EntryMapping deobfMapping) { 57 public boolean putMapping(ValidationContext vc, Entry<?> obfuscatedEntry, @NotNull EntryMapping deobfMapping) {
58 doPutMapping(vc, obfuscatedEntry, deobfMapping, false); 58 return doPutMapping(vc, obfuscatedEntry, deobfMapping, false);
59 } 59 }
60 60
61 private void doPutMapping(ValidationContext vc, Entry<?> obfuscatedEntry, @NotNull EntryMapping deobfMapping, boolean validateOnly) { 61 private boolean doPutMapping(ValidationContext vc, Entry<?> obfuscatedEntry, @NotNull EntryMapping deobfMapping, boolean validateOnly) {
62 if (obfuscatedEntry instanceof FieldEntry) { 62 if (obfuscatedEntry instanceof FieldEntry) {
63 FieldEntry fieldEntry = (FieldEntry) obfuscatedEntry; 63 FieldEntry fieldEntry = (FieldEntry) obfuscatedEntry;
64 ClassEntry classEntry = fieldEntry.getParent(); 64 ClassEntry classEntry = fieldEntry.getParent();
@@ -77,7 +77,7 @@ public class EntryRemapper {
77 } 77 }
78 78
79 if (validateOnly || !vc.canProceed()) { 79 if (validateOnly || !vc.canProceed()) {
80 return; 80 return false;
81 } 81 }
82 82
83 for (Entry<?> resolvedEntry : resolvedEntries) { 83 for (Entry<?> resolvedEntry : resolvedEntries) {
@@ -87,6 +87,8 @@ public class EntryRemapper {
87 obfToDeobf.insert(resolvedEntry, deobfMapping); 87 obfToDeobf.insert(resolvedEntry, deobfMapping);
88 } 88 }
89 } 89 }
90
91 return true;
90 } 92 }
91 93
92 // A little bit of a hack to also map the getter method for record fields. 94 // A little bit of a hack to also map the getter method for record fields.
diff --git a/enigma/src/main/java/cuchaz/enigma/translation/mapping/EntryUtil.java b/enigma/src/main/java/cuchaz/enigma/translation/mapping/EntryUtil.java
index fb8ab631..9e6641be 100644
--- a/enigma/src/main/java/cuchaz/enigma/translation/mapping/EntryUtil.java
+++ b/enigma/src/main/java/cuchaz/enigma/translation/mapping/EntryUtil.java
@@ -1,17 +1,23 @@
1package cuchaz.enigma.translation.mapping; 1package cuchaz.enigma.translation.mapping;
2 2
3import org.jetbrains.annotations.NotNull; 3import org.jetbrains.annotations.NotNull;
4import org.jetbrains.annotations.Nullable;
4 5
6import cuchaz.enigma.EnigmaProject;
5import cuchaz.enigma.translation.representation.entry.Entry; 7import cuchaz.enigma.translation.representation.entry.Entry;
6import cuchaz.enigma.utils.validation.ValidationContext; 8import cuchaz.enigma.utils.validation.ValidationContext;
7 9
8public class EntryUtil { 10public class EntryUtil {
9 public static EntryMapping applyChange(ValidationContext vc, EntryRemapper remapper, EntryChange<?> change) { 11 public static EntryMapping applyChange(ValidationContext vc, @Nullable EnigmaProject project, EntryRemapper remapper, EntryChange<?> change) {
10 Entry<?> target = change.getTarget(); 12 Entry<?> target = change.getTarget();
11 EntryMapping prev = remapper.getDeobfMapping(target); 13 EntryMapping prev = remapper.getDeobfMapping(target);
12 EntryMapping mapping = EntryUtil.applyChange(prev, change); 14 EntryMapping mapping = EntryUtil.applyChange(prev, change);
13 15
14 remapper.putMapping(vc, target, mapping); 16 if (remapper.putMapping(vc, target, mapping)) {
17 if (project != null) {
18 project.onEntryChange(prev, change);
19 }
20 }
15 21
16 return mapping; 22 return mapping;
17 } 23 }
diff --git a/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/FieldEntry.java b/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/FieldEntry.java
index dba86448..90c256c1 100644
--- a/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/FieldEntry.java
+++ b/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/FieldEntry.java
@@ -58,6 +58,10 @@ public class FieldEntry extends ParentedEntry<ClassEntry> implements Comparable<
58 return new FieldEntry(parent, name, desc, null); 58 return new FieldEntry(parent, name, desc, null);
59 } 59 }
60 60
61 public FieldEntry withDesc(TypeDescriptor desc) {
62 return new FieldEntry(parent, name, desc, null);
63 }
64
61 @Override 65 @Override
62 public FieldEntry withParent(ClassEntry parent) { 66 public FieldEntry withParent(ClassEntry parent) {
63 return new FieldEntry(parent, this.name, this.desc, null); 67 return new FieldEntry(parent, this.name, this.desc, null);
diff --git a/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/MethodEntry.java b/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/MethodEntry.java
index d86f1564..da6751e1 100644
--- a/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/MethodEntry.java
+++ b/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/MethodEntry.java
@@ -69,6 +69,10 @@ public class MethodEntry extends ParentedEntry<ClassEntry> implements Comparable
69 return new MethodEntry(parent, name, descriptor, javadocs); 69 return new MethodEntry(parent, name, descriptor, javadocs);
70 } 70 }
71 71
72 public MethodEntry withDesc(MethodDescriptor descriptor) {
73 return new MethodEntry(parent, name, descriptor, javadocs);
74 }
75
72 @Override 76 @Override
73 public MethodEntry withParent(ClassEntry parent) { 77 public MethodEntry withParent(ClassEntry parent) {
74 return new MethodEntry(new ClassEntry(parent.getFullName()), name, descriptor, javadocs); 78 return new MethodEntry(new ClassEntry(parent.getFullName()), name, descriptor, javadocs);