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
}
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())
{
......
......@@ -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)
}
}
......@@ -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;
......
......@@ -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 (m<mdist && mcd->isLinkable())
ClassDef *mcd=mmd->getClassDef();
if (mcd)
{
mdist=m;
cd=mcd;
md=mmd;
int m=minClassDistance(fcd,mcd);
if (m<mdist && mcd->isLinkable())
{
mdist=m;
cd=mcd;
md=mmd;
}
}
}
}
//}
}
if (argList)
{
......@@ -4047,7 +4052,7 @@ bool getDefs(const QCString &scName,
//printf(" >Succes=%d\n",mdist<maxInheritanceDepth);
if (mdist<maxInheritanceDepth)
{
if (!md->isLinkable())
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():"<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)
{
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
......
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