blob: 8accc3b6aecf892d69ace99ad9791c54b4dc56fe [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1994-2004 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.tools.java;
27
28/**
29 * This class represents an Java class declaration. It refers
30 * to either a binary or source definition.
31 *
32 * ClassDefinitions are loaded on demand, this means that
33 * class declarations are late bound. The definition of the
34 * class is obtained in stages. The status field describes
35 * the state of the class definition:
36 *
37 * CS_UNDEFINED - the definition is not yet loaded
38 * CS_UNDECIDED - a binary definition is loaded, but it is
39 * still unclear if the source definition need to
40 * be loaded
41 * CS_BINARY - the binary class is loaded
42 * CS_PARSED - the class is loaded from the source file, the
43 * type information is available, but the class has
44 * not yet been compiled.
45 * CS_CHECKED - the class is loaded from the source file and has
46 * been type-checked.
47 * CS_COMPILED - the class has been type checked, compiled,
48 * and written out.
49 * CS_NOTFOUND - no class definition could be found
50 *
51 * WARNING: The contents of this source file are not part of any
52 * supported API. Code that depends on them does so at its own risk:
53 * they are subject to change or removal without notice.
54 */
55
56public final
57class ClassDeclaration implements Constants {
58 int status;
59 Type type;
60 ClassDefinition definition;
61
62 /**
63 * Constructor
64 */
65 public ClassDeclaration(Identifier name) {
66 this.type = Type.tClass(name);
67 }
68
69 /**
70 * Get the status of the class
71 */
72 public int getStatus() {
73 return status;
74 }
75
76 /**
77 * Get the name of the class
78 */
79 public Identifier getName() {
80 return type.getClassName();
81 }
82
83 /**
84 * Get the type of the class
85 */
86 public Type getType() {
87 return type;
88 }
89
90 /**
91 * Check if the class is defined
92 */
93 public boolean isDefined() {
94 switch (status) {
95 case CS_BINARY:
96 case CS_PARSED:
97 case CS_CHECKED:
98 case CS_COMPILED:
99 return true;
100 }
101 return false;
102 }
103
104 /**
105 * Get the definition of this class. Returns null if
106 * the class is not yet defined.
107 */
108 public ClassDefinition getClassDefinition() {
109 return definition;
110 }
111
112 /**
113 * This is a flag for use by getClassDefinition(env). It is
114 * used to mark that a class has been successfully looked up
115 * by that method before.
116 */
117 private boolean found = false;
118
119 /**
120 * Get the definition of this class, if the class is not
121 * yet defined, load the definition. Loading a class may
122 * throw various exceptions.
123 */
124 public ClassDefinition getClassDefinition(Environment env)
125 throws ClassNotFound {
126 if (tracing) env.dtEvent("getClassDefinition: " +
127 getName() + ", 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) throws ClassNotFound {
176 if (tracing) env.dtEvent("getClassDefinition: " +
177 getName() + ", status " + getStatus());
178 for(;;) {
179 switch (status) {
180 case CS_UNDEFINED:
181 case CS_UNDECIDED:
182 case CS_SOURCE:
183 env.loadDefinition(this);
184 break;
185
186 case CS_BINARY:
187 case CS_PARSED:
188 case CS_CHECKED:
189 case CS_COMPILED:
190 return definition;
191
192 default:
193 throw new ClassNotFound(getName());
194 }
195 }
196 }
197
198 /**
199 * Set the class definition
200 */
201 public void setDefinition(ClassDefinition definition, int status) {
202
203 // Sanity checks.
204
205 // The name of the definition should match that of the declaration.
206 if ((definition != null) && !getName().equals(definition.getName())) {
207 throw new CompilerError("setDefinition: name mismatch: " +
208 this + ", " + definition);
209 }
210
211 // The status states can be considered ordered in the same
212 // manner as their numerical values. We expect classes to
213 // progress through a sequence of monotonically increasing
214 // states. NOTE: There are currently exceptions to this rule
215 // which are believed to be legitimate. In particular, a
216 // class may be checked more than once, though we believe that
217 // this is unnecessary and may be avoided.
218 /*-----------------*
219 if (status <= this.status) {
220 System.out.println("STATUS REGRESSION: " +
221 this + " FROM " + this.status + " TO " + status);
222 }
223 *------------------*/
224
225 this.definition = definition;
226 this.status = status;
227 }
228
229 /**
230 * Equality
231 */
232 public boolean equals(Object obj) {
233 if ((obj != null) && (obj instanceof ClassDeclaration)) {
234 return type.equals(((ClassDeclaration)obj).type);
235 }
236 return false;
237 }
238
239 /**
240 * toString
241 */
242 public String toString() {
243 String name = getName().toString();
244 String type = "type ";
245 String nested = getName().isInner() ? "nested " : "";
246 if (getClassDefinition() != null) {
247 if (getClassDefinition().isInterface()) {
248 type = "interface ";
249 } else {
250 type = "class ";
251 }
252 if (!getClassDefinition().isTopLevel()) {
253 nested = "inner ";
254 if (getClassDefinition().isLocal()) {
255 nested = "local ";
256 if (!getClassDefinition().isAnonymous()) {
257 name = getClassDefinition().getLocalName() +
258 " (" + name + ")";
259 }
260 }
261 }
262 }
263 return nested + type + name;
264 }
265}