Lines 8-13
Link Here
|
8 |
* Contributors: |
8 |
* Contributors: |
9 |
* IBM Corporation - initial API and implementation |
9 |
* IBM Corporation - initial API and implementation |
10 |
* Benjamin Muskalla <bmuskalla@eclipsesource.com> - [extract method] extracting return value results in compile error - https://bugs.eclipse.org/bugs/show_bug.cgi?id=264606 |
10 |
* Benjamin Muskalla <bmuskalla@eclipsesource.com> - [extract method] extracting return value results in compile error - https://bugs.eclipse.org/bugs/show_bug.cgi?id=264606 |
|
|
11 |
* Jean-Noël Rouvignac <jnrouvignac@gmail.com> - [extract method] disregard 'this.' when finding duplicates (was: find simple aliasing) - https://bugs.eclipse.org/bugs/show_bug.cgi?id=58648 |
11 |
*******************************************************************************/ |
12 |
*******************************************************************************/ |
12 |
package org.eclipse.jdt.internal.corext.refactoring.code; |
13 |
package org.eclipse.jdt.internal.corext.refactoring.code; |
13 |
|
14 |
|
Lines 31-39
import org.eclipse.jdt.core.dom.FieldAccess;
Link Here
|
31 |
import org.eclipse.jdt.core.dom.IBinding; |
32 |
import org.eclipse.jdt.core.dom.IBinding; |
32 |
import org.eclipse.jdt.core.dom.IVariableBinding; |
33 |
import org.eclipse.jdt.core.dom.IVariableBinding; |
33 |
import org.eclipse.jdt.core.dom.MethodDeclaration; |
34 |
import org.eclipse.jdt.core.dom.MethodDeclaration; |
|
|
35 |
import org.eclipse.jdt.core.dom.Name; |
34 |
import org.eclipse.jdt.core.dom.QualifiedName; |
36 |
import org.eclipse.jdt.core.dom.QualifiedName; |
35 |
import org.eclipse.jdt.core.dom.SimpleName; |
37 |
import org.eclipse.jdt.core.dom.SimpleName; |
36 |
import org.eclipse.jdt.core.dom.SuperFieldAccess; |
38 |
import org.eclipse.jdt.core.dom.SuperFieldAccess; |
|
|
39 |
import org.eclipse.jdt.core.dom.ThisExpression; |
37 |
import org.eclipse.jdt.core.dom.TypeDeclaration; |
40 |
import org.eclipse.jdt.core.dom.TypeDeclaration; |
38 |
|
41 |
|
39 |
import org.eclipse.jdt.internal.corext.dom.ASTNodes; |
42 |
import org.eclipse.jdt.internal.corext.dom.ASTNodes; |
Lines 86-94
import org.eclipse.jdt.internal.corext.dom.GenericVisitor;
Link Here
|
86 |
/** |
89 |
/** |
87 |
* Tests if the whole duplicate is the full body of a method. If so |
90 |
* Tests if the whole duplicate is the full body of a method. If so |
88 |
* don't replace it since we would replace a method body with a new |
91 |
* don't replace it since we would replace a method body with a new |
89 |
* method body which doesn't make to much sense. |
92 |
* method body which doesn't make too much sense. |
90 |
* |
93 |
* |
91 |
* @return whether the duplicte is the whole method body |
94 |
* @return whether the duplicate is the whole method body |
92 |
*/ |
95 |
*/ |
93 |
public boolean isMethodBody() { |
96 |
public boolean isMethodBody() { |
94 |
ASTNode first= fNodes.get(0); |
97 |
ASTNode first= fNodes.get(0); |
Lines 108-141
import org.eclipse.jdt.internal.corext.dom.GenericVisitor;
Link Here
|
108 |
|
111 |
|
109 |
private class Matcher extends ASTMatcher { |
112 |
private class Matcher extends ASTMatcher { |
110 |
@Override |
113 |
@Override |
|
|
114 |
public boolean match(FieldAccess candidate, Object s) { |
115 |
if (s instanceof FieldAccess) { |
116 |
FieldAccess snippet= (FieldAccess) s; |
117 |
IBinding cb= candidate.resolveFieldBinding(); |
118 |
IBinding sb= snippet.resolveFieldBinding(); |
119 |
if (cb == null || sb == null) |
120 |
return false; |
121 |
if (Bindings.equals(cb, sb)) { |
122 |
Expression ce= candidate.getExpression(); |
123 |
Expression se= snippet.getExpression(); |
124 |
if (ce.getNodeType() == ASTNode.THIS_EXPRESSION && |
125 |
se.getNodeType() == ASTNode.THIS_EXPRESSION) { |
126 |
ThisExpression cte= (ThisExpression) ce; |
127 |
ThisExpression ste= (ThisExpression) se; |
128 |
return isSame(cte.getQualifier(), ste.getQualifier(), cte, ste); |
129 |
} |
130 |
} |
131 |
} else if (s instanceof SimpleName) { |
132 |
return match((SimpleName) s, candidate); |
133 |
} |
134 |
return false; |
135 |
} |
136 |
|
137 |
@Override |
111 |
public boolean match(SimpleName candidate, Object s) { |
138 |
public boolean match(SimpleName candidate, Object s) { |
112 |
if (!(s instanceof SimpleName)) |
139 |
if (s instanceof SimpleName) { |
113 |
return false; |
140 |
SimpleName snippet= (SimpleName) s; |
|
|
141 |
if (candidate.isDeclaration() != snippet.isDeclaration()) |
142 |
return false; |
114 |
|
143 |
|
115 |
SimpleName snippet= (SimpleName)s; |
144 |
IBinding cb= candidate.resolveBinding(); |
116 |
if (candidate.isDeclaration() != snippet.isDeclaration()) |
145 |
IBinding sb= snippet.resolveBinding(); |
117 |
return false; |
146 |
if (cb == null || sb == null) |
|
|
147 |
return false; |
148 |
IVariableBinding vcb= ASTNodes.getVariableBinding(candidate); |
149 |
IVariableBinding vsb= ASTNodes.getVariableBinding(snippet); |
150 |
if (vcb == null || vsb == null) |
151 |
return Bindings.equals(cb, sb); |
152 |
if (!vcb.isField() && !vsb.isField() && Bindings.equals(vcb.getType(), vsb.getType())) { |
153 |
SimpleName mapped= fMatch.getMappedName(vsb); |
154 |
if (mapped != null) { |
155 |
IVariableBinding mappedBinding= ASTNodes.getVariableBinding(mapped); |
156 |
if (!Bindings.equals(vcb, mappedBinding)) |
157 |
return false; |
158 |
} |
159 |
fMatch.addLocal(vsb, candidate); |
160 |
return true; |
161 |
} |
162 |
return Bindings.equals(cb, sb); |
163 |
} else if (s instanceof FieldAccess) { |
164 |
return match(candidate, (FieldAccess) s); |
165 |
} |
166 |
return false; |
167 |
} |
118 |
|
168 |
|
119 |
IBinding cb= candidate.resolveBinding(); |
169 |
private boolean match(SimpleName sn, FieldAccess fa) { |
120 |
IBinding sb= snippet.resolveBinding(); |
170 |
if (!isOverarchingNameOrFieldAccess(sn)) { |
121 |
if (cb == null || sb == null) |
|
|
122 |
return false; |
171 |
return false; |
123 |
IVariableBinding vcb= ASTNodes.getVariableBinding(candidate); |
172 |
} |
124 |
IVariableBinding vsb= ASTNodes.getVariableBinding(snippet); |
173 |
IBinding snb= sn.resolveBinding(); |
125 |
if (vcb == null || vsb == null) |
174 |
IBinding fab= fa.resolveFieldBinding(); |
126 |
return Bindings.equals(cb, sb); |
175 |
if (snb == null || fab == null) |
127 |
if (!vcb.isField() && !vsb.isField() && Bindings.equals(vcb.getType(), vsb.getType())) { |
176 |
return false; |
128 |
SimpleName mapped= fMatch.getMappedName(vsb); |
177 |
|
129 |
if (mapped != null) { |
178 |
if (Bindings.equals(snb, fab)) { |
130 |
IVariableBinding mappedBinding= ASTNodes.getVariableBinding(mapped); |
179 |
Expression e= fa.getExpression(); |
131 |
if (!Bindings.equals(vcb, mappedBinding)) |
180 |
if (e.getNodeType() == ASTNode.THIS_EXPRESSION) { |
132 |
return false; |
181 |
ThisExpression te= (ThisExpression) e; |
|
|
182 |
return te.getQualifier() == null || isEnclosingTypeFor(te.getQualifier(), te); |
133 |
} |
183 |
} |
134 |
fMatch.addLocal(vsb, candidate); |
184 |
} |
|
|
185 |
return false; |
186 |
} |
187 |
|
188 |
/** |
189 |
* @param name the name from where to start looking |
190 |
* @return true if there is no Name/FieldAccess above the given Name, false otherwise. |
191 |
*/ |
192 |
private boolean isOverarchingNameOrFieldAccess(Name name) { |
193 |
final ASTNode parent= name.getParent(); |
194 |
if (parent == null) { |
135 |
return true; |
195 |
return true; |
136 |
} |
196 |
} |
137 |
return Bindings.equals(cb, sb); |
197 |
int parentType= parent.getNodeType(); |
|
|
198 |
return parentType != ASTNode.FIELD_ACCESS && parentType != ASTNode.QUALIFIED_NAME; |
199 |
} |
200 |
|
201 |
private boolean isSame(Name name1, Name name2, ASTNode parent1, ASTNode parent2) { |
202 |
if (name1 == null) { |
203 |
return name2 == null || isEnclosingTypeFor(name2, parent1); |
204 |
} else if (name2 == null) { |
205 |
return isEnclosingTypeFor(name1, parent2); |
206 |
} else if (name1.isSimpleName()) { |
207 |
SimpleName sn1= (SimpleName) name1; |
208 |
if (name2.isSimpleName()) { |
209 |
return isSame(sn1, (SimpleName) name2); |
210 |
} else { |
211 |
return isSame(sn1, (QualifiedName) name2, parent2); |
212 |
} |
213 |
} else if (name1.isQualifiedName()) { |
214 |
QualifiedName qual1= (QualifiedName) name1; |
215 |
if (name2.isSimpleName()) { |
216 |
return isSame((SimpleName) name2, qual1, parent1); |
217 |
} else { |
218 |
QualifiedName qual2= (QualifiedName) name2; |
219 |
return isSame(qual1.getName(), qual2.getName()) && isSame(qual1.getQualifier(), qual2.getQualifier(), parent1, parent2); |
220 |
} |
221 |
} |
222 |
return false; |
223 |
} |
224 |
|
225 |
private boolean isSame(SimpleName name1, SimpleName name2) { |
226 |
return name1.getIdentifier().equals(name2.getIdentifier()); |
227 |
} |
228 |
|
229 |
private boolean isSame(SimpleName sn, QualifiedName qual, ASTNode qualParent) { |
230 |
if (sn.getIdentifier().equals(qual.getName().getIdentifier())) { |
231 |
TypeDeclaration typeDecl= (TypeDeclaration) ASTNodes.getParent(qualParent, TypeDeclaration.class); |
232 |
if (typeDecl.getName().getIdentifier().equals(qual.getName().getIdentifier())) { |
233 |
return isEnclosingTypeFor(qual.getQualifier(), typeDecl.getParent()); |
234 |
} |
235 |
} |
236 |
return false; |
138 |
} |
237 |
} |
|
|
238 |
|
239 |
private boolean isEnclosingTypeFor(Name name, ASTNode node) { |
240 |
if (name == null || node == null || node.getParent() == null) { |
241 |
return false; |
242 |
} |
243 |
ASTNode parent= node.getParent(); |
244 |
if (node.getNodeType() == ASTNode.TYPE_DECLARATION) { |
245 |
final TypeDeclaration typeDecl= (TypeDeclaration) node; |
246 |
final SimpleName typeName= typeDecl.getName(); |
247 |
if (name.isSimpleName()) { |
248 |
SimpleName sn= (SimpleName) name; |
249 |
return sn.getIdentifier().equals(typeName.getIdentifier()); |
250 |
} else if (name.isQualifiedName()) { |
251 |
QualifiedName qn= (QualifiedName) name; |
252 |
return qn.getName().getIdentifier().equals(typeName.getIdentifier()) && isEnclosingTypeFor(qn.getQualifier(), parent); |
253 |
} |
254 |
} |
255 |
return isEnclosingTypeFor(name, parent); |
256 |
} |
257 |
|
139 |
} |
258 |
} |
140 |
|
259 |
|
141 |
private List<Match> fResult= new ArrayList<Match>(2); |
260 |
private List<Match> fResult= new ArrayList<Match>(2); |