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 **/
018 package org.codehaus.groovy.antlr.treewalker;
019
020 import java.io.PrintStream;
021
022 import org.codehaus.groovy.antlr.GroovySourceAST;
023 import org.codehaus.groovy.antlr.parser.GroovyTokenTypes;
024
025 /**
026 * An antlr AST visitor that prints a format suitable for viewing in http://freemind.sourceforge.net
027 *
028 * @author <a href="mailto:groovy@ross-rayner.com">Jeremy Rayner</a>
029 * @version $Revision: 4526 $
030 */
031
032 public class MindMapPrinter extends VisitorAdapter {
033 private String[] tokenNames;
034 private PrintStream out;
035 private int depth;
036
037 /**
038 * A visitor that prints a format suitable for viewing in http://freemind.sourceforge.net
039 * @param out where to print the mindmap file contents to
040 * @param tokenNames an array of token names from antlr
041 */
042
043 public MindMapPrinter(PrintStream out,String[] tokenNames) {
044 this.tokenNames = tokenNames;
045 this.out = out;
046 }
047
048 public void setUp() {
049 depth = 0;
050 out.println("<map version='0.7.1'><node TEXT='AST'>");
051 }
052
053 public void visitDefault(GroovySourceAST t,int visit) {
054 if (visit == OPENING_VISIT) {
055 depth++;
056 String name = getName(t);
057 String colour = getColour(t);
058 String folded = getFolded(t);
059 out.print("<node TEXT='" + name + "' POSITION='right'" + 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
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 }