
org.checkerframework.dataflow.cfg.CFGProcessor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of dataflow-shaded Show documentation
Show all versions of dataflow-shaded Show documentation
dataflow-shaded is a dataflow framework based on the javac compiler.
It differs from the org.checkerframework:dataflow artifact in two ways.
First, the packages in this artifact have been renamed to org.checkerframework.shaded.*.
Second, unlike the dataflow artifact, this artifact contains the dependencies it requires.
package org.checkerframework.dataflow.cfg;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.util.TreePathScanner;
import com.sun.tools.javac.util.Log;
import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.dataflow.cfg.builder.CFGBuilder;
import org.checkerframework.dataflow.qual.Pure;
import org.checkerframework.javacutil.BasicTypeProcessor;
import org.checkerframework.javacutil.TreeUtils;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
/**
* Generate the control flow graph of a given method in a given class. See {@link
* org.checkerframework.dataflow.cfg.visualize.CFGVisualizeLauncher} for example usage.
*/
@SupportedAnnotationTypes("*")
public class CFGProcessor extends BasicTypeProcessor {
/**
* Qualified name of a specified class which includes a specified method to generate the CFG
* for.
*/
private final String className;
/** Name of a specified method to generate the CFG for. */
private final String methodName;
/** AST for source file. */
private @Nullable CompilationUnitTree rootTree;
/** AST node for the specified class. */
private @Nullable ClassTree classTree;
/** AST node for the specified method. */
private @Nullable MethodTree methodTree;
/** Result of CFG process; is set by {@link #typeProcessingOver}. */
private @MonotonicNonNull CFGProcessResult result = null;
/**
* Create a CFG processor.
*
* @param className the qualified name of class which includes the specified method to generate
* the CFG for
* @param methodName the name of the method to generate the CFG for
*/
public CFGProcessor(String className, String methodName) {
this.className = className;
this.methodName = methodName;
}
/**
* Get the CFG process result.
*
* @return result of cfg process
*/
public final @Nullable CFGProcessResult getCFGProcessResult() {
return result;
}
@Override
public void typeProcessingOver() {
if (rootTree == null) {
result = new CFGProcessResult("Root tree is null.");
} else if (classTree == null) {
result = new CFGProcessResult("Method tree is null.");
} else if (methodTree == null) {
result = new CFGProcessResult("Class tree is null.");
} else {
Log log = getCompilerLog();
if (log.nerrors > 0) {
result = new CFGProcessResult("Compilation issued an error.");
} else {
ControlFlowGraph cfg =
CFGBuilder.build(rootTree, methodTree, classTree, processingEnv);
result = new CFGProcessResult(cfg);
}
}
super.typeProcessingOver();
}
@Override
protected TreePathScanner, ?> createTreePathScanner(CompilationUnitTree root) {
rootTree = root;
return new TreePathScanner() {
@Override
public Void visitClass(ClassTree tree, Void p) {
TypeElement el = TreeUtils.elementFromDeclaration(tree);
if (el.getSimpleName().contentEquals(className)) {
classTree = tree;
}
return super.visitClass(tree, p);
}
@Override
public Void visitMethod(MethodTree tree, Void p) {
ExecutableElement el = TreeUtils.elementFromDeclaration(tree);
if (el.getSimpleName().contentEquals(methodName)) {
methodTree = tree;
// Stop execution by throwing an exception. This makes sure that compilation
// does not proceed, and thus the AST is not modified by further phases of the
// compilation (and we save the work to do the compilation).
throw new RuntimeException();
}
return null;
}
};
}
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latestSupported();
}
/** The result of the CFG process, contains the control flow graph when successful. */
public static class CFGProcessResult {
/** Control flow graph. */
private final @Nullable ControlFlowGraph controlFlowGraph;
/** Did the CFG process succeed? */
private final boolean isSuccess;
/** Error message (when the CFG process failed). */
private final @Nullable String errMsg;
/**
* Create the result of the CFG process. Only called if the CFG was built successfully.
*
* @param cfg control flow graph
*/
/*package-private*/ CFGProcessResult(ControlFlowGraph cfg) {
this(cfg, true, null);
}
/**
* Create the result of the CFG process. Only called if the CFG was not built successfully.
*
* @param errMsg the error message
*/
/*package-private*/ CFGProcessResult(String errMsg) {
this(null, false, errMsg);
}
/**
* Create the result of CFG process.
*
* @param cfg the control flow graph
* @param isSuccess did the CFG process succeed?
* @param errMsg error message (when the CFG process failed)
*/
private CFGProcessResult(
@Nullable ControlFlowGraph cfg, boolean isSuccess, @Nullable String errMsg) {
this.controlFlowGraph = cfg;
this.isSuccess = isSuccess;
this.errMsg = errMsg;
}
/**
* Check if the CFG process succeeded.
*
* @return true if the CFG process succeeded
*/
@Pure
@EnsuresNonNullIf(expression = "getCFG()", result = true)
@EnsuresNonNullIf(expression = "getErrMsg()", result = false)
@SuppressWarnings("nullness:contracts.conditional.postcondition.not.satisfied")
public boolean isSuccess() {
return isSuccess;
}
/**
* Returns the generated control flow graph.
*
* @return the generated control flow graph
*/
@Pure
public @Nullable ControlFlowGraph getCFG() {
return controlFlowGraph;
}
/**
* Returns the error message.
*
* @return the error message
*/
@Pure
public @Nullable String getErrMsg() {
return errMsg;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy