src/share/classes/com/sun/tools/javac/comp/Check.java

changeset 1313
873ddd9f4900
parent 1296
cddc2c894cc6
child 1326
30c36e23f154
     1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Check.java	Mon Aug 27 10:59:13 2012 -0700
     1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Check.java	Fri Aug 31 10:37:46 2012 +0100
     1.3 @@ -69,7 +69,6 @@
     1.4      private final Infer infer;
     1.5      private final Types types;
     1.6      private final JCDiagnostic.Factory diags;
     1.7 -    private final boolean skipAnnotations;
     1.8      private boolean warnOnSyntheticConflicts;
     1.9      private boolean suppressAbortOnBadClassFile;
    1.10      private boolean enableSunApiLintControl;
    1.11 @@ -113,7 +112,6 @@
    1.12          allowCovariantReturns = source.allowCovariantReturns();
    1.13          allowSimplifiedVarargs = source.allowSimplifiedVarargs();
    1.14          complexInference = options.isSet("complexinference");
    1.15 -        skipAnnotations = options.isSet("skipAnnotations");
    1.16          warnOnSyntheticConflicts = options.isSet("warnOnSyntheticConflicts");
    1.17          suppressAbortOnBadClassFile = options.isSet("suppressAbortOnBadClassFile");
    1.18          enableSunApiLintControl = options.isSet("enableSunApiLintControl");
    1.19 @@ -2422,14 +2420,13 @@
    1.20      /** Check the annotations of a symbol.
    1.21       */
    1.22      public void validateAnnotations(List<JCAnnotation> annotations, Symbol s) {
    1.23 -        if (skipAnnotations) return;
    1.24          for (JCAnnotation a : annotations)
    1.25              validateAnnotation(a, s);
    1.26      }
    1.27  
    1.28      /** Check an annotation of a symbol.
    1.29       */
    1.30 -    public void validateAnnotation(JCAnnotation a, Symbol s) {
    1.31 +    private void validateAnnotation(JCAnnotation a, Symbol s) {
    1.32          validateAnnotationTree(a);
    1.33  
    1.34          if (!annotationApplicable(a, s))
    1.35 @@ -2441,6 +2438,215 @@
    1.36          }
    1.37      }
    1.38  
    1.39 +    /**
    1.40 +     * Validate the proposed container 'containedBy' on the
    1.41 +     * annotation type symbol 's'. Report errors at position
    1.42 +     * 'pos'.
    1.43 +     *
    1.44 +     * @param s The (annotation)type declaration annotated with a @ContainedBy
    1.45 +     * @param containerAnno the @ContainedBy on 's'
    1.46 +     * @param pos where to report errors
    1.47 +     */
    1.48 +    public void validateContainedBy(TypeSymbol s, Attribute.Compound containedBy, DiagnosticPosition pos) {
    1.49 +        Assert.check(types.isSameType(containedBy.type, syms.containedByType));
    1.50 +
    1.51 +        Type t = null;
    1.52 +        List<Pair<MethodSymbol,Attribute>> l = containedBy.values;
    1.53 +        if (!l.isEmpty()) {
    1.54 +            Assert.check(l.head.fst.name == names.value);
    1.55 +            t = ((Attribute.Class)l.head.snd).getValue();
    1.56 +        }
    1.57 +
    1.58 +        if (t == null) {
    1.59 +            log.error(pos, "invalid.container.wrong.containedby", s, containedBy);
    1.60 +            return;
    1.61 +        }
    1.62 +
    1.63 +        validateHasContainerFor(t.tsym, s, pos);
    1.64 +        validateRetention(t.tsym, s, pos);
    1.65 +        validateDocumented(t.tsym, s, pos);
    1.66 +        validateInherited(t.tsym, s, pos);
    1.67 +        validateTarget(t.tsym, s, pos);
    1.68 +    }
    1.69 +
    1.70 +    /**
    1.71 +     * Validate the proposed container 'containerFor' on the
    1.72 +     * annotation type symbol 's'. Report errors at position
    1.73 +     * 'pos'.
    1.74 +     *
    1.75 +     * @param s The (annotation)type declaration annotated with a @ContainerFor
    1.76 +     * @param containerFor the @ContainedFor on 's'
    1.77 +     * @param pos where to report errors
    1.78 +     */
    1.79 +    public void validateContainerFor(TypeSymbol s, Attribute.Compound containerFor, DiagnosticPosition pos) {
    1.80 +        Assert.check(types.isSameType(containerFor.type, syms.containerForType));
    1.81 +
    1.82 +        Type t = null;
    1.83 +        List<Pair<MethodSymbol,Attribute>> l = containerFor.values;
    1.84 +        if (!l.isEmpty()) {
    1.85 +            Assert.check(l.head.fst.name == names.value);
    1.86 +            t = ((Attribute.Class)l.head.snd).getValue();
    1.87 +        }
    1.88 +
    1.89 +        if (t == null) {
    1.90 +            log.error(pos, "invalid.container.wrong.containerfor", s, containerFor);
    1.91 +            return;
    1.92 +        }
    1.93 +
    1.94 +        validateHasContainedBy(t.tsym, s, pos);
    1.95 +    }
    1.96 +
    1.97 +    private void validateHasContainedBy(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos) {
    1.98 +        Attribute.Compound containedBy = container.attribute(syms.containedByType.tsym);
    1.99 +
   1.100 +        if (containedBy == null) {
   1.101 +            log.error(pos, "invalid.container.no.containedby", container, syms.containedByType.tsym);
   1.102 +            return;
   1.103 +        }
   1.104 +
   1.105 +        Type t = null;
   1.106 +        List<Pair<MethodSymbol,Attribute>> l = containedBy.values;
   1.107 +        if (!l.isEmpty()) {
   1.108 +            Assert.check(l.head.fst.name == names.value);
   1.109 +            t = ((Attribute.Class)l.head.snd).getValue();
   1.110 +        }
   1.111 +
   1.112 +        if (t == null) {
   1.113 +            log.error(pos, "invalid.container.wrong.containedby", container, contained);
   1.114 +            return;
   1.115 +        }
   1.116 +
   1.117 +        if (!types.isSameType(t, contained.type))
   1.118 +            log.error(pos, "invalid.container.wrong.containedby", t.tsym, contained);
   1.119 +    }
   1.120 +
   1.121 +    private void validateHasContainerFor(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos) {
   1.122 +        Attribute.Compound containerFor = container.attribute(syms.containerForType.tsym);
   1.123 +
   1.124 +        if (containerFor == null) {
   1.125 +            log.error(pos, "invalid.container.no.containerfor", container, syms.containerForType.tsym);
   1.126 +            return;
   1.127 +        }
   1.128 +
   1.129 +        Type t = null;
   1.130 +        List<Pair<MethodSymbol,Attribute>> l = containerFor.values;
   1.131 +        if (!l.isEmpty()) {
   1.132 +            Assert.check(l.head.fst.name == names.value);
   1.133 +            t = ((Attribute.Class)l.head.snd).getValue();
   1.134 +        }
   1.135 +
   1.136 +        if (t == null) {
   1.137 +            log.error(pos, "invalid.container.wrong.containerfor", container, contained);
   1.138 +            return;
   1.139 +        }
   1.140 +
   1.141 +        if (!types.isSameType(t, contained.type))
   1.142 +            log.error(pos, "invalid.container.wrong.containerfor", t.tsym, contained);
   1.143 +    }
   1.144 +
   1.145 +    private void validateRetention(Symbol container, Symbol contained, DiagnosticPosition pos) {
   1.146 +        Attribute.RetentionPolicy containerRetention = types.getRetention(container);
   1.147 +        Attribute.RetentionPolicy containedRetention = types.getRetention(contained);
   1.148 +
   1.149 +        boolean error = false;
   1.150 +        switch (containedRetention) {
   1.151 +        case RUNTIME:
   1.152 +            if (containerRetention != Attribute.RetentionPolicy.RUNTIME) {
   1.153 +                error = true;
   1.154 +            }
   1.155 +            break;
   1.156 +        case CLASS:
   1.157 +            if (containerRetention == Attribute.RetentionPolicy.SOURCE)  {
   1.158 +                error = true;
   1.159 +            }
   1.160 +        }
   1.161 +        if (error ) {
   1.162 +            log.error(pos, "invalid.containedby.annotation.retention",
   1.163 +                      container, containerRetention,
   1.164 +                      contained, containedRetention);
   1.165 +        }
   1.166 +    }
   1.167 +
   1.168 +    private void validateDocumented(Symbol container, Symbol contained, DiagnosticPosition pos) {
   1.169 +        if (contained.attribute(syms.documentedType.tsym) != null) {
   1.170 +            if (container.attribute(syms.documentedType.tsym) == null) {
   1.171 +                log.error(pos, "invalid.containedby.annotation.not.documented", container, contained);
   1.172 +            }
   1.173 +        }
   1.174 +    }
   1.175 +
   1.176 +    private void validateInherited(Symbol container, Symbol contained, DiagnosticPosition pos) {
   1.177 +        if (contained.attribute(syms.inheritedType.tsym) != null) {
   1.178 +            if (container.attribute(syms.inheritedType.tsym) == null) {
   1.179 +                log.error(pos, "invalid.containedby.annotation.not.inherited", container, contained);
   1.180 +            }
   1.181 +        }
   1.182 +    }
   1.183 +
   1.184 +    private void validateTarget(Symbol container, Symbol contained, DiagnosticPosition pos) {
   1.185 +        Attribute.Array containedTarget = getAttributeTargetAttribute(contained);
   1.186 +
   1.187 +        // If contained has no Target, we are done
   1.188 +        if (containedTarget == null) {
   1.189 +            return;
   1.190 +        }
   1.191 +
   1.192 +        // If contained has Target m1, container must have a Target
   1.193 +        // annotation, m2, and m2 must be a subset of m1. (This is
   1.194 +        // trivially true if contained has no target as per above).
   1.195 +
   1.196 +        // contained has target, but container has not, error
   1.197 +        Attribute.Array containerTarget = getAttributeTargetAttribute(container);
   1.198 +        if (containerTarget == null) {
   1.199 +            log.error(pos, "invalid.containedby.annotation.incompatible.target", container, contained);
   1.200 +            return;
   1.201 +        }
   1.202 +
   1.203 +        Set<Name> containerTargets = new HashSet<Name>();
   1.204 +        for (Attribute app : containerTarget.values) {
   1.205 +            if (!(app instanceof Attribute.Enum)) {
   1.206 +                continue; // recovery
   1.207 +            }
   1.208 +            Attribute.Enum e = (Attribute.Enum)app;
   1.209 +            containerTargets.add(e.value.name);
   1.210 +        }
   1.211 +
   1.212 +        Set<Name> containedTargets = new HashSet<Name>();
   1.213 +        for (Attribute app : containedTarget.values) {
   1.214 +            if (!(app instanceof Attribute.Enum)) {
   1.215 +                continue; // recovery
   1.216 +            }
   1.217 +            Attribute.Enum e = (Attribute.Enum)app;
   1.218 +            containedTargets.add(e.value.name);
   1.219 +        }
   1.220 +
   1.221 +        if (!isTargetSubset(containedTargets, containerTargets)) {
   1.222 +            log.error(pos, "invalid.containedby.annotation.incompatible.target", container, contained);
   1.223 +        }
   1.224 +    }
   1.225 +
   1.226 +    /** Checks that t is a subset of s, with respect to ElementType
   1.227 +     * semantics, specifically {ANNOTATION_TYPE} is a subset of {TYPE}
   1.228 +     */
   1.229 +    private boolean isTargetSubset(Set<Name> s, Set<Name> t) {
   1.230 +        // Check that all elements in t are present in s
   1.231 +        for (Name n2 : t) {
   1.232 +            boolean currentElementOk = false;
   1.233 +            for (Name n1 : s) {
   1.234 +                if (n1 == n2) {
   1.235 +                    currentElementOk = true;
   1.236 +                    break;
   1.237 +                } else if (n1 == names.TYPE && n2 == names.ANNOTATION_TYPE) {
   1.238 +                    currentElementOk = true;
   1.239 +                    break;
   1.240 +                }
   1.241 +            }
   1.242 +            if (!currentElementOk)
   1.243 +                return false;
   1.244 +        }
   1.245 +        return true;
   1.246 +    }
   1.247 +
   1.248      /** Is s a method symbol that overrides a method in a superclass? */
   1.249      boolean isOverrider(Symbol s) {
   1.250          if (s.kind != MTH || s.isStatic())
   1.251 @@ -2461,12 +2667,10 @@
   1.252  
   1.253      /** Is the annotation applicable to the symbol? */
   1.254      boolean annotationApplicable(JCAnnotation a, Symbol s) {
   1.255 -        Attribute.Compound atTarget =
   1.256 -            a.annotationType.type.tsym.attribute(syms.annotationTargetType.tsym);
   1.257 -        if (atTarget == null) return true;
   1.258 -        Attribute atValue = atTarget.member(names.value);
   1.259 -        if (!(atValue instanceof Attribute.Array)) return true; // error recovery
   1.260 -        Attribute.Array arr = (Attribute.Array) atValue;
   1.261 +        Attribute.Array arr = getAttributeTargetAttribute(a.annotationType.type.tsym);
   1.262 +        if (arr == null) {
   1.263 +            return true;
   1.264 +        }
   1.265          for (Attribute app : arr.values) {
   1.266              if (!(app instanceof Attribute.Enum)) return true; // recovery
   1.267              Attribute.Enum e = (Attribute.Enum) app;
   1.268 @@ -2508,6 +2712,16 @@
   1.269          return false;
   1.270      }
   1.271  
   1.272 +
   1.273 +    Attribute.Array getAttributeTargetAttribute(Symbol s) {
   1.274 +        Attribute.Compound atTarget =
   1.275 +            s.attribute(syms.annotationTargetType.tsym);
   1.276 +        if (atTarget == null) return null; // ok, is applicable
   1.277 +        Attribute atValue = atTarget.member(names.value);
   1.278 +        if (!(atValue instanceof Attribute.Array)) return null; // error recovery
   1.279 +        return (Attribute.Array) atValue;
   1.280 +    }
   1.281 +
   1.282      /** Check an annotation value.
   1.283       */
   1.284      public void validateAnnotation(JCAnnotation a) {

mercurial