package checkers.types.visitors; import java.util.*; import java.lang.UnsupportedOperationException; import checkers.types.AnnotatedTypeMirror; import checkers.types.AnnotatedTypeMirror.*; /** * A TypeVisitor that takes an AnnotatedTypeMirror as a parameter, and * visits it simultaneously. Note that the parameter type must be * assignable to the visited type, or an assertion fails when visiting * an incompatible subtype. * * @see AnnotatedTypeScanner */ public class AnnotatedTypeComparer<R> extends AnnotatedTypeScanner<R, AnnotatedTypeMirror> { protected R scan(Iterable<? extends AnnotatedTypeMirror> types, Iterable<? extends AnnotatedTypeMirror> p) { if (types == null) return null; R r = null; boolean first = true; Iterator<? extends AnnotatedTypeMirror> tIter = types.iterator(), pIter = p.iterator(); while (tIter.hasNext() && pIter.hasNext()) { r = (first ? scan(tIter.next(), pIter.next()) : scanAndReduce(tIter.next(), pIter.next(), r)); first = false; } return r; } protected R scanAndReduce(Iterable<? extends AnnotatedTypeMirror> types, Iterable<? extends AnnotatedTypeMirror> p, R r) { return reduce(scan(types, p), r); } public R scanAndReduce(AnnotatedTypeMirror type, AnnotatedTypeMirror p, R r) { return reduce(scan(type, p), r); } @Override protected R scanAndReduce(Iterable<? extends AnnotatedTypeMirror> types, AnnotatedTypeMirror p, R r) { throw new UnsupportedOperationException(p + "is not Iterable<? extends AnnotatedTypeMirror>"); } @Override public final R visitDeclared(AnnotatedDeclaredType type, AnnotatedTypeMirror p) { assert p instanceof AnnotatedDeclaredType : p; R r = scan(type.getTypeArguments(), ((AnnotatedDeclaredType)p).getTypeArguments()); return r; } @Override public final R visitArray(AnnotatedArrayType type, AnnotatedTypeMirror p) { assert p instanceof AnnotatedArrayType : p; R r = scan(type.getComponentType(), ((AnnotatedArrayType)p).getComponentType()); return r; } @Override public final R visitExecutable(AnnotatedExecutableType type, AnnotatedTypeMirror p) { assert p instanceof AnnotatedExecutableType : p; AnnotatedExecutableType ex = (AnnotatedExecutableType) p; R r = scan(type.getReturnType(), ex.getReturnType()); r = scanAndReduce(type.getReceiverType(), ex.getReceiverType(), r); r = scanAndReduce(type.getParameterTypes(), ex.getParameterTypes(), r); r = scanAndReduce(type.getThrownTypes(), ex.getThrownTypes(), r); r = scanAndReduce(type.getTypeVariables(), ex.getTypeVariables(), r); return r; } @Override public R visitTypeVariable(AnnotatedTypeVariable type, AnnotatedTypeMirror p) { // assert p instanceof AnnotatedTypeVariable : p; R r; if (visitedNodes.containsKey(type)) { return visitedNodes.get(type); } if (p instanceof AnnotatedTypeVariable) { AnnotatedTypeVariable tv = (AnnotatedTypeVariable) p; r = scan(type.getLowerBound(), tv.getLowerBound()); visitedNodes.put(type, r); r = scanAndReduce(type.getUpperBound(), tv.getUpperBound(), r); visitedNodes.put(type, r); } else { r = scan(type.getLowerBound(), p.getErased()); visitedNodes.put(type, r); r = scanAndReduce(type.getUpperBound(), p, r); visitedNodes.put(type, r); } return r; } @Override public final R visitWildcard(AnnotatedWildcardType type, AnnotatedTypeMirror p) { assert p instanceof AnnotatedWildcardType : p; AnnotatedWildcardType w = (AnnotatedWildcardType) p; if (visitedNodes.containsKey(type)) { return visitedNodes.get(type); } R r = scan(type.getExtendsBound(), w.getExtendsBound()); visitedNodes.put(type, r); r = scanAndReduce(type.getSuperBound(), w.getSuperBound(), r); visitedNodes.put(type, r); return r; } }