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
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
12 package net.sourceforge.phpdt.core.dom;
14 import net.sourceforge.phpdt.core.IJavaElement;
15 import net.sourceforge.phpdt.core.compiler.CharOperation;
16 import net.sourceforge.phpdt.internal.compiler.ast.Expression;
17 import net.sourceforge.phpdt.internal.compiler.ast.Wildcard;
18 import net.sourceforge.phpdt.internal.compiler.classfmt.ClassFileConstants;
19 import net.sourceforge.phpdt.internal.compiler.lookup.ArrayBinding;
20 import net.sourceforge.phpdt.internal.compiler.lookup.BaseTypeBinding;
21 import net.sourceforge.phpdt.internal.compiler.lookup.Binding;
22 import net.sourceforge.phpdt.internal.compiler.lookup.CaptureBinding;
23 import net.sourceforge.phpdt.internal.compiler.lookup.FieldBinding;
24 import net.sourceforge.phpdt.internal.compiler.lookup.LocalTypeBinding;
25 import net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding;
26 import net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding;
27 import net.sourceforge.phpdt.internal.compiler.lookup.ParameterizedTypeBinding;
28 import net.sourceforge.phpdt.internal.compiler.lookup.RawTypeBinding;
29 import net.sourceforge.phpdt.internal.compiler.lookup.ReferenceBinding;
30 import net.sourceforge.phpdt.internal.compiler.lookup.Scope;
31 import net.sourceforge.phpdt.internal.compiler.lookup.TagBits;
32 import net.sourceforge.phpdt.internal.compiler.lookup.TypeConstants;
33 import net.sourceforge.phpdt.internal.compiler.lookup.TypeVariableBinding;
34 import net.sourceforge.phpdt.internal.compiler.lookup.WildcardBinding;
35 import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilation;
36 import net.sourceforge.phpdt.internal.compiler.util.SuffixConstants;
37 import net.sourceforge.phpdt.internal.core.JavaElement;
38 import net.sourceforge.phpdt.internal.core.PackageFragment;
41 * Internal implementation of type bindings.
43 class TypeBinding implements ITypeBinding {
44 protected static final IMethodBinding[] NO_METHOD_BINDINGS = new IMethodBinding[0];
46 private static final String NO_NAME = ""; //$NON-NLS-1$
47 protected static final ITypeBinding[] NO_TYPE_BINDINGS = new ITypeBinding[0];
48 protected static final IVariableBinding[] NO_VARIABLE_BINDINGS = new IVariableBinding[0];
50 private static final int VALID_MODIFIERS = Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE |
51 Modifier.ABSTRACT | Modifier.STATIC | Modifier.FINAL | Modifier.STRICTFP;
53 net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding binding;
55 private BindingResolver resolver;
56 private IVariableBinding[] fields;
57 private IAnnotationBinding[] annotations;
58 private IMethodBinding[] methods;
59 private ITypeBinding[] members;
60 private ITypeBinding[] interfaces;
61 private ITypeBinding[] typeArguments;
62 private ITypeBinding[] bounds;
63 private ITypeBinding[] typeParameters;
65 public TypeBinding(BindingResolver resolver, net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding binding) {
66 this.binding = binding;
67 this.resolver = resolver;
70 public ITypeBinding createArrayType(int dimension) {
71 int realDimensions = dimension;
72 realDimensions += this.getDimensions();
73 if (realDimensions < 1 || realDimensions > 255) {
74 throw new IllegalArgumentException();
76 return this.resolver.resolveArrayType(this, dimension);
79 public IAnnotationBinding[] getAnnotations() {
80 if (this.annotations != null) {
81 return this.annotations;
83 if (this.binding.isAnnotationType() || this.binding.isClass() || this.binding.isEnum() || this.binding.isInterface()) {
84 net.sourceforge.phpdt.internal.compiler.lookup.ReferenceBinding refType =
85 (net.sourceforge.phpdt.internal.compiler.lookup.ReferenceBinding) this.binding;
86 net.sourceforge.phpdt.internal.compiler.lookup.AnnotationBinding[] internalAnnotations = refType.getAnnotations();
87 int length = internalAnnotations == null ? 0 : internalAnnotations.length;
89 IAnnotationBinding[] tempAnnotations = new IAnnotationBinding[length];
90 int convertedAnnotationCount = 0;
91 for (int i = 0; i < length; i++) {
92 net.sourceforge.phpdt.internal.compiler.lookup.AnnotationBinding internalAnnotation = internalAnnotations[i];
93 IAnnotationBinding annotationInstance = this.resolver.getAnnotationInstance(internalAnnotation);
94 if (annotationInstance == null) {
97 tempAnnotations[convertedAnnotationCount++] = annotationInstance;
99 if (convertedAnnotationCount != length) {
100 if (convertedAnnotationCount == 0) {
101 return this.annotations = AnnotationBinding.NoAnnotations;
103 System.arraycopy(tempAnnotations, 0, (tempAnnotations = new IAnnotationBinding[convertedAnnotationCount]), 0, convertedAnnotationCount);
105 return this.annotations = tempAnnotations;
108 return this.annotations = AnnotationBinding.NoAnnotations;
112 * @see ITypeBinding#getBinaryName()
115 public String getBinaryName() {
116 if (this.binding.isCapture()) {
117 return null; // no binary name for capture binding
118 } else if (this.binding.isTypeVariable()) {
119 TypeVariableBinding typeVariableBinding = (TypeVariableBinding) this.binding;
120 net.sourceforge.phpdt.internal.compiler.lookup.Binding declaring = typeVariableBinding.declaringElement;
121 StringBuffer binaryName = new StringBuffer();
122 switch(declaring.kind()) {
123 case net.sourceforge.phpdt.internal.compiler.lookup.Binding.METHOD :
124 MethodBinding methodBinding = (MethodBinding) declaring;
125 char[] constantPoolName = methodBinding.declaringClass.constantPoolName();
126 if (constantPoolName == null) return null;
128 .append(CharOperation.replaceOnCopy(constantPoolName, '/', '.'))
130 .append(methodBinding.signature())
132 .append(typeVariableBinding.sourceName);
135 net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding typeBinding = (net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding) declaring;
136 constantPoolName = typeBinding.constantPoolName();
137 if (constantPoolName == null) return null;
139 .append(CharOperation.replaceOnCopy(constantPoolName, '/', '.'))
141 .append(typeVariableBinding.sourceName);
143 return String.valueOf(binaryName);
145 char[] constantPoolName = this.binding.constantPoolName();
146 if (constantPoolName == null) return null;
147 char[] dotSeparated = CharOperation.replaceOnCopy(constantPoolName, '/', '.');
148 return new String(dotSeparated);
152 * @see org.eclipse.jdt.core.dom.ITypeBinding#getBound()
154 public ITypeBinding getBound() {
155 switch (this.binding.kind()) {
156 case Binding.WILDCARD_TYPE :
157 case Binding.INTERSECTION_TYPE :
158 WildcardBinding wildcardBinding = (WildcardBinding) this.binding;
159 if (wildcardBinding.bound != null) {
160 return this.resolver.getTypeBinding(wildcardBinding.bound);
168 * @see ITypeBinding#getComponentType()
170 public ITypeBinding getComponentType() {
171 if (!this.isArray()) {
174 ArrayBinding arrayBinding = (ArrayBinding) binding;
175 return resolver.getTypeBinding(arrayBinding.elementsType());
179 * @see ITypeBinding#getDeclaredFields()
181 public synchronized IVariableBinding[] getDeclaredFields() {
182 if (this.fields != null) {
186 if (isClass() || isInterface() || isEnum()) {
187 ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
188 FieldBinding[] fieldBindings = referenceBinding.availableFields(); // resilience
189 int length = fieldBindings.length;
191 int convertedFieldCount = 0;
192 IVariableBinding[] newFields = new IVariableBinding[length];
193 for (int i = 0; i < length; i++) {
194 FieldBinding fieldBinding = fieldBindings[i];
195 IVariableBinding variableBinding = this.resolver.getVariableBinding(fieldBinding);
196 if (variableBinding == null) {
197 return this.fields = NO_VARIABLE_BINDINGS;
199 newFields[convertedFieldCount++] = variableBinding;
202 if (convertedFieldCount != length) {
203 if (convertedFieldCount == 0) {
204 return this.fields = NO_VARIABLE_BINDINGS;
206 System.arraycopy(newFields, 0, (newFields = new IVariableBinding[convertedFieldCount]), 0, convertedFieldCount);
208 return this.fields = newFields;
211 } catch (RuntimeException e) {
212 /* in case a method cannot be resolvable due to missing jars on the classpath
213 * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
214 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
215 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
217 net.sourceforge.phpdt.internal.core.util.Util.log(e, "Could not retrieve declared fields"); //$NON-NLS-1$
219 return this.fields = NO_VARIABLE_BINDINGS;
223 * @see ITypeBinding#getDeclaredMethods()
225 public synchronized IMethodBinding[] getDeclaredMethods() {
226 if (this.methods != null) {
230 if (isClass() || isInterface() || isEnum()) {
231 ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
232 net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding[] internalMethods = referenceBinding.availableMethods(); // be resilient
233 int length = internalMethods.length;
235 int convertedMethodCount = 0;
236 IMethodBinding[] newMethods = new IMethodBinding[length];
237 for (int i = 0; i < length; i++) {
238 net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding methodBinding = internalMethods[i];
239 if (methodBinding.isDefaultAbstract() || methodBinding.isSynthetic() || (methodBinding.isConstructor() && isInterface())) {
242 IMethodBinding methodBinding2 = this.resolver.getMethodBinding(methodBinding);
243 if (methodBinding2 != null) {
244 newMethods[convertedMethodCount++] = methodBinding2;
247 if (convertedMethodCount != length) {
248 if (convertedMethodCount == 0) {
249 return this.methods = NO_METHOD_BINDINGS;
251 System.arraycopy(newMethods, 0, (newMethods = new IMethodBinding[convertedMethodCount]), 0, convertedMethodCount);
253 return this.methods = newMethods;
256 } catch (RuntimeException e) {
257 /* in case a method cannot be resolvable due to missing jars on the classpath
258 * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
259 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
260 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
262 net.sourceforge.phpdt.internal.core.util.Util.log(e, "Could not retrieve declared methods"); //$NON-NLS-1$
264 return this.methods = NO_METHOD_BINDINGS;
268 * @see ITypeBinding#getDeclaredModifiers()
270 public int getDeclaredModifiers() {
271 return getModifiers();
275 * @see ITypeBinding#getDeclaredTypes()
277 public synchronized ITypeBinding[] getDeclaredTypes() {
278 if (this.members != null) {
282 if (isClass() || isInterface() || isEnum()) {
283 ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
284 ReferenceBinding[] internalMembers = referenceBinding.memberTypes();
285 int length = internalMembers.length;
287 ITypeBinding[] newMembers = new ITypeBinding[length];
288 for (int i = 0; i < length; i++) {
289 ITypeBinding typeBinding = this.resolver.getTypeBinding(internalMembers[i]);
290 if (typeBinding == null) {
291 return this.members = NO_TYPE_BINDINGS;
293 newMembers[i] = typeBinding;
295 return this.members = newMembers;
298 } catch (RuntimeException e) {
299 /* in case a method cannot be resolvable due to missing jars on the classpath
300 * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
301 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
302 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
304 net.sourceforge.phpdt.internal.core.util.Util.log(e, "Could not retrieve declared methods"); //$NON-NLS-1$
306 return this.members = NO_TYPE_BINDINGS;
310 * @see ITypeBinding#getDeclaringMethod()
312 public synchronized IMethodBinding getDeclaringMethod() {
313 if (this.binding instanceof LocalTypeBinding) {
314 LocalTypeBinding localTypeBinding = (LocalTypeBinding) this.binding;
315 MethodBinding methodBinding = localTypeBinding.enclosingMethod;
316 if (methodBinding != null) {
318 return this.resolver.getMethodBinding(localTypeBinding.enclosingMethod);
319 } catch (RuntimeException e) {
320 /* in case a method cannot be resolvable due to missing jars on the classpath
321 * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
322 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
323 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
325 net.sourceforge.phpdt.internal.core.util.Util.log(e, "Could not retrieve declaring method"); //$NON-NLS-1$
328 } else if (this.binding.isTypeVariable()) {
329 TypeVariableBinding typeVariableBinding = (TypeVariableBinding) this.binding;
330 Binding declaringElement = typeVariableBinding.declaringElement;
331 if (declaringElement instanceof MethodBinding) {
333 return this.resolver.getMethodBinding((MethodBinding)declaringElement);
334 } catch (RuntimeException e) {
335 /* in case a method cannot be resolvable due to missing jars on the classpath
336 * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
337 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
338 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
340 net.sourceforge.phpdt.internal.core.util.Util.log(e, "Could not retrieve declaring method"); //$NON-NLS-1$
348 * @see ITypeBinding#getDeclaringClass()
350 public synchronized ITypeBinding getDeclaringClass() {
351 if (isClass() || isInterface() || isEnum()) {
352 ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
353 if (referenceBinding.isNestedType()) {
355 return this.resolver.getTypeBinding(referenceBinding.enclosingType());
356 } catch (RuntimeException e) {
357 /* in case a method cannot be resolvable due to missing jars on the classpath
358 * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
359 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
360 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
362 net.sourceforge.phpdt.internal.core.util.Util.log(e, "Could not retrieve declaring class"); //$NON-NLS-1$
365 } else if (this.binding.isTypeVariable()) {
366 TypeVariableBinding typeVariableBinding = (TypeVariableBinding) this.binding;
367 Binding declaringElement = typeVariableBinding.isCapture() ? ((CaptureBinding) typeVariableBinding).sourceType : typeVariableBinding.declaringElement;
368 if (declaringElement instanceof ReferenceBinding) {
370 return this.resolver.getTypeBinding((ReferenceBinding)declaringElement);
371 } catch (RuntimeException e) {
372 /* in case a method cannot be resolvable due to missing jars on the classpath
373 * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
374 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
375 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
377 net.sourceforge.phpdt.internal.core.util.Util.log(e, "Could not retrieve declaring class"); //$NON-NLS-1$
385 * @see ITypeBinding#getDimensions()
387 public int getDimensions() {
388 if (!this.isArray()) {
391 ArrayBinding arrayBinding = (ArrayBinding) binding;
392 return arrayBinding.dimensions;
396 * @see ITypeBinding#getElementType()
398 public ITypeBinding getElementType() {
399 if (!this.isArray()) {
402 ArrayBinding arrayBinding = (ArrayBinding) binding;
403 return resolver.getTypeBinding(arrayBinding.leafComponentType);
407 * @see org.eclipse.jdt.core.dom.ITypeBinding#getTypeDeclaration()
409 public ITypeBinding getTypeDeclaration() {
410 if (this.binding instanceof ParameterizedTypeBinding)
411 return this.resolver.getTypeBinding(((ParameterizedTypeBinding)this.binding).genericType());
416 * @see org.eclipse.jdt.core.dom.ITypeBinding#getErasure()
418 public ITypeBinding getErasure() {
419 return this.resolver.getTypeBinding(this.binding.erasure());
422 public synchronized ITypeBinding[] getInterfaces() {
423 if (this.interfaces != null) {
424 return this.interfaces;
426 if (this.binding == null)
427 return this.interfaces = NO_TYPE_BINDINGS;
428 switch (this.binding.kind()) {
429 case Binding.ARRAY_TYPE :
430 case Binding.BASE_TYPE :
431 return this.interfaces = NO_TYPE_BINDINGS;
433 ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
434 ReferenceBinding[] internalInterfaces = null;
436 internalInterfaces = referenceBinding.superInterfaces();
437 } catch (RuntimeException e) {
438 /* in case a method cannot be resolvable due to missing jars on the classpath
439 * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
440 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
441 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
443 net.sourceforge.phpdt.internal.core.util.Util.log(e, "Could not retrieve interfaces"); //$NON-NLS-1$
445 int length = internalInterfaces == null ? 0 : internalInterfaces.length;
447 ITypeBinding[] newInterfaces = new ITypeBinding[length];
448 int interfacesCounter = 0;
449 for (int i = 0; i < length; i++) {
450 ITypeBinding typeBinding = this.resolver.getTypeBinding(internalInterfaces[i]);
451 if (typeBinding == null) {
454 newInterfaces[interfacesCounter++] = typeBinding;
456 if (length != interfacesCounter) {
457 System.arraycopy(newInterfaces, 0, (newInterfaces = new ITypeBinding[interfacesCounter]), 0, interfacesCounter);
459 return this.interfaces = newInterfaces;
461 return this.interfaces = NO_TYPE_BINDINGS;
464 public IJavaElement getJavaElement() {
465 JavaElement element = getUnresolvedJavaElement();
467 return element.resolved(this.binding);
469 IPackageBinding packageBinding = getPackage();
470 if (packageBinding != null) {
471 final IJavaElement javaElement = packageBinding.getJavaElement();
472 if (javaElement != null && javaElement.getElementType() == IJavaElement.PACKAGE_FRAGMENT) {
473 // best effort: we don't know if the recovered binding is a binary or source binding, so go with a compilation unit
474 return ((PackageFragment) javaElement).getCompilationUnit(new String(this.binding.sourceName()) + SuffixConstants.SUFFIX_STRING_java);
482 private JavaElement getUnresolvedJavaElement() {
483 return getUnresolvedJavaElement(this.binding);
485 private JavaElement getUnresolvedJavaElement(net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding typeBinding ) {
486 if (this.resolver instanceof DefaultBindingResolver) {
487 DefaultBindingResolver defaultBindingResolver = (DefaultBindingResolver) this.resolver;
488 return net.sourceforge.phpdt.internal.core.util.Util.getUnresolvedJavaElement(
490 defaultBindingResolver.workingCopyOwner,
491 defaultBindingResolver.getBindingsToNodesMap());
493 return net.sourceforge.phpdt.internal.core.util.Util.getUnresolvedJavaElement(typeBinding, null, null);
498 * @see IBinding#getKey()
500 public String getKey() {
501 if (this.key == null) {
502 this.key = new String(this.binding.computeUniqueKey());
508 * @see IBinding#getKind()
510 public int getKind() {
511 return IBinding.TYPE;
515 * @see IBinding#getModifiers()
517 public int getModifiers() {
519 ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
520 final int accessFlags = referenceBinding.getAccessFlags() & VALID_MODIFIERS;
521 if (referenceBinding.isAnonymousType()) {
522 return accessFlags & ~Modifier.FINAL;
525 } else if (isAnnotation()) {
526 ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
527 final int accessFlags = referenceBinding.getAccessFlags() & VALID_MODIFIERS;
528 // clear the AccAbstract, AccAnnotation and the AccInterface bits
529 return accessFlags & ~(ClassFileConstants.AccAbstract | ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation);
530 } else if (isInterface()) {
531 ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
532 final int accessFlags = referenceBinding.getAccessFlags() & VALID_MODIFIERS;
533 // clear the AccAbstract and the AccInterface bits
534 return accessFlags & ~(ClassFileConstants.AccAbstract | ClassFileConstants.AccInterface);
535 } else if (isEnum()) {
536 ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
537 final int accessFlags = referenceBinding.getAccessFlags() & VALID_MODIFIERS;
538 // clear the AccEnum bits
539 return accessFlags & ~ClassFileConstants.AccEnum;
541 return Modifier.NONE;
545 public String getName() {
547 switch (this.binding.kind()) {
549 case Binding.WILDCARD_TYPE :
550 case Binding.INTERSECTION_TYPE:
551 WildcardBinding wildcardBinding = (WildcardBinding) this.binding;
552 buffer = new StringBuffer();
553 buffer.append(TypeConstants.WILDCARD_NAME);
554 if (wildcardBinding.bound != null) {
555 switch(wildcardBinding.boundKind) {
556 case Wildcard.SUPER :
557 buffer.append(TypeConstants.WILDCARD_SUPER);
559 case Wildcard.EXTENDS :
560 buffer.append(TypeConstants.WILDCARD_EXTENDS);
562 buffer.append(getBound().getName());
564 return String.valueOf(buffer);
566 case Binding.TYPE_PARAMETER :
570 TypeVariableBinding typeVariableBinding = (TypeVariableBinding) this.binding;
571 return new String(typeVariableBinding.sourceName);
573 case Binding.PARAMETERIZED_TYPE :
574 ParameterizedTypeBinding parameterizedTypeBinding = (ParameterizedTypeBinding) this.binding;
575 buffer = new StringBuffer();
576 buffer.append(parameterizedTypeBinding.sourceName());
577 ITypeBinding[] tArguments = getTypeArguments();
578 final int typeArgumentsLength = tArguments.length;
579 if (typeArgumentsLength != 0) {
581 for (int i = 0; i < typeArgumentsLength; i++) {
585 buffer.append(tArguments[i].getName());
589 return String.valueOf(buffer);
591 case Binding.RAW_TYPE :
592 return getTypeDeclaration().getName();
594 case Binding.ARRAY_TYPE :
595 ITypeBinding elementType = getElementType();
596 if (elementType.isLocal() || elementType.isAnonymous() || elementType.isCapture()) {
599 int dimensions = getDimensions();
600 char[] brackets = new char[dimensions * 2];
601 for (int i = dimensions * 2 - 1; i >= 0; i -= 2) {
603 brackets[i - 1] = '[';
605 buffer = new StringBuffer(elementType.getName());
606 buffer.append(brackets);
607 return String.valueOf(buffer);
610 if (isPrimitive() || isNullType()) {
611 BaseTypeBinding baseTypeBinding = (BaseTypeBinding) this.binding;
612 return new String(baseTypeBinding.simpleName);
617 return new String(this.binding.sourceName());
622 * @see ITypeBinding#getPackage()
624 public IPackageBinding getPackage() {
625 switch (this.binding.kind()) {
626 case Binding.BASE_TYPE :
627 case Binding.ARRAY_TYPE :
628 case Binding.TYPE_PARAMETER : // includes capture scenario
629 case Binding.WILDCARD_TYPE :
630 case Binding.INTERSECTION_TYPE:
633 ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
634 return this.resolver.getPackageBinding(referenceBinding.getPackage());
638 * @see org.eclipse.jdt.core.dom.ITypeBinding#getQualifiedName()
640 public String getQualifiedName() {
642 switch (this.binding.kind()) {
644 case Binding.WILDCARD_TYPE :
645 case Binding.INTERSECTION_TYPE:
646 WildcardBinding wildcardBinding = (WildcardBinding) this.binding;
647 buffer = new StringBuffer();
648 buffer.append(TypeConstants.WILDCARD_NAME);
649 final ITypeBinding bound = getBound();
651 switch(wildcardBinding.boundKind) {
652 case Wildcard.SUPER :
653 buffer.append(TypeConstants.WILDCARD_SUPER);
655 case Wildcard.EXTENDS :
656 buffer.append(TypeConstants.WILDCARD_EXTENDS);
658 buffer.append(bound.getQualifiedName());
660 return String.valueOf(buffer);
662 case Binding.RAW_TYPE :
663 return getTypeDeclaration().getQualifiedName();
665 case Binding.ARRAY_TYPE :
666 ITypeBinding elementType = getElementType();
667 if (elementType.isLocal() || elementType.isAnonymous() || elementType.isCapture()) {
668 return elementType.getQualifiedName();
670 final int dimensions = getDimensions();
671 char[] brackets = new char[dimensions * 2];
672 for (int i = dimensions * 2 - 1; i >= 0; i -= 2) {
674 brackets[i - 1] = '[';
676 buffer = new StringBuffer(elementType.getQualifiedName());
677 buffer.append(brackets);
678 return String.valueOf(buffer);
680 case Binding.TYPE_PARAMETER :
684 TypeVariableBinding typeVariableBinding = (TypeVariableBinding) this.binding;
685 return new String(typeVariableBinding.sourceName);
687 case Binding.PARAMETERIZED_TYPE :
688 buffer = new StringBuffer();
691 .append(getDeclaringClass().getQualifiedName())
693 ParameterizedTypeBinding parameterizedTypeBinding = (ParameterizedTypeBinding) this.binding;
694 buffer.append(parameterizedTypeBinding.sourceName());
695 ITypeBinding[] tArguments = getTypeArguments();
696 final int typeArgumentsLength = tArguments.length;
697 if (typeArgumentsLength != 0) {
699 for (int i = 0; i < typeArgumentsLength; i++) {
703 buffer.append(tArguments[i].getQualifiedName());
707 return String.valueOf(buffer);
709 buffer.append(getTypeDeclaration().getQualifiedName());
710 ITypeBinding[] tArguments = getTypeArguments();
711 final int typeArgumentsLength = tArguments.length;
712 if (typeArgumentsLength != 0) {
714 for (int i = 0; i < typeArgumentsLength; i++) {
718 buffer.append(tArguments[i].getQualifiedName());
722 return String.valueOf(buffer);
725 if (isAnonymous() || this.binding.isLocalType()) {
728 if (isPrimitive() || isNullType()) {
729 BaseTypeBinding baseTypeBinding = (BaseTypeBinding) this.binding;
730 return new String(baseTypeBinding.simpleName);
733 buffer = new StringBuffer();
735 .append(getDeclaringClass().getQualifiedName())
737 buffer.append(getName());
738 return String.valueOf(buffer);
740 PackageBinding packageBinding = this.binding.getPackage();
741 buffer = new StringBuffer();
742 if (packageBinding != null && packageBinding.compoundName != CharOperation.NO_CHAR_CHAR) {
743 buffer.append(CharOperation.concatWith(packageBinding.compoundName, '.')).append('.');
745 buffer.append(getName());
746 return String.valueOf(buffer);
751 * @see ITypeBinding#getSuperclass()
753 public synchronized ITypeBinding getSuperclass() {
754 if (this.binding == null)
756 switch (this.binding.kind()) {
757 case Binding.ARRAY_TYPE :
758 case Binding.BASE_TYPE :
761 // no superclass for interface types (interface | annotation type)
762 if (this.binding.isInterface())
765 ReferenceBinding superclass = null;
767 superclass = ((ReferenceBinding)this.binding).superclass();
768 } catch (RuntimeException e) {
769 /* in case a method cannot be resolvable due to missing jars on the classpath
770 * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
771 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
772 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
774 net.sourceforge.phpdt.internal.core.util.Util.log(e, "Could not retrieve superclass"); //$NON-NLS-1$
775 return this.resolver.resolveWellKnownType("java.lang.Object"); //$NON-NLS-1$
777 if (superclass == null) {
780 return this.resolver.getTypeBinding(superclass);
784 * @see org.eclipse.jdt.core.dom.ITypeBinding#getTypeArguments()
786 public ITypeBinding[] getTypeArguments() {
787 if (this.typeArguments != null) {
788 return this.typeArguments;
790 if (this.binding.isParameterizedType()) {
791 ParameterizedTypeBinding parameterizedTypeBinding = (ParameterizedTypeBinding) this.binding;
792 final net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding[] arguments = parameterizedTypeBinding.arguments;
793 if (arguments != null) {
794 int argumentsLength = arguments.length;
795 ITypeBinding[] newTypeArguments = new ITypeBinding[argumentsLength];
796 for (int i = 0; i < argumentsLength; i++) {
797 ITypeBinding typeBinding = this.resolver.getTypeBinding(arguments[i]);
798 if (typeBinding == null) {
799 return this.typeArguments = NO_TYPE_BINDINGS;
801 newTypeArguments[i] = typeBinding;
803 return this.typeArguments = newTypeArguments;
806 return this.typeArguments = NO_TYPE_BINDINGS;
810 * @see org.eclipse.jdt.core.dom.ITypeBinding#getTypeBounds()
812 public ITypeBinding[] getTypeBounds() {
813 if (this.bounds != null) {
816 if (this.binding instanceof TypeVariableBinding) {
817 TypeVariableBinding typeVariableBinding = (TypeVariableBinding) this.binding;
818 ReferenceBinding varSuperclass = typeVariableBinding.superclass();
819 net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding firstClassOrArrayBound = typeVariableBinding.firstBound;
820 int boundsLength = 0;
821 if (firstClassOrArrayBound != null) {
822 if (firstClassOrArrayBound == varSuperclass) {
824 } else if (firstClassOrArrayBound.isArrayType()) { // capture of ? extends/super arrayType
827 firstClassOrArrayBound = null;
830 ReferenceBinding[] superinterfaces = typeVariableBinding.superInterfaces();
831 int superinterfacesLength = 0;
832 if (superinterfaces != null) {
833 superinterfacesLength = superinterfaces.length;
834 boundsLength += superinterfacesLength;
836 if (boundsLength != 0) {
837 ITypeBinding[] typeBounds = new ITypeBinding[boundsLength];
839 if (firstClassOrArrayBound != null) {
840 ITypeBinding typeBinding = this.resolver.getTypeBinding(firstClassOrArrayBound);
841 if (typeBinding == null) {
842 return this.bounds = NO_TYPE_BINDINGS;
844 typeBounds[boundsIndex++] = typeBinding;
846 if (superinterfaces != null) {
847 for (int i = 0; i < superinterfacesLength; i++, boundsIndex++) {
848 ITypeBinding typeBinding = this.resolver.getTypeBinding(superinterfaces[i]);
849 if (typeBinding == null) {
850 return this.bounds = NO_TYPE_BINDINGS;
852 typeBounds[boundsIndex] = typeBinding;
855 return this.bounds = typeBounds;
858 return this.bounds = NO_TYPE_BINDINGS;
862 * @see org.eclipse.jdt.core.dom.ITypeBinding#getTypeParameters()
864 public ITypeBinding[] getTypeParameters() {
865 if (this.typeParameters != null) {
866 return this.typeParameters;
868 switch(this.binding.kind()) {
869 case Binding.RAW_TYPE :
870 case Binding.PARAMETERIZED_TYPE :
871 return this.typeParameters = NO_TYPE_BINDINGS;
873 TypeVariableBinding[] typeVariableBindings = this.binding.typeVariables();
874 int typeVariableBindingsLength = typeVariableBindings == null ? 0 : typeVariableBindings.length;
875 if (typeVariableBindingsLength != 0) {
876 ITypeBinding[] newTypeParameters = new ITypeBinding[typeVariableBindingsLength];
877 for (int i = 0; i < typeVariableBindingsLength; i++) {
878 ITypeBinding typeBinding = this.resolver.getTypeBinding(typeVariableBindings[i]);
879 if (typeBinding == null) {
880 return this.typeParameters = NO_TYPE_BINDINGS;
882 newTypeParameters[i] = typeBinding;
884 return this.typeParameters = newTypeParameters;
886 return this.typeParameters = NO_TYPE_BINDINGS;
890 * @see org.eclipse.jdt.core.dom.ITypeBinding#getWildcard()
893 public ITypeBinding getWildcard() {
894 if (this.binding instanceof CaptureBinding) {
895 CaptureBinding captureBinding = (CaptureBinding) this.binding;
896 return this.resolver.getTypeBinding(captureBinding.wildcard);
902 * @see org.eclipse.jdt.core.dom.ITypeBinding#isGenericType()
905 public boolean isGenericType() {
906 // equivalent to return getTypeParameters().length > 0;
910 TypeVariableBinding[] typeVariableBindings = this.binding.typeVariables();
911 return (typeVariableBindings != null && typeVariableBindings.length > 0);
915 * @see org.eclipse.jdt.core.dom.ITypeBinding#isAnnotation()
917 public boolean isAnnotation() {
918 return this.binding.isAnnotationType();
922 * @see ITypeBinding#isAnonymous()
924 public boolean isAnonymous() {
925 if (isClass() || isInterface() || isEnum()) {
926 ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
927 return referenceBinding.isAnonymousType();
933 * @see ITypeBinding#isArray()
935 public boolean isArray() {
936 return binding.isArrayType();
940 * @see ITypeBinding#isAssignmentCompatible(ITypeBinding)
942 public boolean isAssignmentCompatible(ITypeBinding type) {
944 if (this == type) return true;
945 if (!(type instanceof TypeBinding)) return false;
946 TypeBinding other = (TypeBinding) type;
947 Scope scope = this.resolver.scope();
948 if (scope == null) return false;
949 return this.binding.isCompatibleWith(other.binding) || scope.isBoxingCompatibleWith(this.binding, other.binding);
950 } catch (AbortCompilation e) {
951 // don't surface internal exception to clients
952 // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=143013
958 * @see ITypeBinding#isCapture()
960 public boolean isCapture() {
961 return this.binding.isCapture();
965 * @see ITypeBinding#isCastCompatible(ITypeBinding)
967 public boolean isCastCompatible(ITypeBinding type) {
969 Expression expression = new Expression() {
970 public StringBuffer printExpression(int indent,StringBuffer output) {
974 Scope scope = this.resolver.scope();
975 if (scope == null) return false;
976 if (!(type instanceof TypeBinding)) return false;
977 net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding expressionType = ((TypeBinding) type).binding;
978 // simulate capture in case checked binding did not properly get extracted from a reference
979 expressionType = expressionType.capture(scope, 0);
980 return expression.checkCastTypesCompatibility(scope, this.binding, expressionType, null);
981 } catch (AbortCompilation e) {
982 // don't surface internal exception to clients
983 // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=143013
989 * @see ITypeBinding#isClass()
991 public boolean isClass() {
992 switch (this.binding.kind()) {
993 case Binding.TYPE_PARAMETER :
994 case Binding.WILDCARD_TYPE :
995 case Binding.INTERSECTION_TYPE :
998 return this.binding.isClass();
1002 * @see IBinding#isDeprecated()
1004 public boolean isDeprecated() {
1005 if (isClass() || isInterface() || isEnum()) {
1006 ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
1007 return referenceBinding.isDeprecated();
1013 * @see ITypeBinding#isEnum()
1015 public boolean isEnum() {
1016 return this.binding.isEnum();
1020 * @see IBinding#isEqualTo(Binding)
1023 public boolean isEqualTo(IBinding other) {
1024 if (other == this) {
1025 // identical binding - equal (key or no key)
1028 if (other == null) {
1029 // other binding missing
1032 if (!(other instanceof TypeBinding)) {
1035 net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding otherBinding = ((TypeBinding) other).binding;
1036 // check return type
1037 return BindingComparator.isEqual(this.binding, otherBinding);
1041 * @see ITypeBinding#isFromSource()
1043 public boolean isFromSource() {
1044 if (isClass() || isInterface() || isEnum()) {
1045 ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
1046 if (referenceBinding.isRawType()) {
1047 return !((RawTypeBinding) referenceBinding).genericType().isBinaryBinding();
1048 } else if (referenceBinding.isParameterizedType()) {
1049 ParameterizedTypeBinding parameterizedTypeBinding = (ParameterizedTypeBinding) referenceBinding;
1050 net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding erasure = parameterizedTypeBinding.erasure();
1051 if (erasure instanceof ReferenceBinding) {
1052 return !((ReferenceBinding) erasure).isBinaryBinding();
1056 return !referenceBinding.isBinaryBinding();
1058 } else if (isTypeVariable()) {
1059 final TypeVariableBinding typeVariableBinding = (TypeVariableBinding) this.binding;
1060 final Binding declaringElement = typeVariableBinding.declaringElement;
1061 if (declaringElement instanceof MethodBinding) {
1062 MethodBinding methodBinding = (MethodBinding) declaringElement;
1063 return !methodBinding.declaringClass.isBinaryBinding();
1065 final net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding typeBinding = (net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding) declaringElement;
1066 if (typeBinding instanceof ReferenceBinding) {
1067 return !((ReferenceBinding) typeBinding).isBinaryBinding();
1068 } else if (typeBinding instanceof ArrayBinding) {
1069 final ArrayBinding arrayBinding = (ArrayBinding) typeBinding;
1070 final net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding leafComponentType = arrayBinding.leafComponentType;
1071 if (leafComponentType instanceof ReferenceBinding) {
1072 return !((ReferenceBinding) leafComponentType).isBinaryBinding();
1077 } else if (isCapture()) {
1078 CaptureBinding captureBinding = (CaptureBinding) this.binding;
1079 return !captureBinding.sourceType.isBinaryBinding();
1085 * @see ITypeBinding#isInterface()
1087 public boolean isInterface() {
1088 switch (this.binding.kind()) {
1089 case Binding.TYPE_PARAMETER :
1090 case Binding.WILDCARD_TYPE :
1091 case Binding.INTERSECTION_TYPE :
1094 return this.binding.isInterface();
1098 * @see ITypeBinding#isLocal()
1100 public boolean isLocal() {
1101 if (isClass() || isInterface() || isEnum()) {
1102 ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
1103 return referenceBinding.isLocalType() && !referenceBinding.isMemberType();
1109 * @see ITypeBinding#isMember()
1111 public boolean isMember() {
1112 if (isClass() || isInterface() || isEnum()) {
1113 ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
1114 return referenceBinding.isMemberType();
1120 * @see ITypeBinding#isNested()
1122 public boolean isNested() {
1123 if (isClass() || isInterface() || isEnum()) {
1124 ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
1125 return referenceBinding.isNestedType();
1131 * @see ITypeBinding#isNullType()
1133 public boolean isNullType() {
1134 return this.binding == net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding.NULL;
1138 * @see org.eclipse.jdt.core.dom.ITypeBinding#isParameterizedType()
1140 public boolean isParameterizedType() {
1141 return this.binding.isParameterizedType() && ((ParameterizedTypeBinding) this.binding).arguments != null;
1145 * @see ITypeBinding#isPrimitive()
1147 public boolean isPrimitive() {
1148 return !isNullType() && binding.isBaseType();
1152 * @see org.eclipse.jdt.core.dom.ITypeBinding#isRawType()
1154 public boolean isRawType() {
1155 return this.binding.isRawType();
1159 * @see IBinding#isRecovered()
1161 public boolean isRecovered() {
1162 return (this.binding.tagBits & TagBits.HasMissingType) != 0;
1166 * @see ITypeBinding#isSubTypeCompatible(ITypeBinding)
1168 public boolean isSubTypeCompatible(ITypeBinding type) {
1170 if (this == type) return true;
1171 if (this.binding.isBaseType()) return false;
1172 if (!(type instanceof TypeBinding)) return false;
1173 TypeBinding other = (TypeBinding) type;
1174 if (other.binding.isBaseType()) return false;
1175 return this.binding.isCompatibleWith(other.binding);
1176 } catch (AbortCompilation e) {
1177 // don't surface internal exception to clients
1178 // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=143013
1184 * @see IBinding#isSynthetic()
1186 public boolean isSynthetic() {
1191 * @see ITypeBinding#isTopLevel()
1193 public boolean isTopLevel() {
1194 if (isClass() || isInterface() || isEnum()) {
1195 ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
1196 return !referenceBinding.isNestedType();
1202 * @see ITypeBinding#isTypeVariable()
1204 public boolean isTypeVariable() {
1205 return this.binding.isTypeVariable() && !this.binding.isCapture();
1209 * @see org.eclipse.jdt.core.dom.ITypeBinding#isUpperbound()
1211 public boolean isUpperbound() {
1212 switch (this.binding.kind()) {
1213 case Binding.WILDCARD_TYPE :
1214 return ((WildcardBinding) this.binding).boundKind == Wildcard.EXTENDS;
1215 case Binding.INTERSECTION_TYPE :
1222 * @see org.eclipse.jdt.core.dom.ITypeBinding#isWildcardType()
1224 public boolean isWildcardType() {
1225 return this.binding.isWildcard();
1229 * For debugging purpose only.
1230 * @see java.lang.Object#toString()
1232 public String toString() {
1233 return this.binding.toString();