From d63fb8488a84c7a0304ddd1024c07cc5756aa48a Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Sat, 22 Jun 2013 21:58:32 +0200 Subject: Add support for writing and importing C++11 style enums to and from tag files --- src/doxygen.cpp | 8 ++++--- src/memberdef.cpp | 43 ++++++++++++++++------------------- src/tagreader.cpp | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 92 insertions(+), 27 deletions(-) diff --git a/src/doxygen.cpp b/src/doxygen.cpp index 23a936a..f52172f 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -7187,10 +7187,12 @@ static void addEnumValuesToEnums(EntryNav *rootNav) // them here and only add them to the enum e->loadEntry(g_storage); Entry *root = e->entry(); - //printf("md->qualifiedName()=%s rootNav->name()=%s\n", - // md->qualifiedName().data(),rootNav->name().data()); + //printf("md->qualifiedName()=%s rootNav->name()=%s tagInfo=%p\n", + // md->qualifiedName().data(),rootNav->name().data(),rootNav->tagInfo()); 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( root->fileName,root->startLine,root->startColumn, diff --git a/src/memberdef.cpp b/src/memberdef.cpp index 4c9e900..d9b9ce9 100644 --- a/src/memberdef.cpp +++ b/src/memberdef.cpp @@ -3397,6 +3397,8 @@ void MemberDef::_writeTagData(const DefType compoundType) { unsigned typeMask = 1 << compoundType; 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(); // write tag file information of this member if (generateTagFile && isLinkableInProject()) @@ -3447,37 +3449,32 @@ void MemberDef::_writeTagData(const DefType compoundType) Doxygen::tagFile << " " << convertToXML(idStr) << "" << endl; } Doxygen::tagFile << " " << convertToXML(argsString()) << "" << endl; - writeDocAnchorsToTagFile(); - Doxygen::tagFile << " " << endl; - _addToSearchIndex(); - } - MemberList *fmdl=m_impl->enumFields; - if (fmdl) - { - MemberListIterator mli(*fmdl); - MemberDef *fmd; - for (mli.toFirst();(fmd=mli.current());++mli) + if (isStrong()) { - if (!fmd->isReference()) + MemberList *fmdl=m_impl->enumFields; + if (fmdl) { - if (!Config_getString("GENERATE_TAGFILE").isEmpty()) + MemberListIterator mli(*fmdl); + MemberDef *fmd; + for (mli.toFirst();(fmd=mli.current());++mli) { - Doxygen::tagFile << " " << endl; - Doxygen::tagFile << " " << convertToXML(fmd->name()) << "" << endl; - Doxygen::tagFile << " " << convertToXML(getOutputFileBase()+Doxygen::htmlFileExtension) << "" << endl; - Doxygen::tagFile << " " << convertToXML(fmd->anchor()) << "" << endl; - QCString idStr = fmd->id(); - if (!idStr.isEmpty()) + if (!fmd->isReference()) { - Doxygen::tagFile << " " << convertToXML(idStr) << "" << endl; + Doxygen::tagFile << " anchor()); + QCString idStr = fmd->id(); + if (!idStr.isEmpty()) + { + Doxygen::tagFile << "\" clangid=\"" << convertToXML(idStr); + } + Doxygen::tagFile << "\">" << convertToXML(fmd->name()) << "" << endl; } - Doxygen::tagFile << " " << convertToXML(fmd->argsString()) << "" << endl; - Doxygen::tagFile << " " << endl; - fmd->m_impl->tagDataWritten |= typeMask; - fmd->_addToSearchIndex(); } } } + writeDocAnchorsToTagFile(); + Doxygen::tagFile << " " << endl; + _addToSearchIndex(); } m_impl->tagDataWritten |= typeMask; } diff --git a/src/tagreader.cpp b/src/tagreader.cpp index 8b59c05..03cc020 100644 --- a/src/tagreader.cpp +++ b/src/tagreader.cpp @@ -61,11 +61,22 @@ class TagAnchorInfoList : public QList 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 */ class TagMemberInfo { public: - TagMemberInfo() : prot(Public), virt(Normal), isStatic(FALSE) {} + TagMemberInfo() : prot(Public), virt(Normal), isStatic(FALSE) + { enumValues.setAutoDelete(TRUE); } QCString type; QCString name; QCString anchorFile; @@ -77,6 +88,7 @@ class TagMemberInfo Protection prot; Specifier virt; bool isStatic; + QList enumValues; }; /** Container for class specific info that can be read from a tagfile */ @@ -205,6 +217,7 @@ class TagFileParser : public QXmlDefaultHandler InGroup, InPage, InMember, + InEnumValue, InPackage, InDir, 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() { switch(m_state) @@ -745,6 +788,7 @@ class TagFileParser : public QXmlDefaultHandler m_startElementHandlers.insert("compound", new StartElementHandler(this,&TagFileParser::startCompound)); 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("base", new StartElementHandler(this,&TagFileParser::startBase)); 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("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("base", new EndElementHandler(this,&TagFileParser::endBase)); m_endElementHandlers.insert("filename", new EndElementHandler(this,&TagFileParser::endFilename)); @@ -853,6 +898,7 @@ class TagFileParser : public QXmlDefaultHandler TagPageInfo *m_curPage; TagDirInfo *m_curDir; TagMemberInfo *m_curMember; + TagEnumValueInfo *m_curEnumValue; TagIncludeInfo *m_curIncludes; QCString m_curString; QCString m_tagName; @@ -1102,6 +1148,26 @@ void TagFileParser::buildMemberList(Entry *ce,QList &members) me->argList = new ArgumentList; stringToArgumentList(me->args,me->argList); } + if (tmi->enumValues.count()>0) + { + me->spec |= Entry::Strong; + QListIterator 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->virt = tmi->virt; me->stat = tmi->isStatic; -- cgit v0.12