1 /***
2 *
3 * Copyright 2005 Jeremy Rayner
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 **/
18 package org.codehaus.groovy.antlr.treewalker;
19
20 import java.io.PrintStream;
21 import org.codehaus.groovy.antlr.GroovySourceAST;
22 import org.codehaus.groovy.antlr.parser.GroovyTokenTypes;
23
24 /***
25 * An antlr AST visitor that prints a format suitable for viewing in http://freemind.sourceforge.net
26 *
27 * @author <a href="mailto:groovy@ross-rayner.com">Jeremy Rayner</a>
28 * @version $Revision: 1.3 $
29 */
30
31 public class MindMapPrinter extends VisitorAdapter {
32 private String[] tokenNames;
33 private PrintStream out;
34 private int depth;
35
36 /***
37 * A visitor that prints a format suitable for viewing in http://freemind.sourceforge.net
38 * @param out where to print the mindmap file contents to
39 * @param tokenNames an array of token names from antlr
40 */
41
42 public MindMapPrinter(PrintStream out,String[] tokenNames) {
43 this.tokenNames = tokenNames;
44 this.out = out;
45 }
46
47 public void setUp() {
48 depth = 0;
49 out.println("<map version='0.7.1'><node TEXT='AST'>");
50 }
51
52 public void visitDefault(GroovySourceAST t,int visit) {
53 if (visit == OPENING_VISIT) {
54 depth++;
55 String name = getName(t);
56 String colour = getColour(t);
57 String folded = getFolded(t);
58 out.print("<node TEXT='" + name + "' POSITION='right'" + colour + folded + ">");
59 } else {
60 out.println("</node>");
61 depth--;
62 }
63 }
64
65 public void tearDown() {
66 out.println("</node></map>");
67 }
68
69 private String getFolded(GroovySourceAST t) {
70 if (depth > 2 && t.getNumberOfChildren() > 0) {
71 switch (t.getType()) {
72 case GroovyTokenTypes.EXPR :
73 case GroovyTokenTypes.METHOD_DEF :
74 case GroovyTokenTypes.VARIABLE_DEF :
75 return " FOLDED='true'";
76 }
77 }
78 if (t.getType() == GroovyTokenTypes.IMPORT) {
79 return " FOLDED='true'";
80 }
81 return "";
82 }
83
84 private String getColour(GroovySourceAST t) {
85 String colour = "";
86 String black = " COLOR=\"#000000\"";
87 String cyan = " COLOR=\"#006699\"";
88 String blue = " COLOR=\"#17178B\"";
89 String green = " COLOR=\"#008000\"";
90 switch (t.getType()) {
91 case GroovyTokenTypes.ABSTRACT :
92 case GroovyTokenTypes.ANNOTATION :
93 case GroovyTokenTypes.ANNOTATIONS :
94 case GroovyTokenTypes.ANNOTATION_ARRAY_INIT :
95 case GroovyTokenTypes.ANNOTATION_DEF :
96 case GroovyTokenTypes.ANNOTATION_FIELD_DEF :
97 case GroovyTokenTypes.ANNOTATION_MEMBER_VALUE_PAIR :
98 case GroovyTokenTypes.ARRAY_DECLARATOR :
99 case GroovyTokenTypes.ASSIGN :
100 case GroovyTokenTypes.AT :
101 case GroovyTokenTypes.BAND :
102 case GroovyTokenTypes.BAND_ASSIGN :
103 case GroovyTokenTypes.BIG_SUFFIX :
104 case GroovyTokenTypes.BLOCK :
105 case GroovyTokenTypes.BNOT :
106 case GroovyTokenTypes.BOR :
107 case GroovyTokenTypes.BOR_ASSIGN :
108 case GroovyTokenTypes.BSR :
109 case GroovyTokenTypes.BSR_ASSIGN :
110 case GroovyTokenTypes.BXOR :
111 case GroovyTokenTypes.BXOR_ASSIGN :
112 case GroovyTokenTypes.CASE_GROUP :
113 case GroovyTokenTypes.CLOSED_BLOCK :
114 case GroovyTokenTypes.CLOSURE_OP :
115 case GroovyTokenTypes.COLON :
116 case GroovyTokenTypes.COMMA :
117 case GroovyTokenTypes.COMPARE_TO :
118 case GroovyTokenTypes.CTOR_CALL :
119 case GroovyTokenTypes.CTOR_IDENT :
120 case GroovyTokenTypes.DEC :
121 case GroovyTokenTypes.DIGIT :
122 case GroovyTokenTypes.DIV :
123 case GroovyTokenTypes.DIV_ASSIGN :
124 case GroovyTokenTypes.DOLLAR :
125 case GroovyTokenTypes.DOT :
126 case GroovyTokenTypes.DYNAMIC_MEMBER :
127 case GroovyTokenTypes.ELIST :
128 case GroovyTokenTypes.EMPTY_STAT :
129 case GroovyTokenTypes.ENUM_CONSTANT_DEF :
130 case GroovyTokenTypes.ENUM_DEF :
131 case GroovyTokenTypes.EOF :
132 case GroovyTokenTypes.EQUAL :
133 case GroovyTokenTypes.ESC :
134 case GroovyTokenTypes.EXPONENT :
135 case GroovyTokenTypes.EXPR :
136 case GroovyTokenTypes.FINAL :
137 case GroovyTokenTypes.FLOAT_SUFFIX :
138 case GroovyTokenTypes.FOR_CONDITION :
139 case GroovyTokenTypes.FOR_EACH_CLAUSE :
140 case GroovyTokenTypes.FOR_INIT :
141 case GroovyTokenTypes.FOR_IN_ITERABLE :
142 case GroovyTokenTypes.FOR_ITERATOR :
143 case GroovyTokenTypes.GE :
144 case GroovyTokenTypes.GT :
145 case GroovyTokenTypes.HEX_DIGIT :
146 case GroovyTokenTypes.IMPLICIT_PARAMETERS :
147 case GroovyTokenTypes.INC :
148 case GroovyTokenTypes.INDEX_OP :
149 case GroovyTokenTypes.INSTANCE_INIT :
150 case GroovyTokenTypes.INTERFACE_DEF :
151 case GroovyTokenTypes.LABELED_ARG :
152 case GroovyTokenTypes.LABELED_STAT :
153 case GroovyTokenTypes.LAND :
154 case GroovyTokenTypes.LBRACK :
155 case GroovyTokenTypes.LCURLY :
156 case GroovyTokenTypes.LE :
157 case GroovyTokenTypes.LETTER :
158 case GroovyTokenTypes.LIST_CONSTRUCTOR :
159 case GroovyTokenTypes.LNOT :
160 case GroovyTokenTypes.LOR :
161 case GroovyTokenTypes.LPAREN :
162 case GroovyTokenTypes.LT :
163 case GroovyTokenTypes.MAP_CONSTRUCTOR :
164 case GroovyTokenTypes.MEMBER_POINTER :
165 case GroovyTokenTypes.METHOD_CALL :
166 case GroovyTokenTypes.METHOD_DEF :
167 case GroovyTokenTypes.MINUS :
168 case GroovyTokenTypes.MINUS_ASSIGN :
169 case GroovyTokenTypes.ML_COMMENT :
170 case GroovyTokenTypes.MOD :
171 case GroovyTokenTypes.MODIFIERS :
172 case GroovyTokenTypes.MOD_ASSIGN :
173 case GroovyTokenTypes.NLS :
174 case GroovyTokenTypes.NOT_EQUAL :
175 case GroovyTokenTypes.NULL_TREE_LOOKAHEAD :
176 case GroovyTokenTypes.NUM_BIG_DECIMAL :
177 case GroovyTokenTypes.NUM_BIG_INT :
178 case GroovyTokenTypes.NUM_DOUBLE :
179 case GroovyTokenTypes.NUM_FLOAT :
180 case GroovyTokenTypes.NUM_INT :
181 case GroovyTokenTypes.NUM_LONG :
182 case GroovyTokenTypes.OBJBLOCK :
183 case GroovyTokenTypes.ONE_NL :
184 case GroovyTokenTypes.OPTIONAL_DOT :
185 case GroovyTokenTypes.PARAMETERS :
186 case GroovyTokenTypes.PARAMETER_DEF :
187 case GroovyTokenTypes.PLUS :
188 case GroovyTokenTypes.PLUS_ASSIGN :
189 case GroovyTokenTypes.POST_DEC :
190 case GroovyTokenTypes.POST_INC :
191 case GroovyTokenTypes.QUESTION :
192 case GroovyTokenTypes.RANGE_EXCLUSIVE :
193 case GroovyTokenTypes.RANGE_INCLUSIVE :
194 case GroovyTokenTypes.RBRACK :
195 case GroovyTokenTypes.RCURLY :
196 case GroovyTokenTypes.REGEXP_CTOR_END :
197 case GroovyTokenTypes.REGEXP_SYMBOL :
198 case GroovyTokenTypes.REGEX_FIND :
199 case GroovyTokenTypes.REGEX_MATCH :
200 case GroovyTokenTypes.RPAREN :
201 case GroovyTokenTypes.SCOPE_ESCAPE :
202 case GroovyTokenTypes.SELECT_SLOT :
203 case GroovyTokenTypes.SEMI :
204 case GroovyTokenTypes.SH_COMMENT :
205 case GroovyTokenTypes.SL :
206 case GroovyTokenTypes.SLIST :
207 case GroovyTokenTypes.SL_ASSIGN :
208 case GroovyTokenTypes.SL_COMMENT :
209 case GroovyTokenTypes.SPREAD_ARG :
210 case GroovyTokenTypes.SPREAD_DOT :
211 case GroovyTokenTypes.SPREAD_MAP_ARG :
212 case GroovyTokenTypes.SR :
213 case GroovyTokenTypes.SR_ASSIGN :
214 case GroovyTokenTypes.STAR :
215 case GroovyTokenTypes.STAR_ASSIGN :
216 case GroovyTokenTypes.STAR_STAR :
217 case GroovyTokenTypes.STAR_STAR_ASSIGN :
218 case GroovyTokenTypes.STATIC_IMPORT :
219 case GroovyTokenTypes.STATIC_INIT :
220 case GroovyTokenTypes.STRICTFP :
221 case GroovyTokenTypes.STRING_CH :
222 case GroovyTokenTypes.STRING_CONSTRUCTOR :
223 case GroovyTokenTypes.STRING_CTOR_END :
224 case GroovyTokenTypes.STRING_CTOR_MIDDLE :
225 case GroovyTokenTypes.STRING_CTOR_START :
226 case GroovyTokenTypes.STRING_NL :
227 case GroovyTokenTypes.SUPER_CTOR_CALL :
228 case GroovyTokenTypes.TRIPLE_DOT :
229 case GroovyTokenTypes.TYPECAST :
230 case GroovyTokenTypes.TYPE_ARGUMENT :
231 case GroovyTokenTypes.TYPE_ARGUMENTS :
232 case GroovyTokenTypes.TYPE_LOWER_BOUNDS :
233 case GroovyTokenTypes.TYPE_PARAMETER :
234 case GroovyTokenTypes.TYPE_PARAMETERS :
235 case GroovyTokenTypes.TYPE_UPPER_BOUNDS :
236 case GroovyTokenTypes.UNARY_MINUS :
237 case GroovyTokenTypes.UNARY_PLUS :
238 case GroovyTokenTypes.UNUSED_CONST :
239 case GroovyTokenTypes.UNUSED_DO :
240 case GroovyTokenTypes.UNUSED_GOTO :
241 case GroovyTokenTypes.VARIABLE_DEF :
242 case GroovyTokenTypes.VARIABLE_PARAMETER_DEF :
243 case GroovyTokenTypes.VOCAB :
244 case GroovyTokenTypes.WILDCARD_TYPE :
245 case GroovyTokenTypes.WS :
246 colour = black;
247 break;
248
249 case GroovyTokenTypes.STRING_LITERAL :
250 case GroovyTokenTypes.REGEXP_LITERAL :
251 colour = green;
252 break;
253
254 case GroovyTokenTypes.CLASS_DEF :
255 case GroovyTokenTypes.EXTENDS_CLAUSE :
256 case GroovyTokenTypes.IMPLEMENTS_CLAUSE :
257 case GroovyTokenTypes.IMPORT :
258 case GroovyTokenTypes.LITERAL_any :
259 case GroovyTokenTypes.LITERAL_as :
260 case GroovyTokenTypes.LITERAL_assert :
261 case GroovyTokenTypes.LITERAL_boolean :
262 case GroovyTokenTypes.LITERAL_break :
263 case GroovyTokenTypes.LITERAL_byte :
264 case GroovyTokenTypes.LITERAL_case :
265 case GroovyTokenTypes.LITERAL_catch :
266 case GroovyTokenTypes.LITERAL_char :
267 case GroovyTokenTypes.LITERAL_class :
268 case GroovyTokenTypes.LITERAL_continue :
269 case GroovyTokenTypes.LITERAL_def :
270 case GroovyTokenTypes.LITERAL_default :
271 case GroovyTokenTypes.LITERAL_double :
272 case GroovyTokenTypes.LITERAL_else :
273 case GroovyTokenTypes.LITERAL_enum :
274 case GroovyTokenTypes.LITERAL_extends :
275 case GroovyTokenTypes.LITERAL_false :
276 case GroovyTokenTypes.LITERAL_finally :
277 case GroovyTokenTypes.LITERAL_float :
278 case GroovyTokenTypes.LITERAL_for :
279 case GroovyTokenTypes.LITERAL_if :
280 case GroovyTokenTypes.LITERAL_implements :
281 case GroovyTokenTypes.LITERAL_import :
282 case GroovyTokenTypes.LITERAL_in :
283 case GroovyTokenTypes.LITERAL_instanceof :
284 case GroovyTokenTypes.LITERAL_int :
285 case GroovyTokenTypes.LITERAL_interface :
286 case GroovyTokenTypes.LITERAL_long :
287 case GroovyTokenTypes.LITERAL_native :
288 case GroovyTokenTypes.LITERAL_new :
289 case GroovyTokenTypes.LITERAL_null :
290 case GroovyTokenTypes.LITERAL_package :
291 case GroovyTokenTypes.LITERAL_private :
292 case GroovyTokenTypes.LITERAL_protected :
293 case GroovyTokenTypes.LITERAL_public :
294 case GroovyTokenTypes.LITERAL_return :
295 case GroovyTokenTypes.LITERAL_short :
296 case GroovyTokenTypes.LITERAL_static :
297 case GroovyTokenTypes.LITERAL_super :
298 case GroovyTokenTypes.LITERAL_switch :
299 case GroovyTokenTypes.LITERAL_synchronized :
300 case GroovyTokenTypes.LITERAL_this :
301 case GroovyTokenTypes.LITERAL_threadsafe :
302 case GroovyTokenTypes.LITERAL_throw :
303 case GroovyTokenTypes.LITERAL_throws :
304 case GroovyTokenTypes.LITERAL_transient :
305 case GroovyTokenTypes.LITERAL_true :
306 case GroovyTokenTypes.LITERAL_try :
307 case GroovyTokenTypes.LITERAL_void :
308 case GroovyTokenTypes.LITERAL_volatile :
309 case GroovyTokenTypes.LITERAL_while :
310 case GroovyTokenTypes.LITERAL_with :
311 case GroovyTokenTypes.PACKAGE_DEF :
312 case GroovyTokenTypes.TYPE :
313 colour = blue;
314 break;
315
316 case GroovyTokenTypes.IDENT :
317 colour = cyan;
318 break;
319
320 default:
321 colour = black;
322 break;
323 }
324
325
326 if (black.equals(colour) && t.getNumberOfChildren() == 0) {
327 colour = cyan;
328 }
329
330
331
332 return colour;
333 }
334
335 private String getName(GroovySourceAST t) {
336 String name = tokenNames[t.getType()] + " <" + t.getType() + ">";
337 if (!(escape(tokenNames[t.getType()]).equals(escape(t.getText())))) {
338 name = name + " : " + t.getText();
339 }
340 switch (t.getType()) {
341 case GroovyTokenTypes.METHOD_DEF :
342 case GroovyTokenTypes.VARIABLE_DEF :
343 GroovySourceAST identNode = t.childOfType(GroovyTokenTypes.IDENT);
344 if (identNode != null) {
345 name = name + " : " + identNode.getText() + "";
346 }
347 }
348 name = escape(name);
349 return name;
350 }
351
352 private String escape(String name) {
353 name = name.replace('"',' ');
354 name = name.replace('\'',' ');
355 name = name.replaceAll("&","&");
356 name = name.trim();
357 return name;
358 }
359
360 }