Mercurial > hg > graal-jvmci-8
comparison graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTreeBuilder.java @ 16759:23415229349b
Truffle-DSL: new package structure.
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Mon, 11 Aug 2014 15:57:14 +0200 |
parents | graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTreeBuilder.java@55fd5be68a52 |
children | 62cfffca9be2 |
comparison
equal
deleted
inserted
replaced
16758:c5f8eeb3cbc8 | 16759:23415229349b |
---|---|
1 /* | |
2 * Copyright (c) 2012, 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. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
20 * or visit www.oracle.com if you need additional information or have any | |
21 * questions. | |
22 */ | |
23 package com.oracle.truffle.dsl.processor.java.model; | |
24 | |
25 import static com.oracle.truffle.dsl.processor.java.model.CodeTreeKind.*; | |
26 | |
27 import java.util.*; | |
28 | |
29 import javax.lang.model.element.*; | |
30 import javax.lang.model.type.*; | |
31 | |
32 import com.oracle.truffle.dsl.processor.java.*; | |
33 | |
34 public class CodeTreeBuilder { | |
35 | |
36 private final CodeTreeBuilder parent; | |
37 | |
38 private BuilderCodeTree currentElement; | |
39 private final BuilderCodeTree root; | |
40 | |
41 private int treeCount; | |
42 | |
43 public CodeTreeBuilder(CodeTreeBuilder parent) { | |
44 this.root = new BuilderCodeTree(GROUP, null, null); | |
45 this.currentElement = root; | |
46 this.parent = parent; | |
47 } | |
48 | |
49 @Override | |
50 public String toString() { | |
51 return root.toString(); | |
52 } | |
53 | |
54 public int getTreeCount() { | |
55 return treeCount; | |
56 } | |
57 | |
58 public boolean isEmpty() { | |
59 return treeCount == 0; | |
60 } | |
61 | |
62 public CodeTreeBuilder statement(String statement) { | |
63 return startStatement().string(statement).end(); | |
64 } | |
65 | |
66 public CodeTreeBuilder statement(CodeTree statement) { | |
67 return startStatement().tree(statement).end(); | |
68 } | |
69 | |
70 public static CodeTreeBuilder createBuilder() { | |
71 return new CodeTreeBuilder(null); | |
72 } | |
73 | |
74 public static CodeTree singleString(String s) { | |
75 return new CodeTreeBuilder(null).string(s).getTree(); | |
76 } | |
77 | |
78 public static CodeTree singleType(TypeMirror s) { | |
79 return new CodeTreeBuilder(null).type(s).getTree(); | |
80 } | |
81 | |
82 private CodeTreeBuilder push(CodeTreeKind kind) { | |
83 return push(new BuilderCodeTree(kind, null, null)); | |
84 } | |
85 | |
86 private CodeTreeBuilder push(String string) { | |
87 return push(new BuilderCodeTree(CodeTreeKind.STRING, null, string)); | |
88 } | |
89 | |
90 private CodeTreeBuilder push(TypeMirror type) { | |
91 return push(new BuilderCodeTree(CodeTreeKind.TYPE, type, null)); | |
92 } | |
93 | |
94 private CodeTreeBuilder push(CodeTreeKind kind, TypeMirror type, String string) { | |
95 return push(new BuilderCodeTree(kind, type, string)); | |
96 } | |
97 | |
98 private CodeTreeBuilder push(BuilderCodeTree tree) { | |
99 if (currentElement != null) { | |
100 if (!removeLastIfEnqueued(tree)) { | |
101 return this; | |
102 } | |
103 currentElement.add(tree); | |
104 } | |
105 switch (tree.getCodeKind()) { | |
106 case COMMA_GROUP: | |
107 case GROUP: | |
108 case INDENT: | |
109 currentElement = tree; | |
110 break; | |
111 } | |
112 treeCount++; | |
113 return this; | |
114 } | |
115 | |
116 private boolean removeLastIfEnqueued(BuilderCodeTree tree) { | |
117 if (tree.getCodeKind() == REMOVE_LAST) { | |
118 return !clearLastRec(tree.removeLast, currentElement.getEnclosedElements()); | |
119 } | |
120 List<CodeTree> childTree = tree.getEnclosedElements(); | |
121 if (!childTree.isEmpty()) { | |
122 CodeTree last = childTree.get(0); | |
123 if (last instanceof BuilderCodeTree) { | |
124 if (!removeLastIfEnqueued((BuilderCodeTree) last)) { | |
125 childTree.remove(0); | |
126 } | |
127 } | |
128 } | |
129 return true; | |
130 } | |
131 | |
132 private void clearLast(CodeTreeKind kind) { | |
133 if (clearLastRec(kind, currentElement.getEnclosedElements())) { | |
134 treeCount--; | |
135 } else { | |
136 // delay clearing the last | |
137 BuilderCodeTree tree = new BuilderCodeTree(REMOVE_LAST, null, null); | |
138 tree.removeLast = kind; | |
139 push(tree); | |
140 } | |
141 } | |
142 | |
143 public CodeTreeBuilder startStatement() { | |
144 startGroup(); | |
145 registerCallBack(new EndCallback() { | |
146 | |
147 @Override | |
148 public void beforeEnd() { | |
149 string(";").newLine(); | |
150 } | |
151 | |
152 @Override | |
153 public void afterEnd() { | |
154 } | |
155 }); | |
156 return this; | |
157 } | |
158 | |
159 public CodeTreeBuilder startGroup() { | |
160 return push(CodeTreeKind.GROUP); | |
161 } | |
162 | |
163 public CodeTreeBuilder startCommaGroup() { | |
164 return push(CodeTreeKind.COMMA_GROUP); | |
165 } | |
166 | |
167 public CodeTreeBuilder startCall(String callSite) { | |
168 return startCall((CodeTree) null, callSite); | |
169 } | |
170 | |
171 public CodeTreeBuilder startCall(String receiver, String callSite) { | |
172 return startCall(singleString(receiver), callSite); | |
173 } | |
174 | |
175 public CodeTreeBuilder startCall(CodeTree receiver, String callSite) { | |
176 if (receiver == null) { | |
177 return startGroup().string(callSite).startParanthesesCommaGroup().endAfter(); | |
178 } else { | |
179 return startGroup().tree(receiver).string(".").string(callSite).startParanthesesCommaGroup().endAfter(); | |
180 } | |
181 } | |
182 | |
183 public CodeTreeBuilder startStaticCall(TypeMirror type, String methodName) { | |
184 return startGroup().push(CodeTreeKind.STATIC_METHOD_REFERENCE, type, methodName).startParanthesesCommaGroup().endAfter(); | |
185 } | |
186 | |
187 public CodeTreeBuilder startStaticCall(ExecutableElement method) { | |
188 return startStaticCall(ElementUtils.findNearestEnclosingType(method).asType(), method.getSimpleName().toString()); | |
189 } | |
190 | |
191 public CodeTreeBuilder staticReference(TypeMirror type, String fieldName) { | |
192 return push(CodeTreeKind.STATIC_FIELD_REFERENCE, type, fieldName); | |
193 } | |
194 | |
195 private CodeTreeBuilder endAndWhitespaceAfter() { | |
196 registerCallBack(new EndCallback() { | |
197 | |
198 @Override | |
199 public void beforeEnd() { | |
200 } | |
201 | |
202 @Override | |
203 public void afterEnd() { | |
204 string(" "); | |
205 end(); | |
206 } | |
207 }); | |
208 return this; | |
209 } | |
210 | |
211 private CodeTreeBuilder endAfter() { | |
212 registerCallBack(new EndCallback() { | |
213 | |
214 @Override | |
215 public void beforeEnd() { | |
216 } | |
217 | |
218 @Override | |
219 public void afterEnd() { | |
220 end(); | |
221 } | |
222 }); | |
223 return this; | |
224 } | |
225 | |
226 private CodeTreeBuilder startParanthesesCommaGroup() { | |
227 startGroup(); | |
228 string("(").startCommaGroup(); | |
229 registerCallBack(new EndCallback() { | |
230 | |
231 @Override | |
232 public void beforeEnd() { | |
233 } | |
234 | |
235 @Override | |
236 public void afterEnd() { | |
237 string(")"); | |
238 } | |
239 }); | |
240 endAfter(); | |
241 return this; | |
242 } | |
243 | |
244 private CodeTreeBuilder startCurlyBracesCommaGroup() { | |
245 startGroup(); | |
246 string("{").startCommaGroup(); | |
247 registerCallBack(new EndCallback() { | |
248 | |
249 @Override | |
250 public void beforeEnd() { | |
251 } | |
252 | |
253 @Override | |
254 public void afterEnd() { | |
255 string("}"); | |
256 } | |
257 }); | |
258 endAfter(); | |
259 return this; | |
260 } | |
261 | |
262 public CodeTreeBuilder startParantheses() { | |
263 startGroup(); | |
264 string("(").startGroup(); | |
265 registerCallBack(new EndCallback() { | |
266 | |
267 @Override | |
268 public void beforeEnd() { | |
269 } | |
270 | |
271 @Override | |
272 public void afterEnd() { | |
273 string(")"); | |
274 } | |
275 }); | |
276 endAfter(); | |
277 return this; | |
278 } | |
279 | |
280 public CodeTreeBuilder doubleQuote(String s) { | |
281 return startGroup().string("\"" + s + "\"").end(); | |
282 } | |
283 | |
284 public CodeTreeBuilder string(String chunk1) { | |
285 return push(chunk1); | |
286 } | |
287 | |
288 public CodeTreeBuilder string(String chunk1, String chunk2) { | |
289 return push(GROUP).string(chunk1).string(chunk2).end(); | |
290 } | |
291 | |
292 public CodeTreeBuilder string(String chunk1, String chunk2, String chunk3) { | |
293 return push(GROUP).string(chunk1).string(chunk2).string(chunk3).end(); | |
294 } | |
295 | |
296 public CodeTreeBuilder string(String chunk1, String chunk2, String chunk3, String chunk4) { | |
297 return push(GROUP).string(chunk1).string(chunk2).string(chunk3).string(chunk4).end(); | |
298 } | |
299 | |
300 public CodeTreeBuilder tree(CodeTree treeToAdd) { | |
301 if (treeToAdd instanceof BuilderCodeTree) { | |
302 return push((BuilderCodeTree) treeToAdd).end(); | |
303 } else { | |
304 BuilderCodeTree tree = new BuilderCodeTree(GROUP, null, null); | |
305 tree.add(treeToAdd); | |
306 return push(tree).end(); | |
307 } | |
308 } | |
309 | |
310 public CodeTreeBuilder string(String chunk1, String chunk2, String chunk3, String chunk4, String... chunks) { | |
311 push(GROUP).string(chunk1).string(chunk2).string(chunk3).string(chunk4); | |
312 for (int i = 0; i < chunks.length; i++) { | |
313 string(chunks[i]); | |
314 } | |
315 return end(); | |
316 } | |
317 | |
318 public CodeTreeBuilder dot() { | |
319 return string("."); | |
320 } | |
321 | |
322 public CodeTreeBuilder newLine() { | |
323 return push(NEW_LINE); | |
324 } | |
325 | |
326 public CodeTreeBuilder startWhile() { | |
327 return startGroup().string("while ").startParanthesesCommaGroup().endAndWhitespaceAfter().startGroup().endAfter(); | |
328 } | |
329 | |
330 public CodeTreeBuilder startDoBlock() { | |
331 return startGroup().string("do ").startBlock(); | |
332 } | |
333 | |
334 public CodeTreeBuilder startDoWhile() { | |
335 clearLast(CodeTreeKind.NEW_LINE); | |
336 return startStatement().string(" while ").startParanthesesCommaGroup().endAfter().startGroup().endAfter(); | |
337 } | |
338 | |
339 public CodeTreeBuilder startIf() { | |
340 return startGroup().string("if ").startParanthesesCommaGroup().endAndWhitespaceAfter().startGroup().endAfter(); | |
341 } | |
342 | |
343 public CodeTreeBuilder startFor() { | |
344 return startGroup().string("for ").startParantheses().endAndWhitespaceAfter().startGroup().endAfter(); | |
345 } | |
346 | |
347 public boolean startIf(boolean elseIf) { | |
348 if (elseIf) { | |
349 startElseIf(); | |
350 } else { | |
351 startIf(); | |
352 } | |
353 return true; | |
354 } | |
355 | |
356 public CodeTreeBuilder startElseIf() { | |
357 clearLast(CodeTreeKind.NEW_LINE); | |
358 return startGroup().string(" else if ").startParanthesesCommaGroup().endAndWhitespaceAfter().startGroup().endAfter(); | |
359 } | |
360 | |
361 public CodeTreeBuilder startElseBlock() { | |
362 clearLast(CodeTreeKind.NEW_LINE); | |
363 return startGroup().string(" else ").startBlock().endAfter(); | |
364 } | |
365 | |
366 private boolean clearLastRec(CodeTreeKind kind, List<CodeTree> children) { | |
367 for (int i = children.size() - 1; i >= 0; i--) { | |
368 CodeTree child = children.get(i); | |
369 if (child.getCodeKind() == kind) { | |
370 children.remove(children.get(i)); | |
371 return true; | |
372 } else { | |
373 if (clearLastRec(kind, child.getEnclosedElements())) { | |
374 return true; | |
375 } | |
376 } | |
377 } | |
378 return false; | |
379 } | |
380 | |
381 public CodeTreeBuilder startCase() { | |
382 startGroup().string("case "); | |
383 registerCallBack(new EndCallback() { | |
384 | |
385 @Override | |
386 public void beforeEnd() { | |
387 string(" :").newLine(); | |
388 } | |
389 | |
390 @Override | |
391 public void afterEnd() { | |
392 } | |
393 }); | |
394 return this; | |
395 } | |
396 | |
397 public CodeTreeBuilder caseDefault() { | |
398 return startGroup().string("default :").newLine().end(); | |
399 } | |
400 | |
401 public CodeTreeBuilder startSwitch() { | |
402 return startGroup().string("switch ").startParanthesesCommaGroup().endAndWhitespaceAfter(); | |
403 } | |
404 | |
405 public CodeTreeBuilder startReturn() { | |
406 ExecutableElement method = findMethod(); | |
407 if (method != null && ElementUtils.isVoid(method.getReturnType())) { | |
408 startGroup(); | |
409 registerCallBack(new EndCallback() { | |
410 | |
411 @Override | |
412 public void beforeEnd() { | |
413 string(";").newLine(); // complete statement to execute | |
414 } | |
415 | |
416 @Override | |
417 public void afterEnd() { | |
418 string("return").string(";").newLine(); // emit a return; | |
419 } | |
420 }); | |
421 return this; | |
422 } else { | |
423 return startStatement().string("return "); | |
424 } | |
425 } | |
426 | |
427 public CodeTreeBuilder startAssert() { | |
428 return startStatement().string("assert "); | |
429 } | |
430 | |
431 public CodeTreeBuilder startNewArray(ArrayType arrayType, CodeTree size) { | |
432 startGroup().string("new ").type(arrayType.getComponentType()).string("["); | |
433 if (size != null) { | |
434 tree(size); | |
435 } | |
436 string("]"); | |
437 if (size == null) { | |
438 string(" "); | |
439 startCurlyBracesCommaGroup().endAfter(); | |
440 } | |
441 return this; | |
442 } | |
443 | |
444 public CodeTreeBuilder startNew(TypeMirror uninializedNodeClass) { | |
445 return startGroup().string("new ").type(uninializedNodeClass).startParanthesesCommaGroup().endAfter(); | |
446 } | |
447 | |
448 public CodeTreeBuilder startNew(String typeName) { | |
449 return startGroup().string("new ").string(typeName).startParanthesesCommaGroup().endAfter(); | |
450 } | |
451 | |
452 public CodeTreeBuilder startIndention() { | |
453 return push(CodeTreeKind.INDENT); | |
454 } | |
455 | |
456 public CodeTreeBuilder end(int times) { | |
457 for (int i = 0; i < times; i++) { | |
458 end(); | |
459 } | |
460 return this; | |
461 } | |
462 | |
463 public CodeTreeBuilder end() { | |
464 BuilderCodeTree tree = currentElement; | |
465 EndCallback callback = tree.getAtEndListener(); | |
466 if (callback != null) { | |
467 callback.beforeEnd(); | |
468 toParent(); | |
469 callback.afterEnd(); | |
470 } else { | |
471 toParent(); | |
472 } | |
473 return this; | |
474 } | |
475 | |
476 private void toParent() { | |
477 Element parentElement = currentElement.getEnclosingElement(); | |
478 if (currentElement != root) { | |
479 this.currentElement = (BuilderCodeTree) parentElement; | |
480 } else { | |
481 this.currentElement = root; | |
482 } | |
483 } | |
484 | |
485 public CodeTreeBuilder startBlock() { | |
486 startGroup(); | |
487 string("{").newLine().startIndention(); | |
488 registerCallBack(new EndCallback() { | |
489 | |
490 @Override | |
491 public void beforeEnd() { | |
492 } | |
493 | |
494 @Override | |
495 public void afterEnd() { | |
496 string("}").newLine(); | |
497 } | |
498 }); | |
499 endAfter(); | |
500 return this; | |
501 } | |
502 | |
503 private void registerCallBack(EndCallback callback) { | |
504 currentElement.registerAtEnd(callback); | |
505 } | |
506 | |
507 public CodeTreeBuilder defaultDeclaration(TypeMirror type, String name) { | |
508 if (!ElementUtils.isVoid(type)) { | |
509 startStatement(); | |
510 type(type); | |
511 string(" "); | |
512 string(name); | |
513 string(" = "); | |
514 defaultValue(type); | |
515 end(); // statement | |
516 } | |
517 return this; | |
518 } | |
519 | |
520 public CodeTreeBuilder declaration(TypeMirror type, String name, String init) { | |
521 return declaration(type, name, singleString(init)); | |
522 } | |
523 | |
524 public CodeTreeBuilder declaration(String type, String name, CodeTree init) { | |
525 startStatement(); | |
526 string(type); | |
527 string(" "); | |
528 string(name); | |
529 if (init != null) { | |
530 string(" = "); | |
531 tree(init); | |
532 } | |
533 end(); // statement | |
534 return this; | |
535 } | |
536 | |
537 public CodeTreeBuilder declaration(String type, String name, String init) { | |
538 return declaration(type, name, singleString(init)); | |
539 } | |
540 | |
541 public CodeTreeBuilder declaration(TypeMirror type, String name, CodeTree init) { | |
542 if (ElementUtils.isVoid(type)) { | |
543 startStatement(); | |
544 tree(init); | |
545 end(); | |
546 } else { | |
547 startStatement(); | |
548 type(type); | |
549 string(" "); | |
550 string(name); | |
551 if (init != null) { | |
552 string(" = "); | |
553 tree(init); | |
554 } | |
555 end(); // statement | |
556 } | |
557 return this; | |
558 } | |
559 | |
560 public CodeTreeBuilder declaration(TypeMirror type, String name, CodeTreeBuilder init) { | |
561 if (init == this) { | |
562 throw new IllegalArgumentException("Recursive builder usage."); | |
563 } | |
564 return declaration(type, name, init.getTree()); | |
565 } | |
566 | |
567 public CodeTreeBuilder declaration(String type, String name, CodeTreeBuilder init) { | |
568 if (init == this) { | |
569 throw new IllegalArgumentException("Recursive builder usage."); | |
570 } | |
571 return declaration(type, name, init.getTree()); | |
572 } | |
573 | |
574 public CodeTreeBuilder declaration(TypeMirror type, String name) { | |
575 return declaration(type, name, (CodeTree) null); | |
576 } | |
577 | |
578 public CodeTreeBuilder create() { | |
579 return new CodeTreeBuilder(this); | |
580 } | |
581 | |
582 public CodeTreeBuilder type(TypeMirror type) { | |
583 return push(type); | |
584 } | |
585 | |
586 public CodeTreeBuilder typeLiteral(TypeMirror type) { | |
587 return startGroup().type(type).string(".class").end(); | |
588 } | |
589 | |
590 private void assertRoot() { | |
591 if (currentElement != root) { | |
592 throw new IllegalStateException("CodeTreeBuilder was not ended properly."); | |
593 } | |
594 } | |
595 | |
596 public CodeTreeBuilder startCaseBlock() { | |
597 return startIndention(); | |
598 } | |
599 | |
600 public CodeTreeBuilder startThrow() { | |
601 return startStatement().string("throw "); | |
602 } | |
603 | |
604 public CodeTree getTree() { | |
605 assertRoot(); | |
606 return root; | |
607 } | |
608 | |
609 public CodeTree getRoot() { | |
610 return root; | |
611 } | |
612 | |
613 public CodeTreeBuilder cast(String baseClassName) { | |
614 string("(").string(baseClassName).string(") "); | |
615 return this; | |
616 } | |
617 | |
618 public CodeTreeBuilder cast(TypeMirror type, CodeTree content) { | |
619 if (ElementUtils.isVoid(type)) { | |
620 tree(content); | |
621 return this; | |
622 } else if (type.getKind() == TypeKind.DECLARED && ElementUtils.getQualifiedName(type).equals("java.lang.Object")) { | |
623 tree(content); | |
624 return this; | |
625 } else { | |
626 return startGroup().string("(").type(type).string(")").string(" ").tree(content).end(); | |
627 } | |
628 } | |
629 | |
630 public CodeTreeBuilder startSuperCall() { | |
631 return string("super").startParanthesesCommaGroup(); | |
632 } | |
633 | |
634 public CodeTreeBuilder returnFalse() { | |
635 return startReturn().string("false").end(); | |
636 } | |
637 | |
638 public CodeTreeBuilder returnStatement() { | |
639 return statement("return"); | |
640 } | |
641 | |
642 public ExecutableElement findMethod() { | |
643 Element element = currentElement; | |
644 while (element != null && (element.getKind() != ElementKind.METHOD && (element.getKind() != ElementKind.CONSTRUCTOR))) { | |
645 element = element.getEnclosingElement(); | |
646 } | |
647 ExecutableElement found = element != null ? (ExecutableElement) element : null; | |
648 if (found == null && parent != null) { | |
649 found = parent.findMethod(); | |
650 } | |
651 return found; | |
652 } | |
653 | |
654 public CodeTreeBuilder returnNull() { | |
655 return startReturn().string("null").end(); | |
656 } | |
657 | |
658 public CodeTreeBuilder returnTrue() { | |
659 return startReturn().string("true").end(); | |
660 } | |
661 | |
662 public CodeTreeBuilder instanceOf(CodeTree var, CodeTree type) { | |
663 tree(var).string(" instanceof ").tree(type); | |
664 return this; | |
665 } | |
666 | |
667 public CodeTreeBuilder instanceOf(String var, String type) { | |
668 return instanceOf(singleString(var), singleString(type)); | |
669 } | |
670 | |
671 public CodeTreeBuilder instanceOf(String var, TypeMirror type) { | |
672 TypeElement element = ElementUtils.fromTypeMirror(type); | |
673 if (element == null) { | |
674 throw new IllegalArgumentException("Cannot call instanceof for a non supported type: " + type.getKind()); | |
675 } | |
676 return instanceOf(singleString(var), singleType(type)); | |
677 } | |
678 | |
679 public CodeTreeBuilder defaultValue(TypeMirror mirror) { | |
680 switch (mirror.getKind()) { | |
681 case VOID: | |
682 return string(""); | |
683 case ARRAY: | |
684 case DECLARED: | |
685 case PACKAGE: | |
686 case NULL: | |
687 return string("null"); | |
688 case BOOLEAN: | |
689 return string("false"); | |
690 case BYTE: | |
691 return string("(byte) 0"); | |
692 case CHAR: | |
693 return string("(char) 0"); | |
694 case DOUBLE: | |
695 return string("0.0D"); | |
696 case LONG: | |
697 return string("0L"); | |
698 case INT: | |
699 return string("0"); | |
700 case FLOAT: | |
701 return string("0.0F"); | |
702 case SHORT: | |
703 return string("(short) 0"); | |
704 default: | |
705 throw new AssertionError(); | |
706 } | |
707 } | |
708 | |
709 public CodeTreeBuilder assertFalse() { | |
710 return startAssert().string("false").end(); | |
711 } | |
712 | |
713 public CodeTreeBuilder breakStatement() { | |
714 return statement("break"); | |
715 } | |
716 | |
717 public CodeTreeBuilder isNull() { | |
718 return string(" == null"); | |
719 } | |
720 | |
721 public CodeTreeBuilder isNotNull() { | |
722 return string(" != null"); | |
723 } | |
724 | |
725 public CodeTreeBuilder is(CodeTree tree) { | |
726 return string(" == ").tree(tree); | |
727 } | |
728 | |
729 public CodeTreeBuilder startTryBlock() { | |
730 return string("try ").startBlock(); | |
731 } | |
732 | |
733 public CodeTreeBuilder startCatchBlock(TypeMirror exceptionType, String localVarName) { | |
734 clearLast(CodeTreeKind.NEW_LINE); | |
735 string(" catch (").type(exceptionType).string(" ").string(localVarName).string(") "); | |
736 return startBlock(); | |
737 } | |
738 | |
739 public CodeTreeBuilder startFinallyBlock() { | |
740 clearLast(CodeTreeKind.NEW_LINE); | |
741 string(" finally "); | |
742 return startBlock(); | |
743 } | |
744 | |
745 public CodeTreeBuilder nullLiteral() { | |
746 return string("null"); | |
747 } | |
748 | |
749 private static class BuilderCodeTree extends CodeTree { | |
750 | |
751 private EndCallback atEndListener; | |
752 private CodeTreeKind removeLast; | |
753 | |
754 public BuilderCodeTree(CodeTreeKind kind, TypeMirror type, String string) { | |
755 super(kind, type, string); | |
756 } | |
757 | |
758 public void registerAtEnd(EndCallback atEnd) { | |
759 if (this.atEndListener != null) { | |
760 this.atEndListener = new CompoundCallback(this.atEndListener, atEnd); | |
761 } else { | |
762 this.atEndListener = atEnd; | |
763 } | |
764 } | |
765 | |
766 public EndCallback getAtEndListener() { | |
767 return atEndListener; | |
768 } | |
769 | |
770 @Override | |
771 public String toString() { | |
772 final StringBuilder b = new StringBuilder(); | |
773 acceptCodeElementScanner(new Printer(b), null); | |
774 return b.toString(); | |
775 } | |
776 | |
777 private static class CompoundCallback implements EndCallback { | |
778 | |
779 private final EndCallback callback1; | |
780 private final EndCallback callback2; | |
781 | |
782 public CompoundCallback(EndCallback callback1, EndCallback callback2) { | |
783 this.callback1 = callback1; | |
784 this.callback2 = callback2; | |
785 } | |
786 | |
787 @Override | |
788 public void afterEnd() { | |
789 callback1.afterEnd(); | |
790 callback2.afterEnd(); | |
791 } | |
792 | |
793 @Override | |
794 public void beforeEnd() { | |
795 callback1.beforeEnd(); | |
796 callback1.beforeEnd(); | |
797 } | |
798 } | |
799 | |
800 } | |
801 | |
802 private interface EndCallback { | |
803 | |
804 void beforeEnd(); | |
805 | |
806 void afterEnd(); | |
807 } | |
808 | |
809 private static class Printer extends CodeElementScanner<Void, Void> { | |
810 | |
811 private int indent; | |
812 private boolean newLine; | |
813 private final String ln = "\n"; | |
814 | |
815 private final StringBuilder b; | |
816 | |
817 Printer(StringBuilder b) { | |
818 this.b = b; | |
819 } | |
820 | |
821 @Override | |
822 public void visitTree(CodeTree e, Void p) { | |
823 switch (e.getCodeKind()) { | |
824 case COMMA_GROUP: | |
825 List<CodeTree> children = e.getEnclosedElements(); | |
826 for (int i = 0; i < children.size(); i++) { | |
827 children.get(i).acceptCodeElementScanner(this, p); | |
828 if (i < e.getEnclosedElements().size() - 1) { | |
829 b.append(", "); | |
830 } | |
831 } | |
832 break; | |
833 case GROUP: | |
834 super.visitTree(e, p); | |
835 break; | |
836 case INDENT: | |
837 indent(); | |
838 super.visitTree(e, p); | |
839 dedent(); | |
840 break; | |
841 case NEW_LINE: | |
842 writeLn(); | |
843 break; | |
844 case STRING: | |
845 if (e.getString() != null) { | |
846 write(e.getString()); | |
847 } else { | |
848 write("null"); | |
849 } | |
850 break; | |
851 case TYPE: | |
852 write(ElementUtils.getSimpleName(e.getType())); | |
853 break; | |
854 default: | |
855 assert false; | |
856 return; | |
857 } | |
858 } | |
859 | |
860 private void indent() { | |
861 indent++; | |
862 } | |
863 | |
864 private void dedent() { | |
865 indent--; | |
866 } | |
867 | |
868 private void writeLn() { | |
869 write(ln); | |
870 newLine = true; | |
871 } | |
872 | |
873 private void write(String m) { | |
874 if (newLine && m != ln) { | |
875 writeIndent(); | |
876 newLine = false; | |
877 } | |
878 b.append(m); | |
879 } | |
880 | |
881 private void writeIndent() { | |
882 for (int i = 0; i < indent; i++) { | |
883 b.append(" "); | |
884 } | |
885 } | |
886 } | |
887 | |
888 } |