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 | } |