diff options
Diffstat (limited to 'src/main/java/cuchaz/enigma/analysis/index')
5 files changed, 78 insertions, 29 deletions
diff --git a/src/main/java/cuchaz/enigma/analysis/index/BridgeMethodIndex.java b/src/main/java/cuchaz/enigma/analysis/index/BridgeMethodIndex.java index de2ba1e..649ce25 100644 --- a/src/main/java/cuchaz/enigma/analysis/index/BridgeMethodIndex.java +++ b/src/main/java/cuchaz/enigma/analysis/index/BridgeMethodIndex.java | |||
| @@ -2,7 +2,6 @@ package cuchaz.enigma.analysis.index; | |||
| 2 | 2 | ||
| 3 | import com.google.common.collect.Maps; | 3 | import com.google.common.collect.Maps; |
| 4 | import com.google.common.collect.Sets; | 4 | import com.google.common.collect.Sets; |
| 5 | import cuchaz.enigma.translation.mapping.EntryResolver; | ||
| 6 | import cuchaz.enigma.translation.representation.AccessFlags; | 5 | import cuchaz.enigma.translation.representation.AccessFlags; |
| 7 | import cuchaz.enigma.translation.representation.MethodDescriptor; | 6 | import cuchaz.enigma.translation.representation.MethodDescriptor; |
| 8 | import cuchaz.enigma.translation.representation.TypeDescriptor; | 7 | import cuchaz.enigma.translation.representation.TypeDescriptor; |
| @@ -11,10 +10,7 @@ import cuchaz.enigma.translation.representation.entry.MethodDefEntry; | |||
| 11 | import cuchaz.enigma.translation.representation.entry.MethodEntry; | 10 | import cuchaz.enigma.translation.representation.entry.MethodEntry; |
| 12 | 11 | ||
| 13 | import javax.annotation.Nullable; | 12 | import javax.annotation.Nullable; |
| 14 | import java.util.Collection; | 13 | import java.util.*; |
| 15 | import java.util.List; | ||
| 16 | import java.util.Map; | ||
| 17 | import java.util.Set; | ||
| 18 | 14 | ||
| 19 | public class BridgeMethodIndex implements JarIndexer { | 15 | public class BridgeMethodIndex implements JarIndexer { |
| 20 | private final EntryIndex entryIndex; | 16 | private final EntryIndex entryIndex; |
| @@ -30,8 +26,7 @@ public class BridgeMethodIndex implements JarIndexer { | |||
| 30 | this.referenceIndex = referenceIndex; | 26 | this.referenceIndex = referenceIndex; |
| 31 | } | 27 | } |
| 32 | 28 | ||
| 33 | @Override | 29 | public void findBridgeMethods() { |
| 34 | public void processIndex(EntryResolver resolver) { | ||
| 35 | // look for access and bridged methods | 30 | // look for access and bridged methods |
| 36 | for (MethodEntry methodEntry : entryIndex.getMethods()) { | 31 | for (MethodEntry methodEntry : entryIndex.getMethods()) { |
| 37 | MethodDefEntry methodDefEntry = (MethodDefEntry) methodEntry; | 32 | MethodDefEntry methodDefEntry = (MethodDefEntry) methodEntry; |
| @@ -45,6 +40,23 @@ public class BridgeMethodIndex implements JarIndexer { | |||
| 45 | } | 40 | } |
| 46 | } | 41 | } |
| 47 | 42 | ||
| 43 | @Override | ||
| 44 | public void processIndex(JarIndex index) { | ||
| 45 | Map<MethodEntry, MethodEntry> copiedAccessToBridge = new HashMap<>(accessedToBridge); | ||
| 46 | |||
| 47 | for (Map.Entry<MethodEntry, MethodEntry> entry : copiedAccessToBridge.entrySet()) { | ||
| 48 | MethodEntry accessedEntry = entry.getKey(); | ||
| 49 | MethodEntry bridgeEntry = entry.getValue(); | ||
| 50 | if (bridgeEntry.getName().equals(accessedEntry.getName())) { | ||
| 51 | continue; | ||
| 52 | } | ||
| 53 | |||
| 54 | MethodEntry renamedAccessedEntry = accessedEntry.withName(bridgeEntry.getName()); | ||
| 55 | bridgeMethods.add(renamedAccessedEntry); | ||
| 56 | accessedToBridge.put(renamedAccessedEntry, accessedToBridge.get(accessedEntry)); | ||
| 57 | } | ||
| 58 | } | ||
| 59 | |||
| 48 | private void indexSyntheticMethod(MethodDefEntry syntheticMethod, AccessFlags access) { | 60 | private void indexSyntheticMethod(MethodDefEntry syntheticMethod, AccessFlags access) { |
| 49 | MethodEntry accessedMethod = findAccessMethod(syntheticMethod); | 61 | MethodEntry accessedMethod = findAccessMethod(syntheticMethod); |
| 50 | if (accessedMethod == null) { | 62 | if (accessedMethod == null) { |
| @@ -129,4 +141,8 @@ public class BridgeMethodIndex implements JarIndexer { | |||
| 129 | public MethodEntry getBridgeFromAccessed(MethodEntry entry) { | 141 | public MethodEntry getBridgeFromAccessed(MethodEntry entry) { |
| 130 | return accessedToBridge.get(entry); | 142 | return accessedToBridge.get(entry); |
| 131 | } | 143 | } |
| 144 | |||
| 145 | public Map<MethodEntry, MethodEntry> getAccessedToBridge() { | ||
| 146 | return Collections.unmodifiableMap(accessedToBridge); | ||
| 147 | } | ||
| 132 | } | 148 | } |
diff --git a/src/main/java/cuchaz/enigma/analysis/index/EntryIndex.java b/src/main/java/cuchaz/enigma/analysis/index/EntryIndex.java index 773eaf1..645110a 100644 --- a/src/main/java/cuchaz/enigma/analysis/index/EntryIndex.java +++ b/src/main/java/cuchaz/enigma/analysis/index/EntryIndex.java | |||
| @@ -28,6 +28,18 @@ public class EntryIndex implements JarIndexer { | |||
| 28 | fields.put(fieldEntry, fieldEntry.getAccess()); | 28 | fields.put(fieldEntry, fieldEntry.getAccess()); |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | @Override | ||
| 32 | public void processIndex(JarIndex index) { | ||
| 33 | Map<MethodEntry, MethodEntry> accessedToBridge = index.getBridgeMethodIndex().getAccessedToBridge(); | ||
| 34 | for (Map.Entry<MethodEntry, MethodEntry> entry : accessedToBridge.entrySet()) { | ||
| 35 | MethodEntry accessedEntry = entry.getKey(); | ||
| 36 | MethodEntry bridgeEntry = entry.getValue(); | ||
| 37 | |||
| 38 | MethodEntry renamedAccessedEntry = accessedEntry.withName(bridgeEntry.getName()); | ||
| 39 | methods.put(renamedAccessedEntry, methods.remove(accessedEntry)); | ||
| 40 | } | ||
| 41 | } | ||
| 42 | |||
| 31 | public boolean hasClass(ClassEntry entry) { | 43 | public boolean hasClass(ClassEntry entry) { |
| 32 | return classes.containsKey(entry); | 44 | return classes.containsKey(entry); |
| 33 | } | 45 | } |
diff --git a/src/main/java/cuchaz/enigma/analysis/index/JarIndex.java b/src/main/java/cuchaz/enigma/analysis/index/JarIndex.java index cb58fce..a429ff6 100644 --- a/src/main/java/cuchaz/enigma/analysis/index/JarIndex.java +++ b/src/main/java/cuchaz/enigma/analysis/index/JarIndex.java | |||
| @@ -53,19 +53,22 @@ public class JarIndex implements JarIndexer { | |||
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | public void indexJar(ParsedJar jar, Consumer<String> progress) { | 55 | public void indexJar(ParsedJar jar, Consumer<String> progress) { |
| 56 | progress.accept("Indexing entries (1/3)"); | 56 | progress.accept("Indexing entries (1/4)"); |
| 57 | jar.visitReader(name -> new IndexClassVisitor(this, Opcodes.ASM5), ClassReader.SKIP_CODE); | 57 | jar.visitReader(name -> new IndexClassVisitor(this, Opcodes.ASM5), ClassReader.SKIP_CODE); |
| 58 | 58 | ||
| 59 | progress.accept("Indexing entry references (2/3)"); | 59 | progress.accept("Indexing entry references (2/4)"); |
| 60 | jar.visitReader(name -> new IndexReferenceVisitor(this, Opcodes.ASM5), ClassReader.SKIP_FRAMES); | 60 | jar.visitReader(name -> new IndexReferenceVisitor(this, Opcodes.ASM5), ClassReader.SKIP_FRAMES); |
| 61 | 61 | ||
| 62 | progress.accept("Processing index (3/3)"); | 62 | progress.accept("Finding bridge methods (3/4)"); |
| 63 | processIndex(entryResolver); | 63 | bridgeMethodIndex.findBridgeMethods(); |
| 64 | |||
| 65 | progress.accept("Processing index (4/4)"); | ||
| 66 | processIndex(this); | ||
| 64 | } | 67 | } |
| 65 | 68 | ||
| 66 | @Override | 69 | @Override |
| 67 | public void processIndex(EntryResolver resolver) { | 70 | public void processIndex(JarIndex index) { |
| 68 | indexers.forEach(indexer -> indexer.processIndex(entryResolver)); | 71 | indexers.forEach(indexer -> indexer.processIndex(index)); |
| 69 | } | 72 | } |
| 70 | 73 | ||
| 71 | @Override | 74 | @Override |
diff --git a/src/main/java/cuchaz/enigma/analysis/index/JarIndexer.java b/src/main/java/cuchaz/enigma/analysis/index/JarIndexer.java index a087e59..457c223 100644 --- a/src/main/java/cuchaz/enigma/analysis/index/JarIndexer.java +++ b/src/main/java/cuchaz/enigma/analysis/index/JarIndexer.java | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | package cuchaz.enigma.analysis.index; | 1 | package cuchaz.enigma.analysis.index; |
| 2 | 2 | ||
| 3 | import cuchaz.enigma.translation.mapping.EntryResolver; | ||
| 4 | import cuchaz.enigma.translation.representation.entry.*; | 3 | import cuchaz.enigma.translation.representation.entry.*; |
| 5 | 4 | ||
| 6 | public interface JarIndexer { | 5 | public interface JarIndexer { |
| @@ -19,6 +18,6 @@ public interface JarIndexer { | |||
| 19 | default void indexFieldReference(MethodDefEntry callerEntry, FieldEntry referencedEntry) { | 18 | default void indexFieldReference(MethodDefEntry callerEntry, FieldEntry referencedEntry) { |
| 20 | } | 19 | } |
| 21 | 20 | ||
| 22 | default void processIndex(EntryResolver resolver) { | 21 | default void processIndex(JarIndex index) { |
| 23 | } | 22 | } |
| 24 | } | 23 | } |
diff --git a/src/main/java/cuchaz/enigma/analysis/index/ReferenceIndex.java b/src/main/java/cuchaz/enigma/analysis/index/ReferenceIndex.java index ac11da4..ee28b3e 100644 --- a/src/main/java/cuchaz/enigma/analysis/index/ReferenceIndex.java +++ b/src/main/java/cuchaz/enigma/analysis/index/ReferenceIndex.java | |||
| @@ -3,12 +3,12 @@ package cuchaz.enigma.analysis.index; | |||
| 3 | import com.google.common.collect.HashMultimap; | 3 | import com.google.common.collect.HashMultimap; |
| 4 | import com.google.common.collect.Multimap; | 4 | import com.google.common.collect.Multimap; |
| 5 | import cuchaz.enigma.analysis.EntryReference; | 5 | import cuchaz.enigma.analysis.EntryReference; |
| 6 | import cuchaz.enigma.translation.mapping.EntryResolver; | ||
| 7 | import cuchaz.enigma.translation.mapping.ResolutionStrategy; | 6 | import cuchaz.enigma.translation.mapping.ResolutionStrategy; |
| 8 | import cuchaz.enigma.translation.representation.entry.*; | 7 | import cuchaz.enigma.translation.representation.entry.*; |
| 9 | 8 | ||
| 10 | import java.util.Collection; | 9 | import java.util.Collection; |
| 11 | import java.util.Map; | 10 | import java.util.Map; |
| 11 | import java.util.Optional; | ||
| 12 | 12 | ||
| 13 | public class ReferenceIndex implements JarIndexer { | 13 | public class ReferenceIndex implements JarIndexer { |
| 14 | private Multimap<MethodEntry, MethodEntry> methodReferences = HashMultimap.create(); | 14 | private Multimap<MethodEntry, MethodEntry> methodReferences = HashMultimap.create(); |
| @@ -34,35 +34,54 @@ public class ReferenceIndex implements JarIndexer { | |||
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | @Override | 36 | @Override |
| 37 | public void processIndex(EntryResolver resolver) { | 37 | public void processIndex(JarIndex index) { |
| 38 | methodReferences = resolveReferences(resolver, methodReferences); | 38 | methodReferences = remapReferences(index, methodReferences); |
| 39 | referencesToMethods = resolveReferencesTo(resolver, referencesToMethods); | 39 | referencesToMethods = remapReferencesTo(index, referencesToMethods); |
| 40 | referencesToClasses = resolveReferencesTo(resolver, referencesToClasses); | 40 | referencesToClasses = remapReferencesTo(index, referencesToClasses); |
| 41 | referencesToFields = resolveReferencesTo(resolver, referencesToFields); | 41 | referencesToFields = remapReferencesTo(index, referencesToFields); |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | private <K extends Entry<?>, V extends Entry<?>> Multimap<K, V> resolveReferences(EntryResolver resolver, Multimap<K, V> multimap) { | 44 | private <K extends Entry<?>, V extends Entry<?>> Multimap<K, V> remapReferences(JarIndex index, Multimap<K, V> multimap) { |
| 45 | Multimap<K, V> resolved = HashMultimap.create(); | 45 | Multimap<K, V> resolved = HashMultimap.create(); |
| 46 | for (Map.Entry<K, V> entry : multimap.entries()) { | 46 | for (Map.Entry<K, V> entry : multimap.entries()) { |
| 47 | resolved.put(resolve(resolver, entry.getKey()), resolve(resolver, entry.getValue())); | 47 | resolved.put(remap(index, entry.getKey()), remap(index, entry.getValue())); |
| 48 | } | 48 | } |
| 49 | return resolved; | 49 | return resolved; |
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | private <E extends Entry<?>, C extends Entry<?>> Multimap<E, EntryReference<E, C>> resolveReferencesTo(EntryResolver resolver, Multimap<E, EntryReference<E, C>> multimap) { | 52 | private <E extends Entry<?>, C extends Entry<?>> Multimap<E, EntryReference<E, C>> remapReferencesTo(JarIndex index, Multimap<E, EntryReference<E, C>> multimap) { |
| 53 | Multimap<E, EntryReference<E, C>> resolved = HashMultimap.create(); | 53 | Multimap<E, EntryReference<E, C>> resolved = HashMultimap.create(); |
| 54 | for (Map.Entry<E, EntryReference<E, C>> entry : multimap.entries()) { | 54 | for (Map.Entry<E, EntryReference<E, C>> entry : multimap.entries()) { |
| 55 | resolved.put(resolve(resolver, entry.getKey()), resolve(resolver, entry.getValue())); | 55 | resolved.put(remap(index, entry.getKey()), remap(index, entry.getValue())); |
| 56 | } | 56 | } |
| 57 | return resolved; | 57 | return resolved; |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | private <E extends Entry<?>> E resolve(EntryResolver resolver, E entry) { | 60 | private <E extends Entry<?>> E remap(JarIndex index, E entry) { |
| 61 | return resolver.resolveFirstEntry(entry, ResolutionStrategy.RESOLVE_CLOSEST); | 61 | E resolvedEntry = index.getEntryResolver().resolveFirstEntry(entry, ResolutionStrategy.RESOLVE_CLOSEST); |
| 62 | |||
| 63 | Optional<E> remappedBridge = getRemappedBridge(index, resolvedEntry); | ||
| 64 | return remappedBridge.orElse(resolvedEntry); | ||
| 65 | } | ||
| 66 | |||
| 67 | private <E extends Entry<?>, C extends Entry<?>> EntryReference<E, C> remap(JarIndex index, EntryReference<E, C> reference) { | ||
| 68 | EntryReference<E, C> resolvedReference = index.getEntryResolver().resolveFirstReference(reference, ResolutionStrategy.RESOLVE_CLOSEST); | ||
| 69 | |||
| 70 | getRemappedBridge(index, resolvedReference.entry).ifPresent(e -> resolvedReference.entry = e); | ||
| 71 | getRemappedBridge(index, resolvedReference.context).ifPresent(e -> resolvedReference.context = e); | ||
| 72 | |||
| 73 | return resolvedReference; | ||
| 62 | } | 74 | } |
| 63 | 75 | ||
| 64 | private <E extends Entry<?>, C extends Entry<?>> EntryReference<E, C> resolve(EntryResolver resolver, EntryReference<E, C> reference) { | 76 | @SuppressWarnings("unchecked") |
| 65 | return resolver.resolveFirstReference(reference, ResolutionStrategy.RESOLVE_CLOSEST); | 77 | private <E extends Entry<?>> Optional<E> getRemappedBridge(JarIndex index, E entry) { |
| 78 | if (entry instanceof MethodEntry) { | ||
| 79 | MethodEntry bridgeEntry = index.getBridgeMethodIndex().getBridgeFromAccessed((MethodEntry) entry); | ||
| 80 | if (bridgeEntry != null) { | ||
| 81 | return Optional.of((E) entry.withName(bridgeEntry.getName())); | ||
| 82 | } | ||
| 83 | } | ||
| 84 | return Optional.empty(); | ||
| 66 | } | 85 | } |
| 67 | 86 | ||
| 68 | public Collection<MethodEntry> getMethodsReferencedBy(MethodEntry entry) { | 87 | public Collection<MethodEntry> getMethodsReferencedBy(MethodEntry entry) { |