View Javadoc
1   /*
2    * Copyright (c) 1994, 2013, 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 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 }