diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/clangparser.cpp | 3 | ||||
-rw-r--r-- | src/code.l | 16 | ||||
-rw-r--r-- | src/context.cpp | 16 | ||||
-rw-r--r-- | src/context.h | 3 | ||||
-rw-r--r-- | src/defgen.cpp | 99 | ||||
-rw-r--r-- | src/definition.cpp | 152 | ||||
-rw-r--r-- | src/definition.h | 7 | ||||
-rw-r--r-- | src/definitionimpl.h | 21 | ||||
-rw-r--r-- | src/dotcallgraph.cpp | 66 | ||||
-rw-r--r-- | src/doxygen.cpp | 88 | ||||
-rw-r--r-- | src/fortrancode.l | 7 | ||||
-rw-r--r-- | src/htmlgen.cpp | 3 | ||||
-rw-r--r-- | src/index.cpp | 1 | ||||
-rw-r--r-- | src/memberlist.cpp | 2 | ||||
-rw-r--r-- | src/memberlist.h | 9 | ||||
-rw-r--r-- | src/pycode.l | 9 | ||||
-rw-r--r-- | src/sqlite3gen.cpp | 42 | ||||
-rw-r--r-- | src/tooltip.cpp | 48 | ||||
-rw-r--r-- | src/tooltip.h | 22 | ||||
-rw-r--r-- | src/vhdlcode.l | 7 | ||||
-rw-r--r-- | src/xmlgen.cpp | 20 |
21 files changed, 301 insertions, 340 deletions
diff --git a/src/clangparser.cpp b/src/clangparser.cpp index 1a91b8f..d17ed91 100644 --- a/src/clangparser.cpp +++ b/src/clangparser.cpp @@ -133,6 +133,7 @@ class ClangTUParser::Private CXToken *tokens = 0; uint numTokens = 0; StringVector filesInSameTU; + TooltipManager tooltipManager; // state while parsing sources MemberDef *currentMemberDef=0; @@ -572,7 +573,7 @@ void ClangTUParser::writeMultiLineCodeLink(CodeOutputInterface &ol, const char *text) { static bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); - TooltipManager::instance()->addTooltip(d); + p->tooltipManager.addTooltip(d); QCString ref = d->getReference(); QCString file = d->getOutputFileBase(); QCString anchor = d->anchor(); @@ -175,6 +175,7 @@ struct codeYY_state QCString forceTagReference; VariableContext theVarContext; CallContext theCallContext; + TooltipManager tooltipManager; }; static bool isCastKeyword(const QCString &s); @@ -241,7 +242,7 @@ static void addVariable(yyscan_t yyscanner,QCString type,QCString name); //------------------------------------------------------------------- static std::mutex g_searchIndexMutex; -static std::mutex g_tooltipMutex; +static std::mutex g_docCrossReferenceMutex; /* ----------------------------------------------------------------- */ @@ -2471,10 +2472,7 @@ static void writeMultiLineCodeLink(yyscan_t yyscanner,CodeOutputInterface &ol, { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); - { - std::lock_guard<std::mutex> lock(g_tooltipMutex); - TooltipManager::instance()->addTooltip(d); - } + yyextra->tooltipManager.addTooltip(d); QCString ref = d->getReference(); QCString file = d->getOutputFileBase(); QCString anchor = d->anchor(); @@ -2764,6 +2762,7 @@ static bool getLinkInScope(yyscan_t yyscanner, if (yyextra->currentDefinition && yyextra->currentMemberDef && md!=yyextra->currentMemberDef && yyextra->insideBody && yyextra->collectXRefs) { + std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); addDocCrossReference(yyextra->currentMemberDef,const_cast<MemberDef*>(md)); } //printf("d->getReference()='%s' d->getOutputBase()='%s' name='%s' member name='%s'\n",d->getReference().data(),d->getOutputFileBase().data(),d->name().data(),md->name().data()); @@ -2924,6 +2923,7 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, if (d && d->isLinkable() && md->isLinkable() && yyextra->currentMemberDef && yyextra->collectXRefs) { + std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); addDocCrossReference(yyextra->currentMemberDef,const_cast<MemberDef*>(md)); } } @@ -2978,6 +2978,7 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, addToSearchIndex(yyscanner,clName); if (yyextra->currentMemberDef && yyextra->collectXRefs) { + std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); addDocCrossReference(yyextra->currentMemberDef,const_cast<MemberDef*>(md)); } return; @@ -3038,6 +3039,7 @@ static bool generateClassMemberLink(yyscan_t yyscanner, if (yyextra->currentDefinition && yyextra->currentMemberDef && /*xmd!=yyextra->currentMemberDef &&*/ yyextra->insideBody && yyextra->collectXRefs) { + std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); addDocCrossReference(yyextra->currentMemberDef,xmd); } @@ -3457,6 +3459,7 @@ static void writeObjCMethodCall(yyscan_t yyscanner,ObjCCallCtx *ctx) writeMultiLineCodeLink(yyscanner,*yyextra->code,ctx->method,name); if (yyextra->currentMemberDef && yyextra->collectXRefs) { + std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); addDocCrossReference(yyextra->currentMemberDef,const_cast<MemberDef*>(ctx->method)); } } @@ -3531,6 +3534,7 @@ static void writeObjCMethodCall(yyscan_t yyscanner,ObjCCallCtx *ctx) writeMultiLineCodeLink(yyscanner,*yyextra->code,ctx->objectVar,object); if (yyextra->currentMemberDef && yyextra->collectXRefs) { + std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); addDocCrossReference(yyextra->currentMemberDef,const_cast<MemberDef*>(ctx->objectVar)); } } @@ -3903,6 +3907,8 @@ void CCodeParser::parseCode(CodeOutputInterface &od,const char *className,const delete yyextra->sourceFileDef; yyextra->sourceFileDef=0; } + // write the tooltips + yyextra->tooltipManager.writeTooltips(od); printlex(yy_flex_debug, FALSE, __FILE__, fd ? fd->fileName().data(): NULL); return; diff --git a/src/context.cpp b/src/context.cpp index 5a9ab38..394e857 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -4943,7 +4943,7 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private> Cachable &cache = getCache(); if (!cache.sourceRefs) { - cache.sourceRefs.reset(MemberListContext::alloc(m_memberDef->getReferencesMembers(),TRUE)); + cache.sourceRefs.reset(MemberListContext::alloc(m_memberDef->getReferencesMembers())); } return cache.sourceRefs.get(); } @@ -4952,7 +4952,7 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private> Cachable &cache = getCache(); if (!cache.sourceRefBys) { - cache.sourceRefBys.reset(MemberListContext::alloc(m_memberDef->getReferencedByMembers(),TRUE)); + cache.sourceRefBys.reset(MemberListContext::alloc(m_memberDef->getReferencedByMembers())); } return cache.sourceRefBys.get(); } @@ -8581,7 +8581,7 @@ TemplateListIntf::ConstIterator *InheritanceListContext::createIterator() const class MemberListContext::Private : public GenericNodeListContext { public: - void addMember(MemberDef *md) + void addMember(const MemberDef *md) { append(MemberContext::alloc(md)); } @@ -8630,6 +8630,16 @@ MemberListContext::MemberListContext(MemberSDict *list,bool doSort) : RefCounted } } +MemberListContext::MemberListContext(std::vector<const MemberDef *> &&ml) : RefCountedContext("MemberListContext") +{ + p = new Private; + for (const auto &md : ml) + { + p->addMember(md); + } + ml.clear(); +} + MemberListContext::~MemberListContext() { delete p; diff --git a/src/context.h b/src/context.h index c785664..240e8fd 100644 --- a/src/context.h +++ b/src/context.h @@ -954,6 +954,8 @@ class MemberListContext : public RefCountedContext, public TemplateListIntf { return new MemberListContext(ml); } static MemberListContext *alloc(MemberSDict *ml,bool doSort) { return new MemberListContext(ml,doSort); } + static MemberListContext *alloc(std::vector<const MemberDef *> &&ml) + { return new MemberListContext(std::move(ml)); } // TemplateListIntf virtual uint count() const; @@ -966,6 +968,7 @@ class MemberListContext : public RefCountedContext, public TemplateListIntf MemberListContext(); MemberListContext(const MemberList *ml); MemberListContext(MemberSDict *ml,bool doSort); + MemberListContext(std::vector<const MemberDef *> &&ml); ~MemberListContext(); class Private; Private *p; diff --git a/src/defgen.cpp b/src/defgen.cpp index b01d438..82f7c26 100644 --- a/src/defgen.cpp +++ b/src/defgen.cpp @@ -243,71 +243,58 @@ void generateDEFForMember(MemberDef *md, //printf("md->getReferencesMembers()=%p\n",md->getReferencesMembers()); - MemberSDict *mdict = md->getReferencesMembers(); - if (mdict) + QCString refPrefix = " " + memPrefix + "ref-"; + auto refList = md->getReferencesMembers(); + for (const auto &rmd : refList) { - MemberSDict::Iterator mdi(*mdict); - MemberDef *rmd; - QCString refPrefix = " " + memPrefix + "ref-"; - - for (mdi.toFirst();(rmd=mdi.current());++mdi) + if (rmd->getStartBodyLine()!=-1 && rmd->getBodyDef()) { - if (rmd->getStartBodyLine()!=-1 && rmd->getBodyDef()) + t << memPrefix << "referenceto = {" << endl; + t << refPrefix << "id = '" + << rmd->getBodyDef()->getOutputFileBase() + << "_1" // encoded ':' character (see util.cpp:convertNameToFile) + << rmd->anchor() << "';" << endl; + + t << refPrefix << "line = '" + << rmd->getStartBodyLine() << "';" << endl; + + QCString scope = rmd->getScopeString(); + QCString name = rmd->name(); + if (!scope.isEmpty() && scope!=def->name()) { - t << memPrefix << "referenceto = {" << endl; - t << refPrefix << "id = '" - << rmd->getBodyDef()->getOutputFileBase() - << "_1" // encoded ':' character (see util.cpp:convertNameToFile) - << rmd->anchor() << "';" << endl; - - t << refPrefix << "line = '" - << rmd->getStartBodyLine() << "';" << endl; - - QCString scope = rmd->getScopeString(); - QCString name = rmd->name(); - if (!scope.isEmpty() && scope!=def->name()) - { - name.prepend(scope+"::"); - } - - t << refPrefix << "name = "; - writeDEFString(t,name); - t << ';' << endl << " };" << endl; + name.prepend(scope+"::"); } - } /* for (mdi.toFirst...) */ + + t << refPrefix << "name = "; + writeDEFString(t,name); + t << ';' << endl << " };" << endl; + } } - mdict = md->getReferencedByMembers(); - if (mdict) + auto refByList = md->getReferencedByMembers(); + for (const auto &rmd : refByList) { - MemberSDict::Iterator mdi(*mdict); - MemberDef *rmd; - QCString refPrefix = " " + memPrefix + "ref-"; - - for (mdi.toFirst();(rmd=mdi.current());++mdi) + if (rmd->getStartBodyLine()!=-1 && rmd->getBodyDef()) { - if (rmd->getStartBodyLine()!=-1 && rmd->getBodyDef()) + t << memPrefix << "referencedby = {" << endl; + t << refPrefix << "id = '" + << rmd->getBodyDef()->getOutputFileBase() + << "_1" // encoded ':' character (see util.cpp:convertNameToFile) + << rmd->anchor() << "';" << endl; + + t << refPrefix << "line = '" + << rmd->getStartBodyLine() << "';" << endl; + + QCString scope = rmd->getScopeString(); + QCString name = rmd->name(); + if (!scope.isEmpty() && scope!=def->name()) { - t << memPrefix << "referencedby = {" << endl; - t << refPrefix << "id = '" - << rmd->getBodyDef()->getOutputFileBase() - << "_1" // encoded ':' character (see util.cpp:convertNameToFile) - << rmd->anchor() << "';" << endl; - - t << refPrefix << "line = '" - << rmd->getStartBodyLine() << "';" << endl; - - QCString scope = rmd->getScopeString(); - QCString name = rmd->name(); - if (!scope.isEmpty() && scope!=def->name()) - { - name.prepend(scope+"::"); - } - - t << refPrefix << "name = "; - writeDEFString(t,name); - t << ';' << endl << " };" << endl; + name.prepend(scope+"::"); } - } /* for (mdi.toFirst...) */ + + t << refPrefix << "name = "; + writeDEFString(t,name); + t << ';' << endl << " };" << endl; + } } t << " }; /* " << Prefix << "-member */" << endl; diff --git a/src/definition.cpp b/src/definition.cpp index 9e78b74..355ef82 100644 --- a/src/definition.cpp +++ b/src/definition.cpp @@ -16,6 +16,10 @@ */ #include <algorithm> +#include <iterator> +#include <unordered_map> +#include <string> + #include <ctype.h> #include <qregexp.h> #include "md5.h" @@ -58,8 +62,8 @@ class DefinitionImpl::IMPL SectionRefs sectionRefs; - MemberSDict *sourceRefByDict = 0; - MemberSDict *sourceRefsDict = 0; + std::unordered_map<std::string,const MemberDef *> sourceRefByDict; + std::unordered_map<std::string,const MemberDef *> sourceRefsDict; RefItemVector xrefListItems; GroupList *partOfGroups = 0; @@ -100,8 +104,6 @@ class DefinitionImpl::IMPL DefinitionImpl::IMPL::~IMPL() { - delete sourceRefByDict; - delete sourceRefsDict; delete partOfGroups; delete brief; delete details; @@ -138,8 +140,8 @@ void DefinitionImpl::IMPL::init(const char *df, const char *n) details = 0; body = 0; inbodyDocs = 0; - sourceRefByDict = 0; - sourceRefsDict = 0; + sourceRefByDict.clear(); + sourceRefsDict.clear(); outerScope = Doxygen::globalScope; partOfGroups = 0; hidden = FALSE; @@ -314,33 +316,11 @@ DefinitionImpl::DefinitionImpl(const DefinitionImpl &d) { m_impl = new DefinitionImpl::IMPL; *m_impl = *d.m_impl; - m_impl->sourceRefByDict = 0; - m_impl->sourceRefsDict = 0; m_impl->partOfGroups = 0; m_impl->brief = 0; m_impl->details = 0; m_impl->body = 0; m_impl->inbodyDocs = 0; - if (d.m_impl->sourceRefByDict) - { - m_impl->sourceRefByDict = new MemberSDict; - MemberSDict::IteratorDict it(*d.m_impl->sourceRefByDict); - MemberDef *md; - for (it.toFirst();(md=it.current());++it) - { - m_impl->sourceRefByDict->append(it.currentKey(),md); - } - } - if (d.m_impl->sourceRefsDict) - { - m_impl->sourceRefsDict = new MemberSDict; - MemberSDict::IteratorDict it(*d.m_impl->sourceRefsDict); - MemberDef *md; - for (it.toFirst();(md=it.current());++it) - { - m_impl->sourceRefsDict->append(it.currentKey(),md); - } - } if (d.m_impl->partOfGroups) { GroupListIterator it(*d.m_impl->partOfGroups); @@ -1262,11 +1242,27 @@ void DefinitionImpl::writeInlineCode(OutputList &ol,const char *scopeName) const ol.popGeneratorState(); } +static inline std::vector<const MemberDef*> refMapToVector(const std::unordered_map<std::string,const MemberDef *> &map) +{ + // convert map to a vector of values + std::vector<const MemberDef *> result; + std::transform(map.begin(),map.end(), // iterate over map + std::back_inserter(result), // add results to vector + [](const auto &item) + { return item.second; } // extract value to add from map Key,Value pair + ); + // and sort it + std::sort(result.begin(),result.end(), + [](const auto &m1,const auto &m2) { return genericCompareMembers(m1,m2)<0; }); + return result; +} + /*! Write a reference to the source code fragments in which this * definition is used. */ void DefinitionImpl::_writeSourceRefList(OutputList &ol,const char *scopeName, - const QCString &text,MemberSDict *members,bool /*funcOnly*/) const + const QCString &text,const std::unordered_map<std::string,const MemberDef *> &membersMap, + bool /*funcOnly*/) const { static bool latexSourceCode = Config_getBool(LATEX_SOURCE_CODE); static bool docbookSourceCode = Config_getBool(DOCBOOK_PROGRAMLISTING); @@ -1274,15 +1270,15 @@ void DefinitionImpl::_writeSourceRefList(OutputList &ol,const char *scopeName, static bool sourceBrowser = Config_getBool(SOURCE_BROWSER); static bool refLinkSource = Config_getBool(REFERENCES_LINK_SOURCE); ol.pushGeneratorState(); - if (members) + if (!membersMap.empty()) { - members->sort(); + auto members = refMapToVector(membersMap); ol.startParagraph("reference"); ol.parseText(text); ol.docify(" "); - QCString ldefLine=theTranslator->trWriteList((int)members->count()); + QCString ldefLine=theTranslator->trWriteList((int)members.size()); QRegExp marker("@[0-9]+"); uint index=0; @@ -1294,7 +1290,7 @@ void DefinitionImpl::_writeSourceRefList(OutputList &ol,const char *scopeName, bool ok; ol.parseText(ldefLine.mid(index,(uint)newIndex-index)); uint entryIndex = ldefLine.mid(newIndex+1,matchLen-1).toUInt(&ok); - MemberDef *md=members->at(entryIndex); + const MemberDef *md=members.at(entryIndex); if (ok && md) { QCString scope=md->getScopeString(); @@ -1466,14 +1462,7 @@ void DefinitionImpl::addSourceReferencedBy(const MemberDef *md) name.prepend(scope+"::"); } - if (m_impl->sourceRefByDict==0) - { - m_impl->sourceRefByDict = new MemberSDict; - } - if (m_impl->sourceRefByDict->find(name)==0) - { - m_impl->sourceRefByDict->append(name,md); - } + m_impl->sourceRefByDict.insert({name.str(),md}); } } @@ -1489,14 +1478,7 @@ void DefinitionImpl::addSourceReferences(const MemberDef *md) name.prepend(scope+"::"); } - if (m_impl->sourceRefsDict==0) - { - m_impl->sourceRefsDict = new MemberSDict; - } - if (m_impl->sourceRefsDict->find(name)==0) - { - m_impl->sourceRefsDict->append(name,md); - } + m_impl->sourceRefsDict.insert({name.str(),md}); } } @@ -1960,29 +1942,20 @@ QCString DefinitionImpl::briefDescription(bool abbr) const QCString(""); } -QCString DefinitionImpl::briefDescriptionAsTooltip() const +void DefinitionImpl::computeTooltip() { - if (m_impl->brief) + if (m_impl->brief && m_impl->brief->tooltip.isEmpty() && !m_impl->brief->doc.isEmpty()) { - if (m_impl->brief->tooltip.isEmpty() && !m_impl->brief->doc.isEmpty()) - { - static bool reentering=FALSE; - if (!reentering) - { - const MemberDef *md = definitionType()==TypeMember ? dynamic_cast<const MemberDef*>(this) : 0; - const Definition *scope = definitionType()==TypeMember ? getOuterScope() : this; - reentering=TRUE; // prevent requests for tooltips while parsing a tooltip - m_impl->brief->tooltip = parseCommentAsText( - scope,md, - m_impl->brief->doc, - m_impl->brief->file, - m_impl->brief->line); - reentering=FALSE; - } - } - return m_impl->brief->tooltip; + const MemberDef *md = definitionType()==TypeMember ? dynamic_cast<const MemberDef*>(this) : 0; + const Definition *scope = definitionType()==TypeMember ? getOuterScope() : this; + m_impl->brief->tooltip = parseCommentAsText(scope,md, + m_impl->brief->doc, m_impl->brief->file, m_impl->brief->line); } - return QCString(""); +} + +QCString DefinitionImpl::briefDescriptionAsTooltip() const +{ + return m_impl->brief ? m_impl->brief->tooltip : QCString(); } int DefinitionImpl::briefLine() const @@ -2100,16 +2073,49 @@ Definition *DefinitionImpl::getOuterScope() const return m_impl->outerScope; } -MemberSDict *DefinitionImpl::getReferencesMembers() const +std::vector<const MemberDef*> DefinitionImpl::getReferencesMembers() const +{ + return refMapToVector(m_impl->sourceRefsDict); +} + +std::vector<const MemberDef*> DefinitionImpl::getReferencedByMembers() const +{ + return refMapToVector(m_impl->sourceRefByDict); +} + +void DefinitionImpl::mergeReferences(const Definition *other) { - return m_impl->sourceRefsDict; + const DefinitionImpl *defImpl = dynamic_cast<const DefinitionImpl*>(other); + if (defImpl) + { + for (const auto &kv : defImpl->m_impl->sourceRefsDict) + { + auto it = m_impl->sourceRefsDict.find(kv.first); + if (it != m_impl->sourceRefsDict.end()) + { + m_impl->sourceRefsDict.insert(kv); + } + } + } } -MemberSDict *DefinitionImpl::getReferencedByMembers() const +void DefinitionImpl::mergeReferencedBy(const Definition *other) { - return m_impl->sourceRefByDict; + const DefinitionImpl *defImpl = dynamic_cast<const DefinitionImpl*>(other); + if (defImpl) + { + for (const auto &kv : defImpl->m_impl->sourceRefByDict) + { + auto it = m_impl->sourceRefByDict.find(kv.first); + if (it != m_impl->sourceRefByDict.end()) + { + m_impl->sourceRefByDict.insert({kv.first,kv.second}); + } + } + } } + void DefinitionImpl::setReference(const char *r) { m_impl->ref=r; diff --git a/src/definition.h b/src/definition.h index 8ad15b2..b3d7853 100644 --- a/src/definition.h +++ b/src/definition.h @@ -272,8 +272,8 @@ class Definition : public DefinitionIntf virtual Definition *findInnerCompound(const char *name) const = 0; virtual Definition *getOuterScope() const = 0; - virtual MemberSDict *getReferencesMembers() const = 0; - virtual MemberSDict *getReferencedByMembers() const = 0; + virtual std::vector<const MemberDef *> getReferencesMembers() const = 0; + virtual std::vector<const MemberDef *> getReferencedByMembers() const = 0; virtual bool hasSections() const = 0; virtual bool hasSources() const = 0; @@ -347,6 +347,9 @@ class Definition : public DefinitionIntf virtual void mergeRefItems(Definition *d) = 0; virtual void addInnerCompound(const Definition *d) = 0; virtual void addSectionsToIndex() = 0; + virtual void mergeReferences(const Definition *other) = 0; + virtual void mergeReferencedBy(const Definition *other) = 0; + virtual void computeTooltip() = 0; //----------------------------------------------------------------------------------- // --- writing output ---- diff --git a/src/definitionimpl.h b/src/definitionimpl.h index e91d989..c4e6e2a 100644 --- a/src/definitionimpl.h +++ b/src/definitionimpl.h @@ -18,6 +18,9 @@ #ifndef DEFINITIONIMPL_H #define DEFINITIONIMPL_H +#include <unordered_map> +#include <string> + #include "definition.h" class DefinitionImpl : virtual public Definition @@ -71,8 +74,8 @@ class DefinitionImpl : virtual public Definition virtual const RefItemVector &xrefListItems() const; virtual Definition *findInnerCompound(const char *name) const; virtual Definition *getOuterScope() const; - virtual MemberSDict *getReferencesMembers() const; - virtual MemberSDict *getReferencedByMembers() const; + virtual std::vector<const MemberDef *> getReferencesMembers() const; + virtual std::vector<const MemberDef *> getReferencedByMembers() const; virtual bool hasSections() const; virtual bool hasSources() const; virtual bool hasBriefDescription() const; @@ -92,6 +95,8 @@ class DefinitionImpl : virtual public Definition virtual void addSourceReferences(const MemberDef *d); virtual void setRefItems(const RefItemVector &sli); virtual void mergeRefItems(Definition *d); + virtual void mergeReferences(const Definition *other); + virtual void mergeReferencedBy(const Definition *other); virtual void addInnerCompound(const Definition *d); virtual void setOuterScope(Definition *d); virtual void setHidden(bool b); @@ -113,6 +118,7 @@ class DefinitionImpl : virtual public Definition virtual void writeToc(OutputList &ol, const LocalToc <) const; virtual void setCookie(Cookie *cookie) const; virtual Cookie *cookie() const; + virtual void computeTooltip(); protected: @@ -123,8 +129,8 @@ class DefinitionImpl : virtual public Definition virtual QCString _symbolName() const ; int _getXRefListId(const char *listName) const; - void _writeSourceRefList(OutputList &ol,const char *scopeName, - const QCString &text,MemberSDict *members,bool) const; + void _writeSourceRefList(OutputList &ol,const char *scopeName,const QCString &text, + const std::unordered_map<std::string,const MemberDef *> &members,bool) const; void _setBriefDescription(const char *b,const char *briefFile,int briefLine); void _setDocumentation(const char *d,const char *docFile,int docLine,bool stripWhiteSpace,bool atTop); void _setInbodyDocumentation(const char *d,const char *docFile,int docLine); @@ -222,9 +228,9 @@ class DefinitionAliasImpl : virtual public Definition { return m_def->findInnerCompound(name); } virtual Definition *getOuterScope() const { return const_cast<Definition*>(m_scope); } - virtual MemberSDict *getReferencesMembers() const + virtual std::vector<const MemberDef *> getReferencesMembers() const { return m_def->getReferencesMembers(); } - virtual MemberSDict *getReferencedByMembers() const + virtual std::vector<const MemberDef *> getReferencedByMembers() const { return m_def->getReferencedByMembers(); } virtual bool hasSections() const { return m_def->hasSections(); } @@ -254,6 +260,8 @@ class DefinitionAliasImpl : virtual public Definition virtual void addSourceReferences(const MemberDef *) {} virtual void setRefItems(const RefItemVector &) {} virtual void mergeRefItems(Definition *) {} + virtual void mergeReferences(const Definition *) {} + virtual void mergeReferencedBy(const Definition *) {} virtual void addInnerCompound(const Definition *) {} virtual void setOuterScope(Definition *) {} virtual void setHidden(bool) {} @@ -273,6 +281,7 @@ class DefinitionAliasImpl : virtual public Definition virtual void writeToc(OutputList &, const LocalToc &) const {} virtual void setCookie(Cookie *cookie) const { delete m_cookie; m_cookie = cookie; } virtual Cookie *cookie() const { return m_cookie; } + virtual void computeTooltip() {} protected: const Definition *getAlias() const { return m_def; } const Definition *getScope() const { return m_scope; } diff --git a/src/dotcallgraph.cpp b/src/dotcallgraph.cpp index 5e13f8e..ef89627 100644 --- a/src/dotcallgraph.cpp +++ b/src/dotcallgraph.cpp @@ -1,6 +1,6 @@ /****************************************************************************** * -* Copyright (C) 1997-2019 by Dimitri van Heesch. +* Copyright (C) 1997-2020 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 @@ -34,51 +34,45 @@ static QCString getUniqueId(const MemberDef *md) void DotCallGraph::buildGraph(DotNode *n,const MemberDef *md,int distance) { - MemberSDict *refs = m_inverse ? md->getReferencedByMembers() : md->getReferencesMembers(); - if (refs) + auto refs = m_inverse ? md->getReferencedByMembers() : md->getReferencesMembers(); + for (const auto &rmd : refs) { - refs->sort(); - MemberSDict::Iterator mri(*refs); - MemberDef *rmd; - for (;(rmd=mri.current());++mri) + if (rmd->showInCallGraph()) { - if (rmd->showInCallGraph()) + QCString uniqueId = getUniqueId(rmd); + DotNode *bn = m_usedNodes->find(uniqueId); + if (bn) // file is already a node in the graph { - QCString uniqueId = getUniqueId(rmd); - DotNode *bn = m_usedNodes->find(uniqueId); - if (bn) // file is already a node in the graph + n->addChild(bn,0,0,0); + bn->addParent(n); + bn->setDistance(distance); + } + else + { + QCString name; + if (HIDE_SCOPE_NAMES) { - n->addChild(bn,0,0,0); - bn->addParent(n); - bn->setDistance(distance); + name = rmd->getOuterScope()==m_scope ? + rmd->name() : rmd->qualifiedName(); } else { - QCString name; - if (HIDE_SCOPE_NAMES) - { - name = rmd->getOuterScope()==m_scope ? - rmd->name() : rmd->qualifiedName(); - } - else - { - name = rmd->qualifiedName(); - } - QCString tooltip = rmd->briefDescriptionAsTooltip(); - bn = new DotNode( + name = rmd->qualifiedName(); + } + QCString tooltip = rmd->briefDescriptionAsTooltip(); + bn = new DotNode( getNextNodeNumber(), linkToText(rmd->getLanguage(),name,FALSE), tooltip, uniqueId, 0 //distance - ); - n->addChild(bn,0,0,0); - bn->addParent(n); - bn->setDistance(distance); - m_usedNodes->insert(uniqueId,bn); + ); + n->addChild(bn,0,0,0); + bn->addParent(n); + bn->setDistance(distance); + m_usedNodes->insert(uniqueId,bn); - buildGraph(bn,rmd,distance+1); - } + buildGraph(bn,rmd,distance+1); } } } @@ -121,9 +115,9 @@ void DotCallGraph::determineTruncatedNodes(QList<DotNode> &queue) const DotNode *dn; for (li.toFirst();(dn=li.current());++li) { - if (!dn->isVisible()) + if (!dn->isVisible()) truncated = TRUE; - else + else queue.append(dn); } } @@ -198,7 +192,7 @@ QCString DotCallGraph::getMapLabel() const } QCString DotCallGraph::writeGraph( - FTextStream &out, + FTextStream &out, GraphOutputFormat graphFormat, EmbeddedOutputFormat textFormat, const char *path, diff --git a/src/doxygen.cpp b/src/doxygen.cpp index 7c350d4..1a70e61 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -3709,59 +3709,10 @@ static void transferFunctionReferences() ) ) /* match found */ { - MemberSDict *defDict = mdef->getReferencesMembers(); - MemberSDict *decDict = mdec->getReferencesMembers(); - if (defDict!=0) - { - MemberSDict::IteratorDict msdi(*defDict); - MemberDef *rmd; - for (msdi.toFirst();(rmd=msdi.current());++msdi) - { - if (decDict==0 || decDict->find(rmd->name())==0) - { - mdec->addSourceReferences(rmd); - } - } - } - if (decDict!=0) - { - MemberSDict::IteratorDict msdi(*decDict); - MemberDef *rmd; - for (msdi.toFirst();(rmd=msdi.current());++msdi) - { - if (defDict==0 || defDict->find(rmd->name())==0) - { - mdef->addSourceReferences(rmd); - } - } - } - - defDict = mdef->getReferencedByMembers(); - decDict = mdec->getReferencedByMembers(); - if (defDict!=0) - { - MemberSDict::IteratorDict msdi(*defDict); - MemberDef *rmd; - for (msdi.toFirst();(rmd=msdi.current());++msdi) - { - if (decDict==0 || decDict->find(rmd->name())==0) - { - mdec->addSourceReferencedBy(rmd); - } - } - } - if (decDict!=0) - { - MemberSDict::IteratorDict msdi(*decDict); - MemberDef *rmd; - for (msdi.toFirst();(rmd=msdi.current());++msdi) - { - if (defDict==0 || defDict->find(rmd->name())==0) - { - mdef->addSourceReferencedBy(rmd); - } - } - } + mdef->mergeReferences(mdec); + mdec->mergeReferences(mdef); + mdef->mergeReferencedBy(mdec); + mdec->mergeReferencedBy(mdef); } } } @@ -7651,7 +7602,6 @@ static void generateFileSources() results.emplace_back(threadPool.queue(processFile)); } } - // first wait until all files are processed for (auto &f : results) { auto ctx = f.get(); @@ -7860,6 +7810,32 @@ static void sortMemberLists() //---------------------------------------------------------------------------- +void computeTooltipTexts() +{ + QDictIterator<DefinitionIntf> di(*Doxygen::symbolMap); + DefinitionIntf *intf; + for (;(intf=di.current());++di) + { + if (intf->definitionType()==DefinitionIntf::TypeSymbolList) // list of symbols + { + DefinitionListIterator dli(*(DefinitionList*)intf); + Definition *d; + // for each symbol + for (dli.toFirst();(d=dli.current());++dli) + { + d->computeTooltip(); + } + } + else // single symbol + { + Definition *d = (Definition *)intf; + if (d!=Doxygen::globalScope) d->computeTooltip(); + } + } +} + +//---------------------------------------------------------------------------- + static void setAnonymousEnumType() { ClassSDict::Iterator cli(*Doxygen::classSDict); @@ -11443,6 +11419,10 @@ void parseInput() vhdlCorrectMemberProperties(); g_s.end(); + g_s.begin("Computing tooltip texts...\n"); + computeTooltipTexts(); + g_s.end(); + if (Config_getBool(SORT_GROUP_NAMES)) { Doxygen::groupSDict->sort(); diff --git a/src/fortrancode.l b/src/fortrancode.l index f2b0ee8..6b278cc 100644 --- a/src/fortrancode.l +++ b/src/fortrancode.l @@ -172,6 +172,7 @@ struct fortrancodeYY_state int inTypeDecl = 0; bool endComment = false; + TooltipManager tooltipManager; }; #if USE_STATE2STRING @@ -1012,7 +1013,7 @@ static void writeMultiLineCodeLink(yyscan_t yyscanner,CodeOutputInterface &ol, { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; static bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); - TooltipManager::instance()->addTooltip(d); + yyextra->tooltipManager.addTooltip(d); QCString ref = d->getReference(); QCString file = d->getOutputFileBase(); QCString anchor = d->anchor(); @@ -1514,6 +1515,10 @@ void FortranCodeParser::parseCode(CodeOutputInterface & codeOutIntf, } if (yyextra->hasContLine) free(yyextra->hasContLine); yyextra->hasContLine = NULL; + + // write the tooltips + yyextra->tooltipManager.writeTooltips(codeOutIntf); + printlex(yy_flex_debug, FALSE, __FILE__, fileDef ? fileDef->fileName().data(): NULL); } diff --git a/src/htmlgen.cpp b/src/htmlgen.cpp index ea4d895..e1358a7 100644 --- a/src/htmlgen.cpp +++ b/src/htmlgen.cpp @@ -1231,9 +1231,6 @@ void HtmlGenerator::writePageFooter(FTextStream &t,const QCString &lastTitle, void HtmlGenerator::writeFooter(const char *navPath) { - // Currently only tooltips in HTML - TooltipManager::instance()->writeTooltips(m_codeGen); - writePageFooter(t,m_lastTitle,m_relPath,navPath); } diff --git a/src/index.cpp b/src/index.cpp index afe66f4..c4fda05 100644 --- a/src/index.cpp +++ b/src/index.cpp @@ -307,7 +307,6 @@ void endFile(OutputList &ol,bool skipNavIndex,bool skipEndContents, ol.writeFooter(navPath); // write the footer ol.popGeneratorState(); ol.endFile(); - TooltipManager::instance()->clearTooltips(); // Only clear after the last is written } void endFileWithNavPath(const Definition *d,OutputList &ol) diff --git a/src/memberlist.cpp b/src/memberlist.cpp index b8e5e89..0c608ff 100644 --- a/src/memberlist.cpp +++ b/src/memberlist.cpp @@ -63,7 +63,7 @@ MemberList::~MemberList() delete memberGroupList; } -static int genericCompareMembers(const MemberDef *c1,const MemberDef *c2) +int genericCompareMembers(const MemberDef *c1,const MemberDef *c2) { bool sortConstructorsFirst = Config_getBool(SORT_MEMBERS_CTORS_1ST); if (sortConstructorsFirst) diff --git a/src/memberlist.h b/src/memberlist.h index 4038453..b8c723b 100644 --- a/src/memberlist.h +++ b/src/memberlist.h @@ -1,12 +1,12 @@ /****************************************************************************** * - * + * * * Copyright (C) 1997-2015 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 + * 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. * @@ -105,7 +105,7 @@ class MemberList : private QList<MemberDef> int m_dictCnt; int m_protoCnt; int m_defCnt; - int m_friendCnt; + int m_friendCnt; */ int m_numDecMembers; // number of members in the brief part of the memberlist int m_numDecEnumValues; @@ -145,5 +145,6 @@ class MemberSDict : public SDict<MemberDef> int compareValues(const MemberDef *item1,const MemberDef *item2) const; }; +int genericCompareMembers(const MemberDef *c1,const MemberDef *c2); #endif diff --git a/src/pycode.l b/src/pycode.l index cc00447..bcba42f 100644 --- a/src/pycode.l +++ b/src/pycode.l @@ -106,6 +106,7 @@ struct pycodeYY_state bool endComment = FALSE; VariableContext theVarContext; CallContext theCallContext; + TooltipManager tooltipManager; }; @@ -147,7 +148,6 @@ static void addVariable(yyscan_t yyscanner, QCString type, QCString name); //------------------------------------------------------------------- static std::mutex g_searchIndexMutex; -static std::mutex g_tooltipMutex; //------------------------------------------------------------------- @@ -1087,10 +1087,7 @@ static void writeMultiLineCodeLink(yyscan_t yyscanner, { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); - { - std::lock_guard<std::mutex> lock(g_tooltipMutex); - TooltipManager::instance()->addTooltip(d); - } + yyextra->tooltipManager.addTooltip(d); QCString ref = d->getReference(); QCString file = d->getOutputFileBase(); QCString anchor = d->anchor(); @@ -1629,6 +1626,8 @@ void PythonCodeParser::parseCode(CodeOutputInterface &codeOutIntf, delete yyextra->sourceFileDef; yyextra->sourceFileDef=0; } + // write the tooltips + yyextra->tooltipManager.writeTooltips(codeOutIntf); printlex(yy_flex_debug, FALSE, __FILE__, fileDef ? fileDef->fileName().data(): NULL); } diff --git a/src/sqlite3gen.cpp b/src/sqlite3gen.cpp index 235479d..76ac77d 100644 --- a/src/sqlite3gen.cpp +++ b/src/sqlite3gen.cpp @@ -1619,26 +1619,16 @@ static void generateSqlite3ForMember(const MemberDef *md, struct Refid scope_ref // + source references // The cross-references in initializers only work when both the src and dst // are defined. - MemberSDict *mdict = md->getReferencesMembers(); - if (mdict!=0) + auto refList = md->getReferencesMembers(); + for (const auto &rmd : refList) { - MemberSDict::IteratorDict mdi(*mdict); - const MemberDef *rmd; - for (mdi.toFirst();(rmd=mdi.current());++mdi) - { - insertMemberReference(md,rmd, "inline"); - } + insertMemberReference(md,rmd, "inline"); } // + source referenced by - mdict = md->getReferencedByMembers(); - if (mdict!=0) + auto refByList = md->getReferencedByMembers(); + for (const auto &rmd : refByList) { - MemberSDict::IteratorDict mdi(*mdict); - const MemberDef *rmd; - for (mdi.toFirst();(rmd=mdi.current());++mdi) - { - insertMemberReference(rmd,md, "inline"); - } + insertMemberReference(rmd,md, "inline"); } return; } @@ -1856,24 +1846,16 @@ static void generateSqlite3ForMember(const MemberDef *md, struct Refid scope_ref // + source references // The cross-references in initializers only work when both the src and dst // are defined. - MemberSDict *mdict = md->getReferencesMembers(); - if (mdict!=0) + auto refList = md->getReferencesMembers(); + for (const auto &refmd : refList) { - MemberSDict::IteratorDict mdi(*mdict); - for (mdi.toFirst();(rmd=mdi.current());++mdi) - { - insertMemberReference(md,rmd, "inline"); - } + insertMemberReference(md,refmd, "inline"); } // + source referenced by - mdict = md->getReferencedByMembers(); - if (mdict!=0) + auto refByList = md->getReferencedByMembers(); + for (const auto &refmd : refByList) { - MemberSDict::IteratorDict mdi(*mdict); - for (mdi.toFirst();(rmd=mdi.current());++mdi) - { - insertMemberReference(rmd,md, "inline"); - } + insertMemberReference(refmd,md, "inline"); } } diff --git a/src/tooltip.cpp b/src/tooltip.cpp index 8cc1f87..32b43fa 100644 --- a/src/tooltip.cpp +++ b/src/tooltip.cpp @@ -1,10 +1,10 @@ /****************************************************************************** * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 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 + * 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. * @@ -13,7 +13,8 @@ * */ -#include <qdict.h> +#include <map> +#include <string> #include "tooltip.h" #include "definition.h" @@ -26,34 +27,15 @@ class TooltipManager::Private { public: - Private() : tooltipInfo(10007) {} - QDict<Definition> tooltipInfo; + std::map<std::string,const Definition*> tooltipInfo; }; -TooltipManager *TooltipManager::s_theInstance = 0; - -TooltipManager::TooltipManager() +TooltipManager::TooltipManager() : p(std::make_unique<Private>()) { - p = new Private; } TooltipManager::~TooltipManager() { - delete p; -} - -TooltipManager *TooltipManager::instance() -{ - if (!s_theInstance) - { - s_theInstance = new TooltipManager; - } - return s_theInstance; -} - -void TooltipManager::clearTooltips() -{ - p->tooltipInfo.clear(); } static QCString escapeId(const char *s) @@ -70,7 +52,7 @@ static QCString escapeId(const char *s) void TooltipManager::addTooltip(const Definition *d) { - static bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); + bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); if (!sourceTooltips) return; QCString id = d->getOutputFileBase(); int i=id.findRev('/'); @@ -85,18 +67,14 @@ void TooltipManager::addTooltip(const Definition *d) id+="_"+anc; } id = "a" + id; - if (p->tooltipInfo.find(id)==0) - { - p->tooltipInfo.insert(id,d); - } + p->tooltipInfo.insert({id.str(),d}); } void TooltipManager::writeTooltips(CodeOutputInterface &ol) { - QDictIterator<Definition> di(p->tooltipInfo); - Definition *d; - for (di.toFirst();(d=di.current());++di) + for (const auto &kv : p->tooltipInfo) { + const Definition *d = kv.second; DocLinkInfo docInfo; docInfo.name = d->qualifiedName(); docInfo.ref = d->getReference(); @@ -114,13 +92,13 @@ void TooltipManager::writeTooltips(CodeOutputInterface &ol) QCString decl; if (d->definitionType()==Definition::TypeMember) { - MemberDef *md = dynamic_cast<MemberDef*>(d); + const MemberDef *md = dynamic_cast<const MemberDef*>(d); if (!md->isAnonymous()) { decl = md->declaration(); } } - ol.writeTooltip(di.currentKey(), // id + ol.writeTooltip(kv.first.c_str(), // id docInfo, // symName decl, // decl d->briefDescriptionAsTooltip(), // desc diff --git a/src/tooltip.h b/src/tooltip.h index 170ea3c..3517b5d 100644 --- a/src/tooltip.h +++ b/src/tooltip.h @@ -1,10 +1,10 @@ /****************************************************************************** * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 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 + * 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. * @@ -15,23 +15,27 @@ #ifndef TOOLTIP_H #define TOOLTIP_H +#include <memory> + class Definition; class CodeOutputInterface; +//! Class that manages the tooltips for a source file class TooltipManager { public: - static TooltipManager *instance(); - void clearTooltips(); + TooltipManager(); + ~TooltipManager(); + + /** add a tooltip for a given symbol definition */ void addTooltip(const Definition *d); + + /** write the list of all collected tooltip to the given outputs */ void writeTooltips(CodeOutputInterface &ol); private: class Private; - Private *p; - TooltipManager(); - ~TooltipManager(); - static TooltipManager *s_theInstance; + std::unique_ptr<Private> p; }; #endif diff --git a/src/vhdlcode.l b/src/vhdlcode.l index cecf9fb..7610c9a 100644 --- a/src/vhdlcode.l +++ b/src/vhdlcode.l @@ -109,6 +109,7 @@ struct vhdlcodeYY_state bool lexInit = false; int braceCount = 0; + TooltipManager tooltipManager; }; @@ -1229,7 +1230,7 @@ static void writeMultiLineCodeLink(yyscan_t yyscanner,CodeOutputInterface &ol, { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; static bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); - TooltipManager::instance()->addTooltip(d); + yyextra->tooltipManager.addTooltip(d); QCString ref = d->getReference(); QCString file = d->getOutputFileBase(); QCString anchor = d->anchor(); @@ -1656,6 +1657,10 @@ void VHDLCodeParser::parseCode(CodeOutputInterface &od, yyextra->sourceFileDef=0; } yyextra->startCode=false; + + // write the tooltips + yyextra->tooltipManager.writeTooltips(od); + printlex(yy_flex_debug, false, __FILE__, fd ? fd->fileName().data(): NULL); } diff --git a/src/xmlgen.cpp b/src/xmlgen.cpp index a842841..1993c1e 100644 --- a/src/xmlgen.cpp +++ b/src/xmlgen.cpp @@ -1021,23 +1021,15 @@ static void generateXMLForMember(const MemberDef *md,FTextStream &ti,FTextStream } //printf("md->getReferencesMembers()=%p\n",md->getReferencesMembers()); - MemberSDict *mdict = md->getReferencesMembers(); - if (mdict) + auto refList = md->getReferencesMembers(); + for (const auto &refmd : refList) { - MemberSDict::Iterator mdi(*mdict); - for (mdi.toFirst();(rmd=mdi.current());++mdi) - { - writeMemberReference(t,def,rmd,"references"); - } + writeMemberReference(t,def,refmd,"references"); } - mdict = md->getReferencedByMembers(); - if (mdict) + auto refByList = md->getReferencedByMembers(); + for (const auto &refmd : refByList) { - MemberSDict::Iterator mdi(*mdict); - for (mdi.toFirst();(rmd=mdi.current());++mdi) - { - writeMemberReference(t,def,rmd,"referencedby"); - } + writeMemberReference(t,def,refmd,"referencedby"); } t << " </memberdef>" << endl; |