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    }