Skip to content

Commit c86723d

Browse files
cushonJavac Team
authored andcommitted
Model private synthetic record fields for annotation processing
bazelbuild/bazel#27810 PiperOrigin-RevId: 838647742
1 parent 1c9a538 commit c86723d

File tree

3 files changed

+129
-7
lines changed

3 files changed

+129
-7
lines changed

java/com/google/turbine/binder/CanonicalTypeBinder.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616

1717
package com.google.turbine.binder;
1818

19-
import static java.util.Objects.requireNonNull;
20-
2119
import com.google.common.collect.ImmutableList;
2220
import com.google.common.collect.ImmutableMap;
2321
import com.google.turbine.binder.bound.SourceTypeBoundClass;
@@ -64,7 +62,7 @@ static SourceTypeBoundClass bind(
6462
ImmutableList<RecordComponentInfo> components =
6563
components(base.source(), env, sym, pos, base.components());
6664
ImmutableList<MethodInfo> methods = methods(base.source(), pos, env, sym, base.methods());
67-
ImmutableList<FieldInfo> fields = fields(base.source(), env, sym, base.fields());
65+
ImmutableList<FieldInfo> fields = fields(base.source(), pos, env, sym, base.fields());
6866
return new SourceTypeBoundClass(
6967
interfaceTypes.build(),
7068
base.permits(),
@@ -89,6 +87,7 @@ static SourceTypeBoundClass bind(
8987

9088
private static ImmutableList<FieldInfo> fields(
9189
SourceFile source,
90+
int position,
9291
Env<ClassSymbol, TypeBoundClass> env,
9392
ClassSymbol sym,
9493
ImmutableList<FieldInfo> fields) {
@@ -99,8 +98,7 @@ private static ImmutableList<FieldInfo> fields(
9998
base.sym(),
10099
Canonicalize.canonicalize(
101100
source,
102-
// we're processing fields bound from sources in the compilation
103-
requireNonNull(base.decl()).position(),
101+
base.decl() != null ? base.decl().position() : position,
104102
env,
105103
sym,
106104
base.type()),

java/com/google/turbine/binder/TypeBinder.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,10 @@ private SourceTypeBoundClass bind() {
259259
.build();
260260
}
261261

262-
ImmutableList<FieldInfo> fields = bindFields(scope, base.decl().members());
262+
ImmutableList<FieldInfo> fields =
263+
base.kind().equals(TurbineTyKind.RECORD)
264+
? recordFields(components)
265+
: bindFields(scope, base.decl().members());
263266

264267
return new SourceTypeBoundClass(
265268
interfaceTypes.build(),
@@ -397,6 +400,21 @@ private ImmutableList<MethodInfo> recordMethods(
397400
return methods.build();
398401
}
399402

403+
private ImmutableList<FieldInfo> recordFields(ImmutableList<RecordComponentInfo> components) {
404+
ImmutableList.Builder<FieldInfo> fields = ImmutableList.builder();
405+
for (RecordComponentInfo c : components) {
406+
fields.add(
407+
new FieldInfo(
408+
new FieldSymbol(owner, c.name()),
409+
c.type(),
410+
TurbineFlag.ACC_PRIVATE | TurbineFlag.ACC_FINAL,
411+
c.annotations(),
412+
/* decl= */ null,
413+
/* value= */ null));
414+
}
415+
return fields.build();
416+
}
417+
400418
private MethodInfo defaultRecordConstructor(
401419
SyntheticMethods syntheticMethods, ImmutableList<RecordComponentInfo> components) {
402420
MethodSymbol symbol = syntheticMethods.create(owner, "<init>");

javatests/com/google/turbine/processing/ProcessingIntegrationTest.java

Lines changed: 107 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -625,7 +625,9 @@ public void recordProcessing() throws IOException {
625625
"METHOD hashCode()",
626626
"METHOD equals(java.lang.Object)",
627627
"METHOD x()",
628-
"METHOD y()");
628+
"METHOD y()",
629+
"FIELD x",
630+
"FIELD y");
629631
}
630632

631633
@SupportedAnnotationTypes("*")
@@ -1207,6 +1209,110 @@ class B {}
12071209
.containsExactly("package '' contains A", "package '' contains B");
12081210
}
12091211

1212+
@SupportedAnnotationTypes("*")
1213+
public static class RecordMembers extends AbstractProcessor {
1214+
@Override
1215+
public SourceVersion getSupportedSourceVersion() {
1216+
return SourceVersion.latestSupported();
1217+
}
1218+
1219+
@Override
1220+
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
1221+
if (!roundEnv.processingOver()) {
1222+
return false;
1223+
}
1224+
for (Element e :
1225+
processingEnv.getElementUtils().getTypeElement("Person").getEnclosedElements()) {
1226+
processingEnv.getMessager().printError(e + " " + e.getKind(), e);
1227+
}
1228+
return false;
1229+
}
1230+
}
1231+
1232+
@Test
1233+
public void recordMembers() throws Exception {
1234+
ImmutableList<Tree.CompUnit> units =
1235+
parseUnit(
1236+
"""
1237+
=== Person.java ===
1238+
public record Person(String name) {
1239+
}
1240+
""");
1241+
TurbineError e = runProcessors(units, new RecordMembers());
1242+
assertThat(
1243+
e.diagnostics().stream()
1244+
.filter(d -> d.severity().equals(Diagnostic.Kind.ERROR))
1245+
.map(d -> d.message()))
1246+
.containsExactly(
1247+
"name RECORD_COMPONENT",
1248+
"name FIELD",
1249+
"Person(java.lang.String) CONSTRUCTOR",
1250+
"toString() METHOD",
1251+
"hashCode() METHOD",
1252+
"equals(java.lang.Object) METHOD",
1253+
"name() METHOD");
1254+
}
1255+
1256+
@SupportedAnnotationTypes("*")
1257+
public static class RecordFields extends AbstractProcessor {
1258+
@Override
1259+
public SourceVersion getSupportedSourceVersion() {
1260+
return SourceVersion.latestSupported();
1261+
}
1262+
1263+
@Override
1264+
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
1265+
if (!roundEnv.processingOver()) {
1266+
return false;
1267+
}
1268+
for (VariableElement e :
1269+
fieldsIn(
1270+
processingEnv.getElementUtils().getTypeElement("Person").getEnclosedElements())) {
1271+
processingEnv
1272+
.getMessager()
1273+
.printError(
1274+
String.format(
1275+
"%s: modifiers %s, type %s, annotations %s",
1276+
e.getSimpleName(), e.getModifiers(), e.asType(), e.getAnnotationMirrors()),
1277+
e);
1278+
}
1279+
return false;
1280+
}
1281+
}
1282+
1283+
@Test
1284+
public void recordFields() throws Exception {
1285+
ImmutableList<Tree.CompUnit> units =
1286+
parseUnit(
1287+
"""
1288+
=== A.java ===
1289+
import java.lang.annotation.ElementType;
1290+
import java.lang.annotation.Target;
1291+
@Target({ElementType.FIELD, ElementType.TYPE_USE})
1292+
public @interface A {}
1293+
=== B.java ===
1294+
import java.lang.annotation.ElementType;
1295+
import java.lang.annotation.Target;
1296+
@Target({ElementType.PARAMETER})
1297+
public @interface B {}
1298+
=== Person.java ===
1299+
import java.util.List;
1300+
public record Person(String name, List<@A String> b, final @A int c, @B int d) {
1301+
}
1302+
""");
1303+
TurbineError e = runProcessors(units, new RecordFields());
1304+
assertThat(
1305+
e.diagnostics().stream()
1306+
.filter(d -> d.severity().equals(Diagnostic.Kind.ERROR))
1307+
.map(d -> d.message()))
1308+
.containsExactly(
1309+
"name: modifiers [private, final], type java.lang.String, annotations []",
1310+
"b: modifiers [private, final], type java.util.List<java.lang.@A String>, annotations"
1311+
+ " []",
1312+
"c: modifiers [private, final], type @A int, annotations [@A]",
1313+
"d: modifiers [private, final], type int, annotations []");
1314+
}
1315+
12101316
private TurbineError runProcessors(ImmutableList<Tree.CompUnit> units, Processor... processors) {
12111317
return assertThrows(
12121318
TurbineError.class,

0 commit comments

Comments
 (0)