/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* 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.
*/
//JCOV
//end JCOV
/**
* This class defines the environment for a compilation.
* It is used to load classes, resolve class names and
* report errors. It is an abstract class, a subclass
* must define implementations for some of the functions.<p>
*
* An environment has a source object associated with it.
* This is the thing against which errors are reported, it
* is usually a file name, a field or a class.<p>
*
* Environments can be nested to change the source object.<p>
*
* 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.
*
* @author Arthur van Hoff
*/
/**
* The actual environment to which everything is forwarded.
*/
/**
* External character encoding name
*/
/**
* It is either a file name (String) or a field (MemberDefinition)
* or a class (ClassDeclaration or ClassDefinition).
*/
}
public Environment() {
}
/**
* Tells whether an Identifier refers to a package which should be
* exempt from the "exists" check in Imports#resolve().
*/
}
/**
* Return a class declaration given a fully qualified class name.
*/
}
/**
* Return a class definition given a fully qualified class name.
* <p>
* Should be called only with 'internal' class names, i.e., the result
* of a call to 'resolveName' or a synthetic class name.
*/
while (tail.isQualified()) {
//System.out.println("CLASS: " + c + " HEAD: " + head + " TAIL: " + tail);
// If the name is of the form 'ClassName.N$localName', where N is
// a number, the field 'N$localName' may not necessarily be a member
// of the class named by 'ClassName', but might be a member of some
// inaccessible class contained within it. We use 'getLocalClass'
// to do the lookup in this case. This is part of a fix for bugid
// 4054523 and 4030421. See also 'BatchEnvironment.makeClassDefinition'.
// This should also work for anonymous class names of the form
// 'ClassName.N'. Note that the '.' qualifications get converted to
// '$' characters when determining the external name of the class and
// the name of the class file.
if (localClass != null) {
c = localClass;
continue walkTail;
}
} else {
f != null; f = f.getNextMatch()) {
if (f.isInnerClass()) {
c = f.getInnerClass();
continue walkTail;
}
}
}
}
//System.out.println("FOUND " + c + " FOR " + nm);
return c;
}
}
/**
* Return a class declaration given a type. Only works for
* class types.
*/
return getClassDeclaration(t.getClassName());
}
/**
* Return a class definition given a type. Only works for
* class types.
*/
return getClassDefinition(t.getClassName());
}
/**
* Check if a class exists (without actually loading it).
* (Since inner classes cannot in general be examined without
* loading source, this method does not accept inner names.)
*/
}
}
/**
* Get the package path for a package
*/
}
/**
* Load the definition of a class.
*/
env.loadDefinition(c);
}
/**
*/
return source;
}
/**
* Resolve a type. Make sure that all the classes referred to by
* the type have a definition. Report errors. Return true if
* the type is well-formed. Presently used for types appearing
* in member declarations, which represent named types internally as
* qualified identifiers. Type names appearing in local variable
* declarations and within expressions are represented as identifier
* or field expressions, and are resolved by 'toType', which delegates
* handling of the non-inner portion of the name to this method.
* <p>
* In 'toType', the various stages of qualification are represented by
* separate AST nodes. Here, we are given a single identifier which
* contains the entire qualification structure. It is not possible in
* general to set the error location to the exact position of a component
* that is in error, so an error message must refer to the entire qualified
* name. An attempt to keep track of the string length of the components of
* the name and to offset the location accordingly fails because the initial
* prefix of the name may have been rewritten by an earlier call to
* 'resolveName'. See 'SourceMember.resolveTypeStructure'. The situation
* is actually even worse than this, because only a single location is
* passed in for an entire declaration, which may contain many type names.
* All error messages are thus poorly localized. These checks should be
* done while traversing the parse tree for the type, not the type descriptor.
* <p>
* DESIGN NOTE:
* As far as I can tell, the two-stage resolution of names represented in
* string form is an artifact of the late implementation of inner classes
* and the use of mangled names internally within the compiler. All
* qualified names should have their hiearchical structure made explicit
* in the parse tree at the phase at which they are presented for static
* semantic checking. This would affect class names appearing in 'extends',
* 'implements', and 'throws' clauses, as well as in member declarations.
*/
switch (t.getTypeCode()) {
case TC_CLASS: {
try {
}
// Reported error location may be imprecise
// if the name is qualified.
return true; // return false later
}
} catch (AmbiguousClass ee) {
return false;
} catch (ClassNotFound e) {
// For now, report "class.and.package" only when the code
// is going to fail anyway.
try {
e.name.getTopName());
}
} catch (IOException ee) {
}
// This error message is also emitted for 'new' expressions.
// error(where, "class.not.found", e.name, "declaration");
return false;
}
return true;
}
case TC_ARRAY:
case TC_METHOD:
}
return ok;
}
return true;
}
/**
* Given its fully-qualified name, verify that a class is defined and accessible.
* Used to check components of qualified names in contexts where a class is expected.
* Like 'resolve', but is given a single type name, not a type descriptor.
*/
}
}
try {
}
||
return true; // return false later
}
} catch (AmbiguousClass ee) {
return false;
} catch (ClassNotFound e) {
// For now, report "class.and.package" only when the code
// is going to fail anyway.
try {
e.name.getTopName());
}
} catch (IOException ee) {
}
return false;
}
return true;
}
/**
* Like 'getClassDefinition(env)', but check access on each component.
* Currently called only by 'resolve' above. It is doubtful that calls
* to 'getClassDefinition(env)' are appropriate now.
*/
public final ClassDefinition
boolean isExtends) throws ClassNotFound {
while (tail.isQualified()) {
// System.out.println("CLASS: " + c + " HEAD: " + head + " TAIL: " + tail);
// Handle synthesized names of local and anonymous classes.
// See 'getClassDefinition(env)' above.
if (localClass != null) {
c = localClass;
continue walkTail;
}
} else {
f != null; f = f.getNextMatch()) {
if (f.isInnerClass()) {
c = f.getInnerClass();
// This check is presumably applicable even if the
// original source-code name (expanded by 'resolveNames')
// was a simple, unqualified name. Hopefully, JLS 2e
// will clarify the matter.
if ((!isExtends
||
// Reported error location is imprecise.
}
// The JLS 6.6.2 restrictions on access to protected members
// depend in an essential way upon the syntactic form of the name.
// Since the compiler has previously expanded the class names
// here into fully-qualified form ('resolveNames'), this check
// cannot be performed here. Unfortunately, the original names
// are clobbered during 'basicCheck', which is also the phase that
// resolves the inheritance structure, required to implement the
// access restrictions. Pending a large-scale revision of the
// name-resolution machinery, we forgo this check, with the result
// that the JLS 6.6.2 restrictions are not enforced for some cases
// of qualified access to inner classes. Some qualified names are
// resolved elsewhere via a different mechanism, and will be
// treated correctly -- see 'FieldExpression.checkCommon'.
/*---------------------------------------*
if (f.isProtected()) {
Type rty = Type.tClass(rdecl.getName()); // hack
if (!ctxClass.protectedAccess(env, f, rty)) {
// Reported error location is imprecise.
env.error(where, "invalid.protected.type.use",
head, ctxClass, rty);
}
}
*---------------------------------------*/
continue walkTail;
}
}
}
}
//System.out.println("FOUND " + c + " FOR " + nm);
return c;
}
}
/**
* Resolve the names within a type, returning the adjusted type.
* Adjust class names to reflect scoping.
* Do not report errors.
* <p>
* NOTE: It would be convenient to check for errors here, such as
* verifying that each component of a qualified name exists and is
* accessible. Why must this be done in a separate phase?
* <p>
* If the 'synth' argument is true, indicating that the member whose
* type is being resolved is synthetic, names are resolved with respect
* to the package scope. (Fix for 4097882)
*/
switch (t.getTypeCode()) {
case TC_CLASS: {
if (synth) {
} else {
}
}
break;
}
case TC_ARRAY:
break;
case TC_METHOD: {
changed = true;
}
}
if (changed) {
}
break;
}
}
return t;
}
/**
* Resolve a class name, using only package and import directives.
* Report no errors.
* <p>
*/
// This logic is pretty exactly parallel to that of
// ClassDefinition.resolveName().
if (name.isQualified()) {
// Try to resolve the first identifier component,
// because inner class names take precedence over
// package prefixes. (Cf. ClassDefinition.resolveName.)
if (rhead.hasAmbigPrefix()) {
// The first identifier component refers to an
// ambiguous class. Limp on. We throw away the
// rest of the classname as it is irrelevant.
// (part of solution for 4059855).
return rhead;
}
if (!this.classExists(rhead)) {
return this.resolvePackageQualifiedName(name);
}
try {
return this.getClassDefinition(rhead).
} catch (ClassNotFound ee) {
// return partially-resolved name someone else can fail on
}
}
try {
} catch (AmbiguousClass ee) {
// Don't force a resolution of the name if it is ambiguous.
// Forcing the resolution would tack the current package
// name onto the front of the class, which would be wrong.
// Instead, mark the name as ambiguous and let a later stage
// find the error by calling env.resolve(name).
// (part of solution for 4059855).
if (name.hasAmbigPrefix()) {
return name;
} else {
return name.addAmbigPrefix();
}
} catch (ClassNotFound ee) {
// last chance to make something halfway sensible
}
return name;
}
/**
* Discover if name consists of a package prefix, followed by the
* name of a class (that actually exists), followed possibly by
* some inner class names. If we can't find a class that exists,
* return the name unchanged.
* <p>
* This routine is used after a class name fails to
* be resolved by means of imports or inner classes.
* However, import processing uses this routine directly,
* since import names must be exactly qualified to start with.
*/
for (;;) {
if (classExists(name)) {
break;
}
if (!name.isQualified()) {
break;
}
}
return name;
}
/**
* Resolve a class name, using only package and import directives.
*/
}
/**
* Get the imports used to resolve class names.
*/
return env.getImports();
}
/**
* Create a new class.
*/
}
/**
* Create a new field.
*/
}
/**
* Returns true if the given method is applicable to the given arguments
*/
return false;
return false;
return false;
return true;
}
/**
* Returns true if "best" is in every argument at least as good as "other"
*/
throws ClassNotFound {
// System.out.println("isMoreSpecific: " + best + "/" + other
// + " => " + result);
return result;
}
/**
* Returns true if "from" is a more specific type than "to"
*/
}
/**
* Return true if an implicit cast from this type to
* the given type is allowed.
*/
return true;
switch(from.getTypeCode()) {
case TC_BYTE:
if (toTypeCode == TC_SHORT)
return true;
case TC_SHORT:
case TC_CHAR:
if (toTypeCode == TC_INT) return true;
case TC_INT:
if (toTypeCode == TC_LONG) return true;
case TC_LONG:
if (toTypeCode == TC_FLOAT) return true;
case TC_FLOAT:
if (toTypeCode == TC_DOUBLE) return true;
case TC_DOUBLE:
default:
return false;
case TC_NULL:
case TC_ARRAY:
} else {
// both are arrays. recurse down both until one isn't an array
do {
} else {
}
}
case TC_CLASS:
if (toTypeCode == TC_CLASS) {
return toDef.implementedBy(this,
} else {
return false;
}
}
}
/**
* Return true if an explicit cast from this type to
* the given type is allowed.
*/
return true;
}
}
return fromClass.implementedBy(this,
}
return toClass.implementedBy(this,
}
// The code here used to omit this case. If both types
// involved in a cast are interfaces, then JLS 5.5 requires
// that we do a simple test -- make sure none of the methods
// in toClass and fromClass have the same signature but
// different return types. (bug number 4028359)
}
return toClass.isInterface() ||
fromClass.isInterface() ||
}
}
}
return true;
}
return false;
}
/**
* Flags.
*/
public int getFlags() {
}
/**
* Debugging flags. There used to be a method debug()
* that has been replaced because -g has changed meaning
* (it now cooperates with -O and line number, variable
* range and source file info can be toggled separately).
*/
public final boolean debug_lines() {
}
public final boolean debug_vars() {
}
public final boolean debug_source() {
}
/**
* Optimization flags. There used to be a method optimize()
* that has been replaced because -O has changed meaning in
* javac to be replaced with -O and -O:interclass.
*/
public final boolean opt() {
}
public final boolean opt_interclass() {
}
/**
* Verbose
*/
public final boolean verbose() {
}
/**
* Dump debugging stuff
*/
public final boolean dump() {
}
/**
* Verbose
*/
public final boolean warnings() {
}
/**
* Dependencies
*/
public final boolean dependencies() {
}
/**
* Print Dependencies to stdout
*/
public final boolean print_dependencies() {
}
/**
* Deprecation warnings are enabled.
*/
public final boolean deprecation() {
}
/**
* Do not support virtual machines before version 1.2.
* This option is not supported and is only here for testing purposes.
*/
public final boolean version12() {
}
/**
* Floating point is strict by default
*/
public final boolean strictdefault() {
}
/**
* Release resources, if any.
*/
public void shutdown() {
}
}
/**
* Issue an error.
* source - the input source, usually a file name string
* offset - the offset in the source of the error
* err - the error number (as defined in this interface)
* arg1 - an optional argument to the error (null if not applicable)
* arg2 - a second optional argument to the error (null if not applicable)
* arg3 - a third optional argument to the error (null if not applicable)
*/
}
}
}
}
}
/**
* Output a string. This can either be an error message or something
* for debugging. This should be used instead of println.
*/
}
if (Environment.debugging)
}
/**
* set character encoding name
*/
}
/**
* Return character encoding name
*/
return encoding;
}
/**
* Return major version to use in generated class files.
*/
public short getMajorVersion() {
return env.getMajorVersion();
}
/**
* Return minor version to use in generated class files.
*/
public short getMinorVersion() {
return env.getMinorVersion();
}
// JCOV
/**
* get coverage flag
*/
public final boolean coverage() {
}
/**
* get flag of generation the coverage data file
*/
public final boolean covdata() {
}
/**
* Return the coverage data file
*/
return env.getcovFile();
}
// end JCOV
/**
* Debug tracing.
* Currently, this code is used only for tracing the loading and
* checking of classes, particularly the demand-driven aspects.
* This code should probably be integrated with 'debugOutput' above,
* but we need to give more thought to the issue of classifying debugging
* messages and allowing those only those of interest to be enabled.
*
* Calls to these methods are generally conditioned on the final variable
* 'Constants.tracing', which allows the calls to be completely omitted
* in a production release to avoid space and time overhead.
*/
private static boolean dependtrace =
}
}
}
/**
* Enable diagnostic dump of class modifier bits, including those
* in InnerClasses attributes, as they are written to the classfile.
* In the future, may also enable dumping field and method modifiers.
*/
private static boolean dumpmodifiers =
}