summaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorGravatar Erlend Ã…mdal2019-05-15 12:45:41 +0200
committerGravatar Gegy2019-05-15 12:45:41 +0200
commitdf8def23dd0336d8a5d2369c5d4c0f4331838ef4 (patch)
treede7fbdc9ccdf4a20c83103c0e2b0c3129c84430b /src/main/java
parentResolve root when navigating to declaration (diff)
downloadenigma-df8def23dd0336d8a5d2369c5d4c0f4331838ef4.tar.gz
enigma-df8def23dd0336d8a5d2369c5d4c0f4331838ef4.tar.xz
enigma-df8def23dd0336d8a5d2369c5d4c0f4331838ef4.zip
checkmappings command (#137)
* Use expected map sizes for remapped multimaps * Index method and field types * Add package visibility index * Add checkmappings command and use System.err for error messages * Use exit codes for errors * Remove outer class check for package visible only refs * Throw exception on mapping error instead of exiting
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/cuchaz/enigma/CommandMain.java62
-rw-r--r--src/main/java/cuchaz/enigma/analysis/index/EntryIndex.java5
-rw-r--r--src/main/java/cuchaz/enigma/analysis/index/JarIndex.java13
-rw-r--r--src/main/java/cuchaz/enigma/analysis/index/PackageVisibilityIndex.java127
-rw-r--r--src/main/java/cuchaz/enigma/analysis/index/ReferenceIndex.java55
5 files changed, 247 insertions, 15 deletions
diff --git a/src/main/java/cuchaz/enigma/CommandMain.java b/src/main/java/cuchaz/enigma/CommandMain.java
index c9f83828..db4fd125 100644
--- a/src/main/java/cuchaz/enigma/CommandMain.java
+++ b/src/main/java/cuchaz/enigma/CommandMain.java
@@ -11,35 +11,47 @@
11 11
12package cuchaz.enigma; 12package cuchaz.enigma;
13 13
14import cuchaz.enigma.analysis.index.JarIndex;
14import cuchaz.enigma.translation.mapping.EntryMapping; 15import cuchaz.enigma.translation.mapping.EntryMapping;
15import cuchaz.enigma.translation.mapping.serde.MappingFormat; 16import cuchaz.enigma.translation.mapping.serde.MappingFormat;
16import cuchaz.enigma.translation.mapping.tree.EntryTree; 17import cuchaz.enigma.translation.mapping.tree.EntryTree;
18import cuchaz.enigma.translation.representation.entry.ClassEntry;
17 19
18import java.io.File; 20import java.io.File;
19import java.nio.file.Files; 21import java.nio.file.Files;
20import java.nio.file.Path; 22import java.nio.file.Path;
21import java.nio.file.Paths; 23import java.nio.file.Paths;
22import java.util.Locale; 24import java.util.Locale;
25import java.util.Set;
23import java.util.jar.JarFile; 26import java.util.jar.JarFile;
27import java.util.stream.Collectors;
24 28
25public class CommandMain { 29public class CommandMain {
26 30
27 public static void main(String[] args) throws Exception { 31 public static void main(String[] args) throws Exception {
28 try { 32 try {
29 // process the command 33 // process the command
30 String command = getArg(args, 0, "command", true); 34 String command = getArg(args, 0, "command", true).toLowerCase(Locale.ROOT);
31 if (command.equalsIgnoreCase("deobfuscate")) { 35 switch (command) {
32 deobfuscate(args); 36 case "deobfuscate":
33 } else if (command.equalsIgnoreCase("decompile")) { 37 deobfuscate(args);
34 decompile(args); 38 break;
35 } else if (command.equalsIgnoreCase("convertmappings")) { 39 case "decompile":
36 convertMappings(args); 40 decompile(args);
37 } else { 41 break;
38 throw new IllegalArgumentException("Command not recognized: " + command); 42 case "convertmappings":
43 convertMappings(args);
44 break;
45 case "checkmappings":
46 checkMappings(args);
47 break;
48 default:
49 throw new IllegalArgumentException("Command not recognized: " + command);
39 } 50 }
40 } catch (IllegalArgumentException ex) { 51 } catch (IllegalArgumentException ex) {
41 System.out.println(ex.getMessage()); 52 System.err.println(ex.getMessage());
42 printHelp(); 53 printHelp();
54 System.exit(1);
43 } 55 }
44 } 56 }
45 57
@@ -51,6 +63,7 @@ public class CommandMain {
51 System.out.println("\t\tdeobfuscate <in jar> <out jar> [<mappings file>]"); 63 System.out.println("\t\tdeobfuscate <in jar> <out jar> [<mappings file>]");
52 System.out.println("\t\tdecompile <in jar> <out folder> [<mappings file>]"); 64 System.out.println("\t\tdecompile <in jar> <out folder> [<mappings file>]");
53 System.out.println("\t\tconvertmappings <enigma mappings> <converted mappings> <ENIGMA_FILE|ENIGMA_DIRECTORY|SRG_FILE>"); 65 System.out.println("\t\tconvertmappings <enigma mappings> <converted mappings> <ENIGMA_FILE|ENIGMA_DIRECTORY|SRG_FILE>");
66 System.out.println("\t\tcheckmappings <in jar> <mappings file>");
54 } 67 }
55 68
56 private static void decompile(String[] args) throws Exception { 69 private static void decompile(String[] args) throws Exception {
@@ -100,6 +113,35 @@ public class CommandMain {
100 saveFormat.write(mappings, result.toPath(), new ConsoleProgressListener()); 113 saveFormat.write(mappings, result.toPath(), new ConsoleProgressListener());
101 } 114 }
102 115
116 private static void checkMappings(String[] args) throws Exception {
117 File fileJarIn = getReadableFile(getArg(args, 1, "in jar", true));
118 Path fileMappings = getReadablePath(getArg(args, 2, "enigma mapping", true));
119
120 System.out.println("Reading JAR...");
121 Deobfuscator deobfuscator = new Deobfuscator(new JarFile(fileJarIn));
122 System.out.println("Reading mappings...");
123
124 MappingFormat format = chooseEnigmaFormat(fileMappings);
125 EntryTree<EntryMapping> mappings = format.read(fileMappings, ProgressListener.VOID);
126 deobfuscator.setMappings(mappings);
127
128 JarIndex idx = deobfuscator.getJarIndex();
129
130 boolean error = false;
131
132 for (Set<ClassEntry> partition : idx.getPackageVisibilityIndex().getPartitions()) {
133 long packages = partition.stream().map(deobfuscator.getMapper()::deobfuscate).map(ClassEntry::getPackageName).distinct().count();
134 if (packages > 1) {
135 error = true;
136 System.err.println("ERROR: Must be in one package:\n" + partition.stream().map(deobfuscator.getMapper()::deobfuscate).map(ClassEntry::toString).sorted().collect(Collectors.joining("\n")));
137 }
138 }
139
140 if (error) {
141 throw new Exception("Access violations detected");
142 }
143 }
144
103 private static MappingFormat chooseEnigmaFormat(Path path) { 145 private static MappingFormat chooseEnigmaFormat(Path path) {
104 if (Files.isDirectory(path)) { 146 if (Files.isDirectory(path)) {
105 return MappingFormat.ENIGMA_DIRECTORY; 147 return MappingFormat.ENIGMA_DIRECTORY;
diff --git a/src/main/java/cuchaz/enigma/analysis/index/EntryIndex.java b/src/main/java/cuchaz/enigma/analysis/index/EntryIndex.java
index 773eaf18..31c6f54f 100644
--- a/src/main/java/cuchaz/enigma/analysis/index/EntryIndex.java
+++ b/src/main/java/cuchaz/enigma/analysis/index/EntryIndex.java
@@ -65,6 +65,11 @@ public class EntryIndex implements JarIndexer {
65 } 65 }
66 66
67 @Nullable 67 @Nullable
68 public AccessFlags getClassAccess(ClassEntry entry) {
69 return classes.get(entry);
70 }
71
72 @Nullable
68 public AccessFlags getEntryAccess(Entry<?> entry) { 73 public AccessFlags getEntryAccess(Entry<?> entry) {
69 if (entry instanceof MethodEntry) { 74 if (entry instanceof MethodEntry) {
70 return getMethodAccess((MethodEntry) entry); 75 return getMethodAccess((MethodEntry) entry);
diff --git a/src/main/java/cuchaz/enigma/analysis/index/JarIndex.java b/src/main/java/cuchaz/enigma/analysis/index/JarIndex.java
index a429ff6e..ac907af0 100644
--- a/src/main/java/cuchaz/enigma/analysis/index/JarIndex.java
+++ b/src/main/java/cuchaz/enigma/analysis/index/JarIndex.java
@@ -29,18 +29,20 @@ public class JarIndex implements JarIndexer {
29 private final InheritanceIndex inheritanceIndex; 29 private final InheritanceIndex inheritanceIndex;
30 private final ReferenceIndex referenceIndex; 30 private final ReferenceIndex referenceIndex;
31 private final BridgeMethodIndex bridgeMethodIndex; 31 private final BridgeMethodIndex bridgeMethodIndex;
32 private final PackageVisibilityIndex packageVisibilityIndex;
32 private final EntryResolver entryResolver; 33 private final EntryResolver entryResolver;
33 34
34 private final Collection<JarIndexer> indexers; 35 private final Collection<JarIndexer> indexers;
35 36
36 private final Multimap<String, MethodDefEntry> methodImplementations = HashMultimap.create(); 37 private final Multimap<String, MethodDefEntry> methodImplementations = HashMultimap.create();
37 38
38 public JarIndex(EntryIndex entryIndex, InheritanceIndex inheritanceIndex, ReferenceIndex referenceIndex, BridgeMethodIndex bridgeMethodIndex) { 39 public JarIndex(EntryIndex entryIndex, InheritanceIndex inheritanceIndex, ReferenceIndex referenceIndex, BridgeMethodIndex bridgeMethodIndex, PackageVisibilityIndex packageVisibilityIndex) {
39 this.entryIndex = entryIndex; 40 this.entryIndex = entryIndex;
40 this.inheritanceIndex = inheritanceIndex; 41 this.inheritanceIndex = inheritanceIndex;
41 this.referenceIndex = referenceIndex; 42 this.referenceIndex = referenceIndex;
42 this.bridgeMethodIndex = bridgeMethodIndex; 43 this.bridgeMethodIndex = bridgeMethodIndex;
43 this.indexers = Arrays.asList(entryIndex, inheritanceIndex, referenceIndex, bridgeMethodIndex); 44 this.packageVisibilityIndex = packageVisibilityIndex;
45 this.indexers = Arrays.asList(entryIndex, inheritanceIndex, referenceIndex, bridgeMethodIndex, packageVisibilityIndex);
44 this.entryResolver = new IndexEntryResolver(this); 46 this.entryResolver = new IndexEntryResolver(this);
45 } 47 }
46 48
@@ -49,7 +51,8 @@ public class JarIndex implements JarIndexer {
49 InheritanceIndex inheritanceIndex = new InheritanceIndex(entryIndex); 51 InheritanceIndex inheritanceIndex = new InheritanceIndex(entryIndex);
50 ReferenceIndex referenceIndex = new ReferenceIndex(); 52 ReferenceIndex referenceIndex = new ReferenceIndex();
51 BridgeMethodIndex bridgeMethodIndex = new BridgeMethodIndex(entryIndex, inheritanceIndex, referenceIndex); 53 BridgeMethodIndex bridgeMethodIndex = new BridgeMethodIndex(entryIndex, inheritanceIndex, referenceIndex);
52 return new JarIndex(entryIndex, inheritanceIndex, referenceIndex, bridgeMethodIndex); 54 PackageVisibilityIndex packageVisibilityIndex = new PackageVisibilityIndex();
55 return new JarIndex(entryIndex, inheritanceIndex, referenceIndex, bridgeMethodIndex, packageVisibilityIndex);
53 } 56 }
54 57
55 public void indexJar(ParsedJar jar, Consumer<String> progress) { 58 public void indexJar(ParsedJar jar, Consumer<String> progress) {
@@ -142,6 +145,10 @@ public class JarIndex implements JarIndexer {
142 return bridgeMethodIndex; 145 return bridgeMethodIndex;
143 } 146 }
144 147
148 public PackageVisibilityIndex getPackageVisibilityIndex() {
149 return packageVisibilityIndex;
150 }
151
145 public EntryResolver getEntryResolver() { 152 public EntryResolver getEntryResolver() {
146 return entryResolver; 153 return entryResolver;
147 } 154 }
diff --git a/src/main/java/cuchaz/enigma/analysis/index/PackageVisibilityIndex.java b/src/main/java/cuchaz/enigma/analysis/index/PackageVisibilityIndex.java
new file mode 100644
index 00000000..9e9115fe
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/analysis/index/PackageVisibilityIndex.java
@@ -0,0 +1,127 @@
1package cuchaz.enigma.analysis.index;
2
3import com.google.common.collect.HashMultimap;
4import com.google.common.collect.Lists;
5import com.google.common.collect.Maps;
6import com.google.common.collect.Sets;
7import cuchaz.enigma.analysis.EntryReference;
8import cuchaz.enigma.translation.representation.AccessFlags;
9import cuchaz.enigma.translation.representation.entry.*;
10
11import java.util.*;
12
13public class PackageVisibilityIndex implements JarIndexer {
14 private static boolean isPackageVisibleOnlyRef(AccessFlags entryAcc, EntryReference ref, InheritanceIndex inheritanceIndex) {
15 if (entryAcc.isPublic()) return false;
16 if (entryAcc.isProtected()) {
17 Set<ClassEntry> callerAncestors = inheritanceIndex.getAncestors(ref.context.getContainingClass());
18 return !callerAncestors.contains(ref.entry.getContainingClass());
19 }
20 return !entryAcc.isPrivate(); // if isPrivate is false, it must be package-private
21 }
22
23 private final HashMultimap<ClassEntry, ClassEntry> connections = HashMultimap.create();
24 private final List<Set<ClassEntry>> partitions = Lists.newArrayList();
25 private final Map<ClassEntry, Set<ClassEntry>> classPartitions = Maps.newHashMap();
26
27 private void addConnection(ClassEntry classA, ClassEntry classB) {
28 connections.put(classA, classB);
29 connections.put(classB, classA);
30 }
31
32 private void buildPartition(Set<ClassEntry> unassignedClasses, Set<ClassEntry> partition, ClassEntry member) {
33 for (ClassEntry connected : connections.get(member)) {
34 if (unassignedClasses.remove(connected)) {
35 partition.add(connected);
36 buildPartition(unassignedClasses, partition, connected);
37 }
38 }
39 }
40
41 private void addConnections(EntryIndex entryIndex, ReferenceIndex referenceIndex, InheritanceIndex inheritanceIndex) {
42 for (FieldEntry entry : entryIndex.getFields()) {
43 AccessFlags entryAcc = entryIndex.getFieldAccess(entry);
44 if (!entryAcc.isPublic() && !entryAcc.isPrivate()) {
45 for (EntryReference<FieldEntry, MethodDefEntry> ref : referenceIndex.getReferencesToField(entry)) {
46 if (isPackageVisibleOnlyRef(entryAcc, ref, inheritanceIndex)) {
47 addConnection(ref.entry.getContainingClass(), ref.context.getContainingClass());
48 }
49 }
50 }
51 }
52
53 for (MethodEntry entry : entryIndex.getMethods()) {
54 AccessFlags entryAcc = entryIndex.getMethodAccess(entry);
55 if (!entryAcc.isPublic() && !entryAcc.isPrivate()) {
56 for (EntryReference<MethodEntry, MethodDefEntry> ref : referenceIndex.getReferencesToMethod(entry)) {
57 if (isPackageVisibleOnlyRef(entryAcc, ref, inheritanceIndex)) {
58 addConnection(ref.entry.getContainingClass(), ref.context.getContainingClass());
59 }
60 }
61 }
62 }
63
64 for (ClassEntry entry : entryIndex.getClasses()) {
65 AccessFlags entryAcc = entryIndex.getClassAccess(entry);
66 if (!entryAcc.isPublic() && !entryAcc.isPrivate()) {
67 for (EntryReference<ClassEntry, FieldDefEntry> ref : referenceIndex.getFieldTypeReferencesToClass(entry)) {
68 if (isPackageVisibleOnlyRef(entryAcc, ref, inheritanceIndex)) {
69 addConnection(ref.entry.getContainingClass(), ref.context.getContainingClass());
70 }
71 }
72
73 for (EntryReference<ClassEntry, MethodDefEntry> ref : referenceIndex.getMethodTypeReferencesToClass(entry)) {
74 if (isPackageVisibleOnlyRef(entryAcc, ref, inheritanceIndex)) {
75 addConnection(ref.entry.getContainingClass(), ref.context.getContainingClass());
76 }
77 }
78 }
79
80 for (ClassEntry parent : inheritanceIndex.getParents(entry)) {
81 AccessFlags parentAcc = entryIndex.getClassAccess(parent);
82 if (parentAcc != null && !parentAcc.isPublic() && !parentAcc.isPrivate()) {
83 addConnection(entry, parent);
84 }
85 }
86
87 ClassEntry outerClass = entry.getOuterClass();
88 if (outerClass != null) {
89 addConnection(entry, outerClass);
90 }
91 }
92 }
93
94 private void addPartitions(EntryIndex entryIndex) {
95 Set<ClassEntry> unassignedClasses = Sets.newHashSet(entryIndex.getClasses());
96 while (!unassignedClasses.isEmpty()) {
97 Iterator<ClassEntry> iterator = unassignedClasses.iterator();
98 ClassEntry initialEntry = iterator.next();
99 iterator.remove();
100
101 HashSet<ClassEntry> partition = Sets.newHashSet();
102 partition.add(initialEntry);
103 buildPartition(unassignedClasses, partition, initialEntry);
104 partitions.add(partition);
105 for (ClassEntry entry : partition) {
106 classPartitions.put(entry, partition);
107 }
108 }
109 }
110
111 public Collection<Set<ClassEntry>> getPartitions() {
112 return partitions;
113 }
114
115 public Set<ClassEntry> getPartition(ClassEntry classEntry) {
116 return classPartitions.get(classEntry);
117 }
118
119 @Override
120 public void processIndex(JarIndex index) {
121 EntryIndex entryIndex = index.getEntryIndex();
122 ReferenceIndex referenceIndex = index.getReferenceIndex();
123 InheritanceIndex inheritanceIndex = index.getInheritanceIndex();
124 addConnections(entryIndex, referenceIndex, inheritanceIndex);
125 addPartitions(entryIndex);
126 }
127}
diff --git a/src/main/java/cuchaz/enigma/analysis/index/ReferenceIndex.java b/src/main/java/cuchaz/enigma/analysis/index/ReferenceIndex.java
index 2b63c5d4..6764ac0c 100644
--- a/src/main/java/cuchaz/enigma/analysis/index/ReferenceIndex.java
+++ b/src/main/java/cuchaz/enigma/analysis/index/ReferenceIndex.java
@@ -4,6 +4,8 @@ import com.google.common.collect.HashMultimap;
4import com.google.common.collect.Multimap; 4import com.google.common.collect.Multimap;
5import cuchaz.enigma.analysis.EntryReference; 5import cuchaz.enigma.analysis.EntryReference;
6import cuchaz.enigma.translation.mapping.ResolutionStrategy; 6import cuchaz.enigma.translation.mapping.ResolutionStrategy;
7import cuchaz.enigma.translation.representation.MethodDescriptor;
8import cuchaz.enigma.translation.representation.TypeDescriptor;
7import cuchaz.enigma.translation.representation.entry.*; 9import cuchaz.enigma.translation.representation.entry.*;
8 10
9import java.util.Collection; 11import java.util.Collection;
@@ -15,6 +17,43 @@ public class ReferenceIndex implements JarIndexer {
15 private Multimap<MethodEntry, EntryReference<MethodEntry, MethodDefEntry>> referencesToMethods = HashMultimap.create(); 17 private Multimap<MethodEntry, EntryReference<MethodEntry, MethodDefEntry>> referencesToMethods = HashMultimap.create();
16 private Multimap<ClassEntry, EntryReference<ClassEntry, MethodDefEntry>> referencesToClasses = HashMultimap.create(); 18 private Multimap<ClassEntry, EntryReference<ClassEntry, MethodDefEntry>> referencesToClasses = HashMultimap.create();
17 private Multimap<FieldEntry, EntryReference<FieldEntry, MethodDefEntry>> referencesToFields = HashMultimap.create(); 19 private Multimap<FieldEntry, EntryReference<FieldEntry, MethodDefEntry>> referencesToFields = HashMultimap.create();
20 private Multimap<ClassEntry, EntryReference<ClassEntry, FieldDefEntry>> fieldTypeReferences = HashMultimap.create();
21 private Multimap<ClassEntry, EntryReference<ClassEntry, MethodDefEntry>> methodTypeReferences = HashMultimap.create();
22
23 @Override
24 public void indexMethod(MethodDefEntry methodEntry) {
25 indexMethodDescriptor(methodEntry, methodEntry.getDesc());
26 }
27
28 private void indexMethodDescriptor(MethodDefEntry entry, MethodDescriptor descriptor) {
29 for (TypeDescriptor typeDescriptor : descriptor.getArgumentDescs()) {
30 indexMethodTypeDescriptor(entry, typeDescriptor);
31 }
32 indexMethodTypeDescriptor(entry, descriptor.getReturnDesc());
33 }
34
35 private void indexMethodTypeDescriptor(MethodDefEntry method, TypeDescriptor typeDescriptor) {
36 if (typeDescriptor.isType()) {
37 ClassEntry referencedClass = typeDescriptor.getTypeEntry();
38 methodTypeReferences.put(referencedClass, new EntryReference<>(referencedClass, referencedClass.getName(), method));
39 } else if (typeDescriptor.isArray()) {
40 indexMethodTypeDescriptor(method, typeDescriptor.getArrayType());
41 }
42 }
43
44 @Override
45 public void indexField(FieldDefEntry fieldEntry) {
46 indexFieldTypeDescriptor(fieldEntry, fieldEntry.getDesc());
47 }
48
49 private void indexFieldTypeDescriptor(FieldDefEntry field, TypeDescriptor typeDescriptor) {
50 if (typeDescriptor.isType()) {
51 ClassEntry referencedClass = typeDescriptor.getTypeEntry();
52 fieldTypeReferences.put(referencedClass, new EntryReference<>(referencedClass, referencedClass.getName(), field));
53 } else if (typeDescriptor.isArray()) {
54 indexFieldTypeDescriptor(field, typeDescriptor.getArrayType());
55 }
56 }
18 57
19 @Override 58 @Override
20 public void indexMethodReference(MethodDefEntry callerEntry, MethodEntry referencedEntry) { 59 public void indexMethodReference(MethodDefEntry callerEntry, MethodEntry referencedEntry) {
@@ -25,6 +64,8 @@ public class ReferenceIndex implements JarIndexer {
25 ClassEntry referencedClass = referencedEntry.getParent(); 64 ClassEntry referencedClass = referencedEntry.getParent();
26 referencesToClasses.put(referencedClass, new EntryReference<>(referencedClass, referencedEntry.getName(), callerEntry)); 65 referencesToClasses.put(referencedClass, new EntryReference<>(referencedClass, referencedEntry.getName(), callerEntry));
27 } 66 }
67
68 indexMethodDescriptor(callerEntry, referencedEntry.getDesc());
28 } 69 }
29 70
30 @Override 71 @Override
@@ -38,10 +79,12 @@ public class ReferenceIndex implements JarIndexer {
38 referencesToMethods = remapReferencesTo(index, referencesToMethods); 79 referencesToMethods = remapReferencesTo(index, referencesToMethods);
39 referencesToClasses = remapReferencesTo(index, referencesToClasses); 80 referencesToClasses = remapReferencesTo(index, referencesToClasses);
40 referencesToFields = remapReferencesTo(index, referencesToFields); 81 referencesToFields = remapReferencesTo(index, referencesToFields);
82 fieldTypeReferences = remapReferencesTo(index, fieldTypeReferences);
83 methodTypeReferences = remapReferencesTo(index, methodTypeReferences);
41 } 84 }
42 85
43 private <K extends Entry<?>, V extends Entry<?>> Multimap<K, V> remapReferences(JarIndex index, Multimap<K, V> multimap) { 86 private <K extends Entry<?>, V extends Entry<?>> Multimap<K, V> remapReferences(JarIndex index, Multimap<K, V> multimap) {
44 Multimap<K, V> resolved = HashMultimap.create(); 87 Multimap<K, V> resolved = HashMultimap.create(multimap.keySet().size(), multimap.size() / multimap.keySet().size());
45 for (Map.Entry<K, V> entry : multimap.entries()) { 88 for (Map.Entry<K, V> entry : multimap.entries()) {
46 resolved.put(remap(index, entry.getKey()), remap(index, entry.getValue())); 89 resolved.put(remap(index, entry.getKey()), remap(index, entry.getValue()));
47 } 90 }
@@ -49,7 +92,7 @@ public class ReferenceIndex implements JarIndexer {
49 } 92 }
50 93
51 private <E extends Entry<?>, C extends Entry<?>> Multimap<E, EntryReference<E, C>> remapReferencesTo(JarIndex index, Multimap<E, EntryReference<E, C>> multimap) { 94 private <E extends Entry<?>, C extends Entry<?>> Multimap<E, EntryReference<E, C>> remapReferencesTo(JarIndex index, Multimap<E, EntryReference<E, C>> multimap) {
52 Multimap<E, EntryReference<E, C>> resolved = HashMultimap.create(); 95 Multimap<E, EntryReference<E, C>> resolved = HashMultimap.create(multimap.keySet().size(), multimap.size() / multimap.keySet().size());
53 for (Map.Entry<E, EntryReference<E, C>> entry : multimap.entries()) { 96 for (Map.Entry<E, EntryReference<E, C>> entry : multimap.entries()) {
54 resolved.put(remap(index, entry.getKey()), remap(index, entry.getValue())); 97 resolved.put(remap(index, entry.getKey()), remap(index, entry.getValue()));
55 } 98 }
@@ -79,4 +122,12 @@ public class ReferenceIndex implements JarIndexer {
79 public Collection<EntryReference<MethodEntry, MethodDefEntry>> getReferencesToMethod(MethodEntry entry) { 122 public Collection<EntryReference<MethodEntry, MethodDefEntry>> getReferencesToMethod(MethodEntry entry) {
80 return referencesToMethods.get(entry); 123 return referencesToMethods.get(entry);
81 } 124 }
125
126 public Collection<EntryReference<ClassEntry, FieldDefEntry>> getFieldTypeReferencesToClass(ClassEntry entry) {
127 return fieldTypeReferences.get(entry);
128 }
129
130 public Collection<EntryReference<ClassEntry, MethodDefEntry>> getMethodTypeReferencesToClass(ClassEntry entry) {
131 return methodTypeReferences.get(entry);
132 }
82} 133}