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 <cstdio>
19 #include <algorithm>
20 
21 #include "classdef.h"
22 #include "classlist.h"
23 #include "entry.h"
24 #include "doxygen.h"
25 #include "membername.h"
26 #include "message.h"
27 #include "config.h"
28 #include "util.h"
29 #include "diagram.h"
30 #include "language.h"
31 #include "htmlhelp.h"
32 #include "example.h"
33 #include "outputlist.h"
34 #include "dot.h"
35 #include "dotclassgraph.h"
36 #include "dotrunner.h"
37 #include "defargs.h"
38 #include "debug.h"
39 #include "docparser.h"
40 #include "searchindex.h"
41 #include "vhdldocgen.h"
42 #include "layout.h"
43 #include "arguments.h"
44 #include "memberlist.h"
45 #include "groupdef.h"
46 #include "filedef.h"
47 #include "namespacedef.h"
48 #include "membergroup.h"
49 #include "definitionimpl.h"
50 #include "symbolresolver.h"
51 #include "fileinfo.h"
52 
53 //-----------------------------------------------------------------------------
54 
makeQualifiedNameWithTemplateParameters(const ClassDef * cd,const ArgumentLists * actualParams,uint * actualParamIndex)55 static QCString makeQualifiedNameWithTemplateParameters(const ClassDef *cd,
56     const ArgumentLists *actualParams,uint *actualParamIndex)
57 {
58   //static bool optimizeOutputJava = Config_getBool(OPTIMIZE_OUTPUT_JAVA);
59   bool hideScopeNames = Config_getBool(HIDE_SCOPE_NAMES);
60   //printf("qualifiedNameWithTemplateParameters() localName=%s\n",qPrint(localName()));
61   QCString scName;
62   const Definition *d=cd->getOuterScope();
63   if (d)
64   {
65     if (d->definitionType()==Definition::TypeClass)
66     {
67       const ClassDef *ocd=toClassDef(d);
68       scName = ocd->qualifiedNameWithTemplateParameters(actualParams,actualParamIndex);
69     }
70     else if (!hideScopeNames)
71     {
72       scName = d->qualifiedName();
73     }
74   }
75 
76   SrcLangExt lang = cd->getLanguage();
77   QCString scopeSeparator = getLanguageSpecificSeparator(lang);
78   if (!scName.isEmpty()) scName+=scopeSeparator;
79 
80   bool isSpecialization = cd->localName().find('<')!=-1;
81 
82   QCString clName = cd->className();
83   scName+=clName;
84   if (!cd->templateArguments().empty())
85   {
86     if (actualParams && *actualParamIndex<actualParams->size())
87     {
88       const ArgumentList &al = actualParams->at(*actualParamIndex);
89       if (!isSpecialization)
90       {
91         scName+=tempArgListToString(al,lang);
92       }
93       (*actualParamIndex)++;
94     }
95     else
96     {
97       if (!isSpecialization)
98       {
99         scName+=tempArgListToString(cd->templateArguments(),lang);
100       }
101     }
102   }
103   //printf("qualifiedNameWithTemplateParameters: scope=%s qualifiedName=%s\n",qPrint(name()),qPrint(scName));
104   return scName;
105 }
106 
makeDisplayName(const ClassDef * cd,bool includeScope)107 static QCString makeDisplayName(const ClassDef *cd,bool includeScope)
108 {
109   //static bool optimizeOutputForJava = Config_getBool(OPTIMIZE_OUTPUT_JAVA);
110   SrcLangExt lang = cd->getLanguage();
111   //static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
112   QCString n;
113   if (lang==SrcLangExt_VHDL)
114   {
115     n = VhdlDocGen::getClassName(cd);
116   }
117   else
118   {
119     if (includeScope)
120     {
121       n=cd->qualifiedNameWithTemplateParameters();
122     }
123     else
124     {
125       n=cd->className();
126     }
127   }
128   if (cd->isAnonymous())
129   {
130     n = removeAnonymousScopes(n);
131   }
132   QCString sep=getLanguageSpecificSeparator(lang);
133   if (sep!="::")
134   {
135     n=substitute(n,"::",sep);
136   }
137   if (cd->compoundType()==ClassDef::Protocol && n.right(2)=="-p")
138   {
139     n="<"+n.left(n.length()-2)+">";
140   }
141   //else if (n.right(2)=="-g")
142   //{
143   //  n = n.left(n.length()-2);
144   //}
145   //printf("ClassDefImpl::displayName()=%s\n",qPrint(n));
146   return n;
147 }
148 
149 
150 //-----------------------------------------------------------------------------
151 
152 
153 /** Implementation of the ClassDef interface */
154 class ClassDefImpl : public DefinitionMixin<ClassDefMutable>
155 {
156   public:
157     ClassDefImpl(const QCString &fileName,int startLine,int startColumn,
158              const QCString &name,CompoundType ct,
159              const QCString &ref=QCString(),const QCString &fName=QCString(),
160              bool isSymbol=TRUE,bool isJavaEnum=FALSE);
161     /** Destroys a compound definition. */
162    ~ClassDefImpl();
163 
resolveAlias()164     virtual ClassDef *resolveAlias() { return this; }
definitionType() const165     virtual DefType definitionType() const { return TypeClass; }
166     virtual CodeSymbolType codeSymbolType() const;
167     virtual QCString getOutputFileBase() const;
168     virtual QCString getInstanceOutputFileBase() const;
169     virtual QCString getSourceFileBase() const;
170     virtual QCString getReference() const;
171     virtual bool isReference() const;
172     virtual bool isLocal() const;
173     virtual ClassLinkedRefMap getClasses() const;
174     virtual bool hasDocumentation() const;
175     virtual bool hasDetailedDescription() const;
176     virtual QCString collaborationGraphFileName() const;
177     virtual QCString inheritanceGraphFileName() const;
178     virtual QCString displayName(bool includeScope=TRUE) const;
179     virtual CompoundType compoundType() const;
180     virtual QCString compoundTypeString() const;
181     virtual const BaseClassList &baseClasses() const;
182     virtual void updateBaseClasses(const BaseClassList &bcd);
183     virtual const BaseClassList &subClasses() const;
184     virtual void updateSubClasses(const BaseClassList &bcd);
185     virtual const MemberNameInfoLinkedMap &memberNameInfoLinkedMap() const;
186     virtual Protection protection() const;
187     virtual bool isLinkableInProject() const;
188     virtual bool isLinkable() const;
189     virtual bool isVisibleInHierarchy() const;
190     virtual bool visibleInParentsDeclList() const;
191     virtual const ArgumentList &templateArguments() const;
192     virtual FileDef *getFileDef() const;
193     virtual const MemberDef *getMemberByName(const QCString &) const;
194     virtual bool isBaseClass(const ClassDef *bcd,bool followInstances,int level=0) const;
195     virtual bool isSubClass(ClassDef *bcd,int level=0) const;
196     virtual bool isAccessibleMember(const MemberDef *md) const;
197     virtual const TemplateInstanceList &getTemplateInstances() const;
198     virtual const ClassDef *templateMaster() const;
199     virtual bool isTemplate() const;
200     virtual const IncludeInfo *includeInfo() const;
201     virtual const UsesClassList &usedImplementationClasses() const;
202     virtual const UsesClassList &usedByImplementationClasses() const;
203     virtual const ConstraintClassList &templateTypeConstraints() const;
204     virtual bool isTemplateArgument() const;
205     virtual const Definition *findInnerCompound(const QCString &name) const;
206     virtual ArgumentLists getTemplateParameterLists() const;
207     virtual QCString qualifiedNameWithTemplateParameters(
208         const ArgumentLists *actualParams=0,uint *actualParamIndex=0) const;
209     virtual bool isAbstract() const;
210     virtual bool isObjectiveC() const;
211     virtual bool isFortran() const;
212     virtual bool isCSharp() const;
213     virtual bool isFinal() const;
214     virtual bool isSealed() const;
215     virtual bool isPublished() const;
216     virtual bool isExtension() const;
217     virtual bool isForwardDeclared() const;
218     virtual bool isInterface() const;
219     virtual ClassDef *categoryOf() const;
220     virtual QCString className() const;
221     virtual MemberList *getMemberList(MemberListType lt) const;
222     virtual const MemberLists &getMemberLists() const;
223     virtual const MemberGroupList &getMemberGroups() const;
224     virtual const TemplateNameMap &getTemplateBaseClassNames() const;
225     virtual bool isUsedOnly() const;
226     virtual QCString anchor() const;
227     virtual bool isEmbeddedInOuterScope() const;
228     virtual bool isSimple() const;
229     virtual const ClassDef *tagLessReference() const;
230     virtual const MemberDef *isSmartPointer() const;
231     virtual bool isJavaEnum() const;
232     virtual QCString title() const;
233     virtual QCString generatedFromFiles() const;
234     virtual const FileList &usedFiles() const;
235     virtual const ArgumentList &typeConstraints() const;
236     virtual const ExampleList &getExamples() const;
237     virtual bool hasExamples() const;
238     virtual QCString getMemberListFileName() const;
239     virtual bool subGrouping() const;
240     virtual bool isSliceLocal() const;
241     virtual bool hasNonReferenceSuperClass() const;
242     virtual QCString requiresClause() const;
243     virtual ClassDef *insertTemplateInstance(const QCString &fileName,int startLine,int startColumn,
244                                 const QCString &templSpec,bool &freshInstance) const;
245 
246     virtual void insertBaseClass(ClassDef *,const QCString &name,Protection p,Specifier s,const QCString &t=QCString());
247     virtual void insertSubClass(ClassDef *,Protection p,Specifier s,const QCString &t=QCString());
248     virtual void setIncludeFile(FileDef *fd,const QCString &incName,bool local,bool force);
249     virtual void insertMember(MemberDef *);
250     virtual void insertUsedFile(const FileDef *);
251     virtual bool addExample(const QCString &anchor,const QCString &name, const QCString &file);
252     virtual void mergeCategory(ClassDef *category);
253     //virtual void setNamespace(NamespaceDef *nd);
254     virtual void setFileDef(FileDef *fd);
255     virtual void setSubGrouping(bool enabled);
256     virtual void setProtection(Protection p);
257     virtual void setGroupDefForAllMembers(GroupDef *g,Grouping::GroupPri_t pri,const QCString &fileName,int startLine,bool hasDocs);
258     virtual void addInnerCompound(const Definition *d);
259     virtual void addUsedClass(ClassDef *cd,const QCString &accessName,Protection prot);
260     virtual void addUsedByClass(ClassDef *cd,const QCString &accessName,Protection prot);
261     virtual void setIsStatic(bool b);
262     virtual void setCompoundType(CompoundType t);
263     virtual void setClassName(const QCString &name);
264     virtual void setClassSpecifier(uint64 spec);
265     virtual void setTemplateArguments(const ArgumentList &al);
266     virtual void setTemplateBaseClassNames(const TemplateNameMap &templateNames);
267     virtual void setTemplateMaster(const ClassDef *tm);
268     virtual void setTypeConstraints(const ArgumentList &al);
269     virtual void addMembersToTemplateInstance(const ClassDef *cd,const ArgumentList &templateArguments,const QCString &templSpec);
270     virtual void makeTemplateArgument(bool b=TRUE);
271     virtual void setCategoryOf(ClassDef *cd);
272     virtual void setUsedOnly(bool b);
273     virtual void setTagLessReference(const ClassDef *cd);
274     virtual void setName(const QCString &name);
275     virtual void setMetaData(const QCString &md);
276     virtual void findSectionsInDocumentation();
277     virtual void addMembersToMemberGroup();
278     virtual void addListReferences();
279     virtual void addTypeConstraints();
280     virtual void computeAnchors();
281     virtual void mergeMembers();
282     virtual void sortMemberLists();
283     virtual void distributeMemberGroupDocumentation();
284     virtual void writeDocumentation(OutputList &ol) const;
285     virtual void writeDocumentationForInnerClasses(OutputList &ol) const;
286     virtual void writeMemberPages(OutputList &ol) const;
287     virtual void writeMemberList(OutputList &ol) const;
288     virtual void writeDeclaration(OutputList &ol,const MemberDef *md,bool inGroup,int indentLevel,
289                           const ClassDef *inheritedFrom,const QCString &inheritId) const;
290     virtual void writeQuickMemberLinks(OutputList &ol,const MemberDef *md) const;
291     virtual void writeSummaryLinks(OutputList &ol) const;
292     virtual void reclassifyMember(MemberDefMutable *md,MemberType t);
293     virtual void writeInlineDocumentation(OutputList &ol) const;
294     virtual void writeDeclarationLink(OutputList &ol,bool &found,
295                               const QCString &header,bool localNames) const;
296     virtual void removeMemberFromLists(MemberDef *md);
297     virtual void setAnonymousEnumType();
298     virtual void countMembers();
299     virtual void sortAllMembersList();
300 
301     virtual void addGroupedInheritedMembers(OutputList &ol,MemberListType lt,
302                               const ClassDef *inheritedFrom,const QCString &inheritId) const;
303     virtual void writeTagFile(TextStream &);
304 
305     virtual int countMembersIncludingGrouped(MemberListType lt,const ClassDef *inheritedFrom,bool additional) const;
306     virtual int countInheritanceNodes() const;
307     virtual int countMemberDeclarations(MemberListType lt,const ClassDef *inheritedFrom,
308                 int lt2,bool invert,bool showAlways,ClassDefSet &visitedClasses) const;
309     virtual void writeMemberDeclarations(OutputList &ol,ClassDefSet &visitedClasses,
310                  MemberListType lt,const QCString &title,
311                  const QCString &subTitle=QCString(),
312                  bool showInline=FALSE,const ClassDef *inheritedFrom=0,
313                  int lt2=-1,bool invert=FALSE,bool showAlways=FALSE) const;
314     virtual void setRequiresClause(const QCString &req);
315 
316   private:
317     void addUsedInterfaceClasses(MemberDef *md,const QCString &typeStr);
318     void showUsedFiles(OutputList &ol) const;
319 
320     void writeDocumentationContents(OutputList &ol,const QCString &pageTitle) const;
321     void internalInsertMember(const MemberDef *md,Protection prot,bool addToAllList);
322     void addMemberToList(MemberListType lt,const MemberDef *md,bool isBrief);
323     void writeInheritedMemberDeclarations(OutputList &ol,ClassDefSet &visitedClasses,
324                                           MemberListType lt,int lt2,const QCString &title,
325                                           const ClassDef *inheritedFrom,bool invert,
326                                           bool showAlways) const;
327     void writeMemberDocumentation(OutputList &ol,MemberListType lt,const QCString &title,bool showInline=FALSE) const;
328     void writeSimpleMemberDocumentation(OutputList &ol,MemberListType lt) const;
329     void writePlainMemberDeclaration(OutputList &ol,MemberListType lt,bool inGroup,
330                                      int indentLevel,const ClassDef *inheritedFrom,const QCString &inheritId) const;
331     void writeBriefDescription(OutputList &ol,bool exampleFlag) const;
332     void writeDetailedDescription(OutputList &ol,const QCString &pageType,bool exampleFlag,
333                                   const QCString &title,const QCString &anchor=QCString()) const;
334     void writeIncludeFiles(OutputList &ol) const;
335     void writeIncludeFilesForSlice(OutputList &ol) const;
336     void writeInheritanceGraph(OutputList &ol) const;
337     void writeCollaborationGraph(OutputList &ol) const;
338     void writeMemberGroups(OutputList &ol,bool showInline=FALSE) const;
339     void writeNestedClasses(OutputList &ol,const QCString &title) const;
340     void writeInlineClasses(OutputList &ol) const;
341     void startMemberDeclarations(OutputList &ol) const;
342     void endMemberDeclarations(OutputList &ol) const;
343     void startMemberDocumentation(OutputList &ol) const;
344     void endMemberDocumentation(OutputList &ol) const;
345     void writeAuthorSection(OutputList &ol) const;
346     void writeMoreLink(OutputList &ol,const QCString &anchor) const;
347     void writeDetailedDocumentationBody(OutputList &ol) const;
348 
349     int countAdditionalInheritedMembers() const;
350     void writeAdditionalInheritedMembers(OutputList &ol) const;
351     void addClassAttributes(OutputList &ol) const;
352     int countInheritedDecMembers(MemberListType lt,
353                                  const ClassDef *inheritedFrom,bool invert,bool showAlways,
354                                  ClassDefSet &visitedClasses) const;
355     void getTitleForMemberListType(MemberListType type,
356                QCString &title,QCString &subtitle) const;
357     QCString includeStatement() const;
358     void addTypeConstraint(const QCString &typeConstraint,const QCString &type);
359     void writeTemplateSpec(OutputList &ol,const Definition *d,
360             const QCString &type,SrcLangExt lang) const;
361 
362     // PIMPL idiom
363     class IMPL;
364     IMPL *m_impl = 0;
365 };
366 
createClassDef(const QCString & fileName,int startLine,int startColumn,const QCString & name,ClassDef::CompoundType ct,const QCString & ref,const QCString & fName,bool isSymbol,bool isJavaEnum)367 ClassDefMutable *createClassDef(
368              const QCString &fileName,int startLine,int startColumn,
369              const QCString &name,ClassDef::CompoundType ct,
370              const QCString &ref,const QCString &fName,
371              bool isSymbol,bool isJavaEnum)
372 {
373   return new ClassDefImpl(fileName,startLine,startColumn,name,ct,ref,fName,isSymbol,isJavaEnum);
374 }
375 //-----------------------------------------------------------------------------
376 
377 class ClassDefAliasImpl : public DefinitionAliasMixin<ClassDef>
378 {
379   public:
ClassDefAliasImpl(const Definition * newScope,const ClassDef * cd)380     ClassDefAliasImpl(const Definition *newScope,const ClassDef *cd)
381       : DefinitionAliasMixin(newScope,cd) { init(); }
~ClassDefAliasImpl()382     virtual ~ClassDefAliasImpl() { deinit(); }
definitionType() const383     virtual DefType definitionType() const { return TypeClass; }
384 
getCdAlias() const385     const ClassDef *getCdAlias() const { return toClassDef(getAlias()); }
resolveAlias()386     virtual ClassDef *resolveAlias() { return const_cast<ClassDef*>(getCdAlias()); }
387 
codeSymbolType() const388     virtual CodeSymbolType codeSymbolType() const
389     { return getCdAlias()->codeSymbolType(); }
getOutputFileBase() const390     virtual QCString getOutputFileBase() const
391     { return getCdAlias()->getOutputFileBase(); }
getInstanceOutputFileBase() const392     virtual QCString getInstanceOutputFileBase() const
393     { return getCdAlias()->getInstanceOutputFileBase(); }
getSourceFileBase() const394     virtual QCString getSourceFileBase() const
395     { return getCdAlias()->getSourceFileBase(); }
getReference() const396     virtual QCString getReference() const
397     { return getCdAlias()->getReference(); }
isReference() const398     virtual bool isReference() const
399     { return getCdAlias()->isReference(); }
isLocal() const400     virtual bool isLocal() const
401     { return getCdAlias()->isLocal(); }
getClasses() const402     virtual ClassLinkedRefMap getClasses() const
403     { return getCdAlias()->getClasses(); }
hasDocumentation() const404     virtual bool hasDocumentation() const
405     { return getCdAlias()->hasDocumentation(); }
hasDetailedDescription() const406     virtual bool hasDetailedDescription() const
407     { return getCdAlias()->hasDetailedDescription(); }
collaborationGraphFileName() const408     virtual QCString collaborationGraphFileName() const
409     { return getCdAlias()->collaborationGraphFileName(); }
inheritanceGraphFileName() const410     virtual QCString inheritanceGraphFileName() const
411     { return getCdAlias()->inheritanceGraphFileName(); }
displayName(bool includeScope=TRUE) const412     virtual QCString displayName(bool includeScope=TRUE) const
413     { return makeDisplayName(this,includeScope); }
compoundType() const414     virtual CompoundType compoundType() const
415     { return getCdAlias()->compoundType(); }
compoundTypeString() const416     virtual QCString compoundTypeString() const
417     { return getCdAlias()->compoundTypeString(); }
baseClasses() const418     virtual const BaseClassList &baseClasses() const
419     { return getCdAlias()->baseClasses(); }
subClasses() const420     virtual const BaseClassList &subClasses() const
421     { return getCdAlias()->subClasses(); }
memberNameInfoLinkedMap() const422     virtual const MemberNameInfoLinkedMap &memberNameInfoLinkedMap() const
423     { return getCdAlias()->memberNameInfoLinkedMap(); }
protection() const424     virtual Protection protection() const
425     { return getCdAlias()->protection(); }
isLinkableInProject() const426     virtual bool isLinkableInProject() const
427     { return getCdAlias()->isLinkableInProject(); }
isLinkable() const428     virtual bool isLinkable() const
429     { return getCdAlias()->isLinkable(); }
isVisibleInHierarchy() const430     virtual bool isVisibleInHierarchy() const
431     { return getCdAlias()->isVisibleInHierarchy(); }
visibleInParentsDeclList() const432     virtual bool visibleInParentsDeclList() const
433     { return getCdAlias()->visibleInParentsDeclList(); }
templateArguments() const434     virtual const ArgumentList &templateArguments() const
435     { return getCdAlias()->templateArguments(); }
436     //virtual NamespaceDef *getNamespaceDef() const
437     //{ return getCdAlias()->getNamespaceDef(); }
getFileDef() const438     virtual FileDef *getFileDef() const
439     { return getCdAlias()->getFileDef(); }
getMemberByName(const QCString & s) const440     virtual const MemberDef *getMemberByName(const QCString &s) const
441     { return getCdAlias()->getMemberByName(s); }
isBaseClass(const ClassDef * bcd,bool followInstances,int level=0) const442     virtual bool isBaseClass(const ClassDef *bcd,bool followInstances,int level=0) const
443     { return getCdAlias()->isBaseClass(bcd,followInstances,level); }
isSubClass(ClassDef * bcd,int level=0) const444     virtual bool isSubClass(ClassDef *bcd,int level=0) const
445     { return getCdAlias()->isSubClass(bcd,level); }
isAccessibleMember(const MemberDef * md) const446     virtual bool isAccessibleMember(const MemberDef *md) const
447     { return getCdAlias()->isAccessibleMember(md); }
getTemplateInstances() const448     virtual const TemplateInstanceList &getTemplateInstances() const
449     { return getCdAlias()->getTemplateInstances(); }
templateMaster() const450     virtual const ClassDef *templateMaster() const
451     { return getCdAlias()->templateMaster(); }
isTemplate() const452     virtual bool isTemplate() const
453     { return getCdAlias()->isTemplate(); }
includeInfo() const454     virtual const IncludeInfo *includeInfo() const
455     { return getCdAlias()->includeInfo(); }
usedImplementationClasses() const456     virtual const UsesClassList &usedImplementationClasses() const
457     { return getCdAlias()->usedImplementationClasses(); }
usedByImplementationClasses() const458     virtual const UsesClassList &usedByImplementationClasses() const
459     { return getCdAlias()->usedByImplementationClasses(); }
templateTypeConstraints() const460     virtual const ConstraintClassList &templateTypeConstraints() const
461     { return getCdAlias()->templateTypeConstraints(); }
isTemplateArgument() const462     virtual bool isTemplateArgument() const
463     { return getCdAlias()->isTemplateArgument(); }
findInnerCompound(const QCString & name) const464     virtual const Definition *findInnerCompound(const QCString &name) const
465     { return getCdAlias()->findInnerCompound(name); }
getTemplateParameterLists() const466     virtual ArgumentLists getTemplateParameterLists() const
467     { return getCdAlias()->getTemplateParameterLists(); }
qualifiedNameWithTemplateParameters(const ArgumentLists * actualParams=0,uint * actualParamIndex=0) const468     virtual QCString qualifiedNameWithTemplateParameters(
469         const ArgumentLists *actualParams=0,uint *actualParamIndex=0) const
470     { return makeQualifiedNameWithTemplateParameters(this,actualParams,actualParamIndex); }
isAbstract() const471     virtual bool isAbstract() const
472     { return getCdAlias()->isAbstract(); }
isObjectiveC() const473     virtual bool isObjectiveC() const
474     { return getCdAlias()->isObjectiveC(); }
isFortran() const475     virtual bool isFortran() const
476     { return getCdAlias()->isFortran(); }
isCSharp() const477     virtual bool isCSharp() const
478     { return getCdAlias()->isCSharp(); }
isFinal() const479     virtual bool isFinal() const
480     { return getCdAlias()->isFinal(); }
isSealed() const481     virtual bool isSealed() const
482     { return getCdAlias()->isSealed(); }
isPublished() const483     virtual bool isPublished() const
484     { return getCdAlias()->isPublished(); }
isExtension() const485     virtual bool isExtension() const
486     { return getCdAlias()->isExtension(); }
isForwardDeclared() const487     virtual bool isForwardDeclared() const
488     { return getCdAlias()->isForwardDeclared(); }
isInterface() const489     virtual bool isInterface() const
490     { return getCdAlias()->isInterface(); }
categoryOf() const491     virtual ClassDef *categoryOf() const
492     { return getCdAlias()->categoryOf(); }
className() const493     virtual QCString className() const
494     { return getCdAlias()->className(); }
getMemberList(MemberListType lt) const495     virtual MemberList *getMemberList(MemberListType lt) const
496     { return getCdAlias()->getMemberList(lt); }
getMemberLists() const497     virtual const MemberLists &getMemberLists() const
498     { return getCdAlias()->getMemberLists(); }
getMemberGroups() const499     virtual const MemberGroupList &getMemberGroups() const
500     { return getCdAlias()->getMemberGroups(); }
getTemplateBaseClassNames() const501     virtual const TemplateNameMap &getTemplateBaseClassNames() const
502     { return getCdAlias()->getTemplateBaseClassNames(); }
isUsedOnly() const503     virtual bool isUsedOnly() const
504     { return getCdAlias()->isUsedOnly(); }
anchor() const505     virtual QCString anchor() const
506     { return getCdAlias()->anchor(); }
isEmbeddedInOuterScope() const507     virtual bool isEmbeddedInOuterScope() const
508     { return getCdAlias()->isEmbeddedInOuterScope(); }
isSimple() const509     virtual bool isSimple() const
510     { return getCdAlias()->isSimple(); }
tagLessReference() const511     virtual const ClassDef *tagLessReference() const
512     { return getCdAlias()->tagLessReference(); }
isSmartPointer() const513     virtual const MemberDef *isSmartPointer() const
514     { return getCdAlias()->isSmartPointer(); }
isJavaEnum() const515     virtual bool isJavaEnum() const
516     { return getCdAlias()->isJavaEnum(); }
title() const517     virtual QCString title() const
518     { return getCdAlias()->title(); }
generatedFromFiles() const519     virtual QCString generatedFromFiles() const
520     { return getCdAlias()->generatedFromFiles(); }
usedFiles() const521     virtual const FileList &usedFiles() const
522     { return getCdAlias()->usedFiles(); }
typeConstraints() const523     virtual const ArgumentList &typeConstraints() const
524     { return getCdAlias()->typeConstraints(); }
getExamples() const525     virtual const ExampleList &getExamples() const
526     { return getCdAlias()->getExamples(); }
hasExamples() const527     virtual bool hasExamples() const
528     { return getCdAlias()->hasExamples(); }
getMemberListFileName() const529     virtual QCString getMemberListFileName() const
530     { return getCdAlias()->getMemberListFileName(); }
subGrouping() const531     virtual bool subGrouping() const
532     { return getCdAlias()->subGrouping(); }
isSliceLocal() const533     virtual bool isSliceLocal() const
534     { return getCdAlias()->isSliceLocal(); }
hasNonReferenceSuperClass() const535     virtual bool hasNonReferenceSuperClass() const
536     { return getCdAlias()->hasNonReferenceSuperClass(); }
requiresClause() const537     virtual QCString requiresClause() const
538     { return getCdAlias()->requiresClause(); }
539 
countMembersIncludingGrouped(MemberListType lt,const ClassDef * inheritedFrom,bool additional) const540     virtual int countMembersIncludingGrouped(MemberListType lt,const ClassDef *inheritedFrom,bool additional) const
541     { return getCdAlias()->countMembersIncludingGrouped(lt,inheritedFrom,additional); }
countInheritanceNodes() const542     virtual int countInheritanceNodes() const
543     { return getCdAlias()->countInheritanceNodes(); }
countMemberDeclarations(MemberListType lt,const ClassDef * inheritedFrom,int lt2,bool invert,bool showAlways,ClassDefSet & visitedClasses) const544     virtual int countMemberDeclarations(MemberListType lt,const ClassDef *inheritedFrom,
545                 int lt2,bool invert,bool showAlways,ClassDefSet &visitedClasses) const
546     { return getCdAlias()->countMemberDeclarations(lt,inheritedFrom,lt2,invert,showAlways,visitedClasses); }
547 
writeDeclarationLink(OutputList & ol,bool & found,const QCString & header,bool localNames) const548     virtual void writeDeclarationLink(OutputList &ol,bool &found,
549                               const QCString &header,bool localNames) const
550     { getCdAlias()->writeDeclarationLink(ol,found,header,localNames); }
insertTemplateInstance(const QCString & fileName,int startLine,int startColumn,const QCString & templSpec,bool & freshInstance) const551     virtual ClassDef *insertTemplateInstance(const QCString &fileName,int startLine,int startColumn,
552                                              const QCString &templSpec,bool &freshInstance) const
553     { return getCdAlias()->insertTemplateInstance(fileName,startLine,startColumn,templSpec,freshInstance); }
554 
updateBaseClasses(const BaseClassList &)555     virtual void updateBaseClasses(const BaseClassList &) {}
updateSubClasses(const BaseClassList &)556     virtual void updateSubClasses(const BaseClassList &) {}
557 };
558 
createClassDefAlias(const Definition * newScope,const ClassDef * cd)559 ClassDef *createClassDefAlias(const Definition *newScope,const ClassDef *cd)
560 {
561   ClassDef *acd = new ClassDefAliasImpl(newScope,cd);
562   //printf("cd name=%s localName=%s qualifiedName=%s qualifiedNameWith=%s displayName()=%s\n",
563   //    qPrint(acd->name()),qPrint(acd->localName()),qPrint(acd->qualifiedName()),
564   //    qPrint(acd->qualifiedNameWithTemplateParameters()),qPrint(acd->displayName()));
565   return acd;
566 }
567 
568 //-----------------------------------------------------------------------------
569 
570 /** Private data associated with a ClassDef object. */
571 class ClassDefImpl::IMPL
572 {
573   public:
574     IMPL();
575    ~IMPL();
576     void init(const QCString &defFileName, const QCString &name,
577               const QCString &ctStr, const QCString &fName);
578 
579     /*! file name that forms the base for the output file containing the
580      *  class documentation. For compatibility with Qt (e.g. links via tag
581      *  files) this name cannot be derived from the class name directly.
582      */
583     QCString fileName;
584 
585     /*! file name used for the list of all members */
586     QCString memberListFileName;
587 
588     /*! file name used for the collaboration diagram */
589     QCString collabFileName;
590 
591     /*! file name used for the inheritance graph */
592     QCString inheritFileName;
593 
594     /*! Include information about the header file should be included
595      *  in the documentation. 0 by default, set by setIncludeFile().
596      */
597     std::unique_ptr<IncludeInfo> incInfo;
598 
599     /*! List of base class (or super-classes) from which this class derives
600      *  directly.
601      */
602     BaseClassList inherits;
603 
604     /*! List of sub-classes that directly derive from this class
605      */
606     BaseClassList inheritedBy;
607 
608     /*! Namespace this class is part of
609      *  (this is the inner most namespace in case of nested namespaces)
610      */
611     //NamespaceDef  *nspace = 0;
612 
613     /*! File this class is defined in */
614     FileDef *fileDef = 0;
615 
616     /*! List of all members (including inherited members) */
617     MemberNameInfoLinkedMap allMemberNameInfoLinkedMap;
618 
619     /*! Template arguments of this class */
620     ArgumentList tempArgs;
621 
622     /*! Type constraints for template parameters */
623     ArgumentList typeConstraints;
624 
625     /*! Files that were used for generating the class documentation. */
626     FileList files;
627 
628     /*! Examples that use this class */
629     ExampleList examples;
630 
631     /*! Holds the kind of "class" this is. */
632     ClassDef::CompoundType compType;
633 
634     /*! The protection level in which this class was found.
635      *  Typically Public, but for nested classes this can also be Protected
636      *  or Private.
637      */
638     Protection prot;
639 
640     /*! The inner classes contained in this class. Will be 0 if there are
641      *  no inner classes.
642      */
643     ClassLinkedRefMap innerClasses;
644 
645     /* classes for the collaboration diagram */
646     UsesClassList usesImplClassList;
647     UsesClassList usedByImplClassList;
648 
649     ConstraintClassList constraintClassList;
650 
651     /*! Template instances that exists of this class, the key in the
652      *  dictionary is the template argument list.
653      */
654     TemplateInstanceList templateInstances;
655 
656     TemplateNameMap templBaseClassNames;
657 
658     /*! The class this class is an instance of. */
659     const ClassDef *templateMaster = 0;
660 
661     /*! local class name which could be a typedef'ed alias name. */
662     QCString className;
663 
664     /*! If this class is a Objective-C category, then this points to the
665      *  class which is extended.
666      */
667     ClassDef *categoryOf = 0;
668 
669     MemberLists memberLists;
670 
671     /* user defined member groups */
672     MemberGroupList memberGroups;
673 
674     /*! Is this an abstract class? */
675     bool isAbstract = false;
676 
677     /*! Is the class part of an unnamed namespace? */
678     bool isStatic = false;
679 
680     /*! TRUE if classes members are merged with those of the base classes. */
681     bool membersMerged = false;
682 
683     /*! TRUE if the class is defined in a source file rather than a header file. */
684     bool isLocal = false;
685 
686     bool isTemplArg = false;
687 
688     /*! Does this class group its user-grouped members
689      *  as a sub-section of the normal (public/protected/..)
690      *  groups?
691      */
692     bool subGrouping = false;
693 
694     /** Reason of existence is a "use" relation */
695     bool usedOnly = false;
696 
697     /** List of titles to use for the summary */
698     StringSet vhdlSummaryTitles;
699 
700     /** Is this a simple (non-nested) C structure? */
701     bool isSimple = false;
702 
703     /** Does this class overloaded the -> operator? */
704     const MemberDef *arrowOperator = 0;
705 
706     const ClassDef *tagLessRef = 0;
707 
708     /** Does this class represent a Java style enum? */
709     bool isJavaEnum = false;
710 
711     uint64 spec = 0;
712 
713     QCString metaData;
714 
715     /** C++20 requires clause */
716     QCString requiresClause;
717 };
718 
init(const QCString & defFileName,const QCString & name,const QCString & ctStr,const QCString & fName)719 void ClassDefImpl::IMPL::init(const QCString &defFileName, const QCString &name,
720                         const QCString &ctStr, const QCString &fName)
721 {
722   if (!fName.isEmpty())
723   {
724     fileName=stripExtension(fName);
725   }
726   else
727   {
728     fileName=ctStr+name;
729   }
730   prot=Public;
731   //nspace=0;
732   fileDef=0;
733   subGrouping=Config_getBool(SUBGROUPING);
734   templateMaster =0;
735   isAbstract = FALSE;
736   isStatic = FALSE;
737   isTemplArg = FALSE;
738   membersMerged = FALSE;
739   categoryOf = 0;
740   usedOnly = FALSE;
741   isSimple = Config_getBool(INLINE_SIMPLE_STRUCTS);
742   arrowOperator = 0;
743   tagLessRef = 0;
744   spec=0;
745   //QCString ns;
746   //extractNamespaceName(name,className,ns);
747   //printf("m_name=%s m_className=%s ns=%s\n",qPrint(m_name),qPrint(m_className),qPrint(ns));
748 
749   // we cannot use getLanguage at this point, as setLanguage has not been called.
750   SrcLangExt lang = getLanguageFromFileName(defFileName);
751   if ((lang==SrcLangExt_Cpp || lang==SrcLangExt_ObjC) &&
752       guessSection(defFileName)==Entry::SOURCE_SEC)
753   {
754     isLocal=TRUE;
755   }
756   else
757   {
758     isLocal=FALSE;
759   }
760 }
761 
IMPL()762 ClassDefImpl::IMPL::IMPL()
763 {
764 }
765 
~IMPL()766 ClassDefImpl::IMPL::~IMPL()
767 {
768 }
769 
770 //-------------------------------------------------------------------------------------------
771 
772 // constructs a new class definition
ClassDefImpl(const QCString & defFileName,int defLine,int defColumn,const QCString & nm,CompoundType ct,const QCString & lref,const QCString & fName,bool isSymbol,bool isJavaEnum)773 ClassDefImpl::ClassDefImpl(
774     const QCString &defFileName,int defLine,int defColumn,
775     const QCString &nm,CompoundType ct,
776     const QCString &lref,const QCString &fName,
777     bool isSymbol,bool isJavaEnum)
778  : DefinitionMixin(defFileName,defLine,defColumn,removeRedundantWhiteSpace(nm),0,0,isSymbol)
779 {
780   setReference(lref);
781   m_impl = new ClassDefImpl::IMPL;
782   m_impl->compType = ct;
783   m_impl->isJavaEnum = isJavaEnum;
784   m_impl->init(defFileName,name(),compoundTypeString(),fName);
785   m_impl->memberListFileName = convertNameToFile(compoundTypeString()+name()+"-members");
786   m_impl->collabFileName = convertNameToFile(m_impl->fileName+"_coll_graph");
787   m_impl->inheritFileName = convertNameToFile(m_impl->fileName+"_inherit_graph");
788   if (lref.isEmpty())
789   {
790     m_impl->fileName = convertNameToFile(m_impl->fileName);
791   }
792 }
793 
794 // destroy the class definition
~ClassDefImpl()795 ClassDefImpl::~ClassDefImpl()
796 {
797   delete m_impl;
798 }
799 
getMemberListFileName() const800 QCString ClassDefImpl::getMemberListFileName() const
801 {
802   return m_impl->memberListFileName;
803 }
804 
displayName(bool includeScope) const805 QCString ClassDefImpl::displayName(bool includeScope) const
806 {
807   return makeDisplayName(this,includeScope);
808 }
809 
810 // inserts a base/super class in the inheritance list
insertBaseClass(ClassDef * cd,const QCString & n,Protection p,Specifier s,const QCString & t)811 void ClassDefImpl::insertBaseClass(ClassDef *cd,const QCString &n,Protection p,
812                                Specifier s,const QCString &t)
813 {
814   //printf("*** insert base class %s into %s\n",qPrint(cd->name()),qPrint(name()));
815   m_impl->inherits.push_back(BaseClassDef(cd,n,p,s,t));
816   m_impl->isSimple = FALSE;
817 }
818 
819 // inserts a derived/sub class in the inherited-by list
insertSubClass(ClassDef * cd,Protection p,Specifier s,const QCString & t)820 void ClassDefImpl::insertSubClass(ClassDef *cd,Protection p,
821                                 Specifier s,const QCString &t)
822 {
823   //printf("*** insert sub class %s into %s\n",qPrint(cd->name()),qPrint(name()));
824   static bool extractPrivate = Config_getBool(EXTRACT_PRIVATE);
825   if (!extractPrivate && cd->protection()==Private) return;
826   m_impl->inheritedBy.push_back(BaseClassDef(cd,QCString(),p,s,t));
827   m_impl->isSimple = FALSE;
828 }
829 
addMembersToMemberGroup()830 void ClassDefImpl::addMembersToMemberGroup()
831 {
832   for (auto &ml : m_impl->memberLists)
833   {
834     if ((ml->listType()&MemberListType_detailedLists)==0)
835     {
836       ::addMembersToMemberGroup(ml.get(),&m_impl->memberGroups,this);
837     }
838   }
839 
840   // add members inside sections to their groups
841   for (const auto &mg : m_impl->memberGroups)
842   {
843     if (mg->allMembersInSameSection() && m_impl->subGrouping)
844     {
845       //printf("addToDeclarationSection(%s)\n",qPrint(mg->header()));
846       mg->addToDeclarationSection();
847     }
848   }
849 }
850 
851 // adds new member definition to the class
internalInsertMember(const MemberDef * md,Protection prot,bool addToAllList)852 void ClassDefImpl::internalInsertMember(const MemberDef *md,
853                                     Protection prot,
854                                     bool addToAllList
855                                    )
856 {
857   //printf("insertInternalMember(%s) isHidden()=%d\n",qPrint(md->name()),md->isHidden());
858   if (md->isHidden()) return;
859 
860   if (getLanguage()==SrcLangExt_VHDL)
861   {
862     QCString title=theTranslator->trVhdlType(md->getMemberSpecifiers(),FALSE);
863     m_impl->vhdlSummaryTitles.insert(title.str());
864   }
865 
866   if (1 /*!isReference()*/) // changed to 1 for showing members of external
867                             // classes when HAVE_DOT and UML_LOOK are enabled.
868   {
869     bool isSimple=FALSE;
870 
871     /********************************************/
872     /* insert member in the declaration section */
873     /********************************************/
874     if (md->isRelated() && protectionLevelVisible(prot))
875     {
876       addMemberToList(MemberListType_related,md,TRUE);
877     }
878     else if (md->isFriend())
879     {
880       addMemberToList(MemberListType_friends,md,TRUE);
881     }
882     else
883     {
884       switch (md->memberType())
885       {
886         case MemberType_Service: // UNO IDL
887           addMemberToList(MemberListType_services,md,TRUE);
888           break;
889         case MemberType_Interface: // UNO IDL
890           addMemberToList(MemberListType_interfaces,md,TRUE);
891           break;
892         case MemberType_Signal: // Qt specific
893           addMemberToList(MemberListType_signals,md,TRUE);
894           break;
895         case MemberType_DCOP:   // KDE2 specific
896           addMemberToList(MemberListType_dcopMethods,md,TRUE);
897           break;
898         case MemberType_Property:
899           addMemberToList(MemberListType_properties,md,TRUE);
900           break;
901         case MemberType_Event:
902           addMemberToList(MemberListType_events,md,TRUE);
903           break;
904         case MemberType_Slot:   // Qt specific
905           switch (prot)
906           {
907             case Protected:
908             case Package: // slots in packages are not possible!
909               addMemberToList(MemberListType_proSlots,md,TRUE);
910               break;
911             case Public:
912               addMemberToList(MemberListType_pubSlots,md,TRUE);
913               break;
914             case Private:
915               addMemberToList(MemberListType_priSlots,md,TRUE);
916               break;
917           }
918           break;
919         default: // any of the other members
920           if (md->isStatic())
921           {
922             if (md->isVariable())
923             {
924               switch (prot)
925               {
926                 case Protected:
927                   addMemberToList(MemberListType_proStaticAttribs,md,TRUE);
928                   break;
929                 case Package:
930                   addMemberToList(MemberListType_pacStaticAttribs,md,TRUE);
931                   break;
932                 case Public:
933                   addMemberToList(MemberListType_pubStaticAttribs,md,TRUE);
934                   break;
935                 case Private:
936                   addMemberToList(MemberListType_priStaticAttribs,md,TRUE);
937                   break;
938               }
939             }
940             else // function
941             {
942               switch (prot)
943               {
944                 case Protected:
945                   addMemberToList(MemberListType_proStaticMethods,md,TRUE);
946                   break;
947                 case Package:
948                   addMemberToList(MemberListType_pacStaticMethods,md,TRUE);
949                   break;
950                 case Public:
951                   addMemberToList(MemberListType_pubStaticMethods,md,TRUE);
952                   break;
953                 case Private:
954                   addMemberToList(MemberListType_priStaticMethods,md,TRUE);
955                   break;
956               }
957             }
958           }
959           else // not static
960           {
961             if (md->isVariable())
962             {
963               switch (prot)
964               {
965                 case Protected:
966                   addMemberToList(MemberListType_proAttribs,md,TRUE);
967                   break;
968                 case Package:
969                   addMemberToList(MemberListType_pacAttribs,md,TRUE);
970                   break;
971                 case Public:
972                   addMemberToList(MemberListType_pubAttribs,md,TRUE);
973                   isSimple=!md->isFunctionPtr();
974                   break;
975                 case Private:
976                   addMemberToList(MemberListType_priAttribs,md,TRUE);
977                   break;
978               }
979             }
980             else if (md->isTypedef() || md->isEnumerate() || md->isEnumValue())
981             {
982               switch (prot)
983               {
984                 case Protected:
985                   addMemberToList(MemberListType_proTypes,md,TRUE);
986                   break;
987                 case Package:
988                   addMemberToList(MemberListType_pacTypes,md,TRUE);
989                   break;
990                 case Public:
991                   addMemberToList(MemberListType_pubTypes,md,TRUE);
992                   isSimple=!md->isEnumerate() &&
993                            !md->isEnumValue() &&
994                            QCString(md->typeString()).find(")(")==-1; // func ptr typedef
995                   break;
996                 case Private:
997                   addMemberToList(MemberListType_priTypes,md,TRUE);
998                   break;
999               }
1000             }
1001             else // member function
1002             {
1003               switch (prot)
1004               {
1005                 case Protected:
1006                   addMemberToList(MemberListType_proMethods,md,TRUE);
1007                   break;
1008                 case Package:
1009                   addMemberToList(MemberListType_pacMethods,md,TRUE);
1010                   break;
1011                 case Public:
1012                   addMemberToList(MemberListType_pubMethods,md,TRUE);
1013                   break;
1014                 case Private:
1015                   addMemberToList(MemberListType_priMethods,md,TRUE);
1016                   break;
1017               }
1018             }
1019           }
1020           break;
1021       }
1022     }
1023     if (!isSimple) // not a simple field -> not a simple struct
1024     {
1025       m_impl->isSimple = FALSE;
1026     }
1027     //printf("adding %s simple=%d total_simple=%d\n",qPrint(name()),isSimple,m_impl->isSimple);
1028 
1029     /*******************************************************/
1030     /* insert member in the detailed documentation section */
1031     /*******************************************************/
1032     if ((md->isRelated() && protectionLevelVisible(prot)) || md->isFriend())
1033     {
1034       addMemberToList(MemberListType_relatedMembers,md,FALSE);
1035     }
1036     else if (md->isFunction() && md->protection()==Private && md->virtualness()!=Normal && Config_getBool(EXTRACT_PRIV_VIRTUAL))
1037     {
1038       addMemberToList(MemberListType_functionMembers,md,FALSE);
1039     }
1040     else
1041     {
1042       switch (md->memberType())
1043       {
1044         case MemberType_Service: // UNO IDL
1045           addMemberToList(MemberListType_serviceMembers,md,FALSE);
1046           break;
1047         case MemberType_Interface: // UNO IDL
1048           addMemberToList(MemberListType_interfaceMembers,md,FALSE);
1049           break;
1050         case MemberType_Property:
1051           addMemberToList(MemberListType_propertyMembers,md,FALSE);
1052           break;
1053         case MemberType_Event:
1054           addMemberToList(MemberListType_eventMembers,md,FALSE);
1055           break;
1056         case MemberType_Signal: // fall through
1057         case MemberType_DCOP:
1058           addMemberToList(MemberListType_functionMembers,md,FALSE);
1059           break;
1060         case MemberType_Slot:
1061           if (protectionLevelVisible(prot))
1062           {
1063             addMemberToList(MemberListType_functionMembers,md,FALSE);
1064           }
1065           break;
1066         default: // any of the other members
1067           if (protectionLevelVisible(prot))
1068           {
1069             switch (md->memberType())
1070             {
1071               case MemberType_Typedef:
1072                 addMemberToList(MemberListType_typedefMembers,md,FALSE);
1073                 break;
1074               case MemberType_Enumeration:
1075                 addMemberToList(MemberListType_enumMembers,md,FALSE);
1076                 break;
1077               case MemberType_EnumValue:
1078                 addMemberToList(MemberListType_enumValMembers,md,FALSE);
1079                 break;
1080               case MemberType_Function:
1081                 if (md->isConstructor() || md->isDestructor())
1082                 {
1083                   m_impl->memberLists.get(MemberListType_constructors,MemberListContainer::Class)->push_back(md);
1084                 }
1085                 else
1086                 {
1087                   addMemberToList(MemberListType_functionMembers,md,FALSE);
1088                 }
1089                 break;
1090               case MemberType_Variable:
1091                 addMemberToList(MemberListType_variableMembers,md,FALSE);
1092                 break;
1093               case MemberType_Define:
1094                 warn(md->getDefFileName(),md->getDefLine()-1,"A define (%s) cannot be made a member of %s",
1095                      qPrint(md->name()), qPrint(this->name()));
1096                 break;
1097               default:
1098                 err("Unexpected member type %d found!\n",md->memberType());
1099             }
1100           }
1101           break;
1102       }
1103     }
1104 
1105     /*************************************************/
1106     /* insert member in the appropriate member group */
1107     /*************************************************/
1108     // Note: this must be done AFTER inserting the member in the
1109     // regular groups
1110     //addMemberToGroup(md,groupId);
1111 
1112   }
1113 
1114   if (md->virtualness()==Pure)
1115   {
1116     m_impl->isAbstract=TRUE;
1117   }
1118 
1119   if (md->name()=="operator->")
1120   {
1121     m_impl->arrowOperator=md;
1122   }
1123 
1124   //::addClassMemberNameToIndex(md);
1125   if (addToAllList &&
1126       !(Config_getBool(HIDE_FRIEND_COMPOUNDS) &&
1127         md->isFriend() &&
1128         (QCString(md->typeString())=="friend class" ||
1129          QCString(md->typeString())=="friend struct" ||
1130          QCString(md->typeString())=="friend union")))
1131   {
1132     //printf("=======> adding member %s to class %s\n",qPrint(md->name()),qPrint(name()));
1133 
1134     MemberNameInfo *mni = m_impl->allMemberNameInfoLinkedMap.add(md->name());
1135     mni->push_back(std::make_unique<MemberInfo>(md,prot,md->virtualness(),FALSE));
1136   }
1137 }
1138 
insertMember(MemberDef * md)1139 void ClassDefImpl::insertMember(MemberDef *md)
1140 {
1141   internalInsertMember(md,md->protection(),TRUE);
1142 }
1143 
1144 // compute the anchors for all members
computeAnchors()1145 void ClassDefImpl::computeAnchors()
1146 {
1147   for (auto &ml : m_impl->memberLists)
1148   {
1149     if ((ml->listType()&MemberListType_detailedLists)==0)
1150     {
1151       ml->setAnchors();
1152     }
1153   }
1154 
1155   for (const auto &mg : m_impl->memberGroups)
1156   {
1157     mg->setAnchors();
1158   }
1159 }
1160 
distributeMemberGroupDocumentation()1161 void ClassDefImpl::distributeMemberGroupDocumentation()
1162 {
1163   for (const auto &mg : m_impl->memberGroups)
1164   {
1165     mg->distributeMemberGroupDocumentation();
1166   }
1167 }
1168 
findSectionsInDocumentation()1169 void ClassDefImpl::findSectionsInDocumentation()
1170 {
1171   docFindSections(briefDescription(),this,docFile());
1172   docFindSections(documentation(),this,docFile());
1173   for (const auto &mg : m_impl->memberGroups)
1174   {
1175     mg->findSectionsInDocumentation(this);
1176   }
1177   for (auto &ml : m_impl->memberLists)
1178   {
1179     if ((ml->listType()&MemberListType_detailedLists)==0)
1180     {
1181       ml->findSectionsInDocumentation(this);
1182     }
1183   }
1184 }
1185 
1186 
1187 // add a file name to the used files set
insertUsedFile(const FileDef * fd)1188 void ClassDefImpl::insertUsedFile(const FileDef *fd)
1189 {
1190   if (fd==0) return;
1191   auto it = std::find(m_impl->files.begin(),m_impl->files.end(),fd);
1192   if (it==m_impl->files.end())
1193   {
1194     m_impl->files.push_back(fd);
1195   }
1196   for (const auto &ti : m_impl->templateInstances)
1197   {
1198     ClassDefMutable *cdm = toClassDefMutable(ti.classDef);
1199     if (cdm)
1200     {
1201       cdm->insertUsedFile(fd);
1202     }
1203   }
1204 }
1205 
writeInheritanceSpecifier(OutputList & ol,const BaseClassDef & bcd)1206 static void writeInheritanceSpecifier(OutputList &ol,const BaseClassDef &bcd)
1207 {
1208   if (bcd.prot!=Public || bcd.virt!=Normal)
1209   {
1210     ol.startTypewriter();
1211     ol.docify(" [");
1212     StringVector sl;
1213     if      (bcd.prot==Protected) sl.push_back("protected");
1214     else if (bcd.prot==Private)   sl.push_back("private");
1215     if      (bcd.virt==Virtual)   sl.push_back("virtual");
1216     bool first=true;
1217     for (const auto &s : sl)
1218     {
1219       if (!first) ol.docify(", ");
1220       ol.docify(s.c_str());
1221       first=false;
1222     }
1223     ol.docify("]");
1224     ol.endTypewriter();
1225   }
1226 }
1227 
setIncludeFile(FileDef * fd,const QCString & includeName,bool local,bool force)1228 void ClassDefImpl::setIncludeFile(FileDef *fd,
1229              const QCString &includeName,bool local, bool force)
1230 {
1231   //printf("ClassDefImpl::setIncludeFile(%p,%s,%d,%d)\n",fd,includeName,local,force);
1232   if (!m_impl->incInfo) m_impl->incInfo = std::make_unique<IncludeInfo>();
1233   if ((!includeName.isEmpty() && m_impl->incInfo->includeName.isEmpty()) ||
1234       (fd!=0 && m_impl->incInfo->fileDef==0)
1235      )
1236   {
1237     //printf("Setting file info\n");
1238     m_impl->incInfo->fileDef     = fd;
1239     m_impl->incInfo->includeName = includeName;
1240     m_impl->incInfo->local       = local;
1241   }
1242   if (force && !includeName.isEmpty())
1243   {
1244     m_impl->incInfo->includeName = includeName;
1245     m_impl->incInfo->local       = local;
1246   }
1247 }
1248 
1249 // TODO: fix this: a nested template class can have multiple outer templates
1250 //ArgumentList *ClassDefImpl::outerTemplateArguments() const
1251 //{
1252 //  int ti;
1253 //  ClassDef *pcd=0;
1254 //  int pi=0;
1255 //  if (m_impl->tempArgs) return m_impl->tempArgs;
1256 //  // find the outer most class scope
1257 //  while ((ti=name().find("::",pi))!=-1 &&
1258 //      (pcd=getClass(name().left(ti)))==0
1259 //        ) pi=ti+2;
1260 //  if (pcd)
1261 //  {
1262 //    return pcd->templateArguments();
1263 //  }
1264 //  return 0;
1265 //}
1266 
searchTemplateSpecs(const Definition * d,ArgumentLists & result,QCString & name,SrcLangExt lang)1267 static void searchTemplateSpecs(/*in*/  const Definition *d,
1268                                 /*out*/ ArgumentLists &result,
1269                                 /*out*/ QCString &name,
1270                                 /*in*/  SrcLangExt lang)
1271 {
1272   if (d->definitionType()==Definition::TypeClass)
1273   {
1274     if (d->getOuterScope())
1275     {
1276       searchTemplateSpecs(d->getOuterScope(),result,name,lang);
1277     }
1278     const ClassDef *cd=toClassDef(d);
1279     if (!name.isEmpty()) name+="::";
1280     QCString clName = d->localName();
1281     if (/*clName.right(2)=="-g" ||*/ clName.right(2)=="-p")
1282     {
1283       clName = clName.left(clName.length()-2);
1284     }
1285     name+=clName;
1286     bool isSpecialization = d->localName().find('<')!=-1;
1287     if (!cd->templateArguments().empty())
1288     {
1289       result.push_back(cd->templateArguments());
1290       if (!isSpecialization)
1291       {
1292         name+=tempArgListToString(cd->templateArguments(),lang);
1293       }
1294     }
1295   }
1296   else
1297   {
1298     name+=d->qualifiedName();
1299   }
1300 }
1301 
writeTemplateSpec(OutputList & ol,const Definition * d,const QCString & type,SrcLangExt lang) const1302 void ClassDefImpl::writeTemplateSpec(OutputList &ol,const Definition *d,
1303             const QCString &type,SrcLangExt lang) const
1304 {
1305   ArgumentLists specs;
1306   QCString name;
1307   searchTemplateSpecs(d,specs,name,lang);
1308   if (!specs.empty()) // class has template scope specifiers
1309   {
1310     ol.startCompoundTemplateParams();
1311     for (const ArgumentList &al : specs)
1312     {
1313       ol.docify("template<");
1314       auto it = al.begin();
1315       while (it!=al.end())
1316       {
1317         Argument a = *it;
1318         linkifyText(TextGeneratorOLImpl(ol), // out
1319           d,                       // scope
1320           getFileDef(),            // fileScope
1321           this,                    // self
1322           a.type,                  // text
1323           FALSE                    // autoBreak
1324           );
1325         if (!a.name.isEmpty())
1326         {
1327           ol.docify(" ");
1328           ol.docify(a.name);
1329         }
1330         if (a.defval.length()!=0)
1331         {
1332           ol.docify(" = ");
1333           ol.docify(a.defval);
1334         }
1335         ++it;
1336         if (it!=al.end()) ol.docify(", ");
1337       }
1338       ol.docify(">");
1339       ol.lineBreak();
1340     }
1341     if (!m_impl->requiresClause.isEmpty())
1342     {
1343       ol.docify("requires ");
1344       linkifyText(TextGeneratorOLImpl(ol), // out
1345           d,                       // scope
1346           getFileDef(),            // fileScope
1347           this,                    // self
1348           m_impl->requiresClause,  // text
1349           FALSE                    // autoBreak
1350           );
1351       ol.lineBreak();
1352     }
1353     ol.docify(type.lower()+" "+name);
1354     ol.endCompoundTemplateParams();
1355   }
1356 }
1357 
writeBriefDescription(OutputList & ol,bool exampleFlag) const1358 void ClassDefImpl::writeBriefDescription(OutputList &ol,bool exampleFlag) const
1359 {
1360   if (hasBriefDescription())
1361   {
1362     ol.startParagraph();
1363     ol.pushGeneratorState();
1364     ol.disableAllBut(OutputGenerator::Man);
1365     ol.writeString(" - ");
1366     ol.popGeneratorState();
1367     ol.generateDoc(briefFile(),briefLine(),this,0,
1368                    briefDescription(),TRUE,FALSE,QCString(),
1369                    TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT));
1370     ol.pushGeneratorState();
1371     ol.disable(OutputGenerator::RTF);
1372     ol.writeString(" \n");
1373     ol.enable(OutputGenerator::RTF);
1374     ol.popGeneratorState();
1375 
1376     if (hasDetailedDescription() || exampleFlag)
1377     {
1378       writeMoreLink(ol,anchor());
1379     }
1380 
1381     ol.endParagraph();
1382   }
1383   ol.writeSynopsis();
1384 }
1385 
writeDetailedDocumentationBody(OutputList & ol) const1386 void ClassDefImpl::writeDetailedDocumentationBody(OutputList &ol) const
1387 {
1388   static bool repeatBrief = Config_getBool(REPEAT_BRIEF);
1389 
1390   ol.startTextBlock();
1391 
1392   if (getLanguage()==SrcLangExt_Cpp)
1393   {
1394     writeTemplateSpec(ol,this,compoundTypeString(),getLanguage());
1395   }
1396 
1397   // repeat brief description
1398   if (!briefDescription().isEmpty() && repeatBrief)
1399   {
1400     ol.generateDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE,
1401                    QCString(),FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT));
1402   }
1403   if (!briefDescription().isEmpty() && repeatBrief &&
1404       !documentation().isEmpty())
1405   {
1406     ol.pushGeneratorState();
1407     ol.disable(OutputGenerator::Html);
1408     ol.writeString("\n\n");
1409     ol.popGeneratorState();
1410   }
1411   // write documentation
1412   if (!documentation().isEmpty())
1413   {
1414     ol.generateDoc(docFile(),docLine(),this,0,documentation(),TRUE,FALSE,
1415                    QCString(),FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT));
1416   }
1417   // write type constraints
1418   writeTypeConstraints(ol,this,m_impl->typeConstraints);
1419 
1420   // write examples
1421   if (hasExamples())
1422   {
1423     ol.startExamples();
1424     ol.startDescForItem();
1425     //ol.startParagraph();
1426     writeExamples(ol,m_impl->examples);
1427     //ol.endParagraph();
1428     ol.endDescForItem();
1429     ol.endExamples();
1430   }
1431   //ol.newParagraph();
1432   writeSourceDef(ol,name());
1433   ol.endTextBlock();
1434 }
1435 
hasDetailedDescription() const1436 bool ClassDefImpl::hasDetailedDescription() const
1437 {
1438   static bool repeatBrief = Config_getBool(REPEAT_BRIEF);
1439   static bool sourceBrowser = Config_getBool(SOURCE_BROWSER);
1440   return ((!briefDescription().isEmpty() && repeatBrief) ||
1441           !documentation().isEmpty() ||
1442           (sourceBrowser && getStartBodyLine()!=-1 && getBodyDef()));
1443 }
1444 
1445 // write the detailed description for this class
writeDetailedDescription(OutputList & ol,const QCString &,bool exampleFlag,const QCString & title,const QCString & anchor) const1446 void ClassDefImpl::writeDetailedDescription(OutputList &ol, const QCString &/*pageType*/, bool exampleFlag,
1447                                         const QCString &title,const QCString &anchor) const
1448 {
1449   if (hasDetailedDescription() || exampleFlag)
1450   {
1451     ol.pushGeneratorState();
1452       ol.disable(OutputGenerator::Html);
1453       ol.writeRuler();
1454     ol.popGeneratorState();
1455 
1456     ol.pushGeneratorState();
1457       ol.disableAllBut(OutputGenerator::Html);
1458       ol.writeAnchor(QCString(),anchor.isEmpty() ? QCString("details") : anchor);
1459     ol.popGeneratorState();
1460 
1461     if (!anchor.isEmpty())
1462     {
1463       ol.pushGeneratorState();
1464       ol.disable(OutputGenerator::Html);
1465       ol.disable(OutputGenerator::Man);
1466       ol.writeAnchor(getOutputFileBase(),anchor);
1467       ol.popGeneratorState();
1468     }
1469 
1470     ol.startGroupHeader();
1471     ol.parseText(title);
1472     ol.endGroupHeader();
1473 
1474     writeDetailedDocumentationBody(ol);
1475   }
1476   else
1477   {
1478     //writeTemplateSpec(ol,this,pageType);
1479   }
1480 }
1481 
generatedFromFiles() const1482 QCString ClassDefImpl::generatedFromFiles() const
1483 {
1484   QCString result;
1485   SrcLangExt lang = getLanguage();
1486   size_t numFiles = m_impl->files.size();
1487   if (lang==SrcLangExt_Fortran)
1488   {
1489     result = theTranslator->trGeneratedFromFilesFortran(
1490           getLanguage()==SrcLangExt_ObjC && m_impl->compType==Interface ? Class : m_impl->compType,
1491           numFiles==1);
1492   }
1493   else if (isJavaEnum())
1494   {
1495     result = theTranslator->trEnumGeneratedFromFiles(numFiles==1);
1496   }
1497   else if (m_impl->compType==Service)
1498   {
1499     result = theTranslator->trServiceGeneratedFromFiles(numFiles==1);
1500   }
1501   else if (m_impl->compType==Singleton)
1502   {
1503     result = theTranslator->trSingletonGeneratedFromFiles(numFiles==1);
1504   }
1505   else
1506   {
1507     result = theTranslator->trGeneratedFromFiles(
1508           getLanguage()==SrcLangExt_ObjC && m_impl->compType==Interface ? Class : m_impl->compType,
1509           numFiles==1);
1510   }
1511   return result;
1512 }
1513 
showUsedFiles(OutputList & ol) const1514 void ClassDefImpl::showUsedFiles(OutputList &ol) const
1515 {
1516   ol.pushGeneratorState();
1517   ol.disable(OutputGenerator::Man);
1518 
1519 
1520   ol.writeRuler();
1521   ol.pushGeneratorState();
1522     ol.disableAllBut(OutputGenerator::Docbook);
1523     ol.startParagraph();
1524     ol.parseText(generatedFromFiles());
1525     ol.endParagraph();
1526   ol.popGeneratorState();
1527   ol.disable(OutputGenerator::Docbook);
1528     ol.parseText(generatedFromFiles());
1529   ol.enable(OutputGenerator::Docbook);
1530 
1531   bool first=TRUE;
1532   for (const auto &fd : m_impl->files)
1533   {
1534     if (first)
1535     {
1536       first=FALSE;
1537       ol.startItemList();
1538     }
1539 
1540     ol.startItemListItem();
1541     QCString path=fd->getPath();
1542     if (Config_getBool(FULL_PATH_NAMES))
1543     {
1544       ol.docify(stripFromPath(path));
1545     }
1546 
1547     QCString fname = fd->name();
1548     if (!fd->getVersion().isEmpty()) // append version if available
1549     {
1550       fname += " (" + fd->getVersion() + ")";
1551     }
1552 
1553     // for HTML
1554     ol.pushGeneratorState();
1555     ol.disableAllBut(OutputGenerator::Html);
1556     if (fd->generateSourceFile())
1557     {
1558       ol.writeObjectLink(QCString(),fd->getSourceFileBase(),QCString(),fname);
1559     }
1560     else if (fd->isLinkable())
1561     {
1562       ol.writeObjectLink(fd->getReference(),fd->getOutputFileBase(),QCString(),fname);
1563     }
1564     else
1565     {
1566       ol.docify(fname);
1567     }
1568     ol.popGeneratorState();
1569 
1570     // for other output formats
1571     ol.pushGeneratorState();
1572     ol.disable(OutputGenerator::Html);
1573     if (fd->isLinkable())
1574     {
1575       ol.writeObjectLink(fd->getReference(),fd->getOutputFileBase(),QCString(),fname);
1576     }
1577     else
1578     {
1579       ol.docify(fname);
1580     }
1581     ol.popGeneratorState();
1582 
1583     ol.endItemListItem();
1584   }
1585   if (!first) ol.endItemList();
1586 
1587   ol.popGeneratorState();
1588 }
1589 
countInheritanceNodes() const1590 int ClassDefImpl::countInheritanceNodes() const
1591 {
1592   int count=0;
1593   for (const auto &ibcd : m_impl->inheritedBy)
1594   {
1595     const ClassDef *icd=ibcd.classDef;
1596     if ( icd->isVisibleInHierarchy()) count++;
1597   }
1598   for (const auto &ibcd : m_impl->inherits)
1599   {
1600     const ClassDef *icd=ibcd.classDef;
1601     if ( icd->isVisibleInHierarchy()) count++;
1602   }
1603   return count;
1604 }
1605 
writeInheritanceGraph(OutputList & ol) const1606 void ClassDefImpl::writeInheritanceGraph(OutputList &ol) const
1607 {
1608   static bool haveDot    = Config_getBool(HAVE_DOT);
1609   static auto classGraph = Config_getEnum(CLASS_GRAPH);
1610 
1611   if (classGraph == CLASS_GRAPH_t::NO) return;
1612   // count direct inheritance relations
1613   const int count=countInheritanceNodes();
1614 
1615   bool renderDiagram = FALSE;
1616   if (haveDot && (classGraph==CLASS_GRAPH_t::YES || classGraph==CLASS_GRAPH_t::GRAPH))
1617     // write class diagram using dot
1618   {
1619     DotClassGraph inheritanceGraph(this,Inheritance);
1620     if (inheritanceGraph.isTooBig())
1621     {
1622        warn_uncond("Inheritance graph for '%s' not generated, too many nodes (%d), threshold is %d. Consider increasing DOT_GRAPH_MAX_NODES.\n",
1623            qPrint(name()), inheritanceGraph.numNodes(), Config_getInt(DOT_GRAPH_MAX_NODES));
1624     }
1625     else if (!inheritanceGraph.isTrivial())
1626     {
1627       ol.pushGeneratorState();
1628       ol.disable(OutputGenerator::Man);
1629       ol.startDotGraph();
1630       ol.parseText(theTranslator->trClassDiagram(displayName()));
1631       ol.endDotGraph(inheritanceGraph);
1632       ol.popGeneratorState();
1633       renderDiagram = TRUE;
1634     }
1635   }
1636   else if ((classGraph==CLASS_GRAPH_t::YES || classGraph==CLASS_GRAPH_t::GRAPH) && count>0)
1637     // write class diagram using built-in generator
1638   {
1639     ClassDiagram diagram(this); // create a diagram of this class.
1640     ol.startClassDiagram();
1641     ol.disable(OutputGenerator::Man);
1642     ol.parseText(theTranslator->trClassDiagram(displayName()));
1643     ol.enable(OutputGenerator::Man);
1644     ol.endClassDiagram(diagram,getOutputFileBase(),displayName());
1645     renderDiagram = TRUE;
1646   }
1647 
1648   if (renderDiagram) // if we already show the inheritance relations graphically,
1649                      // then hide the text version
1650   {
1651     ol.disableAllBut(OutputGenerator::Man);
1652   }
1653 
1654   if (!m_impl->inherits.empty())
1655   {
1656     auto replaceFunc = [this,&ol](size_t entryIndex)
1657     {
1658       BaseClassDef &bcd=m_impl->inherits[entryIndex];
1659       ClassDef *cd=bcd.classDef;
1660 
1661       // use the class name but with the template arguments as given
1662       // in the inheritance relation
1663       QCString displayName = insertTemplateSpecifierInScope(
1664           cd->displayName(),bcd.templSpecifiers);
1665 
1666       if (cd->isLinkable())
1667       {
1668         ol.writeObjectLink(cd->getReference(),
1669             cd->getOutputFileBase(),
1670             cd->anchor(),
1671             displayName);
1672       }
1673       else
1674       {
1675         ol.docify(displayName);
1676       }
1677     };
1678 
1679     ol.startParagraph();
1680     writeMarkerList(ol,
1681                     theTranslator->trInheritsList((int)m_impl->inherits.size()).str(),
1682                     m_impl->inherits.size(),
1683                     replaceFunc);
1684     ol.endParagraph();
1685   }
1686 
1687   // write subclasses
1688   if (!m_impl->inheritedBy.empty())
1689   {
1690 
1691     auto replaceFunc = [this,&ol](size_t entryIndex)
1692     {
1693       BaseClassDef &bcd=m_impl->inheritedBy[entryIndex];
1694       ClassDef *cd=bcd.classDef;
1695       if (cd->isLinkable())
1696       {
1697         ol.writeObjectLink(cd->getReference(),cd->getOutputFileBase(),cd->anchor(),cd->displayName());
1698       }
1699       else
1700       {
1701         ol.docify(cd->displayName());
1702       }
1703       writeInheritanceSpecifier(ol,bcd);
1704     };
1705 
1706     ol.startParagraph();
1707     writeMarkerList(ol,
1708                     theTranslator->trInheritedByList((int)m_impl->inheritedBy.size()).str(),
1709                     m_impl->inheritedBy.size(),
1710                     replaceFunc);
1711     ol.endParagraph();
1712   }
1713 
1714   if (renderDiagram)
1715   {
1716     ol.enableAll();
1717   }
1718 }
1719 
writeCollaborationGraph(OutputList & ol) const1720 void ClassDefImpl::writeCollaborationGraph(OutputList &ol) const
1721 {
1722   if (Config_getBool(HAVE_DOT) /*&& Config_getBool(COLLABORATION_GRAPH)*/)
1723   {
1724     DotClassGraph usageImplGraph(this,Collaboration);
1725     if (!usageImplGraph.isTrivial())
1726     {
1727       ol.pushGeneratorState();
1728       ol.disable(OutputGenerator::Man);
1729       ol.startDotGraph();
1730       ol.parseText(theTranslator->trCollaborationDiagram(displayName()));
1731       ol.endDotGraph(usageImplGraph);
1732       ol.popGeneratorState();
1733     }
1734   }
1735 }
1736 
includeStatement() const1737 QCString ClassDefImpl::includeStatement() const
1738 {
1739   SrcLangExt lang = getLanguage();
1740   bool isIDLorJava = lang==SrcLangExt_IDL || lang==SrcLangExt_Java;
1741   if (isIDLorJava)
1742   {
1743     return "import";
1744   }
1745   else if (isObjectiveC())
1746   {
1747     return "#import ";
1748   }
1749   else
1750   {
1751     return "#include ";
1752   }
1753 }
1754 
writeIncludeFilesForSlice(OutputList & ol) const1755 void ClassDefImpl::writeIncludeFilesForSlice(OutputList &ol) const
1756 {
1757   if (m_impl->incInfo)
1758   {
1759     QCString nm;
1760     const StringVector &paths = Config_getList(STRIP_FROM_PATH);
1761     if (!paths.empty() && m_impl->incInfo->fileDef)
1762     {
1763       QCString abs = m_impl->incInfo->fileDef->absFilePath();
1764       QCString potential;
1765       unsigned int length = 0;
1766       for (const auto &s : paths)
1767       {
1768         FileInfo info(s);
1769         if (info.exists())
1770         {
1771           QCString prefix = info.absFilePath();
1772           if (prefix.at(prefix.length() - 1) != '/')
1773           {
1774             prefix += '/';
1775           }
1776 
1777           if (prefix.length() > length &&
1778               qstricmp(abs.left(prefix.length()).data(), prefix.data()) == 0) // case insensitive compare
1779           {
1780             length = prefix.length();
1781             potential = abs.right(abs.length() - prefix.length());
1782           }
1783         }
1784       }
1785 
1786       if (length > 0)
1787       {
1788         nm = potential;
1789       }
1790     }
1791 
1792     if (nm.isEmpty())
1793     {
1794       nm = m_impl->incInfo->includeName;
1795     }
1796 
1797     ol.startParagraph();
1798     ol.docify(theTranslator->trDefinedIn()+" ");
1799     ol.startTypewriter();
1800     ol.docify("<");
1801     if (m_impl->incInfo->fileDef)
1802     {
1803       ol.writeObjectLink(QCString(),m_impl->incInfo->fileDef->includeName(),QCString(),nm);
1804     }
1805     else
1806     {
1807       ol.docify(nm);
1808     }
1809     ol.docify(">");
1810     ol.endTypewriter();
1811     ol.endParagraph();
1812   }
1813 
1814   // Write a summary of the Slice definition including metadata.
1815   ol.startParagraph();
1816   ol.startTypewriter();
1817   if (!m_impl->metaData.isEmpty())
1818   {
1819     ol.docify(m_impl->metaData);
1820     ol.lineBreak();
1821   }
1822   if (m_impl->spec & Entry::Local)
1823   {
1824     ol.docify("local ");
1825   }
1826   if (m_impl->spec & Entry::Interface)
1827   {
1828     ol.docify("interface ");
1829   }
1830   else if (m_impl->spec & Entry::Struct)
1831   {
1832     ol.docify("struct ");
1833   }
1834   else if (m_impl->spec & Entry::Exception)
1835   {
1836     ol.docify("exception ");
1837   }
1838   else
1839   {
1840     ol.docify("class ");
1841   }
1842   ol.docify(stripScope(name()));
1843   if (!m_impl->inherits.empty())
1844   {
1845     if (m_impl->spec & (Entry::Interface|Entry::Exception))
1846     {
1847       ol.docify(" extends ");
1848       bool first=true;
1849       for (const auto &ibcd : m_impl->inherits)
1850       {
1851         if (!first) ol.docify(", ");
1852         ClassDef *icd = ibcd.classDef;
1853         ol.docify(icd->name());
1854         first=false;
1855       }
1856     }
1857     else
1858     {
1859       // Must be a class.
1860       bool implements = false;
1861       for (const auto &ibcd : m_impl->inherits)
1862       {
1863         ClassDef *icd = ibcd.classDef;
1864         if (icd->isInterface())
1865         {
1866           implements = true;
1867         }
1868         else
1869         {
1870           ol.docify(" extends ");
1871           ol.docify(icd->name());
1872         }
1873       }
1874       if (implements)
1875       {
1876         ol.docify(" implements ");
1877         bool first = true;
1878         for (const auto &ibcd : m_impl->inherits)
1879         {
1880           ClassDef *icd = ibcd.classDef;
1881           if (icd->isInterface())
1882           {
1883             if (!first) ol.docify(", ");
1884             first = false;
1885             ol.docify(icd->name());
1886           }
1887         }
1888       }
1889     }
1890   }
1891   ol.docify(" { ... }");
1892   ol.endTypewriter();
1893   ol.endParagraph();
1894 }
1895 
writeIncludeFiles(OutputList & ol) const1896 void ClassDefImpl::writeIncludeFiles(OutputList &ol) const
1897 {
1898   if (m_impl->incInfo /*&& Config_getBool(SHOW_HEADERFILE)*/)
1899   {
1900     SrcLangExt lang = getLanguage();
1901     QCString nm=m_impl->incInfo->includeName.isEmpty() ?
1902       (m_impl->incInfo->fileDef ?
1903        m_impl->incInfo->fileDef->docName() : QCString()
1904       ) :
1905       m_impl->incInfo->includeName;
1906     if (!nm.isEmpty())
1907     {
1908       ol.startParagraph();
1909       ol.startTypewriter();
1910       ol.docify(includeStatement());
1911       bool isIDLorJava = lang==SrcLangExt_IDL || lang==SrcLangExt_Java;
1912       if (m_impl->incInfo->local || isIDLorJava)
1913         ol.docify("\"");
1914       else
1915         ol.docify("<");
1916       ol.pushGeneratorState();
1917       ol.disable(OutputGenerator::Html);
1918       ol.docify(nm);
1919       ol.disableAllBut(OutputGenerator::Html);
1920       ol.enable(OutputGenerator::Html);
1921       if (m_impl->incInfo->fileDef)
1922       {
1923         ol.writeObjectLink(QCString(),m_impl->incInfo->fileDef->includeName(),QCString(),nm);
1924       }
1925       else
1926       {
1927         ol.docify(nm);
1928       }
1929       ol.popGeneratorState();
1930       if (m_impl->incInfo->local || isIDLorJava)
1931         ol.docify("\"");
1932       else
1933         ol.docify(">");
1934       if (isIDLorJava)
1935         ol.docify(";");
1936       ol.endTypewriter();
1937       ol.endParagraph();
1938     }
1939   }
1940 }
1941 
writeMemberGroups(OutputList & ol,bool showInline) const1942 void ClassDefImpl::writeMemberGroups(OutputList &ol,bool showInline) const
1943 {
1944   // write user defined member groups
1945   for (const auto &mg : m_impl->memberGroups)
1946   {
1947     if (!mg->allMembersInSameSection() || !m_impl->subGrouping) // group is in its own section
1948     {
1949       mg->writeDeclarations(ol,this,0,0,0,showInline);
1950     }
1951     else // add this group to the corresponding member section
1952     {
1953       //printf("addToDeclarationSection(%s)\n",qPrint(mg->header()));
1954       //mg->addToDeclarationSection();
1955     }
1956   }
1957 }
1958 
writeNestedClasses(OutputList & ol,const QCString & title) const1959 void ClassDefImpl::writeNestedClasses(OutputList &ol,const QCString &title) const
1960 {
1961   // nested classes
1962   m_impl->innerClasses.writeDeclaration(ol,0,title,TRUE);
1963 }
1964 
writeInlineClasses(OutputList & ol) const1965 void ClassDefImpl::writeInlineClasses(OutputList &ol) const
1966 {
1967   m_impl->innerClasses.writeDocumentation(ol,this);
1968 }
1969 
startMemberDocumentation(OutputList & ol) const1970 void ClassDefImpl::startMemberDocumentation(OutputList &ol) const
1971 {
1972   //printf("%s: ClassDefImpl::startMemberDocumentation()\n",qPrint(name()));
1973   if (Config_getBool(SEPARATE_MEMBER_PAGES))
1974   {
1975     ol.disable(OutputGenerator::Html);
1976     Doxygen::suppressDocWarnings = TRUE;
1977   }
1978 }
1979 
endMemberDocumentation(OutputList & ol) const1980 void ClassDefImpl::endMemberDocumentation(OutputList &ol) const
1981 {
1982   //printf("%s: ClassDefImpl::endMemberDocumentation()\n",qPrint(name()));
1983   if (Config_getBool(SEPARATE_MEMBER_PAGES))
1984   {
1985     ol.enable(OutputGenerator::Html);
1986     Doxygen::suppressDocWarnings = FALSE;
1987   }
1988 }
1989 
startMemberDeclarations(OutputList & ol) const1990 void ClassDefImpl::startMemberDeclarations(OutputList &ol) const
1991 {
1992   //printf("%s: ClassDefImpl::startMemberDeclarations()\n",qPrint(name()));
1993   ol.startMemberSections();
1994 }
1995 
endMemberDeclarations(OutputList & ol) const1996 void ClassDefImpl::endMemberDeclarations(OutputList &ol) const
1997 {
1998   //printf("%s: ClassDefImpl::endMemberDeclarations()\n",qPrint(name()));
1999   static bool inlineInheritedMembers = Config_getBool(INLINE_INHERITED_MEMB);
2000   if (!inlineInheritedMembers && countAdditionalInheritedMembers()>0)
2001   {
2002     ol.startMemberHeader("inherited");
2003     ol.parseText(theTranslator->trAdditionalInheritedMembers());
2004     ol.endMemberHeader();
2005     writeAdditionalInheritedMembers(ol);
2006   }
2007   ol.endMemberSections();
2008 }
2009 
writeAuthorSection(OutputList & ol) const2010 void ClassDefImpl::writeAuthorSection(OutputList &ol) const
2011 {
2012   ol.pushGeneratorState();
2013   ol.disableAllBut(OutputGenerator::Man);
2014   ol.writeString("\n");
2015   ol.startGroupHeader();
2016   ol.parseText(theTranslator->trAuthor(TRUE,TRUE));
2017   ol.endGroupHeader();
2018   ol.parseText(theTranslator->trGeneratedAutomatically(Config_getString(PROJECT_NAME)));
2019   ol.popGeneratorState();
2020 }
2021 
2022 
writeSummaryLinks(OutputList & ol) const2023 void ClassDefImpl::writeSummaryLinks(OutputList &ol) const
2024 {
2025   ol.pushGeneratorState();
2026   ol.disableAllBut(OutputGenerator::Html);
2027   bool first=TRUE;
2028   SrcLangExt lang = getLanguage();
2029 
2030   if (lang!=SrcLangExt_VHDL)
2031   {
2032     for (const auto &lde : LayoutDocManager::instance().docEntries(LayoutDocManager::Class))
2033     {
2034       if (lde->kind()==LayoutDocEntry::ClassNestedClasses &&
2035           m_impl->innerClasses.declVisible()
2036          )
2037       {
2038         const LayoutDocEntrySection *ls = (const LayoutDocEntrySection*)lde.get();
2039         ol.writeSummaryLink(QCString(),"nested-classes",ls->title(lang),first);
2040         first=FALSE;
2041       }
2042       else if (lde->kind()==LayoutDocEntry::ClassAllMembersLink &&
2043                !m_impl->allMemberNameInfoLinkedMap.empty() &&
2044                !Config_getBool(OPTIMIZE_OUTPUT_FOR_C)
2045               )
2046       {
2047         ol.writeSummaryLink(getMemberListFileName(),"all-members-list",theTranslator->trListOfAllMembers(),first);
2048         first=FALSE;
2049       }
2050       else if (lde->kind()== LayoutDocEntry::MemberDecl)
2051       {
2052         const LayoutDocEntryMemberDecl *lmd = (const LayoutDocEntryMemberDecl*)lde.get();
2053         MemberList * ml = getMemberList(lmd->type);
2054         if (ml && ml->declVisible())
2055         {
2056           ol.writeSummaryLink(QCString(),MemberList::listTypeAsString(ml->listType()),lmd->title(lang),first);
2057           first=FALSE;
2058         }
2059       }
2060     }
2061   }
2062   else // VDHL only
2063   {
2064     for (const auto &s : m_impl->vhdlSummaryTitles)
2065     {
2066       ol.writeSummaryLink(QCString(),convertToId(QCString(s)),QCString(s),first);
2067       first=FALSE;
2068     }
2069   }
2070   if (!first)
2071   {
2072     ol.writeString("  </div>\n");
2073   }
2074   ol.popGeneratorState();
2075 }
2076 
writeTagFile(TextStream & tagFile)2077 void ClassDefImpl::writeTagFile(TextStream &tagFile)
2078 {
2079   if (!isLinkableInProject() || isArtificial()) return;
2080   tagFile << "  <compound kind=\"";
2081   if (isFortran() && (compoundTypeString() == "type"))
2082     tagFile << "struct";
2083   else
2084     tagFile << compoundTypeString();
2085   tagFile << "\"";
2086   if (isObjectiveC()) { tagFile << " objc=\"yes\""; }
2087   tagFile << ">\n";
2088   tagFile << "    <name>" << convertToXML(name()) << "</name>\n";
2089   tagFile << "    <filename>" << convertToXML(addHtmlExtensionIfMissing(getOutputFileBase())) << "</filename>\n";
2090   if (!anchor().isEmpty())
2091   {
2092     tagFile << "    <anchor>" << convertToXML(anchor()) << "</anchor>\n";
2093   }
2094   QCString idStr = id();
2095   if (!idStr.isEmpty())
2096   {
2097     tagFile << "    <clangid>" << convertToXML(idStr) << "</clangid>\n";
2098   }
2099   for (const Argument &a : m_impl->tempArgs)
2100   {
2101     tagFile << "    <templarg>" << convertToXML(a.type);
2102     if (!a.name.isEmpty())
2103     {
2104       tagFile << " " << convertToXML(a.name);
2105     }
2106     tagFile << "</templarg>\n";
2107   }
2108   for (const auto &ibcd : m_impl->inherits)
2109   {
2110     ClassDef *cd=ibcd.classDef;
2111     if (cd && cd->isLinkable())
2112     {
2113       if (!Config_getString(GENERATE_TAGFILE).isEmpty())
2114       {
2115         tagFile << "    <base";
2116         if (ibcd.prot==Protected)
2117         {
2118           tagFile << " protection=\"protected\"";
2119         }
2120         else if (ibcd.prot==Private)
2121         {
2122           tagFile << " protection=\"private\"";
2123         }
2124         if (ibcd.virt==Virtual)
2125         {
2126           tagFile << " virtualness=\"virtual\"";
2127         }
2128         tagFile << ">" << convertToXML(cd->name()) << "</base>\n";
2129       }
2130     }
2131   }
2132   for (const auto &lde : LayoutDocManager::instance().docEntries(LayoutDocManager::Class))
2133   {
2134     switch (lde->kind())
2135     {
2136       case LayoutDocEntry::ClassNestedClasses:
2137         {
2138           for (const auto &innerCd : m_impl->innerClasses)
2139           {
2140             if (innerCd->isLinkableInProject() && innerCd->templateMaster()==0 &&
2141                 protectionLevelVisible(innerCd->protection()) &&
2142                 !innerCd->isEmbeddedInOuterScope()
2143                )
2144             {
2145               tagFile << "    <class kind=\"" << innerCd->compoundTypeString() <<
2146                 "\">" << convertToXML(innerCd->name()) << "</class>\n";
2147             }
2148           }
2149         }
2150         break;
2151       case LayoutDocEntry::MemberDecl:
2152         {
2153           const LayoutDocEntryMemberDecl *lmd = (const LayoutDocEntryMemberDecl*)lde.get();
2154           MemberList * ml = getMemberList(lmd->type);
2155           if (ml)
2156           {
2157             ml->writeTagFile(tagFile);
2158           }
2159         }
2160         break;
2161       case LayoutDocEntry::MemberGroups:
2162         {
2163           for (const auto &mg : m_impl->memberGroups)
2164           {
2165             mg->writeTagFile(tagFile);
2166           }
2167         }
2168         break;
2169      default:
2170         break;
2171     }
2172   }
2173   writeDocAnchorsToTagFile(tagFile);
2174   tagFile << "  </compound>\n";
2175 }
2176 
2177 /** Write class documentation inside another container (i.e. a group) */
writeInlineDocumentation(OutputList & ol) const2178 void ClassDefImpl::writeInlineDocumentation(OutputList &ol) const
2179 {
2180   bool isSimple = m_impl->isSimple;
2181 
2182   ol.addIndexItem(name(),QCString());
2183   //printf("ClassDefImpl::writeInlineDocumentation(%s)\n",qPrint(name()));
2184 
2185   // part 1: anchor and title
2186   QCString s = compoundTypeString()+" "+name();
2187 
2188   // part 1a
2189   ol.pushGeneratorState();
2190   ol.disableAllBut(OutputGenerator::Html);
2191   { // only HTML only
2192     ol.writeAnchor(QCString(),anchor());
2193     ol.startMemberDoc(QCString(),QCString(),anchor(),name(),1,1,FALSE);
2194     ol.startMemberDocName(FALSE);
2195     ol.parseText(s);
2196     ol.endMemberDocName();
2197     ol.endMemberDoc(FALSE);
2198     ol.writeString("</div>");
2199     ol.startIndent();
2200   }
2201   ol.popGeneratorState();
2202 
2203   // part 1b
2204   ol.pushGeneratorState();
2205   ol.disable(OutputGenerator::Html);
2206   ol.disable(OutputGenerator::Man);
2207   { // for LaTeX/RTF only
2208     ol.writeAnchor(getOutputFileBase(),anchor());
2209   }
2210   ol.popGeneratorState();
2211 
2212   // part 1c
2213   ol.pushGeneratorState();
2214   ol.disable(OutputGenerator::Html);
2215   {
2216     // for LaTeX/RTF/Man
2217     ol.startGroupHeader(1);
2218     ol.parseText(s);
2219     ol.endGroupHeader(1);
2220   }
2221   ol.popGeneratorState();
2222 
2223   SrcLangExt lang=getLanguage();
2224 
2225   // part 2: the header and detailed description
2226   for (const auto &lde : LayoutDocManager::instance().docEntries(LayoutDocManager::Class))
2227   {
2228     switch (lde->kind())
2229     {
2230       case LayoutDocEntry::BriefDesc:
2231         {
2232           // since we already shown the brief description in the
2233           // declaration part of the container, so we use this to
2234           // show the details on top.
2235           writeDetailedDocumentationBody(ol);
2236         }
2237         break;
2238       case LayoutDocEntry::ClassInheritanceGraph:
2239         writeInheritanceGraph(ol);
2240         break;
2241       case LayoutDocEntry::ClassCollaborationGraph:
2242         writeCollaborationGraph(ol);
2243         break;
2244       case LayoutDocEntry::MemberDeclStart:
2245         if (!isSimple) startMemberDeclarations(ol);
2246         break;
2247       case LayoutDocEntry::MemberDecl:
2248         {
2249           ClassDefSet visitedClasses;
2250           const LayoutDocEntryMemberDecl *lmd = (const LayoutDocEntryMemberDecl*)lde.get();
2251           if (!isSimple) writeMemberDeclarations(ol,visitedClasses,lmd->type,lmd->title(lang),lmd->subtitle(lang),TRUE);
2252         }
2253         break;
2254       case LayoutDocEntry::MemberGroups:
2255         if (!isSimple) writeMemberGroups(ol,TRUE);
2256         break;
2257       case LayoutDocEntry::MemberDeclEnd:
2258         if (!isSimple) endMemberDeclarations(ol);
2259         break;
2260       case LayoutDocEntry::MemberDefStart:
2261         if (!isSimple) startMemberDocumentation(ol);
2262         break;
2263       case LayoutDocEntry::MemberDef:
2264         {
2265           const LayoutDocEntryMemberDef *lmd = (const LayoutDocEntryMemberDef*)lde.get();
2266           if (isSimple)
2267           {
2268             writeSimpleMemberDocumentation(ol,lmd->type);
2269           }
2270           else
2271           {
2272             writeMemberDocumentation(ol,lmd->type,lmd->title(lang),TRUE);
2273           }
2274         }
2275         break;
2276       case LayoutDocEntry::MemberDefEnd:
2277         if (!isSimple) endMemberDocumentation(ol);
2278         break;
2279       default:
2280         break;
2281     }
2282   }
2283 
2284   // part 3: close the block
2285   ol.pushGeneratorState();
2286   ol.disableAllBut(OutputGenerator::Html);
2287   { // HTML only
2288     ol.endIndent();
2289   }
2290   ol.popGeneratorState();
2291 }
2292 
writeMoreLink(OutputList & ol,const QCString & anchor) const2293 void ClassDefImpl::writeMoreLink(OutputList &ol,const QCString &anchor) const
2294 {
2295   // TODO: clean up this mess by moving it to
2296   // the output generators...
2297   static bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS);
2298   static bool rtfHyperlinks = Config_getBool(RTF_HYPERLINKS);
2299   static bool usePDFLatex   = Config_getBool(USE_PDFLATEX);
2300 
2301   // HTML only
2302   ol.pushGeneratorState();
2303   ol.disableAllBut(OutputGenerator::Html);
2304   ol.docify(" ");
2305   ol.startTextLink(getOutputFileBase(),
2306       anchor.isEmpty() ? QCString("details") : anchor);
2307   ol.parseText(theTranslator->trMore());
2308   ol.endTextLink();
2309   ol.popGeneratorState();
2310 
2311   if (!anchor.isEmpty())
2312   {
2313     ol.pushGeneratorState();
2314     // LaTeX + RTF
2315     ol.disable(OutputGenerator::Html);
2316     ol.disable(OutputGenerator::Man);
2317     ol.disable(OutputGenerator::Docbook);
2318     if (!(usePDFLatex && pdfHyperlinks))
2319     {
2320       ol.disable(OutputGenerator::Latex);
2321     }
2322     if (!rtfHyperlinks)
2323     {
2324       ol.disable(OutputGenerator::RTF);
2325     }
2326     ol.docify(" ");
2327     ol.startTextLink(getOutputFileBase(), anchor);
2328     ol.parseText(theTranslator->trMore());
2329     ol.endTextLink();
2330     // RTF only
2331     ol.disable(OutputGenerator::Latex);
2332     ol.writeString("\\par");
2333     ol.popGeneratorState();
2334   }
2335 }
2336 
visibleInParentsDeclList() const2337 bool ClassDefImpl::visibleInParentsDeclList() const
2338 {
2339   static bool extractPrivate      = Config_getBool(EXTRACT_PRIVATE);
2340   static bool hideUndocClasses = Config_getBool(HIDE_UNDOC_CLASSES);
2341   static bool extractLocalClasses = Config_getBool(EXTRACT_LOCAL_CLASSES);
2342   bool linkable = isLinkable();
2343   return (!isAnonymous() && !isExtension() &&
2344           (protection()!=::Private || extractPrivate) &&
2345           (linkable || (!hideUndocClasses && (!isLocal() || extractLocalClasses)))
2346          );
2347 }
2348 
writeDeclarationLink(OutputList & ol,bool & found,const QCString & header,bool localNames) const2349 void ClassDefImpl::writeDeclarationLink(OutputList &ol,bool &found,const QCString &header,bool localNames) const
2350 {
2351   //static bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN);
2352   //static bool vhdlOpt    = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
2353   static bool sliceOpt   = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
2354   SrcLangExt lang = getLanguage();
2355   if (visibleInParentsDeclList())
2356   {
2357     if (!found) // first class
2358     {
2359       if (sliceOpt)
2360       {
2361         if (compoundType()==Interface)
2362         {
2363           ol.startMemberHeader("interfaces");
2364         }
2365         else if (compoundType()==Struct)
2366         {
2367           ol.startMemberHeader("structs");
2368         }
2369         else if (compoundType()==Exception)
2370         {
2371           ol.startMemberHeader("exceptions");
2372         }
2373         else // compoundType==Class
2374         {
2375           ol.startMemberHeader("nested-classes");
2376         }
2377       }
2378       else // non-Slice optimization: single header for class/struct/..
2379       {
2380         ol.startMemberHeader("nested-classes");
2381       }
2382       if (!header.isEmpty())
2383       {
2384         ol.parseText(header);
2385       }
2386       else if (lang==SrcLangExt_VHDL)
2387       {
2388         ol.parseText(theTranslator->trVhdlType(VhdlDocGen::ARCHITECTURE,FALSE));
2389       }
2390       else
2391       {
2392         ol.parseText(lang==SrcLangExt_Fortran ?
2393             theTranslator->trDataTypes() :
2394             theTranslator->trCompounds());
2395       }
2396       ol.endMemberHeader();
2397       ol.startMemberList();
2398       found=TRUE;
2399     }
2400     ol.startMemberDeclaration();
2401     ol.startMemberItem(anchor(),FALSE);
2402     QCString ctype = compoundTypeString();
2403     QCString cname = displayName(!localNames);
2404 
2405     if (lang!=SrcLangExt_VHDL) // for VHDL we swap the name and the type
2406     {
2407       if (isSliceLocal())
2408       {
2409         ol.writeString("local ");
2410       }
2411       ol.writeString(ctype);
2412       ol.writeString(" ");
2413       ol.insertMemberAlign();
2414     }
2415     if (isLinkable())
2416     {
2417       ol.writeObjectLink(getReference(),
2418           getOutputFileBase(),
2419           anchor(),
2420           cname
2421           );
2422     }
2423     else
2424     {
2425       ol.startBold();
2426       ol.docify(cname);
2427       ol.endBold();
2428     }
2429     if (lang==SrcLangExt_VHDL) // now write the type
2430     {
2431       ol.writeString(" ");
2432       ol.insertMemberAlign();
2433       ol.writeString(VhdlDocGen::getProtectionName((VhdlDocGen::VhdlClasses)protection()));
2434     }
2435     ol.endMemberItem();
2436 
2437     // add the brief description if available
2438     if (!briefDescription().isEmpty() && Config_getBool(BRIEF_MEMBER_DESC))
2439     {
2440       std::unique_ptr<IDocParser> parser { createDocParser() };
2441       std::unique_ptr<DocRoot> rootNode { validatingParseDoc(*parser.get(),
2442                                 briefFile(),briefLine(),this,0,
2443                                 briefDescription(),FALSE,FALSE,
2444                                 QCString(),TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)) };
2445       if (rootNode && !rootNode->isEmpty())
2446       {
2447         ol.startMemberDescription(anchor());
2448         ol.writeDoc(rootNode.get(),this,0);
2449         if (isLinkableInProject())
2450         {
2451           writeMoreLink(ol,anchor());
2452         }
2453         ol.endMemberDescription();
2454       }
2455     }
2456     ol.endMemberDeclaration(anchor(),QCString());
2457   }
2458 }
2459 
addClassAttributes(OutputList & ol) const2460 void ClassDefImpl::addClassAttributes(OutputList &ol) const
2461 {
2462   StringVector sl;
2463   if (isFinal())    sl.push_back("final");
2464   if (isSealed())   sl.push_back("sealed");
2465   if (isAbstract()) sl.push_back("abstract");
2466   if (getLanguage()==SrcLangExt_IDL && isPublished()) sl.push_back("published");
2467 
2468   ol.pushGeneratorState();
2469   ol.disableAllBut(OutputGenerator::Html);
2470   if (!sl.empty())
2471   {
2472     ol.startLabels();
2473     size_t i=0;
2474     for (const auto &s : sl)
2475     {
2476       i++;
2477       ol.writeLabel(s.c_str(),i==sl.size());
2478     }
2479     ol.endLabels();
2480   }
2481   ol.popGeneratorState();
2482 }
2483 
writeDocumentationContents(OutputList & ol,const QCString &) const2484 void ClassDefImpl::writeDocumentationContents(OutputList &ol,const QCString & /*pageTitle*/) const
2485 {
2486   ol.startContents();
2487 
2488   QCString pageType = " ";
2489   pageType += compoundTypeString();
2490 
2491   bool exampleFlag=hasExamples();
2492 
2493   //---------------------------------------- start flexible part -------------------------------
2494 
2495   SrcLangExt lang = getLanguage();
2496 
2497   for (const auto &lde : LayoutDocManager::instance().docEntries(LayoutDocManager::Class))
2498   {
2499     switch (lde->kind())
2500     {
2501       case LayoutDocEntry::BriefDesc:
2502         writeBriefDescription(ol,exampleFlag);
2503         break;
2504       case LayoutDocEntry::ClassIncludes:
2505         if (lang==SrcLangExt_Slice)
2506         {
2507           writeIncludeFilesForSlice(ol);
2508         }
2509         else
2510         {
2511           writeIncludeFiles(ol);
2512         }
2513         break;
2514       case LayoutDocEntry::ClassInheritanceGraph:
2515         writeInheritanceGraph(ol);
2516         break;
2517       case LayoutDocEntry::ClassCollaborationGraph:
2518         writeCollaborationGraph(ol);
2519         break;
2520       case LayoutDocEntry::ClassAllMembersLink:
2521         //writeAllMembersLink(ol); // this is now part of the summary links
2522         break;
2523       case LayoutDocEntry::MemberDeclStart:
2524         startMemberDeclarations(ol);
2525         break;
2526       case LayoutDocEntry::MemberGroups:
2527         writeMemberGroups(ol);
2528         break;
2529       case LayoutDocEntry::MemberDecl:
2530         {
2531           ClassDefSet visitedClasses;
2532           const LayoutDocEntryMemberDecl *lmd = (const LayoutDocEntryMemberDecl*)lde.get();
2533           writeMemberDeclarations(ol,visitedClasses,lmd->type,lmd->title(lang),lmd->subtitle(lang));
2534         }
2535         break;
2536       case LayoutDocEntry::ClassNestedClasses:
2537         {
2538           const LayoutDocEntrySection *ls = (const LayoutDocEntrySection*)lde.get();
2539           writeNestedClasses(ol,ls->title(lang));
2540         }
2541         break;
2542       case LayoutDocEntry::MemberDeclEnd:
2543         endMemberDeclarations(ol);
2544         break;
2545       case LayoutDocEntry::DetailedDesc:
2546         {
2547           const LayoutDocEntrySection *ls = (const LayoutDocEntrySection*)lde.get();
2548           writeDetailedDescription(ol,pageType,exampleFlag,ls->title(lang));
2549         }
2550         break;
2551       case LayoutDocEntry::MemberDefStart:
2552         startMemberDocumentation(ol);
2553         break;
2554       case LayoutDocEntry::ClassInlineClasses:
2555         writeInlineClasses(ol);
2556         break;
2557       case LayoutDocEntry::MemberDef:
2558         {
2559           const LayoutDocEntryMemberDef *lmd = (const LayoutDocEntryMemberDef*)lde.get();
2560           writeMemberDocumentation(ol,lmd->type,lmd->title(lang));
2561         }
2562         break;
2563       case LayoutDocEntry::MemberDefEnd:
2564         endMemberDocumentation(ol);
2565         break;
2566       case LayoutDocEntry::ClassUsedFiles:
2567         showUsedFiles(ol);
2568         break;
2569       case LayoutDocEntry::AuthorSection:
2570         writeAuthorSection(ol);
2571         break;
2572       case LayoutDocEntry::NamespaceNestedNamespaces:
2573       case LayoutDocEntry::NamespaceNestedConstantGroups:
2574       case LayoutDocEntry::NamespaceClasses:
2575       case LayoutDocEntry::NamespaceConcepts:
2576       case LayoutDocEntry::NamespaceInterfaces:
2577       case LayoutDocEntry::NamespaceStructs:
2578       case LayoutDocEntry::NamespaceExceptions:
2579       case LayoutDocEntry::NamespaceInlineClasses:
2580       case LayoutDocEntry::ConceptDefinition:
2581       case LayoutDocEntry::FileClasses:
2582       case LayoutDocEntry::FileConcepts:
2583       case LayoutDocEntry::FileInterfaces:
2584       case LayoutDocEntry::FileStructs:
2585       case LayoutDocEntry::FileExceptions:
2586       case LayoutDocEntry::FileNamespaces:
2587       case LayoutDocEntry::FileConstantGroups:
2588       case LayoutDocEntry::FileIncludes:
2589       case LayoutDocEntry::FileIncludeGraph:
2590       case LayoutDocEntry::FileIncludedByGraph:
2591       case LayoutDocEntry::FileSourceLink:
2592       case LayoutDocEntry::FileInlineClasses:
2593       case LayoutDocEntry::GroupClasses:
2594       case LayoutDocEntry::GroupConcepts:
2595       case LayoutDocEntry::GroupInlineClasses:
2596       case LayoutDocEntry::GroupNamespaces:
2597       case LayoutDocEntry::GroupDirs:
2598       case LayoutDocEntry::GroupNestedGroups:
2599       case LayoutDocEntry::GroupFiles:
2600       case LayoutDocEntry::GroupGraph:
2601       case LayoutDocEntry::GroupPageDocs:
2602       case LayoutDocEntry::DirSubDirs:
2603       case LayoutDocEntry::DirFiles:
2604       case LayoutDocEntry::DirGraph:
2605         err("Internal inconsistency: member %d should not be part of "
2606             "LayoutDocManager::Class entry list\n",lde->kind());
2607         break;
2608     }
2609   }
2610 
2611   ol.endContents();
2612 }
2613 
title() const2614 QCString ClassDefImpl::title() const
2615 {
2616   QCString pageTitle;
2617   SrcLangExt lang = getLanguage();
2618 
2619   if (lang==SrcLangExt_Fortran)
2620   {
2621     pageTitle = theTranslator->trCompoundReferenceFortran(displayName(),
2622               m_impl->compType,
2623               !m_impl->tempArgs.empty());
2624   }
2625   else if (lang==SrcLangExt_Slice)
2626   {
2627     pageTitle = theTranslator->trCompoundReferenceSlice(displayName(),
2628               m_impl->compType,
2629               isSliceLocal());
2630   }
2631   else if (lang==SrcLangExt_VHDL)
2632   {
2633     pageTitle = theTranslator->trCustomReference(VhdlDocGen::getClassTitle(this));
2634   }
2635   else if (isJavaEnum())
2636   {
2637     pageTitle = theTranslator->trEnumReference(displayName());
2638   }
2639   else if (m_impl->compType==Service)
2640   {
2641     pageTitle = theTranslator->trServiceReference(displayName());
2642   }
2643   else if (m_impl->compType==Singleton)
2644   {
2645     pageTitle = theTranslator->trSingletonReference(displayName());
2646   }
2647   else
2648   {
2649     if (Config_getBool(HIDE_COMPOUND_REFERENCE))
2650     {
2651       pageTitle = displayName();
2652     }
2653     else
2654     {
2655       pageTitle = theTranslator->trCompoundReference(displayName(),
2656                 m_impl->compType == Interface && getLanguage()==SrcLangExt_ObjC ? Class : m_impl->compType,
2657                 !m_impl->tempArgs.empty());
2658     }
2659   }
2660   return pageTitle;
2661 }
2662 
2663 // write all documentation for this class
writeDocumentation(OutputList & ol) const2664 void ClassDefImpl::writeDocumentation(OutputList &ol) const
2665 {
2666   static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW);
2667   //static bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN);
2668   //static bool vhdlOpt    = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
2669   static bool sliceOpt   = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
2670   QCString pageTitle = title();
2671 
2672   HighlightedItem hli;
2673   if (sliceOpt)
2674   {
2675     if (compoundType()==Interface)
2676     {
2677       hli = HLI_InterfaceVisible;
2678     }
2679     else if (compoundType()==Struct)
2680     {
2681       hli = HLI_StructVisible;
2682     }
2683     else if (compoundType()==Exception)
2684     {
2685       hli = HLI_ExceptionVisible;
2686     }
2687     else
2688     {
2689       hli = HLI_ClassVisible;
2690     }
2691   }
2692   else
2693   {
2694     hli = HLI_ClassVisible;
2695   }
2696 
2697   startFile(ol,getOutputFileBase(),name(),pageTitle,hli,!generateTreeView);
2698   if (!generateTreeView)
2699   {
2700     if (getOuterScope()!=Doxygen::globalScope)
2701     {
2702       writeNavigationPath(ol);
2703     }
2704     ol.endQuickIndices();
2705   }
2706 
2707   startTitle(ol,getOutputFileBase(),this);
2708   ol.parseText(pageTitle);
2709   addClassAttributes(ol);
2710   addGroupListToTitle(ol,this);
2711   endTitle(ol,getOutputFileBase(),displayName());
2712   writeDocumentationContents(ol,pageTitle);
2713 
2714   endFileWithNavPath(this,ol);
2715 
2716   if (Config_getBool(SEPARATE_MEMBER_PAGES))
2717   {
2718     writeMemberPages(ol);
2719   }
2720 }
2721 
writeMemberPages(OutputList & ol) const2722 void ClassDefImpl::writeMemberPages(OutputList &ol) const
2723 {
2724   ///////////////////////////////////////////////////////////////////////////
2725   //// Member definitions on separate pages
2726   ///////////////////////////////////////////////////////////////////////////
2727 
2728   ol.pushGeneratorState();
2729   ol.disableAllBut(OutputGenerator::Html);
2730 
2731   for (const auto &ml : m_impl->memberLists)
2732   {
2733     if (ml->numDocMembers()>ml->numDocEnumValues() && (ml->listType()&MemberListType_detailedLists))
2734     {
2735       ml->writeDocumentationPage(ol,displayName(),this);
2736     }
2737   }
2738 
2739   ol.popGeneratorState();
2740 }
2741 
writeQuickMemberLinks(OutputList & ol,const MemberDef * currentMd) const2742 void ClassDefImpl::writeQuickMemberLinks(OutputList &ol,const MemberDef *currentMd) const
2743 {
2744   static bool createSubDirs=Config_getBool(CREATE_SUBDIRS);
2745 
2746   ol.writeString("      <div class=\"navtab\">\n");
2747   ol.writeString("        <table>\n");
2748 
2749   for (auto &mni : m_impl->allMemberNameInfoLinkedMap)
2750   {
2751     for (auto &mi : *mni)
2752     {
2753       const MemberDef *md=mi->memberDef();
2754       if (md->getClassDef()==this && md->isLinkable() && !md->isEnumValue())
2755       {
2756         if (md->isLinkableInProject())
2757         {
2758           if (md==currentMd) // selected item => highlight
2759           {
2760             ol.writeString("          <tr><td class=\"navtabHL\">");
2761           }
2762           else
2763           {
2764             ol.writeString("          <tr><td class=\"navtab\">");
2765           }
2766           ol.writeString("<a class=\"navtab\" ");
2767           ol.writeString("href=\"");
2768           if (createSubDirs) ol.writeString("../../");
2769           ol.writeString(addHtmlExtensionIfMissing(md->getOutputFileBase())+"#"+md->anchor());
2770           ol.writeString("\">");
2771           ol.writeString(convertToHtml(md->name()));
2772           ol.writeString("</a>");
2773           ol.writeString("</td></tr>\n");
2774         }
2775       }
2776     }
2777   }
2778 
2779   ol.writeString("        </table>\n");
2780   ol.writeString("      </div>\n");
2781 }
2782 
2783 
2784 
writeDocumentationForInnerClasses(OutputList & ol) const2785 void ClassDefImpl::writeDocumentationForInnerClasses(OutputList &ol) const
2786 {
2787   // write inner classes after the parent, so the tag files contain
2788   // the definition in proper order!
2789   for (const auto &innerCd : m_impl->innerClasses)
2790   {
2791     ClassDefMutable *innerCdm = toClassDefMutable(innerCd);
2792     if (innerCdm)
2793     {
2794       if (
2795           innerCd->isLinkableInProject() && innerCd->templateMaster()==0 &&
2796           protectionLevelVisible(innerCd->protection()) &&
2797           !innerCd->isEmbeddedInOuterScope()
2798          )
2799       {
2800         msg("Generating docs for nested compound %s...\n",qPrint(innerCd->name()));
2801         innerCdm->writeDocumentation(ol);
2802         innerCdm->writeMemberList(ol);
2803       }
2804       innerCdm->writeDocumentationForInnerClasses(ol);
2805     }
2806   }
2807 }
2808 
2809 // write the list of all (inherited) members for this class
writeMemberList(OutputList & ol) const2810 void ClassDefImpl::writeMemberList(OutputList &ol) const
2811 {
2812   static bool cOpt    = Config_getBool(OPTIMIZE_OUTPUT_FOR_C);
2813   //static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
2814   static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
2815   static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW);
2816   if (m_impl->allMemberNameInfoLinkedMap.empty() || cOpt) return;
2817   // only for HTML
2818   ol.pushGeneratorState();
2819   ol.disableAllBut(OutputGenerator::Html);
2820 
2821   HighlightedItem hli;
2822   if (sliceOpt)
2823   {
2824     if (compoundType()==Interface)
2825     {
2826       hli = HLI_InterfaceVisible;
2827     }
2828     else if (compoundType()==Struct)
2829     {
2830       hli = HLI_StructVisible;
2831     }
2832     else if (compoundType()==Exception)
2833     {
2834       hli = HLI_ExceptionVisible;
2835     }
2836     else
2837     {
2838       hli = HLI_ClassVisible;
2839     }
2840   }
2841   else
2842   {
2843     hli = HLI_ClassVisible;
2844   }
2845 
2846   QCString memListFile = getMemberListFileName();
2847   startFile(ol,memListFile,memListFile,theTranslator->trMemberList(),hli,!generateTreeView,getOutputFileBase());
2848   if (!generateTreeView)
2849   {
2850     if (getOuterScope()!=Doxygen::globalScope)
2851     {
2852       writeNavigationPath(ol);
2853     }
2854     ol.endQuickIndices();
2855   }
2856   startTitle(ol,QCString());
2857   ol.parseText(displayName()+" "+theTranslator->trMemberList());
2858   endTitle(ol,QCString(),QCString());
2859   ol.startContents();
2860   ol.startParagraph();
2861   ol.parseText(theTranslator->trThisIsTheListOfAllMembers());
2862   ol.writeObjectLink(getReference(),getOutputFileBase(),anchor(),displayName());
2863   ol.parseText(theTranslator->trIncludingInheritedMembers());
2864   ol.endParagraph();
2865 
2866   //ol.startItemList();
2867 
2868   bool first = true; // to prevent empty table
2869   int idx=0;
2870   for (auto &mni : m_impl->allMemberNameInfoLinkedMap)
2871   {
2872     for (auto &mi : *mni)
2873     {
2874       const MemberDef *md=mi->memberDef();
2875       const ClassDef  *cd=md->getClassDef();
2876       Protection prot = mi->prot();
2877       Specifier virt=md->virtualness();
2878 
2879       //printf("%s: Member %s of class %s md->protection()=%d mi->prot=%d prot=%d inherited=%d\n",
2880       //    qPrint(name()),qPrint(md->name()),qPrint(cd->name()),md->protection(),mi->prot,prot,mi->inherited);
2881 
2882       if (cd && !md->name().isEmpty() && !md->isAnonymous())
2883       {
2884         bool memberWritten=FALSE;
2885         if (cd->isLinkable() && md->isLinkable())
2886           // create a link to the documentation
2887         {
2888           QCString name=mi->ambiguityResolutionScope()+md->name();
2889           //ol.writeListItem();
2890           if (first)
2891           {
2892             ol.writeString("<table class=\"directory\">\n");
2893             first = false;
2894           }
2895           ol.writeString("  <tr");
2896           if ((idx&1)==0) ol.writeString(" class=\"even\""); else ol.writeString(" class=\"odd\"");
2897           idx++;
2898           ol.writeString("><td class=\"entry\">");
2899           if (cd->isObjectiveC())
2900           {
2901             if (md->isObjCMethod())
2902             {
2903               if (md->isStatic())
2904                 ol.writeString("+&#160;</td><td>");
2905               else
2906                 ol.writeString("-&#160;</td><td>");
2907             }
2908             else
2909               ol.writeString("</td><td class=\"entry\">");
2910           }
2911           if (md->isObjCMethod())
2912           {
2913             ol.writeObjectLink(md->getReference(),
2914                 md->getOutputFileBase(),
2915                 md->anchor(),md->name());
2916           }
2917           else
2918           {
2919             //Definition *bd = md->getGroupDef();
2920             //if (bd==0) bd=cd;
2921             ol.writeObjectLink(md->getReference(),
2922                 md->getOutputFileBase(),
2923                 md->anchor(),name);
2924 
2925             if ( md->isFunction() || md->isSignal() || md->isSlot() ||
2926                 (md->isFriend() && md->argsString().isEmpty()))
2927               ol.docify(md->argsString());
2928             else if (md->isEnumerate())
2929               ol.parseText(" "+theTranslator->trEnumName());
2930             else if (md->isEnumValue())
2931               ol.parseText(" "+theTranslator->trEnumValue());
2932             else if (md->isTypedef())
2933               ol.docify(" typedef");
2934             else if (md->isFriend() && md->typeString()=="friend class")
2935               ol.docify(" class");
2936             //ol.writeString("\n");
2937           }
2938           ol.writeString("</td>");
2939           memberWritten=TRUE;
2940         }
2941         else if (!cd->isArtificial() &&
2942                  !Config_getBool(HIDE_UNDOC_MEMBERS) &&
2943                   (protectionLevelVisible(md->protection()) || md->isFriend())
2944                 ) // no documentation,
2945                   // generate link to the class instead.
2946         {
2947           //ol.writeListItem();
2948           if (first)
2949           {
2950             ol.writeString("<table class=\"directory\">\n");
2951             first = false;
2952           }
2953           ol.writeString("  <tr bgcolor=\"#f0f0f0\"");
2954           if ((idx&1)==0) ol.writeString(" class=\"even\""); else ol.writeString(" class=\"odd\"");
2955           idx++;
2956           ol.writeString("><td class=\"entry\">");
2957           if (cd->isObjectiveC())
2958           {
2959             if (md->isObjCMethod())
2960             {
2961               if (md->isStatic())
2962                 ol.writeString("+&#160;</td><td class=\"entry\">");
2963               else
2964                 ol.writeString("-&#160;</td><td class=\"entry\">");
2965             }
2966             else
2967               ol.writeString("</td><td class=\"entry\">");
2968           }
2969           ol.startBold();
2970           ol.docify(md->name());
2971           ol.endBold();
2972           if (!md->isObjCMethod())
2973           {
2974             if ( md->isFunction() || md->isSignal() || md->isSlot() )
2975               ol.docify(md->argsString());
2976             else if (md->isEnumerate())
2977               ol.parseText(" "+theTranslator->trEnumName());
2978             else if (md->isEnumValue())
2979               ol.parseText(" "+theTranslator->trEnumValue());
2980             else if (md->isTypedef())
2981               ol.docify(" typedef");
2982           }
2983           ol.writeString(" (");
2984           ol.parseText(theTranslator->trDefinedIn()+" ");
2985           if (cd->isLinkable())
2986           {
2987             ol.writeObjectLink(
2988                 cd->getReference(),
2989                 cd->getOutputFileBase(),
2990                 cd->anchor(),
2991                 cd->displayName());
2992           }
2993           else
2994           {
2995             ol.startBold();
2996             ol.docify(cd->displayName());
2997             ol.endBold();
2998           }
2999           ol.writeString(")");
3000           ol.writeString("</td>");
3001           memberWritten=TRUE;
3002         }
3003         if (memberWritten)
3004         {
3005           ol.writeString("<td class=\"entry\">");
3006           ol.writeObjectLink(cd->getReference(),
3007                              cd->getOutputFileBase(),
3008                              cd->anchor(),
3009                              md->category() ?
3010                                 md->category()->displayName() :
3011                                 cd->displayName());
3012           ol.writeString("</td>");
3013           ol.writeString("<td class=\"entry\">");
3014         }
3015         SrcLangExt lang = md->getLanguage();
3016         if (
3017             (prot!=Public || (virt!=Normal && getLanguage()!=SrcLangExt_ObjC) ||
3018              md->isFriend() || md->isRelated() || md->isExplicit() ||
3019              md->isMutable() || (md->isInline() && Config_getBool(INLINE_INFO)) ||
3020              md->isSignal() || md->isSlot() ||
3021              (getLanguage()==SrcLangExt_IDL &&
3022               (md->isOptional() || md->isAttribute() || md->isUNOProperty())) ||
3023              md->isStatic() || lang==SrcLangExt_VHDL
3024             )
3025             && memberWritten)
3026         {
3027           StringVector sl;
3028           if (lang==SrcLangExt_VHDL)
3029           {
3030             sl.push_back(theTranslator->trVhdlType(md->getMemberSpecifiers(),TRUE).str()); //append vhdl type
3031           }
3032           else if (md->isFriend()) sl.push_back("friend");
3033           else if (md->isRelated()) sl.push_back("related");
3034           else
3035           {
3036             if (Config_getBool(INLINE_INFO) && md->isInline())
3037                                        sl.push_back("inline");
3038             if (md->isExplicit())      sl.push_back("explicit");
3039             if (md->isMutable())       sl.push_back("mutable");
3040             if (prot==Protected)       sl.push_back("protected");
3041             else if (prot==Private)    sl.push_back("private");
3042             else if (prot==Package)    sl.push_back("package");
3043             if (virt==Virtual && getLanguage()!=SrcLangExt_ObjC)
3044                                        sl.push_back("virtual");
3045             else if (virt==Pure)       sl.push_back("pure virtual");
3046             if (md->isStatic())        sl.push_back("static");
3047             if (md->isSignal())        sl.push_back("signal");
3048             if (md->isSlot())          sl.push_back("slot");
3049 // this is the extra member page
3050             if (md->isOptional())      sl.push_back("optional");
3051             if (md->isAttribute())     sl.push_back("attribute");
3052             if (md->isUNOProperty())   sl.push_back("property");
3053             if (md->isReadonly())      sl.push_back("readonly");
3054             if (md->isBound())         sl.push_back("bound");
3055             if (md->isRemovable())     sl.push_back("removable");
3056             if (md->isConstrained())   sl.push_back("constrained");
3057             if (md->isTransient())     sl.push_back("transient");
3058             if (md->isMaybeVoid())     sl.push_back("maybevoid");
3059             if (md->isMaybeDefault())  sl.push_back("maybedefault");
3060             if (md->isMaybeAmbiguous())sl.push_back("maybeambiguous");
3061           }
3062           bool firstSpan=true;
3063           for (const auto &s : sl)
3064           {
3065             if (!firstSpan)
3066             {
3067               ol.writeString("</span><span class=\"mlabel\">");
3068             }
3069             else
3070             {
3071               ol.writeString("<span class=\"mlabel\">");
3072               firstSpan=false;
3073             }
3074             ol.docify(s.c_str());
3075           }
3076           if (!firstSpan) ol.writeString("</span>");
3077         }
3078         if (memberWritten)
3079         {
3080           ol.writeString("</td>");
3081           ol.writeString("</tr>\n");
3082         }
3083       }
3084     }
3085   }
3086   //ol.endItemList();
3087 
3088   if (!first) ol.writeString("</table>");
3089 
3090   endFile(ol);
3091   ol.popGeneratorState();
3092 }
3093 
3094 // add a reference to an example
addExample(const QCString & anchor,const QCString & nameStr,const QCString & file)3095 bool ClassDefImpl::addExample(const QCString &anchor,const QCString &nameStr, const QCString &file)
3096 {
3097   return m_impl->examples.inSort(Example(anchor,nameStr,file));
3098 }
3099 
3100 // returns TRUE if this class is used in an example
hasExamples() const3101 bool ClassDefImpl::hasExamples() const
3102 {
3103   return !m_impl->examples.empty();
3104 }
3105 
addTypeConstraint(const QCString & typeConstraint,const QCString & type)3106 void ClassDefImpl::addTypeConstraint(const QCString &typeConstraint,const QCString &type)
3107 {
3108   //printf("addTypeConstraint(%s,%s)\n",qPrint(type),qPrint(typeConstraint));
3109   static bool hideUndocRelation = Config_getBool(HIDE_UNDOC_RELATIONS);
3110   if (typeConstraint.isEmpty() || type.isEmpty()) return;
3111   SymbolResolver resolver(getFileDef());
3112   ClassDefMutable *cd = resolver.resolveClassMutable(this,typeConstraint);
3113   if (cd==0 && !hideUndocRelation)
3114   {
3115     cd = toClassDefMutable(
3116            Doxygen::hiddenClassLinkedMap->add(typeConstraint,
3117              std::unique_ptr<ClassDef>(
3118                new ClassDefImpl(
3119                  getDefFileName(),getDefLine(),
3120                  getDefColumn(),
3121                  typeConstraint,
3122                  ClassDef::Class))));
3123     if (cd)
3124     {
3125       cd->setUsedOnly(TRUE);
3126       cd->setLanguage(getLanguage());
3127       //printf("Adding undocumented constraint '%s' to class %s on type %s\n",
3128       //       qPrint(typeConstraint),qPrint(name()),qPrint(type));
3129     }
3130   }
3131   if (cd)
3132   {
3133     auto it = std::find_if(m_impl->constraintClassList.begin(),
3134                            m_impl->constraintClassList.end(),
3135                            [&cd](const auto &ccd) { return ccd.classDef==cd; });
3136 
3137     if (it==m_impl->constraintClassList.end())
3138     {
3139       m_impl->constraintClassList.emplace_back(cd);
3140       it = m_impl->constraintClassList.end()-1;
3141     }
3142     (*it).addAccessor(type);
3143     //printf("Adding constraint '%s' to class %s on type %s\n",
3144     //       qPrint(typeConstraint),qPrint(name()),qPrint(type));
3145   }
3146 }
3147 
3148 // Java Type Constrains: A<T extends C & I>
addTypeConstraints()3149 void ClassDefImpl::addTypeConstraints()
3150 {
3151   for (const Argument &a : m_impl->tempArgs)
3152   {
3153     if (!a.typeConstraint.isEmpty())
3154     {
3155       QCString typeConstraint;
3156       int i=0,p=0;
3157       while ((i=a.typeConstraint.find('&',p))!=-1) // typeConstraint="A &I" for C<T extends A & I>
3158       {
3159         typeConstraint = a.typeConstraint.mid(p,i-p).stripWhiteSpace();
3160         addTypeConstraint(typeConstraint,a.type);
3161         p=i+1;
3162       }
3163       typeConstraint = a.typeConstraint.right(a.typeConstraint.length()-(uint)p).stripWhiteSpace();
3164       addTypeConstraint(typeConstraint,a.type);
3165     }
3166   }
3167 }
3168 
3169 // C# Type Constraints: D<T> where T : C, I
setTypeConstraints(const ArgumentList & al)3170 void ClassDefImpl::setTypeConstraints(const ArgumentList &al)
3171 {
3172   m_impl->typeConstraints = al;
3173 }
3174 
setTemplateArguments(const ArgumentList & al)3175 void ClassDefImpl::setTemplateArguments(const ArgumentList &al)
3176 {
3177   m_impl->tempArgs = al;
3178 }
3179 
3180 /*! Returns \c TRUE iff this class or a class inheriting from this class
3181  *  is \e not defined in an external tag file.
3182  */
hasNonReferenceSuperClass() const3183 bool ClassDefImpl::hasNonReferenceSuperClass() const
3184 {
3185   bool found=!isReference() && isLinkableInProject() && !isHidden();
3186   if (found)
3187   {
3188     return TRUE; // we're done if this class is not a reference
3189   }
3190   for (const auto &ibcd : m_impl->inheritedBy)
3191   {
3192     ClassDef *bcd=ibcd.classDef;
3193     // recurse into the super class branch
3194     found = found || bcd->hasNonReferenceSuperClass();
3195     if (!found)
3196     {
3197       // look for template instances that might have non-reference super classes
3198       for (const auto &cil : bcd->getTemplateInstances())
3199       {
3200         // recurse into the template instance branch
3201         found = cil.classDef->hasNonReferenceSuperClass();
3202         if (found) break;
3203       }
3204     }
3205     else
3206     {
3207       break;
3208     }
3209   }
3210   return found;
3211 }
3212 
requiresClause() const3213 QCString ClassDefImpl::requiresClause() const
3214 {
3215   return m_impl->requiresClause;
3216 }
3217 
setRequiresClause(const QCString & req)3218 void ClassDefImpl::setRequiresClause(const QCString &req)
3219 {
3220   m_impl->requiresClause = req;
3221 }
3222 
3223 /*! called from MemberDef::writeDeclaration() to (recursively) write the
3224  *  definition of an anonymous struct, union or class.
3225  */
writeDeclaration(OutputList & ol,const MemberDef * md,bool inGroup,int indentLevel,const ClassDef * inheritedFrom,const QCString & inheritId) const3226 void ClassDefImpl::writeDeclaration(OutputList &ol,const MemberDef *md,bool inGroup,int indentLevel,
3227     const ClassDef *inheritedFrom,const QCString &inheritId) const
3228 {
3229   //printf("ClassName='%s' inGroup=%d\n",qPrint(name()),inGroup);
3230 
3231   ol.docify(compoundTypeString());
3232   QCString cn = displayName(FALSE);
3233   if (!cn.isEmpty())
3234   {
3235     ol.docify(" ");
3236     if (md && isLinkable())
3237     {
3238       ol.writeObjectLink(QCString(),QCString(),md->anchor(),cn);
3239     }
3240     else
3241     {
3242       ol.startBold();
3243       ol.docify(cn);
3244       ol.endBold();
3245     }
3246   }
3247   ol.docify(" {");
3248   ol.endMemberItem();
3249 
3250   // write user defined member groups
3251   for (const auto &mg : m_impl->memberGroups)
3252   {
3253     mg->writePlainDeclarations(ol,inGroup,this,0,0,0,indentLevel,inheritedFrom,inheritId);
3254   }
3255 
3256   for (const auto &lde : LayoutDocManager::instance().docEntries(LayoutDocManager::Class))
3257   {
3258     if (lde->kind()==LayoutDocEntry::MemberDecl)
3259     {
3260       const LayoutDocEntryMemberDecl *lmd = (const LayoutDocEntryMemberDecl*)lde.get();
3261       writePlainMemberDeclaration(ol,lmd->type,inGroup,indentLevel,inheritedFrom,inheritId);
3262     }
3263   }
3264 }
3265 
3266 /*! a link to this class is possible within this project */
isLinkableInProject() const3267 bool ClassDefImpl::isLinkableInProject() const
3268 {
3269   static bool extractLocal   = Config_getBool(EXTRACT_LOCAL_CLASSES);
3270   static bool extractStatic  = Config_getBool(EXTRACT_STATIC);
3271   static bool hideUndoc      = Config_getBool(HIDE_UNDOC_CLASSES);
3272   if (m_impl->templateMaster)
3273   {
3274     return m_impl->templateMaster->isLinkableInProject();
3275   }
3276   else
3277   {
3278     return !name().isEmpty() &&                    /* has a name */
3279       !isArtificial() && !isHidden() &&            /* not hidden */
3280       !isAnonymous() &&                            /* not anonymous */
3281       protectionLevelVisible(m_impl->prot)      && /* private/internal */
3282       (!m_impl->isLocal      || extractLocal)   && /* local */
3283       (hasDocumentation()    || !hideUndoc)     && /* documented */
3284       (!m_impl->isStatic     || extractStatic)  && /* static */
3285       !isReference();                              /* not an external reference */
3286   }
3287 }
3288 
isLinkable() const3289 bool ClassDefImpl::isLinkable() const
3290 {
3291   if (m_impl->templateMaster)
3292   {
3293     return m_impl->templateMaster->isLinkable();
3294   }
3295   else
3296   {
3297     return isReference() || isLinkableInProject();
3298   }
3299 }
3300 
3301 
3302 /*! the class is visible in a class diagram, or class hierarchy */
isVisibleInHierarchy() const3303 bool ClassDefImpl::isVisibleInHierarchy() const
3304 {
3305   bool allExternals     = Config_getBool(ALLEXTERNALS);
3306   bool hideUndocClasses = Config_getBool(HIDE_UNDOC_CLASSES);
3307   bool extractStatic    = Config_getBool(EXTRACT_STATIC);
3308 
3309   return // show all classes or a subclass is visible
3310       ((allExternals && !isArtificial()) || hasNonReferenceSuperClass()) &&
3311       // and not an anonymous compound
3312       !isAnonymous() &&
3313       // and not privately inherited
3314       protectionLevelVisible(m_impl->prot) &&
3315       // documented or shown anyway or documentation is external
3316       (hasDocumentation() ||
3317        !hideUndocClasses ||
3318        (m_impl->templateMaster && m_impl->templateMaster->hasDocumentation()) ||
3319        isReference()
3320       ) &&
3321       // is not part of an unnamed namespace or shown anyway
3322       (!m_impl->isStatic || extractStatic);
3323 }
3324 
hasDocumentation() const3325 bool ClassDefImpl::hasDocumentation() const
3326 {
3327   return DefinitionMixin::hasDocumentation();
3328 }
3329 
3330 //----------------------------------------------------------------------
3331 // recursive function:
3332 // returns TRUE iff class definition 'bcd' represents an (in)direct base
3333 // class of class definition 'cd'.
3334 
isBaseClass(const ClassDef * bcd,bool followInstances,int level) const3335 bool ClassDefImpl::isBaseClass(const ClassDef *bcd, bool followInstances,int level) const
3336 {
3337   bool found=FALSE;
3338   //printf("isBaseClass(cd=%s) looking for %s\n",qPrint(name()),qPrint(bcd->name()));
3339   if (level>256)
3340   {
3341     err("Possible recursive class relation while inside %s and looking for base class %s\n",qPrint(name()),qPrint(bcd->name()));
3342     return FALSE;
3343   }
3344   for (const auto &bclass : baseClasses())
3345   {
3346     const ClassDef *ccd = bclass.classDef;
3347     if (!followInstances && ccd->templateMaster()) ccd=ccd->templateMaster();
3348     found = (ccd==bcd) || ccd->isBaseClass(bcd,followInstances,level+1);
3349     if (found) break;
3350   }
3351   return found;
3352 }
3353 
3354 //----------------------------------------------------------------------
3355 
isSubClass(ClassDef * cd,int level) const3356 bool ClassDefImpl::isSubClass(ClassDef *cd,int level) const
3357 {
3358   bool found=FALSE;
3359   if (level>256)
3360   {
3361     err("Possible recursive class relation while inside %s and looking for derived class %s\n",qPrint(name()),qPrint(cd->name()));
3362     return FALSE;
3363   }
3364   for (const auto &iscd : subClasses())
3365   {
3366     ClassDef *ccd=iscd.classDef;
3367     found = (ccd==cd) || ccd->isSubClass(cd,level+1);
3368     if (found) break;
3369   }
3370   return found;
3371 }
3372 
3373 //----------------------------------------------------------------------------
3374 
isStandardFunc(const MemberDef * md)3375 static bool isStandardFunc(const MemberDef *md)
3376 {
3377   return md->name()=="operator=" || // assignment operator
3378          md->isConstructor() ||     // constructor
3379          md->isDestructor();        // destructor
3380 }
3381 
3382 /*!
3383  * recursively merges the 'all members' lists of a class base
3384  * with that of this class. Must only be called for classes without
3385  * subclasses!
3386  */
mergeMembers()3387 void ClassDefImpl::mergeMembers()
3388 {
3389   if (m_impl->membersMerged) return;
3390 
3391   //static bool optimizeOutputForJava = Config_getBool(OPTIMIZE_OUTPUT_JAVA);
3392   //static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
3393   SrcLangExt lang = getLanguage();
3394   QCString sep=getLanguageSpecificSeparator(lang,TRUE);
3395   uint sepLen = sep.length();
3396 
3397   m_impl->membersMerged=TRUE;
3398   //printf("  mergeMembers for %s\n",qPrint(name()));
3399   static bool inlineInheritedMembers = Config_getBool(INLINE_INHERITED_MEMB);
3400   static bool extractPrivate         = Config_getBool(EXTRACT_PRIVATE);
3401   for (const auto &bcd : baseClasses())
3402   {
3403     ClassDefMutable *bClass=toClassDefMutable(bcd.classDef);
3404     if (bClass)
3405     {
3406       // merge the members in the base class of this inheritance branch first
3407       bClass->mergeMembers();
3408       if (bClass->getLanguage()==SrcLangExt_Python) continue; // python does not have member overloading, see issue 8480
3409 
3410       const MemberNameInfoLinkedMap &srcMnd  = bClass->memberNameInfoLinkedMap();
3411       MemberNameInfoLinkedMap &dstMnd        = m_impl->allMemberNameInfoLinkedMap;
3412 
3413       for (auto &srcMni : srcMnd)
3414       {
3415         //printf("    Base member name %s\n",srcMni->memberName());
3416         MemberNameInfo *dstMni;
3417         if ((dstMni=dstMnd.find(srcMni->memberName())))
3418           // a member with that name is already in the class.
3419           // the member may hide or reimplement the one in the sub class
3420           // or there may be another path to the base class that is already
3421           // visited via another branch in the class hierarchy.
3422         {
3423           for (auto &srcMi : *srcMni)
3424           {
3425             const MemberDef *srcMd = srcMi->memberDef();
3426             bool found=FALSE;
3427             bool ambiguous=FALSE;
3428             bool hidden=FALSE;
3429             const ClassDef *srcCd = srcMd->getClassDef();
3430             for (auto &dstMi : *dstMni)
3431             {
3432               const MemberDef *dstMd = dstMi->memberDef();
3433               if (srcMd!=dstMd) // different members
3434               {
3435                 const ClassDef *dstCd = dstMd->getClassDef();
3436                 //printf("  Is %s a base class of %s?\n",qPrint(srcCd->name()),qPrint(dstCd->name()));
3437                 if (srcCd==dstCd || dstCd->isBaseClass(srcCd,TRUE))
3438                   // member is in the same or a base class
3439                 {
3440                   ArgumentList &srcAl = const_cast<ArgumentList&>(srcMd->argumentList());
3441                   ArgumentList &dstAl = const_cast<ArgumentList&>(dstMd->argumentList());
3442                   found=matchArguments2(
3443                       srcMd->getOuterScope(),srcMd->getFileDef(),&srcAl,
3444                       dstMd->getOuterScope(),dstMd->getFileDef(),&dstAl,
3445                       TRUE
3446                       );
3447                   //printf("  Yes, matching (%s<->%s): %d\n",
3448                   //    qPrint(argListToString(srcMd->argumentList())),
3449                   //    qPrint(argListToString(dstMd->argumentList())),
3450                   //    found);
3451                   hidden = hidden  || !found;
3452                 }
3453                 else // member is in a non base class => multiple inheritance
3454                   // using the same base class.
3455                 {
3456                   //printf("$$ Existing member %s %s add scope %s\n",
3457                   //    qPrint(dstMi->ambiguityResolutionScope),
3458                   //    qPrint(dstMd->name()),
3459                   //    qPrint(dstMi->scopePath.left(dstMi->scopePath.find("::")+2));
3460 
3461                   QCString scope=dstMi->scopePath().left((uint)dstMi->scopePath().find(sep)+sepLen);
3462                   if (scope!=dstMi->ambiguityResolutionScope().left(scope.length()))
3463                   {
3464                     dstMi->setAmbiguityResolutionScope(scope+dstMi->ambiguityResolutionScope());
3465                   }
3466                   ambiguous=TRUE;
3467                 }
3468               }
3469               else // same members
3470               {
3471                 // do not add if base class is virtual or
3472                 // if scope paths are equal or
3473                 // if base class is an interface (and thus implicitly virtual).
3474                 //printf("same member found srcMi->virt=%d dstMi->virt=%d\n",srcMi->virt,dstMi->virt);
3475                 if ((srcMi->virt()!=Normal && dstMi->virt()!=Normal) ||
3476                     bClass->name()+sep+srcMi->scopePath() == dstMi->scopePath() ||
3477                     dstMd->getClassDef()->compoundType()==Interface
3478                    )
3479                 {
3480                   found=TRUE;
3481                 }
3482                 else // member can be reached via multiple paths in the
3483                   // inheritance tree
3484                 {
3485                   //printf("$$ Existing member %s %s add scope %s\n",
3486                   //    qPrint(dstMi->ambiguityResolutionScope),
3487                   //    qPrint(dstMd->name()),
3488                   //    qPrint(dstMi->scopePath.left(dstMi->scopePath.find("::")+2));
3489 
3490                   QCString scope=dstMi->scopePath().left((uint)dstMi->scopePath().find(sep)+sepLen);
3491                   if (scope!=dstMi->ambiguityResolutionScope().left(scope.length()))
3492                   {
3493                     dstMi->setAmbiguityResolutionScope(dstMi->ambiguityResolutionScope()+scope);
3494                   }
3495                   ambiguous=TRUE;
3496                 }
3497               }
3498               if (found) break;
3499             }
3500             //printf("member %s::%s hidden %d ambiguous %d srcMi->ambigClass=%p\n",
3501             //    qPrint(srcCd->name()),qPrint(srcMd->name()),hidden,ambiguous,srcMi->ambigClass);
3502 
3503             // TODO: fix the case where a member is hidden by inheritance
3504             //       of a member with the same name but with another prototype,
3505             //       while there is more than one path to the member in the
3506             //       base class due to multiple inheritance. In this case
3507             //       it seems that the member is not reachable by prefixing a
3508             //       scope name either (according to my compiler). Currently,
3509             //       this case is shown anyway.
3510             if (!found && srcMd->protection()!=Private && !srcMd->isFriend())
3511             {
3512               Protection prot=srcMd->protection();
3513               if (bcd.prot==Protected && prot==Public)  prot=bcd.prot;
3514               else if (bcd.prot==Private)               prot=bcd.prot;
3515 
3516               if (inlineInheritedMembers)
3517               {
3518                 if (!isStandardFunc(srcMd))
3519                 {
3520                   //printf("    insertMember '%s'\n",qPrint(srcMd->name()));
3521                   internalInsertMember(srcMd,prot,FALSE);
3522                 }
3523               }
3524 
3525               Specifier virt=srcMi->virt();
3526               if (virt==Normal && bcd.virt!=Normal) virt=bcd.virt;
3527 
3528               std::unique_ptr<MemberInfo> newMi = std::make_unique<MemberInfo>(srcMd,prot,virt,TRUE);
3529               newMi->setScopePath(bClass->name()+sep+srcMi->scopePath());
3530               if (ambiguous)
3531               {
3532                 //printf("$$ New member %s %s add scope %s::\n",
3533                 //     qPrint(srcMi->ambiguityResolutionScope),
3534                 //     qPrint(srcMd->name()),
3535                 //     qPrint(bClass->name()));
3536 
3537                 QCString scope=bClass->name()+sep;
3538                 if (scope!=srcMi->ambiguityResolutionScope().left(scope.length()))
3539                 {
3540                   newMi->setAmbiguityResolutionScope(scope+srcMi->ambiguityResolutionScope());
3541                 }
3542               }
3543               if (hidden)
3544               {
3545                 if (srcMi->ambigClass()==0)
3546                 {
3547                   newMi->setAmbigClass(bClass);
3548                   newMi->setAmbiguityResolutionScope(bClass->name()+sep);
3549                 }
3550                 else
3551                 {
3552                   newMi->setAmbigClass(srcMi->ambigClass());
3553                   newMi->setAmbiguityResolutionScope(srcMi->ambigClass()->name()+sep);
3554                 }
3555               }
3556               dstMni->push_back(std::move(newMi));
3557             }
3558           }
3559         }
3560         else // base class has a member that is not in the sub class => copy
3561         {
3562           // create a deep copy of the list (only the MemberInfo's will be
3563           // copied, not the actual MemberDef's)
3564           MemberNameInfo *newMni = dstMnd.add(srcMni->memberName());
3565 
3566           // copy the member(s) from the base to the sub class
3567           for (auto &mi : *srcMni)
3568           {
3569             if (!mi->memberDef()->isFriend()) // don't inherit friends
3570             {
3571               Protection prot = mi->prot();
3572               if (bcd.prot==Protected)
3573               {
3574                 if (prot==Public) prot=Protected;
3575               }
3576               else if (bcd.prot==Private)
3577               {
3578                 prot=Private;
3579               }
3580               //printf("%s::%s: prot=%d bcd.prot=%d result=%d\n",
3581               //    qPrint(name()),qPrint(mi->memberDef->name()),mi->prot,
3582               //    bcd.prot,prot);
3583 
3584               if (prot!=Private || extractPrivate)
3585               {
3586                 Specifier virt=mi->virt();
3587                 if (virt==Normal && bcd.virt!=Normal) virt=bcd.virt;
3588 
3589                 if (inlineInheritedMembers)
3590                 {
3591                   if (!isStandardFunc(mi->memberDef()))
3592                   {
3593                     //printf("    insertMember '%s'\n",qPrint(mi->memberDef->name()));
3594                     internalInsertMember(mi->memberDef(),prot,FALSE);
3595                   }
3596                 }
3597                 //printf("Adding!\n");
3598                 std::unique_ptr<MemberInfo> newMi = std::make_unique<MemberInfo>(mi->memberDef(),prot,virt,TRUE);
3599                 newMi->setScopePath(bClass->name()+sep+mi->scopePath());
3600                 newMi->setAmbigClass(mi->ambigClass());
3601                 newMi->setAmbiguityResolutionScope(mi->ambiguityResolutionScope());
3602                 newMni->push_back(std::move(newMi));
3603               }
3604             }
3605           }
3606         }
3607       }
3608     }
3609   }
3610   //printf("  end mergeMembers\n");
3611 }
3612 
3613 //----------------------------------------------------------------------------
3614 
3615 /*! Merges the members of a Objective-C category into this class.
3616  */
mergeCategory(ClassDef * cat)3617 void ClassDefImpl::mergeCategory(ClassDef *cat)
3618 {
3619   ClassDefMutable *category = toClassDefMutable(cat);
3620   if (category)
3621   {
3622     static bool extractLocalMethods = Config_getBool(EXTRACT_LOCAL_METHODS);
3623     bool makePrivate = category->isLocal();
3624     // in case extract local methods is not enabled we don't add the methods
3625     // of the category in case it is defined in the .m file.
3626     if (makePrivate && !extractLocalMethods) return;
3627     bool isExtension = category->isExtension();
3628 
3629     category->setCategoryOf(this);
3630     if (isExtension)
3631     {
3632       category->setArtificial(TRUE);
3633 
3634       // copy base classes/protocols from extension
3635       for (const auto &bcd : category->baseClasses())
3636       {
3637         insertBaseClass(bcd.classDef,bcd.usedName,bcd.prot,bcd.virt,bcd.templSpecifiers);
3638         // correct bcd.classDef so that they do no longer derive from
3639         // category, but from this class!
3640         BaseClassList scl = bcd.classDef->subClasses();
3641         for (auto &scd : scl)
3642         {
3643           if (scd.classDef==category)
3644           {
3645             scd.classDef=this;
3646           }
3647         }
3648         bcd.classDef->updateSubClasses(scl);
3649       }
3650     }
3651     // make methods private for categories defined in the .m file
3652     //printf("%s::mergeCategory makePrivate=%d\n",qPrint(name()),makePrivate);
3653 
3654     const MemberNameInfoLinkedMap &srcMnd  = category->memberNameInfoLinkedMap();
3655     MemberNameInfoLinkedMap &dstMnd        = m_impl->allMemberNameInfoLinkedMap;
3656 
3657     for (auto &srcMni : srcMnd)
3658     {
3659       MemberNameInfo *dstMni=dstMnd.find(srcMni->memberName());
3660       if (dstMni) // method is already defined in the class
3661       {
3662         //printf("Existing member %s\n",srcMni->memberName());
3663         auto &dstMi = dstMni->front();
3664         auto &srcMi = srcMni->front();
3665         if (srcMi && dstMi)
3666         {
3667           MemberDefMutable *smdm = toMemberDefMutable(srcMi->memberDef());
3668           MemberDefMutable *dmdm = toMemberDefMutable(dstMi->memberDef());
3669           if (smdm && dmdm)
3670           {
3671             combineDeclarationAndDefinition(smdm,dmdm);
3672             dmdm->setCategory(category);
3673             dmdm->setCategoryRelation(smdm);
3674             smdm->setCategoryRelation(dmdm);
3675           }
3676         }
3677       }
3678       else // new method name
3679       {
3680         //printf("New member %s\n",srcMni->memberName());
3681         // create a deep copy of the list
3682         MemberNameInfo *newMni = dstMnd.add(srcMni->memberName());
3683 
3684         // copy the member(s) from the category to this class
3685         for (auto &mi : *srcMni)
3686         {
3687           //printf("Adding '%s'\n",qPrint(mi->memberDef->name()));
3688           Protection prot = mi->prot();
3689           //if (makePrivate) prot = Private;
3690           std::unique_ptr<MemberDefMutable> newMd { toMemberDefMutable(mi->memberDef()->deepCopy()) };
3691           if (newMd)
3692           {
3693             //printf("Copying member %s\n",qPrint(mi->memberDef->name()));
3694             newMd->moveTo(this);
3695 
3696             std::unique_ptr<MemberInfo> newMi=std::make_unique<MemberInfo>(newMd.get(),prot,mi->virt(),mi->inherited());
3697             newMi->setScopePath(mi->scopePath());
3698             newMi->setAmbigClass(mi->ambigClass());
3699             newMi->setAmbiguityResolutionScope(mi->ambiguityResolutionScope());
3700             newMni->push_back(std::move(newMi));
3701 
3702             // also add the newly created member to the global members list
3703 
3704             QCString name = newMd->name();
3705             MemberName *mn = Doxygen::memberNameLinkedMap->add(name);
3706 
3707             if (newMd)
3708             {
3709               newMd->setCategory(category);
3710               newMd->setCategoryRelation(mi->memberDef());
3711             }
3712             MemberDefMutable *mdm = toMemberDefMutable(mi->memberDef());
3713             if (mdm)
3714             {
3715               mdm->setCategoryRelation(newMd.get());
3716             }
3717             if (newMd && (makePrivate || isExtension))
3718             {
3719               newMd->makeImplementationDetail();
3720             }
3721             internalInsertMember(newMd.get(),prot,FALSE);
3722             mn->push_back(std::move(newMd));
3723           }
3724         }
3725       }
3726     }
3727   }
3728 }
3729 
3730 //----------------------------------------------------------------------------
3731 
addUsedClass(ClassDef * cd,const QCString & accessName,Protection prot)3732 void ClassDefImpl::addUsedClass(ClassDef *cd,const QCString &accessName,
3733                Protection prot)
3734 {
3735   static bool extractPrivate = Config_getBool(EXTRACT_PRIVATE);
3736   static bool umlLook = Config_getBool(UML_LOOK);
3737   if (prot==Private && !extractPrivate) return;
3738   //printf("%s::addUsedClass(%s,%s)\n",qPrint(name()),qPrint(cd->name()),accessName);
3739 
3740   auto it = std::find_if(m_impl->usesImplClassList.begin(),
3741                          m_impl->usesImplClassList.end(),
3742                          [&cd](const auto &ucd) { return ucd.classDef==cd; });
3743   if (it==m_impl->usesImplClassList.end())
3744   {
3745     m_impl->usesImplClassList.emplace_back(cd);
3746     //printf("Adding used class %s to class %s via accessor %s\n",
3747     //    qPrint(cd->name()),qPrint(name()),accessName);
3748     it = m_impl->usesImplClassList.end()-1;
3749   }
3750   QCString acc = accessName;
3751   if (umlLook)
3752   {
3753     switch(prot)
3754     {
3755       case Public:    acc.prepend("+"); break;
3756       case Private:   acc.prepend("-"); break;
3757       case Protected: acc.prepend("#"); break;
3758       case Package:   acc.prepend("~"); break;
3759     }
3760   }
3761   (*it).addAccessor(acc);
3762 }
3763 
addUsedByClass(ClassDef * cd,const QCString & accessName,Protection prot)3764 void ClassDefImpl::addUsedByClass(ClassDef *cd,const QCString &accessName,
3765                Protection prot)
3766 {
3767   static bool extractPrivate = Config_getBool(EXTRACT_PRIVATE);
3768   static bool umlLook = Config_getBool(UML_LOOK);
3769   if (prot==Private && !extractPrivate) return;
3770   //printf("%s::addUsedByClass(%s,%s)\n",qPrint(name()),qPrint(cd->name()),accessName);
3771   //
3772   auto it = std::find_if(m_impl->usedByImplClassList.begin(),
3773                          m_impl->usedByImplClassList.end(),
3774                          [&cd](const auto &ucd) { return ucd.classDef==cd; });
3775   if (it==m_impl->usedByImplClassList.end())
3776   {
3777      m_impl->usedByImplClassList.emplace_back(cd);
3778      //printf("Adding used by class %s to class %s\n",
3779      //    qPrint(cd->name()),qPrint(name()));
3780      it = m_impl->usedByImplClassList.end()-1;
3781   }
3782   QCString acc = accessName;
3783   if (umlLook)
3784   {
3785     switch(prot)
3786     {
3787       case Public:    acc.prepend("+"); break;
3788       case Private:   acc.prepend("-"); break;
3789       case Protected: acc.prepend("#"); break;
3790       case Package:   acc.prepend("~"); break;
3791     }
3792   }
3793   (*it).addAccessor(acc);
3794 }
3795 
3796 
compoundTypeString() const3797 QCString ClassDefImpl::compoundTypeString() const
3798 {
3799   if (getLanguage()==SrcLangExt_Fortran)
3800   {
3801     switch (m_impl->compType)
3802     {
3803       case Class:     return "module";
3804       case Struct:    return "type";
3805       case Union:     return "union";
3806       case Interface: return "interface";
3807       case Protocol:  return "protocol";
3808       case Category:  return "category";
3809       case Exception: return "exception";
3810       default:        return "unknown";
3811     }
3812   }
3813   else
3814   {
3815     switch (m_impl->compType)
3816     {
3817       case Class:     return isJavaEnum() ? "enum" : "class";
3818       case Struct:    return "struct";
3819       case Union:     return "union";
3820       case Interface: return getLanguage()==SrcLangExt_ObjC ? "class" : "interface";
3821       case Protocol:  return "protocol";
3822       case Category:  return "category";
3823       case Exception: return "exception";
3824       case Service:   return "service";
3825       case Singleton: return "singleton";
3826       default:        return "unknown";
3827     }
3828   }
3829 }
3830 
getOutputFileBase() const3831 QCString ClassDefImpl::getOutputFileBase() const
3832 {
3833   static bool inlineGroupedClasses = Config_getBool(INLINE_GROUPED_CLASSES);
3834   static bool inlineSimpleClasses = Config_getBool(INLINE_SIMPLE_STRUCTS);
3835   if (!Doxygen::generatingXmlOutput)
3836   {
3837     Definition *scope=0;
3838     if (inlineGroupedClasses && !partOfGroups().empty())
3839     {
3840       // point to the group that embeds this class
3841       return partOfGroups().front()->getOutputFileBase();
3842     }
3843     else if (inlineSimpleClasses && m_impl->isSimple && !partOfGroups().empty())
3844     {
3845       // point to simple struct inside a group
3846       return partOfGroups().front()->getOutputFileBase();
3847     }
3848     else if (inlineSimpleClasses && m_impl->isSimple && (scope=getOuterScope()))
3849     {
3850       if (scope==Doxygen::globalScope && getFileDef() && getFileDef()->isLinkableInProject()) // simple struct embedded in file
3851       {
3852         return getFileDef()->getOutputFileBase();
3853       }
3854       else if (scope->isLinkableInProject()) // simple struct embedded in other container (namespace/group/class)
3855       {
3856         return getOuterScope()->getOutputFileBase();
3857       }
3858     }
3859   }
3860   if (m_impl->templateMaster)
3861   {
3862     // point to the template of which this class is an instance
3863     return m_impl->templateMaster->getOutputFileBase();
3864   }
3865   return m_impl->fileName;
3866 }
3867 
getInstanceOutputFileBase() const3868 QCString ClassDefImpl::getInstanceOutputFileBase() const
3869 {
3870   return m_impl->fileName;
3871 }
3872 
getSourceFileBase() const3873 QCString ClassDefImpl::getSourceFileBase() const
3874 {
3875   if (m_impl->templateMaster)
3876   {
3877     return m_impl->templateMaster->getSourceFileBase();
3878   }
3879   else
3880   {
3881     return DefinitionMixin::getSourceFileBase();
3882   }
3883 }
3884 
setGroupDefForAllMembers(GroupDef * gd,Grouping::GroupPri_t pri,const QCString & fileName,int startLine,bool hasDocs)3885 void ClassDefImpl::setGroupDefForAllMembers(GroupDef *gd,Grouping::GroupPri_t pri,const QCString &fileName,int startLine,bool hasDocs)
3886 {
3887   gd->addClass(this);
3888   //printf("ClassDefImpl::setGroupDefForAllMembers(%s)\n",qPrint(gd->name()));
3889   for (auto &mni : m_impl->allMemberNameInfoLinkedMap)
3890   {
3891     for (auto &mi : *mni)
3892     {
3893       MemberDefMutable *md = toMemberDefMutable(mi->memberDef());
3894       if (md)
3895       {
3896         md->setGroupDef(gd,pri,fileName,startLine,hasDocs);
3897         gd->insertMember(md,TRUE);
3898         ClassDefMutable *innerClass = toClassDefMutable(md->getClassDefOfAnonymousType());
3899         if (innerClass) innerClass->setGroupDefForAllMembers(gd,pri,fileName,startLine,hasDocs);
3900       }
3901     }
3902   }
3903 }
3904 
addInnerCompound(const Definition * d)3905 void ClassDefImpl::addInnerCompound(const Definition *d)
3906 {
3907   //printf("**** %s::addInnerCompound(%s)\n",qPrint(name()),qPrint(d->name()));
3908   if (d->definitionType()==Definition::TypeClass) // only classes can be
3909                                                   // nested in classes.
3910   {
3911     m_impl->innerClasses.add(d->localName(),toClassDef(d));
3912   }
3913 }
3914 
findInnerCompound(const QCString & name) const3915 const Definition *ClassDefImpl::findInnerCompound(const QCString &name) const
3916 {
3917   return m_impl->innerClasses.find(name);
3918 }
3919 
insertTemplateInstance(const QCString & fileName,int startLine,int startColumn,const QCString & templSpec,bool & freshInstance) const3920 ClassDef *ClassDefImpl::insertTemplateInstance(const QCString &fileName,
3921     int startLine, int startColumn, const QCString &templSpec,bool &freshInstance) const
3922 {
3923   freshInstance = FALSE;
3924   auto it = std::find_if(m_impl->templateInstances.begin(),
3925                          m_impl->templateInstances.end(),
3926                          [&templSpec](const auto &ti) { return templSpec==ti.templSpec; });
3927   ClassDefMutable *templateClass=0;
3928   if (it!=m_impl->templateInstances.end())
3929   {
3930     templateClass = toClassDefMutable((*it).classDef);
3931   }
3932   if (templateClass==0)
3933   {
3934     QCString tcname = removeRedundantWhiteSpace(localName()+templSpec);
3935     Debug::print(Debug::Classes,0,"      New template instance class '%s''%s' inside '%s' hidden=%d\n",qPrint(name()),qPrint(templSpec),qPrint(name()),isHidden());
3936 
3937     ClassDef *foundCd = Doxygen::classLinkedMap->find(tcname);
3938     if (foundCd)
3939     {
3940       return foundCd;
3941     }
3942     templateClass =
3943       toClassDefMutable(
3944           Doxygen::classLinkedMap->add(tcname,
3945             std::unique_ptr<ClassDef>(
3946               new ClassDefImpl(fileName,startLine,startColumn,tcname,ClassDef::Class))));
3947     if (templateClass)
3948     {
3949       templateClass->setTemplateMaster(this);
3950       templateClass->setOuterScope(getOuterScope());
3951       templateClass->setHidden(isHidden());
3952       templateClass->setArtificial(isArtificial());
3953       m_impl->templateInstances.push_back(TemplateInstanceDef(templSpec,templateClass));
3954 
3955       // also add nested classes
3956       for (const auto &innerCd : m_impl->innerClasses)
3957       {
3958         QCString innerName = tcname+"::"+innerCd->localName();
3959         ClassDefMutable *innerClass =
3960           toClassDefMutable(
3961               Doxygen::classLinkedMap->add(innerName,
3962                 std::unique_ptr<ClassDef>(
3963                   new ClassDefImpl(fileName,startLine,startColumn,innerName,ClassDef::Class))));
3964         if (innerClass)
3965         {
3966           templateClass->addInnerCompound(innerClass);
3967           innerClass->setOuterScope(templateClass);
3968           innerClass->setHidden(isHidden());
3969           innerClass->setArtificial(TRUE);
3970         }
3971       }
3972       freshInstance=TRUE;
3973     }
3974   }
3975   return templateClass;
3976 }
3977 
setTemplateBaseClassNames(const TemplateNameMap & templateNames)3978 void ClassDefImpl::setTemplateBaseClassNames(const TemplateNameMap &templateNames)
3979 {
3980   m_impl->templBaseClassNames = templateNames;
3981 }
3982 
getTemplateBaseClassNames() const3983 const TemplateNameMap &ClassDefImpl::getTemplateBaseClassNames() const
3984 {
3985   return m_impl->templBaseClassNames;
3986 }
3987 
addMembersToTemplateInstance(const ClassDef * cd,const ArgumentList & templateArguments,const QCString & templSpec)3988 void ClassDefImpl::addMembersToTemplateInstance(const ClassDef *cd,const ArgumentList &templateArguments,const QCString &templSpec)
3989 {
3990   //printf("%s::addMembersToTemplateInstance(%s,%s)\n",qPrint(name()),qPrint(cd->name()),templSpec);
3991   for (const auto &mni : cd->memberNameInfoLinkedMap())
3992   {
3993     for (const auto &mi : *mni)
3994     {
3995       auto actualArguments_p = stringToArgumentList(getLanguage(),templSpec);
3996       const MemberDef *md = mi->memberDef();
3997       std::unique_ptr<MemberDefMutable> imd { md->createTemplateInstanceMember(
3998                           templateArguments,actualArguments_p) };
3999       //printf("%s->setMemberClass(%p)\n",qPrint(imd->name()),this);
4000       imd->setMemberClass(this);
4001       imd->setTemplateMaster(md);
4002       imd->setDocumentation(md->documentation(),md->docFile(),md->docLine());
4003       imd->setBriefDescription(md->briefDescription(),md->briefFile(),md->briefLine());
4004       imd->setInbodyDocumentation(md->inbodyDocumentation(),md->inbodyFile(),md->inbodyLine());
4005       imd->setMemberSpecifiers(md->getMemberSpecifiers());
4006       imd->setMemberGroupId(md->getMemberGroupId());
4007       insertMember(imd.get());
4008       //printf("Adding member=%s %s%s to class %s templSpec %s\n",
4009       //    imd->typeString(),qPrint(imd->name()),imd->argsString(),
4010       //    qPrint(imd->getClassDef()->name()),templSpec);
4011       // insert imd in the list of all members
4012       //printf("Adding member=%s class=%s\n",qPrint(imd->name()),qPrint(name()));
4013       MemberName *mn = Doxygen::memberNameLinkedMap->add(imd->name());
4014       mn->push_back(std::move(imd));
4015     }
4016   }
4017   // also instantatie members for nested classes
4018   for (const auto &innerCd : cd->getClasses())
4019   {
4020     ClassDefMutable *ncd = toClassDefMutable(m_impl->innerClasses.find(innerCd->localName()));
4021     if (ncd)
4022     {
4023       ncd->addMembersToTemplateInstance(innerCd,cd->templateArguments(),templSpec);
4024     }
4025   }
4026 }
4027 
getReference() const4028 QCString ClassDefImpl::getReference() const
4029 {
4030   if (m_impl->templateMaster)
4031   {
4032     return m_impl->templateMaster->getReference();
4033   }
4034   else
4035   {
4036     return DefinitionMixin::getReference();
4037   }
4038 }
4039 
isReference() const4040 bool ClassDefImpl::isReference() const
4041 {
4042   if (m_impl->templateMaster)
4043   {
4044     return m_impl->templateMaster->isReference();
4045   }
4046   else
4047   {
4048     return DefinitionMixin::isReference();
4049   }
4050 }
4051 
getTemplateParameterLists() const4052 ArgumentLists ClassDefImpl::getTemplateParameterLists() const
4053 {
4054   ArgumentLists result;
4055   Definition *d=getOuterScope();
4056   while (d && d->definitionType()==Definition::TypeClass)
4057   {
4058     result.insert(result.begin(),toClassDef(d)->templateArguments());
4059     d = d->getOuterScope();
4060   }
4061   if (!templateArguments().empty())
4062   {
4063     result.push_back(templateArguments());
4064   }
4065   return result;
4066 }
4067 
qualifiedNameWithTemplateParameters(const ArgumentLists * actualParams,uint * actualParamIndex) const4068 QCString ClassDefImpl::qualifiedNameWithTemplateParameters(
4069     const ArgumentLists *actualParams,uint *actualParamIndex) const
4070 {
4071   return makeQualifiedNameWithTemplateParameters(this,actualParams,actualParamIndex);
4072 }
4073 
className() const4074 QCString ClassDefImpl::className() const
4075 {
4076   if (m_impl->className.isEmpty())
4077   {
4078     return localName();
4079   }
4080   else
4081   {
4082     return m_impl->className;
4083   }
4084 }
4085 
setClassName(const QCString & name)4086 void ClassDefImpl::setClassName(const QCString &name)
4087 {
4088   m_impl->className = name;
4089 }
4090 
addListReferences()4091 void ClassDefImpl::addListReferences()
4092 {
4093   SrcLangExt lang = getLanguage();
4094   if (!isLinkableInProject()) return;
4095   //printf("ClassDef(%s)::addListReferences()\n",qPrint(name()));
4096   {
4097     const RefItemVector &xrefItems = xrefListItems();
4098     addRefItem(xrefItems,
4099              qualifiedName(),
4100              lang==SrcLangExt_Fortran ? theTranslator->trType(TRUE,TRUE)
4101                                       : theTranslator->trClass(TRUE,TRUE),
4102              getOutputFileBase(),
4103              displayName(),
4104              QCString(),
4105              this
4106             );
4107   }
4108   for (const auto &mg : m_impl->memberGroups)
4109   {
4110     mg->addListReferences(this);
4111   }
4112   for (auto &ml : m_impl->memberLists)
4113   {
4114     if (ml->listType()&MemberListType_detailedLists)
4115     {
4116       ml->addListReferences(this);
4117     }
4118   }
4119 }
4120 
getMemberByName(const QCString & name) const4121 const MemberDef *ClassDefImpl::getMemberByName(const QCString &name) const
4122 {
4123   const MemberDef *xmd = 0;
4124   MemberNameInfo *mni = m_impl->allMemberNameInfoLinkedMap.find(name);
4125   if (mni)
4126   {
4127     const int maxInheritanceDepth = 100000;
4128     int mdist=maxInheritanceDepth;
4129     for (auto &mi : *mni)
4130     {
4131       const ClassDef *mcd=mi->memberDef()->getClassDef();
4132       int m=minClassDistance(this,mcd);
4133       //printf("found member in %s linkable=%d m=%d\n",
4134       //    qPrint(mcd->name()),mcd->isLinkable(),m);
4135       if (m<mdist && mcd->isLinkable())
4136       {
4137         mdist=m;
4138         xmd=mi->memberDef();
4139       }
4140     }
4141   }
4142   //printf("getMemberByName(%s)=%p\n",qPrint(name),xmd);
4143   return xmd;
4144 }
4145 
isAccessibleMember(const MemberDef * md) const4146 bool ClassDefImpl::isAccessibleMember(const MemberDef *md) const
4147 {
4148   return md->getClassDef() && isBaseClass(md->getClassDef(),TRUE);
4149 }
4150 
getMemberList(MemberListType lt) const4151 MemberList *ClassDefImpl::getMemberList(MemberListType lt) const
4152 {
4153   for (auto &ml : m_impl->memberLists)
4154   {
4155     if (ml->listType()==lt)
4156     {
4157       return ml.get();
4158     }
4159   }
4160   return 0;
4161 }
4162 
addMemberToList(MemberListType lt,const MemberDef * md,bool isBrief)4163 void ClassDefImpl::addMemberToList(MemberListType lt,const MemberDef *md,bool isBrief)
4164 {
4165   static bool sortBriefDocs = Config_getBool(SORT_BRIEF_DOCS);
4166   static bool sortMemberDocs = Config_getBool(SORT_MEMBER_DOCS);
4167   const auto &ml = m_impl->memberLists.get(lt,MemberListContainer::Class);
4168   ml->setNeedsSorting((isBrief && sortBriefDocs) || (!isBrief && sortMemberDocs));
4169   ml->push_back(md);
4170 
4171   // for members in the declaration lists we set the section, needed for member grouping
4172   if ((ml->listType()&MemberListType_detailedLists)==0)
4173   {
4174     MemberDefMutable *mdm = toMemberDefMutable(md);
4175     if (mdm)
4176     {
4177       mdm->setSectionList(this,ml.get());
4178     }
4179   }
4180 }
4181 
sortMemberLists()4182 void ClassDefImpl::sortMemberLists()
4183 {
4184   for (auto &ml : m_impl->memberLists)
4185   {
4186     if (ml->needsSorting()) { ml->sort(); ml->setNeedsSorting(FALSE); }
4187   }
4188   std::sort(m_impl->innerClasses.begin(),
4189             m_impl->innerClasses.end(),
4190             [](const auto &c1,const auto &c2)
4191             {
4192                return Config_getBool(SORT_BY_SCOPE_NAME)           ?
4193                       qstricmp(c1->name(),      c2->name()     )<0 :
4194                       qstricmp(c1->className(), c2->className())<0 ;
4195             });
4196 }
4197 
countMemberDeclarations(MemberListType lt,const ClassDef * inheritedFrom,int lt2,bool invert,bool showAlways,ClassDefSet & visitedClasses) const4198 int ClassDefImpl::countMemberDeclarations(MemberListType lt,const ClassDef *inheritedFrom,
4199                                       int lt2,bool invert,bool showAlways,ClassDefSet &visitedClasses) const
4200 {
4201   //printf("%s: countMemberDeclarations for %d and %d\n",qPrint(name()),lt,lt2);
4202   int count=0;
4203   MemberList * ml  = getMemberList(lt);
4204   MemberList * ml2 = getMemberList((MemberListType)lt2);
4205   if (getLanguage()!=SrcLangExt_VHDL) // use specific declarations function
4206   {
4207     if (ml)
4208     {
4209       count+=ml->numDecMembers();
4210       //printf("-> ml=%d\n",ml->numDecMembers());
4211     }
4212     if (ml2)
4213     {
4214       count+=ml2->numDecMembers();
4215       //printf("-> ml2=%d\n",ml2->numDecMembers());
4216     }
4217     // also include grouped members that have their own section in the class (see bug 722759)
4218     if (inheritedFrom)
4219     {
4220       for (const auto &mg : m_impl->memberGroups)
4221       {
4222         count+=mg->countGroupedInheritedMembers(lt);
4223         if (lt2!=-1) count+=mg->countGroupedInheritedMembers((MemberListType)lt2);
4224       }
4225     }
4226     static bool inlineInheritedMembers = Config_getBool(INLINE_INHERITED_MEMB);
4227     if (!inlineInheritedMembers) // show inherited members as separate lists
4228     {
4229       count+=countInheritedDecMembers(lt,inheritedFrom,invert,showAlways,visitedClasses);
4230     }
4231   }
4232   //printf("-> %d\n",count);
4233   return count;
4234 }
4235 
setAnonymousEnumType()4236 void ClassDefImpl::setAnonymousEnumType()
4237 {
4238   for (const auto &lde : LayoutDocManager::instance().docEntries(LayoutDocManager::Class))
4239   {
4240     if (lde->kind()==LayoutDocEntry::MemberDecl)
4241     {
4242       const LayoutDocEntryMemberDecl *lmd = (const LayoutDocEntryMemberDecl*)lde.get();
4243       MemberList * ml = getMemberList(lmd->type);
4244       if (ml)
4245       {
4246         ml->setAnonymousEnumType();
4247       }
4248     }
4249     else if (lde->kind()==LayoutDocEntry::MemberGroups)
4250     {
4251       for (const auto &mg : m_impl->memberGroups)
4252       {
4253         mg->setAnonymousEnumType();
4254       }
4255     }
4256   }
4257 }
4258 
countMembers()4259 void ClassDefImpl::countMembers()
4260 {
4261   for (auto &ml : m_impl->memberLists)
4262   {
4263     ml->countDecMembers();
4264     ml->countDocMembers();
4265   }
4266   for (const auto &mg : m_impl->memberGroups)
4267   {
4268     mg->countDecMembers();
4269     mg->countDocMembers();
4270   }
4271 }
4272 
countInheritedDecMembers(MemberListType lt,const ClassDef * inheritedFrom,bool invert,bool showAlways,ClassDefSet & visitedClasses) const4273 int ClassDefImpl::countInheritedDecMembers(MemberListType lt,
4274                                        const ClassDef *inheritedFrom,bool invert,bool showAlways,
4275                                        ClassDefSet &visitedClasses) const
4276 {
4277   int inhCount = 0;
4278   int count = countMembersIncludingGrouped(lt,inheritedFrom,FALSE);
4279   bool process = count>0;
4280   //printf("%s: countInheritedDecMembers: lt=%d process=%d count=%d invert=%d\n",
4281   //    qPrint(name()),lt,process,count,invert);
4282   if ((process^invert) || showAlways)
4283   {
4284     for (const auto &ibcd : m_impl->inherits)
4285     {
4286       ClassDefMutable *icd=toClassDefMutable(ibcd.classDef);
4287       int lt1,lt2;
4288       if (icd && icd->isLinkable())
4289       {
4290         convertProtectionLevel(lt,ibcd.prot,&lt1,&lt2);
4291         //printf("%s: convert %d->(%d,%d) prot=%d\n",
4292         //    qPrint(icd->name()),lt,lt1,lt2,ibcd->prot);
4293         if (visitedClasses.find(icd)==visitedClasses.end())
4294         {
4295           visitedClasses.insert(icd); // guard for multiple virtual inheritance
4296           if (lt1!=-1)
4297           {
4298             inhCount+=icd->countMemberDeclarations((MemberListType)lt1,inheritedFrom,lt2,FALSE,TRUE,visitedClasses);
4299           }
4300         }
4301       }
4302     }
4303   }
4304   return inhCount;
4305 }
4306 
getTitleForMemberListType(MemberListType type,QCString & title,QCString & subtitle) const4307 void ClassDefImpl::getTitleForMemberListType(MemberListType type,
4308                QCString &title,QCString &subtitle) const
4309 {
4310   SrcLangExt lang = getLanguage();
4311   for (const auto &lde : LayoutDocManager::instance().docEntries(LayoutDocManager::Class))
4312   {
4313     if (lde->kind()==LayoutDocEntry::MemberDecl)
4314     {
4315       const LayoutDocEntryMemberDecl *lmd = (const LayoutDocEntryMemberDecl*)lde.get();
4316       if (lmd->type==type)
4317       {
4318         title = lmd->title(lang);
4319         subtitle = lmd->subtitle(lang);
4320         return;
4321       }
4322     }
4323   }
4324   title="";
4325   subtitle="";
4326 }
4327 
countAdditionalInheritedMembers() const4328 int ClassDefImpl::countAdditionalInheritedMembers() const
4329 {
4330   int totalCount=0;
4331   for (const auto &lde : LayoutDocManager::instance().docEntries(LayoutDocManager::Class))
4332   {
4333     if (lde->kind()==LayoutDocEntry::MemberDecl)
4334     {
4335       const LayoutDocEntryMemberDecl *lmd = (const LayoutDocEntryMemberDecl*)lde.get();
4336       if (lmd->type!=MemberListType_friends) // friendship is not inherited
4337       {
4338         ClassDefSet visited;
4339         totalCount+=countInheritedDecMembers(lmd->type,this,TRUE,FALSE,visited);
4340       }
4341     }
4342   }
4343   //printf("countAdditionalInheritedMembers()=%d\n",totalCount);
4344   return totalCount;
4345 }
4346 
writeAdditionalInheritedMembers(OutputList & ol) const4347 void ClassDefImpl::writeAdditionalInheritedMembers(OutputList &ol) const
4348 {
4349   //printf("**** writeAdditionalInheritedMembers()\n");
4350   for (const auto &lde : LayoutDocManager::instance().docEntries(LayoutDocManager::Class))
4351   {
4352     if (lde->kind()==LayoutDocEntry::MemberDecl)
4353     {
4354       const LayoutDocEntryMemberDecl *lmd = (const LayoutDocEntryMemberDecl*)lde.get();
4355       if (lmd->type!=MemberListType_friends)
4356       {
4357         ClassDefSet visited;
4358         writeInheritedMemberDeclarations(ol,visited,lmd->type,-1,lmd->title(getLanguage()),this,TRUE,FALSE);
4359       }
4360     }
4361   }
4362 }
4363 
countMembersIncludingGrouped(MemberListType lt,const ClassDef * inheritedFrom,bool additional) const4364 int ClassDefImpl::countMembersIncludingGrouped(MemberListType lt,
4365               const ClassDef *inheritedFrom,bool additional) const
4366 {
4367   int count=0;
4368   MemberList *ml = getMemberList(lt);
4369   if (ml)
4370   {
4371     count=ml->countInheritableMembers(inheritedFrom);
4372   }
4373   //printf("%s:countMembersIncludingGrouped: count=%d\n",qPrint(name()),count);
4374   for (const auto &mg : m_impl->memberGroups)
4375   {
4376     bool hasOwnSection = !mg->allMembersInSameSection() ||
4377                          !m_impl->subGrouping; // group is in its own section
4378     if ((additional && hasOwnSection) || (!additional && !hasOwnSection))
4379     {
4380       count+=mg->countGroupedInheritedMembers(lt);
4381     }
4382   }
4383   //printf("%s:countMembersIncludingGrouped(lt=%d,%s)=%d\n",
4384   //    qPrint(name()),lt,ml?qPrint(ml->listTypeAsString(ml->listType())):"<none>",count);
4385   return count;
4386 }
4387 
4388 
writeInheritedMemberDeclarations(OutputList & ol,ClassDefSet & visitedClasses,MemberListType lt,int lt2,const QCString & title,const ClassDef * inheritedFrom,bool invert,bool showAlways) const4389 void ClassDefImpl::writeInheritedMemberDeclarations(OutputList &ol,ClassDefSet &visitedClasses,
4390                MemberListType lt,int lt2,const QCString &title,
4391                const ClassDef *inheritedFrom,bool invert,bool showAlways) const
4392 {
4393   ol.pushGeneratorState();
4394   ol.disableAllBut(OutputGenerator::Html);
4395   int count = countMembersIncludingGrouped(lt,inheritedFrom,FALSE);
4396   bool process = count>0;
4397   //printf("%s: writeInheritedMemberDec: lt=%d process=%d invert=%d always=%d\n",
4398   //    qPrint(name()),lt,process,invert,showAlways);
4399   if ((process^invert) || showAlways)
4400   {
4401     for (const auto &ibcd : m_impl->inherits)
4402     {
4403       ClassDefMutable *icd=toClassDefMutable(ibcd.classDef);
4404       if (icd && icd->isLinkable())
4405       {
4406         int lt1,lt3;
4407         convertProtectionLevel(lt,ibcd.prot,&lt1,&lt3);
4408         if (lt2==-1 && lt3!=-1)
4409         {
4410           lt2=lt3;
4411         }
4412         //printf("%s:convert %d->(%d,%d) prot=%d\n",qPrint(icd->name()),lt,lt1,lt2,ibcd->prot);
4413         if (visitedClasses.find(icd)==visitedClasses.end())
4414         {
4415           visitedClasses.insert(icd); // guard for multiple virtual inheritance
4416           if (lt1!=-1)
4417           {
4418             icd->writeMemberDeclarations(ol,visitedClasses,(MemberListType)lt1,
4419                 title,QCString(),FALSE,inheritedFrom,lt2,FALSE,TRUE);
4420           }
4421         }
4422         else
4423         {
4424           //printf("%s: class already visited!\n",qPrint(icd->name()));
4425         }
4426       }
4427     }
4428   }
4429   ol.popGeneratorState();
4430 }
4431 
writeMemberDeclarations(OutputList & ol,ClassDefSet & visitedClasses,MemberListType lt,const QCString & title,const QCString & subTitle,bool showInline,const ClassDef * inheritedFrom,int lt2,bool invert,bool showAlways) const4432 void ClassDefImpl::writeMemberDeclarations(OutputList &ol,ClassDefSet &visitedClasses,
4433                MemberListType lt,const QCString &title,
4434                const QCString &subTitle,bool showInline,const ClassDef *inheritedFrom,int lt2,
4435                bool invert,bool showAlways) const
4436 {
4437   //printf("%s: ClassDefImpl::writeMemberDeclarations lt=%d lt2=%d\n",qPrint(name()),lt,lt2);
4438   MemberList * ml = getMemberList(lt);
4439   MemberList * ml2 = getMemberList((MemberListType)lt2);
4440   if (getLanguage()==SrcLangExt_VHDL) // use specific declarations function
4441   {
4442     static const ClassDef *cdef;
4443     if (cdef!=this)
4444     { // only one inline link
4445       VhdlDocGen::writeInlineClassLink(this,ol);
4446       cdef=this;
4447     }
4448     if (ml)
4449     {
4450       VhdlDocGen::writeVhdlDeclarations(ml,ol,0,this,0,0);
4451     }
4452   }
4453   else
4454   {
4455     //printf("%s::writeMemberDeclarations(%s) ml=%p ml2=%p\n",qPrint(name()),qPrint(title),ml,ml2);
4456     QCString tt = title, st = subTitle;
4457     if (ml)
4458     {
4459       //printf("  writeDeclaration type=%d count=%d\n",lt,ml->numDecMembers());
4460       ml->writeDeclarations(ol,this,0,0,0,tt,st,FALSE,showInline,inheritedFrom,lt);
4461       tt.resize(0);
4462       st.resize(0);
4463     }
4464     if (ml2)
4465     {
4466       //printf("  writeDeclaration type=%d count=%d\n",lt2,ml2->numDecMembers());
4467       ml2->writeDeclarations(ol,this,0,0,0,tt,st,FALSE,showInline,inheritedFrom,lt);
4468     }
4469     static bool inlineInheritedMembers = Config_getBool(INLINE_INHERITED_MEMB);
4470     if (!inlineInheritedMembers) // show inherited members as separate lists
4471     {
4472       writeInheritedMemberDeclarations(ol,visitedClasses,lt,lt2,title,
4473           inheritedFrom ? inheritedFrom : this,
4474           invert,showAlways);
4475     }
4476   }
4477 }
4478 
addGroupedInheritedMembers(OutputList & ol,MemberListType lt,const ClassDef * inheritedFrom,const QCString & inheritId) const4479 void ClassDefImpl::addGroupedInheritedMembers(OutputList &ol,MemberListType lt,
4480                         const ClassDef *inheritedFrom,const QCString &inheritId) const
4481 {
4482   //printf("** %s::addGroupedInheritedMembers(%p) inheritId=%s\n",qPrint(name()),m_impl->memberGroupSDict,qPrint(inheritId));
4483   for (const auto &mg : m_impl->memberGroups)
4484   {
4485     if (!mg->allMembersInSameSection() || !m_impl->subGrouping) // group is in its own section
4486     {
4487       mg->addGroupedInheritedMembers(ol,this,lt,inheritedFrom,inheritId);
4488     }
4489   }
4490 }
4491 
writeMemberDocumentation(OutputList & ol,MemberListType lt,const QCString & title,bool showInline) const4492 void ClassDefImpl::writeMemberDocumentation(OutputList &ol,MemberListType lt,const QCString &title,bool showInline) const
4493 {
4494   //printf("%s: ClassDefImpl::writeMemberDocumentation()\n",qPrint(name()));
4495   MemberList * ml = getMemberList(lt);
4496   if (ml) ml->writeDocumentation(ol,displayName(),this,title,FALSE,showInline);
4497 }
4498 
writeSimpleMemberDocumentation(OutputList & ol,MemberListType lt) const4499 void ClassDefImpl::writeSimpleMemberDocumentation(OutputList &ol,MemberListType lt) const
4500 {
4501   //printf("%s: ClassDefImpl::writeSimpleMemberDocumentation()\n",qPrint(name()));
4502   MemberList * ml = getMemberList(lt);
4503   if (ml) ml->writeSimpleDocumentation(ol,this);
4504 }
4505 
writePlainMemberDeclaration(OutputList & ol,MemberListType lt,bool inGroup,int indentLevel,const ClassDef * inheritedFrom,const QCString & inheritId) const4506 void ClassDefImpl::writePlainMemberDeclaration(OutputList &ol,
4507          MemberListType lt,bool inGroup,
4508          int indentLevel,const ClassDef *inheritedFrom,const QCString &inheritId) const
4509 {
4510   //printf("%s: ClassDefImpl::writePlainMemberDeclaration()\n",qPrint(name()));
4511   MemberList * ml = getMemberList(lt);
4512   if (ml)
4513   {
4514     ml->writePlainDeclarations(ol,inGroup,this,0,0,0,indentLevel,inheritedFrom,inheritId);
4515   }
4516 }
4517 
isLocal() const4518 bool ClassDefImpl::isLocal() const
4519 {
4520   return m_impl->isLocal;
4521 }
4522 
getClasses() const4523 ClassLinkedRefMap ClassDefImpl::getClasses() const
4524 {
4525   return m_impl->innerClasses;
4526 }
4527 
compoundType() const4528 ClassDefImpl::CompoundType ClassDefImpl::compoundType() const
4529 {
4530   return m_impl->compType;
4531 }
4532 
baseClasses() const4533 const BaseClassList &ClassDefImpl::baseClasses() const
4534 {
4535   return m_impl->inherits;
4536 }
4537 
updateBaseClasses(const BaseClassList & bcd)4538 void ClassDefImpl::updateBaseClasses(const BaseClassList &bcd)
4539 {
4540   m_impl->inherits = bcd;
4541 }
4542 
subClasses() const4543 const BaseClassList &ClassDefImpl::subClasses() const
4544 {
4545   return m_impl->inheritedBy;
4546 }
4547 
updateSubClasses(const BaseClassList & bcd)4548 void ClassDefImpl::updateSubClasses(const BaseClassList &bcd)
4549 {
4550   m_impl->inheritedBy = bcd;
4551 }
4552 
memberNameInfoLinkedMap() const4553 const MemberNameInfoLinkedMap &ClassDefImpl::memberNameInfoLinkedMap() const
4554 {
4555   return m_impl->allMemberNameInfoLinkedMap;
4556 }
4557 
sortAllMembersList()4558 void ClassDefImpl::sortAllMembersList()
4559 {
4560   std::sort(m_impl->allMemberNameInfoLinkedMap.begin(),
4561             m_impl->allMemberNameInfoLinkedMap.end(),
4562             [](const auto &m1,const auto &m2)
4563             {
4564               return qstricmp(m1->memberName(),m2->memberName())<0;
4565             });
4566 }
4567 
protection() const4568 Protection ClassDefImpl::protection() const
4569 {
4570   return m_impl->prot;
4571 }
4572 
templateArguments() const4573 const ArgumentList &ClassDefImpl::templateArguments() const
4574 {
4575   return m_impl->tempArgs;
4576 }
4577 
4578 //NamespaceDef *ClassDefImpl::getNamespaceDef() const
4579 //{
4580 //  return m_impl->nspace;
4581 //}
4582 
getFileDef() const4583 FileDef *ClassDefImpl::getFileDef() const
4584 {
4585   return m_impl->fileDef;
4586 }
4587 
getTemplateInstances() const4588 const TemplateInstanceList &ClassDefImpl::getTemplateInstances() const
4589 {
4590   return m_impl->templateInstances;
4591 }
4592 
templateMaster() const4593 const ClassDef *ClassDefImpl::templateMaster() const
4594 {
4595   return m_impl->templateMaster;
4596 }
4597 
isTemplate() const4598 bool ClassDefImpl::isTemplate() const
4599 {
4600   return !m_impl->tempArgs.empty();
4601 }
4602 
includeInfo() const4603 const IncludeInfo *ClassDefImpl::includeInfo() const
4604 {
4605   return m_impl->incInfo.get();
4606 }
4607 
usedImplementationClasses() const4608 const UsesClassList &ClassDefImpl::usedImplementationClasses() const
4609 {
4610   return m_impl->usesImplClassList;
4611 }
4612 
usedByImplementationClasses() const4613 const UsesClassList &ClassDefImpl::usedByImplementationClasses() const
4614 {
4615   return m_impl->usedByImplClassList;
4616 }
4617 
templateTypeConstraints() const4618 const ConstraintClassList &ClassDefImpl::templateTypeConstraints() const
4619 {
4620   return m_impl->constraintClassList;
4621 }
4622 
isTemplateArgument() const4623 bool ClassDefImpl::isTemplateArgument() const
4624 {
4625   return m_impl->isTemplArg;
4626 }
4627 
isAbstract() const4628 bool ClassDefImpl::isAbstract() const
4629 {
4630   return m_impl->isAbstract || (m_impl->spec&Entry::Abstract);
4631 }
4632 
isFinal() const4633 bool ClassDefImpl::isFinal() const
4634 {
4635   return m_impl->spec&Entry::Final;
4636 }
4637 
isSealed() const4638 bool ClassDefImpl::isSealed() const
4639 {
4640   return m_impl->spec&Entry::Sealed;
4641 }
4642 
isPublished() const4643 bool ClassDefImpl::isPublished() const
4644 {
4645   return m_impl->spec&Entry::Published;
4646 }
4647 
isForwardDeclared() const4648 bool ClassDefImpl::isForwardDeclared() const
4649 {
4650   return m_impl->spec&Entry::ForwardDecl;
4651 }
4652 
isInterface() const4653 bool ClassDefImpl::isInterface() const
4654 {
4655   return m_impl->spec&Entry::Interface;
4656 }
4657 
isObjectiveC() const4658 bool ClassDefImpl::isObjectiveC() const
4659 {
4660   return getLanguage()==SrcLangExt_ObjC;
4661 }
4662 
isFortran() const4663 bool ClassDefImpl::isFortran() const
4664 {
4665   return getLanguage()==SrcLangExt_Fortran;
4666 }
4667 
isCSharp() const4668 bool ClassDefImpl::isCSharp() const
4669 {
4670   return getLanguage()==SrcLangExt_CSharp;
4671 }
4672 
categoryOf() const4673 ClassDef *ClassDefImpl::categoryOf() const
4674 {
4675   return m_impl->categoryOf;
4676 }
4677 
getMemberLists() const4678 const MemberLists &ClassDefImpl::getMemberLists() const
4679 {
4680   return m_impl->memberLists;
4681 }
4682 
getMemberGroups() const4683 const MemberGroupList &ClassDefImpl::getMemberGroups() const
4684 {
4685   return m_impl->memberGroups;
4686 }
4687 
setFileDef(FileDef * fd)4688 void ClassDefImpl::setFileDef(FileDef *fd)
4689 {
4690   m_impl->fileDef=fd;
4691 }
4692 
setSubGrouping(bool enabled)4693 void ClassDefImpl::setSubGrouping(bool enabled)
4694 {
4695   m_impl->subGrouping = enabled;
4696 }
4697 
setProtection(Protection p)4698 void ClassDefImpl::setProtection(Protection p)
4699 {
4700   m_impl->prot=p;
4701 }
4702 
setIsStatic(bool b)4703 void ClassDefImpl::setIsStatic(bool b)
4704 {
4705   m_impl->isStatic=b;
4706 }
4707 
setCompoundType(CompoundType t)4708 void ClassDefImpl::setCompoundType(CompoundType t)
4709 {
4710   m_impl->compType = t;
4711 }
4712 
setTemplateMaster(const ClassDef * tm)4713 void ClassDefImpl::setTemplateMaster(const ClassDef *tm)
4714 {
4715   m_impl->templateMaster=tm;
4716 }
4717 
makeTemplateArgument(bool b)4718 void ClassDefImpl::makeTemplateArgument(bool b)
4719 {
4720   m_impl->isTemplArg = b;
4721 }
4722 
setCategoryOf(ClassDef * cd)4723 void ClassDefImpl::setCategoryOf(ClassDef *cd)
4724 {
4725   m_impl->categoryOf = cd;
4726 }
4727 
setUsedOnly(bool b)4728 void ClassDefImpl::setUsedOnly(bool b)
4729 {
4730   m_impl->usedOnly = b;
4731 }
4732 
isUsedOnly() const4733 bool ClassDefImpl::isUsedOnly() const
4734 {
4735   return m_impl->usedOnly;
4736 }
4737 
isSimple() const4738 bool ClassDefImpl::isSimple() const
4739 {
4740   return m_impl->isSimple;
4741 }
4742 
isSmartPointer() const4743 const MemberDef *ClassDefImpl::isSmartPointer() const
4744 {
4745   return m_impl->arrowOperator;
4746 }
4747 
reclassifyMember(MemberDefMutable * md,MemberType t)4748 void ClassDefImpl::reclassifyMember(MemberDefMutable *md,MemberType t)
4749 {
4750   md->setMemberType(t);
4751   for (auto &ml : m_impl->memberLists)
4752   {
4753     ml->remove(md);
4754   }
4755   insertMember(md);
4756 }
4757 
anchor() const4758 QCString ClassDefImpl::anchor() const
4759 {
4760   QCString anc;
4761   if (isEmbeddedInOuterScope() && !Doxygen::generatingXmlOutput)
4762   {
4763     if (m_impl->templateMaster)
4764     {
4765       // point to the template of which this class is an instance
4766       anc = m_impl->templateMaster->getOutputFileBase();
4767     }
4768     else
4769     {
4770       anc = m_impl->fileName;
4771     }
4772   }
4773   return anc;
4774 }
4775 
isEmbeddedInOuterScope() const4776 bool ClassDefImpl::isEmbeddedInOuterScope() const
4777 {
4778   static bool inlineGroupedClasses = Config_getBool(INLINE_GROUPED_CLASSES);
4779   static bool inlineSimpleClasses = Config_getBool(INLINE_SIMPLE_STRUCTS);
4780 
4781   Definition *container = getOuterScope();
4782 
4783   bool containerLinkable =
4784     container &&
4785        (
4786         (container==Doxygen::globalScope && getFileDef() && getFileDef()->isLinkableInProject()) || // global class in documented file
4787         container->isLinkableInProject() // class in documented scope
4788        );
4789 
4790   // inline because of INLINE_GROUPED_CLASSES=YES ?
4791   bool b1 = (inlineGroupedClasses && !partOfGroups().empty()); // a grouped class
4792   // inline because of INLINE_SIMPLE_STRUCTS=YES ?
4793   bool b2 = (inlineSimpleClasses && m_impl->isSimple && // a simple class
4794              (containerLinkable || // in a documented container
4795               !partOfGroups().empty()    // or part of a group
4796              )
4797            );
4798   //printf("%s::isEmbeddedInOuterScope(): inlineGroupedClasses=%d "
4799   //       "inlineSimpleClasses=%d partOfGroups()=%p m_impl->isSimple=%d "
4800   //       "getOuterScope()=%s b1=%d b2=%d\n",
4801   //    qPrint(name()),inlineGroupedClasses,inlineSimpleClasses,
4802   //    partOfGroups().pointer(),m_impl->isSimple,getOuterScope()?qPrint(getOuterScope()->name()):"<none>",b1,b2);
4803   return b1 || b2;  // either reason will do
4804 }
4805 
tagLessReference() const4806 const ClassDef *ClassDefImpl::tagLessReference() const
4807 {
4808   return m_impl->tagLessRef;
4809 }
4810 
setTagLessReference(const ClassDef * cd)4811 void ClassDefImpl::setTagLessReference(const ClassDef *cd)
4812 {
4813   m_impl->tagLessRef = cd;
4814 }
4815 
removeMemberFromLists(MemberDef * md)4816 void ClassDefImpl::removeMemberFromLists(MemberDef *md)
4817 {
4818   for (auto &ml : m_impl->memberLists)
4819   {
4820     ml->remove(md);
4821   }
4822 }
4823 
isJavaEnum() const4824 bool ClassDefImpl::isJavaEnum() const
4825 {
4826   return m_impl->isJavaEnum;
4827 }
4828 
setClassSpecifier(uint64 spec)4829 void ClassDefImpl::setClassSpecifier(uint64 spec)
4830 {
4831   m_impl->spec = spec;
4832 }
4833 
isExtension() const4834 bool ClassDefImpl::isExtension() const
4835 {
4836   QCString n = name();
4837   int si = n.find('(');
4838   int ei = n.find(')');
4839   bool b = ei>si && n.mid(si+1,ei-si-1).stripWhiteSpace().isEmpty();
4840   return b;
4841 }
4842 
usedFiles() const4843 const FileList &ClassDefImpl::usedFiles() const
4844 {
4845   return m_impl->files;
4846 }
4847 
typeConstraints() const4848 const ArgumentList &ClassDefImpl::typeConstraints() const
4849 {
4850   return m_impl->typeConstraints;
4851 }
4852 
getExamples() const4853 const ExampleList &ClassDefImpl::getExamples() const
4854 {
4855   return m_impl->examples;
4856 }
4857 
subGrouping() const4858 bool ClassDefImpl::subGrouping() const
4859 {
4860   return m_impl->subGrouping;
4861 }
4862 
isSliceLocal() const4863 bool ClassDefImpl::isSliceLocal() const
4864 {
4865   return m_impl->spec&Entry::Local;
4866 }
4867 
setName(const QCString & name)4868 void ClassDefImpl::setName(const QCString &name)
4869 {
4870   DefinitionMixin::setName(name);
4871 }
4872 
setMetaData(const QCString & md)4873 void ClassDefImpl::setMetaData(const QCString &md)
4874 {
4875   m_impl->metaData = md;
4876 }
4877 
collaborationGraphFileName() const4878 QCString ClassDefImpl::collaborationGraphFileName() const
4879 {
4880   return m_impl->collabFileName;
4881 }
4882 
inheritanceGraphFileName() const4883 QCString ClassDefImpl::inheritanceGraphFileName() const
4884 {
4885   return m_impl->inheritFileName;
4886 }
4887 
codeSymbolType() const4888 CodeSymbolType ClassDefImpl::codeSymbolType() const
4889 {
4890   switch (compoundType())
4891   {
4892     case Class:     return CodeSymbolType::Class;     break;
4893     case Struct:    return CodeSymbolType::Struct;    break;
4894     case Union:     return CodeSymbolType::Union;     break;
4895     case Interface: return CodeSymbolType::Interface; break;
4896     case Protocol:  return CodeSymbolType::Protocol;  break;
4897     case Category:  return CodeSymbolType::Category;  break;
4898     case Exception: return CodeSymbolType::Exception; break;
4899     case Service:   return CodeSymbolType::Service;   break;
4900     case Singleton: return CodeSymbolType::Singleton; break;
4901   }
4902   return CodeSymbolType::Class;
4903 }
4904 
4905 // --- Cast functions
4906 //
toClassDef(Definition * d)4907 ClassDef *toClassDef(Definition *d)
4908 {
4909   if (d && (typeid(*d)==typeid(ClassDefImpl) || typeid(*d)==typeid(ClassDefAliasImpl)))
4910   {
4911     return static_cast<ClassDef*>(d);
4912   }
4913   else
4914   {
4915     return 0;
4916   }
4917 }
4918 
toClassDef(DefinitionMutable * md)4919 ClassDef *toClassDef(DefinitionMutable *md)
4920 {
4921   Definition *d = toDefinition(md);
4922   if (d && typeid(*d)==typeid(ClassDefImpl))
4923   {
4924     return static_cast<ClassDef*>(d);
4925   }
4926   else
4927   {
4928     return 0;
4929   }
4930 }
4931 
toClassDef(const Definition * d)4932 const ClassDef *toClassDef(const Definition *d)
4933 {
4934   if (d && (typeid(*d)==typeid(ClassDefImpl) || typeid(*d)==typeid(ClassDefAliasImpl)))
4935   {
4936     return static_cast<const ClassDef*>(d);
4937   }
4938   else
4939   {
4940     return 0;
4941   }
4942 }
4943 
toClassDefMutable(Definition * d)4944 ClassDefMutable *toClassDefMutable(Definition *d)
4945 {
4946   if (d && typeid(*d)==typeid(ClassDefImpl))
4947   {
4948     return static_cast<ClassDefMutable*>(d);
4949   }
4950   else
4951   {
4952     return 0;
4953   }
4954 }
4955 
toClassDefMutable(const Definition * d)4956 ClassDefMutable *toClassDefMutable(const Definition *d)
4957 {
4958   if (d && typeid(*d)==typeid(ClassDefImpl))
4959   {
4960     return const_cast<ClassDefMutable*>(static_cast<const ClassDefMutable*>(d));
4961   }
4962   else
4963   {
4964     return 0;
4965   }
4966 }
4967 
4968 
4969 // --- Helpers
4970 
4971 /*! Get a class definition given its name.
4972  *  Returns 0 if the class is not found.
4973  */
getClass(const QCString & n)4974 ClassDef *getClass(const QCString &n)
4975 {
4976   if (n.isEmpty()) return 0;
4977   return Doxygen::classLinkedMap->find(n);
4978 }
4979 
hasVisibleRoot(const BaseClassList & bcl)4980 bool hasVisibleRoot(const BaseClassList &bcl)
4981 {
4982   for (const auto &bcd : bcl)
4983   {
4984     const ClassDef *cd=bcd.classDef;
4985     if (cd->isVisibleInHierarchy()) return true;
4986     if (hasVisibleRoot(cd->baseClasses())) return true;
4987   }
4988   return false;
4989 }
4990 
classHasVisibleChildren(const ClassDef * cd)4991 bool classHasVisibleChildren(const ClassDef *cd)
4992 {
4993   BaseClassList bcl;
4994 
4995   if (cd->getLanguage()==SrcLangExt_VHDL) // reverse baseClass/subClass relation
4996   {
4997     if (cd->baseClasses().empty()) return FALSE;
4998     bcl=cd->baseClasses();
4999   }
5000   else
5001   {
5002     if (cd->subClasses().empty()) return FALSE;
5003     bcl=cd->subClasses();
5004   }
5005 
5006   for (const auto &bcd : bcl)
5007   {
5008     if (bcd.classDef->isVisibleInHierarchy())
5009     {
5010       return TRUE;
5011     }
5012   }
5013   return FALSE;
5014 }
5015 
classVisibleInIndex(const ClassDef * cd)5016 bool classVisibleInIndex(const ClassDef *cd)
5017 {
5018   bool allExternals = Config_getBool(ALLEXTERNALS);
5019   return (allExternals && cd->isLinkable()) || cd->isLinkableInProject();
5020 }
5021 
5022 //----------------------------------------------------------------------
5023 // recursive function that returns the number of branches in the
5024 // inheritance tree that the base class 'bcd' is below the class 'cd'
5025 
minClassDistance(const ClassDef * cd,const ClassDef * bcd,int level)5026 int minClassDistance(const ClassDef *cd,const ClassDef *bcd,int level)
5027 {
5028   const int maxInheritanceDepth = 100000;
5029   if (bcd->categoryOf()) // use class that is being extended in case of
5030     // an Objective-C category
5031   {
5032     bcd=bcd->categoryOf();
5033   }
5034   if (cd==bcd) return level;
5035   if (level==256)
5036   {
5037     warn_uncond("class %s seem to have a recursive "
5038         "inheritance relation!\n",qPrint(cd->name()));
5039     return -1;
5040   }
5041   int m=maxInheritanceDepth;
5042   for (const auto &bcdi : cd->baseClasses())
5043   {
5044     int mc=minClassDistance(bcdi.classDef,bcd,level+1);
5045     if (mc<m) m=mc;
5046     if (m<0) break;
5047   }
5048   return m;
5049 }
5050 
classInheritedProtectionLevel(const ClassDef * cd,const ClassDef * bcd,Protection prot,int level)5051 Protection classInheritedProtectionLevel(const ClassDef *cd,const ClassDef *bcd,Protection prot,int level)
5052 {
5053   if (bcd->categoryOf()) // use class that is being extended in case of
5054     // an Objective-C category
5055   {
5056     bcd=bcd->categoryOf();
5057   }
5058   if (cd==bcd)
5059   {
5060     goto exit;
5061   }
5062   if (level==256)
5063   {
5064     err("Internal inconsistency: found class %s seem to have a recursive "
5065         "inheritance relation! Please send a bug report to doxygen@gmail.com\n",qPrint(cd->name()));
5066   }
5067   else if (prot!=Private)
5068   {
5069     for (const auto &bcdi : cd->baseClasses())
5070     {
5071       Protection baseProt = classInheritedProtectionLevel(bcdi.classDef,bcd,bcdi.prot,level+1);
5072       if (baseProt==Private)        prot=Private;
5073       else if (baseProt==Protected) prot=Protected;
5074     }
5075   }
5076 exit:
5077   //printf("classInheritedProtectionLevel(%s,%s)=%d\n",qPrint(cd->name()),qPrint(bcd->name()),prot);
5078   return prot;
5079 }
5080 
5081 
5082