summaryrefslogtreecommitdiff
path: root/src/main/java/cuchaz/enigma/analysis/SourceIndex.java
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/analysis/SourceIndex.java
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/analysis/SourceIndex.java')
-rw-r--r--src/main/java/cuchaz/enigma/analysis/SourceIndex.java86
1 files changed, 52 insertions, 34 deletions
diff --git a/src/main/java/cuchaz/enigma/analysis/SourceIndex.java b/src/main/java/cuchaz/enigma/analysis/SourceIndex.java
index abdec92..ed12ce3 100644
--- a/src/main/java/cuchaz/enigma/analysis/SourceIndex.java
+++ b/src/main/java/cuchaz/enigma/analysis/SourceIndex.java
@@ -11,17 +11,24 @@
11 11
12package cuchaz.enigma.analysis; 12package cuchaz.enigma.analysis;
13 13
14import com.google.common.collect.*; 14import com.google.common.collect.HashMultimap;
15import com.google.common.collect.Lists;
16import com.google.common.collect.Maps;
17import com.google.common.collect.Multimap;
15import com.strobel.decompiler.languages.Region; 18import com.strobel.decompiler.languages.Region;
16import com.strobel.decompiler.languages.java.ast.AstNode; 19import com.strobel.decompiler.languages.java.ast.*;
17import com.strobel.decompiler.languages.java.ast.ConstructorDeclaration; 20import cuchaz.enigma.gui.SourceRemapper;
18import com.strobel.decompiler.languages.java.ast.Identifier; 21import cuchaz.enigma.translation.mapping.EntryResolver;
19import com.strobel.decompiler.languages.java.ast.TypeDeclaration; 22import cuchaz.enigma.translation.mapping.ResolutionStrategy;
20import cuchaz.enigma.translation.representation.entry.Entry; 23import cuchaz.enigma.translation.representation.entry.Entry;
21 24
22import javax.annotation.Nullable; 25import javax.annotation.Nullable;
23import java.util.*; 26import java.util.Collection;
27import java.util.List;
28import java.util.Map;
29import java.util.TreeMap;
24import java.util.regex.Pattern; 30import java.util.regex.Pattern;
31import java.util.stream.Collectors;
25 32
26public class SourceIndex { 33public class SourceIndex {
27 private static Pattern ANONYMOUS_INNER = Pattern.compile("\\$\\d+$"); 34 private static Pattern ANONYMOUS_INNER = Pattern.compile("\\$\\d+$");
@@ -46,6 +53,13 @@ public class SourceIndex {
46 calculateLineOffsets(); 53 calculateLineOffsets();
47 } 54 }
48 55
56 public static SourceIndex buildIndex(String sourceString, CompilationUnit sourceTree, boolean ignoreBadTokens) {
57 SourceIndex index = new SourceIndex(sourceString, ignoreBadTokens);
58 sourceTree.acceptVisitor(new SourceIndexVisitor(), index);
59
60 return index;
61 }
62
49 private void calculateLineOffsets() { 63 private void calculateLineOffsets() {
50 // count the lines 64 // count the lines
51 this.lineOffsets = Lists.newArrayList(); 65 this.lineOffsets = Lists.newArrayList();
@@ -57,32 +71,29 @@ public class SourceIndex {
57 } 71 }
58 } 72 }
59 73
60 public void remap(String source, Map<Token, Token> tokenMap) { 74 public SourceIndex remapTo(SourceRemapper.Result result) {
61 this.source = source; 75 SourceIndex remapped = new SourceIndex(result.getSource(), ignoreBadTokens);
62 calculateLineOffsets();
63 76
64 for (Entry<?> entry : Lists.newArrayList(declarationToToken.keySet())) { 77 for (Map.Entry<Entry<?>, Token> entry : declarationToToken.entrySet()) {
65 Token token = declarationToToken.get(entry); 78 remapped.declarationToToken.put(entry.getKey(), result.getRemappedToken(entry.getValue()));
66 declarationToToken.put(entry, tokenMap.getOrDefault(token, token));
67 } 79 }
68 80
69 for (EntryReference<Entry<?>, Entry<?>> ref : referenceToTokens.keySet()) { 81 for (Map.Entry<EntryReference<Entry<?>, Entry<?>>, Collection<Token>> entry : referenceToTokens.asMap().entrySet()) {
70 Collection<Token> oldTokens = referenceToTokens.get(ref); 82 EntryReference<Entry<?>, Entry<?>> reference = entry.getKey();
71 List<Token> newTokens = new ArrayList<>(oldTokens.size()); 83 Collection<Token> oldTokens = entry.getValue();
72 84
73 for (Token token : oldTokens) { 85 Collection<Token> newTokens = oldTokens.stream()
74 newTokens.add(tokenMap.getOrDefault(token, token)); 86 .map(result::getRemappedToken)
75 } 87 .collect(Collectors.toList());
76 88
77 referenceToTokens.replaceValues(ref, newTokens); 89 remapped.referenceToTokens.putAll(reference, newTokens);
78 } 90 }
79 91
80 TreeMap<Token, EntryReference<Entry<?>, Entry<?>>> tokenToReferenceCopy = new TreeMap<>(tokenToReference); 92 for (Map.Entry<Token, EntryReference<Entry<?>, Entry<?>>> entry : tokenToReference.entrySet()) {
81 93 remapped.tokenToReference.put(result.getRemappedToken(entry.getKey()), entry.getValue());
82 tokenToReference.clear();
83 for (Token token : tokenToReferenceCopy.keySet()) {
84 tokenToReference.put(tokenMap.getOrDefault(token, token), tokenToReferenceCopy.get(token));
85 } 94 }
95
96 return remapped;
86 } 97 }
87 98
88 public String getSource() { 99 public String getSource() {
@@ -164,20 +175,13 @@ public class SourceIndex {
164 } 175 }
165 176
166 @Nullable 177 @Nullable
167 public EntryReference<Entry<?>, Entry<?>> getDeobfReference(Token token) { 178 public EntryReference<Entry<?>, Entry<?>> getReference(Token token) {
168 if (token == null) { 179 if (token == null) {
169 return null; 180 return null;
170 } 181 }
171 return this.tokenToReference.get(token); 182 return this.tokenToReference.get(token);
172 } 183 }
173 184
174 public void replaceDeobfReference(Token token, EntryReference<Entry<?>, Entry<?>> newDeobfReference) {
175 EntryReference<Entry<?>, Entry<?>> oldDeobfReferences = this.tokenToReference.replace(token, newDeobfReference);
176
177 Collection<Token> tokens = this.referenceToTokens.removeAll(oldDeobfReferences);
178 this.referenceToTokens.putAll(newDeobfReference, tokens);
179 }
180
181 public Iterable<Token> referenceTokens() { 185 public Iterable<Token> referenceTokens() {
182 return this.tokenToReference.keySet(); 186 return this.tokenToReference.keySet();
183 } 187 }
@@ -190,8 +194,8 @@ public class SourceIndex {
190 return this.declarationToToken.keySet(); 194 return this.declarationToToken.keySet();
191 } 195 }
192 196
193 public Token getDeclarationToken(Entry<?> deobfEntry) { 197 public Token getDeclarationToken(Entry<?> entry) {
194 return this.declarationToToken.get(deobfEntry); 198 return this.declarationToToken.get(entry);
195 } 199 }
196 200
197 public int getLineNumber(int pos) { 201 public int getLineNumber(int pos) {
@@ -215,4 +219,18 @@ public class SourceIndex {
215 // line and col are 1-based 219 // line and col are 1-based
216 return this.lineOffsets.get(line - 1) + col - 1; 220 return this.lineOffsets.get(line - 1) + col - 1;
217 } 221 }
222
223 public void resolveReferences(EntryResolver resolver) {
224 // resolve all the classes in the source references
225 for (Token token : Lists.newArrayList(referenceToTokens.values())) {
226 EntryReference<Entry<?>, Entry<?>> reference = tokenToReference.get(token);
227 EntryReference<Entry<?>, Entry<?>> resolvedReference = resolver.resolveFirstReference(reference, ResolutionStrategy.RESOLVE_CLOSEST);
228
229 // replace the reference
230 tokenToReference.replace(token, resolvedReference);
231
232 Collection<Token> tokens = referenceToTokens.removeAll(reference);
233 referenceToTokens.putAll(resolvedReference, tokens);
234 }
235 }
218} 236}