]> git.uio.no Git - ifi-stolz-refaktor.git/blob - case-study/jdt-after/ui/org/eclipse/jdt/internal/ui/text/correction/ASTResolving.java
Case Study: adding data and statistics
[ifi-stolz-refaktor.git] / case-study / jdt-after / ui / org / eclipse / jdt / internal / ui / text / correction / ASTResolving.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2011 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  *******************************************************************************/
11
12 package org.eclipse.jdt.internal.ui.text.correction;
13
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.HashSet;
17 import java.util.Iterator;
18 import java.util.List;
19
20 import org.eclipse.core.runtime.IProgressMonitor;
21
22 import org.eclipse.jdt.core.ICompilationUnit;
23 import org.eclipse.jdt.core.JavaModelException;
24 import org.eclipse.jdt.core.dom.AST;
25 import org.eclipse.jdt.core.dom.ASTNode;
26 import org.eclipse.jdt.core.dom.ASTParser;
27 import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
28 import org.eclipse.jdt.core.dom.Annotation;
29 import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
30 import org.eclipse.jdt.core.dom.ArrayAccess;
31 import org.eclipse.jdt.core.dom.ArrayCreation;
32 import org.eclipse.jdt.core.dom.ArrayInitializer;
33 import org.eclipse.jdt.core.dom.ArrayType;
34 import org.eclipse.jdt.core.dom.AssertStatement;
35 import org.eclipse.jdt.core.dom.Assignment;
36 import org.eclipse.jdt.core.dom.BodyDeclaration;
37 import org.eclipse.jdt.core.dom.CastExpression;
38 import org.eclipse.jdt.core.dom.ClassInstanceCreation;
39 import org.eclipse.jdt.core.dom.CompilationUnit;
40 import org.eclipse.jdt.core.dom.ConditionalExpression;
41 import org.eclipse.jdt.core.dom.ConstructorInvocation;
42 import org.eclipse.jdt.core.dom.Expression;
43 import org.eclipse.jdt.core.dom.FieldAccess;
44 import org.eclipse.jdt.core.dom.FieldDeclaration;
45 import org.eclipse.jdt.core.dom.IBinding;
46 import org.eclipse.jdt.core.dom.IMethodBinding;
47 import org.eclipse.jdt.core.dom.ITypeBinding;
48 import org.eclipse.jdt.core.dom.IVariableBinding;
49 import org.eclipse.jdt.core.dom.InfixExpression;
50 import org.eclipse.jdt.core.dom.Initializer;
51 import org.eclipse.jdt.core.dom.InstanceofExpression;
52 import org.eclipse.jdt.core.dom.MemberValuePair;
53 import org.eclipse.jdt.core.dom.MethodDeclaration;
54 import org.eclipse.jdt.core.dom.MethodInvocation;
55 import org.eclipse.jdt.core.dom.Modifier;
56 import org.eclipse.jdt.core.dom.Name;
57 import org.eclipse.jdt.core.dom.ParameterizedType;
58 import org.eclipse.jdt.core.dom.PrefixExpression;
59 import org.eclipse.jdt.core.dom.PrimitiveType;
60 import org.eclipse.jdt.core.dom.PrimitiveType.Code;
61 import org.eclipse.jdt.core.dom.QualifiedName;
62 import org.eclipse.jdt.core.dom.QualifiedType;
63 import org.eclipse.jdt.core.dom.SimpleName;
64 import org.eclipse.jdt.core.dom.SimpleType;
65 import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
66 import org.eclipse.jdt.core.dom.Statement;
67 import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor;
68 import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
69 import org.eclipse.jdt.core.dom.SuperMethodInvocation;
70 import org.eclipse.jdt.core.dom.SwitchCase;
71 import org.eclipse.jdt.core.dom.SwitchStatement;
72 import org.eclipse.jdt.core.dom.TagElement;
73 import org.eclipse.jdt.core.dom.TryStatement;
74 import org.eclipse.jdt.core.dom.Type;
75 import org.eclipse.jdt.core.dom.TypeDeclaration;
76 import org.eclipse.jdt.core.dom.TypeLiteral;
77 import org.eclipse.jdt.core.dom.TypeParameter;
78 import org.eclipse.jdt.core.dom.VariableDeclaration;
79 import org.eclipse.jdt.core.dom.VariableDeclarationExpression;
80 import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
81 import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
82 import org.eclipse.jdt.core.dom.WildcardType;
83
84 import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory;
85 import org.eclipse.jdt.internal.corext.dom.ASTNodes;
86 import org.eclipse.jdt.internal.corext.dom.Bindings;
87 import org.eclipse.jdt.internal.corext.dom.GenericVisitor;
88 import org.eclipse.jdt.internal.corext.dom.ScopeAnalyzer;
89 import org.eclipse.jdt.internal.corext.dom.TypeBindingVisitor;
90
91 import org.eclipse.jdt.ui.JavaElementLabels;
92
93 import org.eclipse.jdt.internal.ui.javaeditor.ASTProvider;
94 import org.eclipse.jdt.internal.ui.viewsupport.BasicElementLabels;
95 import org.eclipse.jdt.internal.ui.viewsupport.BindingLabelProvider;
96
97 public class ASTResolving {
98
99         public static ITypeBinding guessBindingForReference(ASTNode node) {
100                 return Bindings.normalizeTypeBinding(getPossibleReferenceBinding(node));
101         }
102
103         private static ITypeBinding getPossibleReferenceBinding(ASTNode node) {
104                 ASTNode parent= node.getParent();
105                 switch (parent.getNodeType()) {
106                 case ASTNode.ASSIGNMENT:
107                         Assignment assignment= (Assignment) parent;
108                         if (node.equals(assignment.getLeftHandSide())) {
109                                 // field write access: xx= expression
110                                 return assignment.getRightHandSide().resolveTypeBinding();
111                         }
112                         // read access
113                         return assignment.getLeftHandSide().resolveTypeBinding();
114                 case ASTNode.INFIX_EXPRESSION:
115                         InfixExpression infix= (InfixExpression) parent;
116                         InfixExpression.Operator op= infix.getOperator();
117                         if (op == InfixExpression.Operator.CONDITIONAL_AND || op == InfixExpression.Operator.CONDITIONAL_OR) {
118                                 // boolean operation
119                                 return infix.getAST().resolveWellKnownType("boolean"); //$NON-NLS-1$
120                         } else if (op == InfixExpression.Operator.LEFT_SHIFT || op == InfixExpression.Operator.RIGHT_SHIFT_UNSIGNED || op == InfixExpression.Operator.RIGHT_SHIFT_SIGNED) {
121                                 // asymmetric operation
122                                 return infix.getAST().resolveWellKnownType("int"); //$NON-NLS-1$
123                         }
124                         if (node.equals(infix.getLeftOperand())) {
125                                 //      xx operation expression
126                                 ITypeBinding rigthHandBinding= infix.getRightOperand().resolveTypeBinding();
127                                 if (rigthHandBinding != null) {
128                                         return rigthHandBinding;
129                                 }
130                         } else {
131                                 // expression operation xx
132                                 ITypeBinding leftHandBinding= infix.getLeftOperand().resolveTypeBinding();
133                                 if (leftHandBinding != null) {
134                                         return leftHandBinding;
135                                 }
136                         }
137                         if (op != InfixExpression.Operator.EQUALS && op != InfixExpression.Operator.NOT_EQUALS) {
138                                 return infix.getAST().resolveWellKnownType("int"); //$NON-NLS-1$
139                         }
140                         break;
141                 case ASTNode.INSTANCEOF_EXPRESSION:
142                         InstanceofExpression instanceofExpression= (InstanceofExpression) parent;
143                         return instanceofExpression.getRightOperand().resolveBinding();
144                 case ASTNode.VARIABLE_DECLARATION_FRAGMENT:
145                         VariableDeclarationFragment frag= (VariableDeclarationFragment) parent;
146                         if (frag.getInitializer().equals(node)) {
147                                 return frag.getName().resolveTypeBinding();
148                         }
149                         break;
150                 case ASTNode.SUPER_METHOD_INVOCATION:
151                         SuperMethodInvocation superMethodInvocation= (SuperMethodInvocation) parent;
152                         IMethodBinding superMethodBinding= ASTNodes.getMethodBinding(superMethodInvocation.getName());
153                         if (superMethodBinding != null) {
154                                 return getParameterTypeBinding(node, superMethodInvocation.arguments(), superMethodBinding);
155                         }
156                         break;
157                 case ASTNode.METHOD_INVOCATION:
158                         MethodInvocation methodInvocation= (MethodInvocation) parent;
159                         IMethodBinding methodBinding= methodInvocation.resolveMethodBinding();
160                         if (methodBinding != null) {
161                                 return getParameterTypeBinding(node, methodInvocation.arguments(), methodBinding);
162                         }
163                         break;
164                 case ASTNode.SUPER_CONSTRUCTOR_INVOCATION: {
165                         SuperConstructorInvocation superInvocation= (SuperConstructorInvocation) parent;
166                         IMethodBinding superBinding= superInvocation.resolveConstructorBinding();
167                         if (superBinding != null) {
168                                 return getParameterTypeBinding(node, superInvocation.arguments(), superBinding);
169                         }
170                         break;
171                 }
172                 case ASTNode.CONSTRUCTOR_INVOCATION: {
173                         ConstructorInvocation constrInvocation= (ConstructorInvocation) parent;
174                         IMethodBinding constrBinding= constrInvocation.resolveConstructorBinding();
175                         if (constrBinding != null) {
176                                 return getParameterTypeBinding(node, constrInvocation.arguments(), constrBinding);
177                         }
178                         break;
179                 }
180                 case ASTNode.CLASS_INSTANCE_CREATION: {
181                         ClassInstanceCreation creation= (ClassInstanceCreation) parent;
182                         IMethodBinding creationBinding= creation.resolveConstructorBinding();
183                         if (creationBinding != null) {
184                                 return getParameterTypeBinding(node, creation.arguments(), creationBinding);
185                         }
186                         break;
187                 }
188                 case ASTNode.PARENTHESIZED_EXPRESSION:
189                         return guessBindingForReference(parent);
190                 case ASTNode.ARRAY_ACCESS:
191                         if (((ArrayAccess) parent).getIndex().equals(node)) {
192                                 return parent.getAST().resolveWellKnownType("int"); //$NON-NLS-1$
193                         } else {
194                                 ITypeBinding parentBinding= getPossibleReferenceBinding(parent);
195                                 if (parentBinding == null) {
196                                         parentBinding= parent.getAST().resolveWellKnownType("java.lang.Object"); //$NON-NLS-1$
197                                 }
198                                 return parentBinding.createArrayType(1);
199                         }
200                 case ASTNode.ARRAY_CREATION:
201                         if (((ArrayCreation) parent).dimensions().contains(node)) {
202                                 return parent.getAST().resolveWellKnownType("int"); //$NON-NLS-1$
203                         }
204                         break;
205                 case ASTNode.ARRAY_INITIALIZER:
206                         ASTNode initializerParent= parent.getParent();
207                         int dim= 1;
208                         while (initializerParent instanceof ArrayInitializer) {
209                                 initializerParent= initializerParent.getParent();
210                                 dim++;
211                         }
212                         Type creationType= null;
213                         if (initializerParent instanceof ArrayCreation) {
214                                 creationType= ((ArrayCreation) initializerParent).getType();
215                         } else if (initializerParent instanceof VariableDeclaration) {
216                                 VariableDeclaration varDecl= (VariableDeclaration) initializerParent;
217                                 creationType= ASTNodes.getType(varDecl);
218                                 dim-= varDecl.getExtraDimensions();
219                         } else if (initializerParent instanceof MemberValuePair) {
220                                 String name= ((MemberValuePair) initializerParent).getName().getIdentifier();
221                                 IMethodBinding annotMember= findAnnotationMember((Annotation) initializerParent.getParent(), name);
222                                 if (annotMember != null) {
223                                         return getReducedDimensionBinding(annotMember.getReturnType(), dim);
224                                 }
225                         }
226                         if (creationType != null) {
227                                 while ((creationType instanceof ArrayType) && dim > 0) {
228                                         creationType= ((ArrayType) creationType).getComponentType();
229                                         dim--;
230                                 }
231                                 return creationType.resolveBinding();
232                         }
233                         break;
234                 case ASTNode.CONDITIONAL_EXPRESSION:
235                         ConditionalExpression expression= (ConditionalExpression) parent;
236                         if (node.equals(expression.getExpression())) {
237                                 return parent.getAST().resolveWellKnownType("boolean"); //$NON-NLS-1$
238                         }
239                         if (node.equals(expression.getElseExpression())) {
240                                 return expression.getThenExpression().resolveTypeBinding();
241                         }
242                         return expression.getElseExpression().resolveTypeBinding();
243                 case ASTNode.POSTFIX_EXPRESSION:
244                         return parent.getAST().resolveWellKnownType("int"); //$NON-NLS-1$
245                 case ASTNode.PREFIX_EXPRESSION:
246                         if (((PrefixExpression) parent).getOperator() == PrefixExpression.Operator.NOT) {
247                                 return parent.getAST().resolveWellKnownType("boolean"); //$NON-NLS-1$
248                         }
249                         return parent.getAST().resolveWellKnownType("int"); //$NON-NLS-1$
250                 case ASTNode.IF_STATEMENT:
251                 case ASTNode.WHILE_STATEMENT:
252                 case ASTNode.DO_STATEMENT:
253                         if (node instanceof Expression) {
254                                 return parent.getAST().resolveWellKnownType("boolean"); //$NON-NLS-1$
255                         }
256                         break;
257                 case ASTNode.SWITCH_STATEMENT:
258                         if (((SwitchStatement) parent).getExpression().equals(node)) {
259                                 return parent.getAST().resolveWellKnownType("int"); //$NON-NLS-1$
260                         }
261                         break;
262                 case ASTNode.RETURN_STATEMENT:
263                         MethodDeclaration decl= ASTResolving.findParentMethodDeclaration(parent);
264                         if (decl != null && !decl.isConstructor()) {
265                                 return decl.getReturnType2().resolveBinding();
266                         }
267                         break;
268                 case ASTNode.CAST_EXPRESSION:
269                         return ((CastExpression) parent).getType().resolveBinding();
270                 case ASTNode.THROW_STATEMENT:
271                 case ASTNode.CATCH_CLAUSE:
272             return parent.getAST().resolveWellKnownType("java.lang.Exception"); //$NON-NLS-1$
273                 case ASTNode.FIELD_ACCESS:
274                         if (node.equals(((FieldAccess) parent).getName())) {
275                                 return getPossibleReferenceBinding(parent);
276                         }
277                         break;
278                 case ASTNode.SUPER_FIELD_ACCESS:
279                         return getPossibleReferenceBinding(parent);
280                 case ASTNode.QUALIFIED_NAME:
281                         if (node.equals(((QualifiedName) parent).getName())) {
282                                 return getPossibleReferenceBinding(parent);
283                         }
284                         break;
285                 case ASTNode.SWITCH_CASE:
286                         if (node.equals(((SwitchCase) parent).getExpression()) && parent.getParent() instanceof SwitchStatement) {
287                                 return ((SwitchStatement) parent.getParent()).getExpression().resolveTypeBinding();
288                         }
289                         break;
290                 case ASTNode.ASSERT_STATEMENT:
291                         if (node.getLocationInParent() == AssertStatement.EXPRESSION_PROPERTY) {
292                                 return parent.getAST().resolveWellKnownType("boolean"); //$NON-NLS-1$
293                         }
294                         return parent.getAST().resolveWellKnownType("java.lang.String"); //$NON-NLS-1$
295                 case ASTNode.SINGLE_MEMBER_ANNOTATION: {
296                         IMethodBinding annotMember= findAnnotationMember((Annotation) parent, "value"); //$NON-NLS-1$
297                         if (annotMember != null) {
298                                 return annotMember.getReturnType();
299                         }
300                         break;
301                 }
302                 case ASTNode.MEMBER_VALUE_PAIR: {
303                         String name= ((MemberValuePair) parent).getName().getIdentifier();
304                         IMethodBinding annotMember= findAnnotationMember((Annotation) parent.getParent(), name);
305                         if (annotMember != null) {
306                                 return annotMember.getReturnType();
307                         }
308                         break;
309                 }
310                 default:
311                         // do nothing
312                 }
313
314                 return null;
315         }
316
317         private static IMethodBinding findAnnotationMember(Annotation annotation, String name) {
318                 ITypeBinding annotBinding= annotation.resolveTypeBinding();
319                 if (annotBinding != null) {
320                         return Bindings.findMethodInType(annotBinding, name, (String[]) null);
321                 }
322                 return null;
323         }
324
325         public static Type guessTypeForReference(AST ast, ASTNode node) {
326                 ASTNode parent= node.getParent();
327                 while (parent != null) {
328                         switch (parent.getNodeType()) {
329                                 case ASTNode.VARIABLE_DECLARATION_FRAGMENT:
330                                         if (((VariableDeclarationFragment) parent).getInitializer() == node) {
331                                                 return ASTNodeFactory.newType(ast, (VariableDeclaration) parent);
332                                         }
333                                         return null;
334                                 case ASTNode.SINGLE_VARIABLE_DECLARATION:
335                                         if (((VariableDeclarationFragment) parent).getInitializer() == node) {
336                                                 return ASTNodeFactory.newType(ast, (VariableDeclaration) parent);
337                                         }
338                                         return null;
339                                 case ASTNode.ARRAY_ACCESS:
340                                         if (!((ArrayAccess) parent).getIndex().equals(node)) {
341                                                 Type type= guessTypeForReference(ast, parent);
342                                                 if (type != null) {
343                                                         return ast.newArrayType(type);
344                                                 }
345                                         }
346                                         return null;
347                                 case ASTNode.FIELD_ACCESS:
348                                         if (node.equals(((FieldAccess) parent).getName())) {
349                                                 node= parent;
350                                                 parent= parent.getParent();
351                                         } else {
352                                                 return null;
353                                         }
354                                         break;
355                                 case ASTNode.SUPER_FIELD_ACCESS:
356                                 case ASTNode.PARENTHESIZED_EXPRESSION:
357                                         node= parent;
358                                         parent= parent.getParent();
359                                         break;
360                                 case ASTNode.QUALIFIED_NAME:
361                                         if (node.equals(((QualifiedName) parent).getName())) {
362                                                 node= parent;
363                                                 parent= parent.getParent();
364                                         } else {
365                                                 return null;
366                                         }
367                                         break;
368                                 default:
369                                         return null;
370                         }
371                 }
372                 return null;
373         }
374
375         private static ITypeBinding getReducedDimensionBinding(ITypeBinding arrayBinding, int dimsToReduce) {
376                 while (dimsToReduce > 0) {
377                         arrayBinding= arrayBinding.getComponentType();
378                         dimsToReduce--;
379                 }
380                 return arrayBinding;
381         }
382
383         private static ITypeBinding getParameterTypeBinding(ASTNode node, List<Expression> args, IMethodBinding binding) {
384                 ITypeBinding[] paramTypes= binding.getParameterTypes();
385                 int index= args.indexOf(node);
386                 if (binding.isVarargs() && index >= paramTypes.length - 1) {
387                         return paramTypes[paramTypes.length - 1].getComponentType();
388                 }
389                 if (index >= 0 && index < paramTypes.length) {
390                         return paramTypes[index];
391                 }
392                 return null;
393         }
394
395     public static ITypeBinding guessBindingForTypeReference(ASTNode node) {
396         StructuralPropertyDescriptor locationInParent= node.getLocationInParent();
397         if (locationInParent == QualifiedName.QUALIFIER_PROPERTY) {
398                 return null; // can't guess type for X.A
399         }
400         if (locationInParent == SimpleType.NAME_PROPERTY) {
401                 node= node.getParent();
402         }
403         ITypeBinding binding= Bindings.normalizeTypeBinding(getPossibleTypeBinding(node));
404         if (binding != null) {
405                 if (binding.isWildcardType()) {
406                         return normalizeWildcardType(binding, true, node.getAST());
407                 }
408         }
409         return binding;
410     }
411
412         private static ITypeBinding getPossibleTypeBinding(ASTNode node) {
413                 ASTNode parent= node.getParent();
414                 switch (parent.getNodeType()) {
415                         case ASTNode.ARRAY_TYPE: {
416                                 int dim= 1;
417                                 while (parent.getParent() instanceof ArrayType) {
418                                         parent= parent.getParent();
419                                         dim++;
420                                 }
421                                 ITypeBinding parentBinding= getPossibleTypeBinding(parent);
422                                 if (parentBinding != null && parentBinding.getDimensions() == dim) {
423                                         return parentBinding.getElementType();
424                                 }
425                                 return null;
426                         }
427                         case ASTNode.PARAMETERIZED_TYPE: {
428                                 ITypeBinding parentBinding= getPossibleTypeBinding(parent);
429                                 if (parentBinding == null || !parentBinding.isParameterizedType()) {
430                                         return null;
431                                 }
432                                 if (node.getLocationInParent() == ParameterizedType.TYPE_PROPERTY) {
433                                         return parentBinding;
434                                 }
435
436                                 ITypeBinding[] typeArguments= parentBinding.getTypeArguments();
437                                 List<Type> argumentNodes= ((ParameterizedType) parent).typeArguments();
438                                 int index= argumentNodes.indexOf(node);
439                                 if (index != -1 && typeArguments.length == argumentNodes.size()) {
440                                         return typeArguments[index];
441                                 }
442                                 return null;
443                         }
444                         case ASTNode.WILDCARD_TYPE: {
445                                 ITypeBinding parentBinding= getPossibleTypeBinding(parent);
446                                 if (parentBinding == null || !parentBinding.isWildcardType()) {
447                                         return null;
448                                 }
449                                 WildcardType wildcardType= (WildcardType) parent;
450                                 if (parentBinding.isUpperbound() == wildcardType.isUpperBound()) {
451                                         return parentBinding.getBound();
452                                 }
453                                 return null;
454                         }
455                         case ASTNode.QUALIFIED_TYPE: {
456                                 ITypeBinding parentBinding= getPossibleTypeBinding(parent);
457                                 if (parentBinding == null || !parentBinding.isMember()) {
458                                         return null;
459                                 }
460                                 if (node.getLocationInParent() == QualifiedType.QUALIFIER_PROPERTY) {
461                                         return parentBinding.getDeclaringClass();
462                                 }
463                                 return parentBinding;
464                         }
465                         case ASTNode.VARIABLE_DECLARATION_STATEMENT:
466                                 return guessVariableType(((VariableDeclarationStatement) parent).fragments());
467                         case ASTNode.FIELD_DECLARATION:
468                                 return guessVariableType(((FieldDeclaration) parent).fragments());
469                         case ASTNode.VARIABLE_DECLARATION_EXPRESSION:
470                                 return guessVariableType(((VariableDeclarationExpression) parent).fragments());
471                         case ASTNode.SINGLE_VARIABLE_DECLARATION:
472                                 SingleVariableDeclaration varDecl= (SingleVariableDeclaration) parent;
473                                 if (varDecl.getInitializer() != null) {
474                                         return Bindings.normalizeTypeBinding(varDecl.getInitializer().resolveTypeBinding());
475                                 }
476                                 break;
477                         case ASTNode.ARRAY_CREATION:
478                                 ArrayCreation creation= (ArrayCreation) parent;
479                                 if (creation.getInitializer() != null) {
480                                         return creation.getInitializer().resolveTypeBinding();
481                                 }
482                                 return getPossibleReferenceBinding(parent);
483                         case ASTNode.TYPE_LITERAL:
484                                 return ((TypeLiteral) parent).getType().resolveBinding();
485                         case ASTNode.CLASS_INSTANCE_CREATION:
486                                 return getPossibleReferenceBinding(parent);
487                         case ASTNode.CAST_EXPRESSION:
488                                 return getPossibleReferenceBinding(parent);
489                         case ASTNode.TAG_ELEMENT:
490                                 TagElement tagElement= (TagElement) parent;
491                                 if (TagElement.TAG_THROWS.equals(tagElement.getTagName()) || TagElement.TAG_EXCEPTION.equals(tagElement.getTagName())) {
492                                         ASTNode methNode= tagElement.getParent().getParent();
493                                         if (methNode instanceof MethodDeclaration) {
494                                                 List<Name> thrownExceptions= ((MethodDeclaration) methNode).thrownExceptions();
495                                                 if (thrownExceptions.size() == 1) {
496                                                         return thrownExceptions.get(0).resolveTypeBinding();
497                                                 }
498                                         }
499                                 }
500                                 break;
501                 }
502                 return null;
503         }
504
505         private static ITypeBinding guessVariableType(List<VariableDeclarationFragment> fragments) {
506                 for (Iterator<VariableDeclarationFragment> iter= fragments.iterator(); iter.hasNext();) {
507                         VariableDeclarationFragment frag= iter.next();
508                         if (frag.getInitializer() != null) {
509                                 return Bindings.normalizeTypeBinding(frag.getInitializer().resolveTypeBinding());
510                         }
511                 }
512                 return null;
513         }
514
515         /**
516          * Finds all type bindings that contain a method of a given signature
517          * @param searchRoot the ast node to start the search from
518          * @param selector the method name
519          * @param arguments the method arguments
520          * @param context the context in which the method would be called
521          * @return returns all types known in the AST that have a method with a given name
522          */
523         public static ITypeBinding[] getQualifierGuess(ASTNode searchRoot, final String selector, List<Expression> arguments, final IBinding context) {
524                 final int nArgs= arguments.size();
525                 final ArrayList<ITypeBinding> result= new ArrayList<ITypeBinding>();
526
527                 // test if selector is a object method
528                 ITypeBinding binding= searchRoot.getAST().resolveWellKnownType("java.lang.Object"); //$NON-NLS-1$
529                 IMethodBinding[] objectMethods= binding.getDeclaredMethods();
530                 for (int i= 0; i < objectMethods.length; i++) {
531                         IMethodBinding meth= objectMethods[i];
532                         if (meth.getName().equals(selector) && meth.getParameterTypes().length == nArgs) {
533                                 return new ITypeBinding[] { binding };
534                         }
535                 }
536
537                 visitAllBindings(searchRoot, new TypeBindingVisitor() {
538                         private HashSet<String> fVisitedBindings= new HashSet<String>(100);
539
540                         public boolean visit(ITypeBinding node) {
541                                 node= Bindings.normalizeTypeBinding(node);
542                                 if (node == null) {
543                                         return true;
544                                 }
545
546                                 if (!fVisitedBindings.add(node.getKey())) {
547                                         return true;
548                                 }
549                                 if (node.isGenericType()) {
550                                         return true; // only look at  parameterized types
551                                 }
552                                 if (context != null && !isUseableTypeInContext(node, context, false)) {
553                                         return true;
554                                 }
555
556                                 IMethodBinding[] methods= node.getDeclaredMethods();
557                                 for (int i= 0; i < methods.length; i++) {
558                                         IMethodBinding meth= methods[i];
559                                         if (meth.getName().equals(selector) && meth.getParameterTypes().length == nArgs) {
560                                                 result.add(node);
561                                         }
562                                 }
563                                 return true;
564                         }
565                 });
566                 return result.toArray(new ITypeBinding[result.size()]);
567         }
568
569         public static void visitAllBindings(ASTNode astRoot, TypeBindingVisitor visitor) {
570                 try {
571                         astRoot.accept(new AllBindingsVisitor(visitor));
572                 } catch (AllBindingsVisitor.VisitCancelledException e) {
573                 }
574         }
575
576         private static class AllBindingsVisitor extends GenericVisitor {
577                 private final TypeBindingVisitor fVisitor;
578
579                 private static class VisitCancelledException extends RuntimeException {
580                         private static final long serialVersionUID= 1L;
581                 }
582                 public AllBindingsVisitor(TypeBindingVisitor visitor) {
583                         super(true);
584                         fVisitor= visitor;
585                 }
586                 @Override
587                 public boolean visit(SimpleName node) {
588                         ITypeBinding binding= node.resolveTypeBinding();
589                         if (binding != null) {
590                                 boolean res= fVisitor.visit(binding);
591                                 if (res) {
592                                         res= Bindings.visitHierarchy(binding, fVisitor);
593                                 }
594                                 if (!res) {
595                                         throw new VisitCancelledException();
596                                 }
597                         }
598                         return false;
599                 }
600         }
601
602
603         public static IBinding getParentMethodOrTypeBinding(ASTNode node) {
604                 do {
605                         if (node instanceof MethodDeclaration) {
606                                 return ((MethodDeclaration) node).resolveBinding();
607                         } else if (node instanceof AbstractTypeDeclaration) {
608                                 return ((AbstractTypeDeclaration) node).resolveBinding();
609                         } else if (node instanceof AnonymousClassDeclaration) {
610                                 return ((AnonymousClassDeclaration) node).resolveBinding();
611                         }
612                         node= node.getParent();
613                 } while (node != null);
614
615                 return null;
616         }
617
618         public static BodyDeclaration findParentBodyDeclaration(ASTNode node) {
619                 while ((node != null) && (!(node instanceof BodyDeclaration))) {
620                         node= node.getParent();
621                 }
622                 return (BodyDeclaration) node;
623         }
624
625         public static BodyDeclaration findParentBodyDeclaration(ASTNode node, boolean treatModifiersOutside) {
626                 StructuralPropertyDescriptor lastLocation= null;
627
628                 while (node != null) {
629                         if (node instanceof BodyDeclaration) {
630                                 BodyDeclaration decl= (BodyDeclaration) node;
631                                 if (!treatModifiersOutside || lastLocation != decl.getModifiersProperty()) {
632                                         return decl;
633                                 }
634                                 treatModifiersOutside= false;
635                         }
636                         lastLocation= node.getLocationInParent();
637                         node= node.getParent();
638                 }
639                 return (BodyDeclaration) node;
640         }
641
642
643         public static CompilationUnit findParentCompilationUnit(ASTNode node) {
644                 return (CompilationUnit) findAncestor(node, ASTNode.COMPILATION_UNIT);
645         }
646
647         /**
648          * Finds the parent type of a node.
649          *
650          * @param node the node inside the type to find
651          * @param treatModifiersOutside if set, modifiers are not part of their type, but of the type's parent
652          * @return returns either a AbstractTypeDeclaration or an AnonymousTypeDeclaration
653          */
654         public static ASTNode findParentType(ASTNode node, boolean treatModifiersOutside) {
655                 StructuralPropertyDescriptor lastLocation= null;
656
657                 while (node != null) {
658                         if (node instanceof AbstractTypeDeclaration) {
659                                 AbstractTypeDeclaration decl= (AbstractTypeDeclaration) node;
660                                 if (!treatModifiersOutside || lastLocation != decl.getModifiersProperty()) {
661                                         return decl;
662                                 }
663                         } else if (node instanceof AnonymousClassDeclaration) {
664                                 return node;
665                         }
666                         lastLocation= node.getLocationInParent();
667                         node= node.getParent();
668                 }
669                 return null;
670         }
671
672         public static ASTNode findParentType(ASTNode node) {
673                 return findParentType(node, false);
674         }
675
676         /**
677          * Returns the method binding of the node's parent method declaration or <code>null</code> if
678          * the node is not inside a method.
679          * 
680          * @param node the ast node
681          * @return the method binding of the node's parent method declaration or <code>null</code> if
682          *         the node
683          */
684         public static MethodDeclaration findParentMethodDeclaration(ASTNode node) {
685                 while (node != null) {
686                         if (node.getNodeType() == ASTNode.METHOD_DECLARATION) {
687                                 return (MethodDeclaration) node;
688                         }
689                         if (node instanceof AbstractTypeDeclaration || node instanceof AnonymousClassDeclaration) {
690                                 return null;
691                         }
692                         node= node.getParent();
693                 }
694                 return null;
695         }
696
697         public static ASTNode findAncestor(ASTNode node, int nodeType) {
698                 while ((node != null) && (node.getNodeType() != nodeType)) {
699                         node= node.getParent();
700                 }
701                 return node;
702         }
703
704         public static Statement findParentStatement(ASTNode node) {
705                 while ((node != null) && (!(node instanceof Statement))) {
706                         node= node.getParent();
707                         if (node instanceof BodyDeclaration) {
708                                 return null;
709                         }
710                 }
711                 return (Statement) node;
712         }
713
714         public static TryStatement findParentTryStatement(ASTNode node) {
715                 while ((node != null) && (!(node instanceof TryStatement))) {
716                         node= node.getParent();
717                         if (node instanceof BodyDeclaration) {
718                                 return null;
719                         }
720                 }
721                 return (TryStatement) node;
722         }
723
724         public static boolean isInsideConstructorInvocation(MethodDeclaration methodDeclaration, ASTNode node) {
725                 if (methodDeclaration.isConstructor()) {
726                         Statement statement= ASTResolving.findParentStatement(node);
727                         if (statement instanceof ConstructorInvocation || statement instanceof SuperConstructorInvocation) {
728                                 return true; // argument in a this or super call
729                         }
730                 }
731                 return false;
732         }
733
734         public static boolean isInsideModifiers(ASTNode node) {
735                 while (node != null && !(node instanceof BodyDeclaration)) {
736                         if (node instanceof Annotation) {
737                                 return true;
738                         }
739                         node= node.getParent();
740                 }
741                 return false;
742         }
743
744         public static boolean isInStaticContext(ASTNode selectedNode) {
745                 BodyDeclaration decl= ASTResolving.findParentBodyDeclaration(selectedNode);
746                 if (decl instanceof MethodDeclaration) {
747                         if (isInsideConstructorInvocation((MethodDeclaration) decl, selectedNode)) {
748                                 return true;
749                         }
750                         return Modifier.isStatic(decl.getModifiers());
751                 } else if (decl instanceof Initializer) {
752                         return Modifier.isStatic(((Initializer)decl).getModifiers());
753                 } else if (decl instanceof FieldDeclaration) {
754                         return Modifier.isStatic(((FieldDeclaration)decl).getModifiers());
755                 }
756                 return false;
757         }
758
759         public static boolean isWriteAccess(Name selectedNode) {
760                 ASTNode curr= selectedNode;
761                 ASTNode parent= curr.getParent();
762                 while (parent != null) {
763                         switch (parent.getNodeType()) {
764                                 case ASTNode.QUALIFIED_NAME:
765                                         if (((QualifiedName) parent).getQualifier() == curr) {
766                                                 return false;
767                                         }
768                                         break;
769                                 case ASTNode.FIELD_ACCESS:
770                                         if (((FieldAccess) parent).getExpression() == curr) {
771                                                 return false;
772                                         }
773                                         break;
774                                 case ASTNode.SUPER_FIELD_ACCESS:
775                                         break;
776                                 case ASTNode.ASSIGNMENT:
777                                         return ((Assignment) parent).getLeftHandSide() == curr;
778                                 case ASTNode.VARIABLE_DECLARATION_FRAGMENT:
779                                 case ASTNode.SINGLE_VARIABLE_DECLARATION:
780                                         return ((VariableDeclaration) parent).getName() == curr;
781                                 case ASTNode.POSTFIX_EXPRESSION:
782                                         return true;
783                                 case ASTNode.PREFIX_EXPRESSION:
784                                         PrefixExpression.Operator op= ((PrefixExpression) parent).getOperator();
785                                         return op == PrefixExpression.Operator.DECREMENT || op == PrefixExpression.Operator.INCREMENT;
786                                 default:
787                                         return false;
788                         }
789
790                         curr= parent;
791                         parent= curr.getParent();
792                 }
793                 return false;
794         }
795
796         public static int getPossibleTypeKinds(ASTNode node, boolean is50OrHigher) {
797                 int kinds= internalGetPossibleTypeKinds(node);
798                 if (!is50OrHigher) {
799                         kinds &= (SimilarElementsRequestor.INTERFACES | SimilarElementsRequestor.CLASSES);
800                 }
801                 return kinds;
802         }
803
804
805         private static int internalGetPossibleTypeKinds(ASTNode node) {
806                 int kind= SimilarElementsRequestor.ALL_TYPES;
807
808                 int mask= SimilarElementsRequestor.ALL_TYPES | SimilarElementsRequestor.VOIDTYPE;
809
810                 ASTNode parent= node.getParent();
811                 while (parent instanceof QualifiedName) {
812                         if (node.getLocationInParent() == QualifiedName.QUALIFIER_PROPERTY) {
813                                 return SimilarElementsRequestor.REF_TYPES;
814                         }
815                         node= parent;
816                         parent= parent.getParent();
817                         mask= SimilarElementsRequestor.REF_TYPES;
818                 }
819                 while (parent instanceof Type) {
820                         if (parent instanceof QualifiedType) {
821                                 if (node.getLocationInParent() == QualifiedType.QUALIFIER_PROPERTY) {
822                                         return mask & (SimilarElementsRequestor.REF_TYPES);
823                                 }
824                                 mask&= SimilarElementsRequestor.REF_TYPES;
825                         } else if (parent instanceof ParameterizedType) {
826                                 if (node.getLocationInParent() == ParameterizedType.TYPE_ARGUMENTS_PROPERTY) {
827                                         return mask & SimilarElementsRequestor.REF_TYPES_AND_VAR;
828                                 }
829                                 mask&= SimilarElementsRequestor.CLASSES | SimilarElementsRequestor.INTERFACES;
830                         } else if (parent instanceof WildcardType) {
831                                 if (node.getLocationInParent() == WildcardType.BOUND_PROPERTY) {
832                                         return mask & SimilarElementsRequestor.REF_TYPES_AND_VAR;
833                                 }
834                         }
835                         node= parent;
836                         parent= parent.getParent();
837                 }
838
839                 switch (parent.getNodeType()) {
840                         case ASTNode.TYPE_DECLARATION:
841                                 if (node.getLocationInParent() == TypeDeclaration.SUPER_INTERFACE_TYPES_PROPERTY) {
842                                         kind= SimilarElementsRequestor.INTERFACES;
843                                 } else if (node.getLocationInParent() == TypeDeclaration.SUPERCLASS_TYPE_PROPERTY) {
844                                         kind= SimilarElementsRequestor.CLASSES;
845                                 }
846                                 break;
847                         case ASTNode.ENUM_DECLARATION:
848                                 kind= SimilarElementsRequestor.INTERFACES;
849                                 break;
850                         case ASTNode.METHOD_DECLARATION:
851                                 if (node.getLocationInParent() == MethodDeclaration.THROWN_EXCEPTIONS_PROPERTY) {
852                                         kind= SimilarElementsRequestor.CLASSES;
853                                 } else if (node.getLocationInParent() == MethodDeclaration.RETURN_TYPE2_PROPERTY) {
854                                         kind= SimilarElementsRequestor.ALL_TYPES | SimilarElementsRequestor.VOIDTYPE;
855                                 }
856                                 break;
857                         case ASTNode.ANNOTATION_TYPE_MEMBER_DECLARATION:
858                                 kind= SimilarElementsRequestor.PRIMITIVETYPES | SimilarElementsRequestor.ANNOTATIONS | SimilarElementsRequestor.ENUMS;
859                                 break;
860                         case ASTNode.INSTANCEOF_EXPRESSION:
861                                 kind= SimilarElementsRequestor.REF_TYPES;
862                                 break;
863                         case ASTNode.THROW_STATEMENT:
864                                 kind= SimilarElementsRequestor.CLASSES;
865                                 break;
866                         case ASTNode.CLASS_INSTANCE_CREATION:
867                                 if (((ClassInstanceCreation) parent).getAnonymousClassDeclaration() == null) {
868                                         kind= SimilarElementsRequestor.CLASSES;
869                                 } else {
870                                         kind= SimilarElementsRequestor.CLASSES | SimilarElementsRequestor.INTERFACES;
871                                 }
872                                 break;
873                         case ASTNode.SINGLE_VARIABLE_DECLARATION:
874                                 int superParent= parent.getParent().getNodeType();
875                                 if (superParent == ASTNode.CATCH_CLAUSE) {
876                                         kind= SimilarElementsRequestor.CLASSES;
877                                 }
878                                 break;
879                         case ASTNode.TAG_ELEMENT:
880                                 kind= SimilarElementsRequestor.REF_TYPES;
881                                 break;
882                         case ASTNode.MARKER_ANNOTATION:
883                         case ASTNode.SINGLE_MEMBER_ANNOTATION:
884                         case ASTNode.NORMAL_ANNOTATION:
885                                 kind= SimilarElementsRequestor.ANNOTATIONS;
886                                 break;
887                         case ASTNode.TYPE_PARAMETER:
888                                 if (((TypeParameter) parent).typeBounds().indexOf(node) > 0) {
889                                         kind= SimilarElementsRequestor.INTERFACES;
890                                 } else {
891                                         kind= SimilarElementsRequestor.REF_TYPES_AND_VAR;
892                                 }
893                                 break;
894                         case ASTNode.TYPE_LITERAL:
895                                 kind= SimilarElementsRequestor.REF_TYPES;
896                                 break;
897                         default:
898                 }
899                 return kind & mask;
900         }
901
902         public static String getFullName(Name name) {
903                 return name.getFullyQualifiedName();
904         }
905
906         public static ICompilationUnit findCompilationUnitForBinding(ICompilationUnit cu, CompilationUnit astRoot, ITypeBinding binding) throws JavaModelException {
907                 if (binding == null || !binding.isFromSource() || binding.isTypeVariable() || binding.isWildcardType()) {
908                         return null;
909                 }
910                 ASTNode node= astRoot.findDeclaringNode(binding.getTypeDeclaration());
911                 if (node == null) {
912                         ICompilationUnit targetCU= Bindings.findCompilationUnit(binding, cu.getJavaProject());
913                         if (targetCU != null) {
914                                 return targetCU;
915                         }
916                         return null;
917                 } else if (node instanceof AbstractTypeDeclaration || node instanceof AnonymousClassDeclaration) {
918                         return cu;
919                 }
920                 return null;
921         }
922
923
924         private static final Code[] CODE_ORDER= { PrimitiveType.CHAR, PrimitiveType.SHORT, PrimitiveType.INT, PrimitiveType.LONG, PrimitiveType.FLOAT, PrimitiveType.DOUBLE };
925
926         public static ITypeBinding[] getNarrowingTypes(AST ast, ITypeBinding type) {
927                 ArrayList<ITypeBinding> res= new ArrayList<ITypeBinding>();
928                 res.add(type);
929                 if (type.isPrimitive()) {
930                         Code code= PrimitiveType.toCode(type.getName());
931                         for (int i= 0; i < CODE_ORDER.length && code != CODE_ORDER[i]; i++) {
932                                 String typeName= CODE_ORDER[i].toString();
933                                 res.add(ast.resolveWellKnownType(typeName));
934                         }
935                 }
936                 return res.toArray(new ITypeBinding[res.size()]);
937         }
938
939         public static ITypeBinding[] getRelaxingTypes(AST ast, ITypeBinding type) {
940                 ArrayList<ITypeBinding> res= new ArrayList<ITypeBinding>();
941                 res.add(type);
942                 if (type.isArray()) {
943                         res.add(ast.resolveWellKnownType("java.lang.Object")); //$NON-NLS-1$
944                         // The following two types are not available in some j2me implementations, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=288060 :
945                         ITypeBinding serializable= ast.resolveWellKnownType("java.io.Serializable"); //$NON-NLS-1$
946                         if (serializable != null)
947                                 res.add(serializable);
948                         ITypeBinding cloneable= ast.resolveWellKnownType("java.lang.Cloneable"); //$NON-NLS-1$
949                         if (cloneable != null)
950                                 res.add(cloneable);
951                 } else if (type.isPrimitive()) {
952                         Code code= PrimitiveType.toCode(type.getName());
953                         boolean found= false;
954                         for (int i= 0; i < CODE_ORDER.length; i++) {
955                                 if (found) {
956                                         String typeName= CODE_ORDER[i].toString();
957                                         res.add(ast.resolveWellKnownType(typeName));
958                                 }
959                                 if (code == CODE_ORDER[i]) {
960                                         found= true;
961                                 }
962                         }
963                 } else {
964                         collectRelaxingTypes(res, type);
965                 }
966                 return res.toArray(new ITypeBinding[res.size()]);
967         }
968
969         private static void collectRelaxingTypes(Collection<ITypeBinding> res, ITypeBinding type) {
970                 ITypeBinding[] interfaces= type.getInterfaces();
971                 for (int i= 0; i < interfaces.length; i++) {
972                         ITypeBinding curr= interfaces[i];
973                         if (!res.contains(curr)) {
974                                 res.add(curr);
975                         }
976                         collectRelaxingTypes(res, curr);
977                 }
978                 ITypeBinding binding= type.getSuperclass();
979                 if (binding != null) {
980                         if (!res.contains(binding)) {
981                                 res.add(binding);
982                         }
983                         collectRelaxingTypes(res, binding);
984                 }
985         }
986
987         public static String[] getUsedVariableNames(ASTNode node) {
988                 CompilationUnit root= (CompilationUnit) node.getRoot();
989                 Collection<String> res= (new ScopeAnalyzer(root)).getUsedVariableNames(node.getStartPosition(), node.getLength());
990                 return res.toArray(new String[res.size()]);
991         }
992
993         private static boolean isVariableDefinedInContext(IBinding binding, ITypeBinding typeVariable) {
994                 if (binding.getKind() == IBinding.VARIABLE) {
995                         IVariableBinding var= (IVariableBinding) binding;
996                         binding= var.getDeclaringMethod();
997                         if (binding == null) {
998                                 binding= var.getDeclaringClass();
999                         }
1000                 }
1001                 if (binding instanceof IMethodBinding) {
1002                         if (binding == typeVariable.getDeclaringMethod()) {
1003                                 return true;
1004                         }
1005                         binding= ((IMethodBinding) binding).getDeclaringClass();
1006                 }
1007
1008                 while (binding instanceof ITypeBinding) {
1009                         if (binding == typeVariable.getDeclaringClass()) {
1010                                 return true;
1011                         }
1012                         if (Modifier.isStatic(binding.getModifiers())) {
1013                                 break;
1014                         }
1015                         binding= ((ITypeBinding) binding).getDeclaringClass();
1016                 }
1017                 return false;
1018         }
1019
1020         public static boolean isUseableTypeInContext(ITypeBinding[] binding, IBinding context, boolean noWildcards) {
1021                 for (int i= 0; i < binding.length; i++) {
1022                         if (!isUseableTypeInContext(binding[i], context, noWildcards)) {
1023                                 return false;
1024                         }
1025                 }
1026                 return true;
1027         }
1028
1029
1030         public static boolean isUseableTypeInContext(ITypeBinding type, IBinding context, boolean noWildcards) {
1031                 if (type.isArray()) {
1032                         type= type.getElementType();
1033                 }
1034                 if (type.isAnonymous()) {
1035                         return false;
1036                 }
1037                 if (type.isRawType() || type.isPrimitive()) {
1038                         return true;
1039                 }
1040                 if (type.isTypeVariable()) {
1041                         return isVariableDefinedInContext(context, type);
1042                 }
1043                 if (type.isGenericType()) {
1044                         ITypeBinding[] typeParameters= type.getTypeParameters();
1045                         for (int i= 0; i < typeParameters.length; i++) {
1046                                 if (!isUseableTypeInContext(typeParameters[i], context, noWildcards)) {
1047                                         return false;
1048                                 }
1049                         }
1050                         return true;
1051                 }
1052                 if (type.isParameterizedType()) {
1053                         ITypeBinding[] typeArguments= type.getTypeArguments();
1054                         for (int i= 0; i < typeArguments.length; i++) {
1055                                 if (!isUseableTypeInContext(typeArguments[i], context, noWildcards)) {
1056                                         return false;
1057                                 }
1058                         }
1059                         return true;
1060                 }
1061                 if (type.isCapture()) {
1062                         type= type.getWildcard();
1063                 }
1064
1065                 if (type.isWildcardType()) {
1066                         if (noWildcards) {
1067                                 return false;
1068                         }
1069                         if (type.getBound() != null) {
1070                                 return isUseableTypeInContext(type.getBound(), context, noWildcards);
1071                         }
1072                 }
1073                 return true;
1074         }
1075
1076         /**
1077          * Use this method before creating a type for a wildcard. Either to assign a wildcard to a new type or for a type to be assigned.
1078          *
1079          * @param wildcardType the wildcard type to normalize
1080          * @param isBindingToAssign If true, then a new receiver type is searched (X x= s), else the type of a sender (R r= x)
1081          * @param ast th current AST
1082          * @return Returns the normalized binding or null when only the 'null' binding
1083          */
1084         public static ITypeBinding normalizeWildcardType(ITypeBinding wildcardType, boolean isBindingToAssign, AST ast) {
1085                 ITypeBinding bound= wildcardType.getBound();
1086                 if (isBindingToAssign) {
1087                         if (bound == null || !wildcardType.isUpperbound()) {
1088                                 return ast.resolveWellKnownType("java.lang.Object"); //$NON-NLS-1$
1089                         }
1090                 } else {
1091                         if (bound == null || wildcardType.isUpperbound()) {
1092                                 return null;
1093                         }
1094                 }
1095                 return bound;
1096         }
1097
1098         // pretty signatures
1099
1100         public static String getTypeSignature(ITypeBinding type) {
1101                 return BindingLabelProvider.getBindingLabel(type, BindingLabelProvider.DEFAULT_TEXTFLAGS);
1102         }
1103
1104         public static String getMethodSignature(IMethodBinding binding) {
1105                 return BindingLabelProvider.getBindingLabel(binding, BindingLabelProvider.DEFAULT_TEXTFLAGS);
1106         }
1107
1108         public static String getMethodSignature(String name, ITypeBinding[] params, boolean isVarArgs) {
1109                 StringBuffer buf= new StringBuffer();
1110                 buf.append(name).append('(');
1111                 for (int i= 0; i < params.length; i++) {
1112                         if (i > 0) {
1113                                 buf.append(JavaElementLabels.COMMA_STRING);
1114                         }
1115                         if (isVarArgs && i == params.length - 1) {
1116                                 buf.append(getTypeSignature(params[i].getElementType()));
1117                                 buf.append("..."); //$NON-NLS-1$
1118                         } else {
1119                                 buf.append(getTypeSignature(params[i]));
1120                         }
1121                 }
1122                 buf.append(')');
1123                 return BasicElementLabels.getJavaElementName(buf.toString());
1124         }
1125
1126         public static CompilationUnit createQuickFixAST(ICompilationUnit compilationUnit, IProgressMonitor monitor) {
1127                 ASTParser astParser= ASTParser.newParser(ASTProvider.SHARED_AST_LEVEL);
1128                 astParser.setSource(compilationUnit);
1129                 astParser.setResolveBindings(true);
1130                 astParser.setStatementsRecovery(ASTProvider.SHARED_AST_STATEMENT_RECOVERY);
1131                 astParser.setBindingsRecovery(ASTProvider.SHARED_BINDING_RECOVERY);
1132                 return (CompilationUnit) astParser.createAST(monitor);
1133         }
1134
1135 }