void DCodeGenerationPolicyPage::apply() { CodeGenerationPolicy *commonPolicy = UMLApp::app()->commonPolicy(); DCodeGenerationPolicy * parent = (DCodeGenerationPolicy*) m_parentPolicy; // block signals so we don't cause too many update content calls to code documents commonPolicy->blockSignals(true); commonPolicy->setCommentStyle((CodeGenerationPolicy::CommentStyle) form->m_SelectCommentStyle->currentIndex()); commonPolicy->setAttributeAccessorScope(Uml::Visibility::fromInt(form->m_accessorScopeCB->currentIndex())); commonPolicy->setAssociationFieldScope(Uml::Visibility::fromInt(form->m_assocFieldScopeCB->currentIndex())); commonPolicy->setAutoGenerateConstructors(form->m_generateConstructors->isChecked()); parent->setAutoGenerateAttribAccessors(form->m_generateAttribAccessors->isChecked()); parent->setAutoGenerateAssocAccessors(form->m_generateAssocAccessors->isChecked()); /** * @todo unclean - CreateANTBuildFile attribute should be in d policy CodeGenerator *codegen = UMLApp::app()->getGenerator(); DCodeGenerator *dcodegen = dynamic_cast<DCodeGenerator*>(codegen); if (dcodegen) dcodegen->setCreateANTBuildFile(form->m_makeANTDocumentCheckBox->isChecked()); */ commonPolicy->blockSignals(false); // now send out modified code content signal commonPolicy->emitModifiedCodeContentSig(); }
/** * Set the defaults for this code generator from the passed generator. * @param clone the code gen policy ext object * @param emitUpdateSignal flag whether to emit the update signal */ void DCodeGenerationPolicy::setDefaults ( CodeGenPolicyExt * clone, bool emitUpdateSignal ) { DCodeGenerationPolicy * jclone; if (!clone) return; // NOW block signals for d param setting blockSignals(true); // we need to do this because otherwise most of these // settors below will each send the modifiedCodeContent() signal // needlessly (we can just make one call at the end). // now do d-specific stuff IF our clone is also a DCodeGenerationPolicy object if((jclone = dynamic_cast<DCodeGenerationPolicy*>(clone))) { setAutoGenerateAttribAccessors(jclone->getAutoGenerateAttribAccessors()); setAutoGenerateAssocAccessors(jclone->getAutoGenerateAssocAccessors()); } blockSignals(false); // "as you were citizen" if(emitUpdateSignal) { m_commonPolicy->emitModifiedCodeContentSig(); } }
// 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); }