Bug 560114 - [Robotics] Provide a CDT editor integration

- Provide an initial version of the texteditor integration plugin
- Add it to the parent POM
- Add it to the ROS2 feature

Change-Id: Icf58f1a0da1feac5d313faae931b7fac9feaf550
Signed-off-by: Ansgar Radermacher <ansgar.radermacher@cea.fr>
diff --git a/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/.classpath b/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/.classpath
new file mode 100644
index 0000000..43b9862
--- /dev/null
+++ b/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/.project b/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/.project
new file mode 100644
index 0000000..aa4f730
--- /dev/null
+++ b/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/.project
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.papyrus.robotics.cdt.texteditor</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.m2e.core.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.m2e.core.maven2Nature</nature>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/.settings/org.eclipse.core.resources.prefs b/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..99f26c0
--- /dev/null
+++ b/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/.settings/org.eclipse.jdt.core.prefs b/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..0c68a61
--- /dev/null
+++ b/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/.settings/org.eclipse.m2e.core.prefs b/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/META-INF/MANIFEST.MF b/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..b708ab3
--- /dev/null
+++ b/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/META-INF/MANIFEST.MF
@@ -0,0 +1,39 @@
+Manifest-Version: 1.0
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.ui.editors;bundle-version="3.7.0",
+ org.eclipse.uml2.uml;bundle-version="3.2.0",
+ org.eclipse.cdt.core;bundle-version="5.4.0",
+ org.eclipse.cdt.ui;bundle-version="5.4.0",
+ org.eclipse.cdt.codan.ui.cxx;bundle-version="3.2.0",
+ org.eclipse.papyrus.infra.core.log;bundle-version="1.2.0",
+ org.eclipse.papyrus.designer.languages.cpp.profile;bundle-version="1.1.0",
+ org.eclipse.papyrus.uml.tools;bundle-version="1.2.0",
+ org.eclipse.papyrus.designer.languages.common.texteditor.model;bundle-version="1.1.0",
+ org.eclipse.papyrus.uml.tools.utils;bundle-version="1.2.0",
+ org.eclipse.papyrus.uml.diagram.common;bundle-version="1.2.0",
+ org.eclipse.papyrus.designer.languages.common.extensionpoints;bundle-version="1.1.0",
+ org.eclipse.papyrus.designer.languages.cpp.codegen;bundle-version="1.1.0",
+ org.eclipse.papyrus.infra.core.sasheditor;bundle-version="1.2.0",
+ org.eclipse.papyrus.infra.core.sasheditor.di;bundle-version="1.2.0",
+ org.eclipse.papyrus.infra.core.sashwindows.di;bundle-version="1.2.0",
+ org.eclipse.papyrus.designer.transformation.base;bundle-version="0.8.0",
+ org.eclipse.papyrus.designer.languages.cpp.library;bundle-version="1.1.0",
+ org.eclipse.papyrus.designer.languages.common.base;bundle-version="1.1.0",
+ org.eclipse.papyrus.designer.languages.common.codegen.ui;bundle-version="1.1.0",
+ org.eclipse.papyrus.designer.languages.cpp.cdt.texteditor;bundle-version="1.1.0",
+ org.eclipse.papyrus.robotics.transformation.ros2.library;bundle-version="0.7.0",
+ org.eclipse.papyrus.designer.transformation.core;bundle-version="0.8.0",
+ org.eclipse.papyrus.robotics.profile;bundle-version="0.7.0"
+Bundle-Vendor: %providerName
+Bundle-ActivationPolicy: lazy
+Bundle-Version: 0.7.0.qualifier
+Bundle-Localization: plugin
+Bundle-Name: %pluginName
+Bundle-Activator: org.eclipse.papyrus.robotics.cdt.texteditor.Activator
+Bundle-ManifestVersion: 2
+Bundle-Description: %pluginDescription
+Bundle-SymbolicName: org.eclipse.papyrus.robotics.cdt.texteditor;singleton:=true
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Export-Package: org.eclipse.papyrus.robotics.cdt.texteditor
+Automatic-Module-Name: org.eclipse.papyrus.robotics.cdt.texteditor
diff --git a/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/build.properties b/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/build.properties
new file mode 100644
index 0000000..883d0e1
--- /dev/null
+++ b/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/build.properties
@@ -0,0 +1,8 @@
+source.. = src/
+output.. = target/classes/
+bin.includes = META-INF/,\
+               .,\
+               plugin.xml,\
+               build.properties,\
+               icons/,\
+               plugin.properties
diff --git a/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/icons/texteditor.gif b/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/icons/texteditor.gif
new file mode 100644
index 0000000..0d1a289
--- /dev/null
+++ b/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/icons/texteditor.gif
Binary files differ
diff --git a/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/icons/texteditor.xcf b/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/icons/texteditor.xcf
new file mode 100644
index 0000000..1749c42
--- /dev/null
+++ b/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/icons/texteditor.xcf
Binary files differ
diff --git a/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/plugin.properties b/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/plugin.properties
new file mode 100644
index 0000000..c22c525
--- /dev/null
+++ b/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/plugin.properties
@@ -0,0 +1,12 @@
+# Copyright (c) CEA LIST.
+#
+# This program and the accompanying materials are made
+# available under the terms of the Eclipse Public License 2.0
+# which is available at https://www.eclipse.org/legal/epl-2.0/
+#
+# SPDX-License-Identifier: EPL-2.0
+#
+pluginName=Papyrus for Robotics CDT editor integration
+providerName=Eclipse Modeling Project
+
+pluginDescription=This plugin provides a CDT editor integration for Papyrus for Robotics
diff --git a/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/plugin.xml b/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/plugin.xml
new file mode 100644
index 0000000..7d68dcd
--- /dev/null
+++ b/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/plugin.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+	<extension point="org.eclipse.ui.commands">
+		<command
+			description="Open a Robotics CDT Editor"
+			defaultHandler="org.eclipse.papyrus.robotics.cdt.texteditor.handler.SyncRoboticsCDTEditorHandler"
+			id="org.eclipse.papyrus.robotics.cdt.texteditor.cmd.SyncCDTEditor"
+			name="Open a Robotics CDT Editor">
+		</command>
+	</extension>
+
+	<extension point="org.eclipse.ui.menus">
+		<menuContribution
+			allPopups="false"
+			locationURI="popup:org.eclipse.papyrus.robotics.simplifiedui.ui.menu">
+			<command
+				commandId="org.eclipse.papyrus.robotics.cdt.texteditor.cmd.SyncCDTEditor"
+				id="org.eclipse.papyrus.robotics.cdt.texteditor.menu.SyncCDTEditor"
+				icon="icons/texteditor.gif"
+				style="push">
+				<visibleWhen checkEnabled="false">
+					<iterate>
+						<adapt type="org.eclipse.emf.ecore.EObject">
+							<or>
+								<test property="org.eclipse.papyrus.uml.stereotype" value="robotics::components::ComponentDefinition"/>
+								<test property="org.eclipse.papyrus.uml.stereotype" value="robotics::components::Activity"/>
+								<test property="org.eclipse.papyrus.uml.stereotype" value="robotics::components::System"/>
+							</or>
+						</adapt>
+					</iterate>
+				</visibleWhen>
+			</command>
+		</menuContribution>
+	</extension>
+</plugin>
diff --git a/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/pom.xml b/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/pom.xml
new file mode 100644
index 0000000..8d251fe
--- /dev/null
+++ b/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/pom.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>org.eclipse.papyrus.robotics</groupId>
+		<artifactId>org.eclipse.papyrus.robotics.reverse</artifactId>
+		<version>0.7.0-SNAPSHOT</version>
+	</parent>
+	<artifactId>org.eclipse.papyrus.robotics.cdt.texteditor</artifactId>
+	<packaging>eclipse-plugin</packaging>
+	<description>This module contains the Papyrus CDT integration for C++ (definition for model-explorer)</description>
+</project>
diff --git a/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/src/org/eclipse/papyrus/robotics/cdt/texteditor/Activator.java b/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/src/org/eclipse/papyrus/robotics/cdt/texteditor/Activator.java
new file mode 100644
index 0000000..220f852
--- /dev/null
+++ b/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/src/org/eclipse/papyrus/robotics/cdt/texteditor/Activator.java
@@ -0,0 +1,73 @@
+/*****************************************************************************
+ * Copyright (c) 2012 CEA LIST.
+ *
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *  Vincent Lorenzo (CEA LIST) Vincent.Lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.robotics.cdt.texteditor;
+
+import org.eclipse.papyrus.infra.core.log.LogHelper;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class Activator extends AbstractUIPlugin {
+
+	// The plug-in ID
+	public static final String PLUGIN_ID = "org.eclipse.papyrus.robotics.cdt.texteditor"; //$NON-NLS-1$
+
+	// The shared instance
+	private static Activator plugin;
+
+	public static LogHelper log;
+
+	/**
+	 * The constructor
+	 */
+	public Activator() {
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
+	 */
+	@Override
+	public void start(BundleContext context) throws Exception {
+		super.start(context);
+		plugin = this;
+		log = new LogHelper(this);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+	 */
+	@Override
+	public void stop(BundleContext context) throws Exception {
+		plugin = null;
+		super.stop(context);
+	}
+
+	/**
+	 * Returns the shared instance
+	 *
+	 * @return the shared instance
+	 */
+	public static Activator getDefault() {
+		return plugin;
+	}
+
+}
diff --git a/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/src/org/eclipse/papyrus/robotics/cdt/texteditor/AddProfileAndModelLibsHandler.java b/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/src/org/eclipse/papyrus/robotics/cdt/texteditor/AddProfileAndModelLibsHandler.java
new file mode 100644
index 0000000..a96602e
--- /dev/null
+++ b/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/src/org/eclipse/papyrus/robotics/cdt/texteditor/AddProfileAndModelLibsHandler.java
@@ -0,0 +1,146 @@
+/*******************************************************************************
+ * Copyright (c) 2015 CEA LIST.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Ansgar Radermacher - ansgar.radermacher@cea.fr CEA LIST - initial API and implementation
+ *
+ *******************************************************************************/
+
+package org.eclipse.papyrus.robotics.cdt.texteditor;
+
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.emf.common.command.CommandStack;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.edit.domain.EditingDomain;
+import org.eclipse.emf.transaction.RecordingCommand;
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.emf.transaction.util.TransactionUtil;
+import org.eclipse.uml2.uml.Element;
+import org.eclipse.uml2.uml.Package;
+import org.eclipse.uml2.uml.PackageImport;
+import org.eclipse.uml2.uml.Profile;
+import org.eclipse.uml2.uml.UMLFactory;
+import org.eclipse.uml2.uml.resource.UMLResource;
+
+/**
+ * This class adds the C++ profile as well as the ANSI-C library to your model.
+ * 
+ * TODO: currently not used.
+ */
+public class AddProfileAndModelLibsHandler {
+
+	static final String CPP_PROFILE_URI = "pathmap://CPP_PROFILES/C_Cpp.profile.uml"; //$NON-NLS-1$
+
+	static final String ANSIC_LIBRARY_URI = "pathmap://CPP_LIBRARIES/Ansi_C.library.uml"; //$NON-NLS-1$
+
+	/**
+	 * Retrieve a model library from the repository
+	 *
+	 * @param uri
+	 *            the URI of the repository
+	 * @param domain
+	 *            the editing library
+	 *
+	 * @return the package import created for a model library
+	 */
+	public PackageImport getModelLibraryImportFromURI(URI uri, EditingDomain domain) {
+		// Try to reach model
+		Element root = getContent(uri, domain);
+		if (root instanceof Package) {
+
+			// Import model library
+			Package libToImport = (Package) root;
+			// create import package
+			PackageImport modelLibImport = UMLFactory.eINSTANCE.createPackageImport();
+			modelLibImport.setImportedPackage(libToImport);
+
+			return modelLibImport;
+		}
+		return null;
+	}
+
+	public static Element getContent(URI uri, EditingDomain domain) {
+		// Resource resource = getTransactionalEditingDomain ().getResourceSet().getResource (uri, true);
+		Resource resource = domain.getResourceSet().getResource(uri, true);
+		return getContent(resource);
+	}
+
+	public static Element getContent(Resource resource) {
+		EList<EObject> contentObj = resource.getContents();
+		if ((contentObj.size() > 0) && (contentObj.get(0) instanceof Element)) {
+			return (Element) contentObj.get(0);
+		}
+		return null;
+	}
+
+	/**
+	 * Check whether a package import is already done
+	 *
+	 * @param selectedPkg
+	 * @param pi
+	 * @return
+	 */
+	boolean isAlreadyImported(Package selectedPkg, PackageImport pi) {
+		for (PackageImport existingPI : selectedPkg.getPackageImports()) {
+			if ((existingPI.getImportedPackage() == null) ||
+					(pi.getImportedPackage() == null)) {
+				// import package are null (should not happen?!)
+				continue;
+			}
+			if ((existingPI.getImportedPackage().getName() == null) ||
+					(pi.getImportedPackage().getName() == null)) {
+				// import package name not set (should not happen?!)
+				continue;
+			} else if (existingPI.getImportedPackage().getName().equals(pi.getImportedPackage().getName())) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * Add C++ profile and package import for ANSI-C library
+	 * 
+	 * @param selectedPkg
+	 *            the package to which the profile should be applied
+	 * @throws ExecutionException
+	 */
+	public void addProfileAndImport(final Package selectedPkg) throws ExecutionException {
+
+		final TransactionalEditingDomain domain = TransactionUtil.getEditingDomain(selectedPkg);
+		CommandStack stack = domain.getCommandStack();
+		stack.execute(new RecordingCommand(domain, "Add C++ profile & ANSI-C library") { //$NON-NLS-1$
+			@Override
+			public void doExecute() {
+				// add primitive types
+				// create import package to primitiveType
+				PackageImport pi = getModelLibraryImportFromURI(URI.createURI(UMLResource.UML_PRIMITIVE_TYPES_LIBRARY_URI), domain);
+				selectedPkg.getPackageImports().add(pi);
+				addCppProfile(selectedPkg, domain);
+			};
+		});
+	}
+
+	public static void addCppProfile(Package selectedPkg, TransactionalEditingDomain domain) {
+
+		// Retrieve C++ profile
+		Profile cppProfile = (Profile) getContent(URI.createURI(CPP_PROFILE_URI), domain);
+
+		// Apply C++ profile to model
+		if (cppProfile instanceof Profile) {
+			Profile profile = selectedPkg.getAppliedProfile(cppProfile.getQualifiedName());
+			if ((profile == null) && (!cppProfile.getOwnedStereotypes().isEmpty())) {
+				selectedPkg.applyProfile(cppProfile);
+			}
+		}
+	}
+}
diff --git a/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/src/org/eclipse/papyrus/robotics/cdt/texteditor/TextEditorConstants.java b/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/src/org/eclipse/papyrus/robotics/cdt/texteditor/TextEditorConstants.java
new file mode 100644
index 0000000..366204d
--- /dev/null
+++ b/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/src/org/eclipse/papyrus/robotics/cdt/texteditor/TextEditorConstants.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2013 CEA LIST.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Ansgar Radermacher - ansgar.radermacher@cea.fr CEA LIST - initial API and implementation
+ *
+ *******************************************************************************/
+
+package org.eclipse.papyrus.robotics.cdt.texteditor;
+
+import java.util.regex.Pattern;
+
+public class TextEditorConstants {
+
+	/**
+	 * Regular expression for accepted language for compatible CDT code generators
+	 */
+	public static final Pattern CPP = Pattern.compile("C\\+\\+|c\\+\\+|CPP|cpp|C|c"); //$NON-NLS-1$
+}
diff --git a/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/src/org/eclipse/papyrus/robotics/cdt/texteditor/handler/SyncRoboticsCDTEditorHandler.java b/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/src/org/eclipse/papyrus/robotics/cdt/texteditor/handler/SyncRoboticsCDTEditorHandler.java
new file mode 100644
index 0000000..759f27d
--- /dev/null
+++ b/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/src/org/eclipse/papyrus/robotics/cdt/texteditor/handler/SyncRoboticsCDTEditorHandler.java
@@ -0,0 +1,155 @@
+/*****************************************************************************
+ * Copyright (c) 2012, 2016 CEA LIST, Christian W. Damus, and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *  Vincent Lorenzo (CEA LIST) Vincent.Lorenzo@cea.fr - Initial API and implementation
+ *  Ansgar Radermacher (CEA LIST) ansgar.radermacher@cea.fr
+ *  Christian W. Damus - bug 485220
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.robotics.cdt.texteditor.handler;
+
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.emf.workspace.AbstractEMFOperation;
+import org.eclipse.papyrus.designer.languages.cpp.cdt.texteditor.editor.SyncCDTEditor;
+import org.eclipse.papyrus.designer.languages.cpp.cdt.texteditor.handler.SyncCDTEditorHandler;
+import org.eclipse.papyrus.infra.core.resource.NotFoundException;
+import org.eclipse.papyrus.infra.core.services.ServiceException;
+import org.eclipse.papyrus.infra.core.services.ServicesRegistry;
+import org.eclipse.papyrus.infra.core.utils.ServiceUtils;
+import org.eclipse.papyrus.infra.emf.gmf.command.CheckedOperationHistory;
+import org.eclipse.papyrus.infra.ui.util.ServiceUtilsForHandlers;
+import org.eclipse.papyrus.robotics.cdt.texteditor.Activator;
+import org.eclipse.papyrus.robotics.cdt.texteditor.sync.SyncRoboticsCDTtoModel;
+import org.eclipse.papyrus.robotics.cdt.texteditor.sync.SyncRoboticsModelToCDT;
+import org.eclipse.papyrus.robotics.profile.robotics.components.Activity;
+import org.eclipse.papyrus.uml.tools.utils.StereotypeUtil;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.part.FileEditorInput;
+import org.eclipse.uml2.uml.Classifier;
+
+
+/**
+ * The handler creates a new CDT editor
+ */
+public class SyncRoboticsCDTEditorHandler extends SyncCDTEditorHandler {
+
+
+	public SyncRoboticsCDTEditorHandler() {
+	}
+
+	/**
+	 * @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.ExecutionEvent)
+	 *
+	 * @param event
+	 *            an execution event
+	 * @return the execution result
+	 * @throws ExecutionException
+	 */
+	@Override
+	public Object execute(final ExecutionEvent event) throws ExecutionException {
+		try {
+			final ServicesRegistry serviceRegistry = ServiceUtilsForHandlers.getInstance().getServiceRegistry(event);
+			TransactionalEditingDomain domain = ServiceUtils.getInstance().getTransactionalEditingDomain(serviceRegistry);
+
+			
+			// Create the transactional command
+			AbstractEMFOperation command = new AbstractEMFOperation(domain, "Create CDT editor") { //$NON-NLS-1$
+
+				@Override
+				protected IStatus doExecute(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException {
+					try {
+						SyncRoboticsCDTEditorHandler.this.doExecute(serviceRegistry);
+					} catch (ServiceException e) {
+						Activator.log.error(e);
+						return Status.CANCEL_STATUS;
+					} catch (NotFoundException e) {
+						Activator.log.error(e);
+						return Status.CANCEL_STATUS;
+					}
+					return Status.OK_STATUS;
+				}
+			};
+
+			// Execute the command
+			CheckedOperationHistory.getInstance().execute(command, new NullProgressMonitor(), null);
+		} catch (ExecutionException e) {
+			Activator.log.error("Can't create a CDT editor", e); //$NON-NLS-1$
+		} catch (ServiceException e) {
+			Activator.log.error("Service exception during creation of CDT editor", e); //$NON-NLS-1$
+		}
+		return null;
+	}
+
+
+	/**
+	 * Do the execution of the command.
+	 *
+	 * @param serviceRegistry
+	 * @throws ServiceException
+	 * @throws NotFoundException
+	 */
+	public void doExecute(final ServicesRegistry serviceRegistry) throws ServiceException, NotFoundException {
+		Classifier classifierToEdit = getClassifierToEdit();
+
+		IFile srcFile = SyncRoboticsModelToCDT.syncModelToCDT(classifierToEdit, "Standard C++");
+		if (srcFile == null) {
+			return;
+		}
+
+		Display.getDefault().asyncExec(new Runnable() {
+
+			@Override
+			public void run() {
+				IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+				try {
+					// IEditorPart editorPart = page.openEditor(new FileEditorInput(srcFile), "org.eclipse.cdt.ui.editor.CEditor");
+					
+					IEditorInput input = new FileEditorInput(srcFile);
+					IEditorPart editorPart = page.openEditor(input, "org.eclipse.papyrus.designer.languages.cpp.cdt.texteditor.editor.SyncCDTEditor");
+					if (editorPart instanceof SyncCDTEditor) {
+						// TODO: use editorPart.setInitializationData(cfig, propertyName, data);
+						URI uri = selectedEObject.eResource().getURI();
+						SyncRoboticsCDTtoModel syncCpp =
+								new SyncRoboticsCDTtoModel(input, classifierToEdit, uri.segment(1), "Standard C++");
+
+						((SyncCDTEditor) editorPart).setEditorData(serviceRegistry, syncCpp);
+					}
+				} catch (PartInitException e) {
+					Activator.log.error(e);
+				}
+			}
+		});
+	}
+	
+	@Override
+	protected Classifier getClassifierToEdit() {
+		Classifier cl = super.getClassifierToEdit();
+		if (StereotypeUtil.isApplied(cl, Activity.class)) {
+			// activities are always within components
+			return (Classifier) cl.getOwner();
+		}
+		return cl;
+	}
+}
diff --git a/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/src/org/eclipse/papyrus/robotics/cdt/texteditor/sync/PortInfo.java b/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/src/org/eclipse/papyrus/robotics/cdt/texteditor/sync/PortInfo.java
new file mode 100644
index 0000000..ded5f6c
--- /dev/null
+++ b/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/src/org/eclipse/papyrus/robotics/cdt/texteditor/sync/PortInfo.java
@@ -0,0 +1,12 @@
+package org.eclipse.papyrus.robotics.cdt.texteditor.sync;
+
+public class PortInfo {
+	
+	public enum ProviderKind {
+		PUBLISHER, SUBSCRIBER, CLIENT, SERVER, ACTION_CLI, ACTION_SRV
+	}
+	
+	public ProviderKind pk;
+	public String dtQName;
+	public String topic;
+}
diff --git a/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/src/org/eclipse/papyrus/robotics/cdt/texteditor/sync/SyncPortsFromSource.java b/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/src/org/eclipse/papyrus/robotics/cdt/texteditor/sync/SyncPortsFromSource.java
new file mode 100644
index 0000000..c216d80
--- /dev/null
+++ b/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/src/org/eclipse/papyrus/robotics/cdt/texteditor/sync/SyncPortsFromSource.java
@@ -0,0 +1,173 @@
+package org.eclipse.papyrus.robotics.cdt.texteditor.sync;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
+import org.eclipse.cdt.core.dom.ast.IASTExpression;
+import org.eclipse.cdt.core.dom.ast.IASTExpressionList;
+import org.eclipse.cdt.core.dom.ast.IASTFieldReference;
+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.IASTTranslationUnit;
+import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition;
+import org.eclipse.cdt.core.model.CoreModel;
+import org.eclipse.cdt.core.model.ITranslationUnit;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.papyrus.commands.Activator;
+import org.eclipse.papyrus.robotics.cdt.texteditor.sync.PortInfo.ProviderKind;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.uml2.uml.Classifier;
+
+public class SyncPortsFromSource {
+
+	private static final String CREATE_PUBLISHER = "create_publisher"; //$NON-NLS-1$
+	private static final String CREATE_SUBSCRIPTION = "create_subscription"; //$NON-NLS-1$
+	private static final String CREATE_SERVICE = "create_service"; //$NON-NLS-1$
+	private static final String CREATE_CLIENT = "create_client"; //$NON-NLS-1$
+
+	private static final String EXTERNAL_FILES = "External Files"; //$NON-NLS-1$
+
+	public static void updatePorts(Classifier cl, IASTNode node) {
+		List<PortInfo> portInfoList = new ArrayList<PortInfo>();
+		scanFunctions(node, portInfoList);
+		for (PortInfo pi : portInfoList) {
+			System.err.println(pi.dtQName);
+			// NamedElement namedElemParamType = ElementUtils.getQualifiedElementFromRS(element, expr2);
+		}
+	}
+
+	public static void scanFunctions(IASTNode node, List<PortInfo> portInfoList) {
+
+		for (IASTNode child : node.getChildren()) {
+			if (child instanceof IASTFunctionDefinition) {
+				IASTFunctionDefinition definition = (IASTFunctionDefinition) child;
+				scanBody(definition.getBody(), portInfoList);
+			}
+			if (child instanceof ICPPASTNamespaceDefinition) {
+				// recurse into namespaces
+				scanFunctions(child, portInfoList);
+			}
+		}
+	}
+	public static String getASTName(IASTExpression expr) {
+		if (expr instanceof IASTFieldReference) {
+			IASTName fieldName = ((IASTFieldReference) expr).getFieldName();
+			if (fieldName != null) {
+				return fieldName.toString();
+			}
+			return ""; //$NON-NLS-1$
+		} else {
+			return expr.toString();
+		}
+	}
+
+	public static ProviderKind getProviderFromCall(String fctName) {
+		if (fctName.equals(CREATE_CLIENT)) {
+			return ProviderKind.CLIENT;
+		}
+		if (fctName.equals(CREATE_SERVICE)) {
+			return ProviderKind.SERVER;
+		}
+		if (fctName.equals(CREATE_SUBSCRIPTION)) {
+			return ProviderKind.SUBSCRIBER;
+		}
+		if (fctName.equals(CREATE_PUBLISHER)) {
+			return ProviderKind.PUBLISHER;
+		}
+		return null;
+	}
+
+	public static PortInfo obtainCallDetails(ProviderKind pk, IASTExpression expr1, IASTExpression expr2) {
+		IASTExpression expr2b = ((IASTBinaryExpression) expr1).getOperand2();
+		IASTExpression topicExpr = null;
+		if (expr2 instanceof IASTUnaryExpression) {
+			IASTExpression arguments = ((IASTUnaryExpression) expr2).getOperand();
+			if (arguments instanceof IASTExpressionList) {
+				topicExpr = ((IASTExpressionList) arguments).getExpressions()[0];
+			} else {
+				topicExpr = arguments;
+			}
+		}
+		String topicName = topicExpr.toString();
+		// remove quotes
+		if (topicName.startsWith("\"") && topicName.length()>=2) { //$NON-NLS-1$
+			topicName = topicName.substring(1, topicName.length()-1);
+		}
+		PortInfo portInfo = new PortInfo();
+		portInfo.pk = pk;
+		portInfo.dtQName = getASTName(expr2b);
+		portInfo.topic = topicName;
+		return portInfo;
+}
+	
+	public static void scanBody(IASTNode node, List<PortInfo> portList) {
+		if (node instanceof IASTBinaryExpression) {
+			IASTBinaryExpression expr = (IASTBinaryExpression) node;
+			IASTExpression expr1 = expr.getOperand1();
+			IASTExpression expr2 = expr.getOperand2();
+			if (expr1 instanceof IASTBinaryExpression) {
+				IASTExpression expr1b = ((IASTBinaryExpression) expr1).getOperand1();
+				String fieldName = getASTName(expr1b);
+
+				if (fieldName != null) {
+					ProviderKind pk = getProviderFromCall(fieldName);
+					if (pk != null) {
+						PortInfo portInfo = obtainCallDetails(pk, expr1, expr2);
+						if (portInfo != null) {
+							portList.add(portInfo);
+						}
+					}	
+				}
+			}
+		}
+		for (IASTNode child : node.getChildren()) {
+			// recurse into all children
+			scanBody(child, portList);
+		}
+	}
+
+	public static void tst() {
+		IWorkspace ws = ResourcesPlugin.getWorkspace();
+		IProject project = ws.getRoot().getProject(EXTERNAL_FILES);
+
+		try {
+			if (!project.exists())
+				project.create(null);
+			if (!project.isOpen())
+				project.open(null);
+			Shell shell = Display.getDefault().getActiveShell();
+			String name = (1 == 0) ? "/local/home/ansgar/prog/ros2/demos/demo_nodes_cpp/src/services/add_two_ints_client.cpp" : new FileDialog(shell, SWT.OPEN).open();
+			if (name == null)
+				return;
+			IPath location = new Path(name);
+			IFile srcFile = project.getFile(location.lastSegment());
+			boolean exists = srcFile.exists();
+			if (exists) {
+				srcFile.delete(false, null);
+			}
+			srcFile.createLink(location, IResource.NONE, null);
+
+
+			ITranslationUnit itu = (ITranslationUnit) CoreModel.getDefault().create(srcFile);
+
+			IASTTranslationUnit ast = itu.getAST();
+			scanFunctions(ast, new ArrayList<PortInfo>());
+
+		} catch (CoreException e) {
+			Activator.log.error(e);
+		}
+	}
+}
diff --git a/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/src/org/eclipse/papyrus/robotics/cdt/texteditor/sync/SyncRoboticsCDTtoModel.java b/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/src/org/eclipse/papyrus/robotics/cdt/texteditor/sync/SyncRoboticsCDTtoModel.java
new file mode 100644
index 0000000..6977980
--- /dev/null
+++ b/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/src/org/eclipse/papyrus/robotics/cdt/texteditor/sync/SyncRoboticsCDTtoModel.java
@@ -0,0 +1,468 @@
+/*******************************************************************************
+ * Copyright (c) 2013 CEA LIST.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Ansgar Radermacher - ansgar.radermacher@cea.fr CEA LIST - initial API and implementation
+ *
+ *******************************************************************************/
+
+package org.eclipse.papyrus.robotics.cdt.texteditor.sync;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement;
+import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
+import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
+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.IASTNodeSelector;
+import org.eclipse.cdt.core.dom.ast.IASTStatement;
+import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
+import org.eclipse.cdt.core.index.IIndex;
+import org.eclipse.cdt.core.model.CModelException;
+import org.eclipse.cdt.core.model.CoreModel;
+import org.eclipse.cdt.core.model.ICElement;
+import org.eclipse.cdt.core.model.ICProject;
+import org.eclipse.cdt.core.model.IFunctionDeclaration;
+import org.eclipse.cdt.core.model.IMethodDeclaration;
+import org.eclipse.cdt.core.model.IParent;
+import org.eclipse.cdt.core.model.ISourceRange;
+import org.eclipse.cdt.core.model.ISourceReference;
+import org.eclipse.cdt.core.model.ITranslationUnit;
+import org.eclipse.cdt.core.model.IWorkingCopy;
+import org.eclipse.cdt.ui.CDTUITools;
+import org.eclipse.cdt.ui.CUIPlugin;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.emf.common.util.BasicEList;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.papyrus.designer.languages.common.extensionpoints.ILangCodegen;
+import org.eclipse.papyrus.designer.languages.common.extensionpoints.ILangCodegen2;
+import org.eclipse.papyrus.designer.languages.common.extensionpoints.SyncInformation;
+import org.eclipse.papyrus.designer.languages.cpp.cdt.texteditor.Utils;
+import org.eclipse.papyrus.designer.languages.cpp.cdt.texteditor.listener.ModelListener;
+import org.eclipse.papyrus.designer.languages.cpp.cdt.texteditor.sync.SyncCDTtoModel;
+import org.eclipse.papyrus.designer.languages.cpp.codegen.Constants;
+import org.eclipse.papyrus.designer.languages.cpp.profile.C_Cpp.Include;
+import org.eclipse.papyrus.infra.core.Activator;
+import org.eclipse.papyrus.robotics.cdt.texteditor.TextEditorConstants;
+import org.eclipse.papyrus.uml.tools.utils.StereotypeUtil;
+import org.eclipse.papyrus.uml.tools.utils.UMLUtil;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.uml2.uml.Behavior;
+import org.eclipse.uml2.uml.BehavioralFeature;
+import org.eclipse.uml2.uml.Class;
+import org.eclipse.uml2.uml.Classifier;
+import org.eclipse.uml2.uml.Comment;
+import org.eclipse.uml2.uml.NamedElement;
+import org.eclipse.uml2.uml.OpaqueBehavior;
+import org.eclipse.uml2.uml.Operation;
+import org.eclipse.uml2.uml.PackageableElement;
+import org.eclipse.uml2.uml.Parameter;
+import org.eclipse.uml2.uml.ParameterDirectionKind;
+import org.eclipse.uml2.uml.Type;
+import org.eclipse.uml2.uml.UMLFactory;
+import org.eclipse.uml2.uml.UMLPackage;
+
+public class SyncRoboticsCDTtoModel extends SyncCDTtoModel {
+
+	public SyncRoboticsCDTtoModel(IEditorInput input, Classifier classifier, String projectName, String generatorID) {
+		super(input, classifier, projectName, generatorID);
+	}
+	
+
+	@Override
+	public void run() {
+		ICElement ice = CDTUITools.getEditorInputCElement(m_input);
+		ModelListener.syncFromEditor = true;
+
+		if (ice instanceof ITranslationUnit) {
+			ICProject project = CoreModel.getDefault().getCModel().getCProject(m_projectName);
+
+			IIndex index = null;
+			try {
+				index = CCorePlugin.getIndexManager().getIndex(project);
+				index.acquireReadLock();
+
+				ITranslationUnit itu = (ITranslationUnit) ice;
+
+				IASTTranslationUnit ast = itu.getAST(index, ITranslationUnit.AST_SKIP_INDEXED_HEADERS);
+				IASTNodeSelector selector = ast.getNodeSelector(null);
+
+				examineChildren(itu, selector, itu);
+				updateCppInclude(itu);
+				SyncPortsFromSource.updatePorts(m_classifier, ast);
+
+				CUIPlugin.getDefault().getProblemMarkerManager();
+				if (itu instanceof IWorkingCopy) {
+					((IWorkingCopy) itu).reconcile(true, new NullProgressMonitor());
+				}
+
+			} catch (CModelException e) {
+				Activator.log.error(e);
+			} catch (Exception e) {
+				Activator.log.error(e);
+			} finally {
+				if (index != null) {
+					index.releaseReadLock();
+				}
+			}
+		}
+		ModelListener.syncFromEditor = false;
+	}
+
+	/**
+	 * Examine the children of a translation unit in order to extract the
+	 * methods that are defined within hte unit
+	 *
+	 * @param itu
+	 * @param selector
+	 * @param parent
+	 * @throws CModelException
+	 */
+	public void examineChildren(ITranslationUnit itu, IASTNodeSelector selector, IParent parent)
+			throws CModelException {
+
+		int position = 0;
+		// if (parent instanceof Namespace) {
+		for (ICElement child : parent.getChildren()) {
+			if (child instanceof IParent) {
+				examineChildren(itu, selector, (IParent) child);
+			}
+			ISourceRange range = null;
+			if (child instanceof ISourceReference) {
+				range = ((ISourceReference) child).getSourceRange();
+			}
+			if (child instanceof IFunctionDeclaration) {
+				// function declaration is a superclass for method declaration
+				// (but need to trace functions differently?)
+				String name = ((IFunctionDeclaration) child).getElementName();
+				IASTNode node = selector.findEnclosingNode(range.getStartPos(), range.getLength());
+				if (node instanceof IASTFunctionDefinition) {
+					IASTFunctionDefinition definition = (IASTFunctionDefinition) node;
+					IASTFunctionDeclarator declarator = definition.getDeclarator();
+					String unfilteredBody = getBody(itu, definition);
+					// get additional information about method synchronization from generator
+					SyncInformation syncInfo = null;
+					if (m_codegen instanceof ILangCodegen2) {
+						syncInfo = ((ILangCodegen2) m_codegen).getSyncInformation(name, unfilteredBody);
+					}
+					String body = Utils.removeGenerated(unfilteredBody);
+					if (syncInfo == null || !syncInfo.isGenerated) {
+						// only update method, if it is not generated 
+						NamedElement ne = updateMethod(position, parent, name, body, declarator, syncInfo);
+						if (ne != null) {
+							updateComment(itu, definition, ne);
+						}
+					}
+					// System.err.println("body source <" + body + ">");
+				}
+				position++;
+			}
+		}
+	}
+
+	/**
+	 * update the contents of the CppInclude directive
+	 *
+	 * @param itu
+	 *            the translation unit
+	 */
+	public void updateCppInclude(ITranslationUnit itu) {
+		String contents = new String(itu.getContents());
+		int preBodyStart = contents.indexOf(Constants.cppIncPreBodyStart);
+		int preBodyEnd = contents.indexOf(Constants.cppIncPreBodyEnd);
+		String preBody = ""; //$NON-NLS-1$
+		String body = ""; //$NON-NLS-1$
+		if (preBodyStart != -1) {
+			preBodyStart += Constants.cppIncPreBodyStart.length();
+			if (preBodyEnd > preBodyStart) {
+				preBody = contents.substring(preBodyStart, preBodyEnd).trim();
+			}
+		}
+
+		int bodyStart = contents.indexOf(Constants.cppIncBodyStart);
+		int bodyEnd = contents.indexOf(Constants.cppIncBodyEnd);
+
+		if (bodyStart != -1) {
+			bodyStart += Constants.cppIncBodyStart.length() + 1;
+			if (bodyEnd > bodyStart) {
+				body = contents.substring(bodyStart, bodyEnd).trim();
+			}
+		}
+		if (body.length() > 0 || preBody.length() > 0) {
+			Include include = StereotypeUtil.applyApp(m_classifier, Include.class);
+			if (include != null) {
+				include.setPreBody(preBody);
+				include.setBody(body);
+			}
+		}
+	}
+
+	/**
+	 * Update a method in the model based on the qualified name.
+	 *
+	 * @param position
+	 *            The position of the method within the file. Used to identify
+	 *            renaming operations
+	 * @param parent
+	 *            the CDT parent which is used to get a list of children
+	 * @param qualifiedName
+	 *            the qualified name of a method
+	 * @param body
+	 *            the method body
+	 * @param declarator
+	 *            the declarator for the method
+	 * @return the operation or the behavior within the model that got updated. The latter is returned in
+	 *            case of behaviors that do not have a specification (e.g. the effect of a transition).
+	 */
+	public NamedElement updateMethod(int position, IParent parent, String qualifiedName, String body,
+			IASTFunctionDeclarator declarator, SyncInformation syncInfo) {
+
+		String names[] = qualifiedName.split(Utils.nsSep);
+		String name = names[names.length - 1];
+
+		Operation operation = null;
+		Behavior behavior = null;
+
+		if (syncInfo == null || (syncInfo.behavior == null && syncInfo.createBehaviorName == null)) {
+			behavior = getModelBehaviorFromName(name, parent, position);
+			if (behavior != null) {
+				behavior.setName(name);
+			}
+		}
+		else if (syncInfo.behavior != null) {
+			// operation is still null (=> does not enter operation != null case below)
+			behavior = syncInfo.behavior;
+		}
+		else if ((syncInfo.createBehaviorName != null) && (m_classifier instanceof Class)) {
+			Class clazz = (Class) m_classifier;
+			behavior = (OpaqueBehavior) clazz.createOwnedBehavior(syncInfo.createBehaviorName,
+					UMLPackage.eINSTANCE.getOpaqueBehavior().eClass());
+		}
+		if (behavior == null) {
+			return null;
+		}
+
+		// Remove all parameters from operation / behavior (they will be added later).
+		// Calling parameters.clear() is not sufficient. Otherwise stereotype
+		// applications to unresolved elements remain in the model
+		List<Parameter> existingParameters = new BasicEList<Parameter>();
+		UMLUtil.destroyElements(behavior.getOwnedParameters());
+		if (behavior != null) {
+			for (Parameter existingParameter : behavior.getOwnedParameters()) {
+				Parameter existingParamCopy = UMLFactory.eINSTANCE.createParameter();
+				existingParamCopy.setName(existingParameter.getName());
+				existingParamCopy.setType(existingParameter.getType());
+				existingParamCopy.setDirection(existingParameter.getDirection());
+				existingParameters.add(existingParamCopy);
+			}
+		}
+	
+		IASTFunctionDefinition definition = (IASTFunctionDefinition) declarator.getParent();
+		IASTDeclSpecifier declSpecifier = definition.getDeclSpecifier();
+		Type paramType = getParameterType(null, declSpecifier.toString(), existingParameters);
+		Parameter umlParameter = null;
+		umlParameter = behavior.createOwnedParameter("ret", paramType);
+		umlParameter.setDirection(ParameterDirectionKind.RETURN_LITERAL);
+		// applyParameterModifiers(parameterType, umlParameter, modifiers);
+
+		if (behavior instanceof OpaqueBehavior) {
+			OpaqueBehavior ob = (OpaqueBehavior) behavior;
+			if (ob.getBodies().size() == 0) {
+				ob.getLanguages().add(c_cpp_langID);
+				ob.getBodies().add(""); //$NON-NLS-1$
+			}
+			for (int i = 0; i < ob.getLanguages().size(); i++) {
+				// update first body of one of the languages supported by CDT. This implies that
+				// it is actually not possible to have separate C and C++ bodes in the same opaque
+				// behavior (which is rarely a good idea).
+				String language = ob.getLanguages().get(i);
+				if (TextEditorConstants.CPP.matcher(language).matches() || c_cpp_langID.equals(language)) {
+					if (i < ob.getBodies().size()) {
+						// should always be true, unless sync between
+						// languages/bodies is lost
+						ob.getBodies().set(i, body);
+					}
+				}
+			}
+		}
+		return behavior;
+	}
+
+	/**
+	 * Obtain a behavior from the model. Similar to method getModelOperationFromName in
+	 * superclass, but Robotics functions are currently defined by opaque behaviors
+	 * 
+	 * @param name the operation name within CDT
+	 * @param parent the parent of the CDT method within CDT editor model
+	 * @param position the position within the other methods. This information is used to locate methods
+	 *   within the model that might have been renamed in the CDT editor.
+	 * @return a UML operation
+	 */
+	public Behavior getModelBehaviorFromName(String name, IParent parent, int position) {
+		// operation does not belong to component itself, but to one of the
+		// activities which in turn consist of functions. Currently, functions are defined
+		// in the package containing the component
+		PackageableElement beh = m_classifier.getNearestPackage().getPackagedElement(name);
+		if (beh instanceof OpaqueBehavior) {
+			return (OpaqueBehavior) beh;
+		}
+
+		List<Behavior> bl = new ArrayList<Behavior>();
+		for (PackageableElement pe : m_classifier.getNearestPackage().getPackagedElements()) {
+			if (pe instanceof Behavior) {
+				bl.add((Behavior) pe);
+			}
+		}
+		// operation is not found via name in the model. try to locate the operation in the model at the same
+		// "position" as the method in the file and
+		// verify that this method does not have the same name as any method
+		// in the CDT file.
+		Behavior be = null;
+		if (position < bl.size()) {
+			be = bl.get(position);
+			String modelName = be.getName();
+			try {
+				for (ICElement child : parent.getChildren()) {
+					if (child instanceof IMethodDeclaration) {
+						String cdtName = ((IMethodDeclaration) child).getElementName();
+						if (cdtName.equals(modelName)) {
+							// an existing operation in the CDT file already
+							// has this name
+							be = null;
+							break;
+						}
+					}
+				}
+			} catch (CModelException e) {
+			}
+		}
+		return be;
+	}
+	
+	public static String getBody(ITranslationUnit itu, IASTFunctionDefinition definition) {
+		IASTStatement body = definition.getBody();
+
+		if (body instanceof IASTCompoundStatement) {
+			IASTCompoundStatement bodyComp = (IASTCompoundStatement) body;
+
+			IASTFileLocation bodyLoc = bodyComp.getFileLocation();
+			int start = bodyLoc.getNodeOffset();
+			int end = start + bodyLoc.getNodeLength();
+			char contents[] = itu.getContents();
+			// body contains enclosing { } which we need to remove (+2, -2). We
+			// cannot use the
+			// first and last statement, since leading and trailing comments are
+			// not part of the AST tree.
+			return Utils.decreaseIndent(contents, start + 2, end - 2);
+		}
+		return ""; //$NON-NLS-1$
+	}
+
+	/**
+	 * update a comment of a named element. Besides the comment of the element itself, comments on contained
+	 * parameters are handled.
+	 * 
+	 * @param itu a translation unit
+	 * @param definition
+	 * @param ne a named element that is either an operation or a behavior (in order to update parameters)
+	 */
+	public void updateComment(ITranslationUnit itu, IASTFunctionDefinition definition, NamedElement ne) {
+		IASTFileLocation bodyLoc = definition.getFileLocation();
+		int start = bodyLoc.getNodeOffset() - 1;
+		int end = start;
+		char contents[] = itu.getContents();
+		String comment = ""; //$NON-NLS-1$
+		// backward scan for beginning /*
+		while (start > 0) {
+			if (contents[start] == '/' && contents[start + 1] == '*') {
+				start += "/**".length(); // TODO: common string //$NON-NLS-1$
+											// constants with generator
+				for (int i = start; i < end; i++) {
+					comment += contents[i];
+				}
+				comment = comment.replace("\n * ", "\n"). //$NON-NLS-1$//$NON-NLS-2$
+						replace("*/", "").trim(); //$NON-NLS-1$//$NON-NLS-2$
+				break;
+			}
+			start--;
+		}
+		if (comment.length() > 0) {
+			// filter @param
+			int atParam = comment.indexOf(sAtParam);
+			String commentMethodOnly = (atParam != -1) ? comment.substring(0, atParam).trim() : comment;
+
+			EList<Comment> commentsUML = ne.getOwnedComments();
+			Comment commentUML;
+			if (commentsUML.size() == 0) {
+				commentUML = ne.createOwnedComment();
+				commentUML.getAnnotatedElements().add(commentUML);
+			} else {
+				commentUML = commentsUML.get(0);
+			}
+			while (atParam != -1) {
+				int currentAtParam = atParam;
+				atParam = comment.indexOf(sAtParam, atParam + 1);
+				String commentParam = (atParam != -1) ? comment.substring(currentAtParam, atParam)
+						: comment.substring(currentAtParam);
+				Comment commentParamUML;
+				int atParamName = sAtParam.length();
+
+				while ((atParamName < commentParam.length())
+						&& Character.isWhitespace(commentParam.charAt(atParamName))) {
+					atParamName++;
+				}
+				int atParamNameEnd = atParamName;
+				while ((atParamNameEnd < commentParam.length())
+						&& !Character.isWhitespace(commentParam.charAt(atParamNameEnd))) {
+					atParamNameEnd++;
+				}
+				if (atParamNameEnd < commentParam.length() - 1) {
+					String parameterName = commentParam.substring(atParamName, atParamNameEnd);
+					String commentParamText = commentParam.substring(atParamNameEnd).trim();
+					Parameter parameter = null;
+					if (ne instanceof BehavioralFeature) {
+						parameter = ((BehavioralFeature) ne).getOwnedParameter(parameterName, null, false, false);
+					}
+					else if (ne instanceof Behavior) {
+						parameter = ((Behavior) ne).getOwnedParameter(parameterName, null, false, false);		
+					}
+					if (parameter != null) {
+						EList<Comment> commentsParamUML = parameter.getOwnedComments();
+						if (commentsParamUML.size() == 0) {
+							commentParamUML = parameter.createOwnedComment();
+							commentParamUML.getAnnotatedElements().add(commentParamUML);
+						} else {
+							commentParamUML = commentsParamUML.get(0);
+						}
+						commentParamUML.setBody(commentParamText);
+					} else {
+						// parameter is not found in model, e.g. either renamed
+						// or not yet existing
+						// store comment in operation comment
+						commentMethodOnly += "\n " + sAtParam + parameterName + //$NON-NLS-1$
+								" not found(!) " + commentParamText; //$NON-NLS-1$
+					}
+				}
+			}
+			commentUML.setBody(commentMethodOnly);
+		}
+	}
+
+	/**
+	 * Accessor
+	 * @return value of codegen attribute
+	 */
+	public ILangCodegen getCodeGen() {
+		return m_codegen;
+	}
+}
diff --git a/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/src/org/eclipse/papyrus/robotics/cdt/texteditor/sync/SyncRoboticsModelToCDT.java b/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/src/org/eclipse/papyrus/robotics/cdt/texteditor/sync/SyncRoboticsModelToCDT.java
new file mode 100644
index 0000000..a0f02c4
--- /dev/null
+++ b/plugins/reverse/org.eclipse.papyrus.robotics.cdt.texteditor/src/org/eclipse/papyrus/robotics/cdt/texteditor/sync/SyncRoboticsModelToCDT.java
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright (c) 2013 CEA LIST.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Ansgar Radermacher - ansgar.radermacher@cea.fr CEA LIST - initial API and implementation
+ *
+ *******************************************************************************/
+
+package org.eclipse.papyrus.robotics.cdt.texteditor.sync;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+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.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.papyrus.designer.languages.common.extensionpoints.ILangCodegen;
+import org.eclipse.papyrus.designer.languages.common.extensionpoints.ILangCodegen.FILE_KIND;
+import org.eclipse.papyrus.designer.languages.common.extensionpoints.ILangCodegen2;
+import org.eclipse.papyrus.designer.languages.common.extensionpoints.LanguageCodegen;
+import org.eclipse.papyrus.designer.languages.cpp.codegen.Constants;
+import org.eclipse.papyrus.designer.transformation.base.utils.ProjectManagement;
+import org.eclipse.papyrus.designer.transformation.core.transformations.ExecuteTransformationChain;
+import org.eclipse.papyrus.infra.core.Activator;
+import org.eclipse.papyrus.robotics.cdt.texteditor.TextEditorConstants;
+import org.eclipse.papyrus.robotics.transformation.ros2.library.commands.PrepareCodegenCmd;
+import org.eclipse.papyrus.uml.tools.utils.PackageUtil;
+import org.eclipse.ui.progress.UIJob;
+import org.eclipse.uml2.uml.Class;
+import org.eclipse.uml2.uml.Classifier;
+import org.eclipse.uml2.uml.Package;
+
+/**
+ * Main listener for model changes (registered via plugin.xml). It will delegate
+ * to the sub-listeners for specific sub-elements (type, operation, port, ...) that
+ * can be found in this package
+ *
+ */
+public class SyncRoboticsModelToCDT {
+
+	private static final String CPP_SUFFIX = "cpp"; //$NON-NLS-1$
+	/**
+	 * set to true, if a synchronization from an CDT editor to the model is active
+	 */
+	public static boolean syncFromEditor;
+
+	public static IFile syncModelToCDT(Classifier classifier, String generatorID) {
+		if (!(classifier instanceof Class) || classifier.eResource() == null) {
+			return null;
+		}
+
+		Package pkg = PackageUtil.getRootPackage((Class) classifier);
+		PrepareCodegenCmd prepareCmd = new PrepareCodegenCmd(pkg);
+		if (prepareCmd.prepare()) {
+			IProject modelProject = ProjectManagement.getCurrentProject();
+
+			Job job = new UIJob("Generate ROS code") {
+
+				@Override
+				public IStatus runInUIThread(IProgressMonitor monitor) {
+					// execute the task ...
+					new ExecuteTransformationChain(pkg, modelProject).executeTransformation(monitor, 0);
+					prepareCmd.undo();
+					return Status.OK_STATUS;
+				}
+			};
+			job.setUser(true);
+			job.schedule();
+
+			ILangCodegen codegen = LanguageCodegen.getGenerator(TextEditorConstants.CPP, generatorID);
+			IProject targetProject = ResourcesPlugin.getWorkspace().getRoot().getProject(classifier.getName());
+
+			IContainer srcPkg = null;
+			IFile cppFile = null;
+			try {
+
+				String suffix = (codegen instanceof ILangCodegen2) ? suffix = ((ILangCodegen2) codegen).getSuffix(FILE_KIND.BODY) : CPP_SUFFIX;
+
+				cppFile = targetProject.getFile(new Path(codegen.getFileName(targetProject, classifier) + Constants.DOT + suffix));
+
+				// IStorage storage = new TextStorage(string);
+			} finally {
+				// Refresh the container for the newly created files. This needs to be done even
+				// during error because of the possibility for partial results.
+				try {
+					if (srcPkg != null) {
+						srcPkg.refreshLocal(IResource.DEPTH_INFINITE, null);
+					}
+				} catch (CoreException e) {
+					Activator.log.error(e);
+				}
+			}
+			return cppFile;
+		}
+		return null;
+	}
+}
diff --git a/plugins/reverse/pom.xml b/plugins/reverse/pom.xml
index f82719e..7cc2426 100644
--- a/plugins/reverse/pom.xml
+++ b/plugins/reverse/pom.xml
@@ -15,6 +15,7 @@
 
 	<modules>
 		<module>org.eclipse.papyrus.robotics.reverse.ros2</module>
+		<module>org.eclipse.papyrus.robotics.cdt.texteditor</module>
 	</modules>
 
 </project>
diff --git a/releng/org.eclipse.papyrus.robotics.feature/feature.xml b/releng/org.eclipse.papyrus.robotics.feature/feature.xml
index 4876fc9..7c49833 100644
--- a/releng/org.eclipse.papyrus.robotics.feature/feature.xml
+++ b/releng/org.eclipse.papyrus.robotics.feature/feature.xml
@@ -24,7 +24,7 @@
       <import feature="org.eclipse.papyrus.sdk.feature" version="3.0.0" match="greaterOrEqual"/>
       <import feature="org.eclipse.papyrus.marte.core.feature" version="1.2.2" match="greaterOrEqual"/>
       <import feature="org.eclipse.papyrus.marte.textedit.feature" version="1.2.2" match="greaterOrEqual"/>
-      <import feature="org.eclipse.papyrus.designer.languages.cpp.feature" version="1.0.5" match="greaterOrEqual"/>
+      <import feature="org.eclipse.papyrus.designer.languages.common.feature" version="1.1.1.qualifier"/>
    </requires>
 
    <plugin
diff --git a/releng/org.eclipse.papyrus.robotics.ros2.feature/feature.xml b/releng/org.eclipse.papyrus.robotics.ros2.feature/feature.xml
index 030122a..ef313e7 100644
--- a/releng/org.eclipse.papyrus.robotics.ros2.feature/feature.xml
+++ b/releng/org.eclipse.papyrus.robotics.ros2.feature/feature.xml
@@ -6,7 +6,8 @@
       provider-name="%providerName">
 
    <description url="https://eclipse.org/papyrus/components/robotics/">
-      This feature provides ROS2 code generation and reverse for Papyrus for Robotics
+      This feature provides ROS2 code generation and reverse for Papyrus
+for Robotics. It also provides the integration of an Eclipse CDT editor.
    </description>
 
    <copyright url="https://www.eclipse.org/legal/epl-2.0/">
@@ -22,6 +23,7 @@
 
    <requires>
       <import feature="org.eclipse.papyrus.robotics.feature" version="0.7.0.qualifier"/>
+      <import feature="org.eclipse.papyrus.designer.languages.cpp.feature" version="1.1.0.qualifier"/>
    </requires>
 
    <plugin
@@ -45,4 +47,11 @@
          version="0.0.0"
          unpack="false"/>
 
+   <plugin
+         id="org.eclipse.papyrus.robotics.cdt.texteditor"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
 </feature>