From 438375840da2b1ea19126f8d4b53f0bc71c62a68 Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Thu, 6 Jun 2013 22:08:42 +0200 Subject: Bug 700740 - Doxygen does not create links on C++ 11 style enum classes --- src/code.l | 6 +-- src/memberdef.cpp | 14 ++++- src/memberdef.h | 1 + src/util.cpp | 155 ++++++++++++++++++++++++++++++++++++++++++------------ 4 files changed, 138 insertions(+), 38 deletions(-) diff --git a/src/code.l b/src/code.l index 01636fa..d38f492 100644 --- a/src/code.l +++ b/src/code.l @@ -863,7 +863,7 @@ static bool getLinkInScope(const QCString &c, // scope } Definition *d = md->getOuterScope()==Doxygen::globalScope ? - md->getBodyDef() : md->getOuterScope(); + md->getFileDef() : md->getOuterScope(); if (md->getGroupDef()) d = md->getGroupDef(); if (d && d->isLinkable()) { @@ -1000,7 +1000,7 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName if (md) { Definition *d = md->getOuterScope()==Doxygen::globalScope ? - md->getBodyDef() : md->getOuterScope(); + md->getFileDef() : md->getOuterScope(); if (md->getGroupDef()) d = md->getGroupDef(); if (d && d->isLinkable() && md->isLinkable() && g_currentMemberDef) { @@ -1098,7 +1098,7 @@ static bool generateClassMemberLink(CodeOutputInterface &ol,MemberDef *xmd,const g_theCallContext.setClass(typeClass); Definition *xd = xmd->getOuterScope()==Doxygen::globalScope ? - xmd->getBodyDef() : xmd->getOuterScope(); + xmd->getFileDef() : xmd->getOuterScope(); if (xmd->getGroupDef()) xd = xmd->getGroupDef(); if (xd && xd->isLinkable()) { diff --git a/src/memberdef.cpp b/src/memberdef.cpp index c5bf787..deed432 100644 --- a/src/memberdef.cpp +++ b/src/memberdef.cpp @@ -3795,6 +3795,12 @@ QCString MemberDef::qualifiedName() const qm+="]"; return qm; } + else if (m_impl->enumScope && m_impl->enumScope->isStrong()) + { + return m_impl->enumScope->qualifiedName()+ + getLanguageSpecificSeparator(getLanguage())+ + localName(); + } else { return Definition::qualifiedName(); @@ -4139,6 +4145,13 @@ bool MemberDef::isStrong() const return (m_impl->memSpec&Entry::Strong)!=0; } +bool MemberDef::isStrongEnumValue() const +{ + return m_impl->mtype==MemberType_EnumValue && + m_impl->enumScope && + m_impl->enumScope->isStrong(); +} + bool MemberDef::isUnretained() const { return (m_impl->memSpec&Entry::Unretained)!=0; @@ -4845,4 +4858,3 @@ void combineDeclarationAndDefinition(MemberDef *mdec,MemberDef *mdef) } } - diff --git a/src/memberdef.h b/src/memberdef.h index 8c88f7c..fc2bb44 100644 --- a/src/memberdef.h +++ b/src/memberdef.h @@ -169,6 +169,7 @@ class MemberDef : public Definition bool hasMultiLineInitializer() const; bool protectionVisible() const; bool showInCallGraph() const; + bool isStrongEnumValue() const; // output info bool isLinkableInProject() const; diff --git a/src/util.cpp b/src/util.cpp index 0c36fc0..6ac1585 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -1873,20 +1873,24 @@ int findParameterList(const QString &name) bool rightScopeMatch(const QCString &scope, const QCString &name) { + int sl=scope.length(); + int nl=name.length(); return (name==scope || // equal - (scope.right(name.length())==name && // substring - scope.at(scope.length()-name.length()-1)==':' // scope - ) - ); + (scope.right(nl)==name && // substring + sl-nl>1 && scope.at(sl-nl-1)==':' && scope.at(sl-nl-2)==':' // scope + ) + ); } bool leftScopeMatch(const QCString &scope, const QCString &name) { + int sl=scope.length(); + int nl=name.length(); return (name==scope || // equal - (scope.left(name.length())==name && // substring - scope.at(name.length())==':' // scope - ) - ); + (scope.left(nl)==name && // substring + sl>nl+1 && scope.at(nl)==':' && scope.at(nl+1)==':' // scope + ) + ); } @@ -3972,8 +3976,9 @@ bool getDefs(const QCString &scName, className=mScope; } - ClassDef *fcd=getResolvedClass(Doxygen::globalScope,0,className); - //printf("Trying class scope %s: %p\n",className.data(),fcd); + MemberDef *tmd=0; + ClassDef *fcd=getResolvedClass(Doxygen::globalScope,0,className,&tmd); + //printf("Trying class scope %s: fcd=%p tmd=%p\n",className.data(),fcd,tmd); // todo: fill in correct fileScope! if (fcd && // is it a documented class fcd->isLinkable() @@ -3991,30 +3996,30 @@ bool getDefs(const QCString &scName, } for (mmli.toFirst();(mmd=mmli.current());++mmli) { - //if (mmd->isLinkable()) - //{ - ArgumentList *mmdAl = mmd->argumentList(); - bool match=args==0 || - matchArguments2(mmd->getOuterScope(),mmd->getFileDef(),mmdAl, - fcd,fcd->getFileDef(),argList, - checkCV - ); - //printf("match=%d\n",match); - if (match) + if (!mmd->isStrongEnumValue()) { - ClassDef *mcd=mmd->getClassDef(); - if (mcd) + ArgumentList *mmdAl = mmd->argumentList(); + bool match=args==0 || + matchArguments2(mmd->getOuterScope(),mmd->getFileDef(),mmdAl, + fcd,fcd->getFileDef(),argList, + checkCV + ); + //printf("match=%d\n",match); + if (match) { - int m=minClassDistance(fcd,mcd); - if (misLinkable()) + ClassDef *mcd=mmd->getClassDef(); + if (mcd) { - mdist=m; - cd=mcd; - md=mmd; + int m=minClassDistance(fcd,mcd); + if (misLinkable()) + { + mdist=m; + cd=mcd; + md=mmd; + } } } } - //} } if (argList) { @@ -4047,7 +4052,7 @@ bool getDefs(const QCString &scName, //printf(" >Succes=%d\n",mdistisLinkable()) + if (!md->isLinkable() || md->isStrongEnumValue()) { md=0; // avoid returning things we cannot link to cd=0; @@ -4061,6 +4066,34 @@ bool getDefs(const QCString &scName, } } } + if (tmd && tmd->isEnumerate() && tmd->isStrong()) // scoped enum + { + //printf("Found scoped enum!\n"); + MemberList *tml = tmd->enumFieldList(); + if (tml) + { + MemberListIterator tmi(*tml); + MemberDef *emd; + for (;(emd=tmi.current());++tmi) + { + if (emd->localName()==mName) + { + if (emd->isLinkable()) + { + cd=tmd->getClassDef(); + md=emd; + } + else + { + cd=0; + md=0; + } + //printf("result cd=%p md=%p\n",cd,md); + return TRUE; + } + } + } + } /* go to the parent scope */ if (scopeOffset==0) { @@ -4075,6 +4108,7 @@ bool getDefs(const QCString &scName, } if (mn && scopeName.isEmpty() && mScope.isEmpty()) // Maybe a related function? { + //printf("Global symbol\n"); MemberListIterator mmli(*mn); MemberDef *mmd, *fuzzy_mmd = 0; ArgumentList *argList = 0; @@ -4108,7 +4142,7 @@ bool getDefs(const QCString &scName, mmd = mmd ? mmd : fuzzy_mmd; - if (mmd) + if (mmd && !mmd->isStrongEnumValue()) { md = mmd; cd = mmd->getClassDef(); @@ -4142,7 +4176,8 @@ bool getDefs(const QCString &scName, fnd->isLinkable() ) { - //printf("Function inside existing namespace `%s'\n",namespaceName.data()); + //printf("Symbol inside existing namespace `%s' count=%d\n", + // namespaceName.data(),mn->count()); bool found=FALSE; MemberListIterator mmli(*mn); MemberDef *mmd; @@ -4150,7 +4185,26 @@ bool getDefs(const QCString &scName, { //printf("mmd->getNamespaceDef()=%p fnd=%p\n", // mmd->getNamespaceDef(),fnd); - if (mmd->getNamespaceDef()==fnd /* && mmd->isLinkable() */ ) + MemberDef *emd = mmd->getEnumScope(); + if (emd && emd->isStrong()) + { + //printf("yes match %s<->%s!\n",mScope.data(),emd->localName().data()); + if (emd->getNamespaceDef()==fnd && + rightScopeMatch(mScope,emd->localName())) + { + //printf("found it!\n"); + nd=fnd; + md=mmd; + found=TRUE; + } + else + { + md=0; + cd=0; + return FALSE; + } + } + else if (mmd->getNamespaceDef()==fnd /* && mmd->isLinkable() */ ) { // namespace is found bool match=TRUE; ArgumentList *argList=0; @@ -4206,6 +4260,35 @@ bool getDefs(const QCString &scName, } } } + else + { + //printf("not a namespace\n"); + bool found=FALSE; + MemberListIterator mmli(*mn); + MemberDef *mmd; + for (mmli.toFirst();((mmd=mmli.current()) && !found);++mmli) + { + MemberDef *tmd = mmd->getEnumScope(); + //printf("try member %s tmd=%s\n",mmd->name().data(),tmd?tmd->name().data():""); + int ni=namespaceName.findRev("::"); + bool notInNS = tmd && ni==-1 && tmd->getNamespaceDef()==0; + bool sameNS = tmd && tmd->getNamespaceDef() && namespaceName.left(ni)==tmd->getNamespaceDef()->name(); + //printf("notInNS=%d sameNS=%d\n",notInNS,sameNS); + if (tmd && tmd->isStrong() && // C++11 enum class + (notInNS || sameNS) && + namespaceName.length()>0 // enum is part of namespace so this should not be empty + ) + { + md=mmd; + fd=mmd->getFileDef(); + gd=mmd->getGroupDef(); + if (gd && gd->isLinkable()) fd=0; else gd=0; + //printf("Found scoped enum %s fd=%p gd=%p\n", + // mmd->name().data(),fd,gd); + return TRUE; + } + } + } if (scopeOffset==0) { scopeOffset=-1; @@ -4238,8 +4321,10 @@ bool getDefs(const QCString &scName, //printf("member is linkable md->name()=`%s'\n",md->name().data()); fd=md->getFileDef(); gd=md->getGroupDef(); + MemberDef *tmd = md->getEnumScope(); if ( - (gd && gd->isLinkable()) || (fd && fd->isLinkable()) + (gd && gd->isLinkable()) || (fd && fd->isLinkable()) || + (tmd && tmd->isStrong()) ) { members.append(md); @@ -4252,7 +4337,8 @@ bool getDefs(const QCString &scName, { md=members.last(); } - if (md) // found a matching global member + if (md && (md->getEnumScope()==0 || !md->getEnumScope()->isStrong())) + // found a matching global member, that is not a scoped enum value (or uniquely matches) { fd=md->getFileDef(); gd=md->getGroupDef(); @@ -4466,6 +4552,7 @@ bool resolveRef(/* in */ const char *scName, { //printf("after getDefs checkScope=%d nameStr=%s cd=%p nd=%p\n",checkScope,nameStr.data(),cd,nd); if (checkScope && md && md->getOuterScope()==Doxygen::globalScope && + !md->isStrongEnumValue() && (!scopeStr.isEmpty() || nameStr.find("::")>0)) { // we did find a member, but it is a global one while we were explicitly -- cgit v0.12