Skip to content

Commit cb60060

Browse files
cushonJavac Team
authored andcommitted
Initial support for records in annotation processing
including modeling record components distinctly from parameter declarations, since the annotation processing API cares about the distinction. PiperOrigin-RevId: 399603892
1 parent 407dd72 commit cb60060

17 files changed

Lines changed: 435 additions & 48 deletions

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

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import com.google.turbine.binder.bound.TypeBoundClass.FieldInfo;
2626
import com.google.turbine.binder.bound.TypeBoundClass.MethodInfo;
2727
import com.google.turbine.binder.bound.TypeBoundClass.ParamInfo;
28+
import com.google.turbine.binder.bound.TypeBoundClass.RecordComponentInfo;
2829
import com.google.turbine.binder.bound.TypeBoundClass.TyVarInfo;
2930
import com.google.turbine.binder.env.Env;
3031
import com.google.turbine.binder.sym.ClassSymbol;
@@ -60,8 +61,8 @@ static SourceTypeBoundClass bind(
6061
}
6162
ImmutableMap<TyVarSymbol, TyVarInfo> typParamTypes =
6263
typeParameters(base.source(), pos, env, sym, base.typeParameterTypes());
63-
ImmutableList<ParamInfo> components =
64-
parameters(base.source(), env, sym, pos, base.components());
64+
ImmutableList<RecordComponentInfo> components =
65+
components(base.source(), env, sym, pos, base.components());
6566
ImmutableList<MethodInfo> methods = methods(base.source(), pos, env, sym, base.methods());
6667
ImmutableList<FieldInfo> fields = fields(base.source(), env, sym, base.fields());
6768
return new SourceTypeBoundClass(
@@ -166,6 +167,24 @@ private static ParamInfo param(
166167
base.access());
167168
}
168169

170+
private static ImmutableList<RecordComponentInfo> components(
171+
SourceFile source,
172+
Env<ClassSymbol, TypeBoundClass> env,
173+
ClassSymbol sym,
174+
int pos,
175+
ImmutableList<RecordComponentInfo> components) {
176+
ImmutableList.Builder<RecordComponentInfo> result = ImmutableList.builder();
177+
for (RecordComponentInfo component : components) {
178+
result.add(
179+
new RecordComponentInfo(
180+
component.sym(),
181+
Canonicalize.canonicalize(source, pos, env, sym, component.type()),
182+
component.annotations(),
183+
component.access()));
184+
}
185+
return result.build();
186+
}
187+
169188
private static ImmutableMap<TyVarSymbol, TyVarInfo> typeParameters(
170189
SourceFile source,
171190
int position,

java/com/google/turbine/binder/ConstBinder.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import com.google.turbine.binder.bound.TypeBoundClass.FieldInfo;
3030
import com.google.turbine.binder.bound.TypeBoundClass.MethodInfo;
3131
import com.google.turbine.binder.bound.TypeBoundClass.ParamInfo;
32+
import com.google.turbine.binder.bound.TypeBoundClass.RecordComponentInfo;
3233
import com.google.turbine.binder.bound.TypeBoundClass.TyVarInfo;
3334
import com.google.turbine.binder.env.CompoundEnv;
3435
import com.google.turbine.binder.env.Env;
@@ -104,7 +105,7 @@ public SourceTypeBoundClass bind() {
104105
env,
105106
log)
106107
.evaluateAnnotations(base.annotations());
107-
ImmutableList<TypeBoundClass.ParamInfo> components = bindParameters(base.components());
108+
ImmutableList<RecordComponentInfo> components = bindRecordComponents(base.components());
108109
ImmutableList<TypeBoundClass.FieldInfo> fields = fields(base.fields());
109110
ImmutableList<MethodInfo> methods = bindMethods(base.methods());
110111
return new SourceTypeBoundClass(
@@ -169,6 +170,16 @@ private ParamInfo bindParameter(ParamInfo base) {
169170
return new ParamInfo(base.sym(), bindType(base.type()), annos, base.access());
170171
}
171172

173+
private ImmutableList<RecordComponentInfo> bindRecordComponents(
174+
ImmutableList<RecordComponentInfo> components) {
175+
ImmutableList.Builder<RecordComponentInfo> result = ImmutableList.builder();
176+
for (RecordComponentInfo base : components) {
177+
ImmutableList<AnnoInfo> annos = constEvaluator.evaluateAnnotations(base.annotations());
178+
result.add(new RecordComponentInfo(base.sym(), bindType(base.type()), annos, base.access()));
179+
}
180+
return result.build();
181+
}
182+
172183
static @Nullable AnnotationMetadata bindAnnotationMetadata(
173184
TurbineTyKind kind, Iterable<AnnoInfo> annotations) {
174185
if (kind != TurbineTyKind.ANNOTATION) {

java/com/google/turbine/binder/DisambiguateTypeAnnotations.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import com.google.turbine.binder.bound.TypeBoundClass.FieldInfo;
3131
import com.google.turbine.binder.bound.TypeBoundClass.MethodInfo;
3232
import com.google.turbine.binder.bound.TypeBoundClass.ParamInfo;
33+
import com.google.turbine.binder.bound.TypeBoundClass.RecordComponentInfo;
3334
import com.google.turbine.binder.env.Env;
3435
import com.google.turbine.binder.sym.ClassSymbol;
3536
import com.google.turbine.diag.TurbineError;
@@ -73,7 +74,7 @@ public static SourceTypeBoundClass bind(
7374
base.superClassType(),
7475
base.typeParameterTypes(),
7576
base.access(),
76-
bindParameters(env, base.components(), TurbineElementType.RECORD_COMPONENT),
77+
bindComponents(env, base.components(), TurbineElementType.RECORD_COMPONENT),
7778
bindMethods(env, base.methods()),
7879
bindFields(env, base.fields()),
7980
base.owner(),
@@ -144,6 +145,27 @@ private static ParamInfo bindParam(
144145
return new ParamInfo(base.sym(), type, declarationAnnotations.build(), base.access());
145146
}
146147

148+
private static ImmutableList<RecordComponentInfo> bindComponents(
149+
Env<ClassSymbol, TypeBoundClass> env,
150+
ImmutableList<RecordComponentInfo> components,
151+
TurbineElementType declarationTarget) {
152+
ImmutableList.Builder<RecordComponentInfo> result = ImmutableList.builder();
153+
for (RecordComponentInfo component : components) {
154+
ImmutableList.Builder<AnnoInfo> declarationAnnotations = ImmutableList.builder();
155+
Type type =
156+
disambiguate(
157+
env,
158+
declarationTarget,
159+
component.type(),
160+
component.annotations(),
161+
declarationAnnotations);
162+
result.add(
163+
new RecordComponentInfo(
164+
component.sym(), type, declarationAnnotations.build(), component.access()));
165+
}
166+
return result.build();
167+
}
168+
147169
/**
148170
* Moves type annotations in {@code annotations} to {@code type}, and adds any declaration
149171
* annotations on {@code type} to {@code declarationAnnotations}.

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

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import com.google.turbine.binder.bound.TypeBoundClass.FieldInfo;
2929
import com.google.turbine.binder.bound.TypeBoundClass.MethodInfo;
3030
import com.google.turbine.binder.bound.TypeBoundClass.ParamInfo;
31+
import com.google.turbine.binder.bound.TypeBoundClass.RecordComponentInfo;
3132
import com.google.turbine.binder.bound.TypeBoundClass.TyVarInfo;
3233
import com.google.turbine.binder.env.Env;
3334
import com.google.turbine.binder.lookup.CompoundScope;
@@ -38,6 +39,7 @@
3839
import com.google.turbine.binder.sym.FieldSymbol;
3940
import com.google.turbine.binder.sym.MethodSymbol;
4041
import com.google.turbine.binder.sym.ParamSymbol;
42+
import com.google.turbine.binder.sym.RecordComponentSymbol;
4143
import com.google.turbine.binder.sym.Symbol;
4244
import com.google.turbine.binder.sym.TyVarSymbol;
4345
import com.google.turbine.diag.TurbineError.ErrorKind;
@@ -235,8 +237,7 @@ private SourceTypeBoundClass bind() {
235237

236238
SyntheticMethods syntheticMethods = new SyntheticMethods();
237239

238-
ImmutableList<ParamInfo> components =
239-
bindComponents(scope, syntheticMethods, base.decl().components());
240+
ImmutableList<RecordComponentInfo> components = bindComponents(scope, base.decl().components());
240241

241242
ImmutableList.Builder<MethodInfo> methods =
242243
ImmutableList.<MethodInfo>builder()
@@ -284,20 +285,17 @@ MethodSymbol create(ClassSymbol owner, String name) {
284285
}
285286
}
286287

287-
private ImmutableList<ParamInfo> bindComponents(
288-
CompoundScope scope,
289-
SyntheticMethods syntheticMethods,
290-
ImmutableList<Tree.VarDecl> components) {
291-
ImmutableList.Builder<ParamInfo> result = ImmutableList.builder();
288+
private ImmutableList<RecordComponentInfo> bindComponents(
289+
CompoundScope scope, ImmutableList<Tree.VarDecl> components) {
290+
ImmutableList.Builder<RecordComponentInfo> result = ImmutableList.builder();
292291
for (Tree.VarDecl p : components) {
293292
int access = 0;
294293
for (TurbineModifier m : p.mods()) {
295294
access |= m.flag();
296295
}
297-
MethodSymbol msym = syntheticMethods.create(owner, "");
298-
ParamInfo param =
299-
new ParamInfo(
300-
new ParamSymbol(msym, p.name().value()),
296+
RecordComponentInfo param =
297+
new RecordComponentInfo(
298+
new RecordComponentSymbol(owner, p.name().value()),
301299
bindTy(scope, p.ty()),
302300
bindAnnotations(scope, p.annos()),
303301
access);
@@ -308,7 +306,7 @@ private ImmutableList<ParamInfo> bindComponents(
308306

309307
/** Collect synthetic and implicit methods, including default constructors and enum methods. */
310308
ImmutableList<MethodInfo> syntheticMethods(
311-
SyntheticMethods syntheticMethods, ImmutableList<ParamInfo> components) {
309+
SyntheticMethods syntheticMethods, ImmutableList<RecordComponentInfo> components) {
312310
switch (base.kind()) {
313311
case CLASS:
314312
return maybeDefaultConstructor(syntheticMethods);
@@ -322,13 +320,22 @@ ImmutableList<MethodInfo> syntheticMethods(
322320
}
323321

324322
private ImmutableList<MethodInfo> maybeDefaultRecordConstructor(
325-
SyntheticMethods syntheticMethods, ImmutableList<ParamInfo> components) {
323+
SyntheticMethods syntheticMethods, ImmutableList<RecordComponentInfo> components) {
326324
if (hasConstructor()) {
327325
return ImmutableList.of();
328326
}
329327
MethodSymbol symbol = syntheticMethods.create(owner, "<init>");
328+
ImmutableList.Builder<ParamInfo> params = ImmutableList.builder();
329+
for (RecordComponentInfo component : components) {
330+
params.add(
331+
new ParamInfo(
332+
new ParamSymbol(symbol, component.name()),
333+
component.type(),
334+
component.annotations(),
335+
component.access()));
336+
}
330337
return ImmutableList.of(
331-
syntheticConstructor(symbol, components, TurbineVisibility.fromAccess(base.access())));
338+
syntheticConstructor(symbol, params.build(), TurbineVisibility.fromAccess(base.access())));
332339
}
333340

334341
private ImmutableList<MethodInfo> maybeDefaultConstructor(SyntheticMethods syntheticMethods) {
@@ -450,7 +457,7 @@ private ImmutableList<MethodInfo> syntheticEnumMethods(SyntheticMethods syntheti
450457
}
451458

452459
private ImmutableList<MethodInfo> syntheticRecordMethods(
453-
SyntheticMethods syntheticMethods, ImmutableList<ParamInfo> components) {
460+
SyntheticMethods syntheticMethods, ImmutableList<RecordComponentInfo> components) {
454461
ImmutableList.Builder<MethodInfo> methods = ImmutableList.builder();
455462
MethodSymbol toStringMethod = syntheticMethods.create(owner, "toString");
456463
methods.add(
@@ -496,7 +503,7 @@ private ImmutableList<MethodInfo> syntheticRecordMethods(
496503
null,
497504
ImmutableList.of(),
498505
null));
499-
for (ParamInfo c : components) {
506+
for (RecordComponentInfo c : components) {
500507
MethodSymbol componentMethod = syntheticMethods.create(owner, c.name());
501508
methods.add(
502509
new MethodInfo(

java/com/google/turbine/binder/bound/SourceTypeBoundClass.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public class SourceTypeBoundClass implements TypeBoundClass {
4444
private final ImmutableMap<TyVarSymbol, TyVarInfo> typeParameterTypes;
4545
private final @Nullable Type superClassType;
4646
private final ImmutableList<Type> interfaceTypes;
47-
private final ImmutableList<ParamInfo> components;
47+
private final ImmutableList<RecordComponentInfo> components;
4848
private final ImmutableList<MethodInfo> methods;
4949
private final ImmutableList<FieldInfo> fields;
5050
private final CompoundScope enclosingScope;
@@ -60,7 +60,7 @@ public SourceTypeBoundClass(
6060
@Nullable Type superClassType,
6161
ImmutableMap<TyVarSymbol, TyVarInfo> typeParameterTypes,
6262
int access,
63-
ImmutableList<ParamInfo> components,
63+
ImmutableList<RecordComponentInfo> components,
6464
ImmutableList<MethodInfo> methods,
6565
ImmutableList<FieldInfo> fields,
6666
@Nullable ClassSymbol owner,
@@ -154,7 +154,7 @@ public ImmutableList<Type> interfaceTypes() {
154154

155155
/** The record components. */
156156
@Override
157-
public ImmutableList<ParamInfo> components() {
157+
public ImmutableList<RecordComponentInfo> components() {
158158
return components;
159159
}
160160

java/com/google/turbine/binder/bound/TypeBoundClass.java

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import com.google.turbine.binder.sym.FieldSymbol;
2222
import com.google.turbine.binder.sym.MethodSymbol;
2323
import com.google.turbine.binder.sym.ParamSymbol;
24+
import com.google.turbine.binder.sym.RecordComponentSymbol;
2425
import com.google.turbine.binder.sym.TyVarSymbol;
2526
import com.google.turbine.model.Const;
2627
import com.google.turbine.model.TurbineFlag;
@@ -51,7 +52,7 @@ public interface TypeBoundClass extends HeaderBoundClass {
5152
ImmutableList<MethodInfo> methods();
5253

5354
/** Record components. */
54-
ImmutableList<ParamInfo> components();
55+
ImmutableList<RecordComponentInfo> components();
5556

5657
/**
5758
* Annotation metadata, e.g. from {@link java.lang.annotation.Target}, {@link
@@ -322,4 +323,45 @@ public int access() {
322323
return access;
323324
}
324325
}
326+
327+
/** A record component. */
328+
class RecordComponentInfo {
329+
private final RecordComponentSymbol sym;
330+
private final Type type;
331+
private final int access;
332+
private final ImmutableList<AnnoInfo> annotations;
333+
334+
public RecordComponentInfo(
335+
RecordComponentSymbol sym, Type type, ImmutableList<AnnoInfo> annotations, int access) {
336+
this.sym = sym;
337+
this.type = type;
338+
this.access = access;
339+
this.annotations = annotations;
340+
}
341+
342+
/** The record component's symbol. */
343+
public RecordComponentSymbol sym() {
344+
return sym;
345+
}
346+
347+
/** The record component type. */
348+
public Type type() {
349+
return type;
350+
}
351+
352+
/** Record component annotations. */
353+
public ImmutableList<AnnoInfo> annotations() {
354+
return annotations;
355+
}
356+
357+
/** The Record component's name. */
358+
public String name() {
359+
return sym.name();
360+
}
361+
362+
/** The Record component's modifiers. */
363+
public int access() {
364+
return access;
365+
}
366+
}
325367
}

java/com/google/turbine/binder/bytecode/BytecodeBoundClass.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -487,7 +487,7 @@ public ImmutableList<MethodInfo> methods() {
487487
}
488488

489489
@Override
490-
public ImmutableList<ParamInfo> components() {
490+
public ImmutableList<RecordComponentInfo> components() {
491491
return ImmutableList.of();
492492
}
493493

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Copyright 2021 Google Inc. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.turbine.binder.sym;
18+
19+
import com.google.errorprone.annotations.Immutable;
20+
import java.util.Objects;
21+
import org.jspecify.nullness.Nullable;
22+
23+
/** A record component symbol. */
24+
@Immutable
25+
public class RecordComponentSymbol implements Symbol {
26+
private final ClassSymbol owner;
27+
private final String name;
28+
29+
public RecordComponentSymbol(ClassSymbol owner, String name) {
30+
this.owner = owner;
31+
this.name = name;
32+
}
33+
34+
/** The enclosing class. */
35+
public ClassSymbol owner() {
36+
return owner;
37+
}
38+
39+
/** The parameter name. */
40+
public String name() {
41+
return name;
42+
}
43+
44+
@Override
45+
public Kind symKind() {
46+
return Kind.RECORD_COMPONENT;
47+
}
48+
49+
@Override
50+
public int hashCode() {
51+
return Objects.hash(name, owner);
52+
}
53+
54+
@Override
55+
public boolean equals(@Nullable Object obj) {
56+
if (!(obj instanceof RecordComponentSymbol)) {
57+
return false;
58+
}
59+
RecordComponentSymbol other = (RecordComponentSymbol) obj;
60+
return name().equals(other.name()) && owner().equals(other.owner());
61+
}
62+
63+
@Override
64+
public String toString() {
65+
return name;
66+
}
67+
}

0 commit comments

Comments
 (0)