|
36 | 36 | import java.util.HashSet; |
37 | 37 | import java.util.Map; |
38 | 38 | import java.util.Set; |
39 | | -import java.util.function.BiFunction; |
40 | 39 | import java.util.function.IntFunction; |
41 | 40 | import java.util.function.Predicate; |
| 41 | +import java.util.stream.IntStream; |
42 | 42 |
|
43 | 43 | import javax.lang.model.element.Modifier; |
44 | 44 | import javax.lang.model.element.NestingKind; |
@@ -2342,13 +2342,8 @@ private Type addTypeAnnotations(Type type, Predicate<TypeAnnotationPosition> fil |
2342 | 2342 | .add(attribute); |
2343 | 2343 | } |
2344 | 2344 |
|
2345 | | - // Search the structure of the type to find the contained types at each type path |
2346 | | - Map<Type, List<Attribute.TypeCompound>> attributesByType = new HashMap<>(); |
2347 | | - new TypeAnnotationLocator(attributesByPath, attributesByType).visit(type, List.nil()); |
2348 | | - |
2349 | 2345 | // Rewrite the type and add the annotations |
2350 | | - type = new TypeAnnotationTypeMapping(attributesByType).visit(type, null); |
2351 | | - Assert.check(attributesByType.isEmpty(), "Failed to apply annotations to types"); |
| 2346 | + type = new TypeAnnotationStructuralTypeMapping(attributesByPath).visit(type, List.nil()); |
2352 | 2347 |
|
2353 | 2348 | return type; |
2354 | 2349 | } |
@@ -2376,124 +2371,106 @@ private static Predicate<TypeAnnotationPosition> classExtends(int index) { |
2376 | 2371 | } |
2377 | 2372 |
|
2378 | 2373 | /** |
2379 | | - * Visit all contained types, assembling a type path to represent the current location, and |
2380 | | - * record the types at each type path that need to be annotated. |
| 2374 | + * A type mapping that rewrites the type to include type annotations. |
| 2375 | + * |
| 2376 | + * <p>This logic is similar to {@link Type.StructuralTypeMapping}, but also tracks the path to |
| 2377 | + * the contained types being rewritten, and so cannot easily share the existing logic. |
2381 | 2378 | */ |
2382 | | - private static class TypeAnnotationLocator |
2383 | | - extends Types.DefaultTypeVisitor<Void, List<TypeAnnotationPosition.TypePathEntry>> { |
| 2379 | + private static final class TypeAnnotationStructuralTypeMapping |
| 2380 | + extends Types.TypeMapping<List<TypeAnnotationPosition.TypePathEntry>> { |
| 2381 | + |
2384 | 2382 | private final Map<List<TypeAnnotationPosition.TypePathEntry>, |
2385 | | - ListBuffer<Attribute.TypeCompound>> attributesByPath; |
2386 | | - private final Map<Type, List<Attribute.TypeCompound>> attributesByType; |
| 2383 | + ListBuffer<Attribute.TypeCompound>> attributesByPath; |
2387 | 2384 |
|
2388 | | - private TypeAnnotationLocator( |
| 2385 | + private TypeAnnotationStructuralTypeMapping( |
2389 | 2386 | Map<List<TypeAnnotationPosition.TypePathEntry>, ListBuffer<Attribute.TypeCompound>> |
2390 | | - attributesByPath, |
2391 | | - Map<Type, List<Attribute.TypeCompound>> attributesByType) { |
| 2387 | + attributesByPath) { |
2392 | 2388 | this.attributesByPath = attributesByPath; |
2393 | | - this.attributesByType = attributesByType; |
2394 | 2389 | } |
2395 | 2390 |
|
| 2391 | + |
2396 | 2392 | @Override |
2397 | | - public Void visitClassType(ClassType t, List<TypeAnnotationPosition.TypePathEntry> path) { |
| 2393 | + public Type visitClassType(ClassType t, List<TypeAnnotationPosition.TypePathEntry> path) { |
2398 | 2394 | // As described in JVMS 4.7.20.2, type annotations on nested types are located with |
2399 | 2395 | // 'left-to-right' steps starting on 'the outermost part of the type for which a type |
2400 | 2396 | // annotation is admissible'. So the current path represents the outermost containing |
2401 | 2397 | // type of the type being visited, and we add type path steps for every contained nested |
2402 | 2398 | // type. |
2403 | | - List<ClassType> enclosing = List.nil(); |
2404 | | - for (Type curr = t; |
2405 | | - curr != null && curr != Type.noType; |
| 2399 | + Type outer = t.getEnclosingType(); |
| 2400 | + Type outer1 = outer != Type.noType ? visit(outer, path) : outer; |
| 2401 | + for (Type curr = t.getEnclosingType(); |
| 2402 | + curr != Type.noType; |
2406 | 2403 | curr = curr.getEnclosingType()) { |
2407 | | - enclosing = enclosing.prepend((ClassType) curr); |
2408 | | - } |
2409 | | - for (ClassType te : enclosing) { |
2410 | | - if (te.typarams_field != null) { |
2411 | | - int i = 0; |
2412 | | - for (Type typaram : te.typarams_field) { |
2413 | | - visit(typaram, path.append(new TypeAnnotationPosition.TypePathEntry( |
2414 | | - TypeAnnotationPosition.TypePathEntryKind.TYPE_ARGUMENT, i++))); |
2415 | | - } |
2416 | | - } |
2417 | | - visitType(te, path); |
2418 | 2404 | path = path.append(TypeAnnotationPosition.TypePathEntry.INNER_TYPE); |
2419 | 2405 | } |
2420 | | - return null; |
| 2406 | + List<Type> typarams = t.getTypeArguments(); |
| 2407 | + List<Type> typarams1 = rewriteTypeParams(path, typarams); |
| 2408 | + if (outer1 != outer || typarams != typarams1) { |
| 2409 | + t = new ClassType(outer1, typarams1, t.tsym, t.getMetadata()); |
| 2410 | + } |
| 2411 | + return reannotate(t, path); |
2421 | 2412 | } |
2422 | 2413 |
|
2423 | | - @Override |
2424 | | - public Void visitWildcardType( |
2425 | | - WildcardType t, List<TypeAnnotationPosition.TypePathEntry> path) { |
2426 | | - visit(t.type, path.append(TypeAnnotationPosition.TypePathEntry.WILDCARD)); |
2427 | | - return super.visitWildcardType(t, path); |
| 2414 | + private List<Type> rewriteTypeParams( |
| 2415 | + List<TypeAnnotationPosition.TypePathEntry> path, List<Type> typarams) { |
| 2416 | + var i = IntStream.iterate(0, x -> x + 1).iterator(); |
| 2417 | + return typarams.map(typaram -> visit(typaram, |
| 2418 | + path.append(new TypeAnnotationPosition.TypePathEntry( |
| 2419 | + TypeAnnotationPosition.TypePathEntryKind.TYPE_ARGUMENT, i.nextInt())))); |
2428 | 2420 | } |
2429 | 2421 |
|
2430 | 2422 | @Override |
2431 | | - public Void visitArrayType(ArrayType t, List<TypeAnnotationPosition.TypePathEntry> path) { |
2432 | | - visit(t.elemtype, path.append(TypeAnnotationPosition.TypePathEntry.ARRAY)); |
2433 | | - return super.visitArrayType(t, path); |
| 2423 | + public Type visitWildcardType( |
| 2424 | + WildcardType wt, List<TypeAnnotationPosition.TypePathEntry> path) { |
| 2425 | + Type t = wt.type; |
| 2426 | + if (t != null) { |
| 2427 | + t = visit(t, path.append(TypeAnnotationPosition.TypePathEntry.WILDCARD)); |
| 2428 | + } |
| 2429 | + if (t != wt.type) { |
| 2430 | + wt = new WildcardType(t, wt.kind, wt.tsym, wt.bound, wt.getMetadata()); |
| 2431 | + } |
| 2432 | + return reannotate(wt, path); |
2434 | 2433 | } |
2435 | 2434 |
|
2436 | 2435 | @Override |
2437 | | - public Void visitType(Type t, List<TypeAnnotationPosition.TypePathEntry> path) { |
2438 | | - ListBuffer<Attribute.TypeCompound> attributes = attributesByPath.remove(path); |
2439 | | - if (attributes != null) { |
2440 | | - attributesByType.put(t, attributes.toList()); |
| 2436 | + public Type visitArrayType(ArrayType t, List<TypeAnnotationPosition.TypePathEntry> path) { |
| 2437 | + Type elemtype = t.elemtype; |
| 2438 | + Type elemtype1 = |
| 2439 | + visit(elemtype, path.append(TypeAnnotationPosition.TypePathEntry.ARRAY)); |
| 2440 | + if (elemtype1 != elemtype) { |
| 2441 | + t = new ArrayType(elemtype1, t.tsym, t.getMetadata()); |
2441 | 2442 | } |
2442 | | - return null; |
| 2443 | + return reannotate(t, path); |
2443 | 2444 | } |
2444 | | - } |
2445 | | - |
2446 | | - /** A type mapping that rewrites the type to include type annotations. */ |
2447 | | - private static class TypeAnnotationTypeMapping extends Type.StructuralTypeMapping<Void> { |
2448 | 2445 |
|
2449 | | - private final Map<Type, List<Attribute.TypeCompound>> attributesByType; |
2450 | | - |
2451 | | - private TypeAnnotationTypeMapping( |
2452 | | - Map<Type, List<Attribute.TypeCompound>> attributesByType) { |
2453 | | - this.attributesByType = attributesByType; |
| 2446 | + @Override |
| 2447 | + public Type visitType(Type t, List<TypeAnnotationPosition.TypePathEntry> path) { |
| 2448 | + return reannotate(t, path); |
2454 | 2449 | } |
2455 | 2450 |
|
2456 | | - private <T extends Type> Type reannotate(T t, BiFunction<T, Void, Type> f) { |
2457 | | - // We're relying on object identify of Type instances to record where the annotations |
2458 | | - // need to be added, so we have to retrieve the annotations for each type before |
2459 | | - // rewriting it, and then add them after its contained types have been rewritten. |
2460 | | - List<Attribute.TypeCompound> attributes = attributesByType.remove(t); |
2461 | | - Type mapped = f.apply(t, null); |
2462 | | - if (attributes == null) { |
2463 | | - return mapped; |
| 2451 | + Type reannotate(Type type, List<TypeAnnotationPosition.TypePathEntry> path) { |
| 2452 | + List<Attribute.TypeCompound> attributes = attributesForPath(path); |
| 2453 | + if (attributes.isEmpty()) { |
| 2454 | + return type; |
2464 | 2455 | } |
2465 | 2456 | // Runtime-visible and -invisible annotations are completed separately, so if the same |
2466 | 2457 | // type has annotations from both it will get annotated twice. |
2467 | | - TypeMetadata metadata = mapped.getMetadata(); |
| 2458 | + TypeMetadata metadata = type.getMetadata(); |
2468 | 2459 | TypeMetadata.Annotations existing = |
2469 | 2460 | (TypeMetadata.Annotations) metadata.get(TypeMetadata.Entry.Kind.ANNOTATIONS); |
2470 | 2461 | if (existing != null) { |
2471 | 2462 | TypeMetadata.Annotations combined = new TypeMetadata.Annotations( |
2472 | 2463 | existing.getAnnotations().appendList(attributes)); |
2473 | | - return mapped.cloneWithMetadata( |
| 2464 | + return type.cloneWithMetadata( |
2474 | 2465 | metadata.without(TypeMetadata.Entry.Kind.ANNOTATIONS).combine(combined)); |
2475 | 2466 | } |
2476 | | - return mapped.annotatedType(attributes); |
2477 | | - } |
2478 | | - |
2479 | | - @Override |
2480 | | - public Type visitClassType(ClassType t, Void unused) { |
2481 | | - return reannotate(t, super::visitClassType); |
2482 | | - } |
2483 | | - |
2484 | | - @Override |
2485 | | - public Type visitWildcardType(WildcardType t, Void unused) { |
2486 | | - return reannotate(t, super::visitWildcardType); |
| 2467 | + return type.annotatedType(attributes); |
2487 | 2468 | } |
2488 | 2469 |
|
2489 | | - @Override |
2490 | | - public Type visitArrayType(ArrayType t, Void unused) { |
2491 | | - return reannotate(t, super::visitArrayType); |
2492 | | - } |
2493 | | - |
2494 | | - @Override |
2495 | | - public Type visitType(Type t, Void unused) { |
2496 | | - return reannotate(t, (x, u) -> x); |
| 2470 | + List<Attribute.TypeCompound> attributesForPath( |
| 2471 | + List<TypeAnnotationPosition.TypePathEntry> path) { |
| 2472 | + ListBuffer<Attribute.TypeCompound> attributes = attributesByPath.remove(path); |
| 2473 | + return attributes != null ? attributes.toList() : List.nil(); |
2497 | 2474 | } |
2498 | 2475 | } |
2499 | 2476 |
|
|
0 commit comments