[Uml-devel] [Bug 53368] C# Code Generation and export
Oliver Kellogg
okellogg at users.sourceforge.net
Thu Feb 22 18:15:04 UTC 2007
------- You are receiving this mail because: -------
You are the assignee for the bug, or are watching the assignee.
http://bugs.kde.org/show_bug.cgi?id=53368
okellogg users sourceforge net changed:
What |Removed |Added
----------------------------------------------------------------------------
Status|NEW |RESOLVED
Resolution| |FIXED
------- Additional Comments From okellogg users sourceforge net 2007-02-22 19:15 -------
SVN commit 636283 by okellogg:
Apply attachment 19776 from Ferenc Veres:
> Implemented Interfaces' methods are generated as skeleton, including recursions
> Inherited abstract methods are generated as skels, recursive.
> Including some base 'using System*' commands.
> Not empty and not "1" multiplications are generated as ArrayList
> Fixes in some defitions (baseclass+interfaces,etc).
> [...] Only ENUMS are missing.
Many thanks Ferenc for contributing.
> Maintainers, please check my * and &, [...]
Look okay to me, although you could pass around lists by value (i.e. you don't
really need the pointers.)
FEATURE:53368
M +124 -70 csharpwriter.cpp
M +25 -4 csharpwriter.h
--- branches/KDE/3.5/kdesdk/umbrello/umbrello/codegenerators/csharpwriter.cpp #636282:636283
@ -177,6 +177,12 @
UMLDoc *umldoc = UMLApp::app()->getDocument();
UMLFolder *logicalView = umldoc->getRootFolder(Uml::mt_Logical);
+ // write generic includes
+ cs << "using System;" << m_endl;
+ cs << "using System.Text;" << m_endl;
+ cs << "using System.Collections;" << m_endl;
+ cs << "using System.Collections.Generic;" << m_endl << m_endl;
+
//write includes and namespace
UMLPackage *container = c->getUMLPackage();
@ -221,7 +227,6 @
UMLAssociationList aggregations = c->getAggregations();
UMLAssociationList compositions = c->getCompositions();
UMLAssociationList realizations = c->getRealizations();
- UMLAssociation *a;
bool isInterface = c->isInterface();
m_unnamedRoles = 1;
@ -232,29 +237,40 @
cs << "interface " << classname;
} else {
//check if class is abstract and / or has abstract methods
- if (c->getAbstract())
+ if (c->getAbstract() || c->hasAbstractOps())
cs << "abstract ";
+
cs << "class " << classname << (superclasses.count() > 0 ? " : ":"");
+
+ // write baseclass, ignore interfaces, write error on multiple inheritance
if (superclasses.count() > 0) {
-
- // C# does not support multiple inheritance so only use the first one and print a warning if more are used
-
- UMLClassifier *obj = superclasses.first();
- cs << cleanName(obj->getName());
- if (superclasses.count() > 1)
- cs << m_indentation << "//WARNING: C# does not support multiple inheritance but there is more than 1 superclass defined in your UML model!";
+ UMLClassifier *obj;
+ int supers = 0;
+ for (obj = superclasses.first(); obj; obj = superclasses.next()) {
+ if (!obj->isInterface()) {
+ if (supers > 0) {
+ cs << " // AND ";
+ }
+ cs << cleanName(obj->getName());
+ supers++;
+ }
+ }
+ if (supers > 1) {
+ cs << m_endl << "//WARNING: C# does not support multiple inheritance but there is more than 1 superclass defined in your UML model!" << m_endl;
}
- // FIXME: I get no (valid) input here (realizations are not coming?)
+ }
//check for realizations
+ UMLAssociationList realizations = c->getRealizations();
+ UMLAssociation *a;
+
if (!realizations.isEmpty()) {
- int rc = realizations.count();
- int ri = rc;
for (a = realizations.first(); a; a = realizations.next()) {
- UMLObject *o = a->getObject(Uml::B);
- QString typeName = cleanName(o->getName());
- if (ri == rc)
- cs << ", ";
- cs << typeName << (--rc == 0 ? "" : ", ");
+ UMLClassifier *real = (UMLClassifier*)a->getObject(Uml::B);
+ if(real != c) {
+ // write list of realizations
+ cs << ", " << real->getName();
+ }
+
}
}
}
@ -304,7 +320,7 @
UMLOperationList oppub,opprot,oppriv;
bool isInterface = c->isInterface();
- bool generateErrorStub = false;
+ bool generateErrorStub = true;
oppub.setAutoDelete(false);
opprot.setAutoDelete(false);
@ -328,58 +344,106 @
}
}
- QString classname(cleanName(c->getName()));
+ // write realizations (recursive)
+ UMLAssociationList realizations = c->getRealizations();
+ if (!isInterface && !realizations.isEmpty()) {
+ writeRealizationsRecursive(c, &realizations, cs);
+ }
+
// write public operations
if (forceSections() || !oppub.isEmpty()) {
cs << m_endl << m_container_indent << m_indentation << "#region Public methods" << m_endl << m_endl;
- writeOperations(classname,oppub,cs,isInterface,generateErrorStub);
+ writeOperations(oppub,cs,isInterface,false,generateErrorStub);
cs << m_container_indent << m_indentation << "#endregion" << m_endl << m_endl;
}
// write protected operations
if (forceSections() || !opprot.isEmpty()) {
cs << m_endl << m_container_indent << m_indentation << "#region Protected methods" << m_endl << m_endl;
- writeOperations(classname,opprot,cs,isInterface,generateErrorStub);
+ writeOperations(opprot,cs,isInterface,false,generateErrorStub);
cs << m_container_indent << m_indentation << "#endregion" << m_endl << m_endl;
}
// write private operations
if (forceSections() || !oppriv.isEmpty()) {
cs << m_endl << m_container_indent << m_indentation << "#region Private methods" << m_endl << m_endl;
- writeOperations(classname,oppriv,cs,isInterface,generateErrorStub);
+ writeOperations(oppriv,cs,isInterface,false,generateErrorStub);
cs << m_container_indent << m_indentation << "#endregion" << m_endl << m_endl;
}
+ // write superclasses abstract methods
+ UMLClassifierList superclasses = c->getSuperClasses();
- // build an oplist for all of the realized operations
- UMLOperationList opreal;
- opreal.setAutoDelete(false);
+ if (!isInterface && !c->getAbstract() && !c->hasAbstractOps()
+ && superclasses.count() > 0) {
+ writeOverridesRecursive(&superclasses, cs);
+ }
- // go through each of the realizations, taking each op
- UMLAssociationList realizations = c->getRealizations();
- UMLAssociation *a;
+}
- if (!realizations.isEmpty()) {
- for (a = realizations.first(); a; a = realizations.next()) {
+void CSharpWriter::writeOverridesRecursive(UMLClassifierList *superclasses, QTextStream &cs) {
+ // oplist for implemented abstract operations
+ UMLOperationList opabstract;
+ opabstract.setAutoDelete(false);
+ UMLClassifier *obj;
- // we know its a classifier if its in the list
- UMLClassifier *real = (UMLClassifier*)a->getObject(Uml::B);
-
- UMLOperationList opl(real->getOpList());
+ for (obj = superclasses->first(); obj; obj = superclasses->next()) {
+ if (!obj->isInterface() && obj->hasAbstractOps()) {
+ // collect abstract ops
+ UMLOperationList opl(obj->getOpList());
for (UMLOperation *op = opl.first(); op ; op = opl.next()) {
- opreal.append(op);
+ if (op->getAbstract()) {
+ opabstract.append(op);
+ }
}
+
+ // write abstract implementations
+ cs << m_endl << m_container_indent << m_indentation << "#region " << obj->getName() << " members" << m_endl << m_endl;
+ writeOperations(opabstract,cs,false,true,true);
+ cs << m_container_indent << m_indentation << "#endregion" << m_endl << m_endl;
+
+ opabstract.clear();
}
+ // Recurse to parent superclasses
+ UMLClassifierList superRecursive = obj->getSuperClasses();
+ UMLClassifierList *superRecursivePtr =& superRecursive;
+ if (superRecursivePtr->count() > 0) {
+ writeOverridesRecursive(superRecursivePtr, cs);
+ }
}
+}
+void CSharpWriter::writeRealizationsRecursive(UMLClassifier *currentClass, UMLAssociationList *realizations, QTextStream &cs) {
- // write out all the realizations operations
- writeOperations(classname,opreal,cs,false,true);
+ UMLAssociation *a;
+ for (a = realizations->first(); a; a = realizations->next()) {
+ // we know its a classifier if its in the list
+ UMLClassifier *real = (UMLClassifier*)a->getObject(Uml::B);
+
+ //FIXME: Interfaces realize themselves without this condition!?
+ if (real == currentClass)
+ continue;
+
+ // collect operations of one realization
+ UMLOperationList opreal = real->getOpList();
+
+ // write realizations
+ cs << m_endl << m_container_indent << m_indentation << "#region " << real->getName() << " members" << m_endl << m_endl;
+ writeOperations(opreal,cs,false,false,true);
+ cs << m_container_indent << m_indentation << "#endregion" << m_endl << m_endl;
+
+ // Recurse to parent realizations
+ UMLAssociationList parentReal = real->getRealizations();
+ if (!parentReal.isEmpty()) {
+ writeRealizationsRecursive(real, &parentReal, cs);
+ }
+ }
}
-void CSharpWriter::writeOperations(const QString &/* classname */, UMLOperationList &opList,
+void CSharpWriter::writeOperations(UMLOperationList opList,
QTextStream &cs, bool isInterface /* = false */,
+ bool isOverride /* = false */,
bool generateErrorStub /* = false */) {
for (UMLOperation *op=opList.first(); op ; op=opList.next()) {
@ -394,7 +458,7 @
}
//write method documentation
- if (writeDoc)
+ if (writeDoc && !isOverride)
{
cs << m_container_indent << m_indentation << "/// <summary>" << m_endl;
cs << formatDoc(op->getDoc(), m_container_indent + m_indentation + "/// ");
@ -418,32 +482,22 @
}
cs << "</returns>" << m_endl;
- /* not used in C#
- if (op->getAbstract()) cs << m_indentation << " * abstract" << m_endl;
- if (op->getStatic()) cs << m_indentation << " * static" << m_endl;
-
- switch (op->getVisibility()) {
- case Uml::Visibility::Public:
- cs << m_indentation << " * access public" << m_endl;
- break;
- case Uml::Visibility::Protected:
- cs << m_indentation << " * access protected" << m_endl;
- break;
- case Uml::Visibility::Private:
- cs << m_indentation << " * access private" << m_endl;
- break;
- default:
- break;
- }
-*/
-// cs <<m_indentation << " */" << m_endl;
}
// method visibility
cs << m_container_indent << m_indentation;
- if (op->getAbstract()) cs << "abstract ";
- cs << op->getVisibility().toString() << " ";
- if (op->getStatic()) cs << "static ";
+ if (!isInterface) {
+ if (!isOverride) {
+ if (op->getAbstract()) cs << "abstract ";
+ cs << op->getVisibility().toString() << " ";
+ if (op->getStatic()) cs << "static ";
+ }
+ else {
+ // method overriding an abstract parent
+ cs << op->getVisibility().toString() << " override ";
+ if (op->getStatic()) cs << "static ";
+ }
+ }
// return type
if (op->getTypeName() == "") {
@ -472,7 +526,7 @
cs << ")";
//FIXME: how to control generation of error stub?
- if (!isInterface && !op->getAbstract()) {
+ if (!isInterface && (!op->getAbstract() || isOverride)) {
cs << m_endl << m_container_indent << m_indentation << "{" << m_endl;
if (generateErrorStub) {
cs << m_container_indent << m_indentation << m_indentation;
@ -563,7 +617,7 @
for (a = associated.first(); a ; a = associated.next()) {
if (c != a->getObject(Uml::A)) // we need to be at the A side
continue;
-
+
UMLObject *o = a->getObject(Uml::B);
if (o == NULL) {
kError() << "composition role B object is NULL" << endl;
@ -577,14 +631,14 @
}
QString roleDoc = a->getRoleDoc(Uml::B);
- //FIXME:maybe we should parse the string here and take multiplicity into account to decide
- //which container to use.
- if (a->getMulti(Uml::B).isEmpty()) {
+ //FIXME:is this simple condition enough?
+ if (a->getMulti(Uml::B).isEmpty() || a->getMulti(Uml::B) == "1") {
+ // normal attribute
writeAttribute(roleDoc, a->getVisibility(Uml::B), false, typeName, roleName, "", ( a->getVisibility(Uml::B) != Uml::Visibility::Private), cs);
} else {
- // FIXME:not updated for C# yet
- cs << m_container_indent << m_indentation << "//" << typeName
- << " " << roleName << "Vector = array();" << m_endl;
+ // array
+ roleDoc += "\n(Array of " + typeName + ")";
+ writeAttribute(roleDoc, a->getVisibility(Uml::B), false, "ArrayList", roleName, "", ( a->getVisibility(Uml::B) != Uml::Visibility::Private), cs);
}
}
}
@ -631,7 +685,7 @
if (!initialValue.isEmpty())
cs << " = " << initialValue;
-
+
cs << ";" << m_endl << m_endl;
}
--- branches/KDE/3.5/kdesdk/umbrello/umbrello/codegenerators/csharpwriter.h #636282:636283
@ -77,8 +77,19 @
* Counts associations without a role name for giving a default name.
*/
int m_unnamedRoles;
-
+
/**
+ * write realizations of a class and recurse to parent classes
+
+ * param currentClass class to start with
+ * param realizations realizations of this class
+ * param cs output stream
+ */
+ void writeRealizationsRecursive(UMLClassifier *currentClass,
+ UMLAssociationList *realizations,
+ QTextStream &cs);
+
+ /**
* write all operations for a given class
*
* param c the concept we are generating code for
@ -89,15 +100,25 @
/**
* write a list of class operations
*
- * param classname the name of the class
* param opList the list of operations
* param cs output stream
* param interface indicates if the operation is an interface member
+ * param isOverride implementation of an inherited abstract function
*/
- void writeOperations(const QString &classname, UMLOperationList &opList,
+ void writeOperations(UMLOperationList opList,
QTextStream &cs,
- bool interface = false, bool generateErrorStub = false);
+ bool interface = false,
+ bool isOverride = false,
+ bool generateErrorStub = false);
+ /**
+ * write superclasses' abstract methods
+ *
+ * param superclasses List of superclasses to start recursing on
+ * param cs output stream
+ */
+ void writeOverridesRecursive(UMLClassifierList *superclasses, QTextStream &cs);
+
/** write all the attributes of a class
* param c the class we are generating code for
* param cs output stream
More information about the umbrello-devel
mailing list