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 - [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
/******************************************************************************* * 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 IBindings:
  • additional operations on IBindings and subtypes
  • finding corresponding elements in the type hierarchy
  • resolve bindings from a family of ASTNode types
/** * 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.
Params:
  • b1 – first binding treated as this. So it must not be null
  • b2 – the second binding.
Returns:boolean
/** * 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.
Params:
  • b1 – first binding, must not be null
  • b2 – second binding, must not be null
Returns:boolean
/** * 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 Bindings.equals(IBinding, IBinding) to compare.
Params:
  • b1 – the first array of bindings. Must not be null.
  • b2 – the second array of bindings.
Returns:boolean
/** * 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.
Params:
  • binding – the binding
Returns:a string representation of given binding
/** * 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.

If the binding resolves to a generic type, the fully qualified name of the raw type is returned.

Params:
  • type – the type binding to get its fully qualified name
Returns:the fully qualified name
/** * 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.
Params:
  • thrownException – the type binding
Returns:true if the passed type binding is a runtime exception; otherwise false is returned
/** * 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 fieldName in the given type. Returns null if no such field exists.
Params:
  • type – the type to search the field in
  • fieldName – the field name
Returns:the binding representing the field or null
/** * 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 fieldName in the type hierarchy denoted by the given type. Returns null 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.
Params:
  • type – The type to search the field in
  • fieldName – The name of the field to find
Returns:the variable binding representing the field
/** * 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 methodName and parameters in the given type. Returns null if no such method exists.
Params:
  • type – The type to search the method in
  • methodName – The name of the method to find
  • parameters – The parameter types of the method to find. If null is passed, only the name is matched and parameters are ignored.
Returns:the method binding representing the method
/** * 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 methodName and parameters in the type hierarchy denoted by the given type. Returns null 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.
Params:
  • type – The type to search the method in
  • methodName – The name of the method to find
  • parameters – The parameter types of the method to find. If null is passed, only the name is matched and parameters are ignored.
Returns:the method binding representing the method
/** * 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 methodName and parameters in the given type. Returns null if no such method exists.
Params:
  • type – The type to search the method in
  • methodName – The name of the method to find
  • parameters – The parameter types of the method to find. If null is passed, only the name is matched and parameters are ignored.
Returns:the method binding representing the method
/** * 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 methodName and parameters in the given type. Returns null if no such method exists.

This variant of findMethodInType(ITypeBinding, String, String[]) looks for a method whose declaration's parameters matches the given parameters.

Params:
  • type – The type to search the method in
  • methodName – The name of the method to find
  • parameters – The parameter types of the method to find. If null is passed, only the name is matched and parameters are ignored.
Returns:the method binding representing the method
/** * 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 methodName and parameters in the type hierarchy denoted by the given type. Returns null 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.
Params:
  • type – the type to search the method in
  • methodName – The name of the method to find
  • parameters – The parameter types of the method to find. If null is passed, only the name is matched and parameters are ignored.
Returns:the method binding representing the method
/** * 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 type that is overridden by the specified method. Returns null if no such method exists.
Params:
  • type – The type to search the method in
  • method – The specified method that would override the result
Returns:the method binding of the method that is overridden by the specified method, or 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 type that is overridden by binding. Returns null 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.
Params:
  • type – The type to search the method in
  • binding – The method that overrides
Returns:the method binding overridden the method
/** * 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.
Params:
  • overriding – overriding method
  • testVisibility – If true the result is tested on visibility. Null is returned if the method is not visible.
Returns:the method binding representing the method
/** * 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.
Params:
  • overriding – overriding method
  • testVisibility – if true the result is tested on visibility
  • firstOnly – if true this method will return when the first overridden method is found
Returns:the method bindings representing the overridden method or an empty list if no result is found
Since:3.9
/** * 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.
Params:
  • type – The type to get the supertypes of.
Returns:all super types (excluding type)
/** * 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.
Params:
  • type – the type whose hierarchy is to be visited
  • visitor – the visitor
Returns:true if all types were visited, or false if the visiting got aborted because the visit method returned false for a type
/** * 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.
Params:
  • type – the type whose interface hierarchy is to be visited
  • visitor – the visitor
Returns:true if all types were visited, or false if the visiting got aborted because the visit method returned false for a type
/** * 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.
Params:
  • type – the type whose super class hierarchy is to be visited
  • visitor – the visitor
Returns:true if all types were visited, or false if the visiting got aborted because the visit method returned false for a type
/** * 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.
Params:
  • method – the first method
  • methodName – the name of the second method
  • parameters – the parameters of the second method
Returns:return true if the two bindings are equal
Deprecated:use isSubsignature(IMethodBinding, IMethodBinding)
/** * 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; }
Params:
  • overriding – overriding method (m1)
  • overridden – overridden method (m2)
Returns:true iff the method m1 is a subsignature of the method m2. This is one of the requirements for m1 to override m2. Accessibility and return types are not taken into account. Note that subsignature is not symmetric!
/** * @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.
Params:
  • method – a method
  • methodName – method name to match
  • parameters – the parameter types of the method to find. If null is passed, only the name is matched and parameters are ignored.
Returns:true iff the method m1 (with name methodName and method parameters parameters) is a subsignature of the method m2. Accessibility and return types are not taken into account.
/** * 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 null if no type binding is found.
Params:
  • hierarchyType – the binding representing the hierarchy
  • fullyQualifiedTypeName – the fully qualified name to search for
Returns:the type binding
/** * 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 null if no type binding is found.
Params:
  • hierarchyType – the binding representing the hierarchy
  • fullyQualifiedTypeName – the fully qualified name to search for
Returns:the type binding
/** * 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.
Params:
  • assignment – The assignment
Returns:The binding or null if no bindings are available.
/** * 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 true if the given type is a super type of a candidate. true is returned if the two type bindings are identical.

Warning: With the addition of generics, this method is valid in less cases than before. Consider using 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.

Params:
  • possibleSuperType – the type to inspect
  • type – the type whose super types are looked at
Returns:true iff possibleSuperType is a super type of type or is equal to it
/** * 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 true if the given type is a super type of a candidate. true is returned if the two type bindings are identical (TODO)
Params:
  • possibleSuperType – the type to inspect
  • type – the type whose super types are looked at
  • considerTypeArguments – if true, consider type arguments of type
Returns:true iff possibleSuperType is a super type of type or is equal to it
/** * 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 ITypeBinding is defined, using the class path defined by the given Java project. Returns null if no compilation unit is found (e.g. type binding is from a binary type)
Params:
  • typeBinding – the type binding to search for
  • project – the project used as a scope
Throws:
Returns:the compilation unit containing the type
/** * 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 IMethodBinding. Returns null if the type doesn't contain a corresponding method.
Params:
  • method – the method to find
  • type – the type to look in
Throws:
Returns:the corresponding IMethod or null
Deprecated:Use findMethodInHierarchy(ITypeBinding, String, String[]) or JavaModelUtil
/** * 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 not as type of a declaration (use normalizeForDeclarationUse(ITypeBinding, AST) for that).

Anonymous types are normalized to the super class or interface. For null or void bindings, null is returned.

Params:
  • binding – the binding to normalize
See Also:
Returns:the normalized binding, can be null
/** * 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, null is returned.
Params:
  • binding – binding to normalize
  • ast – current AST
Returns:the normalized type to be used in declarations, or null
/** * 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.
Params:
  • node – an AST node
Returns:the type binding of the node's parent type declaration, or null
/** * 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 getBindingOfParentType(ASTNode) for nodes in the type's body.
Params:
  • node – an AST node
Returns:the type binding of the node's parent type context, or 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
Params:
  • binding – binding to test
Returns:returns true if the binding is a declaration binding
/** * 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; }
Params:
  • candidates – the candidates
  • overridable – the overriding method
Returns:returns true> if the overriding method overrides a candidate
Deprecated:Need to review: Use isSubsignature(IMethodBinding, IMethodBinding) if the two bindings are in the same hierarchy (directly overrides each other), or findMethodInHierarchy(ITypeBinding, String, ITypeBinding[]) else.
/** * @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); }
Params:
  • overridden – the overridden method
  • overridable – the overriding method
Returns:returns true if the overriding method overrrides the overridden
Deprecated:Need to review: Use isSubsignature(IMethodBinding, IMethodBinding) if the two bindings are in the same hierarchy (directly overrides each other), or findMethodInHierarchy(ITypeBinding, String, ITypeBinding[]) else.
/** * @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.
Params:
  • type – a type binding
  • ast – an AST to resolve the boxed type
Returns:the boxed type, or the original type if no boxed type found
/** * 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 (null == primitiveName) return null; else switch (primitiveName) { case "long": //$NON-NLS-1$ return "java.lang.Long"; //$NON-NLS-1$ case "int": //$NON-NLS-1$ return "java.lang.Integer"; //$NON-NLS-1$ case "short": //$NON-NLS-1$ return "java.lang.Short"; //$NON-NLS-1$ case "char": //$NON-NLS-1$ return "java.lang.Character"; //$NON-NLS-1$ case "byte": //$NON-NLS-1$ return "java.lang.Byte"; //$NON-NLS-1$ case "boolean": //$NON-NLS-1$ return "java.lang.Boolean"; //$NON-NLS-1$ case "float": //$NON-NLS-1$ return "java.lang.Float"; //$NON-NLS-1$ case "double": //$NON-NLS-1$ return "java.lang.Double"; //$NON-NLS-1$ default: 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.
Params:
  • type – a type binding
  • ast – an AST to resolve the unboxed type
Returns:the unboxed type, or the original type if no unboxed type found
/** * 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 (null == boxedName) return null; else switch (boxedName) { case "java.lang.Long": //$NON-NLS-1$ return "long"; //$NON-NLS-1$ case "java.lang.Integer": //$NON-NLS-1$ return "int"; //$NON-NLS-1$ case "java.lang.Short": //$NON-NLS-1$ return "short"; //$NON-NLS-1$ case "java.lang.Character": //$NON-NLS-1$ return "char"; //$NON-NLS-1$ case "java.lang.Byte": //$NON-NLS-1$ return "byte"; //$NON-NLS-1$ case "java.lang.Boolean": //$NON-NLS-1$ return "boolean"; //$NON-NLS-1$ case "java.lang.Float": //$NON-NLS-1$ return "float"; //$NON-NLS-1$ case "java.lang.Double": //$NON-NLS-1$ return "double"; //$NON-NLS-1$ default: return null; } }
Resolve the binding (not the type binding) for the expression or a nested expression (e.g. nested in parentheses, cast, ...).
Params:
  • expression – an expression node
  • goIntoCast – iff true, go into a CastExpression's expression to resolve
Returns:the expression binding, or null if the expression has no binding or the binding could not be resolved
Since:3.5
/** * 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 null if the type binding is not an array type or has not that many dimensions.
Params:
  • arrayType – an array type binding
  • n – number of dimensions to cut
Returns:arrayType with n dimensions removed, or null
Since:3.10
/** * 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; } }