package org.jmlspecs.openjml.esc; import static com.sun.tools.javac.code.TypeTag.CLASS; import java.util.LinkedList; import javax.tools.JavaFileObject; import org.jmlspecs.openjml.JmlTree.JmlMethodClauseExpr; import org.jmlspecs.openjml.JmlTree.JmlMethodDecl; import com.sun.tools.javac.code.Scope; import com.sun.tools.javac.code.Symbol.MethodSymbol; import com.sun.tools.javac.code.Symbol.TypeSymbol; import com.sun.tools.javac.code.Symbol.VarSymbol; import com.sun.tools.javac.code.Type; import com.sun.tools.javac.code.Types; import com.sun.tools.javac.tree.JCTree.JCExpression; import com.sun.tools.javac.tree.JCTree.JCMethodDecl; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.ListBuffer; /** This class holds a summary of specification and other useful data about a method. * It is only used during BasicBlock, but it is computed and cached on first request * (within the compilation context). The 'computeMethodInfo' call fills in the details. */ public class JmlMethodInfo { /** Creates an uninitialized instance from a method declaration */ public JmlMethodInfo(JCMethodDecl d, Context context) { this.decl = d; this.owner = d.sym; this.source = ((JmlMethodDecl)d).sourcefile; findOverrides(owner,context); } /** Creates an uninitialized instance from a method symbol */ public JmlMethodInfo(MethodSymbol msym, Context context) { this.decl = null; this.owner = msym; this.source = null; findOverrides(owner,context); } /** The symbol for this method */ MethodSymbol owner; /** The declaration for this method, if there is one */ /*@Nullable*/ JCMethodDecl decl; /** The JmlClassInfo stucture for the containing class */ JmlClassInfo classInfo; /** The file in which the method is declared and implemented */ JavaFileObject source; /** The name used as the result of the method - filled in during translation */ String resultName; /** Whether the result is used - filled in during translation */ boolean resultUsed = false; //FIXME JCExpression exceptionDecl; VarSymbol exceptionLocal; /** A list of all the forall predicates */ // FIXME - how interacts with spec cases java.util.List<JCVariableDecl> foralls = new LinkedList<JCVariableDecl>(); /** A list of all the old predicates */ // FIXME - how interacts with spec cases ListBuffer<JCVariableDecl> olds = new ListBuffer<JCVariableDecl>(); /** A list of the one combined requires predicate */ // FIXME - combined across inheritance? java.util.List<JmlMethodClauseExpr> requiresPredicates = new LinkedList<JmlMethodClauseExpr>(); /** A list of desugared ensures predicates (i.e. in the form \old(precondition) ==> postcondition )*/ java.util.List<JmlMethodClauseExpr> ensuresPredicates = new LinkedList<JmlMethodClauseExpr>(); /** A list of desugared signals predicates (i.e. in the form \old(precondition) ==> postcondition )*/ java.util.List<JmlMethodClauseExpr> exPredicates = new LinkedList<JmlMethodClauseExpr>(); /** A list of desugared signals_only predicates (i.e. in the form \old(precondition) ==> postcondition )*/ java.util.List<JmlMethodClauseExpr> sigPredicates = new LinkedList<JmlMethodClauseExpr>(); /** A list of desugared diverges predicates (i.e. in the form \old(precondition) ==> postcondition )*/ java.util.List<JmlMethodClauseExpr> divergesPredicates = new LinkedList<JmlMethodClauseExpr>(); /** A structure holding information about desugared assignable clauses */ public static class Entry { public Entry(JCExpression pre, java.util.List<JCExpression> list) { this.pre = pre; this.storerefs = list; } /** The precondition guarding this list of assignables */ // FIXME - with \old? public JCExpression pre; /** A list of storerefs for a particular spec case */ public java.util.List<JCExpression> storerefs; } /** A list of assignable clause information */ java.util.List<JmlMethodInfo.Entry> assignables = new LinkedList<JmlMethodInfo.Entry>(); /** A list of overridden methods from super classes */ java.util.List<MethodSymbol> overrides = new LinkedList<MethodSymbol>(); /** A list of overridden methods from super interfaces */ java.util.List<MethodSymbol> interfaceOverrides = new LinkedList<MethodSymbol>(); /** Finds declarations of methods being overridden, so we can use thier * specifications. */ // FIXME - need interfaces also protected void findOverrides(MethodSymbol sym, Context context) { MethodSymbol msym = sym; Types types = Types.instance(context); for (Type t = types.supertype(msym.owner.type); t.getTag() == CLASS; t = types.supertype(t)) { TypeSymbol c = t.tsym; Scope.Entry e = c.members().lookup(msym.name); while (e.scope != null) { if (msym.overrides(e.sym, (TypeSymbol)msym.owner, types, false)) { msym = (MethodSymbol)e.sym; if (msym != null) overrides.add(msym); break; } e = e.next(); } } } }