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 }