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

Add support for writing and importing C++11 style enums to and from tag files

parent 0651fff2
Loading
Loading
Loading
Loading
+5 −3
Original line number Original line Diff line number Diff line
@@ -7187,10 +7187,12 @@ static void addEnumValuesToEnums(EntryNav *rootNav)
                // them here and only add them to the enum
                // them here and only add them to the enum
                e->loadEntry(g_storage);
                e->loadEntry(g_storage);
                Entry *root = e->entry();
                Entry *root = e->entry();
                //printf("md->qualifiedName()=%s rootNav->name()=%s\n",
                //printf("md->qualifiedName()=%s rootNav->name()=%s tagInfo=%p\n",
                //    md->qualifiedName().data(),rootNav->name().data());
                //    md->qualifiedName().data(),rootNav->name().data(),rootNav->tagInfo());
                if (substitute(md->qualifiedName(),"::",".")== // TODO: add function to get canonical representation
                if (substitute(md->qualifiedName(),"::",".")== // TODO: add function to get canonical representation
                    substitute(rootNav->name(),"::",".")) // enum value scope matches that of the enum
                    substitute(rootNav->name(),"::",".") ||    // enum value scope matches that of the enum
                    rootNav->tagInfo()                         // be less strict for tag files as members can have incomplete scope
                   ) 
                {
                {
                  MemberDef *fmd=new MemberDef(
                  MemberDef *fmd=new MemberDef(
                      root->fileName,root->startLine,root->startColumn,
                      root->fileName,root->startLine,root->startColumn,
+20 −23
Original line number Original line Diff line number Diff line
@@ -3397,6 +3397,8 @@ void MemberDef::_writeTagData(const DefType compoundType)
{ 
{ 
  unsigned typeMask = 1 << compoundType;
  unsigned typeMask = 1 << compoundType;
  if ((m_impl->tagDataWritten) & typeMask) return; // member already written for this type
  if ((m_impl->tagDataWritten) & typeMask) return; // member already written for this type
  if (m_impl->mtype==MemberType_EnumValue && m_impl->enumScope &&
      m_impl->enumScope->isStrong()) return; // enum value is part of enum
  static bool generateTagFile = !Config_getString("GENERATE_TAGFILE").isEmpty();
  static bool generateTagFile = !Config_getString("GENERATE_TAGFILE").isEmpty();
  // write tag file information of this member
  // write tag file information of this member
  if (generateTagFile && isLinkableInProject())
  if (generateTagFile && isLinkableInProject())
@@ -3447,10 +3449,8 @@ void MemberDef::_writeTagData(const DefType compoundType)
      Doxygen::tagFile << "      <clangid>" << convertToXML(idStr) << "</clangid>" << endl;
      Doxygen::tagFile << "      <clangid>" << convertToXML(idStr) << "</clangid>" << endl;
    }
    }
    Doxygen::tagFile << "      <arglist>" << convertToXML(argsString()) << "</arglist>" << endl;
    Doxygen::tagFile << "      <arglist>" << convertToXML(argsString()) << "</arglist>" << endl;
    writeDocAnchorsToTagFile();
    if (isStrong())
    Doxygen::tagFile << "    </member>" << endl;
    {
    _addToSearchIndex();
  }
      MemberList *fmdl=m_impl->enumFields;
      MemberList *fmdl=m_impl->enumFields;
      if (fmdl)
      if (fmdl)
      {
      {
@@ -3460,24 +3460,21 @@ void MemberDef::_writeTagData(const DefType compoundType)
        {
        {
          if (!fmd->isReference())
          if (!fmd->isReference())
          {
          {
        if (!Config_getString("GENERATE_TAGFILE").isEmpty())
            Doxygen::tagFile << "      <enumvalue file=\"" << convertToXML(getOutputFileBase()+Doxygen::htmlFileExtension);
        {
            Doxygen::tagFile << "\" anchor=\"" << convertToXML(fmd->anchor());
          Doxygen::tagFile << "    <member kind=\"enumvalue\">" << endl;
          Doxygen::tagFile << "      <name>" << convertToXML(fmd->name()) << "</name>" << endl; 
          Doxygen::tagFile << "      <anchorfile>" << convertToXML(getOutputFileBase()+Doxygen::htmlFileExtension) << "</anchorfile>" << endl;              
          Doxygen::tagFile << "      <anchor>" << convertToXML(fmd->anchor()) << "</anchor>" << endl; 
            QCString idStr = fmd->id();
            QCString idStr = fmd->id();
            if (!idStr.isEmpty()) 
            if (!idStr.isEmpty()) 
            {
            {
            Doxygen::tagFile << "      <clangid>" << convertToXML(idStr) << "</clangid>" << endl;
              Doxygen::tagFile << "\" clangid=\"" << convertToXML(idStr);
            }
            Doxygen::tagFile  << "\">" << convertToXML(fmd->name()) << "</enumvalue>" << endl; 
          }
          }
          Doxygen::tagFile << "      <arglist>" << convertToXML(fmd->argsString()) << "</arglist>" << endl; 
          Doxygen::tagFile << "    </member>" << endl;
          fmd->m_impl->tagDataWritten |= typeMask;
          fmd->_addToSearchIndex();
        }
        }
      }
      }
    }
    }
    writeDocAnchorsToTagFile();
    Doxygen::tagFile << "    </member>" << endl;
    _addToSearchIndex();
  }
  }
  m_impl->tagDataWritten |= typeMask;
  m_impl->tagDataWritten |= typeMask;
}
}
+67 −1
Original line number Original line Diff line number Diff line
@@ -61,11 +61,22 @@ class TagAnchorInfoList : public QList<TagAnchorInfo>
    virtual ~TagAnchorInfoList() {}
    virtual ~TagAnchorInfoList() {}
};
};


/** Container for enum values that are scoped within an enum */
class TagEnumValueInfo
{
  public:
    QCString name;
    QCString file;
    QCString anchor;
    QCString clangid;
};

/** Container for member specific info that can be read from a tagfile */
/** Container for member specific info that can be read from a tagfile */
class TagMemberInfo
class TagMemberInfo
{
{
  public:
  public:
    TagMemberInfo() : prot(Public), virt(Normal), isStatic(FALSE) {}
    TagMemberInfo() : prot(Public), virt(Normal), isStatic(FALSE) 
    { enumValues.setAutoDelete(TRUE); }
    QCString type;
    QCString type;
    QCString name;
    QCString name;
    QCString anchorFile;
    QCString anchorFile;
@@ -77,6 +88,7 @@ class TagMemberInfo
    Protection prot;
    Protection prot;
    Specifier virt;
    Specifier virt;
    bool isStatic; 
    bool isStatic; 
    QList<TagEnumValueInfo> enumValues;
};
};


/** Container for class specific info that can be read from a tagfile */
/** Container for class specific info that can be read from a tagfile */
@@ -205,6 +217,7 @@ class TagFileParser : public QXmlDefaultHandler
                 InGroup,
                 InGroup,
                 InPage,
                 InPage,
                 InMember,
                 InMember,
                 InEnumValue,
                 InPackage,
                 InPackage,
                 InDir,
                 InDir,
                 InTempArgList
                 InTempArgList
@@ -416,6 +429,36 @@ class TagFileParser : public QXmlDefaultHandler
      }
      }
    }
    }


    void startEnumValue( const QXmlAttributes& attrib)
    {
      if (m_state==InMember)
      {
        m_curString = "";
        m_curEnumValue = new TagEnumValueInfo;
        m_curEnumValue->file = attrib.value("file").utf8();
        m_curEnumValue->anchor = attrib.value("anchor").utf8();
        m_curEnumValue->clangid = attrib.value("clangid").utf8();
        m_stateStack.push(new State(m_state));
        m_state = InEnumValue;
      }
      else
      {
        warn("Found enumvalue tag outside of member tag\n");
      }
    }

    void endEnumValue()
    {
      m_curEnumValue->name = m_curString.stripWhiteSpace(); 
      m_state = *m_stateStack.top();
      m_stateStack.remove();
      if (m_state==InMember)
      {
        m_curMember->enumValues.append(m_curEnumValue);
        m_curEnumValue=0;
      }
    }

    void endDocAnchor()
    void endDocAnchor()
    {
    {
      switch(m_state)
      switch(m_state)
@@ -745,6 +788,7 @@ class TagFileParser : public QXmlDefaultHandler


      m_startElementHandlers.insert("compound",    new StartElementHandler(this,&TagFileParser::startCompound));
      m_startElementHandlers.insert("compound",    new StartElementHandler(this,&TagFileParser::startCompound));
      m_startElementHandlers.insert("member",      new StartElementHandler(this,&TagFileParser::startMember));
      m_startElementHandlers.insert("member",      new StartElementHandler(this,&TagFileParser::startMember));
      m_startElementHandlers.insert("enumvalue",   new StartElementHandler(this,&TagFileParser::startEnumValue));
      m_startElementHandlers.insert("name",        new StartElementHandler(this,&TagFileParser::startStringValue));
      m_startElementHandlers.insert("name",        new StartElementHandler(this,&TagFileParser::startStringValue));
      m_startElementHandlers.insert("base",        new StartElementHandler(this,&TagFileParser::startBase));
      m_startElementHandlers.insert("base",        new StartElementHandler(this,&TagFileParser::startBase));
      m_startElementHandlers.insert("filename",    new StartElementHandler(this,&TagFileParser::startStringValue));
      m_startElementHandlers.insert("filename",    new StartElementHandler(this,&TagFileParser::startStringValue));
@@ -768,6 +812,7 @@ class TagFileParser : public QXmlDefaultHandler


      m_endElementHandlers.insert("compound",    new EndElementHandler(this,&TagFileParser::endCompound));
      m_endElementHandlers.insert("compound",    new EndElementHandler(this,&TagFileParser::endCompound));
      m_endElementHandlers.insert("member",      new EndElementHandler(this,&TagFileParser::endMember));
      m_endElementHandlers.insert("member",      new EndElementHandler(this,&TagFileParser::endMember));
      m_endElementHandlers.insert("enumvalue",   new EndElementHandler(this,&TagFileParser::endEnumValue));
      m_endElementHandlers.insert("name",        new EndElementHandler(this,&TagFileParser::endName));
      m_endElementHandlers.insert("name",        new EndElementHandler(this,&TagFileParser::endName));
      m_endElementHandlers.insert("base",        new EndElementHandler(this,&TagFileParser::endBase));
      m_endElementHandlers.insert("base",        new EndElementHandler(this,&TagFileParser::endBase));
      m_endElementHandlers.insert("filename",    new EndElementHandler(this,&TagFileParser::endFilename));
      m_endElementHandlers.insert("filename",    new EndElementHandler(this,&TagFileParser::endFilename));
@@ -853,6 +898,7 @@ class TagFileParser : public QXmlDefaultHandler
    TagPageInfo               *m_curPage;
    TagPageInfo               *m_curPage;
    TagDirInfo                *m_curDir;
    TagDirInfo                *m_curDir;
    TagMemberInfo             *m_curMember;
    TagMemberInfo             *m_curMember;
    TagEnumValueInfo          *m_curEnumValue;
    TagIncludeInfo            *m_curIncludes;
    TagIncludeInfo            *m_curIncludes;
    QCString                   m_curString;
    QCString                   m_curString;
    QCString                   m_tagName;
    QCString                   m_tagName;
@@ -1102,6 +1148,26 @@ void TagFileParser::buildMemberList(Entry *ce,QList<TagMemberInfo> &members)
      me->argList = new ArgumentList;
      me->argList = new ArgumentList;
      stringToArgumentList(me->args,me->argList);
      stringToArgumentList(me->args,me->argList);
    }
    }
    if (tmi->enumValues.count()>0)
    {
      me->spec |= Entry::Strong;
      QListIterator<TagEnumValueInfo> evii(tmi->enumValues);
      TagEnumValueInfo *evi;
      for (evii.toFirst();(evi=evii.current());++evii)
      {
        Entry *ev      = new Entry;
        ev->type       = "@";
        ev->name       = evi->name;
        ev->id         = evi->clangid;
        ev->section    = Entry::VARIABLE_SEC;
        TagInfo *ti    = new TagInfo;
        ti->tagName    = m_tagName;
        ti->anchor     = evi->anchor;
        ti->fileName   = evi->file;
        ev->tagInfo    = ti;
        me->addSubEntry(ev);
      }
    }
    me->protection = tmi->prot;
    me->protection = tmi->prot;
    me->virt       = tmi->virt;
    me->virt       = tmi->virt;
    me->stat       = tmi->isStatic;
    me->stat       = tmi->isStatic;