1 /******************************************************************************
2 *
3 *
4 *
5 * Copyright (C) 1997-2015 by Dimitri van Heesch.
6 *
7 * Permission to use, copy, modify, and distribute this software and its
8 * documentation under the terms of the GNU General Public License is hereby
9 * granted. No representations are made about the suitability of this software
10 * for any purpose. It is provided "as is" without express or implied warranty.
11 * See the GNU General Public License for more details.
12 *
13 * Documents produced by Doxygen are derivative works derived from the
14 * input used in their production; they are not affected by this license.
15 *
16 */
17
18 #include "memberlist.h"
19 #include "classdef.h"
20 #include "message.h"
21 #include "util.h"
22 #include "language.h"
23 #include "doxygen.h"
24 #include "outputlist.h"
25 #include "groupdef.h"
26 #include "vhdldocgen.h"
27 #include "namespacedef.h"
28 #include "filedef.h"
29 #include "membergroup.h"
30 #include "config.h"
31 #include "docparser.h"
32
MemberList(MemberListType lt,MemberListContainer con)33 MemberList::MemberList(MemberListType lt,MemberListContainer con) : m_container(con), m_listType(lt)
34 {
35 //printf("%p: MemberList::MemberList(%d)\n",this,lt);
36 m_numDecMembers=-1; // special value indicating that value needs to be computed
37 m_numDecEnumValues=0;
38 m_numDocMembers=-1; // special value indicating that value needs to be computed
39 m_numDocEnumValues=0;
40 m_needsSorting=FALSE;
41 }
42
~MemberList()43 MemberList::~MemberList()
44 {
45 }
46
genericCompareMembers(const MemberDef * c1,const MemberDef * c2)47 int genericCompareMembers(const MemberDef *c1,const MemberDef *c2)
48 {
49 bool sortConstructorsFirst = Config_getBool(SORT_MEMBERS_CTORS_1ST);
50 if (sortConstructorsFirst)
51 {
52 int ord1 = c1->isConstructor() ? 2 : (c1->isDestructor() ? 1 : 0);
53 int ord2 = c2->isConstructor() ? 2 : (c2->isDestructor() ? 1 : 0);
54 if (ord1 > ord2)
55 return -1;
56 else if (ord2 > ord1)
57 return 1;
58 }
59 // sort on name
60 int cmp = qstricmp(c1->name(),c2->name());
61 // then on argument list
62 if (cmp==0 && !c1->argsString().isEmpty() && !c2->argsString().isEmpty())
63 {
64 cmp = qstricmp(c1->argsString(),c2->argsString());
65 }
66 // then on file in which the item is defined
67 if (cmp==0)
68 {
69 cmp = qstricmp(c1->getDefFileName(),c2->getDefFileName());
70 }
71 // then on line number at which the member is defined
72 if (cmp==0)
73 {
74 cmp = c1->getDefLine()-c2->getDefLine();
75 }
76 return cmp;
77 }
78
countInheritableMembers(const ClassDef * inheritedFrom) const79 int MemberList::countInheritableMembers(const ClassDef *inheritedFrom) const
80 {
81 int count=0;
82 for (const auto &md : m_members)
83 {
84 if (md->isBriefSectionVisible())
85 {
86 if (md->memberType()!=MemberType_Friend &&
87 md->memberType()!=MemberType_EnumValue)
88 {
89 //printf("member %s: isReimplementedBy(%s)=%d\n",qPrint(md->name()),
90 // qPrint(inheritedFrom->name()),
91 // md->isReimplementedBy(inheritedFrom));
92 if (md->memberType()==MemberType_Function)
93 {
94 if (!md->isReimplementedBy(inheritedFrom)) count++;
95 }
96 else
97 {
98 count++;
99 }
100 }
101 }
102 }
103 for (const auto &mg : m_memberGroupRefList)
104 {
105 count+=mg->countInheritableMembers(inheritedFrom);
106 }
107 //printf("%s::countInheritableMembers(%s)=%d\n",
108 // qPrint(listTypeAsString()),
109 // qPrint(inheritedFrom->name()),count);
110 return count;
111 }
112
113 /*! Count the number of members in this list that are visible in
114 * the declaration part of a compound's documentation page.
115 */
countDecMembers()116 void MemberList::countDecMembers()
117 {
118 if (m_numDecMembers!=-1) return;
119
120 //printf("----- countDecMembers count=%d ----\n",count());
121 /*
122 m_varCnt=m_funcCnt=m_enumCnt=m_enumValCnt=0;
123 m_typeCnt=m_seqCnt=m_dictCnt=m_protoCnt=m_defCnt=m_friendCnt=0;
124 */
125 m_numDecMembers=0;
126 for (const auto &md : m_members)
127 {
128 //printf("MemberList::countDecMembers(md=%s,%d)\n",qPrint(md->name()),md->isBriefSectionVisible());
129 if (md->isBriefSectionVisible())
130 {
131 switch(md->memberType())
132 {
133 case MemberType_Variable: // fall through
134 case MemberType_Event: // fall through
135 case MemberType_Property: /*m_varCnt++,*/
136 m_numDecMembers++;
137 break;
138 // apparently necessary to get this to show up in declarations section?
139 case MemberType_Interface: // fall through
140 case MemberType_Service: // fall through
141 case MemberType_Function: // fall through
142 case MemberType_Signal: // fall through
143 case MemberType_DCOP: // fall through
144 case MemberType_Slot: if (!md->isRelated() || md->getClassDef())
145 /*m_funcCnt++,*/
146 m_numDecMembers++;
147 break;
148 case MemberType_Enumeration: /*m_enumCnt++,*/
149 m_numDecMembers++;
150 break;
151 case MemberType_EnumValue: m_numDecEnumValues++;
152 m_numDecMembers++;
153 break;
154 case MemberType_Typedef: /*m_typeCnt++,*/
155 m_numDecMembers++;
156 break;
157 case MemberType_Sequence: /*m_seqCnt++,*/
158 m_numDecMembers++;
159 break;
160 case MemberType_Dictionary: /*m_dictCnt++,*/
161 m_numDecMembers++;
162 break;
163 //case MemberType_Prototype: m_protoCnt++,m_numDecMembers++; break;
164 case MemberType_Define: if (Config_getBool(EXTRACT_ALL) ||
165 !md->argsString().isEmpty() ||
166 !md->initializer().isEmpty() ||
167 md->hasDocumentation()
168 ) /*m_defCnt++,*/ m_numDecMembers++;
169 break;
170 case MemberType_Friend: /*m_friendCnt++,*/
171 m_numDecMembers++;
172 break;
173 default:
174 err("Unknown member type found for member '%s'\n!",qPrint(md->name()));
175 }
176 }
177 }
178 for (const auto &mg : m_memberGroupRefList)
179 {
180 mg->countDecMembers();
181 /*
182 m_varCnt+=mg->varCount();
183 m_funcCnt+=mg->funcCount();
184 m_enumCnt+=mg->enumCount();
185 m_enumValCnt+=mg->enumValueCount();
186 m_typeCnt+=mg->typedefCount();
187 m_seqCnt+=mg->sequenceCount();
188 m_dictCnt+=mg->dictionaryCount();
189 m_protoCnt+=mg->protoCount();
190 m_defCnt+=mg->defineCount();
191 m_friendCnt+=mg->friendCount();
192 */
193 m_numDecMembers+=mg->numDecMembers();
194 m_numDecEnumValues+=mg->numDecEnumValues();
195 }
196 //printf("----- end countDecMembers ----\n");
197
198 //printf("MemberList::countDecMembers()=%d\n",m_numDecMembers);
199 }
200
countDocMembers()201 void MemberList::countDocMembers()
202 {
203 if (m_numDocMembers!=-1) return; // used cached value
204 m_numDocMembers=0;
205 for (const auto &md : m_members)
206 {
207 if (md->isDetailedSectionVisible(m_container) && !md->isAlias())
208 {
209 // do not count enum values, since they do not produce entries of their own
210 if (md->memberType()==MemberType_EnumValue)
211 {
212 m_numDocEnumValues++;
213 }
214 m_numDocMembers++;
215 }
216 }
217 for (const auto &mg : m_memberGroupRefList)
218 {
219 mg->countDocMembers();
220 m_numDocMembers+=mg->numDocMembers();
221 m_numDocEnumValues+=mg->numDocEnumValues();
222 }
223 //printf("MemberList::countDocMembers()=%d memberGroupList=%p\n",m_numDocMembers,memberGroupList);
224 }
225
setAnonymousEnumType()226 void MemberList::setAnonymousEnumType()
227 {
228 //printf("MemberList(%p)::setAnonymousEnumType()\n",this);
229 for (const auto &md : m_members)
230 {
231 if (md->isBriefSectionVisible())
232 {
233 QCString name(md->name());
234 int i=name.findRev("::");
235 if (i!=-1) name=name.right(name.length()-i-2);
236 if (md->memberType()==MemberType_Enumeration && name[0]=='@')
237 {
238 for (const auto &vmd : md->enumFieldList())
239 {
240 MemberDefMutable *vmdm = toMemberDefMutable(vmd);
241 if (vmdm)
242 {
243 QCString vtype=vmd->typeString();
244 if ((vtype.find(name))!=-1)
245 {
246 vmdm->setAnonymousEnumType(md);
247 }
248 }
249 }
250 }
251 }
252 }
253 for (const auto &mg : m_memberGroupRefList)
254 {
255 mg->setAnonymousEnumType();
256 }
257 }
258
countEnumValues(const MemberDef * md) const259 int MemberList::countEnumValues(const MemberDef *md) const
260 {
261 int numEnumValues=0;
262 QCString name(md->name());
263 int i=name.findRev("::");
264 if (i!=-1) name=name.right(name.length()-i-2);
265 if (name[0]=='@')
266 {
267 for (const auto &vmd : m_members)
268 {
269 QCString vtype=vmd->typeString();
270 if ((vtype.find(name))!=-1)
271 {
272 numEnumValues++;
273 }
274 }
275 }
276 return numEnumValues;
277 }
278
declVisible() const279 bool MemberList::declVisible() const
280 {
281 for (const auto &md : m_members)
282 {
283 if (md->isBriefSectionVisible())
284 {
285 switch (md->memberType())
286 {
287 case MemberType_Define: // fall through
288 case MemberType_Typedef: // fall through
289 case MemberType_Variable: // fall through
290 case MemberType_Function: // fall through
291 case MemberType_Signal: // fall through
292 case MemberType_Slot: // fall through
293 case MemberType_DCOP: // fall through
294 case MemberType_Property: // fall through
295 case MemberType_Interface: // fall through
296 case MemberType_Service: // fall through
297 case MemberType_Sequence: // fall through
298 case MemberType_Dictionary: // fall through
299 case MemberType_Event:
300 return TRUE;
301 case MemberType_Enumeration:
302 {
303 // if this is an anonymous enum and there are variables of this
304 // enum type (i.e. enumVars>0), then we do not show the enum here.
305 if (countEnumValues(md)==0) // show enum here
306 {
307 return TRUE;
308 }
309 }
310 break;
311 case MemberType_Friend:
312 return TRUE;
313 case MemberType_EnumValue:
314 {
315 if (m_container==MemberListContainer::Group)
316 {
317 return TRUE;
318 }
319 }
320 break;
321 }
322 }
323 }
324 return FALSE;
325 }
326
writePlainDeclarations(OutputList & ol,bool inGroup,const ClassDef * cd,const NamespaceDef * nd,const FileDef * fd,const GroupDef * gd,int indentLevel,const ClassDef * inheritedFrom,const QCString & inheritId) const327 void MemberList::writePlainDeclarations(OutputList &ol, bool inGroup,
328 const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd, const GroupDef *gd,
329 int indentLevel, const ClassDef *inheritedFrom,const QCString &inheritId
330 ) const
331 {
332 //printf("----- writePlainDeclaration() ----\n");
333 if (numDecMembers()==-1)
334 {
335 err("MemberList::numDecMembers()==-1, so the members of this list have not been counted. Please report as a bug.\n");
336 abort();
337 }
338 if (numDecMembers()<=numDecEnumValues())
339 {
340 //printf(" --> no members!\n");
341 return; // no members in this list
342 }
343 //printf(" --> writePlainDeclaration() numDecMembers()=%d\n",
344 // numDecMembers());
345
346 ol.pushGeneratorState();
347
348 bool first=TRUE;
349 for (const auto &md : m_members)
350 {
351 //printf(">>> Member '%s' type=%d visible=%d\n",
352 // qPrint(md->name()),md->memberType(),md->isBriefSectionVisible());
353 if ((inheritedFrom==0 || !md->isReimplementedBy(inheritedFrom)) &&
354 md->isBriefSectionVisible())
355 {
356 //printf(">>> rendering\n");
357 switch(md->memberType())
358 {
359 case MemberType_Define: // fall through
360 //case MemberType_Prototype: // fall through
361 case MemberType_Typedef: // fall through
362 case MemberType_Variable: // fall through
363 case MemberType_Function: // fall through
364 case MemberType_Signal: // fall through
365 case MemberType_Slot: // fall through
366 case MemberType_DCOP: // fall through
367 case MemberType_Property: // fall through
368 case MemberType_Interface: // fall through
369 case MemberType_Service: // fall through
370 case MemberType_Sequence: // fall through
371 case MemberType_Dictionary: // fall through
372 case MemberType_Event:
373 {
374 if (first) ol.startMemberList(),first=FALSE;
375 md->writeDeclaration(ol,cd,nd,fd,gd,inGroup,indentLevel,inheritedFrom,inheritId);
376 break;
377 }
378 case MemberType_Enumeration:
379 {
380 // if this is an anonymous enum and there are variables of this
381 // enum type (i.e. enumVars>0), then we do not show the enum here.
382 if (countEnumValues(md)==0) // show enum here
383 {
384 //printf("Enum!!\n");
385 if (first)
386 {
387 ol.startMemberList();
388 first=FALSE;
389 }
390 ol.startMemberDeclaration();
391 ol.startMemberItem(md->anchor(),0,inheritId);
392 bool detailsLinkable = md->hasDetailedDescription();
393 if (!detailsLinkable)
394 {
395 ol.startDoxyAnchor(md->getOutputFileBase(),QCString(),md->anchor(),md->name(),QCString());
396 }
397 if (md->isSliceLocal())
398 {
399 ol.writeString("local ");
400 }
401 ol.writeString("enum ");
402 if (md->getLanguage()==SrcLangExt_Cpp && md->isStrong())
403 {
404 if (md->isEnumStruct())
405 {
406 ol.writeString("struct ");
407 }
408 else
409 {
410 ol.writeString("class ");
411 }
412 }
413 ol.insertMemberAlign();
414 md->writeEnumDeclaration(ol,cd,nd,fd,gd);
415 if (!detailsLinkable)
416 {
417 ol.endDoxyAnchor(md->getOutputFileBase(),md->anchor());
418 }
419 ol.endMemberItem();
420 if (!md->briefDescription().isEmpty() && Config_getBool(BRIEF_MEMBER_DESC))
421 {
422 std::unique_ptr<IDocParser> parser { createDocParser() };
423 std::unique_ptr<DocRoot> rootNode { validatingParseDoc(*parser.get(),
424 md->briefFile(),md->briefLine(),
425 cd,md,
426 md->briefDescription(),
427 TRUE,FALSE,
428 QCString(),TRUE,FALSE,
429 Config_getBool(MARKDOWN_SUPPORT)) };
430 if (rootNode && !rootNode->isEmpty())
431 {
432 ol.startMemberDescription(md->anchor());
433 ol.writeDoc(rootNode.get(),cd,md);
434 if (md->hasDetailedDescription())
435 {
436 ol.disableAllBut(OutputGenerator::Html);
437 ol.docify(" ");
438 ol.startTextLink(md->getOutputFileBase(),
439 md->anchor());
440 ol.parseText(theTranslator->trMore());
441 ol.endTextLink();
442 ol.enableAll();
443 }
444 ol.endMemberDescription();
445 }
446 }
447 ol.endMemberDeclaration(md->anchor(),inheritId);
448 }
449 md->warnIfUndocumented();
450 break;
451 }
452 case MemberType_Friend:
453 if (inheritedFrom==0)
454 {
455 if (first)
456 {
457 ol.startMemberList();
458 first=FALSE;
459 }
460 md->writeDeclaration(ol,cd,nd,fd,gd,inGroup,indentLevel,inheritedFrom,inheritId);
461 break;
462 }
463 case MemberType_EnumValue:
464 {
465 if (inGroup)
466 {
467 //printf("EnumValue!\n");
468 if (first) ol.startMemberList(),first=FALSE;
469 md->writeDeclaration(ol,cd,nd,fd,gd,true,indentLevel,inheritedFrom,inheritId);
470 }
471 }
472 break;
473 }
474 }
475 }
476
477 // handle members that are inside anonymous compounds and for which
478 // no variables of the anonymous compound type exist.
479 if (cd)
480 {
481 for (const auto &md : m_members)
482 {
483 if (md->fromAnonymousScope() && !md->anonymousDeclShown())
484 {
485 MemberDefMutable *mdm = toMemberDefMutable(md);
486 if (mdm) mdm->setFromAnonymousScope(FALSE);
487 //printf("anonymous compound members\n");
488 if (md->isBriefSectionVisible())
489 {
490 if (first)
491 {
492 ol.startMemberList();
493 first=FALSE;
494 }
495 md->writeDeclaration(ol,cd,nd,fd,gd,inGroup,indentLevel);
496 }
497 if (mdm) mdm->setFromAnonymousScope(TRUE);
498 }
499 }
500 }
501
502 if (!first)
503 {
504 ol.endMemberList();
505 }
506
507 ol.popGeneratorState();
508 //printf("----- end writePlainDeclaration() ----\n");
509 }
510
511 /** Writes the list of members to the output.
512 * @param ol Output list to write to
513 * @param cd non-null if this list is part of class documentation.
514 * @param nd non-null if this list is part of namespace documentation.
515 * @param fd non-null if this list is part of file documentation.
516 * @param gd non-null if this list is part of group documentation.
517 * @param title Title to use for the member list.
518 * @param subtitle Sub title to use for the member list.
519 * @param showEnumValues Obsolete, always set to FALSE.
520 * @param showInline if set to TRUE if title is rendered differently
521 * @param inheritedFrom if not 0, the list is shown inside the
522 * given class as inherited members, parameter cd points to the
523 * class containing the members.
524 * @param lt Type of list that is inherited from.
525 */
writeDeclarations(OutputList & ol,const ClassDef * cd,const NamespaceDef * nd,const FileDef * fd,const GroupDef * gd,const QCString & title,const QCString & subtitle,bool showEnumValues,bool showInline,const ClassDef * inheritedFrom,MemberListType lt) const526 void MemberList::writeDeclarations(OutputList &ol,
527 const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,
528 const QCString &title,const QCString &subtitle, bool showEnumValues,
529 bool showInline,const ClassDef *inheritedFrom,MemberListType lt) const
530 {
531 (void)showEnumValues; // unused
532
533 //printf("----- writeDeclaration() this=%p ---- inheritedFrom=%p\n",this,inheritedFrom);
534 static bool optimizeVhdl = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
535 QCString inheritId;
536
537 const Definition *ctx = cd;
538 if (ctx==0 && nd) ctx = nd;
539 if (ctx==0 && gd) ctx = gd;
540 if (ctx==0 && fd) ctx = fd;
541
542 //printf("%p: MemberList::writeDeclaration(title='%s',subtitle='%s')=%d inheritedFrom=%p\n",
543 // this,title,subtitle,numDecMembers(),inheritedFrom);
544
545 int num = numDecMembers();
546 int numEnumValues = numDecEnumValues();
547 if (inheritedFrom)
548 {
549 //if ( cd && !optimizeVhdl && countInheritableMembers(inheritedFrom)>0 )
550 if ( cd && !optimizeVhdl && cd->countMembersIncludingGrouped(
551 m_listType,inheritedFrom,TRUE)>0 )
552 {
553 ol.pushGeneratorState();
554 ol.disableAllBut(OutputGenerator::Html);
555 inheritId = substitute(listTypeAsString(lt),"-","_")+"_"+
556 stripPath(cd->getOutputFileBase());
557 if (!title.isEmpty())
558 {
559 ol.writeInheritedSectionTitle(inheritId,cd->getReference(),
560 cd->getOutputFileBase(),
561 cd->anchor(),title,cd->displayName());
562 }
563 ol.popGeneratorState();
564 }
565 }
566 else if (num>numEnumValues)
567 {
568 if (!title.isEmpty())
569 {
570 if (showInline)
571 {
572 ol.startInlineHeader();
573 }
574 else
575 {
576 ol.startMemberHeader(listTypeAsString(m_listType));
577 }
578 ol.parseText(title);
579 if (showInline)
580 {
581 ol.endInlineHeader();
582 }
583 else
584 {
585 ol.endMemberHeader();
586 }
587 }
588 if (!subtitle.stripWhiteSpace().isEmpty())
589 {
590 ol.startMemberSubtitle();
591 ol.generateDoc("[generated]",-1,ctx,0,subtitle,FALSE,FALSE,
592 QCString(),FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT));
593 ol.endMemberSubtitle();
594 }
595 }
596 if (num>numEnumValues)
597 {
598 bool inGroup = m_container==MemberListContainer::Group;
599 // TODO: Two things need to be worked out for proper VHDL output:
600 // 1. Signals and types under the group need to be
601 // formatted to associate them with the group somehow
602 // indentation, or at the very least, extra space after
603 // the group is done
604 // 2. This might need to be repeated below for memberGroupLists
605 if (optimizeVhdl) // use specific declarations function
606 {
607 VhdlDocGen::writeVhdlDeclarations(this,ol,0,cd,0,0);
608 }
609 else
610 {
611 writePlainDeclarations(ol,inGroup,cd,nd,fd,gd,0,0,inheritId);
612 }
613
614 //printf("memberGroupList=%p\n",memberGroupList);
615 for (const auto &mg : m_memberGroupRefList)
616 {
617 bool hasHeader=!mg->header().isEmpty() && mg->header()!="[NOHEADER]";
618 if (inheritId.isEmpty())
619 {
620 //printf("mg->header=%s hasHeader=%d\n",qPrint(mg->header()),hasHeader);
621 ol.startMemberGroupHeader(hasHeader);
622 if (hasHeader)
623 {
624 ol.parseText(mg->header());
625 }
626 ol.endMemberGroupHeader();
627 if (!mg->documentation().isEmpty())
628 {
629 //printf("Member group has docs!\n");
630 ol.startMemberGroupDocs();
631 ol.generateDoc(mg->docFile(),mg->docLine(),ctx,0,mg->documentation()+"\n",FALSE,FALSE,
632 QCString(),FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT));
633 ol.endMemberGroupDocs();
634 }
635 ol.startMemberGroup();
636 }
637 //printf("--- mg->writePlainDeclarations ---\n");
638 mg->writePlainDeclarations(ol,inGroup,cd,nd,fd,gd,0,inheritedFrom,inheritId);
639 if (inheritId.isEmpty())
640 {
641 ol.endMemberGroup(hasHeader);
642 }
643 }
644 }
645 if (inheritedFrom && cd)
646 {
647 const ClassDefMutable *cdm = toClassDefMutable(cd);
648 if (cdm)
649 {
650 // also add members that of this list type, that are grouped together
651 // in a separate list in class 'inheritedFrom'
652 cdm->addGroupedInheritedMembers(ol,m_listType,inheritedFrom,inheritId);
653 }
654 }
655 //printf("----- end writeDeclaration() ----\n");
656 }
657
writeDocumentation(OutputList & ol,const QCString & scopeName,const Definition * container,const QCString & title,bool showEnumValues,bool showInline) const658 void MemberList::writeDocumentation(OutputList &ol,
659 const QCString &scopeName, const Definition *container,
660 const QCString &title,bool showEnumValues,bool showInline) const
661 {
662 if (numDocMembers()==-1)
663 {
664 err("MemberList::numDocMembers()==-1, so the members of this list have not been counted. Please report as a bug.\n");
665 abort();
666 }
667
668 if (numDocMembers()==0) return;
669 if (!showEnumValues && numDocMembers()<=numDocEnumValues()) return;
670
671 if (!title.isEmpty())
672 {
673 ol.pushGeneratorState();
674 ol.disable(OutputGenerator::Html);
675 ol.writeRuler();
676 ol.popGeneratorState();
677 ol.startGroupHeader(showInline ? 2 : 0);
678 ol.parseText(title);
679 ol.endGroupHeader(showInline ? 2 : 0);
680 }
681 ol.startMemberDocList();
682
683 struct OverloadInfo
684 {
685 uint count = 1;
686 uint total = 0;
687 };
688 std::unordered_map<std::string,OverloadInfo> overloadInfo;
689 // count the number of overloaded members
690 for (const auto &md : m_members)
691 {
692 if (md->isDetailedSectionVisible(m_container) &&
693 !(md->isEnumValue() && !showInline))
694 {
695 auto it = overloadInfo.insert(std::make_pair(md->name().str(),OverloadInfo())).first;
696 it->second.total++;
697 }
698 }
699
700 for (const auto &md : m_members)
701 {
702 if (md->isDetailedSectionVisible(m_container) &&
703 !(md->isEnumValue() && !showInline))
704 {
705 auto it = overloadInfo.find(md->name().str());
706 uint overloadCount = it->second.total;
707 uint &count = it->second.count;
708 MemberDefMutable *mdm = toMemberDefMutable(md);
709 if (mdm)
710 {
711 mdm->writeDocumentation(this,count++,overloadCount,ol,scopeName,container,
712 m_container==MemberListContainer::Group,showEnumValues,showInline);
713 }
714 }
715 }
716 //printf("MemberList::writeDocumentation() -- member groups %d\n",memberGroupList->count());
717 for (const auto &mg : m_memberGroupRefList)
718 {
719 mg->writeDocumentation(ol,scopeName,container,showEnumValues,showInline);
720 }
721 ol.endMemberDocList();
722 }
723
724 // members in a table
writeSimpleDocumentation(OutputList & ol,const Definition * container) const725 void MemberList::writeSimpleDocumentation(OutputList &ol,
726 const Definition *container) const
727 {
728 //printf("MemberList count=%d enumValues=%d\n",numDocMembers(),numDocEnumValues());
729 if (numDocMembers()<=numDocEnumValues()) return; // only enum values and they should be excluded
730
731 const ClassDef *cd = 0;
732 if (container && container->definitionType()==Definition::TypeClass)
733 {
734 cd = toClassDef(container);
735 }
736 ol.startMemberDocSimple(cd && cd->isJavaEnum());
737 for (const auto &md : m_members)
738 {
739 MemberDefMutable *mdm = toMemberDefMutable(md);
740 if (mdm)
741 {
742 mdm->writeMemberDocSimple(ol,container);
743 }
744 }
745 ol.endMemberDocSimple(cd && cd->isJavaEnum());
746 }
747
748 // separate member pages
writeDocumentationPage(OutputList & ol,const QCString & scopeName,const DefinitionMutable * container) const749 void MemberList::writeDocumentationPage(OutputList &ol,
750 const QCString &scopeName, const DefinitionMutable *container) const
751 {
752 static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW);
753
754 struct OverloadInfo
755 {
756 uint count = 1;
757 uint total = 0;
758 };
759 std::unordered_map<std::string,OverloadInfo> overloadInfo;
760
761 // count the number of overloaded members
762 for (const auto &imd : m_members)
763 {
764 MemberDefMutable *md = toMemberDefMutable(imd);
765
766 if (md && md->hasDetailedDescription())
767 {
768 auto it = overloadInfo.insert(std::make_pair(md->name().str(),OverloadInfo())).first;
769 it->second.total++;
770 }
771 }
772
773 for (const auto &imd : m_members)
774 {
775 Definition *container_d = toDefinition(const_cast<DefinitionMutable*>(container));
776 MemberDefMutable *md = toMemberDefMutable(imd);
777 if (md && md->hasDetailedDescription())
778 {
779 auto it = overloadInfo.find(md->name().str());
780 uint overloadCount = it->second.total;
781 uint &count = it->second.count;
782 QCString diskName=md->getOutputFileBase();
783 QCString title=md->qualifiedName();
784 startFile(ol,diskName,md->name(),title,HLI_None,!generateTreeView,diskName);
785 if (!generateTreeView)
786 {
787 container->writeNavigationPath(ol);
788 ol.endQuickIndices();
789 }
790 ol.startContents();
791
792 if (generateTreeView)
793 {
794 md->writeDocumentation(this,count++,overloadCount,ol,scopeName,container_d,m_container==MemberListContainer::Group);
795
796 ol.endContents();
797 endFileWithNavPath(container_d,ol);
798 }
799 else
800 {
801 ol.writeString("<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\">\n"
802 " <tr>\n"
803 " <td valign=\"top\">\n");
804
805 container->writeQuickMemberLinks(ol,md);
806
807 ol.writeString(" </td>\n");
808 ol.writeString(" <td valign=\"top\" class=\"mempage\">\n");
809
810 md->writeDocumentation(this,count++,overloadCount,ol,scopeName,container_d,m_container==MemberListContainer::Group);
811
812 ol.writeString(" </td>\n");
813 ol.writeString(" </tr>\n");
814 ol.writeString("</table>\n");
815
816 endFile(ol);
817 }
818 }
819 }
820 for (const auto &mg : m_memberGroupRefList)
821 {
822 mg->writeDocumentationPage(ol,scopeName,container);
823 }
824 }
825
addMemberGroup(MemberGroup * mg)826 void MemberList::addMemberGroup(MemberGroup *mg)
827 {
828 m_memberGroupRefList.push_back(mg);
829 }
830
addListReferences(Definition * def)831 void MemberList::addListReferences(Definition *def)
832 {
833 for (const auto &imd : m_members)
834 {
835 MemberDefMutable *md = toMemberDefMutable(imd);
836 if (md && !md->isAlias() && (md->getGroupDef()==0 || def->definitionType()==Definition::TypeGroup))
837 {
838 md->addListReference(def);
839 const MemberVector &enumFields = md->enumFieldList();
840 if (md->memberType()==MemberType_Enumeration && !enumFields.empty())
841 {
842 //printf(" Adding enum values!\n");
843 for (const auto &vmd : enumFields)
844 {
845 MemberDefMutable *vmdm = toMemberDefMutable(vmd);
846 if (vmdm)
847 {
848 //printf(" adding %s\n",qPrint(vmd->name()));
849 vmdm->addListReference(def);
850 }
851 }
852 }
853 }
854 }
855 for (const auto &mg : m_memberGroupRefList)
856 {
857 mg->addListReferences(def);
858 }
859 }
860
findSectionsInDocumentation(const Definition * d)861 void MemberList::findSectionsInDocumentation(const Definition *d)
862 {
863 for (const auto &imd : m_members)
864 {
865 MemberDefMutable *md = toMemberDefMutable(imd);
866 if (md)
867 {
868 md->findSectionsInDocumentation();
869 }
870 }
871 for (const auto &mg : m_memberGroupRefList)
872 {
873 mg->findSectionsInDocumentation(d);
874 }
875 }
876
setNeedsSorting(bool b)877 void MemberList::setNeedsSorting(bool b)
878 {
879 m_needsSorting = b;
880 }
881
listTypeAsString(MemberListType type)882 QCString MemberList::listTypeAsString(MemberListType type)
883 {
884 switch(type)
885 {
886 case MemberListType_pubMethods: return "pub-methods";
887 case MemberListType_proMethods: return "pro-methods";
888 case MemberListType_pacMethods: return "pac-methods";
889 case MemberListType_priMethods: return "pri-methods";
890 case MemberListType_pubStaticMethods: return "pub-static-methods";
891 case MemberListType_proStaticMethods: return "pro-static-methods";
892 case MemberListType_pacStaticMethods: return "pac-static-methods";
893 case MemberListType_priStaticMethods: return "pri-static-methods";
894 case MemberListType_pubSlots: return "pub-slots";
895 case MemberListType_proSlots: return "pro-slots";
896 case MemberListType_priSlots: return "pri-slots";
897 case MemberListType_pubAttribs: return "pub-attribs";
898 case MemberListType_proAttribs: return "pro-attribs";
899 case MemberListType_pacAttribs: return "pac-attribs";
900 case MemberListType_priAttribs: return "pri-attribs";
901 case MemberListType_pubStaticAttribs: return "pub-static-attribs";
902 case MemberListType_proStaticAttribs: return "pro-static-attribs";
903 case MemberListType_pacStaticAttribs: return "pac-static-attribs";
904 case MemberListType_priStaticAttribs: return "pri-static-attribs";
905 case MemberListType_pubTypes: return "pub-types";
906 case MemberListType_proTypes: return "pro-types";
907 case MemberListType_pacTypes: return "pac-types";
908 case MemberListType_priTypes: return "pri-types";
909 case MemberListType_related: return "related";
910 case MemberListType_signals: return "signals";
911 case MemberListType_friends: return "friends";
912 case MemberListType_dcopMethods: return "dcop-methods";
913 case MemberListType_properties: return "properties";
914 case MemberListType_events: return "events";
915 case MemberListType_interfaces: return "interfaces";
916 case MemberListType_services: return "services";
917 case MemberListType_decDefineMembers: return "define-members";
918 case MemberListType_decProtoMembers: return "proto-members";
919 case MemberListType_decTypedefMembers: return "typedef-members";
920 case MemberListType_decSequenceMembers: return "sequence-members";
921 case MemberListType_decDictionaryMembers: return "dictionary-members";
922 case MemberListType_decEnumMembers: return "enum-members";
923 case MemberListType_decFuncMembers: return "func-members";
924 case MemberListType_decVarMembers: return "var-members";
925 case MemberListType_decEnumValMembers: return "enumval-members";
926 case MemberListType_decPubSlotMembers: return "pub-slot-members";
927 case MemberListType_decProSlotMembers: return "pro-slot-members";
928 case MemberListType_decPriSlotMembers: return "pri-slot-members";
929 case MemberListType_decSignalMembers: return "signal-members";
930 case MemberListType_decEventMembers: return "event-members";
931 case MemberListType_decFriendMembers: return "friend-members";
932 case MemberListType_decPropMembers: return "prop-members";
933 case MemberListType_enumFields: return "enum-fields";
934 case MemberListType_memberGroup: break;
935 default: break;
936 }
937 return "";
938 }
939
writeTagFile(TextStream & tagFile)940 void MemberList::writeTagFile(TextStream &tagFile)
941 {
942 for (const auto &imd : m_members)
943 {
944 MemberDefMutable *md = toMemberDefMutable(imd);
945 if (md)
946 {
947 if (md->getLanguage()!=SrcLangExt_VHDL)
948 {
949 md->writeTagFile(tagFile);
950 if (md->memberType()==MemberType_Enumeration && !md->isStrong())
951 {
952 for (const auto &ivmd : md->enumFieldList())
953 {
954 MemberDefMutable *vmd = toMemberDefMutable(ivmd);
955 if (vmd)
956 {
957 vmd->writeTagFile(tagFile);
958 }
959 }
960 }
961 }
962 else
963 {
964 VhdlDocGen::writeTagFile(md,tagFile);
965 }
966 }
967 }
968 for (const auto &mg : m_memberGroupRefList)
969 {
970 mg->writeTagFile(tagFile);
971 }
972 }
973
974 // compute the HTML anchors for a list of members
setAnchors()975 void MemberList::setAnchors()
976 {
977 //int count=0;
978 for (const auto &md : m_members)
979 {
980 MemberDefMutable *mdm = toMemberDefMutable(md);
981 if (mdm && !md->isReference())
982 {
983 mdm->setAnchor();
984 }
985 }
986 }
987
988