| 1 | /* | 
| 2 |  * Copyright 1999-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.tools.javac.code.*; | 
| 29 | import com.sun.tools.javac.code.Symbol.*; | 
| 30 | import com.sun.tools.javac.code.Type.*; | 
| 31 | import com.sun.tools.javac.util.*; | 
| 32 | import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; | 
| 33 |   | 
| 34 | import com.sun.tools.javac.tree.JCTree.*; | 
| 35 |   | 
| 36 | import static com.sun.tools.javac.code.Flags.*; | 
| 37 | import static com.sun.tools.javac.code.Kinds.*; | 
| 38 | import static com.sun.tools.javac.code.TypeTags.*; | 
| 39 |   | 
| 40 | /** Factory class for trees. | 
| 41 |  * | 
| 42 |  *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If | 
| 43 |  *  you write code that depends on this, you do so at your own risk. | 
| 44 |  *  This code and its internal interfaces are subject to change or | 
| 45 |  *  deletion without notice.</b> | 
| 46 |  */ | 
| 47 | public class TreeMaker implements JCTree.Factory { | 
| 48 |   | 
| 49 |     /** The context key for the tree factory. */ | 
| 50 |     protected static final Context.Key<TreeMaker> treeMakerKey = | 
| 51 |         new Context.Key<TreeMaker>(); | 
| 52 |   | 
| 53 |     /** Get the TreeMaker instance. */ | 
| 54 |     public static TreeMaker instance(Context context) { | 
| 55 |         TreeMaker instance = context.get(treeMakerKey); | 
| 56 |         if (instance == null) | 
| 57 |             instance = new TreeMaker(context); | 
| 58 |         return instance; | 
| 59 |     } | 
| 60 |   | 
| 61 |     /** The position at which subsequent trees will be created. | 
| 62 |      */ | 
| 63 |     public int pos = Position.NOPOS; | 
| 64 |   | 
| 65 |     /** The toplevel tree to which created trees belong. | 
| 66 |      */ | 
| 67 |     public JCCompilationUnit toplevel; | 
| 68 |   | 
| 69 |     /** The current name table. */ | 
| 70 |     Name.Table names; | 
| 71 |   | 
| 72 |     Types types; | 
| 73 |   | 
| 74 |     /** The current symbol table. */ | 
| 75 |     Symtab syms; | 
| 76 |   | 
| 77 |     /** Create a tree maker with null toplevel and NOPOS as initial position. | 
| 78 |      */ | 
| 79 |     protected TreeMaker(Context context) { | 
| 80 |         context.put(treeMakerKey, this); | 
| 81 |         this.pos = Position.NOPOS; | 
| 82 |         this.toplevel = null; | 
| 83 |         this.names = Name.Table.instance(context); | 
| 84 |         this.syms = Symtab.instance(context); | 
| 85 |         this.types = Types.instance(context); | 
| 86 |     } | 
| 87 |   | 
| 88 |     /** Create a tree maker with a given toplevel and FIRSTPOS as initial position. | 
| 89 |      */ | 
| 90 |     TreeMaker(JCCompilationUnit toplevel, Name.Table names, Types types, Symtab syms) { | 
| 91 |         this.pos = Position.FIRSTPOS; | 
| 92 |         this.toplevel = toplevel; | 
| 93 |         this.names = names; | 
| 94 |         this.types = types; | 
| 95 |         this.syms = syms; | 
| 96 |     } | 
| 97 |   | 
| 98 |     /** Create a new tree maker for a given toplevel. | 
| 99 |      */ | 
| 100 |     public TreeMaker forToplevel(JCCompilationUnit toplevel) { | 
| 101 |         return new TreeMaker(toplevel, names, types, syms); | 
| 102 |     } | 
| 103 |   | 
| 104 |     /** Reassign current position. | 
| 105 |      */ | 
| 106 |     public TreeMaker at(int pos) { | 
| 107 |         this.pos = pos; | 
| 108 |         return this; | 
| 109 |     } | 
| 110 |   | 
| 111 |     /** Reassign current position. | 
| 112 |      */ | 
| 113 |     public TreeMaker at(DiagnosticPosition pos) { | 
| 114 |         this.pos = (pos == null ? Position.NOPOS : pos.getStartPosition()); | 
| 115 |         return this; | 
| 116 |     } | 
| 117 |   | 
| 118 |     /** | 
| 119 |      * Create given tree node at current position. | 
| 120 |      * @param defs a list of ClassDef, Import, and Skip | 
| 121 |      */ | 
| 122 |     public JCCompilationUnit TopLevel(List<JCAnnotation> packageAnnotations, | 
| 123 |                                       JCExpression pid, | 
| 124 |                                       List<JCTree> defs) { | 
| 125 |         assert packageAnnotations != null; | 
| 126 |         for (JCTree node : defs) | 
| 127 |             assert node instanceof JCClassDecl | 
| 128 |                 || node instanceof JCImport | 
| 129 |                 || node instanceof JCSkip | 
| 130 |                 || node instanceof JCErroneous | 
| 131 |                 || (node instanceof JCExpressionStatement | 
| 132 |                     && ((JCExpressionStatement)node).expr instanceof JCErroneous) | 
| 133 |                  : node.getClass().getSimpleName(); | 
| 134 |         JCCompilationUnit tree = new JCCompilationUnit(packageAnnotations, pid, defs, | 
| 135 |                                      null, null, null, null); | 
| 136 |         tree.pos = pos; | 
| 137 |         return tree; | 
| 138 |     } | 
| 139 |   | 
| 140 |     public JCImport Import(JCTree qualid, boolean importStatic) { | 
| 141 |         JCImport tree = new JCImport(qualid, importStatic); | 
| 142 |         tree.pos = pos; | 
| 143 |         return tree; | 
| 144 |     } | 
| 145 |   | 
| 146 |     public JCClassDecl ClassDef(JCModifiers mods, | 
| 147 |                                 Name name, | 
| 148 |                                 List<JCTypeParameter> typarams, | 
| 149 |                                 JCTree extending, | 
| 150 |                                 List<JCExpression> implementing, | 
| 151 |                                 List<JCTree> defs) | 
| 152 |     { | 
| 153 |         JCClassDecl tree = new JCClassDecl(mods, | 
| 154 |                                      name, | 
| 155 |                                      typarams, | 
| 156 |                                      extending, | 
| 157 |                                      implementing, | 
| 158 |                                      defs, | 
| 159 |                                      null); | 
| 160 |         tree.pos = pos; | 
| 161 |         return tree; | 
| 162 |     } | 
| 163 |   | 
| 164 |     public JCMethodDecl MethodDef(JCModifiers mods, | 
| 165 |                                Name name, | 
| 166 |                                JCExpression restype, | 
| 167 |                                List<JCTypeParameter> typarams, | 
| 168 |                                List<JCVariableDecl> params, | 
| 169 |                                List<JCExpression> thrown, | 
| 170 |                                JCBlock body, | 
| 171 |                                JCExpression defaultValue) | 
| 172 |     { | 
| 173 |         JCMethodDecl tree = new JCMethodDecl(mods, | 
| 174 |                                        name, | 
| 175 |                                        restype, | 
| 176 |                                        typarams, | 
| 177 |                                        params, | 
| 178 |                                        thrown, | 
| 179 |                                        body, | 
| 180 |                                        defaultValue, | 
| 181 |                                        null); | 
| 182 |         tree.pos = pos; | 
| 183 |         return tree; | 
| 184 |     } | 
| 185 |   | 
| 186 |     public JCVariableDecl VarDef(JCModifiers mods, Name name, JCExpression vartype, JCExpression init) { | 
| 187 |         JCVariableDecl tree = new JCVariableDecl(mods, name, vartype, init, null); | 
| 188 |         tree.pos = pos; | 
| 189 |         return tree; | 
| 190 |     } | 
| 191 |   | 
| 192 |     public JCSkip Skip() { | 
| 193 |         JCSkip tree = new JCSkip(); | 
| 194 |         tree.pos = pos; | 
| 195 |         return tree; | 
| 196 |     } | 
| 197 |   | 
| 198 |     public JCBlock Block(long flags, List<JCStatement> stats) { | 
| 199 |         JCBlock tree = new JCBlock(flags, stats); | 
| 200 |         tree.pos = pos; | 
| 201 |         return tree; | 
| 202 |     } | 
| 203 |   | 
| 204 |     public JCDoWhileLoop DoLoop(JCStatement body, JCExpression cond) { | 
| 205 |         JCDoWhileLoop tree = new JCDoWhileLoop(body, cond); | 
| 206 |         tree.pos = pos; | 
| 207 |         return tree; | 
| 208 |     } | 
| 209 |   | 
| 210 |     public JCWhileLoop WhileLoop(JCExpression cond, JCStatement body) { | 
| 211 |         JCWhileLoop tree = new JCWhileLoop(cond, body); | 
| 212 |         tree.pos = pos; | 
| 213 |         return tree; | 
| 214 |     } | 
| 215 |   | 
| 216 |     public JCForLoop ForLoop(List<JCStatement> init, | 
| 217 |                            JCExpression cond, | 
| 218 |                            List<JCExpressionStatement> step, | 
| 219 |                            JCStatement body) | 
| 220 |     { | 
| 221 |         JCForLoop tree = new JCForLoop(init, cond, step, body); | 
| 222 |         tree.pos = pos; | 
| 223 |         return tree; | 
| 224 |     } | 
| 225 |   | 
| 226 |     public JCEnhancedForLoop ForeachLoop(JCVariableDecl var, JCExpression expr, JCStatement body) { | 
| 227 |         JCEnhancedForLoop tree = new JCEnhancedForLoop(var, expr, body); | 
| 228 |         tree.pos = pos; | 
| 229 |         return tree; | 
| 230 |     } | 
| 231 |   | 
| 232 |     public JCLabeledStatement Labelled(Name label, JCStatement body) { | 
| 233 |         JCLabeledStatement tree = new JCLabeledStatement(label, body); | 
| 234 |         tree.pos = pos; | 
| 235 |         return tree; | 
| 236 |     } | 
| 237 |   | 
| 238 |     public JCSwitch Switch(JCExpression selector, List<JCCase> cases) { | 
| 239 |         JCSwitch tree = new JCSwitch(selector, cases); | 
| 240 |         tree.pos = pos; | 
| 241 |         return tree; | 
| 242 |     } | 
| 243 |   | 
| 244 |     public JCCase Case(JCExpression pat, List<JCStatement> stats) { | 
| 245 |         JCCase tree = new JCCase(pat, stats); | 
| 246 |         tree.pos = pos; | 
| 247 |         return tree; | 
| 248 |     } | 
| 249 |   | 
| 250 |     public JCSynchronized Synchronized(JCExpression lock, JCBlock body) { | 
| 251 |         JCSynchronized tree = new JCSynchronized(lock, body); | 
| 252 |         tree.pos = pos; | 
| 253 |         return tree; | 
| 254 |     } | 
| 255 |   | 
| 256 |     public JCTry Try(JCBlock body, List<JCCatch> catchers, JCBlock finalizer) { | 
| 257 |         JCTry tree = new JCTry(body, catchers, finalizer); | 
| 258 |         tree.pos = pos; | 
| 259 |         return tree; | 
| 260 |     } | 
| 261 |   | 
| 262 |     public JCCatch Catch(JCVariableDecl param, JCBlock body) { | 
| 263 |         JCCatch tree = new JCCatch(param, body); | 
| 264 |         tree.pos = pos; | 
| 265 |         return tree; | 
| 266 |     } | 
| 267 |   | 
| 268 |     public JCConditional Conditional(JCExpression cond, | 
| 269 |                                    JCExpression thenpart, | 
| 270 |                                    JCExpression elsepart) | 
| 271 |     { | 
| 272 |         JCConditional tree = new JCConditional(cond, thenpart, elsepart); | 
| 273 |         tree.pos = pos; | 
| 274 |         return tree; | 
| 275 |     } | 
| 276 |   | 
| 277 |     public JCIf If(JCExpression cond, JCStatement thenpart, JCStatement elsepart) { | 
| 278 |         JCIf tree = new JCIf(cond, thenpart, elsepart); | 
| 279 |         tree.pos = pos; | 
| 280 |         return tree; | 
| 281 |     } | 
| 282 |   | 
| 283 |     public JCExpressionStatement Exec(JCExpression expr) { | 
| 284 |         JCExpressionStatement tree = new JCExpressionStatement(expr); | 
| 285 |         tree.pos = pos; | 
| 286 |         return tree; | 
| 287 |     } | 
| 288 |   | 
| 289 |     public JCBreak Break(Name label) { | 
| 290 |         JCBreak tree = new JCBreak(label, null); | 
| 291 |         tree.pos = pos; | 
| 292 |         return tree; | 
| 293 |     } | 
| 294 |   | 
| 295 |     public JCContinue Continue(Name label) { | 
| 296 |         JCContinue tree = new JCContinue(label, null); | 
| 297 |         tree.pos = pos; | 
| 298 |         return tree; | 
| 299 |     } | 
| 300 |   | 
| 301 |     public JCReturn Return(JCExpression expr) { | 
| 302 |         JCReturn tree = new JCReturn(expr); | 
| 303 |         tree.pos = pos; | 
| 304 |         return tree; | 
| 305 |     } | 
| 306 |   | 
| 307 |     public JCThrow Throw(JCTree expr) { | 
| 308 |         JCThrow tree = new JCThrow(expr); | 
| 309 |         tree.pos = pos; | 
| 310 |         return tree; | 
| 311 |     } | 
| 312 |   | 
| 313 |     public JCAssert Assert(JCExpression cond, JCExpression detail) { | 
| 314 |         JCAssert tree = new JCAssert(cond, detail); | 
| 315 |         tree.pos = pos; | 
| 316 |         return tree; | 
| 317 |     } | 
| 318 |   | 
| 319 |     public JCMethodInvocation Apply(List<JCExpression> typeargs, | 
| 320 |                        JCExpression fn, | 
| 321 |                        List<JCExpression> args) | 
| 322 |     { | 
| 323 |         JCMethodInvocation tree = new JCMethodInvocation(typeargs, fn, args); | 
| 324 |         tree.pos = pos; | 
| 325 |         return tree; | 
| 326 |     } | 
| 327 |   | 
| 328 |     public JCNewClass NewClass(JCExpression encl, | 
| 329 |                              List<JCExpression> typeargs, | 
| 330 |                              JCExpression clazz, | 
| 331 |                              List<JCExpression> args, | 
| 332 |                              JCClassDecl def) | 
| 333 |     { | 
| 334 |         JCNewClass tree = new JCNewClass(encl, typeargs, clazz, args, def); | 
| 335 |         tree.pos = pos; | 
| 336 |         return tree; | 
| 337 |     } | 
| 338 |   | 
| 339 |     public JCNewArray NewArray(JCExpression elemtype, | 
| 340 |                              List<JCExpression> dims, | 
| 341 |                              List<JCExpression> elems) | 
| 342 |     { | 
| 343 |         JCNewArray tree = new JCNewArray(elemtype, dims, elems); | 
| 344 |         tree.pos = pos; | 
| 345 |         return tree; | 
| 346 |     } | 
| 347 |   | 
| 348 |     public JCParens Parens(JCExpression expr) { | 
| 349 |         JCParens tree = new JCParens(expr); | 
| 350 |         tree.pos = pos; | 
| 351 |         return tree; | 
| 352 |     } | 
| 353 |   | 
| 354 |     public JCAssign Assign(JCExpression lhs, JCExpression rhs) { | 
| 355 |         JCAssign tree = new JCAssign(lhs, rhs); | 
| 356 |         tree.pos = pos; | 
| 357 |         return tree; | 
| 358 |     } | 
| 359 |   | 
| 360 |     public JCAssignOp Assignop(int opcode, JCTree lhs, JCTree rhs) { | 
| 361 |         JCAssignOp tree = new JCAssignOp(opcode, lhs, rhs, null); | 
| 362 |         tree.pos = pos; | 
| 363 |         return tree; | 
| 364 |     } | 
| 365 |   | 
| 366 |     public JCUnary Unary(int opcode, JCExpression arg) { | 
| 367 |         JCUnary tree = new JCUnary(opcode, arg); | 
| 368 |         tree.pos = pos; | 
| 369 |         return tree; | 
| 370 |     } | 
| 371 |   | 
| 372 |     public JCBinary Binary(int opcode, JCExpression lhs, JCExpression rhs) { | 
| 373 |         JCBinary tree = new JCBinary(opcode, lhs, rhs, null); | 
| 374 |         tree.pos = pos; | 
| 375 |         return tree; | 
| 376 |     } | 
| 377 |   | 
| 378 |     public JCTypeCast TypeCast(JCTree clazz, JCExpression expr) { | 
| 379 |         JCTypeCast tree = new JCTypeCast(clazz, expr); | 
| 380 |         tree.pos = pos; | 
| 381 |         return tree; | 
| 382 |     } | 
| 383 |   | 
| 384 |     public JCInstanceOf TypeTest(JCExpression expr, JCTree clazz) { | 
| 385 |         JCInstanceOf tree = new JCInstanceOf(expr, clazz); | 
| 386 |         tree.pos = pos; | 
| 387 |         return tree; | 
| 388 |     } | 
| 389 |   | 
| 390 |     public JCArrayAccess Indexed(JCExpression indexed, JCExpression index) { | 
| 391 |         JCArrayAccess tree = new JCArrayAccess(indexed, index); | 
| 392 |         tree.pos = pos; | 
| 393 |         return tree; | 
| 394 |     } | 
| 395 |   | 
| 396 |     public JCFieldAccess Select(JCExpression selected, Name selector) { | 
| 397 |         JCFieldAccess tree = new JCFieldAccess(selected, selector, null); | 
| 398 |         tree.pos = pos; | 
| 399 |         return tree; | 
| 400 |     } | 
| 401 |   | 
| 402 |     public JCIdent Ident(Name name) { | 
| 403 |         JCIdent tree = new JCIdent(name, null); | 
| 404 |         tree.pos = pos; | 
| 405 |         return tree; | 
| 406 |     } | 
| 407 |   | 
| 408 |     public JCLiteral Literal(int tag, Object value) { | 
| 409 |         JCLiteral tree = new JCLiteral(tag, value); | 
| 410 |         tree.pos = pos; | 
| 411 |         return tree; | 
| 412 |     } | 
| 413 |   | 
| 414 |     public JCPrimitiveTypeTree TypeIdent(int typetag) { | 
| 415 |         JCPrimitiveTypeTree tree = new JCPrimitiveTypeTree(typetag); | 
| 416 |         tree.pos = pos; | 
| 417 |         return tree; | 
| 418 |     } | 
| 419 |   | 
| 420 |     public JCArrayTypeTree TypeArray(JCExpression elemtype) { | 
| 421 |         JCArrayTypeTree tree = new JCArrayTypeTree(elemtype); | 
| 422 |         tree.pos = pos; | 
| 423 |         return tree; | 
| 424 |     } | 
| 425 |   | 
| 426 |     public JCTypeApply TypeApply(JCExpression clazz, List<JCExpression> arguments) { | 
| 427 |         JCTypeApply tree = new JCTypeApply(clazz, arguments); | 
| 428 |         tree.pos = pos; | 
| 429 |         return tree; | 
| 430 |     } | 
| 431 |   | 
| 432 |     public JCTypeParameter TypeParameter(Name name, List<JCExpression> bounds) { | 
| 433 |         JCTypeParameter tree = new JCTypeParameter(name, bounds); | 
| 434 |         tree.pos = pos; | 
| 435 |         return tree; | 
| 436 |     } | 
| 437 |   | 
| 438 |     public JCWildcard Wildcard(TypeBoundKind kind, JCTree type) { | 
| 439 |         JCWildcard tree = new JCWildcard(kind, type); | 
| 440 |         tree.pos = pos; | 
| 441 |         return tree; | 
| 442 |     } | 
| 443 |   | 
| 444 |     public TypeBoundKind TypeBoundKind(BoundKind kind) { | 
| 445 |         TypeBoundKind tree = new TypeBoundKind(kind); | 
| 446 |         tree.pos = pos; | 
| 447 |         return tree; | 
| 448 |     } | 
| 449 |   | 
| 450 |     public JCAnnotation Annotation(JCTree annotationType, List<JCExpression> args) { | 
| 451 |         JCAnnotation tree = new JCAnnotation(annotationType, args); | 
| 452 |         tree.pos = pos; | 
| 453 |         return tree; | 
| 454 |     } | 
| 455 |   | 
| 456 |     public JCModifiers Modifiers(long flags, List<JCAnnotation> annotations) { | 
| 457 |         JCModifiers tree = new JCModifiers(flags, annotations); | 
| 458 |         boolean noFlags = (flags & Flags.StandardFlags) == 0; | 
| 459 |         tree.pos = (noFlags && annotations.isEmpty()) ? Position.NOPOS : pos; | 
| 460 |         return tree; | 
| 461 |     } | 
| 462 |   | 
| 463 |     public JCModifiers Modifiers(long flags) { | 
| 464 |         return Modifiers(flags, List.<JCAnnotation>nil()); | 
| 465 |     } | 
| 466 |   | 
| 467 |     public JCErroneous Erroneous() { | 
| 468 |         return Erroneous(List.<JCTree>nil()); | 
| 469 |     } | 
| 470 |   | 
| 471 |     public JCErroneous Erroneous(List<? extends JCTree> errs) { | 
| 472 |         JCErroneous tree = new JCErroneous(errs); | 
| 473 |         tree.pos = pos; | 
| 474 |         return tree; | 
| 475 |     } | 
| 476 |   | 
| 477 |     public LetExpr LetExpr(List<JCVariableDecl> defs, JCTree expr) { | 
| 478 |         LetExpr tree = new LetExpr(defs, expr); | 
| 479 |         tree.pos = pos; | 
| 480 |         return tree; | 
| 481 |     } | 
| 482 |   | 
| 483 | /* *************************************************************************** | 
| 484 |  * Derived building blocks. | 
| 485 |  ****************************************************************************/ | 
| 486 |   | 
| 487 |     public JCClassDecl AnonymousClassDef(JCModifiers mods, | 
| 488 |                                          List<JCTree> defs) | 
| 489 |     { | 
| 490 |         return ClassDef(mods, | 
| 491 |                         names.empty, | 
| 492 |                         List.<JCTypeParameter>nil(), | 
| 493 |                         null, | 
| 494 |                         List.<JCExpression>nil(), | 
| 495 |                         defs); | 
| 496 |     } | 
| 497 |   | 
| 498 |     public LetExpr LetExpr(JCVariableDecl def, JCTree expr) { | 
| 499 |         LetExpr tree = new LetExpr(List.of(def), expr); | 
| 500 |         tree.pos = pos; | 
| 501 |         return tree; | 
| 502 |     } | 
| 503 |   | 
| 504 |     /** Create an identifier from a symbol. | 
| 505 |      */ | 
| 506 |     public JCIdent Ident(Symbol sym) { | 
| 507 |         return (JCIdent)new JCIdent((sym.name != names.empty) | 
| 508 |                                 ? sym.name | 
| 509 |                                 : sym.flatName(), sym) | 
| 510 |             .setPos(pos) | 
| 511 |             .setType(sym.type); | 
| 512 |     } | 
| 513 |   | 
| 514 |     /** Create a selection node from a qualifier tree and a symbol. | 
| 515 |      *  @param base   The qualifier tree. | 
| 516 |      */ | 
| 517 |     public JCExpression Select(JCExpression base, Symbol sym) { | 
| 518 |         return new JCFieldAccess(base, sym.name, sym).setPos(pos).setType(sym.type); | 
| 519 |     } | 
| 520 |   | 
| 521 |     /** Create a qualified identifier from a symbol, adding enough qualifications | 
| 522 |      *  to make the reference unique. | 
| 523 |      */ | 
| 524 |     public JCExpression QualIdent(Symbol sym) { | 
| 525 |         return isUnqualifiable(sym) | 
| 526 |             ? Ident(sym) | 
| 527 |             : Select(QualIdent(sym.owner), sym); | 
| 528 |     } | 
| 529 |   | 
| 530 |     /** Create an identifier that refers to the variable declared in given variable | 
| 531 |      *  declaration. | 
| 532 |      */ | 
| 533 |     public JCExpression Ident(JCVariableDecl param) { | 
| 534 |         return Ident(param.sym); | 
| 535 |     } | 
| 536 |   | 
| 537 |     /** Create a list of identifiers referring to the variables declared | 
| 538 |      *  in given list of variable declarations. | 
| 539 |      */ | 
| 540 |     public List<JCExpression> Idents(List<JCVariableDecl> params) { | 
| 541 |         ListBuffer<JCExpression> ids = new ListBuffer<JCExpression>(); | 
| 542 |         for (List<JCVariableDecl> l = params; l.nonEmpty(); l = l.tail) | 
| 543 |             ids.append(Ident(l.head)); | 
| 544 |         return ids.toList(); | 
| 545 |     } | 
| 546 |   | 
| 547 |     /** Create a tree representing `this', given its type. | 
| 548 |      */ | 
| 549 |     public JCExpression This(Type t) { | 
| 550 |         return Ident(new VarSymbol(FINAL, names._this, t, t.tsym)); | 
| 551 |     } | 
| 552 |   | 
| 553 |     /** Create a tree representing a class literal. | 
| 554 |      */ | 
| 555 |     public JCExpression ClassLiteral(ClassSymbol clazz) { | 
| 556 |         return ClassLiteral(clazz.type); | 
| 557 |     } | 
| 558 |   | 
| 559 |     /** Create a tree representing a class literal. | 
| 560 |      */ | 
| 561 |     public JCExpression ClassLiteral(Type t) { | 
| 562 |         VarSymbol lit = new VarSymbol(STATIC | PUBLIC | FINAL, | 
| 563 |                                       names._class, | 
| 564 |                                       t, | 
| 565 |                                       t.tsym); | 
| 566 |         return Select(Type(t), lit); | 
| 567 |     } | 
| 568 |   | 
| 569 |     /** Create a tree representing `super', given its type and owner. | 
| 570 |      */ | 
| 571 |     public JCIdent Super(Type t, TypeSymbol owner) { | 
| 572 |         return Ident(new VarSymbol(FINAL, names._super, t, owner)); | 
| 573 |     } | 
| 574 |   | 
| 575 |     /** | 
| 576 |      * Create a method invocation from a method tree and a list of | 
| 577 |      * argument trees. | 
| 578 |      */ | 
| 579 |     public JCMethodInvocation App(JCExpression meth, List<JCExpression> args) { | 
| 580 |         return Apply(null, meth, args).setType(meth.type.getReturnType()); | 
| 581 |     } | 
| 582 |   | 
| 583 |     /** | 
| 584 |      * Create a no-arg method invocation from a method tree | 
| 585 |      */ | 
| 586 |     public JCMethodInvocation App(JCExpression meth) { | 
| 587 |         return Apply(null, meth, List.<JCExpression>nil()).setType(meth.type.getReturnType()); | 
| 588 |     } | 
| 589 |   | 
| 590 |     /** Create a method invocation from a method tree and a list of argument trees. | 
| 591 |      */ | 
| 592 |     public JCExpression Create(Symbol ctor, List<JCExpression> args) { | 
| 593 |         Type t = ctor.owner.erasure(types); | 
| 594 |         JCNewClass newclass = NewClass(null, null, Type(t), args, null); | 
| 595 |         newclass.constructor = ctor; | 
| 596 |         newclass.setType(t); | 
| 597 |         return newclass; | 
| 598 |     } | 
| 599 |   | 
| 600 |     /** Create a tree representing given type. | 
| 601 |      */ | 
| 602 |     public JCExpression Type(Type t) { | 
| 603 |         if (t == null) return null; | 
| 604 |         JCExpression tp; | 
| 605 |         switch (t.tag) { | 
| 606 |         case BYTE: case CHAR: case SHORT: case INT: case LONG: case FLOAT: | 
| 607 |         case DOUBLE: case BOOLEAN: case VOID: | 
| 608 |             tp = TypeIdent(t.tag); | 
| 609 |             break; | 
| 610 |         case TYPEVAR: | 
| 611 |             tp = Ident(t.tsym); | 
| 612 |             break; | 
| 613 |         case WILDCARD: { | 
| 614 |             WildcardType a = ((WildcardType) t); | 
| 615 |             tp = Wildcard(TypeBoundKind(a.kind), Type(a.type)); | 
| 616 |             break; | 
| 617 |         } | 
| 618 |         case CLASS: | 
| 619 |             Type outer = t.getEnclosingType(); | 
| 620 |             JCExpression clazz = outer.tag == CLASS && t.tsym.owner.kind == TYP | 
| 621 |                 ? Select(Type(outer), t.tsym) | 
| 622 |                 : QualIdent(t.tsym); | 
| 623 |             tp = t.getTypeArguments().isEmpty() | 
| 624 |                 ? clazz | 
| 625 |                 : TypeApply(clazz, Types(t.getTypeArguments())); | 
| 626 |             break; | 
| 627 |         case ARRAY: | 
| 628 |             tp = TypeArray(Type(types.elemtype(t))); | 
| 629 |             break; | 
| 630 |         case ERROR: | 
| 631 |             tp = TypeIdent(ERROR); | 
| 632 |             break; | 
| 633 |         default: | 
| 634 |             throw new AssertionError("unexpected type: " + t); | 
| 635 |         } | 
| 636 |         return tp.setType(t); | 
| 637 |     } | 
| 638 | //where | 
| 639 |         private JCExpression Selectors(JCExpression base, Symbol sym, Symbol limit) { | 
| 640 |             if (sym == limit) return base; | 
| 641 |             else return Select(Selectors(base, sym.owner, limit), sym); | 
| 642 |         } | 
| 643 |   | 
| 644 |     /** Create a list of trees representing given list of types. | 
| 645 |      */ | 
| 646 |     public List<JCExpression> Types(List<Type> ts) { | 
| 647 |         ListBuffer<JCExpression> types = new ListBuffer<JCExpression>(); | 
| 648 |         for (List<Type> l = ts; l.nonEmpty(); l = l.tail) | 
| 649 |             types.append(Type(l.head)); | 
| 650 |         return types.toList(); | 
| 651 |     } | 
| 652 |   | 
| 653 |     /** Create a variable definition from a variable symbol and an initializer | 
| 654 |      *  expression. | 
| 655 |      */ | 
| 656 |     public JCVariableDecl VarDef(VarSymbol v, JCExpression init) { | 
| 657 |         return (JCVariableDecl) | 
| 658 |             new JCVariableDecl( | 
| 659 |                 Modifiers(v.flags(), Annotations(v.getAnnotationMirrors())), | 
| 660 |                 v.name, | 
| 661 |                 Type(v.type), | 
| 662 |                 init, | 
| 663 |                 v).setPos(pos).setType(v.type); | 
| 664 |     } | 
| 665 |   | 
| 666 |     /** Create annotation trees from annotations. | 
| 667 |      */ | 
| 668 |     public List<JCAnnotation> Annotations(List<Attribute.Compound> attributes) { | 
| 669 |         if (attributes == null) return List.nil(); | 
| 670 |         ListBuffer<JCAnnotation> result = new ListBuffer<JCAnnotation>(); | 
| 671 |         for (List<Attribute.Compound> i = attributes; i.nonEmpty(); i=i.tail) { | 
| 672 |             Attribute a = i.head; | 
| 673 |             result.append(Annotation(a)); | 
| 674 |         } | 
| 675 |         return result.toList(); | 
| 676 |     } | 
| 677 |   | 
| 678 |     public JCLiteral Literal(Object value) { | 
| 679 |         JCLiteral result = null; | 
| 680 |         if (value instanceof String) { | 
| 681 |             result = Literal(CLASS, value). | 
| 682 |                 setType(syms.stringType.constType(value)); | 
| 683 |         } else if (value instanceof Integer) { | 
| 684 |             result = Literal(INT, value). | 
| 685 |                 setType(syms.intType.constType(value)); | 
| 686 |         } else if (value instanceof Long) { | 
| 687 |             result = Literal(LONG, value). | 
| 688 |                 setType(syms.longType.constType(value)); | 
| 689 |         } else if (value instanceof Byte) { | 
| 690 |             result = Literal(BYTE, value). | 
| 691 |                 setType(syms.byteType.constType(value)); | 
| 692 |         } else if (value instanceof Character) { | 
| 693 |             result = Literal(CHAR, value). | 
| 694 |                 setType(syms.charType.constType(value)); | 
| 695 |         } else if (value instanceof Double) { | 
| 696 |             result = Literal(DOUBLE, value). | 
| 697 |                 setType(syms.doubleType.constType(value)); | 
| 698 |         } else if (value instanceof Float) { | 
| 699 |             result = Literal(FLOAT, value). | 
| 700 |                 setType(syms.floatType.constType(value)); | 
| 701 |         } else if (value instanceof Short) { | 
| 702 |             result = Literal(SHORT, value). | 
| 703 |                 setType(syms.shortType.constType(value)); | 
| 704 |         } else { | 
| 705 |             throw new AssertionError(value); | 
| 706 |         } | 
| 707 |         return result; | 
| 708 |     } | 
| 709 |   | 
| 710 |     class AnnotationBuilder implements Attribute.Visitor { | 
| 711 |         JCExpression result = null; | 
| 712 |         public void visitConstant(Attribute.Constant v) { | 
| 713 |             result = Literal(v.value); | 
| 714 |         } | 
| 715 |         public void visitClass(Attribute.Class clazz) { | 
| 716 |             result = ClassLiteral(clazz.type).setType(syms.classType); | 
| 717 |         } | 
| 718 |         public void visitEnum(Attribute.Enum e) { | 
| 719 |             result = QualIdent(e.value); | 
| 720 |         } | 
| 721 |         public void visitError(Attribute.Error e) { | 
| 722 |             result = Erroneous(); | 
| 723 |         } | 
| 724 |         public void visitCompound(Attribute.Compound compound) { | 
| 725 |             result = visitCompoundInternal(compound); | 
| 726 |         } | 
| 727 |         public JCAnnotation visitCompoundInternal(Attribute.Compound compound) { | 
| 728 |             ListBuffer<JCExpression> args = new ListBuffer<JCExpression>(); | 
| 729 |             for (List<Pair<Symbol.MethodSymbol,Attribute>> values = compound.values; values.nonEmpty(); values=values.tail) { | 
| 730 |                 Pair<MethodSymbol,Attribute> pair = values.head; | 
| 731 |                 JCExpression valueTree = translate(pair.snd); | 
| 732 |                 args.append(Assign(Ident(pair.fst), valueTree).setType(valueTree.type)); | 
| 733 |             } | 
| 734 |             return Annotation(Type(compound.type), args.toList()); | 
| 735 |         } | 
| 736 |         public void visitArray(Attribute.Array array) { | 
| 737 |             ListBuffer<JCExpression> elems = new ListBuffer<JCExpression>(); | 
| 738 |             for (int i = 0; i < array.values.length; i++) | 
| 739 |                 elems.append(translate(array.values[i])); | 
| 740 |             result = NewArray(null, List.<JCExpression>nil(), elems.toList()).setType(array.type); | 
| 741 |         } | 
| 742 |         JCExpression translate(Attribute a) { | 
| 743 |             a.accept(this); | 
| 744 |             return result; | 
| 745 |         } | 
| 746 |         JCAnnotation translate(Attribute.Compound a) { | 
| 747 |             return visitCompoundInternal(a); | 
| 748 |         } | 
| 749 |     } | 
| 750 |     AnnotationBuilder annotationBuilder = new AnnotationBuilder(); | 
| 751 |   | 
| 752 |     /** Create an annotation tree from an attribute. | 
| 753 |      */ | 
| 754 |     public JCAnnotation Annotation(Attribute a) { | 
| 755 |         return annotationBuilder.translate((Attribute.Compound)a); | 
| 756 |     } | 
| 757 |   | 
| 758 |     /** Create a method definition from a method symbol and a method body. | 
| 759 |      */ | 
| 760 |     public JCMethodDecl MethodDef(MethodSymbol m, JCBlock body) { | 
| 761 |         return MethodDef(m, m.type, body); | 
| 762 |     } | 
| 763 |   | 
| 764 |     /** Create a method definition from a method symbol, method type | 
| 765 |      *  and a method body. | 
| 766 |      */ | 
| 767 |     public JCMethodDecl MethodDef(MethodSymbol m, Type mtype, JCBlock body) { | 
| 768 |         return (JCMethodDecl) | 
| 769 |             new JCMethodDecl( | 
| 770 |                 Modifiers(m.flags(), Annotations(m.getAnnotationMirrors())), | 
| 771 |                 m.name, | 
| 772 |                 Type(mtype.getReturnType()), | 
| 773 |                 TypeParams(mtype.getTypeArguments()), | 
| 774 |                 Params(mtype.getParameterTypes(), m), | 
| 775 |                 Types(mtype.getThrownTypes()), | 
| 776 |                 body, | 
| 777 |                 null, | 
| 778 |                 m).setPos(pos).setType(mtype); | 
| 779 |     } | 
| 780 |   | 
| 781 |     /** Create a type parameter tree from its name and type. | 
| 782 |      */ | 
| 783 |     public JCTypeParameter TypeParam(Name name, TypeVar tvar) { | 
| 784 |         return (JCTypeParameter) | 
| 785 |             TypeParameter(name, Types(types.getBounds(tvar))).setPos(pos).setType(tvar); | 
| 786 |     } | 
| 787 |   | 
| 788 |     /** Create a list of type parameter trees from a list of type variables. | 
| 789 |      */ | 
| 790 |     public List<JCTypeParameter> TypeParams(List<Type> typarams) { | 
| 791 |         ListBuffer<JCTypeParameter> tparams = new ListBuffer<JCTypeParameter>(); | 
| 792 |         int i = 0; | 
| 793 |         for (List<Type> l = typarams; l.nonEmpty(); l = l.tail) | 
| 794 |             tparams.append(TypeParam(l.head.tsym.name, (TypeVar)l.head)); | 
| 795 |         return tparams.toList(); | 
| 796 |     } | 
| 797 |   | 
| 798 |     /** Create a value parameter tree from its name, type, and owner. | 
| 799 |      */ | 
| 800 |     public JCVariableDecl Param(Name name, Type argtype, Symbol owner) { | 
| 801 |         return VarDef(new VarSymbol(0, name, argtype, owner), null); | 
| 802 |     } | 
| 803 |   | 
| 804 |     /** Create a a list of value parameter trees x0, ..., xn from a list of | 
| 805 |      *  their types and an their owner. | 
| 806 |      */ | 
| 807 |     public List<JCVariableDecl> Params(List<Type> argtypes, Symbol owner) { | 
| 808 |         ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>(); | 
| 809 |         MethodSymbol mth = (owner.kind == MTH) ? ((MethodSymbol)owner) : null; | 
| 810 |         if (mth != null && mth.params != null && argtypes.length() == mth.params.length()) { | 
| 811 |             for (VarSymbol param : ((MethodSymbol)owner).params) | 
| 812 |                 params.append(VarDef(param, null)); | 
| 813 |         } else { | 
| 814 |             int i = 0; | 
| 815 |             for (List<Type> l = argtypes; l.nonEmpty(); l = l.tail) | 
| 816 |                 params.append(Param(paramName(i++), l.head, owner)); | 
| 817 |         } | 
| 818 |         return params.toList(); | 
| 819 |     } | 
| 820 |   | 
| 821 |     /** Wrap a method invocation in an expression statement or return statement, | 
| 822 |      *  depending on whether the method invocation expression's type is void. | 
| 823 |      */ | 
| 824 |     public JCStatement Call(JCExpression apply) { | 
| 825 |         return apply.type.tag == VOID ? Exec(apply) : Return(apply); | 
| 826 |     } | 
| 827 |   | 
| 828 |     /** Construct an assignment from a variable symbol and a right hand side. | 
| 829 |      */ | 
| 830 |     public JCStatement Assignment(Symbol v, JCExpression rhs) { | 
| 831 |         return Exec(Assign(Ident(v), rhs).setType(v.type)); | 
| 832 |     } | 
| 833 |   | 
| 834 |     /** Construct an index expression from a variable and an expression. | 
| 835 |      */ | 
| 836 |     public JCArrayAccess Indexed(Symbol v, JCExpression index) { | 
| 837 |         JCArrayAccess tree = new JCArrayAccess(QualIdent(v), index); | 
| 838 |         tree.type = ((ArrayType)v.type).elemtype; | 
| 839 |         return tree; | 
| 840 |     } | 
| 841 |   | 
| 842 |     /** Make an attributed type cast expression. | 
| 843 |      */ | 
| 844 |     public JCTypeCast TypeCast(Type type, JCExpression expr) { | 
| 845 |         return (JCTypeCast)TypeCast(Type(type), expr).setType(type); | 
| 846 |     } | 
| 847 |   | 
| 848 | /* *************************************************************************** | 
| 849 |  * Helper methods. | 
| 850 |  ****************************************************************************/ | 
| 851 |   | 
| 852 |     /** Can given symbol be referred to in unqualified form? | 
| 853 |      */ | 
| 854 |     boolean isUnqualifiable(Symbol sym) { | 
| 855 |         if (sym.name == names.empty || | 
| 856 |             sym.owner == null || | 
| 857 |             sym.owner.kind == MTH || sym.owner.kind == VAR) { | 
| 858 |             return true; | 
| 859 |         } else if (sym.kind == TYP && toplevel != null) { | 
| 860 |             Scope.Entry e; | 
| 861 |             e = toplevel.namedImportScope.lookup(sym.name); | 
| 862 |             if (e.scope != null) { | 
| 863 |                 return | 
| 864 |                   e.sym == sym && | 
| 865 |                   e.next().scope == null; | 
| 866 |             } | 
| 867 |             e = toplevel.packge.members().lookup(sym.name); | 
| 868 |             if (e.scope != null) { | 
| 869 |                 return | 
| 870 |                   e.sym == sym && | 
| 871 |                   e.next().scope == null; | 
| 872 |             } | 
| 873 |             e = toplevel.starImportScope.lookup(sym.name); | 
| 874 |             if (e.scope != null) { | 
| 875 |                 return | 
| 876 |                   e.sym == sym && | 
| 877 |                   e.next().scope == null; | 
| 878 |             } | 
| 879 |         } | 
| 880 |         return false; | 
| 881 |     } | 
| 882 |   | 
| 883 |     /** The name of synthetic parameter number `i'. | 
| 884 |      */ | 
| 885 |     public Name paramName(int i)   { return names.fromString("x" + i); } | 
| 886 |   | 
| 887 |     /** The name of synthetic type parameter number `i'. | 
| 888 |      */ | 
| 889 |     public Name typaramName(int i) { return names.fromString("A" + i); } | 
| 890 | } |