Commit a577a27e authored by Dimitri van Heesch's avatar Dimitri van Heesch

Bug 700740 - Doxygen does not create links on C++ 11 style enum classes

parent 8295d3ff
...@@ -863,7 +863,7 @@ static bool getLinkInScope(const QCString &c, // scope ...@@ -863,7 +863,7 @@ static bool getLinkInScope(const QCString &c, // scope
} }
Definition *d = md->getOuterScope()==Doxygen::globalScope ? Definition *d = md->getOuterScope()==Doxygen::globalScope ?
md->getBodyDef() : md->getOuterScope(); md->getFileDef() : md->getOuterScope();
if (md->getGroupDef()) d = md->getGroupDef(); if (md->getGroupDef()) d = md->getGroupDef();
if (d && d->isLinkable()) if (d && d->isLinkable())
{ {
...@@ -1000,7 +1000,7 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName ...@@ -1000,7 +1000,7 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName
if (md) if (md)
{ {
Definition *d = md->getOuterScope()==Doxygen::globalScope ? Definition *d = md->getOuterScope()==Doxygen::globalScope ?
md->getBodyDef() : md->getOuterScope(); md->getFileDef() : md->getOuterScope();
if (md->getGroupDef()) d = md->getGroupDef(); if (md->getGroupDef()) d = md->getGroupDef();
if (d && d->isLinkable() && md->isLinkable() && g_currentMemberDef) if (d && d->isLinkable() && md->isLinkable() && g_currentMemberDef)
{ {
...@@ -1098,7 +1098,7 @@ static bool generateClassMemberLink(CodeOutputInterface &ol,MemberDef *xmd,const ...@@ -1098,7 +1098,7 @@ static bool generateClassMemberLink(CodeOutputInterface &ol,MemberDef *xmd,const
g_theCallContext.setClass(typeClass); g_theCallContext.setClass(typeClass);
Definition *xd = xmd->getOuterScope()==Doxygen::globalScope ? Definition *xd = xmd->getOuterScope()==Doxygen::globalScope ?
xmd->getBodyDef() : xmd->getOuterScope(); xmd->getFileDef() : xmd->getOuterScope();
if (xmd->getGroupDef()) xd = xmd->getGroupDef(); if (xmd->getGroupDef()) xd = xmd->getGroupDef();
if (xd && xd->isLinkable()) if (xd && xd->isLinkable())
{ {
......
...@@ -3795,6 +3795,12 @@ QCString MemberDef::qualifiedName() const ...@@ -3795,6 +3795,12 @@ QCString MemberDef::qualifiedName() const
qm+="]"; qm+="]";
return qm; return qm;
} }
else if (m_impl->enumScope && m_impl->enumScope->isStrong())
{
return m_impl->enumScope->qualifiedName()+
getLanguageSpecificSeparator(getLanguage())+
localName();
}
else else
{ {
return Definition::qualifiedName(); return Definition::qualifiedName();
...@@ -4139,6 +4145,13 @@ bool MemberDef::isStrong() const ...@@ -4139,6 +4145,13 @@ bool MemberDef::isStrong() const
return (m_impl->memSpec&Entry::Strong)!=0; 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 bool MemberDef::isUnretained() const
{ {
return (m_impl->memSpec&Entry::Unretained)!=0; return (m_impl->memSpec&Entry::Unretained)!=0;
...@@ -4845,4 +4858,3 @@ void combineDeclarationAndDefinition(MemberDef *mdec,MemberDef *mdef) ...@@ -4845,4 +4858,3 @@ void combineDeclarationAndDefinition(MemberDef *mdec,MemberDef *mdef)
} }
} }
...@@ -169,6 +169,7 @@ class MemberDef : public Definition ...@@ -169,6 +169,7 @@ class MemberDef : public Definition
bool hasMultiLineInitializer() const; bool hasMultiLineInitializer() const;
bool protectionVisible() const; bool protectionVisible() const;
bool showInCallGraph() const; bool showInCallGraph() const;
bool isStrongEnumValue() const;
// output info // output info
bool isLinkableInProject() const; bool isLinkableInProject() const;
......
...@@ -1873,18 +1873,22 @@ int findParameterList(const QString &name) ...@@ -1873,18 +1873,22 @@ int findParameterList(const QString &name)
bool rightScopeMatch(const QCString &scope, const QCString &name) bool rightScopeMatch(const QCString &scope, const QCString &name)
{ {
int sl=scope.length();
int nl=name.length();
return (name==scope || // equal return (name==scope || // equal
(scope.right(name.length())==name && // substring (scope.right(nl)==name && // substring
scope.at(scope.length()-name.length()-1)==':' // scope sl-nl>1 && scope.at(sl-nl-1)==':' && scope.at(sl-nl-2)==':' // scope
) )
); );
} }
bool leftScopeMatch(const QCString &scope, const QCString &name) bool leftScopeMatch(const QCString &scope, const QCString &name)
{ {
int sl=scope.length();
int nl=name.length();
return (name==scope || // equal return (name==scope || // equal
(scope.left(name.length())==name && // substring (scope.left(nl)==name && // substring
scope.at(name.length())==':' // scope sl>nl+1 && scope.at(nl)==':' && scope.at(nl+1)==':' // scope
) )
); );
} }
...@@ -3972,8 +3976,9 @@ bool getDefs(const QCString &scName, ...@@ -3972,8 +3976,9 @@ bool getDefs(const QCString &scName,
className=mScope; className=mScope;
} }
ClassDef *fcd=getResolvedClass(Doxygen::globalScope,0,className); MemberDef *tmd=0;
//printf("Trying class scope %s: %p\n",className.data(),fcd); 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! // todo: fill in correct fileScope!
if (fcd && // is it a documented class if (fcd && // is it a documented class
fcd->isLinkable() fcd->isLinkable()
...@@ -3991,8 +3996,8 @@ bool getDefs(const QCString &scName, ...@@ -3991,8 +3996,8 @@ bool getDefs(const QCString &scName,
} }
for (mmli.toFirst();(mmd=mmli.current());++mmli) for (mmli.toFirst();(mmd=mmli.current());++mmli)
{ {
//if (mmd->isLinkable()) if (!mmd->isStrongEnumValue())
//{ {
ArgumentList *mmdAl = mmd->argumentList(); ArgumentList *mmdAl = mmd->argumentList();
bool match=args==0 || bool match=args==0 ||
matchArguments2(mmd->getOuterScope(),mmd->getFileDef(),mmdAl, matchArguments2(mmd->getOuterScope(),mmd->getFileDef(),mmdAl,
...@@ -4014,7 +4019,7 @@ bool getDefs(const QCString &scName, ...@@ -4014,7 +4019,7 @@ bool getDefs(const QCString &scName,
} }
} }
} }
//} }
} }
if (argList) if (argList)
{ {
...@@ -4047,7 +4052,7 @@ bool getDefs(const QCString &scName, ...@@ -4047,7 +4052,7 @@ bool getDefs(const QCString &scName,
//printf(" >Succes=%d\n",mdist<maxInheritanceDepth); //printf(" >Succes=%d\n",mdist<maxInheritanceDepth);
if (mdist<maxInheritanceDepth) if (mdist<maxInheritanceDepth)
{ {
if (!md->isLinkable()) if (!md->isLinkable() || md->isStrongEnumValue())
{ {
md=0; // avoid returning things we cannot link to md=0; // avoid returning things we cannot link to
cd=0; cd=0;
...@@ -4061,6 +4066,34 @@ bool getDefs(const QCString &scName, ...@@ -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 */ /* go to the parent scope */
if (scopeOffset==0) if (scopeOffset==0)
{ {
...@@ -4075,6 +4108,7 @@ bool getDefs(const QCString &scName, ...@@ -4075,6 +4108,7 @@ bool getDefs(const QCString &scName,
} }
if (mn && scopeName.isEmpty() && mScope.isEmpty()) // Maybe a related function? if (mn && scopeName.isEmpty() && mScope.isEmpty()) // Maybe a related function?
{ {
//printf("Global symbol\n");
MemberListIterator mmli(*mn); MemberListIterator mmli(*mn);
MemberDef *mmd, *fuzzy_mmd = 0; MemberDef *mmd, *fuzzy_mmd = 0;
ArgumentList *argList = 0; ArgumentList *argList = 0;
...@@ -4108,7 +4142,7 @@ bool getDefs(const QCString &scName, ...@@ -4108,7 +4142,7 @@ bool getDefs(const QCString &scName,
mmd = mmd ? mmd : fuzzy_mmd; mmd = mmd ? mmd : fuzzy_mmd;
if (mmd) if (mmd && !mmd->isStrongEnumValue())
{ {
md = mmd; md = mmd;
cd = mmd->getClassDef(); cd = mmd->getClassDef();
...@@ -4142,7 +4176,8 @@ bool getDefs(const QCString &scName, ...@@ -4142,7 +4176,8 @@ bool getDefs(const QCString &scName,
fnd->isLinkable() 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; bool found=FALSE;
MemberListIterator mmli(*mn); MemberListIterator mmli(*mn);
MemberDef *mmd; MemberDef *mmd;
...@@ -4150,7 +4185,26 @@ bool getDefs(const QCString &scName, ...@@ -4150,7 +4185,26 @@ bool getDefs(const QCString &scName,
{ {
//printf("mmd->getNamespaceDef()=%p fnd=%p\n", //printf("mmd->getNamespaceDef()=%p fnd=%p\n",
// mmd->getNamespaceDef(),fnd); // 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 { // namespace is found
bool match=TRUE; bool match=TRUE;
ArgumentList *argList=0; ArgumentList *argList=0;
...@@ -4206,6 +4260,35 @@ bool getDefs(const QCString &scName, ...@@ -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():"<none>");
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) if (scopeOffset==0)
{ {
scopeOffset=-1; scopeOffset=-1;
...@@ -4238,8 +4321,10 @@ bool getDefs(const QCString &scName, ...@@ -4238,8 +4321,10 @@ bool getDefs(const QCString &scName,
//printf("member is linkable md->name()=`%s'\n",md->name().data()); //printf("member is linkable md->name()=`%s'\n",md->name().data());
fd=md->getFileDef(); fd=md->getFileDef();
gd=md->getGroupDef(); gd=md->getGroupDef();
MemberDef *tmd = md->getEnumScope();
if ( if (
(gd && gd->isLinkable()) || (fd && fd->isLinkable()) (gd && gd->isLinkable()) || (fd && fd->isLinkable()) ||
(tmd && tmd->isStrong())
) )
{ {
members.append(md); members.append(md);
...@@ -4252,7 +4337,8 @@ bool getDefs(const QCString &scName, ...@@ -4252,7 +4337,8 @@ bool getDefs(const QCString &scName,
{ {
md=members.last(); 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(); fd=md->getFileDef();
gd=md->getGroupDef(); gd=md->getGroupDef();
...@@ -4466,6 +4552,7 @@ bool resolveRef(/* in */ const char *scName, ...@@ -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); //printf("after getDefs checkScope=%d nameStr=%s cd=%p nd=%p\n",checkScope,nameStr.data(),cd,nd);
if (checkScope && md && md->getOuterScope()==Doxygen::globalScope && if (checkScope && md && md->getOuterScope()==Doxygen::globalScope &&
!md->isStrongEnumValue() &&
(!scopeStr.isEmpty() || nameStr.find("::")>0)) (!scopeStr.isEmpty() || nameStr.find("::")>0))
{ {
// we did find a member, but it is a global one while we were explicitly // we did find a member, but it is a global one while we were explicitly
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment