alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (JCTree.java)

This example Java source code file (JCTree.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

jcblock, jcexpression, jcmodifiers, jcstatement, jctree, jcvariabledecl, kind, list, name, override, r\,d, symbol, tag, typeboundkind, util

The JCTree.java Java example source code

/*
 * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.tools.javac.tree;

import java.io.IOException;
import java.io.StringWriter;
import java.util.*;

import javax.lang.model.element.Modifier;
import javax.lang.model.type.TypeKind;
import javax.tools.JavaFileObject;

import com.sun.source.tree.*;
import com.sun.source.tree.LambdaExpressionTree.BodyKind;
import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Scope.*;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
import com.sun.tools.javac.util.List;
import static com.sun.tools.javac.tree.JCTree.Tag.*;

/**
 * Root class for abstract syntax tree nodes. It provides definitions
 * for specific tree nodes as subclasses nested inside.
 *
 * <p>Each subclass is highly standardized.  It generally contains
 * only tree fields for the syntactic subcomponents of the node.  Some
 * classes that represent identifier uses or definitions also define a
 * Symbol field that denotes the represented identifier.  Classes for
 * non-local jumps also carry the jump target as a field.  The root
 * class Tree itself defines fields for the tree's type and position.
 * No other fields are kept in a tree node; instead parameters are
 * passed to methods accessing the node.
 *
 * <p>Except for the methods defined by com.sun.source, the only
 * method defined in subclasses is `visit' which applies a given
 * visitor to the tree. The actual tree processing is done by visitor
 * classes in other packages. The abstract class Visitor, as well as
 * an Factory interface for trees, are defined as inner classes in
 * Tree.
 *
 * <p>To avoid ambiguities with the Tree API in com.sun.source all sub
 * classes should, by convention, start with JC (javac).
 *
 * <p>This is NOT part of any supported API.
 * If you write code that depends on this, you do so at your own risk.
 * This code and its internal interfaces are subject to change or
 * deletion without notice.</b>
 *
 * @see TreeMaker
 * @see TreeInfo
 * @see TreeTranslator
 * @see Pretty
 */
public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {

    /* Tree tag values, identifying kinds of trees */
    public enum Tag {
        /** For methods that return an invalid tag if a given condition is not met
         */
        NO_TAG,

        /** Toplevel nodes, of type TopLevel, representing entire source files.
        */
        TOPLEVEL,

        /** Import clauses, of type Import.
         */
        IMPORT,

        /** Class definitions, of type ClassDef.
         */
        CLASSDEF,

        /** Method definitions, of type MethodDef.
         */
        METHODDEF,

        /** Variable definitions, of type VarDef.
         */
        VARDEF,

        /** The no-op statement ";", of type Skip
         */
        SKIP,

        /** Blocks, of type Block.
         */
        BLOCK,

        /** Do-while loops, of type DoLoop.
         */
        DOLOOP,

        /** While-loops, of type WhileLoop.
         */
        WHILELOOP,

        /** For-loops, of type ForLoop.
         */
        FORLOOP,

        /** Foreach-loops, of type ForeachLoop.
         */
        FOREACHLOOP,

        /** Labelled statements, of type Labelled.
         */
        LABELLED,

        /** Switch statements, of type Switch.
         */
        SWITCH,

        /** Case parts in switch statements, of type Case.
         */
        CASE,

        /** Synchronized statements, of type Synchonized.
         */
        SYNCHRONIZED,

        /** Try statements, of type Try.
         */
        TRY,

        /** Catch clauses in try statements, of type Catch.
         */
        CATCH,

        /** Conditional expressions, of type Conditional.
         */
        CONDEXPR,

        /** Conditional statements, of type If.
         */
        IF,

        /** Expression statements, of type Exec.
         */
        EXEC,

        /** Break statements, of type Break.
         */
        BREAK,

        /** Continue statements, of type Continue.
         */
        CONTINUE,

        /** Return statements, of type Return.
         */
        RETURN,

        /** Throw statements, of type Throw.
         */
        THROW,

        /** Assert statements, of type Assert.
         */
        ASSERT,

        /** Method invocation expressions, of type Apply.
         */
        APPLY,

        /** Class instance creation expressions, of type NewClass.
         */
        NEWCLASS,

        /** Array creation expressions, of type NewArray.
         */
        NEWARRAY,

        /** Lambda expression, of type Lambda.
         */
        LAMBDA,

        /** Parenthesized subexpressions, of type Parens.
         */
        PARENS,

        /** Assignment expressions, of type Assign.
         */
        ASSIGN,

        /** Type cast expressions, of type TypeCast.
         */
        TYPECAST,

        /** Type test expressions, of type TypeTest.
         */
        TYPETEST,

        /** Indexed array expressions, of type Indexed.
         */
        INDEXED,

        /** Selections, of type Select.
         */
        SELECT,

        /** Member references, of type Reference.
         */
        REFERENCE,

        /** Simple identifiers, of type Ident.
         */
        IDENT,

        /** Literals, of type Literal.
         */
        LITERAL,

        /** Basic type identifiers, of type TypeIdent.
         */
        TYPEIDENT,

        /** Array types, of type TypeArray.
         */
        TYPEARRAY,

        /** Parameterized types, of type TypeApply.
         */
        TYPEAPPLY,

        /** Union types, of type TypeUnion.
         */
        TYPEUNION,

        /** Intersection types, of type TypeIntersection.
         */
        TYPEINTERSECTION,

        /** Formal type parameters, of type TypeParameter.
         */
        TYPEPARAMETER,

        /** Type argument.
         */
        WILDCARD,

        /** Bound kind: extends, super, exact, or unbound
         */
        TYPEBOUNDKIND,

        /** metadata: Annotation.
         */
        ANNOTATION,

        /** metadata: Type annotation.
         */
        TYPE_ANNOTATION,

        /** metadata: Modifiers
         */
        MODIFIERS,

        /** An annotated type tree.
         */
        ANNOTATED_TYPE,

        /** Error trees, of type Erroneous.
         */
        ERRONEOUS,

        /** Unary operators, of type Unary.
         */
        POS,                             // +
        NEG,                             // -
        NOT,                             // !
        COMPL,                           // ~
        PREINC,                          // ++ _
        PREDEC,                          // -- _
        POSTINC,                         // _ ++
        POSTDEC,                         // _ --

        /** unary operator for null reference checks, only used internally.
         */
        NULLCHK,

        /** Binary operators, of type Binary.
         */
        OR,                              // ||
        AND,                             // &&
        BITOR,                           // |
        BITXOR,                          // ^
        BITAND,                          // &
        EQ,                              // ==
        NE,                              // !=
        LT,                              // <
        GT,                              // >
        LE,                              // <=
        GE,                              // >=
        SL,                              // <<
        SR,                              // >>
        USR,                             // >>>
        PLUS,                            // +
        MINUS,                           // -
        MUL,                             // *
        DIV,                             // /
        MOD,                             // %

        /** Assignment operators, of type Assignop.
         */
        BITOR_ASG(BITOR),                // |=
        BITXOR_ASG(BITXOR),              // ^=
        BITAND_ASG(BITAND),              // &=

        SL_ASG(SL),                      // <<=
        SR_ASG(SR),                      // >>=
        USR_ASG(USR),                    // >>>=
        PLUS_ASG(PLUS),                  // +=
        MINUS_ASG(MINUS),                // -=
        MUL_ASG(MUL),                    // *=
        DIV_ASG(DIV),                    // /=
        MOD_ASG(MOD),                    // %=

        /** A synthetic let expression, of type LetExpr.
         */
        LETEXPR;                         // ala scheme

        private final Tag noAssignTag;

        private static final int numberOfOperators = MOD.ordinal() - POS.ordinal() + 1;

        private Tag(Tag noAssignTag) {
            this.noAssignTag = noAssignTag;
        }

        private Tag() {
            this(null);
        }

        public static int getNumberOfOperators() {
            return numberOfOperators;
        }

        public Tag noAssignOp() {
            if (noAssignTag != null)
                return noAssignTag;
            throw new AssertionError("noAssignOp() method is not available for non assignment tags");
        }

        public boolean isPostUnaryOp() {
            return (this == POSTINC || this == POSTDEC);
        }

        public boolean isIncOrDecUnaryOp() {
            return (this == PREINC || this == PREDEC || this == POSTINC || this == POSTDEC);
        }

        public boolean isAssignop() {
            return noAssignTag != null;
        }

        public int operatorIndex() {
            return (this.ordinal() - POS.ordinal());
        }
    }

    /* The (encoded) position in the source file. @see util.Position.
     */
    public int pos;

    /* The type of this node.
     */
    public Type type;

    /* The tag of this node -- one of the constants declared above.
     */
    public abstract Tag getTag();

    /* Returns true if the tag of this node is equals to tag.
     */
    public boolean hasTag(Tag tag) {
        return tag == getTag();
    }

    /** Convert a tree to a pretty-printed string. */
    @Override
    public String toString() {
        StringWriter s = new StringWriter();
        try {
            new Pretty(s, false).printExpr(this);
        }
        catch (IOException e) {
            // should never happen, because StringWriter is defined
            // never to throw any IOExceptions
            throw new AssertionError(e);
        }
        return s.toString();
    }

    /** Set position field and return this tree.
     */
    public JCTree setPos(int pos) {
        this.pos = pos;
        return this;
    }

    /** Set type field and return this tree.
     */
    public JCTree setType(Type type) {
        this.type = type;
        return this;
    }

    /** Visit this tree with a given visitor.
     */
    public abstract void accept(Visitor v);

    public abstract <R,D> R accept(TreeVisitor v, D d);

    /** Return a shallow copy of this tree.
     */
    @Override
    public Object clone() {
        try {
            return super.clone();
        } catch(CloneNotSupportedException e) {
            throw new RuntimeException(e);
        }
    }

    /** Get a default position for this tree node.
     */
    public DiagnosticPosition pos() {
        return this;
    }

    // for default DiagnosticPosition
    public JCTree getTree() {
        return this;
    }

    // for default DiagnosticPosition
    public int getStartPosition() {
        return TreeInfo.getStartPos(this);
    }

    // for default DiagnosticPosition
    public int getPreferredPosition() {
        return pos;
    }

    // for default DiagnosticPosition
    public int getEndPosition(EndPosTable endPosTable) {
        return TreeInfo.getEndPos(this, endPosTable);
    }

    /**
     * Everything in one source file is kept in a {@linkplain JCCompilationUnit} structure.
     */
    public static class JCCompilationUnit extends JCTree implements CompilationUnitTree {
        public List<JCAnnotation> packageAnnotations;
        /** The tree representing the package clause. */
        public JCExpression pid;
        /** All definitions in this file (ClassDef, Import, and Skip) */
        public List<JCTree> defs;
        /* The source file name. */
        public JavaFileObject sourcefile;
        /** The package to which this compilation unit belongs. */
        public PackageSymbol packge;
        /** A scope for all named imports. */
        public ImportScope namedImportScope;
        /** A scope for all import-on-demands. */
        public StarImportScope starImportScope;
        /** Line starting positions, defined only if option -g is set. */
        public Position.LineMap lineMap = null;
        /** A table that stores all documentation comments indexed by the tree
         * nodes they refer to. defined only if option -s is set. */
        public DocCommentTable docComments = null;
        /* An object encapsulating ending positions of source ranges indexed by
         * the tree nodes they belong to. Defined only if option -Xjcov is set. */
        public EndPosTable endPositions = null;
        protected JCCompilationUnit(List<JCAnnotation> packageAnnotations,
                        JCExpression pid,
                        List<JCTree> defs,
                        JavaFileObject sourcefile,
                        PackageSymbol packge,
                        ImportScope namedImportScope,
                        StarImportScope starImportScope) {
            this.packageAnnotations = packageAnnotations;
            this.pid = pid;
            this.defs = defs;
            this.sourcefile = sourcefile;
            this.packge = packge;
            this.namedImportScope = namedImportScope;
            this.starImportScope = starImportScope;
        }
        @Override
        public void accept(Visitor v) { v.visitTopLevel(this); }

        public Kind getKind() { return Kind.COMPILATION_UNIT; }
        public List<JCAnnotation> getPackageAnnotations() {
            return packageAnnotations;
        }
        public List<JCImport> getImports() {
            ListBuffer<JCImport> imports = new ListBuffer();
            for (JCTree tree : defs) {
                if (tree.hasTag(IMPORT))
                    imports.append((JCImport)tree);
                else if (!tree.hasTag(SKIP))
                    break;
            }
            return imports.toList();
        }
        public JCExpression getPackageName() { return pid; }
        public JavaFileObject getSourceFile() {
            return sourcefile;
        }
        public Position.LineMap getLineMap() {
            return lineMap;
        }
        public List<JCTree> getTypeDecls() {
            List<JCTree> typeDefs;
            for (typeDefs = defs; !typeDefs.isEmpty(); typeDefs = typeDefs.tail)
                if (!typeDefs.head.hasTag(IMPORT))
                    break;
            return typeDefs;
        }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitCompilationUnit(this, d);
        }

        @Override
        public Tag getTag() {
            return TOPLEVEL;
        }
    }

    /**
     * An import clause.
     */
    public static class JCImport extends JCTree implements ImportTree {
        public boolean staticImport;
        /** The imported class(es). */
        public JCTree qualid;
        protected JCImport(JCTree qualid, boolean importStatic) {
            this.qualid = qualid;
            this.staticImport = importStatic;
        }
        @Override
        public void accept(Visitor v) { v.visitImport(this); }

        public boolean isStatic() { return staticImport; }
        public JCTree getQualifiedIdentifier() { return qualid; }

        public Kind getKind() { return Kind.IMPORT; }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitImport(this, d);
        }

        @Override
        public Tag getTag() {
            return IMPORT;
        }
    }

    public static abstract class JCStatement extends JCTree implements StatementTree {
        @Override
        public JCStatement setType(Type type) {
            super.setType(type);
            return this;
        }
        @Override
        public JCStatement setPos(int pos) {
            super.setPos(pos);
            return this;
        }
    }

    public static abstract class JCExpression extends JCTree implements ExpressionTree {
        @Override
        public JCExpression setType(Type type) {
            super.setType(type);
            return this;
        }
        @Override
        public JCExpression setPos(int pos) {
            super.setPos(pos);
            return this;
        }
    }

    /**
     * Common supertype for all poly expression trees (lambda, method references,
     * conditionals, method and constructor calls)
     */
    public static abstract class JCPolyExpression extends JCExpression {

        /**
         * A poly expression can only be truly 'poly' in certain contexts
         */
        public enum PolyKind {
            /** poly expression to be treated as a standalone expression */
            STANDALONE,
            /** true poly expression */
            POLY;
        }

        /** is this poly expression a 'true' poly expression? */
        public PolyKind polyKind;
    }

    /**
     * Common supertype for all functional expression trees (lambda and method references)
     */
    public static abstract class JCFunctionalExpression extends JCPolyExpression {

        public JCFunctionalExpression() {
            //a functional expression is always a 'true' poly
            polyKind = PolyKind.POLY;
        }

        /** list of target types inferred for this functional expression. */
        public List<Type> targets;

        public Type getDescriptorType(Types types) {
            return targets.nonEmpty() ? types.findDescriptorType(targets.head) : types.createErrorType(null);
        }
    }

    /**
     * A class definition.
     */
    public static class JCClassDecl extends JCStatement implements ClassTree {
        /** the modifiers */
        public JCModifiers mods;
        /** the name of the class */
        public Name name;
        /** formal class parameters */
        public List<JCTypeParameter> typarams;
        /** the classes this class extends */
        public JCExpression extending;
        /** the interfaces implemented by this class */
        public List<JCExpression> implementing;
        /** all variables and methods defined in this class */
        public List<JCTree> defs;
        /** the symbol */
        public ClassSymbol sym;
        protected JCClassDecl(JCModifiers mods,
                           Name name,
                           List<JCTypeParameter> typarams,
                           JCExpression extending,
                           List<JCExpression> implementing,
                           List<JCTree> defs,
                           ClassSymbol sym)
        {
            this.mods = mods;
            this.name = name;
            this.typarams = typarams;
            this.extending = extending;
            this.implementing = implementing;
            this.defs = defs;
            this.sym = sym;
        }
        @Override
        public void accept(Visitor v) { v.visitClassDef(this); }

        public Kind getKind() {
            if ((mods.flags & Flags.ANNOTATION) != 0)
                return Kind.ANNOTATION_TYPE;
            else if ((mods.flags & Flags.INTERFACE) != 0)
                return Kind.INTERFACE;
            else if ((mods.flags & Flags.ENUM) != 0)
                return Kind.ENUM;
            else
                return Kind.CLASS;
        }

        public JCModifiers getModifiers() { return mods; }
        public Name getSimpleName() { return name; }
        public List<JCTypeParameter> getTypeParameters() {
            return typarams;
        }
        public JCExpression getExtendsClause() { return extending; }
        public List<JCExpression> getImplementsClause() {
            return implementing;
        }
        public List<JCTree> getMembers() {
            return defs;
        }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitClass(this, d);
        }

        @Override
        public Tag getTag() {
            return CLASSDEF;
        }
    }

    /**
     * A method definition.
     */
    public static class JCMethodDecl extends JCTree implements MethodTree {
        /** method modifiers */
        public JCModifiers mods;
        /** method name */
        public Name name;
        /** type of method return value */
        public JCExpression restype;
        /** type parameters */
        public List<JCTypeParameter> typarams;
        /** receiver parameter */
        public JCVariableDecl recvparam;
        /** value parameters */
        public List<JCVariableDecl> params;
        /** exceptions thrown by this method */
        public List<JCExpression> thrown;
        /** statements in the method */
        public JCBlock body;
        /** default value, for annotation types */
        public JCExpression defaultValue;
        /** method symbol */
        public MethodSymbol sym;
        protected JCMethodDecl(JCModifiers mods,
                            Name name,
                            JCExpression restype,
                            List<JCTypeParameter> typarams,
                            JCVariableDecl recvparam,
                            List<JCVariableDecl> params,
                            List<JCExpression> thrown,
                            JCBlock body,
                            JCExpression defaultValue,
                            MethodSymbol sym)
        {
            this.mods = mods;
            this.name = name;
            this.restype = restype;
            this.typarams = typarams;
            this.params = params;
            this.recvparam = recvparam;
            // TODO: do something special if the given type is null?
            // receiver != null ? receiver : List.<JCTypeAnnotation>nil());
            this.thrown = thrown;
            this.body = body;
            this.defaultValue = defaultValue;
            this.sym = sym;
        }
        @Override
        public void accept(Visitor v) { v.visitMethodDef(this); }

        public Kind getKind() { return Kind.METHOD; }
        public JCModifiers getModifiers() { return mods; }
        public Name getName() { return name; }
        public JCTree getReturnType() { return restype; }
        public List<JCTypeParameter> getTypeParameters() {
            return typarams;
        }
        public List<JCVariableDecl> getParameters() {
            return params;
        }
        public JCVariableDecl getReceiverParameter() { return recvparam; }
        public List<JCExpression> getThrows() {
            return thrown;
        }
        public JCBlock getBody() { return body; }
        public JCTree getDefaultValue() { // for annotation types
            return defaultValue;
        }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitMethod(this, d);
        }

        @Override
        public Tag getTag() {
            return METHODDEF;
        }
  }

    /**
     * A variable definition.
     */
    public static class JCVariableDecl extends JCStatement implements VariableTree {
        /** variable modifiers */
        public JCModifiers mods;
        /** variable name */
        public Name name;
        /** variable name expression */
        public JCExpression nameexpr;
        /** type of the variable */
        public JCExpression vartype;
        /** variable's initial value */
        public JCExpression init;
        /** symbol */
        public VarSymbol sym;

        protected JCVariableDecl(JCModifiers mods,
                         Name name,
                         JCExpression vartype,
                         JCExpression init,
                         VarSymbol sym) {
            this.mods = mods;
            this.name = name;
            this.vartype = vartype;
            this.init = init;
            this.sym = sym;
        }

        protected JCVariableDecl(JCModifiers mods,
                         JCExpression nameexpr,
                         JCExpression vartype) {
            this(mods, null, vartype, null, null);
            this.nameexpr = nameexpr;
            if (nameexpr.hasTag(Tag.IDENT)) {
                this.name = ((JCIdent)nameexpr).name;
            } else {
                // Only other option is qualified name x.y.this;
                this.name = ((JCFieldAccess)nameexpr).name;
            }
        }

        @Override
        public void accept(Visitor v) { v.visitVarDef(this); }

        public Kind getKind() { return Kind.VARIABLE; }
        public JCModifiers getModifiers() { return mods; }
        public Name getName() { return name; }
        public JCExpression getNameExpression() { return nameexpr; }
        public JCTree getType() { return vartype; }
        public JCExpression getInitializer() {
            return init;
        }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitVariable(this, d);
        }

        @Override
        public Tag getTag() {
            return VARDEF;
        }
    }

    /**
     * A no-op statement ";".
     */
    public static class JCSkip extends JCStatement implements EmptyStatementTree {
        protected JCSkip() {
        }
        @Override
        public void accept(Visitor v) { v.visitSkip(this); }

        public Kind getKind() { return Kind.EMPTY_STATEMENT; }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitEmptyStatement(this, d);
        }

        @Override
        public Tag getTag() {
            return SKIP;
        }
    }

    /**
     * A statement block.
     */
    public static class JCBlock extends JCStatement implements BlockTree {
        /** flags */
        public long flags;
        /** statements */
        public List<JCStatement> stats;
        /** Position of closing brace, optional. */
        public int endpos = Position.NOPOS;
        protected JCBlock(long flags, List<JCStatement> stats) {
            this.stats = stats;
            this.flags = flags;
        }
        @Override
        public void accept(Visitor v) { v.visitBlock(this); }

        public Kind getKind() { return Kind.BLOCK; }
        public List<JCStatement> getStatements() {
            return stats;
        }
        public boolean isStatic() { return (flags & Flags.STATIC) != 0; }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitBlock(this, d);
        }

        @Override
        public Tag getTag() {
            return BLOCK;
        }
    }

    /**
     * A do loop
     */
    public static class JCDoWhileLoop extends JCStatement implements DoWhileLoopTree {
        public JCStatement body;
        public JCExpression cond;
        protected JCDoWhileLoop(JCStatement body, JCExpression cond) {
            this.body = body;
            this.cond = cond;
        }
        @Override
        public void accept(Visitor v) { v.visitDoLoop(this); }

        public Kind getKind() { return Kind.DO_WHILE_LOOP; }
        public JCExpression getCondition() { return cond; }
        public JCStatement getStatement() { return body; }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitDoWhileLoop(this, d);
        }

        @Override
        public Tag getTag() {
            return DOLOOP;
        }
    }

    /**
     * A while loop
     */
    public static class JCWhileLoop extends JCStatement implements WhileLoopTree {
        public JCExpression cond;
        public JCStatement body;
        protected JCWhileLoop(JCExpression cond, JCStatement body) {
            this.cond = cond;
            this.body = body;
        }
        @Override
        public void accept(Visitor v) { v.visitWhileLoop(this); }

        public Kind getKind() { return Kind.WHILE_LOOP; }
        public JCExpression getCondition() { return cond; }
        public JCStatement getStatement() { return body; }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitWhileLoop(this, d);
        }

        @Override
        public Tag getTag() {
            return WHILELOOP;
        }
    }

    /**
     * A for loop.
     */
    public static class JCForLoop extends JCStatement implements ForLoopTree {
        public List<JCStatement> init;
        public JCExpression cond;
        public List<JCExpressionStatement> step;
        public JCStatement body;
        protected JCForLoop(List<JCStatement> init,
                          JCExpression cond,
                          List<JCExpressionStatement> update,
                          JCStatement body)
        {
            this.init = init;
            this.cond = cond;
            this.step = update;
            this.body = body;
        }
        @Override
        public void accept(Visitor v) { v.visitForLoop(this); }

        public Kind getKind() { return Kind.FOR_LOOP; }
        public JCExpression getCondition() { return cond; }
        public JCStatement getStatement() { return body; }
        public List<JCStatement> getInitializer() {
            return init;
        }
        public List<JCExpressionStatement> getUpdate() {
            return step;
        }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitForLoop(this, d);
        }

        @Override
        public Tag getTag() {
            return FORLOOP;
        }
    }

    /**
     * The enhanced for loop.
     */
    public static class JCEnhancedForLoop extends JCStatement implements EnhancedForLoopTree {
        public JCVariableDecl var;
        public JCExpression expr;
        public JCStatement body;
        protected JCEnhancedForLoop(JCVariableDecl var, JCExpression expr, JCStatement body) {
            this.var = var;
            this.expr = expr;
            this.body = body;
        }
        @Override
        public void accept(Visitor v) { v.visitForeachLoop(this); }

        public Kind getKind() { return Kind.ENHANCED_FOR_LOOP; }
        public JCVariableDecl getVariable() { return var; }
        public JCExpression getExpression() { return expr; }
        public JCStatement getStatement() { return body; }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitEnhancedForLoop(this, d);
        }
        @Override
        public Tag getTag() {
            return FOREACHLOOP;
        }
    }

    /**
     * A labelled expression or statement.
     */
    public static class JCLabeledStatement extends JCStatement implements LabeledStatementTree {
        public Name label;
        public JCStatement body;
        protected JCLabeledStatement(Name label, JCStatement body) {
            this.label = label;
            this.body = body;
        }
        @Override
        public void accept(Visitor v) { v.visitLabelled(this); }
        public Kind getKind() { return Kind.LABELED_STATEMENT; }
        public Name getLabel() { return label; }
        public JCStatement getStatement() { return body; }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitLabeledStatement(this, d);
        }
        @Override
        public Tag getTag() {
            return LABELLED;
        }
    }

    /**
     * A "switch ( ) { }" construction.
     */
    public static class JCSwitch extends JCStatement implements SwitchTree {
        public JCExpression selector;
        public List<JCCase> cases;
        protected JCSwitch(JCExpression selector, List<JCCase> cases) {
            this.selector = selector;
            this.cases = cases;
        }
        @Override
        public void accept(Visitor v) { v.visitSwitch(this); }

        public Kind getKind() { return Kind.SWITCH; }
        public JCExpression getExpression() { return selector; }
        public List<JCCase> getCases() { return cases; }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitSwitch(this, d);
        }
        @Override
        public Tag getTag() {
            return SWITCH;
        }
    }

    /**
     * A "case  :" of a switch.
     */
    public static class JCCase extends JCStatement implements CaseTree {
        public JCExpression pat;
        public List<JCStatement> stats;
        protected JCCase(JCExpression pat, List<JCStatement> stats) {
            this.pat = pat;
            this.stats = stats;
        }
        @Override
        public void accept(Visitor v) { v.visitCase(this); }

        public Kind getKind() { return Kind.CASE; }
        public JCExpression getExpression() { return pat; }
        public List<JCStatement> getStatements() { return stats; }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitCase(this, d);
        }
        @Override
        public Tag getTag() {
            return CASE;
        }
    }

    /**
     * A synchronized block.
     */
    public static class JCSynchronized extends JCStatement implements SynchronizedTree {
        public JCExpression lock;
        public JCBlock body;
        protected JCSynchronized(JCExpression lock, JCBlock body) {
            this.lock = lock;
            this.body = body;
        }
        @Override
        public void accept(Visitor v) { v.visitSynchronized(this); }

        public Kind getKind() { return Kind.SYNCHRONIZED; }
        public JCExpression getExpression() { return lock; }
        public JCBlock getBlock() { return body; }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitSynchronized(this, d);
        }
        @Override
        public Tag getTag() {
            return SYNCHRONIZED;
        }
    }

    /**
     * A "try { } catch ( ) { } finally { }" block.
     */
    public static class JCTry extends JCStatement implements TryTree {
        public JCBlock body;
        public List<JCCatch> catchers;
        public JCBlock finalizer;
        public List<JCTree> resources;
        public boolean finallyCanCompleteNormally;
        protected JCTry(List<JCTree> resources,
                        JCBlock body,
                        List<JCCatch> catchers,
                        JCBlock finalizer) {
            this.body = body;
            this.catchers = catchers;
            this.finalizer = finalizer;
            this.resources = resources;
        }
        @Override
        public void accept(Visitor v) { v.visitTry(this); }

        public Kind getKind() { return Kind.TRY; }
        public JCBlock getBlock() { return body; }
        public List<JCCatch> getCatches() {
            return catchers;
        }
        public JCBlock getFinallyBlock() { return finalizer; }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitTry(this, d);
        }
        @Override
        public List<JCTree> getResources() {
            return resources;
        }
        @Override
        public Tag getTag() {
            return TRY;
        }
    }

    /**
     * A catch block.
     */
    public static class JCCatch extends JCTree implements CatchTree {
        public JCVariableDecl param;
        public JCBlock body;
        protected JCCatch(JCVariableDecl param, JCBlock body) {
            this.param = param;
            this.body = body;
        }
        @Override
        public void accept(Visitor v) { v.visitCatch(this); }

        public Kind getKind() { return Kind.CATCH; }
        public JCVariableDecl getParameter() { return param; }
        public JCBlock getBlock() { return body; }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitCatch(this, d);
        }
        @Override
        public Tag getTag() {
            return CATCH;
        }
    }

    /**
     * A ( ) ? ( ) : ( ) conditional expression
     */
    public static class JCConditional extends JCPolyExpression implements ConditionalExpressionTree {
        public JCExpression cond;
        public JCExpression truepart;
        public JCExpression falsepart;
        protected JCConditional(JCExpression cond,
                              JCExpression truepart,
                              JCExpression falsepart)
        {
            this.cond = cond;
            this.truepart = truepart;
            this.falsepart = falsepart;
        }
        @Override
        public void accept(Visitor v) { v.visitConditional(this); }

        public Kind getKind() { return Kind.CONDITIONAL_EXPRESSION; }
        public JCExpression getCondition() { return cond; }
        public JCExpression getTrueExpression() { return truepart; }
        public JCExpression getFalseExpression() { return falsepart; }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitConditionalExpression(this, d);
        }
        @Override
        public Tag getTag() {
            return CONDEXPR;
        }
    }

    /**
     * An "if ( ) { } else { }" block
     */
    public static class JCIf extends JCStatement implements IfTree {
        public JCExpression cond;
        public JCStatement thenpart;
        public JCStatement elsepart;
        protected JCIf(JCExpression cond,
                     JCStatement thenpart,
                     JCStatement elsepart)
        {
            this.cond = cond;
            this.thenpart = thenpart;
            this.elsepart = elsepart;
        }
        @Override
        public void accept(Visitor v) { v.visitIf(this); }

        public Kind getKind() { return Kind.IF; }
        public JCExpression getCondition() { return cond; }
        public JCStatement getThenStatement() { return thenpart; }
        public JCStatement getElseStatement() { return elsepart; }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitIf(this, d);
        }
        @Override
        public Tag getTag() {
            return IF;
        }
    }

    /**
     * an expression statement
     */
    public static class JCExpressionStatement extends JCStatement implements ExpressionStatementTree {
        /** expression structure */
        public JCExpression expr;
        protected JCExpressionStatement(JCExpression expr)
        {
            this.expr = expr;
        }
        @Override
        public void accept(Visitor v) { v.visitExec(this); }

        public Kind getKind() { return Kind.EXPRESSION_STATEMENT; }
        public JCExpression getExpression() { return expr; }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitExpressionStatement(this, d);
        }
        @Override
        public Tag getTag() {
            return EXEC;
        }

        /** Convert a expression-statement tree to a pretty-printed string. */
        @Override
        public String toString() {
            StringWriter s = new StringWriter();
            try {
                new Pretty(s, false).printStat(this);
            }
            catch (IOException e) {
                // should never happen, because StringWriter is defined
                // never to throw any IOExceptions
                throw new AssertionError(e);
            }
            return s.toString();
        }
    }

    /**
     * A break from a loop or switch.
     */
    public static class JCBreak extends JCStatement implements BreakTree {
        public Name label;
        public JCTree target;
        protected JCBreak(Name label, JCTree target) {
            this.label = label;
            this.target = target;
        }
        @Override
        public void accept(Visitor v) { v.visitBreak(this); }

        public Kind getKind() { return Kind.BREAK; }
        public Name getLabel() { return label; }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitBreak(this, d);
        }
        @Override
        public Tag getTag() {
            return BREAK;
        }
    }

    /**
     * A continue of a loop.
     */
    public static class JCContinue extends JCStatement implements ContinueTree {
        public Name label;
        public JCTree target;
        protected JCContinue(Name label, JCTree target) {
            this.label = label;
            this.target = target;
        }
        @Override
        public void accept(Visitor v) { v.visitContinue(this); }

        public Kind getKind() { return Kind.CONTINUE; }
        public Name getLabel() { return label; }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitContinue(this, d);
        }
        @Override
        public Tag getTag() {
            return CONTINUE;
        }
    }

    /**
     * A return statement.
     */
    public static class JCReturn extends JCStatement implements ReturnTree {
        public JCExpression expr;
        protected JCReturn(JCExpression expr) {
            this.expr = expr;
        }
        @Override
        public void accept(Visitor v) { v.visitReturn(this); }

        public Kind getKind() { return Kind.RETURN; }
        public JCExpression getExpression() { return expr; }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitReturn(this, d);
        }
        @Override
        public Tag getTag() {
            return RETURN;
        }
    }

    /**
     * A throw statement.
     */
    public static class JCThrow extends JCStatement implements ThrowTree {
        public JCExpression expr;
        protected JCThrow(JCExpression expr) {
            this.expr = expr;
        }
        @Override
        public void accept(Visitor v) { v.visitThrow(this); }

        public Kind getKind() { return Kind.THROW; }
        public JCExpression getExpression() { return expr; }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitThrow(this, d);
        }
        @Override
        public Tag getTag() {
            return THROW;
        }
    }

    /**
     * An assert statement.
     */
    public static class JCAssert extends JCStatement implements AssertTree {
        public JCExpression cond;
        public JCExpression detail;
        protected JCAssert(JCExpression cond, JCExpression detail) {
            this.cond = cond;
            this.detail = detail;
        }
        @Override
        public void accept(Visitor v) { v.visitAssert(this); }

        public Kind getKind() { return Kind.ASSERT; }
        public JCExpression getCondition() { return cond; }
        public JCExpression getDetail() { return detail; }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitAssert(this, d);
        }
        @Override
        public Tag getTag() {
            return ASSERT;
        }
    }

    /**
     * A method invocation
     */
    public static class JCMethodInvocation extends JCPolyExpression implements MethodInvocationTree {
        public List<JCExpression> typeargs;
        public JCExpression meth;
        public List<JCExpression> args;
        public Type varargsElement;
        protected JCMethodInvocation(List<JCExpression> typeargs,
                        JCExpression meth,
                        List<JCExpression> args)
        {
            this.typeargs = (typeargs == null) ? List.<JCExpression>nil()
                                               : typeargs;
            this.meth = meth;
            this.args = args;
        }
        @Override
        public void accept(Visitor v) { v.visitApply(this); }

        public Kind getKind() { return Kind.METHOD_INVOCATION; }
        public List<JCExpression> getTypeArguments() {
            return typeargs;
        }
        public JCExpression getMethodSelect() { return meth; }
        public List<JCExpression> getArguments() {
            return args;
        }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitMethodInvocation(this, d);
        }
        @Override
        public JCMethodInvocation setType(Type type) {
            super.setType(type);
            return this;
        }
        @Override
        public Tag getTag() {
            return(APPLY);
        }
    }

    /**
     * A new(...) operation.
     */
    public static class JCNewClass extends JCPolyExpression implements NewClassTree {
        public JCExpression encl;
        public List<JCExpression> typeargs;
        public JCExpression clazz;
        public List<JCExpression> args;
        public JCClassDecl def;
        public Symbol constructor;
        public Type varargsElement;
        public Type constructorType;
        protected JCNewClass(JCExpression encl,
                           List<JCExpression> typeargs,
                           JCExpression clazz,
                           List<JCExpression> args,
                           JCClassDecl def)
        {
            this.encl = encl;
            this.typeargs = (typeargs == null) ? List.<JCExpression>nil()
                                               : typeargs;
            this.clazz = clazz;
            this.args = args;
            this.def = def;
        }
        @Override
        public void accept(Visitor v) { v.visitNewClass(this); }

        public Kind getKind() { return Kind.NEW_CLASS; }
        public JCExpression getEnclosingExpression() { // expr.new C< ... > ( ... )
            return encl;
        }
        public List<JCExpression> getTypeArguments() {
            return typeargs;
        }
        public JCExpression getIdentifier() { return clazz; }
        public List<JCExpression> getArguments() {
            return args;
        }
        public JCClassDecl getClassBody() { return def; }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitNewClass(this, d);
        }
        @Override
        public Tag getTag() {
            return NEWCLASS;
        }
    }

    /**
     * A new[...] operation.
     */
    public static class JCNewArray extends JCExpression implements NewArrayTree {
        public JCExpression elemtype;
        public List<JCExpression> dims;
        // type annotations on inner-most component
        public List<JCAnnotation> annotations;
        // type annotations on dimensions
        public List<List dimAnnotations;
        public List<JCExpression> elems;
        protected JCNewArray(JCExpression elemtype,
                           List<JCExpression> dims,
                           List<JCExpression> elems)
        {
            this.elemtype = elemtype;
            this.dims = dims;
            this.annotations = List.nil();
            this.dimAnnotations = List.nil();
            this.elems = elems;
        }
        @Override
        public void accept(Visitor v) { v.visitNewArray(this); }

        public Kind getKind() { return Kind.NEW_ARRAY; }
        public JCExpression getType() { return elemtype; }
        public List<JCExpression> getDimensions() {
            return dims;
        }
        public List<JCExpression> getInitializers() {
            return elems;
        }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitNewArray(this, d);
        }
        @Override
        public Tag getTag() {
            return NEWARRAY;
        }

        @Override
        public List<JCAnnotation> getAnnotations() {
            return annotations;
        }

        @Override
        public List<List getDimAnnotations() {
            return dimAnnotations;
        }
    }

    /**
     * A lambda expression.
     */
    public static class JCLambda extends JCFunctionalExpression implements LambdaExpressionTree {

        public enum ParameterKind {
            IMPLICIT,
            EXPLICIT;
        }

        public List<JCVariableDecl> params;
        public JCTree body;
        public boolean canCompleteNormally = true;
        public ParameterKind paramKind;

        public JCLambda(List<JCVariableDecl> params,
                        JCTree body) {
            this.params = params;
            this.body = body;
            if (params.isEmpty() ||
                params.head.vartype != null) {
                paramKind = ParameterKind.EXPLICIT;
            } else {
                paramKind = ParameterKind.IMPLICIT;
            }
        }
        @Override
        public Tag getTag() {
            return LAMBDA;
        }
        @Override
        public void accept(Visitor v) {
            v.visitLambda(this);
        }
        @Override
        public <R, D> R accept(TreeVisitor v, D d) {
            return v.visitLambdaExpression(this, d);
        }
        public Kind getKind() {
            return Kind.LAMBDA_EXPRESSION;
        }
        public JCTree getBody() {
            return body;
        }
        public java.util.List<? extends VariableTree> getParameters() {
            return params;
        }
        @Override
        public JCLambda setType(Type type) {
            super.setType(type);
            return this;
        }
        @Override
        public BodyKind getBodyKind() {
            return body.hasTag(BLOCK) ?
                    BodyKind.STATEMENT :
                    BodyKind.EXPRESSION;
        }
    }

    /**
     * A parenthesized subexpression ( ... )
     */
    public static class JCParens extends JCExpression implements ParenthesizedTree {
        public JCExpression expr;
        protected JCParens(JCExpression expr) {
            this.expr = expr;
        }
        @Override
        public void accept(Visitor v) { v.visitParens(this); }

        public Kind getKind() { return Kind.PARENTHESIZED; }
        public JCExpression getExpression() { return expr; }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitParenthesized(this, d);
        }
        @Override
        public Tag getTag() {
            return PARENS;
        }
    }

    /**
     * A assignment with "=".
     */
    public static class JCAssign extends JCExpression implements AssignmentTree {
        public JCExpression lhs;
        public JCExpression rhs;
        protected JCAssign(JCExpression lhs, JCExpression rhs) {
            this.lhs = lhs;
            this.rhs = rhs;
        }
        @Override
        public void accept(Visitor v) { v.visitAssign(this); }

        public Kind getKind() { return Kind.ASSIGNMENT; }
        public JCExpression getVariable() { return lhs; }
        public JCExpression getExpression() { return rhs; }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitAssignment(this, d);
        }
        @Override
        public Tag getTag() {
            return ASSIGN;
        }
    }

    /**
     * An assignment with "+=", "|=" ...
     */
    public static class JCAssignOp extends JCExpression implements CompoundAssignmentTree {
        private Tag opcode;
        public JCExpression lhs;
        public JCExpression rhs;
        public Symbol operator;
        protected JCAssignOp(Tag opcode, JCTree lhs, JCTree rhs, Symbol operator) {
            this.opcode = opcode;
            this.lhs = (JCExpression)lhs;
            this.rhs = (JCExpression)rhs;
            this.operator = operator;
        }
        @Override
        public void accept(Visitor v) { v.visitAssignop(this); }

        public Kind getKind() { return TreeInfo.tagToKind(getTag()); }
        public JCExpression getVariable() { return lhs; }
        public JCExpression getExpression() { return rhs; }
        public Symbol getOperator() {
            return operator;
        }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitCompoundAssignment(this, d);
        }
        @Override
        public Tag getTag() {
            return opcode;
        }
    }

    /**
     * A unary operation.
     */
    public static class JCUnary extends JCExpression implements UnaryTree {
        private Tag opcode;
        public JCExpression arg;
        public Symbol operator;
        protected JCUnary(Tag opcode, JCExpression arg) {
            this.opcode = opcode;
            this.arg = arg;
        }
        @Override
        public void accept(Visitor v) { v.visitUnary(this); }

        public Kind getKind() { return TreeInfo.tagToKind(getTag()); }
        public JCExpression getExpression() { return arg; }
        public Symbol getOperator() {
            return operator;
        }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitUnary(this, d);
        }
        @Override
        public Tag getTag() {
            return opcode;
        }

        public void setTag(Tag tag) {
            opcode = tag;
        }
    }

    /**
     * A binary operation.
     */
    public static class JCBinary extends JCExpression implements BinaryTree {
        private Tag opcode;
        public JCExpression lhs;
        public JCExpression rhs;
        public Symbol operator;
        protected JCBinary(Tag opcode,
                         JCExpression lhs,
                         JCExpression rhs,
                         Symbol operator) {
            this.opcode = opcode;
            this.lhs = lhs;
            this.rhs = rhs;
            this.operator = operator;
        }
        @Override
        public void accept(Visitor v) { v.visitBinary(this); }

        public Kind getKind() { return TreeInfo.tagToKind(getTag()); }
        public JCExpression getLeftOperand() { return lhs; }
        public JCExpression getRightOperand() { return rhs; }
        public Symbol getOperator() {
            return operator;
        }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitBinary(this, d);
        }
        @Override
        public Tag getTag() {
            return opcode;
        }
    }

    /**
     * A type cast.
     */
    public static class JCTypeCast extends JCExpression implements TypeCastTree {
        public JCTree clazz;
        public JCExpression expr;
        protected JCTypeCast(JCTree clazz, JCExpression expr) {
            this.clazz = clazz;
            this.expr = expr;
        }
        @Override
        public void accept(Visitor v) { v.visitTypeCast(this); }

        public Kind getKind() { return Kind.TYPE_CAST; }
        public JCTree getType() { return clazz; }
        public JCExpression getExpression() { return expr; }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitTypeCast(this, d);
        }
        @Override
        public Tag getTag() {
            return TYPECAST;
        }
    }

    /**
     * A type test.
     */
    public static class JCInstanceOf extends JCExpression implements InstanceOfTree {
        public JCExpression expr;
        public JCTree clazz;
        protected JCInstanceOf(JCExpression expr, JCTree clazz) {
            this.expr = expr;
            this.clazz = clazz;
        }
        @Override
        public void accept(Visitor v) { v.visitTypeTest(this); }

        public Kind getKind() { return Kind.INSTANCE_OF; }
        public JCTree getType() { return clazz; }
        public JCExpression getExpression() { return expr; }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitInstanceOf(this, d);
        }
        @Override
        public Tag getTag() {
            return TYPETEST;
        }
    }

    /**
     * An array selection
     */
    public static class JCArrayAccess extends JCExpression implements ArrayAccessTree {
        public JCExpression indexed;
        public JCExpression index;
        protected JCArrayAccess(JCExpression indexed, JCExpression index) {
            this.indexed = indexed;
            this.index = index;
        }
        @Override
        public void accept(Visitor v) { v.visitIndexed(this); }

        public Kind getKind() { return Kind.ARRAY_ACCESS; }
        public JCExpression getExpression() { return indexed; }
        public JCExpression getIndex() { return index; }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitArrayAccess(this, d);
        }
        @Override
        public Tag getTag() {
            return INDEXED;
        }
    }

    /**
     * Selects through packages and classes
     */
    public static class JCFieldAccess extends JCExpression implements MemberSelectTree {
        /** selected Tree hierarchy */
        public JCExpression selected;
        /** name of field to select thru */
        public Name name;
        /** symbol of the selected class */
        public Symbol sym;
        protected JCFieldAccess(JCExpression selected, Name name, Symbol sym) {
            this.selected = selected;
            this.name = name;
            this.sym = sym;
        }
        @Override
        public void accept(Visitor v) { v.visitSelect(this); }

        public Kind getKind() { return Kind.MEMBER_SELECT; }
        public JCExpression getExpression() { return selected; }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitMemberSelect(this, d);
        }
        public Name getIdentifier() { return name; }
        @Override
        public Tag getTag() {
            return SELECT;
        }
    }

    /**
     * Selects a member expression.
     */
    public static class JCMemberReference extends JCFunctionalExpression implements MemberReferenceTree {

        public ReferenceMode mode;
        public ReferenceKind kind;
        public Name name;
        public JCExpression expr;
        public List<JCExpression> typeargs;
        public Symbol sym;
        public Type varargsElement;
        public PolyKind refPolyKind;
        public boolean ownerAccessible;
        public OverloadKind overloadKind;

        public enum OverloadKind {
            OVERLOADED,
            UNOVERLOADED;
        }

        /**
         * Javac-dependent classification for member references, based
         * on relevant properties w.r.t. code-generation
         */
        public enum ReferenceKind {
            /** super # instMethod */
            SUPER(ReferenceMode.INVOKE, false),
            /** Type # instMethod */
            UNBOUND(ReferenceMode.INVOKE, true),
            /** Type # staticMethod */
            STATIC(ReferenceMode.INVOKE, false),
            /** Expr # instMethod */
            BOUND(ReferenceMode.INVOKE, false),
            /** Inner # new */
            IMPLICIT_INNER(ReferenceMode.NEW, false),
            /** Toplevel # new */
            TOPLEVEL(ReferenceMode.NEW, false),
            /** ArrayType # new */
            ARRAY_CTOR(ReferenceMode.NEW, false);

            final ReferenceMode mode;
            final boolean unbound;

            private ReferenceKind(ReferenceMode mode, boolean unbound) {
                this.mode = mode;
                this.unbound = unbound;
            }

            public boolean isUnbound() {
                return unbound;
            }
        }

        protected JCMemberReference(ReferenceMode mode, Name name, JCExpression expr, List<JCExpression> typeargs) {
            this.mode = mode;
            this.name = name;
            this.expr = expr;
            this.typeargs = typeargs;
        }
        @Override
        public void accept(Visitor v) { v.visitReference(this); }

        public Kind getKind() { return Kind.MEMBER_REFERENCE; }
        @Override
        public ReferenceMode getMode() { return mode; }
        @Override
        public JCExpression getQualifierExpression() { return expr; }
        @Override
        public Name getName() { return name; }
        @Override
        public List<JCExpression> getTypeArguments() { return typeargs; }

        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitMemberReference(this, d);
        }
        @Override
        public Tag getTag() {
            return REFERENCE;
        }
        public boolean hasKind(ReferenceKind kind) {
            return this.kind == kind;
        }
    }

    /**
     * An identifier
     */
    public static class JCIdent extends JCExpression implements IdentifierTree {
        /** the name */
        public Name name;
        /** the symbol */
        public Symbol sym;
        protected JCIdent(Name name, Symbol sym) {
            this.name = name;
            this.sym = sym;
        }
        @Override
        public void accept(Visitor v) { v.visitIdent(this); }

        public Kind getKind() { return Kind.IDENTIFIER; }
        public Name getName() { return name; }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitIdentifier(this, d);
        }
        @Override
        public Tag getTag() {
            return IDENT;
        }
    }

    /**
     * A constant value given literally.
     */
    public static class JCLiteral extends JCExpression implements LiteralTree {
        public TypeTag typetag;
        /** value representation */
        public Object value;
        protected JCLiteral(TypeTag typetag, Object value) {
            this.typetag = typetag;
            this.value = value;
        }
        @Override
        public void accept(Visitor v) { v.visitLiteral(this); }

        public Kind getKind() {
            return typetag.getKindLiteral();
        }

        public Object getValue() {
            switch (typetag) {
                case BOOLEAN:
                    int bi = (Integer) value;
                    return (bi != 0);
                case CHAR:
                    int ci = (Integer) value;
                    char c = (char) ci;
                    if (c != ci)
                        throw new AssertionError("bad value for char literal");
                    return c;
                default:
                    return value;
            }
        }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitLiteral(this, d);
        }
        @Override
        public JCLiteral setType(Type type) {
            super.setType(type);
            return this;
        }
        @Override
        public Tag getTag() {
            return LITERAL;
        }
    }

    /**
     * Identifies a basic type.
     * @see TypeTag
     */
    public static class JCPrimitiveTypeTree extends JCExpression implements PrimitiveTypeTree {
        /** the basic type id */
        public TypeTag typetag;
        protected JCPrimitiveTypeTree(TypeTag typetag) {
            this.typetag = typetag;
        }
        @Override
        public void accept(Visitor v) { v.visitTypeIdent(this); }

        public Kind getKind() { return Kind.PRIMITIVE_TYPE; }
        public TypeKind getPrimitiveTypeKind() {
            return typetag.getPrimitiveTypeKind();
        }

        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitPrimitiveType(this, d);
        }
        @Override
        public Tag getTag() {
            return TYPEIDENT;
        }
    }

    /**
     * An array type, A[]
     */
    public static class JCArrayTypeTree extends JCExpression implements ArrayTypeTree {
        public JCExpression elemtype;
        protected JCArrayTypeTree(JCExpression elemtype) {
            this.elemtype = elemtype;
        }
        @Override
        public void accept(Visitor v) { v.visitTypeArray(this); }

        public Kind getKind() { return Kind.ARRAY_TYPE; }
        public JCTree getType() { return elemtype; }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitArrayType(this, d);
        }
        @Override
        public Tag getTag() {
            return TYPEARRAY;
        }
    }

    /**
     * A parameterized type, {@literal T<...>}
     */
    public static class JCTypeApply extends JCExpression implements ParameterizedTypeTree {
        public JCExpression clazz;
        public List<JCExpression> arguments;
        protected JCTypeApply(JCExpression clazz, List<JCExpression> arguments) {
            this.clazz = clazz;
            this.arguments = arguments;
        }
        @Override
        public void accept(Visitor v) { v.visitTypeApply(this); }

        public Kind getKind() { return Kind.PARAMETERIZED_TYPE; }
        public JCTree getType() { return clazz; }
        public List<JCExpression> getTypeArguments() {
            return arguments;
        }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitParameterizedType(this, d);
        }
        @Override
        public Tag getTag() {
            return TYPEAPPLY;
        }
    }

    /**
     * A union type, T1 | T2 | ... Tn (used in multicatch statements)
     */
    public static class JCTypeUnion extends JCExpression implements UnionTypeTree {

        public List<JCExpression> alternatives;

        protected JCTypeUnion(List<JCExpression> components) {
            this.alternatives = components;
        }
        @Override
        public void accept(Visitor v) { v.visitTypeUnion(this); }

        public Kind getKind() { return Kind.UNION_TYPE; }

        public List<JCExpression> getTypeAlternatives() {
            return alternatives;
        }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitUnionType(this, d);
        }
        @Override
        public Tag getTag() {
            return TYPEUNION;
        }
    }

    /**
     * An intersection type, T1 & T2 & ... Tn (used in cast expressions)
     */
    public static class JCTypeIntersection extends JCExpression implements IntersectionTypeTree {

        public List<JCExpression> bounds;

        protected JCTypeIntersection(List<JCExpression> bounds) {
            this.bounds = bounds;
        }
        @Override
        public void accept(Visitor v) { v.visitTypeIntersection(this); }

        public Kind getKind() { return Kind.INTERSECTION_TYPE; }

        public List<JCExpression> getBounds() {
            return bounds;
        }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitIntersectionType(this, d);
        }
        @Override
        public Tag getTag() {
            return TYPEINTERSECTION;
        }
    }

    /**
     * A formal class parameter.
     */
    public static class JCTypeParameter extends JCTree implements TypeParameterTree {
        /** name */
        public Name name;
        /** bounds */
        public List<JCExpression> bounds;
        /** type annotations on type parameter */
        public List<JCAnnotation> annotations;
        protected JCTypeParameter(Name name, List<JCExpression> bounds, List annotations) {
            this.name = name;
            this.bounds = bounds;
            this.annotations = annotations;
        }
        @Override
        public void accept(Visitor v) { v.visitTypeParameter(this); }

        public Kind getKind() { return Kind.TYPE_PARAMETER; }
        public Name getName() { return name; }
        public List<JCExpression> getBounds() {
            return bounds;
        }
        public List<JCAnnotation> getAnnotations() {
            return annotations;
        }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitTypeParameter(this, d);
        }
        @Override
        public Tag getTag() {
            return TYPEPARAMETER;
        }
    }

    public static class JCWildcard extends JCExpression implements WildcardTree {
        public TypeBoundKind kind;
        public JCTree inner;
        protected JCWildcard(TypeBoundKind kind, JCTree inner) {
            kind.getClass(); // null-check
            this.kind = kind;
            this.inner = inner;
        }
        @Override
        public void accept(Visitor v) { v.visitWildcard(this); }

        public Kind getKind() {
            switch (kind.kind) {
            case UNBOUND:
                return Kind.UNBOUNDED_WILDCARD;
            case EXTENDS:
                return Kind.EXTENDS_WILDCARD;
            case SUPER:
                return Kind.SUPER_WILDCARD;
            default:
                throw new AssertionError("Unknown wildcard bound " + kind);
            }
        }
        public JCTree getBound() { return inner; }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitWildcard(this, d);
        }
        @Override
        public Tag getTag() {
            return Tag.WILDCARD;
        }
    }

    public static class TypeBoundKind extends JCTree {
        public BoundKind kind;
        protected TypeBoundKind(BoundKind kind) {
            this.kind = kind;
        }
        @Override
        public void accept(Visitor v) { v.visitTypeBoundKind(this); }

        public Kind getKind() {
            throw new AssertionError("TypeBoundKind is not part of a public API");
        }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            throw new AssertionError("TypeBoundKind is not part of a public API");
        }
        @Override
        public Tag getTag() {
            return TYPEBOUNDKIND;
        }
    }

    public static class JCAnnotation extends JCExpression implements AnnotationTree {
        // Either Tag.ANNOTATION or Tag.TYPE_ANNOTATION
        private Tag tag;

        public JCTree annotationType;
        public List<JCExpression> args;

        // Attribute.Compound if tag is ANNOTATION
        // Attribute.TypeCompound if tag is TYPE_ANNOTATION
        public Attribute.Compound attribute;

        protected JCAnnotation(Tag tag, JCTree annotationType, List<JCExpression> args) {
            this.tag = tag;
            this.annotationType = annotationType;
            this.args = args;
        }

        @Override
        public void accept(Visitor v) { v.visitAnnotation(this); }

        public Kind getKind() { return TreeInfo.tagToKind(getTag()); }

        public JCTree getAnnotationType() { return annotationType; }
        public List<JCExpression> getArguments() {
            return args;
        }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitAnnotation(this, d);
        }
        @Override
        public Tag getTag() {
            return tag;
        }
    }

    public static class JCModifiers extends JCTree implements com.sun.source.tree.ModifiersTree {
        public long flags;
        public List<JCAnnotation> annotations;
        protected JCModifiers(long flags, List<JCAnnotation> annotations) {
            this.flags = flags;
            this.annotations = annotations;
        }
        @Override
        public void accept(Visitor v) { v.visitModifiers(this); }

        public Kind getKind() { return Kind.MODIFIERS; }
        public Set<Modifier> getFlags() {
            return Flags.asModifierSet(flags);
        }
        public List<JCAnnotation> getAnnotations() {
            return annotations;
        }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitModifiers(this, d);
        }
        @Override
        public Tag getTag() {
            return MODIFIERS;
        }
    }

    public static class JCAnnotatedType extends JCExpression implements com.sun.source.tree.AnnotatedTypeTree {
        // type annotations
        public List<JCAnnotation> annotations;
        public JCExpression underlyingType;

        protected JCAnnotatedType(List<JCAnnotation> annotations, JCExpression underlyingType) {
            Assert.check(annotations != null && annotations.nonEmpty());
            this.annotations = annotations;
            this.underlyingType = underlyingType;
        }
        @Override
        public void accept(Visitor v) { v.visitAnnotatedType(this); }

        public Kind getKind() { return Kind.ANNOTATED_TYPE; }
        public List<JCAnnotation> getAnnotations() {
            return annotations;
        }
        public JCExpression getUnderlyingType() {
            return underlyingType;
        }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitAnnotatedType(this, d);
        }
        @Override
        public Tag getTag() {
            return ANNOTATED_TYPE;
        }
    }

    public static class JCErroneous extends JCExpression
            implements com.sun.source.tree.ErroneousTree {
        public List<? extends JCTree> errs;
        protected JCErroneous(List<? extends JCTree> errs) {
            this.errs = errs;
        }
        @Override
        public void accept(Visitor v) { v.visitErroneous(this); }

        public Kind getKind() { return Kind.ERRONEOUS; }

        public List<? extends JCTree> getErrorTrees() {
            return errs;
        }

        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            return v.visitErroneous(this, d);
        }
        @Override
        public Tag getTag() {
            return ERRONEOUS;
        }
    }

    /** (let int x = 3; in x+2) */
    public static class LetExpr extends JCExpression {
        public List<JCVariableDecl> defs;
        public JCTree expr;
        protected LetExpr(List<JCVariableDecl> defs, JCTree expr) {
            this.defs = defs;
            this.expr = expr;
        }
        @Override
        public void accept(Visitor v) { v.visitLetExpr(this); }

        public Kind getKind() {
            throw new AssertionError("LetExpr is not part of a public API");
        }
        @Override
        public <R,D> R accept(TreeVisitor v, D d) {
            throw new AssertionError("LetExpr is not part of a public API");
        }
        @Override
        public Tag getTag() {
            return LETEXPR;
        }
    }

    /** An interface for tree factories
     */
    public interface Factory {
        JCCompilationUnit TopLevel(List<JCAnnotation> packageAnnotations,
                                   JCExpression pid,
                                   List<JCTree> defs);
        JCImport Import(JCTree qualid, boolean staticImport);
        JCClassDecl ClassDef(JCModifiers mods,
                          Name name,
                          List<JCTypeParameter> typarams,
                          JCExpression extending,
                          List<JCExpression> implementing,
                          List<JCTree> defs);
        JCMethodDecl MethodDef(JCModifiers mods,
                            Name name,
                            JCExpression restype,
                            List<JCTypeParameter> typarams,
                            JCVariableDecl recvparam,
                            List<JCVariableDecl> params,
                            List<JCExpression> thrown,
                            JCBlock body,
                            JCExpression defaultValue);
        JCVariableDecl VarDef(JCModifiers mods,
                      Name name,
                      JCExpression vartype,
                      JCExpression init);
        JCSkip Skip();
        JCBlock Block(long flags, List<JCStatement> stats);
        JCDoWhileLoop DoLoop(JCStatement body, JCExpression cond);
        JCWhileLoop WhileLoop(JCExpression cond, JCStatement body);
        JCForLoop ForLoop(List<JCStatement> init,
                        JCExpression cond,
                        List<JCExpressionStatement> step,
                        JCStatement body);
        JCEnhancedForLoop ForeachLoop(JCVariableDecl var, JCExpression expr, JCStatement body);
        JCLabeledStatement Labelled(Name label, JCStatement body);
        JCSwitch Switch(JCExpression selector, List<JCCase> cases);
        JCCase Case(JCExpression pat, List<JCStatement> stats);
        JCSynchronized Synchronized(JCExpression lock, JCBlock body);
        JCTry Try(JCBlock body, List<JCCatch> catchers, JCBlock finalizer);
        JCTry Try(List<JCTree> resources,
                  JCBlock body,
                  List<JCCatch> catchers,
                  JCBlock finalizer);
        JCCatch Catch(JCVariableDecl param, JCBlock body);
        JCConditional Conditional(JCExpression cond,
                                JCExpression thenpart,
                                JCExpression elsepart);
        JCIf If(JCExpression cond, JCStatement thenpart, JCStatement elsepart);
        JCExpressionStatement Exec(JCExpression expr);
        JCBreak Break(Name label);
        JCContinue Continue(Name label);
        JCReturn Return(JCExpression expr);
        JCThrow Throw(JCExpression expr);
        JCAssert Assert(JCExpression cond, JCExpression detail);
        JCMethodInvocation Apply(List<JCExpression> typeargs,
                    JCExpression fn,
                    List<JCExpression> args);
        JCNewClass NewClass(JCExpression encl,
                          List<JCExpression> typeargs,
                          JCExpression clazz,
                          List<JCExpression> args,
                          JCClassDecl def);
        JCNewArray NewArray(JCExpression elemtype,
                          List<JCExpression> dims,
                          List<JCExpression> elems);
        JCParens Parens(JCExpression expr);
        JCAssign Assign(JCExpression lhs, JCExpression rhs);
        JCAssignOp Assignop(Tag opcode, JCTree lhs, JCTree rhs);
        JCUnary Unary(Tag opcode, JCExpression arg);
        JCBinary Binary(Tag opcode, JCExpression lhs, JCExpression rhs);
        JCTypeCast TypeCast(JCTree expr, JCExpression type);
        JCInstanceOf TypeTest(JCExpression expr, JCTree clazz);
        JCArrayAccess Indexed(JCExpression indexed, JCExpression index);
        JCFieldAccess Select(JCExpression selected, Name selector);
        JCIdent Ident(Name idname);
        JCLiteral Literal(TypeTag tag, Object value);
        JCPrimitiveTypeTree TypeIdent(TypeTag typetag);
        JCArrayTypeTree TypeArray(JCExpression elemtype);
        JCTypeApply TypeApply(JCExpression clazz, List<JCExpression> arguments);
        JCTypeParameter TypeParameter(Name name, List<JCExpression> bounds);
        JCWildcard Wildcard(TypeBoundKind kind, JCTree type);
        TypeBoundKind TypeBoundKind(BoundKind kind);
        JCAnnotation Annotation(JCTree annotationType, List<JCExpression> args);
        JCModifiers Modifiers(long flags, List<JCAnnotation> annotations);
        JCErroneous Erroneous(List<? extends JCTree> errs);
        LetExpr LetExpr(List<JCVariableDecl> defs, JCTree expr);
    }

    /** A generic visitor class for trees.
     */
    public static abstract class Visitor {
        public void visitTopLevel(JCCompilationUnit that)    { visitTree(that); }
        public void visitImport(JCImport that)               { visitTree(that); }
        public void visitClassDef(JCClassDecl that)          { visitTree(that); }
        public void visitMethodDef(JCMethodDecl that)        { visitTree(that); }
        public void visitVarDef(JCVariableDecl that)         { visitTree(that); }
        public void visitSkip(JCSkip that)                   { visitTree(that); }
        public void visitBlock(JCBlock that)                 { visitTree(that); }
        public void visitDoLoop(JCDoWhileLoop that)          { visitTree(that); }
        public void visitWhileLoop(JCWhileLoop that)         { visitTree(that); }
        public void visitForLoop(JCForLoop that)             { visitTree(that); }
        public void visitForeachLoop(JCEnhancedForLoop that) { visitTree(that); }
        public void visitLabelled(JCLabeledStatement that)   { visitTree(that); }
        public void visitSwitch(JCSwitch that)               { visitTree(that); }
        public void visitCase(JCCase that)                   { visitTree(that); }
        public void visitSynchronized(JCSynchronized that)   { visitTree(that); }
        public void visitTry(JCTry that)                     { visitTree(that); }
        public void visitCatch(JCCatch that)                 { visitTree(that); }
        public void visitConditional(JCConditional that)     { visitTree(that); }
        public void visitIf(JCIf that)                       { visitTree(that); }
        public void visitExec(JCExpressionStatement that)    { visitTree(that); }
        public void visitBreak(JCBreak that)                 { visitTree(that); }
        public void visitContinue(JCContinue that)           { visitTree(that); }
        public void visitReturn(JCReturn that)               { visitTree(that); }
        public void visitThrow(JCThrow that)                 { visitTree(that); }
        public void visitAssert(JCAssert that)               { visitTree(that); }
        public void visitApply(JCMethodInvocation that)      { visitTree(that); }
        public void visitNewClass(JCNewClass that)           { visitTree(that); }
        public void visitNewArray(JCNewArray that)           { visitTree(that); }
        public void visitLambda(JCLambda that)               { visitTree(that); }
        public void visitParens(JCParens that)               { visitTree(that); }
        public void visitAssign(JCAssign that)               { visitTree(that); }
        public void visitAssignop(JCAssignOp that)           { visitTree(that); }
        public void visitUnary(JCUnary that)                 { visitTree(that); }
        public void visitBinary(JCBinary that)               { visitTree(that); }
        public void visitTypeCast(JCTypeCast that)           { visitTree(that); }
        public void visitTypeTest(JCInstanceOf that)         { visitTree(that); }
        public void visitIndexed(JCArrayAccess that)         { visitTree(that); }
        public void visitSelect(JCFieldAccess that)          { visitTree(that); }
        public void visitReference(JCMemberReference that)   { visitTree(that); }
        public void visitIdent(JCIdent that)                 { visitTree(that); }
        public void visitLiteral(JCLiteral that)             { visitTree(that); }
        public void visitTypeIdent(JCPrimitiveTypeTree that) { visitTree(that); }
        public void visitTypeArray(JCArrayTypeTree that)     { visitTree(that); }
        public void visitTypeApply(JCTypeApply that)         { visitTree(that); }
        public void visitTypeUnion(JCTypeUnion that)         { visitTree(that); }
        public void visitTypeIntersection(JCTypeIntersection that)  { visitTree(that); }
        public void visitTypeParameter(JCTypeParameter that) { visitTree(that); }
        public void visitWildcard(JCWildcard that)           { visitTree(that); }
        public void visitTypeBoundKind(TypeBoundKind that)   { visitTree(that); }
        public void visitAnnotation(JCAnnotation that)       { visitTree(that); }
        public void visitModifiers(JCModifiers that)         { visitTree(that); }
        public void visitAnnotatedType(JCAnnotatedType that) { visitTree(that); }
        public void visitErroneous(JCErroneous that)         { visitTree(that); }
        public void visitLetExpr(LetExpr that)               { visitTree(that); }

        public void visitTree(JCTree that)                   { Assert.error(); }
    }

}

Other Java examples (source code examples)

Here is a short list of links related to this Java JCTree.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.