1 /*
2 SPDX-License-Identifier: GPL-2.0-or-later
3
4 SPDX-FileCopyrightText: 2003 Brian Thomas <thomas@mail630.gsfc.nasa.gov>
5 SPDX-FileCopyrightText: 2004-2020 Umbrello UML Modeller Authors <umbrello-devel@kde.org>
6 */
7
8 // own header
9 #include "cppheadercodedocument.h"
10
11 // local includes
12 #include "cppcodegenerator.h"
13 #include "cppcodegenerationpolicy.h"
14 #include "cppcodedocumentation.h"
15 #include "cppheadercodeaccessormethod.h"
16 #include "cppheadercodeoperation.h"
17 #include "cppheaderclassdeclarationblock.h"
18 #include "cppheadercodeclassfielddeclarationblock.h"
19 #include "debug_utils.h"
20 #include "umlpackagelist.h"
21 #include "package.h"
22 #include "umlclassifierlistitemlist.h"
23 #include "classifierlistitem.h"
24 #include "enum.h"
25 #include "uml.h"
26
27 // qt includes
28 #include <QRegExp>
29
30 /**
31 * Constructor.
32 */
CPPHeaderCodeDocument(UMLClassifier * concept)33 CPPHeaderCodeDocument::CPPHeaderCodeDocument(UMLClassifier* concept)
34 : ClassifierCodeDocument(concept)
35 {
36 setFileExtension(QLatin1String(".h"));
37
38 //initCodeClassFields(); // this is dubious because it calls down to
39 // CodeGenFactory::newCodeClassField(this)
40 // but "this" is still in construction at that time.
41
42 m_classDeclCodeBlock = 0;
43 m_publicBlock = 0;
44 m_protectedBlock = 0;
45 m_privateBlock = 0;
46 m_namespaceBlock = 0;
47 m_pubConstructorBlock = 0;
48 m_protConstructorBlock = 0;
49 m_privConstructorBlock = 0;
50 m_pubOperationsBlock = 0;
51 m_privOperationsBlock = 0;
52 m_protOperationsBlock = 0;
53
54 // this will call updateContent() as well as other things that sync our document.
55 //synchronize();
56 }
57
58 /**
59 * Destructor.
60 */
~CPPHeaderCodeDocument()61 CPPHeaderCodeDocument::~CPPHeaderCodeDocument()
62 {
63 resetTextBlocks();
64 }
65
getClassDecl()66 CPPHeaderClassDeclarationBlock * CPPHeaderCodeDocument::getClassDecl()
67 {
68 if(!m_classDeclCodeBlock) {
69 m_classDeclCodeBlock = new CPPHeaderClassDeclarationBlock (this); // was deleted before our load
70 m_classDeclCodeBlock->updateContent();
71 m_classDeclCodeBlock->setTag(QLatin1String("classDeclarationBlock"));
72 }
73 return m_classDeclCodeBlock;
74 }
75
76 // Sigh. NOT optimal. The only reason that we need to have this
77 // is so we can create the CPPHeaderClassDeclarationBlock.
78 // would be better if we could create a handler interface that each
79 // codeblock used so all we have to do here is add the handler
loadChildTextBlocksFromNode(QDomElement & root)80 void CPPHeaderCodeDocument::loadChildTextBlocksFromNode (QDomElement & root)
81 {
82 QDomNode tnode = root.firstChild();
83 QDomElement telement = tnode.toElement();
84 bool loadCheckForChildrenOK = false;
85 while(!telement.isNull()) {
86 QString nodeName = telement.tagName();
87
88 if(nodeName == QLatin1String("textblocks")) {
89
90 QDomNode node = telement.firstChild();
91 QDomElement element = node.toElement();
92
93 // if there is nothing to begin with, then we don't worry about it
94 loadCheckForChildrenOK = element.isNull() ? true : false;
95
96 while(!element.isNull()) {
97 QString name = element.tagName();
98
99 if(name == QLatin1String("codecomment")) {
100 CodeComment * block = new CPPCodeDocumentation(this);
101 block->loadFromXMI1(element);
102 if(!addTextBlock(block))
103 {
104 uError()<<"Unable to add codeComment to :"<<this;
105 delete block;
106 } else
107 loadCheckForChildrenOK= true;
108 } else
109 if(name == QLatin1String("codeaccessormethod") ||
110 name == QLatin1String("ccfdeclarationcodeblock")) {
111 QString acctag = element.attribute(QLatin1String("tag"));
112 // search for our method in the
113 TextBlock * tb = findCodeClassFieldTextBlockByTag(acctag);
114 if(!tb || !addTextBlock(tb))
115 {
116 uError()<<"Unable to add codeclassfield child method to:"<<this;
117 // DON'T delete
118 } else
119 loadCheckForChildrenOK= true;
120
121 } else
122 if(name == QLatin1String("codeblock")) {
123 CodeBlock * block = newCodeBlock();
124 block->loadFromXMI1(element);
125 if(!addTextBlock(block))
126 {
127 uError()<<"Unable to add codeBlock to :"<<this;
128 delete block;
129 } else
130 loadCheckForChildrenOK= true;
131 } else
132 if(name == QLatin1String("codeblockwithcomments")) {
133 CodeBlockWithComments * block = newCodeBlockWithComments();
134 block->loadFromXMI1(element);
135 if(!addTextBlock(block))
136 {
137 uError()<<"Unable to add codeBlockwithcomments to:"<<this;
138 delete block;
139 } else
140 loadCheckForChildrenOK= true;
141 } else
142 if(name == QLatin1String("header")) {
143 // do nothing.. this is treated elsewhere
144 } else
145 if(name == QLatin1String("hierarchicalcodeblock")) {
146 HierarchicalCodeBlock * block = newHierarchicalCodeBlock();
147 block->loadFromXMI1(element);
148 if(!addTextBlock(block))
149 {
150 uError()<<"Unable to add hierarchicalcodeBlock to:"<<this;
151 delete block;
152 } else
153 loadCheckForChildrenOK= true;
154 } else
155 if(name == QLatin1String("codeoperation")) {
156 // find the code operation by id
157 QString id = element.attribute(QLatin1String("parent_id"),QLatin1String("-1"));
158 UMLObject * obj = UMLApp::app()->document()->findObjectById(Uml::ID::fromString(id));
159 UMLOperation * op = obj->asUMLOperation();
160 if(op) {
161 CodeOperation * block = new CPPHeaderCodeOperation(this, op);
162 block->updateMethodDeclaration();
163 block->updateContent();
164 block->loadFromXMI1(element);
165 if(addTextBlock(block))
166 loadCheckForChildrenOK= true;
167 else
168 {
169 uError()<<"Unable to add codeoperation to:"<<this;
170 block->deleteLater();
171 }
172 } else
173 uError()<<"Unable to find operation create codeoperation for:"<<this;
174 }
175 else
176 if(name == QLatin1String("cppheaderclassdeclarationblock"))
177 {
178 CPPHeaderClassDeclarationBlock * block = getClassDecl();
179 block->loadFromXMI1(element);
180 // normally this would be populated by the following syncToparent
181 // call, but we cant wait for it, so lets just do it now.
182 m_namespaceBlock = getHierarchicalCodeBlock(QLatin1String("namespace"), QLatin1String("Namespace"), 0);
183
184 if(!m_namespaceBlock || !m_namespaceBlock->addTextBlock(block))
185 {
186 uError()<<"Error:cant add class declaration codeblock";
187 // DON'T delete/release block
188 // block->release();
189 } else
190 loadCheckForChildrenOK= true;
191
192 }
193 // only needed for extreme debugging conditions (E.g. making new codeclassdocument loader)
194 //else
195 //uDebug()<<" LoadFromXMI: Got strange tag in text block stack:"<<name<<", ignoring";
196
197 node = element.nextSibling();
198 element = node.toElement();
199 }
200 break;
201 }
202
203 tnode = telement.nextSibling();
204 telement = tnode.toElement();
205 }
206
207 if(!loadCheckForChildrenOK)
208 {
209 uWarning() << "loadChildBlocks : unable to initialize any child blocks in doc: " << getFileName() << " " << this;
210 }
211
212 }
213
resetTextBlocks()214 void CPPHeaderCodeDocument::resetTextBlocks()
215 {
216 // all special pointers need to be zero'd out.
217 if (m_classDeclCodeBlock) {
218 delete m_classDeclCodeBlock;
219 m_classDeclCodeBlock = 0;
220 }
221 if (m_publicBlock) {
222 delete m_publicBlock;
223 m_publicBlock = 0;
224 }
225 if (m_protectedBlock) {
226 delete m_protectedBlock;
227 m_protectedBlock = 0;
228 }
229 if (m_privateBlock) {
230 delete m_privateBlock;
231 m_privateBlock = 0;
232 }
233 if (m_namespaceBlock) {
234 delete m_namespaceBlock;
235 m_namespaceBlock = 0;
236 }
237 if (m_pubConstructorBlock) {
238 delete m_pubConstructorBlock;
239 m_pubConstructorBlock = 0;
240 }
241 if (m_protConstructorBlock) {
242 delete m_protConstructorBlock;
243 m_protConstructorBlock = 0;
244 }
245 if (m_privConstructorBlock) {
246 delete m_privConstructorBlock;
247 m_privConstructorBlock = 0;
248 }
249 if (m_pubOperationsBlock) {
250 delete m_pubOperationsBlock;
251 m_pubOperationsBlock = 0;
252 }
253 if (m_privOperationsBlock) {
254 delete m_privOperationsBlock;
255 m_privOperationsBlock = 0;
256 }
257 if (m_protOperationsBlock) {
258 delete m_protOperationsBlock;
259 m_protOperationsBlock = 0;
260 }
261
262 // now do the traditional release of child text blocks
263 ClassifierCodeDocument::resetTextBlocks();
264 }
265
266 /**
267 * Add a code operation to this cpp classifier code document.
268 * In the vanilla version, we just tack all operations on the end
269 * of the document.
270 * @param op the code operation
271 * @return bool which is true IF the code operation was added successfully
272 */
addCodeOperation(CodeOperation * op)273 bool CPPHeaderCodeDocument::addCodeOperation(CodeOperation* op)
274 {
275 if (op == 0) {
276 uDebug() << "CodeOperation is null!";
277 return false;;
278 }
279 Uml::Visibility::Enum scope = op->getParentOperation()->visibility();
280 if(!op->getParentOperation()->isLifeOperation())
281 {
282 switch (scope) {
283 default:
284 case Uml::Visibility::Public:
285 return (m_pubOperationsBlock == 0 ? false : m_pubOperationsBlock->addTextBlock(op));
286 break;
287 case Uml::Visibility::Protected:
288 return (m_protOperationsBlock == 0 ? false : m_protOperationsBlock->addTextBlock(op));
289 break;
290 case Uml::Visibility::Private:
291 return (m_privOperationsBlock == 0 ? false : m_privOperationsBlock->addTextBlock(op));
292 break;
293 }
294 } else {
295 switch (scope) {
296 default:
297 case Uml::Visibility::Public:
298 return (m_pubConstructorBlock == 0 ? false : m_pubConstructorBlock->addTextBlock(op));
299 break;
300 case Uml::Visibility::Protected:
301 return (m_protConstructorBlock == 0 ? false : m_protConstructorBlock->addTextBlock(op));
302 break;
303 case Uml::Visibility::Private:
304 return (m_privConstructorBlock == 0 ? false : m_privConstructorBlock->addTextBlock(op));
305 break;
306 }
307 }
308 }
309
310 /**
311 * Save the XMI representation of this object
312 * @return bool status of save
313 */
314 /*
315 void CPPHeaderCodeDocument::saveToXMI1(QXmlStreamWriter& writer)
316 {
317 writer.writeEmptyStartElement();
318
319 setAttributesOnNode(writer);
320
321 writer.writeEndElement();
322 }
323 */
324
325 // This method will cause the class to rebuild its text representation.
326 // based on the parent classifier object.
327 // For any situation in which this is called, we are either building the code
328 // document up, or replacing/regenerating the existing auto-generated parts. As
329 // such, we will want to insert everything we reasonably will want
330 // during creation. We can set various parts of the document (esp. the
331 // comments) to appear or not, as needed.
updateContent()332 void CPPHeaderCodeDocument::updateContent()
333 {
334 // Gather info on the various fields and parent objects of this class...
335 UMLClassifier * c = getParentClassifier();
336 Q_ASSERT(c != 0);
337 CodeGenPolicyExt *pe = UMLApp::app()->policyExt();
338 CPPCodeGenerationPolicy * policy = dynamic_cast<CPPCodeGenerationPolicy*>(pe);
339
340 // first, set the global flag on whether or not to show classfield info
341 const CodeClassFieldList * cfList = getCodeClassFieldList();
342 CodeClassFieldList::const_iterator it = cfList->begin();
343 CodeClassFieldList::const_iterator end = cfList->end();
344 for(; it != end; ++it)
345 (*it)->setWriteOutMethods(policy->getAutoGenerateAccessors());
346
347 // attribute-based ClassFields
348 // we do it this way to have the static fields sorted out from regular ones
349 CodeClassFieldList staticPublicAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, true, Uml::Visibility::Public);
350 CodeClassFieldList publicAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, false, Uml::Visibility::Public);
351 CodeClassFieldList staticProtectedAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, true, Uml::Visibility::Protected);
352 CodeClassFieldList protectedAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, false, Uml::Visibility::Protected);
353 CodeClassFieldList staticPrivateAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, true, Uml::Visibility::Private);
354 CodeClassFieldList privateAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, false, Uml::Visibility::Private);
355
356 // association-based ClassFields
357 // don't care if they are static or not..all are lumped together
358 CodeClassFieldList publicPlainAssocClassFields = getSpecificClassFields (CodeClassField::PlainAssociation, Uml::Visibility::Public);
359 CodeClassFieldList publicAggregationClassFields = getSpecificClassFields (CodeClassField::Aggregation, Uml::Visibility::Public);
360 CodeClassFieldList publicCompositionClassFields = getSpecificClassFields (CodeClassField::Composition, Uml::Visibility::Public);
361
362 CodeClassFieldList protPlainAssocClassFields = getSpecificClassFields (CodeClassField::PlainAssociation, Uml::Visibility::Protected);
363 CodeClassFieldList protAggregationClassFields = getSpecificClassFields (CodeClassField::Aggregation, Uml::Visibility::Protected);
364 CodeClassFieldList protCompositionClassFields = getSpecificClassFields (CodeClassField::Composition, Uml::Visibility::Protected);
365
366 CodeClassFieldList privPlainAssocClassFields = getSpecificClassFields (CodeClassField::PlainAssociation, Uml::Visibility::Private);
367 CodeClassFieldList privAggregationClassFields = getSpecificClassFields (CodeClassField::Aggregation, Uml::Visibility::Private);
368 CodeClassFieldList privCompositionClassFields = getSpecificClassFields (CodeClassField::Composition, Uml::Visibility::Private);
369
370 bool hasOperationMethods = false;
371 UMLOperationList list = c->getOpList();
372 hasOperationMethods = ! list.isEmpty();
373
374 bool hasNamespace = false;
375 bool isEnumeration = false;
376 bool isInterface = parentIsInterface();
377 bool hasclassFields = hasClassFields();
378 bool forcedoc = UMLApp::app()->commonPolicy()->getCodeVerboseDocumentComments();
379 QString endLine = UMLApp::app()->commonPolicy()->getNewLineEndingChars();
380
381 UMLClassifierList superclasses = c->findSuperClassConcepts();
382
383
384 // START GENERATING CODE/TEXT BLOCKS and COMMENTS FOR THE DOCUMENT
385 //
386
387 // Write the hash define stuff to prevent multiple parsing/inclusion of header
388 QString cppClassName = CodeGenerator::cleanName(c->name());
389 QString hashDefine = CodeGenerator::cleanName(c->name().toUpper().simplified());
390 QString defText = QLatin1String("#ifndef ") + hashDefine + QLatin1String("_H") + endLine + QLatin1String("#define ") + hashDefine + QLatin1String("_H");
391 addOrUpdateTaggedCodeBlockWithComments(QLatin1String("hashDefBlock"), defText, QString(), 0, false);
392
393 // INCLUDE CODEBLOCK
394 //
395 // Q: Why all utils? Isnt just List and Vector the only classes we are using?
396 // A: doesn't matter at all; its more readable to just include '*' and cpp compilers
397 // don't slow down or anything. (TZ)
398 QString includeStatement;
399 bool stringGlobal = policy->stringIncludeIsGlobal();
400 QString sStartBrak = stringGlobal ? QLatin1String("<") : QLatin1String("\"");
401 QString sEndBrak = stringGlobal ? QLatin1String(">") : QLatin1String("\"");
402 includeStatement.append(QLatin1String("#include ") + sStartBrak + policy->getStringClassNameInclude() + sEndBrak + endLine);
403 if (hasObjectVectorClassFields())
404 {
405 bool vecGlobal = policy->vectorIncludeIsGlobal();
406 QString vStartBrak = vecGlobal ? QLatin1String("<") : QLatin1String("\"");
407 QString vEndBrak = vecGlobal ? QLatin1String(">") : QLatin1String("\"");
408 QString value =QLatin1String("#include ") + vStartBrak + policy->getVectorClassNameInclude() + vEndBrak;
409 includeStatement.append(value + endLine);
410 }
411
412 //only include classes in a different package from this class
413 UMLPackageList includes;
414 QMap<UMLPackage *, QString> packageMap; // so we don't repeat packages
415
416 CodeGenerator::findObjectsRelated(c, includes);
417 foreach(UMLPackage* con, includes) {
418 if (!con->isUMLDatatype() && !packageMap.contains(con)) {
419 packageMap.insert(con, con->package());
420 if(con != getParentClassifier())
421 includeStatement.append(QLatin1String("#include \"") + CodeGenerator::cleanName(con->name().toLower()) + QLatin1String(".h\"") + endLine);
422 }
423 }
424 // now, add/update the includes codeblock
425 CodeBlockWithComments * inclBlock = addOrUpdateTaggedCodeBlockWithComments(QLatin1String("includes"), includeStatement, QString(), 0, false);
426 if(includeStatement.isEmpty() && inclBlock->contentType() == CodeBlock::AutoGenerated)
427 inclBlock->setWriteOutText(false);
428 else
429 inclBlock->setWriteOutText(true);
430
431 // Using
432 QString usingStatement;
433 foreach(UMLClassifier* classifier, superclasses) {
434 if(classifier->package()!=c->package() && !classifier->package().isEmpty()) {
435 usingStatement.append(QLatin1String("using ") + CodeGenerator::cleanName(c->package()) + QLatin1String("::") + cleanName(c->name()) + QLatin1Char(';') + endLine);
436 }
437 }
438 CodeBlockWithComments * usingBlock = addOrUpdateTaggedCodeBlockWithComments(QLatin1String("using"), usingStatement, QString(), 0, false);
439 if(usingStatement.isEmpty() && usingBlock->contentType() == CodeBlock::AutoGenerated)
440 usingBlock->setWriteOutText(false);
441 else
442 usingBlock->setWriteOutText(true);
443
444 // namespace
445 // This needs special treatment. We cant use "nowriteouttext" for this, as
446 // that will prevent the class declaration from being written. Instead, we
447 // check if "hasNamspace" is true or not, and then indent the remaining code
448 // appropriately as well as set the start/end text of this namespace block.
449 if (c->umlPackage() && policy->getPackageIsNamespace())
450 hasNamespace = true;
451 else
452 hasNamespace = false;
453
454 // set start/end text of namespace block
455 m_namespaceBlock = getHierarchicalCodeBlock(QLatin1String("namespace"), QLatin1String("Namespace"), 0);
456 if(hasNamespace) {
457 UMLPackageList pkgList = c->packages();
458 QString pkgs;
459 UMLPackage *pkg;
460 foreach (pkg, pkgList) {
461 pkgs += QLatin1String("namespace ") + CodeGenerator::cleanName(pkg->name()) + QLatin1String(" { ");
462 }
463 m_namespaceBlock->setStartText(pkgs);
464 QString closingBraces;
465 foreach (pkg, pkgList) {
466 closingBraces += QLatin1String("} ");
467 }
468 m_namespaceBlock->setEndText(closingBraces);
469 m_namespaceBlock->getComment()->setWriteOutText(true);
470 } else {
471 m_namespaceBlock->setStartText(QString());
472 m_namespaceBlock->setEndText(QString());
473 m_namespaceBlock->getComment()->setWriteOutText(false);
474 }
475
476 // Enum types for include
477 if (!isInterface) {
478 QString enumStatement;
479 QString indent = UMLApp::app()->commonPolicy()->getIndentation();
480 UMLEnum* e = c->asUMLEnum();
481 if (e) {
482 enumStatement.append(indent + QLatin1String("enum ") + cppClassName + QLatin1String(" {") + endLine);
483
484 // populate
485 UMLClassifierListItemList ell = e->getFilteredList(UMLObject::ot_EnumLiteral);
486 for (UMLClassifierListItemListIt elit(ell) ; elit.hasNext() ;) {
487 UMLClassifierListItem* el = elit.next();
488 enumStatement.append(indent + indent);
489 enumStatement.append(CodeGenerator::cleanName(el->name()));
490 if (elit.hasNext()) {
491 el=elit.next();
492 enumStatement.append(QLatin1String(", ") + endLine);
493 } else {
494 break;
495 }
496 enumStatement.append(endLine);
497 }
498 enumStatement.append(indent + QLatin1String("};"));
499 isEnumeration = true;
500 }
501 m_namespaceBlock->addOrUpdateTaggedCodeBlockWithComments(QLatin1String("enums"), enumStatement, QString(), 0, false);
502 }
503
504 // CLASS DECLARATION BLOCK
505 //
506
507 // add the class declaration block to the namespace block.
508 CPPHeaderClassDeclarationBlock * myClassDeclCodeBlock = getClassDecl();
509 m_namespaceBlock->addTextBlock(myClassDeclCodeBlock); // note: wont add if already present
510
511 // Is this really true?? hmm..
512 if(isEnumeration)
513 myClassDeclCodeBlock->setWriteOutText(false); // not written out IF its an enumeration class
514 else
515 myClassDeclCodeBlock->setWriteOutText(true);
516
517 //
518 // Main Sub-Blocks
519 //
520
521 // declare public, protected and private methods, attributes (fields).
522 // set the start text ONLY if this is the first time we created the objects.
523 bool createdPublicBlock = m_publicBlock == 0 ? true : false;
524 m_publicBlock = myClassDeclCodeBlock->getHierarchicalCodeBlock(QLatin1String("publicBlock"),QLatin1String("Public stuff"), 0);
525 if (createdPublicBlock)
526 m_publicBlock->setStartText(QLatin1String("public:"));
527
528 bool createdProtBlock = m_protectedBlock == 0 ? true : false;
529 m_protectedBlock = myClassDeclCodeBlock->getHierarchicalCodeBlock(QLatin1String("protectedBlock"),QLatin1String("Protected stuff"), 0);
530 if(createdProtBlock)
531 m_protectedBlock->setStartText(QLatin1String("protected:"));
532
533 bool createdPrivBlock = m_privateBlock == 0 ? true : false;
534 m_privateBlock = myClassDeclCodeBlock->getHierarchicalCodeBlock(QLatin1String("privateBlock"),QLatin1String("Private stuff"), 0);
535 if(createdPrivBlock)
536 m_privateBlock->setStartText(QLatin1String("private:"));
537
538 //
539 // * CLASS FIELD declaration section
540 //
541
542 // setup/get/create the field declaration code block
543 //
544
545 // public fields: Update the comment: we only set comment to appear under the following conditions
546 HierarchicalCodeBlock * publicFieldDeclBlock = m_publicBlock->getHierarchicalCodeBlock(QLatin1String("publicFieldsDecl"), QLatin1String("Fields"), 1);
547 CodeComment * pubFcomment = publicFieldDeclBlock->getComment();
548 if (!forcedoc && !hasclassFields)
549 pubFcomment->setWriteOutText(false);
550 else
551 pubFcomment->setWriteOutText(true);
552
553 // protected fields: Update the comment: we only set comment to appear under the following conditions
554 HierarchicalCodeBlock * protectedFieldDeclBlock = m_protectedBlock->getHierarchicalCodeBlock(QLatin1String("protectedFieldsDecl"), QLatin1String("Fields"), 1);
555 CodeComment * protFcomment = protectedFieldDeclBlock->getComment();
556 if (!forcedoc && !hasclassFields)
557 protFcomment->setWriteOutText(false);
558 else
559 protFcomment->setWriteOutText(true);
560
561 // private fields: Update the comment: we only set comment to appear under the following conditions
562 HierarchicalCodeBlock * privateFieldDeclBlock = m_privateBlock->getHierarchicalCodeBlock(QLatin1String("privateFieldsDecl"), QLatin1String("Fields"), 1);
563 CodeComment * privFcomment = privateFieldDeclBlock->getComment();
564 if (!forcedoc && !hasclassFields)
565 privFcomment->setWriteOutText(false);
566 else
567 privFcomment->setWriteOutText(true);
568
569
570 // now actually declare the fields within the appropriate HCodeBlock
571 //
572
573 // public
574 declareClassFields(staticPublicAttribClassFields, publicFieldDeclBlock);
575 declareClassFields(publicAttribClassFields, publicFieldDeclBlock);
576 declareClassFields(publicPlainAssocClassFields, publicFieldDeclBlock);
577 declareClassFields(publicAggregationClassFields, publicFieldDeclBlock);
578 declareClassFields(publicCompositionClassFields, publicFieldDeclBlock);
579
580 // protected
581 declareClassFields(staticProtectedAttribClassFields, protectedFieldDeclBlock);
582 declareClassFields(protectedAttribClassFields, protectedFieldDeclBlock);
583 declareClassFields(protPlainAssocClassFields, protectedFieldDeclBlock);
584 declareClassFields(protAggregationClassFields, protectedFieldDeclBlock);
585 declareClassFields(protCompositionClassFields, protectedFieldDeclBlock);
586
587 // private
588 declareClassFields(staticPrivateAttribClassFields, privateFieldDeclBlock);
589 declareClassFields(privateAttribClassFields, privateFieldDeclBlock);
590 declareClassFields(privPlainAssocClassFields, privateFieldDeclBlock);
591 declareClassFields(privAggregationClassFields, privateFieldDeclBlock);
592 declareClassFields(privCompositionClassFields, privateFieldDeclBlock);
593
594 //
595 // METHODS section
596 //
597
598 // get/create the method codeblock
599
600 // public methods
601 HierarchicalCodeBlock * pubMethodsBlock = m_publicBlock->getHierarchicalCodeBlock(QLatin1String("pubMethodsBlock"), QString(), 1);
602 CodeComment * pubMethodsComment = pubMethodsBlock->getComment();
603 // set conditions for showing this comment
604 if (!forcedoc && !hasclassFields && !hasOperationMethods)
605 pubMethodsComment->setWriteOutText(false);
606 else
607 pubMethodsComment->setWriteOutText(true);
608
609 // protected methods
610 HierarchicalCodeBlock * protMethodsBlock = m_protectedBlock->getHierarchicalCodeBlock(QLatin1String("protMethodsBlock"), QString(), 1);
611 CodeComment * protMethodsComment = protMethodsBlock->getComment();
612 // set conditions for showing this comment
613 if (!forcedoc && !hasclassFields && !hasOperationMethods)
614 protMethodsComment->setWriteOutText(false);
615 else
616 protMethodsComment->setWriteOutText(true);
617
618 // private methods
619 HierarchicalCodeBlock * privMethodsBlock = m_privateBlock->getHierarchicalCodeBlock(QLatin1String("privMethodsBlock"), QString(), 1);
620 CodeComment * privMethodsComment = privMethodsBlock->getComment();
621 // set conditions for showing this comment
622 if (!forcedoc && !hasclassFields && !hasOperationMethods)
623 privMethodsComment->setWriteOutText(false);
624 else
625 privMethodsComment->setWriteOutText(true);
626
627
628 // METHODS sub-section : constructor methods
629 //
630 CodeGenerationPolicy *pol = UMLApp::app()->commonPolicy();
631
632 // setup/get/create the constructor codeblocks
633
634 // public
635 m_pubConstructorBlock = pubMethodsBlock->getHierarchicalCodeBlock(QLatin1String("constructionMethods"), QLatin1String("Constructors"), 1);
636 // special conditions for showing comment: only when autogenerateding empty constructors
637 // Although, we *should* check for other constructor methods too
638 CodeComment * pubConstComment = m_pubConstructorBlock->getComment();
639 if (!forcedoc && (isInterface || !pol->getAutoGenerateConstructors()))
640 pubConstComment->setWriteOutText(false);
641 else
642 pubConstComment->setWriteOutText(true);
643
644 // protected
645 m_protConstructorBlock = protMethodsBlock->getHierarchicalCodeBlock(QLatin1String("constructionMethods"), QLatin1String("Constructors"), 1);
646 // special conditions for showing comment: only when autogenerateding empty constructors
647 // Although, we *should* check for other constructor methods too
648 CodeComment * protConstComment = m_protConstructorBlock->getComment();
649 if (!forcedoc && (isInterface || !pol->getAutoGenerateConstructors()))
650 protConstComment->setWriteOutText(false);
651 else
652 protConstComment->setWriteOutText(true);
653
654 // private
655 m_privConstructorBlock = privMethodsBlock->getHierarchicalCodeBlock(QLatin1String("constructionMethods"), QLatin1String("Constructors"), 1);
656 // special conditions for showing comment: only when autogenerateding empty constructors
657 // Although, we *should* check for other constructor methods too
658 CodeComment * privConstComment = m_privConstructorBlock->getComment();
659 if (!forcedoc && (isInterface || !pol->getAutoGenerateConstructors()))
660 privConstComment->setWriteOutText(false);
661 else
662 privConstComment->setWriteOutText(true);
663
664 // add/get the empty constructor. I guess since there is no
665 // meta-data to state what the scope of this method is, we will make it
666 // "public" as a default. This might present problems if the user wants
667 // to move the block into the "private" or "protected" blocks.
668 QString emptyConstStatement = cppClassName + QLatin1String(" () { }");
669
670 // search for this first in the entire document. IF not present, put
671 // it in the public constructor method block
672 TextBlock * emptyConstTb = findTextBlockByTag(QLatin1String("emptyconstructor"), true);
673 CodeBlockWithComments * emptyConstBlock = dynamic_cast<CodeBlockWithComments*>(emptyConstTb);
674 if(!emptyConstBlock)
675 emptyConstBlock = m_pubConstructorBlock->addOrUpdateTaggedCodeBlockWithComments(QLatin1String("emptyconstructor"), emptyConstStatement, QLatin1String("Empty Constructor"), 1, false);
676
677 // Now, as an additional condition we only show the empty constructor block
678 // IF it was desired to be shown
679 if(!isInterface && pol->getAutoGenerateConstructors())
680 emptyConstBlock->setWriteOutText(true);
681 else
682 emptyConstBlock->setWriteOutText(false);
683
684
685 // METHODS subsection : ACCESSOR METHODS
686 //
687
688 // get/create the accessor codeblock
689
690 // public
691 HierarchicalCodeBlock * pubAccessorBlock = pubMethodsBlock->getHierarchicalCodeBlock(QLatin1String("accessorMethods"), QLatin1String("Accessor Methods"), 1);
692 // set conditions for showing section comment
693 CodeComment * pubAccessComment = pubAccessorBlock->getComment();
694 if (!forcedoc && !hasclassFields)
695 pubAccessComment->setWriteOutText(false);
696 else
697 pubAccessComment->setWriteOutText(true);
698
699 // protected
700 HierarchicalCodeBlock * protAccessorBlock = protMethodsBlock->getHierarchicalCodeBlock(QLatin1String("accessorMethods"), QLatin1String("Accessor Methods"), 1);
701 // set conditions for showing section comment
702 CodeComment * protAccessComment = protAccessorBlock->getComment();
703 if (!forcedoc && !hasclassFields)
704 protAccessComment->setWriteOutText(false);
705 else
706 protAccessComment->setWriteOutText(true);
707
708 // private
709 HierarchicalCodeBlock * privAccessorBlock = privMethodsBlock->getHierarchicalCodeBlock(QLatin1String("accessorMethods"), QLatin1String("Accessor Methods"), 1);
710 // set conditions for showing section comment
711 CodeComment * privAccessComment = privAccessorBlock->getComment();
712 // We've to copy the private accessorMethods to the public block
713 if (!forcedoc && !hasclassFields)
714 privAccessComment->setWriteOutText(false);
715 else
716 privAccessComment->setWriteOutText(true);
717
718 // now, 2 sub-sub sections in accessor block
719 // add/update accessor methods for attributes
720 HierarchicalCodeBlock * pubStaticAccessors = pubAccessorBlock->getHierarchicalCodeBlock(QLatin1String("pubStaticAccessorMethods"), QString(), 1);
721 HierarchicalCodeBlock * pubRegularAccessors = pubAccessorBlock->getHierarchicalCodeBlock(QLatin1String("pubRegularAccessorMethods"), QString(), 1);
722 pubStaticAccessors->getComment()->setWriteOutText(false); // never write block comment
723 pubRegularAccessors->getComment()->setWriteOutText(false); // never write block comment
724
725 HierarchicalCodeBlock * protStaticAccessors = protAccessorBlock->getHierarchicalCodeBlock(QLatin1String("protStaticAccessorMethods"), QString(), 1);
726 HierarchicalCodeBlock * protRegularAccessors = protAccessorBlock->getHierarchicalCodeBlock(QLatin1String("protRegularAccessorMethods"), QString(), 1);
727 protStaticAccessors->getComment()->setWriteOutText(false); // never write block comment
728 protRegularAccessors->getComment()->setWriteOutText(false); // never write block comment
729
730 HierarchicalCodeBlock * privStaticAccessors = privAccessorBlock->getHierarchicalCodeBlock(QLatin1String("privStaticAccessorMethods"), QString(), 1);
731 HierarchicalCodeBlock * privRegularAccessors = privAccessorBlock->getHierarchicalCodeBlock(QLatin1String("privRegularAccessorMethods"), QString(), 1);
732 privStaticAccessors->getComment()->setWriteOutText(false); // never write block comment
733 privRegularAccessors->getComment()->setWriteOutText(false); // never write block comment
734
735 // now add in accessors as appropriate
736
737 // public stuff
738 pubStaticAccessors->addCodeClassFieldMethods(staticPublicAttribClassFields);
739 pubRegularAccessors->addCodeClassFieldMethods(publicAttribClassFields);
740
741 // generate accessors as public
742 if (policy && policy->getAccessorsArePublic())
743 {
744 pubRegularAccessors->addCodeClassFieldMethods(privateAttribClassFields);
745 pubRegularAccessors->addCodeClassFieldMethods(protectedAttribClassFields);
746 }
747
748 pubRegularAccessors->addCodeClassFieldMethods(publicPlainAssocClassFields);
749 pubRegularAccessors->addCodeClassFieldMethods(publicAggregationClassFields);
750 pubRegularAccessors->addCodeClassFieldMethods(publicCompositionClassFields);
751
752 // protected stuff
753 protStaticAccessors->addCodeClassFieldMethods(staticProtectedAttribClassFields);
754
755 // accessors are public so we don't have to create it here
756 if (policy && !policy->getAccessorsArePublic())
757 protRegularAccessors->addCodeClassFieldMethods(protectedAttribClassFields);
758
759 protRegularAccessors->addCodeClassFieldMethods(protPlainAssocClassFields);
760 protRegularAccessors->addCodeClassFieldMethods(protAggregationClassFields);
761 protRegularAccessors->addCodeClassFieldMethods(protCompositionClassFields);
762
763 // private stuff
764 privStaticAccessors->addCodeClassFieldMethods(staticPrivateAttribClassFields);
765
766 // accessors are public so we don't have to create it here
767 if (policy && !policy->getAccessorsArePublic())
768 privRegularAccessors->addCodeClassFieldMethods(privateAttribClassFields);
769
770 privRegularAccessors->addCodeClassFieldMethods(privPlainAssocClassFields);
771 privRegularAccessors->addCodeClassFieldMethods(privAggregationClassFields);
772 privRegularAccessors->addCodeClassFieldMethods(privCompositionClassFields);
773
774
775 // METHODS subsection : Operation methods (e.g. methods derive from operations but which arent constructors)
776 //
777
778 // setup/get/create the operations codeblock
779
780 // public
781 m_pubOperationsBlock = pubMethodsBlock->getHierarchicalCodeBlock(QLatin1String("operationMethods"), QLatin1String("Operations"), 1);
782 // set conditions for showing section comment
783 CodeComment * pubOcomment = m_pubOperationsBlock->getComment();
784 if (!forcedoc && !hasOperationMethods)
785 pubOcomment->setWriteOutText(false);
786 else
787 pubOcomment->setWriteOutText(true);
788
789 //protected
790 m_protOperationsBlock = protMethodsBlock->getHierarchicalCodeBlock(QLatin1String("operationMethods"), QLatin1String("Operations"), 1);
791 // set conditions for showing section comment
792 CodeComment * protOcomment = m_protOperationsBlock->getComment();
793 if (!forcedoc && !hasOperationMethods)
794 protOcomment->setWriteOutText(false);
795 else
796 protOcomment->setWriteOutText(true);
797
798 //private
799 m_privOperationsBlock = privMethodsBlock->getHierarchicalCodeBlock(QLatin1String("operationMethods"), QLatin1String("Operations"), 1);
800 // set conditions for showing section comment
801 CodeComment * privOcomment = m_privOperationsBlock->getComment();
802 if (!forcedoc && !hasOperationMethods)
803 privOcomment->setWriteOutText(false);
804 else
805 privOcomment->setWriteOutText(true);
806
807 // Operations
808 //
809 // nothing to do here.. "updateOperations" in parent class puts things
810 // in the right place using the "addCodeOperation" method we defined in this class
811
812 // FINISH up with hash def block close
813 QString defTextEnd = QLatin1String("#endif //") + hashDefine + QLatin1String("_H");
814 addOrUpdateTaggedCodeBlockWithComments(QLatin1String("hashDefBlockEnd"), defTextEnd, QString(), 0, false);
815 }
816
817