mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-28 12:09:14 +00:00
271 lines
8.7 KiB
Java
271 lines
8.7 KiB
Java
/*
|
|
* Copyright (c) 1994, 2013, 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.java;
|
|
|
|
/**
|
|
* This class represents an Java class declaration. It refers
|
|
* to either a binary or source definition.
|
|
*
|
|
* ClassDefinitions are loaded on demand, this means that
|
|
* class declarations are late bound. The definition of the
|
|
* class is obtained in stages. The status field describes
|
|
* the state of the class definition:
|
|
*
|
|
* CS_UNDEFINED - the definition is not yet loaded
|
|
* CS_UNDECIDED - a binary definition is loaded, but it is
|
|
* still unclear if the source definition need to
|
|
* be loaded
|
|
* CS_BINARY - the binary class is loaded
|
|
* CS_PARSED - the class is loaded from the source file, the
|
|
* type information is available, but the class has
|
|
* not yet been compiled.
|
|
* CS_CHECKED - the class is loaded from the source file and has
|
|
* been type-checked.
|
|
* CS_COMPILED - the class has been type checked, compiled,
|
|
* and written out.
|
|
* CS_NOTFOUND - no class definition could be found
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
public final
|
|
class ClassDeclaration implements Constants {
|
|
int status;
|
|
Type type;
|
|
ClassDefinition definition;
|
|
|
|
/**
|
|
* Constructor
|
|
*/
|
|
public ClassDeclaration(Identifier name) {
|
|
this.type = Type.tClass(name);
|
|
}
|
|
|
|
/**
|
|
* Get the status of the class
|
|
*/
|
|
public int getStatus() {
|
|
return status;
|
|
}
|
|
|
|
/**
|
|
* Get the name of the class
|
|
*/
|
|
public Identifier getName() {
|
|
return type.getClassName();
|
|
}
|
|
|
|
/**
|
|
* Get the type of the class
|
|
*/
|
|
public Type getType() {
|
|
return type;
|
|
}
|
|
|
|
/**
|
|
* Check if the class is defined
|
|
*/
|
|
public boolean isDefined() {
|
|
switch (status) {
|
|
case CS_BINARY:
|
|
case CS_PARSED:
|
|
case CS_CHECKED:
|
|
case CS_COMPILED:
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Get the definition of this class. Returns null if
|
|
* the class is not yet defined.
|
|
*/
|
|
public ClassDefinition getClassDefinition() {
|
|
return definition;
|
|
}
|
|
|
|
/**
|
|
* 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 instanceof ClassDeclaration) {
|
|
return type.equals(((ClassDeclaration)obj).type);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public int hashCode() {
|
|
return type.hashCode();
|
|
}
|
|
|
|
/**
|
|
* 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;
|
|
}
|
|
}
|