001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.core.dom;
011:
012: import org.eclipse.jdt.core.IJavaElement;
013: import org.eclipse.jdt.core.IType;
014: import org.eclipse.jdt.core.util.IModifierConstants;
015: import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
016: import org.eclipse.jdt.internal.compiler.impl.Constant;
017: import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
018: import org.eclipse.jdt.internal.compiler.lookup.TagBits;
019: import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
020: import org.eclipse.jdt.internal.core.JavaElement;
021: import org.eclipse.jdt.internal.core.LocalVariable;
022:
023: /**
024: * Internal implementation of variable bindings.
025: */
026: class VariableBinding implements IVariableBinding {
027:
028: private static final int VALID_MODIFIERS = Modifier.PUBLIC
029: | Modifier.PROTECTED | Modifier.PRIVATE | Modifier.STATIC
030: | Modifier.FINAL | Modifier.TRANSIENT | Modifier.VOLATILE;
031:
032: private org.eclipse.jdt.internal.compiler.lookup.VariableBinding binding;
033: private ITypeBinding declaringClass;
034: private String key;
035: private String name;
036: private BindingResolver resolver;
037: private ITypeBinding type;
038:
039: VariableBinding(
040: BindingResolver resolver,
041: org.eclipse.jdt.internal.compiler.lookup.VariableBinding binding) {
042: this .resolver = resolver;
043: this .binding = binding;
044: }
045:
046: public IAnnotationBinding[] getAnnotations() {
047: org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding[] internalAnnotations = this .binding
048: .getAnnotations();
049: // the variable is not an enum constant nor a field nor an argument.
050: int length = internalAnnotations == null ? 0
051: : internalAnnotations.length;
052: IAnnotationBinding[] domInstances = length == 0 ? AnnotationBinding.NoAnnotations
053: : new AnnotationBinding[length];
054: for (int i = 0; i < length; i++) {
055: final IAnnotationBinding annotationInstance = this .resolver
056: .getAnnotationInstance(internalAnnotations[i]);
057: if (annotationInstance == null) {// not resolving binding
058: return AnnotationBinding.NoAnnotations;
059: }
060: domInstances[i] = annotationInstance;
061: }
062: return domInstances;
063: }
064:
065: /* (non-Javadoc)
066: * @see IVariableBinding#getConstantValue()
067: * @since 3.0
068: */
069: public Object getConstantValue() {
070: Constant c = this .binding.constant();
071: if (c == null || c == Constant.NotAConstant)
072: return null;
073: switch (c.typeID()) {
074: case TypeIds.T_boolean:
075: return Boolean.valueOf(c.booleanValue());
076: case TypeIds.T_byte:
077: return new Byte(c.byteValue());
078: case TypeIds.T_char:
079: return new Character(c.charValue());
080: case TypeIds.T_double:
081: return new Double(c.doubleValue());
082: case TypeIds.T_float:
083: return new Float(c.floatValue());
084: case TypeIds.T_int:
085: return new Integer(c.intValue());
086: case TypeIds.T_long:
087: return new Long(c.longValue());
088: case TypeIds.T_short:
089: return new Short(c.shortValue());
090: case TypeIds.T_JavaLangString:
091: return c.stringValue();
092: }
093: return null;
094: }
095:
096: /*
097: * @see IVariableBinding#getDeclaringClass()
098: */
099: public ITypeBinding getDeclaringClass() {
100: if (isField()) {
101: if (this .declaringClass == null) {
102: FieldBinding fieldBinding = (FieldBinding) this .binding;
103: this .declaringClass = this .resolver
104: .getTypeBinding(fieldBinding.declaringClass);
105: }
106: return this .declaringClass;
107: } else {
108: return null;
109: }
110: }
111:
112: /*
113: * @see IVariableBinding#getDeclaringMethod()
114: */
115: public IMethodBinding getDeclaringMethod() {
116: if (!isField()) {
117: ASTNode node = this .resolver.findDeclaringNode(this );
118: while (true) {
119: if (node == null)
120: break;
121: switch (node.getNodeType()) {
122: case ASTNode.INITIALIZER:
123: return null;
124: case ASTNode.METHOD_DECLARATION:
125: MethodDeclaration methodDeclaration = (MethodDeclaration) node;
126: return methodDeclaration.resolveBinding();
127: default:
128: node = node.getParent();
129: }
130: }
131: }
132: return null;
133: }
134:
135: /*
136: * @see IBinding#getJavaElement()
137: */
138: public IJavaElement getJavaElement() {
139: JavaElement element = getUnresolvedJavaElement();
140: if (element == null)
141: return null;
142: return element.resolved(this .binding);
143: }
144:
145: /*
146: * @see IBinding#getKey()
147: */
148: public String getKey() {
149: if (this .key == null) {
150: this .key = new String(this .binding.computeUniqueKey());
151: }
152: return this .key;
153: }
154:
155: /*
156: * @see IBinding#getKind()
157: */
158: public int getKind() {
159: return IBinding.VARIABLE;
160: }
161:
162: /*
163: * @see IBinding#getModifiers()
164: */
165: public int getModifiers() {
166: if (isField()) {
167: return ((FieldBinding) this .binding).getAccessFlags()
168: & VALID_MODIFIERS;
169: }
170: if (binding.isFinal()) {
171: return IModifierConstants.ACC_FINAL;
172: }
173: return Modifier.NONE;
174: }
175:
176: /*
177: * @see IBinding#getName()
178: */
179: public String getName() {
180: if (this .name == null) {
181: this .name = new String(this .binding.name);
182: }
183: return this .name;
184: }
185:
186: /*
187: * @see IVariableBinding#getType()
188: */
189: public ITypeBinding getType() {
190: if (this .type == null) {
191: this .type = this .resolver.getTypeBinding(this .binding.type);
192: }
193: return this .type;
194: }
195:
196: private JavaElement getUnresolvedJavaElement() {
197: if (isField()) {
198: // field
199: FieldBinding fieldBinding = (FieldBinding) this .binding;
200: if (fieldBinding.declaringClass == null)
201: return null; // arraylength
202: IType declaringType = (IType) getDeclaringClass()
203: .getJavaElement();
204: if (declaringType == null)
205: return null;
206: return (JavaElement) declaringType.getField(getName());
207: }
208: // local variable
209: IMethodBinding declaringMethod = getDeclaringMethod();
210: if (declaringMethod == null)
211: return null;
212: JavaElement method = (JavaElement) declaringMethod
213: .getJavaElement();
214: if (!(this .resolver instanceof DefaultBindingResolver))
215: return null;
216: VariableDeclaration localVar = (VariableDeclaration) ((DefaultBindingResolver) this .resolver).bindingsToAstNodes
217: .get(this );
218: if (localVar == null)
219: return null;
220: int nameStart;
221: int nameLength;
222: int sourceStart;
223: int sourceLength;
224: if (localVar instanceof SingleVariableDeclaration) {
225: sourceStart = localVar.getStartPosition();
226: sourceLength = localVar.getLength();
227: SimpleName simpleName = ((SingleVariableDeclaration) localVar)
228: .getName();
229: nameStart = simpleName.getStartPosition();
230: nameLength = simpleName.getLength();
231: } else {
232: nameStart = localVar.getStartPosition();
233: nameLength = localVar.getLength();
234: ASTNode node = localVar.getParent();
235: sourceStart = node.getStartPosition();
236: sourceLength = node.getLength();
237: }
238: char[] typeSig = this .binding.type.genericTypeSignature();
239: return new LocalVariable(method, localVar.getName()
240: .getIdentifier(), sourceStart, sourceStart
241: + sourceLength - 1, nameStart, nameStart + nameLength
242: - 1, new String(typeSig));
243: }
244:
245: /*
246: * @see IVariableBinding#getVariableDeclaration()
247: * @since 3.1
248: */
249: public IVariableBinding getVariableDeclaration() {
250: if (this .isField()) {
251: FieldBinding fieldBinding = (FieldBinding) this .binding;
252: return this .resolver.getVariableBinding(fieldBinding
253: .original());
254: }
255: return this ;
256: }
257:
258: /*
259: * @see IVariableBinding#getVariableId()
260: */
261: public int getVariableId() {
262: return this .binding.id;
263: }
264:
265: /*
266: * @see IVariableBinding#isParameter()
267: */
268: public boolean isParameter() {
269: return (this .binding.tagBits & TagBits.IsArgument) != 0;
270: }
271:
272: /*
273: * @see IBinding#isDeprecated()
274: */
275: public boolean isDeprecated() {
276: if (isField()) {
277: return ((FieldBinding) this .binding).isDeprecated();
278: }
279: return false;
280: }
281:
282: /*
283: * @see IVariableBinding#isEnumConstant()
284: * @since 3.1
285: */
286: public boolean isEnumConstant() {
287: return (this .binding.modifiers & ClassFileConstants.AccEnum) != 0;
288: }
289:
290: /*
291: * @see IBinding#isEqualTo(Binding)
292: * @since 3.1
293: */
294: public boolean isEqualTo(IBinding other) {
295: if (other == this ) {
296: // identical binding - equal (key or no key)
297: return true;
298: }
299: if (other == null) {
300: // other binding missing
301: return false;
302: }
303: if (!(other instanceof VariableBinding)) {
304: return false;
305: }
306: org.eclipse.jdt.internal.compiler.lookup.VariableBinding otherBinding = ((VariableBinding) other).binding;
307: if (this .binding instanceof FieldBinding) {
308: if (otherBinding instanceof FieldBinding) {
309: return BindingComparator.isEqual(
310: (FieldBinding) this .binding,
311: (FieldBinding) otherBinding);
312: } else {
313: return false;
314: }
315: } else {
316: if (BindingComparator.isEqual(this .binding, otherBinding)) {
317: IMethodBinding declaringMethod = this
318: .getDeclaringMethod();
319: IMethodBinding otherDeclaringMethod = ((VariableBinding) other)
320: .getDeclaringMethod();
321: if (declaringMethod == null) {
322: if (otherDeclaringMethod != null) {
323: return false;
324: }
325: return true;
326: }
327: return declaringMethod.isEqualTo(otherDeclaringMethod);
328: }
329: return false;
330: }
331: }
332:
333: /*
334: * @see IVariableBinding#isField()
335: */
336: public boolean isField() {
337: return this .binding instanceof FieldBinding;
338: }
339:
340: /*
341: * @see IBinding#isSynthetic()
342: */
343: public boolean isSynthetic() {
344: if (isField()) {
345: return ((FieldBinding) this .binding).isSynthetic();
346: }
347: return false;
348: }
349:
350: /*
351: * (non-Javadoc)
352: * @see org.eclipse.jdt.core.dom.IBinding#isRecovered()
353: */
354: public boolean isRecovered() {
355: return false;
356: }
357:
358: /*
359: * For debugging purpose only.
360: * @see java.lang.Object#toString()
361: */
362: public String toString() {
363: return this.binding.toString();
364: }
365: }
|