KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > corext > dom > Bindings


1 /*******************************************************************************
2  * Copyright (c) 2000, 2005 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
7  *
8  * Contributors:
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;
15
16 import java.util.ArrayList JavaDoc;
17 import java.util.HashSet JavaDoc;
18 import java.util.List JavaDoc;
19 import java.util.Set JavaDoc;
20
21 import org.eclipse.core.runtime.IPath;
22 import org.eclipse.core.runtime.Path;
23 import org.eclipse.core.runtime.Platform;
24
25 import org.eclipse.jdt.core.IClassFile;
26 import org.eclipse.jdt.core.ICompilationUnit;
27 import org.eclipse.jdt.core.IField;
28 import org.eclipse.jdt.core.IJavaElement;
29 import org.eclipse.jdt.core.IJavaProject;
30 import org.eclipse.jdt.core.IMethod;
31 import org.eclipse.jdt.core.IType;
32 import org.eclipse.jdt.core.JavaModelException;
33 import org.eclipse.jdt.core.Signature;
34 import org.eclipse.jdt.core.dom.AST;
35 import org.eclipse.jdt.core.dom.ASTNode;
36 import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
37 import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
38 import org.eclipse.jdt.core.dom.Assignment;
39 import org.eclipse.jdt.core.dom.Expression;
40 import org.eclipse.jdt.core.dom.FieldAccess;
41 import org.eclipse.jdt.core.dom.IBinding;
42 import org.eclipse.jdt.core.dom.IMethodBinding;
43 import org.eclipse.jdt.core.dom.IPackageBinding;
44 import org.eclipse.jdt.core.dom.ITypeBinding;
45 import org.eclipse.jdt.core.dom.IVariableBinding;
46 import org.eclipse.jdt.core.dom.Modifier;
47 import org.eclipse.jdt.core.dom.QualifiedName;
48 import org.eclipse.jdt.core.dom.SimpleName;
49 import org.eclipse.jdt.core.dom.SuperFieldAccess;
50
51 import org.eclipse.jdt.internal.corext.Assert;
52 import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
53
54 import org.eclipse.jdt.internal.ui.JavaPlugin;
55
56 public class Bindings {
57     
58     public static final String JavaDoc ARRAY_LENGTH_FIELD_BINDING_STRING= "(array type):length";//$NON-NLS-1$
59
private Bindings() {
60         // No instance
61
}
62     
63     private static final boolean CHECK_CORE_BINDING_IS_EQUAL_TO;
64     static {
65         String JavaDoc value= Platform.getDebugOption("org.eclipse.jdt.ui/debug/checkCoreBindingIsEqualTo"); //$NON-NLS-1$
66
CHECK_CORE_BINDING_IS_EQUAL_TO= value != null && value.equalsIgnoreCase("true"); //$NON-NLS-1$
67
}
68     private static final boolean CHECK_CORE_BINDING_GET_JAVA_ELEMENT;
69     static {
70         String JavaDoc value= Platform.getDebugOption("org.eclipse.jdt.ui/debug/checkCoreBindingGetJavaElement"); //$NON-NLS-1$
71
CHECK_CORE_BINDING_GET_JAVA_ELEMENT= value != null && value.equalsIgnoreCase("true"); //$NON-NLS-1$
72
}
73     private static final boolean USE_UI_BINDING_GET_JAVA_ELEMENT;
74     static {
75         String JavaDoc value= Platform.getDebugOption("org.eclipse.jdt.ui/debug/useUIBindingGetJavaElement"); //$NON-NLS-1$
76
USE_UI_BINDING_GET_JAVA_ELEMENT= value != null && value.equalsIgnoreCase("true"); //$NON-NLS-1$
77
}
78     
79     /**
80      * Checks if the two bindings are equals. First an identity check is
81      * made an then the key of the bindings are compared.
82      * @param b1 first binding treated as <code>this</code>. So it must
83      * not be <code>null</code>
84      * @param b2 the second binding.
85      * @return boolean
86      */

87     public static boolean equals(IBinding b1, IBinding b2) {
88         boolean isEqualTo= b1.isEqualTo(b2);
89         if (CHECK_CORE_BINDING_IS_EQUAL_TO) {
90             boolean originalEquals= originalEquals(b1, b2);
91             if (originalEquals != isEqualTo) {
92                 String JavaDoc message= "Unexpected difference between Bindings.equals(..) and IBinding#isEqualTo(..)"; //$NON-NLS-1$
93
String JavaDoc detail= "\nb1 == " + b1.getKey() + ",\nb2 == " + (b2 == null ? "null binding" : b2.getKey()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
94
try {
95                     detail+= "\nb1.getJavaElement() == " + b1.getJavaElement() + ",\nb2.getJavaElement() == " + (b2 == null ? "null binding" : b2.getJavaElement().toString()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
96
} catch (Exception JavaDoc e) {
97                     detail += "\nException in getJavaElement():\n" + e; //$NON-NLS-1$
98
}
99                 JavaPlugin.logRepeatedMessage(message, detail);
100             }
101         }
102         return isEqualTo;
103     }
104     
105     private static boolean originalEquals(IBinding b1, IBinding b2) {
106         Assert.isNotNull(b1);
107         if (b1 == b2)
108             return true;
109         if (b2 == null)
110             return false;
111         String JavaDoc k1= b1.getKey();
112         String JavaDoc k2= b2.getKey();
113         if (k1 == null || k2 == null)
114             return false;
115         return k1.equals(k2);
116     }
117     
118     /**
119      * Checks if the two arrays of bindings have the same length and
120      * their elements are equal. Uses
121      * <code>Bindings.equals(IBinding, IBinding)</code> to compare.
122      * @param b1 the first array of bindings. Must not be <code>null</code>.
123      * @param b2 the second array of bindings.
124      * @return boolean
125      */

126     public static boolean equals(IBinding[] b1, IBinding[] b2) {
127         Assert.isNotNull(b1);
128         if (b1 == b2)
129             return true;
130         if (b2 == null)
131             return false;
132         if (b1.length != b2.length)
133             return false;
134         for (int i= 0; i < b1.length; i++) {
135             if (! Bindings.equals(b1[i], b2[i]))
136                 return false;
137         }
138         return true;
139     }
140     
141     public static int hashCode(IBinding binding){
142         Assert.isNotNull(binding);
143         String JavaDoc key= binding.getKey();
144         if (key == null)
145             return binding.hashCode();
146         return key.hashCode();
147     }
148     
149     /*
150      * Note: this method is for debugging and testing purposes only.
151      * There are tests whose precomputed test results rely on the returned String's format.
152      * @see org.eclipse.jdt.internal.ui.viewsupport.BindingLabels
153      */

154     public static String JavaDoc asString(IBinding binding) {
155         if (binding instanceof IMethodBinding)
156             return asString((IMethodBinding)binding);
157         else if (binding instanceof ITypeBinding)
158             return asString((ITypeBinding)binding);
159         else if (binding instanceof IVariableBinding)
160             return asString((IVariableBinding)binding);
161         return binding.toString();
162     }
163
164     private static String JavaDoc asString(IVariableBinding variableBinding) {
165         if (! variableBinding.isField())
166             return variableBinding.toString();
167         if (variableBinding.getDeclaringClass() == null) {
168             Assert.isTrue(variableBinding.getName().equals("length"));//$NON-NLS-1$
169
return ARRAY_LENGTH_FIELD_BINDING_STRING;
170         }
171         StringBuffer JavaDoc result= new StringBuffer JavaDoc();
172         result.append(variableBinding.getDeclaringClass().getName());
173         result.append(':');
174         result.append(variableBinding.getName());
175         return result.toString();
176     }
177
178     private static String JavaDoc asString(ITypeBinding type) {
179         return type.getQualifiedName();
180     }
181         
182     private static String JavaDoc asString(IMethodBinding method) {
183         StringBuffer JavaDoc result= new StringBuffer JavaDoc();
184         result.append(method.getDeclaringClass().getName());
185         result.append(':');
186         result.append(method.getName());
187         result.append('(');
188         ITypeBinding[] parameters= method.getParameterTypes();
189         int lastComma= parameters.length - 1;
190         for (int i= 0; i < parameters.length; i++) {
191             ITypeBinding parameter= parameters[i];
192             result.append(parameter.getName());
193             if (i < lastComma)
194                 result.append(", "); //$NON-NLS-1$
195
}
196         result.append(')');
197         return result.toString();
198     }
199     
200     public static String JavaDoc getTypeQualifiedName(ITypeBinding type) {
201         List JavaDoc result= new ArrayList JavaDoc(5);
202         createName(type, false, result);
203         
204         StringBuffer JavaDoc buffer= new StringBuffer JavaDoc();
205         for (int i= 0; i < result.size(); i++) {
206             if (i > 0) {
207                 buffer.append('.');
208             }
209             buffer.append(((String JavaDoc) result.get(i)));
210         }
211         return buffer.toString();
212     }
213
214     /**
215      * Returns the fully qualified name of the specified type binding.
216      * <p>
217      * If the binding resolves to a generic type, the fully qualified name of the raw type is returned.
218      *
219      * @param type the type binding to get its fully qualified name
220      * @return the fully qualified name
221      */

222     public static String JavaDoc getFullyQualifiedName(ITypeBinding type) {
223
224         // TW: replace by call to type.getJavaElement().getFullyQualifiedName (see 78087)
225

226         String JavaDoc name= type.getQualifiedName();
227         final int index= name.indexOf('<');
228         if (index > 0)
229             name= name.substring(0, index);
230         return name;
231     }
232
233     public static String JavaDoc getImportName(IBinding binding) {
234         ITypeBinding declaring= null;
235         switch (binding.getKind()) {
236             case IBinding.TYPE:
237                 return getRawQualifiedName((ITypeBinding) binding);
238             case IBinding.PACKAGE:
239                 return binding.getName() + ".*"; //$NON-NLS-1$
240
case IBinding.METHOD:
241                 declaring= ((IMethodBinding) binding).getDeclaringClass();
242                 break;
243             case IBinding.VARIABLE:
244                 declaring= ((IVariableBinding) binding).getDeclaringClass();
245                 break;
246             default:
247                 return binding.getName();
248         }
249         return JavaModelUtil.concatenateName(getRawQualifiedName(declaring), binding.getName());
250     }
251     
252     
253     private static void createName(ITypeBinding type, boolean includePackage, List JavaDoc list) {
254         ITypeBinding baseType= type;
255         if (type.isArray()) {
256             baseType= type.getElementType();
257         }
258         if (!baseType.isPrimitive() && !baseType.isNullType()) {
259             ITypeBinding declaringType= baseType.getDeclaringClass();
260             if (declaringType != null) {
261                 createName(declaringType, includePackage, list);
262             } else if (includePackage && !baseType.getPackage().isUnnamed()) {
263                 String JavaDoc[] components= baseType.getPackage().getNameComponents();
264                 for (int i= 0; i < components.length; i++) {
265                     list.add(components[i]);
266                 }
267             }
268         }
269         if (!baseType.isAnonymous()) {
270             list.add(type.getName());
271         } else {
272             list.add("$local$"); //$NON-NLS-1$
273
}
274     }
275     
276     
277     public static String JavaDoc[] getNameComponents(ITypeBinding type) {
278         List JavaDoc result= new ArrayList JavaDoc(5);
279         createName(type, false, result);
280         return (String JavaDoc[]) result.toArray(new String JavaDoc[result.size()]);
281     }
282     
283     public static String JavaDoc[] getAllNameComponents(ITypeBinding type) {
284         List JavaDoc result= new ArrayList JavaDoc(5);
285         createName(type, true, result);
286         return (String JavaDoc[]) result.toArray(new String JavaDoc[result.size()]);
287     }
288     
289     public static ITypeBinding getTopLevelType(ITypeBinding type) {
290         ITypeBinding parent= type.getDeclaringClass();
291         while (parent != null) {
292             type= parent;
293             parent= type.getDeclaringClass();
294         }
295         return type;
296     }
297     
298     /**
299      * Checks whether the passed type binding is a runtime exception.
300      *
301      * @param thrownException the type binding
302      *
303      * @return <code>true</code> if the passed type binding is a runtime exception;
304      * otherwise <code>false</code> is returned
305      */

306     public static boolean isRuntimeException(ITypeBinding thrownException) {
307         if (thrownException == null || thrownException.isPrimitive() || thrownException.isArray())
308             return false;
309         return findTypeInHierarchy(thrownException, "java.lang.RuntimeException") != null; //$NON-NLS-1$
310
}
311     
312     /**
313      * Finds the field specified by <code>fieldName<code> in
314      * the given <code>type</code>. Returns <code>null</code> if no such field exits.
315      * @param type the type to search the field in
316      * @param fieldName the field name
317      * @return the binding representing the field or <code>null</code>
318      */

319     public static IVariableBinding findFieldInType(ITypeBinding type, String JavaDoc fieldName) {
320         if (type.isPrimitive())
321             return null;
322         IVariableBinding[] fields= type.getDeclaredFields();
323         for (int i= 0; i < fields.length; i++) {
324             IVariableBinding field= fields[i];
325             if (field.getName().equals(fieldName))
326                 return field;
327         }
328         return null;
329     }
330         
331     /**
332      * Finds the method specified by <code>methodName<code> and </code>parameters</code> in
333      * the given <code>type</code>. Returns <code>null</code> if no such method exits.
334      * @param type The type to search the method in
335      * @param methodName The name of the method to find
336      * @param parameters The parameter types of the method to find. If <code>null</code> is passed, only
337      * the name is matched and parameters are ignored.
338      * @return the method binding representing the method
339      */

340     public static IMethodBinding findMethodInType(ITypeBinding type, String JavaDoc methodName, ITypeBinding[] parameters) {
341         if (type.isPrimitive())
342             return null;
343         IMethodBinding[] methods= type.getDeclaredMethods();
344         for (int i= 0; i < methods.length; i++) {
345             if (parameters == null) {
346                 if (methodName.equals(methods[i].getName()))
347                     return methods[i];
348             } else {
349                 if (isEqualMethod(methods[i], methodName, parameters))
350                     return methods[i];
351             }
352         }
353         return null;
354     }
355     
356     /**
357      * Finds the method specified by <code>methodName<code> and </code>parameters</code> in
358      * the given <code>type</code>. Returns <code>null</code> if no such method exits.
359      * @param type The type to search the method in
360      * @param methodName The name of the method to find
361      * @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.
362      * @return the method binding representing the method
363      */

364     public static IMethodBinding findMethodInType(ITypeBinding type, String JavaDoc methodName, String JavaDoc[] parameters) {
365         if (type.isPrimitive())
366             return null;
367         IMethodBinding[] methods= type.getDeclaredMethods();
368         for (int i= 0; i < methods.length; i++) {
369             if (parameters == null) {
370                 if (methodName.equals(methods[i].getName()))
371                     return methods[i];
372             } else {
373                 if (isEqualMethod(methods[i], methodName, parameters))
374                     return methods[i];
375             }
376         }
377         return null;
378     }
379     
380     /**
381      * Finds the method in the given <code>type</code> that is overrideen by the specified <code>method<code> . Returns <code>null</code> if no such method exits.
382      * @param type The type to search the method in
383      * @param method The specified method that would override the result
384      * @return the method binding representing the method oevrriding the specified <code>method<code>
385      */

386     public static IMethodBinding findOverriddenMethodInType(ITypeBinding type, IMethodBinding method) {
387         return findMethodInType(type, method.getName(), method.getParameterTypes());
388 // String methodName= method.getName();
389
// IMethodBinding[] methods= type.getDeclaredMethods();
390
// for (int i= 0; i < methods.length; i++) {
391
// IMethodBinding curr= methods[i];
392
// if (curr.getName().equals(methodName) && method.overrides(curr)) { // name check: see bug 98483
393
// return curr;
394
// }
395
// }
396
// return null;
397
}
398
399     /**
400      * Finds the field specified by <code>fieldName</code> in
401      * the type hierarchy denoted by the given type. Returns <code>null</code> if no such field
402      * exists. If the field is defined in more than one super type only the first match is
403      * returned. First the super class is examined and than the implemented interfaces.
404      * @param type The type to search the field in
405      * @param fieldName The name of the field to find
406      * @return the variable binding representing the field
407      */

408     public static IVariableBinding findFieldInHierarchy(ITypeBinding type, String JavaDoc fieldName) {
409         IVariableBinding field= findFieldInType(type, fieldName);
410         if (field != null)
411             return field;
412         ITypeBinding superClass= type.getSuperclass();
413         if (superClass != null) {
414             field= findFieldInType(type, fieldName);
415             if (field != null)
416                 return field;
417         }
418         ITypeBinding[] interfaces= type.getInterfaces();
419         for (int i= 0; i < interfaces.length; i++) {
420             field= findFieldInType(type, fieldName);
421             if (field != null) // no private fields in interfaces
422
return field;
423         }
424         return null;
425     }
426
427
428     /**
429      * Finds the method specified by <code>methodName</code> and </code>parameters</code> in
430      * the type hierarchy denoted by the given type. Returns <code>null</code> if no such method
431      * exists. If the method is defined in more than one super type only the first match is
432      * returned. First the super class is examined and than the implemented interfaces.
433      * @param type The type to search the method in
434      * @param methodName The name of the method to find
435      * @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.
436      * @return the method binding representing the method
437      */

438     public static IMethodBinding findMethodInHierarchy(ITypeBinding type, String JavaDoc methodName, ITypeBinding parameters[]) {
439         IMethodBinding method= findMethodInType(type, methodName, parameters);
440         if (method != null)
441             return method;
442         ITypeBinding superClass= type.getSuperclass();
443         if (superClass != null) {
444             method= findMethodInHierarchy(superClass, methodName, parameters);
445             if (method != null)
446                 return method;
447         }
448         ITypeBinding[] interfaces= type.getInterfaces();
449         for (int i= 0; i < interfaces.length; i++) {
450             method= findMethodInHierarchy(interfaces[i], methodName, parameters);
451             if (method != null)
452                 return method;
453         }
454         return null;
455     }
456
457
458     /**
459      * Finds the method specified by <code>methodName</code> and </code>parameters</code> in
460      * the type hierarchy denoted by the given type. Returns <code>null</code> if no such method
461      * exists. If the method is defined in more than one super type only the first match is
462      * returned. First the super class is examined and than the implemented interfaces.
463      * @param typeObject the type binding for <code>java.lang.Object</code>.
464      * @param type the type to search the method in
465      * @param methodName The name of the method to find
466      * @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.
467      * @return the method binding representing the method
468      */

469     public static IMethodBinding findMethodInHierarchy(ITypeBinding typeObject, ITypeBinding type, String JavaDoc methodName, String JavaDoc parameters[]) {
470         IMethodBinding method= findMethodInType(type, methodName, parameters);
471         if (method != null)
472             return method;
473         ITypeBinding superClass= type.getSuperclass();
474         if (superClass == null && type.isInterface())
475             superClass= typeObject;
476         if (superClass != null) {
477             method= findMethodInHierarchy(typeObject, superClass, methodName, parameters);
478             if (method != null)
479                 return method;
480         }
481         ITypeBinding[] interfaces= type.getInterfaces();
482         for (int i= 0; i < interfaces.length; i++) {
483             method= findMethodInHierarchy(typeObject, interfaces[i], methodName, parameters);
484             if (method != null)
485                 return method;
486         }
487         return null;
488     }
489     
490     /**
491      * Finds a method in the hierarchy of <code>type</code> that is overridden by </code>binding</code>.
492      * 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
493      * returned. First the super class is examined and than the implemented interfaces.
494      * @param type The type to search the method in
495      * @param binding The method that overrrides
496      * @return the method binding overridden the method
497      */

498     public static IMethodBinding findOverriddenMethodInHierarchy(ITypeBinding type, IMethodBinding binding) {
499         IMethodBinding method= findOverriddenMethodInType(type, binding);
500         if (method != null)
501             return method;
502         ITypeBinding superClass= type.getSuperclass();
503         if (superClass != null) {
504             method= findOverriddenMethodInHierarchy(superClass, binding);
505             if (method != null)
506                 return method;
507         }
508         ITypeBinding[] interfaces= type.getInterfaces();
509         for (int i= 0; i < interfaces.length; i++) {
510             method= findOverriddenMethodInHierarchy(interfaces[i], binding);
511             if (method != null)
512                 return method;
513         }
514         return null;
515     }
516     
517     
518     /**
519      * Finds the method that is defines the given method. The returned method might not be visible.
520      * @param method The method to find
521      * @param testVisibility If true the result is tested on visibility. Null is returned if the method is not visible.
522      * @return the method binding representing the method
523      */

524     public static IMethodBinding findMethodDefininition(IMethodBinding method, boolean testVisibility) {
525         int modifiers= method.getModifiers();
526         if (Modifier.isPrivate(modifiers) || Modifier.isStatic(modifiers) || method.isConstructor()) {
527             return null;
528         }
529         
530         ITypeBinding type= method.getDeclaringClass();
531         if (type.isInterface()) {
532             return null;
533         }
534         
535         if (type.getSuperclass() != null) {
536             IMethodBinding res= findOverriddenMethodInHierarchy(type.getSuperclass(), method);
537             if (res != null && !Modifier.isPrivate(res.getModifiers())) {
538                 if (!testVisibility || isVisibleInHierarchy(res, method.getDeclaringClass().getPackage())) {
539                     return res;
540                 }
541             }
542         }
543         ITypeBinding[] interfaces= type.getInterfaces();
544         for (int i= 0; i < interfaces.length; i++) {
545             IMethodBinding res= findOverriddenMethodInHierarchy(interfaces[i], method);
546             if (res != null) {
547                 return res; // methods from interfaces are always public and therefore visible
548
}
549         }
550         return null;
551     }
552     
553     /**
554      * Finds the method that is implemented by the given method.
555      * @param method The method to find
556      * @param testVisibility If true the result is tested on visibility. Null is returned if the method is not visible.
557      * @return the method binding representing the method
558      */

559     public static IMethodBinding findMethodImplementation(IMethodBinding method, boolean testVisibility) {
560         ITypeBinding superClass= method.getDeclaringClass().getSuperclass();
561         
562         String JavaDoc methodName= method.getName();
563         ITypeBinding[] parameters= method.getParameterTypes();
564         while (superClass != null) {
565             IMethodBinding res= findMethodInType(superClass, methodName, parameters);
566             if (res != null) {
567                 if (isVisibleInHierarchy(res, method.getDeclaringClass().getPackage())) {
568                     return res;
569                 }
570                 return null;
571             }
572             superClass= superClass.getSuperclass();
573         }
574         return null;
575     }
576     
577     public static boolean isVisibleInHierarchy(IMethodBinding member, IPackageBinding pack) {
578         int otherflags= member.getModifiers();
579         ITypeBinding declaringType= member.getDeclaringClass();
580         if (Modifier.isPublic(otherflags) || Modifier.isProtected(otherflags) || (declaringType != null && declaringType.isInterface())) {
581             return true;
582         } else if (Modifier.isPrivate(otherflags)) {
583             return false;
584         }
585         return pack == declaringType.getPackage();
586     }
587     
588     /**
589      * Finds the declaration of a method specified by <code>methodName</code> and </code>parameters</code> in
590      * the type hierarchy denoted by the given type. Returns <code>null</code> if no such method
591      * exists. If the method is defined in more than one super type only the first match is
592      * returned. First the super class is examined and than the implemented interfaces.
593      * @param type The type to search the method in
594      * @param methodName The name of the method to find
595      * @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.
596      * @return the method binding representing the method
597      */

598     public static IMethodBinding findDeclarationInHierarchy(ITypeBinding type, String JavaDoc methodName, ITypeBinding[] parameters) {
599         ITypeBinding[] interfaces= type.getInterfaces();
600         for (int i= 0; i < interfaces.length; i++) {
601             ITypeBinding curr= interfaces[i];
602             IMethodBinding method= findMethodInType(curr, methodName, parameters);
603             if (method != null)
604                 return method;
605             method= findDeclarationInHierarchy(interfaces[i], methodName, parameters);
606             if (method != null)
607                 return method;
608         }
609         ITypeBinding superClass= type.getSuperclass();
610         if (superClass != null) {
611             IMethodBinding method= findMethodInType(superClass, methodName, parameters);
612             if (method != null)
613                 return method;
614             
615             method= findDeclarationInHierarchy(superClass, methodName, parameters);
616             if (method != null)
617                 return method;
618         }
619         return null;
620     }
621     
622     /**
623      * Returns all super types (classes and interfaces) for the given type.
624      * @param type The type to get the supertypes of.
625      * @return all super types (excluding <code>type</code>)
626      */

627     public static ITypeBinding[] getAllSuperTypes(ITypeBinding type) {
628         Set JavaDoc result= new HashSet JavaDoc();
629         collectSuperTypes(type, result);
630         result.remove(type);
631         return (ITypeBinding[]) result.toArray(new ITypeBinding[result.size()]);
632     }
633     
634     private static void collectSuperTypes(ITypeBinding curr, Set JavaDoc collection) {
635         if (collection.add(curr)) {
636             ITypeBinding[] interfaces= curr.getInterfaces();
637             for (int i= 0; i < interfaces.length; i++) {
638                 collectSuperTypes(interfaces[i], collection);
639             }
640             ITypeBinding superClass= curr.getSuperclass();
641             if (superClass != null) {
642                 collectSuperTypes(superClass, collection);
643             }
644         }
645     }
646
647     /**
648      * Method to visit a type hierarchy defined by a given type.
649      *
650      * @param type the type which hierarchy is to be visited
651      * @param visitor the visitor
652      * @return <code>false</code> if the visiting got interrupted
653      */

654     public static boolean visitHierarchy(ITypeBinding type, TypeBindingVisitor visitor) {
655         boolean result= visitSuperclasses(type, visitor);
656         if(result) {
657             result= visitInterfaces(type, visitor);
658         }
659         return result;
660     }
661
662     /**
663      * Method to visit a interface hierarchy defined by a given type.
664      *
665      * @param type the type which interface hierarchy is to be visited
666      * @param visitor the visitor
667      * @return <code>false</code> if the visiting got interrupted
668      */

669     public static boolean visitInterfaces(ITypeBinding type, TypeBindingVisitor visitor) {
670         ITypeBinding[] interfaces= type.getInterfaces();
671         for (int i= 0; i < interfaces.length; i++) {
672             if (!visitor.visit(interfaces[i])) {
673                 return false;
674             }
675         }
676         return true;
677     }
678
679     /**
680      * Method to visit a super class hierarchy defined by a given type.
681      *
682      * @param type the type which super class hierarchy is to be visited
683      * @param visitor the visitor
684      * @return <code>false</code> if the visiting got interrupted
685      */

686     public static boolean visitSuperclasses(ITypeBinding type, TypeBindingVisitor visitor) {
687         while ((type= type.getSuperclass()) != null) {
688             if (!visitor.visit(type)) {
689                 return false;
690             }
691         }
692         return true;
693     }
694
695     public static boolean isEqualMethod(IMethodBinding method, String JavaDoc methodName, ITypeBinding[] parameters) {
696         if (!method.getName().equals(methodName))
697             return false;
698             
699         ITypeBinding[] methodParameters= method.getParameterTypes();
700         if (methodParameters.length != parameters.length)
701             return false;
702         for (int i= 0; i < parameters.length; i++) {
703             if (!equals(methodParameters[i].getErasure(), parameters[i].getErasure()))
704                 return false;
705         }
706         return true;
707     }
708
709     public static boolean isEqualMethod(IMethodBinding method, String JavaDoc methodName, String JavaDoc[] parameters) {
710         if (!method.getName().equals(methodName))
711             return false;
712
713         ITypeBinding[] methodParameters= method.getParameterTypes();
714         if (methodParameters.length != parameters.length)
715             return false;
716         String JavaDoc first, second;
717         int index;
718         for (int i= 0; i < parameters.length; i++) {
719             first= parameters[i];
720             index= first.indexOf('<');
721             if (index > 0)
722                 first= first.substring(0, index);
723             second= methodParameters[i].getErasure().getQualifiedName();
724             index= second.indexOf('<');
725             if (index > 0)
726                 second= second.substring(0, index);
727             if (!first.equals(second))
728                 return false;
729         }
730         return true;
731     }
732
733     /**
734      * Finds a type binding for a given fully qualified type in the hierarchy of a type.
735      * Returns <code>null</code> if no type binding is found.
736      * @param hierarchyType the binding representing the hierarchy
737      * @param fullyQualifiedTypeName the fully qualified name to search for
738      * @return the type binding
739      */

740     public static ITypeBinding findTypeInHierarchy(ITypeBinding hierarchyType, String JavaDoc fullyQualifiedTypeName) {
741         if (hierarchyType.isArray() || hierarchyType.isPrimitive()) {
742             return null;
743         }
744         if (fullyQualifiedTypeName.equals(hierarchyType.getQualifiedName())) {
745             return hierarchyType;
746         }
747         ITypeBinding superClass= hierarchyType.getSuperclass();
748         if (superClass != null) {
749             ITypeBinding res= findTypeInHierarchy(superClass, fullyQualifiedTypeName);
750             if (res != null) {
751                 return res;
752             }
753         }
754         ITypeBinding[] superInterfaces= hierarchyType.getInterfaces();
755         for (int i= 0; i < superInterfaces.length; i++) {
756             ITypeBinding res= findTypeInHierarchy(superInterfaces[i], fullyQualifiedTypeName);
757             if (res != null) {
758                 return res;
759             }
760         }
761         return null;
762     }
763     
764     /**
765      * Returns the binding of the variable written in an Assignment.
766      * @param assignment The assignment
767      * @return The binding or <code>null</code> if no bindings are available.
768      */

769     public static IVariableBinding getAssignedVariable(Assignment assignment) {
770         Expression leftHand = assignment.getLeftHandSide();
771         switch (leftHand.getNodeType()) {
772             case ASTNode.SIMPLE_NAME:
773                 return (IVariableBinding) ((SimpleName) leftHand).resolveBinding();
774             case ASTNode.QUALIFIED_NAME:
775                 return (IVariableBinding) ((QualifiedName) leftHand).getName().resolveBinding();
776             case ASTNode.FIELD_ACCESS:
777                 return ((FieldAccess) leftHand).resolveFieldBinding();
778             case ASTNode.SUPER_FIELD_ACCESS:
779                 return ((SuperFieldAccess) leftHand).resolveFieldBinding();
780             default:
781                 return null;
782         }
783     }
784     
785     /**
786      * Returns <code>true</code> if the given type is a super type of a candidate.
787      * <code>true</code> is returned if the two type bindings are identical (TODO)
788      * @param type the type to inspect
789      * @param candidate the candidates
790      * @return <code>true</code> is a super type of one of the candidates; otherwise
791      * <code>false</code>
792      */

793     public static boolean isSuperType(ITypeBinding type, ITypeBinding candidate) {
794         if (candidate.isArray() || candidate.isPrimitive()) {
795             return false;
796         }
797         if (Bindings.equals(candidate, type)) {
798             return true;
799         }
800         ITypeBinding superClass= candidate.getSuperclass();
801         if (superClass != null) {
802             if (isSuperType(type, superClass)) {
803                 return true;
804             }
805         }
806         
807         if (type.isInterface()) {
808             ITypeBinding[] superInterfaces= candidate.getInterfaces();
809             for (int i= 0; i < superInterfaces.length; i++) {
810                 if (isSuperType(type, superInterfaces[i])) {
811                     return true;
812                 }
813             }
814         }
815         return false;
816     }
817     
818
819     // find IJavaElements for bindings
820

821     /**
822      * Finds the compilation unit where the type of the given <code>ITypeBinding</code> is defined,
823      * using the class path defined by the given Java project. Returns <code>null</code>
824      * if no compilation unit is found (e.g. type binding is from a binary type)
825      * @param typeBinding the type binding to search for
826      * @param project the project used as a scope
827      * @return the compilation unit containing the type
828      * @throws JavaModelException if an errors occurs in the Java model
829      */

830     public static ICompilationUnit findCompilationUnit(ITypeBinding typeBinding, IJavaProject project) throws JavaModelException {
831         ICompilationUnit coreFindCompilationUnit= coreFindCompilationUnit(typeBinding);
832         if (CHECK_CORE_BINDING_GET_JAVA_ELEMENT) {
833             ICompilationUnit originalFindCompilationUnit= originalFindCompilationUnit(typeBinding, project);
834             if (coreFindCompilationUnit == null) {
835                 if (originalFindCompilationUnit != null) {
836                     JavaPlugin.logRepeatedMessage("ITypeBinding#getJavaElement() is not supposed to be null: ", //$NON-NLS-1$
837
"typeBinding == " + typeBinding.getKey() + ", project == " + project.getElementName() //$NON-NLS-1$//$NON-NLS-2$
838
+ ", coreFindCompilationUnit == " + coreFindCompilationUnit + ", originalFindCompilationUnit == " + originalFindCompilationUnit); //$NON-NLS-1$//$NON-NLS-2$
839
}
840             } else {
841                 if (! coreFindCompilationUnit.equals(originalFindCompilationUnit)) {
842                     JavaPlugin.logRepeatedMessage("ITypeBinding#getJavaElement() is not correct element: ", //$NON-NLS-1$
843
"typeBinding == " + typeBinding.getKey() + ", project == " + project.getElementName() //$NON-NLS-1$//$NON-NLS-2$
844
+ ", coreFindCompilationUnit == " + coreFindCompilationUnit + ", originalFindCompilationUnit == " + originalFindCompilationUnit); //$NON-NLS-1$//$NON-NLS-2$
845
}
846             }
847         }
848         return coreFindCompilationUnit;
849     }
850
851     private static ICompilationUnit coreFindCompilationUnit(ITypeBinding typeBinding) {
852         IJavaElement type= typeBinding.getJavaElement();
853         if (type instanceof IType)
854             return ((IType) type).getCompilationUnit();
855         else
856             return null;
857     }
858
859     private static ICompilationUnit originalFindCompilationUnit(ITypeBinding typeBinding, IJavaProject project) throws JavaModelException {
860         if (!typeBinding.isFromSource()) {
861             return null;
862         }
863         while (typeBinding != null && !typeBinding.isTopLevel()) {
864             typeBinding= typeBinding.getDeclaringClass();
865         }
866         if (typeBinding != null) {
867             typeBinding= typeBinding.getTypeDeclaration();
868             IPackageBinding pack= typeBinding.getPackage();
869             String JavaDoc packageName= pack.isUnnamed() ? "" : pack.getName(); //$NON-NLS-1$
870
IType type= project.findType(packageName, typeBinding.getName());
871             if (type != null) {
872                 return type.getCompilationUnit();
873             }
874         }
875         return null;
876     }
877
878     /**
879      * Finds a field for the given <code>IVariableBinding</code>
880      * using the class path defined by the given Java project. Returns <code>null</code>
881      * if the field could not be found.
882      * @param field the field to search for
883      * @param in the project defining the scope
884      * @return the corresponding IField
885      * @throws JavaModelException if an error occurs in the Java model
886      */

887     public static IField findField(IVariableBinding field, IJavaProject in) throws JavaModelException {
888         Assert.isTrue(field.isField());
889         IField iField= (IField) field.getJavaElement();
890         if (CHECK_CORE_BINDING_GET_JAVA_ELEMENT) {
891             IField originalFindField= originalFindField(field, in);
892             if (iField != null && ! iField.equals(originalFindField)
893                     || iField == null && originalFindField != null) {
894                 JavaPlugin.logRepeatedMessage("IVariableBinding#getJavaElement() is not correct element: ", //$NON-NLS-1$
895
"field == " + field.getKey() + ", project == " + in.getElementName() //$NON-NLS-1$//$NON-NLS-2$
896
+ ", iField == " + iField + ", originalFindField == " + originalFindField); //$NON-NLS-1$//$NON-NLS-2$
897
}
898         }
899         return iField;
900     }
901
902     private static IField originalFindField(IVariableBinding field, IJavaProject in) throws JavaModelException {
903         ITypeBinding declaringClassBinding = field.getDeclaringClass();
904         if (declaringClassBinding == null)
905             return null;
906         IType declaringClass = findType(declaringClassBinding, in);
907         if (declaringClass == null)
908             return null;
909         IField foundField= declaringClass.getField(field.getName());
910         if (! foundField.exists())
911             return null;
912         return foundField;
913     }
914
915     /**
916      * Finds a type for the given <code>ITypeBinding</code>
917      * using the class path defined by the given Java project. Returns <code>null</code>
918      * if the type could not be found.
919      * @param type the type to find
920      * @param scope the project scope
921      * @return the corresponding IType or <code>null</code>
922      * @throws JavaModelException if an error occurs in the Java model
923      */

924     public static IType findType(ITypeBinding type, IJavaProject scope) throws JavaModelException {
925         IType iType= (IType) type.getJavaElement();
926         if (CHECK_CORE_BINDING_GET_JAVA_ELEMENT) {
927             IType originalFindType= originalFindType(type, scope);
928             if (iType != null && ! iType.equals(originalFindType)
929                     || iType == null && originalFindType != null) {
930                 JavaPlugin.logRepeatedMessage("ITypeBinding#getJavaElement() is not correct element: ", //$NON-NLS-1$
931
"type == " + type.getKey() + ", project == " + scope.getElementName() //$NON-NLS-1$//$NON-NLS-2$
932
+ ", iType == " + iType + ", originalFindType == " + originalFindType); //$NON-NLS-1$//$NON-NLS-2$
933
}
934         }
935         return iType;
936     }
937
938     private static IType originalFindType(ITypeBinding type, IJavaProject scope) throws JavaModelException {
939         if (type.isPrimitive() || type.isAnonymous() || type.isNullType())
940             return null;
941         if (type.isArray())
942             return findType(type.getElementType(), scope);
943             
944         // TODO: Bug 36032: JavaCore should allow to find secondary top level types.
945

946         String JavaDoc[] typeElements= Bindings.getNameComponents(type);
947         IJavaElement element= scope.findElement(getPathToCompilationUnit(type.getPackage(), typeElements[0]));
948         IType candidate= null;
949         if (element instanceof ICompilationUnit) {
950             candidate= ((ICompilationUnit)element).getType(typeElements[0]);
951         } else if (element instanceof IClassFile) {
952             candidate= ((IClassFile)element).getType();
953         } else if (element == null) {
954             if (type.isMember())
955                 candidate= JavaModelUtil.findType(scope, Bindings.getFullyQualifiedName(type.getDeclaringClass()));
956             else
957                 candidate= JavaModelUtil.findType(scope, Bindings.getFullyQualifiedName(type));
958         }
959         
960         if (candidate == null || typeElements.length == 1)
961             return candidate;
962             
963         return findTypeInType(typeElements, candidate);
964     }
965
966     /**
967      * Finds a method for the given <code>IMethodBinding</code>. Returns
968      * <code>null</code> if the method can not be found in the declaring type of the method binding.
969      * @param method the method to find
970      * @param scope the project scope
971      * @return the corresponding IMethod or <code>null</code>
972      * @throws JavaModelException if an error occurs in the Java model
973      */

974     public static IMethod findMethod(IMethodBinding method, IJavaProject scope) throws JavaModelException {
975         if (! USE_UI_BINDING_GET_JAVA_ELEMENT) {
976             IMethod iMethod= (IMethod) method.getJavaElement();
977             if (CHECK_CORE_BINDING_GET_JAVA_ELEMENT) {
978                 IMethod originalFindMethod= originalFindMethod(method, scope);
979                 if (iMethod != null && ! iMethod.equals(originalFindMethod)
980                         || iMethod == null && originalFindMethod != null) {
981                     JavaPlugin.logRepeatedMessage("IMethodBinding#getJavaElement() is not correct element: ", //$NON-NLS-1$
982
"method == " + method.getKey() + ", project == " + scope.getElementName() //$NON-NLS-1$//$NON-NLS-2$
983
+ ", iMethod == " + iMethod + ", originalFindMethod == " + originalFindMethod); //$NON-NLS-1$//$NON-NLS-2$
984
}
985             }
986             return iMethod;
987         }
988         
989         IMethod originalFindMethod= originalFindMethod(method, scope);
990         if (CHECK_CORE_BINDING_GET_JAVA_ELEMENT) {
991             IMethod iMethod= (IMethod) method.getJavaElement();
992             if (iMethod != null && ! iMethod.equals(originalFindMethod)
993                     || iMethod == null && originalFindMethod != null) {
994                 JavaPlugin.logRepeatedMessage("IMethodBinding#getJavaElement() is not correct element: ", //$NON-NLS-1$
995
"method == " + method.getKey() + ", project == " + scope.getElementName() //$NON-NLS-1$//$NON-NLS-2$
996
+ ", iMethod == " + iMethod + ", originalFindMethod == " + originalFindMethod); //$NON-NLS-1$//$NON-NLS-2$
997
}
998         }
999         return originalFindMethod;
1000    }
1001
1002    private static IMethod originalFindMethod(IMethodBinding method, IJavaProject scope) throws JavaModelException {
1003        IType type= findType(method.getDeclaringClass(), scope);
1004        if (type == null)
1005            return null;
1006        return findMethod(method, type);
1007    }
1008    
1009    /**
1010     * Finds a method for the given <code>IMethodBinding</code>. Returns
1011     * <code>null</code> if the type doesn't contain a corresponding method.
1012     * @param method the method to find
1013     * @param type the type to look in
1014     * @return the corresponding IMethod or <code>null</code>
1015     * @throws JavaModelException if an error occurs in the Java model
1016     */

1017    public static IMethod findMethod(IMethodBinding method, IType type) throws JavaModelException {
1018        method= method.getMethodDeclaration();
1019        
1020        IMethod[] candidates= type.getMethods();
1021        for (int i= 0; i < candidates.length; i++) {
1022            IMethod candidate= candidates[i];
1023            if (candidate.getElementName().equals(method.getName()) && sameParameters(method, candidate)) {
1024                return candidate;
1025            }
1026        }
1027        return null;
1028    }
1029
1030    //---- Helper methods to convert a type --------------------------------------------
1031

1032    private static IPath getPathToCompilationUnit(IPackageBinding packageBinding, String JavaDoc topLevelTypeName) {
1033        IPath result= Path.EMPTY;
1034        String JavaDoc[] packageNames= packageBinding.getNameComponents();
1035        for (int i= 0; i < packageNames.length; i++) {
1036            result= result.append(packageNames[i]);
1037        }
1038        return result.append(topLevelTypeName + ".java"); //$NON-NLS-1$
1039
}
1040
1041    private static IType findTypeInType(String JavaDoc[] typeElements, IType jmType) {
1042        IType result= jmType;
1043        for (int i= 1; i < typeElements.length; i++) {
1044            result= result.getType(typeElements[i]);
1045            if (!result.exists())
1046                return null;
1047        }
1048        return result == jmType ? null : result;
1049    }
1050
1051    //---- Helper methods to convert a method ---------------------------------------------
1052

1053    private static boolean sameParameters(IMethodBinding method, IMethod candidate) throws JavaModelException {
1054        ITypeBinding[] methodParamters= method.getParameterTypes();
1055        String JavaDoc[] candidateParameters= candidate.getParameterTypes();
1056        if (methodParamters.length != candidateParameters.length)
1057            return false;
1058        IType scope= candidate.getDeclaringType();
1059        for (int i= 0; i < methodParamters.length; i++) {
1060            ITypeBinding methodParameter= methodParamters[i];
1061            String JavaDoc candidateParameter= candidateParameters[i];
1062            if (!sameParameter(methodParameter, candidateParameter, scope))
1063                return false;
1064        }
1065        return true;
1066    }
1067
1068    private static boolean sameParameter(ITypeBinding type, String JavaDoc candidate, IType scope) throws JavaModelException {
1069        if (type.getDimensions() != Signature.getArrayCount(candidate))
1070            return false;
1071            
1072        // Normalizes types
1073
if (type.isArray())
1074            type= type.getElementType();
1075        candidate= Signature.getElementType(candidate);
1076        
1077        if (isPrimitiveType(candidate) != type.isPrimitive()) {
1078            return false;
1079        }
1080            
1081        if (type.isPrimitive() || type.isTypeVariable()) {
1082            return type.getName().equals(Signature.toString(candidate));
1083        } else {
1084            // normalize (quick hack until binding.getJavaElement works)
1085
candidate= Signature.getTypeErasure(candidate);
1086            type= type.getErasure();
1087            
1088            if (isResolvedType(candidate)) {
1089                return Signature.toString(candidate).equals(Bindings.getFullyQualifiedName(type));
1090            } else {
1091                String JavaDoc[][] qualifiedCandidates= scope.resolveType(Signature.toString(candidate));
1092                if (qualifiedCandidates == null || qualifiedCandidates.length == 0)
1093                    return false;
1094                String JavaDoc packageName= type.getPackage().isUnnamed() ? "" : type.getPackage().getName(); //$NON-NLS-1$
1095
String JavaDoc typeName= getTypeQualifiedName(type);
1096                for (int i= 0; i < qualifiedCandidates.length; i++) {
1097                    String JavaDoc[] qualifiedCandidate= qualifiedCandidates[i];
1098                    if ( qualifiedCandidate[0].equals(packageName) &&
1099                            qualifiedCandidate[1].equals(typeName))
1100                        return true;
1101                }
1102            }
1103        }
1104        return false;
1105    }
1106
1107    private static boolean isPrimitiveType(String JavaDoc s) {
1108        return Signature.getTypeSignatureKind(s) == Signature.BASE_TYPE_SIGNATURE;
1109    }
1110    
1111    private static boolean isResolvedType(String JavaDoc s) {
1112        int arrayCount= Signature.getArrayCount(s);
1113        return s.charAt(arrayCount) == Signature.C_RESOLVED;
1114    }
1115
1116    /**
1117     * Normalizes a type binding received from an expression to a type binding that can be used in a declaration signature.
1118     * Anonymous types are normalized, to the super class or interface. For null or void bindings
1119     * <code>null</code> is returned.
1120     * @param binding the binding to normalize
1121     * @return the normalized binding
1122     */

1123    public static ITypeBinding normalizeTypeBinding(ITypeBinding binding) {
1124        if (binding != null && !binding.isNullType() && !isVoidType(binding)) {
1125            if (binding.isAnonymous()) {
1126                ITypeBinding[] baseBindings= binding.getInterfaces();
1127                if (baseBindings.length > 0) {
1128                    return baseBindings[0];
1129                }
1130                return binding.getSuperclass();
1131            }
1132            if (binding.isCapture()) {
1133                return binding.getWildcard();
1134            }
1135            return binding;
1136        }
1137        return null;
1138    }
1139    
1140    public static boolean isVoidType(ITypeBinding binding) {
1141        return "void".equals(binding.getName()); //$NON-NLS-1$
1142
}
1143    
1144    
1145    /**
1146     * Normalizes the binding so that it can be used as a type inside a declaration
1147     * (e.g. variable declaration, method return type, parameter type, ...). For
1148     * null bindings Object is returned.
1149     *
1150     * @return the normalized type to be used in declarations
1151     */

1152    public static ITypeBinding normalizeForDeclarationUse(ITypeBinding binding, AST ast) {
1153        if (binding.isNullType())
1154            return ast.resolveWellKnownType("java.lang.Object"); //$NON-NLS-1$
1155
if (binding.isPrimitive())
1156            return binding;
1157        binding= normalizeTypeBinding(binding);
1158        if (binding == null || !binding.isWildcardType())
1159            return binding;
1160        if (binding.isUpperbound()) {
1161            return binding.getBound();
1162        } else {
1163            return ast.resolveWellKnownType("java.lang.Object"); //$NON-NLS-1$
1164
}
1165    }
1166
1167    /**
1168     * Returns the type binding of the node's parent type declaration
1169     * @param node
1170     * @return CompilationUnit
1171     */

1172    public static ITypeBinding getBindingOfParentType(ASTNode node) {
1173        while (node != null) {
1174            if (node instanceof AbstractTypeDeclaration) {
1175                return ((AbstractTypeDeclaration) node).resolveBinding();
1176            } else if (node instanceof AnonymousClassDeclaration) {
1177                return ((AnonymousClassDeclaration) node).resolveBinding();
1178            }
1179            node= node.getParent();
1180        }
1181        return null;
1182    }
1183
1184    
1185    public static String JavaDoc getRawName(ITypeBinding binding) {
1186        String JavaDoc name= binding.getName();
1187        if (binding.isParameterizedType() || binding.isGenericType()) {
1188            int idx= name.indexOf('<');
1189            if (idx != -1) {
1190                return name.substring(0, idx);
1191            }
1192        }
1193        return name;
1194    }
1195    
1196
1197    public static String JavaDoc getRawQualifiedName(ITypeBinding binding) {
1198        final String JavaDoc EMPTY= ""; //$NON-NLS-1$
1199

1200        if (binding.isAnonymous() || binding.isLocal()) {
1201            return EMPTY; //$NON-NLS-1$
1202
}
1203        
1204        if (binding.isPrimitive() || binding.isNullType() || binding.isTypeVariable()) {
1205            return binding.getName();
1206        }
1207        
1208        if (binding.isArray()) {
1209            String JavaDoc elementTypeQualifiedName = getRawQualifiedName(binding.getElementType());
1210            if (elementTypeQualifiedName.length() != 0) {
1211                StringBuffer JavaDoc stringBuffer= new StringBuffer JavaDoc(elementTypeQualifiedName);
1212                stringBuffer.append('[').append(']');
1213                return stringBuffer.toString();
1214            } else {
1215                return EMPTY;
1216            }
1217        }
1218        if (binding.isMember()) {
1219            String JavaDoc outerName= getRawQualifiedName(binding.getDeclaringClass());
1220            if (outerName.length() > 0) {
1221                StringBuffer JavaDoc buffer= new StringBuffer JavaDoc();
1222                buffer.append(outerName);
1223                buffer.append('.');
1224                buffer.append(getRawName(binding));
1225                return buffer.toString();
1226            } else {
1227                return EMPTY;
1228            }
1229
1230        } else if (binding.isTopLevel()) {
1231            IPackageBinding packageBinding= binding.getPackage();
1232            StringBuffer JavaDoc buffer= new StringBuffer JavaDoc();
1233            if (packageBinding != null && packageBinding.getName().length() > 0) {
1234                buffer.append(packageBinding.getName()).append('.');
1235            }
1236            buffer.append(getRawName(binding));
1237            return buffer.toString();
1238        }
1239        return EMPTY;
1240    }
1241    
1242
1243    /**
1244     * Get field declaration. See bug 83100
1245     */

1246    public static IVariableBinding getVariableDeclaration(IVariableBinding var) {
1247        ITypeBinding declaringClass= var.getDeclaringClass();
1248        if (declaringClass == null) {
1249            return var;
1250        }
1251        if (declaringClass.getTypeDeclaration() == declaringClass) { // test if type is already declaration
1252
return var;
1253        }
1254        IVariableBinding[] genericFields= declaringClass.getTypeDeclaration().getDeclaredFields();
1255        String JavaDoc name= var.getName();
1256        for (int i= 0; i < genericFields.length; i++) {
1257            if (name.equals(genericFields[i].getName())) {
1258                return genericFields[i];
1259            }
1260        }
1261        Assert.isTrue(false, "field does not exist in generic type"); //$NON-NLS-1$
1262
return var;
1263    }
1264
1265    /**
1266     * Tests if the given node is a declaration, not a instance of a generic type, method or field.
1267     * Declarations can be found in AST with CompilationUnit.findDeclaringNode
1268     */

1269    public static boolean isDeclarationBinding(IBinding binding) {
1270        switch (binding.getKind()) {
1271            case IBinding.TYPE:
1272                return ((ITypeBinding) binding).getTypeDeclaration() == binding;
1273            case IBinding.VARIABLE:
1274                IVariableBinding var= (IVariableBinding) binding;
1275                return !var.isField() || isDeclarationBinding(var.getDeclaringClass());
1276            case IBinding.METHOD:
1277                return ((IMethodBinding) binding).getMethodDeclaration() == binding;
1278        }
1279        return true;
1280    }
1281
1282    public static boolean containsOverridingMethod(IMethodBinding[] candidates, IMethodBinding overridable) {
1283        for (int index= 0; index < candidates.length; index++) {
1284            if (areOverriddenMethods(candidates[index], overridable))
1285                return true;
1286        }
1287        return false;
1288    }
1289
1290    public static boolean containsSignatureEquivalentConstructor(IMethodBinding[] candidates, IMethodBinding overridable) {
1291        for (int index= 0; index < candidates.length; index++) {
1292            if (isSignatureEquivalentConstructor(candidates[index], overridable))
1293                return true;
1294        }
1295        return false;
1296    }
1297
1298    public static boolean isSignatureEquivalentConstructor(IMethodBinding overridden, IMethodBinding overridable) {
1299
1300        if (!overridden.isConstructor() || !overridable.isConstructor())
1301            return false;
1302        
1303        if (overridden.isDefaultConstructor())
1304            return false;
1305        
1306        return areSubTypeCompatible(overridden, overridable);
1307    }
1308    
1309    public static boolean areOverriddenMethods(IMethodBinding overridden, IMethodBinding overridable) {
1310
1311        if (!overridden.getName().equals(overridable.getName()))
1312            return false;
1313
1314        return areSubTypeCompatible(overridden, overridable);
1315    }
1316
1317    private static boolean areSubTypeCompatible(IMethodBinding overridden, IMethodBinding overridable) {
1318        
1319        if (overridden.getParameterTypes().length != overridable.getParameterTypes().length)
1320            return false;
1321        
1322        ITypeBinding overriddenReturn= overridden.getReturnType();
1323        ITypeBinding overridableReturn= overridable.getReturnType();
1324        if (overriddenReturn == null || overridableReturn == null)
1325            return false;
1326        
1327        if (!overriddenReturn.getErasure().isSubTypeCompatible(overridableReturn.getErasure()))
1328            return false;
1329        
1330        ITypeBinding[] overriddenTypes= overridden.getParameterTypes();
1331        ITypeBinding[] overridableTypes= overridable.getParameterTypes();
1332        Assert.isTrue(overriddenTypes.length == overridableTypes.length);
1333        for (int index= 0; index < overriddenTypes.length; index++) {
1334            final ITypeBinding overridableErasure= overridableTypes[index].getErasure();
1335            final ITypeBinding overriddenErasure= overriddenTypes[index].getErasure();
1336            if (!overridableErasure.isSubTypeCompatible(overriddenErasure) || !overridableErasure.getKey().equals(overriddenErasure.getKey()))
1337                return false;
1338        }
1339        ITypeBinding[] overriddenExceptions= overridden.getExceptionTypes();
1340        ITypeBinding[] overridableExceptions= overridable.getExceptionTypes();
1341        boolean checked= false;
1342        for (int index= 0; index < overriddenExceptions.length; index++) {
1343            checked= false;
1344            for (int offset= 0; offset < overridableExceptions.length; offset++) {
1345                if (overriddenExceptions[index].isSubTypeCompatible(overridableExceptions[offset]))
1346                    checked= true;
1347            }
1348            if (!checked)
1349                return false;
1350        }
1351        return true;
1352    }
1353    
1354}
1355
Popular Tags