org.checkerframework.dataflow.cfg.UnderlyingAST Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of checker Show documentation
Show all versions of checker Show documentation
The Checker Framework enhances Java's type system to
make it more powerful and useful. This lets software developers
detect and prevent errors in their Java programs.
The Checker Framework includes compiler plug-ins ("checkers")
that find bugs or verify their absence. It also permits you to
write your own compiler plug-ins.
package org.checkerframework.dataflow.cfg;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.LambdaExpressionTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.Tree;
import java.util.concurrent.atomic.AtomicLong;
import org.checkerframework.checker.initialization.qual.UnknownInitialization;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.plumelib.util.StringsPlume;
import org.plumelib.util.UniqueId;
/**
* Represents an abstract syntax tree of type {@link Tree} that underlies a given control flow
* graph.
*/
public abstract class UnderlyingAST implements UniqueId {
/** The kinds of underlying ASTs. */
public enum Kind {
/** The underlying code is a whole method. */
METHOD,
/** The underlying code is a lambda expression. */
LAMBDA,
/** The underlying code is an arbitrary Java statement or expression. */
ARBITRARY_CODE,
}
/** The kind of the underlying AST. */
protected final Kind kind;
/** The unique ID for the next-created object. */
private static final AtomicLong nextUid = new AtomicLong(0);
/** The unique ID of this object. */
private final transient long uid = nextUid.getAndIncrement();
@Override
public long getUid(@UnknownInitialization UnderlyingAST this) {
return uid;
}
/**
* Creates an UnderlyingAST.
*
* @param kind the kind of the AST
*/
protected UnderlyingAST(Kind kind) {
this.kind = kind;
}
/**
* Returns the code that corresponds to the CFG. For a method or lamdda, this returns the body.
* For other constructs, it returns the tree itself (a statement or expression).
*
* @return the code that corresponds to the CFG
*/
public abstract Tree getCode();
public Kind getKind() {
return kind;
}
/** If the underlying AST is a method. */
public static class CFGMethod extends UnderlyingAST {
/** The method declaration. */
protected final MethodTree method;
/** The class tree this method belongs to. */
protected final ClassTree classTree;
public CFGMethod(MethodTree method, ClassTree classTree) {
super(Kind.METHOD);
this.method = method;
this.classTree = classTree;
}
@Override
public Tree getCode() {
return method.getBody();
}
public MethodTree getMethod() {
return method;
}
/**
* Returns the name of the method.
*
* @return the name of the method
*/
public String getMethodName() {
return method.getName().toString();
}
/**
* Returns the class tree this method belongs to.
*
* @return the class tree this method belongs to
*/
public ClassTree getClassTree() {
return classTree;
}
/**
* Returns the simple name of the enclosing class.
*
* @return the simple name of the enclosing class
*/
public String getSimpleClassName() {
return classTree.getSimpleName().toString();
}
@Override
public String toString() {
return StringsPlume.joinLines("CFGMethod(", method, ")");
}
}
/** If the underlying AST is a lambda. */
public static class CFGLambda extends UnderlyingAST {
/** The lambda expression. */
private final LambdaExpressionTree lambda;
/** The enclosing class of the lambda. */
private final ClassTree classTree;
/** The enclosing method of the lambda. */
private final @Nullable MethodTree enclosingMethod;
/**
* Create a new CFGLambda.
*
* @param lambda the lambda expression
* @param classTree the enclosing class of the lambda
* @param enclosingMethod the enclosing method of the lambda
*/
public CFGLambda(
LambdaExpressionTree lambda, ClassTree classTree, @Nullable MethodTree enclosingMethod) {
super(Kind.LAMBDA);
this.lambda = lambda;
this.enclosingMethod = enclosingMethod;
this.classTree = classTree;
}
@Override
public Tree getCode() {
return lambda.getBody();
}
/**
* Returns the lambda expression tree.
*
* @return the lambda expression tree
*/
public LambdaExpressionTree getLambdaTree() {
return lambda;
}
/**
* Returns the enclosing class of the lambda.
*
* @return the enclosing class of the lambda
*/
public ClassTree getClassTree() {
return classTree;
}
/**
* Returns the simple name of the enclosing class.
*
* @return the simple name of the enclosing class
*/
public String getSimpleClassName() {
return classTree.getSimpleName().toString();
}
/**
* Returns the enclosing method of the lambda.
*
* @return the enclosing method of the lambda, or {@code null} if there is no enclosing method
* @deprecated use #getEnclosingMethod()
*/
@Deprecated // 2022-01-23
public @Nullable MethodTree getMethod() {
return enclosingMethod;
}
/**
* Returns the enclosing method of the lambda.
*
* @return the enclosing method of the lambda, or {@code null} if there is no enclosing method
*/
public @Nullable MethodTree getEnclosingMethod() {
return enclosingMethod;
}
/**
* Returns the name of the enclosing method of the lambda.
*
* @return the name of the enclosing method of the lambda, or {@code null} if there is no
* enclosing method
* @deprecated use #getEnclosingMethodName()
*/
@Deprecated // 2022-01-23
public @Nullable String getMethodName() {
return enclosingMethod == null ? null : enclosingMethod.getName().toString();
}
/**
* Returns the name of the enclosing method of the lambda.
*
* @return the name of the enclosing method of the lambda, or {@code null} if there is no
* enclosing method
*/
public @Nullable String getEnclosingMethodName() {
return enclosingMethod == null ? null : enclosingMethod.getName().toString();
}
@Override
public String toString() {
return StringsPlume.joinLines("CFGLambda(", lambda, ")");
}
}
/**
* If the underlying AST is a statement or expression. This is for field definitions (with
* initializers) and initializer blocks.
*/
public static class CFGStatement extends UnderlyingAST {
protected final Tree code;
/** The class tree this method belongs to. */
protected final ClassTree classTree;
public CFGStatement(Tree code, ClassTree classTree) {
super(Kind.ARBITRARY_CODE);
this.code = code;
this.classTree = classTree;
}
@Override
public Tree getCode() {
return code;
}
public ClassTree getClassTree() {
return classTree;
}
/**
* Returns the simple name of the enclosing class.
*
* @return the simple name of the enclosing class
*/
public String getSimpleClassName() {
return classTree.getSimpleName().toString();
}
@Override
public String toString() {
return StringsPlume.joinLines("CFGStatement(", code, ")");
}
}
}