package org.jmlspecs.openjml.esc;
import java.util.HashSet;
import java.util.Set;
import org.jmlspecs.openjml.JmlTree.JmlClassDecl;
import org.jmlspecs.openjml.JmlTree.JmlMethodDecl;
import org.jmlspecs.openjml.JmlTree.JmlMethodInvocation;
import org.jmlspecs.openjml.JmlTree.JmlVariableDecl;
import org.jmlspecs.openjml.JmlTreeScanner;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.code.TypeTag;
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
import com.sun.tools.javac.tree.JCTree.JCIdent;
import com.sun.tools.javac.tree.JCTree.JCInstanceOf;
import com.sun.tools.javac.tree.JCTree.JCLiteral;
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
import com.sun.tools.javac.tree.JCTree.JCTypeCast;
/** This class collects all mentions of classes within the ASTs scanned. */
class ClassCollector extends JmlTreeScanner {
/** Static method that is the entry point to the functionality the collector */
public static /*@ non_null pure */ ClassCollector collect(/*@ non_null */JmlClassDecl cd, /*@ nullable */JmlMethodDecl md) {
ClassCollector collector = new ClassCollector();
collector.doMethods = false;
collector.scan(cd);
if (md != null) {
collector.doMethods = true;
collector.scan(md);
}
return collector;
}
// FIXME - change to collecting TypeSymbol
boolean doMethods;
public final Set<ClassSymbol> classes = new HashSet<ClassSymbol>();
public ClassCollector() {
// scan all the specifications as well
scanMode = AST_SPEC_MODE;
}
// FIXME - what about generic type variables
protected void save(Type tt) {
if (tt != null && tt.getTag() != TypeTag.VOID && tt.getTag() != TypeTag.BOT && !tt.isPrimitive() && tt.tsym instanceof ClassSymbol) {
ClassSymbol c = (ClassSymbol)tt.tsym;
classes.add(c);
}
}
protected void save(Symbol sym) {
if (sym instanceof ClassSymbol) save(sym.type);
}
// Note - we do not include parent classes and interfaces
@Override
public void visitClassDef(JCClassDecl tree) {
classes.add(tree.sym);
super.visitClassDef(tree);
}
@Override
public void visitMethodDef(JCMethodDecl tree) {
if (!doMethods) return;
super.visitMethodDef(tree);
}
@Override
public void visitJmlVariableDecl(JmlVariableDecl tree) {
save(tree.sym.type);
super.visitJmlVariableDecl(tree);
}
@Override
public void visitIdent(JCIdent tree) {
save(tree.type);
super.visitIdent(tree);
}
@Override
public void visitLiteral(JCLiteral tree) {
save(tree.type);
super.visitLiteral(tree);
}
@Override
public void visitSelect(JCFieldAccess tree) {
save(tree.type);
super.visitSelect(tree);
}
@Override
public void visitJmlMethodInvocation(JmlMethodInvocation tree) {
save(tree.type);
super.visitJmlMethodInvocation(tree);
}
@Override
public void visitApply(JCMethodInvocation tree) {
save(tree.type);
super.visitApply(tree);
}
@Override
public void visitTypeCast(JCTypeCast tree) {
save(tree.type);
super.visitTypeCast(tree);
}
@Override
public void visitTypeTest(JCInstanceOf tree) {
save(tree.clazz.type);
super.visitTypeTest(tree);
}
// FIXME - generic visitType... methods
}