/* * 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; } }