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

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

parent 8295d3ff
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -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())
  {
+13 −1
Original line number Diff line number Diff line
@@ -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)
  }
}
+1 −0
Original line number Diff line number Diff line
@@ -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;
+121 −34
Original line number Diff line number Diff line
@@ -1873,18 +1873,22 @@ 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,8 +3996,8 @@ bool getDefs(const QCString &scName,
        }
        for (mmli.toFirst();(mmd=mmli.current());++mmli)
        {
          //if (mmd->isLinkable())
          //{
          if (!mmd->isStrongEnumValue())
          {
            ArgumentList *mmdAl = mmd->argumentList();
            bool match=args==0 || 
              matchArguments2(mmd->getOuterScope(),mmd->getFileDef(),mmdAl,
@@ -4014,7 +4019,7 @@ bool getDefs(const QCString &scName,
                }
              }
            }
          //}
          }
        }
        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