diff options
author | JinWang An <jinwang.an@samsung.com> | 2022-12-27 12:33:07 +0900 |
---|---|---|
committer | JinWang An <jinwang.an@samsung.com> | 2022-12-27 12:33:07 +0900 |
commit | 15e5c5601a13a41757e2a5e1a9105d1714d40215 (patch) | |
tree | b3d78685874664026425debdf3298c29c8eb5dda /src | |
parent | 558fa54c62ec59357cb5c40a411f16f1c1754f33 (diff) | |
download | doxygen-15e5c5601a13a41757e2a5e1a9105d1714d40215.tar.gz doxygen-15e5c5601a13a41757e2a5e1a9105d1714d40215.tar.bz2 doxygen-15e5c5601a13a41757e2a5e1a9105d1714d40215.zip |
Imported Upstream version 1.9.3upstream/1.9.3
Diffstat (limited to 'src')
147 files changed, 12988 insertions, 11352 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1840648..0e0c5f7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -215,6 +215,7 @@ add_library(doxymain STATIC ${GENERATED_SRC}/ce_parse.cpp # custom generated files ${GENERATED_SRC}/lang_cfg.h + ${GENERATED_SRC}/configvalues.h ${GENERATED_SRC}/ce_parse.h ${GENERATED_SRC}/resources.cpp # diff --git a/src/cite.cpp b/src/cite.cpp index 79b45da..ce7c2e1 100644 --- a/src/cite.cpp +++ b/src/cite.cpp @@ -304,7 +304,7 @@ void CitationManager::generatePage() if (line.find("<!-- BEGIN BIBLIOGRAPHY")!=-1) insideBib=TRUE; else if (line.find("<!-- END BIBLIOGRAPH")!=-1) insideBib=FALSE; // determine text to use at the location of the @cite command - if (insideBib && (i=line.find("name=\"CITEREF_"))!=-1) + if (insideBib && ((i=line.find("name=\"CITEREF_"))!=-1 || (i=line.find("name=\"#CITEREF_"))!=-1)) { int j=line.find("\">["); int k=line.find("]</a>"); @@ -315,7 +315,6 @@ void CitationManager::generatePage() uint uk=(uint)k; QCString label = line.mid(ui+14,uj-ui-14); QCString number = line.mid(uj+2,uk-uj-1); - label = substitute(substitute(label,"–","--"),"—","---"); line = line.left(ui+14) + label + line.right(line.length()-uj); auto it = p->entries.find(label.str()); //printf("label='%s' number='%s' => %p\n",qPrint(label),qPrint(number),it->second.get()); diff --git a/src/clangparser.cpp b/src/clangparser.cpp index 5de9907..42a0bc9 100644 --- a/src/clangparser.cpp +++ b/src/clangparser.cpp @@ -486,7 +486,7 @@ std::string ClangTUParser::lookup(uint line,const char *symbol) } -void ClangTUParser::writeLineNumber(CodeOutputInterface &ol,const FileDef *fd,uint line) +void ClangTUParser::writeLineNumber(CodeOutputInterface &ol,const FileDef *fd,uint line,bool writeLineAnchor) { const Definition *d = fd ? fd->getSourceDefinition(line) : 0; if (d && d->isLinkable()) @@ -505,7 +505,7 @@ void ClangTUParser::writeLineNumber(CodeOutputInterface &ol,const FileDef *fd,ui ol.writeLineNumber(md->getReference(), md->getOutputFileBase(), md->anchor(), - line); + line,writeLineAnchor); } else // link to compound { @@ -513,12 +513,12 @@ void ClangTUParser::writeLineNumber(CodeOutputInterface &ol,const FileDef *fd,ui ol.writeLineNumber(d->getReference(), d->getOutputFileBase(), d->anchor(), - line); + line,writeLineAnchor); } } else // no link { - ol.writeLineNumber(QCString(),QCString(),QCString(),line); + ol.writeLineNumber(QCString(),QCString(),QCString(),line,writeLineAnchor); } // set search page target @@ -538,6 +538,7 @@ void ClangTUParser::codifyLines(CodeOutputInterface &ol,const FileDef *fd,const if (fontClass) ol.startFontClass(fontClass); const char *p=text,*sp=p; char c; + bool inlineCodeFragment = false; bool done=FALSE; while (!done) { @@ -556,7 +557,7 @@ void ClangTUParser::codifyLines(CodeOutputInterface &ol,const FileDef *fd,const if (fontClass) ol.endFontClass(); ol.endCodeLine(); ol.startCodeLine(TRUE); - writeLineNumber(ol,fd,line); + writeLineNumber(ol,fd,line,inlineCodeFragment); if (fontClass) ol.startFontClass(fontClass); } else @@ -583,6 +584,7 @@ void ClangTUParser::writeMultiLineCodeLink(CodeOutputInterface &ol, { tooltip = d->briefDescriptionAsTooltip(); } + bool inlineCodeFragment = false; bool done=FALSE; char *p=(char *)text; while (!done) @@ -598,7 +600,7 @@ void ClangTUParser::writeMultiLineCodeLink(CodeOutputInterface &ol, ol.writeCodeLink(d->codeSymbolType(),ref,file,anchor,sp,tooltip); ol.endCodeLine(); ol.startCodeLine(TRUE); - writeLineNumber(ol,fd,line); + writeLineNumber(ol,fd,line,inlineCodeFragment); } else { @@ -760,8 +762,9 @@ void ClangTUParser::writeSources(CodeOutputInterface &ol,const FileDef *fd) unsigned int line=1,column=1; QCString lineNumber,lineAnchor; + bool inlineCodeFragment = false; ol.startCodeLine(TRUE); - writeLineNumber(ol,fd,line); + writeLineNumber(ol,fd,line,inlineCodeFragment); for (unsigned int i=0;i<p->numTokens;i++) { CXSourceLocation start = clang_getTokenLocation(p->tu, p->tokens[i]); @@ -773,7 +776,7 @@ void ClangTUParser::writeSources(CodeOutputInterface &ol,const FileDef *fd) line++; ol.endCodeLine(); ol.startCodeLine(TRUE); - writeLineNumber(ol,fd,line); + writeLineNumber(ol,fd,line,inlineCodeFragment); } while (column<c) { ol.codify(" "); column++; } CXString tokenString = clang_getTokenSpelling(p->tu, p->tokens[i]); @@ -906,6 +909,10 @@ std::unique_ptr<ClangTUParser> ClangParser::createTUParser(const FileDef *fd) co //-------------------------------------------------------------------------- #else // use stubbed functionality in case libclang support is disabled. +class ClangTUParser::Private +{ +}; + void ClangTUParser::switchToFile(const FileDef *fd) { } @@ -914,6 +921,14 @@ void ClangTUParser::parse() { } +ClangTUParser::ClangTUParser(const ClangParser &,const FileDef *) : p(std::make_unique<Private>()) +{ +} + +ClangTUParser::~ClangTUParser() +{ +} + std::string ClangTUParser::lookup(uint,const char *) { return std::string(); diff --git a/src/clangparser.h b/src/clangparser.h index 71a79d5..dbfd4e6 100644 --- a/src/clangparser.h +++ b/src/clangparser.h @@ -50,7 +50,7 @@ class ClangTUParser private: void detectFunctionBody(const char *s); - void writeLineNumber(CodeOutputInterface &ol,const FileDef *fd,uint line); + void writeLineNumber(CodeOutputInterface &ol,const FileDef *fd,uint line,bool writeLineAnchor); void codifyLines(CodeOutputInterface &ol,const FileDef *fd,const char *text, uint &line,uint &column,const char *fontClass=0); void writeMultiLineCodeLink(CodeOutputInterface &ol, diff --git a/src/classdef.cpp b/src/classdef.cpp index a349867..937c531 100644 --- a/src/classdef.cpp +++ b/src/classdef.cpp @@ -285,7 +285,7 @@ class ClassDefImpl : public DefinitionMixin<ClassDefMutable> virtual void writeDocumentationForInnerClasses(OutputList &ol) const; virtual void writeMemberPages(OutputList &ol) const; virtual void writeMemberList(OutputList &ol) const; - virtual void writeDeclaration(OutputList &ol,const MemberDef *md,bool inGroup, + virtual void writeDeclaration(OutputList &ol,const MemberDef *md,bool inGroup,int indentLevel, const ClassDef *inheritedFrom,const QCString &inheritId) const; virtual void writeQuickMemberLinks(OutputList &ol,const MemberDef *md) const; virtual void writeSummaryLinks(OutputList &ol) const; @@ -326,13 +326,13 @@ class ClassDefImpl : public DefinitionMixin<ClassDefMutable> bool showAlways) const; void writeMemberDocumentation(OutputList &ol,MemberListType lt,const QCString &title,bool showInline=FALSE) const; void writeSimpleMemberDocumentation(OutputList &ol,MemberListType lt) const; - void writePlainMemberDeclaration(OutputList &ol,MemberListType lt,bool inGroup,const ClassDef *inheritedFrom,const QCString &inheritId) const; + void writePlainMemberDeclaration(OutputList &ol,MemberListType lt,bool inGroup, + int indentLevel,const ClassDef *inheritedFrom,const QCString &inheritId) const; void writeBriefDescription(OutputList &ol,bool exampleFlag) const; void writeDetailedDescription(OutputList &ol,const QCString &pageType,bool exampleFlag, const QCString &title,const QCString &anchor=QCString()) const; void writeIncludeFiles(OutputList &ol) const; void writeIncludeFilesForSlice(OutputList &ol) const; - //void writeAllMembersLink(OutputList &ol); void writeInheritanceGraph(OutputList &ol) const; void writeCollaborationGraph(OutputList &ol) const; void writeMemberGroups(OutputList &ol,bool showInline=FALSE) const; @@ -1605,12 +1605,15 @@ int ClassDefImpl::countInheritanceNodes() const void ClassDefImpl::writeInheritanceGraph(OutputList &ol) const { + static bool haveDot = Config_getBool(HAVE_DOT); + static auto classGraph = Config_getEnum(CLASS_GRAPH); + + if (classGraph == CLASS_GRAPH_t::NO) return; // count direct inheritance relations const int count=countInheritanceNodes(); bool renderDiagram = FALSE; - if (Config_getBool(HAVE_DOT) && - (Config_getBool(CLASS_DIAGRAMS) || Config_getBool(CLASS_GRAPH))) + if (haveDot && (classGraph==CLASS_GRAPH_t::YES || classGraph==CLASS_GRAPH_t::GRAPH)) // write class diagram using dot { DotClassGraph inheritanceGraph(this,Inheritance); @@ -1630,7 +1633,7 @@ void ClassDefImpl::writeInheritanceGraph(OutputList &ol) const renderDiagram = TRUE; } } - else if (Config_getBool(CLASS_DIAGRAMS) && count>0) + else if ((classGraph==CLASS_GRAPH_t::YES || classGraph==CLASS_GRAPH_t::GRAPH) && count>0) // write class diagram using built-in generator { ClassDiagram diagram(this); // create a diagram of this class. @@ -2083,7 +2086,7 @@ void ClassDefImpl::writeTagFile(TextStream &tagFile) if (isObjectiveC()) { tagFile << " objc=\"yes\""; } tagFile << ">\n"; tagFile << " <name>" << convertToXML(name()) << "</name>\n"; - tagFile << " <filename>" << convertToXML(getOutputFileBase()) << Doxygen::htmlFileExtension << "</filename>\n"; + tagFile << " <filename>" << convertToXML(addHtmlExtensionIfMissing(getOutputFileBase())) << "</filename>\n"; if (!anchor().isEmpty()) { tagFile << " <anchor>" << convertToXML(anchor()) << "</anchor>\n"; @@ -2485,13 +2488,6 @@ void ClassDefImpl::writeDocumentationContents(OutputList &ol,const QCString & /* QCString pageType = " "; pageType += compoundTypeString(); - Doxygen::indexList->addIndexItem(this,0); - - if (Doxygen::searchIndex) - { - Doxygen::searchIndex->setCurrentDoc(this,anchor(),FALSE); - Doxygen::searchIndex->addWord(localName(),TRUE); - } bool exampleFlag=hasExamples(); //---------------------------------------- start flexible part ------------------------------- @@ -2770,7 +2766,7 @@ void ClassDefImpl::writeQuickMemberLinks(OutputList &ol,const MemberDef *current ol.writeString("<a class=\"navtab\" "); ol.writeString("href=\""); if (createSubDirs) ol.writeString("../../"); - ol.writeString(md->getOutputFileBase()+Doxygen::htmlFileExtension+"#"+md->anchor()); + ol.writeString(addHtmlExtensionIfMissing(md->getOutputFileBase())+"#"+md->anchor()); ol.writeString("\">"); ol.writeString(convertToHtml(md->name())); ol.writeString("</a>"); @@ -3227,7 +3223,7 @@ void ClassDefImpl::setRequiresClause(const QCString &req) /*! called from MemberDef::writeDeclaration() to (recursively) write the * definition of an anonymous struct, union or class. */ -void ClassDefImpl::writeDeclaration(OutputList &ol,const MemberDef *md,bool inGroup, +void ClassDefImpl::writeDeclaration(OutputList &ol,const MemberDef *md,bool inGroup,int indentLevel, const ClassDef *inheritedFrom,const QCString &inheritId) const { //printf("ClassName='%s' inGroup=%d\n",qPrint(name()),inGroup); @@ -3254,7 +3250,7 @@ void ClassDefImpl::writeDeclaration(OutputList &ol,const MemberDef *md,bool inGr // write user defined member groups for (const auto &mg : m_impl->memberGroups) { - mg->writePlainDeclarations(ol,inGroup,this,0,0,0,inheritedFrom,inheritId); + mg->writePlainDeclarations(ol,inGroup,this,0,0,0,indentLevel,inheritedFrom,inheritId); } for (const auto &lde : LayoutDocManager::instance().docEntries(LayoutDocManager::Class)) @@ -3262,7 +3258,7 @@ void ClassDefImpl::writeDeclaration(OutputList &ol,const MemberDef *md,bool inGr if (lde->kind()==LayoutDocEntry::MemberDecl) { const LayoutDocEntryMemberDecl *lmd = (const LayoutDocEntryMemberDecl*)lde.get(); - writePlainMemberDeclaration(ol,lmd->type,inGroup,inheritedFrom,inheritId); + writePlainMemberDeclaration(ol,lmd->type,inGroup,indentLevel,inheritedFrom,inheritId); } } } @@ -3971,9 +3967,9 @@ ClassDef *ClassDefImpl::insertTemplateInstance(const QCString &fileName, innerClass->setOuterScope(templateClass); innerClass->setHidden(isHidden()); innerClass->setArtificial(TRUE); - freshInstance=TRUE; } } + freshInstance=TRUE; } } return templateClass; @@ -4224,7 +4220,7 @@ int ClassDefImpl::countMemberDeclarations(MemberListType lt,const ClassDef *inhe for (const auto &mg : m_impl->memberGroups) { count+=mg->countGroupedInheritedMembers(lt); - if (lt2!=1) count+=mg->countGroupedInheritedMembers((MemberListType)lt2); + if (lt2!=-1) count+=mg->countGroupedInheritedMembers((MemberListType)lt2); } } static bool inlineInheritedMembers = Config_getBool(INLINE_INHERITED_MEMB); @@ -4509,13 +4505,13 @@ void ClassDefImpl::writeSimpleMemberDocumentation(OutputList &ol,MemberListType void ClassDefImpl::writePlainMemberDeclaration(OutputList &ol, MemberListType lt,bool inGroup, - const ClassDef *inheritedFrom,const QCString &inheritId) const + int indentLevel,const ClassDef *inheritedFrom,const QCString &inheritId) const { //printf("%s: ClassDefImpl::writePlainMemberDeclaration()\n",qPrint(name())); MemberList * ml = getMemberList(lt); if (ml) { - ml->writePlainDeclarations(ol,inGroup,this,0,0,0,inheritedFrom,inheritId); + ml->writePlainDeclarations(ol,inGroup,this,0,0,0,indentLevel,inheritedFrom,inheritId); } } diff --git a/src/classdef.h b/src/classdef.h index c1c66b5..7d9c22e 100644 --- a/src/classdef.h +++ b/src/classdef.h @@ -446,7 +446,7 @@ class ClassDefMutable : public DefinitionMutable, public ClassDef virtual void writeMemberPages(OutputList &ol) const = 0; virtual void writeMemberList(OutputList &ol) const = 0; virtual void writeDeclaration(OutputList &ol,const MemberDef *md,bool inGroup, - const ClassDef *inheritedFrom,const QCString &inheritId) const = 0; + int indentLevel, const ClassDef *inheritedFrom,const QCString &inheritId) const = 0; virtual void writeQuickMemberLinks(OutputList &ol,const MemberDef *md) const = 0; virtual void writeSummaryLinks(OutputList &ol) const = 0; virtual void writeInlineDocumentation(OutputList &ol) const = 0; diff --git a/src/cmdmapper.cpp b/src/cmdmapper.cpp index ed249b9..a5caede 100644 --- a/src/cmdmapper.cpp +++ b/src/cmdmapper.cpp @@ -60,6 +60,7 @@ CommandMap cmdMap[] = { "internal", CMD_INTERNAL }, { "invariant", CMD_INVARIANT }, { "javalink", CMD_JAVALINK }, + { "javalinkplain", CMD_JAVALINK }, { "latexinclude", CMD_LATEXINCLUDE }, { "latexonly", CMD_LATEXONLY }, { "li", CMD_LI }, @@ -80,7 +81,6 @@ CommandMap cmdMap[] = { "return", CMD_RETURN }, { "returns", CMD_RETURN }, { "retval", CMD_RETVAL }, - { "rtfonly", CMD_RTFONLY }, { "sa", CMD_SA }, { "secreflist", CMD_SECREFLIST }, { "section", CMD_SECTION }, @@ -151,6 +151,8 @@ CommandMap cmdMap[] = { "maninclude", CMD_MANINCLUDE }, { "xmlinclude", CMD_XMLINCLUDE }, { "iline", CMD_ILINE }, + { "iliteral", CMD_ILITERAL }, + { "endiliteral", CMD_ENDILITERAL }, { 0, 0 }, }; @@ -163,6 +165,7 @@ CommandMap htmlTagMap[] = { "table", HTML_TABLE }, { "caption", HTML_CAPTION }, { "small", HTML_SMALL }, + { "cite", HTML_CITE }, { "code", HTML_CODE }, { "dfn", HTML_CODE }, { "var", HTML_EMPHASIS }, @@ -202,6 +205,7 @@ CommandMap htmlTagMap[] = { "u", HTML_UNDERLINE }, { "ins", HTML_INS }, { "del", HTML_DEL }, + { "details", HTML_DETAILS }, { "c", XML_C }, // { "code", XML_CODE }, <= ambiguous <code> is also a HTML tag diff --git a/src/cmdmapper.h b/src/cmdmapper.h index 7ee451c..619470a 100644 --- a/src/cmdmapper.h +++ b/src/cmdmapper.h @@ -143,6 +143,8 @@ enum CommandType CMD_MANINCLUDE = 114, CMD_XMLINCLUDE = 115, CMD_ILINE = 116, + CMD_ILITERAL = 117, + CMD_ENDILITERAL = 118, }; enum HtmlTagType @@ -186,6 +188,8 @@ enum HtmlTagType HTML_INS = 36, HTML_DEL = 37, HTML_S = 38, + HTML_DETAILS = 39, + HTML_CITE = 40, XML_CmdMask = 0x100, @@ -46,7 +46,8 @@ class CCodeParser : public CodeParserInterface bool collectXRefs=TRUE ); void resetCodeParserState(); - void setStartCodeLine(const bool inp); + void setInsideCodeLine(bool inp); + bool insideCodeLine() const; private: struct Private; std::unique_ptr<Private> p; @@ -18,6 +18,10 @@ %option extra-type="struct codeYY_state *" %top{ #include <stdint.h> +// forward declare yyscan_t to improve type safety +#define YY_TYPEDEF_YY_SCANNER_T +struct yyguts_t; +typedef yyguts_t *yyscan_t; } %{ @@ -30,6 +34,7 @@ #include <memory> #include <algorithm> #include <unordered_map> +#include <unordered_set> #include <stack> #include <vector> #include <string> @@ -98,17 +103,13 @@ struct codeYY_state QCString parmType; QCString parmName; - bool beginCodeLine = true; //!< signals whether or not we should with the first line - //!< write a start line code or not. Essential - //!< when this code parser is called from another - //!< code parser. - const char * inputString = 0; //!< the code fragment as text yy_size_t inputPosition = 0; //!< read offset during parsing + QCString fileName; int inputLines = 0; //!< number of line in the code fragment int yyLineNr = 0; //!< current line number yy_size_t yyColNr = 0; //!< current column number - bool needsTermination = FALSE; + bool insideCodeLine = FALSE; bool exampleBlock = FALSE; QCString exampleName; @@ -188,7 +189,7 @@ static bool isCastKeyword(const char *s); //------------------------------------------------------------------- #if USE_STATE2STRING -static const char *stateToString(yyscan_t yyscanner,int state); +static const char *stateToString(int state); #endif static void saveObjCContext(yyscan_t yyscanner); @@ -264,6 +265,9 @@ static std::mutex g_usingDirectiveMutex; #undef YY_INPUT #define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); +// otherwise the filename would be the name of the converted file (*.cpp instead of *.l) +static inline const char *getLexerFILE() {return __FILE__;} +#include "doxygen_lex.h" %} @@ -277,10 +281,11 @@ TEMPLIST "<"[^\"\}\{\(\)\/\n\>]*">" SCOPETNAME (((({ID}{TEMPLIST}?){BN}*)?{SEP}{BN}*)*)((~{BN}*)?{ID}) SCOPEPREFIX ({ID}{TEMPLIST}?{BN}*{SEP}{BN}*)+ KEYWORD_OBJC ("@public"|"@private"|"@protected"|"@class"|"@implementation"|"@interface"|"@end"|"@selector"|"@protocol"|"@optional"|"@required"|"@throw"|"@synthesize"|"@property") -KEYWORD ("asm"|"__assume"|"auto"|"class"|"const"|"delete"|"enum"|"explicit"|"extern"|"false"|"friend"|"gcnew"|"gcroot"|"set"|"get"|"inline"|"internal"|"mutable"|"namespace"|"new"|"null"|"nullptr"|"override"|"operator"|"pin_ptr"|"private"|"protected"|"public"|"raise"|"register"|"remove"|"self"|"sizeof"|"static"|"struct"|"__super"|"function"|"template"|"generic"|"this"|"true"|"typedef"|"typeid"|"typename"|"union"|"using"|"virtual"|"volatile"|"abstract"|"final"|"import"|"synchronized"|"transient"|"alignas"|"alignof"|"concept"|"requires"|"decltype"|{KEYWORD_OBJC}|"constexpr"|"consteval"|"constinit"|"co_await"|"co_return"|"co_yield"|"static_assert"|"noexcept"|"thread_local") + /* please also pay attention to skipLanguageSpecificKeyword when changing the list of keywords. */ +KEYWORD ("asm"|"__assume"|"auto"|"class"|"const"|"delete"|"enum"|"explicit"|"extern"|"false"|"friend"|"gcnew"|"gcroot"|"set"|"get"|"inline"|"internal"|"mutable"|"namespace"|"new"|"null"|"nullptr"|"override"|"operator"|"pin_ptr"|"private"|"protected"|"public"|"raise"|"register"|"remove"|"self"|"sizeof"|"static"|"struct"|"__super"|"function"|"template"|"generic"|"this"|"true"|"typedef"|"typeid"|"typename"|"union"|"using"|"virtual"|"volatile"|"abstract"|"final"|"import"|"synchronized"|"transient"|"alignas"|"alignof"|"concept"|"requires"|"decltype"|{KEYWORD_OBJC}|"constexpr"|"consteval"|"constinit"|"co_await"|"co_return"|"co_yield"|"static_assert"|"noexcept"|"thread_local"|"enum"{B}+("class"|"struct")) FLOWKW ("break"|"catch"|"continue"|"default"|"do"|"else"|"finally"|"return"|"switch"|"throw"|"throws"|"@catch"|"@finally") FLOWCONDITION ("case"|"for"|"foreach"|"for each"|"goto"|"if"|"try"|"while"|"@try") -TYPEKW ("bool"|"byte"|"char"|"double"|"float"|"int"|"long"|"object"|"short"|"signed"|"unsigned"|"void"|"wchar_t"|"size_t"|"boolean"|"id"|"SEL"|"string"|"nullptr") +TYPEKW ("bool"|"byte"|"char"|"char8_t"|"char16_t"|"char32_t"|"double"|"float"|"int"|"long"|"object"|"short"|"signed"|"unsigned"|"void"|"wchar_t"|"size_t"|"boolean"|"id"|"SEL"|"string"|"nullptr") TYPEKWSL ("LocalObject"|"Object"|"Value") CASTKW ("const_cast"|"dynamic_cast"|"reinterpret_cast"|"static_cast") CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^' \\\n]{1,4}"'")) @@ -343,7 +348,6 @@ ENDQopt ("const"|"volatile"|"sealed"|"override")({BN}+("const"|"volatile"|"seale %x SkipComment %x SkipCxxComment %x RemoveSpecialCComment -%x StripSpecialCComment %x Body %x FuncCall %x MemberCall @@ -1529,7 +1533,7 @@ ENDQopt ("const"|"volatile"|"sealed"|"override")({BN}+("const"|"volatile"|"seale yyextra->code->codify(yytext); endFontClass(yyscanner); } -<MemberCall2,FuncCall>{ID}(({B}*"<"[^\n\[\](){}<>]*">")?({B}*"::"{B}*{ID})?)* { +<MemberCall2,FuncCall>("::")?{ID}(({B}*"<"[^\n\[\](){}<>]*">")?({B}*"::"{B}*{ID})?)* { if (isCastKeyword(yytext)) { REJECT; @@ -1939,7 +1943,7 @@ ENDQopt ("const"|"volatile"|"sealed"|"override")({BN}+("const"|"volatile"|"seale BEGIN( yyextra->lastCContext ) ; } } -<SkipCPP>\n/.*\n { +<SkipCPP>\n/(.|\n) { endFontClass(yyscanner); BEGIN( yyextra->lastSkipCppContext ) ; unput('\n'); @@ -2371,24 +2375,26 @@ static void startCodeLine(yyscan_t yyscanner) yyextra->code->writeLineNumber(yyextra->currentMemberDef->getReference(), yyextra->currentMemberDef->getOutputFileBase(), yyextra->currentMemberDef->anchor(), - yyextra->yyLineNr); + yyextra->yyLineNr,!yyextra->includeCodeFragment); setCurrentDoc(yyscanner,lineAnchor); } else if (d->isLinkableInProject()) { yyextra->code->writeLineNumber(d->getReference(), d->getOutputFileBase(), - QCString(),yyextra->yyLineNr); + QCString(),yyextra->yyLineNr,!yyextra->includeCodeFragment); setCurrentDoc(yyscanner,lineAnchor); } } else { - yyextra->code->writeLineNumber(QCString(),QCString(),QCString(),yyextra->yyLineNr); + yyextra->code->writeLineNumber(QCString(),QCString(),QCString(),yyextra->yyLineNr, + !yyextra->includeCodeFragment); } } DBG_CTX((stderr,"startCodeLine(%d)\n",yyextra->yyLineNr)); yyextra->code->startCodeLine(yyextra->sourceFileDef && yyextra->lineNumbers); + yyextra->insideCodeLine = true; if (yyextra->currentFontClass) { yyextra->code->startFontClass(QCString(yyextra->currentFontClass)); @@ -2403,13 +2409,17 @@ static void endCodeLine(yyscan_t yyscanner) DBG_CTX((stderr,"endCodeLine(%d)\n",yyextra->yyLineNr)); endFontClass(yyscanner); yyextra->code->endCodeLine(); + yyextra->insideCodeLine = false; } static void nextCodeLine(yyscan_t yyscanner) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; const char * fc = yyextra->currentFontClass; - endCodeLine(yyscanner); + if (yyextra->insideCodeLine) + { + endCodeLine(yyscanner); + } if (yyextra->yyLineNr<yyextra->inputLines) { yyextra->currentFontClass = fc; @@ -3349,9 +3359,7 @@ static int countLines(yyscan_t yyscanner) } if (p>yyextra->inputString && *(p-1)!='\n') { // last line does not end with a \n, so we add an extra - // line and explicitly terminate the line after parsing. - count++, - yyextra->needsTermination=TRUE; + count++; } return count; } @@ -3726,8 +3734,41 @@ static QCString escapeComment(yyscan_t yyscanner,const char *s) static bool skipLanguageSpecificKeyword(yyscan_t yyscanner,const char *keyword) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - QCString kw(keyword); - return yyextra->lang==SrcLangExt_Cpp && (kw == "remove" || kw == "set" || kw == "get"); + static std::unordered_set<std::string> non_cpp_keywords = { + "__assume", "__super", "abstract", "function", + "gcnew", "gcroot", "generic", "get", + "internal", "null", "pin_ptr", "raise", + "remove", "self", "set", "transient"}; + static std::unordered_set<std::string> non_java_keywords = { + "alignas", "alignof", "and", "and_eq", "asm", + "atomic_cancel", "atomic_commit", "atomic_noexcept", "auto", "bitand", + "bitor", "bool", "char8_t", "char16_t", "char32_t", + "compl", "concept", "consteval", "constexpr", "constinit", + "const_cast", "co_await", "co_return", "co_yield", "decltype", + "delete", "dynamic_cast", "explicit", "export", "extern", + "friend", "inline", "mutable", "namespace", "noexcept", + "not", "not_eq", "nullptr", "operator", "or", + "or_eq", "reflexpr", "register", "reinterpret_cast", "requires", + "signed", "sizeof", "static_assert", "static_cast", "struct", + "template", "thread_local", "typedef", "typeid", "typename", + "union", "unsigned", "using", "virtual", "wchar_t", + "xor", "xor_eq", + "override" + }; + bool retval; + switch (yyextra->lang) + { + case SrcLangExt_Cpp: + retval = (non_cpp_keywords.find(keyword) != non_cpp_keywords.end()); + break; + case SrcLangExt_Java: + retval = (non_java_keywords.find(keyword) != non_java_keywords.end()); + break; + default: + retval = false; + break; + } + return retval; } static bool isCastKeyword(const char *keyword) @@ -3833,12 +3874,19 @@ void CCodeParser::resetCodeParserState() yyextra->codeClassMap.clear(); yyextra->curClassBases.clear(); yyextra->anchorCount = 0; + yyextra->insideCodeLine = false; } -void CCodeParser::setStartCodeLine(const bool inp) +void CCodeParser::setInsideCodeLine(bool inp) { struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; - yyextra->beginCodeLine = inp; + yyextra->insideCodeLine = inp; +} + +bool CCodeParser::insideCodeLine() const +{ + struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; + return yyextra->insideCodeLine; } void CCodeParser::parseCode(CodeOutputInterface &od,const QCString &className,const QCString &s, @@ -3858,10 +3906,10 @@ void CCodeParser::parseCode(CodeOutputInterface &od,const QCString &className,co yyextra->code = &od; yyextra->inputString = s.data(); + yyextra->fileName = fd ? fd->fileName():""; yyextra->inputPosition = 0; codeYYrestart(0,yyscanner); yyextra->currentFontClass = 0; - yyextra->needsTermination = FALSE; yyextra->searchCtx = searchCtx; yyextra->collectXRefs = collectXRefs; yyextra->inFunctionTryBlock = FALSE; @@ -3915,7 +3963,10 @@ void CCodeParser::parseCode(CodeOutputInterface &od,const QCString &className,co } yyextra->includeCodeFragment = inlineFragment; DBG_CTX((stderr,"** exBlock=%d exName=%s include=%d\n",exBlock,qPrint(exName),inlineFragment)); - if (yyextra->beginCodeLine) startCodeLine(yyscanner); + if (!yyextra->insideCodeLine) + { + startCodeLine(yyscanner); + } yyextra->type.resize(0); yyextra->name.resize(0); yyextra->args.resize(0); @@ -3925,11 +3976,9 @@ void CCodeParser::parseCode(CodeOutputInterface &od,const QCString &className,co BEGIN( Body ); codeYYlex(yyscanner); yyextra->lexInit=TRUE; - if (yyextra->needsTermination) + if (yyextra->insideCodeLine) { - endFontClass(yyscanner); - DBG_CTX((stderr,"endCodeLine(%d)\n",yyextra->yyLineNr)); - yyextra->code->endCodeLine(); + endCodeLine(yyscanner); } if (cleanupSourceDef) { @@ -3941,7 +3990,6 @@ void CCodeParser::parseCode(CodeOutputInterface &od,const QCString &className,co yyextra->tooltipManager.writeTooltips(od); printlex(yy_flex_debug, FALSE, __FILE__, fd ? qPrint(fd->fileName()): NULL); - return; } #if USE_STATE2STRING diff --git a/src/commentcnv.l b/src/commentcnv.l index aaf1162..ad9b302 100644 --- a/src/commentcnv.l +++ b/src/commentcnv.l @@ -20,6 +20,10 @@ %option extra-type="struct commentcnvYY_state *" %top{ #include <stdint.h> +// forward declare yyscan_t to improve type safety +#define YY_TYPEDEF_YY_SCANNER_T +struct yyguts_t; +typedef yyguts_t *yyscan_t; } %{ @@ -48,9 +52,9 @@ #define USE_STATE2STRING 0 -struct CondCtx +struct commentcnvYY_CondCtx { - CondCtx(int line,QCString id,bool b) + commentcnvYY_CondCtx(int line,QCString id,bool b) : lineNr(line),sectionId(id), skip(b) {} int lineNr; QCString sectionId; @@ -77,7 +81,7 @@ struct commentcnvYY_state QCString fileName; int lineNr = 0; int condCtx = 0; - std::stack<CondCtx> condStack; + std::stack<commentcnvYY_CondCtx> condStack; std::stack<int> commentStack; QCString blockName; int lastCommentContext = 0; @@ -122,10 +126,13 @@ static void clearCommentStack(yyscan_t yyscanner); #undef YY_INPUT #define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); +// otherwise the filename would be the name of the converted file (*.cpp instead of *.l) +static inline const char *getLexerFILE() {return __FILE__;} +#include "doxygen_lex.h" %} -MAILADR ("mailto:")?[a-z_A-Z0-9.+-]+"@"[a-z_A-Z0-9-]+("."[a-z_A-Z0-9\-]+)+[a-z_A-Z0-9\-]+ +MAILADDR ("mailto:")?[a-z_A-Z0-9\x80-\xff.+-]+"@"[a-z_A-Z0-9\x80-\xff-]+("."[a-z_A-Z0-9\x80-\xff\-]+)+[a-z_A-Z0-9\x80-\xff\-]+ %option noyywrap @@ -406,12 +413,19 @@ SLASHopt [/]* yyextra->commentStack.push(yyextra->lineNr); } } -<CComment,CNComment,ReadLine>{MAILADR} | -<CComment,CNComment,ReadLine>"<"{MAILADR}">" { // Mail address, to prevent seeing e.g x@code-factory.org as start of a code block +<CComment,CNComment,ReadLine>{MAILADDR} | +<CComment,CNComment,ReadLine>"<"{MAILADDR}">" { // Mail address, to prevent seeing e.g x@code-factory.org as start of a code block copyToOutput(yyscanner,yytext,(int)yyleng); } -<CComment>"{@code"/[ \t\n] { - copyToOutput(yyscanner,"@code",5); +<CComment>"{"[ \t]*"@code"/[ \t\n] { + copyToOutput(yyscanner,"@iliteral{code}",15); + yyextra->lastCommentContext = YY_START; + yyextra->javaBlock=1; + yyextra->blockName=&yytext[1]; + BEGIN(VerbatimCode); + } +<CComment>"{"[ \t]*"@literal"/[ \t\n] { + copyToOutput(yyscanner,"@iliteral",9); yyextra->lastCommentContext = YY_START; yyextra->javaBlock=1; yyextra->blockName=&yytext[1]; @@ -460,7 +474,7 @@ SLASHopt [/]* yyextra->lastCommentContext = YY_START; BEGIN(Verbatim); } -<CComment,ReadLine>[\\@]("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"docbookonly"|"rtfonly"|"manonly")/[^a-z_A-Z0-9] { /* start of a verbatim block */ +<CComment,ReadLine>[\\@]("verbatim"|"iliteral"|"latexonly"|"htmlonly"|"xmlonly"|"docbookonly"|"rtfonly"|"manonly")/[^a-z_A-Z0-9] { /* start of a verbatim block */ copyToOutput(yyscanner,yytext,(int)yyleng); yyextra->blockName=&yytext[1]; yyextra->lastCommentContext = YY_START; @@ -475,7 +489,7 @@ SLASHopt [/]* <Scan>. { /* any other character */ copyToOutput(yyscanner,yytext,(int)yyleng); } -<Verbatim>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endrtfonly"|"endmanonly"|"f$"|"f]"|"f}"|"f)") { /* end of verbatim block */ +<Verbatim>[\\@]("endverbatim"|"endiliteral"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endrtfonly"|"endmanonly"|"f$"|"f]"|"f}"|"f)") { /* end of verbatim block */ copyToOutput(yyscanner,yytext,(int)yyleng); if (&yytext[1]==yyextra->blockName) // end of formula { @@ -507,7 +521,7 @@ SLASHopt [/]* yyextra->javaBlock--; if (yyextra->javaBlock==0) { - copyToOutput(yyscanner," @endcode ",10); + copyToOutput(yyscanner," @endiliteral ",14); BEGIN(yyextra->lastCommentContext); } else @@ -876,9 +890,10 @@ SLASHopt [/]* yyextra->condCtx=YY_START; handleCondSectionId(yyscanner," "); // fake section id causing the section to be hidden unconditionally } +<CondLine>\n | <CondLine>. { // forgot section id? handleCondSectionId(yyscanner," "); // fake section id causing the section to be hidden unconditionally - if (*yytext=='\n') yyextra->lineNr++; + if (*yytext=='\n') { yyextra->lineNr++; copyToOutput(yyscanner,"\n",1);} } <CComment,ReadLine>[\\@][a-z_A-Z][a-z_A-Z0-9]* { // expand alias without arguments replaceAliases(yyscanner,QCString(yytext)); @@ -944,6 +959,9 @@ SLASHopt [/]* <*>. { copyToOutput(yyscanner,yytext,(int)yyleng); } + /* +<*>\n { fprintf(stderr,"Lex scanner %s (%s) default rule newline for state %s.\n", __FILE__, qPrint(yyextra->fileName),stateToString(YY_START));} + */ %% static void replaceCommentMarker(yyscan_t yyscanner,const char *s,int len) @@ -1057,7 +1075,7 @@ static void startCondSection(yyscan_t yyscanner,const QCString §Id) //printf("startCondSection: skip=%d stack=%d\n",g_skip,g_condStack.count()); CondParser prs; bool expResult = prs.parse(yyextra->fileName,yyextra->lineNr,sectId); - yyextra->condStack.push(CondCtx(yyextra->lineNr,sectId,yyextra->skip)); + yyextra->condStack.push(commentcnvYY_CondCtx(yyextra->lineNr,sectId,yyextra->skip)); if (!expResult) // not enabled { yyextra->skip=TRUE; @@ -1074,7 +1092,7 @@ static void endCondSection(yyscan_t yyscanner) } else { - const CondCtx &ctx = yyextra->condStack.top(); + const commentcnvYY_CondCtx &ctx = yyextra->condStack.top(); yyextra->skip=ctx.skip; yyextra->condStack.pop(); } @@ -1205,7 +1223,7 @@ void convertCppComments(BufStr *inBuf,BufStr *outBuf,const QCString &fileName) yylex(yyscanner); while (!yyextra->condStack.empty()) { - const CondCtx &ctx = yyextra->condStack.top(); + const commentcnvYY_CondCtx &ctx = yyextra->condStack.top(); QCString sectionInfo(" "); if (ctx.sectionId!=" ") sectionInfo.sprintf(" with label '%s' ",ctx.sectionId.stripWhiteSpace().data()); warn(yyextra->fileName,ctx.lineNr,"Conditional section%sdoes not have " diff --git a/src/commentscan.l b/src/commentscan.l index 23af80f..1974732 100644 --- a/src/commentscan.l +++ b/src/commentscan.l @@ -19,6 +19,10 @@ %option extra-type="struct commentscanYY_state *" %top{ #include <stdint.h> +// forward declare yyscan_t to improve typesafety +#define YY_TYPEDEF_YY_SCANNER_T +struct yyguts_t; +typedef yyguts_t *yyscan_t; } %{ @@ -83,6 +87,7 @@ static bool handleFile(yyscan_t yyscanner,const QCString &, const StringVector & static bool handleDir(yyscan_t yyscanner,const QCString &, const StringVector &); static bool handleExample(yyscan_t yyscanner,const QCString &, const StringVector &); static bool handleDetails(yyscan_t yyscanner,const QCString &, const StringVector &); +static bool handleRaiseWarning(yyscan_t yyscanner,const QCString &, const StringVector &); static bool handleNoop(yyscan_t yyscanner,const QCString &, const StringVector &); static bool handleName(yyscan_t yyscanner,const QCString &, const StringVector &); static bool handleTodo(yyscan_t yyscanner,const QCString &, const StringVector &); @@ -255,6 +260,7 @@ static const std::map< std::string, DocCmdMap > docCmdMap = { "public", { &handlePublic, CommandSpacing::Invisible }}, { "publicsection", { &handlePublicSection, CommandSpacing::Invisible }}, { "pure", { &handlePure, CommandSpacing::Invisible }}, + { "raisewarning", { &handleRaiseWarning, CommandSpacing::Invisible }}, { "refitem", { &handleRefItem, CommandSpacing::Inline }}, { "related", { &handleRelated, CommandSpacing::Invisible }}, { "relatedalso", { &handleRelatedAlso, CommandSpacing::Invisible }}, @@ -301,7 +307,8 @@ static const std::map< std::string, DocCmdMap > docCmdMap = { "weakgroup", { &handleWeakGroup, CommandSpacing::Invisible }}, { "xmlinclude", { 0, CommandSpacing::Inline }}, { "xmlonly", { &handleFormatBlock, CommandSpacing::Invisible }}, - { "xrefitem", { &handleXRefItem, CommandSpacing::XRef }} + { "xrefitem", { &handleXRefItem, CommandSpacing::XRef }}, + { "iliteral", { &handleFormatBlock, CommandSpacing::Inline }}, }; #define YY_NO_INPUT 1 @@ -402,12 +409,15 @@ struct commentscanYY_state QCString guardExpr; int roundCount = 0; + int HTMLDetails = 0; bool insideParBlock = FALSE; bool inInternalDocs = FALSE; int prevPosition = 0; DocGroup docGroup; bool markdownSupport = TRUE; + + QCString raiseWarning; }; @@ -449,6 +459,10 @@ static void addIline(yyscan_t yyscanner,int lineNr); #undef YY_INPUT #define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); +// otherwise the filename would be the name of the converted file (*.cpp instead of *.l) +static inline const char *getLexerFILE() {return __FILE__;} +#include "doxygen_lex.h" + %} /* start command character */ @@ -467,8 +481,11 @@ CODE [cC][oO][dD][eE] CAPTION [cC][aA][pP][tT][iI][oO][nN] CENTER [cC][eE][nN][tT][eE][rR] DIV [dD][iI][vV] +DETAILS [dD][eE][tT][aA][iI][lL][sS] DETAILEDHTML {CENTER}|{DIV}|{PRE}|{UL}|{TABLE}|{OL}|{DL}|{P}|[Hh][1-6]|{IMG}|{HR}|{PARA} DETAILEDHTMLOPT {CODE} +SUMMARY [sS][uU][mM][mM][aA][rR][yY] +REMARKS [rR][eE][mM][aA][rR][kK][sS] BN [ \t\n\r] BL [ \t\r]*"\n" B [ \t] @@ -489,7 +506,7 @@ CITEID {CITESCHAR}{CITEECHAR}*("."{CITESCHAR}{CITEECHAR}*)*|"\""{CITESCHAR}{C SCOPEID {ID}({ID}*{BN}*"::"{BN}*)*({ID}?) SCOPENAME "$"?(({ID}?{BN}*("::"|"."){BN}*)*)((~{BN}*)?{ID}) TMPLSPEC "<"{BN}*[^>]+{BN}*">" -MAILADDR [a-z_A-Z0-9.+\-]+"@"[a-z_A-Z0-9\-]+("."[a-z_A-Z0-9\-]+)+[a-z_A-Z0-9\-]+ +MAILADDR ("mailto:")?[a-z_A-Z0-9\x80-\xff.+-]+"@"[a-z_A-Z0-9\x80-\xff-]+("."[a-z_A-Z0-9\x80-\xff\-]+)+[a-z_A-Z0-9\x80-\xff\-]+ RCSTAG "$"{ID}":"[^\n$]+"$" // C start comment @@ -553,6 +570,7 @@ STopt [^\n@\\]* %x GuardExpr %x CdataSection %x Noop +%x RaiseWarning %% @@ -601,19 +619,28 @@ STopt [^\n@\\]* // continue with the same input REJECT; } -<Comment>"<summary>" { // start of a .NET XML style brief description - setOutput(yyscanner,OutputBrief); +<Comment>"<"{DETAILS}{ATTR}">" { // start of a HTML style details description + yyextra->HTMLDetails++; + setOutput(yyscanner,OutputDoc); addOutput(yyscanner,yytext); } -<Comment>"<remarks>" { // start of a .NET XML style detailed description - setOutput(yyscanner,OutputDoc); +<Comment>"</"{DETAILS}">" { // end of a HTML style details description + if (yyextra->HTMLDetails) yyextra->HTMLDetails--; addOutput(yyscanner,yytext); } -<Comment>"</summary>" { // start of a .NET XML style detailed description +<Comment>"<"{SUMMARY}">" { // start of a .NET XML style brief description + if (!yyextra->HTMLDetails) setOutput(yyscanner,OutputBrief); addOutput(yyscanner,yytext); + } +<Comment>"<"{REMARKS}">" { // start of a .NET XML style detailed description setOutput(yyscanner,OutputDoc); + addOutput(yyscanner,yytext); } -<Comment>"</remarks>" { // end of a brief or detailed description +<Comment>"</"{SUMMARY}">" { // start of a .NET XML style detailed description + addOutput(yyscanner,yytext); + if (!yyextra->HTMLDetails) setOutput(yyscanner,OutputDoc); + } +<Comment>"</"{REMARKS}">" { // end of a brief or detailed description setOutput(yyscanner,OutputDoc); addOutput(yyscanner,yytext); } @@ -737,7 +764,7 @@ STopt [^\n@\\]* <Comment>{B}*{CMD}"~"[a-z_A-Z-]* { // language switch command QCString langId = QCString(yytext).stripWhiteSpace().mid(2); if (!langId.isEmpty() && - qstricmp(Config_getEnum(OUTPUT_LANGUAGE).data(),langId.data())!=0) + qstricmp(Config_getEnumAsString(OUTPUT_LANGUAGE).data(),langId.data())!=0) { // enable language specific section BEGIN(SkipLang); } @@ -1003,7 +1030,8 @@ STopt [^\n@\\]* /* ------------ handle argument of namespace command --------------- */ <NameSpaceDocArg1>{SCOPENAME} { // handle argument - yyextra->current->name = substitute(QCString(yytext),QCString("."),QCString("::")); + lineCount(yyscanner); + yyextra->current->name = substitute(removeRedundantWhiteSpace(QCString(yytext)),QCString("."),QCString("::")); BEGIN( Comment ); } <NameSpaceDocArg1>{LC} { // line continuation @@ -1071,10 +1099,12 @@ STopt [^\n@\\]* /* ------ handle argument of class/struct/union command --------------- */ <ClassDocArg1>{SCOPENAME}{TMPLSPEC} { + lineCount(yyscanner); yyextra->current->name = substitute(removeRedundantWhiteSpace(QCString(yytext)),".","::"); BEGIN( ClassDocArg2 ); } <ClassDocArg1>{SCOPENAME} { // first argument + lineCount(yyscanner); yyextra->current->name = substitute(QCString(yytext),".","::"); if (yyextra->current->section==Entry::PROTOCOLDOC_SEC) { @@ -1084,6 +1114,7 @@ STopt [^\n@\\]* BEGIN( ClassDocArg2 ); } <CategoryDocArg1>{SCOPENAME}{B}*"("[^\)]+")" { + lineCount(yyscanner); yyextra->current->name = substitute(QCString(yytext),".","::"); BEGIN( ClassDocArg2 ); } @@ -1487,7 +1518,7 @@ STopt [^\n@\\]* /* ----- handle arguments of the preformatted block commands ------- */ -<FormatBlock>{CMD}("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endrtfonly"|"endmanonly"|"enddot"|"endcode"|"endmsc")/{NW} { // possible ends +<FormatBlock>{CMD}("endverbatim"|"endiliteral"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endrtfonly"|"endmanonly"|"enddot"|"endcode"|"endmsc")/{NW} { // possible ends addOutput(yyscanner,yytext); if (&yytext[4]==yyextra->blockName) // found end of the block { @@ -1509,12 +1540,12 @@ STopt [^\n@\\]* addOutput(yyscanner,'\n'); } <FormatBlock>{CCS} { // start of a C-comment - if (!(yyextra->blockName=="code" || yyextra->blockName=="verbatim")) yyextra->commentCount++; + if (!(yyextra->blockName=="code" || yyextra->blockName=="verbatim" || yyextra->blockName=="iliteral")) yyextra->commentCount++; addOutput(yyscanner,yytext); } <FormatBlock>{CCE} { // end of a C-comment addOutput(yyscanner,yytext); - if (!(yyextra->blockName=="code" || yyextra->blockName=="verbatim")) + if (!(yyextra->blockName=="code" || yyextra->blockName=="verbatim" || yyextra->blockName=="iliteral")) { yyextra->commentCount--; if (yyextra->commentCount<0) @@ -1760,6 +1791,18 @@ STopt [^\n@\\]* } <Noop>. { // ignore other stuff } + /* ----- handle argument of raisewarning command ------- */ +<RaiseWarning>{DOCNL} { // end of argument + warn_doc_error(yyextra->fileName,yyextra->lineNr, + "%s",qPrint(yyextra->raiseWarning)); + yyextra->raiseWarning = ""; + if (*yytext=='\n') yyextra->lineNr++; + addOutput(yyscanner,'\n'); + BEGIN( Comment ); + } +<RaiseWarning>. { // ignore other stuff + yyextra->raiseWarning += yytext; + } /* ----- handle argument of ingroup command ------- */ <InGroupParam>{LABELID} { // group id @@ -1893,7 +1936,7 @@ STopt [^\n@\\]* <SkipLang>[\\@]"~"[a-zA-Z-]* { /* language switch */ QCString langId(&yytext[2]); if (langId.isEmpty() || - qstricmp(Config_getEnum(OUTPUT_LANGUAGE).data(),langId.data())==0) + qstricmp(Config_getEnumAsString(OUTPUT_LANGUAGE).data(),langId.data())==0) { // enable language specific section BEGIN(Comment); } @@ -1931,20 +1974,41 @@ STopt [^\n@\\]* /* ----- handle argument of the copydoc command ------- */ -<CopyDoc><<EOF>> | -<CopyDoc>{DOCNL} { - if (*yytext=='\n') yyextra->lineNr++; - addOutput(yyscanner,'\n'); +<CopyDoc><<EOF>> { setOutput(yyscanner,OutputDoc); - addOutput(yyscanner," \\copydetails "); + addOutput(yyscanner," \\ilinebr\\ilinebr\\copydetails "); addOutput(yyscanner,yyextra->copyDocArg); addOutput(yyscanner,"\n"); BEGIN(Comment); } -<CopyDoc>[^\n\\]+ { +<CopyDoc>{DOCNL} { + if (*yytext=='\n') yyextra->lineNr++; + if (yyextra->braceCount==0) + { + setOutput(yyscanner,OutputDoc); + addOutput(yyscanner," \\ilinebr\\ilinebr\\copydetails "); + addOutput(yyscanner,yyextra->copyDocArg); + addOutput(yyscanner,"\n"); + BEGIN(Comment); + } + } +<CopyDoc>{LC} { // line continuation + yyextra->lineNr++; + } +<CopyDoc>[^@\\\n()]+ { // non-special characters yyextra->copyDocArg+=yytext; addOutput(yyscanner,yytext); } +<CopyDoc>"(" { + yyextra->copyDocArg+=yytext; + addOutput(yyscanner,yytext); + yyextra->braceCount++; + } +<CopyDoc>")" { + yyextra->copyDocArg+=yytext; + addOutput(yyscanner,yytext); + yyextra->braceCount--; + } <CopyDoc>. { yyextra->copyDocArg+=yytext; addOutput(yyscanner,yytext); @@ -2139,6 +2203,7 @@ static bool handleMainpage(yyscan_t yyscanner,const QCString &, const StringVect { yyextra->current->name = "mainpage"; } + setOutput(yyscanner,OutputDoc); BEGIN( PageDocArg2 ); return stop; } @@ -2216,6 +2281,14 @@ static bool handleDetails(yyscan_t yyscanner,const QCString &, const StringVecto return FALSE; } +static bool handleRaiseWarning(yyscan_t yyscanner,const QCString &, const StringVector &) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->raiseWarning = ""; + BEGIN( RaiseWarning ); + return FALSE; +} + static bool handleNoop(yyscan_t yyscanner,const QCString &, const StringVector &) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; @@ -2324,6 +2397,7 @@ static bool handleRelated(yyscan_t yyscanner,const QCString &cmd, const StringVe "found multiple \\relates, \\relatesalso or \\memberof commands in a comment block, using last definition"); } yyextra->current->relatesType = Simple; + yyextra->currentCmd = cmd; BEGIN(RelatesParam1); return FALSE; } @@ -2823,7 +2897,12 @@ static bool handleCopyDetails(yyscan_t yyscanner,const QCString &, const StringV static bool handleCopyDoc(yyscan_t yyscanner,const QCString &, const StringVector &) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - setOutput(yyscanner,OutputBrief); + if (yyextra->current->brief.isEmpty() && yyextra->current->doc.isEmpty()) + { // if we don't have a brief or detailed description yet, + // then the @copybrief should end up in the brief description. + // otherwise it will be copied inline (see bug691315 & bug700788) + setOutput(yyscanner,OutputBrief); + } if (!yyextra->spaceBeforeCmd.isEmpty()) { addOutput(yyscanner,yyextra->spaceBeforeCmd); @@ -2831,6 +2910,7 @@ static bool handleCopyDoc(yyscan_t yyscanner,const QCString &, const StringVecto } addOutput(yyscanner,"\\copybrief "); yyextra->copyDocArg.resize(0); + yyextra->braceCount = 0; BEGIN(CopyDoc); return FALSE; } @@ -3202,6 +3282,7 @@ static inline void setOutput(yyscan_t yyscanner,OutputContext ctx) if (oldContext!=yyextra->inContext) { stripTrailingWhiteSpace(yyextra->current->doc); + if (yyextra->current->doc.isEmpty()) yyextra->current->docLine = yyextra->lineNr; if (yyextra->current->docFile.isEmpty()) { yyextra->current->docFile = yyextra->fileName; @@ -3213,6 +3294,7 @@ static inline void setOutput(yyscan_t yyscanner,OutputContext ctx) case OutputBrief: if (oldContext!=yyextra->inContext) { + if (yyextra->current->brief.isEmpty()) yyextra->current->briefLine = yyextra->lineNr; if (yyextra->current->briefFile.isEmpty()) { yyextra->current->briefFile = yyextra->fileName; @@ -3304,8 +3386,8 @@ static inline void addOutput(yyscan_t yyscanner,char c) static void addIline(yyscan_t yyscanner,int lineNr) { - char cmd[20]; - sprintf(cmd,"\\iline %d ",lineNr); + char cmd[30]; + sprintf(cmd,"\\iline %d \\ilinebr ",lineNr); addOutput(yyscanner, cmd); } diff --git a/src/conceptdef.cpp b/src/conceptdef.cpp index c9c886e..977f569 100644 --- a/src/conceptdef.cpp +++ b/src/conceptdef.cpp @@ -54,6 +54,7 @@ class ConceptDefImpl : public DefinitionMixin<ConceptDefMutable> virtual const NamespaceDef *getNamespaceDef() const; virtual const FileDef *getFileDef() const; virtual QCString title() const; + virtual int groupId() const; //---------- ConceptDefMutable virtual void setIncludeFile(FileDef *fd,const QCString &incName,bool local,bool force); @@ -64,6 +65,7 @@ class ConceptDefImpl : public DefinitionMixin<ConceptDefMutable> virtual void writeDocumentation(OutputList &); virtual void setInitializer(const QCString &init); virtual void findSectionsInDocumentation(); + virtual void setGroupId(int id); //---------- Helpers void writeBriefDescription(OutputList &) const; @@ -79,6 +81,7 @@ class ConceptDefImpl : public DefinitionMixin<ConceptDefMutable> FileDef *m_fileDef = 0; ArgumentList m_tArgList; QCString m_initializer; + int m_groupId = -1; }; ConceptDefMutable *createConceptDef( @@ -134,6 +137,8 @@ class ConceptDefAliasImpl : public DefinitionAliasMixin<ConceptDef> virtual void writeDeclarationLink(OutputList &ol,bool &found, const QCString &header,bool localNames) const { getCdAlias()->writeDeclarationLink(ol,found,header,localNames); } + virtual int groupId() const + { return getCdAlias()->groupId(); } }; ConceptDef *createConceptDefAlias(const Definition *newScope,const ConceptDef *cd) @@ -266,11 +271,21 @@ QCString ConceptDefImpl::title() const return theTranslator->trConceptReference(displayName()); } +int ConceptDefImpl::groupId() const +{ + return m_groupId; +} + +void ConceptDefImpl::setGroupId(int id) +{ + m_groupId = id; +} + void ConceptDefImpl::writeTagFile(TextStream &tagFile) { tagFile << " <compound kind=\"concept\">\n"; tagFile << " <name>" << convertToXML(name()) << "</name>\n"; - tagFile << " <filename>" << convertToXML(getOutputFileBase()) << Doxygen::htmlFileExtension << "</filename>\n"; + tagFile << " <filename>" << convertToXML(addHtmlExtensionIfMissing(getOutputFileBase())) << "</filename>\n"; QCString idStr = id(); if (!idStr.isEmpty()) { @@ -494,13 +509,6 @@ void ConceptDefImpl::writeDocumentation(OutputList &ol) ol.startContents(); - if (Doxygen::searchIndex) - { - Doxygen::searchIndex->setCurrentDoc(this,anchor(),FALSE); - Doxygen::searchIndex->addWord(localName(),TRUE); - } - - Doxygen::indexList->addIndexItem(this,0); //---------------------------------------- start flexible part ------------------------------- for (const auto &lde : LayoutDocManager::instance().docEntries(LayoutDocManager::Concept)) diff --git a/src/conceptdef.h b/src/conceptdef.h index 8d40ce5..d055579 100644 --- a/src/conceptdef.h +++ b/src/conceptdef.h @@ -37,6 +37,7 @@ class ConceptDef : public Definition virtual const NamespaceDef *getNamespaceDef() const = 0; virtual const FileDef *getFileDef() const = 0; virtual QCString title() const = 0; + virtual int groupId() const = 0; }; class ConceptDefMutable : public DefinitionMutable, public ConceptDef @@ -50,6 +51,7 @@ class ConceptDefMutable : public DefinitionMutable, public ConceptDef virtual void writeDocumentation(OutputList &ol) = 0; virtual void setInitializer(const QCString &init) = 0; virtual void findSectionsInDocumentation() = 0; + virtual void setGroupId(int id) = 0; }; ConceptDefMutable *createConceptDef( diff --git a/src/config.h b/src/config.h index 8436fe3..2de2173 100644 --- a/src/config.h +++ b/src/config.h @@ -33,6 +33,7 @@ #define Config_getBool(name) (ConfigValues::instance().name()) #define Config_getInt(name) (ConfigValues::instance().name()) #define Config_getEnum(name) (ConfigValues::instance().name()) +#define Config_getEnumAsString(name) (ConfigValues::instance().name##_str()) #define Config_getList(name) (ConfigValues::instance().name()) #define Config_updateString(name,value) (ConfigValues::instance().update_##name(value)); #define Config_updateBool(name,value) (ConfigValues::instance().update_##name(value)); @@ -82,8 +83,12 @@ namespace Config /*! Check the validity of the parsed options and correct or warn the user where needed. * \param quiet setting for the QUIET option (can have been overruled by means of a command line option) + * \param check check HTML / LaTeX header file etc. on existence (and terminate when not present) */ - void checkAndCorrect(bool quiet); + void checkAndCorrect(bool quiet, const bool check); + + /*! Adjust any configuration values based on the value of obsolete options. */ + void updateObsolete(); /*! Clean up any data */ void deinit(); diff --git a/src/config.xml b/src/config.xml index cd19d72..92de131 100644 --- a/src/config.xml +++ b/src/config.xml @@ -45,8 +45,13 @@ the <code>+=</code> operator can be used instead of <code>=</code> to append new values to the list. Values are sequences of non-blanks. If the value should contain one or more blanks it must be surrounded by quotes (<code>"..."</code>). Multiple lines can be concatenated by inserting a backslash (\c \\) -as the last character of a line. Environment variables can be expanded -using the pattern <code>\$(ENV_VARIABLE_NAME)</code>. +as the last character of a line. + +Environment variables can be expanded using the pattern <code>\$(ENV_VARIABLE_NAME)</code>. +A small example: +\verbatim +DOT_PATH = $(YOUR_DOT_PATH) +\endverbatim You can also include part of a configuration file from another configuration file using a <code>\@INCLUDE</code> tag as follows: @@ -430,7 +435,6 @@ Go to the <a href="commands.html">next</a> section or return to the started. ]]> </docs> - <value name=''/> </option> <option type='list' id='STRIP_FROM_INC_PATH' format='string'> <docs> @@ -1375,7 +1379,10 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn" <![CDATA[ The \c WARN_LOGFILE tag can be used to specify a file to which warning and error messages should be written. If left blank the output is written - to standard error (`stderr`). + to standard error (`stderr`). In case the file specified cannot be opened for + writing the warning and error messages are written to standard error. When as + file `-` is specified the warning and error messages are written to standard output + (`stdout`). ]]> </docs> </option> @@ -1394,7 +1401,6 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn" \note If this tag is empty the current directory is searched. ]]> </docs> - <value name=''/> </option> <option type='string' id='INPUT_ENCODING' format='string' defval='UTF-8'> <docs> @@ -1514,7 +1520,7 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn" (namespaces, classes, functions, etc.) that should be excluded from the output. The symbol name can be a fully qualified name, a word, or if the wildcard `*` is used, a substring. Examples: `ANamespace`, `AClass`, - `AClass::ANamespace`, `ANamespace::*Test` + `ANamespace::AClass`, `ANamespace::*Test` <br>Note that the wildcards are matched against the file with absolute path, so to exclude all test directories use the pattern `*``/test/``*` @@ -2161,6 +2167,16 @@ hr.footer { ]]> </docs> </option> + <option type='string' id='DOCSET_FEEDURL' format='string' depends='GENERATE_DOCSET'> + <docs> +<![CDATA[ + This tag determines the URL of the docset + feed. A documentation feed provides an umbrella under which multiple + documentation sets from a single provider (such as a company or product suite) + can be grouped. +]]> + </docs> + </option> <option type='string' id='DOCSET_BUNDLE_ID' format='string' defval='org.doxygen.Project' depends='GENERATE_DOCSET'> <docs> <![CDATA[ @@ -2406,14 +2422,16 @@ The \c DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. <option type='bool' id='FULL_SIDEBAR' defval='0' depends='GENERATE_HTML'> <docs> <![CDATA[ - When both \c GENERATE_TREEVIEW and \c DISABLE_INDEX are set to YES, then the + When both \ref cfg_generate_treeview "GENERATE_TREEVIEW" and \ref cfg_disable_index "DISABLE_INDEX" + are set to \c YES, then the \c FULL_SIDEBAR option determines if the side bar is limited to only the treeview area (value \c NO) or if it should extend to the full height of the window (value \c YES). Setting this to \c YES gives a layout similar to https://docs.readthedocs.io with more room for contents, but less room for the project logo, title, and description. - If either \c GENERATOR_TREEVIEW or \c DISABLE_INDEX is set to \c NO, this option + If either \ref cfg_generate_treeview "GENERATE_TREEVIEW" or \ref cfg_disable_index "DISABLE_INDEX" + is set to \c NO, this option has no effect. ]]> </docs> @@ -2445,6 +2463,14 @@ The \c DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. ]]> </docs> </option> + <option type='bool' id='OBFUSCATE_EMAILS' defval='1' depends='GENERATE_HTML'> + <docs> +<![CDATA[ +If the \c OBFUSCATE_EMAILS tag is set to \c YES, doxygen will +obfuscate email addresses. +]]> + </docs> + </option> <option type='enum' id='HTML_FORMULA_FORMAT' defval='png' depends='GENERATE_HTML'> <docs> <![CDATA[ @@ -2859,7 +2885,7 @@ doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty as set by \ref cfg_latex_bib_style "LATEX_BIB_STYLE", in case nothing is set the bib style `plain` is used. This setting is typically used in combination with the block name `CITATIONS_PRESENT`. - <dt><code>$latexbibfiles</code><dd>will be replaced by the comma separated list of `bib. files + <dt><code>$latexbibfiles</code><dd>will be replaced by the comma separated list of `bib`. files as set by \ref cfg_cite_bib_files "CITE_BIB_FILES" (when necessary a missing `.bib` is automatically added). This setting is typically used in combination with the block name `CITATIONS_PRESENT`. @@ -3489,17 +3515,6 @@ where `loc1` and `loc2` can be relative or absolute paths or URLs. </option> </group> <group name='Dot' docs='Configuration options related to the dot tool'> - <option type='bool' id='CLASS_DIAGRAMS' defval='1'> - <docs> -<![CDATA[ - If the \c CLASS_DIAGRAMS tag is set to \c YES, doxygen will - generate a class diagram (in HTML and \f$\mbox{\LaTeX}\f$) for classes with base or - super classes. Setting the tag to \c NO turns the diagrams off. Note that - this option also works with \ref cfg_have_dot "HAVE_DOT" disabled, but it is recommended to - install and use \c dot, since it yields more powerful graphs. -]]> - </docs> - </option> <option type='string' id='DIA_PATH' format='dir' defval=''> <docs> <![CDATA[ @@ -3570,15 +3585,21 @@ to be found in the default search path. ]]> </docs> </option> - <option type='bool' id='CLASS_GRAPH' defval='1' depends='HAVE_DOT'> + <option type='enum' id='CLASS_GRAPH' defval='YES'> <docs> <![CDATA[ - If the \c CLASS_GRAPH tag is set to \c YES then doxygen + If the \c CLASS_GRAPH tag is set to \c YES (or \c GRAPH) then doxygen will generate a graph for each documented class showing the direct and - indirect inheritance relations. Setting this tag to \c YES will force - the \ref cfg_class_diagrams "CLASS_DIAGRAMS" tag to \c NO. + indirect inheritance relations. In case \ref cfg_have_dot "HAVE_DOT" is set as well + `dot` will be used to draw the graph, otherwise the built-in generator will be used. + If the \c CLASS_GRAPH tag is set to \c TEXT the direct and indirect inheritance relations + will be shown as texts / links. ]]> </docs> + <value name="NO" /> + <value name="YES" /> + <value name="TEXT" /> + <value name="GRAPH" /> </option> <option type='bool' id='COLLABORATION_GRAPH' defval='1' depends='HAVE_DOT'> <docs> @@ -3721,6 +3742,14 @@ UML notation for the relationships. ]]> </docs> </option> + <option type='int' id='DIR_GRAPH_MAX_DEPTH' minval='1' maxval='25' defval='1' depends='DIRECTORY_GRAPH'> + <docs> +<![CDATA[ + The \c DIR_GRAPH_MAX_DEPTH tag can be used to limit the maximum number of + levels of child directories generated in directory dependency graphs by \c dot. +]]> + </docs> + </option> <option type='enum' id='DOT_IMAGE_FORMAT' defval='png' depends='HAVE_DOT'> <docs> <![CDATA[ @@ -3793,11 +3822,12 @@ UML notation for the relationships. ]]> </docs> </option> - <option type='string' id='PLANTUML_JAR_PATH' format='dir' defval=''> + <option type='string' id='PLANTUML_JAR_PATH' format='filedir' defval=''> <docs> <![CDATA[ When using plantuml, the \c PLANTUML_JAR_PATH tag should be used to specify the path where - java can find the \c plantuml.jar file. If left blank, it is assumed PlantUML is not used or + java can find the \c plantuml.jar file or to the filename of \c jar file to be used. + If left blank, it is assumed PlantUML is not used or called during a preprocessing step. Doxygen will generate a warning when it encounters a \ref cmdstartuml "\\startuml" command in this case and will not generate output for the diagram. ]]> @@ -3874,6 +3904,9 @@ UML notation for the relationships. If the \c GENERATE_LEGEND tag is set to \c YES doxygen will generate a legend page explaining the meaning of the various boxes and arrows in the dot generated graphs. + \note This tag requires that \ref cfg_uml_look "UML_LOOK" isn't set, i.e. the + doxygen internal graphical representation for inheritance and collaboration diagrams + is used. ]]> </docs> </option> @@ -3887,32 +3920,33 @@ This setting is not only used for dot files but also for msc temporary files. ]]> </docs> </option> - <option type='obsolete' id='USE_WINDOWS_ENCODING'/> - <option type='obsolete' id='DETAILS_AT_TOP'/> - <option type='obsolete' id='QTHELP_FILE'/> - <option type='obsolete' id='QTHELP_CONFIG'/> - <option type='obsolete' id='DOXYGEN2QTHELP_LOC'/> - <option type='obsolete' id='MAX_DOT_GRAPH_WIDTH'/> - <option type='obsolete' id='MAX_DOT_GRAPH_HEIGHT'/> - <option type='obsolete' id='CGI_NAME'/> - <option type='obsolete' id='CGI_URL'/> - <option type='obsolete' id='DOC_URL'/> - <option type='obsolete' id='DOC_ABSPATH'/> - <option type='obsolete' id='BIN_ABSPATH'/> - <option type='obsolete' id='EXT_DOC_PATHS'/> - <option type='obsolete' id='USE_INLINE_TREES'/> - <option type='obsolete' id='SHOW_DIRECTORIES'/> - <option type='obsolete' id='HTML_ALIGN_MEMBERS'/> - <option type='obsolete' id='SYMBOL_CACHE_SIZE'/> - <option type='obsolete' id='XML_SCHEMA'/> - <option type='obsolete' id='XML_DTD'/> - <option type='obsolete' id='PERL_PATH'/> - <option type='obsolete' id='MSCGEN_PATH'/> - <option type='obsolete' id='TCL_SUBST'/> - <option type='obsolete' id='COLS_IN_ALPHA_INDEX'/> - <option type='obsolete' id='OUTPUT_TEXT_DIRECTION'/> - <option type='obsolete' id='DOCBOOK_PROGRAMLISTING'/> - <option type='obsolete' id='RTF_SOURCE_CODE'/> - <option type='obsolete' id='LATEX_SOURCE_CODE'/> + <option type='obsolete' orgtype='bool' id='USE_WINDOWS_ENCODING'/> + <option type='obsolete' orgtype='bool' id='DETAILS_AT_TOP'/> + <option type='obsolete' orgtype='string' id='QTHELP_FILE'/> + <option type='obsolete' orgtype='string' id='QTHELP_CONFIG'/> + <option type='obsolete' orgtype='string' id='DOXYGEN2QTHELP_LOC'/> + <option type='obsolete' orgtype='int' id='MAX_DOT_GRAPH_WIDTH'/> + <option type='obsolete' orgtype='int' id='MAX_DOT_GRAPH_HEIGHT'/> + <option type='obsolete' orgtype='string' id='CGI_NAME'/> + <option type='obsolete' orgtype='string' id='CGI_URL'/> + <option type='obsolete' orgtype='string' id='DOC_URL'/> + <option type='obsolete' orgtype='string' id='DOC_ABSPATH'/> + <option type='obsolete' orgtype='string' id='BIN_ABSPATH'/> + <option type='obsolete' orgtype='list' id='EXT_DOC_PATHS'/> + <option type='obsolete' orgtype='bool' id='USE_INLINE_TREES'/> + <option type='obsolete' orgtype='bool' id='SHOW_DIRECTORIES'/> + <option type='obsolete' orgtype='bool' id='HTML_ALIGN_MEMBERS'/> + <option type='obsolete' orgtype='int' id='SYMBOL_CACHE_SIZE'/> + <option type='obsolete' orgtype='string' id='XML_SCHEMA'/> + <option type='obsolete' orgtype='string' id='XML_DTD'/> + <option type='obsolete' orgtype='string' id='PERL_PATH'/> + <option type='obsolete' orgtype='string' id='MSCGEN_PATH'/> + <option type='obsolete' orgtype='list' id='TCL_SUBST'/> + <option type='obsolete' orgtype='int' id='COLS_IN_ALPHA_INDEX'/> + <option type='obsolete' orgtype='enum' id='OUTPUT_TEXT_DIRECTION'/> + <option type='obsolete' orgtype='bool' id='DOCBOOK_PROGRAMLISTING'/> + <option type='obsolete' orgtype='bool' id='RTF_SOURCE_CODE'/> + <option type='obsolete' orgtype='bool' id='LATEX_SOURCE_CODE'/> + <option type='obsolete' orgtype='bool' id='CLASS_DIAGRAMS'/> </group> </doxygenconfig> diff --git a/src/configgen.py b/src/configgen.py index b7736c4..66bebce 100755 --- a/src/configgen.py +++ b/src/configgen.py @@ -19,821 +19,878 @@ import textwrap from xml.dom import minidom, Node def transformDocs(doc): - # join lines, unless it is an empty line - # remove doxygen layout constructs + # join lines, unless it is an empty line + # remove doxygen layout constructs # Note: also look at expert.cpp of doxywizard for doxywizard parts - doc = doc.strip() - doc = doc.replace("\n", " ") - doc = doc.replace("\r", " ") - doc = doc.replace("\t", " ") - doc = doc.replace("\\&", "&") - doc = doc.replace("(\\c ", "(") - doc = doc.replace("\\c ", " ") - doc = doc.replace("\\b ", " ") - doc = doc.replace("\\e ", " ") - doc = doc.replace("\\$", "$") - doc = doc.replace("\\#include ", "#include ") - doc = doc.replace("\\#undef ", "#undef ") - doc = doc.replace("-# ", "\n - ") - doc = doc.replace(" - ", "\n - ") - doc = doc.replace("\\sa", "\nSee also: ") - doc = doc.replace("\\par", "\n") - doc = doc.replace("@note", "\nNote:") - doc = doc.replace("\\note", "\nNote:") - doc = doc.replace("\\verbatim", "\n") - doc = doc.replace("\\endverbatim", "\n") - doc = doc.replace("<code>", "") - doc = doc.replace("</code>", "") - doc = doc.replace("`", "") - doc = doc.replace("\\<", "<") - doc = doc.replace("\\>", ">") - doc = doc.replace("\\@", "@") - doc = doc.replace("\\\\", "\\") - # \ref name "description" -> description - doc = re.sub('\\\\ref +[^ ]* +"([^"]*)"', '\\1', doc) - # \ref specials - # \ref <key> -> description - doc = re.sub('\\\\ref +doxygen_usage', '"Doxygen usage"', doc) - doc = re.sub('\\\\ref +extsearch', '"External Indexing and Searching"', - doc) - doc = re.sub('\\\\ref +layout', '"Changing the layout of pages"', doc) - doc = re.sub('\\\\ref +external', '"Linking to external documentation"', - doc) - doc = re.sub('\\\\ref +doxygen_finetune', '"Fine-tuning the output"', - doc) - doc = re.sub('\\\\ref +formulas', '"Including formulas"', doc) - # fallback for not handled - doc = re.sub('\\\\ref', '', doc) - #<a href="address">description</a> -> description (see: address) - doc = re.sub('<a +href="([^"]*)" *>([^<]*)</a>', '\\2 (see: \n\\1)', doc) - # LaTeX name as formula -> LaTeX - doc = doc.replace("\\f$\\mbox{\\LaTeX}\\f$", "LaTeX") - # Other formula's (now just 2) so explicitly mentioned. - doc = doc.replace("\\f$2^{(16+\\mbox{LOOKUP\\_CACHE\\_SIZE})}\\f$", - "2^(16+LOOKUP_CACHE_SIZE)") - doc = doc.replace("\\f$2^{16} = 65536\\f$", "2^16=65536") - # remove consecutive spaces - doc = re.sub(" +", " ", doc) - # a dirty trick to get an extra empty line in Doxyfile documentation. - # <br> will be removed later on again, we need it here otherwise splitlines - # will filter the extra line. - doc = doc.replace("<br>", "\n<br>\n") - # a dirty trick to go to the next line in Doxyfile documentation. - # <br/> will be removed later on again, we need it here otherwise splitlines - # will filter the line break. - doc = doc.replace("<br/>", "\n<br/>\n") - # - doc = doc.splitlines() - split_doc = [] - for line in doc: - split_doc += textwrap.wrap(line, 78) - # replace \ by \\, replace " by \", and ' ' by a newline with end string - # and start string at next line - docC = [] - for line in split_doc: - if (line.strip() != "<br/>"): - docC.append(line.strip().replace('\\', '\\\\'). - replace('"', '\\"').replace("<br>", "")) - return docC + doc = doc.strip() + doc = doc.replace("\n", " ") + doc = doc.replace("\r", " ") + doc = doc.replace("\t", " ") + doc = doc.replace("\\&", "&") + doc = doc.replace("(\\c ", "(") + doc = doc.replace("\\c ", " ") + doc = doc.replace("\\b ", " ") + doc = doc.replace("\\e ", " ") + doc = doc.replace("\\$", "$") + doc = doc.replace("\\#include ", "#include ") + doc = doc.replace("\\#undef ", "#undef ") + doc = doc.replace("-# ", "\n - ") + doc = doc.replace(" - ", "\n - ") + doc = doc.replace("\\sa", "\nSee also: ") + doc = doc.replace("\\par", "\n") + doc = doc.replace("@note", "\nNote:") + doc = doc.replace("\\note", "\nNote:") + doc = doc.replace("\\verbatim", "\n") + doc = doc.replace("\\endverbatim", "\n") + doc = doc.replace("<code>", "") + doc = doc.replace("</code>", "") + doc = doc.replace("`", "") + doc = doc.replace("\\<", "<") + doc = doc.replace("\\>", ">") + doc = doc.replace("\\@", "@") + doc = doc.replace("\\\\", "\\") + # \ref name "description" -> description + doc = re.sub('\\\\ref +[^ ]* +"([^"]*)"', '\\1', doc) + # \ref specials + # \ref <key> -> description + doc = re.sub('\\\\ref +doxygen_usage', '"Doxygen usage"', doc) + doc = re.sub('\\\\ref +extsearch', '"External Indexing and Searching"', + doc) + doc = re.sub('\\\\ref +layout', '"Changing the layout of pages"', doc) + doc = re.sub('\\\\ref +external', '"Linking to external documentation"', + doc) + doc = re.sub('\\\\ref +doxygen_finetune', '"Fine-tuning the output"', + doc) + doc = re.sub('\\\\ref +formulas', '"Including formulas"', doc) + # fallback for not handled + doc = re.sub('\\\\ref', '', doc) + #<a href="address">description</a> -> description (see: address) + doc = re.sub('<a +href="([^"]*)" *>([^<]*)</a>', '\\2 (see: \n\\1)', doc) + # LaTeX name as formula -> LaTeX + doc = doc.replace("\\f$\\mbox{\\LaTeX}\\f$", "LaTeX") + # Other formula's (now just 2) so explicitly mentioned. + doc = doc.replace("\\f$2^{(16+\\mbox{LOOKUP\\_CACHE\\_SIZE})}\\f$", + "2^(16+LOOKUP_CACHE_SIZE)") + doc = doc.replace("\\f$2^{16} = 65536\\f$", "2^16=65536") + # remove consecutive spaces + doc = re.sub(" +", " ", doc) + # a dirty trick to get an extra empty line in Doxyfile documentation. + # <br> will be removed later on again, we need it here otherwise splitlines + # will filter the extra line. + doc = doc.replace("<br>", "\n<br>\n") + # a dirty trick to go to the next line in Doxyfile documentation. + # <br/> will be removed later on again, we need it here otherwise splitlines + # will filter the line break. + doc = doc.replace("<br/>", "\n<br/>\n") + # + doc = doc.splitlines() + split_doc = [] + for line in doc: + split_doc += textwrap.wrap(line, 78) + # replace \ by \\, replace " by \", and ' ' by a newline with end string + # and start string at next line + docC = [] + for line in split_doc: + if (line.strip() != "<br/>"): + docC.append(line.strip().replace('\\', '\\\\'). + replace('"', '\\"').replace("<br>", "")) + return docC def collectValues(node): - values = [] - for n in node.childNodes: - if (n.nodeName == "value"): - if n.nodeType == Node.ELEMENT_NODE: - if n.getAttribute('name') != "": - if n.getAttribute('show_docu') != "NO": - name = "<code>" + n.getAttribute('name') + "</code>" - desc = n.getAttribute('desc') - if (desc != ""): - name += " " + desc - values.append(name) - return values + values = [] + for n in node.childNodes: + if (n.nodeName == "value"): + if n.nodeType == Node.ELEMENT_NODE: + if n.getAttribute('name') != "": + if n.getAttribute('show_docu') != "NO": + name = "<code>" + n.getAttribute('name') + "</code>" + desc = n.getAttribute('desc') + if (desc != ""): + name += " " + desc + values.append(name) + return values def addValues(var, node): - for n in node.childNodes: - if (n.nodeName == "value"): - if n.nodeType == Node.ELEMENT_NODE: - name = n.getAttribute('name') - print(" %s->addValue(\"%s\");" % (var, name)) + for n in node.childNodes: + if (n.nodeName == "value"): + if n.nodeType == Node.ELEMENT_NODE: + name = n.getAttribute('name') + print(" %s->addValue(\"%s\");" % (var, name)) def parseHeader(node,objName): - doc = "" - for n in node.childNodes: - if n.nodeType == Node.ELEMENT_NODE: - if (n.nodeName == "docs"): - if (n.getAttribute('doxyfile') != "0"): - doc += parseDocs(n) - docC = transformDocs(doc) - print(" %s->setHeader(" % (objName)) - rng = len(docC) - for i in range(rng): - line = docC[i] - if i != rng - 1: # since we go from 0 to rng-1 - print(" \"%s\\n\"" % (line)) - else: - print(" \"%s\"" % (line)) - print(" );") + doc = "" + for n in node.childNodes: + if n.nodeType == Node.ELEMENT_NODE: + if (n.nodeName == "docs"): + if (n.getAttribute('doxyfile') != "0"): + doc += parseDocs(n) + docC = transformDocs(doc) + print(" %s->setHeader(" % (objName)) + rng = len(docC) + for i in range(rng): + line = docC[i] + if i != rng - 1: # since we go from 0 to rng-1 + print(" \"%s\\n\"" % (line)) + else: + print(" \"%s\"" % (line)) + print(" );") def prepCDocs(node): - type = node.getAttribute('type') - format = node.getAttribute('format') - defval = node.getAttribute('defval') - adefval = node.getAttribute('altdefval') - doc = ""; - if (type != 'obsolete'): - for n in node.childNodes: - if (n.nodeName == "docs"): - if (n.getAttribute('doxyfile') != "0"): - if n.nodeType == Node.ELEMENT_NODE: - doc += parseDocs(n) - if (type == 'enum'): - values = collectValues(node) - doc += "<br/>Possible values are: " - rng = len(values) - for i in range(rng): - val = values[i] - if i == rng - 2: - doc += "%s and " % (val) - elif i == rng - 1: - doc += "%s." % (val) - else: - doc += "%s, " % (val) - if (defval != ""): - doc += "<br/>The default value is: <code>%s</code>." % (defval) - elif (type == 'int'): - minval = node.getAttribute('minval') - maxval = node.getAttribute('maxval') - doc += "<br/>%s: %s, %s: %s, %s: %s." % (" Minimum value", minval, - "maximum value", maxval, - "default value", defval) - elif (type == 'bool'): - if (node.hasAttribute('altdefval')): - doc += "<br/>%s: %s." % ("The default value is", "system dependent") - else: - doc += "<br/>%s: %s." % ("The default value is", "YES" if (defval == "1") else "NO") - elif (type == 'list'): - if format == 'string': - values = collectValues(node) - rng = len(values) - for i in range(rng): - val = values[i] - if i == rng - 2: - doc += "%s and " % (val) - elif i == rng - 1: - doc += "%s." % (val) - else: - doc += "%s, " % (val) - elif (type == 'string'): - if format == 'dir': - if defval != '': - doc += "<br/>The default directory is: <code>%s</code>." % ( - defval) - elif format == 'file': - abspath = node.getAttribute('abspath') - if defval != '': - if abspath != '1': - doc += "<br/>The default file is: <code>%s</code>." % ( - defval) - else: - doc += "<br/>%s: %s%s%s." % ( - "The default file (with absolute path) is", - "<code>",defval,"</code>") - else: - if abspath == '1': - doc += "<br/>The file has to be specified with full path." - elif format =='image': - abspath = node.getAttribute('abspath') - if defval != '': - if abspath != '1': - doc += "<br/>The default image is: <code>%s</code>." % ( - defval) - else: - doc += "<br/>%s: %s%s%s." % ( - "The default image (with absolute path) is", - "<code>",defval,"</code>") - else: - if abspath == '1': - doc += "<br/>The image has to be specified with full path." - else: # format == 'string': - if defval != '': - doc += "<br/>The default value is: <code>%s</code>." % ( - defval) - # depends handling - if (node.hasAttribute('depends')): - depends = node.getAttribute('depends') - doc += "<br/>%s \\ref cfg_%s \"%s\" is set to \\c YES." % ( - "This tag requires that the tag", depends.lower(), depends.upper()) - - docC = transformDocs(doc) - return docC; + type = node.getAttribute('type') + format = node.getAttribute('format') + defval = node.getAttribute('defval') + adefval = node.getAttribute('altdefval') + doc = ""; + if (type != 'obsolete'): + for n in node.childNodes: + if (n.nodeName == "docs"): + if (n.getAttribute('doxyfile') != "0"): + if n.nodeType == Node.ELEMENT_NODE: + doc += parseDocs(n) + if (type == 'enum'): + values = collectValues(node) + doc += "<br/>Possible values are: " + rng = len(values) + for i in range(rng): + val = values[i] + if i == rng - 2: + doc += "%s and " % (val) + elif i == rng - 1: + doc += "%s." % (val) + else: + doc += "%s, " % (val) + if (defval != ""): + doc += "<br/>The default value is: <code>%s</code>." % (defval) + elif (type == 'int'): + minval = node.getAttribute('minval') + maxval = node.getAttribute('maxval') + doc += "<br/>%s: %s, %s: %s, %s: %s." % (" Minimum value", minval, + "maximum value", maxval, + "default value", defval) + elif (type == 'bool'): + if (node.hasAttribute('altdefval')): + doc += "<br/>%s: %s." % ("The default value is", "system dependent") + else: + doc += "<br/>%s: %s." % ("The default value is", "YES" if (defval == "1") else "NO") + elif (type == 'list'): + if format == 'string': + values = collectValues(node) + rng = len(values) + for i in range(rng): + val = values[i] + if i == rng - 2: + doc += "%s and " % (val) + elif i == rng - 1: + doc += "%s." % (val) + else: + doc += "%s, " % (val) + elif (type == 'string'): + if format == 'dir': + if defval != '': + doc += "<br/>The default directory is: <code>%s</code>." % ( + defval) + elif format == 'file': + abspath = node.getAttribute('abspath') + if defval != '': + if abspath != '1': + doc += "<br/>The default file is: <code>%s</code>." % ( + defval) + else: + doc += "<br/>%s: %s%s%s." % ( + "The default file (with absolute path) is", + "<code>",defval,"</code>") + else: + if abspath == '1': + doc += "<br/>The file has to be specified with full path." + elif format =='image': + abspath = node.getAttribute('abspath') + if defval != '': + if abspath != '1': + doc += "<br/>The default image is: <code>%s</code>." % ( + defval) + else: + doc += "<br/>%s: %s%s%s." % ( + "The default image (with absolute path) is", + "<code>",defval,"</code>") + else: + if abspath == '1': + doc += "<br/>The image has to be specified with full path." + else: # format == 'string': + if defval != '': + doc += "<br/>The default value is: <code>%s</code>." % ( + defval) + # depends handling + if (node.hasAttribute('depends')): + depends = node.getAttribute('depends') + doc += "<br/>%s \\ref cfg_%s \"%s\" is set to \\c YES." % ( + "This tag requires that the tag", depends.lower(), depends.upper()) + + docC = transformDocs(doc) + return docC; def parseOption(node): - # Handling part for Doxyfile - name = node.getAttribute('id') - type = node.getAttribute('type') - format = node.getAttribute('format') - defval = node.getAttribute('defval') - adefval = node.getAttribute('altdefval') - depends = node.getAttribute('depends') - setting = node.getAttribute('setting') - docC = prepCDocs(node); - if len(setting) > 0: - print("#if %s" % (setting)) - print(" //----") - if type == 'bool': - if len(adefval) > 0: - enabled = adefval - elif defval == '1': - enabled = "TRUE" - else: - enabled = "FALSE" - print(" cb = cfg->addBool(") - print(" \"%s\"," % (name)) - rng = len(docC) - for i in range(rng): - line = docC[i] - if i != rng - 1: # since we go from 0 to rng-1 - print(" \"%s\\n\"" % (line)) - else: - print(" \"%s\"," % (line)) - print(" %s" % (enabled)) - print(" );") - if depends != '': - print(" cb->addDependency(\"%s\");" % (depends)) - elif type == 'string': - print(" cs = cfg->addString(") - print(" \"%s\"," % (name)) - rng = len(docC) - for i in range(rng): - line = docC[i] - if i != rng - 1: # since we go from 0 to rng-1 - print(" \"%s\\n\"" % (line)) - else: - print(" \"%s\"" % (line)) - print(" );") - if defval != '': - print(" cs->setDefaultValue(\"%s\");" % (defval.replace('\\','\\\\'))) - if format == 'file': - print(" cs->setWidgetType(ConfigString::File);") - elif format == 'image': - print(" cs->setWidgetType(ConfigString::Image);") - elif format == 'dir': - print(" cs->setWidgetType(ConfigString::Dir);") - if depends != '': - print(" cs->addDependency(\"%s\");" % (depends)) - elif type == 'enum': - print(" ce = cfg->addEnum(") - print(" \"%s\"," % (name)) - rng = len(docC) - for i in range(rng): - line = docC[i] - if i != rng - 1: # since we go from 0 to rng-1 - print(" \"%s\\n\"" % (line)) - else: - print(" \"%s\"," % (line)) - print(" \"%s\"" % (defval)) - print(" );") - addValues("ce", node) - if depends != '': - print(" ce->addDependency(\"%s\");" % (depends)) - elif type == 'int': - minval = node.getAttribute('minval') - maxval = node.getAttribute('maxval') - print(" ci = cfg->addInt(") - print(" \"%s\"," % (name)) - rng = len(docC) - for i in range(rng): - line = docC[i] - if i != rng - 1: # since we go from 0 to rng-1 - print(" \"%s\\n\"" % (line)) - else: - print(" \"%s\"," % (line)) - print(" %s,%s,%s" % (minval, maxval, defval)) - print(" );") - if depends != '': - print(" ci->addDependency(\"%s\");" % (depends)) - elif type == 'list': - print(" cl = cfg->addList(") - print(" \"%s\"," % (name)) - rng = len(docC) - for i in range(rng): - line = docC[i] - if i != rng - 1: # since we go from 0 to rng-1 - print(" \"%s\\n\"" % (line)) - else: - print(" \"%s\"" % (line)) - print(" );") - addValues("cl", node) - if depends != '': - print(" cl->addDependency(\"%s\");" % (depends)) - if format == 'file': - print(" cl->setWidgetType(ConfigList::File);") - elif format == 'dir': - print(" cl->setWidgetType(ConfigList::Dir);") - elif format == 'filedir': - print(" cl->setWidgetType(ConfigList::FileAndDir);") - elif type == 'obsolete': - print(" cfg->addObsolete(\"%s\");" % (name)) - if len(setting) > 0: - print("#else") - print(" cfg->addDisabled(\"%s\");" % (name)) - print("#endif") + # Handling part for Doxyfile + name = node.getAttribute('id') + type = node.getAttribute('type') + format = node.getAttribute('format') + defval = node.getAttribute('defval') + adefval = node.getAttribute('altdefval') + depends = node.getAttribute('depends') + setting = node.getAttribute('setting') + orgtype = node.getAttribute('orgtype') + docC = prepCDocs(node); + if len(setting) > 0: + print("#if %s" % (setting)) + print(" //----") + if type == 'bool': + if len(adefval) > 0: + enabled = adefval + elif defval == '1': + enabled = "TRUE" + else: + enabled = "FALSE" + print(" cb = cfg->addBool(") + print(" \"%s\"," % (name)) + rng = len(docC) + for i in range(rng): + line = docC[i] + if i != rng - 1: # since we go from 0 to rng-1 + print(" \"%s\\n\"" % (line)) + else: + print(" \"%s\"," % (line)) + print(" %s" % (enabled)) + print(" );") + if depends != '': + print(" cb->addDependency(\"%s\");" % (depends)) + elif type == 'string': + print(" cs = cfg->addString(") + print(" \"%s\"," % (name)) + rng = len(docC) + for i in range(rng): + line = docC[i] + if i != rng - 1: # since we go from 0 to rng-1 + print(" \"%s\\n\"" % (line)) + else: + print(" \"%s\"" % (line)) + print(" );") + if defval != '': + print(" cs->setDefaultValue(\"%s\");" % (defval.replace('\\','\\\\'))) + if format == 'file': + print(" cs->setWidgetType(ConfigString::File);") + elif format == 'image': + print(" cs->setWidgetType(ConfigString::Image);") + elif format == 'dir': + print(" cs->setWidgetType(ConfigString::Dir);") + elif format == 'filedir': + print(" cs->setWidgetType(ConfigString::FileAndDir);") + if depends != '': + print(" cs->addDependency(\"%s\");" % (depends)) + elif type == 'enum': + print(" ce = cfg->addEnum(") + print(" \"%s\"," % (name)) + rng = len(docC) + for i in range(rng): + line = docC[i] + if i != rng - 1: # since we go from 0 to rng-1 + print(" \"%s\\n\"" % (line)) + else: + print(" \"%s\"," % (line)) + print(" \"%s\"" % (defval)) + print(" );") + addValues("ce", node) + if depends != '': + print(" ce->addDependency(\"%s\");" % (depends)) + elif type == 'int': + minval = node.getAttribute('minval') + maxval = node.getAttribute('maxval') + print(" ci = cfg->addInt(") + print(" \"%s\"," % (name)) + rng = len(docC) + for i in range(rng): + line = docC[i] + if i != rng - 1: # since we go from 0 to rng-1 + print(" \"%s\\n\"" % (line)) + else: + print(" \"%s\"," % (line)) + print(" %s,%s,%s" % (minval, maxval, defval)) + print(" );") + if depends != '': + print(" ci->addDependency(\"%s\");" % (depends)) + elif type == 'list': + print(" cl = cfg->addList(") + print(" \"%s\"," % (name)) + rng = len(docC) + for i in range(rng): + line = docC[i] + if i != rng - 1: # since we go from 0 to rng-1 + print(" \"%s\\n\"" % (line)) + else: + print(" \"%s\"" % (line)) + print(" );") + addValues("cl", node) + if depends != '': + print(" cl->addDependency(\"%s\");" % (depends)) + if format == 'file': + print(" cl->setWidgetType(ConfigList::File);") + elif format == 'dir': + print(" cl->setWidgetType(ConfigList::Dir);") + elif format == 'filedir': + print(" cl->setWidgetType(ConfigList::FileAndDir);") + elif type == 'obsolete': + print(" cfg->addObsolete(\"%s\",ConfigOption::O_%s);" % (name,orgtype.capitalize())) + if len(setting) > 0: + print("#else") + print(" cfg->addDisabled(\"%s\");" % (name)) + print("#endif") def parseGroups(node): - name = node.getAttribute('name') - doc = node.getAttribute('docs') - setting = node.getAttribute('setting') - if len(setting) > 0: - print("#if %s" % (setting)) - print("%s%s" % (" //-----------------------------------------", - "----------------------------------")) - print(" cfg->addInfo(\"%s\",\"%s\");" % (name, doc)) - print("%s%s" % (" //-----------------------------------------", - "----------------------------------")) - print("") - for n in node.childNodes: - if n.nodeType == Node.ELEMENT_NODE: - parseOption(n) - if len(setting) > 0: - print("#endif") - + name = node.getAttribute('name') + doc = node.getAttribute('docs') + setting = node.getAttribute('setting') + if len(setting) > 0: + print("#if %s" % (setting)) + print("%s%s" % (" //-----------------------------------------", + "----------------------------------")) + print(" cfg->addInfo(\"%s\",\"%s\");" % (name, doc)) + print("%s%s" % (" //-----------------------------------------", + "----------------------------------")) + if len(setting) > 0: + print("#endif") + print("") + for n in node.childNodes: + if n.nodeType == Node.ELEMENT_NODE: + parseOption(n) + +def parseGroupMapEnums(node): + def escape(value): + return re.sub(r'[^\w]','_',value) + for n in node.childNodes: + if n.nodeType == Node.ELEMENT_NODE: + type = n.getAttribute('type') + name = n.getAttribute('id') + defval = n.getAttribute('defval') + if type=='enum': + print("\nenum class %s_t" % (name)) + print("{") + for nv in n.childNodes: + if nv.nodeName == "value": + value = nv.getAttribute('name') + if value: + print(" %s," % (escape(value))) + print("};\n") + print("inline {0}_t {1}_str2enum(const QCString &s)".format(name,name)) + print("{") + print(" QCString lc = s.lower();") + print(" static const std::unordered_map<std::string,{0}_t> map =".format(name)) + print(" {") + for nv in n.childNodes: + if nv.nodeName == "value": + value = nv.getAttribute('name') + if value: + print(" {{ \"{0}\", {1}_t::{2} }},".format(value.lower(),name,escape(value))) + print(" };") + print(" auto it = map.find(lc.str());") + print(" return it!=map.end() ? it->second : {0}_t::{1};".format(name,escape(defval))) + print("}\n") + print("inline QCString {0}_enum2str({1}_t v)".format(name,name)) + print("{") + print(" switch(v)") + print(" {") + for nv in n.childNodes: + if nv.nodeName == "value": + value = nv.getAttribute('name') + if value: + print(" case {0}_t::{1}: return \"{2}\";".format(name,escape(value),value)) + print(" }") + print(" return \"{0}\";".format(defval)) + print("}") def parseGroupMapGetter(node): - map = { 'bool':'bool', 'string':'const QCString &', 'enum':'const QCString &', 'int':'int', 'list':'const StringVector &' } - for n in node.childNodes: - if n.nodeType == Node.ELEMENT_NODE: - setting = n.getAttribute('setting') - if len(setting) > 0: - print("#if %s" % (setting)) - type = n.getAttribute('type') - name = n.getAttribute('id') - if type in map: - print(" %-20s %-30s const { return m_%s; }" % (map[type],name+'()',name)) - if len(setting) > 0: - print("#endif") + map = { 'bool':'bool', 'string':'const QCString &', 'int':'int', 'list':'const StringVector &' } + for n in node.childNodes: + if n.nodeType == Node.ELEMENT_NODE: + setting = n.getAttribute('setting') + if len(setting) > 0: + print("#if %s" % (setting)) + type = n.getAttribute('type') + name = n.getAttribute('id') + if type=='enum': + print(" %-22s %-30s const { return %s(m_%s); }" % (name+'_t',name+'()',name+'_str2enum',name)) + print(" %-22s %-30s const { return m_%s; }" % ('const QCString &',name+'_str()',name)) + elif type in map: + print(" %-22s %-30s const { return m_%s; }" % (map[type],name+'()',name)) + if len(setting) > 0: + print("#endif") def parseGroupMapSetter(node): - map = { 'bool':'bool', 'string':'const QCString &', 'enum':'const QCString &', 'int':'int', 'list':'const StringVector &' } - for n in node.childNodes: - if n.nodeType == Node.ELEMENT_NODE: - setting = n.getAttribute('setting') - if len(setting) > 0: - print("#if %s" % (setting)) - type = n.getAttribute('type') - name = n.getAttribute('id') - if type in map: - print(" %-20s update_%-46s { m_%s = v; return m_%s; }" % (map[type],name+'('+map[type]+' v)',name,name)) - if len(setting) > 0: - print("#endif") + map = { 'bool':'bool', 'string':'const QCString &', 'int':'int', 'list':'const StringVector &' } + for n in node.childNodes: + if n.nodeType == Node.ELEMENT_NODE: + setting = n.getAttribute('setting') + if len(setting) > 0: + print("#if %s" % (setting)) + type = n.getAttribute('type') + name = n.getAttribute('id') + if type=='enum': + print(" %-22s update_%-46s { m_%s = %s(v); return v; }" % (name+'_t',name+'('+name+'_t '+' v)',name,name+'_enum2str')) + elif type in map: + print(" %-22s update_%-46s { m_%s = v; return m_%s; }" % (map[type],name+'('+map[type]+' v)',name,name)) + if len(setting) > 0: + print("#endif") def parseGroupMapVar(node): - map = { 'bool':'bool', 'string':'QCString', 'enum':'QCString', 'int':'int', 'list':'StringVector' } - for n in node.childNodes: - if n.nodeType == Node.ELEMENT_NODE: - setting = n.getAttribute('setting') - if len(setting) > 0: - print("#if %s" % (setting)) - type = n.getAttribute('type') - name = n.getAttribute('id') - if type in map: - print(" %-12s m_%s;" % (map[type],name)) - if len(setting) > 0: - print("#endif") + map = { 'bool':'bool', 'string':'QCString', 'enum':'QCString', 'int':'int', 'list':'StringVector' } + for n in node.childNodes: + if n.nodeType == Node.ELEMENT_NODE: + setting = n.getAttribute('setting') + if len(setting) > 0: + print("#if %s" % (setting)) + type = n.getAttribute('type') + name = n.getAttribute('id') + if type in map: + print(" %-12s m_%s;" % (map[type],name)) + if len(setting) > 0: + print("#endif") def parseGroupInit(node): - map = { 'bool':'Bool', 'string':'String', 'enum':'Enum', 'int':'Int', 'list':'List' } - for n in node.childNodes: - if n.nodeType == Node.ELEMENT_NODE: - setting = n.getAttribute('setting') - if len(setting) > 0: - print("#if %s" % (setting)) - type = n.getAttribute('type') - name = n.getAttribute('id') - if type in map: - print(" %-25s = ConfigImpl::instance()->get%s(__FILE__,__LINE__,\"%s\");" % ('m_'+name,map[type],name)) - if len(setting) > 0: - print("#endif") + map = { 'bool':'Bool', 'string':'String', 'enum':'Enum', 'int':'Int', 'list':'List' } + for n in node.childNodes: + if n.nodeType == Node.ELEMENT_NODE: + setting = n.getAttribute('setting') + if len(setting) > 0: + print("#if %s" % (setting)) + type = n.getAttribute('type') + name = n.getAttribute('id') + if type in map: + print(" %-25s = ConfigImpl::instance()->get%s(__FILE__,__LINE__,\"%s\");" % ('m_'+name,map[type],name)) + if len(setting) > 0: + print("#endif") def parseGroupMapInit(node): - map = { 'bool':'Bool', 'string':'String', 'enum':'String', 'int':'Int', 'list':'List' } - for n in node.childNodes: - if n.nodeType == Node.ELEMENT_NODE: - setting = n.getAttribute('setting') - if len(setting) > 0: - print("#if %s" % (setting)) - type = n.getAttribute('type') - name = n.getAttribute('id') - if type in map: - print(" { %-25s Info{ %-13s &ConfigValues::m_%s }}," % ('\"'+name+'\",','Info::'+map[type]+',',name)) - if len(setting) > 0: - print("#endif") + map = { 'bool':'Bool', 'string':'String', 'enum':'String', 'int':'Int', 'list':'List' } + for n in node.childNodes: + if n.nodeType == Node.ELEMENT_NODE: + setting = n.getAttribute('setting') + if len(setting) > 0: + print("#if %s" % (setting)) + type = n.getAttribute('type') + name = n.getAttribute('id') + if type in map: + print(" { %-25s Info{ %-13s &ConfigValues::m_%s }}," % ('\"'+name+'\",','Info::'+map[type]+',',name)) + if len(setting) > 0: + print("#endif") def parseGroupCDocs(node): - for n in node.childNodes: - if n.nodeType == Node.ELEMENT_NODE: - type = n.getAttribute('type') - name = n.getAttribute('id') - docC = prepCDocs(n); - if type != 'obsolete': - print(" doc->add(") - print(" \"%s\"," % (name)) - rng = len(docC) - for i in range(rng): - line = docC[i] - if i != rng - 1: # since we go from 0 to rng-1 - print(" \"%s\\n\"" % (line)) - else: - print(" \"%s\"" % (line)) - print(" );") + for n in node.childNodes: + if n.nodeType == Node.ELEMENT_NODE: + type = n.getAttribute('type') + name = n.getAttribute('id') + docC = prepCDocs(n); + if type != 'obsolete': + print(" doc->add(") + print(" \"%s\"," % (name)) + rng = len(docC) + for i in range(rng): + line = docC[i] + if i != rng - 1: # since we go from 0 to rng-1 + print(" \"%s\\n\"" % (line)) + else: + print(" \"%s\"" % (line)) + print(" );") def parseOptionDoc(node, first): - # Handling part for documentation - name = node.getAttribute('id') - type = node.getAttribute('type') - format = node.getAttribute('format') - defval = node.getAttribute('defval') - adefval = node.getAttribute('altdefval') - depends = node.getAttribute('depends') - setting = node.getAttribute('setting') - doc = "" - if (type != 'obsolete'): - for n in node.childNodes: - if (n.nodeName == "docs"): - if (n.getAttribute('documentation') != "0"): - if n.nodeType == Node.ELEMENT_NODE: - doc += parseDocs(n) - if (first): - print(" \\anchor cfg_%s" % (name.lower())) - print("<dl>") - print("") - print("<dt>\\c %s <dd>" % (name)) - else: - print(" \\anchor cfg_%s" % (name.lower())) - print("<dt>\\c %s <dd>" % (name)) - print(" \\addindex %s" % (name)) - print(doc) - if (type == 'enum'): - values = collectValues(node) - print("") - print("Possible values are: ") - rng = len(values) - for i in range(rng): - val = values[i] - if i == rng - 2: - print("%s and " % (val)) - elif i == rng - 1: - print("%s." % (val)) - else: - print("%s, " % (val)) - if (defval != ""): - print("") - print("") - print("The default value is: <code>%s</code>." % (defval)) - print("") - elif (type == 'int'): - minval = node.getAttribute('minval') - maxval = node.getAttribute('maxval') - print("") - print("") - print("%s: %s%s%s, %s: %s%s%s, %s: %s%s%s." % ( - " Minimum value", "<code>", minval, "</code>", - "maximum value", "<code>", maxval, "</code>", - "default value", "<code>", defval, "</code>")) - print("") - elif (type == 'bool'): - print("") - print("") - if (node.hasAttribute('altdefval')): - print("The default value is: system dependent.") - else: - print("The default value is: <code>%s</code>." % ( - "YES" if (defval == "1") else "NO")) - print("") - elif (type == 'list'): - if format == 'string': - values = collectValues(node) - rng = len(values) - for i in range(rng): - val = values[i] - if i == rng - 2: - print("%s and " % (val)) - elif i == rng - 1: - print("%s." % (val)) - else: - print("%s, " % (val)) - print("") - elif (type == 'string'): - if format == 'dir': - if defval != '': - print("") - print("The default directory is: <code>%s</code>." % ( - defval)) - elif format == 'file': - abspath = node.getAttribute('abspath') - if defval != '': - print("") - if abspath != '1': - print("The default file is: <code>%s</code>." % ( - defval)) - else: - print("%s: %s%s%s." % ( - "The default file (with absolute path) is", - "<code>",defval,"</code>")) - else: - if abspath == '1': - print("") - print("The file has to be specified with full path.") - elif format =='image': - abspath = node.getAttribute('abspath') - if defval != '': - print("") - if abspath != '1': - print("The default image is: <code>%s</code>." % ( - defval)) - else: - print("%s: %s%s%s." % ( - "The default image (with absolute path) is", - "<code>",defval,"</code>")) - else: - if abspath == '1': - print("") - print("The image has to be specified with full path.") - else: # format == 'string': - if defval != '': - print("") - print("The default value is: <code>%s</code>." % ( - defval.replace('\\','\\\\'))) - print("") - # depends handling - if (node.hasAttribute('depends')): - depends = node.getAttribute('depends') - print("") - print("%s \\ref cfg_%s \"%s\" is set to \\c YES." % ( - "This tag requires that the tag", depends.lower(), depends.upper())) - return False + # Handling part for documentation + name = node.getAttribute('id') + type = node.getAttribute('type') + format = node.getAttribute('format') + defval = node.getAttribute('defval') + adefval = node.getAttribute('altdefval') + depends = node.getAttribute('depends') + setting = node.getAttribute('setting') + doc = "" + if (type != 'obsolete'): + for n in node.childNodes: + if (n.nodeName == "docs"): + if (n.getAttribute('documentation') != "0"): + if n.nodeType == Node.ELEMENT_NODE: + doc += parseDocs(n) + if (first): + print(" \\anchor cfg_%s" % (name.lower())) + print("<dl>") + print("") + print("<dt>\\c %s <dd>" % (name)) + else: + print(" \\anchor cfg_%s" % (name.lower())) + print("<dt>\\c %s <dd>" % (name)) + print(" \\addindex %s" % (name)) + print(doc) + if (type == 'enum'): + values = collectValues(node) + print("") + print("Possible values are: ") + rng = len(values) + for i in range(rng): + val = values[i] + if i == rng - 2: + print("%s and " % (val)) + elif i == rng - 1: + print("%s." % (val)) + else: + print("%s, " % (val)) + if (defval != ""): + print("") + print("") + print("The default value is: <code>%s</code>." % (defval)) + print("") + elif (type == 'int'): + minval = node.getAttribute('minval') + maxval = node.getAttribute('maxval') + print("") + print("") + print("%s: %s%s%s, %s: %s%s%s, %s: %s%s%s." % ( + " Minimum value", "<code>", minval, "</code>", + "maximum value", "<code>", maxval, "</code>", + "default value", "<code>", defval, "</code>")) + print("") + elif (type == 'bool'): + print("") + print("") + if (node.hasAttribute('altdefval')): + print("The default value is: system dependent.") + else: + print("The default value is: <code>%s</code>." % ( + "YES" if (defval == "1") else "NO")) + print("") + elif (type == 'list'): + if format == 'string': + values = collectValues(node) + rng = len(values) + for i in range(rng): + val = values[i] + if i == rng - 2: + print("%s and " % (val)) + elif i == rng - 1: + print("%s." % (val)) + else: + print("%s, " % (val)) + print("") + elif (type == 'string'): + if format == 'dir': + if defval != '': + print("") + print("The default directory is: <code>%s</code>." % ( + defval)) + elif format == 'file': + abspath = node.getAttribute('abspath') + if defval != '': + print("") + if abspath != '1': + print("The default file is: <code>%s</code>." % ( + defval)) + else: + print("%s: %s%s%s." % ( + "The default file (with absolute path) is", + "<code>",defval,"</code>")) + else: + if abspath == '1': + print("") + print("The file has to be specified with full path.") + elif format =='image': + abspath = node.getAttribute('abspath') + if defval != '': + print("") + if abspath != '1': + print("The default image is: <code>%s</code>." % ( + defval)) + else: + print("%s: %s%s%s." % ( + "The default image (with absolute path) is", + "<code>",defval,"</code>")) + else: + if abspath == '1': + print("") + print("The image has to be specified with full path.") + else: # format == 'string': + if defval != '': + print("") + print("The default value is: <code>%s</code>." % ( + defval.replace('\\','\\\\'))) + print("") + # depends handling + if (node.hasAttribute('depends')): + depends = node.getAttribute('depends') + print("") + print("%s \\ref cfg_%s \"%s\" is set to \\c YES." % ( + "This tag requires that the tag", depends.lower(), depends.upper())) + return False def parseGroupsDoc(node): - name = node.getAttribute('name') - doc = node.getAttribute('docs') - print("\section config_%s %s" % (name.lower(), doc)) - # Start of list has been moved to the first option for better - # anchor placement - # print "<dl>" - # print "" - first = True - for n in node.childNodes: - if n.nodeType == Node.ELEMENT_NODE: - first = parseOptionDoc(n, first) - if (not first): - print("</dl>") + name = node.getAttribute('name') + doc = node.getAttribute('docs') + print("\section config_%s %s" % (name.lower(), doc)) + # Start of list has been moved to the first option for better + # anchor placement + # print "<dl>" + # print "" + first = True + for n in node.childNodes: + if n.nodeType == Node.ELEMENT_NODE: + first = parseOptionDoc(n, first) + if (not first): + print("</dl>") def parseGroupsList(node, commandsList): - list = () - for n in node.childNodes: - if n.nodeType == Node.ELEMENT_NODE: - type = n.getAttribute('type') - if type != 'obsolete': - commandsList = commandsList + (n.getAttribute('id'),) - return commandsList + list = () + for n in node.childNodes: + if n.nodeType == Node.ELEMENT_NODE: + type = n.getAttribute('type') + if type != 'obsolete': + commandsList = commandsList + (n.getAttribute('id'),) + return commandsList def parseDocs(node): - doc = "" - for n in node.childNodes: - if n.nodeType == Node.TEXT_NODE: - doc += n.nodeValue.strip() - if n.nodeType == Node.CDATA_SECTION_NODE: - doc += n.nodeValue.rstrip("\r\n ").lstrip("\r\n") - #doc += "<br>" - return doc + doc = "" + for n in node.childNodes: + if n.nodeType == Node.TEXT_NODE: + doc += n.nodeValue.strip() + if n.nodeType == Node.CDATA_SECTION_NODE: + doc += n.nodeValue.rstrip("\r\n ").lstrip("\r\n") + #doc += "<br>" + return doc def parseHeaderDoc(node): - doc = "" - for n in node.childNodes: - if n.nodeType == Node.ELEMENT_NODE: - if (n.nodeName == "docs"): - if (n.getAttribute('documentation') != "0"): - doc += parseDocs(n) - print(doc) + doc = "" + for n in node.childNodes: + if n.nodeType == Node.ELEMENT_NODE: + if (n.nodeName == "docs"): + if (n.getAttribute('documentation') != "0"): + doc += parseDocs(n) + print(doc) def parseFooterDoc(node): - doc = "" - for n in node.childNodes: - if n.nodeType == Node.ELEMENT_NODE: - if (n.nodeName == "docs"): - if (n.getAttribute('documentation') != "0"): - doc += parseDocs(n) - print(doc) + doc = "" + for n in node.childNodes: + if n.nodeType == Node.ELEMENT_NODE: + if (n.nodeName == "docs"): + if (n.getAttribute('documentation') != "0"): + doc += parseDocs(n) + print(doc) def main(): - if len(sys.argv)<3 or (not sys.argv[1] in ['-doc','-cpp','-wiz','-maph','-maps']): - sys.exit('Usage: %s -doc|-cpp|-wiz|-maph|-maps config.xml' % sys.argv[0]) - try: - doc = xml.dom.minidom.parse(sys.argv[2]) - except Exception as inst: - sys.stdout = sys.stderr - print("") - print(inst) - print("") - sys.exit(1) - elem = doc.documentElement - if (sys.argv[1] == "-doc"): - print("/* WARNING: This file is generated!") - print(" * Do not edit this file, but edit config.xml instead and run") - print(" * python configgen.py -doc config.xml to regenerate this file!") - print(" */") - # process header - for n in elem.childNodes: - if n.nodeType == Node.ELEMENT_NODE: - if (n.nodeName == "header"): - parseHeaderDoc(n) - # generate list with all commands - commandsList = () - for n in elem.childNodes: - if n.nodeType == Node.ELEMENT_NODE: - if (n.nodeName == "group"): - commandsList = parseGroupsList(n, commandsList) - print("\\secreflist") - for x in sorted(commandsList): - print("\\refitem cfg_%s %s" % (x.lower(), x)) - print("\\endsecreflist") - # process groups and options - for n in elem.childNodes: - if n.nodeType == Node.ELEMENT_NODE: - if (n.nodeName == "group"): - parseGroupsDoc(n) - # process footers - for n in elem.childNodes: - if n.nodeType == Node.ELEMENT_NODE: - if (n.nodeName == "footer"): - parseFooterDoc(n) - elif (sys.argv[1] == "-maph"): - print("/* WARNING: This file is generated!") - print(" * Do not edit this file, but edit config.xml instead and run") - print(" * python configgen.py -map config.xml to regenerate this file!") - print(" */") - print("#ifndef CONFIGVALUES_H") - print("#define CONFIGVALUES_H") - print("") - print("#include \"qcstring.h\"") - print("#include \"containers.h\"") - print("#include \"settings.h\"") - print("") - print("class ConfigValues") - print("{") - print(" public:") - print(" static ConfigValues &instance() { static ConfigValues theInstance; return theInstance; }") - for n in elem.childNodes: - if n.nodeType == Node.ELEMENT_NODE: - if n.nodeName == "group": - parseGroupMapGetter(n) - for n in elem.childNodes: - if n.nodeType == Node.ELEMENT_NODE: - if n.nodeName == "group": - parseGroupMapSetter(n) - print(" void init();") - print(" StringVector fields() const;") - print(" struct Info") - print(" {") - print(" enum Type { Bool, Int, String, List, Unknown };") - print(" Info(Type t,bool ConfigValues::*b) : type(t), value(b) {}") - print(" Info(Type t,int ConfigValues::*i) : type(t), value(i) {}") - print(" Info(Type t,QCString ConfigValues::*s) : type(t), value(s) {}") - print(" Info(Type t,StringVector ConfigValues::*l) : type(t), value(l) {}") - print(" Type type;") - print(" union Item") - print(" {") - print(" Item(bool ConfigValues::*v) : b(v) {}") - print(" Item(int ConfigValues::*v) : i(v) {}") - print(" Item(QCString ConfigValues::*v) : s(v) {}") - print(" Item(StringVector ConfigValues::*v) : l(v) {}") - print(" bool ConfigValues::*b;") - print(" int ConfigValues::*i;") - print(" QCString ConfigValues::*s;") - print(" StringVector ConfigValues::*l;") - print(" } value;") - print(" };") - print(" const Info *get(const QCString &tag) const;") - print(" private:") - for n in elem.childNodes: - if n.nodeType == Node.ELEMENT_NODE: - if (n.nodeName == "group"): - parseGroupMapVar(n) - print("};") - print("") - print("#endif") - elif (sys.argv[1] == "-maps"): - print("/* WARNING: This file is generated!") - print(" * Do not edit this file, but edit config.xml instead and run") - print(" * python configgen.py -maps config.xml to regenerate this file!") - print(" */") - print("#include \"configvalues.h\"") - print("#include \"configimpl.h\"") - print("#include <unordered_map>") - print("") - print("const ConfigValues::Info *ConfigValues::get(const QCString &tag) const"); - print("{"); - print(" static const std::unordered_map< std::string, Info > configMap ="); - print(" {"); - for n in elem.childNodes: - if n.nodeType == Node.ELEMENT_NODE: - if (n.nodeName == "group"): - parseGroupMapInit(n) - print(" };"); - print(" auto it = configMap.find(tag.str());"); - print(" return it!=configMap.end() ? &it->second : nullptr;"); - print("}"); - print("") - print("void ConfigValues::init()") - print("{") - print(" static bool first = TRUE;") - print(" if (!first) return;") - print(" first = FALSE;") - print("") - for n in elem.childNodes: - if n.nodeType == Node.ELEMENT_NODE: - if (n.nodeName == "group"): - parseGroupInit(n) - print("}") - print("") - print("StringVector ConfigValues::fields() const") - print("{") - print(" return {"); - first=True - for n in elem.childNodes: - if n.nodeType == Node.ELEMENT_NODE: - if (n.nodeName == "group"): - for c in n.childNodes: - if c.nodeType == Node.ELEMENT_NODE: - name = c.getAttribute('id') - type = c.getAttribute('type') - if type!='obsolete': - if not first: - print(",") - first=False - sys.stdout.write(' "'+name+'"') - print("") - print(" };") - print("}") - elif (sys.argv[1] == "-cpp"): - print("/* WARNING: This file is generated!") - print(" * Do not edit this file, but edit config.xml instead and run") - print(" * python configgen.py -cpp config.xml to regenerate this file!") - print(" */") - print("") - print("#include \"configoptions.h\"") - print("#include \"configimpl.h\"") - print("#include \"portable.h\"") - print("#include \"settings.h\"") - print("") - print("void addConfigOptions(ConfigImpl *cfg)") - print("{") - print(" ConfigString *cs;") - print(" ConfigEnum *ce;") - print(" ConfigList *cl;") - print(" ConfigInt *ci;") - print(" ConfigBool *cb;") - print("") - # process header - for n in elem.childNodes: - if n.nodeType == Node.ELEMENT_NODE: - if (n.nodeName == "header"): - parseHeader(n,'cfg') - for n in elem.childNodes: - if n.nodeType == Node.ELEMENT_NODE: - if (n.nodeName == "group"): - parseGroups(n) - print("}") - elif (sys.argv[1] == "-wiz"): - print("/* WARNING: This file is generated!") - print(" * Do not edit this file, but edit config.xml instead and run") - print(" * python configgen.py -wiz config.xml to regenerate this file!") - print(" */") - print("#include \"configdoc.h\"") - print("#include \"docintf.h\"") - print("") - print("void addConfigDocs(DocIntf *doc)") - print("{") - for n in elem.childNodes: - if n.nodeType == Node.ELEMENT_NODE: - if (n.nodeName == "header"): - parseHeader(n,'doc') - for n in elem.childNodes: - if n.nodeType == Node.ELEMENT_NODE: - if (n.nodeName == "group"): - parseGroupCDocs(n) - print("}") + if len(sys.argv)<3 or (not sys.argv[1] in ['-doc','-cpp','-wiz','-maph','-maps']): + sys.exit('Usage: %s -doc|-cpp|-wiz|-maph|-maps config.xml' % sys.argv[0]) + try: + doc = xml.dom.minidom.parse(sys.argv[2]) + except Exception as inst: + sys.stdout = sys.stderr + print("") + print(inst) + print("") + sys.exit(1) + elem = doc.documentElement + if (sys.argv[1] == "-doc"): + print("/* WARNING: This file is generated!") + print(" * Do not edit this file, but edit config.xml instead and run") + print(" * python configgen.py -doc config.xml to regenerate this file!") + print(" */") + # process header + for n in elem.childNodes: + if n.nodeType == Node.ELEMENT_NODE: + if (n.nodeName == "header"): + parseHeaderDoc(n) + # generate list with all commands + commandsList = () + for n in elem.childNodes: + if n.nodeType == Node.ELEMENT_NODE: + if (n.nodeName == "group"): + commandsList = parseGroupsList(n, commandsList) + print("\\secreflist") + for x in sorted(commandsList): + print("\\refitem cfg_%s %s" % (x.lower(), x)) + print("\\endsecreflist") + # process groups and options + for n in elem.childNodes: + if n.nodeType == Node.ELEMENT_NODE: + if (n.nodeName == "group"): + parseGroupsDoc(n) + # process footers + for n in elem.childNodes: + if n.nodeType == Node.ELEMENT_NODE: + if (n.nodeName == "footer"): + parseFooterDoc(n) + elif (sys.argv[1] == "-maph"): + print("/* WARNING: This file is generated!") + print(" * Do not edit this file, but edit config.xml instead and run") + print(" * python configgen.py -map config.xml to regenerate this file!") + print(" */") + print("#ifndef CONFIGVALUES_H") + print("#define CONFIGVALUES_H") + print("") + print("#include <string>") + print("#include <unordered_map>") + print("#include \"qcstring.h\"") + print("#include \"containers.h\"") + print("#include \"settings.h\"") + for n in elem.childNodes: + if n.nodeType == Node.ELEMENT_NODE: + if n.nodeName == "group": + parseGroupMapEnums(n) + print("") + print("class ConfigValues") + print("{") + print(" public:") + print(" static ConfigValues &instance() { static ConfigValues theInstance; return theInstance; }") + for n in elem.childNodes: + if n.nodeType == Node.ELEMENT_NODE: + if n.nodeName == "group": + parseGroupMapGetter(n) + for n in elem.childNodes: + if n.nodeType == Node.ELEMENT_NODE: + if n.nodeName == "group": + parseGroupMapSetter(n) + print(" void init();") + print(" StringVector fields() const;") + print(" struct Info") + print(" {") + print(" enum Type { Bool, Int, String, List, Unknown };") + print(" Info(Type t,bool ConfigValues::*b) : type(t), value(b) {}") + print(" Info(Type t,int ConfigValues::*i) : type(t), value(i) {}") + print(" Info(Type t,QCString ConfigValues::*s) : type(t), value(s) {}") + print(" Info(Type t,StringVector ConfigValues::*l) : type(t), value(l) {}") + print(" Type type;") + print(" union Item") + print(" {") + print(" Item(bool ConfigValues::*v) : b(v) {}") + print(" Item(int ConfigValues::*v) : i(v) {}") + print(" Item(QCString ConfigValues::*v) : s(v) {}") + print(" Item(StringVector ConfigValues::*v) : l(v) {}") + print(" bool ConfigValues::*b;") + print(" int ConfigValues::*i;") + print(" QCString ConfigValues::*s;") + print(" StringVector ConfigValues::*l;") + print(" } value;") + print(" };") + print(" const Info *get(const QCString &tag) const;") + print(" private:") + for n in elem.childNodes: + if n.nodeType == Node.ELEMENT_NODE: + if (n.nodeName == "group"): + parseGroupMapVar(n) + print("};") + print("") + print("#endif") + elif (sys.argv[1] == "-maps"): + print("/* WARNING: This file is generated!") + print(" * Do not edit this file, but edit config.xml instead and run") + print(" * python configgen.py -maps config.xml to regenerate this file!") + print(" */") + print("#include \"configvalues.h\"") + print("#include \"configimpl.h\"") + print("#include <unordered_map>") + print("") + print("const ConfigValues::Info *ConfigValues::get(const QCString &tag) const"); + print("{"); + print(" static const std::unordered_map< std::string, Info > configMap ="); + print(" {"); + for n in elem.childNodes: + if n.nodeType == Node.ELEMENT_NODE: + if (n.nodeName == "group"): + parseGroupMapInit(n) + print(" };"); + print(" auto it = configMap.find(tag.str());"); + print(" return it!=configMap.end() ? &it->second : nullptr;"); + print("}"); + print("") + print("void ConfigValues::init()") + print("{") + print(" static bool first = TRUE;") + print(" if (!first) return;") + print(" first = FALSE;") + print("") + for n in elem.childNodes: + if n.nodeType == Node.ELEMENT_NODE: + if (n.nodeName == "group"): + parseGroupInit(n) + print("}") + print("") + print("StringVector ConfigValues::fields() const") + print("{") + print(" return {"); + first=True + for n in elem.childNodes: + if n.nodeType == Node.ELEMENT_NODE: + if (n.nodeName == "group"): + for c in n.childNodes: + if c.nodeType == Node.ELEMENT_NODE: + name = c.getAttribute('id') + type = c.getAttribute('type') + if type!='obsolete': + if not first: + print(",") + first=False + sys.stdout.write(' "'+name+'"') + print("") + print(" };") + print("}") + elif (sys.argv[1] == "-cpp"): + print("/* WARNING: This file is generated!") + print(" * Do not edit this file, but edit config.xml instead and run") + print(" * python configgen.py -cpp config.xml to regenerate this file!") + print(" */") + print("") + print("#include \"configoptions.h\"") + print("#include \"configimpl.h\"") + print("#include \"portable.h\"") + print("#include \"settings.h\"") + print("") + print("void addConfigOptions(ConfigImpl *cfg)") + print("{") + print(" ConfigString *cs;") + print(" ConfigEnum *ce;") + print(" ConfigList *cl;") + print(" ConfigInt *ci;") + print(" ConfigBool *cb;") + print("") + # process header + for n in elem.childNodes: + if n.nodeType == Node.ELEMENT_NODE: + if (n.nodeName == "header"): + parseHeader(n,'cfg') + for n in elem.childNodes: + if n.nodeType == Node.ELEMENT_NODE: + if (n.nodeName == "group"): + parseGroups(n) + print("}") + elif (sys.argv[1] == "-wiz"): + print("/* WARNING: This file is generated!") + print(" * Do not edit this file, but edit config.xml instead and run") + print(" * python configgen.py -wiz config.xml to regenerate this file!") + print(" */") + print("#include \"configdoc.h\"") + print("#include \"docintf.h\"") + print("") + print("void addConfigDocs(DocIntf *doc)") + print("{") + for n in elem.childNodes: + if n.nodeType == Node.ELEMENT_NODE: + if (n.nodeName == "header"): + parseHeader(n,'doc') + for n in elem.childNodes: + if n.nodeType == Node.ELEMENT_NODE: + if (n.nodeName == "group"): + parseGroupCDocs(n) + print("}") if __name__ == '__main__': - main() + main() diff --git a/src/configimpl.h b/src/configimpl.h index e828491..4906391 100644 --- a/src/configimpl.h +++ b/src/configimpl.h @@ -134,6 +134,7 @@ class ConfigList : public ConfigOption WidgetType widgetType() const { return m_widgetType; } StringVector *valueRef() { return &m_value; } StringVector getDefault() { return m_defaultValue; } + void emptyValueToDefault() { if (m_value.empty() && !m_defaultValue.empty()) m_value=m_defaultValue; }; void writeTemplate(TextStream &t,bool sl,bool); void compareDoxyfile(TextStream &t); void writeXMLDoxyfile(TextStream &t); @@ -181,7 +182,7 @@ class ConfigEnum : public ConfigOption class ConfigString : public ConfigOption { public: - enum WidgetType { String, File, Dir, Image }; + enum WidgetType { String, File, Dir, Image, FileAndDir }; ConfigString(const char *name,const char *doc) : ConfigOption(O_String) { @@ -278,12 +279,22 @@ class ConfigBool : public ConfigOption class ConfigObsolete : public ConfigOption { public: - ConfigObsolete(const char *name) : ConfigOption(O_Obsolete) + ConfigObsolete(const char *name,OptionType orgType) : ConfigOption(O_Obsolete), m_orgType(orgType) { m_name = name; } void writeTemplate(TextStream &,bool,bool); void compareDoxyfile(TextStream &) {} void writeXMLDoxyfile(TextStream &) {} void substEnvVars() {} + OptionType orgType() const { return m_orgType; } + StringVector *valueListRef() { return &m_listvalue; } + QCString *valueStringRef() { return &m_valueString; } + void markAsPresent() { m_present = true; } + bool isPresent() const { return m_present; } + private: + OptionType m_orgType; + StringVector m_listvalue; + QCString m_valueString; + bool m_present = false; }; /** Section marker for compile time optional options @@ -468,9 +479,9 @@ class ConfigImpl return result; } /*! Adds an option that has become obsolete. */ - ConfigOption *addObsolete(const char *name) + ConfigOption *addObsolete(const char *name,ConfigOption::OptionType orgType) { - ConfigObsolete *result = new ConfigObsolete(name); + ConfigObsolete *result = new ConfigObsolete(name,orgType); m_obsolete.push_back(std::unique_ptr<ConfigOption>(result)); m_dict.insert(std::make_pair(name,result)); return result; diff --git a/src/configimpl.l b/src/configimpl.l index a72057e..f3ce092 100644 --- a/src/configimpl.l +++ b/src/configimpl.l @@ -210,23 +210,40 @@ void ConfigInt::convertStrToVal() } } -void ConfigBool::convertStrToVal() +static bool convertStringToBool(const QCString &str,bool &isValid) { - QCString val = m_valueString.stripWhiteSpace().lower(); + isValid=false; + QCString val = str.stripWhiteSpace().lower(); if (!val.isEmpty()) { if (val=="yes" || val=="true" || val=="1" || val=="all") { - m_value=TRUE; + isValid=true; + return true; } else if (val=="no" || val=="false" || val=="0" || val=="none") { - m_value=FALSE; + isValid=true; + return false; + } + } + return false; +} + +void ConfigBool::convertStrToVal() +{ + if (!m_valueString.stripWhiteSpace().isEmpty()) + { + bool isValid=false; + bool b = convertStringToBool(m_valueString,isValid); + if (isValid) + { + m_value=b; } else { config_warn("argument '%s' for option %s is not a valid boolean value\n" - "Using the default: %s!\n",qPrint(m_valueString),qPrint(m_name),m_value?"YES":"NO"); + "Using the default: %s!\n",qPrint(m_valueString),qPrint(m_name),m_value?"YES":"NO"); } } } @@ -598,6 +615,11 @@ static ConfigImpl *g_config; #undef YY_INPUT #define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size); +// otherwise the filename would be the name of the converted file (*.cpp instead of *.l) +static inline const char *getLexerFILE() {return __FILE__;} +#define LEX_NO_REENTRANT +#include "doxygen_lex.h" + static yy_size_t yyread(char *buf,yy_size_t max_size) { // no file included @@ -1004,7 +1026,20 @@ static void readIncludeFile(const QCString &incName) " To avoid this warning please remove this line from your configuration " "file or upgrade it using \"doxygen -u\"\n", qPrint(g_cmd),g_yyLineNr,qPrint(g_yyFileName)); } - BEGIN(SkipInvalid); + ((ConfigObsolete*)option)->markAsPresent(); + if (((ConfigObsolete*)option)->orgType()==ConfigOption::O_List) + { + g_list = ((ConfigObsolete*)option)->valueListRef(); + g_list->clear(); + g_listStr=""; + BEGIN(GetStrList); + } + else + { + g_string = ((ConfigObsolete*)option)->valueStringRef(); + g_string->resize(0); + BEGIN(GetString); + } break; case ConfigOption::O_Disabled: if (g_configUpdate) @@ -1058,7 +1093,16 @@ static void readIncludeFile(const QCString &incName) config_warn("Tag '%s' at line %d of file %s has become obsolete.\n" "To avoid this warning please update your configuration " "file using \"doxygen -u\"\n", qPrint(g_cmd),g_yyLineNr,qPrint(g_yyFileName)); - BEGIN(SkipInvalid); + if (((ConfigObsolete*)option)->orgType()==ConfigOption::O_List) + { + g_list = ((ConfigObsolete*)option)->valueListRef(); + g_listStr=""; + BEGIN(GetStrList); + } + else + { + BEGIN(SkipInvalid); + } break; case ConfigOption::O_Disabled: config_warn("Tag '%s' at line %d of file %s belongs to an option that was not enabled at compile time.\n" @@ -1512,7 +1556,36 @@ static void checkList(const StringVector &list,const char *name, bool equalRequi } } -void Config::checkAndCorrect(bool quiet) +static void adjustBoolSetting(const char *depOption, const char *optionName,bool expectedValue) +{ + // lookup option by name + const ConfigValues::Info *option = ConfigValues::instance().get(optionName); + if (option && option->type==ConfigValues::Info::Bool) // safety check + { + if (ConfigValues::instance().*(option->value.b)!=expectedValue) // current value differs from expectation + { + err("When enabling %s the %s option should be disabled. I'll adjust it for you.\n",depOption,optionName); + ConfigValues::instance().*(option->value.b)=expectedValue; // adjust option + } + } +} + +static void adjustStringSetting(const char *depOption, const char *optionName,const QCString &expectedValue) +{ + // lookup option by name + const ConfigValues::Info *option = ConfigValues::instance().get(optionName); + if (option && option->type==ConfigValues::Info::String) // safety check + { + if (ConfigValues::instance().*(option->value.s)!=expectedValue) // current value differs from expectation + { + err("When enabling %s the %s option should have value '%s'. I'll adjust it for you.\n",depOption,optionName,qPrint(expectedValue)); + ConfigValues::instance().*(option->value.s)=expectedValue; // adjust option + } + } +} + + +void Config::checkAndCorrect(bool quiet, const bool check) { ConfigValues::instance().init(); @@ -1520,69 +1593,34 @@ void Config::checkAndCorrect(bool quiet) //------------------------ // check WARN_FORMAT QCString warnFormat = Config_getString(WARN_FORMAT); - if (warnFormat.stripWhiteSpace().isEmpty()) + if (warnFormat.find("$file")==-1) { - Config_updateString(WARN_FORMAT,"$file:$line $text"); + warn_uncond("warning format does not contain a $file tag!\n"); } - else + if (warnFormat.find("$line")==-1) { - if (warnFormat.find("$file")==-1) - { - warn_uncond("warning format does not contain a $file tag!\n"); - } - if (warnFormat.find("$line")==-1) - { - warn_uncond("warning format does not contain a $line tag!\n"); - } - if (warnFormat.find("$text")==-1) - { - warn_uncond("warning format foes not contain a $text tag!\n"); - } + warn_uncond("warning format does not contain a $line tag!\n"); } - - //------------------------ - // set default man page extension if non is given by the user - QCString manExtension = Config_getString(MAN_EXTENSION); - if (manExtension.isEmpty()) + if (warnFormat.find("$text")==-1) { - Config_updateString(MAN_EXTENSION,".3"); + warn_uncond("warning format foes not contain a $text tag!\n"); } //------------------------ // check and correct PAPER_TYPE - QCString paperType = Config_getEnum(PAPER_TYPE); + QCString paperType = Config_getEnumAsString(PAPER_TYPE); paperType=paperType.lower().stripWhiteSpace(); if (paperType.isEmpty() || paperType=="a4wide") { - paperType = "a4"; - } - if (paperType!="a4" && paperType!="letter" && - paperType!="legal" && paperType!="executive") - { - err("Unknown page type specified\n"); - paperType="a4"; - } - Config_updateEnum(PAPER_TYPE,paperType); - - //------------------------ - // check & correct OUTPUT_LANGUAGE - QCString outputLanguage=Config_getEnum(OUTPUT_LANGUAGE); - outputLanguage=outputLanguage.stripWhiteSpace(); - if (outputLanguage.isEmpty()) - { - outputLanguage = "English"; + // use a4 + Config_updateEnum(PAPER_TYPE,PAPER_TYPE_t::a4); } - Config_updateEnum(OUTPUT_LANGUAGE,outputLanguage); - - //------------------------ - // check & correct HTML_FILE_EXTENSION - QCString htmlFileExtension=Config_getString(HTML_FILE_EXTENSION); - htmlFileExtension=htmlFileExtension.stripWhiteSpace(); - if (htmlFileExtension.isEmpty()) + else if (paperType!="a4" && paperType!="letter" && + paperType!="legal" && paperType!="executive") { - htmlFileExtension = ".html"; + err("Unknown page type '%s' specified\n",qPrint(paperType)); + Config_updateEnum(PAPER_TYPE,PAPER_TYPE_t::a4); } - Config_updateString(HTML_FILE_EXTENSION,htmlFileExtension); //------------------------ // check & correct STRIP_FROM_PATH @@ -1607,7 +1645,7 @@ void Config::checkAndCorrect(bool quiet) //------------------------ // Test to see if HTML header is valid QCString headerFile = Config_getString(HTML_HEADER); - if (!headerFile.isEmpty()) + if (check && !headerFile.isEmpty()) { FileInfo fi(headerFile.str()); if (!fi.exists()) @@ -1620,7 +1658,7 @@ void Config::checkAndCorrect(bool quiet) //------------------------ // Test to see if HTML footer is valid QCString footerFile = Config_getString(HTML_FOOTER); - if (!footerFile.isEmpty()) + if (check && !footerFile.isEmpty()) { FileInfo fi(footerFile.str()); if (!fi.exists()) @@ -1634,25 +1672,25 @@ void Config::checkAndCorrect(bool quiet) // Test to see if MathJax code file is valid if (Config_getBool(USE_MATHJAX)) { - QCString mathJaxFormat = Config_getEnum(MATHJAX_FORMAT); - QCString mathjaxVersion = Config_getEnum(MATHJAX_VERSION); - if (!mathJaxFormat.isEmpty()) + auto mathJaxFormat = Config_getEnum(MATHJAX_FORMAT); + auto mathjaxVersion = Config_getEnum(MATHJAX_VERSION); + if (mathjaxVersion == MATHJAX_VERSION_t::MathJax_2) { - if (mathjaxVersion == "MathJax_2") + if (mathJaxFormat==MATHJAX_FORMAT_t::chtml) { - if (mathJaxFormat=="chtml") Config_updateEnum(MATHJAX_FORMAT,"HTML-CSS"); + Config_updateEnum(MATHJAX_FORMAT,MATHJAX_FORMAT_t::HTML_CSS); } - else + } + else + { + if (mathJaxFormat==MATHJAX_FORMAT_t::HTML_CSS || mathJaxFormat==MATHJAX_FORMAT_t::NativeMML) { - if (mathJaxFormat=="HTML-CSS" || mathJaxFormat=="NativeMML") - { - Config_updateEnum(MATHJAX_FORMAT,"chtml"); - } + Config_updateEnum(MATHJAX_FORMAT,MATHJAX_FORMAT_t::chtml); } } QCString mathJaxCodefile = Config_getString(MATHJAX_CODEFILE); - if (!mathJaxCodefile.isEmpty()) + if (check && !mathJaxCodefile.isEmpty()) { FileInfo fi(mathJaxCodefile.str()); if (!fi.exists()) @@ -1664,13 +1702,11 @@ void Config::checkAndCorrect(bool quiet) QCString path = Config_getString(MATHJAX_RELPATH); if (path.isEmpty()) { - if (mathjaxVersion == "MathJax_2") - { - path = "https://cdn.jsdelivr.net/npm/mathjax@2"; - } - else + path = "https://cdn.jsdelivr.net/npm/mathjax@"; + switch (mathjaxVersion) { - path = "https://cdn.jsdelivr.net/npm/mathjax@3"; + case MATHJAX_VERSION_t::MathJax_2: path += "2"; break; + case MATHJAX_VERSION_t::MathJax_3: path += "3"; break; } } @@ -1684,7 +1720,7 @@ void Config::checkAndCorrect(bool quiet) //------------------------ // Test to see if LaTeX header is valid QCString latexHeaderFile = Config_getString(LATEX_HEADER); - if (!latexHeaderFile.isEmpty()) + if (check && !latexHeaderFile.isEmpty()) { FileInfo fi(latexHeaderFile.str()); if (!fi.exists()) @@ -1697,7 +1733,7 @@ void Config::checkAndCorrect(bool quiet) //------------------------ // Test to see if LaTeX footer is valid QCString latexFooterFile = Config_getString(LATEX_FOOTER); - if (!latexFooterFile.isEmpty()) + if (check && !latexFooterFile.isEmpty()) { FileInfo fi(latexFooterFile.str()); if (!fi.exists()) @@ -1774,74 +1810,32 @@ void Config::checkAndCorrect(bool quiet) } //------------------------ - // check if GENERATE_TREEVIEW and GENERATE_HTMLHELP are both enabled - if (Config_getBool(GENERATE_TREEVIEW) && Config_getBool(GENERATE_HTMLHELP)) - { - err("When enabling GENERATE_HTMLHELP the tree view (GENERATE_TREEVIEW) should be disabled. I'll do it for you.\n"); - Config_updateBool(GENERATE_TREEVIEW,FALSE); - } - - //------------------------ - // check if GENERATE_HTMLHELP and HTML_FILE_EXTENSION is not .html - if (Config_getString(HTML_FILE_EXTENSION)!=".html" && Config_getBool(GENERATE_HTMLHELP)) - { - err("When enabling GENERATE_HTMLHELP the HTML_FILE_EXTENSION should be \".html\". I'll do it for you.\n"); - Config_updateString(HTML_FILE_EXTENSION,".html"); - } - //------------------------ - // check if SEARCHENGINE and GENERATE_HTMLHELP are both enabled - if (Config_getBool(SEARCHENGINE) && Config_getBool(GENERATE_HTMLHELP)) + // check for settings that are inconsistent with having GENERATE_HTMLHELP enabled + if (Config_getBool(GENERATE_HTMLHELP)) { - err("When enabling GENERATE_HTMLHELP the search engine (SEARCHENGINE) should be disabled. I'll do it for you.\n"); - Config_updateBool(SEARCHENGINE,FALSE); + const char *depOption = "GENERATE_HTMLHELP"; + adjustBoolSetting( depOption, "GENERATE_TREEVIEW", false ); + adjustBoolSetting( depOption, "SEARCHENGINE", false ); + adjustStringSetting(depOption, "HTML_FILE_EXTENSION", ".html"); } - //------------------------ - // check if SEPARATE_MEMBER_PAGES and INLINE_GROUPED_CLASSES are both enabled - if (Config_getBool(SEPARATE_MEMBER_PAGES) && Config_getBool(INLINE_GROUPED_CLASSES)) + // check for settings that are inconsistent with having INLINE_GROUPED_CLASSES enabled + if (Config_getBool(INLINE_GROUPED_CLASSES)) { - err("When enabling INLINE_GROUPED_CLASSES the SEPARATE_MEMBER_PAGES option should be disabled. I'll do it for you.\n"); - Config_updateBool(SEPARATE_MEMBER_PAGES,FALSE); + const char *depOption = "INLINE_GROUPED_CLASSES"; + adjustBoolSetting(depOption, "SEPARATE_MEMBER_PAGES", false); } //------------------------ - // check and correct DOT_IMAGE_FORMAT - QCString dotImageFormat=Config_getEnum(DOT_IMAGE_FORMAT); - dotImageFormat=dotImageFormat.stripWhiteSpace(); - if (dotImageFormat.isEmpty()) - { - dotImageFormat = "png"; - } - Config_updateEnum(DOT_IMAGE_FORMAT,dotImageFormat); - - //------------------------ // correct DOT_FONTNAME if needed QCString dotFontName=Config_getString(DOT_FONTNAME); if (dotFontName=="FreeSans" || dotFontName=="FreeSans.ttf") { warn_uncond("doxygen no longer ships with the FreeSans font.\n" - "You may want to clear or change DOT_FONTNAME.\n" - "Otherwise you run the risk that the wrong font is being used for dot generated graphs.\n"); - } - else if (dotFontName.isEmpty()) - { - dotFontName = "Helvetica"; + " You may want to clear or change DOT_FONTNAME.\n" + " Otherwise you run the risk that the wrong font is being used for dot generated graphs.\n"); } - Config_updateString(DOT_FONTNAME,dotFontName); - - //------------------------ - // clip dotFontSize against the maximum bounds - int dotFontSize = Config_getInt(DOT_FONTSIZE); - if (dotFontSize<4) - { - dotFontSize=4; - } - else if (dotFontSize>24) - { - dotFontSize=24; - } - Config_updateInt(DOT_FONTSIZE,dotFontSize); //------------------------ // clip number of threads @@ -1884,12 +1878,8 @@ void Config::checkAndCorrect(bool quiet) uint i=0,l=dotPath.length(); for (i=0;i<l;i++) if (dotPath.at(i)=='/') dotPath.at(i)='\\'; #endif + Config_updateString(DOT_PATH,dotPath); } - else // make sure the string is empty but not null! - { - dotPath=""; - } - Config_updateString(DOT_PATH,dotPath); //------------------------ // check plantuml path @@ -1903,27 +1893,27 @@ void Config::checkAndCorrect(bool quiet) FileInfo jar(plantumlJar.str()); if (jar.exists() && jar.isFile()) { - plantumlJarPath = jar.dirPath(TRUE)+Portable::pathSeparator(); + plantumlJarPath = plantumlJar; } else { - err("Jar file plantuml.jar not found at location " + err("Jar file 'plantuml.jar' not found at location " "specified via PLANTUML_JAR_PATH: '%s'\n",qPrint(plantumlJarPath)); plantumlJarPath=""; } } - else if (pu.exists() && pu.isFile() && plantumlJarPath.right(4)==".jar") // PLANTUML_JAR_PATH is file + else if (pu.exists() && pu.isFile()) // PLANTUML_JAR_PATH is file { - plantumlJarPath = pu.dirPath(TRUE)+Portable::pathSeparator(); + // Nothing to be done } else { - err("path specified via PLANTUML_JAR_PATH does not exist or not a directory: %s\n", + err("PLANTUML_JAR_PATH is not a directory with a 'plantuml.jar' file or is not an existing file: %s\n", qPrint(plantumlJarPath)); plantumlJarPath=""; } + Config_updateString(PLANTUML_JAR_PATH,plantumlJarPath); } - Config_updateString(PLANTUML_JAR_PATH,plantumlJarPath); //------------------------ // check dia path @@ -1945,12 +1935,8 @@ void Config::checkAndCorrect(bool quiet) for (i=0;i<l;i++) if (diaPath.at(i)=='/') diaPath.at(i)='\\'; #endif } + Config_updateString(DIA_PATH,diaPath); } - else // make sure the string is empty but not null! - { - diaPath=""; - } - Config_updateString(DIA_PATH,diaPath); //------------------------ // check INPUT @@ -1974,28 +1960,6 @@ void Config::checkAndCorrect(bool quiet) Config_updateList(INPUT,inputSources); //------------------------ - // add default file patterns if needed - StringVector filePatternList = Config_getList(FILE_PATTERNS); - if (filePatternList.empty()) - { - ConfigOption * opt = ConfigImpl::instance()->get("FILE_PATTERNS"); - if (opt->kind()==ConfigOption::O_List) - { - filePatternList = ((ConfigList*)opt)->getDefault(); - } - } - Config_updateList(FILE_PATTERNS,filePatternList); - - //------------------------ - // add default pattern if needed - StringVector examplePatternList = Config_getList(EXAMPLE_PATTERNS); - if (examplePatternList.empty()) - { - examplePatternList.push_back("*"); - Config_updateList(EXAMPLE_PATTERNS,examplePatternList); - } - - //------------------------ // if no output format is enabled, warn the user if (!Config_getBool(GENERATE_HTML) && !Config_getBool(GENERATE_LATEX) && @@ -2053,90 +2017,16 @@ void Config::checkAndCorrect(bool quiet) } //------------------------ - int hue = Config_getInt(HTML_COLORSTYLE_HUE); - if (hue<0) + // check for settings that are inconsistent with having OPTIMIZED_OUTPUT_VHDL enabled + if (Config_getBool(OPTIMIZE_OUTPUT_VHDL)) { - hue=0; - } - else if (hue>=360) - { - hue=hue%360; - } - Config_updateInt(HTML_COLORSTYLE_HUE,hue); - - //------------------------ - int sat = Config_getInt(HTML_COLORSTYLE_SAT); - if (sat<0) - { - sat=0; - } - else if (sat>255) - { - sat=255; - } - Config_updateInt(HTML_COLORSTYLE_SAT,sat); - - - //------------------------ - int gamma = Config_getInt(HTML_COLORSTYLE_GAMMA); - if (gamma<40) - { - gamma=40; - } - else if (gamma>240) - { - gamma=240; - } - Config_updateInt(HTML_COLORSTYLE_GAMMA,gamma); - - //------------------------ - // add default words if needed - const StringVector &annotationFromBrief = Config_getList(ABBREVIATE_BRIEF); - if (annotationFromBrief.empty()) - { - Config_updateList(ABBREVIATE_BRIEF, - { "The $name class", "The $name widget", - "The $name file", "is", "provides", "specifies", - "contains", "represents", "a", "an", "the" - }); - } - - //------------------------ - // some default settings for vhdl - if (Config_getBool(OPTIMIZE_OUTPUT_VHDL) && - (Config_getBool(INLINE_INHERITED_MEMB) || - Config_getBool(INHERIT_DOCS) || - !Config_getBool(HIDE_SCOPE_NAMES) || - !Config_getBool(EXTRACT_PRIVATE) || - !Config_getBool(EXTRACT_PACKAGE) - ) - ) - { - bool b1 = Config_getBool(INLINE_INHERITED_MEMB); - bool b2 = Config_getBool(INHERIT_DOCS); - bool b3 = Config_getBool(HIDE_SCOPE_NAMES); - bool b4 = Config_getBool(EXTRACT_PRIVATE); - bool b5 = Config_getBool(SKIP_FUNCTION_MACROS); - bool b6 = Config_getBool(EXTRACT_PACKAGE); - const char *s1,*s2,*s3,*s4,*s5,*s6; - if (b1) s1=" INLINE_INHERITED_MEMB = NO (was YES)\n"; else s1=""; - if (b2) s2=" INHERIT_DOCS = NO (was YES)\n"; else s2=""; - if (!b3) s3=" HIDE_SCOPE_NAMES = YES (was NO)\n"; else s3=""; - if (!b4) s4=" EXTRACT_PRIVATE = YES (was NO)\n"; else s4=""; - if (b5) s5=" ENABLE_PREPROCESSING = NO (was YES)\n"; else s5=""; - if (!b6) s6=" EXTRACT_PACKAGE = YES (was NO)\n"; else s6=""; - - - warn_uncond("enabling OPTIMIZE_OUTPUT_VHDL assumes the following settings:\n" - "%s%s%s%s%s%s",s1,s2,s3,s4,s5,s6 - ); - - Config_updateBool(INLINE_INHERITED_MEMB, FALSE); - Config_updateBool(INHERIT_DOCS, FALSE); - Config_updateBool(HIDE_SCOPE_NAMES, TRUE); - Config_updateBool(EXTRACT_PRIVATE, TRUE); - Config_updateBool(ENABLE_PREPROCESSING, FALSE); - Config_updateBool(EXTRACT_PACKAGE, TRUE); + const char *depOption = "OPTIMIZE_OUTPUT_VHDL"; + adjustBoolSetting(depOption,"INLINE_INHERITED_MEMB",false); + adjustBoolSetting(depOption,"INHERIT_DOCS", false); + adjustBoolSetting(depOption,"HIDE_SCOPE_NAMES", true ); + adjustBoolSetting(depOption,"EXTRACT_PRIVATE", true ); + adjustBoolSetting(depOption,"ENABLE_PREPROCESSING", false); + adjustBoolSetting(depOption,"EXTRACT_PACKAGE", true ); } if (!checkFileName(Config_getString(GENERATE_TAGFILE),"GENERATE_TAGFILE")) @@ -2166,7 +2056,36 @@ void Config::checkAndCorrect(bool quiet) } #endif +} +void Config::updateObsolete() +{ + //------------------------ + // check for presence of obsolete CLASS_DIAGRAM option and correct CLASS_GRAPH if needed + ConfigOption *classDiagramsOpt = ConfigImpl::instance()->get("CLASS_DIAGRAMS"); + ConfigOption *haveDotOpt = ConfigImpl::instance()->get("HAVE_DOT"); + ConfigOption *classGraphOpt = ConfigImpl::instance()->get("CLASS_GRAPH"); + if (classDiagramsOpt && classDiagramsOpt->kind()==ConfigOption::O_Obsolete && + haveDotOpt && classGraphOpt) + { + ConfigObsolete *classDiagramsOpt_ = dynamic_cast<ConfigObsolete*>(classDiagramsOpt); + ConfigBool *haveDotOpt_ = dynamic_cast<ConfigBool*>(haveDotOpt); + ConfigEnum *classGraphOpt_ = dynamic_cast<ConfigEnum*>(classGraphOpt); + if (classDiagramsOpt_->isPresent() && classDiagramsOpt_->orgType()==ConfigOption::O_Bool) + { + QCString classDiagramValue = *classDiagramsOpt_->valueStringRef(); + QCString haveDotValue = *haveDotOpt_->valueStringRef(); + QCString &classGraphValue = *classGraphOpt_->valueRef(); + bool isValid1=true, isValid2=true; + bool bClassDiagrams = convertStringToBool(classDiagramValue,isValid1); + bool bHaveDot = haveDotValue.isEmpty() ? false : convertStringToBool(haveDotValue, isValid2); + if (isValid1 && isValid2 && !bClassDiagrams && !bHaveDot && classGraphValue.lower()=="yes") + { + warn_uncond("Changing CLASS_GRAPH option to TEXT because obsolete option CLASS_DIAGRAM was found and set to NO.\n"); + classGraphValue="TEXT"; + } + } + } } void Config::writeTemplate(TextStream &t,bool shortList,bool update) @@ -2194,6 +2113,7 @@ bool Config::parse(const QCString &fileName,bool update) // when updating etc. the output is in this format as well and not in the read format ConfigString *option = (ConfigString*)g_config->get("DOXYFILE_ENCODING"); option->init(); + return parseRes; } diff --git a/src/constexp.l b/src/constexp.l index 889626c..7382528 100644 --- a/src/constexp.l +++ b/src/constexp.l @@ -22,12 +22,13 @@ %option extra-type="struct constexpYY_state *" %top{ #include <stdint.h> +// forward declare yyscan_t to improve typesafety +#include "constexp_p.h" } %{ #include "constexp.h" -#include "constexp_p.h" #include "cppvalue.h" #include "ce_parse.hpp" // generated header file #include "message.h" @@ -46,6 +47,11 @@ static yy_size_t yyread(char *buf,yy_size_t max_size,yyscan_t yyscanner); #undef YY_INPUT #define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size,yyscanner); +// otherwise the filename would be the name of the converted file (*.cpp instead of *.l) +static inline const char *getLexerFILE() {return __FILE__;} +#define LEX_NO_INPUT_FILENAME +#include "doxygen_lex.h" + %} CONSTSUFFIX ([uU][lL]?[lL]?)|([lL][lL]?[uU]?) diff --git a/src/constexp_p.h b/src/constexp_p.h index 4ce94bc..94da6ce 100644 --- a/src/constexp_p.h +++ b/src/constexp_p.h @@ -23,8 +23,10 @@ #include "cppvalue.h" #define YYSTYPE CPPValue +#define YY_TYPEDEF_YY_SCANNER_T -typedef void* yyscan_t; +struct yyguts_t; +typedef yyguts_t* yyscan_t; struct constexpYY_state { std::string strToken; diff --git a/src/context.cpp b/src/context.cpp index a84f77a..6274ce6 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -78,37 +78,77 @@ struct ContextGlobals ContextOutputFormat outputFormat; } g_globals; -/** @brief Reference counting smart pointer */ -template<class T> class SharedPtr + +/** Wrapper for data that needs to be cached. + * The cached data can be accessed via the get() method from multiple threads. + * The first thread that calls get() will trigger creation of the data item via + * the creator method, blocking other threads until the item is available in the cache. + * @tparam T the type of the data item in the cache. + * @tparam TOwner the class containing the cached item. + * @tparam creator the method of TOwner to call in order to create the data item to be cached. + */ +template<typename T, typename TOwner, T(TOwner::*creator)() const> +class CachedItem { + public: + /** Returns a reference to the cached data. + * Conceptually this is a const method, i.e. it will always return the same data + * The first time it is called, the owner will be asked to create the data. + */ + T &get(const TOwner *owner) const + { + // create a lamda function to create the cached data + auto creatorFunc = [this,owner]() { m_item = (owner->*creator)(); }; + // use std::call_once to let one thread invoke the creator func + std::call_once(m_cache_flag, creatorFunc); + // return the cached results + return m_item; + } private: - T *m_ptr; - SharedPtr(const SharedPtr &); - SharedPtr &operator=(const SharedPtr &p); - void operator==(const SharedPtr &) const; - void operator!=(const SharedPtr &) const; + mutable std::once_flag m_cache_flag; // flag to keep track if the item is already cached + mutable T m_item; // the cached data item +}; + +//------------------------------------------------------------------------ +/** Class representing a mapping of properties and the corresponding getter function. + * The map should be initialized at initialization time. + */ +template<class T> +class PropertyMap +{ public: - typedef T Type; - explicit SharedPtr(T *p=0) : m_ptr(p) { if (m_ptr) m_ptr->addRef(); } - ~SharedPtr() { if (m_ptr) m_ptr->release(); }; - T &operator*() const { return *m_ptr; } - T *operator->() const { return m_ptr; } - T *get() const { return m_ptr; } - operator bool() const { return m_ptr!=0; } - void reset(T *p=0) - { - if (p) p->addRef(); - if (m_ptr) m_ptr->release(); - m_ptr = p; + using Map = std::map< std::string, TemplateVariant(T::*)() const >; + + PropertyMap(std::initializer_list<typename Map::value_type> init) + : m_map(init) {} + + TemplateVariant get(const T *obj,const QCString &n) const + { + auto it = m_map.find(n.str()); + return it!=m_map.end() ? (obj->*(it->second))() : TemplateVariant(); } + StringVector fields() const + { + StringVector result; + result.reserve(m_map.size()); + for (const auto &imap : m_map) result.push_back(imap.first); + return result; + } + + Map &map() { return m_map; } + + private: + const Map m_map; }; +//------------------------------------------------------------------------ + /** @brief Template List iterator support */ class GenericConstIterator : public TemplateListIntf::ConstIterator { public: - GenericConstIterator(const std::vector<TemplateVariant> &list) : m_list(list) {} + GenericConstIterator(const TemplateVariantList &list) : m_list(list) {} virtual ~GenericConstIterator() {} void toFirst() { @@ -140,7 +180,7 @@ class GenericConstIterator : public TemplateListIntf::ConstIterator } } private: - const std::vector<TemplateVariant> &m_list; + const TemplateVariantList &m_list; int m_index=0; }; @@ -150,12 +190,12 @@ class GenericConstIterator : public TemplateListIntf::ConstIterator class GenericNodeListContext : public TemplateListIntf { public: - GenericNodeListContext() : m_refCount(0) + GenericNodeListContext() { } - static GenericNodeListContext *alloc() + static TemplateListIntfPtr alloc() { - return new GenericNodeListContext; + return std::static_pointer_cast<TemplateListIntf>(std::make_shared<GenericNodeListContext>()); } // TemplateListIntf methods @@ -172,9 +212,9 @@ class GenericNodeListContext : public TemplateListIntf } return result; } - TemplateListIntf::ConstIterator *createIterator() const + TemplateListIntf::ConstIteratorPtr createIterator() const { - return new GenericConstIterator(m_children); + return std::make_unique<GenericConstIterator>(m_children); } void append(const TemplateVariant &ctn) @@ -185,253 +225,156 @@ class GenericNodeListContext : public TemplateListIntf { return m_children.empty(); } - int addRef() - { - return ++m_refCount; - } - int release() - { - int count = --m_refCount; - if (count<=0) - { - delete this; - } - return count; - } private: std::vector< TemplateVariant > m_children; - int m_refCount; }; //------------------------------------------------------------------------ -/** @brief Helper class to map a property name to a handler member function */ -template<typename T> -class PropertyMapper +//%% struct Config : configuration options +//%% { +class ConfigContext::Private { - private: - struct PropertyFuncIntf - { - virtual ~PropertyFuncIntf() {} - virtual TemplateVariant operator()(const T *obj) const = 0; - }; - struct PropertyFunc : public PropertyFuncIntf - { - typedef TemplateVariant (T::*Handler)() const; - PropertyFunc(Handler h) : handler(h) {} - TemplateVariant operator()(const T *obj) const - { - return (obj->*handler)(); - } - Handler handler; - }; - public: - /** Add a property to the map - * @param[in] name The name of the property to add. - * @param[in] handle The method to call when the property is accessed. - */ - void addProperty(const char *name,typename PropertyFunc::Handler handle) - { - auto it = m_map.find(name); - if (it!=m_map.end()) - { - err("adding property '%s' more than once\n",name); - } - else - { - m_map.insert(std::make_pair(name,std::make_unique<PropertyFunc>(handle))); - } - } - - /** Gets the value of a property. - * @param[in] obj The object handling access to the property. - * @param[in] name The name of the property. - * @returns A variant representing the properties value or an - * invalid variant if it was not found. - */ - TemplateVariant get(const T *obj,const QCString &name) const + // TemplateStructIntf methods + StringVector fields() const { - //printf("PropertyMapper::get(%s)\n",name); - TemplateVariant result; - auto it = m_map.find(name.str()); - return it!=m_map.end() ? (*it->second)(obj) : TemplateVariant(); + return m_fields.get(this); } - - StringVector fields() const + TemplateVariant get(const QCString &name) const { - StringVector result; - for (const auto &kv : m_map) - { - result.push_back(kv.first); - } - std::sort(result.begin(),result.end()); - return result; + auto &data = m_configData.get(this); + auto it = data.find(name.str()); + return (it!=data.end()) ? it->second : TemplateVariant(); } - private: - std::unordered_map<std::string,std::unique_ptr<PropertyFuncIntf>> m_map; -}; - + using ConfigData = std::map<std::string,TemplateVariant>; -//------------------------------------------------------------------------ - -//%% struct Config : configuration options -//%% { -class ConfigContext::Private -{ - public: - Private() { } - virtual ~Private() { } - TemplateVariant fetchList(const QCString &name,const StringVector &list) + ConfigData createConfigData() const { - auto it = m_cachedLists.find(name.str()); - if (it==m_cachedLists.end()) + std::map<std::string,TemplateVariant> map; + for (auto name : ConfigValues::instance().fields()) { - TemplateList *tlist = TemplateList::alloc(); - m_cachedLists.insert(std::make_pair(name.str(),TemplateVariant(tlist))); - for (const auto &s : list) + const ConfigValues::Info *option = ConfigValues::instance().get(QCString(name)); + if (option) { - tlist->append(s.c_str()); + switch (option->type) + { + case ConfigValues::Info::Bool: + { + bool b = ConfigValues::instance().*(option->value.b); + map.insert(std::make_pair(name,TemplateVariant(b))); + } + break; + case ConfigValues::Info::Int: + { + int i = ConfigValues::instance().*(option->value.i); + map.insert(std::make_pair(name,TemplateVariant(i))); + } + break; + case ConfigValues::Info::String: + { + QCString s = ConfigValues::instance().*(option->value.s); + map.insert(std::make_pair(name,TemplateVariant(s))); + } + break; + case ConfigValues::Info::List: + { + auto fetchList = [](const StringVector &list) -> TemplateVariant + { + TemplateVariantList elements; + elements.reserve(list.size()); + for (const auto &s : list) + { + elements.push_back(TemplateVariant(s)); + } + return TemplateImmutableList::alloc(elements); + }; + const StringVector &l = ConfigValues::instance().*(option->value.l); + map.insert(std::make_pair(name,fetchList(l))); + } + break; + default: + break; + } } - return tlist; - } - else - { - return it->second; } + return map; } - private: - std::unordered_map<std::string,TemplateVariant> m_cachedLists; + + StringVector createFields() const + { + return ConfigValues::instance().fields(); + } + + CachedItem<StringVector, Private, &Private::createFields > m_fields; + CachedItem<ConfigData, Private, &Private::createConfigData> m_configData; }; //%% } -ConfigContext::ConfigContext() : RefCountedContext("ConfigContext") +ConfigContext::ConfigContext() : p(std::make_unique<Private>()) { - p = new Private; } ConfigContext::~ConfigContext() { - delete p; } TemplateVariant ConfigContext::get(const QCString &name) const { - TemplateVariant result; - if (!name.isEmpty()) - { - const ConfigValues::Info *option = ConfigValues::instance().get(name); - if (option) - { - switch (option->type) - { - case ConfigValues::Info::Bool: - { - bool b = ConfigValues::instance().*(option->value.b); - return TemplateVariant(b); - } - case ConfigValues::Info::Int: - { - int i = ConfigValues::instance().*(option->value.i); - return TemplateVariant(i); - } - case ConfigValues::Info::String: - { - QCString s = ConfigValues::instance().*(option->value.s); - return TemplateVariant(s); - } - case ConfigValues::Info::List: - { - const StringVector &l = ConfigValues::instance().*(option->value.l); - return p->fetchList(name,l); - } - default: - break; - } - } - } - return result; + return p->get(name); } StringVector ConfigContext::fields() const { - return ConfigValues::instance().fields(); + return p->fields(); } //------------------------------------------------------------------------ -//%% struct Doxygen: global information -//%% { class DoxygenContext::Private { public: - TemplateVariant version() const - { - return getDoxygenVersion(); - } - TemplateVariant date() const - { - return dateToString(TRUE); - } - TemplateVariant mathJaxCodeFile() const - { - return m_cache.mathJaxCodeFile; - } - TemplateVariant mathJaxMacros() const - { - return m_cache.mathJaxMacros; - } - Private() - { - static bool init=FALSE; - if (!init) - { - //%% string version - s_inst.addProperty("version", &Private::version); - //%% string date - s_inst.addProperty("date", &Private::date); - //%% string maxJaxCodeFile - s_inst.addProperty("mathJaxCodeFile", &Private::mathJaxCodeFile); - //%% string maxJaxMacros - s_inst.addProperty("mathJaxMacros", &Private::mathJaxMacros); - init=TRUE; - } - } - TemplateVariant get(const QCString &n) const - { - return s_inst.get(this,n); - } - StringVector fields() const - { - return s_inst.fields(); - } + // TemplateStructIntf methods + TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); } + StringVector fields() const { return s_inst.fields(); } + private: - struct Cachable - { - Cachable() { - mathJaxCodeFile=fileToString(Config_getString(MATHJAX_CODEFILE)); - mathJaxMacros=HtmlGenerator::getMathJaxMacros(); - } - QCString mathJaxCodeFile; - QCString mathJaxMacros; - }; - mutable Cachable m_cache; - static PropertyMapper<DoxygenContext::Private> s_inst; + // Property getters + TemplateVariant version() const { return getDoxygenVersion(); } + TemplateVariant date() const { return dateToString(TRUE); } + TemplateVariant mathJaxCodeFile() const { return m_mathJaxCodeFile.get(this); } + TemplateVariant mathJaxMacros() const { return m_mathJaxMacros.get(this); } + + private: + QCString createMathJaxCodeFile() const { return fileToString(Config_getString(MATHJAX_CODEFILE)); } + QCString createMathJaxMacros() const { return HtmlGenerator::getMathJaxMacros(); } + CachedItem<QCString, Private, &Private::createMathJaxCodeFile> m_mathJaxCodeFile; + CachedItem<QCString, Private, &Private::createMathJaxMacros> m_mathJaxMacros; + static const PropertyMap<DoxygenContext::Private> s_inst; }; -//%% } -PropertyMapper<DoxygenContext::Private> DoxygenContext::Private::s_inst; -// (PropertyMapper<DoxygenContext::Private>::instance()); +//%% struct Doxygen: global information +//%% { +const PropertyMap<DoxygenContext::Private> DoxygenContext::Private::s_inst { +{ + //%% string version + { "version", &Private::version }, + //%% string date + { "date", &Private::date }, + //%% string maxJaxCodeFile + { "mathJaxCodeFile", &Private::mathJaxCodeFile }, + //%% string maxJaxMacros + { "mathJaxMacros", &Private::mathJaxMacros } +} }; +//%% } -DoxygenContext::DoxygenContext() : RefCountedContext("DoxygenContext") +DoxygenContext::DoxygenContext() : p(std::make_unique<Private>()) { - p = new Private; } DoxygenContext::~DoxygenContext() { - delete p; } TemplateVariant DoxygenContext::get(const QCString &n) const @@ -446,13 +389,25 @@ StringVector DoxygenContext::fields() const //------------------------------------------------------------------------ -//%% struct Translator: translation methods -//%% { class TranslateContext::Private { public: - TemplateVariant handleGeneratedAt(const std::vector<TemplateVariant> &args) const + Private() + { + m_javaOpt = Config_getBool(OPTIMIZE_OUTPUT_JAVA); + m_fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN); + m_vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL); + m_sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE); + } + + // TemplateStructIntf methods + TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); } + StringVector fields() const { return s_inst.fields(); } + private: + + // Handlers for properties with parameters + TemplateVariant handleGeneratedAt(const TemplateVariantList &args) const { if (args.size()==2) { @@ -464,7 +419,7 @@ class TranslateContext::Private } return TemplateVariant(); } - TemplateVariant handleInheritanceDiagramFor(const std::vector<TemplateVariant> &args) const + TemplateVariant handleInheritanceDiagramFor(const TemplateVariantList &args) const { if (args.size()==1) { @@ -476,7 +431,7 @@ class TranslateContext::Private } return TemplateVariant(); } - TemplateVariant handleCollaborationDiagramFor(const std::vector<TemplateVariant> &args) const + TemplateVariant handleCollaborationDiagramFor(const TemplateVariantList &args) const { if (args.size()==1) { @@ -488,7 +443,7 @@ class TranslateContext::Private } return TemplateVariant(); } - TemplateVariant handleDirDependencyGraphFor(const std::vector<TemplateVariant> &args) const + TemplateVariant handleDirDependencyGraphFor(const TemplateVariantList &args) const { if (args.size()==1) { @@ -500,7 +455,7 @@ class TranslateContext::Private } return TemplateVariant(); } - TemplateVariant handleInheritsList(const std::vector<TemplateVariant> &args) const + TemplateVariant handleInheritsList(const TemplateVariantList &args) const { if (args.size()==1) { @@ -512,7 +467,7 @@ class TranslateContext::Private } return TemplateVariant(); } - TemplateVariant handleInheritedByList(const std::vector<TemplateVariant> &args) const + TemplateVariant handleInheritedByList(const TemplateVariantList &args) const { if (args.size()==1) { @@ -524,7 +479,7 @@ class TranslateContext::Private } return TemplateVariant(); } - TemplateVariant handleWriteList(const std::vector<TemplateVariant> &args) const + TemplateVariant handleWriteList(const TemplateVariantList &args) const { if (args.size()==1) { @@ -536,7 +491,7 @@ class TranslateContext::Private } return TemplateVariant(); } - TemplateVariant handleImplementedBy(const std::vector<TemplateVariant> &args) const + TemplateVariant handleImplementedBy(const TemplateVariantList &args) const { if (args.size()==1) { @@ -548,7 +503,7 @@ class TranslateContext::Private } return TemplateVariant(); } - TemplateVariant handleReimplementedBy(const std::vector<TemplateVariant> &args) const + TemplateVariant handleReimplementedBy(const TemplateVariantList &args) const { if (args.size()==1) { @@ -560,7 +515,7 @@ class TranslateContext::Private } return TemplateVariant(); } - TemplateVariant handleSourceRefs(const std::vector<TemplateVariant> &args) const + TemplateVariant handleSourceRefs(const TemplateVariantList &args) const { if (args.size()==1) { @@ -572,7 +527,7 @@ class TranslateContext::Private } return TemplateVariant(); } - TemplateVariant handleSourceRefBys(const std::vector<TemplateVariant> &args) const + TemplateVariant handleSourceRefBys(const TemplateVariantList &args) const { if (args.size()==1) { @@ -584,7 +539,7 @@ class TranslateContext::Private } return TemplateVariant(); } - TemplateVariant handleIncludeDependencyGraph(const std::vector<TemplateVariant> &args) const + TemplateVariant handleIncludeDependencyGraph(const TemplateVariantList &args) const { if (args.size()==1) { @@ -597,27 +552,26 @@ class TranslateContext::Private return TemplateVariant(); } - - + // Property getters TemplateVariant generatedBy() const { return theTranslator->trGeneratedBy(); } TemplateVariant generatedAt() const { - return TemplateVariant::FunctionDelegate::fromMethod<Private,&Private::handleGeneratedAt>(this); + return TemplateVariant(std::bind(&Private::handleGeneratedAt,this,std::placeholders::_1)); } TemplateVariant inheritanceDiagramFor() const { - return TemplateVariant::FunctionDelegate::fromMethod<Private,&Private::handleInheritanceDiagramFor>(this); + return TemplateVariant(std::bind(&Private::handleInheritanceDiagramFor,this,std::placeholders::_1)); } TemplateVariant collaborationDiagramFor() const { - return TemplateVariant::FunctionDelegate::fromMethod<Private,&Private::handleCollaborationDiagramFor>(this); + return TemplateVariant(std::bind(&Private::handleCollaborationDiagramFor,this,std::placeholders::_1)); } TemplateVariant dirDependencyGraphFor() const { - return TemplateVariant::FunctionDelegate::fromMethod<Private,&Private::handleDirDependencyGraphFor>(this); + return TemplateVariant(std::bind(&Private::handleDirDependencyGraphFor,this,std::placeholders::_1)); } TemplateVariant search() const { @@ -799,11 +753,11 @@ class TranslateContext::Private } TemplateVariant inheritsList() const { - return TemplateVariant::FunctionDelegate::fromMethod<Private,&Private::handleInheritsList>(this); + return TemplateVariant(std::bind(&Private::handleInheritsList,this,std::placeholders::_1)); } TemplateVariant inheritedByList() const { - return TemplateVariant::FunctionDelegate::fromMethod<Private,&Private::handleInheritedByList>(this); + return TemplateVariant(std::bind(&Private::handleInheritedByList,this,std::placeholders::_1)); } TemplateVariant definedAtLineInSourceFile() const { @@ -815,7 +769,7 @@ class TranslateContext::Private } TemplateVariant exampleList() const { - return TemplateVariant::FunctionDelegate::fromMethod<Private,&Private::handleWriteList>(this); + return TemplateVariant(std::bind(&Private::handleWriteList,this,std::placeholders::_1)); } TemplateVariant listOfAllMembers() const { @@ -855,19 +809,19 @@ class TranslateContext::Private } TemplateVariant implementedBy() const { - return TemplateVariant::FunctionDelegate::fromMethod<Private,&Private::handleImplementedBy>(this); + return TemplateVariant(std::bind(&Private::handleImplementedBy,this,std::placeholders::_1)); } TemplateVariant reimplementedBy() const { - return TemplateVariant::FunctionDelegate::fromMethod<Private,&Private::handleReimplementedBy>(this); + return TemplateVariant(std::bind(&Private::handleReimplementedBy,this,std::placeholders::_1)); } TemplateVariant sourceRefs() const { - return TemplateVariant::FunctionDelegate::fromMethod<Private,&Private::handleSourceRefs>(this); + return TemplateVariant(std::bind(&Private::handleSourceRefs,this,std::placeholders::_1)); } TemplateVariant sourceRefBys() const { - return TemplateVariant::FunctionDelegate::fromMethod<Private,&Private::handleSourceRefBys>(this); + return TemplateVariant(std::bind(&Private::handleSourceRefBys,this,std::placeholders::_1)); } TemplateVariant callGraph() const { @@ -895,7 +849,7 @@ class TranslateContext::Private } TemplateVariant includeDependencyGraph() const { - return TemplateVariant::FunctionDelegate::fromMethod<Private,&Private::handleIncludeDependencyGraph>(this); + return TemplateVariant(std::bind(&Private::handleIncludeDependencyGraph,this,std::placeholders::_1)); } TemplateVariant includedByDependencyGraph() const { @@ -1050,245 +1004,226 @@ class TranslateContext::Private { return theTranslator->trCode(); } - Private() - { - static bool init=FALSE; - if (!init) - { - //%% string generatedBy - s_inst.addProperty("generatedBy", &Private::generatedBy); - //%% string generatedAt - s_inst.addProperty("generatedAt", &Private::generatedAt); - //%% string search - s_inst.addProperty("search", &Private::search); - //%% string mainPage - s_inst.addProperty("mainPage", &Private::mainPage); - //%% string classes - s_inst.addProperty("classes", &Private::classes); - //%% string classList - s_inst.addProperty("classList", &Private::classList); - //%% string classListDescription - s_inst.addProperty("classListDescription", &Private::classListDescription); - //%% string classIndex - s_inst.addProperty("classIndex", &Private::classIndex); - //%% string concepts - s_inst.addProperty("concepts", &Private::concepts); - //%% string conceptDefintion - s_inst.addProperty("conceptDefinition", &Private::conceptDefinition); - //%% string namespaceIndex - s_inst.addProperty("namespaceIndex", &Private::namespaceIndex); - //%% string classHierarchy - s_inst.addProperty("classHierarchy", &Private::classHierarchy); - //%% string classMembers - s_inst.addProperty("classMembers", &Private::classMembers); - //%% string classMembersDescription - s_inst.addProperty("classMembersDescription",&Private::classMembersDescription); - //%% string modules - s_inst.addProperty("modules", &Private::modules); - //%% string moduleIndex - s_inst.addProperty("moduleIndex", &Private::moduleIndex); - //%% string namespaces - s_inst.addProperty("namespaces", &Private::namespaces); - //%% string fileIndex - s_inst.addProperty("fileIndex", &Private::fileIndex); - //%% string files - s_inst.addProperty("files", &Private::files); - //%% string pages - s_inst.addProperty("pages", &Private::pages); - //%% string examples - s_inst.addProperty("examples", &Private::examples); - //%% string namespaceList - s_inst.addProperty("namespaceList", &Private::namespaceList); - //%% string namespaceMembers - s_inst.addProperty("namespaceMembers", &Private::namespaceMembers); - //%% string fileList - s_inst.addProperty("fileList", &Private::fileList); - //%% string fileMembers - s_inst.addProperty("fileMembers", &Private::fileMembers); - //%% string fileMembersDescription - s_inst.addProperty("fileMembersDescription", &Private::fileMembersDescription); - //%% string relatedPagesDescription - s_inst.addProperty("relatedPagesDesc", &Private::relatedPagesDesc); - //%% string more - s_inst.addProperty("more", &Private::more); - //%% string detailedDescription - s_inst.addProperty("detailedDesc", &Private::detailedDesc); - //%% string inheritanceDiagramFor - s_inst.addProperty("inheritanceDiagramFor", &Private::inheritanceDiagramFor); - //%% string collaborationDiagramFor - s_inst.addProperty("collaborationDiagramFor", &Private::collaborationDiagramFor); - //%% markerstring inheritsList - s_inst.addProperty("inheritsList", &Private::inheritsList); - //%% markerstring inheritedByList - s_inst.addProperty("inheritedByList", &Private::inheritedByList); - //%% markerstring definedAtLineInSourceFile - s_inst.addProperty("definedAtLineInSourceFile", &Private::definedAtLineInSourceFile); - //%% string typeConstraints - s_inst.addProperty("typeConstraints", &Private::typeConstraints); - //%% string exampleList - s_inst.addProperty("exampleList", &Private::exampleList); - //%% string listOfAllMembers - s_inst.addProperty("listOfAllMembers", &Private::listOfAllMembers); - //%% string memberList - s_inst.addProperty("memberList", &Private::memberList); - //%% string theListOfAllMembers - s_inst.addProperty("theListOfAllMembers",&Private::theListOfAllMembers); - //%% string incInheritedMembers - s_inst.addProperty("incInheritedMembers",&Private::incInheritedMembers); - //%% string defineValue - s_inst.addProperty("defineValue", &Private::defineValue); - //%% string initialValue - s_inst.addProperty("initialValue", &Private::initialValue); - //%% markerstring implements - s_inst.addProperty("implements", &Private::implements); - //%% markerstring reimplements - s_inst.addProperty("reimplements", &Private::reimplements); - //%% markerstring implementedBy - s_inst.addProperty("implementedBy", &Private::implementedBy); - //%% markerstring reimplementedBy - s_inst.addProperty("reimplementedBy", &Private::reimplementedBy); - //%% markerstring sourceRefs - s_inst.addProperty("sourceRefs", &Private::sourceRefs); - //%% markerstring sourceRefBys - s_inst.addProperty("sourceRefBys", &Private::sourceRefBys); - //%% string callGraph - s_inst.addProperty("callGraph", &Private::callGraph); - //%% string callerGraph - s_inst.addProperty("callerGraph", &Private::callerGraph); - //%% string referencedByRelation - s_inst.addProperty("referencedByRelation", &Private::referencedByRelation); - //%% string referencesRelation - s_inst.addProperty("referencesRelation", &Private::referencesRelation); - //%% markerstring inheritedFrom - s_inst.addProperty("inheritedFrom", &Private::inheritedFrom); - //%% string additionalInheritedMembers - s_inst.addProperty("additionalInheritedMembers",&Private::additionalInheritedMembers); - //%% string includeDependencyGraph:container_name - s_inst.addProperty("includeDependencyGraph",&Private::includeDependencyGraph); - //%% string includedByDependencyGraph - s_inst.addProperty("includedByDependencyGraph",&Private::includedByDependencyGraph); - //%% string gotoSourceCode - s_inst.addProperty("gotoSourceCode", &Private::gotoSourceCode); - //%% string gotoDocumentation - s_inst.addProperty("gotoDocumentation", &Private::gotoDocumentation); - //%% string constantgroups - s_inst.addProperty("constantgroups", &Private::constantgroups); - //%% string classDocumentation - s_inst.addProperty("classDocumentation", &Private::classDocumentation); - //%% string namespaceDocumentation - s_inst.addProperty("namespaceDocumentation", &Private::namespaceDocumentation); - //%% string moduleDocumentation - s_inst.addProperty("moduleDocumentation",&Private::moduleDocumentation); - //%% string fileDocumentation - s_inst.addProperty("fileDocumentation", &Private::fileDocumentation); - //%% string compoundMembers - s_inst.addProperty("compoundMembers", &Private::compoundMembers); - //%% string detailLevel - s_inst.addProperty("detailLevel", &Private::detailLevel); - //%% string fileListDescription - s_inst.addProperty("fileListDescription",&Private::fileListDescription); - //%% string namespaceListDescription - s_inst.addProperty("namespaceListDescription",&Private::namespaceListDescription); - //%% string conceptListDescription - s_inst.addProperty("conceptListDescription",&Private::conceptListDescription); - //%% string directories - s_inst.addProperty("directories", &Private::directories); - //%% string moduleDescription - s_inst.addProperty("modulesDescription", &Private::modulesDescription); - //%% string all - s_inst.addProperty("all", &Private::all); - //%% string functions - s_inst.addProperty("functions", &Private::functions); - //%% string variables - s_inst.addProperty("variables", &Private::variables); - //%% string typedefs - s_inst.addProperty("typedefs", &Private::typedefs); - //%% string enums - s_inst.addProperty("enums", &Private::enums); - //%% string enumValues - s_inst.addProperty("enumValues", &Private::enumerationValues); - //%% string properties - s_inst.addProperty("properties", &Private::properties); - //%% string events - s_inst.addProperty("events", &Private::events); - //%% string related - s_inst.addProperty("related", &Private::related); - //%% string macros - s_inst.addProperty("macros", &Private::macros); - //%% string namespaceMembersDescription - s_inst.addProperty("namespaceMembersDescription",&Private::namespaceMembersDescription); - //%% string classHierarchyDescription - s_inst.addProperty("classHierarchyDescription",&Private::classHierarchyDescription); - //%% string gotoGraphicalHierarchy - s_inst.addProperty("gotoGraphicalHierarchy",&Private::gotoGraphicalHierarchy); - //%% string gotoTextualHierarchy - s_inst.addProperty("gotoTextualHierarchy",&Private::gotoTextualHierarchy); - //%% string loading - s_inst.addProperty("loading", &Private::loading); - //%% string searching - s_inst.addProperty("searching", &Private::searching); - //%% string noMatches - s_inst.addProperty("noMatches", &Private::noMatches); - //%% string enumValue - s_inst.addProperty("enumValue", &Private::enumValue); - //%% string enumName - s_inst.addProperty("enumName", &Private::enumName); - //%% string referenceManual - s_inst.addProperty("referenceManual", &Private::referenceManual); - //%% string index - s_inst.addProperty("index", &Private::index); - //%% string panelSyncOn - s_inst.addProperty("panelSyncOn", &Private::panelSyncOn); - //%% string panelSyncOff - s_inst.addProperty("panelSyncOff", &Private::panelSyncOff); - //%% string dirDependencyGraph - s_inst.addProperty("dirDependencyGraphFor", &Private::dirDependencyGraphFor); - //%% string providedByCategory - s_inst.addProperty("providedByCategory", &Private::providedByCategory); - //%% string extendsClass - s_inst.addProperty("extendsClass", &Private::extendsClass); - //%% string examplesDescription - s_inst.addProperty("examplesDescription",&Private::examplesDescription); - //%% string langstring - s_inst.addProperty("langString", &Private::langString); - //%% string code - s_inst.addProperty("code", &Private::code); - - init=TRUE; - } - m_javaOpt = Config_getBool(OPTIMIZE_OUTPUT_JAVA); - m_fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN); - m_vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL); - m_sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE); - } - TemplateVariant get(const QCString &n) const - { - return s_inst.get(this,n); - } - StringVector fields() const - { - return s_inst.fields(); - } private: bool m_javaOpt; bool m_fortranOpt; bool m_vhdlOpt; bool m_sliceOpt; - static PropertyMapper<TranslateContext::Private> s_inst; + static const PropertyMap<TranslateContext::Private> s_inst; }; -//%% } -PropertyMapper<TranslateContext::Private> TranslateContext::Private::s_inst; +//%% struct Translator: translation methods +//%% { +const PropertyMap<TranslateContext::Private> TranslateContext::Private::s_inst { +{ + //%% string generatedBy + { "generatedBy", &Private::generatedBy }, + //%% string generatedAt + { "generatedAt", &Private::generatedAt }, + //%% string search + { "search", &Private::search }, + //%% string mainPage + { "mainPage", &Private::mainPage }, + //%% string classes + { "classes", &Private::classes }, + //%% string classList + { "classList", &Private::classList }, + //%% string classListDescription + { "classListDescription", &Private::classListDescription }, + //%% string classIndex + { "classIndex", &Private::classIndex }, + //%% string concepts + { "concepts", &Private::concepts }, + //%% string conceptDefintion + { "conceptDefinition", &Private::conceptDefinition }, + //%% string namespaceIndex + { "namespaceIndex", &Private::namespaceIndex }, + //%% string classHierarchy + { "classHierarchy", &Private::classHierarchy }, + //%% string classMembers + { "classMembers", &Private::classMembers }, + //%% string classMembersDescription + { "classMembersDescription",&Private::classMembersDescription }, + //%% string modules + { "modules", &Private::modules }, + //%% string moduleIndex + { "moduleIndex", &Private::moduleIndex }, + //%% string namespaces + { "namespaces", &Private::namespaces }, + //%% string fileIndex + { "fileIndex", &Private::fileIndex }, + //%% string files + { "files", &Private::files }, + //%% string pages + { "pages", &Private::pages }, + //%% string examples + { "examples", &Private::examples }, + //%% string namespaceList + { "namespaceList", &Private::namespaceList }, + //%% string namespaceMembers + { "namespaceMembers", &Private::namespaceMembers }, + //%% string fileList + { "fileList", &Private::fileList }, + //%% string fileMembers + { "fileMembers", &Private::fileMembers }, + //%% string fileMembersDescription + { "fileMembersDescription", &Private::fileMembersDescription }, + //%% string relatedPagesDescription + { "relatedPagesDesc", &Private::relatedPagesDesc }, + //%% string more + { "more", &Private::more }, + //%% string detailedDescription + { "detailedDesc", &Private::detailedDesc }, + //%% string inheritanceDiagramFor + { "inheritanceDiagramFor", &Private::inheritanceDiagramFor }, + //%% string collaborationDiagramFor + { "collaborationDiagramFor", &Private::collaborationDiagramFor }, + //%% markerstring inheritsList + { "inheritsList", &Private::inheritsList }, + //%% markerstring inheritedByList + { "inheritedByList", &Private::inheritedByList }, + //%% markerstring definedAtLineInSourceFile + { "definedAtLineInSourceFile", &Private::definedAtLineInSourceFile }, + //%% string typeConstraints + { "typeConstraints", &Private::typeConstraints }, + //%% string exampleList + { "exampleList", &Private::exampleList }, + //%% string listOfAllMembers + { "listOfAllMembers", &Private::listOfAllMembers }, + //%% string memberList + { "memberList", &Private::memberList }, + //%% string theListOfAllMembers + { "theListOfAllMembers",&Private::theListOfAllMembers }, + //%% string incInheritedMembers + { "incInheritedMembers",&Private::incInheritedMembers }, + //%% string defineValue + { "defineValue", &Private::defineValue }, + //%% string initialValue + { "initialValue", &Private::initialValue }, + //%% markerstring implements + { "implements", &Private::implements }, + //%% markerstring reimplements + { "reimplements", &Private::reimplements }, + //%% markerstring implementedBy + { "implementedBy", &Private::implementedBy }, + //%% markerstring reimplementedBy + { "reimplementedBy", &Private::reimplementedBy }, + //%% markerstring sourceRefs + { "sourceRefs", &Private::sourceRefs }, + //%% markerstring sourceRefBys + { "sourceRefBys", &Private::sourceRefBys }, + //%% string callGraph + { "callGraph", &Private::callGraph }, + //%% string callerGraph + { "callerGraph", &Private::callerGraph }, + //%% string referencedByRelation + { "referencedByRelation", &Private::referencedByRelation }, + //%% string referencesRelation + { "referencesRelation", &Private::referencesRelation }, + //%% markerstring inheritedFrom + { "inheritedFrom", &Private::inheritedFrom }, + //%% string additionalInheritedMembers + { "additionalInheritedMembers",&Private::additionalInheritedMembers }, + //%% string includeDependencyGraph:container_name + { "includeDependencyGraph",&Private::includeDependencyGraph }, + //%% string includedByDependencyGraph + { "includedByDependencyGraph",&Private::includedByDependencyGraph }, + //%% string gotoSourceCode + { "gotoSourceCode", &Private::gotoSourceCode }, + //%% string gotoDocumentation + { "gotoDocumentation", &Private::gotoDocumentation }, + //%% string constantgroups + { "constantgroups", &Private::constantgroups }, + //%% string classDocumentation + { "classDocumentation", &Private::classDocumentation }, + //%% string namespaceDocumentation + { "namespaceDocumentation", &Private::namespaceDocumentation }, + //%% string moduleDocumentation + { "moduleDocumentation",&Private::moduleDocumentation }, + //%% string fileDocumentation + { "fileDocumentation", &Private::fileDocumentation }, + //%% string compoundMembers + { "compoundMembers", &Private::compoundMembers }, + //%% string detailLevel + { "detailLevel", &Private::detailLevel }, + //%% string fileListDescription + { "fileListDescription",&Private::fileListDescription }, + //%% string namespaceListDescription + { "namespaceListDescription",&Private::namespaceListDescription }, + //%% string conceptListDescription + { "conceptListDescription",&Private::conceptListDescription }, + //%% string directories + { "directories", &Private::directories }, + //%% string moduleDescription + { "modulesDescription", &Private::modulesDescription }, + //%% string all + { "all", &Private::all }, + //%% string functions + { "functions", &Private::functions }, + //%% string variables + { "variables", &Private::variables }, + //%% string typedefs + { "typedefs", &Private::typedefs }, + //%% string enums + { "enums", &Private::enums }, + //%% string enumValues + { "enumValues", &Private::enumerationValues }, + //%% string properties + { "properties", &Private::properties }, + //%% string events + { "events", &Private::events }, + //%% string related + { "related", &Private::related }, + //%% string macros + { "macros", &Private::macros }, + //%% string namespaceMembersDescription + { "namespaceMembersDescription",&Private::namespaceMembersDescription }, + //%% string classHierarchyDescription + { "classHierarchyDescription",&Private::classHierarchyDescription }, + //%% string gotoGraphicalHierarchy + { "gotoGraphicalHierarchy",&Private::gotoGraphicalHierarchy }, + //%% string gotoTextualHierarchy + { "gotoTextualHierarchy",&Private::gotoTextualHierarchy }, + //%% string loading + { "loading", &Private::loading }, + //%% string searching + { "searching", &Private::searching }, + //%% string noMatches + { "noMatches", &Private::noMatches }, + //%% string enumValue + { "enumValue", &Private::enumValue }, + //%% string enumName + { "enumName", &Private::enumName }, + //%% string referenceManual + { "referenceManual", &Private::referenceManual }, + //%% string index + { "index", &Private::index }, + //%% string panelSyncOn + { "panelSyncOn", &Private::panelSyncOn }, + //%% string panelSyncOff + { "panelSyncOff", &Private::panelSyncOff }, + //%% string dirDependencyGraph + { "dirDependencyGraphFor", &Private::dirDependencyGraphFor }, + //%% string providedByCategory + { "providedByCategory", &Private::providedByCategory }, + //%% string extendsClass + { "extendsClass", &Private::extendsClass }, + //%% string examplesDescription + { "examplesDescription",&Private::examplesDescription }, + //%% string langstring + { "langString", &Private::langString }, + //%% string code + { "code", &Private::code } +} }; +//%% } -TranslateContext::TranslateContext() : RefCountedContext("TranslateContext") +TranslateContext::TranslateContext() : p(std::make_unique<Private>()) { - p = new Private; } TranslateContext::~TranslateContext() { - delete p; } TemplateVariant TranslateContext::get(const QCString &n) const @@ -1301,6 +1236,8 @@ StringVector TranslateContext::fields() const return p->fields(); } +//------------------------------------------------------------------------------------------ + static TemplateVariant parseDoc(const Definition *def,const QCString &file,int line, const QCString &relPath,const QCString &docStr,bool isBrief) { @@ -1426,8 +1363,6 @@ static TemplateVariant parseCode(const FileDef *fd,const QCString &relPath) //------------------------------------------------------------------------ -//%% struct Symbol: shared info for all symbols -//%% { template<typename T> class DefinitionContext { @@ -1435,135 +1370,60 @@ class DefinitionContext DefinitionContext(const Definition *d) : m_def(d) { assert(d!=0); - } - virtual ~DefinitionContext() {} - void addBaseProperties(PropertyMapper<T> &inst) - { - //%% string name: the name of the symbol - inst.addProperty("name",&DefinitionContext::name); - //%% string bareName: the bare name of the symbol with scope info - inst.addProperty("bareName",&DefinitionContext::bareName); - //%% string relPath: the relative path to the root of the output (CREATE_SUBDIRS) - inst.addProperty("relPath",&DefinitionContext::relPath); - //%% string fileName: the file name of the output file associated with the symbol (without extension) - inst.addProperty("fileName",&DefinitionContext::fileName); - //%% string anchor: anchor within the page - inst.addProperty("anchor",&DefinitionContext::anchor); - //%% string details: the detailed documentation for this symbol - inst.addProperty("details",&DefinitionContext::details); - //%% string brief: the brief description for this symbol - inst.addProperty("brief",&DefinitionContext::brief); - //%% string inbodyDocs: the documentation found in the body - inst.addProperty("inbodyDocs",&DefinitionContext::inbodyDocs); - //%% string sourceFileName: the file name of the source file (without extension) - inst.addProperty("sourceFileName",&DefinitionContext::sourceFileName); - //%% bool isLinkable: can the symbol be linked to? - inst.addProperty("isLinkable",&DefinitionContext::isLinkable); - //%% bool isLinkableInProject: can the symbol be linked within this project? - inst.addProperty("isLinkableInProject",&DefinitionContext::isLinkableInProject); - //%% int dynSectionId: identifier that can be used for collapsible sections - inst.addProperty("dynSectionId",&DefinitionContext::dynSectionId); - //%% string language: the programming language in which the symbol is written - inst.addProperty("language",&DefinitionContext::language); - //%% string sourceDef: A link to the source definition - inst.addProperty("sourceDef",&DefinitionContext::sourceDef); - //%% list[Definition] navigationPath: Breadcrumb navigation path to this item - inst.addProperty("navigationPath",&DefinitionContext::navigationPath); - //%% string kind: Kind of compound object: class, namespace, module, package, page, dir - inst.addProperty("compoundKind",&DefinitionContext::compoundKind); - //%% bool isReference: is this definition imported via a tag file - inst.addProperty("isReference",&DefinitionContext::isReference); - //%% string externalReference: the link to the element in the remote documentation - inst.addProperty("externalReference",&DefinitionContext::externalReference); - } - TemplateVariant fileName() const - { - return m_def->getOutputFileBase(); - } - TemplateVariant anchor() const - { - return m_def->anchor(); - } - TemplateVariant sourceFileName() const - { - return m_def->getSourceFileBase(); - } - TemplateVariant isLinkable() const - { - return m_def->isLinkable(); - } - TemplateVariant isLinkableInProject() const - { - return m_def->isLinkableInProject(); - } - TemplateVariant name() const - { - return m_def->displayName(TRUE); - } - TemplateVariant bareName() const - { - return m_def->displayName(FALSE); - } - QCString relPathAsString() const - { - static bool createSubdirs = Config_getBool(CREATE_SUBDIRS); - return createSubdirs ? QCString("../../") : QCString(""); - } - virtual TemplateVariant relPath() const - { - return relPathAsString(); - } - TemplateVariant details() const - { - Cachable &cache = getCache(); - if (!cache.details || g_globals.outputFormat!=cache.detailsOutputFormat) - { - cache.details.reset(new TemplateVariant(parseDoc(m_def,m_def->docFile(),m_def->docLine(), - relPathAsString(),m_def->documentation(),FALSE))); - cache.detailsOutputFormat = g_globals.outputFormat; - } - return *cache.details; - } - TemplateVariant brief() const - { - Cachable &cache = getCache(); - if (!cache.brief || g_globals.outputFormat!=cache.briefOutputFormat) + + if (m_def && !m_def->getSourceFileBase().isEmpty()) { - if (m_def->hasBriefDescription()) + TemplateStructIntfPtr lineLink = TemplateImmutableStruct::alloc( { - cache.brief.reset(new TemplateVariant(parseDoc(m_def,m_def->briefFile(),m_def->briefLine(), - relPathAsString(),m_def->briefDescription(),TRUE))); - cache.briefOutputFormat = g_globals.outputFormat; - } - else + { "text", TemplateVariant(m_def->getStartBodyLine()) }, + { "isLinkable", TemplateVariant(TRUE) }, + { "fileName", TemplateVariant(m_def->getSourceFileBase()) }, + { "anchor", TemplateVariant(m_def->getSourceAnchor()) }, + { "isReference", TemplateVariant(FALSE) }, + { "externalReference", TemplateVariant("") } + }); + + QCString text = m_def->definitionType()==Definition::TypeFile ? m_def->name() : + m_def->getBodyDef() ? m_def->getBodyDef()->name() : + m_def->displayName(TRUE); + + TemplateStructIntfPtr fileLink = TemplateImmutableStruct::alloc( { - cache.brief.reset(new TemplateVariant("")); - } + { "text", TemplateVariant(text) }, + { "isLinkable", TemplateVariant(TRUE) }, + { "fileName", TemplateVariant(m_def->getSourceFileBase()) }, + { "anchor", TemplateVariant("") }, + { "isReference", TemplateVariant(FALSE) }, + { "externalReference", TemplateVariant("") } + }); + + m_sourceDef = TemplateImmutableList::alloc( { lineLink, fileLink }); } - return *cache.brief; - } - TemplateVariant inbodyDocs() const - { - Cachable &cache = getCache(); - if (!cache.inbodyDocs || g_globals.outputFormat!=cache.inbodyDocsOutputFormat) + else { - if (!m_def->inbodyDocumentation().isEmpty()) - { - cache.inbodyDocs.reset(new TemplateVariant(parseDoc(m_def,m_def->inbodyFile(),m_def->inbodyLine(), - relPathAsString(),m_def->inbodyDocumentation(),FALSE))); - cache.inbodyDocsOutputFormat = g_globals.outputFormat; - } - else - { - cache.inbodyDocs.reset(new TemplateVariant("")); - } + m_sourceDef = TemplateImmutableList::alloc( {} ); } - return *cache.inbodyDocs; - } - TemplateVariant dynSectionId() const - { - return g_globals.dynSectionId; } + virtual ~DefinitionContext() {} + + protected: + // Property getters + TemplateVariant fileName() const { return m_def->getOutputFileBase(); } + TemplateVariant anchor() const { return m_def->anchor(); } + TemplateVariant sourceFileName() const { return m_def->getSourceFileBase(); } + TemplateVariant isLinkable() const { return m_def->isLinkable(); } + TemplateVariant isLinkableInProject() const { return m_def->isLinkableInProject(); } + TemplateVariant name() const { return m_def->displayName(TRUE); } + TemplateVariant bareName() const { return m_def->displayName(FALSE); } + TemplateVariant details() const { return m_cachable.details.get(this); } + TemplateVariant brief() const { return m_cachable.brief.get(this); } + TemplateVariant inbodyDocs() const { return m_cachable.inbodyDocs.get(this); } + TemplateVariant dynSectionId() const { return g_globals.dynSectionId; } + TemplateVariant sourceDef() const { return std::static_pointer_cast<TemplateListIntf>(m_sourceDef); } + TemplateVariant navigationPath() const { return m_cachable.navPath.get(this); } + TemplateVariant partOfGroups() const { return m_cachable.partOfGroups.get(this); } + TemplateVariant isReference() const { return m_def->isReference(); } + TemplateVariant externalReference() const { return m_def->externalReference(relPathAsString()); } TemplateVariant language() const { SrcLangExt lang = m_def->getLanguage(); @@ -1607,19 +1467,49 @@ class DefinitionContext } return result; } - TemplateVariant sourceDef() const + + protected: + + QCString relPathAsString() const + { + static bool createSubdirs = Config_getBool(CREATE_SUBDIRS); + return createSubdirs ? QCString("../../") : QCString(""); + } + virtual TemplateVariant relPath() const { return relPathAsString(); } + + + private: + + TemplateVariant createDetails() const + { + return TemplateVariant(parseDoc(m_def,m_def->docFile(),m_def->docLine(), + relPathAsString(),m_def->documentation(),FALSE)); + } + TemplateVariant createBrief() const { - Cachable &cache = getCache(); - if (cache.sourceDef->count()==2) + if (m_def->hasBriefDescription()) { - return cache.sourceDef.get(); + return TemplateVariant(parseDoc(m_def,m_def->briefFile(),m_def->briefLine(), + relPathAsString(),m_def->briefDescription(),TRUE)); } else { - return FALSE; + return TemplateVariant(""); } } - void fillPath(const Definition *def,TemplateList *list) const + TemplateVariant createInbodyDocs() const + { + if (!m_def->inbodyDocumentation().isEmpty()) + { + return TemplateVariant(parseDoc(m_def,m_def->inbodyFile(),m_def->inbodyLine(), + relPathAsString(),m_def->inbodyDocumentation(),FALSE)); + } + else + { + return TemplateVariant(""); + } + } + void fillPath(const Definition *def,TemplateVariantList &list) const { const Definition *outerScope = def->getOuterScope(); Definition::DefType type = def->definitionType(); @@ -1631,102 +1521,77 @@ class DefinitionContext { fillPath((toFileDef(def))->getDirDef(),list); } - list->append(NavPathElemContext::alloc(def)); + list.push_back(NavPathElemContext::alloc(def)); } - TemplateVariant navigationPath() const + TemplateListIntfPtr createNavigationPath() const { - Cachable &cache = getCache(); - if (!cache.navPath) + TemplateVariantList list; + if (m_def->getOuterScope() && m_def->getOuterScope()!=Doxygen::globalScope) { - TemplateList *list = TemplateList::alloc(); - if (m_def->getOuterScope() && m_def->getOuterScope()!=Doxygen::globalScope) - { - fillPath(m_def,list); - } - else if (m_def->definitionType()==Definition::TypeFile && (toFileDef(m_def))->getDirDef()) - { - fillPath((toFileDef(m_def))->getDirDef(),list); - } - cache.navPath.reset(list); + fillPath(m_def,list); } - return cache.navPath.get(); - } - TemplateVariant isReference() const - { - return m_def->isReference(); + else if (m_def->definitionType()==Definition::TypeFile && (toFileDef(m_def))->getDirDef()) + { + fillPath((toFileDef(m_def))->getDirDef(),list); + } + return TemplateImmutableList::alloc(list); } - TemplateVariant externalReference() const + TemplateListIntfPtr createPartOfGroups() const { - return m_def->externalReference(relPathAsString()); + TemplateVariantList list; + list.reserve(m_def->partOfGroups().size()); + for (const auto &gd : m_def->partOfGroups()) + { + list.push_back(ModuleContext::alloc(gd)); + } + return TemplateImmutableList::alloc(list); } protected: struct Cachable : public Definition::Cookie { - Cachable(const Definition *def) : detailsOutputFormat(ContextOutputFormat_Unspecified), - briefOutputFormat(ContextOutputFormat_Unspecified), - inbodyDocsOutputFormat(ContextOutputFormat_Unspecified) - { - sourceDef.reset(TemplateList::alloc()); - lineLink.reset(TemplateStruct::alloc()); - fileLink.reset(TemplateStruct::alloc()); - - if (def && !def->getSourceFileBase().isEmpty()) - { - lineLink->set("text",def->getStartBodyLine()); - lineLink->set("isLinkable",TRUE); - lineLink->set("fileName",def->getSourceFileBase()); - lineLink->set("anchor",def->getSourceAnchor()); - lineLink->set("isReference",FALSE); - lineLink->set("externalReference",""); - if (def->definitionType()==Definition::TypeFile) - { - fileLink->set("text",def->name()); - } - else if (def->getBodyDef()) - { - fileLink->set("text",def->getBodyDef()->name()); - } - else - { - fileLink->set("text",def->displayName(TRUE)); - } - fileLink->set("isLinkable",TRUE); - fileLink->set("fileName",def->getSourceFileBase()); - fileLink->set("anchor",QCString()); - fileLink->set("isReference",FALSE); - fileLink->set("externalReference",""); - sourceDef->append(lineLink.get()); - sourceDef->append(fileLink.get()); - } - } - std::unique_ptr<TemplateVariant> details; - ContextOutputFormat detailsOutputFormat; - std::unique_ptr<TemplateVariant> brief; - ContextOutputFormat briefOutputFormat; - std::unique_ptr<TemplateVariant> inbodyDocs; - ContextOutputFormat inbodyDocsOutputFormat; - SharedPtr<TemplateList> navPath; - SharedPtr<TemplateList> sourceDef; - SharedPtr<TemplateStruct> fileLink; - SharedPtr<TemplateStruct> lineLink; + using DC = DefinitionContext<T>; + CachedItem<TemplateVariant, DC, &DC::createDetails> details; + CachedItem<TemplateVariant, DC, &DC::createBrief> brief; + CachedItem<TemplateVariant, DC, &DC::createInbodyDocs> inbodyDocs; + CachedItem<TemplateListIntfPtr, DC, &DC::createNavigationPath> navPath; + CachedItem<TemplateListIntfPtr, DC, &DC::createPartOfGroups> partOfGroups; }; private: - Cachable &getCache() const - { - Cachable *c = static_cast<Cachable*>(m_def->cookie()); - assert(c!=0); - return *c; - } + Cachable m_cachable; const Definition *m_def; + TemplateListIntfPtr m_sourceDef; + static const PropertyMap< DefinitionContext<T> > s_baseProperties; }; + +//%% struct Definition: shared info for all symbols +//%% { +#define BASE_PROPERTIES \ + { "name", &Private::name }, \ + { "bareName", &Private::bareName }, \ + { "relPath", &Private::relPath }, \ + { "fileName", &Private::fileName }, \ + { "anchor", &Private::anchor }, \ + { "details", &Private::details }, \ + { "brief", &Private::brief }, \ + { "inbodyDocs", &Private::inbodyDocs }, \ + { "sourceFileName", &Private::sourceFileName }, \ + { "isLinkable", &Private::isLinkable }, \ + { "isLinkableInProject",&Private::isLinkableInProject }, \ + { "dynSectionId", &Private::dynSectionId }, \ + { "language", &Private::language }, \ + { "sourceDef", &Private::sourceDef }, \ + { "navigationPath", &Private::navigationPath }, \ + { "partOfGroups", &Private::partOfGroups }, \ + { "compoundKind", &Private::compoundKind }, \ + { "isReference", &Private::isReference }, \ + { "externalReference", &Private::externalReference } //%% } + //------------------------------------------------------------------------ -//%% struct IncludeInfo: include file information -//%% { class IncludeInfoContext::Private { public: @@ -1734,15 +1599,6 @@ class IncludeInfoContext::Private m_info(info), m_lang(lang) { - static bool init=FALSE; - if (!init) - { - s_inst.addProperty("file",&Private::file); - s_inst.addProperty("name",&Private::name); - s_inst.addProperty("isImport",&Private::isImport); - s_inst.addProperty("isLocal",&Private::isLocal); - init=TRUE; - } } TemplateVariant get(const QCString &n) const { @@ -1763,18 +1619,7 @@ class IncludeInfoContext::Private } TemplateVariant file() const { - if (!m_fileContext && m_info && m_info->fileDef) - { - m_fileContext.reset(FileContext::alloc(m_info->fileDef)); - } - if (m_fileContext) - { - return m_fileContext.get(); - } - else - { - return FALSE; - } + return m_fileContext.get(this); } TemplateVariant name() const { @@ -1782,21 +1627,33 @@ class IncludeInfoContext::Private } private: const IncludeInfo *m_info; - mutable SharedPtr<FileContext> m_fileContext; + TemplateVariant createFileContext() const + { + return m_info && m_info->fileDef ? + TemplateVariant(FileContext::alloc(m_info->fileDef)) : + TemplateVariant(false); + } + CachedItem<TemplateVariant, Private, &Private::createFileContext> m_fileContext; SrcLangExt m_lang; - static PropertyMapper<IncludeInfoContext::Private> s_inst; + static const PropertyMap<IncludeInfoContext::Private> s_inst; }; -PropertyMapper<IncludeInfoContext::Private> IncludeInfoContext::Private::s_inst; +//%% struct IncludeInfo: include file information +//%% { +const PropertyMap<IncludeInfoContext::Private> IncludeInfoContext::Private::s_inst { + { "file",&Private::file }, + { "name",&Private::name }, + { "isImport",&Private::isImport }, + { "isLocal",&Private::isLocal } +}; +//%% } -IncludeInfoContext::IncludeInfoContext(const IncludeInfo *info,SrcLangExt lang) : RefCountedContext("IncludeContext") +IncludeInfoContext::IncludeInfoContext(const IncludeInfo *info,SrcLangExt lang) : p(std::make_unique<Private>(info,lang)) { - p = new Private(info,lang); } IncludeInfoContext::~IncludeInfoContext() { - delete p; } TemplateVariant IncludeInfoContext::get(const QCString &n) const @@ -1826,14 +1683,12 @@ class IncludeInfoListContext::Private : public GenericNodeListContext } }; -IncludeInfoListContext::IncludeInfoListContext(const IncludeInfoList &list,SrcLangExt lang) : RefCountedContext("IncludeListContext") +IncludeInfoListContext::IncludeInfoListContext(const IncludeInfoList &list,SrcLangExt lang) : p(std::make_unique<Private>(list,lang)) { - p = new Private(list,lang); } IncludeInfoListContext::~IncludeInfoListContext() { - delete p; } // TemplateListIntf @@ -1847,163 +1702,106 @@ TemplateVariant IncludeInfoListContext::at(uint index) const return p->at(index); } -TemplateListIntf::ConstIterator *IncludeInfoListContext::createIterator() const +TemplateListIntf::ConstIteratorPtr IncludeInfoListContext::createIterator() const { return p->createIterator(); } //------------------------------------------------------------------------ -//%% struct Class(Symbol): class information -//%% { class ClassContext::Private : public DefinitionContext<ClassContext::Private> { public: Private(const ClassDef *cd) : DefinitionContext<ClassContext::Private>(cd), m_classDef(cd) { - static bool init=FALSE; - if (!init) - { - addBaseProperties(s_inst); - s_inst.addProperty("title", &Private::title); - s_inst.addProperty("highlight", &Private::highlight); - s_inst.addProperty("subhighlight", &Private::subHighlight); - s_inst.addProperty("hasDetails", &Private::hasDetails); - s_inst.addProperty("generatedFromFiles", &Private::generatedFromFiles); - s_inst.addProperty("usedFiles", &Private::usedFiles); - s_inst.addProperty("hasInheritanceDiagram", &Private::hasInheritanceDiagram); - s_inst.addProperty("inheritanceDiagram", &Private::inheritanceDiagram); - s_inst.addProperty("hasCollaborationDiagram", &Private::hasCollaborationDiagram); - s_inst.addProperty("collaborationDiagram", &Private::collaborationDiagram); - s_inst.addProperty("includeInfo", &Private::includeInfo); - s_inst.addProperty("inherits", &Private::inherits); - s_inst.addProperty("inheritedBy", &Private::inheritedBy); - s_inst.addProperty("unoIDLServices", &Private::unoIDLServices); - s_inst.addProperty("unoIDLInterfaces", &Private::unoIDLInterfaces); - s_inst.addProperty("signals", &Private::signals); - s_inst.addProperty("publicTypes", &Private::publicTypes); - s_inst.addProperty("publicMethods", &Private::publicMethods); - s_inst.addProperty("publicStaticMethods", &Private::publicStaticMethods); - s_inst.addProperty("publicAttributes", &Private::publicAttributes); - s_inst.addProperty("publicStaticAttributes", &Private::publicStaticAttributes); - s_inst.addProperty("publicSlots", &Private::publicSlots); - s_inst.addProperty("protectedTypes", &Private::protectedTypes); - s_inst.addProperty("protectedMethods", &Private::protectedMethods); - s_inst.addProperty("protectedStaticMethods", &Private::protectedStaticMethods); - s_inst.addProperty("protectedAttributes", &Private::protectedAttributes); - s_inst.addProperty("protectedStaticAttributes", &Private::protectedStaticAttributes); - s_inst.addProperty("protectedSlots", &Private::protectedSlots); - s_inst.addProperty("privateTypes", &Private::privateTypes); - s_inst.addProperty("privateMethods", &Private::privateMethods); - s_inst.addProperty("privateStaticMethods", &Private::privateStaticMethods); - s_inst.addProperty("privateAttributes", &Private::privateAttributes); - s_inst.addProperty("privateStaticAttributes", &Private::privateStaticAttributes); - s_inst.addProperty("privateSlots", &Private::privateSlots); - s_inst.addProperty("packageTypes", &Private::packageTypes); - s_inst.addProperty("packageMethods", &Private::packageMethods); - s_inst.addProperty("packageStaticMethods", &Private::packageStaticMethods); - s_inst.addProperty("packageAttributes", &Private::packageAttributes); - s_inst.addProperty("packageStaticAttributes", &Private::packageStaticAttributes); - s_inst.addProperty("properties", &Private::properties); - s_inst.addProperty("events", &Private::events); - s_inst.addProperty("friends", &Private::friends); - s_inst.addProperty("related", &Private::related); - s_inst.addProperty("detailedTypedefs", &Private::detailedTypedefs); - s_inst.addProperty("detailedEnums", &Private::detailedEnums); - s_inst.addProperty("detailedServices", &Private::detailedServices); - s_inst.addProperty("detailedInterfaces", &Private::detailedInterfaces); - s_inst.addProperty("detailedConstructors", &Private::detailedConstructors); - s_inst.addProperty("detailedMethods", &Private::detailedMethods); - s_inst.addProperty("detailedRelated", &Private::detailedRelated); - s_inst.addProperty("detailedVariables", &Private::detailedVariables); - s_inst.addProperty("detailedProperties", &Private::detailedProperties); - s_inst.addProperty("detailedEvents", &Private::detailedEvents); - s_inst.addProperty("classes", &Private::classes); - s_inst.addProperty("innerClasses", &Private::innerClasses); - s_inst.addProperty("compoundType", &Private::compoundType); - s_inst.addProperty("templateDecls", &Private::templateDecls); - s_inst.addProperty("typeConstraints", &Private::typeConstraints); - s_inst.addProperty("examples", &Private::examples); - s_inst.addProperty("members", &Private::members); - s_inst.addProperty("allMembersList", &Private::allMembersList); - s_inst.addProperty("allMembersFileName", &Private::allMembersFileName); - s_inst.addProperty("memberGroups", &Private::memberGroups); - s_inst.addProperty("additionalInheritedMembers",&Private::additionalInheritedMembers); - s_inst.addProperty("isSimple", &Private::isSimple); - s_inst.addProperty("categoryOf", &Private::categoryOf); - init=TRUE; - } - if (!cd->cookie()) { cd->setCookie(new ClassContext::Private::Cachable(cd)); } } virtual ~Private() {} - TemplateVariant get(const QCString &n) const - { - return s_inst.get(this,n); - } - StringVector fields() const - { - return s_inst.fields(); - } - TemplateVariant title() const - { - return TemplateVariant(m_classDef->title()); - } - TemplateVariant highlight() const - { - return TemplateVariant("classes"); - } - TemplateVariant subHighlight() const - { - return TemplateVariant(""); - } - TemplateVariant hasDetails() const - { - return m_classDef->hasDetailedDescription(); - } - TemplateVariant generatedFromFiles() const - { - return m_classDef->generatedFromFiles(); - } - TemplateVariant usedFiles() const - { - Cachable &cache = getCache(); - if (!cache.usedFiles) - { - cache.usedFiles.reset(UsedFilesContext::alloc(m_classDef)); - } - return cache.usedFiles.get(); - } - DotClassGraph *getClassGraph() const - { - Cachable &cache = getCache(); - if (!cache.classGraph) - { - cache.classGraph.reset(new DotClassGraph(m_classDef,Inheritance)); - } - return cache.classGraph.get(); - } - int numInheritanceNodes() const - { - Cachable &cache = getCache(); - if (cache.inheritanceNodes==-1) - { - cache.inheritanceNodes=m_classDef->countInheritanceNodes(); - } - return cache.inheritanceNodes>0; - } + + // TemplateStructIntf methods + TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); } + StringVector fields() const { return s_inst.fields(); } + + private: + // Property getters + TemplateVariant title() const { return TemplateVariant(m_classDef->title()); } + TemplateVariant highlight() const { return TemplateVariant("classes"); } + TemplateVariant subHighlight() const { return TemplateVariant(""); } + TemplateVariant hasDetails() const { return m_classDef->hasDetailedDescription(); } + TemplateVariant generatedFromFiles() const { return m_classDef->generatedFromFiles(); } + TemplateVariant usedFiles() const { return m_cachable.usedFiles.get(this); } + DotClassGraphPtr getClassGraph() const { return m_cachable.classGraph.get(this); } + int numInheritanceNodes() const { return m_cachable.numInheritanceNodes.get(this); } + TemplateVariant includeInfo() const { return m_cachable.includeInfo.get(this); } + TemplateVariant inherits() const { return m_cachable.inheritsList.get(this); } + TemplateVariant inheritedBy() const { return m_cachable.inheritedByList.get(this); } + TemplateVariant unoIDLServices() const { return m_cachable.unoIDLServices.get(this); } + TemplateVariant unoIDLInterfaces() const { return m_cachable.unoIDLInterfaces.get(this); } + TemplateVariant signals() const { return m_cachable.signals.get(this); } + TemplateVariant publicTypes() const { return m_cachable.publicTypes.get(this); } + TemplateVariant publicMethods() const { return m_cachable.publicMethods.get(this); } + TemplateVariant publicStaticMethods() const { return m_cachable.publicStaticMethods.get(this); } + TemplateVariant publicAttributes() const { return m_cachable.publicAttributes.get(this); } + TemplateVariant publicStaticAttributes() const { return m_cachable.publicStaticAttributes.get(this); } + TemplateVariant publicSlots() const { return m_cachable.publicSlots.get(this); } + TemplateVariant protectedTypes() const { return m_cachable.protectedTypes.get(this); } + TemplateVariant protectedMethods() const { return m_cachable.protectedMethods.get(this); } + TemplateVariant protectedStaticMethods() const { return m_cachable.protectedStaticMethods.get(this); } + TemplateVariant protectedAttributes() const { return m_cachable.protectedAttributes.get(this); } + TemplateVariant protectedStaticAttributes() const { return m_cachable.protectedStaticAttributes.get(this); } + TemplateVariant protectedSlots() const { return m_cachable.protectedSlots.get(this); } + TemplateVariant privateTypes() const { return m_cachable.privateTypes.get(this); } + TemplateVariant privateSlots() const { return m_cachable.privateSlots.get(this); } + TemplateVariant privateMethods() const { return m_cachable.privateMethods.get(this); } + TemplateVariant privateStaticMethods() const { return m_cachable.privateStaticMethods.get(this); } + TemplateVariant privateAttributes() const { return m_cachable.privateAttributes.get(this); } + TemplateVariant privateStaticAttributes() const { return m_cachable.privateStaticAttributes.get(this); } + TemplateVariant packageTypes() const { return m_cachable.packageTypes.get(this); } + TemplateVariant packageMethods() const { return m_cachable.packageMethods.get(this); } + TemplateVariant packageStaticMethods() const { return m_cachable.packageStaticMethods.get(this); } + TemplateVariant packageAttributes() const { return m_cachable.packageAttributes.get(this); } + TemplateVariant packageStaticAttributes() const { return m_cachable.packageStaticAttributes.get(this); } + TemplateVariant properties() const { return m_cachable.properties.get(this); } + TemplateVariant events() const { return m_cachable.events.get(this); } + TemplateVariant friends() const { return m_cachable.friends.get(this); } + TemplateVariant related() const { return m_cachable.related.get(this); } + TemplateVariant detailedTypedefs() const { return m_cachable.detailedTypedefs.get(this); } + TemplateVariant detailedEnums() const { return m_cachable.detailedEnums.get(this); } + TemplateVariant detailedServices() const { return m_cachable.detailedServices.get(this); } + TemplateVariant detailedInterfaces() const { return m_cachable.detailedInterfaces.get(this); } + TemplateVariant detailedConstructors() const { return m_cachable.detailedConstructors.get(this); } + TemplateVariant detailedMethods() const { return m_cachable.detailedMethods.get(this); } + TemplateVariant detailedRelated() const { return m_cachable.detailedRelated.get(this); } + TemplateVariant detailedVariables() const { return m_cachable.detailedVariables.get(this); } + TemplateVariant detailedProperties() const { return m_cachable.detailedProperties.get(this); } + TemplateVariant detailedEvents() const { return m_cachable.detailedEvents.get(this); } + TemplateVariant classes() const { return m_cachable.classes.get(this); } + TemplateVariant innerClasses() const { return m_cachable.innerClasses.get(this); } + TemplateVariant compoundType() const { return m_classDef->compoundTypeString(); } + TemplateVariant templateDecls() const { return m_cachable.templateDecls.get(this); } + TemplateVariant typeConstraints() const { return m_cachable.typeConstraints.get(this); } + TemplateVariant examples() const { return m_cachable.examples.get(this); } + TemplateVariant members() const { return m_cachable.members.get(this); } + TemplateVariant allMembersList() const { return m_cachable.allMembersList.get(this); } + TemplateVariant allMembersFileName() const { return m_classDef->getMemberListFileName(); } + TemplateVariant memberGroups() const { return m_cachable.memberGroups.get(this); } + TemplateVariant additionalInheritedMembers() const { return m_cachable.additionalInheritedMembers.get(this); } + TemplateVariant isSimple() const { return m_classDef->isSimple(); } + TemplateVariant categoryOf() const { return m_cachable.categoryOf.get(this); } + TemplateVariant hasInheritanceDiagram() const { bool result=FALSE; - static bool haveDot = Config_getBool(HAVE_DOT); - static bool classDiagrams = Config_getBool(CLASS_DIAGRAMS); - static bool classGraph = Config_getBool(CLASS_GRAPH); - if (haveDot && (classDiagrams || classGraph)) + static bool haveDot = Config_getBool(HAVE_DOT); + static auto classGraph = Config_getEnum(CLASS_GRAPH); + bool classGraphEnabled = classGraph==CLASS_GRAPH_t::YES || classGraph==CLASS_GRAPH_t::GRAPH; + + if (haveDot && classGraphEnabled) { - DotClassGraph *cg = getClassGraph(); + DotClassGraphPtr cg = getClassGraph(); result = !cg->isTrivial() && !cg->isTooBig(); } - else if (classDiagrams) + else if (classGraphEnabled) { result = numInheritanceNodes()>0; } @@ -2012,19 +1810,20 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private> TemplateVariant inheritanceDiagram() const { TextStream t; - static bool haveDot = Config_getBool(HAVE_DOT); - static bool classDiagrams = Config_getBool(CLASS_DIAGRAMS); - static bool classGraph = Config_getBool(CLASS_GRAPH); - if (haveDot && (classDiagrams || classGraph)) + static bool haveDot = Config_getBool(HAVE_DOT); + static auto classGraph = Config_getEnum(CLASS_GRAPH); + bool classGraphEnabled = classGraph==CLASS_GRAPH_t::YES || classGraph==CLASS_GRAPH_t::GRAPH; + + if (haveDot && classGraphEnabled) { - DotClassGraph *cg = getClassGraph(); + DotClassGraphPtr cg = getClassGraph(); switch (g_globals.outputFormat) { case ContextOutputFormat_Html: { cg->writeGraph(t,GOF_BITMAP,EOF_Html, g_globals.outputDir, - g_globals.outputDir+Portable::pathSeparator()+m_classDef->getOutputFileBase()+Doxygen::htmlFileExtension, + g_globals.outputDir+Portable::pathSeparator()+addHtmlExtensionIfMissing(m_classDef->getOutputFileBase()), relPathAsString(),TRUE,TRUE,g_globals.dynSectionId ); } @@ -2045,7 +1844,7 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private> } g_globals.dynSectionId++; } - else if (classDiagrams) + else if (classGraphEnabled) { ClassDiagram d(m_classDef); switch (g_globals.outputFormat) @@ -2093,14 +1892,9 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private> } return TemplateVariant(t.str().c_str(),TRUE); } - DotClassGraph *getCollaborationGraph() const + DotClassGraphPtr getCollaborationGraph() const { - Cachable &cache = getCache(); - if (!cache.collaborationGraph) - { - cache.collaborationGraph.reset(new DotClassGraph(m_classDef,Collaboration)); - } - return cache.collaborationGraph.get(); + return m_cachable.collaborationGraph.get(this); } TemplateVariant hasCollaborationDiagram() const { @@ -2113,14 +1907,14 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private> TextStream t; if (haveDot) { - DotClassGraph *cg = getCollaborationGraph(); + DotClassGraphPtr cg = getCollaborationGraph(); switch (g_globals.outputFormat) { case ContextOutputFormat_Html: { cg->writeGraph(t,GOF_BITMAP,EOF_Html, g_globals.outputDir, - g_globals.outputDir+Portable::pathSeparator()+m_classDef->getOutputFileBase()+Doxygen::htmlFileExtension, + g_globals.outputDir+Portable::pathSeparator()+addHtmlExtensionIfMissing(m_classDef->getOutputFileBase()), relPathAsString(),TRUE,TRUE,g_globals.dynSectionId ); } @@ -2144,267 +1938,270 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private> return TemplateVariant(t.str().c_str(),TRUE); } - TemplateVariant includeInfo() const + + private: + + TemplateVariant createIncludeInfo() const { - Cachable &cache = getCache(); - if (!cache.includeInfo && m_classDef->includeInfo()) - { - cache.includeInfo.reset(IncludeInfoContext::alloc(m_classDef->includeInfo(),m_classDef->getLanguage())); - } - if (cache.includeInfo) - { - return cache.includeInfo.get(); - } - else - { - return TemplateVariant(FALSE); - } + return m_classDef->includeInfo() ? + IncludeInfoContext::alloc(m_classDef->includeInfo(),m_classDef->getLanguage()) : + TemplateVariant(false); } - TemplateVariant inherits() const + TemplateVariant createInheritsList() const { - Cachable &cache = getCache(); - if (!cache.inheritsList) - { - cache.inheritsList.reset(InheritanceListContext::alloc(m_classDef->baseClasses(),TRUE)); - } - return cache.inheritsList.get(); + return InheritanceListContext::alloc(m_classDef->baseClasses(),TRUE); } - TemplateVariant inheritedBy() const + TemplateVariant createInheritedByList() const { - Cachable &cache = getCache(); - if (!cache.inheritedByList) - { - cache.inheritedByList.reset(InheritanceListContext::alloc(m_classDef->subClasses(),FALSE)); - } - return cache.inheritedByList.get(); + return InheritanceListContext::alloc(m_classDef->subClasses(),FALSE); + } + DotClassGraphPtr createClassGraph() const + { + return std::make_shared<DotClassGraph>(m_classDef,Inheritance); } - TemplateVariant getMemberList(SharedPtr<MemberListInfoContext> &list, - MemberListType type,const QCString &title,bool=FALSE) const + DotClassGraphPtr createCollaborationGraph() const { - if (!list) + return std::make_shared<DotClassGraph>(m_classDef,Collaboration); + } + TemplateVariant createClasses() const + { + TemplateVariantList classList; + classList.reserve(m_classDef->getClasses().size()); + for (const auto &cd : m_classDef->getClasses()) { - const MemberList *ml = m_classDef->getMemberList(type); - if (ml) + if (cd->visibleInParentsDeclList()) { - list.reset(MemberListInfoContext::alloc(m_classDef,relPathAsString(),ml,title,"")); + classList.push_back(ClassContext::alloc(cd)); } } - if (list) - { - return list.get(); - } - else - { - return TemplateVariant(FALSE); - } - } - TemplateVariant unoIDLServices() const - { - return getMemberList(getCache().unoIDLServices,MemberListType_services,theTranslator->trServices()); + return TemplateImmutableList::alloc(classList); } - TemplateVariant unoIDLInterfaces() const + TemplateVariant createInnerClasses() const { - return getMemberList(getCache().unoIDLInterfaces,MemberListType_interfaces,theTranslator->trInterfaces()); + TemplateVariantList classList; + classList.reserve(m_classDef->getClasses().size()); + for (const auto &cd : m_classDef->getClasses()) + { + if (!cd->isAnonymous() && + cd->isLinkableInProject() && + cd->isEmbeddedInOuterScope() && + cd->partOfGroups().empty() + ) + { + classList.push_back(ClassContext::alloc(cd)); + } + } + return TemplateImmutableList::alloc(classList); } - TemplateVariant signals() const + TemplateVariant createMemberList(MemberListType type,const QCString &title) const { - return getMemberList(getCache().signals,MemberListType_signals,theTranslator->trSignals()); + const MemberList *ml = m_classDef->getMemberList(type); + return ml ? TemplateVariant(MemberListInfoContext::alloc(m_classDef,relPathAsString(),ml,title,"")) + : TemplateVariant(false); } - TemplateVariant publicTypes() const + TemplateVariant createPublicTypes() const { - return getMemberList(getCache().publicTypes,MemberListType_pubTypes,theTranslator->trPublicTypes()); + return createMemberList(MemberListType_pubTypes,theTranslator->trPublicTypes()); } - TemplateVariant publicMethods() const + TemplateVariant createPublicMethods() const { - return getMemberList(getCache().publicMethods,MemberListType_pubMethods, + return createMemberList(MemberListType_pubMethods, m_classDef->getLanguage()==SrcLangExt_ObjC ? theTranslator->trInstanceMethods() : theTranslator->trPublicMembers()); } - TemplateVariant publicStaticMethods() const + TemplateVariant createPublicStaticMethods() const { - return getMemberList(getCache().publicStaticMethods,MemberListType_pubStaticMethods, + return createMemberList(MemberListType_pubStaticMethods, m_classDef->getLanguage()==SrcLangExt_ObjC ? theTranslator->trClassMethods() : theTranslator->trStaticPublicMembers()); } - TemplateVariant publicAttributes() const + TemplateVariant createPublicAttributes() const { - return getMemberList(getCache().publicAttributes,MemberListType_pubAttribs,theTranslator->trPublicAttribs()); + return createMemberList(MemberListType_pubAttribs,theTranslator->trPublicAttribs()); } - TemplateVariant publicStaticAttributes() const + TemplateVariant createPublicStaticAttributes() const { - return getMemberList(getCache().publicStaticAttributes,MemberListType_pubStaticAttribs,theTranslator->trStaticPublicAttribs()); + return createMemberList(MemberListType_pubStaticAttribs,theTranslator->trStaticPublicAttribs()); } - TemplateVariant publicSlots() const + TemplateVariant createPublicSlots() const { - return getMemberList(getCache().publicSlots,MemberListType_pubSlots,theTranslator->trPublicSlots()); + return createMemberList(MemberListType_pubSlots,theTranslator->trPublicSlots()); } - TemplateVariant protectedTypes() const + TemplateVariant createUnoIDLServices() const { - return getMemberList(getCache().protectedTypes,MemberListType_proTypes,theTranslator->trProtectedTypes()); + return createMemberList(MemberListType_services,theTranslator->trServices()); } - TemplateVariant protectedMethods() const + TemplateVariant createUnoIDLInterfaces() const { - return getMemberList(getCache().protectedMethods,MemberListType_proMethods,theTranslator->trProtectedMembers()); + return createMemberList(MemberListType_interfaces,theTranslator->trInterfaces()); } - TemplateVariant protectedStaticMethods() const + TemplateVariant createSignals() const { - return getMemberList(getCache().protectedStaticMethods,MemberListType_proStaticMethods,theTranslator->trStaticProtectedMembers()); + return createMemberList(MemberListType_signals,theTranslator->trSignals()); } - TemplateVariant protectedAttributes() const + TemplateVariant createProtectedTypes() const { - return getMemberList(getCache().protectedAttributes,MemberListType_proAttribs,theTranslator->trProtectedAttribs()); + return createMemberList(MemberListType_proTypes,theTranslator->trProtectedTypes()); } - TemplateVariant protectedStaticAttributes() const + TemplateVariant createProtectedMethods() const { - return getMemberList(getCache().protectedStaticAttributes,MemberListType_proStaticAttribs,theTranslator->trStaticProtectedAttribs()); + return createMemberList(MemberListType_proMethods,theTranslator->trProtectedMembers()); } - TemplateVariant protectedSlots() const + TemplateVariant createProtectedStaticMethods() const { - return getMemberList(getCache().protectedSlots,MemberListType_proSlots,theTranslator->trProtectedSlots()); + return createMemberList(MemberListType_proStaticMethods,theTranslator->trStaticProtectedMembers()); } - TemplateVariant privateTypes() const + TemplateVariant createProtectedAttributes() const { - return getMemberList(getCache().privateTypes,MemberListType_priTypes,theTranslator->trPrivateTypes()); + return createMemberList(MemberListType_proAttribs,theTranslator->trProtectedAttribs()); } - TemplateVariant privateSlots() const + TemplateVariant createProtectedStaticAttributes() const { - return getMemberList(getCache().privateSlots,MemberListType_priSlots,theTranslator->trPrivateSlots()); + return createMemberList(MemberListType_proStaticAttribs,theTranslator->trStaticProtectedAttribs()); } - TemplateVariant privateMethods() const + TemplateVariant createProtectedSlots() const { - return getMemberList(getCache().privateMethods,MemberListType_priMethods,theTranslator->trPrivateMembers()); + return createMemberList(MemberListType_proSlots,theTranslator->trProtectedSlots()); } - TemplateVariant privateStaticMethods() const + TemplateVariant createPrivateTypes() const { - return getMemberList(getCache().privateStaticMethods,MemberListType_priStaticMethods,theTranslator->trStaticPrivateMembers()); + return createMemberList(MemberListType_priTypes,theTranslator->trPrivateTypes()); } - TemplateVariant privateAttributes() const + TemplateVariant createPrivateSlots() const { - return getMemberList(getCache().privateAttributes,MemberListType_priAttribs,theTranslator->trPrivateAttribs()); + return createMemberList(MemberListType_priSlots,theTranslator->trPrivateSlots()); } - TemplateVariant privateStaticAttributes() const + TemplateVariant createPrivateMethods() const { - return getMemberList(getCache().privateStaticAttributes,MemberListType_priStaticAttribs,theTranslator->trStaticPrivateAttribs()); + return createMemberList(MemberListType_priMethods,theTranslator->trPrivateMembers()); } - TemplateVariant packageTypes() const + TemplateVariant createPrivateStaticMethods() const { - return getMemberList(getCache().packageTypes,MemberListType_pacTypes,theTranslator->trPackageTypes()); + return createMemberList(MemberListType_priStaticMethods,theTranslator->trStaticPrivateMembers()); } - TemplateVariant packageMethods() const + TemplateVariant createPrivateAttributes() const { - return getMemberList(getCache().packageMethods,MemberListType_pacMethods,theTranslator->trPackageMembers()); + return createMemberList(MemberListType_priAttribs,theTranslator->trPrivateAttribs()); } - TemplateVariant packageStaticMethods() const + TemplateVariant createPrivateStaticAttributes() const { - return getMemberList(getCache().packageStaticMethods,MemberListType_pacStaticMethods,theTranslator->trStaticPackageMembers()); + return createMemberList(MemberListType_priStaticAttribs,theTranslator->trStaticPrivateAttribs()); } - TemplateVariant packageAttributes() const + TemplateVariant createPackageTypes() const { - return getMemberList(getCache().packageAttributes,MemberListType_pacAttribs,theTranslator->trPackageAttribs()); + return createMemberList(MemberListType_pacTypes,theTranslator->trPackageTypes()); } - TemplateVariant packageStaticAttributes() const + TemplateVariant createPackageMethods() const { - return getMemberList(getCache().packageStaticAttributes,MemberListType_pacStaticAttribs,theTranslator->trStaticPackageAttribs()); + return createMemberList(MemberListType_pacMethods,theTranslator->trPackageMembers()); } - TemplateVariant properties() const + TemplateVariant createPackageStaticMethods() const { - return getMemberList(getCache().properties,MemberListType_properties,theTranslator->trProperties()); + return createMemberList(MemberListType_pacStaticMethods,theTranslator->trStaticPackageMembers()); } - TemplateVariant events() const + TemplateVariant createPackageAttributes() const { - return getMemberList(getCache().events,MemberListType_events,theTranslator->trEvents()); + return createMemberList(MemberListType_pacAttribs,theTranslator->trPackageAttribs()); } - TemplateVariant friends() const + TemplateVariant createPackageStaticAttributes() const { - return getMemberList(getCache().friends,MemberListType_friends,theTranslator->trFriends()); + return createMemberList(MemberListType_pacStaticAttribs,theTranslator->trStaticPackageAttribs()); } - TemplateVariant related() const + TemplateVariant createProperties() const { - return getMemberList(getCache().related,MemberListType_related,theTranslator->trRelatedFunctions()); + return createMemberList(MemberListType_properties,theTranslator->trProperties()); } - TemplateVariant detailedTypedefs() const + TemplateVariant createEvents() const { - return getMemberList(getCache().detailedTypedefs,MemberListType_typedefMembers,theTranslator->trMemberTypedefDocumentation(),TRUE); + return createMemberList(MemberListType_events,theTranslator->trEvents()); } - TemplateVariant detailedEnums() const + TemplateVariant createFriends() const { - return getMemberList(getCache().detailedEnums,MemberListType_enumMembers,theTranslator->trMemberEnumerationDocumentation(),TRUE); + return createMemberList(MemberListType_friends,theTranslator->trFriends()); } - TemplateVariant detailedServices() const + TemplateVariant createRelated() const { - return getMemberList(getCache().detailedServices,MemberListType_serviceMembers,theTranslator->trServices(),TRUE); + return createMemberList(MemberListType_related,theTranslator->trRelatedFunctions()); } - TemplateVariant detailedInterfaces() const + TemplateVariant createDetailedTypedefs() const { - return getMemberList(getCache().detailedInterfaces,MemberListType_interfaceMembers,theTranslator->trInterfaces(),TRUE); + return createMemberList(MemberListType_typedefMembers,theTranslator->trMemberTypedefDocumentation()); } - TemplateVariant detailedConstructors() const + TemplateVariant createDetailedEnums() const { - return getMemberList(getCache().detailedConstructors,MemberListType_constructors,theTranslator->trConstructorDocumentation(),TRUE); + return createMemberList(MemberListType_enumMembers,theTranslator->trMemberEnumerationDocumentation()); } - TemplateVariant detailedMethods() const + TemplateVariant createDetailedServices() const { - return getMemberList(getCache().detailedMethods,MemberListType_functionMembers,theTranslator->trMemberFunctionDocumentation(),TRUE); + return createMemberList(MemberListType_serviceMembers,theTranslator->trServices()); } - TemplateVariant detailedRelated() const + TemplateVariant createDetailedInterfaces() const { - return getMemberList(getCache().detailedRelated,MemberListType_relatedMembers,theTranslator->trRelatedFunctionDocumentation(),TRUE); + return createMemberList(MemberListType_interfaceMembers,theTranslator->trInterfaces()); } - TemplateVariant detailedVariables() const + TemplateVariant createDetailedConstructors() const { - return getMemberList(getCache().detailedVariables,MemberListType_variableMembers,theTranslator->trMemberDataDocumentation(),TRUE); + return createMemberList(MemberListType_constructors,theTranslator->trConstructorDocumentation()); } - TemplateVariant detailedProperties() const + TemplateVariant createDetailedMethods() const { - return getMemberList(getCache().detailedProperties,MemberListType_propertyMembers,theTranslator->trPropertyDocumentation(),TRUE); + return createMemberList(MemberListType_functionMembers,theTranslator->trMemberFunctionDocumentation()); } - TemplateVariant detailedEvents() const + TemplateVariant createDetailedRelated() const { - return getMemberList(getCache().detailedEvents,MemberListType_eventMembers,theTranslator->trEventDocumentation(),TRUE); + return createMemberList(MemberListType_relatedMembers,theTranslator->trRelatedFunctionDocumentation()); } - TemplateVariant classes() const + TemplateVariant createDetailedVariables() const { - Cachable &cache = getCache(); - if (!cache.classes) - { - TemplateList *classList = TemplateList::alloc(); - for (const auto &cd : m_classDef->getClasses()) - { - if (cd->visibleInParentsDeclList()) - { - classList->append(ClassContext::alloc(cd)); - } - } - cache.classes.reset(classList); - } - return cache.classes.get(); + return createMemberList(MemberListType_variableMembers,theTranslator->trMemberDataDocumentation()); } - TemplateVariant innerClasses() const + TemplateVariant createDetailedProperties() const { - Cachable &cache = getCache(); - if (!cache.innerClasses) + return createMemberList(MemberListType_propertyMembers,theTranslator->trPropertyDocumentation()); + } + TemplateVariant createDetailedEvents() const + { + return createMemberList(MemberListType_eventMembers,theTranslator->trEventDocumentation()); + } + TemplateVariant createMemberGroups() const + { + return !m_classDef->getMemberGroups().empty() ? + MemberGroupListContext::alloc(m_classDef,relPathAsString(),m_classDef->getMemberGroups(),m_classDef->subGrouping()) : + MemberGroupListContext::alloc(); + } + TemplateVariant createAllMembersList() const + { + return AllMembersListContext::alloc(m_classDef->memberNameInfoLinkedMap()); + } + TemplateVariant createTypeConstraints() const + { + return !m_classDef->typeConstraints().empty() ? + TemplateVariant(ArgumentListContext::alloc(m_classDef->typeConstraints(),m_classDef,relPathAsString())) : + TemplateVariant(false); + } + TemplateVariant createExamples() const + { + TemplateVariantList list; + list.reserve(m_classDef->getExamples().size()); + if (m_classDef->hasExamples()) { - TemplateList *classList = TemplateList::alloc(); - for (const auto &cd : m_classDef->getClasses()) + for (const auto &ex : m_classDef->getExamples()) { - if (!cd->isAnonymous() && - cd->isLinkableInProject() && - cd->isEmbeddedInOuterScope() && - cd->partOfGroups().empty() - ) + TemplateStructIntfPtr s = TemplateImmutableStruct::alloc( { - classList->append(ClassContext::alloc(cd)); - } + { "text", TemplateVariant(ex.name) }, + { "isLinkable", TemplateVariant(TRUE) }, + { "anchor", TemplateVariant(ex.anchor) }, + { "fileName", TemplateVariant(ex.file) }, + { "isReference", TemplateVariant(FALSE) }, + { "externalReference", TemplateVariant("") } + }); + list.push_back(s); } - cache.innerClasses.reset(classList); } - return cache.innerClasses.get(); + return TemplateImmutableList::alloc(list); } - TemplateVariant compoundType() const - { - return m_classDef->compoundTypeString(); - } - void addTemplateDecls(const Definition *d,TemplateList *tl) const + void addTemplateDecls(const Definition *d,TemplateVariantList &tl) const { if (d->definitionType()==Definition::TypeClass) { @@ -2416,300 +2213,267 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private> const ClassDef *cd=toClassDef(d); if (!cd->templateArguments().empty()) { - ArgumentListContext *al = ArgumentListContext::alloc(cd->templateArguments(),cd,relPathAsString()); + TemplateListIntfPtr al = ArgumentListContext::alloc(cd->templateArguments(),cd,relPathAsString()); // since a TemplateVariant does take ownership of the object, we add it // a separate list just to be able to delete it and avoid a memory leak - tl->append(al); - } - } - } - void addExamples(TemplateList *list) const - { - if (m_classDef->hasExamples()) - { - for (const auto &ex : m_classDef->getExamples()) - { - TemplateStruct *s = TemplateStruct::alloc(); - s->set("text",ex.name); - s->set("isLinkable",TRUE); - s->set("anchor",ex.anchor); - s->set("fileName",ex.file); - s->set("isReference",FALSE); - s->set("externalReference",""); - list->append(s); - } - } - } - TemplateVariant templateDecls() const - { - Cachable &cache = getCache(); - if (!cache.templateDecls) - { - TemplateList *tl = TemplateList::alloc(); - addTemplateDecls(m_classDef,tl); - cache.templateDecls.reset(tl); - } - return cache.templateDecls.get(); - } - TemplateVariant typeConstraints() const - { - if (!m_classDef->typeConstraints().empty()) - { - Cachable &cache = getCache(); - if (!cache.typeConstraints && !m_classDef->typeConstraints().empty()) - { - cache.typeConstraints.reset(ArgumentListContext::alloc(m_classDef->typeConstraints(),m_classDef,relPathAsString())); - } - return cache.typeConstraints.get(); - } - return FALSE; - } - TemplateVariant examples() const - { - Cachable &cache = getCache(); - if (!cache.examples) - { - TemplateList *exampleList = TemplateList::alloc(); - addExamples(exampleList); - cache.examples.reset(exampleList); - } - return cache.examples.get(); - } - void addMembers(const ClassDef *cd,MemberListType lt) const + tl.push_back(al); + } + } + } + TemplateVariant createTemplateDecls() const + { + TemplateVariantList tl; + addTemplateDecls(m_classDef,tl); + return TemplateImmutableList::alloc(tl); + } + TemplateVariant createAdditionalInheritedMembers() const + { + TemplateListIntfPtr list = InheritedMemberInfoListContext::alloc(); + auto ctx = std::dynamic_pointer_cast<InheritedMemberInfoListContext>(list); + ctx->addMemberList(m_classDef,MemberListType_pubTypes,theTranslator->trPublicTypes()); + ctx->addMemberList(m_classDef,MemberListType_services,theTranslator->trServices()); + ctx->addMemberList(m_classDef,MemberListType_interfaces,theTranslator->trInterfaces()); + ctx->addMemberList(m_classDef,MemberListType_pubSlots,theTranslator->trPublicSlots()); + ctx->addMemberList(m_classDef,MemberListType_signals,theTranslator->trSignals()); + ctx->addMemberList(m_classDef,MemberListType_pubMethods, + m_classDef->getLanguage()==SrcLangExt_ObjC ? theTranslator->trInstanceMethods() + : theTranslator->trPublicMembers()); + ctx->addMemberList(m_classDef,MemberListType_pubStaticMethods, + m_classDef->getLanguage()==SrcLangExt_ObjC ? theTranslator->trClassMethods() + : theTranslator->trStaticPublicMembers()); + ctx->addMemberList(m_classDef,MemberListType_pubAttribs,theTranslator->trPublicAttribs()); + ctx->addMemberList(m_classDef,MemberListType_pubStaticAttribs,theTranslator->trStaticPublicAttribs()); + ctx->addMemberList(m_classDef,MemberListType_proTypes,theTranslator->trProtectedTypes()); + ctx->addMemberList(m_classDef,MemberListType_proSlots,theTranslator->trProtectedSlots()); + ctx->addMemberList(m_classDef,MemberListType_proMethods,theTranslator->trProtectedMembers()); + ctx->addMemberList(m_classDef,MemberListType_proStaticMethods,theTranslator->trStaticProtectedMembers()); + ctx->addMemberList(m_classDef,MemberListType_proAttribs,theTranslator->trProtectedAttribs()); + ctx->addMemberList(m_classDef,MemberListType_proStaticAttribs,theTranslator->trStaticProtectedAttribs()); + ctx->addMemberList(m_classDef,MemberListType_pacTypes,theTranslator->trPackageTypes()); + ctx->addMemberList(m_classDef,MemberListType_pacMethods,theTranslator->trPackageMembers()); + ctx->addMemberList(m_classDef,MemberListType_pacStaticMethods,theTranslator->trStaticPackageMembers()); + ctx->addMemberList(m_classDef,MemberListType_pacAttribs,theTranslator->trPackageAttribs()); + ctx->addMemberList(m_classDef,MemberListType_pacStaticAttribs,theTranslator->trStaticPackageAttribs()); + ctx->addMemberList(m_classDef,MemberListType_properties,theTranslator->trProperties()); + ctx->addMemberList(m_classDef,MemberListType_events,theTranslator->trEvents()); + ctx->addMemberList(m_classDef,MemberListType_priTypes,theTranslator->trPrivateTypes()); + ctx->addMemberList(m_classDef,MemberListType_priSlots,theTranslator->trPrivateSlots()); + ctx->addMemberList(m_classDef,MemberListType_priMethods,theTranslator->trPrivateMembers()); + ctx->addMemberList(m_classDef,MemberListType_priStaticMethods,theTranslator->trStaticPrivateMembers()); + ctx->addMemberList(m_classDef,MemberListType_priAttribs,theTranslator->trPrivateAttribs()); + ctx->addMemberList(m_classDef,MemberListType_priStaticAttribs,theTranslator->trStaticPrivateAttribs()); + ctx->addMemberList(m_classDef,MemberListType_related,theTranslator->trRelatedFunctions()); + return list; + } + void addMembers(MemberList &list,const ClassDef *cd,MemberListType lt) const { const MemberList *ml = cd->getMemberList(lt); if (ml) { - Cachable &cache = getCache(); for (const auto &md : *ml) { if (md->isBriefSectionVisible()) { - cache.allMembers.push_back(md); + list.push_back(md); } } } } - TemplateVariant members() const - { - Cachable &cache = getCache(); - if (!cache.members) - { - addMembers(m_classDef,MemberListType_pubTypes); - addMembers(m_classDef,MemberListType_services); - addMembers(m_classDef,MemberListType_interfaces); - addMembers(m_classDef,MemberListType_pubSlots); - addMembers(m_classDef,MemberListType_signals); - addMembers(m_classDef,MemberListType_pubMethods); - addMembers(m_classDef,MemberListType_pubStaticMethods); - addMembers(m_classDef,MemberListType_pubAttribs); - addMembers(m_classDef,MemberListType_pubStaticAttribs); - addMembers(m_classDef,MemberListType_proTypes); - addMembers(m_classDef,MemberListType_proSlots); - addMembers(m_classDef,MemberListType_proMethods); - addMembers(m_classDef,MemberListType_proStaticMethods); - addMembers(m_classDef,MemberListType_proAttribs); - addMembers(m_classDef,MemberListType_proStaticAttribs); - addMembers(m_classDef,MemberListType_pacTypes); - addMembers(m_classDef,MemberListType_pacMethods); - addMembers(m_classDef,MemberListType_pacStaticMethods); - addMembers(m_classDef,MemberListType_pacAttribs); - addMembers(m_classDef,MemberListType_pacStaticAttribs); - addMembers(m_classDef,MemberListType_properties); - addMembers(m_classDef,MemberListType_events); - addMembers(m_classDef,MemberListType_priTypes); - addMembers(m_classDef,MemberListType_priSlots); - addMembers(m_classDef,MemberListType_priMethods); - addMembers(m_classDef,MemberListType_priStaticMethods); - addMembers(m_classDef,MemberListType_priAttribs); - addMembers(m_classDef,MemberListType_priStaticAttribs); - addMembers(m_classDef,MemberListType_related); - cache.members.reset(MemberListContext::alloc(&cache.allMembers)); - } - return cache.members.get(); - } - TemplateVariant allMembersList() const - { - Cachable &cache = getCache(); - if (!cache.allMembersList) - { - AllMembersListContext *ml = AllMembersListContext::alloc(m_classDef->memberNameInfoLinkedMap()); - cache.allMembersList.reset(ml); - } - return cache.allMembersList.get(); - } - TemplateVariant allMembersFileName() const - { - return m_classDef->getMemberListFileName(); - } - TemplateVariant memberGroups() const - { - Cachable &cache = getCache(); - if (!cache.memberGroups) - { - if (!m_classDef->getMemberGroups().empty()) - { - cache.memberGroups.reset(MemberGroupListContext::alloc(m_classDef,relPathAsString(),m_classDef->getMemberGroups(),m_classDef->subGrouping())); - } - else - { - cache.memberGroups.reset(MemberGroupListContext::alloc()); - } - } - return cache.memberGroups.get(); - } - TemplateVariant additionalInheritedMembers() const - { - Cachable &cache = getCache(); - if (!cache.additionalInheritedMembers) - { - InheritedMemberInfoListContext *ctx = InheritedMemberInfoListContext::alloc(); - ctx->addMemberList(m_classDef,MemberListType_pubTypes,theTranslator->trPublicTypes()); - ctx->addMemberList(m_classDef,MemberListType_services,theTranslator->trServices()); - ctx->addMemberList(m_classDef,MemberListType_interfaces,theTranslator->trInterfaces()); - ctx->addMemberList(m_classDef,MemberListType_pubSlots,theTranslator->trPublicSlots()); - ctx->addMemberList(m_classDef,MemberListType_signals,theTranslator->trSignals()); - ctx->addMemberList(m_classDef,MemberListType_pubMethods, - m_classDef->getLanguage()==SrcLangExt_ObjC ? theTranslator->trInstanceMethods() - : theTranslator->trPublicMembers()); - ctx->addMemberList(m_classDef,MemberListType_pubStaticMethods, - m_classDef->getLanguage()==SrcLangExt_ObjC ? theTranslator->trClassMethods() - : theTranslator->trStaticPublicMembers()); - ctx->addMemberList(m_classDef,MemberListType_pubAttribs,theTranslator->trPublicAttribs()); - ctx->addMemberList(m_classDef,MemberListType_pubStaticAttribs,theTranslator->trStaticPublicAttribs()); - ctx->addMemberList(m_classDef,MemberListType_proTypes,theTranslator->trProtectedTypes()); - ctx->addMemberList(m_classDef,MemberListType_proSlots,theTranslator->trProtectedSlots()); - ctx->addMemberList(m_classDef,MemberListType_proMethods,theTranslator->trProtectedMembers()); - ctx->addMemberList(m_classDef,MemberListType_proStaticMethods,theTranslator->trStaticProtectedMembers()); - ctx->addMemberList(m_classDef,MemberListType_proAttribs,theTranslator->trProtectedAttribs()); - ctx->addMemberList(m_classDef,MemberListType_proStaticAttribs,theTranslator->trStaticProtectedAttribs()); - ctx->addMemberList(m_classDef,MemberListType_pacTypes,theTranslator->trPackageTypes()); - ctx->addMemberList(m_classDef,MemberListType_pacMethods,theTranslator->trPackageMembers()); - ctx->addMemberList(m_classDef,MemberListType_pacStaticMethods,theTranslator->trStaticPackageMembers()); - ctx->addMemberList(m_classDef,MemberListType_pacAttribs,theTranslator->trPackageAttribs()); - ctx->addMemberList(m_classDef,MemberListType_pacStaticAttribs,theTranslator->trStaticPackageAttribs()); - ctx->addMemberList(m_classDef,MemberListType_properties,theTranslator->trProperties()); - ctx->addMemberList(m_classDef,MemberListType_events,theTranslator->trEvents()); - ctx->addMemberList(m_classDef,MemberListType_priTypes,theTranslator->trPrivateTypes()); - ctx->addMemberList(m_classDef,MemberListType_priSlots,theTranslator->trPrivateSlots()); - ctx->addMemberList(m_classDef,MemberListType_priMethods,theTranslator->trPrivateMembers()); - ctx->addMemberList(m_classDef,MemberListType_priStaticMethods,theTranslator->trStaticPrivateMembers()); - ctx->addMemberList(m_classDef,MemberListType_priAttribs,theTranslator->trPrivateAttribs()); - ctx->addMemberList(m_classDef,MemberListType_priStaticAttribs,theTranslator->trStaticPrivateAttribs()); - ctx->addMemberList(m_classDef,MemberListType_related,theTranslator->trRelatedFunctions()); - cache.additionalInheritedMembers.reset(ctx); - } - return cache.additionalInheritedMembers.get(); - } - TemplateVariant isSimple() const - { - return m_classDef->isSimple(); - } - TemplateVariant categoryOf() const - { - Cachable &cache = getCache(); - if (!cache.categoryOf && m_classDef->categoryOf()) - { - cache.categoryOf.reset(ClassContext::alloc(m_classDef->categoryOf())); - } - if (cache.categoryOf) - { - return cache.categoryOf.get(); - } - else - { - return TemplateVariant(FALSE); - } + TemplateVariant createMembers() const + { + MemberList list(MemberListType_allMembersList,MemberListContainer::Class); + addMembers(list,m_classDef,MemberListType_pubTypes); + addMembers(list,m_classDef,MemberListType_services); + addMembers(list,m_classDef,MemberListType_interfaces); + addMembers(list,m_classDef,MemberListType_pubSlots); + addMembers(list,m_classDef,MemberListType_signals); + addMembers(list,m_classDef,MemberListType_pubMethods); + addMembers(list,m_classDef,MemberListType_pubStaticMethods); + addMembers(list,m_classDef,MemberListType_pubAttribs); + addMembers(list,m_classDef,MemberListType_pubStaticAttribs); + addMembers(list,m_classDef,MemberListType_proTypes); + addMembers(list,m_classDef,MemberListType_proSlots); + addMembers(list,m_classDef,MemberListType_proMethods); + addMembers(list,m_classDef,MemberListType_proStaticMethods); + addMembers(list,m_classDef,MemberListType_proAttribs); + addMembers(list,m_classDef,MemberListType_proStaticAttribs); + addMembers(list,m_classDef,MemberListType_pacTypes); + addMembers(list,m_classDef,MemberListType_pacMethods); + addMembers(list,m_classDef,MemberListType_pacStaticMethods); + addMembers(list,m_classDef,MemberListType_pacAttribs); + addMembers(list,m_classDef,MemberListType_pacStaticAttribs); + addMembers(list,m_classDef,MemberListType_properties); + addMembers(list,m_classDef,MemberListType_events); + addMembers(list,m_classDef,MemberListType_priTypes); + addMembers(list,m_classDef,MemberListType_priSlots); + addMembers(list,m_classDef,MemberListType_priMethods); + addMembers(list,m_classDef,MemberListType_priStaticMethods); + addMembers(list,m_classDef,MemberListType_priAttribs); + addMembers(list,m_classDef,MemberListType_priStaticAttribs); + addMembers(list,m_classDef,MemberListType_related); + return MemberListContext::alloc(list); + } + TemplateVariant createUsedFiles() const + { + return UsedFilesContext::alloc(m_classDef); + } + TemplateVariant createCategoryOf() const + { + return m_classDef->categoryOf() ? + TemplateVariant(ClassContext::alloc(m_classDef->categoryOf())) : + TemplateVariant(FALSE); + } + int createNumInheritanceNodes() const + { + return m_classDef->countInheritanceNodes(); } - private: const ClassDef *m_classDef; struct Cachable : public DefinitionContext<ClassContext::Private>::Cachable { - Cachable(const ClassDef *cd) : DefinitionContext<ClassContext::Private>::Cachable(cd), - inheritanceNodes(-1), - allMembers(MemberListType_allMembersList,MemberListContainer::Class) { } - SharedPtr<IncludeInfoContext> includeInfo; - SharedPtr<InheritanceListContext> inheritsList; - SharedPtr<InheritanceListContext> inheritedByList; - std::unique_ptr<DotClassGraph> classGraph; - std::unique_ptr<DotClassGraph> collaborationGraph; - SharedPtr<TemplateList> classes; - SharedPtr<TemplateList> innerClasses; - SharedPtr<MemberListInfoContext> publicTypes; - SharedPtr<MemberListInfoContext> publicMethods; - SharedPtr<MemberListInfoContext> publicStaticMethods; - SharedPtr<MemberListInfoContext> publicAttributes; - SharedPtr<MemberListInfoContext> publicStaticAttributes; - SharedPtr<MemberListInfoContext> publicSlots; - SharedPtr<MemberListInfoContext> protectedTypes; - SharedPtr<MemberListInfoContext> protectedMethods; - SharedPtr<MemberListInfoContext> protectedStaticMethods; - SharedPtr<MemberListInfoContext> protectedAttributes; - SharedPtr<MemberListInfoContext> protectedStaticAttributes; - SharedPtr<MemberListInfoContext> protectedSlots; - SharedPtr<MemberListInfoContext> privateTypes; - SharedPtr<MemberListInfoContext> privateMethods; - SharedPtr<MemberListInfoContext> privateStaticMethods; - SharedPtr<MemberListInfoContext> privateAttributes; - SharedPtr<MemberListInfoContext> privateStaticAttributes; - SharedPtr<MemberListInfoContext> privateSlots; - SharedPtr<MemberListInfoContext> packageTypes; - SharedPtr<MemberListInfoContext> packageMethods; - SharedPtr<MemberListInfoContext> packageStaticMethods; - SharedPtr<MemberListInfoContext> packageAttributes; - SharedPtr<MemberListInfoContext> packageStaticAttributes; - SharedPtr<MemberListInfoContext> unoIDLServices; - SharedPtr<MemberListInfoContext> unoIDLInterfaces; - SharedPtr<MemberListInfoContext> signals; - SharedPtr<MemberListInfoContext> properties; - SharedPtr<MemberListInfoContext> events; - SharedPtr<MemberListInfoContext> friends; - SharedPtr<MemberListInfoContext> related; - SharedPtr<MemberListInfoContext> detailedTypedefs; - SharedPtr<MemberListInfoContext> detailedEnums; - SharedPtr<MemberListInfoContext> detailedServices; - SharedPtr<MemberListInfoContext> detailedInterfaces; - SharedPtr<MemberListInfoContext> detailedConstructors; - SharedPtr<MemberListInfoContext> detailedMethods; - SharedPtr<MemberListInfoContext> detailedRelated; - SharedPtr<MemberListInfoContext> detailedVariables; - SharedPtr<MemberListInfoContext> detailedProperties; - SharedPtr<MemberListInfoContext> detailedEvents; - SharedPtr<MemberGroupListContext> memberGroups; - SharedPtr<AllMembersListContext> allMembersList; - SharedPtr<ArgumentListContext> typeConstraints; - SharedPtr<TemplateList> examples; - SharedPtr<TemplateList> templateDecls; - SharedPtr<InheritedMemberInfoListContext> additionalInheritedMembers; - SharedPtr<MemberListContext> members; - SharedPtr<UsedFilesContext> usedFiles; - SharedPtr<TemplateList> exampleList; - SharedPtr<ClassContext> categoryOf; - int inheritanceNodes; - MemberList allMembers; + CachedItem<TemplateVariant, Private, &Private::createIncludeInfo> includeInfo; + CachedItem<TemplateVariant, Private, &Private::createInheritsList> inheritsList; + CachedItem<TemplateVariant, Private, &Private::createInheritedByList> inheritedByList; + CachedItem<DotClassGraphPtr, Private, &Private::createClassGraph> classGraph; + CachedItem<DotClassGraphPtr, Private, &Private::createCollaborationGraph> collaborationGraph; + CachedItem<TemplateVariant, Private, &Private::createClasses> classes; + CachedItem<TemplateVariant, Private, &Private::createInnerClasses> innerClasses; + CachedItem<TemplateVariant, Private, &Private::createPublicTypes> publicTypes; + CachedItem<TemplateVariant, Private, &Private::createPublicMethods> publicMethods; + CachedItem<TemplateVariant, Private, &Private::createPublicStaticMethods> publicStaticMethods; + CachedItem<TemplateVariant, Private, &Private::createPublicAttributes> publicAttributes; + CachedItem<TemplateVariant, Private, &Private::createPublicStaticAttributes> publicStaticAttributes; + CachedItem<TemplateVariant, Private, &Private::createPublicSlots> publicSlots; + CachedItem<TemplateVariant, Private, &Private::createProtectedTypes> protectedTypes; + CachedItem<TemplateVariant, Private, &Private::createProtectedMethods> protectedMethods; + CachedItem<TemplateVariant, Private, &Private::createProtectedStaticMethods> protectedStaticMethods; + CachedItem<TemplateVariant, Private, &Private::createProtectedAttributes> protectedAttributes; + CachedItem<TemplateVariant, Private, &Private::createProtectedStaticAttributes> protectedStaticAttributes; + CachedItem<TemplateVariant, Private, &Private::createProtectedSlots> protectedSlots; + CachedItem<TemplateVariant, Private, &Private::createPrivateTypes> privateTypes; + CachedItem<TemplateVariant, Private, &Private::createPrivateMethods> privateMethods; + CachedItem<TemplateVariant, Private, &Private::createPrivateStaticMethods> privateStaticMethods; + CachedItem<TemplateVariant, Private, &Private::createPrivateAttributes> privateAttributes; + CachedItem<TemplateVariant, Private, &Private::createPrivateStaticAttributes> privateStaticAttributes; + CachedItem<TemplateVariant, Private, &Private::createPrivateSlots> privateSlots; + CachedItem<TemplateVariant, Private, &Private::createPackageTypes> packageTypes; + CachedItem<TemplateVariant, Private, &Private::createPackageMethods> packageMethods; + CachedItem<TemplateVariant, Private, &Private::createPackageStaticMethods> packageStaticMethods; + CachedItem<TemplateVariant, Private, &Private::createPackageAttributes> packageAttributes; + CachedItem<TemplateVariant, Private, &Private::createPackageStaticAttributes> packageStaticAttributes; + CachedItem<TemplateVariant, Private, &Private::createUnoIDLServices> unoIDLServices; + CachedItem<TemplateVariant, Private, &Private::createUnoIDLInterfaces> unoIDLInterfaces; + CachedItem<TemplateVariant, Private, &Private::createSignals> signals; + CachedItem<TemplateVariant, Private, &Private::createProperties> properties; + CachedItem<TemplateVariant, Private, &Private::createEvents> events; + CachedItem<TemplateVariant, Private, &Private::createFriends> friends; + CachedItem<TemplateVariant, Private, &Private::createRelated> related; + CachedItem<TemplateVariant, Private, &Private::createDetailedTypedefs> detailedTypedefs; + CachedItem<TemplateVariant, Private, &Private::createDetailedEnums> detailedEnums; + CachedItem<TemplateVariant, Private, &Private::createDetailedServices> detailedServices; + CachedItem<TemplateVariant, Private, &Private::createDetailedInterfaces> detailedInterfaces; + CachedItem<TemplateVariant, Private, &Private::createDetailedConstructors> detailedConstructors; + CachedItem<TemplateVariant, Private, &Private::createDetailedMethods> detailedMethods; + CachedItem<TemplateVariant, Private, &Private::createDetailedRelated> detailedRelated; + CachedItem<TemplateVariant, Private, &Private::createDetailedVariables> detailedVariables; + CachedItem<TemplateVariant, Private, &Private::createDetailedProperties> detailedProperties; + CachedItem<TemplateVariant, Private, &Private::createDetailedEvents> detailedEvents; + CachedItem<TemplateVariant, Private, &Private::createMemberGroups> memberGroups; + CachedItem<TemplateVariant, Private, &Private::createAllMembersList> allMembersList; + CachedItem<TemplateVariant, Private, &Private::createTypeConstraints> typeConstraints; + CachedItem<TemplateVariant, Private, &Private::createExamples> examples; + CachedItem<TemplateVariant, Private, &Private::createTemplateDecls> templateDecls; + CachedItem<TemplateVariant, Private, &Private::createAdditionalInheritedMembers> additionalInheritedMembers; + CachedItem<TemplateVariant, Private, &Private::createMembers> members; + CachedItem<TemplateVariant, Private, &Private::createUsedFiles> usedFiles; + CachedItem<TemplateVariant, Private, &Private::createCategoryOf> categoryOf; + CachedItem<int, Private, &Private::createNumInheritanceNodes> numInheritanceNodes; }; - Cachable &getCache() const - { - Cachable *c = static_cast<Cachable*>(m_classDef->cookie()); - assert(c!=0); - return *c; - } - static PropertyMapper<ClassContext::Private> s_inst; + Cachable m_cachable; + static const PropertyMap<ClassContext::Private> s_inst; +}; + +//%% struct Class(Symbol): class information +//%% { +const PropertyMap<ClassContext::Private> ClassContext::Private::s_inst { + BASE_PROPERTIES, + { "title", &Private::title }, + { "highlight", &Private::highlight }, + { "subhighlight", &Private::subHighlight }, + { "hasDetails", &Private::hasDetails }, + { "generatedFromFiles", &Private::generatedFromFiles }, + { "usedFiles", &Private::usedFiles }, + { "hasInheritanceDiagram", &Private::hasInheritanceDiagram }, + { "inheritanceDiagram", &Private::inheritanceDiagram }, + { "hasCollaborationDiagram", &Private::hasCollaborationDiagram }, + { "collaborationDiagram", &Private::collaborationDiagram }, + { "includeInfo", &Private::includeInfo }, + { "inherits", &Private::inherits }, + { "inheritedBy", &Private::inheritedBy }, + { "unoIDLServices", &Private::unoIDLServices }, + { "unoIDLInterfaces", &Private::unoIDLInterfaces }, + { "signals", &Private::signals }, + { "publicTypes", &Private::publicTypes }, + { "publicMethods", &Private::publicMethods }, + { "publicStaticMethods", &Private::publicStaticMethods }, + { "publicAttributes", &Private::publicAttributes }, + { "publicStaticAttributes", &Private::publicStaticAttributes }, + { "publicSlots", &Private::publicSlots }, + { "protectedTypes", &Private::protectedTypes }, + { "protectedMethods", &Private::protectedMethods }, + { "protectedStaticMethods", &Private::protectedStaticMethods }, + { "protectedAttributes", &Private::protectedAttributes }, + { "protectedStaticAttributes", &Private::protectedStaticAttributes }, + { "protectedSlots", &Private::protectedSlots }, + { "privateTypes", &Private::privateTypes }, + { "privateMethods", &Private::privateMethods }, + { "privateStaticMethods", &Private::privateStaticMethods }, + { "privateAttributes", &Private::privateAttributes }, + { "privateStaticAttributes", &Private::privateStaticAttributes }, + { "privateSlots", &Private::privateSlots }, + { "packageTypes", &Private::packageTypes }, + { "packageMethods", &Private::packageMethods }, + { "packageStaticMethods", &Private::packageStaticMethods }, + { "packageAttributes", &Private::packageAttributes }, + { "packageStaticAttributes", &Private::packageStaticAttributes }, + { "properties", &Private::properties }, + { "events", &Private::events }, + { "friends", &Private::friends }, + { "related", &Private::related }, + { "detailedTypedefs", &Private::detailedTypedefs }, + { "detailedEnums", &Private::detailedEnums }, + { "detailedServices", &Private::detailedServices }, + { "detailedInterfaces", &Private::detailedInterfaces }, + { "detailedConstructors", &Private::detailedConstructors }, + { "detailedMethods", &Private::detailedMethods }, + { "detailedRelated", &Private::detailedRelated }, + { "detailedVariables", &Private::detailedVariables }, + { "detailedProperties", &Private::detailedProperties }, + { "detailedEvents", &Private::detailedEvents }, + { "classes", &Private::classes }, + { "innerClasses", &Private::innerClasses }, + { "compoundType", &Private::compoundType }, + { "templateDecls", &Private::templateDecls }, + { "typeConstraints", &Private::typeConstraints }, + { "examples", &Private::examples }, + { "members", &Private::members }, + { "allMembersList", &Private::allMembersList }, + { "allMembersFileName", &Private::allMembersFileName }, + { "memberGroups", &Private::memberGroups }, + { "additionalInheritedMembers",&Private::additionalInheritedMembers }, + { "isSimple", &Private::isSimple }, + { "categoryOf", &Private::categoryOf } }; //%% } -PropertyMapper<ClassContext::Private> ClassContext::Private::s_inst; +//PropertyMapper<ClassContext::Private> ClassContext::Private::s_inst; -ClassContext::ClassContext(const ClassDef *cd) : RefCountedContext("ClassContext") +ClassContext::ClassContext(const ClassDef *cd) : p(std::make_unique<Private>(cd)) { - //printf("ClassContext::ClassContext(%s)\n",cd?qPrint(cd->name()):"<none>"); - p = new Private(cd); } ClassContext::~ClassContext() { - delete p; } TemplateVariant ClassContext::get(const QCString &n) const @@ -2724,292 +2488,239 @@ StringVector ClassContext::fields() const //------------------------------------------------------------------------ -//%% struct Namespace(Symbol): namespace information -//%% { class NamespaceContext::Private : public DefinitionContext<NamespaceContext::Private> { public: Private(const NamespaceDef *nd) : DefinitionContext<NamespaceContext::Private>(nd), m_namespaceDef(nd) { - static bool init=FALSE; - if (!init) - { - addBaseProperties(s_inst); - s_inst.addProperty("title", &Private::title); - s_inst.addProperty("highlight", &Private::highlight); - s_inst.addProperty("subhighlight", &Private::subHighlight); - s_inst.addProperty("compoundType", &Private::compoundType); - s_inst.addProperty("hasDetails", &Private::hasDetails); - s_inst.addProperty("classes", &Private::classes); - //s_inst.addProperty("interfaces", &Private::interfaces); - s_inst.addProperty("namespaces", &Private::namespaces); - s_inst.addProperty("constantgroups", &Private::constantgroups); - s_inst.addProperty("typedefs", &Private::typedefs); - s_inst.addProperty("sequences", &Private::sequences); - s_inst.addProperty("dictionaries", &Private::dictionaries); - s_inst.addProperty("enums", &Private::enums); - s_inst.addProperty("functions", &Private::functions); - s_inst.addProperty("variables", &Private::variables); - s_inst.addProperty("memberGroups", &Private::memberGroups); - s_inst.addProperty("detailedTypedefs", &Private::detailedTypedefs); - s_inst.addProperty("detailedSequences", &Private::detailedSequences); - s_inst.addProperty("detailedDictionaries", &Private::detailedDictionaries); - s_inst.addProperty("detailedEnums", &Private::detailedEnums); - s_inst.addProperty("detailedFunctions", &Private::detailedFunctions); - s_inst.addProperty("detailedVariables", &Private::detailedVariables); - s_inst.addProperty("inlineClasses", &Private::inlineClasses); - init=TRUE; - } - if (!nd->cookie()) { nd->setCookie(new NamespaceContext::Private::Cachable(nd)); } } virtual ~Private() {} - TemplateVariant get(const QCString &n) const - { - return s_inst.get(this,n); - } - StringVector fields() const - { - return s_inst.fields(); - } - TemplateVariant title() const - { - return TemplateVariant(m_namespaceDef->title()); - } - TemplateVariant highlight() const - { - return TemplateVariant("namespaces"); - } - TemplateVariant subHighlight() const - { - return TemplateVariant(""); - } - TemplateVariant compoundType() const - { - return m_namespaceDef->compoundTypeString(); - } - TemplateVariant hasDetails() const - { - return m_namespaceDef->hasDetailedDescription(); - } - TemplateVariant classes() const + + // TemplateStructIntf methods + TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); } + StringVector fields() const { return s_inst.fields(); } + + private: + // Property getters + TemplateVariant title() const { return TemplateVariant(m_namespaceDef->title()); } + TemplateVariant highlight() const { return TemplateVariant("namespaces"); } + TemplateVariant subHighlight() const { return TemplateVariant(""); } + TemplateVariant compoundType() const { return m_namespaceDef->compoundTypeString(); } + TemplateVariant hasDetails() const { return m_namespaceDef->hasDetailedDescription(); } + TemplateVariant classes() const { return m_cachable.classes.get(this); } + TemplateVariant namespaces() const { return m_cachable.namespaces.get(this); } + TemplateVariant constantgroups() const { return m_cachable.constantgroups.get(this); } + TemplateVariant typedefs() const { return m_cachable.typedefs.get(this); } + TemplateVariant sequences() const { return m_cachable.sequences.get(this); } + TemplateVariant dictionaries() const { return m_cachable.dictionaries.get(this); } + TemplateVariant enums() const { return m_cachable.enums.get(this); } + TemplateVariant functions() const { return m_cachable.functions.get(this); } + TemplateVariant variables() const { return m_cachable.variables.get(this); } + TemplateVariant memberGroups() const { return m_cachable.memberGroups.get(this); } + TemplateVariant detailedTypedefs() const { return m_cachable.detailedTypedefs.get(this); } + TemplateVariant detailedSequences() const { return m_cachable.detailedSequences.get(this); } + TemplateVariant detailedDictionaries() const { return m_cachable.detailedDictionaries.get(this); } + TemplateVariant detailedEnums() const { return m_cachable.detailedEnums.get(this); } + TemplateVariant detailedFunctions() const { return m_cachable.detailedFunctions.get(this); } + TemplateVariant detailedVariables() const { return m_cachable.detailedVariables.get(this); } + TemplateVariant inlineClasses() const { return m_cachable.inlineClasses.get(this); } + + private: + TemplateVariant createClasses() const { - Cachable &cache = getCache(); - if (!cache.classes) + static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE); + TemplateVariantList classList; + classList.reserve(m_namespaceDef->getClasses().size()); + for (const auto &cd : m_namespaceDef->getClasses()) { - static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE); - TemplateList *classList = TemplateList::alloc(); - for (const auto &cd : m_namespaceDef->getClasses()) + if (sliceOpt && (cd->compoundType()==ClassDef::Struct || + cd->compoundType()==ClassDef::Interface || + cd->compoundType()==ClassDef::Exception)) { - if (sliceOpt && (cd->compoundType()==ClassDef::Struct || - cd->compoundType()==ClassDef::Interface || - cd->compoundType()==ClassDef::Exception)) - { - continue; // These types appear in their own sections. - } - if (cd->visibleInParentsDeclList()) - { - classList->append(ClassContext::alloc(cd)); - } + continue; // These types appear in their own sections. } - cache.classes.reset(classList); - } - return cache.classes.get(); - } - TemplateVariant namespaces() const - { - Cachable &cache = getCache(); - if (!cache.namespaces) - { - TemplateList *namespaceList = TemplateList::alloc(); - for (const auto &nd : m_namespaceDef->getNamespaces()) + if (cd->visibleInParentsDeclList()) { - if (nd->isLinkable() && !nd->isConstantGroup()) - { - namespaceList->append(NamespaceContext::alloc(nd)); - } + classList.push_back(ClassContext::alloc(cd)); } - cache.namespaces.reset(namespaceList); } - return cache.namespaces.get(); + return TemplateImmutableList::alloc(classList); } - TemplateVariant constantgroups() const + TemplateVariant createNamespaces() const { - Cachable &cache = getCache(); - if (!cache.constantgroups) + TemplateVariantList list; + list.reserve(m_namespaceDef->getNamespaces().size()); + for (const auto &nd : m_namespaceDef->getNamespaces()) { - TemplateList *namespaceList = TemplateList::alloc(); - for (const auto &nd : m_namespaceDef->getNamespaces()) + if (nd->isLinkable() && !nd->isConstantGroup()) { - if (nd->isLinkable() && nd->isConstantGroup()) - { - namespaceList->append(NamespaceContext::alloc(nd)); - } + list.push_back(NamespaceContext::alloc(nd)); } - cache.constantgroups.reset(namespaceList); } - return cache.constantgroups.get(); + return TemplateImmutableList::alloc(list); } - TemplateVariant getMemberList(SharedPtr<MemberListInfoContext> &list, - MemberListType type,const QCString &title,bool=FALSE) const + TemplateVariant createConstantgroups() const { - if (!list) + TemplateVariantList list; + list.reserve(m_namespaceDef->getNamespaces().size()); + for (const auto &nd : m_namespaceDef->getNamespaces()) { - const MemberList *ml = m_namespaceDef->getMemberList(type); - if (ml) + if (nd->isLinkable() && nd->isConstantGroup()) { - list.reset(MemberListInfoContext::alloc(m_namespaceDef,relPathAsString(),ml,title,"")); + list.push_back(NamespaceContext::alloc(nd)); } } - if (list) - { - return list.get(); - } - else - { - return TemplateVariant(FALSE); - } + return TemplateImmutableList::alloc(list); } - TemplateVariant typedefs() const + TemplateVariant createMemberList(MemberListType type,const QCString &title) const { - return getMemberList(getCache().typedefs,MemberListType_decTypedefMembers,theTranslator->trTypedefs()); + const MemberList *ml = m_namespaceDef->getMemberList(type); + return ml ? TemplateVariant(MemberListInfoContext::alloc(m_namespaceDef,relPathAsString(),ml,title,"")) + : TemplateVariant(false); } - TemplateVariant sequences() const + TemplateVariant createTypedefs() const { - return getMemberList(getCache().sequences,MemberListType_decSequenceMembers,theTranslator->trSequences()); + return createMemberList(MemberListType_decTypedefMembers,theTranslator->trTypedefs()); } - TemplateVariant dictionaries() const + TemplateVariant createSequences() const { - return getMemberList(getCache().dictionaries,MemberListType_decDictionaryMembers,theTranslator->trDictionaries()); + return createMemberList(MemberListType_decSequenceMembers,theTranslator->trSequences()); } - TemplateVariant enums() const + TemplateVariant createDictionaries() const { - return getMemberList(getCache().enums,MemberListType_decEnumMembers,theTranslator->trEnumerations()); + return createMemberList(MemberListType_decDictionaryMembers,theTranslator->trDictionaries()); } - TemplateVariant functions() const + TemplateVariant createEnums() const { - QCString title = theTranslator->trFunctions(); - SrcLangExt lang = m_namespaceDef->getLanguage(); - if (lang==SrcLangExt_Fortran) title=theTranslator->trSubprograms(); - else if (lang==SrcLangExt_VHDL) title=theTranslator->trFunctionAndProc(); - return getMemberList(getCache().functions,MemberListType_decFuncMembers,title); + return createMemberList(MemberListType_decEnumMembers,theTranslator->trEnumerations()); } - TemplateVariant variables() const + TemplateVariant createFunctions() const { - static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE); - return getMemberList(getCache().variables,MemberListType_decVarMembers, - sliceOpt ? theTranslator->trConstants() : theTranslator->trVariables()); + SrcLangExt lang = m_namespaceDef->getLanguage(); + return createMemberList(MemberListType_decFuncMembers,lang==SrcLangExt_Fortran ? theTranslator->trSubprograms() : + lang==SrcLangExt_VHDL ? theTranslator->trFunctionAndProc() : + theTranslator->trFunctions()); } - TemplateVariant memberGroups() const + TemplateVariant createVariables() const { - Cachable &cache = getCache(); - if (!cache.memberGroups) - { - if (!m_namespaceDef->getMemberGroups().empty()) - { - cache.memberGroups.reset(MemberGroupListContext::alloc(m_namespaceDef,relPathAsString(),m_namespaceDef->getMemberGroups(),m_namespaceDef->subGrouping())); - } - else - { - cache.memberGroups.reset(MemberGroupListContext::alloc()); - } - } - return cache.memberGroups.get(); + static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE); + return createMemberList(MemberListType_decVarMembers, sliceOpt ? theTranslator->trConstants() : + theTranslator->trVariables()); } - TemplateVariant detailedTypedefs() const + TemplateVariant createDetailedTypedefs() const { - return getMemberList(getCache().detailedTypedefs,MemberListType_docTypedefMembers,theTranslator->trTypedefDocumentation()); + return createMemberList(MemberListType_docTypedefMembers,theTranslator->trTypedefDocumentation()); } - TemplateVariant detailedSequences() const + TemplateVariant createDetailedSequences() const { - return getMemberList(getCache().detailedSequences,MemberListType_docSequenceMembers,theTranslator->trSequenceDocumentation()); + return createMemberList(MemberListType_docSequenceMembers,theTranslator->trSequenceDocumentation()); } - TemplateVariant detailedDictionaries() const + TemplateVariant createDetailedDictionaries() const { - return getMemberList(getCache().detailedDictionaries,MemberListType_docDictionaryMembers,theTranslator->trDictionaryDocumentation()); + return createMemberList(MemberListType_docDictionaryMembers,theTranslator->trDictionaryDocumentation()); } - TemplateVariant detailedEnums() const + TemplateVariant createDetailedEnums() const { - return getMemberList(getCache().detailedEnums,MemberListType_docEnumMembers,theTranslator->trEnumerationTypeDocumentation()); + return createMemberList(MemberListType_docEnumMembers,theTranslator->trEnumerationTypeDocumentation()); } - TemplateVariant detailedFunctions() const + TemplateVariant createDetailedFunctions() const { - QCString title = theTranslator->trFunctionDocumentation(); SrcLangExt lang = m_namespaceDef->getLanguage(); - if (lang==SrcLangExt_Fortran) title=theTranslator->trSubprogramDocumentation(); - return getMemberList(getCache().detailedFunctions,MemberListType_docFuncMembers,title); + return createMemberList(MemberListType_docFuncMembers, lang==SrcLangExt_Fortran ? theTranslator->trSubprogramDocumentation() : + theTranslator->trFunctionDocumentation()); } - TemplateVariant detailedVariables() const + TemplateVariant createDetailedVariables() const { static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE); - return getMemberList(getCache().detailedVariables,MemberListType_docVarMembers, - sliceOpt ? theTranslator->trConstantDocumentation() : - theTranslator->trVariableDocumentation()); + return createMemberList(MemberListType_docVarMembers, sliceOpt ? theTranslator->trConstantDocumentation() : + theTranslator->trVariableDocumentation()); } - TemplateVariant inlineClasses() const + TemplateVariant createMemberGroups() const { - Cachable &cache = getCache(); - if (!cache.inlineClasses) + return !m_namespaceDef->getMemberGroups().empty() ? + MemberGroupListContext::alloc(m_namespaceDef,relPathAsString(), + m_namespaceDef->getMemberGroups(), + m_namespaceDef->subGrouping()) : + MemberGroupListContext::alloc(); + } + TemplateVariant createInlineClasses() const + { + TemplateVariantList list; + list.reserve(m_namespaceDef->getClasses().size()); + for (const auto &cd : m_namespaceDef->getClasses()) { - TemplateList *classList = TemplateList::alloc(); - for (const auto &cd : m_namespaceDef->getClasses()) + if (!cd->isAnonymous() && + cd->isLinkableInProject() && + cd->isEmbeddedInOuterScope() && + cd->partOfGroups().empty()) { - if (!cd->isAnonymous() && - cd->isLinkableInProject() && - cd->isEmbeddedInOuterScope() && - cd->partOfGroups().empty()) - { - classList->append(ClassContext::alloc(cd)); - } + list.push_back(ClassContext::alloc(cd)); } - cache.inlineClasses.reset(classList); } - return cache.inlineClasses.get(); + return TemplateImmutableList::alloc(list); } - private: + const NamespaceDef *m_namespaceDef; struct Cachable : public DefinitionContext<NamespaceContext::Private>::Cachable { - Cachable(const NamespaceDef *nd) : DefinitionContext<NamespaceContext::Private>::Cachable(nd) {} - SharedPtr<TemplateList> classes; - SharedPtr<TemplateList> interfaces; - SharedPtr<TemplateList> namespaces; - SharedPtr<TemplateList> constantgroups; - SharedPtr<MemberListInfoContext> typedefs; - SharedPtr<MemberListInfoContext> sequences; - SharedPtr<MemberListInfoContext> dictionaries; - SharedPtr<MemberListInfoContext> enums; - SharedPtr<MemberListInfoContext> functions; - SharedPtr<MemberListInfoContext> variables; - SharedPtr<MemberGroupListContext> memberGroups; - SharedPtr<MemberListInfoContext> detailedTypedefs; - SharedPtr<MemberListInfoContext> detailedSequences; - SharedPtr<MemberListInfoContext> detailedDictionaries; - SharedPtr<MemberListInfoContext> detailedEnums; - SharedPtr<MemberListInfoContext> detailedFunctions; - SharedPtr<MemberListInfoContext> detailedVariables; - SharedPtr<TemplateList> inlineClasses; + CachedItem<TemplateVariant, Private, &Private::createClasses> classes; + CachedItem<TemplateVariant, Private, &Private::createNamespaces> namespaces; + CachedItem<TemplateVariant, Private, &Private::createConstantgroups> constantgroups; + CachedItem<TemplateVariant, Private, &Private::createTypedefs> typedefs; + CachedItem<TemplateVariant, Private, &Private::createSequences> sequences; + CachedItem<TemplateVariant, Private, &Private::createDictionaries> dictionaries; + CachedItem<TemplateVariant, Private, &Private::createEnums> enums; + CachedItem<TemplateVariant, Private, &Private::createFunctions> functions; + CachedItem<TemplateVariant, Private, &Private::createVariables> variables; + CachedItem<TemplateVariant, Private, &Private::createMemberGroups> memberGroups; + CachedItem<TemplateVariant, Private, &Private::createDetailedTypedefs> detailedTypedefs; + CachedItem<TemplateVariant, Private, &Private::createDetailedSequences> detailedSequences; + CachedItem<TemplateVariant, Private, &Private::createDetailedDictionaries> detailedDictionaries; + CachedItem<TemplateVariant, Private, &Private::createDetailedEnums> detailedEnums; + CachedItem<TemplateVariant, Private, &Private::createDetailedFunctions> detailedFunctions; + CachedItem<TemplateVariant, Private, &Private::createDetailedVariables> detailedVariables; + CachedItem<TemplateVariant, Private, &Private::createInlineClasses> inlineClasses; }; - Cachable &getCache() const - { - Cachable *c = static_cast<Cachable*>(m_namespaceDef->cookie()); - assert(c!=0); - return *c; - } - static PropertyMapper<NamespaceContext::Private> s_inst; + Cachable m_cachable; + static const PropertyMap<NamespaceContext::Private> s_inst; }; -//%% } -PropertyMapper<NamespaceContext::Private> NamespaceContext::Private::s_inst; +//%% struct Namespace(Symbol): namespace information +//%% { +const PropertyMap<NamespaceContext::Private> NamespaceContext::Private::s_inst { + BASE_PROPERTIES, + { "title", &Private::title }, + { "highlight", &Private::highlight }, + { "subhighlight", &Private::subHighlight }, + { "compoundType", &Private::compoundType }, + { "hasDetails", &Private::hasDetails }, + { "classes", &Private::classes }, + { "namespaces", &Private::namespaces }, + { "constantgroups", &Private::constantgroups }, + { "typedefs", &Private::typedefs }, + { "sequences", &Private::sequences }, + { "dictionaries", &Private::dictionaries }, + { "enums", &Private::enums }, + { "functions", &Private::functions }, + { "variables", &Private::variables }, + { "memberGroups", &Private::memberGroups }, + { "detailedTypedefs", &Private::detailedTypedefs }, + { "detailedSequences", &Private::detailedSequences }, + { "detailedDictionaries", &Private::detailedDictionaries }, + { "detailedEnums", &Private::detailedEnums }, + { "detailedFunctions", &Private::detailedFunctions }, + { "detailedVariables", &Private::detailedVariables }, + { "inlineClasses", &Private::inlineClasses } +}; +//%% } -NamespaceContext::NamespaceContext(const NamespaceDef *nd) : RefCountedContext("NamespaceContext") +NamespaceContext::NamespaceContext(const NamespaceDef *nd) : p(std::make_unique<Private>(nd)) { - p = new Private(nd); } NamespaceContext::~NamespaceContext() { - delete p; } TemplateVariant NamespaceContext::get(const QCString &n) const @@ -3024,110 +2735,56 @@ StringVector NamespaceContext::fields() const //------------------------------------------------------------------------ -//%% struct File(Symbol): file information -//%% { class FileContext::Private : public DefinitionContext<FileContext::Private> { public: Private(const FileDef *fd) : DefinitionContext<FileContext::Private>(fd) , m_fileDef(fd) { if (fd==0) abort(); - static bool init=FALSE; - if (!init) - { - addBaseProperties(s_inst); - s_inst.addProperty("title", &Private::title); - s_inst.addProperty("highlight", &Private::highlight); - s_inst.addProperty("subhighlight", &Private::subHighlight); - s_inst.addProperty("versionInfo", &Private::versionInfo); - s_inst.addProperty("includeList", &Private::includeList); - s_inst.addProperty("hasIncludeGraph", &Private::hasIncludeGraph); - s_inst.addProperty("hasIncludedByGraph", &Private::hasIncludedByGraph); - s_inst.addProperty("includeGraph", &Private::includeGraph); - s_inst.addProperty("includedByGraph", &Private::includedByGraph); - s_inst.addProperty("hasDetails", &Private::hasDetails); - s_inst.addProperty("hasSourceFile", &Private::hasSourceFile); - s_inst.addProperty("sources", &Private::sources); - s_inst.addProperty("version", &Private::version); - s_inst.addProperty("classes", &Private::classes); - s_inst.addProperty("namespaces", &Private::namespaces); - s_inst.addProperty("constantgroups", &Private::constantgroups); - s_inst.addProperty("macros", &Private::macros); - s_inst.addProperty("typedefs", &Private::typedefs); - s_inst.addProperty("sequences", &Private::sequences); - s_inst.addProperty("dictionaries", &Private::dictionaries); - s_inst.addProperty("enums", &Private::enums); - s_inst.addProperty("functions", &Private::functions); - s_inst.addProperty("variables", &Private::variables); - s_inst.addProperty("memberGroups", &Private::memberGroups); - s_inst.addProperty("detailedMacros", &Private::detailedMacros); - s_inst.addProperty("detailedTypedefs", &Private::detailedTypedefs); - s_inst.addProperty("detailedSequences", &Private::detailedSequences); - s_inst.addProperty("detailedDictionaries", &Private::detailedDictionaries); - s_inst.addProperty("detailedEnums", &Private::detailedEnums); - s_inst.addProperty("detailedFunctions", &Private::detailedFunctions); - s_inst.addProperty("detailedVariables", &Private::detailedVariables); - s_inst.addProperty("inlineClasses", &Private::inlineClasses); - s_inst.addProperty("compoundType", &Private::compoundType); - init=TRUE; - } - if (!fd->cookie()) { fd->setCookie(new FileContext::Private::Cachable(fd)); } } virtual ~Private() {} - TemplateVariant get(const QCString &n) const - { - return s_inst.get(this,n); - } - StringVector fields() const - { - return s_inst.fields(); - } - TemplateVariant title() const - { - return m_fileDef->title(); - } - TemplateVariant highlight() const - { - return TemplateVariant("files"); - } - TemplateVariant subHighlight() const - { - return TemplateVariant(""); - } - TemplateVariant versionInfo() const - { - return m_fileDef->getVersion(); - } - TemplateVariant includeList() const - { - Cachable &cache = getCache(); - if (!cache.includeInfoList && !m_fileDef->includeFileList().empty()) - { - cache.includeInfoList.reset(IncludeInfoListContext::alloc( - m_fileDef->includeFileList(),m_fileDef->getLanguage())); - } - if (cache.includeInfoList) - { - return cache.includeInfoList.get(); - } - else - { - return TemplateVariant(FALSE); - } - } - DotInclDepGraph *getIncludeGraph() const - { - Cachable &cache = getCache(); - if (!cache.includeGraph) - { - cache.includeGraph.reset(new DotInclDepGraph(m_fileDef,FALSE)); - } - return cache.includeGraph.get(); - } + + // TemplateStructIntf methods + TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); } + StringVector fields() const { return s_inst.fields(); } + + // Property getters + TemplateVariant title() const { return m_fileDef->title(); } + TemplateVariant highlight() const { return TemplateVariant("files"); } + TemplateVariant subHighlight() const { return TemplateVariant(""); } + TemplateVariant versionInfo() const { return m_fileDef->getVersion(); } + TemplateVariant includeList() const { return m_cachable.includeList.get(this); } + TemplateVariant hasDetails() const { return m_fileDef->hasDetailedDescription(); } + TemplateVariant hasSourceFile() const { return m_fileDef->generateSourceFile(); } + TemplateVariant sources() const { return m_cachable.sources.get(this); } + TemplateVariant version() const { return m_fileDef->fileVersion(); } + TemplateVariant classes() const { return m_cachable.classes.get(this); } + TemplateVariant namespaces() const { return m_cachable.namespaces.get(this); } + TemplateVariant constantgroups() const { return m_cachable.constantgroups.get(this); } + TemplateVariant macros() const { return m_cachable.macros.get(this); } + TemplateVariant typedefs() const { return m_cachable.typedefs.get(this); } + TemplateVariant sequences() const { return m_cachable.sequences.get(this); } + TemplateVariant dictionaries() const { return m_cachable.dictionaries.get(this); } + TemplateVariant enums() const { return m_cachable.enums.get(this); } + TemplateVariant functions() const { return m_cachable.functions.get(this); } + TemplateVariant variables() const { return m_cachable.variables.get(this); } + TemplateVariant memberGroups() const { return m_cachable.memberGroups.get(this); } + TemplateVariant detailedMacros() const { return m_cachable.detailedMacros.get(this); } + TemplateVariant detailedTypedefs() const { return m_cachable.detailedTypedefs.get(this); } + TemplateVariant detailedSequences() const { return m_cachable.detailedSequences.get(this); } + TemplateVariant detailedDictionaries() const { return m_cachable.detailedDictionaries.get(this); } + TemplateVariant detailedEnums() const { return m_cachable.detailedEnums.get(this); } + TemplateVariant detailedFunctions() const { return m_cachable.detailedFunctions.get(this); } + TemplateVariant detailedVariables() const { return m_cachable.detailedVariables.get(this); } + TemplateVariant inlineClasses() const { return m_cachable.inlineClasses.get(this); } + TemplateVariant compoundType() const { return theTranslator->trFile(FALSE,TRUE); } + DotInclDepGraphPtr getIncludeGraph() const { return m_cachable.includeGraph.get(this); } + DotInclDepGraphPtr getIncludedByGraph() const { return m_cachable.includedByGraph.get(this); } + TemplateVariant hasIncludeGraph() const { static bool haveDot = Config_getBool(HAVE_DOT); - DotInclDepGraph *incGraph = getIncludeGraph(); + DotInclDepGraphPtr incGraph = getIncludeGraph(); return (haveDot && !incGraph->isTooBig() && !incGraph->isTrivial()); } TemplateVariant includeGraph() const @@ -3136,14 +2793,14 @@ class FileContext::Private : public DefinitionContext<FileContext::Private> TextStream t; if (haveDot) { - DotInclDepGraph *cg = getIncludeGraph(); + DotInclDepGraphPtr cg = getIncludeGraph(); switch (g_globals.outputFormat) { case ContextOutputFormat_Html: { cg->writeGraph(t,GOF_BITMAP,EOF_Html, g_globals.outputDir, - g_globals.outputDir+Portable::pathSeparator()+m_fileDef->getOutputFileBase()+Doxygen::htmlFileExtension, + g_globals.outputDir+Portable::pathSeparator()+addHtmlExtensionIfMissing(m_fileDef->getOutputFileBase()), relPathAsString(),TRUE,g_globals.dynSectionId ); } @@ -3166,19 +2823,10 @@ class FileContext::Private : public DefinitionContext<FileContext::Private> } return TemplateVariant(t.str().c_str(),TRUE); } - DotInclDepGraph *getIncludedByGraph() const - { - Cachable &cache = getCache(); - if (!cache.includedByGraph) - { - cache.includedByGraph.reset(new DotInclDepGraph(m_fileDef,TRUE)); - } - return cache.includedByGraph.get(); - } TemplateVariant hasIncludedByGraph() const { static bool haveDot = Config_getBool(HAVE_DOT); - DotInclDepGraph *incGraph = getIncludedByGraph(); + DotInclDepGraphPtr incGraph = getIncludedByGraph(); return (haveDot && !incGraph->isTooBig() && !incGraph->isTrivial()); } TemplateVariant includedByGraph() const @@ -3187,14 +2835,14 @@ class FileContext::Private : public DefinitionContext<FileContext::Private> TextStream t; if (haveDot) { - DotInclDepGraph *cg = getIncludedByGraph(); + DotInclDepGraphPtr cg = getIncludedByGraph(); switch (g_globals.outputFormat) { case ContextOutputFormat_Html: { cg->writeGraph(t,GOF_BITMAP,EOF_Html, g_globals.outputDir, - g_globals.outputDir+Portable::pathSeparator()+m_fileDef->getOutputFileBase()+Doxygen::htmlFileExtension, + g_globals.outputDir+Portable::pathSeparator()+addHtmlExtensionIfMissing(m_fileDef->getOutputFileBase()), relPathAsString(),TRUE,g_globals.dynSectionId ); } @@ -3217,260 +2865,239 @@ class FileContext::Private : public DefinitionContext<FileContext::Private> } return TemplateVariant(t.str().c_str(),TRUE); } - TemplateVariant hasDetails() const + + private: + + TemplateVariant createIncludeList() const { - return m_fileDef->hasDetailedDescription(); + return !m_fileDef->includeFileList().empty() ? + TemplateVariant(IncludeInfoListContext::alloc(m_fileDef->includeFileList(),m_fileDef->getLanguage())) : + TemplateVariant(false); } - TemplateVariant hasSourceFile() const + DotInclDepGraphPtr createIncludeGraph() const { - return m_fileDef->generateSourceFile(); + return std::make_shared<DotInclDepGraph>(m_fileDef,FALSE); } - TemplateVariant sources() const + DotInclDepGraphPtr createIncludedByGraph() const { - Cachable &cache = getCache(); - if (!cache.sources) - { - if (m_fileDef->generateSourceFile()) - { - cache.sources.reset(new TemplateVariant(parseCode(m_fileDef,relPathAsString()))); - } - else - { - cache.sources.reset(new TemplateVariant("")); - } - } - return *cache.sources; + return std::make_shared<DotInclDepGraph>(m_fileDef,TRUE); } - TemplateVariant version() const + TemplateVariant createSources() const { - return m_fileDef->fileVersion(); + return m_fileDef->generateSourceFile() ? + TemplateVariant(parseCode(m_fileDef,relPathAsString())) : + TemplateVariant(""); } - TemplateVariant classes() const + TemplateVariant createClasses() const { - Cachable &cache = getCache(); - if (!cache.classes) + TemplateVariantList list; + list.reserve(m_fileDef->getClasses().size()); + for (const auto &cd : m_fileDef->getClasses()) { - TemplateList *classList = TemplateList::alloc(); - for (const auto &cd : m_fileDef->getClasses()) + if (cd->visibleInParentsDeclList()) { - if (cd->visibleInParentsDeclList()) - { - classList->append(ClassContext::alloc(cd)); - } + list.push_back(ClassContext::alloc(cd)); } - cache.classes.reset(classList); } - return cache.classes.get(); + return TemplateImmutableList::alloc(list); } - TemplateVariant namespaces() const + TemplateVariant createNamespaces() const { - Cachable &cache = getCache(); - if (!cache.namespaces) + TemplateVariantList list; + list.reserve(m_fileDef->getNamespaces().size()); + for (const auto &nd : m_fileDef->getNamespaces()) { - TemplateList *namespaceList = TemplateList::alloc(); - for (const auto &nd : m_fileDef->getNamespaces()) + if (nd->isLinkable() && !nd->isConstantGroup()) { - if (nd->isLinkable() && !nd->isConstantGroup()) - { - namespaceList->append(NamespaceContext::alloc(nd)); - } + list.push_back(NamespaceContext::alloc(nd)); } - cache.namespaces.reset(namespaceList); } - return cache.namespaces.get(); + return TemplateImmutableList::alloc(list); } - TemplateVariant constantgroups() const + TemplateVariant createConstantgroups() const { - Cachable &cache = getCache(); - if (!cache.constantgroups) + TemplateVariantList list; + list.reserve(m_fileDef->getNamespaces().size()); + for (const auto &nd : m_fileDef->getNamespaces()) { - TemplateList *namespaceList = TemplateList::alloc(); - for (const auto &nd : m_fileDef->getNamespaces()) + if (nd->isLinkable() && nd->isConstantGroup()) { - if (nd->isLinkable() && nd->isConstantGroup()) - { - namespaceList->append(NamespaceContext::alloc(nd)); - } + list.push_back(NamespaceContext::alloc(nd)); } - cache.constantgroups.reset(namespaceList); } - return cache.constantgroups.get(); + return TemplateImmutableList::alloc(list); } - TemplateVariant getMemberList(SharedPtr<MemberListInfoContext> &list, - MemberListType type,const QCString &title,bool=FALSE) const + TemplateVariant createMemberList(MemberListType type,const QCString &title) const { - if (!list) - { - const MemberList *ml = m_fileDef->getMemberList(type); - if (ml) - { - list.reset(MemberListInfoContext::alloc(m_fileDef,relPathAsString(),ml,title,"")); - } - } - if (list) - { - return list.get(); - } - else - { - return TemplateVariant(FALSE); - } + const MemberList *ml = m_fileDef->getMemberList(type); + return ml ? TemplateVariant(MemberListInfoContext::alloc(m_fileDef,relPathAsString(),ml,title,"")) + : TemplateVariant(false); } - TemplateVariant macros() const + TemplateVariant createMacros() const { - return getMemberList(getCache().macros,MemberListType_decDefineMembers,theTranslator->trDefines()); + return createMemberList(MemberListType_decDefineMembers,theTranslator->trDefines()); } - TemplateVariant typedefs() const + TemplateVariant createTypedefs() const { - return getMemberList(getCache().typedefs,MemberListType_decTypedefMembers,theTranslator->trTypedefs()); + return createMemberList(MemberListType_decTypedefMembers,theTranslator->trTypedefs()); } - TemplateVariant sequences() const + TemplateVariant createSequences() const { - return getMemberList(getCache().sequences,MemberListType_decSequenceMembers,theTranslator->trSequences()); + return createMemberList(MemberListType_decSequenceMembers,theTranslator->trSequences()); } - TemplateVariant dictionaries() const + TemplateVariant createDictionaries() const { - return getMemberList(getCache().dictionaries,MemberListType_decDictionaryMembers,theTranslator->trDictionaries()); + return createMemberList(MemberListType_decDictionaryMembers,theTranslator->trDictionaries()); } - TemplateVariant enums() const + TemplateVariant createEnums() const { - return getMemberList(getCache().enums,MemberListType_decEnumMembers,theTranslator->trEnumerations()); + return createMemberList(MemberListType_decEnumMembers,theTranslator->trEnumerations()); } - TemplateVariant functions() const + TemplateVariant createFunctions() const { - QCString title = theTranslator->trFunctions(); SrcLangExt lang = m_fileDef->getLanguage(); - if (lang==SrcLangExt_Fortran) title=theTranslator->trSubprograms(); - else if (lang==SrcLangExt_VHDL) title=theTranslator->trFunctionAndProc(); - return getMemberList(getCache().functions,MemberListType_decFuncMembers,title); + return createMemberList(MemberListType_decFuncMembers, lang==SrcLangExt_Fortran ? theTranslator->trSubprograms() : + lang==SrcLangExt_VHDL ? theTranslator->trFunctionAndProc() : + theTranslator->trFunctions()); } - TemplateVariant variables() const + TemplateVariant createVariables() const { static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE); - return getMemberList(getCache().variables,MemberListType_decVarMembers, - sliceOpt ? theTranslator->trConstants() : theTranslator->trVariables()); + return createMemberList(MemberListType_decVarMembers, sliceOpt ? theTranslator->trConstants() : + theTranslator->trVariables()); } - TemplateVariant memberGroups() const + TemplateVariant createDetailedMacros() const { - Cachable &cache = getCache(); - if (!cache.memberGroups) - { - if (!m_fileDef->getMemberGroups().empty()) - { - cache.memberGroups.reset(MemberGroupListContext::alloc(m_fileDef,relPathAsString(),m_fileDef->getMemberGroups(),m_fileDef->subGrouping())); - } - else - { - cache.memberGroups.reset(MemberGroupListContext::alloc()); - } - } - return cache.memberGroups.get(); + return createMemberList(MemberListType_docDefineMembers,theTranslator->trDefineDocumentation()); } - TemplateVariant detailedMacros() const + TemplateVariant createDetailedTypedefs() const { - return getMemberList(getCache().detailedMacros,MemberListType_docDefineMembers,theTranslator->trDefineDocumentation()); + return createMemberList(MemberListType_docTypedefMembers,theTranslator->trTypedefDocumentation()); } - TemplateVariant detailedTypedefs() const + TemplateVariant createDetailedSequences() const { - return getMemberList(getCache().detailedTypedefs,MemberListType_docTypedefMembers,theTranslator->trTypedefDocumentation()); + return createMemberList(MemberListType_docSequenceMembers,theTranslator->trSequenceDocumentation()); } - TemplateVariant detailedSequences() const + TemplateVariant createDetailedDictionaries() const { - return getMemberList(getCache().detailedSequences,MemberListType_docSequenceMembers,theTranslator->trSequenceDocumentation()); + return createMemberList(MemberListType_docDictionaryMembers,theTranslator->trDictionaryDocumentation()); } - TemplateVariant detailedDictionaries() const + TemplateVariant createDetailedEnums() const { - return getMemberList(getCache().detailedDictionaries,MemberListType_docDictionaryMembers,theTranslator->trDictionaryDocumentation()); + return createMemberList(MemberListType_docEnumMembers,theTranslator->trEnumerationTypeDocumentation()); } - TemplateVariant detailedEnums() const + TemplateVariant createDetailedFunctions() const { - return getMemberList(getCache().detailedEnums,MemberListType_docEnumMembers,theTranslator->trEnumerationTypeDocumentation()); + SrcLangExt lang = m_fileDef->getLanguage(); + return createMemberList(MemberListType_docFuncMembers, lang==SrcLangExt_Fortran ? theTranslator->trSubprogramDocumentation() : + theTranslator->trFunctionDocumentation()); } - TemplateVariant detailedFunctions() const + TemplateVariant createDetailedVariables() const { - QCString title = theTranslator->trFunctionDocumentation(); - SrcLangExt lang = m_fileDef->getLanguage(); - if (lang==SrcLangExt_Fortran) title=theTranslator->trSubprogramDocumentation(); - return getMemberList(getCache().detailedFunctions,MemberListType_docFuncMembers,title); + return createMemberList(MemberListType_docVarMembers,theTranslator->trVariableDocumentation()); } - TemplateVariant detailedVariables() const + TemplateVariant createMemberGroups() const { - return getMemberList(getCache().detailedVariables,MemberListType_docVarMembers,theTranslator->trVariableDocumentation()); + return !m_fileDef->getMemberGroups().empty() ? + MemberGroupListContext::alloc(m_fileDef,relPathAsString(),m_fileDef->getMemberGroups(),m_fileDef->subGrouping()) : + MemberGroupListContext::alloc(); } - TemplateVariant inlineClasses() const + TemplateVariant createInlineClasses() const { - Cachable &cache = getCache(); - if (!cache.inlineClasses) + TemplateVariantList list; + list.reserve(m_fileDef->getClasses().size()); + for (const auto &cd : m_fileDef->getClasses()) { - TemplateList *classList = TemplateList::alloc(); - for (const auto &cd : m_fileDef->getClasses()) + if (!cd->isAnonymous() && + cd->isLinkableInProject() && + cd->isEmbeddedInOuterScope() && + cd->partOfGroups().empty()) { - if (!cd->isAnonymous() && - cd->isLinkableInProject() && - cd->isEmbeddedInOuterScope() && - cd->partOfGroups().empty()) - { - classList->append(ClassContext::alloc(cd)); - } + list.push_back(ClassContext::alloc(cd)); } - cache.inlineClasses.reset(classList); } - return cache.inlineClasses.get(); - } - TemplateVariant compoundType() const - { - return theTranslator->trFile(FALSE,TRUE); + return TemplateImmutableList::alloc(list); } - private: const FileDef *m_fileDef; struct Cachable : public DefinitionContext<FileContext::Private>::Cachable { - Cachable(const FileDef *fd) : DefinitionContext<FileContext::Private>::Cachable(fd) {} - SharedPtr<IncludeInfoListContext> includeInfoList; - std::unique_ptr<DotInclDepGraph> includeGraph; - std::unique_ptr<DotInclDepGraph> includedByGraph; - std::unique_ptr<TemplateVariant> sources; - SharedPtr<TemplateList> classes; - SharedPtr<TemplateList> namespaces; - SharedPtr<TemplateList> constantgroups; - SharedPtr<MemberListInfoContext> macros; - SharedPtr<MemberListInfoContext> typedefs; - SharedPtr<MemberListInfoContext> sequences; - SharedPtr<MemberListInfoContext> dictionaries; - SharedPtr<MemberListInfoContext> enums; - SharedPtr<MemberListInfoContext> functions; - SharedPtr<MemberListInfoContext> variables; - SharedPtr<MemberGroupListContext> memberGroups; - SharedPtr<MemberListInfoContext> detailedMacros; - SharedPtr<MemberListInfoContext> detailedTypedefs; - SharedPtr<MemberListInfoContext> detailedSequences; - SharedPtr<MemberListInfoContext> detailedDictionaries; - SharedPtr<MemberListInfoContext> detailedEnums; - SharedPtr<MemberListInfoContext> detailedFunctions; - SharedPtr<MemberListInfoContext> detailedVariables; - SharedPtr<TemplateList> inlineClasses; + CachedItem<TemplateVariant, Private, &Private::createIncludeList> includeList; + CachedItem<DotInclDepGraphPtr, Private, &Private::createIncludeGraph> includeGraph; + CachedItem<DotInclDepGraphPtr, Private, &Private::createIncludedByGraph> includedByGraph; + CachedItem<TemplateVariant, Private, &Private::createSources> sources; + CachedItem<TemplateVariant, Private, &Private::createClasses> classes; + CachedItem<TemplateVariant, Private, &Private::createNamespaces> namespaces; + CachedItem<TemplateVariant, Private, &Private::createConstantgroups> constantgroups; + CachedItem<TemplateVariant, Private, &Private::createMacros> macros; + CachedItem<TemplateVariant, Private, &Private::createTypedefs> typedefs; + CachedItem<TemplateVariant, Private, &Private::createSequences> sequences; + CachedItem<TemplateVariant, Private, &Private::createDictionaries> dictionaries; + CachedItem<TemplateVariant, Private, &Private::createEnums> enums; + CachedItem<TemplateVariant, Private, &Private::createFunctions> functions; + CachedItem<TemplateVariant, Private, &Private::createVariables> variables; + CachedItem<TemplateVariant, Private, &Private::createMemberGroups> memberGroups; + CachedItem<TemplateVariant, Private, &Private::createDetailedMacros> detailedMacros; + CachedItem<TemplateVariant, Private, &Private::createDetailedTypedefs> detailedTypedefs; + CachedItem<TemplateVariant, Private, &Private::createDetailedSequences> detailedSequences; + CachedItem<TemplateVariant, Private, &Private::createDetailedDictionaries> detailedDictionaries; + CachedItem<TemplateVariant, Private, &Private::createDetailedEnums> detailedEnums; + CachedItem<TemplateVariant, Private, &Private::createDetailedFunctions> detailedFunctions; + CachedItem<TemplateVariant, Private, &Private::createDetailedVariables> detailedVariables; + CachedItem<TemplateVariant, Private, &Private::createInlineClasses> inlineClasses; }; - Cachable &getCache() const - { - Cachable *c = static_cast<Cachable*>(m_fileDef->cookie()); - assert(c!=0); - return *c; - } - static PropertyMapper<FileContext::Private> s_inst; + Cachable m_cachable; + static const PropertyMap<FileContext::Private> s_inst; +}; + +//%% struct File(Symbol): file information +//%% { +const PropertyMap<FileContext::Private> FileContext::Private::s_inst { + BASE_PROPERTIES, + { "title", &Private::title }, + { "highlight", &Private::highlight }, + { "subhighlight", &Private::subHighlight }, + { "versionInfo", &Private::versionInfo }, + { "includeList", &Private::includeList }, + { "hasIncludeGraph", &Private::hasIncludeGraph }, + { "hasIncludedByGraph", &Private::hasIncludedByGraph }, + { "includeGraph", &Private::includeGraph }, + { "includedByGraph", &Private::includedByGraph }, + { "hasDetails", &Private::hasDetails }, + { "hasSourceFile", &Private::hasSourceFile }, + { "sources", &Private::sources }, + { "version", &Private::version }, + { "classes", &Private::classes }, + { "namespaces", &Private::namespaces }, + { "constantgroups", &Private::constantgroups }, + { "macros", &Private::macros }, + { "typedefs", &Private::typedefs }, + { "sequences", &Private::sequences }, + { "dictionaries", &Private::dictionaries }, + { "enums", &Private::enums }, + { "functions", &Private::functions }, + { "variables", &Private::variables }, + { "memberGroups", &Private::memberGroups }, + { "detailedMacros", &Private::detailedMacros }, + { "detailedTypedefs", &Private::detailedTypedefs }, + { "detailedSequences", &Private::detailedSequences }, + { "detailedDictionaries", &Private::detailedDictionaries }, + { "detailedEnums", &Private::detailedEnums }, + { "detailedFunctions", &Private::detailedFunctions }, + { "detailedVariables", &Private::detailedVariables }, + { "inlineClasses", &Private::inlineClasses }, + { "compoundType", &Private::compoundType } }; //%% } -PropertyMapper<FileContext::Private> FileContext::Private::s_inst; +//PropertyMapper<FileContext::Private> FileContext::Private::s_inst; -FileContext::FileContext(const FileDef *fd) : RefCountedContext("FileContext") +FileContext::FileContext(const FileDef *fd) : p(std::make_unique<Private>(fd)) { - p = new Private(fd); } FileContext::~FileContext() { - delete p; } TemplateVariant FileContext::get(const QCString &n) const @@ -3485,105 +3112,30 @@ StringVector FileContext::fields() const //------------------------------------------------------------------------ -//%% struct Dir(Symbol): directory information -//%% { class DirContext::Private : public DefinitionContext<DirContext::Private> { public: Private(const DirDef *dd) : DefinitionContext<DirContext::Private>(dd) , m_dirDef(dd) { - static bool init=FALSE; - if (!init) - { - addBaseProperties(s_inst); - s_inst.addProperty("title", &Private::title); - s_inst.addProperty("highlight", &Private::highlight); - s_inst.addProperty("subhighlight", &Private::subHighlight); - s_inst.addProperty("dirName", &Private::dirName); - s_inst.addProperty("dirs", &Private::dirs); - s_inst.addProperty("files", &Private::files); - s_inst.addProperty("hasDetails", &Private::hasDetails); - s_inst.addProperty("hasDirGraph", &Private::hasDirGraph); - s_inst.addProperty("dirGraph", &Private::dirGraph); - s_inst.addProperty("compoundType", &Private::compoundType); - init=TRUE; - } - if (!dd->cookie()) { dd->setCookie(new DirContext::Private::Cachable(dd)); } } virtual ~Private() {} - TemplateVariant get(const QCString &n) const - { - return s_inst.get(this,n); - } - StringVector fields() const - { - return s_inst.fields(); - } - TemplateVariant title() const - { - return TemplateVariant(m_dirDef->shortTitle()); - } - TemplateVariant highlight() const - { - return TemplateVariant("files"); - } - TemplateVariant subHighlight() const - { - return TemplateVariant(""); - } - TemplateVariant dirName() const - { - return TemplateVariant(m_dirDef->shortName()); - } - TemplateVariant dirs() const - { - Cachable &cache = getCache(); - if (!cache.dirs) - { - cache.dirs.reset(TemplateList::alloc()); - for(const auto dd : m_dirDef->subDirs()) - { - DirContext *dc = new DirContext(dd); - cache.dirs->append(dc); - } - } - return cache.dirs.get(); - } - TemplateVariant files() const - { - Cachable &cache = getCache(); - if (!cache.files) - { - cache.files.reset(TemplateList::alloc()); - for (const auto &fd : m_dirDef->getFiles()) - { - FileContext *fc = FileContext::alloc(fd); - cache.files->append(fc); - } - } - return cache.files.get(); - } - TemplateVariant hasDetails() const - { - return m_dirDef->hasDetailedDescription(); - } - TemplateVariant compoundType() const - { - return theTranslator->trDir(FALSE,TRUE); - } - TemplateVariant relPath() const - { - return ""; - } - DotDirDeps *getDirDepsGraph() const - { - Cachable &cache = getCache(); - if (!cache.dirDepsGraph) - { - cache.dirDepsGraph.reset(new DotDirDeps(m_dirDef)); - } - return cache.dirDepsGraph.get(); - } + + // TemplateStructIntf methods + TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); } + StringVector fields() const { return s_inst.fields(); } + + // Property getters + TemplateVariant title() const { return TemplateVariant(m_dirDef->shortTitle()); } + TemplateVariant highlight() const { return TemplateVariant("files"); } + TemplateVariant subHighlight() const { return TemplateVariant(""); } + TemplateVariant dirName() const { return TemplateVariant(m_dirDef->shortName()); } + TemplateVariant dirs() const { return m_cachable.dirs.get(this); } + TemplateVariant files() const { return m_cachable.files.get(this); } + TemplateVariant hasDetails() const { return m_dirDef->hasDetailedDescription(); } + TemplateVariant compoundType() const { return theTranslator->trDir(FALSE,TRUE); } + TemplateVariant relPath() const { return ""; } + DotDirDepsPtr getDirDepsGraph() const { return m_cachable.dirDepsGraph.get(this); } + TemplateVariant hasDirGraph() const { bool result=FALSE; @@ -3591,7 +3143,7 @@ class DirContext::Private : public DefinitionContext<DirContext::Private> static bool dirGraph = Config_getBool(DIRECTORY_GRAPH); if (haveDot && dirGraph) { - DotDirDeps *graph = getDirDepsGraph(); + DotDirDepsPtr graph = getDirDepsGraph(); result = !graph->isTrivial(); } return result; @@ -3603,7 +3155,7 @@ class DirContext::Private : public DefinitionContext<DirContext::Private> static bool dirGraph = Config_getBool(DIRECTORY_GRAPH); if (haveDot && dirGraph) { - DotDirDeps *graph = getDirDepsGraph(); + DotDirDepsPtr graph = getDirDepsGraph(); switch (g_globals.outputFormat) { case ContextOutputFormat_Html: @@ -3611,7 +3163,7 @@ class DirContext::Private : public DefinitionContext<DirContext::Private> graph->writeGraph(t,GOF_BITMAP, EOF_Html, g_globals.outputDir, - g_globals.outputDir+Portable::pathSeparator()+m_dirDef->getOutputFileBase()+Doxygen::htmlFileExtension, + g_globals.outputDir+Portable::pathSeparator()+addHtmlExtensionIfMissing(m_dirDef->getOutputFileBase()), relPathAsString(), TRUE, g_globals.dynSectionId, @@ -3641,34 +3193,66 @@ class DirContext::Private : public DefinitionContext<DirContext::Private> } private: + TemplateVariant createDirs() const + { + TemplateVariantList list; + list.reserve(m_dirDef->subDirs().size()); + for(const auto dd : m_dirDef->subDirs()) + { + list.push_back(DirContext::alloc(dd)); + } + return TemplateImmutableList::alloc(list); + } + TemplateVariant createFiles() const + { + TemplateVariantList list; + list.reserve(m_dirDef->getFiles().size()); + for (const auto &fd : m_dirDef->getFiles()) + { + list.push_back(FileContext::alloc(fd)); + } + return TemplateImmutableList::alloc(list); + } + DotDirDepsPtr createDirDepsGraph() const + { + return std::make_shared<DotDirDeps>(m_dirDef); + } const DirDef *m_dirDef; struct Cachable : public DefinitionContext<DirContext::Private>::Cachable { - Cachable(const DirDef *dd) : DefinitionContext<DirContext::Private>::Cachable(dd) {} - SharedPtr<TemplateList> dirs; - SharedPtr<TemplateList> files; - std::unique_ptr<DotDirDeps> dirDepsGraph; + CachedItem<TemplateVariant, Private, &Private::createDirs> dirs; + CachedItem<TemplateVariant, Private, &Private::createFiles> files; + CachedItem<DotDirDepsPtr, Private, &Private::createDirDepsGraph> dirDepsGraph; }; - Cachable &getCache() const - { - Cachable *c = static_cast<Cachable*>(m_dirDef->cookie()); - assert(c!=0); - return *c; - } - static PropertyMapper<DirContext::Private> s_inst; + Cachable m_cachable; + static const PropertyMap<DirContext::Private> s_inst; +}; + +//%% struct Dir(Symbol): directory information +//%% { +const PropertyMap<DirContext::Private> DirContext::Private::s_inst { + BASE_PROPERTIES, + { "title", &Private::title }, + { "highlight", &Private::highlight }, + { "subhighlight", &Private::subHighlight }, + { "dirName", &Private::dirName }, + { "dirs", &Private::dirs }, + { "files", &Private::files }, + { "hasDetails", &Private::hasDetails }, + { "hasDirGraph", &Private::hasDirGraph }, + { "dirGraph", &Private::dirGraph }, + { "compoundType", &Private::compoundType } }; //%% } -PropertyMapper<DirContext::Private> DirContext::Private::s_inst; +//PropertyMapper<DirContext::Private> DirContext::Private::s_inst; -DirContext::DirContext(const DirDef *fd) : RefCountedContext("DirContext") +DirContext::DirContext(const DirDef *fd) : p(std::make_unique<Private>(fd)) { - p = new Private(fd); } DirContext::~DirContext() { - delete p; } TemplateVariant DirContext::get(const QCString &n) const @@ -3683,8 +3267,6 @@ StringVector DirContext::fields() const //------------------------------------------------------------------------ -//%% struct Page(Symbol): page information -//%% { class PageContext::Private : public DefinitionContext<PageContext::Private> { public: @@ -3692,27 +3274,14 @@ class PageContext::Private : public DefinitionContext<PageContext::Private> : DefinitionContext<PageContext::Private>(pd) , m_pageDef(pd), m_isMainPage(isMainPage), m_isExample(isExample) { - static bool init=FALSE; - if (!init) - { - addBaseProperties(s_inst); - s_inst.addProperty("title", &Private::title); - s_inst.addProperty("highlight", &Private::highlight); - s_inst.addProperty("subhighlight",&Private::subHighlight); - s_inst.addProperty("example", &Private::example); - init=TRUE; - } - if (!pd->cookie()) { pd->setCookie(new PageContext::Private::Cachable(pd)); } } virtual ~Private() {} - TemplateVariant get(const QCString &n) const - { - return s_inst.get(this,n); - } - StringVector fields() const - { - return s_inst.fields(); - } + + // TemplateStructIntf methods + TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); } + StringVector fields() const { return s_inst.fields(); } + + // Property getters TemplateVariant title() const { if (m_isMainPage) @@ -3749,14 +3318,8 @@ class PageContext::Private : public DefinitionContext<PageContext::Private> } TemplateVariant relPath() const { - if (m_isMainPage) - { - return ""; - } - else - { - return DefinitionContext<PageContext::Private>::relPath(); - } + return m_isMainPage ? TemplateVariant("") : + TemplateVariant(DefinitionContext<PageContext::Private>::relPath()); } TemplateVariant highlight() const { @@ -3775,54 +3338,45 @@ class PageContext::Private : public DefinitionContext<PageContext::Private> } TemplateVariant example() const { - if (m_isExample) - { - Cachable &cache = getCache(); - if (!cache.example || g_globals.outputFormat!=cache.exampleOutputFormat) - { - cache.example.reset(new TemplateVariant( - parseDoc(m_pageDef,m_pageDef->docFile(),m_pageDef->docLine(), - relPathAsString(),"\\include "+m_pageDef->name(),FALSE))); - cache.exampleOutputFormat = g_globals.outputFormat; - } - return *cache.example; - } - else - { - return TemplateVariant(""); - } + return m_cachable.example.get(this); } private: + TemplateVariant createExample() const + { + return m_isExample ? + TemplateVariant(parseDoc(m_pageDef,m_pageDef->docFile(),m_pageDef->docLine(), + relPathAsString(),"\\include "+m_pageDef->name(),FALSE)) : + TemplateVariant(""); + } + const PageDef *m_pageDef; struct Cachable : public DefinitionContext<PageContext::Private>::Cachable { - Cachable(const PageDef *pd) : DefinitionContext<PageContext::Private>::Cachable(pd), - exampleOutputFormat(ContextOutputFormat_Unspecified) { } - std::unique_ptr<TemplateVariant> example; - ContextOutputFormat exampleOutputFormat; + CachedItem<TemplateVariant, Private, &Private::createExample> example; }; - Cachable &getCache() const - { - Cachable *c = static_cast<Cachable*>(m_pageDef->cookie()); - assert(c!=0); - return *c; - } + Cachable m_cachable; bool m_isMainPage; bool m_isExample; - static PropertyMapper<PageContext::Private> s_inst; + static const PropertyMap<PageContext::Private> s_inst; }; -//%% } -PropertyMapper<PageContext::Private> PageContext::Private::s_inst; +//%% struct Page(Symbol): page information +//%% { +const PropertyMap<PageContext::Private> PageContext::Private::s_inst { + BASE_PROPERTIES, + { "title", &Private::title }, + { "highlight", &Private::highlight }, + { "subhighlight",&Private::subHighlight }, + { "example", &Private::example } +}; +//%% } -PageContext::PageContext(const PageDef *pd,bool isMainPage,bool isExample) : RefCountedContext("PageContext") +PageContext::PageContext(const PageDef *pd,bool isMainPage,bool isExample) : p(std::make_unique<Private>(pd,isMainPage,isExample)) { - p = new Private(pd,isMainPage,isExample); } PageContext::~PageContext() { - delete p; } TemplateVariant PageContext::get(const QCString &n) const @@ -3906,7 +3460,7 @@ class TextGeneratorHtml : public TextGeneratorIntf } m_ts << "href=\""; m_ts << externalRef(m_relPath,ref,TRUE); - if (!f.isEmpty()) m_ts << f << Doxygen::htmlFileExtension; + if (!f.isEmpty()) m_ts << addHtmlExtensionIfMissing(f); if (!anchor.isEmpty()) m_ts << "#" << anchor; m_ts << "\">"; m_ts << convertToHtml(name); @@ -3983,8 +3537,7 @@ class TextGeneratorFactory public: static TextGeneratorFactory *instance() { - static TextGeneratorFactory *instance = 0; - if (instance==0) instance = new TextGeneratorFactory; + static TextGeneratorFactory *instance = new TextGeneratorFactory; return instance; } TextGeneratorIntf *create(TextStream &ts,const QCString &relPath) @@ -4021,748 +3574,427 @@ TemplateVariant createLinkedText(const Definition *def,const QCString &relPath,c } } -//%% struct Member(Symbol): member information -//%% { class MemberContext::Private : public DefinitionContext<MemberContext::Private> { public: Private(const MemberDef *md) : DefinitionContext<MemberContext::Private>(md) , m_memberDef(md) { - static bool init=FALSE; - if (!init) - { - addBaseProperties(s_inst); - s_inst.addProperty("isSignal", &Private::isSignal); - s_inst.addProperty("isSlot", &Private::isSlot); - s_inst.addProperty("isVariable", &Private::isVariable); - s_inst.addProperty("isEnumeration", &Private::isEnumeration); - s_inst.addProperty("isEnumValue", &Private::isEnumValue); - s_inst.addProperty("isTypedef", &Private::isTypedef); - s_inst.addProperty("isFunction", &Private::isFunction); - s_inst.addProperty("isFunctionPtr", &Private::isFunctionPtr); - s_inst.addProperty("isDefine", &Private::isDefine); - s_inst.addProperty("isFriend", &Private::isFriend); - s_inst.addProperty("isProperty", &Private::isProperty); - s_inst.addProperty("isEvent", &Private::isEvent); - s_inst.addProperty("isRelated", &Private::isRelated); - s_inst.addProperty("isForeign", &Private::isForeign); - s_inst.addProperty("isStatic", &Private::isStatic); - s_inst.addProperty("isInline", &Private::isInline); - s_inst.addProperty("isExplicit", &Private::isExplicit); - s_inst.addProperty("isMutable", &Private::isMutable); - s_inst.addProperty("isGettable", &Private::isGettable); - s_inst.addProperty("isPrivateGettable", &Private::isPrivateGettable); - s_inst.addProperty("isProtectedGettable", &Private::isProtectedGettable); - s_inst.addProperty("isSettable", &Private::isSettable); - s_inst.addProperty("isPrivateSettable", &Private::isPrivateSettable); - s_inst.addProperty("isProtectedSettable", &Private::isProtectedSettable); - s_inst.addProperty("isReadable", &Private::isReadable); - s_inst.addProperty("isWritable", &Private::isWritable); - s_inst.addProperty("isAddable", &Private::isAddable); - s_inst.addProperty("isRemovable", &Private::isRemovable); - s_inst.addProperty("isRaisable", &Private::isRaisable); - s_inst.addProperty("isFinal", &Private::isFinal); - s_inst.addProperty("isAbstract", &Private::isAbstract); - s_inst.addProperty("isOverride", &Private::isOverride); - s_inst.addProperty("isInitonly", &Private::isInitonly); - s_inst.addProperty("isOptional", &Private::isOptional); - s_inst.addProperty("isRequired", &Private::isRequired); - s_inst.addProperty("isNonAtomic", &Private::isNonAtomic); - s_inst.addProperty("isCopy", &Private::isCopy); - s_inst.addProperty("isAssign", &Private::isAssign); - s_inst.addProperty("isRetain", &Private::isRetain); - s_inst.addProperty("isWeak", &Private::isWeak); - s_inst.addProperty("isStrong", &Private::isStrong); - s_inst.addProperty("isEnumStruct", &Private::isEnumStruct); - s_inst.addProperty("isUnretained", &Private::isUnretained); - s_inst.addProperty("isNew", &Private::isNew); - s_inst.addProperty("isSealed", &Private::isSealed); - s_inst.addProperty("isImplementation", &Private::isImplementation); - s_inst.addProperty("isExternal", &Private::isExternal); - s_inst.addProperty("isTypeAlias", &Private::isTypeAlias); - s_inst.addProperty("isDefault", &Private::isDefault); - s_inst.addProperty("isDelete", &Private::isDelete); - s_inst.addProperty("isNoExcept", &Private::isNoExcept); - s_inst.addProperty("isAttribute", &Private::isAttribute); - s_inst.addProperty("isUNOProperty", &Private::isUNOProperty); - s_inst.addProperty("isReadonly", &Private::isReadonly); - s_inst.addProperty("isBound", &Private::isBound); - s_inst.addProperty("isConstrained", &Private::isConstrained); - s_inst.addProperty("isTransient", &Private::isTransient); - s_inst.addProperty("isMaybeVoid", &Private::isMaybeVoid); - s_inst.addProperty("isMaybeDefault", &Private::isMaybeDefault); - s_inst.addProperty("isMaybeAmbiguous", &Private::isMaybeAmbiguous); - s_inst.addProperty("isPublished", &Private::isPublished); - s_inst.addProperty("isTemplateSpecialization",&Private::isTemplateSpecialization); - s_inst.addProperty("isObjCMethod", &Private::isObjCMethod); - s_inst.addProperty("isObjCProperty", &Private::isObjCProperty); - s_inst.addProperty("isAnonymous", &Private::isAnonymous); - s_inst.addProperty("hasParameters", &Private::hasParameters); - s_inst.addProperty("declType", &Private::declType); - s_inst.addProperty("declArgs", &Private::declArgs); - s_inst.addProperty("anonymousType", &Private::anonymousType); - s_inst.addProperty("anonymousMember", &Private::anonymousMember); - s_inst.addProperty("hasDetails", &Private::hasDetails); - s_inst.addProperty("exception", &Private::exception); - s_inst.addProperty("bitfields", &Private::bitfields); - s_inst.addProperty("initializer", &Private::initializer); - s_inst.addProperty("initializerAsCode", &Private::initializerAsCode); - s_inst.addProperty("hasOneLineInitializer", &Private::hasOneLineInitializer); - s_inst.addProperty("hasMultiLineInitializer", &Private::hasMultiLineInitializer); - s_inst.addProperty("templateArgs", &Private::templateArgs); - s_inst.addProperty("templateAlias", &Private::templateAlias); - s_inst.addProperty("propertyAttrs", &Private::propertyAttrs); - s_inst.addProperty("eventAttrs", &Private::eventAttrs); - s_inst.addProperty("category", &Private::category); - s_inst.addProperty("categoryRelation", &Private::categoryRelation); - s_inst.addProperty("class", &Private::getClass); - s_inst.addProperty("file", &Private::getFile); - s_inst.addProperty("namespace", &Private::getNamespace); - s_inst.addProperty("definition", &Private::definition); - s_inst.addProperty("parameters", &Private::parameters); - s_inst.addProperty("hasConstQualifier", &Private::hasConstQualifier); - s_inst.addProperty("hasVolatileQualifier",&Private::hasVolatileQualifier); - s_inst.addProperty("hasRefQualifierLValue", &Private::hasRefQualifierLValue); - s_inst.addProperty("hasRefQualifierRValue", &Private::hasRefQualifierRValue); - s_inst.addProperty("trailingReturnType", &Private::trailingReturnType); - s_inst.addProperty("extraTypeChars", &Private::extraTypeChars); - s_inst.addProperty("templateDecls", &Private::templateDecls); - s_inst.addProperty("labels", &Private::labels); - s_inst.addProperty("enumBaseType", &Private::enumBaseType); - s_inst.addProperty("enumValues", &Private::enumValues); - s_inst.addProperty("paramDocs", &Private::paramDocs); - s_inst.addProperty("reimplements", &Private::reimplements); - s_inst.addProperty("implements", &Private::implements); - s_inst.addProperty("reimplementedBy", &Private::reimplementedBy); - s_inst.addProperty("implementedBy", &Private::implementedBy); - s_inst.addProperty("examples", &Private::examples); - s_inst.addProperty("typeConstraints", &Private::typeConstraints); - s_inst.addProperty("functionQualifier", &Private::functionQualifier); - s_inst.addProperty("sourceRefs", &Private::sourceRefs); - s_inst.addProperty("sourceRefBys", &Private::sourceRefBys); - s_inst.addProperty("hasSources", &Private::hasSources); - s_inst.addProperty("sourceCode", &Private::sourceCode); - s_inst.addProperty("hasCallGraph", &Private::hasCallGraph); - s_inst.addProperty("callGraph", &Private::callGraph); - s_inst.addProperty("hasCallerGraph", &Private::hasCallerGraph); - s_inst.addProperty("callerGraph", &Private::callerGraph); - s_inst.addProperty("hasReferencedByRelation", &Private::hasReferencedByRelation); - s_inst.addProperty("referencedByRelation", &Private::referencedByRelation); - s_inst.addProperty("hasReferencesRelation", &Private::hasReferencesRelation); - s_inst.addProperty("referencesRelation", &Private::referencesRelation); - s_inst.addProperty("fieldType", &Private::fieldType); - s_inst.addProperty("type", &Private::type); - s_inst.addProperty("detailsVisibleFor", &Private::detailsVisibleFor); - s_inst.addProperty("nameWithContextFor", &Private::nameWithContextFor); - init=TRUE; - } - if (!md->cookie()) { md->setCookie(new MemberContext::Private::Cachable(md)); } - - Cachable &cache = getCache(); - cache.propertyAttrs.reset(TemplateList::alloc()); - if (md->isProperty()) - { - if (md->isGettable()) cache.propertyAttrs->append("get"); - if (md->isPrivateGettable()) cache.propertyAttrs->append("private get"); - if (md->isProtectedGettable()) cache.propertyAttrs->append("protected get"); - if (md->isSettable()) cache.propertyAttrs->append("set"); - if (md->isPrivateSettable()) cache.propertyAttrs->append("private set"); - if (md->isProtectedSettable()) cache.propertyAttrs->append("protected set"); - } - cache.eventAttrs.reset(TemplateList::alloc()); - if (md->isEvent()) - { - if (md->isAddable()) cache.eventAttrs->append("add"); - if (md->isRemovable()) cache.eventAttrs->append("remove"); - if (md->isRaisable()) cache.eventAttrs->append("raise"); - } } virtual ~Private() {} - TemplateVariant get(const QCString &n) const - { - return s_inst.get(this,n); - } - StringVector fields() const - { - return s_inst.fields(); - } - TemplateVariant fieldType() const - { - return createLinkedText(m_memberDef,relPathAsString(),m_memberDef->fieldType()); - } - TemplateVariant declType() const + + // TemplateStructIntf methods + TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); } + StringVector fields() const { return s_inst.fields(); } + + // Property getters + TemplateVariant isStatic() const { return m_memberDef->isStatic(); } + TemplateVariant isObjCMethod() const { return m_memberDef->isObjCMethod(); } + TemplateVariant isObjCProperty() const { return m_memberDef->isObjCProperty(); } + TemplateVariant isCSharpProperty() const { return m_memberDef->isCSharpProperty(); } + TemplateVariant isImplementation() const { return m_memberDef->isImplementation(); } + TemplateVariant isSignal() const { return m_memberDef->isSignal(); } + TemplateVariant isSlot() const { return m_memberDef->isSlot(); } + TemplateVariant isTypedef() const { return m_memberDef->isTypedef(); } + TemplateVariant isFunction() const { return m_memberDef->isFunction(); } + TemplateVariant isFunctionPtr() const { return m_memberDef->isFunctionPtr(); } + TemplateVariant isFriend() const { return m_memberDef->isFriend(); } + TemplateVariant isForeign() const { return m_memberDef->isForeign(); } + TemplateVariant isEvent() const { return m_memberDef->isEvent(); } + TemplateVariant isInline() const { return m_memberDef->isInline(); } + TemplateVariant isExplicit() const { return m_memberDef->isExplicit(); } + TemplateVariant isMutable() const { return m_memberDef->isMutable(); } + TemplateVariant isGettable() const { return m_memberDef->isGettable(); } + TemplateVariant isPrivateGettable() const { return m_memberDef->isPrivateGettable(); } + TemplateVariant isProtectedGettable() const { return m_memberDef->isProtectedGettable(); } + TemplateVariant isSettable() const { return m_memberDef->isSettable(); } + TemplateVariant isPrivateSettable() const { return m_memberDef->isPrivateSettable(); } + TemplateVariant isProtectedSettable() const { return m_memberDef->isProtectedSettable(); } + TemplateVariant isReadable() const { return m_memberDef->isReadable(); } + TemplateVariant isWritable() const { return m_memberDef->isWritable(); } + TemplateVariant isAddable() const { return m_memberDef->isAddable(); } + TemplateVariant isRemovable() const { return m_memberDef->isRemovable(); } + TemplateVariant isRaisable() const { return m_memberDef->isRaisable(); } + TemplateVariant isFinal() const { return m_memberDef->isFinal(); } + TemplateVariant isAbstract() const { return m_memberDef->isAbstract(); } + TemplateVariant isOverride() const { return m_memberDef->isOverride(); } + TemplateVariant isInitonly() const { return m_memberDef->isInitonly(); } + TemplateVariant isOptional() const { return m_memberDef->isOptional(); } + TemplateVariant isRequired() const { return m_memberDef->isRequired(); } + TemplateVariant isNonAtomic() const { return m_memberDef->isNonAtomic(); } + TemplateVariant isCopy() const { return m_memberDef->isCopy(); } + TemplateVariant isAssign() const { return m_memberDef->isAssign(); } + TemplateVariant isRetain() const { return m_memberDef->isRetain(); } + TemplateVariant isWeak() const { return m_memberDef->isWeak(); } + TemplateVariant isStrong() const { return m_memberDef->isStrong(); } + TemplateVariant isEnumStruct() const { return m_memberDef->isEnumStruct(); } + TemplateVariant isUnretained() const { return m_memberDef->isUnretained(); } + TemplateVariant isNew() const { return m_memberDef->isNew(); } + TemplateVariant isSealed() const { return m_memberDef->isSealed(); } + TemplateVariant isExternal() const { return m_memberDef->isExternal(); } + TemplateVariant isTypeAlias() const { return m_memberDef->isTypeAlias(); } + TemplateVariant isDefault() const { return m_memberDef->isDefault(); } + TemplateVariant isDelete() const { return m_memberDef->isDelete(); } + TemplateVariant isNoExcept() const { return m_memberDef->isNoExcept(); } + TemplateVariant isAttribute() const { return m_memberDef->isAttribute(); } + TemplateVariant isUNOProperty() const { return m_memberDef->isUNOProperty(); } + TemplateVariant isReadonly() const { return m_memberDef->isReadonly(); } + TemplateVariant isBound() const { return m_memberDef->isBound(); } + TemplateVariant isConstrained() const { return m_memberDef->isConstrained(); } + TemplateVariant isTransient() const { return m_memberDef->isTransient(); } + TemplateVariant isMaybeVoid() const { return m_memberDef->isMaybeVoid(); } + TemplateVariant isMaybeDefault() const { return m_memberDef->isMaybeDefault(); } + TemplateVariant isMaybeAmbiguous() const { return m_memberDef->isMaybeAmbiguous(); } + TemplateVariant isPublished() const { return m_memberDef->isPublished(); } + TemplateVariant isTemplateSpecialization() const { return m_memberDef->isTemplateSpecialization(); } + TemplateVariant isProperty() const { return m_memberDef->isProperty(); } + TemplateVariant isEnumValue() const { return m_memberDef->isEnumValue(); } + TemplateVariant isVariable() const { return m_memberDef->isVariable(); } + TemplateVariant isEnumeration() const { return m_memberDef->isEnumerate(); } + TemplateVariant hasDetails() const { return m_memberDef->hasDetailedDescription(); } + TemplateVariant isDefine() const { return m_memberDef->isDefine(); } + TemplateVariant isAnonymous() const { return m_memberDef->isAnonymous(); } + TemplateVariant isRelated() const { return m_memberDef->isRelated(); } + TemplateVariant enumBaseType() const { return m_memberDef->enumBaseType(); } + TemplateVariant hasOneLineInitializer() const { return m_memberDef->hasOneLineInitializer(); } + TemplateVariant hasMultiLineInitializer() const { return m_memberDef->hasMultiLineInitializer(); } + TemplateVariant extraTypeChars() const { return m_memberDef->extraTypeChars(); } + TemplateVariant type() const { return m_memberDef->typeString(); } + TemplateVariant fieldType() const { return m_cachable.fieldType.get(this); } + TemplateVariant declType() const { return m_cachable.declType.get(this); } + TemplateVariant declArgs() const { return m_cachable.declArgs.get(this); } + TemplateVariant exception() const { return m_cachable.exception.get(this); } + TemplateVariant bitfields() const { return m_cachable.bitfields.get(this); } + TemplateVariant initializer() const { return m_cachable.initializer.get(this); } + TemplateVariant initializerAsCode() const { return m_cachable.initializerAsCode.get(this); } + TemplateVariant anonymousType() const { return m_cachable.anonymousType.get(this); } + TemplateVariant anonymousMember() const { return m_cachable.anonymousMember.get(this); } + TemplateVariant enumValues() const { return m_cachable.enumValues.get(this); } + TemplateVariant templateArgs() const { return m_cachable.templateArgs.get(this); } + TemplateVariant templateAlias() const { return m_cachable.templateAlias.get(this); } + TemplateVariant propertyAttrs() const { return m_cachable.propertyAttrs.get(this); } + TemplateVariant eventAttrs() const { return m_cachable.eventAttrs.get(this); } + TemplateVariant getClass() const { return m_cachable.classDef.get(this); } + TemplateVariant category() const { return m_cachable.category.get(this); } + TemplateVariant categoryRelation() const { return m_cachable.categoryRelation.get(this); } + TemplateVariant getFile() const { return m_cachable.fileDef.get(this); } + TemplateVariant getNamespace() const { return m_cachable.namespaceDef.get(this); } + TemplateVariant definition() const { return m_cachable.definition.get(this); } + TemplateVariant parameters() const { return m_cachable.parameters.get(this); } + TemplateVariant hasParameters() const { return !getDefArgList().empty(); } + TemplateVariant hasConstQualifier() const { return getDefArgList().constSpecifier(); } + TemplateVariant hasVolatileQualifier() const { return getDefArgList().volatileSpecifier(); } + TemplateVariant hasRefQualifierLValue() const { return getDefArgList().refQualifier()==RefQualifierLValue; } + TemplateVariant hasRefQualifierRValue() const { return getDefArgList().refQualifier()==RefQualifierRValue; } + TemplateVariant trailingReturnType() const { return m_cachable.trailingReturnType.get(this); } + TemplateVariant templateDecls() const { return m_cachable.templateDecls.get(this); } + TemplateVariant labels() const { return m_cachable.labels.get(this); } + TemplateVariant paramDocs() const { return m_cachable.paramDocs.get(this); } + TemplateVariant implements() const { return m_cachable.implements.get(this); } + TemplateVariant reimplements() const { return m_cachable.reimplements.get(this); } + TemplateVariant implementedBy() const { return m_cachable.implementedBy.get(this); } + TemplateVariant reimplementedBy() const { return m_cachable.reimplementedBy.get(this); } + TemplateVariant examples() const { return m_cachable.examples.get(this); } + TemplateVariant typeConstraints() const { return m_cachable.typeConstraints.get(this); } + TemplateVariant sourceRefs() const { return m_cachable.sourceRefs.get(this); } + TemplateVariant sourceRefBys() const { return m_cachable.sourceRefBys.get(this); } + TemplateVariant sourceCode() const { return m_cachable.sourceCode.get(this); } + DotCallGraphPtr getCallGraph() const { return m_cachable.callGraph.get(this); } + DotCallGraphPtr getCallerGraph() const { return m_cachable.callerGraph.get(this); } + TemplateVariant hasSources() const { return TemplateVariant(m_memberDef->hasSources()); } + TemplateVariant hasReferencedByRelation() const { return TemplateVariant(m_memberDef->hasReferencedByRelation()); } + TemplateVariant hasReferencesRelation() const { return TemplateVariant(m_memberDef->hasReferencesRelation()); } + + const ArgumentList &getDefArgList() const { - Cachable &cache = getCache(); - if (!cache.declTypeParsed) - { - cache.declType=createLinkedText(m_memberDef,relPathAsString(),m_memberDef->getDeclType()); - cache.declTypeParsed = TRUE; - return cache.declType; - } - else - { - return cache.declType; - } + return (m_memberDef->isDocsForDefinition()) ? + m_memberDef->argumentList() : m_memberDef->declArgumentList(); } - TemplateVariant declArgs() const + + TemplateVariant functionQualifier() const { - Cachable &cache = getCache(); - if (!cache.declArgsParsed) + if (!m_memberDef->isObjCMethod() && + (m_memberDef->isFunction() || m_memberDef->isSlot() || + m_memberDef->isPrototype() || m_memberDef->isSignal() + ) + ) { - cache.declArgs=createLinkedText(m_memberDef,relPathAsString(),m_memberDef->argsString()); - cache.declArgsParsed = TRUE; - return cache.declArgs; + return "()"; } else { - return cache.declArgs; + return ""; } } - TemplateVariant exception() const - { - return createLinkedText(m_memberDef,relPathAsString(),m_memberDef->excpString()); - } - TemplateVariant bitfields() const - { - return createLinkedText(m_memberDef,relPathAsString(),m_memberDef->bitfieldString()); - } - TemplateVariant isStatic() const - { - return m_memberDef->isStatic(); - } - TemplateVariant isObjCMethod() const - { - return m_memberDef->isObjCMethod(); - } - TemplateVariant isObjCProperty() const - { - return m_memberDef->isObjCProperty(); - } - TemplateVariant isImplementation() const - { - return m_memberDef->isImplementation(); - } - TemplateVariant isSignal() const - { - return m_memberDef->isSignal(); - } - TemplateVariant isSlot() const - { - return m_memberDef->isSlot(); - } - TemplateVariant isTypedef() const - { - return m_memberDef->isTypedef(); - } - TemplateVariant isFunction() const - { - return m_memberDef->isFunction(); - } - TemplateVariant isFunctionPtr() const - { - return m_memberDef->isFunctionPtr(); - } - TemplateVariant isFriend() const - { - return m_memberDef->isFriend(); - } - TemplateVariant isForeign() const - { - return m_memberDef->isForeign(); - } - TemplateVariant isEvent() const - { - return m_memberDef->isEvent(); - } - TemplateVariant isInline() const - { - return m_memberDef->isInline(); - } - TemplateVariant isExplicit() const - { - return m_memberDef->isExplicit(); - } - TemplateVariant isMutable() const - { - return m_memberDef->isMutable(); - } - TemplateVariant isGettable() const - { - return m_memberDef->isGettable(); - } - TemplateVariant isPrivateGettable() const - { - return m_memberDef->isPrivateGettable(); - } - TemplateVariant isProtectedGettable() const - { - return m_memberDef->isProtectedGettable(); - } - TemplateVariant isSettable() const - { - return m_memberDef->isSettable(); - } - TemplateVariant isPrivateSettable() const - { - return m_memberDef->isPrivateSettable(); - } - TemplateVariant isProtectedSettable() const - { - return m_memberDef->isProtectedSettable(); - } - TemplateVariant isReadable() const - { - return m_memberDef->isReadable(); - } - TemplateVariant isWritable() const - { - return m_memberDef->isWritable(); - } - TemplateVariant isAddable() const - { - return m_memberDef->isAddable(); - } - TemplateVariant isRemovable() const - { - return m_memberDef->isRemovable(); - } - TemplateVariant isRaisable() const - { - return m_memberDef->isRaisable(); - } - TemplateVariant isFinal() const - { - return m_memberDef->isFinal(); - } - TemplateVariant isAbstract() const - { - return m_memberDef->isAbstract(); - } - TemplateVariant isOverride() const - { - return m_memberDef->isOverride(); - } - TemplateVariant isInitonly() const - { - return m_memberDef->isInitonly(); - } - TemplateVariant isOptional() const - { - return m_memberDef->isOptional(); - } - TemplateVariant isRequired() const - { - return m_memberDef->isRequired(); - } - TemplateVariant isNonAtomic() const - { - return m_memberDef->isNonAtomic(); - } - TemplateVariant isCopy() const - { - return m_memberDef->isCopy(); - } - TemplateVariant isAssign() const - { - return m_memberDef->isAssign(); - } - TemplateVariant isRetain() const - { - return m_memberDef->isRetain(); - } - TemplateVariant isWeak() const - { - return m_memberDef->isWeak(); - } - TemplateVariant isStrong() const - { - return m_memberDef->isStrong(); - } - TemplateVariant isEnumStruct() const - { - return m_memberDef->isEnumStruct(); - } - TemplateVariant isUnretained() const - { - return m_memberDef->isUnretained(); - } - TemplateVariant isNew() const - { - return m_memberDef->isNew(); - } - TemplateVariant isSealed() const - { - return m_memberDef->isSealed(); - } - TemplateVariant isExternal() const - { - return m_memberDef->isExternal(); - } - TemplateVariant isTypeAlias() const - { - return m_memberDef->isTypeAlias(); - } - TemplateVariant isDefault() const - { - return m_memberDef->isDefault(); - } - TemplateVariant isDelete() const - { - return m_memberDef->isDelete(); - } - TemplateVariant isNoExcept() const - { - return m_memberDef->isNoExcept(); - } - TemplateVariant isAttribute() const - { - return m_memberDef->isAttribute(); - } - TemplateVariant isUNOProperty() const - { - return m_memberDef->isUNOProperty(); - } - TemplateVariant isReadonly() const - { - return m_memberDef->isReadonly(); - } - TemplateVariant isBound() const - { - return m_memberDef->isBound(); - } - TemplateVariant isConstrained() const - { - return m_memberDef->isConstrained(); - } - TemplateVariant isTransient() const - { - return m_memberDef->isTransient(); - } - TemplateVariant isMaybeVoid() const - { - return m_memberDef->isMaybeVoid(); - } - TemplateVariant isMaybeDefault() const - { - return m_memberDef->isMaybeDefault(); - } - TemplateVariant isMaybeAmbiguous() const - { - return m_memberDef->isMaybeAmbiguous(); - } - TemplateVariant isPublished() const - { - return m_memberDef->isPublished(); - } - TemplateVariant isTemplateSpecialization() const - { - return m_memberDef->isTemplateSpecialization(); - } - TemplateVariant isProperty() const - { - return m_memberDef->isProperty(); - } - TemplateVariant isEnumValue() const - { - return m_memberDef->isEnumValue(); - } - TemplateVariant isVariable() const - { - return m_memberDef->isVariable(); - } - TemplateVariant isEnumeration() const - { - return m_memberDef->isEnumerate(); - } - TemplateVariant hasDetails() const - { - return m_memberDef->hasDetailedDescription(); - } - TemplateVariant initializer() const - { - return createLinkedText(m_memberDef,relPathAsString(),m_memberDef->initializer()); - } - TemplateVariant initializerAsCode() const + TemplateVariant hasCallGraph() const { - Cachable &cache = getCache(); - if (!cache.initializerParsed) + static bool haveDot = Config_getBool(HAVE_DOT); + if (m_memberDef->hasCallGraph() && haveDot && + (m_memberDef->isFunction() || m_memberDef->isSlot() || m_memberDef->isSignal())) { - QCString scopeName; - if (m_memberDef->getClassDef()) - { - scopeName = m_memberDef->getClassDef()->name(); - } - else if (m_memberDef->getNamespaceDef()) - { - scopeName = m_memberDef->getNamespaceDef()->name(); - } - cache.initializer = parseCode(m_memberDef, - scopeName,relPathAsString(), - m_memberDef->initializer()); - cache.initializerParsed = TRUE; + DotCallGraphPtr cg = getCallGraph(); + return !cg->isTooBig() && !cg->isTrivial(); } - return cache.initializer; - } - TemplateVariant isDefine() const - { - return m_memberDef->isDefine(); - } - TemplateVariant isAnonymous() const - { - return m_memberDef->isAnonymous(); + return TemplateVariant(FALSE); } - TemplateVariant anonymousType() const + TemplateVariant callGraph() const { - Cachable &cache = getCache(); - if (!cache.anonymousType) + if (hasCallGraph().toBool()) { - const ClassDef *cd = m_memberDef->getClassDefOfAnonymousType(); - if (cd) + DotCallGraphPtr cg = getCallGraph(); + TextStream t; + switch (g_globals.outputFormat) { - cache.anonymousType.reset(ClassContext::alloc(cd)); + case ContextOutputFormat_Html: + { + cg->writeGraph(t,GOF_BITMAP,EOF_Html, + g_globals.outputDir, + g_globals.outputDir+Portable::pathSeparator()+addHtmlExtensionIfMissing(m_memberDef->getOutputFileBase()), + relPathAsString(),TRUE,g_globals.dynSectionId + ); + } + break; + case ContextOutputFormat_Latex: + { + cg->writeGraph(t,GOF_EPS,EOF_LaTeX, + g_globals.outputDir, + g_globals.outputDir+Portable::pathSeparator()+m_memberDef->getOutputFileBase()+".tex", + relPathAsString(),TRUE,g_globals.dynSectionId + ); + } + break; + // TODO: support other generators + default: + err("context.cpp: output format not yet supported\n"); + break; } - } - if (cache.anonymousType) - { - return cache.anonymousType.get(); + g_globals.dynSectionId++; + return TemplateVariant(t.str().c_str(),TRUE); } else { - return FALSE; + return TemplateVariant(""); } } - TemplateVariant anonymousMember() const + TemplateVariant referencedByRelation() const { - Cachable &cache = getCache(); - if (!cache.anonymousMember) - { - MemberDef *md = m_memberDef->fromAnonymousMember(); - if (md) - { - cache.anonymousMember.reset(MemberContext::alloc(md)); - } - } - if (cache.anonymousMember) - { - return cache.anonymousMember.get(); - } - else + if (hasReferencedByRelation().toBool()) { - return FALSE; + err("context.cpp: referencedByRelation not yet implemented\n"); } + return TemplateVariant(""); } - TemplateVariant isRelated() const - { - return m_memberDef->isRelated(); - } - TemplateVariant enumBaseType() const - { - return m_memberDef->enumBaseType(); - } - TemplateVariant hasOneLineInitializer() const - { - return m_memberDef->hasOneLineInitializer(); - } - TemplateVariant hasMultiLineInitializer() const + TemplateVariant hasCallerGraph() const { - return m_memberDef->hasMultiLineInitializer(); + static bool haveDot = Config_getBool(HAVE_DOT); + if (m_memberDef->hasCallerGraph() && haveDot && + (m_memberDef->isFunction() || m_memberDef->isSlot() || m_memberDef->isSignal())) + { + DotCallGraphPtr cg = getCallerGraph(); + return !cg->isTooBig() && !cg->isTrivial(); + } + return TemplateVariant(FALSE); } - TemplateVariant enumValues() const + TemplateVariant callerGraph() const { - if (m_memberDef->isEnumerate()) + if (hasCallerGraph().toBool()) { - Cachable &cache = getCache(); - if (!cache.enumValues) + DotCallGraphPtr cg = getCallerGraph(); + TextStream t; + switch (g_globals.outputFormat) { - MemberVector mv = m_memberDef->enumFieldList(); - cache.enumValues.reset(MemberListContext::alloc(std::move(mv))); + case ContextOutputFormat_Html: + { + cg->writeGraph(t,GOF_BITMAP,EOF_Html, + g_globals.outputDir, + g_globals.outputDir+Portable::pathSeparator()+addHtmlExtensionIfMissing(m_memberDef->getOutputFileBase()), + relPathAsString(),TRUE,g_globals.dynSectionId + ); + } + break; + case ContextOutputFormat_Latex: + { + cg->writeGraph(t,GOF_EPS,EOF_LaTeX, + g_globals.outputDir, + g_globals.outputDir+Portable::pathSeparator()+m_memberDef->getOutputFileBase()+".tex", + relPathAsString(),TRUE,g_globals.dynSectionId + ); + } + break; + // TODO: support other generators + default: + err("context.cpp: output format not yet supported\n"); + break; } - return cache.enumValues.get(); + g_globals.dynSectionId++; + return TemplateVariant(t.str().c_str(),TRUE); } else { - return TemplateVariant(FALSE); + return TemplateVariant(""); } } - TemplateVariant templateArgs() const + TemplateVariant referencesRelation() const { - Cachable &cache = getCache(); - if (!cache.templateArgs && !m_memberDef->templateArguments().empty()) + if (hasReferencesRelation().toBool()) { - cache.templateArgs.reset(ArgumentListContext::alloc(m_memberDef->templateArguments(),m_memberDef,relPathAsString())); + err("context.cpp: referencesRelation not yet implemented\n"); } - if (cache.templateArgs) + return TemplateVariant(""); + } + TemplateVariant handleDetailsVisibleFor(const TemplateVariantList &args) const + { + if (args.size()==1) { - return cache.templateArgs.get(); + QCString containerStr = args[0].toString(); + MemberListContainer container = MemberListContainer::Class; + if (containerStr=="module") container = MemberListContainer::Group; + else if (containerStr=="file") container = MemberListContainer::File; + else if (containerStr=="namespace") container = MemberListContainer::Namespace; + return m_memberDef->isDetailedSectionVisible(container); } else { - return TemplateVariant(FALSE); - } - } - TemplateVariant templateAlias() const - { - if (m_memberDef->isTypeAlias()) - { - return createLinkedText(m_memberDef,relPathAsString(), - QCString(" = ")+m_memberDef->typeString()); + err(".detailsVisibleFor should take one string argument, got %zu\n",args.size()); } - return ""; - } - TemplateVariant propertyAttrs() const - { - return getCache().propertyAttrs.get(); + return TemplateVariant(); } - TemplateVariant eventAttrs() const + TemplateVariant detailsVisibleFor() const { - return getCache().eventAttrs.get(); + return TemplateVariant(std::bind(&Private::handleDetailsVisibleFor,this,std::placeholders::_1)); } - TemplateVariant getClass() const + TemplateVariant handleNameWithContextFor(const TemplateVariantList &args) const { - Cachable &cache = getCache(); - if (!cache.classDef && m_memberDef->getClassDef()) - { - cache.classDef.reset(ClassContext::alloc(m_memberDef->getClassDef())); - } - if (cache.classDef) + if (args.size()==1) { - return cache.classDef.get(); + SrcLangExt lang = m_memberDef->getLanguage(); + QCString n = m_memberDef->name(); + QCString ctx = args[0].toString(); + QCString sep = getLanguageSpecificSeparator(lang,TRUE); + if (m_memberDef->getEnumScope() && m_memberDef->livesInsideEnum()) + { + n.prepend(m_memberDef->getEnumScope()->displayName()+sep); + } + if (ctx=="module" && m_memberDef->getClassDef() && !m_memberDef->isRelated()) + { + n.prepend(m_memberDef->getClassDef()->displayName()+sep); + } + else if ((ctx=="module" || ctx=="file") && m_memberDef->getNamespaceDef()) + { + n.prepend(m_memberDef->getNamespaceDef()->displayName()+sep); + } + return n; } else { - return TemplateVariant(FALSE); + err(".nameWithContextFor should take one string argument, got %zu\n",args.size()); } + return TemplateVariant(); + } + TemplateVariant nameWithContextFor() const + { + return TemplateVariant(std::bind(&Private::handleNameWithContextFor,this,std::placeholders::_1)); } - TemplateVariant category() const + + private: + + TemplateVariant createTemplateArgs() const { - Cachable &cache = getCache(); - if (!cache.category && m_memberDef->category()) - { - cache.category.reset(ClassContext::alloc(m_memberDef->category())); - } - if (cache.category) - { - return cache.category.get(); - } - else - { - return TemplateVariant(FALSE); - } + return !m_memberDef->templateArguments().empty() ? + TemplateVariant(ArgumentListContext::alloc(m_memberDef->templateArguments(),m_memberDef,relPathAsString())) : + TemplateVariant(false); } - TemplateVariant categoryRelation() const + TemplateVariant createTemplateAlias() const { - Cachable &cache = getCache(); - if (!cache.categoryRelation && m_memberDef->categoryRelation()) - { - cache.categoryRelation.reset(MemberContext::alloc(m_memberDef->categoryRelation())); - } - if (cache.categoryRelation) - { - return cache.categoryRelation.get(); - } - else - { - return TemplateVariant(FALSE); - } + return m_memberDef->isTypeAlias() ? + TemplateVariant(createLinkedText(m_memberDef,relPathAsString(), + QCString(" = ")+m_memberDef->typeString())) : + TemplateVariant(""); } - TemplateVariant getFile() const + TemplateVariant createPropertyAttrs() const { - Cachable &cache = getCache(); - if (!cache.fileDef && m_memberDef->getFileDef()) + TemplateVariantList list; + list.reserve(6); + if (m_memberDef->isProperty()) { - cache.fileDef.reset(FileContext::alloc(m_memberDef->getFileDef())); - } - if (cache.fileDef) - { - return cache.fileDef.get(); - } - else - { - return TemplateVariant(FALSE); + if (m_memberDef->isGettable()) list.push_back("get"); + if (m_memberDef->isPrivateGettable()) list.push_back("private get"); + if (m_memberDef->isProtectedGettable()) list.push_back("protected get"); + if (m_memberDef->isSettable()) list.push_back("set"); + if (m_memberDef->isPrivateSettable()) list.push_back("private set"); + if (m_memberDef->isProtectedSettable()) list.push_back("protected set"); } + return TemplateImmutableList::alloc(list); } - TemplateVariant getNamespace() const + TemplateVariant createEventAttrs() const { - Cachable &cache = getCache(); - if (!cache.namespaceDef && m_memberDef->getNamespaceDef()) - { - cache.namespaceDef.reset(NamespaceContext::alloc(m_memberDef->getNamespaceDef())); - } - if (cache.namespaceDef) + TemplateVariantList list; + list.reserve(3); + if (m_memberDef->isEvent()) { - return cache.namespaceDef.get(); - } - else - { - return TemplateVariant(FALSE); + if (m_memberDef->isAddable()) list.push_back("add"); + if (m_memberDef->isRemovable()) list.push_back("remove"); + if (m_memberDef->isRaisable()) list.push_back("raise"); } + return TemplateImmutableList::alloc(list); } - TemplateVariant definition() const + TemplateVariant createParameters() const { - return createLinkedText(m_memberDef,relPathAsString(), - m_memberDef->displayDefinition()); + const ArgumentList &defArgList = getDefArgList(); + return !m_memberDef->isProperty() ? + ArgumentListContext::alloc(defArgList,m_memberDef,relPathAsString()) : + ArgumentListContext::alloc(); } - const ArgumentList &getDefArgList() const + TemplateVariant createEnumValues() const { - return (m_memberDef->isDocsForDefinition()) ? - m_memberDef->argumentList() : m_memberDef->declArgumentList(); + return m_memberDef->isEnumerate() ? + TemplateVariant(MemberListContext::alloc(m_memberDef->enumFieldList())) : + TemplateVariant(false); } - TemplateVariant parameters() const + TemplateVariant createFileDef() const { - Cachable &cache = getCache(); - if (!cache.arguments) - { - const ArgumentList &defArgList = getDefArgList(); - if (!m_memberDef->isProperty()) - { - cache.arguments.reset(ArgumentListContext::alloc(defArgList,m_memberDef,relPathAsString())); - } - else - { - cache.arguments.reset(ArgumentListContext::alloc()); - } - } - return cache.arguments.get(); + return m_memberDef->getFileDef() ? + TemplateVariant(FileContext::alloc(m_memberDef->getFileDef())) : + TemplateVariant(false); } - TemplateVariant hasParameters() const + TemplateVariant createNamespaceDef() const { - return !getDefArgList().empty(); + return m_memberDef->getNamespaceDef() ? + TemplateVariant(NamespaceContext::alloc(m_memberDef->getNamespaceDef())) : + TemplateVariant(false); } - TemplateVariant hasConstQualifier() const + TemplateVariant createClassDef() const { - return getDefArgList().constSpecifier(); + return m_memberDef->getClassDef() ? + TemplateVariant(ClassContext::alloc(m_memberDef->getClassDef())) : + TemplateVariant(false); } - TemplateVariant hasVolatileQualifier() const + TemplateVariant createCategory() const { - return getDefArgList().volatileSpecifier(); + return m_memberDef->category() ? + TemplateVariant(ClassContext::alloc(m_memberDef->category())) : + TemplateVariant(false); } - TemplateVariant hasRefQualifierLValue() const + TemplateVariant createCategoryRelation() const { - return getDefArgList().refQualifier()==RefQualifierLValue; + return m_memberDef->categoryRelation() ? + TemplateVariant(MemberContext::alloc(m_memberDef->categoryRelation())) : + TemplateVariant(false); } - TemplateVariant hasRefQualifierRValue() const + TemplateVariant createDefinition() const { - return getDefArgList().refQualifier()==RefQualifierRValue; + return createLinkedText(m_memberDef,relPathAsString(), + m_memberDef->displayDefinition()); } - TemplateVariant trailingReturnType() const + TemplateVariant createTrailingReturnType() const { const ArgumentList &al = getDefArgList(); - if (!al.trailingReturnType().isEmpty()) - { - return createLinkedText(m_memberDef,relPathAsString(), - al.trailingReturnType()); - } - else - { - return ""; - } + return !al.trailingReturnType().isEmpty() ? + TemplateVariant(createLinkedText(m_memberDef,relPathAsString(), al.trailingReturnType())) : + TemplateVariant(""); } - TemplateVariant extraTypeChars() const - { - return m_memberDef->extraTypeChars(); - } - void addTemplateDecls(TemplateList *tl) const + TemplateVariant createTemplateDecls() const { + TemplateVariantList list; const ClassDef *cd=m_memberDef->getClassDef(); if (!m_memberDef->definitionTemplateParameterLists().empty()) { @@ -4770,8 +4002,7 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private> { if (!tal.empty()) { - ArgumentListContext *al = ArgumentListContext::alloc(tal,m_memberDef,relPathAsString()); - tl->append(al); + list.push_back(ArgumentListContext::alloc(tal,m_memberDef,relPathAsString())); } } } @@ -4783,520 +4014,409 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private> { if (!tal.empty()) { - ArgumentListContext *al = ArgumentListContext::alloc(tal,m_memberDef,relPathAsString()); - tl->append(al); + list.push_back(ArgumentListContext::alloc(tal,m_memberDef,relPathAsString())); } } } if (!m_memberDef->templateArguments().empty()) // function template prefix { - ArgumentListContext *al = ArgumentListContext::alloc( - m_memberDef->templateArguments(),m_memberDef,relPathAsString()); - tl->append(al); + list.push_back(ArgumentListContext::alloc( + m_memberDef->templateArguments(),m_memberDef,relPathAsString())); } } + return TemplateImmutableList::alloc(list); } - TemplateVariant templateDecls() const - { - Cachable &cache = getCache(); - if (!cache.templateDecls) - { - TemplateList *tl = TemplateList::alloc(); - addTemplateDecls(tl); - cache.templateDecls.reset(tl); - } - return cache.templateDecls.get(); - } - TemplateVariant labels() const + TemplateVariant createAnonymousType() const { - Cachable &cache = getCache(); - if (!cache.labels) - { - StringVector sl = m_memberDef->getLabels(m_memberDef->getOuterScope()); - TemplateList *tl = TemplateList::alloc(); - for (const auto &s : sl) - { - tl->append(s.c_str()); - } - cache.labels.reset(tl); - } - return cache.labels.get(); + const ClassDef *cd = m_memberDef->getClassDefOfAnonymousType(); + return cd ? TemplateVariant(ClassContext::alloc(cd)) : TemplateVariant(false); } - TemplateVariant paramDocs() const + TemplateVariant createParamDocs() const { - Cachable &cache = getCache(); - if (!cache.paramDocs) + if (m_memberDef->argumentList().hasDocumentation()) { - if (m_memberDef->argumentList().hasDocumentation()) + QCString paramDocs; + for (const Argument &a : m_memberDef->argumentList()) { - QCString paramDocs; - for (const Argument &a : m_memberDef->argumentList()) + if (a.hasDocumentation()) { - if (a.hasDocumentation()) - { - QCString docs = a.docs; - QCString direction = extractDirection(docs); - paramDocs+="@param"+direction+" "+a.name+" "+docs; - } + QCString docs = a.docs; + QCString direction = extractDirection(docs); + paramDocs+="@param"+direction+" "+a.name+" "+docs; } - cache.paramDocs.reset(new TemplateVariant(parseDoc(m_memberDef, - m_memberDef->docFile(),m_memberDef->docLine(), - relPathAsString(),paramDocs,FALSE))); - } - else - { - cache.paramDocs.reset(new TemplateVariant("")); } + return TemplateVariant(parseDoc(m_memberDef, + m_memberDef->docFile(),m_memberDef->docLine(), + relPathAsString(),paramDocs,FALSE)); } - return *cache.paramDocs; + return TemplateVariant(""); } - TemplateVariant implements() const + TemplateVariant createImplements() const { - Cachable &cache = getCache(); - if (!cache.implements) + const MemberDef *md = m_memberDef->reimplements(); + TemplateVariantList list; + if (md) { - const MemberDef *md = m_memberDef->reimplements(); - cache.implements.reset(TemplateList::alloc()); - if (md) + const ClassDef *cd = md->getClassDef(); + // filter on pure virtual/interface methods + if (cd && (md->virtualness()==Pure || cd->compoundType()==ClassDef::Interface)) { - const ClassDef *cd = md->getClassDef(); - // filter on pure virtual/interface methods - if (cd && (md->virtualness()==Pure || cd->compoundType()==ClassDef::Interface)) - { - MemberContext *mc = MemberContext::alloc(md); - cache.implements->append(mc); - } + list.push_back(MemberContext::alloc(md)); } } - return cache.implements.get(); + return TemplateImmutableList::alloc(list); } - TemplateVariant reimplements() const + TemplateVariant createReimplements() const { - Cachable &cache = getCache(); - if (!cache.reimplements) + const MemberDef *md = m_memberDef->reimplements(); + TemplateVariantList list; + if (md) { - const MemberDef *md = m_memberDef->reimplements(); - cache.reimplements.reset(TemplateList::alloc()); - if (md) + const ClassDef *cd = md->getClassDef(); + // filter on non-pure virtual & non interface methods + if (cd && md->virtualness()!=Pure && cd->compoundType()!=ClassDef::Interface) { - const ClassDef *cd = md->getClassDef(); - // filter on non-pure virtual & non interface methods - if (cd && md->virtualness()!=Pure && cd->compoundType()!=ClassDef::Interface) - { - MemberContext *mc = MemberContext::alloc(md); - cache.reimplements->append(mc); - } + list.push_back(MemberContext::alloc(md)); } } - return cache.reimplements.get(); + return TemplateImmutableList::alloc(list); } - TemplateVariant implementedBy() const + TemplateVariant createImplementedBy() const { - Cachable &cache = getCache(); - if (!cache.implementedBy) + TemplateVariantList list; + list.reserve(m_memberDef->reimplementedBy().size()); + for (const auto &md : m_memberDef->reimplementedBy()) { - cache.implementedBy.reset(TemplateList::alloc()); - for (const auto &md : m_memberDef->reimplementedBy()) + const ClassDef *cd = md->getClassDef(); + // filter on pure virtual/interface methods + if (cd && md->virtualness()==Pure && cd->compoundType()==ClassDef::Interface) { - const ClassDef *cd = md->getClassDef(); - // filter on pure virtual/interface methods - if (cd && md->virtualness()==Pure && cd->compoundType()==ClassDef::Interface) - { - MemberContext *mc = new MemberContext(md); - cache.implementedBy->append(mc); - } + list.push_back(MemberContext::alloc(md)); } } - return cache.implementedBy.get(); + return TemplateImmutableList::alloc(list); } - TemplateVariant reimplementedBy() const + TemplateVariant createReimplementedBy() const { - Cachable &cache = getCache(); - if (!cache.reimplementedBy) + TemplateVariantList list; + list.reserve(m_memberDef->reimplementedBy().size()); + for (const auto &md : m_memberDef->reimplementedBy()) { - cache.reimplementedBy.reset(TemplateList::alloc()); - for (const auto &md : m_memberDef->reimplementedBy()) + const ClassDef *cd = md->getClassDef(); + // filter on non-pure virtual & non interface methods + if (cd && md->virtualness()!=Pure && cd->compoundType()!=ClassDef::Interface) { - const ClassDef *cd = md->getClassDef(); - // filter on non-pure virtual & non interface methods - if (cd && md->virtualness()!=Pure && cd->compoundType()!=ClassDef::Interface) - { - MemberContext *mc = new MemberContext(md); - cache.reimplementedBy->append(mc); - } + list.push_back(MemberContext::alloc(md)); } } - return cache.reimplementedBy.get(); + return TemplateImmutableList::alloc(list); } - void addExamples(TemplateList *list) const + TemplateVariant createExamples() const { + TemplateVariantList list; if (m_memberDef->hasExamples()) { + list.reserve(m_memberDef->getExamples().size()); for (const auto &ex : m_memberDef->getExamples()) { - TemplateStruct *s = TemplateStruct::alloc(); - s->set("text",ex.name); - s->set("isLinkable",TRUE); - s->set("anchor",ex.anchor); - s->set("fileName",ex.file); - s->set("isReference",FALSE); - s->set("externalReference",""); - list->append(s); + TemplateStructIntfPtr s = TemplateImmutableStruct::alloc( + { + { "text", TemplateVariant(ex.name) }, + { "isLinkable", TemplateVariant(TRUE) }, + { "anchor", TemplateVariant(ex.anchor) }, + { "fileName", TemplateVariant(ex.file) }, + { "isReference", TemplateVariant(FALSE) }, + { "externalReference",TemplateVariant("") } + }); + list.push_back(s); } } + return TemplateImmutableList::alloc(list); } - TemplateVariant examples() const - { - Cachable &cache = getCache(); - if (!cache.examples) - { - TemplateList *exampleList = TemplateList::alloc(); - addExamples(exampleList); - cache.examples.reset(exampleList); - } - return cache.examples.get(); - } - TemplateVariant typeConstraints() const + TemplateVariant createSourceRefs() const { - Cachable &cache = getCache(); - if (cache.typeConstraints && !m_memberDef->typeConstraints().empty()) - { - cache.typeConstraints.reset(ArgumentListContext::alloc(m_memberDef->typeConstraints(),m_memberDef,relPathAsString())); - } - else - { - cache.typeConstraints.reset(ArgumentListContext::alloc()); - } - return cache.typeConstraints.get(); + return MemberListContext::alloc(m_memberDef->getReferencesMembers()); } - TemplateVariant functionQualifier() const + TemplateVariant createSourceRefBys() const { - if (!m_memberDef->isObjCMethod() && - (m_memberDef->isFunction() || m_memberDef->isSlot() || - m_memberDef->isPrototype() || m_memberDef->isSignal() - ) - ) - { - return "()"; - } - else - { - return ""; - } - } - TemplateVariant sourceRefs() const - { - Cachable &cache = getCache(); - if (!cache.sourceRefs) - { - cache.sourceRefs.reset(MemberListContext::alloc(m_memberDef->getReferencesMembers())); - } - return cache.sourceRefs.get(); - } - TemplateVariant sourceRefBys() const - { - Cachable &cache = getCache(); - if (!cache.sourceRefBys) - { - cache.sourceRefBys.reset(MemberListContext::alloc(m_memberDef->getReferencedByMembers())); - } - return cache.sourceRefBys.get(); - } - TemplateVariant hasSources() const - { - return TemplateVariant(m_memberDef->hasSources()); - } - TemplateVariant sourceCode() const - { - Cachable &cache = getCache(); - if (!cache.sourceCodeParsed) - { - QCString codeFragment; - const FileDef *fd = m_memberDef->getBodyDef(); - int startLine = m_memberDef->getStartBodyLine(); - int endLine = m_memberDef->getEndBodyLine(); - if (fd && readCodeFragment(fd->absFilePath(), - startLine,endLine,codeFragment) - ) - { - QCString scopeName; - if (m_memberDef->getClassDef()) - { - scopeName = m_memberDef->getClassDef()->name(); - } - else if (m_memberDef->getNamespaceDef()) - { - scopeName = m_memberDef->getNamespaceDef()->name(); - } - cache.sourceCode = parseCode(m_memberDef, - scopeName,relPathAsString(), - codeFragment,startLine,endLine,TRUE); - cache.sourceCodeParsed = TRUE; - } - } - return cache.sourceCode; + return MemberListContext::alloc(m_memberDef->getReferencedByMembers()); } - DotCallGraph *getCallGraph() const + DotCallGraphPtr createCallGraph() const { - Cachable &cache = getCache(); - if (!cache.callGraph) - { - cache.callGraph.reset(new DotCallGraph(m_memberDef,FALSE)); - } - return cache.callGraph.get(); + return std::make_shared<DotCallGraph>(m_memberDef,FALSE); } - TemplateVariant hasCallGraph() const + DotCallGraphPtr createCallerGraph() const { - static bool haveDot = Config_getBool(HAVE_DOT); - if (m_memberDef->hasCallGraph() && haveDot && - (m_memberDef->isFunction() || m_memberDef->isSlot() || m_memberDef->isSignal())) - { - DotCallGraph *cg = getCallGraph(); - return !cg->isTooBig() && !cg->isTrivial(); - } - return TemplateVariant(FALSE); + return std::make_shared<DotCallGraph>(m_memberDef,TRUE); } - TemplateVariant hasReferencedByRelation() const + TemplateVariant createAnonymousMember() const { - return TemplateVariant(m_memberDef->hasReferencedByRelation()); + return m_memberDef->fromAnonymousMember() ? + TemplateVariant(MemberContext::alloc(m_memberDef)) : + TemplateVariant(false); } - TemplateVariant callGraph() const + TemplateVariant createLabels() const { - if (hasCallGraph().toBool()) - { - DotCallGraph *cg = getCallGraph(); - TextStream t; - switch (g_globals.outputFormat) - { - case ContextOutputFormat_Html: - { - cg->writeGraph(t,GOF_BITMAP,EOF_Html, - g_globals.outputDir, - g_globals.outputDir+Portable::pathSeparator()+m_memberDef->getOutputFileBase()+Doxygen::htmlFileExtension, - relPathAsString(),TRUE,g_globals.dynSectionId - ); - } - break; - case ContextOutputFormat_Latex: - { - cg->writeGraph(t,GOF_EPS,EOF_LaTeX, - g_globals.outputDir, - g_globals.outputDir+Portable::pathSeparator()+m_memberDef->getOutputFileBase()+".tex", - relPathAsString(),TRUE,g_globals.dynSectionId - ); - } - break; - // TODO: support other generators - default: - err("context.cpp: output format not yet supported\n"); - break; - } - g_globals.dynSectionId++; - return TemplateVariant(t.str().c_str(),TRUE); - } - else + StringVector sl = m_memberDef->getLabels(m_memberDef->getOuterScope()); + TemplateVariantList list; + list.reserve(sl.size()); + for (const auto &s : sl) { - return TemplateVariant(""); + list.push_back(s.c_str()); } + return TemplateImmutableList::alloc(list); } - TemplateVariant referencedByRelation() const + TemplateVariant createTypeConstraints() const { - if (hasReferencedByRelation().toBool()) - { - err("context.cpp: output format not yet supported\n"); - } - return TemplateVariant(""); + return !m_memberDef->typeConstraints().empty() ? + TemplateVariant(ArgumentListContext::alloc(m_memberDef->typeConstraints(),m_memberDef,relPathAsString())) : + TemplateVariant(ArgumentListContext::alloc()); } - DotCallGraph *getCallerGraph() const + TemplateVariant createInitializerAsCode() const { - Cachable &cache = getCache(); - if (!cache.callerGraph) + QCString scopeName; + if (m_memberDef->getClassDef()) { - cache.callerGraph.reset(new DotCallGraph(m_memberDef,TRUE)); + scopeName = m_memberDef->getClassDef()->name(); } - return cache.callerGraph.get(); - } - TemplateVariant hasCallerGraph() const - { - static bool haveDot = Config_getBool(HAVE_DOT); - if (m_memberDef->hasCallerGraph() && haveDot && - (m_memberDef->isFunction() || m_memberDef->isSlot() || m_memberDef->isSignal())) + else if (m_memberDef->getNamespaceDef()) { - DotCallGraph *cg = getCallerGraph(); - return !cg->isTooBig() && !cg->isTrivial(); + scopeName = m_memberDef->getNamespaceDef()->name(); } - return TemplateVariant(FALSE); + return TemplateVariant(parseCode(m_memberDef, + scopeName,relPathAsString(), + m_memberDef->initializer())); } - TemplateVariant hasReferencesRelation() const + TemplateVariant createInitializer() const { - return TemplateVariant(m_memberDef->hasReferencesRelation()); + return createLinkedText(m_memberDef,relPathAsString(),m_memberDef->initializer()); } - TemplateVariant callerGraph() const + TemplateVariant createSourceCode() const { - if (hasCallerGraph().toBool()) + QCString codeFragment; + const FileDef *fd = m_memberDef->getBodyDef(); + int startLine = m_memberDef->getStartBodyLine(); + int endLine = m_memberDef->getEndBodyLine(); + if (fd && readCodeFragment(fd->absFilePath(),startLine,endLine,codeFragment)) { - DotCallGraph *cg = getCallerGraph(); - TextStream t; - switch (g_globals.outputFormat) + QCString scopeName; + if (m_memberDef->getClassDef()) { - case ContextOutputFormat_Html: - { - cg->writeGraph(t,GOF_BITMAP,EOF_Html, - g_globals.outputDir, - g_globals.outputDir+Portable::pathSeparator()+m_memberDef->getOutputFileBase()+Doxygen::htmlFileExtension, - relPathAsString(),TRUE,g_globals.dynSectionId - ); - } - break; - case ContextOutputFormat_Latex: - { - cg->writeGraph(t,GOF_EPS,EOF_LaTeX, - g_globals.outputDir, - g_globals.outputDir+Portable::pathSeparator()+m_memberDef->getOutputFileBase()+".tex", - relPathAsString(),TRUE,g_globals.dynSectionId - ); - } - break; - // TODO: support other generators - default: - err("context.cpp: output format not yet supported\n"); - break; + scopeName = m_memberDef->getClassDef()->name(); } - g_globals.dynSectionId++; - return TemplateVariant(t.str().c_str(),TRUE); - } - else - { - return TemplateVariant(""); - } - } - TemplateVariant referencesRelation() const - { - if (hasReferencesRelation().toBool()) - { - err("context.cpp: output format not yet supported\n"); + else if (m_memberDef->getNamespaceDef()) + { + scopeName = m_memberDef->getNamespaceDef()->name(); + } + return parseCode(m_memberDef, + scopeName,relPathAsString(), + codeFragment,startLine,endLine,TRUE); } return TemplateVariant(""); } - TemplateVariant type() const + TemplateVariant createDeclType() const { - return m_memberDef->typeString(); + return createLinkedText(m_memberDef,relPathAsString(),m_memberDef->getDeclType()); } - TemplateVariant handleDetailsVisibleFor(const std::vector<TemplateVariant> &args) const + TemplateVariant createDeclArgs() const { - if (args.size()==1) - { - QCString containerStr = args[0].toString(); - MemberListContainer container = MemberListContainer::Class; - if (containerStr=="module") container = MemberListContainer::Group; - else if (containerStr=="file") container = MemberListContainer::File; - else if (containerStr=="namespace") container = MemberListContainer::Namespace; - return m_memberDef->isDetailedSectionVisible(container); - } - else - { - err(".detailsVisibleFor should take one string argument, got %zu\n",args.size()); - } - return TemplateVariant(); + return createLinkedText(m_memberDef,relPathAsString(),m_memberDef->argsString()); } - TemplateVariant detailsVisibleFor() const + TemplateVariant createFieldType() const { - return TemplateVariant::FunctionDelegate::fromMethod<Private,&Private::handleDetailsVisibleFor>(this); + return createLinkedText(m_memberDef,relPathAsString(),m_memberDef->fieldType()); } - TemplateVariant handleNameWithContextFor(const std::vector<TemplateVariant> &args) const + TemplateVariant createException() const { - if (args.size()==1) - { - SrcLangExt lang = m_memberDef->getLanguage(); - QCString n = m_memberDef->name(); - QCString ctx = args[0].toString(); - QCString sep = getLanguageSpecificSeparator(lang,TRUE); - if (m_memberDef->getEnumScope() && m_memberDef->livesInsideEnum()) - { - n.prepend(m_memberDef->getEnumScope()->displayName()+sep); - } - if (ctx=="module" && m_memberDef->getClassDef() && !m_memberDef->isRelated()) - { - n.prepend(m_memberDef->getClassDef()->displayName()+sep); - } - else if ((ctx=="module" || ctx=="file") && m_memberDef->getNamespaceDef()) - { - n.prepend(m_memberDef->getNamespaceDef()->displayName()+sep); - } - return n; - } - else - { - err(".nameWithContextFor should take one string argument, got %zu\n",args.size()); - } - return TemplateVariant(); + return createLinkedText(m_memberDef,relPathAsString(),m_memberDef->excpString()); } - TemplateVariant nameWithContextFor() const + TemplateVariant createBitfields() const { - return TemplateVariant::FunctionDelegate::fromMethod<Private,&Private::handleNameWithContextFor>(this); + return createLinkedText(m_memberDef,relPathAsString(),m_memberDef->bitfieldString()); } - private: + const MemberDef *m_memberDef; struct Cachable : public DefinitionContext<MemberContext::Private>::Cachable { - Cachable(const MemberDef *md) : DefinitionContext<MemberContext::Private>::Cachable(md), - initializerParsed(FALSE), sourceCodeParsed(FALSE), - declArgsParsed(FALSE), declTypeParsed(FALSE) { } - SharedPtr<ArgumentListContext> templateArgs; - SharedPtr<ArgumentListContext> arguments; - SharedPtr<MemberListContext> enumValues; - SharedPtr<FileContext> fileDef; - SharedPtr<NamespaceContext> namespaceDef; - SharedPtr<ClassContext> category; - SharedPtr<MemberContext> categoryRelation; - SharedPtr<ClassContext> classDef; - SharedPtr<ClassContext> anonymousType; - SharedPtr<TemplateList> templateDecls; - std::unique_ptr<TemplateVariant> paramDocs; - SharedPtr<TemplateList> implements; - SharedPtr<TemplateList> reimplements; - SharedPtr<TemplateList> implementedBy; - SharedPtr<MemberListContext> sourceRefs; - SharedPtr<MemberListContext> sourceRefBys; - std::unique_ptr<DotCallGraph> callGraph; - std::unique_ptr<DotCallGraph> callerGraph; - SharedPtr<MemberContext> anonymousMember; - SharedPtr<TemplateList> reimplementedBy; - SharedPtr<TemplateList> labels; - TemplateVariant initializer; - bool initializerParsed; - TemplateVariant sourceCode; - bool sourceCodeParsed; - TemplateVariant declArgs; - bool declArgsParsed; - TemplateVariant declType; - bool declTypeParsed; - SharedPtr<TemplateList> examples; - SharedPtr<TemplateList> exampleList; - SharedPtr<ArgumentListContext> typeConstraints; - SharedPtr<TemplateList> propertyAttrs; - SharedPtr<TemplateList> eventAttrs; + CachedItem<TemplateVariant, Private, &Private::createTemplateArgs> templateArgs; + CachedItem<TemplateVariant, Private, &Private::createTemplateAlias> templateAlias; + CachedItem<TemplateVariant, Private, &Private::createPropertyAttrs> propertyAttrs; + CachedItem<TemplateVariant, Private, &Private::createEventAttrs> eventAttrs; + CachedItem<TemplateVariant, Private, &Private::createParameters> parameters; + CachedItem<TemplateVariant, Private, &Private::createEnumValues> enumValues; + CachedItem<TemplateVariant, Private, &Private::createFileDef> fileDef; + CachedItem<TemplateVariant, Private, &Private::createNamespaceDef> namespaceDef; + CachedItem<TemplateVariant, Private, &Private::createCategory> category; + CachedItem<TemplateVariant, Private, &Private::createCategoryRelation> categoryRelation; + CachedItem<TemplateVariant, Private, &Private::createDefinition> definition; + CachedItem<TemplateVariant, Private, &Private::createTrailingReturnType> trailingReturnType; + CachedItem<TemplateVariant, Private, &Private::createTemplateDecls> templateDecls; + CachedItem<TemplateVariant, Private, &Private::createClassDef> classDef; + CachedItem<TemplateVariant, Private, &Private::createAnonymousType> anonymousType; + CachedItem<TemplateVariant, Private, &Private::createParamDocs> paramDocs; + CachedItem<TemplateVariant, Private, &Private::createImplements> implements; + CachedItem<TemplateVariant, Private, &Private::createReimplements> reimplements; + CachedItem<TemplateVariant, Private, &Private::createImplementedBy> implementedBy; + CachedItem<TemplateVariant, Private, &Private::createReimplementedBy> reimplementedBy; + CachedItem<TemplateVariant, Private, &Private::createExamples> examples; + CachedItem<TemplateVariant, Private, &Private::createSourceRefs> sourceRefs; + CachedItem<TemplateVariant, Private, &Private::createSourceRefBys> sourceRefBys; + CachedItem<DotCallGraphPtr, Private, &Private::createCallGraph> callGraph; + CachedItem<DotCallGraphPtr, Private, &Private::createCallerGraph> callerGraph; + CachedItem<TemplateVariant, Private, &Private::createAnonymousMember> anonymousMember; + CachedItem<TemplateVariant, Private, &Private::createLabels> labels; + CachedItem<TemplateVariant, Private, &Private::createTypeConstraints> typeConstraints; + CachedItem<TemplateVariant, Private, &Private::createInitializer> initializer; + CachedItem<TemplateVariant, Private, &Private::createInitializerAsCode> initializerAsCode; + CachedItem<TemplateVariant, Private, &Private::createSourceCode> sourceCode; + CachedItem<TemplateVariant, Private, &Private::createDeclArgs> declArgs; + CachedItem<TemplateVariant, Private, &Private::createDeclType> declType; + CachedItem<TemplateVariant, Private, &Private::createFieldType> fieldType; + CachedItem<TemplateVariant, Private, &Private::createException> exception; + CachedItem<TemplateVariant, Private, &Private::createBitfields> bitfields; }; - Cachable &getCache() const - { - Cachable *c = static_cast<Cachable*>(m_memberDef->cookie()); - assert(c!=0); - return *c; - } - static PropertyMapper<MemberContext::Private> s_inst; + Cachable m_cachable; + static const PropertyMap<MemberContext::Private> s_inst; +}; + +//%% struct Member(Symbol): member information +//%% { +const PropertyMap<MemberContext::Private> MemberContext::Private::s_inst { + BASE_PROPERTIES, + { "isSignal", &Private::isSignal }, + { "isSlot", &Private::isSlot }, + { "isVariable", &Private::isVariable }, + { "isEnumeration", &Private::isEnumeration }, + { "isEnumValue", &Private::isEnumValue }, + { "isTypedef", &Private::isTypedef }, + { "isFunction", &Private::isFunction }, + { "isFunctionPtr", &Private::isFunctionPtr }, + { "isDefine", &Private::isDefine }, + { "isFriend", &Private::isFriend }, + { "isProperty", &Private::isProperty }, + { "isEvent", &Private::isEvent }, + { "isRelated", &Private::isRelated }, + { "isForeign", &Private::isForeign }, + { "isStatic", &Private::isStatic }, + { "isInline", &Private::isInline }, + { "isExplicit", &Private::isExplicit }, + { "isMutable", &Private::isMutable }, + { "isGettable", &Private::isGettable }, + { "isPrivateGettable", &Private::isPrivateGettable }, + { "isProtectedGettable", &Private::isProtectedGettable }, + { "isSettable", &Private::isSettable }, + { "isPrivateSettable", &Private::isPrivateSettable }, + { "isProtectedSettable", &Private::isProtectedSettable }, + { "isReadable", &Private::isReadable }, + { "isWritable", &Private::isWritable }, + { "isAddable", &Private::isAddable }, + { "isRemovable", &Private::isRemovable }, + { "isRaisable", &Private::isRaisable }, + { "isFinal", &Private::isFinal }, + { "isAbstract", &Private::isAbstract }, + { "isOverride", &Private::isOverride }, + { "isInitonly", &Private::isInitonly }, + { "isOptional", &Private::isOptional }, + { "isRequired", &Private::isRequired }, + { "isNonAtomic", &Private::isNonAtomic }, + { "isCopy", &Private::isCopy }, + { "isAssign", &Private::isAssign }, + { "isRetain", &Private::isRetain }, + { "isWeak", &Private::isWeak }, + { "isStrong", &Private::isStrong }, + { "isEnumStruct", &Private::isEnumStruct }, + { "isUnretained", &Private::isUnretained }, + { "isNew", &Private::isNew }, + { "isSealed", &Private::isSealed }, + { "isImplementation", &Private::isImplementation }, + { "isExternal", &Private::isExternal }, + { "isTypeAlias", &Private::isTypeAlias }, + { "isDefault", &Private::isDefault }, + { "isDelete", &Private::isDelete }, + { "isNoExcept", &Private::isNoExcept }, + { "isAttribute", &Private::isAttribute }, + { "isUNOProperty", &Private::isUNOProperty }, + { "isReadonly", &Private::isReadonly }, + { "isBound", &Private::isBound }, + { "isConstrained", &Private::isConstrained }, + { "isTransient", &Private::isTransient }, + { "isMaybeVoid", &Private::isMaybeVoid }, + { "isMaybeDefault", &Private::isMaybeDefault }, + { "isMaybeAmbiguous", &Private::isMaybeAmbiguous }, + { "isPublished", &Private::isPublished }, + { "isTemplateSpecialization",&Private::isTemplateSpecialization }, + { "isObjCMethod", &Private::isObjCMethod }, + { "isObjCProperty", &Private::isObjCProperty }, + { "isCSharpProperty", &Private::isCSharpProperty }, + { "isAnonymous", &Private::isAnonymous }, + { "hasParameters", &Private::hasParameters }, + { "declType", &Private::declType }, + { "declArgs", &Private::declArgs }, + { "anonymousType", &Private::anonymousType }, + { "anonymousMember", &Private::anonymousMember }, + { "hasDetails", &Private::hasDetails }, + { "exception", &Private::exception }, + { "bitfields", &Private::bitfields }, + { "initializer", &Private::initializer }, + { "initializerAsCode", &Private::initializerAsCode }, + { "hasOneLineInitializer", &Private::hasOneLineInitializer }, + { "hasMultiLineInitializer", &Private::hasMultiLineInitializer }, + { "templateArgs", &Private::templateArgs }, + { "templateAlias", &Private::templateAlias }, + { "propertyAttrs", &Private::propertyAttrs }, + { "eventAttrs", &Private::eventAttrs }, + { "category", &Private::category }, + { "categoryRelation", &Private::categoryRelation }, + { "class", &Private::getClass }, + { "file", &Private::getFile }, + { "namespace", &Private::getNamespace }, + { "definition", &Private::definition }, + { "parameters", &Private::parameters }, + { "hasConstQualifier", &Private::hasConstQualifier }, + { "hasVolatileQualifier",&Private::hasVolatileQualifier }, + { "hasRefQualifierLValue", &Private::hasRefQualifierLValue }, + { "hasRefQualifierRValue", &Private::hasRefQualifierRValue }, + { "trailingReturnType", &Private::trailingReturnType }, + { "extraTypeChars", &Private::extraTypeChars }, + { "templateDecls", &Private::templateDecls }, + { "labels", &Private::labels }, + { "enumBaseType", &Private::enumBaseType }, + { "enumValues", &Private::enumValues }, + { "paramDocs", &Private::paramDocs }, + { "reimplements", &Private::reimplements }, + { "implements", &Private::implements }, + { "reimplementedBy", &Private::reimplementedBy }, + { "implementedBy", &Private::implementedBy }, + { "examples", &Private::examples }, + { "typeConstraints", &Private::typeConstraints }, + { "functionQualifier", &Private::functionQualifier }, + { "sourceRefs", &Private::sourceRefs }, + { "sourceRefBys", &Private::sourceRefBys }, + { "hasSources", &Private::hasSources }, + { "sourceCode", &Private::sourceCode }, + { "hasCallGraph", &Private::hasCallGraph }, + { "callGraph", &Private::callGraph }, + { "hasCallerGraph", &Private::hasCallerGraph }, + { "callerGraph", &Private::callerGraph }, + { "hasReferencedByRelation", &Private::hasReferencedByRelation }, + { "referencedByRelation", &Private::referencedByRelation }, + { "hasReferencesRelation", &Private::hasReferencesRelation }, + { "referencesRelation", &Private::referencesRelation }, + { "fieldType", &Private::fieldType }, + { "type", &Private::type }, + { "detailsVisibleFor", &Private::detailsVisibleFor }, + { "nameWithContextFor", &Private::nameWithContextFor } }; //%% } -PropertyMapper<MemberContext::Private> MemberContext::Private::s_inst; +//PropertyMapper<MemberContext::Private> MemberContext::Private::s_inst; -MemberContext::MemberContext(const MemberDef *md) : RefCountedContext("MemberContext") +MemberContext::MemberContext(const MemberDef *md) : p(std::make_unique<Private>(md)) { - p = new Private(md); } MemberContext::~MemberContext() { - delete p; } TemplateVariant MemberContext::get(const QCString &n) const @@ -5311,146 +4431,94 @@ StringVector MemberContext::fields() const //------------------------------------------------------------------------ -//%% struct Concept(Symbol): class information -//%% { class ConceptContext::Private : public DefinitionContext<ConceptContext::Private> { public: Private(const ConceptDef *cd) : DefinitionContext<ConceptContext::Private>(cd), m_conceptDef(cd) { - static bool init=FALSE; - if (!init) - { - addBaseProperties(s_inst); - s_inst.addProperty("title", &Private::title); - s_inst.addProperty("highlight", &Private::highlight); - s_inst.addProperty("subhighlight", &Private::subHighlight); - s_inst.addProperty("hasDetails", &Private::hasDetails); - s_inst.addProperty("includeInfo", &Private::includeInfo); - s_inst.addProperty("templateDecls", &Private::templateDecls); - s_inst.addProperty("initializer", &Private::initializer); - s_inst.addProperty("initializerAsCode", &Private::initializerAsCode); - init=TRUE; - } - if (!cd->cookie()) { cd->setCookie(new ConceptContext::Private::Cachable(cd)); } } virtual ~Private() {} - TemplateVariant get(const QCString &n) const - { - return s_inst.get(this,n); - } - StringVector fields() const - { - return s_inst.fields(); - } - TemplateVariant title() const - { - return TemplateVariant(m_conceptDef->title()); - } - TemplateVariant highlight() const - { - return TemplateVariant("concepts"); - } - TemplateVariant subHighlight() const - { - return TemplateVariant(""); - } - TemplateVariant hasDetails() const - { - return m_conceptDef->hasDetailedDescription(); - } - TemplateVariant includeInfo() const - { - Cachable &cache = getCache(); - if (!cache.includeInfo && m_conceptDef->includeInfo()) - { - cache.includeInfo.reset(IncludeInfoContext::alloc(m_conceptDef->includeInfo(),m_conceptDef->getLanguage())); - } - if (cache.includeInfo) - { - return cache.includeInfo.get(); - } - else - { - return TemplateVariant(FALSE); - } - } - void addTemplateDecls(const ConceptDef *cd,TemplateList *tl) const + + // TemplateStructIntf methods + TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); } + StringVector fields() const { return s_inst.fields(); } + + // Property getters + TemplateVariant title() const { return TemplateVariant(m_conceptDef->title()); } + TemplateVariant highlight() const { return TemplateVariant("concepts"); } + TemplateVariant subHighlight() const { return TemplateVariant(""); } + TemplateVariant hasDetails() const { return m_conceptDef->hasDetailedDescription(); } + TemplateVariant includeInfo() const { return m_cachable.includeInfo.get(this); } + TemplateVariant templateDecls() const { return m_cachable.templateDecls.get(this); } + TemplateVariant initializer() const { return m_cachable.initializer.get(this); } + TemplateVariant initializerAsCode() const { return m_cachable.initializerAsCode.get(this); } + + private: + TemplateVariant createIncludeInfo() const { - if (!cd->getTemplateParameterList().empty()) - { - ArgumentListContext *al = ArgumentListContext::alloc(cd->getTemplateParameterList(),cd,relPathAsString()); - // since a TemplateVariant does take ownership of the object, we add it - // a separate list just to be able to delete it and avoid a memory leak - tl->append(al); - } + return m_conceptDef->includeInfo() ? + TemplateVariant(IncludeInfoContext::alloc(m_conceptDef->includeInfo(),m_conceptDef->getLanguage())) : + TemplateVariant(false); } - TemplateVariant templateDecls() const + TemplateVariant createTemplateDecls() const { - Cachable &cache = getCache(); - if (!cache.templateDecls) + TemplateVariantList list; + if (!m_conceptDef->getTemplateParameterList().empty()) { - TemplateList *tl = TemplateList::alloc(); - addTemplateDecls(m_conceptDef,tl); - cache.templateDecls.reset(tl); + list.push_back(ArgumentListContext::alloc(m_conceptDef->getTemplateParameterList(),m_conceptDef,relPathAsString())); } - return cache.templateDecls.get(); + return TemplateImmutableList::alloc(list); } - TemplateVariant initializer() const + TemplateVariant createInitializer() const { return createLinkedText(m_conceptDef,relPathAsString(),m_conceptDef->initializer()); } - TemplateVariant initializerAsCode() const + TemplateVariant createInitializerAsCode() const { - Cachable &cache = getCache(); - if (!cache.initializerParsed) + QCString scopeName; + if (m_conceptDef->getOuterScope()!=Doxygen::globalScope) { - QCString scopeName; - if (m_conceptDef->getOuterScope()!=Doxygen::globalScope) - { - scopeName = m_conceptDef->getOuterScope()->name(); - } - cache.initializer = parseCode(m_conceptDef, - scopeName,relPathAsString(), - m_conceptDef->initializer()); - cache.initializerParsed = TRUE; + scopeName = m_conceptDef->getOuterScope()->name(); } - return cache.initializer; + return parseCode(m_conceptDef, + scopeName,relPathAsString(), + m_conceptDef->initializer()); } - private: const ConceptDef *m_conceptDef; struct Cachable : public DefinitionContext<ConceptContext::Private>::Cachable { - Cachable(const ConceptDef *cd) : DefinitionContext<ConceptContext::Private>::Cachable(cd) {} - SharedPtr<IncludeInfoContext> includeInfo; - SharedPtr<ArgumentListContext> typeConstraints; - SharedPtr<TemplateList> templateDecls; - TemplateVariant initializer; - bool initializerParsed = false; + CachedItem<TemplateVariant, Private, &Private::createIncludeInfo> includeInfo; + CachedItem<TemplateVariant, Private, &Private::createTemplateDecls> templateDecls; + CachedItem<TemplateVariant, Private, &Private::createInitializer> initializer; + CachedItem<TemplateVariant, Private, &Private::createInitializerAsCode> initializerAsCode; }; - Cachable &getCache() const - { - Cachable *c = static_cast<Cachable*>(m_conceptDef->cookie()); - assert(c!=0); - return *c; - } - static PropertyMapper<ConceptContext::Private> s_inst; + Cachable m_cachable; + static const PropertyMap<ConceptContext::Private> s_inst; }; -//%% } -PropertyMapper<ConceptContext::Private> ConceptContext::Private::s_inst; +//%% struct Concept(Symbol): class information +//%% { +const PropertyMap<ConceptContext::Private> ConceptContext::Private::s_inst { + BASE_PROPERTIES, + { "title", &Private::title }, + { "highlight", &Private::highlight }, + { "subhighlight", &Private::subHighlight }, + { "hasDetails", &Private::hasDetails }, + { "includeInfo", &Private::includeInfo }, + { "templateDecls", &Private::templateDecls }, + { "initializer", &Private::initializer }, + { "initializerAsCode", &Private::initializerAsCode } +}; +//%% } -ConceptContext::ConceptContext(const ConceptDef *cd) : RefCountedContext("ConceptContext") +ConceptContext::ConceptContext(const ConceptDef *cd) : p(std::make_unique<Private>(cd)) { - //printf("ConceptContext::ConceptContext(%s)\n",cd?qPrint(cd->name()):"<none>"); - p = new Private(cd); } ConceptContext::~ConceptContext() { - delete p; } TemplateVariant ConceptContext::get(const QCString &n) const @@ -5465,93 +4533,62 @@ StringVector ConceptContext::fields() const //------------------------------------------------------------------------ -//%% struct Module(Symbol): group information -//%% { class ModuleContext::Private : public DefinitionContext<ModuleContext::Private> { public: Private(const GroupDef *gd) : DefinitionContext<ModuleContext::Private>(gd) , m_groupDef(gd) { - static bool init=FALSE; - if (!init) - { - addBaseProperties(s_inst); - s_inst.addProperty("title", &Private::title); - s_inst.addProperty("highlight", &Private::highlight); - s_inst.addProperty("subhighlight", &Private::subHighlight); - s_inst.addProperty("hasGroupGraph", &Private::hasGroupGraph); - s_inst.addProperty("groupGraph", &Private::groupGraph); - s_inst.addProperty("hasDetails", &Private::hasDetails); - s_inst.addProperty("modules", &Private::modules); - s_inst.addProperty("dirs", &Private::dirs); - s_inst.addProperty("files", &Private::files); - s_inst.addProperty("namespaces", &Private::namespaces); - s_inst.addProperty("classes", &Private::classes); - s_inst.addProperty("constantgroups", &Private::constantgroups); - s_inst.addProperty("examples", &Private::examples); - s_inst.addProperty("macros", &Private::macros); - s_inst.addProperty("typedefs", &Private::typedefs); - s_inst.addProperty("enums", &Private::enums); - s_inst.addProperty("enumvalues", &Private::enumValues); - s_inst.addProperty("functions", &Private::functions); - s_inst.addProperty("variables", &Private::variables); - s_inst.addProperty("signals", &Private::signals); - s_inst.addProperty("publicSlots", &Private::publicSlots); - s_inst.addProperty("protectedSlots", &Private::protectedSlots); - s_inst.addProperty("privateSlots", &Private::privateSlots); - s_inst.addProperty("events", &Private::events); - s_inst.addProperty("properties", &Private::properties); - s_inst.addProperty("friends", &Private::friends); - s_inst.addProperty("memberGroups", &Private::memberGroups); - s_inst.addProperty("detailedMacros", &Private::detailedMacros); - s_inst.addProperty("detailedTypedefs", &Private::detailedTypedefs); - s_inst.addProperty("detailedEnums", &Private::detailedEnums); - s_inst.addProperty("detailedEnumValues", &Private::detailedEnumValues); - s_inst.addProperty("detailedFunctions", &Private::detailedFunctions); - s_inst.addProperty("detailedVariables", &Private::detailedVariables); - s_inst.addProperty("detailedSignals", &Private::detailedSignals); - s_inst.addProperty("detailedPublicSlots", &Private::detailedPublicSlots); - s_inst.addProperty("detailedProtectedSlots", &Private::detailedProtectedSlots); - s_inst.addProperty("detailedPrivateSlots", &Private::detailedPrivateSlots); - s_inst.addProperty("detailedEvents", &Private::detailedEvents); - s_inst.addProperty("detailedProperties", &Private::detailedProperties); - s_inst.addProperty("detailedFriends", &Private::detailedFriends); - s_inst.addProperty("inlineClasses", &Private::inlineClasses); - s_inst.addProperty("compoundType", &Private::compoundType); - init=TRUE; - } - if (!gd->cookie()) { gd->setCookie(new ModuleContext::Private::Cachable(gd)); } - } - virtual ~Private() {} - TemplateVariant get(const QCString &n) const - { - return s_inst.get(this,n); - } - StringVector fields() const - { - return s_inst.fields(); - } - TemplateVariant title() const - { - return TemplateVariant(m_groupDef->groupTitle()); - } - TemplateVariant highlight() const - { - return TemplateVariant("modules"); - } - TemplateVariant subHighlight() const - { - return TemplateVariant(""); - } - DotGroupCollaboration *getGroupGraph() const - { - Cachable &cache = getCache(); - if (!cache.groupGraph) - { - cache.groupGraph.reset(new DotGroupCollaboration(m_groupDef)); - } - return cache.groupGraph.get(); } + + // TemplateStructIntf methods + TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); } + StringVector fields() const { return s_inst.fields(); } + + private: + // Property getters + TemplateVariant title() const { return TemplateVariant(m_groupDef->groupTitle()); } + TemplateVariant highlight() const { return TemplateVariant("modules"); } + TemplateVariant subHighlight() const { return TemplateVariant(""); } + TemplateVariant compoundType() const { return TemplateVariant("module"); } + TemplateVariant hasDetails() const { return m_groupDef->hasDetailedDescription(); } + TemplateVariant modules() const { return m_cachable.modules.get(this); } + TemplateVariant examples() const { return m_cachable.examples.get(this); } + TemplateVariant pages() const { return m_cachable.pages.get(this); } + TemplateVariant dirs() const { return m_cachable.dirs.get(this); } + TemplateVariant files() const { return m_cachable.files.get(this); } + TemplateVariant classes() const { return m_cachable.classes.get(this); } + TemplateVariant namespaces() const { return m_cachable.namespaces.get(this); } + TemplateVariant constantgroups() const { return m_cachable.constantgroups.get(this); } + TemplateVariant macros() const { return m_cachable.macros.get(this); } + TemplateVariant typedefs() const { return m_cachable.typedefs.get(this); } + TemplateVariant enums() const { return m_cachable.enums.get(this); } + TemplateVariant enumValues() const { return m_cachable.enums.get(this); } + TemplateVariant functions() const { return m_cachable.functions.get(this); } + TemplateVariant variables() const { return m_cachable.variables.get(this); } + TemplateVariant signals() const { return m_cachable.signals.get(this); } + TemplateVariant publicSlots() const { return m_cachable.publicSlots.get(this); } + TemplateVariant protectedSlots() const { return m_cachable.protectedSlots.get(this); } + TemplateVariant privateSlots() const { return m_cachable.privateSlots.get(this); } + TemplateVariant events() const { return m_cachable.events.get(this); } + TemplateVariant properties() const { return m_cachable.properties.get(this); } + TemplateVariant friends() const { return m_cachable.friends.get(this); } + TemplateVariant memberGroups() const { return m_cachable.memberGroups.get(this); } + TemplateVariant detailedMacros() const { return m_cachable.detailedMacros.get(this); } + TemplateVariant detailedTypedefs() const { return m_cachable.detailedTypedefs.get(this); } + TemplateVariant detailedEnums() const { return m_cachable.detailedEnums.get(this); } + TemplateVariant detailedEnumValues() const { return m_cachable.detailedEnumValues.get(this); } + TemplateVariant detailedFunctions() const { return m_cachable.detailedFunctions.get(this); } + TemplateVariant detailedVariables() const { return m_cachable.detailedVariables.get(this); } + TemplateVariant detailedSignals() const { return m_cachable.detailedSignals.get(this); } + TemplateVariant detailedPublicSlots() const { return m_cachable.detailedPublicSlots.get(this); } + TemplateVariant detailedProtectedSlots() const { return m_cachable.detailedProtectedSlots.get(this); } + TemplateVariant detailedPrivateSlots() const { return m_cachable.detailedPrivateSlots.get(this); } + TemplateVariant detailedEvents() const { return m_cachable.detailedEvents.get(this); } + TemplateVariant detailedProperties() const { return m_cachable.detailedProperties.get(this); } + TemplateVariant detailedFriends() const { return m_cachable.detailedFriends.get(this); } + TemplateVariant inlineClasses() const { return m_cachable.inlineClasses.get(this); } + DotGroupCollaborationPtr getGroupGraph() const { return m_cachable.groupGraph.get(this); } + TemplateVariant hasGroupGraph() const { bool result=FALSE; @@ -5559,7 +4596,7 @@ class ModuleContext::Private : public DefinitionContext<ModuleContext::Private> static bool groupGraphs = Config_getBool(GROUP_GRAPHS); if (haveDot && groupGraphs) { - DotGroupCollaboration *graph = getGroupGraph(); + DotGroupCollaborationPtr graph = getGroupGraph(); result = !graph->isTrivial(); } return result; @@ -5571,7 +4608,7 @@ class ModuleContext::Private : public DefinitionContext<ModuleContext::Private> static bool groupGraphs = Config_getBool(GROUP_GRAPHS); if (haveDot && groupGraphs) { - DotGroupCollaboration *graph = getGroupGraph(); + DotGroupCollaborationPtr graph = getGroupGraph(); switch (g_globals.outputFormat) { case ContextOutputFormat_Html: @@ -5579,7 +4616,7 @@ class ModuleContext::Private : public DefinitionContext<ModuleContext::Private> graph->writeGraph(t,GOF_BITMAP, EOF_Html, g_globals.outputDir, - g_globals.outputDir+Portable::pathSeparator()+m_groupDef->getOutputFileBase()+Doxygen::htmlFileExtension, + g_globals.outputDir+Portable::pathSeparator()+addHtmlExtensionIfMissing(m_groupDef->getOutputFileBase()), relPathAsString(), TRUE, g_globals.dynSectionId); @@ -5605,371 +4642,344 @@ class ModuleContext::Private : public DefinitionContext<ModuleContext::Private> } return TemplateVariant(t.str().c_str(),TRUE); } - TemplateVariant hasDetails() const - { - return m_groupDef->hasDetailedDescription(); - } - TemplateVariant modules() const + + private: + + TemplateVariant createModules() const { - Cachable &cache = getCache(); - if (!cache.modules) + TemplateVariantList list; + list.reserve(m_groupDef->getSubGroups().size()); + for (const auto &gd : m_groupDef->getSubGroups()) { - TemplateList *moduleList = TemplateList::alloc(); - for (const auto &gd : m_groupDef->getSubGroups()) + if (gd->isVisible()) { - if (gd->isVisible()) - { - moduleList->append(ModuleContext::alloc(gd)); - } + list.push_back(ModuleContext::alloc(gd)); } - cache.modules.reset(moduleList); } - return cache.modules.get(); + return TemplateImmutableList::alloc(list); } - TemplateVariant examples() const + TemplateVariant createDirs() const { - Cachable &cache = getCache(); - if (!cache.examples) + TemplateVariantList list; + list.reserve(m_groupDef->getDirs().size()); + for(const auto dd : m_groupDef->getDirs()) { - TemplateList *exampleList = TemplateList::alloc(); - for (const auto &ex : m_groupDef->getExamples()) - { - exampleList->append(PageContext::alloc(ex,FALSE,TRUE)); - } - cache.examples.reset(exampleList); + list.push_back(DirContext::alloc(dd)); } - return cache.examples.get(); + return TemplateImmutableList::alloc(list); } - TemplateVariant pages() const + TemplateVariant createFiles() const { - Cachable &cache = getCache(); - if (!cache.pages) + TemplateVariantList list; + list.reserve(m_groupDef->getFiles().size()); + for (const auto &fd : m_groupDef->getFiles()) { - TemplateList *pageList = TemplateList::alloc(); - for (const auto &ex : m_groupDef->getPages()) - { - pageList->append(PageContext::alloc(ex,FALSE,TRUE)); - } - cache.pages.reset(pageList); + list.push_back(FileContext::alloc(fd)); } - return cache.pages.get(); + return TemplateImmutableList::alloc(list); } - TemplateVariant dirs() const + TemplateVariant createClasses() const { - Cachable &cache = getCache(); - if (!cache.dirs) + TemplateVariantList list; + list.reserve(m_groupDef->getClasses().size()); + for (const auto &cd : m_groupDef->getClasses()) { - TemplateList *dirList = TemplateList::alloc(); - for(const auto dd : m_groupDef->getDirs()) + if (cd->visibleInParentsDeclList()) { - dirList->append(DirContext::alloc(dd)); + list.push_back(ClassContext::alloc(cd)); } - cache.dirs.reset(dirList); } - return cache.dirs.get(); + return TemplateImmutableList::alloc(list); } - TemplateVariant files() const + TemplateVariant createNamespaces() const { - Cachable &cache = getCache(); - if (!cache.files) + TemplateVariantList list; + list.reserve(m_groupDef->getNamespaces().size()); + for (const auto &nd : m_groupDef->getNamespaces()) { - TemplateList *fileList = TemplateList::alloc(); - for (const auto &fd : m_groupDef->getFiles()) + if (nd->isLinkable() && !nd->isConstantGroup()) { - fileList->append(FileContext::alloc(fd)); + list.push_back(NamespaceContext::alloc(nd)); } - cache.files.reset(fileList); } - return cache.files.get(); + return TemplateImmutableList::alloc(list); } - TemplateVariant classes() const + TemplateVariant createConstantgroups() const { - Cachable &cache = getCache(); - if (!cache.classes) + TemplateVariantList list; + list.reserve(m_groupDef->getNamespaces().size()); + for (const auto &nd : m_groupDef->getNamespaces()) { - TemplateList *classList = TemplateList::alloc(); - for (const auto &cd : m_groupDef->getClasses()) + if (nd->isLinkable() && nd->isConstantGroup()) { - if (cd->visibleInParentsDeclList()) - { - classList->append(ClassContext::alloc(cd)); - } + list.push_back(NamespaceContext::alloc(nd)); } - cache.classes.reset(classList); } - return cache.classes.get(); + return TemplateImmutableList::alloc(list); } - TemplateVariant namespaces() const + TemplateVariant createExamples() const { - Cachable &cache = getCache(); - if (!cache.namespaces) + TemplateVariantList list; + list.reserve(m_groupDef->getExamples().size()); + for (const auto &ex : m_groupDef->getExamples()) { - TemplateList *namespaceList = TemplateList::alloc(); - for (const auto &nd : m_groupDef->getNamespaces()) - { - if (nd->isLinkable() && !nd->isConstantGroup()) - { - namespaceList->append(NamespaceContext::alloc(nd)); - } - } - cache.namespaces.reset(namespaceList); + list.push_back(PageContext::alloc(ex,FALSE,TRUE)); } - return cache.namespaces.get(); + return TemplateImmutableList::alloc(list); } - TemplateVariant constantgroups() const + TemplateVariant createPages() const { - Cachable &cache = getCache(); - if (!cache.constantgroups) + TemplateVariantList list; + list.reserve(m_groupDef->getPages().size()); + for (const auto &ex : m_groupDef->getPages()) { - TemplateList *namespaceList = TemplateList::alloc(); - for (const auto &nd : m_groupDef->getNamespaces()) - { - if (nd->isLinkable() && nd->isConstantGroup()) - { - namespaceList->append(NamespaceContext::alloc(nd)); - } - } - cache.constantgroups.reset(namespaceList); + list.push_back(PageContext::alloc(ex,FALSE,TRUE)); } - return cache.constantgroups.get(); + return TemplateImmutableList::alloc(list); } - - TemplateVariant getMemberList(SharedPtr<MemberListInfoContext> &list, - MemberListType type,const QCString &title,bool=FALSE) const + TemplateVariant createMemberList(MemberListType type,const QCString &title) const { - if (!list) - { - MemberList *ml = m_groupDef->getMemberList(type); - if (ml) - { - list.reset(MemberListInfoContext::alloc(m_groupDef,relPathAsString(),ml,title,"")); - } - } - if (list) - { - return list.get(); - } - else - { - return TemplateVariant(FALSE); - } + const MemberList *ml = m_groupDef->getMemberList(type); + return ml ? TemplateVariant(MemberListInfoContext::alloc(m_groupDef,relPathAsString(),ml,title,"")) + : TemplateVariant(false); } - TemplateVariant macros() const + TemplateVariant createMacros() const { - return getMemberList(getCache().macros,MemberListType_decDefineMembers,theTranslator->trDefines()); + return createMemberList(MemberListType_decDefineMembers,theTranslator->trDefines()); } - TemplateVariant typedefs() const + TemplateVariant createTypedefs() const { - return getMemberList(getCache().typedefs,MemberListType_decTypedefMembers,theTranslator->trTypedefs()); + return createMemberList(MemberListType_decTypedefMembers,theTranslator->trTypedefs()); } - TemplateVariant enums() const + TemplateVariant createEnums() const { - return getMemberList(getCache().enums,MemberListType_decEnumMembers,theTranslator->trEnumerations()); + return createMemberList(MemberListType_decEnumMembers,theTranslator->trEnumerations()); } - TemplateVariant enumValues() const + TemplateVariant createEnumValues() const { - return getMemberList(getCache().enums,MemberListType_decEnumValMembers,theTranslator->trEnumerationValues()); + return createMemberList(MemberListType_decEnumValMembers,theTranslator->trEnumerationValues()); } - TemplateVariant functions() const + TemplateVariant createFunctions() const { - QCString title = theTranslator->trFunctions(); SrcLangExt lang = m_groupDef->getLanguage(); - if (lang==SrcLangExt_Fortran) title=theTranslator->trSubprograms(); - else if (lang==SrcLangExt_VHDL) title=theTranslator->trFunctionAndProc(); - return getMemberList(getCache().functions,MemberListType_decFuncMembers,title); + return createMemberList(MemberListType_decFuncMembers, lang==SrcLangExt_Fortran ? theTranslator->trSubprograms() : + lang==SrcLangExt_VHDL ? theTranslator->trFunctionAndProc() : + theTranslator->trFunctions()); } - TemplateVariant variables() const + TemplateVariant createVariables() const { static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE); - return getMemberList(getCache().variables,MemberListType_decVarMembers, - sliceOpt ? theTranslator->trConstants() : theTranslator->trVariables()); + return createMemberList(MemberListType_decVarMembers, sliceOpt ? theTranslator->trConstants() : + theTranslator->trVariables()); } - TemplateVariant signals() const + TemplateVariant createSignals() const { - return getMemberList(getCache().signals,MemberListType_signals,theTranslator->trSignals()); + return createMemberList(MemberListType_signals,theTranslator->trSignals()); } - TemplateVariant publicSlots() const + TemplateVariant createPublicSlots() const { - return getMemberList(getCache().publicSlots,MemberListType_pubSlots,theTranslator->trPublicSlots()); + return createMemberList(MemberListType_pubSlots,theTranslator->trPublicSlots()); } - TemplateVariant protectedSlots() const + TemplateVariant createProtectedSlots() const { - return getMemberList(getCache().protectedSlots,MemberListType_proSlots,theTranslator->trProtectedSlots()); + return createMemberList(MemberListType_proSlots,theTranslator->trProtectedSlots()); } - TemplateVariant privateSlots() const + TemplateVariant createPrivateSlots() const { - return getMemberList(getCache().privateSlots,MemberListType_priSlots,theTranslator->trPrivateSlots()); + return createMemberList(MemberListType_priSlots,theTranslator->trPrivateSlots()); } - TemplateVariant events() const + TemplateVariant createEvents() const { - return getMemberList(getCache().events,MemberListType_events,theTranslator->trEvents()); + return createMemberList(MemberListType_events,theTranslator->trEvents()); } - TemplateVariant properties() const + TemplateVariant createProperties() const { - return getMemberList(getCache().properties,MemberListType_properties,theTranslator->trProperties()); + return createMemberList(MemberListType_properties,theTranslator->trProperties()); } - TemplateVariant friends() const + TemplateVariant createFriends() const { - return getMemberList(getCache().friends,MemberListType_friends,theTranslator->trFriends()); + return createMemberList(MemberListType_friends,theTranslator->trFriends()); } - TemplateVariant memberGroups() const + TemplateVariant createDetailedMacros() const { - Cachable &cache = getCache(); - if (!cache.memberGroups) - { - if (!m_groupDef->getMemberGroups().empty()) - { - cache.memberGroups.reset(MemberGroupListContext::alloc(m_groupDef,relPathAsString(),m_groupDef->getMemberGroups(),m_groupDef->subGrouping())); - } - else - { - cache.memberGroups.reset(MemberGroupListContext::alloc()); - } - } - return cache.memberGroups.get(); + return createMemberList(MemberListType_docDefineMembers,theTranslator->trDefineDocumentation()); } - TemplateVariant detailedMacros() const + TemplateVariant createDetailedTypedefs() const { - return getMemberList(getCache().detailedMacros,MemberListType_docDefineMembers,theTranslator->trDefineDocumentation()); + return createMemberList(MemberListType_docTypedefMembers,theTranslator->trTypedefDocumentation()); } - TemplateVariant detailedTypedefs() const + TemplateVariant createDetailedEnums() const { - return getMemberList(getCache().detailedTypedefs,MemberListType_docTypedefMembers,theTranslator->trTypedefDocumentation()); + return createMemberList(MemberListType_docEnumMembers,theTranslator->trEnumerationTypeDocumentation()); } - TemplateVariant detailedEnums() const + TemplateVariant createDetailedEnumValues() const { - return getMemberList(getCache().detailedEnums,MemberListType_docEnumMembers,theTranslator->trEnumerationTypeDocumentation()); + return createMemberList(MemberListType_docEnumValMembers,theTranslator->trEnumerationValueDocumentation()); } - TemplateVariant detailedEnumValues() const + TemplateVariant createDetailedFunctions() const { - return getMemberList(getCache().detailedEnumValues,MemberListType_docEnumValMembers,theTranslator->trEnumerationValueDocumentation()); - } - TemplateVariant detailedFunctions() const - { - QCString title = theTranslator->trFunctionDocumentation(); SrcLangExt lang = m_groupDef->getLanguage(); - if (lang==SrcLangExt_Fortran) title=theTranslator->trSubprogramDocumentation(); - return getMemberList(getCache().detailedFunctions,MemberListType_docFuncMembers,title); + return createMemberList(MemberListType_docFuncMembers, lang==SrcLangExt_Fortran ? theTranslator->trSubprogramDocumentation() : + theTranslator->trFunctionDocumentation()); } - TemplateVariant detailedVariables() const + TemplateVariant createDetailedVariables() const { - return getMemberList(getCache().detailedVariables,MemberListType_docVarMembers,theTranslator->trVariableDocumentation()); + return createMemberList(MemberListType_docVarMembers,theTranslator->trVariableDocumentation()); } - TemplateVariant detailedSignals() const + TemplateVariant createDetailedSignals() const { - return getMemberList(getCache().detailedSignals,MemberListType_docSignalMembers,theTranslator->trSignals()); + return createMemberList(MemberListType_docSignalMembers,theTranslator->trSignals()); } - TemplateVariant detailedPublicSlots() const + TemplateVariant createDetailedPublicSlots() const { - return getMemberList(getCache().detailedPublicSlots,MemberListType_docPubSlotMembers,theTranslator->trPublicSlots()); + return createMemberList(MemberListType_docPubSlotMembers,theTranslator->trPublicSlots()); } - TemplateVariant detailedProtectedSlots() const + TemplateVariant createDetailedProtectedSlots() const { - return getMemberList(getCache().detailedProtectedSlots,MemberListType_docProSlotMembers,theTranslator->trProtectedSlots()); + return createMemberList(MemberListType_docProSlotMembers,theTranslator->trProtectedSlots()); } - TemplateVariant detailedPrivateSlots() const + TemplateVariant createDetailedPrivateSlots() const { - return getMemberList(getCache().detailedPrivateSlots,MemberListType_docPriSlotMembers,theTranslator->trPrivateSlots()); + return createMemberList(MemberListType_docPriSlotMembers,theTranslator->trPrivateSlots()); } - TemplateVariant detailedEvents() const + TemplateVariant createDetailedEvents() const { - return getMemberList(getCache().detailedEvents,MemberListType_docEventMembers,theTranslator->trEventDocumentation(),TRUE); + return createMemberList(MemberListType_docEventMembers,theTranslator->trEventDocumentation()); } - TemplateVariant detailedProperties() const + TemplateVariant createDetailedProperties() const { - return getMemberList(getCache().detailedProperties,MemberListType_docPropMembers,theTranslator->trPropertyDocumentation(),TRUE); + return createMemberList(MemberListType_docPropMembers,theTranslator->trPropertyDocumentation()); } - TemplateVariant detailedFriends() const + TemplateVariant createDetailedFriends() const { - return getMemberList(getCache().detailedFriends,MemberListType_docFriendMembers,theTranslator->trFriends(),TRUE); + return createMemberList(MemberListType_docFriendMembers,theTranslator->trFriends()); } - TemplateVariant inlineClasses() const + TemplateVariant createInlineClasses() const { - Cachable &cache = getCache(); - if (!cache.inlineClasses) + TemplateVariantList list; + for (const auto &cd : m_groupDef->getClasses()) { - TemplateList *classList = TemplateList::alloc(); - for (const auto &cd : m_groupDef->getClasses()) + if (!cd->isAnonymous() && + cd->isLinkableInProject() && + cd->isEmbeddedInOuterScope() && + cd->partOfGroups().empty()) { - if (!cd->isAnonymous() && - cd->isLinkableInProject() && - cd->isEmbeddedInOuterScope() && - cd->partOfGroups().empty()) - { - classList->append(ClassContext::alloc(cd)); - } + list.push_back(ClassContext::alloc(cd)); } - cache.inlineClasses.reset(classList); } - return cache.inlineClasses.get(); + return TemplateImmutableList::alloc(list); } - TemplateVariant compoundType() const + TemplateVariant createMemberGroups() const { - return "module"; //theTranslator->trGroup(FALSE,TRUE); + return !m_groupDef->getMemberGroups().empty() ? + MemberGroupListContext::alloc(m_groupDef,relPathAsString(),m_groupDef->getMemberGroups(),m_groupDef->subGrouping()) : + MemberGroupListContext::alloc(); } - private: + DotGroupCollaborationPtr createGroupGraph() const + { + return std::make_shared<DotGroupCollaboration>(m_groupDef); + } + const GroupDef *m_groupDef; struct Cachable : public DefinitionContext<ModuleContext::Private>::Cachable { - Cachable(const GroupDef *gd) : DefinitionContext<ModuleContext::Private>::Cachable(gd) {} - SharedPtr<TemplateList> modules; - SharedPtr<TemplateList> dirs; - SharedPtr<TemplateList> files; - SharedPtr<TemplateList> classes; - SharedPtr<TemplateList> namespaces; - SharedPtr<TemplateList> constantgroups; - SharedPtr<TemplateList> examples; - SharedPtr<TemplateList> pages; - SharedPtr<MemberListInfoContext> macros; - SharedPtr<MemberListInfoContext> typedefs; - SharedPtr<MemberListInfoContext> enums; - SharedPtr<MemberListInfoContext> enumValues; - SharedPtr<MemberListInfoContext> functions; - SharedPtr<MemberListInfoContext> variables; - SharedPtr<MemberListInfoContext> signals; - SharedPtr<MemberListInfoContext> publicSlots; - SharedPtr<MemberListInfoContext> protectedSlots; - SharedPtr<MemberListInfoContext> privateSlots; - SharedPtr<MemberListInfoContext> events; - SharedPtr<MemberListInfoContext> properties; - SharedPtr<MemberListInfoContext> friends; - SharedPtr<MemberGroupListContext> memberGroups; - SharedPtr<MemberListInfoContext> detailedMacros; - SharedPtr<MemberListInfoContext> detailedTypedefs; - SharedPtr<MemberListInfoContext> detailedEnums; - SharedPtr<MemberListInfoContext> detailedEnumValues; - SharedPtr<MemberListInfoContext> detailedFunctions; - SharedPtr<MemberListInfoContext> detailedVariables; - SharedPtr<MemberListInfoContext> detailedSignals; - SharedPtr<MemberListInfoContext> detailedPublicSlots; - SharedPtr<MemberListInfoContext> detailedProtectedSlots; - SharedPtr<MemberListInfoContext> detailedPrivateSlots; - SharedPtr<MemberListInfoContext> detailedEvents; - SharedPtr<MemberListInfoContext> detailedProperties; - SharedPtr<MemberListInfoContext> detailedFriends; - SharedPtr<TemplateList> inlineClasses; - std::unique_ptr<DotGroupCollaboration> groupGraph; + CachedItem<TemplateVariant, Private, &Private::createModules> modules; + CachedItem<TemplateVariant, Private, &Private::createDirs> dirs; + CachedItem<TemplateVariant, Private, &Private::createFiles> files; + CachedItem<TemplateVariant, Private, &Private::createClasses> classes; + CachedItem<TemplateVariant, Private, &Private::createNamespaces> namespaces; + CachedItem<TemplateVariant, Private, &Private::createConstantgroups> constantgroups; + CachedItem<TemplateVariant, Private, &Private::createExamples> examples; + CachedItem<TemplateVariant, Private, &Private::createPages> pages; + CachedItem<TemplateVariant, Private, &Private::createMacros> macros; + CachedItem<TemplateVariant, Private, &Private::createTypedefs> typedefs; + CachedItem<TemplateVariant, Private, &Private::createEnums> enums; + CachedItem<TemplateVariant, Private, &Private::createEnumValues> enumValues; + CachedItem<TemplateVariant, Private, &Private::createFunctions> functions; + CachedItem<TemplateVariant, Private, &Private::createVariables> variables; + CachedItem<TemplateVariant, Private, &Private::createSignals> signals; + CachedItem<TemplateVariant, Private, &Private::createPublicSlots> publicSlots; + CachedItem<TemplateVariant, Private, &Private::createProtectedSlots> protectedSlots; + CachedItem<TemplateVariant, Private, &Private::createPrivateSlots> privateSlots; + CachedItem<TemplateVariant, Private, &Private::createEvents> events; + CachedItem<TemplateVariant, Private, &Private::createProperties> properties; + CachedItem<TemplateVariant, Private, &Private::createFriends> friends; + CachedItem<TemplateVariant, Private, &Private::createMemberGroups> memberGroups; + CachedItem<TemplateVariant, Private, &Private::createDetailedMacros> detailedMacros; + CachedItem<TemplateVariant, Private, &Private::createDetailedTypedefs> detailedTypedefs; + CachedItem<TemplateVariant, Private, &Private::createDetailedEnums> detailedEnums; + CachedItem<TemplateVariant, Private, &Private::createDetailedEnumValues> detailedEnumValues; + CachedItem<TemplateVariant, Private, &Private::createDetailedFunctions> detailedFunctions; + CachedItem<TemplateVariant, Private, &Private::createDetailedVariables> detailedVariables; + CachedItem<TemplateVariant, Private, &Private::createDetailedSignals> detailedSignals; + CachedItem<TemplateVariant, Private, &Private::createDetailedPublicSlots> detailedPublicSlots; + CachedItem<TemplateVariant, Private, &Private::createDetailedProtectedSlots> detailedProtectedSlots; + CachedItem<TemplateVariant, Private, &Private::createDetailedPrivateSlots> detailedPrivateSlots; + CachedItem<TemplateVariant, Private, &Private::createDetailedEvents> detailedEvents; + CachedItem<TemplateVariant, Private, &Private::createDetailedProperties> detailedProperties; + CachedItem<TemplateVariant, Private, &Private::createDetailedFriends> detailedFriends; + CachedItem<TemplateVariant, Private, &Private::createInlineClasses> inlineClasses; + CachedItem<DotGroupCollaborationPtr, Private, &Private::createGroupGraph> groupGraph; }; - Cachable &getCache() const - { - Cachable *c = static_cast<Cachable*>(m_groupDef->cookie()); - assert(c!=0); - return *c; - } - static PropertyMapper<ModuleContext::Private> s_inst; + Cachable m_cachable; + static const PropertyMap<ModuleContext::Private> s_inst; }; -//%% } -PropertyMapper<ModuleContext::Private> ModuleContext::Private::s_inst; +//%% struct Module(Symbol): group information +//%% { +const PropertyMap<ModuleContext::Private> ModuleContext::Private::s_inst { + BASE_PROPERTIES, + { "title", &Private::title }, + { "highlight", &Private::highlight }, + { "subhighlight", &Private::subHighlight }, + { "hasGroupGraph", &Private::hasGroupGraph }, + { "groupGraph", &Private::groupGraph }, + { "hasDetails", &Private::hasDetails }, + { "modules", &Private::modules }, + { "dirs", &Private::dirs }, + { "files", &Private::files }, + { "namespaces", &Private::namespaces }, + { "classes", &Private::classes }, + { "constantgroups", &Private::constantgroups }, + { "examples", &Private::examples }, + { "macros", &Private::macros }, + { "typedefs", &Private::typedefs }, + { "enums", &Private::enums }, + { "enumvalues", &Private::enumValues }, + { "functions", &Private::functions }, + { "variables", &Private::variables }, + { "signals", &Private::signals }, + { "publicSlots", &Private::publicSlots }, + { "protectedSlots", &Private::protectedSlots }, + { "privateSlots", &Private::privateSlots }, + { "events", &Private::events }, + { "properties", &Private::properties }, + { "friends", &Private::friends }, + { "memberGroups", &Private::memberGroups }, + { "detailedMacros", &Private::detailedMacros }, + { "detailedTypedefs", &Private::detailedTypedefs }, + { "detailedEnums", &Private::detailedEnums }, + { "detailedEnumValues", &Private::detailedEnumValues }, + { "detailedFunctions", &Private::detailedFunctions }, + { "detailedVariables", &Private::detailedVariables }, + { "detailedSignals", &Private::detailedSignals }, + { "detailedPublicSlots", &Private::detailedPublicSlots }, + { "detailedProtectedSlots", &Private::detailedProtectedSlots }, + { "detailedPrivateSlots", &Private::detailedPrivateSlots }, + { "detailedEvents", &Private::detailedEvents }, + { "detailedProperties", &Private::detailedProperties }, + { "detailedFriends", &Private::detailedFriends }, + { "inlineClasses", &Private::inlineClasses }, + { "compoundType", &Private::compoundType } +}; +//%% } -ModuleContext::ModuleContext(const GroupDef *gd) : RefCountedContext("ModuleContext") +ModuleContext::ModuleContext(const GroupDef *gd) : p(std::make_unique<Private>(gd)) { - p = new Private(gd); } ModuleContext::~ModuleContext() { - delete p; } TemplateVariant ModuleContext::get(const QCString &n) const @@ -6008,16 +5018,14 @@ class ClassListContext::Private : public GenericNodeListContext } }; -ClassListContext::ClassListContext() : RefCountedContext("ClassListContext") +ClassListContext::ClassListContext() : p(std::make_unique<Private>()) { - p = new Private; p->addClasses(*Doxygen::classLinkedMap); p->addClasses(*Doxygen::hiddenClassLinkedMap); } ClassListContext::~ClassListContext() { - delete p; } // TemplateListIntf @@ -6031,118 +5039,80 @@ TemplateVariant ClassListContext::at(uint index) const return p->at(index); } -TemplateListIntf::ConstIterator *ClassListContext::createIterator() const +TemplateListIntf::ConstIteratorPtr ClassListContext::createIterator() const { return p->createIterator(); } //------------------------------------------------------------------------ -//%% list ClassIndex[Class] : list of classes class ClassIndexContext::Private { public: - Private() - { - static bool init=FALSE; - if (!init) - { - s_inst.addProperty("list", &Private::list); - s_inst.addProperty("fileName", &Private::fileName); - s_inst.addProperty("relPath", &Private::relPath); - s_inst.addProperty("highlight", &Private::highlight); - s_inst.addProperty("subhighlight",&Private::subhighlight); - s_inst.addProperty("title", &Private::title); - init=TRUE; - } - } - TemplateVariant get(const QCString &n) const - { - return s_inst.get(this,n); - } - StringVector fields() const + // TemplateStructIntf methods + TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); } + StringVector fields() const { return s_inst.fields(); } + + private: + // Property getters + TemplateVariant list() const { return m_classes.get(this); } + TemplateVariant fileName() const { return "classes"; } + TemplateVariant relPath() const { return ""; } + TemplateVariant highlight() const { return "classes"; } + TemplateVariant subhighlight() const { return "classindex"; } + TemplateVariant title() const { - return s_inst.fields(); + return Config_getBool(OPTIMIZE_FOR_FORTRAN) ? theTranslator->trDataTypes() : + Config_getBool(OPTIMIZE_OUTPUT_VHDL) ? theTranslator->trDesignUnits() : + theTranslator->trCompoundIndex(); } - TemplateVariant list() const + private: + TemplateVariant createClasses() const { - if (!m_cache.classes) + TemplateVariantList list; + list.reserve(Doxygen::classLinkedMap->size()); + if (Doxygen::classLinkedMap) { - TemplateList *classList = TemplateList::alloc(); - if (Doxygen::classLinkedMap) + for (const auto &cd : *Doxygen::classLinkedMap) { - for (const auto &cd : *Doxygen::classLinkedMap) + if (cd->getLanguage()==SrcLangExt_VHDL && + ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKAGECLASS || + (VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKBODYCLASS) + ) // no architecture { - if (cd->getLanguage()==SrcLangExt_VHDL && - ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKAGECLASS || - (VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKBODYCLASS) - ) // no architecture - { - continue; - } - if (cd->isLinkableInProject() && cd->templateMaster()==0) - { - classList->append(ClassContext::alloc(cd.get())); - } + continue; + } + if (cd->isLinkableInProject() && cd->templateMaster()==0) + { + list.push_back(ClassContext::alloc(cd.get())); } } - m_cache.classes.reset(classList); - } - return m_cache.classes.get(); - } - TemplateVariant fileName() const - { - return "classes"; - } - TemplateVariant relPath() const - { - return ""; - } - TemplateVariant highlight() const - { - return "classes"; - } - TemplateVariant subhighlight() const - { - return "classindex"; - } - TemplateVariant title() const - { - static bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN); - static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL); - if (fortranOpt) - { - return theTranslator->trDataTypes(); - } - else if (vhdlOpt) - { - return theTranslator->trDesignUnits(); - } - else - { - return theTranslator->trCompoundIndex(); } + return TemplateImmutableList::alloc(list); } - private: - struct Cachable - { - SharedPtr<TemplateList> classes; - }; - mutable Cachable m_cache; - static PropertyMapper<ClassIndexContext::Private> s_inst; + + CachedItem<TemplateVariant, Private, &Private::createClasses> m_classes; + static const PropertyMap<ClassIndexContext::Private> s_inst; }; -PropertyMapper<ClassIndexContext::Private> ClassIndexContext::Private::s_inst; +//%% struct ClassIndex +//%% { +const PropertyMap<ClassIndexContext::Private> ClassIndexContext::Private::s_inst { + { "list", &Private::list }, + { "fileName", &Private::fileName }, + { "relPath", &Private::relPath }, + { "highlight", &Private::highlight }, + { "subhighlight",&Private::subhighlight }, + { "title", &Private::title } +}; +//%% } -ClassIndexContext::ClassIndexContext() : RefCountedContext("ClassIndexContext") +ClassIndexContext::ClassIndexContext() : p(std::make_unique<Private>()) { - p = new Private; - //p->addClasses(*Doxygen::hiddenClasses); } ClassIndexContext::~ClassIndexContext() { - delete p; } // TemplateStructIntf @@ -6158,26 +5128,25 @@ StringVector ClassIndexContext::fields() const //------------------------------------------------------------------------ -static int computeMaxDepth(const TemplateListIntf *list) +static int computeMaxDepth(const TemplateListIntfPtr list) { int maxDepth=0; if (list) { - TemplateListIntf::ConstIterator *it = list->createIterator(); + TemplateListIntf::ConstIteratorPtr it = list->createIterator(); TemplateVariant v; for (it->toFirst();it->current(v);it->toNext()) { - const TemplateStructIntf *s = v.toStruct(); + const TemplateStructIntfPtr s = v.toStruct(); TemplateVariant child = s->get("children"); int d = computeMaxDepth(child.toList())+1; if (d>maxDepth) maxDepth=d; } - delete it; } return maxDepth; } -static int computeNumNodesAtLevel(const TemplateStructIntf *s,int level,int maxLevel) +static int computeNumNodesAtLevel(const TemplateStructIntfPtr s,int level,int maxLevel) { int num=0; if (level<maxLevel) @@ -6186,19 +5155,18 @@ static int computeNumNodesAtLevel(const TemplateStructIntf *s,int level,int maxL TemplateVariant child = s->get("children"); if (child.toList()) { - TemplateListIntf::ConstIterator *it = child.toList()->createIterator(); + TemplateListIntf::ConstIteratorPtr it = child.toList()->createIterator(); TemplateVariant v; for (it->toFirst();it->current(v);it->toNext()) { num+=computeNumNodesAtLevel(v.toStruct(),level+1,maxLevel); } - delete it; } } return num; } -static int computePreferredDepth(const TemplateListIntf *list,int maxDepth) +static int computePreferredDepth(const TemplateListIntfPtr list,int maxDepth) { int preferredNumEntries = Config_getInt(HTML_INDEX_NUM_ENTRIES); int preferredDepth=1; @@ -6208,13 +5176,12 @@ static int computePreferredDepth(const TemplateListIntf *list,int maxDepth) for (int i=1;i<=depth;i++) { int num=0; - TemplateListIntf::ConstIterator *it = list->createIterator(); + TemplateListIntf::ConstIteratorPtr it = list->createIterator(); TemplateVariant v; for (it->toFirst();it->current(v);it->toNext()) { num+=computeNumNodesAtLevel(v.toStruct(),0,i); } - delete it; if (num<=preferredNumEntries) { preferredDepth=i; @@ -6230,142 +5197,87 @@ static int computePreferredDepth(const TemplateListIntf *list,int maxDepth) //------------------------------------------------------------------------ -//%% struct ClassHierarchy: inheritance tree -//%% { class ClassHierarchyContext::Private { public: Private() { - m_classTree.reset(NestingContext::alloc(0,ContextTreeType::ClassInheritance,0)); + m_classTree = NestingContext::alloc(0,ContextTreeType::ClassInheritance,0); + auto ctx = std::dynamic_pointer_cast<NestingContext>(m_classTree); ClassDefSet visitedClasses; - m_classTree->addClassHierarchy(*Doxygen::classLinkedMap,visitedClasses); - m_classTree->addClassHierarchy(*Doxygen::hiddenClassLinkedMap,visitedClasses); - //%% ClassInheritance tree - static bool init=FALSE; - if (!init) - { - s_inst.addProperty("tree", &Private::tree); - s_inst.addProperty("fileName", &Private::fileName); - s_inst.addProperty("relPath", &Private::relPath); - s_inst.addProperty("highlight", &Private::highlight); - s_inst.addProperty("subhighlight", &Private::subhighlight); - s_inst.addProperty("title", &Private::title); - s_inst.addProperty("preferredDepth", &Private::preferredDepth); - s_inst.addProperty("maxDepth", &Private::maxDepth); - s_inst.addProperty("diagrams", &Private::diagrams); - init=TRUE; - } - } - TemplateVariant get(const QCString &n) const - { - return s_inst.get(this,n); + ctx->addClassHierarchy(*Doxygen::classLinkedMap,visitedClasses); + ctx->addClassHierarchy(*Doxygen::hiddenClassLinkedMap,visitedClasses); } - StringVector fields() const - { - return s_inst.fields(); - } - TemplateVariant tree() const - { - return m_classTree.get(); - } - TemplateVariant fileName() const - { - return "hierarchy"; - } - TemplateVariant relPath() const - { - return ""; - } - TemplateVariant highlight() const - { - return "classes"; - } - TemplateVariant subhighlight() const - { - return "classhierarchy"; - } - DotGfxHierarchyTable *getHierarchy() const + + // TemplateStructIntf methods + TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); } + StringVector fields() const { return s_inst.fields(); } + + private: + // Property getters + TemplateVariant tree() const { return TemplateVariant(m_classTree); } + TemplateVariant fileName() const { return "hierarchy"; } + TemplateVariant relPath() const { return ""; } + TemplateVariant highlight() const { return "classes"; } + TemplateVariant subhighlight() const { return "classhierarchy"; } + TemplateVariant diagrams() const { return m_diagrams.get(this); } + TemplateVariant maxDepth() const { return m_maxDepth.get(this); } + TemplateVariant preferredDepth() const { return m_preferredDepth.get(this); } + TemplateVariant title() const { - if (!m_cache.hierarchy) - { - m_cache.hierarchy.reset(new DotGfxHierarchyTable()); - } - return m_cache.hierarchy.get(); + return Config_getBool(OPTIMIZE_OUTPUT_VHDL) ? theTranslator->trDesignUnitHierarchy() : + theTranslator->trClassHierarchy(); } - TemplateVariant diagrams() const - { - if (!m_cache.diagrams) - { - TemplateList *diagrams = TemplateList::alloc(); - DotGfxHierarchyTable *hierarchy = getHierarchy(); - int id=0; - for (auto n : hierarchy->subGraphs()) - { - diagrams->append(InheritanceGraphContext::alloc(hierarchy,n,id++)); - } - m_cache.diagrams.reset(diagrams); - } - return m_cache.diagrams.get(); - } - TemplateVariant title() const + private: + int createMaxDepth() const { - static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL); - if (vhdlOpt) - { - return theTranslator->trDesignUnitHierarchy(); - } - else - { - return theTranslator->trClassHierarchy(); - } + return computeMaxDepth(m_classTree); } - TemplateVariant maxDepth() const + int createPreferredDepth() const { - if (!m_cache.maxDepthComputed) - { - m_cache.maxDepth = computeMaxDepth(m_classTree.get()); - m_cache.maxDepthComputed=TRUE; - } - return m_cache.maxDepth; + return computePreferredDepth(m_classTree,m_maxDepth.get(this)); } - TemplateVariant preferredDepth() const + TemplateVariant createDiagrams() const { - if (!m_cache.preferredDepthComputed) + TemplateVariantList diagrams; + DotGfxHierarchyTablePtr hierarchy = std::make_shared<DotGfxHierarchyTable>(); + diagrams.reserve(hierarchy->subGraphs().size()); + int id=0; + for (auto n : hierarchy->subGraphs()) { - m_cache.preferredDepth = computePreferredDepth(m_classTree.get(),maxDepth().toInt()); - m_cache.preferredDepthComputed=TRUE; + diagrams.push_back(InheritanceGraphContext::alloc(hierarchy,n,id++)); } - return m_cache.preferredDepth; + return TemplateImmutableList::alloc(diagrams); } - private: - SharedPtr<NestingContext> m_classTree; - struct Cachable - { - Cachable() : maxDepth(0), maxDepthComputed(FALSE), - preferredDepth(0), preferredDepthComputed(FALSE) {} - int maxDepth; - bool maxDepthComputed; - int preferredDepth; - bool preferredDepthComputed; - SharedPtr<TemplateList> diagrams; - std::unique_ptr<DotGfxHierarchyTable> hierarchy; - }; - mutable Cachable m_cache; - static PropertyMapper<ClassHierarchyContext::Private> s_inst; + + TemplateListIntfPtr m_classTree; + CachedItem<int, Private, &Private::createMaxDepth> m_maxDepth; + CachedItem<int, Private, &Private::createPreferredDepth> m_preferredDepth; + CachedItem<TemplateVariant, Private, &Private::createDiagrams> m_diagrams; + static const PropertyMap<ClassHierarchyContext::Private> s_inst; }; -//%% } -PropertyMapper<ClassHierarchyContext::Private> ClassHierarchyContext::Private::s_inst; +//%% struct ClassHierarchy: inheritance tree +//%% { +const PropertyMap<ClassHierarchyContext::Private> ClassHierarchyContext::Private::s_inst { + { "tree", &Private::tree }, + { "fileName", &Private::fileName }, + { "relPath", &Private::relPath }, + { "highlight", &Private::highlight }, + { "subhighlight", &Private::subhighlight }, + { "diagrams", &Private::diagrams }, + { "maxDepth", &Private::maxDepth }, + { "preferredDepth", &Private::preferredDepth }, + { "title", &Private::title }, +}; +//%% } -ClassHierarchyContext::ClassHierarchyContext() : RefCountedContext("ClassHierarchyContext") +ClassHierarchyContext::ClassHierarchyContext() : p(std::make_unique<Private>()) { - p = new Private; } ClassHierarchyContext::~ClassHierarchyContext() { - delete p; } TemplateVariant ClassHierarchyContext::get(const QCString &name) const @@ -6380,8 +5292,6 @@ StringVector ClassHierarchyContext::fields() const //------------------------------------------------------------------------ -//%% struct NestingNode: node is a nesting relation tree -//%% { class NestingNodeContext::Private { public: @@ -6392,49 +5302,8 @@ class NestingNodeContext::Private ClassDefSet &visitedClasses) : m_parent(parent), m_type(type), m_def(d), m_level(level), m_index(index) { - m_children.reset(NestingContext::alloc(thisNode,m_type,level+1)); - m_members.reset(NestingContext::alloc(thisNode,m_type,level+1)); - static bool init=FALSE; - if (!init) - { - //%% bool is_leaf_node: true if this node does not have any children - s_inst.addProperty("is_leaf_node",&Private::isLeafNode); - //%% Nesting children: list of nested classes/namespaces - s_inst.addProperty("children",&Private::children); - //%% Nesting children: list of nested classes/namespaces - s_inst.addProperty("members",&Private::members); - //%% [optional] Class class: class info (if this node represents a class) - s_inst.addProperty("class",&Private::getClass); - //%% [optional] Namespace namespace: namespace info (if this node represents a namespace) - s_inst.addProperty("namespace",&Private::getNamespace); - //%% [optional] File file: file info (if this node represents a file) - s_inst.addProperty("file",&Private::getFile); - //%% [optional] Dir dir: directory info (if this node represents a directory) - s_inst.addProperty("dir",&Private::getDir); - //%% [optional] Page page: page info (if this node represents a page) - s_inst.addProperty("page",&Private::getPage); - //%% [optional] Module module: module info (if this node represents a module) - s_inst.addProperty("module",&Private::getModule); - //%% [optional] Member member: member info (if this node represents a member) - s_inst.addProperty("member",&Private::getMember); - //%% int id - s_inst.addProperty("id",&Private::id); - //%% string level - s_inst.addProperty("level",&Private::level); - //%% string name - s_inst.addProperty("name",&Private::name); - //%% string brief - s_inst.addProperty("brief",&Private::brief); - //%% bool isLinkable - s_inst.addProperty("isLinkable",&Private::isLinkable); - s_inst.addProperty("partOfGroup",&Private::partOfGroup); - s_inst.addProperty("anchor",&Private::anchor); - s_inst.addProperty("fileName",&Private::fileName); - s_inst.addProperty("isReference",&Private::isReference); - s_inst.addProperty("externalReference",&Private::externalReference); - init=TRUE; - } - + m_children = std::dynamic_pointer_cast<NestingContext>(NestingContext::alloc(thisNode,m_type,level+1)); + m_members = std::dynamic_pointer_cast<NestingContext>(NestingContext::alloc(thisNode,m_type,level+1)); addNamespaces(addCls,addCps,visitedClasses); addClasses(inherit,hideSuper,visitedClasses); addDirFiles(visitedClasses); @@ -6442,135 +5311,11 @@ class NestingNodeContext::Private addModules(visitedClasses); addMembers(visitedClasses); } - TemplateVariant get(const QCString &n) const - { - return s_inst.get(this,n); - } - StringVector fields() const - { - return s_inst.fields(); - } - TemplateVariant isLeafNode() const - { - return m_children->count()==0; - } - TemplateVariant children() const - { - return m_children.get(); - } - TemplateVariant members() const - { - return m_members.get(); - } - TemplateVariant getClass() const - { - if (!m_cache.classContext && m_def->definitionType()==Definition::TypeClass) - { - m_cache.classContext.reset(ClassContext::alloc(toClassDef(m_def))); - } - if (m_cache.classContext) - { - return m_cache.classContext.get(); - } - else - { - return TemplateVariant(FALSE); - } - } - TemplateVariant getNamespace() const - { - if (!m_cache.namespaceContext && m_def->definitionType()==Definition::TypeNamespace) - { - m_cache.namespaceContext.reset(NamespaceContext::alloc(toNamespaceDef(m_def))); - } - if (m_cache.namespaceContext) - { - return m_cache.namespaceContext.get(); - } - else - { - return TemplateVariant(FALSE); - } - } - TemplateVariant getDir() const - { - if (!m_cache.dirContext && m_def->definitionType()==Definition::TypeDir) - { - m_cache.dirContext.reset(DirContext::alloc(toDirDef(m_def))); - } - if (m_cache.dirContext) - { - return m_cache.dirContext.get(); - } - else - { - return TemplateVariant(FALSE); - } - } - TemplateVariant getFile() const - { - if (!m_cache.fileContext && m_def->definitionType()==Definition::TypeFile) - { - m_cache.fileContext.reset(FileContext::alloc(toFileDef(m_def))); - } - if (m_cache.fileContext) - { - return m_cache.fileContext.get(); - } - else - { - return TemplateVariant(FALSE); - } - } - TemplateVariant getPage() const - { - if (!m_cache.pageContext && m_def->definitionType()==Definition::TypePage) - { - m_cache.pageContext.reset(PageContext::alloc(toPageDef(m_def),FALSE,FALSE)); - } - if (m_cache.pageContext) - { - return m_cache.pageContext.get(); - } - else - { - return TemplateVariant(FALSE); - } - } - TemplateVariant getModule() const - { - if (!m_cache.moduleContext && m_def->definitionType()==Definition::TypeGroup) - { - m_cache.moduleContext.reset(ModuleContext::alloc(toGroupDef(m_def))); - } - if (m_cache.moduleContext) - { - return m_cache.moduleContext.get(); - } - else - { - return TemplateVariant(FALSE); - } - } - TemplateVariant getMember() const - { - if (!m_cache.memberContext && m_def->definitionType()==Definition::TypeMember) - { - m_cache.memberContext.reset(MemberContext::alloc(toMemberDef(m_def))); - } - if (m_cache.memberContext) - { - return m_cache.memberContext.get(); - } - else - { - return TemplateVariant(FALSE); - } - } - TemplateVariant level() const - { - return m_level; - } + + // TemplateStructIntf methods + TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); } + StringVector fields() const { return s_inst.fields(); } + TemplateVariant id() const { QCString result; @@ -6578,6 +5323,26 @@ class NestingNodeContext::Private result+=QCString().setNum(m_index)+"_"; return result; } + + private: + // Property getters + TemplateVariant isLeafNode() const { return m_children->count()==0; } + TemplateVariant children() const { return std::static_pointer_cast<TemplateListIntf>(m_children); } + TemplateVariant members() const { return std::static_pointer_cast<TemplateListIntf>(m_members); } + TemplateVariant getClass() const { return m_class.get(this); } + TemplateVariant getNamespace() const { return m_namespace.get(this); } + TemplateVariant getDir() const { return m_dir.get(this); } + TemplateVariant getFile() const { return m_file.get(this); } + TemplateVariant getPage() const { return m_page.get(this); } + TemplateVariant getModule() const { return m_module.get(this); } + TemplateVariant getMember() const { return m_member.get(this); } + TemplateVariant level() const { return m_level; } + TemplateVariant brief() const { return m_brief.get(this); } + TemplateVariant isLinkable() const { return m_def->isLinkable(); } + TemplateVariant anchor() const { return m_def->anchor(); } + TemplateVariant fileName() const { return m_def->getOutputFileBase(); } + TemplateVariant isReference() const { return m_def->isReference(); } + TemplateVariant externalReference() const { return m_def->externalReference(relPathAsString()); } TemplateVariant name() const { if (m_def->definitionType()==Definition::TypeMember && m_type==ContextTreeType::Module) @@ -6599,42 +5364,6 @@ class NestingNodeContext::Private static bool createSubdirs = Config_getBool(CREATE_SUBDIRS); return createSubdirs ? QCString("../../") : QCString(""); } - TemplateVariant brief() const - { - if (!m_cache.brief) - { - if (m_def->hasBriefDescription()) - { - m_cache.brief.reset(new TemplateVariant(parseDoc(m_def,m_def->briefFile(),m_def->briefLine(), - "",m_def->briefDescription(),TRUE))); - } - else - { - m_cache.brief.reset(new TemplateVariant("")); - } - } - return *m_cache.brief; - } - TemplateVariant isLinkable() const - { - return m_def->isLinkable(); - } - TemplateVariant anchor() const - { - return m_def->anchor(); - } - TemplateVariant fileName() const - { - return m_def->getOutputFileBase(); - } - TemplateVariant isReference() const - { - return m_def->isReference(); - } - TemplateVariant externalReference() const - { - return m_def->externalReference(relPathAsString()); - } //------------------------------------------------------------------ @@ -6817,30 +5546,115 @@ class NestingNodeContext::Private } } private: + TemplateVariant createClass() const + { + return m_def->definitionType()==Definition::TypeClass ? + TemplateVariant(ClassContext::alloc(toClassDef(m_def))) : + TemplateVariant(false); + } + TemplateVariant createNamespace() const + { + return m_def->definitionType()==Definition::TypeNamespace ? + TemplateVariant(NamespaceContext::alloc(toNamespaceDef(m_def))) : + TemplateVariant(false); + } + TemplateVariant createDir() const + { + return m_def->definitionType()==Definition::TypeDir ? + TemplateVariant(DirContext::alloc(toDirDef(m_def))) : + TemplateVariant(false); + } + TemplateVariant createFile() const + { + return m_def->definitionType()==Definition::TypeFile ? + TemplateVariant(FileContext::alloc(toFileDef(m_def))) : + TemplateVariant(false); + } + TemplateVariant createPage() const + { + return m_def->definitionType()==Definition::TypePage ? + TemplateVariant(PageContext::alloc(toPageDef(m_def),FALSE,FALSE)) : + TemplateVariant(false); + } + TemplateVariant createModule() const + { + return m_def->definitionType()==Definition::TypeGroup ? + TemplateVariant(ModuleContext::alloc(toGroupDef(m_def))) : + TemplateVariant(false); + } + TemplateVariant createMember() const + { + return m_def->definitionType()==Definition::TypeMember ? + TemplateVariant(MemberContext::alloc(toMemberDef(m_def))) : + TemplateVariant(false); + } + TemplateVariant createBrief() const + { + return m_def->hasBriefDescription() ? + TemplateVariant(parseDoc(m_def,m_def->briefFile(),m_def->briefLine(), + "",m_def->briefDescription(),TRUE)) : + TemplateVariant(""); + } + const NestingNodeContext *m_parent; ContextTreeType m_type; const Definition *m_def; - SharedPtr<NestingContext> m_children; - SharedPtr<NestingContext> m_members; + std::shared_ptr<NestingContext> m_children; + std::shared_ptr<NestingContext> m_members; int m_level; int m_index; - struct Cachable - { - SharedPtr<ClassContext> classContext; - SharedPtr<NamespaceContext> namespaceContext; - SharedPtr<DirContext> dirContext; - SharedPtr<FileContext> fileContext; - SharedPtr<PageContext> pageContext; - SharedPtr<ModuleContext> moduleContext; - SharedPtr<MemberContext> memberContext; - std::unique_ptr<TemplateVariant> brief; - }; - mutable Cachable m_cache; - static PropertyMapper<NestingNodeContext::Private> s_inst; + CachedItem<TemplateVariant, Private, &Private::createClass> m_class; + CachedItem<TemplateVariant, Private, &Private::createNamespace> m_namespace; + CachedItem<TemplateVariant, Private, &Private::createDir> m_dir; + CachedItem<TemplateVariant, Private, &Private::createFile> m_file; + CachedItem<TemplateVariant, Private, &Private::createPage> m_page; + CachedItem<TemplateVariant, Private, &Private::createModule> m_module; + CachedItem<TemplateVariant, Private, &Private::createMember> m_member; + CachedItem<TemplateVariant, Private, &Private::createBrief> m_brief; + static const PropertyMap<NestingNodeContext::Private> s_inst; +}; + +//%% struct NestingNode: node is a nesting relation tree +//%% { +const PropertyMap<NestingNodeContext::Private> NestingNodeContext::Private::s_inst { + //%% bool is_leaf_node: true if this node does not have any children + { "is_leaf_node",&Private::isLeafNode }, + //%% Nesting children: list of nested classes/namespaces + { "children",&Private::children }, + //%% Nesting children: list of nested classes/namespaces + { "members",&Private::members }, + //%% [optional] Class class: class info (if this node represents a class) + { "class",&Private::getClass }, + //%% [optional] Namespace namespace: namespace info (if this node represents a namespace) + { "namespace",&Private::getNamespace }, + //%% [optional] File file: file info (if this node represents a file) + { "file",&Private::getFile }, + //%% [optional] Dir dir: directory info (if this node represents a directory) + { "dir",&Private::getDir }, + //%% [optional] Page page: page info (if this node represents a page) + { "page",&Private::getPage }, + //%% [optional] Module module: module info (if this node represents a module) + { "module",&Private::getModule }, + //%% [optional] Member member: member info (if this node represents a member) + { "member",&Private::getMember }, + //%% int id + { "id",&Private::id }, + //%% string level + { "level",&Private::level }, + //%% string name + { "name",&Private::name }, + //%% string brief + { "brief",&Private::brief }, + //%% bool isLinkable + { "isLinkable",&Private::isLinkable }, + { "partOfGroup",&Private::partOfGroup }, + { "anchor",&Private::anchor }, + { "fileName",&Private::fileName }, + { "isReference",&Private::isReference }, + { "externalReference",&Private::externalReference } }; //%% } -PropertyMapper<NestingNodeContext::Private> NestingNodeContext::Private::s_inst; NestingNodeContext::NestingNodeContext(const NestingNodeContext *parent, ContextTreeType type, @@ -6848,14 +5662,12 @@ NestingNodeContext::NestingNodeContext(const NestingNodeContext *parent, bool addClass,bool addConcepts, bool inherit,bool hideSuper, ClassDefSet &visitedClasses) - : RefCountedContext("NestingNodeContext") + : p(std::make_unique<Private>(parent,this,type,d,index,level,addClass,addConcepts,inherit,hideSuper,visitedClasses)) { - p = new Private(parent,this,type,d,index,level,addClass,addConcepts,inherit,hideSuper,visitedClasses); } NestingNodeContext::~NestingNodeContext() { - delete p; } TemplateVariant NestingNodeContext::get(const QCString &n) const @@ -6895,9 +5707,8 @@ class NestingContext::Private : public GenericNodeListContext bool isLinkable = nd->isLinkableInProject(); if (isLinkable && hasChildren) { - NestingNodeContext *nnc = NestingNodeContext::alloc(m_parent,m_type,nd,m_index,m_level, - addClasses,addConcepts,FALSE,FALSE,visitedClasses); - append(nnc); + append(NestingNodeContext::alloc(m_parent,m_type,nd,m_index,m_level, + addClasses,addConcepts,FALSE,FALSE,visitedClasses)); m_index++; } } @@ -6934,9 +5745,8 @@ class NestingContext::Private : public GenericNodeListContext { if (classVisibleInIndex(cd) && cd->templateMaster()==0) { - NestingNodeContext *nnc = NestingNodeContext::alloc(m_parent,m_type,cd,m_index,m_level, - TRUE,FALSE,FALSE,FALSE,visitedClasses); - append(nnc); + append(NestingNodeContext::alloc(m_parent,m_type,cd,m_index,m_level, + TRUE,FALSE,FALSE,FALSE,visitedClasses)); m_index++; } } @@ -6947,9 +5757,8 @@ class NestingContext::Private : public GenericNodeListContext { if (cd->isLinkable()) { - NestingNodeContext *nnc = NestingNodeContext::alloc(m_parent,m_type,cd,m_index,m_level, - FALSE,TRUE,FALSE,FALSE,visitedClasses); - append(nnc); + append(NestingNodeContext::alloc(m_parent,m_type,cd,m_index,m_level, + FALSE,TRUE,FALSE,FALSE,visitedClasses)); m_index++; } } @@ -7011,9 +5820,8 @@ class NestingContext::Private : public GenericNodeListContext { if (fd->getDirDef()==0) // top level file { - NestingNodeContext *nnc = NestingNodeContext::alloc(m_parent,m_type,fd.get(),m_index,m_level, - FALSE,FALSE,FALSE,FALSE,visitedClasses); - append(nnc); + append(NestingNodeContext::alloc(m_parent,m_type,fd.get(),m_index,m_level, + FALSE,FALSE,FALSE,FALSE,visitedClasses)); m_index++; } } @@ -7023,9 +5831,8 @@ class NestingContext::Private : public GenericNodeListContext { for (const auto &fd : fList) { - NestingNodeContext *nnc=NestingNodeContext::alloc(m_parent,m_type,fd,m_index,m_level, - FALSE,FALSE,FALSE,FALSE,visitedClasses); - append(nnc); + append(NestingNodeContext::alloc(m_parent,m_type,fd,m_index,m_level, + FALSE,FALSE,FALSE,FALSE,visitedClasses)); m_index++; } } @@ -7103,9 +5910,8 @@ class NestingContext::Private : public GenericNodeListContext if (cd->isVisibleInHierarchy() && b) { - NestingNodeContext *tnc = NestingNodeContext::alloc(m_parent,m_type,cd,m_index,m_level, - TRUE,FALSE,TRUE,hideSuper,visitedClasses); - append(tnc); + append(NestingNodeContext::alloc(m_parent,m_type,cd,m_index,m_level, + TRUE,FALSE,TRUE,hideSuper,visitedClasses)); m_index++; } } @@ -7132,9 +5938,8 @@ class NestingContext::Private : public GenericNodeListContext if (cd->isVisibleInHierarchy()) // should it be visible { // new root level class - NestingNodeContext *nnc = NestingNodeContext::alloc(m_parent,m_type,cd.get(),m_index,m_level, - TRUE,FALSE,TRUE,FALSE,visitedClasses); - append(nnc); + append(NestingNodeContext::alloc(m_parent,m_type,cd.get(),m_index,m_level, + TRUE,FALSE,TRUE,FALSE,visitedClasses)); m_index++; } } @@ -7146,9 +5951,8 @@ class NestingContext::Private : public GenericNodeListContext { if (md->visibleInIndex()) { - NestingNodeContext *nnc = NestingNodeContext::alloc(m_parent,m_type,md,m_index,m_level+1, - TRUE,FALSE,TRUE,FALSE,visitedClasses); - append(nnc); + append(NestingNodeContext::alloc(m_parent,m_type,md,m_index,m_level+1, + TRUE,FALSE,TRUE,FALSE,visitedClasses)); m_index++; } } @@ -7161,15 +5965,12 @@ class NestingContext::Private : public GenericNodeListContext int m_index = 0; }; -NestingContext::NestingContext(const NestingNodeContext *parent,ContextTreeType type,int level) : - RefCountedContext("NestingContext") +NestingContext::NestingContext(const NestingNodeContext *parent,ContextTreeType type,int level) : p(std::make_unique<Private>(parent,type,level)) { - p = new Private(parent,type,level); } NestingContext::~NestingContext() { - delete p; } // TemplateListIntf @@ -7183,7 +5984,7 @@ TemplateVariant NestingContext::at(uint index) const return p->at(index); } -TemplateListIntf::ConstIterator *NestingContext::createIterator() const +TemplateListIntf::ConstIteratorPtr NestingContext::createIterator() const { return p->createIterator(); } @@ -7276,121 +6077,73 @@ void NestingContext::addMembers(const MemberVector &mv,ClassDefSet &visitedClass //------------------------------------------------------------------------ -//%% struct ClassTree: Class nesting relations -//%% { class ClassTreeContext::Private { public: Private() { - m_classTree.reset(NestingContext::alloc(0,ContextTreeType::ClassNesting,0)); + m_classTree = NestingContext::alloc(0,ContextTreeType::ClassNesting,0); + auto ctx = std::dynamic_pointer_cast<NestingContext>(m_classTree); ClassDefSet visitedClasses; - m_classTree->addNamespaces(*Doxygen::namespaceLinkedMap,TRUE,TRUE,FALSE,visitedClasses); - m_classTree->addClasses(*Doxygen::classLinkedMap,TRUE,visitedClasses); - //%% Nesting tree - static bool init=FALSE; - if (!init) - { - s_inst.addProperty("tree", &Private::tree); - s_inst.addProperty("fileName", &Private::fileName); - s_inst.addProperty("relPath", &Private::relPath); - s_inst.addProperty("highlight", &Private::highlight); - s_inst.addProperty("subhighlight", &Private::subhighlight); - s_inst.addProperty("title", &Private::title); - s_inst.addProperty("preferredDepth",&Private::preferredDepth); - s_inst.addProperty("maxDepth", &Private::maxDepth); - init=TRUE; - } - } - TemplateVariant get(const QCString &n) const - { - return s_inst.get(this,n); - } - StringVector fields() const - { - return s_inst.fields(); - } - TemplateVariant tree() const - { - return m_classTree.get(); - } - TemplateVariant fileName() const - { - return "annotated"; - } - TemplateVariant relPath() const - { - return ""; - } - TemplateVariant highlight() const - { - return "classes"; - } - TemplateVariant subhighlight() const - { - return "classlist"; + ctx->addNamespaces(*Doxygen::namespaceLinkedMap,TRUE,TRUE,FALSE,visitedClasses); + ctx->addClasses(*Doxygen::classLinkedMap,TRUE,visitedClasses); } + + // TemplateStructIntf methods + TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); } + StringVector fields() const { return s_inst.fields(); } + + private: + // Property getters + TemplateVariant tree() const { return TemplateVariant(m_classTree); } + TemplateVariant fileName() const { return "annotated"; } + TemplateVariant relPath() const { return ""; } + TemplateVariant highlight() const { return "classes"; } + TemplateVariant subhighlight() const { return "classlist"; } + TemplateVariant maxDepth() const { return m_maxDepth.get(this); } + TemplateVariant preferredDepth() const { return m_preferredDepth.get(this); } TemplateVariant title() const { - static bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN); - static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL); - if (fortranOpt) - { - return theTranslator->trCompoundListFortran(); - } - else if (vhdlOpt) - { - return theTranslator->trDesignUnitList(); - } - else - { - return theTranslator->trClasses(); - } + return Config_getBool(OPTIMIZE_FOR_FORTRAN) ? theTranslator->trCompoundListFortran() : + Config_getBool(OPTIMIZE_OUTPUT_VHDL) ? theTranslator->trDesignUnitList() : + theTranslator->trClasses(); } - TemplateVariant maxDepth() const + private: + int createMaxDepth() const { - if (!m_cache.maxDepthComputed) - { - m_cache.maxDepth = computeMaxDepth(m_classTree.get()); - m_cache.maxDepthComputed=TRUE; - } - return m_cache.maxDepth; + return computeMaxDepth(m_classTree); } - TemplateVariant preferredDepth() const + int createPreferredDepth() const { - if (!m_cache.preferredDepthComputed) - { - m_cache.preferredDepth = computePreferredDepth(m_classTree.get(),maxDepth().toInt()); - m_cache.preferredDepthComputed=TRUE; - } - return m_cache.preferredDepth; + return computePreferredDepth(m_classTree,m_maxDepth.get(this)); } - private: - SharedPtr<NestingContext> m_classTree; - struct Cachable - { - Cachable() : maxDepth(0), maxDepthComputed(FALSE), - preferredDepth(0), preferredDepthComputed(FALSE) {} - int maxDepth; - bool maxDepthComputed; - int preferredDepth; - bool preferredDepthComputed; - }; - mutable Cachable m_cache; - static PropertyMapper<ClassTreeContext::Private> s_inst; + TemplateListIntfPtr m_classTree; + CachedItem<int, Private, &Private::createMaxDepth> m_maxDepth; + CachedItem<int, Private, &Private::createPreferredDepth> m_preferredDepth; + static const PropertyMap<ClassTreeContext::Private> s_inst; +}; + +//%% struct ClassTree: Class nesting relations +//%% { +const PropertyMap<ClassTreeContext::Private> ClassTreeContext::Private::s_inst { + { "tree", &Private::tree }, + { "fileName", &Private::fileName }, + { "relPath", &Private::relPath }, + { "highlight", &Private::highlight }, + { "subhighlight", &Private::subhighlight }, + { "title", &Private::title }, + { "preferredDepth",&Private::preferredDepth }, + { "maxDepth", &Private::maxDepth } }; //%% } -PropertyMapper<ClassTreeContext::Private> ClassTreeContext::Private::s_inst; -ClassTreeContext::ClassTreeContext() : RefCountedContext("ClassTreeContext") +ClassTreeContext::ClassTreeContext() : p(std::make_unique<Private>()) { - p = new Private; } ClassTreeContext::~ClassTreeContext() { - delete p; } TemplateVariant ClassTreeContext::get(const QCString &name) const @@ -7421,15 +6174,13 @@ class ConceptListContext::Private : public GenericNodeListContext } }; -ConceptListContext::ConceptListContext() : RefCountedContext("ConceptListContext") +ConceptListContext::ConceptListContext() : p(std::make_unique<Private>()) { - p = new Private; p->addConcepts(*Doxygen::conceptLinkedMap); } ConceptListContext::~ConceptListContext() { - delete p; } // TemplateListIntf @@ -7443,7 +6194,7 @@ TemplateVariant ConceptListContext::at(uint index) const return p->at(index); } -TemplateListIntf::ConstIterator *ConceptListContext::createIterator() const +TemplateListIntf::ConstIteratorPtr ConceptListContext::createIterator() const { return p->createIterator(); } @@ -7466,15 +6217,13 @@ class NamespaceListContext::Private : public GenericNodeListContext } }; -NamespaceListContext::NamespaceListContext() : RefCountedContext("NamespaceListContext") +NamespaceListContext::NamespaceListContext() : p(std::make_unique<Private>()) { - p = new Private; p->addNamespaces(*Doxygen::namespaceLinkedMap); } NamespaceListContext::~NamespaceListContext() { - delete p; } // TemplateListIntf @@ -7488,129 +6237,81 @@ TemplateVariant NamespaceListContext::at(uint index) const return p->at(index); } -TemplateListIntf::ConstIterator *NamespaceListContext::createIterator() const +TemplateListIntf::ConstIteratorPtr NamespaceListContext::createIterator() const { return p->createIterator(); } //------------------------------------------------------------------------ -//%% struct NamespaceTree: tree of nested namespace -//%% { class NamespaceTreeContext::Private { public: Private() { - m_namespaceTree.reset(NestingContext::alloc(0,ContextTreeType::Namespace,0)); + m_namespaceTree = NestingContext::alloc(0,ContextTreeType::Namespace,0); + auto ctx = std::dynamic_pointer_cast<NestingContext>(m_namespaceTree); ClassDefSet visitedClasses; - m_namespaceTree->addNamespaces(*Doxygen::namespaceLinkedMap,TRUE,FALSE,TRUE,visitedClasses); - //%% Nesting tree - static bool init=FALSE; - if (!init) - { - s_inst.addProperty("tree", &Private::tree); - s_inst.addProperty("fileName", &Private::fileName); - s_inst.addProperty("relPath", &Private::relPath); - s_inst.addProperty("highlight", &Private::highlight); - s_inst.addProperty("subhighlight", &Private::subhighlight); - s_inst.addProperty("title", &Private::title); - s_inst.addProperty("preferredDepth",&Private::preferredDepth); - s_inst.addProperty("maxDepth", &Private::maxDepth); - init=TRUE; - } - } - TemplateVariant get(const QCString &n) const - { - return s_inst.get(this,n); - } - StringVector fields() const - { - return s_inst.fields(); - } - TemplateVariant tree() const - { - return m_namespaceTree.get(); - } - TemplateVariant fileName() const - { - return "namespaces"; - } - TemplateVariant relPath() const - { - return ""; - } - TemplateVariant highlight() const - { - return "namespaces"; - } - TemplateVariant subhighlight() const - { - return "namespacelist"; + ctx->addNamespaces(*Doxygen::namespaceLinkedMap,TRUE,FALSE,TRUE,visitedClasses); } + + // TemplateStructIntf methods + TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); } + StringVector fields() const { return s_inst.fields(); } + + private: + // Property getters + TemplateVariant tree() const { return TemplateVariant(m_namespaceTree); } + TemplateVariant fileName() const { return "namespaces"; } + TemplateVariant relPath() const { return ""; } + TemplateVariant highlight() const { return "namespaces"; } + TemplateVariant subhighlight() const { return "namespacelist"; } + TemplateVariant maxDepth() const { return m_maxDepth.get(this); } + TemplateVariant preferredDepth() const { return m_preferredDepth.get(this); } TemplateVariant title() const { - static bool javaOpt = Config_getBool(OPTIMIZE_OUTPUT_JAVA); - static bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN); - static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL); - static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE); - if (javaOpt || vhdlOpt) - { - return theTranslator->trPackages(); - } - else if (fortranOpt || sliceOpt) - { - return theTranslator->trModulesList(); - } - else - { - return theTranslator->trNamespaceList(); - } + return Config_getBool(OPTIMIZE_OUTPUT_JAVA) ? theTranslator->trPackages() : + Config_getBool(OPTIMIZE_OUTPUT_VHDL) ? theTranslator->trPackages() : + Config_getBool(OPTIMIZE_FOR_FORTRAN) ? theTranslator->trModulesList() : + Config_getBool(OPTIMIZE_OUTPUT_SLICE) ? theTranslator->trModulesList() : + theTranslator->trNamespaceList(); } - TemplateVariant maxDepth() const + + private: + int createMaxDepth() const { - if (!m_cache.maxDepthComputed) - { - m_cache.maxDepth = computeMaxDepth(m_namespaceTree.get()); - m_cache.maxDepthComputed=TRUE; - } - return m_cache.maxDepth; + return computeMaxDepth(m_namespaceTree); } - TemplateVariant preferredDepth() const + int createPreferredDepth() const { - if (!m_cache.preferredDepthComputed) - { - m_cache.preferredDepth = computePreferredDepth(m_namespaceTree.get(),maxDepth().toInt()); - m_cache.preferredDepthComputed=TRUE; - } - return m_cache.preferredDepth; + return computePreferredDepth(m_namespaceTree,m_maxDepth.get(this)); } - private: - SharedPtr<NestingContext> m_namespaceTree; - struct Cachable - { - Cachable() : maxDepth(0), maxDepthComputed(FALSE), - preferredDepth(0), preferredDepthComputed(FALSE) {} - int maxDepth; - bool maxDepthComputed; - int preferredDepth; - bool preferredDepthComputed; - }; - mutable Cachable m_cache; - static PropertyMapper<NamespaceTreeContext::Private> s_inst; + TemplateListIntfPtr m_namespaceTree; + CachedItem<int, Private, &Private::createMaxDepth> m_maxDepth; + CachedItem<int, Private, &Private::createPreferredDepth> m_preferredDepth; + static const PropertyMap<NamespaceTreeContext::Private> s_inst; }; -//%% } -PropertyMapper<NamespaceTreeContext::Private> NamespaceTreeContext::Private::s_inst; +//%% struct NamespaceTree: tree of nested namespace +//%% { +const PropertyMap<NamespaceTreeContext::Private> NamespaceTreeContext::Private::s_inst { + { "tree", &Private::tree }, + { "fileName", &Private::fileName }, + { "relPath", &Private::relPath }, + { "highlight", &Private::highlight }, + { "subhighlight", &Private::subhighlight }, + { "title", &Private::title }, + { "preferredDepth",&Private::preferredDepth }, + { "maxDepth", &Private::maxDepth } +}; +//%% } -NamespaceTreeContext::NamespaceTreeContext() : RefCountedContext("NamespaceTreeContext") +NamespaceTreeContext::NamespaceTreeContext() : p(std::make_unique<Private>()) { - p = new Private; } NamespaceTreeContext::~NamespaceTreeContext() { - delete p; } TemplateVariant NamespaceTreeContext::get(const QCString &name) const @@ -7649,15 +6350,13 @@ class FileListContext::Private : public GenericNodeListContext } }; -FileListContext::FileListContext() : RefCountedContext("FileListContext") +FileListContext::FileListContext() : p(std::make_unique<Private>()) { - p = new Private; if (Doxygen::inputNameLinkedMap) p->addFiles(*Doxygen::inputNameLinkedMap); } FileListContext::~FileListContext() { - delete p; } // TemplateListIntf @@ -7671,7 +6370,7 @@ TemplateVariant FileListContext::at(uint index) const return p->at(index); } -TemplateListIntf::ConstIterator *FileListContext::createIterator() const +TemplateListIntf::ConstIteratorPtr FileListContext::createIterator() const { return p->createIterator(); } @@ -7691,14 +6390,12 @@ class DirListContext::Private : public GenericNodeListContext } }; -DirListContext::DirListContext() : RefCountedContext("DirListContext") +DirListContext::DirListContext() : p(std::make_unique<Private>()) { - p = new Private; } DirListContext::~DirListContext() { - delete p; } // TemplateListIntf @@ -7712,7 +6409,7 @@ TemplateVariant DirListContext::at(uint index) const return p->at(index); } -TemplateListIntf::ConstIterator *DirListContext::createIterator() const +TemplateListIntf::ConstIteratorPtr DirListContext::createIterator() const { return p->createIterator(); } @@ -7730,9 +6427,8 @@ class UsedFilesContext::Private : public GenericNodeListContext } }; -UsedFilesContext::UsedFilesContext(const ClassDef *cd) : RefCountedContext("UsedFilesContext") +UsedFilesContext::UsedFilesContext(const ClassDef *cd) : p(std::make_unique<Private>()) { - p = new Private; if (cd) { for (const auto &fd : cd->usedFiles()) @@ -7744,7 +6440,6 @@ UsedFilesContext::UsedFilesContext(const ClassDef *cd) : RefCountedContext("Used UsedFilesContext::~UsedFilesContext() { - delete p; } // TemplateListIntf @@ -7758,7 +6453,7 @@ TemplateVariant UsedFilesContext::at(uint index) const return p->at(index); } -TemplateListIntf::ConstIterator *UsedFilesContext::createIterator() const +TemplateListIntf::ConstIteratorPtr UsedFilesContext::createIterator() const { return p->createIterator(); } @@ -7770,112 +6465,74 @@ void UsedFilesContext::addFile(const FileDef *fd) //------------------------------------------------------------------------ -//%% struct FileTree: tree of directories and files -//%% { class FileTreeContext::Private { public: Private() { // Add dirs tree - m_dirFileTree.reset(NestingContext::alloc(0,ContextTreeType::File,0)); + m_dirFileTree = NestingContext::alloc(0,ContextTreeType::File,0); + auto ctx = std::dynamic_pointer_cast<NestingContext>(m_dirFileTree); ClassDefSet visitedClasses; - m_dirFileTree->addDirs(*Doxygen::dirLinkedMap,visitedClasses); + ctx->addDirs(*Doxygen::dirLinkedMap,visitedClasses); if (Doxygen::inputNameLinkedMap) { - m_dirFileTree->addFiles(*Doxygen::inputNameLinkedMap,visitedClasses); + ctx->addFiles(*Doxygen::inputNameLinkedMap,visitedClasses); } - //%% DirFile tree: - static bool init=FALSE; - if (!init) - { - s_inst.addProperty("tree", &Private::tree); - s_inst.addProperty("fileName", &Private::fileName); - s_inst.addProperty("relPath", &Private::relPath); - s_inst.addProperty("highlight", &Private::highlight); - s_inst.addProperty("subhighlight", &Private::subhighlight); - s_inst.addProperty("title", &Private::title); - s_inst.addProperty("preferredDepth",&Private::preferredDepth); - s_inst.addProperty("maxDepth", &Private::maxDepth); - init=TRUE; - } - } - TemplateVariant get(const QCString &n) const - { - return s_inst.get(this,n); - } - StringVector fields() const - { - return s_inst.fields(); - } - TemplateVariant tree() const - { - return m_dirFileTree.get(); - } - TemplateVariant fileName() const - { - return "files"; - } - TemplateVariant relPath() const - { - return ""; - } - TemplateVariant highlight() const - { - return "files"; - } - TemplateVariant subhighlight() const - { - return "filelist"; - } - TemplateVariant title() const - { - return theTranslator->trFileList(); } - TemplateVariant maxDepth() const + + // TemplateStructIntf methods + TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); } + StringVector fields() const { return s_inst.fields(); } + + private: + // Property getters + TemplateVariant tree() const { return TemplateVariant(m_dirFileTree); } + TemplateVariant fileName() const { return "files"; } + TemplateVariant relPath() const { return ""; } + TemplateVariant highlight() const { return "files"; } + TemplateVariant subhighlight() const { return "filelist"; } + TemplateVariant maxDepth() const { return m_maxDepth.get(this); } + TemplateVariant preferredDepth() const { return m_preferredDepth.get(this); } + TemplateVariant title() const { return theTranslator->trFileList(); } + + private: + int createMaxDepth() const { - if (!m_cache.maxDepthComputed) - { - m_cache.maxDepth = computeMaxDepth(m_dirFileTree.get()); - m_cache.maxDepthComputed=TRUE; - } - return m_cache.maxDepth; + return computeMaxDepth(m_dirFileTree); } - TemplateVariant preferredDepth() const + int createPreferredDepth() const { - if (!m_cache.preferredDepthComputed) - { - m_cache.preferredDepth = computePreferredDepth(m_dirFileTree.get(),maxDepth().toInt()); - m_cache.preferredDepthComputed=TRUE; - } - return m_cache.preferredDepth; + return computePreferredDepth(m_dirFileTree,m_maxDepth.get(this)); } - private: - SharedPtr<NestingContext> m_dirFileTree; - struct Cachable - { - Cachable() : maxDepth(0), maxDepthComputed(FALSE), - preferredDepth(0), preferredDepthComputed(FALSE) {} - int maxDepth; - bool maxDepthComputed; - int preferredDepth; - bool preferredDepthComputed; - }; - mutable Cachable m_cache; - static PropertyMapper<FileTreeContext::Private> s_inst; + TemplateListIntfPtr m_dirFileTree; + CachedItem<int, Private, &Private::createMaxDepth> m_maxDepth; + CachedItem<int, Private, &Private::createPreferredDepth> m_preferredDepth; + static const PropertyMap<FileTreeContext::Private> s_inst; +}; + +//%% struct FileTree: tree of directories and files +//%% { +const PropertyMap<FileTreeContext::Private> FileTreeContext::Private::s_inst { + { "tree", &Private::tree }, + { "fileName", &Private::fileName }, + { "relPath", &Private::relPath }, + { "highlight", &Private::highlight }, + { "subhighlight", &Private::subhighlight }, + { "title", &Private::title }, + { "preferredDepth",&Private::preferredDepth }, + { "maxDepth", &Private::maxDepth } }; //%% } -PropertyMapper<FileTreeContext::Private> FileTreeContext::Private::s_inst; +//PropertyMapper<FileTreeContext::Private> FileTreeContext::Private::s_inst; -FileTreeContext::FileTreeContext() : RefCountedContext("FileTreeContext") +FileTreeContext::FileTreeContext() : p(std::make_unique<Private>()) { - p = new Private; } FileTreeContext::~FileTreeContext() { - delete p; } TemplateVariant FileTreeContext::get(const QCString &name) const @@ -7890,109 +6547,69 @@ StringVector FileTreeContext::fields() const //------------------------------------------------------------------------ -//%% struct PageTree: tree of related pages -//%% { class PageTreeContext::Private { public: Private(const PageLinkedMap &pages) { - m_pageTree.reset(NestingContext::alloc(0,ContextTreeType::Page,0)); + m_pageTree = NestingContext::alloc(0,ContextTreeType::Page,0); + auto ctx = std::dynamic_pointer_cast<NestingContext>(m_pageTree); ClassDefSet visitedClasses; // Add pages - m_pageTree->addPages(pages,TRUE,visitedClasses); - - //%% PageNodeList tree: - static bool init=FALSE; - if (!init) - { - s_inst.addProperty("tree", &Private::tree); - s_inst.addProperty("fileName", &Private::fileName); - s_inst.addProperty("relPath", &Private::relPath); - s_inst.addProperty("highlight", &Private::highlight); - s_inst.addProperty("subhighlight", &Private::subhighlight); - s_inst.addProperty("title", &Private::title); - s_inst.addProperty("preferredDepth",&Private::preferredDepth); - s_inst.addProperty("maxDepth", &Private::maxDepth); - init=TRUE; - } - } - TemplateVariant get(const QCString &n) const - { - return s_inst.get(this,n); - } - StringVector fields() const - { - return s_inst.fields(); - } - TemplateVariant tree() const - { - return m_pageTree.get(); - } - TemplateVariant fileName() const - { - return "pages"; + ctx->addPages(pages,TRUE,visitedClasses); } - TemplateVariant relPath() const - { - return ""; - } - TemplateVariant highlight() const - { - return "pages"; - } - TemplateVariant subhighlight() const - { - return ""; - } - TemplateVariant title() const + + // TemplateStructIntf methods + TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); } + StringVector fields() const { return s_inst.fields(); } + + private: + // Property getters + TemplateVariant tree() const { return TemplateVariant(m_pageTree); } + TemplateVariant fileName() const { return "pages"; } + TemplateVariant relPath() const { return ""; } + TemplateVariant highlight() const { return "pages"; } + TemplateVariant subhighlight() const { return ""; } + TemplateVariant maxDepth() const { return m_maxDepth.get(this); } + TemplateVariant preferredDepth() const { return m_preferredDepth.get(this); } + TemplateVariant title() const { return theTranslator->trRelatedPages(); } + + private: + int createMaxDepth() const { - return theTranslator->trRelatedPages(); + return computeMaxDepth(m_pageTree); } - TemplateVariant maxDepth() const + int createPreferredDepth() const { - if (!m_cache.maxDepthComputed) - { - m_cache.maxDepth = computeMaxDepth(m_pageTree.get()); - m_cache.maxDepthComputed=TRUE; - } - return m_cache.maxDepth; + return computePreferredDepth(m_pageTree,m_maxDepth.get(this)); } - TemplateVariant preferredDepth() const - { - if (!m_cache.preferredDepthComputed) - { - m_cache.preferredDepth = computePreferredDepth(m_pageTree.get(),maxDepth().toInt()); - m_cache.preferredDepthComputed=TRUE; - } - return m_cache.preferredDepth; - } - private: - SharedPtr<NestingContext> m_pageTree; - struct Cachable - { - Cachable() : maxDepth(0), maxDepthComputed(FALSE), - preferredDepth(0), preferredDepthComputed(FALSE) {} - int maxDepth; - bool maxDepthComputed; - int preferredDepth; - bool preferredDepthComputed; - }; - mutable Cachable m_cache; - static PropertyMapper<PageTreeContext::Private> s_inst; + TemplateListIntfPtr m_pageTree; + CachedItem<int, Private, &Private::createMaxDepth> m_maxDepth; + CachedItem<int, Private, &Private::createPreferredDepth> m_preferredDepth; + static const PropertyMap<PageTreeContext::Private> s_inst; +}; + +//%% struct PageTree: tree of related pages +//%% { +const PropertyMap<PageTreeContext::Private> PageTreeContext::Private::s_inst { + { "tree", &Private::tree }, + { "fileName", &Private::fileName }, + { "relPath", &Private::relPath }, + { "highlight", &Private::highlight }, + { "subhighlight", &Private::subhighlight }, + { "title", &Private::title }, + { "preferredDepth",&Private::preferredDepth }, + { "maxDepth", &Private::maxDepth } }; //%% } -PropertyMapper<PageTreeContext::Private> PageTreeContext::Private::s_inst; -PageTreeContext::PageTreeContext(const PageLinkedMap &pages) : RefCountedContext("PageTreeContext") +PageTreeContext::PageTreeContext(const PageLinkedMap &pages) : p(std::make_unique<Private>(pages)) { - p = new Private(pages); } PageTreeContext::~PageTreeContext() { - delete p; } TemplateVariant PageTreeContext::get(const QCString &name) const @@ -8023,15 +6640,13 @@ class PageListContext::Private : public GenericNodeListContext } }; -PageListContext::PageListContext(const PageLinkedMap &pages) : RefCountedContext("PageListContext") +PageListContext::PageListContext(const PageLinkedMap &pages) : p(std::make_unique<Private>()) { - p = new Private; p->addPages(pages); } PageListContext::~PageListContext() { - delete p; } // TemplateListIntf @@ -8045,7 +6660,7 @@ TemplateVariant PageListContext::at(uint index) const return p->at(index); } -TemplateListIntf::ConstIterator *PageListContext::createIterator() const +TemplateListIntf::ConstIteratorPtr PageListContext::createIterator() const { return p->createIterator(); } @@ -8068,14 +6683,12 @@ class ExampleListContext::Private : public GenericNodeListContext } }; -ExampleListContext::ExampleListContext() : RefCountedContext("ExampleListContext") +ExampleListContext::ExampleListContext() : p(std::make_unique<Private>()) { - p = new Private; } ExampleListContext::~ExampleListContext() { - delete p; } // TemplateListIntf @@ -8089,7 +6702,7 @@ TemplateVariant ExampleListContext::at(uint index) const return p->at(index); } -TemplateListIntf::ConstIterator *ExampleListContext::createIterator() const +TemplateListIntf::ConstIteratorPtr ExampleListContext::createIterator() const { return p->createIterator(); } @@ -8112,15 +6725,13 @@ class ModuleListContext::Private : public GenericNodeListContext } }; -ModuleListContext::ModuleListContext() : RefCountedContext("ModuleListContext") +ModuleListContext::ModuleListContext() : p(std::make_unique<Private>()) { - p = new Private; p->addModules(); } ModuleListContext::~ModuleListContext() { - delete p; } // TemplateListIntf @@ -8134,117 +6745,77 @@ TemplateVariant ModuleListContext::at(uint index) const return p->at(index); } -TemplateListIntf::ConstIterator *ModuleListContext::createIterator() const +TemplateListIntf::ConstIteratorPtr ModuleListContext::createIterator() const { return p->createIterator(); } //------------------------------------------------------------------------ -//%% struct ConceptTree: tree of modules -//%% { class ConceptTreeContext::Private { public: Private() { - m_conceptTree.reset(NestingContext::alloc(0,ContextTreeType::Concept,0)); + m_conceptTree = NestingContext::alloc(0,ContextTreeType::Concept,0); + auto ctx = std::dynamic_pointer_cast<NestingContext>(m_conceptTree); ClassDefSet visitedClasses; // Add concepts - m_conceptTree->addNamespaces(*Doxygen::namespaceLinkedMap,TRUE,FALSE,TRUE,visitedClasses); - m_conceptTree->addConcepts(*Doxygen::conceptLinkedMap,TRUE,visitedClasses); - - //%% ConceptList tree: - static bool init=FALSE; - if (!init) - { - s_inst.addProperty("tree", &Private::tree); - s_inst.addProperty("fileName", &Private::fileName); - s_inst.addProperty("relPath", &Private::relPath); - s_inst.addProperty("highlight", &Private::highlight); - s_inst.addProperty("subhighlight", &Private::subhighlight); - s_inst.addProperty("title", &Private::title); - s_inst.addProperty("preferredDepth",&Private::preferredDepth); - s_inst.addProperty("maxDepth", &Private::maxDepth); - init=TRUE; - } - } - TemplateVariant get(const QCString &n) const - { - return s_inst.get(this,n); - } - StringVector fields() const - { - return s_inst.fields(); - } - TemplateVariant tree() const - { - return m_conceptTree.get(); - } - TemplateVariant fileName() const - { - return "concepts"; + ctx->addNamespaces(*Doxygen::namespaceLinkedMap,TRUE,FALSE,TRUE,visitedClasses); + ctx->addConcepts(*Doxygen::conceptLinkedMap,TRUE,visitedClasses); } - TemplateVariant relPath() const - { - return ""; - } - TemplateVariant highlight() const - { - return "concepts"; - } - TemplateVariant subhighlight() const - { - return ""; - } - TemplateVariant title() const + + // TemplateStructIntf methods + TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); } + StringVector fields() const { return s_inst.fields(); } + + private: + // Property getters + TemplateVariant tree() const { return TemplateVariant(m_conceptTree); } + TemplateVariant fileName() const { return "concepts"; } + TemplateVariant relPath() const { return ""; } + TemplateVariant highlight() const { return "concepts"; } + TemplateVariant subhighlight() const { return ""; } + TemplateVariant maxDepth() const { return m_maxDepth.get(this); } + TemplateVariant preferredDepth() const { return m_preferredDepth.get(this); } + TemplateVariant title() const { return theTranslator->trConcept(true,false); } + + private: + int createMaxDepth() const { - return theTranslator->trConcept(true,false); + return computeMaxDepth(m_conceptTree); } - TemplateVariant maxDepth() const + int createPreferredDepth() const { - if (!m_cache.maxDepthComputed) - { - m_cache.maxDepth = computeMaxDepth(m_conceptTree.get()); - m_cache.maxDepthComputed=TRUE; - } - return m_cache.maxDepth; + return computePreferredDepth(m_conceptTree,m_maxDepth.get(this)); } - TemplateVariant preferredDepth() const - { - if (!m_cache.preferredDepthComputed) - { - m_cache.preferredDepth = computePreferredDepth(m_conceptTree.get(),maxDepth().toInt()); - m_cache.preferredDepthComputed=TRUE; - } - return m_cache.preferredDepth; - } - private: - SharedPtr<NestingContext> m_conceptTree; - struct Cachable - { - Cachable() : maxDepth(0), maxDepthComputed(FALSE), - preferredDepth(0), preferredDepthComputed(FALSE) {} - int maxDepth; - bool maxDepthComputed; - int preferredDepth; - bool preferredDepthComputed; - }; - mutable Cachable m_cache; - static PropertyMapper<ConceptTreeContext::Private> s_inst; + TemplateListIntfPtr m_conceptTree; + CachedItem<int, Private, &Private::createMaxDepth> m_maxDepth; + CachedItem<int, Private, &Private::createPreferredDepth> m_preferredDepth; + static const PropertyMap<ConceptTreeContext::Private> s_inst; +}; + +//%% struct ConceptTree: tree of modules +//%% { +const PropertyMap<ConceptTreeContext::Private> ConceptTreeContext::Private::s_inst { + { "tree", &Private::tree }, + { "fileName", &Private::fileName }, + { "relPath", &Private::relPath }, + { "highlight", &Private::highlight }, + { "subhighlight", &Private::subhighlight }, + { "title", &Private::title }, + { "preferredDepth",&Private::preferredDepth }, + { "maxDepth", &Private::maxDepth } }; //%% } -PropertyMapper<ConceptTreeContext::Private> ConceptTreeContext::Private::s_inst; -ConceptTreeContext::ConceptTreeContext() : RefCountedContext("ConceptTreeContext") +ConceptTreeContext::ConceptTreeContext() : p(std::make_unique<Private>()) { - p = new Private; } ConceptTreeContext::~ConceptTreeContext() { - delete p; } TemplateVariant ConceptTreeContext::get(const QCString &name) const @@ -8259,109 +6830,69 @@ StringVector ConceptTreeContext::fields() const //------------------------------------------------------------------------ -//%% struct ModuleTree: tree of modules -//%% { class ModuleTreeContext::Private { public: Private() { - m_moduleTree.reset(NestingContext::alloc(0,ContextTreeType::Module,0)); + m_moduleTree = NestingContext::alloc(0,ContextTreeType::Module,0); + auto ctx = std::dynamic_pointer_cast<NestingContext>(m_moduleTree); ClassDefSet visitedClasses; // Add modules - m_moduleTree->addModules(*Doxygen::groupLinkedMap,visitedClasses); - - //%% ModuleList tree: - static bool init=FALSE; - if (!init) - { - s_inst.addProperty("tree", &Private::tree); - s_inst.addProperty("fileName", &Private::fileName); - s_inst.addProperty("relPath", &Private::relPath); - s_inst.addProperty("highlight", &Private::highlight); - s_inst.addProperty("subhighlight", &Private::subhighlight); - s_inst.addProperty("title", &Private::title); - s_inst.addProperty("preferredDepth",&Private::preferredDepth); - s_inst.addProperty("maxDepth", &Private::maxDepth); - init=TRUE; - } - } - TemplateVariant get(const QCString &n) const - { - return s_inst.get(this,n); - } - StringVector fields() const - { - return s_inst.fields(); - } - TemplateVariant tree() const - { - return m_moduleTree.get(); - } - TemplateVariant fileName() const - { - return "modules"; + ctx->addModules(*Doxygen::groupLinkedMap,visitedClasses); } - TemplateVariant relPath() const - { - return ""; - } - TemplateVariant highlight() const - { - return "modules"; - } - TemplateVariant subhighlight() const - { - return ""; - } - TemplateVariant title() const - { - return theTranslator->trModules(); - } - TemplateVariant maxDepth() const + + // TemplateStructIntf methods + TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); } + StringVector fields() const { return s_inst.fields(); } + + private: + // Property getters + TemplateVariant tree() const { return TemplateVariant(m_moduleTree); } + TemplateVariant fileName() const { return "modules"; } + TemplateVariant relPath() const { return ""; } + TemplateVariant highlight() const { return "modules"; } + TemplateVariant subhighlight() const { return ""; } + TemplateVariant maxDepth() const { return m_maxDepth.get(this); } + TemplateVariant preferredDepth() const { return m_preferredDepth.get(this); } + TemplateVariant title() const { return theTranslator->trModules(); } + private: + int createMaxDepth() const { - if (!m_cache.maxDepthComputed) - { - m_cache.maxDepth = computeMaxDepth(m_moduleTree.get()); - m_cache.maxDepthComputed=TRUE; - } - return m_cache.maxDepth; + return computeMaxDepth(m_moduleTree); } - TemplateVariant preferredDepth() const + int createPreferredDepth() const { - if (!m_cache.preferredDepthComputed) - { - m_cache.preferredDepth = computePreferredDepth(m_moduleTree.get(),maxDepth().toInt()); - m_cache.preferredDepthComputed=TRUE; - } - return m_cache.preferredDepth; + return computePreferredDepth(m_moduleTree,m_maxDepth.get(this)); } - private: - SharedPtr<NestingContext> m_moduleTree; - struct Cachable - { - Cachable() : maxDepth(0), maxDepthComputed(FALSE), - preferredDepth(0), preferredDepthComputed(FALSE) {} - int maxDepth; - bool maxDepthComputed; - int preferredDepth; - bool preferredDepthComputed; - }; - mutable Cachable m_cache; - static PropertyMapper<ModuleTreeContext::Private> s_inst; + TemplateListIntfPtr m_moduleTree; + CachedItem<int, Private, &Private::createMaxDepth> m_maxDepth; + CachedItem<int, Private, &Private::createPreferredDepth> m_preferredDepth; + static const PropertyMap<ModuleTreeContext::Private> s_inst; +}; + +//%% struct ModuleTree: tree of modules +//%% { +const PropertyMap<ModuleTreeContext::Private> ModuleTreeContext::Private::s_inst { + { "tree", &Private::tree }, + { "fileName", &Private::fileName }, + { "relPath", &Private::relPath }, + { "highlight", &Private::highlight }, + { "subhighlight", &Private::subhighlight }, + { "title", &Private::title }, + { "preferredDepth",&Private::preferredDepth }, + { "maxDepth", &Private::maxDepth } }; //%% } -PropertyMapper<ModuleTreeContext::Private> ModuleTreeContext::Private::s_inst; +//PropertyMapper<ModuleTreeContext::Private> ModuleTreeContext::Private::s_inst; -ModuleTreeContext::ModuleTreeContext() : RefCountedContext("ModuleTreeContext") +ModuleTreeContext::ModuleTreeContext() : p(std::make_unique<Private>()) { - p = new Private; } ModuleTreeContext::~ModuleTreeContext() { - delete p; } TemplateVariant ModuleTreeContext::get(const QCString &name) const @@ -8376,45 +6907,100 @@ StringVector ModuleTreeContext::fields() const //------------------------------------------------------------------------ -//%% struct NavPathElem: list of examples page -//%% { -class NavPathElemContext::Private +class ExampleTreeContext::Private { public: - Private(const Definition *def) : m_def(def) - { - static bool init=FALSE; - if (!init) - { - s_inst.addProperty("isLinkable", &Private::isLinkable); - s_inst.addProperty("fileName", &Private::fileName); - s_inst.addProperty("anchor", &Private::anchor); - s_inst.addProperty("text", &Private::text); - s_inst.addProperty("isReference", &Private::isReference); - s_inst.addProperty("externalReference",&Private::externalReference); - init=TRUE; - } - } - TemplateVariant get(const QCString &n) const - { - return s_inst.get(this,n); - } - StringVector fields() const - { - return s_inst.fields(); - } - TemplateVariant isLinkable() const + Private() { - return m_def->isLinkable(); + m_exampleTree = NestingContext::alloc(0,ContextTreeType::Example,0); + auto ctx = std::dynamic_pointer_cast<NestingContext>(m_exampleTree); + ClassDefSet visitedClasses; + // Add pages + ctx->addPages(*Doxygen::exampleLinkedMap,TRUE,visitedClasses); } - TemplateVariant anchor() const + + // TemplateStructIntf methods + TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); } + StringVector fields() const { return s_inst.fields(); } + + private: + // Property getters + TemplateVariant tree() const { return TemplateVariant(m_exampleTree); } + TemplateVariant fileName() const { return "examples"; } + TemplateVariant relPath() const { return ""; } + TemplateVariant highlight() const { return "examples"; } + TemplateVariant subhighlight() const { return ""; } + TemplateVariant maxDepth() const { return m_maxDepth.get(this); } + TemplateVariant preferredDepth() const { return m_preferredDepth.get(this); } + TemplateVariant title() const { return theTranslator->trExamples(); } + + private: + int createMaxDepth() const { - return m_def->anchor(); + return computeMaxDepth(m_exampleTree); } - TemplateVariant fileName() const + int createPreferredDepth() const { - return m_def->getOutputFileBase(); + return computePreferredDepth(m_exampleTree,m_maxDepth.get(this)); } + TemplateListIntfPtr m_exampleTree; + CachedItem<int, Private, &Private::createMaxDepth> m_maxDepth; + CachedItem<int, Private, &Private::createPreferredDepth> m_preferredDepth; + static const PropertyMap<ExampleTreeContext::Private> s_inst; +}; + +//%% struct ExampleTree: tree of examples page +//%% { +const PropertyMap<ExampleTreeContext::Private> ExampleTreeContext::Private::s_inst { + { "tree", &Private::tree }, + { "fileName", &Private::fileName }, + { "relPath", &Private::relPath }, + { "highlight", &Private::highlight }, + { "subhighlight", &Private::subhighlight }, + { "title", &Private::title }, + { "preferredDepth",&Private::preferredDepth }, + { "maxDepth", &Private::maxDepth } +}; +//%% } + + +ExampleTreeContext::ExampleTreeContext() : p(std::make_unique<Private>()) +{ +} + +ExampleTreeContext::~ExampleTreeContext() +{ +} + +TemplateVariant ExampleTreeContext::get(const QCString &name) const +{ + return p->get(name); +} + +StringVector ExampleTreeContext::fields() const +{ + return p->fields(); +} + + +//------------------------------------------------------------------------ + +class NavPathElemContext::Private +{ + public: + Private(const Definition *def) : m_def(def) {} + + // TemplateStructIntf methods + TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); } + StringVector fields() const { return s_inst.fields(); } + + private: + // Property getters + TemplateVariant isLinkable() const { return m_def->isLinkable(); } + TemplateVariant anchor() const { return m_def->anchor(); } + TemplateVariant fileName() const { return m_def->getOutputFileBase(); } + TemplateVariant isReference() const { return m_def->isReference(); } + TemplateVariant externalReference() const { return m_def->externalReference(relPathAsString()); } TemplateVariant text() const { Definition::DefType type = m_def->definitionType(); @@ -8436,35 +7022,35 @@ class NavPathElemContext::Private } return text; } - TemplateVariant isReference() const - { - return m_def->isReference(); - } QCString relPathAsString() const { static bool createSubdirs = Config_getBool(CREATE_SUBDIRS); return createSubdirs ? QCString("../../") : QCString(""); } - TemplateVariant externalReference() const - { - return m_def->externalReference(relPathAsString()); - } private: const Definition *m_def; - static PropertyMapper<NavPathElemContext::Private> s_inst; + static const PropertyMap<NavPathElemContext::Private> s_inst; +}; + +//%% struct NavPathElem: list of examples page +//%% { +const PropertyMap<NavPathElemContext::Private> NavPathElemContext::Private::s_inst { + { "isLinkable", &Private::isLinkable }, + { "fileName", &Private::fileName }, + { "anchor", &Private::anchor }, + { "text", &Private::text }, + { "isReference", &Private::isReference }, + { "externalReference",&Private::externalReference } }; //%% } -PropertyMapper<NavPathElemContext::Private> NavPathElemContext::Private::s_inst; -NavPathElemContext::NavPathElemContext(const Definition *def) : RefCountedContext("NavPathElemContext") +NavPathElemContext::NavPathElemContext(const Definition *def) : p(std::make_unique<Private>(def)) { - p = new Private(def); } NavPathElemContext::~NavPathElemContext() { - delete p; } TemplateVariant NavPathElemContext::get(const QCString &name) const @@ -8479,270 +7065,98 @@ StringVector NavPathElemContext::fields() const //------------------------------------------------------------------------ -//%% struct ExampleList: list of examples page -//%% { -class ExampleTreeContext::Private +class GlobalsIndexContext::Private { public: - Private() - { - m_exampleTree.reset(NestingContext::alloc(0,ContextTreeType::Example,0)); - ClassDefSet visitedClasses; - // Add pages - m_exampleTree->addPages(*Doxygen::exampleLinkedMap,TRUE,visitedClasses); + // TemplateStructIntf methods + TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); } + StringVector fields() const { return s_inst.fields(); } - static bool init=FALSE; - if (!init) - { - s_inst.addProperty("tree", &Private::tree); - s_inst.addProperty("fileName", &Private::fileName); - s_inst.addProperty("relPath", &Private::relPath); - s_inst.addProperty("highlight", &Private::highlight); - s_inst.addProperty("subhighlight", &Private::subhighlight); - s_inst.addProperty("title", &Private::title); - s_inst.addProperty("preferredDepth",&Private::preferredDepth); - s_inst.addProperty("maxDepth", &Private::maxDepth); - init=TRUE; - } - } - TemplateVariant get(const QCString &n) const - { - return s_inst.get(this,n); - } - StringVector fields() const - { - return s_inst.fields(); - } - TemplateVariant tree() const - { - return m_exampleTree.get(); - } - TemplateVariant fileName() const - { - return "examples"; - } - TemplateVariant relPath() const - { - return ""; - } - TemplateVariant highlight() const - { - return "examples"; - } - TemplateVariant subhighlight() const - { - return ""; - } - TemplateVariant title() const - { - return theTranslator->trExamples(); - } - TemplateVariant maxDepth() const - { - if (!m_cache.maxDepthComputed) - { - m_cache.maxDepth = computeMaxDepth(m_exampleTree.get()); - m_cache.maxDepthComputed=TRUE; - } - return m_cache.maxDepth; - } - TemplateVariant preferredDepth() const - { - if (!m_cache.preferredDepthComputed) - { - m_cache.preferredDepth = computePreferredDepth(m_exampleTree.get(),maxDepth().toInt()); - m_cache.preferredDepthComputed=TRUE; - } - return m_cache.preferredDepth; - } private: - SharedPtr<NestingContext> m_exampleTree; - struct Cachable - { - Cachable() : maxDepth(0), maxDepthComputed(FALSE), - preferredDepth(0), preferredDepthComputed(FALSE) {} - int maxDepth; - bool maxDepthComputed; - int preferredDepth; - bool preferredDepthComputed; - }; - mutable Cachable m_cache; - static PropertyMapper<ExampleTreeContext::Private> s_inst; -}; -//%% } - -PropertyMapper<ExampleTreeContext::Private> ExampleTreeContext::Private::s_inst; - -ExampleTreeContext::ExampleTreeContext() : RefCountedContext("ExampleTreeContext") -{ - p = new Private; -} - -ExampleTreeContext::~ExampleTreeContext() -{ - delete p; -} - -TemplateVariant ExampleTreeContext::get(const QCString &name) const -{ - return p->get(name); -} - -StringVector ExampleTreeContext::fields() const -{ - return p->fields(); -} + // Property getters + TemplateVariant all() const { return m_all.get(this); } + TemplateVariant functions() const { return m_functions.get(this); } + TemplateVariant variables() const { return m_variables.get(this); } + TemplateVariant typedefs() const { return m_typedefs.get(this); } + TemplateVariant enums() const { return m_enums.get(this); } + TemplateVariant enumValues() const { return m_enumValues.get(this); } + TemplateVariant macros() const { return m_macros.get(this); } + TemplateVariant properties() const { return FALSE; } + TemplateVariant events() const { return FALSE; } + TemplateVariant related() const { return FALSE; } + TemplateVariant fileName() const { return "globals"; } + TemplateVariant relPath() const { return ""; } + TemplateVariant highlight() const { return "files"; } + TemplateVariant subhighlight() const { return "filemembers"; } + TemplateVariant title() const { return theTranslator->trFileMembers(); } -//------------------------------------------------------------------------ - -//%% struct GlobalsIndex: list of examples page -//%% { -class GlobalsIndexContext::Private -{ - public: - Private() - { - static bool init=FALSE; - if (!init) - { - s_inst.addProperty("all", &Private::all); - s_inst.addProperty("functions", &Private::functions); - s_inst.addProperty("variables", &Private::variables); - s_inst.addProperty("typedefs", &Private::typedefs); - s_inst.addProperty("enums", &Private::enums); - s_inst.addProperty("enumValues", &Private::enumValues); - s_inst.addProperty("macros", &Private::macros); - s_inst.addProperty("properties", &Private::properties); - s_inst.addProperty("events", &Private::events); - s_inst.addProperty("related", &Private::related); - s_inst.addProperty("fileName", &Private::fileName); - s_inst.addProperty("relPath", &Private::relPath); - s_inst.addProperty("highlight", &Private::highlight); - s_inst.addProperty("subhighlight",&Private::subhighlight); - s_inst.addProperty("title", &Private::title); - init=TRUE; - } - } - TemplateVariant get(const QCString &n) const - { - return s_inst.get(this,n); - } - StringVector fields() const - { - return s_inst.fields(); - } - typedef bool (MemberDef::*MemberFunc)() const; - TemplateVariant getMembersFiltered(SharedPtr<TemplateList> &listRef,MemberFunc filter) const + private: + using MemberFilter = bool (MemberDef::*)() const; + TemplateVariant createMembersFiltered(MemberFilter filter) const { - if (!listRef) + TemplateVariantList list; + for (const auto &mn : *Doxygen::functionNameLinkedMap) { - TemplateList *list = TemplateList::alloc(); - for (const auto &mn : *Doxygen::functionNameLinkedMap) + for (const auto &md : *mn) { - for (const auto &md : *mn) + const FileDef *fd=md->getFileDef(); + if (fd && fd->isLinkableInProject() && + !md->name().isEmpty() && !md->getNamespaceDef() && md->isLinkableInProject()) { - const FileDef *fd=md->getFileDef(); - if (fd && fd->isLinkableInProject() && - !md->name().isEmpty() && !md->getNamespaceDef() && md->isLinkableInProject()) + if (filter==0 || (md.get()->*filter)()) { - if (filter==0 || (md.get()->*filter)()) - { - list->append(MemberContext::alloc(md.get())); - } + list.push_back(MemberContext::alloc(md.get())); } } } - listRef.reset(list); } - return listRef.get(); - } - TemplateVariant all() const - { - return getMembersFiltered(m_cache.all,0); - } - TemplateVariant functions() const - { - return getMembersFiltered(m_cache.functions,&MemberDef::isFunction); - } - TemplateVariant variables() const - { - return getMembersFiltered(m_cache.variables,&MemberDef::isVariable); - } - TemplateVariant typedefs() const - { - return getMembersFiltered(m_cache.typedefs,&MemberDef::isTypedef); - } - TemplateVariant enums() const - { - return getMembersFiltered(m_cache.enums,&MemberDef::isEnumerate); - } - TemplateVariant enumValues() const - { - return getMembersFiltered(m_cache.enumValues,&MemberDef::isEnumValue); - } - TemplateVariant macros() const - { - return getMembersFiltered(m_cache.macros,&MemberDef::isDefine); - } - TemplateVariant properties() const - { - return FALSE; - } - TemplateVariant events() const - { - return FALSE; - } - TemplateVariant related() const - { - return FALSE; - } - TemplateVariant fileName() const - { - return "globals"; - } - TemplateVariant relPath() const - { - return ""; - } - TemplateVariant highlight() const - { - return "files"; - } - TemplateVariant subhighlight() const - { - return "filemembers"; - } - TemplateVariant title() const - { - return theTranslator->trFileMembers(); - } - private: - struct Cachable - { - Cachable() {} - SharedPtr<TemplateList> all; - SharedPtr<TemplateList> functions; - SharedPtr<TemplateList> variables; - SharedPtr<TemplateList> typedefs; - SharedPtr<TemplateList> enums; - SharedPtr<TemplateList> enumValues; - SharedPtr<TemplateList> macros; - }; - mutable Cachable m_cache; - static PropertyMapper<GlobalsIndexContext::Private> s_inst; + return TemplateImmutableList::alloc(list); + } + TemplateVariant createAll() const { return createMembersFiltered(0); } + TemplateVariant createFunctions() const { return createMembersFiltered(&MemberDef::isFunction); } + TemplateVariant createVariables() const { return createMembersFiltered(&MemberDef::isVariable); } + TemplateVariant createTypedefs() const { return createMembersFiltered(&MemberDef::isTypedef); } + TemplateVariant createEnums() const { return createMembersFiltered(&MemberDef::isEnumerate); } + TemplateVariant createEnumValues() const { return createMembersFiltered(&MemberDef::isEnumValue); } + TemplateVariant createMacros() const { return createMembersFiltered(&MemberDef::isDefine); } + + CachedItem<TemplateVariant, Private, &Private::createAll> m_all; + CachedItem<TemplateVariant, Private, &Private::createFunctions> m_functions; + CachedItem<TemplateVariant, Private, &Private::createVariables> m_variables; + CachedItem<TemplateVariant, Private, &Private::createTypedefs> m_typedefs; + CachedItem<TemplateVariant, Private, &Private::createEnums> m_enums; + CachedItem<TemplateVariant, Private, &Private::createEnumValues> m_enumValues; + CachedItem<TemplateVariant, Private, &Private::createMacros> m_macros; + static const PropertyMap<GlobalsIndexContext::Private> s_inst; }; -//%% } -PropertyMapper<GlobalsIndexContext::Private> GlobalsIndexContext::Private::s_inst; +//%% struct GlobalsIndex: list of examples page +//%% { +const PropertyMap<GlobalsIndexContext::Private> GlobalsIndexContext::Private::s_inst { + { "all", &Private::all }, + { "functions", &Private::functions }, + { "variables", &Private::variables }, + { "typedefs", &Private::typedefs }, + { "enums", &Private::enums }, + { "enumValues", &Private::enumValues }, + { "macros", &Private::macros }, + { "properties", &Private::properties }, + { "events", &Private::events }, + { "related", &Private::related }, + { "fileName", &Private::fileName }, + { "relPath", &Private::relPath }, + { "highlight", &Private::highlight }, + { "subhighlight",&Private::subhighlight }, + { "title", &Private::title } +}; +//%% } -GlobalsIndexContext::GlobalsIndexContext() : RefCountedContext("GlobalsIndexContext") +GlobalsIndexContext::GlobalsIndexContext() : p(std::make_unique<Private>()) { - p = new Private; } GlobalsIndexContext::~GlobalsIndexContext() { - delete p; } TemplateVariant GlobalsIndexContext::get(const QCString &name) const @@ -8758,156 +7172,103 @@ StringVector GlobalsIndexContext::fields() const //------------------------------------------------------------------------ -//%% struct ClassMembersIndex: list of examples page -//%% { class ClassMembersIndexContext::Private { public: - Private() - { - static bool init=FALSE; - if (!init) - { - s_inst.addProperty("all", &Private::all); - s_inst.addProperty("functions", &Private::functions); - s_inst.addProperty("variables", &Private::variables); - s_inst.addProperty("typedefs", &Private::typedefs); - s_inst.addProperty("enums", &Private::enums); - s_inst.addProperty("enumValues", &Private::enumValues); - s_inst.addProperty("macros", &Private::macros); - s_inst.addProperty("properties", &Private::properties); - s_inst.addProperty("events", &Private::events); - s_inst.addProperty("related", &Private::related); - s_inst.addProperty("fileName", &Private::fileName); - s_inst.addProperty("relPath", &Private::relPath); - s_inst.addProperty("highlight", &Private::highlight); - s_inst.addProperty("subhighlight",&Private::subhighlight); - s_inst.addProperty("title", &Private::title); - init=TRUE; - } - } - TemplateVariant get(const QCString &n) const - { - return s_inst.get(this,n); - } - StringVector fields() const - { - return s_inst.fields(); - } - typedef bool (MemberDef::*MemberFunc)() const; - TemplateVariant getMembersFiltered(SharedPtr<TemplateList> &listRef,MemberFunc filter) const + // TemplateStructIntf methods + TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); } + StringVector fields() const { return s_inst.fields(); } + + private: + // Property getters + TemplateVariant all() const { return m_all.get(this); } + TemplateVariant functions() const { return m_functions.get(this); } + TemplateVariant variables() const { return m_variables.get(this); } + TemplateVariant typedefs() const { return m_typedefs.get(this); } + TemplateVariant enums() const { return m_enums.get(this); } + TemplateVariant enumValues() const { return m_enumValues.get(this); } + TemplateVariant macros() const { return FALSE; } + TemplateVariant properties() const { return m_properties.get(this); } + TemplateVariant events() const { return m_events.get(this); } + TemplateVariant related() const { return m_related.get(this); } + TemplateVariant fileName() const { return "functions"; } + TemplateVariant relPath() const { return ""; } + TemplateVariant highlight() const { return "classes"; } + TemplateVariant subhighlight() const { return "classmembers"; } + TemplateVariant title() const { return theTranslator->trCompoundMembers(); } + + private: + using MemberFilter = bool (MemberDef::*)() const; + TemplateVariant createMembersFiltered(MemberFilter filter) const { - if (!listRef) + TemplateVariantList list; + for (const auto &mn : *Doxygen::memberNameLinkedMap) { - TemplateList *list = TemplateList::alloc(); - for (const auto &mn : *Doxygen::memberNameLinkedMap) + for (const auto &md : *mn) { - for (const auto &md : *mn) + const ClassDef *cd = md->getClassDef(); + if (cd && cd->isLinkableInProject() && cd->templateMaster()==0 && + md->isLinkableInProject() && !md->name().isEmpty()) { - const ClassDef *cd = md->getClassDef(); - if (cd && cd->isLinkableInProject() && cd->templateMaster()==0 && - md->isLinkableInProject() && !md->name().isEmpty()) + if (filter==0 || (md.get()->*filter)()) { - if (filter==0 || (md.get()->*filter)()) - { - list->append(MemberContext::alloc(md.get())); - } + list.push_back(MemberContext::alloc(md.get())); } } } - listRef.reset(list); } - return listRef.get(); - } - TemplateVariant all() const - { - return getMembersFiltered(m_cache.all,&MemberDef::isNotFriend); - } - TemplateVariant functions() const - { - return getMembersFiltered(m_cache.functions,&MemberDef::isFunctionOrSignalSlot); - } - TemplateVariant variables() const - { - return getMembersFiltered(m_cache.variables,&MemberDef::isVariable); - } - TemplateVariant typedefs() const - { - return getMembersFiltered(m_cache.typedefs,&MemberDef::isTypedef); - } - TemplateVariant enums() const - { - return getMembersFiltered(m_cache.enums,&MemberDef::isEnumerate); - } - TemplateVariant enumValues() const - { - return getMembersFiltered(m_cache.enumValues,&MemberDef::isEnumValue); - } - TemplateVariant macros() const - { - return FALSE; - } - TemplateVariant properties() const - { - return getMembersFiltered(m_cache.properties,&MemberDef::isProperty); - } - TemplateVariant events() const - { - return getMembersFiltered(m_cache.events,&MemberDef::isEvent); - } - TemplateVariant related() const - { - return getMembersFiltered(m_cache.related,&MemberDef::isRelated); - } - TemplateVariant fileName() const - { - return "functions"; - } - TemplateVariant relPath() const - { - return ""; - } - TemplateVariant highlight() const - { - return "classes"; - } - TemplateVariant subhighlight() const - { - return "classmembers"; - } - TemplateVariant title() const - { - return theTranslator->trCompoundMembers(); - } - private: - struct Cachable - { - Cachable() {} - SharedPtr<TemplateList> all; - SharedPtr<TemplateList> functions; - SharedPtr<TemplateList> variables; - SharedPtr<TemplateList> typedefs; - SharedPtr<TemplateList> enums; - SharedPtr<TemplateList> enumValues; - SharedPtr<TemplateList> properties; - SharedPtr<TemplateList> events; - SharedPtr<TemplateList> related; - }; - mutable Cachable m_cache; - static PropertyMapper<ClassMembersIndexContext::Private> s_inst; + return TemplateImmutableList::alloc(list); + } + TemplateVariant createAll() const { return createMembersFiltered(&MemberDef::isNotFriend); } + TemplateVariant createFunctions() const { return createMembersFiltered(&MemberDef::isFunctionOrSignalSlot); } + TemplateVariant createVariables() const { return createMembersFiltered(&MemberDef::isVariable); } + TemplateVariant createTypedefs() const { return createMembersFiltered(&MemberDef::isTypedef); } + TemplateVariant createEnums() const { return createMembersFiltered(&MemberDef::isEnumerate); } + TemplateVariant createEnumValues() const { return createMembersFiltered(&MemberDef::isEnumValue); } + TemplateVariant createProperties() const { return createMembersFiltered(&MemberDef::isProperty); } + TemplateVariant createEvents() const { return createMembersFiltered(&MemberDef::isEvent); } + TemplateVariant createRelated() const { return createMembersFiltered(&MemberDef::isRelated); } + + CachedItem<TemplateVariant, Private, &Private::createAll> m_all; + CachedItem<TemplateVariant, Private, &Private::createFunctions> m_functions; + CachedItem<TemplateVariant, Private, &Private::createVariables> m_variables; + CachedItem<TemplateVariant, Private, &Private::createTypedefs> m_typedefs; + CachedItem<TemplateVariant, Private, &Private::createEnums> m_enums; + CachedItem<TemplateVariant, Private, &Private::createEnumValues> m_enumValues; + CachedItem<TemplateVariant, Private, &Private::createProperties> m_properties; + CachedItem<TemplateVariant, Private, &Private::createEvents> m_events; + CachedItem<TemplateVariant, Private, &Private::createRelated> m_related; + static const PropertyMap<ClassMembersIndexContext::Private> s_inst; +}; + +//%% struct ClassMembersIndex: list of examples page +//%% { +const PropertyMap<ClassMembersIndexContext::Private> ClassMembersIndexContext::Private::s_inst { + { "all", &Private::all }, + { "functions", &Private::functions }, + { "variables", &Private::variables }, + { "typedefs", &Private::typedefs }, + { "enums", &Private::enums }, + { "enumValues", &Private::enumValues }, + { "macros", &Private::macros }, + { "properties", &Private::properties }, + { "events", &Private::events }, + { "related", &Private::related }, + { "fileName", &Private::fileName }, + { "relPath", &Private::relPath }, + { "highlight", &Private::highlight }, + { "subhighlight",&Private::subhighlight }, + { "title", &Private::title } }; //%% } -PropertyMapper<ClassMembersIndexContext::Private> ClassMembersIndexContext::Private::s_inst; -ClassMembersIndexContext::ClassMembersIndexContext() : RefCountedContext("ClassMembersIndexContext") +ClassMembersIndexContext::ClassMembersIndexContext() : p(std::make_unique<Private>()) { - p = new Private; } ClassMembersIndexContext::~ClassMembersIndexContext() { - delete p; } TemplateVariant ClassMembersIndexContext::get(const QCString &name) const @@ -8922,153 +7283,98 @@ StringVector ClassMembersIndexContext::fields() const //------------------------------------------------------------------------ -//%% struct NamespaceMembersIndex: list of examples page -//%% { class NamespaceMembersIndexContext::Private { public: - Private() - { - static bool init=FALSE; - if (!init) - { - s_inst.addProperty("all", &Private::all); - s_inst.addProperty("functions", &Private::functions); - s_inst.addProperty("variables", &Private::variables); - s_inst.addProperty("typedefs", &Private::typedefs); - s_inst.addProperty("enums", &Private::enums); - s_inst.addProperty("enumValues", &Private::enumValues); - s_inst.addProperty("macros", &Private::macros); - s_inst.addProperty("properties", &Private::properties); - s_inst.addProperty("events", &Private::events); - s_inst.addProperty("related", &Private::related); - s_inst.addProperty("fileName", &Private::fileName); - s_inst.addProperty("relPath", &Private::relPath); - s_inst.addProperty("highlight", &Private::highlight); - s_inst.addProperty("subhighlight",&Private::subhighlight); - s_inst.addProperty("title", &Private::title); - init=TRUE; - } - } - TemplateVariant get(const QCString &n) const - { - return s_inst.get(this,n); - } - StringVector fields() const - { - return s_inst.fields(); - } - typedef bool (MemberDef::*MemberFunc)() const; - TemplateVariant getMembersFiltered(SharedPtr<TemplateList> &listRef,MemberFunc filter) const + // TemplateStructIntf methods + TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); } + StringVector fields() const { return s_inst.fields(); } + + private: + // Property getters + TemplateVariant all() const { return m_all.get(this); } + TemplateVariant functions() const { return m_functions.get(this); } + TemplateVariant variables() const { return m_variables.get(this); } + TemplateVariant typedefs() const { return m_typedefs.get(this); } + TemplateVariant enums() const { return m_enums.get(this); } + TemplateVariant enumValues() const { return m_enumValues.get(this); } + TemplateVariant macros() const { return FALSE; } + TemplateVariant properties() const { return FALSE; } + TemplateVariant events() const { return FALSE; } + TemplateVariant related() const { return FALSE; } + TemplateVariant fileName() const { return "namespacemembers"; } + TemplateVariant relPath() const { return ""; } + TemplateVariant highlight() const { return "namespaces"; } + TemplateVariant subhighlight() const { return "namespacemembers"; } + TemplateVariant title() const { return theTranslator->trNamespaceMembers(); } + + private: + using MemberFilter = bool (MemberDef::*)() const; + TemplateVariant createMembersFiltered(MemberFilter filter) const { - if (!listRef) + TemplateVariantList list; + for (const auto &mn : *Doxygen::functionNameLinkedMap) { - TemplateList *list = TemplateList::alloc(); - for (const auto &mn : *Doxygen::functionNameLinkedMap) + for (const auto &md : *mn) { - for (const auto &md : *mn) + const NamespaceDef *nd=md->getNamespaceDef(); + if (nd && nd->isLinkableInProject() && + !md->name().isEmpty() && md->isLinkableInProject()) { - const NamespaceDef *nd=md->getNamespaceDef(); - if (nd && nd->isLinkableInProject() && - !md->name().isEmpty() && md->isLinkableInProject()) + if (filter==0 || (md.get()->*filter)()) { - if (filter==0 || (md.get()->*filter)()) - { - list->append(MemberContext::alloc(md.get())); - } + list.push_back(MemberContext::alloc(md.get())); } } } - listRef.reset(list); } - return listRef.get(); - } - TemplateVariant all() const - { - return getMembersFiltered(m_cache.all,0); + return TemplateImmutableList::alloc(list); } - TemplateVariant functions() const - { - return getMembersFiltered(m_cache.functions,&MemberDef::isFunction); - } - TemplateVariant variables() const - { - return getMembersFiltered(m_cache.variables,&MemberDef::isVariable); - } - TemplateVariant typedefs() const - { - return getMembersFiltered(m_cache.typedefs,&MemberDef::isTypedef); - } - TemplateVariant enums() const - { - return getMembersFiltered(m_cache.enums,&MemberDef::isEnumerate); - } - TemplateVariant enumValues() const - { - return getMembersFiltered(m_cache.enumValues,&MemberDef::isEnumValue); - } - TemplateVariant macros() const - { - return FALSE; - } - TemplateVariant properties() const - { - return FALSE; - } - TemplateVariant events() const - { - return FALSE; - } - TemplateVariant related() const - { - return FALSE; - } - TemplateVariant fileName() const - { - return "namespacemembers"; - } - TemplateVariant relPath() const - { - return ""; - } - TemplateVariant highlight() const - { - return "namespaces"; - } - TemplateVariant subhighlight() const - { - return "namespacemembers"; - } - TemplateVariant title() const - { - return theTranslator->trNamespaceMembers(); - } - private: - struct Cachable - { - Cachable() {} - SharedPtr<TemplateList> all; - SharedPtr<TemplateList> functions; - SharedPtr<TemplateList> variables; - SharedPtr<TemplateList> typedefs; - SharedPtr<TemplateList> enums; - SharedPtr<TemplateList> enumValues; - }; - mutable Cachable m_cache; - static PropertyMapper<NamespaceMembersIndexContext::Private> s_inst; + + TemplateVariant createAll() const { return createMembersFiltered(0); } + TemplateVariant createFunctions() const { return createMembersFiltered(&MemberDef::isFunction); } + TemplateVariant createVariables() const { return createMembersFiltered(&MemberDef::isVariable); } + TemplateVariant createTypedefs() const { return createMembersFiltered(&MemberDef::isTypedef); } + TemplateVariant createEnums() const { return createMembersFiltered(&MemberDef::isEnumerate); } + TemplateVariant createEnumValues() const { return createMembersFiltered(&MemberDef::isEnumValue); } + + CachedItem<TemplateVariant, Private, &Private::createAll> m_all; + CachedItem<TemplateVariant, Private, &Private::createFunctions> m_functions; + CachedItem<TemplateVariant, Private, &Private::createVariables> m_variables; + CachedItem<TemplateVariant, Private, &Private::createTypedefs> m_typedefs; + CachedItem<TemplateVariant, Private, &Private::createEnums> m_enums; + CachedItem<TemplateVariant, Private, &Private::createEnumValues> m_enumValues; + static const PropertyMap<NamespaceMembersIndexContext::Private> s_inst; +}; + +//%% struct NamespaceMembersIndex: list of examples page +//%% { +const PropertyMap<NamespaceMembersIndexContext::Private> NamespaceMembersIndexContext::Private::s_inst { + { "all", &Private::all }, + { "functions", &Private::functions }, + { "variables", &Private::variables }, + { "typedefs", &Private::typedefs }, + { "enums", &Private::enums }, + { "enumValues", &Private::enumValues }, + { "macros", &Private::macros }, + { "properties", &Private::properties }, + { "events", &Private::events }, + { "related", &Private::related }, + { "fileName", &Private::fileName }, + { "relPath", &Private::relPath }, + { "highlight", &Private::highlight }, + { "subhighlight",&Private::subhighlight }, + { "title", &Private::title } }; //%% } -PropertyMapper<NamespaceMembersIndexContext::Private> NamespaceMembersIndexContext::Private::s_inst; -NamespaceMembersIndexContext::NamespaceMembersIndexContext() : RefCountedContext("NamespaceMembersIndexContext") +NamespaceMembersIndexContext::NamespaceMembersIndexContext() : p(std::make_unique<Private>()) { - p = new Private; } NamespaceMembersIndexContext::~NamespaceMembersIndexContext() { - delete p; } TemplateVariant NamespaceMembersIndexContext::get(const QCString &name) const @@ -9083,29 +7389,22 @@ StringVector NamespaceMembersIndexContext::fields() const //------------------------------------------------------------------------ -//%% struct InheritanceGraph: a connected graph representing part of the overall inheritance tree -//%% { class InheritanceGraphContext::Private { public: - Private(DotGfxHierarchyTable *hierarchy,DotNode *n,int id) : m_hierarchy(hierarchy), m_node(n), m_id(id) - { - static bool init=FALSE; - if (!init) - { - s_inst.addProperty("graph",&Private::graph); - init=TRUE; - } - } - TemplateVariant get(const QCString &n) const - { - return s_inst.get(this,n); - } - StringVector fields() const - { - return s_inst.fields(); - } - TemplateVariant graph() const + Private(DotGfxHierarchyTablePtr hierarchy,DotNode *n,int id) + : m_hierarchy(hierarchy), m_node(n), m_id(id) { } + + // TemplateStructIntf methods + TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); } + StringVector fields() const { return s_inst.fields(); } + + private: + // Property getters + TemplateVariant graph() const { return m_graph.get(this); } + + private: + TemplateVariant createGraph() const { TextStream t; static bool haveDot = Config_getBool(HAVE_DOT); @@ -9121,24 +7420,26 @@ class InheritanceGraphContext::Private } return TemplateVariant(t.str().c_str(),TRUE); } - private: - DotGfxHierarchyTable *m_hierarchy; + DotGfxHierarchyTablePtr m_hierarchy; DotNode *m_node; + CachedItem<TemplateVariant,Private,&Private::createGraph> m_graph; int m_id; - static PropertyMapper<InheritanceGraphContext::Private> s_inst; + static const PropertyMap<InheritanceGraphContext::Private> s_inst; }; -PropertyMapper<InheritanceGraphContext::Private> InheritanceGraphContext::Private::s_inst; +//%% struct InheritanceGraph: a connected graph representing part of the overall inheritance tree +//%% { +const PropertyMap<InheritanceGraphContext::Private> InheritanceGraphContext::Private::s_inst { + { "graph",&Private::graph } +}; +//%% } -InheritanceGraphContext::InheritanceGraphContext(DotGfxHierarchyTable *hierarchy,DotNode *n,int id) - : RefCountedContext("InheritanceGraphContext") +InheritanceGraphContext::InheritanceGraphContext(DotGfxHierarchyTablePtr hierarchy,DotNode *n,int id) : p(std::make_unique<Private>(hierarchy,n,id)) { - p = new Private(hierarchy,n,id); } InheritanceGraphContext::~InheritanceGraphContext() { - delete p; } TemplateVariant InheritanceGraphContext::get(const QCString &name) const @@ -9153,59 +7454,46 @@ StringVector InheritanceGraphContext::fields() const //------------------------------------------------------------------------ -//%% struct InheritanceNode: a class in the inheritance list -//%% { class InheritanceNodeContext::Private { public: - Private(const ClassDef *cd,const QCString &name) : m_classDef(cd), m_name(name) - { - static bool init=FALSE; - if (!init) - { - s_inst.addProperty("class",&Private::getClass); - s_inst.addProperty("name", &Private::name); - init=TRUE; - } - } - TemplateVariant get(const QCString &n) const - { - return s_inst.get(this,n); - } - StringVector fields() const - { - return s_inst.fields(); - } - TemplateVariant getClass() const - { - if (!m_classContext) - { - m_classContext.reset(ClassContext::alloc(m_classDef)); - } - return m_classContext.get(); - } - TemplateVariant name() const + Private(const ClassDef *cd,const QCString &name) + : m_classDef(cd), m_name(name) {} + + // TemplateStructIntf methods + TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); } + StringVector fields() const { return s_inst.fields(); } + + private: + // Property getters + TemplateVariant getClass() const { return m_classContext.get(this); } + TemplateVariant name() const { return m_name; } + + private: + TemplateVariant createClass() const { - return m_name; + return ClassContext::alloc(m_classDef); } - private: const ClassDef *m_classDef; - mutable SharedPtr<ClassContext> m_classContext; + CachedItem<TemplateVariant, Private, &Private::createClass> m_classContext; QCString m_name; - static PropertyMapper<InheritanceNodeContext::Private> s_inst; + static const PropertyMap<InheritanceNodeContext::Private> s_inst; }; -//%% } -PropertyMapper<InheritanceNodeContext::Private> InheritanceNodeContext::Private::s_inst; +//%% struct InheritanceNode: a class in the inheritance list +//%% { +const PropertyMap<InheritanceNodeContext::Private> InheritanceNodeContext::Private::s_inst { + { "class",&Private::getClass }, + { "name", &Private::name } +}; +//%% } -InheritanceNodeContext::InheritanceNodeContext(const ClassDef *cd,const QCString &name) : RefCountedContext("InheritanceNodeContext") +InheritanceNodeContext::InheritanceNodeContext(const ClassDef *cd,const QCString &name) : p(std::make_unique<Private>(cd,name)) { - p = new Private(cd,name); } InheritanceNodeContext::~InheritanceNodeContext() { - delete p; } TemplateVariant InheritanceNodeContext::get(const QCString &name) const @@ -9230,9 +7518,8 @@ class InheritanceListContext::Private : public GenericNodeListContext } }; -InheritanceListContext::InheritanceListContext(const BaseClassList &list, bool baseClasses) : RefCountedContext("InheritanceListContext") +InheritanceListContext::InheritanceListContext(const BaseClassList &list, bool baseClasses) : p(std::make_unique<Private>()) { - p = new Private; for (const auto &bcd : list) { const ClassDef *cd=bcd.classDef; @@ -9253,7 +7540,6 @@ InheritanceListContext::InheritanceListContext(const BaseClassList &list, bool b InheritanceListContext::~InheritanceListContext() { - delete p; } // TemplateListIntf @@ -9267,7 +7553,7 @@ TemplateVariant InheritanceListContext::at(uint index) const return p->at(index); } -TemplateListIntf::ConstIterator *InheritanceListContext::createIterator() const +TemplateListIntf::ConstIteratorPtr InheritanceListContext::createIterator() const { return p->createIterator(); } @@ -9284,14 +7570,12 @@ class MemberListContext::Private : public GenericNodeListContext } }; -MemberListContext::MemberListContext() : RefCountedContext("MemberListContext") +MemberListContext::MemberListContext() : p(std::make_unique<Private>()) { - p = new Private; } -MemberListContext::MemberListContext(const MemberList *list) : RefCountedContext("MemberListContext") +MemberListContext::MemberListContext(const MemberList *list) : p(std::make_unique<Private>()) { - p = new Private; if (list) { bool details = list->listType()&MemberListType_detailedLists; @@ -9307,9 +7591,8 @@ MemberListContext::MemberListContext(const MemberList *list) : RefCountedContext } } -MemberListContext::MemberListContext(const MemberVector &ml) : RefCountedContext("MemberListContext") +MemberListContext::MemberListContext(const MemberVector &ml) : p(std::make_unique<Private>()) { - p = new Private; for (const auto &md : ml) { p->addMember(md); @@ -9318,7 +7601,6 @@ MemberListContext::MemberListContext(const MemberVector &ml) : RefCountedContext MemberListContext::~MemberListContext() { - delete p; } // TemplateListIntf @@ -9332,42 +7614,24 @@ TemplateVariant MemberListContext::at(uint index) const return p->at(index); } -TemplateListIntf::ConstIterator *MemberListContext::createIterator() const +TemplateListIntf::ConstIteratorPtr MemberListContext::createIterator() const { return p->createIterator(); } //------------------------------------------------------------------------ -//%% struct MemberInfo: member information -//%% { class MemberInfoContext::Private { public: - Private(const MemberInfo *mi) : m_memberInfo(mi) - { - static bool init=FALSE; - if (!init) - { - //%% string protection - s_inst.addProperty("protection", &Private::protection); - //%% string virtualness - s_inst.addProperty("virtualness", &Private::virtualness); - //%% string ambiguityScope - s_inst.addProperty("ambiguityScope",&Private::ambiguityScope); - //%% Member member - s_inst.addProperty("member", &Private::member); - init=TRUE; - } - } - TemplateVariant get(const QCString &n) const - { - return s_inst.get(this,n); - } - StringVector fields() const - { - return s_inst.fields(); - } + Private(const MemberInfo *mi) : m_memberInfo(mi) {} + + // TemplateStructIntf methods + TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); } + StringVector fields() const { return s_inst.fields(); } + + private: + // Property getters TemplateVariant protection() const { switch (m_memberInfo->prot()) @@ -9395,36 +7659,41 @@ class MemberInfoContext::Private } TemplateVariant member() const { - if (!m_member && m_memberInfo->memberDef()) - { - m_member.reset(MemberContext::alloc(m_memberInfo->memberDef())); - } - if (m_member) - { - return m_member.get(); - } - else - { - return TemplateVariant(FALSE); - } + return m_member.get(this); } + private: + TemplateVariant createMember() const + { + return m_memberInfo->memberDef() ? + TemplateVariant(MemberContext::alloc(m_memberInfo->memberDef())) : + TemplateVariant(false); + } const MemberInfo *m_memberInfo; - mutable SharedPtr<MemberContext> m_member; - static PropertyMapper<MemberInfoContext::Private> s_inst; + CachedItem<TemplateVariant, Private, &Private::createMember> m_member; + static const PropertyMap<MemberInfoContext::Private> s_inst; }; -//%% } -PropertyMapper<MemberInfoContext::Private> MemberInfoContext::Private::s_inst; +//%% struct MemberInfo: member information +//%% { +const PropertyMap<MemberInfoContext::Private> MemberInfoContext::Private::s_inst { + //%% string protection + { "protection", &Private::protection }, + //%% string virtualness + { "virtualness", &Private::virtualness }, + //%% string ambiguityScope + { "ambiguityScope",&Private::ambiguityScope }, + //%% Member member + { "member", &Private::member } +}; +//%% } -MemberInfoContext::MemberInfoContext(const MemberInfo *mi) : RefCountedContext("MemberInfoContext") +MemberInfoContext::MemberInfoContext(const MemberInfo *mi) : p(std::make_unique<Private>(mi)) { - p = new Private(mi); } MemberInfoContext::~MemberInfoContext() { - delete p; } TemplateVariant MemberInfoContext::get(const QCString &name) const @@ -9468,15 +7737,12 @@ class AllMembersListContext::Private : public GenericNodeListContext } }; -AllMembersListContext::AllMembersListContext(const MemberNameInfoLinkedMap &ml) - : RefCountedContext("AllMembersListContext") +AllMembersListContext::AllMembersListContext(const MemberNameInfoLinkedMap &ml) : p(std::make_unique<Private>(ml)) { - p = new Private(ml); } AllMembersListContext::~AllMembersListContext() { - delete p; } // TemplateListIntf @@ -9490,121 +7756,79 @@ TemplateVariant AllMembersListContext::at(uint index) const return p->at(index); } -TemplateListIntf::ConstIterator *AllMembersListContext::createIterator() const +TemplateListIntf::ConstIteratorPtr AllMembersListContext::createIterator() const { return p->createIterator(); } //------------------------------------------------------------------------ -//%% struct MemberGroupInfo: member group information -//%% { class MemberGroupInfoContext::Private { public: - Private(const Definition *def,const QCString &relPath,const MemberGroup *mg) : - m_def(def), - m_relPath(relPath), - m_memberGroup(mg) - { - static bool init=FALSE; - if (!init) - { - s_inst.addProperty("members", &Private::members); - s_inst.addProperty("title", &Private::groupTitle); - s_inst.addProperty("subtitle", &Private::groupSubtitle); - s_inst.addProperty("anchor", &Private::groupAnchor); - s_inst.addProperty("memberGroups", &Private::memberGroups); - s_inst.addProperty("docs", &Private::docs); - s_inst.addProperty("inherited", &Private::inherited); - init=TRUE; - } - } - TemplateVariant get(const QCString &n) const - { - return s_inst.get(this,n); - } - StringVector fields() const - { - return s_inst.fields(); - } - TemplateVariant members() const - { - if (!m_cache.memberListContext) - { - m_cache.memberListContext.reset(MemberListContext::alloc(&m_memberGroup->members())); - } - return m_cache.memberListContext.get(); - } - TemplateVariant groupTitle() const - { - return m_memberGroup->header(); - } - TemplateVariant groupSubtitle() const - { - return ""; - } - TemplateVariant groupAnchor() const - { - return m_memberGroup->anchor(); - } - TemplateVariant memberGroups() const + Private(const Definition *def,const QCString &relPath,const MemberGroup *mg) + : m_def(def), m_relPath(relPath), m_memberGroup(mg) {} + + // TemplateStructIntf methods + TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); } + StringVector fields() const { return s_inst.fields(); } + + private: + // Property getters + TemplateVariant members() const { return m_members.get(this); } + TemplateVariant groupTitle() const { return m_memberGroup->header(); } + TemplateVariant groupSubtitle() const { return ""; } + TemplateVariant groupAnchor() const { return m_memberGroup->anchor(); } + TemplateVariant memberGroups() const { return m_memberGroups.get(this); } + TemplateVariant docs() const { return m_docs.get(this); } + TemplateVariant inherited() const { return FALSE; } + + private: + TemplateVariant createMembers() const { - if (!m_cache.memberGroups) - { - m_cache.memberGroups.reset(MemberGroupListContext::alloc()); - } - return m_cache.memberGroups.get(); + return MemberListContext::alloc(&m_memberGroup->members()); } - TemplateVariant docs() const + TemplateVariant createMemberGroups() const { - if (!m_cache.docs) - { - QCString docs = m_memberGroup->documentation(); - if (!docs.isEmpty()) - { - m_cache.docs.reset(new TemplateVariant( - parseDoc(m_def,"[@name docs]",-1, // TODO store file & line - m_relPath, - m_memberGroup->documentation()+"\n",FALSE))); - } - else - { - m_cache.docs.reset(new TemplateVariant("")); - } - } - return *m_cache.docs; + return MemberGroupListContext::alloc(); } - TemplateVariant inherited() const + TemplateVariant createDocs() const { - return FALSE; + return !m_memberGroup->documentation().isEmpty() ? + TemplateVariant(parseDoc(m_def,"[@name docs]",-1, // TODO store file & line + m_relPath, + m_memberGroup->documentation(),FALSE)) : + TemplateVariant(""); } - private: const Definition *m_def; QCString m_relPath; const MemberGroup *m_memberGroup; - struct Cachable - { - SharedPtr<MemberListContext> memberListContext; - SharedPtr<MemberGroupListContext> memberGroups; - std::unique_ptr<TemplateVariant> docs; - }; - mutable Cachable m_cache; - static PropertyMapper<MemberGroupInfoContext::Private> s_inst; + CachedItem<TemplateVariant,Private,&Private::createDocs> m_docs; + CachedItem<TemplateVariant,Private,&Private::createMembers> m_members; + CachedItem<TemplateVariant,Private,&Private::createMemberGroups> m_memberGroups; + static const PropertyMap<MemberGroupInfoContext::Private> s_inst; }; -//%% } -PropertyMapper<MemberGroupInfoContext::Private> MemberGroupInfoContext::Private::s_inst; +//%% struct MemberGroupInfo: member group information +//%% { +const PropertyMap<MemberGroupInfoContext::Private> MemberGroupInfoContext::Private::s_inst { + { "members", &Private::members }, + { "title", &Private::groupTitle }, + { "subtitle", &Private::groupSubtitle }, + { "anchor", &Private::groupAnchor }, + { "memberGroups", &Private::memberGroups }, + { "docs", &Private::docs }, + { "inherited", &Private::inherited } +}; +//%% } MemberGroupInfoContext::MemberGroupInfoContext(const Definition *def, - const QCString &relPath,const MemberGroup *mg) : RefCountedContext("MemberGroupInfoContext") + const QCString &relPath,const MemberGroup *mg) : p(std::make_unique<Private>(def,relPath,mg)) { - p = new Private(def,relPath,mg); } MemberGroupInfoContext::~MemberGroupInfoContext() { - delete p; } TemplateVariant MemberGroupInfoContext::get(const QCString &name) const @@ -9629,23 +7853,20 @@ class MemberGroupListContext::Private : public GenericNodeListContext } }; -MemberGroupListContext::MemberGroupListContext() : RefCountedContext("MemberGroupListContext") +MemberGroupListContext::MemberGroupListContext() : p(std::make_unique<Private>()) { - p = new Private; } -MemberGroupListContext::MemberGroupListContext(const Definition *def,const QCString &relPath,const MemberGroupRefList &list) : RefCountedContext("MemberGroupListContext") +MemberGroupListContext::MemberGroupListContext(const Definition *def,const QCString &relPath,const MemberGroupRefList &list) : p(std::make_unique<Private>()) { - p = new Private; for (const auto &mg : list) { p->addMemberGroup(def,relPath,mg); } } -MemberGroupListContext::MemberGroupListContext(const Definition *def,const QCString &relPath,const MemberGroupList &list,bool subGrouping) : RefCountedContext("MemberGroupListContext") +MemberGroupListContext::MemberGroupListContext(const Definition *def,const QCString &relPath,const MemberGroupList &list,bool subGrouping) : p(std::make_unique<Private>()) { - p = new Private; for (const auto &mg : list) { if (!mg->allMembersInSameSection() || !subGrouping) @@ -9657,7 +7878,6 @@ MemberGroupListContext::MemberGroupListContext(const Definition *def,const QCStr MemberGroupListContext::~MemberGroupListContext() { - delete p; } // TemplateListIntf @@ -9671,7 +7891,7 @@ TemplateVariant MemberGroupListContext::at(uint index) const return p->at(index); } -TemplateListIntf::ConstIterator *MemberGroupListContext::createIterator() const +TemplateListIntf::ConstIteratorPtr MemberGroupListContext::createIterator() const { return p->createIterator(); } @@ -9679,113 +7899,81 @@ TemplateListIntf::ConstIterator *MemberGroupListContext::createIterator() const //------------------------------------------------------------------------ -//%% struct MemberListInfo: member list information -//%% { class MemberListInfoContext::Private { public: - Private(const Definition *def,const QCString &relPath,const MemberList *ml,const QCString &title,const QCString &subtitle) : - m_def(def), - m_memberList(ml), - m_relPath(relPath), - m_title(title), - m_subtitle(subtitle) - { - static bool init=FALSE; - if (!init) - { - s_inst.addProperty("members", &Private::members); - s_inst.addProperty("title", &Private::title); - s_inst.addProperty("subtitle", &Private::subtitle); - s_inst.addProperty("anchor", &Private::anchor); - s_inst.addProperty("memberGroups", &Private::memberGroups); - s_inst.addProperty("inherited", &Private::inherited); - init=TRUE; - } - } - TemplateVariant get(const QCString &n) const - { - return s_inst.get(this,n); - } - StringVector fields() const - { - return s_inst.fields(); - } - TemplateVariant members() const - { - if (!m_cache.memberListContext) - { - m_cache.memberListContext.reset(MemberListContext::alloc(m_memberList)); - } - return m_cache.memberListContext.get(); - } - TemplateVariant title() const - { - return m_title; - } - TemplateVariant subtitle() const - { - return m_subtitle; - } - TemplateVariant anchor() const + Private(const Definition *def,const QCString &relPath,const MemberList *ml,const QCString &title,const QCString &subtitle) + : m_def(def), m_memberList(ml), m_relPath(relPath), m_title(title), m_subtitle(subtitle) {} + + // TemplateStructIntf methods + TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); } + StringVector fields() const { return s_inst.fields(); } + + private: + // Property getters + TemplateVariant members() const { return m_memberListCtx.get(this); } + TemplateVariant title() const { return m_title; } + TemplateVariant subtitle() const { return m_subtitle; } + TemplateVariant anchor() const { return MemberList::listTypeAsString(m_memberList->listType()); } + TemplateVariant memberGroups() const { return m_memberGroups.get(this); } + TemplateVariant inherited() const { return m_inherited.get(this); } + + private: + + TemplateVariant createMemberList() const { - return MemberList::listTypeAsString(m_memberList->listType()); + return MemberListContext::alloc(m_memberList); } - TemplateVariant memberGroups() const + TemplateVariant createMemberGroups() const { - if (!m_cache.memberGroups) - { - m_cache.memberGroups.reset(MemberGroupListContext::alloc(m_def,m_relPath,m_memberList->getMemberGroupList())); - } - return m_cache.memberGroups.get(); + return MemberGroupListContext::alloc(m_def,m_relPath,m_memberList->getMemberGroupList()); } - TemplateVariant inherited() const + TemplateVariant createInherited() const { - if (!m_cache.inherited && (m_memberList->listType()&MemberListType_detailedLists)==0 && + if ((m_memberList->listType()&MemberListType_detailedLists)==0 && m_def->definitionType()==Definition::TypeClass) { - InheritedMemberInfoListContext *ctx = InheritedMemberInfoListContext::alloc(); + TemplateListIntfPtr list = InheritedMemberInfoListContext::alloc(); + auto ctx = std::dynamic_pointer_cast<InheritedMemberInfoListContext>(list); ctx->addMemberList(toClassDef(m_def),m_memberList->listType(),m_title,FALSE); - m_cache.inherited.reset(ctx); - } - if (m_cache.inherited) - { - return m_cache.inherited.get(); + return list; } else { - return TemplateVariant(FALSE); + return TemplateVariant(false); } } - private: const Definition *m_def; const MemberList *m_memberList; QCString m_relPath; QCString m_title; QCString m_subtitle; - struct Cachable - { - SharedPtr<MemberListContext> memberListContext; - SharedPtr<MemberGroupListContext> memberGroups; - SharedPtr<InheritedMemberInfoListContext> inherited; - }; - mutable Cachable m_cache; - static PropertyMapper<MemberListInfoContext::Private> s_inst; + CachedItem<TemplateVariant, Private, &Private::createMemberList> m_memberListCtx; + CachedItem<TemplateVariant, Private, &Private::createMemberGroups> m_memberGroups; + CachedItem<TemplateVariant, Private, &Private::createInherited> m_inherited; + static const PropertyMap<MemberListInfoContext::Private> s_inst; }; -//%% } -PropertyMapper<MemberListInfoContext::Private> MemberListInfoContext::Private::s_inst; +//%% struct MemberListInfo: member list information +//%% { +const PropertyMap<MemberListInfoContext::Private> MemberListInfoContext::Private::s_inst { + { "members", &Private::members }, + { "title", &Private::title }, + { "subtitle", &Private::subtitle }, + { "anchor", &Private::anchor }, + { "memberGroups", &Private::memberGroups }, + { "inherited", &Private::inherited } +}; +//%% } MemberListInfoContext::MemberListInfoContext( const Definition *def,const QCString &relPath,const MemberList *ml, - const QCString &title,const QCString &subtitle) : RefCountedContext("MemberListInfoContext") + const QCString &title,const QCString &subtitle) : p(std::make_unique<Private>(def,relPath,ml,title,subtitle)) { - p = new Private(def,relPath,ml,title,subtitle); } MemberListInfoContext::~MemberListInfoContext() { - delete p; } TemplateVariant MemberListInfoContext::get(const QCString &name) const @@ -9800,95 +7988,69 @@ StringVector MemberListInfoContext::fields() const //------------------------------------------------------------------------ -//%% struct InheritedMemberInfo: inherited member information -//%% { class InheritedMemberInfoContext::Private { public: - Private(const ClassDef *cd,const MemberList *ml,const QCString &title) - : m_class(cd), m_memberList(ml), m_title(title) - { - static bool init=FALSE; - if (!init) - { - s_inst.addProperty("class", &Private::getClass); - s_inst.addProperty("title", &Private::title); - s_inst.addProperty("members", &Private::members); - s_inst.addProperty("id", &Private::id); - s_inst.addProperty("inheritedFrom", &Private::inheritedFrom); - init=TRUE; - } - } - TemplateVariant get(const QCString &n) const - { - return s_inst.get(this,n); - } - StringVector fields() const - { - return s_inst.fields(); - } - virtual ~Private() - { - delete m_memberList; - } - TemplateVariant getClass() const - { - if (!m_classCtx) - { - m_classCtx.reset(ClassContext::alloc(m_class)); - } - return m_classCtx.get(); - } - TemplateVariant title() const + Private(const ClassDef *cd,std::unique_ptr<MemberList> &&ml,const QCString &title) + : m_class(cd), m_memberList(std::move(ml)), m_title(title) {} + + // TemplateStructIntf methods + TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); } + StringVector fields() const { return s_inst.fields(); } + + private: + // Property getters + TemplateVariant getClass() const { return m_classCtx.get(this); } + TemplateVariant title() const { return m_title; } + TemplateVariant members() const { return m_memberListCtx.get(this); } + TemplateVariant inheritedFrom() const { return m_inheritedFrom.get(this); } + TemplateVariant id() const { - return m_title; + return substitute(MemberList::listTypeAsString(m_memberList->listType()),"-","_")+"_"+ + stripPath(m_class->getOutputFileBase()); } - TemplateVariant members() const + + private: + TemplateVariant createClass() const { - if (!m_memberListCtx) - { - m_memberListCtx.reset(MemberListContext::alloc(m_memberList)); - } - return m_memberListCtx.get(); + return ClassContext::alloc(m_class); } - TemplateVariant id() const + TemplateVariant createMemberList() const { - return substitute(MemberList::listTypeAsString(m_memberList->listType()),"-","_")+"_"+ - stripPath(m_class->getOutputFileBase()); + return MemberListContext::alloc(m_memberList.get()); } - TemplateVariant inheritedFrom() const + TemplateVariant createInheritedFrom() const { - if (!m_inheritedFrom) - { - m_inheritedFrom.reset(TemplateList::alloc()); - m_inheritedFrom->append(title()); - m_inheritedFrom->append(getClass()); - } - return m_inheritedFrom.get(); + return TemplateImmutableList::alloc({ TemplateVariant(title()), TemplateVariant(getClass()) }); } - private: const ClassDef * m_class; - const MemberList *m_memberList; + std::unique_ptr<const MemberList> m_memberList; QCString m_title; - mutable SharedPtr<ClassContext> m_classCtx; - mutable SharedPtr<MemberListContext> m_memberListCtx; - mutable SharedPtr<TemplateList> m_inheritedFrom; - static PropertyMapper<InheritedMemberInfoContext::Private> s_inst; + CachedItem<TemplateVariant, Private, &Private::createClass> m_classCtx; + CachedItem<TemplateVariant, Private, &Private::createMemberList> m_memberListCtx; + CachedItem<TemplateVariant, Private, &Private::createInheritedFrom> m_inheritedFrom; + static const PropertyMap<InheritedMemberInfoContext::Private> s_inst; }; -//%% } -PropertyMapper<InheritedMemberInfoContext::Private> InheritedMemberInfoContext::Private::s_inst; +//%% struct InheritedMemberInfo: inherited member information +//%% { +const PropertyMap<InheritedMemberInfoContext::Private> InheritedMemberInfoContext::Private::s_inst { + { "class", &Private::getClass }, + { "title", &Private::title }, + { "members", &Private::members }, + { "id", &Private::id }, + { "inheritedFrom", &Private::inheritedFrom } +}; +//%% } -InheritedMemberInfoContext::InheritedMemberInfoContext(const ClassDef *cd,const MemberList *ml, - const QCString &title) : RefCountedContext("InheritedMemberInfoContext") +InheritedMemberInfoContext::InheritedMemberInfoContext(const ClassDef *cd,std::unique_ptr<MemberList> &&ml,const QCString &title) + : p(std::make_unique<Private>(cd,std::move(ml),title)) { - p = new Private(cd,ml,title); } InheritedMemberInfoContext::~InheritedMemberInfoContext() { - delete p; } TemplateVariant InheritedMemberInfoContext::get(const QCString &name) const @@ -9958,12 +8120,12 @@ class InheritedMemberInfoListContext::Private : public GenericNodeListContext { const MemberList *ml = cd->getMemberList(lt1); const MemberList *ml2 = lt2!=-1 ? cd->getMemberList((MemberListType)lt2) : 0; - MemberList *combinedList = new MemberList(lt,MemberListContainer::Class); - addMemberListIncludingGrouped(inheritedFrom,ml,combinedList); - addMemberListIncludingGrouped(inheritedFrom,ml2,combinedList); - addMemberGroupsOfClass(inheritedFrom,cd,lt,combinedList); - if (lt2!=-1) addMemberGroupsOfClass(inheritedFrom,cd,(MemberListType)lt2,combinedList); - append(InheritedMemberInfoContext::alloc(cd,combinedList,title)); + std::unique_ptr<MemberList> combinedList = std::make_unique<MemberList>(lt,MemberListContainer::Class); + addMemberListIncludingGrouped(inheritedFrom,ml,combinedList.get()); + addMemberListIncludingGrouped(inheritedFrom,ml2,combinedList.get()); + addMemberGroupsOfClass(inheritedFrom,cd,lt,combinedList.get()); + if (lt2!=-1) addMemberGroupsOfClass(inheritedFrom,cd,(MemberListType)lt2,combinedList.get()); + append(InheritedMemberInfoContext::alloc(cd,std::move(combinedList),title)); } } void findInheritedMembers(const ClassDef *inheritedFrom,const ClassDef *cd,MemberListType lt, @@ -9997,9 +8159,8 @@ class InheritedMemberInfoListContext::Private : public GenericNodeListContext } }; -InheritedMemberInfoListContext::InheritedMemberInfoListContext() : RefCountedContext("InheritedMemberInfoListContext") +InheritedMemberInfoListContext::InheritedMemberInfoListContext() : p(std::make_unique<Private>()) { - p = new Private; } void InheritedMemberInfoListContext::addMemberList( @@ -10018,7 +8179,6 @@ void InheritedMemberInfoListContext::addMemberList( InheritedMemberInfoListContext::~InheritedMemberInfoListContext() { - delete p; } // TemplateListIntf @@ -10032,79 +8192,31 @@ TemplateVariant InheritedMemberInfoListContext::at(uint index) const return p->at(index); } -TemplateListIntf::ConstIterator *InheritedMemberInfoListContext::createIterator() const +TemplateListIntf::ConstIteratorPtr InheritedMemberInfoListContext::createIterator() const { return p->createIterator(); } //------------------------------------------------------------------------ -//%% struct Argument: parameter information -//%% { class ArgumentContext::Private { public: - Private(const Argument &arg,const Definition *def,const QCString &relPath) : - m_argument(arg), m_def(def), m_relPath(relPath) - { - static bool init=FALSE; - if (!init) - { - s_inst.addProperty("type", &Private::type); - s_inst.addProperty("name", &Private::name); - s_inst.addProperty("defVal", &Private::defVal); - s_inst.addProperty("docs", &Private::docs); - s_inst.addProperty("attrib", &Private::attrib); - s_inst.addProperty("array", &Private::array); - s_inst.addProperty("namePart", &Private::namePart); - init=TRUE; - } - } - TemplateVariant get(const QCString &n) const - { - return s_inst.get(this,n); - } - StringVector fields() const - { - return s_inst.fields(); - } - TemplateVariant type() const - { - return createLinkedText(m_def,m_relPath,m_argument.type); - } - TemplateVariant attrib() const - { - return m_argument.attrib; - } - TemplateVariant name() const - { - return m_argument.name; - } - TemplateVariant defVal() const - { - return createLinkedText(m_def,m_relPath,m_argument.defval); - } - TemplateVariant array() const - { - return m_argument.array; - } - TemplateVariant docs() const - { - if (!m_cache.docs && m_def) - { - if (!m_argument.docs.isEmpty()) - { - m_cache.docs.reset(new TemplateVariant( - parseDoc(m_def,m_def->docFile(),m_def->docLine(), - m_relPath,m_argument.docs,TRUE))); - } - else - { - m_cache.docs.reset(new TemplateVariant("")); - } - } - return *m_cache.docs; - } + Private(const Argument &arg,const Definition *def,const QCString &relPath) + : m_argument(arg), m_def(def), m_relPath(relPath) {} + + // TemplateStructIntf methods + TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); } + StringVector fields() const { return s_inst.fields(); } + + private: + // Property getters + TemplateVariant type() const { return m_type.get(this); } + TemplateVariant attrib() const { return m_argument.attrib; } + TemplateVariant name() const { return m_argument.name; } + TemplateVariant defVal() const { return m_defval.get(this); } + TemplateVariant array() const { return m_argument.array; } + TemplateVariant docs() const { return m_docs.get(this); } TemplateVariant namePart() const { QCString result = m_argument.attrib; @@ -10116,29 +8228,51 @@ class ArgumentContext::Private } return result; } + private: + TemplateVariant createType() const + { + return createLinkedText(m_def,m_relPath,m_argument.type); + } + TemplateVariant createDefval() const + { + return createLinkedText(m_def,m_relPath,m_argument.defval); + } + TemplateVariant createDocs() const + { + return !m_argument.docs.isEmpty() ? + TemplateVariant(parseDoc(m_def,m_def->docFile(),m_def->docLine(),m_relPath,m_argument.docs,TRUE)) : + TemplateVariant(""); + } Argument m_argument; const Definition *m_def; QCString m_relPath; - struct Cachable - { - std::unique_ptr<TemplateVariant> docs; - }; - mutable Cachable m_cache; - static PropertyMapper<ArgumentContext::Private> s_inst; + CachedItem<TemplateVariant, Private, &Private::createType> m_type; + CachedItem<TemplateVariant, Private, &Private::createDefval> m_defval; + CachedItem<TemplateVariant, Private, &Private::createDocs> m_docs; + static const PropertyMap<ArgumentContext::Private> s_inst; +}; + +//%% struct Argument: parameter information +//%% { +const PropertyMap<ArgumentContext::Private> ArgumentContext::Private::s_inst { + { "type", &Private::type }, + { "name", &Private::name }, + { "defVal", &Private::defVal }, + { "docs", &Private::docs }, + { "attrib", &Private::attrib }, + { "array", &Private::array }, + { "namePart", &Private::namePart } }; //%% } -PropertyMapper<ArgumentContext::Private> ArgumentContext::Private::s_inst; -ArgumentContext::ArgumentContext(const Argument &al,const Definition *def,const QCString &relPath) : RefCountedContext("ArgumentContext") +ArgumentContext::ArgumentContext(const Argument &al,const Definition *def,const QCString &relPath) : p(std::make_unique<Private>(al,def,relPath)) { - p = new Private(al,def,relPath); } ArgumentContext::~ArgumentContext() { - delete p; } TemplateVariant ArgumentContext::get(const QCString &name) const @@ -10163,15 +8297,13 @@ class ArgumentListContext::Private : public GenericNodeListContext } }; -ArgumentListContext::ArgumentListContext() : RefCountedContext("ArgumentListContext") +ArgumentListContext::ArgumentListContext() : p(std::make_unique<Private>()) { - p = new Private; } ArgumentListContext::ArgumentListContext(const ArgumentList &list, - const Definition *def,const QCString &relPath) : RefCountedContext("ArgumentListContext") + const Definition *def,const QCString &relPath) : p(std::make_unique<Private>()) { - p = new Private; for (const Argument &arg : list) { p->addArgument(arg,def,relPath); @@ -10180,7 +8312,6 @@ ArgumentListContext::ArgumentListContext(const ArgumentList &list, ArgumentListContext::~ArgumentListContext() { - delete p; } // TemplateListIntf @@ -10194,7 +8325,7 @@ TemplateVariant ArgumentListContext::at(uint index) const return p->at(index); } -TemplateListIntf::ConstIterator *ArgumentListContext::createIterator() const +TemplateListIntf::ConstIteratorPtr ArgumentListContext::createIterator() const { return p->createIterator(); } @@ -10218,41 +8349,25 @@ TemplateListIntf::ConstIterator *ArgumentListContext::createIterator() const //------------------------------------------------------------------------ -//%% struct SymbolGroup: search group of similar symbols -//%% { class SymbolContext::Private { public: - Private(const Definition *d,const Definition *prev, - const Definition *next) : m_def(d), m_prevDef(prev), m_nextDef(next) - { - static bool init=FALSE; - if (!init) - { - s_inst.addProperty("fileName",&Private::fileName); - s_inst.addProperty("anchor", &Private::anchor); - s_inst.addProperty("scope", &Private::scope); - s_inst.addProperty("relPath", &Private::relPath); - init=TRUE; - } - } - TemplateVariant get(const QCString &n) const - { - return s_inst.get(this,n); - } - StringVector fields() const - { - return s_inst.fields(); - } - TemplateVariant fileName() const - { - return m_def->getOutputFileBase(); - } - TemplateVariant anchor() const - { - return m_def->anchor(); - } - TemplateVariant scope() const + Private(const Definition *d,const Definition *prev, const Definition *next) + : m_def(d), m_prevDef(prev), m_nextDef(next) {} + + // TemplateStructIntf methods + TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); } + StringVector fields() const { return s_inst.fields(); } + + private: + // Property getters + TemplateVariant fileName() const { return m_def->getOutputFileBase(); } + TemplateVariant anchor() const { return m_def->anchor(); } + TemplateVariant scope() const { return m_scope.get(this); } + TemplateVariant relPath() const { return externalRef("../",m_def->getReference(),TRUE); } + + private: + TemplateVariant createScope() const { const Definition *scope = m_def->getOuterScope(); const Definition *next = m_nextDef; @@ -10283,7 +8398,6 @@ class SymbolContext::Private } else { - QCString prefix; if (md) prefix=md->localName(); if (overloadedFunction) // overloaded member function @@ -10340,29 +8454,29 @@ class SymbolContext::Private } return name; } - TemplateVariant relPath() const - { - return externalRef("../",m_def->getReference(),TRUE); - } - private: const Definition *m_def; const Definition *m_prevDef; const Definition *m_nextDef; - static PropertyMapper<SymbolContext::Private> s_inst; + CachedItem<TemplateVariant,Private,&Private::createScope> m_scope; + static const PropertyMap<SymbolContext::Private> s_inst; }; -//%% } -PropertyMapper<SymbolContext::Private> SymbolContext::Private::s_inst; +//%% struct Symbol: specific search item +//%% { +const PropertyMap<SymbolContext::Private> SymbolContext::Private::s_inst { + { "fileName",&Private::fileName }, + { "anchor", &Private::anchor }, + { "scope", &Private::scope }, + { "relPath", &Private::relPath } +}; +//%% } -SymbolContext::SymbolContext(const Definition *def,const Definition *prevDef,const Definition *nextDef) - : RefCountedContext("SymbolContext") +SymbolContext::SymbolContext(const Definition *def,const Definition *prevDef,const Definition *nextDef) : p(std::make_unique<Private>(def,prevDef,nextDef)) { - p = new Private(def,prevDef,nextDef); } SymbolContext::~SymbolContext() { - delete p; } TemplateVariant SymbolContext::get(const QCString &name) const @@ -10397,15 +8511,12 @@ class SymbolListContext::Private : public GenericNodeListContext }; SymbolListContext::SymbolListContext(const SearchIndexList::const_iterator &start, - const SearchIndexList::const_iterator &end) - : RefCountedContext("SymbolListContext") + const SearchIndexList::const_iterator &end) : p(std::make_unique<Private>(start,end)) { - p = new Private(start,end); } SymbolListContext::~SymbolListContext() { - delete p; } // TemplateListIntf @@ -10419,78 +8530,58 @@ TemplateVariant SymbolListContext::at(uint index) const return p->at(index); } -TemplateListIntf::ConstIterator *SymbolListContext::createIterator() const +TemplateListIntf::ConstIteratorPtr SymbolListContext::createIterator() const { return p->createIterator(); } //------------------------------------------------------------------------ -//%% struct SymbolGroup: search group of similar symbols -//%% { class SymbolGroupContext::Private { public: - Private(const SearchIndexList::const_iterator &start, - const SearchIndexList::const_iterator &end) : m_start(start), m_end(end) - { - static bool init=FALSE; - if (!init) - { - s_inst.addProperty("id", &Private::id); - s_inst.addProperty("name", &Private::name); - s_inst.addProperty("symbols",&Private::symbolList); - init=TRUE; - } - } - TemplateVariant get(const QCString &n) const - { - return s_inst.get(this,n); - } - StringVector fields() const - { - return s_inst.fields(); - } - TemplateVariant id() const - { - return searchId(*m_start); - } - TemplateVariant name() const - { - return searchName(*m_start); - } - TemplateVariant symbolList() const + Private(const SearchIndexList::const_iterator &start, const SearchIndexList::const_iterator &end) + : m_start(start), m_end(end) {} + + // TemplateStructIntf methods + TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); } + StringVector fields() const { return s_inst.fields(); } + + private: + // Property getters + TemplateVariant id() const { return searchId(*m_start); } + TemplateVariant name() const { return searchName(*m_start); } + TemplateVariant symbolList() const { return m_symbolList.get(this); } + + private: + + TemplateVariant createSymbolList() const { - if (!m_cache.symbolList) - { - m_cache.symbolList.reset(SymbolListContext::alloc(m_start,m_end)); - } - return m_cache.symbolList.get(); + return SymbolListContext::alloc(m_start,m_end); } - private: + SearchIndexList::const_iterator m_start; SearchIndexList::const_iterator m_end; - struct Cachable - { - SharedPtr<SymbolListContext> symbolList; - }; - mutable Cachable m_cache; - static PropertyMapper<SymbolGroupContext::Private> s_inst; + CachedItem<TemplateVariant,Private,&Private::createSymbolList> m_symbolList; + static const PropertyMap<SymbolGroupContext::Private> s_inst; }; -//%% } -PropertyMapper<SymbolGroupContext::Private> SymbolGroupContext::Private::s_inst; +//%% struct SymbolGroup: search group of similar symbols +//%% { +const PropertyMap<SymbolGroupContext::Private> SymbolGroupContext::Private::s_inst { + { "id", &Private::id }, + { "name", &Private::name }, + { "symbols",&Private::symbolList } +}; +//%% } SymbolGroupContext::SymbolGroupContext(const SearchIndexList::const_iterator &start, - const SearchIndexList::const_iterator &end) - : RefCountedContext("SymbolGroupContext") + const SearchIndexList::const_iterator &end) : p(std::make_unique<Private>(start,end)) { - p = new Private(start,end); } SymbolGroupContext::~SymbolGroupContext() { - delete p; } TemplateVariant SymbolGroupContext::get(const QCString &name) const @@ -10535,15 +8626,12 @@ class SymbolGroupListContext::Private : public GenericNodeListContext } }; -SymbolGroupListContext::SymbolGroupListContext(const SearchIndexList &sil) - : RefCountedContext("SymbolGroupListContext") +SymbolGroupListContext::SymbolGroupListContext(const SearchIndexList &sil) : p(std::make_unique<Private>(sil)) { - p = new Private(sil); } SymbolGroupListContext::~SymbolGroupListContext() { - delete p; } // TemplateListIntf @@ -10557,79 +8645,56 @@ TemplateVariant SymbolGroupListContext::at(uint index) const return p->at(index); } -TemplateListIntf::ConstIterator *SymbolGroupListContext::createIterator() const +TemplateListIntf::ConstIteratorPtr SymbolGroupListContext::createIterator() const { return p->createIterator(); } //------------------------------------------------------------------------ -//%% struct SymbolIndex: search index -//%% { class SymbolIndexContext::Private { public: - Private(const std::string &letter, - const SearchIndexList &sl, - const QCString &name) : m_letter(letter), m_searchList(sl), m_name(name) - { - static bool init=FALSE; - if (!init) - { - s_inst.addProperty("name", &Private::name); - s_inst.addProperty("letter", &Private::letter); - s_inst.addProperty("symbolGroups",&Private::symbolGroups); - init=TRUE; - } - } - TemplateVariant get(const QCString &n) const - { - return s_inst.get(this,n); - } - StringVector fields() const - { - return s_inst.fields(); - } - TemplateVariant name() const - { - return m_name; - } - TemplateVariant letter() const - { - return m_letter; - } - TemplateVariant symbolGroups() const + Private(const std::string &letter, const SearchIndexList &sl, const QCString &name) + : m_letter(letter), m_searchList(sl), m_name(name) {} + // TemplateStructIntf methods + TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); } + StringVector fields() const { return s_inst.fields(); } + + private: + // Property getters + TemplateVariant name() const { return m_name; } + TemplateVariant letter() const { return m_letter; } + TemplateVariant symbolGroups() const { return m_symbolGroups.get(this); } + + private: + + TemplateVariant createSymbolGroups() const { - if (!m_cache.symbolGroups) - { - m_cache.symbolGroups.reset(SymbolGroupListContext::alloc(m_searchList)); - } - return m_cache.symbolGroups.get(); + return SymbolGroupListContext::alloc(m_searchList); } - private: QCString m_letter; const SearchIndexList &m_searchList; QCString m_name; - struct Cachable - { - SharedPtr<SymbolGroupListContext> symbolGroups; - }; - mutable Cachable m_cache; - static PropertyMapper<SymbolIndexContext::Private> s_inst; + CachedItem<TemplateVariant,Private,&Private::createSymbolGroups> m_symbolGroups; + static const PropertyMap<SymbolIndexContext::Private> s_inst; }; -//%% } -PropertyMapper<SymbolIndexContext::Private> SymbolIndexContext::Private::s_inst; +//%% struct SymbolIndex: search index +//%% { +const PropertyMap<SymbolIndexContext::Private> SymbolIndexContext::Private::s_inst { + { "name", &Private::name }, + { "letter", &Private::letter }, + { "symbolGroups",&Private::symbolGroups }, +}; +//%% } -SymbolIndexContext::SymbolIndexContext(const std::string &letter,const SearchIndexList &sl,const QCString &name) - : RefCountedContext("SymbolIndexContext") +SymbolIndexContext::SymbolIndexContext(const std::string &letter,const SearchIndexList &sl,const QCString &name) : p(std::make_unique<Private>(letter,sl,name)) { - p = new Private(letter,sl,name); } SymbolIndexContext::~SymbolIndexContext() { - delete p; } TemplateVariant SymbolIndexContext::get(const QCString &name) const @@ -10658,14 +8723,12 @@ class SymbolIndicesContext::Private : public GenericNodeListContext } }; -SymbolIndicesContext::SymbolIndicesContext(const SearchIndexInfo &info) : RefCountedContext("SymbolIndicesContext") +SymbolIndicesContext::SymbolIndicesContext(const SearchIndexInfo &info) : p(std::make_unique<Private>(info)) { - p = new Private(info); } SymbolIndicesContext::~SymbolIndicesContext() { - delete p; } // TemplateListIntf @@ -10679,75 +8742,54 @@ TemplateVariant SymbolIndicesContext::at(uint index) const return p->at(index); } -TemplateListIntf::ConstIterator *SymbolIndicesContext::createIterator() const +TemplateListIntf::ConstIteratorPtr SymbolIndicesContext::createIterator() const { return p->createIterator(); } //------------------------------------------------------------------------ -//%% struct SearchIndex: search index -//%% { class SearchIndexContext::Private { public: - Private(const SearchIndexInfo &info) : m_info(info) - { - static bool init=FALSE; - if (!init) - { - s_inst.addProperty("name", &Private::name); - s_inst.addProperty("text", &Private::text); - s_inst.addProperty("symbolIndices",&Private::symbolIndices); - init=TRUE; - } - } - TemplateVariant get(const QCString &n) const - { - return s_inst.get(this,n); - } - StringVector fields() const - { - return s_inst.fields(); - } - TemplateVariant name() const - { - return m_info.name; - } - TemplateVariant text() const - { - return m_info.getText(); - } - TemplateVariant symbolIndices() const + Private(const SearchIndexInfo &info) : m_info(info) {} + + // TemplateStructIntf methods + TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); } + StringVector fields() const { return s_inst.fields(); } + + private: + // Property getters + TemplateVariant name() const { return m_info.name; } + TemplateVariant text() const { return m_info.getText(); } + TemplateVariant symbolIndices() const { return m_symbolIndices.get(this); } + + private: + TemplateVariant createSymbolIndices() const { - if (!m_cache.symbolIndices) - { - m_cache.symbolIndices.reset(SymbolIndicesContext::alloc(m_info)); - } - return m_cache.symbolIndices.get(); + return SymbolIndicesContext::alloc(m_info); } - private: + const SearchIndexInfo &m_info; - struct Cachable - { - SharedPtr<SymbolIndicesContext> symbolIndices; - }; - mutable Cachable m_cache; - static PropertyMapper<SearchIndexContext::Private> s_inst; + CachedItem<TemplateVariant, Private, &Private::createSymbolIndices> m_symbolIndices; + static const PropertyMap<SearchIndexContext::Private> s_inst; }; -//%% } -PropertyMapper<SearchIndexContext::Private> SearchIndexContext::Private::s_inst; +//%% struct SearchIndex: search index +//%% { +const PropertyMap<SearchIndexContext::Private> SearchIndexContext::Private::s_inst { + { "name", &Private::name }, + { "text", &Private::text }, + { "symbolIndices",&Private::symbolIndices } +}; +//%% } -SearchIndexContext::SearchIndexContext(const SearchIndexInfo &info) - : RefCountedContext("SearchIndexContext") +SearchIndexContext::SearchIndexContext(const SearchIndexInfo &info) : p(std::make_unique<Private>(info)) { - p = new Private(info); } SearchIndexContext::~SearchIndexContext() { - delete p; } TemplateVariant SearchIndexContext::get(const QCString &name) const @@ -10776,14 +8818,12 @@ class SearchIndicesContext::Private : public GenericNodeListContext } }; -SearchIndicesContext::SearchIndicesContext() : RefCountedContext("SearchIndicesContext") +SearchIndicesContext::SearchIndicesContext() : p(std::make_unique<Private>()) { - p = new Private; } SearchIndicesContext::~SearchIndicesContext() { - delete p; } // TemplateListIntf @@ -10797,7 +8837,7 @@ TemplateVariant SearchIndicesContext::at(uint index) const return p->at(index); } -TemplateListIntf::ConstIterator *SearchIndicesContext::createIterator() const +TemplateListIntf::ConstIteratorPtr SearchIndicesContext::createIterator() const { return p->createIterator(); } @@ -10808,6 +8848,10 @@ TemplateListIntf::ConstIterator *SearchIndicesContext::createIterator() const class HtmlEscaper : public TemplateEscapeIntf { public: + std::unique_ptr<TemplateEscapeIntf> clone() + { + return std::make_unique<HtmlEscaper>(*this); + } QCString escape(const QCString &s) { return convertToHtml(s,TRUE); @@ -10821,6 +8865,10 @@ class LatexSpaceless : public TemplateSpacelessIntf { public: LatexSpaceless() { reset(); } + std::unique_ptr<TemplateSpacelessIntf> clone() + { + return std::make_unique<LatexSpaceless>(*this); + } void reset() { } QCString remove(const QCString &s) { @@ -10850,6 +8898,10 @@ class HtmlSpaceless : public TemplateSpacelessIntf { public: HtmlSpaceless() { reset(); } + std::unique_ptr<TemplateSpacelessIntf> clone() + { + return std::make_unique<HtmlSpaceless>(*this); + } void reset() { m_insideTag = FALSE; @@ -10924,6 +8976,10 @@ class HtmlSpaceless : public TemplateSpacelessIntf class LatexEscaper : public TemplateEscapeIntf { public: + std::unique_ptr<TemplateEscapeIntf> clone() + { + return std::make_unique<LatexEscaper>(*this); + } LatexEscaper() : m_tabbing(FALSE) {} QCString escape(const QCString &s) { @@ -10937,112 +8993,107 @@ class LatexEscaper : public TemplateEscapeIntf //------------------------------------------------------------------------ -#if DEBUG_REF -int RefCountedContext::s_totalCount; -#endif - void generateOutputViaTemplate() { - msg("Generating output via template engine...\n"); { - TemplateEngine e; - TemplateContext *ctx = e.createContext(); + auto e = std::make_unique<TemplateEngine>(); + auto ctx = e->createContext(); if (ctx) { - SharedPtr<DoxygenContext> doxygen (DoxygenContext::alloc()); - SharedPtr<ConfigContext> config (ConfigContext::alloc()); - SharedPtr<TranslateContext> tr (TranslateContext::alloc()); - SharedPtr<ClassListContext> classList (ClassListContext::alloc()); - SharedPtr<ClassIndexContext> classIndex (ClassIndexContext::alloc()); - SharedPtr<ClassTreeContext> classTree (ClassTreeContext::alloc()); - SharedPtr<ClassHierarchyContext> classHierarchy (ClassHierarchyContext::alloc()); - SharedPtr<ConceptListContext> conceptList (ConceptListContext::alloc()); - SharedPtr<ConceptTreeContext> conceptTree (ConceptTreeContext::alloc()); - SharedPtr<NamespaceListContext> namespaceList (NamespaceListContext::alloc()); - SharedPtr<NamespaceTreeContext> namespaceTree (NamespaceTreeContext::alloc()); - SharedPtr<DirListContext> dirList (DirListContext::alloc()); - SharedPtr<FileListContext> fileList (FileListContext::alloc()); - SharedPtr<FileTreeContext> fileTree (FileTreeContext::alloc()); - SharedPtr<PageTreeContext> pageTree (PageTreeContext::alloc(*Doxygen::pageLinkedMap)); - SharedPtr<PageListContext> pageList (PageListContext::alloc(*Doxygen::pageLinkedMap)); - SharedPtr<ExampleTreeContext> exampleTree (ExampleTreeContext::alloc()); - SharedPtr<ExampleListContext> exampleList (ExampleListContext::alloc()); - SharedPtr<ModuleTreeContext> moduleTree (ModuleTreeContext::alloc()); - SharedPtr<ModuleListContext> moduleList (ModuleListContext::alloc()); - SharedPtr<GlobalsIndexContext> globalsIndex (GlobalsIndexContext::alloc()); - SharedPtr<ClassMembersIndexContext> classMembersIndex (ClassMembersIndexContext::alloc()); - SharedPtr<NamespaceMembersIndexContext> namespaceMembersIndex(NamespaceMembersIndexContext::alloc()); - SharedPtr<SearchIndicesContext> searchIndices (SearchIndicesContext::alloc()); + TemplateStructIntfPtr doxygen (DoxygenContext::alloc()); + TemplateStructIntfPtr config (ConfigContext::alloc()); + TemplateStructIntfPtr tr (TranslateContext::alloc()); + TemplateListIntfPtr classList (ClassListContext::alloc()); + TemplateStructIntfPtr classIndex (ClassIndexContext::alloc()); + TemplateStructIntfPtr classTree (ClassTreeContext::alloc()); + TemplateStructIntfPtr classHierarchy (ClassHierarchyContext::alloc()); + TemplateListIntfPtr conceptList (ConceptListContext::alloc()); + TemplateStructIntfPtr conceptTree (ConceptTreeContext::alloc()); + TemplateListIntfPtr namespaceList (NamespaceListContext::alloc()); + TemplateStructIntfPtr namespaceTree (NamespaceTreeContext::alloc()); + TemplateListIntfPtr dirList (DirListContext::alloc()); + TemplateListIntfPtr fileList (FileListContext::alloc()); + TemplateStructIntfPtr fileTree (FileTreeContext::alloc()); + TemplateStructIntfPtr pageTree (PageTreeContext::alloc(*Doxygen::pageLinkedMap)); + TemplateListIntfPtr pageList (PageListContext::alloc(*Doxygen::pageLinkedMap)); + TemplateStructIntfPtr exampleTree (ExampleTreeContext::alloc()); + TemplateListIntfPtr exampleList (ExampleListContext::alloc()); + TemplateStructIntfPtr moduleTree (ModuleTreeContext::alloc()); + TemplateListIntfPtr moduleList (ModuleListContext::alloc()); + TemplateStructIntfPtr globalsIndex (GlobalsIndexContext::alloc()); + TemplateStructIntfPtr classMembersIndex (ClassMembersIndexContext::alloc()); + TemplateStructIntfPtr namespaceMembersIndex(NamespaceMembersIndexContext::alloc()); + TemplateListIntfPtr searchIndices (SearchIndicesContext::alloc()); //%% Doxygen doxygen: - ctx->set("doxygen",doxygen.get()); + ctx->set("doxygen",doxygen); //%% Translator tr: - ctx->set("tr",tr.get()); + ctx->set("tr",tr); //%% Config config: - ctx->set("config",config.get()); + ctx->set("config",config); //%% ClassList classList: - ctx->set("classList",classList.get()); // not used for standard HTML + ctx->set("classList",classList); // not used for standard HTML //%% ClassTree classTree: - ctx->set("classTree",classTree.get()); + ctx->set("classTree",classTree); //%% ClassIndex classIndex: - ctx->set("classIndex",classIndex.get()); + ctx->set("classIndex",classIndex); //%% ClassHierarchy classHierarchy: - ctx->set("classHierarchy",classHierarchy.get()); + ctx->set("classHierarchy",classHierarchy); //%% ConceptList conceptList: - ctx->set("conceptList",conceptList.get()); + ctx->set("conceptList",conceptList); //%% ConceptTree conceptTree: - ctx->set("conceptTree",conceptTree.get()); + ctx->set("conceptTree",conceptTree); //%% NamespaceList namespaceList: - ctx->set("namespaceList",namespaceList.get()); + ctx->set("namespaceList",namespaceList); //%% NamespaceTree namespaceTree: - ctx->set("namespaceTree",namespaceTree.get()); + ctx->set("namespaceTree",namespaceTree); //%% FileList fileList: - ctx->set("fileList",fileList.get()); + ctx->set("fileList",fileList); //%% FileTree fileTree: - ctx->set("fileTree",fileTree.get()); + ctx->set("fileTree",fileTree); //%% PageList pageList - ctx->set("pageList",pageList.get()); + ctx->set("pageList",pageList); //%% PageTree pageTree - ctx->set("pageTree",pageTree.get()); + ctx->set("pageTree",pageTree); //%% ExampleTree exampleTree - ctx->set("exampleTree",exampleTree.get()); + ctx->set("exampleTree",exampleTree); //%% ExampleList exampleList - ctx->set("exampleList",exampleList.get()); + ctx->set("exampleList",exampleList); //%% ModuleTree moduleTree - ctx->set("moduleTree",moduleTree.get()); + ctx->set("moduleTree",moduleTree); //%% ModuleList moduleList - ctx->set("moduleList",moduleList.get()); + ctx->set("moduleList",moduleList); //%% DirList dirList - ctx->set("dirList",dirList.get()); + ctx->set("dirList",dirList); //%% Page mainPage if (Doxygen::mainPage) { - SharedPtr<PageContext> mainPage(PageContext::alloc(Doxygen::mainPage.get(),TRUE,FALSE)); - ctx->set("mainPage",mainPage.get()); + TemplateStructIntfPtr mainPage = PageContext::alloc(Doxygen::mainPage.get(),TRUE,FALSE); + ctx->set("mainPage",mainPage); } else { // TODO: for LaTeX output index should be main... => solve in template Doxygen::mainPage.reset(createPageDef("[generated]",1,"index","",Config_getString(PROJECT_NAME))); Doxygen::mainPage->setFileName("index"); - SharedPtr<PageContext> mainPage(PageContext::alloc(Doxygen::mainPage.get(),TRUE,FALSE)); - ctx->set("mainPage",mainPage.get()); + TemplateStructIntfPtr mainPage = PageContext::alloc(Doxygen::mainPage.get(),TRUE,FALSE); + ctx->set("mainPage",mainPage); } //%% GlobalsIndex globalsIndex: - ctx->set("globalsIndex",globalsIndex.get()); + ctx->set("globalsIndex",globalsIndex); //%% ClassMembersIndex classMembersIndex: - ctx->set("classMembersIndex",classMembersIndex.get()); + ctx->set("classMembersIndex",classMembersIndex); //%% NamespaceMembersIndex namespaceMembersIndex: - ctx->set("namespaceMembersIndex",namespaceMembersIndex.get()); + ctx->set("namespaceMembersIndex",namespaceMembersIndex); //%% SearchIndices searchIndices - ctx->set("searchIndices",searchIndices.get()); + ctx->set("searchIndices",searchIndices); //%% string space ctx->set("space"," "); //if (Config_getBool(GENERATE_HTML)) { // render HTML output - e.setTemplateDir("templates/html"); // TODO: make template part user configurable - Template *tpl = e.loadByName("htmllayout.tpl",1); + e->setTemplateDir("templates/html"); // TODO: make template part user configurable + Template *tpl = e->loadByName("htmllayout.tpl",1); if (tpl) { g_globals.outputFormat = ContextOutputFormat_Html; @@ -11050,15 +9101,13 @@ void generateOutputViaTemplate() g_globals.outputDir = Config_getString(HTML_OUTPUT); Dir dir(g_globals.outputDir.str()); createSubDirs(dir); - HtmlEscaper htmlEsc; - ctx->setEscapeIntf(Config_getString(HTML_FILE_EXTENSION),&htmlEsc); - HtmlSpaceless spl; - ctx->setSpacelessIntf(&spl); + ctx->setEscapeIntf(Config_getString(HTML_FILE_EXTENSION),std::make_unique<HtmlEscaper>()); + ctx->setSpacelessIntf(std::make_unique<HtmlSpaceless>()); ctx->setOutputDirectory(g_globals.outputDir); TextStream ts; - tpl->render(ts,ctx); - e.unload(tpl); + tpl->render(ts,ctx.get()); } + e->unload(tpl); } // TODO: clean index before each run... @@ -11066,8 +9115,8 @@ void generateOutputViaTemplate() //if (Config_getBool(GENERATE_LATEX)) if (0) { // render LaTeX output - e.setTemplateDir("templates/latex"); // TODO: make template part user configurable - Template *tpl = e.loadByName("latexlayout.tpl",1); + e->setTemplateDir("templates/latex"); // TODO: make template part user configurable + Template *tpl = e->loadByName("latexlayout.tpl",1); if (tpl) { g_globals.outputFormat = ContextOutputFormat_Latex; @@ -11075,29 +9124,16 @@ void generateOutputViaTemplate() g_globals.outputDir = Config_getString(LATEX_OUTPUT); Dir dir(g_globals.outputDir.str()); createSubDirs(dir); - LatexEscaper latexEsc; - ctx->setEscapeIntf(".tex",&latexEsc); - LatexSpaceless spl; - ctx->setSpacelessIntf(&spl); + ctx->setEscapeIntf(".tex",std::make_unique<LatexEscaper>()); + ctx->setSpacelessIntf(std::make_unique<LatexSpaceless>()); ctx->setOutputDirectory(g_globals.outputDir); TextStream ts; - tpl->render(ts,ctx); - e.unload(tpl); + tpl->render(ts,ctx.get()); } + e->unload(tpl); } - - // clear all cached data in Definition objects. - for (const auto &kv : *Doxygen::symbolMap) - { - kv.second->setCookie(0); - } - - e.destroyContext(ctx); } } -#if DEBUG_REF // should be 0, i.e. all objects are deleted - printf("==== total ref count %d\n",RefCountedContext::s_totalCount); -#endif } void generateTemplateFiles(const QCString &templateDir) diff --git a/src/context.h b/src/context.h index 8621c5f..fa7ab97 100644 --- a/src/context.h +++ b/src/context.h @@ -21,6 +21,7 @@ #include "classdef.h" #include "searchindex.h" #include "memberlist.h" +#include "dotgfxhierarchytable.h" class Definition; @@ -60,7 +61,6 @@ struct Argument; class ArgumentList; class MemberInfo; class DotNode; -class DotGfxHierarchyTable; class MemberGroup; class MemberGroupList; @@ -69,484 +69,411 @@ class MemberVector; //---------------------------------------------------- -#define DEBUG_REF 0 - -/** @brief Helper class to support reference counting */ -#if DEBUG_REF -class RefCountedContext +class ConfigContext : public TemplateStructIntf { public: - RefCountedContext(const char *className) : m_refCount(0) - { - m_className=className; - m_insideRelease = FALSE; - } - virtual ~RefCountedContext() - { - if (!m_insideRelease) abort(); - } - int addRef() - { - ++s_totalCount; - printf("%p:%s::addRef()=%d\n",this,qPrint(m_className),m_refCount); - return ++m_refCount; - } - int release() - { - --s_totalCount; - printf("%p:%s::release()=%d\n",this,qPrint(m_className),m_refCount-1); - int count = --m_refCount; - if (count<=0) - { - m_insideRelease=TRUE; - delete this; - } - return count; - } - private: - int m_refCount; - QCString m_className; - bool m_insideRelease; - public: - static int s_totalCount; -}; - -#else // release version - -class RefCountedContext -{ - public: - RefCountedContext(const char *) : m_refCount(0) {} - virtual ~RefCountedContext() {} - int addRef() { return ++m_refCount; } - int release() - { - int count = --m_refCount; - if (count<=0) - { - delete this; - } - return count; - } - private: - int m_refCount; -}; -#endif - - -//---------------------------------------------------- - -class ConfigContext : public RefCountedContext, public TemplateStructIntf -{ - public: - static ConfigContext *alloc() { return new ConfigContext; } + static TemplateStructIntfPtr alloc() + { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<ConfigContext>()); } // TemplateStructIntf methods virtual TemplateVariant get(const QCString &name) const; virtual StringVector fields() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } - private: ConfigContext(); - ~ConfigContext(); + virtual ~ConfigContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class DoxygenContext : public RefCountedContext, public TemplateStructIntf +class DoxygenContext : public TemplateStructIntf { public: - static DoxygenContext *alloc() { return new DoxygenContext; } + static TemplateStructIntfPtr alloc() + { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<DoxygenContext>()); } // TemplateStructIntf methods virtual TemplateVariant get(const QCString &name) const; virtual StringVector fields() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } - private: DoxygenContext(); - ~DoxygenContext(); + virtual ~DoxygenContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class TranslateContext : public RefCountedContext, public TemplateStructIntf +class TranslateContext : public TemplateStructIntf { public: - static TranslateContext *alloc() { return new TranslateContext; } + static TemplateStructIntfPtr alloc() + { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<TranslateContext>()); } // TemplateStructIntf methods virtual TemplateVariant get(const QCString &name) const; virtual StringVector fields() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } - private: TranslateContext(); - ~TranslateContext(); + virtual ~TranslateContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class UsedFilesContext : public RefCountedContext, public TemplateListIntf +class UsedFilesContext : public TemplateListIntf { public: - static UsedFilesContext *alloc(const ClassDef *cd) { return new UsedFilesContext(cd); } + static TemplateListIntfPtr alloc(const ClassDef *cd) + { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<UsedFilesContext>(cd)); } // TemplateListIntf virtual uint count() const; virtual TemplateVariant at(uint index) const; - virtual TemplateListIntf::ConstIterator *createIterator() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } + virtual TemplateListIntf::ConstIteratorPtr createIterator() const; void addFile(const FileDef *fd); + UsedFilesContext(const ClassDef *cd); + virtual ~UsedFilesContext(); private: - UsedFilesContext(const ClassDef *cd); - ~UsedFilesContext(); class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class IncludeInfoContext : public RefCountedContext, public TemplateStructIntf +class IncludeInfoContext : public TemplateStructIntf { public: - static IncludeInfoContext *alloc(const IncludeInfo *info,SrcLangExt lang) - { return new IncludeInfoContext(info,lang); } + static TemplateStructIntfPtr alloc(const IncludeInfo *info,SrcLangExt lang) + { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<IncludeInfoContext>(info,lang)); } // TemplateStructIntf methods virtual TemplateVariant get(const QCString &name) const; virtual StringVector fields() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } - private: IncludeInfoContext(const IncludeInfo *,SrcLangExt lang); - ~IncludeInfoContext(); + virtual ~IncludeInfoContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class IncludeInfoListContext : public RefCountedContext, public TemplateListIntf +class IncludeInfoListContext : public TemplateListIntf { public: - static IncludeInfoListContext *alloc(const IncludeInfoList &list,SrcLangExt lang) - { return new IncludeInfoListContext(list,lang); } + static TemplateListIntfPtr alloc(const IncludeInfoList &list,SrcLangExt lang) + { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<IncludeInfoListContext>(list,lang)); } // TemplateListIntf virtual uint count() const; virtual TemplateVariant at(uint index) const; - virtual TemplateListIntf::ConstIterator *createIterator() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } + virtual TemplateListIntf::ConstIteratorPtr createIterator() const; - private: IncludeInfoListContext(const IncludeInfoList &list,SrcLangExt lang); - ~IncludeInfoListContext(); + virtual ~IncludeInfoListContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class ClassContext : public RefCountedContext, public TemplateStructIntf +class ClassContext : public TemplateStructIntf { public: - static ClassContext *alloc(const ClassDef *cd) { return new ClassContext(cd); } + static TemplateStructIntfPtr alloc(const ClassDef *cd) + { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<ClassContext>(cd)); } // TemplateStructIntf methods virtual TemplateVariant get(const QCString &name) const; virtual StringVector fields() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } - private: ClassContext(const ClassDef *); - ~ClassContext(); + virtual ~ClassContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class ConceptContext : public RefCountedContext, public TemplateStructIntf +class ConceptContext : public TemplateStructIntf { public: - static ConceptContext *alloc(const ConceptDef *cd) { return new ConceptContext(cd); } + static TemplateStructIntfPtr alloc(const ConceptDef *cd) + { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<ConceptContext>(cd)); } // TemplateStructIntf methods virtual TemplateVariant get(const QCString &name) const; virtual StringVector fields() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } - private: ConceptContext(const ConceptDef *); - ~ConceptContext(); + virtual ~ConceptContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class NamespaceContext : public RefCountedContext, public TemplateStructIntf +class NamespaceContext : public TemplateStructIntf { public: - static NamespaceContext *alloc(const NamespaceDef *nd) { return new NamespaceContext(nd); } + static TemplateStructIntfPtr alloc(const NamespaceDef *nd) + { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<NamespaceContext>(nd)); } // TemplateStructIntf methods virtual TemplateVariant get(const QCString &name) const; virtual StringVector fields() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } - private: NamespaceContext(const NamespaceDef *); - ~NamespaceContext(); + virtual ~NamespaceContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class FileContext : public RefCountedContext, public TemplateStructIntf +class FileContext : public TemplateStructIntf { public: - static FileContext *alloc(const FileDef *fd) { return new FileContext(fd); } + static TemplateStructIntfPtr alloc(const FileDef *fd) + { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<FileContext>(fd)); } // TemplateStructIntf methods virtual TemplateVariant get(const QCString &name) const; virtual StringVector fields() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } - private: FileContext(const FileDef *); - ~FileContext(); + virtual ~FileContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class DirContext : public RefCountedContext, public TemplateStructIntf +class DirContext : public TemplateStructIntf { public: - static DirContext *alloc(const DirDef *dd) { return new DirContext(dd); } + static TemplateStructIntfPtr alloc(const DirDef *dd) + { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<DirContext>(dd)); } // TemplateStructIntf methods virtual TemplateVariant get(const QCString &name) const; virtual StringVector fields() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } - private: DirContext(const DirDef *); - ~DirContext(); + virtual ~DirContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class PageContext : public RefCountedContext, public TemplateStructIntf +class PageContext : public TemplateStructIntf { public: - static PageContext *alloc(const PageDef *pd,bool isMainPage,bool isExample) { return new PageContext(pd,isMainPage,isExample); } + static TemplateStructIntfPtr alloc(const PageDef *pd,bool isMainPage,bool isExample) + { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<PageContext>(pd,isMainPage,isExample)); } // TemplateStructIntf methods virtual TemplateVariant get(const QCString &name) const; virtual StringVector fields() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } - private: PageContext(const PageDef *,bool isMainPage,bool isExample); - ~PageContext(); + virtual ~PageContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class MemberContext : public RefCountedContext, public TemplateStructIntf +class MemberContext : public TemplateStructIntf { public: - static MemberContext *alloc(const MemberDef *md) { return new MemberContext(md); } + static TemplateStructIntfPtr alloc(const MemberDef *md) + { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<MemberContext>(md)); } // TemplateStructIntf methods virtual TemplateVariant get(const QCString &name) const; virtual StringVector fields() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } - private: MemberContext(const MemberDef *); - ~MemberContext(); + virtual ~MemberContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class ModuleContext : public RefCountedContext, public TemplateStructIntf +class ModuleContext : public TemplateStructIntf { public: - static ModuleContext *alloc(const GroupDef *gd) { return new ModuleContext(gd); } + static TemplateStructIntfPtr alloc(const GroupDef *gd) + { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<ModuleContext>(gd)); } // TemplateStructIntf methods virtual TemplateVariant get(const QCString &name) const; virtual StringVector fields() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } - private: ModuleContext(const GroupDef *); - ~ModuleContext(); + virtual ~ModuleContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class ClassListContext : public RefCountedContext, public TemplateListIntf +class ClassListContext : public TemplateListIntf { public: - static ClassListContext *alloc() { return new ClassListContext; } + static TemplateListIntfPtr alloc() + { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<ClassListContext>()); } // TemplateListIntf virtual uint count() const; virtual TemplateVariant at(uint index) const; - virtual TemplateListIntf::ConstIterator *createIterator() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } + virtual TemplateListIntf::ConstIteratorPtr createIterator() const; - private: ClassListContext(); - ~ClassListContext(); + virtual ~ClassListContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class ClassIndexContext : public RefCountedContext, public TemplateStructIntf +class ClassIndexContext : public TemplateStructIntf { public: - static ClassIndexContext *alloc() { return new ClassIndexContext; } + static TemplateStructIntfPtr alloc() + { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<ClassIndexContext>()); } // TemplateStructIntf methods virtual TemplateVariant get(const QCString &name) const; virtual StringVector fields() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } - private: ClassIndexContext(); - ~ClassIndexContext(); + virtual ~ClassIndexContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class InheritanceGraphContext : public RefCountedContext, public TemplateStructIntf +class InheritanceGraphContext : public TemplateStructIntf { public: - static InheritanceGraphContext *alloc(DotGfxHierarchyTable *hierarchy,DotNode *n,int id) - { return new InheritanceGraphContext(hierarchy,n,id); } + static TemplateStructIntfPtr alloc(DotGfxHierarchyTablePtr hierarchy,DotNode *n,int id) + { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<InheritanceGraphContext>(hierarchy,n,id)); } // TemplateStructIntf methods virtual TemplateVariant get(const QCString &name) const; virtual StringVector fields() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } + + InheritanceGraphContext(DotGfxHierarchyTablePtr hierarchy,DotNode *n,int id); + virtual ~InheritanceGraphContext(); private: - InheritanceGraphContext(DotGfxHierarchyTable *hierarchy,DotNode *n,int id); - ~InheritanceGraphContext(); class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class ClassInheritanceNodeContext : public RefCountedContext, public TemplateStructIntf +class ClassInheritanceNodeContext : public TemplateStructIntf { public: - static ClassInheritanceNodeContext *alloc(const ClassDef *cd) - { return new ClassInheritanceNodeContext(cd); } + static TemplateStructIntfPtr alloc(const ClassDef *cd) + { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<ClassInheritanceNodeContext>(cd)); } // TemplateStructIntf methods virtual TemplateVariant get(const QCString &name) const; virtual StringVector fields() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } void addChildren(const BaseClassList &bcl,bool hideSuper); + ClassInheritanceNodeContext(const ClassDef *); + virtual ~ClassInheritanceNodeContext(); private: - ClassInheritanceNodeContext(const ClassDef *); - ~ClassInheritanceNodeContext(); class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class ClassInheritanceContext : public RefCountedContext, public TemplateListIntf +class ClassInheritanceContext : public TemplateListIntf { public: - static ClassInheritanceContext *alloc() { return new ClassInheritanceContext; } + static TemplateListIntfPtr alloc() + { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<ClassInheritanceContext>()); } // TemplateListIntf virtual uint count() const; virtual TemplateVariant at(uint index) const; - virtual TemplateListIntf::ConstIterator *createIterator() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } + virtual TemplateListIntf::ConstIteratorPtr createIterator() const; - private: ClassInheritanceContext(); - ~ClassInheritanceContext(); + virtual ~ClassInheritanceContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class ClassHierarchyContext : public RefCountedContext, public TemplateStructIntf +class ClassHierarchyContext : public TemplateStructIntf { public: - static ClassHierarchyContext *alloc() { return new ClassHierarchyContext; } + static TemplateStructIntfPtr alloc() + { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<ClassHierarchyContext>()); } // TemplateStructIntf methods virtual TemplateVariant get(const QCString &name) const; virtual StringVector fields() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } - private: ClassHierarchyContext(); - ~ClassHierarchyContext(); + virtual ~ClassHierarchyContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- @@ -563,53 +490,50 @@ enum class ContextTreeType Example // ExampleTreeContext }; -class NestingNodeContext : public RefCountedContext, public TemplateStructIntf +class NestingNodeContext : public TemplateStructIntf { public: - static NestingNodeContext *alloc(const NestingNodeContext *parent,ContextTreeType type, + static TemplateStructIntfPtr alloc(const NestingNodeContext *parent,ContextTreeType type, const Definition *def, int index,int level, bool addClasses,bool addConcepts, bool inherit,bool hideSuper, ClassDefSet &visitedClasses) - { return new NestingNodeContext(parent,type,def,index,level,addClasses,addConcepts, - inherit,hideSuper,visitedClasses); } + { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<NestingNodeContext> + (parent,type,def,index,level,addClasses,addConcepts,inherit,hideSuper,visitedClasses)); } QCString id() const; // TemplateStructIntf methods virtual TemplateVariant get(const QCString &name) const; virtual StringVector fields() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } - private: NestingNodeContext(const NestingNodeContext *parent, ContextTreeType type, const Definition *,int index,int level, bool addClasses,bool addConcepts, bool inherit,bool hideSuper, ClassDefSet &visitedClasses); - ~NestingNodeContext(); + virtual ~NestingNodeContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class NestingContext : public RefCountedContext, public TemplateListIntf +class NestingContext : public TemplateListIntf { public: - static NestingContext *alloc(const NestingNodeContext *parent,ContextTreeType type,int level) - { return new NestingContext(parent,type,level); } + static TemplateListIntfPtr alloc(const NestingNodeContext *parent,ContextTreeType type,int level) + { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<NestingContext>(parent,type,level)); } // TemplateListIntf virtual uint count() const; virtual TemplateVariant at(uint index) const; - virtual TemplateListIntf::ConstIterator *createIterator() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } + virtual TemplateListIntf::ConstIteratorPtr createIterator() const; void addNamespaces(const NamespaceLinkedMap &nsLinkedMap,bool rootOnly,bool addClasses,bool addConcepts,ClassDefSet &visitedClasses); void addNamespaces(const NamespaceLinkedRefMap &nsLinkedMap,bool rootOnly,bool addClasses,bool addConcepts,ClassDefSet &visitedClasses); @@ -629,857 +553,842 @@ class NestingContext : public RefCountedContext, public TemplateListIntf void addDerivedClasses(const BaseClassList &bcl,bool hideSuper,ClassDefSet &visitedClasses); void addMembers(const MemberVector &mv,ClassDefSet &visitedClasses); - private: NestingContext(const NestingNodeContext *parent,ContextTreeType type,int level); - ~NestingContext(); + virtual ~NestingContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class ClassTreeContext : public RefCountedContext, public TemplateStructIntf +class ClassTreeContext : public TemplateStructIntf { public: - static ClassTreeContext *alloc() { return new ClassTreeContext; } + static TemplateStructIntfPtr alloc() + { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<ClassTreeContext>()); } // TemplateStructIntf methods virtual TemplateVariant get(const QCString &name) const; virtual StringVector fields() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } - private: ClassTreeContext(); - ~ClassTreeContext(); + virtual ~ClassTreeContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class ConceptListContext : public RefCountedContext, public TemplateListIntf +class ConceptListContext : public TemplateListIntf { public: - static ConceptListContext *alloc() { return new ConceptListContext; } + static TemplateListIntfPtr alloc() + { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<ConceptListContext>()); } // TemplateListIntf virtual uint count() const; virtual TemplateVariant at(uint index) const; - virtual TemplateListIntf::ConstIterator *createIterator() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } + virtual TemplateListIntf::ConstIteratorPtr createIterator() const; - private: ConceptListContext(); - ~ConceptListContext(); + virtual ~ConceptListContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class NamespaceListContext : public RefCountedContext, public TemplateListIntf +class NamespaceListContext : public TemplateListIntf { public: - static NamespaceListContext *alloc() { return new NamespaceListContext; } + static TemplateListIntfPtr alloc() + { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<NamespaceListContext>()); } // TemplateListIntf virtual uint count() const; virtual TemplateVariant at(uint index) const; - virtual TemplateListIntf::ConstIterator *createIterator() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } + virtual TemplateListIntf::ConstIteratorPtr createIterator() const; - private: NamespaceListContext(); - ~NamespaceListContext(); + virtual ~NamespaceListContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class NamespaceTreeContext : public RefCountedContext, public TemplateStructIntf +class NamespaceTreeContext : public TemplateStructIntf { public: - static NamespaceTreeContext *alloc() { return new NamespaceTreeContext; } + static TemplateStructIntfPtr alloc() + { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<NamespaceTreeContext>()); } // TemplateStructIntf methods virtual TemplateVariant get(const QCString &name) const; virtual StringVector fields() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } - private: NamespaceTreeContext(); - ~NamespaceTreeContext(); + virtual ~NamespaceTreeContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class DirListContext : public RefCountedContext, public TemplateListIntf +class DirListContext : public TemplateListIntf { public: - static DirListContext *alloc() { return new DirListContext; } + static TemplateListIntfPtr alloc() + { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<DirListContext>()); } // TemplateListIntf virtual uint count() const; virtual TemplateVariant at(uint index) const; - virtual TemplateListIntf::ConstIterator *createIterator() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } + virtual TemplateListIntf::ConstIteratorPtr createIterator() const; - private: DirListContext(); - ~DirListContext(); + virtual ~DirListContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class FileListContext : public RefCountedContext, public TemplateListIntf +class FileListContext : public TemplateListIntf { public: - static FileListContext *alloc() { return new FileListContext; } + static TemplateListIntfPtr alloc() + { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<FileListContext>()); } // TemplateListIntf virtual uint count() const; virtual TemplateVariant at(uint index) const; - virtual TemplateListIntf::ConstIterator *createIterator() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } + virtual TemplateListIntf::ConstIteratorPtr createIterator() const; - private: FileListContext(); - ~FileListContext(); + virtual ~FileListContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class FileTreeContext : public RefCountedContext, public TemplateStructIntf +class FileTreeContext : public TemplateStructIntf { public: - static FileTreeContext *alloc() { return new FileTreeContext; } + static TemplateStructIntfPtr alloc() + { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<FileTreeContext>()); } // TemplateStructIntf methods virtual TemplateVariant get(const QCString &name) const; virtual StringVector fields() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } - private: FileTreeContext(); - ~FileTreeContext(); + virtual ~FileTreeContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class PageListContext : public RefCountedContext, public TemplateListIntf +class PageListContext : public TemplateListIntf { public: - static PageListContext *alloc(const PageLinkedMap &pages) { return new PageListContext(pages); } + static TemplateListIntfPtr alloc(const PageLinkedMap &pages) + { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<PageListContext>(pages)); } // TemplateListIntf methods virtual uint count() const; virtual TemplateVariant at(uint index) const; - virtual TemplateListIntf::ConstIterator *createIterator() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } + virtual TemplateListIntf::ConstIteratorPtr createIterator() const; void addPages(const PageLinkedMap &pages); - private: PageListContext(const PageLinkedMap &pages); - ~PageListContext(); + virtual ~PageListContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class PageTreeContext : public RefCountedContext, public TemplateStructIntf +class PageTreeContext : public TemplateStructIntf { public: - static PageTreeContext *alloc(const PageLinkedMap &pages) { return new PageTreeContext(pages); } + static TemplateStructIntfPtr alloc(const PageLinkedMap &pages) + { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<PageTreeContext>(pages)); } // TemplateStructIntf methods virtual TemplateVariant get(const QCString &name) const; virtual StringVector fields() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } - private: PageTreeContext(const PageLinkedMap &pages); - ~PageTreeContext(); + virtual ~PageTreeContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class ModuleNodeContext : public RefCountedContext, public TemplateStructIntf +class ModuleNodeContext : public TemplateStructIntf { public: - static ModuleNodeContext *alloc(const GroupDef *gd) { return new ModuleNodeContext(gd); } + static TemplateStructIntfPtr alloc(const GroupDef *gd) + { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<ModuleNodeContext>(gd)); } // TemplateStructIntf methods virtual TemplateVariant get(const QCString &name) const; virtual StringVector fields() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } - private: ModuleNodeContext(const GroupDef *); - ~ModuleNodeContext(); + virtual ~ModuleNodeContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class ModuleListContext : public RefCountedContext, public TemplateListIntf +class ModuleListContext : public TemplateListIntf { public: - static ModuleListContext *alloc() { return new ModuleListContext(); } + static TemplateListIntfPtr alloc() + { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<ModuleListContext>()); } // TemplateListIntf virtual uint count() const; virtual TemplateVariant at(uint index) const; - virtual TemplateListIntf::ConstIterator *createIterator() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } + virtual TemplateListIntf::ConstIteratorPtr createIterator() const; void addModules(const GroupLinkedMap &); void addModules(const GroupList &); - private: ModuleListContext(); - ~ModuleListContext(); + virtual ~ModuleListContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class ConceptTreeContext : public RefCountedContext, public TemplateStructIntf +class ConceptTreeContext : public TemplateStructIntf { public: - static ConceptTreeContext *alloc() { return new ConceptTreeContext(); } + static TemplateStructIntfPtr alloc() + { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<ConceptTreeContext>()); } // TemplateStructIntf methods virtual TemplateVariant get(const QCString &name) const; virtual StringVector fields() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } - private: ConceptTreeContext(); - ~ConceptTreeContext(); + virtual ~ConceptTreeContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class ModuleTreeContext : public RefCountedContext, public TemplateStructIntf +class ModuleTreeContext : public TemplateStructIntf { public: - static ModuleTreeContext *alloc() { return new ModuleTreeContext(); } + static TemplateStructIntfPtr alloc() + { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<ModuleTreeContext>()); } // TemplateStructIntf methods virtual TemplateVariant get(const QCString &name) const; virtual StringVector fields() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } - private: ModuleTreeContext(); - ~ModuleTreeContext(); + virtual ~ModuleTreeContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class ExampleListContext : public RefCountedContext, public TemplateListIntf +class ExampleListContext : public TemplateListIntf { public: - static ExampleListContext *alloc() { return new ExampleListContext; } + static TemplateListIntfPtr alloc() + { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<ExampleListContext>()); } // TemplateListIntf methods virtual uint count() const; virtual TemplateVariant at(uint index) const; - virtual TemplateListIntf::ConstIterator *createIterator() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } + virtual TemplateListIntf::ConstIteratorPtr createIterator() const; - private: ExampleListContext(); - ~ExampleListContext(); + virtual ~ExampleListContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class ExampleTreeContext : public RefCountedContext, public TemplateStructIntf +class ExampleTreeContext : public TemplateStructIntf { public: - static ExampleTreeContext *alloc() { return new ExampleTreeContext; } + static TemplateStructIntfPtr alloc() + { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<ExampleTreeContext>()); } // TemplateStructIntf methods virtual TemplateVariant get(const QCString &name) const; virtual StringVector fields() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } - private: ExampleTreeContext(); - ~ExampleTreeContext(); + virtual ~ExampleTreeContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class GlobalsIndexContext : public RefCountedContext, public TemplateStructIntf +class GlobalsIndexContext : public TemplateStructIntf { public: - static GlobalsIndexContext *alloc() { return new GlobalsIndexContext(); } + static TemplateStructIntfPtr alloc() + { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<GlobalsIndexContext>()); } // TemplateStructIntf methods virtual TemplateVariant get(const QCString &name) const; virtual StringVector fields() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } - private: GlobalsIndexContext(); - ~GlobalsIndexContext(); + virtual ~GlobalsIndexContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class ClassMembersIndexContext : public RefCountedContext, public TemplateStructIntf +class ClassMembersIndexContext : public TemplateStructIntf { public: - static ClassMembersIndexContext *alloc() { return new ClassMembersIndexContext(); } + static TemplateStructIntfPtr alloc() + { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<ClassMembersIndexContext>()); } // TemplateStructIntf methods virtual TemplateVariant get(const QCString &name) const; virtual StringVector fields() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } - private: ClassMembersIndexContext(); - ~ClassMembersIndexContext(); + virtual ~ClassMembersIndexContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class NamespaceMembersIndexContext : public RefCountedContext, public TemplateStructIntf +class NamespaceMembersIndexContext : public TemplateStructIntf { public: - static NamespaceMembersIndexContext *alloc() { return new NamespaceMembersIndexContext(); } + static TemplateStructIntfPtr alloc() + { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<NamespaceMembersIndexContext>()); } // TemplateStructIntf methods virtual TemplateVariant get(const QCString &name) const; virtual StringVector fields() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } - private: NamespaceMembersIndexContext(); - ~NamespaceMembersIndexContext(); + virtual ~NamespaceMembersIndexContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class NavPathElemContext : public RefCountedContext, public TemplateStructIntf +class NavPathElemContext : public TemplateStructIntf { public: - static NavPathElemContext *alloc(const Definition *def) { return new NavPathElemContext(def); } + static TemplateStructIntfPtr alloc(const Definition *def) + { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<NavPathElemContext>(def)); } // TemplateStructIntf methods virtual TemplateVariant get(const QCString &name) const; virtual StringVector fields() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } - private: NavPathElemContext(const Definition *def); - ~NavPathElemContext(); + virtual ~NavPathElemContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class InheritanceNodeContext : public RefCountedContext, public TemplateStructIntf +class InheritanceNodeContext : public TemplateStructIntf { public: - static InheritanceNodeContext *alloc(const ClassDef *cd,const QCString &name) - { return new InheritanceNodeContext(cd,name); } + static TemplateStructIntfPtr alloc(const ClassDef *cd,const QCString &name) + { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<InheritanceNodeContext>(cd,name)); } // TemplateStructIntf methods virtual TemplateVariant get(const QCString &name) const; virtual StringVector fields() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } - private: InheritanceNodeContext(const ClassDef *cd,const QCString &name); - ~InheritanceNodeContext(); + virtual ~InheritanceNodeContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class InheritanceListContext : public RefCountedContext, public TemplateListIntf +class InheritanceListContext : public TemplateListIntf { public: - static InheritanceListContext *alloc(const BaseClassList &list,bool baseClasses) - { return new InheritanceListContext(list,baseClasses); } + static TemplateListIntfPtr alloc(const BaseClassList &list,bool baseClasses) + { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<InheritanceListContext>(list,baseClasses)); } // TemplateListIntf virtual uint count() const; virtual TemplateVariant at(uint index) const; - virtual TemplateListIntf::ConstIterator *createIterator() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } + virtual TemplateListIntf::ConstIteratorPtr createIterator() const; - private: InheritanceListContext(const BaseClassList &list,bool baseClasses); - ~InheritanceListContext(); + virtual ~InheritanceListContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class MemberListContext : public RefCountedContext, public TemplateListIntf +class MemberListContext : public TemplateListIntf { public: - static MemberListContext *alloc() - { return new MemberListContext; } - static MemberListContext *alloc(const MemberList *ml) - { return new MemberListContext(ml); } - static MemberListContext *alloc(const MemberVector &ml) - { return new MemberListContext(ml); } + static TemplateListIntfPtr alloc() + { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<MemberListContext>()); } + static TemplateListIntfPtr alloc(const MemberList *ml) + { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<MemberListContext>(ml)); } + static TemplateListIntfPtr alloc(const MemberVector &ml) + { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<MemberListContext>(ml)); } // TemplateListIntf virtual uint count() const; virtual TemplateVariant at(uint index) const; - virtual TemplateListIntf::ConstIterator *createIterator() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } + virtual TemplateListIntf::ConstIteratorPtr createIterator() const; - private: MemberListContext(); MemberListContext(const MemberList *ml); MemberListContext(const MemberVector &ml); - ~MemberListContext(); + virtual ~MemberListContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class MemberGroupInfoContext : public RefCountedContext, public TemplateStructIntf +class MemberGroupInfoContext : public TemplateStructIntf { public: - static MemberGroupInfoContext *alloc(const Definition *def,const QCString &relPath,const MemberGroup *mg) - { return new MemberGroupInfoContext(def,relPath,mg); } + static TemplateStructIntfPtr alloc(const Definition *def,const QCString &relPath,const MemberGroup *mg) + { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<MemberGroupInfoContext>(def,relPath,mg)); } // TemplateStructIntf methods virtual TemplateVariant get(const QCString &name) const; virtual StringVector fields() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } - private: MemberGroupInfoContext(const Definition *def,const QCString &relPath,const MemberGroup *mg); - ~MemberGroupInfoContext(); + virtual ~MemberGroupInfoContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class MemberGroupListContext : public RefCountedContext, public TemplateListIntf +class MemberGroupListContext : public TemplateListIntf { public: - static MemberGroupListContext *alloc() - { return new MemberGroupListContext; } - static MemberGroupListContext *alloc(const Definition *def,const QCString &relPath,const MemberGroupRefList &list) - { return new MemberGroupListContext(def,relPath,list); } - static MemberGroupListContext *alloc(const Definition *def,const QCString &relPath,const MemberGroupList &list,bool subGrouping) - { return new MemberGroupListContext(def,relPath,list,subGrouping); } + static TemplateListIntfPtr alloc() + { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<MemberGroupListContext>()); } + static TemplateListIntfPtr alloc(const Definition *def,const QCString &relPath,const MemberGroupRefList &list) + { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<MemberGroupListContext>(def,relPath,list)); } + static TemplateListIntfPtr alloc(const Definition *def,const QCString &relPath,const MemberGroupList &list,bool subGrouping) + { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<MemberGroupListContext>(def,relPath,list,subGrouping)); } // TemplateListIntf virtual uint count() const; virtual TemplateVariant at(uint index) const; - virtual TemplateListIntf::ConstIterator *createIterator() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } + virtual TemplateListIntf::ConstIteratorPtr createIterator() const; - private: MemberGroupListContext(); MemberGroupListContext(const Definition *def,const QCString &relPath,const MemberGroupRefList &list); MemberGroupListContext(const Definition *def,const QCString &relPath,const MemberGroupList &list,bool subGrouping); - ~MemberGroupListContext(); + virtual ~MemberGroupListContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class MemberListInfoContext : public RefCountedContext, public TemplateStructIntf +class MemberListInfoContext : public TemplateStructIntf { public: - static MemberListInfoContext *alloc(const Definition *def,const QCString &relPath, + static TemplateStructIntfPtr alloc(const Definition *def,const QCString &relPath, const MemberList *ml,const QCString &title, const QCString &subtitle=QCString()) - { return new MemberListInfoContext(def,relPath,ml,title,subtitle); } + { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<MemberListInfoContext>(def,relPath,ml,title,subtitle)); } // TemplateStructIntf methods virtual TemplateVariant get(const QCString &name) const; virtual StringVector fields() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } - private: MemberListInfoContext(const Definition *def,const QCString &relPath, const MemberList *ml,const QCString &title, const QCString &subtitle=QCString()); - ~MemberListInfoContext(); + virtual ~MemberListInfoContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class MemberInfoContext : public RefCountedContext, public TemplateStructIntf +class MemberInfoContext : public TemplateStructIntf { public: - static MemberInfoContext *alloc(const MemberInfo *mi) { return new MemberInfoContext(mi); } + static TemplateStructIntfPtr alloc(const MemberInfo *mi) + { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<MemberInfoContext>(mi)); } // TemplateStructIntf methods virtual TemplateVariant get(const QCString &name) const; virtual StringVector fields() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } - private: MemberInfoContext(const MemberInfo *mi); - ~MemberInfoContext(); + virtual ~MemberInfoContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class InheritedMemberInfoContext : public RefCountedContext, public TemplateStructIntf +class InheritedMemberInfoContext : public TemplateStructIntf { public: - static InheritedMemberInfoContext *alloc(const ClassDef *cd,const MemberList *ml,const QCString &title) - { return new InheritedMemberInfoContext(cd,ml,title); } + static TemplateStructIntfPtr alloc(const ClassDef *cd,std::unique_ptr<MemberList> &&ml,const QCString &title) + { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<InheritedMemberInfoContext>(cd,std::move(ml),title)); } // TemplateStructIntf methods virtual TemplateVariant get(const QCString &name) const; virtual StringVector fields() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } + + InheritedMemberInfoContext(const ClassDef *cd,std::unique_ptr<MemberList> &&ml,const QCString &title); + virtual ~InheritedMemberInfoContext(); private: - InheritedMemberInfoContext(const ClassDef *cd,const MemberList *ml,const QCString &title); - ~InheritedMemberInfoContext(); class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class InheritedMemberInfoListContext : public RefCountedContext, public TemplateListIntf +class InheritedMemberInfoListContext : public TemplateListIntf { public: - static InheritedMemberInfoListContext *alloc() { return new InheritedMemberInfoListContext; } + static TemplateListIntfPtr alloc() + { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<InheritedMemberInfoListContext>()); } void addMemberList(const ClassDef *cd,MemberListType lt,const QCString &title,bool additionalList=TRUE); // TemplateListIntf virtual uint count() const; virtual TemplateVariant at(uint index) const; - virtual TemplateListIntf::ConstIterator *createIterator() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } + virtual TemplateListIntf::ConstIteratorPtr createIterator() const; - private: InheritedMemberInfoListContext(); - ~InheritedMemberInfoListContext(); + virtual ~InheritedMemberInfoListContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class AllMembersListContext : public RefCountedContext, public TemplateListIntf +class AllMembersListContext : public TemplateListIntf { public: - static AllMembersListContext *alloc(const MemberNameInfoLinkedMap &ml) - { return new AllMembersListContext(ml); } + static TemplateListIntfPtr alloc(const MemberNameInfoLinkedMap &ml) + { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<AllMembersListContext>(ml)); } // TemplateListIntf virtual uint count() const; virtual TemplateVariant at(uint index) const; - virtual TemplateListIntf::ConstIterator *createIterator() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } + virtual TemplateListIntf::ConstIteratorPtr createIterator() const; - private: AllMembersListContext(const MemberNameInfoLinkedMap &ml); - ~AllMembersListContext(); + virtual ~AllMembersListContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class ArgumentContext : public RefCountedContext, public TemplateStructIntf +class ArgumentContext : public TemplateStructIntf { public: - static ArgumentContext *alloc(const Argument &arg,const Definition *def,const QCString &relPath) - { return new ArgumentContext(arg,def,relPath); } + static TemplateStructIntfPtr alloc(const Argument &arg,const Definition *def,const QCString &relPath) + { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<ArgumentContext>(arg,def,relPath)); } // TemplateStructIntf methods virtual TemplateVariant get(const QCString &name) const; virtual StringVector fields() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } - private: ArgumentContext(const Argument &arg,const Definition *def,const QCString &relPath); - ~ArgumentContext(); + virtual ~ArgumentContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class ArgumentListContext : public RefCountedContext, public TemplateListIntf +class ArgumentListContext : public TemplateListIntf { public: - static ArgumentListContext *alloc() { return new ArgumentListContext; } - static ArgumentListContext *alloc(const ArgumentList &al,const Definition *def,const QCString &relPath) - { return new ArgumentListContext(al,def,relPath); } + static TemplateListIntfPtr alloc() + { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<ArgumentListContext>()); } + static TemplateListIntfPtr alloc(const ArgumentList &al,const Definition *def,const QCString &relPath) + { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<ArgumentListContext>(al,def,relPath)); } // TemplateListIntf virtual uint count() const; virtual TemplateVariant at(uint index) const; - virtual TemplateListIntf::ConstIterator *createIterator() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } + virtual TemplateListIntf::ConstIteratorPtr createIterator() const; - private: ArgumentListContext(); ArgumentListContext(const ArgumentList &al,const Definition *def,const QCString &relPath); - ~ArgumentListContext(); + virtual ~ArgumentListContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class SymbolContext : public RefCountedContext, public TemplateStructIntf +class SymbolContext : public TemplateStructIntf { public: - static SymbolContext *alloc(const Definition *def,const Definition *prev,const Definition *next) - { return new SymbolContext(def,prev,next); } + static TemplateStructIntfPtr alloc(const Definition *def,const Definition *prev,const Definition *next) + { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<SymbolContext>(def,prev,next)); } // TemplateStructIntf methods virtual TemplateVariant get(const QCString &name) const; virtual StringVector fields() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } - private: SymbolContext(const Definition *def,const Definition *prev,const Definition *next); - ~SymbolContext(); + virtual ~SymbolContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class SymbolListContext : public RefCountedContext, public TemplateListIntf +class SymbolListContext : public TemplateListIntf { public: - static SymbolListContext *alloc(const SearchIndexList::const_iterator &start, + static TemplateListIntfPtr alloc(const SearchIndexList::const_iterator &start, const SearchIndexList::const_iterator &end) - { return new SymbolListContext(start,end); } + { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<SymbolListContext>(start,end)); } // TemplateListIntf virtual uint count() const; virtual TemplateVariant at(uint index) const; - virtual TemplateListIntf::ConstIterator *createIterator() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } + virtual TemplateListIntf::ConstIteratorPtr createIterator() const; - private: SymbolListContext(const SearchIndexList::const_iterator &start, const SearchIndexList::const_iterator &end); - ~SymbolListContext(); + virtual ~SymbolListContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class SymbolGroupContext : public RefCountedContext, public TemplateStructIntf +class SymbolGroupContext : public TemplateStructIntf { public: - static SymbolGroupContext *alloc(const SearchIndexList::const_iterator &start, + static TemplateStructIntfPtr alloc(const SearchIndexList::const_iterator &start, const SearchIndexList::const_iterator &end) - { return new SymbolGroupContext(start,end); } + { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<SymbolGroupContext>(start,end)); } // TemplateStructIntf methods virtual TemplateVariant get(const QCString &name) const; virtual StringVector fields() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } - private: SymbolGroupContext(const SearchIndexList::const_iterator &start, const SearchIndexList::const_iterator &end); - ~SymbolGroupContext(); + virtual ~SymbolGroupContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class SymbolGroupListContext : public RefCountedContext, public TemplateListIntf +class SymbolGroupListContext : public TemplateListIntf { public: - static SymbolGroupListContext *alloc(const SearchIndexList &sil) - { return new SymbolGroupListContext(sil); } + static TemplateListIntfPtr alloc(const SearchIndexList &sil) + { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<SymbolGroupListContext>(sil)); } // TemplateListIntf virtual uint count() const; virtual TemplateVariant at(uint index) const; - virtual TemplateListIntf::ConstIterator *createIterator() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } + virtual TemplateListIntf::ConstIteratorPtr createIterator() const; - private: SymbolGroupListContext(const SearchIndexList &sil); - ~SymbolGroupListContext(); + virtual ~SymbolGroupListContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class SymbolIndexContext : public RefCountedContext, public TemplateStructIntf +class SymbolIndexContext : public TemplateStructIntf { public: - static SymbolIndexContext *alloc(const std::string &letter, + static TemplateStructIntfPtr alloc(const std::string &letter, const SearchIndexList &sl,const QCString &name) - { return new SymbolIndexContext(letter,sl,name); } + { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<SymbolIndexContext>(letter,sl,name)); } // TemplateStructIntf methods virtual TemplateVariant get(const QCString &name) const; virtual StringVector fields() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } - private: SymbolIndexContext(const std::string &letter,const SearchIndexList &sl,const QCString &name); - ~SymbolIndexContext(); + virtual ~SymbolIndexContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class SymbolIndicesContext : public RefCountedContext, public TemplateListIntf +class SymbolIndicesContext : public TemplateListIntf { public: - static SymbolIndicesContext *alloc(const SearchIndexInfo &info) - { return new SymbolIndicesContext(info); } + static TemplateListIntfPtr alloc(const SearchIndexInfo &info) + { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<SymbolIndicesContext>(info)); } // TemplateListIntf virtual uint count() const; virtual TemplateVariant at(uint index) const; - virtual TemplateListIntf::ConstIterator *createIterator() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } + virtual TemplateListIntf::ConstIteratorPtr createIterator() const; - private: SymbolIndicesContext(const SearchIndexInfo &info); - ~SymbolIndicesContext(); + virtual ~SymbolIndicesContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class SearchIndexContext : public RefCountedContext, public TemplateStructIntf +class SearchIndexContext : public TemplateStructIntf { public: - static SearchIndexContext *alloc(const SearchIndexInfo &info) - { return new SearchIndexContext(info); } + static TemplateStructIntfPtr alloc(const SearchIndexInfo &info) + { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<SearchIndexContext>(info)); } // TemplateStructIntf methods virtual TemplateVariant get(const QCString &name) const; virtual StringVector fields() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } - private: SearchIndexContext(const SearchIndexInfo &info); - ~SearchIndexContext(); + virtual ~SearchIndexContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- -class SearchIndicesContext : public RefCountedContext, public TemplateListIntf +class SearchIndicesContext : public TemplateListIntf { public: - static SearchIndicesContext *alloc() { return new SearchIndicesContext; } + static TemplateListIntfPtr alloc() + { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<SearchIndicesContext>()); } // TemplateListIntf virtual uint count() const; virtual TemplateVariant at(uint index) const; - virtual TemplateListIntf::ConstIterator *createIterator() const; - virtual int addRef() { return RefCountedContext::addRef(); } - virtual int release() { return RefCountedContext::release(); } + virtual TemplateListIntf::ConstIteratorPtr createIterator() const; - private: SearchIndicesContext(); - ~SearchIndicesContext(); + virtual ~SearchIndicesContext(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //---------------------------------------------------- diff --git a/src/declinfo.l b/src/declinfo.l index 3e3f503..2e578b0 100644 --- a/src/declinfo.l +++ b/src/declinfo.l @@ -22,6 +22,10 @@ %option extra-type="struct declinfoYY_state *" %top{ #include <stdint.h> +// forward declare yyscan_t to improve type safety +#define YY_TYPEDEF_YY_SCANNER_T +struct yyguts_t; +typedef yyguts_t *yyscan_t; } %{ @@ -81,21 +85,23 @@ static yy_size_t yyread(char *buf,yy_size_t max_size, yyscan_t yyscanner); */ #undef YY_INPUT #define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size,yyscanner); + +// otherwise the filename would be the name of the converted file (*.cpp instead of *.l) +static inline const char *getLexerFILE() {return __FILE__;} +#define LEX_NO_INPUT_FILENAME +#include "doxygen_lex.h" %} B [ \t] Bopt {B}* ID ([$a-z_A-Z\x80-\xFF][$a-z_A-Z0-9\x80-\xFF]*)|(@[0-9]+) -%x Start +%x Start %x Template %x ReadArgs %x Operator -%x FuncPtr -%x EndTemplate -%x StripTempArgs -%x SkipSharp -%x ReadExceptions +%x DeclType +%x ReadExceptions %% @@ -159,10 +165,28 @@ ID ([$a-z_A-Z\x80-\xFF][$a-z_A-Z0-9\x80-\xFF]*)|(@[0-9]+) <Start>{B}*")" { yyextra->type+=")"; } +<Start>{B}*"decltype"/{B}*"(" { + yyextra->roundCount=0; + yyextra->type="decltype"; + BEGIN(DeclType); + } +<DeclType>{B}*"(" { + ++yyextra->roundCount; + yyextra->type+="("; + } +<DeclType>{B}*")" { + yyextra->type+=")"; + if (--yyextra->roundCount == 0) { + BEGIN(Start); + } + } +<DeclType>. { + yyextra->type+=yytext; + } <Start>{B}*"(" { // TODO: function pointers - yyextra->args+="("; - BEGIN(ReadArgs); - } + yyextra->args+="("; + BEGIN(ReadArgs); + } <Start>{B}*"[" { yyextra->args+="["; BEGIN(ReadArgs); @@ -361,7 +385,7 @@ void parseFuncDecl(const QCString &decl,const SrcLangExt lang,QCString &cl,QCStr a=removeRedundantWhiteSpace(yyextra->args); exc=removeRedundantWhiteSpace(yyextra->exceptionString); - if (!t.isEmpty() && t.at(t.length()-1)==')') // for function pointers + if (!t.isEmpty() && !t.startsWith("decltype") && t.at(t.length()-1)==')') // for function pointers { a.prepend(")"); t=t.left(t.length()-1); diff --git a/src/defargs.l b/src/defargs.l index b1a1b15..121b21b 100644 --- a/src/defargs.l +++ b/src/defargs.l @@ -45,6 +45,10 @@ %option extra-type="struct defargsYY_state *" %top{ #include <stdint.h> +// forward declare yyscan_t to improve type safety +#define YY_TYPEDEF_YY_SCANNER_T +struct yyguts_t; +typedef yyguts_t *yyscan_t; } %{ @@ -111,6 +115,11 @@ static bool nameIsActuallyPartOfType(QCString &name); #undef YY_INPUT #define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); +// otherwise the filename would be the name of the converted file (*.cpp instead of *.l) +static inline const char *getLexerFILE() {return __FILE__;} +#define LEX_NO_INPUT_FILENAME +#include "doxygen_lex.h" + %} B [ \t] diff --git a/src/definition.cpp b/src/definition.cpp index dae7ce2..08ed32e 100644 --- a/src/definition.cpp +++ b/src/definition.cpp @@ -85,7 +85,6 @@ class DefinitionImpl::IMPL QCString symbolName; int defLine; int defColumn; - Definition::Cookie *cookie; mutable MemberVector referencesMembers; mutable MemberVector referencedByMembers; @@ -123,7 +122,7 @@ void DefinitionImpl::IMPL::init(const QCString &df, const QCString &n) { localName=n; } - //printf("m_localName=%s\n",qPrint(m_localName)); + //printf("localName=%s\n",qPrint(localName)); brief = 0; details = 0; @@ -135,7 +134,6 @@ void DefinitionImpl::IMPL::init(const QCString &df, const QCString &n) hidden = FALSE; isArtificial = FALSE; lang = SrcLangExt_Unknown; - cookie = 0; } void DefinitionImpl::setDefFile(const QCString &df,int defLine,int defCol) @@ -490,10 +488,10 @@ void DefinitionImpl::setDocumentation(const QCString &d,const QCString &docFile, void DefinitionImpl::_setBriefDescription(const QCString &b,const QCString &briefFile,int briefLine) { - static QCString outputLanguage = Config_getEnum(OUTPUT_LANGUAGE); - static bool needsDot = outputLanguage!="Japanese" && - outputLanguage!="Chinese" && - outputLanguage!="Korean"; + static OUTPUT_LANGUAGE_t outputLanguage = Config_getEnum(OUTPUT_LANGUAGE); + static bool needsDot = outputLanguage!=OUTPUT_LANGUAGE_t::Japanese && + outputLanguage!=OUTPUT_LANGUAGE_t::Chinese && + outputLanguage!=OUTPUT_LANGUAGE_t::Korean; QCString brief = b; brief = brief.stripWhiteSpace(); brief = stripLeadingAndTrailingEmptyLines(brief,briefLine); @@ -1356,13 +1354,13 @@ QCString DefinitionImpl::navigationPathAsString() const if (m_impl->def->definitionType()==Definition::TypeGroup && !toGroupDef(m_impl->def)->groupTitle().isEmpty()) { - result+="<a class=\"el\" href=\"$relpath^"+m_impl->def->getOutputFileBase()+Doxygen::htmlFileExtension+"\">"+ + result+="<a class=\"el\" href=\"$relpath^"+addHtmlExtensionIfMissing(m_impl->def->getOutputFileBase())+"\">"+ convertToHtml(toGroupDef(m_impl->def)->groupTitle())+"</a>"; } else if (m_impl->def->definitionType()==Definition::TypePage && toPageDef(m_impl->def)->hasTitle()) { - result+="<a class=\"el\" href=\"$relpath^"+m_impl->def->getOutputFileBase()+Doxygen::htmlFileExtension+"\">"+ + result+="<a class=\"el\" href=\"$relpath^"+addHtmlExtensionIfMissing(m_impl->def->getOutputFileBase())+"\">"+ convertToHtml((toPageDef(m_impl->def))->title())+"</a>"; } else if (m_impl->def->definitionType()==Definition::TypeClass) @@ -1372,13 +1370,13 @@ QCString DefinitionImpl::navigationPathAsString() const { name = name.left(name.length()-2); } - result+="<a class=\"el\" href=\"$relpath^"+m_impl->def->getOutputFileBase()+Doxygen::htmlFileExtension; + result+="<a class=\"el\" href=\"$relpath^"+addHtmlExtensionIfMissing(m_impl->def->getOutputFileBase()); if (!m_impl->def->anchor().isEmpty()) result+="#"+m_impl->def->anchor(); result+="\">"+convertToHtml(name)+"</a>"; } else { - result+="<a class=\"el\" href=\"$relpath^"+m_impl->def->getOutputFileBase()+Doxygen::htmlFileExtension+"\">"+ + result+="<a class=\"el\" href=\"$relpath^"+addHtmlExtensionIfMissing(m_impl->def->getOutputFileBase())+"\">"+ convertToHtml(locName)+"</a>"; } } @@ -1476,7 +1474,6 @@ void DefinitionImpl::writeToc(OutputList &ol, const LocalToc &localToc) const level--; } if (level <= maxLevel && inLi[level]) ol.writeString("</li>\n"); - inLi[level]=false; ol.writeString("</ul>\n"); ol.writeString("</div>\n"); ol.popGeneratorState(); @@ -1531,7 +1528,6 @@ void DefinitionImpl::writeToc(OutputList &ol, const LocalToc &localToc) const ol.writeString("</tocdiv>\n"); level--; } - inLi[level]=FALSE; ol.writeString(" </toc>\n"); ol.popGeneratorState(); } @@ -1899,17 +1895,6 @@ int DefinitionImpl::getDefColumn() const return m_impl->defColumn; } -void DefinitionImpl::setCookie(Definition::Cookie *cookie) const -{ - delete m_impl->cookie; - m_impl->cookie = cookie; -} - -Definition::Cookie *DefinitionImpl::cookie() const -{ - return m_impl->cookie; -} - void DefinitionImpl::writeQuickMemberLinks(OutputList &,const MemberDef *) const { } diff --git a/src/definition.h b/src/definition.h index 8bf4de9..ac91201 100644 --- a/src/definition.h +++ b/src/definition.h @@ -23,8 +23,8 @@ #include "types.h" #include "reflist.h" -#if defined(_WIN32) && !defined(__CYGWIN__) -// To disable 'inherits via dominance' warnings. +#ifdef _MSC_VER +// To disable 'inherits via dominance' warnings with MSVC. // See also https://stackoverflow.com/a/14487243/784672 #pragma warning( disable: 4250 ) #endif @@ -289,12 +289,6 @@ class Definition virtual QCString pathFragment() const = 0; //----------------------------------------------------------------------------------- - // --- cookie storage ---- - //----------------------------------------------------------------------------------- - virtual void setCookie(Cookie *cookie) const = 0; - virtual Cookie *cookie() const = 0; - - //----------------------------------------------------------------------------------- // --- symbol name ---- //----------------------------------------------------------------------------------- virtual void _setSymbolName(const QCString &name) = 0; diff --git a/src/definitionimpl.h b/src/definitionimpl.h index a7b3aad..a620b81 100644 --- a/src/definitionimpl.h +++ b/src/definitionimpl.h @@ -117,8 +117,6 @@ class DefinitionImpl void setLocalName(const QCString &name); void addSectionsToIndex(); void writeToc(OutputList &ol, const LocalToc <) const; - void setCookie(Definition::Cookie *cookie) const; - Definition::Cookie *cookie() const; void computeTooltip(); void _setSymbolName(const QCString &name); QCString _symbolName() const; @@ -275,10 +273,6 @@ class DefinitionMixin : public Base { m_impl.addSectionsToIndex(); } virtual void writeToc(OutputList &ol, const LocalToc <) const { m_impl.writeToc(ol,lt); } - virtual void setCookie(Definition::Cookie *cookie) const - { m_impl.setCookie(cookie); } - virtual Definition::Cookie *cookie() const - { return m_impl.cookie(); } virtual void computeTooltip() { m_impl.computeTooltip(); } virtual void _setSymbolName(const QCString &name) @@ -319,7 +313,7 @@ class DefinitionAliasMixin : public Base { public: DefinitionAliasMixin(const Definition *scope,const Definition *alias) - : m_impl(this,scope,alias), m_scope(scope), m_alias(alias), m_cookie(0) {} + : m_impl(this,scope,alias), m_scope(scope), m_alias(alias) {} void init() { m_impl.init(); } void deinit() { m_impl.deinit(); } @@ -437,14 +431,11 @@ class DefinitionAliasMixin : public Base virtual DefinitionMutable *toDefinitionMutable_() { return 0; } virtual const DefinitionImpl *toDefinitionImpl_() const { return 0; } - virtual void setCookie(Definition::Cookie *cookie) const { delete m_cookie; m_cookie = cookie; } - virtual Definition::Cookie *cookie() const { return m_cookie; } virtual void _setSymbolName(const QCString &name) { m_symbolName = name; } virtual QCString _symbolName() const { return m_symbolName; } DefinitionAliasImpl m_impl; const Definition *m_scope; const Definition *m_alias; - mutable Definition::Cookie *m_cookie; QCString m_symbolName; }; diff --git a/src/diagram.cpp b/src/diagram.cpp index 0f20636..af910f4 100644 --- a/src/diagram.cpp +++ b/src/diagram.cpp @@ -255,7 +255,7 @@ static void writeMapArea(TextStream &t,const ClassDef *cd,QCString relPath, } t << "href=\""; t << externalRef(relPath,ref,TRUE); - t << cd->getOutputFileBase() << Doxygen::htmlFileExtension; + t << addHtmlExtensionIfMissing(cd->getOutputFileBase()); if (!cd->anchor().isEmpty()) { t << "#" << cd->anchor(); @@ -1071,7 +1071,6 @@ void ClassDiagram::writeFigure(TextStream &output,const QCString &path, if (realWidth>pageWidth) // assume that the page width is about 15 cm { realHeight*=pageWidth/realWidth; - realWidth=pageWidth; } //output << "}\n"; diff --git a/src/dirdef.cpp b/src/dirdef.cpp index 6920c0d..086b41a 100644 --- a/src/dirdef.cpp +++ b/src/dirdef.cpp @@ -47,12 +47,12 @@ class DirDefImpl : public DefinitionMixin<DirDef> virtual bool isLinkableInProject() const; virtual bool isLinkable() const; virtual QCString displayName(bool=TRUE) const { return m_dispName; } - virtual const QCString &shortName() const { return m_shortName; } + virtual const QCString shortName() const { return m_shortName; } virtual void addSubDir(DirDef *subdir); virtual const FileList &getFiles() const { return m_fileList; } virtual void addFile(const FileDef *fd); virtual const DirList &subDirs() const { return m_subdirs; } - virtual bool isCluster() const { return m_subdirs.size()>0; } + virtual bool hasSubdirs() const { return !m_subdirs.empty(); } virtual int level() const { return m_level; } virtual DirDef *parent() const { return m_parent; } virtual int dirCount() const { return m_dirCount; } @@ -66,9 +66,10 @@ class DirDefImpl : public DefinitionMixin<DirDef> virtual void setDiskName(const QCString &name) { m_diskName = name; } virtual void sort(); virtual void setParent(DirDef *parent); + virtual void setDirCount(int count); virtual void setLevel(); virtual void addUsesDependency(const DirDef *usedDir,const FileDef *srcFd, - const FileDef *dstFd,bool inherited); + const FileDef *dstFd,bool srcDirect, bool dstDirect); virtual void computeDependencies(); public: @@ -92,7 +93,7 @@ class DirDefImpl : public DefinitionMixin<DirDef> QCString m_shortName; QCString m_diskName; FileList m_fileList; // list of files in the group - int m_dirCount; + int m_dirCount = -1; int m_level; DirDef *m_parent; UsedDirLinkedMap m_usedDirs; @@ -107,8 +108,6 @@ DirDef *createDirDef(const QCString &path) //---------------------------------------------------------------------- // method implementation -static int g_dirCount=0; - DirDefImpl::DirDefImpl(const QCString &path) : DefinitionMixin(path,1,1,path) { bool fullPathNames = Config_getBool(FULL_PATH_NAMES); @@ -132,7 +131,6 @@ DirDefImpl::DirDefImpl(const QCString &path) : DefinitionMixin(path,1,1,path) m_dispName = m_dispName.left(m_dispName.length()-1); } - m_dirCount = g_dirCount++; m_level=-1; m_parent=0; } @@ -163,6 +161,11 @@ void DirDefImpl::setParent(DirDef *p) m_parent=p; } +void DirDefImpl::setDirCount(int count) +{ + m_dirCount=count; +} + void DirDefImpl::addFile(const FileDef *fd) { m_fileList.push_back(fd); @@ -339,7 +342,7 @@ void DirDefImpl::writeSubDirList(OutputList &ol) ol.startMemberList(); for(const auto dd : m_subdirs) { - if (dd->hasDocumentation() || dd->getFiles().empty()) + if (dd->hasDocumentation() || !dd->getFiles().empty()) { ol.startMemberDeclaration(); ol.startMemberItem(dd->anchor(),0); @@ -373,7 +376,12 @@ void DirDefImpl::writeFileList(OutputList &ol) int numFiles = 0; for (const auto &fd : m_fileList) { - if (fd->hasDocumentation()) + bool genSourceFile; + if (fileVisibleInIndex(fd,genSourceFile)) + { + numFiles++; + } + else if (genSourceFile) { numFiles++; } @@ -388,7 +396,9 @@ void DirDefImpl::writeFileList(OutputList &ol) ol.startMemberList(); for (const auto &fd : m_fileList) { - if (fd->hasDocumentation()) + bool doc,src; + doc = fileVisibleInIndex(fd,src); + if (doc || src) { ol.startMemberDeclaration(); ol.startMemberItem(fd->anchor(),0); @@ -463,7 +473,7 @@ void DirDefImpl::writeTagFile(TextStream &tagFile) tagFile << " <compound kind=\"dir\">\n"; tagFile << " <name>" << convertToXML(displayName()) << "</name>\n"; tagFile << " <path>" << convertToXML(name()) << "</path>\n"; - tagFile << " <filename>" << convertToXML(getOutputFileBase()) << Doxygen::htmlFileExtension << "</filename>\n"; + tagFile << " <filename>" << addHtmlExtensionIfMissing(getOutputFileBase()) << "</filename>\n"; for (const auto &lde : LayoutDocManager::instance().docEntries(LayoutDocManager::Directory)) { switch (lde->kind()) @@ -629,9 +639,11 @@ void DirDefImpl::setLevel() /** Add as "uses" dependency between \a this dir and \a dir, * that was caused by a dependency on file \a fd. + * srcDirect and dstDirect indicate if it is a direct dependencies (true) or if + * the dependencies was indirect (e.g. a parent dir that has a child dir that has the dependencies) */ void DirDefImpl::addUsesDependency(const DirDef *dir,const FileDef *srcFd, - const FileDef *dstFd,bool inherited) + const FileDef *dstFd,bool srcDirect, bool dstDirect) { if (this==dir) return; // do not add self-dependencies //static int count=0; @@ -650,7 +662,7 @@ void DirDefImpl::addUsesDependency(const DirDef *dir,const FileDef *srcFd, if (usedPair==0) // new file dependency { //printf(" => new file\n"); - usedDir->addFileDep(srcFd,dstFd); + usedDir->addFileDep(srcFd,dstFd, srcDirect, dstDirect); added=TRUE; } else @@ -661,8 +673,8 @@ void DirDefImpl::addUsesDependency(const DirDef *dir,const FileDef *srcFd, else // new directory dependency { //printf(" => new file\n"); - auto newUsedDir = std::make_unique<UsedDir>(dir,inherited); - newUsedDir->addFileDep(srcFd,dstFd); + auto newUsedDir = std::make_unique<UsedDir>(dir); + newUsedDir->addFileDep(srcFd,dstFd, srcDirect, dstDirect); usedDir = m_usedDirs.add(dir->getOutputFileBase(),std::move(newUsedDir)); added=TRUE; } @@ -671,12 +683,20 @@ void DirDefImpl::addUsesDependency(const DirDef *dir,const FileDef *srcFd, if (dir->parent()) { // add relation to parent of used dir - addUsesDependency(dir->parent(),srcFd,dstFd,inherited); + addUsesDependency(dir->parent(), + srcFd, + dstFd, + srcDirect, + false); // indirect dependency on dest dir } if (parent()) { // add relation for the parent of this dir as well - parent()->addUsesDependency(dir,srcFd,dstFd,TRUE); + parent()->addUsesDependency(dir, + srcFd, + dstFd, + false, // indirect dependency from source dir + dstDirect); } } } @@ -701,7 +721,7 @@ void DirDefImpl::computeDependencies() // add dependency: thisDir->usedDir //static int count=0; //printf(" %d: add dependency %s->%s\n",count++,qPrint(name()),qPrint(usedDir->name())); - addUsesDependency(usedDir,fd,ii.fileDef,FALSE); + addUsesDependency(usedDir,fd,ii.fileDef,true,true); } } } @@ -729,14 +749,14 @@ bool DirDefImpl::isParentOf(const DirDef *dir) const bool DirDefImpl::depGraphIsTrivial() const { - return m_usedDirs.empty(); + return m_usedDirs.empty() && m_parent==nullptr; } //---------------------------------------------------------------------- -UsedDir::UsedDir(const DirDef *dir,bool inherited) : - m_dir(dir), m_inherited(inherited) +UsedDir::UsedDir(const DirDef *dir) : + m_dir(dir) { } @@ -744,9 +764,12 @@ UsedDir::~UsedDir() { } -void UsedDir::addFileDep(const FileDef *srcFd,const FileDef *dstFd) +void UsedDir::addFileDep(const FileDef *srcFd,const FileDef *dstFd, bool srcDirect, bool dstDirect) { m_filePairs.add(FilePair::key(srcFd,dstFd),std::make_unique<FilePair>(srcFd,dstFd)); + m_hasDirectDeps = m_hasDirectDeps || (srcDirect && dstDirect); + m_hasDirectSrcDeps = m_hasDirectSrcDeps || srcDirect; + m_hasDirectDstDeps = m_hasDirectDstDeps || dstDirect; } void UsedDir::sort() @@ -993,7 +1016,6 @@ void buildDirectories() { for (const auto &fd : *fn) { - //printf("buildDirectories %s\n",qPrint(fd->name())); if (fd->getReference().isEmpty()) { DirDef *dir; @@ -1038,7 +1060,24 @@ void buildDirectories() std::sort(Doxygen::dirLinkedMap->begin(), Doxygen::dirLinkedMap->end(), [](const auto &d1,const auto &d2) - { return qstricmp(d1->shortName(),d2->shortName()) < 0; }); + { + QCString s1 = d1->shortName(), s2 = d2->shortName(); + int i = qstricmp(s1,s2); + if (i==0) // if sort name are equal, sort on full path + { + QCString n1 = d1->name(), n2 = d2->name(); + int n = qstricmp(n1,n2); + return n < 0; + } + return i < 0; + }); + + // set the directory count identifier + int dirCount=0; + for (const auto &dir : *Doxygen::dirLinkedMap) + { + dir->setDirCount(dirCount++); + } computeCommonDirPrefix(); } @@ -1050,13 +1089,13 @@ void computeDirDependencies() { dir->setLevel(); } + // compute uses dependencies between directories for (const auto &dir : *Doxygen::dirLinkedMap) { //printf("computeDependencies for %s: #dirs=%d\n",qPrint(dir->name()),Doxygen::directories.count()); dir->computeDependencies(); } - } void generateDirDocs(OutputList &ol) diff --git a/src/dirdef.h b/src/dirdef.h index 3d775d0..2dff286 100644 --- a/src/dirdef.h +++ b/src/dirdef.h @@ -63,19 +63,45 @@ class FilePairLinkedMap : public LinkedMap<FilePair> class UsedDir { public: - UsedDir(const DirDef *dir,bool inherited); + UsedDir(const DirDef *dir); virtual ~UsedDir(); - void addFileDep(const FileDef *srcFd,const FileDef *dstFd); + + /** + * Take up dependency between files. + * @param[in] srcFd dependent file which depends on dstFd + * @param[in] dstFd dependee file on which srcFd depends on + * @param[in] srcDirect true iff the source dependency was the direct (not inherited from a sub dir) + * @param[in] dstDirect true iff the destination dependency was direct (not inherited from a sub dir) + */ + void addFileDep(const FileDef *srcFd,const FileDef *dstFd, bool srcDirect, bool dstDirect); FilePair *findFilePair(const QCString &name); const FilePairLinkedMap &filePairs() const { return m_filePairs; } const DirDef *dir() const { return m_dir; } - bool inherited() const { return m_inherited; } + + /** Returns true iff any of the dependencies between source and destination files are + * direct (i.e. not "inherited" from sub directories) + */ + bool hasDirectDeps() const { return m_hasDirectDeps; } + + /** Returns true iff any of the dependencies from the source file to the destination file are + * directly coming from a file in the source directory (i.e. not inherited via sub directories) + */ + bool hasDirectSrcDeps() const { return m_hasDirectSrcDeps; } + + /** Returns true iff any of the dependencies from the source file to the destination file are + * directly targeting a file in the destination directory (i.e. not inherited via sub directories) + */ + bool hasDirectDstDeps() const { return m_hasDirectDstDeps; } + void sort(); private: const DirDef *m_dir; FilePairLinkedMap m_filePairs; - bool m_inherited; + + bool m_hasDirectDeps = false; + bool m_hasDirectSrcDeps = false; + bool m_hasDirectDstDeps = false; }; // ------------------ @@ -95,12 +121,12 @@ class DirDef : public DefinitionMutable, public Definition virtual bool isLinkableInProject() const = 0; virtual bool isLinkable() const = 0; virtual QCString displayName(bool=TRUE) const = 0; - virtual const QCString &shortName() const = 0; + virtual const QCString shortName() const = 0; virtual void addSubDir(DirDef *subdir) = 0; virtual const FileList &getFiles() const = 0; virtual void addFile(const FileDef *fd) = 0; virtual const DirList &subDirs() const = 0; - virtual bool isCluster() const = 0; + virtual bool hasSubdirs() const = 0; virtual int level() const = 0; virtual DirDef *parent() const = 0; virtual int dirCount() const = 0; @@ -115,11 +141,12 @@ class DirDef : public DefinitionMutable, public Definition virtual void writeTagFile(TextStream &t) = 0; virtual void setDiskName(const QCString &name) = 0; + virtual void setDirCount(int count) = 0; virtual void sort() = 0; virtual void setParent(DirDef *parent) = 0; virtual void setLevel() = 0; virtual void addUsesDependency(const DirDef *usedDir,const FileDef *srcFd, - const FileDef *dstFd,bool inherited) = 0; + const FileDef *dstFd,bool srcDirect, bool dstDirect) = 0; virtual void computeDependencies() = 0; }; diff --git a/src/docbookgen.cpp b/src/docbookgen.cpp index 041ab4b..ff85689 100644 --- a/src/docbookgen.cpp +++ b/src/docbookgen.cpp @@ -168,9 +168,10 @@ void DocbookCodeGenerator::writeCodeLink(CodeSymbolType, void DocbookCodeGenerator::writeCodeLinkLine(CodeSymbolType, const QCString &,const QCString &file, const QCString &,const QCString &name, - const QCString &) + const QCString &,bool writeLineAnchor) { Docbook_DB(("(writeCodeLinkLine)\n")); + if (!writeLineAnchor) return; m_t << "<anchor xml:id=\"_" << stripExtensionGeneral(stripPath(file),".xml"); m_t << "_1l"; writeDocbookString(m_t,name); @@ -222,7 +223,7 @@ void DocbookCodeGenerator::writeCodeAnchor(const QCString &) } void DocbookCodeGenerator::writeLineNumber(const QCString &ref,const QCString &fileName, - const QCString &anchor,int l) + const QCString &anchor,int l,bool writeLineAnchor) { Docbook_DB(("(writeLineNumber)\n")); m_insideCodeLine = TRUE; @@ -233,7 +234,7 @@ void DocbookCodeGenerator::writeLineNumber(const QCString &ref,const QCString &f if (!m_sourceFileName.isEmpty()) { - writeCodeLinkLine(CodeSymbolType::Default,ref,m_sourceFileName,anchor,lineNumber,QCString()); + writeCodeLinkLine(CodeSymbolType::Default,ref,m_sourceFileName,anchor,lineNumber,QCString(),writeLineAnchor); } if (!fileName.isEmpty()) { diff --git a/src/docbookgen.h b/src/docbookgen.h index 5ed6fa5..ea4efe9 100644 --- a/src/docbookgen.h +++ b/src/docbookgen.h @@ -37,7 +37,7 @@ class DocbookCodeGenerator : public CodeOutputInterface void writeCodeLinkLine(CodeSymbolType type, const QCString &ref,const QCString &file, const QCString &anchor,const QCString &name, - const QCString &tooltip); + const QCString &tooltip, bool); void writeTooltip(const QCString &, const DocLinkInfo &, const QCString &, const QCString &, const SourceLinkInfo &, const SourceLinkInfo & ); @@ -47,7 +47,7 @@ class DocbookCodeGenerator : public CodeOutputInterface void endFontClass(); void writeCodeAnchor(const QCString &); void writeLineNumber(const QCString &extRef,const QCString &compId, - const QCString &anchorId,int l); + const QCString &anchorId,int l, bool writeLineAnchor); void setCurrentDoc(const Definition *,const QCString &,bool); void addWord(const QCString &,bool); void finish(); @@ -112,8 +112,8 @@ class DocbookGenerator : public OutputGenerator const QCString &anchor,const QCString &name, const QCString &tooltip) { m_codeGen.writeCodeLink(type,ref,file,anchor,name,tooltip); } - void writeLineNumber(const QCString &ref,const QCString &file,const QCString &anchor,int lineNumber) - { m_codeGen.writeLineNumber(ref,file,anchor,lineNumber); } + void writeLineNumber(const QCString &ref,const QCString &file,const QCString &anchor,int lineNumber, bool writeLineAnchor) + { m_codeGen.writeLineNumber(ref,file,anchor,lineNumber,writeLineAnchor); } void writeTooltip(const QCString &id, const DocLinkInfo &docInfo, const QCString &decl, const QCString &desc, const SourceLinkInfo &defInfo, const SourceLinkInfo &declInfo ) diff --git a/src/docbookvisitor.cpp b/src/docbookvisitor.cpp index 25fc21e..471bd3e 100644 --- a/src/docbookvisitor.cpp +++ b/src/docbookvisitor.cpp @@ -295,6 +295,7 @@ DB_VIS_C /* There is no equivalent Docbook tag for rendering Small text */ case DocStyleChange::Small: /* XSLT Stylesheets can be used */ break; /* HTML only */ + case DocStyleChange::Cite: break; case DocStyleChange::S: break; case DocStyleChange::Strike: break; case DocStyleChange::Del: break; @@ -302,6 +303,21 @@ DB_VIS_C case DocStyleChange::Ins: break; case DocStyleChange::Div: /* HTML only */ break; case DocStyleChange::Span: /* HTML only */ break; + case DocStyleChange::Details: /* emulation of the <details> tag */ + if (s->enable()) + { + m_t << "\n"; + m_t << "<para>"; + } + else + { + m_t << "</para>"; + m_t << "\n"; + } + break; + case DocStyleChange::Summary: /* emulation of the <summary> tag inside a <details> tag */ + if (s->enable()) m_t << "<emphasis role=\"bold\">"; else m_t << "</emphasis>"; + break; } } @@ -331,6 +347,14 @@ DB_VIS_C filter(s->text()); m_t << "</computeroutput></literallayout>"; break; + case DocVerbatim::JavaDocLiteral: + filter(s->text(), true); + break; + case DocVerbatim::JavaDocCode: + m_t << "<computeroutput>"; + filter(s->text(), true); + m_t << "</computeroutput>"; + break; case DocVerbatim::HtmlOnly: break; case DocVerbatim::RtfOnly: @@ -936,33 +960,7 @@ void DocbookDocVisitor::visitPre(DocHtmlList *s) { DB_VIS_C if (m_hide) return; - if (s->type()==DocHtmlList::Ordered) - { - m_t << "<orderedlist"; - for (const auto &opt : s->attribs()) - { - if (opt.name=="type") - { - if (opt.value=="1") - m_t << " numeration=\"arabic\""; - else if (opt.value=="a") - m_t << " numeration=\"loweralpha\""; - else if (opt.value=="A") - m_t << " numeration=\"upperalpha\""; - else if (opt.value=="i") - m_t << " numeration=\"lowerroman\""; - else if (opt.value=="I") - m_t << " numeration=\"upperroman\""; - } - else if (opt.name=="start") - { - m_t << " startingnumber=\"" << opt.value << "\""; - } - } - m_t << ">\n"; - } - else - m_t << "<itemizedlist>\n"; + // This will be handled in DocHtmlListItem } void DocbookDocVisitor::visitPost(DocHtmlList *s) @@ -975,10 +973,68 @@ DB_VIS_C m_t << "</itemizedlist>\n"; } -void DocbookDocVisitor::visitPre(DocHtmlListItem *) +void DocbookDocVisitor::visitPre(DocHtmlListItem *s) { DB_VIS_C if (m_hide) return; + DocHtmlList *l = (DocHtmlList *)s->parent(); + if (l->type()==DocHtmlList::Ordered) + { + bool isFirst = l->children().front().get()==s; + int value = 0; + QCString type; + for (const auto &opt : s->attribs()) + { + if (opt.name=="value") + { + bool ok; + int val = opt.value.toInt(&ok); + if (ok) value = val; + } + } + + if (value>0 || isFirst) + { + for (const auto &opt : l->attribs()) + { + if (opt.name=="type") + { + if (opt.value=="1") + type = " numeration=\"arabic\""; + else if (opt.value=="a") + type = " numeration=\"loweralpha\""; + else if (opt.value=="A") + type = " numeration=\"upperalpha\""; + else if (opt.value=="i") + type = " numeration=\"lowerroman\""; + else if (opt.value=="I") + type = " numeration=\"upperroman\""; + } + else if (value==0 && opt.name=="start") + { + bool ok; + int val = opt.value.toInt(&ok); + if (ok) value = val; + } + } + } + + if (value>0 && !isFirst) + { + m_t << "</orderedlist>\n"; + } + if (value>0 || isFirst) + { + m_t << "<orderedlist"; + if (!type.isEmpty()) m_t << type.data(); + if (value>0) m_t << " startingnumber=\"" << value << "\""; + m_t << ">\n"; + } + } + else + { + m_t << "<itemizedlist>\n"; + } m_t << "<listitem>\n"; } @@ -1043,6 +1099,15 @@ DB_VIS_C // do something with colwidth based of cell width specification (be aware of possible colspan in the header)? m_t << " <colspec colname='c" << i+1 << "'/>\n"; } + if (t->hasCaption()) + { + DocHtmlCaption *c = t->caption(); + m_t << "<caption>"; + if (!c->file().isEmpty()) + { + m_t << "<anchor xml:id=\"_" << stripPath(c->file()) << "_1" << filterId(c->anchor()) << "\"/>"; + } + } } void DocbookDocVisitor::visitPost(DocHtmlTable *) @@ -1162,7 +1227,7 @@ void DocbookDocVisitor::visitPre(DocHtmlCaption *) { DB_VIS_C if (m_hide) return; - m_t << "<caption>"; + // start of caption is handled in the DocbookDocVisitor::visitPre(DocHtmlTable *t) } void DocbookDocVisitor::visitPost(DocHtmlCaption *) @@ -1276,6 +1341,7 @@ void DocbookDocVisitor::visitPre(DocDotFile *df) { DB_VIS_C if (m_hide) return; + if (!Config_getBool(DOT_CLEANUP)) copyFile(df->file(),Config_getString(DOCBOOK_OUTPUT)+"/"+stripPath(df->file())); startDotFile(df->file(),df->width(),df->height(),df->hasCaption(),df->children(),df->srcFile(),df->srcLine()); } @@ -1290,6 +1356,7 @@ void DocbookDocVisitor::visitPre(DocMscFile *df) { DB_VIS_C if (m_hide) return; + if (!Config_getBool(DOT_CLEANUP)) copyFile(df->file(),Config_getString(DOCBOOK_OUTPUT)+"/"+stripPath(df->file())); startMscFile(df->file(),df->width(),df->height(),df->hasCaption(),df->children(),df->srcFile(),df->srcLine()); } @@ -1303,6 +1370,7 @@ void DocbookDocVisitor::visitPre(DocDiaFile *df) { DB_VIS_C if (m_hide) return; + if (!Config_getBool(DOT_CLEANUP)) copyFile(df->file(),Config_getString(DOCBOOK_OUTPUT)+"/"+stripPath(df->file())); startDiaFile(df->file(),df->width(),df->height(),df->hasCaption(),df->children(),df->srcFile(),df->srcLine()); } @@ -1607,10 +1675,10 @@ DB_VIS_C } -void DocbookDocVisitor::filter(const QCString &str) +void DocbookDocVisitor::filter(const QCString &str, const bool retainNewLine) { DB_VIS_C - m_t << convertToDocBook(str); + m_t << convertToDocBook(str, retainNewLine); } void DocbookDocVisitor::startLink(const QCString &file,const QCString &anchor) diff --git a/src/docbookvisitor.h b/src/docbookvisitor.h index 220dd5e..93ed94e 100644 --- a/src/docbookvisitor.h +++ b/src/docbookvisitor.h @@ -139,7 +139,7 @@ class DocbookDocVisitor : public DocVisitor //-------------------------------------- // helper functions //-------------------------------------- - void filter(const QCString &str); + void filter(const QCString &str, const bool retainNewLine = false); void startLink(const QCString &file, const QCString &anchor); void endLink(); diff --git a/src/docgroup.cpp b/src/docgroup.cpp index 07ff8f3..875103c 100644 --- a/src/docgroup.cpp +++ b/src/docgroup.cpp @@ -70,12 +70,12 @@ void DocGroup::enterCompound(const QCString &fileName,int line,const QCString &n { m_compoundName=fileName; } - //printf("groupEnterCompound(%s)\n",name); + //printf("groupEnterCompound(%s)\n",qPrint(name)); } -void DocGroup::leaveCompound(const QCString &,int,const QCString & /*name*/) +void DocGroup::leaveCompound(const QCString &,int,const QCString & name) { - //printf("groupLeaveCompound(%s)\n",name); + //printf("groupLeaveCompound(%s)\n",qPrint(name)); //if (m_memberGroupId!=DOX_NOGROUP) //{ // warn(fileName,line,"end of compound %s while inside a member group\n",qPrint(name)); @@ -106,7 +106,7 @@ int DocGroup::findExistingGroup(const MemberGroupInfo *info) void DocGroup::open(Entry *e,const QCString &,int, bool implicit) { if (!implicit) m_openCount++; - //printf("==> openGroup(name=%s,sec=%x) m_autoGroupStack=%d\n", + //printf("==> openGroup(name=%s,sec=%x) m_autoGroupStack=%zu\n", // qPrint(e->name),e->section,m_autoGroupStack.size()); if (e->section==Entry::GROUPDOC_SEC) // auto group { @@ -146,8 +146,8 @@ void DocGroup::close(Entry *e,const QCString &fileName,int line,bool foundInline m_openCount--; } } - //printf("==> closeGroup(name=%s,sec=%x,file=%s,line=%d) m_autoGroupStack=%d\n", - // qPrint(e->name),e->section,fileName,line,m_autoGroupStack.size()); + //printf("==> closeGroup(name=%s,sec=%x,file=%s,line=%d) m_autoGroupStack=%zu\n", + // qPrint(e->name),e->section,qPrint(fileName),line,m_autoGroupStack.size()); if (m_memberGroupId!=DOX_NOGROUP) // end of member group { auto it = Doxygen::memberGroupInfoMap.find(m_memberGroupId); @@ -177,15 +177,15 @@ void DocGroup::close(Entry *e,const QCString &fileName,int line,bool foundInline void DocGroup::initGroupInfo(Entry *e) { - //printf("==> initGroup(id=%d,related=%s,e=%p)\n",m_memberGroupId, - // qPrint(m_memberGroupRelates),e); + //printf("==> initGroup(id=%d,related=%s,e=%p,#stack=%zu)\n",m_memberGroupId, + // qPrint(m_memberGroupRelates),(void*)e,m_autoGroupStack.size()); e->mGrpId = m_memberGroupId; e->relates = m_memberGroupRelates; if (!m_autoGroupStack.empty()) { - //printf("Appending group %s to %s: count=%d entry=%p\n", - // qPrint(m_autoGroupStack.top()->groupname), - // qPrint(e->name),e->groups->count(),e); + //printf("Appending group %s to %s: count=%zu entry=%p\n", + // qPrint(m_autoGroupStack.back().groupname), + // qPrint(e->name),e->groups.size(),(void*)e); e->groups.push_back(Grouping(m_autoGroupStack.back())); } } diff --git a/src/docparser.cpp b/src/docparser.cpp index 2aa20cb..b8ffc23 100644 --- a/src/docparser.cpp +++ b/src/docparser.cpp @@ -61,7 +61,7 @@ //#define DBG(x) printf x // debug to stderr -//#define myprintf(x...) fprintf(stderr,x) +//#define myprintf(...) fprintf(stderr,__VA_ARGS__) //#define DBG(x) myprintf x #define INTERNAL_ASSERT(x) do {} while(0) @@ -92,7 +92,24 @@ static const std::set<std::string> g_plantumlEngine { using DefinitionStack = std::vector<const Definition *>; using DocNodeStack = std::stack<const DocNode *>; -using DocStyleChangeStack = std::stack<const DocStyleChange *>; +//using DocStyleChangeStack = std::stack<const DocStyleChange *>; + +template<typename T, typename Container = std::deque<T>> +class iterable_stack +: public std::stack<T, Container> +{ + using std::stack<T, Container>::c; + +public: + + // expose just the iterators of the underlying container + auto begin() { return std::begin(c); } + auto end() { return std::end(c); } + + auto begin() const { return std::begin(c); } + auto end() const { return std::end(c); } +}; +using DocStyleChangeStack = iterable_stack<const DocStyleChange *>; /** Parser's context to store all global variables. */ @@ -310,6 +327,10 @@ QCString DocParser::findAndCopyImage(const QCString &fileName, DocImage::Type ty if (!Config_getBool(GENERATE_RTF)) return result; outputDir = Config_getString(RTF_OUTPUT); break; + case DocImage::Xml: + if (!Config_getBool(GENERATE_XML)) return result; + outputDir = Config_getString(XML_OUTPUT); + break; } QCString outputFile = outputDir+"/"+result; FileInfo outfi(outputFile.str()); @@ -375,7 +396,7 @@ QCString DocParser::findAndCopyImage(const QCString &fileName, DocImage::Type ty */ void DocParser::checkArgumentName() { - if (!Config_getBool(WARN_IF_DOC_ERROR)) return; + if (!(Config_getBool(WARN_IF_DOC_ERROR) || Config_getBool(WARN_IF_INCOMPLETE_DOC))) return; if (context.memberDef==0) return; // not a member std::string name = context.token->name.str(); const ArgumentList &al=context.memberDef->isDocsForDefinition() ? @@ -492,8 +513,8 @@ void DocParser::checkUnOrMultipleDocumentedParams() } else if (count>1 && Config_getBool(WARN_IF_DOC_ERROR)) { - warn_doc_error(context.memberDef->getDefFileName(), - context.memberDef->getDefLine(), + warn_doc_error(context.memberDef->docFile(), + context.memberDef->docLine(), "%s", qPrint("argument '" + aName + "' from the argument list of " + @@ -520,8 +541,8 @@ void DocParser::checkUnOrMultipleDocumentedParams() first=FALSE; errMsg+=" parameter '"+argName+"'"; } - warn_incomplete_doc(context.memberDef->getDefFileName(), - context.memberDef->getDefLine(), + warn_incomplete_doc(context.memberDef->docFile(), + context.memberDef->docLine(), "%s", qPrint(substitute(errMsg,"%","%%"))); } @@ -614,6 +635,15 @@ static bool insideTable(DocNode *n) return FALSE; } +static const DocStyleChange *insideDetails(DocStyleChangeStack styleStack) +{ + const DocStyleChange *retItem = NULL; + for (auto i : styleStack) + { + if (i->style() == DocStyleChange::Details) retItem = i; + } + return retItem; +} //--------------------------------------------------------------------------- /*! Looks for a documentation block with name commandName in the current * context (g_parserContext.context). The resulting documentation string is @@ -830,6 +860,7 @@ int DocParser::handleStyleArgument(DocNode *parent,DocNodeList &children,const Q { // ignore </li> as the end of a style command continue; } + DBG(("handleStyleArgument(%s) end tok=%s\n",qPrint(saveCmdName), DocTokenizer::tokToString(tok))); return tok; break; default: @@ -839,7 +870,7 @@ int DocParser::handleStyleArgument(DocNode *parent,DocNodeList &children,const Q break; } } - DBG(("handleStyleArgument(%s) end tok=%x\n",qPrint(saveCmdName),tok)); + DBG(("handleStyleArgument(%s) end tok=%s\n",qPrint(saveCmdName), DocTokenizer::tokToString(tok))); return (tok==TK_NEWPARA || tok==TK_LISTITEM || tok==TK_ENDLIST ) ? tok : RetVal_OK; } @@ -980,6 +1011,7 @@ const char *DocStyleChange::styleString() const case DocStyleChange::Code: return "code"; case DocStyleChange::Center: return "center"; case DocStyleChange::Small: return "small"; + case DocStyleChange::Cite: return "cite"; case DocStyleChange::Subscript: return "subscript"; case DocStyleChange::Superscript: return "superscript"; case DocStyleChange::Preformatted: return "pre"; @@ -990,6 +1022,8 @@ const char *DocStyleChange::styleString() const case DocStyleChange::Del: return "del"; case DocStyleChange::Underline: return "u"; case DocStyleChange::Ins: return "ins"; + case DocStyleChange::Details: return "details"; + case DocStyleChange::Summary: return "summary"; } return "<invalid>"; } @@ -1548,6 +1582,16 @@ reparsetoken: handleStyleLeave(parent,children,DocStyleChange::Ins,tokenName); } break; + case HTML_DETAILS: + if (!context.token->endTag) + { + handleStyleEnter(parent,children,DocStyleChange::Details,tokenName,&context.token->attribs); + } + else + { + handleStyleLeave(parent,children,DocStyleChange::Details,tokenName); + } + break; case HTML_CODE: case XML_C: if (!context.token->endTag) @@ -1609,6 +1653,16 @@ reparsetoken: handleStyleLeave(parent,children,DocStyleChange::Small,tokenName); } break; + case HTML_CITE: + if (!context.token->endTag) + { + handleStyleEnter(parent,children,DocStyleChange::Cite,tokenName,&context.token->attribs); + } + else + { + handleStyleLeave(parent,children,DocStyleChange::Cite,tokenName); + } + break; case HTML_IMG: if (!context.token->endTag) handleImg(parent,children,context.token->attribs); @@ -2982,7 +3036,6 @@ endheader: DBG(("DocHtmlHeader::parse() end\n")); return retval; } - //--------------------------------------------------------------------------- int DocHRef::parse() @@ -3089,7 +3142,7 @@ int DocInternal::parse(int level) warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"\\internal command found inside internal section"); } - DBG(("DocInternal::parse() end: retval=%x\n",retval)); + DBG(("DocInternal::parse() end: retval=%s\n",DocTokenizer::retvalToString(retval))); return retval; } @@ -3182,7 +3235,7 @@ int DocIndexEntry::parse() m_parser.tokenizer.setStatePara(); m_entry = m_entry.stripWhiteSpace(); endindexentry: - DBG(("DocIndexEntry::parse() end retval=%x\n",retval)); + DBG(("DocIndexEntry::parse() end retval=%s\n",DocTokenizer::retvalToString(retval))); return retval; } @@ -3281,7 +3334,7 @@ int DocHtmlCell::parse() if (retval==TK_HTMLTAG) { int tagId=Mappers::htmlTagMapper->map(m_parser.context.token->name); - if (tagId==HTML_TD && m_parser.context.token->endTag) // found </dt> tag + if (tagId==HTML_TD && m_parser.context.token->endTag) // found </td> tag { retval=TK_NEWPARA; // ignore the tag } @@ -3291,7 +3344,7 @@ int DocHtmlCell::parse() } } } - while (retval==TK_NEWPARA); + while ((retval==TK_NEWPARA) || (retval==RetVal_EndParBlock)); if (par) par->markLast(); DBG(("DocHtmlCell::parse() end\n")); @@ -4002,7 +4055,7 @@ int DocHtmlListItem::parse() while (retval==TK_NEWPARA); if (par) par->markLast(); - DBG(("DocHtmlListItem::parse() end retval=%x\n",retval)); + DBG(("DocHtmlListItem::parse() end retval=%s\n",DocTokenizer::retvalToString(retval))); return retval; } @@ -4034,7 +4087,7 @@ int DocHtmlListItem::parseXml() if (par) par->markLast(); - DBG(("DocHtmlListItem::parseXml() end retval=%x\n",retval)); + DBG(("DocHtmlListItem::parseXml() end retval=%s\n",DocTokenizer::retvalToString(retval))); return retval; } @@ -4111,7 +4164,7 @@ int DocHtmlList::parse() } endlist: - DBG(("DocHtmlList::parse() end retval=%x\n",retval)); + DBG(("DocHtmlList::parse() end retval=%s\n",DocTokenizer::retvalToString(retval))); return retval==RetVal_EndList ? RetVal_OK : retval; } @@ -4172,7 +4225,7 @@ int DocHtmlList::parseXml() } endlist: - DBG(("DocHtmlList::parseXml() end retval=%x\n",retval)); + DBG(("DocHtmlList::parseXml() end retval=%s\n",DocTokenizer::retvalToString(retval))); return retval==RetVal_EndList || (retval==RetVal_CloseXml || m_parser.context.token->name=="list") ? RetVal_OK : retval; @@ -4199,7 +4252,7 @@ int DocHtmlBlockQuote::parse() while (retval==TK_NEWPARA); if (par) par->markLast(); - DBG(("DocHtmlBlockQuote::parse() end retval=%x\n",retval)); + DBG(("DocHtmlBlockQuote::parse() end retval=%s\n",DocTokenizer::retvalToString(retval))); return (retval==RetVal_EndBlockQuote) ? RetVal_OK : retval; } @@ -4224,7 +4277,7 @@ int DocParBlock::parse() while (retval==TK_NEWPARA); if (par) par->markLast(); - DBG(("DocParBlock::parse() end retval=%x\n",retval)); + DBG(("DocParBlock::parse() end retval=%s\n",DocTokenizer::retvalToString(retval))); return (retval==RetVal_EndBlockQuote) ? RetVal_OK : retval; } @@ -4578,8 +4631,8 @@ int DocParamList::parse(const QCString &cmdName) { if (tok!=TK_NEWPARA) /* empty param description */ { - warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"unexpected token in comment block while parsing the " - "argument of command %s",qPrint(saveCmdName)); + warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"unexpected token %s in comment block while parsing the " + "argument of command %s",DocTokenizer::tokToString(tok),qPrint(saveCmdName)); } retval=RetVal_EndParBlock; goto endparamlist; @@ -4991,9 +5044,10 @@ void DocPara::handleImage(const QCString &cmdName) else if (imgType=="latex") t=DocImage::Latex; else if (imgType=="docbook") t=DocImage::DocBook; else if (imgType=="rtf") t=DocImage::Rtf; + else if (imgType=="xml") t=DocImage::Xml; else { - warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"output format %s specified as the first argument of " + warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"output format `%s` specified as the first argument of " "%s command is not valid", qPrint(imgType),qPrint(saveCmdName)); return; @@ -5072,9 +5126,11 @@ void DocPara::handleLink(const QCString &cmdName,bool isJavaLink) DocTokenizer::tokToString(tok),qPrint(saveCmdName)); return; } + if (saveCmdName == "javalink") m_children.push_back(std::make_unique<DocStyleChange>(m_parser,this,(uint)m_parser.context.nodeStack.size(),DocStyleChange::Code,cmdName,TRUE)); m_parser.tokenizer.setStatePara(); DocLink *lnk = new DocLink(m_parser,this,m_parser.context.token->name); m_children.push_back(std::unique_ptr<DocLink>(lnk)); + if (saveCmdName == "javalink") m_children.push_back(std::make_unique<DocStyleChange>(m_parser,this,(uint)m_parser.context.nodeStack.size(),DocStyleChange::Code,cmdName,FALSE)); QCString leftOver = lnk->parse(isJavaLink); if (!leftOver.isEmpty()) { @@ -5570,6 +5626,53 @@ int DocPara::handleCommand(const QCString &cmdName, const int tok) m_parser.tokenizer.setStatePara(); } break; + case CMD_ILITERAL: + { + DocVerbatim::Type t = DocVerbatim::JavaDocLiteral; + m_parser.tokenizer.setStateILiteralOpt(); + retval = m_parser.tokenizer.lex(); + + QCString fullMatch = m_parser.context.token->verb; + int idx = fullMatch.find('{'); + int idxEnd = fullMatch.find("}",idx+1); + StringVector optList; + if (idx != -1) // options present + { + QCString optStr = fullMatch.mid(idx+1,idxEnd-idx-1).stripWhiteSpace(); + optList = split(optStr.str(),","); + for (const auto &opt : optList) + { + if (opt.empty()) continue; + QCString locOpt(opt); + locOpt = locOpt.stripWhiteSpace().lower(); + if (locOpt == "code") + { + t = DocVerbatim::JavaDocCode; + } + else if (!locOpt.isEmpty()) + { + warn(m_parser.context.fileName,m_parser.tokenizer.getLineNr(), "Unknown option '%s' for '\\iliteral'",qPrint(opt)); + } + } + } + + m_parser.tokenizer.setStateILiteral(); + retval = m_parser.tokenizer.lex(); + m_children.push_back(std::make_unique<DocVerbatim>(m_parser,this,m_parser.context.context,m_parser.context.token->verb,t,m_parser.context.isExample,m_parser.context.exampleName)); + if (retval==0) + { + if (t == DocVerbatim::JavaDocCode) + { + warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"javadoc code section ended without end marker"); + } + else + { + warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"javadoc literal section ended without end marker"); + } + } + m_parser.tokenizer.setStatePara(); + } + break; case CMD_VERBATIM: { m_parser.tokenizer.setStateVerbatim(); @@ -5729,6 +5832,7 @@ int DocPara::handleCommand(const QCString &cmdName, const int tok) case CMD_ENDDBONLY: case CMD_ENDLINK: case CMD_ENDVERBATIM: + case CMD_ENDILITERAL: case CMD_ENDDOT: case CMD_ENDMSC: case CMD_ENDUML: @@ -5936,7 +6040,7 @@ int DocPara::handleCommand(const QCString &cmdName, const int tok) retval==RetVal_Internal || retval==RetVal_SwitchLang || retval==RetVal_EndInternal ); - DBG(("handleCommand(%s) end retval=%x\n",qPrint(cmdName),retval)); + DBG(("handleCommand(%s) end retval=%s\n",qPrint(cmdName),DocTokenizer::retvalToString(retval))); return retval; } @@ -5958,7 +6062,7 @@ static bool findAttribute(const HtmlAttribList &tagHtmlAttribs, int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &tagHtmlAttribs) { - DBG(("handleHtmlStartTag(%s,%d)\n",qPrint(tagName),tagHtmlAttribs.count())); + DBG(("handleHtmlStartTag(%s,%d)\n",qPrint(tagName),tagHtmlAttribs.size())); int retval=RetVal_OK; int tagId = Mappers::htmlTagMapper->map(tagName); if (m_parser.context.token->emptyTag && !(tagId&XML_CmdMask) && @@ -6014,6 +6118,9 @@ int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &ta case HTML_INS: if (!m_parser.context.token->emptyTag) m_parser.handleStyleEnter(this,m_children,DocStyleChange::Ins,tagName,&m_parser.context.token->attribs); break; + case HTML_DETAILS: + if (!m_parser.context.token->emptyTag) m_parser.handleStyleEnter(this,m_children,DocStyleChange::Details,tagName,&m_parser.context.token->attribs); + break; case HTML_CODE: if (m_parser.context.token->emptyTag) break; if (/*getLanguageFromFileName(m_parser.context.fileName)==SrcLangExt_CSharp ||*/ m_parser.context.xmlComment) @@ -6049,6 +6156,9 @@ int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &ta case HTML_SMALL: if (!m_parser.context.token->emptyTag) m_parser.handleStyleEnter(this,m_children,DocStyleChange::Small,tagName,&m_parser.context.token->attribs); break; + case HTML_CITE: + if (!m_parser.context.token->emptyTag) m_parser.handleStyleEnter(this,m_children,DocStyleChange::Cite,tagName,&m_parser.context.token->attribs); + break; case HTML_PRE: if (m_parser.context.token->emptyTag) break; m_parser.handleStyleEnter(this,m_children,DocStyleChange::Preformatted,tagName,&m_parser.context.token->attribs); @@ -6138,6 +6248,11 @@ int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &ta break; case XML_SUMMARY: + if (insideDetails(m_parser.context.styleStack)) + { + if (!m_parser.context.token->emptyTag) m_parser.handleStyleEnter(this,m_children,DocStyleChange::Summary,tagName,&m_parser.context.token->attribs); + break; + } case XML_REMARKS: case XML_EXAMPLE: m_parser.context.xmlComment=TRUE; @@ -6439,6 +6554,9 @@ int DocPara::handleHtmlEndTag(const QCString &tagName) case HTML_INS: m_parser.handleStyleLeave(this,m_children,DocStyleChange::Ins,tagName); break; + case HTML_DETAILS: + m_parser.handleStyleLeave(this,m_children,DocStyleChange::Details,tagName); + break; case HTML_CODE: m_parser.handleStyleLeave(this,m_children,DocStyleChange::Code,tagName); break; @@ -6463,6 +6581,9 @@ int DocPara::handleHtmlEndTag(const QCString &tagName) case HTML_SMALL: m_parser.handleStyleLeave(this,m_children,DocStyleChange::Small,tagName); break; + case HTML_CITE: + m_parser.handleStyleLeave(this,m_children,DocStyleChange::Cite,tagName); + break; case HTML_PRE: m_parser.handleStyleLeave(this,m_children,DocStyleChange::Preformatted,tagName); setInsidePreformatted(FALSE); @@ -6531,6 +6652,11 @@ int DocPara::handleHtmlEndTag(const QCString &tagName) //m_children.push_back(std::make_unique<DocStyleChange>(this,(uint)m_parser.context.nodeStack.size(),DocStyleChange::Bold,FALSE)); break; case XML_SUMMARY: + if (insideDetails(m_parser.context.styleStack)) + { + m_parser.handleStyleLeave(this,m_children,DocStyleChange::Summary,tagName); + break; + } case XML_REMARKS: case XML_PARA: case XML_VALUE: @@ -6765,7 +6891,7 @@ reparsetoken: // handle the command retval=handleCommand(m_parser.context.token->name,tok); - DBG(("handleCommand returns %x\n",retval)); + DBG(("handleCommand returns %s\n",DocTokenizer::retvalToString(retval))); // check the return value if (retval==RetVal_SimpleSec) @@ -6872,14 +6998,14 @@ reparsetoken: break; default: warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(), - "Found unexpected token (id=%x)\n",tok); + "Found unexpected token (id=%s)\n",DocTokenizer::tokToString(tok)); break; } } retval=0; endparagraph: m_parser.handlePendingStyleCommands(this,m_children); - DBG(("DocPara::parse() end retval=%x\n",retval)); + DBG(("DocPara::parse() end retval=%s\n",DocTokenizer::retvalToString(retval))); const DocNode *n = m_parser.context.nodeStack.top(); if (!m_parser.context.token->endTag && n->kind()==DocNode::Kind_Para && retval==TK_NEWPARA && m_parser.context.token->name.lower() == "p") @@ -7013,7 +7139,7 @@ int DocSection::parse() retval==RetVal_EndInternal ); - DBG(("DocSection::parse() end: retval=%x\n",retval)); + DBG(("DocSection::parse() end: retval=%s\n",DocTokenizer::retvalToString(retval))); return retval; } @@ -7337,6 +7463,7 @@ static QCString extractCopyDocId(const char *data, uint &j, uint len) j+=9; } e=j; + if (j>0 && data[j-1]=='.') { e--; } // do not include punctuation added by Definition::_setBriefDescription() QCString id(data+s,e-s); //printf("extractCopyDocId='%s' input='%s'\n",qPrint(id),&data[s]); return id; @@ -7370,6 +7497,7 @@ static uint isVerbatimSection(const char *data,uint i,uint len,QCString &endMark CHECK_FOR_COMMAND("code",endMarker="endcode"); CHECK_FOR_COMMAND("msc",endMarker="endmsc"); CHECK_FOR_COMMAND("verbatim",endMarker="endverbatim"); + CHECK_FOR_COMMAND("iliteral",endMarker="endiliteral"); CHECK_FOR_COMMAND("latexonly",endMarker="endlatexonly"); CHECK_FOR_COMMAND("htmlonly",endMarker="endhtmlonly"); CHECK_FOR_COMMAND("xmlonly",endMarker="endxmlonly"); diff --git a/src/docparser.h b/src/docparser.h index 073a013..e60b1a1 100644 --- a/src/docparser.h +++ b/src/docparser.h @@ -357,7 +357,10 @@ class DocStyleChange : public DocNode Underline = (1<<11), Del = (1<<12), Ins = (1<<13), - S = (1<<14) + S = (1<<14), + Details = (1<<15), + Summary = (1<<16), + Cite = (1<<17) }; DocStyleChange(DocParser &parser,DocNode *parent,uint position,Style s,const QCString &tagName,bool enable, @@ -510,7 +513,7 @@ class DocSeparator : public DocNode class DocVerbatim : public DocNode { public: - enum Type { Code, HtmlOnly, ManOnly, LatexOnly, RtfOnly, XmlOnly, Verbatim, Dot, Msc, DocbookOnly, PlantUML }; + enum Type { Code, HtmlOnly, ManOnly, LatexOnly, RtfOnly, XmlOnly, Verbatim, Dot, Msc, DocbookOnly, PlantUML, JavaDocCode, JavaDocLiteral }; DocVerbatim(DocParser &parser,DocNode *parent,const QCString &context, const QCString &text, Type t,bool isExample, const QCString &exampleFile,bool isBlock=FALSE,const QCString &lang=QCString()); @@ -771,7 +774,7 @@ class DocXRefItem : public CompAccept<DocXRefItem> class DocImage : public CompAccept<DocImage> { public: - enum Type { Html, Latex, Rtf, DocBook }; + enum Type { Html, Latex, Rtf, DocBook, Xml }; DocImage(DocParser &parser,DocNode *parent,const HtmlAttribList &attribs, const QCString &name,Type t,const QCString &url=QCString(), bool inlineImage = TRUE); Kind kind() const override { return Kind_Image; } diff --git a/src/docsets.cpp b/src/docsets.cpp index bf589c4..a18ac82 100644 --- a/src/docsets.cpp +++ b/src/docsets.cpp @@ -58,6 +58,8 @@ void DocSets::initialize() if (bundleId.isEmpty()) bundleId="org.doxygen.Project"; QCString feedName = Config_getString(DOCSET_FEEDNAME); if (feedName.isEmpty()) feedName="FeedName"; + QCString feedURL = Config_getString(DOCSET_FEEDURL); + if (feedURL.isEmpty()) feedURL="FeedUrl"; QCString publisherId = Config_getString(DOCSET_PUBLISHER_ID); if (publisherId.isEmpty()) publisherId="PublisherId"; QCString publisherName = Config_getString(DOCSET_PUBLISHER_NAME); @@ -136,6 +138,8 @@ void DocSets::initialize() " <string>" << projectNumber << "</string>\n" " <key>DocSetFeedName</key>\n" " <string>" << feedName << "</string>\n" + " <key>DocSetFeedUrl</key>\n" + " <string>" << feedURL << "</string>\n" " <key>DocSetPublisherIdentifier</key>\n" " <string>" << publisherId << "</string>\n" " <key>DocSetPublisherName</key>\n" @@ -257,7 +261,7 @@ void DocSets::addContentsItem(bool isDir, } else if (!file.isEmpty()) // doxygen generated file { - p->nts << file << Doxygen::htmlFileExtension; + p->nts << addHtmlExtensionIfMissing(file); } p->nts << "</Path>\n"; if (!file.isEmpty() && !anchor.isEmpty()) @@ -509,8 +513,7 @@ void DocSets::writeToken(TextStream &t, t << " <Scope>" << convertToXML(scope) << "</Scope>\n"; } t << " </TokenIdentifier>\n"; - t << " <Path>" << d->getOutputFileBase() - << Doxygen::htmlFileExtension << "</Path>\n"; + t << " <Path>" << addHtmlExtensionIfMissing(d->getOutputFileBase()) << "</Path>\n"; if (!anchor.isEmpty()) { t << " <Anchor>" << anchor << "</Anchor>\n"; diff --git a/src/doctokenizer.h b/src/doctokenizer.h index f1b10eb..43e4092 100644 --- a/src/doctokenizer.h +++ b/src/doctokenizer.h @@ -126,6 +126,7 @@ class DocTokenizer // helper functions static const char *tokToString(int token); + static const char *retvalToString(int retval); void setLineNr(int lineno); int getLineNr(void); @@ -150,6 +151,8 @@ class DocTokenizer void setStateDbOnly(); void setStateRtfOnly(); void setStateVerbatim(); + void setStateILiteral(); + void setStateILiteralOpt(); void setStateDot(); void setStateMsc(); void setStateParam(); diff --git a/src/doctokenizer.l b/src/doctokenizer.l index ed53565..f5ccc19 100644 --- a/src/doctokenizer.l +++ b/src/doctokenizer.l @@ -22,6 +22,10 @@ %option extra-type="struct doctokenizerYY_state *" %top{ #include <stdint.h> +// forward declare yyscan_t to improve type safety +#define YY_TYPEDEF_YY_SCANNER_T +struct yyguts_t; +typedef yyguts_t *yyscan_t; } %{ @@ -142,6 +146,32 @@ const char *DocTokenizer::tokToString(int token) return "ERROR"; } +const char *DocTokenizer::retvalToString(int retval) +{ + switch (retval) + { + case RetVal_OK: return "RetVal_OK"; + case RetVal_SimpleSec: return "RetVal_SimpleSec"; + case RetVal_ListItem: return "RetVal_ListItem"; + case RetVal_Section: return "RetVal_Section"; + case RetVal_Subsection: return "RetVal_Subsection"; + case RetVal_Subsubsection: return "RetVal_Subsubsection"; + case RetVal_Paragraph: return "RetVal_Paragraph"; + case RetVal_SubParagraph: return "RetVal_SubParagraph"; + case RetVal_EndList: return "RetVal_EndList"; + case RetVal_EndPre: return "RetVal_EndPre"; + case RetVal_DescData: return "RetVal_DescData"; + case RetVal_DescTitle : return "RetVal_DescTitle"; + case RetVal_EndDesc: return "RetVal_EndDesc"; + case RetVal_TableRow: return "RetVal_TableRow"; + case RetVal_TableCell: return "RetVal_TableCell"; + case RetVal_TableHCell: return "RetVal_TableHCell"; + case RetVal_EndTable: return "RetVal_EndTable"; + case RetVal_Internal: return "RetVal_Internal"; + } + return "ERROR"; +} + static int computeIndent(const char *str,size_t length) { if (str==0 || length==std::string::npos) return 0; @@ -214,6 +244,10 @@ static QCString stripEmptyLines(const QCString &s) #undef YY_INPUT #define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); +// otherwise the filename would be the name of the converted file (*.cpp instead of *.l) +static inline const char *getLexerFILE() {return __FILE__;} +#include "doxygen_lex.h" + //-------------------------------------------------------------------------- //#define REAL_YY_DECL int doctokenizerYYlex (void) //#define YY_DECL static int local_doctokenizer(void) @@ -232,8 +266,8 @@ PHPTYPE [\\:a-z_A-Z0-9\x80-\xFF\-]+ CITESCHAR [a-z_A-Z0-9\x80-\xFF\-\?] CITEECHAR [a-z_A-Z0-9\x80-\xFF\-\+:\/\?] CITEID {CITESCHAR}{CITEECHAR}*("."{CITESCHAR}{CITEECHAR}*)*|"\""{CITESCHAR}{CITEECHAR}*("."{CITESCHAR}{CITEECHAR}*)*"\"" -MAILADDR ("mailto:")?[a-z_A-Z0-9.+-]+"@"[a-z_A-Z0-9-]+("."[a-z_A-Z0-9\-]+)+[a-z_A-Z0-9\-]+ -MAILWS [\t a-z_A-Z0-9+-] +MAILADDR ("mailto:")?[a-z_A-Z0-9\x80-\xFF.+-]+"@"[a-z_A-Z0-9\x80-\xFf-]+("."[a-z_A-Z0-9\x80-\xFf\-]+)+[a-z_A-Z0-9\x80-\xFf\-]+ +MAILWS [\t a-z_A-Z0-9\x80-\xFF+-] MAILADDR2 {MAILWS}+{BLANK}+("at"|"AT"|"_at_"|"_AT_"){BLANK}+{MAILWS}+("dot"|"DOT"|"_dot_"|"_DOT_"){BLANK}+{MAILWS}+ OPTSTARS ("/""/"{BLANK}*)?"*"*{BLANK}* LISTITEM {BLANK}*[-]("#")?{WS} @@ -262,7 +296,7 @@ INOUT "in"|"out"|("in"{BLANK}*","?{BLANK}*"out")|("out"{BLANK}*","?{BLANK}*" PARAMIO {CMD}param{BLANK}*"["{BLANK}*{INOUT}{BLANK}*"]" VARARGS "..." TEMPCHAR [a-z_A-Z0-9.,: \t\*\&\(\)\[\]] -FUNCCHAR [a-z_A-Z0-9,:\<\> \t\^\*\&\[\]]|{VARARGS} +FUNCCHAR [a-z_A-Z0-9,:\<\> \t\n\^\*\&\[\]]|{VARARGS}|"\\ilinebr" FUNCPART {FUNCCHAR}*("("{FUNCCHAR}*")"{FUNCCHAR}*)? SCOPESEP "::"|"#"|"." TEMPLPART "<"{TEMPCHAR}*("<"{TEMPCHAR}*("<"{TEMPCHAR}*">")?">")?">" @@ -288,7 +322,7 @@ LNKWORD3 ([0-9a-z_A-Z\-]+("/"|"\\"))*[0-9a-z_A-Z\-]+("."[0-9a-z_A-Z]+)+ CHARWORDQ [^ \t\n\r\\@<>()\[\]:;\?{}&%$#,."='] ESCWORD ("%"{ID}(("::"|"."){ID})*)|("%'") CHARWORDQ1 [^ \-+0-9\t\n\r\\@<>()\[\]:;\?{}&%$#,."='] -WORD1 {ESCWORD}|{CHARWORDQ1}{CHARWORDQ}*|"{"|"}"|"'\"'"|("\""([^"\n]*\n?)*[^"\n]*"\"") +WORD1 {ESCWORD}|{CHARWORDQ1}{CHARWORDQ}*|"{"|"}"|"'\"'"|("\""([^"\n]*(\\\"|\n)?)*[^"\n]*"\"") WORD2 "."|","|"("|")"|"["|"]"|"::"|":"|";"|"\?"|"="|"'" WORD1NQ {ESCWORD}|{CHARWORDQ}+|"{"|"}" WORD2NQ "."|","|"("|")"|"["|"]"|"::"|":"|";"|"\?"|"="|"'" @@ -328,6 +362,8 @@ LINENR {BLANK}*[1-9][0-9]* %x St_XmlOnly %x St_DbOnly %x St_Verbatim +%x St_ILiteral +%x St_ILiteralOpt %x St_Dot %x St_Msc %x St_PlantUMLOpt @@ -485,6 +521,10 @@ LINENR {BLANK}*[1-9][0-9]* yyextra->token->indent = computeIndent(text.data(),dotPos); return TK_ENDLIST; } +<St_Para>"{"{BLANK}*"@linkplain"/{WS}+ { + yyextra->token->name = "javalinkplain"; + return TK_COMMAND_AT; + } <St_Para>"{"{BLANK}*"@link"/{WS}+ { yyextra->token->name = "javalink"; return TK_COMMAND_AT; @@ -622,6 +662,10 @@ LINENR {BLANK}*[1-9][0-9]* yyextra->token->name = yytext; return TK_LNKWORD; } +<St_Para>{LNKWORD1}/"<tt>" { // prevent <tt> html tag to be parsed as template arguments + yyextra->token->name = yytext; + return TK_LNKWORD; + } <St_Para>{LNKWORD1}/"<br>" | // prevent <br> html tag to be parsed as template arguments <St_Para>{LNKWORD1} | <St_Para>{LNKWORD1}{FUNCARG} | @@ -811,12 +855,28 @@ LINENR {BLANK}*[1-9][0-9]* yyextra->token->verb=stripEmptyLines(yyextra->token->verb); return RetVal_OK; } -<St_Verbatim>[^\\@\n]+ | -<St_Verbatim>\n | -<St_Verbatim>. { /* Verbatim text */ +<St_ILiteral>{CMD}"endiliteral " { // note extra space as this is artificially added + // remove spaces that have been added + yyextra->token->verb=yyextra->token->verb.mid(1,yyextra->token->verb.length()-2); + return RetVal_OK; + } +<St_Verbatim,St_ILiteral>[^\\@\n]+ | +<St_Verbatim,St_ILiteral>\n | +<St_Verbatim,St_ILiteral>. { /* Verbatim / javadac literal/code text */ lineCount(yytext,yyleng); yyextra->token->verb+=yytext; } +<St_ILiteralOpt>{BLANK}*"{"[a-zA-Z_,:0-9\. ]*"}" { // option(s) present + yyextra->token->verb = QCString(yytext).stripWhiteSpace(); + return RetVal_OK; + } +<St_ILiteralOpt>"\\ilinebr" | +<St_ILiteralOpt>"\n" | +<St_ILiteralOpt>. { + yyextra->token->sectionId = ""; + unput_string(yytext,yyleng); + return RetVal_OK; + } <St_Dot>{CMD}"enddot" { return RetVal_OK; } @@ -1282,6 +1342,10 @@ LINENR {BLANK}*[1-9][0-9]* yyextra->endMarker="endverbatim"; BEGIN(St_SecSkip); } +<St_Sections>{CMD}"iliteral"/[^a-z_A-Z0-9] { + yyextra->endMarker="endiliteral"; + BEGIN(St_SecSkip); + } <St_Sections>{CMD}"dot"/[^a-z_A-Z0-9] { yyextra->endMarker="enddot"; BEGIN(St_SecSkip); @@ -1732,6 +1796,22 @@ void DocTokenizer::setStateLatexOnly() BEGIN(St_LatexOnly); } +void DocTokenizer::setStateILiteral() +{ + yyscan_t yyscanner = p->yyscanner; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->token->verb=""; + BEGIN(St_ILiteral); +} + +void DocTokenizer::setStateILiteralOpt() +{ + yyscan_t yyscanner = p->yyscanner; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->token->verb=""; + BEGIN(St_ILiteralOpt); +} + void DocTokenizer::setStateVerbatim() { yyscan_t yyscanner = p->yyscanner; diff --git a/src/dot.cpp b/src/dot.cpp index 5d6aa27..e42b73d 100644 --- a/src/dot.cpp +++ b/src/dot.cpp @@ -146,7 +146,7 @@ DotFilePatcher *DotManager::createFilePatcher(const QCString &fileName) if (patcher != m_filePatchers.end()) return &(patcher->second); - auto rv = m_filePatchers.emplace(fileName.str(), fileName.data()); + auto rv = m_filePatchers.emplace(std::make_pair(fileName.str(), fileName)); assert(rv.second); return &(rv.first->second); } @@ -287,7 +287,7 @@ void writeDotGraphFromFile(const QCString &inFile,const QCString &outDir, DotRunner dotRun(inFile); if (format==GOF_BITMAP) { - dotRun.addJob(Config_getEnum(DOT_IMAGE_FORMAT),absImgName,srcFile,srcLine); + dotRun.addJob(Config_getEnumAsString(DOT_IMAGE_FORMAT),absImgName,srcFile,srcLine); } else // format==GOF_EPS { diff --git a/src/dotcallgraph.h b/src/dotcallgraph.h index 53edf87..382f4eb 100644 --- a/src/dotcallgraph.h +++ b/src/dotcallgraph.h @@ -16,6 +16,8 @@ #ifndef DOTCALLGRAPH_H #define DOTCALLGRAPH_H +#include <memory> + #include "dotnode.h" #include "dotgraph.h" #include "memberdef.h" @@ -51,4 +53,6 @@ class DotCallGraph : public DotGraph const Definition * m_scope; }; +using DotCallGraphPtr = std::shared_ptr<DotCallGraph>; + #endif diff --git a/src/dotclassgraph.h b/src/dotclassgraph.h index 6ccba08..d4ffb14 100644 --- a/src/dotclassgraph.h +++ b/src/dotclassgraph.h @@ -16,6 +16,8 @@ #ifndef DOTCLASSGRAPH_H #define DOTCLASSGRAPH_H +#include <memory> + #include "classdef.h" #include "dotnode.h" #include "dotgraph.h" @@ -61,5 +63,6 @@ private: bool m_lrRank; }; +using DotClassGraphPtr = std::shared_ptr<DotClassGraph>; #endif diff --git a/src/dotdirdeps.cpp b/src/dotdirdeps.cpp index 12236a0..27ba67c 100644 --- a/src/dotdirdeps.cpp +++ b/src/dotdirdeps.cpp @@ -13,173 +13,385 @@ * */ -#include <sstream> - #include "dotdirdeps.h" #include "util.h" #include "doxygen.h" #include "config.h" +#include "image.h" + +#include <algorithm> +#include <iterator> +#include <utility> +#include <cstdint> +#include <math.h> +#include <cassert> +#include <map> +#include <memory> +#include <string> +#include <vector> using DirDefMap = std::map<std::string,const DirDef *>; +/** Properties are used to format the directories in the graph distinctively. */ +struct DotDirProperty +{ + bool isIncomplete = false; //!< true if not all successors of a cluster are drawn + bool isOrphaned = false; //!< true if parent is not drawn + bool isTruncated = false; //!< true has successors, none is drawn + bool isOriginal = false; //!< true if is the directory for which the graph is drawn + bool isPeripheral = false; //!< true if no successor of parent of original directory +}; + +/** Builder helper to create instances of the DotDirProperty struct */ +class DotDirPropertyBuilder +{ + public: + DotDirPropertyBuilder &makeIncomplete(bool b=true) { m_property.isIncomplete=b; return *this; } + DotDirPropertyBuilder &makeOrphaned (bool b=true) { m_property.isOrphaned =b; return *this; } + DotDirPropertyBuilder &makeTruncated (bool b=true) { m_property.isTruncated =b; return *this; } + DotDirPropertyBuilder &makeOriginal (bool b=true) { m_property.isOriginal =b; return *this; } + DotDirPropertyBuilder &makePeripheral(bool b=true) { m_property.isPeripheral=b; return *this; } + operator DotDirProperty() { return std::move(m_property); } + private: + DotDirProperty m_property; +}; + +/** Elements consist of (1) directory relation and (2) whether it is pointing only to inherited dependees. */ +typedef std::vector< std::pair< std::unique_ptr<DirRelation>, bool> > DirRelations; + +/** Returns a DOT color name according to the directory depth. */ +static QCString getDirectoryBackgroundColor(int depthIndex) +{ + static int hue = Config_getInt(HTML_COLORSTYLE_HUE); + static int sat = Config_getInt(HTML_COLORSTYLE_SAT); + static int gamma = Config_getInt(HTML_COLORSTYLE_GAMMA); + assert(depthIndex>=0 && depthIndex<=Config_getInt(DIR_GRAPH_MAX_DEPTH)); + float fraction = (float)depthIndex/(float)Config_getInt(DIR_GRAPH_MAX_DEPTH); + const char hex[] = "0123456789abcdef"; + int range = 0x40; // range from darkest color to lightest color + int luma = 0xef-(int)(fraction*range); // interpolation + double r,g,b; + ColoredImage::hsl2rgb(hue/360.0,sat/255.0, + pow(luma/255.0,gamma/100.0),&r,&g,&b); + int red = (int)(r*255.0); + int green = (int)(g*255.0); + int blue = (int)(b*255.0); + assert(red>=0 && red<=255); + assert(green>=0 && green<=255); + assert(blue>=0 && blue<=255); + char colStr[8]; + colStr[0]='#'; + colStr[1]=hex[red>>4]; + colStr[2]=hex[red&0xf]; + colStr[3]=hex[green>>4]; + colStr[4]=hex[green&0xf]; + colStr[5]=hex[blue>>4]; + colStr[6]=hex[blue&0xf]; + colStr[7]=0; + //printf("i=%d max=%d fraction=%f luma=%d %02x %02x %02x -> color=%s\n", + // depthIndex,Config_getInt(DIR_GRAPH_MAX_DEPTH),fraction,luma,red,green,blue,colStr); + return colStr; +} + +/** Returns a DOT color name according to the directory properties. */ +static const char* getDirectoryBorderColor(const DotDirProperty &property) +{ + if (property.isTruncated && property.isOrphaned) + { + return "red"; + } + else if (property.isTruncated) + { + return "red"; + } + else if (property.isOrphaned) + { + return "grey50"; + } + else + { + return "grey25"; + } +} + +/** Returns a DOT node style according to the directory properties. */ +static std::string getDirectoryBorderStyle(const DotDirProperty &property) +{ + std::string style; + if (!property.isPeripheral) + { + style += "filled,"; + } + if (property.isOriginal) + { + style += "bold,"; + } + if (property.isIncomplete) + { + style += "dashed,"; + } + else if (property.isTruncated && property.isOrphaned) + { + style += "dashed,"; + } + return style; +} + /** * Puts DOT code for drawing directory to stream and adds it to the list. - * @param[in,out] outStream stream to which the DOT code is written to + * @param[in,out] t stream to which the DOT code is written to * @param[in] directory will be mapped to a node in DOT code - * @param[in] fillBackground if the node shall be explicitly filled + * @param[in] property are evaluated for formatting * @param[in,out] directoriesInGraph lists the directories which have been written to the output stream + * @param[in] startLevel current level to calculate relative distances from to determine the background color + */ +static void drawDirectory(TextStream &t, const DirDef *const directory, const DotDirProperty &property, + DirDefMap &directoriesInGraph,int startLevel) +{ + t << " " << directory->getOutputFileBase() << " [" + "shape=box, " + "label=\"" << directory->shortName() << "\", " + "style=\"" << getDirectoryBorderStyle(property) << "\", " + "fillcolor=\"" << getDirectoryBackgroundColor(directory->level()-startLevel) << "\", " + "color=\"" << getDirectoryBorderColor(property) << "\", " + "URL=\"" << addHtmlExtensionIfMissing(directory->getOutputFileBase()) << "\"" + "];\n"; + directoriesInGraph.insert(std::make_pair(directory->getOutputFileBase().str(), directory)); +} + +/** Checks, if the directory is a the maximum drawn directory level. */ +static bool isAtMaxDepth(const DirDef *const directory, const int startLevel) +{ + return (directory->level() - startLevel) >= Config_getInt(DIR_GRAPH_MAX_DEPTH); +} + +/** + * Writes DOT code for opening a cluster subgraph to stream. + * + * Ancestor clusters directly get a label. Other clusters get a plain text node with a label instead. + * This is because the plain text node can be used to draw dependency relationships. */ -static void drawDirectory(TextStream &outStream, const DirDef *const directory, const bool fillBackground, - DirDefMap &directoriesInGraph) +static void drawClusterOpening(TextStream &outputStream, const DirDef *const directory, + const DotDirProperty &directoryProperty, DirDefMap &directoriesInGraph, const bool isAncestor,int startLevel) { - outStream << " " << directory->getOutputFileBase() << " [shape=box " - "label=\"" << directory->shortName() << "\" "; - if (fillBackground) + outputStream << " subgraph cluster" << directory->getOutputFileBase() << " {\n" + " graph [ " + "bgcolor=\"" << getDirectoryBackgroundColor(directory->level()-startLevel) << "\", " + "pencolor=\"" << getDirectoryBorderColor(directoryProperty) << "\", " + "style=\"" << getDirectoryBorderStyle(directoryProperty) << "\", " + "label=\""; + if (isAncestor) { - outStream << "fillcolor=\"white\" style=\"filled\" "; + outputStream << directory->shortName(); } - if (directory->isCluster()) + outputStream << "\", " + "fontname=\"" << Config_getString(DOT_FONTNAME) << "\", " + "fontsize=\"" << Config_getInt(DOT_FONTSIZE) << "\", " + "URL=\"" << addHtmlExtensionIfMissing(directory->getOutputFileBase()) << "\"" + "]\n"; + if (!isAncestor) { - outStream << "color=\"red\" "; + outputStream << " " << directory->getOutputFileBase() << " [shape=plaintext, " + "label=\"" << directory->shortName() << "\"" + "];\n"; + directoriesInGraph.insert(std::make_pair(directory->getOutputFileBase().str(), directory)); } - outStream << "URL=\"" << directory->getOutputFileBase() << Doxygen::htmlFileExtension << "\"];\n"; - directoriesInGraph.insert(std::make_pair(directory->getOutputFileBase().str(), directory)); } -void writeDotDirDepGraph(TextStream &t,const DirDef *dd,bool linkRelations) +static void drawClusterClosing(TextStream &t) +{ + t << " }\n"; +} + +/** + * Assembles a list of the directory relations and whether or not they result from "inheritance". + * @param dependencies Array to add the dependencies to. + * @param srcDir is the source of the dependency. + * @param isLeaf true, if no children are drawn for this directory. + */ +static void addDependencies(DirRelations &dependencies,const DirDef *const srcDir, bool isLeaf) { - int fontSize = Config_getInt(DOT_FONTSIZE); - QCString fontName = Config_getString(DOT_FONTNAME); - t << "digraph \"" << dd->displayName() << "\" {\n"; - if (Config_getBool(DOT_TRANSPARENT)) + for (const auto &usedDirectory : srcDir->usedDirs()) { - t << " bgcolor=transparent;\n"; + const auto dstDir = usedDirectory->dir(); + if (!dstDir->isParentOf(srcDir) && (isLeaf || usedDirectory->hasDirectSrcDeps())) + { + QCString relationName; + relationName.sprintf("dir_%06d_%06d", srcDir->dirCount(), dstDir->dirCount()); + bool directRelation = isLeaf ? usedDirectory->hasDirectDstDeps() : usedDirectory->hasDirectDeps(); + auto &&dependency = std::make_unique<DirRelation>(relationName, srcDir, usedDirectory.get()); + auto &&pair = std::make_pair(std::move(dependency),directRelation); + dependencies.emplace_back(std::move(pair)); + } } - t << " compound=true\n"; - t << " node [ fontsize=\"" << fontSize << "\", fontname=\"" << fontName << "\"];\n"; - t << " edge [ labelfontsize=\"" << fontSize << "\", labelfontname=\"" << fontName << "\"];\n"; +} +/** Recursively draws directory tree. */ +static void drawTree(DirRelations &dependencies, TextStream &t, const DirDef *const directory, + int startLevel, DirDefMap &directoriesInGraph, const bool isTreeRoot) +{ + if (!directory->hasSubdirs()) + { + const DotDirProperty directoryProperty = DotDirPropertyBuilder().makeOriginal(isTreeRoot); + drawDirectory(t, directory, directoryProperty, directoriesInGraph,startLevel); + addDependencies(dependencies, directory, true); + } + else + { + if (isAtMaxDepth(directory, startLevel)) // maximum nesting level reached + { + const DotDirProperty directoryProperty = DotDirPropertyBuilder().makeOriginal(isTreeRoot); + drawDirectory(t, directory, directoryProperty, directoriesInGraph,startLevel); + addDependencies(dependencies, directory, true); + } + else // start a new nesting level + { + // open cluster + { + const DotDirProperty directoryProperty = DotDirPropertyBuilder().makeOriginal(isTreeRoot); + drawClusterOpening(t, directory, directoryProperty, directoriesInGraph, false, startLevel); + addDependencies(dependencies, directory, false); + } + + // process all sub directories + for (const auto subDirectory : directory->subDirs()) + { + drawTree(dependencies, t, subDirectory, startLevel, directoriesInGraph, false); + } + + // close cluster + { + drawClusterClosing(t); + } + } + } +} + +/** + * Write DOT code for directory dependency graph. + * + * Code is generated for a directory. Successors (sub-directories) of this directory are recursively drawn. + * Recursion is limited by `DIR_GRAPH_MAX_DEPTH`. The dependencies of those directories + * are drawn. + * + * If a dependee is not part of directory tree above, then the dependency is drawn to the first parent of the + * dependee, whose parent is an ancestor (sub-directory) of the original directory. + * + * @param t stream where the DOT code is written to + * @param dd directory for which the graph is generated for + * @param linkRelations if true, hyperlinks to the list of file dependencies are added + */ +void writeDotDirDepGraph(TextStream &t,const DirDef *dd,bool linkRelations) +{ DirDefMap dirsInGraph; dirsInGraph.insert(std::make_pair(dd->getOutputFileBase().str(),dd)); - std::vector<const DirDef *> usedDirsNotDrawn; - for(const auto& usedDir : dd->usedDirs()) + std::vector<const DirDef *> usedDirsNotDrawn, usedDirsDrawn; + for (const auto& usedDir : dd->usedDirs()) { usedDirsNotDrawn.push_back(usedDir->dir()); } + auto moveDrawnDirs = [&usedDirsDrawn,&usedDirsNotDrawn](const std::vector<const DirDef *>::iterator &newEnd) + { + // usedDirsNotDrawn is split into two segments: [begin()....newEnd-1] and [newEnd....end()] + // where the second segment starting at newEnd has been drawn, so append this segment to the usedDirsDrawn list and + // remove it from the usedDirsNotDrawn list. + std::move(newEnd, std::end(usedDirsNotDrawn), std::back_inserter(usedDirsDrawn)); + usedDirsNotDrawn.erase(newEnd, usedDirsNotDrawn.end()); + }; + + // if dd has a parent draw it as the outer layer const auto parent = dd->parent(); if (parent) { - t << " subgraph cluster" << dd->parent()->getOutputFileBase() << " {\n"; - t << " graph [ bgcolor=\"#ddddee\", pencolor=\"black\", label=\"" - << dd->parent()->shortName() - << "\" fontname=\"" << fontName << "\", fontsize=\"" << fontSize << "\", URL=\""; - t << dd->parent()->getOutputFileBase() << Doxygen::htmlFileExtension; - t << "\"]\n"; + const DotDirProperty parentDirProperty = DotDirPropertyBuilder(). + makeIncomplete(). + makeOrphaned(parent->parent()!=nullptr); + drawClusterOpening(t, parent, parentDirProperty, dirsInGraph, true, parent->level()); { // draw all directories which have `dd->parent()` as parent and `dd` as dependent - const auto newEnd = std::remove_if(usedDirsNotDrawn.begin(), usedDirsNotDrawn.end(), [&](const DirDef *const usedDir) - { - if (dd!=usedDir && dd->parent()==usedDir->parent()) + const auto newEnd = std::stable_partition(usedDirsNotDrawn.begin(), usedDirsNotDrawn.end(), + [&](const DirDef *const usedDir) { - drawDirectory(t, usedDir, usedDir->isCluster() && !Config_getBool(DOT_TRANSPARENT), dirsInGraph); - return true; - } - return false; - } - ); - usedDirsNotDrawn.erase(newEnd, usedDirsNotDrawn.end()); + if (dd!=usedDir && dd->parent()==usedDir->parent()) // usedDir and dd share the same parent + { + const DotDirProperty usedDirProperty = DotDirPropertyBuilder().makeTruncated(usedDir->hasSubdirs()); + drawDirectory(t, usedDir, usedDirProperty, dirsInGraph, parent->level()); + return false; // part of the drawn partition + } + return true; // part of the not-drawn partition + }); + moveDrawnDirs(newEnd); } } - if (dd->isCluster()) - { - t << " subgraph cluster" << dd->getOutputFileBase() << " {\n"; - t << " graph [ bgcolor=\"#eeeeff\", pencolor=\"black\", label=\"\"" - << " URL=\"" << dd->getOutputFileBase() << Doxygen::htmlFileExtension - << "\"];\n"; - t << " " << dd->getOutputFileBase() << " [shape=plaintext label=\"" - << dd->shortName() << "\"];\n"; - // add nodes for sub directories - for(const auto sdir : dd->subDirs()) - { - drawDirectory(t, sdir, true, dirsInGraph); - } - t << " }\n"; - } - else - { - t << " " << dd->getOutputFileBase() << " [shape=box, label=\"" - << dd->shortName() << "\", style=\"filled\", fillcolor=\"#eeeeff\"," - << " pencolor=\"black\", URL=\"" << dd->getOutputFileBase() - << Doxygen::htmlFileExtension << "\"];\n"; - } - if (dd->parent()) + // draw the directory tree with dd as root + DirRelations dependencies; + drawTree(dependencies, t, dd, dd->level(), dirsInGraph, true); + + if (parent) { - t << " }\n"; + drawClusterClosing(t); } - // add nodes for other used directories + // add nodes for other used directories (i.e. outside of the cluster of directories directly connected to dd) { - //printf("*** For dir %s\n",qPrint(shortName())); - for (const auto &usedDir : usedDirsNotDrawn) - // for each used dir (=directly used or a parent of a directly used dir) - { - const DirDef *dir=dd; - while (dir) - { - //printf("*** check relation %s->%s same_parent=%d !%s->isParentOf(%s)=%d\n", - // qPrint(dir->shortName()),qPrint(usedDir->shortName()), - // dir->parent()==usedDir->parent(), - // qPrint(usedDir->shortName()), - // qPrint(shortName()), - // !usedDir->isParentOf(this) - // ); - if (dir!=usedDir && dir->parent()==usedDir->parent()) - // include if both have the same parent (or no parent) - { - drawDirectory(t, usedDir, usedDir->isCluster() && !Config_getBool(DOT_TRANSPARENT), dirsInGraph); - break; - } - dir=dir->parent(); - } - } + const auto newEnd = std::stable_partition(usedDirsNotDrawn.begin(), usedDirsNotDrawn.end(), + [&](const DirDef *const usedDir) // for each used dir (=directly used or a parent of a directly used dir) + { + const DirDef *dir=dd; + while (dir) + { + if (dir!=usedDir && dir->parent()==usedDir->parent()) // include if both have the same parent (or no parent) + { + const DotDirProperty usedDirProperty = DotDirPropertyBuilder(). + makeOrphaned(usedDir->parent()!=nullptr). + makeTruncated(usedDir->hasSubdirs()). + makePeripheral(); + drawDirectory(t, usedDir, usedDirProperty, dirsInGraph, dir->level()); + return false; // part of the drawn partition + } + dir=dir->parent(); + } + return true; // part of the not-drawn partition + }); + moveDrawnDirs(newEnd); } // add relations between all selected directories - for (const auto &kv : dirsInGraph) // foreach dir in the graph { - const DirDef *dir = kv.second; - for (const auto &udir : dir->usedDirs()) + for (const auto &relationPair : dependencies) { - const DirDef *usedDir=udir->dir(); - if ((dir!=dd || !udir->inherited()) && // only show direct dependencies for this dir - (usedDir!=dd || !udir->inherited()) && // only show direct dependencies for this dir - !usedDir->isParentOf(dir) && // don't point to own parent - dirsInGraph.find(usedDir->getOutputFileBase().str())!=dirsInGraph.end()) // only point to nodes that are in the graph + const auto &relation = relationPair.first; + const bool directRelation = relationPair.second; + const auto udir = relation->destination(); + const auto usedDir = udir->dir(); + const bool destIsSibling = std::find(std::begin(usedDirsDrawn), std::end(usedDirsDrawn), usedDir) != std::end(usedDirsDrawn); + const bool destIsDrawn = dirsInGraph.find(usedDir->getOutputFileBase().str())!=dirsInGraph.end(); // only point to nodes that are in the graph + const bool atMaxDepth = isAtMaxDepth(usedDir, dd->level()); + + if (destIsSibling || (destIsDrawn && (directRelation || atMaxDepth))) { - QCString relationName; - relationName.sprintf("dir_%06d_%06d",dir->dirCount(),usedDir->dirCount()); + const auto relationName = relation->getOutputFileBase(); + const auto dir = relation->source(); Doxygen::dirRelations.add(relationName, std::make_unique<DirRelation>( - relationName,dir,udir.get())); + relationName,dir,udir)); size_t nrefs = udir->filePairs().size(); t << " " << dir->getOutputFileBase() << "->" << usedDir->getOutputFileBase(); t << " [headlabel=\"" << (uint)nrefs << "\", labeldistance=1.5"; if (linkRelations) { - t << " headhref=\"" << relationName << Doxygen::htmlFileExtension << "\""; + t << " headhref=\"" << addHtmlExtensionIfMissing(relationName) << "\""; } t << "];\n"; } } } - - t << "}\n"; } DotDirDeps::DotDirDeps(const DirDef *dir) : m_dir(dir) @@ -200,7 +412,10 @@ void DotDirDeps::computeTheGraph() { // compute md5 checksum of the graph were are about to generate TextStream md5stream; + writeGraphHeader(md5stream, m_dir->displayName()); + md5stream << " compound=true\n"; writeDotDirDepGraph(md5stream,m_dir,m_linkRelations); + writeGraphFooter(md5stream); m_theGraph = md5stream.str(); } @@ -214,15 +429,9 @@ QCString DotDirDeps::getImgAltText() const return convertToXML(m_dir->displayName()); } -QCString DotDirDeps::writeGraph(TextStream &out, - GraphOutputFormat graphFormat, - EmbeddedOutputFormat textFormat, - const QCString &path, - const QCString &fileName, - const QCString &relPath, - bool generateImageMap, - int graphId, - bool linkRelations) +QCString DotDirDeps::writeGraph(TextStream &out, GraphOutputFormat graphFormat, EmbeddedOutputFormat textFormat, + const QCString &path, const QCString &fileName, const QCString &relPath, bool generateImageMap, + int graphId, bool linkRelations) { m_linkRelations = linkRelations; m_urlOnly = TRUE; diff --git a/src/dotdirdeps.h b/src/dotdirdeps.h index 4f915f9..b3fe517 100644 --- a/src/dotdirdeps.h +++ b/src/dotdirdeps.h @@ -16,6 +16,8 @@ #ifndef DOTDIRDEPS_H #define DOTDIRDEPS_H +#include <memory> + #include "dotgraph.h" #include "dirdef.h" @@ -48,4 +50,6 @@ class DotDirDeps : public DotGraph bool m_linkRelations = false; }; +using DotDirDepsPtr = std::shared_ptr<DotDirDeps>; + #endif diff --git a/src/dotfilepatcher.cpp b/src/dotfilepatcher.cpp index 5b0c68c..dcb3ecb 100644 --- a/src/dotfilepatcher.cpp +++ b/src/dotfilepatcher.cpp @@ -153,7 +153,7 @@ static QCString replaceRef(const QCString &buf,const QCString &relPath, std::unique_ptr<DocRef> df { createRef( *parser.get(), link.mid(5), context ) }; result+=externalRef(relPath,df->ref(),TRUE); if (!df->file().isEmpty()) - result += df->file() + Doxygen::htmlFileExtension; + result += addHtmlExtensionIfMissing(df->file()); if (!df->anchor().isEmpty()) result += "#" + df->anchor(); result += "\""; diff --git a/src/dotgfxhierarchytable.cpp b/src/dotgfxhierarchytable.cpp index 025e7cb..1668761 100644 --- a/src/dotgfxhierarchytable.cpp +++ b/src/dotgfxhierarchytable.cpp @@ -250,11 +250,7 @@ DotGfxHierarchyTable::DotGfxHierarchyTable(const QCString &prefix,ClassDef::Comp n->markAsVisible(); n->colorConnectedNodes(curColor); curColor++; - const DotNode *dn=n->findDocNode(); - if (dn!=0) - m_rootSubgraphs.push_back(const_cast<DotNode*>(dn)); - else - m_rootSubgraphs.push_back(n); + m_rootSubgraphs.push_back(n); } } } diff --git a/src/dotgfxhierarchytable.h b/src/dotgfxhierarchytable.h index 0d37881..dfec97a 100644 --- a/src/dotgfxhierarchytable.h +++ b/src/dotgfxhierarchytable.h @@ -56,5 +56,6 @@ class DotGfxHierarchyTable : public DotGraph DotNode * m_rootSubgraphNode; }; +using DotGfxHierarchyTablePtr = std::shared_ptr<DotGfxHierarchyTable>; #endif diff --git a/src/dotgraph.cpp b/src/dotgraph.cpp index f8cb194..f55a8d9 100644 --- a/src/dotgraph.cpp +++ b/src/dotgraph.cpp @@ -182,7 +182,7 @@ bool DotGraph::prepareDotFile() { // run dot to create a bitmap image DotRunner * dotRun = DotManager::instance()->createRunner(absDotName(), sigStr); - dotRun->addJob(Config_getEnum(DOT_IMAGE_FORMAT), absImgName(), absDotName(), 1); + dotRun->addJob(Config_getEnumAsString(DOT_IMAGE_FORMAT), absImgName(), absDotName(), 1); if (m_generateImageMap) dotRun->addJob(MAP_CMD, absMapName(), absDotName(), 1); } else if (m_graphFormat == GOF_EPS) diff --git a/src/dotgroupcollaboration.cpp b/src/dotgroupcollaboration.cpp index d409d50..58dd75b 100644 --- a/src/dotgroupcollaboration.cpp +++ b/src/dotgroupcollaboration.cpp @@ -101,7 +101,7 @@ void DotGroupCollaboration::buildGraph(const GroupDef* gd) // Add classes for (const auto &def : gd->getClasses()) { - tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension; + tmp_url = def->getReference()+"$"+addHtmlExtensionIfMissing(def->getOutputFileBase()); if (!def->anchor().isEmpty()) { tmp_url+="#"+def->anchor(); @@ -112,21 +112,21 @@ void DotGroupCollaboration::buildGraph(const GroupDef* gd) // Add namespaces for (const auto &def : gd->getNamespaces()) { - tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension; + tmp_url = def->getReference()+"$"+addHtmlExtensionIfMissing(def->getOutputFileBase()); addCollaborationMember( def, tmp_url, DotGroupCollaboration::tnamespace ); } // Add files for (const auto &def : gd->getFiles()) { - tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension; + tmp_url = def->getReference()+"$"+addHtmlExtensionIfMissing(def->getOutputFileBase()); addCollaborationMember( def, tmp_url, DotGroupCollaboration::tfile ); } // Add pages for (const auto &def : gd->getPages()) { - tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension; + tmp_url = def->getReference()+"$"+addHtmlExtensionIfMissing(def->getOutputFileBase()); addCollaborationMember( def, tmp_url, DotGroupCollaboration::tpages ); } @@ -135,7 +135,7 @@ void DotGroupCollaboration::buildGraph(const GroupDef* gd) { for(const auto def : gd->getDirs()) { - tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension; + tmp_url = def->getReference()+"$"+addHtmlExtensionIfMissing(def->getOutputFileBase()); addCollaborationMember( def, tmp_url, DotGroupCollaboration::tdir ); } } @@ -146,7 +146,7 @@ void DotGroupCollaboration::addMemberList( MemberList* ml ) if ( ml==0 || ml->empty() ) return; for (const auto &def : *ml) { - QCString tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension + QCString tmp_url = def->getReference()+"$"+addHtmlExtensionIfMissing(def->getOutputFileBase()); +"#"+def->anchor(); addCollaborationMember( def, tmp_url, DotGroupCollaboration::tmember ); } diff --git a/src/dotgroupcollaboration.h b/src/dotgroupcollaboration.h index 872e7f7..ddb12bb 100644 --- a/src/dotgroupcollaboration.h +++ b/src/dotgroupcollaboration.h @@ -16,6 +16,8 @@ #ifndef DOTGROUPCOLLABORATION_H #define DOTGROUPCOLLABORATION_H +#include <memory> + #include "dotnode.h" #include "dotgraph.h" #include "groupdef.h" @@ -83,4 +85,6 @@ class DotGroupCollaboration : public DotGraph std::vector< std::unique_ptr<Edge> > m_edges; }; +using DotGroupCollaborationPtr = std::shared_ptr<DotGroupCollaboration>; + #endif diff --git a/src/dotincldepgraph.h b/src/dotincldepgraph.h index a0e58bf..aa340ab 100644 --- a/src/dotincldepgraph.h +++ b/src/dotincldepgraph.h @@ -16,6 +16,8 @@ #ifndef DOTINCLDEPGRAPH_H #define DOTINCLDEPGRAPH_H +#include <memory> + #include "qcstring.h" #include "filedef.h" @@ -57,4 +59,6 @@ class DotInclDepGraph : public DotGraph bool m_inverse; }; +using DotInclDepGraphPtr = std::shared_ptr<DotInclDepGraph>; + #endif diff --git a/src/dotnode.cpp b/src/dotnode.cpp index bfc7c08..b91f111 100644 --- a/src/dotnode.cpp +++ b/src/dotnode.cpp @@ -96,30 +96,6 @@ static EdgeProperties umlEdgeProps = umlEdgeColorMap, umlArrowStyleMap, umlEdgeStyleMap }; -// Extracted from config setting "DOT_UML_DETAILS" -enum class UmlDetailLevel -{ - Default, // == NO, the default setting - Full, // == YES, include type and arguments - None // == NONE, don't include compartments for attributes and methods -}; - -// Local helper function for extracting the configured detail level -static UmlDetailLevel getUmlDetailLevelFromConfig() -{ - UmlDetailLevel result = UmlDetailLevel::Default; - QCString umlDetailsStr = Config_getEnum(DOT_UML_DETAILS).upper(); - if (umlDetailsStr == "YES") - { - result=UmlDetailLevel::Full; - } - else if (umlDetailsStr == "NONE") - { - result=UmlDetailLevel::None; - } - return result; -} - static QCString escapeTooltip(const QCString &tooltip) { if (tooltip.isEmpty()) return tooltip; @@ -155,6 +131,7 @@ static void writeBoxMemberList(TextStream &t, } int count=0; + static auto dotUmlDetails = Config_getEnum(DOT_UML_DETAILS); for (const auto &mma : *ml) { if (mma->getClassDef() == scope && @@ -170,7 +147,7 @@ static void writeBoxMemberList(TextStream &t, { t << prot << " "; QCString label; - if(getUmlDetailLevelFromConfig()==UmlDetailLevel::Full) + if (dotUmlDetails==DOT_UML_DETAILS_t::YES) { label+=mma->typeString(); label+=" "; @@ -178,7 +155,7 @@ static void writeBoxMemberList(TextStream &t, label+=mma->name(); if (!mma->isObjCMethod() && (mma->isFunction() || mma->isSlot() || mma->isSignal())) { - if(getUmlDetailLevelFromConfig()==UmlDetailLevel::Full) + if (dotUmlDetails==DOT_UML_DETAILS_t::YES) { label+=mma->argsString(); } @@ -382,9 +359,27 @@ void DotNode::writeBox(TextStream &t, GraphOutputFormat /*format*/, bool hasNonReachableChildren) const { - const char *labCol = - m_url.isEmpty() ? "grey75" : // non link + const char *labCol; + if (m_classDef) + { + if (m_classDef->hasDocumentation() && hasNonReachableChildren) + labCol = "red"; + else if (m_classDef->hasDocumentation() && !hasNonReachableChildren) + labCol = "black"; + else if (!m_classDef->hasDocumentation() && hasNonReachableChildren) + labCol = "orangered"; + else // (!m_classDef->hasDocumentation() && !hasNonReachableChildren) + { + labCol = "grey75"; + if (m_classDef->templateMaster() && m_classDef->templateMaster()->hasDocumentation()) + labCol = "black"; + } + } + else + { + labCol = m_url.isEmpty() ? "grey75" : // non link (hasNonReachableChildren ? "red" : "black"); + } t << " Node" << m_number << " [label=\""; if (m_classDef && Config_getBool(UML_LOOK) && (gt==Inheritance || gt==Collaboration)) @@ -413,7 +408,8 @@ void DotNode::writeBox(TextStream &t, //printf("DotNode::writeBox for %s\n",qPrint(m_classDef->name())); t << "{" << convertLabel(m_label) << "\\n"; - if (getUmlDetailLevelFromConfig()!=UmlDetailLevel::None) + static auto dotUmlDetails = Config_getEnum(DOT_UML_DETAILS); + if (dotUmlDetails!=DOT_UML_DETAILS_t::NONE) { t << "|"; writeBoxMemberList(t,'+',m_classDef->getMemberList(MemberListType_pubAttribs),m_classDef,FALSE,&arrowNames); @@ -467,26 +463,22 @@ void DotNode::writeBox(TextStream &t, } else { + t << ",color=\"" << labCol << "\""; if (!Config_getBool(DOT_TRANSPARENT)) { - t << ",color=\"" << labCol << "\", fillcolor=\""; - t << "white"; - t << "\", style=\"filled\""; - } - else - { - t << ",color=\"" << labCol << "\""; + t << ", fillcolor=\"white\""; + t << ", style=\"filled\""; } if (!m_url.isEmpty()) { int anchorPos = m_url.findRev('#'); if (anchorPos==-1) { - t << ",URL=\"" << m_url << Doxygen::htmlFileExtension << "\""; + t << ",URL=\"" << addHtmlExtensionIfMissing(m_url) << "\""; } else { - t << ",URL=\"" << m_url.left(anchorPos) << Doxygen::htmlFileExtension + t << ",URL=\"" << addHtmlExtensionIfMissing(m_url.left(anchorPos)) << m_url.right(m_url.length()-anchorPos) << "\""; } } @@ -816,43 +808,38 @@ void DotNode::colorConnectedNodes(int curColor) } } +#define DEBUG_RENUMBERING 0 + void DotNode::renumberNodes(int &number) { - m_number = number++; - for (const auto &cn : m_children) + if (!isRenumbered()) { - if (!cn->isRenumbered()) +#if DEBUG_RENUMBERING + static int level = 0; + printf("%3d: ",subgraphId()); + for (int i = 0; i < level; i++) printf(" "); + printf("> %s old = %d new = %d\n",qPrint(m_label),m_number,number); + level++; +#endif + m_number = number++; + markRenumbered(); + for (const auto &cn : m_children) { - cn->markRenumbered(); cn->renumberNodes(number); } - } -} - -const DotNode *DotNode::findDocNode() const -{ - if (!m_url.isEmpty()) return this; - //printf("findDocNode(): '%s'\n",qPrint(m_label)); - for (const auto &pn : m_parents) - { - if (!pn->hasDocumentation()) - { - pn->markHasDocumentation(); - const DotNode *dn = pn->findDocNode(); - if (dn) return dn; - } - } - for (const auto &cn : m_children) - { - if (!cn->hasDocumentation()) + for (const auto &pn : m_parents) { - cn->markHasDocumentation(); - const DotNode *dn = cn->findDocNode(); - if (dn) return dn; + pn->renumberNodes(number); } +#if DEBUG_RENUMBERING + level--; + printf("%3d: ",subgraphId()); + for (int i = 0; i < level; i++) printf(" "); + printf("< %s assigned = %d\n",qPrint(m_label),m_number); +#endif } - return 0; } + diff --git a/src/dotnode.h b/src/dotnode.h index cd1e75b..c630951 100644 --- a/src/dotnode.h +++ b/src/dotnode.h @@ -104,7 +104,6 @@ class DotNode void colorConnectedNodes(int curColor); void setDistance(int distance); - const DotNode *findDocNode() const; // only works for acyclic graphs! void markAsVisible(bool b=TRUE) { m_visible=b; } void markAsTruncated(bool b=TRUE) { m_truncated=b ? Truncated : Untruncated; } const DotNodeRefVector &children() const { return m_children; } diff --git a/src/doxygen.cpp b/src/doxygen.cpp index 87eb5fc..4686fce 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -308,15 +308,7 @@ static void addRelatedPage(Entry *root) if (!g.groupname.isEmpty() && (gd=Doxygen::groupLinkedMap->find(g.groupname))) break; } //printf("---> addRelatedPage() %s gd=%p\n",qPrint(root->name),gd); - QCString doc; - if (root->brief.isEmpty()) - { - doc=root->doc+root->inbodyDocs; - } - else - { - doc=root->brief+"\n\n"+root->doc+root->inbodyDocs; - } + QCString doc=root->doc+root->inbodyDocs; PageDef *pd = addRelatedPage(root->name,root->args,doc, root->docFile, @@ -1244,6 +1236,7 @@ static void addConceptToContext(const Entry *root) cd->setLanguage(root->lang); cd->setId(root->id); cd->setHidden(root->hidden); + cd->setGroupId(root->mGrpId); if (tArgList) { cd->setTemplateArguments(*tArgList); @@ -1307,6 +1300,37 @@ static void buildConceptDocList(const Entry *root) for (const auto &e : root->children()) buildConceptDocList(e.get()); } +// This routine is to allow @ingroup X @{ concept A; concept B; @} to work +// (same also works for variable and functions because of logic in MemberGroup::insertMember) +static void distributeConceptGroups() +{ + for (const auto &cd : *Doxygen::conceptLinkedMap) + { + if (cd->groupId()!=DOX_NOGROUP) + { + for (const auto &ocd : *Doxygen::conceptLinkedMap) + { + if (cd!=ocd && cd->groupId()==ocd->groupId() && + !cd->partOfGroups().empty() && ocd->partOfGroups().empty()) + { + ConceptDefMutable *ocdm = toConceptDefMutable(ocd.get()); + if (ocdm) + { + for (const auto &gd : cd->partOfGroups()) + { + if (gd) + { + ocdm->makePartOfGroup(gd); + const_cast<GroupDef*>(gd)->addConcept(ocd.get()); + } + } + } + } + } + } + } +} + //---------------------------------------------------------------------- static void resolveClassNestingRelations() @@ -3612,6 +3636,11 @@ static void buildFunctionList(const Entry *root) sameRequiresClause = FALSE; } } + else if (!mdTempl.empty() || !root->tArgLists.empty()) + { // if one has template parameters and the other doesn't then that also counts as a + // difference + sameNumTemplateArgs = FALSE; + } bool staticsInDifferentFiles = root->stat && md->isStatic() && root->fileName!=md->getDefFileName(); @@ -4101,7 +4130,7 @@ static void findUsedClassesForClass(const Entry *root, } // add any template arguments to the class QCString usedName = removeRedundantWhiteSpace(usedClassName+templSpec); - //printf(" usedName=%s\n",qPrint(usedName)); + //printf(" usedName=%s usedClassName=%s templSpec=%s\n",qPrint(usedName),qPrint(usedClassName),qPrint(templSpec)); TemplateNameMap formTemplateNames; if (templateNames.empty()) @@ -5114,7 +5143,7 @@ static void addMemberDocs(const Entry *root, { if (md==0) return; //printf("addMemberDocs: '%s'::'%s' '%s' funcDecl='%s' mSpec=%lld\n", - // qPrint(root->parent()->name),qPrint(md->name()),md->argsString(),funcDecl,spec); + // qPrint(root->parent()->name),qPrint(md->name()),qPrint(md->argsString()),qPrint(funcDecl),spec); QCString fDecl=funcDecl; // strip extern specifier fDecl.stripPrefix("extern "); @@ -5579,7 +5608,7 @@ static QCString substituteTemplatesInString( dst+=src.substr(p); //printf(" substituteTemplatesInString(%s)=%s\n", // qPrint(src),qPrint(dst)); - return dst; + return QCString(dst); } static void substituteTemplatesInArgList( @@ -6642,7 +6671,7 @@ static void findMember(const Entry *root, root->fileName,root->startLine,root->startColumn, funcType,funcName,funcArgs,exceptions, root->protection,root->virt, - root->stat && !isMemberOf, + root->stat, isMemberOf ? Foreign : Related, mtype, (!root->tArgLists.empty() ? root->tArgLists.back() : ArgumentList()), @@ -7575,7 +7604,7 @@ static void findDocumentedEnumValues() static void addMembersToIndex() { - // for each member name + // for each class member name for (const auto &mn : *Doxygen::memberNameLinkedMap) { // for each member definition @@ -7584,7 +7613,7 @@ static void addMembersToIndex() addClassMemberNameToIndex(md.get()); } } - // for each member name + // for each file/namespace function name for (const auto &mn : *Doxygen::functionNameLinkedMap) { // for each member definition @@ -7605,6 +7634,164 @@ static void addMembersToIndex() //---------------------------------------------------------------------- +static void addToIndices() +{ + for (const auto &cd : *Doxygen::classLinkedMap) + { + if (cd->isLinkableInProject()) + { + Doxygen::indexList->addIndexItem(cd.get(),0); + if (Doxygen::searchIndex) + { + Doxygen::searchIndex->setCurrentDoc(cd.get(),cd->anchor(),FALSE); + Doxygen::searchIndex->addWord(cd->localName(),TRUE); + } + } + } + + for (const auto &cd : *Doxygen::conceptLinkedMap) + { + if (cd->isLinkableInProject()) + { + Doxygen::indexList->addIndexItem(cd.get(),0); + if (Doxygen::searchIndex) + { + Doxygen::searchIndex->setCurrentDoc(cd.get(),cd->anchor(),FALSE); + Doxygen::searchIndex->addWord(cd->localName(),TRUE); + } + } + } + + for (const auto &nd : *Doxygen::namespaceLinkedMap) + { + if (nd->isLinkableInProject()) + { + Doxygen::indexList->addIndexItem(nd.get(),0); + if (Doxygen::searchIndex) + { + Doxygen::searchIndex->setCurrentDoc(nd.get(),nd->anchor(),FALSE); + Doxygen::searchIndex->addWord(nd->localName(),TRUE); + } + } + } + + for (const auto &fn : *Doxygen::inputNameLinkedMap) + { + for (const auto &fd : *fn) + { + if (Doxygen::searchIndex && fd->isLinkableInProject()) + { + Doxygen::searchIndex->setCurrentDoc(fd.get(),fd->anchor(),FALSE); + Doxygen::searchIndex->addWord(fd->localName(),TRUE); + } + } + } + + for (const auto &gd : *Doxygen::groupLinkedMap) + { + if (gd->isLinkableInProject()) + { + Doxygen::indexList->addIndexItem(gd.get(),0,QCString(),gd->groupTitle()); + if (Doxygen::searchIndex) + { + Doxygen::searchIndex->setCurrentDoc(gd.get(),gd->anchor(),FALSE); + std::string title = gd->groupTitle().str(); + static const reg::Ex re(R"(\a[\w-]*)"); + reg::Iterator it(title,re); + reg::Iterator end; + for (; it!=end ; ++it) + { + const auto &match = *it; + std::string matchStr = match.str(); + Doxygen::searchIndex->addWord(matchStr.c_str(),TRUE); + } + } + } + } + + for (const auto &pd : *Doxygen::pageLinkedMap) + { + if (pd->isLinkableInProject()) + { + Doxygen::indexList->addIndexItem(pd.get(),0,QCString(),filterTitle(pd->title().str())); + } + } + + auto addMemberToSearchIndex = [](const MemberDef *md) + { + if (Doxygen::searchIndex) + { + Doxygen::searchIndex->setCurrentDoc(md,md->anchor(),FALSE); + QCString ln=md->localName(); + QCString qn=md->qualifiedName(); + Doxygen::searchIndex->addWord(ln,TRUE); + if (ln!=qn) + { + Doxygen::searchIndex->addWord(qn,TRUE); + if (md->getClassDef()) + { + Doxygen::searchIndex->addWord(md->getClassDef()->displayName(),TRUE); + } + if (md->getNamespaceDef()) + { + Doxygen::searchIndex->addWord(md->getNamespaceDef()->displayName(),TRUE); + } + } + } + }; + + auto getScope = [](const MemberDef *md) + { + const Definition *scope = 0; + if (md->getGroupDef()) scope = md->getGroupDef(); + else if (md->getClassDef()) scope = md->getClassDef(); + else if (md->getNamespaceDef()) scope = md->getNamespaceDef(); + else if (md->getFileDef()) scope = md->getFileDef(); + return scope; + }; + + auto addMemberToIndices = [addMemberToSearchIndex,getScope](const MemberDef *md) + { + if (md->isLinkableInProject()) + { + if (!(md->isEnumerate() && md->isAnonymous())) + { + Doxygen::indexList->addIndexItem(getScope(md),md); + addMemberToSearchIndex(md); + } + if (md->isEnumerate()) + { + for (const auto &fmd : md->enumFieldList()) + { + Doxygen::indexList->addIndexItem(getScope(fmd),fmd); + addMemberToSearchIndex(fmd); + } + } + } + }; + + // for each class member name + for (const auto &mn : *Doxygen::memberNameLinkedMap) + { + // for each member definition + for (const auto &md : *mn) + { + addMemberToIndices(md.get()); + } + } + // for each file/namespace function name + for (const auto &mn : *Doxygen::functionNameLinkedMap) + { + // for each member definition + for (const auto &md : *mn) + { + addMemberToIndices(md.get()); + } + } +} + +//---------------------------------------------------------------------- + static void vhdlCorrectMemberProperties() { // for each member name @@ -7670,7 +7857,7 @@ static void computeMemberRelations() bmd->getLanguage()==SrcLangExt_Python || bmd->getLanguage()==SrcLangExt_Java || bmd->getLanguage()==SrcLangExt_PHP || bmcd->compoundType()==ClassDef::Interface || bmcd->compoundType()==ClassDef::Protocol ) && - md->isFunction() && + (md->isFunction() || md->isCSharpProperty()) && mcd->isLinkable() && bmcd->isLinkable() && mcd->isBaseClass(bmcd,TRUE)) @@ -7924,14 +8111,17 @@ static void generateFileSources() auto ctx = std::make_shared<SourceContext>(fd.get(),generateSourceFile,*g_outputList); if (generateSourceFile) { - msg("Generating code for file %s...\n",qPrint(fd->docName())); fd->writeSourceHeader(ctx->ol); } - else - { - msg("Parsing code for file %s...\n",qPrint(fd->docName())); - } auto processFile = [ctx]() { + if (ctx->generateSourceFile) + { + msg("Generating code for file %s...\n",qPrint(ctx->fd->docName())); + } + else + { + msg("Parsing code for file %s...\n",qPrint(ctx->fd->docName())); + } StringVector filesInSameTu; ctx->fd->getAllIncludeFilesRecursively(filesInSameTu); if (ctx->generateSourceFile) // sources need to be shown in the output @@ -7993,15 +8183,56 @@ static void generateFileDocs() if (!Doxygen::inputNameLinkedMap->empty()) { - for (const auto &fn : *Doxygen::inputNameLinkedMap) + std::size_t numThreads = static_cast<std::size_t>(Config_getInt(NUM_PROC_THREADS)); + if (numThreads==0) + { + numThreads = std::thread::hardware_concurrency(); + } + if (numThreads>1) // multi threaded processing { - for (const auto &fd : *fn) + struct DocContext + { + DocContext(FileDef *fd_,OutputList ol_) + : fd(fd_), ol(ol_) {} + FileDef *fd; + OutputList ol; + }; + ThreadPool threadPool(numThreads); + std::vector< std::future< std::shared_ptr<DocContext> > > results; + for (const auto &fn : *Doxygen::inputNameLinkedMap) { - bool doc = fd->isLinkableInProject(); - if (doc) + for (const auto &fd : *fn) { - msg("Generating docs for file %s...\n",qPrint(fd->docName())); - fd->writeDocumentation(*g_outputList); + bool doc = fd->isLinkableInProject(); + if (doc) + { + auto ctx = std::make_shared<DocContext>(fd.get(),*g_outputList); + auto processFile = [ctx]() { + msg("Generating docs for file %s...\n",qPrint(ctx->fd->docName())); + ctx->fd->writeDocumentation(ctx->ol); + return ctx; + }; + results.emplace_back(threadPool.queue(processFile)); + } + } + } + for (auto &f : results) + { + auto ctx = f.get(); + } + } + else // single threaded processing + { + for (const auto &fn : *Doxygen::inputNameLinkedMap) + { + for (const auto &fd : *fn) + { + bool doc = fd->isLinkableInProject(); + if (doc) + { + msg("Generating docs for file %s...\n",qPrint(fd->docName())); + fd->writeDocumentation(*g_outputList); + } } } } @@ -8240,28 +8471,83 @@ static void countMembers() static void generateClassList(const ClassLinkedMap &classList) { - for (const auto &cdi : classList) + std::size_t numThreads = static_cast<std::size_t>(Config_getInt(NUM_PROC_THREADS)); + if (numThreads==0) { - ClassDefMutable *cd=toClassDefMutable(cdi.get()); + numThreads = std::thread::hardware_concurrency(); + } + if (numThreads>1) // multi threaded processing + { + struct DocContext + { + DocContext(ClassDefMutable *cd_,OutputList ol_) + : cd(cd_), ol(ol_) {} + ClassDefMutable *cd; + OutputList ol; + }; + ThreadPool threadPool(numThreads); + std::vector< std::future< std::shared_ptr<DocContext> > > results; + for (const auto &cdi : classList) + { + ClassDefMutable *cd=toClassDefMutable(cdi.get()); - //printf("cd=%s getOuterScope=%p global=%p\n",qPrint(cd->name()),cd->getOuterScope(),Doxygen::globalScope); - if (cd && - (cd->getOuterScope()==0 || // <-- should not happen, but can if we read an old tag file - cd->getOuterScope()==Doxygen::globalScope // only look at global classes - ) && !cd->isHidden() && !cd->isEmbeddedInOuterScope() - ) + //printf("cd=%s getOuterScope=%p global=%p\n",qPrint(cd->name()),cd->getOuterScope(),Doxygen::globalScope); + if (cd && + (cd->getOuterScope()==0 || // <-- should not happen, but can if we read an old tag file + cd->getOuterScope()==Doxygen::globalScope // only look at global classes + ) && !cd->isHidden() && !cd->isEmbeddedInOuterScope() + ) + { + auto ctx = std::make_shared<DocContext>(cd,*g_outputList); + auto processFile = [ctx]() + { + msg("Generating docs for compound %s...\n",qPrint(ctx->cd->name())); + + // skip external references, anonymous compounds and + // template instances + if ( ctx->cd->isLinkableInProject() && ctx->cd->templateMaster()==0) + { + ctx->cd->writeDocumentation(ctx->ol); + ctx->cd->writeMemberList(ctx->ol); + } + + // even for undocumented classes, the inner classes can be documented. + ctx->cd->writeDocumentationForInnerClasses(ctx->ol); + return ctx; + }; + results.emplace_back(threadPool.queue(processFile)); + } + } + for (auto &f : results) { - // skip external references, anonymous compounds and - // template instances - if ( cd->isLinkableInProject() && cd->templateMaster()==0) + auto ctx = f.get(); + } + } + else // single threaded processing + { + for (const auto &cdi : classList) + { + ClassDefMutable *cd=toClassDefMutable(cdi.get()); + + //printf("cd=%s getOuterScope=%p global=%p\n",qPrint(cd->name()),cd->getOuterScope(),Doxygen::globalScope); + if (cd && + (cd->getOuterScope()==0 || // <-- should not happen, but can if we read an old tag file + cd->getOuterScope()==Doxygen::globalScope // only look at global classes + ) && !cd->isHidden() && !cd->isEmbeddedInOuterScope() + ) { - msg("Generating docs for compound %s...\n",qPrint(cd->name())); + // skip external references, anonymous compounds and + // template instances + if ( cd->isLinkableInProject() && cd->templateMaster()==0) + { + msg("Generating docs for compound %s...\n",qPrint(cd->name())); - cd->writeDocumentation(*g_outputList); - cd->writeMemberList(*g_outputList); + cd->writeDocumentation(*g_outputList); + cd->writeMemberList(*g_outputList); + } + // even for undocumented classes, the inner classes can be documented. + cd->writeDocumentationForInnerClasses(*g_outputList); } - // even for undocumented classes, the inner classes can be documented. - cd->writeDocumentationForInnerClasses(*g_outputList); } } } @@ -8479,6 +8765,9 @@ static void findSectionsInDocumentation() if (Doxygen::mainPage) Doxygen::mainPage->findSectionsInDocumentation(); } +//---------------------------------------------------------------------- + + static void flushCachedTemplateRelations() { // remove all references to classes from the cache @@ -9098,6 +9387,7 @@ static void generateExampleDocs() pd->docLine(), // startLine pd.get(), // context 0, // memberDef + (pd->briefDescription().isEmpty()?"":pd->briefDescription()+"\n\n")+ pd->documentation()+"\n\n\\include"+lineNoOptStr+" "+pd->name(), // docs TRUE, // index words TRUE, // is example @@ -9130,25 +9420,76 @@ static void generateGroupDocs() static void generateNamespaceClassDocs(const ClassLinkedRefMap &classList) { - // for each class in the namespace... - for (const auto &cd : classList) + std::size_t numThreads = static_cast<std::size_t>(Config_getInt(NUM_PROC_THREADS)); + if (numThreads==0) { - ClassDefMutable *cdm = toClassDefMutable(cd); - if (cdm) + numThreads = std::thread::hardware_concurrency(); + } + if (numThreads>1) // multi threaded processing + { + struct DocContext { - if ( ( cd->isLinkableInProject() && - cd->templateMaster()==0 - ) // skip external references, anonymous compounds and - // template instances and nested classes - && !cd->isHidden() && !cd->isEmbeddedInOuterScope() - ) + DocContext(ClassDefMutable *cdm_,OutputList ol_) + : cdm(cdm_), ol(ol_) {} + ClassDefMutable *cdm; + OutputList ol; + }; + ThreadPool threadPool(numThreads); + std::vector< std::future< std::shared_ptr<DocContext> > > results; + // for each class in the namespace... + for (const auto &cd : classList) + { + ClassDefMutable *cdm = toClassDefMutable(cd); + if (cdm) + { + auto ctx = std::make_shared<DocContext>(cdm,*g_outputList); + auto processFile = [ctx]() + { + if ( ( ctx->cdm->isLinkableInProject() && + ctx->cdm->templateMaster()==0 + ) // skip external references, anonymous compounds and + // template instances and nested classes + && !ctx->cdm->isHidden() && !ctx->cdm->isEmbeddedInOuterScope() + ) + { + msg("Generating docs for compound %s...\n",qPrint(ctx->cdm->name())); + ctx->cdm->writeDocumentation(ctx->ol); + ctx->cdm->writeMemberList(ctx->ol); + } + ctx->cdm->writeDocumentationForInnerClasses(ctx->ol); + return ctx; + }; + results.emplace_back(threadPool.queue(processFile)); + } + } + // wait for the results + for (auto &f : results) + { + auto ctx = f.get(); + } + } + else // single threaded processing + { + // for each class in the namespace... + for (const auto &cd : classList) + { + ClassDefMutable *cdm = toClassDefMutable(cd); + if (cdm) { - msg("Generating docs for compound %s...\n",qPrint(cd->name())); + if ( ( cd->isLinkableInProject() && + cd->templateMaster()==0 + ) // skip external references, anonymous compounds and + // template instances and nested classes + && !cd->isHidden() && !cd->isEmbeddedInOuterScope() + ) + { + msg("Generating docs for compound %s...\n",qPrint(cd->name())); - cdm->writeDocumentation(*g_outputList); - cdm->writeMemberList(*g_outputList); + cdm->writeDocumentation(*g_outputList); + cdm->writeMemberList(*g_outputList); + } + cdm->writeDocumentationForInnerClasses(*g_outputList); } - cdm->writeDocumentationForInnerClasses(*g_outputList); } } } @@ -9919,6 +10260,8 @@ static void readDir(FileInfo *fi, msg("Searching for files in directory %s\n", qPrint(fi->absFilePath())); //printf("killSet=%p count=%d\n",killSet,killSet ? (int)killSet->count() : -1); + StringVector dirResultList; + for (const auto &dirEntry : dir.iterator()) { FileInfo cfi(dirEntry.path()); @@ -9952,7 +10295,7 @@ static void readDir(FileInfo *fi, fn->push_back(std::move(fd)); } } - if (resultList) resultList->push_back(fullName); + dirResultList.push_back(fullName); if (resultSet) resultSet->insert(fullName); if (killSet) killSet->insert(fullName); } @@ -9964,17 +10307,20 @@ static void readDir(FileInfo *fi, { FileInfo acfi(cfi.absFilePath()); readDir(&acfi,fnMap,exclSet, - patList,exclPatList,resultList,resultSet,errorIfNotExist, + patList,exclPatList,&dirResultList,resultSet,errorIfNotExist, recursive,killSet,paths); } } } - if (resultList) + if (resultList && !dirResultList.empty()) { // sort the resulting list to make the order platform independent. - std::sort(resultList->begin(), - resultList->end(), + std::sort(dirResultList.begin(), + dirResultList.end(), [](const auto &f1,const auto &f2) { return qstricmp(f1.c_str(),f2.c_str())<0; }); + + // append the sorted results to resultList + resultList->insert(resultList->end(), dirResultList.begin(), dirResultList.end()); } } @@ -10157,10 +10503,10 @@ static void dumpSymbol(TextStream &t,Definition *d) QCString scope; if (d->getOuterScope() && d->getOuterScope()!=Doxygen::globalScope) { - scope = d->getOuterScope()->getOutputFileBase()+Doxygen::htmlFileExtension; + scope = addHtmlExtensionIfMissing(d->getOuterScope()->getOutputFileBase()); } t << "REPLACE INTO symbols (symbol_id,scope_id,name,file,line) VALUES('" - << d->getOutputFileBase()+Doxygen::htmlFileExtension+anchor << "','" + << addHtmlExtensionIfMissing(d->getOutputFileBase())+anchor << "','" << scope << "','" << d->name() << "','" << d->getDefFileName() << "','" @@ -10213,10 +10559,6 @@ static void version(const bool extended) extVers += "clang support "; extVers += CLANG_VERSION_STRING; #endif -#if MULTITHREADED_SOURCE_GENERATOR - if (!extVers.isEmpty()) extVers+= ", "; - extVers += "multi-threaded support "; -#endif if (!extVers.isEmpty()) { int lastComma = extVers.findRev(','); @@ -10266,15 +10608,15 @@ static void usage(const QCString &name,const QCString &versionString) //---------------------------------------------------------------------------- // read the argument of option 'c' from the comment argument list and -// update the option index 'optind'. +// update the option index 'optInd'. -static const char *getArg(int argc,char **argv,int &optind) +static const char *getArg(int argc,char **argv,int &optInd) { char *s=0; - if (qstrlen(&argv[optind][2])>0) - s=&argv[optind][2]; - else if (optind+1<argc && argv[optind+1][0]!='-') - s=argv[++optind]; + if (qstrlen(&argv[optInd][2])>0) + s=&argv[optInd][2]; + else if (optInd+1<argc && argv[optInd+1][0]!='-') + s=argv[++optInd]; return s; } @@ -10431,7 +10773,7 @@ void readConfiguration(int argc, char **argv) * Handle arguments * **************************************************************************/ - int optind=1; + int optInd=1; QCString configName; QCString layoutName; QCString debugLabel; @@ -10443,31 +10785,31 @@ void readConfiguration(int argc, char **argv) bool updateConfig=FALSE; int retVal; bool quiet = false; - while (optind<argc && argv[optind][0]=='-' && - (isalpha(argv[optind][1]) || argv[optind][1]=='?' || - argv[optind][1]=='-') + while (optInd<argc && argv[optInd][0]=='-' && + (isalpha(argv[optInd][1]) || argv[optInd][1]=='?' || + argv[optInd][1]=='-') ) { - switch(argv[optind][1]) + switch(argv[optInd][1]) { case 'g': genConfig=TRUE; break; case 'l': - if (optind+1>=argc) + if (optInd+1>=argc) { layoutName="DoxygenLayout.xml"; } else { - layoutName=argv[optind+1]; + layoutName=argv[optInd+1]; } writeDefaultLayoutFile(layoutName); cleanUpDoxygen(); exit(0); break; case 'd': - debugLabel=getArg(argc,argv,optind); + debugLabel=getArg(argc,argv,optInd); if (debugLabel.isEmpty()) { devUsage(); @@ -10493,7 +10835,7 @@ void readConfiguration(int argc, char **argv) updateConfig=TRUE; break; case 'e': - formatName=getArg(argc,argv,optind); + formatName=getArg(argc,argv,optInd); if (formatName.isEmpty()) { err("option \"-e\" is missing format specifier rtf.\n"); @@ -10502,14 +10844,14 @@ void readConfiguration(int argc, char **argv) } if (qstricmp(formatName.data(),"rtf")==0) { - if (optind+1>=argc) + if (optInd+1>=argc) { err("option \"-e rtf\" is missing an extensions file name\n"); cleanUpDoxygen(); exit(1); } std::ofstream f; - if (openOutputFile(argv[optind+1],f)) + if (openOutputFile(argv[optInd+1],f)) { TextStream t(&f); RTFGenerator::writeExtensionsFile(t); @@ -10522,7 +10864,7 @@ void readConfiguration(int argc, char **argv) exit(1); break; case 'f': - listName=getArg(argc,argv,optind); + listName=getArg(argc,argv,optInd); if (listName.isEmpty()) { err("option \"-f\" is missing list specifier.\n"); @@ -10531,14 +10873,14 @@ void readConfiguration(int argc, char **argv) } if (qstricmp(listName.data(),"emoji")==0) { - if (optind+1>=argc) + if (optInd+1>=argc) { err("option \"-f emoji\" is missing an output file name\n"); cleanUpDoxygen(); exit(1); } std::ofstream f; - if (openOutputFile(argv[optind+1],f)) + if (openOutputFile(argv[optInd+1],f)) { TextStream t(&f); EmojiEntityMapper::instance()->writeEmojiFile(t); @@ -10551,7 +10893,7 @@ void readConfiguration(int argc, char **argv) exit(1); break; case 'w': - formatName=getArg(argc,argv,optind); + formatName=getArg(argc,argv,optInd); if (formatName.isEmpty()) { err("option \"-w\" is missing format specifier rtf, html or latex\n"); @@ -10560,14 +10902,14 @@ void readConfiguration(int argc, char **argv) } if (qstricmp(formatName.data(),"rtf")==0) { - if (optind+1>=argc) + if (optInd+1>=argc) { err("option \"-w rtf\" is missing a style sheet file name\n"); cleanUpDoxygen(); exit(1); } std::ofstream f; - if (openOutputFile(argv[optind+1],f)) + if (openOutputFile(argv[optInd+1],f)) { TextStream t(&f); RTFGenerator::writeStyleSheetFile(t); @@ -10578,46 +10920,43 @@ void readConfiguration(int argc, char **argv) else if (qstricmp(formatName.data(),"html")==0) { Config::init(); - if (optind+4<argc || FileInfo("Doxyfile").exists()) + if (optInd+4<argc || FileInfo("Doxyfile").exists()) // explicit config file mentioned or default found on disk { - QCString df = optind+4<argc ? argv[optind+4] : QCString("Doxyfile"); + QCString df = optInd+4<argc ? argv[optInd+4] : QCString("Doxyfile"); if (!Config::parse(df)) // parse the config file { - err("error opening or reading configuration file %s!\n",argv[optind+4]); + err("error opening or reading configuration file %s!\n",argv[optInd+4]); cleanUpDoxygen(); exit(1); } } - if (optind+3>=argc) + if (optInd+3>=argc) { err("option \"-w html\" does not have enough arguments\n"); cleanUpDoxygen(); exit(1); } Config::postProcess(TRUE); - Config::checkAndCorrect(Config_getBool(QUIET)); + Config::updateObsolete(); + Config::checkAndCorrect(Config_getBool(QUIET), false); - QCString outputLanguage=Config_getEnum(OUTPUT_LANGUAGE); - if (!setTranslator(outputLanguage)) - { - warn_uncond("Output language %s not supported! Using English instead.\n", qPrint(outputLanguage)); - } + setTranslator(Config_getEnum(OUTPUT_LANGUAGE)); std::ofstream f; - if (openOutputFile(argv[optind+1],f)) + if (openOutputFile(argv[optInd+1],f)) { TextStream t(&f); - HtmlGenerator::writeHeaderFile(t, argv[optind+3]); + HtmlGenerator::writeHeaderFile(t, argv[optInd+3]); } f.close(); - if (openOutputFile(argv[optind+2],f)) + if (openOutputFile(argv[optInd+2],f)) { TextStream t(&f); HtmlGenerator::writeFooterFile(t); } f.close(); - if (openOutputFile(argv[optind+3],f)) + if (openOutputFile(argv[optInd+3],f)) { TextStream t(&f); HtmlGenerator::writeStyleSheetFile(t); @@ -10628,45 +10967,42 @@ void readConfiguration(int argc, char **argv) else if (qstricmp(formatName.data(),"latex")==0) { Config::init(); - if (optind+4<argc || FileInfo("Doxyfile").exists()) + if (optInd+4<argc || FileInfo("Doxyfile").exists()) { - QCString df = optind+4<argc ? argv[optind+4] : QCString("Doxyfile"); + QCString df = optInd+4<argc ? argv[optInd+4] : QCString("Doxyfile"); if (!Config::parse(df)) { - err("error opening or reading configuration file %s!\n",argv[optind+4]); + err("error opening or reading configuration file %s!\n",argv[optInd+4]); cleanUpDoxygen(); exit(1); } } - if (optind+3>=argc) + if (optInd+3>=argc) { err("option \"-w latex\" does not have enough arguments\n"); cleanUpDoxygen(); exit(1); } Config::postProcess(TRUE); - Config::checkAndCorrect(Config_getBool(QUIET)); + Config::updateObsolete(); + Config::checkAndCorrect(Config_getBool(QUIET), false); - QCString outputLanguage=Config_getEnum(OUTPUT_LANGUAGE); - if (!setTranslator(outputLanguage)) - { - warn_uncond("Output language %s not supported! Using English instead.\n", qPrint(outputLanguage)); - } + setTranslator(Config_getEnum(OUTPUT_LANGUAGE)); std::ofstream f; - if (openOutputFile(argv[optind+1],f)) + if (openOutputFile(argv[optInd+1],f)) { TextStream t(&f); LatexGenerator::writeHeaderFile(t); } f.close(); - if (openOutputFile(argv[optind+2],f)) + if (openOutputFile(argv[optInd+2],f)) { TextStream t(&f); LatexGenerator::writeFooterFile(t); } f.close(); - if (openOutputFile(argv[optind+3],f)) + if (openOutputFile(argv[optInd+3],f)) { TextStream t(&f); LatexGenerator::writeStyleSheetFile(t); @@ -10695,19 +11031,19 @@ void readConfiguration(int argc, char **argv) exit(0); break; case '-': - if (qstrcmp(&argv[optind][2],"help")==0) + if (qstrcmp(&argv[optInd][2],"help")==0) { usage(argv[0],versionString); exit(0); } - else if (qstrcmp(&argv[optind][2],"version")==0) + else if (qstrcmp(&argv[optInd][2],"version")==0) { version(false); cleanUpDoxygen(); exit(0); } - else if ((qstrcmp(&argv[optind][2],"Version")==0) || - (qstrcmp(&argv[optind][2],"VERSION")==0)) + else if ((qstrcmp(&argv[optInd][2],"Version")==0) || + (qstrcmp(&argv[optInd][2],"VERSION")==0)) { version(true); cleanUpDoxygen(); @@ -10715,7 +11051,7 @@ void readConfiguration(int argc, char **argv) } else { - err("Unknown option \"-%s\"\n",&argv[optind][1]); + err("Unknown option \"-%s\"\n",&argv[optInd][1]); usage(argv[0],versionString); exit(1); } @@ -10738,11 +11074,11 @@ void readConfiguration(int argc, char **argv) exit(0); break; default: - err("Unknown option \"-%c\"\n",argv[optind][1]); + err("Unknown option \"-%c\"\n",argv[optInd][1]); usage(argv[0],versionString); exit(1); } - optind++; + optInd++; } /************************************************************************** @@ -10752,7 +11088,7 @@ void readConfiguration(int argc, char **argv) Config::init(); FileInfo configFileInfo1("Doxyfile"),configFileInfo2("doxyfile"); - if (optind>=argc) + if (optInd>=argc) { if (configFileInfo1.exists()) { @@ -10775,14 +11111,14 @@ void readConfiguration(int argc, char **argv) } else { - FileInfo fi(argv[optind]); - if (fi.exists() || qstrcmp(argv[optind],"-")==0 || genConfig) + FileInfo fi(argv[optInd]); + if (fi.exists() || qstrcmp(argv[optInd],"-")==0 || genConfig) { - configName=argv[optind]; + configName=argv[optInd]; } else { - err("configuration file %s not found!\n",argv[optind]); + err("configuration file %s not found!\n",argv[optInd]); usage(argv[0],versionString); exit(1); } @@ -10811,6 +11147,7 @@ void readConfiguration(int argc, char **argv) if (diffList) { + Config::updateObsolete(); compareDoxyfile(); cleanUpDoxygen(); exit(0); @@ -10818,6 +11155,7 @@ void readConfiguration(int argc, char **argv) if (updateConfig) { + Config::updateObsolete(); generateConfigFile(configName,shortList,TRUE); cleanUpDoxygen(); exit(0); @@ -10836,7 +11174,8 @@ void checkConfiguration() { Config::postProcess(FALSE); - Config::checkAndCorrect(Config_getBool(QUIET)); + Config::updateObsolete(); + Config::checkAndCorrect(Config_getBool(QUIET), true); initWarningFormat(); } @@ -10852,12 +11191,7 @@ void adjustConfiguration() Doxygen::mscFileNameLinkedMap = new FileNameLinkedMap; Doxygen::diaFileNameLinkedMap = new FileNameLinkedMap; - QCString outputLanguage=Config_getEnum(OUTPUT_LANGUAGE); - if (!setTranslator(outputLanguage)) - { - warn_uncond("Output language %s not supported! Using English instead.\n", - qPrint(outputLanguage)); - } + setTranslator(Config_getEnum(OUTPUT_LANGUAGE)); /* Set the global html file extension. */ Doxygen::htmlFileExtension = Config_getString(HTML_FILE_EXTENSION); @@ -10924,6 +11258,7 @@ void adjustConfiguration() #ifdef HAS_SIGNALS static void stopDoxygen(int) { + signal(SIGINT,SIG_DFL); // Re-register signal handler for default action Dir thisDir; msg("Cleaning up...\n"); if (!Doxygen::filterDBFileName.isEmpty()) @@ -11323,6 +11658,19 @@ void parseInput() { htmlOutput = createOutputDirectory(outputDirectory,Config_getString(HTML_OUTPUT),"/html"); Config_updateString(HTML_OUTPUT,htmlOutput); + + // add HTML indexers that are enabled + bool generateHtmlHelp = Config_getBool(GENERATE_HTMLHELP); + bool generateEclipseHelp = Config_getBool(GENERATE_ECLIPSEHELP); + bool generateQhp = Config_getBool(GENERATE_QHP); + bool generateTreeView = Config_getBool(GENERATE_TREEVIEW); + bool generateDocSet = Config_getBool(GENERATE_DOCSET); + if (generateEclipseHelp) Doxygen::indexList->addIndex<EclipseHelp>(); + if (generateHtmlHelp) Doxygen::indexList->addIndex<HtmlHelp>(); + if (generateQhp) Doxygen::indexList->addIndex<Qhp>(); + if (generateTreeView) Doxygen::indexList->addIndex<FTVHelp>(TRUE); + if (generateDocSet) Doxygen::indexList->addIndex<DocSets>(); + Doxygen::indexList->initialize(); } QCString docbookOutput; @@ -11547,6 +11895,7 @@ void parseInput() g_s.begin("Associating documentation with concepts...\n"); buildConceptDocList(root.get()); + distributeConceptGroups(); g_s.end(); g_s.begin("Building example list...\n"); @@ -11821,6 +12170,7 @@ void parseInput() g_s.begin("Adding members to index pages...\n"); addMembersToIndex(); + addToIndices(); g_s.end(); g_s.begin("Correcting members for VHDL...\n"); @@ -11876,19 +12226,6 @@ void generateOutput() { g_outputList->add<HtmlGenerator>(); HtmlGenerator::init(); - - // add HTML indexers that are enabled - bool generateHtmlHelp = Config_getBool(GENERATE_HTMLHELP); - bool generateEclipseHelp = Config_getBool(GENERATE_ECLIPSEHELP); - bool generateQhp = Config_getBool(GENERATE_QHP); - bool generateTreeView = Config_getBool(GENERATE_TREEVIEW); - bool generateDocSet = Config_getBool(GENERATE_DOCSET); - if (generateEclipseHelp) Doxygen::indexList->addIndex<EclipseHelp>(); - if (generateHtmlHelp) Doxygen::indexList->addIndex<HtmlHelp>(); - if (generateQhp) Doxygen::indexList->addIndex<Qhp>(); - if (generateTreeView) Doxygen::indexList->addIndex<FTVHelp>(TRUE); - if (generateDocSet) Doxygen::indexList->addIndex<DocSets>(); - Doxygen::indexList->initialize(); HtmlGenerator::writeTabData(); } if (generateLatex) @@ -11959,12 +12296,35 @@ void generateOutput() } g_s.end(); + // copy static stuff + if (generateHtml) + { + FTVHelp::generateTreeViewImages(); + copyStyleSheet(); + copyLogo(Config_getString(HTML_OUTPUT)); + copyExtraFiles(Config_getList(HTML_EXTRA_FILES),"HTML_EXTRA_FILES",Config_getString(HTML_OUTPUT)); + } + if (generateLatex) + { + copyLatexStyleSheet(); + copyLogo(Config_getString(LATEX_OUTPUT)); + copyExtraFiles(Config_getList(LATEX_EXTRA_FILES),"LATEX_EXTRA_FILES",Config_getString(LATEX_OUTPUT)); + } + if (generateDocbook) + { + copyLogo(Config_getString(DOCBOOK_OUTPUT)); + } + if (generateRtf) + { + copyLogo(Config_getString(RTF_OUTPUT)); + } + const FormulaManager &fm = FormulaManager::instance(); if (fm.hasFormulas() && generateHtml && !Config_getBool(USE_MATHJAX)) { g_s.begin("Generating images for formulas in HTML...\n"); - fm.generateImages(Config_getString(HTML_OUTPUT), Config_getEnum(HTML_FORMULA_FORMAT)=="svg" ? + fm.generateImages(Config_getString(HTML_OUTPUT), Config_getEnum(HTML_FORMULA_FORMAT)==HTML_FORMULA_FORMAT_t::svg ? FormulaManager::Format::Vector : FormulaManager::Format::Bitmap, FormulaManager::HighDPI::On); g_s.end(); } @@ -12094,7 +12454,12 @@ void generateOutput() g_s.end(); } - if (g_useOutputTemplate) generateOutputViaTemplate(); + if (g_useOutputTemplate) + { + g_s.begin("Generating output via template engine...\n"); + generateOutputViaTemplate(); + g_s.end(); + } warn_flush(); @@ -12123,29 +12488,6 @@ void generateOutput() g_s.end(); } - // copy static stuff - if (generateHtml) - { - FTVHelp::generateTreeViewImages(); - copyStyleSheet(); - copyLogo(Config_getString(HTML_OUTPUT)); - copyExtraFiles(Config_getList(HTML_EXTRA_FILES),"HTML_EXTRA_FILES",Config_getString(HTML_OUTPUT)); - } - if (generateLatex) - { - copyLatexStyleSheet(); - copyLogo(Config_getString(LATEX_OUTPUT)); - copyExtraFiles(Config_getList(LATEX_EXTRA_FILES),"LATEX_EXTRA_FILES",Config_getString(LATEX_OUTPUT)); - } - if (generateDocbook) - { - copyLogo(Config_getString(DOCBOOK_OUTPUT)); - } - if (generateRtf) - { - copyLogo(Config_getString(RTF_OUTPUT)); - } - if (generateHtml && Config_getBool(GENERATE_HTMLHELP) && !Config_getString(HHC_LOCATION).isEmpty()) diff --git a/src/doxygen_lex.h b/src/doxygen_lex.h new file mode 100644 index 0000000..bb61660 --- /dev/null +++ b/src/doxygen_lex.h @@ -0,0 +1,56 @@ +/****************************************************************************** + * + * Copyright (C) 2021 by Dimitri van Heesch. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software + * for any purpose. It is provided "as is" without express or implied warranty. + * See the GNU General Public License for more details. + * + * Documents produced by Doxygen are derivative works derived from the + * input used in their production; they are not affected by this license. + * + */ + +#ifndef DOXYGEN_LEX_H +#define DOXYGEN_LEX_H + +#ifndef LEX_NO_REENTRANT +#ifndef LEX_NO_INPUT_FILENAME +#define YY_FATAL_ERROR(msg) \ +{ \ + QCString msg1 = msg; \ + msg1 += "\n lexical analyzer: "; \ + msg1 += getLexerFILE(); \ + if (!((struct yyguts_t*)yyscanner)->yyextra_r->fileName.isEmpty()) \ + { \ + msg1 += " (for: "; \ + msg1 += ((struct yyguts_t*)yyscanner)->yyextra_r->fileName; \ + msg1 += ")"; \ + } \ + msg1 += "\n"; \ + yy_fatal_error( qPrint(msg1) , yyscanner); \ +} +#else +#define YY_FATAL_ERROR(msg) \ +{ \ + QCString msg1 = msg; \ + msg1 += "\n lexical analyzer: "; \ + msg1 += getLexerFILE(); \ + msg1 += "\n"; \ + yy_fatal_error( qPrint(msg1) , yyscanner); \ +} +#endif +#else +#define YY_FATAL_ERROR(msg) \ +{ \ + QCString msg1 = msg; \ + msg1 += "\n lexical analyzer: "; \ + msg1 += getLexerFILE(); \ + msg1 += "\n"; \ + yy_fatal_error( qPrint(msg1)); \ +} +#endif + +#endif diff --git a/src/eclipsehelp.cpp b/src/eclipsehelp.cpp index b2f8193..53a370b 100644 --- a/src/eclipsehelp.cpp +++ b/src/eclipsehelp.cpp @@ -188,7 +188,7 @@ void EclipseHelp::addContentsItem( indent(); m_tocstream << "<topic label=\"" << convertToXML(name) << "\""; m_tocstream << " href=\"" << convertToXML(m_pathprefix) - << file << Doxygen::htmlFileExtension; + << addHtmlExtensionIfMissing(file); if (!anchor.isEmpty()) { m_tocstream << "#" << anchor; diff --git a/src/emoji.cpp b/src/emoji.cpp index d723f64..750ec16 100644 --- a/src/emoji.cpp +++ b/src/emoji.cpp @@ -35,9 +35,13 @@ static struct emojiEntityInfo { ":8ball:", "🎱" }, { ":a:", "🅰" }, { ":ab:", "🆎" }, + { ":abacus:", "🧮" }, { ":abc:", "🔤" }, { ":abcd:", "🔡" }, { ":accept:", "🉑" }, + { ":accordion:", "🪗" }, + { ":adhesive_bandage:", "🩹" }, + { ":adult:", "🧑" }, { ":aerial_tramway:", "🚡" }, { ":afghanistan:", "🇦🇫" }, { ":airplane:", "✈" }, @@ -50,6 +54,7 @@ static struct emojiEntityInfo { ":ambulance:", "🚑" }, { ":american_samoa:", "🇦🇸" }, { ":amphora:", "🏺" }, + { ":anatomical_heart:", "🫀" }, { ":anchor:", "⚓" }, { ":andorra:", "🇦🇩" }, { ":angel:", "👼" }, @@ -89,15 +94,20 @@ static struct emojiEntityInfo { ":art:", "🎨" }, { ":articulated_lorry:", "🚛" }, { ":artificial_satellite:", "🛰" }, + { ":artist:", "🧑‍🎨" }, { ":aruba:", "🇦🇼" }, - { ":asterisk:", "*⃣" }, + { ":ascension_island:", "🇦🇨" }, + { ":asterisk:", "*️⃣" }, { ":astonished:", "😲" }, + { ":astronaut:", "🧑‍🚀" }, { ":athletic_shoe:", "👟" }, { ":atm:", "🏧" }, { ":atom_symbol:", "⚛" }, { ":australia:", "🇦🇺" }, { ":austria:", "🇦🇹" }, + { ":auto_rickshaw:", "🛺" }, { ":avocado:", "🥑" }, + { ":axe:", "🪓" }, { ":azerbaijan:", "🇦🇿" }, { ":b:", "🅱" }, { ":baby:", "👶" }, @@ -106,12 +116,17 @@ static struct emojiEntityInfo { ":baby_symbol:", "🚼" }, { ":back:", "🔙" }, { ":bacon:", "🥓" }, + { ":badger:", "🦡" }, { ":badminton:", "🏸" }, + { ":bagel:", "🥯" }, { ":baggage_claim:", "🛄" }, { ":baguette_bread:", "🥖" }, { ":bahamas:", "🇧🇸" }, { ":bahrain:", "🇧🇭" }, { ":balance_scale:", "⚖" }, + { ":bald_man:", "👨‍🦲" }, + { ":bald_woman:", "👩‍🦲" }, + { ":ballet_shoes:", "🩰" }, { ":balloon:", "🎈" }, { ":ballot_box:", "🗳" }, { ":ballot_box_with_check:", "☑" }, @@ -119,43 +134,52 @@ static struct emojiEntityInfo { ":banana:", "🍌" }, { ":bangbang:", "‼" }, { ":bangladesh:", "🇧🇩" }, + { ":banjo:", "🪕" }, { ":bank:", "🏦" }, { ":bar_chart:", "📊" }, { ":barbados:", "🇧🇧" }, { ":barber:", "💈" }, { ":baseball:", "⚾" }, + { ":basket:", "🧺" }, { ":basketball:", "🏀" }, - { ":basketball_man:", "⛹" }, - { ":basketball_woman:", "⛹♀" }, + { ":basketball_man:", "⛹️‍♂️" }, + { ":basketball_woman:", "⛹️‍♀️" }, { ":bat:", "🦇" }, { ":bath:", "🛀" }, { ":bathtub:", "🛁" }, { ":battery:", "🔋" }, { ":beach_umbrella:", "🏖" }, { ":bear:", "🐻" }, + { ":bearded_person:", "🧔" }, + { ":beaver:", "🦫" }, { ":bed:", "🛏" }, { ":bee:", "🐝" }, { ":beer:", "🍺" }, { ":beers:", "🍻" }, - { ":beetle:", "🐞" }, + { ":beetle:", "🪲" }, { ":beginner:", "🔰" }, { ":belarus:", "🇧🇾" }, { ":belgium:", "🇧🇪" }, { ":belize:", "🇧🇿" }, { ":bell:", "🔔" }, + { ":bell_pepper:", "🫑" }, { ":bellhop_bell:", "🛎" }, { ":benin:", "🇧🇯" }, { ":bento:", "🍱" }, { ":bermuda:", "🇧🇲" }, + { ":beverage_box:", "🧃" }, { ":bhutan:", "🇧🇹" }, { ":bicyclist:", "🚴" }, { ":bike:", "🚲" }, - { ":biking_man:", "🚴" }, - { ":biking_woman:", "🚴♀" }, + { ":biking_man:", "🚴‍♂️" }, + { ":biking_woman:", "🚴‍♀️" }, { ":bikini:", "👙" }, + { ":billed_cap:", "🧢" }, { ":biohazard:", "☣" }, { ":bird:", "🐦" }, { ":birthday:", "🎂" }, + { ":bison:", "🦬" }, + { ":black_cat:", "🐈‍⬛" }, { ":black_circle:", "⚫" }, { ":black_flag:", "🏴" }, { ":black_heart:", "🖤" }, @@ -166,43 +190,64 @@ static struct emojiEntityInfo { ":black_nib:", "✒" }, { ":black_small_square:", "▪" }, { ":black_square_button:", "🔲" }, - { ":blonde_man:", "👱" }, - { ":blonde_woman:", "👱♀" }, + { ":blond_haired_man:", "👱‍♂️" }, + { ":blond_haired_person:", "👱" }, + { ":blond_haired_woman:", "👱‍♀️" }, + { ":blonde_woman:", "👱‍♀️" }, { ":blossom:", "🌼" }, { ":blowfish:", "🐡" }, { ":blue_book:", "📘" }, { ":blue_car:", "🚙" }, { ":blue_heart:", "💙" }, + { ":blue_square:", "🟦" }, + { ":blueberries:", "🫐" }, { ":blush:", "😊" }, { ":boar:", "🐗" }, { ":boat:", "⛵" }, { ":bolivia:", "🇧🇴" }, { ":bomb:", "💣" }, + { ":bone:", "🦴" }, { ":book:", "📖" }, { ":bookmark:", "🔖" }, { ":bookmark_tabs:", "📑" }, { ":books:", "📚" }, { ":boom:", "💥" }, + { ":boomerang:", "🪃" }, { ":boot:", "👢" }, { ":bosnia_herzegovina:", "🇧🇦" }, { ":botswana:", "🇧🇼" }, + { ":bouncing_ball_man:", "⛹️‍♂️" }, + { ":bouncing_ball_person:", "⛹" }, + { ":bouncing_ball_woman:", "⛹️‍♀️" }, { ":bouquet:", "💐" }, + { ":bouvet_island:", "🇧🇻" }, { ":bow:", "🙇" }, { ":bow_and_arrow:", "🏹" }, - { ":bowing_man:", "🙇" }, - { ":bowing_woman:", "🙇♀" }, + { ":bowing_man:", "🙇‍♂️" }, + { ":bowing_woman:", "🙇‍♀️" }, + { ":bowl_with_spoon:", "🥣" }, { ":bowling:", "🎳" }, { ":boxing_glove:", "🥊" }, { ":boy:", "👦" }, + { ":brain:", "🧠" }, { ":brazil:", "🇧🇷" }, { ":bread:", "🍞" }, - { ":bride_with_veil:", "👰" }, + { ":breast_feeding:", "🤱" }, + { ":bricks:", "🧱" }, + { ":bride_with_veil:", "👰‍♀️" }, { ":bridge_at_night:", "🌉" }, { ":briefcase:", "💼" }, { ":british_indian_ocean_territory:", "🇮🇴" }, { ":british_virgin_islands:", "🇻🇬" }, + { ":broccoli:", "🥦" }, { ":broken_heart:", "💔" }, + { ":broom:", "🧹" }, + { ":brown_circle:", "🟤" }, + { ":brown_heart:", "🤎" }, + { ":brown_square:", "🟫" }, { ":brunei:", "🇧🇳" }, + { ":bubble_tea:", "🧋" }, + { ":bucket:", "🪣" }, { ":bug:", "🐛" }, { ":building_construction:", "🏗" }, { ":bulb:", "💡" }, @@ -217,6 +262,7 @@ static struct emojiEntityInfo { ":busstop:", "🚏" }, { ":bust_in_silhouette:", "👤" }, { ":busts_in_silhouette:", "👥" }, + { ":butter:", "🧈" }, { ":butterfly:", "🦋" }, { ":cactus:", "🌵" }, { ":cake:", "🍰" }, @@ -234,6 +280,7 @@ static struct emojiEntityInfo { ":cancer:", "♋" }, { ":candle:", "🕯" }, { ":candy:", "🍬" }, + { ":canned_food:", "🥫" }, { ":canoe:", "🛶" }, { ":cape_verde:", "🇨🇻" }, { ":capital_abcd:", "🔠" }, @@ -244,14 +291,18 @@ static struct emojiEntityInfo { ":card_index_dividers:", "🗂" }, { ":caribbean_netherlands:", "🇧🇶" }, { ":carousel_horse:", "🎠" }, + { ":carpentry_saw:", "🪚" }, { ":carrot:", "🥕" }, + { ":cartwheeling:", "🤸" }, { ":cat:", "🐱" }, { ":cat2:", "🐈" }, { ":cayman_islands:", "🇰🇾" }, { ":cd:", "💿" }, { ":central_african_republic:", "🇨🇫" }, + { ":ceuta_melilla:", "🇪🇦" }, { ":chad:", "🇹🇩" }, { ":chains:", "⛓" }, + { ":chair:", "🪑" }, { ":champagne:", "🍾" }, { ":chart:", "💹" }, { ":chart_with_downwards_trend:", "📉" }, @@ -260,12 +311,15 @@ static struct emojiEntityInfo { ":cheese:", "🧀" }, { ":cherries:", "🍒" }, { ":cherry_blossom:", "🌸" }, + { ":chess_pawn:", "♟" }, { ":chestnut:", "🌰" }, { ":chicken:", "🐔" }, + { ":child:", "🧒" }, { ":children_crossing:", "🚸" }, { ":chile:", "🇨🇱" }, { ":chipmunk:", "🐿" }, { ":chocolate_bar:", "🍫" }, + { ":chopsticks:", "🥢" }, { ":christmas_island:", "🇨🇽" }, { ":christmas_tree:", "🎄" }, { ":church:", "⛪" }, @@ -279,8 +333,12 @@ static struct emojiEntityInfo { ":clap:", "👏" }, { ":clapper:", "🎬" }, { ":classical_building:", "🏛" }, + { ":climbing:", "🧗" }, + { ":climbing_man:", "🧗‍♂️" }, + { ":climbing_woman:", "🧗‍♀️" }, { ":clinking_glasses:", "🥂" }, { ":clipboard:", "📋" }, + { ":clipperton_island:", "🇨🇵" }, { ":clock1:", "🕐" }, { ":clock10:", "🕙" }, { ":clock1030:", "🕥" }, @@ -316,15 +374,21 @@ static struct emojiEntityInfo { ":clown_face:", "🤡" }, { ":clubs:", "♣" }, { ":cn:", "🇨🇳" }, + { ":coat:", "🧥" }, + { ":cockroach:", "🪳" }, { ":cocktail:", "🍸" }, + { ":coconut:", "🥥" }, { ":cocos_islands:", "🇨🇨" }, { ":coffee:", "☕" }, { ":coffin:", "⚰" }, + { ":coin:", "🪙" }, + { ":cold_face:", "🥶" }, { ":cold_sweat:", "😰" }, { ":collision:", "💥" }, { ":colombia:", "🇨🇴" }, { ":comet:", "☄" }, { ":comoros:", "🇰🇲" }, + { ":compass:", "🧭" }, { ":computer:", "💻" }, { ":computer_mouse:", "🖱" }, { ":confetti_ball:", "🎊" }, @@ -335,10 +399,11 @@ static struct emojiEntityInfo { ":congratulations:", "㊗" }, { ":construction:", "🚧" }, { ":construction_worker:", "👷" }, - { ":construction_worker_man:", "👷" }, - { ":construction_worker_woman:", "👷♀" }, + { ":construction_worker_man:", "👷‍♂️" }, + { ":construction_worker_woman:", "👷‍♀️" }, { ":control_knobs:", "🎛" }, { ":convenience_store:", "🏪" }, + { ":cook:", "🧑‍🍳" }, { ":cook_islands:", "🇨🇰" }, { ":cookie:", "🍪" }, { ":cool:", "🆒" }, @@ -350,12 +415,13 @@ static struct emojiEntityInfo { ":couch_and_lamp:", "🛋" }, { ":couple:", "👫" }, { ":couple_with_heart:", "💑" }, - { ":couple_with_heart_man_man:", "👨❤👨" }, - { ":couple_with_heart_woman_man:", "💑" }, - { ":couple_with_heart_woman_woman:", "👩❤👩" }, - { ":couplekiss_man_man:", "👨❤💋👨" }, - { ":couplekiss_man_woman:", "💏" }, - { ":couplekiss_woman_woman:", "👩❤💋👩" }, + { ":couple_with_heart_man_man:", "👨‍❤️‍💋‍👨" }, + { ":couple_with_heart_woman_man:", "👩‍❤️‍💋‍👨" }, + { ":couple_with_heart_woman_woman:", "👩‍❤️‍💋‍👩" }, + { ":couplekiss:", "💏" }, + { ":couplekiss_man_man:", "👨‍❤️‍💋‍👨" }, + { ":couplekiss_man_woman:", "👩‍❤️‍💋‍👨" }, + { ":couplekiss_woman_woman:", "👩‍❤️‍💋‍👩" }, { ":cow:", "🐮" }, { ":cow2:", "🐄" }, { ":cowboy_hat_face:", "🤠" }, @@ -363,7 +429,8 @@ static struct emojiEntityInfo { ":crayon:", "🖍" }, { ":credit_card:", "💳" }, { ":crescent_moon:", "🌙" }, - { ":cricket:", "🏏" }, + { ":cricket:", "🦗" }, + { ":cricket_game:", "🏏" }, { ":croatia:", "🇭🇷" }, { ":crocodile:", "🐊" }, { ":croissant:", "🥐" }, @@ -376,27 +443,37 @@ static struct emojiEntityInfo { ":crystal_ball:", "🔮" }, { ":cuba:", "🇨🇺" }, { ":cucumber:", "🥒" }, + { ":cup_with_straw:", "🥤" }, + { ":cupcake:", "🧁" }, { ":cupid:", "💘" }, { ":curacao:", "🇨🇼" }, + { ":curling_stone:", "🥌" }, + { ":curly_haired_man:", "👨‍🦱" }, + { ":curly_haired_woman:", "👩‍🦱" }, { ":curly_loop:", "➰" }, { ":currency_exchange:", "💱" }, { ":curry:", "🍛" }, + { ":cursing_face:", "🤬" }, { ":custard:", "🍮" }, { ":customs:", "🛃" }, + { ":cut_of_meat:", "🥩" }, { ":cyclone:", "🌀" }, { ":cyprus:", "🇨🇾" }, { ":czech_republic:", "🇨🇿" }, { ":dagger:", "🗡" }, { ":dancer:", "💃" }, { ":dancers:", "👯" }, - { ":dancing_men:", "👯♂" }, - { ":dancing_women:", "👯" }, + { ":dancing_men:", "👯‍♂️" }, + { ":dancing_women:", "👯‍♀️" }, { ":dango:", "🍡" }, { ":dark_sunglasses:", "🕶" }, { ":dart:", "🎯" }, { ":dash:", "💨" }, { ":date:", "📅" }, { ":de:", "🇩🇪" }, + { ":deaf_man:", "🧏‍♂️" }, + { ":deaf_person:", "🧏" }, + { ":deaf_woman:", "🧏‍♀️" }, { ":deciduous_tree:", "🌳" }, { ":deer:", "🦌" }, { ":denmark:", "🇩🇰" }, @@ -408,12 +485,18 @@ static struct emojiEntityInfo { ":detective:", "🕵" }, { ":diamond_shape_with_a_dot_inside:", "💠" }, { ":diamonds:", "♦" }, + { ":diego_garcia:", "🇩🇬" }, { ":disappointed:", "😞" }, { ":disappointed_relieved:", "😥" }, + { ":disguised_face:", "🥸" }, + { ":diving_mask:", "🤿" }, + { ":diya_lamp:", "🪔" }, { ":dizzy:", "💫" }, { ":dizzy_face:", "😵" }, { ":djibouti:", "🇩🇯" }, + { ":dna:", "🧬" }, { ":do_not_litter:", "🚯" }, + { ":dodo:", "🦤" }, { ":dog:", "🐶" }, { ":dog2:", "🐕" }, { ":dollar:", "💵" }, @@ -429,14 +512,17 @@ static struct emojiEntityInfo { ":dress:", "👗" }, { ":dromedary_camel:", "🐪" }, { ":drooling_face:", "🤤" }, + { ":drop_of_blood:", "🩸" }, { ":droplet:", "💧" }, { ":drum:", "🥁" }, { ":duck:", "🦆" }, + { ":dumpling:", "🥟" }, { ":dvd:", "📀" }, { ":e-mail:", "📧" }, { ":eagle:", "🦅" }, { ":ear:", "👂" }, { ":ear_of_rice:", "🌾" }, + { ":ear_with_hearing_aid:", "🦻" }, { ":earth_africa:", "🌍" }, { ":earth_americas:", "🌎" }, { ":earth_asia:", "🌏" }, @@ -444,14 +530,20 @@ static struct emojiEntityInfo { ":egg:", "🥚" }, { ":eggplant:", "🍆" }, { ":egypt:", "🇪🇬" }, - { ":eight:", "8⃣" }, + { ":eight:", "8️⃣" }, { ":eight_pointed_black_star:", "✴" }, { ":eight_spoked_asterisk:", "✳" }, + { ":eject_button:", "⏏" }, { ":el_salvador:", "🇸🇻" }, { ":electric_plug:", "🔌" }, { ":elephant:", "🐘" }, - { ":email:", "✉" }, + { ":elevator:", "🛗" }, + { ":elf:", "🧝" }, + { ":elf_man:", "🧝‍♂️" }, + { ":elf_woman:", "🧝‍♀️" }, + { ":email:", "📧" }, { ":end:", "🔚" }, + { ":england:", "🏴󠁧󠁢󠁥󠁮󠁧󠁿" }, { ":envelope:", "✉" }, { ":envelope_with_arrow:", "📩" }, { ":equatorial_guinea:", "🇬🇶" }, @@ -466,49 +558,62 @@ static struct emojiEntityInfo { ":european_union:", "🇪🇺" }, { ":evergreen_tree:", "🌲" }, { ":exclamation:", "❗" }, + { ":exploding_head:", "🤯" }, { ":expressionless:", "😑" }, - { ":eye:", "👁" }, - { ":eye_speech_bubble:", "👁🗨" }, + { ":eye:", "👁️‍🗨️" }, + { ":eye_speech_bubble:", "👁️‍🗨️" }, { ":eyeglasses:", "👓" }, { ":eyes:", "👀" }, + { ":face_exhaling:", "😮‍💨" }, + { ":face_in_clouds:", "😶‍🌫️" }, { ":face_with_head_bandage:", "🤕" }, + { ":face_with_spiral_eyes:", "😵‍💫" }, { ":face_with_thermometer:", "🤒" }, + { ":facepalm:", "🤦" }, { ":facepunch:", "👊" }, { ":factory:", "🏭" }, + { ":factory_worker:", "🧑‍🏭" }, + { ":fairy:", "🧚" }, + { ":fairy_man:", "🧚‍♂️" }, + { ":fairy_woman:", "🧚‍♀️" }, + { ":falafel:", "🧆" }, { ":falkland_islands:", "🇫🇰" }, { ":fallen_leaf:", "🍂" }, { ":family:", "👪" }, - { ":family_man_boy:", "👨👦" }, - { ":family_man_boy_boy:", "👨👦👦" }, - { ":family_man_girl:", "👨👧" }, - { ":family_man_girl_boy:", "👨👧👦" }, - { ":family_man_girl_girl:", "👨👧👧" }, - { ":family_man_man_boy:", "👨👨👦" }, - { ":family_man_man_boy_boy:", "👨👨👦👦" }, - { ":family_man_man_girl:", "👨👨👧" }, - { ":family_man_man_girl_boy:", "👨👨👧👦" }, - { ":family_man_man_girl_girl:", "👨👨👧👧" }, - { ":family_man_woman_boy:", "👪" }, - { ":family_man_woman_boy_boy:", "👨👩👦👦" }, - { ":family_man_woman_girl:", "👨👩👧" }, - { ":family_man_woman_girl_boy:", "👨👩👧👦" }, - { ":family_man_woman_girl_girl:", "👨👩👧👧" }, - { ":family_woman_boy:", "👩👦" }, - { ":family_woman_boy_boy:", "👩👦👦" }, - { ":family_woman_girl:", "👩👧" }, - { ":family_woman_girl_boy:", "👩👧👦" }, - { ":family_woman_girl_girl:", "👩👧👧" }, - { ":family_woman_woman_boy:", "👩👩👦" }, - { ":family_woman_woman_boy_boy:", "👩👩👦👦" }, - { ":family_woman_woman_girl:", "👩👩👧" }, - { ":family_woman_woman_girl_boy:", "👩👩👧👦" }, - { ":family_woman_woman_girl_girl:", "👩👩👧👧" }, + { ":family_man_boy:", "👨‍👩‍👦" }, + { ":family_man_boy_boy:", "👨‍👩‍👦‍👦" }, + { ":family_man_girl:", "👨‍👩‍👧" }, + { ":family_man_girl_boy:", "👨‍👩‍👧‍👦" }, + { ":family_man_girl_girl:", "👨‍👩‍👧‍👧" }, + { ":family_man_man_boy:", "👨‍👨‍👦" }, + { ":family_man_man_boy_boy:", "👨‍👨‍👦‍👦" }, + { ":family_man_man_girl:", "👨‍👨‍👧" }, + { ":family_man_man_girl_boy:", "👨‍👨‍👧‍👦" }, + { ":family_man_man_girl_girl:", "👨‍👨‍👧‍👧" }, + { ":family_man_woman_boy:", "👨‍👩‍👦" }, + { ":family_man_woman_boy_boy:", "👨‍👩‍👦‍👦" }, + { ":family_man_woman_girl:", "👨‍👩‍👧" }, + { ":family_man_woman_girl_boy:", "👨‍👩‍👧‍👦" }, + { ":family_man_woman_girl_girl:", "👨‍👩‍👧‍👧" }, + { ":family_woman_boy:", "👩‍👩‍👦" }, + { ":family_woman_boy_boy:", "👩‍👩‍👦‍👦" }, + { ":family_woman_girl:", "👩‍👩‍👧" }, + { ":family_woman_girl_boy:", "👩‍👩‍👧‍👦" }, + { ":family_woman_girl_girl:", "👩‍👩‍👧‍👧" }, + { ":family_woman_woman_boy:", "👩‍👩‍👦" }, + { ":family_woman_woman_boy_boy:", "👩‍👩‍👦‍👦" }, + { ":family_woman_woman_girl:", "👩‍👩‍👧" }, + { ":family_woman_woman_girl_boy:", "👩‍👩‍👧‍👦" }, + { ":family_woman_woman_girl_girl:", "👩‍👩‍👧‍👧" }, + { ":farmer:", "🧑‍🌾" }, { ":faroe_islands:", "🇫🇴" }, { ":fast_forward:", "⏩" }, { ":fax:", "📠" }, { ":fearful:", "😨" }, + { ":feather:", "🪶" }, { ":feet:", "🐾" }, - { ":female_detective:", "🕵♀" }, + { ":female_detective:", "🕵️‍♀️" }, + { ":female_sign:", "♀" }, { ":ferris_wheel:", "🎡" }, { ":ferry:", "⛴" }, { ":field_hockey:", "🏑" }, @@ -520,6 +625,9 @@ static struct emojiEntityInfo { ":finland:", "🇫🇮" }, { ":fire:", "🔥" }, { ":fire_engine:", "🚒" }, + { ":fire_extinguisher:", "🧯" }, + { ":firecracker:", "🧨" }, + { ":firefighter:", "🧑‍🚒" }, { ":fireworks:", "🎆" }, { ":first_quarter_moon:", "🌓" }, { ":first_quarter_moon_with_face:", "🌛" }, @@ -531,9 +639,12 @@ static struct emojiEntityInfo { ":fist_oncoming:", "👊" }, { ":fist_raised:", "✊" }, { ":fist_right:", "🤜" }, - { ":five:", "5⃣" }, + { ":five:", "5️⃣" }, { ":flags:", "🎏" }, + { ":flamingo:", "🦩" }, { ":flashlight:", "🔦" }, + { ":flat_shoe:", "🥿" }, + { ":flatbread:", "🫓" }, { ":fleur_de_lis:", "⚜" }, { ":flight_arrival:", "🛬" }, { ":flight_departure:", "🛫" }, @@ -541,14 +652,20 @@ static struct emojiEntityInfo { ":floppy_disk:", "💾" }, { ":flower_playing_cards:", "🎴" }, { ":flushed:", "😳" }, + { ":fly:", "🪰" }, + { ":flying_disc:", "🥏" }, + { ":flying_saucer:", "🛸" }, { ":fog:", "🌫" }, { ":foggy:", "🌁" }, + { ":fondue:", "🫕" }, + { ":foot:", "🦶" }, { ":football:", "🏈" }, { ":footprints:", "👣" }, { ":fork_and_knife:", "🍴" }, + { ":fortune_cookie:", "🥠" }, { ":fountain:", "⛲" }, { ":fountain_pen:", "🖋" }, - { ":four:", "4⃣" }, + { ":four:", "4️⃣" }, { ":four_leaf_clover:", "🍀" }, { ":fox_face:", "🦊" }, { ":fr:", "🇫🇷" }, @@ -563,8 +680,9 @@ static struct emojiEntityInfo { ":frog:", "🐸" }, { ":frowning:", "😦" }, { ":frowning_face:", "☹" }, - { ":frowning_man:", "🙍♂" }, - { ":frowning_woman:", "🙍" }, + { ":frowning_man:", "🙍‍♂️" }, + { ":frowning_person:", "🙍" }, + { ":frowning_woman:", "🙍‍♀️" }, { ":fu:", "🖕" }, { ":fuelpump:", "⛽" }, { ":full_moon:", "🌕" }, @@ -573,30 +691,40 @@ static struct emojiEntityInfo { ":gabon:", "🇬🇦" }, { ":gambia:", "🇬🇲" }, { ":game_die:", "🎲" }, + { ":garlic:", "🧄" }, { ":gb:", "🇬🇧" }, { ":gear:", "⚙" }, { ":gem:", "💎" }, { ":gemini:", "♊" }, + { ":genie:", "🧞" }, + { ":genie_man:", "🧞‍♂️" }, + { ":genie_woman:", "🧞‍♀️" }, { ":georgia:", "🇬🇪" }, { ":ghana:", "🇬🇭" }, { ":ghost:", "👻" }, { ":gibraltar:", "🇬🇮" }, { ":gift:", "🎁" }, { ":gift_heart:", "💝" }, + { ":giraffe:", "🦒" }, { ":girl:", "👧" }, { ":globe_with_meridians:", "🌐" }, + { ":gloves:", "🧤" }, { ":goal_net:", "🥅" }, { ":goat:", "🐐" }, + { ":goggles:", "🥽" }, { ":golf:", "⛳" }, - { ":golfing_man:", "🏌" }, - { ":golfing_woman:", "🏌♀" }, + { ":golfing:", "🏌" }, + { ":golfing_man:", "🏌️‍♂️" }, + { ":golfing_woman:", "🏌️‍♀️" }, { ":gorilla:", "🦍" }, { ":grapes:", "🍇" }, { ":greece:", "🇬🇷" }, { ":green_apple:", "🍏" }, { ":green_book:", "📗" }, + { ":green_circle:", "🟢" }, { ":green_heart:", "💚" }, { ":green_salad:", "🥗" }, + { ":green_square:", "🟩" }, { ":greenland:", "🇬🇱" }, { ":grenada:", "🇬🇩" }, { ":grey_exclamation:", "❕" }, @@ -606,18 +734,20 @@ static struct emojiEntityInfo { ":grinning:", "😀" }, { ":guadeloupe:", "🇬🇵" }, { ":guam:", "🇬🇺" }, - { ":guardsman:", "💂" }, - { ":guardswoman:", "💂♀" }, + { ":guard:", "💂" }, + { ":guardsman:", "💂‍♂️" }, + { ":guardswoman:", "💂‍♀️" }, { ":guatemala:", "🇬🇹" }, { ":guernsey:", "🇬🇬" }, + { ":guide_dog:", "🦮" }, { ":guinea:", "🇬🇳" }, { ":guinea_bissau:", "🇬🇼" }, { ":guitar:", "🎸" }, { ":gun:", "🔫" }, { ":guyana:", "🇬🇾" }, { ":haircut:", "💇" }, - { ":haircut_man:", "💇♂" }, - { ":haircut_woman:", "💇" }, + { ":haircut_man:", "💇‍♂️" }, + { ":haircut_woman:", "💇‍♀️" }, { ":haiti:", "🇭🇹" }, { ":hamburger:", "🍔" }, { ":hammer:", "🔨" }, @@ -625,18 +755,24 @@ static struct emojiEntityInfo { ":hammer_and_wrench:", "🛠" }, { ":hamster:", "🐹" }, { ":hand:", "✋" }, + { ":hand_over_mouth:", "🤭" }, { ":handbag:", "👜" }, + { ":handball_person:", "🤾" }, { ":handshake:", "🤝" }, { ":hankey:", "💩" }, - { ":hash:", "#⃣" }, + { ":hash:", "#️⃣" }, { ":hatched_chick:", "🐥" }, { ":hatching_chick:", "🐣" }, { ":headphones:", "🎧" }, + { ":headstone:", "🪦" }, + { ":health_worker:", "🧑‍⚕️" }, { ":hear_no_evil:", "🙉" }, - { ":heart:", "❤" }, + { ":heard_mcdonald_islands:", "🇭🇲" }, + { ":heart:", "❤️‍🔥" }, { ":heart_decoration:", "💟" }, { ":heart_eyes:", "😍" }, { ":heart_eyes_cat:", "😻" }, + { ":heart_on_fire:", "❤️‍🔥" }, { ":heartbeat:", "💓" }, { ":heartpulse:", "💗" }, { ":hearts:", "♥" }, @@ -648,20 +784,26 @@ static struct emojiEntityInfo { ":heavy_minus_sign:", "➖" }, { ":heavy_multiplication_x:", "✖" }, { ":heavy_plus_sign:", "➕" }, + { ":hedgehog:", "🦔" }, { ":helicopter:", "🚁" }, { ":herb:", "🌿" }, { ":hibiscus:", "🌺" }, { ":high_brightness:", "🔆" }, { ":high_heel:", "👠" }, + { ":hiking_boot:", "🥾" }, + { ":hindu_temple:", "🛕" }, + { ":hippopotamus:", "🦛" }, { ":hocho:", "🔪" }, { ":hole:", "🕳" }, { ":honduras:", "🇭🇳" }, { ":honey_pot:", "🍯" }, { ":honeybee:", "🐝" }, { ":hong_kong:", "🇭🇰" }, + { ":hook:", "🪝" }, { ":horse:", "🐴" }, { ":horse_racing:", "🏇" }, { ":hospital:", "🏥" }, + { ":hot_face:", "🥵" }, { ":hot_pepper:", "🌶" }, { ":hotdog:", "🌭" }, { ":hotel:", "🏨" }, @@ -674,7 +816,9 @@ static struct emojiEntityInfo { ":hugs:", "🤗" }, { ":hungary:", "🇭🇺" }, { ":hushed:", "😯" }, + { ":hut:", "🛖" }, { ":ice_cream:", "🍨" }, + { ":ice_cube:", "🧊" }, { ":ice_hockey:", "🏒" }, { ":ice_skate:", "⛸" }, { ":icecream:", "🍦" }, @@ -686,6 +830,7 @@ static struct emojiEntityInfo { ":incoming_envelope:", "📨" }, { ":india:", "🇮🇳" }, { ":indonesia:", "🇮🇩" }, + { ":infinity:", "♾" }, { ":information_desk_person:", "💁" }, { ":information_source:", "ℹ" }, { ":innocent:", "😇" }, @@ -706,12 +851,16 @@ static struct emojiEntityInfo { ":japanese_ogre:", "👹" }, { ":jeans:", "👖" }, { ":jersey:", "🇯🇪" }, + { ":jigsaw:", "🧩" }, { ":jordan:", "🇯🇴" }, { ":joy:", "😂" }, { ":joy_cat:", "😹" }, { ":joystick:", "🕹" }, { ":jp:", "🇯🇵" }, + { ":judge:", "🧑‍⚖️" }, + { ":juggling_person:", "🤹" }, { ":kaaba:", "🕋" }, + { ":kangaroo:", "🦘" }, { ":kazakhstan:", "🇰🇿" }, { ":kenya:", "🇰🇪" }, { ":key:", "🔑" }, @@ -726,15 +875,24 @@ static struct emojiEntityInfo { ":kissing_closed_eyes:", "😚" }, { ":kissing_heart:", "😘" }, { ":kissing_smiling_eyes:", "😙" }, + { ":kite:", "🪁" }, { ":kiwi_fruit:", "🥝" }, + { ":kneeling_man:", "🧎‍♂️" }, + { ":kneeling_person:", "🧎" }, + { ":kneeling_woman:", "🧎‍♀️" }, { ":knife:", "🔪" }, + { ":knot:", "🪢" }, { ":koala:", "🐨" }, { ":koko:", "🈁" }, { ":kosovo:", "🇽🇰" }, { ":kr:", "🇰🇷" }, { ":kuwait:", "🇰🇼" }, { ":kyrgyzstan:", "🇰🇬" }, + { ":lab_coat:", "🥼" }, { ":label:", "🏷" }, + { ":lacrosse:", "🥍" }, + { ":ladder:", "🪜" }, + { ":lady_beetle:", "🐞" }, { ":lantern:", "🏮" }, { ":laos:", "🇱🇦" }, { ":large_blue_circle:", "🔵" }, @@ -745,12 +903,15 @@ static struct emojiEntityInfo { ":latin_cross:", "✝" }, { ":latvia:", "🇱🇻" }, { ":laughing:", "😆" }, + { ":leafy_green:", "🥬" }, { ":leaves:", "🍃" }, { ":lebanon:", "🇱🇧" }, { ":ledger:", "📒" }, { ":left_luggage:", "🛅" }, { ":left_right_arrow:", "↔" }, + { ":left_speech_bubble:", "🗨" }, { ":leftwards_arrow_with_hook:", "↩" }, + { ":leg:", "🦵" }, { ":lemon:", "🍋" }, { ":leo:", "♌" }, { ":leopard:", "🐆" }, @@ -767,15 +928,25 @@ static struct emojiEntityInfo { ":lipstick:", "💄" }, { ":lithuania:", "🇱🇹" }, { ":lizard:", "🦎" }, + { ":llama:", "🦙" }, + { ":lobster:", "🦞" }, { ":lock:", "🔒" }, { ":lock_with_ink_pen:", "🔏" }, { ":lollipop:", "🍭" }, + { ":long_drum:", "🪘" }, { ":loop:", "➿" }, + { ":lotion_bottle:", "🧴" }, + { ":lotus_position:", "🧘" }, + { ":lotus_position_man:", "🧘‍♂️" }, + { ":lotus_position_woman:", "🧘‍♀️" }, { ":loud_sound:", "🔊" }, { ":loudspeaker:", "📢" }, { ":love_hotel:", "🏩" }, { ":love_letter:", "💌" }, + { ":love_you_gesture:", "🤟" }, { ":low_brightness:", "🔅" }, + { ":luggage:", "🧳" }, + { ":lungs:", "🫁" }, { ":luxembourg:", "🇱🇺" }, { ":lying_face:", "🤥" }, { ":m:", "Ⓜ" }, @@ -784,6 +955,11 @@ static struct emojiEntityInfo { ":madagascar:", "🇲🇬" }, { ":mag:", "🔍" }, { ":mag_right:", "🔎" }, + { ":mage:", "🧙" }, + { ":mage_man:", "🧙‍♂️" }, + { ":mage_woman:", "🧙‍♀️" }, + { ":magic_wand:", "🪄" }, + { ":magnet:", "🧲" }, { ":mahjong:", "🀄" }, { ":mailbox:", "📫" }, { ":mailbox_closed:", "📪" }, @@ -792,70 +968,92 @@ static struct emojiEntityInfo { ":malawi:", "🇲🇼" }, { ":malaysia:", "🇲🇾" }, { ":maldives:", "🇲🇻" }, - { ":male_detective:", "🕵" }, + { ":male_detective:", "🕵️‍♂️" }, + { ":male_sign:", "♂" }, { ":mali:", "🇲🇱" }, { ":malta:", "🇲🇹" }, + { ":mammoth:", "🦣" }, { ":man:", "👨" }, - { ":man_artist:", "👨🎨" }, - { ":man_astronaut:", "👨🚀" }, - { ":man_cartwheeling:", "🤸♂" }, - { ":man_cook:", "👨🍳" }, + { ":man_artist:", "👨‍🎨" }, + { ":man_astronaut:", "👨‍🚀" }, + { ":man_beard:", "🧔‍♂️" }, + { ":man_cartwheeling:", "🤸‍♂️" }, + { ":man_cook:", "👨‍🍳" }, { ":man_dancing:", "🕺" }, - { ":man_facepalming:", "🤦♂" }, - { ":man_factory_worker:", "👨🏭" }, - { ":man_farmer:", "👨🌾" }, - { ":man_firefighter:", "👨🚒" }, - { ":man_health_worker:", "👨⚕" }, - { ":man_in_tuxedo:", "🤵" }, - { ":man_judge:", "👨⚖" }, - { ":man_juggling:", "🤹♂" }, - { ":man_mechanic:", "👨🔧" }, - { ":man_office_worker:", "👨💼" }, - { ":man_pilot:", "👨✈" }, - { ":man_playing_handball:", "🤾♂" }, - { ":man_playing_water_polo:", "🤽♂" }, - { ":man_scientist:", "👨🔬" }, - { ":man_shrugging:", "🤷♂" }, - { ":man_singer:", "👨🎤" }, - { ":man_student:", "👨🎓" }, - { ":man_teacher:", "👨🏫" }, - { ":man_technologist:", "👨💻" }, + { ":man_facepalming:", "🤦‍♂️" }, + { ":man_factory_worker:", "👨‍🏭" }, + { ":man_farmer:", "👨‍🌾" }, + { ":man_feeding_baby:", "👨‍🍼" }, + { ":man_firefighter:", "👨‍🚒" }, + { ":man_health_worker:", "👨‍⚕️" }, + { ":man_in_manual_wheelchair:", "👨‍🦽" }, + { ":man_in_motorized_wheelchair:", "👨‍🦼" }, + { ":man_in_tuxedo:", "🤵‍♂️" }, + { ":man_judge:", "👨‍⚖️" }, + { ":man_juggling:", "🤹‍♂️" }, + { ":man_mechanic:", "👨‍🔧" }, + { ":man_office_worker:", "👨‍💼" }, + { ":man_pilot:", "👨‍✈️" }, + { ":man_playing_handball:", "🤾‍♂️" }, + { ":man_playing_water_polo:", "🤽‍♂️" }, + { ":man_scientist:", "👨‍🔬" }, + { ":man_shrugging:", "🤷‍♂️" }, + { ":man_singer:", "👨‍🎤" }, + { ":man_student:", "👨‍🎓" }, + { ":man_teacher:", "👨‍🏫" }, + { ":man_technologist:", "👨‍💻" }, { ":man_with_gua_pi_mao:", "👲" }, - { ":man_with_turban:", "👳" }, + { ":man_with_probing_cane:", "👨‍🦯" }, + { ":man_with_turban:", "👳‍♂️" }, + { ":man_with_veil:", "👰‍♂️" }, { ":mandarin:", "🍊" }, + { ":mango:", "🥭" }, { ":mans_shoe:", "👞" }, { ":mantelpiece_clock:", "🕰" }, + { ":manual_wheelchair:", "🦽" }, { ":maple_leaf:", "🍁" }, { ":marshall_islands:", "🇲🇭" }, { ":martial_arts_uniform:", "🥋" }, { ":martinique:", "🇲🇶" }, { ":mask:", "😷" }, { ":massage:", "💆" }, - { ":massage_man:", "💆♂" }, - { ":massage_woman:", "💆" }, + { ":massage_man:", "💆‍♂️" }, + { ":massage_woman:", "💆‍♀️" }, + { ":mate:", "🧉" }, { ":mauritania:", "🇲🇷" }, { ":mauritius:", "🇲🇺" }, { ":mayotte:", "🇾🇹" }, { ":meat_on_bone:", "🍖" }, + { ":mechanic:", "🧑‍🔧" }, + { ":mechanical_arm:", "🦾" }, + { ":mechanical_leg:", "🦿" }, { ":medal_military:", "🎖" }, { ":medal_sports:", "🏅" }, + { ":medical_symbol:", "⚕" }, { ":mega:", "📣" }, { ":melon:", "🍈" }, { ":memo:", "📝" }, - { ":men_wrestling:", "🤼♂" }, + { ":men_wrestling:", "🤼‍♂️" }, + { ":mending_heart:", "❤️‍🩹" }, { ":menorah:", "🕎" }, { ":mens:", "🚹" }, + { ":mermaid:", "🧜‍♀️" }, + { ":merman:", "🧜‍♂️" }, + { ":merperson:", "🧜" }, { ":metal:", "🤘" }, { ":metro:", "🚇" }, { ":mexico:", "🇲🇽" }, + { ":microbe:", "🦠" }, { ":micronesia:", "🇫🇲" }, { ":microphone:", "🎤" }, { ":microscope:", "🔬" }, { ":middle_finger:", "🖕" }, + { ":military_helmet:", "🪖" }, { ":milk_glass:", "🥛" }, { ":milky_way:", "🌌" }, { ":minibus:", "🚐" }, { ":minidisc:", "💽" }, + { ":mirror:", "🪞" }, { ":mobile_phone_off:", "📴" }, { ":moldova:", "🇲🇩" }, { ":monaco:", "🇲🇨" }, @@ -865,27 +1063,32 @@ static struct emojiEntityInfo { ":mongolia:", "🇲🇳" }, { ":monkey:", "🐒" }, { ":monkey_face:", "🐵" }, + { ":monocle_face:", "🧐" }, { ":monorail:", "🚝" }, { ":montenegro:", "🇲🇪" }, { ":montserrat:", "🇲🇸" }, { ":moon:", "🌔" }, + { ":moon_cake:", "🥮" }, { ":morocco:", "🇲🇦" }, { ":mortar_board:", "🎓" }, { ":mosque:", "🕌" }, + { ":mosquito:", "🦟" }, { ":motor_boat:", "🛥" }, { ":motor_scooter:", "🛵" }, { ":motorcycle:", "🏍" }, + { ":motorized_wheelchair:", "🦼" }, { ":motorway:", "🛣" }, { ":mount_fuji:", "🗻" }, { ":mountain:", "⛰" }, { ":mountain_bicyclist:", "🚵" }, - { ":mountain_biking_man:", "🚵" }, - { ":mountain_biking_woman:", "🚵♀" }, + { ":mountain_biking_man:", "🚵‍♂️" }, + { ":mountain_biking_woman:", "🚵‍♀️" }, { ":mountain_cableway:", "🚠" }, { ":mountain_railway:", "🚞" }, { ":mountain_snow:", "🏔" }, { ":mouse:", "🐭" }, { ":mouse2:", "🐁" }, + { ":mouse_trap:", "🪤" }, { ":movie_camera:", "🎥" }, { ":moyai:", "🗿" }, { ":mozambique:", "🇲🇿" }, @@ -896,6 +1099,7 @@ static struct emojiEntityInfo { ":musical_note:", "🎵" }, { ":musical_score:", "🎼" }, { ":mute:", "🔇" }, + { ":mx_claus:", "🧑‍🎄" }, { ":myanmar:", "🇲🇲" }, { ":nail_care:", "💅" }, { ":name_badge:", "📛" }, @@ -903,10 +1107,12 @@ static struct emojiEntityInfo { ":national_park:", "🏞" }, { ":nauru:", "🇳🇷" }, { ":nauseated_face:", "🤢" }, + { ":nazar_amulet:", "🧿" }, { ":necktie:", "👔" }, { ":negative_squared_cross_mark:", "❎" }, { ":nepal:", "🇳🇵" }, { ":nerd_face:", "🤓" }, + { ":nesting_dolls:", "🪆" }, { ":netherlands:", "🇳🇱" }, { ":neutral_face:", "😐" }, { ":new:", "🆕" }, @@ -918,21 +1124,22 @@ static struct emojiEntityInfo { ":newspaper_roll:", "🗞" }, { ":next_track_button:", "⏭" }, { ":ng:", "🆖" }, - { ":ng_man:", "🙅♂" }, - { ":ng_woman:", "🙅" }, + { ":ng_man:", "🙅‍♂️" }, + { ":ng_woman:", "🙅‍♀️" }, { ":nicaragua:", "🇳🇮" }, { ":niger:", "🇳🇪" }, { ":nigeria:", "🇳🇬" }, { ":night_with_stars:", "🌃" }, - { ":nine:", "9⃣" }, + { ":nine:", "9️⃣" }, + { ":ninja:", "🥷" }, { ":niue:", "🇳🇺" }, { ":no_bell:", "🔕" }, { ":no_bicycles:", "🚳" }, { ":no_entry:", "⛔" }, { ":no_entry_sign:", "🚫" }, { ":no_good:", "🙅" }, - { ":no_good_man:", "🙅♂" }, - { ":no_good_woman:", "🙅" }, + { ":no_good_man:", "🙅‍♂️" }, + { ":no_good_woman:", "🙅‍♀️" }, { ":no_mobile_phones:", "📵" }, { ":no_mouth:", "😶" }, { ":no_pedestrians:", "🚷" }, @@ -953,14 +1160,18 @@ static struct emojiEntityInfo { ":octopus:", "🐙" }, { ":oden:", "🍢" }, { ":office:", "🏢" }, + { ":office_worker:", "🧑‍💼" }, { ":oil_drum:", "🛢" }, { ":ok:", "🆗" }, { ":ok_hand:", "👌" }, - { ":ok_man:", "🙆♂" }, - { ":ok_woman:", "🙆" }, + { ":ok_man:", "🙆‍♂️" }, + { ":ok_person:", "🙆" }, + { ":ok_woman:", "🙆‍♀️" }, { ":old_key:", "🗝" }, + { ":older_adult:", "🧓" }, { ":older_man:", "👴" }, { ":older_woman:", "👵" }, + { ":olive:", "🫒" }, { ":om:", "🕉" }, { ":oman:", "🇴🇲" }, { ":on:", "🔛" }, @@ -968,19 +1179,27 @@ static struct emojiEntityInfo { ":oncoming_bus:", "🚍" }, { ":oncoming_police_car:", "🚔" }, { ":oncoming_taxi:", "🚖" }, - { ":one:", "1⃣" }, + { ":one:", "1️⃣" }, + { ":one_piece_swimsuit:", "🩱" }, + { ":onion:", "🧅" }, { ":open_book:", "📖" }, { ":open_file_folder:", "📂" }, { ":open_hands:", "👐" }, - { ":open_mouth:", "😮" }, + { ":open_mouth:", "😮‍💨" }, { ":open_umbrella:", "☂" }, { ":ophiuchus:", "⛎" }, { ":orange:", "🍊" }, { ":orange_book:", "📙" }, + { ":orange_circle:", "🟠" }, + { ":orange_heart:", "🧡" }, + { ":orange_square:", "🟧" }, + { ":orangutan:", "🦧" }, { ":orthodox_cross:", "☦" }, + { ":otter:", "🦦" }, { ":outbox_tray:", "📤" }, { ":owl:", "🦉" }, { ":ox:", "🐂" }, + { ":oyster:", "🦪" }, { ":package:", "📦" }, { ":page_facing_up:", "📄" }, { ":page_with_curl:", "📃" }, @@ -990,23 +1209,28 @@ static struct emojiEntityInfo { ":palau:", "🇵🇼" }, { ":palestinian_territories:", "🇵🇸" }, { ":palm_tree:", "🌴" }, + { ":palms_up_together:", "🤲" }, { ":panama:", "🇵🇦" }, { ":pancakes:", "🥞" }, { ":panda_face:", "🐼" }, { ":paperclip:", "📎" }, { ":paperclips:", "🖇" }, { ":papua_new_guinea:", "🇵🇬" }, + { ":parachute:", "🪂" }, { ":paraguay:", "🇵🇾" }, { ":parasol_on_ground:", "⛱" }, { ":parking:", "🅿" }, + { ":parrot:", "🦜" }, { ":part_alternation_mark:", "〽" }, { ":partly_sunny:", "⛅" }, + { ":partying_face:", "🥳" }, { ":passenger_ship:", "🛳" }, { ":passport_control:", "🛂" }, { ":pause_button:", "⏸" }, { ":paw_prints:", "🐾" }, { ":peace_symbol:", "☮" }, { ":peach:", "🍑" }, + { ":peacock:", "🦚" }, { ":peanuts:", "🥜" }, { ":pear:", "🍐" }, { ":pen:", "🖊" }, @@ -1014,37 +1238,60 @@ static struct emojiEntityInfo { ":pencil2:", "✏" }, { ":penguin:", "🐧" }, { ":pensive:", "😔" }, + { ":people_holding_hands:", "🧑‍🤝‍🧑" }, + { ":people_hugging:", "🫂" }, { ":performing_arts:", "🎭" }, { ":persevere:", "😣" }, + { ":person_bald:", "🧑‍🦲" }, + { ":person_curly_hair:", "🧑‍🦱" }, + { ":person_feeding_baby:", "🧑‍🍼" }, { ":person_fencing:", "🤺" }, - { ":person_frowning:", "🙍" }, - { ":person_with_blond_hair:", "👱" }, - { ":person_with_pouting_face:", "🙎" }, + { ":person_in_manual_wheelchair:", "🧑‍🦽" }, + { ":person_in_motorized_wheelchair:", "🧑‍🦼" }, + { ":person_in_tuxedo:", "🤵" }, + { ":person_red_hair:", "🧑‍🦰" }, + { ":person_white_hair:", "🧑‍🦳" }, + { ":person_with_probing_cane:", "🧑‍🦯" }, + { ":person_with_turban:", "👳" }, + { ":person_with_veil:", "👰" }, { ":peru:", "🇵🇪" }, + { ":petri_dish:", "🧫" }, { ":philippines:", "🇵🇭" }, { ":phone:", "☎" }, { ":pick:", "⛏" }, + { ":pickup_truck:", "🛻" }, + { ":pie:", "🥧" }, { ":pig:", "🐷" }, { ":pig2:", "🐖" }, { ":pig_nose:", "🐽" }, { ":pill:", "💊" }, + { ":pilot:", "🧑‍✈️" }, + { ":pinata:", "🪅" }, + { ":pinched_fingers:", "🤌" }, + { ":pinching_hand:", "🤏" }, { ":pineapple:", "🍍" }, { ":ping_pong:", "🏓" }, + { ":pirate_flag:", "🏴‍☠️" }, { ":pisces:", "♓" }, { ":pitcairn_islands:", "🇵🇳" }, { ":pizza:", "🍕" }, + { ":placard:", "🪧" }, { ":place_of_worship:", "🛐" }, { ":plate_with_cutlery:", "🍽" }, { ":play_or_pause_button:", "⏯" }, + { ":pleading_face:", "🥺" }, + { ":plunger:", "🪠" }, { ":point_down:", "👇" }, { ":point_left:", "👈" }, { ":point_right:", "👉" }, { ":point_up:", "☝" }, { ":point_up_2:", "👆" }, { ":poland:", "🇵🇱" }, + { ":polar_bear:", "🐻‍❄️" }, { ":police_car:", "🚓" }, - { ":policeman:", "👮" }, - { ":policewoman:", "👮♀" }, + { ":police_officer:", "👮" }, + { ":policeman:", "👮‍♂️" }, + { ":policewoman:", "👮‍♀️" }, { ":poodle:", "🐩" }, { ":poop:", "💩" }, { ":popcorn:", "🍿" }, @@ -1054,23 +1301,29 @@ static struct emojiEntityInfo { ":postbox:", "📮" }, { ":potable_water:", "🚰" }, { ":potato:", "🥔" }, + { ":potted_plant:", "🪴" }, { ":pouch:", "👝" }, { ":poultry_leg:", "🍗" }, { ":pound:", "💷" }, { ":pout:", "😡" }, { ":pouting_cat:", "😾" }, - { ":pouting_man:", "🙎♂" }, - { ":pouting_woman:", "🙎" }, + { ":pouting_face:", "🙎" }, + { ":pouting_man:", "🙎‍♂️" }, + { ":pouting_woman:", "🙎‍♀️" }, { ":pray:", "🙏" }, { ":prayer_beads:", "📿" }, { ":pregnant_woman:", "🤰" }, + { ":pretzel:", "🥨" }, { ":previous_track_button:", "⏮" }, { ":prince:", "🤴" }, { ":princess:", "👸" }, { ":printer:", "🖨" }, + { ":probing_cane:", "🦯" }, { ":puerto_rico:", "🇵🇷" }, { ":punch:", "👊" }, + { ":purple_circle:", "🟣" }, { ":purple_heart:", "💜" }, + { ":purple_square:", "🟪" }, { ":purse:", "👛" }, { ":pushpin:", "📌" }, { ":put_litter_in_its_place:", "🚮" }, @@ -1078,6 +1331,7 @@ static struct emojiEntityInfo { ":question:", "❓" }, { ":rabbit:", "🐰" }, { ":rabbit2:", "🐇" }, + { ":raccoon:", "🦝" }, { ":racehorse:", "🐎" }, { ":racing_car:", "🏎" }, { ":radio:", "📻" }, @@ -1087,21 +1341,28 @@ static struct emojiEntityInfo { ":railway_car:", "🚃" }, { ":railway_track:", "🛤" }, { ":rainbow:", "🌈" }, - { ":rainbow_flag:", "🏳🌈" }, + { ":rainbow_flag:", "🏳️‍🌈" }, { ":raised_back_of_hand:", "🤚" }, + { ":raised_eyebrow:", "🤨" }, { ":raised_hand:", "✋" }, { ":raised_hand_with_fingers_splayed:", "🖐" }, { ":raised_hands:", "🙌" }, { ":raising_hand:", "🙋" }, - { ":raising_hand_man:", "🙋♂" }, - { ":raising_hand_woman:", "🙋" }, + { ":raising_hand_man:", "🙋‍♂️" }, + { ":raising_hand_woman:", "🙋‍♀️" }, { ":ram:", "🐏" }, { ":ramen:", "🍜" }, { ":rat:", "🐀" }, + { ":razor:", "🪒" }, + { ":receipt:", "🧾" }, { ":record_button:", "⏺" }, { ":recycle:", "♻" }, { ":red_car:", "🚗" }, { ":red_circle:", "🔴" }, + { ":red_envelope:", "🧧" }, + { ":red_haired_man:", "👨‍🦰" }, + { ":red_haired_woman:", "👩‍🦰" }, + { ":red_square:", "🟥" }, { ":registered:", "®" }, { ":relaxed:", "☺" }, { ":relieved:", "😌" }, @@ -1121,11 +1382,15 @@ static struct emojiEntityInfo { ":rice_scene:", "🎑" }, { ":right_anger_bubble:", "🗯" }, { ":ring:", "💍" }, + { ":ringed_planet:", "🪐" }, { ":robot:", "🤖" }, + { ":rock:", "🪨" }, { ":rocket:", "🚀" }, { ":rofl:", "🤣" }, { ":roll_eyes:", "🙄" }, + { ":roll_of_paper:", "🧻" }, { ":roller_coaster:", "🎢" }, + { ":roller_skate:", "🛼" }, { ":romania:", "🇷🇴" }, { ":rooster:", "🐓" }, { ":rose:", "🌹" }, @@ -1133,37 +1398,53 @@ static struct emojiEntityInfo { ":rotating_light:", "🚨" }, { ":round_pushpin:", "📍" }, { ":rowboat:", "🚣" }, - { ":rowing_man:", "🚣" }, - { ":rowing_woman:", "🚣♀" }, + { ":rowing_man:", "🚣‍♂️" }, + { ":rowing_woman:", "🚣‍♀️" }, { ":ru:", "🇷🇺" }, { ":rugby_football:", "🏉" }, { ":runner:", "🏃" }, { ":running:", "🏃" }, - { ":running_man:", "🏃" }, + { ":running_man:", "🏃‍♂️" }, { ":running_shirt_with_sash:", "🎽" }, - { ":running_woman:", "🏃♀" }, + { ":running_woman:", "🏃‍♀️" }, { ":rwanda:", "🇷🇼" }, { ":sa:", "🈂" }, + { ":safety_pin:", "🧷" }, + { ":safety_vest:", "🦺" }, { ":sagittarius:", "♐" }, { ":sailboat:", "⛵" }, { ":sake:", "🍶" }, + { ":salt:", "🧂" }, { ":samoa:", "🇼🇸" }, { ":san_marino:", "🇸🇲" }, { ":sandal:", "👡" }, + { ":sandwich:", "🥪" }, { ":santa:", "🎅" }, { ":sao_tome_principe:", "🇸🇹" }, + { ":sari:", "🥻" }, + { ":sassy_man:", "💁‍♂️" }, + { ":sassy_woman:", "💁‍♀️" }, { ":satellite:", "📡" }, { ":satisfied:", "😆" }, { ":saudi_arabia:", "🇸🇦" }, + { ":sauna_man:", "🧖‍♂️" }, + { ":sauna_person:", "🧖" }, + { ":sauna_woman:", "🧖‍♀️" }, + { ":sauropod:", "🦕" }, { ":saxophone:", "🎷" }, + { ":scarf:", "🧣" }, { ":school:", "🏫" }, { ":school_satchel:", "🎒" }, + { ":scientist:", "🧑‍🔬" }, { ":scissors:", "✂" }, { ":scorpion:", "🦂" }, { ":scorpius:", "♏" }, + { ":scotland:", "🏴󠁧󠁢󠁳󠁣󠁴󠁿" }, { ":scream:", "😱" }, { ":scream_cat:", "🙀" }, + { ":screwdriver:", "🪛" }, { ":scroll:", "📜" }, + { ":seal:", "🦭" }, { ":seat:", "💺" }, { ":secret:", "㊙" }, { ":see_no_evil:", "🙈" }, @@ -1171,7 +1452,9 @@ static struct emojiEntityInfo { ":selfie:", "🤳" }, { ":senegal:", "🇸🇳" }, { ":serbia:", "🇷🇸" }, - { ":seven:", "7⃣" }, + { ":service_dog:", "🐕‍🦺" }, + { ":seven:", "7️⃣" }, + { ":sewing_needle:", "🪡" }, { ":seychelles:", "🇸🇨" }, { ":shallow_pan_of_food:", "🥘" }, { ":shamrock:", "☘" }, @@ -1187,24 +1470,32 @@ static struct emojiEntityInfo { ":shoe:", "👞" }, { ":shopping:", "🛍" }, { ":shopping_cart:", "🛒" }, + { ":shorts:", "🩳" }, { ":shower:", "🚿" }, { ":shrimp:", "🦐" }, + { ":shrug:", "🤷" }, + { ":shushing_face:", "🤫" }, { ":sierra_leone:", "🇸🇱" }, { ":signal_strength:", "📶" }, { ":singapore:", "🇸🇬" }, + { ":singer:", "🧑‍🎤" }, { ":sint_maarten:", "🇸🇽" }, - { ":six:", "6⃣" }, + { ":six:", "6️⃣" }, { ":six_pointed_star:", "🔯" }, + { ":skateboard:", "🛹" }, { ":ski:", "🎿" }, { ":skier:", "⛷" }, { ":skull:", "💀" }, { ":skull_and_crossbones:", "☠" }, + { ":skunk:", "🦨" }, + { ":sled:", "🛷" }, { ":sleeping:", "😴" }, { ":sleeping_bed:", "🛌" }, { ":sleepy:", "😪" }, { ":slightly_frowning_face:", "🙁" }, { ":slightly_smiling_face:", "🙂" }, { ":slot_machine:", "🎰" }, + { ":sloth:", "🦥" }, { ":slovakia:", "🇸🇰" }, { ":slovenia:", "🇸🇮" }, { ":small_airplane:", "🛩" }, @@ -1216,6 +1507,8 @@ static struct emojiEntityInfo { ":smile_cat:", "😸" }, { ":smiley:", "😃" }, { ":smiley_cat:", "😺" }, + { ":smiling_face_with_tear:", "🥲" }, + { ":smiling_face_with_three_hearts:", "🥰" }, { ":smiling_imp:", "😈" }, { ":smirk:", "😏" }, { ":smirk_cat:", "😼" }, @@ -1227,8 +1520,11 @@ static struct emojiEntityInfo { ":snowflake:", "❄" }, { ":snowman:", "⛄" }, { ":snowman_with_snow:", "☃" }, + { ":soap:", "🧼" }, { ":sob:", "😭" }, { ":soccer:", "⚽" }, + { ":socks:", "🧦" }, + { ":softball:", "🥎" }, { ":solomon_islands:", "🇸🇧" }, { ":somalia:", "🇸🇴" }, { ":soon:", "🔜" }, @@ -1253,6 +1549,7 @@ static struct emojiEntityInfo { ":spider_web:", "🕸" }, { ":spiral_calendar:", "🗓" }, { ":spiral_notepad:", "🗒" }, + { ":sponge:", "🧽" }, { ":spoon:", "🥄" }, { ":squid:", "🦑" }, { ":sri_lanka:", "🇱🇰" }, @@ -1260,17 +1557,23 @@ static struct emojiEntityInfo { ":st_helena:", "🇸🇭" }, { ":st_kitts_nevis:", "🇰🇳" }, { ":st_lucia:", "🇱🇨" }, + { ":st_martin:", "🇲🇫" }, { ":st_pierre_miquelon:", "🇵🇲" }, { ":st_vincent_grenadines:", "🇻🇨" }, { ":stadium:", "🏟" }, + { ":standing_man:", "🧍‍♂️" }, + { ":standing_person:", "🧍" }, + { ":standing_woman:", "🧍‍♀️" }, { ":star:", "⭐" }, { ":star2:", "🌟" }, { ":star_and_crescent:", "☪" }, { ":star_of_david:", "✡" }, + { ":star_struck:", "🤩" }, { ":stars:", "🌠" }, { ":station:", "🚉" }, { ":statue_of_liberty:", "🗽" }, { ":steam_locomotive:", "🚂" }, + { ":stethoscope:", "🩺" }, { ":stew:", "🍲" }, { ":stop_button:", "⏹" }, { ":stop_sign:", "🛑" }, @@ -1280,6 +1583,7 @@ static struct emojiEntityInfo { ":stuck_out_tongue:", "😛" }, { ":stuck_out_tongue_closed_eyes:", "😝" }, { ":stuck_out_tongue_winking_eye:", "😜" }, + { ":student:", "🧑‍🎓" }, { ":studio_microphone:", "🎙" }, { ":stuffed_flatbread:", "🥙" }, { ":sudan:", "🇸🇩" }, @@ -1292,46 +1596,65 @@ static struct emojiEntityInfo { ":sunny:", "☀" }, { ":sunrise:", "🌅" }, { ":sunrise_over_mountains:", "🌄" }, + { ":superhero:", "🦸" }, + { ":superhero_man:", "🦸‍♂️" }, + { ":superhero_woman:", "🦸‍♀️" }, + { ":supervillain:", "🦹" }, + { ":supervillain_man:", "🦹‍♂️" }, + { ":supervillain_woman:", "🦹‍♀️" }, { ":surfer:", "🏄" }, - { ":surfing_man:", "🏄" }, - { ":surfing_woman:", "🏄♀" }, + { ":surfing_man:", "🏄‍♂️" }, + { ":surfing_woman:", "🏄‍♀️" }, { ":suriname:", "🇸🇷" }, { ":sushi:", "🍣" }, { ":suspension_railway:", "🚟" }, + { ":svalbard_jan_mayen:", "🇸🇯" }, + { ":swan:", "🦢" }, { ":swaziland:", "🇸🇿" }, { ":sweat:", "😓" }, { ":sweat_drops:", "💦" }, { ":sweat_smile:", "😅" }, { ":sweden:", "🇸🇪" }, { ":sweet_potato:", "🍠" }, + { ":swim_brief:", "🩲" }, { ":swimmer:", "🏊" }, - { ":swimming_man:", "🏊" }, - { ":swimming_woman:", "🏊♀" }, + { ":swimming_man:", "🏊‍♂️" }, + { ":swimming_woman:", "🏊‍♀️" }, { ":switzerland:", "🇨🇭" }, { ":symbols:", "🔣" }, { ":synagogue:", "🕍" }, { ":syria:", "🇸🇾" }, { ":syringe:", "💉" }, + { ":t-rex:", "🦖" }, { ":taco:", "🌮" }, { ":tada:", "🎉" }, { ":taiwan:", "🇹🇼" }, { ":tajikistan:", "🇹🇯" }, + { ":takeout_box:", "🥡" }, + { ":tamale:", "🫔" }, { ":tanabata_tree:", "🎋" }, { ":tangerine:", "🍊" }, { ":tanzania:", "🇹🇿" }, { ":taurus:", "♉" }, { ":taxi:", "🚕" }, { ":tea:", "🍵" }, + { ":teacher:", "🧑‍🏫" }, + { ":teapot:", "🫖" }, + { ":technologist:", "🧑‍💻" }, + { ":teddy_bear:", "🧸" }, { ":telephone:", "☎" }, { ":telephone_receiver:", "📞" }, { ":telescope:", "🔭" }, { ":tennis:", "🎾" }, { ":tent:", "⛺" }, + { ":test_tube:", "🧪" }, { ":thailand:", "🇹🇭" }, { ":thermometer:", "🌡" }, { ":thinking:", "🤔" }, + { ":thong_sandal:", "🩴" }, { ":thought_balloon:", "💭" }, - { ":three:", "3⃣" }, + { ":thread:", "🧵" }, + { ":three:", "3️⃣" }, { ":thumbsdown:", "👎" }, { ":thumbsup:", "👍" }, { ":ticket:", "🎫" }, @@ -1340,8 +1663,9 @@ static struct emojiEntityInfo { ":tiger2:", "🐅" }, { ":timer_clock:", "⏲" }, { ":timor_leste:", "🇹🇱" }, - { ":tipping_hand_man:", "💁♂" }, - { ":tipping_hand_woman:", "💁" }, + { ":tipping_hand_man:", "💁‍♂️" }, + { ":tipping_hand_person:", "💁" }, + { ":tipping_hand_woman:", "💁‍♀️" }, { ":tired_face:", "😫" }, { ":tm:", "™" }, { ":togo:", "🇹🇬" }, @@ -1351,6 +1675,9 @@ static struct emojiEntityInfo { ":tomato:", "🍅" }, { ":tonga:", "🇹🇴" }, { ":tongue:", "👅" }, + { ":toolbox:", "🧰" }, + { ":tooth:", "🦷" }, + { ":toothbrush:", "🪥" }, { ":top:", "🔝" }, { ":tophat:", "🎩" }, { ":tornado:", "🌪" }, @@ -1361,10 +1688,13 @@ static struct emojiEntityInfo { ":train:", "🚋" }, { ":train2:", "🚆" }, { ":tram:", "🚊" }, + { ":transgender_flag:", "🏳️‍⚧️" }, + { ":transgender_symbol:", "⚧" }, { ":triangular_flag_on_post:", "🚩" }, { ":triangular_ruler:", "📐" }, { ":trident:", "🔱" }, { ":trinidad_tobago:", "🇹🇹" }, + { ":tristan_da_cunha:", "🇹🇦" }, { ":triumph:", "😤" }, { ":trolleybus:", "🚎" }, { ":trophy:", "🏆" }, @@ -1383,7 +1713,7 @@ static struct emojiEntityInfo { ":tuvalu:", "🇹🇻" }, { ":tv:", "📺" }, { ":twisted_rightwards_arrows:", "🔀" }, - { ":two:", "2⃣" }, + { ":two:", "2️⃣" }, { ":two_hearts:", "💕" }, { ":two_men_holding_hands:", "👬" }, { ":two_women_holding_hands:", "👭" }, @@ -1406,14 +1736,19 @@ static struct emojiEntityInfo { ":underage:", "🔞" }, { ":unicorn:", "🦄" }, { ":united_arab_emirates:", "🇦🇪" }, + { ":united_nations:", "🇺🇳" }, { ":unlock:", "🔓" }, { ":up:", "🆙" }, { ":upside_down_face:", "🙃" }, { ":uruguay:", "🇺🇾" }, { ":us:", "🇺🇸" }, + { ":us_outlying_islands:", "🇺🇲" }, { ":us_virgin_islands:", "🇻🇮" }, { ":uzbekistan:", "🇺🇿" }, { ":v:", "✌" }, + { ":vampire:", "🧛" }, + { ":vampire_man:", "🧛‍♂️" }, + { ":vampire_woman:", "🧛‍♀️" }, { ":vanuatu:", "🇻🇺" }, { ":vatican_city:", "🇻🇦" }, { ":venezuela:", "🇻🇪" }, @@ -1427,11 +1762,14 @@ static struct emojiEntityInfo { ":virgo:", "♍" }, { ":volcano:", "🌋" }, { ":volleyball:", "🏐" }, + { ":vomiting_face:", "🤮" }, { ":vs:", "🆚" }, { ":vulcan_salute:", "🖖" }, + { ":waffle:", "🧇" }, + { ":wales:", "🏴󠁧󠁢󠁷󠁬󠁳󠁿" }, { ":walking:", "🚶" }, - { ":walking_man:", "🚶" }, - { ":walking_woman:", "🚶♀" }, + { ":walking_man:", "🚶‍♂️" }, + { ":walking_woman:", "🚶‍♀️" }, { ":wallis_futuna:", "🇼🇫" }, { ":waning_crescent_moon:", "🌘" }, { ":waning_gibbous_moon:", "🌖" }, @@ -1439,6 +1777,7 @@ static struct emojiEntityInfo { ":wastebasket:", "🗑" }, { ":watch:", "⌚" }, { ":water_buffalo:", "🐃" }, + { ":water_polo:", "🤽" }, { ":watermelon:", "🍉" }, { ":wave:", "👋" }, { ":wavy_dash:", "〰" }, @@ -1447,8 +1786,9 @@ static struct emojiEntityInfo { ":wc:", "🚾" }, { ":weary:", "😩" }, { ":wedding:", "💒" }, - { ":weight_lifting_man:", "🏋" }, - { ":weight_lifting_woman:", "🏋♀" }, + { ":weight_lifting:", "🏋" }, + { ":weight_lifting_man:", "🏋️‍♂️" }, + { ":weight_lifting_woman:", "🏋️‍♀️" }, { ":western_sahara:", "🇪🇭" }, { ":whale:", "🐳" }, { ":whale2:", "🐋" }, @@ -1458,6 +1798,9 @@ static struct emojiEntityInfo { ":white_circle:", "⚪" }, { ":white_flag:", "🏳" }, { ":white_flower:", "💮" }, + { ":white_haired_man:", "👨‍🦳" }, + { ":white_haired_woman:", "👩‍🦳" }, + { ":white_heart:", "🤍" }, { ":white_large_square:", "⬜" }, { ":white_medium_small_square:", "◽" }, { ":white_medium_square:", "◻" }, @@ -1466,66 +1809,107 @@ static struct emojiEntityInfo { ":wilted_flower:", "🥀" }, { ":wind_chime:", "🎐" }, { ":wind_face:", "🌬" }, + { ":window:", "🪟" }, { ":wine_glass:", "🍷" }, { ":wink:", "😉" }, { ":wolf:", "🐺" }, { ":woman:", "👩" }, - { ":woman_artist:", "👩🎨" }, - { ":woman_astronaut:", "👩🚀" }, - { ":woman_cartwheeling:", "🤸♀" }, - { ":woman_cook:", "👩🍳" }, - { ":woman_facepalming:", "🤦♀" }, - { ":woman_factory_worker:", "👩🏭" }, - { ":woman_farmer:", "👩🌾" }, - { ":woman_firefighter:", "👩🚒" }, - { ":woman_health_worker:", "👩⚕" }, - { ":woman_judge:", "👩⚖" }, - { ":woman_juggling:", "🤹♀" }, - { ":woman_mechanic:", "👩🔧" }, - { ":woman_office_worker:", "👩💼" }, - { ":woman_pilot:", "👩✈" }, - { ":woman_playing_handball:", "🤾♀" }, - { ":woman_playing_water_polo:", "🤽♀" }, - { ":woman_scientist:", "👩🔬" }, - { ":woman_shrugging:", "🤷♀" }, - { ":woman_singer:", "👩🎤" }, - { ":woman_student:", "👩🎓" }, - { ":woman_teacher:", "👩🏫" }, - { ":woman_technologist:", "👩💻" }, - { ":woman_with_turban:", "👳♀" }, + { ":woman_artist:", "👩‍🎨" }, + { ":woman_astronaut:", "👩‍🚀" }, + { ":woman_beard:", "🧔‍♀️" }, + { ":woman_cartwheeling:", "🤸‍♀️" }, + { ":woman_cook:", "👩‍🍳" }, + { ":woman_dancing:", "💃" }, + { ":woman_facepalming:", "🤦‍♀️" }, + { ":woman_factory_worker:", "👩‍🏭" }, + { ":woman_farmer:", "👩‍🌾" }, + { ":woman_feeding_baby:", "👩‍🍼" }, + { ":woman_firefighter:", "👩‍🚒" }, + { ":woman_health_worker:", "👩‍⚕️" }, + { ":woman_in_manual_wheelchair:", "👩‍🦽" }, + { ":woman_in_motorized_wheelchair:", "👩‍🦼" }, + { ":woman_in_tuxedo:", "🤵‍♀️" }, + { ":woman_judge:", "👩‍⚖️" }, + { ":woman_juggling:", "🤹‍♀️" }, + { ":woman_mechanic:", "👩‍🔧" }, + { ":woman_office_worker:", "👩‍💼" }, + { ":woman_pilot:", "👩‍✈️" }, + { ":woman_playing_handball:", "🤾‍♀️" }, + { ":woman_playing_water_polo:", "🤽‍♀️" }, + { ":woman_scientist:", "👩‍🔬" }, + { ":woman_shrugging:", "🤷‍♀️" }, + { ":woman_singer:", "👩‍🎤" }, + { ":woman_student:", "👩‍🎓" }, + { ":woman_teacher:", "👩‍🏫" }, + { ":woman_technologist:", "👩‍💻" }, + { ":woman_with_headscarf:", "🧕" }, + { ":woman_with_probing_cane:", "👩‍🦯" }, + { ":woman_with_turban:", "👳‍♀️" }, + { ":woman_with_veil:", "👰‍♀️" }, { ":womans_clothes:", "👚" }, { ":womans_hat:", "👒" }, - { ":women_wrestling:", "🤼♀" }, + { ":women_wrestling:", "🤼‍♀️" }, { ":womens:", "🚺" }, + { ":wood:", "🪵" }, + { ":woozy_face:", "🥴" }, { ":world_map:", "🗺" }, + { ":worm:", "🪱" }, { ":worried:", "😟" }, { ":wrench:", "🔧" }, + { ":wrestling:", "🤼" }, { ":writing_hand:", "✍" }, { ":x:", "❌" }, + { ":yarn:", "🧶" }, + { ":yawning_face:", "🥱" }, + { ":yellow_circle:", "🟡" }, { ":yellow_heart:", "💛" }, + { ":yellow_square:", "🟨" }, { ":yemen:", "🇾🇪" }, { ":yen:", "💴" }, { ":yin_yang:", "☯" }, + { ":yo_yo:", "🪀" }, { ":yum:", "😋" }, { ":zambia:", "🇿🇲" }, + { ":zany_face:", "🤪" }, { ":zap:", "⚡" }, - { ":zero:", "0⃣" }, + { ":zebra:", "🦓" }, + { ":zero:", "0️⃣" }, { ":zimbabwe:", "🇿🇼" }, { ":zipper_mouth_face:", "🤐" }, - { ":zzz:", "💤" } + { ":zombie:", "🧟" }, + { ":zombie_man:", "🧟‍♂️" }, + { ":zombie_woman:", "🧟‍♀️" }, + { ":zzz:", "💤" }, +}; +// compatibility with older versions +static struct emojiEntityCompatibility +{ + const char *oldName; + const char *newName; +} g_emojiCompatibilityEntities[] = +{ + {":blonde_man:", ":blond_haired_man:"}, + {":person_frowning:", ":frowning_person:"}, + {":person_with_blond_hair:", ":blond_haired_person:"}, + {":person_with_pouting_face:", ":pouting_face:"}, }; static const int g_numEmojiEntities = (int)(sizeof(g_emojiEntities)/sizeof(*g_emojiEntities)); +static const int g_numEmojiCompatibilityEntities = (int)(sizeof(g_emojiCompatibilityEntities)/sizeof(*g_emojiCompatibilityEntities)); EmojiEntityMapper *EmojiEntityMapper::s_instance = 0; EmojiEntityMapper::EmojiEntityMapper() { - // 2 loops to be able to give precedence to the unicodeName (CLDR) for (int i = 0; i < g_numEmojiEntities; i++) { m_name2symGh.insert(std::make_pair(g_emojiEntities[i].name, i)); } + for (int i = 0; i < g_numEmojiCompatibilityEntities; i++) + { + int ii = symbol2index(g_emojiCompatibilityEntities[i].newName); + if (ii != -1) m_name2symGh.insert(std::make_pair(g_emojiCompatibilityEntities[i].oldName, ii)); + } } EmojiEntityMapper::~EmojiEntityMapper() @@ -1570,6 +1954,10 @@ void EmojiEntityMapper::writeEmojiFile(TextStream &t) { t << g_emojiEntities[i].name << "\n"; } + for (int i = 0; i < g_numEmojiCompatibilityEntities; i++) + { + t << g_emojiCompatibilityEntities[i].oldName << "\n"; + } } /*! @brief Access routine to the unicode sequence for the Emoji entity @@ -1591,5 +1979,3 @@ const char *EmojiEntityMapper::name(int index) const { return index>=0 && index<g_numEmojiEntities ? g_emojiEntities[index].name : 0; } - - diff --git a/src/filedef.cpp b/src/filedef.cpp index 0c79e01..4a86b4d 100644 --- a/src/filedef.cpp +++ b/src/filedef.cpp @@ -208,7 +208,7 @@ class DevNullCodeDocInterface : public CodeOutputInterface const QCString &, const SourceLinkInfo &, const SourceLinkInfo & ) override {} virtual void writeLineNumber(const QCString &,const QCString &, - const QCString &,int) override {} + const QCString &,int,bool) override {} virtual void startCodeLine(bool) override {} virtual void endCodeLine() override {} virtual void startFontClass(const QCString &) override {} @@ -318,7 +318,7 @@ void FileDefImpl::writeTagFile(TextStream &tagFile) tagFile << " <compound kind=\"file\">\n"; tagFile << " <name>" << convertToXML(name()) << "</name>\n"; tagFile << " <path>" << convertToXML(getPath()) << "</path>\n"; - tagFile << " <filename>" << convertToXML(getOutputFileBase()) << Doxygen::htmlFileExtension << "</filename>\n"; + tagFile << " <filename>" << addHtmlExtensionIfMissing(getOutputFileBase()) << "</filename>\n"; for (const auto &ii : m_includeList) { const FileDef *fd=ii.fileDef; @@ -876,13 +876,6 @@ void FileDefImpl::writeDocumentation(OutputList &ol) ol.enableAll(); } - if (Doxygen::searchIndex) - { - Doxygen::searchIndex->setCurrentDoc(this,anchor(),FALSE); - Doxygen::searchIndex->addWord(localName(),TRUE); - } - - //---------------------------------------- start flexible part ------------------------------- SrcLangExt lang = getLanguage(); @@ -1077,7 +1070,7 @@ void FileDefImpl::writeQuickMemberLinks(OutputList &ol,const MemberDef *currentM ol.writeString("<a class=\"navtab\" "); ol.writeString("href=\""); if (createSubDirs) ol.writeString("../../"); - ol.writeString(md->getOutputFileBase()+Doxygen::htmlFileExtension+"#"+md->anchor()); + ol.writeString(addHtmlExtensionIfMissing(md->getOutputFileBase())+"#"+md->anchor()); ol.writeString("\">"); ol.writeString(convertToHtml(md->localName())); ol.writeString("</a>"); diff --git a/src/fileparser.cpp b/src/fileparser.cpp index f45f36e..ff801f7 100644 --- a/src/fileparser.cpp +++ b/src/fileparser.cpp @@ -25,7 +25,7 @@ void FileCodeParser::parseCode(CodeOutputInterface &codeOutIntf, const FileDef * fileDef, int startLine, int endLine, - bool, // inlineFragment + bool inlineFragment, const MemberDef *, // memberDef bool showLineNumbers, const Definition *, // searchCtx, @@ -43,7 +43,7 @@ void FileCodeParser::parseCode(CodeOutputInterface &codeOutIntf, codeOutIntf.startCodeLine(fileDef != 0 && showLineNumbers); if (fileDef != 0 && showLineNumbers) { - codeOutIntf.writeLineNumber(QCString(),QCString(),QCString(),lineNr); + codeOutIntf.writeLineNumber(QCString(),QCString(),QCString(),lineNr,!inlineFragment); } if (!lineStr.isEmpty()) codeOutIntf.codify(lineStr.data()); codeOutIntf.endCodeLine(); diff --git a/src/fortrancode.l b/src/fortrancode.l index 51e3ada..9ddcd17 100644 --- a/src/fortrancode.l +++ b/src/fortrancode.l @@ -32,6 +32,10 @@ %option noyy_top_state %top{ #include <stdint.h> +// forward declare yyscan_t to improve type safety +#define YY_TYPEDEF_YY_SCANNER_T +struct yyguts_t; +typedef yyguts_t *yyscan_t; } %{ @@ -136,10 +140,11 @@ struct fortrancodeYY_state const char * inputString = 0; //!< the code fragment as text yy_size_t inputPosition = 0; //!< read offset during parsing int inputLines = 0; //!< number of line in the code fragment + QCString fileName; int yyLineNr = 0; //!< current line number int contLineNr = 0; //!< current, local, line number for continuation determination int *hasContLine = 0; //!< signals whether or not a line has a continuation line (fixed source form) - bool needsTermination = false; + bool insideCodeLine = false; const Definition *searchCtx = 0; bool collectXRefs = false; bool isFixedForm = false; @@ -217,6 +222,10 @@ static std::mutex g_countFlowKeywordsMutex; #undef YY_INPUT #define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); +// otherwise the filename would be the name of the converted file (*.cpp instead of *.l) +static inline const char *getLexerFILE() {return __FILE__;} +#include "doxygen_lex.h" + %} IDSYM [a-z_A-Z0-9] @@ -258,9 +267,7 @@ LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}(,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})?") %x Start %x SubCall -%x FuncDef %x ClassName -%x ClassVar %x Subprog %x DocBlock %x Use @@ -269,7 +276,6 @@ LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}(,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})?") %x Declaration %x DeclarationBinding %x DeclContLine -%x Parameterlist %x String %x Subprogend @@ -375,6 +381,7 @@ LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}(,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})?") } <*>"import"{BS}/"\n" | <*>"import"{BS_} { + if(YY_START == String) YY_FTN_REJECT; // ignore in strings startFontClass(yyscanner,"keywordtype"); codifyLines(yyscanner,yytext); endFontClass(yyscanner); @@ -410,6 +417,7 @@ LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}(,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})?") BEGIN(ClassName); } <*>{LANGUAGE_BIND_SPEC} { // + if(YY_START == String) YY_FTN_REJECT; // ignore in strings startFontClass(yyscanner,"keyword"); codifyLines(yyscanner,yytext); endFontClass(yyscanner); @@ -720,11 +728,13 @@ LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}(,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})?") endFontClass(yyscanner); } <*>"assignment"/{BS}"("{BS}"="{BS}")" { + if(YY_START == String) YY_FTN_REJECT; // ignore in strings startFontClass(yyscanner,"keyword"); codifyLines(yyscanner,yytext); endFontClass(yyscanner); } <*>"operator"/{BS}"("[^)]*")" { + if(YY_START == String) YY_FTN_REJECT; // ignore in strings startFontClass(yyscanner,"keyword"); codifyLines(yyscanner,yytext); endFontClass(yyscanner); @@ -929,23 +939,27 @@ static void startCodeLine(yyscan_t yyscanner) { yyextra->code->writeLineNumber(yyextra->currentMemberDef->getReference(), yyextra->currentMemberDef->getOutputFileBase(), - yyextra->currentMemberDef->anchor(),yyextra->yyLineNr); + yyextra->currentMemberDef->anchor(),yyextra->yyLineNr, + !yyextra->includeCodeFragment); setCurrentDoc(yyscanner,lineAnchor); } else if (d->isLinkableInProject()) { yyextra->code->writeLineNumber(d->getReference(), d->getOutputFileBase(), - QCString(),yyextra->yyLineNr); + QCString(),yyextra->yyLineNr, + !yyextra->includeCodeFragment); setCurrentDoc(yyscanner,lineAnchor); } } else { - yyextra->code->writeLineNumber(QCString(),QCString(),QCString(),yyextra->yyLineNr); + yyextra->code->writeLineNumber(QCString(),QCString(),QCString(),yyextra->yyLineNr, + !yyextra->includeCodeFragment); } } yyextra->code->startCodeLine(yyextra->sourceFileDef); + yyextra->insideCodeLine=true; if (yyextra->currentFontClass) { yyextra->code->startFontClass(QCString(yyextra->currentFontClass)); @@ -958,6 +972,7 @@ static void endCodeLine(yyscan_t yyscanner) struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; endFontClass(yyscanner); yyextra->code->endCodeLine(); + yyextra->insideCodeLine=false; } static void nextCodeLine(yyscan_t yyscanner) @@ -1308,8 +1323,7 @@ static int countLines(yyscan_t yyscanner) if (p>yyextra->inputString && *(p-1)!='\n') { // last line does not end with a \n, so we add an extra // line and explicitly terminate the line after parsing. - count++, - yyextra->needsTermination=TRUE; + count++; } return count; } @@ -1425,7 +1439,7 @@ void FortranCodeParser::resetCodeParserState() yyextra->currentDefinition = 0; yyextra->currentMemberDef = 0; yyextra->currentFontClass = 0; - yyextra->needsTermination = FALSE; + yyextra->insideCodeLine = FALSE; BEGIN( Start ); } @@ -1460,6 +1474,7 @@ void FortranCodeParser::parseCode(CodeOutputInterface & codeOutIntf, yyextra->code = &codeOutIntf; yyextra->inputString = input.data(); yyextra->inputPosition = 0; + yyextra->fileName = fileDef ? fileDef->fileName():""; yyextra->isFixedForm = recognizeFixedForm(input,p->format); yyextra->contLineNr = 1; yyextra->hasContLine = NULL; @@ -1468,7 +1483,7 @@ void FortranCodeParser::parseCode(CodeOutputInterface & codeOutIntf, checkContLines(yyscanner,yyextra->inputString); } yyextra->currentFontClass = 0; - yyextra->needsTermination = FALSE; + yyextra->insideCodeLine = FALSE; yyextra->searchCtx = searchCtx; yyextra->collectXRefs = collectXRefs; if (startLine!=-1) @@ -1504,10 +1519,9 @@ void FortranCodeParser::parseCode(CodeOutputInterface & codeOutIntf, fortrancodeYYrestart(0, yyscanner); BEGIN( Start ); fortrancodeYYlex(yyscanner); - if (yyextra->needsTermination) + if (yyextra->insideCodeLine) { - endFontClass(yyscanner); - yyextra->code->endCodeLine(); + endCodeLine(yyscanner); } if (isExampleBlock && yyextra->sourceFileDef) { diff --git a/src/fortranscanner.l b/src/fortranscanner.l index 328612a..20e30b2 100755 --- a/src/fortranscanner.l +++ b/src/fortranscanner.l @@ -44,6 +44,10 @@ %option extra-type="struct fortranscannerYY_state *" %top{ #include <stdint.h> +// forward declare yyscan_t to improve type safety +#define YY_TYPEDEF_YY_SCANNER_T +struct yyguts_t; +typedef yyguts_t *yyscan_t; } %{ @@ -238,6 +242,10 @@ static const char *stateToString(int state); //----------------------------------------------------------------------------- #undef YY_INPUT #define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); + +// otherwise the filename would be the name of the converted file (*.cpp instead of *.l) +static inline const char *getLexerFILE() {return __FILE__;} +#include "doxygen_lex.h" #define YY_USER_ACTION yyextra->colNr+=(int)yyleng; #define INVALID_ENTRY ((Entry*)0x8) //----------------------------------------------------------------------------- @@ -323,7 +331,6 @@ SCOPENAME ({ID}{BS}"::"{BS})* /** comment parsing states */ %x DocBlock %x DocBackLine -%x EndDoc %x BlockData diff --git a/src/ftvhelp.cpp b/src/ftvhelp.cpp index 980130f..4e3150e 100644 --- a/src/ftvhelp.cpp +++ b/src/ftvhelp.cpp @@ -451,8 +451,7 @@ void FTVHelp::generateTree(TextStream &t, const std::vector<FTVNode*> &nl,int le } if (srcRef) { - t << "<a href=\"" << srcRef->getSourceFileBase() - << Doxygen::htmlFileExtension + t << "<a href=\"" << addHtmlExtensionIfMissing(srcRef->getSourceFileBase()) << "\">"; } if (n->def && n->def->definitionType()==Definition::TypeGroup) diff --git a/src/groupdef.cpp b/src/groupdef.cpp index 60a0d18..b5cda7b 100644 --- a/src/groupdef.cpp +++ b/src/groupdef.cpp @@ -613,7 +613,7 @@ void GroupDefImpl::writeTagFile(TextStream &tagFile) tagFile << " <compound kind=\"group\">\n"; tagFile << " <name>" << convertToXML(name()) << "</name>\n"; tagFile << " <title>" << convertToXML(m_title) << "</title>\n"; - tagFile << " <filename>" << convertToXML(getOutputFileBase()) << Doxygen::htmlFileExtension << "</filename>\n"; + tagFile << " <filename>" << addHtmlExtensionIfMissing(getOutputFileBase()) << "</filename>\n"; for (const auto &lde : LayoutDocManager::instance().docEntries(LayoutDocManager::Group)) { switch (lde->kind()) @@ -1119,23 +1119,6 @@ void GroupDefImpl::writeDocumentation(OutputList &ol) ol.endHeaderSection(); ol.startContents(); - if (Doxygen::searchIndex) - { - Doxygen::searchIndex->setCurrentDoc(this,anchor(),FALSE); - std::string title = m_title.str(); - static const reg::Ex re(R"(\a[\w-]*)"); - reg::Iterator it(title,re); - reg::Iterator end; - for (; it!=end ; ++it) - { - const auto &match = *it; - std::string matchStr = match.str(); - Doxygen::searchIndex->addWord(matchStr.c_str(),TRUE); - } - } - - Doxygen::indexList->addIndexItem(this,0,QCString(),m_title); - //---------------------------------------- start flexible part ------------------------------- SrcLangExt lang=getLanguage(); @@ -1320,7 +1303,7 @@ void GroupDefImpl::writeQuickMemberLinks(OutputList &ol,const MemberDef *current ol.writeString("<a class=\"navtab\" "); ol.writeString("href=\""); if (createSubDirs) ol.writeString("../../"); - ol.writeString(md->getOutputFileBase()+Doxygen::htmlFileExtension+"#"+md->anchor()); + ol.writeString(addHtmlExtensionIfMissing(md->getOutputFileBase())+"#"+md->anchor()); ol.writeString("\">"); ol.writeString(convertToHtml(md->localName())); ol.writeString("</a>"); diff --git a/src/growbuf.h b/src/growbuf.h index 8c532ca..00bcfec 100644 --- a/src/growbuf.h +++ b/src/growbuf.h @@ -1,6 +1,7 @@ #ifndef GROWBUF_H #define GROWBUF_H +#include <utility> #include <stdlib.h> #include <string.h> #include <string> @@ -25,6 +26,7 @@ class GrowBuf { if (this!=&other) { + free(m_str); m_len = other.m_len; m_pos = other.m_pos; m_str = (char*)malloc(m_len); @@ -33,16 +35,18 @@ class GrowBuf return *this; } GrowBuf(GrowBuf &&other) + : m_str(std::exchange(other.m_str,(char*)0)) + , m_pos(std::exchange(other.m_pos,0)) + , m_len(std::exchange(other.m_len,0)) { - m_len = std::move(other.m_len); - m_pos = std::move(other.m_pos); - m_str = std::move(other.m_str); } GrowBuf &operator=(GrowBuf &&other) { - m_len = std::move(other.m_len); - m_pos = std::move(other.m_pos); - m_str = std::move(other.m_str); + if (this==&other) + return *this; + m_len = std::exchange(other.m_len,0); + m_pos = std::exchange(other.m_pos,0); + m_str = std::exchange(other.m_str,(char*)0); return *this; } void reserve(uint size) { if (m_len<size) { m_len = size; m_str = (char*)realloc(m_str,m_len); } } diff --git a/src/htmldocvisitor.cpp b/src/htmldocvisitor.cpp index 4a70939..d3f5c95 100644 --- a/src/htmldocvisitor.cpp +++ b/src/htmldocvisitor.cpp @@ -141,7 +141,9 @@ static bool mustBeOutsideParagraph(const DocNode *n) case DocNode::Kind_Verbatim: { DocVerbatim *dv = (DocVerbatim*)n; - return dv->type()!=DocVerbatim::HtmlOnly || dv->isBlock(); + DocVerbatim::Type t = dv->type(); + if (t == DocVerbatim::JavaDocCode || t == DocVerbatim::JavaDocLiteral) return FALSE; + return t!=DocVerbatim::HtmlOnly || dv->isBlock(); } case DocNode::Kind_StyleChange: return ((DocStyleChange*)n)->style()==DocStyleChange::Preformatted || @@ -252,6 +254,15 @@ static QCString htmlAttribsToString(const HtmlAttribList &attribs, QCString *pAl result+="=\""+convertToXML(att.value)+"\""; } } + else if (att.name=="open") + { + // The open attribute is a boolean attribute. + // Specifies that the details should be visible (open) to the user + // As it is a boolean attribute the initialisation value is of no interest + result+=" "; + result+=att.name; + result+="=\"true\""; + } else if (att.name=="nowrap") // In XHTML, attribute minimization is forbidden, and the nowrap attribute must be defined as <td nowrap="nowrap">. { result+=" "; @@ -266,8 +277,7 @@ static QCString htmlAttribsToString(const HtmlAttribList &attribs, QCString *pAl HtmlDocVisitor::HtmlDocVisitor(TextStream &t,CodeOutputInterface &ci, const Definition *ctx) - : DocVisitor(DocVisitor_Html), m_t(t), m_ci(ci), m_insidePre(FALSE), - m_hide(FALSE), m_ctx(ctx) + : DocVisitor(DocVisitor_Html), m_t(t), m_ci(ci), m_ctx(ctx) { if (ctx) m_langExt=ctx->getDefFileExtension(); } @@ -308,14 +318,22 @@ void HtmlDocVisitor::visit(DocWhiteSpace *w) void HtmlDocVisitor::visit(DocSymbol *s) { if (m_hide) return; - const char *res = HtmlEntityMapper::instance()->html(s->symbol()); - if (res) + if (m_insideTitle && + (s->symbol()==DocSymbol::Sym_Quot || s->symbol()==DocSymbol::Sym_quot)) // escape "'s inside title="..." { - m_t << res; + m_t << """; } else { - err("HTML: non supported HTML-entity found: %s\n",HtmlEntityMapper::instance()->html(s->symbol(),TRUE)); + const char *res = HtmlEntityMapper::instance()->html(s->symbol()); + if (res) + { + m_t << res; + } + else + { + err("HTML: non supported HTML-entity found: %s\n",HtmlEntityMapper::instance()->html(s->symbol(),TRUE)); + } } } @@ -335,16 +353,30 @@ void HtmlDocVisitor::visit(DocEmoji *s) void HtmlDocVisitor::writeObfuscatedMailAddress(const QCString &url) { - m_t << "<a href=\"#\" onclick=\"location.href='mai'+'lto:'"; - uint i; - int size=3; - for (i=0;i<url.length();) + if (!Config_getBool(OBFUSCATE_EMAILS)) + { + m_t << "<a href=\"mailto:" << url << "\">"; + } + else { - m_t << "+'" << url.mid(i,size) << "'"; - i+=size; - if (size==3) size=2; else size=3; + m_t << "<a href=\"#\" onclick=\"location.href='mai'+'lto:'"; + if (!url.isEmpty()) + { + const char *p = url.data(); + uint size=3; + while (*p) + { + m_t << "+'"; + for (uint j=0;j<size && *p;j++) + { + p = writeUTF8Char(m_t,p); + } + m_t << "'"; + if (size==3) size=2; else size=3; + } + } + m_t << "; return false;\">"; } - m_t << "; return false;\">"; } void HtmlDocVisitor::visit(DocURL *u) @@ -353,14 +385,26 @@ void HtmlDocVisitor::visit(DocURL *u) if (u->isEmail()) // mail address { QCString url = u->url(); + // obfuscate the mail address link writeObfuscatedMailAddress(url); - uint size=5,i; - for (i=0;i<url.length();) + if (!Config_getBool(OBFUSCATE_EMAILS)) + { + m_t << url; + } + else { - filter(url.mid(i,size)); - if (i<url.length()-size) m_t << "<span style=\"display: none;\">.nosp@m.</span>"; - i+=size; - if (size==5) size=4; else size=5; + const char *p = url.data(); + // also obfuscate the address as shown on the web page + uint size=5; + while (*p) + { + for (uint j=0;j<size && *p;j++) + { + p = writeUTF8Char(m_t,p); + } + if (*p) m_t << "<span class=\"obfuscator\">.nosp@m.</span>"; + if (size==5) size=4; else size=5; + } } m_t << "</a>"; } @@ -437,6 +481,9 @@ void HtmlDocVisitor::visit(DocStyleChange *s) case DocStyleChange::Small: if (s->enable()) m_t << "<small" << htmlAttribsToString(s->attribs()) << ">"; else m_t << "</small>"; break; + case DocStyleChange::Cite: + if (s->enable()) m_t << "<cite" << htmlAttribsToString(s->attribs()) << ">"; else m_t << "</cite>"; + break; case DocStyleChange::Preformatted: if (s->enable()) { @@ -466,7 +513,12 @@ void HtmlDocVisitor::visit(DocStyleChange *s) case DocStyleChange::Span: if (s->enable()) m_t << "<span" << htmlAttribsToString(s->attribs()) << ">"; else m_t << "</span>"; break; - + case DocStyleChange::Details: + if (s->enable()) m_t << "<details" << htmlAttribsToString(s->attribs()) << ">\n"; else m_t << "</details>\n"; + break; + case DocStyleChange::Summary: + if (s->enable()) m_t << "<summary" << htmlAttribsToString(s->attribs()) << ">"; else m_t << "</summary>"; + break; } } @@ -532,6 +584,14 @@ void HtmlDocVisitor::visit(DocVerbatim *s) m_t << "</pre>"; forceStartParagraph(s); break; + case DocVerbatim::JavaDocLiteral: + filter(s->text(), true); + break; + case DocVerbatim::JavaDocCode: + m_t << "<code class=\"JavaDocCode\">"; + filter(s->text(), true); + m_t << "</code>"; + break; case DocVerbatim::HtmlOnly: { if (s->isBlock()) forceEndParagraph(s); @@ -874,7 +934,7 @@ void HtmlDocVisitor::visit(DocFormula *f) filterQuotedCdataAttr(f->text()); m_t << "\""; m_t << " src=\"" << f->relPath() << f->name(); - if (Config_getEnum(HTML_FORMULA_FORMAT)=="svg") + if (Config_getEnum(HTML_FORMULA_FORMAT)==HTML_FORMULA_FORMAT_t::svg) { m_t << ".svg"; } @@ -1745,6 +1805,7 @@ void HtmlDocVisitor::visitPre(DocImage *img) if (inlineImage) { m_t << " title=\""; + m_insideTitle=true; } else { @@ -1774,6 +1835,7 @@ void HtmlDocVisitor::visitPost(DocImage *img) if (inlineImage) { m_t << "\"/>"; + m_insideTitle=false; } else // end <div class="caption"> { @@ -1795,6 +1857,7 @@ void HtmlDocVisitor::visitPost(DocImage *img) void HtmlDocVisitor::visitPre(DocDotFile *df) { if (m_hide) return; + if (!Config_getBool(DOT_CLEANUP)) copyFile(df->file(),Config_getString(HTML_OUTPUT)+"/"+stripPath(df->file())); m_t << "<div class=\"dotgraph\">\n"; writeDotFile(df->file(),df->relPath(),df->context(),df->srcFile(),df->srcLine()); if (df->hasCaption()) @@ -1816,6 +1879,7 @@ void HtmlDocVisitor::visitPost(DocDotFile *df) void HtmlDocVisitor::visitPre(DocMscFile *df) { if (m_hide) return; + if (!Config_getBool(DOT_CLEANUP)) copyFile(df->file(),Config_getString(HTML_OUTPUT)+"/"+stripPath(df->file())); m_t << "<div class=\"mscgraph\">\n"; writeMscFile(df->file(),df->relPath(),df->context(),df->srcFile(),df->srcLine()); if (df->hasCaption()) @@ -1836,6 +1900,7 @@ void HtmlDocVisitor::visitPost(DocMscFile *df) void HtmlDocVisitor::visitPre(DocDiaFile *df) { if (m_hide) return; + if (!Config_getBool(DOT_CLEANUP)) copyFile(df->file(),Config_getString(HTML_OUTPUT)+"/"+stripPath(df->file())); m_t << "<div class=\"diagraph\">\n"; writeDiaFile(df->file(),df->relPath(),df->context(),df->srcFile(),df->srcLine()); if (df->hasCaption()) @@ -2148,7 +2213,7 @@ void HtmlDocVisitor::visitPost(DocParBlock *) -void HtmlDocVisitor::filter(const QCString &str) +void HtmlDocVisitor::filter(const QCString &str, const bool retainNewline) { if (str.isEmpty()) return; const char *p=str.data(); @@ -2158,6 +2223,7 @@ void HtmlDocVisitor::filter(const QCString &str) c=*p++; switch(c) { + case '\n': if(retainNewline) m_t << "<br/>"; m_t << c; break; case '<': m_t << "<"; break; case '>': m_t << ">"; break; case '&': m_t << "&"; break; diff --git a/src/htmldocvisitor.h b/src/htmldocvisitor.h index 4dc7941..46bbec7 100644 --- a/src/htmldocvisitor.h +++ b/src/htmldocvisitor.h @@ -139,7 +139,7 @@ class HtmlDocVisitor : public DocVisitor //-------------------------------------- void writeObfuscatedMailAddress(const QCString &url); - void filter(const QCString &str); + void filter(const QCString &str, const bool retainNewline = false); void filterQuotedCdataAttr(const QCString &str); void startLink(const QCString &ref,const QCString &file, const QCString &relPath,const QCString &anchor, @@ -163,8 +163,9 @@ class HtmlDocVisitor : public DocVisitor TextStream &m_t; CodeOutputInterface &m_ci; - bool m_insidePre; - bool m_hide; + bool m_insidePre = false; + bool m_hide = false; + bool m_insideTitle = false; const Definition *m_ctx; QCString m_langExt; }; diff --git a/src/htmlgen.cpp b/src/htmlgen.cpp index c9c8b93..bd7e6a4 100644 --- a/src/htmlgen.cpp +++ b/src/htmlgen.cpp @@ -332,7 +332,7 @@ static QCString substituteHtmlKeywords(const QCString &str, bool searchEngine = Config_getBool(SEARCHENGINE); bool serverBasedSearch = Config_getBool(SERVER_BASED_SEARCH); bool mathJax = Config_getBool(USE_MATHJAX); - QCString mathJaxFormat = Config_getEnum(MATHJAX_FORMAT); + QCString mathJaxFormat = Config_getEnumAsString(MATHJAX_FORMAT); bool disableIndex = Config_getBool(DISABLE_INDEX); bool hasProjectName = !projectName.isEmpty(); bool hasProjectNumber = !Config_getString(PROJECT_NUMBER).isEmpty(); @@ -440,93 +440,97 @@ static QCString substituteHtmlKeywords(const QCString &str, if (mathJax) { - QCString mathJaxVersion = Config_getEnum(MATHJAX_VERSION); + auto mathJaxVersion = Config_getEnum(MATHJAX_VERSION); QCString path = Config_getString(MATHJAX_RELPATH); if (path.isEmpty() || path.left(2)=="..") // relative path { path.prepend(relPath); } - if (mathJaxVersion == "MathJax_3") + switch (mathJaxVersion) { - mathJaxJs += "<script src=\"https://polyfill.io/v3/polyfill.min.js?features=es6\"></script>\n" - "<script type=\"text/javascript\">\n" - "window.MathJax = {\n" - " options: {\n" - " ignoreHtmlClass: 'tex2jax_ignore',\n" - " processHtmlClass: 'tex2jax_process'\n" - " }"; - const StringVector &mathJaxExtensions = Config_getList(MATHJAX_EXTENSIONS); - if (!mathJaxExtensions.empty() || !g_latex_macro.isEmpty()) - { - mathJaxJs+= ",\n" - " tex: {\n" - " macros: {"; - if (!g_latex_macro.isEmpty()) - { - mathJaxJs += g_latex_macro+" "; - } - mathJaxJs+="},\n" - " packages: ['base','configmacros'"; - if (!g_latex_macro.isEmpty()) + case MATHJAX_VERSION_t::MathJax_3: { - mathJaxJs+= ",'newcommand'"; + mathJaxJs += "<script src=\"https://polyfill.io/v3/polyfill.min.js?features=es6\"></script>\n" + "<script type=\"text/javascript\">\n" + "window.MathJax = {\n" + " options: {\n" + " ignoreHtmlClass: 'tex2jax_ignore',\n" + " processHtmlClass: 'tex2jax_process'\n" + " }"; + const StringVector &mathJaxExtensions = Config_getList(MATHJAX_EXTENSIONS); + if (!mathJaxExtensions.empty() || !g_latex_macro.isEmpty()) + { + mathJaxJs+= ",\n" + " tex: {\n" + " macros: {"; + if (!g_latex_macro.isEmpty()) + { + mathJaxJs += g_latex_macro+" "; + } + mathJaxJs+="},\n" + " packages: ['base','configmacros'"; + if (!g_latex_macro.isEmpty()) + { + mathJaxJs+= ",'newcommand'"; + } + for (const auto &s : mathJaxExtensions) + { + mathJaxJs+= ",'"+QCString(s.c_str())+"'"; + } + mathJaxJs += "]\n" + " }\n"; + } + else + { + mathJaxJs += "\n"; + } + mathJaxJs += "};\n"; + // MATHJAX_CODEFILE + if (!g_mathjax_code.isEmpty()) + { + mathJaxJs += g_mathjax_code; + mathJaxJs += "\n"; + } + mathJaxJs += "</script>\n"; + mathJaxJs += "<script type=\"text/javascript\" id=\"MathJax-script\" async=\"async\" src=\"" + + path + "es5/tex-" + mathJaxFormat.lower() + ".js\">"; + mathJaxJs+="</script>\n"; } - for (const auto &s : mathJaxExtensions) + break; + case MATHJAX_VERSION_t::MathJax_2: { - mathJaxJs+= ",'"+QCString(s.c_str())+"'"; + mathJaxJs = "<script type=\"text/x-mathjax-config\">\n" + "MathJax.Hub.Config({\n" + " extensions: [\"tex2jax.js\""; + const StringVector &mathJaxExtensions = Config_getList(MATHJAX_EXTENSIONS); + for (const auto &s : mathJaxExtensions) + { + mathJaxJs+= ", \""+QCString(s.c_str())+".js\""; + } + if (mathJaxFormat.isEmpty()) + { + mathJaxFormat = "HTML-CSS"; + } + mathJaxJs += "],\n" + " jax: [\"input/TeX\",\"output/"+mathJaxFormat+"\"],\n"; + if (!g_latex_macro.isEmpty()) + { + mathJaxJs += " TeX: { Macros: {\n"; + mathJaxJs += g_latex_macro; + mathJaxJs += "\n" + " } }\n"; + } + mathJaxJs += "});\n"; + if (!g_mathjax_code.isEmpty()) + { + mathJaxJs += g_mathjax_code; + mathJaxJs += "\n"; + } + mathJaxJs += "</script>\n"; + mathJaxJs += "<script type=\"text/javascript\" async=\"async\" src=\"" + path + "MathJax.js\"></script>\n"; } - mathJaxJs += "]\n" - " }\n"; - } - else - { - mathJaxJs += "\n"; - } - mathJaxJs += "};\n"; - // MATHJAX_CODEFILE - if (!g_mathjax_code.isEmpty()) - { - mathJaxJs += g_mathjax_code; - mathJaxJs += "\n"; - } - mathJaxJs += "</script>\n"; - - mathJaxJs += "<script type=\"text/javascript\" id=\"MathJax-script\" async=\"async\" src=\"" + - path + "es5/tex-" + mathJaxFormat.lower() + ".js\">"; - mathJaxJs+="</script>\n"; - } - else // MathJax v2 - { - mathJaxJs = "<script type=\"text/x-mathjax-config\">\n" - "MathJax.Hub.Config({\n" - " extensions: [\"tex2jax.js\""; - const StringVector &mathJaxExtensions = Config_getList(MATHJAX_EXTENSIONS); - for (const auto &s : mathJaxExtensions) - { - mathJaxJs+= ", \""+QCString(s.c_str())+".js\""; - } - if (mathJaxFormat.isEmpty()) - { - mathJaxFormat = "HTML-CSS"; - } - mathJaxJs += "],\n" - " jax: [\"input/TeX\",\"output/"+mathJaxFormat+"\"],\n"; - if (!g_latex_macro.isEmpty()) - { - mathJaxJs += " TeX: { Macros: {\n"; - mathJaxJs += g_latex_macro; - mathJaxJs += "\n" - " } }\n"; - } - mathJaxJs += "});\n"; - if (!g_mathjax_code.isEmpty()) - { - mathJaxJs += g_mathjax_code; - mathJaxJs += "\n"; - } - mathJaxJs += "</script>\n"; - mathJaxJs += "<script type=\"text/javascript\" async=\"async\" src=\"" + path + "MathJax.js\"></script>\n"; + break; } } @@ -692,7 +696,7 @@ void HtmlCodeGenerator::docify(const QCString &str) } void HtmlCodeGenerator::writeLineNumber(const QCString &ref,const QCString &filename, - const QCString &anchor,int l) + const QCString &anchor,int l,bool writeLineAnchor) { const int maxLineNrStr = 10; char lineNumber[maxLineNrStr]; @@ -706,7 +710,8 @@ void HtmlCodeGenerator::writeLineNumber(const QCString &ref,const QCString &file m_lineOpen = TRUE; } - m_t << "<a id=\"" << lineAnchor << "\" name=\"" << lineAnchor << "\"></a><span class=\"lineno\">"; + if (writeLineAnchor) m_t << "<a id=\"" << lineAnchor << "\" name=\"" << lineAnchor << "\"></a>"; + m_t << "<span class=\"lineno\">"; if (!filename.isEmpty()) { _writeCodeLink("line",ref,filename,anchor,lineNumber,QCString()); @@ -1019,6 +1024,7 @@ void HtmlGenerator::writeTabData() mgr.copyResource("nav_f.lum",dname); mgr.copyResource("bc_s.luma",dname); mgr.copyResource("doxygen.svg",dname); + Doxygen::indexList->addImageFile("doxygen.svg"); mgr.copyResource("closed.luma",dname); mgr.copyResource("open.luma",dname); mgr.copyResource("bdwn.luma",dname); @@ -1032,6 +1038,7 @@ void HtmlGenerator::writeTabData() // img.save(dname+"/nav_g.png"); //} mgr.copyResource("nav_g.png",dname); + Doxygen::indexList->addImageFile("nav_g.png"); } void HtmlGenerator::writeSearchData(const QCString &dname) diff --git a/src/htmlgen.h b/src/htmlgen.h index a4eefed..d5f7904 100644 --- a/src/htmlgen.h +++ b/src/htmlgen.h @@ -38,7 +38,7 @@ class HtmlCodeGenerator : public CodeOutputInterface const SourceLinkInfo &defInfo, const SourceLinkInfo &declInfo ); - void writeLineNumber(const QCString &,const QCString &,const QCString &,int); + void writeLineNumber(const QCString &,const QCString &,const QCString &,int, bool); void startCodeLine(bool); void endCodeLine(); void startFontClass(const QCString &s); @@ -95,8 +95,8 @@ class HtmlGenerator : public OutputGenerator const QCString &anchor,const QCString &name, const QCString &tooltip) { m_codeGen.writeCodeLink(type,ref,file,anchor,name,tooltip); } - void writeLineNumber(const QCString &ref,const QCString &file,const QCString &anchor,int lineNumber) - { m_codeGen.writeLineNumber(ref,file,anchor,lineNumber); } + void writeLineNumber(const QCString &ref,const QCString &file,const QCString &anchor,int lineNumber, bool writeLineAnchor) + { m_codeGen.writeLineNumber(ref,file,anchor,lineNumber,writeLineAnchor); } void writeTooltip(const QCString &id, const DocLinkInfo &docInfo, const QCString &decl, const QCString &desc, const SourceLinkInfo &defInfo, const SourceLinkInfo &declInfo ) diff --git a/src/htmlhelp.cpp b/src/htmlhelp.cpp index c86816b..16bd5c0 100644 --- a/src/htmlhelp.cpp +++ b/src/htmlhelp.cpp @@ -174,7 +174,7 @@ void HtmlHelpIndex::addItem(const QCString &level1,const QCString &level2, static QCString field2URL(const IndexField *f,bool checkReversed) { - QCString result = f->url + Doxygen::htmlFileExtension; + QCString result = addHtmlExtensionIfMissing(f->url); if (!f->anchor.isEmpty() && (!checkReversed || f->reversed)) { // HTML Help needs colons in link anchors to be escaped in the .hhk file. @@ -555,7 +555,7 @@ void HtmlHelp::Private::createProjectFile() } for (auto &s : imageFiles) { - t << FileInfo(s).fileName() << "\n"; + t << s.c_str() << "\n"; } t.close(); } @@ -636,6 +636,7 @@ void HtmlHelp::addContentsItem(bool isDir, bool /* addToNavIndex */, const Definition * /* def */) { + static bool binaryTOC = Config_getBool(BINARY_TOC); // If we're using a binary toc then folders cannot have links. // Tried this and I didn't see any problems, when not using // the resetting of file and anchor the TOC works better @@ -657,14 +658,18 @@ void HtmlHelp::addContentsItem(bool isDir, if (file[0]=='^') p->cts << "URL"; else p->cts << "Local"; p->cts << "\" value=\""; p->cts << &file[1]; + p->cts << "\">"; } else { - p->cts << "<param name=\"Local\" value=\""; - p->cts << file << Doxygen::htmlFileExtension; - if (!anchor.isEmpty()) p->cts << "#" << anchor; + if (!(binaryTOC && isDir)) + { + p->cts << "<param name=\"Local\" value=\""; + p->cts << addHtmlExtensionIfMissing(file); + if (!anchor.isEmpty()) p->cts << "#" << anchor; + p->cts << "\">"; + } } - p->cts << "\">"; } p->cts << "<param name=\"ImageNumber\" value=\""; if (isDir) // added - KPW diff --git a/src/index.cpp b/src/index.cpp index 5db1dd9..8e4fb8a 100644 --- a/src/index.cpp +++ b/src/index.cpp @@ -721,16 +721,12 @@ static void writeDirHierarchy(OutputList &ol, FTVHelp* ftv,bool addToIndex) ol.pushGeneratorState(); ol.disable(OutputGenerator::Html); } - bool fullPathNames = Config_getBool(FULL_PATH_NAMES); startIndexHierarchy(ol,0); - if (fullPathNames) + for (const auto &dd : *Doxygen::dirLinkedMap) { - for (const auto &dd : *Doxygen::dirLinkedMap) + if (dd->getOuterScope()==Doxygen::globalScope) { - if (dd->getOuterScope()==Doxygen::globalScope) - { - writeDirTreeNode(ol,dd.get(),0,ftv,addToIndex); - } + writeDirTreeNode(ol,dd.get(),0,ftv,addToIndex); } } if (ftv) @@ -739,7 +735,7 @@ static void writeDirHierarchy(OutputList &ol, FTVHelp* ftv,bool addToIndex) { for (const auto &fd : *fn) { - if (!fullPathNames || fd->getDirDef()==0) // top level file + if (fd->getDirDef()==0) // top level file { bool src; bool doc = fileVisibleInIndex(fd.get(),src); @@ -4145,12 +4141,12 @@ static void writeConceptRootList(FTVHelp *ftv,bool addToIndex) //printf("*** adding %s hasSubPages=%d hasSections=%d\n",qPrint(pageTitle),hasSubPages,hasSections); ftv->addContentsItem( false,cd->localName(),cd->getReference(),cd->getOutputFileBase(), - QCString(),false,true,cd.get()); + QCString(),false,cd->partOfGroups().empty(),cd.get()); if (addToIndex) { Doxygen::indexList->addContentsItem( false,cd->localName(),cd->getReference(),cd->getOutputFileBase(), - QCString(),false,true); + QCString(),false,cd->partOfGroups().empty(),cd.get()); } } } @@ -4932,7 +4928,7 @@ static void writeIndexHierarchyEntries(OutputList &ol,const LayoutNavEntryList & QCString url = correctURL(lne->url(),"!"); // add ! to relative URL if (!url.isEmpty()) { - if (url=="![none]") + if (url=="!") // result of a "[none]" url { Doxygen::indexList->addContentsItem(TRUE,lne->title(),QCString(),QCString(),QCString(),FALSE,FALSE); } diff --git a/src/language.cpp b/src/language.cpp index c7cf204..20259c1 100644 --- a/src/language.cpp +++ b/src/language.cpp @@ -153,271 +153,140 @@ #endif #endif // !ENGLISH_ONLY -#define L_EQUAL(a) !qstricmp(langName.data(),a) - Translator *theTranslator=0; -bool setTranslator(const QCString &langName) +void setTranslator(OUTPUT_LANGUAGE_t langName) { - if (L_EQUAL("english")) + switch (langName) { - theTranslator=new TranslatorEnglish; - } + case OUTPUT_LANGUAGE_t::English: theTranslator = new TranslatorEnglish; break; #if !defined(ENGLISH_ONLY) -#ifdef LANG_NL - else if (L_EQUAL("dutch")) - { - theTranslator=new TranslatorDutch; - } +#ifdef LANG_ZA + case OUTPUT_LANGUAGE_t::Afrikaans: theTranslator = new TranslatorAfrikaans; break; +#endif +#ifdef LANG_AR + case OUTPUT_LANGUAGE_t::Arabic: theTranslator = new TranslatorArabic; break; #endif #ifdef LANG_AM - else if (L_EQUAL("armenian")) - { - theTranslator=new TranslatorArmenian; - } + case OUTPUT_LANGUAGE_t::Armenian: theTranslator = new TranslatorArmenian; break; #endif -#ifdef LANG_SV - else if (L_EQUAL("swedish")) - { - theTranslator=new TranslatorSwedish; - } +#ifdef LANG_BR + case OUTPUT_LANGUAGE_t::Brazilian: theTranslator = new TranslatorBrazilian; break; #endif -#ifdef LANG_CZ - else if (L_EQUAL("czech")) - { - theTranslator=new TranslatorCzech; - } +#ifdef LANG_CA + case OUTPUT_LANGUAGE_t::Catalan: theTranslator = new TranslatorCatalan; break; #endif -#ifdef LANG_FR - else if (L_EQUAL("french")) - { - theTranslator=new TranslatorFrench; - } +#ifdef LANG_CN + case OUTPUT_LANGUAGE_t::Chinese: theTranslator = new TranslatorChinese; break; #endif -#ifdef LANG_ID - else if (L_EQUAL("indonesian")) - { - theTranslator=new TranslatorIndonesian; - } +#ifdef LANG_TW + case OUTPUT_LANGUAGE_t::Chinese_Traditional: theTranslator = new TranslatorChinesetraditional; break; #endif -#ifdef LANG_IT - else if (L_EQUAL("italian")) - { - theTranslator=new TranslatorItalian; - } +#ifdef LANG_HR + case OUTPUT_LANGUAGE_t::Croatian: theTranslator = new TranslatorCroatian; break; #endif -#ifdef LANG_DE - else if (L_EQUAL("german")) - { - theTranslator=new TranslatorGerman; - } +#ifdef LANG_CZ + case OUTPUT_LANGUAGE_t::Czech: theTranslator = new TranslatorCzech; break; #endif -#ifdef LANG_JP - else if (L_EQUAL("japanese")) - { - theTranslator=new TranslatorJapanese; - } +#ifdef LANG_DK + case OUTPUT_LANGUAGE_t::Danish: theTranslator = new TranslatorDanish; break; #endif -#ifdef LANG_JE - else if (L_EQUAL("japanese-en")) - { - theTranslator=new TranslatorJapaneseEn; - } +#ifdef LANG_NL + case OUTPUT_LANGUAGE_t::Dutch: theTranslator = new TranslatorDutch; break; #endif -#ifdef LANG_ES - else if (L_EQUAL("spanish")) - { - theTranslator=new TranslatorSpanish; - } +#ifdef LANG_EO + case OUTPUT_LANGUAGE_t::Esperanto: theTranslator = new TranslatorEsperanto; break; #endif -#ifdef LANG_FI - else if (L_EQUAL("finnish")) - { - theTranslator=new TranslatorFinnish; - } +#ifdef LANG_FA + case OUTPUT_LANGUAGE_t::Farsi: theTranslator = new TranslatorPersian; break; #endif -#ifdef LANG_RU - else if (L_EQUAL("russian")) - { - theTranslator=new TranslatorRussian; - } +#ifdef LANG_FI + case OUTPUT_LANGUAGE_t::Finnish: theTranslator = new TranslatorFinnish; break; #endif -#ifdef LANG_HR - else if (L_EQUAL("croatian")) - { - theTranslator=new TranslatorCroatian; - } +#ifdef LANG_FR + case OUTPUT_LANGUAGE_t::French: theTranslator = new TranslatorFrench; break; #endif -#ifdef LANG_PL - else if (L_EQUAL("polish")) - { - theTranslator=new TranslatorPolish; - } +#ifdef LANG_DE + case OUTPUT_LANGUAGE_t::German: theTranslator = new TranslatorGerman; break; #endif -#ifdef LANG_PT - else if (L_EQUAL("portuguese")) - { - theTranslator=new TranslatorPortuguese; - } +#ifdef LANG_GR + case OUTPUT_LANGUAGE_t::Greek: theTranslator = new TranslatorGreek; break; #endif #ifdef LANG_HU - else if (L_EQUAL("hungarian")) - { - theTranslator=new TranslatorHungarian; - } + case OUTPUT_LANGUAGE_t::Hungarian: theTranslator = new TranslatorHungarian; break; +#endif +#ifdef LANG_ID + case OUTPUT_LANGUAGE_t::Indonesian: theTranslator = new TranslatorIndonesian; break; +#endif +#ifdef LANG_IT + case OUTPUT_LANGUAGE_t::Italian: theTranslator = new TranslatorItalian; break; +#endif +#ifdef LANG_JP + case OUTPUT_LANGUAGE_t::Japanese: theTranslator = new TranslatorJapanese; break; +#endif +#ifdef LANG_JE + case OUTPUT_LANGUAGE_t::Japanese_en: theTranslator = new TranslatorJapaneseEn; break; #endif #ifdef LANG_KR - else if (L_EQUAL("korean")) - { - theTranslator=new TranslatorKorean; - } + case OUTPUT_LANGUAGE_t::Korean: theTranslator = new TranslatorKorean; break; #endif #ifdef LANG_KE - else if (L_EQUAL("korean-en")) - { - theTranslator=new TranslatorKoreanEn; - } + case OUTPUT_LANGUAGE_t::Korean_en: theTranslator = new TranslatorKoreanEn; break; #endif -#ifdef LANG_RO - else if (L_EQUAL("romanian")) - { - theTranslator=new TranslatorRomanian; - } -#endif -#ifdef LANG_SI - else if (L_EQUAL("slovene")) - { - theTranslator=new TranslatorSlovene; - } +#ifdef LANG_LV + case OUTPUT_LANGUAGE_t::Latvian: theTranslator = new TranslatorLatvian; break; #endif -#ifdef LANG_CN - else if (L_EQUAL("chinese")) - { - theTranslator=new TranslatorChinese; - } +#ifdef LANG_LT + case OUTPUT_LANGUAGE_t::Lithuanian: theTranslator = new TranslatorLithuanian; break; #endif -#ifdef LANG_TW - else if (L_EQUAL("chinese-traditional")) - { - theTranslator=new TranslatorChinesetraditional; - } +#ifdef LANG_MK + case OUTPUT_LANGUAGE_t::Macedonian: theTranslator = new TranslatorMacedonian; break; #endif #ifdef LANG_NO - else if (L_EQUAL("norwegian")) - { - theTranslator=new TranslatorNorwegian; - } + case OUTPUT_LANGUAGE_t::Norwegian: theTranslator = new TranslatorNorwegian; break; #endif -#ifdef LANG_BR - else if (L_EQUAL("brazilian")) - { - theTranslator=new TranslatorBrazilian; - } +#ifdef LANG_FA + case OUTPUT_LANGUAGE_t::Persian: theTranslator = new TranslatorPersian; break; #endif -#ifdef LANG_DK - else if (L_EQUAL("danish")) - { - theTranslator=new TranslatorDanish; - } +#ifdef LANG_PL + case OUTPUT_LANGUAGE_t::Polish: theTranslator = new TranslatorPolish; break; #endif -#ifdef LANG_SK - else if (L_EQUAL("slovak")) - { - theTranslator=new TranslatorSlovak; - } +#ifdef LANG_PT + case OUTPUT_LANGUAGE_t::Portuguese: theTranslator = new TranslatorPortuguese; break; #endif -#ifdef LANG_UA - else if (L_EQUAL("ukrainian")) - { - theTranslator=new TranslatorUkrainian; - } +#ifdef LANG_RO + case OUTPUT_LANGUAGE_t::Romanian: theTranslator = new TranslatorRomanian; break; #endif -#ifdef LANG_GR - else if (L_EQUAL("greek")) - { - theTranslator=new TranslatorGreek; - } +#ifdef LANG_RU + case OUTPUT_LANGUAGE_t::Russian: theTranslator = new TranslatorRussian; break; #endif #ifdef LANG_SR - else if (L_EQUAL("serbian")) - { - theTranslator=new TranslatorSerbian; - } + case OUTPUT_LANGUAGE_t::Serbian: theTranslator = new TranslatorSerbian; break; #endif #ifdef LANG_SC - else if (L_EQUAL("serbian-cyrillic") || L_EQUAL("serbiancyr")) /* serbiancyr for consistency with older versions */ - { - theTranslator=new TranslatorSerbianCyrillic; - } -#endif -#ifdef LANG_CA - else if (L_EQUAL("catalan")) - { - theTranslator=new TranslatorCatalan; - } + case OUTPUT_LANGUAGE_t::Serbian_Cyrillic: theTranslator = new TranslatorSerbianCyrillic; break; #endif -#ifdef LANG_LT - else if (L_EQUAL("lithuanian")) - { - theTranslator=new TranslatorLithuanian; - } +#ifdef LANG_SK + case OUTPUT_LANGUAGE_t::Slovak: theTranslator = new TranslatorSlovak; break; #endif -#ifdef LANG_LV - else if (L_EQUAL("latvian")) - { - theTranslator=new TranslatorLatvian; - } +#ifdef LANG_SI + case OUTPUT_LANGUAGE_t::Slovene: theTranslator = new TranslatorSlovene; break; #endif -#ifdef LANG_ZA - else if (L_EQUAL("afrikaans")) - { - theTranslator=new TranslatorAfrikaans; - } +#ifdef LANG_ES + case OUTPUT_LANGUAGE_t::Spanish: theTranslator = new TranslatorSpanish; break; #endif -#ifdef LANG_AR - else if (L_EQUAL("arabic")) - { - theTranslator=new TranslatorArabic; - } +#ifdef LANG_SV + case OUTPUT_LANGUAGE_t::Swedish: theTranslator = new TranslatorSwedish; break; #endif -#ifdef LANG_FA - else if (L_EQUAL("persian") || L_EQUAL("farsi")) - { - theTranslator=new TranslatorPersian; - } +#ifdef LANG_TR + case OUTPUT_LANGUAGE_t::Turkish: theTranslator = new TranslatorTurkish; break; #endif -#ifdef LANG_MK - else if (L_EQUAL("macedonian")) - { - theTranslator=new TranslatorMacedonian; - } +#ifdef LANG_UA + case OUTPUT_LANGUAGE_t::Ukrainian: theTranslator = new TranslatorUkrainian; break; #endif #ifdef LANG_VI - else if (L_EQUAL("vietnamese")) - { - theTranslator=new TranslatorVietnamese; - } -#endif -#ifdef LANG_TR - else if (L_EQUAL("turkish")) - { - theTranslator=new TranslatorTurkish; - } + case OUTPUT_LANGUAGE_t::Vietnamese: theTranslator = new TranslatorVietnamese; break; #endif -#ifdef LANG_EO - else if (L_EQUAL("esperanto")) - { - theTranslator=new TranslatorEsperanto; - } #endif -#endif // ENGLISH_ONLY - else // use the default language (i.e. english) - { - theTranslator=new TranslatorEnglish; - return FALSE; } - - QCString msg = theTranslator->updateNeededMessage(); - if (!msg.isEmpty()) warn_uncond("%s", qPrint(msg)); - return TRUE; } diff --git a/src/language.h b/src/language.h index 8f38bfc..ad74986 100644 --- a/src/language.h +++ b/src/language.h @@ -19,8 +19,9 @@ #define LANGUAGE_H #include "translator.h" +#include "configvalues.h" extern Translator *theTranslator; -extern bool setTranslator(const QCString &languageName); +extern void setTranslator(OUTPUT_LANGUAGE_t languageName); #endif diff --git a/src/latexdocvisitor.cpp b/src/latexdocvisitor.cpp index 7a551d3..3c5a435 100644 --- a/src/latexdocvisitor.cpp +++ b/src/latexdocvisitor.cpp @@ -38,6 +38,7 @@ #include "emoji.h" #include "plantuml.h" #include "fileinfo.h" +#include "regex.h" const int maxLevels=5; static const char *secLabels[maxLevels] = @@ -52,6 +53,26 @@ static const char *getSectionName(int level) return secLabels[std::min(maxLevels-1,l)]; } +static void insertDimension(TextStream &t, QCString dimension, const char *orientationString) +{ + // dimensions for latex images can be a percentage, in this case they need some extra + // handling as the % symbol is used for comments + static const reg::Ex re(R"((\d+)%)"); + std::string s = dimension.str(); + reg::Match match; + if (reg::search(s,match,re)) + { + bool ok; + double percent = QCString(match[1].str()).toInt(&ok); + if (ok) + { + t << percent/100.0 << "\\text" << orientationString; + return; + } + } + t << dimension; +} + static void visitPreStart(TextStream &t, bool hasCaption, QCString name, QCString width, QCString height, bool inlineImage = FALSE) { if (inlineImage) @@ -78,7 +99,8 @@ static void visitPreStart(TextStream &t, bool hasCaption, QCString name, QCStri } if (!width.isEmpty()) { - t << "width=" << width; + t << "width="; + insertDimension(t, width, "width"); } if (!width.isEmpty() && !height.isEmpty()) { @@ -86,7 +108,8 @@ static void visitPreStart(TextStream &t, bool hasCaption, QCString name, QCStri } if (!height.isEmpty()) { - t << "height=" << height; + t << "height="; + insertDimension(t, height, "height"); } if (width.isEmpty() && height.isEmpty()) { @@ -179,8 +202,8 @@ QCString LatexDocVisitor::escapeMakeIndexChars(const char *s) LatexDocVisitor::LatexDocVisitor(TextStream &t,LatexCodeGenerator &ci, const QCString &langExt,bool insideTabbing) : DocVisitor(DocVisitor_Latex), m_t(t), m_ci(ci), m_insidePre(FALSE), - m_insideItem(FALSE), m_hide(FALSE), m_hideCaption(FALSE), m_insideTabbing(insideTabbing), - m_langExt(langExt) + m_insideItem(FALSE), m_hide(FALSE), m_hideCaption(FALSE), + m_insideTabbing(insideTabbing), m_langExt(langExt) { } @@ -218,16 +241,31 @@ void LatexDocVisitor::visit(DocWhiteSpace *w) void LatexDocVisitor::visit(DocSymbol *s) { if (m_hide) return; + bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS); const char *res = HtmlEntityMapper::instance()->latex(s->symbol()); if (res) { if (((s->symbol() == DocSymbol::Sym_lt) || (s->symbol() == DocSymbol::Sym_Less))&& (!m_insidePre)) { - m_t << "\\texorpdfstring{$<$}{<}"; + if (pdfHyperlinks) + { + m_t << "\\texorpdfstring{$<$}{<}"; + } + else + { + m_t << "$<$"; + } } else if (((s->symbol() == DocSymbol::Sym_gt) || (s->symbol() == DocSymbol::Sym_Greater)) && (!m_insidePre)) { - m_t << "\\texorpdfstring{$>$}{>}"; + if (pdfHyperlinks) + { + m_t << "\\texorpdfstring{$>$}{>}"; + } + else + { + m_t << "$>$"; + } } else { @@ -321,6 +359,9 @@ void LatexDocVisitor::visit(DocStyleChange *s) case DocStyleChange::Small: if (s->enable()) m_t << "\n\\footnotesize "; else m_t << "\n\\normalsize "; break; + case DocStyleChange::Cite: + if (s->enable()) m_t << "{\\itshape "; else m_t << "}"; + break; case DocStyleChange::Preformatted: if (s->enable()) { @@ -335,6 +376,12 @@ void LatexDocVisitor::visit(DocStyleChange *s) break; case DocStyleChange::Div: /* HTML only */ break; case DocStyleChange::Span: /* HTML only */ break; + case DocStyleChange::Details: /* emulation of the <details> tag */ + if (!s->enable()) m_t << "\n\n"; + break; + case DocStyleChange::Summary: /* emulation of the <summary> tag inside a <details> tag */ + if (s->enable()) m_t << "{\\bfseries{"; else m_t << "}}"; + break; } } @@ -357,6 +404,14 @@ void LatexDocVisitor::visit(DocVerbatim *s) m_ci.endCodeFragment("DoxyCode"); } break; + case DocVerbatim::JavaDocLiteral: + filter(s->text(), true); + break; + case DocVerbatim::JavaDocCode: + m_t << "{\\ttfamily "; + filter(s->text(), true); + m_t << "}"; + break; case DocVerbatim::Verbatim: m_t << "\\begin{DoxyVerb}"; m_t << s->text(); @@ -665,12 +720,15 @@ void LatexDocVisitor::visit(DocCite *cite) void LatexDocVisitor::visitPre(DocAutoList *l) { if (m_hide) return; + if (m_indentLevel>=maxIndentLevels-1) return; if (l->isEnumList()) { m_t << "\n\\begin{DoxyEnumerate}"; + m_listItemInfo[indentLevel()].isEnum = true; } else { + m_listItemInfo[indentLevel()].isEnum = false; m_t << "\n\\begin{DoxyItemize}"; } } @@ -678,6 +736,7 @@ void LatexDocVisitor::visitPre(DocAutoList *l) void LatexDocVisitor::visitPost(DocAutoList *l) { if (m_hide) return; + if (m_indentLevel>=maxIndentLevels-1) return; if (l->isEnumList()) { m_t << "\n\\end{DoxyEnumerate}"; @@ -692,10 +751,12 @@ void LatexDocVisitor::visitPre(DocAutoListItem *) { if (m_hide) return; m_t << "\n\\item "; + incIndentLevel(); } void LatexDocVisitor::visitPost(DocAutoListItem *) { + decIndentLevel(); } void LatexDocVisitor::visitPre(DocPara *) @@ -712,12 +773,14 @@ void LatexDocVisitor::visitPost(DocPara *p) ) m_t << "\n\n"; } -void LatexDocVisitor::visitPre(DocRoot *) +void LatexDocVisitor::visitPre(DocRoot *r) { + //if (r->indent()) incIndentLevel(); } -void LatexDocVisitor::visitPost(DocRoot *) +void LatexDocVisitor::visitPost(DocRoot *r) { + //if (r->indent()) decIndentLevel(); } void LatexDocVisitor::visitPre(DocSimpleSect *s) @@ -797,6 +860,7 @@ void LatexDocVisitor::visitPre(DocSimpleSect *s) // special case 1: user defined title if (s->type()!=DocSimpleSect::User && s->type()!=DocSimpleSect::Rcs) { + incIndentLevel(); m_t << "}\n"; } else @@ -864,6 +928,7 @@ void LatexDocVisitor::visitPost(DocSimpleSect *s) default: break; } + decIndentLevel(); } void LatexDocVisitor::visitPre(DocTitle *) @@ -881,6 +946,7 @@ void LatexDocVisitor::visitPre(DocSimpleList *) { if (m_hide) return; m_t << "\\begin{DoxyItemize}\n"; + m_listItemInfo[indentLevel()].isEnum = false; } void LatexDocVisitor::visitPost(DocSimpleList *) @@ -893,10 +959,12 @@ void LatexDocVisitor::visitPre(DocSimpleListItem *) { if (m_hide) return; m_t << "\\item "; + incIndentLevel(); } void LatexDocVisitor::visitPost(DocSimpleListItem *) { + decIndentLevel(); } void LatexDocVisitor::visitPre(DocSection *s) @@ -918,6 +986,8 @@ void LatexDocVisitor::visitPost(DocSection *) void LatexDocVisitor::visitPre(DocHtmlList *s) { if (m_hide) return; + if (m_indentLevel>=maxIndentLevels-1) return; + m_listItemInfo[indentLevel()].isEnum = s->type()==DocHtmlList::Ordered; if (s->type()==DocHtmlList::Ordered) { bool first = true; @@ -960,7 +1030,9 @@ void LatexDocVisitor::visitPre(DocHtmlList *s) else if (opt.name=="start") { m_t << (first ? "[": ","); - m_t << "start=" << opt.value; + bool ok; + int val = opt.value.toInt(&ok); + if (ok) m_t << "start=" << val; first = false; } } @@ -973,20 +1045,38 @@ void LatexDocVisitor::visitPre(DocHtmlList *s) void LatexDocVisitor::visitPost(DocHtmlList *s) { if (m_hide) return; + if (m_indentLevel>=maxIndentLevels-1) return; if (s->type()==DocHtmlList::Ordered) m_t << "\n\\end{DoxyEnumerate}"; else m_t << "\n\\end{DoxyItemize}"; } -void LatexDocVisitor::visitPre(DocHtmlListItem *) +void LatexDocVisitor::visitPre(DocHtmlListItem *l) { if (m_hide) return; + if (m_listItemInfo[indentLevel()].isEnum) + { + for (const auto &opt : l->attribs()) + { + if (opt.name=="value") + { + bool ok; + int val = opt.value.toInt(&ok); + if (ok) + { + m_t << "\n\\setcounter{DoxyEnumerate" << integerToRoman(indentLevel()+1,false) << "}{" << (val - 1) << "}"; + } + } + } + } m_t << "\n\\item "; + incIndentLevel(); } void LatexDocVisitor::visitPost(DocHtmlListItem *) { + decIndentLevel(); } //void LatexDocVisitor::visitPre(DocHtmlPre *) @@ -1077,10 +1167,12 @@ void LatexDocVisitor::visitPost(DocHtmlDescTitle *) void LatexDocVisitor::visitPre(DocHtmlDescData *) { + incIndentLevel(); } void LatexDocVisitor::visitPost(DocHtmlDescData *) { + decIndentLevel(); } static bool tableIsNested(const DocNode *n) @@ -1464,6 +1556,7 @@ void LatexDocVisitor::visitPost(DocImage *img) void LatexDocVisitor::visitPre(DocDotFile *df) { if (m_hide) return; + if (!Config_getBool(DOT_CLEANUP)) copyFile(df->file(),Config_getString(LATEX_OUTPUT)+"/"+stripPath(df->file())); startDotFile(df->file(),df->width(),df->height(),df->hasCaption(),df->srcFile(),df->srcLine()); } @@ -1475,6 +1568,7 @@ void LatexDocVisitor::visitPost(DocDotFile *df) void LatexDocVisitor::visitPre(DocMscFile *df) { if (m_hide) return; + if (!Config_getBool(DOT_CLEANUP)) copyFile(df->file(),Config_getString(LATEX_OUTPUT)+"/"+stripPath(df->file())); startMscFile(df->file(),df->width(),df->height(),df->hasCaption(),df->srcFile(),df->srcLine()); } @@ -1487,6 +1581,7 @@ void LatexDocVisitor::visitPost(DocMscFile *df) void LatexDocVisitor::visitPre(DocDiaFile *df) { if (m_hide) return; + if (!Config_getBool(DOT_CLEANUP)) copyFile(df->file(),Config_getString(LATEX_OUTPUT)+"/"+stripPath(df->file())); startDiaFile(df->file(),df->width(),df->height(),df->hasCaption(),df->srcFile(),df->srcLine()); } @@ -1577,11 +1672,13 @@ void LatexDocVisitor::visitPre(DocSecRefList *) m_t << "\\footnotesize\n"; m_t << "\\begin{multicols}{2}\n"; m_t << "\\begin{DoxyCompactList}\n"; + incIndentLevel(); } void LatexDocVisitor::visitPost(DocSecRefList *) { if (m_hide) return; + decIndentLevel(); m_t << "\\end{DoxyCompactList}\n"; m_t << "\\end{multicols}\n"; m_t << "\\normalsize\n"; @@ -1616,6 +1713,7 @@ void LatexDocVisitor::visitPre(DocParamSect *s) break; default: ASSERT(0); + incIndentLevel(); } m_t << "}\n"; } @@ -1640,6 +1738,7 @@ void LatexDocVisitor::visitPost(DocParamSect *s) break; default: ASSERT(0); + decIndentLevel(); } } @@ -1752,6 +1851,7 @@ void LatexDocVisitor::visitPre(DocXRefItem *x) static bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS); if (m_hide) return; if (x->title().isEmpty()) return; + incIndentLevel(); m_t << "\\begin{DoxyRefDesc}{"; filter(x->title()); m_t << "}\n"; @@ -1779,6 +1879,7 @@ void LatexDocVisitor::visitPost(DocXRefItem *x) { if (m_hide) return; if (x->title().isEmpty()) return; + decIndentLevel(); m_t << "\\end{DoxyRefDesc}\n"; } @@ -1806,12 +1907,14 @@ void LatexDocVisitor::visitPre(DocHtmlBlockQuote *) { if (m_hide) return; m_t << "\\begin{quote}\n"; + incIndentLevel(); } void LatexDocVisitor::visitPost(DocHtmlBlockQuote *) { if (m_hide) return; m_t << "\\end{quote}\n"; + decIndentLevel(); } void LatexDocVisitor::visitPre(DocVhdlFlow *) @@ -1834,14 +1937,15 @@ void LatexDocVisitor::visitPost(DocParBlock *) if (m_hide) return; } -void LatexDocVisitor::filter(const QCString &str) +void LatexDocVisitor::filter(const QCString &str, const bool retainNewLine) { filterLatexString(m_t,str, m_insideTabbing, m_insidePre, m_insideItem, m_ci.usedTableLevel()>0, // insideTable - false // keepSpaces + false, // keepSpaces + retainNewLine ); } @@ -2044,3 +2148,25 @@ void LatexDocVisitor::writePlantUMLFile(const QCString &baseName, DocVerbatim *s visitPostEnd(m_t, s->hasCaption()); } +int LatexDocVisitor::indentLevel() const +{ + return std::min(m_indentLevel,maxIndentLevels-1); +} + +void LatexDocVisitor::incIndentLevel() +{ + m_indentLevel++; + if (m_indentLevel>=maxIndentLevels) + { + err("Maximum indent level (%d) exceeded while generating LaTeX output!\n",maxIndentLevels-1); + } +} + +void LatexDocVisitor::decIndentLevel() +{ + if (m_indentLevel>0) + { + m_indentLevel--; + } +} + diff --git a/src/latexdocvisitor.h b/src/latexdocvisitor.h index 745c7a8..470aaf4 100644 --- a/src/latexdocvisitor.h +++ b/src/latexdocvisitor.h @@ -24,6 +24,7 @@ class LatexCodeGenerator; class TextStream; + /*! @brief Concrete visitor implementation for LaTeX output. */ class LatexDocVisitor : public DocVisitor { @@ -152,7 +153,7 @@ class LatexDocVisitor : public DocVisitor // helper functions //-------------------------------------- - void filter(const QCString &str); + void filter(const QCString &str, const bool retainNewLine = false); void startLink(const QCString &ref,const QCString &file, const QCString &anchor,bool refToTable=FALSE); void endLink(const QCString &ref,const QCString &file, @@ -176,6 +177,10 @@ class LatexDocVisitor : public DocVisitor void writeDiaFile(const QCString &fileName, DocVerbatim *s); void writePlantUMLFile(const QCString &fileName, DocVerbatim *s); + void incIndentLevel(); + void decIndentLevel(); + int indentLevel() const; + //-------------------------------------- // state variables //-------------------------------------- @@ -201,6 +206,16 @@ class LatexDocVisitor : public DocVisitor std::stack<TableState> m_tableStateStack; // needed for nested tables RowSpanList m_emptyRowSpanList; + static const int maxIndentLevels = 13; + int m_indentLevel = 0; + + struct LatexListItemInfo + { + bool isEnum = false; + }; + + LatexListItemInfo m_listItemInfo[maxIndentLevels]; + void pushTableState() { m_tableStateStack.push(TableState()); @@ -263,5 +278,4 @@ class LatexDocVisitor : public DocVisitor } }; - #endif diff --git a/src/latexgen.cpp b/src/latexgen.cpp index 60cd26e..bc01e01 100644 --- a/src/latexgen.cpp +++ b/src/latexgen.cpp @@ -1,8 +1,6 @@ /****************************************************************************** * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2021 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its * documentation under the terms of the GNU General Public License is hereby @@ -171,7 +169,7 @@ void LatexCodeGenerator::writeCodeLink(CodeSymbolType, m_col+=l; } -void LatexCodeGenerator::writeLineNumber(const QCString &ref,const QCString &fileName,const QCString &anchor,int l) +void LatexCodeGenerator::writeLineNumber(const QCString &ref,const QCString &fileName,const QCString &anchor,int l,bool writeLineAnchor) { bool usePDFLatex = Config_getBool(USE_PDFLATEX); bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS); @@ -191,7 +189,7 @@ void LatexCodeGenerator::writeLineNumber(const QCString &ref,const QCString &fil lineAnchor.sprintf("_l%05d",l); lineAnchor.prepend(stripExtensionGeneral(m_sourceFileName, ".tex")); } - bool showTarget = usePDFLatex && pdfHyperlinks && !lineAnchor.isEmpty(); + bool showTarget = usePDFLatex && pdfHyperlinks && !lineAnchor.isEmpty() && writeLineAnchor; if (showTarget) { m_t << "\\Hypertarget{" << stripPath(lineAnchor) << "}"; @@ -295,8 +293,8 @@ static void writeLatexMakefile() } TextStream t(&f); // inserted by KONNO Akihisa <konno@researchers.jp> 2002-03-05 - QCString latex_command = theTranslator->latexCommandName(); - QCString mkidx_command = Config_getString(MAKEINDEX_CMD_NAME); + QCString latex_command = theTranslator->latexCommandName().quoted(); + QCString mkidx_command = Config_getString(MAKEINDEX_CMD_NAME).quoted(); // end insertion by KONNO Akihisa <konno@researchers.jp> 2002-03-05 if (!Config_getBool(USE_PDFLATEX)) // use plain old latex { @@ -383,8 +381,8 @@ static void writeMakeBat() #if defined(_MSC_VER) QCString dir=Config_getString(LATEX_OUTPUT); QCString fileName=dir+"/make.bat"; - QCString latex_command = theTranslator->latexCommandName(); - QCString mkidx_command = Config_getString(MAKEINDEX_CMD_NAME); + QCString latex_command = theTranslator->latexCommandName().quoted(); + QCString mkidx_command = Config_getString(MAKEINDEX_CMD_NAME).quoted(); bool generateBib = !CitationManager::instance().isEmpty(); std::ofstream t(fileName.str(),std::ofstream::out | std::ofstream::binary); if (!t.is_open()) @@ -608,7 +606,7 @@ static QCString substituteLatexKeywords(const QCString &str, bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS); bool usePdfLatex = Config_getBool(USE_PDFLATEX); bool latexBatchmode = Config_getBool(LATEX_BATCHMODE); - QCString paperType = Config_getString(PAPER_TYPE); + QCString paperType = Config_getEnumAsString(PAPER_TYPE); QCString style = Config_getString(LATEX_BIB_STYLE); if (style.isEmpty()) diff --git a/src/latexgen.h b/src/latexgen.h index 727c4be..8c76098 100644 --- a/src/latexgen.h +++ b/src/latexgen.h @@ -44,7 +44,7 @@ class LatexCodeGenerator : public CodeOutputInterface const SourceLinkInfo &, const SourceLinkInfo & ) override{} - void writeLineNumber(const QCString &,const QCString &,const QCString &,int) override; + void writeLineNumber(const QCString &,const QCString &,const QCString &,int,bool) override; void startCodeLine(bool) override; void endCodeLine() override; void startFontClass(const QCString &) override; @@ -101,8 +101,8 @@ class LatexGenerator : public OutputGenerator const QCString &anchor,const QCString &name, const QCString &tooltip) { m_codeGen.writeCodeLink(type,ref,file,anchor,name,tooltip); } - void writeLineNumber(const QCString &ref,const QCString &file,const QCString &anchor,int lineNumber) - { m_codeGen.writeLineNumber(ref,file,anchor,lineNumber); } + void writeLineNumber(const QCString &ref,const QCString &file,const QCString &anchor,int lineNumber, bool writeLineAnchor) + { m_codeGen.writeLineNumber(ref,file,anchor,lineNumber,writeLineAnchor); } void writeTooltip(const QCString &id, const DocLinkInfo &docInfo, const QCString &decl, const QCString &desc, const SourceLinkInfo &defInfo, const SourceLinkInfo &declInfo ) diff --git a/src/layout.cpp b/src/layout.cpp index 7c368be..f2a8e9d 100644 --- a/src/layout.cpp +++ b/src/layout.cpp @@ -89,6 +89,10 @@ static bool elemIsVisible(const XMLHandlers::Attributes &attrib,bool defVal=TRUE { return ConfigValues::instance().*(opt->value.b); } + else if (opt && opt->type==ConfigValues::Info::String) + { + return ConfigValues::instance().*(opt->value.s) != "NO"; + } else if (!opt) { err("found unsupported value %s for visible attribute in layout file\n", @@ -98,6 +102,11 @@ static bool elemIsVisible(const XMLHandlers::Attributes &attrib,bool defVal=TRUE return visible!="no" && visible!="0"; } +static bool parentIsVisible(LayoutNavEntry *parent) +{ + return parent==0 || parent->visible(); +} + //--------------------------------------------------------------------------------- LayoutNavEntry *LayoutNavEntry::find(LayoutNavEntry::Kind kind, @@ -118,15 +127,13 @@ LayoutNavEntry *LayoutNavEntry::find(LayoutNavEntry::Kind kind, return result; } - - QCString LayoutNavEntry::url() const { QCString url = baseFile().stripWhiteSpace(); if ((kind()!=LayoutNavEntry::User && kind()!=LayoutNavEntry::UserGroup) || (kind()==LayoutNavEntry::UserGroup && url.left(9)=="usergroup")) { - url+=Doxygen::htmlFileExtension; + url = addHtmlExtensionIfMissing(url); } else if (url.left(5)=="@ref " || url.left(5)=="\\ref ") { @@ -137,7 +144,7 @@ QCString LayoutNavEntry::url() const { if (d && d->isLinkable()) { - url=d->getOutputFileBase()+Doxygen::htmlFileExtension; + url=addHtmlExtensionIfMissing(d->getOutputFileBase()); if (!anchor.isEmpty()) { url+="#"+anchor; @@ -179,7 +186,7 @@ class LayoutParser void startSimpleEntry(LayoutDocEntry::Kind k,const XMLHandlers::Attributes &attrib) { - bool isVisible = elemIsVisible(attrib); + bool isVisible = elemIsVisible(attrib) && parentIsVisible(m_rootNav); if (m_part!=-1 && isVisible) { LayoutDocManager::instance().addEntry((LayoutDocManager::LayoutPart)m_part, @@ -192,7 +199,7 @@ class LayoutParser void startSectionEntry(LayoutDocEntry::Kind k,const XMLHandlers::Attributes &attrib, const QCString &title) { - bool isVisible = elemIsVisible(attrib); + bool isVisible = elemIsVisible(attrib) && parentIsVisible(m_rootNav); QCString userTitle = XMLHandlers::value(attrib,"title"); //printf("startSectionEntry: title='%s' userTitle='%s'\n", // qPrint(title),qPrint(userTitle)); @@ -243,7 +250,10 @@ class LayoutParser { m_scope="navindex/"; m_rootNav = LayoutDocManager::instance().rootNavEntry(); - if (m_rootNav) m_rootNav->clear(); + if (m_rootNav) + { + m_rootNav->clear(); + } } void endNavIndex() @@ -524,7 +534,7 @@ class LayoutParser } QCString baseFile = mapping[i].baseFile; QCString title = XMLHandlers::value(attrib,"title"); - bool isVisible = elemIsVisible(attrib); + bool isVisible = elemIsVisible(attrib) && parentIsVisible(m_rootNav); if (title.isEmpty()) // use default title { title = mapping[i].mainName; // use title for main row @@ -548,7 +558,14 @@ class LayoutParser { if (!url.isEmpty()) { - baseFile=url; + if (url == "[none]") + { + baseFile = QCString(); + } + else + { + baseFile=url; + } } else { @@ -707,6 +724,8 @@ class LayoutParser //--------------------------------------------------------------------------------- +namespace { + struct ElementCallbacks { using StartCallback = std::function<void(LayoutParser&,const XMLHandlers::Attributes&)>; @@ -1495,6 +1514,9 @@ static const std::map< std::string, ElementCallbacks > g_elementHandlers = }; + +} // namespace + void LayoutParser::startElement( const std::string &name, const XMLHandlers::Attributes& attrib ) { //printf("startElement [%s]::[%s]\n",qPrint(m_scope),qPrint(name)); diff --git a/src/layout.h b/src/layout.h index 04fdf52..9b76287 100644 --- a/src/layout.h +++ b/src/layout.h @@ -180,7 +180,7 @@ struct LayoutNavEntry LayoutNavEntry *find(LayoutNavEntry::Kind k,const QCString &file=QCString()) const; private: - LayoutNavEntry() : m_parent(0), m_kind(None), m_visible(FALSE) {} + LayoutNavEntry() : m_parent(0), m_kind(None), m_visible(true) {} LayoutNavEntry *m_parent; Kind m_kind; bool m_visible; diff --git a/src/lexcode.l b/src/lexcode.l index a2c0a97..9ac4c45 100644 --- a/src/lexcode.l +++ b/src/lexcode.l @@ -20,6 +20,10 @@ %option extra-type="struct lexcodeYY_state *" %top{ #include <stdint.h> +// forward declare yyscan_t to improve type safety +#define YY_TYPEDEF_YY_SCANNER_T +struct yyguts_t; +typedef yyguts_t *yyscan_t; } %{ @@ -47,8 +51,9 @@ struct lexcodeYY_state const char *inputString; //!< the code fragment as text yy_size_t inputPosition; //!< read offset during parsing int inputLines; //!< number of line in the code fragment + QCString fileName; int yyLineNr; //!< current line number - bool needsTermination; + bool insideCodeLine = false; bool lineNumbers = FALSE; const Definition *searchCtx; @@ -102,6 +107,10 @@ static void handleCCode(yyscan_t yyscanner); #undef YY_INPUT #define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); +// otherwise the filename would be the name of the converted file (*.cpp instead of *.l) +static inline const char *getLexerFILE() {return __FILE__;} +#include "doxygen_lex.h" + %} nl (\r\n|\r|\n) @@ -628,11 +637,11 @@ NONLopt [^\n]* } <Comment>{CCS} { yyextra->CCodeBuffer += yytext ; } <Comment>{CPPC} { yyextra->CCodeBuffer += yytext ; } -<Comment>{CMD}("code"|"verbatim") { +<Comment>{CMD}("code"|"verbatim"|"iliteral") { yyextra->insideCode=TRUE; yyextra->CCodeBuffer += yytext ; } -<Comment>{CMD}("endcode"|"endverbatim") { +<Comment>{CMD}("endcode"|"endverbatim"|"endiliteral") { yyextra->insideCode=FALSE; yyextra->CCodeBuffer += yytext ; } @@ -757,7 +766,7 @@ NONLopt [^\n]* yyextra->nestedComment=FALSE; BEGIN(DocCopyBlock); } -<DocBlock>{CMD}("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"rtfonly"|"docbookonly"|"dot"|"msc"|"code")/[^a-z_A-Z0-9\-] { // verbatim command (which could contain nested comments!) +<DocBlock>{CMD}("verbatim"|"iliteral"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"rtfonly"|"docbookonly"|"dot"|"msc"|"code")/[^a-z_A-Z0-9\-] { // verbatim command (which could contain nested comments!) yyextra->CCodeBuffer += yytext; yyextra->docBlockName=&yytext[1]; yyextra->fencedSize=0; @@ -816,7 +825,7 @@ NONLopt [^\n]* BEGIN(DocBlock); } } -<DocCopyBlock>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endmanonly"|"endrtfonly"|"enddot"|"endmsc"|"enduml"|"endcode")/[^a-z_A-Z0-9] { // end of verbatim block +<DocCopyBlock>[\\@]("endverbatim"|"endiliteral"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endmanonly"|"endrtfonly"|"enddot"|"endmsc"|"enduml"|"endcode")/[^a-z_A-Z0-9] { // end of verbatim block yyextra->CCodeBuffer += yytext; if (&yytext[4]==yyextra->docBlockName) { @@ -825,11 +834,7 @@ NONLopt [^\n]* } <DocCopyBlock>^{B}*"*"+/{BN}+ { // start of a comment line yyextra->CCodeBuffer += yytext; - if (yyextra->docBlockName=="verbatim") - { - REJECT; - } - else if (yyextra->docBlockName=="code") + if ((yyextra->docBlockName=="verbatim") || (yyextra->docBlockName=="code") || (yyextra->docBlockName=="iliteral")) { REJECT; } @@ -839,7 +844,7 @@ NONLopt [^\n]* } } <DocCopyBlock>^{B}*"*"+/{B}+"*"{BN}* { // start of a comment line with two *'s - if (yyextra->docBlockName=="code") + if ((yyextra->docBlockName=="code") || (yyextra->docBlockName=="iliteral")) { yyextra->CCodeBuffer += yytext; } @@ -849,7 +854,7 @@ NONLopt [^\n]* } } <DocCopyBlock>^{B}*"*"+/({ID}|"(") { // Assume *var or *(... is part of source code (see bug723516) - if (yyextra->docBlockName=="code") + if ((yyextra->docBlockName=="code") || (yyextra->docBlockName=="iliteral")) { yyextra->CCodeBuffer += yytext; } @@ -859,7 +864,7 @@ NONLopt [^\n]* } } <DocCopyBlock>^{B}*"*"+/{BN}* { // start of a comment line with one * - if (yyextra->docBlockName=="code") + if ((yyextra->docBlockName=="code") || (yyextra->docBlockName=="iliteral")) { if (yyextra->nestedComment) // keep * it is part of the code { @@ -981,24 +986,28 @@ static void startCodeLine(yyscan_t yyscanner) { yyextra->code->writeLineNumber(yyextra->currentMemberDef->getReference(), yyextra->currentMemberDef->getOutputFileBase(), - yyextra->currentMemberDef->anchor(),yyextra->yyLineNr); + yyextra->currentMemberDef->anchor(),yyextra->yyLineNr, + !yyextra->includeCodeFragment); setCurrentDoc(yyscanner,lineAnchor); } else { yyextra->code->writeLineNumber(d->getReference(), d->getOutputFileBase(), - QCString(),yyextra->yyLineNr); + QCString(),yyextra->yyLineNr, + !yyextra->includeCodeFragment); setCurrentDoc(yyscanner,lineAnchor); } } else { - yyextra->code->writeLineNumber(QCString(),QCString(),QCString(),yyextra->yyLineNr); + yyextra->code->writeLineNumber(QCString(),QCString(),QCString(),yyextra->yyLineNr, + !yyextra->includeCodeFragment); } } yyextra->code->startCodeLine(yyextra->sourceFileDef && yyextra->lineNumbers); + yyextra->insideCodeLine = true; if (yyextra->currentFontClass) { @@ -1021,13 +1030,17 @@ static void endCodeLine(yyscan_t yyscanner) struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; endFontClass(yyscanner); yyextra->code->endCodeLine(); + yyextra->insideCodeLine = false; } static void nextCodeLine(yyscan_t yyscanner) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; const char *fc = yyextra->currentFontClass; - endCodeLine(yyscanner); + if (yyextra->insideCodeLine) + { + endCodeLine(yyscanner); + } if (yyextra->yyLineNr<yyextra->inputLines) { yyextra->currentFontClass = fc; @@ -1054,15 +1067,7 @@ static void codifyLines(yyscan_t yyscanner,const QCString &text) memcpy(tmp,sp,l); tmp[l]='\0'; yyextra->code->codify(tmp); - if (p) - { - nextCodeLine(yyscanner); - } - else - { - endCodeLine(yyscanner); - done=true; - } + nextCodeLine(yyscanner); free(tmp); } else @@ -1100,9 +1105,7 @@ static int countLines(yyscan_t yyscanner) } if (p>yyextra->inputString && *(p-1)!='\n') { // last line does not end with a \n, so we add an extra - // line and explicitly terminate the line after parsing. - count++, - yyextra->needsTermination=true; + count++; } return count; } @@ -1140,7 +1143,7 @@ static void handleCCode(yyscan_t yyscanner) struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (yyextra->CCodeBuffer.isEmpty()) return; - yyextra->ccodeParser.setStartCodeLine(false); + yyextra->ccodeParser.setInsideCodeLine(yyextra->insideCodeLine); yyextra->ccodeParser.parseCode(*yyextra->code, yyextra->classScope, yyextra->CCodeBuffer, @@ -1157,10 +1160,9 @@ static void handleCCode(yyscan_t yyscanner) yyextra->collectXRefs ); yyextra->CCodeBuffer.resize(0); - yyextra->ccodeParser.setStartCodeLine(true); + yyextra->insideCodeLine = yyextra->ccodeParser.insideCodeLine(); yyextra->yyLineNr--; codifyLines(yyscanner,"\n"); - return; } // public interface ----------------------------------------------------------- @@ -1218,8 +1220,9 @@ void LexCodeParser::parseCode(CodeOutputInterface &codeOutIntf, yyextra->code = &codeOutIntf; yyextra->inputString = input.data(); yyextra->inputPosition = 0; + yyextra->fileName = fileDef ? fileDef->fileName():""; yyextra->currentFontClass = 0; - yyextra->needsTermination = false; + yyextra->insideCodeLine = false; yyextra->classScope=scopeName; yyextra->currentMemberDef=memberDef; @@ -1264,7 +1267,7 @@ void LexCodeParser::parseCode(CodeOutputInterface &codeOutIntf, BEGIN( DefSection ); lexcodeYYlex(yyscanner); - if (yyextra->needsTermination) + if (yyextra->insideCodeLine) { endCodeLine(yyscanner); } diff --git a/src/lexscanner.l b/src/lexscanner.l index 0c5ca31..a314d9d 100644 --- a/src/lexscanner.l +++ b/src/lexscanner.l @@ -20,6 +20,10 @@ %top{ #include <stdint.h> +// forward declare yyscan_t to improve type safety +#define YY_TYPEDEF_YY_SCANNER_T +struct yyguts_t; +typedef yyguts_t *yyscan_t; } %{ @@ -78,7 +82,7 @@ struct lexscannerYY_state QCString cCodeBuffer; int roundCount = 0; - QCString yyFileName; + QCString fileName; ClangTUParser *clangParser = 0; std::shared_ptr<Entry> current; @@ -99,6 +103,10 @@ static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size); #undef YY_INPUT #define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); +// otherwise the filename would be the name of the converted file (*.cpp instead of *.l) +static inline const char *getLexerFILE() {return __FILE__;} +#include "doxygen_lex.h" + %} nl (\r\n|\r|\n) @@ -614,11 +622,11 @@ NONLopt [^\n]* } <Comment>{CCS} { yyextra->cCodeBuffer += yytext ; } <Comment>{CPPC} { yyextra->cCodeBuffer += yytext ; } -<Comment>{CMD}("code"|"verbatim") { +<Comment>{CMD}("code"|"verbatim"|"iliteral") { yyextra->insideCode=TRUE; yyextra->cCodeBuffer += yytext ; } -<Comment>{CMD}("endcode"|"endverbatim") { +<Comment>{CMD}("endcode"|"endverbatim"|"endiliteral") { yyextra->insideCode=FALSE; yyextra->cCodeBuffer += yytext ; } @@ -739,7 +747,7 @@ NONLopt [^\n]* yyextra->nestedComment=FALSE; BEGIN(DocCopyBlock); } -<DocBlock>{CMD}("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"rtfonly"|"docbookonly"|"dot"|"msc"|"code")/[^a-z_A-Z0-9\-] { // verbatim command (which could contain nested comments!) +<DocBlock>{CMD}("verbatim"|"iliteral"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"rtfonly"|"docbookonly"|"dot"|"msc"|"code")/[^a-z_A-Z0-9\-] { // verbatim command (which could contain nested comments!) yyextra->cCodeBuffer += yytext; yyextra->docBlockName=&yytext[1]; yyextra->fencedSize=0; @@ -797,7 +805,7 @@ NONLopt [^\n]* BEGIN(DocBlock); } } -<DocCopyBlock>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endmanonly"|"endrtfonly"|"enddot"|"endmsc"|"enduml"|"endcode")/[^a-z_A-Z0-9] { // end of verbatim block +<DocCopyBlock>[\\@]("endverbatim"|"endiliteral"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endmanonly"|"endrtfonly"|"enddot"|"endmsc"|"enduml"|"endcode")/[^a-z_A-Z0-9] { // end of verbatim block yyextra->cCodeBuffer += yytext; if (yyextra->docBlockName==&yytext[4]) { @@ -806,11 +814,7 @@ NONLopt [^\n]* } <DocCopyBlock>^{B}*"*"+/{BN}+ { // start of a comment line yyextra->cCodeBuffer += yytext; - if (yyextra->docBlockName=="verbatim") - { - REJECT; - } - else if (yyextra->docBlockName=="code") + if ((yyextra->docBlockName=="verbatim") || (yyextra->docBlockName=="code") || (yyextra->docBlockName=="iliteral")) { REJECT; } @@ -820,7 +824,7 @@ NONLopt [^\n]* } } <DocCopyBlock>^{B}*"*"+/{B}+"*"{BN}* { // start of a comment line with two *'s - if (yyextra->docBlockName=="code") + if ((yyextra->docBlockName=="code") || (yyextra->docBlockName=="iliteral")) { yyextra->cCodeBuffer += yytext; } @@ -830,7 +834,7 @@ NONLopt [^\n]* } } <DocCopyBlock>^{B}*"*"+/({ID}|"(") { // Assume *var or *(... is part of source code (see bug723516) - if (yyextra->docBlockName=="code") + if ((yyextra->docBlockName=="code") || (yyextra->docBlockName=="iliteral")) { yyextra->cCodeBuffer += yytext; } @@ -840,7 +844,7 @@ NONLopt [^\n]* } } <DocCopyBlock>^{B}*"*"+/{BN}* { // start of a comment line with one * - if (yyextra->docBlockName=="code") + if ((yyextra->docBlockName=="code") || (yyextra->docBlockName=="iliteral")) { if (yyextra->nestedComment) // keep * it is part of the code { @@ -953,18 +957,18 @@ static void parseMain(yyscan_t yyscanner, lexscannerYYrestart(0,yyscanner); yyextra->current_root = rt; - yyextra->yyFileName = fileName; + yyextra->fileName = fileName; yyextra->clangParser = clangParser; - yyextra->language = getLanguageFromFileName(yyextra->yyFileName); + yyextra->language = getLanguageFromFileName(yyextra->fileName); rt->lang = yyextra->language; - msg("Parsing file %s...\n",qPrint(yyextra->yyFileName)); + msg("Parsing file %s...\n",qPrint(yyextra->fileName)); yyextra->current_root = rt; yyextra->current = std::make_shared<Entry>(); - int sec=guessSection(yyextra->yyFileName); + int sec=guessSection(yyextra->fileName); if (sec) { - yyextra->current->name = yyextra->yyFileName; + yyextra->current->name = yyextra->fileName; yyextra->current->section = sec; yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); } @@ -984,7 +988,7 @@ static void handleCCode(yyscan_t yyscanner) struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (yyextra->cCodeBuffer.isEmpty()) return; - yyextra->cOutlineParser.parseInput(yyextra->yyFileName, + yyextra->cOutlineParser.parseInput(yyextra->fileName, yyextra->cCodeBuffer.data(), yyextra->current_root, yyextra->clangParser); @@ -1019,6 +1023,7 @@ void LexOutlineParser::parseInput(const QCString &fileName, { struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; + yyextra->fileName = fileName; printlex(yy_flex_debug, TRUE, __FILE__, qPrint(fileName)); ::parseMain(p->yyscanner,fileName,fileBuf,root,clangParser); diff --git a/src/mandocvisitor.cpp b/src/mandocvisitor.cpp index 8d41d63..bb1169a 100644 --- a/src/mandocvisitor.cpp +++ b/src/mandocvisitor.cpp @@ -166,6 +166,9 @@ void ManDocVisitor::visit(DocStyleChange *s) case DocStyleChange::Small: /* not supported */ break; + case DocStyleChange::Cite: + /* not supported */ + break; case DocStyleChange::Preformatted: if (s->enable()) { @@ -185,6 +188,18 @@ void ManDocVisitor::visit(DocStyleChange *s) break; case DocStyleChange::Div: /* HTML only */ break; case DocStyleChange::Span: /* HTML only */ break; + case DocStyleChange::Details: /* emulation of the <details> tag */ + if (!s->enable()) + { + if (!m_firstCol) m_t << "\n"; + m_t << ".PP\n"; + m_firstCol=TRUE; + } + break; + case DocStyleChange::Summary: /* emulation of the <summary> tag inside a <details> tag */ + if (s->enable()) m_t << "\\fB"; else m_t << "\\fP"; + m_firstCol=FALSE; + break; } } @@ -211,11 +226,19 @@ void ManDocVisitor::visit(DocVerbatim *s) m_t << ".PP\n"; m_firstCol=TRUE; break; + case DocVerbatim::JavaDocLiteral: + filter(s->text()); + break; + case DocVerbatim::JavaDocCode: + m_t << "\\fC\n"; + filter(s->text()); + m_t << "\\fP\n"; + break; case DocVerbatim::Verbatim: if (!m_firstCol) m_t << "\n"; m_t << ".PP\n"; m_t << ".nf\n"; - m_t << s->text(); + filter(s->text()); if (!m_firstCol) m_t << "\n"; m_t << ".fi\n"; m_t << ".PP\n"; @@ -685,6 +708,15 @@ void ManDocVisitor::visitPre(DocHtmlListItem *li) m_t << ".IP \"" << ws; if (((DocHtmlList *)li->parent())->type()==DocHtmlList::Ordered) { + for (const auto &opt : li->attribs()) + { + if (opt.name=="value") + { + bool ok; + int val = opt.value.toInt(&ok); + if (ok) man_listItemInfo[m_indent].number = val; + } + } switch (man_listItemInfo[m_indent].type) { case '1': diff --git a/src/mangen.h b/src/mangen.h index befea18..30c3f39 100644 --- a/src/mangen.h +++ b/src/mangen.h @@ -126,7 +126,7 @@ class ManGenerator : public OutputGenerator void writeAnchor(const QCString &,const QCString &) {} void startCodeFragment(const QCString &); void endCodeFragment(const QCString &); - void writeLineNumber(const QCString &,const QCString &,const QCString &,int l) { m_t << l << " "; m_col=0; } + void writeLineNumber(const QCString &,const QCString &,const QCString &,int l, bool) { m_t << l << " "; m_col=0; } void startCodeLine(bool) {} void endCodeLine() { codify("\n"); m_col=0; } void startEmphasis() { m_t << "\\fI"; m_firstCol=FALSE; } diff --git a/src/markdown.cpp b/src/markdown.cpp index 0c1db17..c8e6723 100644 --- a/src/markdown.cpp +++ b/src/markdown.cpp @@ -53,6 +53,13 @@ #include "fileinfo.h" #include "utf8.h" +enum class ExplicitPageResult +{ + explicitPage, /**< docs start with a page command */ + explicitMainPage, /**< docs start with a mainpage command */ + notExplicit /**< docs doesn't start with either page or mainpage */ +}; + #if !defined(NDEBUG) #define ENABLE_TRACING #endif @@ -135,6 +142,11 @@ class Trace m_resultSet = true; m_resultValue = b ? "true" : "false"; } + void setResult(ExplicitPageResult ep) + { + m_resultSet = true; + m_resultValue = QCString().setNum(static_cast<int>(ep)); + } void setResult(int i) { m_resultSet = true; @@ -194,7 +206,6 @@ int Trace::s_indent = 0; (data[i]=='(' || data[i]=='{' || data[i]=='[' || (data[i]=='<' && data[i+1]!='/') || \ data[i]=='\\' || \ data[i]=='@') - //---------- struct TableCell @@ -280,8 +291,23 @@ static QCString escapeSpecialChars(const QCString &s) switch (c) { case '"': if (pc!='\\') { insideQuote=!insideQuote; } growBuf.addChar(c); break; - case '<': if (!insideQuote) { growBuf.addChar('\\'); } growBuf.addChar('<'); break; - case '>': if (!insideQuote) { growBuf.addChar('\\'); } growBuf.addChar('>'); break; + case '<': + case '>': if (!insideQuote) + { + growBuf.addChar('\\'); + growBuf.addChar(c); + if ((p[0] == ':') && (p[1] == ':')) + { + growBuf.addChar('\\'); + growBuf.addChar(':'); + p++; + } + } + else + { + growBuf.addChar(c); + } + break; case '\\': if (!insideQuote) { growBuf.addChar('\\'); } growBuf.addChar('\\'); break; case '@': if (!insideQuote) { growBuf.addChar('\\'); } growBuf.addChar('@'); break; case '#': if (!insideQuote) { growBuf.addChar('\\'); } growBuf.addChar('#'); break; @@ -326,6 +352,29 @@ static Alignment markersToAlignment(bool leftMarker,bool rightMarker) } } +/** parse the image attributes and return attributes for given format */ +static QCString getFilteredImageAttributes(const char *fmt, const QCString &attrs) +{ + StringVector attrList = split(attrs.str(),","); + for (const auto &attr_ : attrList) + { + QCString attr = QCString(attr_).stripWhiteSpace(); + int i = attr.find(':'); + if (i>0) // has format + { + QCString format = attr.left(i).stripWhiteSpace().lower(); + if (format == fmt) // matching format + { + return attr.mid(i+1); // keep part after : + } + } + else // option that applies to all formats + { + return attr; + } + } + return QCString(); +} // Check if data contains a block command. If so returned the command // that ends the block. If not an empty string is returned. @@ -341,14 +390,61 @@ static Alignment markersToAlignment(bool leftMarker,bool rightMarker) // \f[..\f] // \f{..\f} // \verbatim..\endverbatim +// \iliteral..\endiliteral // \latexonly..\endlatexonly // \htmlonly..\endhtmlonly // \xmlonly..\endxmlonly // \rtfonly..\endrtfonly // \manonly..\endmanonly +// \startuml..\enduml QCString Markdown::isBlockCommand(const char *data,int offset,int size) { TRACE(data); + + using EndBlockFunc = QCString (*)(const std::string &,bool,char); + + static const auto getEndBlock = [](const std::string &blockName,bool,char) -> QCString + { + return "end"+blockName; + }; + static const auto getEndCode = [](const std::string &blockName,bool openBracket,char) -> QCString + { + return openBracket ? QCString("}") : "end"+blockName; + }; + static const auto getEndUml = [](const std::string &blockName,bool,char) -> QCString + { + return "enduml"; + }; + static const auto getEndFormula = [](const std::string &blockName,bool,char nextChar) -> QCString + { + switch (nextChar) + { + case '$': return "f$"; + case '(': return "f)"; + case '[': return "f]"; + case '{': return "f}"; + } + return ""; + }; + + // table mapping a block start command to a function that can return the matching end block string + static const std::unordered_map<std::string,EndBlockFunc> blockNames = + { + { "dot", getEndBlock }, + { "code", getEndCode }, + { "msc", getEndBlock }, + { "verbatim", getEndBlock }, + { "iliteral", getEndBlock }, + { "latexonly", getEndBlock }, + { "htmlonly", getEndBlock }, + { "xmlonly", getEndBlock }, + { "rtfonly", getEndBlock }, + { "manonly", getEndBlock }, + { "docbookonly", getEndBlock }, + { "startuml", getEndUml }, + { "f", getEndFormula } + }; + bool openBracket = offset>0 && data[-1]=='{'; bool isEscaped = offset>0 && (data[-1]=='\\' || data[-1]=='@'); if (isEscaped) return QCString(); @@ -356,58 +452,208 @@ QCString Markdown::isBlockCommand(const char *data,int offset,int size) int end=1; while (end<size && (data[end]>='a' && data[end]<='z')) end++; if (end==1) return QCString(); - QCString blockName; - convertStringFragment(blockName,data+1,end-1); - if (blockName=="code" && openBracket) - { - TRACE_RESULT("}"); - return "}"; - } - else if (blockName=="dot" || - blockName=="code" || - blockName=="msc" || - blockName=="verbatim" || - blockName=="latexonly" || - blockName=="htmlonly" || - blockName=="xmlonly" || - blockName=="rtfonly" || - blockName=="manonly" || - blockName=="docbookonly" - ) - { - QCString result = "end"+blockName; - TRACE_RESULT(result); - return result; - } - else if (blockName=="startuml") - { - TRACE_RESULT("enduml"); - return "enduml"; + std::string blockName(data+1,end-1); + auto it = blockNames.find(blockName); + QCString result; + if (it!=blockNames.end()) // there is a function assigned + { + result = it->second(blockName, openBracket, end<size ? data[end] : 0); } - else if (blockName=="f" && end<size) + TRACE_RESULT(result); + return result; +} + +int Markdown::isSpecialCommand(const char *data,int offset,int size) +{ + TRACE(data); + + using EndCmdFunc = int (*)(const char *,int,int); + + static const auto endOfLine = [](const char *data_,int offset_,int size_) -> int + { + // skip until the end of line (allowing line continuation characters) + char lc = 0; + char c; + while (offset_<size_ && ((c=data_[offset_])!='\n' || lc=='\\')) + { + if (c=='\\') lc='\\'; // last character was a line continuation + else if (c!=' ') lc=0; // rest line continuation + offset_++; + } + return offset_; + }; + + static const auto endOfLabel = [](const char *data_,int offset_,int size_) -> int { - if (data[end]=='$') + if (offset_<size_ && data_[offset_]==' ') // we expect a space before the label { - TRACE_RESULT("f$"); - return "f$"; + char c; + offset_++; + // skip over spaces + while (offset_<size_ && data_[offset_]==' ') offset_++; + // skip over label + while (offset_<size_ && (c=data_[offset_])!=' ' && c!='\n') offset_++; + return offset_; } - else if (data[end]=='(') + return 0; + }; + + static const auto endOfParam = [](const char *data_,int offset_,int size_) -> int + { + int index=offset_; + if (index<size_ && data_[index]==' ') // skip over optional spaces { - TRACE_RESULT("f)"); - return "f)"; + index++; + while (index<size_ && data_[index]==' ') index++; } - else if (data[end]=='[') + if (index<size_ && data_[index]=='[') // find matching ']' { - TRACE_RESULT("f]"); - return "f]"; + index++; + char c; + while (index<size_ && (c=data_[index])!=']' && c!='\n') index++; + if (index==size_ || data_[index]!=']') return 0; // invalid parameter + offset_=index+1; // part after [...] is the parameter name } - else if (data[end]=='{') + return endOfLabel(data_,offset_,size_); + }; + + static const auto endOfFunc = [](const char *data_,int offset_,int size_) -> int + { + if (offset_<size_ && data_[offset_]==' ') // we expect a space before the name { - TRACE_RESULT("f}"); - return "f}"; + char c=0; + offset_++; + // skip over spaces + while (offset_<size_ && data_[offset_]==' ') offset_++; + // skip over name + while (offset_<size_ && (c=data_[offset_])!=' ' && c!='\n' && c!='(') offset_++; + if (c=='(') // find the end of the function + { + int count=1; + offset_++; + while (offset_<size_ && (c=data_[offset_++])) + { + if (c=='(') count++; + else if (c==')') count--; + if (count==0) return offset_; + } + } + return offset_; } + return 0; + }; + + static const auto endOfGuard = [](const char *data_,int offset_,int size_) -> int + { + return endOfFunc(data_,offset_,size_); + }; + + static const std::unordered_map<std::string,EndCmdFunc> cmdNames = + { + { "a", endOfLabel }, + { "addindex", endOfLine }, + { "addtogroup", endOfLabel }, + { "anchor", endOfLabel }, + { "b", endOfLabel }, + { "c", endOfLabel }, + { "category", endOfLine }, + { "cite", endOfLabel }, + { "class", endOfLine }, + { "concept", endOfLine }, + { "copybrief", endOfFunc }, + { "copydetails", endOfFunc }, + { "copydoc", endOfFunc }, + { "def", endOfFunc }, + { "defgroup", endOfLabel }, + { "diafile", endOfLine }, + { "dir", endOfLine }, + { "dockbookinclude",endOfLine }, + { "dontinclude", endOfLine }, + { "dotfile", endOfLine }, + { "dotfile", endOfLine }, + { "e", endOfLabel }, + { "elseif", endOfGuard }, + { "em", endOfLabel }, + { "emoji", endOfLabel }, + { "enum", endOfLabel }, + { "example", endOfLine }, + { "exception", endOfLine }, + { "extends", endOfLabel }, + { "file", endOfLine }, + { "fn", endOfFunc }, + { "headerfile", endOfLine }, + { "htmlinclude", endOfLine }, + { "idlexcept", endOfLine }, + { "if", endOfGuard }, + { "ifnot", endOfGuard }, + { "image", endOfLine }, + { "implements", endOfLine }, + { "include", endOfLine }, + { "includedoc", endOfLine }, + { "includelineno", endOfLine }, + { "ingroup", endOfLabel }, + { "interface", endOfLine }, + { "interface", endOfLine }, + { "latexinclude", endOfLine }, + { "maninclude", endOfLine }, + { "memberof", endOfLabel }, + { "mscfile", endOfLine }, + { "namespace", endOfLabel }, + { "noop", endOfLine }, + { "overload", endOfLine }, + { "p", endOfLabel }, + { "package", endOfLabel }, + { "page", endOfLabel }, + { "paragraph", endOfLabel }, + { "param", endOfParam }, + { "property", endOfLine }, + { "protocol", endOfLine }, + { "ref", endOfLabel }, + { "refitem", endOfLabel }, + { "related", endOfLabel }, + { "relatedalso", endOfLabel }, + { "relates", endOfLabel }, + { "relatesalso", endOfLabel }, + { "retval", endOfLabel }, + { "rtfinclude", endOfLine }, + { "section", endOfLabel }, + { "skip", endOfLine }, + { "skipline", endOfLine }, + { "snippet", endOfLine }, + { "snippetdoc", endOfLine }, + { "snippetlineno", endOfLine }, + { "struct", endOfLine }, + { "subpage", endOfLabel }, + { "subsection", endOfLabel }, + { "subsubsection", endOfLabel }, + { "throw", endOfLabel }, + { "throws", endOfLabel }, + { "tparam", endOfLabel }, + { "typedef", endOfLine }, + { "union", endOfLine }, + { "until", endOfLine }, + { "var", endOfLine }, + { "verbinclude", endOfLine }, + { "weakgroup", endOfLabel }, + { "xmlinclude", endOfLine }, + { "xrefitem", endOfLabel } + }; + + bool isEscaped = offset>0 && (data[-1]=='\\' || data[-1]=='@'); + if (isEscaped) return 0; + + int end=1; + while (end<size && (data[end]>='a' && data[end]<='z')) end++; + if (end==1) return 0; + std::string cmdName(data+1,end-1); + int result=0; + auto it = cmdNames.find(cmdName); + if (it!=cmdNames.end()) // command with parameters that should be ignored by markdown + { + // find the end of the parameters + result = it->second(data,end,size); } - return QCString(); + return result; } /** looks for the next emph char, skipping other constructs, and @@ -864,11 +1110,18 @@ int Markdown::processEmphasis(const char *data,int offset,int size) return 0; } -void Markdown::writeMarkdownImage(const char *fmt, bool explicitTitle, +void Markdown::writeMarkdownImage(const char *fmt, bool inline_img, bool explicitTitle, const QCString &title, const QCString &content, - const QCString &link, const FileDef *fd) + const QCString &link, const QCString &attrs, + const FileDef *fd) { - m_out.addStr("@image{inline} "); + QCString attributes = getFilteredImageAttributes(fmt, attrs); + m_out.addStr("@image"); + if (inline_img) + { + m_out.addStr("{inline}"); + } + m_out.addStr(" "); m_out.addStr(fmt); m_out.addStr(" "); m_out.addStr(link.mid(fd ? 0 : 5)); @@ -888,10 +1141,16 @@ void Markdown::writeMarkdownImage(const char *fmt, bool explicitTitle, { m_out.addStr(" ");// so the line break will not be part of the image name } - m_out.addStr("\\ilinebr"); + if (!attributes.isEmpty()) + { + m_out.addStr(" "); + m_out.addStr(attributes); + m_out.addStr(" "); + } + m_out.addStr("\\ilinebr "); } -int Markdown::processLink(const char *data,int,int size) +int Markdown::processLink(const char *data,int offset,int size) { TRACE(data); QCString content; @@ -899,6 +1158,7 @@ int Markdown::processLink(const char *data,int,int size) QCString title; int contentStart,contentEnd,linkStart,titleStart,titleEnd; bool isImageLink = FALSE; + bool isImageInline = FALSE; bool isToc = FALSE; int i=1; if (data[0]=='!') @@ -909,6 +1169,22 @@ int Markdown::processLink(const char *data,int,int size) TRACE_RESULT(0); return 0; } + + // if there is non-whitespace before the ![ within the scope of two new lines, the image + // is considered inlined, i.e. the image is not preceded by an empty line + int numNLsNeeded=2; + int pos = -1; + while (pos>=-offset && numNLsNeeded>0) + { + if (data[pos]=='\n') numNLsNeeded--; + else if (data[pos]!=' ') // found non-whitespace, stop searching + { + isImageInline=true; + break; + } + pos--; + } + // skip '![' i++; } contentStart=i; @@ -946,10 +1222,12 @@ int Markdown::processLink(const char *data,int,int size) if (!isImageLink && content.isEmpty()) { TRACE_RESULT(0); return 0; } // no link text i++; // skip over ] + bool whiteSpace = false; // skip whitespace - while (i<size && data[i]==' ') i++; + while (i<size && data[i]==' ') {whiteSpace = true; i++;} if (i<size && data[i]=='\n') // one newline allowed here { + whiteSpace = true; i++; nl++; // skip more whitespace @@ -957,6 +1235,7 @@ int Markdown::processLink(const char *data,int,int size) } nlTotal += nl; nl = 0; + if (whiteSpace && i<size && (data[i]=='(' || data[i]=='[')) return 0; bool explicitTitle=FALSE; if (i<size && data[i]=='(') // inline link @@ -1003,13 +1282,22 @@ int Markdown::processLink(const char *data,int,int size) i++; titleStart=i; nl=0; - while (i<size && data[i]!=')') + while (i<size) { if (data[i]=='\n') { if (nl>1) { TRACE_RESULT(0); return 0; } nl++; } + else if (data[i]=='\\') // escaped char in string + { + i++; + } + else if (data[i]==c) + { + i++; + break; + } i++; } if (i>=size) @@ -1023,7 +1311,17 @@ int Markdown::processLink(const char *data,int,int size) if (data[titleEnd]==c) // found it { convertStringFragment(title,data+titleStart,titleEnd-titleStart); - //printf("processLink: title={%s}\n",qPrint(title)); + explicitTitle=TRUE; + while (i<size) + { + if (data[i]==' ')i++; // remove space after the closing quote and the closing bracket + else if (data[i] == ')') break; // the end bracket + else // illegal + { + TRACE_RESULT(0); + return 0; + } + } } else { @@ -1105,6 +1403,69 @@ int Markdown::processLink(const char *data,int,int size) } nlTotal += nl; nl = 0; + + // search for optional image attributes + QCString attributes; + if (isImageLink) + { + int j = i; + // skip over whitespace + while (j<size && data[j]==' ') { j++; } + if (j<size && data[j]=='{') // we have attributes + { + i = j; + // skip over '{' + i++; + int attributesStart=i; + nl=0; + // find the matching '}' + while (i<size) + { + if (data[i-1]=='\\') // skip escaped characters + { + } + else if (data[i]=='{') + { + level++; + } + else if (data[i]=='}') + { + level--; + if (level<=0) break; + } + else if (data[i]=='\n') + { + nl++; + if (nl>1) { TRACE_RESULT(0); return 0; } // only allow one newline in the content + } + i++; + } + nlTotal += nl; + nl = 0; + if (i>=size) return 0; // premature end of comment -> no attributes + int attributesEnd=i; + convertStringFragment(attributes,data+attributesStart,attributesEnd-attributesStart); + i++; // skip over '}' + } + if (!isImageInline) + { + // if there is non-whitespace after the image within the scope of two new lines, the image + // is considered inlined, i.e. the image is not followed by an empty line + int numNLsNeeded=2; + int pos = i; + while (pos<size && numNLsNeeded>0) + { + if (data[pos]=='\n') numNLsNeeded--; + else if (data[pos]!=' ') // found non-whitespace, stop searching + { + isImageInline=true; + break; + } + pos++; + } + } + } + if (isToc) // special case for [TOC] { int toc_level = Config_getInt(TOC_INCLUDE_HEADINGS); @@ -1123,10 +1484,11 @@ int Markdown::processLink(const char *data,int,int size) (fd=findFileDef(Doxygen::imageNameLinkedMap,link,ambig))) // assume doxygen symbol link or local image link { - writeMarkdownImage("html", explicitTitle, title, content, link, fd); - writeMarkdownImage("latex", explicitTitle, title, content, link, fd); - writeMarkdownImage("rtf", explicitTitle, title, content, link, fd); - writeMarkdownImage("docbook", explicitTitle, title, content, link, fd); + // check if different handling is needed per format + writeMarkdownImage("html", isImageInline, explicitTitle, title, content, link, attributes, fd); + writeMarkdownImage("latex", isImageInline, explicitTitle, title, content, link, attributes, fd); + writeMarkdownImage("rtf", isImageInline, explicitTitle, title, content, link, attributes, fd); + writeMarkdownImage("docbook", isImageInline, explicitTitle, title, content, link, attributes, fd); } else { @@ -1177,32 +1539,44 @@ int Markdown::processLink(const char *data,int,int size) m_out.addStr(" \""); if (explicitTitle && !title.isEmpty()) { - m_out.addStr(title); + m_out.addStr(substitute(title,"\"",""")); } else { - m_out.addStr(content); + m_out.addStr(substitute(content,"\"",""")); } m_out.addStr("\""); } else if (link.find('/')!=-1 || link.find('.')!=-1 || link.find('#')!=-1) { // file/url link - m_out.addStr("<a href=\""); - m_out.addStr(link); - m_out.addStr("\""); - for (int ii = 0; ii < nlTotal; ii++) m_out.addStr("\n"); - if (!title.isEmpty()) + if (link.at(0) == '#') { - m_out.addStr(" title=\""); - m_out.addStr(substitute(title.simplifyWhiteSpace(),"\"",""")); + m_out.addStr("@ref "); + m_out.addStr(link.mid(1)); + m_out.addStr(" \""); + m_out.addStr(substitute(content.simplifyWhiteSpace(),"\"",""")); m_out.addStr("\""); + + } + else + { + m_out.addStr("<a href=\""); + m_out.addStr(link); + m_out.addStr("\""); + for (int ii = 0; ii < nlTotal; ii++) m_out.addStr("\n"); + if (!title.isEmpty()) + { + m_out.addStr(" title=\""); + m_out.addStr(substitute(title.simplifyWhiteSpace(),"\"",""")); + m_out.addStr("\""); + } + m_out.addStr(" "); + m_out.addStr(externalLinkTarget()); + m_out.addStr(">"); + content = substitute(content.simplifyWhiteSpace(),"\"","\\\""); + processInline(content.data(),content.length()); + m_out.addStr("</a>"); } - m_out.addStr(" "); - m_out.addStr(externalLinkTarget()); - m_out.addStr(">"); - content = content.simplifyWhiteSpace(); - processInline(content.data(),content.length()); - m_out.addStr("</a>"); } else // avoid link to e.g. F[x](y) { @@ -1332,7 +1706,13 @@ int Markdown::processSpecialCommand(const char *data, int offset, int size) i++; } } - if (size>1 && data[0]=='\\') + int endPos = isSpecialCommand(data,offset,size); + if (endPos>0) + { + m_out.addStr(data,endPos); + return endPos; + } + if (size>1 && data[0]=='\\') // escaped characters { char c=data[1]; if (c=='[' || c==']' || c=='*' || c=='!' || c=='(' || c==')' || c=='`' || c=='_') @@ -1365,16 +1745,19 @@ void Markdown::processInline(const char *data,int size) Action_t action; while (i<size) { + // skip over character that do not trigger a specific action while (end<size && ((action=m_actions[(uchar)data[end]])==0)) end++; + // and add them to the output m_out.addStr(data+i,end-i); if (end>=size) break; i=end; + // do the action matching a special character at i end = action(data+i,i,size-i); - if (end<=0) + if (end<=0) // update end { end=i+1-end; } - else + else // skip until end { i+=end; end=i; @@ -1434,8 +1817,8 @@ bool isBlockQuote(const char *data,int size,int indent) i++; } // last characters should be a space or newline, - // so a line starting with >= does not match - bool res = level>0 && i<size && ((data[i-1]==' ') || data[i]=='\n'); + // so a line starting with >= does not match, but only when level equals 1 + bool res = (level>0 && i<size && ((data[i-1]==' ') || data[i]=='\n')) || (level > 1); TRACE_RESULT(res); return res; } @@ -1584,7 +1967,7 @@ static QCString extractTitleId(QCString &title, int level) title = title.left((int)match.position()); //printf("found match id='%s' title=%s\n",id.c_str(),qPrint(title)); TRACE_RESULT(QCString(id)); - return id; + return QCString(id); } if ((level > 0) && (level <= Config_getInt(TOC_INCLUDE_HEADINGS))) { @@ -2166,6 +2549,15 @@ int Markdown::writeTableBlock(const char *data,int size) { continue; } + if (tableContents[row][c].colSpan) + { + int cr = c; + while ( cr >= 0 && tableContents[row][cr].colSpan) + { + cr--; + }; + if (cr >= 0 && tableContents[row][cr].cellText == "^") continue; + } unsigned rowSpan = 1, spanRow = row+1; while ((spanRow < tableContents.size()) && (tableContents[spanRow][c].cellText == "^")) @@ -2322,14 +2714,17 @@ int Markdown::writeBlockQuote(const char *data,int size) !(j==size || data[j]=='\n')) // disqualify last > if not followed by space { indent--; + level--; j--; } + if (!level && data[j-1]!='\n') level=curLevel; // lazy if (level>curLevel) // quote level increased => add start markers { - for (l=curLevel;l<level;l++) + for (l=curLevel;l<level-1;l++) { m_out.addStr("<blockquote>"); } + m_out.addStr("<blockquote>‍"); // empty blockquotes are also shown } else if (level<curLevel) // quote level decreased => add end markers { @@ -2452,7 +2847,7 @@ void Markdown::findEndOfLine(const char *data,int size, ) { if (tolower(data[end])=='p' && tolower(data[end+1])=='r' && - tolower(data[end+2])=='e' && data[end+3]=='>') // <pre> tag + tolower(data[end+2])=='e' && (data[end+3]=='>' || data[end+3]==' ')) // <pre> tag { // skip part until including </pre> end = end + processHtmlTagWrite(data+end-1,end-1,size-end+1,false) + 2; @@ -2825,8 +3220,8 @@ QCString Markdown::processBlocks(const QCString &s,const int indent) return m_out.get(); } -/** returns TRUE if input string docs starts with \@page or \@mainpage command */ -static bool isExplicitPage(const QCString &docs) + +static ExplicitPageResult isExplicitPage(const QCString &docs) { TRACE(docs); int i=0; @@ -2843,12 +3238,20 @@ static bool isExplicitPage(const QCString &docs) (qstrncmp(&data[i+1],"page ",5)==0 || qstrncmp(&data[i+1],"mainpage",8)==0) ) { - TRACE_RESULT(TRUE); - return TRUE; + if (qstrncmp(&data[i+1],"page ",5)==0) + { + TRACE_RESULT(ExplicitPageResult::explicitPage); + return ExplicitPageResult::explicitPage; + } + else + { + TRACE_RESULT(ExplicitPageResult::explicitMainPage); + return ExplicitPageResult::explicitMainPage; + } } } - TRACE_RESULT(FALSE); - return FALSE; + TRACE_RESULT(ExplicitPageResult::notExplicit); + return ExplicitPageResult::notExplicit; } QCString Markdown::extractPageTitle(QCString &docs,QCString &id, int &prepend) @@ -3083,30 +3486,55 @@ void MarkdownOutlineParser::parseInput(const QCString &fileName, QCString mdfileAsMainPage = Config_getString(USE_MDFILE_AS_MAINPAGE); bool wasEmpty = id.isEmpty(); if (wasEmpty) id = markdownFileNameToId(fileName); - if (!isExplicitPage(docs)) + switch (isExplicitPage(docs)) { - if (!mdfileAsMainPage.isEmpty() && - (fn==mdfileAsMainPage || // name reference - FileInfo(fileName.str()).absFilePath()== - FileInfo(mdfileAsMainPage.str()).absFilePath()) // file reference with path - ) - { - docs.prepend("@anchor " + id + "\\ilinebr "); - docs.prepend("@mainpage "+title+"\\ilinebr "); - } - else if (id=="mainpage" || id=="index") - { - if (title.isEmpty()) title = titleFn; - docs.prepend("@anchor " + id + "\\ilinebr "); - docs.prepend("@mainpage "+title+"\\ilinebr "); - } - else - { - if (title.isEmpty()) {title = titleFn;prepend=0;} - if (!wasEmpty) docs.prepend("@anchor " + markdownFileNameToId(fileName) + "\\ilinebr "); - docs.prepend("@page "+id+" "+title+"\\ilinebr "); - } - for (int i = 0; i < prepend; i++) docs.prepend("\n"); + case ExplicitPageResult::notExplicit: + if (!mdfileAsMainPage.isEmpty() && + (fn==mdfileAsMainPage || // name reference + FileInfo(fileName.str()).absFilePath()== + FileInfo(mdfileAsMainPage.str()).absFilePath()) // file reference with path + ) + { + docs.prepend("@anchor " + id + "\\ilinebr "); + docs.prepend("@mainpage "+title+"\\ilinebr "); + } + else if (id=="mainpage" || id=="index") + { + if (title.isEmpty()) title = titleFn; + docs.prepend("@anchor " + id + "\\ilinebr "); + docs.prepend("@mainpage "+title+"\\ilinebr "); + } + else + { + if (title.isEmpty()) {title = titleFn;prepend=0;} + if (!wasEmpty) docs.prepend("@anchor " + markdownFileNameToId(fileName) + "\\ilinebr "); + docs.prepend("@page "+id+" "+title+"\\ilinebr "); + } + for (int i = 0; i < prepend; i++) docs.prepend("\n"); + break; + case ExplicitPageResult::explicitPage: + { + // look for `@page label Title\n` and capture `label` + static const reg::Ex re(R"([\\@]page\s+(\a[\w-]*)\s*[^\n]*\n)"); + reg::Match match; + std::string s = docs.str(); + if (reg::search(s,match,re)) + { + QCString orgLabel = match[1].str(); + QCString newLabel = markdownFileNameToId(fileName); + size_t labelStartPos = match[1].position(); + size_t labelEndPos = labelStartPos+match[1].length(); + size_t lineLen = match.length(); + docs = docs.left(labelStartPos)+ // part before label + newLabel+ // new label + docs.mid(labelEndPos,lineLen-labelEndPos-1)+ // part between orgLabel and \n + "\\ilinebr @anchor "+orgLabel+"\n"+ // add original anchor + docs.right(docs.length()-match.length()); // add remainder of docs + } + } + break; + case ExplicitPageResult::explicitMainPage: + break; } int lineNr=1; diff --git a/src/markdown.h b/src/markdown.h index 9d5343c..e3625c5 100644 --- a/src/markdown.h +++ b/src/markdown.h @@ -42,6 +42,7 @@ class Markdown QCString processQuotations(const QCString &s,int refIndent); QCString processBlocks(const QCString &s,int indent); QCString isBlockCommand(const char *data,int offset,int size); + int isSpecialCommand(const char *data,int offset,int size); void findEndOfLine(const char *data,int size,int &pi,int&i,int &end); int processHtmlTagWrite(const char *data,int offset,int size,bool doWrite); int processHtmlTag(const char *data,int offset,int size); @@ -57,9 +58,10 @@ class Markdown int processLink(const char *data,int,int size); int findEmphasisChar(const char *data, int size, char c, int c_size); void processInline(const char *data,int size); - void writeMarkdownImage(const char *fmt, bool explicitTitle, + void writeMarkdownImage(const char *fmt, bool inline_img, bool explicitTitle, const QCString &title, const QCString &content, - const QCString &link, const FileDef *fd); + const QCString &link, const QCString &attributes, + const FileDef *fd); int isHeaderline(const char *data, int size, bool allowAdjustLevel); int isAtxHeader(const char *data,int size, QCString &header,QCString &id,bool allowAdjustLevel); diff --git a/src/memberdef.cpp b/src/memberdef.cpp index d0cb7da..6dd51ea 100644 --- a/src/memberdef.cpp +++ b/src/memberdef.cpp @@ -163,6 +163,7 @@ class MemberDefImpl : public DefinitionMixin<MemberDefMutable> virtual bool isTemplateSpecialization() const; virtual bool isObjCMethod() const; virtual bool isObjCProperty() const; + virtual bool isCSharpProperty() const; virtual bool isConstructor() const; virtual bool isDestructor() const; virtual bool hasOneLineInitializer() const; @@ -312,7 +313,7 @@ class MemberDefImpl : public DefinitionMixin<MemberDefMutable> virtual void incrementFlowKeyWordCount(); virtual void writeDeclaration(OutputList &ol, const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, - bool inGroup, const ClassDef *inheritFrom=0,const QCString &inheritId=QCString()) const; + bool inGroup, int indentLevel,const ClassDef *inheritFrom=0,const QCString &inheritId=QCString()) const; virtual void writeDocumentation(const MemberList *ml,int memCount,int memTotal,OutputList &ol, const QCString &scopeName,const Definition *container, bool inGroup,bool showEnumValues=FALSE,bool @@ -331,7 +332,6 @@ class MemberDefImpl : public DefinitionMixin<MemberDefMutable> virtual void writeLink(OutputList &ol, const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, bool onlyText=FALSE) const; - virtual void addToSearchIndex() const; virtual void resolveUnnamedParameters(const MemberDef *md); private: @@ -358,8 +358,6 @@ class MemberDefImpl : public DefinitionMixin<MemberDefMutable> bool _hasVisibleCallGraph() const; bool _hasVisibleCallerGraph() const; - static int s_indentLevel; - // disable copying of member defs MemberDefImpl(const MemberDefImpl &); MemberDefImpl &operator=(const MemberDefImpl &); @@ -604,6 +602,8 @@ class MemberDefAliasImpl : public DefinitionAliasMixin<MemberDef> { return getMdAlias()->isObjCMethod(); } virtual bool isObjCProperty() const { return getMdAlias()->isObjCProperty(); } + virtual bool isCSharpProperty() const + { return getMdAlias()->isCSharpProperty(); } virtual bool isConstructor() const { return getMdAlias()->isConstructor(); } virtual bool isDestructor() const @@ -767,9 +767,9 @@ class MemberDefAliasImpl : public DefinitionAliasMixin<MemberDef> virtual void writeDeclaration(OutputList &ol, const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, - bool inGroup, const ClassDef *inheritFrom=0,const QCString &inheritId=QCString()) const + bool inGroup, int indentLevel, const ClassDef *inheritFrom=0,const QCString &inheritId=QCString()) const { - getMdAlias()->writeDeclaration(ol,cd,nd,fd,gd,inGroup,inheritFrom,inheritId); + getMdAlias()->writeDeclaration(ol,cd,nd,fd,gd,inGroup,indentLevel,inheritFrom,inheritId); } virtual void writeEnumDeclaration(OutputList &typeDecl, const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd) const @@ -790,10 +790,6 @@ MemberDef *createMemberDefAlias(const Definition *newScope,const MemberDef *alia //----------------------------------------------------------------------------- -int MemberDefImpl::s_indentLevel = 0; - -//----------------------------------------------------------------------------- - static QCString addTemplateNames(const QCString &s,const QCString &n,const QCString &t) { QCString result; @@ -1826,11 +1822,14 @@ void MemberDefImpl::writeLink(OutputList &ol, } } +static std::mutex g_cachedAnonymousTypeMutex; + /*! If this member has an anonymous class/struct/union as its type, then * this method will return the ClassDef that describes this return type. */ ClassDef *MemberDefImpl::getClassDefOfAnonymousType() const { + std::lock_guard<std::mutex> lock(g_cachedAnonymousTypeMutex); //printf("%s:getClassDefOfAnonymousType() cache=%s\n",qPrint(name()), // m_impl->cachedAnonymousType?qPrint(m_impl->cachedAnonymousType->name()):"<empty>"); if (m_impl->cachedAnonymousType) return m_impl->cachedAnonymousType; @@ -2066,9 +2065,9 @@ void MemberDefImpl::_writeTemplatePrefix(OutputList &ol, const Definition *def, void MemberDefImpl::writeDeclaration(OutputList &ol, const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, - bool inGroup, const ClassDef *inheritedFrom,const QCString &inheritId) const + bool inGroup, int indentLevel, const ClassDef *inheritedFrom,const QCString &inheritId) const { - //printf("%s MemberDefImpl::writeDeclaration() inGroup=%d\n",qPrint(qualifiedName()),inGroup); + //printf("> %s MemberDefImpl::writeDeclaration() inGroup=%d\n",qPrint(qualifiedName()),inGroup); // hide enum value, since they appear already as part of the enum, unless they // are explicitly grouped. @@ -2085,8 +2084,6 @@ void MemberDefImpl::writeDeclaration(OutputList &ol, else if (getFileDef()) d = getFileDef(); } - addToSearchIndex(); - QCString cname = d->name(); QCString cdname = d->displayName(); QCString cfname = getOutputFileBase(); @@ -2131,7 +2128,7 @@ void MemberDefImpl::writeDeclaration(OutputList &ol, if (annoClassDef || m_impl->annMemb) { int j; - for (j=0;j<s_indentLevel;j++) + for (j=0;j<indentLevel;j++) { ol.writeNonBreakableSpace(3); } @@ -2173,12 +2170,12 @@ void MemberDefImpl::writeDeclaration(OutputList &ol, { int ir=i+l; //printf("<<<<<<<<<<<<<<\n"); - ol.startAnonTypeScope(s_indentLevel++); - annoClassDef->writeDeclaration(ol,m_impl->annMemb,inGroup,inheritedFrom,inheritId); + ol.startAnonTypeScope(indentLevel); + annoClassDef->writeDeclaration(ol,m_impl->annMemb,inGroup,indentLevel+1,inheritedFrom,inheritId); //printf(">>>>>>>>>>>>>> startMemberItem(2)\n"); ol.startMemberItem(anchor(),2,inheritId); int j; - for (j=0;j< s_indentLevel-1;j++) + for (j=0;j< indentLevel;j++) { ol.writeNonBreakableSpace(3); } @@ -2320,26 +2317,6 @@ void MemberDefImpl::writeDeclaration(OutputList &ol, } } - // add to index - if (isEnumerate() && isAnonymous()) - { - // don't add to index - } - else // index member - { - //static bool separateMemPages = Config_getBool(SEPARATE_MEMBER_PAGES); - //QCString cfname = getOutputFileBase(); - //QCString cfiname = d->getOutputFileBase(); - //Doxygen::indexList->addIndexItem( - // cname, // level1 - // name(), // level2 - // separateMemPages ? cfname : cfiname, // contRef - // cfname, // memRef - // anchor(), // anchor - // this); // memberdef - Doxygen::indexList->addIndexItem(d,this); - } - // *** write arguments if (!argsString().isEmpty() && !isObjCMethod()) { @@ -2356,7 +2333,7 @@ void MemberDefImpl::writeDeclaration(OutputList &ol, m_impl->annMemb, // autoBreak TRUE, // external FALSE, // keepSpaces - s_indentLevel + indentLevel ); } // *** write exceptions @@ -2428,8 +2405,8 @@ void MemberDefImpl::writeDeclaration(OutputList &ol, if (!first) { ol.docify(", "); - first=false; } + first=false; ol.docify(s.c_str()); } ol.docify("]"); @@ -2451,8 +2428,8 @@ void MemberDefImpl::writeDeclaration(OutputList &ol, if (!first) { ol.docify(", "); - first=false; } + first=false; ol.docify(s.c_str()); } ol.docify("]"); @@ -2469,7 +2446,7 @@ void MemberDefImpl::writeDeclaration(OutputList &ol, ol.endMemberItem(); if (endAnonScopeNeeded) { - ol.endAnonTypeScope(--s_indentLevel); + ol.endAnonTypeScope(indentLevel); } // write brief description @@ -2511,6 +2488,7 @@ void MemberDefImpl::writeDeclaration(OutputList &ol, ol.endMemberDeclaration(anchor(),inheritId); warnIfUndocumented(); + //printf("< %s MemberDefImpl::writeDeclaration() inGroup=%d\n",qPrint(qualifiedName()),inGroup); } bool MemberDefImpl::hasDetailedDescription() const @@ -3047,8 +3025,6 @@ void MemberDefImpl::_writeEnumValues(OutputList &ol,const Definition *container, ol.addIndexItem(fmd->name(),ciname); ol.addIndexItem(ciname,fmd->name()); - Doxygen::indexList->addIndexItem(container,fmd); - ol.startDescTableTitle(); ol.startDoxyAnchor(cfname,cname,fmd->anchor(),fmd->name(),fmd->argsString()); first=FALSE; @@ -3734,7 +3710,7 @@ static QCString simplifyTypeForTable(const QCString &s) t = match.prefix().str() + match.suffix().str(); // remove the matched part } //printf("simplifyTypeForTable(%s)->%s\n",qPrint(s),t.c_str()); - return t; + return QCString(t); } QCString MemberDefImpl::fieldType() const @@ -3946,7 +3922,6 @@ static QCString stripTrailingReturn(const QCString &trailRet) void MemberDefImpl::detectUndocumentedParams(bool hasParamCommand,bool hasReturnCommand) const { - if (!Config_getBool(WARN_NO_PARAMDOC)) return; QCString returnType = typeString(); bool isPython = getLanguage()==SrcLangExt_Python; bool isFortran = getLanguage()==SrcLangExt_Fortran; @@ -4030,7 +4005,8 @@ void MemberDefImpl::detectUndocumentedParams(bool hasParamCommand,bool hasReturn ) ) { - warn_doc_error(getDefFileName(),getDefLine(),"documented empty return type of %s", + + warn_doc_error(docFile(),docLine(),"documented empty return type of %s", qPrint(qualifiedName())); } else if ( // see if return needs to documented @@ -4058,14 +4034,14 @@ void MemberDefImpl::warnIfUndocumentedParams() const QCString returnType = typeString(); if (!m_impl->hasDocumentedParams) { - warn_doc_error(getDefFileName(),getDefLine(), + warn_doc_error(docFile(),docLine(), "parameters of member %s are not (all) documented", qPrint(qualifiedName())); } if (!m_impl->hasDocumentedReturnType && hasDocumentation() && !returnType.isEmpty()) { - warn_doc_error(getDefFileName(),getDefLine(), + warn_doc_error(docFile(),docLine(), "return type of member %s is not documented", qPrint(qualifiedName())); } @@ -4395,7 +4371,7 @@ void MemberDefImpl::writeTagFile(TextStream &tagFile) const tagFile << " <type>" << convertToXML(typeString()) << "</type>\n"; } tagFile << " <name>" << convertToXML(name()) << "</name>\n"; - tagFile << " <anchorfile>" << convertToXML(getOutputFileBase()) << Doxygen::htmlFileExtension << "</anchorfile>\n"; + tagFile << " <anchorfile>" << addHtmlExtensionIfMissing(getOutputFileBase()) << "</anchorfile>\n"; tagFile << " <anchor>" << convertToXML(anchor()) << "</anchor>\n"; QCString idStr = id(); if (!idStr.isEmpty()) @@ -4409,7 +4385,7 @@ void MemberDefImpl::writeTagFile(TextStream &tagFile) const { if (!fmd->isReference()) { - tagFile << " <enumvalue file=\"" << convertToXML(getOutputFileBase()+Doxygen::htmlFileExtension); + tagFile << " <enumvalue file=\"" << convertToXML(addHtmlExtensionIfMissing(getOutputFileBase())); tagFile << "\" anchor=\"" << convertToXML(fmd->anchor()); idStr = fmd->id(); if (!idStr.isEmpty()) @@ -4533,7 +4509,6 @@ void MemberDefImpl::writeEnumDeclaration(OutputList &typeDecl, if (isLinkableInProject() || hasDocumentedEnumValues()) { //_writeTagData(compoundType); - addToSearchIndex(); writeLink(typeDecl,cd,nd,fd,gd); } else @@ -4590,7 +4565,6 @@ void MemberDefImpl::writeEnumDeclaration(OutputList &typeDecl, MemberDefMutable *fmdm = toMemberDefMutable(fmd); if (fmdm && fmd->hasDocumentation()) // enum value has docs { - fmdm->addToSearchIndex(); fmdm->writeLink(typeDecl,cd,nd,fd,gd); } else // no docs for this enum value @@ -4732,6 +4706,12 @@ bool MemberDefImpl::isObjCProperty() const return FALSE; } +bool MemberDefImpl::isCSharpProperty() const +{ + if (getClassDef() && getClassDef()->isCSharp() && isProperty()) return TRUE; + return FALSE; +} + QCString MemberDefImpl::qualifiedName() const { if (isObjCMethod()) @@ -5812,31 +5792,6 @@ QCString MemberDefImpl::displayName(bool) const return DefinitionMixin::name(); } -void MemberDefImpl::addToSearchIndex() const -{ - // write search index info - if (Doxygen::searchIndex && isLinkableInProject()) - { - Doxygen::searchIndex->setCurrentDoc(this,anchor(),FALSE); - QCString ln=localName(),qn=qualifiedName(); - Doxygen::searchIndex->addWord(ln,TRUE); - if (ln!=qn) - { - Doxygen::searchIndex->addWord(qn,TRUE); - if (getClassDef()) - { - Doxygen::searchIndex->addWord(getClassDef()->displayName(),TRUE); - } - else if (getNamespaceDef()) - { - Doxygen::searchIndex->addWord(getNamespaceDef()->displayName(),TRUE); - } - } - } -} - - - //---------------- static void transferArgumentDocumentation(ArgumentList &decAl,ArgumentList &defAl) @@ -5881,9 +5836,12 @@ void combineDeclarationAndDefinition(MemberDefMutable *mdec,MemberDefMutable *md // mdef, mdef ? qPrint(mdef->name()) : "", // mdec, mdec ? qPrint(mdec->name()) : ""); + bool sameNumTemplateArgs = mdef->templateArguments().size()==mdec->templateArguments().size(); + ArgumentList &mdefAl = const_cast<ArgumentList&>(mdef->argumentList()); ArgumentList &mdecAl = const_cast<ArgumentList&>(mdec->argumentList()); - if (matchArguments2(mdef->getOuterScope(),mdef->getFileDef(),&mdefAl, + if (sameNumTemplateArgs && + matchArguments2(mdef->getOuterScope(),mdef->getFileDef(),&mdefAl, mdec->getOuterScope(),mdec->getFileDef(),&mdecAl, TRUE ) diff --git a/src/memberdef.h b/src/memberdef.h index a3b8293..46c2479 100644 --- a/src/memberdef.h +++ b/src/memberdef.h @@ -172,6 +172,7 @@ class MemberDef : public Definition virtual bool isTemplateSpecialization() const = 0; virtual bool isObjCMethod() const = 0; virtual bool isObjCProperty() const = 0; + virtual bool isCSharpProperty() const = 0; virtual bool isConstructor() const = 0; virtual bool isDestructor() const = 0; virtual bool hasOneLineInitializer() const = 0; @@ -280,7 +281,7 @@ class MemberDef : public Definition const std::unique_ptr<ArgumentList> &actualArgs) const = 0; virtual void writeDeclaration(OutputList &ol, const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, - bool inGroup, const ClassDef *inheritFrom=0,const QCString &inheritId=QCString()) const = 0; + bool inGroup, int indentLevel=0, const ClassDef *inheritFrom=0,const QCString &inheritId=QCString()) const = 0; virtual void writeEnumDeclaration(OutputList &typeDecl, const ClassDef *cd, const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd) const = 0; virtual void detectUndocumentedParams(bool hasParamCommand,bool hasReturnCommand) const = 0; @@ -407,7 +408,7 @@ class MemberDefMutable : public DefinitionMutable, public MemberDef //----------------------------------------------------------------------------------- virtual void findSectionsInDocumentation() = 0; - virtual void addToSearchIndex() const = 0; + //virtual void addToSearchIndex() const = 0; //----------------------------------------------------------------------------------- // --- write output ---- diff --git a/src/membergroup.cpp b/src/membergroup.cpp index 5ed1030..6cfce97 100644 --- a/src/membergroup.cpp +++ b/src/membergroup.cpp @@ -101,11 +101,11 @@ void MemberGroup::writeDeclarations(OutputList &ol, void MemberGroup::writePlainDeclarations(OutputList &ol,bool inGroup, const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, - const ClassDef *inheritedFrom,const QCString &inheritId + int indentLevel,const ClassDef *inheritedFrom,const QCString &inheritId ) const { //printf("MemberGroup::writePlainDeclarations() memberList->count()=%d\n",memberList->count()); - memberList->writePlainDeclarations(ol,inGroup,cd,nd,fd,gd,inheritedFrom,inheritId); + memberList->writePlainDeclarations(ol,inGroup,cd,nd,fd,gd,indentLevel,inheritedFrom,inheritId); } void MemberGroup::writeDocumentation(OutputList &ol,const QCString &scopeName, @@ -140,7 +140,7 @@ void MemberGroup::addGroupedInheritedMembers(OutputList &ol,const ClassDef *cd, MemberList mml(lt,MemberListContainer::Class); mml.push_back(md); mml.countDecMembers(); - mml.writePlainDeclarations(ol,false,cd,0,0,0,inheritedFrom,inheritId); + mml.writePlainDeclarations(ol,false,cd,0,0,0,0,inheritedFrom,inheritId); } } } diff --git a/src/membergroup.h b/src/membergroup.h index 7fbafaa..8fbe56c 100644 --- a/src/membergroup.h +++ b/src/membergroup.h @@ -51,7 +51,7 @@ class MemberGroup void setAnchors(); void writePlainDeclarations(OutputList &ol,bool inGroup, const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, - const ClassDef *inheritedFrom,const QCString &inheritId) const; + int indentLevel, const ClassDef *inheritedFrom,const QCString &inheritId) const; void writeDeclarations(OutputList &ol, const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, bool showInline=FALSE) const; diff --git a/src/memberlist.cpp b/src/memberlist.cpp index 989eb48..23a02df 100644 --- a/src/memberlist.cpp +++ b/src/memberlist.cpp @@ -325,8 +325,8 @@ bool MemberList::declVisible() const } void MemberList::writePlainDeclarations(OutputList &ol, bool inGroup, - const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd, - const GroupDef *gd,const ClassDef *inheritedFrom,const QCString &inheritId + const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd, const GroupDef *gd, + int indentLevel, const ClassDef *inheritedFrom,const QCString &inheritId ) const { //printf("----- writePlainDeclaration() ----\n"); @@ -372,7 +372,7 @@ void MemberList::writePlainDeclarations(OutputList &ol, bool inGroup, case MemberType_Event: { if (first) ol.startMemberList(),first=FALSE; - md->writeDeclaration(ol,cd,nd,fd,gd,inGroup,inheritedFrom,inheritId); + md->writeDeclaration(ol,cd,nd,fd,gd,inGroup,indentLevel,inheritedFrom,inheritId); break; } case MemberType_Enumeration: @@ -457,7 +457,7 @@ void MemberList::writePlainDeclarations(OutputList &ol, bool inGroup, ol.startMemberList(); first=FALSE; } - md->writeDeclaration(ol,cd,nd,fd,gd,inGroup,inheritedFrom,inheritId); + md->writeDeclaration(ol,cd,nd,fd,gd,inGroup,indentLevel,inheritedFrom,inheritId); break; } case MemberType_EnumValue: @@ -466,7 +466,7 @@ void MemberList::writePlainDeclarations(OutputList &ol, bool inGroup, { //printf("EnumValue!\n"); if (first) ol.startMemberList(),first=FALSE; - md->writeDeclaration(ol,cd,nd,fd,gd,true,inheritedFrom,inheritId); + md->writeDeclaration(ol,cd,nd,fd,gd,true,indentLevel,inheritedFrom,inheritId); } } break; @@ -492,7 +492,7 @@ void MemberList::writePlainDeclarations(OutputList &ol, bool inGroup, ol.startMemberList(); first=FALSE; } - md->writeDeclaration(ol,cd,nd,fd,gd,inGroup); + md->writeDeclaration(ol,cd,nd,fd,gd,inGroup,indentLevel); } if (mdm) mdm->setFromAnonymousScope(TRUE); } @@ -608,7 +608,7 @@ void MemberList::writeDeclarations(OutputList &ol, } else { - writePlainDeclarations(ol,inGroup,cd,nd,fd,gd,inheritedFrom,inheritId); + writePlainDeclarations(ol,inGroup,cd,nd,fd,gd,0,0,inheritId); } //printf("memberGroupList=%p\n",memberGroupList); @@ -635,7 +635,7 @@ void MemberList::writeDeclarations(OutputList &ol, ol.startMemberGroup(); } //printf("--- mg->writePlainDeclarations ---\n"); - mg->writePlainDeclarations(ol,inGroup,cd,nd,fd,gd,inheritedFrom,inheritId); + mg->writePlainDeclarations(ol,inGroup,cd,nd,fd,gd,0,inheritedFrom,inheritId); if (inheritId.isEmpty()) { ol.endMemberGroup(hasHeader); diff --git a/src/memberlist.h b/src/memberlist.h index 426739d..2f207c6 100644 --- a/src/memberlist.h +++ b/src/memberlist.h @@ -97,7 +97,7 @@ class MemberList : public MemberVector int countInheritableMembers(const ClassDef *inheritedFrom) const; void writePlainDeclarations(OutputList &ol,bool inGroup, const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd, const GroupDef *gd, - const ClassDef *inheritedFrom,const QCString &inheritId) const; + int indentLevel,const ClassDef *inheritedFrom,const QCString &inheritId) const; void writeDeclarations(OutputList &ol, const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, const QCString &title,const QCString &subtitle, diff --git a/src/message.cpp b/src/message.cpp index a99ad21..ad8076d 100644 --- a/src/message.cpp +++ b/src/message.cpp @@ -22,43 +22,41 @@ #include <mutex> -static QCString outputFormat; -static const char *warning_str = "warning: "; -static const char *error_str = "error: "; - -static FILE *warnFile = stderr; - -enum warn_as_error -{ - WARN_NO, - WARN_YES, - FAIL_ON_WARNINGS, -}; -static warn_as_error warnBehavior = WARN_NO; -static bool warnStat = false; - -static std::mutex g_mutex; +// globals +static QCString g_warnFormat; +static const char * g_warningStr = "warning: "; +static const char * g_errorStr = "error: "; +static FILE * g_warnFile = stderr; +static WARN_AS_ERROR_t g_warnBehavior = WARN_AS_ERROR_t::NO; +static bool g_warnStat = false; +static std::mutex g_mutex; void initWarningFormat() { - outputFormat = Config_getString(WARN_FORMAT); + g_warnFormat = Config_getString(WARN_FORMAT); + QCString logFile = Config_getString(WARN_LOGFILE); - if (!Config_getString(WARN_LOGFILE).isEmpty()) + if (!logFile.isEmpty()) { - warnFile = Portable::fopen(Config_getString(WARN_LOGFILE).data(),"w"); + if (logFile == "-") + { + g_warnFile = stdout; + } + else if (!(g_warnFile = Portable::fopen(logFile,"w"))) + { + // point it to something valid, because warn() relies on it + g_warnFile = stderr; + err("Cannot open '%s' for writing, redirecting 'WARN_LOGFILE' output to 'stderr'\n",logFile.data()); + } } - if (!warnFile) // point it to something valid, because warn() relies on it + else { - warnFile = stderr; + g_warnFile = stderr; } - - QCString warnStr = Config_getEnum(WARN_AS_ERROR).upper(); - if (warnStr =="NO") warnBehavior=WARN_NO; - else if (warnStr =="YES") warnBehavior=WARN_YES; - else if (warnStr =="FAIL_ON_WARNINGS") warnBehavior=FAIL_ON_WARNINGS; - if (warnBehavior == WARN_YES) + g_warnBehavior = Config_getEnum(WARN_AS_ERROR); + if (g_warnBehavior != WARN_AS_ERROR_t::NO) { - warning_str = error_str; + g_warningStr = g_errorStr; } } @@ -91,7 +89,7 @@ static void format_warn(const QCString &file,int line,const QCString &text) substitute( substitute( substitute( - outputFormat, + g_warnFormat, "$file",fileSubst ), "$line",lineSubst @@ -100,7 +98,7 @@ static void format_warn(const QCString &file,int line,const QCString &text) ), "$text",textSubst ); - if (warnBehavior == WARN_YES) + if (g_warnBehavior == WARN_AS_ERROR_t::YES) { msgText += " (warning treated as error, aborting now)"; } @@ -109,27 +107,27 @@ static void format_warn(const QCString &file,int line,const QCString &text) { std::unique_lock<std::mutex> lock(g_mutex); // print resulting message - fwrite(msgText.data(),1,msgText.length(),warnFile); + fwrite(msgText.data(),1,msgText.length(),g_warnFile); } - if (warnBehavior == WARN_YES) + if (g_warnBehavior == WARN_AS_ERROR_t::YES) { exit(1); } - warnStat = true; + g_warnStat = true; } static void handle_warn_as_error() { - if (warnBehavior == WARN_YES) + if (g_warnBehavior == WARN_AS_ERROR_t::YES) { { std::unique_lock<std::mutex> lock(g_mutex); QCString msgText = " (warning treated as error, aborting now)\n"; - fwrite(msgText.data(),1,msgText.length(),warnFile); + fwrite(msgText.data(),1,msgText.length(),g_warnFile); } exit(1); } - warnStat = true; + g_warnStat = true; } static void do_warn(bool enabled, const QCString &file, int line, const char *prefix, const char *fmt, va_list args) @@ -165,26 +163,26 @@ void warn(const QCString &file,int line,const char *fmt, ...) { va_list args; va_start(args, fmt); - do_warn(Config_getBool(WARNINGS), file, line, warning_str, fmt, args); + do_warn(Config_getBool(WARNINGS), file, line, g_warningStr, fmt, args); va_end(args); } void va_warn(const QCString &file,int line,const char *fmt,va_list args) { - do_warn(Config_getBool(WARNINGS), file, line, warning_str, fmt, args); + do_warn(Config_getBool(WARNINGS), file, line, g_warningStr, fmt, args); } void warn_simple(const QCString &file,int line,const char *text) { if (!Config_getBool(WARNINGS)) return; // warning type disabled - format_warn(file,line,QCString(warning_str) + text); + format_warn(file,line,QCString(g_warningStr) + text); } void warn_undoc(const QCString &file,int line,const char *fmt, ...) { va_list args; va_start(args, fmt); - do_warn(Config_getBool(WARN_IF_UNDOCUMENTED), file, line, warning_str, fmt, args); + do_warn(Config_getBool(WARN_IF_UNDOCUMENTED), file, line, g_warningStr, fmt, args); va_end(args); } @@ -192,7 +190,7 @@ void warn_incomplete_doc(const QCString &file,int line,const char *fmt, ...) { va_list args; va_start(args, fmt); - do_warn(Config_getBool(WARN_IF_INCOMPLETE_DOC), file, line, warning_str, fmt, args); + do_warn(Config_getBool(WARN_IF_INCOMPLETE_DOC), file, line, g_warningStr, fmt, args); va_end(args); } @@ -200,7 +198,7 @@ void warn_doc_error(const QCString &file,int line,const char *fmt, ...) { va_list args; va_start(args, fmt); - do_warn(Config_getBool(WARN_IF_DOC_ERROR), file, line, warning_str, fmt, args); + do_warn(Config_getBool(WARN_IF_DOC_ERROR), file, line, g_warningStr, fmt, args); va_end(args); } @@ -208,7 +206,7 @@ void warn_uncond(const char *fmt, ...) { va_list args; va_start(args, fmt); - vfprintf(warnFile, (QCString(warning_str) + fmt).data(), args); + vfprintf(g_warnFile, (QCString(g_warningStr) + fmt).data(), args); va_end(args); handle_warn_as_error(); } @@ -217,7 +215,7 @@ void err(const char *fmt, ...) { va_list args; va_start(args, fmt); - vfprintf(warnFile, (QCString(error_str) + fmt).data(), args); + vfprintf(g_warnFile, (QCString(g_errorStr) + fmt).data(), args); va_end(args); handle_warn_as_error(); } @@ -226,7 +224,7 @@ extern void err_full(const QCString &file,int line,const char *fmt, ...) { va_list args; va_start(args, fmt); - do_warn(TRUE, file, line, error_str, fmt, args); + do_warn(TRUE, file, line, g_errorStr, fmt, args); va_end(args); } @@ -236,12 +234,12 @@ void term(const char *fmt, ...) std::unique_lock<std::mutex> lock(g_mutex); va_list args; va_start(args, fmt); - vfprintf(warnFile, (QCString(error_str) + fmt).data(), args); + vfprintf(g_warnFile, (QCString(g_errorStr) + fmt).data(), args); va_end(args); - if (warnFile != stderr) + if (g_warnFile != stderr) { - for (int i = 0; i < (int)strlen(error_str); i++) fprintf(warnFile, " "); - fprintf(warnFile, "%s\n", "Exiting..."); + for (int i = 0; i < (int)strlen(g_errorStr); i++) fprintf(g_warnFile, " "); + fprintf(g_warnFile, "%s\n", "Exiting..."); } } exit(1); @@ -249,7 +247,7 @@ void term(const char *fmt, ...) void warn_flush() { - fflush(warnFile); + fflush(g_warnFile); } @@ -283,7 +281,7 @@ void printlex(int dbg, bool enter, const char *lexName, const char *fileName) extern void finishWarnExit() { - if (warnStat && warnBehavior == FAIL_ON_WARNINGS) + if (g_warnStat && g_warnBehavior == WARN_AS_ERROR_t::FAIL_ON_WARNINGS) { exit(1); } diff --git a/src/msc.cpp b/src/msc.cpp index a9db9d8..fff8ad5 100644 --- a/src/msc.cpp +++ b/src/msc.cpp @@ -73,7 +73,7 @@ static bool convertMapFile(TextStream &t,const QCString &mapName,const QCString std::unique_ptr<IDocParser> parser { createDocParser() }; std::unique_ptr<DocRef> df { createRef( *parser.get(), url, context ) }; t << externalRef(relPath,df->ref(),TRUE); - if (!df->file().isEmpty()) t << df->file() << Doxygen::htmlFileExtension; + if (!df->file().isEmpty()) t << addHtmlExtensionIfMissing(df->file()); if (!df->anchor().isEmpty()) t << "#" << df->anchor(); } else diff --git a/src/namespacedef.cpp b/src/namespacedef.cpp index fec3275..f8539c0 100644 --- a/src/namespacedef.cpp +++ b/src/namespacedef.cpp @@ -558,7 +558,7 @@ void NamespaceDefImpl::writeTagFile(TextStream &tagFile) { tagFile << " <compound kind=\"namespace\">\n"; tagFile << " <name>" << convertToXML(name()) << "</name>\n"; - tagFile << " <filename>" << convertToXML(getOutputFileBase()) << Doxygen::htmlFileExtension << "</filename>\n"; + tagFile << " <filename>" << addHtmlExtensionIfMissing(getOutputFileBase()) << "</filename>\n"; QCString idStr = id(); if (!idStr.isEmpty()) { @@ -945,13 +945,12 @@ void NamespaceDefImpl::writeDocumentation(OutputList &ol) endTitle(ol,getOutputFileBase(),displayName()); ol.startContents(); - if (Doxygen::searchIndex) - { - Doxygen::searchIndex->setCurrentDoc(this,anchor(),FALSE); - Doxygen::searchIndex->addWord(localName(),TRUE); - } - - Doxygen::indexList->addIndexItem(this,0); + //if (Doxygen::searchIndex) + //{ + // Doxygen::searchIndex->setCurrentDoc(this,anchor(),FALSE); + // Doxygen::searchIndex->addWord(localName(),TRUE); + //} + //Doxygen::indexList->addIndexItem(this,0); //---------------------------------------- start flexible part ------------------------------- @@ -1138,7 +1137,7 @@ void NamespaceDefImpl::writeQuickMemberLinks(OutputList &ol,const MemberDef *cur ol.writeString("<a class=\"navtab\" "); ol.writeString("href=\""); if (createSubDirs) ol.writeString("../../"); - ol.writeString(md->getOutputFileBase()+Doxygen::htmlFileExtension+"#"+md->anchor()); + ol.writeString(addHtmlExtensionIfMissing(md->getOutputFileBase())+"#"+md->anchor()); ol.writeString("\">"); ol.writeString(convertToHtml(md->localName())); ol.writeString("</a>"); diff --git a/src/outputgen.h b/src/outputgen.h index d7f8f15..1f67a76 100644 --- a/src/outputgen.h +++ b/src/outputgen.h @@ -96,9 +96,10 @@ class CodeOutputInterface * \param file The file part of the URL pointing to the docs. * \param anchor The anchor part of the URL pointing to the docs. * \param lineNumber The line number to write + * \param writeLineAnchor Indicates if an anchor for the line number needs to be written */ virtual void writeLineNumber(const QCString &ref,const QCString &file, - const QCString &anchor,int lineNumber) = 0; + const QCString &anchor,int lineNumber, bool writeLineAnchor) = 0; /*! Writes a tool tip definition * \param id unique identifier for the tooltip diff --git a/src/outputlist.cpp b/src/outputlist.cpp index d556375..3175a76 100644 --- a/src/outputlist.cpp +++ b/src/outputlist.cpp @@ -174,7 +174,6 @@ void OutputList::writeDoc(DocRoot *root,const Definition *ctx,const MemberDef *m // ctx?qPrint(ctx->getDefFileExtension()):"<null>"); if (og->isEnabled()) og->writeDoc(root,ctx,md,m_id); } - VhdlDocGen::setFlowMember(0); } void OutputList::parseText(const QCString &textStr) diff --git a/src/outputlist.h b/src/outputlist.h index c7e0fd4..267a717 100644 --- a/src/outputlist.h +++ b/src/outputlist.h @@ -247,8 +247,8 @@ class OutputList : public OutputDocInterface void endCodeLine() { forall(&OutputGenerator::endCodeLine); } void writeLineNumber(const QCString &ref,const QCString &file,const QCString &anchor, - int lineNumber) - { forall(&OutputGenerator::writeLineNumber,ref,file,anchor,lineNumber); } + int lineNumber, bool writeLineAnchor) + { forall(&OutputGenerator::writeLineNumber,ref,file,anchor,lineNumber,writeLineAnchor); } void startEmphasis() { forall(&OutputGenerator::startEmphasis); } void endEmphasis() diff --git a/src/pagedef.cpp b/src/pagedef.cpp index 810591e..701b769 100644 --- a/src/pagedef.cpp +++ b/src/pagedef.cpp @@ -162,7 +162,7 @@ void PageDefImpl::writeTagFile(TextStream &tagFile) tagFile << " <compound kind=\"page\">\n"; tagFile << " <name>" << name() << "</name>\n"; tagFile << " <title>" << convertToXML(title()) << "</title>\n"; - tagFile << " <filename>" << convertToXML(getOutputFileBase())<< Doxygen::htmlFileExtension << "</filename>\n"; + tagFile << " <filename>" << addHtmlExtensionIfMissing(getOutputFileBase()) << "</filename>\n"; writeDocAnchorsToTagFile(tagFile); tagFile << " </compound>\n"; } @@ -287,14 +287,12 @@ void PageDefImpl::writeDocumentation(OutputList &ol) ol.popGeneratorState(); //1.} - - Doxygen::indexList->addIndexItem(this,0,QCString(),filterTitle(title().str())); } void PageDefImpl::writePageDocumentation(OutputList &ol) const { ol.startTextBlock(); - QCString docStr = documentation()+inbodyDocumentation(); + QCString docStr = (briefDescription().isEmpty()?"":briefDescription()+"\n\n")+documentation()+inbodyDocumentation(); if (hasBriefDescription() && !SectionManager::instance().find(name())) { ol.pushGeneratorState(); diff --git a/src/perlmodgen.cpp b/src/perlmodgen.cpp index 002cc57..5503081 100644 --- a/src/perlmodgen.cpp +++ b/src/perlmodgen.cpp @@ -649,9 +649,16 @@ void PerlModDocVisitor::visit(DocStyleChange *s) case DocStyleChange::Superscript: style = "superscript"; break; case DocStyleChange::Center: style = "center"; break; case DocStyleChange::Small: style = "small"; break; + case DocStyleChange::Cite: style = "cite"; break; case DocStyleChange::Preformatted: style = "preformatted"; break; case DocStyleChange::Div: style = "div"; break; case DocStyleChange::Span: style = "span"; break; + case DocStyleChange::Details: /* emulation of the <details> tag */ + style = "details"; + break; + case DocStyleChange::Summary: /* emulation of the <summary> tag inside a <details> tag */ + style = "summary"; + break; } openItem("style"); @@ -672,6 +679,8 @@ void PerlModDocVisitor::visit(DocVerbatim *s) m_output.add("</programlisting>"); return; #endif + case DocVerbatim::JavaDocCode: + case DocVerbatim::JavaDocLiteral: case DocVerbatim::Verbatim: type = "preformatted"; break; case DocVerbatim::HtmlOnly: type = "htmlonly"; break; case DocVerbatim::RtfOnly: type = "rtfonly"; break; @@ -950,7 +959,17 @@ void PerlModDocVisitor::visitPost(DocHtmlList *) closeItem(); } -void PerlModDocVisitor::visitPre(DocHtmlListItem *) { openSubBlock(); } +void PerlModDocVisitor::visitPre(DocHtmlListItem *l) +{ + for (const auto &opt : l->attribs()) + { + if (opt.name=="value") + { + m_output.addFieldQuotedString("item_value", qPrint(opt.value)); + } + } + openSubBlock(); +} void PerlModDocVisitor::visitPost(DocHtmlListItem *) { closeSubBlock(); } //void PerlModDocVisitor::visitPre(DocHtmlPre *) diff --git a/src/plantuml.cpp b/src/plantuml.cpp index 2e7f04e..fed8b67 100644 --- a/src/plantuml.cpp +++ b/src/plantuml.cpp @@ -90,10 +90,6 @@ QCString PlantumlManager::writePlantUMLSource(const QCString &outDirArg,const QC void PlantumlManager::generatePlantUMLOutput(const QCString &baseName,const QCString &outDir,OutputFormat format) { - QCString plantumlJarPath = Config_getString(PLANTUML_JAR_PATH); - QCString plantumlConfigFile = Config_getString(PLANTUML_CFG_FILE); - QCString dotPath = Config_getString(DOT_PATH); - QCString imgName = baseName; // The basename contains path, we need to strip the path from the filename in order // to create the image file name which should be included in the index.qhp (Qt help index file). @@ -171,7 +167,7 @@ static void runPlantumlContent(const PlantumlManager::FilesMap &plantumlFiles, } } if (!pumlIncludePathList.empty()) pumlArgs += "\" "; - pumlArgs += "-Djava.awt.headless=true -jar \""+plantumlJarPath+"plantuml.jar\" "; + pumlArgs += "-Djava.awt.headless=true -jar \""+plantumlJarPath+"\" "; if (!plantumlConfigFile.isEmpty()) { pumlArgs += "-config \""; @@ -249,7 +245,7 @@ static void runPlantumlContent(const PlantumlManager::FilesMap &plantumlFiles, Portable::sysTimerStart(); if ((exitCode=Portable::system(pumlExe.data(),pumlArguments.data(),TRUE))!=0) { - err_full(nb.srcFile,nb.srcLine,"Problems running PlantUML. Verify that the command 'java -jar \"%splantuml.jar\" -h' works from the command line. Exit code: %d\n", + err_full(nb.srcFile,nb.srcLine,"Problems running PlantUML. Verify that the command 'java -jar \"%s\" -h' works from the command line. Exit code: %d\n", plantumlJarPath.data(),exitCode); } Portable::sysTimerStop(); @@ -18,6 +18,10 @@ %option extra-type="struct preYY_state *" %top{ #include <stdint.h> +// forward declare yyscan_t to improve type safety +#define YY_TYPEDEF_YY_SCANNER_T +struct yyguts_t; +typedef yyguts_t *yyscan_t; } %{ @@ -73,9 +77,9 @@ static const char *stateToString(int state); #endif -struct CondCtx +struct preYY_CondCtx { - CondCtx(int line,QCString id,bool b) + preYY_CondCtx(int line,QCString id,bool b) : lineNr(line),sectionId(id), skip(b) {} int lineNr; QCString sectionId; @@ -249,7 +253,7 @@ struct preYY_state int yyLineNr = 1; int yyMLines = 1; int yyColNr = 1; - QCString yyFileName; + QCString fileName; FileDef *yyFileDef = 0; FileDef *inputFileDef = 0; int ifcount = 0; @@ -268,6 +272,7 @@ struct preYY_state BufStr *outputBuf = 0; int roundCount = 0; bool quoteArg = false; + bool idStart = false; int findDefArgContext = 0; bool expectGuard = false; QCString guardName; @@ -276,6 +281,7 @@ struct preYY_state QCString guardExpr; int curlyCount = 0; bool nospaces = false; // add extra spaces during macro expansion + int javaBlock = 0; bool macroExpansion = false; // from the configuration bool expandOnlyPredef = false; // from the configuration @@ -297,7 +303,7 @@ struct preYY_state StringVector pathList; IntMap argMap; BoolStack levelGuard; - std::stack< std::unique_ptr<CondCtx> > condStack; + std::stack< std::unique_ptr<preYY_CondCtx> > condStack; std::deque< std::unique_ptr<FileState> > includeStack; std::unordered_map<std::string,Define*> expandedDict; StringUnorderedSet expanded; @@ -340,6 +346,10 @@ static Define * isDefined(yyscan_t yyscanner,const QCString &name); #undef YY_INPUT #define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); +// otherwise the filename would be the name of the converted file (*.cpp instead of *.l) +static inline const char *getLexerFILE() {return __FILE__;} +#include "doxygen_lex.h" + /* ----------------------------------------------------------------- */ %} @@ -385,13 +395,12 @@ WSopt [ \t\r]* %x DefineArg %x DefineText %x SkipCPPBlock -%x Ifdef -%x Ifndef %x SkipCComment %x ArgCopyCComment %x CopyCComment %x SkipVerbatim %x SkipCPPComment +%x JavaDocVerbatimCode %x RemoveCComment %x RemoveCPPComment %x Guard @@ -422,7 +431,7 @@ WSopt [ \t\r]* BEGIN(Command); } <Start>^("%top{"|"%{") { - if (getLanguageFromFileName(yyextra->yyFileName)!=SrcLangExt_Lex) REJECT + if (getLanguageFromFileName(yyextra->fileName)!=SrcLangExt_Lex) REJECT outputArray(yyscanner,yytext,yyleng); BEGIN(LexCopyLine); } @@ -471,7 +480,7 @@ WSopt [ \t\r]* BEGIN(CopyLine); } } -<CopyLine,LexCopyLine>"extern"{BN}{0,80}"\"C\""*{BN}{0,80}"{" { +<CopyLine,LexCopyLine>"extern"{BN}*"\""[^\"]+"\""{BN}*("{")? { QCString text=yytext; yyextra->yyLineNr+=text.contains('\n'); outputArray(yyscanner,yytext,yyleng); @@ -509,13 +518,13 @@ WSopt [ \t\r]* outputArray(yyscanner,yytext,yyleng); } <CopyLine,LexCopyLine>@\" { - if (getLanguageFromFileName(yyextra->yyFileName)!=SrcLangExt_CSharp) REJECT; + if (getLanguageFromFileName(yyextra->fileName)!=SrcLangExt_CSharp) REJECT; outputArray(yyscanner,yytext,yyleng); BEGIN( CopyStringCs ); } <CopyLine,LexCopyLine>\" { outputChar(yyscanner,*yytext); - if (getLanguageFromFileName(yyextra->yyFileName)!=SrcLangExt_Fortran) + if (getLanguageFromFileName(yyextra->fileName)!=SrcLangExt_Fortran) { BEGIN( CopyString ); } @@ -525,7 +534,7 @@ WSopt [ \t\r]* } } <CopyLine,LexCopyLine>\' { - if (getLanguageFromFileName(yyextra->yyFileName)!=SrcLangExt_Fortran) REJECT; + if (getLanguageFromFileName(yyextra->fileName)!=SrcLangExt_Fortran) REJECT; outputChar(yyscanner,*yytext); BEGIN( CopyStringFtn ); } @@ -633,7 +642,7 @@ WSopt [ \t\r]* } } <CopyLine,LexCopyLine>"\\"\r?/\n { // strip line continuation characters - if (getLanguageFromFileName(yyextra->yyFileName)==SrcLangExt_Fortran) outputChar(yyscanner,*yytext); + if (getLanguageFromFileName(yyextra->fileName)==SrcLangExt_Fortran) outputChar(yyscanner,*yytext); } <CopyLine,LexCopyLine>\\. { outputArray(yyscanner,yytext,(int)yyleng); @@ -688,7 +697,7 @@ WSopt [ \t\r]* BEGIN(ReadString); } <FindDefineArgs>' { - if (getLanguageFromFileName(yyextra->yyFileName)!=SrcLangExt_Fortran) REJECT; + if (getLanguageFromFileName(yyextra->fileName)!=SrcLangExt_Fortran) REJECT; yyextra->defArgsStr+=*yytext; BEGIN(ReadString); } @@ -723,7 +732,7 @@ WSopt [ \t\r]* BEGIN(FindDefineArgs); } <ReadString>"'" { - if (getLanguageFromFileName(yyextra->yyFileName)!=SrcLangExt_Fortran) REJECT; + if (getLanguageFromFileName(yyextra->fileName)!=SrcLangExt_Fortran) REJECT; yyextra->defArgsStr+=*yytext; BEGIN(FindDefineArgs); } @@ -862,6 +871,16 @@ WSopt [ \t\r]* <Guard>"defined"/{B}+ { BEGIN(DefinedExpr1); } +<Guard>"true"/{B}|{B}*[\r]?\n { yyextra->guardExpr+="1L"; } +<Guard>"false"/{B}|{B}*[\r]?\n { yyextra->guardExpr+="0L"; } +<Guard>"not"/{B} { yyextra->guardExpr+='!'; } +<Guard>"not_eq"/{B} { yyextra->guardExpr+="!="; } +<Guard>"and"/{B} { yyextra->guardExpr+="&&"; } +<Guard>"or"/{B} { yyextra->guardExpr+="||"; } +<Guard>"bitand"/{B} { yyextra->guardExpr+="&"; } +<Guard>"bitor"/{B} { yyextra->guardExpr+="|"; } +<Guard>"xor"/{B} { yyextra->guardExpr+="^"; } +<Guard>"compl"/{B} { yyextra->guardExpr+="~"; } <Guard>{ID} { yyextra->guardExpr+=yytext; } <Guard>"@" { yyextra->guardExpr+="@@"; } <Guard>. { yyextra->guardExpr+=*yytext; } @@ -1223,11 +1242,11 @@ WSopt [ \t\r]* BEGIN(SkipVerbatim); } } -<SkipCComment>[\\@][\\@]("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"docbookonly"|"rtfonly"|"manonly"|"dot"|"code"("{"[^}]*"}")?){BN}+ { +<SkipCComment>[\\@][\\@]("verbatim"|"iliteral"|"latexonly"|"htmlonly"|"xmlonly"|"docbookonly"|"rtfonly"|"manonly"|"dot"|"code"("{"[^}]*"}")?){BN}+ { outputArray(yyscanner,yytext,yyleng); yyextra->yyLineNr+=QCString(yytext).contains('\n'); } -<SkipCComment>[\\@]("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"docbookonly"|"rtfonly"|"manonly"|"dot"|"code"("{"[^}]*"}")?){BN}+ { +<SkipCComment>[\\@]("verbatim"|"iliteral"|"latexonly"|"htmlonly"|"xmlonly"|"docbookonly"|"rtfonly"|"manonly"|"dot"|"code"("{"[^}]*"}")?){BN}+ { outputArray(yyscanner,yytext,yyleng); yyextra->yyLineNr+=QCString(yytext).contains('\n'); yyextra->fenceSize=0; @@ -1244,6 +1263,21 @@ WSopt [ \t\r]* } BEGIN(SkipVerbatim); } +<SkipCond>[\\@][\\@]"cond"[ \t]+ {}// escaped cond command +<SkipCond>[\\@]"cond"[ \t]+ { // cond command in a skipped cond section, this section has to be skipped as well + // but has to be recorded to match the endcond command + startCondSection(yyscanner," "); + } +<SkipCComment>"{"[ \t]*"@code"/[ \t\n] { + outputArray(yyscanner,"@iliteral{code}",15); + yyextra->javaBlock=1; + BEGIN(JavaDocVerbatimCode); + } +<SkipCComment>"{"[ \t]*"@literal"/[ \t\n] { + outputArray(yyscanner,"@iliteral",9); + yyextra->javaBlock=1; + BEGIN(JavaDocVerbatimCode); + } <SkipCComment,SkipCPPComment>[\\@][\\@]"cond"[ \t]+ { // escaped @cond outputArray(yyscanner,yytext,yyleng); } @@ -1346,7 +1380,7 @@ WSopt [ \t\r]* BEGIN(yyextra->condCtx); } } -<SkipVerbatim>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endrtfonly"|"endmanonly"|"enddot"|"endcode"|"f$"|"f]"|"f}""f}") { /* end of verbatim block */ +<SkipVerbatim>[\\@]("endverbatim"|"endiliteral"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endrtfonly"|"endmanonly"|"enddot"|"endcode"|"f$"|"f]"|"f}""f}") { /* end of verbatim block */ outputArray(yyscanner,yytext,yyleng); if (yytext[1]=='f' && yyextra->blockName=="f") { @@ -1374,7 +1408,43 @@ WSopt [ \t\r]* <SkipVerbatim>{CCE}|{CCS} { outputArray(yyscanner,yytext,yyleng); } -<SkipCComment,SkipVerbatim>[^*\\@\x06~`\n\/]+ { +<JavaDocVerbatimCode>"{" { + if (yyextra->javaBlock==0) + { + REJECT; + } + else + { + yyextra->javaBlock++; + outputArray(yyscanner,yytext,(int)yyleng); + } + } +<JavaDocVerbatimCode>"}" { + if (yyextra->javaBlock==0) + { + REJECT; + } + else + { + yyextra->javaBlock--; + if (yyextra->javaBlock==0) + { + outputArray(yyscanner," @endiliteral ",14); + BEGIN(SkipCComment); + } + else + { + outputArray(yyscanner,yytext,(int)yyleng); + } + } + } +<JavaDocVerbatimCode>\n { /* new line in verbatim block */ + outputArray(yyscanner,yytext,(int)yyleng); + } +<JavaDocVerbatimCode>. { /* any other character */ + outputArray(yyscanner,yytext,(int)yyleng); + } +<SkipCComment,SkipVerbatim>[^{*\\@\x06~`\n\/]+ { outputArray(yyscanner,yytext,yyleng); } <SkipCComment,SkipVerbatim>\n { @@ -1446,6 +1516,7 @@ WSopt [ \t\r]* <DefineText>"#"/{IDSTART} { outputChar(yyscanner,' '); yyextra->quoteArg=TRUE; + yyextra->idStart=true; yyextra->defLitText+=yytext; } <DefineText,CopyCComment>{ID} { @@ -1466,6 +1537,12 @@ WSopt [ \t\r]* } else { + if (yyextra->idStart) + { + warn(yyextra->fileName,yyextra->yyLineNr, + "'#' is not followed by a macro parameter '%s': '%s'", + qPrint(yyextra->defName),qPrint(yyextra->defLitText.stripWhiteSpace())); + } yyextra->defText+=yytext; } } @@ -1478,6 +1555,7 @@ WSopt [ \t\r]* yyextra->defText+="\""; } yyextra->quoteArg=FALSE; + yyextra->idStart=false; } <CopyCComment>. { yyextra->defLitText+=yytext; @@ -1495,19 +1573,19 @@ WSopt [ \t\r]* yyextra->defText = yyextra->defText.stripWhiteSpace(); if (yyextra->defText.startsWith("##")) { - warn(yyextra->yyFileName,yyextra->yyLineNr, + warn(yyextra->fileName,yyextra->yyLineNr, "'##' cannot occur at the beginning of a macro definition '%s': '%s'", qPrint(yyextra->defName),qPrint(yyextra->defLitText.stripWhiteSpace())); } else if (yyextra->defText.endsWith("##")) { - warn(yyextra->yyFileName,yyextra->yyLineNr, + warn(yyextra->fileName,yyextra->yyLineNr, "'##' cannot occur at the end of a macro definition '%s': '%s'", qPrint(yyextra->defName),qPrint(yyextra->defLitText.stripWhiteSpace())); } else if (yyextra->defText.endsWith("#")) { - warn(yyextra->yyFileName,yyextra->yyLineNr, + warn(yyextra->fileName,yyextra->yyLineNr, "expected formal parameter after # in macro definition '%s': '%s'", qPrint(yyextra->defName),qPrint(yyextra->defLitText.stripWhiteSpace())); } @@ -1541,7 +1619,7 @@ WSopt [ \t\r]* def->name = yyextra->defName; def->definition = yyextra->defText.stripWhiteSpace(); def->nargs = yyextra->defArgs; - def->fileName = yyextra->yyFileName; + def->fileName = yyextra->fileName; def->lineNr = yyextra->yyLineNr-yyextra->yyMLines; def->columnNr = yyextra->yyColNr; } @@ -1629,9 +1707,9 @@ WSopt [ \t\r]* } else { - QCString toFileName = yyextra->yyFileName; + QCString toFileName = yyextra->fileName; const std::unique_ptr<FileState> &fs=yyextra->includeStack.back(); - //fileDefineCache->merge(yyextra->yyFileName,fs->fileName); + //fileDefineCache->merge(yyextra->fileName,fs->fileName); YY_BUFFER_STATE oldBuf = YY_CURRENT_BUFFER; yy_switch_to_buffer( fs->bufState, yyscanner ); yy_delete_buffer( oldBuf, yyscanner ); @@ -1641,12 +1719,12 @@ WSopt [ \t\r]* yyextra->inputBufPos = fs->oldFileBufPos; yyextra->curlyCount = fs->curlyCount; setFileName(yyscanner,fs->fileName); - DBG_CTX((stderr,"######## FileName %s\n",qPrint(yyextra->yyFileName))); + DBG_CTX((stderr,"######## FileName %s\n",qPrint(yyextra->fileName))); // Deal with file changes due to // #include's within { .. } blocks - QCString lineStr(15+yyextra->yyFileName.length()); - lineStr.sprintf("# %d \"%s\" 2",yyextra->yyLineNr,qPrint(yyextra->yyFileName)); + QCString lineStr(15+yyextra->fileName.length()); + lineStr.sprintf("# %d \"%s\" 2",yyextra->yyLineNr,qPrint(yyextra->fileName)); outputString(yyscanner,lineStr); yyextra->includeStack.pop_back(); @@ -1660,7 +1738,7 @@ WSopt [ \t\r]* if (!g_defineManager.alreadyProcessed(toFileName.str())) { // now that the file is completely processed, prevent it from processing it again - g_defineManager.addInclude(yyextra->yyFileName.str(),toFileName.str()); + g_defineManager.addInclude(yyextra->fileName.str(),toFileName.str()); g_defineManager.store(toFileName.str(),yyextra->localDefines); } else @@ -1708,7 +1786,7 @@ WSopt [ \t\r]* } } <*>{CPPC}[/!]? { - if (YY_START==SkipVerbatim || YY_START==SkipCond || getLanguageFromFileName(yyextra->yyFileName)==SrcLangExt_Fortran) + if (YY_START==SkipVerbatim || YY_START==SkipCond || getLanguageFromFileName(yyextra->fileName)==SrcLangExt_Fortran) { REJECT; } @@ -1756,39 +1834,39 @@ static void setFileName(yyscan_t yyscanner,const QCString &name) YY_EXTRA_TYPE state = preYYget_extra(yyscanner); bool ambig; FileInfo fi(name.str()); - state->yyFileName=fi.absFilePath(); - state->yyFileDef=findFileDef(Doxygen::inputNameLinkedMap,state->yyFileName,ambig); + state->fileName=fi.absFilePath(); + state->yyFileDef=findFileDef(Doxygen::inputNameLinkedMap,state->fileName,ambig); if (state->yyFileDef==0) // if this is not an input file check if it is an // include file { - state->yyFileDef=findFileDef(Doxygen::includeNameLinkedMap,state->yyFileName,ambig); + state->yyFileDef=findFileDef(Doxygen::includeNameLinkedMap,state->fileName,ambig); } - //printf("setFileName(%s) state->yyFileName=%s state->yyFileDef=%p\n", - // name,qPrint(state->yyFileName),state->yyFileDef); + //printf("setFileName(%s) state->fileName=%s state->yyFileDef=%p\n", + // name,qPrint(state->fileName),state->yyFileDef); if (state->yyFileDef && state->yyFileDef->isReference()) state->yyFileDef=0; - state->insideCS = getLanguageFromFileName(state->yyFileName)==SrcLangExt_CSharp; - state->insideFtn = getLanguageFromFileName(state->yyFileName)==SrcLangExt_Fortran; - state->isSource = guessSection(state->yyFileName); + state->insideCS = getLanguageFromFileName(state->fileName)==SrcLangExt_CSharp; + state->insideFtn = getLanguageFromFileName(state->fileName)==SrcLangExt_Fortran; + state->isSource = guessSection(state->fileName); } static void incrLevel(yyscan_t yyscanner) { YY_EXTRA_TYPE state = preYYget_extra(yyscanner); state->levelGuard.push(false); - //printf("%s line %d: incrLevel %d\n",qPrint(yyextra->yyFileName),yyextra->yyLineNr,yyextra->levelGuard.size()); + //printf("%s line %d: incrLevel %d\n",qPrint(yyextra->fileName),yyextra->yyLineNr,yyextra->levelGuard.size()); } static void decrLevel(yyscan_t yyscanner) { YY_EXTRA_TYPE state = preYYget_extra(yyscanner); - //printf("%s line %d: decrLevel %d\n",qPrint(state->yyFileName),state->yyLineNr,state->levelGuard.size()); + //printf("%s line %d: decrLevel %d\n",qPrint(state->fileName),state->yyLineNr,state->levelGuard.size()); if (!state->levelGuard.empty()) { state->levelGuard.pop(); } else { - warn(state->yyFileName,state->yyLineNr,"More #endif's than #if's found.\n"); + warn(state->fileName,state->yyLineNr,"More #endif's than #if's found.\n"); } } @@ -1797,7 +1875,7 @@ static bool otherCaseDone(yyscan_t yyscanner) YY_EXTRA_TYPE state = preYYget_extra(yyscanner); if (state->levelGuard.empty()) { - warn(state->yyFileName,state->yyLineNr,"Found an #else without a preceding #if.\n"); + warn(state->fileName,state->yyLineNr,"Found an #else without a preceding #if.\n"); return TRUE; } else @@ -1873,7 +1951,7 @@ static FileState *checkAndOpenFile(yyscan_t yyscanner,const QCString &fileName,b static FileState *findFile(yyscan_t yyscanner, const QCString &fileName,bool localInclude,bool &alreadyProcessed) { YY_EXTRA_TYPE state = preYYget_extra(yyscanner); - //printf("** findFile(%s,%d) state->yyFileName=%s\n",qPrint(fileName),localInclude,qPrint(state->yyFileName)); + //printf("** findFile(%s,%d) state->fileName=%s\n",qPrint(fileName),localInclude,qPrint(state->fileName)); if (Portable::isAbsolutePath(fileName)) { FileState *fs = checkAndOpenFile(yyscanner,fileName,alreadyProcessed); @@ -1888,9 +1966,9 @@ static FileState *findFile(yyscan_t yyscanner, const QCString &fileName,bool loc return 0; } } - if (localInclude && !state->yyFileName.isEmpty()) + if (localInclude && !state->fileName.isEmpty()) { - FileInfo fi(state->yyFileName.str()); + FileInfo fi(state->fileName.str()); if (fi.exists()) { QCString absName = QCString(fi.dirPath(TRUE))+"/"+fileName; @@ -2823,7 +2901,7 @@ static bool computeExpression(yyscan_t yyscanner,const QCString &expr) e = removeIdsAndMarkers(e); if (e.isEmpty()) return FALSE; //printf("parsing '%s'\n",qPrint(e)); - return state->constExpParser.parse(state->yyFileName.data(),state->yyLineNr,e.str()); + return state->constExpParser.parse(state->fileName.data(),state->yyLineNr,e.str()); } /*! expands the macro definition in \a name @@ -2848,7 +2926,7 @@ static void addDefine(yyscan_t yyscanner) def.name = state->defName; def.definition = state->defText.stripWhiteSpace(); def.nargs = state->defArgs; - def.fileName = state->yyFileName; + def.fileName = state->fileName; def.fileDef = state->yyFileDef; def.lineNr = state->yyLineNr-state->yyMLines; def.columnNr = state->yyColNr; @@ -2876,7 +2954,7 @@ static void addMacroDefinition(yyscan_t yyscanner) // conditional section (cond command) that is disabled. Define define; - define.fileName = state->yyFileName; + define.fileName = state->fileName; define.lineNr = state->yyLineNr - state->yyMLines; define.columnNr = state->yyColNr; define.name = state->defName; @@ -3028,12 +3106,12 @@ static void readIncludeFile(yyscan_t yyscanner,const QCString &inc) return; } - QCString oldFileName = state->yyFileName; + QCString oldFileName = state->fileName; FileDef *oldFileDef = state->yyFileDef; int oldLineNr = state->yyLineNr; //printf("Searching for '%s'\n",qPrint(incFileName)); - QCString absIncFileName = determineAbsoluteIncludeName(state->yyFileName,incFileName); + QCString absIncFileName = determineAbsoluteIncludeName(state->fileName,incFileName); // findFile will overwrite state->yyFileDef if found FileState *fs; @@ -3086,8 +3164,8 @@ static void readIncludeFile(yyscan_t yyscanner,const QCString &inc) // Deal with file changes due to // #include's within { .. } blocks - QCString lineStr(state->yyFileName.length()+20); - lineStr.sprintf("# 1 \"%s\" 1\n",qPrint(state->yyFileName)); + QCString lineStr(state->fileName.length()+20); + lineStr.sprintf("# 1 \"%s\" 1\n",qPrint(state->fileName)); outputString(yyscanner,lineStr); DBG_CTX((stderr,"Switching to include file %s\n",qPrint(incFileName))); @@ -3102,7 +3180,7 @@ static void readIncludeFile(yyscan_t yyscanner,const QCString &inc) // in the local context { std::lock_guard<std::mutex> lock(g_globalDefineMutex); - g_defineManager.addInclude(state->yyFileName.str(),absIncFileName.str()); + g_defineManager.addInclude(state->fileName.str(),absIncFileName.str()); g_defineManager.retrieve(absIncFileName.str(),state->contextDefines); } @@ -3141,7 +3219,7 @@ static void readIncludeFile(yyscan_t yyscanner,const QCString &inc) } if (state->curlyCount>0 && !alreadyProcessed) // failed to find #include inside { ... } { - warn(state->yyFileName,state->yyLineNr,"include file %s not found, perhaps you forgot to add its directory to INCLUDE_PATH?",qPrint(incFileName)); + warn(state->fileName,state->yyLineNr,"include file %s not found, perhaps you forgot to add its directory to INCLUDE_PATH?",qPrint(incFileName)); } } } @@ -3154,8 +3232,8 @@ static void startCondSection(yyscan_t yyscanner,const QCString §Id) YY_EXTRA_TYPE state = preYYget_extra(yyscanner); //printf("startCondSection: skip=%d stack=%d\n",state->skip,state->condStack.size()); CondParser prs; - bool expResult = prs.parse(state->yyFileName.data(),state->yyLineNr,sectId.data()); - state->condStack.emplace(std::make_unique<CondCtx>(state->yyLineNr,sectId,state->skip)); + bool expResult = prs.parse(state->fileName.data(),state->yyLineNr,sectId.data()); + state->condStack.emplace(std::make_unique<preYY_CondCtx>(state->yyLineNr,sectId,state->skip)); if (!expResult) { state->skip=TRUE; @@ -3168,11 +3246,12 @@ static void endCondSection(yyscan_t yyscanner) YY_EXTRA_TYPE state = preYYget_extra(yyscanner); if (state->condStack.empty()) { + warn(state->fileName,state->yyLineNr,"the \\endcond does not have a corresponding \\cond in this file"); state->skip=FALSE; } else { - const std::unique_ptr<CondCtx> &ctx = state->condStack.top(); + const std::unique_ptr<preYY_CondCtx> &ctx = state->condStack.top(); state->skip=ctx->skip; state->condStack.pop(); } @@ -3500,7 +3579,7 @@ void Preprocessor::processFile(const QCString &fileName,BufStr &input,BufStr &ou setFileName(yyscanner,fileName); state->inputFileDef = state->yyFileDef; - //yyextra->defineManager.startContext(state->yyFileName); + //yyextra->defineManager.startContext(state->fileName); initPredefined(yyscanner,fileName); @@ -3519,7 +3598,7 @@ void Preprocessor::processFile(const QCString &fileName,BufStr &input,BufStr &ou while (!state->condStack.empty()) { - const std::unique_ptr<CondCtx> &ctx = state->condStack.top(); + const std::unique_ptr<preYY_CondCtx> &ctx = state->condStack.top(); QCString sectionInfo = " "; if (ctx->sectionId!=" ") sectionInfo.sprintf(" with label '%s' ",qPrint(ctx->sectionId.stripWhiteSpace())); warn(fileName,ctx->lineNr,"Conditional section%sdoes not have " @@ -3579,7 +3658,7 @@ void Preprocessor::processFile(const QCString &fileName,BufStr &input,BufStr &ou } } // add the macro definition for this file to the global map - Doxygen::macroDefinitions.emplace(std::make_pair(state->yyFileName.str(),std::move(state->macroDefinitions))); + Doxygen::macroDefinitions.emplace(std::make_pair(state->fileName.str(),std::move(state->macroDefinitions))); } //yyextra->defineManager.endContext(); diff --git a/src/printdocvisitor.h b/src/printdocvisitor.h index 3cdace8..1424e63 100644 --- a/src/printdocvisitor.h +++ b/src/printdocvisitor.h @@ -137,6 +137,9 @@ class PrintDocVisitor : public DocVisitor case DocStyleChange::Small: if (s->enable()) printf("<small>"); else printf("</small>"); break; + case DocStyleChange::Cite: + if (s->enable()) printf("<cite>"); else printf("</cite>"); + break; case DocStyleChange::Preformatted: if (s->enable()) printf("<pre>"); else printf("</pre>"); break; @@ -146,6 +149,30 @@ class PrintDocVisitor : public DocVisitor case DocStyleChange::Span: if (s->enable()) printf("<span>"); else printf("</span>"); break; + case DocStyleChange::Details: + if (s->enable()) + { + indent_pre(); + printf("<details>\n"); + } + else + { + indent_post(); + printf("</details>\n"); + } + break; + case DocStyleChange::Summary: + if (s->enable()) + { + indent_pre(); + printf("<summary>\n"); + } + else + { + indent_post(); + printf("</summary>\n"); + } + break; } } void visit(DocVerbatim *s) @@ -155,6 +182,8 @@ class PrintDocVisitor : public DocVisitor { case DocVerbatim::Code: printf("<code>"); break; case DocVerbatim::Verbatim: printf("<verbatim>"); break; + case DocVerbatim::JavaDocLiteral: printf("<javadocliteral>"); break; + case DocVerbatim::JavaDocCode: printf("<javadoccode>"); break; case DocVerbatim::HtmlOnly: printf("<htmlonly>"); break; case DocVerbatim::RtfOnly: printf("<rtfonly>"); break; case DocVerbatim::ManOnly: printf("<manonly>"); break; @@ -170,6 +199,8 @@ class PrintDocVisitor : public DocVisitor { case DocVerbatim::Code: printf("</code>"); break; case DocVerbatim::Verbatim: printf("</verbatim>"); break; + case DocVerbatim::JavaDocLiteral: printf("</javadocliteral>"); break; + case DocVerbatim::JavaDocCode: printf("</javadoccode>"); break; case DocVerbatim::HtmlOnly: printf("</htmlonly>"); break; case DocVerbatim::RtfOnly: printf("</rtfonly>"); break; case DocVerbatim::ManOnly: printf("</manonly>"); break; @@ -402,10 +433,15 @@ class PrintDocVisitor : public DocVisitor indent_post(); if (s->type()==DocHtmlList::Ordered) printf("</ol>\n"); else printf("</ul>\n"); } - void visitPre(DocHtmlListItem *) + void visitPre(DocHtmlListItem *s) { indent_pre(); - printf("<li>\n"); + printf("<li"); + for (const auto &opt : s->attribs()) + { + printf(" %s=\"%s\"",qPrint(opt.name),qPrint(opt.value)); + } + printf(">\n"); } void visitPost(DocHtmlListItem *) { @@ -535,6 +571,7 @@ class PrintDocVisitor : public DocVisitor case DocImage::Latex: printf("latex"); break; case DocImage::Rtf: printf("rtf"); break; case DocImage::DocBook: printf("docbook"); break; + case DocImage::Xml: printf("xml"); break; } printf("\" %s %s inline=\"%s\">\n",qPrint(img->width()),qPrint(img->height()),img->isInlineImage() ? "yes" : "no"); } diff --git a/src/pycode.l b/src/pycode.l index b5fecd3..8756325 100644 --- a/src/pycode.l +++ b/src/pycode.l @@ -26,6 +26,10 @@ %option noyy_top_state %top{ #include <stdint.h> +// forward declare yyscan_t to improve type safety +#define YY_TYPEDEF_YY_SCANNER_T +struct yyguts_t; +typedef yyguts_t *yyscan_t; } %{ @@ -74,8 +78,9 @@ struct pycodeYY_state CodeOutputInterface * code = 0; const char * inputString = 0; //!< the code fragment as text yy_size_t inputPosition = 0; //!< read offset during parsing + QCString fileName; const char * currentFontClass = 0; - bool needsTermination = FALSE; + bool insideCodeLine = FALSE; const Definition *searchCtx = 0; bool collectXRefs = FALSE; int inputLines = 0; //!< number of line in the code fragment @@ -90,6 +95,7 @@ struct pycodeYY_state QCString classScope; int paramParens = 0; + bool insideBody = false; bool exampleBlock = FALSE; QCString exampleName; @@ -158,6 +164,10 @@ static std::mutex g_countFlowKeywordsMutex; #undef YY_INPUT #define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); +// otherwise the filename would be the name of the converted file (*.cpp instead of *.l) +static inline const char *getLexerFILE() {return __FILE__;} +#include "doxygen_lex.h" + %} @@ -285,9 +295,6 @@ TARGET ({IDENTIFIER}|"("{TARGET_LIST}")"|"["{TARGET_LIST}"]"|{ATTRIBU %x SuiteCaptureIndent %x SuiteStart %x SuiteMaintain -%x SuiteContinuing - -%x LongString %x SingleQuoteString %x DoubleQuoteString @@ -388,7 +395,9 @@ TARGET ({IDENTIFIER}|"("{TARGET_LIST}")"|"["{TARGET_LIST}"]"|{ATTRIBU // about what to accept. yyextra->curClassBases.push_back(yytext); + yyextra->insideBody = true; generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + yyextra->insideBody = false; // codify(yyscanner,yytext); } @@ -505,10 +514,14 @@ TARGET ({IDENTIFIER}|"("{TARGET_LIST}")"|"["{TARGET_LIST}"]"|{ATTRIBU endFontClass(yyscanner); } ({IDENTIFIER}".")*{IDENTIFIER}/"(" { + yyextra->insideBody = true; generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + yyextra->insideBody = false; } ({IDENTIFIER}".")+{IDENTIFIER} { + yyextra->insideBody = true; generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext,TRUE); + yyextra->insideBody = false; } {IDENTIFIER} { codify(yyscanner,yytext); } @@ -932,7 +945,6 @@ static int countLines(yyscan_t yyscanner) { // last line does not end with a \n, so we add an extra // line and explicitly terminate the line after parsing. count++; - yyextra->needsTermination=TRUE; } return count; } @@ -1022,7 +1034,7 @@ static void startCodeLine(yyscan_t yyscanner) { yyextra->currentDefinition = d; yyextra->currentMemberDef = yyextra->sourceFileDef->getSourceMember(yyextra->yyLineNr); - //yyextra->insideBody = FALSE; + yyextra->insideBody = false; yyextra->endComment = FALSE; yyextra->searchingForBody = TRUE; yyextra->realScope = d->name(); @@ -1035,25 +1047,28 @@ static void startCodeLine(yyscan_t yyscanner) { yyextra->code->writeLineNumber(yyextra->currentMemberDef->getReference(), yyextra->currentMemberDef->getOutputFileBase(), - yyextra->currentMemberDef->anchor(),yyextra->yyLineNr); + yyextra->currentMemberDef->anchor(),yyextra->yyLineNr, + !yyextra->includeCodeFragment); setCurrentDoc(yyscanner,lineAnchor); } else { yyextra->code->writeLineNumber(d->getReference(), d->getOutputFileBase(), - QCString(),yyextra->yyLineNr); + QCString(),yyextra->yyLineNr, + !yyextra->includeCodeFragment); setCurrentDoc(yyscanner,lineAnchor); } } else { - //yyextra->code->codify(lineNumber); - yyextra->code->writeLineNumber(QCString(),QCString(),QCString(),yyextra->yyLineNr); + yyextra->code->writeLineNumber(QCString(),QCString(),QCString(),yyextra->yyLineNr, + !yyextra->includeCodeFragment); } - //yyextra->code->endLineNumber(); } yyextra->code->startCodeLine(yyextra->sourceFileDef); + yyextra->insideCodeLine=true; + if (yyextra->currentFontClass) { yyextra->code->startFontClass(yyextra->currentFontClass); @@ -1075,6 +1090,7 @@ static void endCodeLine(yyscan_t yyscanner) struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; endFontClass(yyscanner); yyextra->code->endCodeLine(); + yyextra->insideCodeLine=false; } //------------------------------------------------------------------------------- @@ -1083,7 +1099,10 @@ static void nextCodeLine(yyscan_t yyscanner) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; const char *fc = yyextra->currentFontClass; - endCodeLine(yyscanner); + if (yyextra->insideCodeLine) + { + endCodeLine(yyscanner); + } if (yyextra->yyLineNr<yyextra->inputLines) { yyextra->currentFontClass = fc; @@ -1230,7 +1249,7 @@ static bool getLinkInScope(yyscan_t yyscanner, //printf("yyextra->currentDefinition=%p yyextra->currentMemberDef=%p\n", // yyextra->currentDefinition,yyextra->currentMemberDef); - if (yyextra->currentDefinition && yyextra->currentMemberDef && yyextra->collectXRefs) + if (yyextra->currentDefinition && yyextra->currentMemberDef && yyextra->collectXRefs && yyextra->insideBody) { std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(md)); @@ -1341,7 +1360,7 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, md->getBodyDef() : md->getOuterScope(); if (md->getGroupDef()) d = md->getGroupDef(); if (d && d->isLinkable() && md->isLinkable() && - yyextra->currentMemberDef && yyextra->collectXRefs) + yyextra->currentMemberDef && yyextra->collectXRefs && yyextra->insideBody) { std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(md)); @@ -1369,7 +1388,7 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, mmd->getBodyDef() : mmd->getOuterScope(); if (mmd->getGroupDef()) d = mmd->getGroupDef(); if (d && d->isLinkable() && mmd->isLinkable() && - yyextra->currentMemberDef && yyextra->collectXRefs) + yyextra->currentMemberDef && yyextra->collectXRefs && yyextra->insideBody) { std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(mmd)); @@ -1393,7 +1412,7 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, mmd->getBodyDef() : mmd->getOuterScope(); if (mmd->getGroupDef()) d = mmd->getGroupDef(); if (d && d->isLinkable() && mmd->isLinkable() && - yyextra->currentMemberDef && yyextra->collectXRefs) + yyextra->currentMemberDef && yyextra->collectXRefs && yyextra->insideBody) { std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(mmd)); @@ -1511,16 +1530,17 @@ static void findMemberLink(yyscan_t yyscanner, // yyextra->currentDefinition?qPrint(yyextra->currentDefinition->name()):"<none>", // yyextra->currentMemberDef?qPrint(yyextra->currentMemberDef->name()):"<none>" // ); + bool found = false; if (yyextra->currentDefinition) { auto range = Doxygen::symbolMap->find(symName); for (auto it = range.first; it!=range.second; ++it) { - findMemberLink(yyscanner,ol,it->second,symName); + if (findMemberLink(yyscanner,ol,it->second,symName)) found = true; } } //printf("sym %s not found\n",&yytext[5]); - codify(yyscanner,symName); + if (!found) codify(yyscanner,symName); } @@ -1581,11 +1601,12 @@ void PythonCodeParser::parseCode(CodeOutputInterface &codeOutIntf, if (input.isEmpty()) return; printlex(yy_flex_debug, TRUE, __FILE__, fileDef ? qPrint(fileDef->fileName()): NULL); + yyextra->fileName = fileDef ? fileDef->fileName():""; yyextra->code = &codeOutIntf; yyextra->inputString = input.data(); yyextra->inputPosition = 0; yyextra->currentFontClass = 0; - yyextra->needsTermination = FALSE; + yyextra->insideCodeLine = FALSE; yyextra->searchCtx=searchCtx; yyextra->collectXRefs=collectXRefs; if (startLine!=-1) @@ -1628,7 +1649,7 @@ void PythonCodeParser::parseCode(CodeOutputInterface &codeOutIntf, // printf("Exited pysourceparser in inconsistent state!\n"); } - if (yyextra->needsTermination) + if (yyextra->insideCodeLine) { endCodeLine(yyscanner); } diff --git a/src/pyscanner.l b/src/pyscanner.l index 38fbe2b..593db6b 100644 --- a/src/pyscanner.l +++ b/src/pyscanner.l @@ -3,8 +3,8 @@ * Copyright (C) 1997-2021 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -25,12 +25,16 @@ %option extra-type="struct pyscannerYY_state *" %top{ #include <stdint.h> +// forward declare yyscan_t to improve type safety +#define YY_TYPEDEF_YY_SCANNER_T +struct yyguts_t; +typedef yyguts_t *yyscan_t; } %{ /* - * includes + * includes */ #include <stdio.h> #include <stdlib.h> @@ -59,6 +63,8 @@ #define USE_STATE2STRING 0 +#define unput_string(yytext,yyleng) do { for (int i=(int)yyleng-1;i>=0;i--) unput(yytext[i]); } while(0) + /* ----------------------------------------------------------------- */ struct pyscannerYY_state @@ -73,7 +79,7 @@ struct pyscannerYY_state std::shared_ptr<Entry> previous; std::shared_ptr<Entry> bodyEntry; int yyLineNr = 1 ; - QCString yyFileName; + QCString fileName; MethodTypes mtype = Method; bool stat = FALSE; Specifier virt = Normal; @@ -140,8 +146,12 @@ static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size); //----------------------------------------------------------------------------- /* ----------------------------------------------------------------- */ -#undef YY_INPUT -#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); +#undef YY_INPUT +#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); + +// otherwise the filename would be the name of the converted file (*.cpp instead of *.l) +static inline const char *getLexerFILE() {return __FILE__;} +#include "doxygen_lex.h" %} @@ -167,7 +177,7 @@ NONEMPTY [A-Za-z0-9_\x80-\xFF] EXPCHAR [#(){}\[\],:.%/\\=`*~|&<>!;+-] NONEMPTYEXP [^ \t\n:] PARAMNONEMPTY [^ \t\n():] -IDENTIFIER ({LETTER}|"_")({LETTER}|{DIGIT}|"_")* +IDENTIFIER ({LETTER}|"_")({LETTER}|{DIGIT}|"_")* SCOPE {IDENTIFIER}("."{IDENTIFIER})* CALL "("[^)]*")" BORDER ([^A-Za-z0-9]) @@ -185,11 +195,11 @@ LONGSTRINGBLOCK ({LONGSTRINGITEM}|{SMALLQUOTE}) SHORTSTRING ("'"{SHORTSTRINGITEM}*"'"|'"'{SHORTSTRINGITEM}*'"') SHORTSTRINGITEM ({SHORTSTRINGCHAR}|{ESCAPESEQ}) SHORTSTRINGCHAR [^\\\n"] -STRINGLITERAL {STRINGPREFIX}?( {SHORTSTRING} | {LONGSTRING}) +STRINGLITERAL {STRINGPREFIX}?( {SHORTSTRING} | {LONGSTRING}) STRINGPREFIX ("r"|"u"|"ur"|"R"|"U"|"UR"|"Ur"|"uR") FLOWKW ("or"|"and"|"is"|"not"|"print"|"for"|"in"|"if"|"try"|"except"|"yield"|"raise"|"break"|"continue"|"pass"|"if"|"return"|"while"|"elif"|"else"|"finally") -POUNDCOMMENT "#"[^#\n][^\n]* -SCRIPTCOMMENT "#!".* +POUNDCOMMENT "#"[^#\n][^\n]* +SCRIPTCOMMENT "#!".* STARTDOCSYMS "##" @@ -204,7 +214,6 @@ STARTDOCSYMS "##" /* %x FuncDoubleComment */ /* %x ClassDoubleComment */ -%x TryClassDocString %x TripleComment %x SpecialComment @@ -249,111 +258,111 @@ STARTDOCSYMS "##" <Search>{ ^{B}"def"{BB} { // start of a function/method definition with indent - DBG_CTX((stderr,"Found def at %d\n",yyextra->yyLineNr)); - yyextra->indent=computeIndent(yytext); - searchFoundDef(yyscanner); - BEGIN( FunctionDec ); - } + DBG_CTX((stderr,"Found def at %d\n",yyextra->yyLineNr)); + yyextra->indent=computeIndent(yytext); + searchFoundDef(yyscanner); + BEGIN( FunctionDec ); + } ^{B}"async"{BB}"def"{BB} { // start of an async function/method definition with indent - DBG_CTX((stderr,"Found async def at %d\n",yyextra->yyLineNr)); - yyextra->indent=computeIndent(yytext); - searchFoundDef(yyscanner); - BEGIN( FunctionDec ); - } + DBG_CTX((stderr,"Found async def at %d\n",yyextra->yyLineNr)); + yyextra->indent=computeIndent(yytext); + searchFoundDef(yyscanner); + BEGIN( FunctionDec ); + } "def"{BB} { // start of a function/method definition - searchFoundDef(yyscanner); - BEGIN( FunctionDec ); + searchFoundDef(yyscanner); + BEGIN( FunctionDec ); } "async"{BB}"def"{BB} { // start of a function/method definition - searchFoundDef(yyscanner); - BEGIN( FunctionDec ); + searchFoundDef(yyscanner); + BEGIN( FunctionDec ); } - ^{B}"class"{BB} { // start of a class definition with indent - DBG_CTX((stderr,"Found class at %d\n",yyextra->yyLineNr)); - yyextra->indent=computeIndent(yytext); - searchFoundClass(yyscanner); - BEGIN( ClassDec ) ; - } + ^{B}"class"{BB} { // start of a class definition with indent + DBG_CTX((stderr,"Found class at %d\n",yyextra->yyLineNr)); + yyextra->indent=computeIndent(yytext); + searchFoundClass(yyscanner); + BEGIN( ClassDec ) ; + } "class"{BB} { // start of a class definition - searchFoundClass(yyscanner); - BEGIN( ClassDec ) ; + searchFoundClass(yyscanner); + BEGIN( ClassDec ) ; } ^{B}"from"{BB} | - "from"{BB} { // start of an from import - yyextra->packageCommentAllowed = FALSE; + "from"{BB} { // start of an from import + yyextra->packageCommentAllowed = FALSE; BEGIN( FromMod ); } ^{B}"import"{BB} | "import"{BB} { // start of an import statement - yyextra->packageCommentAllowed = FALSE; + yyextra->packageCommentAllowed = FALSE; BEGIN( Import ); } ^{B}{IDENTIFIER}/{B}"="{B}"property" { // property - yyextra->current->section = Entry::VARIABLE_SEC; - yyextra->current->mtype = Property; - yyextra->current->name = QCString(yytext).stripWhiteSpace(); - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->packageCommentAllowed = FALSE; - BEGIN(VariableDec); - } + yyextra->current->section = Entry::VARIABLE_SEC; + yyextra->current->mtype = Property; + yyextra->current->name = QCString(yytext).stripWhiteSpace(); + yyextra->current->fileName = yyextra->fileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->packageCommentAllowed = FALSE; + BEGIN(VariableDec); + } ^{B}{IDENTIFIER}/{B}"="[^=] { // variable if (yyextra->search_count) REJECT; - yyextra->indent=computeIndent(yytext); - yyextra->current->section = Entry::VARIABLE_SEC; - yyextra->current->name = QCString(yytext).stripWhiteSpace(); - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->packageCommentAllowed = FALSE; - BEGIN(VariableDec); - } + yyextra->indent=computeIndent(yytext); + yyextra->current->section = Entry::VARIABLE_SEC; + yyextra->current->name = QCString(yytext).stripWhiteSpace(); + yyextra->current->fileName = yyextra->fileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->packageCommentAllowed = FALSE; + BEGIN(VariableDec); + } {B}{IDENTIFIER}/({B},{B}{IDENTIFIER})*{B}")"*{B}"="[^=] { // list of variables, we cannot place the default value // so we will skip it later on in a general rule // Also note ")" this is to catch also (a,b). the "(" // is caught in the rule: [(], the ")" will be handled in [)] if (yyextra->search_count > 1) REJECT; - yyextra->indent=computeIndent(yytext); - yyextra->current->section = Entry::VARIABLE_SEC; - yyextra->current->name = QCString(yytext).stripWhiteSpace(); - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->packageCommentAllowed = FALSE; - newVariable(yyscanner); - } - "'" { // start of a single quoted string - yyextra->stringContext=YY_START; - yyextra->copyString=0; - yyextra->packageCommentAllowed = FALSE; + yyextra->indent=computeIndent(yytext); + yyextra->current->section = Entry::VARIABLE_SEC; + yyextra->current->name = QCString(yytext).stripWhiteSpace(); + yyextra->current->fileName = yyextra->fileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->packageCommentAllowed = FALSE; + newVariable(yyscanner); + } + "'" { // start of a single quoted string + yyextra->stringContext=YY_START; + yyextra->copyString=0; + yyextra->packageCommentAllowed = FALSE; BEGIN( SingleQuoteString ); } - "\"" { // start of a double quoted string - yyextra->stringContext=YY_START; - yyextra->copyString=0; - yyextra->packageCommentAllowed = FALSE; + "\"" { // start of a double quoted string + yyextra->stringContext=YY_START; + yyextra->copyString=0; + yyextra->packageCommentAllowed = FALSE; BEGIN( DoubleQuoteString ); } "@staticmethod" { - yyextra->stat=TRUE; - } + yyextra->stat=TRUE; + } "@"{SCOPE}{CALL}? { // decorator lineCount(yyscanner); } {SCRIPTCOMMENT} { // Unix type script comment if (yyextra->yyLineNr != 1) REJECT; - } - {POUNDCOMMENT} { // normal comment - yyextra->packageCommentAllowed = FALSE; - } + } + {POUNDCOMMENT} { // normal comment + yyextra->packageCommentAllowed = FALSE; + } {IDENTIFIER} { // some other identifier - yyextra->packageCommentAllowed = FALSE; - } - ^{BB} { - yyextra->curIndent=computeIndent(yytext); + yyextra->packageCommentAllowed = FALSE; + } + ^{BB} { + yyextra->curIndent=computeIndent(yytext); } {NEWLINE}+ { // new line @@ -361,20 +370,20 @@ STARTDOCSYMS "##" } {TRIDOUBLEQUOTE} { // start of a comment block - initTriDoubleQuoteBlock(yyscanner); - BEGIN(TripleComment); + initTriDoubleQuoteBlock(yyscanner); + BEGIN(TripleComment); } {TRISINGLEQUOTE} { // start of a comment block - initTriSingleQuoteBlock(yyscanner); - BEGIN(TripleComment); + initTriSingleQuoteBlock(yyscanner); + BEGIN(TripleComment); } {STARTDOCSYMS}/[^#] { // start of a special comment - yyextra->curIndent=computeIndent(yytext); - yyextra->packageCommentAllowed = FALSE; - initSpecialBlock(yyscanner); - BEGIN(SpecialComment); + yyextra->curIndent=computeIndent(yytext); + yyextra->packageCommentAllowed = FALSE; + initSpecialBlock(yyscanner); + BEGIN(SpecialComment); } [(] { // we have to do something with ( yyextra->search_count += 1; @@ -392,18 +401,18 @@ STARTDOCSYMS "##" <FromMod>{ "." { // python3 style imports } - {IDENTIFIER}({B}"."{B}{IDENTIFIER})* { // from package import + {IDENTIFIER}({B}"."{B}{IDENTIFIER})* { // from package import yyextra->packageName=yytext; - } - "import"{B} { - BEGIN(FromModItem); - } - \n { + } + "import"{B} { + BEGIN(FromModItem); + } + \n { incLineNr(yyscanner); BEGIN(Search); } - {B} { - } + {B} { + } . { unput(*yytext); BEGIN(Search); @@ -411,13 +420,13 @@ STARTDOCSYMS "##" } <FromModItem>{ - "*" { // import all + "*" { // import all addFrom(yyscanner,TRUE); BEGIN(Search); - } + } {IDENTIFIER}/{B}","{B} { addFrom(yyscanner,FALSE); - } + } {IDENTIFIER}/{B}")" { addFrom(yyscanner,FALSE); } @@ -427,16 +436,16 @@ STARTDOCSYMS "##" { BEGIN(Search); } - } - \n { + } + \n { incLineNr(yyscanner); if (!yyextra->importTuple) { BEGIN(Search); } } - {B} { - } + {B} { + } "(" { yyextra->importTuple=TRUE; } @@ -444,8 +453,8 @@ STARTDOCSYMS "##" yyextra->importTuple=FALSE; BEGIN(Search); } - "," { - } + "," { + } "\\"{B}\n { // line continuation incLineNr(yyscanner); } @@ -457,20 +466,20 @@ STARTDOCSYMS "##" <Import>{ {IDENTIFIER}({B}"."{B}{IDENTIFIER})* { - yyextra->current->name=removeRedundantWhiteSpace(substitute(yytext,".","::")); - yyextra->current->fileName = yyextra->yyFileName; - //printf("Adding using declaration: found:%s:%d name=%s\n",qPrint(yyextra->yyFileName),yyextra->yyLineNr,qPrint(yyextra->current->name)); - yyextra->current->section=Entry::USINGDECL_SEC; - yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); - initEntry(yyscanner); - BEGIN(Search); - } - \n { + yyextra->current->name=removeRedundantWhiteSpace(substitute(yytext,".","::")); + yyextra->current->fileName = yyextra->fileName; + //printf("Adding using declaration: found:%s:%d name=%s\n",qPrint(yyextra->fileName),yyextra->yyLineNr,qPrint(yyextra->current->name)); + yyextra->current->section=Entry::USINGDECL_SEC; + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + initEntry(yyscanner); + BEGIN(Search); + } + \n { incLineNr(yyscanner); BEGIN(Search); } - {B} { - } + {B} { + } . { unput(*yytext); BEGIN(Search); @@ -480,59 +489,59 @@ STARTDOCSYMS "##" <SearchMemVars>{ "self."{IDENTIFIER}/{B}"=" { DBG_CTX((stderr,"Found instance method variable %s in %s at %d\n",&yytext[5],qPrint(yyextra->current_root->name.data(),yyextra->yyLineNr))); - yyextra->current->name=&yytext[5]; - yyextra->current->section=Entry::VARIABLE_SEC; - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->type.resize(0); - if (yyextra->current->name.at(0)=='_') // mark as private - { - yyextra->current->protection=Private; - } - newEntry(yyscanner); + yyextra->current->name=&yytext[5]; + yyextra->current->section=Entry::VARIABLE_SEC; + yyextra->current->fileName = yyextra->fileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->type.resize(0); + if (yyextra->current->name.at(0)=='_') // mark as private + { + yyextra->current->protection=Private; + } + newEntry(yyscanner); } "cls."{IDENTIFIER}/{B}"=" { DBG_CTX((stderr,"Found class method variable %s in %s at %d\n",&yytext[4],qPrint(yyextra->current_root->name),yyextra->yyLineNr)); - yyextra->current->name=&yytext[4]; - yyextra->current->section=Entry::VARIABLE_SEC; - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->type.resize(0); - if (yyextra->current->name.at(0)=='_') // mark as private - { - yyextra->current->protection=Private; - } - newEntry(yyscanner); + yyextra->current->name=&yytext[4]; + yyextra->current->section=Entry::VARIABLE_SEC; + yyextra->current->fileName = yyextra->fileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->type.resize(0); + if (yyextra->current->name.at(0)=='_') // mark as private + { + yyextra->current->protection=Private; + } + newEntry(yyscanner); } {TRIDOUBLEQUOTE} { // start of a comment block - initTriDoubleQuoteBlock(yyscanner); - BEGIN(TripleComment); + initTriDoubleQuoteBlock(yyscanner); + BEGIN(TripleComment); } {TRISINGLEQUOTE} { // start of a comment block - initTriSingleQuoteBlock(yyscanner); - BEGIN(TripleComment); + initTriSingleQuoteBlock(yyscanner); + BEGIN(TripleComment); } {STARTDOCSYMS}/[^#] { // start of a special comment - initSpecialBlock(yyscanner); - BEGIN(SpecialComment); + initSpecialBlock(yyscanner); + BEGIN(SpecialComment); } {POUNDCOMMENT} { // # - } - "'" { // start of a single quoted string - yyextra->stringContext=YY_START; - yyextra->copyString=0; + } + "'" { // start of a single quoted string + yyextra->stringContext=YY_START; + yyextra->copyString=0; BEGIN( SingleQuoteString ); } "\"" { // start of a double quoted string - yyextra->stringContext=YY_START; - yyextra->copyString=0; + yyextra->stringContext=YY_START; + yyextra->copyString=0; BEGIN( DoubleQuoteString ); } - \n { incLineNr(yyscanner); } + \n { incLineNr(yyscanner); } {IDENTIFIER} // identifiers [^'"\.#a-z_A-Z\n]+ // other uninteresting stuff . // anything else @@ -541,145 +550,137 @@ STARTDOCSYMS "##" <FunctionBody>{ \n{B}/{IDENTIFIER}{BB} { DBG_CTX((stderr,"indent %d<=%d\n",computeIndent(&yytext[1]),yyextra->indent)); - if (computeIndent(&yytext[1])<=yyextra->indent) - { - int i; - for (i=(int)yyleng-1;i>=0;i--) - { - unput(yytext[i]); - } - endOfDef(yyscanner); - //YY_CURRENT_BUFFER->yy_at_bol=TRUE; + if (computeIndent(&yytext[1])<=yyextra->indent) + { + unput_string(yytext,yyleng); + endOfDef(yyscanner); + //YY_CURRENT_BUFFER->yy_at_bol=TRUE; BEGIN(Search); - } - else - { + } + else + { incLineNr(yyscanner); - yyextra->current->program << yytext; - } + yyextra->current->program << yytext; + } } - \n{B}/"##" { + \n{B}/"##" { if (computeIndent(&yytext[1])<=yyextra->indent) - { - int i; - for (i=(int)yyleng-1;i>=0;i--) - { - unput(yytext[i]); - } - endOfDef(yyscanner); - //YY_CURRENT_BUFFER->yy_at_bol=TRUE; + { + unput_string(yytext,yyleng); + endOfDef(yyscanner); + //YY_CURRENT_BUFFER->yy_at_bol=TRUE; BEGIN(Search); - } - else - { - incLineNr(yyscanner); - yyextra->current->program << yytext; - } - } - <<EOF>> { - endOfDef(yyscanner); - yyterminate(); - } - ^{BB}/\n { // skip empty line - yyextra->current->program << yytext; - } - ^{BB} { // something at indent >0 - yyextra->current->program << yytext; - yyextra->curIndent = computeIndent(yytext); - if (yyextra->curIndent<=yyextra->indent) - // jumped out of the function - { - endOfDef(yyscanner,1); + } + else + { + incLineNr(yyscanner); + yyextra->current->program << yytext; + } + } + <<EOF>> { + endOfDef(yyscanner); + yyterminate(); + } + ^{BB}/\n { // skip empty line + yyextra->current->program << yytext; + } + ^{BB} { // something at indent >0 + yyextra->current->program << yytext; + yyextra->curIndent = computeIndent(yytext); + if (yyextra->curIndent<=yyextra->indent) + // jumped out of the function + { + endOfDef(yyscanner,1); BEGIN(Search); - } - } - "'" { // start of a single quoted string - yyextra->current->program << yytext; - yyextra->stringContext=YY_START; - yyextra->specialBlock = FALSE; - yyextra->copyString=&yyextra->current->program; + } + } + "'" { // start of a single quoted string + yyextra->current->program << yytext; + yyextra->stringContext=YY_START; + yyextra->specialBlock = FALSE; + yyextra->copyString=&yyextra->current->program; BEGIN( SingleQuoteString ); } "\"" { // start of a double quoted string - yyextra->current->program << yytext; - yyextra->stringContext=YY_START; - yyextra->specialBlock = FALSE; - yyextra->copyString=&yyextra->current->program; + yyextra->current->program << yytext; + yyextra->stringContext=YY_START; + yyextra->specialBlock = FALSE; + yyextra->copyString=&yyextra->current->program; BEGIN( DoubleQuoteString ); } [^ \t\n#'".]+ { // non-special stuff - yyextra->current->program << yytext; - yyextra->specialBlock = FALSE; + yyextra->current->program << yytext; + yyextra->specialBlock = FALSE; + } + ^{POUNDCOMMENT} { // normal comment + yyextra->current->program << yytext; } - ^{POUNDCOMMENT} { // normal comment - yyextra->current->program << yytext; - } "#".* { // comment half way - yyextra->current->program << yytext; + yyextra->current->program << yytext; + } + {NEWLINE} { + incLineNr(yyscanner); + yyextra->current->program << yytext; } - {NEWLINE} { - incLineNr(yyscanner); - yyextra->current->program << yytext; - } . { // any character - yyextra->current->program << *yytext; - yyextra->specialBlock = FALSE; + yyextra->current->program << *yytext; + yyextra->specialBlock = FALSE; } {TRIDOUBLEQUOTE} { // start of a comment block - yyextra->current->program << yytext; - initTriDoubleQuoteBlock(yyscanner); - BEGIN(TripleComment); + yyextra->current->program << yytext; + initTriDoubleQuoteBlock(yyscanner); + BEGIN(TripleComment); } {TRISINGLEQUOTE} { // start of a comment block - yyextra->current->program << yytext; - initTriSingleQuoteBlock(yyscanner); - BEGIN(TripleComment); + yyextra->current->program << yytext; + initTriSingleQuoteBlock(yyscanner); + BEGIN(TripleComment); } {STARTDOCSYMS}/[^#] { // start of a special comment - initSpecialBlock(yyscanner); - BEGIN(SpecialComment); + initSpecialBlock(yyscanner); + BEGIN(SpecialComment); } - + } <FunctionDec>{ {IDENTIFIER} { - //found function name - if (yyextra->current->type.isEmpty()) - { - yyextra->current->type = "def"; - } - yyextra->current->name = yytext; - yyextra->current->name = yyextra->current->name.stripWhiteSpace(); - newFunction(yyscanner); + //found function name + if (yyextra->current->type.isEmpty()) + { + yyextra->current->type = "def"; + } + yyextra->current->name = yytext; + yyextra->current->name = yyextra->current->name.stripWhiteSpace(); + newFunction(yyscanner); } - {B}":"{B} { // function without arguments - yyextra->specialBlock = TRUE; // expecting a docstring - yyextra->bodyEntry = yyextra->current; + {B}":"{B} { // function without arguments + yyextra->specialBlock = TRUE; // expecting a docstring + yyextra->bodyEntry = yyextra->current; yyextra->current->bodyLine = yyextra->yyLineNr; BEGIN(FunctionBody); - } + } "->" { - yyextra->defVal.str(std::string()); - yyextra->braceCount = 0; - BEGIN(FunctionTypeAnnotation); - } + yyextra->defVal.str(std::string()); + yyextra->braceCount = 0; + BEGIN(FunctionTypeAnnotation); + } {B}"(" { - yyextra->funcParamsEnd = FALSE; + yyextra->funcParamsEnd = FALSE; yyextra->current->bodyLine = yyextra->yyLineNr; - BEGIN(FunctionParams); - } + BEGIN(FunctionParams); + } ")" { // end of parameter list if (yyextra->current->argList.empty()) { yyextra->current->argList.setNoParameters(TRUE); } - yyextra->current->args = argListToString(yyextra->current->argList); - yyextra->funcParamsEnd = TRUE; + yyextra->current->args = argListToString(yyextra->current->argList); + yyextra->funcParamsEnd = TRUE; } } @@ -691,160 +692,160 @@ STARTDOCSYMS "##" yyextra->argType = yytext; } {IDENTIFIER} { // Name of parameter - lineCount(yyscanner); - Argument a; - a.name = QCString(yytext).stripWhiteSpace(); - a.type = yyextra->argType; - yyextra->current->argList.push_back(a); + lineCount(yyscanner); + Argument a; + a.name = QCString(yytext).stripWhiteSpace(); + a.type = yyextra->argType; + yyextra->current->argList.push_back(a); yyextra->argType = ""; } - "=" { // default value + "=" { // default value // TODO: this rule is too simple, need to be able to // match things like =")" as well! - yyextra->defVal.str(std::string()); - yyextra->braceCount = 0; - BEGIN(FunctionParamDefVal); - } + yyextra->defVal.str(std::string()); + yyextra->braceCount = 0; + BEGIN(FunctionParamDefVal); + } ")" { - unput(*yytext); - BEGIN(FunctionDec); + unput(*yytext); + BEGIN(FunctionDec); } ":"{B} { - yyextra->defVal.str(std::string()); - yyextra->braceCount = 0; - BEGIN(FunctionAnnotation); - } - {POUNDCOMMENT} { // a comment - } + yyextra->defVal.str(std::string()); + yyextra->braceCount = 0; + BEGIN(FunctionAnnotation); + } + {POUNDCOMMENT} { // a comment + } {PARAMNONEMPTY} { // Default rule inside arguments. } } <FunctionTypeAnnotation>{ - "{" | - "[" | - "(" { - ++yyextra->braceCount; - yyextra->defVal << *yytext; - } - "}" | - "]" | - ")" { - --yyextra->braceCount; - yyextra->defVal << *yytext; - } - ":" { - if (yyextra->braceCount == 0) - { - yyextra->current->type = yyextra->defVal.str(); - unput(*yytext); - BEGIN(FunctionDec); - } - else - yyextra->defVal << *yytext; - } + "{" | + "[" | + "(" { + ++yyextra->braceCount; + yyextra->defVal << *yytext; + } + "}" | + "]" | + ")" { + --yyextra->braceCount; + yyextra->defVal << *yytext; + } + ":" { + if (yyextra->braceCount == 0) + { + yyextra->current->type = yyextra->defVal.str(); + unput(*yytext); + BEGIN(FunctionDec); + } + else + yyextra->defVal << *yytext; + } "'" { - yyextra->defVal << *yytext; - yyextra->copyString=&yyextra->defVal; - yyextra->stringContext=FunctionTypeAnnotation; - BEGIN(SingleQuoteString); + yyextra->defVal << *yytext; + yyextra->copyString=&yyextra->defVal; + yyextra->stringContext=FunctionTypeAnnotation; + BEGIN(SingleQuoteString); } "\"" { - yyextra->defVal << *yytext; - yyextra->copyString=&yyextra->defVal; - yyextra->stringContext=FunctionTypeAnnotation; - BEGIN(DoubleQuoteString); + yyextra->defVal << *yytext; + yyextra->copyString=&yyextra->defVal; + yyextra->stringContext=FunctionTypeAnnotation; + BEGIN(DoubleQuoteString); } \n { - yyextra->defVal << *yytext; - incLineNr(yyscanner); - } - . { - yyextra->defVal << *yytext; - } + yyextra->defVal << *yytext; + incLineNr(yyscanner); + } + . { + yyextra->defVal << *yytext; + } } <FunctionAnnotation>{ - "{" | - "[" | - "(" { - ++yyextra->braceCount; - yyextra->defVal << *yytext; - } - "}" | - "]" { - --yyextra->braceCount; - yyextra->defVal << *yytext; - } - ")" | - "=" | - "," { - if (yyextra->braceCount == 0) - { - if (!yyextra->current->argList.empty()) - yyextra->current->argList.back().type += yyextra->defVal.str(); - if (*yytext != ',') - unput(*yytext); - BEGIN(FunctionParams); - } - else - { - if (*yytext == ')') - --yyextra->braceCount; - yyextra->defVal << *yytext; - } - } + "{" | + "[" | + "(" { + ++yyextra->braceCount; + yyextra->defVal << *yytext; + } + "}" | + "]" { + --yyextra->braceCount; + yyextra->defVal << *yytext; + } + ")" | + "=" | + "," { + if (yyextra->braceCount == 0) + { + if (!yyextra->current->argList.empty()) + yyextra->current->argList.back().type += yyextra->defVal.str(); + if (*yytext != ',') + unput(*yytext); + BEGIN(FunctionParams); + } + else + { + if (*yytext == ')') + --yyextra->braceCount; + yyextra->defVal << *yytext; + } + } "'" { - yyextra->defVal << *yytext; - yyextra->copyString=&yyextra->defVal; - yyextra->stringContext=FunctionAnnotation; - BEGIN(SingleQuoteString); + yyextra->defVal << *yytext; + yyextra->copyString=&yyextra->defVal; + yyextra->stringContext=FunctionAnnotation; + BEGIN(SingleQuoteString); } "\"" { - yyextra->defVal << *yytext; - yyextra->copyString=&yyextra->defVal; - yyextra->stringContext=FunctionAnnotation; - BEGIN(DoubleQuoteString); + yyextra->defVal << *yytext; + yyextra->copyString=&yyextra->defVal; + yyextra->stringContext=FunctionAnnotation; + BEGIN(DoubleQuoteString); } \n { - yyextra->defVal << *yytext; - incLineNr(yyscanner); - } - . { - yyextra->defVal << *yytext; - } + yyextra->defVal << *yytext; + incLineNr(yyscanner); + } + . { + yyextra->defVal << *yytext; + } } <FunctionParamDefVal>{ - "{" | - "[" | - "(" { // internal opening brace, assumption is that we have correct code so braces do match - ++yyextra->braceCount; - yyextra->defVal << *yytext; - } - "}" | - "]" { - --yyextra->braceCount; - yyextra->defVal << *yytext; - } - ")" | - "," { - if (yyextra->braceCount == 0) - { - if (!yyextra->current->argList.empty()) - yyextra->current->argList.back().defval=QCString(yyextra->defVal.str()).stripWhiteSpace(); - if (*yytext == ')') - unput(*yytext); - BEGIN(FunctionParams); - } - else - { - if (*yytext == ')') - --yyextra->braceCount; - yyextra->defVal << *yytext; - } - } + "{" | + "[" | + "(" { // internal opening brace, assumption is that we have correct code so braces do match + ++yyextra->braceCount; + yyextra->defVal << *yytext; + } + "}" | + "]" { + --yyextra->braceCount; + yyextra->defVal << *yytext; + } + ")" | + "," { + if (yyextra->braceCount == 0) + { + if (!yyextra->current->argList.empty()) + yyextra->current->argList.back().defval=QCString(yyextra->defVal.str()).stripWhiteSpace(); + if (*yytext == ')') + unput(*yytext); + BEGIN(FunctionParams); + } + else + { + if (*yytext == ')') + --yyextra->braceCount; + yyextra->defVal << *yytext; + } + } "'" { yyextra->defVal << *yytext; @@ -859,124 +860,146 @@ STARTDOCSYMS "##" BEGIN( DoubleQuoteString ); } \n { - yyextra->defVal << *yytext; - incLineNr(yyscanner); - } - . { - yyextra->defVal << *yytext; - } + yyextra->defVal << *yytext; + incLineNr(yyscanner); + } + . { + yyextra->defVal << *yytext; + } } <ClassBody>{ \n/{IDENTIFIER}{BB} { // new def at indent 0 - incLineNr(yyscanner); - endOfDef(yyscanner); - //yyextra->hideClassDocs = FALSE; - //YY_CURRENT_BUFFER->yy_at_bol=TRUE; - BEGIN(Search); + if (computeIndent(&yytext[1])<=yyextra->indent) + { + int i; + for (i=(int)yyleng-1;i>=0;i--) + { + unput(yytext[i]); + } + endOfDef(yyscanner); + //YY_CURRENT_BUFFER->yy_at_bol=TRUE; + BEGIN(Search); + } + else + { + incLineNr(yyscanner); + yyextra->current->program << yytext; + } } \n/"##"[^#] { // start of a special comment at indent 0 - incLineNr(yyscanner); - endOfDef(yyscanner); - //yyextra->hideClassDocs = FALSE; - //YY_CURRENT_BUFFER->yy_at_bol=TRUE; - BEGIN(Search); + if (computeIndent(&yytext[1])<=yyextra->indent) + { + int i; + for (i=(int)yyleng-1;i>=0;i--) + { + unput(yytext[i]); + } + endOfDef(yyscanner); + //YY_CURRENT_BUFFER->yy_at_bol=TRUE; + BEGIN(Search); + } + else + { + incLineNr(yyscanner); + yyextra->current->program << yytext; + } + } + ^{BB}/\n { // skip empty line + yyextra->current->program << yytext; + } + <<EOF>> { + endOfDef(yyscanner); + yyterminate(); } - ^{BB}/\n { // skip empty line - yyextra->current->program << yytext; - } - <<EOF>> { - endOfDef(yyscanner); - yyterminate(); - } - ^{BB} { // something at indent >0 + ^{BB} { // something at indent >0 yyextra->curIndent=computeIndent(yytext); - DBG_CTX((stderr,"yyextra->curIndent=%d yyextra->indent=%d\n",yyextra->curIndent,yyextra->indent)); - if (yyextra->curIndent<=yyextra->indent) - // jumped out of the class/method - { - endOfDef(yyscanner,1); - yyextra->indent=yyextra->curIndent; - // make sure the next rule matches ^... - //YY_CURRENT_BUFFER->yy_at_bol=TRUE; - //yyextra->hideClassDocs = FALSE; + DBG_CTX((stderr,"yyextra->curIndent=%d yyextra->indent=%d\n",yyextra->curIndent,yyextra->indent)); + if (yyextra->curIndent<=yyextra->indent) + // jumped out of the class/method + { + endOfDef(yyscanner,1); + yyextra->indent=yyextra->curIndent; + // make sure the next rule matches ^... + //YY_CURRENT_BUFFER->yy_at_bol=TRUE; + //yyextra->hideClassDocs = FALSE; BEGIN(Search); - } - else - { - yyextra->current->program << yytext; - } - } - "'" { // start of a single quoted string - yyextra->current->program << *yytext; - yyextra->stringContext=YY_START; - yyextra->specialBlock = FALSE; - yyextra->copyString=&yyextra->current->program; + } + else + { + yyextra->current->program << yytext; + } + } + "'" { // start of a single quoted string + yyextra->current->program << *yytext; + yyextra->stringContext=YY_START; + yyextra->specialBlock = FALSE; + yyextra->copyString=&yyextra->current->program; BEGIN( SingleQuoteString ); } "\"" { // start of a double quoted string - yyextra->current->program << *yytext; - yyextra->stringContext=YY_START; - yyextra->specialBlock = FALSE; - yyextra->copyString=&yyextra->current->program; + yyextra->current->program << *yytext; + yyextra->stringContext=YY_START; + yyextra->specialBlock = FALSE; + yyextra->copyString=&yyextra->current->program; BEGIN( DoubleQuoteString ); } [^ \t\n#'"]+ { // non-special stuff - yyextra->current->program << yytext; - yyextra->specialBlock = FALSE; - //yyextra->hideClassDocs = FALSE; - } - {NEWLINE} { - yyextra->current->program << *yytext; - incLineNr(yyscanner); - } + yyextra->current->program << yytext; + yyextra->specialBlock = FALSE; + //yyextra->hideClassDocs = FALSE; + } + {NEWLINE} { + yyextra->current->program << *yytext; + incLineNr(yyscanner); + } {POUNDCOMMENT} { // normal comment - yyextra->current->program << yytext; + yyextra->current->program << yytext; } . { // any character - yyextra->specialBlock = FALSE; - yyextra->current->program << *yytext; + yyextra->specialBlock = FALSE; + yyextra->current->program << *yytext; } {TRIDOUBLEQUOTE} { // start of a comment block - //if (!yyextra->hideClassDocs) - yyextra->current->program << yytext; - initTriDoubleQuoteBlock(yyscanner); - BEGIN(TripleComment); + //if (!yyextra->hideClassDocs) + yyextra->current->program << yytext; + initTriDoubleQuoteBlock(yyscanner); + BEGIN(TripleComment); } {TRISINGLEQUOTE} { // start of a comment block - //if (!yyextra->hideClassDocs) - yyextra->current->program << yytext; - initTriSingleQuoteBlock(yyscanner); - BEGIN(TripleComment); + //if (!yyextra->hideClassDocs) + yyextra->current->program << yytext; + initTriSingleQuoteBlock(yyscanner); + BEGIN(TripleComment); } } <ClassDec>{IDENTIFIER} { - if (yyextra->current->type.isEmpty()) - { - yyextra->current->type = "class"; - } - - yyextra->current->section = Entry::CLASS_SEC; - yyextra->current->name = yytext; - - // prepend scope in case of nested classes - if (yyextra->current_root->section&Entry::SCOPE_MASK) - { - //printf("*** Prepending scope %s to class %s\n",qPrint(yyextra->current_root->name),qPrint(yyextra->current->name)); - yyextra->current->name.prepend(yyextra->current_root->name+"::"); - } - - yyextra->current->name = yyextra->current->name.stripWhiteSpace(); - yyextra->current->fileName = yyextra->yyFileName; - yyextra->docBlockContext = YY_START; - yyextra->docBlockInBody = FALSE; - yyextra->docBlockJavaStyle = FALSE; - yyextra->docBlock.resize(0); - - BEGIN(ClassInheritance); + if (yyextra->current->type.isEmpty()) + { + yyextra->current->type = "class"; + } + + yyextra->current->section = Entry::CLASS_SEC; + yyextra->current->name = yytext; + + // prepend scope in case of nested classes + if (yyextra->current_root->section&Entry::SCOPE_MASK) + { + //printf("*** Prepending scope %s to class %s\n",qPrint(yyextra->current_root->name),qPrint(yyextra->current->name)); + yyextra->current->name.prepend(yyextra->current_root->name+"::"); + } + + yyextra->current->name = yyextra->current->name.stripWhiteSpace(); + yyextra->current->fileName = yyextra->fileName; + yyextra->docBlockContext = YY_START; + yyextra->docBlockInBody = FALSE; + yyextra->docBlockJavaStyle = FALSE; + yyextra->docBlock.resize(0); + + BEGIN(ClassInheritance); } <ClassInheritance>{ @@ -984,57 +1007,57 @@ STARTDOCSYMS "##" } ":" { // begin of the class definition - yyextra->specialBlock = TRUE; // expecting a docstring + yyextra->specialBlock = TRUE; // expecting a docstring yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->program.str(std::string()); - BEGIN(ClassCaptureIndent); + yyextra->current->program.str(std::string()); + BEGIN(ClassCaptureIndent); } {SCOPE} { yyextra->current->extends.push_back( - BaseInfo(substitute(yytext,".","::"),Public,Normal) - ); + BaseInfo(substitute(yytext,".","::"),Public,Normal) + ); //Has base class-do stuff } - "'" { // start of a single quoted string - yyextra->stringContext=YY_START; + "'" { // start of a single quoted string + yyextra->stringContext=YY_START; BEGIN( SingleQuoteStringIgnore ); } "\"" { // start of a double quoted string - yyextra->stringContext=YY_START; + yyextra->stringContext=YY_START; BEGIN( DoubleQuoteStringIgnore ); } } <SingleQuoteStringIgnore>{ - "'" { // end of a single quoted string - BEGIN(yyextra->stringContext); + "'" { // end of a single quoted string + BEGIN(yyextra->stringContext); } - . { } + . { } } <DoubleQuoteStringIgnore>{ - "\"" { // end of a double quoted string - BEGIN(yyextra->stringContext); + "\"" { // end of a double quoted string + BEGIN(yyextra->stringContext); } - . { } + . { } } <ClassCaptureIndent>{ "\n"|({BB}"\n") { // Blankline - ignore, keep looking for indentation. - lineCount(yyscanner); - yyextra->current->program << yytext; + lineCount(yyscanner); + yyextra->current->program << yytext; } {TRIDOUBLEQUOTE} { // start of a comment block - initTriDoubleQuoteBlock(yyscanner); - yyextra->current->program << yytext; - BEGIN(TripleComment); - } + initTriDoubleQuoteBlock(yyscanner); + yyextra->current->program << yytext; + BEGIN(TripleComment); + } {TRISINGLEQUOTE} { // start of a comment block - initTriSingleQuoteBlock(yyscanner); - yyextra->current->program << yytext; - BEGIN(TripleComment); + initTriSingleQuoteBlock(yyscanner); + yyextra->current->program << yytext; + BEGIN(TripleComment); } {STARTDOCSYMS}[#]* { // start of a special comment initSpecialBlock(yyscanner); @@ -1042,25 +1065,25 @@ STARTDOCSYMS "##" } {POUNDCOMMENT} { // ignore comment with just one # } - ^{BB} { - yyextra->current->program << yytext; - //yyextra->current->startLine = yyextra->yyLineNr; - yyextra->curIndent=computeIndent(yytext); - yyextra->bodyEntry = yyextra->current; - DBG_CTX((stderr,"setting indent %d\n",yyextra->curIndent)); - //printf("yyextra->current->program=[%s]\n",qPrint(yyextra->current->program)); - //yyextra->hideClassDocs = TRUE; - BEGIN(ClassBody); + ^{BB} { + yyextra->current->program << yytext; + //yyextra->current->startLine = yyextra->yyLineNr; + yyextra->curIndent=computeIndent(yytext); + yyextra->bodyEntry = yyextra->current; + DBG_CTX((stderr,"setting indent %d\n",yyextra->curIndent)); + //printf("yyextra->current->program=[%s]\n",qPrint(yyextra->current->program)); + //yyextra->hideClassDocs = TRUE; + BEGIN(ClassBody); } ""/({NONEMPTY}|{EXPCHAR}) { - // Just pushback an empty class, and - // resume parsing the body. + // Just pushback an empty class, and + // resume parsing the body. newEntry(yyscanner); - yyextra->current->program << yytext; + yyextra->current->program << yytext; - // printf("Failed to find indent - skipping!"); - BEGIN( Search ); + // printf("Failed to find indent - skipping!"); + BEGIN( Search ); } } @@ -1069,88 +1092,88 @@ STARTDOCSYMS "##" "=" { // the assignment operator //printf("====== VariableDec at line %d\n",yyextra->yyLineNr); yyextra->start_init = TRUE; - yyextra->current->initializer.str(yytext); - yyextra->current->initializer << " "; + yyextra->current->initializer.str(yytext); + yyextra->current->initializer << " "; } {B} { // spaces - yyextra->current->initializer << yytext; - } - {INTNUMBER} { // integer value - if (yyextra->current-> type.isEmpty()) yyextra->current->type = "int"; - yyextra->current->initializer << yytext; - } + yyextra->current->initializer << yytext; + } + {INTNUMBER} { // integer value + if (yyextra->current-> type.isEmpty()) yyextra->current->type = "int"; + yyextra->current->initializer << yytext; + } {FLOATNUMBER} { // floating point value - if (yyextra->current->type.isEmpty()) yyextra->current->type = "float"; - yyextra->current->initializer << yytext; - } + if (yyextra->current->type.isEmpty()) yyextra->current->type = "float"; + yyextra->current->initializer << yytext; + } {BOOL} { // boolean value - if (yyextra->current->type.isEmpty()) yyextra->current->type = "bool"; - yyextra->current->initializer << yytext; - } + if (yyextra->current->type.isEmpty()) yyextra->current->type = "bool"; + yyextra->current->initializer << yytext; + } {STRINGPREFIX}?"'" { // string - if (yyextra->current->type.isEmpty()) yyextra->current->type = "string"; - yyextra->current->initializer << yytext; - yyextra->copyString=&yyextra->current->initializer; - yyextra->stringContext=VariableDec; + if (yyextra->current->type.isEmpty()) yyextra->current->type = "string"; + yyextra->current->initializer << yytext; + yyextra->copyString=&yyextra->current->initializer; + yyextra->stringContext=VariableDec; BEGIN( SingleQuoteString ); - } + } {STRINGPREFIX}?"\"" { // string - if (yyextra->current->type.isEmpty()) yyextra->current->type = "string"; - yyextra->current->initializer << yytext; - yyextra->copyString=&yyextra->current->initializer; - yyextra->stringContext=VariableDec; + if (yyextra->current->type.isEmpty()) yyextra->current->type = "string"; + yyextra->current->initializer << yytext; + yyextra->copyString=&yyextra->current->initializer; + yyextra->stringContext=VariableDec; BEGIN( DoubleQuoteString ); - } + } {TRIDOUBLEQUOTE} { // start of a comment block - if (yyextra->current->type.isEmpty()) yyextra->current->type = "string"; - yyextra->current->initializer << yytext; - yyextra->doubleQuote=TRUE; - yyextra->copyString=&yyextra->current->initializer; - yyextra->stringContext=VariableDec; - BEGIN(TripleString); + if (yyextra->current->type.isEmpty()) yyextra->current->type = "string"; + yyextra->current->initializer << yytext; + yyextra->doubleQuote=TRUE; + yyextra->copyString=&yyextra->current->initializer; + yyextra->stringContext=VariableDec; + BEGIN(TripleString); } {TRISINGLEQUOTE} { // start of a comment block - if (yyextra->current->type.isEmpty()) yyextra->current->type = "string"; - yyextra->current->initializer << yytext; - yyextra->doubleQuote=FALSE; - yyextra->copyString=&yyextra->current->initializer; - yyextra->stringContext=VariableDec; - BEGIN(TripleString); - } - "(" { // tuple, only when direct after = + if (yyextra->current->type.isEmpty()) yyextra->current->type = "string"; + yyextra->current->initializer << yytext; + yyextra->doubleQuote=FALSE; + yyextra->copyString=&yyextra->current->initializer; + yyextra->stringContext=VariableDec; + BEGIN(TripleString); + } + "(" { // tuple, only when direct after = if (yyextra->current->mtype!=Property && yyextra->start_init) - { - yyextra->current->type = "tuple"; - } - yyextra->current->initializer << *yytext; + { + yyextra->current->type = "tuple"; + } + yyextra->current->initializer << *yytext; yyextra->atomStart='('; - yyextra->atomEnd=')'; - yyextra->atomCount=1; - BEGIN( VariableAtom ); + yyextra->atomEnd=')'; + yyextra->atomCount=1; + BEGIN( VariableAtom ); } "[" { // list if (yyextra->start_init) yyextra->current->type = "list"; - yyextra->current->initializer << *yytext; + yyextra->current->initializer << *yytext; yyextra->atomStart='['; - yyextra->atomEnd=']'; - yyextra->atomCount=1; - BEGIN( VariableAtom ); + yyextra->atomEnd=']'; + yyextra->atomCount=1; + BEGIN( VariableAtom ); } - "{" { // dictionary + "{" { // dictionary if (yyextra->start_init) yyextra->current->type = "dictionary"; - yyextra->current->initializer << *yytext; + yyextra->current->initializer << *yytext; yyextra->atomStart='{'; - yyextra->atomEnd='}'; - yyextra->atomCount=1; - BEGIN( VariableAtom ); + yyextra->atomEnd='}'; + yyextra->atomCount=1; + BEGIN( VariableAtom ); } "#".* { // comment - BEGIN( VariableEnd ); + BEGIN( VariableEnd ); } - {IDENTIFIER} { - // do something based on the type of the IDENTIFIER - if (yyextra->current->type.isEmpty()) + {IDENTIFIER} { + // do something based on the type of the IDENTIFIER + if (yyextra->current->type.isEmpty()) { for (const auto &child : yyextra->current_root->children()) { @@ -1162,270 +1185,277 @@ STARTDOCSYMS "##" } } yyextra->start_init = FALSE; - yyextra->current->initializer << yytext; - } - . { + yyextra->current->initializer << yytext; + } + . { yyextra->start_init = FALSE; - yyextra->current->initializer << *yytext; + yyextra->current->initializer << *yytext; + } + \n { + unput('\n'); + BEGIN( VariableEnd ); } - \n { - unput('\n'); - BEGIN( VariableEnd ); - } } <VariableAtom>{ - [\(\[\{] { - yyextra->current->initializer << *yytext; + [\(\[\{] { + yyextra->current->initializer << *yytext; if (yyextra->atomStart==*yytext) - { - yyextra->atomCount++; - } + { + yyextra->atomCount++; + } } - [\)\]\}] { - yyextra->current->initializer << *yytext; + [\)\]\}] { + yyextra->current->initializer << *yytext; if (yyextra->atomEnd==*yytext) - { - yyextra->atomCount--; - } - if (yyextra->atomCount==0) - { + { + yyextra->atomCount--; + } + if (yyextra->atomCount==0) + { yyextra->start_init = FALSE; - BEGIN(VariableDec); - } + BEGIN(VariableDec); + } } {TRIDOUBLEQUOTE} { // start of a comment block yyextra->specialBlock = FALSE; - yyextra->current->program << yytext; - initTriDoubleQuoteBlock(yyscanner); - BEGIN(TripleComment); + yyextra->current->program << yytext; + initTriDoubleQuoteBlock(yyscanner); + BEGIN(TripleComment); } {TRISINGLEQUOTE} { // start of a comment block yyextra->specialBlock = FALSE; - yyextra->current->program << yytext; - initTriSingleQuoteBlock(yyscanner); - BEGIN(TripleComment); - } - "'" { - yyextra->stringContext=YY_START; - yyextra->current->initializer << "'"; - yyextra->copyString=&yyextra->current->initializer; + yyextra->current->program << yytext; + initTriSingleQuoteBlock(yyscanner); + BEGIN(TripleComment); + } + "'" { + yyextra->stringContext=YY_START; + yyextra->current->initializer << "'"; + yyextra->copyString=&yyextra->current->initializer; BEGIN( SingleQuoteString ); } - "\"" { - yyextra->stringContext=YY_START; - yyextra->current->initializer << "\""; - yyextra->copyString=&yyextra->current->initializer; + "\"" { + yyextra->stringContext=YY_START; + yyextra->current->initializer << "\""; + yyextra->copyString=&yyextra->current->initializer; BEGIN( DoubleQuoteString ); } {IDENTIFIER} { - yyextra->current->initializer << yytext; - } - . { - yyextra->current->initializer << *yytext; + yyextra->current->initializer << yytext; + } + . { + yyextra->current->initializer << *yytext; + } + \n { + yyextra->current->initializer << *yytext; + incLineNr(yyscanner); } - \n { - yyextra->current->initializer << *yytext; - incLineNr(yyscanner); - } } <VariableEnd>{ \n { incLineNr(yyscanner); - newVariable(yyscanner); + newVariable(yyscanner); BEGIN(Search); } - . { + . { unput(*yytext); - newVariable(yyscanner); + newVariable(yyscanner); BEGIN(Search); - } + } <<EOF>> { yyterminate(); } } <TripleComment>{ - {ENDTRIDOUBLEQUOTE} | + {ENDTRIDOUBLEQUOTE} | {ENDTRISINGLEQUOTE} { - // printf("Expected module block %d special=%d\n",yyextra->expectModuleDocs,yyextra->specialBlock); - if (yyextra->doubleQuote==(yytext[0]=='"')) - { - if (yyextra->specialBlock) // expecting a docstring - { - QCString actualDoc=yyextra->docBlock; - if (!yyextra->docBlockSpecial) // legacy unformatted docstring - { + // printf("Expected module block %d special=%d\n",yyextra->expectModuleDocs,yyextra->specialBlock); + if (yyextra->doubleQuote==(yytext[0]=='"')) + { + if (yyextra->specialBlock) // expecting a docstring + { + QCString actualDoc=yyextra->docBlock; + if (!yyextra->docBlockSpecial) // legacy unformatted docstring + { if (!actualDoc.isEmpty()) { stripIndentation(actualDoc,yyextra->commentIndent); - actualDoc.prepend("\\verbatim\n"); - actualDoc.append("\\endverbatim "); - } - } - //printf("-------> yyextra->current=%p yyextra->bodyEntry=%p\n",yyextra->current,yyextra->bodyEntry); - handleCommentBlock(yyscanner, actualDoc, FALSE); - } - else if (yyextra->packageCommentAllowed) // expecting module docs - { - QCString actualDoc=yyextra->docBlock; - if (!yyextra->docBlockSpecial) // legacy unformatted docstring - { + actualDoc.prepend("\\verbatim\n"); + actualDoc.append("\\endverbatim "); + } + } + //printf("-------> yyextra->current=%p yyextra->bodyEntry=%p\n",yyextra->current,yyextra->bodyEntry); + handleCommentBlock(yyscanner, actualDoc, FALSE); + } + else if (yyextra->packageCommentAllowed) // expecting module docs + { + QCString actualDoc=yyextra->docBlock; + if (!yyextra->docBlockSpecial) // legacy unformatted docstring + { if (!actualDoc.isEmpty()) { stripIndentation(actualDoc,yyextra->commentIndent); - actualDoc.prepend("\\verbatim\n"); - actualDoc.append("\\endverbatim "); - } - } - actualDoc.prepend("\\namespace "+yyextra->moduleScope+" "); - handleCommentBlock(yyscanner, actualDoc, FALSE); - } - if ((yyextra->docBlockContext==ClassBody /*&& !yyextra->hideClassDocs*/) || - yyextra->docBlockContext==FunctionBody) - { - yyextra->current->program << yyextra->docBlock; - yyextra->current->program << yytext; - } + actualDoc.prepend("\\verbatim\n"); + actualDoc.append("\\endverbatim "); + } + } + if (yyextra->moduleScope.startsWith("__") && yyextra->moduleScope.endsWith("__")) + { + actualDoc.prepend("\\namespace \\"+yyextra->moduleScope+" "); + } + else + { + actualDoc.prepend("\\namespace "+yyextra->moduleScope+" "); + } + handleCommentBlock(yyscanner, actualDoc, FALSE); + } + if ((yyextra->docBlockContext==ClassBody /*&& !yyextra->hideClassDocs*/) || + yyextra->docBlockContext==FunctionBody) + { + yyextra->current->program << yyextra->docBlock; + yyextra->current->program << yytext; + } //if (yyextra->hideClassDocs) - //{ + //{ // yyextra->current->startLine = yyextra->yyLineNr; - //} - //yyextra->hideClassDocs=FALSE; - BEGIN(yyextra->docBlockContext); - } - else - { + //} + //yyextra->hideClassDocs=FALSE; + BEGIN(yyextra->docBlockContext); + } + else + { yyextra->docBlock += yytext; } - yyextra->packageCommentAllowed = FALSE; + yyextra->packageCommentAllowed = FALSE; } - ^{BB} { // leading whitespace - yyextra->docBlock += yytext; - } + ^{BB} { // leading whitespace + yyextra->docBlock += yytext; + } [^"'\n \t\\]+ { - yyextra->docBlock += yytext; - } - \n { - incLineNr(yyscanner); - yyextra->docBlock += yytext; - } - \\. { // escaped char - yyextra->docBlock += yytext; - } - . { - yyextra->docBlock += yytext; - } + yyextra->docBlock += yytext; + } + \n { + incLineNr(yyscanner); + yyextra->docBlock += yytext; + } + \\. { // escaped char + yyextra->docBlock += yytext; + } + . { + yyextra->docBlock += yytext; + } } <SpecialComment>{ - ^{B}"#"("#")* { // skip leading hashes - } - \n/{B}"#" { // continuation of the comment on the next line - yyextra->docBlock+='\n'; - yyextra->docBrief = FALSE; - incLineNr(yyscanner); - } + ^{B}"#"("#")* { // skip leading hashes + } + \n/{B}"#" { // continuation of the comment on the next line + yyextra->docBlock+='\n'; + yyextra->docBrief = FALSE; + incLineNr(yyscanner); + } [^#\n]+ { // any other stuff - yyextra->docBlock+=yytext; - } - \n { // new line that ends the comment - handleCommentBlock(yyscanner, yyextra->docBlock, yyextra->docBrief); - incLineNr(yyscanner); - BEGIN(yyextra->docBlockContext); - } - . { // anything we missed - yyextra->docBlock+=*yytext; - } + yyextra->docBlock+=yytext; + } + \n { // new line that ends the comment + handleCommentBlock(yyscanner, yyextra->docBlock, yyextra->docBrief); + incLineNr(yyscanner); + BEGIN(yyextra->docBlockContext); + } + . { // anything we missed + yyextra->docBlock+=*yytext; + } } <SingleQuoteString>{ \\{B}\n { // line continuation - addToString(yyscanner,yytext); - incLineNr(yyscanner); + addToString(yyscanner,yytext); + incLineNr(yyscanner); } - \\. { // escaped char - addToString(yyscanner,yytext); + \\. { // escaped char + addToString(yyscanner,yytext); } - "\"\"\"" { // triple double quotes - addToString(yyscanner,yytext); - } - "'" { // end of the string - addToString(yyscanner,yytext); - BEGIN(yyextra->stringContext); + "\"\"\"" { // triple double quotes + addToString(yyscanner,yytext); } - [^"'\n\\]+ { // normal chars - addToString(yyscanner,yytext); + "'" { // end of the string + addToString(yyscanner,yytext); + BEGIN(yyextra->stringContext); } - . { // normal char - addToString(yyscanner,yytext); + [^"'\n\\]+ { // normal chars + addToString(yyscanner,yytext); + } + . { // normal char + addToString(yyscanner,yytext); } } <DoubleQuoteString>{ \\{B}\n { // line continuation - addToString(yyscanner,yytext); - incLineNr(yyscanner); + addToString(yyscanner,yytext); + incLineNr(yyscanner); + } + \\. { // escaped char + addToString(yyscanner,yytext); } - \\. { // escaped char - addToString(yyscanner,yytext); + "'''" { // triple single quotes + addToString(yyscanner,yytext); } - "'''" { // triple single quotes - addToString(yyscanner,yytext); - } - "\"" { // end of the string - addToString(yyscanner,yytext); - BEGIN(yyextra->stringContext); + "\"" { // end of the string + addToString(yyscanner,yytext); + BEGIN(yyextra->stringContext); } - [^"'\n\\]+ { // normal chars - addToString(yyscanner,yytext); + [^"'\n\\]+ { // normal chars + addToString(yyscanner,yytext); } - . { // normal char - addToString(yyscanner,yytext); + . { // normal char + addToString(yyscanner,yytext); } } <TripleString>{ - {ENDTRIDOUBLEQUOTE} | + {ENDTRIDOUBLEQUOTE} | {ENDTRISINGLEQUOTE} { *yyextra->copyString << yytext; - if (yyextra->doubleQuote==(yytext[0]=='"')) - { - BEGIN(yyextra->stringContext); - } + if (yyextra->doubleQuote==(yytext[0]=='"')) + { + BEGIN(yyextra->stringContext); + } } ({LONGSTRINGBLOCK}) { - lineCount(yyscanner); + lineCount(yyscanner); *yyextra->copyString << yytext; } - \n { - incLineNr(yyscanner); + \n { + incLineNr(yyscanner); *yyextra->copyString << yytext; - } - . { + } + . { *yyextra->copyString << *yytext; - } + } } /* ------------ End rules -------------- */ /* <*>({NONEMPTY}|{EXPCHAR}|{BB}) { // This should go one character at a time. - // printf("[pyscanner] '%s' [ state %d ] [line %d] no match\n", - // yytext, YY_START, yyextra->yyLineNr); + // printf("[pyscanner] '%s' [ state %d ] [line %d] no match\n", + // yytext, YY_START, yyextra->yyLineNr); } */ <*>{NEWLINE} { - //printf("[pyscanner] %d NEWLINE [line %d] no match\n", - // YY_START, yyextra->yyLineNr); + //printf("[pyscanner] %d NEWLINE [line %d] no match\n", + // YY_START, yyextra->yyLineNr); lineCount(yyscanner); } @@ -1435,8 +1465,8 @@ STARTDOCSYMS "##" } <*>. { - //printf("[pyscanner] '%s' [ state %d ] [line %d] no match\n", - // yytext, YY_START, yyextra->yyLineNr); + //printf("[pyscanner] '%s' [ state %d ] [line %d] no match\n", + // yytext, YY_START, yyextra->yyLineNr); } @@ -1474,7 +1504,7 @@ static void initEntry(yyscan_t yyscanner) yyextra->current->mtype = yyextra->mtype; yyextra->current->virt = yyextra->virt; yyextra->current->stat = yyextra->stat; - yyextra->current->lang = SrcLangExt_Python; + yyextra->current->lang = SrcLangExt_Python; yyextra->commentScanner.initGroupInfo(yyextra->current.get()); yyextra->stat = FALSE; } @@ -1548,7 +1578,7 @@ static QCString findPackageScopeFromPath(yyscan_t yyscanner,const QCString &path QCString scope = findPackageScopeFromPath(yyscanner,path.left(i)); if (!scope.isEmpty()) { - scope+="::"; + scope+="::"; } scope+=path.mid(i+1); yyextra->packageNameCache.insert(std::make_pair(path.str(),scope.str())); @@ -1570,8 +1600,8 @@ static void addFrom(yyscan_t yyscanner,bool all) struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; QCString item=all ? yyextra->packageName : yyextra->packageName+"."+yytext; yyextra->current->name=removeRedundantWhiteSpace(substitute(item,".","::")); - yyextra->current->fileName = yyextra->yyFileName; - //printf("Adding using declaration: found:%s:%d name=%s\n",qPrint(yyextra->yyFileName),yyextra->yyLineNr,qPrint(yyextra->current->name)); + yyextra->current->fileName = yyextra->fileName; + //printf("Adding using declaration: found:%s:%d name=%s\n",qPrint(yyextra->fileName),yyextra->yyLineNr,qPrint(yyextra->current->name)); yyextra->current->section=all ? Entry::USINGDIR_SEC : Entry::USINGDECL_SEC; yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); initEntry(yyscanner); @@ -1601,12 +1631,12 @@ static void startCommentBlock(yyscan_t yyscanner,bool brief) struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (brief) { - yyextra->current->briefFile = yyextra->yyFileName; + yyextra->current->briefFile = yyextra->fileName; yyextra->current->briefLine = yyextra->yyLineNr; } else { - yyextra->current->docFile = yyextra->yyFileName; + yyextra->current->docFile = yyextra->fileName; yyextra->current->docLine = yyextra->yyLineNr; } } @@ -1619,7 +1649,7 @@ static void handleCommentBlock(yyscan_t yyscanner,const QCString &doc,bool brief // TODO: Fix me yyextra->docBlockInBody=FALSE; - + if (!yyextra->current->doc.isEmpty()) { yyextra->current->doc=yyextra->current->doc.stripWhiteSpace()+"\n\n"; @@ -1632,15 +1662,15 @@ static void handleCommentBlock(yyscan_t yyscanner,const QCString &doc,bool brief int position = 0; bool needsEntry = false; int lineNr = brief ? yyextra->current->briefLine : yyextra->current->docLine; - Markdown markdown(yyextra->yyFileName,lineNr); + Markdown markdown(yyextra->fileName,lineNr); QCString processedDoc = Config_getBool(MARKDOWN_SUPPORT) ? markdown.process(doc,lineNr) : doc; while (yyextra->commentScanner.parseCommentBlock( yyextra->thisParser, (yyextra->docBlockInBody && yyextra->previous) ? yyextra->previous.get() : yyextra->current.get(), processedDoc, // text - yyextra->yyFileName, // file + yyextra->fileName, // file lineNr, - yyextra->docBlockInBody ? FALSE : brief, + yyextra->docBlockInBody ? FALSE : brief, yyextra->docBlockJavaStyle, // javadoc style // or FALSE, yyextra->docBlockInBody, yyextra->protection, @@ -1721,7 +1751,7 @@ static void initSpecialBlock(yyscan_t yyscanner) static void searchFoundDef(yyscan_t yyscanner) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->bodyLine = yyextra->yyLineNr; yyextra->current->section = Entry::FUNCTION_SEC; @@ -1744,7 +1774,7 @@ static void searchFoundClass(yyscan_t yyscanner) yyextra->current->section = Entry::CLASS_SEC; yyextra->current->argList.clear(); yyextra->current->type += "class" ; - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->bodyLine = yyextra->yyLineNr; yyextra->packageCommentAllowed = FALSE; @@ -1776,17 +1806,17 @@ static void parseCompounds(yyscan_t yyscanner,std::shared_ptr<Entry> rt) else if (ce->parent()) { yyextra->current_root = rt; - //printf("Searching for member variables in %s parent=%s\n", - // qPrint(ce->name),qPrint(ce->parent->name)); - BEGIN( SearchMemVars ); + //printf("Searching for member variables in %s parent=%s\n", + // qPrint(ce->name),qPrint(ce->parent->name)); + BEGIN( SearchMemVars ); } - yyextra->yyFileName = ce->fileName; + yyextra->fileName = ce->fileName; yyextra->yyLineNr = ce->bodyLine ; yyextra->current = std::make_shared<Entry>(); initEntry(yyscanner); QCString name = ce->name; - yyextra->commentScanner.enterCompound(yyextra->yyFileName,yyextra->yyLineNr,name); + yyextra->commentScanner.enterCompound(yyextra->fileName,yyextra->yyLineNr,name); pyscannerYYlex(yyscanner) ; yyextra->lexInit=TRUE; @@ -1794,7 +1824,7 @@ static void parseCompounds(yyscan_t yyscanner,std::shared_ptr<Entry> rt) yyextra->programStr.resize(0); ce->program.str(std::string()); - yyextra->commentScanner.leaveCompound(yyextra->yyFileName,yyextra->yyLineNr,name); + yyextra->commentScanner.leaveCompound(yyextra->fileName,yyextra->yyLineNr,name); } parseCompounds(yyscanner,ce); @@ -1821,10 +1851,10 @@ static void parseMain(yyscan_t yyscanner, const QCString &fileName,const char *f yyextra->current_root = rt; yyextra->specialBlock = FALSE; - yyextra->yyLineNr= 1 ; - yyextra->yyFileName = fileName; + yyextra->yyLineNr= 1 ; + yyextra->fileName = fileName; //setContext(); - msg("Parsing file %s...\n",qPrint(yyextra->yyFileName)); + msg("Parsing file %s...\n",qPrint(yyextra->fileName)); FileInfo fi(fileName.str()); yyextra->moduleScope = findPackageScope(yyscanner,fileName); @@ -1852,7 +1882,7 @@ static void parseMain(yyscan_t yyscanner, const QCString &fileName,const char *f yyextra->current->name = scope.left(pos); yyextra->current->section = Entry::NAMESPACE_SEC; yyextra->current->type = "namespace"; - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->bodyLine = yyextra->yyLineNr; yyextra->current_root = yyextra->current; @@ -1861,7 +1891,7 @@ static void parseMain(yyscan_t yyscanner, const QCString &fileName,const char *f initParser(yyscanner); - yyextra->commentScanner.enterFile(yyextra->yyFileName,yyextra->yyLineNr); + yyextra->commentScanner.enterFile(yyextra->fileName,yyextra->yyLineNr); yyextra->current->reset(); initEntry(yyscanner); @@ -1870,7 +1900,7 @@ static void parseMain(yyscan_t yyscanner, const QCString &fileName,const char *f pyscannerYYlex(yyscanner); yyextra->lexInit=TRUE; - yyextra->commentScanner.leaveFile(yyextra->yyFileName,yyextra->yyLineNr); + yyextra->commentScanner.leaveFile(yyextra->fileName,yyextra->yyLineNr); yyextra->programStr.resize(0); yyextra->current_root->program.str(std::string()); @@ -1884,9 +1914,9 @@ static void parsePrototype(yyscan_t yyscanner,const QCString &text) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; //printf("**** parsePrototype(%s) begin\n",qPrint(text)); - if (text.isEmpty()) + if (text.isEmpty()) { - warn(yyextra->yyFileName,yyextra->yyLineNr,"Empty prototype found!"); + warn(yyextra->fileName,yyextra->yyLineNr,"Empty prototype found!"); return; } @@ -1896,11 +1926,11 @@ static void parsePrototype(yyscan_t yyscanner,const QCString &text) const char *orgInputString; yy_size_t orgInputPosition; YY_BUFFER_STATE orgState; - + // save scanner state orgState = YY_CURRENT_BUFFER; yy_switch_to_buffer(yy_create_buffer(0, YY_BUF_SIZE, yyscanner), yyscanner); - orgInputString = yyextra->inputString; + orgInputString = yyextra->inputString; orgInputPosition = yyextra->inputPosition; // set new string @@ -1922,7 +1952,7 @@ static void parsePrototype(yyscan_t yyscanner,const QCString &text) yy_delete_buffer(YY_CURRENT_BUFFER, yyscanner); yy_switch_to_buffer(orgState, yyscanner); - yyextra->inputString = orgInputString; + yyextra->inputString = orgInputString; yyextra->inputPosition = orgInputPosition; //printf("**** parsePrototype end\n"); diff --git a/src/qcstring.h b/src/qcstring.h index b8eb3e6..6d3d198 100644 --- a/src/qcstring.h +++ b/src/qcstring.h @@ -251,6 +251,32 @@ class QCString return QCString(m_rep.substr(start,1+end-start)); } + // Returns a quoted copy of this string, unless it is already quoted. + // Note that trailing and leading whitespace is removed. + QCString quoted() const + { + size_t start=0, sl=m_rep.size(), end=sl-1; + while (start<sl && qisspace(m_rep[start])) start++; // skip over leading whitespace + if (start==sl) return QCString(); // only whitespace + while (end>start && qisspace(m_rep[end])) end--; // skip over trailing whitespace + bool needsQuotes=false; + size_t i=start; + if (i<end && m_rep[i]!='"') // stripped string has at least non-whitespace unquoted character + { + while (i<end && !needsQuotes) // check if the to be quoted part has at least one whitespace character + { + needsQuotes = qisspace(m_rep[i++]); + } + } + QCString result(m_rep.substr(start,1+end-start)); + if (needsQuotes) + { + result.prepend("\""); + result.append("\""); + } + return result; + } + /// returns a copy of this string with all whitespace removed QCString removeWhiteSpace() const { diff --git a/src/qhp.cpp b/src/qhp.cpp index fc2f215..cac54d3 100644 --- a/src/qhp.cpp +++ b/src/qhp.cpp @@ -38,7 +38,7 @@ static QCString makeFileName(const QCString & withoutExtension) } else // add specified HTML extension { - result+=Doxygen::htmlFileExtension; + addHtmlExtensionIfMissing(result); } } return result; @@ -53,7 +53,7 @@ static QCString makeRef(const QCString & withoutExtension, const QCString & anch return result+"#"+anchor; } -Qhp::Qhp() : m_prevSectionLevel(0), m_sectionLevel(0), m_skipMainPageSection(FALSE) +Qhp::Qhp() { m_doc.setIndentLevel(0); m_toc.setIndentLevel(2); @@ -136,6 +136,7 @@ void Qhp::initialize() NULL }; m_toc.open("section", attributes); + m_openCount=1; m_prevSectionTitle = getFullProjectName(); m_prevSectionLevel = 1; m_sectionLevel = 1; @@ -148,9 +149,10 @@ void Qhp::finalize() { // Finish TOC handlePrevSection(); - for (int i = m_prevSectionLevel; i > 0; i--) + while (m_openCount>0) { m_toc.close("section"); + m_openCount--; } m_toc.close("toc"); m_doc.insert(m_toc); @@ -210,9 +212,11 @@ void Qhp::addContentsItem(bool /*isDir*/, const QCString & name, // Close sections as needed //printf("Qhp::addContentsItem() closing %d sections\n",diff); - for (; diff > 0; diff--) + while (diff>0) { m_toc.close("section"); + m_openCount--; + diff--; } } @@ -223,7 +227,7 @@ void Qhp::addIndexItem(const Definition *context,const MemberDef *md, //printf("addIndexItem(%s %s %s\n", // context?context->name().data():"<none>", // md?md->name().data():"<none>", - // word); + // qPrint(word)); if (md) // member { @@ -326,6 +330,7 @@ void Qhp::handlePrevSection() { // Section with children m_toc.open("section", attributes); + m_openCount++; } else { @@ -61,10 +61,10 @@ class Qhp : public IndexIntf QCString m_prevSectionBaseName; QCString m_prevSectionAnchor; - int m_prevSectionLevel; - int m_sectionLevel; - - bool m_skipMainPageSection; + int m_prevSectionLevel = 0; + int m_sectionLevel = 0; + int m_openCount = 0; + bool m_skipMainPageSection = false; }; #endif // DOXYGEN_QHP_H diff --git a/src/reflist.cpp b/src/reflist.cpp index 9a32449..ffa6128 100644 --- a/src/reflist.cpp +++ b/src/reflist.cpp @@ -75,8 +75,8 @@ void RefList::generatePage() if (!first) { doc += "</dd>"; - first=false; } + first=false; doc += " <dt>"; doc += "\n"; if (item->scope()) diff --git a/src/regex.cpp b/src/regex.cpp index 2a39f63..6286b0b 100644 --- a/src/regex.cpp +++ b/src/regex.cpp @@ -178,7 +178,8 @@ class Ex::Private #if ENABLE_DEBUG void dump(); #endif - bool matchAt(size_t tokenPos,const std::string &str,Match &match,size_t pos,int level) const; + bool matchAt(size_t tokenPos,size_t tokenLen,const std::string &str, + Match &match,size_t pos,int level) const; /** Flag indicating the expression was successfully compiled */ bool error = false; @@ -377,6 +378,14 @@ void Ex::Private::compile() prevTokenPos+=ddiff; tokenPos+=ddiff; } + if (data[prevTokenPos].kind()==PToken::Kind::EndCapture) + { + // find the beginning of the capture range + while (prevTokenPos>0 && data[prevTokenPos].kind()!=PToken::Kind::BeginCapture) + { + prevTokenPos--; + } + } data.insert(data.begin()+prevTokenPos, c=='?' ? PToken(PToken::Kind::Optional) : PToken(PToken::Kind::Star)); tokenPos++; @@ -430,14 +439,15 @@ void Ex::Private::dump() /** Internal matching routine. * @param tokenPos Offset into the token stream. + * @param tokenLen The length of the token stream. * @param str The input string to match against. * @param match The object used to store the matching results. * @param pos The position in the input string to start with matching * @param level Recursion level (used for debugging) */ -bool Ex::Private::matchAt(size_t tokenPos,const std::string &str,Match &match,const size_t pos,int level) const +bool Ex::Private::matchAt(size_t tokenPos,size_t tokenLen,const std::string &str,Match &match,const size_t pos,int level) const { - DBG("%d:matchAt(tokenPos=%zu, str='%s', pos=%zu)\n",level,tokenPos,str.c_str(),pos); + DBG("%d:matchAt(tokenPos=%zu, str='%s', pos=%zu)\n",level,tokenPos,pos<str.length() ? str.substr(pos).c_str() : "",pos); auto isStartIdChar = [](char c) { return isalpha(c) || c=='_'; }; auto isIdChar = [](char c) { return isalnum(c) || c=='_'; }; auto matchCharClass = [this,isStartIdChar,isIdChar](size_t tp,char c) -> bool @@ -473,8 +483,8 @@ bool Ex::Private::matchAt(size_t tokenPos,const std::string &str,Match &match,co return negate ? !found : found; }; size_t index = pos; - enum SequenceType { Star, Optional }; - auto processSequence = [this,&tokenPos,&index,&str,&matchCharClass, + enum SequenceType { Star, Optional, OptionalRange }; + auto processSequence = [this,&tokenPos,&tokenLen,&index,&str,&matchCharClass, &isStartIdChar,&isIdChar,&match,&level,&pos](SequenceType type) -> bool { size_t startIndex = index; @@ -515,11 +525,24 @@ bool Ex::Private::matchAt(size_t tokenPos,const std::string &str,Match &match,co if (type==Optional) index++; else index = str.length(); tokenPos++; } + else if (type==OptionalRange && tok.kind()==PToken::Kind::BeginCapture) + { + size_t tokenStart = ++tokenPos; + while (tokenPos<tokenLen && data[tokenPos].kind()!=PToken::Kind::EndCapture) { tokenPos++; } + Match rangeMatch; + rangeMatch.init(&str); + bool found = matchAt(tokenStart,tokenPos,str,rangeMatch,index,level+1); + if (found) + { + index+=rangeMatch.length(); // (abc)? matches -> eat all + } + tokenPos++; // skip over EndCapture + } tokenPos++; // skip over end marker while ((int)index>=(int)startIndex) { // pattern 'x*xy' should match 'xy' and 'xxxxy' - bool found = matchAt(tokenPos,str,match,index,level+1); + bool found = matchAt(tokenPos,tokenLen,str,match,index,level+1); if (found) { match.setMatch(pos,index-pos+match.length()); @@ -530,10 +553,10 @@ bool Ex::Private::matchAt(size_t tokenPos,const std::string &str,Match &match,co return false; }; - while (tokenPos<data.size()) + while (tokenPos<tokenLen) { PToken tok = data[tokenPos]; - //DBG("loop tokenPos=%zu token=%s\n",tokenPos,tok.kindStr()); + DBG("loop tokenPos=%zu token=%s\n",tokenPos,tok.kindStr()); if (tok.kind()==PToken::Kind::Character) // match literal character { char c_tok = tok.asciiValue(); @@ -603,7 +626,14 @@ bool Ex::Private::matchAt(size_t tokenPos,const std::string &str,Match &match,co case PToken::Kind::Star: return processSequence(Star); case PToken::Kind::Optional: - return processSequence(Optional); + if (tokenPos<tokenLen-1 && data[tokenPos+1].kind()==PToken::Kind::BeginCapture) + { + return processSequence(OptionalRange); // (...)? + } + else + { + return processSequence(Optional); // x? + } default: return false; } @@ -682,7 +712,7 @@ bool Ex::match(const std::string &str,Match &match,size_t pos) const PToken tok = p->data[0]; if (tok.kind()==PToken::Kind::BeginOfLine) // only test match at the given position { - found = p->matchAt(0,str,match,pos,0); + found = p->matchAt(0,p->data.size(),str,match,pos,0); } else { @@ -699,7 +729,7 @@ bool Ex::match(const std::string &str,Match &match,size_t pos) const } while (pos<str.length()) // search for a match starting at pos { - found = p->matchAt(0,str,match,pos,0); + found = p->matchAt(0,p->data.size(),str,match,pos,0); if (found) break; pos++; } diff --git a/src/rtfdocvisitor.cpp b/src/rtfdocvisitor.cpp index 025cc90..49a6f33 100644 --- a/src/rtfdocvisitor.cpp +++ b/src/rtfdocvisitor.cpp @@ -57,21 +57,29 @@ static QCString align(DocHtmlCell *cell) RTFDocVisitor::RTFDocVisitor(TextStream &t,CodeOutputInterface &ci, const QCString &langExt) - : DocVisitor(DocVisitor_RTF), m_t(t), m_ci(ci), m_insidePre(FALSE), - m_hide(FALSE), m_indentLevel(0), m_lastIsPara(FALSE), m_langExt(langExt) + : DocVisitor(DocVisitor_RTF), m_t(t), m_ci(ci), m_langExt(langExt) { } QCString RTFDocVisitor::getStyle(const QCString &name) { - QCString n = name + QCString().setNum(m_indentLevel); + QCString n = name + QCString().setNum(indentLevel()); StyleData &sd = rtf_Style[n.str()]; return sd.reference(); } +int RTFDocVisitor::indentLevel() const +{ + return std::min(m_indentLevel,maxIndentLevels-1); +} + void RTFDocVisitor::incIndentLevel() { - if (m_indentLevel<rtf_maxIndentLevels-1) m_indentLevel++; + m_indentLevel++; + if (m_indentLevel>=maxIndentLevels) + { + err("Maximum indent level (%d) exceeded while generating RTF output!\n",maxIndentLevels-1); + } } void RTFDocVisitor::decIndentLevel() @@ -79,7 +87,7 @@ void RTFDocVisitor::decIndentLevel() if (m_indentLevel>0) m_indentLevel--; } - //-------------------------------------- + //------------------------------------ // visitor functions for leaf nodes //-------------------------------------- @@ -257,6 +265,9 @@ void RTFDocVisitor::visit(DocStyleChange *s) case DocStyleChange::Small: if (s->enable()) m_t << "{\\sub "; else m_t << "} "; break; + case DocStyleChange::Cite: + if (s->enable()) m_t << "{\\i "; else m_t << "} "; + break; case DocStyleChange::Preformatted: if (s->enable()) { @@ -275,6 +286,22 @@ void RTFDocVisitor::visit(DocStyleChange *s) break; case DocStyleChange::Div: /* HTML only */ break; case DocStyleChange::Span: /* HTML only */ break; + case DocStyleChange::Details: /* emulation of the <details> tag */ + if (s->enable()) + { + m_t << "{\n"; + m_t << "\\par\n"; + } + else + { + m_t << "\\par"; + m_t << "}\n"; + } + m_lastIsPara=TRUE; + break; + case DocStyleChange::Summary: /* emulation of the <summary> tag inside a <details> tag */ + if (s->enable()) m_t << "{\\b "; else m_t << "} "; + break; } } @@ -304,6 +331,16 @@ void RTFDocVisitor::visit(DocVerbatim *s) //m_t << "\\par\n"; m_t << "}\n"; break; + case DocVerbatim::JavaDocLiteral: + filter(s->text(),TRUE); + break; + case DocVerbatim::JavaDocCode: + m_t << "{\n"; + m_t << "{\\f2 "; + filter(s->text(),TRUE); + m_t << "}"; + m_t << "}\n"; + break; case DocVerbatim::Verbatim: m_t << "{\n"; m_t << "\\par\n"; @@ -402,7 +439,7 @@ void RTFDocVisitor::visit(DocAnchor *anc) QCString anchor; if (!anc->file().isEmpty()) { - anchor+=anc->file(); + anchor+=stripPath(anc->file()); } if (!anc->file().isEmpty() && !anc->anchor().isEmpty()) { @@ -658,8 +695,10 @@ void RTFDocVisitor::visitPre(DocAutoList *l) if (m_hide) return; DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocAutoList)}\n"); m_t << "{\n"; - rtf_listItemInfo[m_indentLevel].isEnum = l->isEnumList(); - rtf_listItemInfo[m_indentLevel].number = 1; + int level = indentLevel(); + m_listItemInfo[level].isEnum = l->isEnumList(); + m_listItemInfo[level].type = '1'; + m_listItemInfo[level].number = 1; m_lastIsPara=FALSE; } @@ -670,7 +709,7 @@ void RTFDocVisitor::visitPost(DocAutoList *) if (!m_lastIsPara) m_t << "\\par"; m_t << "}\n"; m_lastIsPara=TRUE; - if (!m_indentLevel) m_t << "\\par\n"; + if (indentLevel()==0) m_t << "\\par\n"; } void RTFDocVisitor::visitPre(DocAutoListItem *) @@ -679,11 +718,12 @@ void RTFDocVisitor::visitPre(DocAutoListItem *) DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocAutoListItem)}\n"); if (!m_lastIsPara) m_t << "\\par\n"; m_t << rtf_Style_Reset; - if (rtf_listItemInfo[m_indentLevel].isEnum) + int level = indentLevel(); + if (m_listItemInfo[level].isEnum) { m_t << getStyle("ListEnum") << "\n"; - m_t << rtf_listItemInfo[m_indentLevel].number << ".\\tab "; - rtf_listItemInfo[m_indentLevel].number++; + m_t << m_listItemInfo[level].number << ".\\tab "; + m_listItemInfo[level].number++; } else { @@ -827,7 +867,7 @@ void RTFDocVisitor::visitPre(DocSimpleList *) if (m_hide) return; DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocSimpleSect)}\n"); m_t << "{\n"; - rtf_listItemInfo[m_indentLevel].isEnum = FALSE; + m_listItemInfo[indentLevel()].isEnum = FALSE; m_lastIsPara=FALSE; } @@ -860,8 +900,8 @@ void RTFDocVisitor::visitPre(DocSection *s) if (m_hide) return; DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocSection)}\n"); if (!m_lastIsPara) m_t << "\\par\n"; - m_t << "{\\bkmkstart " << rtfFormatBmkStr(s->file()+"_"+s->anchor()) << "}\n"; - m_t << "{\\bkmkend " << rtfFormatBmkStr(s->file()+"_"+s->anchor()) << "}\n"; + m_t << "{\\bkmkstart " << rtfFormatBmkStr(stripPath(s->file())+"_"+s->anchor()) << "}\n"; + m_t << "{\\bkmkend " << rtfFormatBmkStr(stripPath(s->file())+"_"+s->anchor()) << "}\n"; m_t << "{{" // start section << rtf_Style_Reset; QCString heading; @@ -891,20 +931,21 @@ void RTFDocVisitor::visitPre(DocHtmlList *l) if (m_hide) return; DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlList)}\n"); m_t << "{\n"; - rtf_listItemInfo[m_indentLevel].isEnum = l->type()==DocHtmlList::Ordered; - rtf_listItemInfo[m_indentLevel].number = 1; - rtf_listItemInfo[m_indentLevel].type = '1'; + int level = indentLevel(); + m_listItemInfo[level].isEnum = l->type()==DocHtmlList::Ordered; + m_listItemInfo[level].number = 1; + m_listItemInfo[level].type = '1'; for (const auto &opt : l->attribs()) { if (opt.name=="type") { - rtf_listItemInfo[m_indentLevel].type = opt.value[0]; + m_listItemInfo[level].type = opt.value[0]; } if (opt.name=="start") { bool ok; int val = opt.value.toInt(&ok); - if (ok) rtf_listItemInfo[m_indentLevel].number = val; + if (ok) m_listItemInfo[level].number = val; } } m_lastIsPara=FALSE; @@ -918,38 +959,48 @@ void RTFDocVisitor::visitPost(DocHtmlList *) m_lastIsPara=TRUE; } -void RTFDocVisitor::visitPre(DocHtmlListItem *) +void RTFDocVisitor::visitPre(DocHtmlListItem *l) { if (m_hide) return; DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlListItem)}\n"); m_t << "\\par\n"; m_t << rtf_Style_Reset; - if (rtf_listItemInfo[m_indentLevel].isEnum) + int level = indentLevel(); + if (m_listItemInfo[level].isEnum) { + for (const auto &opt : l->attribs()) + { + if (opt.name=="value") + { + bool ok; + int val = opt.value.toInt(&ok); + if (ok) m_listItemInfo[level].number = val; + } + } m_t << getStyle("ListEnum") << "\n"; - switch (rtf_listItemInfo[m_indentLevel].type) + switch (m_listItemInfo[level].type) { case '1': - m_t << rtf_listItemInfo[m_indentLevel].number; + m_t << m_listItemInfo[level].number; break; case 'a': - m_t << integerToAlpha(rtf_listItemInfo[m_indentLevel].number,false); + m_t << integerToAlpha(m_listItemInfo[level].number,false); break; case 'A': - m_t << integerToAlpha(rtf_listItemInfo[m_indentLevel].number); + m_t << integerToAlpha(m_listItemInfo[level].number); break; case 'i': - m_t << integerToRoman(rtf_listItemInfo[m_indentLevel].number,false); + m_t << integerToRoman(m_listItemInfo[level].number,false); break; case 'I': - m_t << integerToRoman(rtf_listItemInfo[m_indentLevel].number); + m_t << integerToRoman(m_listItemInfo[level].number); break; default: - m_t << rtf_listItemInfo[m_indentLevel].number; + m_t << m_listItemInfo[level].number; break; } m_t << ".\\tab "; - rtf_listItemInfo[m_indentLevel].number++; + m_listItemInfo[level].number++; } else { @@ -1020,12 +1071,23 @@ void RTFDocVisitor::visitPost(DocHtmlDescData *) m_lastIsPara=TRUE; } -void RTFDocVisitor::visitPre(DocHtmlTable *) +void RTFDocVisitor::visitPre(DocHtmlTable *t) { if (m_hide) return; DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlTable)}\n"); if (!m_lastIsPara) m_t << "\\par\n"; m_lastIsPara=TRUE; + if (t->hasCaption()) + { + DocHtmlCaption *c = t->caption(); + m_t << "\\pard \\qc \\b"; + if (!c->file().isEmpty()) + { + m_t << "{\\bkmkstart " << rtfFormatBmkStr(stripPath(c->file())+"_"+c->anchor()) << "}\n"; + m_t << "{\\bkmkend " << rtfFormatBmkStr(stripPath(c->file())+"_"+c->anchor()) << "}\n"; + } + m_t << "{Table \\field\\flddirty{\\*\\fldinst { SEQ Table \\\\*Arabic }}{\\fldrslt {\\noproof 1}} "; + } } void RTFDocVisitor::visitPost(DocHtmlTable *) @@ -1040,8 +1102,7 @@ void RTFDocVisitor::visitPost(DocHtmlTable *) void RTFDocVisitor::visitPre(DocHtmlCaption *) { DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlCaption)}\n"); - m_t << "\\pard \\qc \\b"; - m_t << "{Table \\field\\flddirty{\\*\\fldinst { SEQ Table \\\\*Arabic }}{\\fldrslt {\\noproof 1}} "; + // start of caption is handled in the RTFDocVisitor::visitPre(DocHtmlTable *t) } void RTFDocVisitor::visitPost(DocHtmlCaption *) @@ -1288,6 +1349,7 @@ void RTFDocVisitor::includePicturePostRTF(bool isTypeRTF, bool hasCaption, bool void RTFDocVisitor::visitPre(DocDotFile *df) { DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocDotFile)}\n"); + if (!Config_getBool(DOT_CLEANUP)) copyFile(df->file(),Config_getString(RTF_OUTPUT)+"/"+stripPath(df->file())); writeDotFile(df); } @@ -1299,6 +1361,7 @@ void RTFDocVisitor::visitPost(DocDotFile *df) void RTFDocVisitor::visitPre(DocMscFile *df) { DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocMscFile)}\n"); + if (!Config_getBool(DOT_CLEANUP)) copyFile(df->file(),Config_getString(RTF_OUTPUT)+"/"+stripPath(df->file())); writeMscFile(df); } @@ -1311,6 +1374,7 @@ void RTFDocVisitor::visitPost(DocMscFile *df) void RTFDocVisitor::visitPre(DocDiaFile *df) { DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocDiaFile)}\n"); + if (!Config_getBool(DOT_CLEANUP)) copyFile(df->file(),Config_getString(RTF_OUTPUT)+"/"+stripPath(df->file())); writeDiaFile(df); } @@ -1624,7 +1688,7 @@ void RTFDocVisitor::visitPre(DocXRefItem *x) QCString refName; if (!x->file().isEmpty()) { - refName+=x->file(); + refName+=stripPath(x->file()); } if (!x->file().isEmpty() && !x->anchor().isEmpty()) { @@ -1798,7 +1862,7 @@ void RTFDocVisitor::startLink(const QCString &ref,const QCString &file,const QCS QCString refName; if (!file.isEmpty()) { - refName+=file; + refName+=stripPath(file); } if (!file.isEmpty() && !anchor.isEmpty()) { diff --git a/src/rtfdocvisitor.h b/src/rtfdocvisitor.h index f7cc2b5..9d8a3af 100644 --- a/src/rtfdocvisitor.h +++ b/src/rtfdocvisitor.h @@ -147,6 +147,8 @@ class RTFDocVisitor : public DocVisitor const QCString &anchor); void endLink(const QCString &ref); QCString getStyle(const QCString &name); + + int indentLevel() const; void incIndentLevel(); void decIndentLevel(); @@ -165,11 +167,20 @@ class RTFDocVisitor : public DocVisitor TextStream &m_t; CodeOutputInterface &m_ci; - bool m_insidePre; - bool m_hide; - int m_indentLevel; - bool m_lastIsPara; + bool m_insidePre = false; + bool m_hide = false; + bool m_lastIsPara = false; QCString m_langExt; + + static const int maxIndentLevels = 13; + int m_indentLevel = 0; + struct RTFListItemInfo + { + bool isEnum = false; + int number = 1; + char type = '1'; + }; + RTFListItemInfo m_listItemInfo[maxIndentLevels]; }; #endif diff --git a/src/rtfgen.cpp b/src/rtfgen.cpp index f653245..e740d1f 100644 --- a/src/rtfgen.cpp +++ b/src/rtfgen.cpp @@ -279,23 +279,15 @@ void RTFGenerator::beginRTFDocument() m_t << "{\\widctlpar\\adjustright \\fs20\\cgrid \\snext0 Normal;}\n"; // set the paper dimensions according to PAPER_TYPE - QCString paperName = Config_getEnum(PAPER_TYPE); + static auto paperType = Config_getEnum(PAPER_TYPE); m_t << "{"; - if (paperName=="a4") + switch (paperType) { - m_t << "\\paperw11900\\paperh16840"; // width & height values are inches * 1440 - } - else if (paperName=="letter") - { - m_t << "\\paperw12240\\paperh15840"; - } - else if (paperName=="legal") - { - m_t << "\\paperw12240\\paperh20160"; - } - else if (paperName=="executive") - { - m_t << "\\paperw10440\\paperh15120"; + // width & height values are inches * 1440 + case PAPER_TYPE_t::a4: m_t << "\\paperw11900\\paperh16840"; break; + case PAPER_TYPE_t::letter: m_t << "\\paperw12240\\paperh15840"; break; + case PAPER_TYPE_t::legal: m_t << "\\paperw12240\\paperh20160"; break; + case PAPER_TYPE_t::executive: m_t << "\\paperw10440\\paperh15120"; break; } m_t << "\\margl1800\\margr1800\\margt1440\\margb1440\\gutter0\\ltrsect}\n"; @@ -413,7 +405,7 @@ void RTFGenerator::startIndexSection(IndexSections is) { //QCString paperName; - m_listLevel = 0; + //m_indentLevel = 0; switch (is) { @@ -1014,7 +1006,7 @@ void RTFGenerator::startIndexList() DBG_RTF(m_t << "{\\comment (startIndexList)}\n") m_t << "{\n"; m_t << "\\par\n"; - incrementIndentLevel(); + incIndentLevel(); m_t << rtf_Style_Reset << rtf_LCList_DepthStyle() << "\n"; m_omitParagraph = TRUE; } @@ -1028,26 +1020,29 @@ void RTFGenerator::endIndexList() m_omitParagraph = TRUE; } m_t << "}"; - decrementIndentLevel(); + decIndentLevel(); } /*! start bullet list */ void RTFGenerator::startItemList() { newParagraph(); - DBG_RTF(m_t << "{\\comment (startItemList level=" << m_listLevel << ") }\n") + incIndentLevel(); + int level = indentLevel(); + DBG_RTF(m_t << "{\\comment (startItemList level=" << level << ") }\n") m_t << "{"; - incrementIndentLevel(); - rtf_listItemInfo[m_listLevel].isEnum = FALSE; + m_listItemInfo[level].number = 1; + m_listItemInfo[level].isEnum = false; + m_listItemInfo[level].type = '1'; } /*! end bullet list */ void RTFGenerator::endItemList() { newParagraph(); - DBG_RTF(m_t << "{\\comment (endItemList level=" << m_listLevel << ")}\n") + DBG_RTF(m_t << "{\\comment (endItemList level=" << indentLevel() << ")}\n") m_t << "}"; - decrementIndentLevel(); + decIndentLevel(); m_omitParagraph = TRUE; } @@ -1057,11 +1052,12 @@ void RTFGenerator::startItemListItem() DBG_RTF(m_t << "{\\comment (startItemListItem)}\n") newParagraph(); m_t << rtf_Style_Reset; - if (rtf_listItemInfo[m_listLevel].isEnum) + int level = indentLevel(); + if (m_listItemInfo[level].isEnum) { m_t << rtf_EList_DepthStyle() << "\n"; - m_t << rtf_listItemInfo[m_listLevel].number << ".\\tab "; - rtf_listItemInfo[m_listLevel].number++; + m_t << m_listItemInfo[level].number << ".\\tab "; + m_listItemInfo[level].number++; } else { @@ -1139,7 +1135,7 @@ void RTFGenerator::writeStartAnnoItem(const QCString &,const QCString &f, if (!f.isEmpty() && Config_getBool(RTF_HYPERLINKS)) { m_t << "{\\field {\\*\\fldinst { HYPERLINK \\\\l \""; - m_t << rtfFormatBmkStr(f); + m_t << rtfFormatBmkStr(stripPath(f)); m_t << "\" }{}"; m_t << "}{\\fldrslt {\\cs37\\ul\\cf2 "; @@ -1244,7 +1240,7 @@ void RTFGenerator::startTextLink(const QCString &f,const QCString &anchor) QCString ref; if (!f.isEmpty()) { - ref+=f; + ref+=stripPath(f); } if (!anchor.isEmpty()) { @@ -1275,7 +1271,7 @@ void RTFGenerator::writeObjectLink(const QCString &ref, const QCString &f, QCString refName; if (!f.isEmpty()) { - refName+=f; + refName+=stripPath(f); } if (!anchor.isEmpty()) { @@ -1333,7 +1329,7 @@ void RTFGenerator::writeCodeLink(CodeSymbolType, QCString refName; if (!f.isEmpty()) { - refName+=f; + refName+=stripPath(f); } if (!anchor.isEmpty()) { @@ -1466,7 +1462,7 @@ void RTFGenerator::endDoxyAnchor(const QCString &fName,const QCString &anchor) QCString ref; if (!fName.isEmpty()) { - ref+=fName; + ref+=stripPath(fName); } if (!anchor.isEmpty()) { @@ -1500,7 +1496,7 @@ void RTFGenerator::addIndexItem(const QCString &s1,const QCString &s2) void RTFGenerator::startIndent() { - incrementIndentLevel(); + incIndentLevel(); DBG_RTF(m_t << "{\\comment (startIndent) }\n") m_t << "{\n"; m_t << rtf_Style_Reset << rtf_CList_DepthStyle() << "\n"; @@ -1509,7 +1505,7 @@ void RTFGenerator::startIndent() void RTFGenerator::endIndent() { m_t << "}\n"; - decrementIndentLevel(); + decIndentLevel(); } @@ -1545,7 +1541,7 @@ void RTFGenerator::startMemberDescription(const QCString &,const QCString &,bool { DBG_RTF(m_t << "{\\comment (startMemberDescription)}\n") m_t << "{\n"; - incrementIndentLevel(); + incIndentLevel(); m_t << rtf_Style_Reset << rtf_CList_DepthStyle(); startEmphasis(); } @@ -1555,7 +1551,7 @@ void RTFGenerator::endMemberDescription() DBG_RTF(m_t << "{\\comment (endMemberDescription)}\n") endEmphasis(); //newParagraph(); - decrementIndentLevel(); + decIndentLevel(); m_t << "\\par"; m_t << "}\n"; m_omitParagraph = TRUE; @@ -1727,7 +1723,7 @@ void RTFGenerator::writeAnchor(const QCString &fileName,const QCString &name) QCString anchor; if (!fileName.isEmpty()) { - anchor+=fileName; + anchor+=stripPath(fileName); } if (!fileName.isEmpty() && !name.isEmpty()) { @@ -1747,7 +1743,7 @@ void RTFGenerator::writeAnchor(const QCString &fileName,const QCString &name) void RTFGenerator::writeRTFReference(const QCString &label) { m_t << "{\\field\\fldedit {\\*\\fldinst PAGEREF "; - m_t << rtfFormatBmkStr(label); + m_t << rtfFormatBmkStr(stripPath(label)); m_t << " \\\\*MERGEFORMAT}{\\fldrslt pagenum}}"; } @@ -1862,63 +1858,67 @@ void RTFGenerator::endDescTableData() // a style for list formatted as a "bulleted list" -void RTFGenerator::incrementIndentLevel() +int RTFGenerator::indentLevel() const +{ + return std::min(m_indentLevel,maxIndentLevels-1); +} + +void RTFGenerator::incIndentLevel() { - m_listLevel++; - if (m_listLevel>rtf_maxIndentLevels-1) + m_indentLevel++; + if (m_indentLevel>=maxIndentLevels) { - err("Maximum indent level (%d) exceeded while generating RTF output!\n",rtf_maxIndentLevels); - m_listLevel=rtf_maxIndentLevels-1; + err("Maximum indent level (%d) exceeded while generating RTF output!\n",maxIndentLevels); } } -void RTFGenerator::decrementIndentLevel() +void RTFGenerator::decIndentLevel() { - m_listLevel--; - if (m_listLevel<0) + m_indentLevel--; + if (m_indentLevel<0) { err("Negative indent level while generating RTF output!\n"); - m_listLevel=0; + m_indentLevel=0; } } // a style for list formatted with "list continue" style QCString RTFGenerator::rtf_CList_DepthStyle() { - QCString n=makeIndexName("ListContinue",m_listLevel); + QCString n=makeIndexName("ListContinue",indentLevel()); return rtf_Style[n.str()].reference(); } // a style for list formatted as a "latext style" table of contents QCString RTFGenerator::rtf_LCList_DepthStyle() { - QCString n=makeIndexName("LatexTOC",m_listLevel); + QCString n=makeIndexName("LatexTOC",indentLevel()); return rtf_Style[n.str()].reference(); } // a style for list formatted as a "bullet" style QCString RTFGenerator::rtf_BList_DepthStyle() { - QCString n=makeIndexName("ListBullet",m_listLevel); + QCString n=makeIndexName("ListBullet",indentLevel()); return rtf_Style[n.str()].reference(); } // a style for list formatted as a "enumeration" style QCString RTFGenerator::rtf_EList_DepthStyle() { - QCString n=makeIndexName("ListEnum",m_listLevel); + QCString n=makeIndexName("ListEnum",indentLevel()); return rtf_Style[n.str()].reference(); } QCString RTFGenerator::rtf_DList_DepthStyle() { - QCString n=makeIndexName("DescContinue",m_listLevel); + QCString n=makeIndexName("DescContinue",indentLevel()); return rtf_Style[n.str()].reference(); } QCString RTFGenerator::rtf_Code_DepthStyle() { - QCString n=makeIndexName("CodeExample",m_listLevel); + QCString n=makeIndexName("CodeExample",indentLevel()); return rtf_Style[n.str()].reference(); } @@ -2087,7 +2087,7 @@ static bool preProcessFile(Dir &d,const QCString &infName, TextStream &t, bool b std::ifstream f(infName.str(),std::ifstream::in); if (!f.is_open()) { - err("problems opening rtf file %s for reading\n",infName.data()); + err("problems opening rtf file '%s' for reading\n",infName.data()); return false; } @@ -2112,7 +2112,7 @@ static bool preProcessFile(Dir &d,const QCString &infName, TextStream &t, bool b { line+='\n'; size_t pos; - if ((pos=prevLine.find("INCLUDETEXT"))!=std::string::npos) + if ((pos=prevLine.find("INCLUDETEXT \""))!=std::string::npos) { size_t startNamePos = prevLine.find('"',pos)+1; size_t endNamePos = prevLine.find('"',startNamePos); @@ -2355,7 +2355,7 @@ void RTFGenerator::startMemberGroupHeader(bool hasHeader) { DBG_RTF(m_t << "{\\comment startMemberGroupHeader}\n") m_t << "{\n"; - if (hasHeader) incrementIndentLevel(); + if (hasHeader) incIndentLevel(); m_t << rtf_Style_Reset << rtf_Style["GroupHeader"].reference(); } @@ -2388,7 +2388,7 @@ void RTFGenerator::startMemberGroup() void RTFGenerator::endMemberGroup(bool hasHeader) { DBG_RTF(m_t << "{\\comment endMemberGroup}\n") - if (hasHeader) decrementIndentLevel(); + if (hasHeader) decIndentLevel(); m_t << "}"; } @@ -2403,7 +2403,7 @@ void RTFGenerator::startExamples() endBold(); m_t << "}"; newParagraph(); - incrementIndentLevel(); + incIndentLevel(); m_t << rtf_Style_Reset << rtf_DList_DepthStyle(); } @@ -2412,7 +2412,7 @@ void RTFGenerator::endExamples() DBG_RTF(m_t << "{\\comment (endExamples)}\n") m_omitParagraph = FALSE; newParagraph(); - decrementIndentLevel(); + decIndentLevel(); m_omitParagraph = TRUE; m_t << "}"; } @@ -2428,7 +2428,7 @@ void RTFGenerator::startParamList(ParamListTypes,const QCString &title) endBold(); m_t << "}"; newParagraph(); - incrementIndentLevel(); + incIndentLevel(); m_t << rtf_Style_Reset << rtf_DList_DepthStyle(); } @@ -2436,7 +2436,7 @@ void RTFGenerator::endParamList() { DBG_RTF(m_t << "{\\comment (endParamList)}\n") newParagraph(); - decrementIndentLevel(); + decIndentLevel(); m_omitParagraph = TRUE; m_t << "}"; } @@ -2513,7 +2513,7 @@ void RTFGenerator::startConstraintList(const QCString &header) endBold(); m_t << "}"; newParagraph(); - incrementIndentLevel(); + incIndentLevel(); m_t << rtf_Style_Reset << rtf_DList_DepthStyle(); } @@ -2558,7 +2558,7 @@ void RTFGenerator::endConstraintList() { DBG_RTF(m_t << "{\\comment (endConstraintList)}\n") newParagraph(); - decrementIndentLevel(); + decIndentLevel(); m_omitParagraph = TRUE; m_t << "}"; } @@ -2673,7 +2673,7 @@ void RTFGenerator::endInlineMemberDoc() m_t << "\\cell }{\\row }\n"; } -void RTFGenerator::writeLineNumber(const QCString &ref,const QCString &fileName,const QCString &anchor,int l) +void RTFGenerator::writeLineNumber(const QCString &ref,const QCString &fileName,const QCString &anchor,int l,bool writeLineAnchor) { bool rtfHyperlinks = Config_getBool(RTF_HYPERLINKS); @@ -2687,9 +2687,9 @@ void RTFGenerator::writeLineNumber(const QCString &ref,const QCString &fileName, if (!m_sourceFileName.isEmpty()) { lineAnchor.sprintf("_l%05d",l); - lineAnchor.prepend(stripExtensionGeneral(m_sourceFileName, ".rtf")); + lineAnchor.prepend(stripExtensionGeneral(stripPath(m_sourceFileName), ".rtf")); } - bool showTarget = rtfHyperlinks && !lineAnchor.isEmpty(); + bool showTarget = rtfHyperlinks && !lineAnchor.isEmpty() && writeLineAnchor; if (showTarget) { m_t << "{\\bkmkstart "; diff --git a/src/rtfgen.h b/src/rtfgen.h index c9bce4c..dae336b 100644 --- a/src/rtfgen.h +++ b/src/rtfgen.h @@ -127,7 +127,7 @@ class RTFGenerator : public OutputGenerator void writeAnchor(const QCString &fileName,const QCString &name); void startCodeFragment(const QCString &style); void endCodeFragment(const QCString &style); - void writeLineNumber(const QCString &,const QCString &,const QCString &,int l); + void writeLineNumber(const QCString &,const QCString &,const QCString &,int l, bool); void startCodeLine(bool); void endCodeLine(); void startEmphasis() { m_t << "{\\i "; } @@ -273,8 +273,6 @@ class RTFGenerator : public OutputGenerator QCString rtf_LCList_DepthStyle(); QCString rtf_DList_DepthStyle(); QCString rtf_Code_DepthStyle(); - void incrementIndentLevel(); - void decrementIndentLevel(); void beginRTFDocument(); void beginRTFChapter(); void beginRTFSection(); @@ -284,14 +282,28 @@ class RTFGenerator : public OutputGenerator void rtfwriteRuler_thin(); void writeRTFReference(const QCString &label); + int indentLevel() const; + void incIndentLevel(); + void decIndentLevel(); + QCString m_sourceFileName; int m_col = 0; bool m_bstartedBody = false; // has startbody been called yet? - int m_listLevel = 0; // // RTF does not really have a additive indent...manually set list level. bool m_omitParagraph = false; // should a the next paragraph command be ignored? int m_numCols = 0; // number of columns in a table QCString m_relPath; bool m_doxyCodeLineOpen = false; + + // RTF does not really have a additive indent...manually set list level. + static const int maxIndentLevels = 13; + int m_indentLevel = 0; + struct RTFListItemInfo + { + bool isEnum = false; + int number = 1; + char type = '1'; + }; + RTFListItemInfo m_listItemInfo[maxIndentLevels]; }; #endif diff --git a/src/rtfstyle.cpp b/src/rtfstyle.cpp index 07bc3dd..65f47b1 100644 --- a/src/rtfstyle.cpp +++ b/src/rtfstyle.cpp @@ -20,8 +20,6 @@ #include "message.h" #include "regex.h" -RTFListItemInfo rtf_listItemInfo[rtf_maxIndentLevels]; - QCString rtf_title; QCString rtf_subject; QCString rtf_comments; diff --git a/src/rtfstyle.h b/src/rtfstyle.h index a946b37..fbd6882 100644 --- a/src/rtfstyle.h +++ b/src/rtfstyle.h @@ -35,17 +35,6 @@ extern QCString rtf_documentType; extern QCString rtf_documentId; extern QCString rtf_keywords; -struct RTFListItemInfo -{ - bool isEnum; - int number; - char type; -}; - -const int rtf_maxIndentLevels = 13; - -extern RTFListItemInfo rtf_listItemInfo[rtf_maxIndentLevels]; - struct Rtf_Style_Default { const char *name; diff --git a/src/scanner.l b/src/scanner.l index a7ec675..d7f8b37 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -18,6 +18,10 @@ %option extra-type="struct scannerYY_state *" %top{ #include <stdint.h> +// forward declare yyscan_t to improve typesafety +#define YY_TYPEDEF_YY_SCANNER_T +struct yyguts_t; +typedef yyguts_t *yyscan_t; } %{ @@ -105,7 +109,7 @@ struct scannerYY_state int yyBegLineNr = 1 ; int yyColNr = 1 ; int yyBegColNr = 1 ; - QCString yyFileName; + QCString fileName; MethodTypes mtype = Method; bool stat = false; Specifier virt = Normal; @@ -134,6 +138,7 @@ struct scannerYY_state bool insideCppQuote = false; bool insideProtocolList = false; + bool doxygenComment = false; int argRoundCount = 0; int argSquareCount = 0; @@ -185,7 +190,7 @@ struct scannerYY_state bool odlProp = false; bool lexInit = false; - bool externC = false; + bool externLinkage = false; QCString delimiter; @@ -209,6 +214,7 @@ static inline int computeIndent(const char *s,int startIndent); static QCString stripQuotes(const char *s); static bool nameIsOperator(QCString &name); void fixArgumentListForJavaScript(ArgumentList &al); +static bool startOfRequiresExpression(const QCString &req); // forward declarations for statefull functions static void initParser(yyscan_t yyscanner); @@ -230,6 +236,10 @@ static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size); #undef YY_INPUT #define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); +// otherwise the filename would be the name of the converted file (*.cpp instead of *.l) +static inline const char *getLexerFILE() {return __FILE__;} +#include "doxygen_lex.h" + %} /* start command character */ @@ -266,8 +276,12 @@ CCS "/\*" CCE "*\/" // Cpp comment CPPC "/\/" + // doxygen C start comment +DCOMMC ("/\*!"|"/\**") + // doxygen Cpp start comment +DCOMMCPP ("/\/!"|"/\/\/") // doxygen start comment -DCOMM ("/\*!"|"/\**"|"/\/!"|"/\/\/") +DCOMM {DCOMMC}|{DCOMMCPP} // Optional any character ANYopt .* @@ -301,7 +315,6 @@ NONLopt [^\n]* %x FindMembersPHP %x FindMemberName %x FindFields -%x FindFieldArg %x Function %x FuncRound %x ExcpRound @@ -326,7 +339,6 @@ NONLopt [^\n]* %x SkipC11Inits %x SkipC11Attribute %x SkipCPP -%x SkipCPPBlock %x SkipComment %x SkipCxxComment %x SkipCurlyBlock @@ -334,7 +346,6 @@ NONLopt [^\n]* %x Sharp %x SkipRound %x SkipSquare -%x SkipRemainder %x StaticAssert %x DeclType %x TypedefName @@ -360,7 +371,6 @@ NONLopt [^\n]* %x ObjCPropAttr %x ObjCSkipStatement %x QtPropType -%x QtPropName %x QtPropAttr %x QtPropRead %x QtPropWrite @@ -395,7 +405,6 @@ NONLopt [^\n]* %x Specialization %x SpecializationSingleQuote %x SpecializationDoubleQuote -%x FuncPtrInit %x FuncFunc %x FuncFuncEnd %x FuncFuncType @@ -768,7 +777,7 @@ NONLopt [^\n]* else { lineCount(yyscanner); - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; @@ -910,7 +919,7 @@ NONLopt [^\n]* lineCount(yyscanner); yyextra->current->bodyLine = yyextra->yyLineNr; yyextra->current->bodyColumn = yyextra->yyColNr; - yyextra->current->fileName = yyextra->yyFileName ; + yyextra->current->fileName = yyextra->fileName ; yyextra->current->startLine = yyextra->yyLineNr ; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->args.resize(0); @@ -927,7 +936,7 @@ NONLopt [^\n]* lineCount(yyscanner); yyextra->current->bodyLine = yyextra->yyLineNr; yyextra->current->bodyColumn = yyextra->yyColNr; - yyextra->current->fileName = yyextra->yyFileName ; + yyextra->current->fileName = yyextra->fileName ; yyextra->current->startLine = yyextra->yyLineNr ; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->args.resize(0); @@ -1001,6 +1010,16 @@ NONLopt [^\n]* <ObjCPropAttr>")" { BEGIN(FindMembers); } +<FindMembers>"@"{ID}("."{ID})+ { + if (yyextra->insideJava) // Java annotation + { + // skip annotation + } + else + { + REJECT; + } + } <FindMembers>"@"{ID} { if (yyextra->insideJava) // Java annotation { @@ -1036,7 +1055,7 @@ NONLopt [^\n]* yyextra->current->name = substitute(yyextra->current->name,"\\","::"); yyextra->current->section = Entry::NAMESPACE_SEC; yyextra->current->type = "namespace" ; - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; @@ -1054,7 +1073,7 @@ NONLopt [^\n]* yyextra->curlyCount=0; BEGIN( ReadNSBody ); } -<FindMembers>{B}*"initonly"{BN}+ { +<FindMembers>{B}*"initonly"{BN}+ { if (yyextra->insideJava) REJECT; yyextra->current->type += " initonly "; if (yyextra->insideCli) yyextra->current->spec |= Entry::Initonly; lineCount(yyscanner); @@ -1063,7 +1082,7 @@ NONLopt [^\n]* yyextra->current->stat = TRUE; lineCount(yyscanner); } -<FindMembers>{B}*"extern"{BN}+ { +<FindMembers>{B}*"extern"{BN}+ { if (yyextra->insideJava) REJECT; yyextra->current->stat = FALSE; yyextra->current->explicitExternal = TRUE; lineCount(yyscanner); @@ -1079,21 +1098,17 @@ NONLopt [^\n]* REJECT; } } -<FindMembers>{B}*"virtual"{BN}+ { yyextra->current->type += " virtual "; +<FindMembers>{B}*"virtual"{BN}+ { if (yyextra->insideJava) REJECT; + yyextra->current->type += " virtual "; yyextra->current->virt = Virtual; lineCount(yyscanner); } <FindMembers>{B}*"constexpr"{BN}+ { if (yyextra->insideCpp) { - yyextra->current->type += " constexpr "; yyextra->current->spec |= Entry::ConstExpr; - lineCount(yyscanner); - } - else - { - REJECT; } + REJECT; } <FindMembers>{B}*"published"{BN}+ { // UNO IDL published keyword if (yyextra->insideIDL) @@ -1125,16 +1140,20 @@ NONLopt [^\n]* } lineCount(yyscanner); } -<FindMembers>{B}*"inline"{BN}+ { yyextra->current->spec|=Entry::Inline; +<FindMembers>{B}*"inline"{BN}+ { if (yyextra->insideJava) REJECT; + yyextra->current->spec|=Entry::Inline; lineCount(yyscanner); } -<FindMembers>{B}*"mutable"{BN}+ { yyextra->current->spec|=Entry::Mutable; +<FindMembers>{B}*"mutable"{BN}+ { if (yyextra->insideJava) REJECT; + yyextra->current->spec|=Entry::Mutable; lineCount(yyscanner); } -<FindMembers>{B}*"explicit"{BN}+ { yyextra->current->spec|=Entry::Explicit; +<FindMembers>{B}*"explicit"{BN}+ { if (yyextra->insideJava) REJECT; + yyextra->current->spec|=Entry::Explicit; lineCount(yyscanner); } -<FindMembers>{B}*"local"{BN}+ { yyextra->current->spec|=Entry::Local; +<FindMembers>{B}*"local"{BN}+ { if (yyextra->insideJava) REJECT; + yyextra->current->spec|=Entry::Local; lineCount(yyscanner); } <FindMembers>{B}*"@required"{BN}+ { // Objective C 2.0 protocol required section @@ -1151,11 +1170,11 @@ NONLopt [^\n]* } */ <FindMembers>{B}*"typename"{BN}+ { lineCount(yyscanner); } -<FindMembers>{B}*"namespace"{BNopt}/[^a-z_A-Z0-9] { +<FindMembers>{B}*"namespace"{BNopt}/[^a-z_A-Z0-9] { if (yyextra->insideJava) REJECT; yyextra->isTypedef=FALSE; yyextra->current->section = Entry::NAMESPACE_SEC; yyextra->current->type = "namespace" ; - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; @@ -1177,7 +1196,7 @@ NONLopt [^\n]* yyextra->isTypedef=FALSE; yyextra->current->section = Entry::NAMESPACE_SEC; yyextra->current->type = "module" ; - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; @@ -1202,7 +1221,7 @@ NONLopt [^\n]* yyextra->isTypedef=FALSE; yyextra->current->section = Entry::NAMESPACE_SEC; yyextra->current->type = "library" ; - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; @@ -1222,7 +1241,7 @@ NONLopt [^\n]* yyextra->isTypedef=FALSE; yyextra->current->section = Entry::NAMESPACE_SEC; yyextra->current->type = "constants"; - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; @@ -1246,7 +1265,7 @@ NONLopt [^\n]* (yyextra->current->spec & (Entry::Optional|Entry::Published)); addType(yyscanner); yyextra->current->type += " service " ; - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->bodyLine = yyextra->yyLineNr; yyextra->current->bodyColumn = yyextra->yyColNr; @@ -1268,7 +1287,7 @@ NONLopt [^\n]* (yyextra->current->spec & Entry::Published); // preserve addType(yyscanner); yyextra->current->type += " singleton " ; - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->bodyLine = yyextra->yyLineNr; yyextra->current->bodyColumn = yyextra->yyColNr; @@ -1291,7 +1310,7 @@ NONLopt [^\n]* (yyextra->current->spec & (Entry::Optional|Entry::Published|Entry::Local)); addType(yyscanner); yyextra->current->type += " interface" ; - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; @@ -1313,7 +1332,7 @@ NONLopt [^\n]* yyextra->current->protection = yyextra->protection = Public ; addType(yyscanner); yyextra->current->type += " implementation" ; - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->bodyLine = yyextra->yyLineNr; yyextra->current->bodyColumn = yyextra->yyColNr; @@ -1332,7 +1351,7 @@ NONLopt [^\n]* yyextra->current->protection = yyextra->protection = Public ; addType(yyscanner); yyextra->current->type += " interface" ; - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; @@ -1349,7 +1368,7 @@ NONLopt [^\n]* yyextra->current->protection = yyextra->protection = Public ; addType(yyscanner); yyextra->current->type += " protocol" ; - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; @@ -1357,6 +1376,7 @@ NONLopt [^\n]* BEGIN( CompoundName ); } <FindMembers>{B}*"exception"{BN}+ { // Corba IDL/Slice exception + if (yyextra->insideJava) REJECT; yyextra->isTypedef=FALSE; yyextra->current->section = Entry::CLASS_SEC; // preserve UNO IDL, Slice local @@ -1365,7 +1385,7 @@ NONLopt [^\n]* (yyextra->current->spec & Entry::Local); addType(yyscanner); yyextra->current->type += " exception" ; - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; @@ -1401,7 +1421,7 @@ NONLopt [^\n]* yyextra->current->type += " volatile"; } yyextra->current->type += " class" ; - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; @@ -1422,7 +1442,7 @@ NONLopt [^\n]* yyextra->current->spec = Entry::Value; addType(yyscanner); yyextra->current->type += " value class" ; - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; @@ -1438,7 +1458,7 @@ NONLopt [^\n]* yyextra->current->spec = Entry::Ref; addType(yyscanner); yyextra->current->type += " ref class" ; - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; @@ -1454,7 +1474,7 @@ NONLopt [^\n]* yyextra->current->spec = Entry::Interface; addType(yyscanner); yyextra->current->type += " interface class" ; - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; @@ -1470,7 +1490,7 @@ NONLopt [^\n]* yyextra->current->section = Entry::CLASS_SEC; addType(yyscanner); yyextra->current->type += " coclass" ; - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; @@ -1488,6 +1508,7 @@ NONLopt [^\n]* } <FindMembers>{B}*{TYPEDEFPREFIX}"struct{" | <FindMembers>{B}*{TYPEDEFPREFIX}"struct"/{BN}+ { + if (yyextra->insideJava) REJECT; QCString decl = yytext; yyextra->isTypedef=decl.find("typedef")!=-1; bool isConst=decl.find("const")!=-1; @@ -1510,7 +1531,7 @@ NONLopt [^\n]* yyextra->current->type += " volatile"; } yyextra->current->type += " struct" ; - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; @@ -1526,7 +1547,7 @@ NONLopt [^\n]* yyextra->current->spec = Entry::Struct | Entry::Value; addType(yyscanner); yyextra->current->type += " value struct" ; - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; @@ -1542,7 +1563,7 @@ NONLopt [^\n]* yyextra->current->spec = Entry::Struct | Entry::Ref; addType(yyscanner); yyextra->current->type += " ref struct" ; - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; @@ -1558,7 +1579,7 @@ NONLopt [^\n]* yyextra->current->spec = Entry::Struct | Entry::Interface; addType(yyscanner); yyextra->current->type += " interface struct"; - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; @@ -1569,6 +1590,7 @@ NONLopt [^\n]* } <FindMembers>{B}*{TYPEDEFPREFIX}"union{" | <FindMembers>{B}*{TYPEDEFPREFIX}"union"{BN}+ { + if (yyextra->insideJava) REJECT; QCString decl=yytext; yyextra->isTypedef=decl.find("typedef")!=-1; bool isConst=decl.find("const")!=-1; @@ -1587,7 +1609,7 @@ NONLopt [^\n]* yyextra->current->type += " volatile"; } yyextra->current->type += " union" ; - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; @@ -1622,7 +1644,7 @@ NONLopt [^\n]* yyextra->current->spec |= Entry::Strong; yyextra->current->spec |= Entry::EnumStruct; } - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; @@ -1632,11 +1654,12 @@ NONLopt [^\n]* BEGIN( CompoundName ) ; } <FindMembers>{B}*"concept"{BN}+ { // C++20 concept + if (yyextra->insideJava) REJECT; yyextra->isTypedef=FALSE; yyextra->current->section = Entry::CONCEPT_SEC; addType(yyscanner); yyextra->current->type += " concept"; - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->bodyLine = yyextra->yyLineNr; @@ -1682,6 +1705,7 @@ NONLopt [^\n]* BEGIN( ReadTempArgs ); } <FindMembers>"namespace"{BN}+/{ID}{BN}*"=" { // namespace alias + if (yyextra->insideJava) REJECT; lineCount(yyscanner); BEGIN( NSAliasName ); } @@ -1707,7 +1731,7 @@ NONLopt [^\n]* lineCount(yyscanner); yyextra->current->name=removeRedundantWhiteSpace(substitute(yytext,"\\","::")); //printf("PHP: adding use relation: %s\n",qPrint(yyextra->current->name)); - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; // add a using declaration yyextra->current->section=Entry::USINGDECL_SEC; yyextra->current_root->copyToSubEntry(yyextra->current); @@ -1746,7 +1770,7 @@ NONLopt [^\n]* lineCount(yyscanner); QCString scope=yytext; yyextra->current->name=removeRedundantWhiteSpace(substitute(scope.left(scope.length()-1),".","::")); - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->section=Entry::USINGDIR_SEC; yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); initEntry(yyscanner); @@ -1756,7 +1780,7 @@ NONLopt [^\n]* lineCount(yyscanner); QCString scope=yytext; yyextra->current->name=removeRedundantWhiteSpace(substitute(scope,".","::")); - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; if (yyextra->insideD) { yyextra->current->section=Entry::USINGDIR_SEC; @@ -1772,6 +1796,7 @@ NONLopt [^\n]* BEGIN(Using); } <FindMembers>"using"{BN}+ { + if (yyextra->insideJava) REJECT; yyextra->current->startLine=yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; lineCount(yyscanner); @@ -1781,7 +1806,7 @@ NONLopt [^\n]* <Using>({ID}{BN}*("::"|"."){BN}*)*({ID}|{OPERATOR}) { lineCount(yyscanner); yyextra->current->name=yytext; - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->section=Entry::USINGDECL_SEC; yyextra->current->startLine = yyextra->yyLineNr; yyextra->previous = yyextra->current; @@ -1793,7 +1818,7 @@ NONLopt [^\n]* */ { yyextra->current->name=yytext; - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->section=Entry::USINGDIR_SEC; @@ -1860,7 +1885,7 @@ NONLopt [^\n]* BEGIN(UsingAlias); } <UsingDirective>{SCOPENAME} { yyextra->current->name=removeRedundantWhiteSpace(yytext); - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->section=Entry::USINGDIR_SEC; yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); initEntry(yyscanner); @@ -2104,11 +2129,19 @@ NONLopt [^\n]* BEGIN(FindMembers); } <FindMembers>"requires" { // C++20 requires clause + if (yyextra->insideJava) REJECT; yyextra->current->req.resize(0); yyextra->requiresContext = YY_START; BEGIN(RequiresClause); } +<RequiresClause>"requires"{BN}*/"{" { // requires requires { ... } + if (yyextra->insideJava) REJECT; + lineCount(yyscanner) ; + yyextra->current->req+=yytext; + BEGIN( RequiresExpression ) ; + } <RequiresClause>"requires"{BN}*"(" { // requires requires(T x) { ... } + if (yyextra->insideJava) REJECT; lineCount(yyscanner) ; yyextra->current->req+=yytext; yyextra->lastRoundContext=RequiresExpression; @@ -2125,7 +2158,7 @@ NONLopt [^\n]* } <RequiresExpression>\n { yyextra->current->req+=' '; - lineCount(yyextra); + lineCount(yyscanner); } <RequiresExpression>. { yyextra->current->req+=yytext; @@ -2138,7 +2171,7 @@ NONLopt [^\n]* BEGIN( CopyRound ) ; } <RequiresClause>{ID} { // something like "requires true" - if (yyextra->current->req.stripWhiteSpace().isEmpty()) + if (startOfRequiresExpression(yyextra->current->req)) { yyextra->current->req=yytext; BEGIN(yyextra->requiresContext); @@ -2149,18 +2182,32 @@ NONLopt [^\n]* } } <RequiresClause>{SCOPENAME}{BNopt}"(" { // "requires func(x)" - yyextra->current->req+=yytext; - yyextra->lastRoundContext=RequiresClause; - yyextra->pCopyRoundString=&yyextra->current->req; - yyextra->roundCount=0; - BEGIN( CopyRound ); + if (startOfRequiresExpression(yyextra->current->req)) + { + yyextra->current->req+=yytext; + yyextra->lastRoundContext=RequiresClause; + yyextra->pCopyRoundString=&yyextra->current->req; + yyextra->roundCount=0; + BEGIN( CopyRound ); + } + else + { + REJECT; + } } <RequiresClause>{SCOPENAME}{BNopt}"<" { // "requires C<S,T>" - yyextra->current->req+=yytext; - yyextra->lastSharpContext=RequiresClause; - yyextra->pCopySharpString=&yyextra->current->req; - yyextra->sharpCount=0; - BEGIN( CopySharp ); + if (startOfRequiresExpression(yyextra->current->req)) + { + yyextra->current->req+=yytext; + yyextra->lastSharpContext=RequiresClause; + yyextra->pCopySharpString=&yyextra->current->req; + yyextra->sharpCount=0; + BEGIN( CopySharp ); + } + else + { + REJECT + } } <RequiresClause>"||"|"&&" { // "requires A || B" or "requires A && B" yyextra->current->req+=yytext; @@ -2311,6 +2358,18 @@ NONLopt [^\n]* } yyextra->current->name= yyextra->current->name.mid(7); } + else if (yyextra->current->name.left(10)=="constexpr ") + { + if (yyextra->current->type.isEmpty()) + { + yyextra->current->type="constexpr"; + } + else + { + yyextra->current->type+="constexpr "; + } + yyextra->current->name=yyextra->current->name.mid(10); + } else if (yyextra->current->name.left(6)=="const ") { if (yyextra->current->type.isEmpty()) @@ -2335,6 +2394,18 @@ NONLopt [^\n]* } yyextra->current->name=yyextra->current->name.mid(9); } + else if (yyextra->current->name.left(8)=="typedef ") + { + if (yyextra->current->type.isEmpty()) + { + yyextra->current->type="typedef"; + } + else + { + yyextra->current->type+="typedef "; + } + yyextra->current->name=yyextra->current->name.mid(8); + } } QCString tmp=yytext; if (nameIsOperator(tmp)) @@ -2343,7 +2414,7 @@ NONLopt [^\n]* } else { - yyextra->externC=FALSE; // see bug759247 + yyextra->externLinkage=FALSE; // see bug759247 BEGIN(FindMembers); } } @@ -2439,7 +2510,7 @@ NONLopt [^\n]* BEGIN( PreLineCtrl ); } <PreLineCtrl>"\""[^\n\"]*"\"" { - yyextra->yyFileName = stripQuotes(yytext); + yyextra->fileName = stripQuotes(yytext); if (yyextra->lastPreLineCtrlContext==ReadBody || yyextra->lastPreLineCtrlContext==ReadNSBody || yyextra->lastPreLineCtrlContext==ReadBodyIntf) @@ -2504,7 +2575,7 @@ NONLopt [^\n]* } <DefineEnd>\n { //printf("End define: doc=%s docFile=%s docLine=%d\n",qPrint(yyextra->current->doc),qPrint(yyextra->current->docFile),yyextra->current->docLine); - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->type.resize(0); @@ -2518,7 +2589,7 @@ NONLopt [^\n]* } <DefinePHPEnd>";" { //printf("End define\n"); - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->type.resize(0); @@ -2641,7 +2712,7 @@ NONLopt [^\n]* BEGIN( DocBlock ); } } -<DefineEnd,FindFields,FindFieldArg,ReadInitializer,ReadInitializerPtr,OldStyleArgs>{BN}*{DCOMM}"<" { +<DefineEnd,FindFields,ReadInitializer,ReadInitializerPtr,OldStyleArgs>{BN}*{DCOMM}"<" { if (yyextra->current->bodyLine==-1) { yyextra->current->bodyLine=yyextra->yyLineNr; @@ -2674,12 +2745,12 @@ NONLopt [^\n]* if (yyextra->previous && yyextra->previous->section==Entry::GROUPDOC_SEC) { // link open command to the group defined in the yyextra->previous entry - yyextra->commentScanner.open(yyextra->previous.get(),yyextra->yyFileName,yyextra->yyLineNr); + yyextra->commentScanner.open(yyextra->previous.get(),yyextra->fileName,yyextra->yyLineNr); } else { // link open command to the yyextra->current entry - yyextra->commentScanner.open(yyextra->current.get(),yyextra->yyFileName,yyextra->yyLineNr); + yyextra->commentScanner.open(yyextra->current.get(),yyextra->fileName,yyextra->yyLineNr); } //yyextra->current = tmp; initEntry(yyscanner); @@ -2723,7 +2794,7 @@ NONLopt [^\n]* } <FindMembers,FindFields,ReadInitializer,ReadInitializerPtr>{CPPC}([!/]){B}*{CMD}"}".*|{CCS}([!*]){B}*{CMD}"}"[^*]*{CCE} { bool insideEnum = YY_START==FindFields || ((YY_START==ReadInitializer || YY_START==ReadInitializerPtr) && yyextra->lastInitializerContext==FindFields); // see bug746226 - yyextra->commentScanner.close(yyextra->current.get(),yyextra->yyFileName,yyextra->yyLineNr,insideEnum); + yyextra->commentScanner.close(yyextra->current.get(),yyextra->fileName,yyextra->yyLineNr,insideEnum); lineCount(yyscanner); } <FindMembers>"=>" { @@ -2781,7 +2852,7 @@ NONLopt [^\n]* //printf(">> initializer '%s' <<\n",qPrint(yyextra->current->initializer)); if (*yytext==';' && (yyextra->current_root->spec&Entry::Enum)) { - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->args = yyextra->current->args.simplifyWhiteSpace(); @@ -3378,7 +3449,8 @@ NONLopt [^\n]* } bool stat = yyextra->current->stat; Protection prot = yyextra->current->protection; - if (yyextra->current->section==Entry::CONCEPT_SEC) // C++20 concept + bool isConcept = yyextra->current->section==Entry::CONCEPT_SEC; + if (isConcept) // C++20 concept { yyextra->current_root->moveToSubEntryAndRefresh( yyextra->current ) ; initEntry(yyscanner); @@ -3393,7 +3465,7 @@ NONLopt [^\n]* yyextra->current->spec = 0; } yyextra->current->section = Entry::VARIABLE_SEC ; - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->startLine = yyextra->yyBegLineNr; yyextra->current->startColumn = yyextra->yyBegColNr; yyextra->current_root->moveToSubEntryAndRefresh( yyextra->current ) ; @@ -3466,7 +3538,7 @@ NONLopt [^\n]* { yyextra->current->args += yytext ; yyextra->squareCount=1; - yyextra->externC=FALSE; // see bug759247 + yyextra->externLinkage=FALSE; // see bug759247 BEGIN( Array ) ; } } @@ -3628,7 +3700,7 @@ NONLopt [^\n]* // the parameter name for the property - just skip. } <IDLProp>";" { - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->type = yyextra->idlProp; yyextra->current->args = yyextra->current->args.simplifyWhiteSpace(); if (!yyextra->current->args.isEmpty()) @@ -3689,9 +3761,9 @@ NONLopt [^\n]* yyextra->current->bodyColumn = yyextra->yyColNr; yyextra->current->name = yytext; } -<FindFields>"(" { +<FindFields>[({] { // Java enum initializer - unput('('); + unput(*yytext); yyextra->lastInitializerContext = YY_START; yyextra->initBracketCount=0; yyextra->current->initializer.str("="); @@ -3708,7 +3780,7 @@ NONLopt [^\n]* { if (!yyextra->current->name.isEmpty()) { - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; if (!(yyextra->current_root->spec&Entry::Enum)) @@ -3729,17 +3801,13 @@ NONLopt [^\n]* REJECT; } } -<SkipRemainder>\n { - lineCount(yyscanner); - } -<SkipRemainder>[^\n]* <FindFields>"," { //printf("adding '%s' '%s' '%s' to enum '%s' (mGrpId=%d)\n", // qPrint(yyextra->current->type), qPrint(yyextra->current->name), // qPrint(yyextra->current->args), qPrint(yyextra->current_root->name),yyextra->current->mGrpId); if (!yyextra->current->name.isEmpty()) { - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->startLine = yyextra->yyLineNr; yyextra->current->startColumn = yyextra->yyColNr; if (!(yyextra->current_root->spec&Entry::Enum)) @@ -3774,9 +3842,6 @@ NONLopt [^\n]* yyextra->lastSquareContext = YY_START; BEGIN(SkipSquare); } - /* -<FindFieldArg>"," { unput(*yytext); BEGIN(FindFields); } - */ <ReadBody,ReadNSBody,ReadBodyIntf>[^\r\n\#{}"@'/<]* { yyextra->current->program << yytext ; } <ReadBody,ReadNSBody,ReadBodyIntf>{CPPC}.* { yyextra->current->program << yytext ; } <ReadBody,ReadNSBody,ReadBodyIntf>"#".* { if (!yyextra->insidePHP) @@ -3806,11 +3871,12 @@ NONLopt [^\n]* yyextra->lastStringContext=YY_START; BEGIN( CopyGString ); } -<ReadBody,ReadNSBody,ReadBodyIntf>{CCS}{B}* { yyextra->current->program << yytext ; +<ReadBody,ReadNSBody,ReadBodyIntf>{DCOMMC} { yyextra->doxygenComment=true; REJECT;} +<ReadBody,ReadNSBody,ReadBodyIntf>{CCS}{B}* { yyextra->current->program << yytext ; yyextra->lastContext = YY_START ; BEGIN( Comment ) ; } -<ReadBody,ReadNSBody,ReadBodyIntf>{CCS}{BL} { yyextra->current->program << yytext ; +<ReadBody,ReadNSBody,ReadBodyIntf>{CCS}{BL} { yyextra->current->program << yytext ; ++yyextra->yyLineNr ; yyextra->lastContext = YY_START ; BEGIN( Comment ) ; @@ -4128,7 +4194,7 @@ NONLopt [^\n]* { varEntry->type+=yyextra->current->name+yyextra->msType; } - varEntry->fileName = yyextra->yyFileName; + varEntry->fileName = yyextra->fileName; varEntry->startLine = yyextra->yyLineNr; varEntry->startColumn = yyextra->yyColNr; varEntry->doc = yyextra->current->doc; @@ -4240,7 +4306,7 @@ NONLopt [^\n]* } } <FuncPtr>. { - //printf("error: FuncPtr '%c' unexpected at line %d of %s\n",*yytext,yyextra->yyLineNr,yyextra->yyFileName); + //printf("error: FuncPtr '%c' unexpected at line %d of %s\n",*yytext,yyextra->yyLineNr,yyextra->fileName); } <FuncPtrOperator>"("{BN}*")"{BNopt}/"(" { yyextra->current->name += yytext; @@ -4560,7 +4626,7 @@ NONLopt [^\n]* yyextra->fullArgString+=yytext; BEGIN(CopyArgVerbatim); } -<CopyArgCommentLine>{CMD}("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"rtfonly"|"docbookonly"|"dot"|"msc"|"code")/[^a-z_A-Z0-9\-] { // verbatim command (which could contain nested comments!) +<CopyArgCommentLine>{CMD}("verbatim"|"iliteral"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"rtfonly"|"docbookonly"|"dot"|"msc"|"code")/[^a-z_A-Z0-9\-] { // verbatim command (which could contain nested comments!) yyextra->docBlockName=&yytext[1]; yyextra->fullArgString+=yytext; BEGIN(CopyArgVerbatim); @@ -4582,7 +4648,7 @@ NONLopt [^\n]* yyextra->fullArgString+=yytext; BEGIN(CopyArgVerbatim); } -<CopyArgVerbatim>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endmanonly"|"endrtfonly"|"enddot"|"ebdmsc"|"enduml"|"endcode"|"f$"|"f]"|"f}"|"f)")/[^a-z_A-Z0-9\-] { // end of verbatim block +<CopyArgVerbatim>[\\@]("endverbatim"|"endiliteral"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endmanonly"|"endrtfonly"|"enddot"|"endmsc"|"enduml"|"endcode"|"f$"|"f]"|"f}"|"f)")/[^a-z_A-Z0-9\-] { // end of verbatim block yyextra->fullArgString+=yytext; if (yytext[1]=='f' && yyextra->docBlockName==&yytext[1]) { @@ -4598,7 +4664,7 @@ NONLopt [^\n]* <CopyArgComment,CopyArgVerbatim>\n { yyextra->fullArgString+=*yytext; lineCount(yyscanner); } <CopyArgComment,CopyArgVerbatim>. { yyextra->fullArgString+=*yytext; } <CopyArgComment>{CMD}("brief"|"short"){B}+ { - warn(yyextra->yyFileName,yyextra->yyLineNr, + warn(yyextra->fileName,yyextra->yyLineNr, "Ignoring %cbrief command inside argument documentation",*yytext ); yyextra->fullArgString+=' '; @@ -4841,6 +4907,7 @@ NONLopt [^\n]* BEGIN(FuncQual); } <TrailingReturn>"requires"{BN}+ { + if (yyextra->insideJava) REJECT; yyextra->requiresContext = FuncQual; yyextra->current->req+=' '; BEGIN(RequiresClause); @@ -4857,7 +4924,7 @@ NONLopt [^\n]* } else { - warn(yyextra->yyFileName,yyextra->yyLineNr, + warn(yyextra->fileName,yyextra->yyLineNr, "Found ')' without opening '(' for trailing return type '%s)...'", qPrint(yyextra->current->argList.trailingReturnType())); } @@ -4913,45 +4980,6 @@ NONLopt [^\n]* } <CliOverride>. { } -<FuncPtrInit>[{;] { - unput(*yytext); - BEGIN(FuncQual); - } -<FuncPtrInit>\" { - yyextra->current->args += *yytext; - yyextra->pCopyQuotedString=&yyextra->current->args; - yyextra->lastStringContext=FuncPtrInit; - BEGIN(CopyString); - } -<FuncPtrInit>\' { - yyextra->current->args += *yytext; - if (yyextra->insidePHP) - { - yyextra->pCopyQuotedString=&yyextra->current->args; - yyextra->lastStringContext=FuncPtrInit; - BEGIN(CopyPHPString); - } - } -<FuncPtrInit>{CHARLIT} { - if (yyextra->insidePHP) - { - REJECT; - } - else - { - yyextra->current->args += yytext; - } - } -<FuncPtrInit>{ID} { - yyextra->current->args += yytext; - } -<FuncPtrInit>. { - yyextra->current->args += *yytext; - } -<FuncPtrInit>\n { - yyextra->current->args += *yytext; - lineCount(yyscanner); - } <FuncQual>{ID} { if (yyextra->insideCpp && qstrcmp(yytext,"requires")==0) { @@ -5076,7 +5104,7 @@ NONLopt [^\n]* yyextra->current->name=removeRedundantWhiteSpace(yyextra->current->name); yyextra->current->type=removeRedundantWhiteSpace(yyextra->current->type); yyextra->current->args=removeRedundantWhiteSpace(yyextra->current->args); - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->startLine = yyextra->yyBegLineNr; yyextra->current->startColumn = yyextra->yyBegColNr; static const reg::Ex re(R"(\([^)]*[*&][^)]*\))"); @@ -5382,7 +5410,7 @@ NONLopt [^\n]* BEGIN( SkipString ); } <SkipInits>; { - warn(yyextra->yyFileName,yyextra->yyLineNr, + warn(yyextra->fileName,yyextra->yyLineNr, "Found ';' while parsing initializer list! " "(doxygen could be confused by a macro call without semicolon)" ); @@ -5424,6 +5452,7 @@ NONLopt [^\n]* <SkipString,SkipPHPString>\n { lineCount(yyscanner); } +<SkipString>"[[" { } <SkipString,SkipPHPString>. { } <CompoundName>":" { // for "class : public base {} var;" construct, see bug 608359 unput(':'); @@ -5885,7 +5914,6 @@ NONLopt [^\n]* } } <ClassVar>[;=*&] { - unput(*yytext); if (yyextra->isTypedef) // typedef of a class, put typedef keyword back { yyextra->current->type.prepend("typedef"); @@ -5895,6 +5923,15 @@ NONLopt [^\n]* { // found "enum a *b" -> variable yyextra->current->section = Entry::VARIABLE_SEC ; } + if (yytext[0]==';' && yyextra->current->section == Entry::ENUM_SEC) + { + yyextra->current->reset(); + initEntry(yyscanner); + } + else + { + unput(*yytext); + } BEGIN( FindMembers ); } <Bases,ClassVar>{CPPC}"/"/[^/] { @@ -5906,7 +5943,7 @@ NONLopt [^\n]* { lineCount(yyscanner); yyextra->current->program << yytext; - yyextra->current->fileName = yyextra->yyFileName ; + yyextra->current->fileName = yyextra->fileName ; yyextra->current->startLine = yyextra->yyLineNr ; yyextra->current->startColumn = yyextra->yyColNr; yyextra->curlyCount=0; @@ -5925,7 +5962,7 @@ NONLopt [^\n]* { lineCount(yyscanner); yyextra->current->program << yytext; - yyextra->current->fileName = yyextra->yyFileName ; + yyextra->current->fileName = yyextra->fileName ; yyextra->current->startLine = yyextra->yyLineNr ; yyextra->current->startColumn = yyextra->yyColNr; yyextra->curlyCount=0; @@ -5934,7 +5971,7 @@ NONLopt [^\n]* } <CompoundName,ClassVar>{B}*"{"{B}* { yyextra->current->program.str(std::string()); - yyextra->current->fileName = yyextra->yyFileName ; + yyextra->current->fileName = yyextra->fileName ; yyextra->current->bodyLine = yyextra->yyLineNr; yyextra->current->bodyColumn = yyextra->yyColNr; yyextra->current->name = removeRedundantWhiteSpace(yyextra->current->name); @@ -6187,7 +6224,7 @@ NONLopt [^\n]* } <Bases>{B}*"{"{B}* { yyextra->current->program.str(std::string()); - yyextra->current->fileName = yyextra->yyFileName ; + yyextra->current->fileName = yyextra->fileName ; yyextra->current->bodyLine = yyextra->yyLineNr; yyextra->current->bodyColumn = yyextra->yyColNr; yyextra->current->name = removeRedundantWhiteSpace(yyextra->current->name); @@ -6221,17 +6258,21 @@ NONLopt [^\n]* } <Comment>{CCS} { yyextra->current->program << yytext ; } <Comment>{CPPC} { yyextra->current->program << yytext ; } -<Comment>{CMD}("code"|"verbatim") { - yyextra->insideCode=TRUE; +<Comment>{CMD}("code"|"verbatim"|"iliteral") { + if (yyextra->doxygenComment) yyextra->insideCode=TRUE; yyextra->current->program << yytext ; } -<Comment>{CMD}("endcode"|"endverbatim") { - yyextra->insideCode=FALSE; +<Comment>{CMD}("endcode"|"endverbatim"|"endiliteral") { + if (yyextra->doxygenComment) yyextra->insideCode=FALSE; yyextra->current->program << yytext ; } <Comment>[^ \.\t\r\n\/\*]+ { yyextra->current->program << yytext ; } -<Comment>{CCE} { yyextra->current->program << yytext ; - if (!yyextra->insideCode) BEGIN( yyextra->lastContext ) ; +<Comment>{CCE} { yyextra->current->program << yytext ; + if (!yyextra->insideCode) + { + yyextra->doxygenComment=false; + BEGIN( yyextra->lastContext ); + } } <Comment>. { yyextra->current->program << *yytext ; } @@ -6244,7 +6285,7 @@ NONLopt [^\n]* else { yyextra->current->docLine = yyextra->yyLineNr; - yyextra->current->docFile = yyextra->yyFileName; + yyextra->current->docFile = yyextra->fileName; } yyextra->lastDocContext = YY_START; @@ -6263,7 +6304,7 @@ NONLopt [^\n]* if (yyextra->docBlockAutoBrief) { yyextra->current->briefLine = yyextra->yyLineNr; - yyextra->current->briefFile = yyextra->yyFileName; + yyextra->current->briefFile = yyextra->fileName; } startCommentBlock(yyscanner,FALSE); BEGIN( DocBlock ); @@ -6276,13 +6317,13 @@ NONLopt [^\n]* { yyextra->lastDocContext = YY_START; - //printf("Found comment banner at %s:%d\n",yyextra->yyFileName,yyextra->yyLineNr); + //printf("Found comment banner at %s:%d\n",yyextra->fileName,yyextra->yyLineNr); if (yyextra->current_root->section & Entry::SCOPE_MASK) { yyextra->current->inside = yyextra->current_root->name+"::"; } yyextra->current->docLine = yyextra->yyLineNr; - yyextra->current->docFile = yyextra->yyFileName; + yyextra->current->docFile = yyextra->fileName; yyextra->docBlockContext = YY_START; yyextra->docBlockInBody = YY_START==SkipCurly; bool javadocAutoBrief = Config_getBool(JAVADOC_AUTOBRIEF); @@ -6295,7 +6336,7 @@ NONLopt [^\n]* if (yyextra->docBlockAutoBrief) { yyextra->current->briefLine = yyextra->yyLineNr; - yyextra->current->briefFile = yyextra->yyFileName; + yyextra->current->briefFile = yyextra->fileName; } startCommentBlock(yyscanner,FALSE); BEGIN( DocBlock ); @@ -6304,19 +6345,20 @@ NONLopt [^\n]* { yyextra->current->program << yytext ; yyextra->lastContext = YY_START ; + yyextra->doxygenComment=true; BEGIN( Comment ) ; } } <FindMembers,FindFields,MemberSpec,FuncQual,SkipCurly,Operator,ClassVar,SkipInits,Bases,OldStyleArgs>({CPPC}{B}*)?{CCS}"*"/{NCOMM} { yyextra->lastDocContext = YY_START; - //printf("Found comment block at %s:%d\n",yyextra->yyFileName,yyextra->yyLineNr); + //printf("Found comment block at %s:%d\n",yyextra->fileName,yyextra->yyLineNr); if (yyextra->current_root->section & Entry::SCOPE_MASK) { yyextra->current->inside = yyextra->current_root->name+"::"; } yyextra->current->docLine = yyextra->yyLineNr; - yyextra->current->docFile = yyextra->yyFileName; + yyextra->current->docFile = yyextra->fileName; yyextra->docBlockContext = YY_START; yyextra->docBlockInBody = YY_START==SkipCurly; bool javadocAutoBrief = Config_getBool(JAVADOC_AUTOBRIEF); @@ -6329,7 +6371,7 @@ NONLopt [^\n]* if (yyextra->docBlockAutoBrief) { yyextra->current->briefLine = yyextra->yyLineNr; - yyextra->current->briefFile = yyextra->yyFileName; + yyextra->current->briefFile = yyextra->fileName; } startCommentBlock(yyscanner,FALSE); BEGIN( DocBlock ); @@ -6366,14 +6408,14 @@ NONLopt [^\n]* startCommentBlock(yyscanner,yyextra->current->brief.isEmpty()); BEGIN( DocLine ); } -<FindMembers>"extern"{BN}*"\"C"("++")?"\""{BN}*("{")? { +<FindMembers>"extern"{BN}*"\""[^\"]+"\""{BN}*("{")? { lineCount(yyscanner); - yyextra->externC=TRUE; + yyextra->externLinkage=TRUE; } <FindMembers>"{" { - if (yyextra->externC) + if (yyextra->externLinkage) { - yyextra->externC=FALSE; + yyextra->externLinkage=FALSE; } else if (yyextra->insideCS && !yyextra->current->name.isEmpty() && @@ -6629,7 +6671,7 @@ NONLopt [^\n]* yyextra->nestedComment=FALSE; BEGIN(DocCopyBlock); } -<DocBlock>{CMD}("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"rtfonly"|"docbookonly"|"dot"|"msc"|"code")/[^a-z_A-Z0-9\-] { // verbatim command (which could contain nested comments!) +<DocBlock>{CMD}("verbatim"|"iliteral"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"rtfonly"|"docbookonly"|"dot"|"msc"|"code")/[^a-z_A-Z0-9\-] { // verbatim command (which could contain nested comments!) yyextra->docBlock << yytext; yyextra->docBlockName=&yytext[1]; yyextra->fencedSize=0; @@ -6645,7 +6687,9 @@ NONLopt [^\n]* yyextra->nestedComment=FALSE; BEGIN(DocCopyBlock); } -<DocBlock>^({B}*"*"+)?{B}{0,3}"```"[`]* { +<DocBlock>^({B}*"*"+)?{B}{0,3}"```"[`]*/(".")?[a-zA-Z0-9#_-]+ | +<DocBlock>^({B}*"*"+)?{B}{0,3}"```"[`]*/"{"[^}]+"}" | +<DocBlock>^({B}*"*"+)?{B}{0,3}"```"[`]* { QCString pat = substitute(yytext,"*"," "); yyextra->docBlock << pat; yyextra->docBlockName="```"; @@ -6700,7 +6744,7 @@ NONLopt [^\n]* BEGIN(DocBlock); } } -<DocCopyBlock>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endmanonly"|"endrtfonly"|"enddot"|"endmsc"|"enduml"|"endcode")/[^a-z_A-Z0-9] { // end of verbatim block +<DocCopyBlock>[\\@]("endverbatim"|"endiliteral"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endmanonly"|"endrtfonly"|"enddot"|"endmsc"|"enduml"|"endcode")/[^a-z_A-Z0-9] { // end of verbatim block yyextra->docBlock << yytext; if (&yytext[4]==yyextra->docBlockName) { @@ -6708,11 +6752,7 @@ NONLopt [^\n]* } } <DocCopyBlock>^{B}*"*"+/{BN}+ { // start of a comment line - if (yyextra->docBlockName=="verbatim") - { - REJECT; - } - else if (yyextra->docBlockName=="code") + if ((yyextra->docBlockName=="verbatim") | (yyextra->docBlockName=="code") || (yyextra->docBlockName=="iliteral")) { REJECT; } @@ -6724,7 +6764,7 @@ NONLopt [^\n]* } } <DocCopyBlock>^{B}*"*"+/{B}+"*"{BN}* { // start of a comment line with two *'s - if (yyextra->docBlockName=="code") + if ((yyextra->docBlockName=="code") || (yyextra->docBlockName=="iliteral")) { QCString indent; indent.fill(' ',computeIndent(yytext,0)); @@ -6736,7 +6776,7 @@ NONLopt [^\n]* } } <DocCopyBlock>^{B}*"*"+/({ID}|"(") { // Assume *var or *(... is part of source code (see bug723516) - if (yyextra->docBlockName=="code") + if ((yyextra->docBlockName=="code") || (yyextra->docBlockName=="iliteral")) { QCString indent; indent.fill(' ',computeIndent(yytext,-1)); @@ -6748,7 +6788,7 @@ NONLopt [^\n]* } } <DocCopyBlock>^{B}*"*"+/{BN}* { // start of a comment line with one * - if (yyextra->docBlockName=="code") + if ((yyextra->docBlockName=="code") || (yyextra->docBlockName=="iliteral")) { QCString indent; if (yyextra->nestedComment) // keep * it is part of the code @@ -6805,7 +6845,7 @@ NONLopt [^\n]* yyextra->docBlock << *yytext; } <DocCopyBlock><<EOF>> { - warn(yyextra->yyFileName,yyextra->yyLineNr, + warn(yyextra->fileName,yyextra->yyLineNr, "reached end of file while inside a '%s' block!\n" "The command that should end the block seems to be missing!\n", qPrint(yyextra->docBlockName)); @@ -6924,6 +6964,18 @@ NONLopt [^\n]* BEGIN(EndCppQuote); } } +<*>^{B}*"#" { + if (!yyextra->insidePHP) + { + yyextra->lastCPPContext = YY_START; + BEGIN( SkipCPP ) ; + } + else + { + yyextra->lastCContext = YY_START ; + BEGIN( SkipCxxComment ) ; + } + } <*>"#" { if (!yyextra->insidePHP) REJECT; @@ -6945,7 +6997,7 @@ NONLopt [^\n]* } } <*>\? { - if (yyextra->insideCS && (YY_START != SkipRound)) + if (yyextra->insideCS && (YY_START != SkipRound) && (YY_START != CSAccessorDecl)) { if (yyextra->current->type.isEmpty()) { @@ -7104,6 +7156,16 @@ static QCString stripQuotes(const char *s) //----------------------------------------------------------------- +// return TRUE iff req holds the start of a requires expression +// or sub-expression without parenthesis, i.e. req is empty or ends with || or && +static bool startOfRequiresExpression(const QCString &req) +{ + QCString r = req.stripWhiteSpace(); + return r.isEmpty() || r.endsWith("&&") || r.endsWith("||"); +} + +//----------------------------------------------------------------- + static bool nameIsOperator(QCString &name) { int i=name.find("operator"); @@ -7118,7 +7180,7 @@ static bool nameIsOperator(QCString &name) static void setContext(yyscan_t yyscanner) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - yyextra->language = getLanguageFromFileName(yyextra->yyFileName); + yyextra->language = getLanguageFromFileName(yyextra->fileName); yyextra->insideIDL = yyextra->language==SrcLangExt_IDL; yyextra->insideJava = yyextra->language==SrcLangExt_Java; yyextra->insideCS = yyextra->language==SrcLangExt_CSharp; @@ -7131,7 +7193,7 @@ static void setContext(yyscan_t yyscanner) yyextra->language==SrcLangExt_Lex); //printf("setContext(%s) yyextra->insideIDL=%d yyextra->insideJava=%d yyextra->insideCS=%d " // "yyextra->insideD=%d yyextra->insidePHP=%d yyextra->insideObjC=%d\n", - // qPrint(yyextra->yyFileName),yyextra->insideIDL,yyextra->insideJava,yyextra->insideCS,yyextra->insideD,yyextra->insidePHP,yyextra->insideObjC + // qPrint(yyextra->fileName),yyextra->insideIDL,yyextra->insideJava,yyextra->insideCS,yyextra->insideD,yyextra->insidePHP,yyextra->insideObjC // ); } @@ -7158,7 +7220,7 @@ static void prependScope(yyscan_t yyscanner) static bool checkForKnRstyleC(yyscan_t yyscanner) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - if (((QCString)yyextra->yyFileName).right(2).lower()!=".c") return FALSE; // must be a C file + if (((QCString)yyextra->fileName).right(2).lower()!=".c") return FALSE; // must be a C file if (yyextra->current->argList.empty()) return FALSE; // must have arguments for (const Argument &a : yyextra->current->argList) { @@ -7311,12 +7373,12 @@ static void startCommentBlock(yyscan_t yyscanner,bool brief) struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (brief) { - yyextra->current->briefFile = yyextra->yyFileName; + yyextra->current->briefFile = yyextra->fileName; yyextra->current->briefLine = yyextra->yyLineNr; } else { - yyextra->current->docFile = yyextra->yyFileName; + yyextra->current->docFile = yyextra->fileName; yyextra->current->docLine = yyextra->yyLineNr; } } @@ -7355,20 +7417,20 @@ static void handleCommentBlock(yyscan_t yyscanner,const QCString &doc,bool brief std::shared_ptr<Entry> docEntry = yyextra->docBlockInBody && yyextra->previous ? yyextra->previous : yyextra->current; if (yyextra->docBlockInBody && docEntry && docEntry->inbodyLine==-1) { - docEntry->inbodyFile = yyextra->yyFileName; + docEntry->inbodyFile = yyextra->fileName; docEntry->inbodyLine = lineNr; } int position=0; bool needsEntry=FALSE; - Markdown markdown(yyextra->yyFileName,lineNr); + Markdown markdown(yyextra->fileName,lineNr); QCString strippedDoc = stripIndentation(doc); QCString processedDoc = Config_getBool(MARKDOWN_SUPPORT) ? markdown.process(strippedDoc,lineNr) : strippedDoc; while (yyextra->commentScanner.parseCommentBlock( yyextra->thisParser, yyextra->docBlockInBody && yyextra->previous ? yyextra->previous.get() : yyextra->current.get(), processedDoc, // text - yyextra->yyFileName, // file + yyextra->fileName, // file lineNr, // line of block start yyextra->docBlockInBody ? FALSE : brief, // isBrief yyextra->docBlockInBody ? FALSE : yyextra->docBlockAutoBrief, // isJavaDocStyle @@ -7428,7 +7490,7 @@ static void handleParametersCommentBlocks(yyscan_t yyscanner,ArgumentList &al) yyextra->thisParser, yyextra->current.get(), a.docs, // text - yyextra->yyFileName, // file + yyextra->fileName, // file yyextra->current->docLine, // line of block start FALSE, FALSE, @@ -7483,7 +7545,7 @@ static void parseCompounds(yyscan_t yyscanner,const std::shared_ptr<Entry> &rt) else BEGIN( FindMembers ) ; yyextra->current_root = ce; - yyextra->yyFileName = ce->fileName; + yyextra->fileName = ce->fileName; //setContext(); yyextra->yyLineNr = ce->bodyLine; yyextra->yyColNr = ce->bodyColumn; @@ -7552,13 +7614,13 @@ static void parseCompounds(yyscan_t yyscanner,const std::shared_ptr<Entry> &rt) //memberGroupRelates.resize(0); //memberGroupInside.resize(0); QCString name = ce->name; - yyextra->commentScanner.enterCompound(yyextra->yyFileName,yyextra->yyLineNr,name); + yyextra->commentScanner.enterCompound(yyextra->fileName,yyextra->yyLineNr,name); scannerYYlex(yyscanner); yyextra->lexInit=TRUE; //forceEndGroup(); - yyextra->commentScanner.leaveCompound(yyextra->yyFileName,yyextra->yyLineNr,name); + yyextra->commentScanner.leaveCompound(yyextra->fileName,yyextra->yyLineNr,name); yyextra->programStr.resize(0); ce->program.str(std::string()); @@ -7566,7 +7628,7 @@ static void parseCompounds(yyscan_t yyscanner,const std::shared_ptr<Entry> &rt) //if (depthIf>0) //{ - // warn(yyextra->yyFileName,yyextra->yyLineNr,"Documentation block ended in the middle of a conditional section!"); + // warn(yyextra->fileName,yyextra->yyLineNr,"Documentation block ended in the middle of a conditional section!"); //} } parseCompounds(yyscanner,ce); @@ -7598,21 +7660,21 @@ static void parseMain(yyscan_t yyscanner, yyextra->yyLineNr = 1 ; yyextra->yyBegLineNr = 1; yyextra->yyBegColNr = 0; - yyextra->yyFileName = fileName; + yyextra->fileName = fileName; yyextra->clangParser = clangParser; setContext(yyscanner); rt->lang = yyextra->language; - msg("Parsing file %s...\n",qPrint(yyextra->yyFileName)); + msg("Parsing file %s...\n",qPrint(yyextra->fileName)); yyextra->current_root = rt; initParser(yyscanner); - yyextra->commentScanner.enterFile(yyextra->yyFileName,yyextra->yyLineNr); + yyextra->commentScanner.enterFile(yyextra->fileName,yyextra->yyLineNr); yyextra->current = std::make_shared<Entry>(); //printf("yyextra->current=%p yyextra->current_root=%p\n",yyextra->current,yyextra->current_root); - int sec=guessSection(yyextra->yyFileName); + int sec=guessSection(yyextra->fileName); if (sec) { - yyextra->current->name = yyextra->yyFileName; + yyextra->current->name = yyextra->fileName; yyextra->current->section = sec; yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); } @@ -7625,7 +7687,7 @@ static void parseMain(yyscan_t yyscanner, else if ( yyextra->insideJava ) // add default java.lang package scope { yyextra->current->name="java::lang"; // '::' is used in doxygen's internal representation as a scope separator - yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->fileName = yyextra->fileName; yyextra->current->section=Entry::USINGDIR_SEC; yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); initEntry(yyscanner); @@ -7641,11 +7703,11 @@ static void parseMain(yyscan_t yyscanner, if (YY_START==Comment) { - warn(yyextra->yyFileName,yyextra->yyLineNr,"File ended in the middle of a comment block! Perhaps a missing \\endcode?"); + warn(yyextra->fileName,yyextra->yyLineNr,"File ended in the middle of a comment block! Perhaps a missing \\endcode?"); } //forceEndGroup(); - yyextra->commentScanner.leaveFile(yyextra->yyFileName,yyextra->yyLineNr); + yyextra->commentScanner.leaveFile(yyextra->fileName,yyextra->yyLineNr); yyextra->programStr.resize(0); rt->program.str(std::string()); @@ -7672,7 +7734,7 @@ static void parsePrototype(yyscan_t yyscanner,const QCString &text) //printf("**** parsePrototype(%s) begin\n",qPrint(text)); if (text.isEmpty()) { - warn(yyextra->yyFileName,yyextra->yyLineNr,"Empty prototype found!"); + warn(yyextra->fileName,yyextra->yyLineNr,"Empty prototype found!"); return; } if (!yyextra->current) // nothing to store (see bug683516) diff --git a/src/searchindex.cpp b/src/searchindex.cpp index 0fda0fb..55716e0 100644 --- a/src/searchindex.cpp +++ b/src/searchindex.cpp @@ -472,7 +472,7 @@ void SearchIndexExternal::setCurrentDoc(const Definition *ctx,const QCString &an { static QCString extId = stripPath(Config_getString(EXTERNAL_SEARCH_ID)); QCString baseName = isSourceFile ? (toFileDef(ctx))->getSourceFileBase() : ctx->getOutputFileBase(); - QCString url = baseName + Doxygen::htmlFileExtension; + QCString url = addHtmlExtensionIfMissing(baseName); if (!anchor.isEmpty()) url+=QCString("#")+anchor; QCString key = extId+";"+url; diff --git a/src/section.h b/src/section.h index c219677..0cee070 100644 --- a/src/section.h +++ b/src/section.h @@ -78,6 +78,9 @@ class SectionInfo void setGenerated(bool b) { m_generated = b; } void setDefinition(Definition *d) { m_definition = d; } void setTitle(const QCString &t) { m_title = t; } + void setLevel(int l) { m_level = l; } + void setReference(const QCString &r) { m_ref = r; } + void setLineNr(int l) { m_lineNr = l; } private: QCString m_label; @@ -148,8 +151,21 @@ class SectionManager : public LinkedMap<SectionInfo> SectionInfo *replace(const QCString &label, const QCString &fileName, int lineNr, const QCString &title, SectionType type, int level,const QCString &ref=QCString()) { - LinkedMap<SectionInfo>::del(label.data()); - return LinkedMap<SectionInfo>::add(label.data(),fileName,lineNr,title,type,level,ref); + SectionInfo *si = LinkedMap<SectionInfo>::find(label.data()); + if (si) + { + si->setFileName(fileName); + si->setLineNr(lineNr); + si->setTitle(title); + si->setType(type); + si->setLevel(level); + si->setReference(ref); + return si; + } + else + { + return LinkedMap<SectionInfo>::add(label.data(),fileName,lineNr,title,type,level,ref); + } } //! returns a reference to the singleton diff --git a/src/sqlcode.l b/src/sqlcode.l index a674c71..b82cf34 100644 --- a/src/sqlcode.l +++ b/src/sqlcode.l @@ -21,6 +21,10 @@ %option extra-type="struct sqlcodeYY_state *" %top{ #include <stdint.h> +// forward declare yyscan_t to improve type safety +#define YY_TYPEDEF_YY_SCANNER_T +struct yyguts_t; +typedef yyguts_t *yyscan_t; } %{ @@ -51,9 +55,10 @@ struct sqlcodeYY_state CodeOutputInterface * code; const char *inputString; //!< the code fragment as text yy_size_t inputPosition; //!< read offset during parsing + QCString fileName; int inputLines; //!< number of line in the code fragment int yyLineNr; //!< current line number - bool needsTermination; + bool insideCodeLine; const Definition *searchCtx; bool exampleBlock; @@ -84,6 +89,10 @@ static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size); #undef YY_INPUT #define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); +// otherwise the filename would be the name of the converted file (*.cpp instead of *.l) +static inline const char *getLexerFILE() {return __FILE__;} +#include "doxygen_lex.h" + %} nl (\r\n|\r|\n) @@ -238,24 +247,28 @@ static void startCodeLine(yyscan_t yyscanner) { yyextra->code->writeLineNumber(yyextra->currentMemberDef->getReference(), yyextra->currentMemberDef->getOutputFileBase(), - yyextra->currentMemberDef->anchor(),yyextra->yyLineNr); + yyextra->currentMemberDef->anchor(),yyextra->yyLineNr, + !yyextra->includeCodeFragment); setCurrentDoc(yyscanner,lineAnchor); } else { yyextra->code->writeLineNumber(d->getReference(), d->getOutputFileBase(), - QCString(),yyextra->yyLineNr); + QCString(),yyextra->yyLineNr, + !yyextra->includeCodeFragment); setCurrentDoc(yyscanner,lineAnchor); } } else { - yyextra->code->writeLineNumber(QCString(),QCString(),QCString(),yyextra->yyLineNr); + yyextra->code->writeLineNumber(QCString(),QCString(),QCString(),yyextra->yyLineNr, + !yyextra->includeCodeFragment); } } yyextra->code->startCodeLine(yyextra->sourceFileDef); + yyextra->insideCodeLine=true; if (yyextra->currentFontClass) { @@ -278,13 +291,17 @@ static void endCodeLine(yyscan_t yyscanner) struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; endFontClass(yyscanner); yyextra->code->endCodeLine(); + yyextra->insideCodeLine=false; } static void nextCodeLine(yyscan_t yyscanner) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; const char *fc = yyextra->currentFontClass; - endCodeLine(yyscanner); + if (yyextra->insideCodeLine) + { + endCodeLine(yyscanner); + } if (yyextra->yyLineNr<yyextra->inputLines) { yyextra->currentFontClass = fc; @@ -344,8 +361,7 @@ static int countLines(yyscan_t yyscanner) if (p>yyextra->inputString && *(p-1)!='\n') { // last line does not end with a \n, so we add an extra // line and explicitly terminate the line after parsing. - count++, - yyextra->needsTermination=true; + count++; } return count; } @@ -417,12 +433,13 @@ void SQLCodeParser::parseCode(CodeOutputInterface &codeOutIntf, if (input.isEmpty()) return; printlex(yy_flex_debug, true, __FILE__, fileDef ? qPrint(fileDef->fileName()): NULL); + yyextra->fileName = fileDef ? fileDef->fileName():""; yyextra->code = &codeOutIntf; yyextra->inputString = input.data(); yyextra->inputPosition = 0; yyextra->currentFontClass = 0; - yyextra->needsTermination = false; + yyextra->insideCodeLine = false; yyextra->searchCtx=searchCtx; if (startLine!=-1) @@ -461,7 +478,7 @@ void SQLCodeParser::parseCode(CodeOutputInterface &codeOutIntf, sqlcodeYYlex(yyscanner); - if (yyextra->needsTermination) + if (yyextra->insideCodeLine) { endCodeLine(yyscanner); } diff --git a/src/symbolresolver.cpp b/src/symbolresolver.cpp index 68c93da..29b5d6a 100644 --- a/src/symbolresolver.cpp +++ b/src/symbolresolver.cpp @@ -25,6 +25,7 @@ #include "defargs.h" static std::mutex g_cacheMutex; +static std::recursive_mutex g_cacheTypedefMutex; //-------------------------------------------------------------------------------------- @@ -494,6 +495,7 @@ const ClassDef *SymbolResolver::Private::newResolveTypedef( QCString *pResolvedType, // out const std::unique_ptr<ArgumentList> &actTemplParams) // in { + std::lock_guard<std::recursive_mutex> lock(g_cacheTypedefMutex); //printf("newResolveTypedef(md=%p,cachedVal=%p)\n",md,md->getCachedTypedefVal()); bool isCached = md->isTypedefValCached(); // value already cached if (isCached) @@ -1039,6 +1041,7 @@ const ClassDef *SymbolResolver::resolveClass(const Definition *scope, (scope->definitionType()!=Definition::TypeClass && scope->definitionType()!=Definition::TypeNamespace ) || + (name.stripWhiteSpace().startsWith("::")) || (scope->getLanguage()==SrcLangExt_Java && QCString(name).find("::")!=-1) ) { @@ -1046,7 +1049,7 @@ const ClassDef *SymbolResolver::resolveClass(const Definition *scope, } //fprintf(stderr,"------------ resolveClass(scope=%s,name=%s,mayUnlinkable=%d)\n", // scope?qPrint(scope->name()):"<global>", - // name, + // qPrint(name), // mayBeUnlinkable // ); const ClassDef *result; @@ -1068,12 +1071,12 @@ const ClassDef *SymbolResolver::resolveClass(const Definition *scope, { if (!mayBeHidden || !result->isHidden()) { - //printf("result was %s\n",result?qPrint(result->name()):"<none>"); + //fprintf(stderr,"result was %s\n",result?qPrint(result->name()):"<none>"); result=0; // don't link to artificial/hidden classes unless explicitly allowed } } //fprintf(stderr,"ResolvedClass(%s,%s)=%s\n",scope?qPrint(scope->name()):"<global>", - // name,result?qPrint(result->name()):"<none>"); + // qPrint(name),result?qPrint(result->name()):"<none>"); return result; } diff --git a/src/tagreader.cpp b/src/tagreader.cpp index 6dca1cd..5ff51ae 100644 --- a/src/tagreader.cpp +++ b/src/tagreader.cpp @@ -40,6 +40,13 @@ #include "containers.h" #include "debug.h" +// set to 1 for debugging +#define DUMP_OUTPUT 0 + +// ----------------- private part ----------------------------------------------- + +namespace { + /** Information about an linkable anchor */ class TagAnchorInfo { @@ -105,7 +112,7 @@ class TagCompoundInfo QCString name; QCString filename; std::vector<TagAnchorInfo> docAnchors; - int lineNr; + int lineNr = 0; private: CompoundType m_type; }; @@ -985,6 +992,7 @@ void TagFileParser::startCompound( const XMLHandlers::Attributes& attrib ) } } +#if DUMP_OUTPUT /*! Dumps the internal structures. For debugging only! */ void TagFileParser::dump() { @@ -1156,6 +1164,7 @@ void TagFileParser::dump() } } } +#endif void TagFileParser::addDocAnchors(const std::shared_ptr<Entry> &e,const std::vector<TagAnchorInfo> &l) { @@ -1563,6 +1572,10 @@ void TagFileParser::addIncludes() } } +} // namespace + +// ----------------- public part ----------------------------------------------- + void parseTagFile(const std::shared_ptr<Entry> &root,const char *fullName) { TagFileParser tagFileParser(fullName); @@ -1579,5 +1592,7 @@ void parseTagFile(const std::shared_ptr<Entry> &root,const char *fullName) parser.parse(fullName,inputStr.data(),Debug::isFlagSet(Debug::Lex)); tagFileParser.buildLists(root); tagFileParser.addIncludes(); - //tagFileParser.dump(); +#if DUMP_OUTPUT + tagFileParser.dump(); +#endif } diff --git a/src/template.cpp b/src/template.cpp index aeab71c..7b6954f 100755 --- a/src/template.cpp +++ b/src/template.cpp @@ -141,69 +141,194 @@ static QCString replace(const QCString &s,char csrc,char cdst) } #endif -//- TemplateVariant implementation ------------------------------------------- +//- Template struct & list forward declarations ------------------------------ +class TemplateStruct; +using TemplateStructPtr = std::shared_ptr<TemplateStruct>; -TemplateVariant::TemplateVariant(TemplateStructIntf *s) +/** @brief Default implementation of a context value of type struct. */ +class TemplateStruct : public TemplateStructIntf { - m_variant.set<TemplateStructIntf*>(s); - s->addRef(); -} + public: + // TemplateStructIntf methods + virtual TemplateVariant get(const QCString &name) const; + virtual StringVector fields() const; -TemplateVariant::TemplateVariant(TemplateListIntf *l) -{ - m_variant.set<TemplateListIntf*>(l); - l->addRef(); -} + /** Creates an instance and returns a shared pointer to it */ + static TemplateStructPtr alloc(); + + /** Sets the value the field of a struct + * @param[in] name The name of the field. + * @param[in] v The value to set. + */ + virtual void set(const QCString &name,const TemplateVariant &v); + + /** Removes the field from the struct */ + virtual void remove(const QCString &name); + + /** Creates a struct */ + TemplateStruct() = default; //{ printf("%p:TemplateStruct::TemplateStruct()\n",(void*)this); } + /** Destroys the struct */ + virtual ~TemplateStruct() = default; //{ printf("%p:TemplateStruct::~TemplateStruct()\n",(void*)this); } + + private: + + std::unordered_map<std::string,TemplateVariant> m_fields; +}; -TemplateVariant::~TemplateVariant() +void TemplateStruct::set(const QCString &name,const TemplateVariant &v) { - try + auto it = m_fields.find(name.str()); + if (it!=m_fields.end()) // change existing field { - if (m_variant.is<TemplateStructIntf*>()) m_variant.get<TemplateStructIntf*>()->release(); - else if (m_variant.is<TemplateListIntf*>()) m_variant.get<TemplateListIntf*>()->release(); + it->second = v; } - catch(...) + else // insert new field { - // should never happen + m_fields.insert(std::make_pair(name.str(),v)); } } -TemplateVariant::TemplateVariant(const TemplateVariant &v) +void TemplateStruct::remove(const QCString &name) { - m_raw = v.m_raw; - m_variant = v.m_variant; - if (m_variant.is<TemplateStructIntf*>()) m_variant.get<TemplateStructIntf*>()->addRef(); - else if (m_variant.is<TemplateListIntf*>()) m_variant.get<TemplateListIntf*>()->addRef(); + auto it = m_fields.find(name.str()); + if (it!=m_fields.end()) + { + m_fields.erase(it); + } } -TemplateVariant::TemplateVariant(TemplateVariant &&v) +TemplateVariant TemplateStruct::get(const QCString &name) const { - m_raw = std::move(v.m_raw); - m_variant = std::move(v.m_variant); - v.m_variant.invalidate(); + auto it = m_fields.find(name.str()); + return it!=m_fields.end() ? it->second : TemplateVariant(); } -TemplateVariant &TemplateVariant::operator=(const TemplateVariant &v) +StringVector TemplateStruct::fields() const { - if (this!=&v) + StringVector result; + for (const auto &kv : m_fields) { - // assignment can change the type of the variable, so we have to be - // careful with reference counted content. - TemplateStructIntf *tmpStruct = m_variant.is<TemplateStructIntf*>() ? m_variant.get<TemplateStructIntf*>() : nullptr; - TemplateListIntf *tmpList = m_variant.is<TemplateListIntf*>() ? m_variant.get<TemplateListIntf*>() : nullptr; + result.push_back(kv.first); + } + std::sort(result.begin(),result.end()); + return result; +} + +TemplateStructPtr TemplateStruct::alloc() +{ + return std::make_shared<TemplateStruct>(); +} - m_raw = v.m_raw; - m_variant = v.m_variant; +class TemplateList; +using TemplateListPtr = std::shared_ptr<TemplateList>; - if (m_variant.is<TemplateStructIntf*>()) m_variant.get<TemplateStructIntf*>()->addRef(); - else if (m_variant.is<TemplateListIntf*>()) m_variant.get<TemplateListIntf*>()->addRef(); +//- Template list implementation ---------------------------------------------- - // release overwritten reference counted values - if (tmpStruct) tmpStruct->release(); - else if (tmpList ) tmpList->release(); - } - return *this; +// iterator support +template<class List> +class TemplateListGenericConstIterator : public TemplateListIntf::ConstIterator +{ + public: + TemplateListGenericConstIterator(const List &l) : m_list(l) { m_index=0; } + virtual ~TemplateListGenericConstIterator() {} + virtual void toFirst() + { + m_index=0; + } + virtual void toLast() + { + uint count = m_list.count(); + m_index = count>0 ? count-1 : 0; + } + virtual void toNext() + { + if (m_index<m_list.count()) { m_index++; } + } + virtual void toPrev() + { + if (m_index>0) { --m_index; } + } + virtual bool current(TemplateVariant &v) const + { + if (m_index<m_list.count()) + { + v = m_list.at(m_index); + return TRUE; + } + else + { + v = TemplateVariant(); + return FALSE; + } + } + private: + const List &m_list; + size_t m_index = 0; +}; + +//------------------------------------------------------------------------------- +// +/** @brief Default implementation of a context value of type list. */ +class TemplateList : public TemplateListIntf +{ + public: + // TemplateListIntf methods + virtual uint count() const + { + return static_cast<uint>(m_elems.size()); + } + virtual TemplateVariant at(uint index) const + { + return index < m_elems.size() ? m_elems[index] : TemplateVariant(); + } + virtual TemplateListIntf::ConstIteratorPtr createIterator() const + { + return std::make_unique< TemplateListGenericConstIterator<TemplateList> >(*this); + } + + /** Creates an instance and returns a shared pointer to it */ + static TemplateListPtr alloc() + { + return std::make_shared<TemplateList>(); + } + + /** Appends element \a v to the end of the list */ + virtual void append(const TemplateVariant &v) + { + m_elems.push_back(v); + } + + void removeAt(uint index) + { + if (index<m_elems.size()) + { + m_elems.erase(m_elems.begin()+index); + } + } + + void insertAt(uint index,TemplateListPtr list) + { + auto it = m_elems.begin()+index; + m_elems.insert(it,list->m_elems.begin(),list->m_elems.end()); + } + + /** Creates a list */ + TemplateList() = default; //{ printf("%p:TemplateList::TemplateList()\n",(void*)this); } + /** Destroys the list */ + virtual ~TemplateList() = default; //{ printf("%p:TemplateList::~TemplateList()\n",(void*)this); } + + private: + TemplateVariantList m_elems; +}; + +//- TemplateVariant implementation ------------------------------------------- + +TemplateVariant::TemplateVariant(TemplateVariant &&v) +{ + m_raw = std::move(v.m_raw); + m_variant = std::move(v.m_variant); + v.m_variant.invalidate(); } TemplateVariant &TemplateVariant::operator=(TemplateVariant &&v) @@ -214,17 +339,43 @@ TemplateVariant &TemplateVariant::operator=(TemplateVariant &&v) return *this; } +bool TemplateVariant::operator==(TemplateVariant &other) const +{ + if (!m_variant.valid()) + { + return FALSE; + } + if (isBool() && other.isBool()) + { + return m_variant.get<static_cast<uint8_t>(Type::Bool)>() == other.m_variant.get<static_cast<uint8_t>(Type::Bool)>(); + } + else if (isInt() && other.isInt()) + { + return m_variant.get<static_cast<uint8_t>(Type::Int)>() == other.m_variant.get<static_cast<uint8_t>(Type::Int)>(); + } + else if (isList() && other.isList()) + { + return toList() == other.toList(); + } + else if ((isStruct() || isWeakStruct()) && (other.isStruct() || other.isWeakStruct())) + { + return toStruct() == other.toStruct(); + } + return toString()==other.toString(); +} + bool TemplateVariant::toBool() const { switch (type()) { - case Type::None: return false; - case Type::Bool: return m_variant.get<bool>(); - case Type::Int: return m_variant.get<int>()!=0; - case Type::String: return !m_variant.get<QCString>().isEmpty(); - case Type::Struct: return true; - case Type::List: return m_variant.get<TemplateListIntf*>()->count()!=0; - case Type::Function: return false; + case Type::None: return false; + case Type::Bool: return m_variant.get<static_cast<uint8_t>(Type::Bool)>(); + case Type::Int: return m_variant.get<static_cast<uint8_t>(Type::Int)>()!=0; + case Type::String: return !m_variant.get<static_cast<uint8_t>(Type::String)>().isEmpty(); + case Type::Struct: return true; + case Type::List: return m_variant.get<static_cast<uint8_t>(Type::List)>()->count()!=0; + case Type::Function: return false; + case Type::WeakStruct: return true; } return FALSE; } @@ -233,13 +384,14 @@ int TemplateVariant::toInt() const { switch (type()) { - case Type::None: return 0; - case Type::Bool: return m_variant.get<bool>() ? 1 : 0; - case Type::Int: return m_variant.get<int>(); - case Type::String: return !m_variant.get<QCString>().toInt(); - case Type::Struct: return 0; - case Type::List: return m_variant.get<TemplateListIntf*>()->count(); - case Type::Function: return 0; + case Type::None: return 0; + case Type::Bool: return m_variant.get<static_cast<uint8_t>(Type::Bool)>() ? 1 : 0; + case Type::Int: return m_variant.get<static_cast<uint8_t>(Type::Int)>(); + case Type::String: return !m_variant.get<static_cast<uint8_t>(Type::String)>().toInt(); + case Type::Struct: return 0; + case Type::List: return m_variant.get<static_cast<uint8_t>(Type::List)>()->count(); + case Type::Function: return 0; + case Type::WeakStruct: return 0; } return 0; } @@ -248,75 +400,90 @@ QCString TemplateVariant::toString() const { switch (type()) { - case Type::None: return QCString(); - case Type::Bool: return m_variant.get<bool>() ? "true" : "false"; - case Type::Int: return QCString().setNum(m_variant.get<int>()); - case Type::String: return m_variant.get<QCString>(); - case Type::Struct: return structToString(); - case Type::List: return listToString(); - case Type::Function: return "[function]"; + case Type::None: return QCString(); + case Type::Bool: return m_variant.get<static_cast<uint8_t>(Type::Bool)>() ? "true" : "false"; + case Type::Int: return QCString().setNum(m_variant.get<static_cast<uint8_t>(Type::Int)>()); + case Type::String: return m_variant.get<static_cast<uint8_t>(Type::String)>(); + case Type::Struct: return structToString(); + case Type::List: return listToString(); + case Type::Function: return "[function]"; + case Type::WeakStruct: return structToString(); } return QCString(); } - -//- Template struct implementation -------------------------------------------- - - -/** @brief Private data of a template struct object */ -class TemplateStruct::Private +/** Return a string representation of the type of the value stored in the variant */ +const char *TemplateVariant::typeAsString() const { - public: - Private() : refCount(0) {} - std::unordered_map<std::string,TemplateVariant> fields; - int refCount = 0; -}; + switch (type()) + { + case Type::None: return "invalid"; + case Type::Bool: return "bool"; + case Type::Int: return "integer"; + case Type::String: return "string"; + case Type::Struct: return "struct"; + case Type::List: return "list"; + case Type::Function: return "function"; + case Type::WeakStruct: return "struct"; + } + return "invalid"; +} -TemplateStruct::TemplateStruct() +TemplateListIntfPtr TemplateVariant::toList() +{ + return isList() ? m_variant.get<static_cast<uint8_t>(Type::List)>() : nullptr; +} +const TemplateListIntfPtr TemplateVariant::toList() const { - p = new Private; + return isList() ? m_variant.get<static_cast<uint8_t>(Type::List)>() : nullptr; } -TemplateStruct::~TemplateStruct() +TemplateStructIntfPtr TemplateVariant::toStruct() { - delete p; + return isStruct() ? m_variant.get<static_cast<uint8_t>(Type::Struct)>() : + isWeakStruct() ? m_variant.get<static_cast<uint8_t>(Type::WeakStruct)>().lock() : + nullptr; +} +const TemplateStructIntfPtr TemplateVariant::toStruct() const +{ + return isStruct() ? m_variant.get<static_cast<uint8_t>(Type::Struct)>() : + isWeakStruct() ? m_variant.get<static_cast<uint8_t>(Type::WeakStruct)>().lock() : + nullptr; } -int TemplateStruct::addRef() +TemplateVariant TemplateVariant::call(const std::vector<TemplateVariant> &args) { - return ++p->refCount; + return isFunction() ? m_variant.get<static_cast<uint8_t>(Type::Function)>()(args) : TemplateVariant(); } -int TemplateStruct::release() +//- Template struct implementation -------------------------------------------- + + +/** @brief Private data of a template struct object */ +class TemplateImmutableStruct::Private +{ + public: + Private(std::initializer_list<StructField> fs) : fields(fs) {} + std::unordered_map<std::string,TemplateVariant> fields; +}; + +TemplateImmutableStruct::TemplateImmutableStruct( + std::initializer_list<StructField> fields) + : p(std::make_unique<Private>(fields)) { - int count = --p->refCount; - if (count<=0) - { - delete this; - } - return count; } -void TemplateStruct::set(const QCString &name,const TemplateVariant &v) +TemplateImmutableStruct::~TemplateImmutableStruct() { - auto it = p->fields.find(name.str()); - if (it!=p->fields.end()) // change existing field - { - it->second = v; - } - else // insert new field - { - p->fields.insert(std::make_pair(name.str(),v)); - } } -TemplateVariant TemplateStruct::get(const QCString &name) const +TemplateVariant TemplateImmutableStruct::get(const QCString &name) const { auto it = p->fields.find(name.str()); return it!=p->fields.end() ? it->second : TemplateVariant(); } -StringVector TemplateStruct::fields() const +StringVector TemplateImmutableStruct::fields() const { StringVector result; for (const auto &kv : p->fields) @@ -327,133 +494,60 @@ StringVector TemplateStruct::fields() const return result; } -TemplateStruct *TemplateStruct::alloc() +TemplateStructIntfPtr TemplateImmutableStruct::alloc(std::initializer_list<StructField> fields) { - return new TemplateStruct; + return std::make_shared<TemplateImmutableStruct>(fields); } -//- Template list implementation ---------------------------------------------- - +//- Template immutable list implementation ------------------------------------ -/** @brief Private data of a template list object */ -class TemplateList::Private +/** @brief Private data of a template immutable list object */ +class TemplateImmutableList::Private { public: - Private() : index(-1), refCount(0) {} - std::vector<TemplateVariant> elems; + Private(std::initializer_list<TemplateVariant> e) : elems(e) {} + Private(const TemplateVariantList &e) : elems(e) {} + TemplateVariantList elems; int index = -1; - int refCount = 0; }; - -TemplateList::TemplateList() +TemplateImmutableList::TemplateImmutableList(std::initializer_list<TemplateVariant> elements) + : p(std::make_unique<Private>(elements)) { - p = new Private; } -TemplateList::~TemplateList() +TemplateImmutableList::TemplateImmutableList(const TemplateVariantList &elements) + : p(std::make_unique<Private>(elements)) { - delete p; } -int TemplateList::addRef() +TemplateImmutableList::~TemplateImmutableList() { - return ++p->refCount; } -int TemplateList::release() -{ - int count = --p->refCount; - if (count<=0) - { - delete this; - } - return count; -} - -uint TemplateList::count() const +uint TemplateImmutableList::count() const { return static_cast<uint>(p->elems.size()); } -void TemplateList::append(const TemplateVariant &v) -{ - p->elems.push_back(v); -} - -// iterator support -class TemplateListConstIterator : public TemplateListIntf::ConstIterator -{ - public: - TemplateListConstIterator(const TemplateList &l) : m_list(l) { m_index=0; } - virtual ~TemplateListConstIterator() {} - virtual void toFirst() - { - m_index=0; - } - virtual void toLast() - { - if (m_list.p->elems.size()>0) +TemplateListIntf::ConstIteratorPtr TemplateImmutableList::createIterator() const { - m_index=m_list.p->elems.size()-1; + return std::make_unique< TemplateListGenericConstIterator<TemplateImmutableList> >(*this); } - else - { - m_index=0; - } - } - virtual void toNext() - { - if (m_index<m_list.p->elems.size()) - { - m_index++; - } - } - virtual void toPrev() - { - if (m_index>0) - { - --m_index; - } - } - virtual bool current(TemplateVariant &v) const - { - if (m_index<m_list.p->elems.size()) - { - v = m_list.p->elems[m_index]; - return TRUE; - } - else - { - v = TemplateVariant(); - return FALSE; - } - } - private: - const TemplateList &m_list; - size_t m_index = 0; -}; -TemplateListIntf::ConstIterator *TemplateList::createIterator() const +TemplateVariant TemplateImmutableList::at(uint index) const { - return new TemplateListConstIterator(*this); + return index<p->elems.size() ? p->elems[index] : TemplateVariant(); } -TemplateVariant TemplateList::at(uint index) const +TemplateListIntfPtr TemplateImmutableList::alloc(std::initializer_list<TemplateVariant> elements) { - if (index<p->elems.size()) - { - return p->elems[index]; - } - else - { - return TemplateVariant(); - } + return std::make_shared<TemplateImmutableList>(elements); } -TemplateList *TemplateList::alloc() +TemplateListIntfPtr TemplateImmutableList::alloc(const TemplateVariantList &elements) { - return new TemplateList; + return std::make_shared<TemplateImmutableList>(elements); } //- Operator types ------------------------------------------------------------ @@ -549,27 +643,38 @@ class TemplateContextImpl : public TemplateContext TemplateContextImpl(const TemplateEngine *e); virtual ~TemplateContextImpl(); + using EscapeIntfMap = std::unordered_map<std::string, std::unique_ptr<TemplateEscapeIntf>>; + void copyEscapeIntfMap(const EscapeIntfMap &map) + { + for (const auto &kv : map) + { + m_escapeIntfMap.insert(std::make_pair(kv.first,kv.second->clone())); + } + } + // TemplateContext methods void push(); void pop(); void set(const QCString &name,const TemplateVariant &v); - void update(const QCString &name,const TemplateVariant &v); + //void update(const QCString &name,const TemplateVariant &v); TemplateVariant get(const QCString &name) const; const TemplateVariant *getRef(const QCString &name) const; void setOutputDirectory(const QCString &dir) { m_outputDir = dir; } - void setEscapeIntf(const QCString &ext,TemplateEscapeIntf *intf) + void setEscapeIntf(const QCString &ext,std::unique_ptr<TemplateEscapeIntf> intf) { int i=(!ext.isEmpty() && ext.at(0)=='.') ? 1 : 0; - m_escapeIntfMap.insert(std::make_pair(ext.mid(i).str(),intf)); + m_escapeIntfMap.insert(std::make_pair(ext.mid(i).str(),std::move(intf))); } void selectEscapeIntf(const QCString &ext) { auto it = m_escapeIntfMap.find(ext.str()); - m_activeEscapeIntf = it!=m_escapeIntfMap.end() ? it->second : 0; + m_activeEscapeIntf = it!=m_escapeIntfMap.end() ? it->second.get() : 0; } void setActiveEscapeIntf(TemplateEscapeIntf *intf) { m_activeEscapeIntf = intf; } - void setSpacelessIntf(TemplateSpacelessIntf *intf) { m_spacelessIntf = intf; } + TemplateEscapeIntf *escapeIntf() { return m_activeEscapeIntf; } + const TemplateEscapeIntf *escapeIntf() const { return m_activeEscapeIntf; } + void setSpacelessIntf(std::unique_ptr<TemplateSpacelessIntf> intf) { m_spacelessIntf = std::move(intf); } // internal methods TemplateBlockContext *blockContext(); @@ -579,8 +684,8 @@ class TemplateContextImpl : public TemplateContext QCString templateName() const { return m_templateName; } int line() const { return m_line; } QCString outputDirectory() const { return m_outputDir; } - TemplateEscapeIntf *escapeIntf() const { return m_activeEscapeIntf; } - TemplateSpacelessIntf *spacelessIntf() const { return m_spacelessIntf; } + std::unique_ptr<TemplateSpacelessIntf> &spacelessIntf() { return m_spacelessIntf; } + const std::unique_ptr<TemplateSpacelessIntf> &spacelessInfo() const { return m_spacelessIntf; } void enableSpaceless(bool b) { if (b && !m_spacelessEnabled) m_spacelessIntf->reset(); m_spacelessEnabled=b; } @@ -599,20 +704,21 @@ class TemplateContextImpl : public TemplateContext void openSubIndex(const QCString &indexName); void closeSubIndex(const QCString &indexName); void addIndexEntry(const QCString &indexName,const std::vector<TemplateKeyValue> &arguments); + const TemplateStructPtr indices() const { return m_indices; } private: const TemplateEngine *m_engine = 0; - QCString m_templateName; - int m_line = 0; + QCString m_templateName = "<unknown>"; + int m_line = 1; QCString m_outputDir; - std::deque< std::map<std::string,TemplateVariant> > m_contextStack; + std::deque< std::unordered_map<std::string,TemplateVariant> > m_contextStack; TemplateBlockContext m_blockContext; - std::unordered_map<std::string, TemplateEscapeIntf*> m_escapeIntfMap; + EscapeIntfMap m_escapeIntfMap; TemplateEscapeIntf *m_activeEscapeIntf = 0; - TemplateSpacelessIntf *m_spacelessIntf = 0; + std::unique_ptr<TemplateSpacelessIntf> m_spacelessIntf; bool m_spacelessEnabled = false; bool m_tabbingEnabled = false; - TemplateAutoRef<TemplateStruct> m_indices; + TemplateStructPtr m_indices; std::unordered_map< std::string, std::stack<TemplateVariant> > m_indexStacks; QCString m_encoding; void *m_fromUtf8 = 0; @@ -665,16 +771,24 @@ class FilterGet public: static TemplateVariant apply(const TemplateVariant &v,const TemplateVariant &arg) { - if (v.isValid() && v.isStruct() && arg.isString()) + if (v.isValid() && (v.isStruct() || v.isWeakStruct()) && arg.isString()) { - TemplateVariant result = v.toStruct()->get(arg.toString()); - //printf("\nok[%s]=%d\n",qPrint(arg.toString()),result.type()); - return result; + TemplateStructIntfPtr s = v.toStruct(); + if (s) + { + TemplateVariant result = v.toStruct()->get(arg.toString()); + //printf("\nok[%s]=%d\n",qPrint(arg.toString()),result.type()); + return result; + } + else + { + return false; + } } else { //printf("\nnok[%s]\n",qPrint(arg.toString())); - return FALSE; + return false; } } }; @@ -706,33 +820,37 @@ class FilterKeep public: static TemplateVariant apply(const TemplateVariant &v,const TemplateVariant &args) { - if (v.isValid() && v.isList() && args.isString()) + if (v.isValid() && (v.isList()) && args.isString()) { - //printf("FilterKeep::apply: v=%s args=%s\n",qPrint(v.toString()),qPrint(args.toString())); - TemplateListIntf::ConstIterator *it = v.toList()->createIterator(); - - TemplateList *result = TemplateList::alloc(); - TemplateVariant item; - for (it->toFirst();(it->current(item));it->toNext()) + TemplateListIntfPtr list = v.toList(); + if (list) { - //printf("item type=%s\n",item.typeAsString()); - TemplateStructIntf *s = item.toStruct(); - if (s) + //printf("FilterKeep::apply: v=%s args=%s\n",qPrint(v.toString()),qPrint(args.toString())); + TemplateListIntf::ConstIteratorPtr it = list->createIterator(); + + TemplateListPtr result = TemplateList::alloc(); + TemplateVariant item; + for (it->toFirst();(it->current(item));it->toNext()) { - TemplateVariant value = s->get(args.toString()); - //printf("value type=%s\n",value.typeAsString()); - if (value.toBool()) - { - //printf("keeping it\n"); - result->append(item); - } - else + //printf("item type=%s\n",item.typeAsString()); + TemplateStructIntfPtr s = item.toStruct(); + if (s) { - //printf("Dropping it\n"); + TemplateVariant value = s->get(args.toString()); + //printf("value type=%s\n",value.typeAsString()); + if (value.toBool()) + { + //printf("keeping it\n"); + result->append(item); + } + else + { + //printf("Dropping it\n"); + } } } + return TemplateVariant(std::static_pointer_cast<TemplateListIntf>(result)); } - return result; } return v; } @@ -753,9 +871,9 @@ class FilterList return v; } // create a list with v as the only element - TemplateList *list = TemplateList::alloc(); + TemplateListPtr list = TemplateList::alloc(); list->append(v); - return list; + return TemplateVariant(std::static_pointer_cast<TemplateListIntf>(list)); } else { @@ -905,36 +1023,39 @@ class FilterFlatten } else { - TemplateList *list = TemplateList::alloc(); - flatten(v.toList(),list); - return TemplateVariant(list); + TemplateListPtr list = TemplateList::alloc(); + TemplateListIntfPtr tree = v.toList(); + flatten(tree,list); + return TemplateVariant(std::static_pointer_cast<TemplateListIntf>(list)); } } private: - static void flatten(const TemplateListIntf *tree,TemplateList *list) + static void flatten(const TemplateListIntfPtr tree,TemplateListPtr list) { - TemplateListIntf::ConstIterator *it = tree->createIterator(); - TemplateVariant item; - for (it->toFirst();(it->current(item));it->toNext()) + if (tree) { - TemplateStructIntf *s = item.toStruct(); - if (s) + TemplateListIntf::ConstIteratorPtr it = tree->createIterator(); + TemplateVariant item; + for (it->toFirst();(it->current(item));it->toNext()) { - list->append(item); - // if s has "children" then recurse into the children - TemplateVariant children = s->get("children"); - if (children.isValid() && children.isList()) + TemplateStructIntfPtr s = item.toStruct(); + if (s) { - flatten(children.toList(),list); + list->append(item); + // if s has "children" then recurse into the children + TemplateVariant children = s->get("children"); + if (children.isValid() && children.isList()) + { + flatten(children.toList(),list); + } + } + else + { + list->append(item); } - } - else - { - list->append(item); } } - delete it; } }; @@ -955,44 +1076,47 @@ class FilterListSort if (v.isList() && args.isString()) { //printf("FilterListSort::apply: v=%s args=%s\n",qPrint(v.toString()),qPrint(args.toString())); - TemplateListIntf::ConstIterator *it = v.toList()->createIterator(); + TemplateListIntfPtr list = v.toList(); + if (list) + { + TemplateListIntf::ConstIteratorPtr it = list->createIterator(); - TemplateVariant item; - TemplateList *result = TemplateList::alloc(); + TemplateVariant item; + TemplateListPtr result = TemplateList::alloc(); - // create list of items based on v using the data in args as a sort key - using SortList = std::vector<ListElem>; - SortList sortList; - sortList.reserve(v.toList()->count()); - for (it->toFirst();(it->current(item));it->toNext()) - { - TemplateStructIntf *s = item.toStruct(); - if (s) + // create list of items based on v using the data in args as a sort key + using SortList = std::vector<ListElem>; + SortList sortList; + sortList.reserve(v.toList()->count()); + for (it->toFirst();(it->current(item));it->toNext()) { - QCString sortKey = determineSortKey(s,args.toString()); - sortList.emplace_back(sortKey,item); - //printf("sortKey=%s\n",qPrint(sortKey)); + TemplateStructIntfPtr s = item.toStruct(); + if (s) + { + QCString sortKey = determineSortKey(s,args.toString()); + sortList.emplace_back(sortKey,item); + //printf("sortKey=%s\n",qPrint(sortKey)); + } } - } - delete it; - // sort the list - std::sort(sortList.begin(), - sortList.end(), - [](const auto &lhs,const auto &rhs) { return lhs.key < rhs.key; }); + // sort the list + std::sort(sortList.begin(), + sortList.end(), + [](const auto &lhs,const auto &rhs) { return lhs.key < rhs.key; }); - // add sorted items to the result list - for (const auto &elem : sortList) - { - result->append(elem.value); + // add sorted items to the result list + for (const auto &elem : sortList) + { + result->append(elem.value); + } + return TemplateVariant(std::static_pointer_cast<TemplateListIntf>(result)); } - return result; } return v; } private: - static QCString determineSortKey(TemplateStructIntf *s,const QCString &arg) + static QCString determineSortKey(const TemplateStructIntfPtr s,const QCString &arg) { int i,p=0; QCString result; @@ -1034,53 +1158,56 @@ class FilterGroupBy { if (v.isList() && args.isString()) { - //printf("FilterListSort::apply: v=%s args=%s\n",qPrint(v.toString()),qPrint(args.toString())); - TemplateListIntf::ConstIterator *it = v.toList()->createIterator(); + TemplateListIntfPtr list = v.toList(); + if (list) + { + //printf("FilterListSort::apply: v=%s args=%s\n",qPrint(v.toString()),qPrint(args.toString())); + TemplateListIntf::ConstIteratorPtr it = list->createIterator(); - TemplateVariant item; - TemplateList *result = TemplateList::alloc(); + TemplateVariant item; + TemplateListPtr result = TemplateList::alloc(); - // create list of items based on v using the data in args as a sort key - using SortList = std::vector<ListElem>; - SortList sortList; - sortList.reserve(v.toList()->count()); - for (it->toFirst();(it->current(item));it->toNext()) - { - TemplateStructIntf *s = item.toStruct(); - if (s) + // create list of items based on v using the data in args as a sort key + using SortList = std::vector<ListElem>; + SortList sortList; + sortList.reserve(v.toList()->count()); + for (it->toFirst();(it->current(item));it->toNext()) { - QCString sortKey = determineSortKey(s,args.toString()); - sortList.emplace_back(sortKey,item); - //printf("sortKey=%s\n",qPrint(sortKey)); + TemplateStructIntfPtr s = item.toStruct(); + if (s) + { + QCString sortKey = determineSortKey(s,args.toString()); + sortList.emplace_back(sortKey,item); + //printf("sortKey=%s\n",qPrint(sortKey)); + } } - } - delete it; - // sort the list - std::sort(sortList.begin(), - sortList.end(), - [](const auto &lhs,const auto &rhs) { return lhs.key < rhs.key; }); + // sort the list + std::sort(sortList.begin(), + sortList.end(), + [](const auto &lhs,const auto &rhs) { return lhs.key < rhs.key; }); - // add sorted items to the result list - TemplateList *groupList=0; - QCString prevKey; - for (const auto &elem : sortList) - { - if (groupList==0 || elem.key!=prevKey) + // add sorted items to the result list + TemplateListPtr groupList; + QCString prevKey; + for (const auto &elem : sortList) { - groupList = TemplateList::alloc(); - result->append(groupList); - prevKey = elem.key; + if (groupList==0 || elem.key!=prevKey) + { + groupList = TemplateList::alloc(); + result->append(std::static_pointer_cast<TemplateListIntf>(groupList)); + prevKey = elem.key; + } + groupList->append(elem.value); } - groupList->append(elem.value); + return TemplateVariant(std::static_pointer_cast<TemplateListIntf>(result)); } - return result; } return v; } private: - static QCString determineSortKey(TemplateStructIntf *s,const QCString &attribName) + static QCString determineSortKey(const TemplateStructIntfPtr s,const QCString &attribName) { TemplateVariant v = s->get(attribName); return v.toString(); @@ -1118,18 +1245,18 @@ class FilterPaginate args.isValid() && args.isInt()) { int pageSize = args.toInt(); - const TemplateListIntf *list = v.toList(); - TemplateList *result = TemplateList::alloc(); - TemplateListIntf::ConstIterator *it = list->createIterator(); + const TemplateListIntfPtr list = v.toList(); + TemplateListPtr result = TemplateList::alloc(); + TemplateListIntf::ConstIteratorPtr it = list->createIterator(); TemplateVariant item; - TemplateList *pageList=0; + TemplateListPtr pageList; int i = 0; for (it->toFirst();(it->current(item));it->toNext()) { if (pageList==0) { pageList = TemplateList::alloc(); - result->append(pageList); + result->append(std::static_pointer_cast<TemplateListIntf>(pageList)); } pageList->append(item); i++; @@ -1139,8 +1266,7 @@ class FilterPaginate i=0; } } - delete it; - return result; + return TemplateVariant(std::static_pointer_cast<TemplateListIntf>(result)); } else // wrong arguments { @@ -1184,7 +1310,7 @@ class FilterAlphaIndex //printf("<keyToLabel(%s)\n",qPrint(result)); return result; } - static std::string determineSortKey(TemplateStructIntf *s,const QCString &attribName) + static std::string determineSortKey(const TemplateStructIntfPtr s,const QCString &attribName) { TemplateVariant v = s->get(attribName); int index = getPrefixIndex(v.toString()); @@ -1196,53 +1322,56 @@ class FilterAlphaIndex { if (v.isList() && args.isString()) { - //printf("FilterListSort::apply: v=%s args=%s\n",qPrint(v.toString()),qPrint(args.toString())); - TemplateListIntf::ConstIterator *it = v.toList()->createIterator(); + TemplateListIntfPtr list = v.toList(); + if (list) + { + //printf("FilterListSort::apply: v=%s args=%s\n",qPrint(v.toString()),qPrint(args.toString())); + TemplateListIntf::ConstIteratorPtr it = list->createIterator(); - TemplateVariant item; - TemplateList *result = TemplateList::alloc(); + TemplateVariant item; + TemplateListPtr result = TemplateList::alloc(); - // create list of items based on v using the data in args as a sort key - using SortList = std::vector<ListElem>; - SortList sortList; - sortList.reserve(v.toList()->count()); - for (it->toFirst();(it->current(item));it->toNext()) - { - TemplateStructIntf *s = item.toStruct(); - if (s) + // create list of items based on v using the data in args as a sort key + using SortList = std::vector<ListElem>; + SortList sortList; + sortList.reserve(v.toList()->count()); + for (it->toFirst();(it->current(item));it->toNext()) { - std::string sortKey = determineSortKey(s,args.toString()); - sortList.emplace_back(sortKey,item); - //printf("sortKey=%s\n",qPrint(sortKey)); + TemplateStructIntfPtr s = item.toStruct(); + if (s) + { + std::string sortKey = determineSortKey(s,args.toString()); + sortList.emplace_back(sortKey,item); + //printf("sortKey=%s\n",qPrint(sortKey)); + } } - } - delete it; - - // sort the list - std::sort(sortList.begin(), - sortList.end(), - [](const auto &lhs,const auto &rhs) { return lhs.key < rhs.key; }); - - // create an index from the sorted list - std::string letter; - TemplateStruct *indexNode = 0; - TemplateList *indexList = 0; - for (const auto &elem : sortList) - { - if (letter!=elem.key || indexNode==0) + + // sort the list + std::sort(sortList.begin(), + sortList.end(), + [](const auto &lhs,const auto &rhs) { return lhs.key < rhs.key; }); + + // create an index from the sorted list + std::string letter; + TemplateStructPtr indexNode; + TemplateListPtr indexList; + for (const auto &elem : sortList) { - // create new indexNode - indexNode = TemplateStruct::alloc(); - indexList = TemplateList::alloc(); - indexNode->set("letter", elem.key); - indexNode->set("label", keyToLabel(elem.key.c_str())); - indexNode->set("items",indexList); - result->append(indexNode); - letter=elem.key; + if (letter!=elem.key || indexNode==0) + { + // create new indexNode + indexNode = TemplateStruct::alloc(); + indexList = TemplateList::alloc(); + indexNode->set("letter", elem.key); + indexNode->set("label", keyToLabel(elem.key.c_str())); + indexNode->set("items",std::static_pointer_cast<TemplateListIntf>(indexList)); + result->append(std::static_pointer_cast<TemplateStructIntf>(indexNode)); + letter=elem.key; + } + indexList->append(elem.value); } - indexList->append(elem.value); + return TemplateVariant(std::static_pointer_cast<TemplateListIntf>(result)); } - return result; } return v; } @@ -1456,11 +1585,11 @@ class TemplateFilterFactory public: typedef TemplateVariant (FilterFunction)(const TemplateVariant &v,const TemplateVariant &arg); - static TemplateFilterFactory *instance() + static TemplateFilterFactory &instance() { - static TemplateFilterFactory *instance = 0; - if (instance==0) instance = new TemplateFilterFactory; - return instance; + static std::unique_ptr<TemplateFilterFactory> instance; + if (instance==0) instance = std::make_unique<TemplateFilterFactory>(); + return *instance; } TemplateVariant apply(const QCString &name,const TemplateVariant &v,const TemplateVariant &arg, bool &ok) @@ -1489,7 +1618,7 @@ class TemplateFilterFactory public: AutoRegister<T>(const QCString &key) { - TemplateFilterFactory::instance()->registerFilter(key,&T::apply); + TemplateFilterFactory::instance().registerFilter(key,&T::apply); } }; @@ -1538,7 +1667,8 @@ class ExprAst virtual TemplateVariant resolve(TemplateContext *) { return TemplateVariant(); } }; -using ExprAstList = std::vector< std::unique_ptr<ExprAst> >; +using ExprAstPtr = std::unique_ptr<ExprAst>; +using ExprAstList = std::vector< ExprAstPtr >; /** @brief Class representing a number in the AST */ class ExprAstNumber : public ExprAst @@ -1576,14 +1706,10 @@ class ExprAstVariable : public ExprAst class ExprAstFunctionVariable : public ExprAst { public: - ExprAstFunctionVariable(ExprAst *var, ExprAstList &&args) - : m_var(var), m_args(std::move(args)) + ExprAstFunctionVariable(ExprAstPtr &&var, ExprAstList &&args) + : m_var(std::move(var)), m_args(std::move(args)) { TRACE(("ExprAstFunctionVariable()\n")); } - ~ExprAstFunctionVariable() - { - delete m_var; - } virtual TemplateVariant resolve(TemplateContext *c) { std::vector<TemplateVariant> args; @@ -1600,7 +1726,7 @@ class ExprAstFunctionVariable : public ExprAst return v; } private: - ExprAst *m_var = 0; + ExprAstPtr m_var; ExprAstList m_args; }; @@ -1608,9 +1734,8 @@ class ExprAstFunctionVariable : public ExprAst class ExprAstFilter : public ExprAst { public: - ExprAstFilter(const QCString &name,ExprAst *arg) : m_name(name), m_arg(arg) + ExprAstFilter(const QCString &name,ExprAstPtr &&arg) : m_name(name), m_arg(std::move(arg)) { TRACE(("ExprAstFilter(%s)\n",name.data())); } - ~ExprAstFilter() { delete m_arg; } const QCString &name() const { return m_name; } TemplateVariant apply(const TemplateVariant &v,TemplateContext *c) { @@ -1620,7 +1745,7 @@ class ExprAstFilter : public ExprAst TemplateVariant arg; if (m_arg) arg = m_arg->resolve(c); bool ok; - TemplateVariant result = TemplateFilterFactory::instance()->apply(m_name,v,arg,ok); + TemplateVariant result = TemplateFilterFactory::instance().apply(m_name,v,arg,ok); if (!ok) { ci->warn(ci->templateName(),ci->line(),"unknown filter '%s'",qPrint(m_name)); @@ -1629,24 +1754,25 @@ class ExprAstFilter : public ExprAst } private: QCString m_name; - ExprAst *m_arg = 0; + ExprAstPtr m_arg; }; +using ExprAstFilterPtr = std::unique_ptr<ExprAstFilter>; + /** @brief Class representing a filter applied to an expression in the AST */ class ExprAstFilterAppl : public ExprAst { public: - ExprAstFilterAppl(ExprAst *expr,ExprAstFilter *filter) - : m_expr(expr), m_filter(filter) + ExprAstFilterAppl(ExprAstPtr &&expr,ExprAstFilterPtr &&filter) + : m_expr(std::move(expr)), m_filter(std::move(filter)) { TRACE(("ExprAstFilterAppl\n")); } - ~ExprAstFilterAppl() { delete m_expr; delete m_filter; } virtual TemplateVariant resolve(TemplateContext *c) { return m_filter->apply(m_expr->resolve(c),c); } private: - ExprAst *m_expr = 0; - ExprAstFilter *m_filter; + ExprAstPtr m_expr; + ExprAstFilterPtr m_filter; }; /** @brief Class representing a string literal in the AST */ @@ -1665,45 +1791,42 @@ class ExprAstLiteral : public ExprAst class ExprAstNegate : public ExprAst { public: - ExprAstNegate(ExprAst *expr) : m_expr(expr) + ExprAstNegate(ExprAstPtr &&expr) : m_expr(std::move(expr)) { TRACE(("ExprAstNegate\n")); } - ~ExprAstNegate() { delete m_expr; } virtual TemplateVariant resolve(TemplateContext *c) { return TemplateVariant(!m_expr->resolve(c).toBool()); } private: - ExprAst *m_expr = 0; + ExprAstPtr m_expr; }; class ExprAstUnary : public ExprAst { public: - ExprAstUnary(Operator::Type op,ExprAst *exp) : m_operator(op), m_exp(exp) + ExprAstUnary(Operator::Type op,ExprAstPtr &&expr) : m_operator(op), m_expr(std::move(expr)) { TRACE(("ExprAstUnary %s\n",Operator::toString(op))); } - ~ExprAstUnary() { delete m_exp; } virtual TemplateVariant resolve(TemplateContext *c) { - TemplateVariant exp = m_exp->resolve(c); + TemplateVariant expr = m_expr->resolve(c); switch (m_operator) { case Operator::Minus: - return -exp.toInt(); + return -expr.toInt(); default: return TemplateVariant(); } } private: Operator::Type m_operator = Operator::Or; - ExprAst *m_exp = 0; + ExprAstPtr m_expr; }; /** @brief Class representing a binary operator in the AST */ class ExprAstBinary : public ExprAst { public: - ExprAstBinary(Operator::Type op,ExprAst *lhs,ExprAst *rhs) - : m_operator(op), m_lhs(lhs), m_rhs(rhs) + ExprAstBinary(Operator::Type op,ExprAstPtr &&lhs,ExprAstPtr &&rhs) + : m_operator(op), m_lhs(std::move(lhs)), m_rhs(std::move(rhs)) { TRACE(("ExprAstBinary %s\n",Operator::toString(op))); } - ~ExprAstBinary() { delete m_lhs; delete m_rhs; } virtual TemplateVariant resolve(TemplateContext *c) { TemplateContextImpl *ci = dynamic_cast<TemplateContextImpl*>(c); @@ -1800,8 +1923,8 @@ class ExprAstBinary : public ExprAst } private: Operator::Type m_operator = Operator::Or; - ExprAst *m_lhs = 0; - ExprAst *m_rhs = 0; + ExprAstPtr m_lhs; + ExprAstPtr m_rhs; }; //---------------------------------------------------------- @@ -1821,6 +1944,8 @@ class TemplateNode TemplateNode *m_parent = 0; }; +using TemplateNodePtr = std::unique_ptr<TemplateNode>; + //---------------------------------------------------------- /** @brief Class representing a lexical token in a template */ @@ -1840,7 +1965,7 @@ using TemplateTokenStream = std::deque< TemplateTokenPtr >; //---------------------------------------------------------- /** @brief Class representing a list of AST nodes in a template */ -class TemplateNodeList : public std::vector< std::unique_ptr<TemplateNode> > +class TemplateNodeList : public std::vector< TemplateNodePtr > { public: void render(TextStream &ts,TemplateContext *c) @@ -1893,7 +2018,7 @@ class ExpressionParser { } - ExprAst *parse(const QCString &expr) + ExprAstPtr parse(const QCString &expr) { if (expr.isEmpty()) return 0; m_tokenStream = expr.data(); @@ -1921,65 +2046,65 @@ class ExpressionParser Operator::Type op; }; - ExprAst *parseExpression() + ExprAstPtr parseExpression() { TRACE(("{parseExpression(%s)\n",m_tokenStream)); - ExprAst *result = parseOrExpression(); + ExprAstPtr result { parseOrExpression() }; TRACE(("}parseExpression(%s)\n",m_tokenStream)); return result; } - ExprAst *parseOrExpression() + ExprAstPtr parseOrExpression() { TRACE(("{parseOrExpression(%s)\n",m_tokenStream)); - ExprAst *lhs = parseAndExpression(); + ExprAstPtr lhs { parseAndExpression() }; if (lhs) { while (m_curToken.type==ExprToken::Operator && m_curToken.op==Operator::Or) { getNextToken(); - ExprAst *rhs = parseAndExpression(); - lhs = new ExprAstBinary(Operator::Or,lhs,rhs); + ExprAstPtr rhs { parseAndExpression() }; + lhs = std::make_unique<ExprAstBinary>(Operator::Or,std::move(lhs),std::move(rhs)); } } TRACE(("}parseOrExpression(%s)\n",m_tokenStream)); return lhs; } - ExprAst *parseAndExpression() + ExprAstPtr parseAndExpression() { TRACE(("{parseAndExpression(%s)\n",m_tokenStream)); - ExprAst *lhs = parseNotExpression(); + ExprAstPtr lhs { parseNotExpression() }; if (lhs) { while (m_curToken.type==ExprToken::Operator && m_curToken.op==Operator::And) { getNextToken(); - ExprAst *rhs = parseNotExpression(); - lhs = new ExprAstBinary(Operator::And,lhs,rhs); + ExprAstPtr rhs { parseNotExpression() }; + lhs = std::make_unique<ExprAstBinary>(Operator::And,std::move(lhs),std::move(rhs)); } } TRACE(("}parseAndExpression(%s)\n",m_tokenStream)); return lhs; } - ExprAst *parseNotExpression() + ExprAstPtr parseNotExpression() { TRACE(("{parseNotExpression(%s)\n",m_tokenStream)); - ExprAst *result=0; + ExprAstPtr result; if (m_curToken.type==ExprToken::Operator && m_curToken.op==Operator::Not) { getNextToken(); - ExprAst *expr = parseCompareExpression(); + ExprAstPtr expr = parseCompareExpression(); if (expr==0) { warn(m_parser->templateName(),m_line,"argument missing for not operator"); return 0; } - result = new ExprAstNegate(expr); + result = std::make_unique<ExprAstNegate>(std::move(expr)); } else { @@ -1989,10 +2114,10 @@ class ExpressionParser return result; } - ExprAst *parseCompareExpression() + ExprAstPtr parseCompareExpression() { TRACE(("{parseCompareExpression(%s)\n",m_tokenStream)); - ExprAst *lhs = parseAdditiveExpression(); + ExprAstPtr lhs { parseAdditiveExpression() }; if (lhs) { Operator::Type op = m_curToken.op; @@ -2007,18 +2132,18 @@ class ExpressionParser ) { getNextToken(); - ExprAst *rhs = parseNotExpression(); - lhs = new ExprAstBinary(op,lhs,rhs); + ExprAstPtr rhs { parseNotExpression() }; + lhs = std::make_unique<ExprAstBinary>(op,std::move(lhs),std::move(rhs)); } } TRACE(("}parseCompareExpression(%s)\n",m_tokenStream)); return lhs; } - ExprAst *parseAdditiveExpression() + ExprAstPtr parseAdditiveExpression() { TRACE(("{parseAdditiveExpression(%s)\n",m_tokenStream)); - ExprAst *lhs = parseMultiplicativeExpression(); + ExprAstPtr lhs { parseMultiplicativeExpression() }; if (lhs) { while (m_curToken.type==ExprToken::Operator && @@ -2026,18 +2151,18 @@ class ExpressionParser { Operator::Type op = m_curToken.op; getNextToken(); - ExprAst *rhs = parseMultiplicativeExpression(); - lhs = new ExprAstBinary(op,lhs,rhs); + ExprAstPtr rhs { parseMultiplicativeExpression() }; + lhs = std::make_unique<ExprAstBinary>(op,std::move(lhs),std::move(rhs)); } } TRACE(("}parseAdditiveExpression(%s)\n",m_tokenStream)); return lhs; } - ExprAst *parseMultiplicativeExpression() + ExprAstPtr parseMultiplicativeExpression() { TRACE(("{parseMultiplicativeExpression(%s)\n",m_tokenStream)); - ExprAst *lhs = parseUnaryExpression(); + ExprAstPtr lhs = parseUnaryExpression(); if (lhs) { while (m_curToken.type==ExprToken::Operator && @@ -2045,18 +2170,18 @@ class ExpressionParser { Operator::Type op = m_curToken.op; getNextToken(); - ExprAst *rhs = parseUnaryExpression(); - lhs = new ExprAstBinary(op,lhs,rhs); + ExprAstPtr rhs = parseUnaryExpression(); + lhs = std::make_unique<ExprAstBinary>(op,std::move(lhs),std::move(rhs)); } } TRACE(("}parseMultiplicativeExpression(%s)\n",m_tokenStream)); return lhs; } - ExprAst *parseUnaryExpression() + ExprAstPtr parseUnaryExpression() { TRACE(("{parseUnaryExpression(%s)\n",m_tokenStream)); - ExprAst *result=0; + ExprAstPtr result; if (m_curToken.type==ExprToken::Operator) { if (m_curToken.op==Operator::Plus) @@ -2067,8 +2192,8 @@ class ExpressionParser else if (m_curToken.op==Operator::Minus) { getNextToken(); - ExprAst *rhs = parsePrimaryExpression(); - result = new ExprAstUnary(m_curToken.op,rhs); + ExprAstPtr rhs { parsePrimaryExpression() }; + result = std::make_unique<ExprAstUnary>(m_curToken.op,std::move(rhs)); } else { @@ -2083,10 +2208,10 @@ class ExpressionParser return result; } - ExprAst *parsePrimaryExpression() + ExprAstPtr parsePrimaryExpression() { TRACE(("{parsePrimary(%s)\n",m_tokenStream)); - ExprAst *result=0; + ExprAstPtr result; switch (m_curToken.type) { case ExprToken::Number: @@ -2127,37 +2252,37 @@ class ExpressionParser return result; } - ExprAst *parseNumber() + ExprAstPtr parseNumber() { TRACE(("{parseNumber(%d)\n",m_curToken.num)); - ExprAst *num = new ExprAstNumber(m_curToken.num); + ExprAstPtr num = std::make_unique<ExprAstNumber>(m_curToken.num); getNextToken(); TRACE(("}parseNumber()\n")); return num; } - ExprAst *parseIdentifier() + ExprAstPtr parseIdentifier() { TRACE(("{parseIdentifier(%s)\n",qPrint(m_curToken.id))); - ExprAst *id = new ExprAstVariable(m_curToken.id); + ExprAstPtr id = std::make_unique<ExprAstVariable>(m_curToken.id); getNextToken(); TRACE(("}parseIdentifier()\n")); return id; } - ExprAst *parseLiteral() + ExprAstPtr parseLiteral() { TRACE(("{parseLiteral(%s)\n",qPrint(m_curToken.id))); - ExprAst *expr = new ExprAstLiteral(m_curToken.id); + ExprAstPtr expr = std::make_unique<ExprAstLiteral>(m_curToken.id); getNextToken(); TRACE(("}parseLiteral()\n")); return expr; } - ExprAst *parseIdentifierOptionalArgs() + ExprAstPtr parseIdentifierOptionalArgs() { TRACE(("{parseIdentifierOptionalArgs(%s)\n",qPrint(m_curToken.id))); - ExprAst *expr = parseIdentifier(); + ExprAstPtr expr { parseIdentifier() }; if (expr) { if (m_curToken.type==ExprToken::Operator && @@ -2172,45 +2297,45 @@ class ExpressionParser getNextToken(); args.push_back(std::unique_ptr<ExprAst>(parsePrimaryExpression())); } - expr = new ExprAstFunctionVariable(expr,std::move(args)); + expr = std::make_unique<ExprAstFunctionVariable>(std::move(expr),std::move(args)); } } TRACE(("}parseIdentifierOptionalArgs()\n")); return expr; } - ExprAst *parseFilteredVariable() + ExprAstPtr parseFilteredVariable() { TRACE(("{parseFilteredVariable()\n")); - ExprAst *expr = parseIdentifierOptionalArgs(); + ExprAstPtr expr = parseIdentifierOptionalArgs(); if (expr) { while (m_curToken.type==ExprToken::Operator && m_curToken.op==Operator::Filter) { getNextToken(); - ExprAstFilter *filter = parseFilter(); + ExprAstFilterPtr filter = parseFilter(); if (!filter) break; - expr = new ExprAstFilterAppl(expr,filter); + expr = std::make_unique<ExprAstFilterAppl>(std::move(expr),std::move(filter)); } } TRACE(("}parseFilteredVariable()\n")); return expr; } - ExprAstFilter *parseFilter() + ExprAstFilterPtr parseFilter() { TRACE(("{parseFilter(%s)\n",qPrint(m_curToken.id))); QCString filterName = m_curToken.id; getNextToken(); - ExprAst *argExpr=0; + ExprAstPtr argExpr; if (m_curToken.type==ExprToken::Operator && m_curToken.op==Operator::Colon) { getNextToken(); argExpr = parsePrimaryExpression(); } - ExprAstFilter *filter = new ExprAstFilter(filterName,argExpr); + ExprAstFilterPtr filter = std::make_unique<ExprAstFilter>(filterName,std::move(argExpr)); TRACE(("}parseFilter()\n")); return filter; } @@ -2446,36 +2571,19 @@ class TemplateImpl : public TemplateNode, public Template //---------------------------------------------------------- -/** @brief Weak reference wrapper for TemplateStructIntf that provides access to the - * wrapped struct without holding a reference. - */ -class TemplateStructWeakRef : public TemplateStructIntf -{ - public: - TemplateStructWeakRef(TemplateStructIntf *ref) : m_ref(ref), m_refCount(0) {} - virtual TemplateVariant get(const QCString &name) const { return m_ref->get(name); } - virtual StringVector fields() const { return m_ref->fields(); } - virtual int addRef() { return ++m_refCount; } - virtual int release() { int count=--m_refCount; if (count<=0) { delete this; } return count; } - private: - TemplateStructIntf *m_ref = 0; - int m_refCount = 0; -}; - -//---------------------------------------------------------- - TemplateContextImpl::TemplateContextImpl(const TemplateEngine *e) - : m_engine(e), m_templateName("<unknown>"), m_line(1), m_activeEscapeIntf(0), - m_spacelessIntf(0), m_spacelessEnabled(FALSE), m_tabbingEnabled(FALSE), m_indices(TemplateStruct::alloc()) + : m_engine(e), m_indices(TemplateStruct::alloc()) { + //printf("%p:TemplateContextImpl::TemplateContextImpl()\n",(void*)this); m_fromUtf8 = (void*)(-1); push(); - set("index",m_indices.get()); + set("index",std::static_pointer_cast<TemplateStructIntf>(m_indices)); } TemplateContextImpl::~TemplateContextImpl() { pop(); + //printf("%p:TemplateContextImpl::~TemplateContextImpl()\n",(void*)this); } void TemplateContextImpl::setEncoding(const QCString &templateName,int line,const QCString &enc) @@ -2530,24 +2638,10 @@ void TemplateContextImpl::set(const QCString &name,const TemplateVariant &v) ctx.erase(it); } ctx.insert(std::make_pair(name.str(),v)); + //printf("TemplateContextImpl::set(%s) #stacks=%lu front().size()=%lu\n", + // qPrint(name),m_contextStack.size(),m_contextStack.size()>0 ? m_contextStack.front().size() : 0); } -void TemplateContextImpl::update(const QCString &name,const TemplateVariant &v) -{ - int depth=0; - for (auto &ctx : m_contextStack) - { - auto it = ctx.find(name.str()); - if (it!=ctx.end()) - { - ctx.erase(it); - ctx.insert(std::make_pair(name.str(),v)); - return; - } - depth++; - } - warn(m_templateName,m_line,"requesting update for non-existing variable '%s'",qPrint(name)); -} TemplateVariant TemplateContextImpl::get(const QCString &name) const { @@ -2564,47 +2658,63 @@ TemplateVariant TemplateContextImpl::get(const QCString &name) const while (!propName.isEmpty()) { //printf("getPrimary(%s) type=%zu:%s\n",qPrint(objName),v.type(),qPrint(v.toString())); - if (v.isStruct()) + if (v.isStruct() || v.isWeakStruct()) { - i = propName.find("."); - int l = i==-1 ? propName.length() : i; - v = v.toStruct()->get(propName.left(l)); - if (!v.isValid()) - { - warn(m_templateName,m_line,"requesting non-existing property '%s' for object '%s'",qPrint(propName.left(l)),qPrint(objName)); - } - if (i!=-1) + TemplateStructIntfPtr s = v.toStruct(); + if (s) { - objName = propName.left(i); - propName = propName.mid(i+1); + i = propName.find("."); + int l = i==-1 ? propName.length() : i; + v = s->get(propName.left(l)); + if (!v.isValid()) + { + warn(m_templateName,m_line,"requesting non-existing property '%s' for object '%s'",qPrint(propName.left(l)),qPrint(objName)); + } + if (i!=-1) + { + objName = propName.left(i); + propName = propName.mid(i+1); + } + else + { + propName.resize(0); + } } else { - propName.resize(0); + return TemplateVariant(); } } else if (v.isList()) { - i = propName.find("."); - int l = i==-1 ? propName.length() : i; - bool b; - int index = propName.left(l).toInt(&b); - if (b) - { - v = v.toList()->at(index); - } - else - { - warn(m_templateName,m_line,"list index '%s' is not valid",qPrint(propName)); - break; - } - if (i!=-1) + TemplateListIntfPtr list = v.toList(); + if (list) { - propName = propName.mid(i+1); + i = propName.find("."); + int l = i==-1 ? propName.length() : i; + bool b; + int index = propName.left(l).toInt(&b); + if (b) + { + v = list->at(index); + } + else + { + warn(m_templateName,m_line,"list index '%s' is not valid",qPrint(propName)); + break; + } + if (i!=-1) + { + propName = propName.mid(i+1); + } + else + { + propName.resize(0); + } } else { - propName.resize(0); + return TemplateVariant(); } } else @@ -2638,11 +2748,13 @@ TemplateVariant TemplateContextImpl::getPrimary(const QCString &name) const void TemplateContextImpl::push() { - m_contextStack.push_front(std::map<std::string,TemplateVariant>()); + m_contextStack.push_front(std::unordered_map<std::string,TemplateVariant>()); + //printf("TemplateContextImpl::push() #stacks=%lu\n",m_contextStack.size()); } void TemplateContextImpl::pop() { + //printf("TemplateContextImpl::pop() #stacks=%lu\n",m_contextStack.size()); if (m_contextStack.empty()) { warn(m_templateName,m_line,"pop() called on empty context stack!\n"); @@ -2678,13 +2790,13 @@ void TemplateContextImpl::openSubIndex(const QCString &indexName) } // get the parent entry to add the list to auto &stack = kv->second; - TemplateStruct *entry = dynamic_cast<TemplateStruct*>(stack.top().toStruct()); + TemplateStructPtr entry = std::dynamic_pointer_cast<TemplateStruct>(stack.top().toStruct()); if (entry) { // add new list to the stack - TemplateList *list = TemplateList::alloc(); - stack.emplace(list); - entry->set("children",list); + TemplateListPtr list = TemplateList::alloc(); + stack.emplace(std::static_pointer_cast<TemplateListIntf>(list)); + entry->set("children",std::static_pointer_cast<TemplateListIntf>(list)); entry->set("is_leaf_node",false); } } @@ -2700,7 +2812,7 @@ void TemplateContextImpl::closeSubIndex(const QCString &indexName) else { auto &stack = kv->second; // stack.size()>2 - if (stack.top().isStruct()) + if (stack.top().isStruct() || stack.top().isWeakStruct()) { stack.pop(); // pop struct stack.pop(); // pop list @@ -2708,7 +2820,7 @@ void TemplateContextImpl::closeSubIndex(const QCString &indexName) else // empty list! correct "is_left_node" attribute of the parent entry { stack.pop(); // pop list - TemplateStruct *entry = dynamic_cast<TemplateStruct*>(stack.top().toStruct()); + TemplateStructPtr entry = std::dynamic_pointer_cast<TemplateStruct>(stack.top().toStruct()); if (entry) { entry->set("is_leaf_node",true); @@ -2718,28 +2830,30 @@ void TemplateContextImpl::closeSubIndex(const QCString &indexName) //fprintf(stderr,"TemplateContextImpl::closeSubIndex(%s) end g_count=%d\n\n",qPrint(indexName),g_count); } -static void getPathListFunc(TemplateStructIntf *entry,TemplateList *list) +static void getPathListFunc(const TemplateStructIntfPtr entry,TemplateListPtr list) { - TemplateVariant parent = entry->get("parent"); - if (parent.isStruct()) + if (entry) { - getPathListFunc(parent.toStruct(),list); + TemplateVariant parent = entry->get("parent"); + if (parent.isStruct() || parent.isWeakStruct()) + { + getPathListFunc(parent.toStruct(),list); + } + list->append(entry); } - list->append(entry); } -static TemplateVariant getPathFunc(const void *ctx, const std::vector<TemplateVariant> &) +static TemplateVariant getPathFunc(const TemplateStructIntfWeakPtr entryWeakRef) { - TemplateStruct *entry = (TemplateStruct*)ctx; - TemplateList *result = TemplateList::alloc(); - getPathListFunc(entry,result); - return result; + TemplateListPtr result = TemplateList::alloc(); + getPathListFunc(entryWeakRef.lock(),result); + return std::static_pointer_cast<TemplateListIntf>(result); } void TemplateContextImpl::addIndexEntry(const QCString &indexName,const std::vector<TemplateKeyValue> &arguments) { - auto it = arguments.begin(); - //printf("TemplateContextImpl::addIndexEntry(%s)\n",qPrint(indexName)); + //auto it = arguments.begin(); + //printf("%p:> TemplateContextImpl::addIndexEntry(%s)\n",(void*)this,qPrint(indexName)); //while (it!=arguments.end()) //{ // printf(" key=%s value=%s\n",(*it).key.data(),(*it).value.toString().data()); @@ -2751,17 +2865,17 @@ void TemplateContextImpl::addIndexEntry(const QCString &indexName,const std::vec { kv = m_indexStacks.insert(std::make_pair(indexName.str(),std::stack<TemplateVariant>())).first; } - TemplateList *list = 0; + TemplateListPtr list; auto &stack = kv->second; if (stack.empty()) // first item, create empty list and add it to the index { list = TemplateList::alloc(); - stack.emplace(list); - m_indices->set(indexName,list); // make list available under index + stack.emplace(std::static_pointer_cast<TemplateListIntf>(list)); + m_indices->set(indexName,std::static_pointer_cast<TemplateListIntf>(list)); // make list available under index } else // stack not empty { - if (stack.top().isStruct()) // already an entry in the list + if (stack.top().isStruct() || stack.top().isWeakStruct()) // already an entry in the list { // remove current entry from the stack stack.pop(); @@ -2776,22 +2890,21 @@ void TemplateContextImpl::addIndexEntry(const QCString &indexName,const std::vec stack.pop(); // To prevent a cyclic dependency between parent and child which causes a memory // leak, we wrap the parent into a weak reference version. - parent = new TemplateStructWeakRef(stack.top().toStruct()); + //parent = TemplateVariant(TemplateStructIntfWeakPtr(stack.top().toStruct())); stack.push(tmp); - ASSERT(parent.isStruct()); } // get list to add new item - list = dynamic_cast<TemplateList*>(stack.top().toList()); + list = std::dynamic_pointer_cast<TemplateList>(stack.top().toList()); } - TemplateStruct *entry = TemplateStruct::alloc(); + TemplateStructPtr entry = TemplateStruct::alloc(); // add user specified fields to the entry - for (it=arguments.begin();it!=arguments.end();++it) + for (auto it=arguments.begin();it!=arguments.end();++it) { entry->set((*it).key,(*it).value); } if (list->count()>0) { - TemplateStruct *lastEntry = dynamic_cast<TemplateStruct*>(list->at(list->count()-1).toStruct()); + TemplateStructPtr lastEntry = std::dynamic_pointer_cast<TemplateStruct>(list->at(list->count()-1).toStruct()); if (lastEntry) { lastEntry->set("last",false); @@ -2801,10 +2914,11 @@ void TemplateContextImpl::addIndexEntry(const QCString &indexName,const std::vec entry->set("first",list->count()==0); entry->set("index",list->count()); entry->set("parent",parent); - entry->set("path",TemplateVariant::FunctionDelegate::fromFunction(entry,getPathFunc)); + TemplateStructIntfWeakPtr entryWeak(std::static_pointer_cast<TemplateStructIntf>(entry)); + entry->set("path",TemplateVariant([entryWeak](const TemplateVariantList &){ return getPathFunc(entryWeak); })); entry->set("last",true); - stack.emplace(entry); - list->append(entry); + stack.push(TemplateVariant(std::static_pointer_cast<TemplateStructIntf>(entry))); + list->append(TemplateVariant(std::static_pointer_cast<TemplateStructIntf>(entry))); } //---------------------------------------------------------- @@ -2870,11 +2984,11 @@ class TemplateNodeVariable : public TemplateNode } ~TemplateNodeVariable() { - delete m_var; } void render(TextStream &ts, TemplateContext *c) { + TRACE(("{TemplateNodeVariable::render\n")); TemplateContextImpl* ci = dynamic_cast<TemplateContextImpl*>(c); if (ci==0) return; // should not happen ci->setLocation(m_templateName,m_line); @@ -2883,7 +2997,7 @@ class TemplateNodeVariable : public TemplateNode TemplateVariant v = m_var->resolve(c); if (v.isFunction()) { - v = v.call(std::vector<TemplateVariant>()); + v = v.call(); } if (ci->escapeIntf() && !v.raw()) { @@ -2908,12 +3022,13 @@ class TemplateNodeVariable : public TemplateNode } } } + TRACE(("}TemplateNodeVariable::render\n")); } private: QCString m_templateName; int m_line = 0; - ExprAst *m_var = 0; + ExprAstPtr m_var; }; //---------------------------------------------------------- @@ -2926,12 +3041,12 @@ template<class T> class TemplateNodeCreator : public TemplateNode public: TemplateNodeCreator(TemplateParser *parser,TemplateNode *parent,int line) : TemplateNode(parent), m_templateName(parser->templateName()), m_line(line) {} - static TemplateNode *createInstance(TemplateParser *parser, + static TemplateNodePtr createInstance(TemplateParser *parser, TemplateNode *parent, int line, const QCString &data) { - return new T(parser,parent,line,data); + return std::make_unique<T>(parser,parent,line,data); } TemplateImpl *getTemplate() { @@ -2943,7 +3058,7 @@ template<class T> class TemplateNodeCreator : public TemplateNode return dynamic_cast<TemplateImpl*>(root); } protected: - void mkpath(TemplateContextImpl *ci,const std::string &fileName) + void mkpath(const TemplateContextImpl *ci,const std::string &fileName) { size_t i=fileName.find('/'); std::string outputDir = ci->outputDirectory().str(); @@ -3068,10 +3183,8 @@ class TemplateNodeIf : public TemplateNodeCreator<TemplateNodeIf> private: struct GuardedNodes { - GuardedNodes() : guardAst(0) {} - ~GuardedNodes() { delete guardAst; } int line = 0; - ExprAst *guardAst = 0; + ExprAstPtr guardAst; TemplateNodeList trueNodes; }; std::vector< std::unique_ptr<GuardedNodes> > m_ifGuardedNodes; @@ -3094,10 +3207,6 @@ class TemplateNodeRepeat : public TemplateNodeCreator<TemplateNodeRepeat> parser->removeNextToken(); // skip over endrepeat TRACE(("}TemplateNodeRepeat(%s)\n",qPrint(data))); } - ~TemplateNodeRepeat() - { - delete m_expr; - } void render(TextStream &ts, TemplateContext *c) { TemplateContextImpl* ci = dynamic_cast<TemplateContextImpl*>(c); @@ -3109,14 +3218,14 @@ class TemplateNodeRepeat : public TemplateNodeCreator<TemplateNodeRepeat> int i, n = v.toInt(); for (i=0;i<n;i++) { - TemplateAutoRef<TemplateStruct> s(TemplateStruct::alloc()); + TemplateStructPtr s = TemplateStruct::alloc(); s->set("counter0", (int)i); s->set("counter", (int)(i+1)); s->set("revcounter", (int)(n-i)); s->set("revcounter0", (int)(n-i-1)); s->set("first",i==0); s->set("last", i==n-1); - c->set("repeatloop",s.get()); + c->set("repeatloop",std::static_pointer_cast<TemplateStructIntf>(s)); // render all items for this iteration of the loop m_repeatNodes.render(ts,c); } @@ -3128,7 +3237,7 @@ class TemplateNodeRepeat : public TemplateNodeCreator<TemplateNodeRepeat> } private: TemplateNodeList m_repeatNodes; - ExprAst *m_expr = 0; + ExprAstPtr m_expr; }; //---------------------------------------------------------- @@ -3147,7 +3256,7 @@ class TemplateNodeRange : public TemplateNodeCreator<TemplateNodeRange> int i3 = data.find(" downto "); if (i1==-1) { - if (data.right(5)==" from") + if (data.endsWith(" from")) { parser->warn(m_templateName,line,"range missing after 'from' keyword"); } @@ -3162,11 +3271,11 @@ class TemplateNodeRange : public TemplateNodeCreator<TemplateNodeRange> } else if (i2==-1 && i3==-1) { - if (data.right(3)==" to") + if (data.endsWith(" to")) { parser->warn(m_templateName,line,"range is missing end value after 'to' keyword"); } - else if (data.right(7)==" downto") + else if (data.endsWith(" downto")) { parser->warn(m_templateName,line,"range is missing end value after 'downto' keyword"); } @@ -3204,12 +3313,6 @@ class TemplateNodeRange : public TemplateNodeCreator<TemplateNodeRange> TRACE(("}TemplateNodeRange(%s)\n",qPrint(data))); } - ~TemplateNodeRange() - { - delete m_startExpr; - delete m_endExpr; - } - void render(TextStream &ts, TemplateContext *c) { TemplateContextImpl* ci = dynamic_cast<TemplateContextImpl*>(c); @@ -3237,7 +3340,7 @@ class TemplateNodeRange : public TemplateNodeCreator<TemplateNodeRange> while (!done) { // set the forloop meta-data variable - TemplateAutoRef<TemplateStruct> ls(TemplateStruct::alloc()); + TemplateStructPtr ls = TemplateStruct::alloc(); ls->set("counter0", (int)index); ls->set("counter", (int)(index+1)); ls->set("revcounter", (int)(l-index)); @@ -3245,7 +3348,7 @@ class TemplateNodeRange : public TemplateNodeCreator<TemplateNodeRange> ls->set("first",index==0); ls->set("last", (int)index==l-1); ls->set("parentloop",parentLoop ? *parentLoop : TemplateVariant()); - c->set("forloop",ls.get()); + c->set("forloop",std::static_pointer_cast<TemplateStructIntf>(ls)); // set the iterator variable c->set(m_var,i); @@ -3294,8 +3397,8 @@ class TemplateNodeRange : public TemplateNodeCreator<TemplateNodeRange> private: bool m_down = false; - ExprAst *m_startExpr = 0; - ExprAst *m_endExpr = 0; + ExprAstPtr m_startExpr; + ExprAstPtr m_endExpr; QCString m_var; TemplateNodeList m_loopNodes; }; @@ -3314,7 +3417,7 @@ class TemplateNodeFor : public TemplateNodeCreator<TemplateNodeFor> int i = data.find(" in "); if (i==-1) { - if (data.right(3)==" in") + if (data.endsWith(" in")) { parser->warn(m_templateName,line,"for is missing container after 'in' keyword"); } @@ -3363,11 +3466,6 @@ class TemplateNodeFor : public TemplateNodeCreator<TemplateNodeFor> TRACE(("}TemplateNodeFor(%s)\n",qPrint(data))); } - ~TemplateNodeFor() - { - delete m_expr; - } - void render(TextStream &ts, TemplateContext *c) { TemplateContextImpl* ci = dynamic_cast<TemplateContextImpl*>(c); @@ -3380,9 +3478,9 @@ class TemplateNodeFor : public TemplateNodeCreator<TemplateNodeFor> TemplateVariant v = m_expr->resolve(c); if (v.isFunction()) { - v = v.call(std::vector<TemplateVariant>()); + v = v.call(); } - const TemplateListIntf *list = v.toList(); + const TemplateListIntfPtr list = v.toList(); if (list) { uint listSize = list->count(); @@ -3396,13 +3494,13 @@ class TemplateNodeFor : public TemplateNodeCreator<TemplateNodeFor> //TemplateVariant v; const TemplateVariant *parentLoop = c->getRef("forloop"); uint index = m_reversed ? listSize-1 : 0; - TemplateListIntf::ConstIterator *it = list->createIterator(); + TemplateListIntf::ConstIteratorPtr it = list->createIterator(); TemplateVariant ve; for (m_reversed ? it->toLast() : it->toFirst(); (it->current(ve)); m_reversed ? it->toPrev() : it->toNext()) { - TemplateAutoRef<TemplateStruct> s(TemplateStruct::alloc()); + TemplateStructPtr s = TemplateStruct::alloc(); s->set("counter0", (int)index); s->set("counter", (int)(index+1)); s->set("revcounter", (int)(listSize-index)); @@ -3410,7 +3508,7 @@ class TemplateNodeFor : public TemplateNodeCreator<TemplateNodeFor> s->set("first",index==0); s->set("last", index==listSize-1); s->set("parentloop",parentLoop ? *parentLoop : TemplateVariant()); - c->set("forloop",s.get()); + c->set("forloop",std::static_pointer_cast<TemplateStructIntf>(s)); // add variables for this loop to the context //obj->addVariableToContext(index,m_vars,c); @@ -3419,12 +3517,16 @@ class TemplateNodeFor : public TemplateNodeCreator<TemplateNodeFor> { c->set(m_vars[vi++],ve); } - else if (m_vars.size()>1 && ve.isStruct()) + else if (m_vars.size()>1 && (ve.isStruct() || ve.isWeakStruct())) // loop variables represent elements in a list item { - for (uint i=0;i<m_vars.size();i++,vi++) + TemplateStructIntfPtr vs = ve.toStruct(); + if (vs) { - c->set(m_vars[vi],ve.toStruct()->get(m_vars[vi])); + for (uint i=0;i<m_vars.size();i++,vi++) + { + c->set(m_vars[vi],vs->get(m_vars[vi])); + } } } for (;vi<m_vars.size();vi++) @@ -3438,7 +3540,6 @@ class TemplateNodeFor : public TemplateNodeCreator<TemplateNodeFor> if (m_reversed) index--; else index++; } c->pop(); - delete it; } else // simple type... { @@ -3449,7 +3550,7 @@ class TemplateNodeFor : public TemplateNodeCreator<TemplateNodeFor> private: bool m_reversed = false; - ExprAst *m_expr = 0; + ExprAstPtr m_expr; std::vector<QCString> m_vars; TemplateNodeList m_loopNodes; TemplateNodeList m_emptyNodes; @@ -3472,6 +3573,7 @@ class TemplateNodeMsg : public TemplateNodeCreator<TemplateNodeMsg> } void render(TextStream &, TemplateContext *c) { + TRACE(("{TemplateNodeMsg::render\n")); TemplateContextImpl* ci = dynamic_cast<TemplateContextImpl*>(c); if (ci==0) return; // should not happen ci->setLocation(m_templateName,m_line); @@ -3485,6 +3587,7 @@ class TemplateNodeMsg : public TemplateNodeCreator<TemplateNodeMsg> std::cout << "\n"; ci->setActiveEscapeIntf(escIntf); ci->enableSpaceless(enable); + TRACE(("}TemplateNodeMsg::render\n")); } private: TemplateNodeList m_nodes; @@ -3538,9 +3641,9 @@ class TemplateNodeBlock : public TemplateNodeCreator<TemplateNodeBlock> } QCString super = ss.str(); // add 'block.super' variable to allow access to parent block content - TemplateAutoRef<TemplateStruct> superBlock(TemplateStruct::alloc()); + TemplateStructPtr superBlock = TemplateStruct::alloc(); superBlock->set("super",TemplateVariant(super.data(),TRUE)); - ci->set("block",superBlock.get()); + ci->set("block",std::static_pointer_cast<TemplateStructIntf>(superBlock)); // render the overruled block contents t->engine()->enterBlock(nb->m_templateName,nb->m_blockName,nb->m_line); nb->m_nodes.render(ts,c); @@ -3588,10 +3691,6 @@ class TemplateNodeExtend : public TemplateNodeCreator<TemplateNodeExtend> parser->parse(this,line,stopAt,m_nodes); TRACE(("}TemplateNodeExtend(%s)\n",qPrint(data))); } - ~TemplateNodeExtend() - { - delete m_extendExpr; - } void render(TextStream &ts, TemplateContext *c) { @@ -3637,17 +3736,17 @@ class TemplateNodeExtend : public TemplateNodeCreator<TemplateNodeExtend> // clean up bc->clear(); - t->engine()->unload(t); } else { ci->warn(m_templateName,m_line,"failed to load template %s for extend",qPrint(extendFile)); } + t->engine()->unload(bt); } } private: - ExprAst *m_extendExpr = 0; + ExprAstPtr m_extendExpr; TemplateNodeList m_nodes; }; @@ -3666,10 +3765,6 @@ class TemplateNodeInclude : public TemplateNodeCreator<TemplateNodeInclude> } m_includeExpr = ep.parse(data); } - ~TemplateNodeInclude() - { - delete m_includeExpr; - } void render(TextStream &ts, TemplateContext *c) { TemplateContextImpl* ci = dynamic_cast<TemplateContextImpl*>(c); @@ -3692,35 +3787,36 @@ class TemplateNodeInclude : public TemplateNodeCreator<TemplateNodeInclude> if (incTemplate) { incTemplate->render(ts,c); - t->engine()->unload(t); } else { ci->warn(m_templateName,m_line,"failed to load template '%s' for include",qPrint(includeFile)); } + t->engine()->unload(it); } } } } private: - ExprAst *m_includeExpr = 0; + ExprAstPtr m_includeExpr; }; //---------------------------------------------------------- static void stripLeadingWhiteSpace(QCString &s) { - uint i=0, dstIdx=0, l=s.length(); bool skipSpaces=true; - while (i<l) + const char *src = s.data(); + char *dst = s.rawData(); + char c; + while ((c=*src++)) { - char c = s[i++]; - if (c=='\n') { s[dstIdx++]=c; skipSpaces=true; } + if (c=='\n') { *dst++=c; skipSpaces=true; } else if (c==' ' && skipSpaces) {} - else { s[dstIdx++] = c; skipSpaces=false; } + else { *dst++ = c; skipSpaces=false; } } - s.resize(dstIdx+1); + s.resize(dst-s.data()+1); } /** @brief Class representing an 'create' tag in a template */ @@ -3728,7 +3824,7 @@ class TemplateNodeCreate : public TemplateNodeCreator<TemplateNodeCreate> { public: TemplateNodeCreate(TemplateParser *parser,TemplateNode *parent,int line,const QCString &data) - : TemplateNodeCreator<TemplateNodeCreate>(parser,parent,line), m_templateExpr(0), m_fileExpr(0) + : TemplateNodeCreator<TemplateNodeCreate>(parser,parent,line) { TRACE(("TemplateNodeCreate(%s)\n",qPrint(data))); if (data.isEmpty()) @@ -3738,7 +3834,7 @@ class TemplateNodeCreate : public TemplateNodeCreator<TemplateNodeCreate> int i = data.find(" from "); if (i==-1) { - if (data.right(3)==" from") + if (data.endsWith(" from")) { parser->warn(m_templateName,line,"create is missing template name after 'from' keyword"); } @@ -3758,13 +3854,9 @@ class TemplateNodeCreate : public TemplateNodeCreator<TemplateNodeCreate> m_templateExpr = ep.parse(data.mid(i+6).stripWhiteSpace()); } } - ~TemplateNodeCreate() - { - delete m_templateExpr; - delete m_fileExpr; - } void render(TextStream &, TemplateContext *c) { + TRACE(("{TemplateNodeCreate::render\n")); TemplateContextImpl* ci = dynamic_cast<TemplateContextImpl*>(c); if (ci==0) return; // should not happen ci->setLocation(m_templateName,m_line); @@ -3829,11 +3921,12 @@ class TemplateNodeCreate : public TemplateNodeCreator<TemplateNodeCreate> } } } + TRACE(("}TemplateNodeCreate::render\n")); } private: - ExprAst *m_templateExpr = 0; - ExprAst *m_fileExpr = 0; + ExprAstPtr m_templateExpr; + ExprAstPtr m_fileExpr; }; //---------------------------------------------------------- @@ -3843,10 +3936,10 @@ class TemplateNodeTree : public TemplateNodeCreator<TemplateNodeTree> { struct TreeContext { - TreeContext(TemplateNodeTree *o,const TemplateListIntf *l,TemplateContext *c) + TreeContext(TemplateNodeTree *o,const TemplateListIntfPtr l,TemplateContext *c) : object(o), list(l), templateCtx(c) {} TemplateNodeTree *object; - const TemplateListIntf *list; + const TemplateListIntfPtr list; TemplateContext *templateCtx; }; public: @@ -3865,15 +3958,6 @@ class TemplateNodeTree : public TemplateNodeCreator<TemplateNodeTree> parser->removeNextToken(); // skip over endrecursetree TRACE(("}TemplateNodeTree(%s)\n",qPrint(data))); } - ~TemplateNodeTree() - { - delete m_treeExpr; - } - static TemplateVariant renderChildrenStub(const void *ctx, const std::vector<TemplateVariant> &) - { - return TemplateVariant(((TreeContext*)ctx)->object-> - renderChildren((const TreeContext*)ctx),TRUE); - } QCString renderChildren(const TreeContext *ctx) { //printf("TemplateNodeTree::renderChildren(%d)\n",ctx->list->count()); @@ -3884,22 +3968,25 @@ class TemplateNodeTree : public TemplateNodeCreator<TemplateNodeTree> TextStream ss; c->push(); TemplateVariant node; - TemplateListIntf::ConstIterator *it = ctx->list->createIterator(); + TemplateListIntf::ConstIteratorPtr it = ctx->list->createIterator(); for (it->toFirst();(it->current(node));it->toNext()) { c->set("node",node); bool hasChildren=FALSE; - const TemplateStructIntf *ns = node.toStruct(); + const TemplateStructIntfPtr ns = node.toStruct(); if (ns) // node is a struct { TemplateVariant v = ns->get("children"); if (v.isValid()) // with a field 'children' { - const TemplateListIntf *list = v.toList(); + const TemplateListIntfPtr list = v.toList(); if (list && list->count()>0) // non-empty list { TreeContext childCtx(this,list,ctx->templateCtx); - TemplateVariant children(TemplateVariant::FunctionDelegate::fromFunction(&childCtx,renderChildrenStub)); + TemplateVariant children( + [childCtx](const TemplateVariantList &) { + return TemplateVariant(childCtx.object->renderChildren(&childCtx),TRUE); + }); children.setRaw(TRUE); c->set("children",children); m_treeNodes.render(ss,c); @@ -3922,7 +4009,6 @@ class TemplateNodeTree : public TemplateNodeCreator<TemplateNodeTree> } } c->pop(); - delete it; return ss.str(); } void render(TextStream &ts, TemplateContext *c) @@ -3932,7 +4018,7 @@ class TemplateNodeTree : public TemplateNodeCreator<TemplateNodeTree> if (ci==0) return; // should not happen ci->setLocation(m_templateName,m_line); TemplateVariant v = m_treeExpr->resolve(c); - const TemplateListIntf *list = v.toList(); + const TemplateListIntfPtr list = v.toList(); if (list) { TreeContext ctx(this,list,c); @@ -3945,7 +4031,7 @@ class TemplateNodeTree : public TemplateNodeCreator<TemplateNodeTree> } private: - ExprAst *m_treeExpr = 0; + ExprAstPtr m_treeExpr; TemplateNodeList m_treeNodes; }; @@ -3958,7 +4044,7 @@ class TemplateNodeIndexEntry : public TemplateNodeCreator<TemplateNodeIndexEntry { Mapping(const QCString &n,std::unique_ptr<ExprAst> &&e) : name(n), value(std::move(e)) {} QCString name; - std::unique_ptr<ExprAst> value = 0; + ExprAstPtr value; }; public: TemplateNodeIndexEntry(TemplateParser *parser,TemplateNode *parent,int line,const QCString &data) @@ -3982,10 +4068,10 @@ class TemplateNodeIndexEntry : public TemplateNodeCreator<TemplateNodeIndexEntry int j=arg.find('='); if (j>0) { - ExprAst *expr = expParser.parse(arg.mid(j+1)); + ExprAstPtr expr = expParser.parse(arg.mid(j+1)); if (expr) { - m_args.emplace_back(arg.left(j),std::unique_ptr<ExprAst>(expr)); + m_args.emplace_back(arg.left(j),std::move(expr)); } } else @@ -4097,9 +4183,9 @@ class TemplateNodeWith : public TemplateNodeCreator<TemplateNodeWith> { struct Mapping { - Mapping(const QCString &n,std::unique_ptr<ExprAst> &&e) : name(n), value(std::move(e)) {} + Mapping(const QCString &n,ExprAstPtr &&e) : name(n), value(std::move(e)) {} QCString name; - std::unique_ptr<ExprAst> value; + ExprAstPtr value; }; public: TemplateNodeWith(TemplateParser *parser,TemplateNode *parent,int line,const QCString &data) @@ -4117,10 +4203,10 @@ class TemplateNodeWith : public TemplateNodeCreator<TemplateNodeWith> int j=arg.find('='); if (j>0) { - ExprAst *expr = expParser.parse(arg.mid(j+1)); + ExprAstPtr expr = expParser.parse(arg.mid(j+1)); if (expr) { - m_args.emplace_back(arg.left(j),std::unique_ptr<ExprAst>(expr)); + m_args.emplace_back(arg.left(j),std::move(expr)); } } else @@ -4172,10 +4258,10 @@ class TemplateNodeCycle : public TemplateNodeCreator<TemplateNodeCycle> auto it = args.begin(); while (it!=args.end()) { - ExprAst *expr = expParser.parse(*it); + ExprAstPtr expr = expParser.parse(*it); if (expr) { - m_args.push_back(std::unique_ptr<ExprAst>(expr)); + m_args.emplace_back(std::move(expr)); } ++it; } @@ -4195,7 +4281,7 @@ class TemplateNodeCycle : public TemplateNodeCreator<TemplateNodeCycle> TemplateVariant v = m_args[m_index]->resolve(c); if (v.isFunction()) { - v = v.call(std::vector<TemplateVariant>()); + v = v.call(); } if (ci->escapeIntf() && !v.raw()) { @@ -4237,10 +4323,9 @@ class TemplateNodeSet : public TemplateNodeCreator<TemplateNodeSet> { struct Mapping { - Mapping(const QCString &n,ExprAst *e) : name(n), value(e) {} - ~Mapping() { delete value; } + Mapping(const QCString &n,ExprAstPtr &&e) : name(n), value(std::move(e)) {} QCString name; - ExprAst *value = 0; + ExprAstPtr value; }; public: TemplateNodeSet(TemplateParser *parser,TemplateNode *parent,int line,const QCString &data) @@ -4250,10 +4335,10 @@ class TemplateNodeSet : public TemplateNodeCreator<TemplateNodeSet> ExpressionParser expParser(parser,line); // data format: name=expression int j=data.find('='); - ExprAst *expr = 0; + ExprAstPtr expr = 0; if (j>0 && (expr = expParser.parse(data.mid(j+1)))) { - m_mapping = std::make_unique<Mapping>(data.left(j),expr); + m_mapping = std::make_unique<Mapping>(data.left(j),std::move(expr)); } TRACE(("}TemplateNodeSet(%s)\n",qPrint(data))); } @@ -4311,7 +4396,7 @@ class TemplateNodeMarkers : public TemplateNodeCreator<TemplateNodeMarkers> { public: TemplateNodeMarkers(TemplateParser *parser,TemplateNode *parent,int line,const QCString &data) - : TemplateNodeCreator<TemplateNodeMarkers>(parser,parent,line), m_listExpr(0), m_patternExpr(0) + : TemplateNodeCreator<TemplateNodeMarkers>(parser,parent,line) { TRACE(("{TemplateNodeMarkers(%s)\n",qPrint(data))); int i = data.find(" in "); @@ -4332,11 +4417,6 @@ class TemplateNodeMarkers : public TemplateNodeCreator<TemplateNodeMarkers> parser->removeNextToken(); // skip over endmarkers TRACE(("}TemplateNodeMarkers(%s)\n",qPrint(data))); } - ~TemplateNodeMarkers() - { - delete m_listExpr; - delete m_patternExpr; - } void render(TextStream &ts, TemplateContext *c) { TemplateContextImpl *ci = dynamic_cast<TemplateContextImpl*>(c); @@ -4345,13 +4425,13 @@ class TemplateNodeMarkers : public TemplateNodeCreator<TemplateNodeMarkers> if (!m_var.isEmpty() && m_listExpr && m_patternExpr) { TemplateVariant v = m_listExpr->resolve(c); - const TemplateListIntf *list = v.toList(); + const TemplateListIntfPtr list = v.toList(); TemplateVariant patternStr = m_patternExpr->resolve(c); if (list) { if (patternStr.isString()) { - TemplateListIntf::ConstIterator *it = list->createIterator(); + TemplateListIntf::ConstIteratorPtr it = list->createIterator(); c->push(); std::string str = patternStr.toString().str(); @@ -4380,9 +4460,9 @@ class TemplateNodeMarkers : public TemplateNodeCreator<TemplateNodeMarkers> for (it->toFirst(); (it->current(var)) && i<entryIndex; it->toNext(),i++) {} if (i==entryIndex) // found element { - TemplateAutoRef<TemplateStruct> s(TemplateStruct::alloc()); + TemplateStructPtr s = TemplateStruct::alloc(); s->set("id",(int)i); - c->set("markers",s.get()); + c->set("markers",std::static_pointer_cast<TemplateStructIntf>(s)); c->set(m_var,var); // define local variable to hold element of list type bool wasSpaceless = ci->spacelessEnabled(); ci->enableSpaceless(TRUE); @@ -4404,7 +4484,6 @@ class TemplateNodeMarkers : public TemplateNodeCreator<TemplateNodeMarkers> ts << str.substr(index); // write text after last marker } c->pop(); - delete it; } else { @@ -4420,8 +4499,8 @@ class TemplateNodeMarkers : public TemplateNodeCreator<TemplateNodeMarkers> private: TemplateNodeList m_nodes; QCString m_var; - ExprAst *m_listExpr = 0; - ExprAst *m_patternExpr = 0; + ExprAstPtr m_listExpr; + ExprAstPtr m_patternExpr; }; //---------------------------------------------------------- @@ -4468,8 +4547,8 @@ class TemplateNodeResource : public TemplateNodeCreator<TemplateNodeResource> if (data.isEmpty()) { parser->warn(m_templateName,line,"resource tag is missing resource file argument"); - m_resExpr=0; - m_asExpr=0; + m_resExpr.reset(); + m_asExpr.reset(); } else if ((i=data.find(" as "))!=-1) // resource a as b { @@ -4485,15 +4564,10 @@ class TemplateNodeResource : public TemplateNodeCreator<TemplateNodeResource> else // resource a { m_resExpr = ep.parse(data); - m_asExpr = 0; + m_asExpr.reset(); } TRACE(("}TemplateNodeResource(%s)\n",qPrint(data))); } - ~TemplateNodeResource() - { - delete m_resExpr; - delete m_asExpr; - } void render(TextStream &, TemplateContext *c) { TemplateContextImpl *ci = dynamic_cast<TemplateContextImpl*>(c); @@ -4530,8 +4604,8 @@ class TemplateNodeResource : public TemplateNodeCreator<TemplateNodeResource> } } private: - ExprAst *m_resExpr = 0; - ExprAst *m_asExpr = 0; + ExprAstPtr m_resExpr; + ExprAstPtr m_asExpr; bool m_append = false; }; @@ -4549,7 +4623,7 @@ class TemplateNodeEncoding : public TemplateNodeCreator<TemplateNodeEncoding> if (data.isEmpty()) { parser->warn(m_templateName,line,"encoding tag is missing encoding argument"); - m_encExpr = 0; + m_encExpr.reset(); } else { @@ -4560,10 +4634,6 @@ class TemplateNodeEncoding : public TemplateNodeCreator<TemplateNodeEncoding> parser->removeNextToken(); // skip over endencoding TRACE(("}TemplateNodeEncoding(%s)\n",qPrint(data))); } - ~TemplateNodeEncoding() - { - delete m_encExpr; - } void render(TextStream &ts, TemplateContext *c) { TemplateContextImpl *ci = dynamic_cast<TemplateContextImpl*>(c); @@ -4583,7 +4653,7 @@ class TemplateNodeEncoding : public TemplateNodeCreator<TemplateNodeEncoding> ci->setEncoding(m_templateName,m_line,oldEncStr); } private: - ExprAst *m_encExpr; + ExprAstPtr m_encExpr; TemplateNodeList m_nodes; }; @@ -4593,19 +4663,19 @@ class TemplateNodeEncoding : public TemplateNodeCreator<TemplateNodeEncoding> class TemplateNodeFactory { public: - typedef TemplateNode *(*CreateFunc)(TemplateParser *parser, + typedef TemplateNodePtr (*CreateFunc)(TemplateParser *parser, TemplateNode *parent, int line, const QCString &data); - static TemplateNodeFactory *instance() + static TemplateNodeFactory &instance() { - static TemplateNodeFactory *instance = 0; - if (instance==0) instance = new TemplateNodeFactory; - return instance; + static std::unique_ptr<TemplateNodeFactory> instance; + if (instance==0) instance = std::make_unique<TemplateNodeFactory>(); + return *instance; } - TemplateNode *create(const QCString &name, + TemplateNodePtr create(const QCString &name, TemplateParser *parser, TemplateNode *parent, int line, @@ -4627,7 +4697,7 @@ class TemplateNodeFactory public: AutoRegister<T>(const QCString &key) { - TemplateNodeFactory::instance()->registerTemplateNode(key,T::createInstance); + TemplateNodeFactory::instance().registerTemplateNode(key,T::createInstance); } }; @@ -5023,8 +5093,8 @@ void TemplateParser::parse( { arg = tok_ptr->data.mid(sep+1); } - std::unique_ptr<TemplateNode> node { TemplateNodeFactory::instance()-> - create(command,this,parent,tok_ptr->line,arg) }; + TemplateNodePtr node = TemplateNodeFactory::instance().create( + command,this,parent,tok_ptr->line,arg); if (node) { nodes.push_back(std::move(node)); @@ -5108,6 +5178,7 @@ TemplateImpl::TemplateImpl(TemplateEngine *engine,const QCString &name,const QCS const QCString &extension) : TemplateNode(0) { + //printf("%p:TemplateImpl::TemplateImpl(%s)\n",(void*)this,qPrint(name)); m_name = name; m_engine = engine; TemplateLexer lexer(engine,name,data); @@ -5123,7 +5194,7 @@ TemplateImpl::TemplateImpl(TemplateEngine *engine,const QCString &name,const QCS TemplateImpl::~TemplateImpl() { - //printf("deleting template %s\n",qPrint(m_name)); + //printf("%p:TemplateImpl::~TemplateImpl(%s)\n",(void*)this,qPrint(m_name)); } void TemplateImpl::render(TextStream &ts, TemplateContext *c) @@ -5174,6 +5245,11 @@ class TemplateEngine::Private public: Private(TemplateEngine *engine) : m_engine(engine) { + //printf("%p:TemplateEngine::Private::Private()\n",(void*)this); + } + ~Private() + { + //printf("%p:TemplateEngine::Private::~Private()\n",(void*)this); } Template *loadByName(const QCString &fileName,int line) { @@ -5289,24 +5365,17 @@ class TemplateEngine::Private QCString m_templateDirName; }; -TemplateEngine::TemplateEngine() +TemplateEngine::TemplateEngine() : p(std::make_unique<Private>(this)) { - p = new Private(this); } TemplateEngine::~TemplateEngine() { - delete p; -} - -TemplateContext *TemplateEngine::createContext() const -{ - return new TemplateContextImpl(this); } -void TemplateEngine::destroyContext(TemplateContext *ctx) +std::unique_ptr<TemplateContext> TemplateEngine::createContext() const { - delete ctx; + return std::make_unique<TemplateContextImpl>(this); } Template *TemplateEngine::loadByName(const QCString &fileName,int line) @@ -5354,19 +5423,18 @@ void TemplateEngine::setTemplateDir(const QCString &dirName) QCString TemplateVariant::listToString() const { QCString result="["; - const TemplateListIntf *list = toList(); + const TemplateListIntfPtr list = toList(); if (list) { bool first=true; TemplateVariant ve; - TemplateListIntf::ConstIterator *it = list->createIterator(); + TemplateListIntf::ConstIteratorPtr it = list->createIterator(); for (it->toFirst();it->current(ve);it->toNext()) { if (!first) result+=",\n"; result+="'"+ve.toString()+"'"; first=false; } - delete it; } result+="]"; return result; @@ -5375,7 +5443,7 @@ QCString TemplateVariant::listToString() const QCString TemplateVariant::structToString() const { QCString result="{"; - const TemplateStructIntf *strukt = toStruct(); + const TemplateStructIntfPtr strukt = toStruct(); if (strukt) { bool first=true; @@ -5383,7 +5451,7 @@ QCString TemplateVariant::structToString() const { if (!first) result+=","; result+=s; - if (dynamic_cast<const TemplateStructWeakRef*>(strukt)==0) // avoid endless recursion + if (!isWeakStruct()) // avoid endless recursion { result+=":'"; result+=strukt->get(QCString(s)).toString(); diff --git a/src/template.h b/src/template.h index ba421b4..4c9f89b 100644 --- a/src/template.h +++ b/src/template.h @@ -17,6 +17,8 @@ #define TEMPLATE_H #include <vector> +#include <memory> +#include <functional> #include "qcstring.h" #include "containers.h" @@ -27,6 +29,10 @@ class TemplateStructIntf; class TemplateEngine; class TextStream; +using TemplateListIntfPtr = std::shared_ptr<TemplateListIntf>; +using TemplateStructIntfPtr = std::shared_ptr<TemplateStructIntf>; +using TemplateStructIntfWeakPtr = std::weak_ptr<TemplateStructIntf>; + /** @defgroup template_api Template API * * This is the API for a @@ -92,78 +98,63 @@ class TextStream; class TemplateVariant { public: - /** @brief Helper class to create a delegate that can store a function/method call. */ - class FunctionDelegate + /** Type representing a function call in a template */ + using FunctionDelegate = std::function<TemplateVariant(const std::vector<TemplateVariant>&)>; + + /** Symbolic names for the possible types that this variant can hold. */ + using VariantT = Variant<bool, // index==0: Type::Bool + int, // index==1: Type::Int + QCString, // index==2: Type::String + TemplateStructIntfPtr, // index==3: Type::Struct + TemplateListIntfPtr, // index==4: Type::List + FunctionDelegate, // index==5: Type::Function + TemplateStructIntfWeakPtr // index==6: Type::WeakStruct + >; + + enum class Type : uint8_t { - public: - /** Callback type to use when creating a delegate from a function. */ - typedef TemplateVariant (*StubType)(const void *obj, const std::vector<TemplateVariant> &args); - - FunctionDelegate() : m_objectPtr(0) , m_stubPtr(0) {} - - /** Creates a delegate given an object. The method to call is passed as a template parameter */ - template <class T, TemplateVariant (T::*TMethod)(const std::vector<TemplateVariant> &) const> - static FunctionDelegate fromMethod(const T* objectPtr) - { - FunctionDelegate d; - d.m_objectPtr = objectPtr; - d.m_stubPtr = &methodStub<T, TMethod>; - return d; - } - /** Creates a delegate given an object, and a plain function. */ - static FunctionDelegate fromFunction(const void *obj,StubType func) - { - FunctionDelegate d; - d.m_objectPtr = obj; - d.m_stubPtr = func; - return d; - } - - /** Invokes the function/method stored in the delegate */ - TemplateVariant operator()(const std::vector<TemplateVariant> &args) const - { - return (*m_stubPtr)(m_objectPtr, args); - } - - private: - const void* m_objectPtr; - StubType m_stubPtr; - - template <class T, TemplateVariant (T::*TMethod)(const std::vector<TemplateVariant> &) const> - static TemplateVariant methodStub(const void* objectPtr, const std::vector<TemplateVariant> &args) - { - T* p = (T*)(objectPtr); - return (p->*TMethod)(args); - } + Bool = 0, + Int = 1, + String = 2, + Struct = 3, + List = 4, + Function = 5, + WeakStruct = 6, + None = 255 }; /** Constructs an invalid variant. */ TemplateVariant() {} /** Constructs a new variant with a boolean value \a b. */ - explicit TemplateVariant(bool b) { m_variant.set<bool>(b); } + explicit TemplateVariant(bool b) { m_variant.set<static_cast<uint8_t>(Type::Bool)>(b); } /** Constructs a new variant with a integer value \a v. */ - TemplateVariant(int v) { m_variant.set<int>(v); } + TemplateVariant(int v) { m_variant.set<static_cast<uint8_t>(Type::Int)>(v); } /** Constructs a new variant with a string value \a s. */ - TemplateVariant(const char *s,bool raw=FALSE) : m_raw(raw) { m_variant.set<QCString>(s); } + TemplateVariant(const char *s,bool raw=FALSE) : m_raw(raw) { m_variant.set<static_cast<uint8_t>(Type::String)>(s); } /** Constructs a new variant with a string value \a s. */ - TemplateVariant(const QCString &s,bool raw=FALSE) : m_raw(raw) { m_variant.set<QCString>(s); } + TemplateVariant(const QCString &s,bool raw=FALSE) : m_raw(raw) { m_variant.set<static_cast<uint8_t>(Type::String)>(s.str()); } /** Constructs a new variant with a string value \a s. */ - TemplateVariant(const std::string &s,bool raw=FALSE) : m_raw(raw) { m_variant.set<QCString>(s); } + TemplateVariant(const std::string &s,bool raw=FALSE) : m_raw(raw) { m_variant.set<static_cast<uint8_t>(Type::String)>(s); } /** Constructs a new variant with a struct value \a s. - * @note. The variant will hold a reference to the object. + * @note. The variant will hold a counting reference to the object. */ - TemplateVariant(TemplateStructIntf *s); + TemplateVariant(TemplateStructIntfPtr s) { m_variant.set<static_cast<uint8_t>(Type::Struct)>(s); } /** Constructs a new variant with a list value \a l. - * @note. The variant will hold a reference to the object. + * @note. The variant will hold a counting reference to the object. */ - TemplateVariant(TemplateListIntf *l); + TemplateVariant(TemplateListIntfPtr l) { m_variant.set<static_cast<uint8_t>(Type::List)>(l); } + + /** Constructs a new variant with a struct value \a s. + * @note. The variant will hold a non-counting reference to the object. + */ + TemplateVariant(TemplateStructIntfWeakPtr s) { m_variant.set<static_cast<uint8_t>(Type::WeakStruct)>(s); } /** Constructs a new variant which represents a method call * @param[in] delegate FunctionDelegate object to invoke when @@ -172,15 +163,15 @@ class TemplateVariant * TemplateVariant::FunctionDelegate::fromFunction() to create * FunctionDelegate objects. */ - TemplateVariant(const FunctionDelegate &delegate) { m_variant.set<FunctionDelegate>(delegate); } + TemplateVariant(FunctionDelegate delegate) { m_variant.set<static_cast<uint8_t>(Type::Function)>(delegate); } /** Destroys the Variant object */ - ~TemplateVariant(); + ~TemplateVariant() = default; /** Constructs a copy of the variant, \a v, * passed as the argument to this constructor. */ - TemplateVariant(const TemplateVariant &v); + TemplateVariant(const TemplateVariant &v) = default; /** Moves the contents of variant \a v into this variant. * variant \a v will become invalid @@ -188,7 +179,7 @@ class TemplateVariant TemplateVariant(TemplateVariant &&v); /** Assigns the value of the variant \a v to this variant. */ - TemplateVariant &operator=(const TemplateVariant &v); + TemplateVariant &operator=(const TemplateVariant &v) = default; /** Move the value of the variant \a v into this variant. * Variant \a v will become invalid */ @@ -197,33 +188,7 @@ class TemplateVariant /** Compares this QVariant with v and returns true if they are equal; * otherwise returns false. */ - bool operator==(TemplateVariant &other) - { - if (!m_variant.valid()) - { - return FALSE; - } - if (isBool() && other.isBool()) - { - return m_variant.get<bool>() == other.m_variant.get<bool>(); - } - else if (isInt() && other.isInt()) - { - return m_variant.get<int>() == other.m_variant.get<int>(); - } - else if (isList() && other.isList()) - { - return m_variant.get<TemplateListIntf*>() == other.m_variant.get<TemplateListIntf*>(); - } - else if (isStruct() && other.isStruct()) - { - return m_variant.get<TemplateStructIntf*>() == other.m_variant.get<TemplateStructIntf*>(); - } - return toString()==other.toString(); - } - - QCString listToString() const; - QCString structToString() const; + bool operator==(TemplateVariant &other) const; /** Returns the variant as a string. */ QCString toString() const; @@ -235,51 +200,38 @@ class TemplateVariant int toInt() const; /** Returns TRUE if the variant holds a valid value, or FALSE otherwise */ - constexpr bool isValid() const { return m_variant.valid(); } + constexpr bool isValid() const { return m_variant.valid(); } /** Returns TRUE if the variant holds a boolean value */ - constexpr bool isBool() const { return m_variant.is<bool>(); } + constexpr bool isBool() const { return m_variant.is<static_cast<uint8_t>(Type::Bool)>(); } /** Returns TRUE if the variant holds an integer value */ - constexpr bool isInt() const { return m_variant.is<int>(); } + constexpr bool isInt() const { return m_variant.is<static_cast<uint8_t>(Type::Int)>(); } /** Returns TRUE if the variant holds a string value */ - constexpr bool isString() const { return m_variant.is<QCString>(); } + constexpr bool isString() const { return m_variant.is<static_cast<uint8_t>(Type::String)>(); } /** Returns TRUE if the variant holds a struct value */ - constexpr bool isStruct() const { return m_variant.is<TemplateStructIntf*>(); } + constexpr bool isStruct() const { return m_variant.is<static_cast<uint8_t>(Type::Struct)>(); } /** Returns TRUE if the variant holds a list value */ - constexpr bool isList() const { return m_variant.is<TemplateListIntf*>(); } + constexpr bool isList() const { return m_variant.is<static_cast<uint8_t>(Type::List)>(); } /** Returns TRUE if the variant holds a function value */ - constexpr bool isFunction() const { return m_variant.is<FunctionDelegate>(); } + constexpr bool isFunction() const { return m_variant.is<static_cast<uint8_t>(Type::Function)>(); } + /** Returns TRUE if the variant holds a struct value */ + constexpr bool isWeakStruct() const { return m_variant.is<static_cast<uint8_t>(Type::WeakStruct)>(); } /** Returns the pointer to list referenced by this variant * or 0 if this variant does not have list type. */ - TemplateListIntf *toList() - { - return isList() ? m_variant.get<TemplateListIntf*>() : nullptr; - } - const TemplateListIntf *toList() const - { - return isList() ? m_variant.get<TemplateListIntf*>() : nullptr; - } + TemplateListIntfPtr toList(); + const TemplateListIntfPtr toList() const; /** Returns the pointer to struct referenced by this variant * or 0 if this variant does not have struct type. */ - TemplateStructIntf *toStruct() - { - return isStruct() ? m_variant.get<TemplateStructIntf*>() : nullptr; - } - const TemplateStructIntf *toStruct() const - { - return isStruct() ? m_variant.get<TemplateStructIntf*>() : nullptr; - } + TemplateStructIntfPtr toStruct(); + const TemplateStructIntfPtr toStruct() const; /** Return the result of apply this function with \a args. * Returns an empty string if the variant type is not a function. */ - TemplateVariant call(const std::vector<TemplateVariant> &args) - { - return isFunction() ? m_variant.get<FunctionDelegate>()(args) : TemplateVariant(); - } + TemplateVariant call(const std::vector<TemplateVariant> &args = std::vector<TemplateVariant>()); /** Sets whether or not the value of the Variant should be * escaped or written as-is (raw). @@ -292,69 +244,21 @@ class TemplateVariant */ constexpr bool raw() const { return m_raw; } - /** Symbolic names for the possible types that this variant can hold. */ - enum class Type : size_t - { - None = std::string::npos, - Bool = 0, - Int = 1, - String = 2, - Struct = 3, - List = 4, - Function = 5 - }; - /** Returns the type held by this variant */ constexpr Type type() const { return static_cast<Type>(m_variant.index()); } - /** Return a string representation of the type of the value stored in the variant */ - constexpr const char *typeAsString() const - { - switch (type()) - { - case Type::None: return "invalid"; - case Type::Bool: return "bool"; - case Type::Int: return "integer"; - case Type::String: return "string"; - case Type::Struct: return "struct"; - case Type::List: return "list"; - case Type::Function: return "function"; - } - return "invalid"; - } + /** Returns a string representation of this variant's type */ + const char *typeAsString() const; private: - using VariantT = Variant<bool, // index==0: Type::Bool - int, // index==1: Type::Int - QCString, // index==2: Type::String - TemplateStructIntf*, // index==3: Type::Struct - TemplateListIntf*, // index==4: Type::List - FunctionDelegate // index==5: Type::Function - >; + QCString listToString() const; + QCString structToString() const; + VariantT m_variant; bool m_raw = false; }; -//------------------------------------------------------------------------ - -template<class T> class TemplateAutoRef -{ - public: - TemplateAutoRef(T *obj) : m_obj(obj) - { - m_obj->addRef(); - } - ~TemplateAutoRef() - { - m_obj->release(); - } - T &operator*() const { return *m_obj; } - T *operator->() const { return m_obj; } - T *get() const { return m_obj; } - - private: - T *m_obj; -}; +using TemplateVariantList = std::vector<TemplateVariant>; //------------------------------------------------------------------------ @@ -385,6 +289,7 @@ class TemplateListIntf */ virtual bool current(TemplateVariant &v) const = 0; }; + using ConstIteratorPtr = std::unique_ptr<ConstIterator>; /** Destroys the list */ virtual ~TemplateListIntf() {} @@ -398,41 +303,32 @@ class TemplateListIntf /** Creates a new iterator for this list. * @note the user should call delete on the returned pointer. */ - virtual TemplateListIntf::ConstIterator *createIterator() const = 0; - - /** Increase object's reference count */ - virtual int addRef() = 0; + virtual TemplateListIntf::ConstIteratorPtr createIterator() const = 0; - /** Decreases object's reference count, destroy object if 0 */ - virtual int release() = 0; }; -/** @brief Default implementation of a context value of type list. */ -class TemplateList : public TemplateListIntf +/** @brief Default implementation of a immutable context value of type list. */ +class TemplateImmutableList : public TemplateListIntf { public: // TemplateListIntf methods virtual uint count() const; virtual TemplateVariant at(uint index) const; - virtual TemplateListIntf::ConstIterator *createIterator() const; - virtual int addRef(); - virtual int release(); - - /** Creates an instance with ref count set to 0 */ - static TemplateList *alloc(); + virtual TemplateListIntf::ConstIteratorPtr createIterator() const; - /** Appends element \a v to the end of the list */ - virtual void append(const TemplateVariant &v); + /** Creates an instance and returns a shared pointer to it */ + static TemplateListIntfPtr alloc(std::initializer_list<TemplateVariant> elements); + static TemplateListIntfPtr alloc(const std::vector<TemplateVariant> &elements); - private: /** Creates a list */ - TemplateList(); + TemplateImmutableList(std::initializer_list<TemplateVariant> elements); + TemplateImmutableList(const std::vector<TemplateVariant> &elements); /** Destroys the list */ - ~TemplateList(); + virtual ~TemplateImmutableList(); - friend class TemplateListConstIterator; + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; //------------------------------------------------------------------------ @@ -451,45 +347,37 @@ class TemplateStructIntf /** Return the list of fields. */ virtual StringVector fields() const = 0; - - /** Increase object's reference count */ - virtual int addRef() = 0; - - /** Decreases object's reference count, destroy object if 0 */ - virtual int release() = 0; }; +//------------------------------------------------------------------------ -/** @brief Default implementation of a context value of type struct. */ -class TemplateStruct : public TemplateStructIntf +/** @brief Default implementation of an immutable context value of type struct. */ +class TemplateImmutableStruct : public TemplateStructIntf { public: // TemplateStructIntf methods virtual TemplateVariant get(const QCString &name) const; virtual StringVector fields() const; - virtual int addRef(); - virtual int release(); - /** Creates an instance with ref count set to 0. */ - static TemplateStruct *alloc(); + using StructField = std::pair<const std::string,TemplateVariant>; - /** Sets the value the field of a struct - * @param[in] name The name of the field. - * @param[in] v The value to set. + /** Creates an instance and returns a shared pointer to it + * @param fields the fields of the struct as key/value pairs. */ - virtual void set(const QCString &name,const TemplateVariant &v); - + static TemplateStructIntfPtr alloc(std::initializer_list<StructField> fields); - private: /** Creates a struct */ - TemplateStruct(); + TemplateImmutableStruct(std::initializer_list<StructField> fields); /** Destroys the struct */ - virtual ~TemplateStruct(); + virtual ~TemplateImmutableStruct(); + + private: class Private; - Private *p; + std::unique_ptr<Private> p; }; + //------------------------------------------------------------------------ /** @brief Interface used to escape characters in a string */ @@ -497,6 +385,8 @@ class TemplateEscapeIntf { public: virtual ~TemplateEscapeIntf() {} + /** Create a copy of the escape filter */ + virtual std::unique_ptr<TemplateEscapeIntf> clone() = 0; /** Returns the \a input after escaping certain characters */ virtual QCString escape(const QCString &input) = 0; /** Setting tabbing mode on or off (for LaTeX) */ @@ -510,6 +400,8 @@ class TemplateSpacelessIntf { public: virtual ~TemplateSpacelessIntf() {} + /** Create a copy of the spaceless filter */ + virtual std::unique_ptr<TemplateSpacelessIntf> clone() = 0; /** Returns the \a input after removing redundant whitespace */ virtual QCString remove(const QCString &input) = 0; /** Reset filter state */ @@ -567,12 +459,12 @@ class TemplateContext /** Sets the interface that will be used for escaping the result * of variable expansion before writing it to the output. */ - virtual void setEscapeIntf(const QCString &extension, TemplateEscapeIntf *intf) = 0; + virtual void setEscapeIntf(const QCString &extension, std::unique_ptr<TemplateEscapeIntf> intf) = 0; /** Sets the interface that will be used inside a spaceless block * to remove any redundant whitespace. */ - virtual void setSpacelessIntf(TemplateSpacelessIntf *intf) = 0; + virtual void setSpacelessIntf(std::unique_ptr<TemplateSpacelessIntf> intf) = 0; }; //------------------------------------------------------------------------ @@ -609,12 +501,7 @@ class TemplateEngine /** Creates a new context that can be using to render a template. * @see Template::render() */ - TemplateContext *createContext() const; - - /** Destroys a context created via createContext(). - * @param[in] ctx The context. - */ - void destroyContext(TemplateContext *ctx); + std::unique_ptr<TemplateContext> createContext() const; /** Creates a new template whose contents are in a file. * @param[in] fileName The name of the file containing the template data @@ -650,7 +537,7 @@ class TemplateEngine QCString outputExtension() const; class Private; - Private *p; + std::unique_ptr<Private> p; }; /** @} */ diff --git a/src/textstream.h b/src/textstream.h index a9c4a31..38027ec 100644 --- a/src/textstream.h +++ b/src/textstream.h @@ -67,11 +67,13 @@ class TextStream final { flush(); m_s = s; + m_f = nullptr; } void setFile(FILE *f) { flush(); + m_s = nullptr; m_f = f; } @@ -233,7 +235,7 @@ class TextStream final { n = (uint32_t)(-(int32_t)n); } - do { *--p = ((int32_t)(n%10)) + '0'; n /= 10; } while ( n ); + do { *--p = ((char)(n%10)) + '0'; n /= 10; } while ( n ); if ( neg ) *--p = '-'; m_buffer+=p; } diff --git a/src/tooltip.cpp b/src/tooltip.cpp index 38cda2c..d077ed6 100644 --- a/src/tooltip.cpp +++ b/src/tooltip.cpp @@ -62,7 +62,18 @@ void TooltipManager::addTooltip(CodeOutputInterface &ol,const Definition *d) { id = id.right(id.length()-i-1); // strip path (for CREATE_SUBDIRS=YES) } - id+=escapeId(Doxygen::htmlFileExtension); + // In case an extension is present translate this extension to something understood by the tooltip handler + // otherwise extend t with a translated htmlFileExtension. + QCString currentExtension = getFileNameExtension(id); + if (currentExtension.isEmpty()) + { + id += escapeId(Doxygen::htmlFileExtension); + } + else + { + id = stripExtensionGeneral(id,currentExtension) + escapeId(currentExtension); + } + QCString anc = d->anchor(); if (!anc.isEmpty()) { diff --git a/src/translator_br.h b/src/translator_br.h index baa4710..6a86fad 100644 --- a/src/translator_br.h +++ b/src/translator_br.h @@ -19,6 +19,8 @@ * Thanks to Jorge Ramos, Fernando Carijo and others for their contributions. * * History: + * 20211003: + * - Updated to 1.9.3; * 20200112: * - Updated to 1.9.1; * 20190203: @@ -52,7 +54,7 @@ #ifndef TRANSLATOR_BR_H #define TRANSLATOR_BR_H -class TranslatorBrazilian : public TranslatorAdapter_1_9_2 +class TranslatorBrazilian : public Translator { public: @@ -808,6 +810,7 @@ class TranslatorBrazilian : public TranslatorAdapter_1_9_2 bool single) { // here s is one of " Class", " Struct" or " Union" // single is true implies a single file + static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL); QCString result=(QCString)"A documentação para "; if (compType == ClassDef::Protocol) { @@ -819,7 +822,7 @@ class TranslatorBrazilian : public TranslatorAdapter_1_9_2 } switch(compType) { - case ClassDef::Class: result+="classe "; break; + case ClassDef::Class: result+=vhdlOpt?"Unidade de Design ":"classe "; break; case ClassDef::Struct: result+="estrutura "; break; case ClassDef::Union: result+="união "; break; case ClassDef::Interface: result+="interface "; break; @@ -2348,6 +2351,52 @@ class TranslatorBrazilian : public TranslatorAdapter_1_9_2 return "Documentação da Unidade de Projeto"; } + + ////////////////////////////////////////////////////////////////////////// + // new since 1.9.2 + ////////////////////////////////////////////////////////////////////////// + + /** C++20 concept */ + virtual QCString trConcept(bool first_capital, bool singular) + { + QCString result((first_capital ? "Conceito" : "conceito")); + if (!singular) result+="s"; + return result; + } + /*! used as the title of the HTML page of a C++20 concept page */ + virtual QCString trConceptReference(const QCString &conceptName) + { + QCString result= "Referência do Conceito "; + result+=conceptName; + return result; + } + + /*! used as the title of page containing all the index of all concepts. */ + virtual QCString trConceptList() + { return "Lista de Conceitos"; } + + /*! used as the title of chapter containing the index listing all concepts. */ + virtual QCString trConceptIndex() + { return "Índice de Conceitos"; } + + /*! used as the title of chapter containing all information about concepts. */ + virtual QCString trConceptDocumentation() + { return "Documentação do Conceito"; } + + /*! used as an introduction to the concept list */ + virtual QCString trConceptListDescription(bool extractAll) + { + QCString result="Esta é a lista de todos os conceitos "; + if (!extractAll) result+="documentados "; + result+="com suas respectivas descrições:"; + return result; + } + + /*! used to introduce the definition of the C++20 concept */ + virtual QCString trConceptDefinition() + { + return "Definição de conceito"; + } }; #endif diff --git a/src/translator_cn.h b/src/translator_cn.h index 8d3aa5e..2cc47e4 100644 --- a/src/translator_cn.h +++ b/src/translator_cn.h @@ -24,7 +24,7 @@ */ #define CN_SPC " " -class TranslatorChinese : public TranslatorAdapter_1_8_15 +class TranslatorChinese : public Translator { public: /*! Used for identification of the language. The identification @@ -65,7 +65,7 @@ class TranslatorChinese : public TranslatorAdapter_1_8_15 } virtual QCString latexDocumentPre() { - return "\\begin{CJK}{UTF8}{min}\n"; + return "\\begin{CJK}{UTF8}{gbsn}\n"; } virtual QCString latexDocumentPost() { @@ -1916,6 +1916,281 @@ class TranslatorChinese : public TranslatorAdapter_1_8_15 return "该单例的文档由下列文件生成:"; } +////////////////////////////////////////////////////////////////////////// +// new since 1.8.15 +////////////////////////////////////////////////////////////////////////// + + /** VHDL design unit hierarchy */ + virtual QCString trDesignUnitHierarchy() + { return "设计单元层次结构"; } + /** VHDL design unit list */ + virtual QCString trDesignUnitList() + { return "设计单元列表"; } + /** VHDL design unit members */ + virtual QCString trDesignUnitMembers() + { return "设计单元成员"; } + /** VHDL design unit list description */ + virtual QCString trDesignUnitListDescription() + { + return "这是所有设计单元成员的列表,以及指向他们所属实体的链接:"; + } + /** VHDL design unit index */ + virtual QCString trDesignUnitIndex() + { return "设计单元索引"; } + /** VHDL design units */ + virtual QCString trDesignUnits() + { return "设计单元"; } + /** VHDL functions/procedures/processes */ + virtual QCString trFunctionAndProc() + { return "函数/调用过程/进程语句"; } + /** VHDL type */ + virtual QCString trVhdlType(uint64 type,bool single) + { + switch(type) + { + case VhdlDocGen::LIBRARY: + return "库"; + case VhdlDocGen::PACKAGE: + return "包"; + case VhdlDocGen::SIGNAL: + return "信号"; + case VhdlDocGen::COMPONENT: + return "元件"; + case VhdlDocGen::CONSTANT: + return "常量"; + case VhdlDocGen::ENTITY: + return "实体"; + case VhdlDocGen::TYPE: + return "类型"; + case VhdlDocGen::SUBTYPE: + return "子类型"; + case VhdlDocGen::FUNCTION: + return "函数"; + case VhdlDocGen::RECORD: + return "记录"; + case VhdlDocGen::PROCEDURE: + return "过程"; + case VhdlDocGen::ARCHITECTURE: + return "结构体"; + case VhdlDocGen::ATTRIBUTE: + return "属性"; + case VhdlDocGen::PROCESS: + return "进程语句"; + case VhdlDocGen::PORT: + return "端口"; + case VhdlDocGen::USE: + if (single) return "使用语句"; + else return "使用语句"; + case VhdlDocGen::GENERIC: + return "类属"; + case VhdlDocGen::PACKAGE_BODY: + return "包体"; + case VhdlDocGen::UNITS: + return "单元"; + case VhdlDocGen::SHAREDVARIABLE: + return "共享变量"; + case VhdlDocGen::VFILE: + return "文件"; + case VhdlDocGen::GROUP: + return "组"; + case VhdlDocGen::INSTANTIATION: + return "实例化"; + case VhdlDocGen::ALIAS: + return "别名"; + case VhdlDocGen::CONFIG: + return " 配置"; + case VhdlDocGen::MISCELLANEOUS: + return "混合运算"; + case VhdlDocGen::UCF_CONST: + return "约束"; + default: + return "类"; + } + } + virtual QCString trCustomReference(const QCString &name) + { return QCString(name)+" 引用"; } + + /* Slice */ + virtual QCString trConstants() + { + return "常量"; + } + virtual QCString trConstantDocumentation() + { + return "常量文档"; + } + virtual QCString trSequences() + { + return "序列"; + } + virtual QCString trSequenceDocumentation() + { + return "序列文档"; + } + virtual QCString trDictionaries() + { + return "字典"; + } + virtual QCString trDictionaryDocumentation() + { + return "字典文档"; + } + virtual QCString trSliceInterfaces() + { + return "接口"; + } + virtual QCString trInterfaceIndex() + { + return "接口索引"; + } + virtual QCString trInterfaceList() + { + return "接口列表"; + } + virtual QCString trInterfaceListDescription() + { + return "以下是带有简要说明的接口:"; + } + virtual QCString trInterfaceHierarchy() + { + return "接口层次结构"; + } + virtual QCString trInterfaceHierarchyDescription() + { + return "此继承列表按字母顺序粗略排序:"; + } + virtual QCString trInterfaceDocumentation() + { + return "接口文档"; + } + virtual QCString trStructs() + { + return "结构"; + } + virtual QCString trStructIndex() + { + return "结构索引"; + } + virtual QCString trStructList() + { + return "结构列表"; + } + virtual QCString trStructListDescription() + { + return "以下是带有简要说明的结构:"; + } + virtual QCString trStructDocumentation() + { + return "结构文档"; + } + virtual QCString trExceptionIndex() + { + return "异常索引"; + } + virtual QCString trExceptionList() + { + return "异常列表"; + } + virtual QCString trExceptionListDescription() + { + return "以下是带有简要说明的异常:"; + } + virtual QCString trExceptionHierarchy() + { + return "异常层次结构"; + } + virtual QCString trExceptionHierarchyDescription() + { + return "此继承列表按字母顺序粗略排序:"; + } + virtual QCString trExceptionDocumentation() + { + return "异常文档"; + } + virtual QCString trCompoundReferenceSlice(const QCString &clName, ClassDef::CompoundType compType, bool isLocal) + { + QCString result=(QCString)clName; + if (isLocal) result+=" 局部"; + switch(compType) + { + case ClassDef::Class: result+=" 类"; break; + case ClassDef::Struct: result+=" 结构"; break; + case ClassDef::Union: result+=" 联合"; break; + case ClassDef::Interface: result+=" 接口"; break; + case ClassDef::Protocol: result+=" 协议"; break; + case ClassDef::Category: result+=" 类别"; break; + case ClassDef::Exception: result+=" 异常"; break; + default: break; + } + result+=" 引用"; + return result; + } + virtual QCString trOperations() + { + return "操作"; + } + virtual QCString trOperationDocumentation() + { + return "操作文档"; + } + virtual QCString trDataMembers() + { + return "数据成员"; + } + virtual QCString trDataMemberDocumentation() + { + return "数据成员文档"; + } + +////////////////////////////////////////////////////////////////////////// +// new since 1.8.19 +////////////////////////////////////////////////////////////////////////// + + /** VHDL design unit documentation */ + virtual QCString trDesignUnitDocumentation() + { return "设计单元文档"; } + +////////////////////////////////////////////////////////////////////////// +// new since 1.9.2 +////////////////////////////////////////////////////////////////////////// + + /** C++20 concept */ + virtual QCString trConcept(bool first_capital, bool singular) + { + return "概念"; + } + /*! used as the title of the HTML page of a C++20 concept page */ + virtual QCString trConceptReference(const QCString &conceptName) + { + QCString result=conceptName; + result+=" 概念引用"; + return result; + } + + /*! used as the title of page containing all the index of all concepts. */ + virtual QCString trConceptList() + { return "概念列表"; } + + /*! used as the title of chapter containing the index listing all concepts. */ + virtual QCString trConceptIndex() + { return "概念索引"; } + + /*! used as the title of chapter containing all information about concepts. */ + virtual QCString trConceptDocumentation() + { return "概念文档"; } + + /*! used as an introduction to the concept list */ + virtual QCString trConceptListDescription(bool extractAll) + { + return "以下是带有简要说明的概念"; + } + + /*! used to introduce the definition of the C++20 concept */ + virtual QCString trConceptDefinition() + { + return "概念定义"; + } + }; #endif diff --git a/src/translator_cz.h b/src/translator_cz.h index 1ce249e..ba38959 100644 --- a/src/translator_cz.h +++ b/src/translator_cz.h @@ -20,6 +20,8 @@ // Updates: // -------- +// 2021/08/31 - Updated for 1.9.3 version by: <petyovsky@feec.vutbr.cz>. +// 2021/01/22 - Updated for 1.9.2 version by: <petyovsky@feec.vutbr.cz>. // 2013/04/11 - Updates for "new since 1.8.4". // 2012/07/31 - Updates for "new since 1.8.2". // 2012/04/10 - Updates for "new since 1.8.0". @@ -85,7 +87,7 @@ // something else. It is difficult to find the general translation // for all kinds in the Czech language. -class TranslatorCzech : public TranslatorAdapter_1_8_15 +class TranslatorCzech : public Translator { public: // --- Language control methods ------------------- @@ -173,7 +175,7 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 * parameter s is name of the project name. */ virtual QCString trGeneratedAutomatically(const QCString &s) - { QCString result("Generováno automaticky programem Doxygen " + { QCString result("Vygenerováno automaticky programem Doxygen " "ze zdrojových textů"); if (!s.isEmpty()) result += QCString(" projektu ") + s; result += "."; @@ -261,8 +263,16 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 /*! This is an introduction to the class hierarchy. */ virtual QCString trClassHierarchyDescription() - { return "Zde naleznete seznam, vyjadřující vztah dědičnosti tříd. " - "Je seřazen přibližně (ale ne úplně) podle abecedy:"; + { + if (Config_getBool(OPTIMIZE_OUTPUT_VHDL)) + { + return "Zde je hierarchický seznam všech entit:"; + } + else + { + return "Zde naleznete seznam, vyjadřující vztah dědičnosti tříd. " + "Je seřazen přibližně (ale ne úplně) podle abecedy:"; + } } /*! This is an introduction to the list with all files. */ @@ -277,11 +287,17 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 /*! This is an introduction to the annotated compound list. */ virtual QCString trCompoundListDescription() { + if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C)) { return "Následující seznam obsahuje identifikace datových " "struktur a jejich stručné popisy:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Následující seznam obsahuje identifikace tříd. " + "V seznamu jsou uvedeny jejich stručné popisy:"; + } else { return "Následující seznam obsahuje především identifikace " @@ -300,7 +316,6 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 { result += "dokumentovaných "; } - if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C)) { result += "položek struktur (struct) a unií (union) "; @@ -309,32 +324,29 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 { result += "členů tříd "; } - result += "s odkazy na "; - - if (extractAll) + if (!extractAll) { if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C)) { - result += "dokumentaci struktur/unií, ke kterým příslušejí:"; + result+="struktury/unie, ke kterým příslušejí:"; } else { - result += "dokumentaci tříd, ke kterým příslušejí:"; + result+="třídy, ke kterým příslušejí:"; } } else { if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C)) { - result+="struktury/unie, ke kterým příslušejí:"; + result += "dokumentaci struktur/unií, ke kterým příslušejí:"; } else { - result+="třídy, ke kterým příslušejí:"; + result += "dokumentaci tříd, ke kterým příslušejí:"; } } - return result; } @@ -359,7 +371,6 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 result+="soubory, ke kterým příslušejí:"; else result+="dokumentaci:"; - return result; } @@ -377,7 +388,6 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 // index titles (the project name is prepended for these) - /*! This is used in HTML as the title of index.html. */ virtual QCString trDocumentation() { return "Dokumentace"; } @@ -430,6 +440,10 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 { return "Dokumentace datových struktur"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_VHDL)) + { + return trDesignUnitDocumentation(); + } else { return "Dokumentace tříd"; @@ -531,7 +545,7 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 { if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C)) { - return "Datové struktry"; + return "Datové struktury"; } else { @@ -544,17 +558,16 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 */ virtual QCString trGeneratedAt(const QCString &date,const QCString &projName) { - QCString result("Generováno "); - result += date; - if (!projName.isEmpty()) result += QCString(" pro projekt ") + projName; - result += " programem"; + QCString result=(QCString)"Vygenerováno dne: "+date; + if (!projName.isEmpty()) result += QCString(", pro projekt: ") + projName; + result+=(QCString)", programem"; return result; } /*! this text is put before a class diagram */ virtual QCString trClassDiagram(const QCString &clName) { - return QCString("Diagram dědičnosti pro třídu ") + clName; + return QCString("Diagram dědičnosti pro třídu ") + clName+":"; } /*! this text is generated when the \\internal command is used. */ @@ -591,20 +604,22 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 /*! this text is used in the title page of a LaTeX document. */ virtual QCString trGeneratedBy() - { return "Generováno programem"; } + { return "Vygenerováno programem"; } - // new since 0.49-990307 +////////////////////////////////////////////////////////////////////////// +// new since 0.49-990307 +////////////////////////////////////////////////////////////////////////// /*! used as the title of page containing all the index of all namespaces. */ virtual QCString trNamespaceList() - { return "Seznam prostorů jmen"; } + { return "Seznam jmenných prostorů"; } /*! used as an introduction to the namespace list */ virtual QCString trNamespaceListDescription(bool extractAll) { QCString result="Zde naleznete seznam všech "; if (!extractAll) result+="dokumentovaných "; - result+="prostorů jmen se stručným popisem:"; + result+="jmenných prostorů se stručným popisem:"; return result; } @@ -612,7 +627,7 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 * friends of a class */ virtual QCString trFriends() - { return "Friends"; } + { return "Přátelé třídy"; } ////////////////////////////////////////////////////////////////////////// // new since 0.49-990405 @@ -622,7 +637,7 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 * related classes */ virtual QCString trRelatedFunctionDocumentation() - { return "Dokumentace k friends"; } + { return "Dokumentace přátel a souvisejících funkcí třídy"; } ////////////////////////////////////////////////////////////////////////// // new since 0.49-990425 @@ -661,7 +676,7 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 /*! used as the title of the HTML page of a namespace */ virtual QCString trNamespaceReference(const QCString &namespaceName) { - QCString result("Dokumentace prostoru jmen "); + QCString result("Dokumentace jmenného prostoru "); result+=namespaceName; return result; } @@ -752,39 +767,37 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 */ virtual QCString trReimplementedInList(int numEntries) { - QCString result("Reimplementováno v "); - result += trWriteList(numEntries) + "."; - return result; + return "Reimplementováno v "+trWriteList(numEntries)+"."; } /*! This is put above each page as a link to all members of namespaces. */ virtual QCString trNamespaceMembers() - { return "Symboly v prostorech jmen"; } + { return "Symboly ve jmenném prostoru"; } /*! This is an introduction to the page with all namespace members */ virtual QCString trNamespaceMemberDescription(bool extractAll) { QCString result="Zde naleznete seznam všech "; if (!extractAll) result+="dokumentovaných "; - result+="symbolů, které jsou definovány ve svých prostorech jmen. " + result+="symbolů, které jsou definovány ve svých jmenných prostorech. " "U každého je uveden odkaz na "; if (extractAll) - result+="dokumentaci příslušného prostoru jmen:"; + result+="dokumentaci příslušného jmenného prostoru:"; else - result+="příslušný prostor jmen:"; + result+="příslušný jmenný prostor:"; return result; } /*! This is used in LaTeX as the title of the chapter with the * index of all namespaces. */ virtual QCString trNamespaceIndex() - { return "Rejstřík prostorů jmen"; } + { return "Rejstřík jmenných prostorů"; } /*! This is used in LaTeX as the title of the chapter containing * the documentation of all namespaces. */ virtual QCString trNamespaceDocumentation() - { return "Dokumentace prostorů jmen"; } + { return "Dokumentace jmenných prostorů"; } ////////////////////////////////////////////////////////////////////////// // new since 0.49-990522 @@ -794,7 +807,7 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 * namespaces in a file. */ virtual QCString trNamespaces() - { return "Prostory jmen"; } + { return "Jmenné prostory"; } ////////////////////////////////////////////////////////////////////////// // new since 0.49-990728 @@ -805,21 +818,20 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 */ virtual QCString trGeneratedFromFiles(ClassDef::CompoundType compType, bool single) - { // here s is one of " Class", " Struct" or " Union" - // single is true implies a single file + { // single is true implies a single file QCString result=(QCString)"Dokumentace pro "; switch(compType) { case ClassDef::Class: result+="tuto třídu"; break; - case ClassDef::Struct: result+="tuto strukturu (struct)"; break; - case ClassDef::Union: result+="tuto unii (union)"; break; + case ClassDef::Struct: result+="tuto strukturu"; break; + case ClassDef::Union: result+="tuto unii"; break; case ClassDef::Interface: result+="toto rozhraní"; break; - case ClassDef::Protocol: result+="tento protokol "; break; - case ClassDef::Category: result+="tuto kategorii "; break; + case ClassDef::Protocol: result+="tento protokol"; break; + case ClassDef::Category: result+="tuto kategorii"; break; case ClassDef::Exception: result+="tuto výjimku"; break; default: break; } - result+=" byla generována z "; + result+=" byla vygenerována z "; if (single) result+="následujícího souboru:"; else result+="následujících souborů:"; return result; @@ -873,13 +885,12 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 /*! this text is put before a collaboration diagram */ virtual QCString trCollaborationDiagram(const QCString &clName) { - return (QCString)"Diagram tříd pro "+clName+":"; + return (QCString)"Diagram pro "+clName+":"; } /*! this text is put before an include dependency graph */ virtual QCString trInclDepGraph(const QCString &fName) { - return (QCString)"Graf závislostí na vkládaných souborech " - "pro "+fName+":"; + return (QCString)"Graf závislostí na vkládaných souborech pro "+fName+":"; } /*! header that is put before the list of constructor/destructors. */ virtual QCString trConstructorDocumentation() @@ -914,7 +925,7 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 /*! Text shown before a multi-line variable/enum initialization */ virtual QCString trInitialValue() { - return "Initializer:"; + return "Inicializační hodnota:"; } /*! Text used the source code in the file index */ virtual QCString trCode() @@ -994,7 +1005,7 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 // new since 1.1.3 ////////////////////////////////////////////////////////////////////////// - /*! Used as a marker that is put before a todo item */ + /*! Used as a marker that is put before a \\todo item */ virtual QCString trTodo() { return "Plánované úpravy"; @@ -1031,7 +1042,7 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 return "Od"; // ??? not checked in a context } -//////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // new since 1.1.5 ////////////////////////////////////////////////////////////////////////// @@ -1045,7 +1056,7 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 { return "Zde naleznete vysvětlení, jak mají být interpretovány grafy, " - "které byly generovány programem doxygen.<p>\n" + "které byly vygenerovány programem doxygen.<p>\n" "Uvažujte následující příklad:\n" "\\code\n" "/*! Neviditelná třída, která se v grafu nezobrazuje, protože " @@ -1080,39 +1091,42 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 "};\n" "\\endcode\n" "K výše uvedenému bude vygenerován následující graf:" - "<p><center><img src=\"graph_legend."+getDotImageExtension()+"\"></center>\n" + "<p><center><img alt=\"\" src=\"graph_legend."+getDotImageExtension()+"\"></center></p>\n" "<p>\n" "Bloky (tj. uzly) v uvedeném grafu mají následující význam:\n" + "</p>\n" "<ul>\n" "<li>Šedě vyplněný obdélník reprezentuje strukturu nebo třídu, " - "pro kterou byl graf generován.\n" + "pro kterou byl graf vygenerován.</li>\n" "<li>Obdélník s černým obrysem označuje dokumentovanou " - "strukturu nebo třídu.\n" + "strukturu nebo třídu.</li>\n" "<li>Obdélník s šedým obrysem označuje nedokumentovanou " - "strukturu nebo třídu.\n" + "strukturu nebo třídu.</li>\n" "<li>Obdélník s červeným obrysem označuje dokumentovanou " "strukturu nebo třídu, pro kterou\n" "nejsou zobrazeny všechny vztahy dědičnosti nebo obsažení. " "Graf je ořezán v případě, kdy jej\n" - "není možné umístit do vymezeného prostoru.\n" + "není možné umístit do vymezeného prostoru.</li>\n" "</ul>\n" + "<p>\n" "Šipky (tj. hrany grafu) mají následující význam:\n" + "</p>\n" "<ul>\n" "<li>Tmavě modrá šipka se používá pro označení vztahu veřejné " - "dědičnosti (public) mezi dvěma třídami.\n" + "dědičnosti (public) mezi dvěma třídami.</li>\n" "<li>Tmavě zelená šipka označuje vztah chráněné dědičnosti " - "(protected).\n" + "(protected).</li>\n" "<li>Tmavě červená šipka označuje vztah privátní dědičnosti " - "(private).\n" + "(private).</li>\n" "<li>Purpurová šipka kreslená čárkovaně se používá v případě, " "kdy je třída obsažena v jiné třídě,\n" "nebo kdy je používána jinou třídou. Je označena identifikátorem " "jedné nebo více proměných, přes které\n" - "je třída nebo struktura zpřístupněna.\n" + "je třída nebo struktura zpřístupněna.</li>\n" "<li>Žlutá šipka kreslená čárkovaně vyjadřuje vztah mezi instancí šablony " "a šablonou třídy, na základě které byla\n" "instance šablony vytvořena. V popisu šipky jsou uvedeny příslušné" - " parametry šablony.\n" + " parametry šablony.</li>\n" "</ul>\n"; } /*! text for the link to the legend page */ @@ -1130,7 +1144,6 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 { return "Test"; } - /*! Used as the header of the test list */ virtual QCString trTestList() { @@ -1158,7 +1171,14 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 /*! Used for Java classes in the summary section of Java packages */ virtual QCString trClasses() { - return "Třídy"; + if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C)) + { + return "Datové struktury"; + } + else + { + return "Třídy"; + } } /*! Used as the title of a Java package */ virtual QCString trPackage(const QCString &name) @@ -1203,16 +1223,43 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 } ////////////////////////////////////////////////////////////////////////// -// new since 1.2.6-20010422 -////////////////////////////////////////////////////////////////////////// - - /*! Used as ansicpg for RTF file */ +// new since 1.2.6 +////////////////////////////////////////////////////////////////////////// + + /*! Used as ansicpg for RTF file + * + * The following table shows the correlation of Charset name, Charset Value and + * <pre> + * Codepage number: + * Charset Name Charset Value(hex) Codepage number + * ------------------------------------------------------ + * DEFAULT_CHARSET 1 (x01) + * SYMBOL_CHARSET 2 (x02) + * OEM_CHARSET 255 (xFF) + * ANSI_CHARSET 0 (x00) 1252 + * RUSSIAN_CHARSET 204 (xCC) 1251 + * EE_CHARSET 238 (xEE) 1250 + * GREEK_CHARSET 161 (xA1) 1253 + * TURKISH_CHARSET 162 (xA2) 1254 + * BALTIC_CHARSET 186 (xBA) 1257 + * HEBREW_CHARSET 177 (xB1) 1255 + * ARABIC _CHARSET 178 (xB2) 1256 + * SHIFTJIS_CHARSET 128 (x80) 932 + * HANGEUL_CHARSET 129 (x81) 949 + * GB2313_CHARSET 134 (x86) 936 + * CHINESEBIG5_CHARSET 136 (x88) 950 + * </pre> + * + */ virtual QCString trRTFansicp() { return "1250"; } - /*! Used as ansicpg for RTF fcharset */ + + /*! Used as ansicpg for RTF fcharset + * \see trRTFansicp() for a table of possible values. + */ virtual QCString trRTFCharSet() { return "238"; @@ -1252,9 +1299,10 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 */ virtual QCString trNamespace(bool first_capital, bool singular) { - QCString result((first_capital ? "Prostor" : "prostor")); + QCString result((first_capital ? "Jmenn" : "jmenn")); + result += singular ? "ý" : "é"; + result+=" prostor"; if (!singular) result+="y"; - result+=" jmen"; return result; } @@ -1287,14 +1335,17 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 virtual QCString trMember(bool first_capital, bool singular) { QCString result((first_capital ? "Člen" : "člen")); - if (!singular) - result += "y"; + if (!singular) result += "y"; return result; } /*! ??? Jak to prelozit? Bylo by dobre, kdyby se ozval nekdo, * kdo to pouziva. */ + /*! This is used for translation of the word that will possibly + * be followed by a single name or by a list of names + * of the category. + */ virtual QCString trGlobal(bool first_capital, bool singular) { QCString result((first_capital ? "Global" : "global")); @@ -1470,7 +1521,7 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 } else if (numDocuments==1) { - return "Nalezen jediný dokument, který vyhovuje vašemu dotazu."; + return "Nalezen jeden dokument, který vyhovuje vašemu dotazu."; } else { @@ -1498,12 +1549,10 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 return QCString("Zdrojový soubor ") + filename; } - ////////////////////////////////////////////////////////////////////////// // new since 1.3.9 ////////////////////////////////////////////////////////////////////////// - /*! This is used as the name of the chapter containing the directory * hierarchy. */ @@ -1517,7 +1566,7 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 { return "Dokumentace k adresářům"; } /*! This is used as the title of the directory index and also in the - * Quick links of a HTML page, to link to the directory hierarchy. + * Quick links of an HTML page, to link to the directory hierarchy. */ virtual QCString trDirectories() { return "Adresáře"; } @@ -1542,14 +1591,14 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 } /*! This returns the word directory with or without starting capital - * (\a first_capital) and in sigular or plural form (\a singular). + * (\a first_capital) and in singular or plural form (\a singular). */ virtual QCString trDir(bool first_capital, bool singular) { - QCString result((first_capital ? "Adresář" : "adresář")); - if ( ! singular) - result += "e"; - return result; + QCString result((first_capital ? "Adresář" : "adresář")); + if (!singular) + result += "e"; + return result; } ////////////////////////////////////////////////////////////////////////// @@ -1570,19 +1619,17 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 // new since 1.4.6 ////////////////////////////////////////////////////////////////////////// + /*! This is used to introduce a caller (or called-by) graph */ virtual QCString trCallerGraph() { return "Tuto funkci volají..."; } - /*! This is used in the documentation of a file/namespace before the list * of documentation blocks for enumeration values */ virtual QCString trEnumerationValueDocumentation() - { - return "Dokumentace výčtových hodnot"; - } + { return "Dokumentace výčtových hodnot"; } ////////////////////////////////////////////////////////////////////////// // new since 1.5.4 (mainly for Fortran) @@ -1607,7 +1654,6 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 /*! This is an introduction to the page with all data types (Fortran). */ virtual QCString trCompoundMembersDescriptionFortran(bool extractAll) { - QCString result="Následuje seznam všech "; if (!extractAll) { @@ -1736,12 +1782,13 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 if (!singular) result+="y"; return result; } + /*! This is put at the bottom of a module documentation page and is * followed by a list of files that were used to generate the page. */ virtual QCString trGeneratedFromFilesFortran(ClassDef::CompoundType compType, bool single) - { // here s is one of " Module", " Struct" or " Union" + { // single is true implies a single file QCString result=(QCString)"Dokumentace "; switch(compType) @@ -1760,6 +1807,7 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 else result+="následujících souborů:"; return result; } + /*! This is used for translation of the word that will possibly * be followed by a single name or by a list of names * of the category. @@ -1770,6 +1818,7 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 if (!singular) result+="y"; return result; } + /*! This is used for translation of the word that will possibly * be followed by a single name or by a list of names * of the category. @@ -1781,7 +1830,7 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 return result; } - /*! C# Type Contraint list */ + /*! C# Type Constraint list */ virtual QCString trTypeConstraints() { return "Omezení typů (Type Constraints)"; @@ -1806,7 +1855,7 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 /*! Label used for search results in the global namespace */ virtual QCString trGlobalNamespace() { - return "Globální prostor jmen"; + return "Globální jmenný prostor"; } /*! Message shown while searching */ @@ -1884,7 +1933,7 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 /*! Header for the graph showing the directory dependencies */ virtual QCString trDirDepGraph(const QCString &name) - { return QCString("Graf závislosti na adresářích pro ")+name+":"; } + { return QCString("Graf závislosti na adresářích pro ")+name+":"; } ////////////////////////////////////////////////////////////////////////// // new since 1.8.0 @@ -1904,7 +1953,7 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 /*! Used file list for a Java enum */ virtual QCString trEnumGeneratedFromFiles(bool single) - { QCString result = "Dokumentace pro tento výčet byla generována z "; + { QCString result = "Dokumentace pro tento výčet byla vygenerována z "; if (single) result += "následujícího souboru:"; else @@ -2022,7 +2071,7 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 virtual QCString trServiceGeneratedFromFiles(bool single) { // single is true implies a single file - QCString result="Dokumentace k této službě byla generována "; + QCString result="Dokumentace k této službě byla vygenerována "; if (single) result+="z následujícího souboru:"; else result+="z následujících souborů:"; return result; @@ -2031,12 +2080,317 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15 virtual QCString trSingletonGeneratedFromFiles(bool single) { // single is true implies a single file - QCString result="Dokumentace k tomuto singletonu byla generována "; + QCString result="Dokumentace k tomuto singletonu byla vygenerována "; if (single) result+="z následujícího souboru:"; else result+="z následujících souborů:"; return result; } +////////////////////////////////////////////////////////////////////////// +// new since 1.8.15 +////////////////////////////////////////////////////////////////////////// + + /** VHDL design unit hierarchy */ + virtual QCString trDesignUnitHierarchy() + { return "Hierarchie návrhových jednotek"; } + /** VHDL design unit list */ + virtual QCString trDesignUnitList() + { return "Seznam návrhových jednotek"; } + /** VHDL design unit members */ + virtual QCString trDesignUnitMembers() + { return "Seznam členů návrhových jednotky"; } + /** VHDL design unit list description */ + virtual QCString trDesignUnitListDescription() + { + return "Zde naleznete seznam všech členů návrhové jednotky s odkazy na " + "entity, ke kterým příslušejí:"; + } + /** VHDL design unit index */ + virtual QCString trDesignUnitIndex() + { return "Rejstřík návrhových jednotek"; } + /** VHDL design units */ + virtual QCString trDesignUnits() + { return "Návrhové jednotky"; } + /** VHDL functions/procedures/processes */ + virtual QCString trFunctionAndProc() + { return "Funkce/Procedury/Procesy"; } + /** VHDL type */ + virtual QCString trVhdlType(uint64 type,bool single) + { + switch(type) + { + case VhdlDocGen::LIBRARY: + if (single) return "Knihovna"; + else return "Knihovny"; + case VhdlDocGen::PACKAGE: + if (single) return "Balík"; + else return "Balíky"; + case VhdlDocGen::SIGNAL: + if (single) return "Signál"; + else return "Signály"; + case VhdlDocGen::COMPONENT: + if (single) return "Komponenta"; + else return "Komponenty"; + case VhdlDocGen::CONSTANT: + if (single) return "Konstanta"; + else return "Konstanty"; + case VhdlDocGen::ENTITY: + if (single) return "Entita"; + else return "Entity"; + case VhdlDocGen::TYPE: + if (single) return "Typ"; + else return "Typy"; + case VhdlDocGen::SUBTYPE: + if (single) return "Subtyp"; + else return "Subtypy"; + case VhdlDocGen::FUNCTION: + if (single) return "Funkce"; + else return "Funkce"; + case VhdlDocGen::RECORD: + if (single) return "Záznam"; + else return "Záznamy"; + case VhdlDocGen::PROCEDURE: + if (single) return "Procedura"; + else return "Procedury"; + case VhdlDocGen::ARCHITECTURE: + if (single) return "Architektura"; + else return "Architektury"; + case VhdlDocGen::ATTRIBUTE: + if (single) return "Atribut"; + else return "Atributy"; + case VhdlDocGen::PROCESS: + if (single) return "Proces"; + else return "Procesy"; + case VhdlDocGen::PORT: + if (single) return "Brána"; + else return "Brány"; + case VhdlDocGen::USE: + if (single) return "Klauzule use"; + else return "Klauzule use"; + case VhdlDocGen::GENERIC: + if (single) return "Generický parametr"; + else return "Generické parametry"; + case VhdlDocGen::PACKAGE_BODY: + return "Tělo balíku"; + case VhdlDocGen::UNITS: + return "Fyzikální jednotky"; + case VhdlDocGen::SHAREDVARIABLE: + if (single) return "Sdílená proměnná"; + else return "Sdílené proměnné"; + case VhdlDocGen::VFILE: + if (single) return "Soubor"; + else return "Soubory"; + case VhdlDocGen::GROUP: + if (single) return "Skupina"; + else return "Skupiny"; + case VhdlDocGen::INSTANTIATION: + if (single) return "Vložená instance"; + else return "Vložené instance"; + case VhdlDocGen::ALIAS: + if (single) return "Alias"; + else return "Aliasy"; + case VhdlDocGen::CONFIG: + if (single) return "Konfigurace"; + else return "Konfigurace"; + case VhdlDocGen::MISCELLANEOUS: + return "Ostatní"; + case VhdlDocGen::UCF_CONST: + return "Omezení (constraints)"; + default: + return "Třída"; + } + } + virtual QCString trCustomReference(const QCString &name) + { return "Dokumentace pro "+QCString(name); } + + /* Slice */ + virtual QCString trConstants() + { + return "Konstanty"; + } + virtual QCString trConstantDocumentation() + { + return "Dokumentace konstant"; + } + virtual QCString trSequences() + { + return "Sekvence"; + } + virtual QCString trSequenceDocumentation() + { + return "Dokumentace sekvence"; + } + virtual QCString trDictionaries() + { + return "Slovníky"; + } + virtual QCString trDictionaryDocumentation() + { + return "Dokumentace slovníku"; + } + virtual QCString trSliceInterfaces() + { + return "Rozhraní"; + } + virtual QCString trInterfaceIndex() + { + return "Rejstřík rozhraní"; + } + virtual QCString trInterfaceList() + { + return "Seznam rozhraní"; + } + virtual QCString trInterfaceListDescription() + { + return "Následující seznam obsahuje jména rozhraní a jejich stručné popisy:"; + } + virtual QCString trInterfaceHierarchy() + { + return "Hierarchie rozhraní"; + } + virtual QCString trInterfaceHierarchyDescription() + { + return "Zde naleznete seznam, vyjadřující vztah dědičnosti rozhraní. Je seřazen přibližně (ale ne úplně) podle abecedy:"; + } + virtual QCString trInterfaceDocumentation() + { + return "Dokumentace rozhraní"; + } + virtual QCString trStructs() + { + return "Struktury"; + } + virtual QCString trStructIndex() + { + return "Rejstřík struktur"; + } + virtual QCString trStructList() + { + return "Seznam struktur"; + } + virtual QCString trStructListDescription() + { + return "Následující seznam obsahuje jména struktur a jejich stručné popisy:"; + } + virtual QCString trStructDocumentation() + { + return "Dokumentace struktur"; + } + virtual QCString trExceptionIndex() + { + return "Rejstřík vyjímek"; + } + virtual QCString trExceptionList() + { + return "Seznam vyjímek"; + } + virtual QCString trExceptionListDescription() + { + return "Následující seznam obsahuje jména výjímek a jejich stručné popisy:"; + } + virtual QCString trExceptionHierarchy() + { + return "Hierarchie vyjímek"; + } + virtual QCString trExceptionHierarchyDescription() + { + return "Zde naleznete seznam, vyjadřující vztah dědičnosti vyjímek. Je seřazen přibližně (ale ne úplně) podle abecedy:"; + } + virtual QCString trExceptionDocumentation() + { + return "Dokumentace vyjímek"; + } + virtual QCString trCompoundReferenceSlice(const QCString &clName, ClassDef::CompoundType compType, bool isLocal) + { + QCString result("Dokumentace "); + if (isLocal) result+=" lokální"; + switch(compType) + { + case ClassDef::Class: result+=" třídy "; break; + case ClassDef::Struct: result+=" struktury "; break; + case ClassDef::Union: result+=" unie "; break; + case ClassDef::Interface: result+=" rozhraní "; break; + case ClassDef::Protocol: + if (isLocal) result+="ho"; + result+=" protokolu "; + break; + case ClassDef::Category: result+=" kategorie "; break; + case ClassDef::Exception: result+=" vyjímky "; break; + default: break; + } + result += clName; + return result; + } + virtual QCString trOperations() + { + return "Operace"; + } + virtual QCString trOperationDocumentation() + { + return "Dokumentace operace"; + } + virtual QCString trDataMembers() + { + return "Datové členy"; + } + virtual QCString trDataMemberDocumentation() + { + return "Dokumentace datových členů"; + } + +////////////////////////////////////////////////////////////////////////// +// new since 1.8.19 +////////////////////////////////////////////////////////////////////////// + + /** VHDL design unit documentation */ + virtual QCString trDesignUnitDocumentation() + { return "Dokumentace návrhové jednotky"; } + +////////////////////////////////////////////////////////////////////////// +// new since 1.9.2 +////////////////////////////////////////////////////////////////////////// + + /** C++20 concept */ + virtual QCString trConcept(bool first_capital, bool singular) + { + QCString result((first_capital ? "Koncept" : "koncept")); + if (!singular) result+="y"; + return result; + } + /*! used as the title of the HTML page of a C++20 concept page */ + virtual QCString trConceptReference(const QCString &conceptName) + { + QCString result("Dokumentace konceptu "); + result+=conceptName; + return result; + } + + /*! used as the title of page containing all the index of all concepts. */ + virtual QCString trConceptList() + { return "Seznam konceptů"; } + + /*! used as the title of chapter containing the index listing all concepts. */ + virtual QCString trConceptIndex() + { return "Rejstřík konceptů"; } + + /*! used as the title of chapter containing all information about concepts. */ + virtual QCString trConceptDocumentation() + { return "Dokumentace konceptů"; } + + /*! used as an introduction to the concept list */ + virtual QCString trConceptListDescription(bool extractAll) + { + QCString result="Následuje seznam všech "; + if (!extractAll) result+="dokumentovaných "; + result+="konceptů se stručnými popisy:"; + return result; + } + + /*! used to introduce the definition of the C++20 concept */ + virtual QCString trConceptDefinition() + { + return "Definice konceptů"; + } }; #endif // TRANSLATOR_CZ_H diff --git a/src/translator_de.h b/src/translator_de.h index ff7b704..d7d2de9 100644 --- a/src/translator_de.h +++ b/src/translator_de.h @@ -864,10 +864,11 @@ class TranslatorGerman : public TranslatorAdapter_1_8_15 virtual QCString trGeneratedFromFiles(ClassDef::CompoundType compType, bool single) { // single is true implies a single file + static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL); QCString result=(QCString)"Die Dokumentation für diese"; switch(compType) { - case ClassDef::Class: result+=" Klasse"; break; + case ClassDef::Class: result+=vhdlOpt?"Entwurfseinheiten":"Klasse"; break; case ClassDef::Struct: result+=" Struktur"; break; case ClassDef::Union: result+=" Variante"; break; case ClassDef::Interface: result+=" Schnittstelle"; break; diff --git a/src/translator_en.h b/src/translator_en.h index 3e456cc..55d6742 100644 --- a/src/translator_en.h +++ b/src/translator_en.h @@ -766,10 +766,11 @@ class TranslatorEnglish : public Translator virtual QCString trGeneratedFromFiles(ClassDef::CompoundType compType, bool single) { // single is true implies a single file + static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL); QCString result=(QCString)"The documentation for this "; switch(compType) { - case ClassDef::Class: result+="class"; break; + case ClassDef::Class: result+=vhdlOpt?"design unit":"class"; break; case ClassDef::Struct: result+="struct"; break; case ClassDef::Union: result+="union"; break; case ClassDef::Interface: result+="interface"; break; diff --git a/src/translator_es.h b/src/translator_es.h index 41dbd8f..dff426c 100644 --- a/src/translator_es.h +++ b/src/translator_es.h @@ -756,10 +756,11 @@ class TranslatorSpanish : public TranslatorAdapter_1_8_15 bool single) { // here s is one of " Class", " Struct" or " Union" // single is true implies a single file + static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL); QCString result=(QCString)"La documentación para est"; switch(compType) { - case ClassDef::Class: result+="a clase"; break; + case ClassDef::Class: result+=vhdlOpt? "a unidades de diseño":"a clase"; break; case ClassDef::Struct: result+="a estructura"; break; case ClassDef::Union: result+="a unión"; break; case ClassDef::Interface: result+="e interfaz"; break; diff --git a/src/translator_fr.h b/src/translator_fr.h index 9bbcf2c..a612760 100644 --- a/src/translator_fr.h +++ b/src/translator_fr.h @@ -822,11 +822,12 @@ class TranslatorFrench : public TranslatorAdapter_1_8_15 bool single) { // here s is one of " Class", " Struct" or " Union" // single is true implies a single file + static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL); bool feminine = true; QCString result=(QCString)"La documentation de "; switch(compType) { - case ClassDef::Class: result+="cette classe"; break; + case ClassDef::Class: result+=vhdlOpt? "cette unités de conception":"cette classe"; break; case ClassDef::Struct: result+="cette structure"; break; case ClassDef::Union: result+="cette union"; break; case ClassDef::Interface: result+="cette interface"; break; diff --git a/src/translator_gr.h b/src/translator_gr.h index b40b2ec..41d39f1 100644 --- a/src/translator_gr.h +++ b/src/translator_gr.h @@ -22,7 +22,10 @@ * 01 Jan 2009 : Greek maintenance by * Paul Gessos <gessos.paul@gmail.com> * - * Last update : 06 Jan 2015 + * + * Δουλεύω με C, C++, Java, PHP και Python. Άλλες γλώσσες (π.χ. VHDL) μου είναι + * άγνωστες. + * Αν παρατηρήσετε σφάλματα ΠΑΡΑΚΑΛΩ ΠΟΛΥ επικοινωνήστε μαζί μου. */ /* English to Greek keyword dictionary @@ -36,13 +39,16 @@ exception -> εξαίρεση namespace -> χώρος ονομάτων enumeration -> απαρίθμηση + concept -> έννοια + signal -> σήμα + instantiation -> ενσάρκωση */ #ifndef TRANSLATOR_GR_H #define TRANSLATOR_GR_H -class TranslatorGreek : public TranslatorAdapter_1_8_15 +class TranslatorGreek : public Translator { public: @@ -1878,7 +1884,7 @@ class TranslatorGreek : public TranslatorAdapter_1_8_15 /*! Header of a Java enum page (Java enums are represented as classes). */ virtual QCString trEnumReference(const QCString &name) - { return QCString("Αναφορά Απαρίθμησης ") + QCString(name); } + { return QCString("Αναφορά Απαρίθμησης ") + name; } /*! Used for a section containing inherited members */ virtual QCString trInheritedFrom(const QCString &members,const QCString &what) @@ -2001,7 +2007,308 @@ class TranslatorGreek : public TranslatorAdapter_1_8_15 return result; } +////////////////////////////////////////////////////////////////////////// +// new since 1.8.15 +////////////////////////////////////////////////////////////////////////// + /** VHDL design unit hierarchy */ + virtual QCString trDesignUnitHierarchy() + { return "Ιεραρχία Μονάδας Σχεδιασμού"; } + /** VHDL design unit list */ + virtual QCString trDesignUnitList() + { return "Λίστα Μονάδας Σχεδιασμού"; } + /** VHDL design unit members */ + virtual QCString trDesignUnitMembers() + { return "Μέλη Μονάδας Σχεδιασμού"; } + /** VHDL design unit list description */ + virtual QCString trDesignUnitListDescription() + { + return "Ακολουθεί μια λίστα από τα μέλη της μονάδας σχεδιασμού με συνδέσμους στις Οντότητες στις οποίες ανήκουν:"; + } + /** VHDL design unit index */ + virtual QCString trDesignUnitIndex() + { return "Ευρετήριο Μονάδων Σχεδιασμού"; } + /** VHDL design units */ + virtual QCString trDesignUnits() + { return "Μονάδες Σχεδιασμού"; } + /** VHDL functions/procedures/processes */ + virtual QCString trFunctionAndProc() + { return "Συναρτήσεις/Διαδικασίες/Διεργασίες"; } + /** VHDL type */ + virtual QCString trVhdlType(uint64 type,bool single) + { + switch(type) + { + case VhdlDocGen::LIBRARY: + if (single) return "Βιβλιοθήκη"; + else return "Βιβλιοθήκες"; + case VhdlDocGen::PACKAGE: + if (single) return "Πακέτο"; + else return "Πακέτα"; + case VhdlDocGen::SIGNAL: + if (single) return "Σήμα"; + else return "Σήματα"; + case VhdlDocGen::COMPONENT: + if (single) return "Εξάρτημα"; + else return "Εξαρτήματα"; + case VhdlDocGen::CONSTANT: + if (single) return "Σταθερά"; + else return "Σταθερές"; + case VhdlDocGen::ENTITY: + if (single) return "Οντότητα"; + else return "Οντότητες"; + case VhdlDocGen::TYPE: + if (single) return "Τύπος"; + else return "Τύποι"; + case VhdlDocGen::SUBTYPE: + if (single) return "Υποτύπος"; + else return "Υποτύποι"; + case VhdlDocGen::FUNCTION: + if (single) return "Συνάρτηση"; + else return "Συναρτήσεις"; + case VhdlDocGen::RECORD: + if (single) return "Εγγραφή"; + else return "Εγγραφές"; + case VhdlDocGen::PROCEDURE: + if (single) return "Διαδικασία"; + else return "Διαδικασίες"; + case VhdlDocGen::ARCHITECTURE: + if (single) return "Αρχιτεκτονική"; + else return "Αρχιτεκτονικές"; + case VhdlDocGen::ATTRIBUTE: + if (single) return "Ιδιότητα"; + else return "Ιδιότητες"; + case VhdlDocGen::PROCESS: + if (single) return "Διεργασία"; + else return "Διεργασίες"; + case VhdlDocGen::PORT: + if (single) return "Πόρτα"; + else return "Πόρτες"; + case VhdlDocGen::USE: + if (single) return "χρήση διάταξης"; + else return "Χρήση Διατάξεων"; + case VhdlDocGen::GENERIC: + if (single) return "Γενίκευση"; + else return "Γενικεύσεις"; + case VhdlDocGen::PACKAGE_BODY: + return "Σώμα Πακέτου"; + case VhdlDocGen::UNITS: + return "Μονάδες"; + case VhdlDocGen::SHAREDVARIABLE: + if (single) return "Κοινόχρηστη Μεταβλητή"; + else return "Κοινόχρηστες Μεταβλητές"; + case VhdlDocGen::VFILE: + if (single) return "Αρχείο"; + else return "Αρχεία"; + case VhdlDocGen::GROUP: + if (single) return "Ομάδα"; + else return "Ομάδες"; + case VhdlDocGen::INSTANTIATION: + if (single) return "Ενσάρκωση"; + else return "Ενσαρκώσεις"; + case VhdlDocGen::ALIAS: + if (single) return "Συνώνυμο"; + else return "Συνώνυμα"; + case VhdlDocGen::CONFIG: + if (single) return "Ρύθμιση"; + else return "Ρυθμίσεις"; + case VhdlDocGen::MISCELLANEOUS: + return "Διάφορα"; + case VhdlDocGen::UCF_CONST: + return "Εξαναγκασμοί"; + default: + return "Κλάση"; + } + } + virtual QCString trCustomReference(const QCString &name) + { return QCString("Τεκμηρίωση ")+name; } + + /* Slice */ + virtual QCString trConstants() + { + return "Σταθερές"; + } + virtual QCString trConstantDocumentation() + { + return "Τεκμηρίωση Σταθεράς"; + } + virtual QCString trSequences() + { + return "Ακολουθίες"; + } + virtual QCString trSequenceDocumentation() + { + return "Τεκμηρίωση Ακολουθίας"; + } + virtual QCString trDictionaries() + { + return "Λεξικά"; + } + virtual QCString trDictionaryDocumentation() + { + return "Τεκμηρίωση Λεξικού"; + } + virtual QCString trSliceInterfaces() + { + return "Διεπαφές"; + } + virtual QCString trInterfaceIndex() + { + return "Ευρετήριο Διεπαφής"; + } + virtual QCString trInterfaceList() + { + return "Λίστα Διεπαφής"; + } + virtual QCString trInterfaceListDescription() + { + return "Ακολουθούν οι διεπαφές με σύντομες περιγραφές:"; + } + virtual QCString trInterfaceHierarchy() + { + return "Ιεραρχία Διεπαφής"; + } + virtual QCString trInterfaceHierarchyDescription() + { + return "Αυτή η λίστα ιεραρχίας είναι ταξινομημένη χονδροειδώς και όχι αυστηρά αλφαβητικά:"; + } + virtual QCString trInterfaceDocumentation() + { + return "Τεκμηρίωση Διεπαφής"; + } + virtual QCString trStructs() + { + return "Δομές"; + } + virtual QCString trStructIndex() + { + return "Ευρετήριο Δομής"; + } + virtual QCString trStructList() + { + return "Λίστα Δομής"; + } + virtual QCString trStructListDescription() + { + return "Ακολουθούν οι δομές με σύντομες περιγραφές:"; + } + virtual QCString trStructDocumentation() + { + return "Τεκμηρίωση Δομής"; + } + virtual QCString trExceptionIndex() + { + return "Ευρετήριο Εξαιρέσεων"; + } + virtual QCString trExceptionList() + { + return "Λίστα Εξαίρεσης"; + } + virtual QCString trExceptionListDescription() + { + return "Ακολουθούν οι εξαιρέσεις με σύντομες περιγραφές:"; + } + virtual QCString trExceptionHierarchy() + { + return "Ιεραρχία Εξαίρεσης"; + } + virtual QCString trExceptionHierarchyDescription() + { + return "Αυτή η λίστα ιεραρχίας είναι ταξινομημένη χονδροειδώς και όχι αυστηρά αλφαβητικά:"; + } + virtual QCString trExceptionDocumentation() + { + return "Τεκμηρίωση Εξαίρεσης"; + } + virtual QCString trCompoundReferenceSlice(const QCString &clName, ClassDef::CompoundType compType, bool isLocal) + { + QCString result="Τεκμηρίωση "; + if (isLocal) + result+=compType == ClassDef::Protocol ? "Τοπικού " : "Τοπικής "; + switch(compType) + { + case ClassDef::Class: result+="Κλάσης "; break; + case ClassDef::Struct: result+="Δομής "; break; + case ClassDef::Union: result+="Ένωσης "; break; + case ClassDef::Interface: result+="Διεπαφής "; break; + case ClassDef::Protocol: result+="Πρωτοκόλλου "; break; + case ClassDef::Category: result+="Κατηγορίας "; break; + case ClassDef::Exception: result+="Εξαίρεσης "; break; + default: break; + } + result+=clName; + return result; + } + virtual QCString trOperations() + { + return "Πράξεις"; + } + virtual QCString trOperationDocumentation() + { + return "Τεκμηρίωση Πράξης"; + } + virtual QCString trDataMembers() + { + return "Μέλη Δεδομένων"; + } + virtual QCString trDataMemberDocumentation() + { + return "Τεκμηρίωση Μέλους Δεδομένων"; + } + +////////////////////////////////////////////////////////////////////////// +// new since 1.8.19 +////////////////////////////////////////////////////////////////////////// + + /** VHDL design unit documentation */ + virtual QCString trDesignUnitDocumentation() + { return "Τεκμηρίωση Μονάδας Σχεδιασμού"; } + +////////////////////////////////////////////////////////////////////////// +// new since 1.9.2 +////////////////////////////////////////////////////////////////////////// + + /** C++20 concept */ + virtual QCString trConcept(bool first_capital, bool singular) + { + QCString result((first_capital ? "Έννοι" : "έννοι")); + result+=singular ? "α" : "ες"; + return result; + } + /*! used as the title of the HTML page of a C++20 concept page */ + virtual QCString trConceptReference(const QCString &conceptName) + { + QCString result("Αναφορά Έννοιας "); + result+=conceptName; + return result; + } + + /*! used as the title of page containing all the index of all concepts. */ + virtual QCString trConceptList() + { return "Λίστα Έννοιας"; } + + /*! used as the title of chapter containing the index listing all concepts. */ + virtual QCString trConceptIndex() + { return "Ευρετήριο Έννοιας"; } + + /*! used as the title of chapter containing all information about concepts. */ + virtual QCString trConceptDocumentation() + { return "Τεκμηρίωση Έννοιας"; } + + /*! used as an introduction to the concept list */ + virtual QCString trConceptListDescription(bool extractAll) + { + QCString result="Ακολουθεί μια λίστα από όλες τις "; + if (!extractAll) result+="τεκμηριωμένες "; + result+="έννοιες με σύντομες περιγραφές:"; + return result; + } + + /*! used to introduce the definition of the C++20 concept */ + virtual QCString trConceptDefinition() + { + return "Ορισμός Έννοιας"; + } }; #endif diff --git a/src/translator_nl.h b/src/translator_nl.h index 7bf8db3..0e4171b 100644 --- a/src/translator_nl.h +++ b/src/translator_nl.h @@ -414,10 +414,11 @@ class TranslatorDutch : public Translator bool single) { // here s is one of " Class", " Struct" or " Union" // single is true implies a single file + static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL); QCString result=(QCString)"De documentatie voor "; switch(compType) { - case ClassDef::Class: result+="deze klasse"; break; + case ClassDef::Class: result+=vhdlOpt?"deze ontwerp eenheid":"deze klasse"; break; case ClassDef::Struct: result+="deze struct"; break; case ClassDef::Union: result+="deze union"; break; case ClassDef::Interface: result+="dit interface"; break; diff --git a/src/translator_pt.h b/src/translator_pt.h index 223ca53..8bfbf96 100644 --- a/src/translator_pt.h +++ b/src/translator_pt.h @@ -26,6 +26,8 @@ * VERSION HISTORY * --------------- * History: + * 20211003: + * - Updated to 1.9.3; * 20200112: * - Updated to 1.9.1; * 20190203: @@ -63,7 +65,7 @@ #define TRANSLATOR_PT_H -class TranslatorPortuguese : public TranslatorAdapter_1_9_2 +class TranslatorPortuguese : public Translator { public: @@ -770,10 +772,11 @@ class TranslatorPortuguese : public TranslatorAdapter_1_9_2 bool single) { // here s is one of " Class", " Struct" or " Union" // single is true implies a single file + static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL); QCString result=(QCString)"A documentação para "; switch(compType) { - case ClassDef::Class: result+="esta classe"; break; + case ClassDef::Class: result+=vhdlOpt?"esta Unidade de Design":"esta classe"; break; case ClassDef::Struct: result+="esta estrutura"; break; case ClassDef::Union: result+="esta união"; break; case ClassDef::Interface: result+="este interface"; break; @@ -2285,6 +2288,52 @@ class TranslatorPortuguese : public TranslatorAdapter_1_9_2 { return "Documentação da Unidade de Projeto"; } + + + ////////////////////////////////////////////////////////////////////////// + // new since 1.9.2 + ////////////////////////////////////////////////////////////////////////// + /** C++20 concept */ + virtual QCString trConcept(bool first_capital, bool singular) + { + QCString result((first_capital ? "Conceito" : "conceito")); + if (!singular) result+="s"; + return result; + } + /*! used as the title of the HTML page of a C++20 concept page */ + virtual QCString trConceptReference(const QCString &conceptName) + { + QCString result= "Referência do Conceito "; + result+=conceptName; + return result; + } + + /*! used as the title of page containing all the index of all concepts. */ + virtual QCString trConceptList() + { return "Lista de Conceitos"; } + + /*! used as the title of chapter containing the index listing all concepts. */ + virtual QCString trConceptIndex() + { return "Índice de Conceitos"; } + + /*! used as the title of chapter containing all information about concepts. */ + virtual QCString trConceptDocumentation() + { return "Documentação do Conceito"; } + + /*! used as an introduction to the concept list */ + virtual QCString trConceptListDescription(bool extractAll) + { + QCString result="Esta é a lista de todos os conceitos "; + if (!extractAll) result+="documentados "; + result+="com suas respectivas descrições:"; + return result; + } + + /*! used to introduce the definition of the C++20 concept */ + virtual QCString trConceptDefinition() + { + return "Definição de conceito"; + } }; #endif diff --git a/src/translator_sv.h b/src/translator_sv.h index 4916694..31f764f 100644 --- a/src/translator_sv.h +++ b/src/translator_sv.h @@ -95,6 +95,11 @@ I left use clause untouched as I didn't find a suitable translation for it. English: * Updated the language translation to 1.8.19 +2020/08/19 +* Uppdaterat översättningarna till 1.9.2 +English: +* Updated the language translation to 1.9.2 + =================================================================================== Ordlista =================================================================================== @@ -151,7 +156,7 @@ English: #ifndef TRANSLATOR_SE_H #define TRANSLATOR_SE_H -class TranslatorSwedish : public TranslatorAdapter_1_9_2 +class TranslatorSwedish : public Translator { public: @@ -866,10 +871,11 @@ class TranslatorSwedish : public TranslatorAdapter_1_9_2 bool single) { // here s is one of " Class", " Struct" or " Union" // single is true implies a single file + static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL); QCString result=(QCString)"Dokumentationen för "; switch(compType) { - case ClassDef::Class: result+="denna klass"; break; + case ClassDef::Class: result+=vhdlOpt? "denna designenhets":"denna klass"; break; case ClassDef::Struct: result+="denna strukt"; break; case ClassDef::Union: result+="denna union"; break; case ClassDef::Interface: result+="detta gränssnitt"; break; @@ -2354,5 +2360,49 @@ class TranslatorSwedish : public TranslatorAdapter_1_9_2 virtual QCString trDesignUnitDocumentation() { return "Designenhetsdokumentation"; } +////////////////////////////////////////////////////////////////////////// +// new since 1.9.2 +////////////////////////////////////////////////////////////////////////// + + /** C++20 concept */ + virtual QCString trConcept(bool first_capital, bool singular) + { + QCString result((first_capital ? "Koncept" : "koncept")); + return result; + } + /*! used as the title of the HTML page of a C++20 concept page */ + virtual QCString trConceptReference(const QCString &conceptName) + { + QCString result=conceptName; + result+=" Konceptreferens"; + return result; + } + + /*! used as the title of page containing all the index of all concepts. */ + virtual QCString trConceptList() + { return "Konceptlista"; } + + /*! used as the title of chapter containing the index listing all concepts. */ + virtual QCString trConceptIndex() + { return "Konceptindex"; } + + /*! used as the title of chapter containing all information about concepts. */ + virtual QCString trConceptDocumentation() + { return "Konceptdokumentation"; } + + /*! used as an introduction to the concept list */ + virtual QCString trConceptListDescription(bool extractAll) + { + QCString result="Här är listan över alla "; + if (!extractAll) result+="dokumenterade "; + result+="koncept med en kort beskrivning:"; + return result; + } + + /*! used to introduce the definition of the C++20 concept */ + virtual QCString trConceptDefinition() + { + return "Konceptdefinition"; + } }; #endif diff --git a/src/types.h b/src/types.h index 2bb7056..69d8f7e 100644 --- a/src/types.h +++ b/src/types.h @@ -104,6 +104,8 @@ enum MemberListType MemberListType_declarationLists = 0x2000, MemberListType_documentationLists = 0x4000, + MemberListType_undefined = -1, + MemberListType_pubMethods = 0, MemberListType_proMethods = 1, MemberListType_pacMethods = 2, diff --git a/src/util.cpp b/src/util.cpp index cab6530..9d9cc41 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -166,7 +166,7 @@ const int maxInheritanceDepth = 100000; QCString removeAnonymousScopes(const QCString &str) { std::string result; - if (str.isEmpty()) return result; + if (str.isEmpty()) return QCString(result); // helper to check if the found delimiter starts with a colon auto startsWithColon = [](const std::string &del) @@ -227,7 +227,7 @@ QCString replaceAnonymousScopes(const QCString &s,const QCString &replacement) std::string result = reg::replace(s.str(),marker, replacement.isEmpty() ? replacement.data() : "__anonymous__"); //printf("replaceAnonymousScopes('%s')='%s'\n",qPrint(s),qPrint(result)); - return result; + return QCString(result); } @@ -889,12 +889,12 @@ void linkifyText(const TextGeneratorIntf &out, const Definition *scope, bool keepSpaces,int indentLevel) { if (text.isEmpty()) return; - //printf("linkify='%s'\n",text); + //printf("linkify='%s'\n",qPrint(text)); std::string txtStr=text.str(); size_t strLen = txtStr.length(); if (strLen==0) return; - static const reg::Ex regExp(R"(\a[\w~!\\.:$]*)"); + static const reg::Ex regExp(R"((::)?\a[\w~!\\.:$]*)"); reg::Iterator it(txtStr,regExp); reg::Iterator end; @@ -1204,14 +1204,6 @@ QCString tempArgListToString(const ArgumentList &al,SrcLangExt lang,bool include if (!first) result+=", "; if (!a.name.isEmpty()) // add template argument name { - if (a.type.left(4)=="out") // C# covariance - { - result+="out "; - } - else if (a.type.left(3)=="in") // C# contravariance - { - result+="in "; - } if (lang==SrcLangExt_Java || lang==SrcLangExt_CSharp) { result+=a.type+" "; @@ -1412,7 +1404,7 @@ QCString fileToString(const QCString &name,bool filter,bool isSourceCode) { contents+=line+'\n'; } - return contents; + return QCString(contents); } else // read from file { @@ -4004,7 +3996,7 @@ QCString convertToXML(const QCString &s, bool keepEntities) } /*! Converts a string to an DocBook-encoded string */ -QCString convertToDocBook(const QCString &s) +QCString convertToDocBook(const QCString &s, const bool retainNewline) { if (s.isEmpty()) return s; GrowBuf growBuf; @@ -4016,6 +4008,7 @@ QCString convertToDocBook(const QCString &s) { switch (c) { + case '\n': if (retainNewline) growBuf.addStr("<literallayout> 
</literallayout>"); growBuf.addChar(c); break; case '<': growBuf.addStr("<"); break; case '>': growBuf.addStr(">"); break; case '&': // possibility to have a special symbol @@ -4407,13 +4400,13 @@ int extractClassNameFromType(const QCString &type,int &pos,QCString &name,QCStri pos=i+l; } //printf("extractClassNameFromType([in] type=%s,[out] pos=%d,[out] name=%s,[out] templ=%s)=TRUE i=%d\n", - // type,pos,qPrint(name),qPrint(templSpec),i); + // qPrint(type),pos,qPrint(name),qPrint(templSpec),i); return i; } } pos = typeLen; //printf("extractClassNameFromType([in] type=%s,[out] pos=%d,[out] name=%s,[out] templ=%s)=FALSE\n", - // type,pos,qPrint(name),qPrint(templSpec)); + // qPrint(type),pos,qPrint(name),qPrint(templSpec)); return -1; } @@ -4428,7 +4421,7 @@ QCString normalizeNonTemplateArgumentsInString( p++; QCString result = name.left(p); - std::string s = result.mid(p).str(); + std::string s = name.mid(p).str(); static const reg::Ex re(R"([\a:][\w:]*)"); reg::Iterator it(s,re); reg::Iterator end; @@ -4488,7 +4481,7 @@ QCString substituteTemplateArgumentsInString( const std::unique_ptr<ArgumentList> &actualArgs) { //printf("substituteTemplateArgumentsInString(name=%s formal=%s actualArg=%s)\n", - // qPrint(name),qPrint(argListToString(formalArgs)),qPrint(argListToString(actualArgs))); + // qPrint(nm),qPrint(argListToString(formalArgs)),actualArgs ? qPrint(argListToString(*actualArgs)): ""); if (formalArgs.empty()) return nm; QCString result; @@ -4793,10 +4786,6 @@ PageDef *addRelatedPage(const QCString &name,const QCString &ptitle, pd->setRefItems(sli); newPage = false; } - else if (pd) // we are from a tag file - { - Doxygen::pageLinkedMap->del(name); - } if (newPage) // new page { @@ -4807,9 +4796,21 @@ PageDef *addRelatedPage(const QCString &name,const QCString &ptitle, baseName=baseName.left(baseName.length()-Doxygen::htmlFileExtension.length()); //printf("Appending page '%s'\n",qPrint(baseName)); - pd = Doxygen::pageLinkedMap->add(baseName, - std::unique_ptr<PageDef>( - createPageDef(fileName,docLine,baseName,doc,title))); + if (pd) // replace existing page + { + pd->setDocumentation(doc,fileName,docLine); + pd->setFileName(::convertNameToFile(baseName,FALSE,TRUE)); + pd->setShowLineNo(FALSE); + pd->setNestingLevel(0); + pd->setPageScope(0); + pd->setTitle(title); + } + else // newPage + { + pd = Doxygen::pageLinkedMap->add(baseName, + std::unique_ptr<PageDef>( + createPageDef(fileName,docLine,baseName,doc,title))); + } pd->setBodySegment(startLine,startLine,-1); pd->setRefItems(sli); @@ -4932,7 +4933,7 @@ void addGroupListToTitle(OutputList &ol,const Definition *d) } void filterLatexString(TextStream &t,const QCString &str, - bool insideTabbing,bool insidePre,bool insideItem,bool insideTable,bool keepSpaces) + bool insideTabbing,bool insidePre,bool insideItem,bool insideTable,bool keepSpaces, const bool retainNewline) { if (str.isEmpty()) return; //if (strlen(str)<2) stackTrace(); @@ -4971,6 +4972,8 @@ void filterLatexString(TextStream &t,const QCString &str, case '-': t << "-\\/"; break; case '^': insideTable ? t << "\\string^" : t << (char)c; break; case '~': t << "\\string~"; break; + case '\n': if (retainNewline) t << "\\newline"; else t << ' '; + break; case ' ': if (keepSpaces) t << "~"; else t << ' '; break; default: @@ -5058,6 +5061,8 @@ void filterLatexString(TextStream &t,const QCString &str, break; case '\'': t << "\\textquotesingle{}"; break; + case '\n': if (retainNewline) t << "\\newline"; else t << ' '; + break; case ' ': if (keepSpaces) { if (insideTabbing) t << "\\>"; else t << '~'; } else t << ' '; break; @@ -6269,7 +6274,7 @@ QCString filterTitle(const QCString &title) p=i+l; } tf+=t.substr(p); - return tf; + return QCString(tf); } //---------------------------------------------------------------------------- @@ -6430,7 +6435,7 @@ QCString replaceColorMarkers(const QCString &str) p=i+l; } if (p<sl) result+=s.substr(p); - return result; + return QCString(result); } /** Copies the contents of file with name \a src to the newly created @@ -7031,7 +7036,7 @@ bool mainPageHasTitle() QCString getDotImageExtension() { - QCString imgExt = Config_getEnum(DOT_IMAGE_FORMAT); + QCString imgExt = Config_getEnumAsString(DOT_IMAGE_FORMAT); int i= imgExt.find(':'); // strip renderer part when using e.g. 'png:cairo:gd' as format return i==-1 ? imgExt : imgExt.left(i); } @@ -7381,3 +7386,4 @@ QCString integerToRoman(int n, bool upper) return result; } + @@ -226,7 +226,7 @@ QCString convertToLaTeX(const QCString &s,bool insideTabbing=FALSE,bool keepSpac QCString convertToXML(const QCString &s, bool keepEntities=FALSE); -QCString convertToDocBook(const QCString &s); +QCString convertToDocBook(const QCString &s, const bool retainNewline = false); QCString convertToJSString(const QCString &s); @@ -293,7 +293,8 @@ void filterLatexString(TextStream &t,const QCString &str, bool insidePre, bool insideItem, bool insideTable, - bool keepSpaces); + bool keepSpaces, + const bool retainNewline = false); QCString latexEscapeLabelName(const QCString &s); QCString latexEscapeIndexChars(const QCString &s); diff --git a/src/variant.h b/src/variant.h index d04e5a6..7f0407e 100644 --- a/src/variant.h +++ b/src/variant.h @@ -16,8 +16,6 @@ #ifndef VARIANT_H #define VARIANT_H -#include <typeinfo> -#include <type_traits> #include <string> #include <utility> @@ -50,99 +48,126 @@ struct TMax<arg1, arg2, others...> //------ helper class to deal with memory management of an array of template types -//! generic declaration of a template to handle copyin, moving, deleting, and computing the -//! index for a type that matches one in the set of template parameters. -template<typename... Ts> -struct HelperT; - -//! specialization to stop the recursion for an empty list. -template<> -struct HelperT<> -{ - inline static void copy(size_t src_t, const void * src_v, void * dst_v) { } - inline static void move(size_t src_t, void * src_v, void * dst_v) { } - inline static void destroy(size_t id, void * data) { } - inline static size_t index(size_t id, size_t index) { return std::string::npos; } -}; +//! generic declaration of a template to handle copying, moving, and deleting +//! type that matches a given index in the list of variant parameters. +template<uint8_t n,typename... Ts> +struct HelperRecT; //! Recursive template definition for multiple arguments. -//! Each function check the first parameter, and if the type matches does the action. -//! If not, the same function is called without this template parameters. -template<typename F, typename... Ts> -struct HelperT<F, Ts...> +//! Each function checks for a matching index, and if found does the action. +//! If not, the same function is called with the next index and one less type argument. +template<uint8_t n, typename F, typename... Ts> +struct HelperRecT<n, F, Ts...> { //! Helper function to copy an instance of a type by performing a placement new. - //! @param src_t The id if the type to search for in the template parameter list + //! @param id The id if the type to search for in the template parameter list //! @param src_v A pointer to the value of the type to copy from. //! @param dst_v A pointer to the variable to copy to. - inline static void copy(size_t src_t, const void * src_v, void * dst_v) + inline static void copy(uint8_t id, const void * src_v, void * dst_v) { - if (src_t == typeid(F).hash_code()) // found it + if (n==id) // found it { new (dst_v) F(*reinterpret_cast<const F*>(src_v)); } else // continue searching { - HelperT<Ts...>::copy(src_t, src_v, dst_v); + HelperRecT<n+1,Ts...>::copy(id, src_v, dst_v); } } //! Helper function to move an instance of a type by calling the move constructor on it. - //! @param src_t The id if the type to search for in the template parameter list + //! @param id The id if the type to search for in the template parameter list //! @param src_v A pointer to the value of the type to copy from. //! @param dst_v A pointer to the variable to copy to. - inline static void move(size_t src_t, void * src_v, void * dst_v) + inline static void move(uint8_t id, void * src_v, void * dst_v) { - if (src_t == typeid(F).hash_code()) // found it + if (n==id) // found it { new (dst_v) F(std::move(*reinterpret_cast<F*>(src_v))); } else // continue searching { - HelperT<Ts...>::move(src_t, src_v, dst_v); + HelperRecT<n+1,Ts...>::move(id, src_v, dst_v); } } //! Helper function to destroy an object of a given type by calling its destructor. //! @param id The id if the type to search for in the template parameter list //! @param data A pointer to the object to destroy - inline static void destroy(size_t id, void * data) + inline static void destroy(uint8_t id, void * data) { - if (id == typeid(F).hash_code()) // found it + if (n==id) // found it { reinterpret_cast<F*>(data)->~F(); } else // continue searching { - HelperT<Ts...>::destroy(id, data); + HelperRecT<n+1,Ts...>::destroy(id, data); } } - //! Helper function to returns the index of a given type within the template parameter list - //! @param id The id to search for - //! @param index The index into the original template list - inline static size_t index(size_t id,size_t index) - { - if (id == typeid(F).hash_code()) // found it - { - return index; - } - else // continue searching - { - return HelperT<Ts...>::index(id,index+1); - } - } +}; + +//! Specialization to stop the recursion when the end of the list has reached +template<uint8_t n> +struct HelperRecT<n> +{ + inline static void copy(uint8_t id, const void * src_v, void * dst_v) { } + inline static void move(uint8_t id, void * src_v, void * dst_v) { } + inline static void destroy(uint8_t id, void * data) { } +}; +//! Helper to kickstart the recursive search +template<typename ...Ts> +struct HelperT +{ + inline static void copy(uint8_t id, const void *src_v, void *dst_v) + { HelperRecT<0, Ts...>::copy(id, src_v, dst_v); } + inline static void move(uint8_t id, void *src_v, void *dst_v) + { HelperRecT<0, Ts...>::move(id, src_v, dst_v); } + inline static void destroy(uint8_t id,void *data) + { HelperRecT<0, Ts...>::destroy(id, data); } +}; + +//! Specialization to end the recursion +template<> +struct HelperT<> +{ + inline static void copy(uint8_t id, const void * src_v, void * dst_v) { } + inline static void move(uint8_t id, void * src_v, void * dst_v) { } + inline static void destroy(uint8_t id, void * data) { } }; } // namespace details +//! Generic declaration of a template type wrapper where VariantType<index,...>::type +//! represents the type of the variant at the given index. +//! The first type of the variant has index 0, the second has +//! index 1, etc. +template<uint8_t index, typename... Items> +struct VariantType; + +//! specialization to stop the recursion when arrived at index 0 and type F +template<typename F,typename...Ts> +struct VariantType<0, F, Ts...> +{ + using type = F; +}; + +//! recursive definition of the type wrapper +template<uint8_t index, typename F, typename... Ts> +struct VariantType<index, F, Ts...> +{ + using type = typename VariantType<index-1,Ts...>::type; +}; + //------------------------------------------------------------------ //! Implementation of a variant container (similar to C++17's std::variant). //! It can hold either no instances (e.g. initially or after calling invalidate()), //! or hold exactly one instance of an object (after calling set()) //! whose type is one of the variant's template parameters. +//! Each parameter has an index, the first parameter has index 0. //! It behaves similar to a C union, in that the memory of all //! possible object types is shared, but unlike a C union //! it does allow C++ objects with constructors and destructors to be stored and @@ -157,42 +182,49 @@ struct Variant { //! the data type for the Variant's internal memory using Data = typename std::aligned_storage<data_size, data_align>::type; + //! a short hand name for the helper class using HelperT = details::HelperT<Ts...>; + template<uint8_t index> + using Type = typename VariantType<index,Ts...>::type; + //! The id that represents an invalid type - static inline size_t invalid_type() { return typeid(void).hash_code(); } + static inline uint8_t invalid_id() { return 255; } - //! a unique identifier for the type held by this variant - size_t type_id; //! the actual data - Data data; + Data m_data; + //! a unique identifier for the type held by this variant + uint8_t m_id; public: //! The default constructor - Variant() : type_id(invalid_type()) + Variant() : m_id(invalid_id()) { } //! The copy constructor - Variant(const Variant<Ts...>& src) : type_id(src.type_id) + Variant(const Variant<Ts...>& src) : m_id(src.m_id) { - HelperT::copy(src.type_id, &src.data, &data); + HelperT::copy(src.m_id, &src.m_data, &m_data); } //! The move constructor - Variant(Variant<Ts...>&& src) : type_id(src.type_id) + Variant(Variant<Ts...>&& src) : m_id(src.m_id) { - HelperT::move(src.type_id, &src.data, &data); + HelperT::move(src.m_id, &src.m_data, &m_data); } //! The copy assignment operator Variant<Ts...>& operator= (const Variant<Ts...> &src) { - if (this!=&src) + if (this!=&src) // prevent self assignment { - type_id = src.type_id; - HelperT::copy(src.type_id, &src.data, &data); + // destroy the old value + if (valid()) HelperT::destroy(m_id,&m_data); + // and copy over the new one + m_id = src.m_id; + HelperT::copy(src.m_id, &src.m_data, &m_data); } return *this; } @@ -200,67 +232,70 @@ struct Variant { //! The move assignment operator Variant<Ts...>& operator= (Variant<Ts...> &&src) { - type_id = src.type_id; - HelperT::move(src.type_id, &src.data, &data); + // destroy the old value + if (valid()) HelperT::destroy(m_id,&m_data); + // and move in the new one + m_id = src.m_id; + HelperT::move(src.m_id, &src.m_data, &m_data); return *this; } //! The destructor ~Variant() { - HelperT::destroy(type_id, &data); + HelperT::destroy(m_id, &m_data); } //! Returns true iff the variant container holds a specific type. //! @tparam T the type to search for. - template<typename T> - constexpr bool is() const { return (type_id==typeid(T).hash_code()); } + template<uint8_t index> + constexpr bool is() const { return m_id==index; } //! Returns true iff the Variant holds a valid type. - constexpr bool valid() const { return (type_id!=invalid_type()); } + constexpr bool valid() const { return m_id!=invalid_id(); } //! Invalidate the variant. Will destroy any object that is held. void invalidate() { - HelperT::destroy(type_id,&data); - type_id = invalid_type(); + HelperT::destroy(m_id,&m_data); + m_id = invalid_id(); } - //! Returns the index of the type held by this variant, or std::string::npos if the + //! Returns the index of the type held by this variant, or invalid_id() if the //! variant does not hold any type (i.e. valid() returns false). - constexpr size_t index() const { return HelperT::index(type_id, 0); } + constexpr uint8_t index() const { return m_id; } //! Replaces the contents of the variant container by constructing a type T calling //! the constructor with Args - //! @tparam T the type to make the variant hold an instance of. + //! @tparam index the type to make the variant hold an instance of. //! @tparam Args The arguments types to pass to the constructor of T. //! @param args The argument values - template<typename T, typename... Args> + template<uint8_t index, typename... Args> void set(Args&&... args) { - HelperT::destroy(type_id, &data); - new (&data) T(std::forward<Args>(args)...); - type_id = typeid(T).hash_code(); + HelperT::destroy(m_id, &m_data); + m_id = index; + new (&m_data) Type<index>(std::forward<Args>(args)...); } //! Return a non-constant reference to the value held by the variant container. //! @throw std::bad_cast() if called on a variant container that does not hold - //! an instance of the specified type. - template<typename T> - T& get() + //! an instance of the type of the variant at index. + template<uint8_t index> + Type<index>& get() { - if (type_id != typeid(T).hash_code()) throw std::bad_cast(); - return *reinterpret_cast<T*>(&data); + if (m_id != index) throw std::bad_cast(); + return *reinterpret_cast<Type<index>*>(&m_data); } //! Returns a constant reference to the value held by the variant container. //! @throw std::bad_cast() if called on a variant container that does not hold - //! an instance of the specified type. - template<typename T> - const T& get() const + //! an instance of the type of the variant at index. + template<uint8_t index> + const Type<index>& get() const { - if (type_id != typeid(T).hash_code()) throw std::bad_cast(); - return *reinterpret_cast<const T*>(&data); + if (m_id != index) throw std::bad_cast(); + return *reinterpret_cast<const Type<index>*>(&m_data); } }; diff --git a/src/vhdlcode.l b/src/vhdlcode.l index 12b0bc9..2e11f9e 100644 --- a/src/vhdlcode.l +++ b/src/vhdlcode.l @@ -24,6 +24,10 @@ %option extra-type="struct vhdlcodeYY_state *" %top{ #include <stdint.h> +// forward declare yyscan_t to improve type safety +#define YY_TYPEDEF_YY_SCANNER_T +struct yyguts_t; +typedef yyguts_t *yyscan_t; } %{ @@ -76,7 +80,6 @@ struct vhdlcodeYY_state bool isComponent = false; bool isPackageBody = false; bool isProto = false; - bool startCode = false; QCString prevString; QCString currClass; std::unordered_set<std::string> vhdlKeyDict; @@ -88,9 +91,10 @@ struct vhdlcodeYY_state CodeOutputInterface * code = 0; const char * inputString = 0; //!< the code fragment as text yy_size_t inputPosition = 0; //!< read offset during parsing + QCString fileName; int inputLines = 0; //!< number of line in the code fragment int yyLineNr = 0; //!< current line number - bool needsTermination = false; + bool insideCodeLine = false; const Definition *searchCtx = 0; bool exampleBlock = false; @@ -145,6 +149,10 @@ static const char *stateToString(int state); #undef YY_INPUT #define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); +// otherwise the filename would be the name of the converted file (*.cpp instead of *.l) +static inline const char *getLexerFILE() {return __FILE__;} +#include "doxygen_lex.h" + %} @@ -202,13 +210,9 @@ XILINX "INST"|"NET"|"PIN"|"BLKNM"|"BUFG"|"COLLAPSE"|"CPLD"|"COMPGRP"|"CONFI %x ParseComponent %x ParsePackage %x ParseProcessProto -%x ClassName -%x PackageName -%x ClassVar %x ClassesName %x Map %x End -%x Body %% @@ -1034,24 +1038,27 @@ static void startCodeLine(yyscan_t yyscanner) { yyextra->code->writeLineNumber(yyextra->currentMemberDef->getReference(), yyextra->currentMemberDef->getOutputFileBase(), - yyextra->currentMemberDef->anchor(),yyextra->yyLineNr); + yyextra->currentMemberDef->anchor(),yyextra->yyLineNr, + !yyextra->includeCodeFragment); setCurrentDoc(yyscanner,lineAnchor); } else if (d->isLinkableInProject()) { yyextra->code->writeLineNumber(d->getReference(), d->getOutputFileBase(), - QCString(),yyextra->yyLineNr); + QCString(),yyextra->yyLineNr, + !yyextra->includeCodeFragment); setCurrentDoc(yyscanner,lineAnchor); } } else { - yyextra->code->writeLineNumber(QCString(),QCString(),QCString(),yyextra->yyLineNr); + yyextra->code->writeLineNumber(QCString(),QCString(),QCString(),yyextra->yyLineNr, + !yyextra->includeCodeFragment); } } yyextra->code->startCodeLine(yyextra->sourceFileDef); - yyextra->startCode=true; + yyextra->insideCodeLine=true; if (yyextra->currentFontClass) { yyextra->code->startFontClass(yyextra->currentFontClass); @@ -1063,12 +1070,13 @@ static void endCodeLine(yyscan_t yyscanner) struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; endFontClass(yyscanner); yyextra->code->endCodeLine(); + yyextra->insideCodeLine=false; } static void nextCodeLine(yyscan_t yyscanner) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - if (yyextra->startCode) + if (yyextra->insideCodeLine) { endCodeLine(yyscanner); // </div> } @@ -1386,8 +1394,7 @@ static int countLines(yyscan_t yyscanner) if (p>yyextra->inputString && *(p-1)!='\n') { // last line does not end with a \n, so we add an extra // line and explicitly terminate the line after parsing. - count++, - yyextra->needsTermination=true; + count++; } return count; } @@ -1594,6 +1601,7 @@ void VHDLCodeParser::parseCode(CodeOutputInterface &od, //printf("***parseCode() exBlock=%d exName=%s fd=%p\n",exBlock,exName,fd); if (s.isEmpty()) return; printlex(yy_flex_debug, true, __FILE__, fd ? qPrint(fd->fileName()): NULL); + yyextra->fileName = fd ? fd->fileName():""; if (memberDef) { const ClassDef *dd=memberDef->getClassDef(); @@ -1604,7 +1612,7 @@ void VHDLCodeParser::parseCode(CodeOutputInterface &od, yyextra->inputString = s.data(); yyextra->inputPosition = 0; yyextra->currentFontClass = 0; - yyextra->needsTermination = false; + yyextra->insideCodeLine = false; yyextra->searchCtx = searchCtx; if (startLine!=-1) @@ -1647,11 +1655,10 @@ void VHDLCodeParser::parseCode(CodeOutputInterface &od, VhdlDocGen::init(); yyextra->lexInit=true; } - /*int iLine=*/countLines(yyscanner); vhdlcodeYYrestart( 0, yyscanner ); BEGIN( Bases ); vhdlcodeYYlex(yyscanner); - if (yyextra->needsTermination) + if (yyextra->insideCodeLine) { endCodeLine(yyscanner); } @@ -1661,7 +1668,6 @@ void VHDLCodeParser::parseCode(CodeOutputInterface &od, delete yyextra->sourceFileDef; yyextra->sourceFileDef=0; } - yyextra->startCode=false; // write the tooltips yyextra->tooltipManager.writeTooltips(od); diff --git a/src/vhdldocgen.cpp b/src/vhdldocgen.cpp index d75c879..8793e58 100644 --- a/src/vhdldocgen.cpp +++ b/src/vhdldocgen.cpp @@ -81,6 +81,7 @@ static void writeTable(const std::vector<const MemberDef*> &portList,TextStream static void endTable(TextStream &t); static void writeClassToDot(TextStream &t,ClassDef* cd); static void writeVhdlDotLink(TextStream &t,const QCString &a,const QCString &b,const QCString &style); + static const MemberDef *flowMember=0; void VhdlDocGen::setFlowMember( const MemberDef* mem) @@ -335,7 +336,7 @@ static void writeColumn(TextStream &t,const MemberDef *md,bool start) if (md) { t << "href=\""; - t << md->getOutputFileBase()<< Doxygen::htmlFileExtension; + t << addHtmlExtensionIfMissing(md->getOutputFileBase()); t << "#" << md->anchor(); t<<"\" "; @@ -405,7 +406,7 @@ static void writeClassToDot(TextStream &t,ClassDef* cd) t << cd->name(); t << "\" "; t << "href=\""; - t << cd->getOutputFileBase() << Doxygen::htmlFileExtension; + t << addHtmlExtensionIfMissing(cd->getOutputFileBase()); t << "\" "; t << ">"; t << cd->name(); @@ -1726,7 +1727,7 @@ void VhdlDocGen::writeTagFile(MemberDefMutable *mdef,TextStream &tagFile) tagFile << "\">\n"; tagFile << " <type>" << convertToXML(mdef->typeString()) << "</type>\n"; tagFile << " <name>" << convertToXML(mdef->name()) << "</name>\n"; - tagFile << " <anchorfile>" << convertToXML(mdef->getOutputFileBase()) << Doxygen::htmlFileExtension << "</anchorfile>\n"; + tagFile << " <anchorfile>" << convertToXML(addHtmlExtensionIfMissing(mdef->getOutputFileBase())) << "</anchorfile>\n"; tagFile << " <anchor>" << convertToXML(mdef->anchor()) << "</anchor>\n"; if (VhdlDocGen::isVhdlFunction(mdef)) @@ -2465,7 +2466,7 @@ QCString VhdlDocGen::parseForBinding(QCString & entity,QCString & arch) { arch=ql[2]; } - return label; + return QCString(label); } diff --git a/src/xmlcode.l b/src/xmlcode.l index e5c74aa..c3e7f51 100644 --- a/src/xmlcode.l +++ b/src/xmlcode.l @@ -26,6 +26,10 @@ %option noyywrap %top{ #include <stdint.h> +// forward declare yyscan_t to improve type safety +#define YY_TYPEDEF_YY_SCANNER_T +struct yyguts_t; +typedef yyguts_t *yyscan_t; } %{ @@ -57,9 +61,10 @@ struct xmlcodeYY_state QCString parmName; const char * inputString = 0; //!< the code fragment as text yy_size_t inputPosition = 0; //!< read offset during parsing + QCString fileName; int inputLines = 0; //!< number of line in the code fragment int yyLineNr = 0; //!< current line number - bool needsTermination = false; + bool insideCodeLine = false; const Definition *searchCtx = 0; bool exampleBlock = false; @@ -98,6 +103,10 @@ static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size); #undef YY_INPUT #define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); +// otherwise the filename would be the name of the converted file (*.cpp instead of *.l) +static inline const char *getLexerFILE() {return __FILE__;} +#include "doxygen_lex.h" + %} nl (\r\n|\r|\n) @@ -253,24 +262,28 @@ static void startCodeLine(yyscan_t yyscanner) { yyextra->code->writeLineNumber(yyextra->currentMemberDef->getReference(), yyextra->currentMemberDef->getOutputFileBase(), - yyextra->currentMemberDef->anchor(),yyextra->yyLineNr); + yyextra->currentMemberDef->anchor(),yyextra->yyLineNr, + !yyextra->includeCodeFragment); setCurrentDoc(yyscanner,lineAnchor); } else { yyextra->code->writeLineNumber(d->getReference(), d->getOutputFileBase(), - QCString(),yyextra->yyLineNr); + QCString(),yyextra->yyLineNr, + !yyextra->includeCodeFragment); setCurrentDoc(yyscanner,lineAnchor); } } else { - yyextra->code->writeLineNumber(QCString(),QCString(),QCString(),yyextra->yyLineNr); + yyextra->code->writeLineNumber(QCString(),QCString(),QCString(),yyextra->yyLineNr, + !yyextra->includeCodeFragment); } } yyextra->code->startCodeLine(yyextra->sourceFileDef); + yyextra->insideCodeLine = true; if (yyextra->currentFontClass) { @@ -293,13 +306,17 @@ static void endCodeLine(yyscan_t yyscanner) struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; endFontClass(yyscanner); yyextra->code->endCodeLine(); + yyextra->insideCodeLine = false; } static void nextCodeLine(yyscan_t yyscanner) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; const char *fc = yyextra->currentFontClass; - endCodeLine(yyscanner); + if (yyextra->insideCodeLine) + { + endCodeLine(yyscanner); + } if (yyextra->yyLineNr<yyextra->inputLines) { yyextra->currentFontClass = fc; @@ -359,8 +376,7 @@ static int countLines(yyscan_t yyscanner) if (p>yyextra->inputString && *(p-1)!='\n') { // last line does not end with a \n, so we add an extra // line and explicitly terminate the line after parsing. - count++, - yyextra->needsTermination=true; + count++; } return count; } @@ -416,12 +432,13 @@ void XMLCodeParser::parseCode(CodeOutputInterface &codeOutIntf, if (input.isEmpty()) return; printlex(yy_flex_debug, true, __FILE__, fileDef ? qPrint(fileDef->fileName()): NULL); + yyextra->fileName = fileDef ? fileDef->fileName():""; yyextra->code = &codeOutIntf; yyextra->inputString = input.data(); yyextra->inputPosition = 0; yyextra->currentFontClass = 0; - yyextra->needsTermination = false; + yyextra->insideCodeLine = false; yyextra->searchCtx = searchCtx; if (startLine!=-1) @@ -460,7 +477,7 @@ void XMLCodeParser::parseCode(CodeOutputInterface &codeOutIntf, xmlcodeYYlex(yyscanner); - if (yyextra->needsTermination) + if (yyextra->insideCodeLine) { endCodeLine(yyscanner); } diff --git a/src/xmldocvisitor.cpp b/src/xmldocvisitor.cpp index 00c976c..c0e0271 100644 --- a/src/xmldocvisitor.cpp +++ b/src/xmldocvisitor.cpp @@ -38,7 +38,7 @@ static void visitCaption(XmlDocVisitor *parent, const DocNodeList &children) static void visitPreStart(TextStream &t, const char *cmd, bool doCaption, XmlDocVisitor *parent, const DocNodeList &children, const QCString &name, bool writeType, DocImage::Type type, const QCString &width, - const QCString &height, const QCString &alt = QCString(""), bool inlineImage = FALSE) + const QCString &height, const QCString engine = QCString(), const QCString &alt = QCString(), bool inlineImage = FALSE) { t << "<" << cmd; if (writeType) @@ -50,6 +50,7 @@ static void visitPreStart(TextStream &t, const char *cmd, bool doCaption, case DocImage::Latex: t << "latex"; break; case DocImage::Rtf: t << "rtf"; break; case DocImage::DocBook: t << "docbook"; break; + case DocImage::Xml: t << "xml"; break; } t << "\""; } @@ -65,6 +66,10 @@ static void visitPreStart(TextStream &t, const char *cmd, bool doCaption, { t << " height=\"" << convertToXML(height) << "\""; } + if (!engine.isEmpty()) + { + t << " engine=\"" << convertToXML(engine) << "\""; + } if (!alt.isEmpty()) { t << " alt=\"" << convertToXML(alt) << "\""; @@ -220,6 +225,9 @@ void XmlDocVisitor::visit(DocStyleChange *s) case DocStyleChange::Small: if (s->enable()) m_t << "<small>"; else m_t << "</small>"; break; + case DocStyleChange::Cite: + if (s->enable()) m_t << "<cite>"; else m_t << "</cite>"; + break; case DocStyleChange::Preformatted: if (s->enable()) { @@ -234,6 +242,12 @@ void XmlDocVisitor::visit(DocStyleChange *s) break; case DocStyleChange::Div: /* HTML only */ break; case DocStyleChange::Span: /* HTML only */ break; + case DocStyleChange::Details: + if (s->enable()) m_t << "<details>"; else m_t << "</details>"; + break; + case DocStyleChange::Summary: + if (s->enable()) m_t << "<summary>"; else m_t << "</summary>"; + break; } } @@ -258,6 +272,16 @@ void XmlDocVisitor::visit(DocVerbatim *s) s->isExample(),s->exampleFile()); m_t << "</programlisting>"; break; + case DocVerbatim::JavaDocLiteral: + m_t << "<javadocliteral>"; + filter(s->text()); + m_t << "</javadocliteral>"; + break; + case DocVerbatim::JavaDocCode: + m_t << "<javadoccode>"; + filter(s->text()); + m_t << "</javadoccode>"; + break; case DocVerbatim::Verbatim: m_t << "<verbatim>"; filter(s->text()); @@ -309,7 +333,7 @@ void XmlDocVisitor::visit(DocVerbatim *s) visitPostEnd(m_t, "msc"); break; case DocVerbatim::PlantUML: - visitPreStart(m_t, "plantuml", s->hasCaption(), this, s->children(), QCString(""), FALSE, DocImage::Html, s->width(), s->height()); + visitPreStart(m_t, "plantuml", s->hasCaption(), this, s->children(), QCString(""), FALSE, DocImage::Html, s->width(), s->height(), s->engine()); filter(s->text()); visitPostEnd(m_t, "plantuml"); break; @@ -731,10 +755,18 @@ void XmlDocVisitor::visitPost(DocHtmlList *s) m_t << "</itemizedlist>\n"; } -void XmlDocVisitor::visitPre(DocHtmlListItem *) +void XmlDocVisitor::visitPre(DocHtmlListItem *l) { if (m_hide) return; - m_t << "<listitem>\n"; + m_t << "<listitem"; + for (const auto &opt : l->attribs()) + { + if (opt.name=="value") + { + m_t << " " << opt.name << "=\"" << opt.value << "\""; + } + } + m_t << ">\n"; } void XmlDocVisitor::visitPost(DocHtmlListItem *) @@ -792,6 +824,16 @@ void XmlDocVisitor::visitPre(DocHtmlTable *t) } } m_t << ">"; + if (t->hasCaption()) + { + DocHtmlCaption *c = t->caption(); + m_t << "<caption"; + if (!c->file().isEmpty()) + { + m_t << " id=\"" << stripPath(c->file()) << "_1" << c->anchor() << "\""; + } + m_t << ">"; + } } void XmlDocVisitor::visitPost(DocHtmlTable *) @@ -872,7 +914,7 @@ void XmlDocVisitor::visitPost(DocHtmlCell *) void XmlDocVisitor::visitPre(DocHtmlCaption *) { if (m_hide) return; - m_t << "<caption>"; + // start of caption is handled in the XmlDocVisitor::visitPre(DocHtmlTable *t) } void XmlDocVisitor::visitPost(DocHtmlCaption *) @@ -936,7 +978,7 @@ void XmlDocVisitor::visitPre(DocImage *img) [](const auto &att) { return att.name=="alt"; }); QCString altValue = it!=attribs.end() ? it->value : ""; visitPreStart(m_t, "image", FALSE, this, img->children(), baseName, TRUE, - img->type(), img->width(), img->height(), + img->type(), img->width(), img->height(), QCString(), altValue, img->isInlineImage()); // copy the image to the output dir @@ -957,7 +999,8 @@ void XmlDocVisitor::visitPost(DocImage *) void XmlDocVisitor::visitPre(DocDotFile *df) { if (m_hide) return; - visitPreStart(m_t, "dotfile", FALSE, this, df->children(), df->file(), FALSE, DocImage::Html, df->width(), df->height()); + copyFile(df->file(),Config_getString(XML_OUTPUT)+"/"+stripPath(df->file())); + visitPreStart(m_t, "dotfile", FALSE, this, df->children(), stripPath(df->file()), FALSE, DocImage::Html, df->width(), df->height()); } void XmlDocVisitor::visitPost(DocDotFile *) @@ -969,7 +1012,8 @@ void XmlDocVisitor::visitPost(DocDotFile *) void XmlDocVisitor::visitPre(DocMscFile *df) { if (m_hide) return; - visitPreStart(m_t, "mscfile", FALSE, this, df->children(), df->file(), FALSE, DocImage::Html, df->width(), df->height()); + copyFile(df->file(),Config_getString(XML_OUTPUT)+"/"+stripPath(df->file())); + visitPreStart(m_t, "mscfile", FALSE, this, df->children(), stripPath(df->file()), FALSE, DocImage::Html, df->width(), df->height()); } void XmlDocVisitor::visitPost(DocMscFile *) @@ -981,7 +1025,8 @@ void XmlDocVisitor::visitPost(DocMscFile *) void XmlDocVisitor::visitPre(DocDiaFile *df) { if (m_hide) return; - visitPreStart(m_t, "diafile", FALSE, this, df->children(), df->file(), FALSE, DocImage::Html, df->width(), df->height()); + copyFile(df->file(),Config_getString(XML_OUTPUT)+"/"+stripPath(df->file())); + visitPreStart(m_t, "diafile", FALSE, this, df->children(), stripPath(df->file()), FALSE, DocImage::Html, df->width(), df->height()); } void XmlDocVisitor::visitPost(DocDiaFile *) diff --git a/src/xmlgen.cpp b/src/xmlgen.cpp index f12a52d..14797b5 100644 --- a/src/xmlgen.cpp +++ b/src/xmlgen.cpp @@ -325,7 +325,7 @@ void XMLCodeGenerator::writeCodeAnchor(const QCString &) XML_DB(("(writeCodeAnchor)\n")); } void XMLCodeGenerator::writeLineNumber(const QCString &extRef,const QCString &compId, - const QCString &anchorId,int l) + const QCString &anchorId,int l,bool) { XML_DB(("(writeLineNumber)\n")); // we remember the information provided here to use it @@ -568,12 +568,6 @@ static void generateXMLForMember(const MemberDef *md,TextStream &ti,TextStream & << "_1" << md->anchor() << "\" kind=\"" << memType << "\"><name>" << convertToXML(md->name()) << "</name></member>\n"; - QCString scopeName; - if (md->getClassDef()) - scopeName=md->getClassDef()->name(); - else if (md->getNamespaceDef()) - scopeName=md->getNamespaceDef()->name(); - t << " <memberdef kind=\""; //enum { define_t,variable_t,typedef_t,enum_t,function_t } xmlType = function_t; t << memType << "\" id=\""; @@ -819,7 +813,13 @@ static void generateXMLForMember(const MemberDef *md,TextStream &ti,TextStream & t << "</type>\n"; } - t << " <name>" << convertToXML(md->name()) << "</name>\n"; + QCString name = md->name(); + QCString qualifiedName = md->qualifiedName();; + t << " <name>" << convertToXML(name) << "</name>\n"; + if (name!=qualifiedName) + { + t << " <qualifiedname>" << convertToXML(qualifiedName) << "</qualifiedname>\n"; + } if (md->memberType() == MemberType_Property) { diff --git a/src/xmlgen.h b/src/xmlgen.h index b28384a..7adda71 100644 --- a/src/xmlgen.h +++ b/src/xmlgen.h @@ -38,7 +38,7 @@ class XMLCodeGenerator : public CodeOutputInterface void endFontClass() override; void writeCodeAnchor(const QCString &) override; void writeLineNumber(const QCString &extRef,const QCString &compId, - const QCString &anchorId,int l) override; + const QCString &anchorId,int l,bool writeLineAnchor) override; void setCurrentDoc(const Definition *,const QCString &,bool) override {} void addWord(const QCString &,bool) override {} void startCodeFragment(const QCString &) override; |