diff options
7 files changed, 713 insertions, 36 deletions
diff --git a/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.cpp.codegen.ui/src/org/eclipse/papyrus/cpp/codegen/ui/handlers/GenerateCodeHandler.java b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.cpp.codegen.ui/src/org/eclipse/papyrus/cpp/codegen/ui/handlers/GenerateCodeHandler.java index 8755e9c615c..81e523587e0 100644 --- a/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.cpp.codegen.ui/src/org/eclipse/papyrus/cpp/codegen/ui/handlers/GenerateCodeHandler.java +++ b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.cpp.codegen.ui/src/org/eclipse/papyrus/cpp/codegen/ui/handlers/GenerateCodeHandler.java @@ -86,7 +86,8 @@ public class GenerateCodeHandler extends CmdHandler { // add required classifiers if (pe instanceof Classifier) { - EList<Classifier> requiredClassifiers = ClassUtils.includedClassifiers((Classifier) pe); + EList<Classifier> requiredClassifiers = ClassUtils.requiredClassifiers((Classifier) pe); + for (Classifier requiredClassifier : requiredClassifiers) { if (!alreadyHandled.contains(requiredClassifier)) { generate(mec, requiredClassifier, alreadyHandled, false); diff --git a/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.cpp.codegen/src/org/eclipse/papyrus/cpp/codegen/utils/ClassUtils.java b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.cpp.codegen/src/org/eclipse/papyrus/cpp/codegen/utils/ClassUtils.java index 7653753411f..6450635c0f6 100644 --- a/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.cpp.codegen/src/org/eclipse/papyrus/cpp/codegen/utils/ClassUtils.java +++ b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.cpp.codegen/src/org/eclipse/papyrus/cpp/codegen/utils/ClassUtils.java @@ -11,14 +11,24 @@ package org.eclipse.papyrus.cpp.codegen.utils; +import java.util.List; + +import org.eclipse.emf.common.util.BasicEList; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.common.util.UniqueEList; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.papyrus.C_Cpp.Inline; +import org.eclipse.papyrus.C_Cpp.NoCodeGen; +import org.eclipse.papyrus.C_Cpp.Ptr; +import org.eclipse.papyrus.C_Cpp.Ref; import org.eclipse.papyrus.codegen.base.GenUtils; -import org.eclipse.uml2.uml.Class; import org.eclipse.uml2.uml.Classifier; import org.eclipse.uml2.uml.Element; +import org.eclipse.uml2.uml.Enumeration; import org.eclipse.uml2.uml.Interface; import org.eclipse.uml2.uml.Operation; +import org.eclipse.uml2.uml.Package; +import org.eclipse.uml2.uml.PrimitiveType; /** * A set of utility functions related to classes. @@ -27,27 +37,83 @@ import org.eclipse.uml2.uml.Operation; * */ public class ClassUtils { - /** - * Calculate the list of classifiers that needs to be included + * Calculate the list of classifiers that are required by another classifier * * @param currentClass * @return */ - public static EList<Classifier> includedClassifiers(Classifier currentClass) { + public static EList<Classifier> requiredClassifiers(Classifier currentClass) { // Retrieve package used by current package (dependencies) // use a unique list to avoid duplicates EList<Classifier> usedClasses = new UniqueEList<Classifier>(); // class attributes dependencies - usedClasses.addAll(GenUtils.getOwnedAttributeTypes(currentClass)); + usedClasses.addAll(GenUtils.getTypesViaAttributes(currentClass)); // operation parameters dependencies usedClasses.addAll(GenUtils.getTypesViaOperations(currentClass)); // inner classifier dependencies usedClasses.addAll(GenUtils.getInnerClassifierTypes(currentClass)); // realized interface dependencies - if (currentClass instanceof Class) { - Class clazz = (Class) currentClass; + if (currentClass instanceof org.eclipse.uml2.uml.Class) { + org.eclipse.uml2.uml.Class clazz = (org.eclipse.uml2.uml.Class) currentClass; + EList<Interface> implementedInterfaces = clazz.getImplementedInterfaces(); + usedClasses.addAll(implementedInterfaces); + } + // dependencies and associations + usedClasses.addAll(GenUtils.getTypesViaRelationshipsNoDeps(currentClass)); + + // template parameters are declared locally (if owned) and do not correspond to a file + // that can be included + usedClasses.removeAll(GenUtils.getTemplateParameteredElements(currentClass)); + return usedClasses; + } + + /** + * Calculate the list of classifiers that needs to be included in a header file + * + * @param currentClass + * @return + */ + public static EList<Classifier> includedClassifiers(Classifier currentClass) { + // Retrieve package used by current package (dependencies) + // use a unique list to avoid duplicates + EList<Classifier> usedClasses = new UniqueEList<Classifier>(); + + // Lists of excluded/included stereotypes + EList<Class<? extends EObject>> ptrRefStereotypes = new BasicEList<Class<? extends EObject>>(); + ptrRefStereotypes.add(Ptr.class); + ptrRefStereotypes.add(Ref.class); + + EList<Class<? extends EObject>> noCodeGenInlineStereotypes = new BasicEList<Class<? extends EObject>>(); + noCodeGenInlineStereotypes.add(NoCodeGen.class); + noCodeGenInlineStereotypes.add(Inline.class); + + EList<Class<? extends EObject>> inlineStereotypes = new BasicEList<Class<? extends EObject>>(); + inlineStereotypes.add(Inline.class); + + EList<Class<? extends EObject>> noCodeGenStereotypes = new BasicEList<Class<? extends EObject>>(); + noCodeGenStereotypes.add(NoCodeGen.class); + + // class attributes dependencies (non-ptr and non-ref) + usedClasses.addAll(GenUtils.getTypesViaAttributes(currentClass, ptrRefStereotypes, null, true)); + addEnumerationsAndPrimitiveTypes(usedClasses, GenUtils.getTypesViaAttributes(currentClass)); + + // class inline operation parameters dependencies (non-ptr and non-ref) + usedClasses.addAll(GenUtils.getTypesViaOperations(currentClass, noCodeGenStereotypes, inlineStereotypes, ptrRefStereotypes, null, true)); + addEnumerationsAndPrimitiveTypes(usedClasses, GenUtils.getTypesViaOperations(currentClass)); + + // inner classifier attribute dependencies (non-ptr and non-ref) + usedClasses.addAll(GenUtils.getInnerClassifierTypesViaAttributes(currentClass, ptrRefStereotypes, null, true)); + addEnumerationsAndPrimitiveTypes(usedClasses, GenUtils.getInnerClassifierTypesViaAttributes(currentClass)); + + // inner classifier operation parameters dependencies (non-ptr and non-ref) + usedClasses.addAll(GenUtils.getInnerClassifierTypesViaOperations(currentClass, noCodeGenStereotypes, inlineStereotypes, ptrRefStereotypes, null, true)); + addEnumerationsAndPrimitiveTypes(usedClasses, GenUtils.getInnerClassifierTypesViaOperations(currentClass)); + + // realized interface dependencies + if (currentClass instanceof org.eclipse.uml2.uml.Class) { + org.eclipse.uml2.uml.Class clazz = (org.eclipse.uml2.uml.Class) currentClass; EList<Interface> implementedInterfaces = clazz.getImplementedInterfaces(); usedClasses.addAll(implementedInterfaces); } @@ -61,6 +127,118 @@ public class ClassUtils { } /** + * Calculate the list of classifiers that needs to be included in a body file + * + * @param currentClass + * @return + */ + public static EList<Classifier> includedImplementationClassifiers(Classifier currentClass) { + EList<Classifier> usedClasses = new UniqueEList<Classifier>(); + + // List of excluded/included stereotypes + EList<Class<? extends EObject>> ptrRefStereotypes = new BasicEList<Class<? extends EObject>>(); + ptrRefStereotypes.add(Ptr.class); + ptrRefStereotypes.add(Ref.class); + + EList<Class<? extends EObject>> noCodeGenInlineStereotypes = new BasicEList<Class<? extends EObject>>(); + noCodeGenInlineStereotypes.add(NoCodeGen.class); + noCodeGenInlineStereotypes.add(Inline.class); + + // operation parameter dependencies (non-ptr and non-ref) + usedClasses.addAll(GenUtils.getTypesViaOperations(currentClass, noCodeGenInlineStereotypes, null, ptrRefStereotypes, null, true)); + addEnumerationsAndPrimitiveTypes(usedClasses, GenUtils.getTypesViaOperations(currentClass)); + + // opaque behavior (no-specification) parameter dependencies (non-ptr and non-ref) + usedClasses.addAll(GenUtils.getTypesViaOpaqueBehaviors(currentClass, null, null, ptrRefStereotypes, null, true)); // TODO some excluded/included stereotypes for opaque behavior once bug on "noCodeGen" is fixed + addEnumerationsAndPrimitiveTypes(usedClasses, GenUtils.getTypesViaOpaqueBehaviors(currentClass)); + + // inner classifier operation parameter dependencies (non-ptr and non-ref) + usedClasses.addAll(GenUtils.getInnerClassifierTypesViaOperations(currentClass, noCodeGenInlineStereotypes, null, ptrRefStereotypes, null, true)); + addEnumerationsAndPrimitiveTypes(usedClasses, GenUtils.getInnerClassifierTypesViaOperations(currentClass)); + + // inner classifier opaque behavior (no-specification) parameter dependencies (non-ptr and non-ref) + usedClasses.addAll(GenUtils.getInnerClassifierTypesViaOpaqueBehaviors(currentClass, null, null, ptrRefStereotypes, null, true)); // TODO some excluded/included stereotypes for opaque behavior once bug on "noCodeGen" is fixed + addEnumerationsAndPrimitiveTypes(usedClasses, GenUtils.getInnerClassifierTypesViaOpaqueBehaviors(currentClass)); + + // dependency relationships + usedClasses.addAll(GenUtils.getTypesViaDependencies(currentClass)); + + // template parameters are declared locally (if owned) and do not correspond to a file + // that can be included + usedClasses.removeAll(GenUtils.getTemplateParameteredElements(currentClass)); + return usedClasses; + } + + private static void addEnumerationsAndPrimitiveTypes(List<Classifier> usedClasses, List<Classifier> unfilteredClasses) { + if (usedClasses != null && unfilteredClasses != null) { + for (Classifier classifier : unfilteredClasses) { + if ((classifier instanceof Enumeration) || (classifier instanceof PrimitiveType)) { + if (classifier.getOwner() instanceof Package) { + usedClasses.add(classifier); + } + } + } + } + + } + + /** + * Calculate the list of classifiers that needs to be declared in a header file + * + * @param currentClass + * @return + */ + public static EList<Classifier> declaredClassifiers(Classifier currentClass) { + EList<Classifier> usedClasses = new UniqueEList<Classifier>(); + + // List of excluded/included stereotypes + EList<Class<? extends EObject>> ptrRefStereotypes = new BasicEList<Class<? extends EObject>>(); + ptrRefStereotypes.add(Ptr.class); + ptrRefStereotypes.add(Ref.class); + + EList<Class<? extends EObject>> inlineStereotypes = new BasicEList<Class<? extends EObject>>(); + inlineStereotypes.add(Inline.class); + + EList<Class<? extends EObject>> noCodeGenStereotypes = new BasicEList<Class<? extends EObject>>(); + noCodeGenStereotypes.add(NoCodeGen.class); + + // class attributes dependencies (only ptr and ref) + usedClasses.addAll(GenUtils.getTypesViaAttributes(currentClass, null, ptrRefStereotypes, true)); + // operation parameters dependencies + usedClasses.addAll(GenUtils.getTypesViaOperations(currentClass)); + usedClasses.removeAll(GenUtils.getTypesViaOperations(currentClass, noCodeGenStereotypes, inlineStereotypes, ptrRefStereotypes, null, false)); // Remove inline operation parameter types that have been included previously + // no-specification opaque behavior dependencies + usedClasses.addAll(GenUtils.getTypesViaOpaqueBehaviors(currentClass)); + + // inner classifier attribute dependencies (only ptr and ref) + usedClasses.addAll(GenUtils.getInnerClassifierTypesViaAttributes(currentClass, null, ptrRefStereotypes, false)); + // inner classifier parameters dependencies + usedClasses.addAll(GenUtils.getInnerClassifierTypesViaOperations(currentClass)); + usedClasses.removeAll(GenUtils.getInnerClassifierTypesViaOperations(currentClass, noCodeGenStereotypes, inlineStereotypes, ptrRefStereotypes, null, false)); // Remove inner classifier inline operation parameter types that have been included previously + // inner classifier no-specification opaque behavior dependencies + usedClasses.addAll(GenUtils.getInnerClassifierTypesViaOpaqueBehaviors(currentClass)); + + // TODO inline operation body dependencies: how? + + // template parameters are declared locally (if owned) and do not correspond to a file + // that can be included + usedClasses.removeAll(GenUtils.getTemplateParameteredElements(currentClass)); + + // Remove enumerations and primitive types + List<Classifier> enumerationsAndPrimitiveTypes = new UniqueEList<Classifier>(); + for (Classifier classifier : usedClasses) { + if ((classifier instanceof Enumeration) || (classifier instanceof PrimitiveType)) { + if (classifier.getOwner() instanceof Package) { + enumerationsAndPrimitiveTypes.add(classifier); + } + } + } + usedClasses.removeAll(enumerationsAndPrimitiveTypes); + + return usedClasses; + } + + /** * Retrieve the list of operations of classes nested in the current class * without the operations directly owned by the current class * diff --git a/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.cpp.codegen/src/org/eclipse/papyrus/cpp/codegen/utils/CppGenUtils.java b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.cpp.codegen/src/org/eclipse/papyrus/cpp/codegen/utils/CppGenUtils.java index 36043a363ad..f907e9af896 100644 --- a/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.cpp.codegen/src/org/eclipse/papyrus/cpp/codegen/utils/CppGenUtils.java +++ b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.cpp.codegen/src/org/eclipse/papyrus/cpp/codegen/utils/CppGenUtils.java @@ -269,6 +269,27 @@ public class CppGenUtils { } return openNS; } + + /** + * Return a C++ open-namespace definition for a named element, without spaces and line breaks + * + * @param ne + * a named element + * @return a C++ open-namespace definition for a named element, without spaces and line breaks + */ + public static String openNSMinimal(NamedElement ne) { + String openNS = ""; //$NON-NLS-1$ + currentNS = ne.getNamespace(); + if (ne instanceof Package) { + openNS = "namespace " + ne.getName() + " {"; //$NON-NLS-1$ //$NON-NLS-2$ + } + for (Namespace ns : ne.allNamespaces()) { + if (ns.getOwner() != null) { // skip top-level package (useful?) + openNS = "namespace " + ns.getName() + " {" + openNS; //$NON-NLS-1$ //$NON-NLS-2$ + } + } + return openNS; + } /** @@ -290,6 +311,26 @@ public class CppGenUtils { } return closeNS; } + + /** + * Return a C++ close-namespace definition for a named element, without spaces and line breaks + * + * @param ne + * a named element + * @return a C++ close-namespace definition for a named element, without spaces and line breaks + */ + public static String closeNSMinimal(NamedElement ne) { + String closeNS = ""; //$NON-NLS-1$ + if (ne instanceof Package) { + closeNS = "}"; //$NON-NLS-1$ //$NON-NLS-2$ + } + for (Namespace ns : ne.allNamespaces()) { + if (ns.getOwner() != null) { + closeNS += "}"; //$NON-NLS-1$ //$NON-NLS-2$ + } + } + return closeNS; + } /** diff --git a/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.cpp.codegen/src/org/eclipse/papyrus/cpp/codegen/xtend/CppClassIncludeClassDeclaration.xtend b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.cpp.codegen/src/org/eclipse/papyrus/cpp/codegen/xtend/CppClassIncludeClassDeclaration.xtend index ab952f290cb..c41218e8dae 100644 --- a/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.cpp.codegen/src/org/eclipse/papyrus/cpp/codegen/xtend/CppClassIncludeClassDeclaration.xtend +++ b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.cpp.codegen/src/org/eclipse/papyrus/cpp/codegen/xtend/CppClassIncludeClassDeclaration.xtend @@ -23,6 +23,9 @@ import java.util.List import java.util.ArrayList import org.eclipse.papyrus.cpp.codegen.utils.ClassUtils import org.eclipse.papyrus.codegen.base.GenUtils +import org.eclipse.uml2.uml.DataType +import org.eclipse.uml2.uml.UMLFactory +import org.eclipse.papyrus.cpp.codegen.utils.CppGenUtils /** * @author Önder GÜRCAN (onder.gurcan@cea.fr) @@ -37,8 +40,8 @@ class CppClassIncludeClassDeclaration { } } - static def CppClassAllIncludesDeclarationBody(Classifier classifier) { - cppClassAllIncludes(classifier, GenUtils.getTypesViaDependencies(classifier)) + static def CppClassAllIncludesDeclarationBody(Classifier classifier) { + cppClassAllIncludes(classifier, ClassUtils.includedImplementationClassifiers(classifier)) } static def cppClassAllIncludes(Classifier classifier, EList<Classifier> list) { @@ -47,7 +50,10 @@ class CppClassIncludeClassDeclaration { //var String str = null if ((cl != classifier) && (!GenUtils.hasStereotype(cl, NoCodeGen)) || (GenUtils.hasStereotype(cl, External))) { if ((cl instanceof Enumeration) || (cl instanceof PrimitiveType)) { - if ((cl.owner != null) && (cl.owner instanceof Package)) { + if (cl.owner instanceof Package && cl.owner != classifier.owner) { + /* Enum and Primitive must not be in same package as classifier since + we always enums and primitives are defined in the package header which + is always included in the classifier header */ var includePath = (cl.owner as Package).cppOwnerPackageIncludePath if (!newList.contains(includePath)) newList.add(includePath) } else { @@ -63,7 +69,43 @@ class CppClassIncludeClassDeclaration { return newList.filter[str | str != null] } + static def cppClassAllDeclares(Classifier classifier, EList<Classifier> declaredClassifiers, EList<Classifier> includedClassifiers) { + var List<String> newList = new ArrayList<String>() + + if (declaredClassifiers != null) { + if (includedClassifiers != null) { + declaredClassifiers.removeAll(includedClassifiers) + } + + for (cl : declaredClassifiers) { + if ((cl != classifier) && (!GenUtils.hasStereotype(cl, NoCodeGen)) || (GenUtils.hasStereotype(cl, External))) { + var declaration = ""; + + if ((cl instanceof Enumeration) || (cl instanceof PrimitiveType)) { + // Ignore + } else if (cl instanceof DataType) { + declaration = CppGenUtils.openNSMinimal(cl) + "struct " + cl.name + ";" + CppGenUtils.closeNSMinimal(cl); + } else if (cl.eClass.equals(UMLFactory.eINSTANCE.getUMLPackage().getClass_())) { + declaration = CppGenUtils.openNSMinimal(cl).replaceAll("\r", "").replaceAll("\n", "") + "class " + cl.name + ";" + CppGenUtils.closeNSMinimal(cl).replaceAll("\r", "").replaceAll("\n", ""); + } + + if (declaration != "") { + if (!newList.contains(declaration)) { + newList.add(declaration); + } + } + } + } + } + + return newList.filter[str | str != null] + } + static def CppClassAllIncludes(Classifier clazz) { cppClassAllIncludes(clazz, ClassUtils.includedClassifiers(clazz)) } + + static def CppClassAllDeclares(Classifier clazz) { + cppClassAllDeclares(clazz, ClassUtils.declaredClassifiers(clazz), ClassUtils.includedClassifiers(clazz)) + } }
\ No newline at end of file diff --git a/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.cpp.codegen/src/org/eclipse/papyrus/cpp/codegen/xtend/CppClassifierGenerator.xtend b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.cpp.codegen/src/org/eclipse/papyrus/cpp/codegen/xtend/CppClassifierGenerator.xtend index 41af9c68a4b..8148bde9e02 100644 --- a/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.cpp.codegen/src/org/eclipse/papyrus/cpp/codegen/xtend/CppClassifierGenerator.xtend +++ b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.cpp.codegen/src/org/eclipse/papyrus/cpp/codegen/xtend/CppClassifierGenerator.xtend @@ -36,10 +36,6 @@ class CppClassifierGenerator { «CppIncludeUtil.includeDirective(CppClassIncludeClassDeclaration.cppOwnerPackageIncludePath(classifier.package))» - «FOR path : getSortedIncludePathList(classifier)» - «CppIncludeUtil.includeDirective(path)» - «ENDFOR» - «CppIncludeUtil.CppIncludeHeader(classifier)» «var tb = GenUtils.getTemplateBinding(classifier)» @@ -48,6 +44,10 @@ class CppClassifierGenerator { GenUtils.getFullPath(classifier.package) + '/' + (templateElement.owner as NamedElement).name + '.' + CppCodeGenUtils.getHeaderSuffix())» + «FOR path : getSortedDeclarePathList(classifier)» + «CppIncludeUtil.declareDirective(path)» + «ENDFOR» + «CppGenUtils.openNS(classifier)» /************************************************************/ typedef «(templateElement.owner as NamedElement).name»<«FOR ps : tb.parameterSubstitutions SEPARATOR ', '»« @@ -66,6 +66,11 @@ class CppClassifierGenerator { var includePathList = CppClassIncludeClassDeclaration.CppClassAllIncludes(classifier).sort; return includePathList } + + static def getSortedDeclarePathList(Classifier classifier) { + var declarePathList = CppClassIncludeClassDeclaration.CppClassAllDeclares(classifier).sort; + return declarePathList + } static def generateBindBodyCode(Classifier classifier) ''' #define «GenUtils.getFullNameUC(classifier)»_BODY @@ -80,15 +85,16 @@ class CppClassifierGenerator { «CppIncludeUtil.includeDirective( GenUtils.getFullPath(classifier.package) + '/' + classifier.name + '.' + CppCodeGenUtils.getHeaderSuffix())» - «CppIncludeUtil.CppIncludeBody(classifier)» - - «CppGenUtils.openNS(classifier)» // Derived includes directives - «FOR path : CppClassIncludeClassDeclaration.CppClassAllIncludes(classifier).sort» + «FOR path : CppClassIncludeClassDeclaration.CppClassAllIncludesDeclarationBody(classifier).sort» «CppIncludeUtil.includeDirective(path)» «ENDFOR» + «CppIncludeUtil.CppIncludeBody(classifier)» + + «CppGenUtils.openNS(classifier)» + /************************************************************/ «var tb = GenUtils.getTemplateBinding(classifier)» «var templateElement = tb.targets.get(0)» @@ -112,12 +118,16 @@ class CppClassifierGenerator { «CppIncludeUtil.includeDirective(CppClassIncludeClassDeclaration.cppOwnerPackageIncludePath(classifier.package))» - «FOR path : getSortedIncludePathList(classifier)» + «FOR path : getSortedIncludePathList(classifier)» «CppIncludeUtil.includeDirective(path)» «ENDFOR» «CppIncludeUtil.CppIncludeHeader(classifier)» + «FOR path : getSortedDeclarePathList(classifier)» + «CppIncludeUtil.declareDirective(path)» + «ENDFOR» + «CppGenUtils.openNS(classifier)» /************************************************************/ diff --git a/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.cpp.codegen/src/org/eclipse/papyrus/cpp/codegen/xtend/CppIncludeUtil.xtend b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.cpp.codegen/src/org/eclipse/papyrus/cpp/codegen/xtend/CppIncludeUtil.xtend index c8623883fe1..8d3c4b1f90d 100644 --- a/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.cpp.codegen/src/org/eclipse/papyrus/cpp/codegen/xtend/CppIncludeUtil.xtend +++ b/extraplugins/qompass/codegen/cpp/org.eclipse.papyrus.cpp.codegen/src/org/eclipse/papyrus/cpp/codegen/xtend/CppIncludeUtil.xtend @@ -24,6 +24,12 @@ class CppIncludeUtil { if ((path != null) && (path.length > 0)) return '''#include ''' + '"' + path + '"' } + + static def declareDirective(String path) { + if ((path != null) && (path.length > 0)) { + return path + } + } static def CppIncludeHeader(NamedElement ne) { if (GenUtils.hasStereotype(ne, Include)) { diff --git a/extraplugins/qompass/codegen/org.eclipse.papyrus.codegen.base/src/org/eclipse/papyrus/codegen/base/GenUtils.java b/extraplugins/qompass/codegen/org.eclipse.papyrus.codegen.base/src/org/eclipse/papyrus/codegen/base/GenUtils.java index bf1304e37cb..426db4fe8de 100644 --- a/extraplugins/qompass/codegen/org.eclipse.papyrus.codegen.base/src/org/eclipse/papyrus/codegen/base/GenUtils.java +++ b/extraplugins/qompass/codegen/org.eclipse.papyrus.codegen.base/src/org/eclipse/papyrus/codegen/base/GenUtils.java @@ -36,6 +36,7 @@ import org.eclipse.uml2.uml.Package; import org.eclipse.uml2.uml.Parameter; import org.eclipse.uml2.uml.ParameterDirectionKind; import org.eclipse.uml2.uml.ParameterableElement; +import org.eclipse.uml2.uml.PrimitiveType; import org.eclipse.uml2.uml.Property; import org.eclipse.uml2.uml.TemplateBinding; import org.eclipse.uml2.uml.TemplateParameter; @@ -145,13 +146,13 @@ public class GenUtils { } /** - * Retrieve a list of types that belong to by a classifier in the current class + * Retrieve a list of types of attributes that belong to the current classifier. * * @param current * Class on which the attributes are searched - * @return collection of classes which are the type of the attributes + * @return Collection of classifiers which are the types of the attributes */ - public static EList<Classifier> getOwnedAttributeTypes(Classifier current) { + public static EList<Classifier> getTypesViaAttributes(Classifier current) { EList<Classifier> result = new UniqueEList<Classifier>(); Iterator<Property> attributes; @@ -163,32 +164,62 @@ public class GenUtils { } return result; } - + /** - * Retrieve a list of types that belong to by a classifier in the current class + * Retrieve a list of types of attributes that belong to the current classifier. Filter by stereotypes. * * @param current * Class on which the attributes are searched - * @return collection of classes which are the type of the attributes + * @param excludedStereotypes + * List of ALL stereotypes that must no be applied + * @param includedStereotypes + * List of ANY stereotype that must no be applied (at least one) + * @return Collection of classifiers which are the types of the attributes */ - public static EList<Classifier> getTypesViaAttributes(Classifier current) { + public static EList<Classifier> getTypesViaAttributes(Classifier current, EList<Class<? extends EObject>> excludedStereotypes, EList<Class<? extends EObject>> includedStereotypes, boolean bypassForInnerClassifiers) { EList<Classifier> result = new UniqueEList<Classifier>(); - for (Property currentAttribute : current.getAttributes()) { + Iterator<Property> attributes; + attributes = current.getAttributes().iterator(); + while (attributes.hasNext()) { + Property currentAttribute = attributes.next(); Type type = currentAttribute.getType(); - addFarthestOwnerType(type, result); + + if (type != null) { + if (bypassForInnerClassifiers && !(type.getOwner() instanceof Package)) { // if we force inner class types to be processed + addFarthestOwnerType(type, result); + } else { + // Check stereotypes + boolean ok = true; + if (excludedStereotypes != null && GenUtils.hasAnyStereotype(currentAttribute, excludedStereotypes)) { + ok = false; + } + if (ok) { + if (includedStereotypes != null && !GenUtils.hasAnyStereotype(currentAttribute, includedStereotypes)) { + ok = false; + } + } + + // All ok + if (ok) { + addFarthestOwnerType(type, result); + } + } + } } + return result; } - + /** - * Retrieve the operations in the current class. For each - * operation collected the classifier type. This class thus finds types, on + * Retrieve the operations in the current classifier. For each + * operation, collect types of its parameters. + * This method thus finds types, on * which the signature depends. * * @param current - * Class on which the attributes are searched - * @return collection of classes which are the types of the operations parameters + * Classifier on which the operations are searched for + * @return Collection of classifiers which are the types of the operation parameters */ public static EList<Classifier> getTypesViaOperations(Classifier current) { EList<Classifier> result = new UniqueEList<Classifier>(); @@ -202,7 +233,172 @@ public class GenUtils { } /** - * Retrieves a list of types used by inner classifiers of the current classifier + * Retrieve the operations in the current classifier. For each + * operation, collect types of its parameters. + * This method thus finds types, on + * which the signature depends. + * We check if operations and parameters must have or not have some stereotypes. + * + * @param current + * Classifier on which the operations are searched for + * @param excludedOperationStereotypes + * List of ALL stereotypes that must not be applied to an operation + * @param includedOperationStereotypes + * List of ANY stereotype that must be applied to an operation (at least one) + * @param excludedParameterStereotypes + * List of ALL stereotypes that must not be applied to a parameter + * @param includedParameterStereotypes + * List of ANY stereotype that must be applied to a parameter (at least one) + * @return Collection of classifiers which are the types of the operation parameters + */ + public static EList<Classifier> getTypesViaOperations(Classifier current, + EList<Class<? extends EObject>> excludedOperationStereotypes, + EList<Class<? extends EObject>> includedOperationStereotypes, + EList<Class<? extends EObject>> excludedParameterStereotypes, + EList<Class<? extends EObject>> includedParameterStereotypes, + boolean bypassForInnerClassifiers) { + EList<Classifier> result = new UniqueEList<Classifier>(); + + for (Operation operation : current.getOperations()) { + boolean ok = true; + + if (excludedOperationStereotypes != null && GenUtils.hasAnyStereotype(operation, excludedOperationStereotypes)) { + ok = false; + } + + if (includedOperationStereotypes != null && !GenUtils.hasAnyStereotype(operation, includedOperationStereotypes)) { + ok = false; + } + + if (ok) { + for (Parameter param : operation.getOwnedParameters()) { + Type type = param.getType(); + if (type != null) { + if (bypassForInnerClassifiers && !(type.getOwner() instanceof Package)) { // if we force inner class types to be processed + addFarthestOwnerType(type, result); + } else { + ok = true; + + if (excludedParameterStereotypes != null && GenUtils.hasAnyStereotype(param, excludedParameterStereotypes)) { + ok = false; + } + + if (includedParameterStereotypes != null && !GenUtils.hasAnyStereotype(param, includedParameterStereotypes)) { + ok = false; + } + + if (ok) { + addFarthestOwnerType(type, result); + } + } + } + } + } + } + + return result; + } + + /** + * Retrieve the opaque behaviors in the current classifier, without specification. + * For each opaque behavior, collect types of its parameters. + * This method thus finds types, on + * which the signature depends. + * + * @param current + * Classifier on which the opaque behaviors are searched for + * @return Collection of classifiers which are the types of the opaque behavior parameters + */ + public static EList<Classifier> getTypesViaOpaqueBehaviors(Classifier current) { + EList<Classifier> result = new UniqueEList<Classifier>(); + for (Element element : current.getOwnedElements()) { + if (element instanceof OpaqueBehavior) { + OpaqueBehavior opaqueBehavior = (OpaqueBehavior) element; + if (opaqueBehavior.getSpecification() == null) { + for (Parameter param : opaqueBehavior.getOwnedParameters()) { + Type type = param.getType(); + addFarthestOwnerType(type, result); + } + } + } + } + return result; + } + + /** + * Retrieve the opaque behaviors in the current classifier, without specification. + * For each opaque behavior, collect types of its parameters. + * This method thus finds types, on + * which the signature depends. + * We check if opaque behavior and parameters must have or not have some stereotypes. + * + * @param current + * Classifier on which the opaque behaviors are searched for + * @param excludedOperationStereotypes + * List of ALL stereotypes that must not be applied to an opaque behavior + * @param includedOperationStereotypes + * List of ANY stereotype that must be applied to an opaque behavior (at least one) + * @param excludedParameterStereotypes + * List of ALL stereotypes that must not be applied to a parameter + * @param includedParameterStereotypes + * List of ANY stereotype that must be applied to a parameter (at least one) + * @return Collection of classifiers which are the types of the opaque behavior parameters + */ + public static EList<Classifier> getTypesViaOpaqueBehaviors(Classifier current, + EList<Class<? extends EObject>> excludedOperationStereotypes, + EList<Class<? extends EObject>> includedOperationStereotypes, + EList<Class<? extends EObject>> excludedParameterStereotypes, + EList<Class<? extends EObject>> includedParameterStereotypes, + boolean bypassForInnerClassifiers) { + EList<Classifier> result = new UniqueEList<Classifier>(); + + for (Element element : current.getOwnedElements()) { + if (element instanceof OpaqueBehavior) { + OpaqueBehavior opaqueBehavior = (OpaqueBehavior) element; + if (opaqueBehavior.getSpecification() == null) { + boolean ok = true; + + if (excludedOperationStereotypes != null && GenUtils.hasAnyStereotype(opaqueBehavior, excludedOperationStereotypes)) { + ok = false; + } + + if (includedOperationStereotypes != null && !GenUtils.hasAnyStereotype(opaqueBehavior, includedOperationStereotypes)) { + ok = false; + } + + if (ok) { + for (Parameter param : opaqueBehavior.getOwnedParameters()) { + Type type = param.getType(); + if (type != null) { + if (bypassForInnerClassifiers && !(type.getOwner() instanceof Package)) { // if we force inner class types to be processed + addFarthestOwnerType(type, result); + } else { + ok = true; + + if (excludedParameterStereotypes != null && GenUtils.hasAnyStereotype(param, excludedParameterStereotypes)) { + ok = false; + } + + if (includedParameterStereotypes != null && !GenUtils.hasAnyStereotype(param, includedParameterStereotypes)) { + ok = false; + } + + if (ok) { + addFarthestOwnerType(type, result); + } + } + } + } + } + } + } + } + + return result; + } + + /** + * Retrieves a list of types of attributes of inner classifiers of the current classifier * * @param current * Class on which the attributes are searched @@ -210,14 +406,167 @@ public class GenUtils { */ public static EList<Classifier> getInnerClassifierTypes(Classifier current) { EList<Classifier> result = new UniqueEList<Classifier>(); + result.addAll(getInnerClassifierTypesViaAttributes(current)); + result.addAll(getInnerClassifierTypesViaOperations(current)); + return result; + } + + /** + * Retrieve a list of types of attributes of inner classifiers that belong to the current classifier. + * + * @param current + * Class on which the attributes are searched + * @return Collection of classifiers which are the type of the attributes of inner classifiers + */ + public static EList<Classifier> getInnerClassifierTypesViaAttributes(Classifier current) { + EList<Classifier> result = new UniqueEList<Classifier>(); + for (Element ownedElement : current.allOwnedElements()) { + if (ownedElement instanceof Classifier) { + result.addAll(getTypesViaAttributes((Classifier) ownedElement)); + } + } + return result; + } + + /** + * Retrieve a list of types of attributes of inner classifiers that belong to the current classifier. Filter by stereotypes. + * + * @param current + * Class on which the attributes are searched + * @param excludedStereotypes + * List of ALL stereotypes that must no be applied + * @param includedStereotypes + * List of ANY stereotype that must no be applied (at least one) + * @return Collection of classifiers which are the types of the attributes of inner classifiers + */ + public static EList<Classifier> getInnerClassifierTypesViaAttributes(Classifier current, EList<Class<? extends EObject>> excludedStereotypes, EList<Class<? extends EObject>> includedStereotypes, boolean bypassForInnerClassifiers) { + EList<Classifier> result = new UniqueEList<Classifier>(); + for (Element ownedElement : current.allOwnedElements()) { + if (ownedElement instanceof Classifier) { + result.addAll(getTypesViaAttributes((Classifier) ownedElement, excludedStereotypes, includedStereotypes, bypassForInnerClassifiers)); + } + } + return result; + } + + /** + * Retrieve the operations of inner classifiers of the current classifier. For each + * operation, collect types of its parameters. + * This method thus finds types, on + * which the signature depends. + * + * @param current + * Classifier on which the operations are searched for + * @return Collection of classifiers which are the types of the parameters of inner classifiers + */ + public static EList<Classifier> getInnerClassifierTypesViaOperations(Classifier current) { + EList<Classifier> result = new UniqueEList<Classifier>(); for (Element ownedElement : current.allOwnedElements()) { if (ownedElement instanceof Classifier) { - result.addAll(getOwnedAttributeTypes((Classifier) ownedElement)); result.addAll(getTypesViaOperations((Classifier) ownedElement)); } } return result; } + + /** + * Retrieve the operations of inner classifiers of the current classifier. For each + * operation, collect types of its parameters. + * This method thus finds types, on + * which the signature depends. + * We check if operations and parameters must have or not have some stereotypes. + * + * @param current + * Classifier on which the operations are searched for + * @param excludedOperationStereotypes + * List of ALL stereotypes that must not be applied to an operation + * @param includedOperationStereotypes + * List of ANY stereotype that must be applied to an operation (at least one) + * @param excludedParameterStereotypes + * List of ALL stereotypes that must not be applied to a parameter + * @param includedParameterStereotypes + * List of ANY stereotype that must be applied to a parameter (at least one) + * @return Collection of classifiers which are the types of the parameters of inner classifiers + */ + public static EList<Classifier> getInnerClassifierTypesViaOperations(Classifier current, + EList<Class<? extends EObject>> excludedOperationStereotypes, + EList<Class<? extends EObject>> includedOperationStereotypes, + EList<Class<? extends EObject>> excludedParameterStereotypes, + EList<Class<? extends EObject>> includedParameterStereotypes, + boolean bypassForInnerClassifiers) { + EList<Classifier> result = new UniqueEList<Classifier>(); + for (Element ownedElement : current.allOwnedElements()) { + if (ownedElement instanceof Classifier) { + result.addAll(getTypesViaOperations((Classifier) ownedElement, + excludedOperationStereotypes, + includedOperationStereotypes, + excludedParameterStereotypes, + includedParameterStereotypes, + bypassForInnerClassifiers)); + } + } + return result; + } + + /** + * Retrieve the opaque behaviors of inner classifiers of the current classifier, without specification. + * For each opaque behavior, collect types of its parameters. + * This method thus finds types, on + * which the signature depends. + * + * @param current + * Classifier on which the opaque behaviors are searched for + * @return Collection of classifiers which are the types of the parameters of inner classifiers + */ + public static EList<Classifier> getInnerClassifierTypesViaOpaqueBehaviors(Classifier current) { + EList<Classifier> result = new UniqueEList<Classifier>(); + for (Element ownedElement : current.allOwnedElements()) { + if (ownedElement instanceof Classifier) { + result.addAll(getTypesViaOpaqueBehaviors((Classifier) ownedElement)); + } + } + return result; + } + + /** + * Retrieve the opaque behaviors of inner classifiers of the current classifier, without specification. + * For each opaque behavior, collect types of its parameters. + * This method thus finds types, on + * which the signature depends. + * We check if opaque behavior and parameters must have or not have some stereotypes. + * + * @param current + * Classifier on which the opaque behaviors are searched for + * @param excludedOperationStereotypes + * List of ALL stereotypes that must not be applied to an opaque behavior + * @param includedOperationStereotypes + * List of ANY stereotype that must be applied to an opaque behavior (at least one) + * @param excludedParameterStereotypes + * List of ALL stereotypes that must not be applied to a parameter + * @param includedParameterStereotypes + * List of ANY stereotype that must be applied to a parameter (at least one) + * @return Collection of classifiers which are the types of the opaque behavior parameters of inner classifiers + */ + + public static EList<Classifier> getInnerClassifierTypesViaOpaqueBehaviors(Classifier current, + EList<Class<? extends EObject>> excludedOperationStereotypes, + EList<Class<? extends EObject>> includedOperationStereotypes, + EList<Class<? extends EObject>> excludedParameterStereotypes, + EList<Class<? extends EObject>> includedParameterStereotypes, + boolean bypassForInnerClassifiers) { + EList<Classifier> result = new UniqueEList<Classifier>(); + for (Element ownedElement : current.allOwnedElements()) { + if (ownedElement instanceof Classifier) { + result.addAll(getTypesViaOpaqueBehaviors((Classifier) ownedElement, + excludedOperationStereotypes, + includedOperationStereotypes, + excludedParameterStereotypes, + includedParameterStereotypes, + bypassForInnerClassifiers)); + } + } + return result; + } /** * Return a list of classifiers that are referenced by relationships, i.e. @@ -368,6 +717,12 @@ public class GenUtils { return; } + // TODO why was this condition added? + // We don't need the namespace of a primitive type that is not defined since the namespace won't appear before the primitive type in the code + /*if (element instanceof PrimitiveType && !GenUtils.hasStereotype(element, "C_Cpp::Typedef")) { + return; + }*/ + if (element.getOwner() instanceof Package && element instanceof Classifier) { result.add((Classifier) element); } else { // Type is an inner class. We want to return a classifier C directly owned by a package since it is "C.h" that should be included @@ -462,6 +817,50 @@ public class GenUtils { } return false; } + + /** + * Is a list of stereotypes all applied? + * + * @param element + * a UML element + * @param stereotypes + * The list of classes of an element of a static profile + * @return + */ + public static boolean hasAllStereotypes(Element element, EList<java.lang.Class<? extends EObject>> stereotypes) { + for (EObject stereoApplication : element.getStereotypeApplications()) { + // check whether the stereotype is a super-class of the passed parameter clazz + for (Class<? extends EObject> stereotype : stereotypes) { + if (!stereotype.isAssignableFrom(stereoApplication.getClass())) { + return false; + } + } + + } + return true; + } + + /** + * Is a any stereotype in a list applied? + * + * @param element + * a UML element + * @param stereotypes + * The list of classes of an element of a static profile + * @return + */ + public static boolean hasAnyStereotype(Element element, EList<java.lang.Class<? extends EObject>> stereotypes) { + for (EObject stereoApplication : element.getStereotypeApplications()) { + // check whether the stereotype is a super-class of the passed parameter clazz + for (Class<? extends EObject> stereotype : stereotypes) { + if (stereotype.isAssignableFrom(stereoApplication.getClass())) { + return true; + } + } + + } + return false; + } /** |