summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/commands.doc10
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/classdef.cpp65
-rw-r--r--src/classdef.h4
-rw-r--r--src/code.l80
-rw-r--r--src/commentscan.l35
-rw-r--r--src/conceptdef.cpp733
-rw-r--r--src/conceptdef.h82
-rw-r--r--src/context.cpp5
-rw-r--r--src/definition.h3
-rw-r--r--src/dirdef.cpp4
-rw-r--r--src/docbookgen.cpp24
-rw-r--r--src/docbookgen.h2
-rw-r--r--src/doxygen.cpp244
-rw-r--r--src/doxygen.h2
-rw-r--r--src/entry.h4
-rw-r--r--src/filedef.cpp48
-rw-r--r--src/filedef.h10
-rw-r--r--src/ftvhelp.cpp4
-rw-r--r--src/groupdef.cpp71
-rw-r--r--src/groupdef.h5
-rw-r--r--src/htmlgen.cpp13
-rw-r--r--src/htmlgen.h2
-rw-r--r--src/index.cpp305
-rw-r--r--src/index.h5
-rw-r--r--src/latexgen.cpp37
-rw-r--r--src/latexgen.h2
-rw-r--r--src/layout.cpp57
-rw-r--r--src/layout.h12
-rw-r--r--src/mangen.h2
-rw-r--r--src/memberdef.cpp4
-rw-r--r--src/namespacedef.cpp58
-rw-r--r--src/namespacedef.h6
-rw-r--r--src/outputgen.h2
-rw-r--r--src/outputlist.h4
-rw-r--r--src/parserintf.h2
-rw-r--r--src/perlmodgen.cpp62
-rw-r--r--src/rtfgen.cpp42
-rw-r--r--src/rtfgen.h2
-rw-r--r--src/scanner.l58
-rw-r--r--src/searchindex.cpp18
-rw-r--r--src/searchindex.h2
-rw-r--r--src/sqlite3gen.cpp39
-rw-r--r--src/tagreader.cpp79
-rw-r--r--src/translator.h12
-rw-r--r--src/translator_adapter.h30
-rw-r--r--src/translator_br.h10
-rw-r--r--src/translator_en.h45
-rw-r--r--src/translator_nl.h40
-rw-r--r--src/translator_pt.h10
-rw-r--r--src/translator_sv.h2
-rw-r--r--src/util.cpp84
-rw-r--r--src/util.h8
-rw-r--r--src/xmlgen.cpp108
-rw-r--r--templates/general/layout_default.xml14
-rw-r--r--templates/html/doxygen.css6
-rw-r--r--templates/xml/compound.xsd4
-rw-r--r--templates/xml/index.xsd1
58 files changed, 2466 insertions, 157 deletions
diff --git a/doc/commands.doc b/doc/commands.doc
index 1465a1e..b9ffc3e 100644
--- a/doc/commands.doc
+++ b/doc/commands.doc
@@ -60,6 +60,7 @@ documentation:
\refitem cmdcite \\cite
\refitem cmdclass \\class
\refitem cmdcode \\code
+\refitem cmdconcept \\concept
\refitem cmdcond \\cond
\refitem cmdcopybrief \\copybrief
\refitem cmdcopydetails \\copydetails
@@ -457,6 +458,15 @@ Structural indicators
\endlatexonly
<hr>
+\section cmdconcept \\concept <name>
+
+ \addindex \\concept
+ Indicates that a comment block contains documentation for a
+ C++20 concept with name \<name\>.
+ See also the \ref cmdheaderfile "\\headerfile" command to specify the
+ header a user should be included to use the concept.
+
+<hr>
\section cmddef \\def <name>
\addindex \\def
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 868cd04..1840648 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -224,6 +224,7 @@ add_library(doxymain STATIC
classdef.cpp
classlist.cpp
cmdmapper.cpp
+ conceptdef.cpp
condparser.cpp
context.cpp
cppvalue.cpp
diff --git a/src/classdef.cpp b/src/classdef.cpp
index 6432e2a..f7af740 100644
--- a/src/classdef.cpp
+++ b/src/classdef.cpp
@@ -188,7 +188,7 @@ class ClassDefImpl : public DefinitionMixin<ClassDefMutable>
virtual bool isVisibleInHierarchy() const;
virtual bool visibleInParentsDeclList() const;
virtual const ArgumentList &templateArguments() const;
- virtual NamespaceDef *getNamespaceDef() const;
+ //virtual NamespaceDef *getNamespaceDef() const;
virtual FileDef *getFileDef() const;
virtual const MemberDef *getMemberByName(const QCString &) const;
virtual bool isBaseClass(const ClassDef *bcd,bool followInstances,int level=0) const;
@@ -250,7 +250,7 @@ class ClassDefImpl : public DefinitionMixin<ClassDefMutable>
virtual void insertUsedFile(const FileDef *);
virtual bool addExample(const char *anchor,const char *name, const char *file);
virtual void mergeCategory(ClassDef *category);
- virtual void setNamespace(NamespaceDef *nd);
+ //virtual void setNamespace(NamespaceDef *nd);
virtual void setFileDef(FileDef *fd);
virtual void setSubGrouping(bool enabled);
virtual void setProtection(Protection p);
@@ -355,6 +355,8 @@ class ClassDefImpl : public DefinitionMixin<ClassDefMutable>
QCString &title,QCString &subtitle) const;
QCString includeStatement() const;
void addTypeConstraint(const QCString &typeConstraint,const QCString &type);
+ void writeTemplateSpec(OutputList &ol,const Definition *d,
+ const QCString &type,SrcLangExt lang) const;
// PIMPL idiom
class IMPL;
@@ -428,8 +430,8 @@ class ClassDefAliasImpl : public DefinitionAliasMixin<ClassDef>
{ return getCdAlias()->visibleInParentsDeclList(); }
virtual const ArgumentList &templateArguments() const
{ return getCdAlias()->templateArguments(); }
- virtual NamespaceDef *getNamespaceDef() const
- { return getCdAlias()->getNamespaceDef(); }
+ //virtual NamespaceDef *getNamespaceDef() const
+ //{ return getCdAlias()->getNamespaceDef(); }
virtual FileDef *getFileDef() const
{ return getCdAlias()->getFileDef(); }
virtual const MemberDef *getMemberByName(const QCString &s) const
@@ -551,8 +553,6 @@ class ClassDefAliasImpl : public DefinitionAliasMixin<ClassDef>
virtual void updateSubClasses(const BaseClassList &) {}
};
-
-
ClassDef *createClassDefAlias(const Definition *newScope,const ClassDef *cd)
{
ClassDef *acd = new ClassDefAliasImpl(newScope,cd);
@@ -605,7 +605,7 @@ class ClassDefImpl::IMPL
/*! Namespace this class is part of
* (this is the inner most namespace in case of nested namespaces)
*/
- NamespaceDef *nspace = 0;
+ //NamespaceDef *nspace = 0;
/*! File this class is defined in */
FileDef *fileDef = 0;
@@ -725,7 +725,7 @@ void ClassDefImpl::IMPL::init(const char *defFileName, const char *name,
fileName=ctStr+name;
}
prot=Public;
- nspace=0;
+ //nspace=0;
fileDef=0;
subGrouping=Config_getBool(SUBGROUPING);
templateMaster =0;
@@ -1296,15 +1296,15 @@ static void searchTemplateSpecs(/*in*/ const Definition *d,
}
}
-static void writeTemplateSpec(OutputList &ol,const Definition *d,
- const QCString &type,SrcLangExt lang)
+void ClassDefImpl::writeTemplateSpec(OutputList &ol,const Definition *d,
+ const QCString &type,SrcLangExt lang) const
{
ArgumentLists specs;
QCString name;
searchTemplateSpecs(d,specs,name,lang);
if (!specs.empty()) // class has template scope specifiers
{
- ol.startSubsubsection();
+ ol.startCompoundTemplateParams();
for (const ArgumentList &al : specs)
{
ol.docify("template<");
@@ -1312,7 +1312,13 @@ static void writeTemplateSpec(OutputList &ol,const Definition *d,
while (it!=al.end())
{
Argument a = *it;
- ol.docify(a.type);
+ linkifyText(TextGeneratorOLImpl(ol), // out
+ d, // scope
+ getFileDef(), // fileScope
+ this, // self
+ a.type, // text
+ FALSE // autoBreak
+ );
if (!a.name.isEmpty())
{
ol.docify(" ");
@@ -1329,9 +1335,20 @@ static void writeTemplateSpec(OutputList &ol,const Definition *d,
ol.docify(">");
ol.lineBreak();
}
+ if (!m_impl->requiresClause.isEmpty())
+ {
+ ol.docify("requires ");
+ linkifyText(TextGeneratorOLImpl(ol), // out
+ d, // scope
+ getFileDef(), // fileScope
+ this, // self
+ m_impl->requiresClause, // text
+ FALSE // autoBreak
+ );
+ ol.lineBreak();
+ }
ol.docify(type.lower()+" "+name);
- ol.endSubsubsection();
- ol.writeString("\n");
+ ol.endCompoundTemplateParams();
}
}
@@ -2557,11 +2574,14 @@ void ClassDefImpl::writeDocumentationContents(OutputList &ol,const QCString & /*
case LayoutDocEntry::NamespaceNestedNamespaces:
case LayoutDocEntry::NamespaceNestedConstantGroups:
case LayoutDocEntry::NamespaceClasses:
+ case LayoutDocEntry::NamespaceConcepts:
case LayoutDocEntry::NamespaceInterfaces:
case LayoutDocEntry::NamespaceStructs:
case LayoutDocEntry::NamespaceExceptions:
case LayoutDocEntry::NamespaceInlineClasses:
+ case LayoutDocEntry::ConceptDefinition:
case LayoutDocEntry::FileClasses:
+ case LayoutDocEntry::FileConcepts:
case LayoutDocEntry::FileInterfaces:
case LayoutDocEntry::FileStructs:
case LayoutDocEntry::FileExceptions:
@@ -2573,6 +2593,7 @@ void ClassDefImpl::writeDocumentationContents(OutputList &ol,const QCString & /*
case LayoutDocEntry::FileSourceLink:
case LayoutDocEntry::FileInlineClasses:
case LayoutDocEntry::GroupClasses:
+ case LayoutDocEntry::GroupConcepts:
case LayoutDocEntry::GroupInlineClasses:
case LayoutDocEntry::GroupNamespaces:
case LayoutDocEntry::GroupDirs:
@@ -4557,10 +4578,10 @@ const ArgumentList &ClassDefImpl::templateArguments() const
return m_impl->tempArgs;
}
-NamespaceDef *ClassDefImpl::getNamespaceDef() const
-{
- return m_impl->nspace;
-}
+//NamespaceDef *ClassDefImpl::getNamespaceDef() const
+//{
+// return m_impl->nspace;
+//}
FileDef *ClassDefImpl::getFileDef() const
{
@@ -4667,10 +4688,10 @@ const MemberGroupList &ClassDefImpl::getMemberGroups() const
return m_impl->memberGroups;
}
-void ClassDefImpl::setNamespace(NamespaceDef *nd)
-{
- m_impl->nspace = nd;
-}
+//void ClassDefImpl::setNamespace(NamespaceDef *nd)
+//{
+// m_impl->nspace = nd;
+//}
void ClassDefImpl::setFileDef(FileDef *fd)
{
diff --git a/src/classdef.h b/src/classdef.h
index b3e3325..c908a70 100644
--- a/src/classdef.h
+++ b/src/classdef.h
@@ -211,7 +211,7 @@ class ClassDef : public Definition
/** Returns the namespace this compound is in, or 0 if it has a global
* scope.
*/
- virtual NamespaceDef *getNamespaceDef() const = 0;
+ //virtual NamespaceDef *getNamespaceDef() const = 0;
/** Returns the file in which this compound's definition can be found.
* Should not return 0 (but it might be a good idea to check anyway).
@@ -389,7 +389,7 @@ class ClassDefMutable : public DefinitionMutable, public ClassDef
//-----------------------------------------------------------------------------------
virtual void setIncludeFile(FileDef *fd,const char *incName,bool local,bool force) = 0;
- virtual void setNamespace(NamespaceDef *nd) = 0;
+ //virtual void setNamespace(NamespaceDef *nd) = 0;
virtual void setFileDef(FileDef *fd) = 0;
virtual void setSubGrouping(bool enabled) = 0;
virtual void setProtection(Protection p) = 0;
diff --git a/src/code.l b/src/code.l
index 6632018..87cc333 100644
--- a/src/code.l
+++ b/src/code.l
@@ -270,7 +270,7 @@ 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"|{KEYWORD_OBJC})
+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"|{KEYWORD_OBJC})
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")
@@ -362,6 +362,7 @@ ENDQopt ("const"|"volatile"|"sealed"|"override")({BN}+("const"|"volatile"|"seale
%x ObjCSkipStr
%x ObjCCallComment
%x OldStyleArgs
+%x ConceptName
%x UsingName
%x RawString
%x InlineInit
@@ -908,12 +909,23 @@ ENDQopt ("const"|"volatile"|"sealed"|"override")({BN}+("const"|"volatile"|"seale
yyextra->insideTemplate=TRUE;
yyextra->sharpCount=0;
}
+<Body>"concept"{BN}+ {
+ startFontClass(yyscanner,"keyword");
+ codifyLines(yyscanner,yytext);
+ endFontClass(yyscanner);
+ BEGIN(ConceptName);
+ }
<Body>"using"{BN}+"namespace"{BN}+ {
startFontClass(yyscanner,"keyword");
codifyLines(yyscanner,yytext);
endFontClass(yyscanner);
BEGIN(UsingName);
}
+<ConceptName>{ID}("::"{ID})* {
+ addUsingDirective(yyscanner,yytext);
+ generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext);
+ }
+<ConceptName>"=" { codifyLines(yyscanner,yytext); BEGIN(Body); }
<UsingName>{ID}("::"{ID})* {
addUsingDirective(yyscanner,yytext);
generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext);
@@ -1295,7 +1307,7 @@ ENDQopt ("const"|"volatile"|"sealed"|"override")({BN}+("const"|"volatile"|"seale
<MemberCall>{SCOPENAME}/{B}* {
if (yyextra->theCallContext.getScope().globalDef())
{
- DBG_CTX((stderr,"yyextra->theCallContext.getClass()=%p\n",yyextra->theCallContext.getScope().globalDef()));
+ DBG_CTX((stderr,"yyextra->theCallContext.getClass()=%p\n",(void*)yyextra->theCallContext.getScope().globalDef()));
if (!generateClassMemberLink(yyscanner,*yyextra->code,yyextra->theCallContext.getScope().globalDef(),yytext))
{
yyextra->code->codify(yytext);
@@ -1753,6 +1765,11 @@ ENDQopt ("const"|"volatile"|"sealed"|"override")({BN}+("const"|"volatile"|"seale
endFontClass(yyscanner);
yyextra->inFunctionTryBlock=TRUE;
}
+<CallEnd>"requires" { // function-try-block
+ startFontClass(yyscanner,"keyword");
+ yyextra->code->codify(yytext);
+ endFontClass(yyscanner);
+ }
<CallEnd>{ID} {
if (yyextra->insideBody || !yyextra->parmType.isEmpty())
{
@@ -2356,7 +2373,7 @@ static void startCodeLine(yyscan_t yyscanner)
//lineAnchor.sprintf("l%05d",yyextra->yyLineNr);
const Definition *d = yyextra->sourceFileDef->getSourceDefinition(yyextra->yyLineNr);
- DBG_CTX((stderr,"%s:startCodeLine(%d)=%p\n",yyextra->sourceFileDef->name().data(),yyextra->yyLineNr,d));
+ DBG_CTX((stderr,"%s:startCodeLine(%d)=%p\n",yyextra->sourceFileDef->name().data(),yyextra->yyLineNr,(void*)d));
if (!yyextra->includeCodeFragment && d)
{
yyextra->currentDefinition = d;
@@ -2502,13 +2519,13 @@ static void writeMultiLineCodeLink(yyscan_t yyscanner,CodeOutputInterface &ol,
{
yyextra->yyLineNr++;
*(p-1)='\0';
- DBG_CTX((stderr,"writeCodeLink(%s,%s,%s,%s)\n",ref,file,anchor,sp));
+ DBG_CTX((stderr,"writeCodeLink(%s,%s,%s,%s)\n",ref.data(),file.data(),anchor.data(),sp));
ol.writeCodeLink(ref,file,anchor,sp,tooltip);
nextCodeLine(yyscanner);
}
else
{
- DBG_CTX((stderr,"writeCodeLink(%s,%s,%s,%s)\n",ref,file,anchor,sp));
+ DBG_CTX((stderr,"writeCodeLink(%s,%s,%s,%s)\n",ref.data(),file.data(),anchor.data(),sp));
ol.writeCodeLink(ref,file,anchor,sp,tooltip);
done=TRUE;
}
@@ -2586,7 +2603,7 @@ static const ClassDef *stripClassName(yyscan_t yyscanner,const char *s,const Def
{
cd=yyextra->symbolResolver.resolveClass(d,clName);
}
- DBG_CTX((stderr,"stripClass trying '%s' = %p\n",clName.data(),cd));
+ DBG_CTX((stderr,"stripClass trying '%s' = %p\n",clName.data(),(void*)cd));
if (cd)
{
return cd;
@@ -2767,7 +2784,7 @@ static bool getLinkInScope(yyscan_t yyscanner,
{
yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,md->typeString(),md->getOuterScope())));
DBG_CTX((stderr,"yyextra->currentDefinition=%p yyextra->currentMemberDef=%p yyextra->insideBody=%d\n",
- yyextra->currentDefinition,yyextra->currentMemberDef,yyextra->insideBody));
+ (void*)yyextra->currentDefinition,(void*)yyextra->currentMemberDef,yyextra->insideBody));
if (yyextra->currentDefinition && yyextra->currentMemberDef &&
md!=yyextra->currentMemberDef && yyextra->insideBody && yyextra->collectXRefs)
@@ -2858,9 +2875,11 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner,
DBG_CTX((stderr,"non-local variable name=%s cd=%s md=%s!\n",
className.data(),cd?cd->name().data():"<none>",
md?md->name().data():"<none>"));
- if (cd==0 && md==0 && (i=className.find('<'))!=-1)
+ i=className.find('<');
+ QCString bareName = className;
+ if (i!=-1) bareName = bareName.left(i);
+ if (cd==0 && md==0 && i!=-1)
{
- QCString bareName = className.left(i); //stripTemplateSpecifiersFromScope(className);
DBG_CTX((stderr,"bareName=%s\n",bareName.data()));
if (bareName!=className)
{
@@ -2876,6 +2895,14 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner,
writeMultiLineCodeLink(yyscanner,*yyextra->code,nd,clName);
return;
}
+ const ConceptDef *conceptDef = getResolvedConcept(d,bareName);
+ if (conceptDef && conceptDef->isLinkable())
+ {
+ yyextra->theCallContext.setScope(ScopedTypeVariant(conceptDef));
+ addToSearchIndex(yyscanner,className);
+ writeMultiLineCodeLink(yyscanner,*yyextra->code,conceptDef,clName);
+ return;
+ }
DBG_CTX((stderr,"md=%s\n",md?md->name().data():"<none>"));
DBG_CTX((stderr,"is found as a type cd=%s nd=%s\n",
cd?cd->name().data():"<null>",
@@ -2905,7 +2932,7 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner,
//}
}
isLocal=TRUE;
- DBG_CTX((stderr,"is a local variable cd=%p!\n",cd));
+ DBG_CTX((stderr,"is a local variable cd=%p!\n",(void*)cd));
}
yyextra->isPrefixedWithThis = FALSE; // discard the "this" prefix for the next calls
@@ -2944,13 +2971,13 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner,
}
else // not a class, maybe a global member
{
- DBG_CTX((stderr,"class %s not linkable! cd=%p md=%p typeOnly=%d\n",clName,cd,md,typeOnly));
+ DBG_CTX((stderr,"class %s not linkable! cd=%p md=%p typeOnly=%d\n",clName,(void*)cd,(void*)md,typeOnly));
if (!isLocal && (md!=0 || (cd==0 && !typeOnly))) // not a class, see if it is a global enum/variable/typedef.
{
if (md==0) // not found as a typedef
{
md = setCallContextForVar(yyscanner,clName);
- DBG_CTX((stderr,"setCallContextForVar(%s) md=%p yyextra->currentDefinition=%p\n",clName,md,yyextra->currentDefinition));
+ DBG_CTX((stderr,"setCallContextForVar(%s) md=%p yyextra->currentDefinition=%p\n",clName,(void*)md,(void*)yyextra->currentDefinition));
if (md && yyextra->currentDefinition)
{
DBG_CTX((stderr,"%s accessible from %s? %d md->getOuterScope=%s\n",
@@ -2967,7 +2994,7 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner,
}
if (md && (!varOnly || md->isVariable()))
{
- DBG_CTX((stderr,"is a global md=%p yyextra->currentDefinition=%s linkable=%d\n",md,yyextra->currentDefinition?yyextra->currentDefinition->name().data():"<none>",md->isLinkable()));
+ DBG_CTX((stderr,"is a global md=%p yyextra->currentDefinition=%s linkable=%d\n",(void*)md,yyextra->currentDefinition?yyextra->currentDefinition->name().data():"<none>",md->isLinkable()));
if (md->isLinkable())
{
QCString text=clName;
@@ -3019,7 +3046,7 @@ static bool generateClassMemberLink(yyscan_t yyscanner,
}
const ClassDef *typeClass = stripClassName(yyscanner,removeAnonymousScopes(xmd->typeString()),xmd->getOuterScope());
- DBG_CTX((stderr,"%s -> typeName=%p\n",xmd->typeString(),typeClass));
+ DBG_CTX((stderr,"%s -> typeName=%p\n",xmd->typeString(),(void*)typeClass));
yyextra->theCallContext.setScope(ScopedTypeVariant(typeClass));
const Definition *xd = xmd->getOuterScope()==Doxygen::globalScope ?
@@ -3028,7 +3055,8 @@ static bool generateClassMemberLink(yyscan_t yyscanner,
if (xd && xd->isLinkable())
{
- DBG_CTX((stderr,"yyextra->currentDefinition=%p yyextra->currentMemberDef=%p xmd=%p yyextra->insideBody=%d\n",yyextra->currentDefinition,yyextra->currentMemberDef,xmd,yyextra->insideBody));
+ DBG_CTX((stderr,"yyextra->currentDefinition=%p yyextra->currentMemberDef=%p xmd=%p yyextra->insideBody=%d\n",
+ (void*)yyextra->currentDefinition,(void*)yyextra->currentMemberDef,(void*)xmd,yyextra->insideBody));
if (xmd->templateMaster()) xmd = xmd->templateMaster();
@@ -3062,7 +3090,7 @@ static bool generateClassMemberLink(yyscan_t yyscanner,
{
const ClassDef *cd = toClassDef(def);
const MemberDef *xmd = cd->getMemberByName(memName);
- DBG_CTX((stderr,"generateClassMemberLink(class=%s,member=%s)=%p\n",def->name().data(),memName,xmd));
+ DBG_CTX((stderr,"generateClassMemberLink(class=%s,member=%s)=%p\n",def->name().data(),memName,(void*)xmd));
if (xmd)
{
return generateClassMemberLink(yyscanner,ol,xmd,memName);
@@ -3167,7 +3195,7 @@ static void generateMemberLink(yyscan_t yyscanner,
}
if (vmn)
{
- DBG_CTX((stderr,"There is a variable with name '%s'\n",varName));
+ DBG_CTX((stderr,"There is a variable with name '%s'\n",varName.data()));
for (const auto &vmd : *vmn)
{
if (vmd->getClassDef()==vcd)
@@ -3382,7 +3410,7 @@ static void writeObjCMethodCall(yyscan_t yyscanner,ObjCCallCtx *ctx)
ctx->objectType = yyextra->symbolResolver.resolveClass(yyextra->currentDefinition,ctx->objectTypeOrName);
ctx->method = yyextra->symbolResolver.getTypedef();
}
- DBG_CTX((stderr," object is class? %p\n",ctx->objectType));
+ DBG_CTX((stderr," object is class? %p\n",(void*)ctx->objectType));
if (ctx->objectType) // found class
{
ctx->method = ctx->objectType->getMemberByName(ctx->methodName);
@@ -3391,20 +3419,20 @@ static void writeObjCMethodCall(yyscan_t yyscanner,ObjCCallCtx *ctx)
else if (ctx->method==0) // search for class variable with the same name
{
DBG_CTX((stderr," no\n"));
- DBG_CTX((stderr,"yyextra->currentDefinition=%p\n",yyextra->currentDefinition));
+ DBG_CTX((stderr,"yyextra->currentDefinition=%p\n",(void*)yyextra->currentDefinition));
if (yyextra->currentDefinition &&
yyextra->currentDefinition->definitionType()==Definition::TypeClass)
{
ctx->objectVar = (toClassDef(yyextra->currentDefinition))->getMemberByName(ctx->objectTypeOrName);
- DBG_CTX((stderr," ctx->objectVar=%p\n",ctx->objectVar));
+ DBG_CTX((stderr," ctx->objectVar=%p\n",(void*)ctx->objectVar));
if (ctx->objectVar)
{
ctx->objectType = stripClassName(yyscanner,ctx->objectVar->typeString(),yyextra->currentDefinition);
- DBG_CTX((stderr," ctx->objectType=%p\n",ctx->objectType));
+ DBG_CTX((stderr," ctx->objectType=%p\n",(void*)ctx->objectType));
if (ctx->objectType && !ctx->methodName.isEmpty())
{
ctx->method = ctx->objectType->getMemberByName(ctx->methodName);
- DBG_CTX((stderr," ctx->method=%p\n",ctx->method));
+ DBG_CTX((stderr," ctx->method=%p\n",(void*)ctx->method));
}
}
}
@@ -3420,7 +3448,7 @@ static void writeObjCMethodCall(yyscan_t yyscanner,ObjCCallCtx *ctx)
{
ctx->method = cd->getMemberByName(ctx->methodName);
}
- DBG_CTX((stderr," class=%p method=%p\n",cd,ctx->method));
+ DBG_CTX((stderr," class=%p method=%p\n",(void*)cd,(void*)ctx->method));
}
}
}
@@ -3595,7 +3623,7 @@ static void writeObjCMethodCall(yyscan_t yyscanner,ObjCCallCtx *ctx)
ctx->method = ctx->objectType->getMemberByName(ctx->methodName);
}
}
- DBG_CTX((stderr," ***** method=%s -> object=%p\n",ictx->method->name().data(),ctx->objectType));
+ DBG_CTX((stderr," ***** method=%s -> object=%p\n",(void*)ictx->method->name().data(),(void*)ctx->objectType));
}
}
else
@@ -3820,7 +3848,7 @@ void CCodeParser::parseCode(CodeOutputInterface &od,const char *className,const
yyscan_t yyscanner = p->yyscanner;
struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
DBG_CTX((stderr,"***parseCode() exBlock=%d exName=%s fd=%p className=%s searchCtx=%s\n",
- exBlock,exName,fd,className,searchCtx?searchCtx->name().data():"<none>"));
+ exBlock,exName,(void*)fd,className,searchCtx?searchCtx->name().data():"<none>"));
if (s.isEmpty()) return;
@@ -3873,7 +3901,7 @@ void CCodeParser::parseCode(CodeOutputInterface &od,const char *className,const
{
setCurrentDoc(yyscanner,"l00001");
}
- yyextra->currentDefinition = 0;
+ yyextra->currentDefinition = getResolvedNamespace(className);
yyextra->currentMemberDef = 0;
yyextra->searchingForBody = exBlock;
yyextra->insideBody = FALSE;
diff --git a/src/commentscan.l b/src/commentscan.l
index de359b6..dc16d4c 100644
--- a/src/commentscan.l
+++ b/src/commentscan.l
@@ -68,6 +68,7 @@ static bool handleAddToGroup(yyscan_t yyscanner,const QCString &, const StringVe
static bool handleWeakGroup(yyscan_t yyscanner,const QCString &, const StringVector &);
static bool handleNamespace(yyscan_t yyscanner,const QCString &, const StringVector &);
static bool handlePackage(yyscan_t yyscanner,const QCString &, const StringVector &);
+static bool handleConcept(yyscan_t yyscanner,const QCString &, const StringVector &);
static bool handleClass(yyscan_t yyscanner,const QCString &, const StringVector &);
static bool handleHeaderFile(yyscan_t yyscanner,const QCString &, const StringVector &);
static bool handleProtocol(yyscan_t yyscanner,const QCString &, const StringVector &);
@@ -176,6 +177,7 @@ static const std::map< std::string, DocCmdMap > docCmdMap =
{ "cite", { &handleCite, CommandSpacing::Inline }},
{ "class", { &handleClass, CommandSpacing::Invisible }},
{ "code", { &handleFormatBlock, CommandSpacing::Block }},
+ { "concept", { &handleConcept, CommandSpacing::Invisible }},
{ "copybrief", { &handleCopyBrief, CommandSpacing::Invisible }},
{ "copydetails", { &handleCopyDetails, CommandSpacing::Block }},
{ "copydoc", { &handleCopyDoc, CommandSpacing::Block }},
@@ -518,6 +520,7 @@ STopt [^\n@\\]*
%x EnumDocArg1
%x NameSpaceDocArg1
%x PackageDocArg1
+%x ConceptDocArg1
%x GroupDocArg1
%x GroupDocArg2
%x SectionLabel
@@ -1024,6 +1027,28 @@ STopt [^\n@\\]*
<PackageDocArg1>. { // ignore other stuff
}
+ /* ------------ handle argument of concept command --------------- */
+
+<ConceptDocArg1>{SCOPEID} { // handle argument
+ yyextra->current->name = yytext;
+ BEGIN( Comment );
+ }
+<ConceptDocArg1>{LC} { // line continuation
+ yyextra->lineNr++;
+ addOutput(yyscanner,'\n');
+ }
+<ConceptDocArg1>{DOCNL} { // missing argument
+ warn(yyextra->fileName,yyextra->lineNr,
+ "missing argument after "
+ "\\concept."
+ );
+ unput_string(yytext,yyleng);
+ BEGIN( Comment );
+ }
+<ConceptDocArg1>. { // ignore other stuff
+ }
+
+
/* ------ handle argument of class/struct/union command --------------- */
<ClassDocArg1>{SCOPENAME}{TMPLSPEC} {
@@ -1994,6 +2019,15 @@ static bool handleClass(yyscan_t yyscanner,const QCString &cmd, const StringVect
return stop;
}
+static bool handleConcept(yyscan_t yyscanner,const QCString &cmd, const StringVector &)
+{
+ struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
+ bool stop=makeStructuralIndicator(yyscanner,Entry::CONCEPTDOC_SEC);
+ yyextra->currentCmd = cmd;
+ BEGIN( ConceptDocArg1 );
+ return stop;
+}
+
static bool handleHeaderFile(yyscan_t yyscanner,const QCString &, const StringVector &)
{
struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
@@ -2774,6 +2808,7 @@ static bool getDocSectionName(int s)
case Entry::DIRDOC_SEC:
case Entry::EXAMPLE_SEC:
case Entry::MEMBERGRP_SEC:
+ case Entry::CONCEPTDOC_SEC:
return TRUE;
default:
return FALSE;
diff --git a/src/conceptdef.cpp b/src/conceptdef.cpp
new file mode 100644
index 0000000..c92237f
--- /dev/null
+++ b/src/conceptdef.cpp
@@ -0,0 +1,733 @@
+/******************************************************************************
+ *
+ * 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
+ * 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.
+ *
+ */
+
+#include "conceptdef.h"
+#include "definitionimpl.h"
+#include "util.h"
+#include "config.h"
+#include "doxygen.h"
+#include "language.h"
+#include "outputlist.h"
+#include "searchindex.h"
+#include "message.h"
+#include "parserintf.h"
+
+//------------------------------------------------------------------------------------
+
+class ConceptDefImpl : public DefinitionMixin<ConceptDefMutable>
+{
+ public:
+ ConceptDefImpl(const char *fileName,int startLine,int startColumn,
+ const char *name,const char *tagRef=0,const char *tagFile=0);
+ ~ConceptDefImpl();
+
+ virtual ConceptDef *resolveAlias() { return this; }
+
+ //---------- ConceptDef
+ virtual DefType definitionType() const;
+ virtual QCString getOutputFileBase() const;
+ virtual bool hasDetailedDescription() const;
+ virtual QCString displayName(bool includeScope=true) const;
+ virtual const IncludeInfo *includeInfo() const;
+ virtual ArgumentList getTemplateParameterList() const;
+ virtual QCString anchor() const;
+ virtual bool isLinkableInProject() const;
+ virtual bool isLinkable() const;
+ virtual QCString initializer() const;
+ virtual void writeDeclarationLink(OutputList &ol,bool &found,
+ const char *header,bool localNames) const;
+ virtual const NamespaceDef *getNamespaceDef() const;
+ virtual const FileDef *getFileDef() const;
+
+ //---------- ConceptDefMutable
+ virtual void setIncludeFile(FileDef *fd,const char *incName,bool local,bool force);
+ virtual void setTemplateArguments(const ArgumentList &al);
+ virtual void setNamespace(NamespaceDef *nd);
+ virtual void setFileDef(FileDef *fd);
+ virtual void writeTagFile(TextStream &);
+ virtual void writeDocumentation(OutputList &);
+ virtual void setInitializer(const char *init);
+ virtual void findSectionsInDocumentation();
+
+ //---------- Helpers
+ void writeBriefDescription(OutputList &) const;
+ void writeAuthorSection(OutputList &ol) const;
+ void writeIncludeFiles(OutputList &ol) const;
+ void writeDetailedDescription(OutputList &ol,const QCString &title) const;
+ void writeDefinition(OutputList &ol,const QCString &title) const;
+
+ private:
+ QCString m_fileName;
+ std::unique_ptr<IncludeInfo> m_incInfo;
+ NamespaceDef *m_nspace = 0;
+ FileDef *m_fileDef = 0;
+ ArgumentList m_tArgList;
+ QCString m_initializer;
+};
+
+ConceptDefMutable *createConceptDef(
+ const char *fileName,int startLine,int startColumn,
+ const char *name, const char *tagRef,const char *tagFile)
+{
+ return new ConceptDefImpl(fileName,startLine,startColumn,name,tagRef,tagFile);
+}
+
+//------------------------------------------------------------------------------------
+
+class ConceptDefAliasImpl : public DefinitionAliasMixin<ConceptDef>
+{
+ public:
+ ConceptDefAliasImpl(const Definition *newScope,const ConceptDef *cd)
+ : DefinitionAliasMixin(newScope,cd) { init(); }
+ virtual ~ConceptDefAliasImpl() { deinit(); }
+
+ const ConceptDef *getCdAlias() const { return toConceptDef(getAlias()); }
+ virtual ConceptDef *resolveAlias() { return const_cast<ConceptDef*>(getCdAlias()); }
+
+ virtual DefType definitionType() const { return TypeConcept; }
+ virtual QCString getOutputFileBase() const
+ { return getCdAlias()->getOutputFileBase(); }
+ virtual QCString getReference() const
+ { return getCdAlias()->getReference(); }
+ virtual bool isReference() const
+ { return getCdAlias()->isReference(); }
+ virtual bool hasDetailedDescription() const
+ { return getCdAlias()->hasDetailedDescription(); }
+ virtual QCString displayName(bool includeScope=true) const
+ { return getCdAlias()->displayName(includeScope); }
+ virtual const IncludeInfo *includeInfo() const
+ { return getCdAlias()->includeInfo(); }
+ virtual ArgumentList getTemplateParameterList() const
+ { return getCdAlias()->getTemplateParameterList(); }
+ virtual QCString anchor() const
+ { return getCdAlias()->anchor(); }
+ virtual bool isLinkableInProject() const
+ { return getCdAlias()->isLinkableInProject(); }
+ virtual bool isLinkable() const
+ { return getCdAlias()->isLinkable(); }
+ virtual QCString initializer() const
+ { return getCdAlias()->initializer(); }
+ virtual const NamespaceDef *getNamespaceDef() const
+ { return getCdAlias()->getNamespaceDef(); }
+ virtual const FileDef *getFileDef() const
+ { return getCdAlias()->getFileDef(); }
+ virtual void writeDeclarationLink(OutputList &ol,bool &found,
+ const char *header,bool localNames) const
+ { getCdAlias()->writeDeclarationLink(ol,found,header,localNames); }
+};
+
+ConceptDef *createConceptDefAlias(const Definition *newScope,const ConceptDef *cd)
+{
+ ConceptDef *acd = new ConceptDefAliasImpl(newScope,cd);
+ return acd;
+}
+
+//------------------------------------------------------------------------------------
+
+ConceptDefImpl::ConceptDefImpl(const char *fileName,int startLine,int startColumn,
+ const char *name,const char *tagRef,const char *tagFile) : DefinitionMixin(fileName,startLine,startColumn,name)
+{
+ if (tagFile)
+ {
+ if (tagRef)
+ {
+ m_fileName = stripExtension(tagFile);
+ }
+ else
+ {
+ m_fileName = convertNameToFile(stripExtension(tagFile));
+ }
+ }
+ else
+ {
+ m_fileName = convertNameToFile(QCString("concept")+name);
+ }
+ setReference(tagRef);
+}
+
+ConceptDefImpl::~ConceptDefImpl()
+{
+}
+
+Definition::DefType ConceptDefImpl::definitionType() const
+{
+ return TypeConcept;
+}
+
+QCString ConceptDefImpl::getOutputFileBase() const
+{
+ return m_fileName;
+}
+
+bool ConceptDefImpl::hasDetailedDescription() const
+{
+ bool repeatBrief = Config_getBool(REPEAT_BRIEF);
+ bool sourceBrowser = Config_getBool(SOURCE_BROWSER);
+ return ((!briefDescription().isEmpty() && repeatBrief) ||
+ !documentation().isEmpty() ||
+ (sourceBrowser && getStartBodyLine()!=-1 && getBodyDef()));
+}
+
+QCString ConceptDefImpl::anchor() const
+{
+ return "";
+}
+
+QCString ConceptDefImpl::displayName(bool includeScope) const
+{
+ return includeScope ? name() : localName();
+}
+
+const IncludeInfo *ConceptDefImpl::includeInfo() const
+{
+ return m_incInfo.get();
+}
+
+ArgumentList ConceptDefImpl::getTemplateParameterList() const
+{
+ return m_tArgList;
+}
+
+bool ConceptDefImpl::isLinkableInProject() const
+{
+ return hasDocumentation() && !isReference() && !isHidden();
+}
+
+bool ConceptDefImpl::isLinkable() const
+{
+ return isLinkableInProject() || isReference();
+}
+
+void ConceptDefImpl::setIncludeFile(FileDef *fd,const char *incName,bool local,bool force)
+{
+ if (!m_incInfo) m_incInfo = std::make_unique<IncludeInfo>();
+ if ((incName && m_incInfo->includeName.isEmpty()) ||
+ (fd!=0 && m_incInfo->fileDef==0)
+ )
+ {
+ m_incInfo->fileDef = fd;
+ m_incInfo->includeName = incName;
+ m_incInfo->local = local;
+ }
+ if (force && incName)
+ {
+ m_incInfo->includeName = incName;
+ m_incInfo->local = local;
+ }
+}
+
+void ConceptDefImpl::setTemplateArguments(const ArgumentList &al)
+{
+ m_tArgList = al;
+}
+
+void ConceptDefImpl::setNamespace(NamespaceDef *nd)
+{
+ m_nspace = nd;
+}
+
+const NamespaceDef *ConceptDefImpl::getNamespaceDef() const
+{
+ return m_nspace;
+}
+
+void ConceptDefImpl::setFileDef(FileDef *fd)
+{
+ m_fileDef=fd;
+}
+
+const FileDef *ConceptDefImpl::getFileDef() const
+{
+ return m_fileDef;
+}
+
+void ConceptDefImpl::setInitializer(const char *init)
+{
+ m_initializer = init;
+}
+
+QCString ConceptDefImpl::initializer() const
+{
+ return m_initializer;
+}
+
+void ConceptDefImpl::writeTagFile(TextStream &tagFile)
+{
+ tagFile << " <compound kind=\"concept\">\n";
+ tagFile << " <name>" << convertToXML(name()) << "</name>\n";
+ tagFile << " <filename>" << convertToXML(getOutputFileBase()) << Doxygen::htmlFileExtension << "</filename>\n";
+ QCString idStr = id();
+ if (!idStr.isEmpty())
+ {
+ tagFile << " <clangid>" << convertToXML(idStr) << "</clangid>\n";
+ }
+ writeDocAnchorsToTagFile(tagFile);
+ tagFile << " </compound>\n";
+}
+
+void ConceptDefImpl::writeBriefDescription(OutputList &ol) const
+{
+ if (hasBriefDescription())
+ {
+ DocRoot *rootNode = validatingParseDoc(briefFile(),briefLine(),this,0,
+ briefDescription(),TRUE,FALSE,
+ 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT));
+ if (rootNode && !rootNode->isEmpty())
+ {
+ ol.startParagraph();
+ ol.pushGeneratorState();
+ ol.disableAllBut(OutputGenerator::Man);
+ ol.writeString(" - ");
+ ol.popGeneratorState();
+ ol.writeDoc(rootNode,this,0);
+ ol.pushGeneratorState();
+ ol.disable(OutputGenerator::RTF);
+ ol.writeString(" \n");
+ ol.enable(OutputGenerator::RTF);
+
+ if (hasDetailedDescription())
+ {
+ ol.disableAllBut(OutputGenerator::Html);
+ ol.startTextLink(getOutputFileBase(),"details");
+ ol.parseText(theTranslator->trMore());
+ ol.endTextLink();
+ }
+ ol.popGeneratorState();
+ ol.endParagraph();
+ }
+ delete rootNode;
+ }
+ ol.writeSynopsis();
+}
+
+void ConceptDefImpl::writeIncludeFiles(OutputList &ol) const
+{
+ if (m_incInfo)
+ {
+ QCString nm=m_incInfo->includeName.isEmpty() ?
+ (m_incInfo->fileDef ?
+ m_incInfo->fileDef->docName().data() : ""
+ ) :
+ m_incInfo->includeName.data();
+ if (!nm.isEmpty())
+ {
+ ol.startParagraph();
+ ol.startTypewriter();
+ ol.docify("#include ");
+ if (m_incInfo->local)
+ ol.docify("\"");
+ else
+ ol.docify("<");
+ ol.pushGeneratorState();
+ ol.disable(OutputGenerator::Html);
+ ol.docify(nm);
+ ol.disableAllBut(OutputGenerator::Html);
+ ol.enable(OutputGenerator::Html);
+ if (m_incInfo->fileDef)
+ {
+ ol.writeObjectLink(0,m_incInfo->fileDef->includeName(),0,nm);
+ }
+ else
+ {
+ ol.docify(nm);
+ }
+ ol.popGeneratorState();
+ if (m_incInfo->local)
+ ol.docify("\"");
+ else
+ ol.docify(">");
+ ol.endTypewriter();
+ ol.endParagraph();
+ }
+ }
+}
+
+static QCString templateSpec(const ArgumentList &al)
+{
+ TextStream t;
+ t << "template<";
+ bool first=true;
+ for (const auto &a : al)
+ {
+ if (!first) t << ", ";
+ t << a.type;
+ if (!a.name.isEmpty())
+ {
+ t << " " << a.name;
+ }
+ if (a.defval.length()!=0)
+ {
+ t << " " << a.defval;
+ }
+ first=false;
+ }
+ t << ">";
+ return t.str();
+}
+
+void ConceptDefImpl::writeDefinition(OutputList &ol,const QCString &title) const
+{
+ ol.startGroupHeader();
+ ol.parseText(title);
+ ol.endGroupHeader();
+
+ auto intf = Doxygen::parserManager->getCodeParser(".cpp");
+ intf->resetCodeParserState();
+ ol.startCodeFragment("DoxyCode");
+ QCString scopeName;
+ if (getOuterScope()!=Doxygen::globalScope) scopeName=getOuterScope()->name();
+ TextStream conceptDef;
+ conceptDef << templateSpec(m_tArgList);
+ conceptDef << "\nconcept ";
+ conceptDef << name();
+ conceptDef << " = ";
+ conceptDef << m_initializer;
+ intf->parseCode(ol,scopeName,conceptDef.str(),SrcLangExt_Cpp,false,0,
+ m_fileDef, -1,-1,true,0,false,this);
+ ol.endCodeFragment("DoxyCode");
+}
+
+void ConceptDefImpl::writeDetailedDescription(OutputList &ol,const QCString &title) const
+{
+ static bool repeatBrief = Config_getBool(REPEAT_BRIEF);
+ if (hasDetailedDescription())
+ {
+ ol.pushGeneratorState();
+ ol.disable(OutputGenerator::Html);
+ ol.writeRuler();
+ ol.popGeneratorState();
+
+ ol.pushGeneratorState();
+ ol.disableAllBut(OutputGenerator::Html);
+ ol.writeAnchor(0,"details");
+ ol.popGeneratorState();
+
+ ol.startGroupHeader();
+ ol.parseText(title);
+ ol.endGroupHeader();
+
+ ol.startTextBlock();
+ // repeat brief description
+ if (!briefDescription().isEmpty() && repeatBrief)
+ {
+ ol.generateDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE,
+ 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT));
+ }
+ if (!briefDescription().isEmpty() && repeatBrief &&
+ !documentation().isEmpty())
+ {
+ ol.pushGeneratorState();
+ ol.disable(OutputGenerator::Html);
+ ol.writeString("\n\n");
+ ol.popGeneratorState();
+ }
+
+ // write documentation
+ if (!documentation().isEmpty())
+ {
+ ol.generateDoc(docFile(),docLine(),this,0,documentation(),TRUE,FALSE,
+ 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT));
+ }
+
+ writeSourceDef(ol,name());
+ ol.endTextBlock();
+ }
+}
+
+void ConceptDefImpl::writeAuthorSection(OutputList &ol) const
+{
+ // write Author section (Man only)
+ ol.pushGeneratorState();
+ ol.disableAllBut(OutputGenerator::Man);
+ ol.startGroupHeader();
+ ol.parseText(theTranslator->trAuthor(TRUE,TRUE));
+ ol.endGroupHeader();
+ ol.parseText(theTranslator->trGeneratedAutomatically(Config_getString(PROJECT_NAME)));
+ ol.popGeneratorState();
+}
+
+void ConceptDefImpl::writeDocumentation(OutputList &ol)
+{
+ static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW);
+ QCString pageTitle = theTranslator->trConceptReference(displayName());
+ startFile(ol,getOutputFileBase(),name(),pageTitle,HLI_ConceptVisible,!generateTreeView);
+
+ // ---- navigation part
+ if (!generateTreeView)
+ {
+ if (getOuterScope()!=Doxygen::globalScope)
+ {
+ writeNavigationPath(ol);
+ }
+ ol.endQuickIndices();
+ }
+
+ // ---- title part
+ startTitle(ol,getOutputFileBase(),this);
+ ol.parseText(pageTitle);
+ endTitle(ol,getOutputFileBase(),displayName());
+
+ // ---- contents part
+
+ 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))
+ {
+ switch (lde->kind())
+ {
+ case LayoutDocEntry::BriefDesc:
+ writeBriefDescription(ol);
+ break;
+ case LayoutDocEntry::ConceptDefinition:
+ {
+ const LayoutDocEntrySection *ls = (const LayoutDocEntrySection*)lde.get();
+ writeDefinition(ol,ls->title(getLanguage()));
+ }
+ break;
+ case LayoutDocEntry::DetailedDesc:
+ {
+ const LayoutDocEntrySection *ls = (const LayoutDocEntrySection*)lde.get();
+ writeDetailedDescription(ol,ls->title(getLanguage()));
+ }
+ break;
+ case LayoutDocEntry::AuthorSection:
+ writeAuthorSection(ol);
+ break;
+ case LayoutDocEntry::ClassIncludes:
+ writeIncludeFiles(ol);
+ break;
+ case LayoutDocEntry::MemberDeclStart:
+ case LayoutDocEntry::NamespaceClasses:
+ case LayoutDocEntry::NamespaceInterfaces:
+ case LayoutDocEntry::NamespaceStructs:
+ case LayoutDocEntry::NamespaceExceptions:
+ case LayoutDocEntry::NamespaceConcepts:
+ case LayoutDocEntry::NamespaceNestedNamespaces:
+ case LayoutDocEntry::NamespaceNestedConstantGroups:
+ case LayoutDocEntry::MemberGroups:
+ case LayoutDocEntry::MemberDecl:
+ case LayoutDocEntry::MemberDeclEnd:
+ case LayoutDocEntry::MemberDefStart:
+ case LayoutDocEntry::NamespaceInlineClasses:
+ case LayoutDocEntry::MemberDef:
+ case LayoutDocEntry::MemberDefEnd:
+ case LayoutDocEntry::ClassInheritanceGraph:
+ case LayoutDocEntry::ClassNestedClasses:
+ case LayoutDocEntry::ClassCollaborationGraph:
+ case LayoutDocEntry::ClassAllMembersLink:
+ case LayoutDocEntry::ClassUsedFiles:
+ case LayoutDocEntry::ClassInlineClasses:
+ case LayoutDocEntry::FileClasses:
+ case LayoutDocEntry::FileConcepts:
+ case LayoutDocEntry::FileInterfaces:
+ case LayoutDocEntry::FileStructs:
+ case LayoutDocEntry::FileExceptions:
+ case LayoutDocEntry::FileNamespaces:
+ case LayoutDocEntry::FileConstantGroups:
+ case LayoutDocEntry::FileIncludes:
+ case LayoutDocEntry::FileIncludeGraph:
+ case LayoutDocEntry::FileIncludedByGraph:
+ case LayoutDocEntry::FileInlineClasses:
+ case LayoutDocEntry::FileSourceLink:
+ case LayoutDocEntry::GroupClasses:
+ case LayoutDocEntry::GroupConcepts:
+ case LayoutDocEntry::GroupInlineClasses:
+ case LayoutDocEntry::GroupNamespaces:
+ case LayoutDocEntry::GroupDirs:
+ case LayoutDocEntry::GroupNestedGroups:
+ case LayoutDocEntry::GroupFiles:
+ case LayoutDocEntry::GroupGraph:
+ case LayoutDocEntry::GroupPageDocs:
+ case LayoutDocEntry::DirSubDirs:
+ case LayoutDocEntry::DirFiles:
+ case LayoutDocEntry::DirGraph:
+ err("Internal inconsistency: member %d should not be part of "
+ "LayoutDocManager::Namespace entry list\n",lde->kind());
+ break;
+ }
+ }
+
+ //---------------------------------------- end flexible part -------------------------------
+
+ ol.endContents();
+
+ endFileWithNavPath(this,ol);
+}
+
+void ConceptDefImpl::writeDeclarationLink(OutputList &ol,bool &found,const char *header,bool localNames) const
+{
+ if (isLinkable())
+ {
+ if (!found) // first concept
+ {
+ ol.startMemberHeader("concepts");
+ if (header)
+ {
+ ol.parseText(header);
+ }
+ else
+ {
+ theTranslator->trConcept(true,false);
+ }
+ ol.endMemberHeader();
+ ol.startMemberList();
+ found=TRUE;
+ }
+ ol.startMemberDeclaration();
+ ol.startMemberItem(anchor(),FALSE);
+ ol.writeString("concept ");
+ QCString cname = displayName(!localNames);
+ ol.insertMemberAlign();
+ if (isLinkable())
+ {
+ ol.writeObjectLink(getReference(),
+ getOutputFileBase(),
+ anchor(),
+ cname
+ );
+ }
+ else
+ {
+ ol.startBold();
+ ol.docify(cname);
+ ol.endBold();
+ }
+ ol.endMemberItem();
+ // add the brief description if available
+ if (!briefDescription().isEmpty() && Config_getBool(BRIEF_MEMBER_DESC))
+ {
+ DocRoot *rootNode = validatingParseDoc(briefFile(),briefLine(),this,0,
+ briefDescription(),FALSE,FALSE,
+ 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT));
+ if (rootNode && !rootNode->isEmpty())
+ {
+ ol.startMemberDescription(anchor());
+ ol.writeDoc(rootNode,this,0);
+ ol.endMemberDescription();
+ }
+ delete rootNode;
+ }
+ ol.endMemberDeclaration(anchor(),0);
+ }
+}
+
+void ConceptDefImpl::findSectionsInDocumentation()
+{
+ docFindSections(briefDescription(),this,docFile());
+ docFindSections(documentation(),this,docFile());
+}
+
+//------------------------------------------------------------------------------------
+
+bool ConceptLinkedRefMap::declVisible() const
+{
+ bool hideUndocClasses = Config_getBool(HIDE_UNDOC_CLASSES);
+ for (const auto &cd : *this)
+ {
+ bool isLink = cd->isLinkable();
+ if (isLink || !hideUndocClasses)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+void ConceptLinkedRefMap::writeDeclaration(OutputList &ol,const char *header,bool localNames) const
+{
+ bool found=FALSE;
+ for (const auto &cd : *this)
+ {
+ cd->writeDeclarationLink(ol,found,header,localNames);
+ }
+ if (found) ol.endMemberList();
+}
+
+//------------------------------------------------------------------------------------
+
+// --- Cast functions
+//
+ConceptDef *toConceptDef(Definition *d)
+{
+ if (d && (typeid(*d)==typeid(ConceptDefImpl) || typeid(*d)==typeid(ConceptDefAliasImpl)))
+ {
+ return static_cast<ConceptDef*>(d);
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+ConceptDef *toConceptDef(DefinitionMutable *md)
+{
+ Definition *d = toDefinition(md);
+ if (d && typeid(*d)==typeid(ConceptDefImpl))
+ {
+ return static_cast<ConceptDef*>(d);
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+const ConceptDef *toConceptDef(const Definition *d)
+{
+ if (d && (typeid(*d)==typeid(ConceptDefImpl) || typeid(*d)==typeid(ConceptDefAliasImpl)))
+ {
+ return static_cast<const ConceptDef*>(d);
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+ConceptDefMutable *toConceptDefMutable(Definition *d)
+{
+ if (d && typeid(*d)==typeid(ConceptDefImpl))
+ {
+ return static_cast<ConceptDefMutable*>(d);
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+ConceptDefMutable *toConceptDefMutable(const Definition *d)
+{
+ if (d && typeid(*d)==typeid(ConceptDefImpl))
+ {
+ return const_cast<ConceptDefMutable*>(static_cast<const ConceptDefMutable*>(d));
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+
+
diff --git a/src/conceptdef.h b/src/conceptdef.h
new file mode 100644
index 0000000..224ed57
--- /dev/null
+++ b/src/conceptdef.h
@@ -0,0 +1,82 @@
+/******************************************************************************
+ *
+ * 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
+ * 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 CONCEPTDEF_H
+#define CONCEPTDEF_H
+
+#include "definition.h"
+#include "filedef.h"
+
+class ConceptDef : public Definition
+{
+ public:
+ virtual DefType definitionType() const = 0;
+ virtual QCString getOutputFileBase() const = 0;
+ virtual bool hasDetailedDescription() const = 0;
+ virtual QCString displayName(bool includeScope=true) const = 0;
+ virtual const IncludeInfo *includeInfo() const = 0;
+ virtual ArgumentList getTemplateParameterList() const = 0;
+ virtual QCString anchor() const = 0;
+ virtual bool isLinkableInProject() const = 0;
+ virtual bool isLinkable() const = 0;
+ virtual QCString initializer() const = 0;
+ virtual void writeDeclarationLink(OutputList &ol,bool &found,
+ const char *header,bool localNames) const = 0;
+ virtual const NamespaceDef *getNamespaceDef() const = 0;
+ virtual const FileDef *getFileDef() const = 0;
+};
+
+class ConceptDefMutable : public DefinitionMutable, public ConceptDef
+{
+ public:
+ virtual void setIncludeFile(FileDef *fd,const char *incName,bool local,bool force) = 0;
+ virtual void setTemplateArguments(const ArgumentList &al) = 0;
+ virtual void setNamespace(NamespaceDef *nd) = 0;
+ virtual void setFileDef(FileDef *fd) = 0;
+ virtual void writeTagFile(TextStream &) = 0;
+ virtual void writeDocumentation(OutputList &ol) = 0;
+ virtual void setInitializer(const char *init) = 0;
+ virtual void findSectionsInDocumentation() = 0;
+};
+
+ConceptDefMutable *createConceptDef(
+ const char *fileName,int startLine,int startColumn,const char *name,
+ const char *tagRef=0,const char *tagFile=0);
+
+ConceptDef *createConceptDefAlias(const Definition *newScope,const ConceptDef *cd);
+
+// ---- Map
+
+class ConceptLinkedMap : public LinkedMap<ConceptDef>
+{
+};
+
+class ConceptLinkedRefMap : public LinkedRefMap<const ConceptDef>
+{
+ public:
+ bool declVisible() const;
+ void writeDeclaration(OutputList &ol,const char *header,bool localNames) const;
+ void writeDocumentation(OutputList &ol,const Definition * container=0) const;
+};
+
+// ---- Cast functions
+
+ConceptDef *toConceptDef(Definition *d);
+ConceptDef *toConceptDef(DefinitionMutable *d);
+const ConceptDef *toConceptDef(const Definition *d);
+ConceptDefMutable *toConceptDefMutable(Definition *d);
+ConceptDefMutable *toConceptDefMutable(const Definition *d);
+
+#endif
diff --git a/src/context.cpp b/src/context.cpp
index 32e6720..8275130 100644
--- a/src/context.cpp
+++ b/src/context.cpp
@@ -1552,6 +1552,7 @@ class DefinitionContext
case Definition::TypePackage: result="package"; break;
case Definition::TypePage: result="page"; break;
case Definition::TypeDir: result="dir"; break;
+ case Definition::TypeConcept: result="concept"; break;
case Definition::TypeMember: break;
}
return result;
@@ -6393,7 +6394,9 @@ class NestingContext::Private : public GenericNodeListContext
if (!nd->isAnonymous() &&
(!rootOnly || nd->getOuterScope()==Doxygen::globalScope))
{
- bool hasChildren = namespaceHasNestedNamespace(nd);
+ bool hasChildren = namespaceHasNestedNamespace(nd) ||
+ namespaceHasNestedClass(nd,false,ClassDef::Class) ||
+ namespaceHasNestedConcept(nd);
bool isLinkable = nd->isLinkableInProject();
if (isLinkable || hasChildren)
{
diff --git a/src/definition.h b/src/definition.h
index 1b1c364..66d7628 100644
--- a/src/definition.h
+++ b/src/definition.h
@@ -90,7 +90,8 @@ class Definition
TypeGroup = 4,
TypePackage = 5,
TypePage = 6,
- TypeDir = 7
+ TypeDir = 7,
+ TypeConcept = 8
};
diff --git a/src/dirdef.cpp b/src/dirdef.cpp
index a1363cc..39a5cb1 100644
--- a/src/dirdef.cpp
+++ b/src/dirdef.cpp
@@ -561,11 +561,14 @@ void DirDefImpl::writeDocumentation(OutputList &ol)
case LayoutDocEntry::NamespaceNestedNamespaces:
case LayoutDocEntry::NamespaceNestedConstantGroups:
case LayoutDocEntry::NamespaceClasses:
+ case LayoutDocEntry::NamespaceConcepts:
case LayoutDocEntry::NamespaceInterfaces:
case LayoutDocEntry::NamespaceStructs:
case LayoutDocEntry::NamespaceExceptions:
case LayoutDocEntry::NamespaceInlineClasses:
+ case LayoutDocEntry::ConceptDefinition:
case LayoutDocEntry::FileClasses:
+ case LayoutDocEntry::FileConcepts:
case LayoutDocEntry::FileInterfaces:
case LayoutDocEntry::FileStructs:
case LayoutDocEntry::FileExceptions:
@@ -577,6 +580,7 @@ void DirDefImpl::writeDocumentation(OutputList &ol)
case LayoutDocEntry::FileSourceLink:
case LayoutDocEntry::FileInlineClasses:
case LayoutDocEntry::GroupClasses:
+ case LayoutDocEntry::GroupConcepts:
case LayoutDocEntry::GroupInlineClasses:
case LayoutDocEntry::GroupNamespaces:
case LayoutDocEntry::GroupDirs:
diff --git a/src/docbookgen.cpp b/src/docbookgen.cpp
index 6e6d969..1c03c07 100644
--- a/src/docbookgen.cpp
+++ b/src/docbookgen.cpp
@@ -385,6 +385,9 @@ DB_GEN_C2("IndexSections " << is)
case isNamespaceIndex:
//Namespace Index}\n"
break;
+ case isConceptIndex:
+ //Concept Index}\n"
+ break;
case isClassHierarchyIndex:
//Hierarchical Index}\n"
break;
@@ -409,6 +412,10 @@ DB_GEN_C2("IndexSections " << is)
m_t << "<chapter>\n";
m_t << " <title>";
break;
+ case isConceptDocumentation:
+ m_t << "<chapter>\n";
+ m_t << " <title>";
+ break;
case isClassDocumentation:
m_t << "<chapter>\n";
m_t << " <title>";
@@ -456,6 +463,10 @@ DB_GEN_C2("IndexSections " << is)
//m_t << "<xi:include href=\"namespaces.xml\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>";
//m_t << "</chapter>\n";
break;
+ case isConceptIndex:
+ //m_t << "<xi:include href=\"concepts.xml\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>";
+ //m_t << "</chapter>\n";
+ break;
case isClassHierarchyIndex:
//m_t << "<xi:include href=\"hierarchy.xml\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>";
//m_t << "</chapter>\n";
@@ -510,6 +521,19 @@ DB_GEN_C2("IndexSections " << is)
}
m_t << "</chapter>\n";
break;
+ case isConceptDocumentation:
+ {
+ m_t << "</title>\n";
+ for (const auto &cd : *Doxygen::conceptLinkedMap)
+ {
+ if (cd->isLinkableInProject() && !cd->isAlias())
+ {
+ m_t << "<xi:include href=\"" << cd->getOutputFileBase() << ".xml\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>\n";
+ }
+ }
+ }
+ m_t << "</chapter>\n";
+ break;
case isClassDocumentation:
{
m_t << "</title>\n";
diff --git a/src/docbookgen.h b/src/docbookgen.h
index 2de8a40..fc9d576 100644
--- a/src/docbookgen.h
+++ b/src/docbookgen.h
@@ -241,6 +241,8 @@ class DocbookGenerator : public OutputGenerator
void endMemberItem();
void startMemberTemplateParams();
void endMemberTemplateParams(const char *,const char *);
+ void startCompoundTemplateParams() { startSubsubsection(); }
+ void endCompoundTemplateParams() { endSubsubsection(); }
void startMemberGroupHeader(bool);
void endMemberGroupHeader();
void startMemberGroupDocs(){DB_GEN_EMPTY};
diff --git a/src/doxygen.cpp b/src/doxygen.cpp
index 9a9342b..880a3f4 100644
--- a/src/doxygen.cpp
+++ b/src/doxygen.cpp
@@ -104,6 +104,7 @@
#include "regex.h"
#include "fileinfo.h"
#include "dir.h"
+#include "conceptdef.h"
#if USE_SQLITE3
#include <sqlite3.h>
@@ -124,6 +125,7 @@ extern void initResources();
// globally accessible variables
ClassLinkedMap *Doxygen::classLinkedMap = 0;
ClassLinkedMap *Doxygen::hiddenClassLinkedMap = 0;
+ConceptLinkedMap *Doxygen::conceptLinkedMap = 0;
NamespaceLinkedMap *Doxygen::namespaceLinkedMap = 0;
MemberNameLinkedMap *Doxygen::memberNameLinkedMap = 0;
MemberNameLinkedMap *Doxygen::functionNameLinkedMap = 0;
@@ -184,6 +186,7 @@ void clearAll()
Doxygen::classLinkedMap->clear();
Doxygen::hiddenClassLinkedMap->clear();
+ Doxygen::conceptLinkedMap->clear();
Doxygen::namespaceLinkedMap->clear();
Doxygen::pageLinkedMap->clear();
Doxygen::exampleLinkedMap->clear();
@@ -531,7 +534,8 @@ static void buildFileList(const Entry *root)
for (const auto &e : root->children()) buildFileList(e.get());
}
-static void addIncludeFile(ClassDefMutable *cd,FileDef *ifd,const Entry *root)
+template<class DefMutable>
+static void addIncludeFile(DefMutable *cd,FileDef *ifd,const Entry *root)
{
if (
(!root->doc.stripWhiteSpace().isEmpty() ||
@@ -1158,6 +1162,148 @@ static void buildClassDocList(const Entry *root)
for (const auto &e : root->children()) buildClassDocList(e.get());
}
+//----------------------------------------------------------------------
+// build a list of all classes mentioned in the documentation
+// and all classes that have a documentation block before their definition.
+
+static void addConceptToContext(const Entry *root)
+{
+ FileDef *fd = root->fileDef();
+
+ QCString scName;
+ if (root->parent()->section&Entry::SCOPE_MASK)
+ {
+ scName=root->parent()->name;
+ }
+
+ // name with scope (if not present already)
+ QCString qualifiedName = root->name;
+ if (!scName.isEmpty() && !leftScopeMatch(qualifiedName,scName))
+ {
+ qualifiedName.prepend(scName+"::");
+ }
+
+ // see if we already found the concept before
+ ConceptDefMutable *cd = getConceptMutable(qualifiedName);
+
+ Debug::print(Debug::Classes,0, " Found concept with name %s (qualifiedName=%s -> cd=%p)\n",
+ cd ? qPrint(cd->name()) : qPrint(root->name), qPrint(qualifiedName),cd);
+
+ if (cd)
+ {
+ qualifiedName=cd->name();
+ Debug::print(Debug::Classes,0," Existing concept %s!\n",qPrint(cd->name()));
+
+ cd->setDocumentation(root->doc,root->docFile,root->docLine);
+ cd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
+
+ addIncludeFile(cd,fd,root);
+ }
+ else // new concept
+ {
+ QCString className;
+ QCString namespaceName;
+ extractNamespaceName(qualifiedName,className,namespaceName);
+
+ //printf("New concept: fullname %s namespace '%s' name='%s' brief='%s' docs='%s'\n",
+ // qualifiedName.data(),namespaceName.data(),className.data(),root->brief.data(),root->doc.data());
+
+ QCString tagName;
+ QCString refFileName;
+ const TagInfo *tagInfo = root->tagInfo();
+ if (tagInfo)
+ {
+ tagName = tagInfo->tagName;
+ refFileName = tagInfo->fileName;
+ if (qualifiedName.find("::")!=-1)
+ // symbols imported via tag files may come without the parent scope,
+ // so we artificially create it here
+ {
+ buildScopeFromQualifiedName(qualifiedName,root->lang,tagInfo);
+ }
+ }
+ std::unique_ptr<ArgumentList> tArgList = getTemplateArgumentsFromName(qualifiedName,root->tArgLists);
+ // add concept to the list
+ //printf("ClassDict.insert(%s)\n",fullName.data());
+ cd = toConceptDefMutable(
+ Doxygen::conceptLinkedMap->add(qualifiedName,
+ std::unique_ptr<ConceptDef>(
+ createConceptDef(tagInfo?tagName:root->fileName,root->startLine,root->startColumn,
+ qualifiedName,tagName,refFileName))));
+ if (cd)
+ {
+ Debug::print(Debug::Classes,0," New concept '%s' #tArgLists=%d tagInfo=%p\n",
+ qPrint(qualifiedName),root->tArgLists.size(),tagInfo);
+ cd->setDocumentation(root->doc,root->docFile,root->docLine); // copy docs to definition
+ cd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
+ cd->setLanguage(root->lang);
+ cd->setId(root->id);
+ cd->setHidden(root->hidden);
+ cd->setInitializer(root->initializer.str().c_str());
+ if (tArgList)
+ {
+ cd->setTemplateArguments(*tArgList);
+ }
+ // file definition containing the class cd
+ cd->setBodySegment(root->startLine,root->bodyLine,root->endBodyLine);
+ cd->setBodyDef(fd);
+ addIncludeFile(cd,fd,root);
+
+ // also add namespace to the correct structural context
+ Definition *d = findScopeFromQualifiedName(Doxygen::globalScope,qualifiedName,0,tagInfo);
+ if (d && d->definitionType()==Definition::TypeNamespace)
+ {
+ DefinitionMutable *dm = toDefinitionMutable(d);
+ if (dm)
+ {
+ dm->addInnerCompound(cd);
+ }
+ cd->setOuterScope(d);
+ }
+ }
+ else
+ {
+ Debug::print(Debug::Classes,0," Not added concept '%s', already exists (as alias)\n", qPrint(qualifiedName));
+ }
+ }
+
+ if (cd)
+ {
+ cd->addSectionsToDefinition(root->anchors);
+ if (fd)
+ {
+ //printf(">> Inserting concept '%s' in file '%s' (root->fileName='%s')\n",
+ // cd->name().data(),
+ // fd->name().data(),
+ // root->fileName.data()
+ // );
+ cd->setFileDef(fd);
+ fd->insertConcept(cd);
+ }
+ addConceptToGroups(root,cd);
+ cd->setRefItems(root->sli);
+ }
+}
+static void buildConceptList(const Entry *root)
+{
+ if (root->section & Entry::CONCEPT_SEC)
+ {
+ addConceptToContext(root);
+ }
+ for (const auto &e : root->children()) buildConceptList(e.get());
+}
+
+static void buildConceptDocList(const Entry *root)
+{
+ if (root->section & Entry::CONCEPTDOC_SEC)
+ {
+ addConceptToContext(root);
+ }
+ for (const auto &e : root->children()) buildConceptDocList(e.get());
+}
+
+//----------------------------------------------------------------------
+
static void resolveClassNestingRelations()
{
ClassDefSet visitedClasses;
@@ -3437,6 +3583,7 @@ static void buildFunctionList(const Entry *root)
// functions have the same number of template parameters
bool sameNumTemplateArgs = TRUE;
bool matchingReturnTypes = TRUE;
+ bool sameRequiresClause = TRUE;
if (!mdTempl.empty() && !root->tArgLists.empty())
{
if (mdTempl.size()!=root->tArgLists.back().size())
@@ -3447,6 +3594,10 @@ static void buildFunctionList(const Entry *root)
{
matchingReturnTypes = FALSE;
}
+ if (md->requiresClause()!=root->req)
+ {
+ sameRequiresClause = FALSE;
+ }
}
bool staticsInDifferentFiles =
@@ -3458,6 +3609,7 @@ static void buildFunctionList(const Entry *root)
FALSE) &&
sameNumTemplateArgs &&
matchingReturnTypes &&
+ sameRequiresClause &&
!staticsInDifferentFiles
)
{
@@ -5245,13 +5397,14 @@ static bool findGlobalMember(const Entry *root,
matching = FALSE;
}
- // for template member we also need to check the return type
+ // for template member we also need to check the return type and requires
if (!md->templateArguments().empty() && !root->tArgLists.empty())
{
//printf("Comparing return types '%s'<->'%s'\n",
// md->typeString(),type);
if (md->templateArguments().size()!=root->tArgLists.back().size() ||
- qstrcmp(md->typeString(),type)!=0)
+ qstrcmp(md->typeString(),type)!=0 ||
+ md->requiresClause()!=root->req)
{
//printf(" ---> no matching\n");
matching = FALSE;
@@ -7852,6 +8005,15 @@ static void addSourceReferences()
fd->addSourceRef(cd->getStartDefLine(),cd.get(),0);
}
}
+ // add source references for concept definitions
+ for (const auto &cd : *Doxygen::conceptLinkedMap)
+ {
+ FileDef *fd=cd->getBodyDef();
+ if (fd && cd->isLinkableInProject() && cd->getStartDefLine()!=-1)
+ {
+ fd->addSourceRef(cd->getStartDefLine(),cd.get(),0);
+ }
+ }
// add source references for namespace definitions
for (const auto &nd : *Doxygen::namespaceLinkedMap)
{
@@ -8096,6 +8258,27 @@ static void generateClassDocs()
//----------------------------------------------------------------------------
+static void generateConceptDocs()
+{
+ for (const auto &cdi : *Doxygen::conceptLinkedMap)
+ {
+ ConceptDefMutable *cd=toConceptDefMutable(cdi.get());
+
+ //printf("cd=%s getOuterScope=%p global=%p\n",cd->name().data(),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 concepts
+ ) && !cd->isHidden() && cd->isLinkableInProject()
+ )
+ {
+ msg("Generating docs for concept %s...\n",cd->name().data());
+ cd->writeDocumentation(*g_outputList);
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+
static void inheritDocumentation()
{
for (const auto &mn : *Doxygen::memberNameLinkedMap)
@@ -8241,6 +8424,15 @@ static void findSectionsInDocumentation()
cdm->findSectionsInDocumentation();
}
}
+ // for each concept
+ for (const auto &cd : *Doxygen::conceptLinkedMap)
+ {
+ ConceptDefMutable *cdm = toConceptDefMutable(cd.get());
+ if (cdm)
+ {
+ cdm->findSectionsInDocumentation();
+ }
+ }
// for each file
for (const auto &fn : *Doxygen::inputNameLinkedMap)
{
@@ -8934,6 +9126,20 @@ static void generateNamespaceClassDocs(const ClassLinkedRefMap &classList)
}
}
+static void generateNamespaceConceptDocs(const ConceptLinkedRefMap &conceptList)
+{
+ // for each concept in the namespace...
+ for (const auto &cd : conceptList)
+ {
+ ConceptDefMutable *cdm = toConceptDefMutable(cd);
+ if ( cdm && cd->isLinkableInProject() && !cd->isHidden())
+ {
+ msg("Generating docs for concept %s...\n",cd->name().data());
+ cdm->writeDocumentation(*g_outputList);
+ }
+ }
+}
+
static void generateNamespaceDocs()
{
static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
@@ -8960,6 +9166,7 @@ static void generateNamespaceDocs()
generateNamespaceClassDocs(nd->getStructs());
generateNamespaceClassDocs(nd->getExceptions());
}
+ generateNamespaceConceptDocs(nd->getConcepts());
}
}
@@ -10096,6 +10303,7 @@ void initDoxygen()
Doxygen::namespaceLinkedMap = new NamespaceLinkedMap;
Doxygen::classLinkedMap = new ClassLinkedMap;
Doxygen::hiddenClassLinkedMap = new ClassLinkedMap;
+ Doxygen::conceptLinkedMap = new ConceptLinkedMap;
Doxygen::dirLinkedMap = new DirLinkedMap;
Doxygen::pageLinkedMap = new PageLinkedMap; // all doc pages
Doxygen::exampleLinkedMap = new PageLinkedMap; // all examples
@@ -10715,6 +10923,15 @@ static void writeTagFile()
cdm->writeTagFile(tagFile);
}
}
+ // for each concept
+ for (const auto &cd : *Doxygen::conceptLinkedMap)
+ {
+ ConceptDefMutable *cdm = toConceptDefMutable(cd.get());
+ if (cdm && cdm->isLinkableInProject())
+ {
+ cdm->writeTagFile(tagFile);
+ }
+ }
// for each namespace
for (const auto &nd : *Doxygen::namespaceLinkedMap)
{
@@ -11241,6 +11458,10 @@ void parseInput()
buildClassList(root.get());
g_s.end();
+ g_s.begin("Building concept list...\n");
+ buildConceptList(root.get());
+ g_s.end();
+
// build list of using declarations here (global list)
buildListOfUsingDecls(root.get());
g_s.end();
@@ -11260,6 +11481,11 @@ void parseInput()
g_s.begin("Associating documentation with classes...\n");
buildClassDocList(root.get());
+ g_s.end();
+
+ g_s.begin("Associating documentation with concepts...\n");
+ buildConceptDocList(root.get());
+ g_s.end();
g_s.begin("Building example list...\n");
buildExampleList(root.get());
@@ -11411,6 +11637,11 @@ void parseInput()
return qstricmp(n1->name(),n2->name())<0;
};
+ auto conceptComp = [](const ConceptLinkedMap::Ptr &c1,const ConceptLinkedMap::Ptr &c2)
+ {
+ return qstricmp(c1->name(),c2->name())<0;
+ };
+
g_s.begin("Sorting lists...\n");
std::sort(Doxygen::memberNameLinkedMap->begin(),
Doxygen::memberNameLinkedMap->end(),
@@ -11424,6 +11655,9 @@ void parseInput()
std::sort(Doxygen::classLinkedMap->begin(),
Doxygen::classLinkedMap->end(),
classComp);
+ std::sort(Doxygen::conceptLinkedMap->begin(),
+ Doxygen::conceptLinkedMap->end(),
+ conceptComp);
std::sort(Doxygen::namespaceLinkedMap->begin(),
Doxygen::namespaceLinkedMap->end(),
namespaceComp);
@@ -11711,6 +11945,10 @@ void generateOutput()
generateClassDocs();
g_s.end();
+ g_s.begin("Generating concept documentation...\n");
+ generateConceptDocs();
+ g_s.end();
+
g_s.begin("Generating namespace index...\n");
generateNamespaceDocs();
g_s.end();
diff --git a/src/doxygen.h b/src/doxygen.h
index 5b136b4..787b69e 100644
--- a/src/doxygen.h
+++ b/src/doxygen.h
@@ -41,6 +41,7 @@ class GroupLinkedMap;
class FileDef;
class ClassDef;
class ClassLinkedMap;
+class ConceptLinkedMap;
class MemberNameLinkedMap;
class FileNameLinkedMap;
class NamespaceLinkedMap;
@@ -76,6 +77,7 @@ class Doxygen
public:
static ClassLinkedMap *classLinkedMap;
static ClassLinkedMap *hiddenClassLinkedMap;
+ static ConceptLinkedMap *conceptLinkedMap;
static PageLinkedMap *exampleLinkedMap;
static PageLinkedMap *pageLinkedMap;
static std::unique_ptr<PageDef> mainPage;
diff --git a/src/entry.h b/src/entry.h
index 6ba88e8..95b2274 100644
--- a/src/entry.h
+++ b/src/entry.h
@@ -66,6 +66,7 @@ class Entry
enum Sections {
CLASS_SEC = 0x00000001,
NAMESPACE_SEC = 0x00000010,
+ CONCEPT_SEC = 0x00000020,
COMPOUND_MASK = CLASS_SEC,
SCOPE_MASK = COMPOUND_MASK | NAMESPACE_SEC,
@@ -79,6 +80,7 @@ class Entry
CATEGORYDOC_SEC = 0x00040000,
SERVICEDOC_SEC = 0x00080000,
SINGLETONDOC_SEC = 0x00100000,
+ CONCEPTDOC_SEC = 0x00200000,
COMPOUNDDOC_MASK = CLASSDOC_SEC | STRUCTDOC_SEC | UNIONDOC_SEC |
INTERFACEDOC_SEC | EXCEPTIONDOC_SEC | PROTOCOLDOC_SEC |
CATEGORYDOC_SEC | SERVICEDOC_SEC | SINGLETONDOC_SEC,
@@ -256,7 +258,7 @@ class Entry
QCString args; //!< member argument string
QCString bitfields; //!< member's bit fields
ArgumentList argList; //!< member arguments as a list
- ArgumentLists tArgLists; //!< template argument declarations
+ ArgumentLists tArgLists; //!< template argument declarations
TextStream program; //!< the program text
TextStream initializer; //!< initial value (for variables)
QCString includeFile; //!< include file (2 arg of \\class, must be unique)
diff --git a/src/filedef.cpp b/src/filedef.cpp
index a9503c5..58d38c4 100644
--- a/src/filedef.cpp
+++ b/src/filedef.cpp
@@ -45,6 +45,7 @@
#include "clangparser.h"
#include "settings.h"
#include "definitionimpl.h"
+#include "conceptdef.h"
//---------------------------------------------------------------------------
@@ -90,8 +91,9 @@ class FileDefImpl : public DefinitionMixin<FileDef>
virtual MemberList *getMemberList(MemberListType lt) const;
virtual const MemberLists &getMemberLists() const { return m_memberLists; }
virtual const MemberGroupList &getMemberGroups() const { return m_memberGroups; }
- virtual NamespaceLinkedRefMap getNamespaces() const { return m_namespaces; }
- virtual ClassLinkedRefMap getClasses() const { return m_classes; }
+ virtual const NamespaceLinkedRefMap &getNamespaces() const { return m_namespaces; }
+ virtual const ConceptLinkedRefMap &getConcepts() const { return m_concepts; }
+ virtual const ClassLinkedRefMap &getClasses() const { return m_classes; }
virtual QCString title() const;
virtual bool hasDetailedDescription() const;
virtual QCString fileVersion() const;
@@ -112,6 +114,7 @@ class FileDefImpl : public DefinitionMixin<FileDef>
virtual void setDiskName(const QCString &name);
virtual void insertMember(MemberDef *md);
virtual void insertClass(const ClassDef *cd);
+ virtual void insertConcept(const ConceptDef *cd);
virtual void insertNamespace(const NamespaceDef *nd);
virtual void computeAnchors();
virtual void setPackageDef(PackageDef *pd) { m_package=pd; }
@@ -143,6 +146,7 @@ class FileDefImpl : public DefinitionMixin<FileDef>
void writeNamespaceDeclarations(OutputList &ol,const QCString &title,
bool isConstantGroup);
void writeClassDeclarations(OutputList &ol,const QCString &title,const ClassLinkedRefMap &list);
+ void writeConcepts(OutputList &ol,const QCString &title);
void writeInlineClasses(OutputList &ol);
void startMemberDeclarations(OutputList &ol);
void endMemberDeclarations(OutputList &ol);
@@ -178,6 +182,7 @@ class FileDefImpl : public DefinitionMixin<FileDef>
ClassLinkedRefMap m_interfaces;
ClassLinkedRefMap m_structs;
ClassLinkedRefMap m_exceptions;
+ ConceptLinkedRefMap m_concepts;
bool m_subGrouping;
};
@@ -356,6 +361,17 @@ void FileDefImpl::writeTagFile(TextStream &tagFile)
writeClassesToTagFile(tagFile, m_exceptions);
}
break;
+ case LayoutDocEntry::FileConcepts:
+ {
+ for (const auto *nd : m_concepts)
+ {
+ if (nd->isLinkableInProject())
+ {
+ tagFile << " <concept>" << convertToXML(nd->name()) << "</concept>\n";
+ }
+ }
+ }
+ break;
case LayoutDocEntry::FileNamespaces:
{
for (const auto *nd : m_namespaces)
@@ -668,6 +684,12 @@ void FileDefImpl::writeClassDeclarations(OutputList &ol,const QCString &title,co
list.writeDeclaration(ol,0,title,FALSE);
}
+void FileDefImpl::writeConcepts(OutputList &ol,const QCString &title)
+{
+ // write list of classes
+ m_concepts.writeDeclaration(ol,title,FALSE);
+}
+
void FileDefImpl::writeInlineClasses(OutputList &ol)
{
// temporarily undo the disabling could be done by startMemberDocumentation()
@@ -777,6 +799,13 @@ void FileDefImpl::writeSummaryLinks(OutputList &ol) const
ol.writeSummaryLink(0,label,ls->title(lang),first);
first=FALSE;
}
+ else if (lde->kind()==LayoutDocEntry::FileConcepts && m_concepts.declVisible())
+ {
+ const LayoutDocEntrySection *ls = (const LayoutDocEntrySection*)lde.get();
+ QCString label = "concepts";
+ ol.writeSummaryLink(0,label,ls->title(lang),first);
+ first=FALSE;
+ }
else if (lde->kind()==LayoutDocEntry::MemberDecl)
{
const LayoutDocEntryMemberDecl *lmd = (const LayoutDocEntryMemberDecl*)lde.get();
@@ -919,6 +948,12 @@ void FileDefImpl::writeDocumentation(OutputList &ol)
writeClassDeclarations(ol,ls->title(lang),m_exceptions);
}
break;
+ case LayoutDocEntry::FileConcepts:
+ {
+ const LayoutDocEntrySection *ls = (const LayoutDocEntrySection*)lde.get();
+ writeConcepts(ol,ls->title(lang));
+ }
+ break;
case LayoutDocEntry::FileNamespaces:
{
const LayoutDocEntrySection *ls = (const LayoutDocEntrySection*)lde.get();
@@ -977,11 +1012,14 @@ void FileDefImpl::writeDocumentation(OutputList &ol)
case LayoutDocEntry::NamespaceNestedNamespaces:
case LayoutDocEntry::NamespaceNestedConstantGroups:
case LayoutDocEntry::NamespaceClasses:
+ case LayoutDocEntry::NamespaceConcepts:
case LayoutDocEntry::NamespaceInterfaces:
case LayoutDocEntry::NamespaceStructs:
case LayoutDocEntry::NamespaceExceptions:
case LayoutDocEntry::NamespaceInlineClasses:
+ case LayoutDocEntry::ConceptDefinition:
case LayoutDocEntry::GroupClasses:
+ case LayoutDocEntry::GroupConcepts:
case LayoutDocEntry::GroupInlineClasses:
case LayoutDocEntry::GroupNamespaces:
case LayoutDocEntry::GroupDirs:
@@ -1319,6 +1357,12 @@ void FileDefImpl::insertClass(const ClassDef *cd)
list.add(cd->name(),cd);
}
+void FileDefImpl::insertConcept(const ConceptDef *cd)
+{
+ if (cd->isHidden()) return;
+ m_concepts.add(cd->name(),cd);
+}
+
/*! Adds namespace definition \a nd to the list of all compounds of this file */
void FileDefImpl::insertNamespace(const NamespaceDef *nd)
{
diff --git a/src/filedef.h b/src/filedef.h
index 3075470..02b484a 100644
--- a/src/filedef.h
+++ b/src/filedef.h
@@ -24,16 +24,18 @@
#include "definition.h"
#include "memberlist.h"
#include "containers.h"
-#include "classlist.h"
class MemberList;
class FileDef;
class FileList;
class ClassDef;
+class ConceptDef;
class MemberDef;
class OutputList;
class NamespaceDef;
class NamespaceLinkedRefMap;
+class ConceptLinkedRefMap;
+class ClassLinkedRefMap;
class PackageDef;
class DirDef;
class ClangTUParser;
@@ -133,8 +135,9 @@ class FileDef : public DefinitionMutable, public Definition
/* user defined member groups */
virtual const MemberGroupList &getMemberGroups() const = 0;
- virtual NamespaceLinkedRefMap getNamespaces() const = 0;
- virtual ClassLinkedRefMap getClasses() const = 0;
+ virtual const NamespaceLinkedRefMap &getNamespaces() const = 0;
+ virtual const ConceptLinkedRefMap &getConcepts() const = 0;
+ virtual const ClassLinkedRefMap &getClasses() const = 0;
virtual QCString title() const = 0;
virtual bool hasDetailedDescription() const = 0;
@@ -164,6 +167,7 @@ class FileDef : public DefinitionMutable, public Definition
virtual void insertMember(MemberDef *md) = 0;
virtual void insertClass(const ClassDef *cd) = 0;
+ virtual void insertConcept(const ConceptDef *cd) = 0;
virtual void insertNamespace(const NamespaceDef *nd) = 0;
virtual void computeAnchors() = 0;
diff --git a/src/ftvhelp.cpp b/src/ftvhelp.cpp
index d061325..7ef38c8 100644
--- a/src/ftvhelp.cpp
+++ b/src/ftvhelp.cpp
@@ -479,6 +479,10 @@ void FTVHelp::generateTree(TextStream &t, const std::vector<FTVNode*> &nl,int le
char icon=compoundIcon(toClassDef(n->def));
t << "<span class=\"icona\"><span class=\"icon\">" << icon << "</span></span>";
}
+ else if (n->def && n->def->definitionType()==Definition::TypeConcept)
+ {
+ t << "<span class=\"icona\"><span class=\"icon\">R</span></span>";
+ }
else if (n->def && n->def->definitionType()==Definition::TypeDir)
{
t << "<span class=\"iconfclosed\"></span>";
diff --git a/src/groupdef.cpp b/src/groupdef.cpp
index 27ab775..82a550d 100644
--- a/src/groupdef.cpp
+++ b/src/groupdef.cpp
@@ -64,6 +64,7 @@ class GroupDefImpl : public DefinitionMixin<GroupDef>
virtual bool hasGroupTitle( ) const { return m_titleSet; }
virtual void addFile(const FileDef *def);
virtual bool addClass(const ClassDef *def);
+ virtual bool addConcept(const ConceptDef *def);
virtual bool addNamespace(const NamespaceDef *def);
virtual void addGroup(const GroupDef *def);
virtual void addPage(const PageDef *def);
@@ -102,6 +103,7 @@ class GroupDefImpl : public DefinitionMixin<GroupDef>
virtual const FileList &getFiles() const { return m_fileList; }
virtual const ClassLinkedRefMap &getClasses() const { return m_classes; }
+ virtual const ConceptLinkedRefMap &getConcepts() const { return m_concepts; }
virtual const NamespaceLinkedRefMap &getNamespaces() const { return m_namespaces; }
virtual const GroupList &getSubGroups() const { return m_groups; }
virtual const PageLinkedRefMap &getPages() const { return m_pages; }
@@ -122,6 +124,7 @@ class GroupDefImpl : public DefinitionMixin<GroupDef>
void writeNestedGroups(OutputList &ol,const QCString &title);
void writeDirs(OutputList &ol,const QCString &title);
void writeClasses(OutputList &ol,const QCString &title);
+ void writeConcepts(OutputList &ol,const QCString &title);
void writeInlineClasses(OutputList &ol);
void writePageDocumentation(OutputList &ol);
void writeDetailedDescription(OutputList &ol,const QCString &title);
@@ -140,6 +143,7 @@ class GroupDefImpl : public DefinitionMixin<GroupDef>
QCString m_fileName; // base name of the generated file
FileList m_fileList; // list of files in the group
ClassLinkedRefMap m_classes; // list of classes in the group
+ ConceptLinkedRefMap m_concepts; // list of concepts in the group
NamespaceLinkedRefMap m_namespaces; // list of namespaces in the group
GroupList m_groups; // list of sub groups.
PageLinkedRefMap m_pages; // list of pages in the group
@@ -256,6 +260,18 @@ bool GroupDefImpl::addClass(const ClassDef *cd)
return FALSE;
}
+bool GroupDefImpl::addConcept(const ConceptDef *cd)
+{
+ if (cd->isHidden()) return FALSE;
+ QCString qn = cd->name();
+ if (m_concepts.find(qn)==0)
+ {
+ m_concepts.add(qn,cd);
+ return TRUE;
+ }
+ return FALSE;
+}
+
bool GroupDefImpl::addNamespace(const NamespaceDef *def)
{
//printf("adding namespace hidden=%d\n",def->isHidden());
@@ -619,6 +635,18 @@ void GroupDefImpl::writeTagFile(TextStream &tagFile)
}
}
break;
+ case LayoutDocEntry::GroupConcepts:
+ {
+ for (const auto &cd : m_concepts)
+ {
+ if (cd->isLinkableInProject())
+ {
+ tagFile << " <concept>" << convertToXML(cd->name())
+ << "</concept>\n";
+ }
+ }
+ }
+ break;
case LayoutDocEntry::GroupNamespaces:
{
for (const auto &nd : m_namespaces)
@@ -936,6 +964,12 @@ void GroupDefImpl::writeClasses(OutputList &ol,const QCString &title)
m_classes.writeDeclaration(ol,0,title,FALSE);
}
+void GroupDefImpl::writeConcepts(OutputList &ol,const QCString &title)
+{
+ // write list of concepts
+ m_concepts.writeDeclaration(ol,title,FALSE);
+}
+
void GroupDefImpl::writeInlineClasses(OutputList &ol)
{
m_classes.writeDocumentation(ol);
@@ -1023,15 +1057,17 @@ void GroupDefImpl::writeSummaryLinks(OutputList &ol) const
SrcLangExt lang = getLanguage();
for (const auto &lde : LayoutDocManager::instance().docEntries(LayoutDocManager::Group))
{
- if ((lde->kind()==LayoutDocEntry::GroupClasses && m_classes.declVisible()) ||
- (lde->kind()==LayoutDocEntry::GroupNamespaces && m_namespaces.declVisible()) ||
- (lde->kind()==LayoutDocEntry::GroupFiles && !m_fileList.empty()) ||
+ if ((lde->kind()==LayoutDocEntry::GroupClasses && m_classes.declVisible()) ||
+ (lde->kind()==LayoutDocEntry::GroupConcepts && m_concepts.declVisible()) ||
+ (lde->kind()==LayoutDocEntry::GroupNamespaces && m_namespaces.declVisible()) ||
+ (lde->kind()==LayoutDocEntry::GroupFiles && !m_fileList.empty()) ||
(lde->kind()==LayoutDocEntry::GroupNestedGroups && !m_groups.empty()) ||
- (lde->kind()==LayoutDocEntry::GroupDirs && !m_dirList.empty())
+ (lde->kind()==LayoutDocEntry::GroupDirs && !m_dirList.empty())
)
{
const LayoutDocEntrySection *ls = (const LayoutDocEntrySection*)lde.get();
QCString label = lde->kind()==LayoutDocEntry::GroupClasses ? "nested-classes" :
+ lde->kind()==LayoutDocEntry::GroupConcepts ? "concepts" :
lde->kind()==LayoutDocEntry::GroupNamespaces ? "namespaces" :
lde->kind()==LayoutDocEntry::GroupFiles ? "files" :
lde->kind()==LayoutDocEntry::GroupNestedGroups ? "groups" :
@@ -1123,6 +1159,12 @@ void GroupDefImpl::writeDocumentation(OutputList &ol)
writeClasses(ol,ls->title(lang));
}
break;
+ case LayoutDocEntry::GroupConcepts:
+ {
+ const LayoutDocEntrySection *ls = (const LayoutDocEntrySection*)lde.get();
+ writeConcepts(ol,ls->title(lang));
+ }
+ break;
case LayoutDocEntry::GroupInlineClasses:
{
writeInlineClasses(ol);
@@ -1201,11 +1243,14 @@ void GroupDefImpl::writeDocumentation(OutputList &ol)
case LayoutDocEntry::NamespaceNestedNamespaces:
case LayoutDocEntry::NamespaceNestedConstantGroups:
case LayoutDocEntry::NamespaceClasses:
+ case LayoutDocEntry::NamespaceConcepts:
case LayoutDocEntry::NamespaceInterfaces:
case LayoutDocEntry::NamespaceStructs:
case LayoutDocEntry::NamespaceExceptions:
case LayoutDocEntry::NamespaceInlineClasses:
+ case LayoutDocEntry::ConceptDefinition:
case LayoutDocEntry::FileClasses:
+ case LayoutDocEntry::FileConcepts:
case LayoutDocEntry::FileInterfaces:
case LayoutDocEntry::FileStructs:
case LayoutDocEntry::FileExceptions:
@@ -1312,6 +1357,24 @@ void addClassToGroups(const Entry *root,ClassDef *cd)
}
}
+void addConceptToGroups(const Entry *root,ConceptDef *cd)
+{
+ for (const Grouping &g : root->groups)
+ {
+ GroupDef *gd = Doxygen::groupLinkedMap->find(g.groupname);
+ if (gd && gd->addConcept(cd))
+ {
+ ConceptDefMutable *cdm = toConceptDefMutable(cd);
+ if (cdm)
+ {
+ cdm->makePartOfGroup(gd);
+ }
+ //printf("Compound %s: in group %s\n",cd->name().data(),gd->groupTitle());
+ }
+ }
+}
+
+
void addNamespaceToGroups(const Entry *root,NamespaceDef *nd)
{
//printf("root->groups.size()=%zu\n",root->groups.size());
diff --git a/src/groupdef.h b/src/groupdef.h
index 26d26ca..8d3b78e 100644
--- a/src/groupdef.h
+++ b/src/groupdef.h
@@ -30,9 +30,11 @@ class MemberList;
class MemberLists;
class FileList;
class ClassLinkedRefMap;
+class ConceptLinkedRefMap;
class NamespaceLinkedRefMap;
class FileDef;
class ClassDef;
+class ConceptDef;
class NamespaceDef;
class GroupList;
class OutputList;
@@ -58,6 +60,7 @@ class GroupDef : public DefinitionMutable, public Definition
virtual bool hasGroupTitle( ) const = 0;
virtual void addFile(const FileDef *def) = 0;
virtual bool addClass(const ClassDef *def) = 0;
+ virtual bool addConcept(const ConceptDef *def) = 0;
virtual bool addNamespace(const NamespaceDef *def) = 0;
virtual void addGroup(const GroupDef *def) = 0;
virtual void addPage(const PageDef *def) = 0;
@@ -96,6 +99,7 @@ class GroupDef : public DefinitionMutable, public Definition
virtual const FileList &getFiles() const = 0;
virtual const ClassLinkedRefMap &getClasses() const = 0;
+ virtual const ConceptLinkedRefMap &getConcepts() const = 0;
virtual const NamespaceLinkedRefMap &getNamespaces() const = 0;
virtual const GroupList &getSubGroups() const = 0;
virtual const PageLinkedRefMap &getPages() const = 0;
@@ -125,6 +129,7 @@ class GroupList : public std::vector<const GroupDef *>
};
void addClassToGroups (const Entry *root,ClassDef *cd);
+void addConceptToGroups (const Entry *root,ConceptDef *cd);
void addNamespaceToGroups(const Entry *root,NamespaceDef *nd);
void addGroupToGroups (const Entry *root,GroupDef *subGroup);
void addMemberToGroups (const Entry *root,MemberDef *md);
diff --git a/src/htmlgen.cpp b/src/htmlgen.cpp
index b239116..fc00b17 100644
--- a/src/htmlgen.cpp
+++ b/src/htmlgen.cpp
@@ -1630,6 +1630,15 @@ void HtmlGenerator::endMemberTemplateParams(const char *anchor,const char *inher
m_t << "\"><td class=\"memTemplItemLeft\" align=\"right\" valign=\"top\">";
}
+void HtmlGenerator::startCompoundTemplateParams()
+{
+ m_t << "<div class=\"compoundTemplParams\">";
+}
+
+void HtmlGenerator::endCompoundTemplateParams()
+{
+ m_t << "</div>";
+}
void HtmlGenerator::insertMemberAlign(bool templ)
{
@@ -2222,6 +2231,7 @@ static bool quickLinkVisible(LayoutNavEntry::Kind kind)
case LayoutNavEntry::Namespaces: return documentedNamespaces>0 && showNamespaces;
case LayoutNavEntry::NamespaceList: return documentedNamespaces>0 && showNamespaces;
case LayoutNavEntry::NamespaceMembers: return documentedNamespaceMembers[NMHL_All]>0;
+ case LayoutNavEntry::Concepts: return documentedConcepts>0;
case LayoutNavEntry::Classes: return annotatedClasses>0;
case LayoutNavEntry::ClassList: return annotatedClasses>0;
case LayoutNavEntry::ClassIndex: return annotatedClasses>0;
@@ -2369,6 +2379,7 @@ static void writeDefaultQuickLinks(TextStream &t,bool compact,
case HLI_InterfaceHierarchy: kind = LayoutNavEntry::InterfaceHierarchy; break;
case HLI_ExceptionHierarchy: kind = LayoutNavEntry::ExceptionHierarchy; break;
case HLI_Classes: kind = LayoutNavEntry::ClassIndex; altKind = LayoutNavEntry::Classes; break;
+ case HLI_Concepts: kind = LayoutNavEntry::Concepts; break;
case HLI_Interfaces: kind = LayoutNavEntry::InterfaceIndex; altKind = LayoutNavEntry::Interfaces; break;
case HLI_Structs: kind = LayoutNavEntry::StructIndex; altKind = LayoutNavEntry::Structs; break;
case HLI_Exceptions: kind = LayoutNavEntry::ExceptionIndex; altKind = LayoutNavEntry::Exceptions; break;
@@ -2385,6 +2396,8 @@ static void writeDefaultQuickLinks(TextStream &t,bool compact,
case HLI_UserGroup: kind = LayoutNavEntry::UserGroup; break;
case HLI_ClassVisible: kind = LayoutNavEntry::ClassList; altKind = LayoutNavEntry::Classes;
highlightParent = TRUE; break;
+ case HLI_ConceptVisible: kind = LayoutNavEntry::Concepts;
+ highlightParent = TRUE; break;
case HLI_InterfaceVisible: kind = LayoutNavEntry::InterfaceList; altKind = LayoutNavEntry::Interfaces;
highlightParent = TRUE; break;
case HLI_StructVisible: kind = LayoutNavEntry::StructList; altKind = LayoutNavEntry::Structs;
diff --git a/src/htmlgen.h b/src/htmlgen.h
index 5c8eff5..3abb733 100644
--- a/src/htmlgen.h
+++ b/src/htmlgen.h
@@ -185,6 +185,8 @@ class HtmlGenerator : public OutputGenerator
void endMemberItem();
void startMemberTemplateParams();
void endMemberTemplateParams(const char *anchor,const char *inheritId);
+ void startCompoundTemplateParams();
+ void endCompoundTemplateParams();
void startMemberGroupHeader(bool);
void endMemberGroupHeader();
diff --git a/src/index.cpp b/src/index.cpp
index 3d3169b..1a91430 100644
--- a/src/index.cpp
+++ b/src/index.cpp
@@ -67,6 +67,7 @@ int hierarchyExceptions;
int documentedFiles;
int documentedGroups;
int documentedNamespaces;
+int documentedConcepts;
int indexedPages;
int documentedClassMembers[CMHL_Total];
int documentedFileMembers[FMHL_Total];
@@ -80,6 +81,7 @@ static void countFiles(int &htmlFiles,int &files);
static int countGroups();
static int countDirs();
static int countNamespaces();
+static int countConcepts();
static int countAnnotatedClasses(int *cp,ClassDef::CompoundType ct);
static void countRelatedPages(int &docPages,int &indexPages);
@@ -102,6 +104,7 @@ void countDataStructures()
countRelatedPages(documentedPages,indexedPages); // "pages"
documentedGroups = countGroups(); // "modules"
documentedNamespaces = countNamespaces(); // "namespaces"
+ documentedConcepts = countConcepts(); // "concepts"
documentedDirs = countDirs(); // "dirs"
// "globals"
// "namespacemembers"
@@ -347,7 +350,9 @@ static void writeMemberToIndex(const Definition *def,const MemberDef *md,bool ad
template<class T>
void addMembersToIndex(T *def,LayoutDocManager::LayoutPart part,
const QCString &name,const QCString &anchor,
- bool addToIndex=TRUE,bool preventSeparateIndex=FALSE)
+ bool addToIndex=TRUE,bool preventSeparateIndex=FALSE,
+ const ConceptLinkedRefMap *concepts = nullptr)
+
{
bool hasMembers = !def->getMemberLists().empty() || !def->getMemberGroups().empty();
Doxygen::indexList->addContentsItem(hasMembers,name,
@@ -360,13 +365,22 @@ void addMembersToIndex(T *def,LayoutDocManager::LayoutPart part,
{
if (cd->isLinkable()) numClasses++;
}
+ int numConcepts=0;
+ if (concepts)
+ {
+ for (const auto &cd : *concepts)
+ {
+ if (cd->isLinkable()) numConcepts++;
+ }
+ }
//printf("addMembersToIndex(def=%s hasMembers=%d numClasses=%d)\n",def->name().data(),hasMembers,numClasses);
- if (hasMembers || numClasses>0)
+ if (hasMembers || numClasses>0 || numConcepts>0)
{
Doxygen::indexList->incContentsDepth();
for (const auto &lde : LayoutDocManager::instance().docEntries(part))
{
- if (lde->kind()==LayoutDocEntry::MemberDef)
+ auto kind = lde->kind();
+ if (kind==LayoutDocEntry::MemberDef)
{
const LayoutDocEntryMemberDef *lmd = (const LayoutDocEntryMemberDef*)lde.get();
MemberList *ml = def->getMemberList(lmd->type);
@@ -381,9 +395,9 @@ void addMembersToIndex(T *def,LayoutDocManager::LayoutPart part,
}
}
}
- else if (lde->kind()==LayoutDocEntry::NamespaceClasses ||
- lde->kind()==LayoutDocEntry::FileClasses ||
- lde->kind()==LayoutDocEntry::ClassNestedClasses
+ else if (kind==LayoutDocEntry::NamespaceClasses ||
+ kind==LayoutDocEntry::FileClasses ||
+ kind==LayoutDocEntry::ClassNestedClasses
)
{
for (const auto &cd : def->getClasses())
@@ -392,12 +406,26 @@ void addMembersToIndex(T *def,LayoutDocManager::LayoutPart part,
{
static bool inlineSimpleStructs = Config_getBool(INLINE_SIMPLE_STRUCTS);
bool isNestedClass = def->definitionType()==Definition::TypeClass;
- addMembersToIndex(cd,LayoutDocManager::Class,cd->displayName(FALSE),cd->anchor(),
+ addMembersToIndex(cd,LayoutDocManager::Class,cd->displayName(lde->kind()==LayoutDocEntry::FileClasses),cd->anchor(),
addToIndex && (isNestedClass || (cd->isSimple() && inlineSimpleStructs)),
preventSeparateIndex || cd->isEmbeddedInOuterScope());
}
}
}
+ else if (kind==LayoutDocEntry::FileConcepts && concepts)
+ {
+ for (const auto &cd : *concepts)
+ {
+ if (cd->isLinkable() && (cd->partOfGroups().empty() || def->definitionType()==Definition::TypeGroup))
+ {
+ Doxygen::indexList->addContentsItem(false,cd->displayName(),
+ cd->getReference(),cd->getOutputFileBase(),0,
+ false,
+ false,
+ cd);
+ }
+ }
+ }
}
Doxygen::indexList->decContentsDepth();
@@ -675,7 +703,8 @@ static void writeDirTreeNode(OutputList &ol, const DirDef *dd, int level, FTVHel
doc = fileVisibleInIndex(fd,src);
if (doc)
{
- addMembersToIndex(fd,LayoutDocManager::File,fd->displayName(),QCString(),TRUE);
+ addMembersToIndex(fd,LayoutDocManager::File,fd->displayName(),QCString(),
+ TRUE,FALSE,&fd->getConcepts());
}
else if (src)
{
@@ -743,7 +772,7 @@ static void writeDirHierarchy(OutputList &ol, FTVHelp* ftv,bool addToIndex)
{
if (doc)
{
- addMembersToIndex(fd.get(),LayoutDocManager::File,fd->displayName(),QCString(),TRUE);
+ addMembersToIndex(fd.get(),LayoutDocManager::File,fd->displayName(),QCString(),TRUE,FALSE,&fd->getConcepts());
}
else if (src)
{
@@ -1486,6 +1515,18 @@ static int countNamespaces()
}
//----------------------------------------------------------------------------
+static int countConcepts()
+{
+ int count=0;
+ for (const auto &cd : *Doxygen::conceptLinkedMap)
+ {
+ if (cd->isLinkableInProject()) count++;
+ }
+ return count;
+}
+
+
+//----------------------------------------------------------------------------
template<typename Ptr> const ClassDef *get_pointer(const Ptr &p);
template<> const ClassDef *get_pointer(const ClassLinkedMap::Ptr &p) { return p.get(); }
template<> const ClassDef *get_pointer(const ClassLinkedRefMap::Ptr &p) { return p; }
@@ -1603,6 +1644,7 @@ static void writeNamespaceMembers(const NamespaceDef *nd,bool addToIndex)
}
}
+static void writeConceptList(const ConceptLinkedRefMap &concepts, FTVHelp *ftv,bool addToIndex);
static void writeNamespaceTree(const NamespaceLinkedRefMap &nsLinkedMap,FTVHelp *ftv,
bool rootOnly,bool addToIndex);
@@ -1614,7 +1656,8 @@ static void writeNamespaceTreeElement(const NamespaceDef *nd,FTVHelp *ftv,
{
bool hasChildren = namespaceHasNestedNamespace(nd) ||
- namespaceHasNestedClass(nd,false,ClassDef::Class);
+ namespaceHasNestedClass(nd,false,ClassDef::Class) ||
+ namespaceHasNestedConcept(nd);
bool isLinkable = nd->isLinkableInProject();
int visibleMembers = countVisibleMembers(nd);
@@ -1647,13 +1690,12 @@ static void writeNamespaceTreeElement(const NamespaceDef *nd,FTVHelp *ftv,
Doxygen::indexList->incContentsDepth();
}
- //printf("*** writeNamespaceTree count=%d addToIndex=%d false=%d classCount=%d\n",
- // count,addToIndex,false,classCount);
if (isDir)
{
ftv->incContentsDepth();
writeNamespaceTree(nd->getNamespaces(),ftv,FALSE,addToIndex);
writeClassTree(nd->getClasses(),ftv,FALSE,FALSE,ClassDef::Class);
+ writeConceptList(nd->getConcepts(),ftv,FALSE);
writeNamespaceMembers(nd,addToIndex);
ftv->decContentsDepth();
}
@@ -3736,6 +3778,7 @@ static void writeGroupTreeNode(OutputList &ol, const GroupDef *gd, int level, FT
numSubItems += gd->getNamespaces().size();
numSubItems += gd->getClasses().size();
numSubItems += gd->getFiles().size();
+ numSubItems += gd->getConcepts().size();
numSubItems += gd->getDirs().size();
numSubItems += gd->getPages().size();
}
@@ -3819,7 +3862,7 @@ static void writeGroupTreeNode(OutputList &ol, const GroupDef *gd, int level, FT
//if (cd->isEmbeddedInOuterScope())
//{
//printf("add class & members %d\n",addToIndex);
- addMembersToIndex(cd,LayoutDocManager::Class,cd->displayName(FALSE),cd->anchor(),addToIndex,TRUE);
+ addMembersToIndex(cd,LayoutDocManager::Class,cd->displayName(),cd->anchor(),addToIndex,TRUE);
//}
//else // only index the class, not its members
//{
@@ -3838,11 +3881,23 @@ static void writeGroupTreeNode(OutputList &ol, const GroupDef *gd, int level, FT
if (nd->isVisible())
{
Doxygen::indexList->addContentsItem(FALSE,
- nd->localName(),nd->getReference(),
+ nd->displayName(),nd->getReference(),
nd->getOutputFileBase(),0,FALSE,FALSE);
}
}
}
+ else if (lde->kind()==LayoutDocEntry::GroupConcepts && addToIndex)
+ {
+ for (const auto &cd : gd->getConcepts())
+ {
+ if (cd->isVisible())
+ {
+ Doxygen::indexList->addContentsItem(FALSE,
+ cd->displayName(),cd->getReference(),
+ cd->getOutputFileBase(),0,FALSE,FALSE);
+ }
+ }
+ }
else if (lde->kind()==LayoutDocEntry::GroupFiles && addToIndex)
{
for (const auto &fd : gd->getFiles())
@@ -4016,6 +4071,211 @@ static void writeGroupIndex(OutputList &ol)
//----------------------------------------------------------------------------
+static void writeConceptList(const ConceptLinkedRefMap &concepts, FTVHelp *ftv,bool addToIndex)
+{
+ for (const auto &cd : concepts)
+ {
+ ftv->addContentsItem(false,cd->displayName(FALSE),cd->getReference(),
+ cd->getOutputFileBase(),0,false,true,cd);
+ if (addToIndex)
+ {
+ Doxygen::indexList->addContentsItem(false,cd->displayName(FALSE),cd->getReference(),
+ cd->getOutputFileBase(),0,false,true);
+ }
+ }
+}
+
+static void writeConceptTreeInsideNamespaceElement(const NamespaceDef *nd,FTVHelp *ftv,
+ bool rootOnly, bool addToIndex);
+
+static void writeConceptTreeInsideNamespace(const NamespaceLinkedRefMap &nsLinkedMap,FTVHelp *ftv,
+ bool rootOnly, bool addToIndex)
+{
+ for (const auto &nd : nsLinkedMap)
+ {
+ writeConceptTreeInsideNamespaceElement(nd,ftv,rootOnly,addToIndex);
+ }
+}
+
+
+static void writeConceptTreeInsideNamespaceElement(const NamespaceDef *nd,FTVHelp *ftv,
+ bool rootOnly, bool addToIndex)
+{
+ if (!nd->isAnonymous() &&
+ (!rootOnly || nd->getOuterScope()==Doxygen::globalScope))
+ {
+ bool isDir = namespaceHasNestedConcept(nd);
+ bool isLinkable = nd->isLinkableInProject();
+
+ //printf("namespace %s isDir=%d\n",nd->name().data(),isDir);
+
+ QCString ref;
+ QCString file;
+ if (isLinkable)
+ {
+ ref = nd->getReference();
+ file = nd->getOutputFileBase();
+ }
+
+ if (isDir)
+ {
+ ftv->addContentsItem(isDir,nd->localName(),ref,file,0,FALSE,TRUE,nd);
+
+ if (addToIndex)
+ {
+ // the namespace entry is already shown under the namespace list so don't
+ // add it to the nav index and don't create a separate index file for it otherwise
+ // it will overwrite the one written for the namespace list.
+ Doxygen::indexList->addContentsItem(isDir,nd->localName(),ref,file,QCString(),
+ false, // separateIndex
+ false // addToNavIndex
+ );
+ }
+ if (addToIndex)
+ {
+ Doxygen::indexList->incContentsDepth();
+ }
+
+ ftv->incContentsDepth();
+ writeConceptTreeInsideNamespace(nd->getNamespaces(),ftv,FALSE,addToIndex);
+ writeConceptList(nd->getConcepts(),ftv,addToIndex);
+ ftv->decContentsDepth();
+
+ if (addToIndex)
+ {
+ Doxygen::indexList->decContentsDepth();
+ }
+ }
+ }
+}
+
+static void writeConceptRootList(FTVHelp *ftv,bool addToIndex)
+{
+ for (const auto &cd : *Doxygen::conceptLinkedMap)
+ {
+ if (cd->getOuterScope()==0 ||
+ cd->getOuterScope()==Doxygen::globalScope)
+ {
+ //printf("*** adding %s hasSubPages=%d hasSections=%d\n",pageTitle.data(),hasSubPages,hasSections);
+ ftv->addContentsItem(
+ false,cd->localName(),cd->getReference(),cd->getOutputFileBase(),
+ 0,false,true,cd.get());
+ if (addToIndex)
+ {
+ Doxygen::indexList->addContentsItem(
+ false,cd->localName(),cd->getReference(),cd->getOutputFileBase(),
+ 0,false,true);
+ }
+ }
+ }
+}
+
+static void writeConceptIndex(OutputList &ol)
+{
+ if (documentedConcepts==0) return;
+ ol.pushGeneratorState();
+ // 1.{
+ ol.disable(OutputGenerator::Man);
+ ol.disable(OutputGenerator::Docbook);
+ LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::Concepts);
+ QCString title = lne ? lne->title() : theTranslator->trConceptList();
+ bool addToIndex = lne==0 || lne->visible();
+
+ startFile(ol,"concepts",0,title,HLI_Concepts);
+ startTitle(ol,0);
+ ol.parseText(title);
+ endTitle(ol,0,0);
+ ol.startContents();
+ ol.startTextBlock();
+ ol.parseText(lne ? lne->intro() : theTranslator->trConceptListDescription(Config_getBool(EXTRACT_ALL)));
+ ol.endTextBlock();
+
+ // ---------------
+ // Normal group index for Latex/RTF
+ // ---------------
+ // 2.{
+ ol.pushGeneratorState();
+ ol.disable(OutputGenerator::Html);
+
+ bool first=TRUE;
+ for (const auto &cd : *Doxygen::conceptLinkedMap)
+ {
+ if (cd->isLinkableInProject())
+ {
+ if (first)
+ {
+ ol.startIndexList();
+ first=FALSE;
+ }
+ //ol.writeStartAnnoItem("namespace",nd->getOutputFileBase(),0,nd->name());
+ ol.startIndexKey();
+ ol.writeObjectLink(0,cd->getOutputFileBase(),0,cd->displayName());
+ ol.endIndexKey();
+
+ bool hasBrief = !cd->briefDescription().isEmpty();
+ ol.startIndexValue(hasBrief);
+ if (hasBrief)
+ {
+ //ol.docify(" (");
+ ol.generateDoc(
+ cd->briefFile(),cd->briefLine(),
+ cd.get(),0,
+ cd->briefDescription(TRUE),
+ FALSE, // index words
+ FALSE, // isExample
+ 0, // example name
+ TRUE, // single line
+ TRUE, // link from index
+ Config_getBool(MARKDOWN_SUPPORT)
+ );
+ //ol.docify(")");
+ }
+ ol.endIndexValue(cd->getOutputFileBase(),hasBrief);
+
+ }
+ }
+ if (!first) ol.endIndexList();
+
+ ol.popGeneratorState();
+ // 2.}
+
+ // ---------------
+ // interactive group index for HTML
+ // ---------------
+ // 2.{
+ ol.pushGeneratorState();
+ ol.disableAllBut(OutputGenerator::Html);
+
+ {
+ if (addToIndex)
+ {
+ Doxygen::indexList->addContentsItem(TRUE,title,0,"concepts",0,TRUE,TRUE);
+ Doxygen::indexList->incContentsDepth();
+ }
+ FTVHelp ftv(false);
+ for (const auto &nd : *Doxygen::namespaceLinkedMap)
+ {
+ writeConceptTreeInsideNamespaceElement(nd.get(),&ftv,true,addToIndex);
+ }
+ writeConceptRootList(&ftv,addToIndex);
+ TextStream t;
+ ftv.generateTreeViewInline(t);
+ ol.writeString(t.str().c_str());
+ if (addToIndex)
+ {
+ Doxygen::indexList->decContentsDepth();
+ }
+ }
+ ol.popGeneratorState();
+ // 2.}
+
+ endFile(ol);
+ ol.popGeneratorState();
+ // 1.}
+}
+
+//----------------------------------------------------------------------------
+
static void writeUserGroupStubPage(OutputList &ol,LayoutNavEntry *lne)
{
if (lne->baseFile().left(9)=="usergroup")
@@ -4298,6 +4558,12 @@ static void writeIndex(OutputList &ol)
ol.parseText(/*projPrefix+*/(fortranOpt?theTranslator->trModulesIndex():theTranslator->trNamespaceIndex()));
ol.endIndexSection(isNamespaceIndex);
}
+ if (documentedConcepts>0)
+ {
+ ol.startIndexSection(isConceptIndex);
+ ol.parseText(/*projPrefix+*/theTranslator->trConceptIndex());
+ ol.endIndexSection(isConceptIndex);
+ }
if (hierarchyInterfaces>0)
{
ol.startIndexSection(isClassHierarchyIndex);
@@ -4369,6 +4635,12 @@ static void writeIndex(OutputList &ol)
ol.parseText(/*projPrefix+*/(fortranOpt?theTranslator->trModuleDocumentation():theTranslator->trNamespaceDocumentation()));
ol.endIndexSection(isNamespaceDocumentation);
}
+ if (documentedConcepts>0)
+ {
+ ol.startIndexSection(isConceptDocumentation);
+ ol.parseText(/*projPrefix+*/theTranslator->trConceptDocumentation());
+ ol.endIndexSection(isConceptDocumentation);
+ }
if (annotatedInterfacesPrinted>0)
{
ol.startIndexSection(isClassDocumentation);
@@ -4510,6 +4782,10 @@ static void writeIndexHierarchyEntries(OutputList &ol,const LayoutNavEntryList &
writeAnnotatedIndex(ol);
}
break;
+ case LayoutNavEntry::Concepts:
+ msg("Generating concept index...\n");
+ writeConceptIndex(ol);
+ break;
case LayoutNavEntry::ClassList:
msg("Generating annotated compound index...\n");
writeAnnotatedIndex(ol);
@@ -4747,6 +5023,7 @@ static bool quickLinkVisible(LayoutNavEntry::Kind kind)
case LayoutNavEntry::Namespaces: return documentedNamespaces>0 && showNamespaces;
case LayoutNavEntry::NamespaceList: return documentedNamespaces>0 && showNamespaces;
case LayoutNavEntry::NamespaceMembers: return documentedNamespaceMembers[NMHL_All]>0;
+ case LayoutNavEntry::Concepts: return documentedConcepts>0;
case LayoutNavEntry::Classes: return annotatedClasses>0;
case LayoutNavEntry::ClassList: return annotatedClasses>0;
case LayoutNavEntry::ClassIndex: return annotatedClasses>0;
diff --git a/src/index.h b/src/index.h
index 8b090dc..a595ec2 100644
--- a/src/index.h
+++ b/src/index.h
@@ -119,6 +119,7 @@ enum IndexSections
isModuleIndex,
isDirIndex,
isNamespaceIndex,
+ isConceptIndex,
isClassHierarchyIndex,
isCompoundIndex,
isFileIndex,
@@ -127,6 +128,7 @@ enum IndexSections
isDirDocumentation,
isNamespaceDocumentation,
isClassDocumentation,
+ isConceptDocumentation,
isFileDocumentation,
isExampleDocumentation,
isPageDocumentation,
@@ -145,6 +147,7 @@ enum HighlightedItem
HLI_InterfaceHierarchy,
HLI_ExceptionHierarchy,
HLI_Classes,
+ HLI_Concepts,
HLI_Interfaces,
HLI_Structs,
HLI_Exceptions,
@@ -162,6 +165,7 @@ enum HighlightedItem
HLI_UserGroup,
HLI_ClassVisible,
+ HLI_ConceptVisible,
HLI_InterfaceVisible,
HLI_StructVisible,
HLI_ExceptionVisible,
@@ -238,6 +242,7 @@ extern int hierarchyExceptions;
extern int documentedFiles;
extern int documentedGroups;
extern int documentedNamespaces;
+extern int documentedConcepts;
extern int indexedPages;
extern int documentedClassMembers[CMHL_Total];
extern int documentedFileMembers[FMHL_Total];
diff --git a/src/latexgen.cpp b/src/latexgen.cpp
index 0f6d110..92bbfd7 100644
--- a/src/latexgen.cpp
+++ b/src/latexgen.cpp
@@ -719,6 +719,10 @@ void LatexGenerator::startIndexSection(IndexSections is)
if (compactLatex) m_t << "\\doxysection"; else m_t << "\\chapter";
m_t << "{"; //Namespace Index}\n"
break;
+ case isConceptIndex:
+ if (compactLatex) m_t << "\\doxysection"; else m_t << "\\chapter";
+ m_t << "{"; //Concept Index}\n"
+ break;
case isClassHierarchyIndex:
if (compactLatex) m_t << "\\doxysection"; else m_t << "\\chapter";
m_t << "{"; //Hierarchical Index}\n"
@@ -774,6 +778,19 @@ void LatexGenerator::startIndexSection(IndexSections is)
}
}
break;
+ case isConceptDocumentation:
+ {
+ for (const auto &cd : *Doxygen::conceptLinkedMap)
+ {
+ if (cd->isLinkableInProject() && !cd->isAlias())
+ {
+ if (compactLatex) m_t << "\\doxysection"; else m_t << "\\chapter";
+ m_t << "{"; // Concept Documentation}\n":
+ break;
+ }
+ }
+ }
+ break;
case isClassDocumentation:
{
for (const auto &cd : *Doxygen::classLinkedMap)
@@ -858,6 +875,9 @@ void LatexGenerator::endIndexSection(IndexSections is)
case isNamespaceIndex:
m_t << "}\n\\input{namespaces}\n";
break;
+ case isConceptIndex:
+ m_t << "}\n\\input{concepts}\n";
+ break;
case isClassHierarchyIndex:
m_t << "}\n\\input{hierarchy}\n";
break;
@@ -921,6 +941,23 @@ void LatexGenerator::endIndexSection(IndexSections is)
}
}
break;
+ case isConceptDocumentation:
+ {
+ bool found=FALSE;
+ for (const auto &cd : *Doxygen::conceptLinkedMap)
+ {
+ if (cd->isLinkableInProject() && !cd->isAlias())
+ {
+ if (!found)
+ {
+ m_t << "}\n";
+ found=true;
+ }
+ m_t << "\\input{" << cd->getOutputFileBase() << "}\n";
+ }
+ }
+ }
+ break;
case isClassDocumentation:
{
bool found=FALSE;
diff --git a/src/latexgen.h b/src/latexgen.h
index 4e92280..4a8be62 100644
--- a/src/latexgen.h
+++ b/src/latexgen.h
@@ -192,6 +192,8 @@ class LatexGenerator : public OutputGenerator
void endMemberItem();
void startMemberTemplateParams();
void endMemberTemplateParams(const char *,const char *);
+ void startCompoundTemplateParams() { startSubsubsection(); }
+ void endCompoundTemplateParams() { endSubsubsection(); }
void startMemberGroupHeader(bool);
void endMemberGroupHeader();
diff --git a/src/layout.cpp b/src/layout.cpp
index fe71db0..bd88d35 100644
--- a/src/layout.cpp
+++ b/src/layout.cpp
@@ -319,6 +319,13 @@ class LayoutParser
fortranOpt || sliceOpt ? theTranslator->trModulesMemberDescription(extractAll) : theTranslator->trNamespaceMemberDescription(extractAll),
"namespacemembers"
},
+ { "concepts",
+ LayoutNavEntry::Concepts,
+ theTranslator->trConcept(true,false),
+ theTranslator->trConceptList(),
+ theTranslator->trConceptListDescription(extractAll),
+ "concepts"
+ },
{ "classindex",
LayoutNavEntry::ClassIndex,
fortranOpt ? theTranslator->trDataTypes() : vhdlOpt ? theTranslator->trDesignUnits() : theTranslator->trCompoundIndex(),
@@ -585,6 +592,19 @@ class LayoutParser
m_part = -1;
}
+ void startConcept(const XMLHandlers::Attributes &)
+ {
+ LayoutDocManager::instance().clear(LayoutDocManager::Concept);
+ m_scope="concept/";
+ m_part = (int)LayoutDocManager::Concept;
+ }
+
+ void endConcept()
+ {
+ m_scope="";
+ m_part = -1;
+ }
+
void startFile(const XMLHandlers::Attributes &)
{
LayoutDocManager::instance().clear(LayoutDocManager::File);
@@ -973,6 +993,31 @@ static const std::map< std::string, ElementCallbacks > g_elementHandlers =
endCb()
} },
+ // concept layout handlers
+ { "concept", { startCb(&LayoutParser::startConcept),
+ endCb(&LayoutParser::endConcept)
+ } },
+
+ { "concept/briefdescription", { startCb(&LayoutParser::startSimpleEntry, LayoutDocEntry::BriefDesc),
+ endCb()
+ } },
+ { "concept/definition", { startCb(&LayoutParser::startSectionEntry, LayoutDocEntry::ConceptDefinition,
+ []() { return compileOptions(theTranslator->trConceptDefinition()); }),
+ endCb()
+ } },
+ { "concept/includes", { startCb(&LayoutParser::startSimpleEntry, LayoutDocEntry::ClassIncludes),
+ endCb()
+ } },
+ { "concept/sourcelink", { startCb(&LayoutParser::startSimpleEntry, LayoutDocEntry::FileSourceLink),
+ endCb()
+ } },
+ { "concept/detaileddescription", { startCb(&LayoutParser::startSectionEntry,LayoutDocEntry::DetailedDesc,
+ []() { return compileOptions(theTranslator->trDetailedDescription()); }),
+ endCb()
+ } },
+ { "concept/authorsection", { startCb(&LayoutParser::startSimpleEntry, LayoutDocEntry::AuthorSection),
+ endCb()
+ } },
// namespace layout handlers
{ "namespace", { startCb(&LayoutParser::startNamespace),
endCb(&LayoutParser::endNamespace)
@@ -1016,6 +1061,10 @@ static const std::map< std::string, ElementCallbacks > g_elementHandlers =
SrcLangExt_Fortran,theTranslator->trDataTypes()); }),
endCb()
} },
+ { "namespace/memberdecl/concepts", { startCb(&LayoutParser::startSectionEntry, LayoutDocEntry::NamespaceConcepts,
+ []() { return compileOptions(theTranslator->trConcept(true,false)); }),
+ endCb()
+ } },
{ "namespace/memberdecl/structs", { startCb(&LayoutParser::startSectionEntry,LayoutDocEntry::NamespaceStructs,
[]() { return compileOptions(theTranslator->trStructs()); }),
endCb()
@@ -1135,6 +1184,10 @@ static const std::map< std::string, ElementCallbacks > g_elementHandlers =
SrcLangExt_Fortran,theTranslator->trDataTypes()); }),
endCb()
} },
+ { "file/memberdecl/concepts", { startCb(&LayoutParser::startSectionEntry, LayoutDocEntry::FileConcepts,
+ []() { return compileOptions(theTranslator->trConcept(true,false)); }),
+ endCb()
+ } },
{ "file/memberdecl/structs", { startCb(&LayoutParser::startSectionEntry,LayoutDocEntry::FileStructs,
[]() { return compileOptions(theTranslator->trStructs()); }),
endCb()
@@ -1255,6 +1308,10 @@ static const std::map< std::string, ElementCallbacks > g_elementHandlers =
[]() { return compileOptions(/* default */ theTranslator->trCompounds(),
SrcLangExt_VHDL, theTranslator->trVhdlType(VhdlDocGen::ENTITY,FALSE),
SrcLangExt_Fortran, theTranslator->trDataTypes()); }),
+ endCb()
+ } },
+ { "group/memberdecl/concepts", { startCb(&LayoutParser::startSectionEntry, LayoutDocEntry::GroupConcepts,
+ []() { return compileOptions(theTranslator->trConcept(true,false)); }),
endCb()
} },
{ "group/memberdecl/namespaces", { startCb(&LayoutParser::startSectionEntry, LayoutDocEntry::GroupNamespaces,
diff --git a/src/layout.h b/src/layout.h
index 851af22..900d192 100644
--- a/src/layout.h
+++ b/src/layout.h
@@ -45,19 +45,22 @@ struct LayoutDocEntry
ClassCollaborationGraph, ClassAllMembersLink,
ClassUsedFiles,
+ // Concept specific items
+ ConceptDefinition,
+
// Namespace specific items
NamespaceNestedNamespaces, NamespaceNestedConstantGroups,
- NamespaceClasses, NamespaceInterfaces, NamespaceStructs, NamespaceExceptions,
+ NamespaceClasses, NamespaceConcepts, NamespaceInterfaces, NamespaceStructs, NamespaceExceptions,
NamespaceInlineClasses,
// File specific items
- FileClasses, FileInterfaces, FileStructs, FileExceptions, FileConstantGroups, FileNamespaces,
+ FileClasses, FileConcepts, FileInterfaces, FileStructs, FileExceptions, FileConstantGroups, FileNamespaces,
FileIncludes, FileIncludeGraph,
FileIncludedByGraph, FileSourceLink,
FileInlineClasses,
// Group specific items
- GroupClasses, GroupInlineClasses, GroupNamespaces,
+ GroupClasses, GroupConcepts, GroupInlineClasses, GroupNamespaces,
GroupDirs, GroupNestedGroups, GroupFiles,
GroupGraph, GroupPageDocs,
@@ -130,6 +133,7 @@ struct LayoutNavEntry
Namespaces,
NamespaceList,
NamespaceMembers,
+ Concepts,
Classes,
ClassList,
ClassIndex,
@@ -196,7 +200,7 @@ class LayoutDocManager
public:
enum LayoutPart
{
- Class, Namespace, File, Group, Directory,
+ Class, Concept, Namespace, File, Group, Directory,
NrParts
};
/** Returns a reference to this singleton. */
diff --git a/src/mangen.h b/src/mangen.h
index e621988..8b9c3cd 100644
--- a/src/mangen.h
+++ b/src/mangen.h
@@ -111,6 +111,8 @@ class ManGenerator : public OutputGenerator
void endMemberItem();
void startMemberTemplateParams() {}
void endMemberTemplateParams(const char *,const char *) {}
+ void startCompoundTemplateParams() { startSubsubsection(); }
+ void endCompoundTemplateParams() { endSubsubsection(); }
void startMemberGroupHeader(bool);
void endMemberGroupHeader();
diff --git a/src/memberdef.cpp b/src/memberdef.cpp
index 38164ef..4e9f4a9 100644
--- a/src/memberdef.cpp
+++ b/src/memberdef.cpp
@@ -4074,6 +4074,10 @@ void MemberDefImpl::setAnchor()
buf[19]='\0';
memAnchor.prepend(buf);
}
+ if (!m_impl->requiresClause.isEmpty())
+ {
+ memAnchor+=" "+m_impl->requiresClause;
+ }
// convert to md5 hash
uchar md5_sig[16];
diff --git a/src/namespacedef.cpp b/src/namespacedef.cpp
index d392f69..4bfaa2b 100644
--- a/src/namespacedef.cpp
+++ b/src/namespacedef.cpp
@@ -32,6 +32,7 @@
#include "config.h"
#include "definitionimpl.h"
#include "membername.h"
+#include "conceptdef.h"
//------------------------------------------------------------------
static QCString makeDisplayName(const NamespaceDef *nd,bool includeScope)
@@ -65,6 +66,7 @@ class NamespaceDefImpl : public DefinitionMixin<NamespaceDefMutable>
virtual void writeQuickMemberLinks(OutputList &ol,const MemberDef *currentMd) const;
virtual void writeTagFile(TextStream &);
virtual void insertClass(const ClassDef *cd);
+ virtual void insertConcept(const ConceptDef *cd);
virtual void insertNamespace(const NamespaceDef *nd);
virtual void insertMember(MemberDef *md);
virtual void computeAnchors();
@@ -103,6 +105,7 @@ class NamespaceDefImpl : public DefinitionMixin<NamespaceDefMutable>
virtual ClassLinkedRefMap getStructs() const { return structs; }
virtual ClassLinkedRefMap getExceptions() const { return exceptions; }
virtual NamespaceLinkedRefMap getNamespaces() const { return namespaces; }
+ virtual ConceptLinkedRefMap getConcepts() const { return m_concepts; }
virtual QCString title() const;
virtual QCString compoundTypeString() const;
@@ -118,6 +121,7 @@ class NamespaceDefImpl : public DefinitionMixin<NamespaceDefMutable>
void startMemberDeclarations(OutputList &ol);
void endMemberDeclarations(OutputList &ol);
void writeClassDeclarations(OutputList &ol,const QCString &title,const ClassLinkedRefMap &d);
+ void writeConcepts(OutputList &ol,const QCString &title);
void writeInlineClasses(OutputList &ol);
void writeMemberGroups(OutputList &ol);
void writeAuthorSection(OutputList &ol);
@@ -126,6 +130,7 @@ class NamespaceDefImpl : public DefinitionMixin<NamespaceDefMutable>
void writeSummaryLinks(OutputList &ol) const;
void addNamespaceAttributes(OutputList &ol);
void writeClassesToTagFile(TextStream &,const ClassLinkedRefMap &d);
+ void writeConceptsToTagFile(TextStream &);
void writeNamespaceDeclarations(OutputList &ol,const QCString &title,
bool isConstantGroup=false);
@@ -144,6 +149,7 @@ class NamespaceDefImpl : public DefinitionMixin<NamespaceDefMutable>
ClassLinkedRefMap interfaces;
ClassLinkedRefMap structs;
ClassLinkedRefMap exceptions;
+ ConceptLinkedRefMap m_concepts;
NamespaceLinkedRefMap namespaces;
bool m_subGrouping = false;
enum { NAMESPACE, MODULE, CONSTANT_GROUP, LIBRARY } m_type;
@@ -223,6 +229,8 @@ class NamespaceDefAliasImpl : public DefinitionAliasMixin<NamespaceDef>
{ return getNSAlias()->getExceptions(); }
virtual NamespaceLinkedRefMap getNamespaces() const
{ return getNSAlias()->getNamespaces(); }
+ virtual ConceptLinkedRefMap getConcepts() const
+ { return getNSAlias()->getConcepts(); }
virtual QCString title() const
{ return getNSAlias()->title(); }
virtual QCString compoundTypeString() const
@@ -345,6 +353,10 @@ void NamespaceDefImpl::addInnerCompound(const Definition *d)
{
insertClass(toClassDef(d));
}
+ else if (d->definitionType()==Definition::TypeConcept)
+ {
+ insertConcept(toConceptDef(d));
+ }
}
void NamespaceDefImpl::insertClass(const ClassDef *cd)
@@ -370,6 +382,11 @@ void NamespaceDefImpl::insertClass(const ClassDef *cd)
d.add(cd->name(),cd);
}
+void NamespaceDefImpl::insertConcept(const ConceptDef *cd)
+{
+ m_concepts.add(cd->name(),cd);
+}
+
void NamespaceDefImpl::insertNamespace(const NamespaceDef *nd)
{
namespaces.add(nd->name(),nd);
@@ -578,6 +595,11 @@ void NamespaceDefImpl::writeTagFile(TextStream &tagFile)
writeClassesToTagFile(tagFile, exceptions);
}
break;
+ case LayoutDocEntry::NamespaceConcepts:
+ {
+ writeConceptsToTagFile(tagFile);
+ }
+ break;
case LayoutDocEntry::MemberDecl:
{
const LayoutDocEntryMemberDecl *lmd = (const LayoutDocEntryMemberDecl*)lde.get();
@@ -740,6 +762,11 @@ void NamespaceDefImpl::writeClassDeclarations(OutputList &ol,const QCString &tit
d.writeDeclaration(ol,0,title,TRUE);
}
+void NamespaceDefImpl::writeConcepts(OutputList &ol,const QCString &title)
+{
+ m_concepts.writeDeclaration(ol,title,TRUE);
+}
+
void NamespaceDefImpl::writeInlineClasses(OutputList &ol)
{
classes.writeDocumentation(ol,this);
@@ -819,6 +846,13 @@ void NamespaceDefImpl::writeSummaryLinks(OutputList &ol) const
ol.writeSummaryLink(0,label,ls->title(lang),first);
first=FALSE;
}
+ else if (lde->kind()==LayoutDocEntry::NamespaceConcepts && m_concepts.declVisible())
+ {
+ const LayoutDocEntrySection *ls = (const LayoutDocEntrySection*)lde.get();
+ QCString label = "concepts";
+ ol.writeSummaryLink(0,label,ls->title(lang),first);
+ first=FALSE;
+ }
else if (lde->kind()== LayoutDocEntry::MemberDecl)
{
const LayoutDocEntryMemberDecl *lmd = (const LayoutDocEntryMemberDecl*)lde.get();
@@ -863,6 +897,17 @@ void NamespaceDefImpl::writeClassesToTagFile(TextStream &tagFile,const ClassLink
}
}
+void NamespaceDefImpl::writeConceptsToTagFile(TextStream &tagFile)
+{
+ for (const auto &cd : m_concepts)
+ {
+ if (cd->isLinkableInProject())
+ {
+ tagFile << " <concept>" << convertToXML(cd->name()) << "</concept>\n";
+ }
+ }
+}
+
void NamespaceDefImpl::writeDocumentation(OutputList &ol)
{
static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW);
@@ -933,6 +978,12 @@ void NamespaceDefImpl::writeDocumentation(OutputList &ol)
writeClassDeclarations(ol,ls->title(lang),exceptions);
}
break;
+ case LayoutDocEntry::NamespaceConcepts:
+ {
+ const LayoutDocEntrySection *ls = (const LayoutDocEntrySection*)lde.get();
+ writeConcepts(ol,ls->title(lang));
+ }
+ break;
case LayoutDocEntry::NamespaceNestedNamespaces:
{
const LayoutDocEntrySection *ls = (const LayoutDocEntrySection*)lde.get();
@@ -988,7 +1039,9 @@ void NamespaceDefImpl::writeDocumentation(OutputList &ol)
case LayoutDocEntry::ClassAllMembersLink:
case LayoutDocEntry::ClassUsedFiles:
case LayoutDocEntry::ClassInlineClasses:
+ case LayoutDocEntry::ConceptDefinition:
case LayoutDocEntry::FileClasses:
+ case LayoutDocEntry::FileConcepts:
case LayoutDocEntry::FileInterfaces:
case LayoutDocEntry::FileStructs:
case LayoutDocEntry::FileExceptions:
@@ -1000,6 +1053,7 @@ void NamespaceDefImpl::writeDocumentation(OutputList &ol)
case LayoutDocEntry::FileSourceLink:
case LayoutDocEntry::FileInlineClasses:
case LayoutDocEntry::GroupClasses:
+ case LayoutDocEntry::GroupConcepts:
case LayoutDocEntry::GroupInlineClasses:
case LayoutDocEntry::GroupNamespaces:
case LayoutDocEntry::GroupDirs:
@@ -1449,7 +1503,7 @@ QCString NamespaceDefImpl::compoundTypeString() const
}
else if(lang==SrcLangExt_CSharp)
{
- return "namespace";
+ return "namespace";
}
else if (lang==SrcLangExt_Fortran)
{
@@ -1474,7 +1528,7 @@ QCString NamespaceDefImpl::compoundTypeString() const
err_full(getDefFileName(),getDefLine(),"Internal inconsistency: namespace in IDL not module, library or constant group");
}
}
- return "";
+ return "namespace";
}
void NamespaceDefImpl::setMetaData(const QCString &m)
diff --git a/src/namespacedef.h b/src/namespacedef.h
index 0dc0005..711c9df 100644
--- a/src/namespacedef.h
+++ b/src/namespacedef.h
@@ -25,8 +25,10 @@
class MemberList;
class ClassDef;
+class ConceptDef;
class OutputList;
class ClassLinkedRefMap;
+class ConceptLinkedRefMap;
class MemberDef;
class NamespaceDef;
class NamespaceDef;
@@ -94,6 +96,9 @@ class NamespaceDef : public Definition
/*! Returns the namespaces contained in this namespace */
virtual NamespaceLinkedRefMap getNamespaces() const = 0;
+ /*! Returns the concepts contained in this namespace */
+ virtual ConceptLinkedRefMap getConcepts() const = 0;
+
virtual QCString title() const = 0;
virtual QCString compoundTypeString() const = 0;
};
@@ -110,6 +115,7 @@ class NamespaceDefMutable : public DefinitionMutable, public NamespaceDef
virtual void writeQuickMemberLinks(OutputList &ol,const MemberDef *currentMd) const = 0;
virtual void writeTagFile(TextStream &) = 0;
virtual void insertClass(const ClassDef *cd) = 0;
+ virtual void insertConcept(const ConceptDef *cd) = 0;
virtual void insertNamespace(const NamespaceDef *nd) = 0;
virtual void insertMember(MemberDef *md) = 0; // md cannot be const, since setSectionList is called on it
virtual void computeAnchors() = 0;
diff --git a/src/outputgen.h b/src/outputgen.h
index 9eab898..6cfb14b 100644
--- a/src/outputgen.h
+++ b/src/outputgen.h
@@ -404,6 +404,8 @@ class OutputGenerator : public BaseOutputDocInterface
virtual void endMemberItem() = 0;
virtual void startMemberTemplateParams() = 0;
virtual void endMemberTemplateParams(const char *,const char *) = 0;
+ virtual void startCompoundTemplateParams() = 0;
+ virtual void endCompoundTemplateParams() = 0;
virtual void startMemberGroupHeader(bool) = 0;
virtual void endMemberGroupHeader() = 0;
virtual void startMemberGroupDocs() = 0;
diff --git a/src/outputlist.h b/src/outputlist.h
index 7baef7a..fbb8801 100644
--- a/src/outputlist.h
+++ b/src/outputlist.h
@@ -213,6 +213,10 @@ class OutputList : public OutputDocInterface
{ forall(&OutputGenerator::startMemberTemplateParams); }
void endMemberTemplateParams(const char *anchor,const char *inheritId)
{ forall(&OutputGenerator::endMemberTemplateParams,anchor,inheritId); }
+ void startCompoundTemplateParams()
+ { forall(&OutputGenerator::startCompoundTemplateParams); }
+ void endCompoundTemplateParams()
+ { forall(&OutputGenerator::endCompoundTemplateParams); }
void startMemberGroupHeader(bool b)
{ forall(&OutputGenerator::startMemberGroupHeader,b); }
void endMemberGroupHeader()
diff --git a/src/parserintf.h b/src/parserintf.h
index 05b3adf..9c43e93 100644
--- a/src/parserintf.h
+++ b/src/parserintf.h
@@ -88,9 +88,9 @@ class CodeParserInterface
/** Parses a source file or fragment with the goal to produce
* highlighted and cross-referenced output.
* @param[in] codeOutIntf Abstract interface for writing the result.
- * @param[in] lang The programming language of the code fragment.
* @param[in] scopeName Name of scope to which the code belongs.
* @param[in] input Actual code in the form of a string
+ * @param[in] lang The programming language of the code fragment.
* @param[in] isExampleBlock TRUE iff the code is part of an example.
* @param[in] exampleName Name of the example.
* @param[in] fileDef File definition to which the code
diff --git a/src/perlmodgen.cpp b/src/perlmodgen.cpp
index ab931f9..6bf7319 100644
--- a/src/perlmodgen.cpp
+++ b/src/perlmodgen.cpp
@@ -1434,6 +1434,11 @@ static void addTemplateList(const ClassDef *cd,PerlModOutput &output)
addTemplateArgumentList(cd->templateArguments(),output,cd->name());
}
+static void addTemplateList(const ConceptDef *cd,PerlModOutput &output)
+{
+ addTemplateArgumentList(cd->getTemplateParameterList(),output,cd->name());
+}
+
static void addPerlModDocBlock(PerlModOutput &output,
const char *name,
const QCString &fileName,
@@ -1516,7 +1521,9 @@ public:
void generatePerlModSection(const Definition *d, MemberList *ml,
const char *name, const char *header=0);
void addListOfAllMembers(const ClassDef *cd);
+ void addIncludeInfo(const IncludeInfo *ii);
void generatePerlModForClass(const ClassDef *cd);
+ void generatePerlModForConcept(const ConceptDef *cd);
void generatePerlModForNamespace(const NamespaceDef *nd);
void generatePerlModForFile(const FileDef *fd);
void generatePerlModForGroup(const GroupDef *gd);
@@ -1780,6 +1787,22 @@ void PerlModGenerator::generatePerlUserDefinedSection(const Definition *d, const
}
}
+void PerlModGenerator::addIncludeInfo(const IncludeInfo *ii)
+{
+ if (ii)
+ {
+ QCString nm = ii->includeName;
+ if (nm.isEmpty() && ii->fileDef) nm = ii->fileDef->docName();
+ if (!nm.isEmpty())
+ {
+ m_output.openHash("includes");
+ m_output.addFieldBoolean("local", ii->local)
+ .addFieldQuotedString("name", nm)
+ .closeHash();
+ }
+ }
+}
+
void PerlModGenerator::generatePerlModForClass(const ClassDef *cd)
{
// + brief description
@@ -1844,23 +1867,7 @@ void PerlModGenerator::generatePerlModForClass(const ClassDef *cd)
m_output.closeList();
}
- const IncludeInfo *ii=cd->includeInfo();
- if (ii)
- {
- QCString nm = ii->includeName;
- if (nm.isEmpty() && ii->fileDef) nm = ii->fileDef->docName();
- if (!nm.isEmpty())
- {
- m_output.openHash("includes");
-#if 0
- if (ii->fileDef && !ii->fileDef->isReference()) // TODO: support external references
- t << " id=\"" << ii->fileDef->getOutputFileBase() << "\"";
-#endif
- m_output.addFieldBoolean("local", ii->local)
- .addFieldQuotedString("name", nm)
- .closeHash();
- }
- }
+ addIncludeInfo(cd->includeInfo());
addTemplateList(cd,m_output);
addListOfAllMembers(cd);
@@ -1922,6 +1929,22 @@ void PerlModGenerator::generatePerlModForClass(const ClassDef *cd)
m_output.closeHash();
}
+void PerlModGenerator::generatePerlModForConcept(const ConceptDef *cd)
+{
+ if (cd->isReference()) return; // skip external references
+
+ m_output.openHash()
+ .addFieldQuotedString("name", cd->name());
+
+ addIncludeInfo(cd->includeInfo());
+ addTemplateList(cd,m_output);
+ m_output.addFieldQuotedString("initializer", cd->initializer());
+ addPerlModDocBlock(m_output,"brief",cd->getDefFileName(),cd->getDefLine(),0,0,cd->briefDescription());
+ addPerlModDocBlock(m_output,"detailed",cd->getDefFileName(),cd->getDefLine(),0,0,cd->documentation());
+
+ m_output.closeHash();
+}
+
void PerlModGenerator::generatePerlModForNamespace(const NamespaceDef *nd)
{
// + contained class definitions
@@ -2154,6 +2177,11 @@ bool PerlModGenerator::generatePerlModOutput()
generatePerlModForClass(cd.get());
m_output.closeList();
+ m_output.openList("concepts");
+ for (const auto &cd : *Doxygen::conceptLinkedMap)
+ generatePerlModForConcept(cd.get());
+ m_output.closeList();
+
m_output.openList("namespaces");
for (const auto &nd : *Doxygen::namespaceLinkedMap)
generatePerlModForNamespace(nd.get());
diff --git a/src/rtfgen.cpp b/src/rtfgen.cpp
index 91e4996..032d568 100644
--- a/src/rtfgen.cpp
+++ b/src/rtfgen.cpp
@@ -447,6 +447,10 @@ void RTFGenerator::startIndexSection(IndexSections is)
//Namespace Index
beginRTFChapter();
break;
+ case isConceptIndex:
+ //Concept Index
+ beginRTFChapter();
+ break;
case isClassHierarchyIndex:
//Hierarchical Index
DBG_RTF(m_t << "{\\comment start classhierarchy}\n")
@@ -503,6 +507,19 @@ void RTFGenerator::startIndexSection(IndexSections is)
}
}
break;
+ case isConceptDocumentation:
+ {
+ // Concept Documentation
+ for (const auto &cd : *Doxygen::conceptLinkedMap)
+ {
+ if (cd->isLinkableInProject())
+ {
+ beginRTFChapter();
+ break;
+ }
+ }
+ }
+ break;
case isClassDocumentation:
{
//Compound Documentation
@@ -700,6 +717,11 @@ void RTFGenerator::endIndexSection(IndexSections is)
m_t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \"namespaces.rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n";
break;
+ case isConceptIndex:
+ m_t << "\\par " << rtf_Style_Reset << "\n";
+ m_t << "{\\tc \\v " << theTranslator->trConceptIndex() << "}\n";
+ m_t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \"concepts.rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n";
+ break;
case isClassHierarchyIndex:
m_t << "\\par " << rtf_Style_Reset << "\n";
m_t << "{\\tc \\v " << theTranslator->trHierarchicalIndex() << "}\n";
@@ -793,6 +815,26 @@ void RTFGenerator::endIndexSection(IndexSections is)
}
}
break;
+ case isConceptDocumentation:
+ {
+ bool first=true;
+ for (const auto &cd : *Doxygen::conceptLinkedMap)
+ {
+ if (cd->isLinkableInProject() && !cd->isAlias())
+ {
+ m_t << "\\par " << rtf_Style_Reset << "\n";
+ if (!first)
+ {
+ beginRTFSection();
+ }
+ first=false;
+ m_t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \"";
+ m_t << cd->getOutputFileBase();
+ m_t << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n";
+ }
+ }
+ }
+ break;
case isClassDocumentation:
{
bool first=true;
diff --git a/src/rtfgen.h b/src/rtfgen.h
index b1ae9f1..344121c 100644
--- a/src/rtfgen.h
+++ b/src/rtfgen.h
@@ -117,6 +117,8 @@ class RTFGenerator : public OutputGenerator
void endMemberItem();
void startMemberTemplateParams() {}
void endMemberTemplateParams(const char *,const char *) {}
+ void startCompoundTemplateParams() { startSubsubsection(); }
+ void endCompoundTemplateParams() { endSubsubsection(); }
void insertMemberAlign(bool) {}
void insertMemberAlignLeft(int,bool){}
diff --git a/src/scanner.l b/src/scanner.l
index 9e719d0..a37ff09 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -445,6 +445,8 @@ NONLopt [^\n]*
/** C++20 concepts */
%x RequiresClause
+%x RequiresExpression
+%x ConceptName
%%
@@ -1622,6 +1624,19 @@ NONLopt [^\n]*
if (yytext[yyleng-1]=='{') unput('{');
BEGIN( CompoundName ) ;
}
+<FindMembers>{B}*"concept"{BN}+ { // C++20 concept
+ yyextra->isTypedef=FALSE;
+ yyextra->current->section = Entry::CONCEPT_SEC;
+ addType(yyscanner);
+ yyextra->current->type += " concept";
+ yyextra->current->fileName = yyextra->yyFileName;
+ yyextra->current->startLine = yyextra->yyLineNr;
+ yyextra->current->startColumn = yyextra->yyColNr;
+ yyextra->current->bodyLine = yyextra->yyLineNr;
+ yyextra->current->bodyColumn = yyextra->yyColNr;
+ lineCount(yyscanner) ;
+ BEGIN( ConceptName ) ;
+ }
<Operator>"("{BN}*")"({BN}*"<"[^>]*">"){BNopt}/"(" { // A::operator()<int>(int arg)
lineCount(yyscanner);
yyextra->current->name += "()";
@@ -2075,6 +2090,7 @@ NONLopt [^\n]*
}
<FindMembers>"friend"{BN}+("class"|"union"|"struct"){BN}+ {
yyextra->current->name=yytext;
+ lineCount(yyscanner) ;
BEGIN(FindMembers);
}
<FindMembers>"requires" { // C++20 requires clause
@@ -2082,6 +2098,28 @@ NONLopt [^\n]*
yyextra->requiresContext = YY_START;
BEGIN(RequiresClause);
}
+<RequiresClause>"requires"{BN}*"(" { // requires requires(T x) { ... }
+ lineCount(yyscanner) ;
+ yyextra->current->req+=yytext;
+ yyextra->lastRoundContext=RequiresExpression;
+ yyextra->pCopyRoundString=&yyextra->current->req;
+ yyextra->roundCount=0;
+ BEGIN( CopyRound ) ;
+ }
+<RequiresExpression>"{" {
+ yyextra->current->req+=yytext;
+ yyextra->lastCurlyContext=RequiresClause;
+ yyextra->pCopyCurlyString=&yyextra->current->req;
+ yyextra->curlyCount=0;
+ BEGIN( CopyCurly ) ;
+ }
+<RequiresExpression>\n {
+ yyextra->current->req+=' ';
+ lineCount(yyextra);
+ }
+<RequiresExpression>. {
+ yyextra->current->req+=yytext;
+ }
<RequiresClause>"(" { // requires "(A && B)"
yyextra->current->req+=yytext;
yyextra->lastRoundContext=RequiresClause;
@@ -2119,6 +2157,7 @@ NONLopt [^\n]*
}
<RequiresClause>{BN}+ {
yyextra->current->req+=' ';
+ lineCount(yyscanner) ;
}
<RequiresClause>. {
unput(*yytext);
@@ -2126,7 +2165,6 @@ NONLopt [^\n]*
BEGIN(yyextra->requiresContext);
}
<FindMembers,FindMemberName>{SCOPENAME} {
-
if (yyextra->clangParser && (yyextra->insideCpp || yyextra->insideObjC))
{
yyextra->current->id = yyextra->clangParser->lookup(yyextra->yyLineNr,yytext);
@@ -3314,7 +3352,12 @@ NONLopt [^\n]*
yyextra->current->type.prepend("typedef ");
}
bool stat = yyextra->current->stat;
- if (!yyextra->current->name.isEmpty() && yyextra->current->section!=Entry::ENUM_SEC)
+ if (yyextra->current->section==Entry::CONCEPT_SEC) // C++20 concept
+ {
+ yyextra->current_root->moveToSubEntryAndRefresh( yyextra->current ) ;
+ initEntry(yyscanner);
+ }
+ else if (!yyextra->current->name.isEmpty() && yyextra->current->section!=Entry::ENUM_SEC)
{
yyextra->current->type=yyextra->current->type.simplifyWhiteSpace();
yyextra->current->args=removeRedundantWhiteSpace(yyextra->current->args);
@@ -5514,6 +5557,17 @@ NONLopt [^\n]*
}
<AlignAsEnd>\n { lineCount(yyscanner); }
<AlignAsEnd>.
+<ConceptName>{ID} {
+ yyextra->current->name = yytext ;
+ }
+<ConceptName>"=" {
+ yyextra->current->bodyLine = yyextra->yyLineNr;
+ yyextra->current->bodyColumn = yyextra->yyColNr;
+ yyextra->current->initializer.str(std::string());
+ yyextra->lastInitializerContext = FindMembers;
+ yyextra->initBracketCount=0;
+ BEGIN(ReadInitializer);
+ }
<CompoundName>{SCOPENAME}/{BN}*"," { // multiple forward declarations on one line
// e.g. @protocol A,B;
yyextra->current->reset();
diff --git a/src/searchindex.cpp b/src/searchindex.cpp
index cd048c4..2b8df67 100644
--- a/src/searchindex.cpp
+++ b/src/searchindex.cpp
@@ -36,6 +36,7 @@
#include "namespacedef.h"
#include "classdef.h"
#include "utf8.h"
+#include "classlist.h"
//---------------------------------------------------------------------------------------------
// the following part is for the server based search engine
@@ -452,6 +453,8 @@ static QCString definitionToName(const Definition *ctx)
return "file";
case Definition::TypeNamespace:
return "namespace";
+ case Definition::TypeConcept:
+ return "concept";
case Definition::TypeGroup:
return "group";
case Definition::TypePackage:
@@ -593,6 +596,7 @@ QCString searchId(const Definition *d)
#define SEARCH_INDEX_DEFINES 17
#define SEARCH_INDEX_GROUPS 18
#define SEARCH_INDEX_PAGES 19
+#define SEARCH_INDEX_CONCEPTS 20
static std::array<SearchIndexInfo,NUM_SEARCH_INDICES> g_searchIndexInfo =
{ {
@@ -622,7 +626,8 @@ static std::array<SearchIndexInfo,NUM_SEARCH_INDICES> g_searchIndexInfo =
{ /* SEARCH_INDEX_RELATED */ "related" , []() { return theTranslator->trFriends(); }, {} },
{ /* SEARCH_INDEX_DEFINES */ "defines" , []() { return theTranslator->trDefines(); }, {} },
{ /* SEARCH_INDEX_GROUPS */ "groups" , []() { return theTranslator->trGroup(TRUE,FALSE); }, {} },
- { /* SEARCH_INDEX_PAGES */ "pages" , []() { return theTranslator->trPage(TRUE,FALSE); }, {} }
+ { /* SEARCH_INDEX_PAGES */ "pages" , []() { return theTranslator->trPage(TRUE,FALSE); }, {} },
+ { /* SEARCH_INDEX_CONCEPTS */ "concepts" , []() { return theTranslator->trConcept(true,false); }, {} }
} };
static void addMemberToSearchIndex(const MemberDef *md)
@@ -791,6 +796,17 @@ void createJavaScriptSearchIndex()
}
}
+ // index concepts
+ for (const auto &cd : *Doxygen::conceptLinkedMap)
+ {
+ std::string letter = convertUTF8ToLower(getUTF8CharAt(cd->name().str(),0));
+ if (cd->isLinkable())
+ {
+ g_searchIndexInfo[SEARCH_INDEX_ALL].add(letter,cd.get());
+ g_searchIndexInfo[SEARCH_INDEX_CONCEPTS].add(letter,cd.get());
+ }
+ }
+
// index files
for (const auto &fn : *Doxygen::inputNameLinkedMap)
{
diff --git a/src/searchindex.h b/src/searchindex.h
index ee56b08..0da7828 100644
--- a/src/searchindex.h
+++ b/src/searchindex.h
@@ -109,7 +109,7 @@ class SearchIndexExternal : public SearchIndexIntf
//------- client side search index ----------------------
-#define NUM_SEARCH_INDICES 20
+#define NUM_SEARCH_INDICES 21
QCString searchId(const Definition *d);
QCString searchName(const Definition *d);
diff --git a/src/sqlite3gen.cpp b/src/sqlite3gen.cpp
index 49cf00c..855f703 100644
--- a/src/sqlite3gen.cpp
+++ b/src/sqlite3gen.cpp
@@ -1372,9 +1372,15 @@ static void writeMemberTemplateLists(const MemberDef *md)
{
writeTemplateArgumentList(md->templateArguments(),md->getClassDef(),md->getFileDef());
}
+
static void writeTemplateList(const ClassDef *cd)
{
- writeTemplateArgumentList(cd->templateArguments(),cd,0);
+ writeTemplateArgumentList(cd->templateArguments(),cd,cd->getFileDef());
+}
+
+static void writeTemplateList(const ConceptDef *cd)
+{
+ writeTemplateArgumentList(cd->getTemplateParameterList(),cd,cd->getFileDef());
}
QCString getSQLDocBlock(const Definition *scope,
@@ -2003,6 +2009,30 @@ static void generateSqlite3ForClass(const ClassDef *cd)
associateAllClassMembers(cd, refid);
}
+static void generateSqlite3ForConcept(const ConceptDef *cd)
+{
+ if (cd->isReference() || cd->isHidden()) return; // skip external references
+
+ struct Refid refid = insertRefid(cd->getOutputFileBase());
+ if(!refid.created && compounddefExists(refid)){return;}
+ bindIntParameter(compounddef_insert,":rowid", refid.rowid);
+ bindTextParameter(compounddef_insert,":name",cd->name());
+ bindTextParameter(compounddef_insert,":kind","concept");
+
+ int file_id = insertPath(cd->getDefFileName());
+ bindIntParameter(compounddef_insert,":file_id",file_id);
+ bindIntParameter(compounddef_insert,":line",cd->getDefLine());
+ bindIntParameter(compounddef_insert,":column",cd->getDefColumn());
+
+ getSQLDesc(compounddef_insert,":briefdescription",cd->briefDescription(),cd);
+ getSQLDesc(compounddef_insert,":detaileddescription",cd->documentation(),cd);
+
+ step(compounddef_insert);
+
+ // + template argument list(s)
+ writeTemplateList(cd);
+}
+
// kinds: constants library module namespace package
static void generateSqlite3ForNamespace(const NamespaceDef *nd)
{
@@ -2477,6 +2507,13 @@ void generateSqlite3()
generateSqlite3ForClass(cd.get());
}
+ // + concepts
+ for (const auto &cd : *Doxygen::conceptLinkedMap)
+ {
+ msg("Generating Sqlite3 output for concept %s\n",cd->name().data());
+ generateSqlite3ForConcept(cd.get());
+ }
+
// + namespaces
for (const auto &nd : *Doxygen::namespaceLinkedMap)
{
diff --git a/src/tagreader.cpp b/src/tagreader.cpp
index 786c851..cb9b537 100644
--- a/src/tagreader.cpp
+++ b/src/tagreader.cpp
@@ -96,7 +96,7 @@ class TagMemberInfo
class TagCompoundInfo
{
public:
- enum class CompoundType { Class, Namespace, Package, File, Group, Page, Dir };
+ enum class CompoundType { Class, Concept, Namespace, Package, File, Group, Page, Dir };
explicit TagCompoundInfo(CompoundType type) : m_type(type) {}
virtual ~TagCompoundInfo() {}
CompoundType compoundType() const { return m_type; }
@@ -131,6 +131,22 @@ class TagClassInfo : public TagCompoundInfo
}
};
+/** Container for concept specific info that can be read from a tagfile */
+class TagConceptInfo : public TagCompoundInfo
+{
+ public:
+ TagConceptInfo() :TagCompoundInfo(CompoundType::Concept) {}
+ std::string clangId;
+ static TagConceptInfo *get(std::unique_ptr<TagCompoundInfo> &t)
+ {
+ return dynamic_cast<TagConceptInfo*>(t.get());
+ }
+ static const TagConceptInfo *get(const std::unique_ptr<TagCompoundInfo> &t)
+ {
+ return dynamic_cast<const TagConceptInfo*>(t.get());
+ }
+};
+
/** Container for namespace specific info that can be read from a tagfile */
class TagNamespaceInfo : public TagCompoundInfo
{
@@ -138,6 +154,7 @@ class TagNamespaceInfo : public TagCompoundInfo
TagNamespaceInfo() :TagCompoundInfo(CompoundType::Namespace) {}
std::string clangId;
StringVector classList;
+ StringVector conceptList;
StringVector namespaceList;
static TagNamespaceInfo *get(std::unique_ptr<TagCompoundInfo> &t)
{
@@ -172,6 +189,7 @@ class TagFileInfo : public TagCompoundInfo
TagFileInfo() : TagCompoundInfo(CompoundType::File) { }
std::string path;
StringVector classList;
+ StringVector conceptList;
StringVector namespaceList;
std::vector<TagIncludeInfo> includes;
static TagFileInfo *get(std::unique_ptr<TagCompoundInfo> &t)
@@ -192,6 +210,7 @@ class TagGroupInfo : public TagCompoundInfo
std::string title;
StringVector subgroupList;
StringVector classList;
+ StringVector conceptList;
StringVector namespaceList;
StringVector fileList;
StringVector pageList;
@@ -279,6 +298,7 @@ class TagFileParser
switch (m_state)
{
case InClass:
+ case InConcept:
case InFile:
case InNamespace:
case InGroup:
@@ -379,6 +399,7 @@ class TagFileParser
switch(m_state)
{
case InClass:
+ case InConcept:
case InFile:
case InNamespace:
case InGroup:
@@ -395,6 +416,7 @@ class TagFileParser
switch(m_state)
{
case InClass:
+ case InConcept:
case InFile:
case InNamespace:
case InGroup:
@@ -435,6 +457,25 @@ class TagFileParser
}
}
+ void endConcept()
+ {
+ switch(m_state)
+ {
+ case InNamespace:
+ TagNamespaceInfo::get(m_curCompound)->conceptList.push_back(m_curString);
+ break;
+ case InFile:
+ TagFileInfo::get(m_curCompound)->conceptList.push_back(m_curString);
+ break;
+ case InGroup:
+ TagGroupInfo::get(m_curCompound)->conceptList.push_back(m_curString);
+ break;
+ default:
+ warn("Unexpected tag 'concept' found");
+ break;
+ }
+ }
+
void endNamespace()
{
switch(m_state)
@@ -525,6 +566,7 @@ class TagFileParser
switch (m_state)
{
case InClass:
+ case InConcept:
case InFile:
case InNamespace:
case InGroup:
@@ -623,6 +665,7 @@ class TagFileParser
switch (m_state)
{
case InClass:
+ case InConcept:
case InNamespace:
case InFile:
case InGroup:
@@ -757,6 +800,7 @@ class TagFileParser
enum State { Invalid,
InClass,
+ InConcept,
InFile,
InNamespace,
InGroup,
@@ -839,6 +883,7 @@ static const std::map< std::string, ElementCallbacks > g_elementHandlers =
{ "title", { startCb(&TagFileParser::startStringValue ), endCb(&TagFileParser::endTitle ) } },
{ "subgroup", { startCb(&TagFileParser::startStringValue ), endCb(&TagFileParser::endSubgroup ) } },
{ "class", { startCb(&TagFileParser::startStringValue ), endCb(&TagFileParser::endClass ) } },
+ { "concept", { startCb(&TagFileParser::startStringValue ), endCb(&TagFileParser::endConcept ) } },
{ "namespace", { startCb(&TagFileParser::startStringValue ), endCb(&TagFileParser::endNamespace ) } },
{ "file", { startCb(&TagFileParser::startStringValue ), endCb(&TagFileParser::endFile ) } },
{ "dir", { startCb(&TagFileParser::startStringValue ), endCb(&TagFileParser::endDir ) } },
@@ -874,6 +919,7 @@ static const std::map< std::string, CompoundFactory > g_compoundFactory =
{ "singleton", { TagFileParser::InClass, []() { return std::make_unique<TagClassInfo>(TagClassInfo::Kind::Singleton); } } },
{ "file", { TagFileParser::InFile, []() { return std::make_unique<TagFileInfo>(); } } },
{ "namespace", { TagFileParser::InNamespace, []() { return std::make_unique<TagNamespaceInfo>(); } } },
+ { "concept", { TagFileParser::InConcept, []() { return std::make_unique<TagConceptInfo>(); } } },
{ "group", { TagFileParser::InGroup, []() { return std::make_unique<TagGroupInfo>(); } } },
{ "page", { TagFileParser::InPage, []() { return std::make_unique<TagPageInfo>(); } } },
{ "package", { TagFileParser::InPackage, []() { return std::make_unique<TagPackageInfo>(); } } },
@@ -962,6 +1008,17 @@ void TagFileParser::dump()
}
}
}
+ //============== CONCEPTS
+ for (const auto &comp : m_tagFileCompounds)
+ {
+ if (comp->compoundType()==TagCompoundInfo::CompoundType::Concept)
+ {
+ const TagConceptInfo *cd = TagConceptInfo::get(comp);
+
+ msg("concept '%s'\n",cd->name.data());
+ msg(" filename '%s'\n",cd->filename.data());
+ }
+ }
//============== NAMESPACES
for (const auto &comp : m_tagFileCompounds)
{
@@ -1342,6 +1399,26 @@ void TagFileParser::buildLists(const std::shared_ptr<Entry> &root)
}
}
+ // build concept list
+ for (const auto &comp : m_tagFileCompounds)
+ {
+ if (comp->compoundType()==TagCompoundInfo::CompoundType::Concept)
+ {
+ const TagConceptInfo *tci = TagConceptInfo::get(comp);
+
+ std::shared_ptr<Entry> ce = std::make_shared<Entry>();
+ ce->section = Entry::CONCEPT_SEC;
+ ce->name = tci->name;
+ addDocAnchors(ce,tci->docAnchors);
+ ce->tagInfoData.tagName = m_tagName;
+ ce->tagInfoData.fileName = tci->filename;
+ ce->hasTagInfo = TRUE;
+ ce->id = tci->clangId;
+
+ root->moveToSubEntryAndKeep(ce);
+ }
+ }
+
// build namespace list
for (const auto &comp : m_tagFileCompounds)
{
diff --git a/src/translator.h b/src/translator.h
index bcc70ff..89e4216 100644
--- a/src/translator.h
+++ b/src/translator.h
@@ -657,6 +657,18 @@ class Translator
//////////////////////////////////////////////////////////////////////////
virtual QCString trDesignUnitDocumentation() = 0;
+
+//////////////////////////////////////////////////////////////////////////
+// new since 1.9.2
+//////////////////////////////////////////////////////////////////////////
+
+ virtual QCString trConcept(bool first_capital, bool singular) = 0;
+ virtual QCString trConceptReference(const char *conceptName) = 0;
+ virtual QCString trConceptList() = 0;
+ virtual QCString trConceptIndex() = 0;
+ virtual QCString trConceptDocumentation() = 0;
+ virtual QCString trConceptListDescription(bool extractAll) = 0;
+ virtual QCString trConceptDefinition() = 0;
};
#endif
diff --git a/src/translator_adapter.h b/src/translator_adapter.h
index 388304c..ad08910 100644
--- a/src/translator_adapter.h
+++ b/src/translator_adapter.h
@@ -41,7 +41,35 @@ class TranslatorAdapterBase : public Translator
};
-class TranslatorAdapter_1_8_19 : public TranslatorAdapterBase
+class TranslatorAdapter_1_9_2 : public TranslatorAdapterBase
+{
+ public:
+ virtual QCString updateNeededMessage()
+ { return createUpdateNeededMessage(idLanguage(),"release 1.9.2"); }
+
+ virtual QCString trConcept(bool first_capital,bool singular)
+ { return english.trConcept(first_capital,singular); }
+
+ virtual QCString trConceptReference(const char *conceptName)
+ { return english.trConceptReference(conceptName); }
+
+ virtual QCString trConceptList()
+ { return english.trConceptList(); }
+
+ virtual QCString trConceptIndex()
+ { return english.trConceptIndex(); }
+
+ virtual QCString trConceptDocumentation()
+ { return english.trConceptDocumentation(); }
+
+ virtual QCString trConceptListDescription(bool extractAll)
+ { return english.trConceptListDescription(extractAll); }
+
+ virtual QCString trConceptDefinition()
+ { return english.trConceptDefinition(); }
+};
+
+class TranslatorAdapter_1_8_19 : public TranslatorAdapter_1_9_2
{
public:
virtual QCString updateNeededMessage()
diff --git a/src/translator_br.h b/src/translator_br.h
index e180f62..533e6cd 100644
--- a/src/translator_br.h
+++ b/src/translator_br.h
@@ -52,7 +52,7 @@
#ifndef TRANSLATOR_BR_H
#define TRANSLATOR_BR_H
-class TranslatorBrazilian : public Translator
+class TranslatorBrazilian : public TranslatorAdapter_1_9_2
{
public:
@@ -2341,13 +2341,13 @@ class TranslatorBrazilian : public Translator
//////////////////////////////////////////////////////////////////////////
// new since 1.8.19
//////////////////////////////////////////////////////////////////////////
-
+
/** VHDL design unit documentation */
virtual QCString trDesignUnitDocumentation()
- {
- return "Documentação da Unidade de Projeto";
+ {
+ return "Documentação da Unidade de Projeto";
}
-
+
};
#endif
diff --git a/src/translator_en.h b/src/translator_en.h
index ba26bc7..8f7676e 100644
--- a/src/translator_en.h
+++ b/src/translator_en.h
@@ -2262,6 +2262,51 @@ class TranslatorEnglish : public Translator
virtual QCString trDesignUnitDocumentation()
{ return "Design Unit Documentation"; }
+//////////////////////////////////////////////////////////////////////////
+// new since 1.9.2
+//////////////////////////////////////////////////////////////////////////
+
+ /** C++20 concept */
+ virtual QCString trConcept(bool first_capital, bool singular)
+ {
+ QCString result((first_capital ? "Concept" : "concept"));
+ if (!singular) result+="s";
+ return result;
+ }
+ /*! used as the title of the HTML page of a C++20 concept page */
+ virtual QCString trConceptReference(const char *conceptName)
+ {
+ QCString result=conceptName;
+ result+=" Concept Reference";
+ return result;
+ }
+
+ /*! used as the title of page containing all the index of all concepts. */
+ virtual QCString trConceptList()
+ { return "Concept List"; }
+
+ /*! used as the title of chapter containing the index listing all concepts. */
+ virtual QCString trConceptIndex()
+ { return "Concept Index"; }
+
+ /*! used as the title of chapter containing all information about concepts. */
+ virtual QCString trConceptDocumentation()
+ { return "Concept Documentation"; }
+
+ /*! used as an introduction to the concept list */
+ virtual QCString trConceptListDescription(bool extractAll)
+ {
+ QCString result="Here is a list of all ";
+ if (!extractAll) result+="documented ";
+ result+="concepts with brief descriptions:";
+ return result;
+ }
+
+ /*! used to introduce the definition of the C++20 concept */
+ virtual QCString trConceptDefinition()
+ {
+ return "Concept definition";
+ }
};
#endif
diff --git a/src/translator_nl.h b/src/translator_nl.h
index 413d353..13b5ce1 100644
--- a/src/translator_nl.h
+++ b/src/translator_nl.h
@@ -1796,6 +1796,46 @@ class TranslatorDutch : public Translator
//////////////////////////////////////////////////////////////////////////
virtual QCString trDesignUnitDocumentation()
{ return "Ontwerp Eenheid Documentatie"; }
+
+//////////////////////////////////////////////////////////////////////////
+// new since 1.9.2
+//////////////////////////////////////////////////////////////////////////
+ virtual QCString trConcept(bool first_capital, bool singular)
+ {
+ QCString result((first_capital ? "Concept" : "concept"));
+ if (!singular) result+="en";
+ return result;
+ }
+
+ virtual QCString trConceptReference(const char *conceptName)
+ {
+ QCString result=conceptName;
+ result+=" Concept Referentie";
+ return result;
+ }
+
+ virtual QCString trConceptList()
+ { return "Concept Lijst"; }
+
+ virtual QCString trConceptIndex()
+ { return "Concept Index"; }
+
+ virtual QCString trConceptDocumentation()
+ { return "Concept Documentatie"; }
+
+ virtual QCString trConceptListDescription(bool extractAll)
+ {
+ QCString result="Hieronder volgt de lijst met alle ";
+ if (!extractAll) result+="gedocumenteerde ";
+ result+="concepten, elk met een korte beschrijving:";
+ return result;
+ }
+
+ virtual QCString trConceptDefinition()
+ {
+ return "Concept definitie";
+ }
+
};
#endif
diff --git a/src/translator_pt.h b/src/translator_pt.h
index 2273c97..c092e2e 100644
--- a/src/translator_pt.h
+++ b/src/translator_pt.h
@@ -27,7 +27,7 @@
* ---------------
* History:
* 20200112:
- * - Updated to 1.9.1;
+ * - Updated to 1.9.1;
* 20190203:
* - Slice methods added;
* 20180612:
@@ -63,7 +63,7 @@
#define TRANSLATOR_PT_H
-class TranslatorPortuguese : public Translator
+class TranslatorPortuguese : public TranslatorAdapter_1_9_2
{
public:
@@ -2279,11 +2279,11 @@ class TranslatorPortuguese : public Translator
//////////////////////////////////////////////////////////////////////////
// new since 1.8.19
//////////////////////////////////////////////////////////////////////////
-
+
/** VHDL design unit documentation */
virtual QCString trDesignUnitDocumentation()
- {
- return "Documentação da Unidade de Projeto";
+ {
+ return "Documentação da Unidade de Projeto";
}
};
diff --git a/src/translator_sv.h b/src/translator_sv.h
index 853e265..b3c48dc 100644
--- a/src/translator_sv.h
+++ b/src/translator_sv.h
@@ -151,7 +151,7 @@ English:
#ifndef TRANSLATOR_SE_H
#define TRANSLATOR_SE_H
-class TranslatorSwedish : public Translator
+class TranslatorSwedish : public TranslatorAdapter_1_9_2
{
public:
diff --git a/src/util.cpp b/src/util.cpp
index 16a3879..c7b82df 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -491,6 +491,26 @@ ClassDef *getClass(const char *n)
return Doxygen::classLinkedMap->find(n);
}
+
+ConceptDef *getConcept(const char *n)
+{
+ if (n==0 || n[0]=='\0') return 0;
+ return Doxygen::conceptLinkedMap->find(n);
+}
+
+ConceptDef *getResolvedConcept(const Definition *d,const char *name)
+{
+ ConceptDef *cd=0;
+ while (d && d!=Doxygen::globalScope)
+ {
+ cd = getConcept(d->name()+"::"+name);
+ if (cd) return cd;
+ d = d->getOuterScope();
+ }
+ cd = getConcept(name);
+ return cd;
+}
+
NamespaceDef *getResolvedNamespace(const char *name)
{
if (name==0 || name[0]=='\0') return 0;
@@ -973,6 +993,7 @@ void linkifyText(const TextGeneratorIntf &out, const Definition *scope,
const FileDef *fd=0;
const NamespaceDef *nd=0;
const GroupDef *gd=0;
+ const ConceptDef *cnd=0;
//printf("** Match word '%s'\n",matchWord.data());
SymbolResolver resolver(fileScope);
@@ -1018,18 +1039,18 @@ void linkifyText(const TextGeneratorIntf &out, const Definition *scope,
}
}
}
-// else if ((cd=getClass(matchWord+"-g"))) // C# generic as well
-// {
-// // add link to the result
-// if (external ? cd->isLinkable() : cd->isLinkableInProject())
-// {
-// if (cd!=self)
-// {
-// out.writeLink(cd->getReference(),cd->getOutputFileBase(),cd->anchor(),word);
-// found=TRUE;
-// }
-// }
-// }
+ else if ((cnd=getConcept(matchWord)))
+ {
+ // add link to the result
+ if (external ? cnd->isLinkable() : cnd->isLinkableInProject())
+ {
+ if (cnd!=self)
+ {
+ out.writeLink(cnd->getReference(),cnd->getOutputFileBase(),cnd->anchor(),word.c_str());
+ found=TRUE;
+ }
+ }
+ }
else
{
//printf(" -> nothing\n");
@@ -2932,6 +2953,7 @@ bool resolveRef(/* in */ const char *scName,
const FileDef *fd = 0;
const NamespaceDef *nd = 0;
const GroupDef *gd = 0;
+ const ConceptDef *cnd = 0;
// check if nameStr is a member or global.
//printf("getDefs(scope=%s,name=%s,args=%s checkScope=%d)\n",
@@ -2974,6 +2996,11 @@ bool resolveRef(/* in */ const char *scName,
*resContext=gd;
return TRUE;
}
+ else if ((cnd=Doxygen::conceptLinkedMap->find(nameStr)))
+ {
+ *resContext=cnd;
+ return TRUE;
+ }
else if (tsName.find('.')!=-1) // maybe a link to a file
{
bool ambig;
@@ -3113,6 +3140,7 @@ bool resolveLink(/* in */ const char *scName,
const PageDef *pd;
const ClassDef *cd;
const DirDef *dir;
+ const ConceptDef *cnd;
const NamespaceDef *nd;
const SectionInfo *si=0;
bool ambig;
@@ -3175,12 +3203,12 @@ bool resolveLink(/* in */ const char *scName,
resAnchor=cd->anchor();
return TRUE;
}
-// else if ((cd=getClass(linkRef+"-g"))) // C# generic link
-// {
-// *resContext=cd;
-// resAnchor=cd->anchor();
-// return TRUE;
-// }
+ else if ((cnd=getConcept(linkRef))) // C++20 concept definition
+ {
+ *resContext=cnd;
+ resAnchor=cnd->anchor();
+ return TRUE;
+ }
else if ((nd=Doxygen::namespaceLinkedMap->find(linkRef)))
{
*resContext=nd;
@@ -6812,6 +6840,26 @@ bool namespaceHasNestedNamespace(const NamespaceDef *nd)
return false;
}
+bool namespaceHasNestedConcept(const NamespaceDef *nd)
+{
+ for (const auto &cnd : nd->getNamespaces())
+ {
+ if (namespaceHasNestedConcept(cnd))
+ {
+ //printf("<namespaceHasVisibleChild(%s,includeClasses=%d): case2\n",nd->name().data(),includeClasses);
+ return true;
+ }
+ }
+ for (const auto &cnd : nd->getConcepts())
+ {
+ if (cnd->isLinkableInProject())
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
bool namespaceHasNestedClass(const NamespaceDef *nd,bool filterClasses,ClassDef::CompoundType ct)
{
//printf(">namespaceHasVisibleChild(%s,includeClasses=%d)\n",nd->name().data(),includeClasses);
diff --git a/src/util.h b/src/util.h
index ab30c61..8fe5ea1 100644
--- a/src/util.h
+++ b/src/util.h
@@ -36,6 +36,7 @@
#include "outputgen.h"
#include "regex.h"
#include "dir.h"
+#include "conceptdef.h"
//--------------------------------------------------------------------
@@ -173,6 +174,12 @@ inline ClassDefMutable *getClassMutable(const char *key)
{
return toClassDefMutable(getClass(key));
}
+ConceptDef *getConcept(const char *key);
+inline ConceptDefMutable *getConceptMutable(const char *key)
+{
+ return toConceptDefMutable(getConcept(key));
+}
+ConceptDef *getResolvedConcept(const Definition *scope,const char *name);
NamespaceDef *getResolvedNamespace(const char *key);
inline NamespaceDefMutable *getResolvedNamespaceMutable(const char *key)
@@ -228,6 +235,7 @@ QCString replaceAnonymousScopes(const char *s,const char *replacement=0);
bool hasVisibleRoot(const BaseClassList &bcl);
bool classHasVisibleChildren(const ClassDef *cd);
bool namespaceHasNestedNamespace(const NamespaceDef *nd);
+bool namespaceHasNestedConcept(const NamespaceDef *nd);
bool namespaceHasNestedClass(const NamespaceDef *nd,bool filterClasses,ClassDef::CompoundType ct);
bool classVisibleInIndex(const ClassDef *cd);
diff --git a/src/xmlgen.cpp b/src/xmlgen.cpp
index fa661a9..3eca727 100644
--- a/src/xmlgen.cpp
+++ b/src/xmlgen.cpp
@@ -398,7 +398,12 @@ static void writeMemberTemplateLists(const MemberDef *md,TextStream &t)
static void writeTemplateList(const ClassDef *cd,TextStream &t)
{
- writeTemplateArgumentList(t,cd->templateArguments(),cd,0,4);
+ writeTemplateArgumentList(t,cd->templateArguments(),cd,cd->getFileDef(),4);
+}
+
+static void writeTemplateList(const ConceptDef *cd,TextStream &t)
+{
+ writeTemplateArgumentList(t,cd->getTemplateParameterList(),cd,cd->getFileDef(),4);
}
static void writeXMLDocBlock(TextStream &t,
@@ -928,6 +933,12 @@ static void generateXMLForMember(const MemberDef *md,TextStream &ti,TextStream &
}
}
}
+ if (!md->requiresClause().isEmpty())
+ {
+ t << " <requiresclause>";
+ linkifyText(TextGeneratorXMLImpl(t),md,md->getFileDef(),md,md->requiresClause());
+ t << " </requiresclause>\n";
+ }
if (md->hasOneLineInitializer() || md->hasMultiLineInitializer())
{
@@ -1192,6 +1203,26 @@ static void writeInnerDirs(const DirList *dl,TextStream &t)
}
}
+static void writeIncludeInfo(const IncludeInfo *ii,TextStream &t)
+{
+ if (ii)
+ {
+ QCString nm = ii->includeName;
+ if (nm.isEmpty() && ii->fileDef) nm = ii->fileDef->docName();
+ if (!nm.isEmpty())
+ {
+ t << " <includes";
+ if (ii->fileDef && !ii->fileDef->isReference()) // TODO: support external references
+ {
+ t << " refid=\"" << ii->fileDef->getOutputFileBase() << "\"";
+ }
+ t << " local=\"" << (ii->local ? "yes" : "no") << "\">";
+ t << nm;
+ t << "</includes>\n";
+ }
+ }
+}
+
static void generateXMLForClass(const ClassDef *cd,TextStream &ti)
{
// + brief description
@@ -1310,23 +1341,7 @@ static void generateXMLForClass(const ClassDef *cd,TextStream &ti)
<< "</derivedcompoundref>\n";
}
- const IncludeInfo *ii=cd->includeInfo();
- if (ii)
- {
- QCString nm = ii->includeName;
- if (nm.isEmpty() && ii->fileDef) nm = ii->fileDef->docName();
- if (!nm.isEmpty())
- {
- t << " <includes";
- if (ii->fileDef && !ii->fileDef->isReference()) // TODO: support external references
- {
- t << " refid=\"" << ii->fileDef->getOutputFileBase() << "\"";
- }
- t << " local=\"" << (ii->local ? "yes" : "no") << "\">";
- t << nm;
- t << "</includes>\n";
- }
- }
+ writeIncludeInfo(cd->includeInfo(),t);
writeInnerClasses(cd->getClasses(),t);
@@ -1345,6 +1360,13 @@ static void generateXMLForClass(const ClassDef *cd,TextStream &ti)
}
}
+ if (!cd->requiresClause().isEmpty())
+ {
+ t << " <requiresclause>";
+ linkifyText(TextGeneratorXMLImpl(t),cd,cd->getFileDef(),0,cd->requiresClause());
+ t << " </requiresclause>\n";
+ }
+
t << " <briefdescription>\n";
writeXMLDocBlock(t,cd->briefFile(),cd->briefLine(),cd,0,cd->briefDescription());
t << " </briefdescription>\n";
@@ -1387,6 +1409,50 @@ static void generateXMLForClass(const ClassDef *cd,TextStream &ti)
ti << " </compound>\n";
}
+static void generateXMLForConcept(const ConceptDef *cd,TextStream &ti)
+{
+ if (cd->isReference() || cd->isHidden()) return; // skip external references.
+
+ ti << " <compound refid=\"" << cd->getOutputFileBase()
+ << "\" kind=\"concept\"" << "><name>"
+ << convertToXML(cd->name()) << "</name>\n";
+
+ QCString outputDirectory = Config_getString(XML_OUTPUT);
+ QCString fileName=outputDirectory+"/"+cd->getOutputFileBase()+".xml";
+ std::ofstream f(fileName.str(),std::ofstream::out | std::ofstream::binary);
+ if (!f.is_open())
+ {
+ err("Cannot open file %s for writing!\n",fileName.data());
+ return;
+ }
+ TextStream t(&f);
+ writeXMLHeader(t);
+ t << " <compounddef id=\"" << cd->getOutputFileBase()
+ << "\" kind=\"concept\">\n";
+ t << " <compoundname>";
+ writeXMLString(t,cd->name());
+ t << "</compoundname>\n";
+ writeIncludeInfo(cd->includeInfo(),t);
+ writeTemplateList(cd,t);
+ t << " <initializer>";
+ linkifyText(TextGeneratorXMLImpl(t),cd,cd->getFileDef(),0,cd->initializer());
+ t << " </initializer>\n";
+ t << " <briefdescription>\n";
+ writeXMLDocBlock(t,cd->briefFile(),cd->briefLine(),cd,0,cd->briefDescription());
+ t << " </briefdescription>\n";
+ t << " <detaileddescription>\n";
+ writeXMLDocBlock(t,cd->docFile(),cd->docLine(),cd,0,cd->documentation());
+ t << " </detaileddescription>\n";
+ t << " <location file=\""
+ << convertToXML(stripFromPath(cd->getDefFileName())) << "\" line=\""
+ << cd->getDefLine() << "\"" << " column=\""
+ << cd->getDefColumn() << "\"/>\n" ;
+ t << " </compounddef>\n";
+ t << "</doxygen>\n";
+
+ ti << " </compound>\n";
+}
+
static void generateXMLForNamespace(const NamespaceDef *nd,TextStream &ti)
{
// + contained class definitions
@@ -1817,6 +1883,7 @@ static void generateXMLForPage(PageDef *pd,TextStream &ti,bool isExample)
void generateXML()
{
// + classes
+ // + concepts
// + namespaces
// + files
// + groups
@@ -1891,6 +1958,11 @@ void generateXML()
{
generateXMLForClass(cd.get(),t);
}
+ for (const auto &cd : *Doxygen::conceptLinkedMap)
+ {
+ msg("Generating XML output for concept %s\n",cd->name().data());
+ generateXMLForConcept(cd.get(),t);
+ }
for (const auto &nd : *Doxygen::namespaceLinkedMap)
{
msg("Generating XML output for namespace %s\n",nd->name().data());
diff --git a/templates/general/layout_default.xml b/templates/general/layout_default.xml
index 373bb20..c671020 100644
--- a/templates/general/layout_default.xml
+++ b/templates/general/layout_default.xml
@@ -9,6 +9,8 @@
<tab type="namespacelist" visible="yes" title="" intro=""/>
<tab type="namespacemembers" visible="yes" title="" intro=""/>
</tab>
+ <tab type="concepts" visible="yes" title="">
+ </tab>
<tab type="interfaces" visible="yes" title="">
<tab type="interfacelist" visible="yes" title="" intro=""/>
<tab type="interfaceindex" visible="$ALPHABETICAL_INDEX" title=""/>
@@ -103,6 +105,7 @@
<constantgroups visible="yes" title=""/>
<interfaces visible="yes" title=""/>
<classes visible="yes" title=""/>
+ <concepts visible="yes" title=""/>
<structs visible="yes" title=""/>
<exceptions visible="yes" title=""/>
<typedefs title=""/>
@@ -126,6 +129,15 @@
<authorsection visible="yes"/>
</namespace>
+ <!-- Layout definition for a concept page -->
+ <concept>
+ <briefdescription visible="yes"/>
+ <includes visible="$SHOW_INCLUDE_FILES"/>
+ <definition visible="yes" title=""/>
+ <detaileddescription title=""/>
+ <authorsection visible="yes"/>
+ </concept>
+
<!-- Layout definition for a file page -->
<file>
<briefdescription visible="yes"/>
@@ -139,6 +151,7 @@
<structs visible="yes" title=""/>
<exceptions visible="yes" title=""/>
<namespaces visible="yes" title=""/>
+ <concepts visible="yes" title=""/>
<constantgroups visible="yes" title=""/>
<defines title=""/>
<typedefs title=""/>
@@ -172,6 +185,7 @@
<dirs visible="yes" title=""/>
<files visible="yes" title=""/>
<namespaces visible="yes" title=""/>
+ <concepts visible="yes" title=""/>
<classes visible="yes" title=""/>
<defines title=""/>
<typedefs title=""/>
diff --git a/templates/html/doxygen.css b/templates/html/doxygen.css
index 5898d87..29dafbe 100644
--- a/templates/html/doxygen.css
+++ b/templates/html/doxygen.css
@@ -439,6 +439,12 @@ img.footer {
vertical-align: middle;
}
+.compoundTemplParams {
+ color: ##60;
+ font-size: 80%;
+ line-height: 120%;
+}
+
/* @group Code Colorization */
span.keyword {
diff --git a/templates/xml/compound.xsd b/templates/xml/compound.xsd
index 400bea5..c128140 100644
--- a/templates/xml/compound.xsd
+++ b/templates/xml/compound.xsd
@@ -33,6 +33,8 @@
<xsd:element name="templateparamlist" type="templateparamlistType" minOccurs="0" />
<xsd:element name="sectiondef" type="sectiondefType" minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="tableofcontents" type="tableofcontentsType" minOccurs="0" maxOccurs="1" />
+ <xsd:element name="requiresclause" type="linkedTextType" minOccurs="0" />
+ <xsd:element name="initializer" type="linkedTextType" minOccurs="0" />
<xsd:element name="briefdescription" type="descriptionType" minOccurs="0" />
<xsd:element name="detaileddescription" type="descriptionType" minOccurs="0" />
<xsd:element name="inheritancegraph" type="graphType" minOccurs="0" />
@@ -147,6 +149,7 @@
<xsd:element name="reimplementedby" type="reimplementType" minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="param" type="paramType" minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="enumvalue" type="enumvalueType" minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element name="requiresclause" type="linkedTextType" minOccurs="0" />
<xsd:element name="initializer" type="linkedTextType" minOccurs="0" />
<xsd:element name="exceptions" type="linkedTextType" minOccurs="0" />
<xsd:element name="briefdescription" type="descriptionType" minOccurs="0" />
@@ -815,6 +818,7 @@
<xsd:enumeration value="page" />
<xsd:enumeration value="example" />
<xsd:enumeration value="dir" />
+ <xsd:enumeration value="concept" />
</xsd:restriction>
</xsd:simpleType>
diff --git a/templates/xml/index.xsd b/templates/xml/index.xsd
index edb1d34..cfb7041 100644
--- a/templates/xml/index.xsd
+++ b/templates/xml/index.xsd
@@ -45,6 +45,7 @@
<xsd:enumeration value="example"/>
<xsd:enumeration value="dir"/>
<xsd:enumeration value="type"/>
+ <xsd:enumeration value="concept"/>
</xsd:restriction>
</xsd:simpleType>