Skip to main content
aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorMarkus Schorn2008-04-16 09:59:50 -0400
committerMarkus Schorn2008-04-16 09:59:50 -0400
commitcd48414961ff3e7ec5cc4f1ed8bd5aa575b771b7 (patch)
treef5741627cf6582a0171773c0b94305a5ae593005 /core
parent6df6c40158c211d18f71da8d5380e68894ff0d2f (diff)
downloadorg.eclipse.cdt-cd48414961ff3e7ec5cc4f1ed8bd5aa575b771b7.tar.gz
org.eclipse.cdt-cd48414961ff3e7ec5cc4f1ed8bd5aa575b771b7.tar.xz
org.eclipse.cdt-cd48414961ff3e7ec5cc4f1ed8bd5aa575b771b7.zip
Generate getters and setters by Emanuel Graf, bug 226658.
Diffstat (limited to 'core')
-rw-r--r--core/org.eclipse.cdt.ui.tests/resources/refactoring/GenerateGettersAndSetters.rts652
-rw-r--r--core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/RefactoringTestSuite.java3
-rw-r--r--core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/gettersandsetters/GenerateGettersAndSettersTest.java125
-rw-r--r--core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF1
-rw-r--r--core/org.eclipse.cdt.ui/plugin.properties3
-rw-r--r--core/org.eclipse.cdt.ui/plugin.xml27
-rw-r--r--core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/ICEditorActionDefinitionIds.java6
-rw-r--r--core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/CRefactoring.java2
-rw-r--r--core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/FunctionFactory.java108
-rw-r--r--core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GenerateGettersAndSettersInputPage.java72
-rw-r--r--core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GenerateGettersAndSettersRefactoring.java123
-rw-r--r--core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GenerateGettersAndSettersRefactoringRunner.java49
-rw-r--r--core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GenerateGettersAndSettersRefactoringWizard.java37
-rw-r--r--core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GetterAndSetterContext.java167
-rw-r--r--core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GetterSetterInsertEditProvider.java33
-rw-r--r--core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/Messages.java30
-rw-r--r--core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/messages.properties2
-rw-r--r--core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/NameHelper.java67
-rw-r--r--core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/actions/CdtActionConstants.java6
-rw-r--r--core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/refactoring/actions/CRefactoringActionGroup.java10
-rw-r--r--core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/refactoring/actions/GettersAndSettersAction.java57
-rw-r--r--core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/refactoring/actions/Messages.java1
-rw-r--r--core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/refactoring/actions/messages.properties1
23 files changed, 1568 insertions, 14 deletions
diff --git a/core/org.eclipse.cdt.ui.tests/resources/refactoring/GenerateGettersAndSetters.rts b/core/org.eclipse.cdt.ui.tests/resources/refactoring/GenerateGettersAndSetters.rts
new file mode 100644
index 00000000000..5eca1f4fa5d
--- /dev/null
+++ b/core/org.eclipse.cdt.ui.tests/resources/refactoring/GenerateGettersAndSetters.rts
@@ -0,0 +1,652 @@
+//!Generate Getters and Setters One Getter Selection
+//#org.eclipse.cdt.ui.tests.refactoring.gettersandsetters.GenerateGettersAndSettersTest
+//@.config
+filename=C.h
+getters=name
+//@C.cpp
+#include "C.h"
+
+int Person::SocSecNo(){
+ return socSecNo;
+}
+
+int main(int argc, char **argv) {
+
+}
+
+//=
+//@C.h
+#ifndef C_H_
+#define C_H_
+
+class Person {
+
+private:
+
+ int systemId;
+
+protected:
+
+ char *name;
+
+public:
+
+ const int socSecNo;
+
+ Person myFriend;
+
+
+ Person(int socSecNo); // contructor
+
+ ~Person(); // destructor
+
+
+ char* Name();
+
+ void Print();
+
+ int //$SocSecNo$//();
+
+ int GetUniqueId();
+
+ int getSystemId(){
+ return systemId;
+ }
+
+ void setSystemId(int systemId){
+ this.systemId = systemId;
+ }
+};
+
+int gooo = 1;
+
+#endif /*C_H_*/
+//=
+#ifndef C_H_
+#define C_H_
+
+class Person {
+
+private:
+
+ int systemId;
+
+protected:
+
+ char *name;
+
+public:
+
+ const int socSecNo;
+
+ Person myFriend;
+
+
+ Person(int socSecNo); // contructor
+
+ ~Person(); // destructor
+
+
+ char* Name();
+
+ void Print();
+
+ int SocSecNo();
+
+ int GetUniqueId();
+ char *getName() const
+ {
+ return name;
+ }
+
+ int getSystemId(){
+ return systemId;
+ }
+
+ void setSystemId(int systemId){
+ this.systemId = systemId;
+ }
+};
+
+int gooo = 1;
+
+#endif /*C_H_*/
+//!Generate Getters and Setters One Getter Selection with Namespace
+//#org.eclipse.cdt.ui.tests.refactoring.gettersandsetters.GenerateGettersAndSettersTest
+//@.config
+filename=C.h
+getters=name
+//@C.cpp
+#include "C.h"
+
+int Person::SocSecNo(){
+ return socSecNo;
+}
+
+int main(int argc, char **argv) {
+
+}
+
+//=
+//@C.h
+#ifndef C_H_
+#define C_H_
+
+namespace Personal {
+ class Person {
+
+ private:
+
+ int systemId;
+
+ protected:
+
+ char *name;
+
+ public:
+
+ const int socSecNo;
+
+ Person myFriend;
+
+
+ Person(int socSecNo); // contructor
+
+ ~Person(); // destructor
+
+
+ char* Name();
+
+ void Print();
+
+ int //$SocSecNo$//();
+
+ int GetUniqueId();
+
+ int getSystemId(){
+ return systemId;
+ }
+
+ void setSystemId(int systemId){
+ this.systemId = systemId;
+ }
+ };
+}
+
+int gooo = 1;
+
+#endif /*C_H_*/
+
+//=
+#ifndef C_H_
+#define C_H_
+
+namespace Personal {
+ class Person {
+
+ private:
+
+ int systemId;
+
+ protected:
+
+ char *name;
+
+ public:
+
+ const int socSecNo;
+
+ Person myFriend;
+
+
+ Person(int socSecNo); // contructor
+
+ ~Person(); // destructor
+
+
+ char* Name();
+
+ void Print();
+
+ int SocSecNo();
+
+ int GetUniqueId();
+ char *getName() const
+ {
+ return name;
+ }
+
+ int getSystemId(){
+ return systemId;
+ }
+
+ void setSystemId(int systemId){
+ this.systemId = systemId;
+ }
+ };
+}
+
+int gooo = 1;
+
+#endif /*C_H_*/
+
+//!Generate Getters and Setters One Setter Selection
+//#org.eclipse.cdt.ui.tests.refactoring.gettersandsetters.GenerateGettersAndSettersTest
+//@.config
+filename=C.h
+setters=name
+//@C.cpp
+#include "C.h"
+
+int Person::SocSecNo(){
+ return socSecNo;
+}
+
+int main(int argc, char **argv) {
+
+}
+
+//=
+//@C.h
+#ifndef C_H_
+#define C_H_
+
+class Person {
+
+private:
+
+ int systemId;
+
+protected:
+
+ char *name;
+
+public:
+
+ const int socSecNo;
+
+ Person myFriend;
+
+
+ Person(int socSecNo); // contructor
+
+ ~Person(); // destructor
+
+
+ char* Name();
+
+ void Print();
+
+ int //$SocSecNo$//();
+
+ int GetUniqueId();
+
+ int getSystemId(){
+ return systemId;
+ }
+
+ void setSystemId(int systemId){
+ this.systemId = systemId;
+ }
+};
+
+
+int gooo = 1;
+
+#endif /*C_H_*/
+//=
+#ifndef C_H_
+#define C_H_
+
+class Person {
+
+private:
+
+ int systemId;
+
+protected:
+
+ char *name;
+
+public:
+
+ const int socSecNo;
+
+ Person myFriend;
+
+
+ Person(int socSecNo); // contructor
+
+ ~Person(); // destructor
+
+
+ char* Name();
+
+ void Print();
+
+ int SocSecNo();
+
+ int GetUniqueId();
+ void setName(char *name)
+ {
+ this.name = name;
+ }
+
+ int getSystemId(){
+ return systemId;
+ }
+
+ void setSystemId(int systemId){
+ this.systemId = systemId;
+ }
+};
+
+
+int gooo = 1;
+
+#endif /*C_H_*/
+//!Generate Getters and Setters Getter and Setter Selection
+//#org.eclipse.cdt.ui.tests.refactoring.gettersandsetters.GenerateGettersAndSettersTest
+//@.config
+filename=C.h
+setters=name
+getters=name
+//@C.cpp
+#include "C.h"
+
+int Person::SocSecNo(){
+ return socSecNo;
+}
+
+int main(int argc, char **argv) {
+
+}
+
+//=
+//@C.h
+#ifndef C_H_
+#define C_H_
+
+class Person {
+
+private:
+
+ int systemId;
+
+protected:
+
+ char *name;
+
+public:
+
+ const int socSecNo;
+
+ Person myFriend;
+
+
+ Person(int socSecNo); // contructor
+
+ ~Person(); // destructor
+
+
+ char* Name();
+
+ void Print();
+
+ int //$SocSecNo$//();
+
+ int GetUniqueId();
+
+ int getSystemId(){
+ return systemId;
+ }
+
+ void setSystemId(int systemId){
+ this.systemId = systemId;
+ }
+};
+
+
+int gooo = 1;
+
+#endif /*C_H_*/
+//=
+#ifndef C_H_
+#define C_H_
+
+class Person {
+
+private:
+
+ int systemId;
+
+protected:
+
+ char *name;
+
+public:
+
+ const int socSecNo;
+
+ Person myFriend;
+
+
+ Person(int socSecNo); // contructor
+
+ ~Person(); // destructor
+
+
+ char* Name();
+
+ void Print();
+
+ int SocSecNo();
+
+ int GetUniqueId();
+ char *getName() const
+ {
+ return name;
+ }
+
+ void setName(char *name)
+ {
+ this.name = name;
+ }
+
+ int getSystemId(){
+ return systemId;
+ }
+
+ void setSystemId(int systemId){
+ this.systemId = systemId;
+ }
+};
+
+
+int gooo = 1;
+
+#endif /*C_H_*/
+//!Generate Getters and Setters Multiple Selection
+//#org.eclipse.cdt.ui.tests.refactoring.gettersandsetters.GenerateGettersAndSettersTest
+//@.config
+filename=C.h
+getters=name,systemId
+setters=name,systemId
+//@C.cpp
+#include "C.h"
+
+int Person::SocSecNo(){
+ return socSecNo;
+}
+
+int main(int argc, char **argv) {
+
+}
+
+//=
+//@C.h
+#ifndef C_H_
+#define C_H_
+
+class Person {
+
+private:
+
+ int systemId;
+
+protected:
+
+ char *name;
+
+public:
+
+ const int socSecNo;
+
+ Person myFriend;
+
+
+ Person(int socSecNo); // contructor
+
+ ~Person(); // destructor
+
+
+ char* Name();
+
+ void Print();
+
+ int //$SocSecNo$//();
+
+ int GetUniqueId();
+
+};
+
+int gooo = 1;
+
+#endif /*C_H_*/
+
+//=
+#ifndef C_H_
+#define C_H_
+
+class Person {
+
+private:
+
+ int systemId;
+
+protected:
+
+ char *name;
+
+public:
+
+ const int socSecNo;
+
+ Person myFriend;
+ int getSystemId() const
+ {
+ return systemId;
+ }
+
+ void setSystemId(int systemId)
+ {
+ this.systemId = systemId;
+ }
+
+ char *getName() const
+ {
+ return name;
+ }
+
+ void setName(char *name)
+ {
+ this.name = name;
+ }
+
+ Person(int socSecNo); // contructor
+
+ ~Person(); // destructor
+
+
+ char* Name();
+
+ void Print();
+
+ int SocSecNo();
+
+ int GetUniqueId();
+
+};
+
+int gooo = 1;
+
+#endif /*C_H_*/
+
+//!Generate Getters and Setters Visibility order 1
+//#org.eclipse.cdt.ui.tests.refactoring.gettersandsetters.GenerateGettersAndSettersTest
+//@.config
+filename=GaS.h
+getters=i,isOk
+setters=i,isOk
+//@GaS.cpp
+#include "Getters.h"
+
+GaS::Getters() {
+}
+
+GaS::~Getters() {
+}
+
+//@GaS.h
+#ifndef GAS_H_
+#define GAS_H_
+
+class GaS {
+public:
+ GaS();
+ virtual ~GaS();
+ bool //$isOk$//;
+ void methode2();
+
+private:
+ int i;
+};
+
+#endif
+
+//=
+#ifndef GAS_H_
+#define GAS_H_
+
+class GaS {
+public:
+ GaS();
+ virtual ~GaS();
+ bool isOk;
+ void methode2();
+ bool getIsOk() const
+ {
+ return isOk;
+ }
+
+ void setIsOk(bool isOk)
+ {
+ this.isOk = isOk;
+ }
+
+ int getI() const
+ {
+ return i;
+ }
+
+ void setI(int i)
+ {
+ this.i = i;
+ }
+
+private:
+ int i;
+};
+
+#endif
+
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 48c6c63b6b7..2c575bc0d71 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
@@ -26,11 +26,12 @@ public class RefactoringTestSuite extends TestSuite {
public static Test suite() throws Exception {
TestSuite suite = new RefactoringTestSuite();
+ suite.addTest(UtilTestSuite.suite());
suite.addTest(RenameRegressionTests.suite());
suite.addTest(ExtractFunctionTestSuite.suite());
suite.addTest(RefactoringTester.suite("ExtractConstantRefactoringTests", "resources/refactoring/ExtractConstant.rts"));
suite.addTest(RefactoringTester.suite("HideMethodRefactoringTests", "resources/refactoring/HideMethod.rts"));
- suite.addTest(UtilTestSuite.suite());
+ suite.addTest(RefactoringTester.suite("GettersAndSettersTests", "resources/refactoring/GenerateGettersAndSetters.rts"));
suite.addTest(RefactoringTester.suite("ImplementMethodRefactoringTests", "resources/refactoring/ImplementMethod.rts"));
return suite;
}
diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/gettersandsetters/GenerateGettersAndSettersTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/gettersandsetters/GenerateGettersAndSettersTest.java
new file mode 100644
index 00000000000..7bb838c0647
--- /dev/null
+++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/gettersandsetters/GenerateGettersAndSettersTest.java
@@ -0,0 +1,125 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Institute for Software, HSR Hochschule fuer Technik
+ * Rapperswil, University of applied sciences
+ * 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 & Leo Buettiker - initial API and implementation
+ * Thomas Corbat - implementation
+ ******************************************************************************/
+package org.eclipse.cdt.ui.tests.refactoring.gettersandsetters;
+
+import java.util.ArrayList;
+import java.util.Properties;
+import java.util.Vector;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.ltk.core.refactoring.Change;
+import org.eclipse.ltk.core.refactoring.RefactoringStatus;
+
+import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
+import org.eclipse.cdt.ui.tests.refactoring.RefactoringTest;
+import org.eclipse.cdt.ui.tests.refactoring.TestSourceFile;
+
+import org.eclipse.cdt.internal.ui.refactoring.gettersandsetters.GenerateGettersAndSettersRefactoring;
+import org.eclipse.cdt.internal.ui.refactoring.gettersandsetters.GetterAndSetterContext;
+
+/**
+ * @author Thomas Corbat
+ *
+ */
+public class GenerateGettersAndSettersTest extends RefactoringTest {
+
+ protected boolean fatalError;
+ private int warnings;
+ private ArrayList<String> selectedGetters;
+ private ArrayList<String> selectedSetters;
+ private GenerateGettersAndSettersRefactoring refactoring;
+
+
+ /**
+ * @param name
+ * @param files
+ */
+ public GenerateGettersAndSettersTest(String name, Vector<TestSourceFile> files) {
+ super(name, files);
+ }
+
+ @Override
+ protected void runTest() throws Throwable {
+ IFile refFile = project.getFile(fileName);
+ refactoring = new GenerateGettersAndSettersRefactoring(refFile, selection, null);
+ RefactoringStatus initialConditions = refactoring.checkInitialConditions(NULL_PROGRESS_MONITOR);
+
+
+ if(fatalError){
+ assertConditionsFatalError(initialConditions);
+ return;
+ }
+ else{
+ assertConditionsOk(initialConditions);
+ executeRefactoring();
+ }
+
+
+ }
+
+ private void executeRefactoring() throws CoreException, Exception {
+
+ RefactoringStatus initialConditions = refactoring.checkInitialConditions(NULL_PROGRESS_MONITOR);
+ assertConditionsOk(initialConditions);
+ selectFields();
+ Change createChange = refactoring.createChange(NULL_PROGRESS_MONITOR);
+ RefactoringStatus finalConditions = refactoring.checkFinalConditions(NULL_PROGRESS_MONITOR);
+ if(warnings > 0){
+ assertConditionsWarning(finalConditions, warnings);
+ }
+ else{
+ assertConditionsOk(finalConditions);
+ }
+
+ createChange.perform(NULL_PROGRESS_MONITOR);
+
+ compareFiles(fileMap);
+ }
+
+ private void selectFields() {
+ GetterAndSetterContext context = refactoring.getContext();
+
+ for(IASTSimpleDeclaration currentDecl : context.existingFields){
+ String name = currentDecl.getDeclarators()[0].getName().getRawSignature();
+ if(selectedGetters.contains(name) ){
+ selectedGetters.remove(name);
+ context.selectedFunctions.add(context.createGetterInserter(currentDecl));
+ }
+
+ if(selectedSetters.contains(name) ){
+ selectedSetters.remove(name);
+ context.selectedFunctions.add(context.createSetterInserter(currentDecl));
+ }
+ }
+ }
+
+
+ @Override
+ protected void configureRefactoring(Properties refactoringProperties) {
+ fatalError = Boolean.valueOf(refactoringProperties.getProperty("fatalerror", "false")).booleanValue(); //$NON-NLS-1$//$NON-NLS-2$
+ warnings = new Integer(refactoringProperties.getProperty("warnings", "0")).intValue(); //$NON-NLS-1$//$NON-NLS-2$
+ String getters = refactoringProperties.getProperty("getters", ""); //$NON-NLS-1$ //$NON-NLS-2$
+ String setters = refactoringProperties.getProperty("setters", ""); //$NON-NLS-1$ //$NON-NLS-2$
+
+ selectedGetters = new ArrayList<String>();
+ for(String getterName : getters.split(",")){ //$NON-NLS-1$
+ selectedGetters.add(getterName);
+ }
+ selectedSetters = new ArrayList<String>();
+ for(String setterName : setters.split(",")){ //$NON-NLS-1$
+ selectedSetters.add(setterName);
+ }
+ }
+
+}
diff --git a/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF b/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF
index 1a2706068cc..310952d8945 100644
--- a/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF
+++ b/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF
@@ -32,6 +32,7 @@ Export-Package: org.eclipse.cdt.internal.corext;x-internal:=true,
org.eclipse.cdt.internal.ui.refactoring.dialogs;x-internal:=true,
org.eclipse.cdt.internal.ui.refactoring.extractconstant;x-friends:="org.eclipse.cdt.ui.tests",
org.eclipse.cdt.internal.ui.refactoring.extractfunction;x-friends:="org.eclipse.cdt.ui.tests",
+ org.eclipse.cdt.internal.ui.refactoring.gettersandsetters;x-friends:="org.eclipse.cdt.ui.tests",
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",
diff --git a/core/org.eclipse.cdt.ui/plugin.properties b/core/org.eclipse.cdt.ui/plugin.properties
index 351dd8acb5c..17b686626ed 100644
--- a/core/org.eclipse.cdt.ui/plugin.properties
+++ b/core/org.eclipse.cdt.ui/plugin.properties
@@ -148,6 +148,8 @@ ActionDefinition.extractFunction.name= Extract Function - Refactoring
ActionDefinition.extractFunction.description= Extract a function for the selected list of expressions or statements
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...
+ActionDefinition.gettersAndSetters.description = Generates getters and setters for a selected field
# Action Set
CodingActionSet.label= C/C++ Coding
@@ -159,6 +161,7 @@ Refactoring.extractConstant.label=Extr&act Constant...
Refactoring.extractFunction.label=Extract &Function... (work in progress)
Refactoring.hideMethod.label=Hide Member Function... (work in progress)
Refactoring.implementMethod.label=Impl&ement Method... (work in progress)
+Refactoring.gettersAndSetters.label=Generate Getters and Setters...
CEditor.name=C/C++ Editor
diff --git a/core/org.eclipse.cdt.ui/plugin.xml b/core/org.eclipse.cdt.ui/plugin.xml
index 3fbe2853638..85e08d57f55 100644
--- a/core/org.eclipse.cdt.ui/plugin.xml
+++ b/core/org.eclipse.cdt.ui/plugin.xml
@@ -1172,9 +1172,16 @@
retarget="true">
</action>
<action
+ definitionId="org.eclipse.cdt.ui.refactor.getters.and.setters"
+ label="%Refactoring.gettersAndSetters.label"
+ menubarPath="org.eclipse.jdt.ui.refactoring.menu/codingGroup2"
+ id="org.eclipse.cdt.ui.actions.GettersAndSetters"
+ retarget="true">
+ </action>
+ <action
definitionId="org.eclipse.cdt.ui.refactor.implement.method"
label="%Refactoring.implementMethod.label"
- menubarPath="org.eclipse.jdt.ui.refactoring.menu/codingGroup"
+ menubarPath="org.eclipse.jdt.ui.refactoring.menu/codingGroup2"
id="org.eclipse.cdt.ui.actions.ImplementMethod"
retarget="true">
</action>
@@ -1989,27 +1996,27 @@
name="%ActionDefinition.renameElement.name"
description="%ActionDefinition.renameElement.description"
categoryId="org.eclipse.cdt.ui.category.refactoring"
- id="org.eclipse.cdt.ui.edit.text.rename.element">
- </command>
+ id="org.eclipse.cdt.ui.edit.text.rename.element"/>
<command
name="%ActionDefinition.extractConstant.name"
description="%ActionDefinition.extractConstant.description"
categoryId="org.eclipse.cdt.ui.category.refactoring"
- id="org.eclipse.cdt.ui.refactor.extract.constant">
- </command>
+ id="org.eclipse.cdt.ui.refactor.extract.constant"/>
<command
name="%ActionDefinition.extractFunction.name"
description="%ActionDefinition.extractFunction.description"
categoryId="org.eclipse.cdt.ui.category.refactoring"
- id="org.eclipse.cdt.ui.refactor.extract.function">
- </command>
+ id="org.eclipse.cdt.ui.refactor.extract.function"/>
<command
name="%ActionDefinition.implementMethod.name"
description="%ActionDefinition.implementMethod.description"
categoryId="org.eclipse.cdt.ui.category.refactoring"
- id="org.eclipse.cdt.ui.refactor.implement.method">
- </command>
-
+ id="org.eclipse.cdt.ui.refactor.implement.method"/>
+ <command
+ name="%ActionDefinition.gettersAndSetters.name"
+ description="%ActionDefinition.gettersAndSetters.description"
+ categoryId="org.eclipse.cdt.ui.category.refactoring"
+ id="org.eclipse.cdt.ui.refactor.getters.and.setters"/>
</extension>
<extension
id="pdomSearchPage"
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/ICEditorActionDefinitionIds.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/ICEditorActionDefinitionIds.java
index b5f6bd4a664..c1ccf960678 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/ICEditorActionDefinitionIds.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/ICEditorActionDefinitionIds.java
@@ -117,6 +117,12 @@ public interface ICEditorActionDefinitionIds extends ITextEditorActionDefinition
public static final String IMPLEMENT_METHOD= "org.eclipse.cdt.ui.refactor.implement.method"; //$NON-NLS-1$
/**
+ * Action definition ID of the refactor -> generate getters and setters
+ * (value <code>"org.eclipse.cdt.ui.refactor.getters.and.setters"</code>).
+ */
+ public static final String GETTERS_AND_SETTERS= "org.eclipse.cdt.ui.refactor.getters.and.setters"; //$NON-NLS-1$
+
+ /**
* Action definition ID of the refactor -> undo action
* (value <code>"org.eclipse.cdt.ui.edit.text.undo.action"</code>).
*/
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/CRefactoring.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/CRefactoring.java
index a11985198b8..f4b003b2ac9 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/CRefactoring.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/CRefactoring.java
@@ -278,7 +278,7 @@ public abstract class CRefactoring extends Refactoring {
return null;
}
- private boolean loadTranslationUnit(RefactoringStatus status,
+ protected boolean loadTranslationUnit(RefactoringStatus status,
IProgressMonitor mon) {
SubMonitor subMonitor = SubMonitor.convert(mon, 10);
if (file != null) {
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/FunctionFactory.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/FunctionFactory.java
new file mode 100644
index 00000000000..0fa8ac1a282
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/FunctionFactory.java
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright (c) 2008 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.gettersandsetters;
+
+import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
+import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
+import org.eclipse.cdt.core.dom.ast.IASTPointerOperator;
+import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclSpecifier;
+import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
+
+import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTBinaryExpression;
+import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTCompoundStatement;
+import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTExpressionStatement;
+import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTFieldReference;
+import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTFunctionDeclarator;
+import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTFunctionDefinition;
+import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTIdExpression;
+import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTLiteralExpression;
+import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTName;
+import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTParameterDeclaration;
+import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTReturnStatement;
+import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTSimpleDeclSpecifier;
+
+import org.eclipse.cdt.internal.ui.refactoring.utils.NameHelper;
+
+public class FunctionFactory {
+
+ public static IASTFunctionDefinition createGetter(String varName, IASTSimpleDeclaration fieldDeclaration) {
+
+ IASTFunctionDefinition getter = new CPPASTFunctionDefinition();
+
+ getter.setDeclSpecifier(fieldDeclaration.getDeclSpecifier());
+
+ CPPASTName getterName = new CPPASTName();
+ String varPartOfGetterName = NameHelper.makeFirstCharUpper(NameHelper.trimFieldName(varName));
+ getterName.setName("get".concat(varPartOfGetterName).toCharArray()); //$NON-NLS-1$
+ CPPASTFunctionDeclarator declarator = new CPPASTFunctionDeclarator();
+ declarator.setConst(true);
+ declarator.setName(getterName);
+ for(IASTPointerOperator pointer : fieldDeclaration.getDeclarators()[0].getPointerOperators()){
+ declarator.addPointerOperator(pointer);
+ }
+ getter.setDeclarator(declarator);
+
+ CPPASTCompoundStatement compound = new CPPASTCompoundStatement();
+ CPPASTReturnStatement returnStatement = new CPPASTReturnStatement();
+ CPPASTIdExpression idExpr = new CPPASTIdExpression();
+ CPPASTName returnVal = new CPPASTName();
+ returnVal.setName(varName.toCharArray());
+ idExpr.setName(returnVal);
+ returnStatement.setReturnValue(idExpr);
+ compound.addStatement(returnStatement);
+
+ getter.setBody(compound);
+
+ return getter;
+ }
+
+ public static IASTFunctionDefinition createSetter(String varName, IASTSimpleDeclaration fieldDeclaration) {
+
+ IASTFunctionDefinition setter = new CPPASTFunctionDefinition();
+
+ CPPASTSimpleDeclSpecifier declSpecifier = new CPPASTSimpleDeclSpecifier();
+ declSpecifier.setType(IASTSimpleDeclSpecifier.t_void);
+ setter.setDeclSpecifier(declSpecifier);
+
+ CPPASTName setterName = new CPPASTName();
+ String varPartOfSetterName = NameHelper.makeFirstCharUpper(NameHelper.trimFieldName(varName));
+ setterName.setName("set".concat(varPartOfSetterName).toCharArray()); //$NON-NLS-1$
+ CPPASTFunctionDeclarator declarator = new CPPASTFunctionDeclarator();
+ declarator.setName(setterName);
+ setter.setDeclarator(declarator);
+ CPPASTParameterDeclaration parameterDeclaration = new CPPASTParameterDeclaration();
+ parameterDeclaration.setDeclarator(fieldDeclaration.getDeclarators()[0]);
+ parameterDeclaration.setDeclSpecifier(fieldDeclaration.getDeclSpecifier());
+ declarator.addParameterDeclaration(parameterDeclaration);
+
+ CPPASTCompoundStatement compound = new CPPASTCompoundStatement();
+ CPPASTExpressionStatement exprStmt = new CPPASTExpressionStatement();
+ CPPASTBinaryExpression binExpr = new CPPASTBinaryExpression();
+ CPPASTFieldReference fieldRef = new CPPASTFieldReference();
+ CPPASTLiteralExpression litExpr = new CPPASTLiteralExpression();
+ litExpr.setValue("this"); //$NON-NLS-1$
+ fieldRef.setFieldOwner(litExpr);
+ fieldRef.setFieldName(fieldDeclaration.getDeclarators()[0].getName());
+ binExpr.setOperand1(fieldRef);
+ binExpr.setOperator(IASTBinaryExpression.op_assign);
+ CPPASTIdExpression idExpr = new CPPASTIdExpression();
+ idExpr.setName(fieldDeclaration.getDeclarators()[0].getName());
+ binExpr.setOperand2(idExpr);
+ exprStmt.setExpression(binExpr);
+ compound.addStatement(exprStmt);
+
+ setter.setBody(compound);
+
+ return setter;
+ }
+
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GenerateGettersAndSettersInputPage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GenerateGettersAndSettersInputPage.java
new file mode 100644
index 00000000000..6c8f57dcdbb
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GenerateGettersAndSettersInputPage.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (c) 2008 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.gettersandsetters;
+
+import java.util.ArrayList;
+
+import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
+import org.eclipse.jface.viewers.CheckStateChangedEvent;
+import org.eclipse.jface.viewers.ICheckStateListener;
+import org.eclipse.ltk.ui.refactoring.UserInputWizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.dialogs.ContainerCheckedTreeViewer;
+
+public class GenerateGettersAndSettersInputPage extends UserInputWizardPage {
+
+ private GetterAndSetterContext context;
+
+ public GenerateGettersAndSettersInputPage(GetterAndSetterContext context) {
+ super(Messages.GettersAndSetters_Name);
+ this.context = context;
+ }
+
+ public void createControl(Composite parent) {
+ Composite comp = new Composite(parent, SWT.NONE );
+ comp.setLayout(new FillLayout());
+ createTree(comp);
+
+ setControl(comp);
+ }
+
+ private void createTree(Composite comp) {
+ final ContainerCheckedTreeViewer variableSelectionView = new ContainerCheckedTreeViewer(comp, SWT.BORDER);
+ for(IASTSimpleDeclaration currentField : context.existingFields){
+ if(currentField.getDeclarators().length == 0){
+ continue;
+ }
+
+ variableSelectionView.setContentProvider(context);
+ variableSelectionView.setAutoExpandLevel(3);
+ variableSelectionView.setInput(""); //$NON-NLS-1$
+
+ variableSelectionView.addCheckStateListener(new ICheckStateListener(){
+
+ public void checkStateChanged(CheckStateChangedEvent event) {
+ ArrayList<GetterSetterInsertEditProvider> checkedFunctions = new ArrayList<GetterSetterInsertEditProvider>();
+ for(Object currentElement : variableSelectionView.getCheckedElements()){
+ if (currentElement instanceof GetterSetterInsertEditProvider) {
+ GetterSetterInsertEditProvider editProvider = (GetterSetterInsertEditProvider) currentElement;
+ checkedFunctions.add(editProvider);
+ }
+ }
+ context.selectedFunctions = checkedFunctions;
+
+ }
+
+ });
+ }
+
+ }
+
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GenerateGettersAndSettersRefactoring.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GenerateGettersAndSettersRefactoring.java
new file mode 100644
index 00000000000..ae206abb082
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GenerateGettersAndSettersRefactoring.java
@@ -0,0 +1,123 @@
+/*******************************************************************************
+ * Copyright (c) 2008 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.gettersandsetters;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.SubMonitor;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ltk.core.refactoring.RefactoringStatus;
+
+import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
+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.IASTFunctionDefinition;
+import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
+import org.eclipse.cdt.core.dom.ast.cpp.CPPASTVisitor;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
+import org.eclipse.cdt.core.model.ICElement;
+
+import org.eclipse.cdt.internal.ui.refactoring.AddDeclarationNodeToClassChange;
+import org.eclipse.cdt.internal.ui.refactoring.CRefactoring;
+import org.eclipse.cdt.internal.ui.refactoring.ModificationCollector;
+import org.eclipse.cdt.internal.ui.refactoring.utils.VisibilityEnum;
+
+/**
+ * @author Thomas Corbat
+ *
+ */
+public class GenerateGettersAndSettersRefactoring extends CRefactoring {
+
+ private static final String MEMBER_DECLARATION = "MEMBER_DECLARATION"; //$NON-NLS-1$
+ private final GetterAndSetterContext context = new GetterAndSetterContext();
+
+ public GenerateGettersAndSettersRefactoring(IFile file, ISelection selection, ICElement element) {
+ super(file, selection, element);
+ }
+
+ @Override
+ public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException, OperationCanceledException {
+ SubMonitor sm = SubMonitor.convert(pm, 10);
+
+ super.checkInitialConditions(sm.newChild(6));
+
+ initRefactoring(pm);
+
+ return initStatus;
+ }
+
+ private void initRefactoring(IProgressMonitor pm) {
+ loadTranslationUnit(initStatus, pm);
+ context.setUnit(unit);
+ findDeclarations();
+
+ }
+
+ protected void findDeclarations() {
+
+ unit.accept(new CPPASTVisitor() {
+
+ {
+ shouldVisitDeclarations = true;
+ }
+
+ @Override
+ public int visit(IASTDeclaration declaration) {
+ if (declaration instanceof IASTSimpleDeclaration) {
+ IASTSimpleDeclaration fieldDeclaration = (IASTSimpleDeclaration) declaration;
+ ASTNodeProperty props = fieldDeclaration.getPropertyInParent();
+ if (props.getName().contains(MEMBER_DECLARATION)) {
+ final IASTDeclarator[] declarators = fieldDeclaration.getDeclarators();
+ if (declarators.length > 0) {
+ if ((declarators[0] instanceof IASTFunctionDeclarator)) {
+ context.existingFunctionDeclarations.add(fieldDeclaration);
+ } else {
+ if(isInSameFile(fieldDeclaration)){
+ context.existingFields.add(fieldDeclaration);
+ }
+ }
+ }
+ }
+ }
+ if (declaration instanceof IASTFunctionDefinition) {
+ IASTFunctionDefinition functionDefinition = (IASTFunctionDefinition) declaration;
+ ASTNodeProperty props = functionDefinition.getPropertyInParent();
+ if (props.getName().contains(MEMBER_DECLARATION)) {
+ context.existingFunctionDefinitions.add(functionDefinition);
+ }
+ }
+ return super.visit(declaration);
+ }
+ });
+ }
+
+ @Override
+ protected void collectModifications(IProgressMonitor pm,ModificationCollector collector) throws CoreException, OperationCanceledException {
+// egtodo
+// ASTRewrite rewriter = collector.rewriterForTranslationUnit(unit);
+
+ for(GetterSetterInsertEditProvider currentProvider : context.selectedFunctions){
+// egtodo
+// TextEditGroup editGroup = new TextEditGroup(Messages.GenerateGettersAndSettersRefactoring_Insert + currentProvider.toString());
+ ICPPASTCompositeTypeSpecifier classDefinition = (ICPPASTCompositeTypeSpecifier) context.existingFunctionDeclarations.get(context.existingFunctionDeclarations.size()-1).getParent();
+ AddDeclarationNodeToClassChange.createChange(classDefinition, VisibilityEnum.v_public, currentProvider.getFunction(), false, collector);
+ }
+ }
+
+ public GetterAndSetterContext getContext() {
+ return context;
+ }
+
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GenerateGettersAndSettersRefactoringRunner.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GenerateGettersAndSettersRefactoringRunner.java
new file mode 100644
index 00000000000..0d8d8ca1744
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GenerateGettersAndSettersRefactoringRunner.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2008 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.gettersandsetters;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.window.IShellProvider;
+import org.eclipse.ltk.ui.refactoring.RefactoringWizardOpenOperation;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+import org.eclipse.cdt.core.model.ICElement;
+
+import org.eclipse.cdt.internal.ui.refactoring.RefactoringRunner;
+
+/**
+ * @author Thomas Corbat
+ *
+ */
+public class GenerateGettersAndSettersRefactoringRunner extends RefactoringRunner {
+
+ public GenerateGettersAndSettersRefactoringRunner(IFile file, ISelection selection, ICElement elem, IShellProvider shellProvider) {
+ super(file, selection, elem, shellProvider);
+ }
+
+ @Override
+ public void run() {
+ if (PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor() instanceof ITextEditor) {
+ GenerateGettersAndSettersRefactoring refactoring = new GenerateGettersAndSettersRefactoring(file, selection, celement);
+ GenerateGettersAndSettersRefactoringWizard wizard = new GenerateGettersAndSettersRefactoringWizard(refactoring);
+ RefactoringWizardOpenOperation operator = new RefactoringWizardOpenOperation(wizard);
+
+ try {
+ operator.run(shellProvider.getShell(), refactoring.getName());
+ } catch (InterruptedException e) {
+ //initial condition checking got canceled by the user.
+ }
+ }
+ }
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GenerateGettersAndSettersRefactoringWizard.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GenerateGettersAndSettersRefactoringWizard.java
new file mode 100644
index 00000000000..5dea88b9b2f
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GenerateGettersAndSettersRefactoringWizard.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2008 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.gettersandsetters;
+
+import org.eclipse.ltk.ui.refactoring.RefactoringWizard;
+import org.eclipse.ltk.ui.refactoring.UserInputWizardPage;
+
+/**
+ * @author Thomas Corbat
+ *
+ */
+public class GenerateGettersAndSettersRefactoringWizard extends
+ RefactoringWizard {
+
+ private final GenerateGettersAndSettersRefactoring refactoring;
+
+ public GenerateGettersAndSettersRefactoringWizard(
+ GenerateGettersAndSettersRefactoring refactoring) {
+ super(refactoring, WIZARD_BASED_USER_INTERFACE);
+ this.refactoring = refactoring;
+ }
+
+ @Override
+ protected void addUserInputPages() {
+ UserInputWizardPage page = new GenerateGettersAndSettersInputPage(refactoring.getContext());
+ addPage(page);
+ }
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GetterAndSetterContext.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GetterAndSetterContext.java
new file mode 100644
index 00000000000..49f1d854d11
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GetterAndSetterContext.java
@@ -0,0 +1,167 @@
+/*******************************************************************************
+ * Copyright (c) 2008 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.gettersandsetters;
+
+import java.util.ArrayList;
+
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+
+import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
+import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
+import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
+
+import org.eclipse.cdt.internal.ui.refactoring.utils.NameHelper;
+
+public class GetterAndSetterContext implements ITreeContentProvider{
+
+ public ArrayList<IASTSimpleDeclaration> existingFields = new ArrayList<IASTSimpleDeclaration>();
+ public ArrayList<IASTFunctionDefinition> existingFunctionDefinitions = new ArrayList<IASTFunctionDefinition>();
+ public ArrayList<IASTSimpleDeclaration> existingFunctionDeclarations = new ArrayList<IASTSimpleDeclaration>();
+ public ArrayList<GetterSetterInsertEditProvider> selectedFunctions = new ArrayList<GetterSetterInsertEditProvider>();
+ private IASTTranslationUnit unit;
+
+ public Object[] getChildren(Object parentElement) {
+
+ ArrayList<GetterSetterInsertEditProvider> children = new ArrayList<GetterSetterInsertEditProvider>();
+ if (parentElement instanceof FieldWrapper) {
+ FieldWrapper wrapper = (FieldWrapper) parentElement;
+
+ if(!wrapper.getter.exists()){
+ children.add(createGetterInserter(wrapper.field));
+ }
+ if(!wrapper.setter.exists() && !wrapper.field.getDeclSpecifier().isConst()){
+
+ children.add(createSetterInserter(wrapper.field));
+ }
+ }
+ return children.toArray();
+ }
+
+ public GetterSetterInsertEditProvider createGetterInserter(IASTSimpleDeclaration simpleDeclaration) {
+ String varName = simpleDeclaration.getDeclarators()[0].getName().toString();
+ IASTFunctionDefinition getter = FunctionFactory.createGetter(varName, simpleDeclaration);
+ getter.setParent(unit);
+ return new GetterSetterInsertEditProvider(getter);
+ }
+
+ public GetterSetterInsertEditProvider createSetterInserter(IASTSimpleDeclaration simpleDeclaration) {
+ String varName = simpleDeclaration.getDeclarators()[0].getName().toString();
+ IASTFunctionDefinition setter = FunctionFactory.createSetter(varName, simpleDeclaration);
+ setter.setParent(unit);
+ return new GetterSetterInsertEditProvider(setter);
+ }
+
+ public Object getParent(Object element) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public boolean hasChildren(Object element) {
+ if (element instanceof FieldWrapper) {
+ FieldWrapper wrapper = (FieldWrapper) element;
+
+ return wrapper.missingGetterOrSetter();
+ }
+ return false;
+ }
+
+ public Object[] getElements(Object inputElement) {
+
+ return getWrappedFields().toArray();
+ }
+
+ public void dispose() {
+ // TODO Auto-generated method stub
+ }
+
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ // TODO Auto-generated method stub
+ }
+
+ public void setUnit(IASTTranslationUnit unit) {
+ this.unit = unit;
+ }
+
+ private ArrayList<FieldWrapper> getWrappedFields() {
+ ArrayList<FieldWrapper> wrappedFields = new ArrayList<FieldWrapper>();
+ for(IASTSimpleDeclaration currentField : existingFields){
+ FieldWrapper wrapper = new FieldWrapper();
+ wrapper.field = currentField;
+ wrapper.getter = getGetterForField(currentField);
+ wrapper.setter = getSetterForField(currentField);
+ if(wrapper.missingGetterOrSetter()){
+ wrappedFields.add(wrapper);
+ }
+ }
+ return wrappedFields;
+ }
+
+ private FunctionWrapper getGetterForField(IASTSimpleDeclaration currentField) {
+ FunctionWrapper wrapper = new FunctionWrapper();
+ String trimmedName = NameHelper.trimFieldName(currentField.getDeclarators()[0].getName().toString());
+ String getterName = "get" + NameHelper.makeFirstCharUpper(trimmedName); //$NON-NLS-1$
+
+ setFunctionToWrapper(wrapper, getterName);
+
+ return wrapper;
+ }
+
+ private FunctionWrapper getSetterForField(IASTSimpleDeclaration currentField) {
+ FunctionWrapper wrapper = new FunctionWrapper();
+ String trimmedName = NameHelper.trimFieldName(currentField.getDeclarators()[0].getName().toString());
+ String setterName = "set" + NameHelper.makeFirstCharUpper(trimmedName); //$NON-NLS-1$
+
+ setFunctionToWrapper(wrapper, setterName);
+
+ return wrapper;
+ }
+ private void setFunctionToWrapper(FunctionWrapper wrapper, String getterName) {
+ for(IASTFunctionDefinition currentDefinition : existingFunctionDefinitions){
+ if(currentDefinition.getDeclarator().getName().toString().endsWith(getterName)){
+ wrapper.functionDefinition = currentDefinition;
+ }
+ }
+
+ for(IASTSimpleDeclaration currentDeclaration : existingFunctionDeclarations){
+ if(currentDeclaration.getDeclarators()[0].getName().toString().endsWith(getterName)){
+ wrapper.functionDeclaration = currentDeclaration;
+ }
+ }
+ }
+
+
+ protected class FieldWrapper{
+ protected IASTSimpleDeclaration field;
+ protected FunctionWrapper getter;
+ protected FunctionWrapper setter;
+
+ @Override
+ public String toString(){
+ return field.getDeclarators()[0].getName().toString();
+ }
+
+ public boolean missingGetterOrSetter() {
+ return !getter.exists() || !setter.exists();
+ }
+ }
+
+ protected class FunctionWrapper{
+ protected IASTSimpleDeclaration functionDeclaration;
+ protected IASTFunctionDefinition functionDefinition;
+
+ public boolean exists() {
+
+ return functionDeclaration != null || functionDefinition != null;
+ }
+ }
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GetterSetterInsertEditProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GetterSetterInsertEditProvider.java
new file mode 100644
index 00000000000..444f2f17c4b
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GetterSetterInsertEditProvider.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2008 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.gettersandsetters;
+
+import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
+
+
+public class GetterSetterInsertEditProvider {
+
+ private IASTFunctionDefinition function;
+
+ public GetterSetterInsertEditProvider(IASTFunctionDefinition function){
+ this.function = function;
+ }
+
+ @Override
+ public String toString(){
+ return function.getDeclarator().getName().toString();
+ }
+
+ public IASTFunctionDefinition getFunction() {
+ return function;
+ }
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/Messages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/Messages.java
new file mode 100644
index 00000000000..b1bf3da98fc
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/Messages.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2008 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.gettersandsetters;
+
+import org.eclipse.osgi.util.NLS;
+
+public final class Messages extends NLS {
+
+ private static final String BUNDLE_NAME = "org.eclipse.cdt.hsrrefactoring.generategettersandsetters.messages";//$NON-NLS-1$
+
+ private Messages() {
+ // Do not instantiate
+ }
+
+ public static String GenerateGettersAndSettersRefactoring_Insert;
+ public static String GettersAndSetters_Name;
+
+ static {
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/messages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/messages.properties
new file mode 100644
index 00000000000..abb369946b0
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/messages.properties
@@ -0,0 +1,2 @@
+GettersAndSetters_Name=Generate Getters and Setters
+GenerateGettersAndSettersRefactoring_Insert=Insert
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/NameHelper.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/NameHelper.java
index b6708d16a1a..73173b249f1 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/NameHelper.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/NameHelper.java
@@ -15,7 +15,11 @@ import java.util.regex.Pattern;
import org.eclipse.core.resources.IFile;
+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.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTQualifiedName;
@@ -64,4 +68,67 @@ public class NameHelper {
qname.addName(declaratorName);
return qname;
}
+
+
+ public static IASTFunctionDefinition getAncestorFunctionDefinition(IASTName startNode) {
+ return (IASTFunctionDefinition) getAncestorDefinition(startNode, IASTFunctionDefinition.class);
+ }
+
+ public static IASTSimpleDeclaration getAncestorFunctionDeclaration(IASTName startNode) {
+ return (IASTSimpleDeclaration) getAncestorDefinition(startNode, IASTSimpleDeclaration.class);
+ }
+
+ public static ICPPASTCompositeTypeSpecifier getAncestorClassDefinition(IASTName startNode) {
+ return (ICPPASTCompositeTypeSpecifier) getAncestorDefinition(startNode, ICPPASTCompositeTypeSpecifier.class);
+ }
+
+
+ public static IASTNode getAncestorDefinition(IASTName startNode, Class<? extends IASTNode> type) {
+
+ IASTNode node = startNode;
+
+ while(node != null ){
+ if(type.isInstance(node)) {
+ return node;
+ }
+ node = node.getParent();
+ }
+
+ return null;
+ }
+
+ public static String trimFieldName(String fieldName){
+ char[] letters = fieldName.toCharArray();
+ int start = 0;
+ int end = letters.length - 1;
+ try{
+ while(!Character.isLetter(letters[start]) && start < end) {
+ ++start;
+ }
+
+ if(Character.isLowerCase(letters[start])){
+ if(!Character.isLetter(letters[start + 1])){
+ start+= 2;
+ }
+ else if (Character.isUpperCase(letters[start + 1])){
+ start += 1;
+ }
+ }
+
+ while((!Character.isLetter(letters[end]) && !Character.isDigit(letters[end])) && start < end) {
+ --end;
+ }
+ }catch(IndexOutOfBoundsException e){}
+
+ return new String(letters, start, end - start + 1);
+
+ }
+
+ public static String makeFirstCharUpper(String name) {
+ if(Character.isLowerCase(name.charAt(0))){
+ name = Character.toUpperCase(name.charAt(0)) + name.substring(1);
+ }
+ return name;
+ }
+
}
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 8fdad457994..4c5e7f1f188 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
@@ -261,6 +261,12 @@ public class CdtActionConstants {
public static final String IMPLEMENT_METHOD= "org.eclipse.cdt.ui.actions.ImplementMethod"; //$NON-NLS-1$
/**
+ * Refactor menu: name of standard Generate Getters and Setters global action
+ * (value <code>"org.eclipse.cdt.ui.actions.GettersAndSetters"</code>).
+ */
+ public static final String GETTERS_AND_SETTERS= "org.eclipse.cdt.ui.actions.GettersAndSetters"; //$NON-NLS-1$
+
+ /**
* Refactor menu: name of standard Introduce Parameter global action
* (value <code>"org.eclipse.cdt.ui.actions.IntroduceParameter"</code>).
*/
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 807fff139f4..c13458f37f2 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 fExtractFunctionAction;
private RefactoringAction fHideMethodAction;
private RefactoringAction fImplementMethodAction;
+ private RefactoringAction fGettersAndSettersAction;
private IWorkbenchSite fSite;
private List<RefactoringAction> fAllActions= new ArrayList<RefactoringAction>();
@@ -164,6 +165,10 @@ public class CRefactoringActionGroup extends ActionGroup implements ISelectionCh
fImplementMethodAction = new ImplementMethodAction();
fImplementMethodAction.setActionDefinitionId(ICEditorActionDefinitionIds.IMPLEMENT_METHOD);
fAllActions.add(fImplementMethodAction);
+
+ fGettersAndSettersAction = new GettersAndSettersAction();
+ fGettersAndSettersAction.setActionDefinitionId(ICEditorActionDefinitionIds.GETTERS_AND_SETTERS);
+ fAllActions.add(fGettersAndSettersAction);
}
public void setWorkbenchSite(IWorkbenchSite site) {
@@ -202,6 +207,7 @@ public class CRefactoringActionGroup extends ActionGroup implements ISelectionCh
setActionHandler(actionBar, CdtActionConstants.EXTRACT_METHOD, fExtractFunctionAction);
setActionHandler(actionBar, CdtActionConstants.HIDE_METHOD, fHideMethodAction);
setActionHandler(actionBar, CdtActionConstants.IMPLEMENT_METHOD, fImplementMethodAction);
+ setActionHandler(actionBar, CdtActionConstants.GETTERS_AND_SETTERS, fGettersAndSettersAction);
}
private void setActionHandler(IActionBars actionBar, String id, RefactoringAction action) {
@@ -232,12 +238,12 @@ public class CRefactoringActionGroup extends ActionGroup implements ISelectionCh
addAction(refactorSubmenu, fExtractConstantAction);
addAction(refactorSubmenu, fExtractFunctionAction);
addAction(refactorSubmenu, fHideMethodAction);
- addAction(refactorSubmenu, fImplementMethodAction);
-
refactorSubmenu.add(new Separator(GROUP_REORG2));
refactorSubmenu.add(new Separator(GROUP_TYPE));
refactorSubmenu.add(new Separator(GROUP_TYPE2));
refactorSubmenu.add(new Separator(GROUP_CODING2));
+ addAction(refactorSubmenu, fImplementMethodAction);
+ addAction(refactorSubmenu, fGettersAndSettersAction);
refactorSubmenu.add(new Separator(GROUP_TYPE3));
menu.appendToGroup(fGroupName, refactorSubmenu);
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/refactoring/actions/GettersAndSettersAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/refactoring/actions/GettersAndSettersAction.java
new file mode 100644
index 00000000000..9db220e93b2
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/refactoring/actions/GettersAndSettersAction.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2008 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.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.cdt.core.model.ICElement;
+import org.eclipse.cdt.core.model.IField;
+import org.eclipse.cdt.core.model.ISourceReference;
+import org.eclipse.cdt.core.model.IWorkingCopy;
+
+import org.eclipse.cdt.internal.ui.refactoring.gettersandsetters.GenerateGettersAndSettersRefactoringRunner;
+
+/**
+ * Launches a getter and setter source code generation.
+ */
+public class GettersAndSettersAction extends RefactoringAction {
+
+ public GettersAndSettersAction() {
+ super(Messages.GettersAndSetters_label);
+ }
+
+ @Override
+ public void run(IShellProvider shellProvider, ICElement elem) {
+ new GenerateGettersAndSettersRefactoringRunner(null, null, elem, shellProvider).run();
+ }
+
+ @Override
+ public void run(IShellProvider shellProvider, IWorkingCopy wc, ITextSelection s) {
+ IResource res= wc.getResource();
+ if (res instanceof IFile) {
+ new GenerateGettersAndSettersRefactoringRunner((IFile) res, s, null, shellProvider).run();
+ }
+ }
+
+ @Override
+ public void updateSelection(ICElement elem) {
+ super.updateSelection(elem);
+ if (elem instanceof IField == false
+ || elem instanceof ISourceReference == false
+ || ((ISourceReference) elem).getTranslationUnit().getResource() instanceof IFile == false) {
+ setEnabled(false);
+ }
+ }
+}
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 c90df502eaf..ffc21b54597 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
@@ -20,6 +20,7 @@ public class Messages extends NLS {
public static String ExtractFunctionAction_label;
public static String HideMethodAction_label;
public static String ImplementMethodAction_label;
+ public static String GettersAndSetters_label;
static {
// initialize resource bundle
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 a122e389716..52d03bcbb77 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
@@ -11,6 +11,7 @@
CRefactoringActionGroup_menu=Refactor
CRenameAction_label=Rename...
ExtractConstantAction_label=Extract Constant...
+GettersAndSetters_label=Generate Getters and Setters...
ImplementMethodAction_label=Implement Method... (work in progress)
HideMethodAction_label=Hide Member Function... (work in progress)
ExtractFunctionAction_label=Extract Function... (work in progress)

Back to the top