gt: 				PackageBinding packageBinding = this.binding.getPackage();
context: /*******************************************************************************
   * Copyright (c) 2000, 2014 IBM Corporation and others.
   * All rights reserved. This program and the accompanying materials
   * are made available under the terms of the Eclipse Public License v1.0
   * which accompanies this distribution, and is available at
   * http://www.eclipse.org/legal/epl-v10.html
   *
   * Contributors:
   *     IBM Corporation - initial API and implementation
   *     Stephan Herrmann - Contribution for
   *								Bug 438458 - [1.8][null] clean up handling of null type annotations wrt type variables
   *******************************************************************************/
  
  package org.eclipse.jdt.core.dom;
  
  import org.eclipse.jdt.core.IJavaElement;
  import org.eclipse.jdt.core.JavaCore;
  import org.eclipse.jdt.core.compiler.CharOperation;
  import org.eclipse.jdt.internal.compiler.ast.StringLiteral;
  import org.eclipse.jdt.internal.compiler.ast.Wildcard;
  import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
  import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
  import org.eclipse.jdt.internal.compiler.lookup.BaseTypeBinding;
  import org.eclipse.jdt.internal.compiler.lookup.Binding;
  import org.eclipse.jdt.internal.compiler.lookup.CaptureBinding;
  import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
  import org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding;
  import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
  import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
  import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
  import org.eclipse.jdt.internal.compiler.lookup.RawTypeBinding;
  import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
  import org.eclipse.jdt.internal.compiler.lookup.Scope;
  import org.eclipse.jdt.internal.compiler.lookup.TagBits;
  import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
  import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
  import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
  import org.eclipse.jdt.internal.compiler.lookup.WildcardBinding;
  import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
  import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
  import org.eclipse.jdt.internal.core.JavaElement;
  import org.eclipse.jdt.internal.core.PackageFragment;
  
  /**
   * Internal implementation of type bindings.
   */
  class TypeBinding implements ITypeBinding {
  	private static final StringLiteral EXPRESSION = new org.eclipse.jdt.internal.compiler.ast.StringLiteral(0,0);
  
  	protected static final IMethodBinding[] NO_METHOD_BINDINGS = new IMethodBinding[0];
  
  	private static final String NO_NAME = ""; //$NON-NLS-1$
  	protected static final ITypeBinding[] NO_TYPE_BINDINGS = new ITypeBinding[0];
  	protected static final IVariableBinding[] NO_VARIABLE_BINDINGS = new IVariableBinding[0];
  
  	private static final int VALID_MODIFIERS = Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE |
  		Modifier.ABSTRACT | Modifier.STATIC | Modifier.FINAL | Modifier.STRICTFP;
  
  	org.eclipse.jdt.internal.compiler.lookup.TypeBinding binding;
  	private TypeBinding prototype = null;
  	private String key;
  	private BindingResolver resolver;
  	private IVariableBinding[] fields;
  	private IAnnotationBinding[] annotations;
  	private IAnnotationBinding[] typeAnnotations;
  	private IMethodBinding[] methods;
  	private ITypeBinding[] members;
  	private ITypeBinding[] interfaces;
  	private ITypeBinding[] typeArguments;
  	private ITypeBinding[] bounds;
  	private ITypeBinding[] typeParameters;
  
  	public TypeBinding(BindingResolver resolver, org.eclipse.jdt.internal.compiler.lookup.TypeBinding binding) {
  		this.binding = binding;
  		this.resolver = resolver;
  		org.eclipse.jdt.internal.compiler.lookup.TypeBinding compilerPrototype = binding.prototype();
  		this.prototype = (TypeBinding) (compilerPrototype == null || compilerPrototype == binding ? null : resolver.getTypeBinding(compilerPrototype)); //$IDENTITY-COMPARISON$
  	}
  
  	public ITypeBinding createArrayType(int dimension) {
  		int realDimensions = dimension;
  		realDimensions += getDimensions();
  		if (realDimensions < 1 || realDimensions > 255) {
  			throw new IllegalArgumentException();
  		}
  		return this.resolver.resolveArrayType(this, dimension);
  	}
  
  	public IAnnotationBinding[] getAnnotations() {
  		if (this.prototype != null) {
  			return this.prototype.getAnnotations();
  		}
  		if (this.annotations != null) {
  			return this.annotations;
  		}
  		org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding refType = null;
  		if (this.binding instanceof ParameterizedTypeBinding) {
  			refType = ((ParameterizedTypeBinding) this.binding).genericType();
  		} else if (this.binding.isAnnotationType() || this.binding.isClass() || this.binding.isEnum() || this.binding.isInterface()) {
  			refType = (org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding) this.binding;
  		}
  		if (refType != null) {
  			return this.annotations = resolveAnnotationBindings(refType.getAnnotations(), false);
  		}
  		return this.annotations = AnnotationBinding.NoAnnotations;
  	}
  	private IAnnotationBinding[] resolveAnnotationBindings(org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding[] internalAnnotations, boolean isTypeUse) {
  		int length = internalAnnotations == null ? 0 : internalAnnotations.length;
  		if (length != 0) {
  			IAnnotationBinding[] tempAnnotations = new IAnnotationBinding[length];
  			int convertedAnnotationCount = 0;
  			for (int i = 0; i < length; i++) {
  				org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding internalAnnotation = internalAnnotations[i];
  				if (isTypeUse && internalAnnotation == null) {
  					break;
  				}
  				IAnnotationBinding annotationInstance = this.resolver.getAnnotationInstance(internalAnnotation);
  				if (annotationInstance == null) {
  					continue;
  				}
  				tempAnnotations[convertedAnnotationCount++] = annotationInstance;
  			}
  			if (convertedAnnotationCount != length) {
  				if (convertedAnnotationCount == 0) {
  					return this.annotations = AnnotationBinding.NoAnnotations;
  				}
  				System.arraycopy(tempAnnotations, 0, (tempAnnotations = new IAnnotationBinding[convertedAnnotationCount]), 0, convertedAnnotationCount);
  			}
  			return tempAnnotations;
  		}
  		return AnnotationBinding.NoAnnotations;
  	}
  
  	/*
  	 * @see ITypeBinding#getBinaryName()
  	 * @since 3.0
  	 */
  	public String getBinaryName() {
  		if (this.binding.isCapture()) {
  			return null; // no binary name for capture binding
  		} else if (this.binding.isTypeVariable()) {
  			TypeVariableBinding typeVariableBinding = (TypeVariableBinding) this.binding;
  			org.eclipse.jdt.internal.compiler.lookup.Binding declaring = typeVariableBinding.declaringElement;
  			StringBuffer binaryName = new StringBuffer();
  			switch(declaring.kind()) {
  				case org.eclipse.jdt.internal.compiler.lookup.Binding.METHOD :
  					MethodBinding methodBinding = (MethodBinding) declaring;
  					char[] constantPoolName = methodBinding.declaringClass.constantPoolName();
  					if (constantPoolName == null) return null;
  					binaryName
  						.append(CharOperation.replaceOnCopy(constantPoolName, '/', '.'))
  						.append('$')
  						.append(methodBinding.signature())
  						.append('$')
  						.append(typeVariableBinding.sourceName);
  					break;
  				default :
  					org.eclipse.jdt.internal.compiler.lookup.TypeBinding typeBinding = (org.eclipse.jdt.internal.compiler.lookup.TypeBinding) declaring;
  					constantPoolName = typeBinding.constantPoolName();
  					if (constantPoolName == null) return null;
  					binaryName
  						.append(CharOperation.replaceOnCopy(constantPoolName, '/', '.'))
  						.append('$')
  						.append(typeVariableBinding.sourceName);
  			}
  			return String.valueOf(binaryName);
  		}
   		char[] constantPoolName = this.binding.constantPoolName();
  		if (constantPoolName == null) return null;
  		char[] dotSeparated = CharOperation.replaceOnCopy(constantPoolName, '/', '.');
  		return new String(dotSeparated);
  	}
  
  	/* (non-Javadoc)
  	 * @see org.eclipse.jdt.core.dom.ITypeBinding#getBound()
  	 */
  	public ITypeBinding getBound() {
  		switch (this.binding.kind()) {
  			case Binding.WILDCARD_TYPE :
  			case Binding.INTERSECTION_TYPE :
  				WildcardBinding wildcardBinding = (WildcardBinding) this.binding;
  				if (wildcardBinding.bound != null) {
  					return this.resolver.getTypeBinding(wildcardBinding.bound);
  				}
  				break;
  		}
  		return null;
  	}
  	
  	/* (non-Javadoc)
  	 * @see org.eclipse.jdt.core.dom.ITypeBinding#getGenericTypeOfWildcardType()
  	 */
  	public ITypeBinding getGenericTypeOfWildcardType() {
  		switch (this.binding.kind()) {
  			case Binding.WILDCARD_TYPE :
  				WildcardBinding wildcardBinding = (WildcardBinding) this.binding;
  				if (wildcardBinding.genericType != null) {
  					return this.resolver.getTypeBinding(wildcardBinding.genericType);
  				}
  				break;
  		}
  		return null;
  	}
  	
  	/* (non-Javadoc)
  	 * @see org.eclipse.jdt.core.dom.ITypeBinding#getRank()
  	 */
  	public int getRank() {
  		switch (this.binding.kind()) {
  			case Binding.WILDCARD_TYPE :
  			case Binding.INTERSECTION_TYPE :
  				WildcardBinding wildcardBinding = (WildcardBinding) this.binding;
  				return wildcardBinding.rank;
  			default:
  				return -1;
  		}
  	}
  	
  	/*
  	 * @see ITypeBinding#getComponentType()
  	 */
  	public ITypeBinding getComponentType() {
  		if (!isArray()) {
  			return null;
  		}
  		ArrayBinding arrayBinding = (ArrayBinding) this.binding;
  		return this.resolver.getTypeBinding(arrayBinding.elementsType());
  	}
  
  	/*
  	 * @see ITypeBinding#getDeclaredFields()
  	 */
  	public synchronized IVariableBinding[] getDeclaredFields() {
  		if (this.prototype != null) {
  			return this.prototype.getDeclaredFields();
  		}
  		if (this.fields != null) {
  			return this.fields;
  		}
  		try {
  			if (isClass() || isInterface() || isEnum()) {
  				ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
  				FieldBinding[] fieldBindings = referenceBinding.availableFields(); // resilience
  				int length = fieldBindings.length;
  				if (length != 0) {
  					int convertedFieldCount = 0;
  					IVariableBinding[] newFields = new IVariableBinding[length];
  					for (int i = 0; i < length; i++) {
  						FieldBinding fieldBinding = fieldBindings[i];
  						IVariableBinding variableBinding = this.resolver.getVariableBinding(fieldBinding);
  						if (variableBinding != null) {
  							newFields[convertedFieldCount++] = variableBinding;
  						}
  					}
  
  					if (convertedFieldCount != length) {
  						if (convertedFieldCount == 0) {
  							return this.fields = NO_VARIABLE_BINDINGS;
  						}
  						System.arraycopy(newFields, 0, (newFields = new IVariableBinding[convertedFieldCount]), 0, convertedFieldCount);
  					}
  					return this.fields = newFields;
  				}
  			}
  		} catch (RuntimeException e) {
  			/* in case a method cannot be resolvable due to missing jars on the classpath
  			 * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
  			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
  			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
  			 */
  			org.eclipse.jdt.internal.core.util.Util.log(e, "Could not retrieve declared fields"); //$NON-NLS-1$
  		}
  		return this.fields = NO_VARIABLE_BINDINGS;
  	}
  
  	/*
  	 * @see ITypeBinding#getDeclaredMethods()
  	 */
  	public synchronized IMethodBinding[] getDeclaredMethods() {
  		if (this.prototype != null) {
  			return this.prototype.getDeclaredMethods();
  		}
  		if (this.methods != null) {
  			return this.methods;
  		}
  		try {
  			if (isClass() || isInterface() || isEnum()) {
  				ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
  				org.eclipse.jdt.internal.compiler.lookup.MethodBinding[] internalMethods = referenceBinding.availableMethods(); // be resilient
  				int length = internalMethods.length;
  				if (length != 0) {
  					int convertedMethodCount = 0;
  					IMethodBinding[] newMethods = new IMethodBinding[length];
  					for (int i = 0; i < length; i++) {
  						org.eclipse.jdt.internal.compiler.lookup.MethodBinding methodBinding = internalMethods[i];
  						if (methodBinding.isDefaultAbstract() || methodBinding.isSynthetic() || (methodBinding.isConstructor() && isInterface())) {
  							continue;
  						}
  						IMethodBinding methodBinding2 = this.resolver.getMethodBinding(methodBinding);
  						if (methodBinding2 != null) {
  							newMethods[convertedMethodCount++] = methodBinding2;
  						}
  					}
  					if (convertedMethodCount != length) {
  						if (convertedMethodCount == 0) {
  							return this.methods = NO_METHOD_BINDINGS;
  						}
  						System.arraycopy(newMethods, 0, (newMethods = new IMethodBinding[convertedMethodCount]), 0, convertedMethodCount);
  					}
  					return this.methods = newMethods;
  				}
  			}
  		} catch (RuntimeException e) {
  			/* in case a method cannot be resolvable due to missing jars on the classpath
  			 * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
  			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
  			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
  			 */
  			org.eclipse.jdt.internal.core.util.Util.log(e, "Could not retrieve declared methods"); //$NON-NLS-1$
  		}
  		return this.methods = NO_METHOD_BINDINGS;
  	}
  
  	/*
  	 * @see ITypeBinding#getDeclaredModifiers()
  	 * @deprecated Use ITypeBinding#getModifiers() instead
  	 */
  	public int getDeclaredModifiers() {
  		return getModifiers();
  	}
  
  	/*
  	 * @see ITypeBinding#getDeclaredTypes()
  	 */
  	public synchronized ITypeBinding[] getDeclaredTypes() { // should not deflect to prototype.
  		if (this.members != null) {
  			return this.members;
  		}
  		try {
  			if (isClass() || isInterface() || isEnum()) {
  				ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
  				ReferenceBinding[] internalMembers = referenceBinding.memberTypes();
  				int length = internalMembers.length;
  				if (length != 0) {
  					ITypeBinding[] newMembers = new ITypeBinding[length];
  					for (int i = 0; i < length; i++) {
  						ITypeBinding typeBinding = this.resolver.getTypeBinding(internalMembers[i]);
  						if (typeBinding == null) {
  							return this.members = NO_TYPE_BINDINGS;
  						}
  						newMembers[i] = typeBinding;
  					}
  					return this.members = newMembers;
  				}
  			}
  		} catch (RuntimeException e) {
  			/* in case a method cannot be resolvable due to missing jars on the classpath
  			 * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
  			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
  			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
  			 */
  			org.eclipse.jdt.internal.core.util.Util.log(e, "Could not retrieve declared methods"); //$NON-NLS-1$
  		}
  		return this.members = NO_TYPE_BINDINGS;
  	}
  
  	/*
  	 * @see ITypeBinding#getDeclaringMethod()
  	 */
  	public synchronized IMethodBinding getDeclaringMethod() {
  		if (this.binding instanceof LocalTypeBinding) {
  			LocalTypeBinding localTypeBinding = (LocalTypeBinding) this.binding;
  			MethodBinding methodBinding = localTypeBinding.enclosingMethod;
  			if (methodBinding != null) {
  				try {
  					return this.resolver.getMethodBinding(localTypeBinding.enclosingMethod);
  				} catch (RuntimeException e) {
  					/* in case a method cannot be resolvable due to missing jars on the classpath
  					 * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
  					 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
  					 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
  					 */
  					org.eclipse.jdt.internal.core.util.Util.log(e, "Could not retrieve declaring method"); //$NON-NLS-1$
  				}
  			}
  		} else if (this.binding.isTypeVariable()) {
  			TypeVariableBinding typeVariableBinding = (TypeVariableBinding) this.binding;
  			Binding declaringElement = typeVariableBinding.declaringElement;
  			if (declaringElement instanceof MethodBinding) {
  				try {
  					return this.resolver.getMethodBinding((MethodBinding)declaringElement);
  				} catch (RuntimeException e) {
  					/* in case a method cannot be resolvable due to missing jars on the classpath
  					 * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
  					 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
  					 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
  					 */
  					org.eclipse.jdt.internal.core.util.Util.log(e, "Could not retrieve declaring method"); //$NON-NLS-1$
  				}
  			}
  		}
  		return null;
  	}
  
  	/*
  	 * @see ITypeBinding#getDeclaringClass()
  	 */
  	public synchronized ITypeBinding getDeclaringClass() {
  		if (isClass() || isInterface() || isEnum()) {
  			ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
  			if (referenceBinding.isNestedType()) {
  				try {
  					return this.resolver.getTypeBinding(referenceBinding.enclosingType());
  				} catch (RuntimeException e) {
  					/* in case a method cannot be resolvable due to missing jars on the classpath
  					 * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
  					 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
  					 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
  					 */
  					org.eclipse.jdt.internal.core.util.Util.log(e, "Could not retrieve declaring class"); //$NON-NLS-1$
  				}
  			}
  		} else if (this.binding.isTypeVariable()) {
  			TypeVariableBinding typeVariableBinding = (TypeVariableBinding) this.binding;
  			Binding declaringElement = typeVariableBinding.isCapture() ? ((CaptureBinding) typeVariableBinding).sourceType : typeVariableBinding.declaringElement;
  			if (declaringElement instanceof ReferenceBinding) {
  				try {
  					return this.resolver.getTypeBinding((ReferenceBinding)declaringElement);
  				} catch (RuntimeException e) {
  					/* in case a method cannot be resolvable due to missing jars on the classpath
  					 * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
  					 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
  					 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
  					 */
  					org.eclipse.jdt.internal.core.util.Util.log(e, "Could not retrieve declaring class"); //$NON-NLS-1$
  				}
  			}
  		}
  		return null;
  	}
  
  	/*
  	 * @see ITypeBinding#getDimensions()
  	 */
  	public int getDimensions() {
  		if (!isArray()) {
  			return 0;
  		}
  		ArrayBinding arrayBinding = (ArrayBinding) this.binding;
  		return arrayBinding.dimensions;
  	}
  
  	/*
  	 * @see ITypeBinding#getElementType()
  	 */
  	public ITypeBinding getElementType() {
  		if (!isArray()) {
  			return null;
  		}
  		ArrayBinding arrayBinding = (ArrayBinding) this.binding;
  		return this.resolver.getTypeBinding(arrayBinding.leafComponentType);
  	}
  
  	/* (non-Javadoc)
  	 * @see org.eclipse.jdt.core.dom.ITypeBinding#getTypeDeclaration()
  	 */
  	public ITypeBinding getTypeDeclaration() {
  		if (this.binding instanceof ParameterizedTypeBinding)
  			return this.resolver.getTypeBinding(((ParameterizedTypeBinding)this.binding).genericType());
  		return this.resolver.getTypeBinding(this.binding.unannotated(false));
  	}
  	
  	/* (non-Javadoc)
  	 * @see org.eclipse.jdt.core.dom.ITypeBinding#getErasure()
  	 */
  	public ITypeBinding getErasure() {
  		return this.resolver.getTypeBinding(this.binding.erasure());
  	}
  	
  	/* (non-Javadoc)
  	 * @see org.eclipse.jdt.core.dom.ITypeBinding#getFunctionalInterfaceMethod
  	 */
  	@Override
  	public IMethodBinding getFunctionalInterfaceMethod() {
  		Scope scope = this.resolver.scope();
  		if (this.binding == null || scope == null)
  			return null;
  		MethodBinding sam = this.binding.getSingleAbstractMethod(scope, true);
  		if (sam == null || !sam.isValidBinding())
  			return null;
  		return this.resolver.getMethodBinding(sam);
  	}
  
  	public synchronized ITypeBinding[] getInterfaces() {
  		if (this.prototype != null) {
  			return this.prototype.getInterfaces();
  		}
  		if (this.interfaces != null) {
  			return this.interfaces;
  		}
  		if (this.binding == null)
  			return this.interfaces = NO_TYPE_BINDINGS;
  		switch (this.binding.kind()) {
  			case Binding.ARRAY_TYPE :
  			case Binding.BASE_TYPE :
  				return this.interfaces = NO_TYPE_BINDINGS;
  		}
  		ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
  		ReferenceBinding[] internalInterfaces = null;
  		try {
  			internalInterfaces = referenceBinding.superInterfaces();
  		} catch (RuntimeException e) {
  			/* in case a method cannot be resolvable due to missing jars on the classpath
  			 * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
  			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
  			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
  			 */
  			org.eclipse.jdt.internal.core.util.Util.log(e, "Could not retrieve interfaces"); //$NON-NLS-1$
  		}
  		int length = internalInterfaces == null ? 0 : internalInterfaces.length;
  		if (length != 0) {
  			ITypeBinding[] newInterfaces = new ITypeBinding[length];
  			int interfacesCounter = 0;
  			for (int i = 0; i < length; i++) {
  				ITypeBinding typeBinding = this.resolver.getTypeBinding(internalInterfaces[i]);
  				if (typeBinding == null) {
  					continue;
  				}
  				newInterfaces[interfacesCounter++] = typeBinding;
  			}
  			if (length != interfacesCounter) {
  				System.arraycopy(newInterfaces, 0, (newInterfaces = new ITypeBinding[interfacesCounter]), 0, interfacesCounter);
  			}
  			return this.interfaces = newInterfaces;
  		}
  		return this.interfaces = NO_TYPE_BINDINGS;
  	}
  
  	public IJavaElement getJavaElement() {
  		JavaElement element = getUnresolvedJavaElement();
  		if (element != null)
  			return element.resolved(this.binding);
  		if (isRecovered()) {
  			IPackageBinding packageBinding = getPackage();
  			if (packageBinding != null) {
  				final IJavaElement javaElement = packageBinding.getJavaElement();
  				if (javaElement != null && javaElement.getElementType() == IJavaElement.PACKAGE_FRAGMENT) {
  					// best effort: we don't know if the recovered binding is a binary or source binding, so go with a simple source type
  					return ((PackageFragment) javaElement).getCompilationUnit(new String(this.binding.sourceName()) + SuffixConstants.SUFFIX_STRING_java).getType(this.getName());
  				}
  			}
  			return null;
  		}
  		return null;
  	}
  
  	private JavaElement getUnresolvedJavaElement() {
  		return getUnresolvedJavaElement(this.binding);
  	}
  	private JavaElement getUnresolvedJavaElement(org.eclipse.jdt.internal.compiler.lookup.TypeBinding typeBinding ) {
  		if (JavaCore.getPlugin() == null) {
  			return null;
  		}
  		if (this.resolver instanceof DefaultBindingResolver) {
  			DefaultBindingResolver defaultBindingResolver = (DefaultBindingResolver) this.resolver;
  			if (!defaultBindingResolver.fromJavaProject) return null;
  			return org.eclipse.jdt.internal.core.util.Util.getUnresolvedJavaElement(
  					typeBinding,
  					defaultBindingResolver.workingCopyOwner,
  					defaultBindingResolver.getBindingsToNodesMap());
  		}
  		return null;
  	}
  
  	/*
  	 * @see IBinding#getKey()
  	 */
  	public String getKey() {
  		if (this.key == null) {
  			this.key = new String(this.binding.computeUniqueKey());
  		}
  		return this.key;
  	}
  
  	/*
  	 * @see IBinding#getKind()
  	 */
  	public int getKind() {
  		return IBinding.TYPE;
  	}
  
  	/*
  	 * @see IBinding#getModifiers()
  	 */
  	public int getModifiers() {
  		if (isClass()) {
  			ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
  			final int accessFlags = referenceBinding.getAccessFlags() & VALID_MODIFIERS;
  			if (referenceBinding.isAnonymousType()) {
  				return accessFlags & ~Modifier.FINAL;
  			}
  			return accessFlags;
  		} else if (isAnnotation()) {
  			ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
  			final int accessFlags = referenceBinding.getAccessFlags() & VALID_MODIFIERS;
  			// clear the AccAbstract, AccAnnotation and the AccInterface bits
  			return accessFlags & ~(ClassFileConstants.AccAbstract | ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation);
  		} else if (isInterface()) {
  			ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
  			final int accessFlags = referenceBinding.getAccessFlags() & VALID_MODIFIERS;
  			// clear the AccAbstract and the AccInterface bits
  			return accessFlags & ~(ClassFileConstants.AccAbstract | ClassFileConstants.AccInterface);
  		} else if (isEnum()) {
  			ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
  			final int accessFlags = referenceBinding.getAccessFlags() & VALID_MODIFIERS;
  			// clear the AccEnum bits
  			return accessFlags & ~ClassFileConstants.AccEnum;
  		} else {
  			return Modifier.NONE;
  		}
  	}
  
  	public String getName() {
  		StringBuffer buffer;
  		switch (this.binding.kind()) {
  
  			case Binding.WILDCARD_TYPE :
  			case Binding.INTERSECTION_TYPE:
  				WildcardBinding wildcardBinding = (WildcardBinding) this.binding;
  				buffer = new StringBuffer();
  				buffer.append(TypeConstants.WILDCARD_NAME);
  				if (wildcardBinding.bound != null) {
  					switch(wildcardBinding.boundKind) {
  				        case Wildcard.SUPER :
  				        	buffer.append(TypeConstants.WILDCARD_SUPER);
  				            break;
  				        case Wildcard.EXTENDS :
  				        	buffer.append(TypeConstants.WILDCARD_EXTENDS);
  					}
  					buffer.append(getBound().getName());
  				}
  				return String.valueOf(buffer);
  
  			case Binding.TYPE_PARAMETER :
  				if (isCapture()) {
  					return NO_NAME;
  				}
  				TypeVariableBinding typeVariableBinding = (TypeVariableBinding) this.binding;
  				return new String(typeVariableBinding.sourceName);
  
  			case Binding.PARAMETERIZED_TYPE :
  				ParameterizedTypeBinding parameterizedTypeBinding = (ParameterizedTypeBinding) this.binding;
  				buffer = new StringBuffer();
  				buffer.append(parameterizedTypeBinding.sourceName());
  				ITypeBinding[] tArguments = getTypeArguments();
  				final int typeArgumentsLength = tArguments.length;
  				if (typeArgumentsLength != 0) {
  					buffer.append('<');
  					for (int i = 0; i < typeArgumentsLength; i++) {
  						if (i > 0) {
  							buffer.append(',');
  						}
  						buffer.append(tArguments[i].getName());
  					}
  					buffer.append('>');
  				}
  				return String.valueOf(buffer);
  
  			case Binding.RAW_TYPE :
  				return getTypeDeclaration().getName();
  
  			case Binding.ARRAY_TYPE :
  				ITypeBinding elementType = getElementType();
  				if (elementType.isLocal() || elementType.isAnonymous() || elementType.isCapture()) {
  					return NO_NAME;
  				}
  				int dimensions = getDimensions();
  				char[] brackets = new char[dimensions * 2];
  				for (int i = dimensions * 2 - 1; i >= 0; i -= 2) {
  					brackets[i] = ']';
  					brackets[i - 1] = '[';
  				}
  				buffer = new StringBuffer(elementType.getName());
  				buffer.append(brackets);
  				return String.valueOf(buffer);
  
  			default :
  				if (isPrimitive() || isNullType()) {
  					BaseTypeBinding baseTypeBinding = (BaseTypeBinding) this.binding;
  					return new String(baseTypeBinding.simpleName);
  				}
  				if (isAnonymous()) {
  					return NO_NAME;
  				}
  				return new String(this.binding.sourceName());
  		}
  	}
  
  	/*
  	 * @see ITypeBinding#getPackage()
  	 */
  	public IPackageBinding getPackage() {
  		switch (this.binding.kind()) {
  			case Binding.BASE_TYPE :
  			case Binding.ARRAY_TYPE :
  			case Binding.TYPE_PARAMETER : // includes capture scenario
  			case Binding.WILDCARD_TYPE :
  			case Binding.INTERSECTION_TYPE:
  			case Binding.INTERSECTION_CAST_TYPE:
  				return null;
  		}
  		ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
  		return this.resolver.getPackageBinding(referenceBinding.getPackage());
  	}
  
  	/**
  	 * @see org.eclipse.jdt.core.dom.ITypeBinding#getQualifiedName()
  	 */
  	public String getQualifiedName() {
  		StringBuffer buffer;
  		switch (this.binding.kind()) {
  
  			case Binding.WILDCARD_TYPE :
  			case Binding.INTERSECTION_TYPE:
  				WildcardBinding wildcardBinding = (WildcardBinding) this.binding;
  				buffer = new StringBuffer();
  				buffer.append(TypeConstants.WILDCARD_NAME);
  				final ITypeBinding bound = getBound();
  				if (bound != null) {
  					switch(wildcardBinding.boundKind) {
  						case Wildcard.SUPER :
  							buffer.append(TypeConstants.WILDCARD_SUPER);
  							break;
  						case Wildcard.EXTENDS :
  							buffer.append(TypeConstants.WILDCARD_EXTENDS);
  					}
  					buffer.append(bound.getQualifiedName());
  				}
  				return String.valueOf(buffer);
  
  			case Binding.RAW_TYPE :
  				return getTypeDeclaration().getQualifiedName();
  
  			case Binding.ARRAY_TYPE :
  				ITypeBinding elementType = getElementType();
  				if (elementType.isLocal() || elementType.isAnonymous() || elementType.isCapture()) {
  					return elementType.getQualifiedName();
  				}
  				final int dimensions = getDimensions();
  				char[] brackets = new char[dimensions * 2];
  				for (int i = dimensions * 2 - 1; i >= 0; i -= 2) {
  					brackets[i] = ']';
  					brackets[i - 1] = '[';
  				}
  				buffer = new StringBuffer(elementType.getQualifiedName());
  				buffer.append(brackets);
  				return String.valueOf(buffer);
  
  			case Binding.TYPE_PARAMETER :
  				if (isCapture()) {
  					return NO_NAME;
  				}
  				TypeVariableBinding typeVariableBinding = (TypeVariableBinding) this.binding;
  				return new String(typeVariableBinding.sourceName);
  
  			case Binding.PARAMETERIZED_TYPE :
  				if (this.binding.isLocalType()) {
  					return NO_NAME;
  				}
  				buffer = new StringBuffer();
  				if (isMember()) {
  					buffer
  						.append(getDeclaringClass().getQualifiedName())
  						.append('.');
  					ParameterizedTypeBinding parameterizedTypeBinding = (ParameterizedTypeBinding) this.binding;
  					buffer.append(parameterizedTypeBinding.sourceName());
  					ITypeBinding[] tArguments = getTypeArguments();
  					final int typeArgumentsLength = tArguments.length;
  					if (typeArgumentsLength != 0) {
  						buffer.append('<');
  						for (int i = 0; i < typeArgumentsLength; i++) {
  							if (i > 0) {
  								buffer.append(',');
  							}
  							buffer.append(tArguments[i].getQualifiedName());
  						}
  						buffer.append('>');
  					}
  					return String.valueOf(buffer);
  				}
  				buffer.append(getTypeDeclaration().getQualifiedName());
  				ITypeBinding[] tArguments = getTypeArguments();
  				final int typeArgumentsLength = tArguments.length;
  				if (typeArgumentsLength != 0) {
  					buffer.append('<');
  					for (int i = 0; i < typeArgumentsLength; i++) {
  						if (i > 0) {
  							buffer.append(',');
  						}
  						buffer.append(tArguments[i].getQualifiedName());
  					}
  					buffer.append('>');
  				}
  				return String.valueOf(buffer);
  			default :
  				if (isAnonymous() || this.binding.isLocalType() || this.binding.isIntersectionCastType()) {
  					return NO_NAME;
  				}
  				if (isPrimitive() || isNullType()) {
  					BaseTypeBinding baseTypeBinding = (BaseTypeBinding) this.binding;
  					return new String(baseTypeBinding.simpleName);
  				}
  				if (isMember()) {
  					buffer = new StringBuffer();
  					buffer
  						.append(getDeclaringClass().getQualifiedName())
  						.append('.');
  					buffer.append(getName());
  					return String.valueOf(buffer);
  				}
  