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

framework.src.org.checkerframework.qualframework.poly.QualifierParameterHierarchy 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.42.0
Show newest version
package org.checkerframework.qualframework.poly;

import java.util.*;

import org.checkerframework.javacutil.Pair;

import org.checkerframework.qualframework.base.QualifierHierarchy;

/** This class provides a QualifierHierarchy implementation for
 * sets of qualifier parameters.  Under this hierarchy, A is a subtype of B iff
 * the value of each qualifier parameter in A is contained within the value of
 * the corresponding parameter in B.
 */
public class QualifierParameterHierarchy implements QualifierHierarchy> {
    private QualifierHierarchy> polyQualHierarchy;
    private QualifierHierarchy> containmentHierarchy;
    private List, Wildcard>> constraintTarget = null;

    /** The bottom QualParams in the QualifierHierarchy */
    public QualParams PARAMS_BOTTOM;
    /** The top QualParams in the QualifierHierarchy */
    public QualParams PARAMS_TOP;

    public QualifierParameterHierarchy(QualifierHierarchy> containmentHierarchy,
            QualifierHierarchy> polyQualHierarchy) {
        this.containmentHierarchy = containmentHierarchy;
        this.polyQualHierarchy = polyQualHierarchy;

        setTop(polyQualHierarchy);
        setBottom(polyQualHierarchy);
    }

    // We can't use constructor overloads for the following variants because
    // they all have the same erasure.

    /** Construct an instance from a {@link ContainmentHierarchy} or
     * equivalent.
     */
    public static  QualifierParameterHierarchy fromContainment(QualifierHierarchy> containmentHierarchy,
            QualifierHierarchy> polyQualHierarchy) {
        return new QualifierParameterHierarchy<>(containmentHierarchy, polyQualHierarchy);
    }

    /** Construct an instance from a {@link PolyQualHierarchy} or equivalent,
     * using the default {@link ContainmentHierarchy} implementation.
     */
    public static  QualifierParameterHierarchy fromPolyQual(QualifierHierarchy> polyQualHierarchy) {
        return fromContainment(new ContainmentHierarchy(polyQualHierarchy), polyQualHierarchy);
    }

    /** Construct an instance from a {@code QualifierHierarchy}, using the
     * default {@link PolyQualHierarchy} and {@link ContainmentHierarchy}
     * implementations.
     */
    public static  QualifierParameterHierarchy fromGround(QualifierHierarchy groundHierarchy) {
        return fromPolyQual(new PolyQualHierarchy(groundHierarchy));
    }


    /** Get the containment hierarchy that is used to compare wildcards. */
    protected QualifierHierarchy> getContaintmentHierarchy() {
        return containmentHierarchy;
    }

    /** Set a target for constraint generation.  When the current constraint
     * target is not {@code null}, all subtyping checks return {@code true} and
     * populate the target with a (subtype, supertype) pair for each
     * containment check that would normally be made.
     */
    public void setConstraintTarget(List, Wildcard>> constraintTarget) {
        this.constraintTarget = constraintTarget;
    }


    @Override
    public boolean isSubtype(QualParams subtype, QualParams supertype) {
        if (subtype.equals(supertype)) {
            return true;
        }

        if (subtype == PARAMS_BOTTOM || supertype == PARAMS_TOP) {
            return true;
        }

        // There is no corollary for PARAMS_BOTTOM, since the other would have to have every parameter.
        if (subtype == PARAMS_TOP
                && polyQualHierarchy.isSubtype(subtype.getPrimary(), supertype.getPrimary())
                && supertype.isEmpty()) {
            return true;
        }

        if (subtype == PARAMS_TOP || supertype == PARAMS_BOTTOM ||
                !subtype.keySet().equals(supertype.keySet())) {
            if (constraintTarget == null) {
                return false;
            } else {
                constraintTarget.add(null);
                return true;
            }
        }

        if (subtype.getPrimary() != null && supertype.getPrimary() != null) {
            if (constraintTarget == null) {
                if (!polyQualHierarchy.isSubtype(subtype.getPrimary(), supertype.getPrimary())) {
                    return false;
                }
            } else {
                constraintTarget.add(Pair.of(new Wildcard<>(subtype.getPrimary()), new Wildcard<>(supertype.getPrimary())));
            }
        }

        for (String k : subtype.keySet()) {
            if (constraintTarget == null) {
                if (!containmentHierarchy.isSubtype(subtype.get(k), supertype.get(k))) {
                    return false;
                }
            } else {
                constraintTarget.add(Pair.of(subtype.get(k), supertype.get(k)));
            }
        }

        return true;
    }

    @Override
    public QualParams leastUpperBound(QualParams a, QualParams b) {
        if (this.constraintTarget != null) {
            throw new UnsupportedOperationException("unexpected leastUpperBound when generating constraints");
        }

        if (a == PARAMS_BOTTOM) {
            return b;
        }

        if (b == PARAMS_BOTTOM) {
            return a;
        }

        if (a == PARAMS_TOP || b == PARAMS_TOP) {
            return PARAMS_TOP;
        }

        Map> result = new HashMap<>();

        for (String k : a.keySet()) {
            if (b.containsKey(k)) {
                result.put(k, containmentHierarchy.leastUpperBound(a.get(k), b.get(k)));
            } else {
                result.put(k, a.get(k));
            }
        }

        for (String k : b.keySet()) {
            if (!a.containsKey(k)) {
                result.put(k, b.get(k));
            }
        }

        PolyQual newPrimary = null;
        if (a.getPrimary() != null && b.getPrimary() != null) {
            newPrimary = polyQualHierarchy.leastUpperBound(a.getPrimary(), b.getPrimary());
        }
        return new QualParams(result, newPrimary);
    }

    @Override
    public QualParams greatestLowerBound(QualParams a, QualParams b) {
        if (this.constraintTarget != null) {
            throw new UnsupportedOperationException("unexpected leastUpperBound when generating constraints");
        }

        if (a == PARAMS_TOP) {
            return b;
        }

        if (b == PARAMS_TOP) {
            return a;
        }

        if (a == PARAMS_BOTTOM || b == PARAMS_BOTTOM) {
            return PARAMS_BOTTOM;
        }

        Map> result = new HashMap<>();

        for (String k : a.keySet()) {
            if (b.containsKey(k)) {
                result.put(k, containmentHierarchy.greatestLowerBound(a.get(k), b.get(k)));
            } else {
                result.put(k, a.get(k));
            }
        }

        for (String k : b.keySet()) {
            if (!a.containsKey(k)) {
                result.put(k, b.get(k));
            }
        }

        PolyQual newPrimary = null;
        if (a.getPrimary() != null && b.getPrimary() != null) {
            newPrimary = polyQualHierarchy.greatestLowerBound(a.getPrimary(), b.getPrimary());
        }
        return new QualParams(result, newPrimary);
    }

    /*package*/ static final String PARAMS_BOTTOM_TO_STRING = "__@RegexBottom__";
    /*package*/ static final String PARAMS_TOP_TO_STRING = "__@RegexTop__";

    /**
     * Create and set the top of the qual params hierarchy
     */
    private void setTop(final QualifierHierarchy> polyQualHierarchy) {
        PARAMS_TOP = new QualParams(polyQualHierarchy.getTop()) {
            public String toString() {
                return PARAMS_TOP_TO_STRING;
            }};
    }

    /**
     * Create and set the bottom of the qual params hierarchy
     */
    private void setBottom(final QualifierHierarchy> polyQualHierarchy) {
        PARAMS_BOTTOM = new QualParams(polyQualHierarchy.getBottom()) {
            public String toString() {
                return PARAMS_BOTTOM_TO_STRING;
            }};
    }

    @Override
    public QualParams getBottom() {
        return PARAMS_BOTTOM;
    }

    @Override
    public QualParams getTop() {
        return PARAMS_TOP;
    }
}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy