|
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; |
@@ -2461,13 +2461,8 @@ private Type addTypeAnnotations(Type type, Predicate<TypeAnnotationPosition> fil |
2461 | 2461 | .add(attribute); |
2462 | 2462 | } |
2463 | 2463 |
|
2464 | | - // Search the structure of the type to find the contained types at each type path |
2465 | | - Map<Type, List<Attribute.TypeCompound>> attributesByType = new HashMap<>(); |
2466 | | - new TypeAnnotationLocator(attributesByPath, attributesByType).visit(type, List.nil()); |
2467 | | - |
2468 | 2464 | // Rewrite the type and add the annotations |
2469 | | - type = new TypeAnnotationTypeMapping(attributesByType).visit(type, null); |
2470 | | - Assert.check(attributesByType.isEmpty(), "Failed to apply annotations to types"); |
| 2465 | + type = new TypeAnnotationStructuralTypeMapping(attributesByPath).visit(type, List.nil()); |
2471 | 2466 |
|
2472 | 2467 | return type; |
2473 | 2468 | } |
@@ -2495,120 +2490,102 @@ private static Predicate<TypeAnnotationPosition> classExtends(int index) { |
2495 | 2490 | } |
2496 | 2491 |
|
2497 | 2492 | /** |
2498 | | - * Visit all contained types, assembling a type path to represent the current location, and |
2499 | | - * record the types at each type path that need to be annotated. |
| 2493 | + * A type mapping that rewrites the type to include type annotations. |
| 2494 | + * |
| 2495 | + * <p>This logic is similar to {@link Type.StructuralTypeMapping}, but also tracks the path to |
| 2496 | + * the contained types being rewritten, and so cannot easily share the existing logic. |
2500 | 2497 | */ |
2501 | | - private static class TypeAnnotationLocator |
2502 | | - extends Types.DefaultTypeVisitor<Void, List<TypeAnnotationPosition.TypePathEntry>> { |
| 2498 | + private static final class TypeAnnotationStructuralTypeMapping |
| 2499 | + extends Types.TypeMapping<List<TypeAnnotationPosition.TypePathEntry>> { |
| 2500 | + |
2503 | 2501 | private final Map<List<TypeAnnotationPosition.TypePathEntry>, |
2504 | | - ListBuffer<Attribute.TypeCompound>> attributesByPath; |
2505 | | - private final Map<Type, List<Attribute.TypeCompound>> attributesByType; |
| 2502 | + ListBuffer<Attribute.TypeCompound>> attributesByPath; |
2506 | 2503 |
|
2507 | | - private TypeAnnotationLocator( |
| 2504 | + private TypeAnnotationStructuralTypeMapping( |
2508 | 2505 | Map<List<TypeAnnotationPosition.TypePathEntry>, ListBuffer<Attribute.TypeCompound>> |
2509 | | - attributesByPath, |
2510 | | - Map<Type, List<Attribute.TypeCompound>> attributesByType) { |
| 2506 | + attributesByPath) { |
2511 | 2507 | this.attributesByPath = attributesByPath; |
2512 | | - this.attributesByType = attributesByType; |
2513 | 2508 | } |
2514 | 2509 |
|
| 2510 | + |
2515 | 2511 | @Override |
2516 | | - public Void visitClassType(ClassType t, List<TypeAnnotationPosition.TypePathEntry> path) { |
| 2512 | + public Type visitClassType(ClassType t, List<TypeAnnotationPosition.TypePathEntry> path) { |
2517 | 2513 | // As described in JVMS 4.7.20.2, type annotations on nested types are located with |
2518 | 2514 | // 'left-to-right' steps starting on 'the outermost part of the type for which a type |
2519 | 2515 | // annotation is admissible'. So the current path represents the outermost containing |
2520 | 2516 | // type of the type being visited, and we add type path steps for every contained nested |
2521 | 2517 | // type. |
2522 | | - List<ClassType> enclosing = List.nil(); |
2523 | | - for (Type curr = t; |
2524 | | - curr != null && curr != Type.noType; |
| 2518 | + Type outer = t.getEnclosingType(); |
| 2519 | + Type outer1 = outer != Type.noType ? visit(outer, path) : outer; |
| 2520 | + for (Type curr = t.getEnclosingType(); |
| 2521 | + curr != Type.noType; |
2525 | 2522 | curr = curr.getEnclosingType()) { |
2526 | | - enclosing = enclosing.prepend((ClassType) curr); |
2527 | | - } |
2528 | | - for (ClassType te : enclosing) { |
2529 | | - if (te.typarams_field != null) { |
2530 | | - int i = 0; |
2531 | | - for (Type typaram : te.typarams_field) { |
2532 | | - visit(typaram, path.append(new TypeAnnotationPosition.TypePathEntry( |
2533 | | - TypeAnnotationPosition.TypePathEntryKind.TYPE_ARGUMENT, i++))); |
2534 | | - } |
2535 | | - } |
2536 | | - visitType(te, path); |
2537 | 2523 | path = path.append(TypeAnnotationPosition.TypePathEntry.INNER_TYPE); |
2538 | 2524 | } |
2539 | | - return null; |
| 2525 | + List<Type> typarams = t.getTypeArguments(); |
| 2526 | + List<Type> typarams1 = rewriteTypeParams(path, typarams); |
| 2527 | + if (outer1 != outer || typarams != typarams1) { |
| 2528 | + t = new ClassType(outer1, typarams1, t.tsym, t.getMetadata()); |
| 2529 | + } |
| 2530 | + return reannotate(t, path); |
2540 | 2531 | } |
2541 | 2532 |
|
2542 | | - @Override |
2543 | | - public Void visitWildcardType( |
2544 | | - WildcardType t, List<TypeAnnotationPosition.TypePathEntry> path) { |
2545 | | - visit(t.type, path.append(TypeAnnotationPosition.TypePathEntry.WILDCARD)); |
2546 | | - return super.visitWildcardType(t, path); |
| 2533 | + private List<Type> rewriteTypeParams( |
| 2534 | + List<TypeAnnotationPosition.TypePathEntry> path, List<Type> typarams) { |
| 2535 | + var i = IntStream.iterate(0, x -> x + 1).iterator(); |
| 2536 | + return typarams.map(typaram -> visit(typaram, |
| 2537 | + path.append(new TypeAnnotationPosition.TypePathEntry( |
| 2538 | + TypeAnnotationPosition.TypePathEntryKind.TYPE_ARGUMENT, i.nextInt())))); |
2547 | 2539 | } |
2548 | 2540 |
|
2549 | 2541 | @Override |
2550 | | - public Void visitArrayType(ArrayType t, List<TypeAnnotationPosition.TypePathEntry> path) { |
2551 | | - visit(t.elemtype, path.append(TypeAnnotationPosition.TypePathEntry.ARRAY)); |
2552 | | - return super.visitArrayType(t, path); |
| 2542 | + public Type visitWildcardType( |
| 2543 | + WildcardType wt, List<TypeAnnotationPosition.TypePathEntry> path) { |
| 2544 | + Type t = wt.type; |
| 2545 | + if (t != null) { |
| 2546 | + t = visit(t, path.append(TypeAnnotationPosition.TypePathEntry.WILDCARD)); |
| 2547 | + } |
| 2548 | + if (t != wt.type) { |
| 2549 | + wt = new WildcardType(t, wt.kind, wt.tsym, wt.bound, wt.getMetadata()); |
| 2550 | + } |
| 2551 | + return reannotate(wt, path); |
2553 | 2552 | } |
2554 | 2553 |
|
2555 | 2554 | @Override |
2556 | | - public Void visitType(Type t, List<TypeAnnotationPosition.TypePathEntry> path) { |
2557 | | - ListBuffer<Attribute.TypeCompound> attributes = attributesByPath.remove(path); |
2558 | | - if (attributes != null) { |
2559 | | - attributesByType.put(t, attributes.toList()); |
| 2555 | + public Type visitArrayType(ArrayType t, List<TypeAnnotationPosition.TypePathEntry> path) { |
| 2556 | + Type elemtype = t.elemtype; |
| 2557 | + Type elemtype1 = |
| 2558 | + visit(elemtype, path.append(TypeAnnotationPosition.TypePathEntry.ARRAY)); |
| 2559 | + if (elemtype1 != elemtype) { |
| 2560 | + t = new ArrayType(elemtype1, t.tsym, t.getMetadata()); |
2560 | 2561 | } |
2561 | | - return null; |
| 2562 | + return reannotate(t, path); |
2562 | 2563 | } |
2563 | | - } |
2564 | | - |
2565 | | - /** A type mapping that rewrites the type to include type annotations. */ |
2566 | | - private static class TypeAnnotationTypeMapping extends Type.StructuralTypeMapping<Void> { |
2567 | 2564 |
|
2568 | | - private final Map<Type, List<Attribute.TypeCompound>> attributesByType; |
2569 | | - |
2570 | | - private TypeAnnotationTypeMapping( |
2571 | | - Map<Type, List<Attribute.TypeCompound>> attributesByType) { |
2572 | | - this.attributesByType = attributesByType; |
| 2565 | + @Override |
| 2566 | + public Type visitType(Type t, List<TypeAnnotationPosition.TypePathEntry> path) { |
| 2567 | + return reannotate(t, path); |
2573 | 2568 | } |
2574 | 2569 |
|
2575 | | - private <T extends Type> Type reannotate(T t, BiFunction<T, Void, Type> f) { |
2576 | | - // We're relying on object identify of Type instances to record where the annotations |
2577 | | - // need to be added, so we have to retrieve the annotations for each type before |
2578 | | - // rewriting it, and then add them after its contained types have been rewritten. |
2579 | | - List<Attribute.TypeCompound> attributes = attributesByType.remove(t); |
2580 | | - Type mapped = f.apply(t, null); |
2581 | | - if (attributes == null) { |
2582 | | - return mapped; |
| 2570 | + Type reannotate(Type type, List<TypeAnnotationPosition.TypePathEntry> path) { |
| 2571 | + List<Attribute.TypeCompound> attributes = attributesForPath(path); |
| 2572 | + if (attributes.isEmpty()) { |
| 2573 | + return type; |
2583 | 2574 | } |
2584 | 2575 | // Runtime-visible and -invisible annotations are completed separately, so if the same |
2585 | 2576 | // type has annotations from both it will get annotated twice. |
2586 | | - TypeMetadata.Annotations existing = mapped.getMetadata(TypeMetadata.Annotations.class); |
| 2577 | + TypeMetadata.Annotations existing = type.getMetadata(TypeMetadata.Annotations.class); |
2587 | 2578 | if (existing != null) { |
2588 | 2579 | existing.annotationBuffer().addAll(attributes); |
2589 | | - return mapped; |
| 2580 | + return type; |
2590 | 2581 | } |
2591 | | - return mapped.annotatedType(attributes); |
| 2582 | + return type.annotatedType(attributes); |
2592 | 2583 | } |
2593 | 2584 |
|
2594 | | - @Override |
2595 | | - public Type visitClassType(ClassType t, Void unused) { |
2596 | | - return reannotate(t, super::visitClassType); |
2597 | | - } |
2598 | | - |
2599 | | - @Override |
2600 | | - public Type visitWildcardType(WildcardType t, Void unused) { |
2601 | | - return reannotate(t, super::visitWildcardType); |
2602 | | - } |
2603 | | - |
2604 | | - @Override |
2605 | | - public Type visitArrayType(ArrayType t, Void unused) { |
2606 | | - return reannotate(t, super::visitArrayType); |
2607 | | - } |
2608 | | - |
2609 | | - @Override |
2610 | | - public Type visitType(Type t, Void unused) { |
2611 | | - return reannotate(t, (x, u) -> x); |
| 2585 | + List<Attribute.TypeCompound> attributesForPath( |
| 2586 | + List<TypeAnnotationPosition.TypePathEntry> path) { |
| 2587 | + ListBuffer<Attribute.TypeCompound> attributes = attributesByPath.remove(path); |
| 2588 | + return attributes != null ? attributes.toList() : List.nil(); |
2612 | 2589 | } |
2613 | 2590 | } |
2614 | 2591 |
|
|
0 commit comments