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("+ </td><td>");
2905 else
2906 ol.writeString("- </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("+ </td><td class=\"entry\">");
2963 else
2964 ol.writeString("- </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,<1,<2);
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,<1,<3);
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