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