Project: JDT
Bug 186061 [extract method] does not detect duplicate code snippet
Reported: 2007-05-08 20:47:07 | Status: verified fixed

Build ID: M20060629-1905 Steps To Reproduce: 1.Have snippets of code that are nearly identical. public void a3() { Transaction t = new Transaction(); Action action = new Action(" A.a3"); String string = "A.a3"; // MY SELECTED EXTRACT TARGET t.start(string); t.run(action); t.end(); // MY EXTRACT TARGET ENDS } public void a4() { Transaction t = new Transaction(); String t_name = "A.a4"; Action action = new Action(t_name); t.start(t_name); t.run(t_name); t.end(); } public void a6() { Transaction t = new Transaction(); String t_name = "A.a6"; Action action = new Action(t_name); // DUPLICATE!!! t.start(t_name); t.run(action); t.end(); } 2. Select the following snippet in a3(), and press Alt-Shift-M. t.start(string); t.run(action); t.end(); 3. In Extract Method Refactoring Wizard Input Page, the "Replace all occurence of statements with occurence " checkbox is not highlighted. However, a3() and a6() have identical snippets. if a user switch the positions between a4() and a6(), and redo the Extract Method, "Replace 1 occurence of statements with occurence " checkbox is highlighted. More information: poked around the code and realize that the bug in the following method org.eclipse.jdt.internal.corext.refactoring.code.SnippetFinder.Match.isEmpty() public boolean isEmpty() { return fNodes.isEmpty(); } This condition is pre-requisite for a reset. However, in the body of a4(), when t.run(t_name) matches against t.run(action), the test failed, SnippetFinder reset() is called. SnippetFinder then matches t.run(action) in a4() and t.start(string) in a3(). Both local variables t in both snippet matches and is stored in the SnippetFinder.Match.fLocalMappings. however, subsequent subtree matches fail. however, although no nodes is added to SnippetFinder.Match, the fLocalMapping is NOT empty. Later when SnippetFinder matches t.start(string) in a3() and t.start(string) in a6(), since the typebinding of t (which comes from a4) exist in the Snippet.Match object and the binding is indeed different from t in a6(), the match will fail.

Files changed in fix:
org.eclipse.jdt.ui.tests.refactoring/resources/ExtractMethodWorkSpace/ExtractMethodTests/duplicates_in/A_test970.java org.eclipse.jdt.ui.tests.refactoring/resources/ExtractMethodWorkSpace/ExtractMethodTests/duplicates_out/A_test970.java org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/ExtractMethodTests.java org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/SnippetFinder.java