langtools/src/share/classes/com/sun/tools/javac/comp/Check.java
changeset 13689 4d519199a6aa
parent 13438 83729994273a
child 13844 56339cf983a3
equal deleted inserted replaced
13636:bee2d435e11f 13689:4d519199a6aa
    67     private final Symtab syms;
    67     private final Symtab syms;
    68     private final Enter enter;
    68     private final Enter enter;
    69     private final Infer infer;
    69     private final Infer infer;
    70     private final Types types;
    70     private final Types types;
    71     private final JCDiagnostic.Factory diags;
    71     private final JCDiagnostic.Factory diags;
    72     private final boolean skipAnnotations;
       
    73     private boolean warnOnSyntheticConflicts;
    72     private boolean warnOnSyntheticConflicts;
    74     private boolean suppressAbortOnBadClassFile;
    73     private boolean suppressAbortOnBadClassFile;
    75     private boolean enableSunApiLintControl;
    74     private boolean enableSunApiLintControl;
    76     private final TreeInfo treeinfo;
    75     private final TreeInfo treeinfo;
    77 
    76 
   111         allowVarargs = source.allowVarargs();
   110         allowVarargs = source.allowVarargs();
   112         allowAnnotations = source.allowAnnotations();
   111         allowAnnotations = source.allowAnnotations();
   113         allowCovariantReturns = source.allowCovariantReturns();
   112         allowCovariantReturns = source.allowCovariantReturns();
   114         allowSimplifiedVarargs = source.allowSimplifiedVarargs();
   113         allowSimplifiedVarargs = source.allowSimplifiedVarargs();
   115         complexInference = options.isSet("complexinference");
   114         complexInference = options.isSet("complexinference");
   116         skipAnnotations = options.isSet("skipAnnotations");
       
   117         warnOnSyntheticConflicts = options.isSet("warnOnSyntheticConflicts");
   115         warnOnSyntheticConflicts = options.isSet("warnOnSyntheticConflicts");
   118         suppressAbortOnBadClassFile = options.isSet("suppressAbortOnBadClassFile");
   116         suppressAbortOnBadClassFile = options.isSet("suppressAbortOnBadClassFile");
   119         enableSunApiLintControl = options.isSet("enableSunApiLintControl");
   117         enableSunApiLintControl = options.isSet("enableSunApiLintControl");
   120 
   118 
   121         Target target = Target.instance(context);
   119         Target target = Target.instance(context);
  2420     }
  2418     }
  2421 
  2419 
  2422     /** Check the annotations of a symbol.
  2420     /** Check the annotations of a symbol.
  2423      */
  2421      */
  2424     public void validateAnnotations(List<JCAnnotation> annotations, Symbol s) {
  2422     public void validateAnnotations(List<JCAnnotation> annotations, Symbol s) {
  2425         if (skipAnnotations) return;
       
  2426         for (JCAnnotation a : annotations)
  2423         for (JCAnnotation a : annotations)
  2427             validateAnnotation(a, s);
  2424             validateAnnotation(a, s);
  2428     }
  2425     }
  2429 
  2426 
  2430     /** Check an annotation of a symbol.
  2427     /** Check an annotation of a symbol.
  2431      */
  2428      */
  2432     public void validateAnnotation(JCAnnotation a, Symbol s) {
  2429     private void validateAnnotation(JCAnnotation a, Symbol s) {
  2433         validateAnnotationTree(a);
  2430         validateAnnotationTree(a);
  2434 
  2431 
  2435         if (!annotationApplicable(a, s))
  2432         if (!annotationApplicable(a, s))
  2436             log.error(a.pos(), "annotation.type.not.applicable");
  2433             log.error(a.pos(), "annotation.type.not.applicable");
  2437 
  2434 
  2438         if (a.annotationType.type.tsym == syms.overrideType.tsym) {
  2435         if (a.annotationType.type.tsym == syms.overrideType.tsym) {
  2439             if (!isOverrider(s))
  2436             if (!isOverrider(s))
  2440                 log.error(a.pos(), "method.does.not.override.superclass");
  2437                 log.error(a.pos(), "method.does.not.override.superclass");
  2441         }
  2438         }
       
  2439     }
       
  2440 
       
  2441     /**
       
  2442      * Validate the proposed container 'containedBy' on the
       
  2443      * annotation type symbol 's'. Report errors at position
       
  2444      * 'pos'.
       
  2445      *
       
  2446      * @param s The (annotation)type declaration annotated with a @ContainedBy
       
  2447      * @param containerAnno the @ContainedBy on 's'
       
  2448      * @param pos where to report errors
       
  2449      */
       
  2450     public void validateContainedBy(TypeSymbol s, Attribute.Compound containedBy, DiagnosticPosition pos) {
       
  2451         Assert.check(types.isSameType(containedBy.type, syms.containedByType));
       
  2452 
       
  2453         Type t = null;
       
  2454         List<Pair<MethodSymbol,Attribute>> l = containedBy.values;
       
  2455         if (!l.isEmpty()) {
       
  2456             Assert.check(l.head.fst.name == names.value);
       
  2457             t = ((Attribute.Class)l.head.snd).getValue();
       
  2458         }
       
  2459 
       
  2460         if (t == null) {
       
  2461             log.error(pos, "invalid.container.wrong.containedby", s, containedBy);
       
  2462             return;
       
  2463         }
       
  2464 
       
  2465         validateHasContainerFor(t.tsym, s, pos);
       
  2466         validateRetention(t.tsym, s, pos);
       
  2467         validateDocumented(t.tsym, s, pos);
       
  2468         validateInherited(t.tsym, s, pos);
       
  2469         validateTarget(t.tsym, s, pos);
       
  2470     }
       
  2471 
       
  2472     /**
       
  2473      * Validate the proposed container 'containerFor' on the
       
  2474      * annotation type symbol 's'. Report errors at position
       
  2475      * 'pos'.
       
  2476      *
       
  2477      * @param s The (annotation)type declaration annotated with a @ContainerFor
       
  2478      * @param containerFor the @ContainedFor on 's'
       
  2479      * @param pos where to report errors
       
  2480      */
       
  2481     public void validateContainerFor(TypeSymbol s, Attribute.Compound containerFor, DiagnosticPosition pos) {
       
  2482         Assert.check(types.isSameType(containerFor.type, syms.containerForType));
       
  2483 
       
  2484         Type t = null;
       
  2485         List<Pair<MethodSymbol,Attribute>> l = containerFor.values;
       
  2486         if (!l.isEmpty()) {
       
  2487             Assert.check(l.head.fst.name == names.value);
       
  2488             t = ((Attribute.Class)l.head.snd).getValue();
       
  2489         }
       
  2490 
       
  2491         if (t == null) {
       
  2492             log.error(pos, "invalid.container.wrong.containerfor", s, containerFor);
       
  2493             return;
       
  2494         }
       
  2495 
       
  2496         validateHasContainedBy(t.tsym, s, pos);
       
  2497     }
       
  2498 
       
  2499     private void validateHasContainedBy(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos) {
       
  2500         Attribute.Compound containedBy = container.attribute(syms.containedByType.tsym);
       
  2501 
       
  2502         if (containedBy == null) {
       
  2503             log.error(pos, "invalid.container.no.containedby", container, syms.containedByType.tsym);
       
  2504             return;
       
  2505         }
       
  2506 
       
  2507         Type t = null;
       
  2508         List<Pair<MethodSymbol,Attribute>> l = containedBy.values;
       
  2509         if (!l.isEmpty()) {
       
  2510             Assert.check(l.head.fst.name == names.value);
       
  2511             t = ((Attribute.Class)l.head.snd).getValue();
       
  2512         }
       
  2513 
       
  2514         if (t == null) {
       
  2515             log.error(pos, "invalid.container.wrong.containedby", container, contained);
       
  2516             return;
       
  2517         }
       
  2518 
       
  2519         if (!types.isSameType(t, contained.type))
       
  2520             log.error(pos, "invalid.container.wrong.containedby", t.tsym, contained);
       
  2521     }
       
  2522 
       
  2523     private void validateHasContainerFor(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos) {
       
  2524         Attribute.Compound containerFor = container.attribute(syms.containerForType.tsym);
       
  2525 
       
  2526         if (containerFor == null) {
       
  2527             log.error(pos, "invalid.container.no.containerfor", container, syms.containerForType.tsym);
       
  2528             return;
       
  2529         }
       
  2530 
       
  2531         Type t = null;
       
  2532         List<Pair<MethodSymbol,Attribute>> l = containerFor.values;
       
  2533         if (!l.isEmpty()) {
       
  2534             Assert.check(l.head.fst.name == names.value);
       
  2535             t = ((Attribute.Class)l.head.snd).getValue();
       
  2536         }
       
  2537 
       
  2538         if (t == null) {
       
  2539             log.error(pos, "invalid.container.wrong.containerfor", container, contained);
       
  2540             return;
       
  2541         }
       
  2542 
       
  2543         if (!types.isSameType(t, contained.type))
       
  2544             log.error(pos, "invalid.container.wrong.containerfor", t.tsym, contained);
       
  2545     }
       
  2546 
       
  2547     private void validateRetention(Symbol container, Symbol contained, DiagnosticPosition pos) {
       
  2548         Attribute.RetentionPolicy containerRetention = types.getRetention(container);
       
  2549         Attribute.RetentionPolicy containedRetention = types.getRetention(contained);
       
  2550 
       
  2551         boolean error = false;
       
  2552         switch (containedRetention) {
       
  2553         case RUNTIME:
       
  2554             if (containerRetention != Attribute.RetentionPolicy.RUNTIME) {
       
  2555                 error = true;
       
  2556             }
       
  2557             break;
       
  2558         case CLASS:
       
  2559             if (containerRetention == Attribute.RetentionPolicy.SOURCE)  {
       
  2560                 error = true;
       
  2561             }
       
  2562         }
       
  2563         if (error ) {
       
  2564             log.error(pos, "invalid.containedby.annotation.retention",
       
  2565                       container, containerRetention,
       
  2566                       contained, containedRetention);
       
  2567         }
       
  2568     }
       
  2569 
       
  2570     private void validateDocumented(Symbol container, Symbol contained, DiagnosticPosition pos) {
       
  2571         if (contained.attribute(syms.documentedType.tsym) != null) {
       
  2572             if (container.attribute(syms.documentedType.tsym) == null) {
       
  2573                 log.error(pos, "invalid.containedby.annotation.not.documented", container, contained);
       
  2574             }
       
  2575         }
       
  2576     }
       
  2577 
       
  2578     private void validateInherited(Symbol container, Symbol contained, DiagnosticPosition pos) {
       
  2579         if (contained.attribute(syms.inheritedType.tsym) != null) {
       
  2580             if (container.attribute(syms.inheritedType.tsym) == null) {
       
  2581                 log.error(pos, "invalid.containedby.annotation.not.inherited", container, contained);
       
  2582             }
       
  2583         }
       
  2584     }
       
  2585 
       
  2586     private void validateTarget(Symbol container, Symbol contained, DiagnosticPosition pos) {
       
  2587         Attribute.Array containedTarget = getAttributeTargetAttribute(contained);
       
  2588 
       
  2589         // If contained has no Target, we are done
       
  2590         if (containedTarget == null) {
       
  2591             return;
       
  2592         }
       
  2593 
       
  2594         // If contained has Target m1, container must have a Target
       
  2595         // annotation, m2, and m2 must be a subset of m1. (This is
       
  2596         // trivially true if contained has no target as per above).
       
  2597 
       
  2598         // contained has target, but container has not, error
       
  2599         Attribute.Array containerTarget = getAttributeTargetAttribute(container);
       
  2600         if (containerTarget == null) {
       
  2601             log.error(pos, "invalid.containedby.annotation.incompatible.target", container, contained);
       
  2602             return;
       
  2603         }
       
  2604 
       
  2605         Set<Name> containerTargets = new HashSet<Name>();
       
  2606         for (Attribute app : containerTarget.values) {
       
  2607             if (!(app instanceof Attribute.Enum)) {
       
  2608                 continue; // recovery
       
  2609             }
       
  2610             Attribute.Enum e = (Attribute.Enum)app;
       
  2611             containerTargets.add(e.value.name);
       
  2612         }
       
  2613 
       
  2614         Set<Name> containedTargets = new HashSet<Name>();
       
  2615         for (Attribute app : containedTarget.values) {
       
  2616             if (!(app instanceof Attribute.Enum)) {
       
  2617                 continue; // recovery
       
  2618             }
       
  2619             Attribute.Enum e = (Attribute.Enum)app;
       
  2620             containedTargets.add(e.value.name);
       
  2621         }
       
  2622 
       
  2623         if (!isTargetSubset(containedTargets, containerTargets)) {
       
  2624             log.error(pos, "invalid.containedby.annotation.incompatible.target", container, contained);
       
  2625         }
       
  2626     }
       
  2627 
       
  2628     /** Checks that t is a subset of s, with respect to ElementType
       
  2629      * semantics, specifically {ANNOTATION_TYPE} is a subset of {TYPE}
       
  2630      */
       
  2631     private boolean isTargetSubset(Set<Name> s, Set<Name> t) {
       
  2632         // Check that all elements in t are present in s
       
  2633         for (Name n2 : t) {
       
  2634             boolean currentElementOk = false;
       
  2635             for (Name n1 : s) {
       
  2636                 if (n1 == n2) {
       
  2637                     currentElementOk = true;
       
  2638                     break;
       
  2639                 } else if (n1 == names.TYPE && n2 == names.ANNOTATION_TYPE) {
       
  2640                     currentElementOk = true;
       
  2641                     break;
       
  2642                 }
       
  2643             }
       
  2644             if (!currentElementOk)
       
  2645                 return false;
       
  2646         }
       
  2647         return true;
  2442     }
  2648     }
  2443 
  2649 
  2444     /** Is s a method symbol that overrides a method in a superclass? */
  2650     /** Is s a method symbol that overrides a method in a superclass? */
  2445     boolean isOverrider(Symbol s) {
  2651     boolean isOverrider(Symbol s) {
  2446         if (s.kind != MTH || s.isStatic())
  2652         if (s.kind != MTH || s.isStatic())
  2459         return false;
  2665         return false;
  2460     }
  2666     }
  2461 
  2667 
  2462     /** Is the annotation applicable to the symbol? */
  2668     /** Is the annotation applicable to the symbol? */
  2463     boolean annotationApplicable(JCAnnotation a, Symbol s) {
  2669     boolean annotationApplicable(JCAnnotation a, Symbol s) {
  2464         Attribute.Compound atTarget =
  2670         Attribute.Array arr = getAttributeTargetAttribute(a.annotationType.type.tsym);
  2465             a.annotationType.type.tsym.attribute(syms.annotationTargetType.tsym);
  2671         if (arr == null) {
  2466         if (atTarget == null) return true;
  2672             return true;
  2467         Attribute atValue = atTarget.member(names.value);
  2673         }
  2468         if (!(atValue instanceof Attribute.Array)) return true; // error recovery
       
  2469         Attribute.Array arr = (Attribute.Array) atValue;
       
  2470         for (Attribute app : arr.values) {
  2674         for (Attribute app : arr.values) {
  2471             if (!(app instanceof Attribute.Enum)) return true; // recovery
  2675             if (!(app instanceof Attribute.Enum)) return true; // recovery
  2472             Attribute.Enum e = (Attribute.Enum) app;
  2676             Attribute.Enum e = (Attribute.Enum) app;
  2473             if (e.value.name == names.TYPE)
  2677             if (e.value.name == names.TYPE)
  2474                 { if (s.kind == TYP) return true; }
  2678                 { if (s.kind == TYP) return true; }
  2504                 }
  2708                 }
  2505             else
  2709             else
  2506                 return true; // recovery
  2710                 return true; // recovery
  2507         }
  2711         }
  2508         return false;
  2712         return false;
       
  2713     }
       
  2714 
       
  2715 
       
  2716     Attribute.Array getAttributeTargetAttribute(Symbol s) {
       
  2717         Attribute.Compound atTarget =
       
  2718             s.attribute(syms.annotationTargetType.tsym);
       
  2719         if (atTarget == null) return null; // ok, is applicable
       
  2720         Attribute atValue = atTarget.member(names.value);
       
  2721         if (!(atValue instanceof Attribute.Array)) return null; // error recovery
       
  2722         return (Attribute.Array) atValue;
  2509     }
  2723     }
  2510 
  2724 
  2511     /** Check an annotation value.
  2725     /** Check an annotation value.
  2512      */
  2726      */
  2513     public void validateAnnotation(JCAnnotation a) {
  2727     public void validateAnnotation(JCAnnotation a) {