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 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: 1.3 $ 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'" + colour + folded + ">"); 059 } else { 060 out.println("</node>"); 061 depth--; 062 } 063 } 064 065 public void tearDown() { 066 out.println("</node></map>"); 067 } 068 069 private String getFolded(GroovySourceAST t) { 070 if (depth > 2 && t.getNumberOfChildren() > 0) { 071 switch (t.getType()) { 072 case GroovyTokenTypes.EXPR : 073 case GroovyTokenTypes.METHOD_DEF : 074 case GroovyTokenTypes.VARIABLE_DEF : 075 return " FOLDED='true'"; 076 } 077 } 078 if (t.getType() == GroovyTokenTypes.IMPORT) { 079 return " FOLDED='true'"; 080 } 081 return ""; 082 } 083 084 private String getColour(GroovySourceAST t) { 085 String colour = ""; 086 String black = " COLOR=\"#000000\""; 087 String cyan = " COLOR=\"#006699\""; 088 String blue = " COLOR=\"#17178B\""; 089 String green = " COLOR=\"#008000\""; 090 switch (t.getType()) { 091 case GroovyTokenTypes.ABSTRACT : 092 case GroovyTokenTypes.ANNOTATION : 093 case GroovyTokenTypes.ANNOTATIONS : 094 case GroovyTokenTypes.ANNOTATION_ARRAY_INIT : 095 case GroovyTokenTypes.ANNOTATION_DEF : 096 case GroovyTokenTypes.ANNOTATION_FIELD_DEF : 097 case GroovyTokenTypes.ANNOTATION_MEMBER_VALUE_PAIR : 098 case GroovyTokenTypes.ARRAY_DECLARATOR : 099 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 // leaf nodes that haven't been coloured yet 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 }