/*******************************************************************************
 * Copyright (c) 2000, 2018 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Dmitry Stalnov (dstalnov@fusionone.com) - contributed fix for
 *       bug "inline method - doesn't handle implicit cast" (see
 *       https://bugs.eclipse.org/bugs/show_bug.cgi?id=24941).
 *     Rabea Gransberger <rgransberger@gmx.de> - [quick fix] Fix several visibility issues - https://bugs.eclipse.org/394692
 *     Stephan Herrmann - Contribution for Bug 463360 - [override method][null] generating method override should not create redundant null annotations
 *******************************************************************************/
package org.eclipse.jdt.internal.corext.dom;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.eclipse.core.runtime.Assert;

import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
import org.eclipse.jdt.core.dom.Annotation;
import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
import org.eclipse.jdt.core.dom.ArrayAccess;
import org.eclipse.jdt.core.dom.Assignment;
import org.eclipse.jdt.core.dom.CastExpression;
import org.eclipse.jdt.core.dom.ClassInstanceCreation;
import org.eclipse.jdt.core.dom.EnumDeclaration;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.FieldAccess;
import org.eclipse.jdt.core.dom.IBinding;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.IPackageBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.IVariableBinding;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.ParenthesizedExpression;
import org.eclipse.jdt.core.dom.PostfixExpression;
import org.eclipse.jdt.core.dom.PrefixExpression;
import org.eclipse.jdt.core.dom.QualifiedName;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor;
import org.eclipse.jdt.core.dom.SuperFieldAccess;
import org.eclipse.jdt.core.dom.SuperMethodInvocation;

import org.eclipse.jdt.internal.corext.util.JavaModelUtil;

/**
 * JDT-UI-internal helper methods that deal with {@link IBinding}s:
 * <ul>
 * <li>additional operations on {@link IBinding}s and subtypes</li>
 * <li>finding corresponding elements in the type hierarchy</li>
 * <li>resolve bindings from a family of {@link ASTNode} types</li>
 * </ul>
 */
// @see JDTUIHelperClasses
public class Bindings {

	public static final String ARRAY_LENGTH_FIELD_BINDING_STRING= "(array type):length";//$NON-NLS-1$
	private Bindings() {
		// No instance
	}

	/**
	 * Checks if the two bindings are equals. Also works across binding environments.
	 * @param b1 first binding treated as <code>this</code>. So it must
	 *  not be <code>null</code>
	 * @param b2 the second binding.
	 * @return boolean
	 */
	public static boolean equals(IBinding b1, IBinding b2) {
		return b1.isEqualTo(b2);
	}


	/**
	 * Checks if the declarations of two bindings are equals.
	 * Also works across binding environments.
	 * @param b1 first binding, must not be <code>null</code>
	 * @param b2 second binding, must not be <code>null</code>
	 * @return boolean
	 */
	public static boolean equalDeclarations(IBinding b1, IBinding b2) {
		if (b1.getKind() != b2.getKind())
			return false;
		return getDeclaration(b1).isEqualTo(getDeclaration(b2));
	}

	/**
	 * Checks if the two arrays of bindings have the same length and
	 * their elements are equal. Uses
	 * <code>Bindings.equals(IBinding, IBinding)</code> to compare.
	 * @param b1 the first array of bindings. Must not be <code>null</code>.
	 * @param b2 the second array of bindings.
	 * @return boolean
	 */
	public static boolean equals(IBinding[] b1, IBinding[] b2) {
		Assert.isNotNull(b1);
		if (b1 == b2)
			return true;
		if (b2 == null)
			return false;
		if (b1.length != b2.length)
			return false;
		for (int i= 0; i < b1.length; i++) {
			if (! Bindings.equals(b1[i], b2[i]))
				return false;
		}
		return true;
	}

	public static int hashCode(IBinding binding){
		Assert.isNotNull(binding);
		String key= binding.getKey();
		if (key == null)
			return binding.hashCode();
		return key.hashCode();
	}

	/**
	 * Note: this method is for debugging and testing purposes only.
	 * There are tests whose pre-computed test results rely on the returned String's format.
	 * Use org.eclipse.jdt.internal.ui.viewsupport.BindingLabelProvider to present a binding to the user.
	 * 
	 * @param binding the binding
	 * @return a string representation of given binding
	 */
	public static String asString(IBinding binding) {
		if (binding instanceof IMethodBinding)
			return asString((IMethodBinding)binding);
		else if (binding instanceof ITypeBinding)
			return ((ITypeBinding)binding).getQualifiedName();
		else if (binding instanceof IVariableBinding)
			return asString((IVariableBinding)binding);
		return binding.toString();
	}

	private static String asString(IVariableBinding variableBinding) {
		if (! variableBinding.isField())
			return variableBinding.toString();
		if (variableBinding.getDeclaringClass() == null) {
			Assert.isTrue(variableBinding.getName().equals("length"));//$NON-NLS-1$
			return ARRAY_LENGTH_FIELD_BINDING_STRING;
		}
		StringBuilder result= new StringBuilder();
		result.append(variableBinding.getDeclaringClass().getName());
		result.append(':');
		result.append(variableBinding.getName());
		return result.toString();
	}

	private static String asString(IMethodBinding method) {
		StringBuilder result= new StringBuilder();
		result.append(method.getDeclaringClass().getName());
		result.append(':');
		result.append(method.getName());
		result.append('(');
		ITypeBinding[] parameters= method.getParameterTypes();
		int lastComma= parameters.length - 1;
		for (int i= 0; i < parameters.length; i++) {
			ITypeBinding parameter= parameters[i];
			result.append(parameter.getName());
			if (i < lastComma)
				result.append(", "); //$NON-NLS-1$
		}
		result.append(')');
		return result.toString();
	}

	public static String getTypeQualifiedName(ITypeBinding type) {
		List<String> result= new ArrayList<>(5);
		createName(type, false, result);

		StringBuilder buffer= new StringBuilder();
		for (int i= 0; i < result.size(); i++) {
			if (i > 0) {
				buffer.append('.');
			}
			buffer.append(result.get(i));
		}
		return buffer.toString();
	}

	/**
	 * Returns the fully qualified name of the specified type binding.
	 * <p>
	 * If the binding resolves to a generic type, the fully qualified name of the raw type is returned.
	 *
	 * @param type the type binding to get its fully qualified name
	 * @return the fully qualified name
	 */
	public static String getFullyQualifiedName(ITypeBinding type) {
		String name= type.getQualifiedName();
		final int index= name.indexOf('<');
		if (index > 0)
			name= name.substring(0, index);
		return name;
	}

	public static String getImportName(IBinding binding) {
		ITypeBinding declaring= null;
		switch (binding.getKind()) {
			case IBinding.TYPE:
				return getRawQualifiedName((ITypeBinding) binding);
			case IBinding.PACKAGE:
				return binding.getName() + ".*"; //$NON-NLS-1$
			case IBinding.METHOD:
				declaring= ((IMethodBinding) binding).getDeclaringClass();
				break;
			case IBinding.VARIABLE:
				declaring= ((IVariableBinding) binding).getDeclaringClass();
				if (declaring == null) {
					return binding.getName(); // array.length
				}

				break;
			default:
				return binding.getName();
		}
		return JavaModelUtil.concatenateName(getRawQualifiedName(declaring), binding.getName());
	}


	private static void createName(ITypeBinding type, boolean includePackage, List<String> list) {
		ITypeBinding baseType= type;
		if (type.isArray()) {
			baseType= type.getElementType();
		}
		if (!baseType.isPrimitive() && !baseType.isNullType()) {
			ITypeBinding declaringType= baseType.getDeclaringClass();
			if (declaringType != null) {
				createName(declaringType, includePackage, list);
			} else if (includePackage && !baseType.getPackage().isUnnamed()) {
				String[] components= baseType.getPackage().getNameComponents();
				list.addAll(Arrays.asList(components));
			}
		}
		if (!baseType.isAnonymous()) {
			list.add(type.getName());
		} else {
			list.add("$local$"); //$NON-NLS-1$
		}
	}


	public static String[] getNameComponents(ITypeBinding type) {
		List<String> result= new ArrayList<>(5);
		createName(type, false, result);
		return result.toArray(new String[result.size()]);
	}

	public static String[] getAllNameComponents(ITypeBinding type) {
		List<String> result= new ArrayList<>(5);
		createName(type, true, result);
		return result.toArray(new String[result.size()]);
	}

	public static ITypeBinding getTopLevelType(ITypeBinding type) {
		ITypeBinding parent= type.getDeclaringClass();
		while (parent != null) {
			type= parent;
			parent= type.getDeclaringClass();
		}
		return type;
	}

	/**
	 * Checks whether the passed type binding is a runtime exception.
	 *
	 * @param thrownException the type binding
	 *
	 * @return <code>true</code> if the passed type binding is a runtime exception;
	 * 	otherwise <code>false</code> is returned
	 */
	public static boolean isRuntimeException(ITypeBinding thrownException) {
		if (thrownException == null || thrownException.isPrimitive() || thrownException.isArray())
			return false;
		return findTypeInHierarchy(thrownException, "java.lang.RuntimeException") != null; //$NON-NLS-1$
	}

	/**
	 * Finds the field specified by <code>fieldName</code> in
	 * the given <code>type</code>. Returns <code>null</code> if no such field exists.
	 * @param type the type to search the field in
	 * @param fieldName the field name
	 * @return the binding representing the field or <code>null</code>
	 */
	public static IVariableBinding findFieldInType(ITypeBinding type, String fieldName) {
		if (type.isPrimitive())
			return null;
		IVariableBinding[] fields= type.getDeclaredFields();
		for (int i= 0; i < fields.length; i++) {
			IVariableBinding field= fields[i];
			if (field.getName().equals(fieldName))
				return field;
		}
		return null;
	}

	/**
	 * Finds the field specified by <code>fieldName</code> in
	 * the type hierarchy denoted by the given type. Returns <code>null</code> if no such field
	 * exists. If the field is defined in more than one super type only the first match is
	 * returned. First the super class is examined and then the implemented interfaces.
	 * @param type The type to search the field in
	 * @param fieldName The name of the field to find
	 * @return the variable binding representing the field
	 */
	public static IVariableBinding findFieldInHierarchy(ITypeBinding type, String fieldName) {
		IVariableBinding field= findFieldInType(type, fieldName);
		if (field != null)
			return field;
		ITypeBinding superClass= type.getSuperclass();
		if (superClass != null) {
			field= findFieldInHierarchy(superClass, fieldName);
			if (field != null)
				return field;
		}
		ITypeBinding[] interfaces= type.getInterfaces();
		for (int i= 0; i < interfaces.length; i++) {
			field= findFieldInHierarchy(interfaces[i], fieldName);
			if (field != null) // no private fields in interfaces
				return field;
		}
		return null;
	}

	/**
	 * Finds the method specified by <code>methodName</code> and <code>parameters</code> in
	 * the given <code>type</code>. Returns <code>null</code> if no such method exists.
	 * @param type The type to search the method in
	 * @param methodName The name of the method to find
	 * @param parameters The parameter types of the method to find. If <code>null</code> is passed, only
	 *  the name is matched and parameters are ignored.
	 * @return the method binding representing the method
	 */
	public static IMethodBinding findMethodInType(ITypeBinding type, String methodName, ITypeBinding[] parameters) {
		if (type.isPrimitive())
			return null;
		IMethodBinding[] methods= type.getDeclaredMethods();
		for (int i= 0; i < methods.length; i++) {
			if (parameters == null) {
				if (methodName.equals(methods[i].getName()))
					return methods[i];
			} else {
				if (isEqualMethod(methods[i], methodName, parameters))
					return methods[i];
			}
		}
		return null;
	}

	/**
	 * Finds the method specified by <code>methodName</code> and <code>parameters</code> in
	 * the type hierarchy denoted by the given type. Returns <code>null</code> if no such method
	 * exists. If the method is defined in more than one super type only the first match is
	 * returned. First the super class is examined and then the implemented interfaces.
	 * 
	 * @param type The type to search the method in
	 * @param methodName The name of the method to find
	 * @param parameters The parameter types of the method to find. If <code>null</code> is passed, only the name is matched and parameters are ignored.
	 * @return the method binding representing the method
	 */
	public static IMethodBinding findMethodInHierarchy(ITypeBinding type, String methodName, ITypeBinding[] parameters) {
		IMethodBinding method= findMethodInType(type, methodName, parameters);
		if (method != null)
			return method;
		ITypeBinding superClass= type.getSuperclass();
		if (superClass != null) {
			method= findMethodInHierarchy(superClass, methodName, parameters);
			if (method != null)
				return method;
		}
		ITypeBinding[] interfaces= type.getInterfaces();
		for (int i= 0; i < interfaces.length; i++) {
			method= findMethodInHierarchy(interfaces[i], methodName, parameters);
			if (method != null)
				return method;
		}
		return null;
	}

	/**
	 * Finds the method specified by <code>methodName</code> and <code>parameters</code> in
	 * the given <code>type</code>. Returns <code>null</code> if no such method exists.
	 * @param type The type to search the method in
	 * @param methodName The name of the method to find
	 * @param parameters The parameter types of the method to find. If <code>null</code> is passed, only the name is matched and parameters are ignored.
	 * @return the method binding representing the method
	 */
	public static IMethodBinding findMethodInType(ITypeBinding type, String methodName, String[] parameters) {
		if (type.isPrimitive())
			return null;
		IMethodBinding[] methods= type.getDeclaredMethods();
		for (int i= 0; i < methods.length; i++) {
			if (parameters == null) {
				if (methodName.equals(methods[i].getName()))
					return methods[i];
			} else {
				if (isEqualMethod(methods[i], methodName, parameters))
					return methods[i];
			}
		}
		return null;
	}

	/**
	 * Finds the method specified by <code>methodName</code> and <code>parameters</code> in
	 * the given <code>type</code>. Returns <code>null</code> if no such method exists.
	 * <p>
	 * This variant of {@link #findMethodInType(ITypeBinding, String, String[])} looks for a method
	 * whose {@link IMethodBinding#getMethodDeclaration() declaration}'s parameters matches the
	 * given parameters.
	 * </p>
	 * 
	 * @param type The type to search the method in
	 * @param methodName The name of the method to find
	 * @param parameters The parameter types of the method to find. If <code>null</code> is passed, only the name is matched and parameters are ignored.
	 * @return the method binding representing the method
	 */
	public static IMethodBinding findMethodWithDeclaredParameterTypesInType(ITypeBinding type, String methodName, String[] parameters) {
		if (type.isPrimitive())
			return null;
		IMethodBinding[] methods= type.getDeclaredMethods();
		for (int i= 0; i < methods.length; i++) {
			if (parameters == null) {
				if (methodName.equals(methods[i].getName()))
					return methods[i];
			} else {
				if (isEqualMethod(methods[i].getMethodDeclaration(), methodName, parameters))
					return methods[i];
			}
		}
		return null;
	}
	
	/**
	 * Finds the method specified by <code>methodName</code> and <code>parameters</code> in
	 * the type hierarchy denoted by the given type. Returns <code>null</code> if no such method
	 * exists. If the method is defined in more than one super type only the first match is
	 * returned. First the super class is examined and then the implemented interfaces.
	 * @param type the type to search the method in
	 * @param methodName The name of the method to find
	 * @param parameters The parameter types of the method to find. If <code>null</code> is passed, only the name is matched and parameters are ignored.
	 * @return the method binding representing the method
	 */
	public static IMethodBinding findMethodInHierarchy(ITypeBinding type, String methodName, String[] parameters) {
		IMethodBinding method= findMethodInType(type, methodName, parameters);
		if (method != null)
			return method;
		ITypeBinding superClass= type.getSuperclass();
		if (superClass != null) {
			method= findMethodInHierarchy(superClass, methodName, parameters);
			if (method != null)
				return method;
		}
		ITypeBinding[] interfaces= type.getInterfaces();
		for (int i= 0; i < interfaces.length; i++) {
			method= findMethodInHierarchy(interfaces[i], methodName, parameters);
			if (method != null)
				return method;
		}
		return null;
	}

	/**
	 * Finds the method in the given <code>type</code> that is overridden by the specified <code>method</code>.
	 * Returns <code>null</code> if no such method exists.
	 * @param type The type to search the method in
	 * @param method The specified method that would override the result
	 * @return the method binding of the method that is overridden by the specified <code>method</code>, or <code>null</code>
	 */
	public static IMethodBinding findOverriddenMethodInType(ITypeBinding type, IMethodBinding method) {
		IMethodBinding[] methods= type.getDeclaredMethods();
		for (int i= 0; i < methods.length; i++) {
			if (isSubsignature(method, methods[i]))
				return methods[i];
		}
		return null;
	}

	/**
	 * Finds a method in the hierarchy of <code>type</code> that is overridden by <code>binding</code>.
	 * Returns <code>null</code> if no such method exists. If the method is defined in more than one super type only the first match is
	 * returned. First the super class is examined and then the implemented interfaces.
	 * @param type The type to search the method in
	 * @param binding The method that overrides
	 * @return the method binding overridden the method
	 */
	public static IMethodBinding findOverriddenMethodInHierarchy(ITypeBinding type, IMethodBinding binding) {
		IMethodBinding method= findOverriddenMethodInType(type, binding);
		if (method != null)
			return method;
		ITypeBinding superClass= type.getSuperclass();
		if (superClass != null) {
			method= findOverriddenMethodInHierarchy(superClass, binding);
			if (method != null)
				return method;
		}
		ITypeBinding[] interfaces= type.getInterfaces();
		for (int i= 0; i < interfaces.length; i++) {
			method= findOverriddenMethodInHierarchy(interfaces[i], binding);
			if (method != null)
				return method;
		}
		return null;
	}


	/**
	 * Finds the method that is overridden by the given method. The search is bottom-up, so this
	 * returns the nearest defining/declaring method.
	 * @param overriding overriding method
	 * @param testVisibility If true the result is tested on visibility. Null is returned if the method is not visible.
	 * @return the method binding representing the method
	 */
	public static IMethodBinding findOverriddenMethod(IMethodBinding overriding, boolean testVisibility) {
		List<IMethodBinding> findOverriddenMethods= findOverriddenMethods(overriding, testVisibility, true);
		if (findOverriddenMethods.isEmpty()) {
			return null;
		}
		return findOverriddenMethods.get(0);
	}
	
	/**
	 * Finds all methods that are overridden by the given method. The search is bottom-up, so this
	 * returns the nearest defining/declaring methods in order.
	 * 
	 * @param overriding overriding method
	 * @param testVisibility if <code>true</code> the result is tested on visibility
	 * @param firstOnly if <code>true</code> this method will return when the first overridden
	 *            method is found
	 * @return the method bindings representing the overridden method or an empty list if no result
	 *         is found
	 * @since 3.9
	 */
	public static List<IMethodBinding> findOverriddenMethods(IMethodBinding overriding, boolean testVisibility, boolean firstOnly) {
		List<IMethodBinding> methodList= new ArrayList<>();

		int modifiers= overriding.getModifiers();
		if (Modifier.isPrivate(modifiers) || Modifier.isStatic(modifiers) || overriding.isConstructor()) {
			return methodList;
		}

		ITypeBinding type= overriding.getDeclaringClass();
		if (type.getSuperclass() != null) {
			IMethodBinding res= findOverriddenMethodInHierarchy(type.getSuperclass(), overriding);
			if (res != null && !Modifier.isPrivate(res.getModifiers())) {
				if (!testVisibility || isVisibleInHierarchy(res, overriding.getDeclaringClass().getPackage())) {
					methodList.add(res);
					if (firstOnly) {
						return methodList;
					}
				}
			}
		}
		ITypeBinding[] interfaces= type.getInterfaces();
		for (int i= 0; i < interfaces.length; i++) {
			IMethodBinding res= findOverriddenMethodInHierarchy(interfaces[i], overriding);
			if (res != null) {
				methodList.add(res); // methods from interfaces are always public and therefore visible
				if (firstOnly) {
					return methodList;
				}
			}
		}
		return methodList;
	}


	public static boolean isVisibleInHierarchy(IMethodBinding member, IPackageBinding pack) {
		int otherflags= member.getModifiers();
		ITypeBinding declaringType= member.getDeclaringClass();
		if (Modifier.isPublic(otherflags) || Modifier.isProtected(otherflags) || (declaringType != null && declaringType.isInterface())) {
			return true;
		} else if (Modifier.isPrivate(otherflags)) {
			return false;
		}
		return declaringType != null && pack == declaringType.getPackage();
	}

	/**
	 * Returns all super types (classes and interfaces) for the given type.
	 * @param type The type to get the supertypes of.
	 * @return all super types (excluding <code>type</code>)
	 */
	public static ITypeBinding[] getAllSuperTypes(ITypeBinding type) {
		Set<ITypeBinding> result= new HashSet<>();
		collectSuperTypes(type, result);
		result.remove(type);
		return result.toArray(new ITypeBinding[result.size()]);
	}

	private static void collectSuperTypes(ITypeBinding curr, Set<ITypeBinding> collection) {
		if (collection.add(curr)) {
			ITypeBinding[] interfaces= curr.getInterfaces();
			for (int i= 0; i < interfaces.length; i++) {
				collectSuperTypes(interfaces[i], collection);
			}
			ITypeBinding superClass= curr.getSuperclass();
			if (superClass != null) {
				collectSuperTypes(superClass, collection);
			}
		}
	}

	/**
	 * Method to visit a type hierarchy defined by a given type.
	 * The given type itself is not visited.
	 *
	 * @param type the type whose hierarchy is to be visited
	 * @param visitor the visitor
	 * @return <code>true</code> if all types were visited,
	 *         or <code>false</code> if the visiting got aborted because the <code>visit</code>
	 *         method returned <code>false</code> for a type
	 */
	public static boolean visitHierarchy(ITypeBinding type, TypeBindingVisitor visitor) {
		boolean result= visitSuperclasses(type, visitor);
		if (result) {
			result= visitInterfaces(type, visitor);
		}
		return result;
	}

	/**
	 * Method to visit an interface hierarchy defined by a given type.
	 * The given type itself is not visited.
	 *
	 * @param type the type whose interface hierarchy is to be visited
	 * @param visitor the visitor
	 * @return <code>true</code> if all types were visited,
	 *         or <code>false</code> if the visiting got aborted because the <code>visit</code>
	 *         method returned <code>false</code> for a type
	 */
	public static boolean visitInterfaces(ITypeBinding type, TypeBindingVisitor visitor) {
		return visitInterfaces(type, visitor, new HashSet<ITypeBinding>());
	}

	private static boolean visitInterfaces(ITypeBinding type, TypeBindingVisitor visitor, HashSet<ITypeBinding> visited) {
		boolean unvisited= visited.add(type);
		if (!unvisited)
			return true;
		ITypeBinding[] interfaces= type.getInterfaces();
		for (int i= 0; i < interfaces.length; i++) {
			if (!visitor.visit(interfaces[i])) {
				return false;
			}
			if (!visitInterfaces(interfaces[i], visitor, visited)) {
				return false;
			}
		}
		return true;
	}

	/**
	 * Method to visit a super class hierarchy defined by a given type.
	 * The given type itself is not visited.
	 *
	 * @param type the type whose super class hierarchy is to be visited
	 * @param visitor the visitor
	 * @return <code>true</code> if all types were visited,
	 *         or <code>false</code> if the visiting got aborted because the <code>visit</code>
	 *         method returned <code>false</code> for a type
	 */
	public static boolean visitSuperclasses(ITypeBinding type, TypeBindingVisitor visitor) {
		while ((type= type.getSuperclass()) != null) {
			if (!visitor.visit(type)) {
				return false;
			}
		}
		return true;
	}

	/**
	 * Tests whether the two methods are erasure-equivalent.
	 * @param method the first method
	 * @param methodName the name of the second method
	 * @param parameters the parameters of the second method
	 * @return return <code>true</code> if the two bindings are equal
	 * @deprecated use {@link #isSubsignature(IMethodBinding, IMethodBinding)}
	 */
	//TODO: rename to isErasureEquivalentMethod and change to two IMethodBinding parameters
	@Deprecated
	public static boolean isEqualMethod(IMethodBinding method, String methodName, ITypeBinding[] parameters) {
		if (!method.getName().equals(methodName))
			return false;

		ITypeBinding[] methodParameters= method.getParameterTypes();
		if (methodParameters.length != parameters.length)
			return false;
		for (int i= 0; i < parameters.length; i++) {
			if (!equals(methodParameters[i].getErasure(), parameters[i].getErasure()))
				return false;
		}
		//Can't use this fix, since some clients assume that this method tests erasure equivalence:
//		if (method.getTypeParameters().length == 0) {
//			//a method without type parameters cannot be overridden by one that declares type parameters -> can be exact here
//			for (int i= 0; i < parameters.length; i++) {
//				if ( ! (equals(methodParameters[i], parameters[i])
//						|| equals(methodParameters[i].getErasure(), parameters[i]))) // subsignature
//					return false;
//			}
//		} else {
//			//this will find all overridden methods, but may generate false positives in some cases:
//			for (int i= 0; i < parameters.length; i++) {
//				if (!equals(methodParameters[i].getErasure(), parameters[i].getErasure()))
//					return false;
//			}
//		}
		return true;
	}

	/**
	 * @param overriding overriding method (m1)
	 * @param overridden overridden method (m2)
	 * @return <code>true</code> iff the method <code>m1</code> is a subsignature of the method <code>m2</code>.
	 * 		This is one of the requirements for m1 to override m2.
	 * 		Accessibility and return types are not taken into account.
	 * 		Note that subsignature is <em>not</em> symmetric!
	 */
	public static boolean isSubsignature(IMethodBinding overriding, IMethodBinding overridden) {
		//TODO: use IMethodBinding#isSubsignature(..) once it is tested and fixed (only erasure of m1's parameter types, considering type variable counts, doing type variable substitution
		if (!overriding.getName().equals(overridden.getName()))
			return false;

		ITypeBinding[] m1Params= overriding.getParameterTypes();
		ITypeBinding[] m2Params= overridden.getParameterTypes();
		if (m1Params.length != m2Params.length)
			return false;

		ITypeBinding[] m1TypeParams= overriding.getTypeParameters();
		ITypeBinding[] m2TypeParams= overridden.getTypeParameters();
		if (m1TypeParams.length != m2TypeParams.length
				&& m1TypeParams.length != 0) //non-generic m1 can override a generic m2
			return false;

		//m1TypeParameters.length == (m2TypeParameters.length || 0)
		if (m2TypeParams.length != 0) {
			//Note: this branch does not 100% adhere to the spec and may report some false positives.
			// Full compliance would require major duplication of compiler code.

			//Compare type parameter bounds:
			for (int i= 0; i < m1TypeParams.length; i++) {
				// loop over m1TypeParams, which is either empty, or equally long as m2TypeParams
				Set<ITypeBinding> m1Bounds= getTypeBoundsForSubsignature(m1TypeParams[i]);
				Set<ITypeBinding> m2Bounds= getTypeBoundsForSubsignature(m2TypeParams[i]);
				if (! m1Bounds.equals(m2Bounds))
					return false;
			}
			//Compare parameter types:
			if (equals(m2Params, m1Params))
				return true;
			for (int i= 0; i < m1Params.length; i++) {
				ITypeBinding m1Param= m1Params[i];
				ITypeBinding m2Param= m2Params[i];
				if (containsTypeVariables(m1Param) || m1Param.isRawType())
					m1Param= m1Param.getErasure(); // try to achieve effect of "rename type variables"
				if (! (equals(m1Param, m2Param) || equals(m1Param, m2Param.getErasure())))
					return false;
			}
			return true;

		} else {
			// m1TypeParams.length == m2TypeParams.length == 0
			if (equals(m1Params, m2Params))
				return true;
			for (int i= 0; i < m1Params.length; i++) {
				ITypeBinding m1Param= m1Params[i];
				ITypeBinding m2Param= m2Params[i];
				if (m1Param.isRawType())
					m1Param= m1Param.getTypeDeclaration();
				if (! (equals(m1Param, m2Param) || equals(m1Param, m2Param.getErasure())))
					return false;
			}
			return true;
		}
	}

	public static boolean containsTypeVariables(ITypeBinding type) {
		if (type.isTypeVariable())
			return true;
		if (type.isArray())
			return containsTypeVariables(type.getElementType());
		if (type.isCapture())
			return containsTypeVariables(type.getWildcard());
		if (type.isParameterizedType())
			return containsTypeVariables(type.getTypeArguments());
		if (type.isWildcardType() && type.getBound() != null)
			return containsTypeVariables(type.getBound());
		return false;
	}

	private static boolean containsTypeVariables(ITypeBinding[] types) {
		for (int i= 0; i < types.length; i++)
			if (containsTypeVariables(types[i]))
				return true;
		return false;
	}

	private static Set<ITypeBinding> getTypeBoundsForSubsignature(ITypeBinding typeParameter) {
		ITypeBinding[] typeBounds= typeParameter.getTypeBounds();
		int count= typeBounds.length;
		if (count == 0)
			return Collections.emptySet();

		Set<ITypeBinding> result= new HashSet<>(typeBounds.length);
		for (int i= 0; i < typeBounds.length; i++) {
			ITypeBinding bound= typeBounds[i];
			if ("java.lang.Object".equals(typeBounds[0].getQualifiedName())) //$NON-NLS-1$
				continue;
			else if (containsTypeVariables(bound))
				result.add(bound.getErasure()); // try to achieve effect of "rename type variables"
			else if (bound.isRawType())
				result.add(bound.getTypeDeclaration());
			else
				result.add(bound);
		}
		return result;
	}

	/**
	 * Checks whether a method with the given name and parameter types
	 * is a subsignature of the given method binding.
	 * 
	 * @param method a method
	 * @param methodName method name to match
	 * @param parameters the parameter types of the method to find. If <code>null</code> is passed, only the name is matched and parameters are ignored.
	 * @return <code>true</code> iff the method
	 * 		m1 (with name <code>methodName</code> and method parameters <code>parameters</code>)
	 * 		is a subsignature of the method <code>m2</code>. Accessibility and return types are not taken into account.
	 */
	public static boolean isEqualMethod(IMethodBinding method, String methodName, String[] parameters) {
		if (!method.getName().equals(methodName))
			return false;

		ITypeBinding[] methodParameters= method.getParameterTypes();
		if (methodParameters.length != parameters.length)
			return false;
		String first, second;
		int index;
		for (int i= 0; i < parameters.length; i++) {
			first= parameters[i];
			index= first.indexOf('<');
			if (index > 0){
				int lastIndex= first.lastIndexOf('>');
				StringBuilder buf= new StringBuilder();
				buf.append(first.substring(0, index));
				if (lastIndex < first.length() - 1)
					buf.append(first.substring(lastIndex + 1, first.length()));
				first= buf.toString();
			}
			second= methodParameters[i].getQualifiedName();
			if (!first.equals(second)) {
				second= methodParameters[i].getErasure().getQualifiedName();
				if (!first.equals(second))
					return false;
			}
		}
		return true;
	}

	/**
	 * Finds a type binding for a given fully qualified type in the hierarchy of a type.
	 * Returns <code>null</code> if no type binding is found.
	 * @param hierarchyType the binding representing the hierarchy
	 * @param fullyQualifiedTypeName the fully qualified name to search for
	 * @return the type binding
	 */
	public static ITypeBinding findTypeInHierarchy(ITypeBinding hierarchyType, String fullyQualifiedTypeName) {
		if (hierarchyType.isArray() || hierarchyType.isPrimitive()) {
			return null;
		}
		if (fullyQualifiedTypeName.equals(hierarchyType.getTypeDeclaration().getQualifiedName())) {
			return hierarchyType;
		}
		ITypeBinding superClass= hierarchyType.getSuperclass();
		if (superClass != null) {
			ITypeBinding res= findTypeInHierarchy(superClass, fullyQualifiedTypeName);
			if (res != null) {
				return res;
			}
		}
		ITypeBinding[] superInterfaces= hierarchyType.getInterfaces();
		for (int i= 0; i < superInterfaces.length; i++) {
			ITypeBinding res= findTypeInHierarchy(superInterfaces[i], fullyQualifiedTypeName);
			if (res != null) {
				return res;
			}
		}
		return null;
	}

	/**
	 * Searches for a type binding for a given fully qualified type in the hierarchy of a type.
	 * Returns the immediate super type in whose supertype hierarchy the given type appears, or <code>null</code> if no type binding is found.
	 * @param hierarchyType the binding representing the hierarchy
	 * @param fullyQualifiedTypeName the fully qualified name to search for
	 * @return the type binding
	 */
	public static ITypeBinding findImmediateSuperTypeInHierarchy(ITypeBinding hierarchyType, String fullyQualifiedTypeName) {
		if (hierarchyType.isArray() || hierarchyType.isPrimitive()) {
			return null;
		}
		ITypeBinding superClass= hierarchyType.getSuperclass();
		if (superClass != null) {
			ITypeBinding res= findTypeInHierarchy(superClass, fullyQualifiedTypeName);
			if (res != null) {
				return superClass;
			}
		}
		ITypeBinding[] superInterfaces= hierarchyType.getInterfaces();
		for (int i= 0; i < superInterfaces.length; i++) {
			ITypeBinding res= findTypeInHierarchy(superInterfaces[i], fullyQualifiedTypeName);
			if (res != null) {
				return superInterfaces[i];
			}
		}
		return null;
	}
	
	/**
	 * Returns the binding of the variable written in an Assignment.
	 * @param assignment The assignment
	 * @return The binding or <code>null</code> if no bindings are available.
	 */
	public static IVariableBinding getAssignedVariable(Assignment assignment) {
		Expression leftHand = assignment.getLeftHandSide();
		switch (leftHand.getNodeType()) {
			case ASTNode.SIMPLE_NAME:
				return (IVariableBinding) ((SimpleName) leftHand).resolveBinding();
			case ASTNode.QUALIFIED_NAME:
				return (IVariableBinding) ((QualifiedName) leftHand).getName().resolveBinding();
			case ASTNode.FIELD_ACCESS:
				return ((FieldAccess) leftHand).resolveFieldBinding();
			case ASTNode.SUPER_FIELD_ACCESS:
				return ((SuperFieldAccess) leftHand).resolveFieldBinding();
			default:
				return null;
		}
	}

	/**
	 * Returns <code>true</code> if the given type is a super type of a candidate.
	 * <code>true</code> is returned if the two type bindings are identical.
	 * 
	 * <p><b>Warning:</b> With the addition of generics, this method is valid in less
	 * cases than before. Consider using {@link TypeRules#canAssign(ITypeBinding, ITypeBinding)}
	 * if you're dealing with types of variables. The classical notion of supertypes
	 * only makes sense if you really need to walk the type hierarchy but don't need to play
	 * the assignment rules.</p>
	 * 
	 * @param possibleSuperType the type to inspect
	 * @param type the type whose super types are looked at
	 * @return <code>true</code> iff <code>possibleSuperType</code> is
	 * 		a super type of <code>type</code> or is equal to it
	 */
	public static boolean isSuperType(ITypeBinding possibleSuperType, ITypeBinding type) {
		return isSuperType(possibleSuperType, type, true);
	}
	
	/**
	 * Returns <code>true</code> if the given type is a super type of a candidate.
	 * <code>true</code> is returned if the two type bindings are identical (TODO)
	 * @param possibleSuperType the type to inspect
	 * @param type the type whose super types are looked at
	 * @param considerTypeArguments if <code>true</code>, consider type arguments of <code>type</code>
	 * @return <code>true</code> iff <code>possibleSuperType</code> is
	 * 		a super type of <code>type</code> or is equal to it
	 */
	public static boolean isSuperType(ITypeBinding possibleSuperType, ITypeBinding type, boolean considerTypeArguments) {
		if (type.isArray() || type.isPrimitive()) {
			return false;
		}
		if (! considerTypeArguments) {
			type= type.getTypeDeclaration();
		}
		if (Bindings.equals(type, possibleSuperType)) {
			return true;
		}
		ITypeBinding superClass= type.getSuperclass();
		if (superClass != null) {
			if (isSuperType(possibleSuperType, superClass, considerTypeArguments)) {
				return true;
			}
		}

		if (possibleSuperType.isInterface()) {
			ITypeBinding[] superInterfaces= type.getInterfaces();
			for (int i= 0; i < superInterfaces.length; i++) {
				if (isSuperType(possibleSuperType, superInterfaces[i], considerTypeArguments)) {
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * Finds the compilation unit where the type of the given <code>ITypeBinding</code> is defined,
	 * using the class path defined by the given Java project. Returns <code>null</code>
	 * if no compilation unit is found (e.g. type binding is from a binary type)
	 * @param typeBinding the type binding to search for
	 * @param project the project used as a scope
	 * @return the compilation unit containing the type
	 * @throws JavaModelException if an errors occurs in the Java model
	 */
	public static ICompilationUnit findCompilationUnit(ITypeBinding typeBinding, IJavaProject project) throws JavaModelException {
		IJavaElement type= typeBinding.getJavaElement();
		if (type instanceof IType)
			return ((IType) type).getCompilationUnit();
		else
			return null;
	}

	/**
	 * Finds a method for the given <code>IMethodBinding</code>. Returns
	 * <code>null</code> if the type doesn't contain a corresponding method.
	 * @param method the method to find
	 * @param type the type to look in
	 * @return the corresponding IMethod or <code>null</code>
	 * @throws JavaModelException if an error occurs in the Java model
	 * @deprecated Use {@link #findMethodInHierarchy(ITypeBinding, String, String[])} or {@link JavaModelUtil}
	 */
	@Deprecated
	public static IMethod findMethod(IMethodBinding method, IType type) throws JavaModelException {
		method= method.getMethodDeclaration();

		IMethod[] candidates= type.getMethods();
		for (int i= 0; i < candidates.length; i++) {
			IMethod candidate= candidates[i];
			if (candidate.getElementName().equals(method.getName()) && sameParameters(method, candidate)) {
				return candidate;
			}
		}
		return null;
	}

	//---- Helper methods to convert a method ---------------------------------------------

	private static boolean sameParameters(IMethodBinding method, IMethod candidate) throws JavaModelException {
		ITypeBinding[] methodParamters= method.getParameterTypes();
		String[] candidateParameters= candidate.getParameterTypes();
		if (methodParamters.length != candidateParameters.length)
			return false;
		IType scope= candidate.getDeclaringType();
		for (int i= 0; i < methodParamters.length; i++) {
			ITypeBinding methodParameter= methodParamters[i];
			String candidateParameter= candidateParameters[i];
			if (!sameParameter(methodParameter, candidateParameter, scope))
				return false;
		}
		return true;
	}

	private static boolean sameParameter(ITypeBinding type, String candidate, IType scope) throws JavaModelException {
		if (type.getDimensions() != Signature.getArrayCount(candidate))
			return false;

		// Normalizes types
		if (type.isArray())
			type= type.getElementType();
		candidate= Signature.getElementType(candidate);

		if ((Signature.getTypeSignatureKind(candidate) == Signature.BASE_TYPE_SIGNATURE) != type.isPrimitive()) {
			return false;
		}

		if (type.isPrimitive() || type.isTypeVariable()) {
			return type.getName().equals(Signature.toString(candidate));
		} else {
			// normalize (quick hack until binding.getJavaElement works)
			candidate= Signature.getTypeErasure(candidate);
			type= type.getErasure();

			if (candidate.charAt(Signature.getArrayCount(candidate)) == Signature.C_RESOLVED) {
				return Signature.toString(candidate).equals(Bindings.getFullyQualifiedName(type));
			} else {
				String[][] qualifiedCandidates= scope.resolveType(Signature.toString(candidate));
				if (qualifiedCandidates == null || qualifiedCandidates.length == 0)
					return false;
				String packageName= type.getPackage().isUnnamed() ? "" : type.getPackage().getName(); //$NON-NLS-1$
				String typeName= getTypeQualifiedName(type);
				for (int i= 0; i < qualifiedCandidates.length; i++) {
					String[] qualifiedCandidate= qualifiedCandidates[i];
					if (	qualifiedCandidate[0].equals(packageName) &&
							qualifiedCandidate[1].equals(typeName))
						return true;
				}
			}
		}
		return false;
	}

	/**
	 * Normalizes a type binding received from an expression to a type binding that can be used inside a
	 * declaration signature, but <em>not</em> as type of a declaration (use {@link #normalizeForDeclarationUse(ITypeBinding, AST)} for that).
	 * <p>
	 * Anonymous types are normalized to the super class or interface. For
	 * null or void bindings, <code>null</code> is returned.
	 * </p>
	 * 
	 * @param binding the binding to normalize
	 * @return the normalized binding, can be <code>null</code>
	 * 
	 * @see #normalizeForDeclarationUse(ITypeBinding, AST)
	 */
	public static ITypeBinding normalizeTypeBinding(ITypeBinding binding) {
		if (binding != null && !binding.isNullType() && !isVoidType(binding)) {
			if (binding.isAnonymous()) {
				ITypeBinding[] baseBindings= binding.getInterfaces();
				if (baseBindings.length > 0) {
					return baseBindings[0];
				}
				return binding.getSuperclass();
			}
			if (binding.isCapture()) {
				return binding.getWildcard();
			}
			return binding;
		}
		return null;
	}

	public static boolean isVoidType(ITypeBinding binding) {
		return "void".equals(binding.getName()); //$NON-NLS-1$
	}

	/**
	 * Normalizes the binding so that it can be used as a type inside a declaration (e.g. variable
	 * declaration, method return type, parameter type, ...).
	 * For null bindings, java.lang.Object is returned.
	 * For void bindings, <code>null</code> is returned.
	 * 
	 * @param binding binding to normalize
	 * @param ast current AST
	 * @return the normalized type to be used in declarations, or <code>null</code>
	 */
	public static ITypeBinding normalizeForDeclarationUse(ITypeBinding binding, AST ast) {
		if (binding.isNullType())
			return ast.resolveWellKnownType("java.lang.Object"); //$NON-NLS-1$
		if (binding.isPrimitive())
			return binding;
		binding= normalizeTypeBinding(binding);
		if (binding == null)
			return binding;
		if (binding.isArray())
			return normalizeForDeclarationUse(binding.getComponentType(), ast).createArrayType(1);
		if (!binding.isWildcardType())
			return binding;
		ITypeBinding bound= binding.getBound();
		if (bound == null || !binding.isUpperbound()) {
			ITypeBinding[] typeBounds= binding.getTypeBounds();
			if (typeBounds.length > 0) {
				return typeBounds[0];
			} else {
				return binding.getErasure();
			}
		} else {
			return bound;
		}
	}

	/**
	 * Returns the type binding of the node's enclosing type declaration.
	 * 
	 * @param node an AST node
	 * @return the type binding of the node's parent type declaration, or <code>null</code>
	 */
	public static ITypeBinding getBindingOfParentType(ASTNode node) {
		while (node != null) {
			if (node instanceof AbstractTypeDeclaration) {
				return ((AbstractTypeDeclaration) node).resolveBinding();
			} else if (node instanceof AnonymousClassDeclaration) {
				return ((AnonymousClassDeclaration) node).resolveBinding();
			}
			node= node.getParent();
		}
		return null;
	}

	/**
	 * Returns the type binding of the node's type context or null if the node is inside
	 * an annotation, type parameter, super type declaration, or Javadoc of a top level type.
	 * The result of this method is equal to the result of {@link #getBindingOfParentType(ASTNode)} for nodes in the type's body.
	 * 
	 * @param node an AST node
	 * @return the type binding of the node's parent type context, or <code>null</code>
	 */
	public static ITypeBinding getBindingOfParentTypeContext(ASTNode node) {
		StructuralPropertyDescriptor lastLocation= null;

		while (node != null) {
			if (node instanceof AbstractTypeDeclaration) {
				AbstractTypeDeclaration decl= (AbstractTypeDeclaration) node;
				if (lastLocation == decl.getBodyDeclarationsProperty()
						|| lastLocation == decl.getJavadocProperty()) {
					return decl.resolveBinding();
				} else if (decl instanceof EnumDeclaration && lastLocation == EnumDeclaration.ENUM_CONSTANTS_PROPERTY) {
					return decl.resolveBinding();
				}
			} else if (node instanceof AnonymousClassDeclaration) {
				return ((AnonymousClassDeclaration) node).resolveBinding();
			}
			lastLocation= node.getLocationInParent();
			node= node.getParent();
		}
		return null;
	}


	public static String getRawName(ITypeBinding binding) {
		String name= binding.getName();
		if (binding.isParameterizedType() || binding.isGenericType()) {
			int idx= name.indexOf('<');
			if (idx != -1) {
				return name.substring(0, idx);
			}
		}
		return name;
	}


	public static String getRawQualifiedName(ITypeBinding binding) {
		final String EMPTY= ""; //$NON-NLS-1$

		if (binding.isAnonymous() || binding.isLocal()) {
			return EMPTY;
		}

		if (binding.isPrimitive() || binding.isNullType() || binding.isTypeVariable()) {
			return binding.getName();
		}

		if (binding.isArray()) {
			String elementTypeQualifiedName = getRawQualifiedName(binding.getElementType());
			if (elementTypeQualifiedName.length() != 0) {
				StringBuilder stringBuffer= new StringBuilder(elementTypeQualifiedName);
				stringBuffer.append('[').append(']');
				return stringBuffer.toString();
			} else {
				return EMPTY;
			}
		}
		if (binding.isMember()) {
			String outerName= getRawQualifiedName(binding.getDeclaringClass());
			if (outerName.length() > 0) {
				StringBuilder buffer= new StringBuilder();
				buffer.append(outerName);
				buffer.append('.');
				buffer.append(getRawName(binding));
				return buffer.toString();
			} else {
				return EMPTY;
			}

		} else if (binding.isTopLevel()) {
			IPackageBinding packageBinding= binding.getPackage();
			StringBuilder buffer= new StringBuilder();
			if (packageBinding != null && packageBinding.getName().length() > 0) {
				buffer.append(packageBinding.getName()).append('.');
			}
			buffer.append(getRawName(binding));
			return buffer.toString();
		}
		return EMPTY;
	}


	/**
	 * Tests if the given node is a declaration, not a instance of a generic type, method or field.
	 * Declarations can be found in AST with CompilationUnit.findDeclaringNode
	 * @param binding binding to test
	 * @return returns <code>true</code> if the binding is a declaration binding
	 */
	public static boolean isDeclarationBinding(IBinding binding) {
		switch (binding.getKind()) {
			case IBinding.TYPE:
				return ((ITypeBinding) binding).getTypeDeclaration() == binding;
			case IBinding.VARIABLE:
				return ((IVariableBinding) binding).getVariableDeclaration() == binding;
			case IBinding.METHOD:
				return ((IMethodBinding) binding).getMethodDeclaration() == binding;
		}
		return true;
	}


	public static IBinding getDeclaration(IBinding binding) {
		switch (binding.getKind()) {
			case IBinding.TYPE:
				return ((ITypeBinding) binding).getTypeDeclaration();
			case IBinding.VARIABLE:
				return ((IVariableBinding) binding).getVariableDeclaration();
			case IBinding.METHOD:
				return ((IMethodBinding) binding).getMethodDeclaration();
		}
		return binding;
	}


	/**
	 * @param candidates the candidates
	 * @param overridable the overriding method
	 * @return returns <code>true></code> if the overriding method overrides a candidate
	 * @deprecated Need to review: Use {@link #isSubsignature(IMethodBinding, IMethodBinding)} if the two bindings
	 * are in the same hierarchy (directly overrides each other), or {@link #findMethodInHierarchy(ITypeBinding, String, ITypeBinding[])}
	 * else.
	 */
	@Deprecated
	public static boolean containsSignatureEquivalentConstructor(IMethodBinding[] candidates, IMethodBinding overridable) {
		for (int index= 0; index < candidates.length; index++) {
			if (isSignatureEquivalentConstructor(candidates[index], overridable))
				return true;
		}
		return false;
	}

	private static boolean isSignatureEquivalentConstructor(IMethodBinding overridden, IMethodBinding overridable) {

		if (!overridden.isConstructor() || !overridable.isConstructor())
			return false;

		if (overridden.isDefaultConstructor())
			return false;

		return areSubTypeCompatible(overridden, overridable);
	}

	/**
	 * @param overridden the overridden method
	 * @param overridable the overriding method
	 * @return returns <code>true</code> if the overriding method overrrides the overridden
	 * @deprecated Need to review: Use {@link #isSubsignature(IMethodBinding, IMethodBinding)} if the two bindings
	 * are in the same hierarchy (directly overrides each other), or {@link #findMethodInHierarchy(ITypeBinding, String, ITypeBinding[])}
	 * else.
	 */
	@Deprecated
	public static boolean areOverriddenMethods(IMethodBinding overridden, IMethodBinding overridable) {

		if (!overridden.getName().equals(overridable.getName()))
			return false;

		return areSubTypeCompatible(overridden, overridable);
	}

	private static boolean areSubTypeCompatible(IMethodBinding overridden, IMethodBinding overridable) {

		if (overridden.getParameterTypes().length != overridable.getParameterTypes().length)
			return false;

		ITypeBinding overriddenReturn= overridden.getReturnType();
		ITypeBinding overridableReturn= overridable.getReturnType();
		if (overriddenReturn == null || overridableReturn == null)
			return false;

		if (!overriddenReturn.getErasure().isSubTypeCompatible(overridableReturn.getErasure()))
			return false;

		ITypeBinding[] overriddenTypes= overridden.getParameterTypes();
		ITypeBinding[] overridableTypes= overridable.getParameterTypes();
		Assert.isTrue(overriddenTypes.length == overridableTypes.length);
		for (int index= 0; index < overriddenTypes.length; index++) {
			final ITypeBinding overridableErasure= overridableTypes[index].getErasure();
			final ITypeBinding overriddenErasure= overriddenTypes[index].getErasure();
			if (!overridableErasure.isSubTypeCompatible(overriddenErasure) || !overridableErasure.getKey().equals(overriddenErasure.getKey()))
				return false;
		}
		ITypeBinding[] overriddenExceptions= overridden.getExceptionTypes();
		ITypeBinding[] overridableExceptions= overridable.getExceptionTypes();
		boolean checked= false;
		for (int index= 0; index < overriddenExceptions.length; index++) {
			checked= false;
			for (int offset= 0; offset < overridableExceptions.length; offset++) {
				if (overriddenExceptions[index].isSubTypeCompatible(overridableExceptions[offset]))
					checked= true;
			}
			if (!checked)
				return false;
		}
		return true;
	}

	/**
	 * Returns the boxed type binding according to JLS3 5.1.7, or the original binding if
	 * the given type is not a primitive type.
	 *
	 * @param type a type binding
	 * @param ast an AST to resolve the boxed type
	 * @return the boxed type, or the original type if no boxed type found
	 */
	public static ITypeBinding getBoxedTypeBinding(ITypeBinding type, AST ast) {
		if (!type.isPrimitive())
			return type;
		String boxedTypeName= getBoxedTypeName(type.getName());
		if (boxedTypeName == null)
			return type;
		ITypeBinding boxed= ast.resolveWellKnownType(boxedTypeName);
		if (boxed == null)
			return type;
		return boxed;
	}

	private static String getBoxedTypeName(String primitiveName) {
		if ("long".equals(primitiveName)) //$NON-NLS-1$
			return "java.lang.Long"; //$NON-NLS-1$

		else if ("int".equals(primitiveName)) //$NON-NLS-1$
			return "java.lang.Integer"; //$NON-NLS-1$

		else if ("short".equals(primitiveName)) //$NON-NLS-1$
			return "java.lang.Short"; //$NON-NLS-1$

		else if ("char".equals(primitiveName)) //$NON-NLS-1$
			return "java.lang.Character"; //$NON-NLS-1$

		else if ("byte".equals(primitiveName)) //$NON-NLS-1$
			return "java.lang.Byte"; //$NON-NLS-1$

		else if ("boolean".equals(primitiveName)) //$NON-NLS-1$
			return "java.lang.Boolean"; //$NON-NLS-1$

		else if ("float".equals(primitiveName)) //$NON-NLS-1$
			return "java.lang.Float"; //$NON-NLS-1$

		else if ("double".equals(primitiveName)) //$NON-NLS-1$
			return "java.lang.Double"; //$NON-NLS-1$

		else
			return null;
	}

	/**
	 * Returns the unboxed type binding according to JLS3 5.1.7, or the original binding if
	 * the given type is not a boxed type.
	 *
	 * @param type a type binding
	 * @param ast an AST to resolve the unboxed type
	 * @return the unboxed type, or the original type if no unboxed type found
	 */
	public static ITypeBinding getUnboxedTypeBinding(ITypeBinding type, AST ast) {
		if (!type.isClass())
			return type;
		String unboxedTypeName= getUnboxedTypeName(type.getQualifiedName());
		if (unboxedTypeName == null)
			return type;
		ITypeBinding unboxed= ast.resolveWellKnownType(unboxedTypeName);
		if (unboxed == null)
			return type;
		return unboxed;
	}
	
	private static String getUnboxedTypeName(String boxedName) {
		if ("java.lang.Long".equals(boxedName)) //$NON-NLS-1$
			return "long"; //$NON-NLS-1$
		
		else if ("java.lang.Integer".equals(boxedName)) //$NON-NLS-1$
			return "int"; //$NON-NLS-1$
		
		else if ("java.lang.Short".equals(boxedName)) //$NON-NLS-1$
			return "short"; //$NON-NLS-1$
		
		else if ("java.lang.Character".equals(boxedName)) //$NON-NLS-1$
			return "char"; //$NON-NLS-1$
		
		else if ("java.lang.Byte".equals(boxedName)) //$NON-NLS-1$
			return "byte"; //$NON-NLS-1$
		
		else if ("java.lang.Boolean".equals(boxedName)) //$NON-NLS-1$
			return "boolean"; //$NON-NLS-1$
		
		else if ("java.lang.Float".equals(boxedName)) //$NON-NLS-1$
			return "float"; //$NON-NLS-1$
		
		else if ("java.lang.Double".equals(boxedName)) //$NON-NLS-1$
			return "double"; //$NON-NLS-1$
		
		else
			return null;
	}
	
	/**
	 * Resolve the binding (<em>not</em> the type binding) for the expression or a nested expression
	 * (e.g. nested in parentheses, cast, ...).
	 * 
	 * @param expression an expression node
	 * @param goIntoCast iff <code>true</code>, go into a CastExpression's expression to resolve
	 * @return the expression binding, or <code>null</code> if the expression has no binding or the
	 *         binding could not be resolved
	 * 
	 * @since 3.5
	 */
	public static IBinding resolveExpressionBinding(Expression expression, boolean goIntoCast) {
		//TODO: search for callers of resolve*Binding() methods and replace with call to this method
		
		// similar to StubUtility#getVariableNameSuggestions(int, IJavaProject, ITypeBinding, Expression, Collection)
		switch (expression.getNodeType()) {
			case ASTNode.SIMPLE_NAME:
			case ASTNode.QUALIFIED_NAME:
				return ((Name) expression).resolveBinding();
				
			case ASTNode.FIELD_ACCESS:
				return ((FieldAccess) expression).resolveFieldBinding();
			case ASTNode.SUPER_FIELD_ACCESS:
				return ((SuperFieldAccess) expression).resolveFieldBinding();
				
			case ASTNode.METHOD_INVOCATION:
				return ((MethodInvocation) expression).resolveMethodBinding();
			case ASTNode.SUPER_METHOD_INVOCATION:
				return ((SuperMethodInvocation) expression).resolveMethodBinding();
			case ASTNode.CLASS_INSTANCE_CREATION:
				return ((ClassInstanceCreation) expression).resolveConstructorBinding();
				
			case ASTNode.MARKER_ANNOTATION:
			case ASTNode.SINGLE_MEMBER_ANNOTATION:
			case ASTNode.NORMAL_ANNOTATION:
				return ((Annotation) expression).resolveAnnotationBinding();
				
			case ASTNode.ARRAY_ACCESS:
				return resolveExpressionBinding(((ArrayAccess) expression).getArray(), goIntoCast);
			case ASTNode.CAST_EXPRESSION:
				if (goIntoCast) {
					return resolveExpressionBinding(((CastExpression) expression).getExpression(), true);
				} else {
					return null;
				}
			case ASTNode.PARENTHESIZED_EXPRESSION:
				return resolveExpressionBinding(((ParenthesizedExpression) expression).getExpression(), goIntoCast);
			case ASTNode.PREFIX_EXPRESSION:
				return resolveExpressionBinding(((PrefixExpression) expression).getOperand(), goIntoCast);
			case ASTNode.POSTFIX_EXPRESSION:
				return resolveExpressionBinding(((PostfixExpression) expression).getOperand(), goIntoCast);
			default:
				return null;
		}
	}

	public static boolean isNonNullAnnotation(ITypeBinding annotationType, IJavaProject project) {
		String qualifiedName= annotationType.getQualifiedName();
		return qualifiedName.equals(project.getOption(JavaCore.COMPILER_NONNULL_ANNOTATION_NAME, true));
	}

	public static boolean isAnyNullAnnotation(ITypeBinding annotationType, IJavaProject project) {
		String qualifiedName= annotationType.getQualifiedName();
		return qualifiedName.equals(project.getOption(JavaCore.COMPILER_NONNULL_ANNOTATION_NAME, true))
				|| qualifiedName.equals(project.getOption(JavaCore.COMPILER_NULLABLE_ANNOTATION_NAME, true));
	}

	/**
	 * Returns the n-th component type of the given type, or <code>null</code> if
	 * the type binding is not an array type or has not that many dimensions.
	 * 
	 * @param arrayType an array type binding
	 * @param n number of dimensions to cut
	 * @return arrayType with n dimensions removed, or <code>null</code>
	 * @since 3.10
	 */
	public static ITypeBinding getComponentType(ITypeBinding arrayType, int n) {
		ITypeBinding type= arrayType;
		while (n > 0 && type != null) {
			type= type.getComponentType();
			n--;
		}
		return type;
	}

}
