diff options
author | Dimitri van Heesch <dimitri@stack.nl> | 2006-10-04 20:28:41 (GMT) |
---|---|---|
committer | Dimitri van Heesch <dimitri@stack.nl> | 2006-10-04 20:28:41 (GMT) |
commit | ca720513ae89ad82fd8d8c4340271375ae1e9f64 (patch) | |
tree | d2526ce0c99b1f268769fd8bd1c56e6dda83fd7f /src | |
parent | b1dbef9886c3bf49050a5f49b9ae9d12021e4b50 (diff) | |
download | Doxygen-ca720513ae89ad82fd8d8c4340271375ae1e9f64.zip Doxygen-ca720513ae89ad82fd8d8c4340271375ae1e9f64.tar.gz Doxygen-ca720513ae89ad82fd8d8c4340271375ae1e9f64.tar.bz2 |
Release-1.4.7-20061004
Diffstat (limited to 'src')
-rw-r--r-- | src/classdef.cpp | 85 | ||||
-rw-r--r-- | src/classdef.h | 8 | ||||
-rw-r--r-- | src/code.l | 3 | ||||
-rw-r--r-- | src/commentscan.l | 278 | ||||
-rw-r--r-- | src/definition.cpp | 88 | ||||
-rw-r--r-- | src/definition.h | 14 | ||||
-rw-r--r-- | src/docparser.cpp | 11 | ||||
-rw-r--r-- | src/doxygen.cpp | 247 | ||||
-rw-r--r-- | src/doxygen.h | 6 | ||||
-rw-r--r-- | src/filedef.cpp | 20 | ||||
-rw-r--r-- | src/filedef.h | 1 | ||||
-rw-r--r-- | src/lockingptr.h | 5 | ||||
-rw-r--r-- | src/marshal.h | 12 | ||||
-rw-r--r-- | src/memberdef.cpp | 122 | ||||
-rw-r--r-- | src/memberdef.h | 11 | ||||
-rw-r--r-- | src/membergroup.cpp | 1 | ||||
-rw-r--r-- | src/memberlist.cpp | 3 | ||||
-rw-r--r-- | src/namespacedef.cpp | 32 | ||||
-rw-r--r-- | src/namespacedef.h | 2 | ||||
-rw-r--r-- | src/objcache.cpp | 33 | ||||
-rw-r--r-- | src/pre.l | 14 | ||||
-rw-r--r-- | src/translator_jp.h | 26 | ||||
-rw-r--r-- | src/util.cpp | 233 | ||||
-rw-r--r-- | src/util.h | 6 |
24 files changed, 829 insertions, 432 deletions
diff --git a/src/classdef.cpp b/src/classdef.cpp index 1470ee3..8dffbd9 100644 --- a/src/classdef.cpp +++ b/src/classdef.cpp @@ -168,6 +168,8 @@ class ClassDefImpl * groups? */ bool subGrouping; + + bool usedOnly; }; void ClassDefImpl::init(const char *defFileName, const char *name, @@ -206,6 +208,7 @@ void ClassDefImpl::init(const char *defFileName, const char *name, isTemplArg = FALSE; membersMerged = FALSE; categoryOf = 0; + usedOnly = FALSE; QCString ns; extractNamespaceName(name,className,ns); //printf("m_name=%s m_className=%s ns=%s\n",m_name.data(),m_className.data(),ns.data()); @@ -258,78 +261,11 @@ ClassDef::ClassDef( m_impl->isObjC = FALSE; m_impl->init(defFileName,name(),compoundTypeString(),fName); -#if 0 - m_compType=ct; - m_isObjC = FALSE; - QCString compoundName=compoundTypeString(); - if (fName) - { - m_fileName=stripExtension(fName); - } - else - { - m_fileName=compoundName+name(); - } - m_exampleSDict = 0; - m_inherits = 0; - m_inheritedBy = 0; - m_allMemberNameInfoSDict = 0; - m_incInfo=0; - m_tempArgs=0; - m_prot=Public; - m_nspace=0; - m_fileDef=0; - m_usesImplClassDict=0; - m_usedByImplClassDict=0; - m_usesIntfClassDict=0; - memberGroupSDict = 0; - m_innerClasses = 0; - m_subGrouping=Config_getBool("SUBGROUPING"); - m_templateInstances = 0; - m_variableInstances = 0; - m_templateMaster =0; - m_templBaseClassNames = 0; - m_artificial = FALSE; - m_isAbstract = FALSE; - m_isStatic = FALSE; - m_isTemplArg = FALSE; - m_membersMerged = FALSE; - m_categoryOf = 0; - QCString ns; - extractNamespaceName(name(),m_className,ns); - //printf("m_name=%s m_className=%s ns=%s\n",m_name.data(),m_className.data(),ns.data()); - - if (((QCString)defFileName).right(5)!=".java" && - guessSection(defFileName)==Entry::SOURCE_SEC) - { - m_isLocal=TRUE; - } - else - { - m_isLocal=FALSE; - } -#endif } // destroy the class definition ClassDef::~ClassDef() { -#if 0 - delete m_inherits; - delete m_inheritedBy; - delete m_allMemberNameInfoSDict; - delete m_exampleSDict; - delete m_usesImplClassDict; - delete m_usedByImplClassDict; - delete m_usesIntfClassDict; - delete m_incInfo; - delete memberGroupSDict; - delete m_innerClasses; - delete m_templateInstances; - delete m_variableInstances; - delete m_templBaseClassNames; - delete m_tempArgs; -#endif delete m_impl; } @@ -3080,6 +3016,11 @@ MemberDef *ClassDef::getMemberByName(const QCString &name) const 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); @@ -3321,3 +3262,13 @@ 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; +} + diff --git a/src/classdef.h b/src/classdef.h index c417244..3646d9b 100644 --- a/src/classdef.h +++ b/src/classdef.h @@ -188,6 +188,11 @@ class ClassDef : public Definition */ bool isBaseClass(ClassDef *bcd,bool followInstances,int level=0); + /*! returns TRUE iff \a md is a member of this class or of the + * the public/protected members of a base class + */ + bool isAccessibleMember(MemberDef *md); + /*! Returns a sorted dictionary with all template instances found for * this template class. Returns 0 if not a template or no instances. */ @@ -258,6 +263,8 @@ class ClassDef : public Definition ClassDef *getVariableInstance(const char *templSpec); + bool isUsedOnly() const; + //----------------------------------------------------------------------------------- // --- setters ---- //----------------------------------------------------------------------------------- @@ -290,6 +297,7 @@ class ClassDef : public Definition void addMembersToTemplateInstance(ClassDef *cd,const char *templSpec); void makeTemplateArgument(bool b=TRUE); void setCategoryOf(ClassDef *cd); + void setUsedOnly(bool b); //----------------------------------------------------------------------------------- // --- actions ---- @@ -798,7 +798,7 @@ static bool getLinkInScope(const QCString &c, // scope FileDef *fd; NamespaceDef *nd; GroupDef *gd; - //printf("Trying `%s'::`%s'\n",c.data(),m.data()); + //printf("getLinkInScope: trying `%s'::`%s'\n",c.data(),m.data()); if (getDefs(c,m,"()",md,cd,fd,nd,gd,FALSE,g_sourceFileDef) && md->isLinkable()) { @@ -851,6 +851,7 @@ static bool getLink(const char *className, CodeOutputInterface &ol, const char *text=0) { + //printf("getLink(%s,%s)\n",className,memberName); QCString m=removeRedundantWhiteSpace(memberName); QCString c=className; if (!getLinkInScope(c,m,memberName,ol,text)) diff --git a/src/commentscan.l b/src/commentscan.l index 95404b5..dc80846 100644 --- a/src/commentscan.l +++ b/src/commentscan.l @@ -107,96 +107,125 @@ static bool handlePublicSection(const QCString &s); static bool handleInherit(const QCString &); typedef bool (*DocCmdFunc)(const QCString &name); - + struct DocCmdMap { const char *cmdName; DocCmdFunc handler; + bool endsBrief; }; // map of command to handler function static DocCmdMap docCmdMap[] = { - { "brief", &handleBrief }, - { "short", &handleBrief }, - { "fn", &handleFn }, - { "var", &handleFn }, - { "typedef", &handleFn }, - { "property", &handleFn }, - { "def", &handleDef }, - { "overload", &handleOverload }, - { "enum", &handleEnum }, - { "defgroup", &handleDefGroup }, - { "addtogroup", &handleAddToGroup }, - { "weakgroup", &handleWeakGroup }, - { "namespace", &handleNamespace }, - { "package", &handlePackage }, - { "class", &handleClass }, - { "protocol", &handleProtocol }, - { "category", &handleCategory }, - { "union", &handleUnion }, - { "struct", &handleStruct }, - { "interface", &handleInterface }, - { "idlexcept", &handleIdlException }, - { "page", &handlePage }, - { "mainpage", &handleMainpage }, - { "file", &handleFile }, - { "dir", &handleDir }, - { "example", &handleExample }, - { "details", &handleDetails }, - { "name", &handleName }, - { "todo", &handleTodo }, - { "test", &handleTest }, - { "bug", &handleBug }, - { "deprecated", &handleDeprecated }, - { "xrefitem", &handleXRefItem }, - { "related", &handleRelated }, - { "relates", &handleRelated }, - { "relatedalso", &handleRelatedAlso }, - { "relatesalso", &handleRelatedAlso }, - { "refitem", &handleRefItem }, - { "subpage", &handleSubpage }, - { "section", &handleSection }, - { "subsection", &handleSection }, - { "subsubsection", &handleSection }, - { "paragraph", &handleSection }, - { "anchor", &handleAnchor }, - { "verbatim", &handleFormatBlock }, - { "latexonly", &handleFormatBlock }, - { "htmlonly", &handleFormatBlock }, - { "xmlonly", &handleFormatBlock }, - { "rtfonly", &handleFormatBlock }, - { "manonly", &handleFormatBlock }, - { "dot", &handleFormatBlock }, - { "code", &handleFormatBlock }, - { "addindex", &handleAddIndex }, - { "if", &handleIf }, - { "ifnot", &handleIfNot }, - { "elseif", &handleElseIf }, - { "else", &handleElse }, - { "endif", &handleEndIf }, - { "ingroup", &handleIngroup }, - { "nosubgrouping", &handleNoSubGrouping }, - { "showinitializer", &handleShowInitializer }, - { "hideinitializer", &handleHideInitializer }, - { "callgraph", &handleCallgraph }, - { "callergraph", &handleCallergraph }, - { "internal", &handleInternal }, - { "_linebr", &handleLineBr }, - { "static", &handleStatic }, - { "pure", &handlePure }, - { "private", &handlePrivate}, - { "privatesection", &handlePrivateSection }, - { "protected", &handleProtected }, - { "protectedsection",&handleProtectedSection }, - { "public", &handlePublic }, - { "publicsection", &handlePublicSection }, - { "inherit", &handleInherit }, - { 0, 0 } + // command name handler function ends brief description + { "brief", &handleBrief, FALSE }, + { "short", &handleBrief, FALSE }, + { "fn", &handleFn, TRUE }, + { "var", &handleFn, TRUE }, + { "typedef", &handleFn, TRUE }, + { "property", &handleFn, TRUE }, + { "def", &handleDef, TRUE }, + { "overload", &handleOverload, TRUE }, + { "enum", &handleEnum, TRUE }, + { "defgroup", &handleDefGroup, TRUE }, + { "addtogroup", &handleAddToGroup, TRUE }, + { "weakgroup", &handleWeakGroup, TRUE }, + { "namespace", &handleNamespace, TRUE }, + { "package", &handlePackage, TRUE }, + { "class", &handleClass, TRUE }, + { "protocol", &handleProtocol, TRUE }, + { "category", &handleCategory, TRUE }, + { "union", &handleUnion, TRUE }, + { "struct", &handleStruct, TRUE }, + { "interface", &handleInterface, TRUE }, + { "idlexcept", &handleIdlException, TRUE }, + { "page", &handlePage, TRUE }, + { "mainpage", &handleMainpage, TRUE }, + { "file", &handleFile, TRUE }, + { "dir", &handleDir, TRUE }, + { "example", &handleExample, TRUE }, + { "details", &handleDetails, TRUE }, + { "name", &handleName, TRUE }, + { "todo", &handleTodo, TRUE }, + { "test", &handleTest, TRUE }, + { "bug", &handleBug, TRUE }, + { "deprecated", &handleDeprecated, TRUE }, + { "xrefitem", &handleXRefItem, TRUE }, + { "related", &handleRelated, TRUE }, + { "relates", &handleRelated, TRUE }, + { "relatedalso", &handleRelatedAlso, TRUE }, + { "relatesalso", &handleRelatedAlso, TRUE }, + { "refitem", &handleRefItem, TRUE }, + { "subpage", &handleSubpage, TRUE }, + { "section", &handleSection, TRUE }, + { "subsection", &handleSection, TRUE }, + { "subsubsection", &handleSection, TRUE }, + { "paragraph", &handleSection, TRUE }, + { "anchor", &handleAnchor, TRUE }, + { "verbatim", &handleFormatBlock, TRUE }, + { "latexonly", &handleFormatBlock, FALSE }, + { "htmlonly", &handleFormatBlock, FALSE }, + { "xmlonly", &handleFormatBlock, FALSE }, + { "rtfonly", &handleFormatBlock, FALSE }, + { "manonly", &handleFormatBlock, FALSE }, + { "dot", &handleFormatBlock, TRUE }, + { "code", &handleFormatBlock, TRUE }, + { "addindex", &handleAddIndex, TRUE }, + { "if", &handleIf, FALSE }, + { "ifnot", &handleIfNot, FALSE }, + { "elseif", &handleElseIf, FALSE }, + { "else", &handleElse, FALSE }, + { "endif", &handleEndIf, FALSE }, + { "ingroup", &handleIngroup, TRUE }, + { "nosubgrouping", &handleNoSubGrouping, TRUE }, + { "showinitializer", &handleShowInitializer, TRUE }, + { "hideinitializer", &handleHideInitializer, TRUE }, + { "callgraph", &handleCallgraph, TRUE }, + { "callergraph", &handleCallergraph, TRUE }, + { "internal", &handleInternal, TRUE }, + { "_linebr", &handleLineBr, FALSE }, + { "static", &handleStatic, TRUE }, + { "pure", &handlePure, TRUE }, + { "private", &handlePrivate, TRUE }, + { "privatesection", &handlePrivateSection, TRUE }, + { "protected", &handleProtected, TRUE }, + { "protectedsection",&handleProtectedSection, TRUE }, + { "public", &handlePublic, TRUE }, + { "publicsection", &handlePublicSection, TRUE }, + { "inherit", &handleInherit, TRUE }, + { "arg", 0, TRUE }, + { "attention", 0, TRUE }, + { "author", 0, TRUE }, + { "date", 0, TRUE }, + { "dotfile", 0, TRUE }, + { "htmlinclude", 0, TRUE }, + { "image", 0, TRUE }, + { "include", 0, TRUE }, + { "includelineno", 0, TRUE }, + { "invariant", 0, TRUE }, + { "li", 0, TRUE }, + { "line", 0, TRUE }, + { "note", 0, TRUE }, + { "par", 0, TRUE }, + { "param", 0, TRUE }, + { "post", 0, TRUE }, + { "pre", 0, TRUE }, + { "remarks", 0, TRUE }, + { "return", 0, TRUE }, + { "returns", 0, TRUE }, + { "retval", 0, TRUE }, + { "sa", 0, TRUE }, + { "see", 0, TRUE }, + { "since", 0, TRUE }, + { "throw", 0, TRUE }, + { "until", 0, TRUE }, + { "verbinclude", 0, TRUE }, + { "version", 0, TRUE }, + { "warning", 0, TRUE }, + { 0, 0, FALSE } }; - - /** @brief Command mapper. * * Maps a command name (as found in a comment block) onto a @@ -205,8 +234,14 @@ static DocCmdMap docCmdMap[] = class DocCmdMapper { public: + struct Cmd + { + DocCmdFunc func; + bool endsBrief; + }; + /** maps a command name to a handler function */ - static DocCmdFunc *map(const char *name) + static Cmd *map(const char *name) { return instance()->find(name); } @@ -224,21 +259,30 @@ class DocCmdMapper return s_instance; } - DocCmdMapper() : m_map(89) + DocCmdMapper() : m_map(113) { + m_map.setAutoDelete(TRUE); DocCmdMap *p = docCmdMap; while (p->cmdName) { - m_map.insert(p->cmdName,&p->handler); + if (m_map.find(p->cmdName)!=0) + { + printf("Error: command %s already added\n",p->cmdName); + exit(1); + } + Cmd *cmd = new Cmd; + cmd->func = p->handler; + cmd->endsBrief = p->endsBrief; + m_map.insert(p->cmdName,cmd); p++; } } - DocCmdFunc *find(const char *name) + Cmd *find(const char *name) { return m_map.find(name); } - QDict<DocCmdFunc> m_map; + QDict<Cmd> m_map; static DocCmdMapper *s_instance; }; @@ -656,6 +700,17 @@ static inline void addOutput(char c) *pOutputString+=c; } +static void endBrief() +{ + if (!current->brief.stripWhiteSpace().isEmpty()) + { // only go to the detailed description if we have + // found some brief description and not just whitespace + briefEndsAtDot=FALSE; + setOutput(OutputDoc); + addOutput(yytext); + } +} + /* ----------------------------------------------------------------- */ #undef YY_INPUT #define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size); @@ -801,12 +856,14 @@ MAILADR [a-z_A-Z0-9.+\-]+"@"[a-z_A-Z0-9\-]+("."[a-z_A-Z0-9\-]+)+[a-z_A-Z0-9\-] // continue with the same input REJECT; } + /* <Comment>{DETAILEDCMD}/[^a-z_A-Z]* { // command that can end a brief description briefEndsAtDot=FALSE; setOutput(OutputDoc); // continue with the same input REJECT; } + */ <Comment>"<"{DETAILEDHTML}{ATTR}">" { // HTML command that ends a brief description setOutput(OutputDoc); // continue with the same input @@ -825,10 +882,16 @@ MAILADR [a-z_A-Z0-9.+\-]+"@"[a-z_A-Z0-9\-]+("."[a-z_A-Z0-9\-]+)+[a-z_A-Z0-9\-] } <Comment>{CMD}[a-z_A-Z]+{B}* { // potentially interesting command QCString cmdName = QCString(&yytext[1]).stripWhiteSpace(); - DocCmdFunc *funcPtr = DocCmdMapper::map(cmdName); - if (funcPtr) // special action is required + DocCmdMapper::Cmd *cmdPtr = DocCmdMapper::map(cmdName); + if (cmdPtr) // special action is required { - if ((*funcPtr)(cmdName)) + if (cmdPtr->endsBrief && !current->brief.stripWhiteSpace().isEmpty()) + { + briefEndsAtDot=FALSE; + // this command forces the end of brief description + setOutput(OutputDoc); + } + if (cmdPtr->func && cmdPtr->func(cmdName)) { // implicit split of the comment block into two // entries. Restart the next block at the start @@ -846,6 +909,12 @@ MAILADR [a-z_A-Z0-9.+\-]+"@"[a-z_A-Z0-9\-]+("."[a-z_A-Z0-9\-]+)+[a-z_A-Z0-9\-] #endif yyterminate(); } + else if (cmdPtr->func==0) + { + // command without handler, to be processed + // later by parsedoc.cpp + addOutput(yytext); + } } else // command not relevant { @@ -911,11 +980,10 @@ MAILADR [a-z_A-Z0-9.+\-]+"@"[a-z_A-Z0-9\-]+("."[a-z_A-Z0-9\-]+)+[a-z_A-Z0-9\-] addOutput(yytext); setOutput(OutputDoc); } - else if (!current->brief.stripWhiteSpace().isEmpty()) + else { // only go to the detailed description if we have // found some brief description and not just whitespace - setOutput(OutputDoc); - addOutput(yytext); + endBrief(); } lineCount(); } @@ -1853,7 +1921,7 @@ static bool handlePage(const QCString &) static bool handleMainpage(const QCString &) { bool stop=makeStructuralIndicator(Entry::MAINPAGEDOC_SEC); - current->name = "mainpage"; + if (!stop) current->name = "mainpage"; BEGIN( PageDocArg2 ); return stop; } @@ -1861,7 +1929,7 @@ static bool handleMainpage(const QCString &) static bool handleFile(const QCString &) { bool stop=makeStructuralIndicator(Entry::FILEDOC_SEC); - current->name = yyFileName; + if (!stop) current->name = yyFileName; BEGIN( FileDocArg1 ); return stop; } @@ -1869,7 +1937,7 @@ static bool handleFile(const QCString &) static bool handleDir(const QCString &) { bool stop=makeStructuralIndicator(Entry::DIRDOC_SEC); - current->name = yyFileName; + if (!stop) current->name = yyFileName; BEGIN( FileDocArg1 ); return stop; } @@ -1877,7 +1945,7 @@ static bool handleDir(const QCString &) static bool handleExample(const QCString &) { bool stop=makeStructuralIndicator(Entry::EXAMPLE_SEC); - current->name = yyFileName; + if (!stop) current->name = yyFileName; BEGIN( FileDocArg1 ); return stop; } @@ -1891,11 +1959,14 @@ static bool handleDetails(const QCString &) static bool handleName(const QCString &) { bool stop=makeStructuralIndicator(Entry::MEMBERGRP_SEC); - g_memberGroupHeader.resize(0); - BEGIN( NameParam ); - if (g_memberGroupId!=DOX_NOGROUP) // end of previous member group + if (!stop) { - closeGroup(current,yyFileName,yyLineNr); + g_memberGroupHeader.resize(0); + BEGIN( NameParam ); + if (g_memberGroupId!=DOX_NOGROUP) // end of previous member group + { + closeGroup(current,yyFileName,yyLineNr); + } } return stop; } @@ -2123,54 +2194,63 @@ static bool handleLineBr(const QCString &) static bool handleStatic(const QCString &) { + endBrief(); current->stat = TRUE; return FALSE; } static bool handlePure(const QCString &) { + endBrief(); current->virt = Pure; return FALSE; } static bool handlePrivate(const QCString &) { + endBrief(); current->protection = Private; return FALSE; } static bool handlePrivateSection(const QCString &) { + endBrief(); current->protection = protection = Private; return FALSE; } static bool handleProtected(const QCString &) { + endBrief(); current->protection = Protected; return FALSE; } static bool handleProtectedSection(const QCString &) { + endBrief(); current->protection = protection = Protected ; return FALSE; } static bool handlePublic(const QCString &) { + endBrief(); current->protection = Public; return FALSE; } static bool handlePublicSection(const QCString &) { + endBrief(); current->protection = protection = Public; return FALSE; } static bool handleInherit(const QCString &) { + endBrief(); BEGIN(InheritParam); return FALSE; } @@ -2200,7 +2280,7 @@ bool parseCommentBlock(/* in */ ParserInterface *parser, /* out */ bool &newEntryNeeded ) { - //fprintf(stderr,"parseCommentBlock() isBrief=%d isJavaDocStyle=%d lineNr=%d\n", + //printf("parseCommentBlock() isBrief=%d isJavaDocStyle=%d lineNr=%d\n", // isBrief,isJavaDocStyle,lineNr); initParser(); diff --git a/src/definition.cpp b/src/definition.cpp index b837a37..3c00fbb 100644 --- a/src/definition.cpp +++ b/src/definition.cpp @@ -34,7 +34,6 @@ #include "section.h" #include "htags.h" #include "parserintf.h" -#include "objcache.h" #include "marshal.h" #if defined(_MSC_VER) || defined(__BORLANDC__) @@ -237,14 +236,11 @@ Definition::Definition(const char *df,int dl, const char *name,const char *b, const char *d,bool isSymbol) { - m_storagePos=-1; m_name = name; m_impl = new DefinitionImpl; m_impl->init(df,dl,name,b,d); m_isSymbol = isSymbol; if (isSymbol) addToMap(name,this); - m_cacheHandle=-1; - m_flushPending = FALSE; } Definition::~Definition() @@ -258,11 +254,6 @@ Definition::~Definition() delete m_impl; m_impl=0; } - if (m_cacheHandle!=-1) - { - Doxygen::symbolCache->del(m_cacheHandle); - m_cacheHandle=-1; - } } void Definition::addSectionsToDefinition(QList<SectionInfo> *anchorList) @@ -1173,74 +1164,14 @@ void Definition::setLocalName(const QCString name) } void Definition::makeResident() const -{ - if (m_cacheHandle==-1) // not yet in cache - { - Definition *victim = 0; - Definition *that = (Definition*)this; // fake method constness - that->m_cacheHandle = Doxygen::symbolCache->add(that,(void **)&victim); - //printf("adding %s to cache, handle=%d\n",m_impl->name.data(),that->m_cacheHandle); - if (victim) // cache was full, victim was the least recently used item and has to go - { - victim->m_cacheHandle=-1; // invalidate cache handle - victim->saveToDisk(); // store the item on disk - } - else // cache not yet full - { - //printf("Adding %s to cache, handle=%d\n",m_impl->name.data(),m_cacheHandle); - } - if (m_storagePos!=-1) // already been written to disk - { - if (isLocked()) // locked in memory - { - assert(m_impl!=0); - that->m_flushPending=FALSE; // no need to flush anymore - } - else // not locked in memory - { - assert(m_impl==0); - loadFromDisk(); - } - } - } - else // already cached, make this object the most recently used. - { - assert(m_impl!=0); - //printf("Touching symbol %s\n",m_impl->name.data()); - Doxygen::symbolCache->use(m_cacheHandle); - } -} - -void Definition::saveToDisk() const { - assert(m_impl!=0); - Definition *that = (Definition *)this; - if (isLocked()) // cannot flush the item as it is locked - { - that->m_flushPending=TRUE; // flush when unlocked - } - else // ready to flush the item to disk - { - //printf("Adding %s to cache, handle=%d by replacing %s\n", - // m_impl->name.data(),m_cacheHandle,victim->m_impl->name.data()); - if (m_storagePos!=-1) - // if victim was stored on disk already and is not locked - { - // free the storage space occupied by the old store item - Doxygen::symbolStorage->release(m_storagePos); // free up space for others - } - // write a the new (possibly modified) instance to disk - flushToDisk(); - // end to write sequence (unless nothing was written due to the lock) - Doxygen::symbolStorage->end(); - } } + void Definition::flushToDisk() const { //printf("%p: Definition::flushToDisk()\n",this); Definition *that = (Definition *)this; - that->m_storagePos = Doxygen::symbolStorage->alloc(); //printf("Definition::flushToDisk(): pos=%d\n",(int)m_storagePos); marshalUInt(Doxygen::symbolStorage,START_MARKER); marshalSectionDict (Doxygen::symbolStorage,m_impl->sectionDict); @@ -1262,7 +1193,6 @@ void Definition::flushToDisk() const marshalUInt(Doxygen::symbolStorage,END_MARKER); delete that->m_impl; that->m_impl = 0; - that->m_flushPending=FALSE; } void Definition::loadFromDisk() const @@ -1271,7 +1201,6 @@ void Definition::loadFromDisk() const Definition *that = (Definition *)this; assert(m_impl==0); that->m_impl = new DefinitionImpl; - Doxygen::symbolStorage->seek(m_storagePos); uint marker = unmarshalUInt(Doxygen::symbolStorage); assert(marker==START_MARKER); m_impl->sectionDict = unmarshalSectionDict (Doxygen::symbolStorage); @@ -1294,18 +1223,3 @@ void Definition::loadFromDisk() const assert(marker==END_MARKER); } -void Definition::lock() const -{ -} - -void Definition::unlock() const -{ - if (m_flushPending && !isLocked()) - { - // write a the new (possibly modified) instance to disk - flushToDisk(); - // end to write sequence (unless nothing was written due to the lock) - Doxygen::symbolStorage->end(); - } -} - diff --git a/src/definition.h b/src/definition.h index 8f46e7a..9e2790d 100644 --- a/src/definition.h +++ b/src/definition.h @@ -279,19 +279,14 @@ class Definition : public DefinitionIntf, public LockableObj virtual void flushToDisk() const; virtual void loadFromDisk() const; - void makeResident() const; - bool isResident() const - { - return m_cacheHandle!=-1; - } + virtual void makeResident() const; + void lock() const {} + void unlock() const {} private: - void lock() const; - void unlock() const; static void addToMap(const char *name,Definition *d); static void removeFromMap(Definition *d); - void saveToDisk() const; void _setSymbolName(const QCString &name); @@ -299,10 +294,7 @@ class Definition : public DefinitionIntf, public LockableObj void _writeSourceRefList(OutputList &ol,const char *scopeName, const QCString &text,MemberSDict *members,bool); DefinitionImpl *m_impl; // internal structure holding all private data - off_t m_storagePos; // location where the item is stored in file (if impl==0) - int m_cacheHandle; QCString m_name; - bool m_flushPending; bool m_isSymbol; QCString m_symbolName; diff --git a/src/docparser.cpp b/src/docparser.cpp index 3d34aa3..0cfeb88 100644 --- a/src/docparser.cpp +++ b/src/docparser.cpp @@ -339,6 +339,7 @@ static void checkUndocumentedParams() } if (found) { + bool first=TRUE; QString errMsg= "Warning: The following parameters of "+ QString(g_memberDef->qualifiedName()) + @@ -349,7 +350,15 @@ static void checkUndocumentedParams() QString argName = g_memberDef->isDefine() ? a->type : a->name; if (!argName.isEmpty() && g_paramsFound.find(argName)==0) { - errMsg+=" parameter "+argName+"\n"; + if (!first) + { + errMsg+="\n"; + } + else + { + first=FALSE; + } + errMsg+=" parameter "+argName; } } if (g_memberDef->inheritsDocsFrom()) diff --git a/src/doxygen.cpp b/src/doxygen.cpp index 0b60c3d..695cfc9 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -879,7 +879,7 @@ static Definition *buildScopeFromQualifiedName(const QCString name,int level) static Definition *findScopeFromQualifiedName(Definition *startScope,const QCString &n, FileDef *fileScope) { - //printf("findScopeFromQualifiedName(%s,%s)\n",startScope ? startScope->name().data() : 0, n.data()); + //printf("<findScopeFromQualifiedName(%s,%s)\n",startScope ? startScope->name().data() : 0, n.data()); Definition *resultScope=startScope; if (resultScope==0) resultScope=Doxygen::globalScope; QCString scope=stripTemplateSpecifiersFromScope(n,FALSE); @@ -887,7 +887,7 @@ static Definition *findScopeFromQualifiedName(Definition *startScope,const QCStr i1=getScopeFragment(scope,0,&l1); if (i1==-1) { - //printf("no fragments!\n"); + //printf(">no fragments!\n"); return resultScope; } int p=i1+l1,l2=0,i2; @@ -895,24 +895,34 @@ static Definition *findScopeFromQualifiedName(Definition *startScope,const QCStr { QCString nestedNameSpecifier = scope.mid(i1,l1); Definition *orgScope = resultScope; + //printf(" nestedNameSpecifier=%s\n",nestedNameSpecifier.data()); resultScope = resultScope->findInnerCompound(nestedNameSpecifier); - //printf("resultScope=%p\n",resultScope); + //printf(" resultScope=%p\n",resultScope); if (resultScope==0) { - if (orgScope==Doxygen::globalScope && fileScope) + NamespaceSDict *usedNamespaces; + if (orgScope==Doxygen::globalScope && fileScope && + (usedNamespaces = fileScope->getUsedNamespaces())) // also search for used namespaces { - NamespaceSDict *usedNamespaces = fileScope->getUsedNamespaces(); - if (usedNamespaces) + NamespaceSDict::Iterator ni(*usedNamespaces); + NamespaceDef *nd; + for (ni.toFirst();((nd=ni.current()) && resultScope==0);++ni) { - NamespaceSDict::Iterator ni(*usedNamespaces); - NamespaceDef *nd; - for (ni.toFirst();((nd=ni.current()) && resultScope==0);++ni) + // restart search within the used namespace + resultScope = findScopeFromQualifiedName(nd,n,fileScope); + } + if (resultScope) + { + // for a nested class A::I in used namespace N, we get + // N::A::I while looking for A, so we should compare + // resultScope->name() against scope.left(i2+l2) + //printf(" -> result=%s scope=%s\n",resultScope->name().data(),scope.data()); + if (rightScopeMatch(resultScope->name(),scope.left(i2+l2))) { - // restart search within the used namespace - resultScope = findScopeFromQualifiedName(nd,n,fileScope); + break; } - if (resultScope) goto nextFragment; + goto nextFragment; } } @@ -934,13 +944,15 @@ static Definition *findScopeFromQualifiedName(Definition *startScope,const QCStr scope.right(scope.length()-p); resultScope = buildScopeFromQualifiedName(fqn,fqn.contains("::")); //printf("Creating scope from fqn=%s result %p\n",fqn.data(),resultScope); - //resultScope = findScopeFromQualifiedName(startScope,fqn,usedFd); - //printf("Match! resultScope=%p\n",resultScope); - if (resultScope) return resultScope; + if (resultScope) + { + //printf("> Match! resultScope=%s\n",resultScope->name().data()); + return resultScope; + } } } - //printf("name %s not found in scope %s\n",nestedNameSpecifier.data(),orgScope->name().data()); + //printf("> name %s not found in scope %s\n",nestedNameSpecifier.data(),orgScope->name().data()); return 0; } nextFragment: @@ -948,7 +960,7 @@ static Definition *findScopeFromQualifiedName(Definition *startScope,const QCStr l1=l2; p=i2+l2; } - //printf("findScopeFromQualifiedName scope %s\n",resultScope->name().data()); + //printf(">findScopeFromQualifiedName scope %s\n",resultScope->name().data()); return resultScope; } @@ -1061,9 +1073,9 @@ static void addClassToContext(EntryNav *rootNav) { warn( root->fileName,root->startLine, - "Warning: class %s already has a detailed description. " + "Warning: class %s already has a detailed description found in file %s at line %d. " "Skipping the one found here.", - fullName.data() + fullName.data(),cd->docFile().data(),cd->docLine() ); } else if (!root->doc.isEmpty()) @@ -1074,9 +1086,9 @@ static void addClassToContext(EntryNav *rootNav) { warn( root->fileName,root->startLine, - "Warning: class %s already has a brief description\n" + "Warning: class %s already has a brief description found in file %s at line %d\n" " skipping the one found here.", - fullName.data() + fullName.data(),cd->briefFile().data(),cd->briefLine() ); } else if (!root->brief.isEmpty()) @@ -1252,7 +1264,7 @@ static void resolveClassNestingRelations() cd->setOuterScope(d); warn(cd->getDefFileName(),cd->getDefLine(), "Warning: Internal inconsistency: scope for class %s not " - "found!\n",cd->name().data() + "found!",cd->name().data() ); } } @@ -1286,7 +1298,7 @@ static void resolveClassNestingRelations() cd->setOuterScope(d); warn(cd->getDefFileName(),cd->getDefLine(), "Warning: Internal inconsistency: scope for class %s not " - "found!\n",cd->name().data() + "found!",cd->name().data() ); } } @@ -1347,9 +1359,9 @@ static void buildNamespaceList(EntryNav *rootNav) { warn( root->fileName,root->startLine, - "Warning: namespace %s already has a detailed description. " + "Warning: namespace %s already has a detailed description found in file %s at line %d. " "Skipping the documentation found here.", - fullName.data()); + fullName.data(),nd->docFile().data(),nd->docLine()); } if (nd->briefDescription().isEmpty() && !root->brief.isEmpty()) { @@ -1359,9 +1371,9 @@ static void buildNamespaceList(EntryNav *rootNav) else if (!nd->briefDescription().isEmpty() && !root->brief.isEmpty()) { warn(root->fileName,root->startLine, - "Warning: namespace %s already has a brief description. " + "Warning: namespace %s already has a brief description found in file %s at line %d. " "Skipping the documentation found here.", - fullName.data() + fullName.data(),nd->docFile().data(),nd->docLine() ); } } @@ -3642,6 +3654,7 @@ static void findUsedClassesForClass(EntryNav *rootNav, usedName,ClassDef::Class); //printf("making %s a template argument!!!\n",usedCd->name().data()); usedCd->makeTemplateArgument(); + usedCd->setUsedOnly(TRUE); Doxygen::hiddenClasses->append(usedName,usedCd); } if (usedCd) @@ -3688,6 +3701,7 @@ static void findUsedClassesForClass(EntryNav *rootNav, usedCd = new ClassDef( masterCd->getDefFileName(),masterCd->getDefLine(), type,ClassDef::Class); + usedCd->setUsedOnly(TRUE); Doxygen::hiddenClasses->append(type,usedCd); } if (usedCd) @@ -5250,6 +5264,7 @@ static void findMember(EntryNav *rootNav, if (funcSpec.isEmpty()) // not a member specialization { int count=0; + int noMatchCount=0; MemberNameIterator mni(*mn); MemberDef *md; bool memFound=FALSE; @@ -5371,6 +5386,11 @@ static void findMember(EntryNav *rootNav, memFound=TRUE; } } + else if (cd && cd!=tcd) // we did find a class with the same name as cd + // but in a different namespace + { + noMatchCount++; + } } if (count==0 && rootNav->parent() && rootNav->parent()->section()==Entry::OBJCIMPL_SEC) @@ -5402,7 +5422,8 @@ static void findMember(EntryNav *rootNav, } warn(root->fileName,root->startLine, - "Warning: no matching class member found for" + "Warning: no %smatching class member found for", + noMatchCount>1 ? "uniquely " : "" ); if (root->tArgLists) @@ -5440,6 +5461,7 @@ static void findMember(EntryNav *rootNav, QCString qScope = cd->qualifiedNameWithTemplateParameters(); if (!qScope.isEmpty()) warn_cont("%s::%s",qScope.data(),md->name().data()); if (md->argsString()) warn_cont("%s",md->argsString()); + if (noMatchCount>1) warn_cont(" at line %d of file %s",md->getDefLine(),md->getDefFileName().data()); warn_cont("\n"); } } @@ -6146,6 +6168,7 @@ static void findEnums(EntryNav *rootNav) } addMemberToGroups(root,md); +#if 0 if (rootNav->children()) { EntryNavListIterator eli(*rootNav->children()); @@ -6209,6 +6232,7 @@ static void findEnums(EntryNav *rootNav) } } } +#endif } rootNav->releaseEntry(); @@ -6220,6 +6244,160 @@ static void findEnums(EntryNav *rootNav) } //---------------------------------------------------------------------- + +static void addEnumValuesToEnums(EntryNav *rootNav) +{ + if (rootNav->section()==Entry::ENUM_SEC) + // non anonymous enumeration + { + rootNav->loadEntry(g_storage); + Entry *root = rootNav->entry(); + + ClassDef *cd=0; + FileDef *fd=0; + NamespaceDef *nd=0; + MemberNameSDict *mnsd=0; + bool isGlobal; + bool isRelated=FALSE; + //printf("Found enum with name `%s' relates=%s\n",root->name.data(),root->relates.data()); + int i; + + QCString name; + QCString scope; + + if ((i=root->name.findRev("::"))!=-1) // scope is specified + { + scope=root->name.left(i); // extract scope + name=root->name.right(root->name.length()-i-2); // extract name + if ((cd=getClass(scope))==0) nd=getResolvedNamespace(scope); + } + else // no scope, check the scope in which the docs where found + { + if (( rootNav->parent()->section() & Entry::SCOPE_MASK ) + && !rootNav->parent()->name().isEmpty() + ) // found enum docs inside a compound + { + scope=rootNav->parent()->name(); + if ((cd=getClass(scope))==0) nd=getResolvedNamespace(scope); + } + name=root->name; + } + + if (!root->relates.isEmpty()) + { // related member, prefix user specified scope + isRelated=TRUE; + if (getClass(root->relates)==0 && !scope.isEmpty()) + scope=mergeScopes(scope,root->relates); + else + scope=root->relates.copy(); + if ((cd=getClass(scope))==0) nd=getResolvedNamespace(scope); + } + + if (cd && !name.isEmpty()) // found a enum inside a compound + { + //printf("Enum `%s'::`%s'\n",cd->name(),name.data()); + fd=0; + mnsd=Doxygen::memberNameSDict; + isGlobal=FALSE; + } + else if (nd && !nd->name().isEmpty() && nd->name().at(0)!='@') // found enum inside namespace + { + mnsd=Doxygen::functionNameSDict; + isGlobal=TRUE; + } + else // found a global enum + { + fd=rootNav->fileDef(); + mnsd=Doxygen::functionNameSDict; + isGlobal=TRUE; + } + + if (!name.isEmpty()) + { + MemberName *mn = mnsd->find(name); + if (mn) + { + MemberNameIterator mni(*mn); + MemberDef *md; + for (mni.toFirst(); (md=mni.current()) ; ++mni) + { + if (md->isEnumerate() && rootNav->children()) + { + EntryNavListIterator eli(*rootNav->children()); + EntryNav *e; + for (;(e=eli.current());++eli) + { + //printf("e->name=%s isRelated=%d\n",e->name.data(),isRelated); + MemberName *fmn=0; + MemberNameSDict *emnsd = isRelated ? Doxygen::functionNameSDict : mnsd; + if (!e->name().isEmpty() && (fmn=(*emnsd)[e->name()])) + // get list of members with the same name as the field + { + MemberNameIterator fmni(*fmn); + MemberDef *fmd; + for (fmni.toFirst(); (fmd=fmni.current()) ; ++fmni) + { + if (fmd->isEnumValue()) + { + //printf("found enum value with same name\n"); + if (nd && !nd->name().isEmpty() && nd->name().at(0)!='@') + { + NamespaceDef *fnd=fmd->getNamespaceDef(); + if (fnd==nd) // enum value is inside a namespace + { + md->insertEnumField(fmd); + fmd->setEnumScope(md); + } + } + else if (isGlobal) + { + FileDef *ffd=fmd->getFileDef(); + if (ffd==fd) // enum value has file scope + { + md->insertEnumField(fmd); + fmd->setEnumScope(md); + } + } + else if (isRelated && cd) // reparent enum value to + // match the enum's scope + { + md->insertEnumField(fmd); // add field def to list + fmd->setEnumScope(md); // cross ref with enum name + fmd->setEnumClassScope(cd); // cross ref with enum name + fmd->setOuterScope(cd); + fmd->makeRelated(); + cd->insertMember(fmd); + } + else + { + ClassDef *fcd=fmd->getClassDef(); + if (fcd==cd) // enum value is inside a class + { + //printf("Inserting enum field %s in enum scope %s\n", + // fmd->name().data(),md->name().data()); + md->insertEnumField(fmd); // add field def to list + fmd->setEnumScope(md); // cross ref with enum name + } + } + } + } + } + } + } + } + } + } + + rootNav->releaseEntry(); + } + else + { + RECURSE_ENTRYTREE(addEnumValuesToEnums,rootNav); + } +} + + +//---------------------------------------------------------------------- // find the documentation blocks for the enumerations static void findEnumDocumentation(EntryNav *rootNav) @@ -7203,7 +7381,6 @@ static void buildPageList(EntryNav *rootNav) { if (rootNav->section() == Entry::PAGEDOC_SEC) { - //printf("buildPageList %s\n",root->name.data()); rootNav->loadEntry(g_storage); Entry *root = rootNav->entry(); @@ -8801,8 +8978,8 @@ void parseInput() **************************************************************************/ Doxygen::symbolMap = new QDict<DefinitionIntf>(1000); - Doxygen::symbolCache = new ObjCache(15); // 15 -> room for 32768 elements, - // ~1.0 MByte "overhead" + Doxygen::symbolCache = new ObjCache(16); // 16 -> room for 65536 elements, + // ~2.0 MByte "overhead" Doxygen::symbolStorage = new Store; if (Doxygen::symbolStorage->open(outputDirectory+"/doxygen_objdb.tmp")==-1) @@ -9182,6 +9359,9 @@ void parseInput() msg("Building example list...\n"); buildExampleList(rootNav); + msg("Searching for enumerations...\n"); + findEnums(rootNav); + msg("Searching for documented variables...\n"); buildVarList(rootNav); @@ -9210,10 +9390,9 @@ void parseInput() computeClassRelations(); classEntries.clear(); - msg("Searching for enumerations...\n"); - findEnums(rootNav); + addEnumValuesToEnums(rootNav); findEnumDocumentation(rootNav); - + msg("Searching for member function documentation...\n"); findObjCMethodDefinitions(rootNav); findMemberDocumentation(rootNav); // may introduce new members ! diff --git a/src/doxygen.h b/src/doxygen.h index 43ee18b..92c09ba 100644 --- a/src/doxygen.h +++ b/src/doxygen.h @@ -59,11 +59,13 @@ class StringDict : public QDict<QCString> struct LookupInfo { - LookupInfo(ClassDef *cd=0,MemberDef *td=0,QCString ts="") - : classDef(cd), typeDef(td), templSpec(ts) {} + LookupInfo() : classDef(0), typeDef(0) {} + LookupInfo(ClassDef *cd,MemberDef *td,QCString ts,QCString rt) + : classDef(cd), typeDef(td), templSpec(ts),resolvedType(rt) {} ClassDef *classDef; MemberDef *typeDef; QCString templSpec; + QCString resolvedType; }; extern QCString spaces; diff --git a/src/filedef.cpp b/src/filedef.cpp index c43cd72..7214a56 100644 --- a/src/filedef.cpp +++ b/src/filedef.cpp @@ -93,6 +93,7 @@ FileDef::FileDef(const char *p,const char *nm, m_isJava = name().right(5)==".java"; memberGroupSDict = 0; acquireFileVersion(); + m_subGrouping=Config_getBool("SUBGROUPING"); } /*! destroy the file definition */ @@ -491,7 +492,8 @@ void FileDef::writeDocumentation(OutputList &ol) MemberGroup *mg; for (;(mg=mgli.current());++mgli) { - if (mg->header()!="[NOHEADER]") + if ((!mg->allMembersInSameSection() || !m_subGrouping) + && mg->header()!="[NOHEADER]") { mg->writeDeclarations(ol,0,0,this,0); } @@ -689,6 +691,21 @@ void FileDef::addMembersToMemberGroup() ::addMembersToMemberGroup(ml,&memberGroupSDict,this); } } + + // add members inside sections to their groups + if (memberGroupSDict) + { + MemberGroupSDict::Iterator mgli(*memberGroupSDict); + MemberGroup *mg; + for (;(mg=mgli.current());++mgli) + { + if (mg->allMembersInSameSection() && m_subGrouping) + { + //printf("----> addToDeclarationSection(%s)\n",mg->header().data()); + mg->addToDeclarationSection(); + } + } + } } /*! Adds member definition \a md to the list of all members of this file */ @@ -1363,6 +1380,7 @@ void FileDef::addMemberToList(MemberList::ListType lt,MemberDef *md) { ml->setInFile(TRUE); } + if (ml->listType()&MemberList::declarationLists) md->setSectionList(this,ml); } MemberList *FileDef::getMemberList(MemberList::ListType lt) const diff --git a/src/filedef.h b/src/filedef.h index c794b70..15554e2 100644 --- a/src/filedef.h +++ b/src/filedef.h @@ -214,6 +214,7 @@ class FileDef : public Definition MemberGroupSDict *memberGroupSDict; NamespaceSDict *namespaceSDict; ClassSDict *classSDict; + bool m_subGrouping; }; diff --git a/src/lockingptr.h b/src/lockingptr.h index e981056..1936bec 100644 --- a/src/lockingptr.h +++ b/src/lockingptr.h @@ -37,20 +37,15 @@ class LockableObj /*! Returns TRUE if the object is currently locked. */ bool isLocked() const { return m_lockCount>0; } -#ifndef _WIN32 protected: -#endif /*! Called when the object is locked. */ virtual void lock() const = 0; /*! Called when the object is unlocked. */ virtual void unlock() const = 0; -#ifndef _WIN32 // HACK: VC++ 6.0 does not understand friend template classes. private: template<class T> friend class LockingPtr; -#endif - int m_lockCount; }; diff --git a/src/marshal.h b/src/marshal.h index dd751fa..864e8b3 100644 --- a/src/marshal.h +++ b/src/marshal.h @@ -7,17 +7,17 @@ #include "store.h" class ArgumentList; -class BaseInfo; -class Grouping; -class SectionInfo; -class ListItemInfo; +struct BaseInfo; +struct Grouping; +struct SectionInfo; +struct ListItemInfo; class QCString; class QGString; class SectionDict; class MemberSDict; class GroupList; -class BodyInfo; -class DocInfo; +struct BodyInfo; +struct DocInfo; class MemberList; class ExampleSDict; diff --git a/src/memberdef.cpp b/src/memberdef.cpp index 9ae8123..976fdc8 100644 --- a/src/memberdef.cpp +++ b/src/memberdef.cpp @@ -37,6 +37,7 @@ #include "searchindex.h" #include "parserintf.h" #include "marshal.h" +#include "objcache.h" #define START_MARKER 0x4D454D5B // MEM[ #define END_MARKER 0x4D454D5D // MEM] @@ -367,6 +368,7 @@ class MemberDefImpl bool isTypedefValCached; ClassDef *cachedTypedefValue; QCString cachedTypedefTemplSpec; + QCString cachedResolvedType; // inbody documentation int inbodyLine; @@ -574,8 +576,11 @@ MemberDef::MemberDef(const char *df,int dl, const ArgumentList *tal,const ArgumentList *al ) : Definition(df,dl,removeRedundantWhiteSpace(na)) { + m_storagePos=-1; + m_cacheHandle=-1; m_impl = new MemberDefImpl; m_impl->init(this,t,a,e,p,v,s,r,mt,tal,al); + m_flushPending = FALSE; #if 0 //printf("++++++ MemberDef(%s file=%s,line=%d static=%d) ++++++ \n", @@ -697,6 +702,11 @@ MemberDef::MemberDef(const char *df,int dl, MemberDef::~MemberDef() { delete m_impl; + if (m_cacheHandle!=-1) + { + Doxygen::symbolCache->del(m_cacheHandle); + m_cacheHandle=-1; + } } void MemberDef::setReimplements(MemberDef *md) @@ -774,7 +784,10 @@ QCString MemberDef::getOutputFileBase() const makeResident(); static bool separateMemberPages = Config_getBool("SEPARATE_MEMBER_PAGES"); QCString baseName; - if (m_impl->explicitOutputFileBase) + //printf("Member: %s: templateMaster=%p group=%p classDef=%p nspace=%p fileDef=%p\n", + // name().data(),m_impl->templateMaster,m_impl->group,m_impl->classDef, + // m_impl->nspace,m_impl->fileDef); + if (!m_impl->explicitOutputFileBase.isEmpty()) { return m_impl->explicitOutputFileBase; } @@ -805,6 +818,7 @@ QCString MemberDef::getOutputFileBase() const "Warning: Internal inconsistency: member %s does not belong to any" " container!",name().data() ); + exit(1); return "dummy"; } else if (separateMemberPages) @@ -3375,6 +3389,12 @@ QCString MemberDef::getCachedTypedefTemplSpec() const return m_impl->cachedTypedefTemplSpec; } +QCString MemberDef::getCachedResolvedTypedef() const +{ + makeResident(); + return m_impl->cachedResolvedType; +} + MemberDef *MemberDef::memberDefinition() const { makeResident(); @@ -3591,21 +3611,24 @@ void MemberDef::setMemberDeclaration(MemberDef *md) m_impl->memDec=md; } -void MemberDef::cacheTypedefVal(ClassDef*val, QCString const& templSpec) +void MemberDef::cacheTypedefVal(ClassDef*val, const QCString & templSpec, const QCString &resolvedType) { makeResident(); m_impl->isTypedefValCached=TRUE; m_impl->cachedTypedefValue=val; m_impl->cachedTypedefTemplSpec=templSpec; + m_impl->cachedResolvedType=resolvedType; } void MemberDef::flushToDisk() const { + if (isLocked()) return; + MemberDef *that = (MemberDef*)this; + that->m_storagePos = Doxygen::symbolStorage->alloc(); //printf("%p: MemberDef::flushToDisk()\n",this); // write the definition base class member variables to disk Definition::flushToDisk(); - if (isLocked()) return; //printf("%p: flushing specific part\n",this); // write the memberdef member variables to disk @@ -3658,6 +3681,7 @@ void MemberDef::flushToDisk() const marshalBool (Doxygen::symbolStorage,m_impl->isTypedefValCached); marshalObjPointer (Doxygen::symbolStorage,m_impl->cachedTypedefValue); marshalQCString (Doxygen::symbolStorage,m_impl->cachedTypedefTemplSpec); + marshalQCString (Doxygen::symbolStorage,m_impl->cachedResolvedType); marshalInt (Doxygen::symbolStorage,m_impl->inbodyLine); marshalQCString (Doxygen::symbolStorage,m_impl->inbodyFile); marshalQCString (Doxygen::symbolStorage,m_impl->inbodyDocs); @@ -3682,25 +3706,27 @@ void MemberDef::flushToDisk() const marshalUInt(Doxygen::symbolStorage,END_MARKER); // function doesn't modify the object conceptually but compiler doesn't know this. - MemberDef *that = (MemberDef *)this; delete that->m_impl; that->m_impl=0; + that->m_flushPending=FALSE; } void MemberDef::loadFromDisk() const { //printf("%p: MemberDef::loadFromDisk()\n",this); - Definition::loadFromDisk(); - + MemberDef *that = (MemberDef *)this; if (isLocked()) { assert(m_impl!=0); return; } assert(m_impl==0); + + Doxygen::symbolStorage->seek(m_storagePos); + Definition::loadFromDisk(); + //printf("%p: loading specific part\n",this); - MemberDef *that = (MemberDef *)this; that->m_impl = new MemberDefImpl; uint marker = unmarshalUInt(Doxygen::symbolStorage); @@ -3753,6 +3779,7 @@ void MemberDef::loadFromDisk() const m_impl->isTypedefValCached = unmarshalBool (Doxygen::symbolStorage); m_impl->cachedTypedefValue = (ClassDef*)unmarshalObjPointer (Doxygen::symbolStorage); m_impl->cachedTypedefTemplSpec = unmarshalQCString (Doxygen::symbolStorage); + m_impl->cachedResolvedType = unmarshalQCString (Doxygen::symbolStorage); m_impl->inbodyLine = unmarshalInt (Doxygen::symbolStorage); m_impl->inbodyFile = unmarshalQCString (Doxygen::symbolStorage); m_impl->inbodyDocs = unmarshalQCString (Doxygen::symbolStorage); @@ -3778,3 +3805,84 @@ void MemberDef::loadFromDisk() const assert(marker==END_MARKER); } +void MemberDef::makeResident() const +{ + if (m_cacheHandle==-1) // not yet in cache + { + MemberDef *victim = 0; + MemberDef *that = (MemberDef*)this; // fake method constness + that->m_cacheHandle = Doxygen::symbolCache->add(that,(void **)&victim); + //printf("adding %s to cache, handle=%d\n",m_impl->name.data(),that->m_cacheHandle); + if (victim) // cache was full, victim was the least recently used item and has to go + { + victim->m_cacheHandle=-1; // invalidate cache handle + victim->saveToDisk(); // store the item on disk + } + else // cache not yet full + { + //printf("Adding %s to cache, handle=%d\n",m_impl->name.data(),m_cacheHandle); + } + if (m_storagePos!=-1) // already been written to disk + { + if (isLocked()) // locked in memory + { + assert(m_impl!=0); + that->m_flushPending=FALSE; // no need to flush anymore + } + else // not locked in memory + { + assert(m_impl==0); + loadFromDisk(); + } + } + } + else // already cached, make this object the most recently used. + { + assert(m_impl!=0); + //printf("Touching symbol %s\n",m_impl->name.data()); + Doxygen::symbolCache->use(m_cacheHandle); + } +} + +void MemberDef::saveToDisk() const +{ + assert(m_impl!=0); + MemberDef *that = (MemberDef *)this; + if (isLocked()) // cannot flush the item as it is locked + { + that->m_flushPending=TRUE; // flush when unlocked + } + else // ready to flush the item to disk + { + //printf("Adding %s to cache, handle=%d by replacing %s\n", + // m_impl->name.data(),m_cacheHandle,victim->m_impl->name.data()); + if (m_storagePos!=-1) + // if victim was stored on disk already and is not locked + { + // free the storage space occupied by the old store item + Doxygen::symbolStorage->release(m_storagePos); // free up space for others + } + // write a the new (possibly modified) instance to disk + flushToDisk(); + // end to write sequence (unless nothing was written due to the lock) + Doxygen::symbolStorage->end(); + } +} + +void MemberDef::lock() const +{ +} + +void MemberDef::unlock() const +{ + if (m_flushPending && !isLocked()) + { + // write a the new (possibly modified) instance to disk + flushToDisk(); + // end to write sequence (unless nothing was written due to the lock) + Doxygen::symbolStorage->end(); + } +} + + + diff --git a/src/memberdef.h b/src/memberdef.h index 52ee455..f0935a4 100644 --- a/src/memberdef.h +++ b/src/memberdef.h @@ -209,6 +209,7 @@ class MemberDef : public Definition bool isTypedefValCached() const; ClassDef *getCachedTypedefVal() const; QCString getCachedTypedefTemplSpec() const; + QCString getCachedResolvedTypedef() const; MemberDef *memberDefinition() const; MemberDef *memberDeclaration() const; @@ -294,7 +295,7 @@ class MemberDef : public Definition void setDocsForDefinition(bool b); void setGroupAlias(MemberDef *md); - void cacheTypedefVal(ClassDef *val,const QCString &templSpec); + void cacheTypedefVal(ClassDef *val,const QCString &templSpec,const QCString &resolvedType); void invalidateTypedefValCache(); // declaration <-> definition relation @@ -330,6 +331,11 @@ class MemberDef : public Definition void flushToDisk() const; void loadFromDisk() const; private: + void lock() const; + void unlock() const; + void saveToDisk() const; + void makeResident() const; + static int s_indentLevel; // disable copying of member defs MemberDef(const MemberDef &); @@ -340,6 +346,9 @@ class MemberDef : public Definition bool onlyText=FALSE); MemberDefImpl *m_impl; + int m_cacheHandle; + off_t m_storagePos; // location where the item is stored in file (if impl==0) + bool m_flushPending; }; #endif diff --git a/src/membergroup.cpp b/src/membergroup.cpp index 786b38f..ba599da 100644 --- a/src/membergroup.cpp +++ b/src/membergroup.cpp @@ -133,6 +133,7 @@ void MemberGroup::addToDeclarationSection() { if (inDeclSection) { + //printf("Adding group %p to list %p\n",this,inDeclSection); inDeclSection->addMemberGroup(this); } } diff --git a/src/memberlist.cpp b/src/memberlist.cpp index 78509bb..218bbd3 100644 --- a/src/memberlist.cpp +++ b/src/memberlist.cpp @@ -316,7 +316,8 @@ void MemberList::writeDeclarations(OutputList &ol, //printf("----- writeDeclaration() ----\n"); countDecMembers(showEnumValues); // count member not in group if (numDecMembers()==0) return; - //printf("MemberList::writeDeclaration(title=`%s',subtitle=`%s')=%d\n",title,subtitle,numDecMembers()); + //printf("%p: MemberList::writeDeclaration(title=`%s',subtitle=`%s')=%d\n", + // this,title,subtitle,numDecMembers()); if (title) { ol.startMemberHeader(); diff --git a/src/namespacedef.cpp b/src/namespacedef.cpp index e216081..1cbe197 100644 --- a/src/namespacedef.cpp +++ b/src/namespacedef.cpp @@ -51,6 +51,7 @@ NamespaceDef::NamespaceDef(const char *df,int dl, memberGroupSDict = new MemberGroupSDict; memberGroupSDict->setAutoDelete(TRUE); visited=FALSE; + m_subGrouping=Config_getBool("SUBGROUPING"); } NamespaceDef::~NamespaceDef() @@ -151,6 +152,21 @@ void NamespaceDef::addMembersToMemberGroup() ::addMembersToMemberGroup(ml,&memberGroupSDict,this); } } + + // add members inside sections to their groups + if (memberGroupSDict) + { + MemberGroupSDict::Iterator mgli(*memberGroupSDict); + MemberGroup *mg; + for (;(mg=mgli.current());++mgli) + { + if (mg->allMembersInSameSection() && m_subGrouping) + { + //printf("----> addToDeclarationSection(%s)\n",mg->header().data()); + mg->addToDeclarationSection(); + } + } + } } void NamespaceDef::insertMember(MemberDef *md) @@ -316,11 +332,18 @@ void NamespaceDef::writeDocumentation(OutputList &ol) namespaceSDict->writeDeclaration(ol,TRUE); /* write user defined member groups */ - MemberGroupSDict::Iterator mgli(*memberGroupSDict); - MemberGroup *mg; - for (;(mg=mgli.current());++mgli) + if (memberGroupSDict) { - mg->writeDeclarations(ol,0,this,0,0); + MemberGroupSDict::Iterator mgli(*memberGroupSDict); + MemberGroup *mg; + for (;(mg=mgli.current());++mgli) + { + if ((!mg->allMembersInSameSection() || !m_subGrouping) + && mg->header()!="[NOHEADER]") + { + mg->writeDeclarations(ol,0,this,0,0); + } + } } writeMemberDeclarations(ol,MemberList::decDefineMembers,theTranslator->trDefines()); @@ -676,6 +699,7 @@ void NamespaceDef::addMemberToList(MemberList::ListType lt,MemberDef *md) ml->inSort(md); else ml->append(md); + if (ml->listType()&MemberList::declarationLists) md->setSectionList(this,ml); } MemberList *NamespaceDef::getMemberList(MemberList::ListType lt) const diff --git a/src/namespacedef.h b/src/namespacedef.h index a1355d5..b720912 100644 --- a/src/namespacedef.h +++ b/src/namespacedef.h @@ -106,7 +106,7 @@ class NamespaceDef : public Definition MemberGroupSDict *memberGroupSDict; ClassSDict *classSDict; NamespaceSDict *namespaceSDict; - + bool m_subGrouping; }; class NamespaceList : public QList<NamespaceDef> diff --git a/src/objcache.cpp b/src/objcache.cpp index c192504..63e7eb7 100644 --- a/src/objcache.cpp +++ b/src/objcache.cpp @@ -176,16 +176,31 @@ void ObjCache::moveToFront(int index) unsigned int ObjCache::hash(void *addr) { - // Thomas Wang's 32 bit Mix Function + static bool isPtr64 = sizeof(addr)==8 && sizeof(long)==8; - // TODO: what if sizeof(void*)!=4 ? - unsigned int key = (unsigned int)addr; - key += ~(key << 15); - key ^= (key >> 10); - key += (key << 3); - key ^= (key >> 6); - key += ~(key << 11); - key ^= (key >> 16); + unsigned long key = (unsigned long)addr; + if (isPtr64) + { + // Thomas Wang's 64 bit Mix Function + key += ~(key << 32); + key ^= (key >> 22); + key += ~(key << 13); + key ^= (key >> 8); + key += (key << 3); + key ^= (key >> 15); + key += ~(key << 27); + key ^= (key >> 31); + } + else + { + // Thomas Wang's 32 bit Mix Function + key += ~(key << 15); + key ^= (key >> 10); + key += (key << 3); + key ^= (key >> 6); + key += ~(key << 11); + key ^= (key >> 16); + } return key & (m_size-1); } @@ -69,6 +69,7 @@ struct FileState static int g_yyLineNr = 1; static QCString g_yyFileName; static FileDef *g_yyFileDef; +static FileDef *g_inputFileDef; static int g_ifcount = 0; static QStrList *g_pathList = 0; static QStack<FileState> g_includeStack; @@ -1043,17 +1044,13 @@ void addDefine() } md->setInitializer(g_defLitText.stripWhiteSpace()); - //md->setDefFile(g_yyFileName); - //md->setDefLine(g_yyLineNr); - md->setFileDef(g_yyFileDef); + md->setFileDef(g_inputFileDef); md->setDefinition("#define "+g_defName); MemberName *mn=Doxygen::functionNameSDict->find(g_defName); if (mn==0) { mn = new MemberName(g_defName); - //Doxygen::functionNameList.append(mn); - //Doxygen::functionNameDict.insert(g_defName,mn); Doxygen::functionNameSDict->append(g_defName,mn); } mn->append(md); @@ -1790,6 +1787,12 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) g_insideComment=FALSE; BEGIN(DefineText); } +<DefineArg>"..." { // Variadic macro + g_defVarArgs = TRUE; + g_defArgsStr+=yytext; + g_argDict->insert("__VA_ARGS__",new int(g_defArgs)); + g_defArgs++; + } <DefineArg>{ID}{B}*("..."?) { //printf("Define addArg(%s)\n",yytext); QCString argName=yytext; @@ -2372,6 +2375,7 @@ void preprocessFile(const char *fileName,BufStr &output) g_level = 0; g_ifcount = 0; setFileName(fileName); + g_inputFileDef = g_yyFileDef; BEGIN( Start ); g_lastGuardName.resize(0); diff --git a/src/translator_jp.h b/src/translator_jp.h index 9ab9fbc..01aec89 100644 --- a/src/translator_jp.h +++ b/src/translator_jp.h @@ -29,7 +29,7 @@ #ifndef TRANSLATOR_JP_H #define TRANSLATOR_JP_H -class TranslatorJapanese : public TranslatorAdapter_1_4_6 +class TranslatorJapanese : public Translator { private: /*! The decode() can change euc into sjis */ @@ -454,12 +454,6 @@ class TranslatorJapanese : public TranslatorAdapter_1_4_6 { return decode("列挙型"); } /*! This is used in the documentation of a file/namespace before the list - * of documentation blocks for enumeration values - */ - virtual QCString trEnumerationValueDocumentation() - { return decode("列挙型の値"); } - - /*! This is used in the documentation of a file/namespace before the list * of documentation blocks for functions */ virtual QCString trFunctionDocumentation() @@ -1562,5 +1556,23 @@ class TranslatorJapanese : public TranslatorAdapter_1_4_6 "利便性のために用意されています。" "元の関数との違いは引き数のみです。"); } + +////////////////////////////////////////////////////////////////////////// +// new since 1.4.6 +////////////////////////////////////////////////////////////////////////// + + /*! This is used to introduce a caller (or called-by) graph */ + virtual QCString trCallerGraph() + { + // return "Here is the caller graph for this function:"; + return "呼出しグラフ:"; + } + + /*! This is used in the documentation of a file/namespace before the list + * of documentation blocks for enumeration values + */ + virtual QCString trEnumerationValueDocumentation() + { return "列挙型"; } + }; #endif diff --git a/src/util.cpp b/src/util.cpp index c9993a1..0ae6fa2 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -594,7 +594,8 @@ ClassDef *getResolvedClassRec(Definition *scope, FileDef *fileScope, const char *n, MemberDef **pTypeDef, - QCString *pTemplSpec + QCString *pTemplSpec, + QCString *pResolvedType ); int isAccessibleFromWithExpScope(Definition *scope,FileDef *fileScope,Definition *item, const QCString &explicitScopePart); @@ -607,7 +608,8 @@ int isAccessibleFromWithExpScope(Definition *scope,FileDef *fileScope,Definition * Example: typedef int T; will return 0, since "int" is not a class. */ ClassDef *newResolveTypedef(FileDef *fileScope,MemberDef *md, - MemberDef **pMemType,QCString *pTemplSpec) + MemberDef **pMemType,QCString *pTemplSpec, + QCString *pResolvedType) { //printf("newResolveTypedef(md=%p,cachedVal=%p)\n",md,md->getCachedTypedefVal()); bool isCached = md->isTypedefValCached(); // value already cached @@ -616,7 +618,8 @@ ClassDef *newResolveTypedef(FileDef *fileScope,MemberDef *md, //printf("Already cached %s->%s\n", // md->name().data(), // md->getCachedTypedefVal()?md->getCachedTypedefVal()->name().data():"<none>"); - if (pTemplSpec) *pTemplSpec = md->getCachedTypedefTemplSpec(); + if (pTemplSpec) *pTemplSpec = md->getCachedTypedefTemplSpec(); + if (pResolvedType) *pResolvedType = md->getCachedResolvedTypedef(); return md->getCachedTypedefVal(); } QCString qname = md->qualifiedName(); @@ -625,29 +628,33 @@ ClassDef *newResolveTypedef(FileDef *fileScope,MemberDef *md, g_resolvedTypedefs.insert(qname,md); // put on the trace list QCString type = md->typeString(); // get the "value" of the typedef - int ip=type.length()-1; // remove * and & at the end + QCString typedefValue = type; + int tl=type.length(); + int ip=tl-1; // remove * and & at the end while (ip>=0 && (type.at(ip)=='*' || type.at(ip)=='&' || type.at(ip)==' ')) { ip--; } type=type.left(ip+1); - type.stripPrefix("const "); // strip leading "const" - type.stripPrefix("struct "); // strip leading "struct" - type.stripPrefix("union "); // strip leading "union" - type=type.stripWhiteSpace(); // strip leading and trailing whitespace + int sp=0; + if (type.stripPrefix("const ")) sp+=6; // strip leading "const" + if (type.stripPrefix("struct ")) sp+=7; // strip leading "struct" + if (type.stripPrefix("union ")) sp+=6; // strip leading "union" + while (sp<tl && type.at(sp)==' ') sp++; MemberDef *memTypeDef = 0; ClassDef *result = getResolvedClassRec(md->getOuterScope(), - fileScope,type,&memTypeDef,0); - // if type is a typedef than return what it resolves to. + fileScope,type,&memTypeDef,0,pResolvedType); + // if type is a typedef then return what it resolves to. if (memTypeDef && memTypeDef->isTypedef()) { - return newResolveTypedef(fileScope,memTypeDef,pMemType,pTemplSpec); + result=newResolveTypedef(fileScope,memTypeDef,pMemType,pTemplSpec); + goto done; } else if (memTypeDef && memTypeDef->isEnumerate() && pMemType) { *pMemType = memTypeDef; } - + //printf("type=%s result=%p\n",type.data(),result); if (result==0) { @@ -656,8 +663,9 @@ ClassDef *newResolveTypedef(FileDef *fileScope,MemberDef *md, int i=type.find('<'); if (si==-1 && i!=-1) // typedef of a template => try the unspecialized version { - *pTemplSpec = type.mid(i); - result = getResolvedClassRec(md->getOuterScope(),fileScope,type.left(i),0,0); + if (pTemplSpec) *pTemplSpec = type.mid(i); + result = getResolvedClassRec(md->getOuterScope(),fileScope, + type.left(i),0,0,pResolvedType); } else if (si!=-1) // A::B { @@ -671,7 +679,25 @@ ClassDef *newResolveTypedef(FileDef *fileScope,MemberDef *md, if (pTemplSpec) *pTemplSpec = type.mid(i); } result = getResolvedClassRec(md->getOuterScope(),fileScope, - stripTemplateSpecifiersFromScope(type.left(i),FALSE),0,0); + stripTemplateSpecifiersFromScope(type.left(i),FALSE),0,0, + pResolvedType); + } + + if (result) ip=si+sp+1; + } + +done: + if (pResolvedType) + { + if (result) + { + *pResolvedType=result->qualifiedName(); + if (sp>0) pResolvedType->prepend(typedefValue.left(sp)); + if (ip<tl-1) pResolvedType->append(typedefValue.right(tl-ip-1)); + } + else + { + *pResolvedType=typedefValue; } } @@ -682,14 +708,10 @@ ClassDef *newResolveTypedef(FileDef *fileScope,MemberDef *md, { //printf("setting cached typedef %p in result %p\n",md,result); //printf("==> %s (%s,%d)\n",result->name().data(),result->getDefFileName().data(),result->getDefLine()); - if (pTemplSpec) - { - md->cacheTypedefVal(result,*pTemplSpec); - } - else - { - md->cacheTypedefVal(result,""); - } + md->cacheTypedefVal(result, + pTemplSpec ? *pTemplSpec : QCString(), + pResolvedType ? *pResolvedType : QCString() + ); } g_resolvedTypedefs.remove(qname); // remove from the trace list @@ -914,7 +936,15 @@ int isAccessibleFrom(Definition *scope,FileDef *fileScope,Definition *item) int result=0; // assume we found it int i; - if (item->getOuterScope()==scope) + Definition *itemScope=item->getOuterScope(); + + if (itemScope==scope || + (item->definitionType()==Definition::TypeMember && + itemScope && itemScope->definitionType()==Definition::TypeClass && + scope->definitionType()==Definition::TypeClass && + ((ClassDef*)scope)->isAccessibleMember((MemberDef *)item) + ) + ) { //printf("> found it\n"); } @@ -1118,14 +1148,15 @@ int computeQualifiedIndex(const QCString &name) return name.findRev("::",i==-1 ? name.length() : i); } -void getResolvedSymbol(Definition *scope, +static void getResolvedSymbol(Definition *scope, FileDef *fileScope, Definition *d, const QCString &explicitScopePart, int &minDistance, ClassDef *&bestMatch, MemberDef *&bestTypedef, - QCString &bestTemplSpec + QCString &bestTemplSpec, + QCString &bestResolvedType ) { //printf(" found type %x name=%s d=%p\n", @@ -1161,6 +1192,7 @@ void getResolvedSymbol(Definition *scope, bestMatch = cd; bestTypedef = 0; bestTemplSpec.resize(0); + bestResolvedType = cd->qualifiedName(); } else if (distance==minDistance && fileScope && bestMatch && @@ -1181,6 +1213,7 @@ void getResolvedSymbol(Definition *scope, bestMatch = cd; bestTypedef = 0; bestTemplSpec.resize(0); + bestResolvedType = cd->qualifiedName(); } } else @@ -1206,22 +1239,25 @@ void getResolvedSymbol(Definition *scope, if (distance<minDistance) { QCString spec; + QCString type; minDistance=distance; MemberDef *enumType = 0; - ClassDef *cd = newResolveTypedef(fileScope,md,&enumType,&spec); - if (cd) // shouldn't be 0, but could in some weird cases + ClassDef *cd = newResolveTypedef(fileScope,md,&enumType,&spec,&type); + if (cd) // type resolves to a class { - //printf(" bestTypeDef=%p spec=%s\n",md,spec.data()); + //printf(" bestTypeDef=%p spec=%s type=%s\n",md,spec.data(),type.data()); bestMatch = cd; bestTypedef = md; bestTemplSpec = spec; + bestResolvedType = type; } - else if (enumType) + else if (enumType) // type resolves to a enum { //printf(" is enum\n"); bestMatch = 0; bestTypedef = enumType; bestTemplSpec = ""; + bestResolvedType = enumType->qualifiedName(); } else { @@ -1246,6 +1282,7 @@ void getResolvedSymbol(Definition *scope, bestMatch = 0; bestTypedef = md; bestTemplSpec = ""; + bestResolvedType = md->qualifiedName(); } } } @@ -1255,6 +1292,7 @@ void getResolvedSymbol(Definition *scope, //printf(" Not accessible!\n"); } } // if definition is a class or member + //printf(" bestMatch=%p bestResolvedType=%s\n",bestMatch,bestResolvedType.data()); } /* Find the fully qualified class name refered to by the input class @@ -1267,7 +1305,8 @@ ClassDef *getResolvedClassRec(Definition *scope, FileDef *fileScope, const char *n, MemberDef **pTypeDef, - QCString *pTemplSpec + QCString *pTemplSpec, + QCString *pResolvedType ) { //printf("[getResolvedClassRec(%s,%s)\n",scope?scope->name().data():"<global>",n); @@ -1345,8 +1384,9 @@ ClassDef *getResolvedClassRec(Definition *scope, //printf("Searching for %s result=%p\n",key.data(),pval); if (pval) { - if (pTemplSpec) *pTemplSpec=pval->templSpec; - if (pTypeDef) *pTypeDef=pval->typeDef; + if (pTemplSpec) *pTemplSpec=pval->templSpec; + if (pTypeDef) *pTypeDef=pval->typeDef; + if (pResolvedType) *pResolvedType=pval->resolvedType; //printf("] cachedMatch=%s\n", // pval->classDef?pval->classDef->name().data():"<none>"); //if (pTemplSpec) @@ -1362,6 +1402,7 @@ ClassDef *getResolvedClassRec(Definition *scope, ClassDef *bestMatch=0; MemberDef *bestTypedef=0; QCString bestTemplSpec; + QCString bestResolvedType; int minDistance=10000; // init at "infinite" if (di->definitionType()==DefinitionIntf::TypeSymbolList) @@ -1372,14 +1413,16 @@ ClassDef *getResolvedClassRec(Definition *scope, for (dli.toFirst();(d=dli.current());++dli,++count) // foreach definition { getResolvedSymbol(scope,fileScope,d,explicitScopePart, - minDistance,bestMatch,bestTypedef,bestTemplSpec); + minDistance,bestMatch,bestTypedef,bestTemplSpec, + bestResolvedType); } } else { Definition *d = (Definition *)di; getResolvedSymbol(scope,fileScope,d,explicitScopePart, - minDistance,bestMatch,bestTypedef,bestTemplSpec); + minDistance,bestMatch,bestTypedef,bestTemplSpec, + bestResolvedType); } if (pTypeDef) @@ -1390,17 +1433,24 @@ ClassDef *getResolvedClassRec(Definition *scope, { *pTemplSpec = bestTemplSpec; } + if (pResolvedType) + { + *pResolvedType = bestResolvedType; + } + //printf("getResolvedClassRec: bestMatch=%p pval->resolvedType=%s\n", + // bestMatch,bestResolvedType.data()); pval=Doxygen::lookupCache.find(key); if (pval) { - pval->classDef = bestMatch; - pval->typeDef = bestTypedef; - pval->templSpec = bestTemplSpec; + pval->classDef = bestMatch; + pval->typeDef = bestTypedef; + pval->templSpec = bestTemplSpec; + pval->resolvedType = bestResolvedType; } else { - Doxygen::lookupCache.insert(key,new LookupInfo(bestMatch,bestTypedef,bestTemplSpec)); + Doxygen::lookupCache.insert(key,new LookupInfo(bestMatch,bestTypedef,bestTemplSpec,bestResolvedType)); } //printf("] bestMatch=%s distance=%d\n", // bestMatch?bestMatch->name().data():"<none>",minDistance); @@ -1420,7 +1470,8 @@ ClassDef *getResolvedClass(Definition *scope, MemberDef **pTypeDef, QCString *pTemplSpec, bool mayBeUnlinkable, - bool mayBeHidden + bool mayBeHidden, + QCString *pResolvedType ) { g_resolvedTypedefs.clear(); @@ -1439,7 +1490,7 @@ ClassDef *getResolvedClass(Definition *scope, // n, // mayBeUnlinkable // ); - ClassDef *result = getResolvedClassRec(scope,fileScope,n,pTypeDef,pTemplSpec); + ClassDef *result = getResolvedClassRec(scope,fileScope,n,pTypeDef,pTemplSpec,pResolvedType); if (!mayBeUnlinkable && result && !result->isLinkable()) { if (!mayBeHidden || !result->isHidden()) @@ -2115,7 +2166,7 @@ int minClassDistance(const ClassDef *cd,const ClassDef *bcd,int level) if (level==256) { err("Error: Internal inconsistency: found class %s seem to have a recursive " - "inheritance relation! Please send a bug report to dimitri@stack.nl\n",cd->name().data()); + "inheritance relation! Please send a bug report to dimitri@stack.nl",cd->name().data()); return -1; } int m=maxInheritanceDepth; @@ -2531,7 +2582,6 @@ static bool matchArgument(const Argument *srcA,const Argument *dstA, dstAType = dstAType.right(dstAType.length()-9); } - srcAType = removeRedundantWhiteSpace(srcAType); dstAType = removeRedundantWhiteSpace(dstAType); @@ -2883,9 +2933,10 @@ static QCString extractCanonicalType(Definition *d,FileDef *fs,QCString type); QCString getCanonicalTemplateSpec(Definition *d,FileDef *fs,const QCString& spec) { + //printf("getCanonicalTemplateSpec(%s)\n",spec.data()); QCString templSpec = spec.stripWhiteSpace(); if (templSpec.isEmpty() || templSpec.at(0) != '<') return templSpec; - return "< " + extractCanonicalType(d,fs,templSpec.right(templSpec.length()-1)); + return "< " + extractCanonicalType(d,fs,templSpec.right(templSpec.length()-1).stripWhiteSpace()); } @@ -2895,7 +2946,7 @@ static QCString getCanonicalTypeForIdentifier( { QCString symName,scope,result,templSpec,tmpName; //DefinitionList *defList=0; - if (tSpec) templSpec = stripDeclKeywords(getCanonicalTemplateSpec(d,fs,*tSpec)); + if (tSpec && !tSpec->isEmpty()) templSpec = stripDeclKeywords(getCanonicalTemplateSpec(d,fs,*tSpec)); if (word.findRev("::")!=-1 && !(tmpName=stripScope(word)).isEmpty()) { @@ -2909,17 +2960,19 @@ static QCString getCanonicalTypeForIdentifier( ClassDef *cd = 0; MemberDef *mType = 0; QCString ts; + QCString resolvedType; // lookup class / class template instance - cd = getResolvedClass(d,fs,word+templSpec,&mType,&ts,TRUE); + cd = getResolvedClass(d,fs,word+templSpec,&mType,&ts,TRUE,TRUE,&resolvedType); bool isTemplInst = cd && !templSpec.isEmpty(); if (!cd && !templSpec.isEmpty()) { // class template specialization not known, look up class template - cd = getResolvedClass(d,fs,word,&mType,&ts,TRUE); + cd = getResolvedClass(d,fs,word,&mType,&ts,TRUE,TRUE,&resolvedType); } + if (cd && cd->isUsedOnly()) cd=0; // ignore types introduced by usage relations - //printf("symbol=%s word=%s cd=%s d=%s fs=%s cd->isTemplate=%d\n", + //printf(" symbol=%s word=%s cd=%s d=%s fs=%s cd->isTemplate=%d\n", // symName.data(), // word.data(), // cd?cd->name().data():"<none>", @@ -2928,38 +2981,57 @@ static QCString getCanonicalTypeForIdentifier( // cd?cd->isTemplate():-1 // ); - //printf(">>>> word '%s' => '%s' templSpec=%s ts=%s tSpec=%s\n", + //printf(" >>>> word '%s' => '%s' templSpec=%s ts=%s tSpec=%s isTemplate=%d resolvedType=%s\n", // (word+templSpec).data(), // cd?cd->qualifiedName().data():"<none>", - // templSpec.data(),ts.data(), - // tSpec?tSpec->data():"<null>"); + // templSpec.data(),ts.data(), + // tSpec?tSpec->data():"<null>", + // cd?cd->isTemplate():FALSE, + // resolvedType.data()); - if (cd) // known class type + //printf(" mtype=%s\n",mType?mType->name().data():"<none>"); + + if (cd) // resolves to a known class type { - if (isTemplInst) + if (mType && mType->isTypedef()) // but via a typedef { - // spec is already part of class type - templSpec=""; - if (tSpec) *tSpec=""; + result = resolvedType; } - else if (!ts.isEmpty() && templSpec.isEmpty()) + else { - // use formal template args for spec - templSpec = stripDeclKeywords(ts); - } + if (isTemplInst) + { + // spec is already part of class type + templSpec=""; + if (tSpec) *tSpec=""; + } + else if (!ts.isEmpty() && templSpec.isEmpty()) + { + // use formal template args for spec + templSpec = stripDeclKeywords(getCanonicalTemplateSpec(d,fs,ts)); + } - result = removeRedundantWhiteSpace(cd->qualifiedName() + templSpec); + result = removeRedundantWhiteSpace(cd->qualifiedName() + templSpec); - if (cd->isTemplate() && tSpec) - { - // template class, so remove the template part (it is part of the class name) - *tSpec=""; - } - else if (ts.isEmpty() && !templSpec.isEmpty() && cd && !cd->isTemplate() && tSpec) - { - // obscure case, where a class is used as a template, but doxygen think it is - // not (could happen when loading the class from a tag file). - *tSpec=""; + if (cd->isTemplate() && tSpec) // + { + if (!templSpec.isEmpty()) // specific instance + { + result=cd->name()+templSpec; + } + else // use template type + { + result=cd->qualifiedNameWithTemplateParameters(); + } + // template class, so remove the template part (it is part of the class name) + *tSpec=""; + } + else if (ts.isEmpty() && !templSpec.isEmpty() && cd && !cd->isTemplate() && tSpec) + { + // obscure case, where a class is used as a template, but doxygen think it is + // not (could happen when loading the class from a tag file). + *tSpec=""; + } } } else if (mType && mType->isEnumerate()) // an enum @@ -2968,7 +3040,7 @@ static QCString getCanonicalTypeForIdentifier( } else { - QCString resolvedType = resolveTypeDef(d,word); + resolvedType = resolveTypeDef(d,word); if (resolvedType.isEmpty()) // not known as a typedef either { result = word; @@ -2996,7 +3068,8 @@ static QCString extractCanonicalType(Definition *d,FileDef *fs,QCString type) type.stripPrefix("typename "); type = removeRedundantWhiteSpace(type); - //printf("extractCanonicalType(type=%s)\n",type.data()); + //printf("extractCanonicalType(type=%s) def=%s file=%s\n",type.data(), + // d ? d->name().data() : "<null>",fs ? fs->name().data() : "<null>"); static QRegExp id("[a-z_A-Z][:a-z_A-Z0-9]*"); @@ -3008,7 +3081,7 @@ static QCString extractCanonicalType(Definition *d,FileDef *fs,QCString type) //printf(" i=%d p=%d\n",i,p); canType += type.mid(pp,i-pp); - //printf("word=%s templSpec=%s\n",word.data(),templSpec.data()); + //printf(" word=%s templSpec=%s\n",word.data(),templSpec.data()); canType += getCanonicalTypeForIdentifier(d,fs,word,&templSpec); if (!templSpec.isEmpty()) // if we didn't use up the templSpec already @@ -3668,14 +3741,13 @@ bool getDefs(const QCString &scName,const QCString &memberName, MemberListIterator mli(*mn); for (mli.toFirst();(md=mli.current());++mli) { - //if (md->isLinkable()) - //{ fd=md->getFileDef(); gd=md->getGroupDef(); //printf(" md->name()=`%s' md->args=`%s' fd=%p gd=%p\n", // md->name().data(),args,fd,gd); if ( - (gd && gd->isLinkable()) || (fd && fd->isLinkable()) + ((gd && gd->isLinkable()) || (fd && fd->isLinkable())) && + md->getNamespaceDef()==0 ) { //printf(" fd=%p gd=%p args=`%s'\n",fd,gd,args); @@ -3698,7 +3770,6 @@ bool getDefs(const QCString &scName,const QCString &memberName, members.append(md); } } - //} } if (members.count()!=1 && args && !strcmp(args,"()")) { @@ -3739,12 +3810,12 @@ bool getDefs(const QCString &scName,const QCString &memberName, MemberDef *bmd = 0; for (md=members.first(); md; md=members.next()) { - if (md->getFileDef() == currentFile) + if (currentFile && md->getBodyDef()==currentFile) { bmd = 0; break; } - if (!(md->isStatic()) || Config_getBool("EXTRACT_STATIC")) bmd = md; + if (!md->isStatic() || Config_getBool("EXTRACT_STATIC")) bmd = md; } if (bmd) md=bmd; } @@ -4174,7 +4245,7 @@ bool generateLink(OutputDocInterface &od,const char *clName, } else { - err("%s:%d: Internal error: resolveLink successful but no compound found!\n",__FILE__,__LINE__); + err("%s:%d: Internal error: resolveLink successful but no compound found!",__FILE__,__LINE__); } return TRUE; } @@ -175,7 +175,8 @@ ClassDef *getResolvedClass(Definition *scope, MemberDef **pTypeDef=0, QCString *pTemplSpec=0, bool mayBeUnlinkable=FALSE, - bool mayBeHidden=FALSE); + bool mayBeHidden=FALSE, + QCString *pResolvedType=0); NamespaceDef *getResolvedNamespace(const char *key); @@ -326,7 +327,8 @@ SrcLangExt getLanguageFromFileName(const QCString fileName); bool checkIfTypedef(Definition *scope,FileDef *fileScope,const char *n); ClassDef *newResolveTypedef(FileDef *fileScope,MemberDef *md, - MemberDef **pMemType=0,QCString *pTemplSpec=0); + MemberDef **pMemType=0,QCString *pTemplSpec=0, + QCString *pResolvedType=0); #endif |