diff --git a/core/org.eclipse.cdt.ui.tests/resources/refactoring/ExtractMethodDuplicates.rts b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ExtractMethodDuplicates.rts
new file mode 100644
index 00000000000..a3be46e65ad
--- /dev/null
+++ b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ExtractMethodDuplicates.rts
@@ -0,0 +1,1075 @@
+//!ExtractFunctionRefactoringTest with duplicates
+//#org.eclipse.cdt.ui.tests.refactoring.extractfunction.ExtractFunctionRefactoringTest
+//@.config
+replaceduplicates=true
+//@A.h
+#ifndef A_H_
+#define A_H_
+
+class A
+{
+public:
+ A();
+ virtual ~A();
+ int foo();
+
+private:
+ int help();
+};
+
+#endif /*A_H_*/
+
+//=
+#ifndef A_H_
+#define A_H_
+
+class A
+{
+public:
+ A();
+ virtual ~A();
+ int foo();
+
+private:
+ int help();
+ void exp(int & i);
+};
+
+#endif /*A_H_*/
+
+//@A.cpp
+#include "A.h"
+
+A::A()
+{
+}
+
+A::~A()
+{
+ int i = 2;
+ ++i;
+ help();
+}int A::foo()
+{
+ int i = 2;
+ /*$*/++i;
+ help();/*$$*/
+ return i;
+}
+
+int A::help()
+{
+ return 42;
+}
+
+//=
+#include "A.h"
+
+A::A()
+{
+}
+
+A::~A()
+{
+ int i = 2;
+ exp(i);
+}void A::exp(int & i)
+{
+ ++i;
+ help();
+}
+
+int A::foo()
+{
+ int i = 2;
+ exp(i);
+ return i;
+}
+
+int A::help()
+{
+ return 42;
+}
+
+//!ExtractFunctionRefactoringTest duplicates with different Names
+//#org.eclipse.cdt.ui.tests.refactoring.extractfunction.ExtractFunctionRefactoringTest
+//@.config
+replaceduplicates=true
+//@A.h
+#ifndef A_H_
+#define A_H_
+
+class A
+{
+public:
+ A();
+ virtual ~A();
+ int foo();
+
+private:
+ int help();
+};
+
+#endif /*A_H_*/
+
+//=
+#ifndef A_H_
+#define A_H_
+
+class A
+{
+public:
+ A();
+ virtual ~A();
+ int foo();
+
+private:
+ int help();
+ void exp(int & i);
+};
+
+#endif /*A_H_*/
+
+//@A.cpp
+#include "A.h"
+
+A::A()
+{
+}
+
+A::~A()
+{
+ int oo = 99;
+ ++oo;
+ help();
+}int A::foo()
+{
+ int i = 2;
+ /*$*/++i;
+ help();/*$$*/
+ return i;
+}
+
+int A::help()
+{
+ return 42;
+}
+
+//=
+#include "A.h"
+
+A::A()
+{
+}
+
+A::~A()
+{
+ int oo = 99;
+ exp(oo);
+}void A::exp(int & i)
+{
+ ++i;
+ help();
+}
+
+int A::foo()
+{
+ int i = 2;
+ exp(i);
+ return i;
+}
+
+int A::help()
+{
+ return 42;
+}
+
+//!ExtractFunctionRefactoringTest dublicate with field
+//#org.eclipse.cdt.ui.tests.refactoring.extractfunction.ExtractFunctionRefactoringTest
+//@.config
+replaceduplicates=true
+returnvalue=true
+//@A.h
+#ifndef A_H_
+#define A_H_
+
+class A
+{
+public:
+ A();
+ virtual ~A();
+ void foo();
+ int i;
+
+private:
+ int help();
+};
+
+#endif /*A_H_*/
+
+//=
+#ifndef A_H_
+#define A_H_
+
+class A
+{
+public:
+ A();
+ virtual ~A();
+ void foo();
+ int i;
+
+private:
+ int help();
+ int exp(int j, int & a);
+};
+
+#endif /*A_H_*/
+
+//@A.cpp
+#include "A.h"
+
+A::A()
+{
+}
+
+A::~A()
+{
+ int j = 0;
+ i++;
+ j++;
+ help();
+}void A::foo()
+{
+ int j = 0;
+ int a = 1;
+ /*$*/j++;
+ a++;
+ help();/*$$*/
+ a++;
+ j++;
+}
+
+int A::help()
+{
+ return 42;
+}
+
+//=
+#include "A.h"
+
+A::A()
+{
+}
+
+A::~A()
+{
+ int j = 0;
+ i = exp(i, j);
+}int A::exp(int j, int & a)
+{
+ j++;
+ a++;
+ help();
+ return j;
+}
+
+void A::foo()
+{
+ int j = 0;
+ int a = 1;
+ j = exp(j, a);
+ a++;
+ j++;
+}
+
+int A::help()
+{
+ return 42;
+}
+
+//!ExtractFunctionRefactoringTest dublicate with field in marked scope
+//#org.eclipse.cdt.ui.tests.refactoring.extractfunction.ExtractFunctionRefactoringTest
+//@.config
+replaceduplicates=true
+returnvalue=true
+//@A.h
+#ifndef A_H_
+#define A_H_
+
+class A
+{
+public:
+ A();
+ virtual ~A();
+ void foo();
+ int i;
+ int field;
+
+private:
+ int help();
+};
+
+#endif /*A_H_*/
+
+//=
+#ifndef A_H_
+#define A_H_
+
+class A
+{
+public:
+ A();
+ virtual ~A();
+ void foo();
+ int i;
+ int field;
+
+private:
+ int help();
+ int exp(int j);
+};
+
+#endif /*A_H_*/
+
+//@A.cpp
+#include "A.h"
+
+A::A()
+{
+}
+
+A::~A()
+{
+ int j = 0;
+ int a = 1;
+ a++;
+ j++;
+ help();
+}void A::foo()
+{
+ int j = 0;
+
+ /*$*/field++;
+ j++;
+ help();/*$$*/
+ field++;
+ j++;
+}
+
+int A::help()
+{
+ return 42;
+}
+
+//=
+#include "A.h"
+
+A::A()
+{
+}
+
+A::~A()
+{
+ int j = 0;
+ int a = 1;
+ a++;
+ j++;
+ help();
+}int A::exp(int j)
+{
+ field++;
+ j++;
+ help();
+ return j;
+}
+
+void A::foo()
+{
+ int j = 0;
+ j = exp(j);
+ field++;
+ j++;
+}
+
+int A::help()
+{
+ return 42;
+}
+
+//!ExtractFunctionRefactoringTest duplicates with different Names and return type
+//#org.eclipse.cdt.ui.tests.refactoring.extractfunction.ExtractFunctionRefactoringTest
+//@.config
+replaceduplicates=true
+returnvalue=true
+//@A.h
+#ifndef A_H_
+#define A_H_
+
+class A
+{
+public:
+ A();
+ virtual ~A();
+ int foo();
+
+private:
+ int help();
+};
+
+#endif /*A_H_*/
+
+//=
+#ifndef A_H_
+#define A_H_
+
+class A
+{
+public:
+ A();
+ virtual ~A();
+ int foo();
+
+private:
+ int help();
+ int exp(int i, float & j);
+};
+
+#endif /*A_H_*/
+
+//@A.cpp
+#include "A.h"
+
+A::A()
+{
+}
+
+A::~A()
+{
+ int oo = 99;
+ float blabla = 0;
+ ++oo;
+ blabla += 1;
+ help();
+ blabla += 1;
+}int A::foo()
+{
+ int i = 2;
+ float j = 8989;
+ /*$*/++i;
+ j+=1;
+ help();/*$$*/
+ j++;
+ return i;
+}
+
+int A::help()
+{
+ return 42;
+}
+
+//=
+#include "A.h"
+
+A::A()
+{
+}
+
+A::~A()
+{
+ int oo = 99;
+ float blabla = 0;
+ oo = exp(oo, blabla);
+ blabla += 1;
+}int A::exp(int i, float & j)
+{
+ ++i;
+ j += 1;
+ help();
+ return i;
+}
+
+int A::foo()
+{
+ int i = 2;
+ float j = 8989;
+ i = exp(i, j);
+ j++;
+ return i;
+}
+
+int A::help()
+{
+ return 42;
+}
+
+//!ExtractFunctionRefactoringTest duplicates with a lot of different Names an variable not used afterwards in the duplicate
+//#org.eclipse.cdt.ui.tests.refactoring.extractfunction.ExtractFunctionRefactoringTest
+//@.config
+replaceduplicates=true
+//@A.h
+#ifndef A_H_
+#define A_H_
+
+class A
+{
+public:
+ A();
+ virtual ~A();
+ int foo();
+
+private:
+ int help();
+};
+
+#endif /*A_H_*/
+
+//=
+#ifndef A_H_
+#define A_H_
+
+class A
+{
+public:
+ A();
+ virtual ~A();
+ int foo();
+
+private:
+ int help();
+ void exp(int & i, float j);
+};
+
+#endif /*A_H_*/
+
+//@A.cpp
+#include "A.h"
+
+A::A()
+{
+}
+
+A::~A()
+{
+ int oo = 99;
+ float blabla = 0;
+ ++oo;
+ blabla += 1;
+ help();
+}int A::foo()
+{
+ int i = 2;
+ float j = 8989;
+ /*$*/++i;
+ j+=1;
+ help();/*$$*/
+ return i;
+}
+
+int A::help()
+{
+ return 42;
+}
+
+//=
+#include "A.h"
+
+A::A()
+{
+}
+
+A::~A()
+{
+ int oo = 99;
+ float blabla = 0;
+ exp(oo, blabla);
+}void A::exp(int & i, float j)
+{
+ ++i;
+ j += 1;
+ help();
+}
+
+int A::foo()
+{
+ int i = 2;
+ float j = 8989;
+ exp(i, j);
+ return i;
+}
+
+int A::help()
+{
+ return 42;
+}
+
+//!ExtractFunctionRefactoringTest with duplicates name used afterwards in duplicate but not in original selection this is no dublicate
+//#org.eclipse.cdt.ui.tests.refactoring.extractfunction.ExtractFunctionRefactoringTest
+//@.config
+replaceduplicates=true
+//@A.h
+#ifndef A_H_
+#define A_H_
+
+class A
+{
+public:
+ A();
+ virtual ~A();
+ void foo();
+
+private:
+ int help();
+};
+
+#endif /*A_H_*/
+
+//=
+#ifndef A_H_
+#define A_H_
+
+class A
+{
+public:
+ A();
+ virtual ~A();
+ void foo();
+
+private:
+ int help();
+ void exp(int i);
+};
+
+#endif /*A_H_*/
+
+//@A.cpp
+#include "A.h"
+
+A::A()
+{
+}
+
+A::~A()
+{
+ int i = 2;
+ ++i;// No Duplicate
+ help();
+ ++i;// this is the reason
+}void A::foo()
+{
+ int i = 2;
+ /*$*/++i;
+ help();/*$$*/
+}
+
+int A::help()
+{
+ return 42;
+}
+
+//=
+#include "A.h"
+
+A::A()
+{
+}
+
+A::~A()
+{
+ int i = 2;
+ ++i;// No Duplicate
+ help();
+ ++i;// this is the reason
+}void A::exp(int i)
+{
+ ++i;
+ help();
+}
+
+void A::foo()
+{
+ int i = 2;
+ exp(i);
+}
+
+int A::help()
+{
+ return 42;
+}
+
+//!ExtractFunctionRefactoringTest with Return Value and a lot Ref Parameter and a method call
+//#org.eclipse.cdt.ui.tests.refactoring.extractfunction.ExtractFunctionRefactoringTest
+//@.config
+replaceduplicates=true
+returnvalue=true
+//@A.h
+#ifndef A_H_
+#define A_H_
+
+#include "B.h"
+
+class A
+{
+public:
+ A();
+ virtual ~A();
+ int foo();
+
+private:
+ int help();
+};
+
+#endif /*A_H_*/
+
+//=
+#ifndef A_H_
+#define A_H_
+
+#include "B.h"
+
+class A
+{
+public:
+ A();
+ virtual ~A();
+ int foo();
+
+private:
+ int help();
+ int exp(int i, B *& b, int & y, float & x);
+};
+
+#endif /*A_H_*/
+
+//@A.cpp
+#include "A.h"
+
+A::A()
+{
+}
+
+A::~A()
+{
+ int i = 2;
+ float x = i;
+ B* b = new B();
+ int y = x + i;
+ ++i;
+ b->hello(y);
+ i = i + x;
+ help();
+ b->hello(y);
+ ++x;
+ i++;
+}int A::foo()
+{
+ int i = 2;
+ float x = i;
+ B* b = new B();
+ int y = x + i;
+ /*$*/++i;
+ b->hello(y);
+ i = i + x;
+ help();/*$$*/
+ b->hello(y);
+ ++x;
+ return i;
+}
+
+int A::help()
+{
+ return 42;
+}
+
+//=
+#include "A.h"
+
+A::A()
+{
+}
+
+A::~A()
+{
+ int i = 2;
+ float x = i;
+ B* b = new B();
+ int y = x + i;
+ i = exp(i, b, y, x);
+ b->hello(y);
+ ++x;
+ i++;
+}int A::exp(int i, B *& b, int & y, float & x)
+{
+ ++i;
+ b->hello(y);
+ i = i + x;
+ help();
+ return i;
+}
+
+int A::foo()
+{
+ int i = 2;
+ float x = i;
+ B* b = new B();
+ int y = x + i;
+ i = exp(i, b, y, x);
+ b->hello(y);
+ ++x;
+ return i;
+}
+
+int A::help()
+{
+ return 42;
+}
+
+//@B.h
+#ifndef B_H_
+#define B_H_
+
+class B
+{
+public:
+ B();
+ virtual ~B();
+ void hello(float y);
+};
+
+#endif /*B_H_*/
+
+//!ExtractFunctionRefactoringTest with Return Value and a lot Ref Parameter and a method call, duplicate is not similar
+//#org.eclipse.cdt.ui.tests.refactoring.extractfunction.ExtractFunctionRefactoringTest
+//@.config
+replaceduplicates=true
+returnvalue=true
+//@A.h
+#ifndef A_H_
+#define A_H_
+
+#include "B.h"
+
+class A
+{
+public:
+ A();
+ virtual ~A();
+ int foo();
+
+private:
+ int help();
+};
+
+#endif /*A_H_*/
+
+//=
+#ifndef A_H_
+#define A_H_
+
+#include "B.h"
+
+class A
+{
+public:
+ A();
+ virtual ~A();
+ int foo();
+
+private:
+ int help();
+ int exp(int i, B *& b, int & y, float x);
+};
+
+#endif /*A_H_*/
+
+//@A.cpp
+#include "A.h"
+
+A::A()
+{
+}
+
+A::~A()
+{
+ int i = 2;
+ float x = i;
+ B* b = new B();
+ int y = x + i;
+ ++i;
+ b->hello(y);
+ i = i + x;
+ help();
+ b->hello(y);
+ ++x;
+ i++;
+}int A::foo()
+{
+ int i = 2;
+ float x = i;
+ B* b = new B();
+ int y = x + i;
+ /*$*/++i;
+ b->hello(y);
+ i = i + x;
+ help();/*$$*/
+ b->hello(y);
+ return i;
+}
+
+int A::help()
+{
+ return 42;
+}
+
+//=
+#include "A.h"
+
+A::A()
+{
+}
+
+A::~A()
+{
+ int i = 2;
+ float x = i;
+ B* b = new B();
+ int y = x + i;
+ ++i;
+ b->hello(y);
+ i = i + x;
+ help();
+ b->hello(y);
+ ++x;
+ i++;
+}int A::exp(int i, B *& b, int & y, float x)
+{
+ ++i;
+ b->hello(y);
+ i = i + x;
+ help();
+ return i;
+}
+
+int A::foo()
+{
+ int i = 2;
+ float x = i;
+ B* b = new B();
+ int y = x + i;
+ i = exp(i, b, y, x);
+ b->hello(y);
+ return i;
+}
+
+int A::help()
+{
+ return 42;
+}
+
+//@B.h
+#ifndef B_H_
+#define B_H_
+
+class B
+{
+public:
+ B();
+ virtual ~B();
+ void hello(float y);
+};
+
+#endif /*B_H_*/
+
+//!ExtractFunctionRefactoringTest with duplicates and comments
+//#org.eclipse.cdt.ui.tests.refactoring.extractfunction.ExtractFunctionRefactoringTest
+//@.config
+replaceduplicates=true
+//@A.h
+#ifndef A_H_
+#define A_H_
+
+class A
+{
+public:
+ A();
+ virtual ~A();
+ int foo();
+
+private:
+ int help();
+};
+
+#endif /*A_H_*/
+
+//=
+#ifndef A_H_
+#define A_H_
+
+class A
+{
+public:
+ A();
+ virtual ~A();
+ int foo();
+
+private:
+ int help();
+ void exp(int & i);
+};
+
+#endif /*A_H_*/
+
+//@A.cpp
+#include "A.h"
+
+A::A()
+{
+}
+
+A::~A()
+{
+ int i = 2;
+ ++i;
+ help();
+}int A::foo()
+{
+ int i = 2;
+ /*$*/++i;
+ help();/*$$*/
+ return i;
+}
+
+int A::help()
+{
+ return 42;
+}
+
+//=
+#include "A.h"
+
+A::A()
+{
+}
+
+A::~A()
+{
+ int i = 2;
+ exp(i);
+}void A::exp(int & i)
+{
+ ++i;
+ help();
+}
+
+int A::foo()
+{
+ int i = 2;
+ exp(i);
+ return i;
+}
+
+int A::help()
+{
+ return 42;
+}
+
diff --git a/core/org.eclipse.cdt.ui.tests/resources/refactoring/ExtractMethodHistory.rts b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ExtractMethodHistory.rts
index d359fd5bcc4..218bbba9ccc 100644
--- a/core/org.eclipse.cdt.ui.tests/resources/refactoring/ExtractMethodHistory.rts
+++ b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ExtractMethodHistory.rts
@@ -261,3 +261,102 @@ int main(){
flags="4" id="org.eclipse.cdt.internal.ui.refactoring.extractfunction.ExtractFunctionRefactoring"
name="exp" project="RegressionTestProject" selection="23,5" visibility="private"/>
+
+//!ExtractFunctionRefactoringTest duplicates with different Names History Test
+//#org.eclipse.cdt.ui.tests.refactoring.RefactoringHistoryTest
+//@A.h
+#ifndef A_H_
+#define A_H_
+
+class A
+{
+public:
+ A();
+ virtual ~A();
+ int foo();
+
+private:
+ int help();
+};
+
+#endif /*A_H_*/
+
+//=
+#ifndef A_H_
+#define A_H_
+
+class A
+{
+public:
+ A();
+ virtual ~A();
+ int foo();
+
+private:
+ int help();
+ void exp(int & i);
+};
+
+#endif /*A_H_*/
+
+//@A.cpp
+#include "A.h"
+
+A::A()
+{
+}
+
+A::~A()
+{
+ int oo = 99;
+ ++oo;
+ help();
+}int A::foo()
+{
+ int i = 2;
+ ++i;
+ help();
+ return i;
+}
+
+int A::help()
+{
+ return 42;
+}
+
+//=
+#include "A.h"
+
+A::A()
+{
+}
+
+A::~A()
+{
+ int oo = 99;
+ exp(oo);
+}void A::exp(int & i)
+{
+ ++i;
+ help();
+}
+
+int A::foo()
+{
+ int i = 2;
+ exp(i);
+ return i;
+}
+
+int A::help()
+{
+ return 42;
+}
+
+//@refScript.xml
+
+
+
+
diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/extractfunction/ExtractFunctionTestSuite.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/extractfunction/ExtractFunctionTestSuite.java
index 816fe41c6d6..562ff556e9a 100644
--- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/extractfunction/ExtractFunctionTestSuite.java
+++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/extractfunction/ExtractFunctionTestSuite.java
@@ -30,6 +30,7 @@ public class ExtractFunctionTestSuite extends TestSuite {
suite.addTest(RefactoringTester.suite("ExtractMethodPreprocessorRefactoringTests", "resources/refactoring/ExtractMethodPreprocessor.rts"));
suite.addTest(RefactoringTester.suite("Extract Function Templates Tests", "resources/refactoring/ExtractFunctionTemplates.rts"));
suite.addTest(RefactoringTester.suite("Extract Method History Test", "resources/refactoring/ExtractMethodHistory.rts"));
+ suite.addTest(RefactoringTester.suite("Extract Function Dublicates Test", "resources/refactoring/ExtractMethodDuplicates.rts"));
return suite;
}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionComposite.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionComposite.java
index e77f5a6100d..9a69a5f1d24 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionComposite.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionComposite.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2008 Institute for Software, HSR Hochschule fuer Technik
+ * Copyright (c) 2008, 2009 Institute for Software, HSR Hochschule fuer Technik
* Rapperswil, University of applied sciences and others
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -40,15 +40,13 @@ public class ExtractFunctionComposite extends Composite {
Group returnGroup = createReturnGroup(nameVisiComp);
createReturnValueChooser(returnGroup, info, ip);
- // Disabled for now
- //createReplaceCheckBox(nameVisiComp);
+ createReplaceCheckBox(nameVisiComp);
if (info.getMethodContext().getType() == MethodContext.ContextType.METHOD) {
visibilityPanelSetVisible(true);
}else {
visibilityPanelSetVisible(false);
}
-
layout();
}
@@ -106,13 +104,13 @@ public class ExtractFunctionComposite extends Composite {
}
-// private void createReplaceCheckBox(Composite parent) {
-// replaceSimilar = new Button(parent, SWT.CHECK | SWT.LEFT);
-// GridData buttonLayoutData = new GridData(SWT.None);
-// buttonLayoutData.verticalIndent = 5;
-// replaceSimilar.setLayoutData(buttonLayoutData);
-// replaceSimilar.setText(Messages.ExtractFunctionComposite_ReplaceDuplicates);
-// }
+ private void createReplaceCheckBox(Composite parent) {
+ replaceSimilar = new Button(parent, SWT.CHECK | SWT.LEFT);
+ GridData buttonLayoutData = new GridData(SWT.None);
+ buttonLayoutData.verticalIndent = 5;
+ replaceSimilar.setLayoutData(buttonLayoutData);
+ replaceSimilar.setText(Messages.ExtractFunctionComposite_ReplaceDuplicates);
+ }
public ChooserComposite getReturnChooser() {
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionInputPage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionInputPage.java
index d0dc6da41d9..c877b466e11 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionInputPage.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionInputPage.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2008 Institute for Software, HSR Hochschule fuer Technik
+ * Copyright (c) 2008, 2009 Institute for Software, HSR Hochschule fuer Technik
* Rapperswil, University of applied sciences and others
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -17,6 +17,8 @@ import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
@@ -65,9 +67,7 @@ public class ExtractFunctionInputPage extends UserInputWizardPage {
});
}
- /* Disable until it works again.
- *
- * comp.getReplaceSimilarButton().addSelectionListener(new SelectionListener(){
+ comp.getReplaceSimilarButton().addSelectionListener(new SelectionListener(){
public void widgetDefaultSelected(SelectionEvent e) {
info.setReplaceDuplicates(comp.getReplaceSimilarButton().isEnabled());
@@ -77,7 +77,7 @@ public class ExtractFunctionInputPage extends UserInputWizardPage {
widgetDefaultSelected(e);
}
- });*/
+ });
setControl(comp);
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionRefactoring.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionRefactoring.java
index 8f14212aee0..beed263a8fe 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionRefactoring.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionRefactoring.java
@@ -13,6 +13,7 @@ package org.eclipse.cdt.internal.ui.refactoring.extractfunction;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Vector;
@@ -36,6 +37,7 @@ import org.eclipse.text.edits.TextEditGroup;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
+import org.eclipse.cdt.core.dom.ast.IASTComment;
import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement;
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
@@ -49,6 +51,7 @@ import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTInitializerExpression;
import org.eclipse.cdt.core.dom.ast.IASTName;
+import org.eclipse.cdt.core.dom.ast.IASTNamedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTPointerOperator;
@@ -63,11 +66,15 @@ import org.eclipse.cdt.core.dom.ast.INodeFactory;
import org.eclipse.cdt.core.dom.ast.IParameter;
import org.eclipse.cdt.core.dom.ast.cpp.CPPASTVisitor;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConversionName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTOperatorName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateParameter;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPBinding;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.core.dom.rewrite.ASTRewrite;
@@ -105,6 +112,7 @@ import org.eclipse.cdt.internal.ui.refactoring.NodeContainer;
import org.eclipse.cdt.internal.ui.refactoring.MethodContext.ContextType;
import org.eclipse.cdt.internal.ui.refactoring.NodeContainer.NameInformation;
import org.eclipse.cdt.internal.ui.refactoring.utils.ASTHelper;
+import org.eclipse.cdt.internal.ui.refactoring.utils.CPPASTAllVisitor;
import org.eclipse.cdt.internal.ui.refactoring.utils.NodeHelper;
import org.eclipse.cdt.internal.ui.refactoring.utils.SelectionHelper;
@@ -129,7 +137,7 @@ public class ExtractFunctionRefactoring extends CRefactoring {
HashMap nameTrail;
private ExtractedFunctionConstructionHelper extractedFunctionConstructionHelper;
- private INodeFactory factory = CPPNodeFactory.getDefault();
+ private final INodeFactory factory = CPPNodeFactory.getDefault();
public ExtractFunctionRefactoring(IFile file, ISelection selection,
ExtractFunctionInformation info, ICProject project) {
@@ -340,6 +348,11 @@ public class ExtractFunctionRefactoring extends CRefactoring {
methodCall = declarationStatement;
}
insertCallintoTree(methodCall, container.getNodesToWrite(), rewriter, editGroup);
+
+ if (info.isReplaceDuplicates()) {
+ replaceSimilar(collector, astMethodName, implementationFile, context.getType());
+ }
+
for (IASTNode node : container.getNodesToWrite()) {
if (node != firstNodeToWrite) {
rewriter.remove(node, editGroup);
@@ -404,6 +417,158 @@ public class ExtractFunctionRefactoring extends CRefactoring {
}
+ private void replaceSimilar(ModificationCollector collector, final IASTName astMethodName,
+ final IFile implementationFile,
+ final ContextType contextType) {
+ // Find similar code
+ final List nodesToRewriteWithoutComments = new LinkedList();
+
+ for (IASTNode node : container.getNodesToWrite()) {
+ if (!(node instanceof IASTComment)) {
+ nodesToRewriteWithoutComments.add(node);
+ }
+ }
+
+ final Vector initTrail = getTrail(nodesToRewriteWithoutComments);
+ final String title;
+ if (contextType == MethodContext.ContextType.METHOD) {
+ title = Messages.ExtractFunctionRefactoring_CreateMethodCall;
+ } else {
+ title = Messages.ExtractFunctionRefactoring_CreateFunctionCall;
+ }
+
+ if (!hasNameResolvingForSimilarError) {
+ unit.accept(new SimilarFinderVisitor(this, collector, initTrail, implementationFile,
+ astMethodName, nodesToRewriteWithoutComments, title));
+ }
+ }
+
+ protected Vector getTrail(List stmts) {
+ final Vector trail = new Vector();
+
+ nameTrail = new HashMap();
+ final Container trailCounter = new Container(NULL_INTEGER);
+
+ for (IASTNode node : stmts) {
+ node.accept(new CPPASTAllVisitor() {
+ @Override
+ public int visitAll(IASTNode node) {
+
+ if (node instanceof IASTComment) {
+ // Visit Comment, but don't add them to the trail
+ return super.visitAll(node);
+ } else if (node instanceof IASTNamedTypeSpecifier) {
+ // Skip if somewhere is a named Type Specifier
+ trail.add(node);
+ return PROCESS_SKIP;
+ } else if (node instanceof IASTName) {
+ if (node instanceof ICPPASTConversionName && node instanceof ICPPASTOperatorName
+ && node instanceof ICPPASTTemplateId) {
+ trail.add(node);
+ return super.visitAll(node);
+ } else {
+ // Save Name Sequenz Number
+ IASTName name = (IASTName) node;
+ TrailName trailName = new TrailName();
+ int actCount = trailCounter.getObject().intValue();
+ if (nameTrail.containsKey(name.getRawSignature())) {
+ Integer value = nameTrail.get(name.getRawSignature());
+ actCount = value.intValue();
+ } else {
+ trailCounter.setObject(Integer.valueOf(++actCount));
+ nameTrail.put(name.getRawSignature(), trailCounter.getObject());
+ }
+ trailName.setNameNumber(actCount);
+ trailName.setRealName(name);
+
+ if (info.getReturnVariable() != null
+ && info.getReturnVariable().getName().getRawSignature().equals(
+ name.getRawSignature())) {
+ returnNumber.setObject(Integer.valueOf(actCount));
+ }
+
+ // Save type informations for the name
+ IBinding bind = name.resolveBinding();
+ IASTName[] declNames = name.getTranslationUnit().getDeclarationsInAST(bind);
+ if (declNames.length > 0) {
+ IASTNode tmpNode = ASTHelper.getDeclarationForNode(declNames[0]);
+
+ IBinding declbind = declNames[0].resolveBinding();
+ if (declbind instanceof ICPPBinding) {
+ ICPPBinding cppBind = (ICPPBinding) declbind;
+ try {
+ trailName.setGloballyQualified(cppBind.isGloballyQualified());
+ } catch (DOMException e) {
+ ILog logger = CUIPlugin.getDefault().getLog();
+ IStatus status = new Status(IStatus.WARNING, CUIPlugin.PLUGIN_ID,
+ IStatus.OK, e.getMessage(), e);
+
+ logger.log(status);
+ }
+ }
+
+ if (tmpNode != null) {
+ trailName.setDeclaration(tmpNode);
+ } else {
+ hasNameResolvingForSimilarError = true;
+ }
+ }
+
+ trail.add(trailName);
+ return PROCESS_SKIP;
+ }
+ } else {
+ trail.add(node);
+ return super.visitAll(node);
+ }
+ }
+ });
+
+ }
+
+ return trail;
+ }
+
+ protected boolean isStatementInTrail(IASTStatement stmt, final Vector trail) {
+ final Container same = new Container(Boolean.TRUE);
+ final TrailNodeEqualityChecker equalityChecker = new TrailNodeEqualityChecker(names, namesCounter);
+
+ stmt.accept(new CPPASTAllVisitor() {
+ @Override
+ public int visitAll(IASTNode node) {
+
+ int pos = trailPos.getObject().intValue();
+
+ if (trail.size() <= 0 || pos >= trail.size()) {
+ same.setObject(Boolean.FALSE);
+ return PROCESS_ABORT;
+ }
+
+ if (node instanceof IASTComment) {
+ // Visit Comment, but they are not in the trail
+ return super.visitAll(node);
+ }
+
+ IASTNode trailNode = trail.get(pos);
+ trailPos.setObject(Integer.valueOf(pos + 1));
+
+ if (equalityChecker.isEquals(trailNode, node)) {
+ if (node instanceof ICPPASTQualifiedName || node instanceof IASTNamedTypeSpecifier) {
+ return PROCESS_SKIP;
+ } else {
+ return super.visitAll(node);
+ }
+
+ } else {
+ same.setObject(new Boolean(false));
+ return PROCESS_ABORT;
+ }
+ }
+ });
+
+ return same.getObject().booleanValue();
+ }
+
private boolean isMethodAllreadyDefined(
IASTSimpleDeclaration methodDeclaration,
ICPPASTCompositeTypeSpecifier classDeclaration) {
@@ -777,6 +942,7 @@ public class ExtractFunctionRefactoring extends CRefactoring {
arguments.put(CRefactoringDescription.SELECTION, region.getOffset() + "," + region.getLength()); //$NON-NLS-1$
arguments.put(ExtractFunctionRefactoringDescription.NAME, info.getMethodName());
arguments.put(ExtractFunctionRefactoringDescription.VISIBILITY, info.getVisibility().toString());
+ arguments.put(ExtractFunctionRefactoringDescription.REPLACE_DUBLICATES, Boolean.toString(info.isReplaceDuplicates()));
return arguments;
}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionRefactoringDescription.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionRefactoringDescription.java
index 2f034329f75..ab641456027 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionRefactoringDescription.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionRefactoringDescription.java
@@ -32,6 +32,7 @@ import org.eclipse.cdt.internal.ui.refactoring.utils.VisibilityEnum;
public class ExtractFunctionRefactoringDescription extends CRefactoringDescription {
protected static final String NAME = "name"; //$NON-NLS-1$
protected static final String VISIBILITY = "visibility"; //$NON-NLS-1$
+ protected static final String REPLACE_DUBLICATES = "replaceDuplicates"; //$NON-NLS-1$
public ExtractFunctionRefactoringDescription(String project, String description,
String comment, Map arguments) {
@@ -46,6 +47,7 @@ public class ExtractFunctionRefactoringDescription extends CRefactoringDescripti
info.setMethodName(arguments.get(NAME));
info.setVisibility(VisibilityEnum.getEnumForStringRepresentation(arguments.get(VISIBILITY)));
+ info.setReplaceDuplicates(Boolean.parseBoolean(arguments.get(REPLACE_DUBLICATES)));
proj = getCProject();
file = getFile();
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/Messages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/Messages.java
index 4c8b1d95f28..3c9aee0dc3c 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/Messages.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/Messages.java
@@ -34,7 +34,7 @@ public final class Messages extends NLS {
public static String ExtractFunctionComposite_ReturnValue;
public static String ExtractFunctionRefactoring_CreateMethodDef;
public static String ExtractFunctionRefactoring_CreateFunctionDef;
-// public static String ExtractFunctionComposite_ReplaceDuplicates;
+ public static String ExtractFunctionComposite_ReplaceDuplicates;
public static String ExtractFunctionRefactoring_CreateMethodCall;
public static String ExtractFunctionRefactoring_CreateFunctionCall;
public static String ChooserComposite_Return;
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/SimilarFinderVisitor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/SimilarFinderVisitor.java
new file mode 100644
index 00000000000..de2e1382715
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/SimilarFinderVisitor.java
@@ -0,0 +1,146 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Institute for Software, HSR Hochschule fuer Technik
+ * Rapperswil, University of applied sciences and others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Institute for Software - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.internal.ui.refactoring.extractfunction;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Vector;
+import java.util.Map.Entry;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.text.edits.TextEditGroup;
+
+import org.eclipse.cdt.core.dom.ast.IASTName;
+import org.eclipse.cdt.core.dom.ast.IASTNode;
+import org.eclipse.cdt.core.dom.ast.IASTStatement;
+import org.eclipse.cdt.core.dom.ast.cpp.CPPASTVisitor;
+import org.eclipse.cdt.core.dom.rewrite.ASTRewrite;
+
+import org.eclipse.cdt.internal.ui.refactoring.ModificationCollector;
+import org.eclipse.cdt.internal.ui.refactoring.NodeContainer;
+import org.eclipse.cdt.internal.ui.refactoring.NodeContainer.NameInformation;
+
+final class SimilarFinderVisitor extends CPPASTVisitor {
+
+ private final ExtractFunctionRefactoring refactoring;
+
+ private final Vector trail;
+ private final IASTName name;
+ private final List stmts;
+ private int i = 0;
+ private NodeContainer similarContainer;
+ private final List stmtToReplace = new ArrayList();
+
+ private final ModificationCollector collector;
+
+ SimilarFinderVisitor(ExtractFunctionRefactoring refactoring,
+ ModificationCollector collector, Vector trail, IFile file, IASTName name,
+ List stmts, String title) {
+ this.refactoring = refactoring;
+ this.trail = trail;
+ this.name = name;
+ this.stmts = stmts;
+ this.collector = collector;
+ this.similarContainer = new NodeContainer();
+ }
+
+ {
+ shouldVisitStatements = true;
+ }
+
+ @Override
+ public int visit(IASTStatement stmt) {
+
+ boolean isAllreadyInMainRefactoring = isInSelection(stmt);
+
+ if( (!isAllreadyInMainRefactoring)
+ && this.refactoring.isStatementInTrail(stmt, trail)){
+ stmtToReplace.add(stmt);
+ similarContainer.add(stmt);
+ ++i;
+
+ if(i==stmts.size()){
+ //found similar code
+
+ boolean similarOnReturnWays = true;
+ for (NameInformation nameInfo : similarContainer.getAllAfterUsedNames()) {
+ if(this.refactoring.names.containsKey(nameInfo.getDeclaration().getRawSignature())){
+ Integer nameOrderNumber = this.refactoring.names.get(nameInfo.getDeclaration().getRawSignature());
+ if(this.refactoring.nameTrail.containsValue(nameOrderNumber)){
+ String orgName = null;
+ boolean found = false;
+ for (Entry entry : this.refactoring.nameTrail.entrySet()) {
+ if(entry.getValue().equals(nameOrderNumber)){
+ orgName = entry.getKey();
+ }
+ }
+ if(orgName != null){
+ for (NameInformation orgNameInfo : this.refactoring.container.getAllAfterUsedNamesChoosenByUser()) {
+ if( orgName.equals(orgNameInfo.getDeclaration().getRawSignature()) ){
+ found = true;
+ }
+ }
+ }
+
+ if(!found){
+ similarOnReturnWays = false;
+ }
+ }
+ }
+ }
+
+ if(similarOnReturnWays){
+ System.out.println(6);
+ IASTNode call = refactoring.getMethodCall(name,
+ this.refactoring.nameTrail, this.refactoring.names,
+ this.refactoring.container, similarContainer);
+ ASTRewrite rewrite = collector.rewriterForTranslationUnit(stmtToReplace.get(0)
+ .getTranslationUnit());
+ TextEditGroup editGroup = new TextEditGroup("Replace Dublicated Code");
+ rewrite.replace(stmtToReplace.get(0), call, editGroup);
+ if (stmtToReplace.size() > 1) {
+ for (int i = 1; i < stmtToReplace.size(); ++i) {
+ rewrite.remove(stmtToReplace.get(i), editGroup);
+ }
+ }
+ }
+
+ clear();
+ }
+
+ return PROCESS_SKIP;
+ } else {
+ clear();
+ return super.visit(stmt);
+ }
+
+ }
+
+ private boolean isInSelection(IASTStatement stmt) {
+ Listnodes = this.refactoring.container.getNodesToWrite();
+ for (IASTNode node : nodes) {
+ if(node.equals(stmt)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void clear() {
+ i = 0;
+ this.refactoring.names.clear();
+ similarContainer = new NodeContainer();
+ this.refactoring.namesCounter.setObject(ExtractFunctionRefactoring.NULL_INTEGER);
+ this.refactoring.trailPos.setObject(ExtractFunctionRefactoring.NULL_INTEGER);
+ stmtToReplace.clear();
+ }
+ }
\ No newline at end of file
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/messages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/messages.properties
index 19b02e9be22..a1612196e4c 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/messages.properties
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/messages.properties
@@ -22,7 +22,7 @@ ExtractFunctionInputPage_1=is used after the extracted block - it needs to be pa
ExtractFunctionComposite_ReturnValue=Return value:
ExtractFunctionRefactoring_CreateMethodDef=Create Method Definition
ExtractFunctionRefactoring_CreateFunctionDef=Create Function Definition
-#ExtractFunctionComposite_ReplaceDuplicates=Replace all occurrences of statements with method.
+ExtractFunctionComposite_ReplaceDuplicates=Replace all occurrences of statements with method.
ExtractFunctionRefactoring_CreateMethodCall=Create Method Call
ExtractFunctionRefactoring_CreateFunctionCall=Create Function Call
ChooserComposite_Return=Return