1 /******************************************************************************
2 *
3 * Copyright (C) 1997-2015 by Dimitri van Heesch.
4 *
5 * Permission to use, copy, modify, and distribute this software and its
6 * documentation under the terms of the GNU General Public License is hereby
7 * granted. No representations are made about the suitability of this software
8 * for any purpose. It is provided "as is" without express or implied warranty.
9 * See the GNU General Public License for more details.
10 *
11 * Documents produced by Doxygen are derivative works derived from the
12 * input used in their production; they are not affected by this license.
13 *
14 */
15
16
17 #include <stdio.h>
18 #include <assert.h>
19 #include <mutex>
20
21 #include "md5.h"
22 #include "memberdef.h"
23 #include "membername.h"
24 #include "doxygen.h"
25 #include "util.h"
26 #include "code.h"
27 #include "message.h"
28 #include "htmlhelp.h"
29 #include "language.h"
30 #include "outputlist.h"
31 #include "example.h"
32 #include "membergroup.h"
33 #include "groupdef.h"
34 #include "defargs.h"
35 #include "docparser.h"
36 #include "dot.h"
37 #include "dotcallgraph.h"
38 #include "searchindex.h"
39 #include "parserintf.h"
40 #include "vhdldocgen.h"
41 #include "arguments.h"
42 #include "memberlist.h"
43 #include "namespacedef.h"
44 #include "filedef.h"
45 #include "config.h"
46 #include "definitionimpl.h"
47 #include "regex.h"
48
49 //-----------------------------------------------------------------------------
50
51 class MemberDefImpl : public DefinitionMixin<MemberDefMutable>
52 {
53 public:
54 MemberDefImpl(const QCString &defFileName,int defLine,int defColumn,
55 const QCString &type,const QCString &name,const QCString &args,
56 const QCString &excp,Protection prot,Specifier virt,bool stat,
57 Relationship related,MemberType t,const ArgumentList &tal,
58 const ArgumentList &al,const QCString &metaData);
59 virtual ~MemberDefImpl();
60
definitionType() const61 virtual DefType definitionType() const { return TypeMember; }
resolveAlias()62 virtual MemberDef *resolveAlias() { return this; }
resolveAlias() const63 virtual const MemberDef *resolveAlias() const { return this; }
64 virtual CodeSymbolType codeSymbolType() const;
65 virtual MemberDef *deepCopy() const;
66 virtual void moveTo(Definition *);
67 virtual QCString getOutputFileBase() const;
68 virtual QCString getReference() const;
69 virtual QCString anchor() const;
70 virtual QCString declaration() const;
71 virtual QCString definition() const;
72 virtual QCString typeString() const;
73 virtual QCString argsString() const;
74 virtual QCString excpString() const;
75 virtual QCString bitfieldString() const;
76 virtual QCString extraTypeChars() const;
77 virtual const QCString &initializer() const;
78 virtual int initializerLines() const;
79 virtual uint64 getMemberSpecifiers() const;
80 virtual const MemberList *getSectionList(const Definition *) const;
81 virtual QCString displayDefinition() const;
82 virtual const ClassDef *getClassDef() const;
83 virtual const FileDef *getFileDef() const;
84 virtual const NamespaceDef* getNamespaceDef() const;
85 virtual const GroupDef *getGroupDef() const;
86 virtual ClassDef *accessorClass() const;
87 virtual QCString getReadAccessor() const;
88 virtual QCString getWriteAccessor() const;
89 virtual Grouping::GroupPri_t getGroupPri() const;
90 virtual QCString getGroupFileName() const;
91 virtual int getGroupStartLine() const;
92 virtual bool getGroupHasDocs() const;
93 virtual QCString qualifiedName() const;
94 virtual QCString objCMethodName(bool localLink,bool showStatic) const;
95 virtual Protection protection() const;
96 virtual Specifier virtualness(int count=0) const;
97 virtual MemberType memberType() const;
98 virtual QCString memberTypeName() const;
99 virtual bool isSignal() const;
100 virtual bool isSlot() const;
101 virtual bool isVariable() const;
102 virtual bool isEnumerate() const;
103 virtual bool isEnumValue() const;
104 virtual bool isTypedef() const;
105 virtual bool isSequence() const;
106 virtual bool isDictionary() const;
107 virtual bool isFunction() const;
108 virtual bool isFunctionPtr() const;
109 virtual bool isDefine() const;
110 virtual bool isFriend() const;
111 virtual bool isDCOP() const;
112 virtual bool isProperty() const;
113 virtual bool isEvent() const;
114 virtual bool isRelated() const;
115 virtual bool isForeign() const;
116 virtual bool isStatic() const;
117 virtual bool isInline() const;
118 virtual bool isExplicit() const;
119 virtual bool isMutable() const;
120 virtual bool isGettable() const;
121 virtual bool isPrivateGettable() const;
122 virtual bool isProtectedGettable() const;
123 virtual bool isSettable() const;
124 virtual bool isPrivateSettable() const;
125 virtual bool isProtectedSettable() const;
126 virtual bool isReadable() const;
127 virtual bool isWritable() const;
128 virtual bool isAddable() const;
129 virtual bool isRemovable() const;
130 virtual bool isRaisable() const;
131 virtual bool isFinal() const;
132 virtual bool isAbstract() const;
133 virtual bool isOverride() const;
134 virtual bool isInitonly() const;
135 virtual bool isOptional() const;
136 virtual bool isRequired() const;
137 virtual bool isNonAtomic() const;
138 virtual bool isCopy() const;
139 virtual bool isAssign() const;
140 virtual bool isRetain() const;
141 virtual bool isWeak() const;
142 virtual bool isStrong() const;
143 virtual bool isEnumStruct() const;
144 virtual bool isUnretained() const;
145 virtual bool isNew() const;
146 virtual bool isSealed() const;
147 virtual bool isImplementation() const;
148 virtual bool isExternal() const;
149 virtual bool isTypeAlias() const;
150 virtual bool isDefault() const;
151 virtual bool isDelete() const;
152 virtual bool isNoExcept() const;
153 virtual bool isAttribute() const;
154 virtual bool isUNOProperty() const;
155 virtual bool isReadonly() const;
156 virtual bool isBound() const;
157 virtual bool isConstrained() const;
158 virtual bool isTransient() const;
159 virtual bool isMaybeVoid() const;
160 virtual bool isMaybeDefault() const;
161 virtual bool isMaybeAmbiguous() const;
162 virtual bool isPublished() const;
163 virtual bool isTemplateSpecialization() const;
164 virtual bool isObjCMethod() const;
165 virtual bool isObjCProperty() const;
166 virtual bool isCSharpProperty() const;
167 virtual bool isConstructor() const;
168 virtual bool isDestructor() const;
169 virtual bool hasOneLineInitializer() const;
170 virtual bool hasMultiLineInitializer() const;
171 virtual bool showInCallGraph() const;
172 virtual bool isStrongEnumValue() const;
173 virtual bool livesInsideEnum() const;
174 virtual bool isSliceLocal() const;
175 virtual bool isConstExpr() const;
176 virtual int numberOfFlowKeyWords() const;
177 virtual bool isFriendToHide() const;
178 virtual bool isNotFriend() const;
179 virtual bool isFunctionOrSignalSlot() const;
180 virtual bool isRelatedOrFriend() const;
181 virtual bool isLinkableInProject() const;
182 virtual bool isLinkable() const;
183 virtual bool hasDocumentation() const;
184 virtual bool isDeleted() const;
185 virtual bool isBriefSectionVisible() const;
186 virtual bool isDetailedSectionVisible(MemberListContainer container) const;
187 virtual bool hasDetailedDescription() const;
188 virtual bool isFriendClass() const;
189 virtual bool isDocumentedFriendClass() const;
190 virtual const MemberDef *reimplements() const;
191 virtual const MemberVector &reimplementedBy() const;
192 virtual bool isReimplementedBy(const ClassDef *cd) const;
193 virtual ClassDef *relatedAlso() const;
194 virtual bool hasDocumentedEnumValues() const;
195 virtual const MemberDef *getAnonymousEnumType() const;
196 virtual bool isDocsForDefinition() const;
197 virtual const MemberDef *getEnumScope() const;
198 virtual const MemberVector &enumFieldList() const;
199 virtual void setEnumBaseType(const QCString &type);
200 virtual QCString enumBaseType() const;
201 virtual bool hasExamples() const;
202 virtual const ExampleList &getExamples() const;
203 virtual bool isPrototype() const;
204 virtual const ArgumentList &argumentList() const;
205 virtual ArgumentList &argumentList();
206 virtual const ArgumentList &declArgumentList() const;
207 virtual const ArgumentList &templateArguments() const;
208 virtual const ArgumentLists &definitionTemplateParameterLists() const;
209 virtual int getMemberGroupId() const;
210 virtual MemberGroup *getMemberGroup() const;
211 virtual bool fromAnonymousScope() const;
212 virtual bool anonymousDeclShown() const;
213 virtual MemberDef *fromAnonymousMember() const;
214 virtual bool hasCallGraph() const;
215 virtual bool hasCallerGraph() const;
216 virtual bool visibleMemberGroup(bool hideNoHeader) const;
217 virtual bool hasReferencesRelation() const;
218 virtual bool hasReferencedByRelation() const;
219 virtual const MemberDef *templateMaster() const;
220 virtual QCString getScopeString() const;
221 virtual ClassDef *getClassDefOfAnonymousType() const;
222 virtual bool isTypedefValCached() const;
223 virtual const ClassDef *getCachedTypedefVal() const;
224 virtual QCString getCachedTypedefTemplSpec() const;
225 virtual QCString getCachedResolvedTypedef() const;
226 virtual MemberDef *memberDefinition() const;
227 virtual MemberDef *memberDeclaration() const;
228 virtual const MemberDef *inheritsDocsFrom() const;
229 virtual const MemberDef *getGroupAlias() const;
230 virtual ClassDef *category() const;
231 virtual const MemberDef *categoryRelation() const;
232 virtual QCString displayName(bool=TRUE) const;
233 virtual QCString getDeclType() const;
234 virtual StringVector getLabels(const Definition *container) const;
235 virtual const ArgumentList &typeConstraints() const;
236 virtual QCString requiresClause() const;
237 virtual QCString documentation() const;
238 virtual QCString briefDescription(bool abbr=FALSE) const;
239 virtual QCString fieldType() const;
240 virtual bool isReference() const;
241 virtual QCString getDeclFileName() const;
242 virtual int getDeclLine() const;
243 virtual int getDeclColumn() const;
244 virtual void setMemberType(MemberType t);
245 virtual void setDefinition(const QCString &d);
246 virtual void setFileDef(const FileDef *fd);
247 virtual void setAnchor();
248 virtual void setProtection(Protection p);
249 virtual void setMemberSpecifiers(uint64 s);
250 virtual void mergeMemberSpecifiers(uint64 s);
251 virtual void setInitializer(const QCString &i);
252 virtual void setBitfields(const QCString &s);
253 virtual void setMaxInitLines(int lines);
254 virtual void setMemberClass(const ClassDef *cd);
255 virtual void setSectionList(const Definition *container,const MemberList *sl);
256 virtual void setGroupDef(const GroupDef *gd,Grouping::GroupPri_t pri,
257 const QCString &fileName,int startLine,bool hasDocs,
258 MemberDef *member=0);
259 virtual void setReadAccessor(const QCString &r);
260 virtual void setWriteAccessor(const QCString &w);
261 virtual void setTemplateSpecialization(bool b);
262 virtual void makeRelated();
263 virtual void makeForeign();
264 virtual void setInheritsDocsFrom(const MemberDef *md);
265 virtual void setTagInfo(const TagInfo *i);
266 virtual void setArgsString(const QCString &as);
267 virtual void setReimplements(const MemberDef *md);
268 virtual void insertReimplementedBy(const MemberDef *md);
269 virtual void setRelatedAlso(ClassDef *cd);
270 virtual void insertEnumField(const MemberDef *md);
271 virtual void setEnumScope(const MemberDef *md,bool livesInsideEnum=FALSE);
272 virtual void setEnumClassScope(const ClassDef *cd);
273 virtual void setDocumentedEnumValues(bool value);
274 virtual void setAnonymousEnumType(const MemberDef *md);
275 virtual bool addExample(const QCString &anchor,const QCString &name,const QCString &file);
276 virtual void setPrototype(bool p,const QCString &df,int line, int column);
277 virtual void setExplicitExternal(bool b,const QCString &df,int line,int column);
278 virtual void setDeclFile(const QCString &df,int line,int column);
279 virtual void moveArgumentList(std::unique_ptr<ArgumentList> al);
280 virtual void moveDeclArgumentList(std::unique_ptr<ArgumentList> al);
281 virtual void setDefinitionTemplateParameterLists(const ArgumentLists &lists);
282 virtual void setTypeConstraints(const ArgumentList &al);
283 virtual void setType(const QCString &t);
284 virtual void setAccessorType(ClassDef *cd,const QCString &t);
285 virtual void setNamespace(const NamespaceDef *nd);
286 virtual void setMemberGroup(MemberGroup *grp);
287 virtual void setMemberGroupId(int id);
288 virtual void makeImplementationDetail();
289 virtual void setFromAnonymousScope(bool b) const;
290 virtual void setFromAnonymousMember(MemberDef *m);
291 virtual void enableCallGraph(bool e);
292 virtual void enableCallerGraph(bool e);
293 virtual void enableReferencedByRelation(bool e);
294 virtual void enableReferencesRelation(bool e);
295 virtual void setTemplateMaster(const MemberDef *mt);
296 virtual void addListReference(Definition *d);
297 virtual void setDocsForDefinition(bool b);
298 virtual void setGroupAlias(const MemberDef *md);
299 virtual void cacheTypedefVal(const ClassDef *val,const QCString &templSpec,const QCString &resolvedType);
300 virtual void invalidateTypedefValCache();
301 virtual void invalidateCachedArgumentTypes();
302 virtual void setMemberDefinition(MemberDef *md);
303 virtual void setMemberDeclaration(MemberDef *md);
304 virtual void setAnonymousUsed() const;
305 virtual void copyArgumentNames(const MemberDef *bmd);
306 virtual void setCategory(ClassDef *);
307 virtual void setCategoryRelation(const MemberDef *);
308 virtual void setDocumentation(const QCString &d,const QCString &docFile,int docLine,bool stripWhiteSpace=TRUE);
309 virtual void setBriefDescription(const QCString &b,const QCString &briefFile,int briefLine);
310 virtual void setInbodyDocumentation(const QCString &d,const QCString &inbodyFile,int inbodyLine);
311 virtual void setHidden(bool b);
312 virtual void setRequiresClause(const QCString &req);
313 virtual void incrementFlowKeyWordCount();
314 virtual void writeDeclaration(OutputList &ol,
315 const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,
316 bool inGroup, int indentLevel,const ClassDef *inheritFrom=0,const QCString &inheritId=QCString()) const;
317 virtual void writeDocumentation(const MemberList *ml,int memCount,int memTotal,OutputList &ol,
318 const QCString &scopeName,const Definition *container,
319 bool inGroup,bool showEnumValues=FALSE,bool
320 showInline=FALSE) const;
321 virtual void writeMemberDocSimple(OutputList &ol,const Definition *container) const;
322 virtual void writeEnumDeclaration(OutputList &typeDecl,
323 const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd) const;
324 virtual void writeTagFile(TextStream &) const;
325 virtual void warnIfUndocumented() const;
326 virtual void warnIfUndocumentedParams() const;
327 virtual bool visibleInIndex() const;
328 virtual void detectUndocumentedParams(bool hasParamCommand,bool hasReturnCommand) const;
329 virtual MemberDefMutable *createTemplateInstanceMember(const ArgumentList &formalArgs,
330 const std::unique_ptr<ArgumentList> &actualArgs) const;
331 virtual void findSectionsInDocumentation();
332 virtual void writeLink(OutputList &ol,
333 const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,
334 bool onlyText=FALSE) const;
335 virtual void resolveUnnamedParameters(const MemberDef *md);
336
337 private:
338 void _computeLinkableInProject();
339 void _computeIsConstructor();
340 void _computeIsDestructor();
341 void _writeGroupInclude(OutputList &ol,bool inGroup) const;
342 void _writeMultiLineInitializer(OutputList &ol,const QCString &scopeName) const;
343 void _writeCallGraph(OutputList &ol) const;
344 void _writeCallerGraph(OutputList &ol) const;
345 void _writeReimplements(OutputList &ol) const;
346 bool _isReimplements() const;
347 void _writeReimplementedBy(OutputList &ol) const;
348 size_t _countReimplementedBy() const;
349 void _writeExamples(OutputList &ol) const;
350 void _writeTypeConstraints(OutputList &ol) const;
351 void _writeEnumValues(OutputList &ol,const Definition *container,
352 const QCString &cfname,const QCString &ciname,
353 const QCString &cname) const;
354 void _writeCategoryRelation(OutputList &ol) const;
355 void _writeTagData(const DefType) const;
356 void _writeTemplatePrefix(OutputList &ol, const Definition *def,
357 const ArgumentList &al, bool writeReqClause=true) const;
358 bool _hasVisibleCallGraph() const;
359 bool _hasVisibleCallerGraph() const;
360
361 // disable copying of member defs
362 MemberDefImpl(const MemberDefImpl &);
363 MemberDefImpl &operator=(const MemberDefImpl &);
364
365
366 // PIMPL idiom
367 class IMPL;
368 IMPL *m_impl;
369 uchar m_isLinkableCached; // 0 = not cached, 1=FALSE, 2=TRUE
370 uchar m_isConstructorCached; // 0 = not cached, 1=FALSE, 2=TRUE
371 uchar m_isDestructorCached; // 1 = not cached, 1=FALSE, 2=TRUE
372 };
373
createMemberDef(const QCString & defFileName,int defLine,int defColumn,const QCString & type,const QCString & name,const QCString & args,const QCString & excp,Protection prot,Specifier virt,bool stat,Relationship related,MemberType t,const ArgumentList & tal,const ArgumentList & al,const QCString & metaData)374 MemberDefMutable *createMemberDef(const QCString &defFileName,int defLine,int defColumn,
375 const QCString &type,const QCString &name,const QCString &args,
376 const QCString &excp,Protection prot,Specifier virt,bool stat,
377 Relationship related,MemberType t,const ArgumentList &tal,
378 const ArgumentList &al,const QCString &metaData)
379 {
380 return new MemberDefImpl(defFileName,defLine,defColumn,type,name,args,excp,prot,virt,
381 stat,related,t,tal,al,metaData);
382 }
383
384 //-----------------------------------------------------------------------------
385
386 class MemberDefAliasImpl : public DefinitionAliasMixin<MemberDef>
387 {
388 public:
MemberDefAliasImpl(const Definition * newScope,const MemberDef * md)389 MemberDefAliasImpl(const Definition *newScope,const MemberDef *md)
390 : DefinitionAliasMixin(newScope,md), m_memberGroup(0) { init(); }
~MemberDefAliasImpl()391 virtual ~MemberDefAliasImpl() { deinit(); }
definitionType() const392 virtual DefType definitionType() const { return TypeMember; }
393
getMdAlias() const394 const MemberDef *getMdAlias() const { return toMemberDef(getAlias()); }
resolveAlias()395 virtual MemberDef *resolveAlias() { return const_cast<MemberDef*>(getMdAlias()); }
resolveAlias() const396 virtual const MemberDef *resolveAlias() const { return getMdAlias(); }
397
deepCopy() const398 virtual MemberDef *deepCopy() const {
399 return createMemberDefAlias(getScope(),getMdAlias());
400 }
moveTo(Definition *)401 virtual void moveTo(Definition *) {}
402
name() const403 virtual QCString name() const
404 { return getMdAlias()->name(); }
codeSymbolType() const405 virtual CodeSymbolType codeSymbolType() const
406 { return getMdAlias()->codeSymbolType(); }
getOutputFileBase() const407 virtual QCString getOutputFileBase() const
408 { return getMdAlias()->getOutputFileBase(); }
getReference() const409 virtual QCString getReference() const
410 { return getMdAlias()->getReference(); }
anchor() const411 virtual QCString anchor() const
412 { return getMdAlias()->anchor(); }
declaration() const413 virtual QCString declaration() const
414 { return getMdAlias()->declaration(); }
definition() const415 virtual QCString definition() const
416 { return getMdAlias()->definition(); }
typeString() const417 virtual QCString typeString() const
418 { return getMdAlias()->typeString(); }
argsString() const419 virtual QCString argsString() const
420 { return getMdAlias()->argsString(); }
excpString() const421 virtual QCString excpString() const
422 { return getMdAlias()->excpString(); }
bitfieldString() const423 virtual QCString bitfieldString() const
424 { return getMdAlias()->bitfieldString(); }
extraTypeChars() const425 virtual QCString extraTypeChars() const
426 { return getMdAlias()->extraTypeChars(); }
initializer() const427 virtual const QCString &initializer() const
428 { return getMdAlias()->initializer(); }
initializerLines() const429 virtual int initializerLines() const
430 { return getMdAlias()->initializerLines(); }
getMemberSpecifiers() const431 virtual uint64 getMemberSpecifiers() const
432 { return getMdAlias()->getMemberSpecifiers(); }
getSectionList(const Definition * container) const433 virtual const MemberList *getSectionList(const Definition *container) const
434 { return getMdAlias()->getSectionList(container); }
displayDefinition() const435 virtual QCString displayDefinition() const
436 { return getMdAlias()->displayDefinition(); }
getClassDef() const437 virtual const ClassDef *getClassDef() const
438 { return getMdAlias()->getClassDef(); }
getFileDef() const439 virtual const FileDef *getFileDef() const
440 { return getMdAlias()->getFileDef(); }
getNamespaceDef() const441 virtual const NamespaceDef* getNamespaceDef() const
442 { return getMdAlias()->getNamespaceDef(); }
accessorClass() const443 virtual const ClassDef *accessorClass() const
444 { return getMdAlias()->accessorClass(); }
getReadAccessor() const445 virtual QCString getReadAccessor() const
446 { return getMdAlias()->getReadAccessor(); }
getWriteAccessor() const447 virtual QCString getWriteAccessor() const
448 { return getMdAlias()->getWriteAccessor(); }
getGroupDef() const449 virtual const GroupDef *getGroupDef() const
450 { return getMdAlias()->getGroupDef(); }
getGroupPri() const451 virtual Grouping::GroupPri_t getGroupPri() const
452 { return getMdAlias()->getGroupPri(); }
getGroupFileName() const453 virtual QCString getGroupFileName() const
454 { return getMdAlias()->getGroupFileName(); }
getGroupStartLine() const455 virtual int getGroupStartLine() const
456 { return getMdAlias()->getGroupStartLine(); }
getGroupHasDocs() const457 virtual bool getGroupHasDocs() const
458 { return getMdAlias()->getGroupHasDocs(); }
qualifiedName() const459 virtual QCString qualifiedName() const
460 { return getMdAlias()->qualifiedName(); }
objCMethodName(bool localLink,bool showStatic) const461 virtual QCString objCMethodName(bool localLink,bool showStatic) const
462 { return getMdAlias()->objCMethodName(localLink,showStatic); }
protection() const463 virtual Protection protection() const
464 { return getMdAlias()->protection(); }
virtualness(int count) const465 virtual Specifier virtualness(int count) const
466 { return getMdAlias()->virtualness(); }
memberType() const467 virtual MemberType memberType() const
468 { return getMdAlias()->memberType(); }
memberTypeName() const469 virtual QCString memberTypeName() const
470 { return getMdAlias()->memberTypeName(); }
isSignal() const471 virtual bool isSignal() const
472 { return getMdAlias()->isSignal(); }
isSlot() const473 virtual bool isSlot() const
474 { return getMdAlias()->isSlot(); }
isVariable() const475 virtual bool isVariable() const
476 { return getMdAlias()->isVariable(); }
isEnumerate() const477 virtual bool isEnumerate() const
478 { return getMdAlias()->isEnumerate(); }
isEnumValue() const479 virtual bool isEnumValue() const
480 { return getMdAlias()->isEnumValue(); }
isTypedef() const481 virtual bool isTypedef() const
482 { return getMdAlias()->isTypedef(); }
isSequence() const483 virtual bool isSequence() const
484 { return getMdAlias()->isSequence(); }
isDictionary() const485 virtual bool isDictionary() const
486 { return getMdAlias()->isDictionary(); }
isFunction() const487 virtual bool isFunction() const
488 { return getMdAlias()->isFunction(); }
isFunctionPtr() const489 virtual bool isFunctionPtr() const
490 { return getMdAlias()->isFunctionPtr(); }
isDefine() const491 virtual bool isDefine() const
492 { return getMdAlias()->isDefine(); }
isFriend() const493 virtual bool isFriend() const
494 { return getMdAlias()->isFriend(); }
isDCOP() const495 virtual bool isDCOP() const
496 { return getMdAlias()->isDCOP(); }
isProperty() const497 virtual bool isProperty() const
498 { return getMdAlias()->isProperty(); }
isEvent() const499 virtual bool isEvent() const
500 { return getMdAlias()->isEvent(); }
isRelated() const501 virtual bool isRelated() const
502 { return getMdAlias()->isRelated(); }
isForeign() const503 virtual bool isForeign() const
504 { return getMdAlias()->isForeign(); }
isStatic() const505 virtual bool isStatic() const
506 { return getMdAlias()->isStatic(); }
isInline() const507 virtual bool isInline() const
508 { return getMdAlias()->isInline(); }
isExplicit() const509 virtual bool isExplicit() const
510 { return getMdAlias()->isExplicit(); }
isMutable() const511 virtual bool isMutable() const
512 { return getMdAlias()->isMutable(); }
isGettable() const513 virtual bool isGettable() const
514 { return getMdAlias()->isGettable(); }
isPrivateGettable() const515 virtual bool isPrivateGettable() const
516 { return getMdAlias()->isPrivateGettable(); }
isProtectedGettable() const517 virtual bool isProtectedGettable() const
518 { return getMdAlias()->isProtectedGettable(); }
isSettable() const519 virtual bool isSettable() const
520 { return getMdAlias()->isSettable(); }
isPrivateSettable() const521 virtual bool isPrivateSettable() const
522 { return getMdAlias()->isPrivateSettable(); }
isProtectedSettable() const523 virtual bool isProtectedSettable() const
524 { return getMdAlias()->isProtectedSettable(); }
isReadable() const525 virtual bool isReadable() const
526 { return getMdAlias()->isReadable(); }
isWritable() const527 virtual bool isWritable() const
528 { return getMdAlias()->isWritable(); }
isAddable() const529 virtual bool isAddable() const
530 { return getMdAlias()->isAddable(); }
isRemovable() const531 virtual bool isRemovable() const
532 { return getMdAlias()->isRemovable(); }
isRaisable() const533 virtual bool isRaisable() const
534 { return getMdAlias()->isRaisable(); }
isFinal() const535 virtual bool isFinal() const
536 { return getMdAlias()->isFinal(); }
isAbstract() const537 virtual bool isAbstract() const
538 { return getMdAlias()->isAbstract(); }
isOverride() const539 virtual bool isOverride() const
540 { return getMdAlias()->isOverride(); }
isInitonly() const541 virtual bool isInitonly() const
542 { return getMdAlias()->isInitonly(); }
isOptional() const543 virtual bool isOptional() const
544 { return getMdAlias()->isOptional(); }
isRequired() const545 virtual bool isRequired() const
546 { return getMdAlias()->isRequired(); }
isNonAtomic() const547 virtual bool isNonAtomic() const
548 { return getMdAlias()->isNonAtomic(); }
isCopy() const549 virtual bool isCopy() const
550 { return getMdAlias()->isCopy(); }
isAssign() const551 virtual bool isAssign() const
552 { return getMdAlias()->isAssign(); }
isRetain() const553 virtual bool isRetain() const
554 { return getMdAlias()->isRetain(); }
isWeak() const555 virtual bool isWeak() const
556 { return getMdAlias()->isWeak(); }
isStrong() const557 virtual bool isStrong() const
558 { return getMdAlias()->isStrong(); }
isEnumStruct() const559 virtual bool isEnumStruct() const
560 { return getMdAlias()->isEnumStruct(); }
isUnretained() const561 virtual bool isUnretained() const
562 { return getMdAlias()->isUnretained(); }
isNew() const563 virtual bool isNew() const
564 { return getMdAlias()->isNew(); }
isSealed() const565 virtual bool isSealed() const
566 { return getMdAlias()->isSealed(); }
isImplementation() const567 virtual bool isImplementation() const
568 { return getMdAlias()->isImplementation(); }
isExternal() const569 virtual bool isExternal() const
570 { return getMdAlias()->isExternal(); }
isTypeAlias() const571 virtual bool isTypeAlias() const
572 { return getMdAlias()->isTypeAlias(); }
isDefault() const573 virtual bool isDefault() const
574 { return getMdAlias()->isDefault(); }
isDelete() const575 virtual bool isDelete() const
576 { return getMdAlias()->isDelete(); }
isNoExcept() const577 virtual bool isNoExcept() const
578 { return getMdAlias()->isNoExcept(); }
isAttribute() const579 virtual bool isAttribute() const
580 { return getMdAlias()->isAttribute(); }
isUNOProperty() const581 virtual bool isUNOProperty() const
582 { return getMdAlias()->isUNOProperty(); }
isReadonly() const583 virtual bool isReadonly() const
584 { return getMdAlias()->isReadable(); }
isBound() const585 virtual bool isBound() const
586 { return getMdAlias()->isBound(); }
isConstrained() const587 virtual bool isConstrained() const
588 { return getMdAlias()->isConstrained(); }
isTransient() const589 virtual bool isTransient() const
590 { return getMdAlias()->isTransient(); }
isMaybeVoid() const591 virtual bool isMaybeVoid() const
592 { return getMdAlias()->isMaybeVoid(); }
isMaybeDefault() const593 virtual bool isMaybeDefault() const
594 { return getMdAlias()->isMaybeDefault(); }
isMaybeAmbiguous() const595 virtual bool isMaybeAmbiguous() const
596 { return getMdAlias()->isMaybeAmbiguous(); }
isPublished() const597 virtual bool isPublished() const
598 { return getMdAlias()->isPublished(); }
isTemplateSpecialization() const599 virtual bool isTemplateSpecialization() const
600 { return getMdAlias()->isTemplateSpecialization(); }
isObjCMethod() const601 virtual bool isObjCMethod() const
602 { return getMdAlias()->isObjCMethod(); }
isObjCProperty() const603 virtual bool isObjCProperty() const
604 { return getMdAlias()->isObjCProperty(); }
isCSharpProperty() const605 virtual bool isCSharpProperty() const
606 { return getMdAlias()->isCSharpProperty(); }
isConstructor() const607 virtual bool isConstructor() const
608 { return getMdAlias()->isConstructor(); }
isDestructor() const609 virtual bool isDestructor() const
610 { return getMdAlias()->isDestructor(); }
hasOneLineInitializer() const611 virtual bool hasOneLineInitializer() const
612 { return getMdAlias()->hasOneLineInitializer(); }
hasMultiLineInitializer() const613 virtual bool hasMultiLineInitializer() const
614 { return getMdAlias()->hasMultiLineInitializer(); }
showInCallGraph() const615 virtual bool showInCallGraph() const
616 { return getMdAlias()->showInCallGraph(); }
isStrongEnumValue() const617 virtual bool isStrongEnumValue() const
618 { return getMdAlias()->isStrongEnumValue(); }
livesInsideEnum() const619 virtual bool livesInsideEnum() const
620 { return getMdAlias()->livesInsideEnum(); }
isSliceLocal() const621 virtual bool isSliceLocal() const
622 { return getMdAlias()->isSliceLocal(); }
isConstExpr() const623 virtual bool isConstExpr() const
624 { return getMdAlias()->isConstExpr(); }
numberOfFlowKeyWords() const625 virtual int numberOfFlowKeyWords() const
626 { return getMdAlias()->numberOfFlowKeyWords(); }
isFriendToHide() const627 virtual bool isFriendToHide() const
628 { return getMdAlias()->isFriendToHide(); }
isNotFriend() const629 virtual bool isNotFriend() const
630 { return getMdAlias()->isNotFriend(); }
isFunctionOrSignalSlot() const631 virtual bool isFunctionOrSignalSlot() const
632 { return getMdAlias()->isFunctionOrSignalSlot(); }
isRelatedOrFriend() const633 virtual bool isRelatedOrFriend() const
634 { return getMdAlias()->isRelatedOrFriend(); }
isLinkableInProject() const635 virtual bool isLinkableInProject() const
636 { return getMdAlias()->isLinkableInProject(); }
isLinkable() const637 virtual bool isLinkable() const
638 { return getMdAlias()->isLinkable(); }
hasDocumentation() const639 virtual bool hasDocumentation() const
640 { return getMdAlias()->hasDocumentation(); }
isDeleted() const641 virtual bool isDeleted() const
642 { return getMdAlias()->isDeleted(); }
isBriefSectionVisible() const643 virtual bool isBriefSectionVisible() const
644 { return getMdAlias()->isBriefSectionVisible(); }
isDetailedSectionVisible(MemberListContainer container) const645 virtual bool isDetailedSectionVisible(MemberListContainer container) const
646 { return getMdAlias()->isDetailedSectionVisible(container); }
hasDetailedDescription() const647 virtual bool hasDetailedDescription() const
648 { return getMdAlias()->hasDetailedDescription(); }
isFriendClass() const649 virtual bool isFriendClass() const
650 { return getMdAlias()->isFriendClass(); }
isDocumentedFriendClass() const651 virtual bool isDocumentedFriendClass() const
652 { return getMdAlias()->isDocumentedFriendClass(); }
reimplements() const653 virtual const MemberDef *reimplements() const
654 { return getMdAlias()->reimplements(); }
reimplementedBy() const655 virtual const MemberVector &reimplementedBy() const
656 { return getMdAlias()->reimplementedBy(); }
isReimplementedBy(const ClassDef * cd) const657 virtual bool isReimplementedBy(const ClassDef *cd) const
658 { return getMdAlias()->isReimplementedBy(cd); }
relatedAlso() const659 virtual ClassDef *relatedAlso() const
660 { return getMdAlias()->relatedAlso(); }
hasDocumentedEnumValues() const661 virtual bool hasDocumentedEnumValues() const
662 { return getMdAlias()->hasDocumentedEnumValues(); }
getAnonymousEnumType() const663 virtual const MemberDef *getAnonymousEnumType() const
664 { return getMdAlias()->getAnonymousEnumType(); }
isDocsForDefinition() const665 virtual bool isDocsForDefinition() const
666 { return getMdAlias()->isDocsForDefinition(); }
getEnumScope() const667 virtual const MemberDef *getEnumScope() const
668 { return getMdAlias()->getEnumScope(); }
enumFieldList() const669 virtual const MemberVector &enumFieldList() const
670 { return getMdAlias()->enumFieldList(); }
enumBaseType() const671 virtual QCString enumBaseType() const
672 { return getMdAlias()->enumBaseType(); }
hasExamples() const673 virtual bool hasExamples() const
674 { return getMdAlias()->hasExamples(); }
getExamples() const675 virtual const ExampleList &getExamples() const
676 { return getMdAlias()->getExamples(); }
isPrototype() const677 virtual bool isPrototype() const
678 { return getMdAlias()->isPrototype(); }
argumentList() const679 virtual const ArgumentList &argumentList() const
680 { return getMdAlias()->argumentList(); }
declArgumentList() const681 virtual const ArgumentList &declArgumentList() const
682 { return getMdAlias()->declArgumentList(); }
templateArguments() const683 virtual const ArgumentList &templateArguments() const
684 { return getMdAlias()->templateArguments(); }
definitionTemplateParameterLists() const685 virtual const ArgumentLists &definitionTemplateParameterLists() const
686 { return getMdAlias()->definitionTemplateParameterLists(); }
getMemberGroupId() const687 virtual int getMemberGroupId() const
688 { return getMdAlias()->getMemberGroupId(); }
getMemberGroup() const689 virtual MemberGroup *getMemberGroup() const
690 { return m_memberGroup; }
fromAnonymousScope() const691 virtual bool fromAnonymousScope() const
692 { return getMdAlias()->fromAnonymousScope(); }
anonymousDeclShown() const693 virtual bool anonymousDeclShown() const
694 { return getMdAlias()->anonymousDeclShown(); }
fromAnonymousMember() const695 virtual MemberDef *fromAnonymousMember() const
696 { return getMdAlias()->fromAnonymousMember(); }
hasCallGraph() const697 virtual bool hasCallGraph() const
698 { return getMdAlias()->hasCallGraph(); }
hasCallerGraph() const699 virtual bool hasCallerGraph() const
700 { return getMdAlias()->hasCallerGraph(); }
visibleMemberGroup(bool hideNoHeader) const701 virtual bool visibleMemberGroup(bool hideNoHeader) const
702 { return getMdAlias()->visibleMemberGroup(hideNoHeader); }
hasReferencesRelation() const703 virtual bool hasReferencesRelation() const
704 { return getMdAlias()->hasReferencesRelation(); }
hasReferencedByRelation() const705 virtual bool hasReferencedByRelation() const
706 { return getMdAlias()->hasReferencedByRelation(); }
templateMaster() const707 virtual const MemberDef *templateMaster() const
708 { return getMdAlias()->templateMaster(); }
getScopeString() const709 virtual QCString getScopeString() const
710 { return getMdAlias()->getScopeString(); }
getClassDefOfAnonymousType() const711 virtual ClassDef *getClassDefOfAnonymousType() const
712 { return getMdAlias()->getClassDefOfAnonymousType(); }
isTypedefValCached() const713 virtual bool isTypedefValCached() const
714 { return getMdAlias()->isTypedefValCached(); }
getCachedTypedefVal() const715 virtual const ClassDef *getCachedTypedefVal() const
716 { return getMdAlias()->getCachedTypedefVal(); }
getCachedTypedefTemplSpec() const717 virtual QCString getCachedTypedefTemplSpec() const
718 { return getMdAlias()->getCachedTypedefTemplSpec(); }
getCachedResolvedTypedef() const719 virtual QCString getCachedResolvedTypedef() const
720 { return getMdAlias()->getCachedResolvedTypedef(); }
memberDefinition() const721 virtual MemberDef *memberDefinition() const
722 { return getMdAlias()->memberDefinition(); }
memberDeclaration() const723 virtual MemberDef *memberDeclaration() const
724 { return getMdAlias()->memberDeclaration(); }
inheritsDocsFrom() const725 virtual const MemberDef *inheritsDocsFrom() const
726 { return getMdAlias()->inheritsDocsFrom(); }
getGroupAlias() const727 virtual const MemberDef *getGroupAlias() const
728 { return getMdAlias()->getGroupAlias(); }
category() const729 virtual ClassDef *category() const
730 { return getMdAlias()->category(); }
categoryRelation() const731 virtual const MemberDef *categoryRelation() const
732 { return getMdAlias()->categoryRelation(); }
displayName(bool b=TRUE) const733 virtual QCString displayName(bool b=TRUE) const
734 { return getMdAlias()->displayName(b); }
getDeclType() const735 virtual QCString getDeclType() const
736 { return getMdAlias()->getDeclType(); }
getLabels(const Definition * container) const737 virtual StringVector getLabels(const Definition *container) const
738 { return getMdAlias()->getLabels(container); }
typeConstraints() const739 virtual const ArgumentList &typeConstraints() const
740 { return getMdAlias()->typeConstraints(); }
documentation() const741 virtual QCString documentation() const
742 { return getMdAlias()->documentation(); }
briefDescription(bool abbr=FALSE) const743 virtual QCString briefDescription(bool abbr=FALSE) const
744 { return getMdAlias()->briefDescription(); }
fieldType() const745 virtual QCString fieldType() const
746 { return getMdAlias()->fieldType(); }
isReference() const747 virtual bool isReference() const
748 { return getMdAlias()->isReference(); }
getDeclFileName() const749 virtual QCString getDeclFileName() const
750 { return getMdAlias()->getDeclFileName(); }
getDeclLine() const751 virtual int getDeclLine() const
752 { return getMdAlias()->getDeclLine(); }
getDeclColumn() const753 virtual int getDeclColumn() const
754 { return getMdAlias()->getDeclColumn(); }
requiresClause() const755 virtual QCString requiresClause() const
756 { return getMdAlias()->requiresClause(); }
visibleInIndex() const757 virtual bool visibleInIndex() const
758 { return getMdAlias()->visibleInIndex(); }
759
warnIfUndocumented() const760 virtual void warnIfUndocumented() const {}
warnIfUndocumentedParams() const761 virtual void warnIfUndocumentedParams() const {}
detectUndocumentedParams(bool hasParamCommand,bool hasReturnCommand) const762 virtual void detectUndocumentedParams(bool hasParamCommand,bool hasReturnCommand) const {}
setMemberGroup(MemberGroup * grp)763 virtual void setMemberGroup(MemberGroup *grp) { m_memberGroup = grp; }
createTemplateInstanceMember(const ArgumentList & formalArgs,const std::unique_ptr<ArgumentList> & actualArgs) const764 virtual MemberDefMutable *createTemplateInstanceMember(const ArgumentList &formalArgs,
765 const std::unique_ptr<ArgumentList> &actualArgs) const
766 { return getMdAlias()->createTemplateInstanceMember(formalArgs,actualArgs); }
767
writeDeclaration(OutputList & ol,const ClassDef * cd,const NamespaceDef * nd,const FileDef * fd,const GroupDef * gd,bool inGroup,int indentLevel,const ClassDef * inheritFrom=0,const QCString & inheritId=QCString ()) const768 virtual void writeDeclaration(OutputList &ol,
769 const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,
770 bool inGroup, int indentLevel, const ClassDef *inheritFrom=0,const QCString &inheritId=QCString()) const
771 {
772 getMdAlias()->writeDeclaration(ol,cd,nd,fd,gd,inGroup,indentLevel,inheritFrom,inheritId);
773 }
writeEnumDeclaration(OutputList & typeDecl,const ClassDef * cd,const NamespaceDef * nd,const FileDef * fd,const GroupDef * gd) const774 virtual void writeEnumDeclaration(OutputList &typeDecl,
775 const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd) const
776 {
777 getMdAlias()->writeEnumDeclaration(typeDecl,cd,nd,fd,gd);
778 }
779 private:
780 MemberGroup *m_memberGroup; // group's member definition
781 };
782
783
createMemberDefAlias(const Definition * newScope,const MemberDef * aliasMd)784 MemberDef *createMemberDefAlias(const Definition *newScope,const MemberDef *aliasMd)
785 {
786 MemberDef *amd = new MemberDefAliasImpl(newScope,aliasMd);
787 //printf("amd: name=%s displayName=%s\n",qPrint(amd->name()),qPrint(amd->displayName()));
788 return amd;
789 }
790
791 //-----------------------------------------------------------------------------
792
addTemplateNames(const QCString & s,const QCString & n,const QCString & t)793 static QCString addTemplateNames(const QCString &s,const QCString &n,const QCString &t)
794 {
795 QCString result;
796 QCString clRealName=n;
797 int p=0,i;
798 if ((i=clRealName.find('<'))!=-1)
799 {
800 clRealName=clRealName.left(i); // strip template specialization
801 }
802 if ((i=clRealName.findRev("::"))!=-1)
803 {
804 clRealName=clRealName.right(clRealName.length()-i-2);
805 }
806 while ((i=s.find(clRealName,p))!=-1)
807 {
808 result+=s.mid(p,i-p);
809 uint j=clRealName.length()+i;
810 if (s.length()==j || (s.at(j)!='<' && !isId(s.at(j))))
811 { // add template names
812 //printf("Adding %s+%s\n",qPrint(clRealName),qPrint(t));
813 result+=clRealName+t;
814 }
815 else
816 { // template names already present
817 //printf("Adding %s\n",qPrint(clRealName));
818 result+=clRealName;
819 }
820 p=i+clRealName.length();
821 }
822 result+=s.right(s.length()-p);
823 //printf("addTemplateNames(%s,%s,%s)=%s\n",qPrint(s),qPrint(n),qPrint(t),qPrint(result));
824 return result;
825 }
826
827 // ol.startMemberDocName has already been done before this is called.
828 // when this function returns TRUE, ol.endParameterList will be called.
829 //
830 // typical sequence:
831 // ol.startMemberDoc
832 // ol.startMemberDocName
833 // --- enter writeDefArgumentList
834 // ol.endMemberDocName
835 // ol.startParameterList
836 // ...
837 // ol.startParameterType(first=TRUE)
838 // ol.endParameterType
839 // ol.startParameterName
840 // ol.endParameterName(last==FALSE)
841 // ...
842 // ol.startParameterType(first=FALSE)
843 // ol.endParameterType
844 // ol.startParameterName
845 // ol.endParameterName(last==TRUE)
846 // ...
847 // --- leave writeDefArgumentList with return value TRUE
848 // ol.endParameterList
849 // ol.endMemberDoc(hasArgs=TRUE)
850 //
851 // For an empty list the function should return FALSE, the sequence is
852 // ol.startMemberDoc
853 // ol.startMemberDocName
854 // --- enter writeDefArgumentList
855 // --- leave writeDefArgumentList with return value FALSE
856 // ol.endMemberDocName
857 // ol.endMemberDoc(hasArgs=FALSE);
858 //
859
writeDefArgumentList(OutputList & ol,const Definition * scope,const MemberDef * md)860 static bool writeDefArgumentList(OutputList &ol,const Definition *scope,const MemberDef *md)
861 {
862 const ArgumentList &defArgList=(md->isDocsForDefinition()) ?
863 md->argumentList() : md->declArgumentList();
864 //printf("writeDefArgumentList '%s' isDocsForDefinition()=%d\n",qPrint(md->name()),md->isDocsForDefinition());
865 if (!defArgList.hasParameters() || md->isProperty() || md->isTypedef())
866 {
867 return FALSE; // member has no function like argument list
868 }
869
870 if (!md->isDefine()) ol.docify(" ");
871
872 //printf("writeDefArgList(%d)\n",defArgList->count());
873 ol.pushGeneratorState();
874 //ol.disableAllBut(OutputGenerator::Html);
875 bool htmlOn = ol.isEnabled(OutputGenerator::Html);
876 bool latexOn = ol.isEnabled(OutputGenerator::Latex);
877 bool docbookOn = ol.isEnabled(OutputGenerator::Docbook);
878 {
879 // html and latex
880 if (htmlOn) ol.enable(OutputGenerator::Html);
881 if (latexOn) ol.enable(OutputGenerator::Latex);
882 if (docbookOn) ol.enable(OutputGenerator::Docbook);
883
884 ol.endMemberDocName();
885 ol.startParameterList(!md->isObjCMethod());
886 }
887 ol.enableAll();
888 ol.disable(OutputGenerator::Html);
889 ol.disable(OutputGenerator::Latex);
890 ol.disable(OutputGenerator::Docbook);
891 {
892 // other formats
893 if (!md->isObjCMethod()) ol.docify("("); // start argument list
894 ol.endMemberDocName();
895 }
896 ol.popGeneratorState();
897 //printf("===> name=%s isDefine=%d\n",qPrint(md->name()),md->isDefine());
898
899 QCString cName;
900 if (scope)
901 {
902 cName=scope->name();
903 int il=cName.find('<');
904 int ir=cName.findRev('>');
905 if (il!=-1 && ir!=-1 && ir>il)
906 {
907 cName=cName.mid(il,ir-il+1);
908 //printf("1. cName=%s\n",qPrint(cName));
909 }
910 else if (scope->definitionType()==Definition::TypeClass)
911 {
912 cName=tempArgListToString((toClassDef(scope))->templateArguments(),
913 scope->getLanguage());
914 //printf("2. cName=%s\n",qPrint(cName));
915 }
916 else // no template specifier
917 {
918 cName.resize(0);
919 }
920 }
921 //printf("~~~ %s cName=%s\n",qPrint(md->name()),qPrint(cName));
922
923 bool first=TRUE;
924 bool paramTypeStarted=FALSE;
925 bool isDefine = md->isDefine();
926 auto alIt = defArgList.begin();
927 while (alIt!=defArgList.end())
928 {
929 Argument a = *alIt;
930 if (isDefine || first)
931 {
932 ol.startParameterType(first,QCString());
933 paramTypeStarted=TRUE;
934 if (isDefine)
935 {
936 ol.endParameterType();
937 ol.startParameterName(TRUE);
938 }
939 }
940
941 if (!a.attrib.isEmpty() && !md->isObjCMethod()) // argument has an IDL attribute
942 {
943 ol.docify(a.attrib+" ");
944 }
945
946 {
947 QCString n=a.type;
948 if (md->isObjCMethod()) { n.prepend("("); n.append(")"); }
949 if (a.type!="...")
950 {
951 if (!cName.isEmpty()) n=addTemplateNames(n,scope->name(),cName);
952 linkifyText(TextGeneratorOLImpl(ol),scope,md->getBodyDef(),md,n);
953 }
954 }
955
956 if (!isDefine)
957 {
958 if (paramTypeStarted)
959 {
960 ol.endParameterType();
961 paramTypeStarted=FALSE;
962 }
963 ol.startParameterName(defArgList.size()<2);
964 }
965 if (!a.name.isEmpty() || a.type=="...") // argument has a name
966 {
967 ol.disable(OutputGenerator::Latex);
968 ol.disable(OutputGenerator::Docbook);
969 ol.disable(OutputGenerator::Html);
970 ol.docify(" "); /* man page */
971 if (htmlOn) ol.enable(OutputGenerator::Html);
972 ol.disable(OutputGenerator::Man);
973 ol.startEmphasis();
974 ol.enable(OutputGenerator::Man);
975 if (latexOn) ol.enable(OutputGenerator::Latex);
976 if (docbookOn) ol.enable(OutputGenerator::Docbook);
977 if (a.name.isEmpty()) ol.docify(a.type); else ol.docify(a.name);
978 ol.disable(OutputGenerator::Man);
979 ol.disable(OutputGenerator::Latex);
980 ol.disable(OutputGenerator::Docbook);
981 ol.endEmphasis();
982 ol.enable(OutputGenerator::Man);
983 if (latexOn) ol.enable(OutputGenerator::Latex);
984 if (docbookOn) ol.enable(OutputGenerator::Docbook);
985 }
986 if (!a.array.isEmpty())
987 {
988 ol.docify(a.array);
989 }
990 if (!a.defval.isEmpty()) // write the default value
991 {
992 QCString n=a.defval;
993 if (!cName.isEmpty()) n=addTemplateNames(n,scope->name(),cName);
994 ol.docify(" = ");
995
996 ol.startTypewriter();
997 linkifyText(TextGeneratorOLImpl(ol),scope,md->getBodyDef(),md,n,FALSE,TRUE,TRUE);
998 ol.endTypewriter();
999
1000 }
1001 ++alIt;
1002 if (alIt!=defArgList.end())
1003 {
1004 a = *alIt;
1005 if (!md->isObjCMethod()) ol.docify(", "); // there are more arguments
1006 if (!isDefine)
1007 {
1008 QCString key;
1009 if (md->isObjCMethod() && a.attrib.length()>=2)
1010 {
1011 //printf("Found parameter keyword %s\n",a.qPrint(attrib));
1012 // strip [ and ]
1013 key=a.attrib.mid(1,a.attrib.length()-2);
1014 if (key!=",") key+=":"; // for normal keywords add colon
1015 }
1016 ol.endParameterName(FALSE,FALSE,!md->isObjCMethod());
1017 if (paramTypeStarted)
1018 {
1019 ol.endParameterType();
1020 }
1021 ol.startParameterType(FALSE,key);
1022 paramTypeStarted=TRUE;
1023 }
1024 else // isDefine
1025 {
1026 ol.endParameterName(FALSE,FALSE,TRUE);
1027 }
1028 }
1029 first=FALSE;
1030 }
1031 ol.pushGeneratorState();
1032 ol.disable(OutputGenerator::Html);
1033 ol.disable(OutputGenerator::Latex);
1034 ol.disable(OutputGenerator::Docbook);
1035 if (!md->isObjCMethod()) ol.docify(")"); // end argument list
1036 ol.enableAll();
1037 if (htmlOn) ol.enable(OutputGenerator::Html);
1038 if (latexOn) ol.enable(OutputGenerator::Latex);
1039 if (docbookOn) ol.enable(OutputGenerator::Docbook);
1040 if (first) ol.startParameterName(defArgList.size()<2);
1041 ol.endParameterName(TRUE,defArgList.size()<2,!md->isObjCMethod());
1042 ol.popGeneratorState();
1043 if (!md->extraTypeChars().isEmpty())
1044 {
1045 ol.docify(md->extraTypeChars());
1046 }
1047 if (defArgList.constSpecifier())
1048 {
1049 ol.docify(" const");
1050 }
1051 if (defArgList.volatileSpecifier())
1052 {
1053 ol.docify(" volatile");
1054 }
1055 if (defArgList.refQualifier()==RefQualifierLValue)
1056 {
1057 ol.docify(" &");
1058 }
1059 else if (defArgList.refQualifier()==RefQualifierRValue)
1060 {
1061 ol.docify(" &&");
1062 }
1063 if (!defArgList.trailingReturnType().isEmpty())
1064 {
1065 linkifyText(TextGeneratorOLImpl(ol), // out
1066 scope, // scope
1067 md->getBodyDef(), // fileScope
1068 md, // self
1069 defArgList.trailingReturnType(), // text
1070 FALSE // autoBreak
1071 );
1072
1073 }
1074 return TRUE;
1075 }
1076
writeExceptionListImpl(OutputList & ol,const ClassDef * cd,const MemberDef * md,QCString const & exception)1077 static void writeExceptionListImpl(
1078 OutputList &ol, const ClassDef *cd, const MemberDef *md, QCString const& exception)
1079 {
1080 // this is ordinary exception spec - there must be a '('
1081 //printf("exception='%s'\n",qPrint(exception));
1082 int index = exception.find('(');
1083 if (index!=-1)
1084 {
1085 ol.exceptionEntry(exception.left(index),false);
1086 ++index; // paren in second column so skip it here
1087 for (int comma = exception.find(',', index); comma!=-1; )
1088 {
1089 ++comma; // include comma
1090 linkifyText(TextGeneratorOLImpl(ol),cd,md->getBodyDef(),md,
1091 exception.mid(index,comma-index));
1092 ol.exceptionEntry(QCString(),false);
1093 index=comma;
1094 comma = exception.find(',', index);
1095 }
1096 int close = exception.find(')', index);
1097 if (close!=-1)
1098 {
1099 QCString type=removeRedundantWhiteSpace(exception.mid(index,close-index));
1100 linkifyText(TextGeneratorOLImpl(ol),cd,md->getBodyDef(),md,type);
1101 ol.exceptionEntry(QCString(),true);
1102 }
1103 else
1104 {
1105 warn(md->getDefFileName(),md->getDefLine(),
1106 "missing ) in exception list on member %s",qPrint(md->name()));
1107 }
1108 }
1109 else // Java Exception
1110 {
1111 ol.docify(" ");
1112 linkifyText(TextGeneratorOLImpl(ol),cd,md->getBodyDef(),md,exception);
1113 }
1114 }
1115
writeExceptionList(OutputList & ol,const ClassDef * cd,const MemberDef * md)1116 static void writeExceptionList(OutputList &ol, const ClassDef *cd, const MemberDef *md)
1117 {
1118 QCString exception(QCString(md->excpString()).stripWhiteSpace());
1119 if ('{'==exception.at(0))
1120 {
1121 // this is an UNO IDL attribute - need special handling
1122 int index = exception.find(';');
1123 int oldIndex = 1;
1124 while (-1 != index) // there should be no more than 2 (set / get)
1125 {
1126 // omit '{' and ';' -> "set raises (...)"
1127 writeExceptionListImpl(ol,cd,md,exception.mid(oldIndex,index-oldIndex));
1128 oldIndex=index+1;
1129 index = exception.find(';',oldIndex);
1130 }
1131 // the rest is now just '}' - omit that
1132 }
1133 else
1134 {
1135 writeExceptionListImpl(ol,cd,md,exception);
1136 }
1137 }
1138
1139 //-----------------------------------------------------------------------------
1140 //-----------------------------------------------------------------------------
1141 //-----------------------------------------------------------------------------
1142
1143 class MemberDefImpl::IMPL
1144 {
1145 public:
1146 IMPL();
1147 ~IMPL();
1148 void init(Definition *def,const QCString &t,const QCString &a,const QCString &e,
1149 Protection p,Specifier v,bool s,Relationship r,
1150 MemberType mt,const ArgumentList &tal,
1151 const ArgumentList &al,const QCString &meta
1152 );
1153
1154 const ClassDef *classDef = 0; // member of or related to
1155 const FileDef *fileDef = 0; // member of file definition
1156 const NamespaceDef *nspace = 0; // the namespace this member is in.
1157
1158 const MemberDef *enumScope = 0; // the enclosing scope, if this is an enum field
1159 bool livesInsideEnum = false;
1160 const MemberDef *annEnumType = 0; // the anonymous enum that is the type of this member
1161 MemberVector enumFields; // enumeration fields
1162
1163 const MemberDef *redefines = 0; // the members that this member redefines
1164 MemberVector redefinedBy; // the list of members that redefine this one
1165
1166 MemberDef *memDef = 0; // member definition for this declaration
1167 MemberDef *memDec = 0; // member declaration for this definition
1168 ClassDef *relatedAlso = 0; // points to class marked by relatedAlso
1169
1170 ExampleList examples; // a dictionary of all examples for quick access
1171
1172 QCString type; // return actual type
1173 QCString accessorType; // return type that tell how to get to this member
1174 ClassDef *accessorClass = 0; // class that this member accesses (for anonymous types)
1175 QCString args; // function arguments/variable array specifiers
1176 QCString def; // member definition in code (fully qualified name)
1177 QCString anc; // HTML anchor name
1178 Specifier virt = Normal; // normal/virtual/pure virtual
1179 Protection prot = Public; // protection type [Public/Protected/Private]
1180 QCString decl; // member declaration in class
1181
1182 QCString bitfields; // struct member bitfields
1183 QCString read; // property read accessor
1184 QCString write; // property write accessor
1185 QCString exception; // exceptions that can be thrown
1186 QCString initializer; // initializer
1187 QCString extraTypeChars; // extra type info found after the argument list
1188 QCString enumBaseType; // base type of the enum (C++11)
1189 QCString requiresClause; // requires clause (C++20)
1190 int initLines = 0; // number of lines in the initializer
1191
1192 uint64 memSpec = 0; // The specifiers present for this member
1193 MemberType mtype = MemberType_Define; // returns the kind of member
1194 int maxInitLines = 0; // when the initializer will be displayed
1195 int userInitLines = 0; // result of explicit \hideinitializer or \showinitializer
1196 MemberDef *annMemb = 0;
1197
1198 ArgumentList defArgList; // argument list of this member definition
1199 ArgumentList declArgList; // argument list of this member declaration
1200
1201 ArgumentList tArgList; // template argument list of function template
1202 ArgumentList typeConstraints; // type constraints for template parameters
1203 const MemberDef *templateMaster;
1204 ArgumentLists defTmpArgLists; // lists of template argument lists
1205 // (for template functions in nested template classes)
1206
1207 QCString metaData; // Slice metadata.
1208
1209 ClassDef *cachedAnonymousType; // if the member has an anonymous compound
1210 // as its type then this is computed by
1211 // getClassDefOfAnonymousType() and
1212 // cached here.
1213 std::map<const Definition *,const MemberList *> sectionMap;
1214
1215 const MemberDef *groupAlias = 0; // Member containing the definition
1216 int grpId = 0; // group id
1217 MemberGroup *memberGroup = 0; // group's member definition
1218 const GroupDef *group = 0; // group in which this member is in
1219 Grouping::GroupPri_t grouppri; // priority of this definition
1220 QCString groupFileName; // file where this grouping was defined
1221 int groupStartLine = 0; // line " " " " "
1222 MemberDef *groupMember = 0;
1223
1224 bool isTypedefValCached = false;
1225 const ClassDef *cachedTypedefValue = 0;
1226 QCString cachedTypedefTemplSpec;
1227 QCString cachedResolvedType;
1228
1229 // inbody documentation
1230 //int inbodyLine;
1231 //QCString inbodyFile;
1232 //QCString inbodyDocs;
1233
1234 // documentation inheritance
1235 const MemberDef *docProvider = 0;
1236
1237 // to store the output file base from tag files
1238 QCString explicitOutputFileBase;
1239
1240 // objective-c
1241 bool implOnly = false; // function found in implementation but not
1242 // in the interface
1243 mutable bool hasDocumentedParams = false;
1244 mutable bool hasDocumentedReturnType = false;
1245 bool isDMember = false;
1246 Relationship related = Member; // relationship of this to the class
1247 bool stat = false; // is it a static function?
1248 bool proto = false; // is it a prototype?
1249 bool docEnumValues = false; // is an enum with documented enum values.
1250
1251 mutable bool annScope = false; // member is part of an anonymous scope
1252 mutable bool annUsed = false; // ugly: needs to be mutable to allow setAnonymousUsed to act as a
1253 mutable bool hasDetailedDescriptionCached = false;
1254 bool detailedDescriptionCachedValue = false;
1255 // const member.
1256 bool hasCallGraph = false;
1257 bool hasCallerGraph = false;
1258 bool hasReferencedByRelation = false;
1259 bool hasReferencesRelation = false;
1260 bool explExt = false; // member was explicitly declared external
1261 bool tspec = false; // member is a template specialization
1262 bool groupHasDocs = false; // true if the entry that caused the grouping was documented
1263 bool docsForDefinition = false; // TRUE => documentation block is put before
1264 // definition.
1265 // FALSE => block is put before declaration.
1266 ClassDef *category = 0;
1267 const MemberDef *categoryRelation = 0;
1268 QCString declFileName;
1269 int declLine = -1;
1270 int declColumn = -1;
1271 int numberOfFlowKW = 0;
1272 };
1273
IMPL()1274 MemberDefImpl::IMPL::IMPL()
1275 {
1276 }
1277
~IMPL()1278 MemberDefImpl::IMPL::~IMPL()
1279 {
1280 }
1281
init(Definition * d,const QCString & t,const QCString & a,const QCString & e,Protection p,Specifier v,bool s,Relationship r,MemberType mt,const ArgumentList & tal,const ArgumentList & al,const QCString & meta)1282 void MemberDefImpl::IMPL::init(Definition *d,
1283 const QCString &t,const QCString &a,const QCString &e,
1284 Protection p,Specifier v,bool s,Relationship r,
1285 MemberType mt,const ArgumentList &tal,
1286 const ArgumentList &al,const QCString &meta
1287 )
1288 {
1289 classDef=0;
1290 fileDef=0;
1291 redefines=0;
1292 relatedAlso=0;
1293 accessorClass=0;
1294 nspace=0;
1295 memDef=0;
1296 memDec=0;
1297 group=0;
1298 grpId=-1;
1299 enumScope=0;
1300 livesInsideEnum=FALSE;
1301 hasCallGraph = FALSE;
1302 hasCallerGraph = FALSE;
1303 hasReferencedByRelation = FALSE;
1304 hasReferencesRelation = FALSE;
1305 initLines=0;
1306 type=t;
1307 if (mt==MemberType_Typedef) type.stripPrefix("typedef ");
1308 // type.stripPrefix("struct ");
1309 // type.stripPrefix("class " );
1310 // type.stripPrefix("union " );
1311 type=removeRedundantWhiteSpace(type);
1312 args=a;
1313 args=removeRedundantWhiteSpace(args);
1314 if (type.isEmpty()) decl=d->name()+args; else decl=type+" "+d->name()+args;
1315
1316 memberGroup=0;
1317 virt=v;
1318 prot=p;
1319 related=r;
1320 stat=s;
1321 mtype=mt;
1322 exception=e;
1323 proto=FALSE;
1324 annScope=FALSE;
1325 memSpec=0;
1326 annMemb=0;
1327 annUsed=FALSE;
1328 annEnumType=0;
1329 groupAlias=0;
1330 explExt=FALSE;
1331 tspec=FALSE;
1332 cachedAnonymousType=0;
1333 maxInitLines=Config_getInt(MAX_INITIALIZER_LINES);
1334 userInitLines=-1;
1335 docEnumValues=FALSE;
1336 // copy function template arguments (if any)
1337 tArgList = tal;
1338 //printf("new member al=%p\n",al);
1339 // copy function definition arguments (if any)
1340 defArgList = al;
1341 // convert function declaration arguments (if any)
1342 if (!args.isEmpty())
1343 {
1344 declArgList = *stringToArgumentList(d->getLanguage(),args,&extraTypeChars);
1345 //printf("setDeclArgList %s to %s const=%d\n",qPrint(args),
1346 // qPrint(argListToString(declArgList)),declArgList->constSpecifier);
1347 }
1348 metaData = meta;
1349 templateMaster = 0;
1350 docsForDefinition = TRUE;
1351 isTypedefValCached = FALSE;
1352 cachedTypedefValue = 0;
1353 //inbodyLine = -1;
1354 implOnly=FALSE;
1355 groupMember = 0;
1356 hasDocumentedParams = FALSE;
1357 hasDocumentedReturnType = FALSE;
1358 docProvider = 0;
1359 isDMember = d->getDefFileName().right(2).lower()==".d";
1360 }
1361
1362
1363 //-----------------------------------------------------------------------------
1364 //-----------------------------------------------------------------------------
1365 //-----------------------------------------------------------------------------
1366
1367 /*! Creates a new member definition.
1368 *
1369 * \param df File containing the definition of this member.
1370 * \param dl Line at which the member definition was found.
1371 * \param dc Column at which the member definition was found.
1372 * \param t A string representing the type of the member.
1373 * \param na A string representing the name of the member.
1374 * \param a A string representing the arguments of the member.
1375 * \param e A string representing the throw clause of the members.
1376 * \param p The protection context of the member, possible values are:
1377 * \c Public, \c Protected, \c Private.
1378 * \param v The degree of 'virtualness' of the member, possible values are:
1379 * \c Normal, \c Virtual, \c Pure.
1380 * \param s A boolean that is true iff the member is static.
1381 * \param r The relationship between the class and the member.
1382 * \param mt The kind of member. See #MemberType for a list of
1383 * all types.
1384 * \param tal The template arguments of this member.
1385 * \param al The arguments of this member. This is a structured form of
1386 * the string past as argument \a a.
1387 * \param meta Slice metadata.
1388 */
1389
MemberDefImpl(const QCString & df,int dl,int dc,const QCString & t,const QCString & na,const QCString & a,const QCString & e,Protection p,Specifier v,bool s,Relationship r,MemberType mt,const ArgumentList & tal,const ArgumentList & al,const QCString & meta)1390 MemberDefImpl::MemberDefImpl(const QCString &df,int dl,int dc,
1391 const QCString &t,const QCString &na,const QCString &a,const QCString &e,
1392 Protection p,Specifier v,bool s,Relationship r,MemberType mt,
1393 const ArgumentList &tal,const ArgumentList &al,const QCString &meta
1394 ) : DefinitionMixin(df,dl,dc,removeRedundantWhiteSpace(na))
1395 {
1396 //printf("MemberDefImpl::MemberDef(%s)\n",na);
1397 m_impl = new MemberDefImpl::IMPL;
1398 m_impl->init(this,t,a,e,p,v,s,r,mt,tal,al,meta);
1399 m_isLinkableCached = 0;
1400 m_isConstructorCached = 0;
1401 m_isDestructorCached = 0;
1402 }
1403
MemberDefImpl(const MemberDefImpl & md)1404 MemberDefImpl::MemberDefImpl(const MemberDefImpl &md) : DefinitionMixin(md)
1405 {
1406 m_impl = new MemberDefImpl::IMPL;
1407 m_isLinkableCached = 0;
1408 m_isConstructorCached = 0;
1409 m_isDestructorCached = 0;
1410 }
1411
deepCopy() const1412 MemberDef *MemberDefImpl::deepCopy() const
1413 {
1414 //MemberDef *result = new MemberDef(getDefFileName(),getDefLine(),name());
1415 MemberDefImpl *result = new MemberDefImpl(*this);
1416 // first copy everything by reference
1417 *result->m_impl = *m_impl;
1418 result->m_impl->defArgList = m_impl->defArgList;
1419 result->m_impl->tArgList = m_impl->tArgList;
1420 result->m_impl->typeConstraints = m_impl->typeConstraints;
1421 result->setDefinitionTemplateParameterLists(m_impl->defTmpArgLists);
1422 result->m_impl->declArgList = m_impl->declArgList;
1423 return result;
1424 }
1425
moveTo(Definition * scope)1426 void MemberDefImpl::moveTo(Definition *scope)
1427 {
1428 setOuterScope(scope);
1429 if (scope->definitionType()==Definition::TypeClass)
1430 {
1431 m_impl->classDef = toClassDef(scope);
1432 }
1433 else if (scope->definitionType()==Definition::TypeFile)
1434 {
1435 m_impl->fileDef = toFileDef(scope);
1436 }
1437 else if (scope->definitionType()==Definition::TypeNamespace)
1438 {
1439 m_impl->nspace = toNamespaceDef(scope);
1440 }
1441 m_isLinkableCached = 0;
1442 m_isConstructorCached = 0;
1443 }
1444
1445
1446 /*! Destroys the member definition. */
~MemberDefImpl()1447 MemberDefImpl::~MemberDefImpl()
1448 {
1449 delete m_impl;
1450 //printf("%p: ~MemberDef()\n",this);
1451 m_impl=0;
1452 }
1453
setReimplements(const MemberDef * md)1454 void MemberDefImpl::setReimplements(const MemberDef *md)
1455 {
1456 m_impl->redefines = md;
1457 }
1458
insertReimplementedBy(const MemberDef * md)1459 void MemberDefImpl::insertReimplementedBy(const MemberDef *md)
1460 {
1461 if (m_impl->templateMaster)
1462 {
1463 MemberDefMutable *mdm = toMemberDefMutable(m_impl->templateMaster);
1464 if (mdm)
1465 {
1466 mdm->insertReimplementedBy(md);
1467 }
1468 }
1469 if (!m_impl->redefinedBy.contains(md))
1470 {
1471 m_impl->redefinedBy.inSort(md);
1472 }
1473 }
1474
reimplements() const1475 const MemberDef *MemberDefImpl::reimplements() const
1476 {
1477 return m_impl->redefines;
1478 }
1479
reimplementedBy() const1480 const MemberVector &MemberDefImpl::reimplementedBy() const
1481 {
1482 return m_impl->redefinedBy;
1483 }
1484
isReimplementedBy(const ClassDef * cd) const1485 bool MemberDefImpl::isReimplementedBy(const ClassDef *cd) const
1486 {
1487 if (cd)
1488 {
1489 for (const auto &md : m_impl->redefinedBy)
1490 {
1491 const ClassDef *mcd = md->getClassDef();
1492 if (mcd)
1493 {
1494 if (cd==mcd || cd->isBaseClass(mcd,TRUE))
1495 {
1496 return TRUE;
1497 }
1498 }
1499 }
1500 }
1501 return FALSE;
1502 }
1503
insertEnumField(const MemberDef * md)1504 void MemberDefImpl::insertEnumField(const MemberDef *md)
1505 {
1506 m_impl->enumFields.push_back(md);
1507 }
1508
addExample(const QCString & anchor,const QCString & nameStr,const QCString & file)1509 bool MemberDefImpl::addExample(const QCString &anchor,const QCString &nameStr, const QCString &file)
1510 {
1511 //printf("%s::addExample(%s,%s,%s)\n",qPrint(name()),anchor,nameStr,file);
1512 return m_impl->examples.inSort(Example(anchor,nameStr,file));
1513 }
1514
hasExamples() const1515 bool MemberDefImpl::hasExamples() const
1516 {
1517 return !m_impl->examples.empty();
1518 }
1519
getOutputFileBase() const1520 QCString MemberDefImpl::getOutputFileBase() const
1521 {
1522 static bool separateMemberPages = Config_getBool(SEPARATE_MEMBER_PAGES);
1523 static bool inlineSimpleClasses = Config_getBool(INLINE_SIMPLE_STRUCTS);
1524 QCString baseName;
1525
1526 //printf("Member: %s: templateMaster=%p group=%p classDef=%p nspace=%p fileDef=%p\n",
1527 // qPrint(name()),m_impl->templateMaster,m_impl->group,m_impl->classDef,
1528 // m_impl->nspace,m_impl->fileDef);
1529 const NamespaceDef *nspace = getNamespaceDef();
1530 const FileDef *fileDef = getFileDef();
1531 const ClassDef *classDef = getClassDef();
1532 const GroupDef *groupDef = getGroupDef();
1533 if (!m_impl->explicitOutputFileBase.isEmpty())
1534 {
1535 return m_impl->explicitOutputFileBase;
1536 }
1537 else if (templateMaster())
1538 {
1539 return templateMaster()->getOutputFileBase();
1540 }
1541 else if (groupDef)
1542 {
1543 baseName=groupDef->getOutputFileBase();
1544 }
1545 else if (classDef)
1546 {
1547 baseName=classDef->getOutputFileBase();
1548 if (inlineSimpleClasses && classDef->isSimple())
1549 {
1550 return baseName;
1551 }
1552 }
1553 else if (nspace && (nspace->isLinkable() || nspace->isAnonymous()))
1554 {
1555 baseName=nspace->getOutputFileBase();
1556 }
1557 else if (fileDef)
1558 {
1559 baseName=fileDef->getOutputFileBase();
1560 }
1561
1562 if (baseName.isEmpty())
1563 {
1564 warn(getDefFileName(),getDefLine(),
1565 "Internal inconsistency: member %s does not belong to any"
1566 " container!",qPrint(name())
1567 );
1568 return "dummy";
1569 }
1570 else if (separateMemberPages && hasDetailedDescription())
1571 {
1572 if (getEnumScope()) // enum value, which is part of enum's documentation
1573 {
1574 baseName+="_"+getEnumScope()->anchor();
1575 }
1576 else
1577 {
1578 baseName+="_"+anchor();
1579 }
1580 }
1581 return baseName;
1582 }
1583
getReference() const1584 QCString MemberDefImpl::getReference() const
1585 {
1586 QCString ref = DefinitionMixin::getReference();
1587 if (!ref.isEmpty())
1588 {
1589 return ref;
1590 }
1591 const NamespaceDef *nspace = getNamespaceDef();
1592 const FileDef *fileDef = getFileDef();
1593 const ClassDef *classDef = getClassDef();
1594 const GroupDef *groupDef = getGroupDef();
1595 if (templateMaster())
1596 {
1597 return templateMaster()->getReference();
1598 }
1599 else if (groupDef)
1600 {
1601 return groupDef->getReference();
1602 }
1603 else if (classDef)
1604 {
1605 return classDef->getReference();
1606 }
1607 else if (nspace)
1608 {
1609 return nspace->getReference();
1610 }
1611 else if (fileDef)
1612 {
1613 return fileDef->getReference();
1614 }
1615 return "";
1616 }
1617
anchor() const1618 QCString MemberDefImpl::anchor() const
1619 {
1620 QCString result=m_impl->anc;
1621 if (m_impl->groupAlias) return m_impl->groupAlias->anchor();
1622 if (m_impl->templateMaster) return m_impl->templateMaster->anchor();
1623 if (m_impl->enumScope && m_impl->enumScope!=this) // avoid recursion for C#'s public enum E { E, F }
1624 {
1625 result.prepend(m_impl->enumScope->anchor());
1626 }
1627 if (getGroupDef())
1628 {
1629 if (m_impl->groupMember)
1630 {
1631 result=m_impl->groupMember->anchor();
1632 }
1633 else if (getReference().isEmpty())
1634 {
1635 result.prepend("g");
1636 }
1637 }
1638 return result;
1639 }
1640
_computeLinkableInProject()1641 void MemberDefImpl::_computeLinkableInProject()
1642 {
1643 static bool extractStatic = Config_getBool(EXTRACT_STATIC);
1644 static bool extractPrivateVirtual = Config_getBool(EXTRACT_PRIV_VIRTUAL);
1645 m_isLinkableCached = 2; // linkable
1646 //printf("MemberDefImpl::isLinkableInProject(name=%s)\n",qPrint(name()));
1647 if (isHidden())
1648 {
1649 //printf("is hidden\n");
1650 m_isLinkableCached = 1;
1651 return;
1652 }
1653 if (templateMaster())
1654 {
1655 //printf("has template master\n");
1656 m_isLinkableCached = templateMaster()->isLinkableInProject() ? 2 : 1;
1657 return;
1658 }
1659 if (isAnonymous())
1660 {
1661 //printf("name invalid\n");
1662 m_isLinkableCached = 1; // not a valid or a dummy name
1663 return;
1664 }
1665 if (!hasDocumentation() || isReference())
1666 {
1667 //printf("no docs or reference\n");
1668 m_isLinkableCached = 1; // no documentation
1669 return;
1670 }
1671 const GroupDef *groupDef = getGroupDef();
1672 const ClassDef *classDef = getClassDef();
1673 if (groupDef && !groupDef->isLinkableInProject())
1674 {
1675 //printf("group but group not linkable!\n");
1676 m_isLinkableCached = 1; // group but group not linkable
1677 return;
1678 }
1679 if (!groupDef && classDef && !classDef->isLinkableInProject())
1680 {
1681 //printf("in a class but class not linkable!\n");
1682 m_isLinkableCached = 1; // in class but class not linkable
1683 return;
1684 }
1685 const NamespaceDef *nspace = getNamespaceDef();
1686 const FileDef *fileDef = getFileDef();
1687 if (!groupDef && nspace && !m_impl->related && !nspace->isLinkableInProject()
1688 && (fileDef==0 || !fileDef->isLinkableInProject()))
1689 {
1690 //printf("in a namespace but namespace not linkable!\n");
1691 m_isLinkableCached = 1; // in namespace but namespace not linkable
1692 return;
1693 }
1694 if (!groupDef && !nspace &&
1695 !m_impl->related && !classDef &&
1696 fileDef && !fileDef->isLinkableInProject())
1697 {
1698 //printf("in a file but file not linkable!\n");
1699 m_isLinkableCached = 1; // in file (and not in namespace) but file not linkable
1700 return;
1701 }
1702 if ((!protectionLevelVisible(m_impl->prot) && m_impl->mtype!=MemberType_Friend) &&
1703 !(m_impl->prot==Private && m_impl->virt!=Normal && extractPrivateVirtual))
1704 {
1705 //printf("private and invisible!\n");
1706 m_isLinkableCached = 1; // hidden due to protection
1707 return;
1708 }
1709 if (m_impl->stat && classDef==0 && !extractStatic)
1710 {
1711 //printf("static and invisible!\n");
1712 m_isLinkableCached = 1; // hidden due to staticness
1713 return;
1714 }
1715 //printf("linkable!\n");
1716 return; // linkable!
1717 }
1718
setDocumentation(const QCString & d,const QCString & docFile,int docLine,bool stripWhiteSpace)1719 void MemberDefImpl::setDocumentation(const QCString &d,const QCString &docFile,int docLine,bool stripWhiteSpace)
1720 {
1721 DefinitionMixin::setDocumentation(d,docFile,docLine,stripWhiteSpace);
1722 m_isLinkableCached = 0;
1723 }
1724
setBriefDescription(const QCString & b,const QCString & briefFile,int briefLine)1725 void MemberDefImpl::setBriefDescription(const QCString &b,const QCString &briefFile,int briefLine)
1726 {
1727 DefinitionMixin::setBriefDescription(b,briefFile,briefLine);
1728 m_isLinkableCached = 0;
1729 }
1730
setInbodyDocumentation(const QCString & d,const QCString & inbodyFile,int inbodyLine)1731 void MemberDefImpl::setInbodyDocumentation(const QCString &d,const QCString &inbodyFile,int inbodyLine)
1732 {
1733 DefinitionMixin::setInbodyDocumentation(d,inbodyFile,inbodyLine);
1734 m_isLinkableCached = 0;
1735 }
1736
setHidden(bool b)1737 void MemberDefImpl::setHidden(bool b)
1738 {
1739 DefinitionMixin::setHidden(b);
1740 m_isLinkableCached = 0;
1741 }
1742
isLinkableInProject() const1743 bool MemberDefImpl::isLinkableInProject() const
1744 {
1745 if (m_isLinkableCached==0)
1746 {
1747 MemberDefImpl *that = (MemberDefImpl*)this;
1748 that->_computeLinkableInProject();
1749 }
1750 ASSERT(m_isLinkableCached>0);
1751 return m_isLinkableCached==2;
1752 }
1753
isLinkable() const1754 bool MemberDefImpl::isLinkable() const
1755 {
1756 if (m_impl->templateMaster)
1757 {
1758 return m_impl->templateMaster->isLinkable();
1759 }
1760 else
1761 {
1762 return isLinkableInProject() || isReference();
1763 }
1764 }
1765
1766
setDefinitionTemplateParameterLists(const ArgumentLists & lists)1767 void MemberDefImpl::setDefinitionTemplateParameterLists(const ArgumentLists &lists)
1768 {
1769 m_impl->defTmpArgLists = lists;
1770 }
1771
writeLink(OutputList & ol,const ClassDef *,const NamespaceDef *,const FileDef * fd,const GroupDef * gd,bool onlyText) const1772 void MemberDefImpl::writeLink(OutputList &ol,
1773 const ClassDef *,const NamespaceDef *,const FileDef *fd,const GroupDef *gd,
1774 bool onlyText) const
1775 {
1776 SrcLangExt lang = getLanguage();
1777 static bool hideScopeNames = Config_getBool(HIDE_SCOPE_NAMES);
1778 QCString sep = getLanguageSpecificSeparator(lang,TRUE);
1779 QCString n = name();
1780 const ClassDef *classDef = getClassDef();
1781 const NamespaceDef *nspace = getNamespaceDef();
1782 if (!hideScopeNames)
1783 {
1784 if (m_impl->enumScope && m_impl->livesInsideEnum && getGroupDef()!=0)
1785 {
1786 n.prepend(m_impl->enumScope->displayName()+sep);
1787 }
1788 if (classDef && gd && !isRelated())
1789 {
1790 n.prepend(classDef->displayName()+sep);
1791 }
1792 else if (nspace && (gd || fd))
1793 {
1794 n.prepend(nspace->displayName()+sep);
1795 }
1796 }
1797
1798 if (isObjCMethod())
1799 {
1800 if (isStatic()) ol.docify("+ "); else ol.docify("- ");
1801 }
1802 if (!onlyText && (isLinkable() || hasDetailedDescription())) // write link
1803 {
1804 if (m_impl->mtype==MemberType_EnumValue && getGroupDef()==0 && // enum value is not grouped
1805 getEnumScope() && getEnumScope()->getGroupDef()) // but its container is
1806 {
1807 const GroupDef *enumValGroup = getEnumScope()->getGroupDef();
1808 ol.writeObjectLink(enumValGroup->getReference(),
1809 enumValGroup->getOutputFileBase(),
1810 anchor(),n);
1811 }
1812 else
1813 {
1814 ol.writeObjectLink(getReference(),getOutputFileBase(),anchor(),n);
1815 }
1816 }
1817 else // write only text
1818 {
1819 ol.startBold();
1820 ol.docify(n);
1821 ol.endBold();
1822 }
1823 }
1824
1825 static std::mutex g_cachedAnonymousTypeMutex;
1826
1827 /*! If this member has an anonymous class/struct/union as its type, then
1828 * this method will return the ClassDef that describes this return type.
1829 */
getClassDefOfAnonymousType() const1830 ClassDef *MemberDefImpl::getClassDefOfAnonymousType() const
1831 {
1832 std::lock_guard<std::mutex> lock(g_cachedAnonymousTypeMutex);
1833 //printf("%s:getClassDefOfAnonymousType() cache=%s\n",qPrint(name()),
1834 // m_impl->cachedAnonymousType?qPrint(m_impl->cachedAnonymousType->name()):"<empty>");
1835 if (m_impl->cachedAnonymousType) return m_impl->cachedAnonymousType;
1836
1837 QCString cname;
1838 if (getClassDef()!=0)
1839 {
1840 cname=getClassDef()->name();
1841 }
1842 else if (getNamespaceDef()!=0)
1843 {
1844 cname=getNamespaceDef()->name();
1845 }
1846 QCString ltype(m_impl->type);
1847 // strip 'static' keyword from ltype
1848 //if (ltype.left(7)=="static ") ltype=ltype.right(ltype.length()-7);
1849 // strip 'friend' keyword from ltype
1850 ltype.stripPrefix("friend ");
1851
1852 // search for the last anonymous scope in the member type
1853 ClassDef *annoClassDef=0;
1854
1855 // match expression if it contains at least one @1 marker, e.g.
1856 // 'struct A::@1::@2::B' matches 'A::@1::@2::B' but 'struct A::B' does not match.
1857 std::string stype = ltype.str();
1858 static const reg::Ex r(R"([\w@:]*@\d+[\w@:]*)");
1859 reg::Match match;
1860 if (reg::search(stype,match,r)) // found anonymous scope in type
1861 {
1862 QCString annName = match.str();
1863
1864 // if inside a class or namespace try to prepend the scope name
1865 if (!cname.isEmpty() && annName.left(cname.length()+2)!=cname+"::")
1866 {
1867 QCString ts=stripAnonymousNamespaceScope(cname+"::"+annName);
1868 annoClassDef=getClass(ts);
1869 }
1870 // if not found yet, try without scope name
1871 if (annoClassDef==0)
1872 {
1873 QCString ts=stripAnonymousNamespaceScope(annName);
1874 annoClassDef=getClass(ts);
1875 }
1876 }
1877 m_impl->cachedAnonymousType = annoClassDef;
1878 return annoClassDef;
1879 }
1880
1881 /*! This methods returns TRUE iff the brief section (also known as
1882 * declaration section) is visible in the documentation.
1883 */
isBriefSectionVisible() const1884 bool MemberDefImpl::isBriefSectionVisible() const
1885 {
1886 static bool extractStatic = Config_getBool(EXTRACT_STATIC);
1887 static bool extractPrivateVirtual = Config_getBool(EXTRACT_PRIV_VIRTUAL);
1888 static bool hideUndocMembers = Config_getBool(HIDE_UNDOC_MEMBERS);
1889 static bool briefMemberDesc = Config_getBool(BRIEF_MEMBER_DESC);
1890 static bool repeatBrief = Config_getBool(REPEAT_BRIEF);
1891 static bool hideFriendCompounds = Config_getBool(HIDE_FRIEND_COMPOUNDS);
1892
1893 //printf("Member %s grpId=%d docs=%s file=%s args=%s\n",
1894 // qPrint(name()),
1895 // 0,"", //grpId,grpId==-1?"<none>":Doxygen::memberDocDict[grpId]->data(),
1896 // "", //qPrint(getFileDef()->name()),
1897 // argsString());
1898
1899 auto it = Doxygen::memberGroupInfoMap.find(m_impl->grpId);
1900 bool hasDocs = hasDocumentation();
1901 if (it!=Doxygen::memberGroupInfoMap.end())
1902 {
1903 auto &info = it->second;
1904 //printf("name=%s m_impl->grpId=%d info=%p\n",qPrint(name()),m_impl->grpId,info);
1905 //QCString *pMemGrp = Doxygen::memberDocDict[grpId];
1906 hasDocs = hasDocs ||
1907 // part of a documented member group
1908 (m_impl->grpId!=-1 && !(info->doc.isEmpty() && info->header.isEmpty()));
1909 }
1910
1911 // only include static members with file/namespace scope if
1912 // explicitly enabled in the config file
1913 bool visibleIfStatic = !(getClassDef()==0 &&
1914 isStatic() &&
1915 !extractStatic
1916 );
1917
1918 // only include members is the are documented or
1919 // HIDE_UNDOC_MEMBERS is NO in the config file
1920 bool visibleIfDocumented = (!hideUndocMembers ||
1921 hasDocs ||
1922 isDocumentedFriendClass()
1923 );
1924
1925 // hide members with no detailed description and brief descriptions
1926 // explicitly disabled.
1927 bool visibleIfEnabled = !(hideUndocMembers &&
1928 documentation().isEmpty() &&
1929 !briefMemberDesc &&
1930 !repeatBrief
1931 );
1932
1933 // Hide friend (class|struct|union) declarations if HIDE_FRIEND_COMPOUNDS is true
1934 bool visibleIfFriendCompound = !(hideFriendCompounds &&
1935 isFriend() /*&&
1936 (m_impl->type=="friend class" ||
1937 m_impl->type=="friend struct" ||
1938 m_impl->type=="friend union"
1939 )*/
1940 );
1941
1942 // only include members that are non-private unless EXTRACT_PRIVATE is
1943 // set to YES or the member is part of a group. And as a special case,
1944 // private *documented* virtual members are shown if EXTRACT_PRIV_VIRTUAL
1945 // is set to YES
1946 bool visibleIfPrivate = (protectionLevelVisible(protection()) ||
1947 m_impl->mtype==MemberType_Friend ||
1948 (m_impl->prot==Private && m_impl->virt!=Normal && extractPrivateVirtual && hasDocs)
1949 );
1950
1951 // hide member if it overrides a member in a superclass and has no
1952 // documentation of its own
1953 //bool visibleIfDocVirtual = !reimplements() ||
1954 // !Config_getBool(INHERIT_DOCS) ||
1955 // hasDocs;
1956
1957 // true if this member is a constructor or destructor
1958 bool cOrDTor = isConstructor() || isDestructor();
1959
1960 // hide default constructors or destructors (no args) without
1961 // documentation
1962 bool visibleIfNotDefaultCDTor = !(cOrDTor &&
1963 (m_impl->defArgList.empty() ||
1964 m_impl->defArgList.front().type == "void"
1965 ) &&
1966 !hasDocs
1967 );
1968
1969
1970 //printf("visibleIfStatic=%d visibleIfDocumented=%d visibleIfEnabled=%d "
1971 // "visibleIfPrivate=%d visibleIfNotDefaultCDTor=%d "
1972 // "visibleIfFriendCompound=%d !annScope=%d\n",
1973 // visibleIfStatic,visibleIfDocumented,
1974 // visibleIfEnabled,visibleIfPrivate,visibleIfNotDefaultCDTor,
1975 // visibleIfFriendCompound,!m_impl->annScope);
1976
1977 bool visible = visibleIfStatic && visibleIfDocumented &&
1978 visibleIfEnabled && visibleIfPrivate &&
1979 /*visibleIfDocVirtual &&*/ visibleIfNotDefaultCDTor &&
1980 visibleIfFriendCompound &&
1981 !m_impl->annScope && !isHidden();
1982 //printf("MemberDefImpl::isBriefSectionVisible() %d\n",visible);
1983 return visible;
1984 }
1985
getDeclType() const1986 QCString MemberDefImpl::getDeclType() const
1987 {
1988 SrcLangExt lang = getLanguage();
1989 QCString ltype(m_impl->type);
1990 if (lang==SrcLangExt_Cpp && isEnumerate() && isStrong())
1991 {
1992 if (isEnumStruct())
1993 {
1994 ltype+=" struct";
1995 }
1996 else
1997 {
1998 ltype+=" class";
1999 }
2000 }
2001 if (isTypedef() && getLanguage() != SrcLangExt_Slice)
2002 {
2003 ltype.prepend("typedef ");
2004 }
2005 if (isTypeAlias())
2006 {
2007 ltype="using";
2008 }
2009 // strip 'friend' keyword from ltype
2010 ltype.stripPrefix("friend ");
2011 if (ltype=="@") // rename type from enum values
2012 {
2013 ltype="";
2014 }
2015 else
2016 {
2017 if (isObjCMethod())
2018 {
2019 ltype.prepend("(");
2020 ltype.append(")");
2021 }
2022 }
2023 return ltype;
2024 }
2025
_writeTemplatePrefix(OutputList & ol,const Definition * def,const ArgumentList & al,bool writeReqClause) const2026 void MemberDefImpl::_writeTemplatePrefix(OutputList &ol, const Definition *def,
2027 const ArgumentList &al, bool writeReqClause) const
2028 {
2029 ol.docify("template<");
2030 for (auto it = al.begin(); it!=al.end();)
2031 {
2032 Argument a = *it;
2033 linkifyText(TextGeneratorOLImpl(ol), // out
2034 def, // scope
2035 getFileDef(), // fileScope
2036 this, // self
2037 a.type, // text
2038 FALSE // autoBreak
2039 );
2040 ol.docify(" ");
2041 ol.docify(a.name);
2042 if (a.defval.length()!=0)
2043 {
2044 ol.docify(" = ");
2045 ol.docify(a.defval);
2046 }
2047 ++it;
2048 if (it!=al.end()) ol.docify(", ");
2049 }
2050 ol.docify("> ");
2051 if (writeReqClause && !m_impl->requiresClause.isEmpty())
2052 {
2053 ol.lineBreak();
2054 ol.docify("requires ");
2055 linkifyText(TextGeneratorOLImpl(ol), // out
2056 def, // scope
2057 getFileDef(), // fileScope
2058 this, // self
2059 m_impl->requiresClause, // text
2060 FALSE // autoBreak
2061 );
2062 }
2063 }
2064
2065
writeDeclaration(OutputList & ol,const ClassDef * cd,const NamespaceDef * nd,const FileDef * fd,const GroupDef * gd,bool inGroup,int indentLevel,const ClassDef * inheritedFrom,const QCString & inheritId) const2066 void MemberDefImpl::writeDeclaration(OutputList &ol,
2067 const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,
2068 bool inGroup, int indentLevel, const ClassDef *inheritedFrom,const QCString &inheritId) const
2069 {
2070 //printf("> %s MemberDefImpl::writeDeclaration() inGroup=%d\n",qPrint(qualifiedName()),inGroup);
2071
2072 // hide enum value, since they appear already as part of the enum, unless they
2073 // are explicitly grouped.
2074 if (!inGroup && m_impl->mtype==MemberType_EnumValue) return;
2075
2076
2077 const Definition *d=0;
2078 ASSERT (cd!=0 || nd!=0 || fd!=0 || gd!=0); // member should belong to something
2079 if (cd) d=cd; else if (nd) d=nd; else if (fd) d=fd; else d=gd;
2080 if (d==gd) // see bug 753608
2081 {
2082 if (getClassDef()) d = getClassDef();
2083 else if (getNamespaceDef()) d = getNamespaceDef();
2084 else if (getFileDef()) d = getFileDef();
2085 }
2086
2087 QCString cname = d->name();
2088 QCString cdname = d->displayName();
2089 QCString cfname = getOutputFileBase();
2090
2091 // search for the last anonymous scope in the member type
2092 ClassDefMutable *annoClassDef=toClassDefMutable(getClassDefOfAnonymousType());
2093
2094 ol.startMemberDeclaration();
2095
2096 // start a new member declaration
2097 bool isAnonType = annoClassDef || m_impl->annMemb || m_impl->annEnumType;
2098 ol.startMemberItem(anchor(),
2099 isAnonType ? 1 : !m_impl->tArgList.empty() ? 3 : 0,
2100 inheritId
2101 );
2102
2103 // If there is no detailed description we need to write the anchor here.
2104 bool detailsVisible = hasDetailedDescription();
2105 bool writeAnchor = (inGroup || getGroupDef()==0) && // only write anchors for member that have no details and are
2106 !detailsVisible && !m_impl->annMemb; // rendered inside the group page or are not grouped at all
2107 if (writeAnchor)
2108 {
2109 QCString doxyArgs=argsString();
2110 QCString doxyName=name();
2111 if (!cname.isEmpty())
2112 {
2113 doxyName.prepend(cdname+getLanguageSpecificSeparator(getLanguage()));
2114 }
2115 ol.startDoxyAnchor(cfname,cname,anchor(),doxyName,doxyArgs);
2116 }
2117
2118 if (!detailsVisible)
2119 {
2120 ol.pushGeneratorState();
2121 ol.disable(OutputGenerator::Man);
2122 ol.disable(OutputGenerator::Latex);
2123 ol.disable(OutputGenerator::Docbook);
2124 ol.docify("\n");
2125 ol.popGeneratorState();
2126 }
2127
2128 if (annoClassDef || m_impl->annMemb)
2129 {
2130 int j;
2131 for (j=0;j<indentLevel;j++)
2132 {
2133 ol.writeNonBreakableSpace(3);
2134 }
2135 }
2136
2137 // *** write template lists
2138 if (m_impl->tArgList.hasParameters() && getLanguage()==SrcLangExt_Cpp)
2139 {
2140 if (!isAnonType) ol.startMemberTemplateParams();
2141 _writeTemplatePrefix(ol,d,m_impl->tArgList);
2142 if (!isAnonType) ol.endMemberTemplateParams(anchor(),inheritId);
2143 }
2144
2145
2146 // *** write type
2147 QCString ltype(m_impl->type);
2148 if (isTypedef() && getLanguage() != SrcLangExt_Slice)
2149 {
2150 ltype.prepend("typedef ");
2151 }
2152 if (isTypeAlias())
2153 {
2154 ltype="using";
2155 }
2156 // strip 'friend' keyword from ltype
2157 ltype.stripPrefix("friend ");
2158 static const reg::Ex r(R"(@\d+)");
2159 reg::Match match;
2160 std::string stype = ltype.str();
2161 bool endAnonScopeNeeded=FALSE;
2162 if (reg::search(stype,match,r)) // member has an anonymous type
2163 {
2164 int i = (int)match.position();
2165 int l = (int)match.length();
2166 //printf("annoClassDef=%p annMemb=%p scopeName='%s' anonymous='%s'\n",
2167 // annoClassDef,annMemb,qPrint(cname),qPrint(ltype.mid(i,l)));
2168
2169 if (annoClassDef) // type is an anonymous compound
2170 {
2171 int ir=i+l;
2172 //printf("<<<<<<<<<<<<<<\n");
2173 ol.startAnonTypeScope(indentLevel);
2174 annoClassDef->writeDeclaration(ol,m_impl->annMemb,inGroup,indentLevel+1,inheritedFrom,inheritId);
2175 //printf(">>>>>>>>>>>>>> startMemberItem(2)\n");
2176 ol.startMemberItem(anchor(),2,inheritId);
2177 int j;
2178 for (j=0;j< indentLevel;j++)
2179 {
2180 ol.writeNonBreakableSpace(3);
2181 }
2182 QCString varName=ltype.right(ltype.length()-ir).stripWhiteSpace();
2183 //printf(">>>>>> ltype='%s' varName='%s'\n",qPrint(ltype),qPrint(varName));
2184 ol.docify("}");
2185 if (varName.isEmpty() && isAnonymous())
2186 {
2187 ol.docify(";");
2188 }
2189 else if (!varName.isEmpty() && (varName.at(0)=='*' || varName.at(0)=='&'))
2190 {
2191 ol.docify(" ");
2192 ol.docify(varName);
2193 }
2194 endAnonScopeNeeded=TRUE;
2195 }
2196 else
2197 {
2198 if (getAnonymousEnumType()) // type is an anonymous enum
2199 {
2200 linkifyText(TextGeneratorOLImpl(ol), // out
2201 d, // scope
2202 getBodyDef(), // fileScope
2203 this, // self
2204 ltype.left(i), // text
2205 FALSE // autoBreak
2206 );
2207 getAnonymousEnumType()->writeEnumDeclaration(ol,cd,nd,fd,gd);
2208 //ol+=*getAnonymousEnumType()->enumDecl();
2209 linkifyText(TextGeneratorOLImpl(ol),d,getFileDef(),this,ltype.right(ltype.length()-i-l),TRUE);
2210 }
2211 else
2212 {
2213 ltype = ltype.left(i) + " { ... } " + removeAnonymousScopes(ltype.right(ltype.length()-i-l));
2214 linkifyText(TextGeneratorOLImpl(ol), // out
2215 d, // scope
2216 getBodyDef(), // fileScope
2217 this, // self
2218 ltype, // text
2219 FALSE // autoBreak
2220 );
2221 }
2222 }
2223 }
2224 else if (ltype=="@") // rename type from enum values
2225 {
2226 ltype="";
2227 }
2228 else
2229 {
2230 if (isObjCMethod())
2231 {
2232 ltype.prepend("(");
2233 ltype.append(")");
2234 }
2235 linkifyText(TextGeneratorOLImpl(ol), // out
2236 d, // scope
2237 getBodyDef(), // fileScope
2238 this, // self
2239 ltype, // text
2240 FALSE // autoBreak
2241 );
2242 }
2243 bool htmlOn = ol.isEnabled(OutputGenerator::Html);
2244 if (htmlOn && !ltype.isEmpty())
2245 {
2246 ol.disable(OutputGenerator::Html);
2247 }
2248 if (!ltype.isEmpty()) ol.docify(" ");
2249 if (htmlOn)
2250 {
2251 ol.enable(OutputGenerator::Html);
2252 }
2253
2254 if (m_impl->annMemb)
2255 {
2256 ol.pushGeneratorState();
2257 ol.disableAllBut(OutputGenerator::Html);
2258 ol.writeNonBreakableSpace(3);
2259 ol.popGeneratorState();
2260 }
2261 else
2262 {
2263 ol.insertMemberAlign(m_impl->tArgList.hasParameters());
2264 }
2265
2266 // *** write name
2267 if (!isAnonymous()) // hide anonymous stuff
2268 {
2269 static bool extractPrivate = Config_getBool(EXTRACT_PRIVATE);
2270 static bool extractPrivateVirtual = Config_getBool(EXTRACT_PRIV_VIRTUAL);
2271 static bool extractStatic = Config_getBool(EXTRACT_STATIC);
2272 MemberDefMutable *annMemb = toMemberDefMutable(m_impl->annMemb);
2273 //printf("Member name=`%s gd=%p md->groupDef=%p inGroup=%d isLinkable()=%d hasDocumentation=%d\n",qPrint(name()),gd,getGroupDef(),inGroup,isLinkable(),hasDocumentation());
2274 if (!name().isEmpty() && // name valid
2275 (hasDetailedDescription() || isReference()) && // has docs
2276 !(m_impl->prot==Private && !extractPrivate && (m_impl->virt==Normal || !extractPrivateVirtual) && m_impl->mtype!=MemberType_Friend) && // hidden due to protection
2277 !(isStatic() && getClassDef()==0 && !extractStatic) // hidden due to static-ness
2278 )
2279 {
2280 if (annMemb)
2281 {
2282 //printf("anchor=%s ann_anchor=%s\n",anchor(),annMemb->anchor());
2283 annMemb->writeLink(ol,
2284 annMemb->getClassDef(),
2285 annMemb->getNamespaceDef(),
2286 annMemb->getFileDef(),
2287 annMemb->getGroupDef());
2288 annMemb->setAnonymousUsed();
2289 setAnonymousUsed();
2290 }
2291 else
2292 {
2293 //printf("writeLink %s->%d\n",qPrint(name),hasDocumentation());
2294 const ClassDef *rcd = cd;
2295 if (isReference() && getClassDef()) rcd = getClassDef();
2296 writeLink(ol,rcd,nd,fd,gd);
2297 }
2298 }
2299 else if (isDocumentedFriendClass())
2300 // if the member is an undocumented friend declaration for some class,
2301 // then maybe we can link to the class
2302 {
2303 writeLink(ol,getClass(name()),0,0,0);
2304 }
2305 else
2306 // there is a brief member description and brief member
2307 // descriptions are enabled or there is no detailed description.
2308 {
2309 if (annMemb)
2310 {
2311 annMemb->setAnonymousUsed();
2312 setAnonymousUsed();
2313 }
2314 const ClassDef *rcd = cd;
2315 if (isReference() && getClassDef()) rcd = getClassDef();
2316 writeLink(ol,rcd,nd,fd,gd,TRUE);
2317 }
2318 }
2319
2320 // *** write arguments
2321 if (!argsString().isEmpty() && !isObjCMethod())
2322 {
2323 if (!isDefine() && !isTypedef()) ol.writeString(" ");
2324 linkifyText(TextGeneratorOLImpl(ol), // out
2325 d, // scope
2326 getBodyDef(), // fileScope
2327 this, // self
2328 isDefine() ?
2329 substitute(argsString(),",",", ") :
2330 isTypedef() ?
2331 substitute(argsString(),")(",") (") :
2332 argsString(), // text
2333 m_impl->annMemb, // autoBreak
2334 TRUE, // external
2335 FALSE, // keepSpaces
2336 indentLevel
2337 );
2338 }
2339 // *** write exceptions
2340 if (!excpString().isEmpty())
2341 {
2342 ol.writeString(" ");
2343 ol.docify(excpString());
2344 }
2345
2346 // *** write bitfields
2347 if (!m_impl->bitfields.isEmpty()) // add bitfields
2348 {
2349 linkifyText(TextGeneratorOLImpl(ol),d,getBodyDef(),this,m_impl->bitfields);
2350 }
2351 else if (hasOneLineInitializer()
2352 //!init.isEmpty() && initLines==0 && // one line initializer
2353 //((maxInitLines>0 && userInitLines==-1) || userInitLines>0) // enabled by default or explicitly
2354 ) // add initializer
2355 {
2356 if (!isDefine())
2357 {
2358 //ol.writeString(" = ");
2359 ol.writeString(" ");
2360 linkifyText(TextGeneratorOLImpl(ol),d,getBodyDef(),this,m_impl->initializer.simplifyWhiteSpace());
2361 }
2362 else
2363 {
2364 ol.writeNonBreakableSpace(3);
2365 linkifyText(TextGeneratorOLImpl(ol),d,getBodyDef(),this,m_impl->initializer);
2366 }
2367 }
2368 else if (isTypeAlias()) // using template alias
2369 {
2370 ol.writeString(" = ");
2371 linkifyText(TextGeneratorOLImpl(ol),d,getBodyDef(),this,m_impl->type);
2372 }
2373
2374
2375 if ((isObjCMethod() || isObjCProperty()) && isImplementation())
2376 {
2377 ol.startTypewriter();
2378 ol.docify(" [implementation]");
2379 ol.endTypewriter();
2380 }
2381
2382 bool extractPrivate = Config_getBool(EXTRACT_PRIVATE);
2383
2384 if (isProperty() && (isSettable() || isGettable() ||
2385 isPrivateSettable() || isPrivateGettable() ||
2386 isProtectedSettable() || isProtectedGettable()))
2387 {
2388 ol.writeLatexSpacing();
2389 ol.startTypewriter();
2390 ol.docify(" [");
2391 StringVector sl;
2392
2393 if (isGettable()) sl.push_back("get");
2394 if (isProtectedGettable()) sl.push_back("protected get");
2395 if (isSettable()) sl.push_back("set");
2396 if (isProtectedSettable()) sl.push_back("protected set");
2397 if (extractPrivate)
2398 {
2399 if (isPrivateGettable()) sl.push_back("private get");
2400 if (isPrivateSettable()) sl.push_back("private set");
2401 }
2402 bool first=true;
2403 for (const auto &s : sl)
2404 {
2405 if (!first)
2406 {
2407 ol.docify(", ");
2408 }
2409 first=false;
2410 ol.docify(s.c_str());
2411 }
2412 ol.docify("]");
2413 ol.endTypewriter();
2414 }
2415
2416 if (isEvent() && (isAddable() || isRemovable() || isRaisable()))
2417 {
2418 ol.writeLatexSpacing();
2419 ol.startTypewriter();
2420 ol.docify(" [");
2421 StringVector sl;
2422 if (isAddable()) sl.push_back("add");
2423 if (isRemovable()) sl.push_back("remove");
2424 if (isRaisable()) sl.push_back("raise");
2425 bool first=true;
2426 for (const auto &s : sl)
2427 {
2428 if (!first)
2429 {
2430 ol.docify(", ");
2431 }
2432 first=false;
2433 ol.docify(s.c_str());
2434 }
2435 ol.docify("]");
2436 ol.endTypewriter();
2437 }
2438
2439 if (writeAnchor)
2440 {
2441 ol.endDoxyAnchor(cfname,anchor());
2442 }
2443
2444 //printf("endMember %s annoClassDef=%p annEnumType=%p\n",
2445 // qPrint(name()),annoClassDef,annEnumType);
2446 ol.endMemberItem();
2447 if (endAnonScopeNeeded)
2448 {
2449 ol.endAnonTypeScope(indentLevel);
2450 }
2451
2452 // write brief description
2453 if (!briefDescription().isEmpty() &&
2454 Config_getBool(BRIEF_MEMBER_DESC)
2455 )
2456 {
2457 std::unique_ptr<IDocParser> parser { createDocParser() };
2458 std::unique_ptr<DocRoot> rootNode { validatingParseDoc(*parser.get(),
2459 briefFile(),briefLine(),
2460 getOuterScope()?getOuterScope():d,
2461 this,briefDescription(),TRUE,FALSE,
2462 QCString(),TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)) };
2463
2464 if (rootNode && !rootNode->isEmpty())
2465 {
2466 ol.startMemberDescription(anchor(),inheritId);
2467 ol.writeDoc(rootNode.get(),getOuterScope()?getOuterScope():d,this);
2468 if (detailsVisible) // add More.. link only when both brief and details are visible
2469 {
2470 ol.pushGeneratorState();
2471 ol.disableAllBut(OutputGenerator::Html);
2472 ol.docify(" ");
2473 ol.startTextLink(getOutputFileBase(),anchor());
2474 ol.parseText(theTranslator->trMore());
2475 ol.endTextLink();
2476 ol.popGeneratorState();
2477 }
2478 // for RTF we need to add an extra empty paragraph
2479 ol.pushGeneratorState();
2480 ol.disableAllBut(OutputGenerator::RTF);
2481 ol.startParagraph();
2482 ol.endParagraph();
2483 ol.popGeneratorState();
2484 ol.endMemberDescription();
2485 }
2486 }
2487
2488 ol.endMemberDeclaration(anchor(),inheritId);
2489
2490 warnIfUndocumented();
2491 //printf("< %s MemberDefImpl::writeDeclaration() inGroup=%d\n",qPrint(qualifiedName()),inGroup);
2492 }
2493
hasDetailedDescription() const2494 bool MemberDefImpl::hasDetailedDescription() const
2495 {
2496 //printf(">hasDetailedDescription(cached=%d)\n",m_impl->hasDetailedDescriptionCached);
2497 if (!m_impl->hasDetailedDescriptionCached)
2498 {
2499 static bool extractAll = Config_getBool(EXTRACT_ALL);
2500 static bool alwaysDetailedSec = Config_getBool(ALWAYS_DETAILED_SEC);
2501 static bool repeatBrief = Config_getBool(REPEAT_BRIEF);
2502 static bool briefMemberDesc = Config_getBool(BRIEF_MEMBER_DESC);
2503 static bool hideUndocMembers = Config_getBool(HIDE_UNDOC_MEMBERS);
2504 static bool extractStatic = Config_getBool(EXTRACT_STATIC);
2505 static bool extractPrivateVirtual = Config_getBool(EXTRACT_PRIV_VIRTUAL);
2506 static bool inlineSources = Config_getBool(INLINE_SOURCES);
2507
2508 // the member has detailed documentation because the user added some comments
2509 bool docFilter =
2510 // extract all is enabled
2511 extractAll ||
2512 // has detailed docs
2513 !documentation().isEmpty() ||
2514 // has inbody docs
2515 !inbodyDocumentation().isEmpty() ||
2516 // is an enum with values that are documented
2517 (isEnumerate() && hasDocumentedEnumValues()) ||
2518 // is documented enum value
2519 (m_impl->mtype==MemberType_EnumValue && !briefDescription().isEmpty()) ||
2520 // has brief description that is part of the detailed description
2521 (!briefDescription().isEmpty() && // has brief docs
2522 (alwaysDetailedSec && // they are visible in
2523 (repeatBrief || // detailed section or
2524 !briefMemberDesc // they are explicitly not
2525 ) // shown in brief section
2526 )
2527 ) ||
2528 // has one or more documented arguments
2529 (m_impl->templateMaster ?
2530 m_impl->templateMaster->argumentList().hasDocumentation() :
2531 m_impl->defArgList.hasDocumentation());
2532
2533 // generate function guard
2534 // ================== =======
2535 // _writeGroupInclude -> ignored in calculation
2536 // multiLineInitializer() -> hasMultiLineInitializer()
2537 // _writeReimplements -> _isReimplements()
2538 // _writeReimplementedBy -> _countReimplementedBy()>0
2539 // _writeExamples -> hasExamples()
2540 // _writeTypeConstraints -> m_impl->typeConstraints.hasParameters()
2541 // writeSourceDef -> !getSourceFileBase().isEmpty();
2542 // writeInlineCode -> INLINE_SOURCES && hasSources()
2543 // writeSourceRefs -> hasReferencesRelation() && hasSourceRefs()
2544 // writeSourceReffedBy -> hasReferencedByRelation() && hasSourceReffedBy()
2545 // _writeCallGraph -> _hasVisibleCallGraph()
2546 // _writeCallerGraph -> _hasVisibleCallerGraph()
2547
2548 // the member has detailed documentation because there is some generated info
2549 bool docInfo =
2550 // has a multi-line initialization block
2551 (hasMultiLineInitializer()) ||
2552 // reimplements / reimplemented by
2553 _isReimplements() || (_countReimplementedBy() > 0) ||
2554 // examples
2555 hasExamples() ||
2556 // type constraints
2557 m_impl->typeConstraints.hasParameters() ||
2558 // has source definition
2559 !getSourceFileBase().isEmpty() ||
2560 // has inline sources
2561 (inlineSources && hasSources()) ||
2562 // has references
2563 (hasReferencesRelation() && hasSourceRefs()) ||
2564 (hasReferencedByRelation() && hasSourceReffedBy()) ||
2565 // call graph
2566 _hasVisibleCallGraph() ||
2567 // caller graph
2568 _hasVisibleCallerGraph();
2569
2570 if (!hideUndocMembers) // if HIDE_UNDOC_MEMBERS is NO we also show the detailed section
2571 // if there is only some generated info
2572 {
2573 docFilter = docFilter || docInfo;
2574 }
2575
2576 // this is not a global static or global statics should be extracted
2577 bool staticFilter = getClassDef()!=0 || !isStatic() || extractStatic;
2578
2579 // only include members that are non-private unless EXTRACT_PRIVATE is
2580 // set to YES or the member is part of a group
2581 bool privateFilter = protectionLevelVisible(protection()) || m_impl->mtype==MemberType_Friend ||
2582 (m_impl->prot==Private && m_impl->virt!=Normal && extractPrivateVirtual);
2583
2584 // hide friend (class|struct|union) member if HIDE_FRIEND_COMPOUNDS
2585 // is true
2586 bool friendCompoundFilter = !(Config_getBool(HIDE_FRIEND_COMPOUNDS) && isFriend());
2587
2588 m_impl->detailedDescriptionCachedValue =
2589 (docFilter && staticFilter && privateFilter && friendCompoundFilter && !isHidden());
2590 //printf("docFilter=%d docInfo=%d staticFilter=%d privateFilter=%d friendCompoundFilter=%d !isHidden()=%d",
2591 // docFilter,docInfo,staticFilter,privateFilter,friendCompoundFilter,!isHidden());
2592 m_impl->hasDetailedDescriptionCached = true;
2593 }
2594 //printf("<hasDetailedDescription(cached=%d)\n",m_impl->hasDetailedDescriptionCached);
2595 return m_impl->detailedDescriptionCachedValue;
2596 }
2597
isDetailedSectionVisible(MemberListContainer container) const2598 bool MemberDefImpl::isDetailedSectionVisible(MemberListContainer container) const
2599 {
2600 static bool separateMemPages = Config_getBool(SEPARATE_MEMBER_PAGES);
2601 static bool inlineSimpleStructs = Config_getBool(INLINE_SIMPLE_STRUCTS);
2602 static bool hideUndocMembers = Config_getBool(HIDE_UNDOC_MEMBERS);
2603 bool groupFilter = getGroupDef()==0 || container==MemberListContainer::Group || separateMemPages;
2604 bool fileFilter = getNamespaceDef()==0 || !getNamespaceDef()->isLinkable() || container!=MemberListContainer::File;
2605 bool simpleFilter = (hasBriefDescription() || !hideUndocMembers) && inlineSimpleStructs &&
2606 getClassDef()!=0 && getClassDef()->isSimple();
2607
2608 bool visible = hasDetailedDescription() && groupFilter && fileFilter &&
2609 !isReference();
2610 bool result = visible || simpleFilter;
2611 //printf("%s::isDetailedSectionVisible: %d groupFilter=%d fileFilter=%d\n",
2612 // qPrint(name()),result,groupFilter,fileFilter);
2613 return result;
2614 }
2615
getLabels(const Definition * container) const2616 StringVector MemberDefImpl::getLabels(const Definition *container) const
2617 {
2618 StringVector sl;
2619 static bool inlineInfo = Config_getBool(INLINE_INFO);
2620
2621 Specifier lvirt=virtualness();
2622 if ((!isObjCMethod() || isOptional() || isRequired()) &&
2623 (protection()!=Public || lvirt!=Normal ||
2624 isFriend() || isRelated() ||
2625 (isInline() && inlineInfo) ||
2626 isSignal() || isSlot() ||
2627 isStatic() || isExternal() ||
2628 (getClassDef() && getClassDef()!=container && container->definitionType()==TypeClass) ||
2629 (m_impl->memSpec & ~Entry::Inline)!=0
2630 )
2631 )
2632 {
2633 // write the member specifier list
2634 //ol.writeLatexSpacing();
2635 //ol.startTypewriter();
2636 //ol.docify(" [");
2637 SrcLangExt lang = getLanguage();
2638 bool optVhdl = lang==SrcLangExt_VHDL;
2639 static bool extractPrivate = Config_getBool(EXTRACT_PRIVATE);
2640 if (optVhdl)
2641 {
2642 sl.push_back(theTranslator->trVhdlType(getMemberSpecifiers(),TRUE).str());
2643 }
2644 else
2645 {
2646 if (isFriend()) sl.push_back("friend");
2647 else if (isRelated()) sl.push_back("related");
2648 else
2649 {
2650 if (isExternal()) sl.push_back("extern");
2651 if (inlineInfo && isInline()) sl.push_back("inline");
2652 if (isExplicit()) sl.push_back("explicit");
2653 if (isMutable()) sl.push_back("mutable");
2654 if (isStatic()) sl.push_back("static");
2655 if (isGettable()) sl.push_back("get");
2656 if (isProtectedGettable()) sl.push_back("protected get");
2657 if (isSettable()) sl.push_back("set");
2658 if (isProtectedSettable()) sl.push_back("protected set");
2659 if (extractPrivate)
2660 {
2661 if (isPrivateGettable()) sl.push_back("private get");
2662 if (isPrivateSettable()) sl.push_back("private set");
2663 }
2664 if (isConstExpr()) sl.push_back("constexpr");
2665 if (isAddable()) sl.push_back("add");
2666 if (!isUNOProperty() && isRemovable()) sl.push_back("remove");
2667 if (isRaisable()) sl.push_back("raise");
2668 if (isReadable()) sl.push_back("read");
2669 if (isWritable()) sl.push_back("write");
2670 if (isFinal()) sl.push_back("final");
2671 if (isAbstract()) sl.push_back("abstract");
2672 if (isOverride()) sl.push_back("override");
2673 if (isInitonly()) sl.push_back("initonly");
2674 if (isSealed()) sl.push_back("sealed");
2675 if (isNew()) sl.push_back("new");
2676 if (isOptional()) sl.push_back("optional");
2677 if (isRequired()) sl.push_back("required");
2678
2679 if (isNonAtomic()) sl.push_back("nonatomic");
2680 else if (isObjCProperty()) sl.push_back("atomic");
2681
2682 // mutual exclusive Objective 2.0 property attributes
2683 if (isAssign()) sl.push_back("assign");
2684 else if (isCopy()) sl.push_back("copy");
2685 else if (isRetain()) sl.push_back("retain");
2686 else if (isWeak()) sl.push_back("weak");
2687 else if (lang!=SrcLangExt_CSharp && isStrong()) sl.push_back("strong");
2688 else if (isUnretained()) sl.push_back("unsafe_unretained");
2689
2690 if (!isObjCMethod())
2691 {
2692 if (protection()==Protected) sl.push_back("protected");
2693 else if (protection()==Private) sl.push_back("private");
2694 else if (protection()==Package) sl.push_back("package");
2695
2696 if (lvirt==Virtual) sl.push_back("virtual");
2697 else if (lvirt==Pure) sl.push_back("pure virtual");
2698 if (isSignal()) sl.push_back("signal");
2699 if (isSlot()) sl.push_back("slot");
2700 if (isDefault()) sl.push_back("default");
2701 if (isDelete()) sl.push_back("delete");
2702 if (isNoExcept()) sl.push_back("noexcept");
2703 if (isAttribute()) sl.push_back("attribute");
2704 if (isUNOProperty()) sl.push_back("property");
2705 if (isReadonly()) sl.push_back("readonly");
2706 if (isBound()) sl.push_back("bound");
2707 if (isUNOProperty() && isRemovable()) sl.push_back("removable");
2708 if (isConstrained()) sl.push_back("constrained");
2709 if (isTransient()) sl.push_back("transient");
2710 if (isMaybeVoid()) sl.push_back("maybevoid");
2711 if (isMaybeDefault()) sl.push_back("maybedefault");
2712 if (isMaybeAmbiguous()) sl.push_back("maybeambiguous");
2713 if (isPublished()) sl.push_back("published"); // enum
2714 }
2715 if (isObjCProperty() && isImplementation())
2716 {
2717 sl.push_back("implementation");
2718 }
2719 }
2720 if (getClassDef() &&
2721 container->definitionType()==TypeClass &&
2722 getClassDef()!=container &&
2723 !isRelated()
2724 )
2725 {
2726 sl.push_back("inherited");
2727 }
2728 }
2729 }
2730 else if (isObjCMethod() && isImplementation())
2731 {
2732 sl.push_back("implementation");
2733 }
2734 return sl;
2735 }
2736
_writeCallGraph(OutputList & ol) const2737 void MemberDefImpl::_writeCallGraph(OutputList &ol) const
2738 {
2739 // write call graph
2740 if (_hasVisibleCallGraph())
2741 {
2742 DotCallGraph callGraph(this,FALSE);
2743 if (callGraph.isTooBig())
2744 {
2745 warn_uncond("Call graph for '%s' not generated, too many nodes (%d), threshold is %d. Consider increasing DOT_GRAPH_MAX_NODES.\n",
2746 qPrint(qualifiedName()), callGraph.numNodes(), Config_getInt(DOT_GRAPH_MAX_NODES));
2747 }
2748 else if (!callGraph.isTrivial())
2749 {
2750 msg("Generating call graph for function %s\n",qPrint(qualifiedName()));
2751 ol.disable(OutputGenerator::Man);
2752 ol.startCallGraph();
2753 ol.parseText(theTranslator->trCallGraph());
2754 ol.endCallGraph(callGraph);
2755 ol.enableAll();
2756 }
2757 }
2758 }
2759
_writeCallerGraph(OutputList & ol) const2760 void MemberDefImpl::_writeCallerGraph(OutputList &ol) const
2761 {
2762 if (_hasVisibleCallerGraph())
2763 {
2764 DotCallGraph callerGraph(this, TRUE);
2765 if (callerGraph.isTooBig())
2766 {
2767 warn_uncond("Caller graph for '%s' not generated, too many nodes (%d), threshold is %d. Consider increasing DOT_GRAPH_MAX_NODES.\n",
2768 qPrint(qualifiedName()), callerGraph.numNodes(), Config_getInt(DOT_GRAPH_MAX_NODES));
2769 }
2770 else if (!callerGraph.isTrivial())
2771 {
2772 msg("Generating caller graph for function %s\n",qPrint(qualifiedName()));
2773 ol.disable(OutputGenerator::Man);
2774 ol.startCallGraph();
2775 ol.parseText(theTranslator->trCallerGraph());
2776 ol.endCallGraph(callerGraph);
2777 ol.enableAll();
2778 }
2779 }
2780 }
2781
_isReimplements() const2782 bool MemberDefImpl::_isReimplements() const
2783 {
2784 const MemberDef *bmd=reimplements();
2785 const ClassDef *bcd=0;
2786 if (bmd && (bcd=bmd->getClassDef()))
2787 {
2788 // write class that contains a member that is reimplemented by this one
2789 if (bcd->isLinkable())
2790 {
2791 return true;
2792 }
2793 }
2794 return false;
2795 }
_writeReimplements(OutputList & ol) const2796 void MemberDefImpl::_writeReimplements(OutputList &ol) const
2797 {
2798 const MemberDef *bmd=reimplements();
2799 const ClassDef *bcd=0;
2800 if (bmd && (bcd=bmd->getClassDef()))
2801 {
2802 // write class that contains a member that is reimplemented by this one
2803 if (bcd->isLinkable())
2804 {
2805 ol.startParagraph();
2806 QCString reimplFromLine;
2807 if (bmd->virtualness()!=Pure && bcd->compoundType()!=ClassDef::Interface)
2808 {
2809 reimplFromLine = theTranslator->trReimplementedFromList(1);
2810 }
2811 else
2812 {
2813 reimplFromLine = theTranslator->trImplementedFromList(1);
2814 }
2815 int markerPos = reimplFromLine.find("@0");
2816 if (markerPos!=-1) // should always pass this.
2817 {
2818 ol.parseText(reimplFromLine.left(markerPos)); //text left from marker
2819 if (bmd->isLinkable()) // replace marker with link
2820 {
2821 //Definition *bd=bmd->group;
2822 //if (bd==0) bd=bcd;
2823 ol.writeObjectLink(bmd->getReference(),bmd->getOutputFileBase(),
2824 bmd->anchor(),bcd->displayName());
2825
2826 //ol.writeObjectLink(bcd->getReference(),bcd->getOutputFileBase(),
2827 // bmd->anchor(),bcd->name());
2828 if ( bmd->isLinkableInProject() )
2829 {
2830 writePageRef(ol,bmd->getOutputFileBase(),bmd->anchor());
2831 }
2832 }
2833 else
2834 {
2835 ol.writeObjectLink(bcd->getReference(),bcd->getOutputFileBase(),
2836 QCString(),bcd->displayName());
2837 if (bcd->isLinkableInProject()/* && !Config_getBool(PDF_HYPERLINKS)*/ )
2838 {
2839 writePageRef(ol,bcd->getOutputFileBase(),bcd->anchor());
2840 }
2841 }
2842 ol.parseText(reimplFromLine.right(
2843 reimplFromLine.length()-markerPos-2)); // text right from marker
2844
2845 }
2846 else
2847 {
2848 err("translation error: no marker in trReimplementsFromList()\n");
2849 }
2850 ol.endParagraph();
2851 }
2852 }
2853 }
2854
_countReimplementedBy() const2855 size_t MemberDefImpl::_countReimplementedBy() const
2856 {
2857 const MemberVector &bml=reimplementedBy();
2858 size_t count=0;
2859 for (const auto &bmd : bml)
2860 {
2861 const ClassDef *bcd=bmd->getClassDef();
2862 // count the members that directly inherit from md and for
2863 // which the member and class are visible in the docs.
2864 if ( bcd && bmd->isLinkable() && bcd->isLinkable() )
2865 {
2866 count++;
2867 }
2868 }
2869 return count;
2870 }
2871
_writeReimplementedBy(OutputList & ol) const2872 void MemberDefImpl::_writeReimplementedBy(OutputList &ol) const
2873 {
2874 const MemberVector &bml=reimplementedBy();
2875 size_t count = _countReimplementedBy();
2876 if (count>0)
2877 {
2878 auto replaceFunc = [&bml,&ol](size_t entryIndex)
2879 {
2880 size_t cnt=0;
2881 auto it = bml.begin();
2882 // find the entryIndex-th documented entry in the inheritance list.
2883 const MemberDef *bmd = 0;
2884 const ClassDef *bcd = 0;
2885 while (it!=bml.end())
2886 {
2887 bmd = *it;
2888 bcd = bmd->getClassDef();
2889 if ( bmd->isLinkable() && bcd->isLinkable())
2890 {
2891 if (cnt==entryIndex) break;
2892 cnt++;
2893 }
2894 ++it;
2895 }
2896
2897 if (bcd && bmd) // write link for marker
2898 {
2899 //ol.writeObjectLink(bcd->getReference(),bcd->getOutputFileBase(),
2900 // bmd->anchor(),bcd->name());
2901 ol.writeObjectLink(bmd->getReference(),bmd->getOutputFileBase(),
2902 bmd->anchor(),bcd->displayName());
2903
2904 if (bmd->isLinkableInProject() )
2905 {
2906 writePageRef(ol,bmd->getOutputFileBase(),bmd->anchor());
2907 }
2908 }
2909 };
2910
2911 QCString reimplInLine;
2912 if (m_impl->virt==Pure || (getClassDef() && getClassDef()->compoundType()==ClassDef::Interface))
2913 {
2914 reimplInLine = theTranslator->trImplementedInList((int)count);
2915 }
2916 else
2917 {
2918 reimplInLine = theTranslator->trReimplementedInList((int)count);
2919 }
2920
2921 // write the list of classes that overwrite this member
2922 ol.startParagraph();
2923 writeMarkerList(ol,
2924 reimplInLine.str(),
2925 count,
2926 replaceFunc);
2927 ol.endParagraph();
2928 }
2929 }
2930
_writeCategoryRelation(OutputList & ol) const2931 void MemberDefImpl::_writeCategoryRelation(OutputList &ol) const
2932 {
2933 if (getClassDef()) // this should be a member of a class/category
2934 {
2935 //printf("%s: category %s relation %s class=%s categoryOf=%s\n",
2936 // qPrint(name()),
2937 // m_impl->category ? qPrint(m_impl->category->name()) : "<none>",
2938 // m_impl->categoryRelation ? qPrint(m_impl->categoryRelation->name()) : "<none>",
2939 // qPrint(m_impl->classDef->name()),
2940 // m_impl->classDef->categoryOf() ? qPrint(m_impl->classDef->categoryOf()->name()) : "<none>"
2941 // );
2942 QCString text;
2943 QCString ref;
2944 QCString file;
2945 QCString anc;
2946 QCString name;
2947 int i=-1;
2948 if (m_impl->categoryRelation && m_impl->categoryRelation->isLinkable())
2949 {
2950 if (m_impl->category)
2951 {
2952 // this member is in a normal class and implements method categoryRelation from category
2953 // so link to method 'categoryRelation' with 'provided by category 'category' text.
2954 text = theTranslator->trProvidedByCategory();
2955 name = m_impl->category->displayName();
2956 }
2957 else if (getClassDef()->categoryOf())
2958 {
2959 // this member is part of a category so link to the corresponding class member of the class we extend
2960 // so link to method 'categoryRelation' with 'extends class 'classDef->categoryOf()'
2961 text = theTranslator->trExtendsClass();
2962 name = getClassDef()->categoryOf()->displayName();
2963 }
2964 i=text.find("@0");
2965 if (i!=-1)
2966 {
2967 const MemberDef *md = m_impl->categoryRelation;
2968 ref = md->getReference();
2969 file = md->getOutputFileBase();
2970 anc = md->anchor();
2971 }
2972 }
2973 if (i!=-1 && !name.isEmpty())
2974 {
2975 ol.startParagraph();
2976 ol.parseText(text.left(i));
2977 ol.writeObjectLink(ref,file,anc,name);
2978 ol.parseText(text.mid(i+2));
2979 ol.endParagraph();
2980 }
2981 }
2982 }
2983
_writeExamples(OutputList & ol) const2984 void MemberDefImpl::_writeExamples(OutputList &ol) const
2985 {
2986 // write the list of examples that use this member
2987 if (hasExamples())
2988 {
2989 ol.startExamples();
2990 ol.startDescForItem();
2991 writeExamples(ol,m_impl->examples);
2992 ol.endDescForItem();
2993 ol.endExamples();
2994 }
2995 }
2996
_writeTypeConstraints(OutputList & ol) const2997 void MemberDefImpl::_writeTypeConstraints(OutputList &ol) const
2998 {
2999 if (m_impl->typeConstraints.hasParameters())
3000 {
3001 writeTypeConstraints(ol,this,m_impl->typeConstraints);
3002 }
3003 }
3004
_writeEnumValues(OutputList & ol,const Definition * container,const QCString & cfname,const QCString & ciname,const QCString & cname) const3005 void MemberDefImpl::_writeEnumValues(OutputList &ol,const Definition *container,
3006 const QCString &cfname,const QCString &ciname,
3007 const QCString &cname) const
3008 {
3009 // For enum, we also write the documented enum values
3010 if (isEnumerate())
3011 {
3012 bool first=TRUE;
3013 //printf("** %s: enum values=%zu\n",qPrint(name()),enumFieldList().size());
3014 for (const auto &fmd : enumFieldList())
3015 {
3016 //printf("Enum %p: isLinkable()=%d\n",fmd,fmd->isLinkable());
3017 if (fmd->isLinkable())
3018 {
3019 if (first)
3020 {
3021 ol.startDescTable(theTranslator->trEnumerationValues());
3022 }
3023
3024 ol.startDescTableRow();
3025 ol.addIndexItem(fmd->name(),ciname);
3026 ol.addIndexItem(ciname,fmd->name());
3027
3028 ol.startDescTableTitle();
3029 ol.startDoxyAnchor(cfname,cname,fmd->anchor(),fmd->name(),fmd->argsString());
3030 first=FALSE;
3031 ol.docify(fmd->name());
3032 ol.disableAllBut(OutputGenerator::Man);
3033 ol.writeString(" ");
3034 ol.enableAll();
3035 ol.endDoxyAnchor(cfname,fmd->anchor());
3036 ol.endDescTableTitle();
3037 ol.startDescTableData();
3038
3039 bool hasBrief = !fmd->briefDescription().isEmpty();
3040 bool hasDetails = !fmd->documentation().isEmpty();
3041
3042 if (hasBrief)
3043 {
3044 ol.generateDoc(fmd->briefFile(),fmd->briefLine(),
3045 getOuterScope()?getOuterScope():container,
3046 fmd,fmd->briefDescription(),TRUE,FALSE,
3047 QCString(),FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT));
3048 }
3049 // FIXME:PARA
3050 //if (!fmd->briefDescription().isEmpty() &&
3051 // !fmd->documentation().isEmpty())
3052 //{
3053 // ol.newParagraph();
3054 //}
3055 if (hasDetails)
3056 {
3057 ol.generateDoc(fmd->docFile(),fmd->docLine(),
3058 getOuterScope()?getOuterScope():container,
3059 fmd,fmd->documentation()+"\n",TRUE,FALSE,
3060 QCString(),FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT));
3061 }
3062 ol.endDescTableData();
3063 ol.endDescTableRow();
3064 }
3065 }
3066 if (!first)
3067 {
3068 ol.endDescTable();
3069 }
3070 }
3071 }
3072
3073 // match from the start of the scope until the last marker
3074 static const reg::Ex reAnonymous(R"([\w:@]*@\d+)");
3075
displayDefinition() const3076 QCString MemberDefImpl::displayDefinition() const
3077 {
3078 QCString ldef = definition();
3079 QCString title = name();
3080 if (isEnumerate())
3081 {
3082 if (isAnonymous())
3083 {
3084 ldef = title = "anonymous enum";
3085 if (!m_impl->enumBaseType.isEmpty())
3086 {
3087 ldef+=" : "+m_impl->enumBaseType;
3088 }
3089 }
3090 else
3091 {
3092 ldef.prepend("enum ");
3093 if (isSliceLocal())
3094 {
3095 ldef.prepend("local ");
3096 }
3097 }
3098 }
3099 else if (isEnumValue())
3100 {
3101 if (isAnonymous())
3102 {
3103 ldef=ldef.mid(2);
3104 }
3105 }
3106
3107 std::string sdef = ldef.str();
3108 reg::Match match;
3109 if (reg::search(sdef,match,reAnonymous))
3110 {
3111 ldef = match.prefix().str() + " { ... } " + match.suffix().str();
3112 }
3113
3114 const ClassDef *cd=getClassDef();
3115 if (cd && cd->isObjectiveC())
3116 {
3117 // strip scope name
3118 int ep = ldef.find("::");
3119 if (ep!=-1)
3120 {
3121 int sp=ldef.findRev(' ',ep);
3122 if (sp!=-1)
3123 {
3124 ldef=ldef.left(sp+1)+ldef.mid(ep+2);
3125 }
3126 }
3127 // strip keywords
3128 int dp = ldef.find(':');
3129 if (dp!=-1)
3130 {
3131 ldef=ldef.left(dp+1);
3132 }
3133 int l=ldef.length();
3134 //printf("start >%s<\n",qPrint(ldef));
3135 int i=l-1;
3136 while (i>=0 && (isId(ldef.at(i)) || ldef.at(i)==':')) i--;
3137 while (i>=0 && isspace((uchar)ldef.at(i))) i--;
3138 if (i>0)
3139 {
3140 // insert braches around the type
3141 QCString tmp("("+ldef.left(i+1)+")"+ldef.mid(i+1));
3142 ldef=tmp;
3143 }
3144 //printf("end >%s< i=%d\n",qPrint(ldef),i);
3145 if (isStatic()) ldef.prepend("+ "); else ldef.prepend("- ");
3146 }
3147 SrcLangExt lang = getLanguage();
3148 QCString sep = getLanguageSpecificSeparator(lang,TRUE);
3149 return substitute(ldef,"::",sep);
3150 }
3151
_writeGroupInclude(OutputList & ol,bool inGroup) const3152 void MemberDefImpl::_writeGroupInclude(OutputList &ol,bool inGroup) const
3153 {
3154 // only write out the include file if this is not part of a class or file
3155 // definition
3156 static bool showGroupedMembInc = Config_getBool(SHOW_GROUPED_MEMB_INC);
3157 const FileDef *fd = getFileDef();
3158 QCString nm;
3159 if (fd) nm = getFileDef()->docName();
3160 if (inGroup && fd && showGroupedMembInc && !nm.isEmpty())
3161 {
3162 ol.startParagraph();
3163 ol.startTypewriter();
3164 SrcLangExt lang = getLanguage();
3165 bool isIDLorJava = lang==SrcLangExt_IDL || lang==SrcLangExt_Java;
3166 if (isIDLorJava)
3167 {
3168 ol.docify("import ");
3169 }
3170 else
3171 {
3172 ol.docify("#include ");
3173 }
3174
3175 if (isIDLorJava) ol.docify("\""); else ol.docify("<");
3176
3177 if (fd->isLinkable())
3178 {
3179 ol.writeObjectLink(fd->getReference(),fd->getOutputFileBase(),fd->anchor(),nm);
3180 }
3181 else
3182 {
3183 ol.docify(nm);
3184 }
3185
3186 if (isIDLorJava) ol.docify("\""); else ol.docify(">");
3187
3188 ol.endTypewriter();
3189 ol.endParagraph();
3190 }
3191 }
3192
_writeMultiLineInitializer(OutputList & ol,const QCString & scopeName) const3193 void MemberDefImpl::_writeMultiLineInitializer(OutputList &ol,const QCString &scopeName) const
3194 {
3195 //printf("md=%s initLines=%d init='%s'\n",qPrint(name()),initLines,qPrint(init));
3196 ol.startBold();
3197 if (m_impl->mtype==MemberType_Define)
3198 ol.parseText(theTranslator->trDefineValue());
3199 else
3200 ol.parseText(theTranslator->trInitialValue());
3201 ol.endBold();
3202 QCString langCorrected = getDefFileExtension();
3203 SrcLangExt srcLangExt = getLanguageFromFileName(getDefFileExtension());
3204 if (srcLangExt == SrcLangExt_Lex)
3205 {
3206 langCorrected = ".doxygen_lex_c";
3207 srcLangExt = SrcLangExt_Cpp;
3208 }
3209 auto intf = Doxygen::parserManager->getCodeParser(langCorrected);
3210 intf->resetCodeParserState();
3211 ol.startCodeFragment("DoxyCode");
3212 intf->parseCode(ol,scopeName,m_impl->initializer,srcLangExt,FALSE,QCString(),const_cast<FileDef*>(getFileDef()),
3213 -1,-1,TRUE,this,FALSE,this);
3214 ol.endCodeFragment("DoxyCode");
3215 }
3216
3217 /*! Writes the "detailed documentation" section of this member to
3218 * all active output formats.
3219 */
writeDocumentation(const MemberList * ml,int memCount,int memTotal,OutputList & ol,const QCString & scName,const Definition * container,bool inGroup,bool showEnumValues,bool showInline) const3220 void MemberDefImpl::writeDocumentation(const MemberList *ml,
3221 int memCount,int memTotal,
3222 OutputList &ol,
3223 const QCString &scName,
3224 const Definition *container,
3225 bool inGroup,
3226 bool showEnumValues,
3227 bool showInline
3228 ) const
3229 {
3230 // if this member is in a group find the real scope name.
3231 bool hasParameterList = FALSE;
3232
3233 //printf("MemberDefImpl::writeDocumentation(): name='%s' hasDocs='%d' containerType=%d inGroup=%d sectionLinkable=%d\n",
3234 // qPrint(name()),hasDocs,container->definitionType(),inGroup,hasDetailedDescription());
3235
3236 //if ( !hasDocs ) return;
3237 //if (isEnumValue() && !showEnumValues) return;
3238
3239 SrcLangExt lang = getLanguage();
3240 //printf("member=%s lang=%d\n",qPrint(name()),lang);
3241 bool optVhdl = lang==SrcLangExt_VHDL;
3242 QCString sep = getLanguageSpecificSeparator(lang,TRUE);
3243
3244 QCString scopeName = scName;
3245 QCString memAnchor = anchor();
3246 QCString ciname = container->displayName();
3247 const Definition *scopedContainer = container; // see bug 753608
3248 if (container->definitionType()==TypeGroup)
3249 {
3250 if (getClassDef()) { scopeName=getClassDef()->displayName(); scopedContainer=getClassDef(); }
3251 else if (getNamespaceDef()) { scopeName=getNamespaceDef()->displayName(); scopedContainer=getNamespaceDef(); }
3252 else if (getFileDef()) { scopeName=getFileDef()->displayName(); scopedContainer=getFileDef(); }
3253 ciname = (toGroupDef(container))->groupTitle();
3254 }
3255 else if (container->definitionType()==TypeFile && getNamespaceDef() && getNamespaceDef()->isLinkable())
3256 { // member is in a namespace, but is written as part of the file documentation
3257 // as well, so we need to make sure its anchor is unique (it is not really used).
3258 memAnchor.prepend("file_");
3259 }
3260
3261 QCString cname = container->name();
3262 QCString cfname = getOutputFileBase();
3263
3264 // get member name
3265 QCString doxyName=name();
3266 // prepend scope if there is any. TODO: make this optional for C only docs
3267 if (!scopeName.isEmpty())
3268 {
3269 doxyName.prepend(scopeName+sep);
3270 }
3271 QCString doxyArgs=argsString();
3272
3273 QCString ldef = definition();
3274 QCString title = name();
3275 //printf("member '%s' def='%s'\n",qPrint(name()),qPrint(ldef));
3276 if (isEnumerate())
3277 {
3278 if (title.at(0)=='@')
3279 {
3280 ldef = title = "anonymous enum";
3281 if (!m_impl->enumBaseType.isEmpty())
3282 {
3283 ldef+=" : "+m_impl->enumBaseType;
3284 }
3285 }
3286 else
3287 {
3288 if (lang==SrcLangExt_Cpp)
3289 {
3290 if (isEnumStruct()) ldef.prepend("struct ");
3291 else if (isStrong()) ldef.prepend("class ");
3292 }
3293 ldef.prepend("enum ");
3294 if (isSliceLocal())
3295 {
3296 ldef.prepend("local ");
3297 }
3298 }
3299 }
3300 else if (isEnumValue())
3301 {
3302 if (ldef.at(0)=='@')
3303 {
3304 ldef=ldef.mid(2);
3305 }
3306 }
3307 else if (isFunction() && !isObjCMethod())
3308 {
3309 title += "()";
3310 }
3311 if (lang == SrcLangExt_Slice)
3312 {
3313 // Remove the container scope from the member name.
3314 QCString prefix = scName + sep;
3315 int pos = ldef.findRev(prefix.data());
3316 if(pos != -1)
3317 {
3318 ldef.remove(pos, prefix.length());
3319 }
3320 }
3321
3322 //----------------------------------------
3323
3324 ol.pushGeneratorState();
3325
3326 bool htmlEndLabelTable=FALSE;
3327 StringVector sl = getLabels(scopedContainer);
3328
3329 static const reg::Ex r(R"(@\d+)");
3330 reg::Match match;
3331 std::string sdef = ldef.str();
3332 if ((isVariable() || isTypedef()) && reg::search(sdef,match,r))
3333 {
3334 // find enum type and insert it in the definition
3335 bool found=false;
3336 for (const auto &vmd : *ml)
3337 {
3338 if (vmd->isEnumerate() && match.str()==vmd->name())
3339 {
3340 ol.startDoxyAnchor(cfname,cname,memAnchor,doxyName,doxyArgs);
3341 ol.startMemberDoc(ciname,name(),memAnchor,name(),memCount,memTotal,showInline);
3342 std::string prefix = match.prefix().str();
3343 std::string suffix = match.suffix().str();
3344 linkifyText(TextGeneratorOLImpl(ol),scopedContainer,getBodyDef(),this,prefix.c_str());
3345 vmd->writeEnumDeclaration(ol,getClassDef(),getNamespaceDef(),getFileDef(),getGroupDef());
3346 linkifyText(TextGeneratorOLImpl(ol),scopedContainer,getBodyDef(),this,suffix.c_str());
3347
3348 found=true;
3349 break;
3350 }
3351 }
3352 if (!found) // anonymous compound
3353 {
3354 //printf("Anonymous compound '%s'\n",qPrint(cname));
3355 ol.startDoxyAnchor(cfname,cname,memAnchor,doxyName,doxyArgs);
3356 ol.startMemberDoc(ciname,name(),memAnchor,"",memCount,memTotal,showInline);
3357 // search for the last anonymous compound name in the definition
3358
3359 ol.startMemberDocName(isObjCMethod());
3360 if (reg::search(sdef,match,reAnonymous))
3361 {
3362 std::string prefix = match.prefix().str();
3363 std::string suffix = match.suffix().str();
3364 ol.docify(prefix.c_str());
3365 ol.docify(" { ... } ");
3366 linkifyText(TextGeneratorOLImpl(ol),scopedContainer,getBodyDef(),this,suffix.c_str());
3367 }
3368 else
3369 {
3370 linkifyText(TextGeneratorOLImpl(ol),scopedContainer,getBodyDef(),this,ldef);
3371 }
3372 }
3373 }
3374 else // not an enum value or anonymous compound
3375 {
3376 ol.startDoxyAnchor(cfname,cname,memAnchor,doxyName,doxyArgs);
3377 ol.startMemberDoc(ciname,name(),memAnchor,title,memCount,memTotal,showInline);
3378
3379 if (!m_impl->metaData.isEmpty() && getLanguage()==SrcLangExt_Slice)
3380 {
3381 ol.startMemberDocPrefixItem();
3382 ol.docify(m_impl->metaData);
3383 ol.endMemberDocPrefixItem();
3384 }
3385
3386 const ClassDef *cd=getClassDef();
3387 const NamespaceDef *nd=getNamespaceDef();
3388 if (!Config_getBool(HIDE_SCOPE_NAMES))
3389 {
3390 bool first=TRUE;
3391 if (!m_impl->defTmpArgLists.empty() && lang==SrcLangExt_Cpp)
3392 // definition has explicit template parameter declarations
3393 {
3394 for (const ArgumentList &tal : m_impl->defTmpArgLists)
3395 {
3396 if (!tal.empty())
3397 {
3398 if (!first) ol.docify(" ");
3399 ol.startMemberDocPrefixItem();
3400 _writeTemplatePrefix(ol,scopedContainer,tal);
3401 ol.endMemberDocPrefixItem();
3402 }
3403 }
3404 }
3405 else // definition gets it template parameters from its class
3406 // (since no definition was found)
3407 {
3408 if (cd && lang==SrcLangExt_Cpp && !isTemplateSpecialization())
3409 {
3410 for (const ArgumentList &tal : cd->getTemplateParameterLists())
3411 {
3412 if (!tal.empty())
3413 {
3414 if (!first) ol.docify(" ");
3415 ol.startMemberDocPrefixItem();
3416 _writeTemplatePrefix(ol,scopedContainer,tal,false);
3417 ol.endMemberDocPrefixItem();
3418 }
3419 }
3420 }
3421 if (m_impl->tArgList.hasParameters() && lang==SrcLangExt_Cpp) // function template prefix
3422 {
3423 ol.startMemberDocPrefixItem();
3424 _writeTemplatePrefix(ol,scopedContainer,m_impl->tArgList);
3425 ol.endMemberDocPrefixItem();
3426 }
3427 }
3428 }
3429
3430 if (!sl.empty())
3431 {
3432 ol.pushGeneratorState();
3433 ol.disableAll();
3434 ol.enable(OutputGenerator::Html);
3435 ol.writeString("<table class=\"mlabels\">\n");
3436 ol.writeString(" <tr>\n");
3437 ol.writeString(" <td class=\"mlabels-left\">\n");
3438 ol.popGeneratorState();
3439 htmlEndLabelTable=TRUE;
3440 }
3441
3442 ol.startMemberDocName(isObjCMethod());
3443 if (cd && cd->isObjectiveC())
3444 {
3445 // strip scope name
3446 int ep = ldef.find("::");
3447 if (ep!=-1)
3448 {
3449 int sp=ldef.findRev(' ',ep);
3450 if (sp!=-1)
3451 {
3452 ldef=ldef.left(sp+1)+ldef.mid(ep+2);
3453 } else {
3454 ldef=ldef.mid(ep+2);
3455 }
3456 }
3457 // strip keywords
3458 int dp = ldef.find(':');
3459 if (dp!=-1)
3460 {
3461 ldef=ldef.left(dp+1);
3462 }
3463 int dl=ldef.length();
3464 //printf("start >%s<\n",qPrint(ldef));
3465 int i=dl-1;
3466 while (i>=0 && (isId(ldef.at(i)) || ldef.at(i)==':')) i--;
3467 while (i>=0 && isspace((uchar)ldef.at(i))) i--;
3468 if (i>0)
3469 {
3470 // insert braches around the type
3471 QCString tmp("("+ldef.left(i+1)+")"+ldef.mid(i+1));
3472 ldef=tmp;
3473 }
3474 //printf("end >%s< i=%d\n",qPrint(ldef),i);
3475 if (isStatic()) ldef.prepend("+ "); else ldef.prepend("- ");
3476 }
3477
3478 if (optVhdl)
3479 {
3480 hasParameterList=VhdlDocGen::writeVHDLTypeDocumentation(this,scopedContainer,ol);
3481 }
3482 else if (lang==SrcLangExt_Slice)
3483 {
3484 // Eliminate the self-reference.
3485 int pos = ldef.findRev(' ');
3486 if (pos<0) pos=0;
3487 if (pos>0)
3488 {
3489 linkifyText(TextGeneratorOLImpl(ol),
3490 scopedContainer,
3491 getBodyDef(),
3492 this,
3493 ldef.left(pos)
3494 );
3495 }
3496 ol.docify(ldef.mid(pos));
3497 const Definition *scope = cd;
3498 if (scope==0) scope = nd;
3499 hasParameterList=writeDefArgumentList(ol,scope,this);
3500 }
3501 else
3502 {
3503 linkifyText(TextGeneratorOLImpl(ol),
3504 scopedContainer,
3505 getBodyDef(),
3506 this,
3507 substitute(ldef,"::",sep)
3508 );
3509 const Definition *scope = cd;
3510 if (scope==0) scope = nd;
3511 hasParameterList=writeDefArgumentList(ol,scope,this);
3512 }
3513
3514 if (hasOneLineInitializer()) // add initializer
3515 {
3516 if (!isDefine())
3517 {
3518 //ol.docify(" = ");
3519 ol.docify(" ");
3520 QCString init = m_impl->initializer.simplifyWhiteSpace();
3521 linkifyText(TextGeneratorOLImpl(ol),scopedContainer,getBodyDef(),this,init);
3522 }
3523 else
3524 {
3525 ol.writeNonBreakableSpace(3);
3526 linkifyText(TextGeneratorOLImpl(ol),scopedContainer,getBodyDef(),this,m_impl->initializer);
3527 }
3528 }
3529 if (!excpString().isEmpty()) // add exception list
3530 {
3531 writeExceptionList(ol,cd,this);
3532 hasParameterList=true; // call endParameterList below
3533 }
3534 }
3535
3536 ol.pushGeneratorState();
3537 ol.disable(OutputGenerator::Html);
3538 if (!sl.empty())
3539 {
3540 ol.startLabels();
3541 size_t count=0;
3542 for (const auto &s : sl)
3543 {
3544 count++;
3545 ol.writeLabel(s.c_str(),count==sl.size());
3546 }
3547 ol.endLabels();
3548 }
3549 ol.popGeneratorState();
3550
3551 if (hasParameterList)
3552 {
3553 ol.endParameterList();
3554 ol.endMemberDoc(TRUE);
3555 }
3556 else
3557 {
3558 ol.endMemberDocName();
3559 ol.endMemberDoc(FALSE);
3560 }
3561
3562 // for HTML write the labels here
3563 ol.pushGeneratorState();
3564 ol.disableAll();
3565 ol.enable(OutputGenerator::Html);
3566 if (htmlEndLabelTable)
3567 {
3568 ol.writeString(" </td>\n");
3569 ol.writeString(" <td class=\"mlabels-right\">\n");
3570 ol.startLabels();
3571 size_t count=0;
3572 for (const auto &s : sl)
3573 {
3574 count++;
3575 ol.writeLabel(s.c_str(),count==sl.size());
3576 }
3577 ol.endLabels();
3578 ol.writeString(" </td>\n");
3579 ol.writeString(" </tr>\n");
3580 ol.writeString("</table>\n");
3581 }
3582 ol.writeString("</div>");
3583 ol.popGeneratorState();
3584
3585
3586 ol.endDoxyAnchor(cfname,memAnchor);
3587 ol.startIndent();
3588
3589 _writeGroupInclude(ol,inGroup);
3590
3591 /* write multi-line initializer (if any) */
3592 if (hasMultiLineInitializer()) _writeMultiLineInitializer(ol,scopeName);
3593
3594 /* write brief description */
3595 QCString brief = briefDescription();
3596 if (!brief.isEmpty() &&
3597 (Config_getBool(REPEAT_BRIEF) ||
3598 !Config_getBool(BRIEF_MEMBER_DESC)
3599 )
3600 )
3601 {
3602 ol.startParagraph();
3603 ol.generateDoc(briefFile(),briefLine(),
3604 scopedContainer,this,
3605 brief,FALSE,FALSE,
3606 QCString(),TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT));
3607 ol.endParagraph();
3608 }
3609
3610 /* write detailed description */
3611 QCString detailed = documentation();
3612 if (!detailed.isEmpty() ||
3613 !inbodyDocumentation().isEmpty())
3614 {
3615 // write vhdl inline code with or without option INLINE_SOURCE
3616 if (optVhdl && VhdlDocGen::isMisc(this))
3617 {
3618 VhdlDocGen::writeSource(this,ol,cname);
3619 return;
3620 }
3621 else
3622 {
3623 ol.generateDoc(docFile(),docLine(),scopedContainer,this,detailed+"\n",TRUE,FALSE,
3624 QCString(),FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT));
3625 }
3626
3627 if (!inbodyDocumentation().isEmpty())
3628 {
3629 ol.generateDoc(inbodyFile(),inbodyLine(),
3630 scopedContainer,this,
3631 inbodyDocumentation()+"\n",TRUE,FALSE,
3632 QCString(),FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT));
3633 }
3634 }
3635 else if (!brief.isEmpty() && (Config_getBool(REPEAT_BRIEF) || !Config_getBool(BRIEF_MEMBER_DESC)))
3636 {
3637 if (!inbodyDocumentation().isEmpty())
3638 {
3639 ol.generateDoc(inbodyFile(),inbodyLine(),scopedContainer,this,inbodyDocumentation()+"\n",TRUE,FALSE,
3640 QCString(),FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT));
3641 }
3642 }
3643
3644
3645 //printf("***** defArgList=%p name=%s docs=%s hasDocs=%d\n",
3646 // defArgList,
3647 // defArgList?defArgList->hasDocumentation():-1);
3648 const ArgumentList &docArgList = m_impl->templateMaster ?
3649 m_impl->templateMaster->argumentList() :
3650 m_impl->defArgList;
3651 if (docArgList.hasDocumentation())
3652 {
3653 QCString paramDocs;
3654 for (const Argument &a : docArgList)
3655 {
3656 if (a.hasDocumentation())
3657 {
3658 QCString docsWithoutDir = a.docs;
3659 QCString direction = extractDirection(docsWithoutDir);
3660 paramDocs+="@param"+direction+" "+a.name+" "+docsWithoutDir;
3661 }
3662 }
3663 // feed the result to the documentation parser
3664 ol.generateDoc(
3665 docFile(),docLine(),
3666 scopedContainer,
3667 this, // memberDef
3668 paramDocs, // docStr
3669 TRUE, // indexWords
3670 FALSE, // isExample
3671 QCString(),FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)
3672 );
3673
3674 }
3675
3676 _writeEnumValues(ol,scopedContainer,cfname,ciname,cname);
3677 _writeReimplements(ol);
3678 _writeReimplementedBy(ol);
3679 _writeCategoryRelation(ol);
3680 _writeExamples(ol);
3681 _writeTypeConstraints(ol);
3682 writeSourceDef(ol,cname);
3683 writeInlineCode(ol,cname);
3684 if (hasReferencesRelation()) writeSourceRefs(ol,cname);
3685 if (hasReferencedByRelation()) writeSourceReffedBy(ol,cname);
3686 _writeCallGraph(ol);
3687 _writeCallerGraph(ol);
3688
3689 ol.endIndent();
3690
3691 // enable LaTeX again
3692 //if (Config_getBool(EXTRACT_ALL) && !hasDocs) ol.enable(OutputGenerator::Latex);
3693 ol.popGeneratorState();
3694
3695 warnIfUndocumentedParams();
3696 }
3697
3698 // strip scope and field name from the type
3699 // example: "struct N<K::J>::S.v.c" will become "struct v"
simplifyTypeForTable(const QCString & s)3700 static QCString simplifyTypeForTable(const QCString &s)
3701 {
3702 QCString ts=removeAnonymousScopes(s);
3703 if (ts.right(2)=="::") ts = ts.left(ts.length()-2);
3704 static const reg::Ex re1(R"(\a\w*::)"); // non-template version
3705 static const reg::Ex re2(R"(\a\w*<[^>]*>::)"); // template version
3706 reg::Match match;
3707 std::string t = ts.str();
3708 while (reg::search(t,match,re2) || reg::search(t,match,re1))
3709 {
3710 t = match.prefix().str() + match.suffix().str(); // remove the matched part
3711 }
3712 //printf("simplifyTypeForTable(%s)->%s\n",qPrint(s),t.c_str());
3713 return QCString(t);
3714 }
3715
fieldType() const3716 QCString MemberDefImpl::fieldType() const
3717 {
3718 QCString type = m_impl->accessorType;
3719 if (type.isEmpty())
3720 {
3721 type = m_impl->type;
3722 }
3723
3724 if (isTypedef() && getLanguage() != SrcLangExt_Slice) type.prepend("typedef ");
3725 return simplifyTypeForTable(type);
3726 }
3727
writeMemberDocSimple(OutputList & ol,const Definition * container) const3728 void MemberDefImpl::writeMemberDocSimple(OutputList &ol, const Definition *container) const
3729 {
3730 Definition *scope = getOuterScope();
3731 QCString doxyName = name();
3732 QCString doxyArgs = argsString();
3733 QCString memAnchor = anchor();
3734 QCString cfname = getOutputFileBase();
3735 QCString cname;
3736 if (scope) cname = scope->name();
3737 if (doxyName.at(0)=='@')
3738 {
3739 doxyName="__unnamed__";
3740 }
3741
3742 ClassDef *cd = m_impl->accessorClass;
3743 //printf("===> %s::anonymous: %s\n",qPrint(name()),cd?qPrint(cd->name()):"<none>");
3744
3745 if (container && container->definitionType()==Definition::TypeClass &&
3746 !(toClassDef(container))->isJavaEnum())
3747 {
3748 ol.startInlineMemberType();
3749 ol.startDoxyAnchor(cfname,cname,memAnchor,doxyName,doxyArgs);
3750
3751 QCString ts = fieldType();
3752
3753 if (cd) // cd points to an anonymous struct pointed to by this member
3754 // so we add a link to it from the type column.
3755 {
3756 int i=0;
3757 const char *prefixes[] = { "struct ","union ","class ", 0 };
3758 const char **p = prefixes;
3759 while (*p)
3760 {
3761 int l=qstrlen(*p);
3762 if (ts.left(l)==*p)
3763 {
3764 ol.writeString(*p);
3765 i=l;
3766 }
3767 p++;
3768 }
3769 ol.writeObjectLink(cd->getReference(),
3770 cd->getOutputFileBase(),
3771 cd->anchor(),ts.mid(i));
3772 }
3773 else // use standard auto linking
3774 {
3775 linkifyText(TextGeneratorOLImpl(ol), // out
3776 scope, // scope
3777 getBodyDef(), // fileScope
3778 this, // self
3779 ts // text
3780 );
3781 }
3782 ol.endDoxyAnchor(cfname,memAnchor);
3783 ol.endInlineMemberType();
3784 }
3785
3786 ol.startInlineMemberName();
3787 ol.docify(doxyName);
3788 if (isVariable() && !argsString().isEmpty() && !isObjCMethod())
3789 {
3790 linkifyText(TextGeneratorOLImpl(ol),getOuterScope(),getBodyDef(),this,argsString());
3791 }
3792 if (!m_impl->bitfields.isEmpty()) // add bitfields
3793 {
3794 linkifyText(TextGeneratorOLImpl(ol),getOuterScope(),getBodyDef(),this,m_impl->bitfields);
3795 }
3796 ol.endInlineMemberName();
3797
3798 ol.startInlineMemberDoc();
3799
3800 QCString brief = briefDescription();
3801 QCString detailed = documentation();
3802
3803 /* write brief description */
3804 if (!brief.isEmpty())
3805 {
3806 ol.generateDoc(briefFile(),briefLine(),
3807 getOuterScope()?getOuterScope():container,this,
3808 brief,FALSE,FALSE,
3809 QCString(),TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT));
3810 }
3811
3812 /* write detailed description */
3813 if (!detailed.isEmpty())
3814 {
3815 if (!brief.isEmpty())
3816 {
3817 ol.disable(OutputGenerator::Html);
3818 ol.lineBreak();
3819 ol.enable(OutputGenerator::Html);
3820 }
3821 ol.generateDoc(docFile(),docLine(),
3822 getOuterScope()?getOuterScope():container,this,
3823 detailed+"\n",FALSE,FALSE,
3824 QCString(),FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT));
3825
3826 }
3827
3828 ol.endInlineMemberDoc();
3829 }
3830
memberTypeName() const3831 QCString MemberDefImpl::memberTypeName() const
3832 {
3833 switch (m_impl->mtype)
3834 {
3835 case MemberType_Define: return "macro definition";
3836 case MemberType_Function: return "function";
3837 case MemberType_Variable: return "variable";
3838 case MemberType_Typedef: return "typedef";
3839 case MemberType_Enumeration: return "enumeration";
3840 case MemberType_EnumValue: return "enumvalue";
3841 case MemberType_Signal: return "signal";
3842 case MemberType_Slot: return "slot";
3843 case MemberType_Friend: return "friend";
3844 case MemberType_DCOP: return "dcop";
3845 case MemberType_Property: return "property";
3846 case MemberType_Event: return "event";
3847 case MemberType_Interface: return "interface";
3848 case MemberType_Service: return "service";
3849 case MemberType_Sequence: return "sequence";
3850 case MemberType_Dictionary: return "dictionary";
3851 default: return "unknown";
3852 }
3853 }
3854
warnIfUndocumented() const3855 void MemberDefImpl::warnIfUndocumented() const
3856 {
3857 /*
3858 * Removed bug_303020:
3859 * if (m_impl->memberGroup) return;
3860 */
3861 const ClassDef *cd = getClassDef();
3862 const NamespaceDef *nd = getNamespaceDef();
3863 const FileDef *fd = getFileDef();
3864 const GroupDef *gd = getGroupDef();
3865 const Definition *d=0;
3866 QCString t;
3867 if (cd)
3868 t=cd->compoundTypeString(), d=cd;
3869 else if (nd)
3870 {
3871 d=nd;
3872 t=nd->compoundTypeString();
3873 }
3874 else if (gd)
3875 t="group", d=gd;
3876 else
3877 t="file", d=fd;
3878 static bool extractAll = Config_getBool(EXTRACT_ALL);
3879
3880 //printf("%s:warnIfUndoc: hasUserDocs=%d isFriendClass=%d protection=%d isRef=%d isDel=%d\n",
3881 // qPrint(name()),
3882 // hasUserDocumentation(),isFriendClass(),protectionLevelVisible(m_impl->prot),isReference(),isDeleted());
3883 if ((!hasUserDocumentation() && !extractAll) &&
3884 !isFriendClass() &&
3885 name().find('@')==-1 && d && d->name().find('@')==-1 &&
3886 protectionLevelVisible(m_impl->prot) &&
3887 !isReference() && !isDeleted()
3888 )
3889 {
3890 warn_undoc(getDefFileName(),getDefLine(),"Member %s%s (%s) of %s %s is not documented.",
3891 qPrint(name()),qPrint(argsString()),qPrint(memberTypeName()),qPrint(t),qPrint(d->name()));
3892 }
3893 else if (!hasDetailedDescription())
3894 {
3895 warnIfUndocumentedParams();
3896 }
3897 }
3898
visibleInIndex() const3899 bool MemberDefImpl::visibleInIndex() const
3900 {
3901 bool hideUndocMembers = Config_getBool(HIDE_UNDOC_MEMBERS);
3902 bool extractStatic = Config_getBool(EXTRACT_STATIC);
3903 return (!isAnonymous() &&
3904 (!hideUndocMembers || hasDocumentation()) &&
3905 (!isStatic() || extractStatic) &&
3906 isLinkable()
3907 );
3908 }
3909
stripTrailingReturn(const QCString & trailRet)3910 static QCString stripTrailingReturn(const QCString &trailRet)
3911 {
3912 QCString ret = trailRet;
3913
3914 ret = ret.stripWhiteSpace();
3915 if (ret.startsWith("->"))
3916 {
3917 ret = ret.mid(2).stripWhiteSpace();
3918 return ret;
3919 }
3920 return trailRet;
3921 }
3922
detectUndocumentedParams(bool hasParamCommand,bool hasReturnCommand) const3923 void MemberDefImpl::detectUndocumentedParams(bool hasParamCommand,bool hasReturnCommand) const
3924 {
3925 QCString returnType = typeString();
3926 bool isPython = getLanguage()==SrcLangExt_Python;
3927 bool isFortran = getLanguage()==SrcLangExt_Fortran;
3928 bool isFortranSubroutine = isFortran && returnType.find("subroutine")!=-1;
3929
3930 bool isVoidReturn = (returnType=="void") || (returnType.right(5)==" void");
3931 if (!isVoidReturn && returnType == "auto")
3932 {
3933 const ArgumentList &defArgList=isDocsForDefinition() ? argumentList() : declArgumentList();
3934 if (!defArgList.trailingReturnType().isEmpty())
3935 {
3936 QCString strippedTrailingReturn = stripTrailingReturn(defArgList.trailingReturnType());
3937 isVoidReturn = (strippedTrailingReturn=="void") || (strippedTrailingReturn.right(5)==" void");
3938 }
3939 }
3940
3941 if (!m_impl->hasDocumentedParams && hasParamCommand)
3942 {
3943 //printf("%s:hasDocumentedParams=TRUE;\n",qPrint(name()));
3944 m_impl->hasDocumentedParams = TRUE;
3945 }
3946 else if (!m_impl->hasDocumentedParams)
3947 {
3948 const ArgumentList &al = argumentList();
3949 const ArgumentList &declAl = declArgumentList();
3950 bool allDoc=TRUE; // no parameter => all parameters are documented
3951 if ( // member has parameters
3952 al.hasParameters() // with at least one parameter (that is not void)
3953 )
3954 {
3955 // see if all parameters have documentation
3956 for (auto it = al.begin(); it!=al.end() && allDoc; ++it)
3957 {
3958 Argument a = *it;
3959 if (!a.name.isEmpty() && a.type!="void" &&
3960 !(isPython && (a.name=="self" || a.name=="cls"))
3961 )
3962 {
3963 allDoc = !a.docs.isEmpty();
3964 }
3965 //printf("a->type=%s a->name=%s doc=%s\n",
3966 // qPrint(a->type),qPrint(a->name),qPrint(a->docs));
3967 }
3968 if (!allDoc && declAl.empty()) // try declaration arguments as well
3969 {
3970 allDoc=TRUE;
3971 for (auto it = al.begin(); it!=al.end() && allDoc; ++it)
3972 {
3973 Argument a = *it;
3974 if (!a.name.isEmpty() && a.type!="void" &&
3975 !(isPython && (a.name=="self" || a.name=="cls"))
3976 )
3977 {
3978 allDoc = !a.docs.isEmpty();
3979 }
3980 //printf("a->name=%s doc=%s\n",qPrint(a->name),qPrint(a->docs));
3981 }
3982 }
3983 }
3984 if (allDoc)
3985 {
3986 //printf("%s:hasDocumentedParams=TRUE;\n",qPrint(name()));
3987 m_impl->hasDocumentedParams = TRUE;
3988 }
3989 }
3990
3991 //printf("Member %s hasDocumentedReturnType=%d hasReturnCommand=%d\n",
3992 // qPrint(name()),m_impl->hasDocumentedReturnType,hasReturnCommand);
3993 if (!m_impl->hasDocumentedReturnType && // docs not yet found
3994 hasReturnCommand)
3995 {
3996 m_impl->hasDocumentedReturnType = TRUE;
3997 }
3998 else if ( // see if return type is documented in a function w/o return type
3999 hasReturnCommand &&
4000 (
4001 isVoidReturn || // void return type
4002 isFortranSubroutine || // fortran subroutine
4003 isConstructor() || // a constructor
4004 isDestructor() // or destructor
4005 )
4006 )
4007 {
4008
4009 warn_doc_error(docFile(),docLine(),"documented empty return type of %s",
4010 qPrint(qualifiedName()));
4011 }
4012 else if ( // see if return needs to documented
4013 m_impl->hasDocumentedReturnType ||
4014 isVoidReturn || // void return type
4015 isFortranSubroutine || // fortran subroutine
4016 isConstructor() || // a constructor
4017 isDestructor() // or destructor
4018 )
4019 {
4020 m_impl->hasDocumentedReturnType = TRUE;
4021 }
4022 }
4023
warnIfUndocumentedParams() const4024 void MemberDefImpl::warnIfUndocumentedParams() const
4025 {
4026 if (!Config_getBool(EXTRACT_ALL) &&
4027 Config_getBool(WARN_IF_UNDOCUMENTED) &&
4028 Config_getBool(WARN_NO_PARAMDOC) &&
4029 isFunction() &&
4030 !isDeleted() &&
4031 !isReference() &&
4032 !Doxygen::suppressDocWarnings)
4033 {
4034 QCString returnType = typeString();
4035 if (!m_impl->hasDocumentedParams)
4036 {
4037 warn_doc_error(docFile(),docLine(),
4038 "parameters of member %s are not (all) documented",
4039 qPrint(qualifiedName()));
4040 }
4041 if (!m_impl->hasDocumentedReturnType &&
4042 hasDocumentation() && !returnType.isEmpty())
4043 {
4044 warn_doc_error(docFile(),docLine(),
4045 "return type of member %s is not documented",
4046 qPrint(qualifiedName()));
4047 }
4048 }
4049 }
4050
isDocumentedFriendClass() const4051 bool MemberDefImpl::isDocumentedFriendClass() const
4052 {
4053 ClassDef *fcd=0;
4054 QCString baseName=name();
4055 int i=baseName.find('<');
4056 if (i!=-1) baseName=baseName.left(i);
4057 return (isFriendClass() &&
4058 (fcd=getClass(baseName)) && fcd->isLinkable());
4059 }
4060
isDeleted() const4061 bool MemberDefImpl::isDeleted() const
4062 {
4063 return m_impl->defArgList.isDeleted();
4064 }
4065
hasDocumentation() const4066 bool MemberDefImpl::hasDocumentation() const
4067 {
4068 return DefinitionMixin::hasDocumentation() ||
4069 (m_impl->mtype==MemberType_Enumeration && m_impl->docEnumValues) || // has enum values
4070 (m_impl->defArgList.hasDocumentation()); // has doc arguments
4071 }
4072
4073
setMemberGroup(MemberGroup * grp)4074 void MemberDefImpl::setMemberGroup(MemberGroup *grp)
4075 {
4076 m_impl->memberGroup = grp;
4077 }
4078
visibleMemberGroup(bool hideNoHeader) const4079 bool MemberDefImpl::visibleMemberGroup(bool hideNoHeader) const
4080 {
4081 return m_impl->memberGroup!=0 &&
4082 (!hideNoHeader || m_impl->memberGroup->header()!="[NOHEADER]");
4083 }
4084
getScopeString() const4085 QCString MemberDefImpl::getScopeString() const
4086 {
4087 QCString result;
4088 if (getClassDef()) result=getClassDef()->displayName();
4089 else if (getNamespaceDef()) result=getNamespaceDef()->displayName();
4090 return result;
4091 }
4092
setAnchor()4093 void MemberDefImpl::setAnchor()
4094 {
4095 QCString memAnchor = name();
4096 if (!m_impl->args.isEmpty()) memAnchor+=m_impl->args;
4097
4098 memAnchor.prepend(definition()); // actually the method name is now included
4099 // twice, which is silly, but we keep it this way for backward
4100 // compatibility.
4101
4102 // include number of template arguments as well,
4103 // to distinguish between two template
4104 // specializations that only differ in the template parameters.
4105 if (m_impl->tArgList.hasParameters())
4106 {
4107 char buf[20];
4108 qsnprintf(buf,20,"%d:",(int)m_impl->tArgList.size());
4109 buf[19]='\0';
4110 memAnchor.prepend(buf);
4111 }
4112 if (!m_impl->requiresClause.isEmpty())
4113 {
4114 memAnchor+=" "+m_impl->requiresClause;
4115 }
4116
4117 // convert to md5 hash
4118 uchar md5_sig[16];
4119 char sigStr[33];
4120 MD5Buffer((const unsigned char *)memAnchor.data(),memAnchor.length(),md5_sig);
4121 MD5SigToString(md5_sig,sigStr);
4122 m_impl->anc = QCString("a")+sigStr;
4123 }
4124
setGroupDef(const GroupDef * gd,Grouping::GroupPri_t pri,const QCString & fileName,int startLine,bool hasDocs,MemberDef * member)4125 void MemberDefImpl::setGroupDef(const GroupDef *gd,Grouping::GroupPri_t pri,
4126 const QCString &fileName,int startLine,
4127 bool hasDocs,MemberDef *member)
4128 {
4129 //printf("%s MemberDefImpl::setGroupDef(%s)\n",qPrint(name()),qPrint(gd->name()));
4130 m_impl->group=gd;
4131 m_impl->grouppri=pri;
4132 m_impl->groupFileName=fileName;
4133 m_impl->groupStartLine=startLine;
4134 m_impl->groupHasDocs=hasDocs;
4135 m_impl->groupMember=member;
4136 m_isLinkableCached = 0;
4137 }
4138
setEnumScope(const MemberDef * md,bool livesInsideEnum)4139 void MemberDefImpl::setEnumScope(const MemberDef *md,bool livesInsideEnum)
4140 {
4141 m_impl->enumScope=md;
4142 m_impl->livesInsideEnum=livesInsideEnum;
4143 if (md->getGroupDef())
4144 {
4145 m_impl->group = const_cast<GroupDef*>(md->getGroupDef());
4146 m_impl->grouppri = md->getGroupPri();
4147 m_impl->groupFileName = md->getGroupFileName();
4148 m_impl->groupStartLine = md->getGroupStartLine();
4149 m_impl->groupHasDocs = md->getGroupHasDocs();
4150 m_isLinkableCached = 0;
4151 }
4152 }
4153
setMemberClass(const ClassDef * cd)4154 void MemberDefImpl::setMemberClass(const ClassDef *cd)
4155 {
4156 m_impl->classDef=cd;
4157 m_isLinkableCached = 0;
4158 m_isConstructorCached = 0;
4159 setOuterScope(const_cast<ClassDef*>(cd));
4160 }
4161
setNamespace(const NamespaceDef * nd)4162 void MemberDefImpl::setNamespace(const NamespaceDef *nd)
4163 {
4164 m_impl->nspace=nd;
4165 setOuterScope(const_cast<NamespaceDef*>(nd));
4166 }
4167
createTemplateInstanceMember(const ArgumentList & formalArgs,const std::unique_ptr<ArgumentList> & actualArgs) const4168 MemberDefMutable *MemberDefImpl::createTemplateInstanceMember(
4169 const ArgumentList &formalArgs,const std::unique_ptr<ArgumentList> &actualArgs) const
4170 {
4171 //printf(" Member %s %s %s\n",typeString(),qPrint(name()),argsString());
4172 std::unique_ptr<ArgumentList> actualArgList = std::make_unique<ArgumentList>(m_impl->defArgList);
4173 if (!m_impl->defArgList.empty())
4174 {
4175 // replace formal arguments with actuals
4176 for (Argument &arg : *actualArgList)
4177 {
4178 arg.type = substituteTemplateArgumentsInString(arg.type,formalArgs,actualArgs);
4179 }
4180 actualArgList->setTrailingReturnType(
4181 substituteTemplateArgumentsInString(actualArgList->trailingReturnType(),formalArgs,actualArgs));
4182 }
4183
4184 QCString methodName=name();
4185 if (methodName.left(9)=="operator ") // conversion operator
4186 {
4187 methodName=substituteTemplateArgumentsInString(methodName,formalArgs,actualArgs);
4188 }
4189
4190 MemberDefMutable *imd = createMemberDef(
4191 getDefFileName(),getDefLine(),getDefColumn(),
4192 substituteTemplateArgumentsInString(m_impl->type,formalArgs,actualArgs),
4193 methodName,
4194 substituteTemplateArgumentsInString(m_impl->args,formalArgs,actualArgs),
4195 m_impl->exception, m_impl->prot,
4196 m_impl->virt, m_impl->stat, m_impl->related, m_impl->mtype,
4197 ArgumentList(), ArgumentList(), ""
4198 );
4199 imd->moveArgumentList(std::move(actualArgList));
4200 imd->setDefinition(substituteTemplateArgumentsInString(m_impl->def,formalArgs,actualArgs));
4201 imd->setBodyDef(getBodyDef());
4202 imd->setBodySegment(getDefLine(),getStartBodyLine(),getEndBodyLine());
4203 //imd->setBodyMember(this);
4204
4205 // TODO: init other member variables (if needed).
4206 // TODO: reimplemented info
4207 return imd;
4208 }
4209
hasOneLineInitializer() const4210 bool MemberDefImpl::hasOneLineInitializer() const
4211 {
4212 //printf("%s: init=%s, initLines=%d maxInitLines=%d userInitLines=%d\n",
4213 // qPrint(name()),qPrint(m_impl->initializer),m_impl->initLines,
4214 // m_impl->maxInitLines,m_impl->userInitLines);
4215 return !m_impl->initializer.isEmpty() && m_impl->initLines==0 && // one line initializer
4216 ((m_impl->maxInitLines>0 && m_impl->userInitLines==-1) || m_impl->userInitLines>0); // enabled by default or explicitly
4217 }
4218
hasMultiLineInitializer() const4219 bool MemberDefImpl::hasMultiLineInitializer() const
4220 {
4221 //printf("initLines=%d userInitLines=%d maxInitLines=%d\n",
4222 // initLines,userInitLines,maxInitLines);
4223 return m_impl->initLines>0 &&
4224 ((m_impl->initLines<m_impl->maxInitLines && m_impl->userInitLines==-1) // implicitly enabled
4225 || m_impl->initLines<m_impl->userInitLines // explicitly enabled
4226 );
4227 }
4228
setInitializer(const QCString & initializer)4229 void MemberDefImpl::setInitializer(const QCString &initializer)
4230 {
4231 m_impl->initializer=initializer;
4232 int l=m_impl->initializer.length();
4233 int p=l-1;
4234 while (p>=0 && isspace((uchar)m_impl->initializer.at(p))) p--;
4235 m_impl->initializer=m_impl->initializer.left(p+1);
4236 m_impl->initLines=m_impl->initializer.contains('\n');
4237 //printf("%s::setInitializer(%s)\n",qPrint(name()),qPrint(m_impl->initializer));
4238 }
4239
addListReference(Definition *)4240 void MemberDefImpl::addListReference(Definition *)
4241 {
4242 static bool optimizeOutputForC = Config_getBool(OPTIMIZE_OUTPUT_FOR_C);
4243 //static bool hideScopeNames = Config_getBool(HIDE_SCOPE_NAMES);
4244 //static bool optimizeOutputJava = Config_getBool(OPTIMIZE_OUTPUT_JAVA);
4245 //static bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN);
4246 SrcLangExt lang = getLanguage();
4247 if (!isLinkableInProject()) return;
4248 QCString memLabel;
4249 if (optimizeOutputForC)
4250 {
4251 memLabel=theTranslator->trGlobal(TRUE,TRUE);
4252 }
4253 else if (lang==SrcLangExt_Fortran)
4254 {
4255 memLabel=theTranslator->trSubprogram(TRUE,TRUE);
4256 }
4257 else
4258 {
4259 memLabel=theTranslator->trMember(TRUE,TRUE);
4260 }
4261 QCString memName = name();
4262 Definition *pd=getOuterScope();
4263 QCString pdName = pd->definitionType()==Definition::TypeClass ?
4264 (toClassDef(pd))->displayName() : pd->name();
4265 QCString sep = getLanguageSpecificSeparator(lang,TRUE);
4266 QCString memArgs;
4267 if (!isRelated()
4268 /* && commented out as a result of bug 597016
4269 (
4270 (!hideScopeNames && // there is a scope
4271 pd && pd!=Doxygen::globalScope) // and we can show it
4272 ||
4273 (pd=getClassDef()) // it's a class so we
4274 // show the scope anyway
4275 )
4276 */
4277 )
4278 {
4279 if (isObjCMethod())
4280 {
4281 memName = "[" + pd->name() + " " + name() + "]";
4282 }
4283 else
4284 {
4285 if (pd!=Doxygen::globalScope) memName.prepend(pdName+sep);
4286 memArgs = argsString();
4287 }
4288 }
4289 const RefItemVector &xrefItems = xrefListItems();
4290 addRefItem(xrefItems,
4291 qualifiedName()+argsString(), // argsString is needed for overloaded functions (see bug 609624)
4292 memLabel,
4293 getOutputFileBase()+"#"+anchor(),memName,memArgs,pd);
4294 }
4295
getSectionList(const Definition * container) const4296 const MemberList *MemberDefImpl::getSectionList(const Definition *container) const
4297 {
4298 auto it = m_impl->sectionMap.find(container);
4299 return it!=m_impl->sectionMap.end() ? it->second : 0;
4300 }
4301
setSectionList(const Definition * container,const MemberList * sl)4302 void MemberDefImpl::setSectionList(const Definition *container,const MemberList *sl)
4303 {
4304 //printf("MemberDefImpl::setSectionList(%s,%p) name=%s\n",qPrint(d->name()),sl,qPrint(name()));
4305 m_impl->sectionMap.insert(std::make_pair(container,sl));
4306 }
4307
virtualness(int count) const4308 Specifier MemberDefImpl::virtualness(int count) const
4309 {
4310 if (count>25)
4311 {
4312 warn(getDefFileName(),getDefLine(),
4313 "Internal inconsistency: recursion detected in overload relation for member %s!"
4314 ,qPrint(name())
4315 );
4316 return Normal;
4317 }
4318 Specifier v = m_impl->virt;
4319 const MemberDef *rmd = reimplements();
4320 while (rmd && v==Normal)
4321 {
4322 v = rmd->virtualness(count+1)==Normal ? Normal : Virtual;
4323 rmd = rmd->reimplements();
4324 }
4325 return v;
4326 }
4327
writeTagFile(TextStream & tagFile) const4328 void MemberDefImpl::writeTagFile(TextStream &tagFile) const
4329 {
4330 if (!isLinkableInProject()) return;
4331 tagFile << " <member kind=\"";
4332 switch (m_impl->mtype)
4333 {
4334 case MemberType_Define: tagFile << "define"; break;
4335 case MemberType_EnumValue: tagFile << "enumvalue"; break;
4336 case MemberType_Property: tagFile << "property"; break;
4337 case MemberType_Event: tagFile << "event"; break;
4338 case MemberType_Variable: tagFile << "variable"; break;
4339 case MemberType_Typedef: tagFile << "typedef"; break;
4340 case MemberType_Enumeration: tagFile << "enumeration"; break;
4341 case MemberType_Function: tagFile << "function"; break;
4342 case MemberType_Signal: tagFile << "signal"; break;
4343 case MemberType_Friend: tagFile << "friend"; break;
4344 case MemberType_DCOP: tagFile << "dcop"; break;
4345 case MemberType_Slot: tagFile << "slot"; break;
4346 case MemberType_Interface: tagFile << "interface"; break;
4347 case MemberType_Service: tagFile << "service"; break;
4348 case MemberType_Sequence: tagFile << "sequence"; break;
4349 case MemberType_Dictionary: tagFile << "dictionary"; break;
4350 }
4351 if (m_impl->prot!=Public)
4352 {
4353 tagFile << "\" protection=\"";
4354 if (m_impl->prot==Protected) tagFile << "protected";
4355 else if (m_impl->prot==Package) tagFile << "package";
4356 else /* Private */ tagFile << "private";
4357 }
4358 if (m_impl->virt!=Normal)
4359 {
4360 tagFile << "\" virtualness=\"";
4361 if (m_impl->virt==Virtual) tagFile << "virtual";
4362 else /* Pure */ tagFile << "pure";
4363 }
4364 if (isStatic())
4365 {
4366 tagFile << "\" static=\"yes";
4367 }
4368 tagFile << "\">\n";
4369 if (typeString()!=QCString("@"))
4370 {
4371 tagFile << " <type>" << convertToXML(typeString()) << "</type>\n";
4372 }
4373 tagFile << " <name>" << convertToXML(name()) << "</name>\n";
4374 tagFile << " <anchorfile>" << addHtmlExtensionIfMissing(getOutputFileBase()) << "</anchorfile>\n";
4375 tagFile << " <anchor>" << convertToXML(anchor()) << "</anchor>\n";
4376 QCString idStr = id();
4377 if (!idStr.isEmpty())
4378 {
4379 tagFile << " <clangid>" << convertToXML(idStr) << "</clangid>\n";
4380 }
4381 tagFile << " <arglist>" << convertToXML(argsString()) << "</arglist>\n";
4382 if (isStrong())
4383 {
4384 for (const auto &fmd : m_impl->enumFields)
4385 {
4386 if (!fmd->isReference())
4387 {
4388 tagFile << " <enumvalue file=\"" << convertToXML(addHtmlExtensionIfMissing(getOutputFileBase()));
4389 tagFile << "\" anchor=\"" << convertToXML(fmd->anchor());
4390 idStr = fmd->id();
4391 if (!idStr.isEmpty())
4392 {
4393 tagFile << "\" clangid=\"" << convertToXML(idStr);
4394 }
4395 tagFile << "\">" << convertToXML(fmd->name()) << "</enumvalue>\n";
4396 }
4397 }
4398 }
4399 writeDocAnchorsToTagFile(tagFile);
4400 tagFile << " </member>\n";
4401 }
4402
_computeIsConstructor()4403 void MemberDefImpl::_computeIsConstructor()
4404 {
4405 m_isConstructorCached=1; // FALSE
4406 if (getClassDef())
4407 {
4408 if (m_impl->isDMember) // for D
4409 {
4410 m_isConstructorCached = name()=="this" ? 2 : 1;
4411 return;
4412 }
4413 else if (getLanguage()==SrcLangExt_PHP) // for PHP
4414 {
4415 m_isConstructorCached = name()=="__construct" ? 2 : 1;
4416 return;
4417 }
4418 else if (name()=="__init__" &&
4419 getLanguage()==SrcLangExt_Python) // for Python
4420 {
4421 m_isConstructorCached = 2; // TRUE
4422 return;
4423 }
4424 else // for other languages
4425 {
4426 QCString locName = getClassDef()->localName();
4427 int i=locName.find('<');
4428 if (i==-1) // not a template class
4429 {
4430 m_isConstructorCached = name()==locName ? 2 : 1;
4431 }
4432 else
4433 {
4434 m_isConstructorCached = name()==locName.left(i) ? 2 : 1;
4435 }
4436 return;
4437 }
4438 }
4439 }
4440
isConstructor() const4441 bool MemberDefImpl::isConstructor() const
4442 {
4443 if (m_isConstructorCached==0)
4444 {
4445 MemberDefImpl *that = (MemberDefImpl*)this;
4446 that->_computeIsConstructor();
4447 }
4448 ASSERT(m_isConstructorCached>0);
4449 return m_isConstructorCached==2;
4450
4451 }
4452
_computeIsDestructor()4453 void MemberDefImpl::_computeIsDestructor()
4454 {
4455 bool isDestructor;
4456 if (m_impl->isDMember) // for D
4457 {
4458 isDestructor = name()=="~this";
4459 }
4460 else if (getLanguage()==SrcLangExt_PHP) // for PHP
4461 {
4462 isDestructor = name()=="__destruct";
4463 }
4464 else if (name()=="__del__" &&
4465 getLanguage()==SrcLangExt_Python) // for Python
4466 {
4467 isDestructor=TRUE;
4468 }
4469 else // other languages
4470 {
4471 isDestructor =
4472 (name().find('~')!=-1 || name().find('!')!=-1) // The ! is for C++/CLI
4473 && name().find("operator")==-1;
4474 }
4475 m_isDestructorCached = isDestructor ? 2 : 1;
4476 }
4477
isDestructor() const4478 bool MemberDefImpl::isDestructor() const
4479 {
4480 if (m_isDestructorCached==0)
4481 {
4482 MemberDefImpl *that=(MemberDefImpl*)this;
4483 that->_computeIsDestructor();
4484 }
4485 ASSERT(m_isDestructorCached>0);
4486 return m_isDestructorCached==2;
4487 }
4488
writeEnumDeclaration(OutputList & typeDecl,const ClassDef * cd,const NamespaceDef * nd,const FileDef * fd,const GroupDef * gd) const4489 void MemberDefImpl::writeEnumDeclaration(OutputList &typeDecl,
4490 const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd) const
4491 {
4492 int enumMemCount=0;
4493
4494 uint numVisibleEnumValues=0;
4495 for (const auto &fmd : m_impl->enumFields)
4496 {
4497 if (fmd->isBriefSectionVisible()) numVisibleEnumValues++;
4498 }
4499 if (numVisibleEnumValues==0 && !isBriefSectionVisible())
4500 {
4501 return;
4502 }
4503
4504 QCString n = name();
4505 int i=n.findRev("::");
4506 if (i!=-1) n=n.right(n.length()-i-2); // strip scope (TODO: is this needed?)
4507 if (n[0]!='@') // not an anonymous enum
4508 {
4509 if (isLinkableInProject() || hasDocumentedEnumValues())
4510 {
4511 //_writeTagData(compoundType);
4512 writeLink(typeDecl,cd,nd,fd,gd);
4513 }
4514 else
4515 {
4516 typeDecl.startBold();
4517 typeDecl.docify(n);
4518 typeDecl.endBold();
4519 }
4520 typeDecl.writeChar(' ');
4521 }
4522 if (!m_impl->enumBaseType.isEmpty())
4523 {
4524 typeDecl.writeChar(':');
4525 typeDecl.writeChar(' ');
4526 typeDecl.docify(m_impl->enumBaseType);
4527 typeDecl.writeChar(' ');
4528 }
4529
4530 uint enumValuesPerLine = (uint)Config_getInt(ENUM_VALUES_PER_LINE);
4531 if (numVisibleEnumValues>0 && enumValuesPerLine>0)
4532 {
4533 typeDecl.docify("{ ");
4534
4535 auto it = m_impl->enumFields.begin();
4536 if (it!=m_impl->enumFields.end())
4537 {
4538 const MemberDef *fmd=*it;
4539 bool fmdVisible = fmd->isBriefSectionVisible();
4540 bool first=true;
4541 while (fmd)
4542 {
4543 if (fmdVisible)
4544 {
4545 if (!first)
4546 {
4547 typeDecl.writeString(", ");
4548 }
4549 /* in html we start a new line after a number of items */
4550 if (numVisibleEnumValues>enumValuesPerLine
4551 && (enumMemCount%enumValuesPerLine)==0
4552 )
4553 {
4554 typeDecl.pushGeneratorState();
4555 typeDecl.disableAllBut(OutputGenerator::Html);
4556 typeDecl.enable(OutputGenerator::Latex);
4557 typeDecl.enable(OutputGenerator::Docbook);
4558 typeDecl.lineBreak();
4559 typeDecl.disable(OutputGenerator::Latex);
4560 typeDecl.disable(OutputGenerator::Docbook);
4561 typeDecl.writeString("  ");
4562 typeDecl.popGeneratorState();
4563 }
4564
4565 MemberDefMutable *fmdm = toMemberDefMutable(fmd);
4566 if (fmdm && fmd->hasDocumentation()) // enum value has docs
4567 {
4568 fmdm->writeLink(typeDecl,cd,nd,fd,gd);
4569 }
4570 else // no docs for this enum value
4571 {
4572 typeDecl.startBold();
4573 typeDecl.docify(fmd->name());
4574 typeDecl.endBold();
4575 }
4576 if (fmd->hasOneLineInitializer()) // enum value has initializer
4577 {
4578 //typeDecl.writeString(" = ");
4579 typeDecl.writeString(" ");
4580 typeDecl.parseText(fmd->initializer());
4581 }
4582 first=false;
4583 }
4584
4585 bool prevVisible = fmdVisible;
4586 ++it;
4587 if (it!=m_impl->enumFields.end())
4588 {
4589 fmd=*it;
4590 }
4591 else
4592 {
4593 fmd=0;
4594 }
4595 if (prevVisible)
4596 {
4597 typeDecl.disable(OutputGenerator::Man);
4598 typeDecl.writeString("\n"); // to prevent too long lines in LaTeX
4599 typeDecl.enable(OutputGenerator::Man);
4600 enumMemCount++;
4601 }
4602 }
4603 if (numVisibleEnumValues>enumValuesPerLine)
4604 {
4605 typeDecl.pushGeneratorState();
4606 typeDecl.disableAllBut(OutputGenerator::Html);
4607 typeDecl.lineBreak();
4608 typeDecl.popGeneratorState();
4609 }
4610 }
4611 typeDecl.docify(" }");
4612 }
4613 }
4614
moveArgumentList(std::unique_ptr<ArgumentList> al)4615 void MemberDefImpl::moveArgumentList(std::unique_ptr<ArgumentList> al)
4616 {
4617 m_impl->defArgList = *al;
4618 }
4619
moveDeclArgumentList(std::unique_ptr<ArgumentList> al)4620 void MemberDefImpl::moveDeclArgumentList(std::unique_ptr<ArgumentList> al)
4621 {
4622 m_impl->declArgList = *al;
4623 }
4624
setTypeConstraints(const ArgumentList & al)4625 void MemberDefImpl::setTypeConstraints(const ArgumentList &al)
4626 {
4627 m_impl->typeConstraints = al;
4628 }
4629
setType(const QCString & t)4630 void MemberDefImpl::setType(const QCString &t)
4631 {
4632 m_impl->type = t;
4633 }
4634
setAccessorType(ClassDef * cd,const QCString & t)4635 void MemberDefImpl::setAccessorType(ClassDef *cd,const QCString &t)
4636 {
4637 m_impl->accessorClass = cd;
4638 m_impl->accessorType = t;
4639 }
4640
accessorClass() const4641 ClassDef *MemberDefImpl::accessorClass() const
4642 {
4643 return m_impl->accessorClass;
4644 }
4645
findSectionsInDocumentation()4646 void MemberDefImpl::findSectionsInDocumentation()
4647 {
4648 docFindSections(briefDescription(),this,docFile());
4649 docFindSections(documentation(),this,docFile());
4650 }
4651
enableCallGraph(bool e)4652 void MemberDefImpl::enableCallGraph(bool e)
4653 {
4654 m_impl->hasCallGraph=e;
4655 if (e) Doxygen::parseSourcesNeeded = TRUE;
4656 }
4657
enableCallerGraph(bool e)4658 void MemberDefImpl::enableCallerGraph(bool e)
4659 {
4660 m_impl->hasCallerGraph=e;
4661 if (e) Doxygen::parseSourcesNeeded = TRUE;
4662 }
4663
enableReferencedByRelation(bool e)4664 void MemberDefImpl::enableReferencedByRelation(bool e)
4665 {
4666 m_impl->hasReferencedByRelation=e;
4667 if (e) Doxygen::parseSourcesNeeded = TRUE;
4668 }
4669
enableReferencesRelation(bool e)4670 void MemberDefImpl::enableReferencesRelation(bool e)
4671 {
4672 m_impl->hasReferencesRelation=e;
4673 if (e) Doxygen::parseSourcesNeeded = TRUE;
4674 }
4675
4676 #if 0
4677 bool MemberDefImpl::protectionVisible() const
4678 {
4679 return m_impl->prot==Public ||
4680 (m_impl->prot==Private && Config_getBool(EXTRACT_PRIVATE)) ||
4681 (m_impl->prot==Protected && Config_getBool(EXTRACT_PROTECTED)) ||
4682 (m_impl->prot==Package && Config_getBool(EXTRACT_PACKAGE));
4683 }
4684 #endif
4685
4686 #if 0
4687 void MemberDefImpl::setInbodyDocumentation(const QCString &docs,
4688 const QCString &docFile,int docLine)
4689 {
4690 m_impl->inbodyDocs = docs;
4691 m_impl->inbodyDocs = m_impl->inbodyDocs.stripWhiteSpace();
4692 m_impl->inbodyLine = docLine;
4693 m_impl->inbodyFile = docFile;
4694 }
4695 #endif
4696
isObjCMethod() const4697 bool MemberDefImpl::isObjCMethod() const
4698 {
4699 if (getClassDef() && getClassDef()->isObjectiveC() && isFunction()) return TRUE;
4700 return FALSE;
4701 }
4702
isObjCProperty() const4703 bool MemberDefImpl::isObjCProperty() const
4704 {
4705 if (getClassDef() && getClassDef()->isObjectiveC() && isProperty()) return TRUE;
4706 return FALSE;
4707 }
4708
isCSharpProperty() const4709 bool MemberDefImpl::isCSharpProperty() const
4710 {
4711 if (getClassDef() && getClassDef()->isCSharp() && isProperty()) return TRUE;
4712 return FALSE;
4713 }
4714
qualifiedName() const4715 QCString MemberDefImpl::qualifiedName() const
4716 {
4717 if (isObjCMethod())
4718 {
4719 QCString qm;
4720 if (isStatic()) qm="+"; else qm="-";
4721 qm+="[";
4722 qm+=getClassDef()->name()+" ";
4723 qm+=name();
4724 qm+="]";
4725 return qm;
4726 }
4727 else if (m_impl->enumScope && m_impl->enumScope->isStrong())
4728 {
4729 return m_impl->enumScope->qualifiedName()+
4730 getLanguageSpecificSeparator(getLanguage())+
4731 localName();
4732 }
4733 else
4734 {
4735 return DefinitionMixin::qualifiedName();
4736 }
4737 }
4738
setTagInfo(const TagInfo * ti)4739 void MemberDefImpl::setTagInfo(const TagInfo *ti)
4740 {
4741 if (ti)
4742 {
4743 //printf("%s: Setting tag name=%s anchor=%s\n",qPrint(name()),qPrint(ti->tagName),qPrint(ti->anchor));
4744 m_impl->anc=ti->anchor;
4745 setReference(ti->tagName);
4746 m_impl->explicitOutputFileBase = stripExtension(ti->fileName);
4747 }
4748 }
4749
objCMethodName(bool localLink,bool showStatic) const4750 QCString MemberDefImpl::objCMethodName(bool localLink,bool showStatic) const
4751 {
4752 QCString qm;
4753 if (showStatic)
4754 {
4755 if (isStatic()) qm="+ "; else qm="- ";
4756 }
4757 qm+=name();
4758 if (!localLink) // link to method of same class
4759 {
4760 qm+=" (";
4761 qm+=getClassDef()->name();
4762 qm+=")";
4763 }
4764 return qm;
4765 }
4766
declaration() const4767 QCString MemberDefImpl::declaration() const
4768 {
4769 return m_impl->decl;
4770 }
4771
definition() const4772 QCString MemberDefImpl::definition() const
4773 {
4774 return m_impl->def;
4775 }
4776
extraTypeChars() const4777 QCString MemberDefImpl::extraTypeChars() const
4778 {
4779 return m_impl->extraTypeChars;
4780 }
4781
typeString() const4782 QCString MemberDefImpl::typeString() const
4783 {
4784 return m_impl->type;
4785 }
4786
argsString() const4787 QCString MemberDefImpl::argsString() const
4788 {
4789 return m_impl->args;
4790 }
4791
excpString() const4792 QCString MemberDefImpl::excpString() const
4793 {
4794 return m_impl->exception;
4795 }
4796
bitfieldString() const4797 QCString MemberDefImpl::bitfieldString() const
4798 {
4799 return m_impl->bitfields;
4800 }
4801
initializer() const4802 const QCString &MemberDefImpl::initializer() const
4803 {
4804 return m_impl->initializer;
4805 }
4806
initializerLines() const4807 int MemberDefImpl::initializerLines() const
4808 {
4809 return m_impl->initLines;
4810 }
4811
getMemberSpecifiers() const4812 uint64 MemberDefImpl::getMemberSpecifiers() const
4813 {
4814 return m_impl->memSpec;
4815 }
4816
getClassDef() const4817 const ClassDef *MemberDefImpl::getClassDef() const
4818 {
4819 return m_impl->classDef;
4820 }
4821
getFileDef() const4822 const FileDef *MemberDefImpl::getFileDef() const
4823 {
4824 return m_impl->fileDef;
4825 }
4826
getNamespaceDef() const4827 const NamespaceDef* MemberDefImpl::getNamespaceDef() const
4828 {
4829 return m_impl->nspace;
4830 }
4831
getReadAccessor() const4832 QCString MemberDefImpl::getReadAccessor() const
4833 {
4834 return m_impl->read;
4835 }
4836
getWriteAccessor() const4837 QCString MemberDefImpl::getWriteAccessor() const
4838 {
4839 return m_impl->write;
4840 }
4841
getGroupDef() const4842 const GroupDef *MemberDefImpl::getGroupDef() const
4843 {
4844 return m_impl->group;
4845 }
4846
getGroupPri() const4847 Grouping::GroupPri_t MemberDefImpl::getGroupPri() const
4848 {
4849 return m_impl->grouppri;
4850 }
4851
getGroupFileName() const4852 QCString MemberDefImpl::getGroupFileName() const
4853 {
4854 return m_impl->groupFileName;
4855 }
4856
getGroupStartLine() const4857 int MemberDefImpl::getGroupStartLine() const
4858 {
4859 return m_impl->groupStartLine;
4860 }
4861
getGroupHasDocs() const4862 bool MemberDefImpl::getGroupHasDocs() const
4863 {
4864 return m_impl->groupHasDocs;
4865 }
4866
protection() const4867 Protection MemberDefImpl::protection() const
4868 {
4869 return m_impl->prot;
4870 }
4871
memberType() const4872 MemberType MemberDefImpl::memberType() const
4873 {
4874 return m_impl->mtype;
4875 }
4876
isSignal() const4877 bool MemberDefImpl::isSignal() const
4878 {
4879 return m_impl->mtype==MemberType_Signal;
4880 }
4881
isSlot() const4882 bool MemberDefImpl::isSlot() const
4883 {
4884 return m_impl->mtype==MemberType_Slot;
4885 }
4886
isVariable() const4887 bool MemberDefImpl::isVariable() const
4888 {
4889 return m_impl->mtype==MemberType_Variable;
4890 }
4891
isEnumerate() const4892 bool MemberDefImpl::isEnumerate() const
4893 {
4894 return m_impl->mtype==MemberType_Enumeration;
4895 }
4896
isEnumValue() const4897 bool MemberDefImpl::isEnumValue() const
4898 {
4899 return m_impl->mtype==MemberType_EnumValue;
4900 }
4901
isTypedef() const4902 bool MemberDefImpl::isTypedef() const
4903 {
4904 return m_impl->mtype==MemberType_Typedef;
4905 }
4906
isSequence() const4907 bool MemberDefImpl::isSequence() const
4908 {
4909 return m_impl->mtype==MemberType_Sequence;
4910 }
4911
isDictionary() const4912 bool MemberDefImpl::isDictionary() const
4913 {
4914 return m_impl->mtype==MemberType_Dictionary;
4915 }
4916
isFunction() const4917 bool MemberDefImpl::isFunction() const
4918 {
4919 return m_impl->mtype==MemberType_Function;
4920 }
4921
isFunctionPtr() const4922 bool MemberDefImpl::isFunctionPtr() const
4923 {
4924 return m_impl->mtype==MemberType_Variable && QCString(argsString()).find(")(")!=-1;
4925 }
4926
isDefine() const4927 bool MemberDefImpl::isDefine() const
4928 {
4929 return m_impl->mtype==MemberType_Define;
4930 }
4931
isFriend() const4932 bool MemberDefImpl::isFriend() const
4933 {
4934 return m_impl->mtype==MemberType_Friend;
4935 }
4936
isDCOP() const4937 bool MemberDefImpl::isDCOP() const
4938 {
4939 return m_impl->mtype==MemberType_DCOP;
4940 }
4941
isProperty() const4942 bool MemberDefImpl::isProperty() const
4943 {
4944 return m_impl->mtype==MemberType_Property;
4945 }
4946
isEvent() const4947 bool MemberDefImpl::isEvent() const
4948 {
4949 return m_impl->mtype==MemberType_Event;
4950 }
4951
isRelated() const4952 bool MemberDefImpl::isRelated() const
4953 {
4954 return m_impl->related == Related;
4955 }
4956
isForeign() const4957 bool MemberDefImpl::isForeign() const
4958 {
4959 return m_impl->related == Foreign;
4960 }
4961
isStatic() const4962 bool MemberDefImpl::isStatic() const
4963 {
4964 return m_impl->stat;
4965 }
4966
isInline() const4967 bool MemberDefImpl::isInline() const
4968 {
4969 return (m_impl->memSpec&Entry::Inline)!=0;
4970 }
4971
isExplicit() const4972 bool MemberDefImpl::isExplicit() const
4973 {
4974 return (m_impl->memSpec&Entry::Explicit)!=0;
4975 }
4976
isMutable() const4977 bool MemberDefImpl::isMutable() const
4978 {
4979 return (m_impl->memSpec&Entry::Mutable)!=0;
4980 }
4981
isGettable() const4982 bool MemberDefImpl::isGettable() const
4983 {
4984 return (m_impl->memSpec&Entry::Gettable)!=0;
4985 }
4986
isPrivateGettable() const4987 bool MemberDefImpl::isPrivateGettable() const
4988 {
4989 return (m_impl->memSpec&Entry::PrivateGettable)!=0;
4990 }
4991
isProtectedGettable() const4992 bool MemberDefImpl::isProtectedGettable() const
4993 {
4994 return (m_impl->memSpec&Entry::ProtectedGettable)!=0;
4995 }
4996
isSettable() const4997 bool MemberDefImpl::isSettable() const
4998 {
4999 return (m_impl->memSpec&Entry::Settable)!=0;
5000 }
5001
isPrivateSettable() const5002 bool MemberDefImpl::isPrivateSettable() const
5003 {
5004 return (m_impl->memSpec&Entry::PrivateSettable)!=0;
5005 }
5006
isProtectedSettable() const5007 bool MemberDefImpl::isProtectedSettable() const
5008 {
5009 return (m_impl->memSpec&Entry::ProtectedSettable)!=0;
5010 }
5011
isAddable() const5012 bool MemberDefImpl::isAddable() const
5013 {
5014 return (m_impl->memSpec&Entry::Addable)!=0;
5015 }
5016
isRemovable() const5017 bool MemberDefImpl::isRemovable() const
5018 {
5019 return (m_impl->memSpec&Entry::Removable)!=0;
5020 }
5021
isRaisable() const5022 bool MemberDefImpl::isRaisable() const
5023 {
5024 return (m_impl->memSpec&Entry::Raisable)!=0;
5025 }
5026
isReadable() const5027 bool MemberDefImpl::isReadable() const
5028 {
5029 return (m_impl->memSpec&Entry::Readable)!=0;
5030 }
5031
isWritable() const5032 bool MemberDefImpl::isWritable() const
5033 {
5034 return (m_impl->memSpec&Entry::Writable)!=0;
5035 }
5036
isFinal() const5037 bool MemberDefImpl::isFinal() const
5038 {
5039 return (m_impl->memSpec&Entry::Final)!=0;
5040 }
5041
isNew() const5042 bool MemberDefImpl::isNew() const
5043 {
5044 return (m_impl->memSpec&Entry::New)!=0;
5045 }
5046
isSealed() const5047 bool MemberDefImpl::isSealed() const
5048 {
5049 return (m_impl->memSpec&Entry::Sealed)!=0;
5050 }
5051
isOverride() const5052 bool MemberDefImpl::isOverride() const
5053 {
5054 return (m_impl->memSpec&Entry::Override)!=0;
5055 }
5056
isInitonly() const5057 bool MemberDefImpl::isInitonly() const
5058 {
5059 return (m_impl->memSpec&Entry::Initonly)!=0;
5060 }
5061
isAbstract() const5062 bool MemberDefImpl::isAbstract() const
5063 {
5064 return (m_impl->memSpec&Entry::Abstract)!=0;
5065 }
5066
isOptional() const5067 bool MemberDefImpl::isOptional() const
5068 {
5069 return (m_impl->memSpec&Entry::Optional)!=0;
5070 }
5071
isRequired() const5072 bool MemberDefImpl::isRequired() const
5073 {
5074 return (m_impl->memSpec&Entry::Required)!=0;
5075 }
5076
isNonAtomic() const5077 bool MemberDefImpl::isNonAtomic() const
5078 {
5079 return (m_impl->memSpec&Entry::NonAtomic)!=0;
5080 }
5081
isCopy() const5082 bool MemberDefImpl::isCopy() const
5083 {
5084 return (m_impl->memSpec&Entry::Copy)!=0;
5085 }
5086
isAssign() const5087 bool MemberDefImpl::isAssign() const
5088 {
5089 return (m_impl->memSpec&Entry::Assign)!=0;
5090 }
5091
isRetain() const5092 bool MemberDefImpl::isRetain() const
5093 {
5094 return (m_impl->memSpec&Entry::Retain)!=0;
5095 }
5096
isWeak() const5097 bool MemberDefImpl::isWeak() const
5098 {
5099 return (m_impl->memSpec&Entry::Weak)!=0;
5100 }
5101
isStrong() const5102 bool MemberDefImpl::isStrong() const
5103 {
5104 return (m_impl->memSpec&Entry::Strong)!=0;
5105 }
5106
isEnumStruct() const5107 bool MemberDefImpl::isEnumStruct() const
5108 {
5109 return (m_impl->memSpec&Entry::EnumStruct)!=0;
5110 }
5111
isStrongEnumValue() const5112 bool MemberDefImpl::isStrongEnumValue() const
5113 {
5114 return m_impl->mtype==MemberType_EnumValue &&
5115 m_impl->enumScope &&
5116 m_impl->enumScope->isStrong();
5117 }
5118
isUnretained() const5119 bool MemberDefImpl::isUnretained() const
5120 {
5121 return (m_impl->memSpec&Entry::Unretained)!=0;
5122 }
5123
isTypeAlias() const5124 bool MemberDefImpl::isTypeAlias() const
5125 {
5126 return (m_impl->memSpec&Entry::Alias)!=0;
5127 }
5128
isDefault() const5129 bool MemberDefImpl::isDefault() const
5130 {
5131 return (m_impl->memSpec&Entry::Default)!=0;
5132 }
5133
isDelete() const5134 bool MemberDefImpl::isDelete() const
5135 {
5136 return (m_impl->memSpec&Entry::Delete)!=0;
5137 }
5138
isNoExcept() const5139 bool MemberDefImpl::isNoExcept() const
5140 {
5141 return (m_impl->memSpec&Entry::NoExcept)!=0;
5142 }
5143
isAttribute() const5144 bool MemberDefImpl::isAttribute() const
5145 {
5146 return (m_impl->memSpec&Entry::Attribute)!=0;
5147 }
5148
isUNOProperty() const5149 bool MemberDefImpl::isUNOProperty() const
5150 {
5151 return (m_impl->memSpec&Entry::Property)!=0;
5152 }
5153
isReadonly() const5154 bool MemberDefImpl::isReadonly() const
5155 {
5156 return (m_impl->memSpec&Entry::Readonly)!=0;
5157 }
5158
isBound() const5159 bool MemberDefImpl::isBound() const
5160 {
5161 return (m_impl->memSpec&Entry::Bound)!=0;
5162 }
5163
isConstrained() const5164 bool MemberDefImpl::isConstrained() const
5165 {
5166 return (m_impl->memSpec&Entry::Constrained)!=0;
5167 }
5168
isTransient() const5169 bool MemberDefImpl::isTransient() const
5170 {
5171 return (m_impl->memSpec&Entry::Transient)!=0;
5172 }
5173
isMaybeVoid() const5174 bool MemberDefImpl::isMaybeVoid() const
5175 {
5176 return (m_impl->memSpec&Entry::MaybeVoid)!=0;
5177 }
5178
isMaybeDefault() const5179 bool MemberDefImpl::isMaybeDefault() const
5180 {
5181 return (m_impl->memSpec&Entry::MaybeDefault)!=0;
5182 }
5183
isMaybeAmbiguous() const5184 bool MemberDefImpl::isMaybeAmbiguous() const
5185 {
5186 return (m_impl->memSpec&Entry::MaybeAmbiguous)!=0;
5187 }
5188
isPublished() const5189 bool MemberDefImpl::isPublished() const
5190 {
5191 return (m_impl->memSpec&Entry::Published)!=0;
5192 }
5193
5194
isImplementation() const5195 bool MemberDefImpl::isImplementation() const
5196 {
5197 return m_impl->implOnly;
5198 }
5199
isExternal() const5200 bool MemberDefImpl::isExternal() const
5201 {
5202 return m_impl->explExt;
5203 }
5204
isTemplateSpecialization() const5205 bool MemberDefImpl::isTemplateSpecialization() const
5206 {
5207 return m_impl->tspec;
5208 }
5209
showInCallGraph() const5210 bool MemberDefImpl::showInCallGraph() const
5211 {
5212 return isFunction() ||
5213 isSlot() ||
5214 isConstructor() ||
5215 isDestructor() ||
5216 isObjCMethod();
5217 }
5218
relatedAlso() const5219 ClassDef *MemberDefImpl::relatedAlso() const
5220 {
5221 return m_impl->relatedAlso;
5222 }
5223
hasDocumentedEnumValues() const5224 bool MemberDefImpl::hasDocumentedEnumValues() const
5225 {
5226 return m_impl->docEnumValues;
5227 }
5228
getAnonymousEnumType() const5229 const MemberDef *MemberDefImpl::getAnonymousEnumType() const
5230 {
5231 return m_impl->annEnumType;
5232 }
5233
isDocsForDefinition() const5234 bool MemberDefImpl::isDocsForDefinition() const
5235 {
5236 return m_impl->docsForDefinition;
5237 }
5238
getEnumScope() const5239 const MemberDef *MemberDefImpl::getEnumScope() const
5240 {
5241 return m_impl->enumScope;
5242 }
5243
livesInsideEnum() const5244 bool MemberDefImpl::livesInsideEnum() const
5245 {
5246 return m_impl->livesInsideEnum;
5247 }
5248
isSliceLocal() const5249 bool MemberDefImpl::isSliceLocal() const
5250 {
5251 return (m_impl->memSpec&Entry::Local)!=0;
5252 }
5253
isConstExpr() const5254 bool MemberDefImpl::isConstExpr() const
5255 {
5256 return (m_impl->memSpec&Entry::ConstExpr)!=0;
5257 }
5258
enumFieldList() const5259 const MemberVector &MemberDefImpl::enumFieldList() const
5260 {
5261 return m_impl->enumFields;
5262 }
5263
getExamples() const5264 const ExampleList &MemberDefImpl::getExamples() const
5265 {
5266 return m_impl->examples;
5267 }
5268
isPrototype() const5269 bool MemberDefImpl::isPrototype() const
5270 {
5271 return m_impl->proto;
5272 }
5273
argumentList() const5274 const ArgumentList &MemberDefImpl::argumentList() const
5275 {
5276 return m_impl->defArgList;
5277 }
5278
argumentList()5279 ArgumentList &MemberDefImpl::argumentList()
5280 {
5281 return m_impl->defArgList;
5282 }
5283
declArgumentList() const5284 const ArgumentList &MemberDefImpl::declArgumentList() const
5285 {
5286 return m_impl->declArgList;
5287 }
5288
resolveUnnamedParameters(const MemberDef * md)5289 void MemberDefImpl::resolveUnnamedParameters(const MemberDef *md)
5290 {
5291 ArgumentList &decAl = m_impl->declArgList;
5292 ArgumentList &defAl = m_impl->defArgList;
5293 const ArgumentList &decAlSrc = md->declArgumentList();
5294 const ArgumentList &defAlSrc = md->argumentList();
5295 auto decSrc = decAlSrc.begin(), defSrc = defAlSrc.begin();
5296 for (auto decIt = decAl.begin(), defIt = defAl.begin();
5297 decIt != decAl.end() && defIt != defAl.end() && decSrc != decAlSrc.end() && defSrc != defAlSrc.end();
5298 ++decIt, ++defIt, ++decSrc, ++defSrc++)
5299 {
5300 Argument &decA = *decIt;
5301 Argument &defA = *defIt;
5302 const Argument &decAS = *decSrc;
5303 const Argument &defAS = *defSrc;
5304 if (decA.name.isEmpty())
5305 {
5306 if (!defA.name.isEmpty())
5307 {
5308 decA.name = defA.name;
5309 }
5310 else if (!decAS.name.isEmpty())
5311 {
5312 decA.name = decAS.name;
5313 }
5314 else if (!defAS.name.isEmpty())
5315 {
5316 decA.name = defAS.name;
5317 }
5318 }
5319 if (defA.name.isEmpty())
5320 {
5321 if (!decA.name.isEmpty())
5322 {
5323 defA.name = decA.name;
5324 }
5325 else if (!decAS.name.isEmpty())
5326 {
5327 defA.name = decAS.name;
5328 }
5329 else if (!defAS.name.isEmpty())
5330 {
5331 defA.name = defAS.name;
5332 }
5333 }
5334 }
5335 }
5336
templateArguments() const5337 const ArgumentList &MemberDefImpl::templateArguments() const
5338 {
5339 return m_impl->tArgList;
5340 }
5341
definitionTemplateParameterLists() const5342 const ArgumentLists &MemberDefImpl::definitionTemplateParameterLists() const
5343 {
5344 return m_impl->defTmpArgLists;
5345 }
5346
getMemberGroupId() const5347 int MemberDefImpl::getMemberGroupId() const
5348 {
5349 return m_impl->grpId;
5350 }
5351
getMemberGroup() const5352 MemberGroup *MemberDefImpl::getMemberGroup() const
5353 {
5354 return m_impl->memberGroup;
5355 }
5356
fromAnonymousScope() const5357 bool MemberDefImpl::fromAnonymousScope() const
5358 {
5359 return m_impl->annScope;
5360 }
5361
anonymousDeclShown() const5362 bool MemberDefImpl::anonymousDeclShown() const
5363 {
5364 return m_impl->annUsed;
5365 }
5366
setAnonymousUsed() const5367 void MemberDefImpl::setAnonymousUsed() const
5368 {
5369 m_impl->annUsed = TRUE;
5370 }
5371
hasCallGraph() const5372 bool MemberDefImpl::hasCallGraph() const
5373 {
5374 return m_impl->hasCallGraph;
5375 }
5376
_hasVisibleCallGraph() const5377 bool MemberDefImpl::_hasVisibleCallGraph() const
5378 {
5379 bool enabled = m_impl->hasCallGraph &&
5380 (isFunction() || isSlot() || isSignal()) &&
5381 Config_getBool(HAVE_DOT);
5382 if (enabled)
5383 {
5384 bool trivial = DotCallGraph::isTrivial(this,FALSE);
5385 return !trivial;
5386 }
5387 return FALSE;
5388 }
5389
hasCallerGraph() const5390 bool MemberDefImpl::hasCallerGraph() const
5391 {
5392 return m_impl->hasCallerGraph;
5393 }
5394
_hasVisibleCallerGraph() const5395 bool MemberDefImpl::_hasVisibleCallerGraph() const
5396 {
5397 bool enabled = m_impl->hasCallerGraph &&
5398 (isFunction() || isSlot() || isSignal()) &&
5399 Config_getBool(HAVE_DOT);
5400 if (enabled)
5401 {
5402 bool trivial = DotCallGraph::isTrivial(this,TRUE);
5403 return !trivial;
5404 }
5405 return FALSE;
5406 }
5407
hasReferencedByRelation() const5408 bool MemberDefImpl::hasReferencedByRelation() const
5409 {
5410 return m_impl->hasReferencedByRelation;
5411 }
5412
hasReferencesRelation() const5413 bool MemberDefImpl::hasReferencesRelation() const
5414 {
5415 return m_impl->hasReferencesRelation;
5416 }
5417
templateMaster() const5418 const MemberDef *MemberDefImpl::templateMaster() const
5419 {
5420 return m_impl->templateMaster;
5421 }
5422
isTypedefValCached() const5423 bool MemberDefImpl::isTypedefValCached() const
5424 {
5425 return m_impl->isTypedefValCached;
5426 }
5427
getCachedTypedefVal() const5428 const ClassDef *MemberDefImpl::getCachedTypedefVal() const
5429 {
5430 return m_impl->cachedTypedefValue;
5431 }
5432
getCachedTypedefTemplSpec() const5433 QCString MemberDefImpl::getCachedTypedefTemplSpec() const
5434 {
5435 return m_impl->cachedTypedefTemplSpec;
5436 }
5437
getCachedResolvedTypedef() const5438 QCString MemberDefImpl::getCachedResolvedTypedef() const
5439 {
5440 //printf("MemberDefImpl::getCachedResolvedTypedef()=%s m_impl=%p\n",qPrint(m_impl->cachedResolvedType),m_impl);
5441 return m_impl->cachedResolvedType;
5442 }
5443
memberDefinition() const5444 MemberDef *MemberDefImpl::memberDefinition() const
5445 {
5446 return m_impl->memDef;
5447 }
5448
memberDeclaration() const5449 MemberDef *MemberDefImpl::memberDeclaration() const
5450 {
5451 return m_impl->memDec;
5452 }
5453
inheritsDocsFrom() const5454 const MemberDef *MemberDefImpl::inheritsDocsFrom() const
5455 {
5456 return m_impl->docProvider;
5457 }
5458
getGroupAlias() const5459 const MemberDef *MemberDefImpl::getGroupAlias() const
5460 {
5461 return m_impl->groupAlias;
5462 }
5463
getDeclFileName() const5464 QCString MemberDefImpl::getDeclFileName() const
5465 {
5466 return m_impl->declFileName;
5467 }
5468
getDeclLine() const5469 int MemberDefImpl::getDeclLine() const
5470 {
5471 return m_impl->declLine;
5472 }
5473
getDeclColumn() const5474 int MemberDefImpl::getDeclColumn() const
5475 {
5476 return m_impl->declColumn;
5477 }
5478
5479
5480 //----------------------------------------------
5481
setMemberType(MemberType t)5482 void MemberDefImpl::setMemberType(MemberType t)
5483 {
5484 m_impl->mtype=t;
5485 m_isLinkableCached = 0;
5486 }
5487
setDefinition(const QCString & d)5488 void MemberDefImpl::setDefinition(const QCString &d)
5489 {
5490 m_impl->def=d;
5491 }
5492
setFileDef(const FileDef * fd)5493 void MemberDefImpl::setFileDef(const FileDef *fd)
5494 {
5495 m_impl->fileDef=fd;
5496 m_isLinkableCached = 0;
5497 m_isConstructorCached = 0;
5498 m_isDestructorCached = 0;
5499 }
5500
setProtection(Protection p)5501 void MemberDefImpl::setProtection(Protection p)
5502 {
5503 m_impl->prot=p;
5504 m_isLinkableCached = 0;
5505 }
5506
setMemberSpecifiers(uint64 s)5507 void MemberDefImpl::setMemberSpecifiers(uint64 s)
5508 {
5509 m_impl->memSpec=s;
5510 }
5511
mergeMemberSpecifiers(uint64 s)5512 void MemberDefImpl::mergeMemberSpecifiers(uint64 s)
5513 {
5514 m_impl->memSpec|=s;
5515 }
5516
setBitfields(const QCString & s)5517 void MemberDefImpl::setBitfields(const QCString &s)
5518 {
5519 m_impl->bitfields = QCString(s).simplifyWhiteSpace();
5520 }
5521
setMaxInitLines(int lines)5522 void MemberDefImpl::setMaxInitLines(int lines)
5523 {
5524 if (lines!=-1)
5525 {
5526 m_impl->userInitLines=lines;
5527 }
5528 }
5529
setReadAccessor(const QCString & r)5530 void MemberDefImpl::setReadAccessor(const QCString &r)
5531 {
5532 m_impl->read=r;
5533 }
5534
setWriteAccessor(const QCString & w)5535 void MemberDefImpl::setWriteAccessor(const QCString &w)
5536 {
5537 m_impl->write=w;
5538 }
5539
setTemplateSpecialization(bool b)5540 void MemberDefImpl::setTemplateSpecialization(bool b)
5541 {
5542 m_impl->tspec=b;
5543 }
5544
makeRelated()5545 void MemberDefImpl::makeRelated()
5546 {
5547 m_impl->related = Related;
5548 m_isLinkableCached = 0;
5549 }
5550
makeForeign()5551 void MemberDefImpl::makeForeign()
5552 {
5553 m_impl->related = Foreign;
5554 m_isLinkableCached = 0;
5555 }
5556
setInheritsDocsFrom(const MemberDef * md)5557 void MemberDefImpl::setInheritsDocsFrom(const MemberDef *md)
5558 {
5559 m_impl->docProvider = md;
5560 }
5561
setArgsString(const QCString & as)5562 void MemberDefImpl::setArgsString(const QCString &as)
5563 {
5564 m_impl->args = as;
5565 }
5566
setRelatedAlso(ClassDef * cd)5567 void MemberDefImpl::setRelatedAlso(ClassDef *cd)
5568 {
5569 m_impl->relatedAlso=cd;
5570 }
5571
setEnumClassScope(const ClassDef * cd)5572 void MemberDefImpl::setEnumClassScope(const ClassDef *cd)
5573 {
5574 m_impl->classDef = cd;
5575 m_isLinkableCached = 0;
5576 m_isConstructorCached = 0;
5577 }
5578
setDocumentedEnumValues(bool value)5579 void MemberDefImpl::setDocumentedEnumValues(bool value)
5580 {
5581 m_impl->docEnumValues=value;
5582 }
5583
setAnonymousEnumType(const MemberDef * md)5584 void MemberDefImpl::setAnonymousEnumType(const MemberDef *md)
5585 {
5586 m_impl->annEnumType = md;
5587 }
5588
setPrototype(bool p,const QCString & df,int line,int column)5589 void MemberDefImpl::setPrototype(bool p,const QCString &df,int line,int column)
5590 {
5591 m_impl->proto=p;
5592 if (p)
5593 {
5594 setDeclFile(df,line,column);
5595 }
5596 else
5597 {
5598 setDefFile(df,line,column);
5599 }
5600 }
5601
setExplicitExternal(bool b,const QCString & df,int line,int column)5602 void MemberDefImpl::setExplicitExternal(bool b,const QCString &df,int line,int column)
5603 {
5604 m_impl->explExt=b;
5605 if (b)
5606 {
5607 setDeclFile(df,line,column);
5608 }
5609 else
5610 {
5611 setDefFile(df,line,column);
5612 }
5613 }
5614
5615
setDeclFile(const QCString & df,int line,int column)5616 void MemberDefImpl::setDeclFile(const QCString &df,int line,int column)
5617 {
5618 m_impl->declFileName = df;
5619 m_impl->declLine = line;
5620 m_impl->declColumn = column;
5621 }
5622
setMemberGroupId(int id)5623 void MemberDefImpl::setMemberGroupId(int id)
5624 {
5625 m_impl->grpId=id;
5626 }
5627
makeImplementationDetail()5628 void MemberDefImpl::makeImplementationDetail()
5629 {
5630 m_impl->implOnly=TRUE;
5631 }
5632
setFromAnonymousScope(bool b) const5633 void MemberDefImpl::setFromAnonymousScope(bool b) const
5634 {
5635 m_impl->annScope=b;
5636 }
5637
setFromAnonymousMember(MemberDef * m)5638 void MemberDefImpl::setFromAnonymousMember(MemberDef *m)
5639 {
5640 m_impl->annMemb=m;
5641 }
5642
fromAnonymousMember() const5643 MemberDef *MemberDefImpl::fromAnonymousMember() const
5644 {
5645 return m_impl->annMemb;
5646 }
5647
setTemplateMaster(const MemberDef * mt)5648 void MemberDefImpl::setTemplateMaster(const MemberDef *mt)
5649 {
5650 m_impl->templateMaster=mt;
5651 m_isLinkableCached = 0;
5652 }
5653
setDocsForDefinition(bool b)5654 void MemberDefImpl::setDocsForDefinition(bool b)
5655 {
5656 m_impl->docsForDefinition = b;
5657 }
5658
setGroupAlias(const MemberDef * md)5659 void MemberDefImpl::setGroupAlias(const MemberDef *md)
5660 {
5661 m_impl->groupAlias = md;
5662 }
5663
invalidateTypedefValCache()5664 void MemberDefImpl::invalidateTypedefValCache()
5665 {
5666 m_impl->isTypedefValCached=FALSE;
5667 }
5668
setMemberDefinition(MemberDef * md)5669 void MemberDefImpl::setMemberDefinition(MemberDef *md)
5670 {
5671 m_impl->memDef=md;
5672 }
5673
setMemberDeclaration(MemberDef * md)5674 void MemberDefImpl::setMemberDeclaration(MemberDef *md)
5675 {
5676 m_impl->memDec=md;
5677 }
5678
category() const5679 ClassDef *MemberDefImpl::category() const
5680 {
5681 return m_impl->category;
5682 }
5683
setCategory(ClassDef * def)5684 void MemberDefImpl::setCategory(ClassDef *def)
5685 {
5686 m_impl->category = def;
5687 }
5688
categoryRelation() const5689 const MemberDef *MemberDefImpl::categoryRelation() const
5690 {
5691 return m_impl->categoryRelation;
5692 }
5693
setCategoryRelation(const MemberDef * md)5694 void MemberDefImpl::setCategoryRelation(const MemberDef *md)
5695 {
5696 m_impl->categoryRelation = md;
5697 }
5698
setEnumBaseType(const QCString & type)5699 void MemberDefImpl::setEnumBaseType(const QCString &type)
5700 {
5701 m_impl->enumBaseType = type;
5702 }
5703
enumBaseType() const5704 QCString MemberDefImpl::enumBaseType() const
5705 {
5706 return m_impl->enumBaseType;
5707 }
5708
setRequiresClause(const QCString & req)5709 void MemberDefImpl::setRequiresClause(const QCString &req)
5710 {
5711 m_impl->requiresClause = req;
5712 }
5713
requiresClause() const5714 QCString MemberDefImpl::requiresClause() const
5715 {
5716 return m_impl->requiresClause;
5717 }
5718
cacheTypedefVal(const ClassDef * val,const QCString & templSpec,const QCString & resolvedType)5719 void MemberDefImpl::cacheTypedefVal(const ClassDef*val, const QCString & templSpec, const QCString &resolvedType)
5720 {
5721 m_impl->isTypedefValCached=TRUE;
5722 m_impl->cachedTypedefValue=val;
5723 m_impl->cachedTypedefTemplSpec=templSpec;
5724 m_impl->cachedResolvedType=resolvedType;
5725 //printf("MemberDefImpl::cacheTypedefVal=%s m_impl=%p\n",qPrint(m_impl->cachedResolvedType),m_impl);
5726 }
5727
copyArgumentNames(const MemberDef * bmd)5728 void MemberDefImpl::copyArgumentNames(const MemberDef *bmd)
5729 {
5730 {
5731 const ArgumentList &srcAl = bmd->argumentList();
5732 ArgumentList &dstAl = m_impl->defArgList;
5733 auto srcIt = srcAl.begin();
5734 auto dstIt = dstAl.begin();
5735 while ( srcIt!=srcAl.end() && dstIt!=dstAl.end())
5736 {
5737 Argument &argDst = *dstIt;
5738 const Argument &argSrc = *srcIt;
5739 argDst.name = argSrc.name;
5740 argDst.docs = argSrc.docs;
5741 ++srcIt;
5742 ++dstIt;
5743 }
5744 }
5745
5746 {
5747 const ArgumentList &srcAl = bmd->declArgumentList();
5748 ArgumentList &dstAl = m_impl->declArgList;
5749 auto srcIt = srcAl.begin();
5750 auto dstIt = dstAl.begin();
5751
5752 while ( srcIt!=srcAl.end() && dstIt!=dstAl.end())
5753 {
5754 Argument &argDst = *dstIt;
5755 const Argument &argSrc = *srcIt;
5756 argDst.name = argSrc.name;
5757 argDst.docs = argSrc.docs;
5758 ++srcIt;
5759 ++dstIt;
5760 }
5761 }
5762 }
5763
invalidateCachedTypesInArgumentList(ArgumentList & al)5764 static void invalidateCachedTypesInArgumentList(ArgumentList &al)
5765 {
5766 for (Argument &a : al)
5767 {
5768 a.canType.resize(0);
5769 }
5770 }
5771
invalidateCachedArgumentTypes()5772 void MemberDefImpl::invalidateCachedArgumentTypes()
5773 {
5774 invalidateCachedTypesInArgumentList(m_impl->defArgList);
5775 invalidateCachedTypesInArgumentList(m_impl->declArgList);
5776 }
5777
incrementFlowKeyWordCount()5778 void MemberDefImpl::incrementFlowKeyWordCount()
5779 {
5780 m_impl->numberOfFlowKW++;
5781 }
5782
numberOfFlowKeyWords() const5783 int MemberDefImpl::numberOfFlowKeyWords() const
5784 {
5785 return m_impl->numberOfFlowKW;
5786 }
5787
5788 //----------------
5789
displayName(bool) const5790 QCString MemberDefImpl::displayName(bool) const
5791 {
5792 return DefinitionMixin::name();
5793 }
5794
5795 //----------------
5796
transferArgumentDocumentation(ArgumentList & decAl,ArgumentList & defAl)5797 static void transferArgumentDocumentation(ArgumentList &decAl,ArgumentList &defAl)
5798 {
5799 for (auto decIt = decAl.begin(), defIt = defAl.begin();
5800 decIt!= decAl.end() && defIt!= defAl.end();
5801 ++decIt, ++defIt)
5802 {
5803 Argument &decA = *decIt;
5804 Argument &defA = *defIt;
5805 if (decA.docs.isEmpty() && !defA.docs.isEmpty())
5806 {
5807 decA.docs = defA.docs;
5808 }
5809 else if (defA.docs.isEmpty() && !decA.docs.isEmpty())
5810 {
5811 defA.docs = decA.docs;
5812 }
5813 if (Config_getBool(RESOLVE_UNNAMED_PARAMS))
5814 {
5815 if (decA.name.isEmpty() && !defA.name.isEmpty())
5816 {
5817 decA.name = defA.name;
5818 }
5819 else if (defA.name.isEmpty() && !decA.name.isEmpty())
5820 {
5821 defA.name = decA.name;
5822 }
5823 }
5824 }
5825 }
5826
combineDeclarationAndDefinition(MemberDefMutable * mdec,MemberDefMutable * mdef)5827 void combineDeclarationAndDefinition(MemberDefMutable *mdec,MemberDefMutable *mdef)
5828 {
5829 //printf("mdec=%s isPrototype()=%d\n",qPrint(mdec->name()),mdec->isPrototype());
5830 if (
5831 (mdef->isFunction() && !mdef->isStatic() && !mdef->isPrototype()) ||
5832 (mdef->isVariable() && !mdef->isExternal() && !mdef->isStatic())
5833 )
5834 {
5835 //printf("mdef=(%p,%s) mdec=(%p,%s)\n",
5836 // mdef, mdef ? qPrint(mdef->name()) : "",
5837 // mdec, mdec ? qPrint(mdec->name()) : "");
5838
5839 bool sameNumTemplateArgs = mdef->templateArguments().size()==mdec->templateArguments().size();
5840
5841 ArgumentList &mdefAl = const_cast<ArgumentList&>(mdef->argumentList());
5842 ArgumentList &mdecAl = const_cast<ArgumentList&>(mdec->argumentList());
5843 if (sameNumTemplateArgs &&
5844 matchArguments2(mdef->getOuterScope(),mdef->getFileDef(),&mdefAl,
5845 mdec->getOuterScope(),mdec->getFileDef(),&mdecAl,
5846 TRUE
5847 )
5848 ) /* match found */
5849 {
5850 //printf("Found member %s: definition in %s (doc='%s') and declaration in %s (doc='%s')\n",
5851 // mn->memberName(),
5852 // qPrint(mdef->getFileDef()->name()),qPrint(mdef->documentation()),
5853 // qPrint(mdec->getFileDef()->name()),qPrint(mdec->documentation())
5854 // );
5855
5856 if (Config_getBool(RESOLVE_UNNAMED_PARAMS))
5857 {
5858 mdec->resolveUnnamedParameters(mdef);
5859 }
5860
5861 // first merge argument documentation
5862 transferArgumentDocumentation(mdecAl,mdefAl);
5863
5864 /* copy documentation between function definition and declaration */
5865 if (!mdec->briefDescription().isEmpty())
5866 {
5867 mdef->setBriefDescription(mdec->briefDescription(),mdec->briefFile(),mdec->briefLine());
5868 }
5869 else if (!mdef->briefDescription().isEmpty())
5870 {
5871 mdec->setBriefDescription(mdef->briefDescription(),mdef->briefFile(),mdef->briefLine());
5872 }
5873 if (!mdef->documentation().isEmpty())
5874 {
5875 //printf("transferring docs mdef->mdec (%s->%s)\n",mdef->argsString(),mdec->argsString());
5876 mdec->setDocumentation(mdef->documentation(),mdef->docFile(),mdef->docLine());
5877 mdec->setDocsForDefinition(mdef->isDocsForDefinition());
5878 if (mdefAl.hasParameters())
5879 {
5880 auto mdefAlComb = stringToArgumentList(mdef->getLanguage(),mdef->argsString());
5881 transferArgumentDocumentation(mdefAl,*mdefAlComb);
5882 mdec->moveArgumentList(std::move(mdefAlComb));
5883 }
5884 }
5885 else if (!mdec->documentation().isEmpty())
5886 {
5887 //printf("transferring docs mdec->mdef (%s->%s)\n",mdec->argsString(),mdef->argsString());
5888 mdef->setDocumentation(mdec->documentation(),mdec->docFile(),mdec->docLine());
5889 mdef->setDocsForDefinition(mdec->isDocsForDefinition());
5890 if (mdecAl.hasParameters())
5891 {
5892 auto mdecAlComb = stringToArgumentList(mdec->getLanguage(),mdec->argsString());
5893 transferArgumentDocumentation(mdecAl,*mdecAlComb);
5894 mdef->moveDeclArgumentList(std::move(mdecAlComb));
5895 }
5896 }
5897 if (!mdef->inbodyDocumentation().isEmpty())
5898 {
5899 mdec->setInbodyDocumentation(mdef->inbodyDocumentation(),mdef->inbodyFile(),mdef->inbodyLine());
5900 }
5901 else if (!mdec->inbodyDocumentation().isEmpty())
5902 {
5903 mdef->setInbodyDocumentation(mdec->inbodyDocumentation(),mdec->inbodyFile(),mdec->inbodyLine());
5904 }
5905 if (mdec->getStartBodyLine()!=-1 && mdef->getStartBodyLine()==-1)
5906 {
5907 //printf("body mdec->mdef %d-%d\n",mdec->getStartBodyLine(),mdef->getEndBodyLine());
5908 mdef->setBodySegment(mdec->getDefLine(),mdec->getStartBodyLine(),mdec->getEndBodyLine());
5909 mdef->setBodyDef(mdec->getBodyDef());
5910 //mdef->setBodyMember(mdec);
5911 }
5912 else if (mdef->getStartBodyLine()!=-1 && mdec->getStartBodyLine()==-1)
5913 {
5914 //printf("body mdef->mdec %d-%d\n",mdef->getStartBodyLine(),mdec->getEndBodyLine());
5915 mdec->setBodySegment(mdef->getDefLine(),mdef->getStartBodyLine(),mdef->getEndBodyLine());
5916 mdec->setBodyDef(mdef->getBodyDef());
5917 //mdec->setBodyMember(mdef);
5918 }
5919 mdec->mergeMemberSpecifiers(mdef->getMemberSpecifiers());
5920 mdef->mergeMemberSpecifiers(mdec->getMemberSpecifiers());
5921
5922 // copy group info.
5923 if (mdec->getGroupDef()==0 && mdef->getGroupDef()!=0)
5924 {
5925 mdec->setGroupDef(mdef->getGroupDef(),
5926 mdef->getGroupPri(),
5927 mdef->docFile(),
5928 mdef->docLine(),
5929 mdef->hasDocumentation(),
5930 mdef
5931 );
5932 }
5933 else if (mdef->getGroupDef()==0 && mdec->getGroupDef()!=0)
5934 {
5935 mdef->setGroupDef(mdec->getGroupDef(),
5936 mdec->getGroupPri(),
5937 mdec->docFile(),
5938 mdec->docLine(),
5939 mdec->hasDocumentation(),
5940 mdec
5941 );
5942 }
5943
5944
5945 mdec->mergeRefItems(mdef);
5946 mdef->mergeRefItems(mdec);
5947
5948 mdef->setMemberDeclaration(mdec);
5949 mdec->setMemberDefinition(mdef);
5950
5951 mdef->enableCallGraph(mdec->hasCallGraph() || mdef->hasCallGraph());
5952 mdef->enableCallerGraph(mdec->hasCallerGraph() || mdef->hasCallerGraph());
5953 mdec->enableCallGraph(mdec->hasCallGraph() || mdef->hasCallGraph());
5954 mdec->enableCallerGraph(mdec->hasCallerGraph() || mdef->hasCallerGraph());
5955
5956 mdef->enableReferencedByRelation(mdec->hasReferencedByRelation() || mdef->hasReferencedByRelation());
5957 mdef->enableReferencesRelation(mdec->hasReferencesRelation() || mdef->hasReferencesRelation());
5958 mdec->enableReferencedByRelation(mdec->hasReferencedByRelation() || mdef->hasReferencedByRelation());
5959 mdec->enableReferencesRelation(mdec->hasReferencesRelation() || mdef->hasReferencesRelation());
5960 }
5961 }
5962 }
5963
briefDescription(bool abbr) const5964 QCString MemberDefImpl::briefDescription(bool abbr) const
5965 {
5966 if (m_impl->templateMaster)
5967 {
5968 return m_impl->templateMaster->briefDescription(abbr);
5969 }
5970 else
5971 {
5972 return DefinitionMixin::briefDescription(abbr);
5973 }
5974 }
5975
documentation() const5976 QCString MemberDefImpl::documentation() const
5977 {
5978 if (m_impl->templateMaster)
5979 {
5980 return m_impl->templateMaster->documentation();
5981 }
5982 else
5983 {
5984 return DefinitionMixin::documentation();
5985 }
5986 }
5987
typeConstraints() const5988 const ArgumentList &MemberDefImpl::typeConstraints() const
5989 {
5990 return m_impl->typeConstraints;
5991 }
5992
isFriendToHide() const5993 bool MemberDefImpl::isFriendToHide() const
5994 {
5995 static bool hideFriendCompounds = Config_getBool(HIDE_FRIEND_COMPOUNDS);
5996 bool isFriendToHide = hideFriendCompounds &&
5997 (m_impl->type=="friend class" ||
5998 m_impl->type=="friend struct" ||
5999 m_impl->type=="friend union");
6000 return isFriendToHide;
6001 }
6002
isFriendClass() const6003 bool MemberDefImpl::isFriendClass() const
6004 {
6005 return (isFriend() &&
6006 (m_impl->type=="friend class" || m_impl->type=="friend struct" ||
6007 m_impl->type=="friend union"));
6008 }
6009
6010
isNotFriend() const6011 bool MemberDefImpl::isNotFriend() const
6012 {
6013 return !(isFriend() && isFriendToHide());
6014 }
6015
isFunctionOrSignalSlot() const6016 bool MemberDefImpl::isFunctionOrSignalSlot() const
6017 {
6018 return isFunction() || isSlot() || isSignal();
6019 }
6020
isRelatedOrFriend() const6021 bool MemberDefImpl::isRelatedOrFriend() const
6022 {
6023 return isRelated() || isForeign() || (isFriend() && !isFriendToHide());
6024 }
6025
isReference() const6026 bool MemberDefImpl::isReference() const
6027 {
6028 return DefinitionMixin::isReference() ||
6029 (m_impl->templateMaster && m_impl->templateMaster->isReference());
6030 }
6031
codeSymbolType() const6032 CodeSymbolType MemberDefImpl::codeSymbolType() const
6033 {
6034 switch (memberType())
6035 {
6036 case MemberType_Define: return CodeSymbolType::Define;
6037 case MemberType_Function: return CodeSymbolType::Function;
6038 case MemberType_Variable: return CodeSymbolType::Variable;
6039 case MemberType_Typedef: return CodeSymbolType::Typedef;
6040 case MemberType_Enumeration: return CodeSymbolType::Enumeration;
6041 case MemberType_EnumValue: return CodeSymbolType::EnumValue;
6042 case MemberType_Signal: return CodeSymbolType::Signal;
6043 case MemberType_Slot: return CodeSymbolType::Slot;
6044 case MemberType_Friend: return CodeSymbolType::Friend;
6045 case MemberType_DCOP: return CodeSymbolType::DCOP;
6046 case MemberType_Property: return CodeSymbolType::Property;
6047 case MemberType_Event: return CodeSymbolType::Event;
6048 case MemberType_Interface: return CodeSymbolType::Interface;
6049 case MemberType_Service: return CodeSymbolType::Service;
6050 case MemberType_Sequence: return CodeSymbolType::Sequence;
6051 case MemberType_Dictionary: return CodeSymbolType::Dictionary;
6052 }
6053 return CodeSymbolType::Default;
6054 }
6055
6056 //-------------------------------------------------------------------------------
6057 // Helpers
6058
addDocCrossReference(MemberDefMutable * src,MemberDefMutable * dst)6059 void addDocCrossReference(MemberDefMutable *src,MemberDefMutable *dst)
6060 {
6061 if (src==0 || dst==0) return;
6062 //printf("--> addDocCrossReference src=%s,dst=%s\n",qPrint(src->name()),qPrint(dst->name()));
6063 if (dst->isTypedef() || dst->isEnumerate()) return; // don't add types
6064 if ((dst->hasReferencedByRelation() || dst->hasCallerGraph()) &&
6065 src->showInCallGraph()
6066 )
6067 {
6068 dst->addSourceReferencedBy(src);
6069 MemberDefMutable *mdDef = toMemberDefMutable(dst->memberDefinition());
6070 if (mdDef)
6071 {
6072 mdDef->addSourceReferencedBy(src);
6073 }
6074 MemberDefMutable *mdDecl = toMemberDefMutable(dst->memberDeclaration());
6075 if (mdDecl)
6076 {
6077 mdDecl->addSourceReferencedBy(src);
6078 }
6079 }
6080 if ((src->hasReferencesRelation() || src->hasCallGraph()) &&
6081 src->showInCallGraph()
6082 )
6083 {
6084 src->addSourceReferences(dst);
6085 MemberDefMutable *mdDef = toMemberDefMutable(src->memberDefinition());
6086 if (mdDef)
6087 {
6088 mdDef->addSourceReferences(dst);
6089 }
6090 MemberDefMutable *mdDecl = toMemberDefMutable(src->memberDeclaration());
6091 if (mdDecl)
6092 {
6093 mdDecl->addSourceReferences(dst);
6094 }
6095 }
6096 }
6097
6098 // --- Cast functions
6099 //
toMemberDef(Definition * d)6100 MemberDef *toMemberDef(Definition *d)
6101 {
6102 if (d && (typeid(*d)==typeid(MemberDefImpl) || typeid(*d)==typeid(MemberDefAliasImpl)))
6103 {
6104 return static_cast<MemberDef*>(d);
6105 }
6106 else
6107 {
6108 return 0;
6109 }
6110 }
6111
toMemberDef(DefinitionMutable * md)6112 MemberDef *toMemberDef(DefinitionMutable *md)
6113 {
6114 Definition *d = toDefinition(md);
6115 if (d && typeid(*d)==typeid(MemberDefImpl))
6116 {
6117 return static_cast<MemberDef*>(d);
6118 }
6119 else
6120 {
6121 return 0;
6122 }
6123 }
6124
toMemberDef(const Definition * d)6125 const MemberDef *toMemberDef(const Definition *d)
6126 {
6127 if (d && (typeid(*d)==typeid(MemberDefImpl) || typeid(*d)==typeid(MemberDefAliasImpl)))
6128 {
6129 return static_cast<const MemberDef*>(d);
6130 }
6131 else
6132 {
6133 return 0;
6134 }
6135 }
6136
toMemberDefMutable(Definition * d)6137 MemberDefMutable *toMemberDefMutable(Definition *d)
6138 {
6139 if (d && typeid(*d)==typeid(MemberDefImpl))
6140 {
6141 return static_cast<MemberDefMutable*>(d);
6142 }
6143 else
6144 {
6145 return 0;
6146 }
6147 }
6148
toMemberDefMutable(const Definition * d)6149 MemberDefMutable *toMemberDefMutable(const Definition *d)
6150 {
6151 if (d && typeid(*d)==typeid(MemberDefImpl))
6152 {
6153 return const_cast<MemberDefMutable*>(static_cast<const MemberDefMutable*>(d));
6154 }
6155 else
6156 {
6157 return 0;
6158 }
6159 }
6160
6161
6162
6163