/*
* This file is part of the OpenJML project.
* Author: David R. Cok
*/
package org.jmlspecs.openjml;
import java.util.Iterator;
import org.jmlspecs.openjml.JmlTree.*;
import com.sun.source.tree.LabeledStatementTree;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.TreeScanner;
import com.sun.tools.javac.tree.JCTree.JCLabeledStatement;
import com.sun.tools.javac.tree.JCTree.JCStatement;
/**
* This class is used to construct visitors that walk a Java/JML parse tree. The
* visit methods each call the method 'scan' on any children, which in turn
* causes those subtrees to be visited. A derived class that intends to do some
* work while walking the tree will override selected visit methods to do some
* work for that node and then will call the super method in order to continue
* the walking. The scan method can be overridden in order to do some processing
* for every node.
*
* @author David Cok
*
*/
public class JmlTreeScanner extends TreeScanner implements IJmlVisitor {
public static final int AST_JAVA_MODE = 0;
public static final int AST_JML_MODE = 1;
public static final int AST_SPEC_MODE = 2;
/** The mode in which subtrees are scanned: <BR>
* AST_JAVA_MODE scans the tree as it
* was parsed, ignoring convenience fields in which links to specs are
* placed, and ignoring the specs CU; <BR>
* AST_JML_MODE scans the tree as an individual compilation unit
* (no specs in other files, but including the specs that are part of that file)<BR>
* SPEC_MODE ignores parsed specs and instead scans through the
* summaries of specs (that come from the specification files).
*/
public int scanMode;
public JmlTreeScanner() {
scanMode = AST_JML_MODE;
}
public JmlTreeScanner(int mode) {
scanMode = mode;
}
public void scan(Iterable<? extends JCTree> list) {
Iterator<? extends JCTree> iter = list.iterator();
while (iter.hasNext()) scan(iter.next());
}
public void visitJmlBinary(JmlBinary that) {
scan(that.lhs);
scan(that.rhs);
}
public void visitJmlBlock(JmlBlock that) {
visitBlock(that);
}
public void visitJmlChoose(JmlChoose that) {
scan(that.orBlocks);
scan(that.elseBlock);
}
public void visitJmlClassDecl(JmlClassDecl that) {
if (scanMode == AST_SPEC_MODE) {
if (!that.isTypeChecked()) throw new RuntimeException("AST_SPEC_MODE requires that the Class be type-checked; class " + that.name + " is not.");
}
boolean isJML = (that.mods.flags & Utils.JMLBIT) != 0; // SHould use Utils.isJML(), but it needs a context value
if (!isJML || scanMode == AST_JML_MODE) visitClassDef(that);
if (scanMode == AST_SPEC_MODE) {
JmlSpecs.TypeSpecs ms = that.typeSpecs;
if (ms != null) {
scan(ms.modifiers);
scan(ms.clauses);
scan(ms.decls);
} else {
// FIXME - why does this happen: System.out.println("No specs found for " + that.name);
}
}
if (scanMode == AST_JML_MODE) {
JmlSpecs.TypeSpecs ms = that.typeSpecs;
// already done - scan(ms.modifiers);
if (ms != null) scan(ms.clauses);
if (ms != null) scan(ms.decls);
}
}
public void visitJmlCompilationUnit(JmlCompilationUnit that) {
scan(that.packageAnnotations);
scan(that.pid); // package id
scan(that.defs);
// if (scanMode == AST_JML_MODE) scan(that.parsedTopLevelModelTypes);
// if (scanMode == AST_SPEC_MODE) scan(that.specsTopLevelModelTypes);
}
public void visitJmlMethodSig(JmlMethodSig that) {
scan(that.expression);
scan(that.argtypes);
}
public void visitJmlDoWhileLoop(JmlDoWhileLoop that) {
scan(that.loopSpecs);
visitDoLoop(that);
}
public void visitJmlEnhancedForLoop(JmlEnhancedForLoop that) {
scan(that.loopSpecs);
visitForeachLoop(that);
}
public void visitJmlForLoop(JmlForLoop that) {
scan(that.loopSpecs);
visitForLoop(that);
}
public void visitJmlGroupName(JmlGroupName tree) {
scan(tree.selection);
}
public void visitJmlImport(JmlImport that) {
visitImport(that);
}
public void visitJmlLabeledStatement(JmlLabeledStatement that) {
// scan(that.extraStatements.toList());
scan(that.body);
}
public void visitJmlLblExpression(JmlLblExpression that) {
scan(that.expression);
}
public void visitJmlMethodClauseCallable(JmlMethodClauseCallable tree) {
scan(tree.keyword);
scan(tree.methodSignatures);
}
public void visitJmlMethodClauseConditional(JmlMethodClauseConditional tree) {
scan(tree.expression);
scan(tree.predicate);
}
public void visitJmlMethodClauseDecl(JmlMethodClauseDecl tree) {
for (JCTree.JCVariableDecl s: tree.decls) {
scan(s);
}
}
public void visitJmlMethodClauseExpr(JmlMethodClauseExpr tree) {
scan(tree.expression);
}
public void visitJmlMethodClauseGroup(JmlMethodClauseGroup tree) {
for (JCTree t: tree.cases) {
scan(t);
}
}
public void visitJmlMethodClauseSignals(JmlMethodClauseSignals tree) {
scan(tree.expression);
}
public void visitJmlMethodClauseSigOnly(JmlMethodClauseSignalsOnly tree) {
scan(tree.list);
}
public void visitJmlMethodClauseStoreRef(JmlMethodClauseStoreRef tree) {
scan(tree.list);
}
public void visitJmlMethodDecl(JmlMethodDecl that) {
if (scanMode == AST_SPEC_MODE) {
JmlSpecs.MethodSpecs ms = that.methodSpecsCombined;
scan(ms.mods);
scan(ms.cases);
}
if (scanMode == AST_JML_MODE) {
scan(that.cases);
}
visitMethodDef(that);
}
public void visitJmlMethodInvocation(JmlMethodInvocation that) {
scan(that.args);
}
public void visitJmlMethodSpecs(JmlMethodSpecs tree) {
scan(tree.cases);
scan(tree.impliesThatCases);
scan(tree.forExampleCases);
}
public void visitJmlModelProgramStatement(JmlModelProgramStatement that) {
scan(that.item);
}
public void visitJmlPrimitiveTypeTree(JmlPrimitiveTypeTree tree) {
// no children to scan
}
public void visitJmlQuantifiedExpr(JmlQuantifiedExpr that) {
scan(that.decls);
scan(that.range);
scan(that.value);
scan(that.racexpr);
}
public void visitJmlSetComprehension(JmlSetComprehension that) {
scan(that.newtype);
scan(that.variable);
scan(that.predicate);
}
public void visitJmlSingleton(JmlSingleton that) {
// no children to scan
}
public void visitJmlSpecificationCase(JmlSpecificationCase tree) {
scan(tree.modifiers);
scan(tree.clauses);
scan(tree.block);
}
public void visitJmlStatement(JmlStatement tree) {
scan(tree.statement);
}
public void visitJmlStatementDecls(JmlStatementDecls tree) {
for (JCTree.JCStatement s : tree.list) {
scan(s);
}
}
public void visitJmlStatementExpr(JmlStatementExpr tree) {
scan(tree.expression);
scan(tree.optionalExpression);
}
public void visitJmlStatementHavoc(JmlStatementHavoc tree) {
scan(tree.storerefs);
}
public void visitJmlStatementLoop(JmlStatementLoop tree) {
scan(tree.expression);
}
public void visitJmlStatementSpec(JmlStatementSpec tree) {
scan(tree.statementSpecs);
}
public void visitJmlStoreRefArrayRange(JmlStoreRefArrayRange that) {
scan(that.expression);
scan(that.lo);
scan(that.hi);
}
public void visitJmlStoreRefKeyword(JmlStoreRefKeyword that) {
// nothing to scan
}
public void visitJmlStoreRefListExpression(JmlStoreRefListExpression that) {
for (JCTree t: that.list) {
scan(t);
}
}
public void visitJmlTypeClauseConditional(JmlTypeClauseConditional tree) {
scan(tree.modifiers);
scan(tree.identifier);
scan(tree.expression);
}
public void visitJmlTypeClauseConstraint(JmlTypeClauseConstraint tree) {
scan(tree.modifiers);
scan(tree.expression);
scan(tree.sigs);
}
public void visitJmlTypeClauseDecl(JmlTypeClauseDecl tree) {
scan(tree.modifiers);
scan(tree.decl);
}
public void visitJmlTypeClauseExpr(JmlTypeClauseExpr tree) {
scan(tree.modifiers);
scan(tree.expression);
}
public void visitJmlTypeClauseIn(JmlTypeClauseIn tree) {
scan(tree.modifiers);
for (JmlGroupName g: tree.list) {
scan(g);
}
}
public void visitJmlTypeClauseInitializer(JmlTypeClauseInitializer tree) {
scan(tree.modifiers);
scan(tree.specs);
}
public void visitJmlTypeClauseMaps(JmlTypeClauseMaps tree) {
scan(tree.modifiers);
scan(tree.expression);
for (JmlGroupName g: tree.list) {
scan(g);
}
}
public void visitJmlTypeClauseMonitorsFor(JmlTypeClauseMonitorsFor tree) {
scan(tree.modifiers);
scan(tree.identifier);
for (JCTree.JCExpression e: tree.list) {
scan(e);
}
}
public void visitJmlTypeClauseRepresents(JmlTypeClauseRepresents tree) {
scan(tree.modifiers);
scan(tree.ident);
scan(tree.expression);
}
public void visitJmlVariableDecl(JmlVariableDecl that) {
visitVarDef(that);
if (scanMode == AST_SPEC_MODE) {
if (that.fieldSpecsCombined != null) {
scan(that.fieldSpecsCombined.mods);
scan(that.fieldSpecsCombined.list);
}
}
if (scanMode == AST_JML_MODE) {
if (that.fieldSpecs != null) {
scan(that.fieldSpecs.mods);
scan(that.fieldSpecs.list);
}
}
}
public void visitJmlWhileLoop(JmlWhileLoop that) {
scan(that.loopSpecs);
visitWhileLoop(that);
}
}