1 /*
   2  * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.tools.javac.tree;
  27 
  28 import com.sun.source.tree.*;
  29 import com.sun.tools.javac.tree.JCTree.*;
  30 import com.sun.tools.javac.util.List;
  31 import com.sun.tools.javac.util.ListBuffer;
  32 
  33 /**
  34  * Creates a copy of a tree, using a given TreeMaker.
  35  * Names, literal values, etc are shared with the original.
  36  *
  37  *  <p><b>This is NOT part of any supported API.
  38  *  If you write code that depends on this, you do so at your own risk.
  39  *  This code and its internal interfaces are subject to change or
  40  *  deletion without notice.</b>
  41  */
  42 public class TreeCopier<P> implements TreeVisitor<JCTree,P> {
  43     private TreeMaker M;
  44 
  45     /** Creates a new instance of TreeCopier */
  46     public TreeCopier(TreeMaker M) {
  47         this.M = M;
  48     }
  49 
  50     public <T extends JCTree> T copy(T tree) {
  51         return copy(tree, null);
  52     }
  53 
  54     @SuppressWarnings("unchecked")
  55     public <T extends JCTree> T copy(T tree, P p) {
  56         if (tree == null)
  57             return null;
  58         return (T) (tree.accept(this, p));
  59     }
  60 
  61     public <T extends JCTree> List<T> copy(List<T> trees) {
  62         return copy(trees, null);
  63     }
  64 
  65     public <T extends JCTree> List<T> copy(List<T> trees, P p) {
  66         if (trees == null)
  67             return null;
  68         ListBuffer<T> lb = new ListBuffer<T>();
  69         for (T tree: trees)
  70             lb.append(copy(tree, p));
  71         return lb.toList();
  72     }
  73 
  74     public JCTree visitAnnotation(AnnotationTree node, P p) {
  75         JCAnnotation t = (JCAnnotation) node;
  76         JCTree annotationType = copy(t.annotationType, p);
  77         List<JCExpression> args = copy(t.args, p);
  78         return M.at(t.pos).Annotation(annotationType, args);
  79     }
  80 
  81     public JCTree visitAssert(AssertTree node, P p) {
  82         JCAssert t = (JCAssert) node;
  83         JCExpression cond = copy(t.cond, p);
  84         JCExpression detail = copy(t.detail, p);
  85         return M.at(t.pos).Assert(cond, detail);
  86     }
  87 
  88     public JCTree visitAssignment(AssignmentTree node, P p) {
  89         JCAssign t = (JCAssign) node;
  90         JCExpression lhs = copy(t.lhs, p);
  91         JCExpression rhs = copy(t.rhs, p);
  92         return M.at(t.pos).Assign(lhs, rhs);
  93     }
  94 
  95     public JCTree visitCompoundAssignment(CompoundAssignmentTree node, P p) {
  96         JCAssignOp t = (JCAssignOp) node;
  97         JCTree lhs = copy(t.lhs, p);
  98         JCTree rhs = copy(t.rhs, p);
  99         return M.at(t.pos).Assignop(t.getTag(), lhs, rhs);
 100     }
 101 
 102     public JCTree visitBinary(BinaryTree node, P p) {
 103         JCBinary t = (JCBinary) node;
 104         JCExpression lhs = copy(t.lhs, p);
 105         JCExpression rhs = copy(t.rhs, p);
 106         return M.at(t.pos).Binary(t.getTag(), lhs, rhs);
 107     }
 108 
 109     public JCTree visitBlock(BlockTree node, P p) {
 110         JCBlock t = (JCBlock) node;
 111         List<JCStatement> stats = copy(t.stats, p);
 112         return M.at(t.pos).Block(t.flags, stats);
 113     }
 114 
 115     public JCTree visitBreak(BreakTree node, P p) {
 116         JCBreak t = (JCBreak) node;
 117         return M.at(t.pos).Break(t.label);
 118     }
 119 
 120     public JCTree visitCase(CaseTree node, P p) {
 121         JCCase t = (JCCase) node;
 122         JCExpression pat = copy(t.pat, p);
 123         List<JCStatement> stats = copy(t.stats, p);
 124         return M.at(t.pos).Case(pat, stats);
 125     }
 126 
 127     public JCTree visitCatch(CatchTree node, P p) {
 128         JCCatch t = (JCCatch) node;
 129         JCVariableDecl param = copy(t.param, p);
 130         JCBlock body = copy(t.body, p);
 131         return M.at(t.pos).Catch(param, body);
 132     }
 133 
 134     public JCTree visitClass(ClassTree node, P p) {
 135         JCClassDecl t = (JCClassDecl) node;
 136         JCModifiers mods = copy(t.mods, p);
 137         List<JCTypeParameter> typarams = copy(t.typarams, p);
 138         JCExpression extending = copy(t.extending, p);
 139         List<JCExpression> implementing = copy(t.implementing, p);
 140         List<JCTree> defs = copy(t.defs, p);
 141         return M.at(t.pos).ClassDef(mods, t.name, typarams, extending, implementing, defs);
 142     }
 143 
 144     public JCTree visitConditionalExpression(ConditionalExpressionTree node, P p) {
 145         JCConditional t = (JCConditional) node;
 146         JCExpression cond = copy(t.cond, p);
 147         JCExpression truepart = copy(t.truepart, p);
 148         JCExpression falsepart = copy(t.falsepart, p);
 149         return M.at(t.pos).Conditional(cond, truepart, falsepart);
 150     }
 151 
 152     public JCTree visitContinue(ContinueTree node, P p) {
 153         JCContinue t = (JCContinue) node;
 154         return M.at(t.pos).Continue(t.label);
 155     }
 156 
 157     public JCTree visitDoWhileLoop(DoWhileLoopTree node, P p) {
 158         JCDoWhileLoop t = (JCDoWhileLoop) node;
 159         JCStatement body = copy(t.body, p);
 160         JCExpression cond = copy(t.cond, p);
 161         return M.at(t.pos).DoLoop(body, cond);
 162     }
 163 
 164     public JCTree visitErroneous(ErroneousTree node, P p) {
 165         JCErroneous t = (JCErroneous) node;
 166         List<? extends JCTree> errs = copy(t.errs, p);
 167         return M.at(t.pos).Erroneous(errs);
 168     }
 169 
 170     public JCTree visitExpressionStatement(ExpressionStatementTree node, P p) {
 171         JCExpressionStatement t = (JCExpressionStatement) node;
 172         JCExpression expr = copy(t.expr, p);
 173         return M.at(t.pos).Exec(expr);
 174     }
 175 
 176     public JCTree visitEnhancedForLoop(EnhancedForLoopTree node, P p) {
 177         JCEnhancedForLoop t = (JCEnhancedForLoop) node;
 178         JCVariableDecl var = copy(t.var, p);
 179         JCExpression expr = copy(t.expr, p);
 180         JCStatement body = copy(t.body, p);
 181         return M.at(t.pos).ForeachLoop(var, expr, body);
 182     }
 183 
 184     public JCTree visitForLoop(ForLoopTree node, P p) {
 185         JCForLoop t = (JCForLoop) node;
 186         List<JCStatement> init = copy(t.init, p);
 187         JCExpression cond = copy(t.cond, p);
 188         List<JCExpressionStatement> step = copy(t.step, p);
 189         JCStatement body = copy(t.body, p);
 190         return M.at(t.pos).ForLoop(init, cond, step, body);
 191     }
 192 
 193     public JCTree visitIdentifier(IdentifierTree node, P p) {
 194         JCIdent t = (JCIdent) node;
 195         return M.at(t.pos).Ident(t.name);
 196     }
 197 
 198     public JCTree visitIf(IfTree node, P p) {
 199         JCIf t = (JCIf) node;
 200         JCExpression cond = copy(t.cond, p);
 201         JCStatement thenpart = copy(t.thenpart, p);
 202         JCStatement elsepart = copy(t.elsepart, p);
 203         return M.at(t.pos).If(cond, thenpart, elsepart);
 204     }
 205 
 206     public JCTree visitImport(ImportTree node, P p) {
 207         JCImport t = (JCImport) node;
 208         JCTree qualid = copy(t.qualid, p);
 209         return M.at(t.pos).Import(qualid, t.staticImport);
 210     }
 211 
 212     public JCTree visitArrayAccess(ArrayAccessTree node, P p) {
 213         JCArrayAccess t = (JCArrayAccess) node;
 214         JCExpression indexed = copy(t.indexed, p);
 215         JCExpression index = copy(t.index, p);
 216         return M.at(t.pos).Indexed(indexed, index);
 217     }
 218 
 219     public JCTree visitLabeledStatement(LabeledStatementTree node, P p) {
 220         JCLabeledStatement t = (JCLabeledStatement) node;
 221         JCStatement body = copy(t.body, p);
 222         return M.at(t.pos).Labelled(t.label, t.body);
 223     }
 224 
 225     public JCTree visitLiteral(LiteralTree node, P p) {
 226         JCLiteral t = (JCLiteral) node;
 227         return M.at(t.pos).Literal(t.typetag, t.value);
 228     }
 229 
 230     public JCTree visitMethod(MethodTree node, P p) {
 231         JCMethodDecl t  = (JCMethodDecl) node;
 232         JCModifiers mods = copy(t.mods, p);
 233         JCExpression restype = copy(t.restype, p);
 234         List<JCTypeParameter> typarams = copy(t.typarams, p);
 235         List<JCVariableDecl> params = copy(t.params, p);
 236         List<JCExpression> thrown = copy(t.thrown, p);
 237         JCBlock body = copy(t.body, p);
 238         JCExpression defaultValue = copy(t.defaultValue, p);
 239         return M.at(t.pos).MethodDef(mods, t.name, restype, typarams, params, thrown, body, defaultValue);
 240     }
 241 
 242     public JCTree visitMethodInvocation(MethodInvocationTree node, P p) {
 243         JCMethodInvocation t = (JCMethodInvocation) node;
 244         List<JCExpression> typeargs = copy(t.typeargs, p);
 245         JCExpression meth = copy(t.meth, p);
 246         List<JCExpression> args = copy(t.args, p);
 247         return M.at(t.pos).Apply(typeargs, meth, args);
 248     }
 249 
 250     public JCTree visitModifiers(ModifiersTree node, P p) {
 251         JCModifiers t = (JCModifiers) node;
 252         List<JCAnnotation> annotations = copy(t.annotations, p);
 253         return M.at(t.pos).Modifiers(t.flags, annotations);
 254     }
 255 
 256     public JCTree visitNewArray(NewArrayTree node, P p) {
 257         JCNewArray t = (JCNewArray) node;
 258         JCExpression elemtype = copy(t.elemtype, p);
 259         List<JCExpression> dims = copy(t.dims, p);
 260         List<JCExpression> elems = copy(t.elems, p);
 261         return M.at(t.pos).NewArray(elemtype, dims, elems);
 262     }
 263 
 264     public JCTree visitNewClass(NewClassTree node, P p) {
 265         JCNewClass t = (JCNewClass) node;
 266         JCExpression encl = copy(t.encl, p);
 267         List<JCExpression> typeargs = copy(t.typeargs, p);
 268         JCExpression clazz = copy(t.clazz, p);
 269         List<JCExpression> args = copy(t.args, p);
 270         JCClassDecl def = copy(t.def, p);
 271         return M.at(t.pos).NewClass(encl, typeargs, clazz, args, def);
 272     }
 273 
 274     public JCTree visitParenthesized(ParenthesizedTree node, P p) {
 275         JCParens t = (JCParens) node;
 276         JCExpression expr = copy(t.expr, p);
 277         return M.at(t.pos).Parens(expr);
 278     }
 279 
 280     public JCTree visitReturn(ReturnTree node, P p) {
 281         JCReturn t = (JCReturn) node;
 282         JCExpression expr = copy(t.expr, p);
 283         return M.at(t.pos).Return(expr);
 284     }
 285 
 286     public JCTree visitMemberSelect(MemberSelectTree node, P p) {
 287         JCFieldAccess t = (JCFieldAccess) node;
 288         JCExpression selected = copy(t.selected, p);
 289         return M.at(t.pos).Select(selected, t.name);
 290     }
 291 
 292     public JCTree visitEmptyStatement(EmptyStatementTree node, P p) {
 293         JCSkip t = (JCSkip) node;
 294         return M.at(t.pos).Skip();
 295     }
 296 
 297     public JCTree visitSwitch(SwitchTree node, P p) {
 298         JCSwitch t = (JCSwitch) node;
 299         JCExpression selector = copy(t.selector, p);
 300         List<JCCase> cases = copy(t.cases, p);
 301         return M.at(t.pos).Switch(selector, cases);
 302     }
 303 
 304     public JCTree visitSynchronized(SynchronizedTree node, P p) {
 305         JCSynchronized t = (JCSynchronized) node;
 306         JCExpression lock = copy(t.lock, p);
 307         JCBlock body = copy(t.body, p);
 308         return M.at(t.pos).Synchronized(lock, body);
 309     }
 310 
 311     public JCTree visitThrow(ThrowTree node, P p) {
 312         JCThrow t = (JCThrow) node;
 313         JCTree expr = copy(t.expr, p);
 314         return M.at(t.pos).Throw(expr);
 315     }
 316 
 317     public JCTree visitCompilationUnit(CompilationUnitTree node, P p) {
 318         JCCompilationUnit t = (JCCompilationUnit) node;
 319         List<JCAnnotation> packageAnnotations = copy(t.packageAnnotations, p);
 320         JCExpression pid = copy(t.pid, p);
 321         List<JCTree> defs = copy(t.defs, p);
 322         return M.at(t.pos).TopLevel(packageAnnotations, pid, defs);
 323     }
 324 
 325     public JCTree visitTry(TryTree node, P p) {
 326         JCTry t = (JCTry) node;
 327         List<JCTree> resources = copy(t.resources, p);
 328         JCBlock body = copy(t.body, p);
 329         List<JCCatch> catchers = copy(t.catchers, p);
 330         JCBlock finalizer = copy(t.finalizer, p);
 331         return M.at(t.pos).Try(resources, body, catchers, finalizer);
 332     }
 333 
 334     public JCTree visitParameterizedType(ParameterizedTypeTree node, P p) {
 335         JCTypeApply t = (JCTypeApply) node;
 336         JCExpression clazz = copy(t.clazz, p);
 337         List<JCExpression> arguments = copy(t.arguments, p);
 338         return M.at(t.pos).TypeApply(clazz, arguments);
 339     }
 340 
 341     public JCTree visitUnionType(UnionTypeTree node, P p) {
 342         JCTypeUnion t = (JCTypeUnion) node;
 343         List<JCExpression> components = copy(t.alternatives, p);
 344         return M.at(t.pos).TypeUnion(components);
 345     }
 346 
 347     public JCTree visitArrayType(ArrayTypeTree node, P p) {
 348         JCArrayTypeTree t = (JCArrayTypeTree) node;
 349         JCExpression elemtype = copy(t.elemtype, p);
 350         return M.at(t.pos).TypeArray(elemtype);
 351     }
 352 
 353     public JCTree visitTypeCast(TypeCastTree node, P p) {
 354         JCTypeCast t = (JCTypeCast) node;
 355         JCTree clazz = copy(t.clazz, p);
 356         JCExpression expr = copy(t.expr, p);
 357         return M.at(t.pos).TypeCast(clazz, expr);
 358     }
 359 
 360     public JCTree visitPrimitiveType(PrimitiveTypeTree node, P p) {
 361         JCPrimitiveTypeTree t = (JCPrimitiveTypeTree) node;
 362         return M.at(t.pos).TypeIdent(t.typetag);
 363     }
 364 
 365     public JCTree visitTypeParameter(TypeParameterTree node, P p) {
 366         JCTypeParameter t = (JCTypeParameter) node;
 367         List<JCExpression> bounds = copy(t.bounds, p);
 368         return M.at(t.pos).TypeParameter(t.name, bounds);
 369     }
 370 
 371     public JCTree visitInstanceOf(InstanceOfTree node, P p) {
 372         JCInstanceOf t = (JCInstanceOf) node;
 373         JCExpression expr = copy(t.expr, p);
 374         JCTree clazz = copy(t.clazz, p);
 375         return M.at(t.pos).TypeTest(expr, clazz);
 376     }
 377 
 378     public JCTree visitUnary(UnaryTree node, P p) {
 379         JCUnary t = (JCUnary) node;
 380         JCExpression arg = copy(t.arg, p);
 381         return M.at(t.pos).Unary(t.getTag(), arg);
 382     }
 383 
 384     public JCTree visitVariable(VariableTree node, P p) {
 385         JCVariableDecl t = (JCVariableDecl) node;
 386         JCModifiers mods = copy(t.mods, p);
 387         JCExpression vartype = copy(t.vartype, p);
 388         JCExpression init = copy(t.init, p);
 389         return M.at(t.pos).VarDef(mods, t.name, vartype, init);
 390     }
 391 
 392     public JCTree visitWhileLoop(WhileLoopTree node, P p) {
 393         JCWhileLoop t = (JCWhileLoop) node;
 394         JCStatement body = copy(t.body, p);
 395         JCExpression cond = copy(t.cond, p);
 396         return M.at(t.pos).WhileLoop(cond, body);
 397     }
 398 
 399     public JCTree visitWildcard(WildcardTree node, P p) {
 400         JCWildcard t = (JCWildcard) node;
 401         TypeBoundKind kind = M.at(t.kind.pos).TypeBoundKind(t.kind.kind);
 402         JCTree inner = copy(t.inner, p);
 403         return M.at(t.pos).Wildcard(kind, inner);
 404     }
 405 
 406     public JCTree visitOther(Tree node, P p) {
 407         JCTree tree = (JCTree) node;
 408         switch (tree.getTag()) {
 409             case JCTree.LETEXPR: {
 410                 LetExpr t = (LetExpr) node;
 411                 List<JCVariableDecl> defs = copy(t.defs, p);
 412                 JCTree expr = copy(t.expr, p);
 413                 return M.at(t.pos).LetExpr(defs, expr);
 414             }
 415             default:
 416                 throw new AssertionError("unknown tree tag: " + tree.getTag());
 417         }
 418     }
 419 
 420 }