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 "membergroup.h"
19 #include "memberlist.h"
20 #include "outputlist.h"
21 #include "util.h"
22 #include "classdef.h"
23 #include "namespacedef.h"
24 #include "filedef.h"
25 #include "language.h"
26 #include "groupdef.h"
27 #include "doxygen.h"
28 #include "docparser.h"
29 #include "entry.h"
30 #include "md5.h"
31 
MemberGroup(const Definition * container,int id,const QCString & hdr,const QCString & d,const QCString & docFile,int docLine,MemberListContainer con)32 MemberGroup::MemberGroup(const Definition *container,int id,const QCString &hdr,
33                          const QCString &d,const QCString &docFile,int docLine,
34                          MemberListContainer con)
35   : m_container(container),
36     memberList(std::make_unique<MemberList>(MemberListType_memberGroup,con)),
37     grpId(id), grpHeader(hdr), doc(d), m_docFile(docFile), m_docLine(docLine)
38 {
39   //printf("New member group id=%d header=%s desc=%s\n",id,hdr,d);
40   memberList->setNeedsSorting(Config_getBool(SORT_BRIEF_DOCS)); // detailed sections are already sorted elsewhere.
41   //printf("Member group docs='%s'\n",qPrint(doc));
42 }
43 
~MemberGroup()44 MemberGroup::~MemberGroup()
45 {
46 }
47 
insertMember(const MemberDef * md)48 void MemberGroup::insertMember(const MemberDef *md)
49 {
50   //printf("MemberGroup::insertMember memberList=%p count=%d"
51   //       " member section list: %p: md=%p:%s\n",
52   //       memberList->first() ? memberList->first()->getSectionList() : 0,
53   //       memberList->count(),
54   //       md->getSectionList(),
55   //       md,qPrint(md->name()));
56 
57   const MemberDef *firstMd = memberList->empty() ? 0 : memberList->front();
58   if (inSameSection && firstMd &&
59       firstMd->getSectionList(m_container)!=md->getSectionList(m_container))
60   {
61     inSameSection=FALSE;
62   }
63   else if (inDeclSection==0)
64   {
65     inDeclSection = const_cast<MemberList*>(md->getSectionList(m_container));
66     //printf("inDeclSection=%p type=%d\n",inDeclSection,inDeclSection->listType());
67   }
68   memberList->push_back(md);
69 
70   // copy the group of the first member in the memberGroup
71   GroupDef *gd;
72   if (firstMd && !firstMd->isAlias() && (gd=const_cast<GroupDef*>(firstMd->getGroupDef())))
73   {
74     MemberDefMutable *mdm = toMemberDefMutable(md);
75     if (mdm)
76     {
77       mdm->setGroupDef(gd, firstMd->getGroupPri(),
78                        firstMd->getGroupFileName(),
79                        firstMd->getGroupStartLine(),
80                        firstMd->getGroupHasDocs());
81     }
82     gd->insertMember(md);
83   }
84 }
85 
86 
setAnchors()87 void MemberGroup::setAnchors()
88 {
89   memberList->setAnchors();
90 }
91 
writeDeclarations(OutputList & ol,const ClassDef * cd,const NamespaceDef * nd,const FileDef * fd,const GroupDef * gd,bool showInline) const92 void MemberGroup::writeDeclarations(OutputList &ol,
93                const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,
94                bool showInline) const
95 {
96   //printf("MemberGroup::writeDeclarations() %s\n",qPrint(grpHeader));
97   QCString ldoc = doc;
98   if (!ldoc.isEmpty()) ldoc.prepend("<a name=\""+anchor()+"\" id=\""+anchor()+"\"></a>");
99   memberList->writeDeclarations(ol,cd,nd,fd,gd,grpHeader,ldoc,FALSE,showInline);
100 }
101 
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) const102 void MemberGroup::writePlainDeclarations(OutputList &ol,bool inGroup,
103                const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,
104                int indentLevel,const ClassDef *inheritedFrom,const QCString &inheritId
105               ) const
106 {
107   //printf("MemberGroup::writePlainDeclarations() memberList->count()=%d\n",memberList->count());
108   memberList->writePlainDeclarations(ol,inGroup,cd,nd,fd,gd,indentLevel,inheritedFrom,inheritId);
109 }
110 
writeDocumentation(OutputList & ol,const QCString & scopeName,const Definition * container,bool showEnumValues,bool showInline) const111 void MemberGroup::writeDocumentation(OutputList &ol,const QCString &scopeName,
112                const Definition *container,bool showEnumValues,bool showInline) const
113 {
114   //printf("MemberGroup::writeDocumentation() %s\n",qPrint(grpHeader));
115   memberList->writeDocumentation(ol,scopeName,container,QCString(),showEnumValues,showInline);
116 }
117 
writeDocumentationPage(OutputList & ol,const QCString & scopeName,const DefinitionMutable * container) const118 void MemberGroup::writeDocumentationPage(OutputList &ol,const QCString &scopeName,
119                const DefinitionMutable *container) const
120 {
121   memberList->writeDocumentationPage(ol,scopeName,container);
122 }
123 
setAnonymousEnumType()124 void MemberGroup::setAnonymousEnumType()
125 {
126   memberList->setAnonymousEnumType();
127 }
128 
addGroupedInheritedMembers(OutputList & ol,const ClassDef * cd,MemberListType lt,const ClassDef * inheritedFrom,const QCString & inheritId) const129 void MemberGroup::addGroupedInheritedMembers(OutputList &ol,const ClassDef *cd,
130                MemberListType lt,
131                const ClassDef *inheritedFrom,const QCString &inheritId) const
132 {
133   //printf("** addGroupedInheritedMembers()\n");
134   for (const auto &md : *memberList)
135   {
136     //printf("matching %d == %d\n",lt,md->getSectionList()->listType());
137     const MemberList *ml = md->getSectionList(m_container);
138     if (ml && lt==ml->listType())
139     {
140       MemberList mml(lt,MemberListContainer::Class);
141       mml.push_back(md);
142       mml.countDecMembers();
143       mml.writePlainDeclarations(ol,false,cd,0,0,0,0,inheritedFrom,inheritId);
144     }
145   }
146 }
147 
countGroupedInheritedMembers(MemberListType lt)148 int MemberGroup::countGroupedInheritedMembers(MemberListType lt)
149 {
150   //printf("** countGroupedInheritedMembers()\n");
151   int count=0;
152   for (const auto &md : *memberList)
153   {
154     //printf("matching %d == %d\n",lt,md->getSectionList()->listType());
155     const MemberList *ml = md->getSectionList(m_container);
156     if (ml && lt==ml->listType())
157     {
158       count++;
159     }
160   }
161   return count;
162 }
163 
164 
165 /*! Add this group as a subsection of the declaration section, instead
166  *  of rendering it in its own section
167  */
addToDeclarationSection()168 void MemberGroup::addToDeclarationSection()
169 {
170   if (inDeclSection)
171   {
172     //printf("Adding group %p to list %p (type=%d) memberList=%p\n",this,
173     //                             inDeclSection,inDeclSection->listType(),memberList);
174     inDeclSection->addMemberGroup(this);
175   }
176 }
177 
countDecMembers()178 void MemberGroup::countDecMembers()
179 {
180   memberList->countDecMembers();
181 }
182 
countDocMembers()183 void MemberGroup::countDocMembers()
184 {
185   memberList->countDocMembers();
186 }
187 
container() const188 const Definition *MemberGroup::container() const
189 {
190   return m_container;
191 }
192 
countInheritableMembers(const ClassDef * inheritedFrom) const193 int MemberGroup::countInheritableMembers(const ClassDef *inheritedFrom) const
194 {
195   return memberList->countInheritableMembers(inheritedFrom);
196 }
197 
198 
distributeMemberGroupDocumentation()199 void MemberGroup::distributeMemberGroupDocumentation()
200 {
201   //printf("MemberGroup::distributeMemberGroupDocumentation() %s\n",qPrint(grpHeader));
202   const MemberDef *md = 0;
203   for (const auto &smd : *memberList)
204   {
205     //printf("checking md=%s\n",qPrint(md->name()));
206     // find the first member of the group with documentation
207     if (!smd->documentation().isEmpty()       ||
208         !smd->briefDescription().isEmpty()    ||
209         !smd->inbodyDocumentation().isEmpty()
210        )
211     {
212       //printf("found it!\n");
213       md = smd;
214       break;
215     }
216   }
217   if (md) // distribute docs of md to other members of the list
218   {
219     //printf("Member %s has documentation!\n",qPrint(md->name()));
220     for (const auto &iomd : *memberList)
221     {
222       MemberDefMutable *omd = toMemberDefMutable(iomd);
223       if (omd && md!=omd && omd->documentation().isEmpty() &&
224                             omd->briefDescription().isEmpty() &&
225                             omd->inbodyDocumentation().isEmpty()
226          )
227       {
228         //printf("Copying documentation to member %s\n",qPrint(omd->name()));
229         omd->setBriefDescription(md->briefDescription(),md->briefFile(),md->briefLine());
230         omd->setDocumentation(md->documentation(),md->docFile(),md->docLine());
231         omd->setInbodyDocumentation(md->inbodyDocumentation(),md->inbodyFile(),md->inbodyLine());
232       }
233     }
234   }
235 }
236 
237 
numDecMembers() const238 int MemberGroup::numDecMembers() const
239 {
240   return memberList->numDecMembers();
241 }
242 
numDecEnumValues() const243 int MemberGroup::numDecEnumValues() const
244 {
245   return memberList->numDecEnumValues();
246 }
247 
numDocMembers() const248 int MemberGroup::numDocMembers() const
249 {
250   return memberList->numDocMembers();
251 }
252 
numDocEnumValues() const253 int MemberGroup::numDocEnumValues() const
254 {
255   return memberList->numDocEnumValues();
256 }
257 
anchor() const258 QCString MemberGroup::anchor() const
259 {
260   uchar md5_sig[16];
261   char sigStr[33];
262   QCString locHeader = grpHeader;
263   if (locHeader.isEmpty()) locHeader="[NOHEADER]";
264   MD5Buffer((const unsigned char *)locHeader.data(),locHeader.length(),md5_sig);
265   MD5SigToString(md5_sig,sigStr);
266   return QCString("amgrp")+sigStr;
267 }
268 
addListReferences(Definition * def)269 void MemberGroup::addListReferences(Definition *def)
270 {
271   memberList->addListReferences(def);
272   if (def)
273   {
274     QCString name = def->getOutputFileBase()+"#"+anchor();
275     addRefItem(m_xrefListItems,
276         name,
277         theTranslator->trGroup(TRUE,TRUE),
278         name,
279         grpHeader,QCString(),def);
280   }
281 }
282 
findSectionsInDocumentation(const Definition * d)283 void MemberGroup::findSectionsInDocumentation(const Definition *d)
284 {
285   docFindSections(doc,d,m_docFile);
286   memberList->findSectionsInDocumentation(d);
287 }
288 
setRefItems(const RefItemVector & sli)289 void MemberGroup::setRefItems(const RefItemVector &sli)
290 {
291   m_xrefListItems.insert(m_xrefListItems.end(), sli.cbegin(), sli.cend());
292 }
293 
writeTagFile(TextStream & tagFile)294 void MemberGroup::writeTagFile(TextStream &tagFile)
295 {
296   memberList->writeTagFile(tagFile);
297 }
298 
299 //--------------------------------------------------------------------------
300 
setRefItems(const RefItemVector & sli)301 void MemberGroupInfo::setRefItems(const RefItemVector &sli)
302 {
303   m_sli.insert(m_sli.end(), sli.cbegin(), sli.cend());
304 }
305