diff options
author | Ansgar Radermacher | 2016-01-16 23:21:13 +0000 |
---|---|---|
committer | Ansgar Radermacher | 2016-01-17 13:03:01 +0000 |
commit | 36b670f0a9f5dd59422a9f368dfe035d0b5f719c (patch) | |
tree | 7bb419a329ba5c568f5b3062b7661ed0b3e78d46 /extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org | |
parent | 47dd8f8ebd64192956b097cb70f783d7446138ab (diff) | |
download | org.eclipse.papyrus-36b670f0a9f5dd59422a9f368dfe035d0b5f719c.tar.gz org.eclipse.papyrus-36b670f0a9f5dd59422a9f368dfe035d0b5f719c.tar.xz org.eclipse.papyrus-36b670f0a9f5dd59422a9f368dfe035d0b5f719c.zip |
Bug 484701 - [QDesigner] Refactoring - code generators, architecture exploration and component based design should be organised in common directory
Bug 478797 - [model library] Decide which model library to use for C++ primitive types
Change-Id: Idade4edfcf803da3528c0873aa04b754915866fd
Diffstat (limited to 'extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org')
23 files changed, 3432 insertions, 0 deletions
diff --git a/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/Activator.java b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/Activator.java new file mode 100644 index 00000000000..f69ef78e6f2 --- /dev/null +++ b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/Activator.java @@ -0,0 +1,71 @@ +/*****************************************************************************
+ * 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 v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Vincent Lorenzo (CEA LIST) Vincent.Lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.texteditor.cdt;
+
+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.texteditor.cdt"; //$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/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/AddProfileAndModelLibsHandler.java b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/AddProfileAndModelLibsHandler.java new file mode 100644 index 00000000000..fa0e02c1594 --- /dev/null +++ b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/AddProfileAndModelLibsHandler.java @@ -0,0 +1,144 @@ +/*******************************************************************************
+ * 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 v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ansgar Radermacher - ansgar.radermacher@cea.fr CEA LIST - initial API and implementation
+ *
+ *******************************************************************************/
+
+package org.eclipse.papyrus.texteditor.cdt;
+
+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
+ *
+ * @return
+ */
+ 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;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction)
+ */
+ /**
+ * {@inheritDoc}
+ */
+ 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/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/CommandSupport.java b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/CommandSupport.java new file mode 100644 index 00000000000..a3e32434420 --- /dev/null +++ b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/CommandSupport.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * 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 v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ansgar Radermacher - ansgar.radermacher@cea.fr CEA LIST - initial API and implementation + * + *******************************************************************************/ + +package org.eclipse.papyrus.texteditor.cdt; + +import java.util.Collections; + +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.commands.operations.IOperationHistory; +import org.eclipse.core.commands.operations.OperationHistoryFactory; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.emf.transaction.TransactionalEditingDomain; +import org.eclipse.gmf.runtime.common.core.command.CommandResult; +import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand; +import org.eclipse.papyrus.infra.core.services.ServiceException; +import org.eclipse.papyrus.infra.core.utils.ServiceUtilsForActionHandlers; + +/** + * Utility function. Allow execution of commands on a transactional command stack + */ +public class CommandSupport { + + /** + * Execute the passed Runnable within a command + * + * @param label + * @param command + */ + public static void exec(String label, final Runnable command) { + ServiceUtilsForActionHandlers serviceUtils = ServiceUtilsForActionHandlers.getInstance(); + try { + exec(serviceUtils.getTransactionalEditingDomain(), label, command); + } catch (ServiceException e) { + // Log.log(Log.ERROR_MSG, Log.UTILS, "Can not get editing domain"); + } + } + + /** + * Execute the passed Runnable within a command + * + * @param label + * @param command + */ + public static void exec(TransactionalEditingDomain domain, String label, final Runnable command) { + if (domain == null) { + command.run(); + } + else { + IOperationHistory history = OperationHistoryFactory.getOperationHistory(); + try { + history.execute(new AbstractTransactionalCommand(domain, label, Collections.EMPTY_LIST) { + + @Override + public CommandResult doExecuteWithResult(IProgressMonitor dummy, IAdaptable info) { + command.run(); + return CommandResult.newOKCommandResult(); + } + }, null, null); + } catch (ExecutionException e) { + e.printStackTrace(); + } + } + } + +} diff --git a/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/TextEditorConstants.java b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/TextEditorConstants.java new file mode 100644 index 00000000000..2436b7373b5 --- /dev/null +++ b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/TextEditorConstants.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * 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 v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ansgar Radermacher - ansgar.radermacher@cea.fr CEA LIST - initial API and implementation + * + *******************************************************************************/ + +package org.eclipse.papyrus.texteditor.cdt; + +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/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/Utils.java b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/Utils.java new file mode 100644 index 00000000000..2beb89ab936 --- /dev/null +++ b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/Utils.java @@ -0,0 +1,187 @@ +/******************************************************************************* + * 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 v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ansgar Radermacher - ansgar.radermacher@cea.fr CEA LIST - initial API and implementation + * + *******************************************************************************/ + +package org.eclipse.papyrus.texteditor.cdt; + +import org.eclipse.papyrus.codegen.extensionpoints.GenerationConstants; +import org.eclipse.uml2.uml.Element; +import org.eclipse.uml2.uml.NamedElement; +import org.eclipse.uml2.uml.Package; + +/** + * Collection of utility operations that are used by the CDT editor. + */ +public class Utils { + + public static final String nsSep = "::"; //$NON-NLS-1$ + + /** + * Decrease the indentation of a text block. This function is used during synchronization, since + * the code within an opaque behavior is not indented, whereas the code of an operation within a + * file is indented with a tab. + */ + public static String decreaseIndent(char[] contents, int start, int end) { + String newBlock = ""; //$NON-NLS-1$ + boolean newLine = true; + int consume = 0; + for (int i = start; i < end; i++) { + char c = contents[i]; + + // consume either a tab or 4 spaces; + if (newLine && (c == '\t')) { + consume = 1; + } + if (newLine && (c == ' ')) { + consume = 4; + } + + if (consume == 0) { + newBlock += c; + } + else if (c == ' ') { + consume--; + } + else { + consume = 0; + } + if ((c == '\n') || (c == '\r')) { + newLine = true; + } + else { + newLine = false; + } + } + return newBlock; + } + + /** + * Get an element via its qualified name. Will find elements from the root + * model and elements in imported models. Also supports target model in + * which imports have been copied (while keeping the top-level name) + * + * @param root + * @param qualifiedName + * @return + */ + public static NamedElement getQualifiedElement(Package root, + String qualifiedName) { + NamedElement namedElement = null; + int index = qualifiedName.indexOf(nsSep); + if (index != -1) { + // first try using a path without top element (since + // getQualifiedElement is typically used for + // imported elements) + String remainder = qualifiedName.substring(index + 2); + namedElement = getQualifiedElement(root, remainder, qualifiedName); + } + if (namedElement == null) { + // try with complete name as path name, but assume that the element + // has been copied into the model, + // i.e. qualifiedName is prefixed by model name + namedElement = getQualifiedElement(root, qualifiedName, + root.getName() + nsSep + qualifiedName); + } + return namedElement; + } + + /** + * Retrieve an element via its qualified name within a package The segments + * of the package may be non unique due to imports + * + * @return the found element, if it exists + */ + public static NamedElement getQualifiedElement(Package root, + String remainingPath, String qualifiedName) { + if (root == null) { + return null; + } + if (!remainingPath.contains(nsSep)) { + for (NamedElement candidate : root.getMembers()) { + String name = candidate.getName(); + if ((name != null) && name.equals(remainingPath)) { + if (candidate.getQualifiedName().equals(qualifiedName)) { + return candidate; + } + } + } + } else { + String segment = remainingPath.split(nsSep)[0]; + String remainder = remainingPath.substring(segment.length() + 2); + for (Element element : root.getMembers()) { + if (element instanceof Package) { + if (((NamedElement) element).getName().equals(segment)) { + NamedElement foundElement = getQualifiedElement( + (Package) element, remainder, qualifiedName); + // return, if not found + if (foundElement != null) { + return foundElement; + } + } + } + } + } + return null; + } + + /** + * return the top-level owner of an element. This function returns the same + * value as getModel, if the top-level element is a model. While this is the + * case for models, model libraries have a top-level package (not a model). + * In this case, getTop returns the top-level package whereas getModel would + * return null. + * + * @param element + * @return the top-level owning package + */ + public static Package getTop(Element element) { + while (element != null) { + Element owner = element.getOwner(); + if (owner == null) { + if (element instanceof Package) { + return (Package) element; + } + } + element = owner; + } + return null; + } + + /** + * Remove generated code from a body (everything between the GENERATED_START flag + * + * @param bodyStr + * @return + */ + public static String removeGenerated(String bodyStr) { + for (;;) { + int startPos = bodyStr.indexOf(GenerationConstants.GENERATED_START); + if (startPos == -1) { + break; + } + // search line break of previous line (if any) + while ((startPos > 0) && bodyStr.charAt(startPos) != '\r' && bodyStr.charAt(startPos) != '\n') { + startPos--; + } + int endPos = bodyStr.indexOf(GenerationConstants.GENERATED_END, startPos); + if (endPos == -1) { + break; + } + endPos += GenerationConstants.GENERATED_END.length(); + // stop at first non white-space character after comment. + while ((endPos < bodyStr.length()) && Character.isWhitespace(bodyStr.charAt(endPos))) { + endPos++; + } + bodyStr = bodyStr.substring(0, startPos) + bodyStr.substring(endPos); + } + return bodyStr; + } +} diff --git a/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/editor/DelegatingSourceViewer.java b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/editor/DelegatingSourceViewer.java new file mode 100644 index 00000000000..f5d61481370 --- /dev/null +++ b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/editor/DelegatingSourceViewer.java @@ -0,0 +1,400 @@ +/***************************************************************************** + * 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 v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ansgar Radermacher (CEA LIST) Ansgar.Radermacher@cea.fr - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.texteditor.cdt.editor; + +import java.util.Iterator; +import java.util.List; + +import org.eclipse.emf.common.util.BasicEList; +import org.eclipse.jface.text.IAutoIndentStrategy; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IEventConsumer; +import org.eclipse.jface.text.IFindReplaceTarget; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ITextDoubleClickStrategy; +import org.eclipse.jface.text.ITextHover; +import org.eclipse.jface.text.ITextInputListener; +import org.eclipse.jface.text.ITextListener; +import org.eclipse.jface.text.ITextOperationTarget; +import org.eclipse.jface.text.IUndoManager; +import org.eclipse.jface.text.IViewportListener; +import org.eclipse.jface.text.TextPresentation; +import org.eclipse.jface.text.source.Annotation; +import org.eclipse.jface.text.source.IAnnotationHover; +import org.eclipse.jface.text.source.IAnnotationModel; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.SourceViewerConfiguration; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Point; +import org.eclipse.uml2.uml.Classifier; + +/** + * Unsuccessful attempt to create a delegating source viewer that changes the implementation of + * the operation getSelectionProvider of a source viewer. This does not work in case of CDT since the + * source viewer is cast to CSourceViewer later. + * + * CURRENTLY NOT USED + */ +@Deprecated +public class DelegatingSourceViewer implements ISourceViewer { + + public DelegatingSourceViewer(ISourceViewer delegationTarget, Classifier classifier) { + // super(null, null, null, false, 0, null); + this.dt = delegationTarget; + this.cl = classifier; + + sp = new ISelectionProvider() { + + @Override + public void setSelection(ISelection selection) { + } + + @Override + public void removeSelectionChangedListener( + ISelectionChangedListener listener) { + System.err.println("removeSelectionChangedListener"); + } + + @Override + public ISelection getSelection() { + return new IStructuredSelection() { + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public List toList() { + List l = new BasicEList<Object>(); + l.add(cl); + return l; + } + + @Override + public Object[] toArray() { + return new Object[] { cl }; + } + + @Override + public int size() { + // TODO Auto-generated method stub + return 1; + } + + @Override + public Iterator iterator() { + return null; + } + + @Override + public Object getFirstElement() { + return cl; + } + }; + } + + @Override + public void addSelectionChangedListener(ISelectionChangedListener listener) { + // TODO Auto-generated method stub + System.err.println("add SelectionChangedListener"); + + } + }; + } + + ISourceViewer dt; + + Classifier cl; + + ISelectionProvider sp; + + @Override + public StyledText getTextWidget() { + return dt.getTextWidget(); + } + + @Override + public void setUndoManager(IUndoManager undoManager) { + dt.setUndoManager(undoManager); + } + + @Override + public void setTextDoubleClickStrategy( + ITextDoubleClickStrategy strategy, String contentType) { + dt.setTextDoubleClickStrategy(strategy, contentType); + } + + @Override + public void setAutoIndentStrategy(IAutoIndentStrategy strategy, + String contentType) { + dt.setAutoIndentStrategy(strategy, contentType); + } + + @Override + public void setTextHover(ITextHover textViewerHover, + String contentType) { + dt.setTextHover(textViewerHover, contentType); + } + + @Override + public void activatePlugins() { + dt.activatePlugins(); + } + + @Override + public void resetPlugins() { + dt.resetPlugins(); + } + + @Override + public void addViewportListener(IViewportListener listener) { + dt.addViewportListener(listener); + } + + @Override + public void removeViewportListener(IViewportListener listener) { + dt.removeViewportListener(listener); + } + + @Override + public void addTextListener(ITextListener listener) { + dt.addTextListener(listener); + } + + @Override + public void removeTextListener(ITextListener listener) { + dt.removeTextListener(listener); + } + + @Override + public void addTextInputListener(ITextInputListener listener) { + dt.addTextInputListener(listener); + } + + @Override + public void removeTextInputListener(ITextInputListener listener) { + dt.removeTextInputListener(listener); + } + + @Override + public void setDocument(IDocument document) { + dt.setDocument(document); + } + + @Override + public IDocument getDocument() { + return dt.getDocument(); + } + + @Override + public void setEventConsumer(IEventConsumer consumer) { + dt.setEventConsumer(consumer); + + } + + @Override + public void setEditable(boolean editable) { + dt.setEditable(editable); + } + + @Override + public boolean isEditable() { + return dt.isEditable(); + } + + @Override + public void setDocument(IDocument document, int modelRangeOffset, + int modelRangeLength) { + dt.setDocument(document, modelRangeOffset, modelRangeLength); + } + + @Override + public void setVisibleRegion(int offset, int length) { + dt.setVisibleRegion(offset, length); + } + + @Override + public void resetVisibleRegion() { + dt.resetVisibleRegion(); + } + + @Override + public IRegion getVisibleRegion() { + return dt.getVisibleRegion(); + } + + @Override + public boolean overlapsWithVisibleRegion(int offset, int length) { + return dt.overlapsWithVisibleRegion(offset, length); + } + + @Override + public void changeTextPresentation(TextPresentation presentation, + boolean controlRedraw) { + dt.changeTextPresentation(presentation, controlRedraw); + } + + @Override + public void invalidateTextPresentation() { + dt.invalidateTextPresentation(); + + } + + @Override + public void setTextColor(Color color) { + dt.setTextColor(color); + } + + @Override + public void setTextColor(Color color, int offset, int length, + boolean controlRedraw) { + dt.setTextColor(color, offset, length, controlRedraw); + } + + @Override + public ITextOperationTarget getTextOperationTarget() { + return dt.getTextOperationTarget(); + } + + @Override + public IFindReplaceTarget getFindReplaceTarget() { + return dt.getFindReplaceTarget(); + } + + @Override + public void setDefaultPrefixes(String[] defaultPrefixes, + String contentType) { + dt.setDefaultPrefixes(defaultPrefixes, contentType); + + } + + @Override + public void setIndentPrefixes(String[] indentPrefixes, + String contentType) { + dt.setIndentPrefixes(indentPrefixes, contentType); + } + + @Override + public void setSelectedRange(int offset, int length) { + dt.setSelectedRange(offset, length); + } + + @Override + public Point getSelectedRange() { + return dt.getSelectedRange(); + } + + @Override + public ISelectionProvider getSelectionProvider() { + return dt.getSelectionProvider(); + } + + @Override + public void revealRange(int offset, int length) { + dt.revealRange(offset, length); + } + + @Override + public void setTopIndex(int index) { + dt.setTopIndex(index); + } + + @Override + public int getTopIndex() { + return dt.getTopIndex(); + } + + @Override + public int getTopIndexStartOffset() { + return dt.getTopIndexStartOffset(); + } + + @Override + public int getBottomIndex() { + return dt.getBottomIndex(); + } + + @Override + public int getBottomIndexEndOffset() { + return dt.getBottomIndexEndOffset(); + } + + @Override + public int getTopInset() { + return dt.getTopInset(); + } + + @Override + public void configure(SourceViewerConfiguration configuration) { + dt.configure(configuration); + } + + @Override + public void setAnnotationHover(IAnnotationHover annotationHover) { + dt.setAnnotationHover(annotationHover); + } + + @Override + public void setDocument(IDocument document, + IAnnotationModel annotationModel) { + dt.setDocument(document, annotationModel); + } + + @Override + public void setDocument(IDocument document, + IAnnotationModel annotationModel, int modelRangeOffset, + int modelRangeLength) { + dt.setDocument(document, annotationModel, modelRangeOffset, modelRangeLength); + + } + + @Override + public IAnnotationModel getAnnotationModel() { + return dt.getAnnotationModel(); + } + + @Override + public void setRangeIndicator(Annotation rangeIndicator) { + dt.setRangeIndicator(rangeIndicator); + + } + + @Override + public void setRangeIndication(int offset, int length, + boolean moveCursor) { + dt.setRangeIndication(offset, length, moveCursor); + } + + @Override + public IRegion getRangeIndication() { + return dt.getRangeIndication(); + } + + @Override + public void removeRangeIndication() { + dt.removeRangeIndication(); + } + + @Override + public void showAnnotations(boolean show) { + dt.showAnnotations(show); + } +} diff --git a/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/editor/PapyrusCDTEditor.java b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/editor/PapyrusCDTEditor.java new file mode 100644 index 00000000000..4ae37530cac --- /dev/null +++ b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/editor/PapyrusCDTEditor.java @@ -0,0 +1,395 @@ +/*****************************************************************************
+ * 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 v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ansgar Radermacher (CEA LIST) Ansgar.Radermacher@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.texteditor.cdt.editor;
+
+import org.eclipse.cdt.codan.internal.ui.cxx.CodanCReconciler;
+import org.eclipse.cdt.core.model.ICElement;
+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.internal.ui.editor.CEditor;
+import org.eclipse.cdt.ui.CDTUITools;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.emf.common.notify.Adapter;
+import org.eclipse.emf.common.notify.Notification;
+import org.eclipse.emf.common.notify.Notifier;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EValidator;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.text.source.IVerticalRuler;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.papyrus.infra.core.lifecycleevents.DoSaveEvent;
+import org.eclipse.papyrus.infra.core.lifecycleevents.ILifeCycleEventsProvider;
+import org.eclipse.papyrus.infra.core.lifecycleevents.ISaveAndDirtyService;
+import org.eclipse.papyrus.infra.core.lifecycleevents.ISaveEventListener;
+import org.eclipse.papyrus.infra.core.services.ServiceException;
+import org.eclipse.papyrus.infra.core.services.ServicesRegistry;
+import org.eclipse.papyrus.texteditor.cdt.Activator;
+import org.eclipse.papyrus.texteditor.cdt.sync.ObtainICElement;
+import org.eclipse.papyrus.texteditor.cdt.sync.RevealCurrentOperation;
+import org.eclipse.papyrus.texteditor.cdt.sync.SyncCDTtoModel;
+import org.eclipse.papyrus.texteditor.cdt.sync.SyncModelToCDT;
+import org.eclipse.papyrus.texteditor.model.texteditormodel.TextEditorModel;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.ide.IGotoMarker;
+import org.eclipse.ui.part.FileEditorInput;
+import org.eclipse.ui.texteditor.ITextEditorActionConstants;
+import org.eclipse.uml2.uml.Classifier;
+import org.eclipse.uml2.uml.Element;
+import org.eclipse.uml2.uml.NamedElement;
+
+/**
+ * A specialization of the CDT editor made for integration into Papyrus
+ *
+ */
+public class PapyrusCDTEditor extends CEditor {
+
+ /** the service registry */
+ protected final ServicesRegistry registry;
+
+ /** the papyrus text instance */
+ protected final TextEditorModel papyrusTextInstance;
+
+ /** the text listener */
+ protected FocusListener focusListener;
+
+ public static final String EDITOR_DEFAULT_NAME = "CDT Editor";
+
+ public static final String EDITOR_TYPE = "CDTEditorInPapyrus"; //$NON-NLS-1$
+
+ protected SyncCDTtoModel syncCpp;
+
+ protected RevealCurrentOperation reveal;
+
+ protected Adapter gotoListener;
+
+ /**
+ *
+ * Constructor.
+ *
+ * @param registry
+ * @param papyrusTextInstance
+ */
+ public PapyrusCDTEditor(final ServicesRegistry registry, final TextEditorModel papyrusTextInstance) {
+ super();
+ gotoListener = null;
+ this.registry = registry;
+ this.papyrusTextInstance = papyrusTextInstance;
+ try {
+ saveAndDirtyService = registry.getService(ISaveAndDirtyService.class);
+ saveAndDirtyService.registerIsaveablePart(this);
+ ILifeCycleEventsProvider lifeCycleEvents = registry.getService(ILifeCycleEventsProvider.class);
+ ISaveEventListener preSaveEvent = new ISaveEventListener() {
+
+ @Override
+ public void doSaveAs(DoSaveEvent event) {
+ // TODO Auto-generated method stub
+ }
+
+ @Override
+ public void doSave(DoSaveEvent event) {
+ syncCpp.syncCDTtoModel();
+ }
+ };
+ lifeCycleEvents.addAboutToDoSaveListener(preSaveEvent);
+ } catch (ServiceException e) {
+ Activator.log.error(e);
+ }
+ }
+
+ /**
+ * override method in order to save & restore action bars entries
+ */
+ @Override
+ public void createPartControl(Composite parent) {
+ // save Papyrus (GMF) handlers
+ IActionBars actionBars = getEditorSite().getActionBars();
+ if ((actionBars != null) && (gmfUndo == null)) {
+ gmfUndo = actionBars.getGlobalActionHandler(ITextEditorActionConstants.UNDO);
+ gmfRedo = actionBars.getGlobalActionHandler(ITextEditorActionConstants.REDO);
+ }
+
+ super.createPartControl(parent);
+
+ if (actionBars != null) {
+ // save CDT (textEditor) handlers
+ textUndo = actionBars.getGlobalActionHandler(ITextEditorActionConstants.UNDO);
+ textRedo = actionBars.getGlobalActionHandler(ITextEditorActionConstants.REDO);
+ // & restore Papyrus bar
+ actionBars.setGlobalActionHandler(ITextEditorActionConstants.UNDO, gmfUndo);
+ actionBars.setGlobalActionHandler(ITextEditorActionConstants.REDO, gmfRedo);
+ actionBars.updateActionBars();
+ }
+
+ gotoListener = new Adapter() {
+
+ // assure that gotoElement is called, if the element in the model gets updated
+ @Override
+ public void notifyChanged(Notification notification) {
+ if (notification.getEventType() == Notification.SET) {
+ Object newValue = notification.getNewValue();
+ if (newValue instanceof NamedElement) {
+ gotoElement((NamedElement) newValue);
+ }
+
+ }
+ }
+
+ @Override
+ public Notifier getTarget() {
+ return null;
+ }
+
+ @Override
+ public void setTarget(Notifier newTarget) {
+ }
+
+ @Override
+ public boolean isAdapterForType(Object type) {
+ return false;
+ }
+ };
+ papyrusTextInstance.eAdapters().add(gotoListener);
+
+ if (papyrusTextInstance.getSelectedObject() instanceof NamedElement) {
+ gotoElement((NamedElement) papyrusTextInstance.getSelectedObject());
+ }
+ }
+
+ /**
+ *
+ * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#createSourceViewer(org.eclipse.swt.widgets.Composite, org.eclipse.jface.text.source.IVerticalRuler, int)
+ *
+ * @param parent
+ * @param ruler
+ * @param styles
+ * @return
+ */
+ @Override
+ public ISourceViewer createSourceViewer(Composite parent, IVerticalRuler ruler, int styles) {
+
+ final ISourceViewer viewer = super.createSourceViewer(parent, ruler, styles);
+ // ISourceViewer viewer = new DelegatingSourceViewer(origViewer, (Classifier)papyrusTextInstance.getEditedObject());
+ focusListener = new FocusListener() {
+
+ @Override
+ public void focusLost(FocusEvent e) {
+ // potential problem for undo/redo!!
+ if (isDirty()) {
+ doSave(new NullProgressMonitor());
+ syncCpp.syncCDTtoModel();
+ Classifier classifier = (Classifier) papyrusTextInstance.getEditedObject();
+ // regenerate code. TODO: raises update dialog
+ // SyncModelToCDT.syncModelToCDT(classifier);
+ }
+ // restore handlers
+ IActionBars actionBars = getEditorSite().getActionBars();
+ if (actionBars != null) {
+ if ((gmfUndo != null) && (gmfRedo != null)) {
+ actionBars.setGlobalActionHandler(ITextEditorActionConstants.UNDO, gmfUndo);
+ actionBars.setGlobalActionHandler(ITextEditorActionConstants.REDO, gmfRedo);
+ actionBars.updateActionBars();
+ }
+ }
+ }
+
+ @Override
+ public void focusGained(FocusEvent e) {
+ // restore handlers
+ IActionBars actionBars = getEditorSite().getActionBars();
+ if (actionBars != null) {
+ if ((textUndo != null) && (textRedo != null)) {
+ actionBars.setGlobalActionHandler(ITextEditorActionConstants.UNDO, textUndo);
+ actionBars.setGlobalActionHandler(ITextEditorActionConstants.REDO, textRedo);
+ actionBars.updateActionBars();
+ }
+ }
+ }
+ };
+ // register focus listener
+ viewer.getTextWidget().addFocusListener(focusListener);
+ SelectionListener selectionListener = new SelectionListener() {
+
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ IEditorPart ep = getEditorSite().getPage().getActiveEditor();
+ ISelection selection = getSelectionProvider().getSelection();
+ if ((ep instanceof IGotoMarker) && (selection instanceof ITextSelection)) {
+ if (((ITextSelection) selection).getLength() > 0) {
+ // don't try to navigate during selection of a chunk of text.
+ return;
+ }
+ IMarker marker;
+ /*
+ * create a temporary validation marker on the
+ * srcFile file, call the gotoMarker operation of the editor
+ * and remove the marker afterwards.
+ * TODO: operation activates the model-explorer
+ */
+ try {
+ Element element = reveal.obtainSelectedElement((ITextSelection) selection);
+ String modelURI = EcoreUtil.getURI(element).toString();
+ marker = srcFile.createMarker(EValidator.MARKER);
+ marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_INFO); // set severity before URI to avoid marker update without associated icon
+ marker.setAttribute(EValidator.URI_ATTRIBUTE, modelURI);
+ IWorkbenchPage wbpage = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+ IWorkbenchPart activePart = wbpage.getActivePart();
+ ((IGotoMarker) ep).gotoMarker(marker);
+ // reactivate this editor
+ wbpage.activate(activePart);
+ marker.delete();
+ } catch (CoreException e1) {
+ // TODO Auto-generated catch block
+ e1.printStackTrace();
+ }
+ }
+ }
+
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ };
+
+ // TODO: don't add selection listener for the moment. It can cause deadlocks (setting a marker attribute while file is locked, reproducible with cut (^X) on selection)
+ // viewer.getTextWidget().addSelectionListener(selectionListener);
+
+ return viewer;
+ }
+
+ /**
+ * Goto a specific element within the text editor. Currently, only methods are supported.
+ *
+ * @param element
+ * @throws CoreException
+ */
+ public void gotoElement(NamedElement element) {
+ ICElement ice = CDTUITools.getEditorInputCElement(m_input);
+
+ if (ice instanceof ITranslationUnit) {
+ ITranslationUnit itu = (ITranslationUnit) ice;
+ ICElement icElement = ObtainICElement.getICElement(syncCpp.getCodeGen(), itu, element);
+ if (icElement instanceof ISourceReference) {
+ try {
+ ISourceRange range = ((ISourceReference) icElement).getSourceRange();
+
+ ISourceViewer viewer = getSourceViewer();
+ viewer.revealRange(range.getStartPos(), 1);
+ viewer.setSelectedRange(range.getStartPos(), range.getLength());
+ return;
+ } catch (CoreException e) {
+ Activator.log.error(e);
+ }
+ }
+ }
+ }
+
+ @Override
+ public boolean isDirty() {
+ boolean isDirty = super.isDirty();
+ if (isDirty != oldDirty) {
+ oldDirty = isDirty;
+ // hack. Normally, the saveAndDirtyService detects this itself (should find a solution how it can do that)
+ // ((SaveAndDirtyService) saveAndDirtyService).fireIsDirtyChanged();
+ }
+ return isDirty;
+ }
+
+ /**
+ * We override this method because setInput can't be overriden for TextEditor.
+ * We replace the default Papyrus input with the CPP file
+ *
+ * @see org.eclipse.ui.editors.text.TextEditor#doSetInput(org.eclipse.ui.IEditorInput)
+ *
+ * @param input
+ * @throws CoreException
+ */
+ @Override
+ protected void doSetInput(IEditorInput input) throws CoreException {
+
+ URI uri = papyrusTextInstance.eResource().getURI();
+ Classifier classifier = (Classifier) papyrusTextInstance.getEditedObject();
+ String generatorID = papyrusTextInstance.getGeneratorID();
+ srcFile = SyncModelToCDT.syncModelToCDT(classifier, generatorID);
+ if (srcFile == null || !srcFile.exists()) {
+ throw new PartInitException("Code generation before editing failed. Please check error log");
+ }
+ IEditorInput newInput = new FileEditorInput(srcFile);
+
+ // IStorage storage = new TextStorage(string);
+ super.doSetInput(newInput);
+
+ syncCpp = new SyncCDTtoModel(newInput, classifier, uri.segment(1), generatorID);
+ m_input = newInput;
+ reveal = new RevealCurrentOperation(newInput, classifier, uri.segment(1));
+
+ // add the reconciler to get syntax check and completion. (still no full checks)
+ addReconcileListener(new CodanCReconciler());
+ }
+
+ /**
+ *
+ * @see org.eclipse.ui.editors.text.TextEditor#dispose()
+ *
+ */
+ @Override
+ public void dispose() {
+
+ saveAndDirtyService.removeIsaveablePart(this);
+ if (gotoListener != null) {
+ papyrusTextInstance.eAdapters().remove(gotoListener);
+ }
+
+ // we remove the listener
+ StyledText st = getSourceViewer().getTextWidget();
+ st.removeFocusListener(focusListener);
+ super.dispose();
+ // assure that embedded text widget is disposed now. Otherwise, it will be closed
+ // later, when the editorSite is already set to null by Papyrus (mainEditorSite attribute in MultiPageEditorSite4x)
+ // resulting in a null pointer exception and resulting inconsistencies in the Papyrus editor.
+ st.dispose();
+ }
+
+ protected IAction gmfUndo, gmfRedo;
+
+ protected IAction textUndo, textRedo;
+
+ protected boolean oldDirty;
+
+ protected ISaveAndDirtyService saveAndDirtyService;
+
+ protected IFile srcFile;
+
+ protected ISelectionProvider sp;
+
+ protected IEditorInput m_input;
+}
diff --git a/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/factory/PapyrusCDTEditorFactory.java b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/factory/PapyrusCDTEditorFactory.java new file mode 100644 index 00000000000..f4f552858e7 --- /dev/null +++ b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/factory/PapyrusCDTEditorFactory.java @@ -0,0 +1,210 @@ +/*****************************************************************************
+ * Copyright (c) 2013, 2014 CEA LIST 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:
+ * Vincent Lorenzo (CEA LIST) Vincent.Lorenzo@cea.fr - Initial API and implementation
+ * Ansgar Radermacher (CEA LIST) - Minor adaptations
+ * Christian W. Damus (CEA) - bug 392301
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.texteditor.cdt.factory;
+
+import org.eclipse.papyrus.infra.core.editor.BackboneException;
+import org.eclipse.papyrus.infra.core.extension.diagrameditor.AbstractEditorFactory;
+import org.eclipse.papyrus.infra.core.multidiagram.actionbarcontributor.ActionBarContributorRegistry;
+import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IEditorModel;
+import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IPageModel;
+import org.eclipse.papyrus.infra.core.services.ServiceException;
+import org.eclipse.papyrus.texteditor.cdt.Activator;
+import org.eclipse.papyrus.texteditor.cdt.editor.PapyrusCDTEditor;
+import org.eclipse.papyrus.texteditor.model.texteditormodel.TextEditorModel;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.part.EditorActionBarContributor;
+
+
+public class PapyrusCDTEditorFactory extends AbstractEditorFactory {
+
+ /**
+ * Constructor.
+ */
+ public PapyrusCDTEditorFactory() {
+ super(PapyrusCDTEditor.class, PapyrusCDTEditor.EDITOR_TYPE);
+ }
+
+ /**
+ * Create the IPageModel that is used by the SashWindows to manage the editor.
+ *
+ * @see org.eclipse.papyrus.infra.core.editorsfactory.IEditorFactory#createIPageModel(java.lang.Object)
+ *
+ * @param pageIdentifier
+ * The model pushed in the sashmodel by the creation command
+ * @return A model implementing the IPageModel
+ */
+ @Override
+ public IPageModel createIPageModel(Object pageIdentifier) {
+ return new TextEditorModelDelegate(pageIdentifier);
+ }
+
+ /**
+ * @see org.eclipse.papyrus.infra.core.editorsfactory.IEditorFactory#isPageModelFactoryFor(java.lang.Object)
+ *
+ * @param pageIdentifier
+ * @return
+ */
+ @Override
+ public boolean isPageModelFactoryFor(Object pageIdentifier) {
+ if (pageIdentifier instanceof TextEditorModel) {
+ return ((TextEditorModel) pageIdentifier).getType().equals(this.getExpectedType());
+ }
+ return false;
+ }
+
+ /**
+ * IEditorModel used internally by the SashContainer. This model know how to handle IEditor creation.
+ *
+ */
+ class TextEditorModelDelegate implements IEditorModel {
+
+ /**
+ * The created editor.
+ */
+ private IEditorPart editor;
+
+ /**
+ * The raw model stored in the SashProvider.
+ */
+ private TextEditorModel rawEditorModel;
+
+ /**
+ *
+ * Constructor.
+ */
+ public TextEditorModelDelegate(Object pageIdentifier) {
+ rawEditorModel = (TextEditorModel) pageIdentifier;
+ }
+
+ /**
+ * Create the IEditor for the diagram.
+ *
+ * @see org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IEditorModel#createIEditorPart()
+ * @return
+ * @throws PartInitException
+ *
+ */
+ @Override
+ public IEditorPart createIEditorPart() throws PartInitException {
+ try {
+ // we use this way when there is one factory for several editor types
+ // Constructor<?> c = getDiagramClass().getConstructor(ServicesRegistry.class, TextEditorModel.class);
+ // editor = (IEditorPart)c.newInstance(servicesRegistry, rawModel);
+
+ // we use this way when there is only one editor type
+ editor = new PapyrusCDTEditor(getServiceRegistry(), rawEditorModel);
+ return editor;
+
+ } catch (Exception e) {
+ // Lets propagate. This is an implementation problem that should be solved by
+ // programmer.
+ throw new PartInitException("Can't create TextEditor", e);
+ }
+
+ }
+
+ /**
+ * Get the action bar requested by the Editor.
+ *
+ * @see org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IEditorModel#getActionBarContributor()
+ * @return
+ *
+ */
+ @Override
+ public EditorActionBarContributor getActionBarContributor() {
+
+ String actionBarId = editorDescriptor.getActionBarContributorId();
+
+ // Do nothing if no EditorActionBarContributor is specify.
+ if (actionBarId == null || actionBarId.length() == 0) {
+ return null;
+ }
+
+ // Try to get it.
+
+ // Get ServiceRegistry
+ // ServicesRegistry serviceRegistry = getServicesRegistry();
+ ActionBarContributorRegistry registry;
+ try {
+ registry = getServiceRegistry().getService(ActionBarContributorRegistry.class);
+ } catch (ServiceException e) {
+ // Service not found
+ Activator.log.error(e);
+ return null;
+ }
+
+ try {
+ return registry.getActionBarContributor(actionBarId);
+ } catch (BackboneException e) {
+ Activator.log.error(e);
+ return null;
+ }
+ }
+
+ /**
+ * Get the underlying RawModel. Return the TextEditor (normally returns a diagram)
+ *
+ * @see org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IPageModel#getRawModel()
+ * @return
+ *
+ */
+ @Override
+ public Object getRawModel() {
+ return rawEditorModel;
+ }
+
+ /**
+ * Get the icon to be shown by Tabs
+ *
+ * @see org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IPageModel#getTabIcon()
+ * @return
+ *
+ */
+ @Override
+ public Image getTabIcon() {
+ org.eclipse.papyrus.infra.widgets.Activator widgetsActivator =
+ org.eclipse.papyrus.infra.widgets.Activator.getDefault();
+ if (widgetsActivator == null) {
+ return null;
+ }
+ String path = getEditorDescriptor().getIconURL();
+ if (path.startsWith(Activator.PLUGIN_ID)) {
+ // remove PLUGIN-ID prefix from the path (since the image will be searched relative to plugin)
+ path = path.substring(Activator.PLUGIN_ID.length());
+ }
+ return widgetsActivator.getImage(Activator.PLUGIN_ID, path);
+ }
+
+ /**
+ * Get the title of the Diagram.
+ *
+ * @see org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IPageModel#getTabTitle()
+ * @return
+ *
+ */
+ @Override
+ public String getTabTitle() {
+ return rawEditorModel.getName();
+ }
+
+ @Override
+ public void dispose() {
+ // Pass. The tab icon is a plugin-shared image
+ }
+ }
+}
diff --git a/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/handler/PapyrusCDTEditorHandler.java b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/handler/PapyrusCDTEditorHandler.java new file mode 100644 index 00000000000..7d6df1edfc4 --- /dev/null +++ b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/handler/PapyrusCDTEditorHandler.java @@ -0,0 +1,308 @@ +/*****************************************************************************
+ * 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 v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Vincent Lorenzo (CEA LIST) Vincent.Lorenzo@cea.fr - Initial API and implementation
+ * Ansgar Radermacher (CEA LIST) ansgar.radermacher@cea.fr
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.texteditor.cdt.handler;
+
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+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.codegen.extensionpoints.ILangCodegen;
+import org.eclipse.papyrus.codegen.extensionpoints.LanguageCodegen;
+import org.eclipse.papyrus.commands.CheckedOperationHistory;
+import org.eclipse.papyrus.infra.core.resource.NotFoundException;
+import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IPageManager;
+import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.ISashWindowsContentProvider;
+import org.eclipse.papyrus.infra.core.sasheditor.di.contentprovider.DiSashModelManager;
+import org.eclipse.papyrus.infra.core.sasheditor.editor.ISashWindowsContainer;
+import org.eclipse.papyrus.infra.core.sashwindows.di.PageRef;
+import org.eclipse.papyrus.infra.core.sashwindows.di.SashPanel;
+import org.eclipse.papyrus.infra.core.sashwindows.di.TabFolder;
+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.utils.ServiceUtilsForHandlers;
+import org.eclipse.papyrus.texteditor.cdt.Activator;
+import org.eclipse.papyrus.texteditor.cdt.TextEditorConstants;
+import org.eclipse.papyrus.texteditor.cdt.editor.PapyrusCDTEditor;
+import org.eclipse.papyrus.texteditor.cdt.modelresource.TextEditorModelSharedResource;
+import org.eclipse.papyrus.texteditor.model.texteditormodel.TextEditorModel;
+import org.eclipse.papyrus.texteditor.model.texteditormodel.TextEditorModelFactory;
+import org.eclipse.papyrus.uml.diagram.common.handlers.CmdHandler;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.uml2.uml.Behavior;
+import org.eclipse.uml2.uml.Class;
+import org.eclipse.uml2.uml.Classifier;
+import org.eclipse.uml2.uml.Element;
+import org.eclipse.uml2.uml.Operation;
+import org.eclipse.uml2.uml.Transition;
+import org.eclipse.uml2.uml.UMLPackage;
+
+
+/**
+ * The handler creates a new CDT editor
+ */
+public class PapyrusCDTEditorHandler extends CmdHandler {
+
+
+ public PapyrusCDTEditorHandler() {
+ }
+
+ /**
+ *
+ * @see org.eclipse.infra.core.commands.AbstractHandler#isEnabled()
+ *
+ * @return
+ */
+ @Override
+ public boolean isEnabled() {
+ updateSelectedEObject();
+ // Filter Classes (including Behaviors, since Behavior inherits from Class), Operation and Transition
+ if (selectedEObject instanceof Class ||
+ selectedEObject instanceof Operation ||
+ selectedEObject instanceof Transition)
+ {
+ URI uri = selectedEObject.eResource().getURI();
+
+ // URIConverter uriConverter = resource.getResourceSet().getURIConverter();
+ IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+ if (uri.segmentCount() < 2) {
+ return false;
+ }
+ IProject modelProject = root.getProject(uri.segment(1));
+ return modelProject.exists();
+ }
+ return false;
+ }
+
+ /**
+ * @see org.eclipse.infra.core.commands.IHandler#execute(org.eclipse.infra.core.commands.ExecutionEvent)
+ *
+ * @param event
+ * @return
+ * @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") {
+
+ @Override
+ protected IStatus doExecute(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException {
+ try {
+ PapyrusCDTEditorHandler.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);
+ } catch (ServiceException e) {
+ Activator.log.error("Service exception during creation of CDT editor", e);
+ }
+ return null;
+ }
+
+
+ /**
+ * Do the execution of the command.
+ *
+ * @param serviceRegistry
+ * @throws ServiceException
+ * @throws NotFoundException
+ */
+ public void doExecute(final ServicesRegistry serviceRegistry) throws ServiceException, NotFoundException {
+ // Get the page manager allowing to add/open an editor.
+ final IPageManager pageMngr = ServiceUtils.getInstance().getIPageManager(serviceRegistry);
+
+ Classifier classifierToEdit = getClassifierToEdit();
+ TextEditorModel editorModel = getEditorModel(serviceRegistry, classifierToEdit);
+ if (editorModel == null) {
+ // no editor exist for the given file => create
+ editorModel = createEditorModel(serviceRegistry, classifierToEdit);
+ if (editorModel == null) {
+ return;
+ }
+ }
+ ILangCodegen codegen = LanguageCodegen.getGenerator(TextEditorConstants.CPP, editorModel.getGeneratorID());
+
+ if (codegen.getTargetProject(classifierToEdit, true) == null) {
+ return;
+ }
+
+ if (selectedEObject instanceof Transition) {
+ Transition transition = (Transition) selectedEObject;
+ if (transition.getEffect() == null) {
+ Behavior effect = transition.createEffect("effectOf" + transition.getName(), UMLPackage.eINSTANCE.getOpaqueBehavior()); //$NON-NLS-1$
+ }
+ }
+ // add the new editor model to the sash.
+ editorModel.setSelectedObject(selectedEObject);
+
+ final TextEditorModel editorModelFinal = editorModel;
+ // open asynchronously to prevent handler cycles, see bug 434484
+ Display.getDefault().asyncExec(new Runnable() {
+
+ @Override
+ public void run() {
+ if (pageMngr.isOpen(editorModelFinal)) {
+ // select existing editor
+ pageMngr.selectPage(editorModelFinal);
+ }
+ else {
+ pageMngr.openPage(editorModelFinal);
+ }
+ try {
+ // move page to the RIGHT
+ DiSashModelManager modelMngr = ServiceUtils.getInstance().getService(DiSashModelManager.class, serviceRegistry);
+ ISashWindowsContentProvider sashContentProvider = modelMngr.getISashWindowsContentProvider();
+ Object rootModel = sashContentProvider.getRootModel();
+
+ if (rootModel instanceof TabFolder) {
+ // root = tabFolder, i.e. there is a single folder
+ ISashWindowsContainer sashContainer = ServiceUtils.getInstance().getISashWindowsContainer(serviceRegistry);
+ int index = lookupIndex((TabFolder) rootModel, editorModelFinal);
+ if (index != -1) {
+ sashContentProvider.createFolder(sashContainer.getSelectedTabFolderModel(), index, sashContainer.getSelectedTabFolderModel(), SWT.RIGHT);
+ }
+ }
+ else if (rootModel instanceof SashPanel) {
+ // multiple tab-folders exist. Find existing one and move editorModel to other
+ // TODO
+ // ISashWindowsContainer sashContainer = ServiceUtils.getInstance().getISashWindowsContainer(serviceRegistry);
+ // sashContentProvider.movePage(sashContainer.getSelectedTabFolderModel(), lookupIndex(sourceTab, editorModel), targetTabModel, -1);
+ }
+ } catch (ServiceException e) {
+
+ }
+ }
+
+ });
+
+ }
+
+ /**
+ * Create a model identifying the editor. This model will be saved with the sash
+ *
+ * @return
+ * @throws ServiceException
+ * @throws NotFoundException
+ * The model where to save the TableInstance is not found.
+ */
+ protected TextEditorModel createEditorModel(final ServicesRegistry serviceRegistry, Classifier classifierToEdit) throws ServiceException, NotFoundException {
+ TextEditorModel editorModel = TextEditorModelFactory.eINSTANCE.createTextEditorModel();
+
+ editorModel.setEditedObject(classifierToEdit);
+ editorModel.setType(PapyrusCDTEditor.EDITOR_TYPE);
+ editorModel.setName("CDT " + classifierToEdit.getName()); //$NON-NLS-1$
+ ILangCodegen codegen = LanguageCodegen.chooseGenerator(TextEditorConstants.CPP, classifierToEdit);
+ if (codegen == null) {
+ return null;
+ }
+ editorModel.setGeneratorID(LanguageCodegen.getID(codegen));
+ TextEditorModelSharedResource model = (TextEditorModelSharedResource)
+ ServiceUtils.getInstance().getModelSet(serviceRegistry).getModelChecked(TextEditorModelSharedResource.MODEL_ID);
+ model.addTextEditorModel(editorModel);
+
+ return editorModel;
+ }
+
+ /**
+ * The classifier to edit - corresponding to the selected object.
+ *
+ * @return
+ */
+ protected Classifier getClassifierToEdit() {
+ if (selectedEObject instanceof Operation) {
+ return ((Operation) selectedEObject).getFeaturingClassifiers().get(0);
+ }
+ else if (selectedEObject instanceof Transition) {
+ return ((Transition) selectedEObject).getContainer().getStateMachine().getContext();
+ }
+ else if (selectedEObject instanceof Behavior) {
+ Element owner = (Behavior) selectedEObject;
+ while (owner != null) {
+ owner = owner.getOwner();
+ if ((owner instanceof Classifier) && !(owner instanceof Behavior)) {
+ return (Classifier) owner;
+ }
+ }
+ return null;
+ }
+ else if (selectedEObject instanceof Classifier) {
+ // must be class or datatype
+ return (Classifier) selectedEObject;
+ }
+ return null;
+ }
+
+ /**
+ * return the editor model corresponding to an EObject
+ *
+ * @param serviceRegistry
+ * the service registry
+ * @param classifierToEdit
+ * The classifier for which a CDT editor should be opened
+ * @return
+ * @throws ServiceException
+ * @throws NotFoundException
+ */
+ protected TextEditorModel getEditorModel(final ServicesRegistry serviceRegistry, Classifier classifierToEdit) throws ServiceException, NotFoundException {
+ TextEditorModelSharedResource model = (TextEditorModelSharedResource)
+ ServiceUtils.getInstance().getModelSet(serviceRegistry).getModelChecked(TextEditorModelSharedResource.MODEL_ID);
+ return model.getTextEditorModel(classifierToEdit);
+ }
+
+ /**
+ * Recursively search in sash models for a FolderModel.
+ * Return the first encountered folder.
+ *
+ * @param panelModel
+ * @return
+ */
+ public static int lookupIndex(TabFolder folder, Object model) {
+
+ int index = 0;
+ for (PageRef pr : folder.getChildren()) {
+ if (pr.getPageIdentifier() == model) {
+ return index;
+ }
+ index++;
+ }
+ return -1;
+ }
+}
diff --git a/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/listener/ChangeKind.java b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/listener/ChangeKind.java new file mode 100644 index 00000000000..c6e407ed35f --- /dev/null +++ b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/listener/ChangeKind.java @@ -0,0 +1,7 @@ +package org.eclipse.papyrus.texteditor.cdt.listener; + +public enum ChangeKind { + INTERFACE, + IMPLEMENTATION, + OPERATION +}; diff --git a/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/listener/Closure.java b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/listener/Closure.java new file mode 100644 index 00000000000..b81203d94bc --- /dev/null +++ b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/listener/Closure.java @@ -0,0 +1,81 @@ +/***************************************************************************** + * 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 v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ansgar Radermacher (CEA LIST) Ansgar.Radermacher@cea.fr - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.texteditor.cdt.listener; + +import org.eclipse.emf.common.util.BasicEList; +import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EStructuralFeature.Setting; +import org.eclipse.uml2.common.util.UML2Util; +import org.eclipse.uml2.uml.Association; +import org.eclipse.uml2.uml.Classifier; +import org.eclipse.uml2.uml.Element; + +/** + * Calculate the closure of classifiers that need to be re-generated, if a + * classifier changes + * + * There are two different reasons for the need to re-generate a classifier: + * (1) one of the elements that it contains has changed + * (2) an element outside the containment close is changed. An example is a superclass + * that changes its name or an association target. In many cases, classifier depend + * on names of outside elements, but the also require a regeneration if the element + * is deleted. + * We need to take the change-kind into account. E.g. if the name of an operation in A changes, we need to + * re-generate class A, but we only need to regenerate class B (inheriting from A), if it actually + * redefines that operation. + */ +public class Closure { + public static EList<Classifier> calc(Classifier cl) { + EList<Classifier> list = new BasicEList<Classifier>(); + calc(cl, list); + return list; + } + + public static void calc(Classifier cl, EList<Classifier> list) { + if (cl != null) { + for (Setting setting : UML2Util.getNonNavigableInverseReferences(cl)) { + EObject eObj = setting.getEObject(); + if (eObj instanceof Element) { + Classifier referencedCl = nearestClassifier(eObj); + if (!list.contains(referencedCl) && (!(referencedCl instanceof Association))) { + list.add(referencedCl); + calc(referencedCl, list); + } + } + } + } + } + + public static boolean isContained(EObject parent, EObject possibleChild) { + while (possibleChild != null) { + if (parent == possibleChild) { + return true; + } + possibleChild = possibleChild.eContainer(); + } + return false; + } + + public static Classifier nearestClassifier(EObject eObj) { + while (eObj != null) { + if (eObj instanceof Classifier) { + return (Classifier) eObj; + } + eObj = eObj.eContainer(); + } + return null; + } +} diff --git a/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/listener/ModelListener.java b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/listener/ModelListener.java new file mode 100644 index 00000000000..18bc74c536e --- /dev/null +++ b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/listener/ModelListener.java @@ -0,0 +1,135 @@ +/***************************************************************************** + * 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 v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ansgar Radermacher (CEA LIST) Ansgar.Radermacher@cea.fr - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.texteditor.cdt.listener; + +import org.eclipse.emf.common.notify.Notification; +import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.common.util.UniqueEList; +import org.eclipse.papyrus.infra.core.listenerservice.IPapyrusListener; +import org.eclipse.papyrus.uml.tools.listeners.PapyrusStereotypeListener; +import org.eclipse.uml2.uml.Behavior; +import org.eclipse.uml2.uml.Classifier; +import org.eclipse.uml2.uml.DirectedRelationship; +import org.eclipse.uml2.uml.Element; +import org.eclipse.uml2.uml.Feature; +import org.eclipse.uml2.uml.Package; +import org.eclipse.uml2.uml.Parameter; + +/** + * 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 + * + * @author ansgar + * + */ +public class ModelListener implements IPapyrusListener { + + /** + * set to true, if a synchronization from an CDT editor to the model is active + */ + public static boolean syncFromEditor; + + @Override + public void notifyChanged(Notification notification) { + Object notifier = notification.getNotifier(); + int eventType = notification.getEventType(); + if (syncFromEditor) { + return; + } + if ((eventType == Notification.REMOVING_ADAPTER) || + (eventType == Notification.RESOLVE)) { + // does not indicate a modification of the element + return; + } + // System.err.println(eventType + ": " + notifier); + + OperationHistoryListener.init(); + try { + // TODO: kind of get nearest classifier + + if (notifier instanceof Classifier) { + Classifier classifier = (Classifier) notifier; + if ((eventType == Notification.REMOVE) || + (eventType == PapyrusStereotypeListener.MODIFIED_STEREOTYPE)) { + regenList.add(classifier); + } + // don't treat addition here, since operations/properties do not have their final names yet + // IStorage storage = new TextStorage(string); + } + if (notifier instanceof Behavior) { + Behavior behavior = (Behavior) notifier; + if (eventType == Notification.SET) { + // name modification + if (behavior.getSpecification() == null) { + } + } + else if (eventType == Notification.ADD) { + // modification of an opaque behavior in Papyrus implied remove&add operations + Classifier nearestCl = getNearestClassifier(behavior); + if (nearestCl != null) { + regenList.add(nearestCl); + } + } + } + + else if (notifier instanceof Feature) { + // if a feature is added, it is first generated with a dummy name, then the name is corrected. + Feature feature = (Feature) notifier; + Element owner = feature.getOwner(); + if (owner instanceof Classifier) { + // System.out.println(owner); + regenList.add((Classifier) owner); + } + } + else if (notifier instanceof Parameter) { + Parameter parameter = (Parameter) notifier; + if (parameter.getOperation() != null) { + Element owner = parameter.getOperation().getOwner(); + if (owner instanceof Classifier) { + // System.out.println(owner); + regenList.add((Classifier) owner); + } + } + } + else if (notifier instanceof DirectedRelationship) { + // if a feature is added, it is first generated with a dummy name, then the name is corrected. + DirectedRelationship dr = (DirectedRelationship) notifier; + for (Element client : dr.getSources()) { + if (client instanceof Classifier) { + // System.out.println(client); + regenList.add((Classifier) client); + } + } + } + else if (notifier instanceof Package) { + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static Classifier getNearestClassifier(Element element) { + while (element != null) { + if (!(element instanceof Behavior) && (element instanceof Classifier)) { + return (Classifier) element; + } + element = element.getOwner(); + } + return null; + } + + static EList<Classifier> regenList = new UniqueEList<Classifier>(); +} diff --git a/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/listener/OperationHistoryListener.java b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/listener/OperationHistoryListener.java new file mode 100644 index 00000000000..ca34d6ab0ba --- /dev/null +++ b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/listener/OperationHistoryListener.java @@ -0,0 +1,76 @@ +/***************************************************************************** + * 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 v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ansgar Radermacher (CEA LIST) Ansgar.Radermacher@cea.fr - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.texteditor.cdt.listener; + +import org.eclipse.core.commands.operations.IOperationHistoryListener; +import org.eclipse.core.commands.operations.OperationHistoryEvent; +import org.eclipse.core.commands.operations.OperationHistoryFactory; +import org.eclipse.emf.common.util.BasicEList; +import org.eclipse.emf.common.util.EList; +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.utils.ServiceUtilsForEObject; +import org.eclipse.papyrus.texteditor.cdt.Activator; +import org.eclipse.papyrus.texteditor.cdt.modelresource.TextEditorModelSharedResource; +import org.eclipse.papyrus.texteditor.cdt.sync.SyncModelToCDT; +import org.eclipse.papyrus.texteditor.model.texteditormodel.TextEditorModel; +import org.eclipse.uml2.uml.Classifier; + +public class OperationHistoryListener implements IOperationHistoryListener { + + public static void init() { + if (ohl == null) { + ohl = new OperationHistoryListener(); + OperationHistoryFactory.getOperationHistory().addOperationHistoryListener(ohl); + } + } + + private static OperationHistoryListener ohl = null; + + @Override + public void historyNotification(OperationHistoryEvent event) { + int eventType = event.getEventType(); + if (eventType == OperationHistoryEvent.OPERATION_ADDED || eventType == OperationHistoryEvent.REDONE + || eventType == OperationHistoryEvent.UNDONE) { + + EList<Classifier> regenListCopy = new BasicEList<Classifier>(ModelListener.regenList); + ModelListener.regenList.clear(); + + // re-generate files from list - if they are still in a resource + for (Classifier cl : regenListCopy) { + if (cl.eResource() != null) { + try { + ServicesRegistry serviceRegistry = ServiceUtilsForEObject.getInstance().getServiceRegistry(cl); + TextEditorModelSharedResource model = (TextEditorModelSharedResource) ServiceUtils.getInstance() + .getModelSet(serviceRegistry).getModelChecked(TextEditorModelSharedResource.MODEL_ID); + + if (model != null) { + TextEditorModel tem = model.getTextEditorModel(cl); + if (tem != null) { + SyncModelToCDT.syncModelToCDT(cl, tem.getGeneratorID()); + } + } + } catch (ServiceException e) { + Activator.log.error(e); + } catch (NotFoundException e) { + Activator.log.error(e); + } + } + } + } + } +} diff --git a/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/modelresource/TextEditorModelSharedResource.java b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/modelresource/TextEditorModelSharedResource.java new file mode 100644 index 00000000000..7781972dd12 --- /dev/null +++ b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/modelresource/TextEditorModelSharedResource.java @@ -0,0 +1,120 @@ +/*****************************************************************************
+ * 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 v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Vincent Lorenzo (CEA LIST) Vincent.Lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.texteditor.cdt.modelresource;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.papyrus.infra.core.resource.AbstractModelWithSharedResource;
+import org.eclipse.papyrus.infra.core.resource.IModel;
+import org.eclipse.papyrus.texteditor.model.texteditormodel.TextEditorModel;
+
+
+public class TextEditorModelSharedResource extends AbstractModelWithSharedResource<TextEditorModel> implements IModel {
+
+
+ /**
+ * File extension used for notation.
+ */
+ public static final String NOTATION_FILE_EXTENSION = "notation"; //$NON-NLS-1$
+
+ /**
+ * Model ID.
+ */
+ public static final String MODEL_ID = "org.eclipse.papyrus.exteditor.cdt.CDTEditorModelSharedResource"; //$NON-NLS-1$
+
+
+ /**
+ *
+ * Constructor.
+ *
+ */
+ public TextEditorModelSharedResource() {
+
+ }
+
+
+ /**
+ * Get the file extension used for this model.
+ *
+ * @see org.eclipse.papyrus.infra.core.resource.AbstractBaseModel#getModelFileExtension()
+ *
+ * @return
+ */
+ @Override
+ protected String getModelFileExtension() {
+ return NOTATION_FILE_EXTENSION;
+ }
+
+ /**
+ * Get the identifier used to register this model.
+ *
+ * @see org.eclipse.papyrus.infra.core.resource.AbstractBaseModel#getIdentifier()
+ *
+ * @return
+ */
+ @Override
+ public String getIdentifier() {
+ return MODEL_ID;
+ }
+
+
+ /**
+ * Add a new initialized {@link TextEditorModel} to the model.
+ *
+ * @param textInstance
+ * The textInstance to add.
+ */
+ public void addTextEditorModel(TextEditorModel textInstance) {
+ getResource().getContents().add(textInstance);
+ }
+
+ /**
+ * Add a new initialized {@link PapyrustextInstance} to the model.
+ *
+ * @param textInstance
+ * The textInstance to add.
+ */
+ public void removeTextEditorModel(TextEditorModel textInstance) {
+ getResource().getContents().remove(textInstance);
+ }
+
+ /**
+ * @param editedObject
+ * an edited element
+ * @return an editor reference for a given object if an editor exists, or null
+ */
+ public TextEditorModel getTextEditorModel(EObject editedObject) {
+ for (EObject textInstanceEO : getResource().getContents()) {
+ if (textInstanceEO instanceof TextEditorModel) {
+ TextEditorModel textInstance = (TextEditorModel) textInstanceEO;
+ if (textInstance.getEditedObject() == editedObject) {
+ return textInstance;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ *
+ * @see org.eclipse.papyrus.infra.core.resource.AbstractModelWithSharedResource#isModelRoot(org.eclipse.emf.ecore.EObject)
+ *
+ * @param object
+ * @return
+ */
+ @Override
+ protected boolean isModelRoot(EObject object) {
+ return false;
+ }
+
+}
diff --git a/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/preferences/CDTPreferenceConstants.java b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/preferences/CDTPreferenceConstants.java new file mode 100644 index 00000000000..ca20cafca87 --- /dev/null +++ b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/preferences/CDTPreferenceConstants.java @@ -0,0 +1,33 @@ +/***************************************************************************** + * 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 v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * CEA LIST - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.texteditor.cdt.preferences; + +/** + * Constant definitions for plug-in preferences + */ +public class CDTPreferenceConstants { + + /** + * Default option for opening the editor at a specified location. Store uses directly the SWT constants + */ + public static final String P_OPEN_LOCATION = "openLocation"; //$NON-NLS-1$ + + /** + * For attributes, the default "aggregation kind" value is "none". When this option is set + * it will be treated as composite + */ + public static final String P_SYNC_PERMANENTLY = "syncPermanently"; //$NON-NLS-1$ + + public static final String P_SYNC_ALL_FILES = "syncAllFiles"; //$NON-NLS-1$ +} diff --git a/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/preferences/CDTPreferenceInitializer.java b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/preferences/CDTPreferenceInitializer.java new file mode 100644 index 00000000000..494838690c5 --- /dev/null +++ b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/preferences/CDTPreferenceInitializer.java @@ -0,0 +1,39 @@ +/***************************************************************************** + * 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 v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * CEA LIST - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.texteditor.cdt.preferences; + +import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.papyrus.texteditor.cdt.Activator; +import org.eclipse.swt.SWT; + +/** + * Class used to initialize default preference values. + */ +public class CDTPreferenceInitializer extends AbstractPreferenceInitializer { + + /* + * (non-Javadoc) + * + * @see org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer#initializeDefaultPreferences() + */ + @Override + public void initializeDefaultPreferences() { + IPreferenceStore store = Activator.getDefault().getPreferenceStore(); + store.setDefault(CDTPreferenceConstants.P_OPEN_LOCATION, SWT.RIGHT); + store.setDefault(CDTPreferenceConstants.P_SYNC_ALL_FILES, false); + store.setDefault(CDTPreferenceConstants.P_SYNC_PERMANENTLY, false); + } +} diff --git a/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/preferences/CDTPreferencePage.java b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/preferences/CDTPreferencePage.java new file mode 100644 index 00000000000..efc94febace --- /dev/null +++ b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/preferences/CDTPreferencePage.java @@ -0,0 +1,64 @@ +/***************************************************************************** + * 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 v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * CEA LIST - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.texteditor.cdt.preferences; + +import org.eclipse.jface.preference.BooleanFieldEditor; +import org.eclipse.jface.preference.FieldEditorPreferencePage; +import org.eclipse.papyrus.texteditor.cdt.Activator; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPreferencePage; + + +/** + * This class represents the EC3M preference page + * <p> + * This page is used to modify preferences only. They are stored in the preference store that belongs to the main plug-in class. That way, preferences can be accessed directly via the preference store. + */ + +public class CDTPreferencePage + extends FieldEditorPreferencePage + implements IWorkbenchPreferencePage { + + public CDTPreferencePage() { + super(GRID); + setPreferenceStore(Activator.getDefault().getPreferenceStore()); + setDescription("CDT editor integration options"); //$NON-NLS-1$ + } + + /** + * Creates the field editors. Field editors are abstractions of + * the common GUI blocks needed to manipulate various types + * of preferences. Each field editor knows how to save and + * restore itself. + */ + @Override + public void createFieldEditors() { + addField(new BooleanFieldEditor( + CDTPreferenceConstants.P_SYNC_PERMANENTLY, "&Synchronize permanently (otherwise only on demand)", //$NON-NLS-1$ + getFieldEditorParent())); + + addField(new BooleanFieldEditor( + CDTPreferenceConstants.P_SYNC_ALL_FILES, "Synchronize all classes (otherwise synchronize only classes with open editor)", //$NON-NLS-1$ + getFieldEditorParent())); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench) + */ + @Override + public void init(IWorkbench workbench) { + } +} diff --git a/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/sync/FindTransition.java b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/sync/FindTransition.java new file mode 100644 index 00000000000..e737e45abf3 --- /dev/null +++ b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/sync/FindTransition.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * 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 v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ansgar Radermacher - ansgar.radermacher@cea.fr CEA LIST - initial API and implementation + * + *******************************************************************************/ + +package org.eclipse.papyrus.texteditor.cdt.sync; + +import org.eclipse.uml2.uml.Behavior; +import org.eclipse.uml2.uml.Classifier; +import org.eclipse.uml2.uml.Element; +import org.eclipse.uml2.uml.NamedElement; +import org.eclipse.uml2.uml.Transition; + +/** + * Find the behavior in the model from a given method in the code. Used during the + * back synchronization from code to model. + */ +public class FindTransition { + + private static final String UNDERSCORE = "_"; //$NON-NLS-1$ + + public static Behavior findBehavior(Classifier cl, String methodName) { + for (Element element : cl.allOwnedElements()) { + if (element instanceof Transition) { + Transition transition = (Transition) element; + Behavior effect = transition.getEffect(); + if ((effect != null) && behaviorMatches(effect, methodName)) { + return transition.getEffect(); + } + } + } + return null; + } + + public static boolean behaviorMatches(Behavior behavior, String methodName) { + return + methodName.endsWith(NamedElement.SEPARATOR + behavior.getName()) || + methodName.endsWith(UNDERSCORE + behavior.getName()); + } +} diff --git a/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/sync/ObtainICElement.java b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/sync/ObtainICElement.java new file mode 100644 index 00000000000..e5457380c45 --- /dev/null +++ b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/sync/ObtainICElement.java @@ -0,0 +1,129 @@ +/******************************************************************************* + * 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 v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ansgar Radermacher - ansgar.radermacher@cea.fr CEA LIST - initial API and implementation + * + *******************************************************************************/ + +package org.eclipse.papyrus.texteditor.cdt.sync; + +import java.util.Iterator; + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.IFunctionDeclaration; +import org.eclipse.cdt.core.model.IParent; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.emf.common.util.EList; +import org.eclipse.papyrus.codegen.extensionpoints.ILangCodegen; +import org.eclipse.papyrus.codegen.extensionpoints.ILangCodegen2; +import org.eclipse.papyrus.codegen.extensionpoints.MethodInfo; +import org.eclipse.uml2.uml.Behavior; +import org.eclipse.uml2.uml.NamedElement; +import org.eclipse.uml2.uml.Operation; +import org.eclipse.uml2.uml.Parameter; +import org.eclipse.uml2.uml.ParameterDirectionKind; +import org.eclipse.uml2.uml.Transition; + + +/** + * This class is used to select the operation the user wants to edit after opening the editor. + * In case of transition, the selection is based on simple name only (either prefixed with the name separator or with an + * underscore - based on the assumption that scoped names are either kept or flattened using underscore as separator + * + */ +public class ObtainICElement { + + /** + * Return the ICelement associated with a UML element. Currently, only methods are supported. + * + * @param parent + * the parent (typically the translation unit of a CDT file) + * @param element + * A named UML element + * @throws CoreException + */ + public static ICElement getICElement(ILangCodegen codegen, IParent parent, NamedElement element) { + MethodInfo methodInfo = null; + NamedElement operationOrBehavior = element; + if (element instanceof Transition) { + operationOrBehavior = ((Transition) element).getEffect(); + } + + // no behavior found => not possible to locate element + if (operationOrBehavior == null) { + return null; + } + + if (codegen instanceof ILangCodegen2) { + // get generator specific method info. + methodInfo = ((ILangCodegen2) codegen).getMethodInfo(operationOrBehavior); + } + if (methodInfo == null) { + // use default behavior. + if (element instanceof Behavior) { + methodInfo = MethodInfo.fromBehavior((Behavior) operationOrBehavior); + } + else if (element instanceof Operation) { + methodInfo = MethodInfo.fromOperation((Operation) operationOrBehavior); + } + else { + return null; + } + } + + try { + for (ICElement child : parent.getChildren()) { + if (child instanceof IParent) { + return getICElement(codegen, (IParent) child, element); + } + if (child instanceof IFunctionDeclaration) { + IFunctionDeclaration function = (IFunctionDeclaration) child; + + // does the element name match? (CDT provides className::methodName information). Since we are in the scope of + // the class, we only verify the postfix part of the name + if (child.getElementName().endsWith(NamedElement.SEPARATOR + methodInfo.getName())) { + // check, if parameters match. This handles most common overloading cases (it does not handle functions that + // only differ with respect to the modifiers + Iterator<String> paramIter = methodInfo.getParameterTypes().iterator(); + boolean match = methodInfo.getParameterTypes().size() == function.getParameterTypes().length; + if (match) { + for (String cdtParamType : function.getParameterTypes()) { + String umlParamType = paramIter.next(); + if (!cdtParamType.equals(umlParamType)) { + match = false; + break; + } + } + if (match) { + return child; + } + } + } + } + } + } catch (CoreException e) { + } + return null; + } + + /** + * Count the number of parameters without taking the return parameter into account + * + * @param list + * @return + */ + public static int countParameters(EList<Parameter> list) { + int params = 0; + for (Parameter par : list) { + if (par.getDirection() != ParameterDirectionKind.RETURN_LITERAL) { + params++; + } + } + return params; + } +} diff --git a/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/sync/ParameterModifiers.java b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/sync/ParameterModifiers.java new file mode 100644 index 00000000000..8601ac73484 --- /dev/null +++ b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/sync/ParameterModifiers.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * 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 v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ansgar Radermacher - ansgar.radermacher@cea.fr CEA LIST - initial API and implementation + * + *******************************************************************************/ + +package org.eclipse.papyrus.texteditor.cdt.sync; + +/** + * Simple grouping of modifier related parameters + */ +public class ParameterModifiers { + public ParameterModifiers() { + isPointer = false; + isRef = false; + isRegister = false; + array = ""; //$NON-NLS-1$ + } + + /** + * true, if parameter is a pointer + */ + boolean isPointer; + + /** + * true, if parameter is a reference + */ + boolean isRef; + + /** + * true, if parameter is a register + */ + boolean isRegister; + + /** + * value of array modifiers (e.g. [2]) + */ + String array ; +} diff --git a/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/sync/RevealCurrentOperation.java b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/sync/RevealCurrentOperation.java new file mode 100644 index 00000000000..cf53a0b5468 --- /dev/null +++ b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/sync/RevealCurrentOperation.java @@ -0,0 +1,128 @@ +/******************************************************************************* + * 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 v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ansgar Radermacher - ansgar.radermacher@cea.fr CEA LIST - initial API and implementation + * + *******************************************************************************/ + +package org.eclipse.papyrus.texteditor.cdt.sync; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.dom.ast.IASTNodeSelector; +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.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.ui.CDTUITools; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.papyrus.infra.core.Activator; +import org.eclipse.ui.IEditorInput; +import org.eclipse.uml2.uml.Classifier; +import org.eclipse.uml2.uml.Element; +import org.eclipse.uml2.uml.Operation; + + +public class RevealCurrentOperation { + + public RevealCurrentOperation(IEditorInput input, Classifier classifier, String projectName) { + m_input = input; + m_classifier = classifier; + m_projectName = projectName; + } + + public Element obtainSelectedElement(ITextSelection selection) { + ICElement ice = CDTUITools.getEditorInputCElement(m_input); + + if (ice instanceof ITranslationUnit) { + ICProject project = CoreModel.getDefault().getCModel().getCProject(m_projectName); + + IIndex index = null; + try { + index = CCorePlugin.getIndexManager().getIndex(project); + index.acquireReadLock(); + + // index = CCorePlugin.getIndexManager().getIndex(project); + ITranslationUnit itu = (ITranslationUnit) ice; + // hack: force re-evaluation of AST node, requires modified CDT! + // Seems to be no longer required. + // ASTProvider.getASTProvider().fCache.setActiveElement(itu); + + IASTTranslationUnit ast = itu.getAST(index, ITranslationUnit.AST_SKIP_INDEXED_HEADERS); + IASTNodeSelector selector = ast.getNodeSelector(null); + + String opName = findOperation(itu, selector, itu, selection); + if (opName != null) { + int sep = opName.lastIndexOf("::"); //$NON-NLS-1$ + if (sep != -1) { + opName = opName.substring(sep + 2); + } + Operation operation = m_classifier.getOperation(opName, null, null); + if (operation != null) { + return operation; + } + } + + } catch (CModelException e) { + Activator.getDefault().getLog().log(e.getStatus()); + } catch (Exception e) { + System.err.println(e); + } finally { + if (index != null) { + index.releaseReadLock(); + } + } + } + return m_classifier; + } + + /** + * Examine the children of a translation unit in order to extract the methods that are defined within + * the unit + * + * @param itu + * @param selector + * @param parent + * @throws CModelException + */ + public String findOperation(ITranslationUnit itu, IASTNodeSelector selector, IParent parent, ITextSelection selection) throws CModelException { + + for (ICElement child : parent.getChildren()) { + if (child instanceof IParent) { + return findOperation(itu, selector, (IParent) child, selection); + } + 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(); + int pos = selection.getOffset(); + if ((pos >= range.getStartPos()) && (pos < range.getStartPos() + range.getLength())) { + return name; + } + } + } + return null; + } + + + + protected IEditorInput m_input; + + protected Classifier m_classifier; + + protected String m_projectName; +} diff --git a/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/sync/SyncCDTtoModel.java b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/sync/SyncCDTtoModel.java new file mode 100644 index 00000000000..1a0d635b974 --- /dev/null +++ b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/sync/SyncCDTtoModel.java @@ -0,0 +1,635 @@ +/******************************************************************************* + * 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 v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ansgar Radermacher - ansgar.radermacher@cea.fr CEA LIST - initial API and implementation + * + *******************************************************************************/ + +package org.eclipse.papyrus.texteditor.cdt.sync; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.dom.ast.ExpansionOverlapsBoundaryException; +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.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTNodeSelector; +import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration; +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.core.parser.IToken; +import org.eclipse.cdt.ui.CDTUITools; +import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.emf.common.util.EList; +import org.eclipse.papyrus.C_Cpp.Array; +import org.eclipse.papyrus.C_Cpp.Const; +import org.eclipse.papyrus.C_Cpp.EStorageClass; +import org.eclipse.papyrus.C_Cpp.Include; +import org.eclipse.papyrus.C_Cpp.Ptr; +import org.eclipse.papyrus.C_Cpp.Ref; +import org.eclipse.papyrus.C_Cpp.StorageClass; +import org.eclipse.papyrus.C_Cpp.Volatile; +import org.eclipse.papyrus.codegen.extensionpoints.ILangCodegen; +import org.eclipse.papyrus.codegen.extensionpoints.ILangCodegen2; +import org.eclipse.papyrus.codegen.extensionpoints.LanguageCodegen; +import org.eclipse.papyrus.codegen.extensionpoints.SyncInformation; +import org.eclipse.papyrus.cpp.codegen.Constants; +import org.eclipse.papyrus.infra.core.Activator; +import org.eclipse.papyrus.texteditor.cdt.CommandSupport; +import org.eclipse.papyrus.texteditor.cdt.TextEditorConstants; +import org.eclipse.papyrus.texteditor.cdt.Utils; +import org.eclipse.papyrus.texteditor.cdt.listener.ModelListener; +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.DataType; +import org.eclipse.uml2.uml.NamedElement; +import org.eclipse.uml2.uml.OpaqueBehavior; +import org.eclipse.uml2.uml.Operation; +import org.eclipse.uml2.uml.Parameter; +import org.eclipse.uml2.uml.Type; +import org.eclipse.uml2.uml.UMLPackage; + +public class SyncCDTtoModel implements Runnable { + + public static final String REGISTER = "register"; //$NON-NLS-1$ + + public static final String CONST = "const"; //$NON-NLS-1$ + + public static final String VOLATILE = "volatile"; //$NON-NLS-1$ + + public static final String sAtParam = "@param"; //$NON-NLS-1$ + + public static final String ansiCLib = "AnsiCLibrary"; //$NON-NLS-1$ + + public SyncCDTtoModel(IEditorInput input, Classifier classifier, String projectName, String generatorID) { + m_input = input; + m_classifier = classifier; + m_projectName = projectName; + m_codegen = LanguageCodegen.getGenerator(TextEditorConstants.CPP, generatorID); + } + + + public final String c_cpp_langID = "C/C++"; //$NON-NLS-1$ + + public void syncCDTtoModel() { + CommandSupport.exec("update model from CDT", this); + } + + @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(); + + // index = CCorePlugin.getIndexManager().getIndex(project); + ITranslationUnit itu = (ITranslationUnit) ice; + // hack: force re-evaluation of AST node, requires modified CDT! + // Seems to be no longer required. + // ASTProvider.getASTProvider().fCache.setActiveElement(itu); + + IASTTranslationUnit ast = itu.getAST(index, ITranslationUnit.AST_SKIP_INDEXED_HEADERS); + IASTNodeSelector selector = ast.getNodeSelector(null); + + examineChildren(itu, selector, itu); + updateCppInclude(itu); + + CUIPlugin.getDefault().getProblemMarkerManager(); + if (itu instanceof IWorkingCopy) { + // ((IWorkingCopy)itu).commit(true, new + // NullProgressMonitor()); + // ((IWorkingCopy)itu).reconcile(); + ((IWorkingCopy) itu).reconcile(true, new NullProgressMonitor()); + // ((IWorkingCopy)itu).reconcile(true, true, new + // NullProgressMonitor()); + } + + } catch (CModelException e) { + Activator.getDefault().getLog().log(e.getStatus()); + } catch (Exception e) { + System.err.println(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); + 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)) { + operation = getModelOperationFromName(name, parent, position); + if (operation != null) { + operation.setName(name); + } else { + // it is possible that the C++ method corresponds to the effect + // of a transition. try to locate the behavior (without using an operation) + behavior = FindTransition.findBehavior(m_classifier, name); + if (behavior == null) { + // still null => create new operation in model + if (m_classifier instanceof Class) { + operation = ((Class) m_classifier).createOwnedOperation(name, null, null); + } else if (m_classifier instanceof DataType) { + operation = ((DataType) m_classifier).createOwnedOperation(name, null, null); + } + } + } + } + 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 (operation != null) { + if (operation.getMethods().size() == 0) { + // operation exists, but does not have any method => create + + if (m_classifier instanceof Class) { + behavior = ((Class) m_classifier).createOwnedBehavior(name, UMLPackage.eINSTANCE.getOpaqueBehavior()); + } else if (m_classifier instanceof DataType) { + // ob = (OpaqueBehavior) ((DataType) + // m_classifier).createOwnedBehavior(name, + // UMLPackage.eINSTANCE.getOpaqueBehavior()); + } + behavior.setSpecification(operation); + behavior.setIsReentrant(false); + } + else { + behavior = operation.getMethods().get(0); + // operation has at least one method, this may not be null. + if (!behavior.getName().equals(name)) { + behavior.setName(name); + } + } + } + + // assertions: operation can be null, behavior is always non-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 + if (operation != null) { + UMLUtil.destroyElements(operation.getOwnedParameters()); + } + UMLUtil.destroyElements(behavior.getOwnedParameters()); + + for (IASTNode declaratorChild : declarator.getChildren()) { + if (declaratorChild instanceof IASTParameterDeclaration) { + IASTParameterDeclaration parameter = (IASTParameterDeclaration) declaratorChild; + IASTName parameterName = parameter.getDeclarator().getName(); + IASTDeclSpecifier parameterType = parameter.getDeclSpecifier(); + ParameterModifiers modifiers = new ParameterModifiers(); + String parameterTypeName = ""; //$NON-NLS-1$ + try { + IToken token = parameter.getDeclarator().getSyntax(); + while (token != null) { + String tokenStr = token.toString(); + if (tokenStr.equals("*")) { //$NON-NLS-1$ + modifiers.isPointer = true; + } else if (tokenStr.equals("&")) { //$NON-NLS-1$ + modifiers.isRef = true; + } else if (tokenStr.equals("[")) { //$NON-NLS-1$ + while (token != null) { + modifiers.array += token.toString(); + token = token.getNext(); + } + if (token == null) { + break; + } + } + token = token.getNext(); + } + + token = parameterType.getSyntax(); + while (token != null) { + String tokenStr = token.toString(); + if (tokenStr.equals("*")) { //$NON-NLS-1$ + // TODO: check, if this can be called (depending on + // * position with different semantics?) + modifiers.isPointer = true; + } else if (tokenStr.equals("&")) { //$NON-NLS-1$ + modifiers.isRef = true; + } else if (tokenStr.equals(REGISTER)) { + modifiers.isRegister = true; + } else if (tokenStr.equals(CONST) || tokenStr.equals(VOLATILE)) { + // do nothing (use isConst() or isVolatile() operation of parameterType) + // is not part of parameter type + } else { + if (parameterTypeName.length() > 0) { + parameterTypeName += " "; //$NON-NLS-1$ + } + parameterTypeName += tokenStr; + } + token = token.getNext(); + } + } catch (ExpansionOverlapsBoundaryException e) { + } + + NamedElement namedElemParamType = Utils.getQualifiedElement(Utils.getTop(m_classifier), + parameterTypeName); + if (namedElemParamType == null) { + namedElemParamType = Utils.getQualifiedElement(Utils.getTop(m_classifier), + ansiCLib + Utils.nsSep + parameterTypeName); + } + if (parameterType.isRestrict()) { + } + Parameter umlParameter = null; + Type paramType = namedElemParamType instanceof Type ? (Type) namedElemParamType : null; + if (operation != null) { + umlParameter = operation.createOwnedParameter(parameterName.toString(), paramType); + applyParameterModifiers(parameterType, umlParameter, modifiers); + } + umlParameter = behavior.createOwnedParameter(parameterName.toString(), paramType); + 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); + } + } + } + } + if (operation != null) { + return operation; + } + else { + return behavior; + } + } + + /** + * Apply the modifiers for a parameter, notably the stereotypes of the C++ profile + * + * @param parameterType the CDT AST parameter specification + * @param umlParameter the UML parameter (to which a stereotype should be applied) + * @param modifiers the modifiers that should be applied (stored in an instance of class ParameterModifiers) + */ + public void applyParameterModifiers(IASTDeclSpecifier parameterType, Parameter umlParameter, ParameterModifiers modifiers) { + if (parameterType.isConst()) { + StereotypeUtil.apply(umlParameter, Const.class); + } + if (parameterType.isVolatile()) { + StereotypeUtil.apply(umlParameter, Volatile.class); + } + if (modifiers.isRegister) { + StorageClass sc = StereotypeUtil.applyApp(umlParameter, StorageClass.class); + if (sc != null) { + sc.setStorageClass(EStorageClass.REGISTER); + } + } + if (modifiers.isPointer) { + StereotypeUtil.apply(umlParameter, Ptr.class); + } else if (modifiers.isRef) { + StereotypeUtil.apply(umlParameter, Ref.class); + } + if (modifiers.array.length() > 0) { + Array arraySt = StereotypeUtil.applyApp(umlParameter, Array.class); + if (arraySt != null && !modifiers.array.equals("[]") && (!modifiers.array.equals("[ ]"))) { //$NON-NLS-1$//$NON-NLS-2$ + arraySt.setDefinition(modifiers.array); + } + } + } + + /** + * Obtain an operation from the model by using the name of a CDT method. + * If an operation of the given name does not exist, it might indicate that + * the method has been renamed. + * + * @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 + */ + public Operation getModelOperationFromName(String name, IParent parent, int position) { + Operation operation = m_classifier.getOperation(name, null, null); + + if (operation == null) { + // 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. + if (position < m_classifier.getOperations().size()) { + operation = m_classifier.getOperations().get(position); + String modelName = operation.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 + operation = null; + break; + } + } + } + } catch (CModelException e) { + } + } + } + return operation; + } + + 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; + } + + /** + * input of the CDT editor. Used to obtain code within editor. + */ + protected IEditorInput m_input; + + /** + * The classifier (class) that is currently edited + */ + protected Classifier m_classifier; + + /** + * name of CDT project in which the generated code is stored. + */ + protected String m_projectName; + + /** + * reference to code generator + */ + protected ILangCodegen m_codegen; +} diff --git a/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/sync/SyncModelToCDT.java b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/sync/SyncModelToCDT.java new file mode 100644 index 00000000000..207dfa013c9 --- /dev/null +++ b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/sync/SyncModelToCDT.java @@ -0,0 +1,80 @@ +/******************************************************************************* + * 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 v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ansgar Radermacher - ansgar.radermacher@cea.fr CEA LIST - initial API and implementation + * + *******************************************************************************/ + +package org.eclipse.papyrus.texteditor.cdt.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.runtime.CoreException; +import org.eclipse.core.runtime.Path; +import org.eclipse.papyrus.codegen.extensionpoints.ILangCodegen; +import org.eclipse.papyrus.codegen.extensionpoints.ILangCodegen.FILE_KIND; +import org.eclipse.papyrus.codegen.extensionpoints.ILangCodegen2; +import org.eclipse.papyrus.codegen.extensionpoints.LanguageCodegen; +import org.eclipse.papyrus.cpp.codegen.Constants; +import org.eclipse.papyrus.infra.core.Activator; +import org.eclipse.papyrus.texteditor.cdt.TextEditorConstants; +import org.eclipse.uml2.uml.Classifier; + +/** + * 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 SyncModelToCDT { + + 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 == null) || (classifier.eResource() == null)) { + return null; + } + + ILangCodegen codegen = LanguageCodegen.getGenerator(TextEditorConstants.CPP, generatorID); + + IProject modelProject = codegen.getTargetProject(classifier, false); + if (modelProject == null) { + return null; + } + + IContainer srcPkg = null; + IFile cppFile = null; + try { + codegen.generateCode(modelProject, classifier, null); // need listener for sync in both directions! + + String suffix = (codegen instanceof ILangCodegen2) ? + suffix = ((ILangCodegen2) codegen).getSuffix(FILE_KIND.BODY) : CPP_SUFFIX; + + cppFile = modelProject.getFile(new Path(codegen.getFileName(modelProject, 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; + } +} |