From 9b7e344590c0c18f739c9b96e6bf2ac0de7721a2 Mon Sep 17 00:00:00 2001 From: Emanuel Graf Date: Tue, 12 Apr 2011 09:08:19 +0000 Subject: [PATCH] Bug 339364: Toggle Function Definition Refactoring https://bugs.eclipse.org/bugs/show_bug.cgi?id=339364 --- .../resources/refactoring/NewCreationTest.rts | 47 ++ .../refactoring/NewImplementRefactoring.rts | 22 + .../ToggleCommentsClassToHeader.rts | 211 ++++++++ .../ToggleCommentsHeaderToClass.rts | 157 ++++++ .../ToggleCommentsHeaderToImpl.rts | 131 +++++ .../ToggleCommentsImplToHeader.rts | 152 ++++++ .../refactoring/ToggleCtorDtorRefactoring.rts | 266 ++++++++++ .../ToggleDefaultParameterRefactoring.rts | 108 ++++ .../refactoring/ToggleDifferentSelections.rts | 88 ++++ .../refactoring/ToggleErrorRefactoring.rts | 113 +++++ .../refactoring/ToggleFreeFunction.rts | 283 +++++++++++ .../ToggleNamespaceRefactoring.rts | 259 ++++++++++ .../refactoring/ToggleNestedRefactoring.rts | 121 +++++ .../resources/refactoring/ToggleOrdering.rts | 226 +++++++++ .../resources/refactoring/ToggleSelection.rts | 156 ++++++ .../ToggleSimpleFunctionRefactoring.rts | 126 +++++ .../refactoring/ToggleTemplateRefactoring.rts | 155 ++++++ .../refactoring/ToggleTryCatchRefactoring.rts | 297 +++++++++++ .../refactoring/ToggleVirtualFunction.rts | 105 ++++ .../refactoring/RefactoringTestSuite.java | 4 +- .../tests/refactoring/RefactoringTester.java | 3 +- .../MockToggleRefactoringTest.java | 32 ++ .../togglefunction/ToggleNodeHelperTest.java | 42 ++ .../togglefunction/ToggleRefactoringTest.java | 121 +++++ .../ToggleRefactoringTestSuite.java | 66 +++ core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF | 1 + core/org.eclipse.cdt.ui/plugin.properties | 3 + core/org.eclipse.cdt.ui/plugin.xml | 17 + .../editor/ICEditorActionDefinitionIds.java | 6 + .../ui/refactoring/IndexToASTNameHelper.java | 150 ++++++ .../togglefunction/DeclaratorFinder.java | 102 ++++ .../EmptyRefactoringDescription.java | 33 ++ .../IToggleRefactoringStrategy.java | 18 + .../togglefunction/InsertionPointFinder.java | 154 ++++++ .../refactoring/togglefunction/Messages.java | 52 ++ .../togglefunction/NotSupportedException.java | 26 + .../togglefunction/RefactoringJob.java | 81 +++ .../togglefunction/ToggleFileCreator.java | 117 +++++ .../ToggleFromClassToInHeaderStrategy.java | 116 +++++ ...ImplementationToHeaderOrClassStrategy.java | 180 +++++++ .../ToggleFromInHeaderToClassStrategy.java | 122 +++++ ...eFromInHeaderToImplementationStrategy.java | 382 +++++++++++++++ .../togglefunction/ToggleNodeHelper.java | 460 ++++++++++++++++++ .../togglefunction/ToggleRefactoring.java | 100 ++++ .../ToggleRefactoringContext.java | 201 ++++++++ .../ToggleRefactoringRunner.java | 49 ++ .../togglefunction/ToggleStrategyFactory.java | 54 ++ .../TogglingActionDelegate.java | 79 +++ .../togglefunction/messages.properties | 27 + .../cdt/ui/actions/CdtActionConstants.java | 8 + .../actions/CRefactoringActionGroup.java | 7 + .../cdt/ui/refactoring/actions/Messages.java | 4 + .../actions/ToggleFunctionAction.java | 80 +++ .../refactoring/actions/messages.properties | 1 + 54 files changed, 5919 insertions(+), 2 deletions(-) create mode 100644 core/org.eclipse.cdt.ui.tests/resources/refactoring/NewCreationTest.rts create mode 100644 core/org.eclipse.cdt.ui.tests/resources/refactoring/NewImplementRefactoring.rts create mode 100644 core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleCommentsClassToHeader.rts create mode 100644 core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleCommentsHeaderToClass.rts create mode 100644 core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleCommentsHeaderToImpl.rts create mode 100644 core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleCommentsImplToHeader.rts create mode 100644 core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleCtorDtorRefactoring.rts create mode 100644 core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleDefaultParameterRefactoring.rts create mode 100644 core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleDifferentSelections.rts create mode 100644 core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleErrorRefactoring.rts create mode 100644 core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleFreeFunction.rts create mode 100644 core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleNamespaceRefactoring.rts create mode 100644 core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleNestedRefactoring.rts create mode 100644 core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleOrdering.rts create mode 100644 core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleSelection.rts create mode 100644 core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleSimpleFunctionRefactoring.rts create mode 100644 core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleTemplateRefactoring.rts create mode 100644 core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleTryCatchRefactoring.rts create mode 100644 core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleVirtualFunction.rts create mode 100644 core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/togglefunction/MockToggleRefactoringTest.java create mode 100644 core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/togglefunction/ToggleNodeHelperTest.java create mode 100644 core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/togglefunction/ToggleRefactoringTest.java create mode 100644 core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/togglefunction/ToggleRefactoringTestSuite.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/IndexToASTNameHelper.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/DeclaratorFinder.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/EmptyRefactoringDescription.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/IToggleRefactoringStrategy.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/InsertionPointFinder.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/Messages.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/NotSupportedException.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/RefactoringJob.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleFileCreator.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleFromClassToInHeaderStrategy.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleFromImplementationToHeaderOrClassStrategy.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleFromInHeaderToClassStrategy.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleFromInHeaderToImplementationStrategy.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleNodeHelper.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleRefactoring.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleRefactoringContext.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleRefactoringRunner.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleStrategyFactory.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/TogglingActionDelegate.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/messages.properties create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/refactoring/actions/ToggleFunctionAction.java diff --git a/core/org.eclipse.cdt.ui.tests/resources/refactoring/NewCreationTest.rts b/core/org.eclipse.cdt.ui.tests/resources/refactoring/NewCreationTest.rts new file mode 100644 index 00000000000..998e7a844d2 --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/resources/refactoring/NewCreationTest.rts @@ -0,0 +1,47 @@ +//!FreefunctionFromHeaderToImpl +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +newfilecreation=true +newfiles=A.cpp +//@A.h +void /*$*/freefunction/*$$*/() { + return; +} +//= +void freefunction(); + +//@A.cpp +//= + + +#include "A.h" + +void freefunction() +{ + return; +} +//!FreefunctionFromImplToHeader +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.cpp +newfilecreation=true +newfiles=A.h +//@A.cpp +void /*$*/freefunction/*$$*/() +{ + return; +} +//= +#include "A.h" + + +//@A.h +//= + + +void freefunction() +{ + return; +} + diff --git a/core/org.eclipse.cdt.ui.tests/resources/refactoring/NewImplementRefactoring.rts b/core/org.eclipse.cdt.ui.tests/resources/refactoring/NewImplementRefactoring.rts new file mode 100644 index 00000000000..1b8b79b1022 --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/resources/refactoring/NewImplementRefactoring.rts @@ -0,0 +1,22 @@ +//!TestImplementFunctionTest +//#ch.hsr.ifs.cute.refactoringpreview.togglefunction.tests.newimplement.NewImplementRefactoringTest +//@.config +filename=A.h +//@A.h +#include +using namespace std; + +class A { + int /*$*/member/*$$*/(); +}; +//= +#include +using namespace std; + +class A { + int member() + { + return int(); + } + +}; \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleCommentsClassToHeader.rts b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleCommentsClassToHeader.rts new file mode 100644 index 00000000000..6f9e5856cc9 --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleCommentsClassToHeader.rts @@ -0,0 +1,211 @@ +//!ClassToHeaderBodyComment +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +class A { + void /*$*/member/*$$*/() + { + // return comment + return; + } +}; +//= +class A { + void member(); +}; + +inline void A::member() +{ + // return comment + return; +} + + +//!ClassToHeaderTopCommentOrder +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +class A { + // First Top Comment + // Second Top Comment + void /*$*/member/*$$*/() + { + return; + } +}; +//= +class A { + // First Top Comment + // Second Top Comment + void member(); +}; + +inline void A::member() +{ + return; +} + + +//!ClassToHeaderCatchComment +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +class A { + void /*$*/member/*$$*/() try + { + return; + } catch (int i) { + // catch comment + } +}; +//= +class A { + void member(); +}; + +inline void A::member() +try +{ + return; +} +catch(int i){ + // catch comment +} + + +//!ClassToHeaderTopComment +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +class A { + // Top comment + void /*$*/member/*$$*/() + { + return; + } +}; +//= +class A { + // Top comment + void member(); +}; + +inline void A::member() +{ + return; +} + + +//!ClassToHeaderTemplateTopComment +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +class A { + // Top comment + template + T /*$*/member/*$$*/() + { + return T(); + } +}; +//= +class A { + // Top comment + template + T member(); + +}; + +// Top comment +template inline T A::member() +{ + return T(); +} + + +//!ClassToHeaderTrailingComment +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +class A { + void /*$*/member/*$$*/() + { + return; + } // Trailing comment +}; +//= +class A { + void member(); +}; + +inline void A::member() +{ + return; +} // Trailing comment + + +//!ClassToHeaderTrailingCommentWithTryBlock +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +class A { + void /*$*/member/*$$*/() try + { + return; + } catch (int e) { + } // Trailing comment +}; +//= +class A { + void member(); +}; + +inline void A::member() +try +{ + return; +} +catch(int e){ +} + // Trailing comment + +//!ClassToHeaderTrailingMultipleCommentsInTryBlock +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +class A { + int /*$*/member/*$$*/() try + { + // aans + } /* one */ catch (int i) { + // zwaa + } /* two */ catch (int j) { + // draa + } /* three */ +}; +//= +class A { + int member(); +}; + +inline int A::member() +try +{ + // aans +} /* one */ +catch(int i){ + // zwaa +} + /* two */catch(int j){ + // draa +} + /* three */ + diff --git a/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleCommentsHeaderToClass.rts b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleCommentsHeaderToClass.rts new file mode 100644 index 00000000000..e3c4166f074 --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleCommentsHeaderToClass.rts @@ -0,0 +1,157 @@ +//!HeaderToClassBodyComment1 +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +template +class A { + T /*$*/member/*$$*/(); +}; + +template inline T A::member() { + // body comment + return T(); +} +//= +template +class A { + T member() + { + // body comment + return T(); + } +}; + + +//!HeaderToClassRetainTopComments +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +template +class A { + // First comment + // Second comment + T /*$*/member/*$$*/(); +}; + +// Third comment +// Fourth comment +template +inline T A::member() +{ + return T(); +} +//= +template +class A { + // Third comment + // Fourth comment + // First comment + // Second comment + T member() + { + return T(); + } +}; + + + + +//!HeaderToClassTryCatchComment +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +template +class A { + T /*$*/member/*$$*/(); +}; + +template inline T A::member() try { + // body comment + return T(); +} catch(int e) { + // Catch 1 +} catch(int e) { + // Catch 2 +} +//= +template +class A { + T member() + try + { + // body comment + return T(); + } + catch(int e){ + // Catch 1 + } + catch(int e){ + // Catch 2 + } +}; + + +//!HeaderToClassMultiTemplateComment +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +template +class A { + // Top Comment + template + T /*$*/member/*$$*/(); +}; + +// 2nd Top Comment +template +template +inline T A::member() { + // body comment + return T(); +} +//= +template +class A { + // Top Comment + template + T member() + { + // body comment + return T(); + } + + +}; + +// 2nd Top Comment + +//!HeaderToClassBodyComment +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +template +class A { + T /*$*/member/*$$*/(); +}; + +// Top comment +template inline T A::member() { + return T(); +} +//= +template +class A { + // Top comment + T member() + { + return T(); + } +}; + + + diff --git a/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleCommentsHeaderToImpl.rts b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleCommentsHeaderToImpl.rts new file mode 100644 index 00000000000..a5c548880a1 --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleCommentsHeaderToImpl.rts @@ -0,0 +1,131 @@ +//!HeaderToImplBodyComment +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +class A { + void /*$*/member/*$$*/(); +}; + +inline void A::member() { + // body comment + return; +} +//= +class A { + void member(); +}; + + +//@A.cpp +#include "A.h" +//= +#include "A.h" + + +void A::member() +{ + // body comment + return; +} + +//!HeaderToImplTryCatchComment +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +class A { + void /*$*/member/*$$*/(); +}; + +inline void A::member() try { + // body comment + return; +} catch /*1*/ (int e) { /*2*/ } +catch /*3*/ (int e) { /*4*/ } +//= +class A { + void member(); +}; + + +//@A.cpp +#include "A.h" +//= +#include "A.h" + + +void A::member() +try +{ + // body comment + return; +} +catch(/*1*/int e){ + /*2*/ +} +catch(/*3*/int e){ + /*4*/ +} + +//!HeaderToImplTopComment +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +class A { + void /*$*/member/*$$*/(); +}; + +// Top comment +inline void A::member() { + // body comment + return; +} +//= +class A { + void member(); +}; + + + +//@A.cpp +#include "A.h" +//= +#include "A.h" + + +// Top comment +void A::member() +{ + // body comment + return; +} + +//!HeaderToImplFreeFuncTopComment +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +// Definition comment +void /*$*/member/*$$*/() { + return; +} +//= +// Definition comment +void member(); + +//@A.cpp +#include "A.h" + +//= +#include "A.h" + + + +// Definition comment +void member() +{ + return; +} + diff --git a/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleCommentsImplToHeader.rts b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleCommentsImplToHeader.rts new file mode 100644 index 00000000000..46e33666500 --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleCommentsImplToHeader.rts @@ -0,0 +1,152 @@ +//!ImplToHeaderBodyComment +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.cpp +//@A.cpp +#include "A.h" + +void A::/*$*/member/*$$*/() +{ + // body comment + return; +} +//= +#include "A.h" + + +//@A.h +class A { + void member(); +}; +//= +class A { + void member() + { + // body comment + return; + } +}; +//!ImplToHeaderTopComment +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.cpp +//@A.cpp +#include "A.h" + +// Definition comment +void A::/*$*/member/*$$*/() +{ + return; +} +//= +#include "A.h" + +// Definition comment + +//@A.h +class A { + void member(); +}; +//= +class A { + // Definition comment + void member() + { + return; + } +}; +//!ImplToHeaderTryCatchComment +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.cpp +//@A.cpp +#include "A.h" + +// Definition comment +void A::/*$*/member/*$$*/() try +{ + return; +} /*1*/ catch (int e) { /*2*/ } /*3*/ catch (int e) { /*4*/ } +//= +#include "A.h" + +// Definition comment + +//@A.h +class A { + void member(); +}; +//= +class A { + // Definition comment + void member() + try + { + return; + } /*1*/ + catch(int e){ + /*2*/ + } + /*3*/catch(int e){ + /*4*/ + } +}; +//!ImplToHeaderBodyCommentWithoutDeclaration +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.cpp +//@A.cpp +#include "A.h" + +void /*$*/member/*$$*/() +{ + // body comment + return; +} +//= +#include "A.h" + + +//@A.h + +//= + + + +void member() +{ + // body comment + return; +} + +//!ImplToHeaderTopCommentWithoutDeclaration +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.cpp +//@A.cpp +#include "A.h" + +// Top comment +void /*$*/member/*$$*/() +{ + // body comment + return; +} +//= +#include "A.h" + +// Top comment + +//@A.h + +//= + + + +// Top comment +void member() +{ + // body comment + return; +} + diff --git a/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleCtorDtorRefactoring.rts b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleCtorDtorRefactoring.rts new file mode 100644 index 00000000000..8e84291e3d0 --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleCtorDtorRefactoring.rts @@ -0,0 +1,266 @@ +//!TestConstructorToggleInClassToInHeader +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +#include + +class A { +private: + int a; + int b; +public: + /*$*/A/*$$*/(int x, int y) + :a(x), b(y) + {} + ~A() + { + } +}; +//= +#include + +class A { +private: + int a; + int b; +public: + A(int x, int y); + ~A() + { + } +}; + +inline A::A(int x, int y) +:a(x), b(y) +{ +} + + +//!TestConstructorToggleInHeaderToImplementation +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +#include + +class A { +private: + int a; + int b; +public: + A(int x, int y); + ~A() + { + } +}; + +inline A::/*$*/A/*$$*/(int x, int y) +:a(x), b(y) +{ +} +//= +#include + +class A { +private: + int a; + int b; +public: + A(int x, int y); + ~A() + { + } +}; + + +//@A.cpp +#include "A.h" + +int main() { + return 0; +} +//= +#include "A.h" + +int main() { + return 0; +} + +A::A(int x, int y) +:a(x), b(y) +{ +} + + +//!TestConstructorToggleInImplementationToClass +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.cpp +//@A.cpp +#include "A.h" + +A::/*$*/A/*$$*/(int x, int y) +:a(x), b(y) +{ +} + +int main() { + return 0; +} +//= +#include "A.h" + + + +int main() { + return 0; +} +//@A.h +#include + +class A { + A(int x, int y); + ~A() + { + } +}; +//= +#include + +class A { + A(int x, int y) + :a(x), b(y) + { + } + ~A() + { + } +}; +//!TestDestructorToggleInClassToInHeader +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +#include + +class A { +private: + int a; + int b; +public: + /*$*/~A/*$$*/() + {} +}; +//= +#include + +class A { +private: + int a; + int b; +public: + ~A(); +}; + +inline A::~A() +{ +} + + +//!TestDestructorToggleInHeaderToImplementation +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +#include + +class A { +private: + int a; + int b; +public: + ~A(); +}; + +inline /*$*/A::~A/*$$*/() +{ +} +//= +#include + +class A { +private: + int a; + int b; +public: + ~A(); +}; + + +//@A.cpp +#include "A.h" + +int main() { + return 0; +} +//= +#include "A.h" + +int main() { + return 0; +} + +A::~A() +{ +} + + +//!TestDestructorToggleInImplementationToClass +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.cpp +//@A.cpp +#include "A.h" + +/*$*/A::~A/*$$*/() +{ + int x; + int y; + return; +} + +int main() { + return 0; +} +//= +#include "A.h" + + + +int main() { + return 0; +} +//@A.h +#include + +class A { + A(int x, int y) + :a(x), b(y) + {} + ~A(); +}; +//= +#include + +class A { + A(int x, int y) + :a(x), b(y) + {} + ~A() + { + int x; + int y; + return; + } +}; diff --git a/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleDefaultParameterRefactoring.rts b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleDefaultParameterRefactoring.rts new file mode 100644 index 00000000000..53c44c6cd8f --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleDefaultParameterRefactoring.rts @@ -0,0 +1,108 @@ +//!TestDefaultParameterInitializerInClassToInHeader +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +#include + +class A { + void /*$*/member/*$$*/(int a=0, int b=0) + { + return; + } +}; +//= +#include + +class A { + void member(int a=0, int b=0); +}; + +inline void A::member(int a, int b) +{ + return; +} + + +//!TestDefaultParameterInitializerInHeaderToImplementation +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +#include + +class A { + void member(int a=0, int b=0); +}; + +inline void /*$*/A::member/*$$*/(int a, int b) +{ + return; +} +//= +#include + +class A { + void member(int a=0, int b=0); +}; + + +//@A.cpp +#include "A.h" + +int main() { + return 0; +} +//= +#include "A.h" + +int main() { + return 0; +} + +void A::member(int a, int b) +{ + return; +} + + +//!TestDefaultParameterInitializerInImplementationToClass +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.cpp +//@A.cpp +#include "A.h" + +void A::/*$*/member/*$$*/(int a, int b) +{ + return; +} + +int main() +{ + return 0; +} +//= +#include "A.h" + + + +int main() +{ + return 0; +} +//@A.h +#include + +class A { + void member(int a = 0, int b = 0); +}; +//= +#include + +class A { + void member(int a = 0, int b = 0) + { + return; + } +}; \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleDifferentSelections.rts b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleDifferentSelections.rts new file mode 100644 index 00000000000..f885a692437 --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleDifferentSelections.rts @@ -0,0 +1,88 @@ +//!TestImplementationToClassWithDefintionSelected +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.cpp +//@A.cpp +#include "A.h" + +int main() { + return 0; +} + +void N::A::/*$*/foo/*$$*/() +{ + return; +} +//= +#include "A.h" + +int main() { + return 0; +} + + +//@A.h +#include +#include + +namespace N { + class A { + void foo(); + }; +} +//= +#include +#include + +namespace N { + class A { + void foo() + { + return; + } + }; +} +//!TestImplementationToClassWithDeclarationSelected +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +#include +#include + +namespace N { + class A { + void /*$*/foo/*$$*/(); + }; +} + +//= +#include +#include + +namespace N { + class A { + void foo() + { + return; + } + }; +} + +//@A.cpp +#include "A.h" + +int main() { + return 0; +} +void N::A::foo() +{ + return; +} +//= +#include "A.h" + +int main() { + return 0; +} + diff --git a/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleErrorRefactoring.rts b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleErrorRefactoring.rts new file mode 100644 index 00000000000..bdeca96e7ce --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleErrorRefactoring.rts @@ -0,0 +1,113 @@ +//!TestNotSupportedVariableSelection +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +fatalerror=true +//@A.h +#include + +class A { +public: + void foo() + { + } +private: + int /*$*/x/*$$*/; +}; + +//!TestNotSupportedNoDefinition +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +fatalerror=true +//@A.h +#include + +class A { +public: + void /*$*/foo/*$$*/(); +}; +//@A.cpp +#include "A.h" + +int main() +{ + return 0; +} + +//!TestNotSupportedNoTranslationunit +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +fatalerror=true +//@A.h +#include + +class A { +public: + void /*$*/foo/*$$*/(); +}; + +//!TestMultipleDeclarations +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +fatalerror=true +//@A.h +#include + +class A { + void /*$*/foo/*$$*/(); + void foo(); +}; +//@A.cpp +#include "A.h" + +int main() +{ + return 0; +} + +//!TestMultipledefinitions +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +fatalerror=true +//@A.h +#include + +class A { + void foo(); + void /*$*/foo/*$$*/() + { + return; + } +}; + +void blah() +{ + +} + +inline void A::foo() +{ + return; +} +//@A.cpp +#include "A.h" + +int main() +{ + return 0; +} + +//!TestNotSupportedNestedFunctions +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +fatalerror=true +//@A.h +#include + +class A { + void foo() + { + void /*$*/bar/*$$*/() { + } + } +}; \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleFreeFunction.rts b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleFreeFunction.rts new file mode 100644 index 00000000000..1166da4888c --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleFreeFunction.rts @@ -0,0 +1,283 @@ +//!TestFreeFunctionToggleFromHeaderToImplementation +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +#include + +class A { +private: + int a; + int b; +public: + A(int x, int y) + :a(x), b(y) + {} + ~A() + { + } +}; + +int /*$*/freeFunction/*$$*/(int *a, int & b) { + return 42; +} +//= +#include + +class A { +private: + int a; + int b; +public: + A(int x, int y) + :a(x), b(y) + {} + ~A() + { + } +}; + +int freeFunction(int *a, int & b); + +//@A.cpp +#include "A.h" + +int main() { + return 0; +} +//= +#include "A.h" + +int main() { + return 0; +} + +int freeFunction(int *a, int & b) +{ + return 42; +} + + +//!TestFreeFunctionToggleFromImplementationToHeaderWithDeclaration +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.cpp +//@A.cpp +#include "A.h" + +int main() { + return 0; +} + +int /*$*/freeFunction/*$$*/(int *a, int & b) +{ + return 42; +} +//= +#include "A.h" + +int main() { + return 0; +} + + +//@A.h +#include + +class A { +private: + int a; + int b; +public: + A(int x, int y) + :a(x), b(y) + {} + ~A() + { + } +}; + +int freeFunction(int *a, int & b); +//= +#include + +class A { +private: + int a; + int b; +public: + A(int x, int y) + :a(x), b(y) + {} + ~A() + { + } +}; + +int freeFunction(int *a, int & b) +{ + return 42; +} + + +//!TestFreeFunctionToggleFromImplementationToHeaderWithOutDeclaration +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.cpp +//@A.cpp +#include "A.h" + +int main() { + return 0; +} + +int /*$*/freeFunction/*$$*/(int *a, int & b) +try { + return 42; +} catch (std::exception & e) +{ +} +//= +#include "A.h" + +int main() { + return 0; +} + + +//@A.h +#include + +class A { +private: + int a; + int b; +public: + A(int x, int y) + :a(x), b(y) + {} + ~A() + { + } +}; + +//= +#include + +class A { +private: + int a; + int b; +public: + A(int x, int y) + :a(x), b(y) + {} + ~A() + { + } +}; + +int freeFunction(int *a, int & b) +try +{ + return 42; +} +catch(std::exception & e){ +} + + + +//!TestFreeFunction +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +int /*$*/freeFunction/*$$*/() +{ + return 42; +} +//= +int freeFunction(); + +//@A.cpp +#include "A.h" +//= +#include "A.h" + + +int freeFunction() +{ + return 42; +} + +//!TestQualifiedNameToggle +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.cpp +fatalerror=true +//@A.cpp +#include "A.h" + +int /*$*/A::freefunction/*$$*/() +{ + return 42; +} +//= +#include "A.h" + +int A::freefunction() +{ + return 42; +} + +//!TestNamespacedFreeFunction +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +#ifndef A_H_ +#define A_H_ + +#include + +namespace N { + void /*$*/freefunction/*$$*/() + { + return; + } +} + +#endif /* A_H_ */ +//= +#ifndef A_H_ +#define A_H_ + +#include + +namespace N { + void freefunction(); +} + +#endif /* A_H_ */ +//@A.cpp +#include "A.h" + +int main() { + return 0; +} +//= +#include "A.h" + +int main() { + return 0; +} + +namespace N +{ + void freefunction() + { + return; + } + +} + diff --git a/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleNamespaceRefactoring.rts b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleNamespaceRefactoring.rts new file mode 100644 index 00000000000..568bf32d6ba --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleNamespaceRefactoring.rts @@ -0,0 +1,259 @@ +//!TestSimpleNamespaceInClassToInHeader +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +#include +#include + +namespace N { + class A { + void /*$*/foo/*$$*/() { + return; + } + }; +} +//= +#include +#include + +namespace N { + class A { + void foo(); + }; + inline void A::foo() + { + return; + } +} +//!TestSimpleNamespaceInHeaderToImplementationWithinNSDefinition +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +#include +#include + +namespace N { + class A { + void foo(); + }; + inline void A::/*$*/foo/*$$*/() + { + return; + } +} +//= +#include +#include + +namespace N { + class A { + void foo(); + }; +} +//@A.cpp +#include "A.h" + +int main() { + return 0; +} +//= +#include "A.h" + +int main() { + return 0; +} + +namespace N +{ + void A::foo() + { + return; + } + +} + +//!TestSimpleNamespaceInHeaderToImplementationWithNSDefinitionInImpl +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +#include +#include + +namespace N { + class A { + void foo(); + }; + inline void A::/*$*/foo/*$$*/() + { + return; + } + +} +//= +#include +#include + +namespace N { + class A { + void foo(); + }; + +} +//@A.cpp +#include "A.h" + +int main() { + return 0; +} + +namespace N +{ +} +//= +#include "A.h" + +int main() { + return 0; +} + +namespace N +{ + void A::foo() + { + return; + } +} +//!TestSimpleNamespaceInHeaderToImplementationWithNamespaceQualifiedName +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +#include +#include + +namespace N { + class A { + void foo(); + }; +} + +inline void /*$*/N::A::foo/*$$*/() +{ + return; +} +//= +#include +#include + +namespace N { + class A { + void foo(); + }; +} + + +//@A.cpp +#include "A.h" + +int main() { + return 0; +} +//= +#include "A.h" + +int main() { + return 0; +} + +namespace N +{ + void A::foo() + { + return; + } + +} + +//!TestSimpleNamespaceFromImplementationToInHeader +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.cpp +//@A.cpp +#include "A.h" + +void /*$*/N::A::foo/*$$*/() +{ + return; +} + +int main() +{ + return 0; +} +//= +#include "A.h" + + + +int main() +{ + return 0; +} +//@A.h +#include + +namespace N { + class A { + void foo(); + }; +} +//= +#include + +namespace N { + class A { + void foo() + { + return; + } + }; +} +//!TestRemoveEmptyNamespaceFromImplentation +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.cpp +//@A.cpp +#include "A.h" + +namespace N { + void /*$*/A::foo/*$$*/() + { + return; + } +} +//= +#include "A.h" + + +//@A.h +#include + +namespace N { + class A { + void foo(); + }; +} +//= +#include + +namespace N { + class A { + void foo() + { + return; + } + }; +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleNestedRefactoring.rts b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleNestedRefactoring.rts new file mode 100644 index 00000000000..012f07668e2 --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleNestedRefactoring.rts @@ -0,0 +1,121 @@ +//!TestNestedClassInClassToInHeader +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +#include + +class A { + class B { + void /*$*/member/*$$*/(int a, int b) { + return; + } + }; +}; +//= +#include + +class A { + class B { + void member(int a, int b); + }; +}; + +inline void A::B::member(int a, int b) +{ + return; +} + + +//!TestNestedClassInHeaderToImplementation +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +#include + +class A { + class B { + void member(int a, int b); + }; +}; + +inline void A::B::/*$*/member/*$$*/(int a, int b) +{ + return; +} +//= +#include + +class A { + class B { + void member(int a, int b); + }; +}; + + +//@A.cpp +#include "A.h" + +int main() +{ + return 0; +} +//= +#include "A.h" + +int main() +{ + return 0; +} + +void A::B::member(int a, int b) +{ + return; +} + + +//!TestNestedClassInImplementationToClass +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.cpp +//@A.cpp +#include "A.h" + +int main() +{ + return 0; +} + +void A::B::/*$*/member/*$$*/(int a, int b) +{ + return; +} +//= +#include "A.h" + +int main() +{ + return 0; +} + + +//@A.h +#include + +class A { + class B { + void member(int a, int b); + }; +}; +//= +#include + +class A { + class B { + void member(int a, int b) + { + return; + } + }; +}; diff --git a/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleOrdering.rts b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleOrdering.rts new file mode 100644 index 00000000000..005ad09617f --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleOrdering.rts @@ -0,0 +1,226 @@ +//!TestCorrectOrderingInClassToInHeader +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +#include + +class A { +public: + void func1(); + void /*$*/func2/*$$*/() + { + } + void func3(); + void func4() + { + } +}; + +inline void A::func1() +{ +} + +inline void A::func3() +{ +} +//= +#include + +class A { +public: + void func1(); + void func2(); + void func3(); + void func4() + { + } +}; + +inline void A::func1() +{ +} + +inline void A::func2() +{ +} + +inline void A::func3() +{ +} +//!TestCorrectOrderingInHeaderToImplementation +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +#include + +class A { +public: + void func1(); + void func2(); + void func3(); + void func4() + { + } +}; + +inline void A::/*$*/func2/*$$*/() +{ + return; +} + +//= +#include + +class A { +public: + void func1(); + void func2(); + void func3(); + void func4() + { + } +}; + + + +//@A.cpp +#include "A.h" + +int main() +{ + return 0; +} + +void A::func1() +{ + return; +} + +void A::func3() +{ + return; +} +//= +#include "A.h" + +int main() +{ + return 0; +} + +void A::func1() +{ + return; +} + +void A::func2() +{ + return; +} + +void A::func3() +{ + return; +} +//!TestCorrectTemplateOrderingInClassToInHeader +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +#include + +template +class A { +public: + void func1(); + void /*$*/func2/*$$*/() + { + } + void func3(); + void func4() + { + } +}; + +template inline void A::func1() +{ +} +template inline void A::func3() +{ +} +//= +#include + +template +class A { +public: + void func1(); + void func2(); + void func3(); + void func4() + { + } +}; + +template inline void A::func1() +{ +} +template inline void A::func2() +{ +} + +template inline void A::func3() +{ +} +//!TestCorrectTemplateOrderingInHeaderToInClass +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +#include + +template +class A { +public: + void func1(); + void func2(); + void func3(); + void func4() + { + } +}; + +template inline void A::func1() +{ +} +template inline void A::/*$*/func2/*$$*/() +{ +} +template inline void A::func3() +{ +} +//= +#include + +template +class A { +public: + void func1(); + void func2() + { + } + void func3(); + void func4() + { + } +}; + +template inline void A::func1() +{ +} + +template inline void A::func3() +{ +} diff --git a/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleSelection.rts b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleSelection.rts new file mode 100644 index 00000000000..f8cb1c31fb7 --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleSelection.rts @@ -0,0 +1,156 @@ +//!TestZeroLengthSelection +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +class A { + void me/*$*//*$$*/mber() + { + return; + } +}; +//= +class A { + void member(); +}; + +inline void A::member() +{ + return; +} + + +//!TestSubstringSelection +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +class A { + void m/*$*/e/*$$*/mber() + { + return; + } +}; +//= +class A { + void member(); +}; + +inline void A::member() +{ + return; +} + + +//!TestBodySelection +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +class A { + void member() + { + r/*$*//*$$*/eturn; + } +}; +//= +class A { + void member(); +}; + +inline void A::member() +{ + return; +} + + +//!TestBodySelectionWithConfusingName +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +class A { + void member() + { + int /*$*/abcd/*$$*/ = 42; + return; + } +}; +//= +class A { + void member(); +}; + +inline void A::member() +{ + int abcd = 42; + return; +} + + +//!TestLeftBorderSelection +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +class A { + /*$*//*$$*/void member() + { + return; + } +}; +//= +class A { + void member(); +}; + +inline void A::member() +{ + return; +} + + +//!TestRightBorderSelection +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +class A { + void member() + { + return; + }/*$*//*$$*/ +}; +//= +class A { + void member(); +}; + +inline void A::member() +{ + return; +} + + +//!TestOverlappingSelection +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +class A { + vo/*$*/id member() + { + ret/*$$*/urn; + } +}; +//= +class A { + void member(); +}; + +inline void A::member() +{ + return; +} + + diff --git a/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleSimpleFunctionRefactoring.rts b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleSimpleFunctionRefactoring.rts new file mode 100644 index 00000000000..8e9492deb0d --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleSimpleFunctionRefactoring.rts @@ -0,0 +1,126 @@ +//!TestSimpleFunctionInClassToInHeader +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +#include + +class A { +public: + int /*$*/function/*$$*/() + { + return 0; + } +private: + int a; +}; +//= +#include + +class A { +public: + int function(); +private: + int a; +}; + +inline int A::function() +{ + return 0; +} + + +//!TestSimpleFunctionInHeaderToImplementation +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +#include + +class A { +public: + int function(); +private: + int a; +}; + +inline int A::/*$*/function/*$$*/() +{ + return 0; +} +//= +#include + +class A { +public: + int function(); +private: + int a; +}; + + +//@A.cpp +#include "A.h" + +int main() { + return 0; +} +//= +#include "A.h" + +int main() { + return 0; +} + +int A::function() +{ + return 0; +} + + +//!TestSimpleFunctionInImplementationToInClass +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.cpp +//@A.cpp +#include "A.h" + +int A::/*$*/function/*$$*/() +{ + return 0; +} + +int main() +{ + return 0; +} +//= +#include "A.h" + + + +int main() +{ + return 0; +} +//@A.h +#include + +class A { +public: + int function(); +private: + int a; +}; +//= +#include + +class A { +public: + int function() + { + return 0; + } +private: + int a; +}; diff --git a/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleTemplateRefactoring.rts b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleTemplateRefactoring.rts new file mode 100644 index 00000000000..5d50b808b0d --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleTemplateRefactoring.rts @@ -0,0 +1,155 @@ +//!TestTemplateFunctionInClassToInHeader +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +#include + +template +class A { + class B { + T /*$*/member/*$$*/() + { + return T(); + } + }; +}; +//= +#include + +template +class A { + class B { + T member(); + }; +}; + +template inline T A::B::member() +{ + return T(); +} + + +//!TestTemplateFunctionInHeaderToInClass +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +#include + +template +class A { + class B { + T member(); + }; + +}; + +template inline T A::B::/*$*/member/*$$*/() +{ + return T(); +} +//= +#include + +template +class A { + class B { + T member() + { + return T(); + } + }; + +}; + + +//!TestTemplateFunctionInHeaderToInClassWithTemplateSelected +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +class A { + tem/*$*/plate/*$$*/ + T foo() { + return T(); + } +}; +//= +class A { + template + T foo(); + +}; + +template inline T A::foo() +{ + return T(); +} + + +//!TestComplexTemplateFunctionFromInClassToInheader +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +template +class A +{ +public: + template + void /*$*/foo/*$$*/(const U & u, const V &v) + { + return; + } +}; +//= +template +class A +{ +public: + template + void foo(const U & u, const V &v); + +}; + +template template inline void A::foo(const U & u, const V & v) +{ + return; +} + + +//!TestComplexTemplateFunctionFromInHeaderToInClass +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +template +class A +{ +public: + template + void /*$*/foo/*$$*/(const U & u, const V &v); + +}; + +template template inline void A::foo(const U & u, const V & v) +{ + return; +} +//= +template +class A +{ +public: + template + void foo(const U & u, const V &v) + { + return; + } + + + +}; + + diff --git a/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleTryCatchRefactoring.rts b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleTryCatchRefactoring.rts new file mode 100644 index 00000000000..41aec3dac98 --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleTryCatchRefactoring.rts @@ -0,0 +1,297 @@ +//!TestTryCatchFromInClassToInHeader +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +#include +#include + +class A { + void /*$*/member/*$$*/(int a, int b) + try + { + return; + } catch (std::exception & e1) + { + return; + } +}; +//= +#include +#include + +class A { + void member(int a, int b); +}; + +inline void A::member(int a, int b) +try +{ + return; +} +catch(std::exception & e1){ + return; +} + + +//!TestTryCatchFromInHeaderToImplementation +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +#include +#include + +class A { + void member(int a, int b); +}; + +inline void /*$*/A::member/*$$*/(int a, int b) +try +{ + return; +} +catch(std::exception & e1){ + return; +} +//= +#include +#include + +class A { + void member(int a, int b); +}; + + +//@A.cpp +#include "A.h" + +int main() { + return 0; +} +//= +#include "A.h" + +int main() { + return 0; +} + +void A::member(int a, int b) +try +{ + return; +} +catch(std::exception & e1){ + return; +} + + +//!TestTryCatchFromInImplementationToClass +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.cpp +//@A.cpp +#include +#include "A.h" + +void A::/*$*/member/*$$*/() +try +{ + return; +} +catch(std::exception & e1) +{ + return; +} + +int main() +{ + return 0; +} +//= +#include +#include "A.h" + + + +int main() +{ + return 0; +} +//@A.h +#include + +class A { + void member(); +}; +//= +#include + +class A { + void member() + try + { + return; + } + catch(std::exception & e1){ + return; + } +}; +//!TestMultipleTryCatchFromInClassToInHeader +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +#include +#include + +class A { + void /*$*/member/*$$*/(int a, int b) + try + { + return; + } catch (std::exception & e1) + { + return; + } catch (std::exception & e2) + { + return; + } +}; +//= +#include +#include + +class A { + void member(int a, int b); +}; + +inline void A::member(int a, int b) +try +{ + return; +} +catch(std::exception & e1){ + return; +} +catch(std::exception & e2){ + return; +} + + +//!TestMultipleTryCatchFromInHeaderToImplementation +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h +#include +#include + +class A { + void member(int a, int b); +}; + +inline void /*$*/A::member/*$$*/(int a, int b) +try +{ + return; +} +catch(std::exception & e1){ + return; +} +catch(std::exception & e2){ + return; +} +//= +#include +#include + +class A { + void member(int a, int b); +}; + + +//@A.cpp +#include "A.h" + +int main() { + return 0; +} +//= +#include "A.h" + +int main() { + return 0; +} + +void A::member(int a, int b) +try +{ + return; +} +catch(std::exception & e1){ + return; +} +catch(std::exception & e2){ + return; +} + + +//!TestMultipleTryCatchFromInImplementationToClass +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.cpp +//@A.cpp +#include +#include "A.h" + +void A::/*$*/member/*$$*/() +try +{ + return; +} +catch(std::exception & e1) +{ + return; +} +catch(std::exception & e2) +{ + return; +} + +int main() +{ + return 0; +} +//= +#include +#include "A.h" + + + +int main() +{ + return 0; +} +//@A.h +#include + +class A { + void member(); +}; +//= +#include + +class A { + void member() + try + { + return; + } + catch(std::exception & e1){ + return; + } + catch(std::exception & e2){ + return; + } +}; \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleVirtualFunction.rts b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleVirtualFunction.rts new file mode 100644 index 00000000000..9c1ef038bf0 --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ToggleVirtualFunction.rts @@ -0,0 +1,105 @@ +//!TestRemoveVirtualSpecifierFromClassToInheader +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h + +class A { + virtual int /*$*/foo/*$$*/() + { + return 0; + } +}; +//= + +class A { + virtual int foo(); +}; + +inline int A::foo() +{ + return 0; +} + + +//!TestVirtualSpecifierFromInHeaderToImplementation +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//%CPP +//@.config +filename=A.h +//@A.h + +class A { + virtual int /*$*/foo/*$$*/(); +}; + +inline int A::foo() +{ + return 0; +} +//= + +class A { + virtual int foo(); +}; + + +//@A.cpp +#include "A.h" + +int main() +{ + return 0; +} +//= +#include "A.h" + +int main() +{ + return 0; +} + +int A::foo() +{ + return 0; +} + + +//!TestVirtualSpecifierFromImplementationToHeader +//#org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest +//@.config +filename=A.h +//@A.h + +class A { + virtual int /*$*/foo/*$$*/(); +}; +//= + +class A { + virtual int foo() + { + return 0; + } +}; +//@A.cpp +#include "A.h" + +int main() +{ + return 0; +} + +int A::foo() +{ + return 0; +} +//= +#include "A.h" + +int main() +{ + return 0; +} + + diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/RefactoringTestSuite.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/RefactoringTestSuite.java index 4d9adc3cd3e..0420da30cef 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/RefactoringTestSuite.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/RefactoringTestSuite.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2009 Institute for Software, HSR Hochschule fuer Technik + * Copyright (c) 2008, 2011 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 @@ -22,6 +22,7 @@ import org.eclipse.cdt.ui.tests.refactoring.gettersandsetters.GenerateGettersAnd import org.eclipse.cdt.ui.tests.refactoring.hidemethod.HideMethodTestSuite; import org.eclipse.cdt.ui.tests.refactoring.implementmethod.ImplementMethodTestSuite; import org.eclipse.cdt.ui.tests.refactoring.rename.RenameRegressionTests; +import org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTestSuite; import org.eclipse.cdt.ui.tests.refactoring.utils.UtilTestSuite; /** @@ -39,6 +40,7 @@ public class RefactoringTestSuite extends TestSuite { suite.addTest(GenerateGettersAndSettersTestSuite.suite()); suite.addTest(ImplementMethodTestSuite.suite()); suite.addTest(ExtractLocalVariableTestSuite.suite()); + suite.addTest(ToggleRefactoringTestSuite.suite()); return suite; } } diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/RefactoringTester.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/RefactoringTester.java index 61f6a5d10b0..848783ec2a5 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/RefactoringTester.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/RefactoringTester.java @@ -144,7 +144,8 @@ public class RefactoringTester extends TestSuite{ } catch (ClassNotFoundException e) { throw new Exception("Unknown test class " + className); //$NON-NLS-1$ } catch (Exception e) { - throw new Exception(e.getClass().getSimpleName() + " diring creation of test " + className, e); //$NON-NLS-1$ + throw new Exception(e.getClass().getSimpleName() + + " during creation of test " + className, e); //$NON-NLS-1$ } } diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/togglefunction/MockToggleRefactoringTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/togglefunction/MockToggleRefactoringTest.java new file mode 100644 index 00000000000..b4af0209612 --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/togglefunction/MockToggleRefactoringTest.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2011 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.ui.tests.refactoring.togglefunction; + +import org.eclipse.core.resources.IFile; +import org.eclipse.jface.text.TextSelection; + +import org.eclipse.cdt.core.model.ICProject; + +import org.eclipse.cdt.internal.ui.refactoring.togglefunction.ToggleRefactoring; +import org.eclipse.cdt.internal.ui.refactoring.togglefunction.ToggleRefactoringContext; + +public class MockToggleRefactoringTest extends ToggleRefactoring { + + public MockToggleRefactoringTest(IFile file, TextSelection selection, + ICProject proj) { + super(file, selection, proj); + } + + public ToggleRefactoringContext getContext() { + return context; + } +} diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/togglefunction/ToggleNodeHelperTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/togglefunction/ToggleNodeHelperTest.java new file mode 100644 index 00000000000..b8f2b2aaa54 --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/togglefunction/ToggleNodeHelperTest.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2011 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: + * Emanuel Graf - initial API and implementation + ******************************************************************************/ +package org.eclipse.cdt.ui.tests.refactoring.togglefunction; + +import junit.framework.TestCase; + +import org.junit.Test; + +import org.eclipse.cdt.internal.ui.refactoring.togglefunction.ToggleNodeHelper; + +/** + * @author egraf + * + */ +public class ToggleNodeHelperTest extends TestCase { + + /** + * Test method for {@link org.eclipse.cdt.internal.ui.refactoring.togglefunction.ToggleNodeHelper#getFilenameWithoutExtension(java.lang.String)}. + */ + @Test + public void testGetFilenameWithoutExtension1() { + assertEquals("MyClass", ToggleNodeHelper.getFilenameWithoutExtension("MyClass.h")); + } + + /** + * Test method for {@link org.eclipse.cdt.internal.ui.refactoring.togglefunction.ToggleNodeHelper#getFilenameWithoutExtension(java.lang.String)}. + */ + @Test + public void testGetFilenameWithoutExtension2() { + assertEquals("My.Class", ToggleNodeHelper.getFilenameWithoutExtension("My.Class.h")); + } + +} diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/togglefunction/ToggleRefactoringTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/togglefunction/ToggleRefactoringTest.java new file mode 100644 index 00000000000..9d45da70813 --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/togglefunction/ToggleRefactoringTest.java @@ -0,0 +1,121 @@ +/******************************************************************************* + * Copyright (c) 2011 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.ui.tests.refactoring.togglefunction; + +import java.util.Collection; +import java.util.Properties; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.Path; +import org.eclipse.ltk.core.refactoring.Change; +import org.eclipse.ltk.core.refactoring.Refactoring; +import org.eclipse.ltk.core.refactoring.RefactoringStatus; + +import org.eclipse.cdt.core.parser.tests.rewrite.TestHelper; +import org.eclipse.cdt.ui.tests.refactoring.RefactoringTest; +import org.eclipse.cdt.ui.tests.refactoring.TestSourceFile; + +public class ToggleRefactoringTest extends RefactoringTest { + + private boolean fatalError; + private boolean newFileCreation; + private String[] newfiles; + + public ToggleRefactoringTest(String name, Collection files) { + super(name, files); + } + + @Override + protected void configureRefactoring(Properties refactoringProperties) { + fatalError = Boolean.valueOf(refactoringProperties.getProperty("fatalerror", "false")).booleanValue(); //$NON-NLS-1$ //$NON-NLS-2$ + newFileCreation = Boolean.valueOf(refactoringProperties.getProperty("newfilecreation", "false")).booleanValue(); + newfiles = separateNewFiles(refactoringProperties); + } + + private String[] separateNewFiles(Properties refactoringProperties) { + return String.valueOf(refactoringProperties.getProperty("newfiles", "")).replace(" ", "").split(","); + } + + @Override + protected void runTest() throws Throwable { + MockToggleRefactoringTest refactoring = new MockToggleRefactoringTest(project.getFile(fileName), selection, cproject); + if (newFileCreation) { + pre_executeNewFileCreationRefactoring(refactoring); + RefactoringStatus checkInitialConditions = refactoring.checkInitialConditions(NULL_PROGRESS_MONITOR); + refactoring.getContext().setSettedDefaultAnswer(true); + refactoring.getContext().setDefaultAnswer(true); + if (fatalError) { + assertConditionsFatalError(checkInitialConditions); + return; + } + assertConditionsOk(checkInitialConditions); + aftertest(refactoring); + return; + } else { + RefactoringStatus checkInitialConditions = refactoring.checkInitialConditions(NULL_PROGRESS_MONITOR); + if (fatalError) { + assertConditionsFatalError(checkInitialConditions); + return; + } + assertConditionsOk(checkInitialConditions); + executeRefactoring(refactoring); + } + } + + private void aftertest(Refactoring refactoring) throws Exception { + Change changes = refactoring.createChange(NULL_PROGRESS_MONITOR); + assertConditionsOk(refactoring.checkFinalConditions(NULL_PROGRESS_MONITOR)); + changes.perform(NULL_PROGRESS_MONITOR); + filesDoExist(); + for(String fileName: fileMap.keySet()) { + IFile iFile = project.getFile(new Path(fileName)); + String code = getCodeFromIFile(iFile); + String expectedSource = fileMap.get(fileName).getExpectedSource(); + assertEquals(TestHelper.unifyNewLines(expectedSource), TestHelper.unifyNewLines(code)); + } + } + + private void pre_executeNewFileCreationRefactoring(Refactoring refactoring) throws Exception { + removeFiles(); + filesDoNotExist(); + } + + private void filesDoExist() { + for(String fileName: newfiles) { + IFile file = project.getFile(new Path(fileName)); + assertTrue(file.exists()); + } + } + + private void filesDoNotExist() { + for(String fileName: newfiles) { + IFile file = project.getFile(new Path(fileName)); + assertFalse(file.exists()); + } + } + + private void removeFiles() throws CoreException { + for(String fileName: newfiles) { + IFile file = project.getFile(new Path(fileName)); + file.delete(true, NULL_PROGRESS_MONITOR); + } + } + + private void executeRefactoring(Refactoring refactoring) throws Exception { + Change changes = refactoring.createChange(NULL_PROGRESS_MONITOR); + assertConditionsOk(refactoring.checkFinalConditions(NULL_PROGRESS_MONITOR)); + changes.perform(NULL_PROGRESS_MONITOR); + compareFiles(fileMap); + } + +} diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/togglefunction/ToggleRefactoringTestSuite.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/togglefunction/ToggleRefactoringTestSuite.java new file mode 100644 index 00000000000..657b54be781 --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/togglefunction/ToggleRefactoringTestSuite.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (c) 2011 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.ui.tests.refactoring.togglefunction; + +import junit.framework.Test; +import junit.framework.TestSuite; + +import org.eclipse.cdt.ui.tests.refactoring.RefactoringTester; + +public class ToggleRefactoringTestSuite extends TestSuite { + + @SuppressWarnings("nls") + public static Test suite() throws Exception { + TestSuite suite = new ToggleRefactoringTestSuite(); + suite.addTest(RefactoringTester.suite("NewCreationTest", + "resources/refactoring/NewCreationTest.rts")); + suite.addTest(RefactoringTester.suite("ToggleErrorRefactoring", + "resources/refactoring/ToggleErrorRefactoring.rts")); + suite.addTest(RefactoringTester.suite("ToggleSelectionTest", + "resources/refactoring/ToggleSelection.rts")); + suite.addTest(RefactoringTester.suite( + "ToggleSimpleFunctionRefactoringTest", + "resources/refactoring/ToggleSimpleFunctionRefactoring.rts")); + suite.addTest(RefactoringTester.suite("ToggleTemplateRefactoringTest", + "resources/refactoring/ToggleTemplateRefactoring.rts")); + suite.addTest(RefactoringTester.suite("ToggleNamespaceRefacotringTest", + "resources/refactoring/ToggleNamespaceRefactoring.rts")); + suite.addTest(RefactoringTester.suite("ToggleTryCatchRefactoringTest", + "resources/refactoring/ToggleTryCatchRefactoring.rts")); + suite.addTest(RefactoringTester.suite( + "ToggleDefaultParameterRefactoringTest", + "resources/refactoring/ToggleDefaultParameterRefactoring.rts")); + suite.addTest(RefactoringTester.suite("ToggleCtorDtorRefactoringTest", + "resources/refactoring/ToggleCtorDtorRefactoring.rts")); + suite.addTest(RefactoringTester.suite("ToggleNestedRefactoringTest", + "resources/refactoring/ToggleNestedRefactoring.rts")); + suite.addTest(RefactoringTester.suite("ToggleDifferentSelectionsTest", + "resources/refactoring/ToggleDifferentSelections.rts")); + suite.addTest(RefactoringTester.suite("ToggleFreeFunctionTest", + "resources/refactoring/ToggleFreeFunction.rts")); + suite.addTest(RefactoringTester.suite("ToggleVirtualFunctionTest", + "resources/refactoring/ToggleVirtualFunction.rts")); + suite.addTest(RefactoringTester.suite("ToggleOrderintTest", + "resources/refactoring/ToggleOrdering.rts")); + suite.addTest(RefactoringTester.suite("ToggleCommentsClassToHeader", + "resources/refactoring/ToggleCommentsClassToHeader.rts")); + suite.addTest(RefactoringTester.suite("ToggleCommentsHeaderToClass", + "resources/refactoring/ToggleCommentsHeaderToClass.rts")); + suite.addTest(RefactoringTester.suite("ToggleCommentsHeaderToImpl", + "resources/refactoring/ToggleCommentsHeaderToImpl.rts")); + suite.addTest(RefactoringTester.suite("ToggleCommentsImplToHeader", + "resources/refactoring/ToggleCommentsImplToHeader.rts")); + suite.addTestSuite(ToggleNodeHelperTest.class); + return suite; + } + +} diff --git a/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF b/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF index c8481892f51..e2411bb6060 100644 --- a/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF +++ b/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF @@ -42,6 +42,7 @@ Export-Package: org.eclipse.cdt.internal.corext;x-internal:=true, org.eclipse.cdt.internal.ui.refactoring.hidemethod;x-friends:="org.eclipse.cdt.ui.tests", org.eclipse.cdt.internal.ui.refactoring.implementmethod;x-friends:="org.eclipse.cdt.ui.tests", org.eclipse.cdt.internal.ui.refactoring.rename;x-friends:="org.eclipse.cdt.ui.tests", + org.eclipse.cdt.internal.ui.refactoring.togglefunction;x-friends:="org.eclipse.cdt.ui.tests", org.eclipse.cdt.internal.ui.refactoring.utils;x-friends:="org.eclipse.cdt.ui.tests", org.eclipse.cdt.internal.ui.search;x-internal:=true, org.eclipse.cdt.internal.ui.search.actions;x-internal:=true, diff --git a/core/org.eclipse.cdt.ui/plugin.properties b/core/org.eclipse.cdt.ui/plugin.properties index ad43e1f9bd7..7465b355bc5 100644 --- a/core/org.eclipse.cdt.ui/plugin.properties +++ b/core/org.eclipse.cdt.ui/plugin.properties @@ -150,6 +150,8 @@ ActionDefinition.extractLocalVariable.name= Extract Local Variable - Refactoring ActionDefinition.extractLocalVariable.description= Extract a local variable for the selected expression ActionDefinition.extractFunction.name= Extract Function - Refactoring ActionDefinition.extractFunction.description= Extract a function for the selected list of expressions or statements +ActionDefinition.toggleFunction.name= Toggle Function - Refactoring +ActionDefinition.toggleFunction.description= Toggles the implementation between header and implementation file ActionDefinition.implementMethod.name= Implement Method - Source Generation ActionDefinition.implementMethod.description= Implements a method for a selected method declaration ActionDefinition.gettersAndSetters.name = Generate Getters and Setters... @@ -167,6 +169,7 @@ Refactoring.renameAction.label=Re&name... Refactoring.extractConstant.label=Extr&act Constant... Refactoring.extractLocalVariable.label=Extract &Local Variable Refactoring.extractFunction.label=Extract &Function... +Refactoring.toggleFunction.label=Toggle Function Refactoring.hideMethod.label=Hide Method... Refactoring.implementMethod.label=Impl&ement Method... Refactoring.gettersAndSetters.label=Gene&rate Getters and Setters... diff --git a/core/org.eclipse.cdt.ui/plugin.xml b/core/org.eclipse.cdt.ui/plugin.xml index 8382e186c8d..5b08f1fd611 100644 --- a/core/org.eclipse.cdt.ui/plugin.xml +++ b/core/org.eclipse.cdt.ui/plugin.xml @@ -1252,6 +1252,13 @@ id="org.eclipse.cdt.ui.actions.ExtractMethod" retarget="true"> + + + + toggle function action (value + * "org.eclipse.cdt.ui.refactor.toggle.function"). + */ + public static final String TOGGLE_FUNCTION = "org.eclipse.cdt.ui.refactor.toggle.function"; //$NON-NLS-1$ + /** * Action definition ID of the refactor -> hide method action * (value "org.eclipse.cdt.ui.refactor.hide.method"). diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/IndexToASTNameHelper.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/IndexToASTNameHelper.java new file mode 100644 index 00000000000..88b961e1c6b --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/IndexToASTNameHelper.java @@ -0,0 +1,150 @@ +/******************************************************************************* + * Copyright (c) 2011 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; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.runtime.CoreException; + +import org.eclipse.cdt.core.dom.IName; +import org.eclipse.cdt.core.dom.ast.ASTVisitor; +import org.eclipse.cdt.core.dom.ast.IASTFileLocation; +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; +import org.eclipse.cdt.core.index.IIndex; +import org.eclipse.cdt.core.index.IIndexName; +import org.eclipse.cdt.core.parser.util.CharArrayUtils; + +public class IndexToASTNameHelper { + + public static List findNamesIn(IASTTranslationUnit tu, IBinding binding, IIndex index) { + BindingToAstNameMatcher visitor = new BindingToAstNameMatcher(binding, index); + tu.accept(visitor); + return visitor.getMatches(); + } + + public static IASTName findMatchingASTName(IASTTranslationUnit tu, IName name, IIndex index) throws CoreException { + if (name instanceof IASTName) { + return (IASTName) name; + } else if (!(name instanceof IIndexName)) { + return null; + } + + IndexNameToAstNameMatcher visitor = new IndexNameToAstNameMatcher(tu, (IIndexName) name, index); + tu.accept(visitor); + return visitor.getMatch(); + } + + static boolean shouldConsiderName(IASTName candidate) { + return !isQualifiedName(candidate) && isLastNameInQualifiedName(candidate) && !isUnnamedName(candidate); + } + + private static boolean isLastNameInQualifiedName(IASTName name) { + if (name.getParent() instanceof ICPPASTQualifiedName) { + ICPPASTQualifiedName qName = (ICPPASTQualifiedName) name.getParent(); + return name.equals(qName.getLastName()); + } + return true; + } + + private static boolean isUnnamedName(IASTName name) { + return name.getFileLocation() == null && "".equals(name.toString()); //$NON-NLS-1$ + } + + private static boolean isQualifiedName(IASTName name) { + return name instanceof ICPPASTQualifiedName; + } +} + +class IndexNameToAstNameMatcher extends ASTVisitor { + + private IASTName result; + private IBinding bindingToFind; + private char[] charNameToFind; + private IIndex index; + private IASTFileLocation locationToFind; + + public IndexNameToAstNameMatcher(IASTTranslationUnit tu, IIndexName indexName, IIndex index) throws CoreException { + super(true); + locationToFind = indexName.getFileLocation(); + bindingToFind = index.findBinding(indexName); + this.index = index; + charNameToFind = bindingToFind.getNameCharArray(); + shouldVisitImplicitNames = true; + shouldVisitImplicitNameAlternates = true; + } + + @Override + public int visit(IASTName candidate) { + if (!IndexToASTNameHelper.shouldConsiderName(candidate)) { + return PROCESS_CONTINUE; + } + if (isEquivalent(candidate)) { + result = candidate; + return PROCESS_ABORT; + } + return PROCESS_CONTINUE; + } + + private boolean isEquivalent(IASTName candidate) { + return matchesIndexName(candidate) && bindingToFind.equals(index.adaptBinding(candidate.resolveBinding())); + } + + private boolean matchesIndexName(IASTName candidate) { + IASTFileLocation candidateLocation = candidate.getFileLocation(); + return locationToFind.getNodeOffset() == candidateLocation.getNodeOffset() && locationToFind.getNodeLength() == candidateLocation.getNodeLength() + && locationToFind.getFileName().equals(candidateLocation.getFileName()) && CharArrayUtils.equals(candidate.getLookupKey(), charNameToFind); + } + + public IASTName getMatch() { + return result; + } +} + +class BindingToAstNameMatcher extends ASTVisitor { + + private List results = new ArrayList(); + private IBinding bindingToFind; + private char[] toFindName; + private IIndex index; + + public BindingToAstNameMatcher(IBinding binding, IIndex index) { + super(true); + bindingToFind = index.adaptBinding(binding); + this.index = index; + toFindName = binding.getNameCharArray(); + shouldVisitImplicitNames = true; + shouldVisitImplicitNameAlternates = true; + } + + @Override + public int visit(IASTName candidate) { + if (!IndexToASTNameHelper.shouldConsiderName(candidate)) { + return PROCESS_CONTINUE; + } + if (isEquivalent(candidate)) { + results.add(candidate); + } + return PROCESS_CONTINUE; + } + + private boolean isEquivalent(IASTName candidate) { + return CharArrayUtils.equals(candidate.getLookupKey(), toFindName) && bindingToFind.equals(index.adaptBinding(candidate.resolveBinding())); + } + + public List getMatches() { + return results; + } +}; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/DeclaratorFinder.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/DeclaratorFinder.java new file mode 100644 index 00000000000..639461576bb --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/DeclaratorFinder.java @@ -0,0 +1,102 @@ +/******************************************************************************* + * Copyright (c) 2011 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: + * Martin Schwab & Thomas Kallenberg - initial API and implementation + ******************************************************************************/ +package org.eclipse.cdt.internal.ui.refactoring.togglefunction; + +import org.eclipse.jface.text.ITextSelection; + +import org.eclipse.cdt.core.dom.ast.IASTDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTStatement; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration; + +/** + * Given a selection and a translation unit, this class finds a + * ICPPASTFunctionDeclarator if possible. Special case: Nested local functions + * are skipped during search. + */ +public class DeclaratorFinder { + + private IASTFunctionDeclarator foundDeclarator; + + public DeclaratorFinder(ITextSelection selection, IASTTranslationUnit unit) { + foundDeclarator = findDeclaratorInSelection(selection, unit); + + if (foundDeclarator == null) { + throw new NotSupportedException(Messages.DeclaratorFinder_NoDeclarator); + } + if (isPartOfAStatement(foundDeclarator)) { + throw new NotSupportedException(Messages.DeclaratorFinder_NestedFunction); + } + } + + public IASTName getName() { + return foundDeclarator.getName(); + } + + private IASTFunctionDeclarator findDeclaratorInSelection( +ITextSelection selection, + IASTTranslationUnit unit) { + IASTNode firstNodeInsideSelection = unit.getNodeSelector(null) + .findFirstContainedNode(selection.getOffset(), + selection.getLength()); + IASTFunctionDeclarator declarator = findDeclaratorInAncestors(firstNodeInsideSelection); + + if (declarator == null) { + firstNodeInsideSelection = unit.getNodeSelector(null).findEnclosingNode( + selection.getOffset(), selection.getLength()); + declarator = findDeclaratorInAncestors(firstNodeInsideSelection); + } + return declarator; + } + + private IASTFunctionDeclarator findDeclaratorInAncestors(IASTNode node) { + while (node != null) { + IASTFunctionDeclarator declarator = extractDeclarator(node); + if (node instanceof ICPPASTTemplateDeclaration) { + declarator = extractDeclarator(((ICPPASTTemplateDeclaration) node).getDeclaration()); + } + if (declarator != null) { + return declarator; + } + node = node.getParent(); + } + return null; + } + + private IASTFunctionDeclarator extractDeclarator(IASTNode node) { + if (node instanceof ICPPASTTemplateDeclaration) { + node = ((ICPPASTTemplateDeclaration) node).getDeclaration(); + } + if (node instanceof IASTFunctionDeclarator) { + return (IASTFunctionDeclarator) node; + } + if (node instanceof IASTFunctionDefinition) { + return ((IASTFunctionDefinition) node).getDeclarator(); + } + if (node instanceof IASTSimpleDeclaration) { + IASTDeclarator[] declarators = ((IASTSimpleDeclaration) node).getDeclarators(); + if (declarators.length == 1 && + declarators[0] instanceof IASTFunctionDeclarator) + return (IASTFunctionDeclarator) declarators[0]; + } + return null; + } + + private boolean isPartOfAStatement(IASTNode node) { + return ToggleNodeHelper.getAncestorOfType(node, IASTStatement.class) != null; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/EmptyRefactoringDescription.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/EmptyRefactoringDescription.java new file mode 100644 index 00000000000..8d22493b575 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/EmptyRefactoringDescription.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2010 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: + * Martin Schwab & Thomas Kallenberg - initial API and implementation + ******************************************************************************/ +package org.eclipse.cdt.internal.ui.refactoring.togglefunction; + +import java.util.HashMap; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.text.TextSelection; +import org.eclipse.ltk.core.refactoring.Refactoring; +import org.eclipse.ltk.core.refactoring.RefactoringStatus; + +import org.eclipse.cdt.internal.ui.refactoring.CRefactoringDescription; + +class EmptyRefactoringDescription extends CRefactoringDescription { + @SuppressWarnings("nls") + public EmptyRefactoringDescription() { + super("id", "proj", "desc", "comment", 0, new HashMap()); + } + + @Override + public Refactoring createRefactoring(RefactoringStatus status) throws CoreException { + return new ToggleRefactoring(getFile(), (TextSelection)getSelection(), getCProject()); + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/IToggleRefactoringStrategy.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/IToggleRefactoringStrategy.java new file mode 100644 index 00000000000..29c1f66918e --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/IToggleRefactoringStrategy.java @@ -0,0 +1,18 @@ +/******************************************************************************* + * Copyright (c) 2011 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: + * Martin Schwab & Thomas Kallenberg - initial API and implementation + ******************************************************************************/ +package org.eclipse.cdt.internal.ui.refactoring.togglefunction; + +import org.eclipse.cdt.internal.ui.refactoring.ModificationCollector; + +public interface IToggleRefactoringStrategy { + public void run(ModificationCollector modifications); +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/InsertionPointFinder.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/InsertionPointFinder.java new file mode 100644 index 00000000000..4f39a6da264 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/InsertionPointFinder.java @@ -0,0 +1,154 @@ +/******************************************************************************* + * Copyright (c) 2011 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: + * Martin Schwab & Thomas Kallenberg - initial API and implementation + ******************************************************************************/ +package org.eclipse.cdt.internal.ui.refactoring.togglefunction; + +import java.util.ArrayList; + +import org.eclipse.cdt.core.dom.ast.ASTVisitor; +import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration; + +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTCompositeTypeSpecifier; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTName; + +import org.eclipse.cdt.internal.ui.refactoring.Container; + +public class InsertionPointFinder { + + private static ArrayList allafterdeclarations; + private static ArrayList alldefinitionsoutside; + private static IASTDeclaration position; + + public static IASTDeclaration findInsertionPoint(IASTTranslationUnit classunit, IASTTranslationUnit functiondefunit, IASTFunctionDeclarator funcdecl) { + position = null; + findAllDeclarationsAfterInClass(classunit, funcdecl); + findAllDefinitionsoutSideClass(functiondefunit); + findRightPlace(); + return position; + } + + private static void findRightPlace() { + if (allafterdeclarations == null || alldefinitionsoutside == null) + return; + for(ICPPASTFunctionDeclarator decl: allafterdeclarations) { + String decl_name = decl.getName().toString(); + for(ICPPASTFunctionDefinition def: alldefinitionsoutside) { + String def_name = null; + if (def.getDeclarator().getName() instanceof ICPPASTQualifiedName) { + ICPPASTQualifiedName qname = (ICPPASTQualifiedName) def.getDeclarator().getName(); + def_name = qname.getNames()[1].toString(); + } + else if (def.getDeclarator().getName() instanceof CPPASTName) { + def_name = def.getDeclarator().getName().toString(); + } + + if (decl_name.equals(def_name)) { + if (def.getParent() != null && def.getParent() instanceof ICPPASTTemplateDeclaration) + position = (IASTDeclaration) def.getParent(); + else + position = def; + return; + } + } + } + } + + private static void findAllDeclarationsAfterInClass(IASTTranslationUnit classunit, IASTFunctionDeclarator funcdecl) { + ICPPASTCompositeTypeSpecifier klass = getklass(classunit); + if (klass != null) + allafterdeclarations = getDeclarationsInClass(klass, funcdecl); + } + + /** + * @param unit the translation unit where to find the definitions + */ + private static void findAllDefinitionsoutSideClass(IASTTranslationUnit unit) { + final ArrayList definitions = new ArrayList(); + if (unit == null) { + alldefinitionsoutside = definitions; + return; + } + unit.accept( + new ASTVisitor() { + { + shouldVisitDeclarations = true; + } + + @Override + public int visit(IASTDeclaration declaration) { + if (declaration instanceof ICPPASTFunctionDefinition) { + if (declaration.getParent() != null && ToggleNodeHelper.getAncestorOfType(declaration, CPPASTCompositeTypeSpecifier.class) != null) + return PROCESS_CONTINUE; + definitions.add((ICPPASTFunctionDefinition) declaration); + } + return super.visit(declaration); + } + }); + alldefinitionsoutside = definitions; + } + + private static ArrayList getDeclarationsInClass(ICPPASTCompositeTypeSpecifier klass, final IASTFunctionDeclarator selected) { + final ArrayList declarations = new ArrayList(); + + klass.accept( + new ASTVisitor() { + { + shouldVisitDeclarators = true; + } + + boolean got = false; + @Override + public int visit(IASTDeclarator declarator) { + if (declarator instanceof ICPPASTFunctionDeclarator) { + if (((ICPPASTFunctionDeclarator) declarator) == selected) { + got = true; + } + if (got) { + declarations.add((ICPPASTFunctionDeclarator) declarator); + } + } + return super.visit(declarator); + } + }); + + return declarations; + } + + private static ICPPASTCompositeTypeSpecifier getklass(IASTTranslationUnit unit) { + final Container result = new Container(); + + unit.accept( + new ASTVisitor() { + { + shouldVisitDeclSpecifiers = true; + } + + @Override + public int visit(IASTDeclSpecifier declSpec) { + if (declSpec instanceof ICPPASTCompositeTypeSpecifier) { + result.setObject((ICPPASTCompositeTypeSpecifier) declSpec); + return PROCESS_ABORT; + } + return super.visit(declSpec); + } + }); + return result.getObject(); + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/Messages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/Messages.java new file mode 100644 index 00000000000..e96a5ad0eab --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/Messages.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2011 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: + * Emanuel Graf IFS - initial API and implementation + ******************************************************************************/ +package org.eclipse.cdt.internal.ui.refactoring.togglefunction; + +import org.eclipse.osgi.util.NLS; + +public class Messages extends NLS { + private static final String BUNDLE_NAME = "org.eclipse.cdt.internal.ui.refactoring.togglefunction.messages"; //$NON-NLS-1$ + public static String DeclaratorFinder_NestedFunction; + public static String DeclaratorFinder_NoDeclarator; + public static String RefactoringJob_UndoName; + public static String ToggleFileCreator_andMove; + public static String ToggleFileCreator_CanNotCreateNewFile; + public static String ToggleFileCreator_CreateNewFile; + public static String ToggleFileCreator_NewImplFile; + public static String ToggleFileCreator_NoTuForSibling; + public static String ToggleFileCreator_QMark; + public static String ToggleFromClassToInHeaderStrategy_DefAndDecInsideClass; + public static String EditGroupName; + public static String ToggleFromImplementationToHeaderOrClassStrategy_CanNotCreateNewFile; + public static String ToggleFromImplementationToHeaderOrClassStrategy_CanNotToggle; + public static String ToggleFromInHeaderToClassStrategy_CanNotToggleTemplateFreeFunction; + public static String ToggleFromInHeaderToImplementationStrategy_CanNotCreateImplFile; + public static String ToggleRefactoring_AnalyseSelection; + public static String ToggleRefactoring_CalculateModifications; + public static String ToggleRefactoring_CanNotSaveFiles; + public static String ToggleRefactoring_InvalidSelection; + public static String ToggleRefactoring_NoIndex; + public static String ToggleRefactoring_WaitingForIndexer; + public static String ToggleRefactoringContext_MultipleDeclarations; + public static String ToggleRefactoringContext_MultipleDefinitions; + public static String ToggleRefactoringContext_NoDefinitionFound; + public static String ToggleRefactoringContext_NoTuFound; + public static String ToggleStrategyFactory_NoDefinitionFound; + public static String ToggleStrategyFactory_UnsupportedSituation; + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } + + private Messages() { + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/NotSupportedException.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/NotSupportedException.java new file mode 100644 index 00000000000..4c325930e64 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/NotSupportedException.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2011 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: + * Martin Schwab & Thomas Kallenberg - initial API and implementation + ******************************************************************************/ +package org.eclipse.cdt.internal.ui.refactoring.togglefunction; + +/** + * Thrown when the developer had no time to implement a special case the user + * tried to refactor. + * + */ +public class NotSupportedException extends RuntimeException { + + private static final long serialVersionUID = -4359705945683270L; + + public NotSupportedException(String message) { + super(message); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/RefactoringJob.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/RefactoringJob.java new file mode 100644 index 00000000000..633574d5628 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/RefactoringJob.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * Copyright (c) 2011 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.togglefunction; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.ltk.core.refactoring.Change; +import org.eclipse.ltk.core.refactoring.IUndoManager; +import org.eclipse.ltk.core.refactoring.NullChange; +import org.eclipse.ltk.core.refactoring.Refactoring; +import org.eclipse.ltk.core.refactoring.RefactoringCore; +import org.eclipse.ltk.core.refactoring.RefactoringStatus; + +import org.eclipse.cdt.ui.CUIPlugin; + +class RefactoringJob extends Job { + public final static Object FAMILY_TOGGLE_DEFINITION = new Object(); + private final Refactoring refactoring; + + RefactoringJob(Refactoring refactoring) { + super("'toggle function definition' code automation"); //$NON-NLS-1$ + this.refactoring = refactoring; + setPriority(Job.SHORT); + } + + @Override + public boolean belongsTo(Object family) { + return family == FAMILY_TOGGLE_DEFINITION; + } + + @Override + protected IStatus run(IProgressMonitor monitor) { + IUndoManager undoManager = RefactoringCore.getUndoManager(); + Change change = new NullChange(); + Change undoChange = new NullChange(); + boolean success = false; + try { + RefactoringStatus status = refactoring.checkAllConditions(monitor); + if (status.hasFatalError()) + return new Status(IStatus.ERROR, CUIPlugin.PLUGIN_ID, status.getMessageMatchingSeverity(RefactoringStatus.ERROR)); + change = refactoring.createChange(monitor); + change.initializeValidationData(monitor); + if (!change.isValid(monitor).isOK()) { + return Status.CANCEL_STATUS; + } + undoManager.aboutToPerformChange(change); + undoChange = change.perform(monitor); + success = true; + } catch (IllegalStateException e) { + CUIPlugin.log("Another refactoring is still in progress, aborting.", e); //$NON-NLS-1$ + } catch (CoreException e) { + CUIPlugin.log("Failure during generation of changes.", e); //$NON-NLS-1$ + } finally { + undoChange.initializeValidationData(monitor); + undoManager.changePerformed(change, success); + try { + if (success && undoChange.isValid(monitor).isOK()) { + // Note: addUndo MUST be called AFTER changePerformed or + // the change won't be unlocked correctly. (17.11.2010) + undoManager.addUndo(Messages.RefactoringJob_UndoName, undoChange); + } + } catch (OperationCanceledException e) { + } catch (CoreException e) { + } + } + return Status.OK_STATUS; + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleFileCreator.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleFileCreator.java new file mode 100644 index 00000000000..36d091d4cde --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleFileCreator.java @@ -0,0 +1,117 @@ +/******************************************************************************* + * Copyright (c) 2011 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: + * Martin Schwab & Thomas Kallenberg - initial API and implementation + ******************************************************************************/ +package org.eclipse.cdt.internal.ui.refactoring.togglefunction; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.Path; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.PlatformUI; + +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.model.CModelException; +import org.eclipse.cdt.core.model.CoreModelUtil; +import org.eclipse.cdt.ui.CUIPlugin; + +import org.eclipse.cdt.internal.ui.refactoring.Container; +import org.eclipse.cdt.internal.ui.refactoring.CreateFileChange; + +public class ToggleFileCreator { + + private static final String EMPTY_STRING = ""; //$NON-NLS-1$ + private static final String H = ".h"; //$NON-NLS-1$ + private ToggleRefactoringContext context; + private String ending; + + public ToggleFileCreator(ToggleRefactoringContext context, String ending) { + this.context = context; + this.ending = ending; + } + + public IASTTranslationUnit loadTranslationUnit() { + String filename; + if (context.getDeclaration() != null) { + filename = context.getDeclaration().getContainingFilename(); + } else { + filename = context.getDefinition().getContainingFilename(); + } + String other; + if (ending.equals(H)) { + other = ".cpp"; //$NON-NLS-1$ + } else { + other = H; + } + filename = filename.replaceAll("\\w*" + other + "$", EMPTY_STRING) + getNewFileName(); //$NON-NLS-1$//$NON-NLS-2$ + IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(filename)); + IASTTranslationUnit result = null; + try { + result = CoreModelUtil.findTranslationUnitForLocation(file.getFullPath(), null).getAST(); + } catch (CModelException e) { + } catch (CoreException e) { + } + if (result == null) { + throw new NotSupportedException(Messages.ToggleFileCreator_NoTuForSibling); + } + return result; + } + + public void createNewFile() { + CreateFileChange change; + String filename = getNewFileName(); + try { + change = new CreateFileChange(filename, new Path(getPath()+filename), + EMPTY_STRING, context.getSelectionFile().getCharset()); + change.perform(new NullProgressMonitor()); + } catch (CoreException e) { + throw new NotSupportedException(Messages.ToggleFileCreator_CanNotCreateNewFile); + } + } + + public boolean askUserForFileCreation(final ToggleRefactoringContext context) { + if (context.isSettedDefaultAnswer()) { + return context.getDefaultAnswer(); + } + final Container answer = new Container(); + Runnable r = new Runnable() { + public void run() { + Shell shell = CUIPlugin.getDefault().getWorkbench().getWorkbenchWindows()[0].getShell(); + String functionname; + if (context.getDeclaration() != null) { + functionname = context.getDeclaration().getRawSignature(); + } else { + functionname = context.getDefinition().getDeclarator().getRawSignature(); + } + boolean createnew = MessageDialog.openQuestion(shell, Messages.ToggleFileCreator_NewImplFile, + Messages.ToggleFileCreator_CreateNewFile + getNewFileName() + Messages.ToggleFileCreator_andMove + functionname + Messages.ToggleFileCreator_QMark); + answer.setObject(createnew); + } + }; + PlatformUI.getWorkbench().getDisplay().syncExec(r); + return answer.getObject(); + } + + public String getIncludeStatement() { + return "#include \"" + ToggleNodeHelper.getFilenameWithoutExtension(getNewFileName()) + ".h\""; //$NON-NLS-1$//$NON-NLS-2$ + } + + private String getNewFileName() { + return ToggleNodeHelper.getFilenameWithoutExtension(context.getSelectionFile().getFullPath().toString()) + ending; + } + + private String getPath() { + String result = context.getSelectionFile().getFullPath().toOSString(); + return result.replaceAll("(\\w)*\\.(\\w)*", EMPTY_STRING); //$NON-NLS-1$ + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleFromClassToInHeaderStrategy.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleFromClassToInHeaderStrategy.java new file mode 100644 index 00000000000..2c749f3c9e6 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleFromClassToInHeaderStrategy.java @@ -0,0 +1,116 @@ +/******************************************************************************* + * Copyright (c) 2011 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: + * Martin Schwab & Thomas Kallenberg - initial API and implementation + ******************************************************************************/ +package org.eclipse.cdt.internal.ui.refactoring.togglefunction; + +import org.eclipse.text.edits.TextEditGroup; + +import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTNode.CopyStyle; +import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.dom.ast.INodeFactory; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCatchHandler; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionWithTryBlock; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration; +import org.eclipse.cdt.core.dom.rewrite.ASTRewrite; + +import org.eclipse.cdt.internal.ui.refactoring.ModificationCollector; + +public class ToggleFromClassToInHeaderStrategy implements IToggleRefactoringStrategy { + + protected TextEditGroup infoText = new TextEditGroup(Messages.EditGroupName); + private ToggleRefactoringContext context; + + public ToggleFromClassToInHeaderStrategy(ToggleRefactoringContext context) { + if (isInClass(context.getDeclaration()) && isInClass(context.getDefinition())) + throw new NotSupportedException(Messages.ToggleFromClassToInHeaderStrategy_DefAndDecInsideClass); + this.context = context; + } + + private boolean isInClass(IASTNode node) { + return ToggleNodeHelper.getAncestorOfType(node, + ICPPASTCompositeTypeSpecifier.class) != null; + } + + public void run(ModificationCollector modifications) { + IASTNode parentNamespace = getParentNamespace(); + IASTNode newDefinition = getNewDefinition(parentNamespace); + IASTSimpleDeclaration newDeclaration = getNewDeclaration(); + ASTRewrite rewriter = replaceDefinitionWithDeclaration(modifications, newDeclaration); + IASTNode insertion_point = getInsertionPoint(parentNamespace); + rewriter.insertBefore(parentNamespace, + insertion_point, newDefinition, infoText); + } + + private IASTNode getNewDefinition(IASTNode parentNamespace) { + IASTNode newDefinition = ToggleNodeHelper.getQualifiedNameDefinition( + context.getDefinition(), context.getDefinitionUnit(), parentNamespace); + ((IASTFunctionDefinition) newDefinition).setBody(context.getDefinition().getBody() + .copy(CopyStyle.withLocations)); + if (newDefinition instanceof ICPPASTFunctionWithTryBlock) { + ICPPASTFunctionWithTryBlock newTryFun = (ICPPASTFunctionWithTryBlock) newDefinition; + ICPPASTFunctionWithTryBlock oldTryFun = (ICPPASTFunctionWithTryBlock) context.getDefinition(); + for (ICPPASTCatchHandler catchH : oldTryFun.getCatchHandlers()) { + newTryFun.addCatchHandler(catchH.copy(CopyStyle.withLocations)); + } + } + ICPPASTTemplateDeclaration templdecl = ToggleNodeHelper.getTemplateDeclaration( + context.getDefinition(), (IASTFunctionDefinition) newDefinition); + if (templdecl != null) { + newDefinition = templdecl; + } + newDefinition.setParent(context.getDefinitionUnit()); + return newDefinition; + } + + private IASTNode getParentNamespace() { + IASTNode parentNamespace = ToggleNodeHelper.getAncestorOfType( + context.getDefinition(), ICPPASTNamespaceDefinition.class); + if (parentNamespace == null) + parentNamespace = context.getDefinitionUnit(); + return parentNamespace; + } + + private IASTNode getInsertionPoint(IASTNode parentNamespace) { + IASTTranslationUnit unit = parentNamespace.getTranslationUnit(); + IASTNode insertion_point = InsertionPointFinder.findInsertionPoint( + unit, unit, context.getDefinition().getDeclarator()); + return insertion_point; + } + + private ASTRewrite replaceDefinitionWithDeclaration( + ModificationCollector modifications, + IASTSimpleDeclaration newDeclaration) { + ASTRewrite rewriter = modifications.rewriterForTranslationUnit( + context.getDefinitionUnit()); + rewriter.replace(context.getDefinition(), newDeclaration, infoText); + return rewriter; + } + + private IASTSimpleDeclaration getNewDeclaration() { + INodeFactory factory = context.getDefinitionUnit().getASTNodeFactory(); + IASTDeclSpecifier newDeclSpecifier = context.getDefinition().getDeclSpecifier() + .copy(CopyStyle.withLocations); + newDeclSpecifier.setInline(false); + IASTSimpleDeclaration newDeclaration = factory.newSimpleDeclaration(newDeclSpecifier); + IASTFunctionDeclarator newDeclarator = context.getDefinition().getDeclarator() + .copy(CopyStyle.withLocations); + newDeclaration.addDeclarator(newDeclarator); + newDeclaration.setParent(context.getDefinition().getParent()); + return newDeclaration; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleFromImplementationToHeaderOrClassStrategy.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleFromImplementationToHeaderOrClassStrategy.java new file mode 100644 index 00000000000..83de3379568 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleFromImplementationToHeaderOrClassStrategy.java @@ -0,0 +1,180 @@ +/******************************************************************************* + * Copyright (c) 2011 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: + * Martin Schwab & Thomas Kallenberg - initial API and implementation + ******************************************************************************/ +package org.eclipse.cdt.internal.ui.refactoring.togglefunction; + +import java.util.List; + +import org.eclipse.text.edits.TextEditGroup; + +import org.eclipse.cdt.core.dom.ast.IASTComment; +import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTNode.CopyStyle; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCatchHandler; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionWithTryBlock; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; +import org.eclipse.cdt.core.dom.rewrite.ASTRewrite; +import org.eclipse.cdt.core.dom.rewrite.ASTRewrite.CommentPosition; + +import org.eclipse.cdt.internal.core.dom.rewrite.ASTLiteralNode; + +import org.eclipse.cdt.internal.ui.refactoring.ModificationCollector; +import org.eclipse.cdt.internal.ui.refactoring.utils.CPPASTAllVisitor; + +public class ToggleFromImplementationToHeaderOrClassStrategy implements IToggleRefactoringStrategy { + + private ToggleRefactoringContext context; + private TextEditGroup infoText; + private IASTTranslationUnit other_tu; + private ASTLiteralNode includenode; + + public ToggleFromImplementationToHeaderOrClassStrategy( + ToggleRefactoringContext context) { + this.context = context; + this.infoText = new TextEditGroup(Messages.EditGroupName); + } + + private boolean isFreeFunction(IASTFunctionDefinition definition) { + return definition.getDeclarator().getName() instanceof ICPPASTQualifiedName; + } + + public void run(ModificationCollector modifications) { + newFileCheck(); + ASTRewrite implast = modifications.rewriterForTranslationUnit(context.getDefinitionUnit()); + ListleadingComments = implast.getComments(context.getDefinition(), CommentPosition.leading); + removeDefinitionFromImplementation(implast); + if (includenode != null) { + implast.insertBefore(context.getDefinitionUnit(), + context.getDefinitionUnit().getChildren()[0], includenode, infoText); + } + if (context.getDeclarationUnit() != null) { + addDefinitionToClass(modifications, leadingComments); + } else { + addDefinitionToHeader(modifications, leadingComments); + } + } + + private void newFileCheck() { + if (context.getDeclarationUnit() == null) { + if (isFreeFunction(context.getDefinition())) { + throw new NotSupportedException(Messages.ToggleFromImplementationToHeaderOrClassStrategy_CanNotToggle); + } + other_tu = context.getTUForSiblingFile(); + if (other_tu == null) { + ToggleFileCreator filecreator = new ToggleFileCreator(context, ".h"); //$NON-NLS-1$ + if (filecreator.askUserForFileCreation(context)) { + filecreator.createNewFile(); + other_tu = filecreator.loadTranslationUnit(); + includenode = new ASTLiteralNode(filecreator.getIncludeStatement() + "\n\n"); //$NON-NLS-1$ + } else { + throw new NotSupportedException(Messages.ToggleFromImplementationToHeaderOrClassStrategy_CanNotCreateNewFile); + } + } + } + } + + private void addDefinitionToHeader(ModificationCollector modifications, List leadingComments) { + ASTRewrite headerRewrite = modifications.rewriterForTranslationUnit(other_tu); + IASTFunctionDefinition newDefinition = ToggleNodeHelper.createFunctionSignatureWithEmptyBody( +context + .getDefinition().getDeclSpecifier().copy(CopyStyle.withLocations), context.getDefinition() + .getDeclarator().copy(CopyStyle.withLocations), + context.getDefinition().copy(CopyStyle.withLocations)); + newDefinition.setParent(other_tu); + headerRewrite.insertBefore(other_tu.getTranslationUnit(), null, newDefinition, infoText); + restoreBody(headerRewrite, newDefinition, modifications); + for (IASTComment comment : leadingComments) { + headerRewrite.addComment(newDefinition, comment, CommentPosition.leading); + } + } + + private void addDefinitionToClass(ModificationCollector modifications, List leadingComments) { + ASTRewrite headerRewrite = modifications.rewriterForTranslationUnit( + context.getDeclarationUnit()); + IASTFunctionDefinition newDefinition = ToggleNodeHelper.createInClassDefinition( + context.getDeclaration(), context.getDefinition(), + context.getDeclarationUnit()); + newDefinition.setParent(getParent()); + restoreBody(headerRewrite, newDefinition, modifications); + headerRewrite.replace(context.getDeclaration().getParent(), newDefinition, infoText); + for (IASTComment comment : leadingComments) { + headerRewrite.addComment(newDefinition, comment, CommentPosition.leading); + } + } + + private IASTNode getParent() { + IASTNode parent = ToggleNodeHelper.getAncestorOfType(context.getDefinition(), + ICPPASTCompositeTypeSpecifier.class); + IASTNode parentnode = null; + if (parent != null) { + parentnode = parent; + } + else { + parentnode =context.getDeclarationUnit(); + } + return parentnode; + } + + private void restoreBody(ASTRewrite headerRewrite, IASTFunctionDefinition newDefinition, + ModificationCollector modifications) { + IASTFunctionDefinition oldDefinition = context.getDefinition(); + newDefinition.setBody(oldDefinition.getBody().copy(CopyStyle.withLocations)); + + if (newDefinition instanceof ICPPASTFunctionWithTryBlock && oldDefinition instanceof ICPPASTFunctionWithTryBlock) { + ICPPASTFunctionWithTryBlock newTryDef = (ICPPASTFunctionWithTryBlock) newDefinition; + ICPPASTFunctionWithTryBlock oldTryDef = (ICPPASTFunctionWithTryBlock) oldDefinition; + for (ICPPASTCatchHandler handler : oldTryDef.getCatchHandlers()) { + newTryDef.addCatchHandler(handler.copy(CopyStyle.withLocations)); + } + } + copyAllCommentsToNewLocation(oldDefinition, modifications.rewriterForTranslationUnit(oldDefinition.getTranslationUnit()), headerRewrite); + } + + private void copyAllCommentsToNewLocation(IASTNode node, final ASTRewrite oldRw, final ASTRewrite newRw) { + node.accept(new CPPASTAllVisitor() { + @Override + public int visitAll(IASTNode node){ + copyComments(oldRw, newRw, node, CommentPosition.leading); + copyComments(oldRw, newRw, node, CommentPosition.trailing); + copyComments(oldRw, newRw, node, CommentPosition.freestanding); + return PROCESS_CONTINUE; + } + + private void copyComments(final ASTRewrite oldRw, final ASTRewrite newRw, IASTNode node, + CommentPosition pos) { + List comments = oldRw.getComments(node, pos); + for (IASTComment comment : comments) { + newRw.addComment(node, comment, pos); + } + } + }); + + } + + private void removeDefinitionFromImplementation(ASTRewrite implast) { + ICPPASTNamespaceDefinition ns = ToggleNodeHelper.getAncestorOfType( + context.getDefinition(), ICPPASTNamespaceDefinition.class); + if (ns != null && isSingleElementInNamespace(ns, context.getDefinition())) { + implast.remove(ns, infoText); + } else { + implast.remove(context.getDefinition(), infoText); + } + } + + private boolean isSingleElementInNamespace(ICPPASTNamespaceDefinition ns, + IASTFunctionDefinition definition) { + return ns.getChildren().length == 2 && (ns.contains(definition)); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleFromInHeaderToClassStrategy.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleFromInHeaderToClassStrategy.java new file mode 100644 index 00000000000..b8aafee1b68 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleFromInHeaderToClassStrategy.java @@ -0,0 +1,122 @@ +/******************************************************************************* + * Copyright (c) 2011 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: + * Martin Schwab & Thomas Kallenberg - initial API and implementation + ******************************************************************************/ +package org.eclipse.cdt.internal.ui.refactoring.togglefunction; + +import java.util.List; + +import org.eclipse.text.edits.TextEditGroup; + +import org.eclipse.cdt.core.dom.ast.IASTComment; +import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTNode.CopyStyle; +import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCatchHandler; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionWithTryBlock; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration; +import org.eclipse.cdt.core.dom.rewrite.ASTRewrite; +import org.eclipse.cdt.core.dom.rewrite.ASTRewrite.CommentPosition; + +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTSimpleDeclaration; + +import org.eclipse.cdt.internal.ui.refactoring.ModificationCollector; + +public class ToggleFromInHeaderToClassStrategy implements IToggleRefactoringStrategy { + + private TextEditGroup infoText; + private ToggleRefactoringContext context; + + public ToggleFromInHeaderToClassStrategy(ToggleRefactoringContext context) { + if (isFreeFunction(context)) + throw new NotSupportedException(Messages.ToggleFromInHeaderToClassStrategy_CanNotToggleTemplateFreeFunction); + this.context = context; + this.infoText = new TextEditGroup(Messages.EditGroupName); + } + + private boolean isFreeFunction(ToggleRefactoringContext context) { + return isNotInsideAClass(context.getDefinition().getDeclarator(), + context.getDeclaration()); + } + + boolean isNotInsideAClass(IASTFunctionDeclarator declarator, IASTFunctionDeclarator backup) { + if (declarator.getName() instanceof ICPPASTQualifiedName) { + declarator = backup; + } + return (ToggleNodeHelper.getAncestorOfType(declarator, + IASTCompositeTypeSpecifier.class) == null); + } + + public void run(ModificationCollector modifications) { + ASTRewrite rewriter = removeDefinition(modifications); + IASTFunctionDefinition newDefinition = getNewDefinition(); + replaceDeclarationWithDefinition(rewriter, newDefinition); + + IASTNode parentTemplateDeclaration = + ToggleNodeHelper.getParentTemplateDeclaration(context.getDeclaration()); + if (parentTemplateDeclaration instanceof ICPPASTTemplateDeclaration) { + } else { + restoreLeadingComments(rewriter, newDefinition); + } + } + + private void restoreLeadingComments(ASTRewrite rewriter, IASTFunctionDefinition newDefinition) { + Listcomments = rewriter.getComments(context.getDefinition().getParent(), CommentPosition.leading); + if(comments != null) { + for (IASTComment comment : comments) { + rewriter.addComment(newDefinition, comment, CommentPosition.leading); + rewriter.remove(comment, infoText); + } + } + } + + private ASTRewrite removeDefinition(ModificationCollector modifications) { + ASTRewrite rewriter = modifications.rewriterForTranslationUnit(context.getDefinitionUnit()); + IASTNode parentRemovePoint = ToggleNodeHelper.getParentRemovePoint(context.getDefinition()); + rewriter.remove(parentRemovePoint, infoText); + return rewriter; + } + + private IASTFunctionDefinition getNewDefinition() { + IASTFunctionDefinition newDefinition = ToggleNodeHelper.createInClassDefinition( + context.getDeclaration(), context.getDefinition(), context.getDefinitionUnit()); + newDefinition.setBody(context.getDefinition().getBody().copy(CopyStyle.withLocations)); + if (newDefinition instanceof ICPPASTFunctionWithTryBlock) { + ICPPASTFunctionWithTryBlock newTryFun = (ICPPASTFunctionWithTryBlock) newDefinition; + ICPPASTFunctionWithTryBlock oldTryFun = (ICPPASTFunctionWithTryBlock) context.getDefinition(); + for (ICPPASTCatchHandler catchH : oldTryFun.getCatchHandlers()) { + newTryFun.addCatchHandler(catchH.copy(CopyStyle.withLocations)); + } + } + + IASTNode parent = ToggleNodeHelper.getAncestorOfType(context.getDefinition(), + ICPPASTCompositeTypeSpecifier.class); + if (parent != null) { + newDefinition.setParent(parent); + } + else { + newDefinition.setParent(context.getDefinitionUnit()); + } + return newDefinition; + } + + private ASTRewrite replaceDeclarationWithDefinition(ASTRewrite rewriter, + IASTFunctionDefinition newDefinition) { + IASTSimpleDeclaration fullDeclaration = ToggleNodeHelper.getAncestorOfType( + context.getDeclaration(), CPPASTSimpleDeclaration.class); + ASTRewrite newRewriter = rewriter.replace(fullDeclaration, newDefinition, infoText); + return newRewriter; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleFromInHeaderToImplementationStrategy.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleFromInHeaderToImplementationStrategy.java new file mode 100644 index 00000000000..36eba0e5d17 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleFromInHeaderToImplementationStrategy.java @@ -0,0 +1,382 @@ +/******************************************************************************* + * Copyright (c) 2011 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: + * Martin Schwab & Thomas Kallenberg - initial API and implementation + ******************************************************************************/ +package org.eclipse.cdt.internal.ui.refactoring.togglefunction; + +import java.util.List; + +import org.eclipse.text.edits.TextEditGroup; + +import org.eclipse.cdt.core.dom.ast.ASTVisitor; +import org.eclipse.cdt.core.dom.ast.IASTArrayModifier; +import org.eclipse.cdt.core.dom.ast.IASTComment; +import org.eclipse.cdt.core.dom.ast.IASTCopyLocation; +import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator; +import org.eclipse.cdt.core.dom.ast.IASTExpression; +import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; +import org.eclipse.cdt.core.dom.ast.IASTInitializer; +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTNode.CopyStyle; +import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTPointerOperator; +import org.eclipse.cdt.core.dom.ast.IASTProblem; +import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTStatement; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.dom.ast.IASTTypeId; +import org.eclipse.cdt.core.dom.ast.c.ICASTDesignator; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCapture; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCatchHandler; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionWithTryBlock; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateParameter; +import org.eclipse.cdt.core.dom.rewrite.ASTRewrite; +import org.eclipse.cdt.core.dom.rewrite.ASTRewrite.CommentPosition; + +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTNamespaceDefinition; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTQualifiedName; +import org.eclipse.cdt.internal.core.dom.rewrite.ASTLiteralNode; + +import org.eclipse.cdt.internal.ui.refactoring.Container; +import org.eclipse.cdt.internal.ui.refactoring.ModificationCollector; + +public class ToggleFromInHeaderToImplementationStrategy implements IToggleRefactoringStrategy { + + private IASTTranslationUnit impl_unit; + private ToggleRefactoringContext context; + private TextEditGroup infoText; + private ASTLiteralNode includenode; + + public ToggleFromInHeaderToImplementationStrategy(final ToggleRefactoringContext context) { + this.infoText = new TextEditGroup(Messages.EditGroupName); + this.context = context; + } + + public void run(ModificationCollector collector) { + if(!newFileCheck()) { + return; + } +// newFileCheck(); + ICPPASTFunctionDefinition newDefinition = getNewDefinition(); + if (context.getDeclaration() != null) { + removeDefinitionFromHeader(collector); + } + else { + replaceDefinitionWithDeclaration(collector); + } + + ASTRewrite implRewrite = collector.rewriterForTranslationUnit(impl_unit); + if (includenode != null) { + implRewrite.insertBefore(impl_unit, null, includenode, infoText); + } + + IASTNode insertionParent = null; + ICPPASTNamespaceDefinition parent = getParentNamespace(); + + if (parent != null) { + adaptQualifiedNameToNamespaceLevel(newDefinition, parent); + insertionParent = searchNamespaceInImplementation(parent.getName()); + if (insertionParent == null) { + insertionParent = createNamespace(parent); + implRewrite = implRewrite.insertBefore(impl_unit.getTranslationUnit(), + null, insertionParent, infoText); + } + } + else { + insertionParent = impl_unit.getTranslationUnit(); + } + + newDefinition.setParent(insertionParent); + + IASTNode insertionPoint = findInsertionPoint(insertionParent, + context.getDeclarationUnit()); + ASTRewrite newRewriter = implRewrite.insertBefore(insertionParent, + insertionPoint, newDefinition, infoText); + copyCommentsToNewFile(newDefinition, newRewriter, collector.rewriterForTranslationUnit(context.getDefinitionUnit())); + restoreLeadingComments(newDefinition, newRewriter, collector); + } + + private void copyCommentsToNewFile(ICPPASTFunctionDefinition newDefinition, final ASTRewrite newRewriter, + final ASTRewrite oldRewriter) { + newDefinition.accept(new ASTVisitor(true) { + + private void copy(IASTNode node) { + copyComments(node, newRewriter, oldRewriter, CommentPosition.leading); + copyComments(node, newRewriter, oldRewriter, CommentPosition.trailing); + copyComments(node, newRewriter, oldRewriter, CommentPosition.freestanding); + } + + private void copyComments(IASTNode node, ASTRewrite newRewriter, ASTRewrite oldRewriter, + CommentPosition pos) { + if (node.getNodeLocations().length > 0 && node.getNodeLocations()[0] instanceof IASTCopyLocation) { + IASTCopyLocation copyLoc = (IASTCopyLocation) node.getNodeLocations()[0]; + List comments = oldRewriter.getComments(copyLoc.getOriginalNode(), pos); + for (IASTComment comment : comments) { + newRewriter.addComment(node, comment, pos); + } + } + + } + + @Override + public int visit(IASTName name) { + copy(name); + return super.visit(name); + } + + @Override + public int visit(IASTDeclaration declaration) { + copy(declaration); + return super.visit(declaration); + } + + @Override + public int visit(IASTInitializer initializer) { + copy(initializer); + return super.visit(initializer); + } + + @Override + public int visit(IASTParameterDeclaration parameterDeclaration) { + copy(parameterDeclaration); + return super.visit(parameterDeclaration); + } + + @Override + public int visit(IASTDeclarator declarator) { + copy(declarator); + return super.visit(declarator); + } + + @Override + public int visit(IASTDeclSpecifier declSpec) { + copy(declSpec); + return super.visit(declSpec); + } + + @Override + public int visit(IASTArrayModifier arrayModifier) { + copy(arrayModifier); + return super.visit(arrayModifier); + } + + @Override + public int visit(IASTPointerOperator ptrOperator) { + copy(ptrOperator); + return super.visit(ptrOperator); + } + + @Override + public int visit(IASTExpression expression) { + copy(expression); + return super.visit(expression); + } + + @Override + public int visit(IASTStatement statement) { + copy(statement); + return super.visit(statement); + } + + @Override + public int visit(IASTTypeId typeId) { + copy(typeId); + return super.visit(typeId); + } + + @Override + public int visit(IASTEnumerator enumerator) { + copy(enumerator); + return super.visit(enumerator); + } + + @Override + public int visit(IASTProblem problem) { + copy(problem); + return super.visit(problem); + } + + @Override + public int visit(ICPPASTBaseSpecifier baseSpecifier) { + copy(baseSpecifier); + return super.visit(baseSpecifier); + } + + @Override + public int visit(ICPPASTNamespaceDefinition namespaceDefinition) { + copy(namespaceDefinition); + return super.visit(namespaceDefinition); + } + + @Override + public int visit(ICPPASTTemplateParameter templateParameter) { + copy(templateParameter); + return super.visit(templateParameter); + } + + @Override + public int visit(ICPPASTCapture capture) { + copy(capture); + return super.visit(capture); + } + + @Override + public int visit(ICASTDesignator designator) { + copy(designator); + return super.visit(designator); + } + }); + + } + + private boolean newFileCheck() { + impl_unit = context.getTUForSiblingFile(); + if (this.impl_unit == null) { + ToggleFileCreator filecreator = new ToggleFileCreator(context, ".cpp"); //$NON-NLS-1$ + if (filecreator.askUserForFileCreation(context)) { + filecreator.createNewFile(); + impl_unit = filecreator.loadTranslationUnit(); + includenode = new ASTLiteralNode(filecreator.getIncludeStatement()); + return true; + }else { + return false; + } + } + return true; + } + + private ICPPASTNamespaceDefinition getParentNamespace() { + IASTNode toquery = context.getDeclaration(); + if (toquery == null) { + toquery = context.getDefinition(); + } + return ToggleNodeHelper.getAncestorOfType(toquery, ICPPASTNamespaceDefinition.class); + } + + private IASTNode findInsertionPoint(IASTNode insertionParent, + IASTTranslationUnit unit) { + IASTFunctionDeclarator declarator = context.getDeclaration(); + if (unit == null) { + unit = context.getDefinitionUnit(); + } + if (declarator == null) { + declarator = context.getDefinition().getDeclarator(); + } + IASTNode insertion_point = InsertionPointFinder.findInsertionPoint( + unit, insertionParent.getTranslationUnit(), declarator); + return insertion_point; + } + + private void restoreLeadingComments( + ICPPASTFunctionDefinition newDefinition, ASTRewrite newRewriter, ModificationCollector collector) { + ASTRewrite rw = collector.rewriterForTranslationUnit(context.getDefinitionUnit()); + Listcomments = rw.getComments(context.getDefinition(), CommentPosition.leading); + if(comments != null) { + for (IASTComment comment : comments) { + newRewriter.addComment(newDefinition, comment, CommentPosition.leading); + if(context.getDeclaration() != null) { + rw.remove(comment, infoText); + } + } + } + } + + private void replaceDefinitionWithDeclaration( + ModificationCollector collector) { + IASTSimpleDeclaration newdeclarator = + ToggleNodeHelper.createDeclarationFromDefinition(context.getDefinition()); + ASTRewrite rewrite = collector.rewriterForTranslationUnit(context.getDefinitionUnit()); + rewrite.replace(context.getDefinition(), newdeclarator, infoText); + } + + private ICPPASTFunctionDefinition getNewDefinition() { + ICPPASTFunctionDefinition newDefinition = + ToggleNodeHelper.createFunctionSignatureWithEmptyBody( + context.getDefinition().getDeclSpecifier().copy(CopyStyle.withLocations), context + .getDefinition().getDeclarator().copy(CopyStyle.withLocations), context + .getDefinition().copy(CopyStyle.withLocations)); + newDefinition.getDeclSpecifier().setInline(false); + newDefinition.setBody(context.getDefinition().getBody().copy(CopyStyle.withLocations)); + if (newDefinition instanceof ICPPASTFunctionWithTryBlock) { + ICPPASTFunctionWithTryBlock newTryFun = (ICPPASTFunctionWithTryBlock) newDefinition; + ICPPASTFunctionWithTryBlock oldTryFun = (ICPPASTFunctionWithTryBlock) context.getDefinition(); + for (ICPPASTCatchHandler catchHandler : oldTryFun.getCatchHandlers()) { + newTryFun.addCatchHandler(catchHandler.copy(CopyStyle.withLocations)); + } + } + return newDefinition; + } + + private void adaptQualifiedNameToNamespaceLevel( + IASTFunctionDefinition new_definition, IASTNode parent) { + if (parent instanceof ICPPASTNamespaceDefinition) { + ICPPASTNamespaceDefinition ns = (ICPPASTNamespaceDefinition) parent; + if (new_definition.getDeclarator().getName() instanceof ICPPASTQualifiedName) { + ICPPASTQualifiedName qname = + (ICPPASTQualifiedName) new_definition.getDeclarator().getName(); + ICPPASTQualifiedName qname_new = new CPPASTQualifiedName(); + boolean start = false; + for(IASTName partname: qname.getNames()) { + if (partname.toString().equals(ns.getName().toString())) { + start = true; + continue; + } + if (start) + qname_new.addName(partname); + } + if (start) + new_definition.getDeclarator().setName(qname_new); + } + } + } + + private CPPASTNamespaceDefinition createNamespace( + ICPPASTNamespaceDefinition parent_namespace) { + CPPASTNamespaceDefinition insertionParent = new CPPASTNamespaceDefinition( +parent_namespace.getName() + .copy(CopyStyle.withLocations)); + insertionParent.setParent(impl_unit); + return insertionParent; + } + + private void removeDefinitionFromHeader(ModificationCollector collector) { + ASTRewrite header_rewrite = collector.rewriterForTranslationUnit( + context.getDefinitionUnit()); + header_rewrite.remove(ToggleNodeHelper.getParentRemovePoint(context.getDefinition()), infoText); + } + + private IASTNode searchNamespaceInImplementation(final IASTName name) { + final Container result = new Container(); + this.impl_unit.accept( +new ASTVisitor() { + { + shouldVisitNamespaces = true; + } + @Override + public int visit(ICPPASTNamespaceDefinition namespaceDefinition) { + if (name.toString().equals(namespaceDefinition.getName().toString())) { + result.setObject(namespaceDefinition); + return PROCESS_ABORT; + } + return super.visit(namespaceDefinition); + } + }); + return result.getObject(); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleNodeHelper.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleNodeHelper.java new file mode 100644 index 00000000000..795d40638b3 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleNodeHelper.java @@ -0,0 +1,460 @@ +/******************************************************************************* + * Copyright (c) 2011 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: + * Martin Schwab & Thomas Kallenberg - initial API and implementation + ******************************************************************************/ +package org.eclipse.cdt.internal.ui.refactoring.togglefunction; + +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; +import java.util.Stack; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.Path; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.dom.ast.IASTComment; +import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTNode.CopyStyle; +import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCatchHandler; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorChainInitializer; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionWithTryBlock; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleTypeTemplateParameter; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId; +import org.eclipse.cdt.core.dom.rewrite.ASTRewrite; +import org.eclipse.cdt.core.dom.rewrite.ASTRewrite.CommentPosition; +import org.eclipse.cdt.core.index.IIndex; +import org.eclipse.cdt.core.index.IIndexFile; +import org.eclipse.cdt.core.index.IIndexInclude; +import org.eclipse.cdt.core.index.IndexLocationFactory; +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.model.CoreModelUtil; +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.model.ITranslationUnit; + +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTCompoundStatement; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTFunctionDefinition; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTFunctionWithTryBlock; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTNamedTypeSpecifier; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTQualifiedName; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTSimpleDeclaration; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTemplateId; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTypeId; +import org.eclipse.cdt.internal.core.model.TranslationUnit; + +import org.eclipse.cdt.internal.ui.refactoring.ModificationCollector; +import org.eclipse.cdt.internal.ui.refactoring.utils.NodeHelper; + +public class ToggleNodeHelper extends NodeHelper { + + private static final String EMPTY_STRING = ""; //$NON-NLS-1$ + + private static void removeParameterInitializations(IASTFunctionDeclarator funcDecl) { + for (IASTNode child : funcDecl.getChildren()) { + if (child instanceof IASTParameterDeclaration) { + IASTParameterDeclaration parameter = (IASTParameterDeclaration) child; + parameter.getDeclarator().setInitializer(null); + } + } + } + + private static ArrayList + getInitializerList(IASTFunctionDefinition definition) { + ArrayList initalizers = + new ArrayList(); + + for (IASTNode node : definition.getChildren()) { + if (node instanceof ICPPASTConstructorChainInitializer) { + initalizers.add(((ICPPASTConstructorChainInitializer) node).copy(CopyStyle.withLocations)); + } + } + return initalizers; + } + + static IASTSimpleDeclaration createDeclarationFromDefinition( + IASTFunctionDefinition oldDefinition) { + IASTDeclarator newDeclarator = oldDefinition.getDeclarator().copy(CopyStyle.withLocations); + IASTDeclSpecifier newDeclSpec = oldDefinition.getDeclSpecifier().copy(CopyStyle.withLocations); + IASTSimpleDeclaration newDeclaration = new CPPASTSimpleDeclaration(newDeclSpec); + newDeclaration.addDeclarator(newDeclarator); + return newDeclaration; + } + + static ICPPASTFunctionDefinition createFunctionSignatureWithEmptyBody( + IASTDeclSpecifier newDeclSpec, IASTFunctionDeclarator newFuncDecl, + IASTFunctionDefinition oldDefinition) { + ICPPASTFunctionDefinition newFunc = null; + if (oldDefinition instanceof ICPPASTFunctionWithTryBlock) { + newFunc = new CPPASTFunctionWithTryBlock(newDeclSpec, newFuncDecl, + new CPPASTCompoundStatement()); + } else { + newFunc = new CPPASTFunctionDefinition(newDeclSpec, newFuncDecl, + new CPPASTCompoundStatement()); + } + copyInitializerList(newFunc, oldDefinition); + return newFunc; + } + + private static void copyInitializerList(ICPPASTFunctionDefinition newFunc, + IASTFunctionDefinition oldFunc) { + for (ICPPASTConstructorChainInitializer initializer : getInitializerList(oldFunc)) { + initializer.setParent(newFunc); + newFunc.addMemberInitializer(initializer); + } + } + + static IASTFunctionDefinition getQualifiedNameDefinition(IASTFunctionDefinition oldDefinition, + IASTTranslationUnit definitionUnit, IASTNode nameSpace) { + + ICPPASTDeclSpecifier newDeclSpec = + (ICPPASTDeclSpecifier) oldDefinition.getDeclSpecifier().copy( + CopyStyle.withLocations); + + newDeclSpec.setVirtual(false); + newDeclSpec.setInline(true); + newDeclSpec.setStorageClass(IASTDeclSpecifier.sc_unspecified); + + IASTFunctionDeclarator newDeclarator = oldDefinition.getDeclarator().copy(CopyStyle.withLocations); + newDeclarator.setName(getQualifiedName(oldDefinition.getDeclarator(), nameSpace)); + removeParameterInitializations(newDeclarator); + + ICPPASTFunctionDefinition newFunction = + createFunctionSignatureWithEmptyBody(newDeclSpec, newDeclarator, oldDefinition); + + return newFunction; + } + + public static ICPPASTTemplateDeclaration getTemplateDeclaration( + IASTFunctionDefinition oldFunction, IASTFunctionDefinition newFunction) { + ArrayList templateDeclarations = getAllTemplateDeclaration(oldFunction); + return addTemplateDeclarationsInOrder(templateDeclarations, newFunction); + } + + private static ICPPASTTemplateDeclaration addTemplateDeclarationsInOrder( + ArrayList templdecs, IASTFunctionDefinition newfunc) { + ListIterator iter1 = templdecs.listIterator(); + ICPPASTTemplateDeclaration child = null; + while(iter1.hasNext()) { + child = iter1.next(); + child.setDeclaration(newfunc); + ListIterator iter2 = iter1; + if (iter2.hasNext()) { + ICPPASTTemplateDeclaration parent = iter2.next(); + child.setParent(parent); + parent.setDeclaration(child); + child = parent; + } + } + return child; + } + + private static ArrayList getAllTemplateDeclaration( + IASTNode node) { + ArrayList templdecs = new ArrayList(); + while (node.getParent() != null) { + node = node.getParent(); + if (node instanceof ICPPASTTemplateDeclaration) { + templdecs.add((ICPPASTTemplateDeclaration) node.copy(CopyStyle.withLocations)); + } + } + return templdecs; + } + + static IASTFunctionDefinition createInClassDefinition( + IASTFunctionDeclarator dec, + IASTFunctionDefinition def, + IASTTranslationUnit insertionunit) { + IASTFunctionDeclarator declarator = dec.copy(CopyStyle.withLocations); + ICPPASTDeclSpecifier declSpec = (ICPPASTDeclSpecifier) def.getDeclSpecifier().copy( + CopyStyle.withLocations); + declSpec.setInline(false); + if (ToggleNodeHelper.isVirtual(dec)) { + declSpec.setVirtual(true); + } + declSpec.setStorageClass(getStorageClass(dec)); + + return createFunctionSignatureWithEmptyBody(declSpec, declarator, def); + } + + static boolean isVirtual(IASTFunctionDeclarator fdec) { + if (fdec.getParent() instanceof IASTSimpleDeclaration) { + IASTSimpleDeclaration dec = (IASTSimpleDeclaration) fdec.getParent(); + return ((ICPPASTDeclSpecifier) dec.getDeclSpecifier()).isVirtual(); + } + return false; + } + + static int getStorageClass(IASTFunctionDeclarator fdec) { + if (fdec.getParent() instanceof IASTSimpleDeclaration) { + IASTSimpleDeclaration dec = (IASTSimpleDeclaration) fdec.getParent(); + return ((ICPPASTDeclSpecifier) dec.getDeclSpecifier()).getStorageClass(); + } + return -1; + } + + static IASTNode getParentRemovePoint(IASTFunctionDefinition definition) { + IASTNode toremove = definition; + while (toremove.getParent() != null && + toremove.getParent() instanceof ICPPASTTemplateDeclaration) + toremove = toremove.getParent(); + return toremove; + } + + /** + * @param declarator the declarator from which the full qualified namespace should be fetched + * @param limiter set a limiter in the class hierarchy where the lookup will stop + * @return + */ + static ICPPASTQualifiedName getQualifiedName(IASTFunctionDeclarator declarator, IASTNode limiter) { + Stack nodes = getQualifiedNames(declarator, limiter, declarator); + CPPASTQualifiedName qName = reAssembleQualifiedName(nodes); + qName.addName(declarator.getName().copy(CopyStyle.withLocations)); + return qName; + } + + private static CPPASTQualifiedName reAssembleQualifiedName(Stack nodes) { + CPPASTQualifiedName qName = new CPPASTQualifiedName(); + while(!nodes.isEmpty()) { + IASTNode nnode = nodes.pop(); + if (nnode instanceof IASTCompositeTypeSpecifier) { + qName.addName(((IASTCompositeTypeSpecifier) nnode).getName()); + } + else if (nnode instanceof ICPPASTNamespaceDefinition) { + qName.addName(((ICPPASTNamespaceDefinition) nnode).getName()); + } + else if (nnode instanceof ICPPASTTemplateId) { + qName.addName((ICPPASTTemplateId) nnode); + } + } + return qName; + } + + private static Stack getQualifiedNames( + IASTFunctionDeclarator declarator, IASTNode limiter, IASTNode node) { + IASTName lastName = declarator.getName(); + Stack nodes = new Stack(); + while(node.getParent() != null && node.getParent() != limiter) { + node = node.getParent(); + if (node instanceof IASTCompositeTypeSpecifier) { + nodes.push(((IASTCompositeTypeSpecifier) node).copy(CopyStyle.withLocations)); + lastName = ((IASTCompositeTypeSpecifier) node).getName(); + } + else if (node instanceof ICPPASTNamespaceDefinition) { + nodes.push(((ICPPASTNamespaceDefinition) node).copy(CopyStyle.withLocations)); + lastName = ((ICPPASTNamespaceDefinition) node).getName(); + } + else if (shouldAddTemplateBrackets(node)) { + if (!nodes.isEmpty()) + nodes.pop(); + ICPPASTTemplateId templateID = ToggleNodeHelper.getTemplateParameter(node, lastName); + nodes.add(templateID); + } + } + return nodes; + } + + private static boolean shouldAddTemplateBrackets(IASTNode node) { + return node instanceof ICPPASTTemplateDeclaration + && !(((ICPPASTTemplateDeclaration) node).getDeclaration() + instanceof CPPASTFunctionDefinition); + } + + private static ICPPASTTemplateId getTemplateParameter(IASTNode node, IASTName name) { + ICPPASTTemplateId templateID = new CPPASTTemplateId(); + templateID.setTemplateName(name.copy(CopyStyle.withLocations)); + for(IASTNode child : node.getChildren()) { + if (child instanceof ICPPASTSimpleTypeTemplateParameter) { + ICPPASTSimpleTypeTemplateParameter tempcild = (ICPPASTSimpleTypeTemplateParameter) child; + + CPPASTNamedTypeSpecifier namedTypeSpecifier = new CPPASTNamedTypeSpecifier(); + namedTypeSpecifier.setName(tempcild.getName().copy(CopyStyle.withLocations)); + + CPPASTTypeId id = new CPPASTTypeId(); + id.setDeclSpecifier(namedTypeSpecifier); + templateID.addTemplateArgument(id); + } + } + return templateID; + } + + static IASTTranslationUnit getSiblingFile(IFile file, IASTTranslationUnit asttu) throws CoreException { + ICProject cProject = CoreModel.getDefault().create(file).getCProject(); + ICProject[] projects = CoreModel.getDefault().getCModel().getCProjects(); + IIndex projectIndex = CCorePlugin.getIndexManager().getIndex(projects); + try { + projectIndex.acquireReadLock(); + + IIndexFile thisFile = projectIndex.getFile(asttu.getLinkage().getLinkageID(), + IndexLocationFactory.getWorkspaceIFL(file)); + String fileName = ToggleNodeHelper.getFilenameWithoutExtension( + file.getFullPath().toString()); + if (asttu.isHeaderUnit()) { + for (IIndexInclude include : projectIndex.findIncludedBy(thisFile)) { + if (ToggleNodeHelper.getFilenameWithoutExtension(include.getIncludedBy().getLocation().getFullPath()).equals(fileName)) { + ITranslationUnit tu = CoreModelUtil.findTranslationUnitForLocation(include.getIncludedBy().getLocation().getURI(), cProject); + return tu.getAST(projectIndex, ITranslationUnit.AST_SKIP_ALL_HEADERS); + } + } + } else { + for (IIndexInclude include : projectIndex.findIncludes(thisFile)) { + if (ToggleNodeHelper.getFilenameWithoutExtension(include.getFullName()).equals(fileName)) { + if (include.getIncludesLocation() == null){ + throw new NotSupportedException("The include file does not exist"); //$NON-NLS-1$ + } + String loc = include.getIncludesLocation().getFullPath(); + ICElement tufile = CoreModel.getDefault().create(new Path(loc)); + if (tufile instanceof TranslationUnit) { + return ((TranslationUnit) tufile).getAST(null, ITranslationUnit.AST_SKIP_ALL_HEADERS); + } + } + } + } + }catch (InterruptedException e) { + e.printStackTrace(); + } finally { + projectIndex.releaseReadLock(); + } + return null; + } + + public static String getFilenameWithoutExtension(String filename) { + int index = filename.lastIndexOf('.'); + return filename.substring(0, index); + } + + /** + * Will extract the innermost ICPPASTFunctionDefinition out of a template declaration. + * + * template // <-- input this node + * template + * void function(T t, U u) { ... } // <-- will find this node here + * + * @param declaration the template declaration that should be searched for the function definition. + * @return null if a declaration is found instead of a definition. + */ + public static ICPPASTFunctionDefinition getFunctionDefinition(IASTNode declaration) { + IASTNode node = declaration; + while (node != null) { + if (node instanceof ICPPASTTemplateDeclaration) { + ICPPASTTemplateDeclaration templdec = (ICPPASTTemplateDeclaration) node; + node = templdec.getDeclaration(); + continue; + } + if (node instanceof ICPPASTFunctionDefinition) { + return (ICPPASTFunctionDefinition) node; + } else { + return null; + } + } + return null; + } + + /** + * Gets comments inside the body of a function. + * @return The body as a string and all the catch handlers + */ + public static String getBody(IASTFunctionDefinition oldDefinition, IASTTranslationUnit oldUnit, + ModificationCollector modifications) { + return getBodyOnly(oldDefinition, oldUnit, modifications) + + getCatchHandlers(oldDefinition, oldUnit, modifications); + } + + private static String getBodyOnly(IASTFunctionDefinition oldDefinition, IASTTranslationUnit oldUnit, + ModificationCollector modifications) { + String leadingComments = getCommentsAsString(getLeadingCommentsFromNode(oldDefinition.getBody(), + oldUnit, modifications)); + String trailingComments = getCommentsAsString(getTrailingComments(oldDefinition.getBody(), oldUnit, + modifications)); + return leadingComments + oldDefinition.getBody().getRawSignature() + trailingComments; + } + + private static String getCatchHandlers(IASTFunctionDefinition oldDefinition, IASTTranslationUnit oldUnit, + ModificationCollector modifications) { + if (oldDefinition instanceof ICPPASTFunctionWithTryBlock) { + ICPPASTCatchHandler[] oldCatches = ((ICPPASTFunctionWithTryBlock) oldDefinition) + .getCatchHandlers(); + String allCatchHandlers = ""; //$NON-NLS-1$ + for (int i = 0; i < oldCatches.length; i++) { + String lead = getCommentsAsString(getLeadingCommentsFromNode(oldCatches[i], oldUnit, + modifications)); + String trail = getCommentsAsString(getTrailingComments(oldCatches[i], oldUnit, modifications)); + allCatchHandlers += lead + oldCatches[i].getRawSignature() + trail; + } + return allCatchHandlers; + } + return ""; //$NON-NLS-1$ + } + + private static List getLeadingCommentsFromNode(IASTNode existingNode, + IASTTranslationUnit oldUnit, ModificationCollector modifications) { + ASTRewrite rw = modifications.rewriterForTranslationUnit(oldUnit); + return rw.getComments(existingNode, CommentPosition.leading); + } + + private static List getTrailingComments(IASTNode existingNode, + IASTTranslationUnit oldUnit, ModificationCollector modifications) { + ASTRewrite rw = modifications.rewriterForTranslationUnit(oldUnit); + return rw.getComments(existingNode, CommentPosition.trailing); + } + + + public static IASTNode getParentTemplateDeclaration( + IASTNode def) { + if (def == null) + return null; + IASTNode lastSeen = def; + IASTNode node = def.getParent(); + while (node != null) { + if (node instanceof ICPPASTTemplateDeclaration || + node instanceof IASTSimpleDeclaration) { + lastSeen = node; + node = node.getParent(); + continue; + } + return lastSeen; + } + return lastSeen; + } + + private static String getCommentsAsString(List commentList) { + String comments = EMPTY_STRING; + for (IASTComment c : commentList) { + comments += c.getRawSignature() + System.getProperty("line.separator"); //$NON-NLS-1$ + } + return comments; + } + + @SuppressWarnings("unchecked") + public static T getAncestorOfType(IASTNode node, Class T) { + while(node != null) { + if (T.isInstance(node)) { + return (T) node; + } + node = node.getParent(); + } + return null; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleRefactoring.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleRefactoring.java new file mode 100644 index 00000000000..207b6cd5690 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleRefactoring.java @@ -0,0 +1,100 @@ +/******************************************************************************* + * Copyright (c) 2011 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: + * Martin Schwab & Thomas Kallenberg - initial API and implementation + ******************************************************************************/ +package org.eclipse.cdt.internal.ui.refactoring.togglefunction; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.ltk.core.refactoring.RefactoringDescriptor; +import org.eclipse.ltk.core.refactoring.RefactoringStatus; +import org.eclipse.ui.ide.IDE; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.index.IIndex; +import org.eclipse.cdt.core.index.IIndexManager; +import org.eclipse.cdt.core.model.ICProject; + +import org.eclipse.cdt.internal.core.pdom.indexer.IndexerPreferences; + +import org.eclipse.cdt.internal.ui.refactoring.CRefactoring; +import org.eclipse.cdt.internal.ui.refactoring.ModificationCollector; + +/** + * Determines whether a valid function was selected by the user to be able to + * run the appropriate strategy for moving the function body to another + * position. + */ +public class ToggleRefactoring extends CRefactoring { + + private ITextSelection selection; + private IToggleRefactoringStrategy strategy; + protected ToggleRefactoringContext context; + private IIndex fIndex; + + public ToggleRefactoring(IFile file, ITextSelection selection, ICProject proj) { + super(file, selection, null, proj); + if (selection == null || file == null || project == null) + initStatus.addFatalError(Messages.ToggleRefactoring_InvalidSelection); + if (!IDE.saveAllEditors(new IResource[] {ResourcesPlugin.getWorkspace().getRoot()}, false)) + initStatus.addFatalError(Messages.ToggleRefactoring_CanNotSaveFiles); + this.selection = selection; + } + + @Override + public RefactoringStatus checkInitialConditions(IProgressMonitor pm) + throws CoreException, OperationCanceledException { + try { + pm.subTask(Messages.ToggleRefactoring_WaitingForIndexer); + prepareIndexer(pm); + pm.subTask(Messages.ToggleRefactoring_AnalyseSelection); + context = new ToggleRefactoringContext(fIndex, file, selection); + strategy = new ToggleStrategyFactory(context).getAppropriateStategy(); + } catch (InterruptedException e) { + } catch (NotSupportedException e) { + initStatus.addFatalError(e.getMessage()); + } finally { + fIndex.releaseReadLock(); + } + + return initStatus; + } + + private void prepareIndexer(IProgressMonitor pm) throws CoreException, InterruptedException { + IIndexManager im = CCorePlugin.getIndexManager(); + while (!im.isProjectIndexed(project)) { + im.joinIndexer(500, pm); + if (pm.isCanceled()) + throw new NotSupportedException(Messages.ToggleRefactoring_NoIndex); + } + if (!im.isProjectIndexed(project)) + throw new NotSupportedException(Messages.ToggleRefactoring_NoIndex); + IndexerPreferences.set(project.getProject(), IndexerPreferences.KEY_INDEX_UNUSED_HEADERS_WITH_DEFAULT_LANG, Boolean.TRUE.toString()); + fIndex = CCorePlugin.getIndexManager().getIndex(project); + fIndex.acquireReadLock(); + } + + @Override + protected void collectModifications(IProgressMonitor pm, + ModificationCollector modifications) throws CoreException { + pm.subTask(Messages.ToggleRefactoring_CalculateModifications); + strategy.run(modifications); + } + + @Override + protected RefactoringDescriptor getRefactoringDescriptor() { + return new EmptyRefactoringDescription(); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleRefactoringContext.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleRefactoringContext.java new file mode 100644 index 00000000000..a263af8246c --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleRefactoringContext.java @@ -0,0 +1,201 @@ +/******************************************************************************* + * Copyright (c) 2011 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: + * Martin Schwab & Thomas Kallenberg - initial API and implementation + ******************************************************************************/ +package org.eclipse.cdt.internal.ui.refactoring.togglefunction; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.jface.text.ITextSelection; + +import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.index.IIndex; +import org.eclipse.cdt.core.index.IIndexName; +import org.eclipse.cdt.core.model.CModelException; +import org.eclipse.cdt.ui.CUIPlugin; + +import org.eclipse.cdt.internal.ui.refactoring.IndexToASTNameHelper; +import org.eclipse.cdt.internal.ui.refactoring.utils.TranslationUnitHelper; + +public class ToggleRefactoringContext { + + private IASTFunctionDefinition targetDefinition; + private IASTFunctionDeclarator targetDeclaration; + private IASTTranslationUnit targetDefinitionUnit; + private IASTTranslationUnit targetDeclarationUnit; + private IIndex index; + private IASTTranslationUnit selectionUnit; + private IFile selectionFile; + private IBinding binding; + private IASTName selectionName; + private boolean defaultAnswer; + private boolean settedDefaultAnswer; + + public ToggleRefactoringContext(IIndex index, IFile file, ITextSelection selection) { + this.index = index; + this.selectionFile = file; + findSelectionUnit(); + findSelectedFunctionDeclarator(selection); + findBinding(); + findDeclaration(); + findDefinition(); + } + + public void findSelectedFunctionDeclarator(ITextSelection selection) { + selectionName = new DeclaratorFinder(selection, selectionUnit).getName(); + } + + public void findBinding() { + try { + binding = index.findBinding(selectionName); + if(binding == null) { + binding = selectionName.resolveBinding(); + } + } catch (CoreException e) { + CUIPlugin.log(e); + } + } + + // Declaration may still be null afterwards, but thats ok. + public void findDeclaration() { + try { + IIndexName[] decnames = index.findNames(binding, IIndex.FIND_DECLARATIONS); + if (decnames.length > 1) + throw new NotSupportedException( + Messages.ToggleRefactoringContext_MultipleDeclarations); + for (IIndexName iname : decnames) { + selectionUnit = getTUForNameinFile(iname); + IASTName astname = IndexToASTNameHelper.findMatchingASTName( + selectionUnit, iname, index); + if (astname != null) { + targetDeclaration = findFunctionDeclarator(astname); + targetDeclarationUnit = selectionUnit; + break; + } + } + } catch (CoreException e) { + CUIPlugin.log(e); + } + } + + public void findDefinition() { + try { + IIndexName[] defnames = index.findNames(binding, IIndex.FIND_DEFINITIONS); + if (defnames.length > 1) { + throw new NotSupportedException(Messages.ToggleRefactoringContext_MultipleDefinitions); + } + for (IIndexName iname : defnames) { + IASTTranslationUnit unit = getTUForNameinFile(iname); + IASTName astname = IndexToASTNameHelper.findMatchingASTName( + unit, iname, index); + if (astname != null) { + targetDefinition = findFunctionDefinition(astname); + targetDefinitionUnit = unit; + break; + } + } + } catch (CoreException e) { + CUIPlugin.log(e); + } + if (targetDefinition == null) + throw new NotSupportedException(Messages.ToggleRefactoringContext_NoDefinitionFound); + } + + public IASTFunctionDeclarator getDeclaration() { + return targetDeclaration; + } + + public IASTFunctionDefinition getDefinition() { + return targetDefinition; + } + + public IASTTranslationUnit getDeclarationUnit() { + return targetDeclarationUnit; + } + + public IASTTranslationUnit getDefinitionUnit() { + return targetDefinitionUnit; + } + + public IFile getSelectionFile() { + return selectionFile; + } + + public IASTTranslationUnit getTUForSiblingFile() { + IASTTranslationUnit unit = getDeclarationUnit(); + if (unit == null) + unit = getDefinitionUnit(); + try { + return ToggleNodeHelper.getSiblingFile(getSelectionFile(), unit); + } catch (CoreException e) { + CUIPlugin.log(e); + return null; + } + } + + private void findSelectionUnit() { + try { + selectionUnit = TranslationUnitHelper.loadTranslationUnit( + selectionFile, true); + } catch (Exception e) { + } + if (selectionUnit == null) + throw new NotSupportedException(Messages.ToggleRefactoringContext_NoTuFound); + } + + private IASTTranslationUnit getTUForNameinFile(IIndexName iname) + throws CModelException, CoreException { + if (isSameFileAsInTU(iname)) { + return selectionUnit; + } + IPath path = new Path(iname.getFileLocation().getFileName()); + return TranslationUnitHelper.loadTranslationUnit(path.toString(), true); + } + + private boolean isSameFileAsInTU(IIndexName iname) { + return iname.getFileLocation().getFileName().equals( + selectionUnit.getFileLocation().getFileName()); + } + + private IASTFunctionDeclarator findFunctionDeclarator(IASTNode node) { + if (node instanceof IASTSimpleDeclaration) { + return (IASTFunctionDeclarator) ((IASTSimpleDeclaration) node).getDeclarators()[0]; + } + return ToggleNodeHelper.getAncestorOfType(node, IASTFunctionDeclarator.class); + } + + private IASTFunctionDefinition findFunctionDefinition(IASTNode node) { + return ToggleNodeHelper.getAncestorOfType(node, IASTFunctionDefinition.class); + } + + public void setDefaultAnswer(boolean defaultAnswer) { + this.defaultAnswer = defaultAnswer; + } + + public boolean getDefaultAnswer() { + return defaultAnswer; + } + + public void setSettedDefaultAnswer(boolean settedDefaultAnswer) { + this.settedDefaultAnswer = settedDefaultAnswer; + } + + public boolean isSettedDefaultAnswer() { + return settedDefaultAnswer; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleRefactoringRunner.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleRefactoringRunner.java new file mode 100644 index 00000000000..bdcec69bca3 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleRefactoringRunner.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2011 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: + * Martin Schwab & Thomas Kallenberg - initial API and implementation + ******************************************************************************/ +package org.eclipse.cdt.internal.ui.refactoring.togglefunction; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.window.IShellProvider; + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.ui.CUIPlugin; + +import org.eclipse.cdt.internal.ui.refactoring.RefactoringRunner; + +/** + * Responsible for scheduling a job which runs the ToggleRefactoring. Differs + * from other subclasses of RefactoringRunner in the way that it does not use a + * wizard but calls the refactoring directly. + */ +public class ToggleRefactoringRunner extends RefactoringRunner { + + private ToggleRefactoring refactoring; + + public ToggleRefactoringRunner(IFile file, ITextSelection selection, + ICElement element, IShellProvider shellProvider, ICProject project) { + super(file, selection, element, shellProvider, project); + refactoring = new ToggleRefactoring(file, selection, project); + } + + @Override + public void run() { + Job[] jobs = Job.getJobManager().find(RefactoringJob.FAMILY_TOGGLE_DEFINITION); + if (jobs.length > 0) { + CUIPlugin.log("no concurrent toggling allowed", new NotSupportedException("")); //$NON-NLS-1$//$NON-NLS-2$ + return; + } + new RefactoringJob(refactoring).schedule(); + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleStrategyFactory.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleStrategyFactory.java new file mode 100644 index 00000000000..19409907989 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleStrategyFactory.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2011 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: + * Martin Schwab & Thomas Kallenberg - initial API and implementation + ******************************************************************************/ +package org.eclipse.cdt.internal.ui.refactoring.togglefunction; + +import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration; + +public class ToggleStrategyFactory { + + private ToggleRefactoringContext context; + + public ToggleStrategyFactory(ToggleRefactoringContext context) { + this.context = context; + } + + public IToggleRefactoringStrategy getAppropriateStategy() { + if (context.getDefinition() == null) + throw new NotSupportedException(Messages.ToggleStrategyFactory_NoDefinitionFound); + if (!context.getDefinitionUnit().isHeaderUnit()) + return new ToggleFromImplementationToHeaderOrClassStrategy(context); + if (isInClassSituation()) + return new ToggleFromClassToInHeaderStrategy(context); + if (isTemplateSituation()) + return new ToggleFromInHeaderToClassStrategy(context); + if (isinHeaderSituation()) + return new ToggleFromInHeaderToImplementationStrategy(context); + throw new NotSupportedException(Messages.ToggleStrategyFactory_UnsupportedSituation); + } + + private boolean isinHeaderSituation() { + return (context.getDefinition() != null) + && (context.getDefinitionUnit().isHeaderUnit()); + } + + private boolean isInClassSituation() { + return (context.getDeclaration() == null) && + (ToggleNodeHelper.getAncestorOfType(context.getDefinition(), + IASTCompositeTypeSpecifier.class) != null); + } + + private boolean isTemplateSituation() { + return (ToggleNodeHelper.getAncestorOfType(context.getDefinition(), + ICPPASTTemplateDeclaration.class) != null); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/TogglingActionDelegate.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/TogglingActionDelegate.java new file mode 100644 index 00000000000..ee44cd6b4d1 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/TogglingActionDelegate.java @@ -0,0 +1,79 @@ +/******************************************************************************* + * Copyright (c) 2011 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: + * Martin Schwab & Thomas Kallenberg - initial API and implementation + ******************************************************************************/ +package org.eclipse.cdt.internal.ui.refactoring.togglefunction; + +import org.eclipse.core.resources.IFile; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.text.TextSelection; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.IWorkbenchWindowActionDelegate; + +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.model.IWorkingCopy; +import org.eclipse.cdt.ui.CUIPlugin; + +/** + * Represents the interface between the user who invokes the action and the + * actual refactoring mechanism. Starts the ToggleRefactoringRunner. + * + * Order of execution is: constructor, init, selectionChanged, run + */ +public class TogglingActionDelegate implements IWorkbenchWindowActionDelegate { + + private IWorkbenchWindow window; + private TextSelection selection; + private ICProject project; + private IFile file; + + public void init(IWorkbenchWindow window) { + this.window = window; + assert (window != null); + } + + public void selectionChanged(IAction action, ISelection selection) { + boolean isTextSelection = selection != null + && selection instanceof TextSelection; + action.setEnabled(isTextSelection); + if (!isTextSelection) + return; + //get our own selection due to (a possible) bug?? + this.selection = (TextSelection) CUIPlugin.getActivePage().getActiveEditor().getEditorSite().getSelectionProvider().getSelection(); + } + + public void run(IAction action) { + if (!isWorkbenchReady()) + return; + new ToggleRefactoringRunner(file, selection, project, window, project).run(); + } + + private boolean isWorkbenchReady() { + IWorkbenchPage activePage = window.getActivePage(); + if (activePage == null) + return false; + IEditorPart editor = activePage.getActiveEditor(); + if (editor == null || editor.getEditorInput() == null) + return false; + IWorkingCopy wc = CUIPlugin.getDefault().getWorkingCopyManager() + .getWorkingCopy(editor.getEditorInput()); + if (wc == null) + return false; + project = wc.getCProject(); + file = (IFile) wc.getResource(); + return project != null && file != null; + } + + public void dispose() { + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/messages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/messages.properties new file mode 100644 index 00000000000..c3af94a0c27 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/messages.properties @@ -0,0 +1,27 @@ +DeclaratorFinder_NestedFunction=Nested function declarations not supported +DeclaratorFinder_NoDeclarator=cannot work without declarator +RefactoringJob_UndoName=toggle function definition +ToggleFileCreator_andMove=\ and move +ToggleFileCreator_CanNotCreateNewFile=Cannot create new filechange +ToggleFileCreator_CreateNewFile=Create a new file named: +ToggleFileCreator_NewImplFile=New Implementation file? +ToggleFileCreator_NoTuForSibling=Cannot find translation unit for sibling file +ToggleFileCreator_QMark=? +ToggleFromClassToInHeaderStrategy_DefAndDecInsideClass=Definition and Declaration both inside class. Behavior is undefined. +ToggleFromImplementationToHeaderOrClassStrategy_CanNotCreateNewFile=Cannot create new File +ToggleFromImplementationToHeaderOrClassStrategy_CanNotToggle=Not a free function. Cannot decide where to toggle +ToggleFromInHeaderToClassStrategy_CanNotToggleTemplateFreeFunction=Cannot toggle templated free function +EditGroupName=Toggle function body placement +ToggleFromInHeaderToImplementationStrategy_CanNotCreateImplFile=Cannot create new Implementation File +ToggleRefactoring_AnalyseSelection=analyzing user text selection +ToggleRefactoring_CalculateModifications=calculating required code modifications +ToggleRefactoring_CanNotSaveFiles=Cannot save files +ToggleRefactoring_InvalidSelection=Invalid selection +ToggleRefactoring_NoIndex=cannot work without the indexer +ToggleRefactoring_WaitingForIndexer=waiting for indexer +ToggleRefactoringContext_MultipleDeclarations=multiple declarations would result in ambiguous results +ToggleRefactoringContext_MultipleDefinitions=one-definition-rule broken +ToggleRefactoringContext_NoDefinitionFound=cannot work without definition +ToggleRefactoringContext_NoTuFound=cannot work without translation unit +ToggleStrategyFactory_NoDefinitionFound=cannot work without function definition +ToggleStrategyFactory_UnsupportedSituation=Unsupported situation for moving function body. diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/actions/CdtActionConstants.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/actions/CdtActionConstants.java index 64891982b87..3bc790af8ae 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/actions/CdtActionConstants.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/actions/CdtActionConstants.java @@ -299,6 +299,14 @@ public class CdtActionConstants { */ public static final String EXTRACT_METHOD= "org.eclipse.cdt.ui.actions.ExtractMethod"; //$NON-NLS-1$ + /** + * Refactor menu: name of standard Toggle Function global action (value + * "org.eclipse.cdt.ui.actions.ExtractMethod"). + * + * @since 5.3 + */ + public static final String TOGGLE_FUNCTION = "org.eclipse.cdt.ui.actions.ToggleFunction"; //$NON-NLS-1$ + /** * Refactor menu: name of standard Inline global action * (value "org.eclipse.cdt.ui.actions.Inline"). diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/refactoring/actions/CRefactoringActionGroup.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/refactoring/actions/CRefactoringActionGroup.java index 10d29b6a2f3..9ade7e6b734 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/refactoring/actions/CRefactoringActionGroup.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/refactoring/actions/CRefactoringActionGroup.java @@ -116,6 +116,7 @@ public class CRefactoringActionGroup extends ActionGroup implements ISelectionCh private RefactoringAction fExtractConstantAction; private RefactoringAction fExtractLocalVariableAction; private RefactoringAction fExtractFunctionAction; + private RefactoringAction fToggleFunctionAction; private RefactoringAction fHideMethodAction; private IWorkbenchSite fSite; private List fAllActions= new ArrayList(); @@ -160,6 +161,10 @@ public class CRefactoringActionGroup extends ActionGroup implements ISelectionCh fExtractFunctionAction = new ExtractFunctionAction(); fExtractFunctionAction.setActionDefinitionId(ICEditorActionDefinitionIds.EXTRACT_FUNCTION); fAllActions.add(fExtractFunctionAction); + + fToggleFunctionAction = new ToggleFunctionAction(); + fToggleFunctionAction.setActionDefinitionId(ICEditorActionDefinitionIds.TOGGLE_FUNCTION); + fAllActions.add(fToggleFunctionAction); } fHideMethodAction = new HideMethodAction(); @@ -203,6 +208,7 @@ public class CRefactoringActionGroup extends ActionGroup implements ISelectionCh setActionHandler(actionBar, CdtActionConstants.EXTRACT_CONSTANT, fExtractConstantAction); setActionHandler(actionBar, CdtActionConstants.EXTRACT_LOCAL_VARIABLE, fExtractLocalVariableAction); setActionHandler(actionBar, CdtActionConstants.EXTRACT_METHOD, fExtractFunctionAction); + setActionHandler(actionBar, CdtActionConstants.TOGGLE_FUNCTION, fToggleFunctionAction); setActionHandler(actionBar, CdtActionConstants.HIDE_METHOD, fHideMethodAction); } @@ -234,6 +240,7 @@ public class CRefactoringActionGroup extends ActionGroup implements ISelectionCh addAction(refactorSubmenu, fExtractConstantAction); addAction(refactorSubmenu, fExtractLocalVariableAction); addAction(refactorSubmenu, fExtractFunctionAction); + addAction(refactorSubmenu, fToggleFunctionAction); addAction(refactorSubmenu, fHideMethodAction); refactorSubmenu.add(new Separator(GROUP_REORG2)); refactorSubmenu.add(new Separator(GROUP_TYPE)); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/refactoring/actions/Messages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/refactoring/actions/Messages.java index 479627d9a94..fb089c82729 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/refactoring/actions/Messages.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/refactoring/actions/Messages.java @@ -30,6 +30,10 @@ public class Messages extends NLS { public static String HideMethodAction_label; public static String ImplementMethodAction_label; public static String GettersAndSetters_label; + /** + * @since 5.3 + */ + public static String ToggleFunctionAction_label; static { // initialize resource bundle diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/refactoring/actions/ToggleFunctionAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/refactoring/actions/ToggleFunctionAction.java new file mode 100644 index 00000000000..5d98d2799c6 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/refactoring/actions/ToggleFunctionAction.java @@ -0,0 +1,80 @@ +/******************************************************************************* + * Copyright (c) 2011 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 (IFS)- initial API and implementation + ******************************************************************************/ +package org.eclipse.cdt.ui.refactoring.actions; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IResource; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.window.IShellProvider; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IWorkbenchPage; + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.model.IWorkingCopy; +import org.eclipse.cdt.ui.CUIPlugin; + +import org.eclipse.cdt.internal.ui.refactoring.togglefunction.ToggleRefactoringRunner; + +/** + * + * @since 5.3 + * @author Emanuel Graf IFS + * + * @noextend This class is not intended to be subclassed by clients. + */ +public class ToggleFunctionAction extends RefactoringAction { + private ICProject project; + private IFile file; + + public ToggleFunctionAction() { + super(Messages.ToggleFunctionAction_label); + } + + @Override + public void run(IShellProvider shellProvider, ICElement elem) { + } + + @Override + public void run(IShellProvider shellProvider, IWorkingCopy wc, + ITextSelection s) { + IResource res = wc.getResource(); + if (isWorkbenchReady(wc) && res instanceof IFile) { + new ToggleRefactoringRunner(file, s, project, shellProvider, project).run(); + } + } + + private boolean isWorkbenchReady(IWorkingCopy wc) { + try { + IWorkbenchPage activePage = CUIPlugin.getActivePage(); + if (activePage == null) + return false; + IEditorPart editor = activePage.getActiveEditor(); + if (editor == null || editor.getEditorInput() == null) + return false; + if (wc == null) + return false; + project = wc.getCProject(); + file = (IFile) wc.getResource(); + return project != null && file != null; + } catch (ClassCastException e) { + return false; + } + } + + @Override + public void updateSelection(ICElement elem) { + super.updateSelection(elem); + setEnabled(false); + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/refactoring/actions/messages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/refactoring/actions/messages.properties index 6c00c3ab274..251ae6ccb5e 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/refactoring/actions/messages.properties +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/refactoring/actions/messages.properties @@ -16,3 +16,4 @@ GettersAndSetters_label=Generate Getters and Setters... ImplementMethodAction_label=Implement Method... HideMethodAction_label=Hide Method... ExtractFunctionAction_label=Extract Function... +ToggleFunctionAction_label=Toggle Function Definition