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 }