Search in sources :

Example 1 with SafeEffect

use of org.checkerframework.checker.guieffect.qual.SafeEffect 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)

Example 2 with SafeEffect

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

the class GuiEffectTypeFactory method getComputedEffectAtCallsite.

/**
 * Get the effect of a method call at its callsite, acknowledging polymorphic instantiation
 * using type use annotations.
 *
 * @param node The method invocation as an AST node.
 * @param callerReceiver The type of the receiver object if available. Used to resolve direct
 *     calls like "super()"
 * @param methodElt The element of the callee method.
 * @return The computed effect (SafeEffect or UIEffect) for the method call.
 */
public Effect getComputedEffectAtCallsite(MethodInvocationTree node, AnnotatedTypeMirror.AnnotatedDeclaredType callerReceiver, ExecutableElement methodElt) {
    Effect targetEffect = getDeclaredEffect(methodElt);
    if (targetEffect.isPoly()) {
        AnnotatedTypeMirror srcType = null;
        if (node.getMethodSelect().getKind() == Tree.Kind.MEMBER_SELECT) {
            ExpressionTree src = ((MemberSelectTree) node.getMethodSelect()).getExpression();
            srcType = getAnnotatedType(src);
        } else if (node.getMethodSelect().getKind() == Tree.Kind.IDENTIFIER) {
            // Tree.Kind.IDENTIFIER, e.g. a direct call like "super()"
            if (callerReceiver == null) {
                // Not enought information provided to instantiate this type-polymorphic effects
                return targetEffect;
            }
            srcType = callerReceiver;
        } else {
            ErrorReporter.errorAbort("Unexpected getMethodSelect() kind at callsite " + node);
        }
        // Instantiate type-polymorphic effects
        if (srcType.hasAnnotation(AlwaysSafe.class)) {
            targetEffect = new Effect(SafeEffect.class);
        } else if (srcType.hasAnnotation(UI.class)) {
            targetEffect = new Effect(UIEffect.class);
        }
    // Poly substitution would be a noop.
    }
    return targetEffect;
}
Also used : PolyUI(org.checkerframework.checker.guieffect.qual.PolyUI) UI(org.checkerframework.checker.guieffect.qual.UI) MemberSelectTree(com.sun.source.tree.MemberSelectTree) SafeEffect(org.checkerframework.checker.guieffect.qual.SafeEffect) LambdaExpressionTree(com.sun.source.tree.LambdaExpressionTree) ExpressionTree(com.sun.source.tree.ExpressionTree) SafeEffect(org.checkerframework.checker.guieffect.qual.SafeEffect) PolyUIEffect(org.checkerframework.checker.guieffect.qual.PolyUIEffect) UIEffect(org.checkerframework.checker.guieffect.qual.UIEffect) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror)

Aggregations

PolyUIEffect (org.checkerframework.checker.guieffect.qual.PolyUIEffect)2 SafeEffect (org.checkerframework.checker.guieffect.qual.SafeEffect)2 UIEffect (org.checkerframework.checker.guieffect.qual.UIEffect)2 AnnotatedTypeMirror (org.checkerframework.framework.type.AnnotatedTypeMirror)2 ExpressionTree (com.sun.source.tree.ExpressionTree)1 LambdaExpressionTree (com.sun.source.tree.LambdaExpressionTree)1 MemberSelectTree (com.sun.source.tree.MemberSelectTree)1 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 PolyUI (org.checkerframework.checker.guieffect.qual.PolyUI)1 PolyUIType (org.checkerframework.checker.guieffect.qual.PolyUIType)1 UI (org.checkerframework.checker.guieffect.qual.UI)1