1 /*******************************************************************************
2 * Copyright (c) 2000, 2012 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
9 * IBM Corporation - initial API and implementation
10 * Dmitry Stalnov (dstalnov@fusionone.com) - contributed fix for
11 * bug "inline method - doesn't handle implicit cast" (see
12 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=24941).
13 *******************************************************************************/
14 package org.eclipse.jdt.internal.corext.dom;
16 import java.util.ArrayList;
17 import java.util.Collections;
18 import java.util.HashSet;
19 import java.util.List;
22 import org.eclipse.core.runtime.Assert;
24 import org.eclipse.jdt.core.ICompilationUnit;
25 import org.eclipse.jdt.core.IJavaElement;
26 import org.eclipse.jdt.core.IJavaProject;
27 import org.eclipse.jdt.core.IMethod;
28 import org.eclipse.jdt.core.IType;
29 import org.eclipse.jdt.core.JavaModelException;
30 import org.eclipse.jdt.core.Signature;
31 import org.eclipse.jdt.core.dom.AST;
32 import org.eclipse.jdt.core.dom.ASTNode;
33 import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
34 import org.eclipse.jdt.core.dom.Annotation;
35 import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
36 import org.eclipse.jdt.core.dom.ArrayAccess;
37 import org.eclipse.jdt.core.dom.Assignment;
38 import org.eclipse.jdt.core.dom.CastExpression;
39 import org.eclipse.jdt.core.dom.ClassInstanceCreation;
40 import org.eclipse.jdt.core.dom.EnumDeclaration;
41 import org.eclipse.jdt.core.dom.Expression;
42 import org.eclipse.jdt.core.dom.FieldAccess;
43 import org.eclipse.jdt.core.dom.IAnnotationBinding;
44 import org.eclipse.jdt.core.dom.IBinding;
45 import org.eclipse.jdt.core.dom.IMemberValuePairBinding;
46 import org.eclipse.jdt.core.dom.IMethodBinding;
47 import org.eclipse.jdt.core.dom.IPackageBinding;
48 import org.eclipse.jdt.core.dom.ITypeBinding;
49 import org.eclipse.jdt.core.dom.IVariableBinding;
50 import org.eclipse.jdt.core.dom.MethodInvocation;
51 import org.eclipse.jdt.core.dom.Modifier;
52 import org.eclipse.jdt.core.dom.Name;
53 import org.eclipse.jdt.core.dom.ParenthesizedExpression;
54 import org.eclipse.jdt.core.dom.PostfixExpression;
55 import org.eclipse.jdt.core.dom.PrefixExpression;
56 import org.eclipse.jdt.core.dom.QualifiedName;
57 import org.eclipse.jdt.core.dom.SimpleName;
58 import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor;
59 import org.eclipse.jdt.core.dom.SuperFieldAccess;
60 import org.eclipse.jdt.core.dom.SuperMethodInvocation;
62 import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
63 import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
65 public class Bindings {
67 public static final String ARRAY_LENGTH_FIELD_BINDING_STRING= "(array type):length";//$NON-NLS-1$
73 * Checks if the two bindings are equals. Also works across binding environments.
74 * @param b1 first binding treated as <code>this</code>. So it must
75 * not be <code>null</code>
76 * @param b2 the second binding.
79 public static boolean equals(IBinding b1, IBinding b2) {
80 return b1.isEqualTo(b2);
85 * Checks if the declarations of two bindings are equals.
86 * Also works across binding environments.
87 * @param b1 first binding, must not be <code>null</code>
88 * @param b2 second binding, must not be <code>null</code>
91 public static boolean equalDeclarations(IBinding b1, IBinding b2) {
92 if (b1.getKind() != b2.getKind())
94 return getDeclaration(b1).isEqualTo(getDeclaration(b2));
98 * Checks if the two arrays of bindings have the same length and
99 * their elements are equal. Uses
100 * <code>Bindings.equals(IBinding, IBinding)</code> to compare.
101 * @param b1 the first array of bindings. Must not be <code>null</code>.
102 * @param b2 the second array of bindings.
105 public static boolean equals(IBinding[] b1, IBinding[] b2) {
106 Assert.isNotNull(b1);
111 if (b1.length != b2.length)
113 for (int i= 0; i < b1.length; i++) {
114 if (! Bindings.equals(b1[i], b2[i]))
120 public static int hashCode(IBinding binding){
121 Assert.isNotNull(binding);
122 String key= binding.getKey();
124 return binding.hashCode();
125 return key.hashCode();
129 * Note: this method is for debugging and testing purposes only.
130 * There are tests whose pre-computed test results rely on the returned String's format.
131 * @param binding the binding
132 * @return a string representation of given binding
133 * @see org.eclipse.jdt.internal.ui.viewsupport.BindingLabelProvider
135 public static String asString(IBinding binding) {
136 if (binding instanceof IMethodBinding)
137 return asString((IMethodBinding)binding);
138 else if (binding instanceof ITypeBinding)
139 return ((ITypeBinding)binding).getQualifiedName();
140 else if (binding instanceof IVariableBinding)
141 return asString((IVariableBinding)binding);
142 return binding.toString();
145 private static String asString(IVariableBinding variableBinding) {
146 if (! variableBinding.isField())
147 return variableBinding.toString();
148 if (variableBinding.getDeclaringClass() == null) {
149 Assert.isTrue(variableBinding.getName().equals("length"));//$NON-NLS-1$
150 return ARRAY_LENGTH_FIELD_BINDING_STRING;
152 StringBuffer result= new StringBuffer();
153 result.append(variableBinding.getDeclaringClass().getName());
155 result.append(variableBinding.getName());
156 return result.toString();
159 private static String asString(IMethodBinding method) {
160 StringBuffer result= new StringBuffer();
161 result.append(method.getDeclaringClass().getName());
163 result.append(method.getName());
165 ITypeBinding[] parameters= method.getParameterTypes();
166 int lastComma= parameters.length - 1;
167 for (int i= 0; i < parameters.length; i++) {
168 ITypeBinding parameter= parameters[i];
169 result.append(parameter.getName());
171 result.append(", "); //$NON-NLS-1$
174 return result.toString();
177 public static String getTypeQualifiedName(ITypeBinding type) {
178 List<String> result= new ArrayList<String>(5);
179 createName(type, false, result);
181 StringBuffer buffer= new StringBuffer();
182 for (int i= 0; i < result.size(); i++) {
186 buffer.append(result.get(i));
188 return buffer.toString();
192 * Returns the fully qualified name of the specified type binding.
194 * If the binding resolves to a generic type, the fully qualified name of the raw type is returned.
196 * @param type the type binding to get its fully qualified name
197 * @return the fully qualified name
199 public static String getFullyQualifiedName(ITypeBinding type) {
200 String name= type.getQualifiedName();
201 final int index= name.indexOf('<');
203 name= name.substring(0, index);
207 public static String getImportName(IBinding binding) {
208 ITypeBinding declaring= null;
209 switch (binding.getKind()) {
211 return getRawQualifiedName((ITypeBinding) binding);
212 case IBinding.PACKAGE:
213 return binding.getName() + ".*"; //$NON-NLS-1$
214 case IBinding.METHOD:
215 declaring= ((IMethodBinding) binding).getDeclaringClass();
217 case IBinding.VARIABLE:
218 declaring= ((IVariableBinding) binding).getDeclaringClass();
219 if (declaring == null) {
220 return binding.getName(); // array.length
225 return binding.getName();
227 return JavaModelUtil.concatenateName(getRawQualifiedName(declaring), binding.getName());
231 private static void createName(ITypeBinding type, boolean includePackage, List<String> list) {
232 ITypeBinding baseType= type;
233 if (type.isArray()) {
234 baseType= type.getElementType();
236 if (!baseType.isPrimitive() && !baseType.isNullType()) {
237 ITypeBinding declaringType= baseType.getDeclaringClass();
238 if (declaringType != null) {
239 createName(declaringType, includePackage, list);
240 } else if (includePackage && !baseType.getPackage().isUnnamed()) {
241 String[] components= baseType.getPackage().getNameComponents();
242 for (int i= 0; i < components.length; i++) {
243 list.add(components[i]);
247 if (!baseType.isAnonymous()) {
248 list.add(type.getName());
250 list.add("$local$"); //$NON-NLS-1$
255 public static String[] getNameComponents(ITypeBinding type) {
256 List<String> result= new ArrayList<String>(5);
257 createName(type, false, result);
258 return result.toArray(new String[result.size()]);
261 public static String[] getAllNameComponents(ITypeBinding type) {
262 List<String> result= new ArrayList<String>(5);
263 createName(type, true, result);
264 return result.toArray(new String[result.size()]);
267 public static ITypeBinding getTopLevelType(ITypeBinding type) {
268 ITypeBinding parent= type.getDeclaringClass();
269 while (parent != null) {
271 parent= type.getDeclaringClass();
277 * Checks whether the passed type binding is a runtime exception.
279 * @param thrownException the type binding
281 * @return <code>true</code> if the passed type binding is a runtime exception;
282 * otherwise <code>false</code> is returned
284 public static boolean isRuntimeException(ITypeBinding thrownException) {
285 if (thrownException == null || thrownException.isPrimitive() || thrownException.isArray())
287 return findTypeInHierarchy(thrownException, "java.lang.RuntimeException") != null; //$NON-NLS-1$
291 * Finds the field specified by <code>fieldName<code> in
292 * the given <code>type</code>. Returns <code>null</code> if no such field exits.
293 * @param type the type to search the field in
294 * @param fieldName the field name
295 * @return the binding representing the field or <code>null</code>
297 public static IVariableBinding findFieldInType(ITypeBinding type, String fieldName) {
298 if (type.isPrimitive())
300 IVariableBinding[] fields= type.getDeclaredFields();
301 for (int i= 0; i < fields.length; i++) {
302 IVariableBinding field= fields[i];
303 if (field.getName().equals(fieldName))
310 * Finds the field specified by <code>fieldName</code> in
311 * the type hierarchy denoted by the given type. Returns <code>null</code> if no such field
312 * exists. If the field is defined in more than one super type only the first match is
313 * returned. First the super class is examined and then the implemented interfaces.
314 * @param type The type to search the field in
315 * @param fieldName The name of the field to find
316 * @return the variable binding representing the field
318 public static IVariableBinding findFieldInHierarchy(ITypeBinding type, String fieldName) {
319 IVariableBinding field= findFieldInType(type, fieldName);
322 ITypeBinding superClass= type.getSuperclass();
323 if (superClass != null) {
324 field= findFieldInHierarchy(superClass, fieldName);
328 ITypeBinding[] interfaces= type.getInterfaces();
329 for (int i= 0; i < interfaces.length; i++) {
330 field= findFieldInHierarchy(interfaces[i], fieldName);
331 if (field != null) // no private fields in interfaces
338 * Finds the method specified by <code>methodName<code> and </code>parameters</code> in
339 * the given <code>type</code>. Returns <code>null</code> if no such method exits.
340 * @param type The type to search the method in
341 * @param methodName The name of the method to find
342 * @param parameters The parameter types of the method to find. If <code>null</code> is passed, only
343 * the name is matched and parameters are ignored.
344 * @return the method binding representing the method
346 public static IMethodBinding findMethodInType(ITypeBinding type, String methodName, ITypeBinding[] parameters) {
347 if (type.isPrimitive())
349 IMethodBinding[] methods= type.getDeclaredMethods();
350 for (int i= 0; i < methods.length; i++) {
351 if (parameters == null) {
352 if (methodName.equals(methods[i].getName()))
355 if (isEqualMethod(methods[i], methodName, parameters))
363 * Finds the method specified by <code>methodName</code> and </code>parameters</code> in
364 * the type hierarchy denoted by the given type. Returns <code>null</code> if no such method
365 * exists. If the method is defined in more than one super type only the first match is
366 * returned. First the super class is examined and then the implemented interfaces.
368 * @param type The type to search the method in
369 * @param methodName The name of the method to find
370 * @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.
371 * @return the method binding representing the method
373 public static IMethodBinding findMethodInHierarchy(ITypeBinding type, String methodName, ITypeBinding[] parameters) {
374 IMethodBinding method= findMethodInType(type, methodName, parameters);
377 ITypeBinding superClass= type.getSuperclass();
378 if (superClass != null) {
379 method= findMethodInHierarchy(superClass, methodName, parameters);
383 ITypeBinding[] interfaces= type.getInterfaces();
384 for (int i= 0; i < interfaces.length; i++) {
385 method= findMethodInHierarchy(interfaces[i], methodName, parameters);
393 * Finds the method specified by <code>methodName<code> and </code>parameters</code> in
394 * the given <code>type</code>. Returns <code>null</code> if no such method exits.
395 * @param type The type to search the method in
396 * @param methodName The name of the method to find
397 * @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.
398 * @return the method binding representing the method
400 public static IMethodBinding findMethodInType(ITypeBinding type, String methodName, String[] parameters) {
401 if (type.isPrimitive())
403 IMethodBinding[] methods= type.getDeclaredMethods();
404 for (int i= 0; i < methods.length; i++) {
405 if (parameters == null) {
406 if (methodName.equals(methods[i].getName()))
409 if (isEqualMethod(methods[i], methodName, parameters))
417 * Finds the method specified by <code>methodName</code> and </code>parameters</code> in
418 * the type hierarchy denoted by the given type. Returns <code>null</code> if no such method
419 * exists. If the method is defined in more than one super type only the first match is
420 * returned. First the super class is examined and then the implemented interfaces.
421 * @param type the type to search the method in
422 * @param methodName The name of the method to find
423 * @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.
424 * @return the method binding representing the method
426 public static IMethodBinding findMethodInHierarchy(ITypeBinding type, String methodName, String[] parameters) {
427 IMethodBinding method= findMethodInType(type, methodName, parameters);
430 ITypeBinding superClass= type.getSuperclass();
431 if (superClass != null) {
432 method= findMethodInHierarchy(superClass, methodName, parameters);
436 ITypeBinding[] interfaces= type.getInterfaces();
437 for (int i= 0; i < interfaces.length; i++) {
438 method= findMethodInHierarchy(interfaces[i], methodName, parameters);
446 * Finds the method in the given <code>type</code> that is overridden by the specified <code>method<code>.
447 * Returns <code>null</code> if no such method exits.
448 * @param type The type to search the method in
449 * @param method The specified method that would override the result
450 * @return the method binding of the method that is overridden by the specified <code>method<code>, or <code>null</code>
452 public static IMethodBinding findOverriddenMethodInType(ITypeBinding type, IMethodBinding method) {
453 IMethodBinding[] methods= type.getDeclaredMethods();
454 for (int i= 0; i < methods.length; i++) {
455 if (isSubsignature(method, methods[i]))
462 * Finds a method in the hierarchy of <code>type</code> that is overridden by </code>binding</code>.
463 * 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
464 * returned. First the super class is examined and then the implemented interfaces.
465 * @param type The type to search the method in
466 * @param binding The method that overrides
467 * @return the method binding overridden the method
469 public static IMethodBinding findOverriddenMethodInHierarchy(ITypeBinding type, IMethodBinding binding) {
470 IMethodBinding method= findOverriddenMethodInType(type, binding);
473 ITypeBinding superClass= type.getSuperclass();
474 if (superClass != null) {
475 method= findOverriddenMethodInHierarchy(superClass, binding);
479 ITypeBinding[] interfaces= type.getInterfaces();
480 for (int i= 0; i < interfaces.length; i++) {
481 method= findOverriddenMethodInHierarchy(interfaces[i], binding);
490 * Finds the method that is overridden by the given method. The search is bottom-up, so this
491 * returns the nearest defining/declaring method.
492 * @param overriding overriding method
493 * @param testVisibility If true the result is tested on visibility. Null is returned if the method is not visible.
494 * @return the method binding representing the method
496 public static IMethodBinding findOverriddenMethod(IMethodBinding overriding, boolean testVisibility) {
497 int modifiers= overriding.getModifiers();
498 if (Modifier.isPrivate(modifiers) || Modifier.isStatic(modifiers) || overriding.isConstructor()) {
502 ITypeBinding type= overriding.getDeclaringClass();
503 if (type.getSuperclass() != null) {
504 IMethodBinding res= findOverriddenMethodInHierarchy(type.getSuperclass(), overriding);
505 if (res != null && !Modifier.isPrivate(res.getModifiers())) {
506 if (!testVisibility || isVisibleInHierarchy(res, overriding.getDeclaringClass().getPackage())) {
511 ITypeBinding[] interfaces= type.getInterfaces();
512 for (int i= 0; i < interfaces.length; i++) {
513 IMethodBinding res= findOverriddenMethodInHierarchy(interfaces[i], overriding);
515 return res; // methods from interfaces are always public and therefore visible
522 public static boolean isVisibleInHierarchy(IMethodBinding member, IPackageBinding pack) {
523 int otherflags= member.getModifiers();
524 ITypeBinding declaringType= member.getDeclaringClass();
525 if (Modifier.isPublic(otherflags) || Modifier.isProtected(otherflags) || (declaringType != null && declaringType.isInterface())) {
527 } else if (Modifier.isPrivate(otherflags)) {
530 return declaringType != null && pack == declaringType.getPackage();
534 * Returns all super types (classes and interfaces) for the given type.
535 * @param type The type to get the supertypes of.
536 * @return all super types (excluding <code>type</code>)
538 public static ITypeBinding[] getAllSuperTypes(ITypeBinding type) {
539 Set<ITypeBinding> result= new HashSet<ITypeBinding>();
540 collectSuperTypes(type, result);
542 return result.toArray(new ITypeBinding[result.size()]);
545 private static void collectSuperTypes(ITypeBinding curr, Set<ITypeBinding> collection) {
546 if (collection.add(curr)) {
547 ITypeBinding[] interfaces= curr.getInterfaces();
548 for (int i= 0; i < interfaces.length; i++) {
549 collectSuperTypes(interfaces[i], collection);
551 ITypeBinding superClass= curr.getSuperclass();
552 if (superClass != null) {
553 collectSuperTypes(superClass, collection);
559 * Method to visit a type hierarchy defined by a given type.
561 * @param type the type which hierarchy is to be visited
562 * @param visitor the visitor
563 * @return <code>false</code> if the visiting got interrupted
565 public static boolean visitHierarchy(ITypeBinding type, TypeBindingVisitor visitor) {
566 boolean result= visitSuperclasses(type, visitor);
568 result= visitInterfaces(type, visitor);
574 * Method to visit a interface hierarchy defined by a given type.
576 * @param type the type which interface hierarchy is to be visited
577 * @param visitor the visitor
578 * @return <code>false</code> if the visiting got interrupted
580 public static boolean visitInterfaces(ITypeBinding type, TypeBindingVisitor visitor) {
581 ITypeBinding[] interfaces= type.getInterfaces();
582 for (int i= 0; i < interfaces.length; i++) {
583 if (!visitor.visit(interfaces[i])) {
591 * Method to visit a super class hierarchy defined by a given type.
593 * @param type the type which super class hierarchy is to be visited
594 * @param visitor the visitor
595 * @return <code>false</code> if the visiting got interrupted
597 public static boolean visitSuperclasses(ITypeBinding type, TypeBindingVisitor visitor) {
598 while ((type= type.getSuperclass()) != null) {
599 if (!visitor.visit(type)) {
607 * Tests whether the two methods are erasure-equivalent.
608 * @param method the first method
609 * @param methodName the name of the second method
610 * @param parameters the parameters of the second method
611 * @return return <code>true</code> if the two bindings are equal
612 * @deprecated use {@link #isSubsignature(IMethodBinding, IMethodBinding)}
614 //TODO: rename to isErasureEquivalentMethod and change to two IMethodBinding parameters
615 public static boolean isEqualMethod(IMethodBinding method, String methodName, ITypeBinding[] parameters) {
616 if (!method.getName().equals(methodName))
619 ITypeBinding[] methodParameters= method.getParameterTypes();
620 if (methodParameters.length != parameters.length)
622 for (int i= 0; i < parameters.length; i++) {
623 if (!equals(methodParameters[i].getErasure(), parameters[i].getErasure()))
626 //Can't use this fix, since some clients assume that this method tests erasure equivalence:
627 // if (method.getTypeParameters().length == 0) {
628 // //a method without type parameters cannot be overridden by one that declares type parameters -> can be exact here
629 // for (int i= 0; i < parameters.length; i++) {
630 // if ( ! (equals(methodParameters[i], parameters[i])
631 // || equals(methodParameters[i].getErasure(), parameters[i]))) // subsignature
635 // //this will find all overridden methods, but may generate false positives in some cases:
636 // for (int i= 0; i < parameters.length; i++) {
637 // if (!equals(methodParameters[i].getErasure(), parameters[i].getErasure()))
645 * @param overriding overriding method (m1)
646 * @param overridden overridden method (m2)
647 * @return <code>true</code> iff the method <code>m1</code> is a subsignature of the method <code>m2</code>.
648 * This is one of the requirements for m1 to override m2.
649 * Accessibility and return types are not taken into account.
650 * Note that subsignature is <em>not</em> symmetric!
652 public static boolean isSubsignature(IMethodBinding overriding, IMethodBinding overridden) {
653 //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
654 if (!overriding.getName().equals(overridden.getName()))
657 ITypeBinding[] m1Params= overriding.getParameterTypes();
658 ITypeBinding[] m2Params= overridden.getParameterTypes();
659 if (m1Params.length != m2Params.length)
662 ITypeBinding[] m1TypeParams= overriding.getTypeParameters();
663 ITypeBinding[] m2TypeParams= overridden.getTypeParameters();
664 if (m1TypeParams.length != m2TypeParams.length
665 && m1TypeParams.length != 0) //non-generic m1 can override a generic m2
668 //m1TypeParameters.length == (m2TypeParameters.length || 0)
669 if (m2TypeParams.length != 0) {
670 //Note: this branch does not 100% adhere to the spec and may report some false positives.
671 // Full compliance would require major duplication of compiler code.
673 //Compare type parameter bounds:
674 for (int i= 0; i < m1TypeParams.length; i++) {
675 // loop over m1TypeParams, which is either empty, or equally long as m2TypeParams
676 Set<ITypeBinding> m1Bounds= getTypeBoundsForSubsignature(m1TypeParams[i]);
677 Set<ITypeBinding> m2Bounds= getTypeBoundsForSubsignature(m2TypeParams[i]);
678 if (! m1Bounds.equals(m2Bounds))
681 //Compare parameter types:
682 if (equals(m2Params, m1Params))
684 for (int i= 0; i < m1Params.length; i++) {
685 ITypeBinding m1Param= m1Params[i];
686 ITypeBinding m2Param= m2Params[i];
687 if (containsTypeVariables(m1Param) || m1Param.isRawType())
688 m1Param= m1Param.getErasure(); // try to achieve effect of "rename type variables"
689 if (! (equals(m1Param, m2Param) || equals(m1Param, m2Param.getErasure())))
695 // m1TypeParams.length == m2TypeParams.length == 0
696 if (equals(m1Params, m2Params))
698 for (int i= 0; i < m1Params.length; i++) {
699 ITypeBinding m1Param= m1Params[i];
700 ITypeBinding m2Param= m2Params[i];
701 if (m1Param.isRawType())
702 m1Param= m1Param.getTypeDeclaration();
703 if (! (equals(m1Param, m2Param) || equals(m1Param, m2Param.getErasure())))
710 static boolean containsTypeVariables(ITypeBinding type) {
711 if (type.isTypeVariable())
714 return containsTypeVariables(type.getElementType());
715 if (type.isCapture())
716 return containsTypeVariables(type.getWildcard());
717 if (type.isParameterizedType())
718 return containsTypeVariables(type.getTypeArguments());
719 if (type.isTypeVariable())
720 return containsTypeVariables(type.getTypeBounds());
721 if (type.isWildcardType() && type.getBound() != null)
722 return containsTypeVariables(type.getBound());
726 private static boolean containsTypeVariables(ITypeBinding[] types) {
727 for (int i= 0; i < types.length; i++)
728 if (containsTypeVariables(types[i]))
733 private static Set<ITypeBinding> getTypeBoundsForSubsignature(ITypeBinding typeParameter) {
734 ITypeBinding[] typeBounds= typeParameter.getTypeBounds();
735 int count= typeBounds.length;
737 return Collections.emptySet();
739 Set<ITypeBinding> result= new HashSet<ITypeBinding>(typeBounds.length);
740 for (int i= 0; i < typeBounds.length; i++) {
741 ITypeBinding bound= typeBounds[i];
742 if ("java.lang.Object".equals(typeBounds[0].getQualifiedName())) //$NON-NLS-1$
744 else if (containsTypeVariables(bound))
745 result.add(bound.getErasure()); // try to achieve effect of "rename type variables"
746 else if (bound.isRawType())
747 result.add(bound.getTypeDeclaration());
755 * Checks whether a method with the given name and parameter types
756 * is a subsignature of the given method binding.
758 * @param method a method
759 * @param methodName method name to match
760 * @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.
761 * @return <code>true</code> iff the method
762 * m1 (with name <code>methodName</code> and method parameters <code>parameters</code>)
763 * is a subsignature of the method <code>m2</code>. Accessibility and return types are not taken into account.
765 public static boolean isEqualMethod(IMethodBinding method, String methodName, String[] parameters) {
766 if (!method.getName().equals(methodName))
769 ITypeBinding[] methodParameters= method.getParameterTypes();
770 if (methodParameters.length != parameters.length)
772 String first, second;
774 for (int i= 0; i < parameters.length; i++) {
775 first= parameters[i];
776 index= first.indexOf('<');
778 int lastIndex= first.lastIndexOf('>');
779 StringBuffer buf= new StringBuffer();
780 buf.append(first.substring(0, index));
781 if (lastIndex < first.length() - 1)
782 buf.append(first.substring(lastIndex + 1, first.length()));
783 first= buf.toString();
785 second= methodParameters[i].getQualifiedName();
786 if (!first.equals(second)) {
787 second= methodParameters[i].getErasure().getQualifiedName();
788 if (!first.equals(second))
796 * Finds a type binding for a given fully qualified type in the hierarchy of a type.
797 * Returns <code>null</code> if no type binding is found.
798 * @param hierarchyType the binding representing the hierarchy
799 * @param fullyQualifiedTypeName the fully qualified name to search for
800 * @return the type binding
802 public static ITypeBinding findTypeInHierarchy(ITypeBinding hierarchyType, String fullyQualifiedTypeName) {
803 if (hierarchyType.isArray() || hierarchyType.isPrimitive()) {
806 if (fullyQualifiedTypeName.equals(hierarchyType.getTypeDeclaration().getQualifiedName())) {
807 return hierarchyType;
809 ITypeBinding superClass= hierarchyType.getSuperclass();
810 if (superClass != null) {
811 ITypeBinding res= findTypeInHierarchy(superClass, fullyQualifiedTypeName);
816 ITypeBinding[] superInterfaces= hierarchyType.getInterfaces();
817 for (int i= 0; i < superInterfaces.length; i++) {
818 ITypeBinding res= findTypeInHierarchy(superInterfaces[i], fullyQualifiedTypeName);
827 * Returns the binding of the variable written in an Assignment.
828 * @param assignment The assignment
829 * @return The binding or <code>null</code> if no bindings are available.
831 public static IVariableBinding getAssignedVariable(Assignment assignment) {
832 Expression leftHand = assignment.getLeftHandSide();
833 switch (leftHand.getNodeType()) {
834 case ASTNode.SIMPLE_NAME:
835 return (IVariableBinding) ((SimpleName) leftHand).resolveBinding();
836 case ASTNode.QUALIFIED_NAME:
837 return (IVariableBinding) ((QualifiedName) leftHand).getName().resolveBinding();
838 case ASTNode.FIELD_ACCESS:
839 return ((FieldAccess) leftHand).resolveFieldBinding();
840 case ASTNode.SUPER_FIELD_ACCESS:
841 return ((SuperFieldAccess) leftHand).resolveFieldBinding();
848 * Returns <code>true</code> if the given type is a super type of a candidate.
849 * <code>true</code> is returned if the two type bindings are identical.
851 * <p><b>Warning:</b> With the addition of generics, this method is valid in less
852 * cases than before. Consider using {@link TypeRules#canAssign(ITypeBinding, ITypeBinding)}
853 * if you're dealing with types of variables. The classical notion of supertypes
854 * only makes sense if you really need to walk the type hierarchy but don't need to play
855 * the assignment rules.</p>
857 * @param possibleSuperType the type to inspect
858 * @param type the type whose super types are looked at
859 * @return <code>true</code> iff <code>possibleSuperType</code> is
860 * a super type of <code>type</code> or is equal to it
862 public static boolean isSuperType(ITypeBinding possibleSuperType, ITypeBinding type) {
863 return isSuperType(possibleSuperType, type, true);
867 * Returns <code>true</code> if the given type is a super type of a candidate.
868 * <code>true</code> is returned if the two type bindings are identical (TODO)
869 * @param possibleSuperType the type to inspect
870 * @param type the type whose super types are looked at
871 * @param considerTypeArguments if <code>true</code>, consider type arguments of <code>type</code>
872 * @return <code>true</code> iff <code>possibleSuperType</code> is
873 * a super type of <code>type</code> or is equal to it
875 public static boolean isSuperType(ITypeBinding possibleSuperType, ITypeBinding type, boolean considerTypeArguments) {
876 if (type.isArray() || type.isPrimitive()) {
879 if (! considerTypeArguments) {
880 type= type.getTypeDeclaration();
882 if (Bindings.equals(type, possibleSuperType)) {
885 ITypeBinding superClass= type.getSuperclass();
886 if (superClass != null) {
887 if (isSuperType(possibleSuperType, superClass, considerTypeArguments)) {
892 if (possibleSuperType.isInterface()) {
893 ITypeBinding[] superInterfaces= type.getInterfaces();
894 for (int i= 0; i < superInterfaces.length; i++) {
895 if (isSuperType(possibleSuperType, superInterfaces[i], considerTypeArguments)) {
904 * Finds the compilation unit where the type of the given <code>ITypeBinding</code> is defined,
905 * using the class path defined by the given Java project. Returns <code>null</code>
906 * if no compilation unit is found (e.g. type binding is from a binary type)
907 * @param typeBinding the type binding to search for
908 * @param project the project used as a scope
909 * @return the compilation unit containing the type
910 * @throws JavaModelException if an errors occurs in the Java model
912 public static ICompilationUnit findCompilationUnit(ITypeBinding typeBinding, IJavaProject project) throws JavaModelException {
913 IJavaElement type= typeBinding.getJavaElement();
914 if (type instanceof IType)
915 return ((IType) type).getCompilationUnit();
921 * Finds a method for the given <code>IMethodBinding</code>. Returns
922 * <code>null</code> if the type doesn't contain a corresponding method.
923 * @param method the method to find
924 * @param type the type to look in
925 * @return the corresponding IMethod or <code>null</code>
926 * @throws JavaModelException if an error occurs in the Java model
927 * @deprecated Use {@link #findMethodInHierarchy(ITypeBinding, String, String[])} or {@link JavaModelUtil}
929 public static IMethod findMethod(IMethodBinding method, IType type) throws JavaModelException {
930 method= method.getMethodDeclaration();
932 IMethod[] candidates= type.getMethods();
933 for (int i= 0; i < candidates.length; i++) {
934 IMethod candidate= candidates[i];
935 if (candidate.getElementName().equals(method.getName()) && sameParameters(method, candidate)) {
942 //---- Helper methods to convert a method ---------------------------------------------
944 private static boolean sameParameters(IMethodBinding method, IMethod candidate) throws JavaModelException {
945 ITypeBinding[] methodParamters= method.getParameterTypes();
946 String[] candidateParameters= candidate.getParameterTypes();
947 if (methodParamters.length != candidateParameters.length)
949 IType scope= candidate.getDeclaringType();
950 for (int i= 0; i < methodParamters.length; i++) {
951 ITypeBinding methodParameter= methodParamters[i];
952 String candidateParameter= candidateParameters[i];
953 if (!sameParameter(methodParameter, candidateParameter, scope))
959 private static boolean sameParameter(ITypeBinding type, String candidate, IType scope) throws JavaModelException {
960 if (type.getDimensions() != Signature.getArrayCount(candidate))
965 type= type.getElementType();
966 candidate= Signature.getElementType(candidate);
968 if ((Signature.getTypeSignatureKind(candidate) == Signature.BASE_TYPE_SIGNATURE) != type.isPrimitive()) {
972 if (type.isPrimitive() || type.isTypeVariable()) {
973 return type.getName().equals(Signature.toString(candidate));
975 // normalize (quick hack until binding.getJavaElement works)
976 candidate= Signature.getTypeErasure(candidate);
977 type= type.getErasure();
979 if (candidate.charAt(Signature.getArrayCount(candidate)) == Signature.C_RESOLVED) {
980 return Signature.toString(candidate).equals(Bindings.getFullyQualifiedName(type));
982 String[][] qualifiedCandidates= scope.resolveType(Signature.toString(candidate));
983 if (qualifiedCandidates == null || qualifiedCandidates.length == 0)
985 String packageName= type.getPackage().isUnnamed() ? "" : type.getPackage().getName(); //$NON-NLS-1$
986 String typeName= getTypeQualifiedName(type);
987 for (int i= 0; i < qualifiedCandidates.length; i++) {
988 String[] qualifiedCandidate= qualifiedCandidates[i];
989 if ( qualifiedCandidate[0].equals(packageName) &&
990 qualifiedCandidate[1].equals(typeName))
999 * Normalizes a type binding received from an expression to a type binding that can be used inside a
1000 * declaration signature, but <em>not</em> as type of a declaration (use {@link #normalizeForDeclarationUse(ITypeBinding, AST)} for that).
1002 * Anonymous types are normalized to the super class or interface. For
1003 * null or void bindings, <code>null</code> is returned.
1006 * @param binding the binding to normalize
1007 * @return the normalized binding, can be <code>null</code>
1009 * @see #normalizeForDeclarationUse(ITypeBinding, AST)
1011 public static ITypeBinding normalizeTypeBinding(ITypeBinding binding) {
1012 if (binding != null && !binding.isNullType() && !isVoidType(binding)) {
1013 if (binding.isAnonymous()) {
1014 ITypeBinding[] baseBindings= binding.getInterfaces();
1015 if (baseBindings.length > 0) {
1016 return baseBindings[0];
1018 return binding.getSuperclass();
1020 if (binding.isCapture()) {
1021 return binding.getWildcard();
1028 public static boolean isVoidType(ITypeBinding binding) {
1029 return "void".equals(binding.getName()); //$NON-NLS-1$
1033 * Normalizes the binding so that it can be used as a type inside a declaration (e.g. variable
1034 * declaration, method return type, parameter type, ...).
1035 * For null bindings, java.lang.Object is returned.
1036 * For void bindings, <code>null</code> is returned.
1038 * @param binding binding to normalize
1039 * @param ast current AST
1040 * @return the normalized type to be used in declarations, or <code>null</code>
1042 public static ITypeBinding normalizeForDeclarationUse(ITypeBinding binding, AST ast) {
1043 if (binding.isNullType())
1044 return ast.resolveWellKnownType("java.lang.Object"); //$NON-NLS-1$
1045 if (binding.isPrimitive())
1047 binding= normalizeTypeBinding(binding);
1048 if (binding == null || !binding.isWildcardType())
1050 if (binding.isUpperbound()) {
1051 return binding.getBound();
1053 return ast.resolveWellKnownType("java.lang.Object"); //$NON-NLS-1$
1058 * Returns the type binding of the node's enclosing type declaration.
1060 * @param node an AST node
1061 * @return the type binding of the node's parent type declaration, or <code>null</code>
1063 public static ITypeBinding getBindingOfParentType(ASTNode node) {
1064 while (node != null) {
1065 if (node instanceof AbstractTypeDeclaration) {
1066 return ((AbstractTypeDeclaration) node).resolveBinding();
1067 } else if (node instanceof AnonymousClassDeclaration) {
1068 return ((AnonymousClassDeclaration) node).resolveBinding();
1070 node= node.getParent();
1076 * Returns the type binding of the node's type context or null if the node is inside
1077 * an annotation, type parameter, super type declaration, or Javadoc of a top level type.
1078 * The result of this method is equal to the result of {@link #getBindingOfParentType(ASTNode)} for nodes in the type's body.
1080 * @param node an AST node
1081 * @return the type binding of the node's parent type context, or <code>null</code>
1083 public static ITypeBinding getBindingOfParentTypeContext(ASTNode node) {
1084 StructuralPropertyDescriptor lastLocation= null;
1086 while (node != null) {
1087 if (node instanceof AbstractTypeDeclaration) {
1088 AbstractTypeDeclaration decl= (AbstractTypeDeclaration) node;
1089 if (lastLocation == decl.getBodyDeclarationsProperty()
1090 || lastLocation == decl.getJavadocProperty()) {
1091 return decl.resolveBinding();
1092 } else if (decl instanceof EnumDeclaration && lastLocation == EnumDeclaration.ENUM_CONSTANTS_PROPERTY) {
1093 return decl.resolveBinding();
1095 } else if (node instanceof AnonymousClassDeclaration) {
1096 return ((AnonymousClassDeclaration) node).resolveBinding();
1098 lastLocation= node.getLocationInParent();
1099 node= node.getParent();
1105 public static String getRawName(ITypeBinding binding) {
1106 String name= binding.getName();
1107 if (binding.isParameterizedType() || binding.isGenericType()) {
1108 int idx= name.indexOf('<');
1110 return name.substring(0, idx);
1117 public static String getRawQualifiedName(ITypeBinding binding) {
1118 final String EMPTY= ""; //$NON-NLS-1$
1120 if (binding.isAnonymous() || binding.isLocal()) {
1124 if (binding.isPrimitive() || binding.isNullType() || binding.isTypeVariable()) {
1125 return binding.getName();
1128 if (binding.isArray()) {
1129 String elementTypeQualifiedName = getRawQualifiedName(binding.getElementType());
1130 if (elementTypeQualifiedName.length() != 0) {
1131 StringBuffer stringBuffer= new StringBuffer(elementTypeQualifiedName);
1132 stringBuffer.append('[').append(']');
1133 return stringBuffer.toString();
1138 if (binding.isMember()) {
1139 String outerName= getRawQualifiedName(binding.getDeclaringClass());
1140 if (outerName.length() > 0) {
1141 StringBuffer buffer= new StringBuffer();
1142 buffer.append(outerName);
1144 buffer.append(getRawName(binding));
1145 return buffer.toString();
1150 } else if (binding.isTopLevel()) {
1151 IPackageBinding packageBinding= binding.getPackage();
1152 StringBuffer buffer= new StringBuffer();
1153 if (packageBinding != null && packageBinding.getName().length() > 0) {
1154 buffer.append(packageBinding.getName()).append('.');
1156 buffer.append(getRawName(binding));
1157 return buffer.toString();
1164 * Tests if the given node is a declaration, not a instance of a generic type, method or field.
1165 * Declarations can be found in AST with CompilationUnit.findDeclaringNode
1166 * @param binding binding to test
1167 * @return returns <code>true</code> if the binding is a declaration binding
1169 public static boolean isDeclarationBinding(IBinding binding) {
1170 switch (binding.getKind()) {
1172 return ((ITypeBinding) binding).getTypeDeclaration() == binding;
1173 case IBinding.VARIABLE:
1174 return ((IVariableBinding) binding).getVariableDeclaration() == binding;
1175 case IBinding.METHOD:
1176 return ((IMethodBinding) binding).getMethodDeclaration() == binding;
1182 public static IBinding getDeclaration(IBinding binding) {
1183 switch (binding.getKind()) {
1185 return ((ITypeBinding) binding).getTypeDeclaration();
1186 case IBinding.VARIABLE:
1187 return ((IVariableBinding) binding).getVariableDeclaration();
1188 case IBinding.METHOD:
1189 return ((IMethodBinding) binding).getMethodDeclaration();
1196 * @param candidates the candidates
1197 * @param overridable the overriding method
1198 * @return returns <code>true></code> if the overriding method overrides a candidate
1199 * @deprecated Need to review: Use {@link #isSubsignature(IMethodBinding, IMethodBinding)} if the two bindings
1200 * are in the same hierarchy (directly overrides each other), or {@link #findMethodInHierarchy(ITypeBinding, String, ITypeBinding[])}
1203 public static boolean containsSignatureEquivalentConstructor(IMethodBinding[] candidates, IMethodBinding overridable) {
1204 for (int index= 0; index < candidates.length; index++) {
1205 if (isSignatureEquivalentConstructor(candidates[index], overridable))
1211 private static boolean isSignatureEquivalentConstructor(IMethodBinding overridden, IMethodBinding overridable) {
1213 if (!overridden.isConstructor() || !overridable.isConstructor())
1216 if (overridden.isDefaultConstructor())
1219 return areSubTypeCompatible(overridden, overridable);
1223 * @param overridden the overridden method
1224 * @param overridable the overriding method
1225 * @return returns <code>true</code> if the overriding method overrrides the overridden
1226 * @deprecated Need to review: Use {@link #isSubsignature(IMethodBinding, IMethodBinding)} if the two bindings
1227 * are in the same hierarchy (directly overrides each other), or {@link #findMethodInHierarchy(ITypeBinding, String, ITypeBinding[])}
1230 public static boolean areOverriddenMethods(IMethodBinding overridden, IMethodBinding overridable) {
1232 if (!overridden.getName().equals(overridable.getName()))
1235 return areSubTypeCompatible(overridden, overridable);
1238 private static boolean areSubTypeCompatible(IMethodBinding overridden, IMethodBinding overridable) {
1240 if (overridden.getParameterTypes().length != overridable.getParameterTypes().length)
1243 ITypeBinding overriddenReturn= overridden.getReturnType();
1244 ITypeBinding overridableReturn= overridable.getReturnType();
1245 if (overriddenReturn == null || overridableReturn == null)
1248 if (!overriddenReturn.getErasure().isSubTypeCompatible(overridableReturn.getErasure()))
1251 ITypeBinding[] overriddenTypes= overridden.getParameterTypes();
1252 ITypeBinding[] overridableTypes= overridable.getParameterTypes();
1253 Assert.isTrue(overriddenTypes.length == overridableTypes.length);
1254 for (int index= 0; index < overriddenTypes.length; index++) {
1255 final ITypeBinding overridableErasure= overridableTypes[index].getErasure();
1256 final ITypeBinding overriddenErasure= overriddenTypes[index].getErasure();
1257 if (!overridableErasure.isSubTypeCompatible(overriddenErasure) || !overridableErasure.getKey().equals(overriddenErasure.getKey()))
1260 ITypeBinding[] overriddenExceptions= overridden.getExceptionTypes();
1261 ITypeBinding[] overridableExceptions= overridable.getExceptionTypes();
1262 boolean checked= false;
1263 for (int index= 0; index < overriddenExceptions.length; index++) {
1265 for (int offset= 0; offset < overridableExceptions.length; offset++) {
1266 if (overriddenExceptions[index].isSubTypeCompatible(overridableExceptions[offset]))
1276 * Returns the boxed type binding according to JLS3 5.1.7, or the original binding if
1277 * the given type is not a primitive type.
1279 * @param type a type binding
1280 * @param ast an AST to resolve the boxed type
1281 * @return the boxed type, or the original type if no boxed type found
1283 public static ITypeBinding getBoxedTypeBinding(ITypeBinding type, AST ast) {
1284 if (!type.isPrimitive())
1286 String boxedTypeName= getBoxedTypeName(type.getName());
1287 if (boxedTypeName == null)
1289 ITypeBinding boxed= ast.resolveWellKnownType(boxedTypeName);
1295 private static String getBoxedTypeName(String primitiveName) {
1296 if ("long".equals(primitiveName)) //$NON-NLS-1$
1297 return "java.lang.Long"; //$NON-NLS-1$
1299 else if ("int".equals(primitiveName)) //$NON-NLS-1$
1300 return "java.lang.Integer"; //$NON-NLS-1$
1302 else if ("short".equals(primitiveName)) //$NON-NLS-1$
1303 return "java.lang.Short"; //$NON-NLS-1$
1305 else if ("char".equals(primitiveName)) //$NON-NLS-1$
1306 return "java.lang.Character"; //$NON-NLS-1$
1308 else if ("byte".equals(primitiveName)) //$NON-NLS-1$
1309 return "java.lang.Byte"; //$NON-NLS-1$
1311 else if ("boolean".equals(primitiveName)) //$NON-NLS-1$
1312 return "java.lang.Boolean"; //$NON-NLS-1$
1314 else if ("float".equals(primitiveName)) //$NON-NLS-1$
1315 return "java.lang.Float"; //$NON-NLS-1$
1317 else if ("double".equals(primitiveName)) //$NON-NLS-1$
1318 return "java.lang.Double"; //$NON-NLS-1$
1325 * Returns the unboxed type binding according to JLS3 5.1.7, or the original binding if
1326 * the given type is not a boxed type.
1328 * @param type a type binding
1329 * @param ast an AST to resolve the unboxed type
1330 * @return the unboxed type, or the original type if no unboxed type found
1332 public static ITypeBinding getUnboxedTypeBinding(ITypeBinding type, AST ast) {
1333 if (!type.isClass())
1335 String unboxedTypeName= getUnboxedTypeName(type.getQualifiedName());
1336 if (unboxedTypeName == null)
1338 ITypeBinding unboxed= ast.resolveWellKnownType(unboxedTypeName);
1339 if (unboxed == null)
1344 private static String getUnboxedTypeName(String boxedName) {
1345 if ("java.lang.Long".equals(boxedName)) //$NON-NLS-1$
1346 return "long"; //$NON-NLS-1$
1348 else if ("java.lang.Integer".equals(boxedName)) //$NON-NLS-1$
1349 return "int"; //$NON-NLS-1$
1351 else if ("java.lang.Short".equals(boxedName)) //$NON-NLS-1$
1352 return "short"; //$NON-NLS-1$
1354 else if ("java.lang.Character".equals(boxedName)) //$NON-NLS-1$
1355 return "char"; //$NON-NLS-1$
1357 else if ("java.lang.Byte".equals(boxedName)) //$NON-NLS-1$
1358 return "byte"; //$NON-NLS-1$
1360 else if ("java.lang.Boolean".equals(boxedName)) //$NON-NLS-1$
1361 return "boolean"; //$NON-NLS-1$
1363 else if ("java.lang.Float".equals(boxedName)) //$NON-NLS-1$
1364 return "float"; //$NON-NLS-1$
1366 else if ("java.lang.Double".equals(boxedName)) //$NON-NLS-1$
1367 return "double"; //$NON-NLS-1$
1374 * Resolve the binding (<em>not</em> the type binding) for the expression or a nested expression
1375 * (e.g. nested in parentheses, cast, ...).
1377 * @param expression an expression node
1378 * @param goIntoCast iff <code>true</code>, go into a CastExpression's expression to resolve
1379 * @return the expression binding, or <code>null</code> if the expression has no binding or the
1380 * binding could not be resolved
1382 * @see StubUtility#getVariableNameSuggestions(int, IJavaProject, ITypeBinding, Expression, java.util.Collection)
1385 public static IBinding resolveExpressionBinding(Expression expression, boolean goIntoCast) {
1386 //TODO: search for callers of resolve*Binding() methods and replace with call to this method
1388 // similar to StubUtility#getVariableNameSuggestions(int, IJavaProject, ITypeBinding, Expression, Collection)
1389 switch (expression.getNodeType()) {
1390 case ASTNode.SIMPLE_NAME:
1391 case ASTNode.QUALIFIED_NAME:
1392 return ((Name) expression).resolveBinding();
1394 case ASTNode.FIELD_ACCESS:
1395 return ((FieldAccess) expression).resolveFieldBinding();
1396 case ASTNode.SUPER_FIELD_ACCESS:
1397 return ((SuperFieldAccess) expression).resolveFieldBinding();
1399 case ASTNode.METHOD_INVOCATION:
1400 return ((MethodInvocation) expression).resolveMethodBinding();
1401 case ASTNode.SUPER_METHOD_INVOCATION:
1402 return ((SuperMethodInvocation) expression).resolveMethodBinding();
1403 case ASTNode.CLASS_INSTANCE_CREATION:
1404 return ((ClassInstanceCreation) expression).resolveConstructorBinding();
1406 case ASTNode.MARKER_ANNOTATION:
1407 case ASTNode.SINGLE_MEMBER_ANNOTATION:
1408 case ASTNode.NORMAL_ANNOTATION:
1409 return ((Annotation) expression).resolveAnnotationBinding();
1411 case ASTNode.ARRAY_ACCESS:
1412 return resolveExpressionBinding(((ArrayAccess) expression).getArray(), goIntoCast);
1413 case ASTNode.CAST_EXPRESSION:
1415 return resolveExpressionBinding(((CastExpression) expression).getExpression(), true);
1419 case ASTNode.PARENTHESIZED_EXPRESSION:
1420 return resolveExpressionBinding(((ParenthesizedExpression) expression).getExpression(), goIntoCast);
1421 case ASTNode.PREFIX_EXPRESSION:
1422 return resolveExpressionBinding(((PrefixExpression) expression).getOperand(), goIntoCast);
1423 case ASTNode.POSTFIX_EXPRESSION:
1424 return resolveExpressionBinding(((PostfixExpression) expression).getOperand(), goIntoCast);
1430 public static boolean isClassOrRuntimeAnnotation(ITypeBinding annotationType) {
1431 IAnnotationBinding[] metaAnnotations= annotationType.getAnnotations();
1432 for (IAnnotationBinding metaAnnotation : metaAnnotations) {
1433 if ("java.lang.annotation.Retention".equals(metaAnnotation.getAnnotationType().getQualifiedName())) { //$NON-NLS-1$
1434 IMemberValuePairBinding[] mvps= metaAnnotation.getDeclaredMemberValuePairs();
1435 if (mvps.length == 1) {
1436 Object value= mvps[0].getValue();
1437 if (value instanceof IVariableBinding) {
1438 String name= ((IVariableBinding) value).getName();
1439 if ("RUNTIME".equals(name) || "CLASS".equals(name)) //$NON-NLS-1$ //$NON-NLS-2$