use of org.checkerframework.checker.guieffect.qual.UI in project checker-framework by typetools.
the class GuiEffectTypeFactory method findInheritedEffectRange.
public Effect.EffectRange findInheritedEffectRange(TypeElement declaringType, ExecutableElement overridingMethod, boolean issueConflictWarning, Tree errorNode) {
assert (declaringType != null);
ExecutableElement ui_override = null;
ExecutableElement safe_override = null;
ExecutableElement poly_override = null;
// We must account for explicit annotation, type declaration annotations, and package
// annotations
boolean isUI = (getDeclAnnotation(overridingMethod, UIEffect.class) != null || isUIType(declaringType)) && getDeclAnnotation(overridingMethod, SafeEffect.class) == null;
boolean isPolyUI = getDeclAnnotation(overridingMethod, PolyUIEffect.class) != null;
// TODO: We must account for @UI and @AlwaysSafe annotations for extends
// and implements clauses, and do the proper substitution of @Poly effects and quals!
// List<? extends TypeMirror> interfaces = declaringType.getInterfaces();
TypeMirror superclass = declaringType.getSuperclass();
while (superclass != null && superclass.getKind() != TypeKind.NONE) {
ExecutableElement overrides = findJavaOverride(overridingMethod, superclass);
if (overrides != null) {
Effect eff = getDeclaredEffect(overrides);
assert (eff != null);
if (eff.isSafe()) {
// found a safe override
safe_override = overrides;
if (isUI && issueConflictWarning) {
checker.report(Result.failure("override.effect.invalid", overridingMethod, declaringType, safe_override, superclass), errorNode);
}
if (isPolyUI && issueConflictWarning) {
checker.report(Result.failure("override.effect.invalid.polymorphic", overridingMethod, declaringType, safe_override, superclass), errorNode);
}
} else if (eff.isUI()) {
// found a ui override
ui_override = overrides;
} else {
assert (eff.isPoly());
poly_override = overrides;
// TODO: Is this right? is the supertype covered by the
// directSuperTypes() method all I need? Or should I be
// using that utility method that returns a set of
// annodecl-method pairs given a method that overrides stuff
// if (isUI && issueConflictWarning) {
// AnnotatedTypeMirror.AnnotatedDeclaredType supdecl =
// fromElement((TypeElement)(((DeclaredType)superclass).asElement()));//((DeclaredType)superclass).asElement());
// // Need to special case an anonymous class with @UI on the decl, because
// "new @UI Runnable {...}" parses as @UI on an anon class decl extending
// Runnable
// boolean isAnonInstantiation =
// TypesUtils.isAnonymousType(ElementUtils.getType(declaringType)) &&
// getDeclAnnotation(declaringType, UI.class) != null;
// if (!isAnonInstantiation && !hasAnnotationByName(supdecl, UI.class)) {
// checker.report(Result.failure("override.effect.invalid",
// "non-UI instantiation of "+supdecl), errorNode);
// If uncommenting this, change the above line to match other calls of
// Result.failure("override.effect.invalid", ...)
// }
// }
}
}
DeclaredType decl = (DeclaredType) superclass;
superclass = ((TypeElement) decl.asElement()).getSuperclass();
}
AnnotatedTypeMirror.AnnotatedDeclaredType annoDecl = fromElement(declaringType);
for (AnnotatedTypeMirror.AnnotatedDeclaredType ty : annoDecl.directSuperTypes()) {
ExecutableElement overrides = findJavaOverride(overridingMethod, ty.getUnderlyingType());
if (overrides != null) {
Effect eff = getDeclaredEffect(overrides);
if (eff.isSafe()) {
// found a safe override
safe_override = overrides;
if (isUI && issueConflictWarning) {
checker.report(Result.failure("override.effect.invalid", overridingMethod, declaringType, safe_override, ty), errorNode);
}
if (isPolyUI && issueConflictWarning) {
checker.report(Result.failure("override.effect.invalid.polymorphic", overridingMethod, declaringType, safe_override, ty), errorNode);
}
} else if (eff.isUI()) {
// found a ui override
ui_override = overrides;
} else {
assert (eff.isPoly());
poly_override = overrides;
if (isUI && issueConflictWarning) {
AnnotatedTypeMirror.AnnotatedDeclaredType supdecl = ty;
// Need to special case an anonymous class with @UI on
// the decl, because "new @UI Runnable {...}" parses as
// @UI on an anon class decl extending Runnable
boolean isAnonInstantiation = isAnonymousType(declaringType) && fromElement(declaringType).hasAnnotation(UI.class);
if (!isAnonInstantiation && !supdecl.hasAnnotation(UI.class)) {
checker.report(Result.failure("override.effect.invalid.nonui", overridingMethod, declaringType, poly_override, supdecl), errorNode);
}
}
}
}
}
// We don't need to issue warnings for inheriting from poly and a concrete effect.
if (ui_override != null && safe_override != null && issueConflictWarning) {
// There may be more than two parent methods, but for now it's
// enough to know there are at least 2 in conflict
checker.report(Result.warning("override.effect.warning.inheritance", overridingMethod, declaringType, ui_override.toString(), ui_override.getEnclosingElement().asType().toString(), safe_override.toString(), safe_override.getEnclosingElement().asType().toString()), errorNode);
}
Effect min = (safe_override != null ? new Effect(SafeEffect.class) : (poly_override != null ? new Effect(PolyUIEffect.class) : (ui_override != null ? new Effect(UIEffect.class) : null)));
Effect max = (ui_override != null ? new Effect(UIEffect.class) : (poly_override != null ? new Effect(PolyUIEffect.class) : (safe_override != null ? new Effect(SafeEffect.class) : null)));
if (debugSpew) {
System.err.println("Found " + declaringType + "." + overridingMethod + " to have inheritance pair (" + min + "," + max + ")");
}
if (min == null && max == null) {
return null;
} else {
return new Effect.EffectRange(min, max);
}
}
Aggregations