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

framework.src.org.checkerframework.framework.type.visitor.EquivalentAtmComboScanner 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.framework.type.visitor;


import org.checkerframework.framework.type.AnnotatedTypeMirror;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedArrayType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedIntersectionType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedNoType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedNullType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedPrimitiveType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedUnionType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedWildcardType;
import org.checkerframework.framework.util.AtmCombo;

import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * EquivalentAtmComboScanner is an AtmComboVisitor that accepts combinations that are identical in TypeMirror structure
 * but might differ in contained AnnotationMirrors.  This method will scan the individual components of
 * the visited type pairs together.
*/
public abstract class EquivalentAtmComboScanner extends AbstractAtmComboVisitor {
    /**
     * A history of type pairs that have already been visited and  the return type of their visit
     */
    protected final Visited visited = new Visited();

    /**
     * Entry point for this scanner.
     */
    @Override
    public RETURN_TYPE visit(final AnnotatedTypeMirror type1, final AnnotatedTypeMirror type2, PARAM param) {
        visited.clear();
        return scan(type1, type2, param);
    }

    /**
     * In an AnnotatedTypeScanner a null type is encounter than null is returned.  A user may want to customize
     * the behavior of this scanner depending on whether or not one or both types is null.
     * @param type1 a nullable AnnotatedTypeMirror
     * @param type2 a nullable AnnotatedTypeMirror
     * @param param the visitor param
     * @return a subclass specific return type/value
     */
    protected abstract RETURN_TYPE scanWithNull(AnnotatedTypeMirror type1, AnnotatedTypeMirror type2, PARAM param);

    protected RETURN_TYPE scan(AnnotatedTypeMirror type1, AnnotatedTypeMirror type2, PARAM param) {
        if (type1 == null || type2 == null) {
            return scanWithNull(type1, type2, param);
        }

        return AtmCombo.accept(type1, type2, param, this);
    }

    protected RETURN_TYPE scan(Iterable types1,
                               Iterable types2,
                               PARAM param) {
        RETURN_TYPE r = null;
        boolean first = true;

        Iterator tIter1 = types1.iterator();
        Iterator tIter2 = types2.iterator();

        while (tIter1.hasNext() && tIter2.hasNext()) {
            final AnnotatedTypeMirror type1 = tIter1.next();
            final AnnotatedTypeMirror type2 = tIter2.next();

            r = first ? scan(type1, type2, param)
                      : scanAndReduce(type1, type2, param, r);
        }

        return r;
    }

    protected RETURN_TYPE scanAndReduce(Iterable types1,
                                        Iterable types2,
                                        PARAM param, RETURN_TYPE r) {
        return reduce(scan(types1, types2, param), r);
    }

    protected RETURN_TYPE scanAndReduce(AnnotatedTypeMirror type1, AnnotatedTypeMirror type2, PARAM param, RETURN_TYPE r) {
        return reduce(scan(type1, type2, param), r);
    }

    protected RETURN_TYPE reduce(RETURN_TYPE r1, RETURN_TYPE r2) {
        if (r1 == null) {
            return r2;
        }
        return r1;
    }

    @Override
    public RETURN_TYPE visitArray_Array(AnnotatedArrayType type1, AnnotatedArrayType type2, PARAM param) {
        if (visited.contains(type1, type2)) {
            return visited.getResult(type1, type2);
        }
        visited.add(type1, type2, null);

        return scan(type1.getComponentType(), type2.getComponentType(), param);
    }

    @Override
    public RETURN_TYPE visitDeclared_Declared(AnnotatedDeclaredType type1, AnnotatedDeclaredType type2, PARAM param) {
        if (visited.contains(type1, type2)) {
            return visited.getResult(type1, type2);
        }
        visited.add(type1, type2, null);

        return scan(type1.getTypeArguments(), type2.getTypeArguments(), param);
    }

    @Override
    public RETURN_TYPE visitExecutable_Executable(AnnotatedExecutableType type1, AnnotatedExecutableType type2, PARAM param) {
        if (visited.contains(type1, type2)) {
            return visited.getResult(type1, type2);
        }
        visited.add(type1, type2, null);

        RETURN_TYPE r = scan(type1.getReturnType(),  type2.getReturnType(),     param);
        r = scanAndReduce(type1.getReceiverType(),   type2.getReceiverType(),   param, r);
        r = scanAndReduce(type1.getParameterTypes(), type2.getParameterTypes(), param, r);
        r = scanAndReduce(type1.getThrownTypes(),    type2.getThrownTypes(),    param, r);
        r = scanAndReduce(type1.getTypeVariables(),  type2.getTypeVariables(),  param, r);
        return r;
    }

    @Override
    public RETURN_TYPE visitIntersection_Intersection(AnnotatedIntersectionType type1, AnnotatedIntersectionType type2, PARAM param) {
        if (visited.contains(type1, type2)) {
            return visited.getResult(type1, type2);
        }
        visited.add(type1, type2, null);

        return scan(type1.directSuperTypes(), type2.directSuperTypes(), param);
    }

    @Override
    public RETURN_TYPE visitNone_None(AnnotatedNoType type1, AnnotatedNoType type2, PARAM param) {
        return null;
    }

    @Override
    public RETURN_TYPE visitNull_Null(AnnotatedNullType type1, AnnotatedNullType type2, PARAM param) {
        return null;
    }

    @Override
    public RETURN_TYPE visitPrimitive_Primitive(AnnotatedPrimitiveType type1, AnnotatedPrimitiveType type2, PARAM param) {
        return null;
    }

    @Override
    public RETURN_TYPE visitUnion_Union(AnnotatedUnionType type1, AnnotatedUnionType type2, PARAM param) {
        if (visited.contains(type1, type2)) {
            return visited.getResult(type1, type2);
        }

        visited.add(type1, type2, null);

        return scan(type1.getAlternatives(), type2.getAlternatives(), param);
    }

    @Override
    public RETURN_TYPE visitTypevar_Typevar(AnnotatedTypeVariable type1, AnnotatedTypeVariable type2, PARAM param) {
        if (visited.contains(type1, type2)) {
            return visited.getResult(type1, type2);
        }

        visited.add(type1, type2, null);

        RETURN_TYPE r = scan(type1.getUpperBound(), type2.getUpperBound(), param);
        r = scanAndReduce(type1.getLowerBound(), type2.getLowerBound(), param, r);
        return r;
    }

    @Override
    public RETURN_TYPE visitWildcard_Wildcard(AnnotatedWildcardType type1, AnnotatedWildcardType type2, PARAM param) {
        if (visited.contains(type1, type2)) {
            return visited.getResult(type1, type2);
        }

        visited.add(type1, type2, null);

        RETURN_TYPE r = scan(type1.getExtendsBound(), type2.getExtendsBound(), param);
        r = scanAndReduce(type1.getSuperBound(), type2.getSuperBound(), param, r);
        return r;
    }

    protected class Visited {

        private final Map> visits = new IdentityHashMap<>();

        public void clear() {
            visits.clear();
        }

        public boolean contains(final AnnotatedTypeMirror type1, final AnnotatedTypeMirror type2) {
            Map recordFor1 = visits.get(type1);
            return recordFor1 != null && recordFor1.containsKey(type2);
        }

        public RETURN_TYPE getResult(final AnnotatedTypeMirror type1, final AnnotatedTypeMirror type2) {
            Map recordFor1 = visits.get(type1);
            if (recordFor1 == null) {
                return null;
            }

            return recordFor1.get(type2);
        }

        public void add(final AnnotatedTypeMirror type1, final AnnotatedTypeMirror type2, final RETURN_TYPE ret) {
            Map recordFor1 = visits.get(type1);
            if (recordFor1 == null) {
                recordFor1 = new IdentityHashMap();
                visits.put(type1, recordFor1);
            }

            recordFor1.put(type2, ret);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy