KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > corext > refactoring > typeconstraints > FullConstraintCreator


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 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 package org.eclipse.jdt.internal.corext.refactoring.typeconstraints;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Arrays JavaDoc;
15 import java.util.Collection JavaDoc;
16 import java.util.HashSet JavaDoc;
17 import java.util.Iterator JavaDoc;
18 import java.util.LinkedHashSet JavaDoc;
19 import java.util.List JavaDoc;
20 import java.util.Set JavaDoc;
21
22 import org.eclipse.core.runtime.Assert;
23
24 import org.eclipse.jdt.core.dom.ArrayCreation;
25 import org.eclipse.jdt.core.dom.ArrayInitializer;
26 import org.eclipse.jdt.core.dom.Assignment;
27 import org.eclipse.jdt.core.dom.CastExpression;
28 import org.eclipse.jdt.core.dom.CatchClause;
29 import org.eclipse.jdt.core.dom.ClassInstanceCreation;
30 import org.eclipse.jdt.core.dom.ConditionalExpression;
31 import org.eclipse.jdt.core.dom.ConstructorInvocation;
32 import org.eclipse.jdt.core.dom.Expression;
33 import org.eclipse.jdt.core.dom.FieldAccess;
34 import org.eclipse.jdt.core.dom.FieldDeclaration;
35 import org.eclipse.jdt.core.dom.IBinding;
36 import org.eclipse.jdt.core.dom.IMethodBinding;
37 import org.eclipse.jdt.core.dom.ITypeBinding;
38 import org.eclipse.jdt.core.dom.IVariableBinding;
39 import org.eclipse.jdt.core.dom.InstanceofExpression;
40 import org.eclipse.jdt.core.dom.MethodDeclaration;
41 import org.eclipse.jdt.core.dom.MethodInvocation;
42 import org.eclipse.jdt.core.dom.Name;
43 import org.eclipse.jdt.core.dom.ParenthesizedExpression;
44 import org.eclipse.jdt.core.dom.QualifiedName;
45 import org.eclipse.jdt.core.dom.ReturnStatement;
46 import org.eclipse.jdt.core.dom.SimpleName;
47 import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
48 import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
49 import org.eclipse.jdt.core.dom.SuperFieldAccess;
50 import org.eclipse.jdt.core.dom.SuperMethodInvocation;
51 import org.eclipse.jdt.core.dom.ThisExpression;
52 import org.eclipse.jdt.core.dom.Type;
53 import org.eclipse.jdt.core.dom.VariableDeclaration;
54 import org.eclipse.jdt.core.dom.VariableDeclarationExpression;
55 import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
56 import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
57
58 import org.eclipse.jdt.internal.corext.dom.ASTNodes;
59 import org.eclipse.jdt.internal.corext.dom.Bindings;
60 import org.eclipse.jdt.internal.corext.refactoring.rename.MethodChecks;
61
62 /**
63  * Default implementation of the creator. Creates all or nearly all constraints for program constructs.
64  * Subclasses can provide additional checks to avoid creating constraints that are not useful for their purposes.
65  */

66 public class FullConstraintCreator extends ConstraintCreator{
67
68     private final IConstraintVariableFactory fConstraintVariableFactory;
69     private final ITypeConstraintFactory fTypeConstraintFactory;
70     private IContext fContext;
71
72     public FullConstraintCreator(){
73         this(new ConstraintVariableFactory(), new TypeConstraintFactory());
74     }
75     
76     public FullConstraintCreator(IConstraintVariableFactory cFactory,
77                                  ITypeConstraintFactory tFactory) {
78         Assert.isTrue(cFactory != null);
79         fConstraintVariableFactory= cFactory;
80         fTypeConstraintFactory= tFactory;
81         fContext= new NullContext();
82     }
83
84     public IContext getContext() {
85         return fContext;
86     }
87     
88     public void setContext(IContext context) {
89         fContext= context;
90     }
91     
92     public ITypeConstraintFactory getConstraintFactory(){
93         return fTypeConstraintFactory;
94     }
95     
96     public IConstraintVariableFactory getConstraintVariableFactory(){
97         return fConstraintVariableFactory;
98     }
99     
100     /* (non-Javadoc)
101      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ArrayInitializer)
102      */

103     public ITypeConstraint[] create(ArrayInitializer arrayInitializer){
104         ITypeBinding arrayBinding= arrayInitializer.resolveTypeBinding();
105         Assert.isTrue(arrayBinding.isArray());
106         List JavaDoc expressions= arrayInitializer.expressions();
107         List JavaDoc/*<ITypeConstraint>*/ constraints= new ArrayList JavaDoc();
108         Type type= getTypeParent(arrayInitializer);
109         ConstraintVariable typeVariable= fConstraintVariableFactory.makeTypeVariable(type);
110         for (int i= 0; i < expressions.size(); i++) {
111             Expression each= (Expression) expressions.get(i);
112             ITypeConstraint[] c= fTypeConstraintFactory.createSubtypeConstraint(
113                     fConstraintVariableFactory.makeExpressionOrTypeVariable(each, getContext()),
114                     typeVariable);
115             constraints.addAll(Arrays.asList(c));
116         }
117         return (ITypeConstraint[])constraints.toArray(new ITypeConstraint[constraints.size()]);
118     }
119
120     /* (non-Javadoc)
121      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.Assignment)
122      */

123     public ITypeConstraint[] create(Assignment assignment){
124         return fTypeConstraintFactory.createSubtypeConstraint(
125                 fConstraintVariableFactory.makeExpressionOrTypeVariable(assignment.getRightHandSide(), getContext()),
126                 fConstraintVariableFactory.makeExpressionOrTypeVariable(assignment.getLeftHandSide(), getContext()));
127     }
128
129     /* (non-Javadoc)
130      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.CastExpression)
131      */

132     public ITypeConstraint[] create(CastExpression castExpression){
133         Expression expression= castExpression.getExpression();
134         Type type= castExpression.getType();
135         ITypeConstraint[] definesConstraint= fTypeConstraintFactory.createDefinesConstraint(fConstraintVariableFactory.makeExpressionOrTypeVariable(castExpression, getContext()),
136                                                                                         fConstraintVariableFactory.makeTypeVariable(castExpression.getType()));
137         if (isClassBinding(expression.resolveTypeBinding()) && isClassBinding(type.resolveBinding())){
138             ConstraintVariable expressionVariable= fConstraintVariableFactory.makeExpressionOrTypeVariable(expression, getContext());
139             ConstraintVariable castExpressionVariable= fConstraintVariableFactory.makeExpressionOrTypeVariable(castExpression, getContext());
140             ITypeConstraint[] c2 = createOrOrSubtypeConstraint(expressionVariable, castExpressionVariable);
141             if (definesConstraint.length == 0){
142                 return c2;
143             } else {
144                 ITypeConstraint c1 = definesConstraint[0];
145                 Collection JavaDoc/*<ITypeConstraint>*/ constraints= new ArrayList JavaDoc();
146                 constraints.add(c1);
147                 constraints.addAll(Arrays.asList(c2));
148                 return (ITypeConstraint[])constraints.toArray(new ITypeConstraint[constraints.size()]);
149             }
150         } else
151             return definesConstraint;
152     }
153     
154     public ITypeConstraint[] create(CatchClause node) {
155         SingleVariableDeclaration exception= node.getException();
156         ConstraintVariable nameVariable= fConstraintVariableFactory.makeExpressionOrTypeVariable(exception.getName(), getContext());
157         
158         ITypeConstraint[] defines= fTypeConstraintFactory.createDefinesConstraint(
159                 nameVariable,
160                 fConstraintVariableFactory.makeTypeVariable(exception.getType()));
161         
162         ITypeBinding throwable= node.getAST().resolveWellKnownType("java.lang.Throwable"); //$NON-NLS-1$
163
ITypeConstraint[] catchBound= fTypeConstraintFactory.createSubtypeConstraint(
164                 nameVariable,
165                 fConstraintVariableFactory.makeRawBindingVariable(throwable));
166         
167         ArrayList JavaDoc result= new ArrayList JavaDoc();
168         result.addAll(Arrays.asList(defines));
169         result.addAll(Arrays.asList(catchBound));
170         return (ITypeConstraint[]) result.toArray(new ITypeConstraint[result.size()]);
171     }
172
173
174     /* (non-Javadoc)
175      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ClassInstanceCreation)
176      */

177     public ITypeConstraint[] create(ClassInstanceCreation instanceCreation){
178         List JavaDoc arguments= instanceCreation.arguments();
179         List JavaDoc result= new ArrayList JavaDoc(arguments.size());
180         IMethodBinding methodBinding= instanceCreation.resolveConstructorBinding();
181         result.addAll(Arrays.asList(getArgumentConstraints(arguments, methodBinding)));
182         if (instanceCreation.getAnonymousClassDeclaration() == null){
183             ConstraintVariable constructorVar= fConstraintVariableFactory.makeExpressionOrTypeVariable(instanceCreation, getContext());
184             ConstraintVariable typeVar= fConstraintVariableFactory.makeRawBindingVariable(instanceCreation.resolveTypeBinding());
185             result.addAll(Arrays.asList(fTypeConstraintFactory.createDefinesConstraint(constructorVar, typeVar)));
186         }
187         return (ITypeConstraint[]) result.toArray(new ITypeConstraint[result.size()]);
188     }
189
190     /* (non-Javadoc)
191      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ConstructorInvocation)
192      */

193     public ITypeConstraint[] create(ConstructorInvocation invocation){
194         List JavaDoc arguments= invocation.arguments();
195         List JavaDoc result= new ArrayList JavaDoc(arguments.size());
196         IMethodBinding methodBinding= invocation.resolveConstructorBinding();
197         result.addAll(Arrays.asList(getArgumentConstraints(arguments, methodBinding)));
198         return (ITypeConstraint[]) result.toArray(new ITypeConstraint[result.size()]);
199     }
200
201     /* (non-Javadoc)
202      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.FieldAccess)
203      */

204     public ITypeConstraint[] create(FieldAccess access){
205         Expression expression= access.getExpression();
206         SimpleName name= access.getName();
207         IBinding binding= name.resolveBinding();
208         if (! (binding instanceof IVariableBinding))
209             return new ITypeConstraint[0];
210         IVariableBinding vb= (IVariableBinding)binding;
211         return createConstraintsForAccessToField(vb, expression, access);
212     }
213
214     /* (non-Javadoc)
215      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.FieldDeclaration)
216      */

217     public ITypeConstraint[] create(FieldDeclaration fd){
218         List JavaDoc result= new ArrayList JavaDoc();
219         result.addAll(Arrays.asList(getConstraintsFromFragmentList(fd.fragments(), fd.getType())));
220         result.addAll(getConstraintsForHiding(fd));
221         result.addAll(getConstraintsForFieldDeclaringTypes(fd));
222         return (ITypeConstraint[]) result.toArray(new ITypeConstraint[result.size()]);
223     }
224
225     /* (non-Javadoc)
226      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.InstanceofExpression)
227      */

228     public ITypeConstraint[] create(InstanceofExpression instanceofExpression){
229         Expression expression= instanceofExpression.getLeftOperand();
230         Type type= instanceofExpression.getRightOperand();
231         if (isClassBinding(expression.resolveTypeBinding()) && isClassBinding(type.resolveBinding())) {
232             ConstraintVariable expressionVar= fConstraintVariableFactory.makeExpressionOrTypeVariable(expression, getContext());
233             ConstraintVariable typeVariable= fConstraintVariableFactory.makeTypeVariable(type);
234             return createOrOrSubtypeConstraint(expressionVar, typeVariable);
235         } else
236             return new ITypeConstraint[0];
237     }
238
239     /* (non-Javadoc)
240      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ConditionalExpression)
241      */

242     public ITypeConstraint[] create(ConditionalExpression node) {
243         List JavaDoc result= new ArrayList JavaDoc();
244         Expression thenExpression= node.getThenExpression();
245         Expression elseExpression= node.getElseExpression();
246         ConstraintVariable whole= fConstraintVariableFactory.makeExpressionOrTypeVariable(node, getContext());
247         ConstraintVariable ev1= fConstraintVariableFactory.makeExpressionOrTypeVariable(thenExpression, getContext());
248         ConstraintVariable ev2= fConstraintVariableFactory.makeExpressionOrTypeVariable(elseExpression, getContext());
249         ITypeConstraint[] constraints1= fTypeConstraintFactory.createEqualsConstraint(ev1, ev2);
250         ITypeConstraint[] constraints2= fTypeConstraintFactory.createSubtypeConstraint(ev1, whole);
251         ITypeConstraint[] constraints3= fTypeConstraintFactory.createSubtypeConstraint(ev2, whole);
252         result.addAll(Arrays.asList(constraints1));
253         result.addAll(Arrays.asList(constraints2));
254         result.addAll(Arrays.asList(constraints3));
255         return (ITypeConstraint[])result.toArray(new ITypeConstraint[result.size()]);
256     }
257     
258     /* (non-Javadoc)
259      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MethodDeclaration)
260      */

261     public ITypeConstraint[] create(MethodDeclaration declaration){
262         List JavaDoc result= new ArrayList JavaDoc();
263         IMethodBinding methodBinding= declaration.resolveBinding();
264         if (methodBinding == null)
265             return new ITypeConstraint[0];
266         ITypeConstraint[] constraints = fTypeConstraintFactory.createDefinesConstraint(
267                 fConstraintVariableFactory.makeDeclaringTypeVariable(methodBinding),
268                 fConstraintVariableFactory.makeRawBindingVariable(methodBinding.getDeclaringClass()));
269         result.addAll(Arrays.asList(constraints));
270         if (! methodBinding.isConstructor() && ! methodBinding.getReturnType().isPrimitive()){
271             ConstraintVariable returnTypeBindingVariable= fConstraintVariableFactory.makeReturnTypeVariable(methodBinding);
272             ConstraintVariable returnTypeVariable= fConstraintVariableFactory.makeTypeVariable(declaration.getReturnType2());
273             ITypeConstraint[] defines= fTypeConstraintFactory.createDefinesConstraint(
274                     returnTypeBindingVariable, returnTypeVariable);
275             result.addAll(Arrays.asList(defines));
276         }
277         for (int i= 0, n= declaration.parameters().size(); i < n; i++) {
278             SingleVariableDeclaration paramDecl= (SingleVariableDeclaration)declaration.parameters().get(i);
279             ConstraintVariable parameterTypeVariable= fConstraintVariableFactory.makeParameterTypeVariable(methodBinding, i);
280             ConstraintVariable parameterNameVariable= fConstraintVariableFactory.makeExpressionOrTypeVariable(paramDecl.getName(), getContext());
281             ITypeConstraint[] constraint= fTypeConstraintFactory.createDefinesConstraint(
282                     parameterTypeVariable, parameterNameVariable);
283             result.addAll(Arrays.asList(constraint));
284         }
285         if (MethodChecks.isVirtual(methodBinding)){
286             Collection JavaDoc constraintsForOverriding = getConstraintsForOverriding(methodBinding);
287             result.addAll(constraintsForOverriding);
288         }
289         return (ITypeConstraint[]) result.toArray(new ITypeConstraint[result.size()]);
290     }
291
292     /* (non-Javadoc)
293      * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ConstraintCreator#create(org.eclipse.jdt.core.dom.ParenthesizedExpression)
294      */

295     public ITypeConstraint[] create(ParenthesizedExpression node) {
296         ConstraintVariable v1= fConstraintVariableFactory.makeExpressionOrTypeVariable(node, getContext());
297         ConstraintVariable v2= fConstraintVariableFactory.makeExpressionOrTypeVariable(node.getExpression(), getContext());
298         ITypeConstraint[] equal= fTypeConstraintFactory.createEqualsConstraint(v1, v2);
299         return equal;
300     }
301
302     /* (non-Javadoc)
303      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MethodInvocation)
304      */

305     public ITypeConstraint[] create(MethodInvocation invocation){
306         List JavaDoc arguments= invocation.arguments();
307         List JavaDoc result= new ArrayList JavaDoc(arguments.size());
308         IMethodBinding methodBinding= invocation.resolveMethodBinding();
309         if (methodBinding == null)
310             return new ITypeConstraint[0];
311         ITypeConstraint[] returnTypeConstraint= getReturnTypeConstraint(invocation, methodBinding);
312         result.addAll(Arrays.asList(returnTypeConstraint));
313         result.addAll(Arrays.asList(getArgumentConstraints(arguments, methodBinding)));
314         if (invocation.getExpression() != null){
315             if(MethodChecks.isVirtual(methodBinding)){
316                 IMethodBinding[] rootDefs= getRootDefs(methodBinding);
317                 Assert.isTrue(rootDefs.length > 0);
318                 ConstraintVariable expressionVar= fConstraintVariableFactory.makeExpressionOrTypeVariable(invocation.getExpression(), getContext());
319                 if (rootDefs.length == 1){
320                     result.addAll(Arrays.asList(fTypeConstraintFactory.createSubtypeConstraint(expressionVar, fConstraintVariableFactory.makeDeclaringTypeVariable(rootDefs[0]))));
321                 }else{
322                     Collection JavaDoc/*<ITypeConstraint>*/ constraints= new ArrayList JavaDoc();
323                     for (int i= 0; i < rootDefs.length; i++) {
324                         ConstraintVariable rootDefTypeVar= fConstraintVariableFactory.makeDeclaringTypeVariable(rootDefs[i]);
325                         ITypeConstraint[] tc= fTypeConstraintFactory.createSubtypeConstraint(expressionVar, rootDefTypeVar);
326                         constraints.addAll(Arrays.asList(tc));
327                     }
328                     ITypeConstraint[] constraintsArray= (ITypeConstraint[])constraints.toArray(new ITypeConstraint[constraints.size()]);
329                     if (constraintsArray.length > 0){
330                         result.add(fTypeConstraintFactory.createCompositeOrTypeConstraint(constraintsArray));
331                     }
332                 }
333             } else {
334                 ConstraintVariable typeVar= fConstraintVariableFactory.makeDeclaringTypeVariable(methodBinding);
335                 ConstraintVariable expressionVar= fConstraintVariableFactory.makeExpressionOrTypeVariable(invocation.getExpression(), getContext());
336                 result.addAll(Arrays.asList(fTypeConstraintFactory.createSubtypeConstraint(expressionVar, typeVar)));
337             }
338         }
339         return (ITypeConstraint[]) result.toArray(new ITypeConstraint[result.size()]);
340     }
341
342     /* (non-Javadoc)
343      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.QualifiedName)
344      */

345     public ITypeConstraint[] create(QualifiedName qualifiedName){
346         SimpleName name= qualifiedName.getName();
347         Name qualifier= qualifiedName.getQualifier();
348         IBinding nameBinding= name.resolveBinding();
349         if (nameBinding instanceof IVariableBinding){
350             IVariableBinding vb= (IVariableBinding)nameBinding;
351             if (vb.isField())
352                 return createConstraintsForAccessToField(vb, qualifier, qualifiedName);
353         } //TODO other bindings
354
return new ITypeConstraint[0];
355     }
356
357     /* (non-Javadoc)
358      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ReturnStatement)
359      */

360     public ITypeConstraint[] create(ReturnStatement returnStatement){
361         if (returnStatement.getExpression() == null)
362             return new ITypeConstraint[0];
363         
364         ConstraintVariable returnTypeVariable= fConstraintVariableFactory.makeReturnTypeVariable(returnStatement);
365         return fTypeConstraintFactory.createSubtypeConstraint(
366                 fConstraintVariableFactory.makeExpressionOrTypeVariable(returnStatement.getExpression(), getContext()),
367                 returnTypeVariable);
368     }
369     
370     /* (non-Javadoc)
371      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.SingleVariableDeclaration)
372      */

373     public ITypeConstraint[] create(SingleVariableDeclaration svd){
374         ITypeConstraint[] defines= fTypeConstraintFactory.createDefinesConstraint(
375                 fConstraintVariableFactory.makeExpressionOrTypeVariable(svd.getName(), getContext()),
376                 fConstraintVariableFactory.makeTypeVariable(svd.getType()));
377         if (svd.getInitializer() == null)
378             return defines;
379         ITypeConstraint[] constraints = fTypeConstraintFactory.createSubtypeConstraint(
380                 fConstraintVariableFactory.makeExpressionOrTypeVariable(svd.getInitializer(), getContext()),
381                 fConstraintVariableFactory.makeExpressionOrTypeVariable(svd.getName(), getContext()));
382         if (defines.length == 0 && constraints.length == 0){
383             return new ITypeConstraint[0];
384         } else if (defines.length == 0){
385             return constraints;
386         } else if (constraints.length == 0){
387             return defines;
388         } else {
389             List JavaDoc all= new ArrayList JavaDoc();
390             all.addAll(Arrays.asList(defines));
391             all.addAll(Arrays.asList(constraints));
392             return (ITypeConstraint[])all.toArray();
393         }
394     }
395
396     /* (non-Javadoc)
397      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.SuperConstructorInvocation)
398      */

399     public ITypeConstraint[] create(SuperConstructorInvocation invocation){
400         List JavaDoc arguments= invocation.arguments();
401         List JavaDoc result= new ArrayList JavaDoc(arguments.size());
402         IMethodBinding methodBinding= invocation.resolveConstructorBinding();
403         result.addAll(Arrays.asList(getArgumentConstraints(arguments, methodBinding)));
404         return (ITypeConstraint[]) result.toArray(new ITypeConstraint[result.size()]);
405     }
406     
407     /* (non-Javadoc)
408      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.SuperFieldAccess)
409      */

410     public ITypeConstraint[] create(SuperFieldAccess access){
411         SimpleName name= access.getName();
412         IBinding binding= name.resolveBinding();
413         if (! (binding instanceof IVariableBinding))
414             return new ITypeConstraint[0];
415         IVariableBinding vb= (IVariableBinding)binding;
416         return createConstraintsForAccessToField(vb, null, access);
417     }
418         
419     /* (non-Javadoc)
420      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.SuperMethodInvocation)
421      */

422     public ITypeConstraint[] create(SuperMethodInvocation invocation){
423         List JavaDoc arguments= invocation.arguments();
424         List JavaDoc result= new ArrayList JavaDoc(arguments.size());
425         IMethodBinding methodBinding= invocation.resolveMethodBinding();
426         ITypeConstraint[] returnTypeConstraint= getReturnTypeConstraint(invocation, methodBinding);
427         result.addAll(Arrays.asList(returnTypeConstraint));
428         result.addAll(Arrays.asList(getArgumentConstraints(arguments, methodBinding)));
429         return (ITypeConstraint[]) result.toArray(new ITypeConstraint[result.size()]);
430     }
431
432     /* (non-Javadoc)
433      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ThisExpression)
434      */

435     public ITypeConstraint[] create(ThisExpression expression){
436         ConstraintVariable thisExpression= fConstraintVariableFactory.makeExpressionOrTypeVariable(expression, getContext());
437         ConstraintVariable declaringType= fConstraintVariableFactory.makeRawBindingVariable(expression.resolveTypeBinding());//TODO fix this - can't use Decl(M) because 'this' can live outside of methods
438
return fTypeConstraintFactory.createDefinesConstraint(thisExpression, declaringType);
439     }
440     
441     /* (non-Javadoc)
442      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.VariableDeclarationExpression)
443      */

444     public ITypeConstraint[] create(VariableDeclarationExpression vde){
445         return getConstraintsFromFragmentList(vde.fragments(), vde.getType());
446     }
447
448     /* (non-Javadoc)
449      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.VariableDeclarationFragment)
450      */

451     public ITypeConstraint[] create(VariableDeclarationFragment vdf){
452         if (vdf.getInitializer() == null)
453             return new ITypeConstraint[0];
454         return fTypeConstraintFactory.createSubtypeConstraint(
455                 fConstraintVariableFactory.makeExpressionOrTypeVariable(vdf.getInitializer(), getContext()),
456                 fConstraintVariableFactory.makeExpressionOrTypeVariable(vdf.getName(), getContext()));
457     }
458
459     /* (non-Javadoc)
460      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.VariableDeclarationStatement)
461      */

462     public ITypeConstraint[] create(VariableDeclarationStatement vds){
463         return getConstraintsFromFragmentList(vds.fragments(), vds.getType());
464     }
465
466
467     //--------- private helpers ----------------//
468

469     private Collection JavaDoc getConstraintsForFieldDeclaringTypes(FieldDeclaration fd) {
470         Collection JavaDoc result= new ArrayList JavaDoc(fd.fragments().size());
471         for (Iterator JavaDoc iter= fd.fragments().iterator(); iter.hasNext();) {
472             VariableDeclarationFragment varDecl= (VariableDeclarationFragment) iter.next();
473             IVariableBinding binding= varDecl.resolveBinding();
474             Assert.isTrue(binding.isField());
475             result.addAll(Arrays.asList(fTypeConstraintFactory.createDefinesConstraint(
476                     fConstraintVariableFactory.makeDeclaringTypeVariable(binding),
477                     fConstraintVariableFactory.makeRawBindingVariable(binding.getDeclaringClass()))));
478         }
479         return result;
480     }
481     
482     private Collection JavaDoc getConstraintsForHiding(FieldDeclaration fd) {
483         Collection JavaDoc result= new ArrayList JavaDoc();
484         for (Iterator JavaDoc iter= fd.fragments().iterator(); iter.hasNext();) {
485             result.addAll(getConstraintsForHiding((VariableDeclarationFragment) iter.next()));
486         }
487         return result;
488     }
489     
490     private Collection JavaDoc getConstraintsForHiding(VariableDeclarationFragment fragment) {
491         Collection JavaDoc result= new ArrayList JavaDoc();
492         IVariableBinding fieldBinding= fragment.resolveBinding();
493         Assert.isTrue(fieldBinding.isField());
494         Set JavaDoc declaringTypes= getDeclaringSuperTypes(fieldBinding);
495         ConstraintVariable hiddingFieldVar= fConstraintVariableFactory.makeDeclaringTypeVariable(fieldBinding);
496         for (Iterator JavaDoc iter= declaringTypes.iterator(); iter.hasNext();) {
497             ITypeBinding declaringSuperType= (ITypeBinding) iter.next();
498             IVariableBinding hiddenField= findField(fieldBinding, declaringSuperType);
499             Assert.isTrue(hiddenField.isField());
500             ConstraintVariable hiddenFieldVar= fConstraintVariableFactory.makeDeclaringTypeVariable(hiddenField);
501             result.addAll(Arrays.asList(fTypeConstraintFactory.createStrictSubtypeConstraint(hiddingFieldVar, hiddenFieldVar)));
502         }
503         return result;
504     }
505     
506     private ITypeConstraint[] getConstraintsFromFragmentList(List JavaDoc fragments, Type type) {
507         int size= fragments.size();
508         ConstraintVariable typeVariable= fConstraintVariableFactory.makeTypeVariable(type);
509         List JavaDoc result= new ArrayList JavaDoc((size * (size - 1))/2);
510         for (int i= 0; i < size; i++) {
511             VariableDeclarationFragment fragment1= (VariableDeclarationFragment) fragments.get(i);
512             SimpleName fragment1Name= fragment1.getName();
513             result.addAll(Arrays.asList(fTypeConstraintFactory.createDefinesConstraint(
514                     fConstraintVariableFactory.makeExpressionOrTypeVariable(fragment1Name, getContext()),
515                     typeVariable)));
516             for (int j= i + 1; j < size; j++) {
517                 VariableDeclarationFragment fragment2= (VariableDeclarationFragment) fragments.get(j);
518                 result.addAll(Arrays.asList(fTypeConstraintFactory.createEqualsConstraint(
519                         fConstraintVariableFactory.makeExpressionOrTypeVariable(fragment1Name, getContext()),
520                         fConstraintVariableFactory.makeExpressionOrTypeVariable(fragment2.getName(), getContext()))));
521             }
522         }
523         return (ITypeConstraint[]) result.toArray(new ITypeConstraint[result.size()]);
524     }
525     
526     private Collection JavaDoc getConstraintsForOverriding(IMethodBinding overriddingMethod) {
527         Collection JavaDoc result= new ArrayList JavaDoc();
528         Set JavaDoc declaringSupertypes= getDeclaringSuperTypes(overriddingMethod);
529         for (Iterator JavaDoc iter= declaringSupertypes.iterator(); iter.hasNext();) {
530             ITypeBinding superType= (ITypeBinding) iter.next();
531             IMethodBinding overriddenMethod= findMethod(overriddingMethod, superType);
532             Assert.isNotNull(overriddenMethod);//because we asked for declaring types
533
if (Bindings.equals(overriddingMethod, overriddenMethod)) continue;
534             ITypeConstraint[] returnTypeConstraint= fTypeConstraintFactory.createEqualsConstraint(
535                     fConstraintVariableFactory.makeReturnTypeVariable(overriddenMethod),
536                     fConstraintVariableFactory.makeReturnTypeVariable(overriddingMethod));
537             result.addAll(Arrays.asList(returnTypeConstraint));
538             Assert.isTrue(overriddenMethod.getParameterTypes().length == overriddingMethod.getParameterTypes().length);
539             for (int i= 0, n= overriddenMethod.getParameterTypes().length; i < n; i++) {
540                 ITypeConstraint[] parameterTypeConstraint= fTypeConstraintFactory.createEqualsConstraint(
541                         fConstraintVariableFactory.makeParameterTypeVariable(overriddenMethod, i),
542                         fConstraintVariableFactory.makeParameterTypeVariable(overriddingMethod, i));
543                 result.addAll(Arrays.asList(parameterTypeConstraint));
544             }
545             ITypeConstraint[] declaringTypeConstraint= fTypeConstraintFactory.createStrictSubtypeConstraint(
546                     fConstraintVariableFactory.makeDeclaringTypeVariable(overriddingMethod),
547                     fConstraintVariableFactory.makeDeclaringTypeVariable(overriddenMethod));
548             result.addAll(Arrays.asList(declaringTypeConstraint));
549         }
550         return result;
551     }
552     
553     private ITypeConstraint[] getReturnTypeConstraint(Expression invocation, IMethodBinding methodBinding){
554         if (methodBinding == null || methodBinding.isConstructor() || methodBinding.getReturnType().isPrimitive())
555             return new ITypeConstraint[0];
556         ConstraintVariable returnTypeVariable= fConstraintVariableFactory.makeReturnTypeVariable(methodBinding);
557         ConstraintVariable invocationVariable= fConstraintVariableFactory.makeExpressionOrTypeVariable(invocation, getContext());
558         return fTypeConstraintFactory.createDefinesConstraint(invocationVariable, returnTypeVariable);
559     }
560     
561     private ITypeConstraint[] getArgumentConstraints(List JavaDoc arguments, IMethodBinding methodBinding){
562         List JavaDoc result= new ArrayList JavaDoc(arguments.size());
563         for (int i= 0, n= arguments.size(); i < n; i++) {
564             Expression argument= (Expression) arguments.get(i);
565             ConstraintVariable expressionVariable= fConstraintVariableFactory.makeExpressionOrTypeVariable(argument, getContext());
566             ConstraintVariable parameterTypeVariable= fConstraintVariableFactory.makeParameterTypeVariable(methodBinding, i);
567             ITypeConstraint[] argConstraint= fTypeConstraintFactory.createSubtypeConstraint(expressionVariable, parameterTypeVariable);
568             result.addAll(Arrays.asList(argConstraint));
569         }
570         return (ITypeConstraint[]) result.toArray(new ITypeConstraint[result.size()]);
571     }
572     
573     private static Type getTypeParent(ArrayInitializer arrayInitializer) {
574         if (arrayInitializer.getParent() instanceof ArrayCreation){
575             return ((ArrayCreation)arrayInitializer.getParent()).getType().getElementType();
576         } else if (arrayInitializer.getParent() instanceof ArrayInitializer){
577             return getTypeParent((ArrayInitializer) arrayInitializer.getParent());
578         } else if (arrayInitializer.getParent() instanceof VariableDeclaration){
579             VariableDeclaration parent= (VariableDeclaration)arrayInitializer.getParent();
580             
581             if (parent.getParent() instanceof VariableDeclarationStatement){
582                 Type type= ((VariableDeclarationStatement)parent.getParent()).getType();
583                 return ASTNodes.getElementType(type);
584             } else if (parent.getParent() instanceof VariableDeclarationExpression){
585                 Type type= ((VariableDeclarationExpression)parent.getParent()).getType();
586                 return ASTNodes.getElementType(type);
587             } else if (parent.getParent() instanceof FieldDeclaration){
588                 Type type= ((FieldDeclaration)parent.getParent()).getType();
589                 return ASTNodes.getElementType(type);
590             }
591         }
592         Assert.isTrue(false);//array initializers are allowed in only 2 places
593
return null;
594     }
595     
596     private ITypeConstraint[] createOrOrSubtypeConstraint(ConstraintVariable var1, ConstraintVariable var2){
597         ITypeConstraint[] c1= fTypeConstraintFactory.createSubtypeConstraint(var1, var2);
598         ITypeConstraint[] c2= fTypeConstraintFactory.createSubtypeConstraint(var2, var1);
599         if (c1.length == 0 && c2.length == 0){
600             return new ITypeConstraint[0];
601         }
602         return new ITypeConstraint[]{ fTypeConstraintFactory.createCompositeOrTypeConstraint(new ITypeConstraint[]{c1[0], c2[0]}) };
603     }
604     
605     private ITypeConstraint[] createConstraintsForAccessToField(IVariableBinding fieldBinding, Expression qualifier, Expression accessExpression){
606         Assert.isTrue(fieldBinding.isField());
607         ITypeConstraint[] defines= fTypeConstraintFactory.createDefinesConstraint(
608                 fConstraintVariableFactory.makeExpressionOrTypeVariable(accessExpression, getContext()),
609                 fConstraintVariableFactory.makeRawBindingVariable(fieldBinding.getType()));
610         if (qualifier == null)
611             return defines;
612         ITypeConstraint[] subType= fTypeConstraintFactory.createSubtypeConstraint(
613                 fConstraintVariableFactory.makeExpressionOrTypeVariable(qualifier, getContext()),
614                 fConstraintVariableFactory.makeDeclaringTypeVariable(fieldBinding));
615         
616         if (defines.length == 0){
617             return subType;
618         } else if (subType.length == 0){
619             return defines;
620         } else {
621             return new ITypeConstraint[]{defines[0], subType[0]};
622         }
623     }
624     
625     private static IVariableBinding findField(IVariableBinding fieldBinding, ITypeBinding type) {
626         if (fieldBinding.getDeclaringClass().equals(type))
627             return fieldBinding;
628         return Bindings.findFieldInType(type, fieldBinding.getName());
629     }
630     
631     /*
632      * return Set of ITypeBindings
633      */

634     private static Set JavaDoc getDeclaringSuperTypes(IVariableBinding fieldBinding) {
635         ITypeBinding[] allSuperTypes= Bindings.getAllSuperTypes(fieldBinding.getDeclaringClass());
636         Set JavaDoc result= new HashSet JavaDoc();
637         for (int i= 0; i < allSuperTypes.length; i++) {
638             ITypeBinding type= allSuperTypes[i];
639             if (findField(fieldBinding, type) != null)
640                 result.add(type);
641         }
642         return result;
643     }
644     
645     //--- RootDef ----//
646
protected static IMethodBinding[] getRootDefs(IMethodBinding methodBinding) {
647         Set JavaDoc/*<ITypeBinding>*/ declaringSuperTypes= getDeclaringSuperTypes(methodBinding);
648         Set JavaDoc/*<IMethodBinding>*/ result= new LinkedHashSet JavaDoc();
649         for (Iterator JavaDoc iter= declaringSuperTypes.iterator(); iter.hasNext();) {
650             ITypeBinding type= (ITypeBinding) iter.next();
651             if (! containsASuperType(type, declaringSuperTypes))
652                 result.add(findMethod(methodBinding, type));
653         }
654         
655         if (result.size() == 0){
656             result.add(methodBinding);
657         }
658         return (IMethodBinding[]) result.toArray(new IMethodBinding[result.size()]);
659     }
660     
661     /*
662      * @param declaringSuperTypes Set of ITypeBindings
663      * @return <code>true</code> iff <code>declaringSuperTypes</code> contains a type
664      * which is a strict supertype of <code>type</code>
665      */

666     private static boolean containsASuperType(ITypeBinding type, Set JavaDoc declaringSuperTypes) {
667         for (Iterator JavaDoc iter= declaringSuperTypes.iterator(); iter.hasNext();) {
668             ITypeBinding maybeSuperType= (ITypeBinding) iter.next();
669             if (! Bindings.equals(maybeSuperType, type) && Bindings.isSuperType(maybeSuperType, type))
670                 return true;
671         }
672         return false;
673     }
674     
675     /*
676      * return Set of ITypeBindings
677      */

678     protected static Set JavaDoc getDeclaringSuperTypes(IMethodBinding methodBinding) {
679         ITypeBinding superClass = methodBinding.getDeclaringClass();
680         Set JavaDoc allSuperTypes= new LinkedHashSet JavaDoc();
681         allSuperTypes.addAll(Arrays.asList(Bindings.getAllSuperTypes(superClass)));
682         if (allSuperTypes.isEmpty())
683             allSuperTypes.add(methodBinding.getDeclaringClass()); //TODO: Why only iff empty? The declaring class is not a supertype ...
684
Set JavaDoc result= new HashSet JavaDoc();
685         for (Iterator JavaDoc iter= allSuperTypes.iterator(); iter.hasNext();) {
686             ITypeBinding type= (ITypeBinding) iter.next();
687             if (findMethod(methodBinding, type) != null)
688                 result.add(type);
689         }
690         return result;
691     }
692     
693     protected static IMethodBinding findMethod(IMethodBinding methodBinding, ITypeBinding type) {
694         if (methodBinding.getDeclaringClass().equals(type))
695             return methodBinding;
696         return Bindings.findOverriddenMethodInType(type, methodBinding);
697     }
698
699     private static boolean isClassBinding(ITypeBinding typeBinding){
700         return typeBinding != null && typeBinding.isClass();
701     }
702     
703 }
704
Popular Tags