/*
* This file is part of the OpenJML project.
* Author: David R. Cok
*/
package org.jmlspecs.openjml;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.Log;
import com.sun.tools.javac.util.Options;
import com.sun.tools.javac.util.Log.WriterKind;
/**
* This is an Enum that contains information about command-line options for JML
* and related tools. To assist with future extensions, do not use the Enum type
* directly; rather use the OptionInterface interface.
*
* @author David Cok
*/
// FIXME - investigate integrating this with Option, OptionName; also change to
// something other than an enum since it is not extensible
// FIXME - best practice would use a resources file for all the help
// information; javac loads its resources on demand
public enum JmlOption implements IOption {
// Arguments: option as on CL; true=1 argument, false=0 args; help string
DIR("-dir",true,null,"Process all files, recursively, within this directory",null),
DIRS("-dirs",true,null,"Process all files, recursively, within these directories (listed as separate arguments, up to an argument that begins with a - sign)",null),
ENDOPTIONS("--",false,null,"Terminates option processing - all remaining arguments are files",null), // FIXME - fix or remove
KEYS("-keys",true,"","Identifiers for optional JML comments",null),
COMMAND("-command",true,"check","The command to execute (check,esc,rac,compile)",null),
CHECK("-check",false,null,"Does a JML syntax check","-command=check"),
COMPILE("-compile",false,null,"Does a Java-only compile","-command=compile"),
RAC("-rac",false,null,"Enables generating code instrumented with runtime assertion checks","-command=rac"),
ESC("-esc",false,null,"Enables static checking","-command=esc"),
BOOGIE("-boogie",false,false,"Enables static checking with boogie",null),
USEJAVACOMPILER("-java",false,false,"When on, the tool uses only the underlying javac or javadoc compiler (must be the first option)",null),
JML("-jml",false,true,"When on, the JML compiler is used and all JML constructs are ignored; use -no-jml to use OpenJML but ignore JML annotations",null),
STRICT("-strictJML",false,false,"Disables any JML extensions in OpenJML",null),
EXTENSIONS("-extensions",true,null,"Extension packages and classes (comma-separated qualified names)",null),
STOPIFERRORS("-stopIfParseErrors",false,false,"When enabled, stops after parsing if any files have parsing errors",null),
METHOD("-method",true,null,"Comma-separated list of method name patterns on which to run ESC",null),
EXCLUDE("-exclude",true,null,"Comma-separated list of method name patterns to exclude from ESC",null),
PROVER("-prover",true,null,"The prover to use to check verification conditions",null),
PROVEREXEC("-exec",true,null,"The prover executable to use",null),
LOGIC("-logic",true,null,"The SMT logic to use",null),
NONNULLBYDEFAULT("-nonnullByDefault",false,false,"Makes references non_null by default","-nullableByDefault=false"),
NULLABLEBYDEFAULT("-nullableByDefault",false,false,"Makes references nullable by default",null),
CODE_MATH("-code-math",true,"safe","Arithmetic mode for Java code",null),
SPEC_MATH("-spec-math",true,"bigint","Arithmetic mode for specifications",null),
// FIXME - turn default back to true when problems have been worked out
CHECK_ACCESSIBLE("-checkAccessible",false,false,"When on (the default), JML accessible clauses are checked",null),
SPECS("-specspath",true,null,"Specifies the directory path to search for specification files",null),
CHECKSPECSPATH("-checkSpecsPath",false,true,"When on (the default), warnings for non-existent specification path directories are issued",null),
PURITYCHECK("-purityCheck",false,false,"When on (off by default), warnings for use of impure methods are issued",null),
INTERNALSPECS("-internalSpecs",false,true,"When on (the default), automatically appends the internal specs directory to the specification path",null),
INTERNALRUNTIME("-internalRuntime",false,true,"When on (the default), automatically appends the internal JML runtime library to the classpath",null),
TIMEOUT("-timeout",true,null,"Number of seconds to limit any individual proof attempt (default infinite)",null),
SHOW_NOT_IMPLEMENTED("-showNotImplemented",false,false,"When on (off by default), warnings about unimplemented constructs are issued",null),
SHOW_NOT_EXECUTABLE("-showNotExecutable",false,false,"When on (off by default), warnings about non-executable constructs are issued",null),
VERBOSENESS("-verboseness",true,1,"Level of verboseness (0=quiet...4=debug)",null),
QUIET("-quiet",false,null,"Only output warnings and errors","-verboseness="+Utils.QUIET),
NORMAL("-normal",false,null,"Limited output","-verboseness="+Utils.NORMAL),
PROGRESS("-progress",false,null,"Shows progress through compilation phases","-verboseness="+Utils.PROGRESS),
JMLVERBOSE("-jmlverbose",false,null,"Like -verbose, but only jml information and not as much","-verboseness="+Utils.JMLVERBOSE),
JMLDEBUG("-jmldebug",false,null,"When on, the program emits lots of output (includes -progress)","-verboseness="+Utils.JMLDEBUG),
SHOW_OPTIONS("-showOptions",true, "none","When enabled, the values of options and properties are printed, for debugging",null),
JMLTESTING("-jmltesting",false,false,"Only used to generate tracing information during testing",null),
TRACE("-trace",false,false,"ESC: Enables tracing of counterexamples",null),
SHOW("-show",false,false,"Show intermediate programs",null),
ESC_MAX_WARNINGS("-escMaxWarnings",true,"all","ESC: Maximum number of warnings to find per method",null),
MAXWARNINGSPATH("-escMaxWarningsPath",false,false,"ESC: If true, find all counterexample paths to each invalid assert",null),
COUNTEREXAMPLE("-counterexample",false,false,"ESC: Enables output of complete, raw counterexample",null),
CE("-ce",false,null,"ESC: Enables output of complete, raw counterexample","-counterexample"),
SUBEXPRESSIONS("-subexpressions",false,false,"ESC: Enables tracing with subexpressions",null),
FEASIBILITY("-checkFeasibility",true,null,"ESC: Check feasibility of assumptions",null),
BENCHMARKS("-benchmarks",true,null,"ESC: Collects solver communications",null),
MINIMIZE_QUANTIFICATIONS("-minQuant",false,true,"Minimizes using quantifications, in favor of inlining",null),
QUANTS_FOR_TYPES("-typeQuants",true,"auto","Introduces quantified assertions for type variables (true, false, or auto)",null),
MODEL_FIELD_NO_REP("-modelFieldNoRep",true,"zero","RAC action when a model field has no represents clause (zero,ignore,warn)",null),
// ROOTS("-roots",false,false,"Enables the Reflective Object-Oriented Testing System---w00t!",null),
RAC_SHOW_SOURCE("-racShowSource",false,true,"RAC: Error messages will include source information",null),
RAC_CHECK_ASSUMPTIONS("-racCheckAssumptions",false,false,"RAC: Enables runtime checking that assumptions hold",null),
RAC_JAVA_CHECKS("-racJavaChecks",false,false,"RAC: Enables explicit checking of Java language checks",null),
RAC_COMPILE_TO_JAVA_ASSERT("-racCompileToJavaAssert",false,false,"RAC: Compiles JML checks as Java asserts",null),
RAC_PRECONDITION_ENTRY("-racPreconditionEntry",false,false,"RAC: Distinguishes Precondition failures on entry calls",null),
RAC_MISSING_MODEL_FIELD_REP_SOURCE("-racMissingModelFieldRepSource",true,"zero","RAC: action when a model field has no representation (zero,warn,skip)",null),
RAC_MISSING_MODEL_FIELD_REP_BINARY("-racMissingModelFieldRepBinary",true,"skip","RAC: action when a model field for a binary class has no representation (zero,warn,skip)",null),
PROPERTIES("-properties",true,null,"Specifies the path to the properties file",null),
PROPERTIES_DEFAULT("-properties-default",true,null,"Specifies the path to the default properties file",null),
// Obsolete
NOCHECKSPECSPATHX("-noCheckSpecsPath",false,false,"When on, no warnings for non-existent specification path directories are issued","-checkSpecsPath=false",true),
NOPURITYCHECKX("-noPurityCheck",false,false,"When on, no warnings for use of impure methods are issued","-purityCheck=false",true),
NOINTERNALSPECSX("-noInternalSpecs",false,false,"Disables automatically appending the internal specs directory to the specification path","-internalSpecs=false",true),
NOINTERNALRUNTIMEX("-noInternalRuntime",false,false,"Disables automatically appending the internal JML runtime library to the classpath","-internalRuntime=false",true),
NO_RAC_SOURCEX("-noRacSource",false,false,"RAC: Error messages will not include source information","-racShowSource=false",true),
NO_RAC_CHECK_ASSUMPTIONSX("-noRacCheckAssumptions",false,false,"RAC: Disables checking that assumptions hold","-racCheckAssumptions=false",true),
NO_RAC_JAVA_CHECKSX("-noRacJavaChecks",false,false,"RAC: Disables explicit checking of Java language checks","-racJavaChecks=false",true),
;
/** Holds the name of the option, as it is used in the command-line,
* including the leading '-' character.
*/
final private String name;
/** Whether the option takes an argument */
final private boolean hasArg;
/** The default value of the option */
final private Object defaultValue;
/** The help string for this option */
final private String help;
/** The canonical form for the option */
final private String synonym;
/** If true, the option is obsolete */
final private boolean obsolete;
/** Private constructor to create Enum instances.
* @param s The option name, including any leading - character
* @param defaultValue the default value for the option
* @param hasArg Whether the option takes a (required) argument
* @param help The associated help string
* @param synonym an equivalent command-line argument
*/
private JmlOption(/*@ non_null */ String s,
boolean hasArg,
Object defaultValue,
/*@ non_null */ String help,
/*@ nullable */ String synonym) {
this(s,hasArg,defaultValue,help,synonym,false);
}
/** Private constructor to create Enum instances.
* @param s The option name, including any leading - character
* @param defaultValue the default value for the option
* @param hasArg Whether the option takes a (required) argument
* @param help The associated help string
* @param synonym an equivalent command-line argument
* @param obsolete whether the option is obsolete
*/
private JmlOption(/*@ non_null */ String s,
boolean hasArg,
Object defaultValue,
/*@ non_null */ String help,
/*@ nullable */ String synonym,
boolean obsolete) {
this.name = s;
this.hasArg = hasArg;
this.defaultValue = defaultValue;
this.help = help;
this.synonym = synonym;
this.obsolete = obsolete;
}
/** Enables the given option
*
* @param context the compilation context
* @param option the option to enable
*/
public static void putOption(Context context, JmlOption option) {
putOption(context,option,"");
}
/** Sets the value of the given option
*
* @param context the compilation context
* @param option the option to set
* @param value the value to give the option - boolean options interpret null as false and non-null as true
*/
public static void putOption(Context context, JmlOption option, String value) {
Options.instance(context).put(option.name,value);
}
/** Sets the value of a boolean option, returning the previous value
* @param context the compilation context
* @param option the option name
* @param value the new value of the option
* @return true if the option was previously enabled, false otherwise
*/
public static boolean setOption(Context context, IOption option, boolean value) {
boolean b = isOption(context,option.optionName());
Options.instance(context).put(option.optionName(),value?"":null);
return b;
}
/** Return whether an option is enabled in the given context
* @param context the compilation context
* @param option the option name
* @return true if the option is enabled, false otherwise
*/
public static boolean isOption(Context context, JmlOption option) {
String val = Options.instance(context).get(option.name);
return val != null && !"false".equals(val);
}
/** Return whether an option is enabled in the given context
* @param context the compilation context
* @param option the option name by string (including leading -)
* @return true if the option is enabled, false otherwise
*/
public static boolean isOption(Context context, String option) {
return value(context,option) != null;
}
/** Return the value of an option with an argument
* @param context the compilation unit context
* @param option the option name
* @return the value of the argument, or null if not specified
*/
//@ nullable
public static String value(Context context, JmlOption option) {
return value(context,option.optionName());
}
/** Return the value of an option with an argument
* @param context the compilation unit context
* @param option the option name
* @return the value of the argument, or null if not specified
*/
//@ nullable
public static String value(Context context, String option) {
return Options.instance(context).get(option);
}
/** The name of the option, including any leading - sign
* @see org.jmlspecs.openjml.IOption#optionName()
*/
//@ non_null
public String optionName() { return name; }
/** The name of the option, including any leading - sign
* @see org.jmlspecs.openjml.IOption#optionName()
*/
//@ non_null
public String getText() { return name; }
/* Whether the option takes an argument
* @see org.jmlspecs.openjml.OptionInterface#hasArg()
*/
public boolean hasArg() { return hasArg; }
/* Whether the option takes an argument
* @see org.jmlspecs.openjml.OptionInterface#hasArg()
*/
public Object defaultValue() { return defaultValue; }
/* Whether the option is obsolete */
public boolean obsolete() { return obsolete; }
/**
* @return the help string associated with this option
*/
//@ non_null
public String help() {
if (synonym() == null) {
return help;
} else {
return help + " [" + synonym() + "]";
}
}
/**
* @return the canonical form for this option
*/
//@ nullable
public String synonym() { return synonym; }
/** Finds the option with the given name, returning it if
* found and returning null if not found.
* @param s the name of the option to find
* @return the option found, or null
*/
//@ ensures \result == null || \result.optionName().equals(s);
//@ nullable
static public JmlOption find(/*@ non_null */ String s) {
return map.get(s);
}
static private final Map<String,JmlOption> map = new HashMap<String,JmlOption>();
static {
// Puts all the options in the map and adds any synonyms
// synonyms include the all lowercase versions of each name
for (JmlOption n: JmlOption.values()) {
map.put(n.name,n);
map.put(n.name.toLowerCase(),n);
}
// Other synonyms
// FIXME - where did these come from - do we want them?
map.put("-nonnull",NONNULLBYDEFAULT);
map.put("-nullable",NULLABLEBYDEFAULT);
}
/** A help value which is the platform-dependent line termination string */
//@ non_null
final static public String eol = System.getProperty("line.separator");
/** Returns the JML command-line argument help information as a String
*
* @return the JML part of the command-line help information
*/
//@ non_null
public static String helpInfo() {
StringBuilder sb = new StringBuilder();
sb.append("JML options:").append(eol);
for (IOption j : values()) {
if (j.obsolete()) continue;
sb.append(" ").append(j.optionName()).append(" ");
// The count up to 26 is just to make for nice formatting
for (int i = j.optionName().length(); i<26; i++) {
sb.append(" ");
}
sb.append(j.help()).append(eol);
}
return sb.toString();
}
public static void listOptions(Context context, boolean all) {
Options options = JmlOptions.instance(context);
PrintWriter noticeWriter = Log.instance(context).getWriter(WriterKind.NOTICE);
for (String key: new java.util.TreeSet<String>(options.keySet())) {
if (all || key.startsWith("-") || key.startsWith("openjml") || key.startsWith("org.jmlspecs.openjml")) {
noticeWriter.println(key + " = " + JmlOption.value(context,key));
}
}
}
}