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("&","&amp;");
357            name = name.trim();
358            return name;
359        }
360    }