KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > corext > refactoring > structure > constraints > SuperTypeConstraintsSolver


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.structure.constraints;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Arrays JavaDoc;
15 import java.util.Collection JavaDoc;
16 import java.util.HashMap JavaDoc;
17 import java.util.Iterator JavaDoc;
18 import java.util.LinkedList JavaDoc;
19 import java.util.Map JavaDoc;
20
21 import org.eclipse.core.runtime.Assert;
22
23 import org.eclipse.jdt.core.ICompilationUnit;
24
25 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.TType;
26 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.CastVariable2;
27 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ConstraintVariable2;
28 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ITypeConstraint2;
29 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ITypeConstraintVariable;
30 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ITypeSet;
31 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ImmutableTypeVariable2;
32 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.TypeEquivalenceSet;
33
34 /**
35  * Type constraint solver to solve supertype constraint models.
36  *
37  * @since 3.1
38  */

39 public class SuperTypeConstraintsSolver {
40
41     /** The type estimate data (type: <code>TType</code>) */
42     public static final String JavaDoc DATA_TYPE_ESTIMATE= "te"; //$NON-NLS-1$
43

44     /** The type constraint model to solve */
45     protected final SuperTypeConstraintsModel fModel;
46
47     /** The obsolete casts (element type: <code>&ltICompilationUnit, Collection&ltCastVariable2&gt&gt</code>) */
48     protected Map JavaDoc fObsoleteCasts= null;
49
50     /** The list of constraint variables to be processed */
51     protected LinkedList JavaDoc fProcessable= null;
52
53     /** The type occurrences (element type: <code>&ltICompilationUnit, Collection&ltIDeclaredConstraintVariable&gt</code>) */
54     protected Map JavaDoc fTypeOccurrences= null;
55
56     /**
57      * Creates a new super type constraints solver.
58      *
59      * @param model the model to solve
60      */

61     public SuperTypeConstraintsSolver(final SuperTypeConstraintsModel model) {
62         Assert.isNotNull(model);
63
64         fModel= model;
65     }
66
67     /**
68      * Computes the necessary equality constraints for conditional expressions.
69      *
70      * @param constraints the type constraints (element type: <code>ITypeConstraint2</code>)
71      * @param level the compliance level
72      */

73     private void computeConditionalTypeConstraints(final Collection JavaDoc constraints, final int level) {
74         ITypeConstraint2 constraint= null;
75         for (final Iterator JavaDoc iterator= constraints.iterator(); iterator.hasNext();) {
76             constraint= (ITypeConstraint2) iterator.next();
77             if (constraint instanceof ConditionalTypeConstraint) {
78                 final ConditionalTypeConstraint conditional= (ConditionalTypeConstraint) constraint;
79                 fModel.createEqualityConstraint(constraint.getLeft(), constraint.getRight());
80                 fModel.createEqualityConstraint(conditional.getExpression(), constraint.getLeft());
81                 fModel.createEqualityConstraint(conditional.getExpression(), constraint.getRight());
82             }
83         }
84     }
85
86     /**
87      * Computes the necessary equality constraints for non-covariant return types.
88      *
89      * @param constraints the type constraints (element type: <code>ITypeConstraint2</code>)
90      * @param level the compliance level
91      */

92     private void computeNonCovariantConstraints(final Collection JavaDoc constraints, final int level) {
93         if (level != 3) {
94             ITypeConstraint2 constraint= null;
95             for (final Iterator JavaDoc iterator= constraints.iterator(); iterator.hasNext();) {
96                 constraint= (ITypeConstraint2) iterator.next();
97                 if (constraint instanceof CovariantTypeConstraint)
98                     fModel.createEqualityConstraint(constraint.getLeft(), constraint.getRight());
99             }
100         }
101     }
102
103     /**
104      * Computes the obsolete casts for the specified cast variables.
105      *
106      * @param variables the cast variables (element type: <code>CastVariable2</code>)
107      */

108     private void computeObsoleteCasts(final Collection JavaDoc variables) {
109         fObsoleteCasts= new HashMap JavaDoc();
110         CastVariable2 variable= null;
111         for (final Iterator JavaDoc iterator= variables.iterator(); iterator.hasNext();) {
112             variable= (CastVariable2) iterator.next();
113             final TType type= (TType) variable.getExpressionVariable().getData(DATA_TYPE_ESTIMATE);
114             if (type != null && type.canAssignTo(variable.getType())) {
115                 final ICompilationUnit unit= variable.getCompilationUnit();
116                 Collection JavaDoc casts= (Collection JavaDoc) fObsoleteCasts.get(unit);
117                 if (casts != null)
118                     casts.add(variable);
119                 else {
120                     casts= new ArrayList JavaDoc(1);
121                     casts.add(variable);
122                     fObsoleteCasts.put(unit, casts);
123                 }
124             }
125         }
126     }
127
128     /**
129      * Computes the initial type estimate for the specified constraint variable.
130      *
131      * @param variable the constraint variable
132      * @return the initial type estimate
133      */

134     protected ITypeSet computeTypeEstimate(final ConstraintVariable2 variable) {
135         final TType type= variable.getType();
136         if (variable instanceof ImmutableTypeVariable2 || !type.getErasure().equals(fModel.getSubType().getErasure()))
137             return SuperTypeSet.createTypeSet(type);
138         return SuperTypeSet.createTypeSet(type, fModel.getSuperType());
139     }
140
141     /**
142      * Computes the initial type estimates for the specified variables.
143      *
144      * @param variables the constraint variables (element type: <code>ConstraintVariable2</code>)
145      */

146     private void computeTypeEstimates(final Collection JavaDoc variables) {
147         ConstraintVariable2 variable= null;
148         for (final Iterator JavaDoc iterator= variables.iterator(); iterator.hasNext();) {
149             variable= (ConstraintVariable2) iterator.next();
150             TypeEquivalenceSet set= variable.getTypeEquivalenceSet();
151             if (set == null) {
152                 set= new TypeEquivalenceSet(variable);
153                 set.setTypeEstimate(computeTypeEstimate(variable));
154                 variable.setTypeEquivalenceSet(set);
155             } else {
156                 ITypeSet estimate= variable.getTypeEstimate();
157                 if (estimate == null) {
158                     final ConstraintVariable2[] contributing= set.getContributingVariables();
159                     estimate= SuperTypeSet.getUniverse();
160                     for (int index= 0; index < contributing.length; index++)
161                         estimate= estimate.restrictedTo(computeTypeEstimate(contributing[index]));
162                     set.setTypeEstimate(estimate);
163                 }
164             }
165         }
166     }
167
168     /**
169      * Computes a single type for each of the specified constraint variables.
170      *
171      * @param variables the constraint variables (element type: <code>ConstraintVariable2</code>)
172      */

173     private void computeTypeOccurrences(final Collection JavaDoc variables) {
174         fTypeOccurrences= new HashMap JavaDoc();
175         final TType superErasure= fModel.getSuperType().getErasure();
176         TType estimatedType= null;
177         ITypeSet set= null;
178         ICompilationUnit unit= null;
179         ConstraintVariable2 variable= null;
180         ITypeConstraintVariable declaration= null;
181         TType variableType= null;
182         for (final Iterator JavaDoc iterator= variables.iterator(); iterator.hasNext();) {
183             variable= (ConstraintVariable2) iterator.next();
184             if (variable instanceof ITypeConstraintVariable) {
185                 declaration= (ITypeConstraintVariable) variable;
186                 variableType= variable.getType();
187                 set= declaration.getTypeEstimate();
188                 if (set != null) {
189                     estimatedType= set.chooseSingleType();
190                     if (estimatedType != null) {
191                         final TType typeErasure= estimatedType.getErasure();
192                         if (!typeErasure.equals(variableType.getErasure()) && typeErasure.equals(superErasure)) {
193                             declaration.setData(DATA_TYPE_ESTIMATE, estimatedType);
194                             unit= declaration.getCompilationUnit();
195                             if (unit != null) {
196                                 Collection JavaDoc matches= (Collection JavaDoc) fTypeOccurrences.get(unit);
197                                 if (matches != null)
198                                     matches.add(declaration);
199                                 else {
200                                     matches= new ArrayList JavaDoc(1);
201                                     matches.add(declaration);
202                                     fTypeOccurrences.put(unit, matches);
203                                 }
204                             }
205                         }
206                     }
207                 }
208             }
209         }
210     }
211
212     /**
213      * Returns the computed obsolete casts.
214      *
215      * @return the obsolete casts (element type: <code>&ltICompilationUnit, Collection&ltCastVariable2&gt&gt</code>)
216      */

217     public final Map JavaDoc getObsoleteCasts() {
218         return fObsoleteCasts;
219     }
220
221     /**
222      * Returns the computed type occurrences.
223      *
224      * @return the type occurrences (element type: <code>&ltICompilationUnit, Collection&ltIDeclaredConstraintVariable&gt</code>)
225      */

226     public final Map JavaDoc getTypeOccurrences() {
227         return fTypeOccurrences;
228     }
229
230     /**
231      * Processes the given constraints on the constraint variable and propagates it.
232      *
233      * @param constraints the type constraints to process (element type: <code>ITypeConstraint2</code>)
234      */

235     private void processConstraints(final Collection JavaDoc constraints) {
236         final int level= fModel.getCompliance();
237         ITypeConstraint2 constraint= null;
238         for (final Iterator JavaDoc iterator= constraints.iterator(); iterator.hasNext();) {
239             constraint= (ITypeConstraint2) iterator.next();
240             if ((level == 3 || !(constraint instanceof CovariantTypeConstraint)) && !(constraint instanceof ConditionalTypeConstraint)) {
241                 final ConstraintVariable2 leftVariable= constraint.getLeft();
242                 final ITypeSet leftEstimate= leftVariable.getTypeEstimate();
243                 final TypeEquivalenceSet set= leftVariable.getTypeEquivalenceSet();
244                 final ITypeSet newEstimate= leftEstimate.restrictedTo(constraint.getRight().getTypeEstimate());
245                 if (leftEstimate != newEstimate) {
246                     set.setTypeEstimate(newEstimate);
247                     fProcessable.addAll(Arrays.asList(set.getContributingVariables()));
248                 }
249             }
250         }
251     }
252
253     /**
254      * Solves the constraints of the associated model.
255      */

256     public final void solveConstraints() {
257         fProcessable= new LinkedList JavaDoc();
258         final Collection JavaDoc variables= fModel.getConstraintVariables();
259         final Collection JavaDoc constraints= fModel.getTypeConstraints();
260         final int level= fModel.getCompliance();
261         computeNonCovariantConstraints(constraints, level);
262
263         // TODO: use most specific common type for AST.JLS3
264
computeConditionalTypeConstraints(constraints, level);
265
266         computeTypeEstimates(variables);
267         fProcessable.addAll(variables);
268         Collection JavaDoc usage= null;
269         ConstraintVariable2 variable= null;
270         while (!fProcessable.isEmpty()) {
271             variable= (ConstraintVariable2) fProcessable.removeFirst();
272             usage= SuperTypeConstraintsModel.getVariableUsage(variable);
273             if (!usage.isEmpty())
274                 processConstraints(usage);
275             else
276                 variable.setData(DATA_TYPE_ESTIMATE, variable.getTypeEstimate().chooseSingleType());
277         }
278         computeTypeOccurrences(variables);
279         computeObsoleteCasts(fModel.getCastVariables());
280     }
281 }
282
Popular Tags