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
22 import org.codehaus.groovy.antlr.GroovySourceAST;
23 import org.codehaus.groovy.antlr.parser.GroovyTokenTypes;
24
25 /***
26 * An antlr AST visitor that prints a format suitable for viewing in http://freemind.sourceforge.net
27 *
28 * @author <a href="mailto:groovy@ross-rayner.com">Jeremy Rayner</a>
29 * @version $Revision: 1.4 $
30 */
31
32 public class MindMapPrinter extends VisitorAdapter {
33 private String[] tokenNames;
34 private PrintStream out;
35 private int depth;
36
37 /***
38 * A visitor that prints a format suitable for viewing in http://freemind.sourceforge.net
39 * @param out where to print the mindmap file contents to
40 * @param tokenNames an array of token names from antlr
41 */
42
43 public MindMapPrinter(PrintStream out,String[] tokenNames) {
44 this.tokenNames = tokenNames;
45 this.out = out;
46 }
47
48 public void setUp() {
49 depth = 0;
50 out.println("<map version='0.7.1'><node TEXT='AST'>");
51 }
52
53 public void visitDefault(GroovySourceAST t,int visit) {
54 if (visit == OPENING_VISIT) {
55 depth++;
56 String name = getName(t);
57 String colour = getColour(t);
58 String folded = getFolded(t);
59 out.print("<node TEXT='" + name + "' POSITION='right'" + colour + folded + ">");
60 } else {
61 out.println("</node>");
62 depth--;
63 }
64 }
65
66 public void tearDown() {
67 out.println("</node></map>");
68 }
69
70 private String getFolded(GroovySourceAST t) {
71 if (depth > 2 && t.getNumberOfChildren() > 0) {
72 switch (t.getType()) {
73 case GroovyTokenTypes.EXPR :
74 case GroovyTokenTypes.METHOD_DEF :
75 case GroovyTokenTypes.VARIABLE_DEF :
76 return " FOLDED='true'";
77 }
78 }
79 if (t.getType() == GroovyTokenTypes.IMPORT) {
80 return " FOLDED='true'";
81 }
82 return "";
83 }
84
85 private String getColour(GroovySourceAST t) {
86 String colour = "";
87 String black = " COLOR=\"#000000\"";
88 String cyan = " COLOR=\"#006699\"";
89 String blue = " COLOR=\"#17178B\"";
90 String green = " COLOR=\"#008000\"";
91 switch (t.getType()) {
92 case GroovyTokenTypes.ABSTRACT :
93 case GroovyTokenTypes.ANNOTATION :
94 case GroovyTokenTypes.ANNOTATIONS :
95 case GroovyTokenTypes.ANNOTATION_ARRAY_INIT :
96 case GroovyTokenTypes.ANNOTATION_DEF :
97 case GroovyTokenTypes.ANNOTATION_FIELD_DEF :
98 case GroovyTokenTypes.ANNOTATION_MEMBER_VALUE_PAIR :
99 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.CLOSED_BLOCK :
115 case GroovyTokenTypes.CLOSURE_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
327 if (black.equals(colour) && t.getNumberOfChildren() == 0) {
328 colour = cyan;
329 }
330
331
332
333 return colour;
334 }
335
336 private String getName(GroovySourceAST t) {
337 String name = tokenNames[t.getType()] + " <" + t.getType() + ">";
338 if (!(escape(tokenNames[t.getType()]).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.childOfType(GroovyTokenTypes.IDENT);
345 if (identNode != null) {
346 name = name + " : " + identNode.getText() + "";
347 }
348 }
349 name = escape(name);
350 return name;
351 }
352
353 private String escape(String name) {
354 name = name.replace('"',' ');
355 name = name.replace('\'',' ');
356 name = name.replaceAll("&","&");
357 name = name.trim();
358 return name;
359 }
360 }