use of org.checkerframework.javacutil.TypeSystemError in project checker-framework by typetools.
the class MustCallConsistencyAnalyzer method isValidCreatesMustCallForExpression.
/**
* Checks the validity of the given expression from an invoked method's {@link
* org.checkerframework.checker.mustcall.qual.CreatesMustCallFor} annotation. Helper method for
* {@link #checkCreatesMustCallForInvocation(Set, MethodInvocationNode)}.
*
* <p>An expression is valid if one of the following conditions is true: 1) the expression is an
* owning pointer, 2) the expression already has a tracked Obligation (i.e. there is already a
* resource alias in some Obligation's resource alias set that refers to the expression), or 3)
* the method in which the invocation occurs also has an @CreatesMustCallFor annotation, with the
* same expression.
*
* @param obligations the currently-tracked Obligations; this value is side-effected if there is
* an Obligation in it which tracks {@code expression} as one of its resource aliases
* @param expression an element of a method's @CreatesMustCallFor annotation
* @param path the path to the invocation of the method from whose @CreateMustCallFor annotation
* {@code expression} came
* @return true iff the expression is valid, as defined above
*/
private boolean isValidCreatesMustCallForExpression(Set<Obligation> obligations, JavaExpression expression, TreePath path) {
if (expression instanceof FieldAccess) {
Element elt = ((FieldAccess) expression).getField();
if (!checker.hasOption(MustCallChecker.NO_LIGHTWEIGHT_OWNERSHIP) && typeFactory.getDeclAnnotation(elt, Owning.class) != null) {
// The expression is an Owning field. This satisfies case 1.
return true;
}
} else if (expression instanceof LocalVariable) {
Element elt = ((LocalVariable) expression).getElement();
if (!checker.hasOption(MustCallChecker.NO_LIGHTWEIGHT_OWNERSHIP) && typeFactory.getDeclAnnotation(elt, Owning.class) != null) {
// This satisfies case 1.
return true;
} else {
Obligation toRemove = null;
Obligation toAdd = null;
for (Obligation obligation : obligations) {
ResourceAlias alias = obligation.getResourceAlias(expression);
if (alias != null) {
// This satisfies case 2 above. Remove all its aliases, then return below.
if (toRemove != null) {
throw new TypeSystemError("tried to remove multiple sets containing a reset expression at once");
}
toRemove = obligation;
toAdd = new Obligation(ImmutableSet.of(alias));
}
}
if (toRemove != null) {
obligations.remove(toRemove);
obligations.add(toAdd);
// This satisfies case 2.
return true;
}
}
}
// TODO: Getting this every time is inefficient if a method has many @CreatesMustCallFor
// annotations, but that should be rare.
MethodTree enclosingMethodTree = TreePathUtil.enclosingMethod(path);
if (enclosingMethodTree == null) {
return false;
}
ExecutableElement enclosingMethodElt = TreeUtils.elementFromDeclaration(enclosingMethodTree);
MustCallAnnotatedTypeFactory mcAtf = typeFactory.getTypeFactoryOfSubchecker(MustCallChecker.class);
List<String> enclosingCmcfValues = ResourceLeakVisitor.getCreatesMustCallForValues(enclosingMethodElt, mcAtf, typeFactory);
if (enclosingCmcfValues.isEmpty()) {
return false;
}
for (String enclosingCmcfValue : enclosingCmcfValues) {
JavaExpression enclosingTarget;
try {
enclosingTarget = StringToJavaExpression.atMethodBody(enclosingCmcfValue, enclosingMethodTree, checker);
} catch (JavaExpressionParseException e) {
// Do not issue an error here, because it would be a duplicate.
// The error will be issued by the Transfer class of the checker,
// via the CreatesMustCallForElementSupplier interface.
enclosingTarget = null;
}
if (areSame(expression, enclosingTarget)) {
// This satisfies case 3.
return true;
}
}
return false;
}
use of org.checkerframework.javacutil.TypeSystemError in project checker-framework by typetools.
the class DefaultQualifierKindHierarchy method verifyHierarchy.
/**
* Verifies that the {@link DefaultQualifierKindHierarchy} is a valid hierarchy.
*
* @param directSuperMap mapping from qualifier to its direct supertypes; used to verify that a
* polymorphic annotation does not have a {@link SubtypeOf} meta-annotation
* @throws TypeSystemError if the hierarchy isn't valid
*/
@RequiresNonNull({ "this.qualifierKinds", "this.tops", "this.bottoms" })
protected void verifyHierarchy(@UnderInitialization DefaultQualifierKindHierarchy this, Map<DefaultQualifierKind, Set<DefaultQualifierKind>> directSuperMap) {
for (DefaultQualifierKind qualifierKind : qualifierKinds) {
boolean isPoly = qualifierKind.isPoly();
boolean hasSubtypeOfAnno = directSuperMap.containsKey(qualifierKind);
if (isPoly && hasSubtypeOfAnno) {
// Polymorphic qualifiers with upper and lower bounds are currently not supported.
throw new TypeSystemError("AnnotatedTypeFactory: " + qualifierKind + " is polymorphic and specifies super qualifiers.%n" + "Remove the @PolymorphicQualifier or @SubtypeOf annotation from it.");
} else if (!isPoly && !hasSubtypeOfAnno) {
throw new TypeSystemError("AnnotatedTypeFactory: %s does not specify its super qualifiers.%n" + "Add an @SubtypeOf or @PolymorphicQualifier annotation to it,%n" + "or if it is an alias, exclude it from `createSupportedTypeQualifiers()`.", qualifierKind);
} else if (isPoly) {
if (qualifierKind.top == null) {
throw new TypeSystemError("PolymorphicQualifier, %s, has to specify a type hierarchy in its" + " @PolymorphicQualifier meta-annotation, if more than one exists; top types:" + " [%s].", qualifierKind, StringsPlume.join(", ", tops));
} else if (!tops.contains(qualifierKind.top)) {
throw new TypeSystemError("Polymorphic qualifier %s has invalid top %s. Top qualifiers: %s", qualifierKind, qualifierKind.top, StringsPlume.join(", ", tops));
}
}
}
if (bottoms.size() != tops.size()) {
throw new TypeSystemError("Number of tops not equal to number of bottoms: Tops: [%s] Bottoms: [%s]", StringsPlume.join(", ", tops), StringsPlume.join(", ", bottoms));
}
}
use of org.checkerframework.javacutil.TypeSystemError in project checker-framework by typetools.
the class DefaultQualifierKindHierarchy method initializePolymorphicQualifiers.
/**
* Iterates over all the qualifier kinds and adds all polymorphic qualifier kinds to
* polymorphicQualifiers. Also sets {@link DefaultQualifierKind#poly} and {@link
* DefaultQualifierKind#top} for the polymorphic qualifiers, and sets {@link
* DefaultQualifierKind#poly} for the top qualifiers.
*
* <p>Requires that tops has been initialized.
*/
@RequiresNonNull({ "this.nameToQualifierKind", "this.qualifierKinds", "this.tops" })
protected void initializePolymorphicQualifiers(@UnderInitialization DefaultQualifierKindHierarchy this, ) {
for (DefaultQualifierKind qualifierKind : qualifierKinds) {
Class<? extends Annotation> clazz = qualifierKind.getAnnotationClass();
PolymorphicQualifier polyMetaAnno = clazz.getAnnotation(PolymorphicQualifier.class);
if (polyMetaAnno == null) {
continue;
}
qualifierKind.poly = qualifierKind;
String topName = QualifierKindHierarchy.annotationClassName(polyMetaAnno.value());
if (nameToQualifierKind.containsKey(topName)) {
qualifierKind.top = nameToQualifierKind.get(topName);
} else if (topName.equals(Annotation.class.getCanonicalName())) {
// then there must be exactly one top.
if (tops.size() == 1) {
qualifierKind.top = tops.iterator().next();
} else {
throw new TypeSystemError("Polymorphic qualifier %s did not specify a top annotation class. Tops: [%s]", qualifierKind, StringsPlume.join(", ", tops));
}
} else {
throw new TypeSystemError("Polymorphic qualifier %s's top, %s, is not a qualifier.", qualifierKind, topName);
}
qualifierKind.strictSuperTypes = Collections.singleton(qualifierKind.top);
qualifierKind.top.poly = qualifierKind;
}
}
use of org.checkerframework.javacutil.TypeSystemError in project checker-framework by typetools.
the class AnnotatedTypeFactory method postInit.
/**
* Actions that logically belong in the constructor, but need to run after the subclass
* constructor has completed. In particular, parseStubFiles() may try to do type resolution with
* this AnnotatedTypeFactory.
*/
protected void postInit() {
this.qualHierarchy = createQualifierHierarchy();
if (qualHierarchy == null) {
throw new TypeSystemError("AnnotatedTypeFactory with null qualifier hierarchy not supported.");
} else if (!qualHierarchy.isValid()) {
throw new TypeSystemError("AnnotatedTypeFactory: invalid qualifier hierarchy: %s %s ", qualHierarchy.getClass(), qualHierarchy);
}
this.typeHierarchy = createTypeHierarchy();
this.typeVarSubstitutor = createTypeVariableSubstitutor();
this.typeArgumentInference = createTypeArgumentInference();
this.qualifierUpperBounds = createQualifierUpperBounds();
// TODO: is this the best location for declaring this alias?
addAliasedDeclAnnotation(org.jmlspecs.annotation.Pure.class, org.checkerframework.dataflow.qual.Pure.class, AnnotationBuilder.fromClass(elements, org.checkerframework.dataflow.qual.Pure.class));
// Accommodate the inability to write @InheritedAnnotation on these annotations.
addInheritedAnnotation(AnnotationBuilder.fromClass(elements, org.checkerframework.dataflow.qual.Pure.class));
addInheritedAnnotation(AnnotationBuilder.fromClass(elements, org.checkerframework.dataflow.qual.SideEffectFree.class));
addInheritedAnnotation(AnnotationBuilder.fromClass(elements, org.checkerframework.dataflow.qual.Deterministic.class));
addInheritedAnnotation(AnnotationBuilder.fromClass(elements, org.checkerframework.dataflow.qual.TerminatesExecution.class));
initializeReflectionResolution();
if (this.getClass() == AnnotatedTypeFactory.class) {
this.parseAnnotationFiles();
}
TypeMirror iterableTypeMirror = ElementUtils.getTypeElement(processingEnv, Iterable.class).asType();
this.iterableDeclType = (AnnotatedDeclaredType) AnnotatedTypeMirror.createType(iterableTypeMirror, this, true);
}
use of org.checkerframework.javacutil.TypeSystemError in project checker-framework by typetools.
the class AnnotatedTypeFactory method checkSupportedQuals.
/**
* @throws BugInCF If supportedQuals is empty or if any of the support qualifiers has a @Target
* meta-annotation that contain something besides TYPE_USE or TYPE_PARAMETER. (@Target({}) is
* allowed.)
*/
private void checkSupportedQuals() {
if (supportedQuals.isEmpty()) {
throw new TypeSystemError("Found no supported qualifiers.");
}
for (Class<? extends Annotation> annotationClass : supportedQuals) {
// Check @Target values
ElementType[] targetValues = annotationClass.getAnnotation(Target.class).value();
List<ElementType> badTargetValues = new ArrayList<>();
for (ElementType element : targetValues) {
if (!(element == ElementType.TYPE_USE || element == ElementType.TYPE_PARAMETER)) {
// if there's an ElementType with an enumerated value of something other
// than TYPE_USE or TYPE_PARAMETER then it isn't a valid qualifier
badTargetValues.add(element);
}
}
if (!badTargetValues.isEmpty()) {
String msg = "The @Target meta-annotation on type qualifier " + annotationClass.toString() + " must not contain " + StringsPlume.conjunction("or", badTargetValues) + ".";
throw new TypeSystemError(msg);
}
}
}
Aggregations