View | Details | Raw Unified | Return to bug 58648 | Differences between
and this patch

Collapse All | Expand All

(-)a/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/ExtractMethodTests.java (-1 / +17 lines)
Lines 968-974 public class ExtractMethodTests extends AbstractSelectionTestCase { Link Here
968
	public void test374() throws Exception {
968
	public void test374() throws Exception {
969
		validSelectionTestChecked();
969
		validSelectionTestChecked();
970
	}
970
	}
971
	
971
972
	public void test375() throws Exception {
973
		validSelectionTestChecked(); //https://bugs.eclipse.org/bugs/show_bug.cgi?id=58648
974
	}
975
976
	public void test376() throws Exception {
977
		validSelectionTestChecked(); //https://bugs.eclipse.org/bugs/show_bug.cgi?id=58648
978
	}
979
980
	public void test377() throws Exception {
981
		validSelectionTestChecked(); //https://bugs.eclipse.org/bugs/show_bug.cgi?id=58648
982
	}
983
984
	public void test378() throws Exception {
985
		validSelectionTestChecked(); //https://bugs.eclipse.org/bugs/show_bug.cgi?id=58648
986
	}
987
972
	//====================================================================================
988
	//====================================================================================
973
	// Testing Extracted result
989
	// Testing Extracted result
974
	//====================================================================================
990
	//====================================================================================
(-)a/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/ExtractMethodRefactoring.java (-8 / +7 lines)
Lines 505-515 public class ExtractMethodRefactoring extends Refactoring { Link Here
505
			TextEditGroup substituteDesc= new TextEditGroup(Messages.format(RefactoringCoreMessages.ExtractMethodRefactoring_substitute_with_call, BasicElementLabels.getJavaElementName(fMethodName)));
505
			TextEditGroup substituteDesc= new TextEditGroup(Messages.format(RefactoringCoreMessages.ExtractMethodRefactoring_substitute_with_call, BasicElementLabels.getJavaElementName(fMethodName)));
506
			result.addTextEditGroup(substituteDesc);
506
			result.addTextEditGroup(substituteDesc);
507
507
508
			MethodDeclaration mm= createNewMethod(selectedNodes, fCUnit.findRecommendedLineSeparator(), substituteDesc);
508
			MethodDeclaration extractedMethod= createNewMethod(selectedNodes, fCUnit.findRecommendedLineSeparator(), substituteDesc);
509
509
510
			if (fLinkedProposalModel != null) {
510
			if (fLinkedProposalModel != null) {
511
				LinkedProposalPositionGroup typeGroup= fLinkedProposalModel.getPositionGroup(KEY_TYPE, true);
511
				LinkedProposalPositionGroup typeGroup= fLinkedProposalModel.getPositionGroup(KEY_TYPE, true);
512
				typeGroup.addPosition(fRewriter.track(mm.getReturnType2()), false);
512
				typeGroup.addPosition(fRewriter.track(extractedMethod.getReturnType2()), false);
513
513
514
				ITypeBinding typeBinding= fAnalyzer.getReturnTypeBinding();
514
				ITypeBinding typeBinding= fAnalyzer.getReturnTypeBinding();
515
				if (typeBinding != null) {
515
				if (typeBinding != null) {
Lines 520-528 public class ExtractMethodRefactoring extends Refactoring { Link Here
520
				}
520
				}
521
521
522
				LinkedProposalPositionGroup nameGroup= fLinkedProposalModel.getPositionGroup(KEY_NAME, true);
522
				LinkedProposalPositionGroup nameGroup= fLinkedProposalModel.getPositionGroup(KEY_NAME, true);
523
				nameGroup.addPosition(fRewriter.track(mm.getName()), false);
523
				nameGroup.addPosition(fRewriter.track(extractedMethod.getName()), false);
524
524
525
				ModifierCorrectionSubProcessor.installLinkedVisibilityProposals(fLinkedProposalModel, fRewriter, mm.modifiers(), false);
525
				ModifierCorrectionSubProcessor.installLinkedVisibilityProposals(fLinkedProposalModel, fRewriter, extractedMethod.modifiers(), false);
526
			}
526
			}
527
527
528
			TextEditGroup insertDesc= new TextEditGroup(Messages.format(RefactoringCoreMessages.ExtractMethodRefactoring_add_method, BasicElementLabels.getJavaElementName(fMethodName)));
528
			TextEditGroup insertDesc= new TextEditGroup(Messages.format(RefactoringCoreMessages.ExtractMethodRefactoring_add_method, BasicElementLabels.getJavaElementName(fMethodName)));
Lines 531-543 public class ExtractMethodRefactoring extends Refactoring { Link Here
531
			if (fDestination == fDestinations[0]) {
531
			if (fDestination == fDestinations[0]) {
532
				ChildListPropertyDescriptor desc= (ChildListPropertyDescriptor)declaration.getLocationInParent();
532
				ChildListPropertyDescriptor desc= (ChildListPropertyDescriptor)declaration.getLocationInParent();
533
				ListRewrite container= fRewriter.getListRewrite(declaration.getParent(), desc);
533
				ListRewrite container= fRewriter.getListRewrite(declaration.getParent(), desc);
534
				container.insertAfter(mm, declaration, insertDesc);
534
				container.insertAfter(extractedMethod, declaration, insertDesc);
535
			} else {
535
			} else {
536
				BodyDeclarationRewrite container= BodyDeclarationRewrite.create(fRewriter, fDestination);
536
				BodyDeclarationRewrite container= BodyDeclarationRewrite.create(fRewriter, fDestination);
537
				container.insert(mm, insertDesc);
537
				container.insert(extractedMethod, insertDesc);
538
			}
538
			}
539
539
540
			replaceDuplicates(result, mm.getModifiers());
540
			replaceDuplicates(result, extractedMethod.getModifiers());
541
			replaceBranches(result);
541
			replaceBranches(result);
542
542
543
			if (fImportRewriter.hasRecordedChanges()) {
543
			if (fImportRewriter.hasRecordedChanges()) {
Lines 553-559 public class ExtractMethodRefactoring extends Refactoring { Link Here
553
		} finally {
553
		} finally {
554
			pm.done();
554
			pm.done();
555
		}
555
		}
556
557
	}
556
	}
558
557
559
	private void replaceBranches(final CompilationUnitChange result) {
558
	private void replaceBranches(final CompilationUnitChange result) {
(-)a/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/SnippetFinder.java (-22 / +141 lines)
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 <jn.rouvignac@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);

Return to bug 58648