|
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; |
@@ -2348,13 +2348,8 @@ private Type addTypeAnnotations(Type type, Predicate<TypeAnnotationPosition> fil |
2348 | 2348 | .add(attribute); |
2349 | 2349 | } |
2350 | 2350 |
|
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 | | - |
2355 | 2351 | // 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()); |
2358 | 2353 |
|
2359 | 2354 | return type; |
2360 | 2355 | } |
@@ -2382,124 +2377,106 @@ private static Predicate<TypeAnnotationPosition> classExtends(int index) { |
2382 | 2377 | } |
2383 | 2378 |
|
2384 | 2379 | /** |
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. |
2387 | 2384 | */ |
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 | + |
2390 | 2388 | 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; |
2393 | 2390 |
|
2394 | | - private TypeAnnotationLocator( |
| 2391 | + private TypeAnnotationStructuralTypeMapping( |
2395 | 2392 | Map<List<TypeAnnotationPosition.TypePathEntry>, ListBuffer<Attribute.TypeCompound>> |
2396 | | - attributesByPath, |
2397 | | - Map<Type, List<Attribute.TypeCompound>> attributesByType) { |
| 2393 | + attributesByPath) { |
2398 | 2394 | this.attributesByPath = attributesByPath; |
2399 | | - this.attributesByType = attributesByType; |
2400 | 2395 | } |
2401 | 2396 |
|
| 2397 | + |
2402 | 2398 | @Override |
2403 | | - public Void visitClassType(ClassType t, List<TypeAnnotationPosition.TypePathEntry> path) { |
| 2399 | + public Type visitClassType(ClassType t, List<TypeAnnotationPosition.TypePathEntry> path) { |
2404 | 2400 | // As described in JVMS 4.7.20.2, type annotations on nested types are located with |
2405 | 2401 | // 'left-to-right' steps starting on 'the outermost part of the type for which a type |
2406 | 2402 | // annotation is admissible'. So the current path represents the outermost containing |
2407 | 2403 | // type of the type being visited, and we add type path steps for every contained nested |
2408 | 2404 | // 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; |
2412 | 2409 | 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); |
2424 | 2410 | path = path.append(TypeAnnotationPosition.TypePathEntry.INNER_TYPE); |
2425 | 2411 | } |
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); |
2427 | 2418 | } |
2428 | 2419 |
|
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())))); |
2434 | 2426 | } |
2435 | 2427 |
|
2436 | 2428 | @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); |
2440 | 2439 | } |
2441 | 2440 |
|
2442 | 2441 | @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()); |
2447 | 2448 | } |
2448 | | - return null; |
| 2449 | + return reannotate(t, path); |
2449 | 2450 | } |
2450 | | - } |
2451 | | - |
2452 | | - /** A type mapping that rewrites the type to include type annotations. */ |
2453 | | - private static class TypeAnnotationTypeMapping extends Type.StructuralTypeMapping<Void> { |
2454 | 2451 |
|
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); |
2460 | 2455 | } |
2461 | 2456 |
|
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; |
2470 | 2461 | } |
2471 | 2462 | // Runtime-visible and -invisible annotations are completed separately, so if the same |
2472 | 2463 | // type has annotations from both it will get annotated twice. |
2473 | | - TypeMetadata metadata = mapped.getMetadata(); |
| 2464 | + TypeMetadata metadata = type.getMetadata(); |
2474 | 2465 | TypeMetadata.Annotations existing = |
2475 | 2466 | (TypeMetadata.Annotations) metadata.get(TypeMetadata.Entry.Kind.ANNOTATIONS); |
2476 | 2467 | if (existing != null) { |
2477 | 2468 | TypeMetadata.Annotations combined = new TypeMetadata.Annotations( |
2478 | 2469 | existing.getAnnotations().appendList(attributes)); |
2479 | | - return mapped.cloneWithMetadata( |
| 2470 | + return type.cloneWithMetadata( |
2480 | 2471 | metadata.without(TypeMetadata.Entry.Kind.ANNOTATIONS).combine(combined)); |
2481 | 2472 | } |
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); |
2493 | 2474 | } |
2494 | 2475 |
|
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(); |
2503 | 2480 | } |
2504 | 2481 | } |
2505 | 2482 |
|
|
0 commit comments