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;
+ }
}
//