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 }