From bc0e886f47be6098e2cab134114eb712b0019bb8 Mon Sep 17 00:00:00 2001 From: Liam Miller-Cushon Date: Fri, 31 Jul 2026 12:21:39 -0700 Subject: [PATCH] Omit TYPE_USE annotations from string representations of Dagger binding keys RELNOTES=n/a PiperOrigin-RevId: 957275939 --- dagger-spi/main/java/dagger/model/Key.java | 127 ++++++++++++++++++++- 1 file changed, 126 insertions(+), 1 deletion(-) diff --git a/dagger-spi/main/java/dagger/model/Key.java b/dagger-spi/main/java/dagger/model/Key.java index 6916951aff5..f3aff9e865d 100644 --- a/dagger-spi/main/java/dagger/model/Key.java +++ b/dagger-spi/main/java/dagger/model/Key.java @@ -36,8 +36,16 @@ import javax.lang.model.element.AnnotationValue; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; +import javax.lang.model.type.ArrayType; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.NoType; +import javax.lang.model.type.PrimitiveType; +import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; +import javax.lang.model.type.TypeVariable; +import javax.lang.model.type.WildcardType; import javax.lang.model.util.SimpleAnnotationValueVisitor8; +import javax.lang.model.util.SimpleTypeVisitor8; /** * A {@linkplain TypeMirror type} and an optional {@linkplain javax.inject.Qualifier qualifier} that @@ -161,13 +169,130 @@ public String visitArray(List value, Void ignore) { null); } + /** + * Returns a string representation of the given {@link TypeMirror} with all {@code TYPE_USE} + * annotations stripped. + * + *

Type-use annotations do not affect Dagger's key resolution, and omitting them ensures + * stability of conformance test allowlists (avoiding test churn when annotations are added or + * removed). + */ + private static String unannotatedTypeToString(TypeMirror type) { + UnannotatedTypeVisitor visitor = new UnannotatedTypeVisitor(); + type.accept(visitor, null); + return visitor.toString(); + } + + private static final class UnannotatedTypeVisitor extends SimpleTypeVisitor8 { + private final StringBuilder sb = new StringBuilder(); + + @Override + public String toString() { + return sb.toString(); + } + + @Override + public Void visitDeclared(DeclaredType t, Void aVoid) { + TypeMirror enclosing = t.getEnclosingType(); + if (enclosing.getKind() == TypeKind.DECLARED) { + enclosing.accept(this, null); + sb.append('.').append(t.asElement().getSimpleName()); + } else { + TypeElement element = (TypeElement) t.asElement(); + sb.append(element.getQualifiedName()); + } + List typeArguments = t.getTypeArguments(); + if (!typeArguments.isEmpty()) { + sb.append('<'); + for (int i = 0; i < typeArguments.size(); i++) { + if (i > 0) { + sb.append(','); + } + typeArguments.get(i).accept(this, null); + } + sb.append('>'); + } + return null; + } + + @Override + public Void visitArray(ArrayType t, Void aVoid) { + t.getComponentType().accept(this, null); + sb.append("[]"); + return null; + } + + @Override + public Void visitPrimitive(PrimitiveType t, Void aVoid) { + sb.append(primitiveName(t)); + return null; + } + + @Override + public Void visitTypeVariable(TypeVariable t, Void aVoid) { + sb.append(t.asElement().getSimpleName()); + return null; + } + + @Override + public Void visitWildcard(WildcardType t, Void aVoid) { + sb.append('?'); + TypeMirror extendsBound = t.getExtendsBound(); + if (extendsBound != null) { + sb.append(" extends "); + extendsBound.accept(this, null); + } + TypeMirror superBound = t.getSuperBound(); + if (superBound != null) { + sb.append(" super "); + superBound.accept(this, null); + } + return null; + } + + @Override + public Void visitNoType(NoType t, Void aVoid) { + sb.append(t.toString()); + return null; + } + + @Override + protected Void defaultAction(TypeMirror e, Void aVoid) { + sb.append(e.toString()); + return null; + } + + private static String primitiveName(PrimitiveType t) { + switch (t.getKind()) { + case BOOLEAN: + return "boolean"; + case BYTE: + return "byte"; + case SHORT: + return "short"; + case INT: + return "int"; + case LONG: + return "long"; + case CHAR: + return "char"; + case FLOAT: + return "float"; + case DOUBLE: + return "double"; + default: + throw new IllegalArgumentException("not a primitive: " + t); + } + } + } + @Override public final String toString() { return Joiner.on(' ') .skipNulls() .join( qualifier().map(Key::stableAnnotationMirrorToString).orElse(null), - type(), + unannotatedTypeToString(type()), multibindingContributionIdentifier().orElse(null)); }