Initial upgrade to Platform/JDT 3.4.1
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / core / dom / VariableBinding.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2008 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
12 package net.sourceforge.phpdt.core.dom;
13
14 import net.sourceforge.phpdt.core.IJavaElement;
15 import net.sourceforge.phpdt.core.util.IModifierConstants;
16 import net.sourceforge.phpdt.internal.compiler.classfmt.ClassFileConstants;
17 import net.sourceforge.phpdt.internal.compiler.impl.Constant;
18 import net.sourceforge.phpdt.internal.compiler.lookup.FieldBinding;
19 import net.sourceforge.phpdt.internal.compiler.lookup.LocalVariableBinding;
20 import net.sourceforge.phpdt.internal.compiler.lookup.TagBits;
21 import net.sourceforge.phpdt.internal.compiler.lookup.TypeIds;
22 import net.sourceforge.phpdt.internal.core.JavaElement;
23 import net.sourceforge.phpdt.internal.core.LocalVariable;
24 import net.sourceforge.phpdt.internal.core.util.Util;
25
26 /**
27  * Internal implementation of variable bindings.
28  */
29 class VariableBinding implements IVariableBinding {
30
31         private static final int VALID_MODIFIERS = Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE |
32                 Modifier.STATIC | Modifier.FINAL | Modifier.TRANSIENT | Modifier.VOLATILE;
33
34         private net.sourceforge.phpdt.internal.compiler.lookup.VariableBinding binding;
35         private ITypeBinding declaringClass;
36         private String key;
37         private String name;
38         private BindingResolver resolver;
39         private ITypeBinding type;
40         private IAnnotationBinding[] annotations;
41         
42         VariableBinding(BindingResolver resolver,net.sourceforge.phpdt.internal.compiler.lookup.VariableBinding binding) {
43                 this.resolver = resolver;
44                 this.binding = binding;
45         }
46
47         public IAnnotationBinding[] getAnnotations() {
48                 if (this.annotations != null) {
49                         return this.annotations;
50                 }
51                 net.sourceforge.phpdt.internal.compiler.lookup.AnnotationBinding[] internalAnnotations = this.binding.getAnnotations();
52                 int length = internalAnnotations == null ? 0 : internalAnnotations.length;
53                 if (length != 0) {
54                         IAnnotationBinding[] tempAnnotations = new IAnnotationBinding[length];
55                         int convertedAnnotationCount = 0;
56                         for (int i = 0; i < length; i++) {
57                                 net.sourceforge.phpdt.internal.compiler.lookup.AnnotationBinding internalAnnotation = internalAnnotations[i];
58                                 final IAnnotationBinding annotationInstance = this.resolver.getAnnotationInstance(internalAnnotation);
59                                 if (annotationInstance == null) {
60                                         continue;
61                                 }
62                                 tempAnnotations[convertedAnnotationCount++] = annotationInstance;
63                         }
64                         if (convertedAnnotationCount != length) {
65                                 if (convertedAnnotationCount == 0) {
66                                         return this.annotations = AnnotationBinding.NoAnnotations;
67                                 }
68                                 System.arraycopy(tempAnnotations, 0, (tempAnnotations = new IAnnotationBinding[convertedAnnotationCount]), 0, convertedAnnotationCount);
69                         }
70                         return this.annotations = tempAnnotations;
71                 }
72                 return this.annotations = AnnotationBinding.NoAnnotations;
73         }
74
75         /* (non-Javadoc)
76          * @see IVariableBinding#getConstantValue()
77          * @since 3.0
78          */
79         public Object getConstantValue() {
80                 Constant c = this.binding.constant();
81                 if (c == null || c == Constant.NotAConstant) return null;
82                 switch (c.typeID()) {
83                         case TypeIds.T_boolean:
84                                 return Boolean.valueOf(c.booleanValue());
85                         case TypeIds.T_byte:
86                                 return new Byte(c.byteValue());
87                         case TypeIds.T_char:
88                                 return new Character(c.charValue());
89                         case TypeIds.T_double:
90                                 return new Double(c.doubleValue());
91                         case TypeIds.T_float:
92                                 return new Float(c.floatValue());
93                         case TypeIds.T_int:
94                                 return new Integer(c.intValue());
95                         case TypeIds.T_long:
96                                 return new Long(c.longValue());
97                         case TypeIds.T_short:
98                                 return new Short(c.shortValue());
99                         case TypeIds.T_JavaLangString:
100                                 return c.stringValue();
101                 }
102                 return null;
103         }
104
105         /*
106          * @see IVariableBinding#getDeclaringClass()
107          */
108         public ITypeBinding getDeclaringClass() {
109                 if (isField()) {
110                         if (this.declaringClass == null) {
111                                 FieldBinding fieldBinding = (FieldBinding) this.binding;
112                                 this.declaringClass = this.resolver.getTypeBinding(fieldBinding.declaringClass);
113                         }
114                         return this.declaringClass;
115                 } else {
116                         return null;
117                 }
118         }
119
120         /*
121          * @see IVariableBinding#getDeclaringMethod()
122          */
123         public IMethodBinding getDeclaringMethod() {
124                 if (!isField()) {
125                         ASTNode node = this.resolver.findDeclaringNode(this);
126                         while (true) {
127                                 if (node == null) break;
128                                 switch(node.getNodeType()) {
129                                         case ASTNode.INITIALIZER :
130                                                 return null;
131                                         case ASTNode.METHOD_DECLARATION :
132                                                 MethodDeclaration methodDeclaration = (MethodDeclaration) node;
133                                                 return methodDeclaration.resolveBinding();
134                                         default:
135                                                 node = node.getParent();
136                                 }
137                         }
138                 }
139                 return null;
140         }
141
142         /*
143          * @see IBinding#getJavaElement()
144          */
145         public IJavaElement getJavaElement() {
146                 JavaElement element = getUnresolvedJavaElement();
147                 if (element == null)
148                         return null;
149                 return element.resolved(this.binding);
150         }
151
152         /*
153          * @see IBinding#getKey()
154          */
155         public String getKey() {
156                 if (this.key == null) {
157                         this.key = new String(this.binding.computeUniqueKey());
158                 }
159                 return this.key;
160         }
161
162         /*
163          * @see IBinding#getKind()
164          */
165         public int getKind() {
166                 return IBinding.VARIABLE;
167         }
168
169         /*
170          * @see IBinding#getModifiers()
171          */
172         public int getModifiers() {
173                 if (isField()) {
174                         return ((FieldBinding) this.binding).getAccessFlags() & VALID_MODIFIERS;
175                 }
176                 if (binding.isFinal()) {
177                         return IModifierConstants.ACC_FINAL;
178                 }
179                 return Modifier.NONE;
180         }
181
182         /*
183          * @see IBinding#getName()
184          */
185         public String getName() {
186                 if (this.name == null) {
187                         this.name = new String(this.binding.name);
188                 }
189                 return this.name;
190         }
191
192         /*
193          * @see IVariableBinding#getType()
194          */
195         public ITypeBinding getType() {
196                 if (this.type == null) {
197                         this.type = this.resolver.getTypeBinding(this.binding.type);
198                 }
199                 return this.type;
200         }
201
202         private JavaElement getUnresolvedJavaElement() {
203                 if (isField()) {
204                         if (this.resolver instanceof DefaultBindingResolver) {
205                                 DefaultBindingResolver defaultBindingResolver = (DefaultBindingResolver) this.resolver;
206                                 return Util.getUnresolvedJavaElement(
207                                                 (FieldBinding) this.binding,
208                                                 defaultBindingResolver.workingCopyOwner,
209                                                 defaultBindingResolver.getBindingsToNodesMap());
210                         } else {
211                                 return Util.getUnresolvedJavaElement((FieldBinding) this.binding, null, null);
212                         }
213                 }
214                 // local variable
215                 IMethodBinding declaringMethod = getDeclaringMethod();
216                 if (declaringMethod == null) return null;
217                 JavaElement method = (JavaElement) declaringMethod.getJavaElement();
218                 if (method == null) return null;
219                 if (!(this.resolver instanceof DefaultBindingResolver)) return null;
220                 VariableDeclaration localVar = (VariableDeclaration) ((DefaultBindingResolver) this.resolver).bindingsToAstNodes.get(this);
221                 if (localVar == null) return null;
222                 int nameStart;
223                 int nameLength;
224                 int sourceStart;
225                 int sourceLength;
226                 if (localVar instanceof SingleVariableDeclaration) {
227                         sourceStart = localVar.getStartPosition();
228                         sourceLength = localVar.getLength();
229                         SimpleName simpleName = ((SingleVariableDeclaration) localVar).getName();
230                         nameStart = simpleName.getStartPosition();
231                         nameLength = simpleName.getLength();
232                 } else {
233                         nameStart =  localVar.getStartPosition();
234                         nameLength = localVar.getLength();
235                         ASTNode node = localVar.getParent();
236                         sourceStart = node.getStartPosition();
237                         sourceLength = node.getLength();
238                 }
239                 char[] typeSig = this.binding.type.genericTypeSignature();
240                 return new LocalVariable(method, localVar.getName().getIdentifier(), sourceStart, sourceStart+sourceLength-1, nameStart, nameStart+nameLength-1, new String(typeSig), ((LocalVariableBinding) this.binding).declaration.annotations);
241         }
242
243         /*
244          * @see IVariableBinding#getVariableDeclaration()
245          * @since 3.1
246          */
247         public IVariableBinding getVariableDeclaration() {
248                 if (this.isField()) {
249                         FieldBinding fieldBinding = (FieldBinding) this.binding;
250                         return this.resolver.getVariableBinding(fieldBinding.original());
251                 }
252                 return this;
253         }
254
255         /*
256          * @see IVariableBinding#getVariableId()
257          */
258         public int getVariableId() {
259                 return this.binding.id;
260         }
261
262         /*
263          * @see IVariableBinding#isParameter()
264          */
265         public boolean isParameter() {
266                 return (this.binding.tagBits & TagBits.IsArgument) != 0;
267         }
268         /*
269          * @see IBinding#isDeprecated()
270          */
271         public boolean isDeprecated() {
272                 if (isField()) {
273                         return ((FieldBinding) this.binding).isDeprecated();
274                 }
275                 return false;
276         }
277
278         /*
279          * @see IVariableBinding#isEnumConstant()
280          * @since 3.1
281          */
282         public boolean isEnumConstant() {
283                 return (this.binding.modifiers & ClassFileConstants.AccEnum) != 0;
284         }
285
286         /*
287          * @see IBinding#isEqualTo(Binding)
288          * @since 3.1
289          */
290         public boolean isEqualTo(IBinding other) {
291                 if (other == this) {
292                         // identical binding - equal (key or no key)
293                         return true;
294                 }
295                 if (other == null) {
296                         // other binding missing
297                         return false;
298                 }
299                 if (!(other instanceof VariableBinding)) {
300                         return false;
301                 }
302                 net.sourceforge.phpdt.internal.compiler.lookup.VariableBinding otherBinding = ((VariableBinding) other).binding;
303                 if (this.binding instanceof FieldBinding) {
304                         if (otherBinding instanceof FieldBinding) {
305                                 return BindingComparator.isEqual((FieldBinding) this.binding, (FieldBinding) otherBinding);
306                         } else {
307                                 return false;
308                         }
309                 } else {
310                         if (BindingComparator.isEqual(this.binding, otherBinding)) {
311                                 IMethodBinding declaringMethod = this.getDeclaringMethod();
312                                 IMethodBinding otherDeclaringMethod = ((VariableBinding) other).getDeclaringMethod();
313                                 if (declaringMethod == null) {
314                                         if (otherDeclaringMethod != null) {
315                                                 return false;
316                                         }
317                                         return true;
318                                 }
319                                 return declaringMethod.isEqualTo(otherDeclaringMethod);
320                         }
321                         return false;
322                 }
323         }
324
325         /*
326          * @see IVariableBinding#isField()
327          */
328         public boolean isField() {
329                 return this.binding instanceof FieldBinding;
330         }
331
332         /*
333          * @see IBinding#isSynthetic()
334          */
335         public boolean isSynthetic() {
336                 if (isField()) {
337                         return ((FieldBinding) this.binding).isSynthetic();
338                 }
339                 return false;
340         }
341
342         /*
343          * (non-Javadoc)
344          * @see org.eclipse.jdt.core.dom.IBinding#isRecovered()
345          */
346         public boolean isRecovered() {
347                 return false;
348         }
349
350         /*
351          * For debugging purpose only.
352          * @see java.lang.Object#toString()
353          */
354         public String toString() {
355                 return this.binding.toString();
356         }
357 }