All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.checkerframework.framework.util.FieldInvariants Maven / Gradle / Ivy

Go to download

The Checker Framework enhances Java's type system to make it more powerful and useful. This lets software developers detect and prevent errors in their Java programs. The Checker Framework includes compiler plug-ins ("checkers") that find bugs or verify their absence. It also permits you to write your own compiler plug-ins.

There is a newer version: 3.43.0
Show newest version
package org.checkerframework.framework.util;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.lang.model.element.AnnotationMirror;
import javax.tools.Diagnostic.Kind;
import org.checkerframework.framework.source.DiagMessage;
import org.checkerframework.framework.type.AnnotatedTypeFactory;
import org.checkerframework.framework.type.QualifierHierarchy;
import org.checkerframework.javacutil.BugInCF;

/**
 * Represents field invariants, which the user states by writing {@code @FieldInvariant}. Think of
 * this as a set of (field, qualifier) pairs.
 *
 * 

A FieldInvariants object may be malformed (inconsistent number of fields and qualifiers). In * this case, the BaseTypeVisitor will issue an error. */ public class FieldInvariants { /** * A list of simple field names. A field may appear more than once in this list. This list has the * same length as {@code qualifiers}. */ private final List fields; /** * A list of qualifiers that apply to the field at the same index in {@code fields}. In a * well-formed FieldInvariants, has the same length as {@code fields}. */ private final List qualifiers; /** * Creates a new FieldInvariants object. The result is well-formed if length of qualifiers is * either 1 or equal to length of {@code fields}. * * @param fields list of fields * @param qualifiers list of qualifiers */ public FieldInvariants(List fields, List qualifiers) { this(null, fields, qualifiers); } /** * Creates a new object with all the invariants in {@code other}, plus those specified by {@code * fields} and {@code qualifiers}. The result is well-formed if length of qualifiers is either 1 * or equal to length of {@code fields}. * * @param other other invariant object, may be null * @param fields list of fields * @param qualifiers list of qualifiers */ public FieldInvariants( FieldInvariants other, List fields, List qualifiers) { if (qualifiers.size() == 1) { while (fields.size() > qualifiers.size()) { qualifiers.add(qualifiers.get(0)); } } if (other != null) { fields.addAll(other.fields); qualifiers.addAll(other.qualifiers); } this.fields = Collections.unmodifiableList(fields); this.qualifiers = qualifiers; } /** The simple names of the fields that have a qualifier. May contain duplicates. */ public List getFields() { return fields; } /** * Returns a list of qualifiers for {@code field}. If {@code field} has no qualifiers, returns an * empty list. * * @param field simple field name * @return a list of qualifiers for {@code field}, possibly empty */ public List getQualifiersFor(CharSequence field) { if (!isWellFormed()) { throw new BugInCF("malformed FieldInvariants"); } String fieldString = field.toString(); int index = fields.indexOf(fieldString); if (index == -1) { return Collections.emptyList(); } List list = new ArrayList<>(); for (int i = 0; i < fields.size(); i++) { if (fields.get(i).equals(fieldString)) { list.add(qualifiers.get(i)); } } return list; } /** * Returns true if there is a qualifier for each field in {@code fields}. * * @return true if there is a qualifier for each field in {@code fields} */ public boolean isWellFormed() { return qualifiers.size() == fields.size(); } /** * Returns null if {@code superInvar} is a super invariant, otherwise returns the error message. * * @param superInvar the value to check for being a super invariant * @param factory the type factory * @return null if {@code superInvar} is a super invariant, otherwise returns the error message */ public DiagMessage isSuperInvariant(FieldInvariants superInvar, AnnotatedTypeFactory factory) { QualifierHierarchy qualifierHierarchy = factory.getQualifierHierarchy(); if (!this.fields.containsAll(superInvar.fields)) { List missingFields = new ArrayList<>(superInvar.fields); missingFields.removeAll(fields); return new DiagMessage( Kind.ERROR, "field.invariant.not.found.superclass", String.join(", ", missingFields)); } for (String field : superInvar.fields) { List superQualifiers = superInvar.getQualifiersFor(field); List subQualifiers = this.getQualifiersFor(field); for (AnnotationMirror superA : superQualifiers) { AnnotationMirror sub = qualifierHierarchy.findAnnotationInSameHierarchy(subQualifiers, superA); if (sub == null || !qualifierHierarchy.isSubtype(sub, superA)) { return new DiagMessage( Kind.ERROR, "field.invariant.not.subtype.superclass", field, sub, superA); } } } return null; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy