Skip to content

Commit 8d37a77

Browse files
committed
Backport 8d0831478338e9b084b2c47f46eba9faae3a5eb6
1 parent f4deb60 commit 8d37a77

File tree

2 files changed

+81
-84
lines changed

2 files changed

+81
-84
lines changed

src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java

Lines changed: 61 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@
3636
import java.util.HashSet;
3737
import java.util.Map;
3838
import java.util.Set;
39-
import java.util.function.BiFunction;
4039
import java.util.function.IntFunction;
4140
import java.util.function.Predicate;
41+
import java.util.stream.IntStream;
4242

4343
import javax.lang.model.element.Modifier;
4444
import javax.lang.model.element.NestingKind;
@@ -2348,13 +2348,8 @@ private Type addTypeAnnotations(Type type, Predicate<TypeAnnotationPosition> fil
23482348
.add(attribute);
23492349
}
23502350

2351-
// Search the structure of the type to find the contained types at each type path
2352-
Map<Type, List<Attribute.TypeCompound>> attributesByType = new HashMap<>();
2353-
new TypeAnnotationLocator(attributesByPath, attributesByType).visit(type, List.nil());
2354-
23552351
// Rewrite the type and add the annotations
2356-
type = new TypeAnnotationTypeMapping(attributesByType).visit(type, null);
2357-
Assert.check(attributesByType.isEmpty(), "Failed to apply annotations to types");
2352+
type = new TypeAnnotationStructuralTypeMapping(attributesByPath).visit(type, List.nil());
23582353

23592354
return type;
23602355
}
@@ -2382,124 +2377,106 @@ private static Predicate<TypeAnnotationPosition> classExtends(int index) {
23822377
}
23832378

23842379
/**
2385-
* Visit all contained types, assembling a type path to represent the current location, and
2386-
* record the types at each type path that need to be annotated.
2380+
* A type mapping that rewrites the type to include type annotations.
2381+
*
2382+
* <p>This logic is similar to {@link Type.StructuralTypeMapping}, but also tracks the path to
2383+
* the contained types being rewritten, and so cannot easily share the existing logic.
23872384
*/
2388-
private static class TypeAnnotationLocator
2389-
extends Types.DefaultTypeVisitor<Void, List<TypeAnnotationPosition.TypePathEntry>> {
2385+
private static final class TypeAnnotationStructuralTypeMapping
2386+
extends Types.TypeMapping<List<TypeAnnotationPosition.TypePathEntry>> {
2387+
23902388
private final Map<List<TypeAnnotationPosition.TypePathEntry>,
2391-
ListBuffer<Attribute.TypeCompound>> attributesByPath;
2392-
private final Map<Type, List<Attribute.TypeCompound>> attributesByType;
2389+
ListBuffer<Attribute.TypeCompound>> attributesByPath;
23932390

2394-
private TypeAnnotationLocator(
2391+
private TypeAnnotationStructuralTypeMapping(
23952392
Map<List<TypeAnnotationPosition.TypePathEntry>, ListBuffer<Attribute.TypeCompound>>
2396-
attributesByPath,
2397-
Map<Type, List<Attribute.TypeCompound>> attributesByType) {
2393+
attributesByPath) {
23982394
this.attributesByPath = attributesByPath;
2399-
this.attributesByType = attributesByType;
24002395
}
24012396

2397+
24022398
@Override
2403-
public Void visitClassType(ClassType t, List<TypeAnnotationPosition.TypePathEntry> path) {
2399+
public Type visitClassType(ClassType t, List<TypeAnnotationPosition.TypePathEntry> path) {
24042400
// As described in JVMS 4.7.20.2, type annotations on nested types are located with
24052401
// 'left-to-right' steps starting on 'the outermost part of the type for which a type
24062402
// annotation is admissible'. So the current path represents the outermost containing
24072403
// type of the type being visited, and we add type path steps for every contained nested
24082404
// type.
2409-
List<ClassType> enclosing = List.nil();
2410-
for (Type curr = t;
2411-
curr != null && curr != Type.noType;
2405+
Type outer = t.getEnclosingType();
2406+
Type outer1 = outer != Type.noType ? visit(outer, path) : outer;
2407+
for (Type curr = t.getEnclosingType();
2408+
curr != Type.noType;
24122409
curr = curr.getEnclosingType()) {
2413-
enclosing = enclosing.prepend((ClassType) curr);
2414-
}
2415-
for (ClassType te : enclosing) {
2416-
if (te.typarams_field != null) {
2417-
int i = 0;
2418-
for (Type typaram : te.typarams_field) {
2419-
visit(typaram, path.append(new TypeAnnotationPosition.TypePathEntry(
2420-
TypeAnnotationPosition.TypePathEntryKind.TYPE_ARGUMENT, i++)));
2421-
}
2422-
}
2423-
visitType(te, path);
24242410
path = path.append(TypeAnnotationPosition.TypePathEntry.INNER_TYPE);
24252411
}
2426-
return null;
2412+
List<Type> typarams = t.getTypeArguments();
2413+
List<Type> typarams1 = rewriteTypeParams(path, typarams);
2414+
if (outer1 != outer || typarams != typarams1) {
2415+
t = new ClassType(outer1, typarams1, t.tsym, t.getMetadata());
2416+
}
2417+
return reannotate(t, path);
24272418
}
24282419

2429-
@Override
2430-
public Void visitWildcardType(
2431-
WildcardType t, List<TypeAnnotationPosition.TypePathEntry> path) {
2432-
visit(t.type, path.append(TypeAnnotationPosition.TypePathEntry.WILDCARD));
2433-
return super.visitWildcardType(t, path);
2420+
private List<Type> rewriteTypeParams(
2421+
List<TypeAnnotationPosition.TypePathEntry> path, List<Type> typarams) {
2422+
var i = IntStream.iterate(0, x -> x + 1).iterator();
2423+
return typarams.map(typaram -> visit(typaram,
2424+
path.append(new TypeAnnotationPosition.TypePathEntry(
2425+
TypeAnnotationPosition.TypePathEntryKind.TYPE_ARGUMENT, i.nextInt()))));
24342426
}
24352427

24362428
@Override
2437-
public Void visitArrayType(ArrayType t, List<TypeAnnotationPosition.TypePathEntry> path) {
2438-
visit(t.elemtype, path.append(TypeAnnotationPosition.TypePathEntry.ARRAY));
2439-
return super.visitArrayType(t, path);
2429+
public Type visitWildcardType(
2430+
WildcardType wt, List<TypeAnnotationPosition.TypePathEntry> path) {
2431+
Type t = wt.type;
2432+
if (t != null) {
2433+
t = visit(t, path.append(TypeAnnotationPosition.TypePathEntry.WILDCARD));
2434+
}
2435+
if (t != wt.type) {
2436+
wt = new WildcardType(t, wt.kind, wt.tsym, wt.bound, wt.getMetadata());
2437+
}
2438+
return reannotate(wt, path);
24402439
}
24412440

24422441
@Override
2443-
public Void visitType(Type t, List<TypeAnnotationPosition.TypePathEntry> path) {
2444-
ListBuffer<Attribute.TypeCompound> attributes = attributesByPath.remove(path);
2445-
if (attributes != null) {
2446-
attributesByType.put(t, attributes.toList());
2442+
public Type visitArrayType(ArrayType t, List<TypeAnnotationPosition.TypePathEntry> path) {
2443+
Type elemtype = t.elemtype;
2444+
Type elemtype1 =
2445+
visit(elemtype, path.append(TypeAnnotationPosition.TypePathEntry.ARRAY));
2446+
if (elemtype1 != elemtype) {
2447+
t = new ArrayType(elemtype1, t.tsym, t.getMetadata());
24472448
}
2448-
return null;
2449+
return reannotate(t, path);
24492450
}
2450-
}
2451-
2452-
/** A type mapping that rewrites the type to include type annotations. */
2453-
private static class TypeAnnotationTypeMapping extends Type.StructuralTypeMapping<Void> {
24542451

2455-
private final Map<Type, List<Attribute.TypeCompound>> attributesByType;
2456-
2457-
private TypeAnnotationTypeMapping(
2458-
Map<Type, List<Attribute.TypeCompound>> attributesByType) {
2459-
this.attributesByType = attributesByType;
2452+
@Override
2453+
public Type visitType(Type t, List<TypeAnnotationPosition.TypePathEntry> path) {
2454+
return reannotate(t, path);
24602455
}
24612456

2462-
private <T extends Type> Type reannotate(T t, BiFunction<T, Void, Type> f) {
2463-
// We're relying on object identify of Type instances to record where the annotations
2464-
// need to be added, so we have to retrieve the annotations for each type before
2465-
// rewriting it, and then add them after its contained types have been rewritten.
2466-
List<Attribute.TypeCompound> attributes = attributesByType.remove(t);
2467-
Type mapped = f.apply(t, null);
2468-
if (attributes == null) {
2469-
return mapped;
2457+
Type reannotate(Type type, List<TypeAnnotationPosition.TypePathEntry> path) {
2458+
List<Attribute.TypeCompound> attributes = attributesForPath(path);
2459+
if (attributes.isEmpty()) {
2460+
return type;
24702461
}
24712462
// Runtime-visible and -invisible annotations are completed separately, so if the same
24722463
// type has annotations from both it will get annotated twice.
2473-
TypeMetadata metadata = mapped.getMetadata();
2464+
TypeMetadata metadata = type.getMetadata();
24742465
TypeMetadata.Annotations existing =
24752466
(TypeMetadata.Annotations) metadata.get(TypeMetadata.Entry.Kind.ANNOTATIONS);
24762467
if (existing != null) {
24772468
TypeMetadata.Annotations combined = new TypeMetadata.Annotations(
24782469
existing.getAnnotations().appendList(attributes));
2479-
return mapped.cloneWithMetadata(
2470+
return type.cloneWithMetadata(
24802471
metadata.without(TypeMetadata.Entry.Kind.ANNOTATIONS).combine(combined));
24812472
}
2482-
return mapped.annotatedType(attributes);
2483-
}
2484-
2485-
@Override
2486-
public Type visitClassType(ClassType t, Void unused) {
2487-
return reannotate(t, super::visitClassType);
2488-
}
2489-
2490-
@Override
2491-
public Type visitWildcardType(WildcardType t, Void unused) {
2492-
return reannotate(t, super::visitWildcardType);
2473+
return type.annotatedType(attributes);
24932474
}
24942475

2495-
@Override
2496-
public Type visitArrayType(ArrayType t, Void unused) {
2497-
return reannotate(t, super::visitArrayType);
2498-
}
2499-
2500-
@Override
2501-
public Type visitType(Type t, Void unused) {
2502-
return reannotate(t, (x, u) -> x);
2476+
List<Attribute.TypeCompound> attributesForPath(
2477+
List<TypeAnnotationPosition.TypePathEntry> path) {
2478+
ListBuffer<Attribute.TypeCompound> attributes = attributesByPath.remove(path);
2479+
return attributes != null ? attributes.toList() : List.nil();
25032480
}
25042481
}
25052482

test/langtools/tools/javac/processing/model/type/BasicAnnoTests.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,4 +585,24 @@ class Inner90<@TA(90) T> {
585585
@Test(posn=4, annoType = TB.class, expect = "100")
586586
class Inner100<T extends Inner100<@TB(100) T>> {
587587
}
588+
589+
// receiver parameters
590+
class Inner110 {
591+
@Test(posn=2, annoType = TA.class, expect = "110")
592+
void f(@TA(110) Inner110 this) {}
593+
594+
@Test(posn=2, annoType = TA.class, expect = "111")
595+
Inner110(@TA(111) BasicAnnoTests BasicAnnoTests.this) {}
596+
}
597+
598+
static class GenericInner120<X> {
599+
private class GenericNested<Y> {
600+
@Test(posn=2, annoType = TA.class, expect = "120")
601+
GenericNested(@TA(120) GenericInner120<X> GenericInner120.this) {}
602+
}
603+
}
604+
605+
@Test(posn=1, annoType=TA.class, expect="130")
606+
@Test(posn=23, annoType=TA.class, expect="131")
607+
public Map<@TA(130) String, @TA(131) String> f130;
588608
}

0 commit comments

Comments
 (0)