summaryrefslogtreecommitdiff
path: root/src/main/java/cuchaz/enigma/analysis
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/cuchaz/enigma/analysis')
-rw-r--r--src/main/java/cuchaz/enigma/analysis/DropImportAstTransform.java33
-rw-r--r--src/main/java/cuchaz/enigma/analysis/ParsedJar.java34
-rw-r--r--src/main/java/cuchaz/enigma/analysis/SourceIndex.java86
-rw-r--r--src/main/java/cuchaz/enigma/analysis/SourceIndexClassVisitor.java14
-rw-r--r--src/main/java/cuchaz/enigma/analysis/SourceIndexMethodVisitor.java64
-rw-r--r--src/main/java/cuchaz/enigma/analysis/SourceIndexVisitor.java9
-rw-r--r--src/main/java/cuchaz/enigma/analysis/Token.java6
-rw-r--r--src/main/java/cuchaz/enigma/analysis/index/BridgeMethodIndex.java16
-rw-r--r--src/main/java/cuchaz/enigma/analysis/index/EntryIndex.java20
-rw-r--r--src/main/java/cuchaz/enigma/analysis/index/InheritanceIndex.java18
-rw-r--r--src/main/java/cuchaz/enigma/analysis/index/JarIndex.java22
-rw-r--r--src/main/java/cuchaz/enigma/analysis/index/RemappableIndex.java9
12 files changed, 147 insertions, 184 deletions
diff --git a/src/main/java/cuchaz/enigma/analysis/DropImportAstTransform.java b/src/main/java/cuchaz/enigma/analysis/DropImportAstTransform.java
new file mode 100644
index 0000000..991e91d
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/analysis/DropImportAstTransform.java
@@ -0,0 +1,33 @@
1package cuchaz.enigma.analysis;
2
3import com.strobel.decompiler.languages.java.ast.AstNode;
4import com.strobel.decompiler.languages.java.ast.DepthFirstAstVisitor;
5import com.strobel.decompiler.languages.java.ast.ImportDeclaration;
6import com.strobel.decompiler.languages.java.ast.PackageDeclaration;
7import com.strobel.decompiler.languages.java.ast.transforms.IAstTransform;
8
9public final class DropImportAstTransform implements IAstTransform {
10 public static final DropImportAstTransform INSTANCE = new DropImportAstTransform();
11
12 private DropImportAstTransform() {
13 }
14
15 @Override
16 public void run(AstNode compilationUnit) {
17 compilationUnit.acceptVisitor(new Visitor(), null);
18 }
19
20 static class Visitor extends DepthFirstAstVisitor<Void, Void> {
21 @Override
22 public Void visitPackageDeclaration(PackageDeclaration node, Void data) {
23 node.remove();
24 return null;
25 }
26
27 @Override
28 public Void visitImportDeclaration(ImportDeclaration node, Void data) {
29 node.remove();
30 return null;
31 }
32 }
33}
diff --git a/src/main/java/cuchaz/enigma/analysis/ParsedJar.java b/src/main/java/cuchaz/enigma/analysis/ParsedJar.java
index ad3aceb..ddcda3e 100644
--- a/src/main/java/cuchaz/enigma/analysis/ParsedJar.java
+++ b/src/main/java/cuchaz/enigma/analysis/ParsedJar.java
@@ -12,9 +12,12 @@
12package cuchaz.enigma.analysis; 12package cuchaz.enigma.analysis;
13 13
14import com.google.common.io.ByteStreams; 14import com.google.common.io.ByteStreams;
15import cuchaz.enigma.CompiledSource;
16import cuchaz.enigma.bytecode.translators.LocalVariableFixVisitor;
15import cuchaz.enigma.translation.representation.entry.ClassEntry; 17import cuchaz.enigma.translation.representation.entry.ClassEntry;
16import org.objectweb.asm.ClassReader; 18import org.objectweb.asm.ClassReader;
17import org.objectweb.asm.ClassVisitor; 19import org.objectweb.asm.ClassVisitor;
20import org.objectweb.asm.Opcodes;
18import org.objectweb.asm.tree.ClassNode; 21import org.objectweb.asm.tree.ClassNode;
19 22
20import javax.annotation.Nullable; 23import javax.annotation.Nullable;
@@ -28,12 +31,12 @@ import java.util.jar.JarEntry;
28import java.util.jar.JarFile; 31import java.util.jar.JarFile;
29import java.util.jar.JarInputStream; 32import java.util.jar.JarInputStream;
30 33
31public class ParsedJar { 34public class ParsedJar implements CompiledSource {
32 private final Map<String, byte[]> classBytes; 35 private final Map<String, byte[]> classBytes;
33 private final Map<String, ClassNode> nodeCache = new HashMap<>(); 36 private final Map<String, ClassNode> nodeCache = new HashMap<>();
34 37
35 public ParsedJar(JarFile jar) throws IOException { 38 public ParsedJar(JarFile jar) throws IOException {
36 Map<String, byte[]> uClassBytes = new LinkedHashMap<>();; 39 Map<String, byte[]> uClassBytes = new LinkedHashMap<>();
37 try { 40 try {
38 // get the jar entries that correspond to classes 41 // get the jar entries that correspond to classes
39 Enumeration<JarEntry> entries = jar.entries(); 42 Enumeration<JarEntry> entries = jar.entries();
@@ -93,29 +96,34 @@ public class ParsedJar {
93 return classBytes.size(); 96 return classBytes.size();
94 } 97 }
95 98
96 public List<ClassEntry> getClassEntries() {
97 List<ClassEntry> entries = new ArrayList<>(classBytes.size());
98 for (String s : classBytes.keySet()) {
99 entries.add(new ClassEntry(s));
100 }
101 return entries;
102 }
103
104 @Nullable 99 @Nullable
100 @Override
105 public ClassNode getClassNode(String name) { 101 public ClassNode getClassNode(String name) {
106 return nodeCache.computeIfAbsent(name, (n) -> { 102 return nodeCache.computeIfAbsent(name, (n) -> {
107 byte[] bytes = classBytes.get(name); 103 byte[] bytes = classBytes.get(name);
108 if (bytes == null) { 104 if (bytes == null) {
109 return null; 105 return null;
110 } 106 }
107
111 ClassReader reader = new ClassReader(bytes); 108 ClassReader reader = new ClassReader(bytes);
112 ClassNode node = new ClassNode(); 109 ClassNode node = new ClassNode();
113 reader.accept(node, 0); 110
111 LocalVariableFixVisitor visitor = new LocalVariableFixVisitor(Opcodes.ASM5, node);
112 reader.accept(visitor, 0);
113
114 return node; 114 return node;
115 }); 115 });
116 } 116 }
117 117
118 public Map<String, byte[]> getClassDataMap() { 118 public List<ClassEntry> getClassEntries() {
119 List<ClassEntry> entries = new ArrayList<>(classBytes.size());
120 for (String s : classBytes.keySet()) {
121 entries.add(new ClassEntry(s));
122 }
123 return entries;
124 }
125
126 public Map<String, byte[]> getClassDataMap() {
119 return classBytes; 127 return classBytes;
120 } 128 }
121} 129}
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}
diff --git a/src/main/java/cuchaz/enigma/analysis/SourceIndexClassVisitor.java b/src/main/java/cuchaz/enigma/analysis/SourceIndexClassVisitor.java
index 486603c..a4fe9ee 100644
--- a/src/main/java/cuchaz/enigma/analysis/SourceIndexClassVisitor.java
+++ b/src/main/java/cuchaz/enigma/analysis/SourceIndexClassVisitor.java
@@ -18,21 +18,17 @@ import com.strobel.assembler.metadata.TypeReference;
18import com.strobel.decompiler.languages.TextLocation; 18import com.strobel.decompiler.languages.TextLocation;
19import com.strobel.decompiler.languages.java.ast.*; 19import com.strobel.decompiler.languages.java.ast.*;
20import cuchaz.enigma.translation.representation.ProcyonEntryFactory; 20import cuchaz.enigma.translation.representation.ProcyonEntryFactory;
21import cuchaz.enigma.translation.representation.ReferencedEntryPool;
22import cuchaz.enigma.translation.representation.entry.ClassDefEntry; 21import cuchaz.enigma.translation.representation.entry.ClassDefEntry;
23import cuchaz.enigma.translation.representation.entry.ClassEntry; 22import cuchaz.enigma.translation.representation.entry.ClassEntry;
24import cuchaz.enigma.translation.representation.entry.FieldDefEntry; 23import cuchaz.enigma.translation.representation.entry.FieldDefEntry;
25import cuchaz.enigma.translation.representation.entry.MethodDefEntry; 24import cuchaz.enigma.translation.representation.entry.MethodDefEntry;
26 25
27public class SourceIndexClassVisitor extends SourceIndexVisitor { 26public class SourceIndexClassVisitor extends SourceIndexVisitor {
28 private final ReferencedEntryPool entryPool;
29 private final ProcyonEntryFactory entryFactory; 27 private final ProcyonEntryFactory entryFactory;
30 private ClassDefEntry classEntry; 28 private ClassDefEntry classEntry;
31 29
32 public SourceIndexClassVisitor(ReferencedEntryPool entryPool, ClassDefEntry classEntry) { 30 public SourceIndexClassVisitor(ClassDefEntry classEntry) {
33 super(entryPool); 31 this.entryFactory = new ProcyonEntryFactory();
34 this.entryPool = entryPool;
35 this.entryFactory = new ProcyonEntryFactory(entryPool);
36 this.classEntry = classEntry; 32 this.classEntry = classEntry;
37 } 33 }
38 34
@@ -44,7 +40,7 @@ public class SourceIndexClassVisitor extends SourceIndexVisitor {
44 if (!classEntry.equals(this.classEntry)) { 40 if (!classEntry.equals(this.classEntry)) {
45 // it's a subtype, recurse 41 // it's a subtype, recurse
46 index.addDeclaration(node.getNameToken(), classEntry); 42 index.addDeclaration(node.getNameToken(), classEntry);
47 return node.acceptVisitor(new SourceIndexClassVisitor(entryPool, classEntry), index); 43 return node.acceptVisitor(new SourceIndexClassVisitor(classEntry), index);
48 } 44 }
49 45
50 return recurse(node, index); 46 return recurse(node, index);
@@ -71,7 +67,7 @@ public class SourceIndexClassVisitor extends SourceIndexVisitor {
71 tokenNode = node.getModifiers().firstOrNullObject(); 67 tokenNode = node.getModifiers().firstOrNullObject();
72 } 68 }
73 index.addDeclaration(tokenNode, methodEntry); 69 index.addDeclaration(tokenNode, methodEntry);
74 return node.acceptVisitor(new SourceIndexMethodVisitor(entryPool, methodEntry), index); 70 return node.acceptVisitor(new SourceIndexMethodVisitor(methodEntry), index);
75 } 71 }
76 72
77 @Override 73 @Override
@@ -79,7 +75,7 @@ public class SourceIndexClassVisitor extends SourceIndexVisitor {
79 MethodDefinition def = node.getUserData(Keys.METHOD_DEFINITION); 75 MethodDefinition def = node.getUserData(Keys.METHOD_DEFINITION);
80 MethodDefEntry methodEntry = entryFactory.getMethodDefEntry(def); 76 MethodDefEntry methodEntry = entryFactory.getMethodDefEntry(def);
81 index.addDeclaration(node.getNameToken(), methodEntry); 77 index.addDeclaration(node.getNameToken(), methodEntry);
82 return node.acceptVisitor(new SourceIndexMethodVisitor(entryPool, methodEntry), index); 78 return node.acceptVisitor(new SourceIndexMethodVisitor(methodEntry), index);
83 } 79 }
84 80
85 @Override 81 @Override
diff --git a/src/main/java/cuchaz/enigma/analysis/SourceIndexMethodVisitor.java b/src/main/java/cuchaz/enigma/analysis/SourceIndexMethodVisitor.java
index 73db28f..c4785b6 100644
--- a/src/main/java/cuchaz/enigma/analysis/SourceIndexMethodVisitor.java
+++ b/src/main/java/cuchaz/enigma/analysis/SourceIndexMethodVisitor.java
@@ -17,8 +17,8 @@ import com.strobel.assembler.metadata.*;
17import com.strobel.decompiler.ast.Variable; 17import com.strobel.decompiler.ast.Variable;
18import com.strobel.decompiler.languages.TextLocation; 18import com.strobel.decompiler.languages.TextLocation;
19import com.strobel.decompiler.languages.java.ast.*; 19import com.strobel.decompiler.languages.java.ast.*;
20import cuchaz.enigma.translation.representation.MethodDescriptor;
20import cuchaz.enigma.translation.representation.TypeDescriptor; 21import cuchaz.enigma.translation.representation.TypeDescriptor;
21import cuchaz.enigma.translation.representation.*;
22import cuchaz.enigma.translation.representation.entry.*; 22import cuchaz.enigma.translation.representation.entry.*;
23 23
24import java.lang.Error; 24import java.lang.Error;
@@ -26,16 +26,12 @@ import java.util.HashMap;
26import java.util.Map; 26import java.util.Map;
27 27
28public class SourceIndexMethodVisitor extends SourceIndexVisitor { 28public class SourceIndexMethodVisitor extends SourceIndexVisitor {
29 private final ReferencedEntryPool entryPool;
30
31 private final MethodDefEntry methodEntry; 29 private final MethodDefEntry methodEntry;
32 30
33 private Multimap<String, Identifier> unmatchedIdentifier = HashMultimap.create(); 31 private Multimap<String, Identifier> unmatchedIdentifier = HashMultimap.create();
34 private Map<String, Entry<?>> identifierEntryCache = new HashMap<>(); 32 private Map<String, Entry<?>> identifierEntryCache = new HashMap<>();
35 33
36 public SourceIndexMethodVisitor(ReferencedEntryPool entryPool, MethodDefEntry methodEntry) { 34 public SourceIndexMethodVisitor(MethodDefEntry methodEntry) {
37 super(entryPool);
38 this.entryPool = entryPool;
39 this.methodEntry = methodEntry; 35 this.methodEntry = methodEntry;
40 } 36 }
41 37
@@ -44,10 +40,10 @@ public class SourceIndexMethodVisitor extends SourceIndexVisitor {
44 MemberReference ref = node.getUserData(Keys.MEMBER_REFERENCE); 40 MemberReference ref = node.getUserData(Keys.MEMBER_REFERENCE);
45 41
46 // get the behavior entry 42 // get the behavior entry
47 ClassEntry classEntry = entryPool.getClass(ref.getDeclaringType().getInternalName()); 43 ClassEntry classEntry = new ClassEntry(ref.getDeclaringType().getInternalName());
48 MethodEntry methodEntry = null; 44 MethodEntry methodEntry = null;
49 if (ref instanceof MethodReference) { 45 if (ref instanceof MethodReference) {
50 methodEntry = entryPool.getMethod(classEntry, ref.getName(), ref.getErasedSignature()); 46 methodEntry = new MethodEntry(classEntry, ref.getName(), new MethodDescriptor(ref.getErasedSignature()));
51 } 47 }
52 if (methodEntry != null) { 48 if (methodEntry != null) {
53 // get the node for the token 49 // get the node for the token
@@ -80,11 +76,8 @@ public class SourceIndexMethodVisitor extends SourceIndexVisitor {
80 throw new Error("Expected a field here! got " + ref); 76 throw new Error("Expected a field here! got " + ref);
81 } 77 }
82 78
83 ClassEntry classEntry = entryPool.getClass(ref.getDeclaringType().getInternalName()); 79 ClassEntry classEntry = new ClassEntry(ref.getDeclaringType().getInternalName());
84 FieldEntry fieldEntry = entryPool.getField(classEntry, ref.getName(), new TypeDescriptor(erasedSignature)); 80 FieldEntry fieldEntry = new FieldEntry(classEntry, ref.getName(), new TypeDescriptor(erasedSignature));
85 if (fieldEntry == null) {
86 throw new Error("Failed to find field " + ref.getName() + " on " + classEntry.getFullName());
87 }
88 index.addReference(node.getMemberNameToken(), fieldEntry, this.methodEntry); 81 index.addReference(node.getMemberNameToken(), fieldEntry, this.methodEntry);
89 } 82 }
90 83
@@ -95,7 +88,7 @@ public class SourceIndexMethodVisitor extends SourceIndexVisitor {
95 public Void visitSimpleType(SimpleType node, SourceIndex index) { 88 public Void visitSimpleType(SimpleType node, SourceIndex index) {
96 TypeReference ref = node.getUserData(Keys.TYPE_REFERENCE); 89 TypeReference ref = node.getUserData(Keys.TYPE_REFERENCE);
97 if (node.getIdentifierToken().getStartLocation() != TextLocation.EMPTY) { 90 if (node.getIdentifierToken().getStartLocation() != TextLocation.EMPTY) {
98 ClassEntry classEntry = entryPool.getClass(ref.getInternalName()); 91 ClassEntry classEntry = new ClassEntry(ref.getInternalName());
99 index.addReference(node.getIdentifierToken(), classEntry, this.methodEntry); 92 index.addReference(node.getIdentifierToken(), classEntry, this.methodEntry);
100 } 93 }
101 94
@@ -108,7 +101,8 @@ public class SourceIndexMethodVisitor extends SourceIndexVisitor {
108 int parameterIndex = def.getSlot(); 101 int parameterIndex = def.getSlot();
109 102
110 if (parameterIndex >= 0) { 103 if (parameterIndex >= 0) {
111 LocalVariableEntry localVariableEntry = new LocalVariableEntry(methodEntry, parameterIndex, node.getName(), true); 104 TypeDescriptor parameterType = TypeDescriptor.parse(def.getParameterType());
105 LocalVariableDefEntry localVariableEntry = new LocalVariableDefEntry(methodEntry, parameterIndex, node.getName(), true, parameterType);
112 Identifier identifier = node.getNameToken(); 106 Identifier identifier = node.getNameToken();
113 // cache the argument entry and the identifier 107 // cache the argument entry and the identifier
114 identifierEntryCache.put(identifier.getName(), localVariableEntry); 108 identifierEntryCache.put(identifier.getName(), localVariableEntry);
@@ -122,11 +116,8 @@ public class SourceIndexMethodVisitor extends SourceIndexVisitor {
122 public Void visitIdentifierExpression(IdentifierExpression node, SourceIndex index) { 116 public Void visitIdentifierExpression(IdentifierExpression node, SourceIndex index) {
123 MemberReference ref = node.getUserData(Keys.MEMBER_REFERENCE); 117 MemberReference ref = node.getUserData(Keys.MEMBER_REFERENCE);
124 if (ref != null) { 118 if (ref != null) {
125 ClassEntry classEntry = entryPool.getClass(ref.getDeclaringType().getInternalName()); 119 ClassEntry classEntry = new ClassEntry(ref.getDeclaringType().getInternalName());
126 FieldEntry fieldEntry = entryPool.getField(classEntry, ref.getName(), new TypeDescriptor(ref.getErasedSignature())); 120 FieldEntry fieldEntry = new FieldEntry(classEntry, ref.getName(), new TypeDescriptor(ref.getErasedSignature()));
127 if (fieldEntry == null) {
128 throw new Error("Failed to find field " + ref.getName() + " on " + classEntry.getFullName());
129 }
130 index.addReference(node.getIdentifierToken(), fieldEntry, this.methodEntry); 121 index.addReference(node.getIdentifierToken(), fieldEntry, this.methodEntry);
131 } else 122 } else
132 this.checkIdentifier(node, index); 123 this.checkIdentifier(node, index);
@@ -154,13 +145,11 @@ public class SourceIndexMethodVisitor extends SourceIndexVisitor {
154 @Override 145 @Override
155 public Void visitObjectCreationExpression(ObjectCreationExpression node, SourceIndex index) { 146 public Void visitObjectCreationExpression(ObjectCreationExpression node, SourceIndex index) {
156 MemberReference ref = node.getUserData(Keys.MEMBER_REFERENCE); 147 MemberReference ref = node.getUserData(Keys.MEMBER_REFERENCE);
157 if (ref != null) { 148 if (ref != null && node.getType() instanceof SimpleType) {
158 ClassEntry classEntry = entryPool.getClass(ref.getDeclaringType().getInternalName()); 149 SimpleType simpleTypeNode = (SimpleType) node.getType();
159 MethodEntry constructorEntry = entryPool.getMethod(classEntry, "<init>", ref.getErasedSignature()); 150 ClassEntry classEntry = new ClassEntry(ref.getDeclaringType().getInternalName());
160 if (node.getType() instanceof SimpleType) { 151 MethodEntry constructorEntry = new MethodEntry(classEntry, "<init>", new MethodDescriptor(ref.getErasedSignature()));
161 SimpleType simpleTypeNode = (SimpleType) node.getType(); 152 index.addReference(simpleTypeNode.getIdentifierToken(), constructorEntry, this.methodEntry);
162 index.addReference(simpleTypeNode.getIdentifierToken(), constructorEntry, this.methodEntry);
163 }
164 } 153 }
165 154
166 return recurse(node, index); 155 return recurse(node, index);
@@ -181,7 +170,8 @@ public class SourceIndexMethodVisitor extends SourceIndexVisitor {
181 if (originalVariable != null) { 170 if (originalVariable != null) {
182 int variableIndex = originalVariable.getSlot(); 171 int variableIndex = originalVariable.getSlot();
183 if (variableIndex >= 0) { 172 if (variableIndex >= 0) {
184 LocalVariableEntry localVariableEntry = new LocalVariableEntry(methodEntry, variableIndex, initializer.getName(), false); 173 TypeDescriptor variableType = TypeDescriptor.parse(originalVariable.getVariableType());
174 LocalVariableDefEntry localVariableEntry = new LocalVariableDefEntry(methodEntry, variableIndex, initializer.getName(), false, variableType);
185 identifierEntryCache.put(identifier.getName(), localVariableEntry); 175 identifierEntryCache.put(identifier.getName(), localVariableEntry);
186 addDeclarationToUnmatched(identifier.getName(), index); 176 addDeclarationToUnmatched(identifier.getName(), index);
187 index.addDeclaration(identifier, localVariableEntry); 177 index.addDeclaration(identifier, localVariableEntry);
@@ -199,17 +189,19 @@ public class SourceIndexMethodVisitor extends SourceIndexVisitor {
199 189
200 if (ref instanceof MethodReference) { 190 if (ref instanceof MethodReference) {
201 // get the behavior entry 191 // get the behavior entry
202 ClassEntry classEntry = entryPool.getClass(ref.getDeclaringType().getInternalName()); 192 ClassEntry classEntry = new ClassEntry(ref.getDeclaringType().getInternalName());
203 MethodEntry methodEntry = null; 193 MethodEntry methodEntry = new MethodEntry(classEntry, ref.getName(), new MethodDescriptor(ref.getErasedSignature()));
204 194
205 methodEntry = entryPool.getMethod(classEntry, ref.getName(), ref.getErasedSignature());
206 // get the node for the token 195 // get the node for the token
207 AstNode tokenNode = node.getMethodNameToken(); 196 AstNode methodNameToken = node.getMethodNameToken();
208 if (tokenNode == null || (tokenNode.getRegion().getBeginLine() == 0 || tokenNode.getRegion().getEndLine() == 0)){ 197 AstNode targetToken = node.getTarget();
209 tokenNode = node.getTarget(); 198
199 if (methodNameToken != null) {
200 index.addReference(methodNameToken, methodEntry, this.methodEntry);
210 } 201 }
211 if (tokenNode != null) { 202
212 index.addReference(tokenNode, methodEntry, this.methodEntry); 203 if (targetToken != null && !(targetToken instanceof ThisReferenceExpression)) {
204 index.addReference(targetToken, methodEntry.getParent(), this.methodEntry);
213 } 205 }
214 } 206 }
215 207
diff --git a/src/main/java/cuchaz/enigma/analysis/SourceIndexVisitor.java b/src/main/java/cuchaz/enigma/analysis/SourceIndexVisitor.java
index 564830c..75a66a2 100644
--- a/src/main/java/cuchaz/enigma/analysis/SourceIndexVisitor.java
+++ b/src/main/java/cuchaz/enigma/analysis/SourceIndexVisitor.java
@@ -14,23 +14,16 @@ package cuchaz.enigma.analysis;
14import com.strobel.assembler.metadata.TypeDefinition; 14import com.strobel.assembler.metadata.TypeDefinition;
15import com.strobel.decompiler.languages.java.ast.*; 15import com.strobel.decompiler.languages.java.ast.*;
16import com.strobel.decompiler.patterns.Pattern; 16import com.strobel.decompiler.patterns.Pattern;
17import cuchaz.enigma.translation.representation.ReferencedEntryPool;
18import cuchaz.enigma.translation.representation.entry.ClassDefEntry; 17import cuchaz.enigma.translation.representation.entry.ClassDefEntry;
19 18
20public class SourceIndexVisitor implements IAstVisitor<SourceIndex, Void> { 19public class SourceIndexVisitor implements IAstVisitor<SourceIndex, Void> {
21 private final ReferencedEntryPool entryPool;
22
23 public SourceIndexVisitor(ReferencedEntryPool entryPool) {
24 this.entryPool = entryPool;
25 }
26
27 @Override 20 @Override
28 public Void visitTypeDeclaration(TypeDeclaration node, SourceIndex index) { 21 public Void visitTypeDeclaration(TypeDeclaration node, SourceIndex index) {
29 TypeDefinition def = node.getUserData(Keys.TYPE_DEFINITION); 22 TypeDefinition def = node.getUserData(Keys.TYPE_DEFINITION);
30 ClassDefEntry classEntry = ClassDefEntry.parse(def); 23 ClassDefEntry classEntry = ClassDefEntry.parse(def);
31 index.addDeclaration(node.getNameToken(), classEntry); 24 index.addDeclaration(node.getNameToken(), classEntry);
32 25
33 return node.acceptVisitor(new SourceIndexClassVisitor(entryPool, classEntry), index); 26 return node.acceptVisitor(new SourceIndexClassVisitor(classEntry), index);
34 } 27 }
35 28
36 protected Void recurse(AstNode node, SourceIndex index) { 29 protected Void recurse(AstNode node, SourceIndex index) {
diff --git a/src/main/java/cuchaz/enigma/analysis/Token.java b/src/main/java/cuchaz/enigma/analysis/Token.java
index 14fa7ca..12e0aa6 100644
--- a/src/main/java/cuchaz/enigma/analysis/Token.java
+++ b/src/main/java/cuchaz/enigma/analysis/Token.java
@@ -30,12 +30,12 @@ public class Token implements Comparable<Token> {
30 return to.length() - length; 30 return to.length() - length;
31 } 31 }
32 32
33 public String rename(String source, String to) { 33 public void rename(StringBuffer source, String to) {
34 int oldEnd = this.end; 34 int oldEnd = this.end;
35 this.text = to; 35 this.text = to;
36 this.end = this.start + to.length(); 36 this.end = this.start + to.length();
37 37
38 return source.substring(0, this.start) + to + source.substring(oldEnd); 38 source.replace(start, oldEnd, to);
39 } 39 }
40 40
41 public Token move(int offset) { 41 public Token move(int offset) {
@@ -64,7 +64,7 @@ public class Token implements Comparable<Token> {
64 } 64 }
65 65
66 public boolean equals(Token other) { 66 public boolean equals(Token other) {
67 return start == other.start && end == other.end; 67 return start == other.start && end == other.end && text.equals(other.text);
68 } 68 }
69 69
70 @Override 70 @Override
diff --git a/src/main/java/cuchaz/enigma/analysis/index/BridgeMethodIndex.java b/src/main/java/cuchaz/enigma/analysis/index/BridgeMethodIndex.java
index e1903d9..8f6bd46 100644
--- a/src/main/java/cuchaz/enigma/analysis/index/BridgeMethodIndex.java
+++ b/src/main/java/cuchaz/enigma/analysis/index/BridgeMethodIndex.java
@@ -1,7 +1,6 @@
1package cuchaz.enigma.analysis.index; 1package cuchaz.enigma.analysis.index;
2 2
3import com.google.common.collect.Maps; 3import com.google.common.collect.Maps;
4import cuchaz.enigma.translation.Translator;
5import cuchaz.enigma.translation.mapping.EntryResolver; 4import cuchaz.enigma.translation.mapping.EntryResolver;
6import cuchaz.enigma.translation.representation.AccessFlags; 5import cuchaz.enigma.translation.representation.AccessFlags;
7import cuchaz.enigma.translation.representation.entry.MethodEntry; 6import cuchaz.enigma.translation.representation.entry.MethodEntry;
@@ -10,7 +9,7 @@ import javax.annotation.Nullable;
10import java.util.Collection; 9import java.util.Collection;
11import java.util.Map; 10import java.util.Map;
12 11
13public class BridgeMethodIndex implements JarIndexer, RemappableIndex { 12public class BridgeMethodIndex implements JarIndexer {
14 private final EntryIndex entryIndex; 13 private final EntryIndex entryIndex;
15 private final ReferenceIndex referenceIndex; 14 private final ReferenceIndex referenceIndex;
16 15
@@ -22,19 +21,6 @@ public class BridgeMethodIndex implements JarIndexer, RemappableIndex {
22 } 21 }
23 22
24 @Override 23 @Override
25 public void remap(Translator translator) {
26 accessedToBridge = translator.translate(accessedToBridge);
27 }
28
29 @Override
30 public BridgeMethodIndex remapped(Translator translator) {
31 BridgeMethodIndex index = new BridgeMethodIndex(entryIndex, referenceIndex);
32 index.accessedToBridge = translator.translate(accessedToBridge);
33
34 return index;
35 }
36
37 @Override
38 public void processIndex(EntryResolver resolver) { 24 public void processIndex(EntryResolver resolver) {
39 // look for access and bridged methods 25 // look for access and bridged methods
40 for (MethodEntry methodEntry : entryIndex.getMethods()) { 26 for (MethodEntry methodEntry : entryIndex.getMethods()) {
diff --git a/src/main/java/cuchaz/enigma/analysis/index/EntryIndex.java b/src/main/java/cuchaz/enigma/analysis/index/EntryIndex.java
index 55bfbc2..773eaf1 100644
--- a/src/main/java/cuchaz/enigma/analysis/index/EntryIndex.java
+++ b/src/main/java/cuchaz/enigma/analysis/index/EntryIndex.java
@@ -1,6 +1,5 @@
1package cuchaz.enigma.analysis.index; 1package cuchaz.enigma.analysis.index;
2 2
3import cuchaz.enigma.translation.Translator;
4import cuchaz.enigma.translation.representation.AccessFlags; 3import cuchaz.enigma.translation.representation.AccessFlags;
5import cuchaz.enigma.translation.representation.entry.*; 4import cuchaz.enigma.translation.representation.entry.*;
6 5
@@ -9,29 +8,12 @@ import java.util.Collection;
9import java.util.HashMap; 8import java.util.HashMap;
10import java.util.Map; 9import java.util.Map;
11 10
12public class EntryIndex implements JarIndexer, RemappableIndex { 11public class EntryIndex implements JarIndexer {
13 private Map<ClassEntry, AccessFlags> classes = new HashMap<>(); 12 private Map<ClassEntry, AccessFlags> classes = new HashMap<>();
14 private Map<FieldEntry, AccessFlags> fields = new HashMap<>(); 13 private Map<FieldEntry, AccessFlags> fields = new HashMap<>();
15 private Map<MethodEntry, AccessFlags> methods = new HashMap<>(); 14 private Map<MethodEntry, AccessFlags> methods = new HashMap<>();
16 15
17 @Override 16 @Override
18 public void remap(Translator translator) {
19 classes = translator.translateKeys(classes);
20 fields = translator.translateKeys(fields);
21 methods = translator.translateKeys(methods);
22 }
23
24 @Override
25 public EntryIndex remapped(Translator translator) {
26 EntryIndex index = new EntryIndex();
27 index.classes = translator.translateKeys(classes);
28 index.fields = translator.translateKeys(fields);
29 index.methods = translator.translateKeys(methods);
30
31 return index;
32 }
33
34 @Override
35 public void indexClass(ClassDefEntry classEntry) { 17 public void indexClass(ClassDefEntry classEntry) {
36 classes.put(classEntry, classEntry.getAccess()); 18 classes.put(classEntry, classEntry.getAccess());
37 } 19 }
diff --git a/src/main/java/cuchaz/enigma/analysis/index/InheritanceIndex.java b/src/main/java/cuchaz/enigma/analysis/index/InheritanceIndex.java
index d165cc8..17bed54 100644
--- a/src/main/java/cuchaz/enigma/analysis/index/InheritanceIndex.java
+++ b/src/main/java/cuchaz/enigma/analysis/index/InheritanceIndex.java
@@ -14,7 +14,6 @@ package cuchaz.enigma.analysis.index;
14import com.google.common.collect.HashMultimap; 14import com.google.common.collect.HashMultimap;
15import com.google.common.collect.Multimap; 15import com.google.common.collect.Multimap;
16import com.google.common.collect.Sets; 16import com.google.common.collect.Sets;
17import cuchaz.enigma.translation.Translator;
18import cuchaz.enigma.translation.representation.entry.ClassDefEntry; 17import cuchaz.enigma.translation.representation.entry.ClassDefEntry;
19import cuchaz.enigma.translation.representation.entry.ClassEntry; 18import cuchaz.enigma.translation.representation.entry.ClassEntry;
20 19
@@ -22,26 +21,11 @@ import java.util.Collection;
22import java.util.LinkedList; 21import java.util.LinkedList;
23import java.util.Set; 22import java.util.Set;
24 23
25public class InheritanceIndex implements JarIndexer, RemappableIndex { 24public class InheritanceIndex implements JarIndexer {
26 private Multimap<ClassEntry, ClassEntry> classParents = HashMultimap.create(); 25 private Multimap<ClassEntry, ClassEntry> classParents = HashMultimap.create();
27 private Multimap<ClassEntry, ClassEntry> classChildren = HashMultimap.create(); 26 private Multimap<ClassEntry, ClassEntry> classChildren = HashMultimap.create();
28 27
29 @Override 28 @Override
30 public void remap(Translator translator) {
31 classChildren = translator.translate(classChildren);
32 classParents = translator.translate(classParents);
33 }
34
35 @Override
36 public InheritanceIndex remapped(Translator translator) {
37 InheritanceIndex index = new InheritanceIndex();
38 index.classParents = translator.translate(classParents);
39 index.classChildren = translator.translate(classChildren);
40
41 return index;
42 }
43
44 @Override
45 public void indexClass(ClassDefEntry classEntry) { 29 public void indexClass(ClassDefEntry classEntry) {
46 ClassEntry superClass = classEntry.getSuperClass(); 30 ClassEntry superClass = classEntry.getSuperClass();
47 if (superClass != null) { 31 if (superClass != null) {
diff --git a/src/main/java/cuchaz/enigma/analysis/index/JarIndex.java b/src/main/java/cuchaz/enigma/analysis/index/JarIndex.java
index 0880244..9b21cba 100644
--- a/src/main/java/cuchaz/enigma/analysis/index/JarIndex.java
+++ b/src/main/java/cuchaz/enigma/analysis/index/JarIndex.java
@@ -14,7 +14,6 @@ package cuchaz.enigma.analysis.index;
14import com.google.common.collect.HashMultimap; 14import com.google.common.collect.HashMultimap;
15import com.google.common.collect.Multimap; 15import com.google.common.collect.Multimap;
16import cuchaz.enigma.analysis.ParsedJar; 16import cuchaz.enigma.analysis.ParsedJar;
17import cuchaz.enigma.translation.Translator;
18import cuchaz.enigma.translation.mapping.EntryResolver; 17import cuchaz.enigma.translation.mapping.EntryResolver;
19import cuchaz.enigma.translation.mapping.IndexEntryResolver; 18import cuchaz.enigma.translation.mapping.IndexEntryResolver;
20import cuchaz.enigma.translation.representation.entry.*; 19import cuchaz.enigma.translation.representation.entry.*;
@@ -25,7 +24,7 @@ import java.util.Arrays;
25import java.util.Collection; 24import java.util.Collection;
26import java.util.function.Consumer; 25import java.util.function.Consumer;
27 26
28public class JarIndex implements JarIndexer, RemappableIndex { 27public class JarIndex implements JarIndexer {
29 private final EntryIndex entryIndex; 28 private final EntryIndex entryIndex;
30 private final InheritanceIndex inheritanceIndex; 29 private final InheritanceIndex inheritanceIndex;
31 private final ReferenceIndex referenceIndex; 30 private final ReferenceIndex referenceIndex;
@@ -53,25 +52,6 @@ public class JarIndex implements JarIndexer, RemappableIndex {
53 return new JarIndex(entryIndex, inheritanceIndex, referenceIndex, bridgeMethodIndex); 52 return new JarIndex(entryIndex, inheritanceIndex, referenceIndex, bridgeMethodIndex);
54 } 53 }
55 54
56 @Override
57 public void remap(Translator translator) {
58 entryIndex.remap(translator);
59 inheritanceIndex.remap(translator);
60 bridgeMethodIndex.remap(translator);
61 }
62
63 @Override
64 public JarIndex remapped(Translator translator) {
65 EntryIndex entryIndex = this.entryIndex.remapped(translator);
66 InheritanceIndex inheritanceIndex = this.inheritanceIndex.remapped(translator);
67 BridgeMethodIndex bridgeMethodIndex = this.bridgeMethodIndex.remapped(translator);
68
69 JarIndex remappedIndex = new JarIndex(entryIndex, inheritanceIndex, this.referenceIndex, bridgeMethodIndex);
70 remappedIndex.methodImplementations.putAll(methodImplementations);
71
72 return remappedIndex;
73 }
74
75 public void indexJar(ParsedJar jar, Consumer<String> progress) { 55 public void indexJar(ParsedJar jar, Consumer<String> progress) {
76 progress.accept("Indexing entries (1/3)"); 56 progress.accept("Indexing entries (1/3)");
77 jar.visitReader(name -> new IndexClassVisitor(this, Opcodes.ASM5), ClassReader.SKIP_CODE); 57 jar.visitReader(name -> new IndexClassVisitor(this, Opcodes.ASM5), ClassReader.SKIP_CODE);
diff --git a/src/main/java/cuchaz/enigma/analysis/index/RemappableIndex.java b/src/main/java/cuchaz/enigma/analysis/index/RemappableIndex.java
deleted file mode 100644
index 537e772..0000000
--- a/src/main/java/cuchaz/enigma/analysis/index/RemappableIndex.java
+++ /dev/null
@@ -1,9 +0,0 @@
1package cuchaz.enigma.analysis.index;
2
3import cuchaz.enigma.translation.Translator;
4
5public interface RemappableIndex {
6 void remap(Translator translator);
7
8 RemappableIndex remapped(Translator translator);
9}