KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > compiler > lookup > FieldBinding


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.compiler.lookup;
12
13 import org.eclipse.jdt.core.compiler.CharOperation;
14 import org.eclipse.jdt.internal.compiler.ast.ASTNode;
15 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
16 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
17 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
18 import org.eclipse.jdt.internal.compiler.impl.Constant;
19
20 public class FieldBinding extends VariableBinding {
21     public ReferenceBinding declaringClass;
22 protected FieldBinding() {
23     super(null, null, 0, null);
24     // for creating problem field
25
}
26 public FieldBinding(char[] name, TypeBinding type, int modifiers, ReferenceBinding declaringClass, Constant constant) {
27     super(name, type, modifiers, constant);
28     this.declaringClass = declaringClass;
29 }
30 public FieldBinding(FieldDeclaration field, TypeBinding type, int modifiers, ReferenceBinding declaringClass) {
31     this(field.name, type, modifiers, declaringClass, null);
32     field.binding = this; // record binding in declaration
33
}
34 // special API used to change field declaring class for runtime visibility check
35
public FieldBinding(FieldBinding initialFieldBinding, ReferenceBinding declaringClass) {
36     super(initialFieldBinding.name, initialFieldBinding.type, initialFieldBinding.modifiers, initialFieldBinding.constant());
37     this.declaringClass = declaringClass;
38     this.id = initialFieldBinding.id;
39     setAnnotations(initialFieldBinding.getAnnotations());
40 }
41 /* API
42 * Answer the receiver's binding type from Binding.BindingID.
43 */

44
45 public final int kind() {
46     return FIELD;
47 }
48 /* Answer true if the receiver is visible to the invocationPackage.
49 */

50
51 public final boolean canBeSeenBy(PackageBinding invocationPackage) {
52     if (isPublic()) return true;
53     if (isPrivate()) return false;
54
55     // isProtected() or isDefault()
56
return invocationPackage == declaringClass.getPackage();
57 }
58 /* Answer true if the receiver is visible to the type provided by the scope.
59 * InvocationSite implements isSuperAccess() to provide additional information
60 * if the receiver is protected.
61 *
62 * NOTE: Cannot invoke this method with a compilation unit scope.
63 */

64
65 public final boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invocationSite, Scope scope) {
66     if (isPublic()) return true;
67
68     SourceTypeBinding invocationType = scope.enclosingSourceType();
69     if (invocationType == declaringClass && invocationType == receiverType) return true;
70
71     if (invocationType == null) // static import call
72
return !isPrivate() && scope.getCurrentPackage() == declaringClass.fPackage;
73
74     if (isProtected()) {
75         // answer true if the invocationType is the declaringClass or they are in the same package
76
// OR the invocationType is a subclass of the declaringClass
77
// AND the receiverType is the invocationType or its subclass
78
// OR the method is a static method accessed directly through a type
79
// OR previous assertions are true for one of the enclosing type
80
if (invocationType == declaringClass) return true;
81         if (invocationType.fPackage == declaringClass.fPackage) return true;
82
83         ReferenceBinding currentType = invocationType;
84         int depth = 0;
85         ReferenceBinding receiverErasure = (ReferenceBinding)receiverType.erasure();
86         ReferenceBinding declaringErasure = (ReferenceBinding) declaringClass.erasure();
87         do {
88             if (currentType.findSuperTypeWithSameErasure(declaringErasure) != null) {
89                 if (invocationSite.isSuperAccess())
90                     return true;
91                 // receiverType can be an array binding in one case... see if you can change it
92
if (receiverType instanceof ArrayBinding)
93                     return false;
94                 if (isStatic()) {
95                     if (depth > 0) invocationSite.setDepth(depth);
96                     return true; // see 1FMEPDL - return invocationSite.isTypeAccess();
97
}
98                 if (currentType == receiverErasure || receiverErasure.findSuperTypeWithSameErasure(currentType) != null) {
99                     if (depth > 0) invocationSite.setDepth(depth);
100                     return true;
101                 }
102             }
103             depth++;
104             currentType = currentType.enclosingType();
105         } while (currentType != null);
106         return false;
107     }
108
109     if (isPrivate()) {
110         // answer true if the receiverType is the declaringClass
111
// AND the invocationType and the declaringClass have a common enclosingType
112
receiverCheck: {
113             if (receiverType != declaringClass) {
114                 // special tolerance for type variable direct bounds
115
if (receiverType.isTypeVariable() && ((TypeVariableBinding) receiverType).isErasureBoundTo(declaringClass.erasure()))
116                     break receiverCheck;
117                 return false;
118             }
119         }
120
121         if (invocationType != declaringClass) {
122             ReferenceBinding outerInvocationType = invocationType;
123             ReferenceBinding temp = outerInvocationType.enclosingType();
124             while (temp != null) {
125                 outerInvocationType = temp;
126                 temp = temp.enclosingType();
127             }
128
129             ReferenceBinding outerDeclaringClass = (ReferenceBinding) declaringClass.erasure();
130             temp = outerDeclaringClass.enclosingType();
131             while (temp != null) {
132                 outerDeclaringClass = temp;
133                 temp = temp.enclosingType();
134             }
135             if (outerInvocationType != outerDeclaringClass) return false;
136         }
137         return true;
138     }
139
140     // isDefault()
141
PackageBinding declaringPackage = declaringClass.fPackage;
142     if (invocationType.fPackage != declaringPackage) return false;
143
144     // receiverType can be an array binding in one case... see if you can change it
145
if (receiverType instanceof ArrayBinding)
146         return false;
147     ReferenceBinding currentType = (ReferenceBinding) receiverType;
148     do {
149         if (declaringClass == currentType) return true;
150         PackageBinding currentPackage = currentType.fPackage;
151         // package could be null for wildcards/intersection types, ignore and recurse in superclass
152
if (currentPackage != null && currentPackage != declaringPackage) return false;
153     } while ((currentType = currentType.superclass()) != null);
154     return false;
155 }
156 /*
157  * declaringUniqueKey dot fieldName ) returnTypeUniqueKey
158  * p.X { X<T> x} --> Lp/X;.x)p/X<TT;>;
159  */

160 public char[] computeUniqueKey(boolean isLeaf) {
161     // declaring key
162
char[] declaringKey =
163         this.declaringClass == null /*case of length field for an array*/
164             ? CharOperation.NO_CHAR
165             : this.declaringClass.computeUniqueKey(false/*not a leaf*/);
166     int declaringLength = declaringKey.length;
167     
168     // name
169
int nameLength = this.name.length;
170     
171     // return type
172
char[] returnTypeKey = this.type == null ? new char[] {'V'} : this.type.computeUniqueKey(false/*not a leaf*/);
173     int returnTypeLength = returnTypeKey.length;
174     
175     char[] uniqueKey = new char[declaringLength + 1 + nameLength + 1 + returnTypeLength];
176     int index = 0;
177     System.arraycopy(declaringKey, 0, uniqueKey, index, declaringLength);
178     index += declaringLength;
179     uniqueKey[index++] = '.';
180     System.arraycopy(this.name, 0, uniqueKey, index, nameLength);
181     index += nameLength;
182     uniqueKey[index++] = ')';
183     System.arraycopy(returnTypeKey, 0, uniqueKey, index, returnTypeLength);
184     return uniqueKey;
185 }
186
187 public Constant constant() {
188     Constant fieldConstant = this.constant;
189     if (fieldConstant == null) {
190         if (this.isFinal()) {
191             //The field has not been yet type checked.
192
//It also means that the field is not coming from a class that
193
//has already been compiled. It can only be from a class within
194
//compilation units to process. Thus the field is NOT from a BinaryTypeBinbing
195
FieldBinding originalField = this.original();
196             if (originalField.declaringClass instanceof SourceTypeBinding) {
197                 SourceTypeBinding sourceType = (SourceTypeBinding) originalField.declaringClass;
198                 if (sourceType.scope != null) {
199                     TypeDeclaration typeDecl = sourceType.scope.referenceContext;
200                     FieldDeclaration fieldDecl = typeDecl.declarationOf(originalField);
201                     fieldDecl.resolve(originalField.isStatic() //side effect on binding
202
? typeDecl.staticInitializerScope
203                             : typeDecl.initializerScope);
204                     fieldConstant = originalField.constant();
205                 } else {
206                     fieldConstant = Constant.NotAConstant; // shouldn't occur per construction (paranoid null check)
207
}
208             } else {
209                 fieldConstant = Constant.NotAConstant; // shouldn't occur per construction (paranoid null check)
210
}
211         } else {
212             fieldConstant = Constant.NotAConstant;
213         }
214         this.constant = fieldConstant;
215     }
216     return fieldConstant;
217 }
218 /**
219  * X<T> t --> LX<TT;>;
220  */

221 public char[] genericSignature() {
222     if ((this.modifiers & ExtraCompilerModifiers.AccGenericSignature) == 0) return null;
223     return this.type.genericTypeSignature();
224 }
225
226 public final int getAccessFlags() {
227     return modifiers & ExtraCompilerModifiers.AccJustFlag;
228 }
229
230 /**
231  * Compute the tagbits for standard annotations. For source types, these could require
232  * lazily resolving corresponding annotation nodes, in case of forward references.
233  * @see org.eclipse.jdt.internal.compiler.lookup.Binding#getAnnotationTagBits()
234  */

235 public long getAnnotationTagBits() {
236     FieldBinding originalField = this.original();
237     if ((originalField.tagBits & TagBits.AnnotationResolved) == 0 && originalField.declaringClass instanceof SourceTypeBinding) {
238         ClassScope scope = ((SourceTypeBinding) originalField.declaringClass).scope;
239         if (scope == null) { // synthetic fields do not have a scope nor any annotations
240
this.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved);
241             return 0;
242         }
243         TypeDeclaration typeDecl = scope.referenceContext;
244         FieldDeclaration fieldDecl = typeDecl.declarationOf(originalField);
245         if (fieldDecl != null) {
246             MethodScope initializationScope = isStatic() ? typeDecl.staticInitializerScope : typeDecl.initializerScope;
247             FieldBinding previousField = initializationScope.initializedField;
248             int previousFieldID = initializationScope.lastVisibleFieldID;
249             try {
250                 initializationScope.initializedField = originalField;
251                 initializationScope.lastVisibleFieldID = originalField.id;
252                 ASTNode.resolveAnnotations(initializationScope, fieldDecl.annotations, originalField);
253             } finally {
254                 initializationScope.initializedField = previousField;
255                 initializationScope.lastVisibleFieldID = previousFieldID;
256             }
257         }
258     }
259     return originalField.tagBits;
260 }
261
262 public AnnotationBinding[] getAnnotations() {
263     FieldBinding originalField = this.original();
264     ReferenceBinding declaringClassBinding = originalField.declaringClass;
265     if (declaringClassBinding == null) {
266         return Binding.NO_ANNOTATIONS;
267     }
268     return declaringClassBinding.retrieveAnnotations(originalField);
269 }
270
271 /* Answer true if the receiver has default visibility
272 */

273
274 public final boolean isDefault() {
275     return !isPublic() && !isProtected() && !isPrivate();
276 }
277 /* Answer true if the receiver is a deprecated field
278 */

279
280 public final boolean isDeprecated() {
281     return (modifiers & ClassFileConstants.AccDeprecated) != 0;
282 }
283 /* Answer true if the receiver has private visibility
284 */

285
286 public final boolean isPrivate() {
287     return (modifiers & ClassFileConstants.AccPrivate) != 0;
288 }
289 /* Answer true if the receiver has private visibility and is used locally
290 */

291
292 public final boolean isUsed() {
293     return (modifiers & ExtraCompilerModifiers.AccLocallyUsed) != 0;
294 }
295 /* Answer true if the receiver has protected visibility
296 */

297
298 public final boolean isProtected() {
299     return (modifiers & ClassFileConstants.AccProtected) != 0;
300 }
301 /* Answer true if the receiver has public visibility
302 */

303
304 public final boolean isPublic() {
305     return (modifiers & ClassFileConstants.AccPublic) != 0;
306 }
307 /* Answer true if the receiver is a static field
308 */

309
310 public final boolean isStatic() {
311     return (modifiers & ClassFileConstants.AccStatic) != 0;
312 }
313 /* Answer true if the receiver is not defined in the source of the declaringClass
314 */

315
316 public final boolean isSynthetic() {
317     return (modifiers & ClassFileConstants.AccSynthetic) != 0;
318 }
319 /* Answer true if the receiver is a transient field
320 */

321
322 public final boolean isTransient() {
323     return (modifiers & ClassFileConstants.AccTransient) != 0;
324 }
325 /* Answer true if the receiver's declaring type is deprecated (or any of its enclosing types)
326 */

327
328 public final boolean isViewedAsDeprecated() {
329     return (modifiers & (ClassFileConstants.AccDeprecated | ExtraCompilerModifiers.AccDeprecatedImplicitly)) != 0;
330 }
331 /* Answer true if the receiver is a volatile field
332 */

333
334 public final boolean isVolatile() {
335     return (modifiers & ClassFileConstants.AccVolatile) != 0;
336 }
337 /**
338  * Returns the original field (as opposed to parameterized instances)
339  */

340 public FieldBinding original() {
341     return this;
342 }
343 public void setAnnotations(AnnotationBinding[] annotations) {
344     this.declaringClass.storeAnnotations(this, annotations);
345 }
346 public FieldDeclaration sourceField() {
347     SourceTypeBinding sourceType;
348     try {
349         sourceType = (SourceTypeBinding) declaringClass;
350     } catch (ClassCastException JavaDoc e) {
351         return null;
352     }
353
354     FieldDeclaration[] fields = sourceType.scope.referenceContext.fields;
355     if (fields != null) {
356         for (int i = fields.length; --i >= 0;)
357             if (this == fields[i].binding)
358                 return fields[i];
359     }
360     return null;
361 }
362 }
363
Popular Tags