| /* |
| * Copyright (c) 1994, 2004, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| package sun.tools.javac; |
| |
| import sun.tools.java.*; |
| import sun.tools.tree.*; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.util.Vector; |
| import java.util.Enumeration; |
| |
| /** |
| * Batch file parser, this needs more work. |
| * |
| * WARNING: The contents of this source file are not part of any |
| * supported API. Code that depends on them does so at its own risk: |
| * they are subject to change or removal without notice. |
| */ |
| @Deprecated |
| public |
| class BatchParser extends Parser { |
| /** |
| * The current package |
| */ |
| protected Identifier pkg; |
| |
| /** |
| * The current imports |
| */ |
| protected Imports imports; |
| |
| /** |
| * The classes defined in this file |
| */ |
| protected Vector<SourceClass> classes; |
| |
| |
| /** |
| * The current class |
| */ |
| protected SourceClass sourceClass; |
| |
| /** |
| * The toplevel environment |
| */ |
| protected Environment toplevelEnv; |
| |
| /** |
| * Create a batch file parser |
| */ |
| public BatchParser(Environment env, InputStream in) throws IOException { |
| super(env, in); |
| |
| imports = new Imports(env); |
| classes = new Vector<>(); |
| toplevelEnv = imports.newEnvironment(env); |
| } |
| |
| /** |
| * Package declaration |
| */ |
| public void packageDeclaration(long where, IdentifierToken t) { |
| Identifier nm = t.getName(); |
| //System.out.println("package " + nm); |
| if (pkg == null) { |
| // This code has been changed to pass an IdentifierToken, |
| // rather than an Identifier, to setCurrentPackage(). Imports |
| // now needs the location of the token. |
| pkg = t.getName(); |
| imports.setCurrentPackage(t); |
| } else { |
| env.error(where, "package.repeated"); |
| } |
| } |
| |
| /** |
| * Import class |
| */ |
| public void importClass(long pos, IdentifierToken t) { |
| //System.out.println("import class " + t); |
| imports.addClass(t); |
| } |
| |
| /** |
| * Import package |
| */ |
| public void importPackage(long pos, IdentifierToken t) { |
| //System.out.println("import package " + t); |
| imports.addPackage(t); |
| } |
| |
| /** |
| * Define class |
| */ |
| public ClassDefinition beginClass(long where, String doc, int mod, |
| IdentifierToken t, |
| IdentifierToken sup, |
| IdentifierToken interfaces[]) { |
| |
| // If this class is nested, the modifier bits set here will |
| // be copied into the 'SourceMember' object for the inner class |
| // created during the call to 'makeClassDefinition' below. |
| // When writing the class file, we will look there for the |
| // 'untransformed' modifiers. The modifiers in the ClassDefinition |
| // object will end up as the 'transformed' modifiers. Note that |
| // there are some bits set here that are not legal class modifiers |
| // according to the JVMS, e.g., M_PRIVATE and M_STATIC. These are |
| // masked off while writing the class file, but are preserved in |
| // the InnerClasses attributes. |
| |
| if (tracing) toplevelEnv.dtEnter("beginClass: " + sourceClass); |
| |
| SourceClass outerClass = sourceClass; |
| |
| if (outerClass == null && pkg != null) { |
| t = new IdentifierToken(t.getWhere(), |
| Identifier.lookup(pkg, t.getName())); |
| } |
| |
| // The defaults for anonymous and local classes should be documented! |
| |
| if ((mod & M_ANONYMOUS) != 0) { |
| mod |= (M_FINAL | M_PRIVATE); |
| } |
| if ((mod & M_LOCAL) != 0) { |
| mod |= M_PRIVATE; |
| } |
| |
| // Certain modifiers are implied as follows: |
| // |
| // 1. Any interface (nested or not) is implicitly deemed to be abstract, |
| // whether it is explicitly marked so or not. (Java 1.0.) |
| // 2. A interface which is a member of a type is implicitly deemed to |
| // be static, whether it is explicitly marked so or not. (InnerClasses) |
| // 3a. A type which is a member of an interface is implicitly deemed |
| // to be public, whether it is explicitly marked so or not. (InnerClasses) |
| // 3b. A type which is a member of an interface is implicitly deemed |
| // to be static, whether it is explicitly marked so or not. (InnerClasses) |
| |
| if ((mod & M_INTERFACE) != 0) { |
| // Rule 1. |
| mod |= M_ABSTRACT; |
| if (outerClass != null) { |
| // Rule 2. |
| mod |= M_STATIC; |
| } |
| } |
| |
| if (outerClass != null && outerClass.isInterface()) { |
| // Rule 3a. |
| // For interface members, neither 'private' nor 'protected' |
| // are legal modifiers. We avoid setting M_PUBLIC in some |
| // cases in order to avoid interfering with error detection |
| // and reporting. This is patched up, after reporting an |
| // error, by 'SourceClass.addMember'. |
| if ((mod & (M_PRIVATE | M_PROTECTED)) == 0) |
| mod |= M_PUBLIC; |
| // Rule 3b. |
| mod |= M_STATIC; |
| } |
| |
| // For nested classes, we must transform 'protected' to 'public' |
| // and 'private' to package scope. This must be done later, |
| // because any modifiers set here will be copied into the |
| // 'MemberDefinition' for the nested class, which must represent |
| // the original untransformed modifiers. Also, compile-time |
| // checks should be performed against the actual, untransformed |
| // modifiers. This is in contrast to transformations that implement |
| // implicit modifiers, such as M_STATIC and M_FINAL for fields |
| // of interfaces. |
| |
| sourceClass = (SourceClass) |
| toplevelEnv.makeClassDefinition(toplevelEnv, where, t, |
| doc, mod, sup, |
| interfaces, outerClass); |
| |
| sourceClass.getClassDeclaration().setDefinition(sourceClass, CS_PARSED); |
| env = new Environment(toplevelEnv, sourceClass); |
| |
| if (tracing) toplevelEnv.dtEvent("beginClass: SETTING UP DEPENDENCIES"); |
| |
| // The code which adds artificial dependencies between |
| // classes in the same source file has been moved to |
| // BatchEnvironment#parseFile(). |
| |
| if (tracing) toplevelEnv.dtEvent("beginClass: ADDING TO CLASS LIST"); |
| |
| classes.addElement(sourceClass); |
| |
| if (tracing) toplevelEnv.dtExit("beginClass: " + sourceClass); |
| |
| return sourceClass; |
| } |
| |
| /** |
| * Report the current class under construction. |
| */ |
| public ClassDefinition getCurrentClass() { |
| return sourceClass; |
| } |
| |
| /** |
| * End class |
| */ |
| public void endClass(long where, ClassDefinition c) { |
| |
| if (tracing) toplevelEnv.dtEnter("endClass: " + sourceClass); |
| |
| // c == sourceClass; don't bother to check |
| sourceClass.setEndPosition(where); |
| SourceClass outerClass = (SourceClass) sourceClass.getOuterClass(); |
| sourceClass = outerClass; |
| env = toplevelEnv; |
| if (sourceClass != null) |
| env = new Environment(env, sourceClass); |
| |
| if (tracing) toplevelEnv.dtExit("endClass: " + sourceClass); |
| } |
| |
| /** |
| * Define a method |
| */ |
| public void defineField(long where, ClassDefinition c, |
| String doc, int mod, Type t, |
| IdentifierToken name, IdentifierToken args[], |
| IdentifierToken exp[], Node val) { |
| // c == sourceClass; don't bother to check |
| Identifier nm = name.getName(); |
| // Members that are nested classes are not created with 'defineField', |
| // so these transformations do not apply to them. See 'beginClass' above. |
| if (sourceClass.isInterface()) { |
| // Members of interfaces are implicitly public. |
| if ((mod & (M_PRIVATE | M_PROTECTED)) == 0) |
| // For interface members, neither 'private' nor 'protected' |
| // are legal modifiers. Avoid setting M_PUBLIC in some cases |
| // to avoid interfering with later error detection. This will |
| // be fixed up after the error is reported. |
| mod |= M_PUBLIC; |
| // Methods of interfaces are implicitly abstract. |
| // Fields of interfaces are implicitly static and final. |
| if (t.isType(TC_METHOD)) { |
| mod |= M_ABSTRACT; |
| } else { |
| mod |= M_STATIC | M_FINAL; |
| } |
| } |
| if (nm.equals(idInit)) { |
| // The parser reports "idInit" when in reality it has found |
| // that there is no method name at all present. |
| // So, decide if it's really a constructor, or a syntax error. |
| Type rt = t.getReturnType(); |
| Identifier retname = !rt.isType(TC_CLASS) ? idStar /*no match*/ |
| : rt.getClassName(); |
| Identifier clsname = sourceClass.getLocalName(); |
| if (clsname.equals(retname)) { |
| t = Type.tMethod(Type.tVoid, t.getArgumentTypes()); |
| } else if (clsname.equals(retname.getFlatName().getName())) { |
| // It appears to be a constructor with spurious qualification. |
| t = Type.tMethod(Type.tVoid, t.getArgumentTypes()); |
| env.error(where, "invalid.method.decl.qual"); |
| } else if (retname.isQualified() || retname.equals(idStar)) { |
| // It appears to be a type name with no method name. |
| env.error(where, "invalid.method.decl.name"); |
| return; |
| } else { |
| // We assume the type name is missing, even though the |
| // simple name that's present might have been intended |
| // to be a type: "String (){}" vs. "toString(){}". |
| env.error(where, "invalid.method.decl"); |
| return; |
| } |
| } |
| |
| if (args == null && t.isType(TC_METHOD)) { |
| args = new IdentifierToken[0]; |
| } |
| |
| if (exp == null && t.isType(TC_METHOD)) { |
| exp = new IdentifierToken[0]; |
| } |
| |
| MemberDefinition f = env.makeMemberDefinition(env, where, sourceClass, |
| doc, mod, t, nm, |
| args, exp, val); |
| if (env.dump()) { |
| f.print(System.out); |
| } |
| } |
| } |