void CSharpWriter::writeOverridesRecursive(UMLClassifierList *superclasses, QTextStream &cs) { // oplist for implemented abstract operations UMLOperationList opabstract; opabstract.setAutoDelete(false); UMLClassifier *obj; 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()) { 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); } } }
/** * Setup dialog operations list. */ void SelectOperationDialog::setupOperationsList() { m_pOpCB->clear(); UMLOperationList list = m_classifier->getOpList(true); if (list.count() > 0) m_pOpCB->insertItem(0, QString()); qSort(list.begin(), list.end(), caseInsensitiveLessThan); foreach(UMLOperation * obj, list) { QString s = obj->toString(Uml::SignatureType::SigNoVis); m_pOpCB->insertItem(list.count(), s); m_pOpCB->completionObject()->addItem(s); }
SelectOpDlg::SelectOpDlg(UMLView * parent, UMLClassifier * c) : KDialog( parent) { setCaption( i18n("Select Operation") ); setButtons( Ok | Cancel ); setDefaultButton( Yes ); setModal( true ); showButtonSeparator( true ); QFrame *frame = new QFrame( this ); setMainWidget( frame ); m_pView = parent; QVBoxLayout * topLayout = new QVBoxLayout(frame); m_pOpGB = new QGroupBox(i18n("Select Operation"), frame); topLayout->addWidget(m_pOpGB); QGridLayout * mainLayout = new QGridLayout(m_pOpGB); mainLayout->setSpacing(spacingHint()); mainLayout->setMargin(fontMetrics().height()); Dialog_Utils::makeLabeledEditField( m_pOpGB, mainLayout, 0, m_pSeqL, i18n("Sequence number:"), m_pSeqLE ); m_pOpRB = new QRadioButton(i18n("Class operation:"), m_pOpGB); connect(m_pOpRB, SIGNAL(clicked()), this, SLOT(slotSelectedOp())); mainLayout->addWidget(m_pOpRB, 1, 0); m_pOpCB = new KComboBox(m_pOpGB); m_pOpCB->setCompletionMode( KGlobalSettings::CompletionPopup ); m_pOpCB->setDuplicatesEnabled(false); // only allow one of each type in box mainLayout->addWidget(m_pOpCB, 1, 1); m_pCustomRB = new QRadioButton(i18n("Custom operation:"), m_pOpGB); connect(m_pCustomRB, SIGNAL(clicked()), this, SLOT(slotSelectedCustom())); mainLayout->addWidget(m_pCustomRB, 2, 0); m_pOpLE = new KLineEdit(m_pOpGB); mainLayout->addWidget(m_pOpLE, 2, 1); UMLOperationList list = c->getOpList(true); foreach (UMLOperation* obj, list ) { insertOperation( obj->toString(Uml::st_SigNoVis), list.count() ); }
// This method will cause the class to rebuild its text representation. // based on the parent classifier object. // For any situation in which this is called, we are either building the code // document up, or replacing/regenerating the existing auto-generated parts. As // such, we will want to insert everything we resonablely will want // during creation. We can set various parts of the document (esp. the // comments) to appear or not, as needed. void RubyClassifierCodeDocument::updateContent() { // Gather info on the various fields and parent objects of this class... UMLClassifier * c = getParentClassifier(); RubyCodeGenerator * gen = dynamic_cast<RubyCodeGenerator*>(UMLApp::app()->generator()); // first, set the global flag on whether or not to show classfield info // This depends on whether or not we have attribute/association classes const CodeClassFieldList * cfList = getCodeClassFieldList(); CodeClassFieldList::const_iterator it = cfList->begin(); CodeClassFieldList::const_iterator end = cfList->end(); for (; it != end; ++it) { CodeClassField * field = *it; if (field->parentIsAttribute()) field->setWriteOutMethods(gen->getAutoGenerateAttribAccessors()); else field->setWriteOutMethods(gen->getAutoGenerateAssocAccessors()); } // attribute-based ClassFields // we do it this way to have the static fields sorted out from regular ones CodeClassFieldList staticPublicAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, true, Uml::Visibility::Public); CodeClassFieldList publicAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, false, Uml::Visibility::Public); CodeClassFieldList staticProtectedAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, true, Uml::Visibility::Protected); CodeClassFieldList protectedAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, false, Uml::Visibility::Protected); CodeClassFieldList staticPrivateAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, true, Uml::Visibility::Private); CodeClassFieldList privateAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, false, Uml::Visibility::Private); // association-based ClassFields // don't care if they are static or not..all are lumped together CodeClassFieldList publicPlainAssocClassFields = getSpecificClassFields (CodeClassField::PlainAssociation, Uml::Visibility::Public); CodeClassFieldList publicAggregationClassFields = getSpecificClassFields (CodeClassField::Aggregation, Uml::Visibility::Public); CodeClassFieldList publicCompositionClassFields = getSpecificClassFields (CodeClassField::Composition, Uml::Visibility::Public); CodeClassFieldList protPlainAssocClassFields = getSpecificClassFields (CodeClassField::PlainAssociation, Uml::Visibility::Protected); CodeClassFieldList protAggregationClassFields = getSpecificClassFields (CodeClassField::Aggregation, Uml::Visibility::Protected); CodeClassFieldList protCompositionClassFields = getSpecificClassFields (CodeClassField::Composition, Uml::Visibility::Protected); CodeClassFieldList privPlainAssocClassFields = getSpecificClassFields (CodeClassField::PlainAssociation, Uml::Visibility::Private); CodeClassFieldList privAggregationClassFields = getSpecificClassFields (CodeClassField::Aggregation, Uml::Visibility::Private); CodeClassFieldList privCompositionClassFields = getSpecificClassFields (CodeClassField::Composition, Uml::Visibility::Private); bool isInterface = parentIsInterface(); bool hasOperationMethods = false; Q_ASSERT(c != NULL); if (c) { UMLOperationList list = c->getOpList(); hasOperationMethods = ! list.isEmpty(); } CodeGenerationPolicy *pol = UMLApp::app()->commonPolicy(); QString endLine = pol->getNewLineEndingChars(); // a shortcut..so we don't have to call this all the time // // START GENERATING CODE/TEXT BLOCKS and COMMENTS FOR THE DOCUMENT // // CLASS DECLARATION BLOCK // // get the declaration block. If it is not already present, add it too RubyClassDeclarationBlock * myClassDeclCodeBlock = getClassDecl(); addTextBlock(myClassDeclCodeBlock); // note: wont add if already present // declare public, protected and private methods, attributes (fields). // set the start text ONLY if this is the first time we created the objects. bool createdPublicBlock = publicBlock == 0 ? true : false; publicBlock = myClassDeclCodeBlock->getHierarchicalCodeBlock(QLatin1String("publicBlock"), QLatin1String("Public Items"), 0); if (createdPublicBlock) publicBlock->setStartText(QLatin1String("public")); bool createdProtBlock = protectedBlock == 0 ? true : false; protectedBlock = myClassDeclCodeBlock->getHierarchicalCodeBlock(QLatin1String("protectedBlock"), QLatin1String("Protected Items"), 0); if (createdProtBlock) protectedBlock->setStartText(QLatin1String("protected")); bool createdPrivBlock = privateBlock == 0 ? true : false; privateBlock = myClassDeclCodeBlock->getHierarchicalCodeBlock(QLatin1String("privateBlock"), QLatin1String("Private Items"), 0); if (createdPrivBlock) privateBlock->setStartText(QLatin1String("private")); // NOW create document in sections.. // now we want to populate the body of our class // our layout is the following general groupings of code blocks: // start ruby classifier document // header comment // class declaration // section: // section: // - methods section comment // sub-section: constructor ops // - constructor method section comment // - constructor methods (0+ codeblocks) // sub-section: accessors // - accessor method section comment // - static accessor methods (0+ codeblocks) // - non-static accessor methods (0+ codeblocks) // sub-section: non-constructor ops // - operation method section comment // - operations (0+ codeblocks) // end class declaration // end ruby classifier document // Q: Why use the more complicated scheme of arranging code blocks within codeblocks? // A: This will allow us later to preserve the format of our document so that if // codeblocks are added, they may be easily added in the correct place, rather than at // the end of the document, or by using a difficult algorithm to find the location of // the last appropriate code block sibling (which may not exist.. for example user adds // a constructor operation, but there currently are no constructor code blocks // within the document). // // METHODS section // // get/create the method codeblock // public methods HierarchicalCodeBlock * pubMethodsBlock = publicBlock->getHierarchicalCodeBlock(QLatin1String("pubMethodsBlock"), QString(), 1); CodeComment * pubMethodsComment = pubMethodsBlock->getComment(); bool forceDoc = pol->getCodeVerboseDocumentComments(); // set conditions for showing this comment if (!forceDoc && !hasClassFields() && !hasOperationMethods) pubMethodsComment->setWriteOutText(false); else pubMethodsComment->setWriteOutText(true); // protected methods HierarchicalCodeBlock * protMethodsBlock = protectedBlock->getHierarchicalCodeBlock(QLatin1String("protMethodsBlock"), QString(), 1); CodeComment * protMethodsComment = protMethodsBlock->getComment(); // set conditions for showing this comment if (!forceDoc && !hasClassFields() && !hasOperationMethods) protMethodsComment->setWriteOutText(false); else protMethodsComment->setWriteOutText(true); // private methods HierarchicalCodeBlock * privMethodsBlock = privateBlock->getHierarchicalCodeBlock(QLatin1String("privMethodsBlock"), QString(), 1); CodeComment * privMethodsComment = privMethodsBlock->getComment(); // set conditions for showing this comment if (!forceDoc && !hasClassFields() && !hasOperationMethods) privMethodsComment->setWriteOutText(false); else privMethodsComment->setWriteOutText(true); // METHODS sub-section : constructor methods // // public pubConstructorBlock = pubMethodsBlock->getHierarchicalCodeBlock(QLatin1String("constructionMethods"), QLatin1String("Constructors"), 1); // special condiions for showing comment: only when autogenerateding empty constructors // Although, we *should* check for other constructor methods too CodeComment * pubConstComment = pubConstructorBlock->getComment(); if (!forceDoc && (isInterface || !pol->getAutoGenerateConstructors())) pubConstComment->setWriteOutText(false); else pubConstComment->setWriteOutText(true); // protected protConstructorBlock = protMethodsBlock->getHierarchicalCodeBlock(QLatin1String("constructionMethods"), QLatin1String("Constructors"), 1); // special condiions for showing comment: only when autogenerateding empty constructors // Although, we *should* check for other constructor methods too CodeComment * protConstComment = protConstructorBlock->getComment(); if (!forceDoc && (isInterface || !pol->getAutoGenerateConstructors())) protConstComment->setWriteOutText(false); else protConstComment->setWriteOutText(true); // private privConstructorBlock = privMethodsBlock->getHierarchicalCodeBlock(QLatin1String("constructionMethods"), QLatin1String("Constructors"), 1); // special condiions for showing comment: only when autogenerateding empty constructors // Although, we *should* check for other constructor methods too CodeComment * privConstComment = privConstructorBlock->getComment(); if (!forceDoc && (isInterface || !pol->getAutoGenerateConstructors())) privConstComment->setWriteOutText(false); else privConstComment->setWriteOutText(true); // get/create the accessor codeblock // public HierarchicalCodeBlock * pubAccessorBlock = pubMethodsBlock->getHierarchicalCodeBlock(QLatin1String("accessorMethods"), QLatin1String("Accessor Methods"), 1); // set conditions for showing section comment CodeComment * pubAccessComment = pubAccessorBlock->getComment(); if (!forceDoc && !hasClassFields()) pubAccessComment->setWriteOutText(false); else pubAccessComment->setWriteOutText(true); // protected HierarchicalCodeBlock * protAccessorBlock = protMethodsBlock->getHierarchicalCodeBlock(QLatin1String("accessorMethods"), QLatin1String("Accessor Methods"), 1); // set conditions for showing section comment CodeComment * protAccessComment = protAccessorBlock->getComment(); if (!forceDoc && !hasClassFields()) protAccessComment->setWriteOutText(false); else protAccessComment->setWriteOutText(true); // private HierarchicalCodeBlock * privAccessorBlock = privMethodsBlock->getHierarchicalCodeBlock(QLatin1String("accessorMethods"), QLatin1String("Accessor Methods"), 1); // set conditions for showing section comment CodeComment * privAccessComment = privAccessorBlock->getComment(); if (!forceDoc && !hasClassFields()) privAccessComment->setWriteOutText(false); else privAccessComment->setWriteOutText(true); // now, 2 sub-sub sections in accessor block // add/update accessor methods for attributes HierarchicalCodeBlock * pubStaticAccessors = pubAccessorBlock->getHierarchicalCodeBlock(QLatin1String("pubStaticAccessorMethods"), QString(), 1); HierarchicalCodeBlock * pubRegularAccessors = pubAccessorBlock->getHierarchicalCodeBlock(QLatin1String("pubRegularAccessorMethods"), QString(), 1); pubStaticAccessors->getComment()->setWriteOutText(false); // never write block comment pubRegularAccessors->getComment()->setWriteOutText(false); // never write block comment HierarchicalCodeBlock * protStaticAccessors = protAccessorBlock->getHierarchicalCodeBlock(QLatin1String("protStaticAccessorMethods"), QString(), 1); HierarchicalCodeBlock * protRegularAccessors = protAccessorBlock->getHierarchicalCodeBlock(QLatin1String("protRegularAccessorMethods"), QString(), 1); protStaticAccessors->getComment()->setWriteOutText(false); // never write block comment protRegularAccessors->getComment()->setWriteOutText(false); // never write block comment HierarchicalCodeBlock * privStaticAccessors = privAccessorBlock->getHierarchicalCodeBlock(QLatin1String("privStaticAccessorMethods"), QString(), 1); HierarchicalCodeBlock * privRegularAccessors = privAccessorBlock->getHierarchicalCodeBlock(QLatin1String("privRegularAccessorMethods"), QString(), 1); privStaticAccessors->getComment()->setWriteOutText(false); // never write block comment privRegularAccessors->getComment()->setWriteOutText(false); // never write block comment // now add in accessors as appropriate // public stuff pubStaticAccessors->addCodeClassFieldMethods(staticPublicAttribClassFields); pubRegularAccessors->addCodeClassFieldMethods(publicAttribClassFields); pubRegularAccessors->addCodeClassFieldMethods(publicPlainAssocClassFields); pubRegularAccessors->addCodeClassFieldMethods(publicAggregationClassFields); pubRegularAccessors->addCodeClassFieldMethods(publicCompositionClassFields); // protected stuff protStaticAccessors->addCodeClassFieldMethods(staticProtectedAttribClassFields); protRegularAccessors->addCodeClassFieldMethods(protectedAttribClassFields); protRegularAccessors->addCodeClassFieldMethods(protPlainAssocClassFields); protRegularAccessors->addCodeClassFieldMethods(protAggregationClassFields); protRegularAccessors->addCodeClassFieldMethods(protCompositionClassFields); // private stuff privStaticAccessors->addCodeClassFieldMethods(staticPrivateAttribClassFields); privRegularAccessors->addCodeClassFieldMethods(privateAttribClassFields); privRegularAccessors->addCodeClassFieldMethods(privPlainAssocClassFields); privRegularAccessors->addCodeClassFieldMethods(privAggregationClassFields); privRegularAccessors->addCodeClassFieldMethods(privCompositionClassFields); // METHODS subsection : Operation methods (which aren't constructors) // // setup/get/create the operations codeblock // public pubOperationsBlock = pubMethodsBlock->getHierarchicalCodeBlock(QLatin1String("operationMethods"), QLatin1String("Operations"), 1); // set conditions for showing section comment CodeComment * pubOcomment = pubOperationsBlock->getComment(); if (!forceDoc && !hasOperationMethods) pubOcomment->setWriteOutText(false); else pubOcomment->setWriteOutText(true); //protected protOperationsBlock = protMethodsBlock->getHierarchicalCodeBlock(QLatin1String("operationMethods"), QLatin1String("Operations"), 1); // set conditions for showing section comment CodeComment * protOcomment = protOperationsBlock->getComment(); if (!forceDoc && !hasOperationMethods) protOcomment->setWriteOutText(false); else protOcomment->setWriteOutText(true); //private privOperationsBlock = privMethodsBlock->getHierarchicalCodeBlock(QLatin1String("operationMethods"), QLatin1String("Operations"), 1); // set conditions for showing section comment CodeComment * privOcomment = privOperationsBlock->getComment(); if (!forceDoc && !hasOperationMethods) privOcomment->setWriteOutText(false); else privOcomment->setWriteOutText(true); }
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()) { UMLAttributeList atl = op->getParmList(); UMLAttribute *at; //write method doc if we have doc || if at least one of the params has doc bool writeDoc = forceDoc() || !op->getDoc().isEmpty(); for (at = atl.first(); at; at = atl.next()) { writeDoc |= !at->getDoc().isEmpty(); } //write method documentation if (writeDoc && !isOverride) { cs << m_container_indent << m_indentation << "/// <summary>" << m_endl; cs << formatDoc(op->getDoc(), m_container_indent + m_indentation + "/// "); cs << m_container_indent << m_indentation << "/// </summary>" << m_endl; //write parameter documentation for (at = atl.first(); at; at = atl.next()) { if (forceDoc() || !at->getDoc().isEmpty()) { cs << m_container_indent << m_indentation << "/// <param name=\"" << cleanName(at->getName()) << "\">"; //removing newlines from parameter doc cs << formatDoc(at->getDoc(), "").replace("\n", " ").remove('\r').replace(QRegExp(" $"), ""); cs << "</param>" << m_endl; } } // FIXME: "returns" should contain documentation, not type. cs << m_container_indent << m_indentation << "/// <returns>"; if (! op->getTypeName().isEmpty()) { cs << makeLocalTypeName(op); } cs << "</returns>" << m_endl; } // method visibility cs << m_container_indent << m_indentation; 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 (unless constructor, destructor) if (!op->isLifeOperation()) { if (op->getTypeName().isEmpty()) { cs << "void "; } else { cs << makeLocalTypeName(op) << " "; } } // method name cs << cleanName(op->getName()) << "("; // method parameters int i= atl.count(); int j=0; for (at = atl.first(); at; at = atl.next(), j++) { cs << makeLocalTypeName(at) << " " << cleanName(at->getName()); // no initial values in C# //<< (!(at->getInitialValue().isEmpty()) ? // (QString(" = ")+at->getInitialValue()) : // QString("")) cs << ((j < i-1)?", ":""); } cs << ")"; //FIXME: how to control generation of error stub? 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; cs << "throw new Exception(\"The method or operation is not implemented.\");" << m_endl; } cs << m_container_indent << m_indentation << "}" << m_endl; } else { cs << ';' << m_endl; } cs << m_endl; } }
// This method will cause the class to rebuild its text representation. // based on the parent classifier object. // For any situation in which this is called, we are either building the code // document up, or replacing/regenerating the existing auto-generated parts. As // such, we will want to insert everything we resonablely will want // during creation. We can set various parts of the document (esp. the // comments) to appear or not, as needed. void CPPHeaderCodeDocument::updateContent() { // Gather info on the various fields and parent objects of this class... UMLClassifier * c = getParentClassifier(); Q_ASSERT(c != NULL); CodeGenPolicyExt *pe = UMLApp::app()->policyExt(); CPPCodeGenerationPolicy * policy = dynamic_cast<CPPCodeGenerationPolicy*>(pe); // first, set the global flag on whether or not to show classfield info const CodeClassFieldList * cfList = getCodeClassFieldList(); CodeClassFieldList::const_iterator it = cfList->begin(); CodeClassFieldList::const_iterator end = cfList->end(); for(; it != end; ++it) (*it)->setWriteOutMethods(policy->getAutoGenerateAccessors()); // attribute-based ClassFields // we do it this way to have the static fields sorted out from regular ones CodeClassFieldList staticPublicAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, true, Uml::Visibility::Public); CodeClassFieldList publicAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, false, Uml::Visibility::Public); CodeClassFieldList staticProtectedAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, true, Uml::Visibility::Protected); CodeClassFieldList protectedAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, false, Uml::Visibility::Protected); CodeClassFieldList staticPrivateAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, true, Uml::Visibility::Private); CodeClassFieldList privateAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, false, Uml::Visibility::Private); // association-based ClassFields // don't care if they are static or not..all are lumped together CodeClassFieldList publicPlainAssocClassFields = getSpecificClassFields (CodeClassField::PlainAssociation, Uml::Visibility::Public); CodeClassFieldList publicAggregationClassFields = getSpecificClassFields (CodeClassField::Aggregation, Uml::Visibility::Public); CodeClassFieldList publicCompositionClassFields = getSpecificClassFields (CodeClassField::Composition, Uml::Visibility::Public); CodeClassFieldList protPlainAssocClassFields = getSpecificClassFields (CodeClassField::PlainAssociation, Uml::Visibility::Protected); CodeClassFieldList protAggregationClassFields = getSpecificClassFields (CodeClassField::Aggregation, Uml::Visibility::Protected); CodeClassFieldList protCompositionClassFields = getSpecificClassFields (CodeClassField::Composition, Uml::Visibility::Protected); CodeClassFieldList privPlainAssocClassFields = getSpecificClassFields (CodeClassField::PlainAssociation, Uml::Visibility::Private); CodeClassFieldList privAggregationClassFields = getSpecificClassFields (CodeClassField::Aggregation, Uml::Visibility::Private); CodeClassFieldList privCompositionClassFields = getSpecificClassFields (CodeClassField::Composition, Uml::Visibility::Private); bool hasOperationMethods = false; UMLOperationList list = c->getOpList(); hasOperationMethods = ! list.isEmpty(); bool hasNamespace = false; bool isEnumeration = false; bool isInterface = parentIsInterface(); bool hasclassFields = hasClassFields(); bool forcedoc = UMLApp::app()->commonPolicy()->getCodeVerboseDocumentComments(); QString endLine = UMLApp::app()->commonPolicy()->getNewLineEndingChars(); UMLClassifierList superclasses = c->findSuperClassConcepts(); // START GENERATING CODE/TEXT BLOCKS and COMMENTS FOR THE DOCUMENT // // Write the hash define stuff to prevent multiple parsing/inclusion of header QString cppClassName = CodeGenerator::cleanName(c->name()); QString hashDefine = CodeGenerator::cleanName(c->name().toUpper().simplified()); QString defText = QLatin1String("#ifndef ") + hashDefine + QLatin1String("_H") + endLine + QLatin1String("#define ") + hashDefine + QLatin1String("_H"); addOrUpdateTaggedCodeBlockWithComments(QLatin1String("hashDefBlock"), defText, QString(), 0, false); // INCLUDE CODEBLOCK // // Q: Why all utils? Isnt just List and Vector the only classes we are using? // A: doesn't matter at all; its more readable to just include '*' and cpp compilers // don't slow down or anything. (TZ) QString includeStatement; bool stringGlobal = policy->stringIncludeIsGlobal(); QString sStartBrak = stringGlobal ? QLatin1String("<") : QLatin1String("\""); QString sEndBrak = stringGlobal ? QLatin1String(">") : QLatin1String("\""); includeStatement.append(QLatin1String("#include ") + sStartBrak + policy->getStringClassNameInclude() + sEndBrak + endLine); if (hasObjectVectorClassFields()) { bool vecGlobal = policy->vectorIncludeIsGlobal(); QString vStartBrak = vecGlobal ? QLatin1String("<") : QLatin1String("\""); QString vEndBrak = vecGlobal ? QLatin1String(">") : QLatin1String("\""); QString value =QLatin1String("#include ") + vStartBrak + policy->getVectorClassNameInclude() + vEndBrak; includeStatement.append(value + endLine); } //only include classes in a different package from this class UMLPackageList includes; QMap<UMLPackage *, QString> packageMap; // so we don't repeat packages CodeGenerator::findObjectsRelated(c, includes); foreach(UMLPackage* con, includes) { if (con->baseType() != UMLObject::ot_Datatype && !packageMap.contains(con)) { packageMap.insert(con, con->package()); if(con != getParentClassifier()) includeStatement.append(QLatin1String("#include \"") + CodeGenerator::cleanName(con->name().toLower()) + QLatin1String(".h\"") + endLine); } } // now, add/update the includes codeblock CodeBlockWithComments * inclBlock = addOrUpdateTaggedCodeBlockWithComments(QLatin1String("includes"), includeStatement, QString(), 0, false); if(includeStatement.isEmpty() && inclBlock->contentType() == CodeBlock::AutoGenerated) inclBlock->setWriteOutText(false); else inclBlock->setWriteOutText(true); // Using QString usingStatement; foreach(UMLClassifier* classifier, superclasses) { if(classifier->package()!=c->package() && !classifier->package().isEmpty()) { usingStatement.append(QLatin1String("using ") + CodeGenerator::cleanName(c->package()) + QLatin1String("::") + cleanName(c->name()) + QLatin1Char(';') + endLine); } } CodeBlockWithComments * usingBlock = addOrUpdateTaggedCodeBlockWithComments(QLatin1String("using"), usingStatement, QString(), 0, false); if(usingStatement.isEmpty() && usingBlock->contentType() == CodeBlock::AutoGenerated) usingBlock->setWriteOutText(false); else usingBlock->setWriteOutText(true); // namespace // This needs special treatment. We cant use "nowriteouttext" for this, as // that will prevent the class declaration from being written. Instead, we // check if "hasNamspace" is true or not, and then indent the remaining code // appropriately as well as set the start/end text of this namespace block. if (c->umlPackage() && policy->getPackageIsNamespace()) hasNamespace = true; else hasNamespace = false; // set start/end text of namespace block m_namespaceBlock = getHierarchicalCodeBlock(QLatin1String("namespace"), QLatin1String("Namespace"), 0); if(hasNamespace) { UMLPackageList pkgList = c->packages(); QString pkgs; UMLPackage *pkg; foreach (pkg, pkgList) { pkgs += QLatin1String("namespace ") + CodeGenerator::cleanName(pkg->name()) + QLatin1String(" { "); } m_namespaceBlock->setStartText(pkgs); QString closingBraces; foreach (pkg, pkgList) { closingBraces += QLatin1String("} "); }
// This method will cause the class to rebuild its text representation. // based on the parent classifier object. // For any situation in which this is called, we are either building the code // document up, or replacing/regenerating the existing auto-generated parts. As // such, we will want to insert everything we resonablely will want // during creation. We can set various parts of the document (esp. the // comments) to appear or not, as needed. void DClassifierCodeDocument::updateContent() { // Gather info on the various fields and parent objects of this class... UMLClassifier * c = getParentClassifier(); Q_ASSERT(c != 0); CodeGenerationPolicy * commonPolicy = UMLApp::app()->commonPolicy(); CodeGenPolicyExt * pe = UMLApp::app()->policyExt(); DCodeGenerationPolicy * policy = dynamic_cast<DCodeGenerationPolicy*>(pe); // first, set the global flag on whether or not to show classfield info // This depends on whether or not we have attribute/association classes const CodeClassFieldList * cfList = getCodeClassFieldList(); CodeClassFieldList::const_iterator it = cfList->begin(); CodeClassFieldList::const_iterator end = cfList->end(); for (; it != end; ++it) { CodeClassField * field = *it; if (field->parentIsAttribute()) field->setWriteOutMethods(policy->getAutoGenerateAttribAccessors()); else field->setWriteOutMethods(policy->getAutoGenerateAssocAccessors()); } // attribute-based ClassFields // we do it this way to have the static fields sorted out from regular ones CodeClassFieldList staticAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, true); CodeClassFieldList attribClassFields = getSpecificClassFields (CodeClassField::Attribute, false); // association-based ClassFields // don't care if they are static or not..all are lumped together CodeClassFieldList plainAssocClassFields = getSpecificClassFields (CodeClassField::PlainAssociation); CodeClassFieldList aggregationClassFields = getSpecificClassFields (CodeClassField::Aggregation); CodeClassFieldList compositionClassFields = getSpecificClassFields (CodeClassField::Composition); bool isInterface = parentIsInterface(); bool hasOperationMethods = false; UMLOperationList list = c->getOpList(); hasOperationMethods = ! list.isEmpty(); QString endLine = commonPolicy->getNewLineEndingChars(); // a shortcut..so we don't have to call this all the time // // START GENERATING CODE/TEXT BLOCKS and COMMENTS FOR THE DOCUMENT // // // PACKAGE CODE BLOCK // QString pkgs = getPackage(); pkgs.replace(QRegExp(QLatin1String("::")), QLatin1String(".")); QString packageText = getPackage().isEmpty() ? QString() : QString(QLatin1String("package ")+pkgs+QLatin1Char(';')+endLine); CodeBlockWithComments * pblock = addOrUpdateTaggedCodeBlockWithComments(QLatin1String("packages"), packageText, QString(), 0, false); if (packageText.isEmpty() && pblock->contentType() == CodeBlock::AutoGenerated) pblock->setWriteOutText(false); else pblock->setWriteOutText(true); // IMPORT CODEBLOCK // // Q: Why all utils? Aren't just List and Vector the only classes we are using? // A: doesn't matter at all; it is more readable to just include '*' and d compilers // don't slow down or anything. (TZ) QString importStatement; if (hasObjectVectorClassFields()) importStatement.append(QLatin1String("import d.util.*;")); //only import classes in a different package from this class UMLPackageList imports; QMap<UMLPackage*, QString> packageMap; // so we don't repeat packages CodeGenerator::findObjectsRelated(c, imports); for (UMLPackageListIt importsIt(imports); importsIt.hasNext();) { UMLPackage *con = importsIt.next(); // NO (default) datatypes in the import statement.. use defined // ones whould be possible, but no idea how to do that...at least for now. // Dynamic casting is slow..not an optimal way to do this. if (!packageMap.contains(con) && !con->isUMLDatatype()) { packageMap.insert(con, con->package()); // now, we DON'T need to import classes that are already in our own package // (that is, IF a package is specified). Otherwise, we should have a declaration. if (con->package() != c->package() || (c->package().isEmpty() && con->package().isEmpty())) { importStatement.append(endLine+QLatin1String("import ")); if (!con->package().isEmpty()) importStatement.append(con->package()+QLatin1Char('.')); importStatement.append(CodeGenerator::cleanName(con->name())+QLatin1Char(';')); } } } // now, add/update the imports codeblock CodeBlockWithComments * iblock = addOrUpdateTaggedCodeBlockWithComments(QLatin1String("imports"), importStatement, QString(), 0, false); if (importStatement.isEmpty() && iblock->contentType() == CodeBlock::AutoGenerated) iblock->setWriteOutText(false); else iblock->setWriteOutText(true); // CLASS DECLARATION BLOCK // // get the declaration block. If it is not already present, add it too DClassDeclarationBlock * myClassDeclCodeBlock = getClassDecl(); addTextBlock(myClassDeclCodeBlock); // note: wont add if already present // NOW create document in sections.. // now we want to populate the body of our class // our layout is the following general groupings of code blocks: // start d classifier document // header comment // package code block // import code block // class declaration // section: // - class field declaration section comment // - class field declarations (0+ codeblocks) // section: // - methods section comment // sub-section: constructor ops // - constructor method section comment // - constructor methods (0+ codeblocks) // sub-section: accessors // - accessor method section comment // - static accessor methods (0+ codeblocks) // - non-static accessor methods (0+ codeblocks) // sub-section: non-constructor ops // - operation method section comment // - operations (0+ codeblocks) // end class declaration // end d classifier document // Q: Why use the more complicated scheme of arranging code blocks within codeblocks? // A: This will allow us later to preserve the format of our document so that if // codeblocks are added, they may be easily added in the correct place, rather than at // the end of the document, or by using a difficult algorithm to find the location of // the last appropriate code block sibling (which may not exist.. for example user adds // a constructor operation, but there currently are no constructor code blocks // within the document). // // * CLASS FIELD declaration section // // get/create the field declaration code block HierarchicalCodeBlock * fieldDeclBlock = myClassDeclCodeBlock->getHierarchicalCodeBlock(QLatin1String("fieldsDecl"), QLatin1String("Fields"), 1); // Update the comment: we only set comment to appear under the following conditions CodeComment * fcomment = fieldDeclBlock->getComment(); if (isInterface || (!forceDoc() && !hasClassFields())) fcomment->setWriteOutText(false); else fcomment->setWriteOutText(true); // now actually declare the fields within the appropriate HCodeBlock declareClassFields(staticAttribClassFields, fieldDeclBlock); declareClassFields(attribClassFields, fieldDeclBlock); declareClassFields(plainAssocClassFields, fieldDeclBlock); declareClassFields(aggregationClassFields, fieldDeclBlock); declareClassFields(compositionClassFields, fieldDeclBlock); // // METHODS section // // get/create the method codeblock HierarchicalCodeBlock * methodsBlock = myClassDeclCodeBlock->getHierarchicalCodeBlock(QLatin1String("methodsBlock"), QLatin1String("Methods"), 1); // Update the section comment CodeComment * methodsComment = methodsBlock->getComment(); // set conditions for showing this comment if (!forceDoc() && !hasClassFields() && !hasOperationMethods) methodsComment->setWriteOutText(false); else methodsComment->setWriteOutText(true); // METHODS sub-section : constructor methods // // get/create the constructor codeblock HierarchicalCodeBlock * constBlock = methodsBlock->getHierarchicalCodeBlock(QLatin1String("constructorMethods"), QLatin1String("Constructors"), 1); constructorBlock = constBlock; // record this codeblock for later, when operations are updated // special condiions for showing comment: only when autogenerateding empty constructors // Although, we *should* check for other constructor methods too CodeComment * constComment = constBlock->getComment(); CodeGenerationPolicy *pol = UMLApp::app()->commonPolicy(); if (!forceDoc() && (isInterface || !pol->getAutoGenerateConstructors())) constComment->setWriteOutText(false); else constComment->setWriteOutText(true); // add/get the empty constructor QString DClassName = getDClassName(c->name()); QString emptyConstStatement = QLatin1String("public ")+DClassName+QLatin1String(" () { }"); CodeBlockWithComments * emptyConstBlock = constBlock->addOrUpdateTaggedCodeBlockWithComments(QLatin1String("emptyconstructor"), emptyConstStatement, QLatin1String("Empty Constructor"), 1, false); // Now, as an additional condition we only show the empty constructor block // IF it was desired to be shown if (parentIsClass() && pol->getAutoGenerateConstructors()) emptyConstBlock->setWriteOutText(true); else emptyConstBlock->setWriteOutText(false); // METHODS subsection : ACCESSOR METHODS // // get/create the accessor codeblock HierarchicalCodeBlock * accessorBlock = methodsBlock->getHierarchicalCodeBlock(QLatin1String("accessorMethods"), QLatin1String("Accessor Methods"), 1); // set conditions for showing section comment CodeComment * accessComment = accessorBlock->getComment(); if (!forceDoc() && !hasClassFields()) accessComment->setWriteOutText(false); else accessComment->setWriteOutText(true); // now, 2 sub-sub sections in accessor block // add/update accessor methods for attributes HierarchicalCodeBlock * staticAccessors = accessorBlock->getHierarchicalCodeBlock(QLatin1String("staticAccessorMethods"), QString(), 1); staticAccessors->getComment()->setWriteOutText(false); // never write block comment staticAccessors->addCodeClassFieldMethods(staticAttribClassFields); staticAccessors->addCodeClassFieldMethods(attribClassFields); // add/update accessor methods for associations HierarchicalCodeBlock * regularAccessors = accessorBlock->getHierarchicalCodeBlock(QLatin1String("regularAccessorMethods"), QString(), 1); regularAccessors->getComment()->setWriteOutText(false); // never write block comment regularAccessors->addCodeClassFieldMethods(plainAssocClassFields); regularAccessors->addCodeClassFieldMethods(aggregationClassFields); regularAccessors->addCodeClassFieldMethods(compositionClassFields); // METHODS subsection : Operation methods (which arent constructors) // // get/create the operations codeblock operationsBlock = methodsBlock->getHierarchicalCodeBlock(QLatin1String("operationMethods"), QLatin1String("Operations"), 1); // set conditions for showing section comment CodeComment * ocomment = operationsBlock->getComment(); if (!forceDoc() && !hasOperationMethods) ocomment->setWriteOutText(false); else ocomment->setWriteOutText(true); }