framework.src.org.checkerframework.framework.type.visitor.AnnotatedTypeScanner Maven / Gradle / Ivy
Show all versions of checker Show documentation
package org.checkerframework.framework.type.visitor;
import java.util.IdentityHashMap;
import java.util.Map;
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;
/**
* A TypeVisitor that visits all the child tree nodes. To visit types
* of a particular type, just override the corresponding visitXYZ
* method. Inside your method, call super.visitXYZ to visit descendant
* nodes.
*
*
* The default implementation of the visitXYZ methods will determine a
* result as follows:
*
*
* - If the node being visited has no children, the result will be null.
* - If the node being visited has one child, the result will be the
* result of calling scan on that child. The child may be a simple
* node or itself a list of nodes.
* - If the node being visited has more
* than one child, the result will be determined by calling scan each
* child in turn, and then combining the result of each scan after the
* first with the cumulative result so far, as determined by the
* reduce(R, R) method. Each child may be either a simple node or a
* list of nodes. The default behavior of the reduce method is such
* that the result of the visitXYZ method will be the result of the
* last child scanned.
*
*
* Here is an example to count the parameter types number of nodes in
* a tree:
*
*
* class CountTypeVariable extends TreeScanner {
*
* @Override
* public Integer visitTypeVariable(ATypeVariable node, Void p) {
* return 1;
* }
*
* @Override
* public Integer reduce(Integer r1, Integer r2) {
* return (r1 == null ? 0 : r1) + (r2 == null ? 0 : r2);
* }
* }
*
*
* @param
* the return type of this visitor's methods. Use Void for
* visitors that do not need to return results.
* @param
* the type of the additional parameter to this visitor's
* methods. Use Void for visitors that do not need an
* additional parameter.
*/
public class AnnotatedTypeScanner implements AnnotatedTypeVisitor {
// To prevent infinite loops
protected final Map visitedNodes =
new IdentityHashMap();
/**
* Reset the scanner to allow reuse of the same instance.
* Subclasses should override this method to clear their additional
* state; they must call the super implementation.
*/
public void reset() {
visitedNodes.clear();
}
@Override
public final R visit(AnnotatedTypeMirror t) {
return visit(t, null);
}
@Override
public final R visit(AnnotatedTypeMirror type, P p) {
reset();
return scan(type, p);
}
/**
* Processes an element by calling e.accept(this, p); this method
* may be overridden by subclasses.
*
* @return the result of visiting {@code type}
*/
protected R scan(AnnotatedTypeMirror type, P p) {
return (type == null ? null : type.accept(this, p));
}
/**
* Processes an element by calling e.accept(this, p); this method
* may be overridden by subclasses.
*
* @return a visitor-specified result
*/
protected R scan(Iterable types, P p) {
if (types == null) {
return null;
}
R r = null;
boolean first = true;
for (AnnotatedTypeMirror type : types) {
r = (first ? scan(type, p) : scanAndReduce(type, p, r));
first = false;
}
return r;
}
protected R scanAndReduce(Iterable types, P p, R r) {
return reduce(scan(types, p), r);
}
public R scanAndReduce(AnnotatedTypeMirror type, P p, R r) {
return reduce(scan(type, p), r);
}
protected R reduce(R r1, R r2) {
if (r1 == null) {
return r2;
}
return r1;
}
@Override
public R visitDeclared(AnnotatedDeclaredType type, P p) {
if (visitedNodes.containsKey(type)) {
return visitedNodes.get(type);
}
visitedNodes.put(type, null);
R r = scan(type.getTypeArguments(), p);
return r;
}
@Override
public R visitIntersection(AnnotatedIntersectionType type, P p) {
if (visitedNodes.containsKey(type)) {
return visitedNodes.get(type);
}
visitedNodes.put(type, null);
R r = scan(type.directSuperTypes(), p);
return r;
}
@Override
public R visitUnion(AnnotatedUnionType type, P p) {
if (visitedNodes.containsKey(type)) {
return visitedNodes.get(type);
}
visitedNodes.put(type, null);
R r = scan(type.getAlternatives(), p);
return r;
}
@Override
public R visitArray(AnnotatedArrayType type, P p) {
R r = scan(type.getComponentType(), p);
return r;
}
@Override
public R visitExecutable(AnnotatedExecutableType type, P p) {
R r = scan(type.getReturnType(), p);
r = scanAndReduce(type.getReceiverType(), p, r);
r = scanAndReduce(type.getParameterTypes(), p, r);
r = scanAndReduce(type.getThrownTypes(), p, r);
r = scanAndReduce(type.getTypeVariables(), p, r);
return r;
}
@Override
public R visitTypeVariable(AnnotatedTypeVariable type, P p) {
if (visitedNodes.containsKey(type)) {
return visitedNodes.get(type);
}
visitedNodes.put(type, null);
R r = scan(type.getLowerBound(), p);
visitedNodes.put(type, r);
r = scanAndReduce(type.getUpperBound(), p, r);
visitedNodes.put(type, r);
return r;
}
@Override
public R visitNoType(AnnotatedNoType type, P p) {
return null;
}
@Override
public R visitNull(AnnotatedNullType type, P p) {
return null;
}
@Override
public R visitPrimitive(AnnotatedPrimitiveType type, P p) {
return null;
}
@Override
public R visitWildcard(AnnotatedWildcardType type, P p) {
if (visitedNodes.containsKey(type)) {
return visitedNodes.get(type);
}
visitedNodes.put(type, null);
R r = scan(type.getExtendsBound(), p);
visitedNodes.put(type, r);
r = scanAndReduce(type.getSuperBound(), p, r);
visitedNodes.put(type, r);
return r;
}
}