Skip to content

Commit

Permalink
TypeMirror#toString should include type annotations for primitive types
Browse files Browse the repository at this point in the history
A few of the `toString` overrides in `TurbineTypeMirror` were unnecessary, and the one for primitives was incorrect because it dropped the type annotations.

PiperOrigin-RevId: 715809229
  • Loading branch information
cushon authored and Javac Team committed Jan 15, 2025
1 parent f69f1cb commit 7513c30
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 31 deletions.
31 changes: 0 additions & 31 deletions java/com/google/turbine/processing/TurbineTypeMirror.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import static com.google.common.collect.Iterables.getLast;
import static java.util.Objects.requireNonNull;

import com.google.common.base.Ascii;
import com.google.common.base.Joiner;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableList;
Expand Down Expand Up @@ -100,11 +99,6 @@ public String toString() {
/** A {@link PrimitiveType} implementation backed by a {@link PrimTy}. */
static class TurbinePrimitiveType extends TurbineTypeMirror implements PrimitiveType {

@Override
public String toString() {
return Ascii.toLowerCase(type.primkind().toString());
}

@Override
public Type asTurbineType() {
return type;
Expand Down Expand Up @@ -182,11 +176,6 @@ public ClassTy asTurbineType() {
this.type = type;
}

@Override
public String toString() {
return type.toString();
}

final Supplier<Element> element =
factory.memoize(
new Supplier<Element>() {
Expand Down Expand Up @@ -340,11 +329,6 @@ public TypeMirror getEnclosingType() {
public List<? extends TypeMirror> getTypeArguments() {
return factory.asTypeMirrors(type.targs());
}

@Override
public String toString() {
return type.toString();
}
}

/** A 'package type' implementation backed by a {@link PackageSymbol}. */
Expand Down Expand Up @@ -416,11 +400,6 @@ public <R, P> R accept(TypeVisitor<R, P> v, P p) {
return v.visitNoType(this, p);
}

@Override
public String toString() {
return "none";
}

@Override
public boolean equals(@Nullable Object other) {
return other instanceof TurbineNoType;
Expand Down Expand Up @@ -530,11 +509,6 @@ public TypeMirror getLowerBound() {
: factory.nullType();
}

@Override
public String toString() {
return type.toString();
}

@Override
protected ImmutableList<AnnoInfo> annos() {
return type.annos();
Expand Down Expand Up @@ -694,11 +668,6 @@ public <R, P> R accept(TypeVisitor<R, P> v, P p) {
/** An {@link ExecutableType} implementation backed by a {@link MethodTy}. */
public static class TurbineExecutableType extends TurbineTypeMirror implements ExecutableType {

@Override
public String toString() {
return type.toString();
}

@Override
public MethodTy asTurbineType() {
return type;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ protected static TypeParameters typeParameters() throws Exception {
// type annotations
List<String> annotatedTypes = new ArrayList<>();
annotatedTypes.add("@A int @B []");
annotatedTypes.add("@A int");
// The string representation of these types changed in JDK 19, see JDK-8281238
if (Runtime.version().feature() >= 19) {
annotatedTypes.add("@A List<@B Integer>");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.RecordComponentElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.ErrorType;
import javax.lang.model.type.ExecutableType;
Expand Down Expand Up @@ -1098,6 +1099,70 @@ class T extends M<N> {
"c supertype: B.E<F>, arguments: [F], enclosing: none");
}

@SupportedAnnotationTypes("*")
public static class TypeAnnotationFieldType extends AbstractProcessor {
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latestSupported();
}

private boolean first = true;

@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
if (!first) {
return false;
}
first = false;
for (Element root : roundEnv.getRootElements()) {
for (VariableElement field : ElementFilter.fieldsIn(root.getEnclosedElements())) {
TypeMirror type = field.asType();
processingEnv
.getMessager()
.printMessage(
Diagnostic.Kind.ERROR,
String.format(
"field %s with annotations %s, type '%s' with annotations %s",
field, field.getAnnotationMirrors(), type, type.getAnnotationMirrors()));
}
}
return false;
}
}

// Ensure that type annotations are included in the string representation of primtive types
@Test
public void fieldTypeToString() {
ImmutableList<Tree.CompUnit> units =
parseUnit(
"""
=== T.java ===
class T {
private final @A int f;
private final @A Object g;
private final @A int[] h;
}
=== A.java ===
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
public @interface A {
}
""");
TurbineError e = runProcessors(units, new TypeAnnotationFieldType());
assertThat(
e.diagnostics().stream()
.filter(d -> d.severity().equals(Diagnostic.Kind.ERROR))
.map(d -> d.message()))
.containsExactly(
"field f with annotations [], type '@A int' with annotations [@A]",
"field g with annotations [], type 'java.lang.@A Object' with annotations [@A]",
"field h with annotations [], type '@A int[]' with annotations []");
}

private TurbineError runProcessors(ImmutableList<Tree.CompUnit> units, Processor... processors) {
return assertThrows(
TurbineError.class,
Expand Down

0 comments on commit 7513c30

Please sign in to comment.