J. Duke | 319a3b9 | 2007-12-01 00:00:00 +0000 | [diff] [blame^] | 1 | /* |
| 2 | * Copyright 1994-2004 Sun Microsystems, Inc. All Rights Reserved. |
| 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| 4 | * |
| 5 | * This code is free software; you can redistribute it and/or modify it |
| 6 | * under the terms of the GNU General Public License version 2 only, as |
| 7 | * published by the Free Software Foundation. Sun designates this |
| 8 | * particular file as subject to the "Classpath" exception as provided |
| 9 | * by Sun in the LICENSE file that accompanied this code. |
| 10 | * |
| 11 | * This code is distributed in the hope that it will be useful, but WITHOUT |
| 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| 14 | * version 2 for more details (a copy is included in the LICENSE file that |
| 15 | * accompanied this code). |
| 16 | * |
| 17 | * You should have received a copy of the GNU General Public License version |
| 18 | * 2 along with this work; if not, write to the Free Software Foundation, |
| 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| 20 | * |
| 21 | * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
| 22 | * CA 95054 USA or visit www.sun.com if you need additional information or |
| 23 | * have any questions. |
| 24 | */ |
| 25 | |
| 26 | package sun.tools.javac; |
| 27 | |
| 28 | import sun.tools.java.*; |
| 29 | import sun.tools.tree.*; |
| 30 | |
| 31 | import java.io.IOException; |
| 32 | import java.io.InputStream; |
| 33 | import java.util.Vector; |
| 34 | import java.util.Enumeration; |
| 35 | |
| 36 | /** |
| 37 | * Batch file parser, this needs more work. |
| 38 | * |
| 39 | * WARNING: The contents of this source file are not part of any |
| 40 | * supported API. Code that depends on them does so at its own risk: |
| 41 | * they are subject to change or removal without notice. |
| 42 | */ |
| 43 | @Deprecated |
| 44 | public |
| 45 | class BatchParser extends Parser { |
| 46 | /** |
| 47 | * The current package |
| 48 | */ |
| 49 | protected Identifier pkg; |
| 50 | |
| 51 | /** |
| 52 | * The current imports |
| 53 | */ |
| 54 | protected Imports imports; |
| 55 | |
| 56 | /** |
| 57 | * The classes defined in this file |
| 58 | */ |
| 59 | protected Vector classes; |
| 60 | |
| 61 | |
| 62 | /** |
| 63 | * The current class |
| 64 | */ |
| 65 | protected SourceClass sourceClass; |
| 66 | |
| 67 | /** |
| 68 | * The toplevel environment |
| 69 | */ |
| 70 | protected Environment toplevelEnv; |
| 71 | |
| 72 | /** |
| 73 | * Create a batch file parser |
| 74 | */ |
| 75 | public BatchParser(Environment env, InputStream in) throws IOException { |
| 76 | super(env, in); |
| 77 | |
| 78 | imports = new Imports(env); |
| 79 | classes = new Vector(); |
| 80 | toplevelEnv = imports.newEnvironment(env); |
| 81 | } |
| 82 | |
| 83 | /** |
| 84 | * Package declaration |
| 85 | */ |
| 86 | public void packageDeclaration(long where, IdentifierToken t) { |
| 87 | Identifier nm = t.getName(); |
| 88 | //System.out.println("package " + nm); |
| 89 | if (pkg == null) { |
| 90 | // This code has been changed to pass an IdentifierToken, |
| 91 | // rather than an Identifier, to setCurrentPackage(). Imports |
| 92 | // now needs the location of the token. |
| 93 | pkg = t.getName(); |
| 94 | imports.setCurrentPackage(t); |
| 95 | } else { |
| 96 | env.error(where, "package.repeated"); |
| 97 | } |
| 98 | } |
| 99 | |
| 100 | /** |
| 101 | * Import class |
| 102 | */ |
| 103 | public void importClass(long pos, IdentifierToken t) { |
| 104 | //System.out.println("import class " + t); |
| 105 | imports.addClass(t); |
| 106 | } |
| 107 | |
| 108 | /** |
| 109 | * Import package |
| 110 | */ |
| 111 | public void importPackage(long pos, IdentifierToken t) { |
| 112 | //System.out.println("import package " + t); |
| 113 | imports.addPackage(t); |
| 114 | } |
| 115 | |
| 116 | /** |
| 117 | * Define class |
| 118 | */ |
| 119 | public ClassDefinition beginClass(long where, String doc, int mod, |
| 120 | IdentifierToken t, |
| 121 | IdentifierToken sup, |
| 122 | IdentifierToken interfaces[]) { |
| 123 | |
| 124 | // If this class is nested, the modifier bits set here will |
| 125 | // be copied into the 'SourceMember' object for the inner class |
| 126 | // created during the call to 'makeClassDefinition' below. |
| 127 | // When writing the class file, we will look there for the |
| 128 | // 'untransformed' modifiers. The modifiers in the ClassDefinition |
| 129 | // object will end up as the 'transformed' modifiers. Note that |
| 130 | // there are some bits set here that are not legal class modifiers |
| 131 | // according to the JVMS, e.g., M_PRIVATE and M_STATIC. These are |
| 132 | // masked off while writing the class file, but are preserved in |
| 133 | // the InnerClasses attributes. |
| 134 | |
| 135 | if (tracing) toplevelEnv.dtEnter("beginClass: " + sourceClass); |
| 136 | |
| 137 | SourceClass outerClass = sourceClass; |
| 138 | |
| 139 | if (outerClass == null && pkg != null) { |
| 140 | t = new IdentifierToken(t.getWhere(), |
| 141 | Identifier.lookup(pkg, t.getName())); |
| 142 | } |
| 143 | |
| 144 | // The defaults for anonymous and local classes should be documented! |
| 145 | |
| 146 | if ((mod & M_ANONYMOUS) != 0) { |
| 147 | mod |= (M_FINAL | M_PRIVATE); |
| 148 | } |
| 149 | if ((mod & M_LOCAL) != 0) { |
| 150 | mod |= M_PRIVATE; |
| 151 | } |
| 152 | |
| 153 | // Certain modifiers are implied as follows: |
| 154 | // |
| 155 | // 1. Any interface (nested or not) is implicitly deemed to be abstract, |
| 156 | // whether it is explicitly marked so or not. (Java 1.0.) |
| 157 | // 2. A interface which is a member of a type is implicitly deemed to |
| 158 | // be static, whether it is explicitly marked so or not. (InnerClasses) |
| 159 | // 3a. A type which is a member of an interface is implicitly deemed |
| 160 | // to be public, whether it is explicitly marked so or not. (InnerClasses) |
| 161 | // 3b. A type which is a member of an interface is implicitly deemed |
| 162 | // to be static, whether it is explicitly marked so or not. (InnerClasses) |
| 163 | |
| 164 | if ((mod & M_INTERFACE) != 0) { |
| 165 | // Rule 1. |
| 166 | mod |= M_ABSTRACT; |
| 167 | if (outerClass != null) { |
| 168 | // Rule 2. |
| 169 | mod |= M_STATIC; |
| 170 | } |
| 171 | } |
| 172 | |
| 173 | if (outerClass != null && outerClass.isInterface()) { |
| 174 | // Rule 3a. |
| 175 | // For interface members, neither 'private' nor 'protected' |
| 176 | // are legal modifiers. We avoid setting M_PUBLIC in some |
| 177 | // cases in order to avoid interfering with error detection |
| 178 | // and reporting. This is patched up, after reporting an |
| 179 | // error, by 'SourceClass.addMember'. |
| 180 | if ((mod & (M_PRIVATE | M_PROTECTED)) == 0) |
| 181 | mod |= M_PUBLIC; |
| 182 | // Rule 3b. |
| 183 | mod |= M_STATIC; |
| 184 | } |
| 185 | |
| 186 | // For nested classes, we must transform 'protected' to 'public' |
| 187 | // and 'private' to package scope. This must be done later, |
| 188 | // because any modifiers set here will be copied into the |
| 189 | // 'MemberDefinition' for the nested class, which must represent |
| 190 | // the original untransformed modifiers. Also, compile-time |
| 191 | // checks should be performed against the actual, untransformed |
| 192 | // modifiers. This is in contrast to transformations that implement |
| 193 | // implicit modifiers, such as M_STATIC and M_FINAL for fields |
| 194 | // of interfaces. |
| 195 | |
| 196 | sourceClass = (SourceClass) |
| 197 | toplevelEnv.makeClassDefinition(toplevelEnv, where, t, |
| 198 | doc, mod, sup, |
| 199 | interfaces, outerClass); |
| 200 | |
| 201 | sourceClass.getClassDeclaration().setDefinition(sourceClass, CS_PARSED); |
| 202 | env = new Environment(toplevelEnv, sourceClass); |
| 203 | |
| 204 | if (tracing) toplevelEnv.dtEvent("beginClass: SETTING UP DEPENDENCIES"); |
| 205 | |
| 206 | // The code which adds artificial dependencies between |
| 207 | // classes in the same source file has been moved to |
| 208 | // BatchEnvironment#parseFile(). |
| 209 | |
| 210 | if (tracing) toplevelEnv.dtEvent("beginClass: ADDING TO CLASS LIST"); |
| 211 | |
| 212 | classes.addElement(sourceClass); |
| 213 | |
| 214 | if (tracing) toplevelEnv.dtExit("beginClass: " + sourceClass); |
| 215 | |
| 216 | return sourceClass; |
| 217 | } |
| 218 | |
| 219 | /** |
| 220 | * Report the current class under construction. |
| 221 | */ |
| 222 | public ClassDefinition getCurrentClass() { |
| 223 | return sourceClass; |
| 224 | } |
| 225 | |
| 226 | /** |
| 227 | * End class |
| 228 | */ |
| 229 | public void endClass(long where, ClassDefinition c) { |
| 230 | |
| 231 | if (tracing) toplevelEnv.dtEnter("endClass: " + sourceClass); |
| 232 | |
| 233 | // c == sourceClass; don't bother to check |
| 234 | sourceClass.setEndPosition(where); |
| 235 | SourceClass outerClass = (SourceClass) sourceClass.getOuterClass(); |
| 236 | sourceClass = outerClass; |
| 237 | env = toplevelEnv; |
| 238 | if (sourceClass != null) |
| 239 | env = new Environment(env, sourceClass); |
| 240 | |
| 241 | if (tracing) toplevelEnv.dtExit("endClass: " + sourceClass); |
| 242 | } |
| 243 | |
| 244 | /** |
| 245 | * Define a method |
| 246 | */ |
| 247 | public void defineField(long where, ClassDefinition c, |
| 248 | String doc, int mod, Type t, |
| 249 | IdentifierToken name, IdentifierToken args[], |
| 250 | IdentifierToken exp[], Node val) { |
| 251 | // c == sourceClass; don't bother to check |
| 252 | Identifier nm = name.getName(); |
| 253 | // Members that are nested classes are not created with 'defineField', |
| 254 | // so these transformations do not apply to them. See 'beginClass' above. |
| 255 | if (sourceClass.isInterface()) { |
| 256 | // Members of interfaces are implicitly public. |
| 257 | if ((mod & (M_PRIVATE | M_PROTECTED)) == 0) |
| 258 | // For interface members, neither 'private' nor 'protected' |
| 259 | // are legal modifiers. Avoid setting M_PUBLIC in some cases |
| 260 | // to avoid interfering with later error detection. This will |
| 261 | // be fixed up after the error is reported. |
| 262 | mod |= M_PUBLIC; |
| 263 | // Methods of interfaces are implicitly abstract. |
| 264 | // Fields of interfaces are implicitly static and final. |
| 265 | if (t.isType(TC_METHOD)) { |
| 266 | mod |= M_ABSTRACT; |
| 267 | } else { |
| 268 | mod |= M_STATIC | M_FINAL; |
| 269 | } |
| 270 | } |
| 271 | if (nm.equals(idInit)) { |
| 272 | // The parser reports "idInit" when in reality it has found |
| 273 | // that there is no method name at all present. |
| 274 | // So, decide if it's really a constructor, or a syntax error. |
| 275 | Type rt = t.getReturnType(); |
| 276 | Identifier retname = !rt.isType(TC_CLASS) ? idStar /*no match*/ |
| 277 | : rt.getClassName(); |
| 278 | Identifier clsname = sourceClass.getLocalName(); |
| 279 | if (clsname.equals(retname)) { |
| 280 | t = Type.tMethod(Type.tVoid, t.getArgumentTypes()); |
| 281 | } else if (clsname.equals(retname.getFlatName().getName())) { |
| 282 | // It appears to be a constructor with spurious qualification. |
| 283 | t = Type.tMethod(Type.tVoid, t.getArgumentTypes()); |
| 284 | env.error(where, "invalid.method.decl.qual"); |
| 285 | } else if (retname.isQualified() || retname.equals(idStar)) { |
| 286 | // It appears to be a type name with no method name. |
| 287 | env.error(where, "invalid.method.decl.name"); |
| 288 | return; |
| 289 | } else { |
| 290 | // We assume the type name is missing, even though the |
| 291 | // simple name that's present might have been intended |
| 292 | // to be a type: "String (){}" vs. "toString(){}". |
| 293 | env.error(where, "invalid.method.decl"); |
| 294 | return; |
| 295 | } |
| 296 | } |
| 297 | |
| 298 | if (args == null && t.isType(TC_METHOD)) { |
| 299 | args = new IdentifierToken[0]; |
| 300 | } |
| 301 | |
| 302 | if (exp == null && t.isType(TC_METHOD)) { |
| 303 | exp = new IdentifierToken[0]; |
| 304 | } |
| 305 | |
| 306 | MemberDefinition f = env.makeMemberDefinition(env, where, sourceClass, |
| 307 | doc, mod, t, nm, |
| 308 | args, exp, val); |
| 309 | if (env.dump()) { |
| 310 | f.print(System.out); |
| 311 | } |
| 312 | } |
| 313 | } |