diff options
author | Ansgar Radermacher | 2015-09-01 12:28:29 +0000 |
---|---|---|
committer | Ansgar Radermacher | 2015-09-01 12:34:57 +0000 |
commit | 0574ed7672c448837626f042621b155fb74d60ff (patch) | |
tree | faa681a69c9a2ad55c58c165f530e80174e2d7d7 /extraplugins/codegen | |
parent | b6db7cbea107c843bf0f7ff5fbc6484822500437 (diff) | |
download | org.eclipse.papyrus-0574ed7672c448837626f042621b155fb74d60ff.tar.gz org.eclipse.papyrus-0574ed7672c448837626f042621b155fb74d60ff.tar.xz org.eclipse.papyrus-0574ed7672c448837626f042621b155fb74d60ff.zip |
474339 - [CDT integration] Synchronization of code to model requires additional information
Diffstat (limited to 'extraplugins/codegen')
15 files changed, 507 insertions, 169 deletions
diff --git a/extraplugins/codegen/org.eclipse.papyrus.codegen.extensionpoints/schema/languageCodegen.exsd b/extraplugins/codegen/org.eclipse.papyrus.codegen.extensionpoints/schema/languageCodegen.exsd index 5e2dee390b4..7b60f913ef4 100644 --- a/extraplugins/codegen/org.eclipse.papyrus.codegen.extensionpoints/schema/languageCodegen.exsd +++ b/extraplugins/codegen/org.eclipse.papyrus.codegen.extensionpoints/schema/languageCodegen.exsd @@ -52,15 +52,15 @@ <attribute name="id" type="string"> <annotation> <documentation> - ID of a code generator + ID of a code generator, currently optional for backward compatibility. </documentation> </annotation> </attribute> <attribute name="language" type="string" use="required"> <annotation> - <documentation> - Programming language supported by the code generator - </documentation> + <documentation> + Programming language supported by the code generator + </documentation> </annotation> </attribute> <attribute name="class" type="string" use="required"> @@ -76,4 +76,9 @@ </complexType> </element> + + + + + </schema> diff --git a/extraplugins/codegen/org.eclipse.papyrus.codegen.extensionpoints/src/org/eclipse/papyrus/codegen/extensionpoints/GeneratorSelectionDialog.java b/extraplugins/codegen/org.eclipse.papyrus.codegen.extensionpoints/src/org/eclipse/papyrus/codegen/extensionpoints/GeneratorSelectionDialog.java index a01afe946fd..fd3066b0ddf 100644 --- a/extraplugins/codegen/org.eclipse.papyrus.codegen.extensionpoints/src/org/eclipse/papyrus/codegen/extensionpoints/GeneratorSelectionDialog.java +++ b/extraplugins/codegen/org.eclipse.papyrus.codegen.extensionpoints/src/org/eclipse/papyrus/codegen/extensionpoints/GeneratorSelectionDialog.java @@ -72,7 +72,7 @@ public class GeneratorSelectionDialog extends AbstractElementListSelectionDialog @Override public void widgetSelected(SelectionEvent e) { int index = fFilteredList.getSelectionIndex(); - m_description.setText(getElement(index).getDescription()); + updateDescription(getElement(index)); } @Override @@ -89,11 +89,20 @@ public class GeneratorSelectionDialog extends AbstractElementListSelectionDialog m_description = new Text(contents, SWT.NONE | SWT.WRAP | SWT.V_SCROLL | SWT.READ_ONLY); m_description.setLayoutData(descriptionGD); - m_description.setText(getElement(0).getDescription()); + updateDescription(getElement(0)); return contents; } + protected void updateDescription(ILangCodegen codegen) { + if (codegen instanceof ILangCodegen2) { + m_description.setText(((ILangCodegen2) codegen).getDescription()); + } + else { + m_description.setText("not available"); //$NON-NLS-1$ + } + } + /** * Obtain ILangCodegen object via index. Note that we need to access the data from the filtered list * since the order might not be the same as the local "generators" array (the filtered list sorts) diff --git a/extraplugins/codegen/org.eclipse.papyrus.codegen.extensionpoints/src/org/eclipse/papyrus/codegen/extensionpoints/ILangCodegen.java b/extraplugins/codegen/org.eclipse.papyrus.codegen.extensionpoints/src/org/eclipse/papyrus/codegen/extensionpoints/ILangCodegen.java index 2e518f7b610..9c1c5fa8371 100644 --- a/extraplugins/codegen/org.eclipse.papyrus.codegen.extensionpoints/src/org/eclipse/papyrus/codegen/extensionpoints/ILangCodegen.java +++ b/extraplugins/codegen/org.eclipse.papyrus.codegen.extensionpoints/src/org/eclipse/papyrus/codegen/extensionpoints/ILangCodegen.java @@ -14,7 +14,6 @@ package org.eclipse.papyrus.codegen.extensionpoints; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.uml2.uml.NamedElement; -import org.eclipse.uml2.uml.Package; import org.eclipse.uml2.uml.PackageableElement; /** @@ -31,48 +30,8 @@ public interface ILangCodegen { public enum FILE_KIND { HEADER, BODY } - - /** - * Provide a user friendly description of the generator - */ - public String getDescription(); - - /** - * Some code generators use a non-trivial mapping from behaviors to methods in the generated code or - * add methods that are not part of a existing behavior in the model. - * This is a problem for code synchronization (update of model from code) as done for instance - * with the CDT editor integration. - * - * @param methodName the name of the method as in the code - * @param body the body - * @return the associated synchronization information. Null indicates that a default mapping is used - */ - public SyncInformation getSyncInformation(String methodName, String body); /** - * Return true, if the generator is eligible for a certain type of model. - * The method may check for instance whether a certain profile (such as - * UML-RT) has been applied. Generators are allowed to return true for all - * models, if they do not have specific (profile related) requirements. - * - * @param modelRoot - * the root of a UML model (for which code should be generated) - * @return true, iff the generator is eligible for this model - */ - public boolean isEligible(Package modelRoot); - - /** - * Return the suffix of a code generator. Some languages use different - * suffixes depending on the file kind, e.g. C distinguishes between HEADER - * and BODY languages. Other languages can ignore this parameter. - * - * @param FILE_KIND - * The file kind - * @return - */ - public String getSuffix(FILE_KIND fileKind); - - /** * Generate code for a specific language * * @param project diff --git a/extraplugins/codegen/org.eclipse.papyrus.codegen.extensionpoints/src/org/eclipse/papyrus/codegen/extensionpoints/ILangCodegen2.java b/extraplugins/codegen/org.eclipse.papyrus.codegen.extensionpoints/src/org/eclipse/papyrus/codegen/extensionpoints/ILangCodegen2.java new file mode 100644 index 00000000000..f75d7de8b20 --- /dev/null +++ b/extraplugins/codegen/org.eclipse.papyrus.codegen.extensionpoints/src/org/eclipse/papyrus/codegen/extensionpoints/ILangCodegen2.java @@ -0,0 +1,53 @@ +package org.eclipse.papyrus.codegen.extensionpoints; + +import org.eclipse.uml2.uml.NamedElement; +import org.eclipse.uml2.uml.Package; + +public interface ILangCodegen2 extends ILangCodegen { + + /** + * Provide a user friendly description of the generator + */ + public String getDescription(); + + /** + * Some code generators use a non-trivial mapping from behaviors to methods in the generated code or + * add methods that are not part of a existing behavior in the model. + * This is a problem for code synchronization (update of model from code) as done for instance + * with the CDT editor integration. + * + * @param methodName the name of the method as in the code + * @param body the body + * @return the associated synchronization information. Null indicates that a default mapping is used + */ + public SyncInformation getSyncInformation(String methodName, String body); + + /** + * Return true, if the generator is eligible for a certain type of model. + * The method may check for instance whether a certain profile (such as + * UML-RT) has been applied. Generators are allowed to return true for all + * models, if they do not have specific (profile related) requirements. + * + * @param modelRoot + * the root of a UML model (for which code should be generated) + * @return true, iff the generator is eligible for this model + */ + public boolean isEligible(Package modelRoot); + + /** + * Return the suffix of a code generator. Some languages use different + * suffixes depending on the file kind, e.g. C distinguishes between HEADER + * and BODY languages. Other languages can ignore this parameter. + * + * @param FILE_KIND + * The file kind + * @return + */ + public String getSuffix(FILE_KIND fileKind); + + /** + * return additional information about the method that has been generated for a UML behavior. + * This information is used by the CDT editor integration to locate the method in the code. + */ + public MethodInfo getMethodInfo(NamedElement operationOrBehavior); +} diff --git a/extraplugins/codegen/org.eclipse.papyrus.codegen.extensionpoints/src/org/eclipse/papyrus/codegen/extensionpoints/LanguageCodegen.java b/extraplugins/codegen/org.eclipse.papyrus.codegen.extensionpoints/src/org/eclipse/papyrus/codegen/extensionpoints/LanguageCodegen.java index 283b57a8642..1ae6609dbf0 100644 --- a/extraplugins/codegen/org.eclipse.papyrus.codegen.extensionpoints/src/org/eclipse/papyrus/codegen/extensionpoints/LanguageCodegen.java +++ b/extraplugins/codegen/org.eclipse.papyrus.codegen.extensionpoints/src/org/eclipse/papyrus/codegen/extensionpoints/LanguageCodegen.java @@ -125,7 +125,7 @@ public class LanguageCodegen { * eligible for a passe classifier * * @param languagePattern - * a l-anguage pattern + * a language pattern * @param classifier * a classifier * @return @@ -135,7 +135,12 @@ public class LanguageCodegen { Package modelRoot = PackageUtil.getRootPackage(classifier); for (ILangCodegen generator : getCodegenList(languagePattern)) { - if (generator.isEligible(modelRoot)) { + if (generator instanceof ILangCodegen2) { + if (((ILangCodegen2) generator).isEligible(modelRoot)) { + eligibleGenerators.add(generator); + } + } + else { eligibleGenerators.add(generator); } } @@ -176,6 +181,35 @@ public class LanguageCodegen { return generators; } + /** + * Get a code generator for a given language + * @param language + * @return + * @deprecated This method is deprecated and kept for compatibility, since there could be more than one generator + * for a given programming language. + */ + @Deprecated + public static ILangCodegen getCodegen(String language) + { + IExtensionRegistry reg = Platform.getExtensionRegistry(); + IConfigurationElement[] configElements = reg.getConfigurationElementsFor(ILANG_SUPPORT_ID); + for (IConfigurationElement configElement : configElements) { + try { + final String extLanguage = configElement.getAttribute(LANGUAGE); + if (extLanguage.equals(language)) { + // TODO: cache returned instance (avoid creating a new instance each time => more efficient, no need for static attributes) + final Object obj = configElement.createExecutableExtension("class"); //$NON-NLS-1$ + if (obj instanceof ILangCodegen) { + return (ILangCodegen) obj; + } + } + } catch (CoreException exception) { + exception.printStackTrace(); + } + } + throw new RuntimeException(String.format(Messages.LanguageSupport_LanguageNotSupported, language)); + } + public static String getID(ILangCodegen generator) { return generatorIDs.get(generator); } diff --git a/extraplugins/codegen/org.eclipse.papyrus.codegen.extensionpoints/src/org/eclipse/papyrus/codegen/extensionpoints/MethodInfo.java b/extraplugins/codegen/org.eclipse.papyrus.codegen.extensionpoints/src/org/eclipse/papyrus/codegen/extensionpoints/MethodInfo.java new file mode 100644 index 00000000000..3886c365d17 --- /dev/null +++ b/extraplugins/codegen/org.eclipse.papyrus.codegen.extensionpoints/src/org/eclipse/papyrus/codegen/extensionpoints/MethodInfo.java @@ -0,0 +1,124 @@ +/***************************************************************************** + * 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 + * + *****************************************************************************/ + +package org.eclipse.papyrus.codegen.extensionpoints; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.uml2.uml.Behavior; +import org.eclipse.uml2.uml.Operation; +import org.eclipse.uml2.uml.Parameter; +import org.eclipse.uml2.uml.ParameterDirectionKind; + +/** + * Additional information about a method that has been generated for a UML behavior. + * This information is used by the CDT editor integration to locate the method in the code, but might be useful + * for other languages as well. + */ +public class MethodInfo { + + /** + * Create a new method info with a given name. The parameter list is initially empty. + * Parameter types can be added with the method addParameterType + * can be initialized later. + * @param name + */ + public MethodInfo(String name) { + this.name = name; + this.parameterTypes = new ArrayList<String>(); + } + + /** + * Create a new method info + * @param name + * @param parameterTypes + */ + public MethodInfo(String name, List<String> parameterTypes) { + this.name = name; + this.parameterTypes = parameterTypes; + } + + /** + * constructor creating a default method information instance from a given behavior + * @param behavior + */ + public static MethodInfo fromBehavior(Behavior behavior) { + MethodInfo mi = new MethodInfo(behavior.getName()); + for (Parameter parameter : behavior.getOwnedParameters()) { + if (parameter.getDirection() != ParameterDirectionKind.RETURN_LITERAL) { + if (parameter.getType() != null) { + mi.addParameterType(parameter.getType().getQualifiedName()); + } + } + else { + mi.addParameterType("undefined"); //$NON-NLS-1$ + } + } + return mi; + } + + /** + * default initializer from a method + * @param behavior + */ + public static MethodInfo fromOperation(Operation operation) { + MethodInfo mi = new MethodInfo(operation.getName()); + for (Parameter parameter : operation.getOwnedParameters()) { + if (parameter.getDirection() != ParameterDirectionKind.RETURN_LITERAL) { + if (parameter.getType() != null) { + mi.addParameterType(parameter.getType().getQualifiedName()); + } + } + else { + mi.addParameterType("undefined"); //$NON-NLS-1$ + } + } + return mi; + } + + /** + * Add a parameter type + * + * @param parameterType the parameter type + */ + public void addParameterType(String parameterType) { + parameterTypes.add(parameterType); + } + + /** + * @return method name + */ + public String getName() { + return name; + } + + /** + * @return list of parameters types (in form of strings). These might contain additional + * modifiers, e.g. { "const char*" } + */ + public List<String> getParameterTypes() { + return parameterTypes; + } + + /** + * The name of the generated method. + */ + protected String name; + + /** + * The names of parameter types + */ + protected List<String> parameterTypes; +} diff --git a/extraplugins/codegen/org.eclipse.papyrus.codegen.extensionpoints/src/org/eclipse/papyrus/codegen/extensionpoints/SyncInformation.java b/extraplugins/codegen/org.eclipse.papyrus.codegen.extensionpoints/src/org/eclipse/papyrus/codegen/extensionpoints/SyncInformation.java index 87fbc1d5dd1..82f5d4e4af9 100644 --- a/extraplugins/codegen/org.eclipse.papyrus.codegen.extensionpoints/src/org/eclipse/papyrus/codegen/extensionpoints/SyncInformation.java +++ b/extraplugins/codegen/org.eclipse.papyrus.codegen.extensionpoints/src/org/eclipse/papyrus/codegen/extensionpoints/SyncInformation.java @@ -1,5 +1,6 @@ package org.eclipse.papyrus.codegen.extensionpoints; +import org.eclipse.emf.ecore.EObject; import org.eclipse.uml2.uml.Behavior; /** @@ -9,7 +10,7 @@ import org.eclipse.uml2.uml.Behavior; */ public class SyncInformation { /** - * true, iff the method has been added by the generate and does not need synchronization. + * true, iff the method has been added by the generator and does not need synchronization. */ public boolean isGenerated; @@ -24,4 +25,15 @@ public class SyncInformation { * model, but it does not exist yet. Only one of the two attributes (behavior and createBehaviorName) must be set. */ public String createBehaviorName; + + /** + * the element for which the CDT editor has been opened. This may for instance be the class that is edited. + */ + public EObject editedElement; + + /** + * The method body gets filtered during default synchronization (text between generation markers is removed), but the filtered information might be + * important for customized back-synchronization. + */ + public String unfilteredBody; }
\ No newline at end of file diff --git a/extraplugins/codegen/org.eclipse.papyrus.cpp.codegen/src/org/eclipse/papyrus/cpp/codegen/CppLangCodegen.java b/extraplugins/codegen/org.eclipse.papyrus.cpp.codegen/src/org/eclipse/papyrus/cpp/codegen/CppLangCodegen.java index e716db6273b..b5395d3f019 100644 --- a/extraplugins/codegen/org.eclipse.papyrus.cpp.codegen/src/org/eclipse/papyrus/cpp/codegen/CppLangCodegen.java +++ b/extraplugins/codegen/org.eclipse.papyrus.cpp.codegen/src/org/eclipse/papyrus/cpp/codegen/CppLangCodegen.java @@ -13,23 +13,30 @@ package org.eclipse.papyrus.cpp.codegen; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.emf.common.util.EList; import org.eclipse.papyrus.C_Cpp.C_CppPackage; import org.eclipse.papyrus.codegen.base.ModelElementsCreator; -import org.eclipse.papyrus.codegen.extensionpoints.ILangCodegen; +import org.eclipse.papyrus.codegen.extensionpoints.ILangCodegen2; +import org.eclipse.papyrus.codegen.extensionpoints.MethodInfo; import org.eclipse.papyrus.codegen.extensionpoints.SyncInformation; import org.eclipse.papyrus.cpp.codegen.preferences.CppCodeGenUtils; import org.eclipse.papyrus.cpp.codegen.transformation.CppModelElementsCreator; import org.eclipse.papyrus.cpp.codegen.utils.LocateCppProject; +import org.eclipse.papyrus.cpp.codegen.xtend.CppParameter; +import org.eclipse.uml2.uml.Behavior; import org.eclipse.uml2.uml.Element; import org.eclipse.uml2.uml.NamedElement; +import org.eclipse.uml2.uml.Operation; import org.eclipse.uml2.uml.Package; import org.eclipse.uml2.uml.PackageableElement; +import org.eclipse.uml2.uml.Parameter; +import org.eclipse.uml2.uml.ParameterDirectionKind; /** * C++ language support * */ -public class CppLangCodegen implements ILangCodegen { +public class CppLangCodegen implements ILangCodegen2 { protected ModelElementsCreator creator = null; @@ -93,4 +100,25 @@ public class CppLangCodegen implements ILangCodegen { public SyncInformation getSyncInformation(String methodName, String body) { return null; } + + @Override + public MethodInfo getMethodInfo(NamedElement operationOrBehavior) { + MethodInfo mi = new MethodInfo(operationOrBehavior.getName()); + EList<Parameter> parameters = null; + if (operationOrBehavior instanceof Operation) { + parameters = ((Operation) operationOrBehavior).getOwnedParameters(); + } + else if (operationOrBehavior instanceof Behavior) { + parameters = ((Behavior) operationOrBehavior).getOwnedParameters(); + } + + if (parameters != null) { + for (Parameter parameter : parameters) { + if (parameter.getDirection() != ParameterDirectionKind.RETURN_LITERAL) { + mi.addParameterType(CppParameter.CppParameterForCDT(parameter).toString()); + } + } + } + return mi; + } } diff --git a/extraplugins/codegen/org.eclipse.papyrus.cpp.codegen/src/org/eclipse/papyrus/cpp/codegen/utils/Modifier.java b/extraplugins/codegen/org.eclipse.papyrus.cpp.codegen/src/org/eclipse/papyrus/cpp/codegen/utils/Modifier.java index d7e83cb6cbc..981b4d328e7 100644 --- a/extraplugins/codegen/org.eclipse.papyrus.cpp.codegen/src/org/eclipse/papyrus/cpp/codegen/utils/Modifier.java +++ b/extraplugins/codegen/org.eclipse.papyrus.cpp.codegen/src/org/eclipse/papyrus/cpp/codegen/utils/Modifier.java @@ -15,6 +15,7 @@ import org.eclipse.papyrus.C_Cpp.Array; import org.eclipse.papyrus.C_Cpp.Const; 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.base.GenUtils; import org.eclipse.papyrus.cpp.codegen.preferences.CppCodeGenUtils; @@ -27,133 +28,153 @@ import org.eclipse.uml2.uml.ParameterDirectionKind; import org.eclipse.uml2.uml.Property; import org.eclipse.uml2.uml.util.UMLUtil; - /** - * Utility functions managing the "modifier" of an element, i.e. additional information whether a passed - * parameter or an attribute is a pointer, a reference, an array or constant. + * Utility functions managing the "modifier" of an element, i.e. additional + * information whether a passed parameter or an attribute is a pointer, a + * reference, an array or constant. * * @author ansgar * */ public class Modifier { - public static String ptr; - - public static String ref; - - public static String array; - - public static String cvQualifier; - public static String modPtr(Element propertyOrParameter) { - update(propertyOrParameter); - return ptr; - } - - public static String modRef(Element propertyOrParameter) { - update(propertyOrParameter); - return ref; - } - - public static String modArray(Element propertyOrParameter) { - update(propertyOrParameter); - return array; - } - - public static String modCVQualifier(Element propertyOrParameter) { - update(propertyOrParameter); - return cvQualifier; - } - - /** - * Create instance and initialize the ptr/ref/array/isConst attributes. - * - * @param propertyOperationOrParameter - */ - public static void update(Element propertyOperationOrParameter) { - // Pointer - Ptr cppPtr = UMLUtil.getStereotypeApplication(propertyOperationOrParameter, Ptr.class); + String ptr = ""; //$NON-NLS-1$ + Ptr cppPtr = UMLUtil.getStereotypeApplication(propertyOrParameter, Ptr.class); if (cppPtr != null) { ptr = (cppPtr.getDeclaration() != null) ? cppPtr.getDeclaration() : "*"; //$NON-NLS-1$ } else { ptr = ""; //$NON-NLS-1$ } - if (propertyOperationOrParameter instanceof Property) { - if (((Property) propertyOperationOrParameter).getAggregation() == AggregationKind.SHARED_LITERAL) { + if (propertyOrParameter instanceof Property) { + if (((Property) propertyOrParameter).getAggregation() == AggregationKind.SHARED_LITERAL) { ptr += "*"; //$NON-NLS-1$ } } + boolean ptrOrRef = GenUtils.hasStereotype(propertyOrParameter, Ref.class) + || GenUtils.hasStereotype(propertyOrParameter, Ptr.class); + + // out and inout parameter are realized by means of a pointer + if (propertyOrParameter instanceof Parameter) { + ParameterDirectionKind directionKind = ((Parameter) propertyOrParameter).getDirection(); + if (directionKind == ParameterDirectionKind.OUT_LITERAL || directionKind == ParameterDirectionKind.INOUT_LITERAL) { + // parameter is an out or inout parameter. If the user already either a pointer or reference, use this. + if (!ptrOrRef) { + // .. otherwise add the oeprator from the preferences + ptr += CppCodeGenUtils.getOutInoutOp(); + } + } + } + return ptr; + } + + public static String modRef(Element propertyOrParameter) { // Ref - ref = GenUtils.hasStereotype(propertyOperationOrParameter, Ref.class) ? "&" : ""; //$NON-NLS-1$ //$NON-NLS-2$ - boolean ptrOrRef = GenUtils.hasStereotype(propertyOperationOrParameter, Ref.class) || - GenUtils.hasStereotype(propertyOperationOrParameter, Ptr.class); + return GenUtils.hasStereotype(propertyOrParameter, Ref.class) ? "&" : ""; //$NON-NLS-1$ //$NON-NLS-2$ + } + public static String modArray(Element propertyOrParameter) { // Array - Array cppArray = UMLUtil.getStereotypeApplication(propertyOperationOrParameter, Array.class); + Array cppArray = UMLUtil.getStereotypeApplication(propertyOrParameter, Array.class); + String array = ""; //$NON-NLS-1$ if (cppArray != null) { // explicit array definition array = (cppArray.getDefinition() != null) ? cppArray.getDefinition() : "[]"; //$NON-NLS-1$ } else { // calculate array from multiplicity definition int multiplicity = 1; - if (propertyOperationOrParameter instanceof MultiplicityElement) { - multiplicity = ((MultiplicityElement) propertyOperationOrParameter).getUpper(); + if (propertyOrParameter instanceof MultiplicityElement) { + multiplicity = ((MultiplicityElement) propertyOrParameter).getUpper(); } array = ""; //$NON-NLS-1$ if (multiplicity == -1) { - ptr += "*"; //$NON-NLS-1$ + array = "[]"; //$NON-NLS-1$ } else if (multiplicity > 1) { array = "[" + multiplicity + "]"; //$NON-NLS-1$ //$NON-NLS-2$ } } + return array; + } - // out an inout parameter are realized by means of a pointer - if (propertyOperationOrParameter instanceof Parameter) { - ParameterDirectionKind directionKind = ((Parameter) propertyOperationOrParameter).getDirection(); - if (directionKind == ParameterDirectionKind.IN_LITERAL) { - ptr += " /*in*/"; //$NON-NLS-1$ - } - else if (directionKind == ParameterDirectionKind.OUT_LITERAL) { - ptr += " /*out*/"; //$NON-NLS-1$ - if (!ptrOrRef) { - ptr += CppCodeGenUtils.getOutInoutOp(); - } - } - else if (directionKind == ParameterDirectionKind.INOUT_LITERAL) { - ptr += " /*inout*/"; //$NON-NLS-1$ - if (!ptrOrRef) { - ptr += CppCodeGenUtils.getOutInoutOp(); - } - } - } - + /** + * return modifier for const and volatile + * @param propertyOrParameter + * @return + */ + public static String modCVQualifier(Element propertyOrParameter) { + String cvQualifier = ""; //$NON-NLS-1$ // CVQualifiers cannot be used with static functions - if (propertyOperationOrParameter instanceof Operation - && ((Operation) propertyOperationOrParameter).isStatic()) { - cvQualifier = new String(); + if (propertyOrParameter instanceof Operation && ((Operation) propertyOrParameter).isStatic()) { + // do nothing } // Const - else if (GenUtils.hasStereotype(propertyOperationOrParameter, Const.class)) { + else if (GenUtils.hasStereotype(propertyOrParameter, Const.class)) { // Volatile with const - if (GenUtils.hasStereotype(propertyOperationOrParameter, Volatile.class)) { - cvQualifier = (propertyOperationOrParameter instanceof Operation) ? " const volatile" : // added at the end of operation, prefix with " " //$NON-NLS-1$ - "const volatile "; // before operation or parameter, postfix with " " //$NON-NLS-1$ + if (GenUtils.hasStereotype(propertyOrParameter, Volatile.class)) { + cvQualifier = (propertyOrParameter instanceof Operation) ? " const volatile" //$NON-NLS-1$ + : // added at the end of operation, prefix with " " + "const volatile "; // before operation or //$NON-NLS-1$ + // parameter, postfix with " " } // Const without Volatile else { - cvQualifier = (propertyOperationOrParameter instanceof Operation) ? " const" : // added at the end of operation, prefix with " " //$NON-NLS-1$ - "const "; // before operation or parameter, postfix with " " //$NON-NLS-1$ + cvQualifier = (propertyOrParameter instanceof Operation) ? " const" //$NON-NLS-1$ + : // added at the end of operation, prefix with " " + "const "; // before operation or //$NON-NLS-1$ + // parameter, postfix with " " } } // Volatile without const - else if (GenUtils.hasStereotype(propertyOperationOrParameter, Volatile.class)) { - cvQualifier = (propertyOperationOrParameter instanceof Operation) ? " volatile" : // added at the end of operation, prefix with " " //$NON-NLS-1$ - "volatile "; // before operation or parameter, postfix with " " //$NON-NLS-1$ + else if (GenUtils.hasStereotype(propertyOrParameter, Volatile.class)) { + cvQualifier = (propertyOrParameter instanceof Operation) ? " volatile" //$NON-NLS-1$ + : // added at the end of operation, prefix with " " + "volatile "; // before operation or parameter, //$NON-NLS-1$ + // postfix with " " } - // No CV qualifiers - else { - cvQualifier = ""; //$NON-NLS-1$ + return cvQualifier; + } + + /** + * return modifier for storage class + * @param propertyOrParameter + * @return + */ + public static String modSCQualifier(Element propertyOrParameter) { + StorageClass sc = UMLUtil.getStereotypeApplication(propertyOrParameter, StorageClass.class); + if (sc != null) { + return sc.getStorageClass().getLiteral() + " "; //$NON-NLS-1$ } + return ""; //$NON-NLS-1$ + } + + /** + * Return inform about the direction of a parameter in form of a comment + * + * @param propertyOperationOrParameter + * @return + */ + public static String dirInfo(Element propertyOperationOrParameter) { + if (propertyOperationOrParameter instanceof Parameter) { + ParameterDirectionKind directionKind = ((Parameter) propertyOperationOrParameter).getDirection(); + if (directionKind == ParameterDirectionKind.IN_LITERAL) { + return " /*in*/"; //$NON-NLS-1$ + } else if (directionKind == ParameterDirectionKind.OUT_LITERAL) { + return " /*out*/"; //$NON-NLS-1$ + } else if (directionKind == ParameterDirectionKind.INOUT_LITERAL) { + return " /*inout*/"; //$NON-NLS-1$ + } + } + return ""; //$NON-NLS-1$ + } + + /** + * initialize the ptr/ref/array/isConst attributes. + * + * @param propertyOperationOrParameter + */ + public static void update(Element propertyOperationOrParameter) { + + } } diff --git a/extraplugins/codegen/org.eclipse.papyrus.cpp.codegen/src/org/eclipse/papyrus/cpp/codegen/xtend/CppParameter.xtend b/extraplugins/codegen/org.eclipse.papyrus.cpp.codegen/src/org/eclipse/papyrus/cpp/codegen/xtend/CppParameter.xtend index 2682871de4b..160265df9b8 100644 --- a/extraplugins/codegen/org.eclipse.papyrus.cpp.codegen/src/org/eclipse/papyrus/cpp/codegen/xtend/CppParameter.xtend +++ b/extraplugins/codegen/org.eclipse.papyrus.cpp.codegen/src/org/eclipse/papyrus/cpp/codegen/xtend/CppParameter.xtend @@ -17,6 +17,8 @@ import org.eclipse.papyrus.cpp.codegen.utils.Modifier import org.eclipse.papyrus.cpp.codegen.utils.CppGenUtils import org.eclipse.uml2.uml.ParameterDirectionKind import org.eclipse.uml2.uml.Behavior +import org.eclipse.papyrus.C_Cpp.Array +import org.eclipse.uml2.uml.util.UMLUtil /** * @author Önder GÜRCAN (onder.gurcan@cea.fr) @@ -37,9 +39,23 @@ class CppParameter { * C++ parameter. Default values are added, if parameter showDefault is true (implementation signature */ static def CppParameter(Parameter parameter, boolean showDefault) { - Modifier.modCVQualifier(parameter)+CppGenUtils.cppQualifiedName(parameter.type)+Modifier.modPtr(parameter)+Modifier.modRef(parameter)+" "+parameter.name + Modifier.modArray(parameter) + {if (showDefault) defaultValue(parameter) else ""} + Modifier.modCVQualifier(parameter) + Modifier.modSCQualifier(parameter) + CppGenUtils.cppQualifiedName(parameter.type) + + Modifier.modPtr(parameter) + Modifier.modRef(parameter) + Modifier.dirInfo(parameter) + " " + parameter.name + + Modifier.modArray(parameter) + {if (showDefault) defaultValue(parameter) else ""} } + /** + * CppParameterCalculation for CDT + */ + static def CppParameterForCDT(Parameter parameter) { + var paramStr = Modifier.modCVQualifier(parameter) + Modifier.modSCQualifier(parameter) + CppGenUtils.cppQualifiedName(parameter.type) + + Modifier.modPtr(parameter) + Modifier.modRef(parameter) + if (UMLUtil.getStereotypeApplication(parameter, Array) != null) { + paramStr += "[]" + } + return paramStr + } + static def defaultValue(Parameter parameter) { if (parameter.defaultValue != null) " = " + parameter.defaultValue.stringValue() else "" } diff --git a/extraplugins/codegen/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/editor/PapyrusCDTEditor.java b/extraplugins/codegen/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/editor/PapyrusCDTEditor.java index dee8abaf9cf..4ae37530cac 100644 --- a/extraplugins/codegen/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/editor/PapyrusCDTEditor.java +++ b/extraplugins/codegen/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/editor/PapyrusCDTEditor.java @@ -293,14 +293,11 @@ public class PapyrusCDTEditor extends CEditor { * @throws CoreException
*/
public void gotoElement(NamedElement element) {
- // IFile srcFile = SyncModelToCDT.syncModelToCDT((Classifier) pe);
- // ITranslationUnit itu2 = (ITranslationUnit) CoreModel.getDefault().create(srcFile);
-
ICElement ice = CDTUITools.getEditorInputCElement(m_input);
if (ice instanceof ITranslationUnit) {
ITranslationUnit itu = (ITranslationUnit) ice;
- ICElement icElement = ObtainICElement.getICElement(itu, element);
+ ICElement icElement = ObtainICElement.getICElement(syncCpp.getCodeGen(), itu, element);
if (icElement instanceof ISourceReference) {
try {
ISourceRange range = ((ISourceReference) icElement).getSourceRange();
@@ -386,9 +383,6 @@ public class PapyrusCDTEditor extends CEditor { protected IAction textUndo, textRedo;
- // TODO: remove, unused
- protected IActionBars gmfActionBars, textActionBars;
-
protected boolean oldDirty;
protected ISaveAndDirtyService saveAndDirtyService;
diff --git a/extraplugins/codegen/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/sync/FindTransition.java b/extraplugins/codegen/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/sync/FindTransition.java index 8db8ecfb4c0..e737e45abf3 100644 --- a/extraplugins/codegen/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/sync/FindTransition.java +++ b/extraplugins/codegen/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/sync/FindTransition.java @@ -1,3 +1,15 @@ +/******************************************************************************* + * 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; @@ -6,6 +18,10 @@ 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$ diff --git a/extraplugins/codegen/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/sync/ObtainICElement.java b/extraplugins/codegen/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/sync/ObtainICElement.java index 0fdcf395ecb..e5457380c45 100644 --- a/extraplugins/codegen/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/sync/ObtainICElement.java +++ b/extraplugins/codegen/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/sync/ObtainICElement.java @@ -12,11 +12,17 @@ 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; @@ -41,32 +47,61 @@ public class ObtainICElement { * A named UML element * @throws CoreException */ - public static ICElement getICElement(IParent parent, NamedElement element) { + 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((IParent) child, element); + return getICElement(codegen, (IParent) child, element); } if (child instanceof IFunctionDeclaration) { IFunctionDeclaration function = (IFunctionDeclaration) child; - - if (element instanceof Operation) { - if (child.getElementName().endsWith(NamedElement.SEPARATOR + element.getName())) { - // check, if number of parameter matches. TODO: this only handles a part of possible overloading cases - if (function.getNumberOfParameters() == countParameters(((Operation) element).getOwnedParameters())) { - return child; - } - } - } - else if (element instanceof Transition) { - Transition transition = (Transition) element; - if (transition.getEffect() != null) { - if (FindTransition.behaviorMatches(transition.getEffect(), child.getElementName())) { - - if (function.getNumberOfParameters() == countParameters(transition.getEffect().getOwnedParameters())) { - return 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; + } } } } diff --git a/extraplugins/codegen/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/sync/SyncCDTtoModel.java b/extraplugins/codegen/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/sync/SyncCDTtoModel.java index c25b00ef4b0..53b5aa2c6ac 100644 --- a/extraplugins/codegen/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/sync/SyncCDTtoModel.java +++ b/extraplugins/codegen/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/sync/SyncCDTtoModel.java @@ -44,11 +44,14 @@ 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; @@ -75,6 +78,12 @@ 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$ @@ -171,9 +180,13 @@ public class SyncCDTtoModel implements Runnable { if (node instanceof IASTFunctionDefinition) { IASTFunctionDefinition definition = (IASTFunctionDefinition) node; IASTFunctionDeclarator declarator = definition.getDeclarator(); - String body = getBody(itu, definition); + String unfilteredBody = getBody(itu, definition); // get additional information about method synchronization from generator - SyncInformation syncInfo = m_codegen.getSyncInformation(name, body); + 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); @@ -317,6 +330,7 @@ public class SyncCDTtoModel implements Runnable { IASTDeclSpecifier parameterType = parameter.getDeclSpecifier(); boolean isPointer = false; boolean isRef = false; + boolean isRegister = false; String array = ""; //$NON-NLS-1$ String parameterTypeName = ""; //$NON-NLS-1$ try { @@ -348,9 +362,10 @@ public class SyncCDTtoModel implements Runnable { isPointer = true; } else if (tokenStr.equals("&")) { //$NON-NLS-1$ isRef = true; - } else if (tokenStr.equals("const")) { //$NON-NLS-1$ - // do nothing (use isConst() operation of - // parameterType) + } else if (tokenStr.equals(REGISTER)) { + 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) { @@ -383,6 +398,12 @@ public class SyncCDTtoModel implements Runnable { if (parameterType.isVolatile()) { StereotypeUtil.apply(umlParameter, Volatile.class); } + if (isRegister) { + StorageClass sc = StereotypeUtil.applyApp(umlParameter, StorageClass.class); + if (sc != null) { + sc.setStorageClass(EStorageClass.REGISTER); + } + } if (isPointer) { StereotypeUtil.apply(umlParameter, Ptr.class); } else if (isRef) { @@ -394,7 +415,6 @@ public class SyncCDTtoModel implements Runnable { arraySt.setDefinition(array); } } - } } @@ -481,8 +501,7 @@ public class SyncCDTtoModel implements Runnable { // cannot use the // first and last statement, since leading and trailing comments are // not part of the AST tree. - String bodyStr = Utils.decreaseIndent(contents, start + 2, end - 2); - return Utils.removeGenerated(bodyStr); + return Utils.decreaseIndent(contents, start + 2, end - 2); } return ""; //$NON-NLS-1$ } @@ -578,6 +597,14 @@ public class SyncCDTtoModel implements Runnable { } /** + * 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; diff --git a/extraplugins/codegen/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/sync/SyncModelToCDT.java b/extraplugins/codegen/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/sync/SyncModelToCDT.java index 50a2af1c0ff..207dfa013c9 100644 --- a/extraplugins/codegen/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/sync/SyncModelToCDT.java +++ b/extraplugins/codegen/org.eclipse.papyrus.texteditor.cdt/src/org/eclipse/papyrus/texteditor/cdt/sync/SyncModelToCDT.java @@ -20,6 +20,7 @@ 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; @@ -34,6 +35,7 @@ import org.eclipse.uml2.uml.Classifier; */ 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 */ @@ -56,7 +58,10 @@ public class SyncModelToCDT { try { codegen.generateCode(modelProject, classifier, null); // need listener for sync in both directions! - cppFile = modelProject.getFile(new Path(codegen.getFileName(modelProject, classifier) + Constants.DOT + codegen.getSuffix(FILE_KIND.BODY))); + 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 { |