2777 } |
2777 } |
2778 } |
2778 } |
2779 } |
2779 } |
2780 |
2780 |
2781 private void validateTarget(Symbol container, Symbol contained, DiagnosticPosition pos) { |
2781 private void validateTarget(Symbol container, Symbol contained, DiagnosticPosition pos) { |
2782 Attribute.Array containedTarget = getAttributeTargetAttribute(contained); |
2782 // The set of targets the container is applicable to must be a subset |
2783 |
2783 // (with respect to annotation target semantics) of the set of targets |
2784 // If contained has no Target, we are done |
2784 // the contained is applicable to. The target sets may be implicit or |
2785 if (containedTarget == null) { |
2785 // explicit. |
2786 return; |
2786 |
2787 } |
2787 Set<Name> containerTargets; |
2788 |
|
2789 // If contained has Target m1, container must have a Target |
|
2790 // annotation, m2, and m2 must be a subset of m1. (This is |
|
2791 // trivially true if contained has no target as per above). |
|
2792 |
|
2793 // contained has target, but container has not, error |
|
2794 Attribute.Array containerTarget = getAttributeTargetAttribute(container); |
2788 Attribute.Array containerTarget = getAttributeTargetAttribute(container); |
2795 if (containerTarget == null) { |
2789 if (containerTarget == null) { |
2796 log.error(pos, "invalid.repeatable.annotation.incompatible.target", container, contained); |
2790 containerTargets = getDefaultTargetSet(); |
2797 return; |
2791 } else { |
2798 } |
2792 containerTargets = new HashSet<Name>(); |
2799 |
|
2800 Set<Name> containerTargets = new HashSet<Name>(); |
|
2801 for (Attribute app : containerTarget.values) { |
2793 for (Attribute app : containerTarget.values) { |
2802 if (!(app instanceof Attribute.Enum)) { |
2794 if (!(app instanceof Attribute.Enum)) { |
2803 continue; // recovery |
2795 continue; // recovery |
2804 } |
2796 } |
2805 Attribute.Enum e = (Attribute.Enum)app; |
2797 Attribute.Enum e = (Attribute.Enum)app; |
2806 containerTargets.add(e.value.name); |
2798 containerTargets.add(e.value.name); |
2807 } |
2799 } |
2808 |
2800 } |
2809 Set<Name> containedTargets = new HashSet<Name>(); |
2801 |
|
2802 Set<Name> containedTargets; |
|
2803 Attribute.Array containedTarget = getAttributeTargetAttribute(contained); |
|
2804 if (containedTarget == null) { |
|
2805 containedTargets = getDefaultTargetSet(); |
|
2806 } else { |
|
2807 containedTargets = new HashSet<Name>(); |
2810 for (Attribute app : containedTarget.values) { |
2808 for (Attribute app : containedTarget.values) { |
2811 if (!(app instanceof Attribute.Enum)) { |
2809 if (!(app instanceof Attribute.Enum)) { |
2812 continue; // recovery |
2810 continue; // recovery |
2813 } |
2811 } |
2814 Attribute.Enum e = (Attribute.Enum)app; |
2812 Attribute.Enum e = (Attribute.Enum)app; |
2815 containedTargets.add(e.value.name); |
2813 containedTargets.add(e.value.name); |
2816 } |
2814 } |
2817 |
2815 } |
2818 if (!isTargetSubset(containedTargets, containerTargets)) { |
2816 |
|
2817 if (!isTargetSubsetOf(containerTargets, containedTargets)) { |
2819 log.error(pos, "invalid.repeatable.annotation.incompatible.target", container, contained); |
2818 log.error(pos, "invalid.repeatable.annotation.incompatible.target", container, contained); |
2820 } |
2819 } |
2821 } |
2820 } |
2822 |
2821 |
2823 /** Checks that t is a subset of s, with respect to ElementType |
2822 /* get a set of names for the default target */ |
|
2823 private Set<Name> getDefaultTargetSet() { |
|
2824 if (defaultTargets == null) { |
|
2825 Set<Name> targets = new HashSet<Name>(); |
|
2826 targets.add(names.ANNOTATION_TYPE); |
|
2827 targets.add(names.CONSTRUCTOR); |
|
2828 targets.add(names.FIELD); |
|
2829 targets.add(names.LOCAL_VARIABLE); |
|
2830 targets.add(names.METHOD); |
|
2831 targets.add(names.PACKAGE); |
|
2832 targets.add(names.PARAMETER); |
|
2833 targets.add(names.TYPE); |
|
2834 |
|
2835 defaultTargets = java.util.Collections.unmodifiableSet(targets); |
|
2836 } |
|
2837 |
|
2838 return defaultTargets; |
|
2839 } |
|
2840 private Set<Name> defaultTargets; |
|
2841 |
|
2842 |
|
2843 /** Checks that s is a subset of t, with respect to ElementType |
2824 * semantics, specifically {ANNOTATION_TYPE} is a subset of {TYPE} |
2844 * semantics, specifically {ANNOTATION_TYPE} is a subset of {TYPE} |
2825 */ |
2845 */ |
2826 private boolean isTargetSubset(Set<Name> s, Set<Name> t) { |
2846 private boolean isTargetSubsetOf(Set<Name> s, Set<Name> t) { |
2827 // Check that all elements in t are present in s |
2847 // Check that all elements in s are present in t |
2828 for (Name n2 : t) { |
2848 for (Name n2 : s) { |
2829 boolean currentElementOk = false; |
2849 boolean currentElementOk = false; |
2830 for (Name n1 : s) { |
2850 for (Name n1 : t) { |
2831 if (n1 == n2) { |
2851 if (n1 == n2) { |
2832 currentElementOk = true; |
2852 currentElementOk = true; |
2833 break; |
2853 break; |
2834 } else if (n1 == names.TYPE && n2 == names.ANNOTATION_TYPE) { |
2854 } else if (n1 == names.TYPE && n2 == names.ANNOTATION_TYPE) { |
2835 currentElementOk = true; |
2855 currentElementOk = true; |