1 /* |
1 /* |
2 * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. Oracle designates this |
7 * published by the Free Software Foundation. Oracle designates this |
390 new Attribute.Array(arrayOfOrigAnnoType, repeated)); |
390 new Attribute.Array(arrayOfOrigAnnoType, repeated)); |
391 annoTree = m.Annotation(new Attribute.Compound(targetContainerType, |
391 annoTree = m.Annotation(new Attribute.Compound(targetContainerType, |
392 List.of(p))); |
392 List.of(p))); |
393 |
393 |
394 if (!chk.annotationApplicable(annoTree, on)) |
394 if (!chk.annotationApplicable(annoTree, on)) |
395 log.error(annoTree.pos(), "invalid.containedby.annotation.incompatible.target", targetContainerType, origAnnoType); |
395 log.error(annoTree.pos(), "invalid.repeatable.annotation.incompatible.target", targetContainerType, origAnnoType); |
396 |
396 |
397 if (!chk.validateAnnotationDeferErrors(annoTree)) |
397 if (!chk.validateAnnotationDeferErrors(annoTree)) |
398 log.error(annoTree.pos(), "duplicate.annotation.invalid.repeated", origAnnoType); |
398 log.error(annoTree.pos(), "duplicate.annotation.invalid.repeated", origAnnoType); |
399 |
399 |
400 Attribute.Compound c = enterAnnotation(annoTree, |
400 Attribute.Compound c = enterAnnotation(annoTree, |
412 DiagnosticPosition pos) |
412 DiagnosticPosition pos) |
413 { |
413 { |
414 Type origAnnoType = currentAnno.type; |
414 Type origAnnoType = currentAnno.type; |
415 TypeSymbol origAnnoDecl = origAnnoType.tsym; |
415 TypeSymbol origAnnoDecl = origAnnoType.tsym; |
416 |
416 |
417 // Fetch the ContainedBy annotation from the current |
417 // Fetch the Repeatable annotation from the current |
418 // annotation's declaration, or null if it has none |
418 // annotation's declaration, or null if it has none |
419 Attribute.Compound ca = origAnnoDecl.attribute(syms.containedByType.tsym); |
419 Attribute.Compound ca = origAnnoDecl.attribute(syms.repeatableType.tsym); |
420 if (ca == null) { // has no ContainedBy annotation |
420 if (ca == null) { // has no Repeatable annotation |
421 log.error(pos, "duplicate.annotation.missing.container", origAnnoType, syms.containedByType); |
421 log.error(pos, "duplicate.annotation.missing.container", origAnnoType, syms.repeatableType); |
422 return null; |
422 return null; |
423 } |
423 } |
424 |
424 |
425 return filterSame(extractContainingType(ca, pos, origAnnoDecl), |
425 return filterSame(extractContainingType(ca, pos, origAnnoDecl), |
426 origAnnoType); |
426 origAnnoType); |
438 /** Extract the actual Type to be used for a containing annotation. */ |
438 /** Extract the actual Type to be used for a containing annotation. */ |
439 private Type extractContainingType(Attribute.Compound ca, |
439 private Type extractContainingType(Attribute.Compound ca, |
440 DiagnosticPosition pos, |
440 DiagnosticPosition pos, |
441 TypeSymbol annoDecl) |
441 TypeSymbol annoDecl) |
442 { |
442 { |
443 // The next three checks check that the ContainedBy annotation |
443 // The next three checks check that the Repeatable annotation |
444 // on the declaration of the annotation type that is repeating is |
444 // on the declaration of the annotation type that is repeating is |
445 // valid. |
445 // valid. |
446 |
446 |
447 // ContainedBy must have at least one element |
447 // Repeatable must have at least one element |
448 if (ca.values.isEmpty()) { |
448 if (ca.values.isEmpty()) { |
449 log.error(pos, "invalid.containedby.annotation", annoDecl); |
449 log.error(pos, "invalid.repeatable.annotation", annoDecl); |
450 return null; |
450 return null; |
451 } |
451 } |
452 Pair<MethodSymbol,Attribute> p = ca.values.head; |
452 Pair<MethodSymbol,Attribute> p = ca.values.head; |
453 Name name = p.fst.name; |
453 Name name = p.fst.name; |
454 if (name != names.value) { // should contain only one element, named "value" |
454 if (name != names.value) { // should contain only one element, named "value" |
455 log.error(pos, "invalid.containedby.annotation", annoDecl); |
455 log.error(pos, "invalid.repeatable.annotation", annoDecl); |
456 return null; |
456 return null; |
457 } |
457 } |
458 if (!(p.snd instanceof Attribute.Class)) { // check that the value of "value" is an Attribute.Class |
458 if (!(p.snd instanceof Attribute.Class)) { // check that the value of "value" is an Attribute.Class |
459 log.error(pos, "invalid.containedby.annotation", annoDecl); |
459 log.error(pos, "invalid.repeatable.annotation", annoDecl); |
460 return null; |
460 return null; |
461 } |
461 } |
462 |
462 |
463 return ((Attribute.Class)p.snd).getValue(); |
463 return ((Attribute.Class)p.snd).getValue(); |
464 } |
464 } |
489 error = true; |
489 error = true; |
490 } |
490 } |
491 } |
491 } |
492 if (error) { |
492 if (error) { |
493 log.error(pos, |
493 log.error(pos, |
494 "invalid.containedby.annotation.multiple.values", |
494 "invalid.repeatable.annotation.multiple.values", |
495 targetContainerType, |
495 targetContainerType, |
496 nr_value_elems); |
496 nr_value_elems); |
497 return null; |
497 return null; |
498 } else if (nr_value_elems == 0) { |
498 } else if (nr_value_elems == 0) { |
499 log.error(pos, |
499 log.error(pos, |
500 "invalid.containedby.annotation.no.value", |
500 "invalid.repeatable.annotation.no.value", |
501 targetContainerType); |
501 targetContainerType); |
502 return null; |
502 return null; |
503 } |
503 } |
504 |
504 |
505 // validate that the 'value' element is a method |
505 // validate that the 'value' element is a method |
506 // probably "impossible" to fail this |
506 // probably "impossible" to fail this |
507 if (containerValueSymbol.kind != Kinds.MTH) { |
507 if (containerValueSymbol.kind != Kinds.MTH) { |
508 log.error(pos, |
508 log.error(pos, |
509 "invalid.containedby.annotation.invalid.value", |
509 "invalid.repeatable.annotation.invalid.value", |
510 targetContainerType); |
510 targetContainerType); |
511 fatalError = true; |
511 fatalError = true; |
512 } |
512 } |
513 |
513 |
514 // validate that the 'value' element has the correct return type |
514 // validate that the 'value' element has the correct return type |
516 Type valueRetType = containerValueSymbol.type.getReturnType(); |
516 Type valueRetType = containerValueSymbol.type.getReturnType(); |
517 Type expectedType = types.makeArrayType(originalAnnoType); |
517 Type expectedType = types.makeArrayType(originalAnnoType); |
518 if (!(types.isArray(valueRetType) && |
518 if (!(types.isArray(valueRetType) && |
519 types.isSameType(expectedType, valueRetType))) { |
519 types.isSameType(expectedType, valueRetType))) { |
520 log.error(pos, |
520 log.error(pos, |
521 "invalid.containedby.annotation.value.return", |
521 "invalid.repeatable.annotation.value.return", |
522 targetContainerType, |
522 targetContainerType, |
523 valueRetType, |
523 valueRetType, |
524 expectedType); |
524 expectedType); |
525 fatalError = true; |
525 fatalError = true; |
526 } |
526 } |
527 if (error) { |
527 if (error) { |
528 fatalError = true; |
528 fatalError = true; |
529 } |
529 } |
530 |
530 |
531 // Explicitly no check for/validity of @ContainerFor. That is |
531 // The conditions for a valid containing annotation are made |
532 // done on declaration of the container, and at reflect time. |
|
533 |
|
534 // The rest of the conditions for a valid containing annotation are made |
|
535 // in Check.validateRepeatedAnnotaton(); |
532 // in Check.validateRepeatedAnnotaton(); |
536 |
533 |
537 return fatalError ? null : containerValueSymbol; |
534 return fatalError ? null : containerValueSymbol; |
538 } |
535 } |
539 } |
536 } |