001    /* Copyright 2000, 2001, Compaq Computer Corporation */
002    
003    package javafe;
004    
005    
006    import javafe.ast.*;
007    import javafe.tc.*;
008    
009    import javafe.util.*;
010    
011    
012    /**
013     * <code>TestTool</code> is an test class for <code>SrcTool</code> and
014     * its superclasses. <p>
015     *
016     * It just loads in files unless <code>-superclasses</code> is
017     * supplied, in which case it chases down each classes' superclass
018     * chain.<p>
019     *
020     * Note: because this class is intended as a test class routine, the 
021     * code for chasing superclass pointers is kludgey and does not always
022     * work correctly.
023     */
024    
025    public class TestTool extends SrcTool {
026    
027        /***************************************************
028         *                                                 *
029         * Generating a usage message:                     *
030         *                                                 *
031         **************************************************/
032    
033        /**
034         * Return the name of this tool.  E.g., "ls" or "cp".<p>
035         *
036         * Used in usage and error messages.<p>
037         */
038        public String name() { return "TestTool"; }
039        
040        public javafe.Options makeOptions() { return new Options(); }
041        
042        public final Options options() { return (Options)options; }
043    
044        public class Options extends SrcToolOptions {
045                /**
046                 * Print option information to <code>System.err</code>.  Each
047                 * printed line should be preceeded by two blank spaces. <p>
048                 *
049                 * Each overriding method should first call
050                 * <code>super.showOptions()</code>.<p>
051                 */
052                public String showOptions(boolean all) {
053                    return super.showOptions(all) + ("  -superclasses") + eol;
054                }
055            
056            
057                /***************************************************
058                 *                                                 *
059                 * Option processing:                              *
060                 *                                                 *
061                 **************************************************/
062            
063                /**
064                 * Should we chase superclass pointers?  Defaults to no, set by
065                 * <code>-superclasses</code>.
066                 */
067                public boolean chaseSuperclasses = false;
068            
069            
070            /**
071             * Process next tool option. <p>
072             *
073             * See <code>Tool.processOption</code> for the complete
074             * specification of this routine.<p>
075             *
076             * This routine handles the <code>-superclasses</code> option.<p>
077             */
078            public int processOption(String option, String[] args, int offset) 
079                                         throws UsageError {
080                if (option.equals("-superclasses")) {
081                    chaseSuperclasses = true;
082                    return offset;
083                }
084        
085                // Pass on unrecognized options:
086                return super.processOption(option, args, offset);
087            }
088                
089        }
090    
091    
092        /***************************************************
093         *                                                 *
094         * Main processing code:                           *
095         *                                                 *
096         **************************************************/
097    
098        /**
099         * Start up an instance of this tool using command-line arguments
100         * <code>args</code>. <p> 
101         *
102         * <b>Note</b>: this code needs to be copied verbatim to each
103         * subclass of <code>Tool</code> except with the name of the actual
104         * subclass inserted after the new operator.<p>
105         *
106         * (This needs to be done because static methods cannot be
107         * inherited.)<p>
108         */
109        //@ requires \nonnullelements(args);
110        public static void main(String[] args) {
111                    Tool t = new TestTool();
112                    int result = t.run(args);
113                    if (result != 0) System.exit(result);
114        }
115    
116    
117        /***************************************************
118         *                                                 *
119         * SrcTool-instance specific processing:           *
120         *                                                 *
121         **************************************************/
122    
123        /**
124         * This method is called on the TypeDecl of each
125         * outside type that SrcTool is to process. <p>
126         */
127        public void handleTD(TypeDecl td) {
128                    Info.out("[processing "
129                            + TypeSig.getSig(td).getExternalName());
130            
131                    if (!options().chaseSuperclasses)
132                       return;
133            
134                    TypeSig current = TypeSig.getSig(td);
135                    while (current != null) {
136                        Info.out("  At " + current.getExternalName());
137            
138                        current = getSuperClass(current.getTypeDecl());
139                    }
140            
141                    Info.out("]");
142        }
143    
144    
145        /**
146         * Attempt to fetch the <code>TypeSig</code> for a given
147         * <code>TypeDecl</code>. <p>
148         * 
149         * Returns null if none exists.<p>
150         */
151        public TypeSig getSuperClass(TypeDecl td) {
152                    // If  td is not a class, then it has no superclass:
153                    if (!(td instanceof ClassDecl))
154                        return null;
155                    ClassDecl cd = (ClassDecl)td;
156            
157                    // Get td's superclass name:
158                    TypeSig root = Types.javaLangObject();
159                    if (TypeSig.getSig(td) == root)
160                        return null;
161                    if (cd.superClass == null) {
162                        Info.out("    extended by java.lang.Object");
163                        return root;
164                    }
165            
166                    Name superClassName = cd.superClass.name;
167                    Info.out("    extended by " + superClassName.printName());
168            
169                    int sz = superClassName.size();
170                    String[] P = superClassName.toStrings(sz-1);
171                    String   T = superClassName.identifierAt(sz-1).toString();
172            
173                    if (sz == 1) {
174                        // Simple name -- assume for now in same package:
175                        // This is a bit of a hack:
176                        TypeSig sig = TypeSig.getSig(td);
177                        P = sig.packageName;
178                    }
179            
180                    TypeSig S = OutsideEnv.lookup(P, T);
181                    if (S == null)
182                        ErrorSet.error("unable to load type "
183                                            + superClassName.printName());
184                    return S;
185        }
186    }