Base clean up of parsing generic signatures

Bug: 129925954
Change-Id: I59f165cf87b7fb10f8b5dde9e7e647c71f3a0807
diff --git a/src/main/java/com/android/tools/r8/graph/GenericSignature.java b/src/main/java/com/android/tools/r8/graph/GenericSignature.java
index beb391d..2427913 100644
--- a/src/main/java/com/android/tools/r8/graph/GenericSignature.java
+++ b/src/main/java/com/android/tools/r8/graph/GenericSignature.java
@@ -7,13 +7,13 @@
 import static com.android.tools.r8.utils.DescriptorUtils.getDescriptorFromClassBinaryName;
 
 import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.utils.DescriptorUtils;
+import com.android.tools.r8.utils.Reporter;
 import com.google.common.collect.ImmutableList;
 import java.lang.reflect.GenericSignatureFormatError;
 import java.nio.CharBuffer;
 import java.util.List;
-import java.util.function.Function;
 
 /**
  * Internal encoding of the generics signature attribute as defined by JVMS 7 $ 4.3.4.
@@ -95,29 +95,33 @@
  */
 public class GenericSignature {
 
-  private static final List<FormalTypeParameter> EMPTY_TYPE_PARAMS = ImmutableList.of();
+  static final List<FormalTypeParameter> EMPTY_TYPE_PARAMS = ImmutableList.of();
+  static final List<FieldTypeSignature> EMPTY_TYPE_ARGUMENTS = ImmutableList.of();
+  static final List<ClassTypeSignature> EMPTY_SUPER_INTERFACES = ImmutableList.of();
+  static final List<TypeSignature> EMPTY_TYPE_SIGNATURES = ImmutableList.of();
 
   interface DexDefinitionSignature<T extends DexDefinition> {
+
     default boolean isClassSignature() {
       return false;
     }
 
+    default boolean isFieldTypeSignature() {
+      return false;
+    }
+
+    default boolean isMethodTypeSignature() {
+      return false;
+    }
+
     default ClassSignature asClassSignature() {
       return null;
     }
 
-    default boolean isFieldTypeSignature() {
-      return false;
-    }
-
     default FieldTypeSignature asFieldTypeSignature() {
       return null;
     }
 
-    default boolean isMethodTypeSignature() {
-      return false;
-    }
-
     default MethodTypeSignature asMethodTypeSignature() {
       return null;
     }
@@ -147,14 +151,22 @@
     public List<FieldTypeSignature> getInterfaceBounds() {
       return interfaceBounds;
     }
+
+    public void visit(GenericSignatureVisitor visitor) {
+      visitor.visitClassBound(classBound);
+      if (interfaceBounds == null) {
+        return;
+      }
+      for (FieldTypeSignature interfaceBound : interfaceBounds) {
+        visitor.visitInterfaceBound(interfaceBound);
+      }
+    }
   }
 
   public static class ClassSignature implements DexDefinitionSignature<DexClass> {
-    static final ClassSignature UNKNOWN_CLASS_SIGNATURE =
-        new ClassSignature(
-            ImmutableList.of(),
-            ClassTypeSignature.UNKNOWN_CLASS_TYPE_SIGNATURE,
-            ImmutableList.of());
+
+    public static final ClassSignature NO_CLASS_SIGNATURE =
+        new ClassSignature(EMPTY_TYPE_PARAMS, NO_FIELD_TYPE_SIGNATURE, EMPTY_SUPER_INTERFACES);
 
     final List<FormalTypeParameter> formalTypeParameters;
     final ClassTypeSignature superClassSignature;
@@ -180,6 +192,14 @@
       return superInterfaceSignatures;
     }
 
+    public boolean hasSignature() {
+      return this != NO_CLASS_SIGNATURE;
+    }
+
+    public boolean hasNoSignature() {
+      return !hasSignature();
+    }
+
     @Override
     public boolean isClassSignature() {
       return true;
@@ -189,9 +209,18 @@
     public ClassSignature asClassSignature() {
       return this;
     }
+
+    public void visit(GenericSignatureVisitor visitor) {
+      visitor.visitFormalTypeParameters(formalTypeParameters);
+      visitor.visitSuperClass(superClassSignature);
+      for (ClassTypeSignature superInterface : superInterfaceSignatures) {
+        visitor.visitSuperInterface(superInterface);
+      }
+    }
   }
 
   public abstract static class TypeSignature {
+
     public boolean isFieldTypeSignature() {
       return false;
     }
@@ -208,11 +237,7 @@
       return null;
     }
 
-    public TypeSignature toArrayTypeSignature(AppView<?> appView) {
-      return null;
-    }
-
-    public TypeSignature toArrayElementTypeSignature(AppView<?> appView) {
+    public ArrayTypeSignature toArrayTypeSignature() {
       return null;
     }
   }
@@ -275,8 +300,8 @@
       return null;
     }
 
-    public boolean isUnknown() {
-      return this == ClassTypeSignature.UNKNOWN_CLASS_TYPE_SIGNATURE;
+    public boolean hasSignature() {
+      return this != GenericSignature.NO_FIELD_TYPE_SIGNATURE;
     }
 
     public abstract FieldTypeSignature asArgument(WildcardIndicator indicator);
@@ -286,10 +311,9 @@
     }
   }
 
-  private static final class StarFieldTypeSignature extends FieldTypeSignature {
+  static final class StarFieldTypeSignature extends FieldTypeSignature {
 
-    private static final StarFieldTypeSignature STAR_FIELD_TYPE_SIGNATURE =
-        new StarFieldTypeSignature();
+    static final StarFieldTypeSignature STAR_FIELD_TYPE_SIGNATURE = new StarFieldTypeSignature();
 
     private StarFieldTypeSignature() {
       super(WildcardIndicator.NONE);
@@ -306,11 +330,13 @@
     }
   }
 
+  public static final ClassTypeSignature NO_FIELD_TYPE_SIGNATURE =
+      new ClassTypeSignature(DexItemFactory.nullValueType, EMPTY_TYPE_ARGUMENTS);
+
   public static class ClassTypeSignature extends FieldTypeSignature {
-    static final ClassTypeSignature UNKNOWN_CLASS_TYPE_SIGNATURE =
-        new ClassTypeSignature(DexItemFactory.nullValueType, ImmutableList.of());
 
     final DexType type;
+
     // E.g., for Map<K, V>, a signature will indicate what types are for K and V.
     // Note that this could be nested, e.g., Map<K, Consumer<V>>.
     final List<FieldTypeSignature> typeArguments;
@@ -361,8 +387,12 @@
       return argument;
     }
 
+    public boolean isNoSignature() {
+      return this == NO_FIELD_TYPE_SIGNATURE;
+    }
+
     @Override
-    public ArrayTypeSignature toArrayTypeSignature(AppView<?> appView) {
+    public ArrayTypeSignature toArrayTypeSignature() {
       return new ArrayTypeSignature(this);
     }
 
@@ -371,6 +401,13 @@
       outer.innerTypeSignature = inner;
       inner.enclosingTypeSignature = outer;
     }
+
+    public void visit(GenericSignatureVisitor visitor) {
+      visitor.visitTypeArguments(typeArguments);
+      if (innerTypeSignature != null) {
+        visitor.visitSimpleClass(innerTypeSignature);
+      }
+    }
   }
 
   public static class ArrayTypeSignature extends FieldTypeSignature {
@@ -408,13 +445,12 @@
     }
 
     @Override
-    public TypeSignature toArrayTypeSignature(AppView<?> appView) {
+    public ArrayTypeSignature toArrayTypeSignature() {
       return new ArrayTypeSignature(this);
     }
 
-    @Override
-    public TypeSignature toArrayElementTypeSignature(AppView<?> appView) {
-      return elementSignature;
+    public void visit(GenericSignatureVisitor visitor) {
+      visitor.visitTypeSignature(elementSignature);
     }
   }
 
@@ -449,7 +485,7 @@
     }
 
     @Override
-    public ArrayTypeSignature toArrayTypeSignature(AppView<?> appView) {
+    public ArrayTypeSignature toArrayTypeSignature() {
       return new ArrayTypeSignature(this);
     }
 
@@ -479,7 +515,7 @@
     }
 
     @Override
-    public ArrayTypeSignature toArrayTypeSignature(AppView<?> appView) {
+    public ArrayTypeSignature toArrayTypeSignature() {
       assert !type.isVoidType();
       return new ArrayTypeSignature(this);
     }
@@ -505,9 +541,10 @@
   }
 
   public static class MethodTypeSignature implements DexDefinitionSignature<DexEncodedMethod> {
-    static final MethodTypeSignature UNKNOWN_METHOD_TYPE_SIGNATURE =
+
+    public static final MethodTypeSignature NO_METHOD_TYPE_SIGNATURE =
         new MethodTypeSignature(
-            ImmutableList.of(), ImmutableList.of(), ReturnType.VOID, ImmutableList.of());
+            EMPTY_TYPE_PARAMS, EMPTY_TYPE_SIGNATURES, ReturnType.VOID, EMPTY_TYPE_SIGNATURES);
 
     final List<FormalTypeParameter> formalTypeParameters;
     final List<TypeSignature> typeSignatures;
@@ -549,110 +586,82 @@
       return true;
     }
 
+    public boolean hasSignature() {
+      return this != NO_METHOD_TYPE_SIGNATURE;
+    }
+
     @Override
     public MethodTypeSignature asMethodTypeSignature() {
       return this;
     }
 
+    public void visit(GenericSignatureVisitor visitor) {
+      visitor.visitFormalTypeParameters(formalTypeParameters);
+      visitor.visitMethodTypeSignatures(typeSignatures);
+      visitor.visitReturnType(returnType);
+      visitor.visitThrowsSignatures(throwsSignatures);
+    }
+
     public List<FormalTypeParameter> getFormalTypeParameters() {
       return formalTypeParameters;
     }
   }
 
-  enum Kind {
-    CLASS, FIELD, METHOD;
-
-    static Kind fromDexDefinition(DexDefinition definition) {
-      if (definition.isDexClass()) {
-        return CLASS;
-      }
-      if (definition.isDexEncodedField()) {
-        return FIELD;
-      }
-      if (definition.isDexEncodedMethod()) {
-        return METHOD;
-      }
-      throw new Unreachable("Unexpected kind of DexDefinition: " + definition);
+  public static ClassSignature parseClassSignature(
+      String className,
+      String signature,
+      Origin origin,
+      DexItemFactory factory,
+      Reporter reporter) {
+    if (signature == null || signature.isEmpty()) {
+      return ClassSignature.NO_CLASS_SIGNATURE;
     }
+    Parser parser = new Parser(factory);
+    try {
+      return parser.parseClassSignature(signature);
+    } catch (GenericSignatureFormatError e) {
+      reporter.warning(
+          GenericSignatureDiagnostic.invalidClassSignature(signature, className, origin, e));
+      return ClassSignature.NO_CLASS_SIGNATURE;
+    }
+  }
 
-    Function<String, ? extends DexDefinitionSignature<? extends DexDefinition>>
-        parserMethod(Parser parser) {
-      switch (this) {
-        case CLASS:
-          return parser::parseClassSignature;
-        case FIELD:
-          return parser::parseFieldTypeSignature;
-        case METHOD:
-          return parser::parseMethodTypeSignature;
-      }
-      throw new Unreachable("Unexpected kind: " + this);
+  public static FieldTypeSignature parseFieldTypeSignature(
+      String fieldName,
+      String signature,
+      Origin origin,
+      DexItemFactory factory,
+      Reporter reporter) {
+    Parser parser = new Parser(factory);
+    try {
+      return parser.parseFieldTypeSignature(signature);
+    } catch (GenericSignatureFormatError e) {
+      reporter.warning(
+          GenericSignatureDiagnostic.invalidFieldSignature(signature, fieldName, origin, e));
+      return GenericSignature.NO_FIELD_TYPE_SIGNATURE;
+    }
+  }
+
+  public static MethodTypeSignature parseMethodSignature(
+      String methodName,
+      String signature,
+      Origin origin,
+      DexItemFactory factory,
+      Reporter reporter) {
+    if (signature == null || signature.isEmpty()) {
+      return MethodTypeSignature.NO_METHOD_TYPE_SIGNATURE;
+    }
+    Parser parser = new Parser(factory);
+    try {
+      return parser.parseMethodTypeSignature(signature);
+    } catch (GenericSignatureFormatError e) {
+      reporter.warning(
+          GenericSignatureDiagnostic.invalidMethodSignature(signature, methodName, origin, e));
+      return MethodTypeSignature.NO_METHOD_TYPE_SIGNATURE;
     }
   }
 
   public static class Parser {
-    // TODO(b/129925954): Can we merge variants of to*Signature below and just expose
-    //  type-parameterized version of this, like
-    //    <T extends DexDefinitionSignature<?>> T toGenericSignature
-    //  without unchecked cast?
-    private static DexDefinitionSignature<? extends DexDefinition> toGenericSignature(
-        DexClass currentClassContext,
-        DexDefinition definition,
-        AppView<AppInfoWithLiveness> appView) {
-      DexAnnotationSet annotations = definition.annotations();
-      if (annotations.annotations.length == 0) {
-        return null;
-      }
-      for (int i = 0; i < annotations.annotations.length; i++) {
-        DexAnnotation annotation = annotations.annotations[i];
-        if (!DexAnnotation.isSignatureAnnotation(annotation, appView.dexItemFactory())) {
-          continue;
-        }
-        Kind kind = Kind.fromDexDefinition(definition);
-        Parser parser = new Parser(currentClassContext, appView);
-        String signature = DexAnnotation.getSignature(annotation);
-        try {
-          return kind.parserMethod(parser).apply(signature);
-        } catch (GenericSignatureFormatError e) {
-          appView.options().warningInvalidSignature(
-              definition, currentClassContext.getOrigin(), signature, e);
-        }
-      }
-      return null;
-    }
-
-    public static ClassSignature toClassSignature(
-        DexClass clazz, AppView<AppInfoWithLiveness> appView) {
-      DexDefinitionSignature<?> signature = toGenericSignature(clazz, clazz, appView);
-      if (signature != null) {
-        assert signature.isClassSignature();
-        return signature.asClassSignature();
-      }
-      return ClassSignature.UNKNOWN_CLASS_SIGNATURE;
-    }
-
-    public static FieldTypeSignature toFieldTypeSignature(
-        DexEncodedField field, AppView<AppInfoWithLiveness> appView) {
-      DexClass currentClassContext = appView.definitionFor(field.holder());
-      DexDefinitionSignature<?> signature =
-          toGenericSignature(currentClassContext, field, appView);
-      if (signature != null) {
-        assert signature.isFieldTypeSignature();
-        return signature.asFieldTypeSignature();
-      }
-      return ClassTypeSignature.UNKNOWN_CLASS_TYPE_SIGNATURE;
-    }
-
-    public static MethodTypeSignature toMethodTypeSignature(
-        DexEncodedMethod method, AppView<AppInfoWithLiveness> appView) {
-      DexClass currentClassContext = appView.definitionFor(method.holder());
-      DexDefinitionSignature<?> signature =
-          toGenericSignature(currentClassContext, method, appView);
-      if (signature != null) {
-        assert signature.isMethodTypeSignature();
-        return signature.asMethodTypeSignature();
-      }
-      return MethodTypeSignature.UNKNOWN_METHOD_TYPE_SIGNATURE;
-    }
 
     /*
      * Parser:
@@ -672,9 +681,8 @@
 
     private int pos;
 
-    private Parser(DexClass currentClassContext, AppView<AppInfoWithLiveness> appView) {
-      this.currentClassContext = currentClassContext;
-      this.appView = appView;
+    private Parser(DexItemFactory factory) {
+      this.factory = factory;
     }
 
     ClassSignature parseClassSignature(String signature) {
@@ -708,7 +716,7 @@
     FieldTypeSignature parseFieldTypeSignature(String signature) {
       try {
         setInput(signature);
-        return parseFieldTypeSignature(ParserPosition.MEMBER_ANNOTATION);
+        return parseFieldTypeSignature();
       } catch (GenericSignatureFormatError e) {
         throw e;
       } catch (Throwable t) {
@@ -732,40 +740,11 @@
     // Action:
     //
 
-    enum ParserPosition {
-      CLASS_SUPER_OR_INTERFACE_ANNOTATION,
-      ENCLOSING_INNER_OR_TYPE_ANNOTATION,
-      MEMBER_ANNOTATION
-    }
+    private final DexItemFactory factory;
 
-    private final AppView<AppInfoWithLiveness> appView;
-    private final DexClass currentClassContext;
-    private DexType lastWrittenType = null;
-
-    private DexType parsedTypeName(String name, ParserPosition parserPosition) {
-      if (parserPosition == ParserPosition.ENCLOSING_INNER_OR_TYPE_ANNOTATION
-          && lastWrittenType == null) {
-        // We are writing type-arguments for a merged class.
-        return null;
-      }
+    private DexType parsedTypeName(String name) {
       String originalDescriptor = getDescriptorFromClassBinaryName(name);
-      DexType type =
-          appView.graphLens().lookupType(appView.dexItemFactory().createType(originalDescriptor));
-      if (appView.appInfo().wasPruned(type)) {
-        type = appView.dexItemFactory().objectType;
-      }
-      if (parserPosition == ParserPosition.CLASS_SUPER_OR_INTERFACE_ANNOTATION
-          && currentClassContext != null) {
-        // We may have merged the type down to the current class type.
-        DexString classDescriptor = currentClassContext.type.descriptor;
-        if (!originalDescriptor.equals(classDescriptor.toString())
-            && type.descriptor.equals(classDescriptor)) {
-          lastWrittenType = null;
-          return type;
-        }
-      }
-      lastWrittenType = type;
-      return type;
+      return factory.createType(originalDescriptor);
     }
 
     private DexType parsedInnerTypeName(DexType enclosingType, String name) {
@@ -775,15 +754,11 @@
       }
       assert enclosingType.isClassType();
       String enclosingDescriptor = enclosingType.toDescriptorString();
-      DexType type =
-          appView
-              .dexItemFactory()
-              .createType(
-                  getDescriptorFromClassBinaryName(
-                      getClassBinaryNameFromDescriptor(enclosingDescriptor)
-                          + DescriptorUtils.INNER_CLASS_SEPARATOR
-                          + name));
-      return appView.graphLens().lookupType(type);
+      return factory.createType(
+          getDescriptorFromClassBinaryName(
+              getClassBinaryNameFromDescriptor(enclosingDescriptor)
+                  + DescriptorUtils.INNER_CLASS_SEPARATOR
+                  + name));
     }
 
     //
@@ -796,13 +771,12 @@
       List<FormalTypeParameter> formalTypeParameters = parseOptFormalTypeParameters();
 
       // SuperclassSignature ::= ClassTypeSignature.
-      ClassTypeSignature superClassSignature =
-          parseClassTypeSignature(ParserPosition.CLASS_SUPER_OR_INTERFACE_ANNOTATION);
+      ClassTypeSignature superClassSignature = parseClassTypeSignature();
 
       ImmutableList.Builder<ClassTypeSignature> builder = ImmutableList.builder();
       while (symbol > 0) {
         // SuperinterfaceSignature ::= ClassTypeSignature.
-        builder.add(parseClassTypeSignature(ParserPosition.CLASS_SUPER_OR_INTERFACE_ANNOTATION));
+        builder.add(parseClassTypeSignature());
       }
 
       return new ClassSignature(formalTypeParameters, superClassSignature, builder.build());
@@ -833,9 +807,9 @@
       // ClassBound ::= ":" FieldTypeSignature?.
       expect(':');
 
-      FieldTypeSignature classBound = ClassTypeSignature.UNKNOWN_CLASS_TYPE_SIGNATURE;
+      FieldTypeSignature classBound = GenericSignature.NO_FIELD_TYPE_SIGNATURE;
       if (symbol == 'L' || symbol == '[' || symbol == 'T') {
-        classBound = parseFieldTypeSignature(ParserPosition.MEMBER_ANNOTATION);
+        classBound = parseFieldTypeSignature();
       }
 
       // Only build the interfacebound builder, which is uncommon, if we actually see an interface.
@@ -846,7 +820,7 @@
           builder = ImmutableList.builder();
         }
         scanSymbol();
-        builder.add(parseFieldTypeSignature(ParserPosition.MEMBER_ANNOTATION));
+        builder.add(parseFieldTypeSignature());
       }
       if (builder == null) {
         return new FormalTypeParameter(typeParameterIdentifier, classBound, null);
@@ -854,16 +828,16 @@
       return new FormalTypeParameter(typeParameterIdentifier, classBound, builder.build());
     }
 
-    private FieldTypeSignature parseFieldTypeSignature(ParserPosition parserPosition) {
+    private FieldTypeSignature parseFieldTypeSignature() {
       // FieldTypeSignature ::= ClassTypeSignature | ArrayTypeSignature | TypeVariableSignature.
       switch (symbol) {
         case 'L':
-          return parseClassTypeSignature(parserPosition);
+          return parseClassTypeSignature();
         case '[':
           // ArrayTypeSignature ::= "[" TypeSignature.
           scanSymbol();
-          TypeSignature baseTypeSignature = updateTypeSignature(parserPosition);
-          return baseTypeSignature.toArrayTypeSignature(appView).asFieldTypeSignature();
+          TypeSignature baseTypeSignature = updateTypeSignature();
+          return baseTypeSignature.toArrayTypeSignature().asFieldTypeSignature();
         case 'T':
           return updateTypeVariableSignature();
         default:
@@ -872,7 +846,7 @@
       throw new Unreachable("Either FieldTypeSignature is returned or a parse error is thrown.");
     }
 
-    private ClassTypeSignature parseClassTypeSignature(ParserPosition parserPosition) {
+    private ClassTypeSignature parseClassTypeSignature() {
       // ClassTypeSignature ::=
       //   "L" (Identifier "/")* Identifier TypeArguments? ("." Identifier TypeArguments?)* ";".
       expect('L');
@@ -888,11 +862,12 @@
       }
 
       qualIdent.append(this.identifier);
-      DexType parsedEnclosingType = parsedTypeName(qualIdent.toString(), parserPosition);
+      DexType parsedEnclosingType = parsedTypeName(qualIdent.toString());
 
       List<FieldTypeSignature> typeArguments = updateOptTypeArguments();
       ClassTypeSignature outerMostTypeSignature =
-          new ClassTypeSignature(parsedEnclosingType, typeArguments);
+          new ClassTypeSignature(
+              parsedEnclosingType, typeArguments.isEmpty() ? EMPTY_TYPE_ARGUMENTS : typeArguments);
 
       ClassTypeSignature outerTypeSignature = outerMostTypeSignature;
       ClassTypeSignature innerTypeSignature;
@@ -903,7 +878,10 @@
         assert identifier != null;
         parsedEnclosingType = parsedInnerTypeName(parsedEnclosingType, identifier);
         typeArguments = updateOptTypeArguments();
-        innerTypeSignature = new ClassTypeSignature(parsedEnclosingType, typeArguments);
+        innerTypeSignature =
+            new ClassTypeSignature(
+                parsedEnclosingType,
+                typeArguments.isEmpty() ? EMPTY_TYPE_ARGUMENTS : typeArguments);
         ClassTypeSignature.link(outerTypeSignature, innerTypeSignature);
         outerTypeSignature = innerTypeSignature;
       }
@@ -935,15 +913,12 @@
         return StarFieldTypeSignature.STAR_FIELD_TYPE_SIGNATURE;
       } else if (symbol == '+') {
         scanSymbol();
-        return parseFieldTypeSignature(ParserPosition.ENCLOSING_INNER_OR_TYPE_ANNOTATION)
-            .asArgument(WildcardIndicator.POSITIVE);
+        return parseFieldTypeSignature().asArgument(WildcardIndicator.POSITIVE);
       } else if (symbol == '-') {
         scanSymbol();
-        return parseFieldTypeSignature(ParserPosition.ENCLOSING_INNER_OR_TYPE_ANNOTATION)
-            .asArgument(WildcardIndicator.NEGATIVE);
+        return parseFieldTypeSignature().asArgument(WildcardIndicator.NEGATIVE);
       } else {
-        return parseFieldTypeSignature(ParserPosition.ENCLOSING_INNER_OR_TYPE_ANNOTATION)
-            .asArgument(WildcardIndicator.NONE);
+        return parseFieldTypeSignature().asArgument(WildcardIndicator.NONE);
       }
     }
 
@@ -958,7 +933,7 @@
       return new TypeVariableSignature(identifier);
     }
 
-    private TypeSignature updateTypeSignature(ParserPosition parserPosition) {
+    private TypeSignature updateTypeSignature() {
       switch (symbol) {
         case 'B':
         case 'C':
@@ -968,13 +943,13 @@
         case 'J':
         case 'S':
         case 'Z':
-          DexType type = appView.dexItemFactory().createType(String.valueOf(symbol));
+          DexType type = factory.createType(String.valueOf(symbol));
           BaseTypeSignature baseTypeSignature = new BaseTypeSignature(type);
           scanSymbol();
           return baseTypeSignature;
         default:
           // Not an elementary type, but a FieldTypeSignature.
-          return parseFieldTypeSignature(parserPosition);
+          return parseFieldTypeSignature();
       }
     }
 
@@ -987,7 +962,7 @@
 
       ImmutableList.Builder<TypeSignature> parameterSignatureBuilder = ImmutableList.builder();
       while (symbol != ')' && (symbol > 0)) {
-        parameterSignatureBuilder.add(updateTypeSignature(ParserPosition.MEMBER_ANNOTATION));
+        parameterSignatureBuilder.add(updateTypeSignature());
       }
 
       expect(')');
@@ -1003,7 +978,7 @@
           if (symbol == 'T') {
             throwsSignatureBuilder.add(updateTypeVariableSignature());
           } else {
-            throwsSignatureBuilder.add(parseClassTypeSignature(ParserPosition.MEMBER_ANNOTATION));
+            throwsSignatureBuilder.add(parseClassTypeSignature());
           }
         } while (symbol == '^');
       }
@@ -1018,7 +993,7 @@
     private ReturnType updateReturnType() {
       // ReturnType ::= TypeSignature | "V".
       if (symbol != 'V') {
-        return new ReturnType(updateTypeSignature(ParserPosition.MEMBER_ANNOTATION));
+        return new ReturnType(updateTypeSignature());
       } else {
         scanSymbol();
         return ReturnType.VOID;
diff --git a/src/main/java/com/android/tools/r8/graph/GenericSignatureDiagnostic.java b/src/main/java/com/android/tools/r8/graph/GenericSignatureDiagnostic.java
new file mode 100644
index 0000000..fa95bce
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/GenericSignatureDiagnostic.java
@@ -0,0 +1,75 @@
+// Copyright (c) 2020, 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.graph;
+
+import com.android.tools.r8.Diagnostic;
+import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.position.Position;
+import java.lang.reflect.GenericSignatureFormatError;
+
+public class GenericSignatureDiagnostic implements Diagnostic {
+
+  private final Origin origin;
+  private final Position position;
+  private final String message;
+
+  GenericSignatureDiagnostic(Origin origin, Position position, String message) {
+    this.origin = origin;
+    this.position = position;
+    this.message = message;
+  }
+
+  @Override
+  public Origin getOrigin() {
+    return origin;
+  }
+
+  @Override
+  public Position getPosition() {
+    return position;
+  }
+
+  @Override
+  public String getDiagnosticMessage() {
+    return message;
+  }
+
+  static GenericSignatureDiagnostic invalidClassSignature(
+      String signature, String name, Origin origin, GenericSignatureFormatError error) {
+    return invalidSignature(signature, "class", name, origin, error);
+  }
+
+  static GenericSignatureDiagnostic invalidMethodSignature(
+      String signature, String name, Origin origin, GenericSignatureFormatError error) {
+    return invalidSignature(signature, "method", name, origin, error);
+  }
+
+  static GenericSignatureDiagnostic invalidFieldSignature(
+      String signature, String name, Origin origin, GenericSignatureFormatError error) {
+    return invalidSignature(signature, "field", name, origin, error);
+  }
+
+  private static GenericSignatureDiagnostic invalidSignature(
+      String signature,
+      String kind,
+      String name,
+      Origin origin,
+      GenericSignatureFormatError error) {
+    String message =
+        "Invalid signature '"
+            + signature
+            + "' for "
+            + kind
+            + " "
+            + name
+            + "."
+            + System.lineSeparator()
+            + "Signature is ignored and will not be present in the output."
+            + System.lineSeparator()
+            + "Parser error: "
+            + error.getMessage();
+    return new GenericSignatureDiagnostic(origin, Position.UNKNOWN, message);
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/graph/GenericSignatureVisitor.java b/src/main/java/com/android/tools/r8/graph/GenericSignatureVisitor.java
new file mode 100644
index 0000000..22ddca7
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/GenericSignatureVisitor.java
@@ -0,0 +1,75 @@
+// Copyright (c) 2020, 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.graph;
+
+import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.graph.GenericSignature.ClassSignature;
+import com.android.tools.r8.graph.GenericSignature.ClassTypeSignature;
+import com.android.tools.r8.graph.GenericSignature.FieldTypeSignature;
+import com.android.tools.r8.graph.GenericSignature.FormalTypeParameter;
+import com.android.tools.r8.graph.GenericSignature.ReturnType;
+import com.android.tools.r8.graph.GenericSignature.TypeSignature;
+import com.android.tools.r8.naming.MemberNaming.FieldSignature;
+import com.android.tools.r8.naming.MemberNaming.MethodSignature;
+import java.util.List;
+
+public interface GenericSignatureVisitor {
+
+  default void visitClassSignature(ClassSignature classSignature) {
+    throw new Unreachable("Implement if visited");
+  }
+
+  default void visitMethodSignature(MethodSignature methodSignature) {
+    throw new Unreachable("Implement if visited");
+  }
+
+  default void visitFieldSignature(FieldSignature fieldSignature) {
+    throw new Unreachable("Implement if visited");
+  }
+
+  default void visitFormalTypeParameters(List<FormalTypeParameter> formalTypeParameters) {
+    throw new Unreachable("Implement if visited");
+  }
+
+  default void visitClassBound(FieldTypeSignature fieldSignature) {
+    throw new Unreachable("Implement if visited");
+  }
+
+  default void visitInterfaceBound(FieldTypeSignature fieldSignature) {
+    throw new Unreachable("Implement if visited");
+  }
+
+  default void visitSuperClass(ClassTypeSignature classTypeSignature) {
+    throw new Unreachable("Implement if visited");
+  }
+
+  default void visitSuperInterface(ClassTypeSignature classTypeSignature) {
+    throw new Unreachable("Implement if visited");
+  }
+
+  default void visitTypeSignature(TypeSignature typeSignature) {
+    throw new Unreachable("Implement if visited");
+  }
+
+  default void visitSimpleClass(ClassTypeSignature classTypeSignature) {
+    throw new Unreachable("Implement if visited");
+  }
+
+  default void visitReturnType(ReturnType returnType) {
+    throw new Unreachable("Implement if visited");
+  }
+
+  default void visitMethodTypeSignatures(List<TypeSignature> typeSignatures) {
+    throw new Unreachable("Implement if visited");
+  }
+
+  default void visitThrowsSignatures(List<TypeSignature> typeSignatures) {
+    throw new Unreachable("Implement if visited");
+  }
+
+  default void visitTypeArguments(List<FieldTypeSignature> typeArguments) {
+    throw new Unreachable("Implement if visited");
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/graph/GenericSignatureTest.java b/src/test/java/com/android/tools/r8/graph/GenericSignatureTest.java
index 5001645..366e98b 100644
--- a/src/test/java/com/android/tools/r8/graph/GenericSignatureTest.java
+++ b/src/test/java/com/android/tools/r8/graph/GenericSignatureTest.java
@@ -19,11 +19,11 @@
 import com.android.tools.r8.graph.GenericSignature.FieldTypeSignature;
 import com.android.tools.r8.graph.GenericSignature.FormalTypeParameter;
 import com.android.tools.r8.graph.GenericSignature.MethodTypeSignature;
-import com.android.tools.r8.graph.GenericSignature.Parser;
 import com.android.tools.r8.graph.GenericSignature.ReturnType;
 import com.android.tools.r8.graph.GenericSignature.TypeSignature;
 import com.android.tools.r8.graph.GenericSignature.WildcardIndicator;
 import com.android.tools.r8.graph.GenericSignatureTestClassA.I;
+import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.android.tools.r8.utils.AndroidApp;
 import com.android.tools.r8.utils.DescriptorUtils;
@@ -103,7 +103,13 @@
     // class <T:GenericSignatureTestClassA<T>.Y>CYY<T extends A<T>.Y> extends CY<T>
     DexClass clazz = cyy.getDexProgramClass();
     assertNotNull(clazz);
-    classSignature = Parser.toClassSignature(clazz, appView);
+    classSignature =
+        GenericSignature.parseClassSignature(
+            clazz.getType().getName(),
+            getGenericSignature(clazz, appView),
+            clazz.origin,
+            appView.dexItemFactory(),
+            appView.options().reporter);
     assertNotNull(classSignature);
 
     assertEquals(1, classSignature.formalTypeParameters.size());
@@ -135,7 +141,13 @@
     DexEncodedField field = yyInZZ.getField();
     assertNotNull(field);
 
-    fieldTypeSignature = Parser.toFieldTypeSignature(field, appView);
+    fieldTypeSignature =
+        GenericSignature.parseFieldTypeSignature(
+            field.field.qualifiedName(),
+            getGenericSignature(field, appView),
+            Origin.unknown(),
+            appView.dexItemFactory(),
+            appView.options().reporter);
     assertNotNull(fieldTypeSignature);
 
     // field type: A$Y$YY
@@ -152,7 +164,13 @@
     method = newYY.getMethod();
     assertNotNull(method);
 
-    methodTypeSignature = Parser.toMethodTypeSignature(method, appView);
+    methodTypeSignature =
+        GenericSignature.parseMethodSignature(
+            method.qualifiedName(),
+            getGenericSignature(method, appView),
+            Origin.unknown(),
+            appView.dexItemFactory(),
+            appView.options().reporter);
     assertNotNull(methodTypeSignature);
 
     assertEquals(1, methodTypeSignature.formalTypeParameters.size());
@@ -194,7 +212,13 @@
     method = convertToYY.getMethod();
     assertNotNull(method);
 
-    methodTypeSignature = GenericSignature.Parser.toMethodTypeSignature(method, appView);
+    methodTypeSignature =
+        GenericSignature.parseMethodSignature(
+            method.qualifiedName(),
+            getGenericSignature(method, appView),
+            Origin.unknown(),
+            appView.dexItemFactory(),
+            appView.options().reporter);
     assertNotNull(methodTypeSignature);
 
     // return type: Function<A$Y$ZZ<TT>, A$Y$YY>
@@ -231,7 +255,13 @@
     assertNotNull(method);
 
     // return type: void
-    methodTypeSignature = Parser.toMethodTypeSignature(method, appView);
+    methodTypeSignature =
+        GenericSignature.parseMethodSignature(
+            method.qualifiedName(),
+            getGenericSignature(method, appView),
+            Origin.unknown(),
+            appView.dexItemFactory(),
+            appView.options().reporter);
     assertNotNull(methodTypeSignature);
     returnType = methodTypeSignature.returnType();
     assertTrue(returnType.isVoidDescriptor());
@@ -304,7 +334,12 @@
       AppView<AppInfoWithLiveness> appView,
       Consumer<FieldTypeSignature> fieldTypeConsumer) {
     MethodTypeSignature methodTypeSignature =
-        Parser.toMethodTypeSignature(methodSubject.getMethod(), appView);
+        GenericSignature.parseMethodSignature(
+            methodSubject.getOriginalName(),
+            getGenericSignature(methodSubject.getMethod(), appView),
+            Origin.unknown(),
+            appView.dexItemFactory(),
+            appView.options().reporter);
     TypeSignature typeSignature = methodTypeSignature.returnType.typeSignature;
     FieldTypeSignature fieldTypeSignature = typeSignature.asFieldTypeSignature();
     assertTrue(fieldTypeSignature.isClassTypeSignature());
@@ -334,6 +369,22 @@
     assertTrue(typeArgument.isClassTypeSignature());
     check_A_Y_ZZ(a, y, zz, typeArgument.asClassTypeSignature());
   }
+
+  private static String getGenericSignature(
+      DexDefinition definition, AppView<AppInfoWithLiveness> appView) {
+    DexAnnotationSet annotations = definition.annotations();
+    if (annotations.annotations.length == 0) {
+      return null;
+    }
+    for (int i = 0; i < annotations.annotations.length; i++) {
+      DexAnnotation annotation = annotations.annotations[i];
+      if (!DexAnnotation.isSignatureAnnotation(annotation, appView.dexItemFactory())) {
+        continue;
+      }
+      return DexAnnotation.getSignature(annotation);
+    }
+    return null;
+  }
 }
 
 //