aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/com/android/tools/r8/naming/ClassNamingForMapApplier.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/android/tools/r8/naming/ClassNamingForMapApplier.java')
-rw-r--r--src/main/java/com/android/tools/r8/naming/ClassNamingForMapApplier.java193
1 files changed, 193 insertions, 0 deletions
diff --git a/src/main/java/com/android/tools/r8/naming/ClassNamingForMapApplier.java b/src/main/java/com/android/tools/r8/naming/ClassNamingForMapApplier.java
new file mode 100644
index 000000000..d94fe57c0
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/naming/ClassNamingForMapApplier.java
@@ -0,0 +1,193 @@
+// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.naming;
+
+import com.android.tools.r8.graph.DexField;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.naming.MemberNaming.FieldSignature;
+import com.android.tools.r8.naming.MemberNaming.MethodSignature;
+import com.android.tools.r8.naming.MemberNaming.Signature;
+import com.android.tools.r8.naming.MemberNaming.Signature.SignatureKind;
+import com.android.tools.r8.utils.ThrowingConsumer;
+import com.google.common.collect.ImmutableMap;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Stores name information for a class.
+ * <p>
+ * The main differences of this against {@link ClassNamingForNameMapper} are:
+ * 1) field and method mappings are maintained and searched separately for faster lookup;
+ * 2) similar to the relation between {@link ClassNameMapper} and {@link SeedMapper}, this one
+ * uses original {@link Signature} as a key to look up {@link MemberNaming},
+ * whereas {@link ClassNamingForNameMapper} uses renamed {@link Signature} as a key; and thus
+ * 3) logic of {@link #lookup} and {@link #lookupByOriginalSignature} are inverted; and
+ * 4) {@link #lookupByOriginalItem}'s are introduced for lightweight lookup.
+ */
+public class ClassNamingForMapApplier implements ClassNaming {
+
+ public static class Builder extends ClassNaming.Builder {
+ private final String originalName;
+ private final String renamedName;
+ private final Map<MethodSignature, MemberNaming> methodMembers = new HashMap<>();
+ private final Map<FieldSignature, MemberNaming> fieldMembers = new HashMap<>();
+
+ private Builder(String renamedName, String originalName) {
+ this.originalName = originalName;
+ this.renamedName = renamedName;
+ }
+
+ @Override
+ ClassNaming.Builder addMemberEntry(MemberNaming entry) {
+ // Unlike {@link ClassNamingForNameMapper.Builder#addMemberEntry},
+ // the key is original signature.
+ if (entry.isMethodNaming()) {
+ methodMembers.put((MethodSignature) entry.getOriginalSignature(), entry);
+ } else {
+ fieldMembers.put((FieldSignature) entry.getOriginalSignature(), entry);
+ }
+ return this;
+ }
+
+ @Override
+ ClassNamingForMapApplier build() {
+ return new ClassNamingForMapApplier(renamedName, originalName, methodMembers, fieldMembers);
+ }
+ }
+
+ static Builder builder(String renamedName, String originalName) {
+ return new Builder(renamedName, originalName);
+ }
+
+ private final String originalName;
+ final String renamedName;
+
+ private final ImmutableMap<MethodSignature, MemberNaming> methodMembers;
+ private final ImmutableMap<FieldSignature, MemberNaming> fieldMembers;
+
+ // Constructor to help chaining {@link ClassNamingForMapApplier} according to class hierarchy.
+ ClassNamingForMapApplier(ClassNamingForMapApplier proxy) {
+ this(proxy.renamedName, proxy.originalName, proxy.methodMembers, proxy.fieldMembers);
+ }
+
+ private ClassNamingForMapApplier(
+ String renamedName,
+ String originalName,
+ Map<MethodSignature, MemberNaming> methodMembers,
+ Map<FieldSignature, MemberNaming> fieldMembers) {
+ this.renamedName = renamedName;
+ this.originalName = originalName;
+ this.methodMembers = ImmutableMap.copyOf(methodMembers);
+ this.fieldMembers = ImmutableMap.copyOf(fieldMembers);
+ }
+
+ @Override
+ public <T extends Throwable> void forAllMemberNaming(
+ ThrowingConsumer<MemberNaming, T> consumer) throws T {
+ forAllFieldNaming(consumer);
+ forAllMethodNaming(consumer);
+ }
+
+ @Override
+ public <T extends Throwable> void forAllFieldNaming(
+ ThrowingConsumer<MemberNaming, T> consumer) throws T {
+ for (MemberNaming naming : fieldMembers.values()) {
+ consumer.accept(naming);
+ }
+ }
+
+ @Override
+ public <T extends Throwable> void forAllMethodNaming(
+ ThrowingConsumer<MemberNaming, T> consumer) throws T {
+ for (MemberNaming naming : methodMembers.values()) {
+ consumer.accept(naming);
+ }
+ }
+
+ @Override
+ public MemberNaming lookup(Signature renamedSignature) {
+ // As the key is inverted, this looks a lot like
+ // {@link ClassNamingForNameMapper#lookupByOriginalSignature}.
+ if (renamedSignature.kind() == SignatureKind.METHOD) {
+ for (MemberNaming memberNaming : methodMembers.values()) {
+ if (memberNaming.getRenamedSignature().equals(renamedSignature)) {
+ return memberNaming;
+ }
+ }
+ return null;
+ } else {
+ assert renamedSignature.kind() == SignatureKind.FIELD;
+ for (MemberNaming memberNaming : fieldMembers.values()) {
+ if (memberNaming.getRenamedSignature().equals(renamedSignature)) {
+ return memberNaming;
+ }
+ }
+ return null;
+ }
+ }
+
+ @Override
+ public MemberNaming lookupByOriginalSignature(Signature original) {
+ // As the key is inverted, this looks a lot like {@link ClassNamingForNameMapper#lookup}.
+ if (original.kind() == SignatureKind.METHOD) {
+ return methodMembers.get(original);
+ } else {
+ assert original.kind() == SignatureKind.FIELD;
+ return fieldMembers.get(original);
+ }
+ }
+
+ MemberNaming lookupByOriginalItem(DexField field) {
+ for (Map.Entry<FieldSignature, MemberNaming> entry : fieldMembers.entrySet()) {
+ FieldSignature signature = entry.getKey();
+ if (signature.name.equals(field.name.toString())
+ && signature.type.equals(field.type.getName())) {
+ return entry.getValue();
+ }
+ }
+ return null;
+ }
+
+ protected MemberNaming lookupByOriginalItem(DexMethod method) {
+ for (Map.Entry<MethodSignature, MemberNaming> entry : methodMembers.entrySet()) {
+ MethodSignature signature = entry.getKey();
+ if (signature.name.equals(method.name.toString())
+ && signature.type.equals(method.proto.returnType.toString())
+ && Arrays.equals(signature.parameters,
+ Arrays.stream(method.proto.parameters.values)
+ .map(DexType::toString).toArray(String[]::new))) {
+ return entry.getValue();
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof ClassNamingForMapApplier)) {
+ return false;
+ }
+
+ ClassNamingForMapApplier that = (ClassNamingForMapApplier) o;
+
+ return originalName.equals(that.originalName)
+ && renamedName.equals(that.renamedName)
+ && methodMembers.equals(that.methodMembers)
+ && fieldMembers.equals(that.fieldMembers);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = originalName.hashCode();
+ result = 31 * result + renamedName.hashCode();
+ result = 31 * result + methodMembers.hashCode();
+ result = 31 * result + fieldMembers.hashCode();
+ return result;
+ }
+}