Merge "Add support for getting method and field signatures in DexInspector"
diff --git a/src/test/java/com/android/tools/r8/utils/DexInspector.java b/src/test/java/com/android/tools/r8/utils/DexInspector.java
index 38de25e..e7e882a 100644
--- a/src/test/java/com/android/tools/r8/utils/DexInspector.java
+++ b/src/test/java/com/android/tools/r8/utils/DexInspector.java
@@ -56,6 +56,7 @@
 import com.android.tools.r8.dex.ApplicationReader;
 import com.android.tools.r8.graph.DexAnnotation;
 import com.android.tools.r8.graph.DexAnnotationElement;
+import com.android.tools.r8.graph.DexAnnotationSet;
 import com.android.tools.r8.graph.DexApplication;
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexCode;
@@ -92,6 +93,7 @@
 import java.util.List;
 import java.util.NoSuchElementException;
 import java.util.concurrent.ExecutionException;
+import java.util.function.BiConsumer;
 import java.util.function.BiFunction;
 import java.util.function.Consumer;
 import java.util.function.Function;
@@ -198,6 +200,50 @@
     }
   }
 
+  DexAnnotation findAnnotation(String name, DexAnnotationSet annotations) {
+    for (DexAnnotation annotation : annotations.annotations) {
+      DexType type = annotation.annotation.type;
+      String original = mapping == null ? type.toSourceString() : mapping.originalNameOf(type);
+      if (original.equals(name)) {
+        return annotation;
+      }
+    }
+    return null;
+  }
+
+  public String getFinalSignatureAttribute(DexAnnotationSet annotations) {
+    DexAnnotation annotation =
+        findAnnotation("dalvik.annotation.Signature", annotations);
+    if (annotation == null) {
+      return null;
+    }
+    assert annotation.annotation.elements.length == 1;
+    DexAnnotationElement element = annotation.annotation.elements[0];
+    assert element.value instanceof DexValueArray;
+    StringBuilder builder = new StringBuilder();
+    DexValueArray valueArray = (DexValueArray) element.value;
+    for (DexValue value : valueArray.getValues()) {
+      assertTrue(value instanceof DexValueString);
+      DexValueString s = (DexValueString) value;
+      builder.append(s.getValue());
+    }
+    return builder.toString();
+  }
+
+  public String getOriginalSignatureAttribute(
+      DexAnnotationSet annotations, BiConsumer<GenericSignatureParser, String> parse) {
+    String finalSignature = getFinalSignatureAttribute(annotations);
+    if (finalSignature == null || mapping == null) {
+      return finalSignature;
+    }
+
+    GenericSignatureGenerater rewriter = new GenericSignatureGenerater();
+    GenericSignatureParser<String> parser = new GenericSignatureParser<>(rewriter);
+    parse.accept(parser, finalSignature);
+    return rewriter.getSignature();
+  }
+
+
   public ClassSubject clazz(Class clazz) {
     return clazz(clazz.getTypeName());
   }
@@ -582,23 +628,12 @@
       assert !name.endsWith("EnclosingClass")
           && !name.endsWith("EnclosingMethod")
           && !name.endsWith("InnerClass");
-      DexAnnotation annotation = findAnnotation(name);
+      DexAnnotation annotation = findAnnotation(name, dexClass.annotations);
       return annotation == null
           ? new AbsentAnnotationSubject()
           : new FoundAnnotationSubject(annotation);
     }
 
-    private DexAnnotation findAnnotation(String name) {
-      for (DexAnnotation annotation : dexClass.annotations.annotations) {
-        DexType type = annotation.annotation.type;
-        String original = mapping == null ? type.toSourceString() : mapping.originalNameOf(type);
-        if (original.equals(name)) {
-          return annotation;
-        }
-      }
-      return null;
-    }
-
     @Override
     public String getOriginalName() {
       if (naming != null) {
@@ -663,94 +698,13 @@
 
     @Override
     public String getOriginalSignatureAttribute() {
-      // Build the generic signature using the current mapping if any.
-      class GenericSignatureGenerater implements GenericSignatureAction<String> {
-
-        private StringBuilder signature;
-
-        public String getSignature() {
-          return signature.toString();
-        }
-
-        @Override
-        public void parsedSymbol(char symbol) {
-          signature.append(symbol);
-        }
-
-        @Override
-        public void parsedIdentifier(String identifier) {
-          signature.append(identifier);
-        }
-
-        @Override
-        public String parsedTypeName(String name) {
-          String type = name;
-          if (originalToObfuscatedMapping != null) {
-            String original = originalToObfuscatedMapping.inverse().get(name);
-            type = original != null ? original : name;
-          }
-          signature.append(type);
-          return type;
-        }
-
-        @Override
-        public String parsedInnerTypeName(String enclosingType, String name) {
-          if (originalToObfuscatedMapping != null) {
-            // The enclosingType has already been mapped if a mapping is present.
-            String minifiedEnclosing = originalToObfuscatedMapping.get(enclosingType);
-            String type = originalToObfuscatedMapping.inverse().get(minifiedEnclosing + "$" + name);
-            if (type != null) {
-              assert type.startsWith(enclosingType + "$");
-              name = type.substring(enclosingType.length() + 1);
-            }
-            signature.append(name);
-            return type;
-          } else {
-            String type = enclosingType + "$" + name;
-            signature.append(name);
-            return type;
-          }
-        }
-
-        @Override
-        public void start() {
-          signature = new StringBuilder();
-        }
-
-        @Override
-        public void stop() {
-          // nothing to do
-        }
-      }
-
-      String finalSignature = getFinalSignatureAttribute();
-      if (finalSignature == null || mapping == null) {
-        return finalSignature;
-      }
-
-      GenericSignatureGenerater rewriter = new GenericSignatureGenerater();
-      GenericSignatureParser<String> parser = new GenericSignatureParser<>(rewriter);
-      parser.parseClassSignature(finalSignature);
-      return rewriter.getSignature();
+      return DexInspector.this.getOriginalSignatureAttribute(
+          dexClass.annotations, GenericSignatureParser::parseClassSignature);
     }
 
     @Override
     public String getFinalSignatureAttribute() {
-      DexAnnotation annotation = findAnnotation("dalvik.annotation.Signature");
-      if (annotation == null) {
-        return null;
-      }
-      assert annotation.annotation.elements.length == 1;
-      DexAnnotationElement element = annotation.annotation.elements[0];
-      assert element.value instanceof DexValueArray;
-      StringBuilder builder = new StringBuilder();
-      DexValueArray valueArray = (DexValueArray) element.value;
-      for (DexValue value : valueArray.getValues()) {
-        assertTrue(value instanceof DexValueString);
-        DexValueString s = (DexValueString) value;
-        builder.append(s.getValue());
-      }
-      return builder.toString();
+      return DexInspector.this.getFinalSignatureAttribute(dexClass.annotations);
     }
 
     @Override
@@ -790,6 +744,10 @@
 
     public abstract boolean isClassInitializer();
 
+    public abstract String getOriginalSignatureAttribute();
+
+    public abstract String getFinalSignatureAttribute();
+
     public abstract DexEncodedMethod getMethod();
 
     public Iterator<InstructionSubject> iterateInstructions() {
@@ -858,6 +816,16 @@
     public Signature getFinalSignature() {
       return null;
     }
+
+    @Override
+    public String getOriginalSignatureAttribute() {
+      return null;
+    }
+
+    @Override
+    public String getFinalSignatureAttribute() {
+      return null;
+    }
   }
 
   public class FoundMethodSubject extends MethodSubject {
@@ -930,6 +898,17 @@
     }
 
     @Override
+    public String getOriginalSignatureAttribute() {
+      return DexInspector.this.getOriginalSignatureAttribute(
+          dexMethod.annotations, GenericSignatureParser::parseMethodSignature);
+    }
+
+    @Override
+    public String getFinalSignatureAttribute() {
+      return DexInspector.this.getFinalSignatureAttribute(dexMethod.annotations);
+    }
+
+    @Override
     public Iterator<InstructionSubject> iterateInstructions() {
       return new InstructionIterator(this);
     }
@@ -954,6 +933,10 @@
     public abstract DexValue getStaticValue();
 
     public abstract boolean isRenamed();
+
+    public abstract String getOriginalSignatureAttribute();
+
+    public abstract String getFinalSignatureAttribute();
   }
 
   public class AbsentFieldSubject extends FieldSubject {
@@ -1002,6 +985,16 @@
     public DexEncodedField getField() {
       return null;
     }
+
+    @Override
+    public String getOriginalSignatureAttribute() {
+      return null;
+    }
+
+    @Override
+    public String getFinalSignatureAttribute() {
+      return null;
+    }
   }
 
   public class FoundFieldSubject extends FieldSubject {
@@ -1069,6 +1062,17 @@
     }
 
     @Override
+    public String getOriginalSignatureAttribute() {
+      return DexInspector.this.getOriginalSignatureAttribute(
+          dexField.annotations, GenericSignatureParser::parseFieldSignature);
+    }
+
+    @Override
+    public String getFinalSignatureAttribute() {
+      return DexInspector.this.getFinalSignatureAttribute(dexField.annotations);
+    }
+
+    @Override
     public String toString() {
       return dexField.toSourceString();
     }
@@ -1523,4 +1527,63 @@
       return result;
     }
   }
+
+  // Build the generic signature using the current mapping if any.
+  class GenericSignatureGenerater implements GenericSignatureAction<String> {
+
+    private StringBuilder signature;
+
+    public String getSignature() {
+      return signature.toString();
+    }
+
+    @Override
+    public void parsedSymbol(char symbol) {
+      signature.append(symbol);
+    }
+
+    @Override
+    public void parsedIdentifier(String identifier) {
+      signature.append(identifier);
+    }
+
+    @Override
+    public String parsedTypeName(String name) {
+      String type = name;
+      if (originalToObfuscatedMapping != null) {
+        String original = originalToObfuscatedMapping.inverse().get(name);
+        type = original != null ? original : name;
+      }
+      signature.append(type);
+      return type;
+    }
+
+    @Override
+    public String parsedInnerTypeName(String enclosingType, String name) {
+      String type;
+      if (originalToObfuscatedMapping != null) {
+        // The enclosingType has already been mapped if a mapping is present.
+        String minifiedEnclosing = originalToObfuscatedMapping.get(enclosingType);
+        type = originalToObfuscatedMapping.inverse().get(minifiedEnclosing + "$" + name);
+        if (type != null) {
+          assert type.startsWith(enclosingType + "$");
+          name = type.substring(enclosingType.length() + 1);
+        }
+      } else {
+        type = enclosingType + "$" + name;
+      }
+      signature.append(name);
+      return type;
+    }
+
+    @Override
+    public void start() {
+      signature = new StringBuilder();
+    }
+
+    @Override
+    public void stop() {
+      // nothing to do
+    }
+  }
 }