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);
}
Aggregations