All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.checkerframework.dataflow.cfg.UnderlyingAST Maven / Gradle / Ivy

Go to download

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.

There is a newer version: 3.42.0-eisop5
Show newest version
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 org.checkerframework.checker.initialization.qual.UnknownInitialization;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.plumelib.util.StringsPlume;
import org.plumelib.util.UniqueId;

import java.util.concurrent.atomic.AtomicLong;

/**
 * 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
         */
        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
         */
        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, ")");
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy