]> git.uio.no Git - ifi-stolz-refaktor.git/blob - case-study/refaktor-after/src/no/uio/ifi/refaktor/prefix/Prefix.java
Case Study: adding data and statistics
[ifi-stolz-refaktor.git] / case-study / refaktor-after / src / no / uio / ifi / refaktor / prefix / Prefix.java
1 package no.uio.ifi.refaktor.prefix;
2
3 import java.util.Collections;
4 import java.util.Comparator;
5 import java.util.LinkedList;
6 import java.util.List;
7
8 import no.uio.ifi.refaktor.analyze.collectors.LongestCommonPrefixCollector;
9 import no.uio.ifi.refaktor.utils.ParseUtils;
10
11 import org.eclipse.jdt.core.dom.ASTMatcher;
12 import org.eclipse.jdt.core.dom.ASTNode;
13 import org.eclipse.jdt.core.dom.ASTVisitor;
14 import org.eclipse.jdt.core.dom.Expression;
15 import org.eclipse.jdt.core.dom.IBinding;
16 import org.eclipse.jdt.core.dom.IVariableBinding;
17 import org.eclipse.jdt.core.dom.Name;
18
19 /**
20  * A class for representing a prefix of an Expression/Statement.
21  * 
22  * It has an Expression member for the prefix.
23  */
24 public class Prefix {
25
26         private class SubExpressionsFinder extends ASTVisitor {
27
28                 private int topExpressionStartPosition;
29                 private final LinkedList<Expression> expressions;
30
31                 public SubExpressionsFinder(Expression expression) {
32                         topExpressionStartPosition = expression.getStartPosition();
33                         this.expressions = new LinkedList<Expression>();
34                         if (expression != null)
35                                 expression.accept(this);
36                 }
37
38                 public List<Expression> getExpressions() {
39                         return expressions;
40                 }
41
42                 @Override
43                 public void preVisit(ASTNode node) {
44                         if (nodeIsSubExpressionOfTopExpression(node))
45                                 expressions.add((Expression) node);
46                 }
47
48                 private boolean nodeIsSubExpressionOfTopExpression(ASTNode node) {
49                         return node instanceof Expression && node.getStartPosition() == topExpressionStartPosition;
50                 }
51         }
52
53         private final Expression prefixExpression;
54         private int count;
55         private PrefixSet subPrefixes;
56
57         private final Object lazyToString = new Object() {
58                 private String string;
59
60                 @Override
61                 public String toString() {
62                         if (string == null)
63                                 string = ParseUtils.getNodeText(prefixExpression); 
64                         return string;
65                 }
66         };
67
68         /**
69          * Represent a prefix on the base of an Expression.
70          * 
71          * @param expression the Expression that is the base of the prefix.
72          */
73         public Prefix(Expression expression) {
74                 assert expression != null;
75                 this.prefixExpression = expression;
76                 this.count = 1;
77         }
78
79         public int getCount() {
80                 return count;
81         }
82
83         public void incrementCount() {
84                 count++;
85         }
86
87         @Override
88         public String toString() {
89                 return lazyToString.toString();
90         }
91
92         /**
93          * Intersect this prefix with another prefix.
94          * 
95          * @param other the prefix to intersect with this one.
96          * @return If other is equal to this, a copy of this will be returned,
97          *              or else the longest common prefix of other and this is returned.
98          */
99         public Prefix intersectWith(Prefix other) {
100                 return other.generated_2853864130712417478(this);
101         }
102
103         private Expression longestCommonExpressionWith(Prefix other) {
104                 Expression longestCommonExpression = null;
105
106                 for (Expression thisExp: getSubExpressions(prefixExpression)) {
107                         longestCommonExpression = other.generated_4200363536186052423(this,
108                                         longestCommonExpression, thisExp);
109                 }
110                 return longestCommonExpression;
111         }
112
113         private List<Expression> getSubExpressions(Expression expression) {
114                 return new SubExpressionsFinder(expression).getExpressions();
115         }
116
117         @Override
118         public int hashCode() {
119                 /*
120                  Proven to be effective.
121                  Adding information about prefixExpression.resolveTypeBinding().getKey().hashCode()
122                  made things slightly worse.
123                 
124                  More than 20 times more effective than (the cached version of)
125                  toString().hashCode() when analyzing org.eclipse.jdt.ui.
126                  */
127                 return prefixExpression.getLength();
128         }
129
130         @Override
131         public boolean equals(Object other) {
132                 if (this == other)
133                         return true;
134                 if (other == null || !(other instanceof Prefix))
135                         return false;
136                 Prefix otherPrefix = (Prefix) other;
137                 return otherPrefix.generated_436244330295722658(this);
138         }
139
140         private boolean hasExpressionMatching(Prefix other) {
141                 return other.generated_7899053605141751224(this);
142         }
143
144         private boolean hasVariableBindingEqualTo(Prefix other) {
145                 return getVariableBindingOfFirstExpression().isEqualTo(other.getVariableBindingOfFirstExpression());
146         }
147
148         private boolean expressionsMatch(Expression a, Expression b) {
149                 return a.subtreeMatch(new ASTMatcher(), b);
150         }
151
152         public int length() {
153                 return prefixExpression.getLength();
154         }
155
156         public IVariableBinding getVariableBindingOfFirstExpression() {
157                 IBinding binding = resolveBindingOfFirstExpression();
158                 assert binding instanceof IVariableBinding;
159                 return (IVariableBinding) binding;
160         }
161
162         private IBinding resolveBindingOfFirstExpression() {
163                 Expression firstExpression = getFirstExpression();
164                 assert firstExpression instanceof Name;
165                 return ((Name) firstExpression).resolveBinding();
166         }
167
168         private Expression getFirstExpression() {
169                 List<Expression> subExpressions = getSubExpressions(prefixExpression);
170                 Collections.sort(subExpressions, new Comparator<Expression>() {
171                         @Override
172                         public int compare(Expression e1, Expression e2) {
173                                 if (e1.getLength() < e2.getLength())
174                                         return -1;
175                                 else if (e1.getLength() > e2.getLength())
176                                         return 1;
177                                 else
178                                         return 0;
179                         }
180                 });
181                 return subExpressions.get(0);
182         }
183
184         /**
185          * Tests if this prefix has the other prefix as its sub-prefix.
186          * 
187          * Example: "a.b" is sub-prefix of "a.b.c", as is "a.b.c".
188          * 
189          * @param other The prefix to test.
190          * @return true if other is prefix of this prefix, else false.
191          */
192         public boolean hasSubPrefix(Prefix other) {
193                 return getSubPrefixes().contains(other);
194         }
195
196         /**
197          * @return the list of possible sub-prefixes, including a copy of this one.
198          */
199         public PrefixSet getSubPrefixes() {
200                 if (subPrefixes == null) {
201                         subPrefixes = new PrefixSet();
202                         for (Expression exp: getSubExpressions(prefixExpression))
203                                 subPrefixes.add(new Prefix(exp));
204                 }
205                 return subPrefixes;
206         }
207
208         public boolean firstExpressionIsBoundToVariable() {
209                 return resolveBindingOfFirstExpression() instanceof IVariableBinding;
210         }
211
212         public int getNumberOfSegments() {
213                 return getSubPrefixes().size();
214         }
215
216         public boolean generated_825955664987272076() {
217                 return getNumberOfSegments() == 1 && getCount() == 1;
218         }
219
220         public int generated_3478548225149205143(Prefix p1) {
221                 if (p1.getCount() > getCount()) {
222                         return 1;
223                 } else if (p1.getCount() < getCount()) {
224                         return -1;
225                 } else if (p1.length() > length()) {
226                         return 1;
227                 } else if (p1.length() < length()) {
228                         return -1;
229                 }
230                 return 0;
231         }
232
233         public void generated_7609478919728457568(LongestCommonPrefixCollector longestcommonprefixcollector) {
234                 if (longestcommonprefixcollector.longestCommonPrefix == null) {
235                         longestcommonprefixcollector.longestCommonPrefix = this;
236                 } else {
237                         longestcommonprefixcollector.longestCommonPrefix = longestcommonprefixcollector.longestCommonPrefix.intersectWith(this);
238                 }
239         }
240
241         public void generated_7681675865424797515(PrefixSet prefixset) {
242                 if (!prefixset.contains(this))
243                         prefixset.prefixes.put(this, this);
244         }
245
246         public void generated_1397335264344119528(PrefixSet prefixset) {
247                 assert prefixset.get(this) != null : this;
248         }
249
250         public void generated_57330167832506990(PrefixSet prefixset) {
251                 Prefix prefixFromMap = prefixset.get(this);
252                 if (prefixFromMap != null) {
253                         prefixFromMap.incrementCount();
254                 } else {
255                         prefixset.add(this);
256                 }
257         }
258
259         public String generated_797445745298232673(String str) {
260                 str += toString() + " (" + getCount() + ")\n";
261                 return str;
262         }
263
264         public void generated_9031955363082597180(PrefixSet prefixSet, Prefix p) {
265                 if (hasSubPrefix(p))
266                         prefixSet.remove(this);
267         }
268
269         public Prefix generated_2853864130712417478(Prefix prefix) {
270                 if (prefix.equals(this))
271                         return new Prefix(prefix.prefixExpression);
272         
273                 return new Prefix(prefix.longestCommonExpressionWith(this));
274         }
275
276         public Expression generated_4200363536186052423(Prefix prefix, Expression longestCommonExpression, Expression thisExp) {
277                 for (Expression otherExp: prefix.getSubExpressions(prefixExpression)) {
278                         if (prefix.expressionsMatch(otherExp, thisExp)) {
279                                 if (longestCommonExpression == null) {
280                                         longestCommonExpression = thisExp;
281                                 } else if (thisExp.getLength() > longestCommonExpression.getLength()) {
282                                         longestCommonExpression = thisExp;
283                                 }
284                                 break;
285                         }
286                 }
287                 return longestCommonExpression;
288         }
289
290         public boolean generated_436244330295722658(Prefix prefix) {
291                 if (!prefix.hasExpressionMatching(this))
292                         return false;
293                 return prefix.hasVariableBindingEqualTo(this);
294         }
295
296         public boolean generated_7899053605141751224(Prefix prefix) {
297                 return prefix.expressionsMatch(prefix.prefixExpression, prefixExpression);
298         }
299 }