diff options
Diffstat (limited to 'src/classdef.cpp')
-rw-r--r-- | src/classdef.cpp | 4498 |
1 files changed, 4498 insertions, 0 deletions
diff --git a/src/classdef.cpp b/src/classdef.cpp new file mode 100644 index 0000000..985c7b3 --- /dev/null +++ b/src/classdef.cpp @@ -0,0 +1,4498 @@ +/****************************************************************************** + * + * $Id: classdef.cpp,v 1.54 2001/03/19 19:27:39 root Exp $ + * + * Copyright (C) 1997-2012 by Dimitri van Heesch. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software + * for any purpose. It is provided "as is" without express or implied warranty. + * See the GNU General Public License for more details. + * + * Documents produced by Doxygen are derivative works derived from the + * input used in their production; they are not affected by this license. + * + */ + +#include <stdio.h> +#include <qfile.h> +#include <qregexp.h> +#include "classdef.h" +#include "classlist.h" +#include "entry.h" +#include "doxygen.h" +#include "membername.h" +#include "message.h" +#include "config.h" +#include "util.h" +#include "diagram.h" +#include "language.h" +#include "htmlhelp.h" +#include "example.h" +#include "outputlist.h" +#include "dot.h" +#include "defargs.h" +#include "debug.h" +#include "docparser.h" +#include "searchindex.h" +#include "vhdldocgen.h" +#include "layout.h" +#include "arguments.h" + +//----------------------------------------------------------------------------- + +/** Private data associated with a ClassDef object. */ +class ClassDefImpl +{ + public: + ClassDefImpl(); + ~ClassDefImpl(); + void init(const char *defFileName, const char *name, + const QCString &ctStr, const char *fName); + + /*! file name that forms the base for the output file containing the + * class documentation. For compatibility with Qt (e.g. links via tag + * files) this name cannot be derived from the class name directly. + */ + QCString fileName; + + /*! Include information about the header file should be included + * in the documentation. 0 by default, set by setIncludeFile(). + */ + IncludeInfo *incInfo; + + /*! List of base class (or super-classes) from which this class derives + * directly. + */ + BaseClassList *inherits; + + /*! List of sub-classes that directly derive from this class + */ + BaseClassList *inheritedBy; + + /*! Namespace this class is part of + * (this is the inner most namespace in case of nested namespaces) + */ + NamespaceDef *nspace; + + /*! File this class is defined in */ + FileDef *fileDef; + + /*! List of all members (including inherited members) */ + MemberNameInfoSDict *allMemberNameInfoSDict; + + /*! Template arguments of this class */ + ArgumentList *tempArgs; + + /*! Type constraints for template parameters */ + ArgumentList *typeConstraints; + + /*! Files that were used for generating the class documentation. */ + QStrList files; + + /*! Examples that use this class */ + ExampleSDict *exampleSDict; + + /*! Holds the kind of "class" this is. */ + ClassDef::CompoundType compType; + + /*! The protection level in which this class was found. + * Typically Public, but for nested classes this can also be Protected + * or Private. + */ + Protection prot; + + /*! The inner classes contained in this class. Will be 0 if there are + * no inner classes. + */ + ClassSDict *innerClasses; + + /* classes for the collaboration diagram */ + UsesClassDict *usesImplClassDict; + UsesClassDict *usedByImplClassDict; + UsesClassDict *usesIntfClassDict; + + /*! Template instances that exists of this class, the key in the + * dictionary is the template argument list. + */ + QDict<ClassDef> *templateInstances; + + /*! Template instances that exists of this class, as defined by variables. + * We do NOT want to document these individually. The key in the + * dictionary is the template argument list. + */ + QDict<ClassDef> *variableInstances; + + QDict<int> *templBaseClassNames; + + /*! The class this class is an instance of. */ + ClassDef *templateMaster; + + /*! local class name which could be a typedef'ed alias name. */ + QCString className; + + /*! If this class is a Objective-C category, then this points to the + * class which is extended. + */ + ClassDef *categoryOf; + + QList<MemberList> memberLists; + + /* user defined member groups */ + MemberGroupSDict *memberGroupSDict; + + /*! Is this an abstact class? */ + bool isAbstract; + + /*! Is the class part of an unnamed namespace? */ + bool isStatic; + + /*! TRUE if classes members are merged with those of the base classes. */ + bool membersMerged; + + /*! TRUE if the class is defined in a source file rather than a header file. */ + bool isLocal; + + bool isTemplArg; + + /*! Does this class group its user-grouped members + * as a sub-section of the normal (public/protected/..) + * groups? + */ + bool subGrouping; + + /** Reason of existence is a "use" relation */ + bool usedOnly; + + /** List of titles to use for the summary */ + SDict<QCString> vhdlSummaryTitles; + + /** Is this a simple (non-nested) C structure? */ + bool isSimple; + + /** Does this class overloaded the -> operator? */ + MemberDef *arrowOperator; + + ClassList *taggedInnerClasses; + ClassDef *tagLessRef; + + /** Does this class represent a Java style enum? */ + bool isJavaEnum; + + bool isGeneric; + + int spec; +}; + +void ClassDefImpl::init(const char *defFileName, const char *name, + const QCString &ctStr, const char *fName) +{ + if (fName) + { + fileName=stripExtension(fName); + } + else + { + fileName=ctStr+name; + } + exampleSDict = 0; + inherits = 0; + inheritedBy = 0; + allMemberNameInfoSDict = 0; + incInfo=0; + tempArgs=0; + typeConstraints=0; + prot=Public; + nspace=0; + fileDef=0; + usesImplClassDict=0; + usedByImplClassDict=0; + usesIntfClassDict=0; + memberGroupSDict = 0; + innerClasses = 0; + subGrouping=Config_getBool("SUBGROUPING"); + templateInstances = 0; + variableInstances = 0; + templateMaster =0; + templBaseClassNames = 0; + isAbstract = FALSE; + isStatic = FALSE; + isTemplArg = FALSE; + membersMerged = FALSE; + categoryOf = 0; + usedOnly = FALSE; + isSimple = Config_getBool("INLINE_SIMPLE_STRUCTS"); + arrowOperator = 0; + taggedInnerClasses = 0; + tagLessRef = 0; + spec=0; + //QCString ns; + //extractNamespaceName(name,className,ns); + //printf("m_name=%s m_className=%s ns=%s\n",m_name.data(),m_className.data(),ns.data()); + + // we cannot use getLanguage at this point, as setLanguage has not been called. + SrcLangExt lang = getLanguageFromFileName(defFileName); + if ((lang==SrcLangExt_Cpp || lang==SrcLangExt_ObjC) && + guessSection(defFileName)==Entry::SOURCE_SEC) + { + isLocal=TRUE; + } + else + { + isLocal=FALSE; + } + isGeneric = lang==SrcLangExt_CSharp && QCString(name).find('<')!=-1; +} + +ClassDefImpl::ClassDefImpl() : vhdlSummaryTitles(17) +{ + vhdlSummaryTitles.setAutoDelete(TRUE); +} + +ClassDefImpl::~ClassDefImpl() +{ + delete inherits; + delete inheritedBy; + delete allMemberNameInfoSDict; + delete exampleSDict; + delete usesImplClassDict; + delete usedByImplClassDict; + delete usesIntfClassDict; + delete incInfo; + delete memberGroupSDict; + delete innerClasses; + delete templateInstances; + delete variableInstances; + delete templBaseClassNames; + delete tempArgs; + delete typeConstraints; + delete taggedInnerClasses; +} + +// constructs a new class definition +ClassDef::ClassDef( + const char *defFileName,int defLine, + const char *nm,CompoundType ct, + const char *lref,const char *fName, + bool isSymbol,bool isJavaEnum) + : Definition(defFileName,defLine,removeRedundantWhiteSpace(nm),0,0,isSymbol) +{ + visited=FALSE; + setReference(lref); + m_impl = new ClassDefImpl; + m_impl->compType = ct; + m_impl->isJavaEnum = isJavaEnum; + m_impl->init(defFileName,name(),compoundTypeString(),fName); +} + +// destroy the class definition +ClassDef::~ClassDef() +{ + delete m_impl; +} + +QCString ClassDef::getMemberListFileName() const +{ + return convertNameToFile(compoundTypeString()+name()+"-members"); +} + +QCString ClassDef::displayName(bool includeScope) const +{ + //static bool optimizeOutputForJava = Config_getBool("OPTIMIZE_OUTPUT_JAVA"); + SrcLangExt lang = getLanguage(); + //static bool vhdlOpt = Config_getBool("OPTIMIZE_OUTPUT_VHDL"); + QCString n; + if (lang==SrcLangExt_VHDL) + { + n = VhdlDocGen::getClassName(this); + } + else + { + if (includeScope) + { + n=qualifiedNameWithTemplateParameters(); + } + else + { + n=className(); + } + } + QCString sep=getLanguageSpecificSeparator(lang); + if (sep!="::") + { + n=substitute(n,"::",sep); + } + if (m_impl->compType==ClassDef::Protocol && n.right(2)=="-p") + { + n="<"+n.left(n.length()-2)+">"; + } + //else if (n.right(2)=="-g") + //{ + // n = n.left(n.length()-2); + //} + //printf("ClassDef::displayName()=%s\n",n.data()); + return n; +} + +// inserts a base/super class in the inheritance list +void ClassDef::insertBaseClass(ClassDef *cd,const char *n,Protection p, + Specifier s,const char *t) +{ + //printf("*** insert base class %s into %s\n",cd->name().data(),name().data()); + //inherits->inSort(new BaseClassDef(cd,p,s,t)); + if (m_impl->inherits==0) + { + m_impl->inherits = new BaseClassList; + m_impl->inherits->setAutoDelete(TRUE); + } + m_impl->inherits->append(new BaseClassDef(cd,n,p,s,t)); + m_impl->isSimple = FALSE; +} + +// inserts a derived/sub class in the inherited-by list +void ClassDef::insertSubClass(ClassDef *cd,Protection p, + Specifier s,const char *t) +{ + //printf("*** insert sub class %s into %s\n",cd->name().data(),name().data()); + if (m_impl->inheritedBy==0) + { + m_impl->inheritedBy = new BaseClassList; + m_impl->inheritedBy->setAutoDelete(TRUE); + } + m_impl->inheritedBy->inSort(new BaseClassDef(cd,0,p,s,t)); + m_impl->isSimple = FALSE; +} + +void ClassDef::addMembersToMemberGroup() +{ + QListIterator<MemberList> mli(m_impl->memberLists); + MemberList *ml; + for (mli.toFirst();(ml=mli.current());++mli) + { + if ((ml->listType()&MemberList::detailedLists)==0) + { + ::addMembersToMemberGroup(ml,&m_impl->memberGroupSDict,this); + } + } + + // add members inside sections to their groups + if (m_impl->memberGroupSDict) + { + MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict); + MemberGroup *mg; + for (;(mg=mgli.current());++mgli) + { + if (mg->allMembersInSameSection() && m_impl->subGrouping) + { + //printf("addToDeclarationSection(%s)\n",mg->header().data()); + mg->addToDeclarationSection(); + } + } + } +} + +// adds new member definition to the class +void ClassDef::internalInsertMember(MemberDef *md, + Protection prot, + bool addToAllList + ) +{ + //printf("insertInternalMember(%s) isHidden()=%d\n",md->name().data(),md->isHidden()); + if (md->isHidden()) return; + + if (getLanguage()==SrcLangExt_VHDL) + { + QCString title=VhdlDocGen::trVhdlType(md->getMemberSpecifiers(),FALSE); + if (!m_impl->vhdlSummaryTitles.find(title)) + { + m_impl->vhdlSummaryTitles.append(title,new QCString(title)); + } + } + + if (1 /*!isReference()*/) // changed to 1 for showing members of external + // classes when HAVE_DOT and UML_LOOK are enabled. + { + bool isSimple=FALSE; + + /********************************************/ + /* insert member in the declaration section */ + /********************************************/ + if (md->isRelated() && protectionLevelVisible(prot)) + { + addMemberToList(MemberList::related,md,TRUE); + } + else if (md->isFriend()) + { + addMemberToList(MemberList::friends,md,TRUE); + } + else + { + switch (md->memberType()) + { + case MemberDef::Signal: // Qt specific + addMemberToList(MemberList::signals,md,TRUE); + break; + case MemberDef::DCOP: // KDE2 specific + addMemberToList(MemberList::dcopMethods,md,TRUE); + break; + case MemberDef::Property: + addMemberToList(MemberList::properties,md,TRUE); + break; + case MemberDef::Event: + addMemberToList(MemberList::events,md,TRUE); + break; + case MemberDef::Slot: // Qt specific + switch (prot) + { + case Protected: + case Package: // slots in packages are not possible! + addMemberToList(MemberList::proSlots,md,TRUE); + break; + case Public: + addMemberToList(MemberList::pubSlots,md,TRUE); + break; + case Private: + addMemberToList(MemberList::priSlots,md,TRUE); + break; + } + break; + default: // any of the other members + if (md->isStatic()) + { + if (md->isVariable()) + { + switch (prot) + { + case Protected: + addMemberToList(MemberList::proStaticAttribs,md,TRUE); + break; + case Package: + addMemberToList(MemberList::pacStaticAttribs,md,TRUE); + break; + case Public: + addMemberToList(MemberList::pubStaticAttribs,md,TRUE); + break; + case Private: + addMemberToList(MemberList::priStaticAttribs,md,TRUE); + break; + } + } + else // function + { + switch (prot) + { + case Protected: + addMemberToList(MemberList::proStaticMethods,md,TRUE); + break; + case Package: + addMemberToList(MemberList::pacStaticMethods,md,TRUE); + break; + case Public: + addMemberToList(MemberList::pubStaticMethods,md,TRUE); + break; + case Private: + addMemberToList(MemberList::priStaticMethods,md,TRUE); + break; + } + } + } + else // not static + { + if (md->isVariable()) + { + switch (prot) + { + case Protected: + addMemberToList(MemberList::proAttribs,md,TRUE); + break; + case Package: + addMemberToList(MemberList::pacAttribs,md,TRUE); + break; + case Public: + addMemberToList(MemberList::pubAttribs,md,TRUE); + isSimple=!md->isFunctionPtr(); + break; + case Private: + addMemberToList(MemberList::priAttribs,md,TRUE); + break; + } + } + else if (md->isTypedef() || md->isEnumerate() || md->isEnumValue()) + { + switch (prot) + { + case Protected: + addMemberToList(MemberList::proTypes,md,TRUE); + break; + case Package: + addMemberToList(MemberList::pacTypes,md,TRUE); + break; + case Public: + addMemberToList(MemberList::pubTypes,md,TRUE); + break; + case Private: + addMemberToList(MemberList::priTypes,md,TRUE); + break; + } + } + else // member function + { + switch (prot) + { + case Protected: + addMemberToList(MemberList::proMethods,md,TRUE); + break; + case Package: + addMemberToList(MemberList::pacMethods,md,TRUE); + break; + case Public: + addMemberToList(MemberList::pubMethods,md,TRUE); + break; + case Private: + addMemberToList(MemberList::priMethods,md,TRUE); + break; + } + } + } + break; + } + } + if (!isSimple) // not a simple field -> not a simple struct + { + m_impl->isSimple = FALSE; + } + //printf("adding %s simple=%d total_simple=%d\n",name().data(),isSimple,m_impl->isSimple); + + /*******************************************************/ + /* insert member in the detailed documentation section */ + /*******************************************************/ + if ((md->isRelated() && protectionLevelVisible(prot)) || md->isFriend()) + { + addMemberToList(MemberList::relatedMembers,md,FALSE); + } + else + { + switch (md->memberType()) + { + case MemberDef::Property: + addMemberToList(MemberList::propertyMembers,md,FALSE); + break; + case MemberDef::Event: + addMemberToList(MemberList::eventMembers,md,FALSE); + break; + case MemberDef::Signal: // fall through + case MemberDef::DCOP: + addMemberToList(MemberList::functionMembers,md,FALSE); + break; + case MemberDef::Slot: + if (protectionLevelVisible(prot)) + { + addMemberToList(MemberList::functionMembers,md,FALSE); + } + break; + default: // any of the other members + if (protectionLevelVisible(prot)) + { + switch (md->memberType()) + { + case MemberDef::Typedef: + addMemberToList(MemberList::typedefMembers,md,FALSE); + break; + case MemberDef::Enumeration: + addMemberToList(MemberList::enumMembers,md,FALSE); + break; + case MemberDef::EnumValue: + addMemberToList(MemberList::enumValMembers,md,FALSE); + break; + case MemberDef::Function: + if (md->isConstructor() || md->isDestructor()) + { + MemberList *ml = createMemberList(MemberList::constructors); + ml->append(md); + } + else + { + addMemberToList(MemberList::functionMembers,md,FALSE); + } + break; + case MemberDef::Variable: + addMemberToList(MemberList::variableMembers,md,FALSE); + break; + default: + err("Unexpected member type %d found!\n",md->memberType()); + } + } + break; + } + } + + /*************************************************/ + /* insert member in the appropriate member group */ + /*************************************************/ + // Note: this must be done AFTER inserting the member in the + // regular groups + //addMemberToGroup(md,groupId); + + } + + if (md->virtualness()==Pure) + { + m_impl->isAbstract=TRUE; + } + + if (md->name()=="operator->") + { + m_impl->arrowOperator=md; + } + + //::addClassMemberNameToIndex(md); + if (addToAllList && + !(Config_getBool("HIDE_FRIEND_COMPOUNDS") && + md->isFriend() && + (QCString(md->typeString())=="friend class" || + QCString(md->typeString())=="friend struct" || + QCString(md->typeString())=="friend union"))) + { + //printf("=======> adding member %s to class %s\n",md->name().data(),name().data()); + MemberInfo *mi = new MemberInfo((MemberDef *)md, + prot,md->virtualness(),FALSE); + MemberNameInfo *mni=0; + if (m_impl->allMemberNameInfoSDict==0) + { + m_impl->allMemberNameInfoSDict = new MemberNameInfoSDict(17); + m_impl->allMemberNameInfoSDict->setAutoDelete(TRUE); + } + if ((mni=m_impl->allMemberNameInfoSDict->find(md->name()))) + { + mni->append(mi); + } + else + { + mni = new MemberNameInfo(md->name()); + mni->append(mi); + m_impl->allMemberNameInfoSDict->append(mni->memberName(),mni); + } + } +} + +void ClassDef::insertMember(MemberDef *md) +{ + internalInsertMember(md,md->protection(),TRUE); +} + +// compute the anchors for all members +void ClassDef::computeAnchors() +{ + ClassDef *context = Config_getBool("INLINE_INHERITED_MEMB") ? this : 0; + const char *letters = "abcdefghijklmnopqrstuvwxyz0123456789"; + QListIterator<MemberList> mli(m_impl->memberLists); + MemberList *ml; + int index = 0; + for (mli.toFirst();(ml=mli.current());++mli) + { + if ((ml->listType()&MemberList::detailedLists)==0) + { + setAnchors(context,letters[index++],ml); + } + } + + if (m_impl->memberGroupSDict) + { + MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict); + MemberGroup *mg; + for (;(mg=mgli.current());++mgli) + { + mg->setAnchors(context); + } + } +} + +void ClassDef::distributeMemberGroupDocumentation() +{ + if (m_impl->memberGroupSDict) + { + MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict); + MemberGroup *mg; + for (;(mg=mgli.current());++mgli) + { + mg->distributeMemberGroupDocumentation(); + } + } +} + +void ClassDef::findSectionsInDocumentation() +{ + docFindSections(documentation(),this,0,docFile()); + if (m_impl->memberGroupSDict) + { + MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict); + MemberGroup *mg; + for (;(mg=mgli.current());++mgli) + { + mg->findSectionsInDocumentation(); + } + } + QListIterator<MemberList> mli(m_impl->memberLists); + MemberList *ml; + for (mli.toFirst();(ml=mli.current());++mli) + { + if ((ml->listType()&MemberList::detailedLists)==0) + { + ml->findSectionsInDocumentation(); + } + } +} + + +// add a file name to the used files set +void ClassDef::insertUsedFile(const char *f) +{ + if (m_impl->files.find(f)==-1) m_impl->files.append(f); + if (m_impl->templateInstances) + { + QDictIterator<ClassDef> qdi(*m_impl->templateInstances); + ClassDef *cd; + for (qdi.toFirst();(cd=qdi.current());++qdi) + { + cd->insertUsedFile(f); + } + } +} + +static void writeInheritanceSpecifier(OutputList &ol,BaseClassDef *bcd) +{ + if (bcd->prot!=Public || bcd->virt!=Normal) + { + ol.startTypewriter(); + ol.docify(" ["); + QStrList sl; + if (bcd->prot==Protected) sl.append("protected"); + else if (bcd->prot==Private) sl.append("private"); + if (bcd->virt==Virtual) sl.append("virtual"); + const char *s=sl.first(); + while (s) + { + ol.docify(s); + s=sl.next(); + if (s) ol.docify(", "); + } + ol.docify("]"); + ol.endTypewriter(); + } +} + +void ClassDef::setIncludeFile(FileDef *fd, + const char *includeName,bool local, bool force) +{ + //printf("ClassDef::setIncludeFile(%p,%s,%d,%d)\n",fd,includeName,local,force); + if (!m_impl->incInfo) m_impl->incInfo=new IncludeInfo; + if ((includeName && m_impl->incInfo->includeName.isEmpty()) || + (fd!=0 && m_impl->incInfo->fileDef==0) + ) + { + //printf("Setting file info\n"); + m_impl->incInfo->fileDef = fd; + m_impl->incInfo->includeName = includeName; + m_impl->incInfo->local = local; + } + if (force && includeName) + { + m_impl->incInfo->includeName = includeName; + m_impl->incInfo->local = local; + } +} + +// TODO: fix this: a nested template class can have multiple outer templates +//ArgumentList *ClassDef::outerTemplateArguments() const +//{ +// int ti; +// ClassDef *pcd=0; +// int pi=0; +// if (m_impl->tempArgs) return m_impl->tempArgs; +// // find the outer most class scope +// while ((ti=name().find("::",pi))!=-1 && +// (pcd=getClass(name().left(ti)))==0 +// ) pi=ti+2; +// if (pcd) +// { +// return pcd->templateArguments(); +// } +// return 0; +//} + +static void searchTemplateSpecs(/*in*/ Definition *d, + /*out*/ QList<ArgumentList> &result, + /*out*/ QCString &name) +{ + if (d->definitionType()==Definition::TypeClass) + { + if (d->getOuterScope()) + { + searchTemplateSpecs(d->getOuterScope(),result,name); + } + ClassDef *cd=(ClassDef *)d; + if (!name.isEmpty()) name+="::"; + QCString clName = d->localName(); + if (/*clName.right(2)=="-g" ||*/ clName.right(2)=="-p") + { + clName = clName.left(clName.length()-2); + } + name+=clName; + bool isSpecialization = d->localName().find('<')!=-1; + if (cd->templateArguments()) + { + result.append(cd->templateArguments()); + if (!isSpecialization) + { + name+=tempArgListToString(cd->templateArguments()); + } + } + } + else + { + name+=d->qualifiedName(); + } +} + +static void writeTemplateSpec(OutputList &ol,Definition *d, + const QCString &type) +{ + QList<ArgumentList> specs; + QCString name; + searchTemplateSpecs(d,specs,name); + if (specs.count()>0) // class has template scope specifiers + { + ol.startSubsubsection(); + QListIterator<ArgumentList> spi(specs); + ArgumentList *al; + for (spi.toFirst();(al=spi.current());++spi) + { + ol.docify("template<"); + Argument *a=al->first(); + while (a) + { + ol.docify(a->type); + if (!a->name.isEmpty()) + { + ol.docify(" "); + ol.docify(a->name); + } + if (a->defval.length()!=0) + { + ol.docify(" = "); + ol.docify(a->defval); + } + a=al->next(); + if (a) ol.docify(", "); + } + ol.docify(">"); + ol.pushGeneratorState(); + ol.disableAllBut(OutputGenerator::Html); + ol.lineBreak(); + ol.popGeneratorState(); + } + ol.docify(type.lower()+" "+name); + ol.endSubsubsection(); + ol.writeString("\n"); + } +} + +void ClassDef::writeBriefDescription(OutputList &ol,bool exampleFlag) +{ + if (!briefDescription().isEmpty() && Config_getBool("BRIEF_MEMBER_DESC")) + { + ol.startParagraph(); + ol.parseDoc(briefFile(),briefLine(),this,0, + briefDescription(),TRUE,FALSE,0,TRUE,FALSE); + ol.pushGeneratorState(); + ol.disable(OutputGenerator::RTF); + ol.writeString(" \n"); + ol.enable(OutputGenerator::RTF); + ol.popGeneratorState(); + + if (Config_getBool("REPEAT_BRIEF") || + !documentation().isEmpty() || + exampleFlag + ) + { + writeMoreLink(ol,anchor()); + } + + ol.endParagraph(); + } + ol.writeSynopsis(); +} + +void ClassDef::writeDetailedDocumentationBody(OutputList &ol) +{ + static bool repeatBrief = Config_getBool("REPEAT_BRIEF"); + + ol.startTextBlock(); + + if (getLanguage()==SrcLangExt_Cpp) + { + writeTemplateSpec(ol,this,compoundTypeString()); + } + + // repeat brief description + if (!briefDescription().isEmpty() && repeatBrief) + { + ol.parseDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE); + } + if (!briefDescription().isEmpty() && repeatBrief && + !documentation().isEmpty()) + { + ol.pushGeneratorState(); + ol.disable(OutputGenerator::Html); + ol.writeString("\n\n"); + ol.popGeneratorState(); + } + // write documentation + if (!documentation().isEmpty()) + { + ol.parseDoc(docFile(),docLine(),this,0,documentation(),TRUE,FALSE); + } + // write type constraints + writeTypeConstraints(ol,this,m_impl->typeConstraints); + + // write examples + if (hasExamples() && m_impl->exampleSDict) + { + ol.startSimpleSect(BaseOutputDocInterface::Examples,0,0,theTranslator->trExamples()+": "); + ol.startDescForItem(); + //ol.startParagraph(); + writeExample(ol,m_impl->exampleSDict); + //ol.endParagraph(); + ol.endDescForItem(); + ol.endSimpleSect(); + } + //ol.newParagraph(); + writeSourceDef(ol,name()); + ol.endTextBlock(); +} + +// write the detailed description for this class +void ClassDef::writeDetailedDescription(OutputList &ol, const QCString &/*pageType*/, bool exampleFlag, + const QCString &title,const QCString &anchor) +{ + if ((!briefDescription().isEmpty() && Config_getBool("REPEAT_BRIEF")) || + !documentation().isEmpty() || + (Config_getBool("SOURCE_BROWSER") && getStartBodyLine()!=-1 && getBodyDef()) || + exampleFlag) + { + ol.pushGeneratorState(); + ol.disable(OutputGenerator::Html); + ol.writeRuler(); + ol.popGeneratorState(); + + ol.pushGeneratorState(); + ol.disableAllBut(OutputGenerator::Html); + ol.writeAnchor(0,anchor.isEmpty() ? QCString("details") : anchor); + ol.popGeneratorState(); + + if (!anchor.isEmpty()) + { + ol.pushGeneratorState(); + ol.disable(OutputGenerator::Html); + ol.disable(OutputGenerator::Man); + ol.writeAnchor(getOutputFileBase(),anchor); + ol.popGeneratorState(); + } + + ol.startGroupHeader(); + ol.parseText(title); + ol.endGroupHeader(); + + writeDetailedDocumentationBody(ol); + } + else + { + //writeTemplateSpec(ol,this,pageType); + } +} + +void ClassDef::showUsedFiles(OutputList &ol) +{ + ol.pushGeneratorState(); + ol.disable(OutputGenerator::Man); + + SrcLangExt lang = getLanguage(); + ol.writeRuler(); + if (lang==SrcLangExt_Fortran) + { + ol.parseText(theTranslator->trGeneratedFromFilesFortran( + getLanguage()==SrcLangExt_ObjC && m_impl->compType==Interface ? Class : m_impl->compType, + m_impl->files.count()==1)); + } + else if (isJavaEnum()) + { + ol.parseText(theTranslator->trEnumGeneratedFromFiles(m_impl->files.count()==1)); + } + else + { + ol.parseText(theTranslator->trGeneratedFromFiles( + getLanguage()==SrcLangExt_ObjC && m_impl->compType==Interface ? Class : m_impl->compType, + m_impl->files.count()==1)); + } + + bool first=TRUE; + const char *file = m_impl->files.first(); + while (file) + { + bool ambig; + FileDef *fd=findFileDef(Doxygen::inputNameDict,file,ambig); + if (fd) + { + if (first) + { + first=FALSE; + ol.startItemList(); + } + + ol.startItemListItem(); + QCString path=fd->getPath(); + if (Config_getBool("FULL_PATH_NAMES")) + { + ol.docify(stripFromPath(path)); + } + + QCString fname = fd->name(); + if (!fd->getVersion().isEmpty()) // append version if available + { + fname += " (" + fd->getVersion() + ")"; + } + + // for HTML + ol.pushGeneratorState(); + ol.disableAllBut(OutputGenerator::Html); + if (fd->generateSourceFile()) + { + ol.writeObjectLink(0,fd->getSourceFileBase(),0,fname); + } + else if (fd->isLinkable()) + { + ol.writeObjectLink(fd->getReference(),fd->getOutputFileBase(),0, + fname); + } + else + { + ol.docify(fname); + } + ol.popGeneratorState(); + + // for other output formats + ol.pushGeneratorState(); + ol.disable(OutputGenerator::Html); + if (fd->isLinkable()) + { + ol.writeObjectLink(fd->getReference(),fd->getOutputFileBase(),0, + fname); + } + else + { + ol.docify(fname); + } + ol.popGeneratorState(); + + ol.endItemListItem(); + } + file=m_impl->files.next(); + } + if (!first) ol.endItemList(); + + ol.popGeneratorState(); +} + + +void ClassDef::writeInheritanceGraph(OutputList &ol) +{ + // count direct inheritance relations + int count=0; + BaseClassDef *ibcd; + if (m_impl->inheritedBy) + { + ibcd=m_impl->inheritedBy->first(); + while (ibcd) + { + ClassDef *icd=ibcd->classDef; + if ( icd->isVisibleInHierarchy()) count++; + ibcd=m_impl->inheritedBy->next(); + } + } + if (m_impl->inherits) + { + ibcd=m_impl->inherits->first(); + while (ibcd) + { + ClassDef *icd=ibcd->classDef; + if ( icd->isVisibleInHierarchy()) count++; + ibcd=m_impl->inherits->next(); + } + } + + + bool renderDiagram = FALSE; + if (Config_getBool("HAVE_DOT") && + (Config_getBool("CLASS_DIAGRAMS") || Config_getBool("CLASS_GRAPH"))) + // write class diagram using dot + { + DotClassGraph inheritanceGraph(this,DotNode::Inheritance); + if (!inheritanceGraph.isTrivial() && !inheritanceGraph.isTooBig()) + { + ol.pushGeneratorState(); + ol.disable(OutputGenerator::Man); + ol.startDotGraph(); + ol.parseText(theTranslator->trClassDiagram(displayName())); + ol.endDotGraph(inheritanceGraph); + ol.popGeneratorState(); + renderDiagram = TRUE; + } + } + else if (Config_getBool("CLASS_DIAGRAMS") && count>0) + // write class diagram using build-in generator + { + ClassDiagram diagram(this); // create a diagram of this class. + ol.startClassDiagram(); + ol.disable(OutputGenerator::Man); + ol.parseText(theTranslator->trClassDiagram(displayName())); + ol.enable(OutputGenerator::Man); + ol.endClassDiagram(diagram,getOutputFileBase(),displayName()); + renderDiagram = TRUE; + } + + if (renderDiagram) // if we already show the inheritance relations graphically, + // then hide the text version + { + ol.disableAllBut(OutputGenerator::Man); + } + + if (m_impl->inherits && (count=m_impl->inherits->count())>0) + { + ol.startParagraph(); + //parseText(ol,theTranslator->trInherits()+" "); + + QCString inheritLine = theTranslator->trInheritsList(m_impl->inherits->count()); + QRegExp marker("@[0-9]+"); + int index=0,newIndex,matchLen; + // now replace all markers in inheritLine with links to the classes + while ((newIndex=marker.match(inheritLine,index,&matchLen))!=-1) + { + ol.parseText(inheritLine.mid(index,newIndex-index)); + bool ok; + uint entryIndex = inheritLine.mid(newIndex+1,matchLen-1).toUInt(&ok); + BaseClassDef *bcd=m_impl->inherits->at(entryIndex); + if (ok && bcd) + { + ClassDef *cd=bcd->classDef; + + // use the class name but with the template arguments as given + // in the inheritance relation + QCString displayName = insertTemplateSpecifierInScope( + cd->displayName(),bcd->templSpecifiers); + + if (cd->isLinkable()) + { + if (!Config_getString("GENERATE_TAGFILE").isEmpty()) + { + Doxygen::tagFile << " <base"; + if (bcd->prot==Protected) + { + Doxygen::tagFile << " protection=\"protected\""; + } + else if (bcd->prot==Private) + { + Doxygen::tagFile << " protection=\"private\""; + } + if (bcd->virt==Virtual) + { + Doxygen::tagFile << " virtualness=\"virtual\""; + } + Doxygen::tagFile << ">" << convertToXML(cd->name()) + << "</base>" << endl; + } + ol.writeObjectLink(cd->getReference(), + cd->getOutputFileBase(), + cd->anchor(), + displayName); + } + else + { + ol.docify(displayName); + } + } + else + { + err("error: invalid marker %d in inherits list!\n",entryIndex); + } + index=newIndex+matchLen; + } + ol.parseText(inheritLine.right(inheritLine.length()-index)); + ol.endParagraph(); + } + + // write subclasses + if (m_impl->inheritedBy && (count=m_impl->inheritedBy->count())>0) + { + ol.startParagraph(); + QCString inheritLine = theTranslator->trInheritedByList(m_impl->inheritedBy->count()); + QRegExp marker("@[0-9]+"); + int index=0,newIndex,matchLen; + // now replace all markers in inheritLine with links to the classes + while ((newIndex=marker.match(inheritLine,index,&matchLen))!=-1) + { + ol.parseText(inheritLine.mid(index,newIndex-index)); + bool ok; + uint entryIndex = inheritLine.mid(newIndex+1,matchLen-1).toUInt(&ok); + BaseClassDef *bcd=m_impl->inheritedBy->at(entryIndex); + if (ok && bcd) + { + ClassDef *cd=bcd->classDef; + if (cd->isLinkable()) + { + ol.writeObjectLink(cd->getReference(),cd->getOutputFileBase(),cd->anchor(),cd->displayName()); + } + else + { + ol.docify(cd->displayName()); + } + writeInheritanceSpecifier(ol,bcd); + } + index=newIndex+matchLen; + } + ol.parseText(inheritLine.right(inheritLine.length()-index)); + ol.endParagraph(); + } + + if (renderDiagram) + { + ol.enableAll(); + } +} + +void ClassDef::writeCollaborationGraph(OutputList &ol) +{ + if (Config_getBool("HAVE_DOT") /*&& Config_getBool("COLLABORATION_GRAPH")*/) + { + DotClassGraph usageImplGraph(this,DotNode::Collaboration); + if (!usageImplGraph.isTrivial()) + { + ol.pushGeneratorState(); + ol.disable(OutputGenerator::Man); + ol.startDotGraph(); + ol.parseText(theTranslator->trCollaborationDiagram(displayName())); + ol.endDotGraph(usageImplGraph); + ol.popGeneratorState(); + } + } +} + +void ClassDef::writeIncludeFiles(OutputList &ol) +{ + if (m_impl->incInfo /*&& Config_getBool("SHOW_INCLUDE_FILES")*/) + { + QCString nm=m_impl->incInfo->includeName.isEmpty() ? + (m_impl->incInfo->fileDef ? + m_impl->incInfo->fileDef->docName().data() : "" + ) : + m_impl->incInfo->includeName.data(); + if (!nm.isEmpty()) + { + ol.startParagraph(); + ol.startTypewriter(); + SrcLangExt lang = getLanguage(); + bool isIDLorJava = lang==SrcLangExt_IDL || lang==SrcLangExt_Java; + if (isIDLorJava) + { + ol.docify("import "); + } + else if (isObjectiveC()) + { + ol.docify("#import "); + } + else + { + ol.docify("#include "); + } + if (m_impl->incInfo->local || isIDLorJava) + ol.docify("\""); + else + ol.docify("<"); + ol.pushGeneratorState(); + ol.disable(OutputGenerator::Html); + ol.docify(nm); + ol.disableAllBut(OutputGenerator::Html); + ol.enable(OutputGenerator::Html); + if (m_impl->incInfo->fileDef) + { + ol.writeObjectLink(0,m_impl->incInfo->fileDef->includeName(),0,nm); + } + else + { + ol.docify(nm); + } + ol.popGeneratorState(); + if (m_impl->incInfo->local || isIDLorJava) + ol.docify("\""); + else + ol.docify(">"); + if (isIDLorJava) + ol.docify(";"); + ol.endTypewriter(); + ol.endParagraph(); + } + } +} + +#if 0 +void ClassDef::writeAllMembersLink(OutputList &ol) +{ + // write link to list of all members (HTML only) + if (m_impl->allMemberNameInfoSDict && + !Config_getBool("OPTIMIZE_OUTPUT_FOR_C") + ) + { + ol.pushGeneratorState(); + ol.disableAllBut(OutputGenerator::Html); + ol.startParagraph(); + ol.startTextLink(getMemberListFileName(),0); + ol.parseText(theTranslator->trListOfAllMembers()); + ol.endTextLink(); + ol.endParagraph(); + ol.enableAll(); + ol.popGeneratorState(); + } +} +#endif + +void ClassDef::writeMemberGroups(OutputList &ol,bool showInline) +{ + // write user defined member groups + if (m_impl->memberGroupSDict) + { + m_impl->memberGroupSDict->sort(); + MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict); + MemberGroup *mg; + for (;(mg=mgli.current());++mgli) + { + if (!mg->allMembersInSameSection() || !m_impl->subGrouping) // group is in its own section + { + mg->writeDeclarations(ol,this,0,0,0,showInline); + } + else // add this group to the corresponding member section + { + //printf("addToDeclarationSection(%s)\n",mg->header().data()); + //mg->addToDeclarationSection(); + } + } + } +} + +void ClassDef::writeNestedClasses(OutputList &ol,const QCString &title) +{ + // nested classes + if (m_impl->innerClasses) + { + m_impl->innerClasses->writeDeclaration(ol,0,title,TRUE); + } +} + +void ClassDef::writeInlineClasses(OutputList &ol) +{ + if (m_impl->innerClasses) + { + m_impl->innerClasses->writeDocumentation(ol,this); + } +} + +void ClassDef::startMemberDocumentation(OutputList &ol) +{ + //printf("%s: ClassDef::startMemberDocumentation()\n",name().data()); + if (Config_getBool("SEPARATE_MEMBER_PAGES")) + { + ol.disable(OutputGenerator::Html); + Doxygen::suppressDocWarnings = TRUE; + } +} + +void ClassDef::endMemberDocumentation(OutputList &ol) +{ + //printf("%s: ClassDef::endMemberDocumentation()\n",name().data()); + if (Config_getBool("SEPARATE_MEMBER_PAGES")) + { + ol.enable(OutputGenerator::Html); + Doxygen::suppressDocWarnings = FALSE; + } +} + +void ClassDef::startMemberDeclarations(OutputList &ol) +{ + //printf("%s: ClassDef::startMemberDeclarations()\n",name().data()); + ol.startMemberSections(); +} + +void ClassDef::endMemberDeclarations(OutputList &ol) +{ + //printf("%s: ClassDef::endMemberDeclarations()\n",name().data()); + static bool inlineInheritedMembers = Config_getBool("INLINE_INHERITED_MEMB"); + if (!inlineInheritedMembers && countAdditionalInheritedMembers()>0) + { + ol.startMemberHeader("inherited"); + ol.parseText(theTranslator->trAdditionalInheritedMembers()); + ol.endMemberHeader(); + writeAdditionalInheritedMembers(ol); + } + ol.endMemberSections(); +} + +void ClassDef::writeAuthorSection(OutputList &ol) +{ + ol.pushGeneratorState(); + ol.disableAllBut(OutputGenerator::Man); + ol.writeString("\n"); + ol.startGroupHeader(); + ol.parseText(theTranslator->trAuthor(TRUE,TRUE)); + ol.endGroupHeader(); + ol.parseText(theTranslator->trGeneratedAutomatically(Config_getString("PROJECT_NAME"))); + ol.popGeneratorState(); +} + + +void ClassDef::writeSummaryLinks(OutputList &ol) +{ + ol.pushGeneratorState(); + ol.disableAllBut(OutputGenerator::Html); + QListIterator<LayoutDocEntry> eli( + LayoutDocManager::instance().docEntries(LayoutDocManager::Class)); + LayoutDocEntry *lde; + bool first=TRUE; + SrcLangExt lang = getLanguage(); + + if (lang!=SrcLangExt_VHDL) + { + for (eli.toFirst();(lde=eli.current());++eli) + { + if (lde->kind()==LayoutDocEntry::ClassNestedClasses && + m_impl->innerClasses && + m_impl->innerClasses->declVisible() + ) + { + LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; + ol.writeSummaryLink(0,"nested-classes",ls->title(lang),first); + first=FALSE; + } + else if (lde->kind()==LayoutDocEntry::ClassAllMembersLink && + m_impl->allMemberNameInfoSDict && + !Config_getBool("OPTIMIZE_OUTPUT_FOR_C") + ) + { + ol.writeSummaryLink(getMemberListFileName(),"all-members-list",theTranslator->trListOfAllMembers(),first); + first=FALSE; + } + else if (lde->kind()== LayoutDocEntry::MemberDecl) + { + LayoutDocEntryMemberDecl *lmd = (LayoutDocEntryMemberDecl*)lde; + MemberList * ml = getMemberList(lmd->type); + if (ml && ml->declVisible()) + { + ol.writeSummaryLink(0,ml->listTypeAsString(),lmd->title(lang),first); + first=FALSE; + } + } + } + } + else // VDHL only + { + SDict<QCString>::Iterator li(m_impl->vhdlSummaryTitles); + for (li.toFirst();li.current();++li) + { + ol.writeSummaryLink(0,li.current()->data(),li.current()->data(),first); + } + } + if (!first) + { + ol.writeString(" </div>\n"); + } + ol.popGeneratorState(); +} + +void ClassDef::writeTagFileMarker() +{ + // write section to the tag file + if (!Config_getString("GENERATE_TAGFILE").isEmpty()) + { + Doxygen::tagFile << " <compound kind=\"" << compoundTypeString(); + Doxygen::tagFile << "\""; + if (isObjectiveC()) { Doxygen::tagFile << " objc=\"yes\""; } + Doxygen::tagFile << ">" << endl; + Doxygen::tagFile << " <name>" << convertToXML(name()) << "</name>" << endl; + Doxygen::tagFile << " <filename>" << convertToXML(getOutputFileBase()) << Doxygen::htmlFileExtension << "</filename>" << endl; + if (!anchor().isEmpty()) + { + Doxygen::tagFile << " <anchor>" << convertToXML(anchor()) << "</anchor>" << endl; + } + if (m_impl->tempArgs) + { + ArgumentListIterator ali(*m_impl->tempArgs); + Argument *a; + for (;(a=ali.current());++ali) + { + Doxygen::tagFile << " <templarg>" << convertToXML(a->name) << "</templarg>" << endl; + } + } + } +} + +/** Write class documentation inside another container (i.e. a group) */ +void ClassDef::writeInlineDocumentation(OutputList &ol) +{ + bool isSimple = m_impl->isSimple; + + ol.addIndexItem(name(),0); + //printf("ClassDef::writeInlineDocumentation(%s)\n",name().data()); + QListIterator<LayoutDocEntry> eli( + LayoutDocManager::instance().docEntries(LayoutDocManager::Class)); + LayoutDocEntry *lde; + + // part 1: anchor and title + QCString s = compoundTypeString()+" "+name(); + + // part 1a + ol.pushGeneratorState(); + ol.disableAllBut(OutputGenerator::Html); + { // only HTML only + ol.writeAnchor(0,anchor()); + ol.startMemberDoc(0,0,0,0,FALSE); + ol.startMemberDocName(FALSE); + ol.parseText(s); + ol.endMemberDocName(); + ol.endMemberDoc(FALSE); + ol.writeString("</div>"); + ol.startIndent(); + } + ol.popGeneratorState(); + + // part 1b + ol.pushGeneratorState(); + ol.disable(OutputGenerator::Html); + ol.disable(OutputGenerator::Man); + { // for LaTeX/RTF only + ol.writeAnchor(getOutputFileBase(),anchor()); + } + ol.popGeneratorState(); + + // part 1c + ol.pushGeneratorState(); + ol.disable(OutputGenerator::Html); + { + // for LaTeX/RTF/Man + ol.startGroupHeader(1); + ol.parseText(s); + ol.endGroupHeader(1); + } + ol.popGeneratorState(); + + SrcLangExt lang=getLanguage(); + + // part 2: the header and detailed description + for (eli.toFirst();(lde=eli.current());++eli) + { + switch (lde->kind()) + { + case LayoutDocEntry::BriefDesc: + { + // since we already shown the brief description in the + // declaration part of the container, so we use this to + // show the details on top. + writeDetailedDocumentationBody(ol); + } + break; + case LayoutDocEntry::ClassInheritanceGraph: + writeInheritanceGraph(ol); + break; + case LayoutDocEntry::ClassCollaborationGraph: + writeCollaborationGraph(ol); + break; + case LayoutDocEntry::MemberDeclStart: + if (!isSimple) startMemberDeclarations(ol); + break; + case LayoutDocEntry::MemberDecl: + { + LayoutDocEntryMemberDecl *lmd = (LayoutDocEntryMemberDecl*)lde; + if (!isSimple) writeMemberDeclarations(ol,lmd->type,lmd->title(lang),lmd->subtitle(lang),TRUE); + } + break; + case LayoutDocEntry::MemberGroups: + if (!isSimple) writeMemberGroups(ol,TRUE); + break; + case LayoutDocEntry::MemberDeclEnd: + if (!isSimple) endMemberDeclarations(ol); + break; + case LayoutDocEntry::MemberDefStart: + if (!isSimple) startMemberDocumentation(ol); + break; + case LayoutDocEntry::MemberDef: + { + LayoutDocEntryMemberDef *lmd = (LayoutDocEntryMemberDef*)lde; + if (isSimple) + { + writeSimpleMemberDocumentation(ol,lmd->type); + } + else + { + writeMemberDocumentation(ol,lmd->type,lmd->title(lang),TRUE); + } + } + break; + case LayoutDocEntry::MemberDefEnd: + if (!isSimple) endMemberDocumentation(ol); + break; + default: + break; + } + } + + // part 3: close the block + ol.pushGeneratorState(); + ol.disableAllBut(OutputGenerator::Html); + { // HTML only + ol.endIndent(); + } + ol.popGeneratorState(); + + // part 4: write tag file information + writeTagFileMarker(); +} + +void ClassDef::writeMoreLink(OutputList &ol,const QCString &anchor) +{ + // TODO: clean up this mess by moving it to + // the output generators... + static bool pdfHyperlinks = Config_getBool("PDF_HYPERLINKS"); + static bool rtfHyperlinks = Config_getBool("RTF_HYPERLINKS"); + static bool usePDFLatex = Config_getBool("USE_PDFLATEX"); + + // HTML only + ol.pushGeneratorState(); + ol.disableAllBut(OutputGenerator::Html); + ol.docify(" "); + ol.startTextLink(getOutputFileBase(), + anchor.isEmpty() ? QCString("details") : anchor); + ol.parseText(theTranslator->trMore()); + ol.endTextLink(); + ol.popGeneratorState(); + + if (!anchor.isEmpty()) + { + ol.pushGeneratorState(); + // LaTeX + RTF + ol.disable(OutputGenerator::Html); + ol.disable(OutputGenerator::Man); + if (!(usePDFLatex && pdfHyperlinks)) + { + ol.disable(OutputGenerator::Latex); + } + if (!rtfHyperlinks) + { + ol.disable(OutputGenerator::RTF); + } + ol.docify(" "); + ol.startTextLink(getOutputFileBase(), anchor); + ol.parseText(theTranslator->trMore()); + ol.endTextLink(); + // RTF only + ol.disable(OutputGenerator::Latex); + ol.writeString("\\par"); + ol.popGeneratorState(); + } +} + + +void ClassDef::writeDeclarationLink(OutputList &ol,bool &found,const char *header,bool localNames) +{ + //static bool fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN"); + //static bool vhdlOpt = Config_getBool("OPTIMIZE_OUTPUT_VHDL"); + static bool hideUndocClasses = Config_getBool("HIDE_UNDOC_CLASSES"); + static bool extractLocalClasses = Config_getBool("EXTRACT_LOCAL_CLASSES"); + bool isLink = isLinkable(); + SrcLangExt lang = getLanguage(); + if (isLink || + (!hideUndocClasses && + (!isLocal() || extractLocalClasses) + ) + ) + { + if (!found) // first class + { + ol.startMemberHeader("nested-classes"); + if (header) + { + ol.parseText(header); + } + else if (lang==SrcLangExt_VHDL) + { + ol.parseText(VhdlDocGen::trVhdlType(VhdlDocGen::ARCHITECTURE,FALSE)); + } + else + { + ol.parseText(lang==SrcLangExt_Fortran ? + theTranslator->trDataTypes() : + theTranslator->trCompounds()); + } + ol.endMemberHeader(); + ol.startMemberList(); + found=TRUE; + } + if (!Config_getString("GENERATE_TAGFILE").isEmpty() && + !isReference()) // skip classes found in tag files + { + Doxygen::tagFile << " <class kind=\"" << compoundTypeString() + << "\">" << convertToXML(name()) << "</class>" << endl; + } + ol.startMemberDeclaration(); + ol.startMemberItem(anchor(),FALSE); + QCString ctype = compoundTypeString(); + QCString cname = displayName(!localNames); + + if (lang!=SrcLangExt_VHDL) // for VHDL we swap the name and the type + { + ol.writeString(ctype); + ol.writeString(" "); + ol.insertMemberAlign(); + } + if (isLink) + { + ol.writeObjectLink(getReference(), + getOutputFileBase(), + anchor(), + cname + ); + } + else + { + ol.startBold(); + ol.docify(cname); + ol.endBold(); + } + if (lang==SrcLangExt_VHDL) // now write the type + { + ol.writeString(" "); + ol.insertMemberAlign(); + ol.writeString(VhdlDocGen::getProtectionName((VhdlDocGen::VhdlClasses)protection())); + } + ol.endMemberItem(); + + // add the brief description if available + if (!briefDescription().isEmpty()) + { + ol.startMemberDescription(anchor()); + ol.parseDoc(briefFile(),briefLine(),this,0, + briefDescription(),FALSE,FALSE,0,TRUE,FALSE); + if (isLinkableInProject()) + { + writeMoreLink(ol,anchor()); + } + ol.endMemberDescription(); + } + ol.endMemberDeclaration(anchor(),0); + } +} + +void ClassDef::addClassAttributes(OutputList &ol) +{ + QStrList sl; + if (isFinal()) sl.append("final"); + if (isSealed()) sl.append("sealed"); + if (isAbstract()) sl.append("abstract"); + + ol.pushGeneratorState(); + ol.disableAllBut(OutputGenerator::Html); + if (sl.count()>0) + { + ol.startLabels(); + const char *s=sl.first(); + while (s) + { + const char *ns = sl.next(); + ol.writeLabel(s,ns==0); + s=ns; + } + ol.endLabels(); + } + ol.popGeneratorState(); +} + +void ClassDef::writeDocumentationContents(OutputList &ol,const QCString & /*pageTitle*/) +{ + ol.startContents(); + + QCString pageType = " "; + pageType += compoundTypeString(); + toupper(pageType.at(1)); + + writeTagFileMarker(); + + Doxygen::indexList.addIndexItem(this,0); + + if (Doxygen::searchIndex) + { + Doxygen::searchIndex->setCurrentDoc(this,anchor(),FALSE); + Doxygen::searchIndex->addWord(localName(),TRUE); + } + bool exampleFlag=hasExamples(); + + //---------------------------------------- start flexible part ------------------------------- + + SrcLangExt lang = getLanguage(); + + QListIterator<LayoutDocEntry> eli( + LayoutDocManager::instance().docEntries(LayoutDocManager::Class)); + LayoutDocEntry *lde; + for (eli.toFirst();(lde=eli.current());++eli) + { + switch (lde->kind()) + { + case LayoutDocEntry::BriefDesc: + writeBriefDescription(ol,exampleFlag); + break; + case LayoutDocEntry::ClassIncludes: + writeIncludeFiles(ol); + break; + case LayoutDocEntry::ClassInheritanceGraph: + writeInheritanceGraph(ol); + break; + case LayoutDocEntry::ClassCollaborationGraph: + writeCollaborationGraph(ol); + break; + case LayoutDocEntry::ClassAllMembersLink: + //writeAllMembersLink(ol); // this is now part of the summary links + break; + case LayoutDocEntry::MemberDeclStart: + startMemberDeclarations(ol); + break; + case LayoutDocEntry::MemberGroups: + writeMemberGroups(ol); + break; + case LayoutDocEntry::MemberDecl: + { + LayoutDocEntryMemberDecl *lmd = (LayoutDocEntryMemberDecl*)lde; + writeMemberDeclarations(ol,lmd->type,lmd->title(lang),lmd->subtitle(lang)); + } + break; + case LayoutDocEntry::ClassNestedClasses: + { + LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; + writeNestedClasses(ol,ls->title(lang)); + } + break; + case LayoutDocEntry::MemberDeclEnd: + endMemberDeclarations(ol); + break; + case LayoutDocEntry::DetailedDesc: + { + LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; + writeDetailedDescription(ol,pageType,exampleFlag,ls->title(lang)); + } + break; + case LayoutDocEntry::MemberDefStart: + startMemberDocumentation(ol); + break; + case LayoutDocEntry::ClassInlineClasses: + writeInlineClasses(ol); + break; + case LayoutDocEntry::MemberDef: + { + LayoutDocEntryMemberDef *lmd = (LayoutDocEntryMemberDef*)lde; + writeMemberDocumentation(ol,lmd->type,lmd->title(lang)); + } + break; + case LayoutDocEntry::MemberDefEnd: + endMemberDocumentation(ol); + break; + case LayoutDocEntry::ClassUsedFiles: + showUsedFiles(ol); + break; + case LayoutDocEntry::AuthorSection: + writeAuthorSection(ol); + break; + case LayoutDocEntry::NamespaceNestedNamespaces: + case LayoutDocEntry::NamespaceClasses: + case LayoutDocEntry::NamespaceInlineClasses: + case LayoutDocEntry::FileClasses: + case LayoutDocEntry::FileNamespaces: + case LayoutDocEntry::FileIncludes: + case LayoutDocEntry::FileIncludeGraph: + case LayoutDocEntry::FileIncludedByGraph: + case LayoutDocEntry::FileSourceLink: + case LayoutDocEntry::FileInlineClasses: + case LayoutDocEntry::GroupClasses: + case LayoutDocEntry::GroupInlineClasses: + case LayoutDocEntry::GroupNamespaces: + case LayoutDocEntry::GroupDirs: + case LayoutDocEntry::GroupNestedGroups: + case LayoutDocEntry::GroupFiles: + case LayoutDocEntry::GroupGraph: + case LayoutDocEntry::GroupPageDocs: + case LayoutDocEntry::DirSubDirs: + case LayoutDocEntry::DirFiles: + case LayoutDocEntry::DirGraph: + err("Internal inconsistency: member %d should not be part of " + "LayoutDocManager::Class entry list\n",lde->kind()); + break; + } + } + + if (!Config_getString("GENERATE_TAGFILE").isEmpty()) + { + writeDocAnchorsToTagFile(); + Doxygen::tagFile << " </compound>" << endl; + } + ol.endContents(); +} + +// write all documentation for this class +void ClassDef::writeDocumentation(OutputList &ol) +{ + static bool generateTreeView = Config_getBool("GENERATE_TREEVIEW"); + //static bool fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN"); + //static bool vhdlOpt = Config_getBool("OPTIMIZE_OUTPUT_VHDL"); + QCString pageTitle; + SrcLangExt lang = getLanguage(); + + if (lang==SrcLangExt_Fortran) + { + pageTitle = theTranslator->trCompoundReferenceFortran(displayName(), + m_impl->compType, + m_impl->tempArgs != 0); + } + else if (lang==SrcLangExt_VHDL) + { + pageTitle = VhdlDocGen::getClassTitle(this)+" Reference"; + } + else if (isJavaEnum()) + { + pageTitle = theTranslator->trEnumReference(displayName()); + } + else + { + pageTitle = theTranslator->trCompoundReference(displayName(), + m_impl->compType == Interface && getLanguage()==SrcLangExt_ObjC ? Class : m_impl->compType, + m_impl->tempArgs != 0); + } + + startFile(ol,getOutputFileBase(),name(),pageTitle,HLI_ClassVisible,!generateTreeView); + if (!generateTreeView) + { + if (getOuterScope()!=Doxygen::globalScope) + { + writeNavigationPath(ol); + } + ol.endQuickIndices(); + } + + startTitle(ol,getOutputFileBase(),this); + ol.parseText(pageTitle); + addClassAttributes(ol); + addGroupListToTitle(ol,this); + endTitle(ol,getOutputFileBase(),displayName()); + writeDocumentationContents(ol,pageTitle); + + endFileWithNavPath(this,ol); + + if (Config_getBool("SEPARATE_MEMBER_PAGES")) + { + writeMemberPages(ol); + } +} + +void ClassDef::writeMemberPages(OutputList &ol) +{ + /////////////////////////////////////////////////////////////////////////// + //// Member definitions on separate pages + /////////////////////////////////////////////////////////////////////////// + + ol.pushGeneratorState(); + ol.disableAllBut(OutputGenerator::Html); + + QListIterator<MemberList> mli(m_impl->memberLists); + MemberList *ml; + for (mli.toFirst();(ml=mli.current());++mli) + { + if (ml->listType()&MemberList::detailedLists) + { + ml->writeDocumentationPage(ol,displayName(),this); + } + } + + ol.popGeneratorState(); +} + +void ClassDef::writeQuickMemberLinks(OutputList &ol,MemberDef *currentMd) const +{ + static bool createSubDirs=Config_getBool("CREATE_SUBDIRS"); + + ol.writeString(" <div class=\"navtab\">\n"); + ol.writeString(" <table>\n"); + + if (m_impl->allMemberNameInfoSDict) + { + MemberNameInfoSDict::Iterator mnili(*m_impl->allMemberNameInfoSDict); + MemberNameInfo *mni; + for (;(mni=mnili.current());++mnili) + { + MemberNameInfoIterator mnii(*mni); + MemberInfo *mi; + for (mnii.toFirst();(mi=mnii.current());++mnii) + { + MemberDef *md=mi->memberDef; + if (md->getClassDef()==this && md->isLinkable()) + { + ol.writeString(" <tr><td class=\"navtab\">"); + if (md->isLinkableInProject()) + { + if (md==currentMd) // selected item => highlight + { + ol.writeString("<a class=\"qindexHL\" "); + } + else + { + ol.writeString("<a class=\"qindex\" "); + } + ol.writeString("href=\""); + if (createSubDirs) ol.writeString("../../"); + ol.writeString(md->getOutputFileBase()+Doxygen::htmlFileExtension+"#"+md->anchor()); + ol.writeString("\">"); + ol.writeString(convertToHtml(md->name())); + ol.writeString("</a>"); + } + ol.writeString("</td></tr>\n"); + } + } + } + } + + ol.writeString(" </table>\n"); + ol.writeString(" </div>\n"); +} + + + +void ClassDef::writeDocumentationForInnerClasses(OutputList &ol) +{ + // write inner classes after the parent, so the tag files contain + // the definition in proper order! + if (m_impl->innerClasses) + { + ClassSDict::Iterator cli(*m_impl->innerClasses); + ClassDef *innerCd; + for (cli.toFirst();(innerCd=cli.current());++cli) + { + if (innerCd->isLinkableInProject() && innerCd->templateMaster()==0 && + protectionLevelVisible(innerCd->protection()) && + !innerCd->isEmbeddedInOuterScope() + ) + { + msg("Generating docs for nested compound %s...\n",qPrint(innerCd->name())); + innerCd->writeDocumentation(ol); + innerCd->writeMemberList(ol); + } + innerCd->writeDocumentationForInnerClasses(ol); + } + } +} + +// write the list of all (inherited) members for this class +void ClassDef::writeMemberList(OutputList &ol) +{ + static bool cOpt = Config_getBool("OPTIMIZE_OUTPUT_FOR_C"); + //static bool vhdlOpt = Config_getBool("OPTIMIZE_OUTPUT_VHDL"); + static bool generateTreeView = Config_getBool("GENERATE_TREEVIEW"); + if (m_impl->allMemberNameInfoSDict==0 || cOpt) return; + // only for HTML + ol.pushGeneratorState(); + ol.disableAllBut(OutputGenerator::Html); + + QCString memListFile = getMemberListFileName(); + startFile(ol,memListFile,memListFile,theTranslator->trMemberList(), + HLI_ClassVisible,!generateTreeView,getOutputFileBase()); + if (!generateTreeView) + { + if (getOuterScope()!=Doxygen::globalScope) + { + writeNavigationPath(ol); + } + ol.endQuickIndices(); + } + startTitle(ol,0); + ol.parseText(displayName()+" "+theTranslator->trMemberList()); + endTitle(ol,0,0); + ol.startContents(); + ol.startParagraph(); + ol.parseText(theTranslator->trThisIsTheListOfAllMembers()); + ol.writeObjectLink(getReference(),getOutputFileBase(),anchor(),displayName()); + ol.parseText(theTranslator->trIncludingInheritedMembers()); + ol.endParagraph(); + + //ol.startItemList(); + ol.writeString("<table class=\"directory\">\n"); + + int idx=0; + //MemberNameInfo *mni=m_impl->allMemberNameInfoList->first(); + MemberNameInfoSDict::Iterator mnii(*m_impl->allMemberNameInfoSDict); + MemberNameInfo *mni; + for (mnii.toFirst();(mni=mnii.current());++mnii) + { + MemberInfo *mi=mni->first(); + while (mi) + { + MemberDef *md=mi->memberDef; + ClassDef *cd=md->getClassDef(); + Protection prot = mi->prot; + Specifier virt=md->virtualness(); + + //printf("%s: Member %s of class %s md->protection()=%d mi->prot=%d prot=%d inherited=%d\n", + // name().data(),md->name().data(),cd->name().data(),md->protection(),mi->prot,prot,mi->inherited); + + if (cd && !md->name().isEmpty() && md->name()[0]!='@') + { + bool memberWritten=FALSE; + if (cd->isLinkable() && md->isLinkable()) + // create a link to the documentation + { + QCString name=mi->ambiguityResolutionScope+md->name(); + //ol.writeListItem(); + ol.writeString(" <tr"); + if ((idx&1)==0) ol.writeString(" class=\"even\""); + idx++; + ol.writeString("><td class=\"entry\">"); + if (cd->isObjectiveC()) + { + if (md->isObjCMethod()) + { + if (md->isStatic()) + ol.writeString("+ </td><td>"); + else + ol.writeString("- </td><td>"); + } + else + ol.writeString("</td><td class=\"entry\">"); + } + if (md->isObjCMethod()) + { + ol.writeObjectLink(md->getReference(), + md->getOutputFileBase(), + md->anchor(),md->name()); + } + else + { + //Definition *bd = md->getGroupDef(); + //if (bd==0) bd=cd; + ol.writeObjectLink(md->getReference(), + md->getOutputFileBase(), + md->anchor(),name); + + if ( md->isFunction() || md->isSignal() || md->isSlot() || + (md->isFriend() && md->argsString())) + ol.docify(md->argsString()); + else if (md->isEnumerate()) + ol.parseText(" "+theTranslator->trEnumName()); + else if (md->isEnumValue()) + ol.parseText(" "+theTranslator->trEnumValue()); + else if (md->isTypedef()) + ol.docify(" typedef"); + else if (md->isFriend() && !strcmp(md->typeString(),"friend class")) + ol.docify(" class"); + //ol.writeString("\n"); + } + ol.writeString("</td>"); + memberWritten=TRUE; + } + else if (!Config_getBool("HIDE_UNDOC_MEMBERS") && + (protectionLevelVisible(md->protection()) || md->isFriend()) + ) // no documentation, + // generate link to the class instead. + { + //ol.writeListItem(); + ol.writeString(" <tr bgcolor=\"#f0f0f0\""); + if ((idx&1)==0) ol.writeString("class=\"even\""); + idx++; + ol.writeString("><td class=\"entry\">"); + if (cd->isObjectiveC()) + { + if (md->isObjCMethod()) + { + if (md->isStatic()) + ol.writeString("+ </td><td class=\"entry\">"); + else + ol.writeString("- </td><td class=\"entry\">"); + } + else + ol.writeString("</td><td class=\"entry\">"); + } + ol.startBold(); + ol.docify(md->name()); + ol.endBold(); + if (!md->isObjCMethod()) + { + if ( md->isFunction() || md->isSignal() || md->isSlot() ) + ol.docify(md->argsString()); + else if (md->isEnumerate()) + ol.parseText(" "+theTranslator->trEnumName()); + else if (md->isEnumValue()) + ol.parseText(" "+theTranslator->trEnumValue()); + else if (md->isTypedef()) + ol.docify(" typedef"); + } + ol.writeString(" ("); + ol.parseText(theTranslator->trDefinedIn()+" "); + if (cd->isLinkable()) + { + ol.writeObjectLink( + cd->getReference(), + cd->getOutputFileBase(), + cd->anchor(), + cd->displayName()); + } + else + { + ol.startBold(); + ol.docify(cd->displayName()); + ol.endBold(); + } + ol.writeString(")"); + ol.writeString("</td>"); + memberWritten=TRUE; + } + if (memberWritten) + { + ol.writeString("<td class=\"entry\">"); + ol.writeObjectLink(cd->getReference(), + cd->getOutputFileBase(), + cd->anchor(), + md->category() ? + md->category()->displayName() : + cd->displayName()); + ol.writeString("</td>"); + ol.writeString("<td class=\"entry\">"); + } + SrcLangExt lang = md->getLanguage(); + if ( + (prot!=Public || (virt!=Normal && getLanguage()!=SrcLangExt_ObjC) || + md->isFriend() || md->isRelated() || md->isExplicit() || + md->isMutable() || (md->isInline() && Config_getBool("INLINE_INFO")) || + md->isSignal() || md->isSlot() || + md->isStatic() || lang==SrcLangExt_VHDL + ) + && memberWritten) + { + ol.writeString("<span class=\"mlabel\">"); + QStrList sl; + if (lang==SrcLangExt_VHDL) + { + sl.append(VhdlDocGen::trVhdlType(md->getMemberSpecifiers())); //append vhdl type + } + else if (md->isFriend()) sl.append("friend"); + else if (md->isRelated()) sl.append("related"); + else + { + if (Config_getBool("INLINE_INFO") && md->isInline()) + sl.append("inline"); + if (md->isExplicit()) sl.append("explicit"); + if (md->isMutable()) sl.append("mutable"); + if (prot==Protected) sl.append("protected"); + else if (prot==Private) sl.append("private"); + else if (prot==Package) sl.append("package"); + if (virt==Virtual && getLanguage()!=SrcLangExt_ObjC) + sl.append("virtual"); + else if (virt==Pure) sl.append("pure virtual"); + if (md->isStatic()) sl.append("static"); + if (md->isSignal()) sl.append("signal"); + if (md->isSlot()) sl.append("slot"); + } + const char *s=sl.first(); + while (s) + { + ol.docify(s); + s=sl.next(); + if (s) ol.writeString("</span><span class=\"mlabel\">"); + } + ol.writeString("</span>"); + } + if (memberWritten) + { + ol.writeString("</td>"); + ol.writeString("</tr>\n"); + } + } + mi=mni->next(); + } + } + //ol.endItemList(); + + ol.writeString("</table>"); + + endFile(ol); + ol.popGeneratorState(); +} + + +// add a reference to an example +bool ClassDef::addExample(const char *anchor,const char *nameStr, + const char *file) +{ + if (m_impl->exampleSDict==0) + { + m_impl->exampleSDict = new ExampleSDict; + m_impl->exampleSDict->setAutoDelete(TRUE); + } + if (!m_impl->exampleSDict->find(nameStr)) + { + Example *e=new Example; + e->anchor=anchor; + e->name=nameStr; + e->file=file; + m_impl->exampleSDict->inSort(nameStr,e); + return TRUE; + } + return FALSE; +} + +// returns TRUE if this class is used in an example +bool ClassDef::hasExamples() +{ + if (m_impl->exampleSDict==0) + return FALSE; + else + return m_impl->exampleSDict->count()>0; +} + + +void ClassDef::setTemplateArguments(ArgumentList *al) +{ + if (al==0) return; + if (!m_impl->tempArgs) delete m_impl->tempArgs; // delete old list if needed + m_impl->tempArgs=new ArgumentList; + ArgumentListIterator ali(*al); + Argument *a; + for (;(a=ali.current());++ali) + { + m_impl->tempArgs->append(new Argument(*a)); + } +} + +void ClassDef::setTypeConstraints(ArgumentList *al) +{ + if (al==0) return; + if (!m_impl->typeConstraints) delete m_impl->typeConstraints; + m_impl->typeConstraints = new ArgumentList; + ArgumentListIterator ali(*al); + Argument *a; + for (;(a=ali.current());++ali) + { + m_impl->typeConstraints->append(new Argument(*a)); + } +} + +/*! Returns \c TRUE iff this class or a class inheriting from this class + * is \e not defined in an external tag file. + */ +bool ClassDef::hasNonReferenceSuperClass() +{ + bool found=!isReference() && isLinkableInProject() && !isHidden(); + if (found) + { + return TRUE; // we're done if this class is not a reference + } + if (m_impl->inheritedBy) + { + BaseClassListIterator bcli(*m_impl->inheritedBy); + for ( ; bcli.current() && !found ; ++bcli ) // for each super class + { + ClassDef *bcd=bcli.current()->classDef; + // recurse into the super class branch + found = found || bcd->hasNonReferenceSuperClass(); + if (!found) + { + // look for template instances that might have non-reference super classes + QDict<ClassDef> *cil = bcd->getTemplateInstances(); + if (cil) + { + QDictIterator<ClassDef> tidi(*cil); + for ( ; tidi.current() && !found ; ++tidi) // for each template instance + { + // recurse into the template instance branch + found = found || tidi.current()->hasNonReferenceSuperClass(); + } + } + } + } + } + return found; +} + +/*! called from MemberDef::writeDeclaration() to (recusively) write the + * definition of an anonymous struct, union or class. + */ +void ClassDef::writeDeclaration(OutputList &ol,MemberDef *md,bool inGroup, + ClassDef *inheritedFrom,const char *inheritId) +{ + //ol.insertMemberAlign(); + //printf("ClassName=`%s' inGroup=%d\n",name().data(),inGroup); + + //if (inGroup && md && md->getClassDef()==this) return; + + ol.docify(compoundTypeString()); + int ri=name().findRev("::"); + if (ri==-1) ri=name().length(); + QCString cn=name().right(name().length()-ri-2); + if (!cn.isEmpty() && cn.at(0)!='@' && md) + { + if (cn.right(2)=="-p" /*|| cn.right(2)=="-g"*/) + { + cn = cn.left(cn.length()-2); + } + ol.docify(" "); + if (isLinkable()) + { + ol.writeObjectLink(0,0,md->anchor(),cn); + } + else + { + ol.startBold(); + ol.docify(cn); + ol.endBold(); + } + } + ol.docify(" {"); + ol.endMemberItem(); + + // write user defined member groups + if (m_impl->memberGroupSDict) + { + MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict); + MemberGroup *mg; + for (;(mg=mgli.current());++mgli) + { + mg->setInGroup(inGroup); + mg->writePlainDeclarations(ol,this,0,0,0,inheritedFrom,inheritId); + } + } + + QListIterator<LayoutDocEntry> eli( + LayoutDocManager::instance().docEntries(LayoutDocManager::Class)); + LayoutDocEntry *lde; + for (eli.toFirst();(lde=eli.current());++eli) + { + if (lde->kind()==LayoutDocEntry::MemberDecl) + { + LayoutDocEntryMemberDecl *lmd = (LayoutDocEntryMemberDecl*)lde; + writePlainMemberDeclaration(ol,lmd->type,inGroup,inheritedFrom,inheritId); + } + } +} + +/*! a link to this class is possible within this project */ +bool ClassDef::isLinkableInProject() const +{ + static bool extractLocal = Config_getBool("EXTRACT_LOCAL_CLASSES"); + static bool extractStatic = Config_getBool("EXTRACT_STATIC"); + static bool hideUndoc = Config_getBool("HIDE_UNDOC_CLASSES"); + if (m_impl->templateMaster) + { + return m_impl->templateMaster->isLinkableInProject(); + } + else + { + return !name().isEmpty() && /* has a name */ + !isArtificial() && !isHidden() && /* not hidden */ + name().find('@')==-1 && /* not anonymous */ + protectionLevelVisible(m_impl->prot) && /* private/internal */ + (!m_impl->isLocal || extractLocal) && /* local */ + (hasDocumentation() || !hideUndoc) && /* documented */ + (!m_impl->isStatic || extractStatic) && /* static */ + !isReference(); /* not an external reference */ + } +} + +bool ClassDef::isLinkable() const +{ + if (m_impl->templateMaster) + { + return m_impl->templateMaster->isLinkable(); + } + else + { + return isLinkableInProject() || isReference(); + } +} + + +/*! the class is visible in a class diagram, or class hierarchy */ +bool ClassDef::isVisibleInHierarchy() +{ + static bool allExternals = Config_getBool("ALLEXTERNALS"); + static bool hideUndocClasses = Config_getBool("HIDE_UNDOC_CLASSES"); + static bool extractStatic = Config_getBool("EXTRACT_STATIC"); + + return // show all classes or a subclass is visible + (allExternals || hasNonReferenceSuperClass()) && + // and not an anonymous compound + name().find('@')==-1 && + // not an artificially introduced class + /*!isArtificial() &&*/ // 1.8.2: allowed these to appear + // and not privately inherited + protectionLevelVisible(m_impl->prot) && + // documented or shown anyway or documentation is external + (hasDocumentation() || + !hideUndocClasses || + (m_impl->templateMaster && m_impl->templateMaster->hasDocumentation()) || + isReference() + ) && + // is not part of an unnamed namespace or shown anyway + (!m_impl->isStatic || extractStatic); +} + +bool ClassDef::hasDocumentation() const +{ + return Definition::hasDocumentation(); +} + +//---------------------------------------------------------------------- +// recursive function: +// returns TRUE iff class definition `bcd' represents an (in)direct base +// class of class definition `cd'. + +bool ClassDef::isBaseClass(ClassDef *bcd, bool followInstances,int level) +{ + bool found=FALSE; + //printf("isBaseClass(cd=%s) looking for %s\n",name().data(),bcd->name().data()); + if (level>256) + { + err("Possible recursive class relation while inside %s and looking for %s\n",qPrint(name()),qPrint(bcd->name())); + abort(); + return FALSE; + } + if (baseClasses()) + { + // Beware: trying to optimise the iterator away using ->first() & ->next() + // causes bug 625531 + BaseClassListIterator bcli(*baseClasses()); + for ( ; bcli.current() && !found ; ++bcli) + { + ClassDef *ccd=bcli.current()->classDef; + if (!followInstances && ccd->templateMaster()) ccd=ccd->templateMaster(); + //printf("isBaseClass() baseclass %s\n",ccd->name().data()); + if (ccd==bcd) + found=TRUE; + else + found=ccd->isBaseClass(bcd,followInstances,level+1); + } + } + return found; +} + +//---------------------------------------------------------------------------- + +static bool isStandardFunc(MemberDef *md) +{ + return md->name()=="operator=" || // assignment operator + md->isConstructor() || // constructor + md->isDestructor(); // destructor +} + +/*! + * recusively merges the `all members' lists of a class base + * with that of this class. Must only be called for classes without + * subclasses! + */ +void ClassDef::mergeMembers() +{ + if (m_impl->membersMerged) return; + + //static bool optimizeOutputForJava = Config_getBool("OPTIMIZE_OUTPUT_JAVA"); + //static bool vhdlOpt = Config_getBool("OPTIMIZE_OUTPUT_VHDL"); + SrcLangExt lang = getLanguage(); + QCString sep=getLanguageSpecificSeparator(lang,TRUE); + int sepLen = sep.length(); + + m_impl->membersMerged=TRUE; + //printf(" mergeMembers for %s\n",name().data()); + bool inlineInheritedMembers = Config_getBool("INLINE_INHERITED_MEMB" ); + if (baseClasses()) + { + //printf(" => has base classes!\n"); + BaseClassListIterator bcli(*baseClasses()); + BaseClassDef *bcd; + for ( ; (bcd=bcli.current()) ; ++bcli ) + { + ClassDef *bClass=bcd->classDef; + + // merge the members in the base class of this inheritance branch first + bClass->mergeMembers(); + + MemberNameInfoSDict *srcMnd = bClass->memberNameInfoSDict(); + MemberNameInfoSDict *dstMnd = m_impl->allMemberNameInfoSDict; + + if (srcMnd) + { + MemberNameInfoSDict::Iterator srcMnili(*srcMnd); + MemberNameInfo *srcMni; + for ( ; (srcMni=srcMnili.current()) ; ++srcMnili) + { + //printf(" Base member name %s\n",srcMni->memberName()); + MemberNameInfo *dstMni; + if (dstMnd!=0 && (dstMni=dstMnd->find(srcMni->memberName()))) + // a member with that name is already in the class. + // the member may hide or reimplement the one in the sub class + // or there may be another path to the base class that is already + // visited via another branch in the class hierarchy. + { + MemberNameInfoIterator srcMnii(*srcMni); + MemberInfo *srcMi; + for ( ; (srcMi=srcMnii.current()) ; ++srcMnii ) + { + MemberDef *srcMd = srcMi->memberDef; + bool found=FALSE; + bool ambigue=FALSE; + bool hidden=FALSE; + MemberNameInfoIterator dstMnii(*dstMni); + MemberInfo *dstMi; + ClassDef *srcCd = srcMd->getClassDef(); + for ( ; (dstMi=dstMnii.current()) && !found; ++dstMnii ) + { + MemberDef *dstMd = dstMi->memberDef; + if (srcMd!=dstMd) // different members + { + ClassDef *dstCd = dstMd->getClassDef(); + //printf(" Is %s a base class of %s?\n",srcCd->name().data(),dstCd->name().data()); + if (srcCd==dstCd || dstCd->isBaseClass(srcCd,TRUE)) + // member is in the same or a base class + { + LockingPtr<ArgumentList> srcAl = srcMd->argumentList(); + LockingPtr<ArgumentList> dstAl = dstMd->argumentList(); + found=matchArguments2( + srcMd->getOuterScope(),srcMd->getFileDef(),srcAl.pointer(), + dstMd->getOuterScope(),dstMd->getFileDef(),dstAl.pointer(), + TRUE + ); + //printf(" Yes, matching (%s<->%s): %d\n", + // argListToString(srcMd->argumentList()).data(), + // argListToString(dstMd->argumentList()).data(), + // found); + hidden = hidden || !found; + } + else // member is in a non base class => multiple inheritance + // using the same base class. + { + //printf("$$ Existing member %s %s add scope %s\n", + // dstMi->ambiguityResolutionScope.data(), + // dstMd->name().data(), + // dstMi->scopePath.left(dstMi->scopePath.find("::")+2).data()); + + QCString scope=dstMi->scopePath.left(dstMi->scopePath.find(sep)+sepLen); + if (scope!=dstMi->ambiguityResolutionScope.left(scope.length())) + dstMi->ambiguityResolutionScope.prepend(scope); + ambigue=TRUE; + } + } + else // same members + { + // do not add if base class is virtual or + // if scope paths are equal or + // if base class is an interface (and thus implicitly virtual). + //printf("same member found srcMi->virt=%d dstMi->virt=%d\n",srcMi->virt,dstMi->virt); + if ((srcMi->virt!=Normal && dstMi->virt!=Normal) || + bClass->name()+sep+srcMi->scopePath == dstMi->scopePath || + dstMd->getClassDef()->compoundType()==Interface + ) + { + found=TRUE; + } + else // member can be reached via multiple paths in the + // inheritance tree + { + //printf("$$ Existing member %s %s add scope %s\n", + // dstMi->ambiguityResolutionScope.data(), + // dstMd->name().data(), + // dstMi->scopePath.left(dstMi->scopePath.find("::")+2).data()); + + QCString scope=dstMi->scopePath.left(dstMi->scopePath.find(sep)+sepLen); + if (scope!=dstMi->ambiguityResolutionScope.left(scope.length())) + { + dstMi->ambiguityResolutionScope.prepend(scope); + } + ambigue=TRUE; + } + } + } + //printf("member %s::%s hidden %d ambigue %d srcMi->ambigClass=%p\n", + // srcCd->name().data(),srcMd->name().data(),hidden,ambigue,srcMi->ambigClass); + + // TODO: fix the case where a member is hidden by inheritance + // of a member with the same name but with another prototype, + // while there is more than one path to the member in the + // base class due to multiple inheritance. In this case + // it seems that the member is not reachable by prefixing a + // scope name either (according to my compiler). Currently, + // this case is shown anyway. + if (!found && srcMd->protection()!=Private && !srcMd->isFriend()) + { + Protection prot=srcMd->protection(); + if (bcd->prot==Protected && prot==Public) prot=bcd->prot; + else if (bcd->prot==Private) prot=bcd->prot; + + if (inlineInheritedMembers) + { + if (!isStandardFunc(srcMd)) + { + //printf(" insertMember `%s'\n",srcMd->name().data()); + internalInsertMember(srcMd,prot,FALSE); + } + } + + Specifier virt=srcMi->virt; + if (srcMi->virt==Normal && bcd->virt!=Normal) virt=bcd->virt; + + MemberInfo *newMi = new MemberInfo(srcMd,prot,virt,TRUE); + newMi->scopePath=bClass->name()+sep+srcMi->scopePath; + if (ambigue) + { + //printf("$$ New member %s %s add scope %s::\n", + // srcMi->ambiguityResolutionScope.data(), + // srcMd->name().data(), + // bClass->name().data()); + + QCString scope=bClass->name()+sep; + if (scope!=srcMi->ambiguityResolutionScope.left(scope.length())) + { + newMi->ambiguityResolutionScope= + scope+srcMi->ambiguityResolutionScope.copy(); + } + } + if (hidden) + { + if (srcMi->ambigClass==0) + { + newMi->ambigClass=bClass; + newMi->ambiguityResolutionScope=bClass->name()+sep; + } + else + { + newMi->ambigClass=srcMi->ambigClass; + newMi->ambiguityResolutionScope=srcMi->ambigClass->name()+sep; + } + } + dstMni->append(newMi); + } + } + } + else // base class has a member that is not in the sub class => copy + { + // create a deep copy of the list (only the MemberInfo's will be + // copied, not the actual MemberDef's) + MemberNameInfo *newMni = 0; + newMni = new MemberNameInfo(srcMni->memberName()); + + // copy the member(s) from the base to the sub class + MemberNameInfoIterator mnii(*srcMni); + MemberInfo *mi; + for (;(mi=mnii.current());++mnii) + { + if (!mi->memberDef->isFriend()) // don't inherit friends + { + Protection prot = mi->prot; + if (bcd->prot==Protected) + { + if (prot==Public) prot=Protected; + } + else if (bcd->prot==Private) + { + prot=Private; + } + //printf("%s::%s: prot=%d bcd->prot=%d result=%d\n", + // name().data(),mi->memberDef->name().data(),mi->prot, + // bcd->prot,prot); + + if (mi->prot!=Private) + { + Specifier virt=mi->virt; + if (mi->virt==Normal && bcd->virt!=Normal) virt=bcd->virt; + + if (inlineInheritedMembers) + { + if (!isStandardFunc(mi->memberDef)) + { + //printf(" insertMember `%s'\n",mi->memberDef->name().data()); + internalInsertMember(mi->memberDef,prot,FALSE); + } + } + //printf("Adding!\n"); + MemberInfo *newMi=new MemberInfo(mi->memberDef,prot,virt,TRUE); + newMi->scopePath=bClass->name()+sep+mi->scopePath; + newMi->ambigClass=mi->ambigClass; + newMi->ambiguityResolutionScope=mi->ambiguityResolutionScope.copy(); + newMni->append(newMi); + } + } + } + + if (dstMnd==0) + { + m_impl->allMemberNameInfoSDict = new MemberNameInfoSDict(17); + m_impl->allMemberNameInfoSDict->setAutoDelete(TRUE); + dstMnd = m_impl->allMemberNameInfoSDict; + } + // add it to the dictionary + dstMnd->append(newMni->memberName(),newMni); + } + } + } + } + } + //printf(" end mergeMembers\n"); +} + +//---------------------------------------------------------------------------- + +/*! Merges the members of a Objective-C category into this class. + */ +void ClassDef::mergeCategory(ClassDef *category) +{ + static bool extractLocalMethods = Config_getBool("EXTRACT_LOCAL_METHODS"); + bool makePrivate = category->isLocal(); + // in case extract local methods is not enabled we don't add the methods + // of the category in case it is defined in the .m file. + if (makePrivate && !extractLocalMethods) return; + bool isExtension = category->isExtension(); + + category->setCategoryOf(this); + if (isExtension) + { + category->setArtificial(TRUE); + + // copy base classes/protocols from extension + if (category->baseClasses()) + { + BaseClassListIterator bcli(*category->baseClasses()); + BaseClassDef *bcd; + for ( ; (bcd=bcli.current()) ; ++bcli ) + { + insertBaseClass(bcd->classDef,bcd->usedName,bcd->prot,bcd->virt,bcd->templSpecifiers); + // correct bcd->classDef so that they do no longer derive from + // category, but from this class! + if (bcd->classDef->subClasses()) + { + BaseClassListIterator scli(*bcd->classDef->subClasses()); + BaseClassDef *scd; + for ( ; (scd=scli.current()) ; ++scli ) + { + if (scd->classDef==category) + { + scd->classDef=this; + } + } + } + } + } + + } + // make methods private for categories defined in the .m file + //printf("%s::mergeCategory makePrivate=%d\n",name().data(),makePrivate); + + MemberNameInfoSDict *srcMnd = category->memberNameInfoSDict(); + MemberNameInfoSDict *dstMnd = m_impl->allMemberNameInfoSDict; + + if (srcMnd && dstMnd) + { + MemberNameInfoSDict::Iterator srcMnili(*srcMnd); + MemberNameInfo *srcMni; + for ( ; (srcMni=srcMnili.current()) ; ++srcMnili) + { + MemberNameInfo *dstMni=dstMnd->find(srcMni->memberName()); + if (dstMni) // method is already defined in the class + { + //printf("Existing member %s\n",srcMni->memberName()); + MemberInfo *dstMi = dstMni->getFirst(); + MemberInfo *srcMi = srcMni->getFirst(); + //if (dstMi) + //{ + // Protection prot = dstMi->prot; + // if (makePrivate || isExtension) + // { + // prot = Private; + // removeMemberFromLists(dstMi->memberDef); + // internalInsertMember(dstMi->memberDef,prot,FALSE); + // } + //} + if (srcMi && dstMi) + { + combineDeclarationAndDefinition(srcMi->memberDef,dstMi->memberDef); + dstMi->memberDef->setCategory(category); + dstMi->memberDef->setCategoryRelation(srcMi->memberDef); + srcMi->memberDef->setCategoryRelation(dstMi->memberDef); + } + } + else // new method name + { + //printf("New member %s\n",srcMni->memberName()); + // create a deep copy of the list + MemberNameInfo *newMni = 0; + newMni = new MemberNameInfo(srcMni->memberName()); + + // copy the member(s) from the category to this class + MemberNameInfoIterator mnii(*srcMni); + MemberInfo *mi; + for (;(mi=mnii.current());++mnii) + { + //printf("Adding '%s'\n",mi->memberDef->name().data()); + Protection prot = mi->prot; + //if (makePrivate) prot = Private; + MemberDef *newMd = mi->memberDef->deepCopy(); + //printf("Copying member %s\n",mi->memberDef->name().data()); + newMd->moveTo(this); + + MemberInfo *newMi=new MemberInfo(newMd,prot,mi->virt,mi->inherited); + newMi->scopePath=mi->scopePath; + newMi->ambigClass=mi->ambigClass; + newMi->ambiguityResolutionScope=mi->ambiguityResolutionScope; + newMni->append(newMi); + + // also add the newly created member to the global members list + if (newMd) + { + MemberName *mn; + QCString name = newMd->name(); + if ((mn=Doxygen::memberNameSDict->find(name))) + { + mn->append(newMd); + } + else + { + mn = new MemberName(newMd->name()); + mn->append(newMd); + Doxygen::memberNameSDict->append(name,mn); + } + } + + newMd->setCategory(category); + newMd->setCategoryRelation(mi->memberDef); + mi->memberDef->setCategoryRelation(newMd); + if (makePrivate || isExtension) + { + newMd->makeImplementationDetail(); + } + internalInsertMember(newMd,prot,FALSE); + } + + // add it to the dictionary + dstMnd->append(newMni->memberName(),newMni); + } + } + } +} + +//---------------------------------------------------------------------------- + +void ClassDef::addUsedClass(ClassDef *cd,const char *accessName, + Protection prot) +{ + static bool extractPrivate = Config_getBool("EXTRACT_PRIVATE"); + if (prot==Private && !extractPrivate) return; + //printf("%s::addUsedClass(%s,%s)\n",name().data(),cd->name().data(),accessName); + if (m_impl->usesImplClassDict==0) + { + m_impl->usesImplClassDict = new UsesClassDict(17); + m_impl->usesImplClassDict->setAutoDelete(TRUE); + } + UsesClassDef *ucd=m_impl->usesImplClassDict->find(cd->name()); + if (ucd==0) + { + ucd = new UsesClassDef(cd); + m_impl->usesImplClassDict->insert(cd->name(),ucd); + //printf("Adding used class %s to class %s via accessor %s\n", + // cd->name().data(),name().data(),accessName); + } + ucd->addAccessor(accessName); +} + +void ClassDef::addUsedByClass(ClassDef *cd,const char *accessName, + Protection prot) +{ + static bool extractPrivate = Config_getBool("EXTRACT_PRIVATE"); + if (prot==Private && !extractPrivate) return; + //printf("%s::addUsedByClass(%s,%s)\n",name().data(),cd->name().data(),accessName); + if (m_impl->usedByImplClassDict==0) + { + m_impl->usedByImplClassDict = new UsesClassDict(17); + m_impl->usedByImplClassDict->setAutoDelete(TRUE); + } + UsesClassDef *ucd=m_impl->usedByImplClassDict->find(cd->name()); + if (ucd==0) + { + ucd = new UsesClassDef(cd); + m_impl->usedByImplClassDict->insert(cd->name(),ucd); + //printf("Adding used by class %s to class %s\n", + // cd->name().data(),name().data()); + } + ucd->addAccessor(accessName); +} + + +#if 0 +/*! Builds up a dictionary of all classes that are used by the state of this + * class (the "implementation"). + * Must be called before mergeMembers() is called! + */ + +void ClassDef::determineImplUsageRelation() +{ + MemberNameInfoSDict::Iterator mnili(*m_impl->allMemberNameInfoSDict); + MemberNameInfo *mni; + for (;(mni=mnili.current());++mnili) + { + MemberNameInfoIterator mnii(*mni); + MemberInfo *mi; + for (mnii.toFirst();(mi=mnii.current());++mnii) + { + MemberDef *md=mi->memberDef; + if (md->isVariable()) // for each member variable in this class + { + QCString type=removeRedundantWhiteSpace(md->typeString()); + //printf("in class %s found var type=`%s' name=`%s'\n", + // name().data(),type.data(),md->name().data()); + int pos=0; + QCString usedClassName; + QCString templSpec; + bool found=FALSE; + while (extractClassNameFromType(type,pos,usedClassName,templSpec)!=-1 && !found) + { + //printf("usedClassName=`%s' templSpec=%s\n",usedClassName.data(),templSpec.data()); + // check if usedClassName is a template argument of its class + ClassDef *cd=md->getClassDef(); + if (cd && cd->templateArguments()) + { + ArgumentListIterator ali(*cd->templateArguments()); + Argument *arg; + int count=0; + for (ali.toFirst();(arg=ali.current());++ali,++count) + { + if (arg->name==usedClassName) // type is a template argument + { + found=TRUE; + if (m_impl->usesImplClassDict==0) m_impl->usesImplClassDict = new UsesClassDict(257); + cd = new ClassDef(cd->getDefFileName(),cd->getDefLine(), + usedClassName,ClassDef::Class); + cd->setIsTemplateBaseClass(count); + UsesClassDef *ucd = new UsesClassDef(cd); + m_impl->usesImplClassDict->insert(cd->name(),ucd); + ucd->templSpecifiers = templSpec; + ucd->addAccessor(md->name()); + Doxygen::hiddenClasses.append(cd); + //printf("Adding used template argument %s to class %s\n", + // cd->name().data(),name().data()); + //printf("Adding accessor %s to class %s\n", + // md->name().data(),ucd->classDef->name().data()); + } + } + } + + if (!found) + { + cd=0; + if (getNamespaceDef()!=0) + { + cd=getResolvedClass(getNamespaceDef()->name()+"::"+usedClassName,0,&templSpec); + } + if (cd==0) cd=getResolvedClass(name()+"::"+usedClassName,0,&templSpec); + if (cd==0) cd=getResolvedClass(usedClassName,0,&templSpec); // TODO: also try inbetween scopes! + //printf("Search for class %s result=%p\n",usedClassName.data(),cd); + if (cd) // class exists + { + found=TRUE; + if (m_impl->usesImplClassDict==0) + { + m_impl->usesImplClassDict = new UsesClassDict(257); + m_impl->usesImplClassDict->setAutoDelete(TRUE); + } + UsesClassDef *ucd=m_impl->usesImplClassDict->find(cd->name()); + if (ucd==0 || ucd->templSpecifiers!=templSpec) + { + ucd = new UsesClassDef(cd); + m_impl->usesImplClassDict->insert(cd->name(),ucd); + ucd->templSpecifiers = templSpec; + //printf("Adding used class %s to class %s\n", + // cd->name().data(),name().data()); + } + ucd->addAccessor(md->name()); + //printf("Adding accessor %s to class %s\n", + // md->name().data(),ucd->classDef->name().data()); + } + } + } + } + } + } +#ifdef DUMP + if (m_impl->usesClassDict) + { + msg("Class %s uses the following classes:\n",name().data()); + UsesClassDictIterator ucdi(*m_impl->usesClassDict); + UsesClassDef *ucd; + for (;(ucd=ucdi.current());++ucdi) + { + msg(" %s via ",ucd->classDef->name().data()); + QDictIterator<void> dvi(*ucd->accessors); + const char *s; + for (;(s=dvi.currentKey());++dvi) + { + msg("%s ",s); + } + msg("\n"); + } + } +#endif +} + +//---------------------------------------------------------------------------- + +// I have disabled this code because the graphs it renders quickly become +// too large to be of practical use. + +void ClassDef::addUsedInterfaceClasses(MemberDef *md,const char *typeStr) +{ + QCString type = typeStr; + static const QRegExp re("[a-z_A-Z][a-z_A-Z0-9:]*"); + int p=0,i,l; + while ((i=re.match(type,p,&l))!=-1) // for each class name in the type + { + ClassDef *cd=getClass(name()+"::"+type.mid(i,l)); + if (cd==0) cd=getClass(type.mid(i,l)); // TODO: also try inbetween scopes! + if (cd && cd!=this && !isBaseClass(cd)) + { + if (m_impl->usesIntfClassDict==0) + { + m_impl->usesIntfClassDict = new UsesClassDict(257); + } + UsesClassDef *ucd=m_impl->usesIntfClassDict->find(cd->name()); + if (ucd==0) + { + ucd = new UsesClassDef(cd); + m_impl->usesIntfClassDict->insert(cd->name(),ucd); + //printf("in class `%s' adding used intf class `%s'\n", + // name().data(),cd->name().data()); + } + ucd->addAccessor(md->name()); + //printf("in class `%s' adding accessor `%s' to class `%s'\n", + // name().data(),md->name().data(),ucd->classDef->name().data()); + } + p=i+l; + } +} + +void ClassDef::determineIntfUsageRelation() +{ + MemberNameInfoSDict::Iterator mnili(*m_impl->allMemberNameInfoList); + MemberNameInfo *mni; + for (;(mni=mnili.current());++mnili) + { + MemberNameInfoIterator mnii(*mni); + MemberInfo *mi; + for (mnii.toFirst();(mi=mnii.current());++mnii) + { + MemberDef *md=mi->memberDef; + + // compute the protection level for this member + Protection protect=md->protection(); + if (mi->prot==Protected) // inherited protection + { + if (protect==Public) protect=Protected; + else if (protect==Protected) protect=Private; + } + + if (!md->name().isEmpty() && md->name()[0]!='@' && + (mi->prot!=Private && protect!=Private) + ) + { + // add classes found in the return type + addUsedInterfaceClasses(md,md->typeString()); + ArgumentList *al = md->argumentList(); + if (al) // member has arguments + { + // add classes found in the types of the argument list + ArgumentListIterator ali(*al); + Argument *a; + for (;(a=ali.current());++ali) + { + if (!a->type.isEmpty() && a->type.at(0)!='@') + { + addUsedInterfaceClasses(md,a->type); + } + } + } + } + } + } +} +#endif + +QCString ClassDef::compoundTypeString() const +{ + if (getLanguage()==SrcLangExt_Fortran) + { + switch (m_impl->compType) + { + case Class: return "module"; + case Struct: return "type"; + case Union: return "union"; + case Interface: return "interface"; + case Protocol: return "protocol"; + case Category: return "category"; + case Exception: return "exception"; + default: return "unknown"; + } + } + else + { + switch (m_impl->compType) + { + case Class: return isJavaEnum() ? "enum" : "class"; + case Struct: return "struct"; + case Union: return "union"; + case Interface: return getLanguage()==SrcLangExt_ObjC ? "class" : "interface"; + case Protocol: return "protocol"; + case Category: return "category"; + case Exception: return "exception"; + default: return "unknown"; + } + } +} + +QCString ClassDef::getOutputFileBase() const +{ + if (!Doxygen::generatingXmlOutput) + { + static bool inlineGroupedClasses = Config_getBool("INLINE_GROUPED_CLASSES"); + static bool inlineSimpleClasses = Config_getBool("INLINE_SIMPLE_STRUCTS"); + Definition *scope=0; + if (inlineGroupedClasses && partOfGroups()!=0) + { + // point to the group that embeds this class + return partOfGroups()->at(0)->getOutputFileBase(); + } + else if (inlineSimpleClasses && m_impl->isSimple && partOfGroups()!=0) + { + // point to simple struct inside a group + return partOfGroups()->at(0)->getOutputFileBase(); + } + else if (inlineSimpleClasses && m_impl->isSimple && (scope=getOuterScope())) + { + if (scope==Doxygen::globalScope && getFileDef() && getFileDef()->isLinkableInProject()) // simple struct embedded in file + { + return getFileDef()->getOutputFileBase(); + } + else if (scope->isLinkableInProject()) // simple struct embedded in other container (namespace/group/class) + { + return getOuterScope()->getOutputFileBase(); + } + } + } + if (m_impl->templateMaster) + { + // point to the template of which this class is an instance + return m_impl->templateMaster->getOutputFileBase(); + } + else if (isReference()) + { + // point to the external location + return m_impl->fileName; + } + else + { + // normal locally defined class + return convertNameToFile(m_impl->fileName); + } +} + +QCString ClassDef::getInstanceOutputFileBase() const +{ + if (isReference()) + { + return m_impl->fileName; + } + else + { + return convertNameToFile(m_impl->fileName); + } +} + +QCString ClassDef::getFileBase() const +{ + if (m_impl->templateMaster) + { + return m_impl->templateMaster->getFileBase(); + } + else + { + return m_impl->fileName; + } +} + +QCString ClassDef::getSourceFileBase() const +{ + if (m_impl->templateMaster) + { + return m_impl->templateMaster->getSourceFileBase(); + } + else + { + return convertNameToFile(m_impl->fileName)+"_source"; + } +} + +void ClassDef::setGroupDefForAllMembers(GroupDef *gd,Grouping::GroupPri_t pri,const QCString &fileName,int startLine,bool hasDocs) +{ + gd->addClass(this); + //printf("ClassDef::setGroupDefForAllMembers(%s)\n",gd->name().data()); + if (m_impl->allMemberNameInfoSDict==0) return; + MemberNameInfoSDict::Iterator mnili(*m_impl->allMemberNameInfoSDict); + MemberNameInfo *mni; + for (;(mni=mnili.current());++mnili) + { + MemberNameInfoIterator mnii(*mni); + MemberInfo *mi; + for (mnii.toFirst();(mi=mnii.current());++mnii) + { + MemberDef *md=mi->memberDef; + md->setGroupDef(gd,pri,fileName,startLine,hasDocs); + gd->insertMember(md,TRUE); + ClassDef *innerClass = md->getClassDefOfAnonymousType(); + if (innerClass) innerClass->setGroupDefForAllMembers(gd,pri,fileName,startLine,hasDocs); + } + } +} + +void ClassDef::addInnerCompound(Definition *d) +{ + //printf("**** %s::addInnerCompound(%s)\n",name().data(),d->name().data()); + if (d->definitionType()==Definition::TypeClass) // only classes can be + // nested in classes. + { + if (m_impl->innerClasses==0) + { + m_impl->innerClasses = new ClassSDict(17); + } + m_impl->innerClasses->inSort(d->localName(),(ClassDef *)d); + } +} + +Definition *ClassDef::findInnerCompound(const char *name) +{ + Definition *result=0; + if (name==0) return 0; + if (m_impl->innerClasses) + { + result = m_impl->innerClasses->find(name); + } + return result; +} + +//void ClassDef::initTemplateMapping() +//{ +// m_impl->templateMapping->clear(); +// ArgumentList *al = templateArguments(); +// if (al) +// { +// ArgumentListIterator ali(*al); +// Argument *arg; +// for (ali.toFirst();(arg=ali.current());++ali) +// { +// setTemplateArgumentMapping(arg->name,arg->defval); +// } +// } +//} +//void ClassDef::setTemplateArgumentMapping(const char *formal,const char *actual) +//{ +// //printf("ClassDef::setTemplateArgumentMapping(%s,%s)\n",formal,actual); +// if (m_impl->templateMapping && formal) +// { +// if (m_impl->templateMapping->find(formal)) +// { +// m_impl->templateMapping->remove(formal); +// } +// m_impl->templateMapping->insert(formal,new QCString(actual)); +// } +//} +// +//QCString ClassDef::getTemplateArgumentMapping(const char *formal) const +//{ +// if (m_impl->templateMapping && formal) +// { +// QCString *s = m_impl->templateMapping->find(formal); +// if (s) +// { +// return *s; +// } +// } +// return ""; +//} + +ClassDef *ClassDef::insertTemplateInstance(const QCString &fileName, + int startLine, const QCString &templSpec,bool &freshInstance) +{ + freshInstance = FALSE; + if (m_impl->templateInstances==0) + { + m_impl->templateInstances = new QDict<ClassDef>(17); + } + ClassDef *templateClass=m_impl->templateInstances->find(templSpec); + if (templateClass==0) + { + Debug::print(Debug::Classes,0," New template instance class `%s'`%s'\n",name().data(),templSpec.data()); + templateClass = new ClassDef( + fileName,startLine,localName()+templSpec,ClassDef::Class); + templateClass->setTemplateMaster(this); + templateClass->setOuterScope(getOuterScope()); + templateClass->setHidden(isHidden()); + m_impl->templateInstances->insert(templSpec,templateClass); + freshInstance=TRUE; + } + return templateClass; +} + +ClassDef *ClassDef::getVariableInstance(const char *templSpec) +{ + if (m_impl->variableInstances==0) + { + m_impl->variableInstances = new QDict<ClassDef>(17); + m_impl->variableInstances->setAutoDelete(TRUE); + } + ClassDef *templateClass=m_impl->variableInstances->find(templSpec); + if (templateClass==0) + { + Debug::print(Debug::Classes,0," New template variable instance class `%s'`%s'\n",qPrint(name()),qPrint(templSpec)); + templateClass = new ClassDef("<code>",1,name()+templSpec, + ClassDef::Class,0,0,FALSE); + templateClass->addMembersToTemplateInstance( this, templSpec ); + templateClass->setTemplateMaster(this); + m_impl->variableInstances->insert(templSpec,templateClass); + } + return templateClass; +} + +void ClassDef::setTemplateBaseClassNames(QDict<int> *templateNames) +{ + if (templateNames==0) return; + if (m_impl->templBaseClassNames==0) + { + m_impl->templBaseClassNames = new QDict<int>(17); + m_impl->templBaseClassNames->setAutoDelete(TRUE); + } + // make a deep copy of the dictionary. + QDictIterator<int> qdi(*templateNames); + for (;qdi.current();++qdi) + { + if (m_impl->templBaseClassNames->find(qdi.currentKey())==0) + { + m_impl->templBaseClassNames->insert(qdi.currentKey(),new int(*qdi.current())); + } + } +} + +QDict<int> *ClassDef::getTemplateBaseClassNames() const +{ + return m_impl->templBaseClassNames; +} + +void ClassDef::addMembersToTemplateInstance(ClassDef *cd,const char *templSpec) +{ + //printf("%s::addMembersToTemplateInstance(%s,%s)\n",name().data(),cd->name().data(),templSpec); + if (cd->memberNameInfoSDict()==0) return; + MemberNameInfoSDict::Iterator mnili(*cd->memberNameInfoSDict()); + MemberNameInfo *mni; + for (;(mni=mnili.current());++mnili) + { + MemberNameInfoIterator mnii(*mni); + MemberInfo *mi; + for (mnii.toFirst();(mi=mnii.current());++mnii) + { + ArgumentList *actualArguments = new ArgumentList; + stringToArgumentList(templSpec,actualArguments); + MemberDef *md = mi->memberDef; + MemberDef *imd = md->createTemplateInstanceMember( + cd->templateArguments(),actualArguments); + delete actualArguments; + //printf("%s->setMemberClass(%p)\n",imd->name().data(),this); + imd->setMemberClass(this); + imd->setTemplateMaster(md); + imd->setDocumentation(md->documentation(),md->docFile(),md->docLine()); + imd->setBriefDescription(md->briefDescription(),md->briefFile(),md->briefLine()); + imd->setInbodyDocumentation(md->inbodyDocumentation(),md->inbodyFile(),md->inbodyLine()); + imd->setMemberSpecifiers(md->getMemberSpecifiers()); + imd->setMemberGroupId(md->getMemberGroupId()); + insertMember(imd); + //printf("Adding member=%s %s%s to class %s templSpec %s\n", + // imd->typeString(),imd->name().data(),imd->argsString(), + // imd->getClassDef()->name().data(),templSpec); + // insert imd in the list of all members + //printf("Adding member=%s class=%s\n",imd->name().data(),name().data()); + MemberName *mn = Doxygen::memberNameSDict->find(imd->name()); + if (mn==0) + { + mn = new MemberName(imd->name()); + Doxygen::memberNameSDict->append(imd->name(),mn); + } + mn->append(imd); + } + } +} + +QCString ClassDef::getReference() const +{ + if (m_impl->templateMaster) + { + return m_impl->templateMaster->getReference(); + } + else + { + return Definition::getReference(); + } +} + +bool ClassDef::isReference() const +{ + if (m_impl->templateMaster) + { + return m_impl->templateMaster->isReference(); + } + else + { + return Definition::isReference(); + } +} + +void ClassDef::getTemplateParameterLists(QList<ArgumentList> &lists) const +{ + Definition *d=getOuterScope(); + if (d) + { + if (d->definitionType()==Definition::TypeClass) + { + ClassDef *cd=(ClassDef *)d; + cd->getTemplateParameterLists(lists); + } + } + if (templateArguments()) + { + lists.append(templateArguments()); + } +} + +QCString ClassDef::qualifiedNameWithTemplateParameters( + QList<ArgumentList> *actualParams) const +{ + //static bool optimizeOutputJava = Config_getBool("OPTIMIZE_OUTPUT_JAVA"); + static bool hideScopeNames = Config_getBool("HIDE_SCOPE_NAMES"); + //printf("qualifiedNameWithTemplateParameters() localName=%s\n",localName().data()); + QCString scName; + Definition *d=getOuterScope(); + if (d) + { + if (d->definitionType()==Definition::TypeClass) + { + ClassDef *cd=(ClassDef *)d; + scName = cd->qualifiedNameWithTemplateParameters(actualParams); + } + else if (!hideScopeNames) + { + scName = d->qualifiedName(); + } + } + + SrcLangExt lang = getLanguage(); + QCString scopeSeparator = getLanguageSpecificSeparator(lang); + if (!scName.isEmpty()) scName+=scopeSeparator; + + bool isSpecialization = localName().find('<')!=-1; + + QCString clName = className(); + //bool isGeneric = getLanguage()==SrcLangExt_CSharp; + //if (isGeneric && clName.right(2)=="-g") + //{ + // clName = clName.left(clName.length()-2); + //} + //printf("m_impl->lang=%d clName=%s\n",m_impl->lang,clName.data()); + scName+=clName; + ArgumentList *al=0; + if (templateArguments()) + { + if (actualParams && (al=actualParams->current())) + { + if (!isSpecialization) + { + scName+=tempArgListToString(al); + } + actualParams->next(); + } + else + { + if (!isSpecialization) + { + scName+=tempArgListToString(templateArguments()); + } + } + } + //printf("qualifiedNameWithTemplateParameters: scope=%s qualifiedName=%s\n",name().data(),scName.data()); + return scName; +} + +QCString ClassDef::className() const +{ + if (m_impl->className.isEmpty()) + { + return localName(); + } + else + { + return m_impl->className; + } +}; + +void ClassDef::setClassName(const char *name) +{ + m_impl->className = name; +} + +void ClassDef::addListReferences() +{ + SrcLangExt lang = getLanguage(); + if (!isLinkableInProject()) return; + //printf("ClassDef(%s)::addListReferences()\n",name().data()); + { + LockingPtr< QList<ListItemInfo> > xrefItems = xrefListItems(); + addRefItem(xrefItems.pointer(), + qualifiedName(), + lang==SrcLangExt_Fortran ? theTranslator->trType(TRUE,TRUE) + : theTranslator->trClass(TRUE,TRUE), + getOutputFileBase(), + displayName(), + 0 + ); + } + if (m_impl->memberGroupSDict) + { + MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict); + MemberGroup *mg; + for (;(mg=mgli.current());++mgli) + { + mg->addListReferences(this); + } + } + QListIterator<MemberList> mli(m_impl->memberLists); + MemberList *ml; + for (mli.toFirst();(ml=mli.current());++mli) + { + if (ml->listType()&MemberList::detailedLists) + { + ml->addListReferences(this); + } + } +} + +MemberDef *ClassDef::getMemberByName(const QCString &name) const +{ + MemberDef *xmd = 0; + if (m_impl->allMemberNameInfoSDict) + { + MemberNameInfo *mni = m_impl->allMemberNameInfoSDict->find(name); + if (mni) + { + const int maxInheritanceDepth = 100000; + int mdist=maxInheritanceDepth; + MemberNameInfoIterator mnii(*mni); + MemberInfo *mi; + for (mnii.toFirst();(mi=mnii.current());++mnii) + { + ClassDef *mcd=mi->memberDef->getClassDef(); + int m=minClassDistance(this,mcd); + //printf("found member in %s linkable=%d m=%d\n", + // mcd->name().data(),mcd->isLinkable(),m); + if (m<mdist && mcd->isLinkable()) + { + mdist=m; + xmd=mi->memberDef; + } + } + } + } + //printf("getMemberByName(%s)=%p\n",name.data(),xmd); + return xmd; +} + +bool ClassDef::isAccessibleMember(MemberDef *md) +{ + return md->getClassDef() && isBaseClass(md->getClassDef(),TRUE); +} + +MemberList *ClassDef::createMemberList(MemberList::ListType lt) +{ + m_impl->memberLists.setAutoDelete(TRUE); + QListIterator<MemberList> mli(m_impl->memberLists); + MemberList *ml; + for (mli.toFirst();(ml=mli.current());++mli) + { + if (ml->listType()==lt) + { + return ml; + } + } + // not found, create a new member list + ml = new MemberList(lt); + m_impl->memberLists.append(ml); + return ml; +} + +MemberList *ClassDef::getMemberList(MemberList::ListType lt) +{ + MemberList *ml = m_impl->memberLists.first(); + while (ml) + { + if (ml->listType()==lt) + { + return ml; + } + ml = m_impl->memberLists.next(); + } + return 0; +} + +void ClassDef::addMemberToList(MemberList::ListType lt,MemberDef *md,bool isBrief) +{ + static bool sortBriefDocs = Config_getBool("SORT_BRIEF_DOCS"); + static bool sortMemberDocs = Config_getBool("SORT_MEMBER_DOCS"); + MemberList *ml = createMemberList(lt); + ml->setNeedsSorting((isBrief && sortBriefDocs) || (!isBrief && sortMemberDocs)); + ml->append(md); + + // for members in the declaration lists we set the section, needed for member grouping + if ((ml->listType()&MemberList::detailedLists)==0) md->setSectionList(this,ml); +} + +void ClassDef::sortMemberLists() +{ + MemberList *ml = m_impl->memberLists.first(); + while (ml) + { + if (ml->needsSorting()) { ml->sort(); ml->setNeedsSorting(FALSE); } + ml = m_impl->memberLists.next(); + } +} + +static void convertProtectionLevel( + MemberList::ListType inListType, + Protection inProt, + int *outListType1, + int *outListType2 + ) +{ + // default representing Public inheritance + *outListType1=inListType; + *outListType2=-1; + if (inProt==Public) + { + switch (inListType) // in the private section of the derived class, + // the private section of the base class should not + // be visible + { + case MemberList::priMethods: + case MemberList::priStaticMethods: + case MemberList::priSlots: + case MemberList::priAttribs: + case MemberList::priStaticAttribs: + case MemberList::priTypes: + *outListType1=-1; + *outListType2=-1; + break; + default: + break; + } + } + else if (inProt==Protected) // Protected inheritance + { + switch (inListType) // in the protected section of the derived class, + // both the public and protected members are shown + // as protected + { + case MemberList::pubMethods: + case MemberList::pubStaticMethods: + case MemberList::pubSlots: + case MemberList::pubAttribs: + case MemberList::pubStaticAttribs: + case MemberList::pubTypes: + case MemberList::priMethods: + case MemberList::priStaticMethods: + case MemberList::priSlots: + case MemberList::priAttribs: + case MemberList::priStaticAttribs: + case MemberList::priTypes: + *outListType1=-1; + *outListType2=-1; + break; + + case MemberList::proMethods: + *outListType1=MemberList::pubMethods; + *outListType2=MemberList::proMethods; + break; + case MemberList::proStaticMethods: + *outListType1=MemberList::pubStaticMethods; + *outListType2=MemberList::proStaticMethods; + break; + case MemberList::proSlots: + *outListType1=MemberList::pubSlots; + *outListType1=MemberList::proSlots; + break; + case MemberList::proAttribs: + *outListType1=MemberList::pubAttribs; + *outListType2=MemberList::proAttribs; + break; + case MemberList::proStaticAttribs: + *outListType1=MemberList::pubStaticAttribs; + *outListType2=MemberList::proStaticAttribs; + break; + case MemberList::proTypes: + *outListType1=MemberList::pubTypes; + *outListType2=MemberList::proTypes; + break; + default: + break; + } + } + else if (inProt==Private) + { + switch (inListType) // in the private section of the derived class, + // both the public and protected members are shown + // as private + { + case MemberList::pubMethods: + case MemberList::pubStaticMethods: + case MemberList::pubSlots: + case MemberList::pubAttribs: + case MemberList::pubStaticAttribs: + case MemberList::pubTypes: + case MemberList::proMethods: + case MemberList::proStaticMethods: + case MemberList::proSlots: + case MemberList::proAttribs: + case MemberList::proStaticAttribs: + case MemberList::proTypes: + *outListType1=-1; + *outListType2=-1; + break; + + case MemberList::priMethods: + *outListType1=MemberList::pubMethods; + *outListType2=MemberList::proMethods; + break; + case MemberList::priStaticMethods: + *outListType1=MemberList::pubStaticMethods; + *outListType2=MemberList::proStaticMethods; + break; + case MemberList::priSlots: + *outListType1=MemberList::pubSlots; + *outListType1=MemberList::proSlots; + break; + case MemberList::priAttribs: + *outListType1=MemberList::pubAttribs; + *outListType2=MemberList::proAttribs; + break; + case MemberList::priStaticAttribs: + *outListType1=MemberList::pubStaticAttribs; + *outListType2=MemberList::proStaticAttribs; + break; + case MemberList::priTypes: + *outListType1=MemberList::pubTypes; + *outListType2=MemberList::proTypes; + break; + default: + break; + } + } + //printf("convertProtectionLevel(type=%d prot=%d): %d,%d\n", + // inListType,inProt,*outListType1,*outListType2); +} + +int ClassDef::countInheritedDecMembersRec(MemberList::ListType lt, + ClassDef *inheritedFrom) +{ + //printf("> %s::countedInheritedDecMembersRec(%d)\n",name().data(),lt); + int count=0; + if (m_impl->inherits) + { + BaseClassListIterator it(*m_impl->inherits); + BaseClassDef *ibcd; + for (it.toFirst();(ibcd=it.current());++it) + { + ClassDef *icd=ibcd->classDef; + int lt1,lt2; + // an inherited member with protection level lt + // could have come from a section with protection levels lt1 or lt2 + // in the bass class (e.g. for protected inheritance, the protected + // member comes from protected and public methods in the base class) + convertProtectionLevel(lt,ibcd->prot,<1,<2); + MemberList *ml1 = icd->getMemberList((MemberList::ListType)lt1); + MemberList *ml2 = icd->getMemberList((MemberList::ListType)lt2); + if (ml1) + { + count+=icd->countMembersIncludingGrouped((MemberList::ListType)lt1,inheritedFrom,TRUE); + } + if (ml2) + { + count+=icd->countMembersIncludingGrouped((MemberList::ListType)lt2,inheritedFrom,TRUE); + } + if (lt1!=-1) + { + count+=icd->countInheritedDecMembersRec((MemberList::ListType)lt1,inheritedFrom); + } + if (lt2!=-1) + { + count+=icd->countInheritedDecMembersRec((MemberList::ListType)lt2,inheritedFrom); + } + } + } + //printf("< %s::countedInheritedDecMembersRec(%d) count=%d\n",name().data(),lt,count); + return count; +} + +int ClassDef::countInheritedDecMembers(MemberList::ListType lt) +{ + int count=0; + MemberList *ml = getMemberList(lt); + if (ml) + { + count = ml->countInheritableMembers(this); + } + if (count==0) // for this class the (non-private) member list is empty + // see if we need to create a section for it under + // Additional Inherited Members + { + count = countInheritedDecMembersRec(lt,this); + } + else // member list is not empty, so we will add the inherited members there + { + count = 0; + } + return count; +} + +int ClassDef::countAdditionalInheritedMembers() +{ + int totalCount=0; + QListIterator<LayoutDocEntry> eli( + LayoutDocManager::instance().docEntries(LayoutDocManager::Class)); + LayoutDocEntry *lde; + for (eli.toFirst();(lde=eli.current());++eli) + { + if (lde->kind()==LayoutDocEntry::MemberDecl) + { + LayoutDocEntryMemberDecl *lmd = (LayoutDocEntryMemberDecl*)lde; + if (lmd->type!=MemberList::friends) // friendship is not inherited + { + totalCount+=countInheritedDecMembers(lmd->type); + } + } + } + //printf("countAdditonalInheritedMembers()=%d\n",totalCount); + return totalCount; +} + +void ClassDef::writeAdditionalInheritedMembers(OutputList &ol) +{ + //printf("**** writeAdditionalInheritedMembers()\n"); + QListIterator<LayoutDocEntry> eli( + LayoutDocManager::instance().docEntries(LayoutDocManager::Class)); + LayoutDocEntry *lde; + for (eli.toFirst();(lde=eli.current());++eli) + { + if (lde->kind()==LayoutDocEntry::MemberDecl) + { + LayoutDocEntryMemberDecl *lmd = (LayoutDocEntryMemberDecl*)lde; + MemberList *ml = getMemberList(lmd->type); + if (ml==0 || ml->numDecMembers()==0) + { + QPtrDict<void> visited(17); + writeInheritedMemberDeclarations(ol,lmd->type,lmd->title(getLanguage()),this,TRUE,&visited); + } + } + } +} + +int ClassDef::countMembersIncludingGrouped(MemberList::ListType lt, + ClassDef *inheritedFrom,bool additional) +{ + int count=0; + MemberList *ml = getMemberList(lt); + if (ml) + { + count=ml->countInheritableMembers(inheritedFrom); + } + //printf("%s:countMembersIncludingGrouped: count=%d\n",name().data(),count); + if (m_impl->memberGroupSDict) + { + MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict); + MemberGroup *mg; + for (;(mg=mgli.current());++mgli) + { + bool hasOwnSection = !mg->allMembersInSameSection() || + !m_impl->subGrouping; // group is in its own section + if ((additional && hasOwnSection) || (!additional && !hasOwnSection)) + { + count+=mg->countGroupedInheritedMembers(lt); + } + } + } + //printf("%s:countMembersIncludingGrouped(lt=%d,%s)=%d\n", + // name().data(),lt,ml?ml->listTypeAsString().data():"<none>",count); + return count; +} + +void ClassDef::writeInheritedMemberDeclarations(OutputList &ol, + MemberList::ListType lt,const QCString &title, + ClassDef *inheritedFrom,bool invert, + QPtrDict<void> *visitedClasses) +{ + ol.pushGeneratorState(); + ol.disableAllBut(OutputGenerator::Html); + bool process = countMembersIncludingGrouped(lt,inheritedFrom,FALSE)>0; + //printf("%s: writeInheritedMemberDec: lt=%d process=%d invert=%d\n", + // name().data(),lt,process,invert); + if (process^invert) + { + if (m_impl->inherits) + { + BaseClassListIterator it(*m_impl->inherits); + BaseClassDef *ibcd; + for (it.toFirst();(ibcd=it.current());++it) + { + ClassDef *icd=ibcd->classDef; + int lt1,lt2; + convertProtectionLevel(lt,ibcd->prot,<1,<2); + //printf("%s:convert %d->(%d,%d)\n",icd->name().data(),lt,lt1,lt2); + if (visitedClasses->find(icd)!=0) + { + return; // already processed before (in case of multiple inheritance) + } + visitedClasses->insert(icd,icd); + if (lt1!=-1) + { + icd->writeMemberDeclarations(ol,(MemberList::ListType)lt1, + title,QCString(),FALSE,inheritedFrom,lt2,invert,visitedClasses); + } + } + } + } + ol.popGeneratorState(); +} + +void ClassDef::writeMemberDeclarations(OutputList &ol,MemberList::ListType lt,const QCString &title, + const char *subTitle,bool showInline,ClassDef *inheritedFrom,int lt2,bool invert,QPtrDict<void> *visitedClasses) +{ + //printf("%s: ClassDef::writeMemberDeclarations for %s\n",name().data(),ml->listTypeAsString().data()); + MemberList * ml = getMemberList(lt); + if (getLanguage()==SrcLangExt_VHDL) // use specific declarations function + { + if (ml) + { + VhdlDocGen::writeVhdlDeclarations(ml,ol,0,this,0,0); + } + } + else + { + //printf("%s::writeMemberDeclarations(%s)\n",name().data(),title.data()); + //static bool optimizeVhdl = Config_getBool("OPTIMIZE_OUTPUT_VHDL"); + if (ml) + { + ml->writeDeclarations(ol,this,0,0,0,title,subTitle,FALSE,showInline,inheritedFrom); + if (lt2!=-1) + { + MemberList * ml2 = getMemberList((MemberList::ListType)lt2); + if (ml2) + { + ml2->writeDeclarations(ol,this,0,0,0,0,0,FALSE,showInline,inheritedFrom); + } + } + } + static bool inlineInheritedMembers = Config_getBool("INLINE_INHERITED_MEMB"); + if (!inlineInheritedMembers) // show inherited members as separate lists + { + QPtrDict<void> visited(17); + writeInheritedMemberDeclarations(ol,lt,title, + inheritedFrom ? inheritedFrom : this, + invert,visitedClasses==0 ? &visited: visitedClasses); + } + } +} + +void ClassDef::addGroupedInheritedMembers(OutputList &ol,MemberList::ListType lt, + ClassDef *inheritedFrom,const QCString &inheritId) +{ + //printf("** %s::addGroupedInheritedMembers(%p) inheritId=%s\n",name().data(),m_impl->memberGroupSDict,inheritId.data()); + if (m_impl->memberGroupSDict) + { + MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict); + MemberGroup *mg; + for (;(mg=mgli.current());++mgli) + { + if (!mg->allMembersInSameSection() || !m_impl->subGrouping) // group is in its own section + { + mg->addGroupedInheritedMembers(ol,this,lt,inheritedFrom,inheritId); + } + } + } +} + +void ClassDef::writeMemberDocumentation(OutputList &ol,MemberList::ListType lt,const QCString &title,bool showInline) +{ + //printf("%s: ClassDef::writeMemberDocumentation()\n",name().data()); + MemberList * ml = getMemberList(lt); + if (ml) ml->writeDocumentation(ol,displayName(),this,title,FALSE,showInline); +} + +void ClassDef::writeSimpleMemberDocumentation(OutputList &ol,MemberList::ListType lt) +{ + //printf("%s: ClassDef::writeSimpleMemberDocumentation()\n",name().data()); + MemberList * ml = getMemberList(lt); + if (ml) ml->writeSimpleDocumentation(ol,this); +} + +void ClassDef::writePlainMemberDeclaration(OutputList &ol, + MemberList::ListType lt,bool inGroup, + ClassDef *inheritedFrom,const char *inheritId) +{ + //printf("%s: ClassDef::writePlainMemberDeclaration()\n",name().data()); + MemberList * ml = getMemberList(lt); + if (ml) + { + ml->setInGroup(inGroup); + ml->writePlainDeclarations(ol,this,0,0,0,inheritedFrom,inheritId); + } +} + +bool ClassDef::isLocal() const +{ + return m_impl->isLocal; +} + +ClassSDict *ClassDef::getClassSDict() +{ + return m_impl->innerClasses; +} + +ClassDef::CompoundType ClassDef::compoundType() const +{ + return m_impl->compType; +} + +BaseClassList *ClassDef::baseClasses() const +{ + return m_impl->inherits; +} + +BaseClassList *ClassDef::subClasses() const +{ + return m_impl->inheritedBy; +} + +MemberNameInfoSDict *ClassDef::memberNameInfoSDict() const +{ + return m_impl->allMemberNameInfoSDict; +} + +Protection ClassDef::protection() const +{ + return m_impl->prot; +} + +ArgumentList *ClassDef::templateArguments() const +{ + return m_impl->tempArgs; +} + +NamespaceDef *ClassDef::getNamespaceDef() const +{ + return m_impl->nspace; +} + +FileDef *ClassDef::getFileDef() const +{ + return m_impl->fileDef; +} + +QDict<ClassDef> *ClassDef::getTemplateInstances() const +{ + return m_impl->templateInstances; +} + +ClassDef *ClassDef::templateMaster() const +{ + return m_impl->templateMaster; +} + +bool ClassDef::isTemplate() const +{ + return m_impl->tempArgs!=0; +} + +IncludeInfo *ClassDef::includeInfo() const +{ + return m_impl->incInfo; +} + +UsesClassDict *ClassDef::usedImplementationClasses() const +{ + return m_impl->usesImplClassDict; +} + +UsesClassDict *ClassDef::usedByImplementationClasses() const +{ + return m_impl->usedByImplClassDict; +} + +UsesClassDict *ClassDef::usedInterfaceClasses() const +{ + return m_impl->usesIntfClassDict; +} + +bool ClassDef::isTemplateArgument() const +{ + return m_impl->isTemplArg; +} + +bool ClassDef::isAbstract() const +{ + return m_impl->isAbstract || (m_impl->spec&Entry::Abstract); +} + +bool ClassDef::isFinal() const +{ + return m_impl->spec&Entry::Final; +} + +bool ClassDef::isSealed() const +{ + return m_impl->spec&Entry::Sealed; +} + +bool ClassDef::isObjectiveC() const +{ + return getLanguage()==SrcLangExt_ObjC; +} + +bool ClassDef::isCSharp() const +{ + return getLanguage()==SrcLangExt_CSharp; +} + +ClassDef *ClassDef::categoryOf() const +{ + return m_impl->categoryOf; +} + +const QList<MemberList> &ClassDef::getMemberLists() const +{ + return m_impl->memberLists; +} + +MemberGroupSDict *ClassDef::getMemberGroupSDict() const +{ + return m_impl->memberGroupSDict; +} + +void ClassDef::setNamespace(NamespaceDef *nd) +{ + m_impl->nspace = nd; +} + +void ClassDef::setFileDef(FileDef *fd) +{ + m_impl->fileDef=fd; +} + +void ClassDef::setSubGrouping(bool enabled) +{ + m_impl->subGrouping = enabled; +} + +void ClassDef::setProtection(Protection p) +{ + m_impl->prot=p; +} + +void ClassDef::setIsStatic(bool b) +{ + m_impl->isStatic=b; +} + +void ClassDef::setCompoundType(CompoundType t) +{ + m_impl->compType = t; +} + +void ClassDef::setTemplateMaster(ClassDef *tm) +{ + m_impl->templateMaster=tm; +} + +void ClassDef::makeTemplateArgument(bool b) +{ + m_impl->isTemplArg = b; +} + +void ClassDef::setCategoryOf(ClassDef *cd) +{ + m_impl->categoryOf = cd; +} + +void ClassDef::setUsedOnly(bool b) +{ + m_impl->usedOnly = b; +} + +bool ClassDef::isUsedOnly() const +{ + return m_impl->usedOnly; +} + +bool ClassDef::isSimple() const +{ + return m_impl->isSimple; +} + +MemberDef *ClassDef::isSmartPointer() const +{ + return m_impl->arrowOperator; +} + +void ClassDef::reclassifyMember(MemberDef *md,MemberDef::MemberType t) +{ + md->setMemberType(t); + MemberList *ml = m_impl->memberLists.first(); + while (ml) + { + ml->remove(md); + ml = m_impl->memberLists.next(); + } + insertMember(md); +} + +QCString ClassDef::anchor() const +{ + QCString anc; + if (isEmbeddedInOuterScope() && !Doxygen::generatingXmlOutput) + { + if (m_impl->templateMaster) + { + // point to the template of which this class is an instance + anc = m_impl->templateMaster->getOutputFileBase(); + } + else if (isReference()) + { + // point to the external location + anc = m_impl->fileName; + } + else + { + // normal locally defined class + anc = convertNameToFile(m_impl->fileName); + } + } + return anc; +} + +bool ClassDef::isEmbeddedInOuterScope() const +{ + static bool inlineGroupedClasses = Config_getBool("INLINE_GROUPED_CLASSES"); + static bool inlineSimpleClasses = Config_getBool("INLINE_SIMPLE_STRUCTS"); + + Definition *container = getOuterScope(); + + bool containerLinkable = + container && + ( + (container==Doxygen::globalScope && getFileDef() && getFileDef()->isLinkableInProject()) || // global class in documented file + container->isLinkableInProject() // class in documented scope + ); + + // inline because of INLINE_GROUPED_CLASSES=YES ? + bool b1 = (inlineGroupedClasses && partOfGroups()!=0); // a grouped class + // inline because of INLINE_SIMPLE_STRUCTS=YES ? + bool b2 = (inlineSimpleClasses && m_impl->isSimple && // a simple class + (containerLinkable || // in a documented container + partOfGroups()!=0 // or part of a group + ) + ); + //printf("%s::isEmbeddedInOuterScope(): inlineGroupedClasses=%d " + // "inlineSimpleClasses=%d partOfGroups()=%p m_impl->isSimple=%d " + // "getOuterScope()=%s b1=%d b2=%d\n", + // name().data(),inlineGroupedClasses,inlineSimpleClasses, + // partOfGroups().pointer(),m_impl->isSimple,getOuterScope()?getOuterScope()->name().data():"<none>",b1,b2); + return b1 || b2; // either reason will do +} + +const ClassList *ClassDef::taggedInnerClasses() const +{ + return m_impl->taggedInnerClasses; +} + +void ClassDef::addTaggedInnerClass(ClassDef *cd) +{ + if (m_impl->taggedInnerClasses==0) + { + m_impl->taggedInnerClasses = new ClassList; + } + m_impl->taggedInnerClasses->append(cd); +} + +ClassDef *ClassDef::tagLessReference() const +{ + return m_impl->tagLessRef; +} + +void ClassDef::setTagLessReference(ClassDef *cd) +{ + m_impl->tagLessRef = cd; +} + +void ClassDef::removeMemberFromLists(MemberDef *md) +{ + MemberList *ml = m_impl->memberLists.first(); + while (ml) + { + ml->remove(md); + ml = m_impl->memberLists.next(); + } +} + +bool ClassDef::isJavaEnum() const +{ + return m_impl->isJavaEnum; +} + +bool ClassDef::isGeneric() const +{ + return m_impl->isGeneric; +} + +void ClassDef::setClassSpecifier(int spec) +{ + m_impl->spec = spec; +} + +bool ClassDef::isExtension() const +{ + QCString n = name(); + int si = n.find('('); + int ei = n.find(')'); + bool b = ei>si && n.mid(si+1,ei-si-1).stripWhiteSpace().isEmpty(); + return b; +} + + |