Search in sources :

Example 1 with PolyUIEffect

use of org.checkerframework.checker.guieffect.qual.PolyUIEffect in project checker-framework by typetools.

the class GuiEffectTypeFactory method getDeclaredEffect.

/**
 * Calling context annotations
 *
 * <p>To make anon-inner-classes work, I need to climb the inheritance DAG, until I:
 *
 * <ul>
 *   <li>find the class/interface that declares this calling method (an anon inner class is a
 *       separate class that implements an interface)
 *   <li>check whether *that* declaration specifies @UI on either the type or method
 * </ul>
 *
 * A method has the UI effect when:
 *
 * <ol>
 *   <li>A method is UI if annotated @UIEffect
 *   <li>A method is UI if the enclosing class is annotated @UI or @UIType and the method is not
 *       annotated @AlwaysSafe
 *   <li>A method is UI if the corresponding method in the super-class/interface is UI, and this
 *       method is not annotated @AlwaysSafe, and this method resides in an anonymous inner
 *       class (named classes still require a package/class/method annotation to make it UI,
 *       only anon inner classes have this inheritance-by-default)
 *       <ul>
 *         <li>A method must be *annotated* UI if the method it overrides is *annotated* UI
 *         <li>A method must be *annotated* UI if it overrides a UI method and the enclosing
 *             class is not UI
 *       </ul>
 *   <li>It is an error if a method is UI but the same method in a super-type is not UI
 *   <li>It is an error if two super-types specify the same method, where one type says it's UI
 *       and one says it's not (it's possible to simply enforce the weaker (safe) effect, but
 *       this seems more principled, it's easier --- backwards-compatible --- to change our
 *       minds about this later)
 * </ol>
 */
public Effect getDeclaredEffect(ExecutableElement methodElt) {
    if (debugSpew) {
        System.err.println("begin mayHaveUIEffect(" + methodElt + ")");
    }
    AnnotationMirror targetUIP = getDeclAnnotation(methodElt, UIEffect.class);
    AnnotationMirror targetSafeP = getDeclAnnotation(methodElt, SafeEffect.class);
    AnnotationMirror targetPolyP = getDeclAnnotation(methodElt, PolyUIEffect.class);
    TypeElement targetClassElt = (TypeElement) methodElt.getEnclosingElement();
    if (debugSpew) {
        System.err.println("targetClassElt found");
    }
    // Short-circuit if the method is explicitly annotated
    if (targetSafeP != null) {
        if (debugSpew) {
            System.err.println("Method marked @SafeEffect");
        }
        return new Effect(SafeEffect.class);
    } else if (targetUIP != null) {
        if (debugSpew) {
            System.err.println("Method marked @UIEffect");
        }
        return new Effect(UIEffect.class);
    } else if (targetPolyP != null) {
        if (debugSpew) {
            System.err.println("Method marked @PolyUIEffect");
        }
        return new Effect(PolyUIEffect.class);
    }
    if (isUIType(targetClassElt)) {
        // Already checked, no explicit @SafeEffect annotation
        return new Effect(UIEffect.class);
    }
    // developer to be explicit.
    if (isAnonymousType(targetClassElt)) {
        // Refine this for polymorphic parents
        boolean canInheritParentEffects = true;
        DeclaredType directSuper = (DeclaredType) targetClassElt.getSuperclass();
        TypeElement superElt = (TypeElement) directSuper.asElement();
        // Anonymous subtypes of polymorphic classes other than object can't inherit
        if (getDeclAnnotation(superElt, PolyUIType.class) != null && !TypesUtils.isObject(directSuper)) {
            canInheritParentEffects = false;
        } else {
            for (TypeMirror ifaceM : targetClassElt.getInterfaces()) {
                DeclaredType iface = (DeclaredType) ifaceM;
                TypeElement ifaceElt = (TypeElement) iface.asElement();
                if (getDeclAnnotation(ifaceElt, PolyUIType.class) != null) {
                    canInheritParentEffects = false;
                }
            }
        }
        if (canInheritParentEffects) {
            Effect.EffectRange r = findInheritedEffectRange(targetClassElt, methodElt);
            return (r != null ? Effect.min(r.min, r.max) : new Effect(SafeEffect.class));
        }
    }
    return new Effect(SafeEffect.class);
}
Also used : AnnotationMirror(javax.lang.model.element.AnnotationMirror) PolyUIEffect(org.checkerframework.checker.guieffect.qual.PolyUIEffect) UIEffect(org.checkerframework.checker.guieffect.qual.UIEffect) PolyUIType(org.checkerframework.checker.guieffect.qual.PolyUIType) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror) TypeMirror(javax.lang.model.type.TypeMirror) TypeElement(javax.lang.model.element.TypeElement) SafeEffect(org.checkerframework.checker.guieffect.qual.SafeEffect) PolyUIEffect(org.checkerframework.checker.guieffect.qual.PolyUIEffect) UIEffect(org.checkerframework.checker.guieffect.qual.UIEffect) DeclaredType(javax.lang.model.type.DeclaredType)

Aggregations

AnnotationMirror (javax.lang.model.element.AnnotationMirror)1 TypeElement (javax.lang.model.element.TypeElement)1 DeclaredType (javax.lang.model.type.DeclaredType)1 TypeMirror (javax.lang.model.type.TypeMirror)1 PolyUIEffect (org.checkerframework.checker.guieffect.qual.PolyUIEffect)1 PolyUIType (org.checkerframework.checker.guieffect.qual.PolyUIType)1 SafeEffect (org.checkerframework.checker.guieffect.qual.SafeEffect)1 UIEffect (org.checkerframework.checker.guieffect.qual.UIEffect)1 AnnotatedTypeMirror (org.checkerframework.framework.type.AnnotatedTypeMirror)1