]> git.uio.no Git - ifi-stolz-refaktor.git/blob - case-study/jdt-after/core refactoring/org/eclipse/jdt/internal/corext/refactoring/generics/InferTypeArgumentsConstraintsSolver.java
Case Study: adding data and statistics
[ifi-stolz-refaktor.git] / case-study / jdt-after / core refactoring / org / eclipse / jdt / internal / corext / refactoring / generics / InferTypeArgumentsConstraintsSolver.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.corext.refactoring.generics;
13
14
15 import java.util.ArrayList;
16 import java.util.Comparator;
17 import java.util.Iterator;
18 import java.util.LinkedHashMap;
19 import java.util.LinkedList;
20 import java.util.List;
21 import java.util.Map;
22
23 import org.eclipse.core.runtime.IProgressMonitor;
24 import org.eclipse.core.runtime.OperationCanceledException;
25 import org.eclipse.core.runtime.SubProgressMonitor;
26
27 import org.eclipse.jdt.core.JavaModelException;
28
29 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.HierarchyType;
30 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.TType;
31 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.SingletonTypeSet;
32 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet;
33 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.TypeSetEnvironment;
34 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ArrayElementVariable2;
35 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ArrayTypeVariable2;
36 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.CastVariable2;
37 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ConstraintVariable2;
38 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ITypeConstraint2;
39 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.IndependentTypeVariable2;
40 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.TypeEquivalenceSet;
41
42
43 public class InferTypeArgumentsConstraintsSolver {
44
45         public static class TTypeComparator implements Comparator<TType> {
46                 public int compare(TType o1, TType o2) {
47                         return o1.getPrettySignature().compareTo(o2.getPrettySignature());
48                 }
49                 public static TTypeComparator INSTANCE= new TTypeComparator();
50         }
51
52         private final static String CHOSEN_TYPE= "chosenType"; //$NON-NLS-1$
53
54         final InferTypeArgumentsTCModel fTCModel;
55         public TypeSetEnvironment fTypeSetEnvironment;
56
57         /**
58          * The work-list used by the type constraint solver to hold the set of
59          * nodes in the constraint graph that remain to be (re-)processed. Entries
60          * are <code>ConstraintVariable2</code>s.
61          */
62         public LinkedList<ConstraintVariable2> fWorkList;
63
64         public InferTypeArgumentsUpdate fUpdate;
65
66
67         public InferTypeArgumentsConstraintsSolver(InferTypeArgumentsTCModel typeConstraintFactory) {
68                 fTCModel= typeConstraintFactory;
69                 fWorkList= new LinkedList<ConstraintVariable2>();
70         }
71
72         public InferTypeArgumentsUpdate solveConstraints(IProgressMonitor pm) {
73                 pm.beginTask("", 2); //$NON-NLS-1$
74                 return fTCModel.generated_5627551663167226042(this, pm);
75         }
76
77         void initializeTypeEstimates(ConstraintVariable2[] allConstraintVariables) {
78                 for (int i= 0; i < allConstraintVariables.length; i++) {
79                         ConstraintVariable2 cv= allConstraintVariables[i];
80                         //TODO: not necessary for types that are not used in a TypeConstraint but only as type in CollectionElementVariable
81                         //TODO: handle nested element variables; see ParametricStructureComputer.createAndInitVars()
82                         TypeEquivalenceSet set= cv.getTypeEquivalenceSet();
83                         if (set == null) {
84                                 set= new TypeEquivalenceSet(cv);
85                                 set.generated_1744245873183469336(cv, this);
86                         } else {
87                                 TypeSet typeEstimate= (TypeSet) cv.getTypeEstimate();
88                                 if (typeEstimate == null) {
89                                         ConstraintVariable2[] cvs= set.getContributingVariables();
90                                         typeEstimate= fTypeSetEnvironment.getUniverseTypeSet();
91                                         for (int j= 0; j < cvs.length; j++) //TODO: optimize: just try to find an immutable CV; if not found, use Universe
92                                                 typeEstimate= typeEstimate.intersectedWith(createInitialEstimate(cvs[j]));
93                                         set.setTypeEstimate(typeEstimate);
94                                 }
95                         }
96                 }
97         }
98
99         public TypeSet createInitialEstimate(ConstraintVariable2 cv) {
100                 // TODO: check assumption: only immutable CVs have a type
101 //              ParametricStructure parametricStructure= fElemStructureEnv.elemStructure(cv);
102 //              if (parametricStructure != null && parametricStructure != ParametricStructureComputer.ParametricStructure.NONE) {
103 //                      return SubTypesOfSingleton.create(parametricStructure.getBase());
104 //              }
105
106                 TType type= cv.getType();
107                 if (type == null) {
108                         return fTypeSetEnvironment.getUniverseTypeSet();
109
110                 } else if (cv instanceof IndependentTypeVariable2) {
111                         return fTypeSetEnvironment.getUniverseTypeSet();
112                         //TODO: solve problem with recursive bounds
113 //                      TypeVariable tv= (TypeVariable) type;
114 //                      TType[] bounds= tv.getBounds();
115 //                      TypeSet result= SubTypesOfSingleton.create(bounds[0].getErasure());
116 //                      for (int i= 1; i < bounds.length; i++) {
117 //                              result= result.intersectedWith(SubTypesOfSingleton.create(bounds[i].getErasure()));
118 //                      }
119 //                      return result;
120
121                 } else if (cv instanceof ArrayTypeVariable2) {
122                         return fTypeSetEnvironment.getUniverseTypeSet();
123                 } else if (cv instanceof ArrayElementVariable2) {
124                         if (cv.getType() != null && cv.getType().isTypeVariable()) {
125                                 return fTypeSetEnvironment.getUniverseTypeSet();
126                         } else {
127                                 return new SingletonTypeSet(type, fTypeSetEnvironment);
128                         }
129
130                 } else
131                         return fTypeSetEnvironment.generated_2609078052071831070(type);
132         }
133
134         void runSolver(SubProgressMonitor pm) {
135                 pm.beginTask("", fWorkList.size() * 3); //$NON-NLS-1$
136                 while (! fWorkList.isEmpty()) {
137                         // Get a variable whose type estimate has changed
138                         ConstraintVariable2 cv= fWorkList.removeFirst();
139                         List<ITypeConstraint2> usedIn= fTCModel.getUsedIn(cv);
140                         processConstraints(usedIn);
141                         pm.worked(1);
142                         if (pm.isCanceled())
143                                 throw new OperationCanceledException();
144                 }
145                 pm.done();
146         }
147
148         /**
149          * Given a list of <code>ITypeConstraint2</code>s that all refer to a
150          * given <code>ConstraintVariable2</code> (whose type bound has presumably
151          * just changed), process each <code>ITypeConstraint</code>, propagating
152          * the type bound across the constraint as needed.
153          *
154          * @param usedIn the <code>List</code> of <code>ITypeConstraint2</code>s
155          * to process
156          */
157         private void processConstraints(List<ITypeConstraint2> usedIn) {
158                 Iterator<ITypeConstraint2> iter= usedIn.iterator();
159                 while (iter.hasNext()) {
160                         ITypeConstraint2 tc= iter.next();
161
162                                 maintainSimpleConstraint(tc);
163                                 //TODO: prune tcs which cannot cause further changes
164                                 // Maybe these should be pruned after a special first loop over all ConstraintVariables,
165                                 // Since this can only happen once for every CV in the work list.
166 //                              if (isConstantConstraint(stc))
167 //                                      fTypeConstraintFactory.removeUsedIn(stc, changedCv);
168                 }
169         }
170
171         private void maintainSimpleConstraint(ITypeConstraint2 stc) {
172                 ConstraintVariable2 left= stc.getLeft();
173                 ConstraintVariable2 right= stc.getRight();
174
175                 TypeEquivalenceSet leftSet= left.getTypeEquivalenceSet();
176                 leftSet.generated_8886690084417838134(right, this);
177         }
178
179         void chooseTypes(ConstraintVariable2[] allConstraintVariables, SubProgressMonitor pm) {
180                 pm.beginTask("", allConstraintVariables.length); //$NON-NLS-1$
181                 for (int i= 0; i < allConstraintVariables.length; i++) {
182                         ConstraintVariable2 cv= allConstraintVariables[i];
183
184                         TypeEquivalenceSet set= cv.getTypeEquivalenceSet();
185                         if (set == null)
186                                 continue; //TODO: should not happen iff all unused constraint variables got pruned
187                         //TODO: should calculate only once per EquivalenceRepresentative; can throw away estimate TypeSet afterwards
188                         TType type= cv.generated_2463815950094098277(pm, this);
189                 }
190                 pm.done();
191         }
192
193         public TType chooseSingleType(TypeSet typeEstimate) {
194                 return typeEstimate.generated_8224593875850740143(this);
195         }
196
197         private static final int MAX_CACHE= 1024;
198         public Map<TType, Boolean> fInterfaceTaggingCache= new LinkedHashMap<TType, Boolean>(MAX_CACHE, 0.75f, true) {
199                 private static final long serialVersionUID= 1L;
200                 @Override
201                 protected boolean removeEldestEntry(Map.Entry<TType, Boolean> eldest) {
202                         return size() > MAX_CACHE;
203                 }
204         };
205
206         public ArrayList<TType> getNonTaggingInterfaces(ArrayList<TType> interfaceCandidates) {
207                 ArrayList<TType> unresolvedTypes= new ArrayList<TType>();
208                 ArrayList<TType> nonTagging= new ArrayList<TType>();
209
210                 for (int i= 0; i < interfaceCandidates.size(); i++) {
211                         TType interf= interfaceCandidates.get(i);
212                         Object isTagging= fInterfaceTaggingCache.get(interf);
213                         if (isTagging == null)
214                                 unresolvedTypes.add(interf);
215                         else if (isTagging == Boolean.FALSE)
216                                 nonTagging.add(interf);
217                 }
218
219                 if (unresolvedTypes.size() != 0) {
220                         TType[] interfaces= unresolvedTypes.toArray(new TType[unresolvedTypes.size()]);
221                         for (int i= 0; i < interfaces.length; i++) {
222                                 TType interf= interfaces[i];
223                                 interf.generated_906562671490961319(nonTagging, this);
224                         }
225                 }
226
227                 return nonTagging;
228         }
229
230         public static boolean isTaggingInterface(TType interf) {
231                 if (interf instanceof HierarchyType) {
232                         try {
233                                 return ((HierarchyType) interf).getJavaElementType().getMethods().length == 0;
234                         } catch (JavaModelException e) {
235                                 // assume it's not
236                         }
237                 }
238                 return false;
239         }
240
241         void findCastsToRemove(CastVariable2[] castVariables) {
242                 fUpdate.generated_4229093701003042937(this, castVariables);
243         }
244
245         public static TType getChosenType(ConstraintVariable2 cv) {
246                 TType type= (TType) cv.getData(CHOSEN_TYPE);
247                 if (type != null)
248                         return type;
249                 TypeEquivalenceSet set= cv.getTypeEquivalenceSet();
250                 if (set == null) { //TODO: should not have to set this here. Clean up when caching chosen type
251                         return null;
252 //                      // no representative == no restriction
253 //                      set= new TypeEquivalenceSet(cv);
254 //                      set.setTypeEstimate(TypeUniverseSet.create());
255 //                      cv.setTypeEquivalenceSet(set);
256                 }
257                 return cv.getTypeEstimate().chooseSingleType();
258         }
259
260         public static void setChosenType(ConstraintVariable2 cv, TType type) {
261                 cv.setData(CHOSEN_TYPE, type);
262         }
263 }