diff options
| author | 2019-01-24 14:48:32 +0200 | |
|---|---|---|
| committer | 2019-01-24 13:48:32 +0100 | |
| commit | 00fcd0550fcdda621c2e4662f6ddd55ce673b931 (patch) | |
| tree | 6f9e4c24dbcc6d118fceec56adf7bf9d747a485c /src/main/java/cuchaz/enigma/gui/GuiController.java | |
| parent | mark as 0.13.0-SNAPSHOT for preliminary development (diff) | |
| download | enigma-fork-00fcd0550fcdda621c2e4662f6ddd55ce673b931.tar.gz enigma-fork-00fcd0550fcdda621c2e4662f6ddd55ce673b931.tar.xz enigma-fork-00fcd0550fcdda621c2e4662f6ddd55ce673b931.zip | |
[WIP] Mapping rework (#91)
* Move packages
* Mapping & entry refactor: first pass
* Fix deobf -> obf tree remapping
* Resolve various issues
* Give all entries the potential for parents and treat inner classes as children
* Deobf UI tree elements
* Tests pass
* Sort mapping output
* Fix delta tracking
* Index separation and first pass for #97
* Keep track of remapped jar index
* Fix child entries not being remapped
* Drop non-root entries
* Track dropped mappings
* Fix enigma mapping ordering
* EntryTreeNode interface
* Small tweaks
* Naive full index remap on rename
* Entries can resolve to more than one root entry
* Support alternative resolution strategies
* Bridge method resolution
* Tests pass
* Fix mappings being used where there are none
* Fix methods with different descriptors being considered unique. closes #89
Diffstat (limited to 'src/main/java/cuchaz/enigma/gui/GuiController.java')
| -rw-r--r-- | src/main/java/cuchaz/enigma/gui/GuiController.java | 209 |
1 files changed, 107 insertions, 102 deletions
diff --git a/src/main/java/cuchaz/enigma/gui/GuiController.java b/src/main/java/cuchaz/enigma/gui/GuiController.java index 69aefe5..06cb33e 100644 --- a/src/main/java/cuchaz/enigma/gui/GuiController.java +++ b/src/main/java/cuchaz/enigma/gui/GuiController.java | |||
| @@ -20,19 +20,25 @@ import cuchaz.enigma.analysis.*; | |||
| 20 | import cuchaz.enigma.api.EnigmaPlugin; | 20 | import cuchaz.enigma.api.EnigmaPlugin; |
| 21 | import cuchaz.enigma.config.Config; | 21 | import cuchaz.enigma.config.Config; |
| 22 | import cuchaz.enigma.gui.dialog.ProgressDialog; | 22 | import cuchaz.enigma.gui.dialog.ProgressDialog; |
| 23 | import cuchaz.enigma.mapping.*; | ||
| 24 | import cuchaz.enigma.mapping.entry.ClassEntry; | ||
| 25 | import cuchaz.enigma.mapping.entry.Entry; | ||
| 26 | import cuchaz.enigma.mapping.entry.FieldEntry; | ||
| 27 | import cuchaz.enigma.mapping.entry.MethodEntry; | ||
| 28 | import cuchaz.enigma.throwables.MappingParseException; | 23 | import cuchaz.enigma.throwables.MappingParseException; |
| 24 | import cuchaz.enigma.translation.Translator; | ||
| 25 | import cuchaz.enigma.translation.mapping.*; | ||
| 26 | import cuchaz.enigma.translation.mapping.serde.MappingFormat; | ||
| 27 | import cuchaz.enigma.translation.mapping.tree.EntryTree; | ||
| 28 | import cuchaz.enigma.translation.representation.entry.ClassEntry; | ||
| 29 | import cuchaz.enigma.translation.representation.entry.Entry; | ||
| 30 | import cuchaz.enigma.translation.representation.entry.FieldEntry; | ||
| 31 | import cuchaz.enigma.translation.representation.entry.MethodEntry; | ||
| 29 | import cuchaz.enigma.utils.ReadableToken; | 32 | import cuchaz.enigma.utils.ReadableToken; |
| 30 | 33 | ||
| 34 | import javax.annotation.Nullable; | ||
| 31 | import java.awt.event.ItemEvent; | 35 | import java.awt.event.ItemEvent; |
| 32 | import java.io.File; | 36 | import java.io.File; |
| 33 | import java.io.IOException; | 37 | import java.io.IOException; |
| 38 | import java.nio.file.Path; | ||
| 34 | import java.util.*; | 39 | import java.util.*; |
| 35 | import java.util.jar.JarFile; | 40 | import java.util.jar.JarFile; |
| 41 | import java.util.stream.Collectors; | ||
| 36 | 42 | ||
| 37 | public class GuiController { | 43 | public class GuiController { |
| 38 | 44 | ||
| @@ -40,27 +46,26 @@ public class GuiController { | |||
| 40 | private Gui gui; | 46 | private Gui gui; |
| 41 | private SourceIndex index; | 47 | private SourceIndex index; |
| 42 | private ClassEntry currentObfClass; | 48 | private ClassEntry currentObfClass; |
| 43 | private boolean isDirty; | 49 | private Deque<EntryReference<Entry<?>, Entry<?>>> referenceStack; |
| 44 | private Deque<EntryReference<Entry, Entry>> referenceStack; | 50 | |
| 51 | private Path loadedMappingPath; | ||
| 52 | private MappingFormat loadedMappingFormat; | ||
| 45 | 53 | ||
| 46 | public GuiController(Gui gui) { | 54 | public GuiController(Gui gui) { |
| 47 | this.gui = gui; | 55 | this.gui = gui; |
| 48 | this.deobfuscator = null; | 56 | this.deobfuscator = null; |
| 49 | this.index = null; | 57 | this.index = null; |
| 50 | this.currentObfClass = null; | 58 | this.currentObfClass = null; |
| 51 | this.isDirty = false; | ||
| 52 | this.referenceStack = Queues.newArrayDeque(); | 59 | this.referenceStack = Queues.newArrayDeque(); |
| 53 | } | 60 | } |
| 54 | 61 | ||
| 55 | public boolean isDirty() { | 62 | public boolean isDirty() { |
| 56 | return this.isDirty; | 63 | return deobfuscator.getMapper().isDirty(); |
| 57 | } | 64 | } |
| 58 | 65 | ||
| 59 | public void openJar(final JarFile jar) throws IOException { | 66 | public void openJar(final JarFile jar) throws IOException { |
| 60 | this.gui.onStartOpenJar("Loading JAR..."); | 67 | this.gui.onStartOpenJar("Loading JAR..."); |
| 61 | this.deobfuscator = new Deobfuscator(jar, (msg) -> { | 68 | this.deobfuscator = new Deobfuscator(jar, this.gui::onStartOpenJar); |
| 62 | this.gui.onStartOpenJar(msg); | ||
| 63 | }); | ||
| 64 | this.gui.onFinishOpenJar(jar.getName()); | 69 | this.gui.onFinishOpenJar(jar.getName()); |
| 65 | refreshClasses(); | 70 | refreshClasses(); |
| 66 | } | 71 | } |
| @@ -70,43 +75,37 @@ public class GuiController { | |||
| 70 | this.gui.onCloseJar(); | 75 | this.gui.onCloseJar(); |
| 71 | } | 76 | } |
| 72 | 77 | ||
| 73 | public void openEnigmaMappings(File file) throws IOException, MappingParseException { | 78 | public void openMappings(MappingFormat format, Path path) throws IOException, MappingParseException { |
| 74 | this.deobfuscator.setMappings(new MappingsEnigmaReader().read(file)); | 79 | EntryTree<EntryMapping> mappings = format.read(path); |
| 75 | this.isDirty = false; | 80 | deobfuscator.setMappings(mappings); |
| 76 | this.gui.setMappingsFile(file); | 81 | |
| 82 | gui.setMappingsFile(path); | ||
| 83 | loadedMappingFormat = format; | ||
| 84 | |||
| 77 | refreshClasses(); | 85 | refreshClasses(); |
| 78 | refreshCurrentClass(); | 86 | refreshCurrentClass(); |
| 79 | } | 87 | } |
| 80 | 88 | ||
| 81 | public void openTinyMappings(File file) throws IOException, MappingParseException { | 89 | public void saveMappings(Path path) { |
| 82 | this.deobfuscator.setMappings(new MappingsTinyReader().read(file)); | 90 | saveMappings(loadedMappingFormat, path); |
| 83 | this.isDirty = false; | ||
| 84 | this.gui.setMappingsFile(file); | ||
| 85 | refreshClasses(); | ||
| 86 | refreshCurrentClass(); | ||
| 87 | } | 91 | } |
| 88 | 92 | ||
| 89 | public void saveMappings(File file) throws IOException { | 93 | public void saveMappings(MappingFormat format, Path path) { |
| 90 | Mappings mappings = this.deobfuscator.getMappings(); | 94 | EntryRemapper mapper = deobfuscator.getMapper(); |
| 91 | switch (mappings.getOriginMappingFormat()) { | ||
| 92 | case SRG_FILE: | ||
| 93 | saveSRGMappings(file); | ||
| 94 | break; | ||
| 95 | default: | ||
| 96 | saveEnigmaMappings(file, Mappings.FormatType.ENIGMA_FILE != mappings.getOriginMappingFormat()); | ||
| 97 | break; | ||
| 98 | } | ||
| 99 | 95 | ||
| 100 | } | 96 | MappingDelta delta = mapper.takeMappingDelta(); |
| 97 | boolean saveAll = !path.equals(loadedMappingPath); | ||
| 101 | 98 | ||
| 102 | public void saveEnigmaMappings(File file, boolean isDirectoryFormat) throws IOException { | 99 | ProgressDialog.runInThread(this.gui.getFrame(), progress -> { |
| 103 | this.deobfuscator.getMappings().saveEnigmaMappings(file, isDirectoryFormat); | 100 | if (saveAll) { |
| 104 | this.isDirty = false; | 101 | format.write(mapper.getObfToDeobf(), path, progress); |
| 105 | } | 102 | } else { |
| 103 | format.write(mapper.getObfToDeobf(), delta, path, progress); | ||
| 104 | } | ||
| 105 | }); | ||
| 106 | 106 | ||
| 107 | public void saveSRGMappings(File file) throws IOException { | 107 | loadedMappingFormat = format; |
| 108 | this.deobfuscator.getMappings().saveSRGMappings(file); | 108 | loadedMappingPath = path; |
| 109 | this.isDirty = false; | ||
| 110 | } | 109 | } |
| 111 | 110 | ||
| 112 | public void closeMappings() { | 111 | public void closeMappings() { |
| @@ -116,11 +115,6 @@ public class GuiController { | |||
| 116 | refreshCurrentClass(); | 115 | refreshCurrentClass(); |
| 117 | } | 116 | } |
| 118 | 117 | ||
| 119 | public void rebuildMethodNames() { | ||
| 120 | ProgressDialog.runInThread(this.gui.getFrame(), progress -> this.deobfuscator.rebuildMethodNames(progress)); | ||
| 121 | this.isDirty = true; | ||
| 122 | } | ||
| 123 | |||
| 124 | public void exportSource(final File dirOut) { | 118 | public void exportSource(final File dirOut) { |
| 125 | ProgressDialog.runInThread(this.gui.getFrame(), progress -> this.deobfuscator.writeSources(dirOut, progress)); | 119 | ProgressDialog.runInThread(this.gui.getFrame(), progress -> this.deobfuscator.writeSources(dirOut, progress)); |
| 126 | } | 120 | } |
| @@ -136,7 +130,8 @@ public class GuiController { | |||
| 136 | return this.index.getReferenceToken(pos); | 130 | return this.index.getReferenceToken(pos); |
| 137 | } | 131 | } |
| 138 | 132 | ||
| 139 | public EntryReference<Entry, Entry> getDeobfReference(Token token) { | 133 | @Nullable |
| 134 | public EntryReference<Entry<?>, Entry<?>> getDeobfReference(Token token) { | ||
| 140 | if (this.index == null) { | 135 | if (this.index == null) { |
| 141 | return null; | 136 | return null; |
| 142 | } | 137 | } |
| @@ -148,44 +143,52 @@ public class GuiController { | |||
| 148 | return null; | 143 | return null; |
| 149 | } | 144 | } |
| 150 | return new ReadableToken( | 145 | return new ReadableToken( |
| 151 | this.index.getLineNumber(token.start), | 146 | this.index.getLineNumber(token.start), |
| 152 | this.index.getColumnNumber(token.start), | 147 | this.index.getColumnNumber(token.start), |
| 153 | this.index.getColumnNumber(token.end) | 148 | this.index.getColumnNumber(token.end) |
| 154 | ); | 149 | ); |
| 155 | } | 150 | } |
| 156 | 151 | ||
| 157 | public boolean entryHasDeobfuscatedName(Entry deobfEntry) { | 152 | public boolean entryHasDeobfuscatedName(Entry<?> deobfEntry) { |
| 158 | return this.deobfuscator.hasDeobfuscatedName(this.deobfuscator.obfuscateEntry(deobfEntry)); | 153 | EntryResolver resolver = this.deobfuscator.getMapper().getDeobfResolver(); |
| 154 | Entry<?> resolvedEntry = resolver.resolveFirstEntry(deobfEntry, ResolutionStrategy.RESOLVE_ROOT); | ||
| 155 | return this.deobfuscator.hasDeobfuscatedName(this.deobfuscator.getMapper().obfuscate(resolvedEntry)); | ||
| 159 | } | 156 | } |
| 160 | 157 | ||
| 161 | public boolean entryIsInJar(Entry deobfEntry) { | 158 | public boolean entryIsInJar(Entry<?> deobfEntry) { |
| 162 | return this.deobfuscator.isObfuscatedIdentifier(this.deobfuscator.obfuscateEntry(deobfEntry)); | 159 | if (deobfEntry == null) return false; |
| 160 | return this.deobfuscator.isObfuscatedIdentifier(this.deobfuscator.getMapper().obfuscate(deobfEntry)); | ||
| 163 | } | 161 | } |
| 164 | 162 | ||
| 165 | public boolean referenceIsRenameable(EntryReference<Entry, Entry> deobfReference) { | 163 | public boolean referenceIsRenameable(EntryReference<Entry<?>, Entry<?>> deobfReference) { |
| 166 | return this.deobfuscator.isRenameable(this.deobfuscator.obfuscateReference(deobfReference)); | 164 | if (deobfReference == null) return false; |
| 165 | return this.deobfuscator.isRenameable(this.deobfuscator.getMapper().obfuscate(deobfReference)); | ||
| 167 | } | 166 | } |
| 168 | 167 | ||
| 169 | public ClassInheritanceTreeNode getClassInheritance(ClassEntry deobfClassEntry) { | 168 | public ClassInheritanceTreeNode getClassInheritance(ClassEntry deobfClassEntry) { |
| 170 | ClassEntry obfClassEntry = this.deobfuscator.obfuscateEntry(deobfClassEntry); | 169 | ClassEntry obfClassEntry = this.deobfuscator.getMapper().obfuscate(deobfClassEntry); |
| 171 | ClassInheritanceTreeNode rootNode = this.deobfuscator.getJarIndex().getClassInheritance(this.deobfuscator.getTranslator(TranslationDirection.DEOBFUSCATING), obfClassEntry); | 170 | Translator translator = this.deobfuscator.getMapper().getDeobfuscator(); |
| 171 | ClassInheritanceTreeNode rootNode = this.deobfuscator.getIndexTreeBuilder().buildClassInheritance(translator, obfClassEntry); | ||
| 172 | return ClassInheritanceTreeNode.findNode(rootNode, obfClassEntry); | 172 | return ClassInheritanceTreeNode.findNode(rootNode, obfClassEntry); |
| 173 | } | 173 | } |
| 174 | 174 | ||
| 175 | public ClassImplementationsTreeNode getClassImplementations(ClassEntry deobfClassEntry) { | 175 | public ClassImplementationsTreeNode getClassImplementations(ClassEntry deobfClassEntry) { |
| 176 | ClassEntry obfClassEntry = this.deobfuscator.obfuscateEntry(deobfClassEntry); | 176 | ClassEntry obfClassEntry = this.deobfuscator.getMapper().obfuscate(deobfClassEntry); |
| 177 | return this.deobfuscator.getJarIndex().getClassImplementations(this.deobfuscator.getTranslator(TranslationDirection.DEOBFUSCATING), obfClassEntry); | 177 | Translator translator = this.deobfuscator.getMapper().getDeobfuscator(); |
| 178 | return this.deobfuscator.getIndexTreeBuilder().buildClassImplementations(translator, obfClassEntry); | ||
| 178 | } | 179 | } |
| 179 | 180 | ||
| 180 | public MethodInheritanceTreeNode getMethodInheritance(MethodEntry deobfMethodEntry) { | 181 | public MethodInheritanceTreeNode getMethodInheritance(MethodEntry deobfMethodEntry) { |
| 181 | MethodEntry obfMethodEntry = this.deobfuscator.obfuscateEntry(deobfMethodEntry); | 182 | MethodEntry obfMethodEntry = this.deobfuscator.getMapper().obfuscate(deobfMethodEntry); |
| 182 | MethodInheritanceTreeNode rootNode = this.deobfuscator.getJarIndex().getMethodInheritance(this.deobfuscator.getTranslator(TranslationDirection.DEOBFUSCATING), obfMethodEntry); | 183 | Translator translator = this.deobfuscator.getMapper().getDeobfuscator(); |
| 184 | MethodInheritanceTreeNode rootNode = this.deobfuscator.getIndexTreeBuilder().buildMethodInheritance(translator, obfMethodEntry); | ||
| 183 | return MethodInheritanceTreeNode.findNode(rootNode, obfMethodEntry); | 185 | return MethodInheritanceTreeNode.findNode(rootNode, obfMethodEntry); |
| 184 | } | 186 | } |
| 185 | 187 | ||
| 186 | public MethodImplementationsTreeNode getMethodImplementations(MethodEntry deobfMethodEntry) { | 188 | public MethodImplementationsTreeNode getMethodImplementations(MethodEntry deobfMethodEntry) { |
| 187 | MethodEntry obfMethodEntry = this.deobfuscator.obfuscateEntry(deobfMethodEntry); | 189 | MethodEntry obfMethodEntry = this.deobfuscator.getMapper().obfuscate(deobfMethodEntry); |
| 188 | List<MethodImplementationsTreeNode> rootNodes = this.deobfuscator.getJarIndex().getMethodImplementations(this.deobfuscator.getTranslator(TranslationDirection.DEOBFUSCATING), obfMethodEntry); | 190 | Translator translator = this.deobfuscator.getMapper().getDeobfuscator(); |
| 191 | List<MethodImplementationsTreeNode> rootNodes = this.deobfuscator.getIndexTreeBuilder().buildMethodImplementations(translator, obfMethodEntry); | ||
| 189 | if (rootNodes.isEmpty()) { | 192 | if (rootNodes.isEmpty()) { |
| 190 | return null; | 193 | return null; |
| 191 | } | 194 | } |
| @@ -196,34 +199,32 @@ public class GuiController { | |||
| 196 | } | 199 | } |
| 197 | 200 | ||
| 198 | public ClassReferenceTreeNode getClassReferences(ClassEntry deobfClassEntry) { | 201 | public ClassReferenceTreeNode getClassReferences(ClassEntry deobfClassEntry) { |
| 199 | ClassEntry obfClassEntry = this.deobfuscator.obfuscateEntry(deobfClassEntry); | 202 | ClassEntry obfClassEntry = this.deobfuscator.getMapper().obfuscate(deobfClassEntry); |
| 200 | ClassReferenceTreeNode rootNode = new ClassReferenceTreeNode(this.deobfuscator.getTranslator(TranslationDirection.DEOBFUSCATING), obfClassEntry); | 203 | Translator deobfuscator = this.deobfuscator.getMapper().getDeobfuscator(); |
| 204 | ClassReferenceTreeNode rootNode = new ClassReferenceTreeNode(deobfuscator, obfClassEntry); | ||
| 201 | rootNode.load(this.deobfuscator.getJarIndex(), true); | 205 | rootNode.load(this.deobfuscator.getJarIndex(), true); |
| 202 | return rootNode; | 206 | return rootNode; |
| 203 | } | 207 | } |
| 204 | 208 | ||
| 205 | public FieldReferenceTreeNode getFieldReferences(FieldEntry deobfFieldEntry) { | 209 | public FieldReferenceTreeNode getFieldReferences(FieldEntry deobfFieldEntry) { |
| 206 | FieldEntry obfFieldEntry = this.deobfuscator.obfuscateEntry(deobfFieldEntry); | 210 | FieldEntry obfFieldEntry = this.deobfuscator.getMapper().obfuscate(deobfFieldEntry); |
| 207 | FieldReferenceTreeNode rootNode = new FieldReferenceTreeNode(this.deobfuscator.getTranslator(TranslationDirection.DEOBFUSCATING), obfFieldEntry); | 211 | Translator translator = this.deobfuscator.getMapper().getDeobfuscator(); |
| 212 | FieldReferenceTreeNode rootNode = new FieldReferenceTreeNode(translator, obfFieldEntry); | ||
| 208 | rootNode.load(this.deobfuscator.getJarIndex(), true); | 213 | rootNode.load(this.deobfuscator.getJarIndex(), true); |
| 209 | return rootNode; | 214 | return rootNode; |
| 210 | } | 215 | } |
| 211 | 216 | ||
| 212 | public MethodReferenceTreeNode getMethodReferences(MethodEntry deobfMethodEntry, boolean recursive) { | 217 | public MethodReferenceTreeNode getMethodReferences(MethodEntry deobfMethodEntry, boolean recursive) { |
| 213 | MethodEntry obfMethodEntry = this.deobfuscator.obfuscateEntry(deobfMethodEntry); | 218 | MethodEntry obfMethodEntry = this.deobfuscator.getMapper().obfuscate(deobfMethodEntry); |
| 214 | MethodReferenceTreeNode rootNode = new MethodReferenceTreeNode(this.deobfuscator.getTranslator(TranslationDirection.DEOBFUSCATING), obfMethodEntry); | 219 | Translator translator = this.deobfuscator.getMapper().getDeobfuscator(); |
| 220 | MethodReferenceTreeNode rootNode = new MethodReferenceTreeNode(translator, obfMethodEntry); | ||
| 215 | rootNode.load(this.deobfuscator.getJarIndex(), true, recursive); | 221 | rootNode.load(this.deobfuscator.getJarIndex(), true, recursive); |
| 216 | return rootNode; | 222 | return rootNode; |
| 217 | } | 223 | } |
| 218 | 224 | ||
| 219 | public void rename(EntryReference<Entry, Entry> deobfReference, String newName) { | 225 | public void rename(EntryReference<Entry<?>, Entry<?>> deobfReference, String newName, boolean refreshClassTree) { |
| 220 | rename(deobfReference, newName, true, true); | 226 | EntryReference<Entry<?>, Entry<?>> obfReference = this.deobfuscator.getMapper().obfuscate(deobfReference); |
| 221 | } | 227 | this.deobfuscator.rename(obfReference.getNameableEntry(), newName); |
| 222 | |||
| 223 | public void rename(EntryReference<Entry, Entry> deobfReference, String newName, boolean refreshClassTree, boolean clearTranslationCache) { | ||
| 224 | EntryReference<Entry, Entry> obfReference = this.deobfuscator.obfuscateReference(deobfReference); | ||
| 225 | this.deobfuscator.rename(obfReference.getNameableEntry(), newName, clearTranslationCache); | ||
| 226 | this.isDirty = true; | ||
| 227 | 228 | ||
| 228 | if (refreshClassTree && deobfReference.entry instanceof ClassEntry && !((ClassEntry) deobfReference.entry).isInnerClass()) | 229 | if (refreshClassTree && deobfReference.entry instanceof ClassEntry && !((ClassEntry) deobfReference.entry).isInnerClass()) |
| 229 | this.gui.moveClassTree(deobfReference, newName); | 230 | this.gui.moveClassTree(deobfReference, newName); |
| @@ -231,39 +232,37 @@ public class GuiController { | |||
| 231 | 232 | ||
| 232 | } | 233 | } |
| 233 | 234 | ||
| 234 | public void removeMapping(EntryReference<Entry, Entry> deobfReference) { | 235 | public void removeMapping(EntryReference<Entry<?>, Entry<?>> deobfReference) { |
| 235 | EntryReference<Entry, Entry> obfReference = this.deobfuscator.obfuscateReference(deobfReference); | 236 | EntryReference<Entry<?>, Entry<?>> obfReference = this.deobfuscator.getMapper().obfuscate(deobfReference); |
| 236 | this.deobfuscator.removeMapping(obfReference.getNameableEntry()); | 237 | this.deobfuscator.removeMapping(obfReference.getNameableEntry()); |
| 237 | this.isDirty = true; | ||
| 238 | if (deobfReference.entry instanceof ClassEntry) | 238 | if (deobfReference.entry instanceof ClassEntry) |
| 239 | this.gui.moveClassTree(deobfReference, obfReference.entry.getName(), false, true); | 239 | this.gui.moveClassTree(deobfReference, obfReference.entry.getName(), false, true); |
| 240 | refreshCurrentClass(obfReference); | 240 | refreshCurrentClass(obfReference); |
| 241 | } | 241 | } |
| 242 | 242 | ||
| 243 | public void markAsDeobfuscated(EntryReference<Entry, Entry> deobfReference) { | 243 | public void markAsDeobfuscated(EntryReference<Entry<?>, Entry<?>> deobfReference) { |
| 244 | EntryReference<Entry, Entry> obfReference = this.deobfuscator.obfuscateReference(deobfReference); | 244 | EntryReference<Entry<?>, Entry<?>> obfReference = this.deobfuscator.getMapper().obfuscate(deobfReference); |
| 245 | this.deobfuscator.markAsDeobfuscated(obfReference.getNameableEntry()); | 245 | this.deobfuscator.markAsDeobfuscated(obfReference.getNameableEntry()); |
| 246 | this.isDirty = true; | ||
| 247 | if (deobfReference.entry instanceof ClassEntry && !((ClassEntry) deobfReference.entry).isInnerClass()) | 246 | if (deobfReference.entry instanceof ClassEntry && !((ClassEntry) deobfReference.entry).isInnerClass()) |
| 248 | this.gui.moveClassTree(deobfReference, obfReference.entry.getName(), true, false); | 247 | this.gui.moveClassTree(deobfReference, obfReference.entry.getName(), true, false); |
| 249 | refreshCurrentClass(obfReference); | 248 | refreshCurrentClass(obfReference); |
| 250 | } | 249 | } |
| 251 | 250 | ||
| 252 | public void openDeclaration(Entry deobfEntry) { | 251 | public void openDeclaration(Entry<?> deobfEntry) { |
| 253 | if (deobfEntry == null) { | 252 | if (deobfEntry == null) { |
| 254 | throw new IllegalArgumentException("Entry cannot be null!"); | 253 | throw new IllegalArgumentException("Entry cannot be null!"); |
| 255 | } | 254 | } |
| 256 | openReference(new EntryReference<>(deobfEntry, deobfEntry.getName())); | 255 | openReference(new EntryReference<>(deobfEntry, deobfEntry.getName())); |
| 257 | } | 256 | } |
| 258 | 257 | ||
| 259 | public void openReference(EntryReference<Entry, Entry> deobfReference) { | 258 | public void openReference(EntryReference<Entry<?>, Entry<?>> deobfReference) { |
| 260 | if (deobfReference == null) { | 259 | if (deobfReference == null) { |
| 261 | throw new IllegalArgumentException("Reference cannot be null!"); | 260 | throw new IllegalArgumentException("Reference cannot be null!"); |
| 262 | } | 261 | } |
| 263 | 262 | ||
| 264 | // get the reference target class | 263 | // get the reference target class |
| 265 | EntryReference<Entry, Entry> obfReference = this.deobfuscator.obfuscateReference(deobfReference); | 264 | EntryReference<Entry<?>, Entry<?>> obfReference = this.deobfuscator.getMapper().obfuscate(deobfReference); |
| 266 | ClassEntry obfClassEntry = obfReference.getLocationClassEntry().getOutermostClassEntry(); | 265 | ClassEntry obfClassEntry = obfReference.getLocationClassEntry(); |
| 267 | if (!this.deobfuscator.isObfuscatedIdentifier(obfClassEntry)) { | 266 | if (!this.deobfuscator.isObfuscatedIdentifier(obfClassEntry)) { |
| 268 | throw new IllegalArgumentException("Obfuscated class " + obfClassEntry + " was not found in the jar!"); | 267 | throw new IllegalArgumentException("Obfuscated class " + obfClassEntry + " was not found in the jar!"); |
| 269 | } | 268 | } |
| @@ -276,24 +275,30 @@ public class GuiController { | |||
| 276 | } | 275 | } |
| 277 | } | 276 | } |
| 278 | 277 | ||
| 279 | private void showReference(EntryReference<Entry, Entry> obfReference) { | 278 | private void showReference(EntryReference<Entry<?>, Entry<?>> obfReference) { |
| 280 | EntryReference<Entry, Entry> deobfReference = this.deobfuscator.deobfuscateReference(obfReference); | 279 | EntryRemapper mapper = this.deobfuscator.getMapper(); |
| 281 | Collection<Token> tokens = this.index.getReferenceTokens(deobfReference); | 280 | |
| 281 | Collection<Token> tokens = mapper.getObfResolver().resolveReference(obfReference, ResolutionStrategy.RESOLVE_ROOT) | ||
| 282 | .stream() | ||
| 283 | .map(mapper::deobfuscate) | ||
| 284 | .flatMap(reference -> index.getReferenceTokens(reference).stream()) | ||
| 285 | .collect(Collectors.toList()); | ||
| 286 | |||
| 282 | if (tokens.isEmpty()) { | 287 | if (tokens.isEmpty()) { |
| 283 | // DEBUG | 288 | // DEBUG |
| 284 | System.err.println(String.format("WARNING: no tokens found for %s in %s", deobfReference, this.currentObfClass)); | 289 | System.err.println(String.format("WARNING: no tokens found for %s in %s", tokens, this.currentObfClass)); |
| 285 | } else { | 290 | } else { |
| 286 | this.gui.showTokens(tokens); | 291 | this.gui.showTokens(tokens); |
| 287 | } | 292 | } |
| 288 | } | 293 | } |
| 289 | 294 | ||
| 290 | public void savePreviousReference(EntryReference<Entry, Entry> deobfReference) { | 295 | public void savePreviousReference(EntryReference<Entry<?>, Entry<?>> deobfReference) { |
| 291 | this.referenceStack.push(this.deobfuscator.obfuscateReference(deobfReference)); | 296 | this.referenceStack.push(this.deobfuscator.getMapper().obfuscate(deobfReference)); |
| 292 | } | 297 | } |
| 293 | 298 | ||
| 294 | public void openPreviousReference() { | 299 | public void openPreviousReference() { |
| 295 | if (hasPreviousLocation()) { | 300 | if (hasPreviousLocation()) { |
| 296 | openReference(this.deobfuscator.deobfuscateReference(this.referenceStack.pop())); | 301 | openReference(this.deobfuscator.getMapper().deobfuscate(this.referenceStack.pop())); |
| 297 | } | 302 | } |
| 298 | } | 303 | } |
| 299 | 304 | ||
| @@ -313,13 +318,13 @@ public class GuiController { | |||
| 313 | refreshCurrentClass(null); | 318 | refreshCurrentClass(null); |
| 314 | } | 319 | } |
| 315 | 320 | ||
| 316 | private void refreshCurrentClass(EntryReference<Entry, Entry> obfReference) { | 321 | private void refreshCurrentClass(EntryReference<Entry<?>, Entry<?>> obfReference) { |
| 317 | if (this.currentObfClass != null) { | 322 | if (this.currentObfClass != null) { |
| 318 | deobfuscate(this.currentObfClass, obfReference); | 323 | deobfuscate(this.currentObfClass, obfReference); |
| 319 | } | 324 | } |
| 320 | } | 325 | } |
| 321 | 326 | ||
| 322 | private void deobfuscate(final ClassEntry classEntry, final EntryReference<Entry, Entry> obfReference) { | 327 | private void deobfuscate(final ClassEntry classEntry, final EntryReference<Entry<?>, Entry<?>> obfReference) { |
| 323 | 328 | ||
| 324 | this.gui.setSource("(deobfuscating...)"); | 329 | this.gui.setSource("(deobfuscating...)"); |
| 325 | 330 | ||
| @@ -327,7 +332,7 @@ public class GuiController { | |||
| 327 | new Thread(() -> | 332 | new Thread(() -> |
| 328 | { | 333 | { |
| 329 | // decompile,deobfuscate the bytecode | 334 | // decompile,deobfuscate the bytecode |
| 330 | CompilationUnit sourceTree = deobfuscator.getSourceTree(classEntry.getClassName()); | 335 | CompilationUnit sourceTree = deobfuscator.getSourceTree(classEntry.getFullName()); |
| 331 | if (sourceTree == null) { | 336 | if (sourceTree == null) { |
| 332 | // decompilation of this class is not supported | 337 | // decompilation of this class is not supported |
| 333 | gui.setSource("Unable to find class: " + classEntry); | 338 | gui.setSource("Unable to find class: " + classEntry); |
| @@ -349,17 +354,18 @@ public class GuiController { | |||
| 349 | boolean remapped = false; | 354 | boolean remapped = false; |
| 350 | 355 | ||
| 351 | for (Token inToken : index.referenceTokens()) { | 356 | for (Token inToken : index.referenceTokens()) { |
| 352 | EntryReference<Entry, Entry> reference = index.getDeobfReference(inToken); | ||
| 353 | Token token = inToken.move(offset); | 357 | Token token = inToken.move(offset); |
| 354 | 358 | ||
| 359 | EntryReference<Entry<?>, Entry<?>> reference = index.getDeobfReference(inToken); | ||
| 355 | if (referenceIsRenameable(reference)) { | 360 | if (referenceIsRenameable(reference)) { |
| 356 | boolean added = false; | 361 | boolean added = false; |
| 357 | 362 | ||
| 358 | if (!entryHasDeobfuscatedName(reference.getNameableEntry())) { | 363 | if (!entryHasDeobfuscatedName(reference.getNameableEntry())) { |
| 359 | Entry obfEntry = deobfuscator.obfuscateEntry(reference.getNameableEntry()); | 364 | Entry<?> obfEntry = deobfuscator.getMapper().obfuscate(reference.getNameableEntry()); |
| 360 | if (obfEntry instanceof FieldEntry) { | 365 | if (obfEntry instanceof FieldEntry) { |
| 361 | for (EnigmaPlugin plugin : deobfuscator.getPlugins()) { | 366 | for (EnigmaPlugin plugin : deobfuscator.getPlugins()) { |
| 362 | String proposal = plugin.proposeFieldName(obfEntry.getClassName(), obfEntry.getName(), ((FieldEntry) obfEntry).getDesc().toString()); | 367 | String owner = obfEntry.getContainingClass().getFullName(); |
| 368 | String proposal = plugin.proposeFieldName(owner, obfEntry.getName(), ((FieldEntry) obfEntry).getDesc().toString()); | ||
| 363 | if (proposal != null) { | 369 | if (proposal != null) { |
| 364 | proposedTokens.add(token); | 370 | proposedTokens.add(token); |
| 365 | offset += token.getRenameOffset(proposal); | 371 | offset += token.getRenameOffset(proposal); |
| @@ -411,8 +417,7 @@ public class GuiController { | |||
| 411 | 417 | ||
| 412 | public void modifierChange(ItemEvent event) { | 418 | public void modifierChange(ItemEvent event) { |
| 413 | if (event.getStateChange() == ItemEvent.SELECTED) { | 419 | if (event.getStateChange() == ItemEvent.SELECTED) { |
| 414 | deobfuscator.changeModifier(gui.reference.entry, (Mappings.EntryModifier) event.getItem()); | 420 | deobfuscator.changeModifier(gui.reference.entry, (AccessModifier) event.getItem()); |
| 415 | this.isDirty = true; | ||
| 416 | refreshCurrentClass(); | 421 | refreshCurrentClass(); |
| 417 | } | 422 | } |
| 418 | } | 423 | } |