001: /**
002: *
003: * Copyright 2005 Jeremy Rayner
004: *
005: * Licensed under the Apache License, Version 2.0 (the "License");
006: * you may not use this file except in compliance with the License.
007: * You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: **/package org.codehaus.groovy.antlr.treewalker;
018:
019: import java.io.PrintStream;
020:
021: import org.codehaus.groovy.antlr.GroovySourceAST;
022: import org.codehaus.groovy.antlr.parser.GroovyTokenTypes;
023:
024: /**
025: * An antlr AST visitor that prints a format suitable for viewing in http://freemind.sourceforge.net
026: *
027: * @author <a href="mailto:groovy@ross-rayner.com">Jeremy Rayner</a>
028: * @version $Revision: 4526 $
029: */
030:
031: public class MindMapPrinter extends VisitorAdapter {
032: private String[] tokenNames;
033: private PrintStream out;
034: private int depth;
035:
036: /**
037: * A visitor that prints a format suitable for viewing in http://freemind.sourceforge.net
038: * @param out where to print the mindmap file contents to
039: * @param tokenNames an array of token names from antlr
040: */
041:
042: public MindMapPrinter(PrintStream out, String[] tokenNames) {
043: this .tokenNames = tokenNames;
044: this .out = out;
045: }
046:
047: public void setUp() {
048: depth = 0;
049: out.println("<map version='0.7.1'><node TEXT='AST'>");
050: }
051:
052: public void visitDefault(GroovySourceAST t, int visit) {
053: if (visit == OPENING_VISIT) {
054: depth++;
055: String name = getName(t);
056: String colour = getColour(t);
057: String folded = getFolded(t);
058: out.print("<node TEXT='" + name + "' POSITION='right'"
059: + colour + folded + ">");
060: } else {
061: out.println("</node>");
062: depth--;
063: }
064: }
065:
066: public void tearDown() {
067: out.println("</node></map>");
068: }
069:
070: private String getFolded(GroovySourceAST t) {
071: if (depth > 2 && t.getNumberOfChildren() > 0) {
072: switch (t.getType()) {
073: case GroovyTokenTypes.EXPR:
074: case GroovyTokenTypes.METHOD_DEF:
075: case GroovyTokenTypes.VARIABLE_DEF:
076: return " FOLDED='true'";
077: }
078: }
079: if (t.getType() == GroovyTokenTypes.IMPORT) {
080: return " FOLDED='true'";
081: }
082: return "";
083: }
084:
085: private String getColour(GroovySourceAST t) {
086: String colour = "";
087: String black = " COLOR=\"#000000\"";
088: String cyan = " COLOR=\"#006699\"";
089: String blue = " COLOR=\"#17178B\"";
090: String green = " COLOR=\"#008000\"";
091: switch (t.getType()) {
092: case GroovyTokenTypes.ABSTRACT:
093: case GroovyTokenTypes.ANNOTATION:
094: case GroovyTokenTypes.ANNOTATIONS:
095: case GroovyTokenTypes.ANNOTATION_ARRAY_INIT:
096: case GroovyTokenTypes.ANNOTATION_DEF:
097: case GroovyTokenTypes.ANNOTATION_FIELD_DEF:
098: case GroovyTokenTypes.ANNOTATION_MEMBER_VALUE_PAIR:
099: case GroovyTokenTypes.ARRAY_DECLARATOR:
100: case GroovyTokenTypes.ASSIGN:
101: case GroovyTokenTypes.AT:
102: case GroovyTokenTypes.BAND:
103: case GroovyTokenTypes.BAND_ASSIGN:
104: case GroovyTokenTypes.BIG_SUFFIX:
105: case GroovyTokenTypes.BLOCK:
106: case GroovyTokenTypes.BNOT:
107: case GroovyTokenTypes.BOR:
108: case GroovyTokenTypes.BOR_ASSIGN:
109: case GroovyTokenTypes.BSR:
110: case GroovyTokenTypes.BSR_ASSIGN:
111: case GroovyTokenTypes.BXOR:
112: case GroovyTokenTypes.BXOR_ASSIGN:
113: case GroovyTokenTypes.CASE_GROUP:
114: case GroovyTokenTypes.CLOSABLE_BLOCK:
115: case GroovyTokenTypes.CLOSABLE_BLOCK_OP:
116: case GroovyTokenTypes.COLON:
117: case GroovyTokenTypes.COMMA:
118: case GroovyTokenTypes.COMPARE_TO:
119: case GroovyTokenTypes.CTOR_CALL:
120: case GroovyTokenTypes.CTOR_IDENT:
121: case GroovyTokenTypes.DEC:
122: case GroovyTokenTypes.DIGIT:
123: case GroovyTokenTypes.DIV:
124: case GroovyTokenTypes.DIV_ASSIGN:
125: case GroovyTokenTypes.DOLLAR:
126: case GroovyTokenTypes.DOT:
127: case GroovyTokenTypes.DYNAMIC_MEMBER:
128: case GroovyTokenTypes.ELIST:
129: case GroovyTokenTypes.EMPTY_STAT:
130: case GroovyTokenTypes.ENUM_CONSTANT_DEF:
131: case GroovyTokenTypes.ENUM_DEF:
132: case GroovyTokenTypes.EOF:
133: case GroovyTokenTypes.EQUAL:
134: case GroovyTokenTypes.ESC:
135: case GroovyTokenTypes.EXPONENT:
136: case GroovyTokenTypes.EXPR:
137: case GroovyTokenTypes.FINAL:
138: case GroovyTokenTypes.FLOAT_SUFFIX:
139: case GroovyTokenTypes.FOR_CONDITION:
140: case GroovyTokenTypes.FOR_EACH_CLAUSE:
141: case GroovyTokenTypes.FOR_INIT:
142: case GroovyTokenTypes.FOR_IN_ITERABLE:
143: case GroovyTokenTypes.FOR_ITERATOR:
144: case GroovyTokenTypes.GE:
145: case GroovyTokenTypes.GT:
146: case GroovyTokenTypes.HEX_DIGIT:
147: case GroovyTokenTypes.IMPLICIT_PARAMETERS:
148: case GroovyTokenTypes.INC:
149: case GroovyTokenTypes.INDEX_OP:
150: case GroovyTokenTypes.INSTANCE_INIT:
151: case GroovyTokenTypes.INTERFACE_DEF:
152: case GroovyTokenTypes.LABELED_ARG:
153: case GroovyTokenTypes.LABELED_STAT:
154: case GroovyTokenTypes.LAND:
155: case GroovyTokenTypes.LBRACK:
156: case GroovyTokenTypes.LCURLY:
157: case GroovyTokenTypes.LE:
158: case GroovyTokenTypes.LETTER:
159: case GroovyTokenTypes.LIST_CONSTRUCTOR:
160: case GroovyTokenTypes.LNOT:
161: case GroovyTokenTypes.LOR:
162: case GroovyTokenTypes.LPAREN:
163: case GroovyTokenTypes.LT:
164: case GroovyTokenTypes.MAP_CONSTRUCTOR:
165: case GroovyTokenTypes.MEMBER_POINTER:
166: case GroovyTokenTypes.METHOD_CALL:
167: case GroovyTokenTypes.METHOD_DEF:
168: case GroovyTokenTypes.MINUS:
169: case GroovyTokenTypes.MINUS_ASSIGN:
170: case GroovyTokenTypes.ML_COMMENT:
171: case GroovyTokenTypes.MOD:
172: case GroovyTokenTypes.MODIFIERS:
173: case GroovyTokenTypes.MOD_ASSIGN:
174: case GroovyTokenTypes.NLS:
175: case GroovyTokenTypes.NOT_EQUAL:
176: case GroovyTokenTypes.NULL_TREE_LOOKAHEAD:
177: case GroovyTokenTypes.NUM_BIG_DECIMAL:
178: case GroovyTokenTypes.NUM_BIG_INT:
179: case GroovyTokenTypes.NUM_DOUBLE:
180: case GroovyTokenTypes.NUM_FLOAT:
181: case GroovyTokenTypes.NUM_INT:
182: case GroovyTokenTypes.NUM_LONG:
183: case GroovyTokenTypes.OBJBLOCK:
184: case GroovyTokenTypes.ONE_NL:
185: case GroovyTokenTypes.OPTIONAL_DOT:
186: case GroovyTokenTypes.PARAMETERS:
187: case GroovyTokenTypes.PARAMETER_DEF:
188: case GroovyTokenTypes.PLUS:
189: case GroovyTokenTypes.PLUS_ASSIGN:
190: case GroovyTokenTypes.POST_DEC:
191: case GroovyTokenTypes.POST_INC:
192: case GroovyTokenTypes.QUESTION:
193: case GroovyTokenTypes.RANGE_EXCLUSIVE:
194: case GroovyTokenTypes.RANGE_INCLUSIVE:
195: case GroovyTokenTypes.RBRACK:
196: case GroovyTokenTypes.RCURLY:
197: case GroovyTokenTypes.REGEXP_CTOR_END:
198: case GroovyTokenTypes.REGEXP_SYMBOL:
199: case GroovyTokenTypes.REGEX_FIND:
200: case GroovyTokenTypes.REGEX_MATCH:
201: case GroovyTokenTypes.RPAREN:
202: case GroovyTokenTypes.SCOPE_ESCAPE:
203: case GroovyTokenTypes.SELECT_SLOT:
204: case GroovyTokenTypes.SEMI:
205: case GroovyTokenTypes.SH_COMMENT:
206: case GroovyTokenTypes.SL:
207: case GroovyTokenTypes.SLIST:
208: case GroovyTokenTypes.SL_ASSIGN:
209: case GroovyTokenTypes.SL_COMMENT:
210: case GroovyTokenTypes.SPREAD_ARG:
211: case GroovyTokenTypes.SPREAD_DOT:
212: case GroovyTokenTypes.SPREAD_MAP_ARG:
213: case GroovyTokenTypes.SR:
214: case GroovyTokenTypes.SR_ASSIGN:
215: case GroovyTokenTypes.STAR:
216: case GroovyTokenTypes.STAR_ASSIGN:
217: case GroovyTokenTypes.STAR_STAR:
218: case GroovyTokenTypes.STAR_STAR_ASSIGN:
219: case GroovyTokenTypes.STATIC_IMPORT:
220: case GroovyTokenTypes.STATIC_INIT:
221: case GroovyTokenTypes.STRICTFP:
222: case GroovyTokenTypes.STRING_CH:
223: case GroovyTokenTypes.STRING_CONSTRUCTOR:
224: case GroovyTokenTypes.STRING_CTOR_END:
225: case GroovyTokenTypes.STRING_CTOR_MIDDLE:
226: case GroovyTokenTypes.STRING_CTOR_START:
227: case GroovyTokenTypes.STRING_NL:
228: case GroovyTokenTypes.SUPER_CTOR_CALL:
229: case GroovyTokenTypes.TRIPLE_DOT:
230: case GroovyTokenTypes.TYPECAST:
231: case GroovyTokenTypes.TYPE_ARGUMENT:
232: case GroovyTokenTypes.TYPE_ARGUMENTS:
233: case GroovyTokenTypes.TYPE_LOWER_BOUNDS:
234: case GroovyTokenTypes.TYPE_PARAMETER:
235: case GroovyTokenTypes.TYPE_PARAMETERS:
236: case GroovyTokenTypes.TYPE_UPPER_BOUNDS:
237: case GroovyTokenTypes.UNARY_MINUS:
238: case GroovyTokenTypes.UNARY_PLUS:
239: case GroovyTokenTypes.UNUSED_CONST:
240: case GroovyTokenTypes.UNUSED_DO:
241: case GroovyTokenTypes.UNUSED_GOTO:
242: case GroovyTokenTypes.VARIABLE_DEF:
243: case GroovyTokenTypes.VARIABLE_PARAMETER_DEF:
244: case GroovyTokenTypes.VOCAB:
245: case GroovyTokenTypes.WILDCARD_TYPE:
246: case GroovyTokenTypes.WS:
247: colour = black;
248: break;
249:
250: case GroovyTokenTypes.STRING_LITERAL:
251: case GroovyTokenTypes.REGEXP_LITERAL:
252: colour = green;
253: break;
254:
255: case GroovyTokenTypes.CLASS_DEF:
256: case GroovyTokenTypes.EXTENDS_CLAUSE:
257: case GroovyTokenTypes.IMPLEMENTS_CLAUSE:
258: case GroovyTokenTypes.IMPORT:
259: case GroovyTokenTypes.LITERAL_any:
260: case GroovyTokenTypes.LITERAL_as:
261: case GroovyTokenTypes.LITERAL_assert:
262: case GroovyTokenTypes.LITERAL_boolean:
263: case GroovyTokenTypes.LITERAL_break:
264: case GroovyTokenTypes.LITERAL_byte:
265: case GroovyTokenTypes.LITERAL_case:
266: case GroovyTokenTypes.LITERAL_catch:
267: case GroovyTokenTypes.LITERAL_char:
268: case GroovyTokenTypes.LITERAL_class:
269: case GroovyTokenTypes.LITERAL_continue:
270: case GroovyTokenTypes.LITERAL_def:
271: case GroovyTokenTypes.LITERAL_default:
272: case GroovyTokenTypes.LITERAL_double:
273: case GroovyTokenTypes.LITERAL_else:
274: case GroovyTokenTypes.LITERAL_enum:
275: case GroovyTokenTypes.LITERAL_extends:
276: case GroovyTokenTypes.LITERAL_false:
277: case GroovyTokenTypes.LITERAL_finally:
278: case GroovyTokenTypes.LITERAL_float:
279: case GroovyTokenTypes.LITERAL_for:
280: case GroovyTokenTypes.LITERAL_if:
281: case GroovyTokenTypes.LITERAL_implements :
282: case GroovyTokenTypes.LITERAL_import:
283: case GroovyTokenTypes.LITERAL_in:
284: case GroovyTokenTypes.LITERAL_instanceof :
285: case GroovyTokenTypes.LITERAL_int:
286: case GroovyTokenTypes.LITERAL_interface:
287: case GroovyTokenTypes.LITERAL_long:
288: case GroovyTokenTypes.LITERAL_native:
289: case GroovyTokenTypes.LITERAL_new:
290: case GroovyTokenTypes.LITERAL_null:
291: case GroovyTokenTypes.LITERAL_package:
292: case GroovyTokenTypes.LITERAL_private:
293: case GroovyTokenTypes.LITERAL_protected:
294: case GroovyTokenTypes.LITERAL_public:
295: case GroovyTokenTypes.LITERAL_return:
296: case GroovyTokenTypes.LITERAL_short:
297: case GroovyTokenTypes.LITERAL_static:
298: case GroovyTokenTypes.LITERAL_super :
299: case GroovyTokenTypes.LITERAL_switch:
300: case GroovyTokenTypes.LITERAL_synchronized:
301: case GroovyTokenTypes.LITERAL_this :
302: case GroovyTokenTypes.LITERAL_threadsafe:
303: case GroovyTokenTypes.LITERAL_throw:
304: case GroovyTokenTypes.LITERAL_throws:
305: case GroovyTokenTypes.LITERAL_transient:
306: case GroovyTokenTypes.LITERAL_true:
307: case GroovyTokenTypes.LITERAL_try:
308: case GroovyTokenTypes.LITERAL_void:
309: case GroovyTokenTypes.LITERAL_volatile:
310: case GroovyTokenTypes.LITERAL_while:
311: case GroovyTokenTypes.LITERAL_with:
312: case GroovyTokenTypes.PACKAGE_DEF:
313: case GroovyTokenTypes.TYPE:
314: colour = blue;
315: break;
316:
317: case GroovyTokenTypes.IDENT:
318: colour = cyan;
319: break;
320:
321: default:
322: colour = black;
323: break;
324: }
325:
326: // leaf nodes that haven't been coloured yet
327: if (black.equals(colour) && t.getNumberOfChildren() == 0) {
328: colour = cyan;
329: }
330:
331: return colour;
332: }
333:
334: private String getName(GroovySourceAST t) {
335: String name = tokenNames[t.getType()] + " <" + t.getType()
336: + ">";
337: if (!(escape(tokenNames[t.getType()])
338: .equals(escape(t.getText())))) {
339: name = name + " : " + t.getText();
340: }
341: switch (t.getType()) {
342: case GroovyTokenTypes.METHOD_DEF:
343: case GroovyTokenTypes.VARIABLE_DEF:
344: GroovySourceAST identNode = t
345: .childOfType(GroovyTokenTypes.IDENT);
346: if (identNode != null) {
347: name = name + " : " + identNode.getText() + "";
348: }
349: }
350: name = escape(name);
351: return name;
352: }
353:
354: private String escape(String name) {
355: name = name.replace('"', ' ');
356: name = name.replace('\'', ' ');
357: name = name.replaceAll("&", "&");
358: name = name.trim();
359: return name;
360: }
361: }
|