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("&#160;&#160;");
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