use of org.checkerframework.checker.nullness.qual.Nullable in project checker-framework by typetools.
the class GenericAnnotatedTypeFactory method createCFGVisualizer.
/**
* Create a new CFGVisualizer.
*
* @return a new CFGVisualizer, or null if none will be used on this run
*/
@Nullable
protected CFGVisualizer<Value, Store, TransferFunction> createCFGVisualizer() {
if (checker.hasOption("flowdotdir")) {
String flowdotdir = checker.getOption("flowdotdir");
if (flowdotdir.equals("")) {
throw new UserError("Emtpy string provided for -Aflowdotdir command-line argument");
}
boolean verbose = checker.hasOption("verbosecfg");
Map<String, Object> args = new HashMap<>(2);
args.put("outdir", flowdotdir);
args.put("verbose", verbose);
args.put("checkerName", getCheckerName());
CFGVisualizer<Value, Store, TransferFunction> res = new DOTCFGVisualizer<>();
res.init(args);
return res;
} else if (checker.hasOption("cfgviz")) {
String cfgviz = checker.getOption("cfgviz");
if (cfgviz == null) {
throw new UserError("-Acfgviz specified without arguments, should be -Acfgviz=VizClassName[,opts,...]");
}
String[] opts = cfgviz.split(",");
String vizClassName = opts[0];
if (!Signatures.isBinaryName(vizClassName)) {
throw new UserError("Bad -Acfgviz class name \"%s\", should be a binary name.", vizClassName);
}
Map<String, Object> args = processCFGVisualizerOption(opts);
if (!args.containsKey("verbose")) {
boolean verbose = checker.hasOption("verbosecfg");
args.put("verbose", verbose);
}
args.put("checkerName", getCheckerName());
CFGVisualizer<Value, Store, TransferFunction> res = BaseTypeChecker.invokeConstructorFor(vizClassName, null, null);
res.init(args);
return res;
}
// Nobody expected to use cfgVisualizer if neither option given.
return null;
}
use of org.checkerframework.checker.nullness.qual.Nullable in project checker-framework by typetools.
the class GenericAnnotatedTypeFactory method getSharedCFGForTree.
/**
* Get the shared control flow graph used for {@code tree} by this checker's topmost superchecker.
* Returns null if no information is available about the given tree, or if this checker has a
* parent checker that does not have a GenericAnnotatedTypeFactory.
*
* <p>Calls to this method should be guarded by checking {@link #hasOrIsSubchecker}; it is
* nonsensical to have a shared CFG when a checker is running alone.
*
* @param tree the tree whose CFG should be looked up
* @return the CFG stored by this checker's uppermost superchecker for tree, or null if it is not
* available
*/
@Nullable
public ControlFlowGraph getSharedCFGForTree(Tree tree) {
if (!shouldCache) {
return null;
}
BaseTypeChecker parentChecker = this.checker.getUltimateParentChecker();
// Checking reference equality.
@SuppressWarnings("interning") boolean parentIsThisChecker = parentChecker == this.checker;
if (parentIsThisChecker) {
// This is the ultimate parent;
return this.subcheckerSharedCFG == null ? null : this.subcheckerSharedCFG.getOrDefault(tree, null);
}
// This is a subchecker.
if (parentChecker != null) {
GenericAnnotatedTypeFactory<?, ?, ?, ?> parentAtf = parentChecker.getTypeFactory();
return parentAtf.getSharedCFGForTree(tree);
} else {
return null;
}
}
use of org.checkerframework.checker.nullness.qual.Nullable in project checker-framework by typetools.
the class GenericAnnotatedTypeFactory method getAnnotatedTypeVarargsArray.
/**
* Returns the type of a varargs array of a method invocation or a constructor invocation. Returns
* null only if private field {@code useFlow} is false.
*
* @param tree a method invocation or a constructor invocation
* @return AnnotatedTypeMirror of varargs array for a method or constructor invocation {@code
* tree}; returns null if private field {@code useFlow} is false
*/
@Nullable
public AnnotatedTypeMirror getAnnotatedTypeVarargsArray(Tree tree) {
if (!useFlow) {
return null;
}
// Get the synthetic NewArray tree that dataflow creates as the last argument of a call to a
// vararg method. Do this by getting the MethodInvocationNode to which "tree" maps. The last
// argument node of the MethodInvocationNode stores the synthetic NewArray tree.
List<Node> args;
switch(tree.getKind()) {
case METHOD_INVOCATION:
args = getFirstNodeOfKindForTree(tree, MethodInvocationNode.class).getArguments();
break;
case NEW_CLASS:
args = getFirstNodeOfKindForTree(tree, ObjectCreationNode.class).getArguments();
break;
default:
throw new BugInCF("Unexpected kind of tree: " + tree);
}
assert !args.isEmpty() : "Arguments are empty";
Node varargsArray = args.get(args.size() - 1);
AnnotatedTypeMirror varargtype = getAnnotatedType(varargsArray.getTree());
return varargtype;
}
use of org.checkerframework.checker.nullness.qual.Nullable in project checker-framework by typetools.
the class ElementQualifierHierarchy method getPolymorphicAnnotation.
@Override
@Nullable
public AnnotationMirror getPolymorphicAnnotation(AnnotationMirror start) {
QualifierKind polyKind = getQualifierKind(start).getPolymorphic();
if (polyKind == null) {
return null;
}
AnnotationMirror poly = kindToElementlessQualifier.get(polyKind);
if (poly == null) {
throw new TypeSystemError("Poly %s has an element. Override ElementQualifierHierarchy#getPolymorphicAnnotation.", polyKind);
}
return poly;
}
use of org.checkerframework.checker.nullness.qual.Nullable in project checker-framework by typetools.
the class GenericAnnotatedTypeFactory method createRequiresOrEnsuresQualifier.
/**
* Creates a {@code RequiresQualifier("...")} or {@code EnsuresQualifier("...")} annotation for
* the given expression.
*
* <p>This is of the form {@code @RequiresQualifier(expression="expression",
* qualifier=MyQual.class)} or {@code @EnsuresQualifier(expression="expression",
* qualifier=MyQual.class)}, where "expression" is exactly the string {@code expression} and
* MyQual is the annotation represented by {@code qualifier}.
*
* <p>Returns null if the expression is invalid when combined with the kind of annotation: for
* example, precondition annotations on "this" and parameters ("#1", etc.) are not supported,
* because receiver/parameter annotations should be inferred instead.
*
* <p>This implementation returns null if no annotation can be created, because the qualifier has
* elements/arguments, which {@code @RequiresQualifier} and {@code @EnsuresQualifier} do not
* support. Subclasses may override this method to return qualifiers that do have arguments
* instead of returning null.
*
* @param expression the expression to which the qualifier applies
* @param qualifier the qualifier that must be present
* @param declaredType the declared type of the expression, which is used to avoid inferring
* redundant pre- or postcondition annotations
* @param preOrPost whether to return a precondition or postcondition annotation
* @param preconds the list of precondition annotations; used to suppress redundant
* postconditions; non-null exactly when {@code preOrPost} is {@code BeforeOrAfter.BEFORE}
* @return a {@code RequiresQualifier("...")} or {@code EnsuresQualifier("...")} annotation for
* the given expression, or null
*/
@Nullable
protected AnnotationMirror createRequiresOrEnsuresQualifier(String expression, AnnotationMirror qualifier, AnnotatedTypeMirror declaredType, Analysis.BeforeOrAfter preOrPost, @Nullable List<AnnotationMirror> preconds) {
// Do not generate RequiresQualifier annotations for "this" or parameter expressions.
if (preOrPost == BeforeOrAfter.BEFORE && ("this".equals(expression) || formalParameterPattern.matcher(expression).matches())) {
return null;
}
if (!qualifier.getElementValues().isEmpty()) {
// elements/arguments.
return null;
}
AnnotationBuilder builder = new AnnotationBuilder(processingEnv, preOrPost == BeforeOrAfter.BEFORE ? RequiresQualifier.class : EnsuresQualifier.class);
builder.setValue("expression", new String[] { expression });
builder.setValue("qualifier", AnnotationUtils.annotationMirrorToClass(qualifier));
return builder.build();
}
Aggregations