001: /*
002: * Copyright 1994-2004 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.tools.java;
027:
028: /**
029: * This class represents an Java class declaration. It refers
030: * to either a binary or source definition.
031: *
032: * ClassDefinitions are loaded on demand, this means that
033: * class declarations are late bound. The definition of the
034: * class is obtained in stages. The status field describes
035: * the state of the class definition:
036: *
037: * CS_UNDEFINED - the definition is not yet loaded
038: * CS_UNDECIDED - a binary definition is loaded, but it is
039: * still unclear if the source definition need to
040: * be loaded
041: * CS_BINARY - the binary class is loaded
042: * CS_PARSED - the class is loaded from the source file, the
043: * type information is available, but the class has
044: * not yet been compiled.
045: * CS_CHECKED - the class is loaded from the source file and has
046: * been type-checked.
047: * CS_COMPILED - the class has been type checked, compiled,
048: * and written out.
049: * CS_NOTFOUND - no class definition could be found
050: *
051: * WARNING: The contents of this source file are not part of any
052: * supported API. Code that depends on them does so at its own risk:
053: * they are subject to change or removal without notice.
054: */
055:
056: public final class ClassDeclaration implements Constants {
057: int status;
058: Type type;
059: ClassDefinition definition;
060:
061: /**
062: * Constructor
063: */
064: public ClassDeclaration(Identifier name) {
065: this .type = Type.tClass(name);
066: }
067:
068: /**
069: * Get the status of the class
070: */
071: public int getStatus() {
072: return status;
073: }
074:
075: /**
076: * Get the name of the class
077: */
078: public Identifier getName() {
079: return type.getClassName();
080: }
081:
082: /**
083: * Get the type of the class
084: */
085: public Type getType() {
086: return type;
087: }
088:
089: /**
090: * Check if the class is defined
091: */
092: public boolean isDefined() {
093: switch (status) {
094: case CS_BINARY:
095: case CS_PARSED:
096: case CS_CHECKED:
097: case CS_COMPILED:
098: return true;
099: }
100: return false;
101: }
102:
103: /**
104: * Get the definition of this class. Returns null if
105: * the class is not yet defined.
106: */
107: public ClassDefinition getClassDefinition() {
108: return definition;
109: }
110:
111: /**
112: * This is a flag for use by getClassDefinition(env). It is
113: * used to mark that a class has been successfully looked up
114: * by that method before.
115: */
116: private boolean found = false;
117:
118: /**
119: * Get the definition of this class, if the class is not
120: * yet defined, load the definition. Loading a class may
121: * throw various exceptions.
122: */
123: public ClassDefinition getClassDefinition(Environment env)
124: throws ClassNotFound {
125: if (tracing)
126: env.dtEvent("getClassDefinition: " + getName()
127: + ", status " + getStatus());
128:
129: // The majority of calls to getClassDefinition() are duplicates.
130: // This check makes them fast. It also allows us to avoid
131: // duplicate, useless calls to basicCheck(). In the future it
132: // would be good to add an additional status value, CS_BASICCHECKED.
133: if (found) {
134: return definition;
135: }
136:
137: for (;;) {
138: switch (status) {
139: case CS_UNDEFINED:
140: case CS_UNDECIDED:
141: case CS_SOURCE:
142: env.loadDefinition(this );
143: break;
144:
145: case CS_BINARY:
146: case CS_PARSED:
147: //+FIX FOR BUGID 4056065
148: //definition.basicCheck(env);
149: if (!definition.isInsideLocal()) {
150: // Classes inside a block, including anonymous classes,
151: // are checked when their surrounding member is checked.
152: definition.basicCheck(env);
153: }
154: //-FIX FOR BUGID 4056065
155: found = true;
156: return definition;
157:
158: case CS_CHECKED:
159: case CS_COMPILED:
160: found = true;
161: return definition;
162:
163: default:
164: throw new ClassNotFound(getName());
165: }
166: }
167: }
168:
169: /**
170: * Get the definition of this class, if the class is not
171: * yet defined, load the definition. Loading a class may
172: * throw various exceptions. Perform no basicCheck() on this
173: * class.
174: */
175: public ClassDefinition getClassDefinitionNoCheck(Environment env)
176: throws ClassNotFound {
177: if (tracing)
178: env.dtEvent("getClassDefinition: " + getName()
179: + ", status " + getStatus());
180: for (;;) {
181: switch (status) {
182: case CS_UNDEFINED:
183: case CS_UNDECIDED:
184: case CS_SOURCE:
185: env.loadDefinition(this );
186: break;
187:
188: case CS_BINARY:
189: case CS_PARSED:
190: case CS_CHECKED:
191: case CS_COMPILED:
192: return definition;
193:
194: default:
195: throw new ClassNotFound(getName());
196: }
197: }
198: }
199:
200: /**
201: * Set the class definition
202: */
203: public void setDefinition(ClassDefinition definition, int status) {
204:
205: // Sanity checks.
206:
207: // The name of the definition should match that of the declaration.
208: if ((definition != null)
209: && !getName().equals(definition.getName())) {
210: throw new CompilerError("setDefinition: name mismatch: "
211: + this + ", " + definition);
212: }
213:
214: // The status states can be considered ordered in the same
215: // manner as their numerical values. We expect classes to
216: // progress through a sequence of monotonically increasing
217: // states. NOTE: There are currently exceptions to this rule
218: // which are believed to be legitimate. In particular, a
219: // class may be checked more than once, though we believe that
220: // this is unnecessary and may be avoided.
221: /*-----------------*
222: if (status <= this.status) {
223: System.out.println("STATUS REGRESSION: " +
224: this + " FROM " + this.status + " TO " + status);
225: }
226: *------------------*/
227:
228: this .definition = definition;
229: this .status = status;
230: }
231:
232: /**
233: * Equality
234: */
235: public boolean equals(Object obj) {
236: if ((obj != null) && (obj instanceof ClassDeclaration)) {
237: return type.equals(((ClassDeclaration) obj).type);
238: }
239: return false;
240: }
241:
242: /**
243: * toString
244: */
245: public String toString() {
246: String name = getName().toString();
247: String type = "type ";
248: String nested = getName().isInner() ? "nested " : "";
249: if (getClassDefinition() != null) {
250: if (getClassDefinition().isInterface()) {
251: type = "interface ";
252: } else {
253: type = "class ";
254: }
255: if (!getClassDefinition().isTopLevel()) {
256: nested = "inner ";
257: if (getClassDefinition().isLocal()) {
258: nested = "local ";
259: if (!getClassDefinition().isAnonymous()) {
260: name = getClassDefinition().getLocalName()
261: + " (" + name + ")";
262: }
263: }
264: }
265: }
266: return nested + type + name;
267: }
268: }
|