diff options
| author | 2019-01-30 21:05:32 +0200 | |
|---|---|---|
| committer | 2019-01-30 21:05:32 +0200 | |
| commit | ba7a354efae7d49833c887cf147ac940c975a1fa (patch) | |
| tree | 02e14fda81dd5984e24f2df392c57c6e829fc875 /src/main/java/cuchaz/enigma/gui/DecompiledClassSource.java | |
| parent | Rewrite the Jenkinsfile to use the new declarative pipeline syntax, lets hope... (diff) | |
| download | enigma-fork-ba7a354efae7d49833c887cf147ac940c975a1fa.tar.gz enigma-fork-ba7a354efae7d49833c887cf147ac940c975a1fa.tar.xz enigma-fork-ba7a354efae7d49833c887cf147ac940c975a1fa.zip | |
Remap sources (#106)
* Source remapping beginnings
* Fix navigation to remapped classes
* Translate identifier info reference
* Remap local variables with default names in source
* Caching translator
* Fix lack of highlighting for first opened class
* Fix unicode variable names
* Unicode checker shouldn't be checking just alphanumeric
* Fix package tree being built from obf names
* Don't index `this` as method call for method::reference
* Apply proposed names
* Fix source export issues
* Replace unicode var names at bytecode level uniquely
* Drop imports from editor source
* Class selector fixes
* Delta keep track of base mappings to enable lookup of old names
* Optimize source remapping by remapping source with a StringBuffer instead of copying
* Bump version
Diffstat (limited to 'src/main/java/cuchaz/enigma/gui/DecompiledClassSource.java')
| -rw-r--r-- | src/main/java/cuchaz/enigma/gui/DecompiledClassSource.java | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/src/main/java/cuchaz/enigma/gui/DecompiledClassSource.java b/src/main/java/cuchaz/enigma/gui/DecompiledClassSource.java new file mode 100644 index 0000000..03f76c9 --- /dev/null +++ b/src/main/java/cuchaz/enigma/gui/DecompiledClassSource.java | |||
| @@ -0,0 +1,129 @@ | |||
| 1 | package cuchaz.enigma.gui; | ||
| 2 | |||
| 3 | import cuchaz.enigma.Deobfuscator; | ||
| 4 | import cuchaz.enigma.analysis.EntryReference; | ||
| 5 | import cuchaz.enigma.analysis.SourceIndex; | ||
| 6 | import cuchaz.enigma.analysis.Token; | ||
| 7 | import cuchaz.enigma.api.EnigmaPlugin; | ||
| 8 | import cuchaz.enigma.gui.highlight.TokenHighlightType; | ||
| 9 | import cuchaz.enigma.translation.LocalNameGenerator; | ||
| 10 | import cuchaz.enigma.translation.Translator; | ||
| 11 | import cuchaz.enigma.translation.representation.TypeDescriptor; | ||
| 12 | import cuchaz.enigma.translation.representation.entry.ClassEntry; | ||
| 13 | import cuchaz.enigma.translation.representation.entry.Entry; | ||
| 14 | import cuchaz.enigma.translation.representation.entry.FieldEntry; | ||
| 15 | import cuchaz.enigma.translation.representation.entry.LocalVariableDefEntry; | ||
| 16 | |||
| 17 | import javax.annotation.Nullable; | ||
| 18 | import java.util.*; | ||
| 19 | |||
| 20 | public class DecompiledClassSource { | ||
| 21 | private final ClassEntry classEntry; | ||
| 22 | private final Deobfuscator deobfuscator; | ||
| 23 | |||
| 24 | private final SourceIndex obfuscatedIndex; | ||
| 25 | private SourceIndex remappedIndex; | ||
| 26 | |||
| 27 | private final Map<TokenHighlightType, Collection<Token>> highlightedTokens = new EnumMap<>(TokenHighlightType.class); | ||
| 28 | |||
| 29 | public DecompiledClassSource(ClassEntry classEntry, Deobfuscator deobfuscator, SourceIndex index) { | ||
| 30 | this.classEntry = classEntry; | ||
| 31 | this.deobfuscator = deobfuscator; | ||
| 32 | this.obfuscatedIndex = index; | ||
| 33 | this.remappedIndex = index; | ||
| 34 | } | ||
| 35 | |||
| 36 | public void remapSource(Translator translator) { | ||
| 37 | highlightedTokens.clear(); | ||
| 38 | |||
| 39 | SourceRemapper remapper = new SourceRemapper(obfuscatedIndex.getSource(), obfuscatedIndex.referenceTokens()); | ||
| 40 | |||
| 41 | SourceRemapper.Result remapResult = remapper.remap((token, movedToken) -> remapToken(token, movedToken, translator)); | ||
| 42 | remappedIndex = obfuscatedIndex.remapTo(remapResult); | ||
| 43 | } | ||
| 44 | |||
| 45 | private String remapToken(Token token, Token movedToken, Translator translator) { | ||
| 46 | EntryReference<Entry<?>, Entry<?>> reference = obfuscatedIndex.getReference(token); | ||
| 47 | |||
| 48 | if (deobfuscator.isRenamable(reference)) { | ||
| 49 | Entry<?> entry = reference.getNameableEntry(); | ||
| 50 | Entry<?> translatedEntry = translator.translate(entry); | ||
| 51 | |||
| 52 | if (isDeobfuscated(entry, translatedEntry)) { | ||
| 53 | highlightToken(movedToken, TokenHighlightType.DEOBFUSCATED); | ||
| 54 | return translatedEntry.getSourceRemapName(); | ||
| 55 | } else { | ||
| 56 | String proposedName = proposeName(entry); | ||
| 57 | if (proposedName != null) { | ||
| 58 | highlightToken(movedToken, TokenHighlightType.PROPOSED); | ||
| 59 | return proposedName; | ||
| 60 | } | ||
| 61 | |||
| 62 | highlightToken(movedToken, TokenHighlightType.OBFUSCATED); | ||
| 63 | |||
| 64 | String defaultName = generateDefaultName(translatedEntry); | ||
| 65 | if (defaultName != null) { | ||
| 66 | return defaultName; | ||
| 67 | } | ||
| 68 | } | ||
| 69 | } | ||
| 70 | |||
| 71 | return null; | ||
| 72 | } | ||
| 73 | |||
| 74 | @Nullable | ||
| 75 | private String proposeName(Entry<?> entry) { | ||
| 76 | if (entry instanceof FieldEntry) { | ||
| 77 | for (EnigmaPlugin plugin : deobfuscator.getPlugins()) { | ||
| 78 | String owner = entry.getContainingClass().getFullName(); | ||
| 79 | String proposal = plugin.proposeFieldName(owner, entry.getName(), ((FieldEntry) entry).getDesc().toString()); | ||
| 80 | if (proposal != null) { | ||
| 81 | return proposal; | ||
| 82 | } | ||
| 83 | } | ||
| 84 | } | ||
| 85 | return null; | ||
| 86 | } | ||
| 87 | |||
| 88 | @Nullable | ||
| 89 | private String generateDefaultName(Entry<?> entry) { | ||
| 90 | if (entry instanceof LocalVariableDefEntry) { | ||
| 91 | LocalVariableDefEntry localVariable = (LocalVariableDefEntry) entry; | ||
| 92 | |||
| 93 | int index = localVariable.getIndex(); | ||
| 94 | if (localVariable.isArgument()) { | ||
| 95 | List<TypeDescriptor> arguments = localVariable.getParent().getDesc().getArgumentDescs(); | ||
| 96 | return LocalNameGenerator.generateArgumentName(index, localVariable.getDesc(), arguments); | ||
| 97 | } else { | ||
| 98 | return LocalNameGenerator.generateLocalVariableName(index, localVariable.getDesc()); | ||
| 99 | } | ||
| 100 | } | ||
| 101 | |||
| 102 | return null; | ||
| 103 | } | ||
| 104 | |||
| 105 | private boolean isDeobfuscated(Entry<?> entry, Entry<?> translatedEntry) { | ||
| 106 | return !entry.getName().equals(translatedEntry.getName()); | ||
| 107 | } | ||
| 108 | |||
| 109 | public ClassEntry getEntry() { | ||
| 110 | return classEntry; | ||
| 111 | } | ||
| 112 | |||
| 113 | public SourceIndex getIndex() { | ||
| 114 | return remappedIndex; | ||
| 115 | } | ||
| 116 | |||
| 117 | public Map<TokenHighlightType, Collection<Token>> getHighlightedTokens() { | ||
| 118 | return highlightedTokens; | ||
| 119 | } | ||
| 120 | |||
| 121 | private void highlightToken(Token token, TokenHighlightType highlightType) { | ||
| 122 | highlightedTokens.computeIfAbsent(highlightType, t -> new ArrayList<>()).add(token); | ||
| 123 | } | ||
| 124 | |||
| 125 | @Override | ||
| 126 | public String toString() { | ||
| 127 | return remappedIndex.getSource(); | ||
| 128 | } | ||
| 129 | } | ||