feat(jdk8): move files to new folder to avoid resources compiled.
This commit is contained in:
1372
jdkSrc/jdk8/sun/tools/javac/BatchEnvironment.java
Normal file
1372
jdkSrc/jdk8/sun/tools/javac/BatchEnvironment.java
Normal file
File diff suppressed because it is too large
Load Diff
313
jdkSrc/jdk8/sun/tools/javac/BatchParser.java
Normal file
313
jdkSrc/jdk8/sun/tools/javac/BatchParser.java
Normal file
@@ -0,0 +1,313 @@
|
||||
/*
|
||||
* 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 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
67
jdkSrc/jdk8/sun/tools/javac/CompilerMember.java
Normal file
67
jdkSrc/jdk8/sun/tools/javac/CompilerMember.java
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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.asm.Assembler;
|
||||
|
||||
/**
|
||||
* This class is used to represents fields while they are
|
||||
* being compiled
|
||||
*
|
||||
* 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
|
||||
final
|
||||
class CompilerMember implements Comparable {
|
||||
MemberDefinition field;
|
||||
Assembler asm;
|
||||
Object value;
|
||||
String name;
|
||||
String sig;
|
||||
String key;
|
||||
|
||||
CompilerMember(MemberDefinition field, Assembler asm) {
|
||||
this.field = field;
|
||||
this.asm = asm;
|
||||
name = field.getName().toString();
|
||||
sig = field.getType().getTypeSignature();
|
||||
}
|
||||
|
||||
public int compareTo(Object o) {
|
||||
CompilerMember cm = (CompilerMember) o;
|
||||
return getKey().compareTo(cm.getKey());
|
||||
}
|
||||
|
||||
String getKey() {
|
||||
if (key==null)
|
||||
key = name+sig;
|
||||
return key;
|
||||
}
|
||||
|
||||
}
|
||||
42
jdkSrc/jdk8/sun/tools/javac/ErrorConsumer.java
Normal file
42
jdkSrc/jdk8/sun/tools/javac/ErrorConsumer.java
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 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;
|
||||
|
||||
/**
|
||||
* Allows for easier parsing of errors and warnings from the compiler
|
||||
*
|
||||
* 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
|
||||
interface ErrorConsumer {
|
||||
public void pushError(String errorFileName,
|
||||
int line,
|
||||
String message,
|
||||
String referenceText, String referenceTextPointer);
|
||||
};
|
||||
49
jdkSrc/jdk8/sun/tools/javac/ErrorMessage.java
Normal file
49
jdkSrc/jdk8/sun/tools/javac/ErrorMessage.java
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* A sorted list of error messages
|
||||
*
|
||||
* 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
|
||||
final
|
||||
class ErrorMessage {
|
||||
long where;
|
||||
String message;
|
||||
ErrorMessage next;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
ErrorMessage(long where, String message) {
|
||||
this.where = where;
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
751
jdkSrc/jdk8/sun/tools/javac/Main.java
Normal file
751
jdkSrc/jdk8/sun/tools/javac/Main.java
Normal file
@@ -0,0 +1,751 @@
|
||||
/*
|
||||
* 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.util.CommandLine;
|
||||
// JCOV
|
||||
import sun.tools.asm.Assembler;
|
||||
// end JCOV
|
||||
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
import java.text.MessageFormat;
|
||||
|
||||
/**
|
||||
* Main program of the Java compiler
|
||||
*
|
||||
* 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 As of J2SE 1.3, the preferred way to compile Java
|
||||
* language sources is by using the new compiler,
|
||||
* com.sun.tools.javac.Main.
|
||||
*/
|
||||
@Deprecated
|
||||
public
|
||||
class Main implements Constants {
|
||||
/**
|
||||
* Name of the program.
|
||||
*/
|
||||
String program;
|
||||
|
||||
/**
|
||||
* The stream where error message are printed.
|
||||
*/
|
||||
OutputStream out;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public Main(OutputStream out, String program) {
|
||||
this.out = out;
|
||||
this.program = program;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exit status.
|
||||
* We introduce a separate integer status variable, and do not alter the
|
||||
* convention that 'compile' returns a boolean true upon a successful
|
||||
* compilation with no errors. (JavaTest relies on this.)
|
||||
*/
|
||||
|
||||
public static final int EXIT_OK = 0; // Compilation completed with no errors.
|
||||
public static final int EXIT_ERROR = 1; // Compilation completed but reported errors.
|
||||
public static final int EXIT_CMDERR = 2; // Bad command-line arguments and/or switches.
|
||||
public static final int EXIT_SYSERR = 3; // System error or resource exhaustion.
|
||||
public static final int EXIT_ABNORMAL = 4; // Compiler terminated abnormally.
|
||||
|
||||
private int exitStatus;
|
||||
|
||||
public int getExitStatus() {
|
||||
return exitStatus;
|
||||
}
|
||||
|
||||
public boolean compilationPerformedSuccessfully() {
|
||||
return exitStatus == EXIT_OK || exitStatus == EXIT_ERROR;
|
||||
}
|
||||
|
||||
public boolean compilationReportedErrors () {
|
||||
return exitStatus != EXIT_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output a message.
|
||||
*/
|
||||
private void output(String msg) {
|
||||
PrintStream out =
|
||||
this.out instanceof PrintStream ? (PrintStream)this.out
|
||||
: new PrintStream(this.out, true);
|
||||
out.println(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Top level error message. This method is called when the
|
||||
* environment could not be set up yet.
|
||||
*/
|
||||
private void error(String msg) {
|
||||
exitStatus = EXIT_CMDERR;
|
||||
output(getText(msg));
|
||||
}
|
||||
|
||||
private void error(String msg, String arg1) {
|
||||
exitStatus = EXIT_CMDERR;
|
||||
output(getText(msg, arg1));
|
||||
}
|
||||
|
||||
private void error(String msg, String arg1, String arg2) {
|
||||
exitStatus = EXIT_CMDERR;
|
||||
output(getText(msg, arg1, arg2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Print usage message and make exit status an error.
|
||||
* Note: 'javac' invoked without any arguments is considered
|
||||
* be an error.
|
||||
*/
|
||||
public void usage_error() {
|
||||
error("main.usage", program);
|
||||
}
|
||||
|
||||
private static ResourceBundle messageRB;
|
||||
|
||||
/**
|
||||
* Initialize ResourceBundle
|
||||
*/
|
||||
static void initResource() {
|
||||
try {
|
||||
messageRB =
|
||||
ResourceBundle.getBundle("sun.tools.javac.resources.javac");
|
||||
} catch (MissingResourceException e) {
|
||||
throw new Error("Fatal: Resource for javac is missing");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get and format message string from resource
|
||||
*/
|
||||
public static String getText(String key) {
|
||||
return getText(key, (String)null);
|
||||
}
|
||||
|
||||
public static String getText(String key, int num) {
|
||||
return getText(key, Integer.toString(num));
|
||||
}
|
||||
|
||||
public static String getText(String key, String fixed) {
|
||||
return getText(key, fixed, null);
|
||||
}
|
||||
|
||||
public static String getText(String key, String fixed1, String fixed2) {
|
||||
return getText(key, fixed1, fixed2, null);
|
||||
}
|
||||
|
||||
public static String getText(String key, String fixed1,
|
||||
String fixed2, String fixed3) {
|
||||
if (messageRB == null) {
|
||||
initResource();
|
||||
}
|
||||
try {
|
||||
String message = messageRB.getString(key);
|
||||
return MessageFormat.format(message, fixed1, fixed2, fixed3);
|
||||
} catch (MissingResourceException e) {
|
||||
if (fixed1 == null) fixed1 = "null";
|
||||
if (fixed2 == null) fixed2 = "null";
|
||||
if (fixed3 == null) fixed3 = "null";
|
||||
String message = "JAVAC MESSAGE FILE IS BROKEN: key={0}, arguments={1}, {2}, {3}";
|
||||
return MessageFormat.format(message, key, fixed1, fixed2, fixed3);
|
||||
}
|
||||
}
|
||||
|
||||
// What major and minor version numbers to use for the -target flag.
|
||||
// This should grow every time the minor version number accepted by
|
||||
// the VM is incremented.
|
||||
private static final String[] releases = { "1.1", "1.2", "1.3", "1.4" };
|
||||
private static final short[] majorVersions = { 45, 46, 47, 48 };
|
||||
private static final short[] minorVersions = { 3, 0, 0, 0 };
|
||||
|
||||
/**
|
||||
* Run the compiler
|
||||
*/
|
||||
public synchronized boolean compile(String argv[]) {
|
||||
String sourcePathArg = null;
|
||||
String classPathArg = null;
|
||||
String sysClassPathArg = null;
|
||||
String extDirsArg = null;
|
||||
boolean verbosePath = false;
|
||||
|
||||
String targetArg = null;
|
||||
short majorVersion = JAVA_DEFAULT_VERSION;
|
||||
short minorVersion = JAVA_DEFAULT_MINOR_VERSION;
|
||||
|
||||
File destDir = null;
|
||||
//JCOV
|
||||
File covFile = null;
|
||||
String optJcov = "-Xjcov";
|
||||
String optJcovFile = "-Xjcov:file=";
|
||||
//end JCOV
|
||||
int flags = F_WARNINGS | F_DEBUG_LINES | F_DEBUG_SOURCE;
|
||||
long tm = System.currentTimeMillis();
|
||||
Vector v = new Vector();
|
||||
boolean nowrite = false;
|
||||
String props = null;
|
||||
String encoding = null;
|
||||
|
||||
// These flags are used to make sure conflicting -O and -g
|
||||
// options aren't given.
|
||||
String prior_g = null;
|
||||
String prior_O = null;
|
||||
|
||||
exitStatus = EXIT_OK;
|
||||
|
||||
// Pre-process command line for @file arguments
|
||||
try {
|
||||
argv = CommandLine.parse(argv);
|
||||
} catch (FileNotFoundException e) {
|
||||
error("javac.err.cant.read", e.getMessage());
|
||||
System.exit(1);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
// Parse arguments
|
||||
for (int i = 0 ; i < argv.length ; i++) {
|
||||
if (argv[i].equals("-g")) {
|
||||
if (prior_g!=null && !(prior_g.equals("-g")))
|
||||
error("main.conflicting.options", prior_g, "-g");
|
||||
prior_g = "-g";
|
||||
flags |= F_DEBUG_LINES;
|
||||
flags |= F_DEBUG_VARS;
|
||||
flags |= F_DEBUG_SOURCE;
|
||||
} else if (argv[i].equals("-g:none")) {
|
||||
if (prior_g!=null && !(prior_g.equals("-g:none")))
|
||||
error("main.conflicting.options", prior_g, "-g:none");
|
||||
prior_g = "-g:none";
|
||||
flags &= ~F_DEBUG_LINES;
|
||||
flags &= ~F_DEBUG_VARS;
|
||||
flags &= ~F_DEBUG_SOURCE;
|
||||
} else if (argv[i].startsWith("-g:")) {
|
||||
// We choose to have debugging options conflict even
|
||||
// if they amount to the same thing (for example,
|
||||
// -g:source,lines and -g:lines,source). However, multiple
|
||||
// debugging options are allowed if they are textually
|
||||
// identical.
|
||||
if (prior_g!=null && !(prior_g.equals(argv[i])))
|
||||
error("main.conflicting.options", prior_g, argv[i]);
|
||||
prior_g = argv[i];
|
||||
String args = argv[i].substring("-g:".length());
|
||||
flags &= ~F_DEBUG_LINES;
|
||||
flags &= ~F_DEBUG_VARS;
|
||||
flags &= ~F_DEBUG_SOURCE;
|
||||
while (true) {
|
||||
if (args.startsWith("lines")) {
|
||||
flags |= F_DEBUG_LINES;
|
||||
args = args.substring("lines".length());
|
||||
} else if (args.startsWith("vars")) {
|
||||
flags |= F_DEBUG_VARS;
|
||||
args = args.substring("vars".length());
|
||||
} else if (args.startsWith("source")) {
|
||||
flags |= F_DEBUG_SOURCE;
|
||||
args = args.substring("source".length());
|
||||
} else {
|
||||
error("main.bad.debug.option",argv[i]);
|
||||
usage_error();
|
||||
return false; // Stop processing now
|
||||
}
|
||||
if (args.length() == 0) break;
|
||||
if (args.startsWith(","))
|
||||
args = args.substring(",".length());
|
||||
}
|
||||
} else if (argv[i].equals("-O")) {
|
||||
// -O is accepted for backward compatibility, but
|
||||
// is no longer effective. Use the undocumented
|
||||
// -XO option to get the old behavior.
|
||||
if (prior_O!=null && !(prior_O.equals("-O")))
|
||||
error("main.conflicting.options", prior_O, "-O");
|
||||
prior_O = "-O";
|
||||
} else if (argv[i].equals("-nowarn")) {
|
||||
flags &= ~F_WARNINGS;
|
||||
} else if (argv[i].equals("-deprecation")) {
|
||||
flags |= F_DEPRECATION;
|
||||
} else if (argv[i].equals("-verbose")) {
|
||||
flags |= F_VERBOSE;
|
||||
} else if (argv[i].equals("-nowrite")) {
|
||||
nowrite = true;
|
||||
} else if (argv[i].equals("-classpath")) {
|
||||
if ((i + 1) < argv.length) {
|
||||
if (classPathArg!=null) {
|
||||
error("main.option.already.seen","-classpath");
|
||||
}
|
||||
classPathArg = argv[++i];
|
||||
} else {
|
||||
error("main.option.requires.argument","-classpath");
|
||||
usage_error();
|
||||
return false; // Stop processing now
|
||||
}
|
||||
} else if (argv[i].equals("-sourcepath")) {
|
||||
if ((i + 1) < argv.length) {
|
||||
if (sourcePathArg != null) {
|
||||
error("main.option.already.seen","-sourcepath");
|
||||
}
|
||||
sourcePathArg = argv[++i];
|
||||
} else {
|
||||
error("main.option.requires.argument","-sourcepath");
|
||||
usage_error();
|
||||
return false; // Stop processing now
|
||||
}
|
||||
} else if (argv[i].equals("-sysclasspath")) {
|
||||
if ((i + 1) < argv.length) {
|
||||
if (sysClassPathArg != null) {
|
||||
error("main.option.already.seen","-sysclasspath");
|
||||
}
|
||||
sysClassPathArg = argv[++i];
|
||||
} else {
|
||||
error("main.option.requires.argument","-sysclasspath");
|
||||
usage_error();
|
||||
return false; // Stop processing now
|
||||
}
|
||||
} else if (argv[i].equals("-bootclasspath")) {
|
||||
if ((i + 1) < argv.length) {
|
||||
if (sysClassPathArg != null) {
|
||||
error("main.option.already.seen","-bootclasspath");
|
||||
}
|
||||
sysClassPathArg = argv[++i];
|
||||
} else {
|
||||
error("main.option.requires.argument","-bootclasspath");
|
||||
usage_error();
|
||||
return false; // Stop processing now
|
||||
}
|
||||
} else if (argv[i].equals("-extdirs")) {
|
||||
if ((i + 1) < argv.length) {
|
||||
if (extDirsArg != null) {
|
||||
error("main.option.already.seen","-extdirs");
|
||||
}
|
||||
extDirsArg = argv[++i];
|
||||
} else {
|
||||
error("main.option.requires.argument","-extdirs");
|
||||
usage_error();
|
||||
return false; // Stop processing now
|
||||
}
|
||||
} else if (argv[i].equals("-encoding")) {
|
||||
if ((i + 1) < argv.length) {
|
||||
if (encoding!=null)
|
||||
error("main.option.already.seen","-encoding");
|
||||
encoding = argv[++i];
|
||||
} else {
|
||||
error("main.option.requires.argument","-encoding");
|
||||
usage_error();
|
||||
return false; // Stop processing now
|
||||
}
|
||||
} else if (argv[i].equals("-target")) {
|
||||
if ((i + 1) < argv.length) {
|
||||
if (targetArg!=null)
|
||||
error("main.option.already.seen","-target");
|
||||
targetArg = argv[++i];
|
||||
int j;
|
||||
for (j=0; j<releases.length; j++) {
|
||||
if (releases[j].equals(targetArg)) {
|
||||
majorVersion = majorVersions[j];
|
||||
minorVersion = minorVersions[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j==releases.length) {
|
||||
error("main.unknown.release",targetArg);
|
||||
usage_error();
|
||||
return false; // Stop processing now
|
||||
}
|
||||
} else {
|
||||
error("main.option.requires.argument","-target");
|
||||
usage_error();
|
||||
return false; // Stop processing now
|
||||
}
|
||||
} else if (argv[i].equals("-d")) {
|
||||
if ((i + 1) < argv.length) {
|
||||
if (destDir!=null)
|
||||
error("main.option.already.seen","-d");
|
||||
destDir = new File(argv[++i]);
|
||||
if (!destDir.exists()) {
|
||||
error("main.no.such.directory",destDir.getPath());
|
||||
usage_error();
|
||||
return false; // Stop processing now
|
||||
}
|
||||
} else {
|
||||
error("main.option.requires.argument","-d");
|
||||
usage_error();
|
||||
return false; // Stop processing now
|
||||
}
|
||||
// JCOV
|
||||
} else if (argv[i].equals(optJcov)) {
|
||||
flags |= F_COVERAGE;
|
||||
flags &= ~F_OPT;
|
||||
flags &= ~F_OPT_INTERCLASS;
|
||||
} else if ((argv[i].startsWith(optJcovFile)) &&
|
||||
(argv[i].length() > optJcovFile.length())) {
|
||||
covFile = new File(argv[i].substring(optJcovFile.length()));
|
||||
flags &= ~F_OPT;
|
||||
flags &= ~F_OPT_INTERCLASS;
|
||||
flags |= F_COVERAGE;
|
||||
flags |= F_COVDATA;
|
||||
// end JCOV
|
||||
} else if (argv[i].equals("-XO")) {
|
||||
// This is what -O used to be. Now undocumented.
|
||||
if (prior_O!=null && !(prior_O.equals("-XO")))
|
||||
error("main.conflicting.options", prior_O, "-XO");
|
||||
prior_O = "-XO";
|
||||
flags |= F_OPT;
|
||||
} else if (argv[i].equals("-Xinterclass")) {
|
||||
if (prior_O!=null && !(prior_O.equals("-Xinterclass")))
|
||||
error("main.conflicting.options", prior_O, "-Xinterclass");
|
||||
prior_O = "-Xinterclass";
|
||||
flags |= F_OPT;
|
||||
flags |= F_OPT_INTERCLASS;
|
||||
flags |= F_DEPENDENCIES;
|
||||
} else if (argv[i].equals("-Xdepend")) {
|
||||
flags |= F_DEPENDENCIES;
|
||||
} else if (argv[i].equals("-Xdebug")) {
|
||||
flags |= F_DUMP;
|
||||
// Unadvertised option used by JWS. The non-X version should
|
||||
// be removed, but we'll leave it in until we find out for
|
||||
// sure that no one still depends on that option syntax.
|
||||
} else if (argv[i].equals("-xdepend") || argv[i].equals("-Xjws")) {
|
||||
flags |= F_PRINT_DEPENDENCIES;
|
||||
// change the default output in this case:
|
||||
if (out == System.err) {
|
||||
out = System.out;
|
||||
}
|
||||
} else if (argv[i].equals("-Xstrictdefault")) {
|
||||
// Make strict floating point the default
|
||||
flags |= F_STRICTDEFAULT;
|
||||
} else if (argv[i].equals("-Xverbosepath")) {
|
||||
verbosePath = true;
|
||||
} else if (argv[i].equals("-Xstdout")) {
|
||||
out = System.out;
|
||||
} else if (argv[i].equals("-X")) {
|
||||
error("main.unsupported.usage");
|
||||
return false; // Stop processing now
|
||||
} else if (argv[i].equals("-Xversion1.2")) {
|
||||
// Inform the compiler that it need not target VMs
|
||||
// earlier than version 1.2. This option is here
|
||||
// for testing purposes only. It is deliberately
|
||||
// kept orthogonal to the -target option in 1.2.0
|
||||
// for the sake of stability. These options will
|
||||
// be merged in a future release.
|
||||
flags |= F_VERSION12;
|
||||
} else if (argv[i].endsWith(".java")) {
|
||||
v.addElement(argv[i]);
|
||||
} else {
|
||||
error("main.no.such.option",argv[i]);
|
||||
usage_error();
|
||||
return false; // Stop processing now
|
||||
}
|
||||
}
|
||||
if (v.size() == 0 || exitStatus == EXIT_CMDERR) {
|
||||
usage_error();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create our Environment.
|
||||
BatchEnvironment env = BatchEnvironment.create(out,
|
||||
sourcePathArg,
|
||||
classPathArg,
|
||||
sysClassPathArg,
|
||||
extDirsArg);
|
||||
if (verbosePath) {
|
||||
output(getText("main.path.msg",
|
||||
env.sourcePath.toString(),
|
||||
env.binaryPath.toString()));
|
||||
}
|
||||
|
||||
env.flags |= flags;
|
||||
env.majorVersion = majorVersion;
|
||||
env.minorVersion = minorVersion;
|
||||
// JCOV
|
||||
env.covFile = covFile;
|
||||
// end JCOV
|
||||
env.setCharacterEncoding(encoding);
|
||||
|
||||
// Preload the "out of memory" error string just in case we run
|
||||
// out of memory during the compile.
|
||||
String noMemoryErrorString = getText("main.no.memory");
|
||||
String stackOverflowErrorString = getText("main.stack.overflow");
|
||||
|
||||
env.error(0, "warn.class.is.deprecated", "sun.tools.javac.Main");
|
||||
|
||||
try {
|
||||
// Parse all input files
|
||||
for (Enumeration e = v.elements() ; e.hasMoreElements() ;) {
|
||||
File file = new File((String)e.nextElement());
|
||||
try {
|
||||
env.parseFile(new ClassFile(file));
|
||||
} catch (FileNotFoundException ee) {
|
||||
env.error(0, "cant.read", file.getPath());
|
||||
exitStatus = EXIT_CMDERR;
|
||||
}
|
||||
}
|
||||
|
||||
// Do a post-read check on all newly-parsed classes,
|
||||
// after they have all been read.
|
||||
for (Enumeration e = env.getClasses() ; e.hasMoreElements() ; ) {
|
||||
ClassDeclaration c = (ClassDeclaration)e.nextElement();
|
||||
if (c.getStatus() == CS_PARSED) {
|
||||
if (c.getClassDefinition().isLocal())
|
||||
continue;
|
||||
try {
|
||||
c.getClassDefinition(env);
|
||||
} catch (ClassNotFound ee) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// compile all classes that need compilation
|
||||
ByteArrayOutputStream buf = new ByteArrayOutputStream(4096);
|
||||
boolean done;
|
||||
|
||||
do {
|
||||
done = true;
|
||||
env.flushErrors();
|
||||
for (Enumeration e = env.getClasses() ; e.hasMoreElements() ; ) {
|
||||
ClassDeclaration c = (ClassDeclaration)e.nextElement();
|
||||
SourceClass src;
|
||||
|
||||
switch (c.getStatus()) {
|
||||
case CS_UNDEFINED:
|
||||
if (!env.dependencies()) {
|
||||
break;
|
||||
}
|
||||
// fall through
|
||||
|
||||
case CS_SOURCE:
|
||||
if (tracing)
|
||||
env.dtEvent("Main.compile (SOURCE): loading, " + c);
|
||||
done = false;
|
||||
env.loadDefinition(c);
|
||||
if (c.getStatus() != CS_PARSED) {
|
||||
if (tracing)
|
||||
env.dtEvent("Main.compile (SOURCE): not parsed, " + c);
|
||||
break;
|
||||
}
|
||||
// fall through
|
||||
|
||||
case CS_PARSED:
|
||||
if (c.getClassDefinition().isInsideLocal()) {
|
||||
// the enclosing block will check this one
|
||||
if (tracing)
|
||||
env.dtEvent("Main.compile (PARSED): skipping local class, " + c);
|
||||
continue;
|
||||
}
|
||||
done = false;
|
||||
if (tracing) env.dtEvent("Main.compile (PARSED): checking, " + c);
|
||||
src = (SourceClass)c.getClassDefinition(env);
|
||||
src.check(env);
|
||||
c.setDefinition(src, CS_CHECKED);
|
||||
// fall through
|
||||
|
||||
case CS_CHECKED:
|
||||
src = (SourceClass)c.getClassDefinition(env);
|
||||
// bail out if there were any errors
|
||||
if (src.getError()) {
|
||||
if (tracing)
|
||||
env.dtEvent("Main.compile (CHECKED): bailing out on error, " + c);
|
||||
c.setDefinition(src, CS_COMPILED);
|
||||
break;
|
||||
}
|
||||
done = false;
|
||||
buf.reset();
|
||||
if (tracing)
|
||||
env.dtEvent("Main.compile (CHECKED): compiling, " + c);
|
||||
src.compile(buf);
|
||||
c.setDefinition(src, CS_COMPILED);
|
||||
src.cleanup(env);
|
||||
|
||||
if (src.getNestError() || nowrite) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String pkgName = c.getName().getQualifier().toString().replace('.', File.separatorChar);
|
||||
String className = c.getName().getFlatName().toString().replace('.', SIGC_INNERCLASS) + ".class";
|
||||
|
||||
File file;
|
||||
if (destDir != null) {
|
||||
if (pkgName.length() > 0) {
|
||||
file = new File(destDir, pkgName);
|
||||
if (!file.exists()) {
|
||||
file.mkdirs();
|
||||
}
|
||||
file = new File(file, className);
|
||||
} else {
|
||||
file = new File(destDir, className);
|
||||
}
|
||||
} else {
|
||||
ClassFile classfile = (ClassFile)src.getSource();
|
||||
if (classfile.isZipped()) {
|
||||
env.error(0, "cant.write", classfile.getPath());
|
||||
exitStatus = EXIT_CMDERR;
|
||||
continue;
|
||||
}
|
||||
file = new File(classfile.getPath());
|
||||
file = new File(file.getParent(), className);
|
||||
}
|
||||
|
||||
// Create the file
|
||||
try {
|
||||
FileOutputStream out = new FileOutputStream(file.getPath());
|
||||
buf.writeTo(out);
|
||||
out.close();
|
||||
|
||||
if (env.verbose()) {
|
||||
output(getText("main.wrote", file.getPath()));
|
||||
}
|
||||
} catch (IOException ee) {
|
||||
env.error(0, "cant.write", file.getPath());
|
||||
exitStatus = EXIT_CMDERR;
|
||||
}
|
||||
|
||||
// Print class dependencies if requested (-xdepend)
|
||||
if (env.print_dependencies()) {
|
||||
src.printClassDependencies(env);
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (!done);
|
||||
} catch (OutOfMemoryError ee) {
|
||||
// The compiler has run out of memory. Use the error string
|
||||
// which we preloaded.
|
||||
env.output(noMemoryErrorString);
|
||||
exitStatus = EXIT_SYSERR;
|
||||
return false;
|
||||
} catch (StackOverflowError ee) {
|
||||
env.output(stackOverflowErrorString);
|
||||
exitStatus = EXIT_SYSERR;
|
||||
return false;
|
||||
} catch (Error ee) {
|
||||
// We allow the compiler to take an exception silently if a program
|
||||
// error has previously been detected. Presumably, this makes the
|
||||
// compiler more robust in the face of bad error recovery.
|
||||
if (env.nerrors == 0 || env.dump()) {
|
||||
ee.printStackTrace();
|
||||
env.error(0, "fatal.error");
|
||||
exitStatus = EXIT_ABNORMAL;
|
||||
}
|
||||
} catch (Exception ee) {
|
||||
if (env.nerrors == 0 || env.dump()) {
|
||||
ee.printStackTrace();
|
||||
env.error(0, "fatal.exception");
|
||||
exitStatus = EXIT_ABNORMAL;
|
||||
}
|
||||
}
|
||||
|
||||
int ndepfiles = env.deprecationFiles.size();
|
||||
if (ndepfiles > 0 && env.warnings()) {
|
||||
int ndeps = env.ndeprecations;
|
||||
Object file1 = env.deprecationFiles.elementAt(0);
|
||||
if (env.deprecation()) {
|
||||
if (ndepfiles > 1) {
|
||||
env.error(0, "warn.note.deprecations",
|
||||
new Integer(ndepfiles), new Integer(ndeps));
|
||||
} else {
|
||||
env.error(0, "warn.note.1deprecation",
|
||||
file1, new Integer(ndeps));
|
||||
}
|
||||
} else {
|
||||
if (ndepfiles > 1) {
|
||||
env.error(0, "warn.note.deprecations.silent",
|
||||
new Integer(ndepfiles), new Integer(ndeps));
|
||||
} else {
|
||||
env.error(0, "warn.note.1deprecation.silent",
|
||||
file1, new Integer(ndeps));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
env.flushErrors();
|
||||
env.shutdown();
|
||||
|
||||
boolean status = true;
|
||||
if (env.nerrors > 0) {
|
||||
String msg = "";
|
||||
if (env.nerrors > 1) {
|
||||
msg = getText("main.errors", env.nerrors);
|
||||
} else {
|
||||
msg = getText("main.1error");
|
||||
}
|
||||
if (env.nwarnings > 0) {
|
||||
if (env.nwarnings > 1) {
|
||||
msg += ", " + getText("main.warnings", env.nwarnings);
|
||||
} else {
|
||||
msg += ", " + getText("main.1warning");
|
||||
}
|
||||
}
|
||||
output(msg);
|
||||
if (exitStatus == EXIT_OK) {
|
||||
// Allow EXIT_CMDERR or EXIT_ABNORMAL to take precedence.
|
||||
exitStatus = EXIT_ERROR;
|
||||
}
|
||||
status = false;
|
||||
} else {
|
||||
if (env.nwarnings > 0) {
|
||||
if (env.nwarnings > 1) {
|
||||
output(getText("main.warnings", env.nwarnings));
|
||||
} else {
|
||||
output(getText("main.1warning"));
|
||||
}
|
||||
}
|
||||
}
|
||||
//JCOV
|
||||
if (env.covdata()) {
|
||||
Assembler CovAsm = new Assembler();
|
||||
CovAsm.GenJCov(env);
|
||||
}
|
||||
// end JCOV
|
||||
|
||||
// We're done
|
||||
if (env.verbose()) {
|
||||
tm = System.currentTimeMillis() - tm;
|
||||
output(getText("main.done_in", Long.toString(tm)));
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Main program
|
||||
*/
|
||||
public static void main(String argv[]) {
|
||||
OutputStream out = System.err;
|
||||
|
||||
// This is superceeded by the -Xstdout option, but we leave
|
||||
// in the old property check for compatibility.
|
||||
if (Boolean.getBoolean("javac.pipe.output")) {
|
||||
out = System.out;
|
||||
}
|
||||
|
||||
Main compiler = new Main(out, "javac");
|
||||
System.exit(compiler.compile(argv) ? 0 : compiler.exitStatus);
|
||||
}
|
||||
}
|
||||
2674
jdkSrc/jdk8/sun/tools/javac/SourceClass.java
Normal file
2674
jdkSrc/jdk8/sun/tools/javac/SourceClass.java
Normal file
File diff suppressed because it is too large
Load Diff
907
jdkSrc/jdk8/sun/tools/javac/SourceMember.java
Normal file
907
jdkSrc/jdk8/sun/tools/javac/SourceMember.java
Normal file
@@ -0,0 +1,907 @@
|
||||
/*
|
||||
* 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 sun.tools.asm.*;
|
||||
import java.util.Vector;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
import java.io.PrintStream;
|
||||
|
||||
/**
|
||||
* A Source Member
|
||||
*
|
||||
* 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 SourceMember extends MemberDefinition implements Constants {
|
||||
/**
|
||||
* The argument names (if it is a method)
|
||||
*/
|
||||
Vector args;
|
||||
|
||||
// set to the MemberDefinition in the interface if we have this field because
|
||||
// it has been forced on us
|
||||
MemberDefinition abstractSource;
|
||||
|
||||
/**
|
||||
* The status of the field
|
||||
*/
|
||||
int status;
|
||||
|
||||
static final int PARSED = 0;
|
||||
static final int CHECKING = 1;
|
||||
static final int CHECKED = 2;
|
||||
static final int INLINING = 3;
|
||||
static final int INLINED = 4;
|
||||
static final int ERROR = 5;
|
||||
|
||||
public Vector getArguments() {
|
||||
return args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param argNames a vector of IdentifierToken
|
||||
*/
|
||||
public SourceMember(long where, ClassDefinition clazz,
|
||||
String doc, int modifiers, Type type,
|
||||
Identifier name, Vector argNames,
|
||||
IdentifierToken exp[], Node value) {
|
||||
super(where, clazz, modifiers, type, name, exp, value);
|
||||
this.documentation = doc;
|
||||
this.args = argNames; // for the moment
|
||||
// not until type names are resolved: createArgumentFields(argNames);
|
||||
|
||||
if (ClassDefinition.containsDeprecated(documentation)) {
|
||||
this.modifiers |= M_DEPRECATED;
|
||||
}
|
||||
}
|
||||
|
||||
void createArgumentFields(Vector argNames) {
|
||||
// Create a list of arguments
|
||||
if (isMethod()) {
|
||||
args = new Vector();
|
||||
|
||||
if (isConstructor() || !(isStatic() || isInitializer())) {
|
||||
args.addElement(((SourceClass)clazz).getThisArgument());
|
||||
}
|
||||
|
||||
if (argNames != null) {
|
||||
Enumeration e = argNames.elements();
|
||||
Type argTypes[] = getType().getArgumentTypes();
|
||||
for (int i = 0 ; i < argTypes.length ; i++) {
|
||||
Object x = e.nextElement();
|
||||
if (x instanceof LocalMember) {
|
||||
// This should not happen, but it does
|
||||
// in cases of vicious cyclic inheritance.
|
||||
args = argNames;
|
||||
return;
|
||||
}
|
||||
Identifier id;
|
||||
int mod;
|
||||
long where;
|
||||
if (x instanceof Identifier) {
|
||||
// allow argNames to be simple Identifiers (deprecated!)
|
||||
id = (Identifier)x;
|
||||
mod = 0;
|
||||
where = getWhere();
|
||||
} else {
|
||||
IdentifierToken token = (IdentifierToken)x;
|
||||
id = token.getName();
|
||||
mod = token.getModifiers();
|
||||
where = token.getWhere();
|
||||
}
|
||||
args.addElement(new LocalMember(where, clazz, mod,
|
||||
argTypes[i], id));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The methods addOuterThis() and addUplevelArguments() were
|
||||
// both originally part of a single method called addUplevelArguments()
|
||||
// which took a single boolean parameter describing which of the
|
||||
// two behaviors it wanted.
|
||||
//
|
||||
// The original addUplevelArguments() claimed to keep the arguments in
|
||||
// the following order:
|
||||
//
|
||||
// (1) <this> <early outer this> <uplevel arguments...> <true arguments...>
|
||||
//
|
||||
// (By <early outer this> I am referring to the clientOuterField added
|
||||
// to some constructors when they are created. If an outer this is
|
||||
// added later, on demand, then this is mixed in with the rest of the
|
||||
// uplevel arguments and is added by addUplevelArguments.)
|
||||
//
|
||||
// In reality, the `args' Vector was generated in this order, but the
|
||||
// Type array `argTypes' was generated as:
|
||||
//
|
||||
// (2) <this> <uplevel arguments...> <early outer this> <true arguments...>
|
||||
//
|
||||
// This didn't make a difference in the common case -- that is, when
|
||||
// a class had an <outer.this> or <uplevel arguments...> but not both.
|
||||
// Both can happen in the case that a member class is declared inside
|
||||
// of a local class. It seems that the calling sequences, generated
|
||||
// in places like NewInstanceExpression.codeCommon(), use order (2),
|
||||
// so I have changed the code below to stick with that order. Since
|
||||
// the only time this happens is in classes which are insideLocal, no
|
||||
// one should be able to tell the difference between these orders.
|
||||
// (bug number 4085633)
|
||||
|
||||
LocalMember outerThisArg = null;
|
||||
|
||||
/**
|
||||
* Get outer instance link, or null if none.
|
||||
*/
|
||||
|
||||
public LocalMember getOuterThisArg() {
|
||||
return outerThisArg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the outer.this argument to the list of arguments for this
|
||||
* constructor. This is called from resolveTypeStructure. Any
|
||||
* additional uplevel arguments get added later by addUplevelArguments().
|
||||
*/
|
||||
|
||||
void addOuterThis() {
|
||||
UplevelReference refs = clazz.getReferences();
|
||||
|
||||
// See if we have a client outer field.
|
||||
while (refs != null &&
|
||||
!refs.isClientOuterField()) {
|
||||
refs = refs.getNext();
|
||||
}
|
||||
|
||||
// There is no outer this argument. Quit.
|
||||
if (refs == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the old arg types.
|
||||
Type oldArgTypes[] = type.getArgumentTypes();
|
||||
|
||||
// And make an array for the new ones with space for one more.
|
||||
Type argTypes[] = new Type[oldArgTypes.length + 1];
|
||||
|
||||
LocalMember arg = refs.getLocalArgument();
|
||||
outerThisArg = arg;
|
||||
|
||||
// args is our list of arguments. It contains a `this', so
|
||||
// we insert at position 1. The list of types does not have a
|
||||
// this, so we insert at position 0.
|
||||
args.insertElementAt(arg, 1);
|
||||
argTypes[0] = arg.getType();
|
||||
|
||||
// Add on the rest of the constructor arguments.
|
||||
for (int i = 0; i < oldArgTypes.length; i++) {
|
||||
argTypes[i + 1] = oldArgTypes[i];
|
||||
}
|
||||
|
||||
type = Type.tMethod(type.getReturnType(), argTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepend argument names and argument types for local variable references.
|
||||
* This information is never seen by the type-check phase,
|
||||
* but it affects code generation, which is the earliest moment
|
||||
* we have comprehensive information on uplevel references.
|
||||
* The code() methods tweaks the constructor calls, prepending
|
||||
* the proper values to the argument list.
|
||||
*/
|
||||
void addUplevelArguments() {
|
||||
UplevelReference refs = clazz.getReferences();
|
||||
clazz.getReferencesFrozen();
|
||||
|
||||
// Count how many uplevels we have to add.
|
||||
int count = 0;
|
||||
for (UplevelReference r = refs; r != null; r = r.getNext()) {
|
||||
if (!r.isClientOuterField()) {
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
// None to add, quit.
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the old argument types.
|
||||
Type oldArgTypes[] = type.getArgumentTypes();
|
||||
|
||||
// Make an array with enough room for the new.
|
||||
Type argTypes[] = new Type[oldArgTypes.length + count];
|
||||
|
||||
// Add all of the late uplevel references to args and argTypes.
|
||||
// Note that they are `off-by-one' because of the `this'.
|
||||
int ins = 0;
|
||||
for (UplevelReference r = refs; r != null; r = r.getNext()) {
|
||||
if (!r.isClientOuterField()) {
|
||||
LocalMember arg = r.getLocalArgument();
|
||||
|
||||
args.insertElementAt(arg, 1 + ins);
|
||||
argTypes[ins] = arg.getType();
|
||||
|
||||
ins++;
|
||||
}
|
||||
}
|
||||
|
||||
// Add the rest of the old arguments.
|
||||
for (int i = 0; i < oldArgTypes.length; i++) {
|
||||
argTypes[ins + i] = oldArgTypes[i];
|
||||
}
|
||||
|
||||
type = Type.tMethod(type.getReturnType(), argTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for an inner class.
|
||||
*/
|
||||
public SourceMember(ClassDefinition innerClass) {
|
||||
super(innerClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* Used only to generate an abstract copy of a method that a class
|
||||
* inherits from an interface
|
||||
*/
|
||||
public SourceMember(MemberDefinition f, ClassDefinition c, Environment env) {
|
||||
this(f.getWhere(), c, f.getDocumentation(),
|
||||
f.getModifiers() | M_ABSTRACT, f.getType(), f.getName(), null,
|
||||
f.getExceptionIds(), null);
|
||||
this.args = f.getArguments();
|
||||
this.abstractSource = f;
|
||||
this.exp = f.getExceptions(env);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get exceptions
|
||||
*/
|
||||
public ClassDeclaration[] getExceptions(Environment env) {
|
||||
if ((!isMethod()) || (exp != null)) {
|
||||
return exp;
|
||||
}
|
||||
if (expIds == null) {
|
||||
// (should not happen)
|
||||
exp = new ClassDeclaration[0];
|
||||
return exp;
|
||||
}
|
||||
// be sure to get the imports right:
|
||||
env = ((SourceClass)getClassDefinition()).setupEnv(env);
|
||||
exp = new ClassDeclaration[expIds.length];
|
||||
for (int i = 0; i < exp.length; i++) {
|
||||
Identifier e = expIds[i].getName();
|
||||
Identifier rexp = getClassDefinition().resolveName(env, e);
|
||||
exp[i] = env.getClassDeclaration(rexp);
|
||||
}
|
||||
return exp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set array of name-resolved exceptions directly, e.g., for access methods.
|
||||
*/
|
||||
public void setExceptions(ClassDeclaration[] exp) {
|
||||
this.exp = exp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve types in a field, after parsing.
|
||||
* @see ClassDefinition.resolveTypeStructure
|
||||
*/
|
||||
|
||||
public boolean resolved = false;
|
||||
|
||||
public void resolveTypeStructure(Environment env) {
|
||||
if (tracing) env.dtEnter("SourceMember.resolveTypeStructure: " + this);
|
||||
|
||||
// A member should only be resolved once. For a constructor, it is imperative
|
||||
// that 'addOuterThis' be called only once, else the outer instance argument may
|
||||
// be inserted into the argument list multiple times.
|
||||
|
||||
if (resolved) {
|
||||
if (tracing) env.dtEvent("SourceMember.resolveTypeStructure: OK " + this);
|
||||
// This case shouldn't be happening. It is the responsibility
|
||||
// of our callers to avoid attempting multiple resolutions of a member.
|
||||
// *** REMOVE FOR SHIPMENT? ***
|
||||
throw new CompilerError("multiple member type resolution");
|
||||
//return;
|
||||
} else {
|
||||
if (tracing) env.dtEvent("SourceMember.resolveTypeStructure: RESOLVING " + this);
|
||||
resolved = true;
|
||||
}
|
||||
|
||||
super.resolveTypeStructure(env);
|
||||
if (isInnerClass()) {
|
||||
ClassDefinition nc = getInnerClass();
|
||||
if (nc instanceof SourceClass && !nc.isLocal()) {
|
||||
((SourceClass)nc).resolveTypeStructure(env);
|
||||
}
|
||||
type = innerClass.getType();
|
||||
} else {
|
||||
// Expand all class names in 'type', including those that are not
|
||||
// fully-qualified or refer to inner classes, into fully-qualified
|
||||
// names. Local and anonymous classes get synthesized names here,
|
||||
// corresponding to the class files that will be generated. This is
|
||||
// currently the only place where 'resolveNames' is used.
|
||||
type = env.resolveNames(getClassDefinition(), type, isSynthetic());
|
||||
|
||||
// do the throws also:
|
||||
getExceptions(env);
|
||||
|
||||
if (isMethod()) {
|
||||
Vector argNames = args; args = null;
|
||||
createArgumentFields(argNames);
|
||||
// Add outer instance argument for constructors.
|
||||
if (isConstructor()) {
|
||||
addOuterThis();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tracing) env.dtExit("SourceMember.resolveTypeStructure: " + this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the class declaration in which the field is actually defined
|
||||
*/
|
||||
public ClassDeclaration getDefiningClassDeclaration() {
|
||||
if (abstractSource == null)
|
||||
return super.getDefiningClassDeclaration();
|
||||
else
|
||||
return abstractSource.getDefiningClassDeclaration();
|
||||
}
|
||||
|
||||
/**
|
||||
* A source field never reports deprecation, since the compiler
|
||||
* allows access to deprecated features that are being compiled
|
||||
* in the same job.
|
||||
*/
|
||||
public boolean reportDeprecated(Environment env) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check this field.
|
||||
* <p>
|
||||
* This is the method which requests checking.
|
||||
* The real work is done by
|
||||
* <tt>Vset check(Environment, Context, Vset)</tt>.
|
||||
*/
|
||||
public void check(Environment env) throws ClassNotFound {
|
||||
if (tracing) env.dtEnter("SourceMember.check: " +
|
||||
getName() + ", status = " + status);
|
||||
// rely on the class to check all fields in the proper order
|
||||
if (status == PARSED) {
|
||||
if (isSynthetic() && getValue() == null) {
|
||||
// break a big cycle for small synthetic variables
|
||||
status = CHECKED;
|
||||
if (tracing)
|
||||
env.dtExit("SourceMember.check: BREAKING CYCLE");
|
||||
return;
|
||||
}
|
||||
if (tracing) env.dtEvent("SourceMember.check: CHECKING CLASS");
|
||||
clazz.check(env);
|
||||
if (status == PARSED) {
|
||||
if (getClassDefinition().getError()) {
|
||||
status = ERROR;
|
||||
} else {
|
||||
if (tracing)
|
||||
env.dtExit("SourceMember.check: CHECK FAILED");
|
||||
throw new CompilerError("check failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tracing) env.dtExit("SourceMember.check: DONE " +
|
||||
getName() + ", status = " + status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check a field.
|
||||
* @param vset tells which uplevel variables are definitely assigned
|
||||
* The vset is also used to track the initialization of blank finals
|
||||
* by whichever fields which are relevant to them.
|
||||
*/
|
||||
public Vset check(Environment env, Context ctx, Vset vset) throws ClassNotFound {
|
||||
if (tracing) env.dtEvent("SourceMember.check: MEMBER " +
|
||||
getName() + ", status = " + status);
|
||||
if (status == PARSED) {
|
||||
if (isInnerClass()) {
|
||||
// some classes are checked separately
|
||||
ClassDefinition nc = getInnerClass();
|
||||
if (nc instanceof SourceClass && !nc.isLocal()
|
||||
&& nc.isInsideLocal()) {
|
||||
status = CHECKING;
|
||||
vset = ((SourceClass)nc).checkInsideClass(env, ctx, vset);
|
||||
}
|
||||
status = CHECKED;
|
||||
return vset;
|
||||
}
|
||||
if (env.dump()) {
|
||||
System.out.println("[check field " + getClassDeclaration().getName() + "." + getName() + "]");
|
||||
if (getValue() != null) {
|
||||
getValue().print(System.out);
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
env = new Environment(env, this);
|
||||
|
||||
// This is where all checking of names appearing within the type
|
||||
// of the member is done. Includes return type and argument types.
|
||||
// Since only one location ('where') for error messages is provided,
|
||||
// localization of errors is poor. Throws clauses are handled below.
|
||||
env.resolve(where, getClassDefinition(), getType());
|
||||
|
||||
// Make sure that all the classes that we claim to throw really
|
||||
// are subclasses of Throwable, and are classes that we can reach
|
||||
if (isMethod()) {
|
||||
ClassDeclaration throwable =
|
||||
env.getClassDeclaration(idJavaLangThrowable);
|
||||
ClassDeclaration exp[] = getExceptions(env);
|
||||
for (int i = 0 ; i < exp.length ; i++) {
|
||||
ClassDefinition def;
|
||||
long where = getWhere();
|
||||
if (expIds != null && i < expIds.length) {
|
||||
where = IdentifierToken.getWhere(expIds[i], where);
|
||||
}
|
||||
try {
|
||||
def = exp[i].getClassDefinition(env);
|
||||
|
||||
// Validate access for all inner-class components
|
||||
// of a qualified name, not just the last one, which
|
||||
// is checked below. Yes, this is a dirty hack...
|
||||
// Part of fix for 4094658.
|
||||
env.resolveByName(where, getClassDefinition(), def.getName());
|
||||
|
||||
} catch (ClassNotFound e) {
|
||||
env.error(where, "class.not.found", e.name, "throws");
|
||||
break;
|
||||
}
|
||||
def.noteUsedBy(getClassDefinition(), where, env);
|
||||
if (!getClassDefinition().
|
||||
canAccess(env, def.getClassDeclaration())) {
|
||||
env.error(where, "cant.access.class", def);
|
||||
} else if (!def.subClassOf(env, throwable)) {
|
||||
env.error(where, "throws.not.throwable", def);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
status = CHECKING;
|
||||
|
||||
if (isMethod() && args != null) {
|
||||
int length = args.size();
|
||||
outer_loop:
|
||||
for (int i = 0; i < length; i++) {
|
||||
LocalMember lf = (LocalMember)(args.elementAt(i));
|
||||
Identifier name_i = lf.getName();
|
||||
for (int j = i + 1; j < length; j++) {
|
||||
LocalMember lf2 = (LocalMember)(args.elementAt(j));
|
||||
Identifier name_j = lf2.getName();
|
||||
if (name_i.equals(name_j)) {
|
||||
env.error(lf2.getWhere(), "duplicate.argument",
|
||||
name_i);
|
||||
break outer_loop;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (getValue() != null) {
|
||||
ctx = new Context(ctx, this);
|
||||
|
||||
if (isMethod()) {
|
||||
Statement s = (Statement)getValue();
|
||||
// initialize vset, indication that each of the arguments
|
||||
// to the function has a value
|
||||
|
||||
for (Enumeration e = args.elements(); e.hasMoreElements();){
|
||||
LocalMember f = (LocalMember)e.nextElement();
|
||||
vset.addVar(ctx.declare(env, f));
|
||||
}
|
||||
|
||||
if (isConstructor()) {
|
||||
// Undefine "this" in some constructors, until after
|
||||
// the super constructor has been called.
|
||||
vset.clearVar(ctx.getThisNumber());
|
||||
|
||||
// If the first thing in the definition isn't a call
|
||||
// to either super() or this(), then insert one.
|
||||
Expression supCall = s.firstConstructor();
|
||||
if ((supCall == null)
|
||||
&& (getClassDefinition().getSuperClass() != null)) {
|
||||
supCall = getDefaultSuperCall(env);
|
||||
Statement scs = new ExpressionStatement(where,
|
||||
supCall);
|
||||
s = Statement.insertStatement(scs, s);
|
||||
setValue(s);
|
||||
}
|
||||
}
|
||||
|
||||
//System.out.println("VSET = " + vset);
|
||||
ClassDeclaration exp[] = getExceptions(env);
|
||||
int htsize = (exp.length > 3) ? 17 : 7;
|
||||
Hashtable thrown = new Hashtable(htsize);
|
||||
|
||||
vset = s.checkMethod(env, ctx, vset, thrown);
|
||||
|
||||
ClassDeclaration ignore1 =
|
||||
env.getClassDeclaration(idJavaLangError);
|
||||
ClassDeclaration ignore2 =
|
||||
env.getClassDeclaration(idJavaLangRuntimeException);
|
||||
|
||||
for (Enumeration e = thrown.keys(); e.hasMoreElements();) {
|
||||
ClassDeclaration c = (ClassDeclaration)e.nextElement();
|
||||
ClassDefinition def = c.getClassDefinition(env);
|
||||
if (def.subClassOf(env, ignore1)
|
||||
|| def.subClassOf(env, ignore2)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
boolean ok = false;
|
||||
if (!isInitializer()) {
|
||||
for (int i = 0 ; i < exp.length ; i++) {
|
||||
if (def.subClassOf(env, exp[i])) {
|
||||
ok = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!ok) {
|
||||
Node n = (Node)thrown.get(c);
|
||||
long where = n.getWhere();
|
||||
String errorMsg;
|
||||
|
||||
if (isConstructor()) {
|
||||
if (where ==
|
||||
getClassDefinition().getWhere()) {
|
||||
|
||||
// If this message is being generated for
|
||||
// a default constructor, we should give
|
||||
// a different error message. Currently
|
||||
// we check for this by seeing if the
|
||||
// constructor has the same "where" as
|
||||
// its class. This is a bit kludgy, but
|
||||
// works. (bug id 4034836)
|
||||
errorMsg = "def.constructor.exception";
|
||||
} else {
|
||||
// Constructor with uncaught exception.
|
||||
errorMsg = "constructor.exception";
|
||||
}
|
||||
} else if (isInitializer()) {
|
||||
// Initializer with uncaught exception.
|
||||
errorMsg = "initializer.exception";
|
||||
} else {
|
||||
// Method with uncaught exception.
|
||||
errorMsg = "uncaught.exception";
|
||||
}
|
||||
env.error(where, errorMsg, c.getName());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Hashtable thrown = new Hashtable(3); // small & throw-away
|
||||
Expression val = (Expression)getValue();
|
||||
|
||||
vset = val.checkInitializer(env, ctx, vset,
|
||||
getType(), thrown);
|
||||
setValue(val.convert(env, ctx, getType(), val));
|
||||
|
||||
// Complain about static final members of inner classes that
|
||||
// do not have an initializer that is a constant expression.
|
||||
// In general, static members are not permitted for inner
|
||||
// classes, but an exception is made for named constants.
|
||||
// Other cases of static members, including non-final ones,
|
||||
// are handled in 'SourceClass'. Part of fix for 4095568.
|
||||
if (isStatic() && isFinal() && !clazz.isTopLevel()) {
|
||||
if (!((Expression)getValue()).isConstant()) {
|
||||
env.error(where, "static.inner.field", getName(), this);
|
||||
setValue(null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Both RuntimeExceptions and Errors should be
|
||||
// allowed in initializers. Fix for bug 4102541.
|
||||
ClassDeclaration except =
|
||||
env.getClassDeclaration(idJavaLangThrowable);
|
||||
ClassDeclaration ignore1 =
|
||||
env.getClassDeclaration(idJavaLangError);
|
||||
ClassDeclaration ignore2 =
|
||||
env.getClassDeclaration(idJavaLangRuntimeException);
|
||||
|
||||
for (Enumeration e = thrown.keys(); e.hasMoreElements(); ) {
|
||||
ClassDeclaration c = (ClassDeclaration)e.nextElement();
|
||||
ClassDefinition def = c.getClassDefinition(env);
|
||||
|
||||
if (!def.subClassOf(env, ignore1)
|
||||
&& !def.subClassOf(env, ignore2)
|
||||
&& def.subClassOf(env, except)) {
|
||||
Node n = (Node)thrown.get(c);
|
||||
env.error(n.getWhere(),
|
||||
"initializer.exception", c.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (env.dump()) {
|
||||
getValue().print(System.out);
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
status = getClassDefinition().getError() ? ERROR : CHECKED;
|
||||
}
|
||||
|
||||
|
||||
// Initializers (static and instance) must be able to complete normally.
|
||||
if (isInitializer() && vset.isDeadEnd()) {
|
||||
env.error(where, "init.no.normal.completion");
|
||||
vset = vset.clearDeadEnd();
|
||||
}
|
||||
|
||||
return vset;
|
||||
}
|
||||
|
||||
// helper to check(): synthesize a missing super() call
|
||||
private Expression getDefaultSuperCall(Environment env) {
|
||||
Expression se = null;
|
||||
ClassDefinition sclass = getClassDefinition().getSuperClass().getClassDefinition();
|
||||
// does the superclass constructor require an enclosing instance?
|
||||
ClassDefinition reqc = (sclass == null) ? null
|
||||
: sclass.isTopLevel() ? null
|
||||
: sclass.getOuterClass();
|
||||
ClassDefinition thisc = getClassDefinition();
|
||||
if (reqc != null && !Context.outerLinkExists(env, reqc, thisc)) {
|
||||
se = new SuperExpression(where, new NullExpression(where));
|
||||
env.error(where, "no.default.outer.arg", reqc, getClassDefinition());
|
||||
}
|
||||
if (se == null) {
|
||||
se = new SuperExpression(where);
|
||||
}
|
||||
return new MethodExpression(where, se, idInit, new Expression[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inline the field
|
||||
*/
|
||||
void inline(Environment env) throws ClassNotFound {
|
||||
switch (status) {
|
||||
case PARSED:
|
||||
check(env);
|
||||
inline(env);
|
||||
break;
|
||||
|
||||
case CHECKED:
|
||||
if (env.dump()) {
|
||||
System.out.println("[inline field " + getClassDeclaration().getName() + "." + getName() + "]");
|
||||
}
|
||||
status = INLINING;
|
||||
env = new Environment(env, this);
|
||||
|
||||
if (isMethod()) {
|
||||
if ((!isNative()) && (!isAbstract())) {
|
||||
Statement s = (Statement)getValue();
|
||||
Context ctx = new Context((Context)null, this);
|
||||
for (Enumeration e = args.elements() ; e.hasMoreElements() ;) {
|
||||
LocalMember local = (LocalMember)e.nextElement();
|
||||
ctx.declare(env, local);
|
||||
}
|
||||
setValue(s.inline(env, ctx));
|
||||
}
|
||||
} else if (isInnerClass()) {
|
||||
// some classes are checked and inlined separately
|
||||
ClassDefinition nc = getInnerClass();
|
||||
if (nc instanceof SourceClass && !nc.isLocal()
|
||||
&& nc.isInsideLocal()) {
|
||||
status = INLINING;
|
||||
((SourceClass)nc).inlineLocalClass(env);
|
||||
}
|
||||
status = INLINED;
|
||||
break;
|
||||
} else {
|
||||
if (getValue() != null) {
|
||||
Context ctx = new Context((Context)null, this);
|
||||
if (!isStatic()) {
|
||||
// Cf. "thisArg" in SourceClass.checkMembers().
|
||||
Context ctxInst = new Context(ctx, this);
|
||||
LocalMember thisArg =
|
||||
((SourceClass)clazz).getThisArgument();
|
||||
ctxInst.declare(env, thisArg);
|
||||
setValue(((Expression)getValue())
|
||||
.inlineValue(env, ctxInst));
|
||||
} else {
|
||||
setValue(((Expression)getValue())
|
||||
.inlineValue(env, ctx));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (env.dump()) {
|
||||
System.out.println("[inlined field " + getClassDeclaration().getName() + "." + getName() + "]");
|
||||
if (getValue() != null) {
|
||||
getValue().print(System.out);
|
||||
System.out.println();
|
||||
} else {
|
||||
System.out.println("<empty>");
|
||||
}
|
||||
}
|
||||
status = INLINED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the field (or null if the value can't be determined)
|
||||
*/
|
||||
public Node getValue(Environment env) throws ClassNotFound {
|
||||
Node value = getValue();
|
||||
if (value != null && status != INLINED) {
|
||||
// be sure to get the imports right:
|
||||
env = ((SourceClass)clazz).setupEnv(env);
|
||||
inline(env);
|
||||
value = (status == INLINED) ? getValue() : null;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public boolean isInlineable(Environment env, boolean fromFinal) throws ClassNotFound {
|
||||
if (super.isInlineable(env, fromFinal)) {
|
||||
getValue(env);
|
||||
return (status == INLINED) && !getClassDefinition().getError();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the initial value of the field
|
||||
*/
|
||||
public Object getInitialValue() {
|
||||
if (isMethod() || (getValue() == null) || (!isFinal()) || (status != INLINED)) {
|
||||
return null;
|
||||
}
|
||||
return ((Expression)getValue()).getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate code
|
||||
*/
|
||||
public void code(Environment env, Assembler asm) throws ClassNotFound {
|
||||
switch (status) {
|
||||
case PARSED:
|
||||
check(env);
|
||||
code(env, asm);
|
||||
return;
|
||||
|
||||
case CHECKED:
|
||||
inline(env);
|
||||
code(env, asm);
|
||||
return;
|
||||
|
||||
case INLINED:
|
||||
// Actually generate code
|
||||
if (env.dump()) {
|
||||
System.out.println("[code field " + getClassDeclaration().getName() + "." + getName() + "]");
|
||||
}
|
||||
if (isMethod() && (!isNative()) && (!isAbstract())) {
|
||||
env = new Environment(env, this);
|
||||
Context ctx = new Context((Context)null, this);
|
||||
Statement s = (Statement)getValue();
|
||||
|
||||
for (Enumeration e = args.elements() ; e.hasMoreElements() ; ) {
|
||||
LocalMember f = (LocalMember)e.nextElement();
|
||||
ctx.declare(env, f);
|
||||
//ctx.declare(env, (LocalMember)e.nextElement());
|
||||
}
|
||||
|
||||
/*
|
||||
if (isConstructor() && ((s == null) || (s.firstConstructor() == null))) {
|
||||
ClassDeclaration c = getClassDefinition().getSuperClass();
|
||||
if (c != null) {
|
||||
MemberDefinition field = c.getClassDefinition(env).matchMethod(env, getClassDefinition(), idInit);
|
||||
asm.add(getWhere(), opc_aload, new Integer(0));
|
||||
asm.add(getWhere(), opc_invokespecial, field);
|
||||
asm.add(getWhere(), opc_pop);
|
||||
}
|
||||
|
||||
// Output initialization code
|
||||
for (MemberDefinition f = getClassDefinition().getFirstMember() ; f != null ; f = f.getNextMember()) {
|
||||
if (!f.isStatic()) {
|
||||
f.codeInit(env, ctx, asm);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
if (s != null) {
|
||||
s.code(env, ctx, asm);
|
||||
}
|
||||
if (getType().getReturnType().isType(TC_VOID) && !isInitializer()) {
|
||||
asm.add(getWhere(), opc_return, true);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void codeInit(Environment env, Context ctx, Assembler asm) throws ClassNotFound {
|
||||
if (isMethod()) {
|
||||
return;
|
||||
}
|
||||
switch (status) {
|
||||
case PARSED:
|
||||
check(env);
|
||||
codeInit(env, ctx, asm);
|
||||
return;
|
||||
|
||||
case CHECKED:
|
||||
inline(env);
|
||||
codeInit(env, ctx, asm);
|
||||
return;
|
||||
|
||||
case INLINED:
|
||||
// Actually generate code
|
||||
if (env.dump()) {
|
||||
System.out.println("[code initializer " + getClassDeclaration().getName() + "." + getName() + "]");
|
||||
}
|
||||
if (getValue() != null) {
|
||||
Expression e = (Expression)getValue();
|
||||
// The JLS Section 8.5 specifies that static (non-final)
|
||||
// initializers should be executed in textual order. Eliding
|
||||
// initializations to default values can interfere with this,
|
||||
// so the tests for !e.equalsDefault() have been eliminated,
|
||||
// below.
|
||||
if (isStatic()) {
|
||||
if (getInitialValue() == null) {
|
||||
// removed: && !e.equalsDefault()) {
|
||||
e.codeValue(env, ctx, asm);
|
||||
asm.add(getWhere(), opc_putstatic, this);
|
||||
}
|
||||
} else { // removed: if (!e.equalsDefault()) {
|
||||
// This code doesn't appear to be reached for
|
||||
// instance initializers. Code for these is generated
|
||||
// in the makeVarInits() method of the class
|
||||
// MethodExpression.
|
||||
asm.add(getWhere(), opc_aload, new Integer(0));
|
||||
e.codeValue(env, ctx, asm);
|
||||
asm.add(getWhere(), opc_putfield, this);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print for debugging
|
||||
*/
|
||||
public void print(PrintStream out) {
|
||||
super.print(out);
|
||||
if (getValue() != null) {
|
||||
getValue().print(out);
|
||||
out.println();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user