1 /* 2 * Copyright (c) 1994, 2004, Oracle and/or its affiliates. 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package 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 56 public final 57 class 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 @Override 240 public int hashCode() { 241 return type.hashCode(); 242 } 243 244 /** 245 * toString 246 */ 247 public String toString() { 248 String name = getName().toString(); 249 String type = "type "; 250 String nested = getName().isInner() ? "nested " : ""; 251 if (getClassDefinition() != null) { 252 if (getClassDefinition().isInterface()) { 253 type = "interface "; 254 } else { 255 type = "class "; 256 } 257 if (!getClassDefinition().isTopLevel()) { 258 nested = "inner "; 259 if (getClassDefinition().isLocal()) { 260 nested = "local "; 261 if (!getClassDefinition().isAnonymous()) { 262 name = getClassDefinition().getLocalName() + 263 " (" + name + ")"; 264 } 265 } 266 } 267 } 268 return nested + type + name; 269 } 270 }