2600N/A/*
2600N/A * Copyright (c) 1994, 2004, Oracle and/or its affiliates. All rights reserved.
2600N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
2600N/A *
2600N/A * This code is free software; you can redistribute it and/or modify it
2600N/A * under the terms of the GNU General Public License version 2 only, as
2600N/A * published by the Free Software Foundation. Oracle designates this
2600N/A * particular file as subject to the "Classpath" exception as provided
2600N/A * by Oracle in the LICENSE file that accompanied this code.
2600N/A *
2600N/A * This code is distributed in the hope that it will be useful, but WITHOUT
2600N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
2600N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
2600N/A * version 2 for more details (a copy is included in the LICENSE file that
2600N/A * accompanied this code).
2600N/A *
2600N/A * You should have received a copy of the GNU General Public License version
2600N/A * 2 along with this work; if not, write to the Free Software Foundation,
2600N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2600N/A *
2600N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2600N/A * or visit www.oracle.com if you need additional information or have any
2600N/A * questions.
2600N/A */
2600N/A
2600N/Apackage sun.tools.java;
2600N/A
2600N/A/**
2600N/A * This class represents an Java class declaration. It refers
2600N/A * to either a binary or source definition.
2600N/A *
2600N/A * ClassDefinitions are loaded on demand, this means that
2600N/A * class declarations are late bound. The definition of the
2600N/A * class is obtained in stages. The status field describes
2600N/A * the state of the class definition:
2600N/A *
2600N/A * CS_UNDEFINED - the definition is not yet loaded
2600N/A * CS_UNDECIDED - a binary definition is loaded, but it is
2600N/A * still unclear if the source definition need to
2600N/A * be loaded
2600N/A * CS_BINARY - the binary class is loaded
2600N/A * CS_PARSED - the class is loaded from the source file, the
2600N/A * type information is available, but the class has
2600N/A * not yet been compiled.
2600N/A * CS_CHECKED - the class is loaded from the source file and has
2600N/A * been type-checked.
2600N/A * CS_COMPILED - the class has been type checked, compiled,
2600N/A * and written out.
2600N/A * CS_NOTFOUND - no class definition could be found
2600N/A *
2600N/A * WARNING: The contents of this source file are not part of any
2600N/A * supported API. Code that depends on them does so at its own risk:
2600N/A * they are subject to change or removal without notice.
2600N/A */
2600N/A
2600N/Apublic final
2600N/Aclass ClassDeclaration implements Constants {
2600N/A int status;
2600N/A Type type;
2600N/A ClassDefinition definition;
2600N/A
2600N/A /**
2600N/A * Constructor
2600N/A */
2600N/A public ClassDeclaration(Identifier name) {
2600N/A this.type = Type.tClass(name);
2600N/A }
2600N/A
2600N/A /**
2600N/A * Get the status of the class
2600N/A */
2600N/A public int getStatus() {
2600N/A return status;
2600N/A }
2600N/A
2600N/A /**
2600N/A * Get the name of the class
2600N/A */
2600N/A public Identifier getName() {
2600N/A return type.getClassName();
2600N/A }
2600N/A
2600N/A /**
2600N/A * Get the type of the class
2600N/A */
2600N/A public Type getType() {
2600N/A return type;
2600N/A }
2600N/A
2600N/A /**
2600N/A * Check if the class is defined
2600N/A */
2600N/A public boolean isDefined() {
2600N/A switch (status) {
2600N/A case CS_BINARY:
2600N/A case CS_PARSED:
2600N/A case CS_CHECKED:
2600N/A case CS_COMPILED:
2600N/A return true;
2600N/A }
2600N/A return false;
2600N/A }
2600N/A
2600N/A /**
2600N/A * Get the definition of this class. Returns null if
2600N/A * the class is not yet defined.
2600N/A */
2600N/A public ClassDefinition getClassDefinition() {
2600N/A return definition;
2600N/A }
2600N/A
/**
* This is a flag for use by getClassDefinition(env). It is
* used to mark that a class has been successfully looked up
* by that method before.
*/
private boolean found = false;
/**
* Get the definition of this class, if the class is not
* yet defined, load the definition. Loading a class may
* throw various exceptions.
*/
public ClassDefinition getClassDefinition(Environment env)
throws ClassNotFound {
if (tracing) env.dtEvent("getClassDefinition: " +
getName() + ", status " + getStatus());
// The majority of calls to getClassDefinition() are duplicates.
// This check makes them fast. It also allows us to avoid
// duplicate, useless calls to basicCheck(). In the future it
// would be good to add an additional status value, CS_BASICCHECKED.
if (found) {
return definition;
}
for(;;) {
switch (status) {
case CS_UNDEFINED:
case CS_UNDECIDED:
case CS_SOURCE:
env.loadDefinition(this);
break;
case CS_BINARY:
case CS_PARSED:
//+FIX FOR BUGID 4056065
//definition.basicCheck(env);
if (!definition.isInsideLocal()) {
// Classes inside a block, including anonymous classes,
// are checked when their surrounding member is checked.
definition.basicCheck(env);
}
//-FIX FOR BUGID 4056065
found = true;
return definition;
case CS_CHECKED:
case CS_COMPILED:
found = true;
return definition;
default:
throw new ClassNotFound(getName());
}
}
}
/**
* Get the definition of this class, if the class is not
* yet defined, load the definition. Loading a class may
* throw various exceptions. Perform no basicCheck() on this
* class.
*/
public ClassDefinition getClassDefinitionNoCheck(Environment env) throws ClassNotFound {
if (tracing) env.dtEvent("getClassDefinition: " +
getName() + ", status " + getStatus());
for(;;) {
switch (status) {
case CS_UNDEFINED:
case CS_UNDECIDED:
case CS_SOURCE:
env.loadDefinition(this);
break;
case CS_BINARY:
case CS_PARSED:
case CS_CHECKED:
case CS_COMPILED:
return definition;
default:
throw new ClassNotFound(getName());
}
}
}
/**
* Set the class definition
*/
public void setDefinition(ClassDefinition definition, int status) {
// Sanity checks.
// The name of the definition should match that of the declaration.
if ((definition != null) && !getName().equals(definition.getName())) {
throw new CompilerError("setDefinition: name mismatch: " +
this + ", " + definition);
}
// The status states can be considered ordered in the same
// manner as their numerical values. We expect classes to
// progress through a sequence of monotonically increasing
// states. NOTE: There are currently exceptions to this rule
// which are believed to be legitimate. In particular, a
// class may be checked more than once, though we believe that
// this is unnecessary and may be avoided.
/*-----------------*
if (status <= this.status) {
System.out.println("STATUS REGRESSION: " +
this + " FROM " + this.status + " TO " + status);
}
*------------------*/
this.definition = definition;
this.status = status;
}
/**
* Equality
*/
public boolean equals(Object obj) {
if ((obj != null) && (obj instanceof ClassDeclaration)) {
return type.equals(((ClassDeclaration)obj).type);
}
return false;
}
/**
* toString
*/
public String toString() {
String name = getName().toString();
String type = "type ";
String nested = getName().isInner() ? "nested " : "";
if (getClassDefinition() != null) {
if (getClassDefinition().isInterface()) {
type = "interface ";
} else {
type = "class ";
}
if (!getClassDefinition().isTopLevel()) {
nested = "inner ";
if (getClassDefinition().isLocal()) {
nested = "local ";
if (!getClassDefinition().isAnonymous()) {
name = getClassDefinition().getLocalName() +
" (" + name + ")";
}
}
}
}
return nested + type + name;
}
}