Commit 744d1ca5 authored by Dimitri van Heesch's avatar Dimitri van Heesch

More work on the template and context mechanisms

parent 2912829c
......@@ -1767,20 +1767,24 @@ void ClassDef::writeMoreLink(OutputList &ol,const QCString &anchor)
}
}
bool ClassDef::visibleInParentsDeclList() const
{
static bool extractPrivate = Config_getBool("EXTRACT_PRIVATE");
static bool hideUndocClasses = Config_getBool("HIDE_UNDOC_CLASSES");
static bool extractLocalClasses = Config_getBool("EXTRACT_LOCAL_CLASSES");
bool linkable = isLinkable();
return (name().find('@')==-1 && !isExtension() &&
(protection()!=::Private || extractPrivate) &&
(linkable || (!hideUndocClasses && (!isLocal() || extractLocalClasses)))
);
}
void ClassDef::writeDeclarationLink(OutputList &ol,bool &found,const char *header,bool localNames)
{
//static bool fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN");
//static bool vhdlOpt = Config_getBool("OPTIMIZE_OUTPUT_VHDL");
static bool hideUndocClasses = Config_getBool("HIDE_UNDOC_CLASSES");
static bool extractLocalClasses = Config_getBool("EXTRACT_LOCAL_CLASSES");
bool isLink = isLinkable();
SrcLangExt lang = getLanguage();
if (isLink ||
(!hideUndocClasses &&
(!isLocal() || extractLocalClasses)
)
)
if (visibleInParentsDeclList())
{
if (!found) // first class
{
......@@ -1820,7 +1824,7 @@ void ClassDef::writeDeclarationLink(OutputList &ol,bool &found,const char *heade
ol.writeString(" ");
ol.insertMemberAlign();
}
if (isLink)
if (isLinkable())
{
ol.writeObjectLink(getReference(),
getOutputFileBase(),
......
......@@ -168,6 +168,9 @@ class ClassDef : public Definition
/** the class is visible in a class diagram, or class hierarchy */
bool isVisibleInHierarchy();
/** show this class in the declaration section of its parent? */
bool visibleInParentsDeclList() const;
/** Returns the template arguments of this class
* Will return 0 if not applicable.
*/
......@@ -310,14 +313,13 @@ class ClassDef : public Definition
QCString generatedFromFiles() const;
const FileList &usedFiles() const;
QCString includeStatement() const;
const ArgumentList *typeConstraints() const;
const ExampleSDict *exampleList() const;
bool hasExamples() const;
QCString getMemberListFileName() const;
bool subGrouping() const;
//-----------------------------------------------------------------------------------
// --- setters ----
//-----------------------------------------------------------------------------------
......@@ -432,6 +434,8 @@ class ClassDef : public Definition
QPtrDict<void> *visitedClasses);
void getTitleForMemberListType(MemberListType type,
QCString &title,QCString &subtitle);
QCString includeStatement() const;
ClassDefImpl *m_impl;
......
......@@ -27,6 +27,8 @@
// TODO: pass the current file to Dot*::writeGraph, so the user can put dot graphs in other
// files as well
#define ADD_PROPERTY(name) addProperty(#name,this,&Private::name);
struct ContextGlobals
{
enum OutputFormat
......@@ -453,6 +455,18 @@ class TranslateContext::Private : public PropertyMapper
}
return TemplateVariant();
}
TemplateVariant handleIncludeDependencyGraph(const QValueList<TemplateVariant> &args) const
{
if (args.count()==1)
{
return theTranslator->trInclDepGraph(args[0].toString());
}
else
{
err("tr.includeDependencyGraph should take one string argument, got %d\n",args.count());
}
return TemplateVariant();
}
......@@ -483,6 +497,8 @@ class TranslateContext::Private : public PropertyMapper
TemplateVariant classes() const
{
return theTranslator->trClasses();
// TODO: VHDL: trVhdlType(VhdlDocGen::ENTITY,FALSE)
// TODO: Fortran: trDataTypes()
}
TemplateVariant classList() const
{
......@@ -669,6 +685,34 @@ class TranslateContext::Private : public PropertyMapper
{
return theTranslator->trAdditionalInheritedMembers();
}
TemplateVariant includeDependencyGraph() const
{
return TemplateVariant::Delegate::fromMethod<Private,&Private::handleIncludeDependencyGraph>(this);
}
TemplateVariant includedByDependencyGraph() const
{
return theTranslator->trInclByDepGraph();
}
TemplateVariant gotoSourceCode() const
{
return theTranslator->trGotoSourceCode();
}
TemplateVariant gotoDocumentation() const
{
return theTranslator->trGotoDocumentation();
}
TemplateVariant constantgroups() const
{
return theTranslator->trConstantGroups();
}
TemplateVariant classDocumentation() const
{
return theTranslator->trClassDocumentation();
}
TemplateVariant compoundMembers() const
{
return theTranslator->trCompoundMembers();
}
Private()
{
//%% string generatedBy
......@@ -761,6 +805,20 @@ class TranslateContext::Private : public PropertyMapper
addProperty("inheritedFrom", this,&Private::inheritedFrom);
//%% string addtionalInheritedMembers
addProperty("additionalInheritedMembers",this,&Private::additionalInheritedMembers);
//%% string includeDependencyGraph:container_name
addProperty("includeDependencyGraph",this,&Private::includeDependencyGraph);
//%% string includedByDependencyGraph
addProperty("includedByDependencyGraph",this,&Private::includedByDependencyGraph);
//%% string gotoSourceCode
addProperty("gotoSourceCode", this,&Private::gotoSourceCode);
//%% string gotoDocumentation
addProperty("gotoDocumentation", this,&Private::gotoDocumentation);
//%% string constantgroups
addProperty("constantgroups", this,&Private::constantgroups);
//%% string classDocumentation
addProperty("classDocumentation", this,&Private::classDocumentation);
//%% string compoundMembers
addProperty("compoundMembers", this,&Private::compoundMembers);
m_javaOpt = Config_getBool("OPTIMIZE_OUTPUT_JAVA");
m_fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN");
......@@ -823,6 +881,31 @@ static TemplateVariant parseCode(MemberDef *md,const QCString &scopeName,const Q
return TemplateVariant(s.data(),TRUE);
}
static TemplateVariant parseCode(FileDef *fd,const QCString &relPath)
{
static bool filterSourceFiles = Config_getBool("FILTER_SOURCE_FILES");
ParserInterface *pIntf = Doxygen::parserManager->getParser(fd->getDefFileExtension());
pIntf->resetCodeParserState();
QGString s;
FTextStream t(&s);
HtmlCodeGenerator codeGen(t,relPath);
pIntf->parseCode(codeGen,0,
fileToString(fd->absFilePath(),filterSourceFiles,TRUE), // the sources
fd->getLanguage(), // lang
FALSE, // isExampleBlock
0, // exampleName
fd, // fileDef
-1, // startLine
-1, // endLine
FALSE, // inlineFragment
0, // memberDef
TRUE, // showLineNumbers
0, // searchCtx
TRUE // collectXRefs, TODO: should become FALSE
);
return TemplateVariant(s.data(),TRUE);
}
//------------------------------------------------------------------------
//%% struct Symbol: shared info for all symbols
......@@ -1027,7 +1110,10 @@ class DefinitionContext : public PropertyMapper
if (!m_cache.navPath)
{
TemplateList *list = new TemplateList;
fillPath(m_def,list);
if (m_def->getOuterScope() && m_def->getOuterScope()!=Doxygen::globalScope)
{
fillPath(m_def->getOuterScope(),list);
}
m_cache.navPath.reset(list);
}
return m_cache.navPath.get();
......@@ -1058,7 +1144,7 @@ class DefinitionContext : public PropertyMapper
class IncludeInfoContext::Private : public PropertyMapper
{
public:
Private(IncludeInfo *info,SrcLangExt lang) :
Private(const IncludeInfo *info,SrcLangExt lang) :
m_info(info),
m_fileContext(info && info->fileDef ? info->fileDef : 0),
m_lang(lang)
......@@ -1096,12 +1182,12 @@ class IncludeInfoContext::Private : public PropertyMapper
return m_info->includeName;
}
private:
IncludeInfo *m_info;
const IncludeInfo *m_info;
FileContext m_fileContext;
SrcLangExt m_lang;
};
IncludeInfoContext::IncludeInfoContext(IncludeInfo *info,SrcLangExt lang)
IncludeInfoContext::IncludeInfoContext(const IncludeInfo *info,SrcLangExt lang)
{
p = new Private(info,lang);
}
......@@ -1119,14 +1205,59 @@ TemplateVariant IncludeInfoContext::get(const char *n) const
//------------------------------------------------------------------------
//%% list IncludeInfoList[Class] : list of nested classes
class IncludeInfoListContext::Private : public GenericNodeListContext<IncludeInfoContext>
{
public:
Private(const QList<IncludeInfo> &list,SrcLangExt lang)
{
QListIterator<IncludeInfo> li(list);
IncludeInfo *ii;
for (li.toFirst();(ii=li.current());++li)
{
if (!ii->indirect)
{
append(new IncludeInfoContext(ii,lang));
}
}
}
};
IncludeInfoListContext::IncludeInfoListContext(const QList<IncludeInfo> &list,SrcLangExt lang)
{
p = new Private(list,lang);
}
IncludeInfoListContext::~IncludeInfoListContext()
{
delete p;
}
// TemplateListIntf
int IncludeInfoListContext::count() const
{
return p->count();
}
TemplateVariant IncludeInfoListContext::at(int index) const
{
return p->at(index);
}
TemplateListIntf::ConstIterator *IncludeInfoListContext::createIterator() const
{
return p->createIterator();
}
//------------------------------------------------------------------------
//%% struct Class(Symbol): class information
//%% {
class ClassContext::Private : public DefinitionContext<ClassContext::Private>
{
public:
Private(ClassDef *cd) : DefinitionContext<ClassContext::Private>(cd) ,
m_classDef(cd), m_usedFiles(cd),
m_includeInfo(cd ? cd->includeInfo() : 0, cd ? cd->getLanguage() : SrcLangExt_Unknown)
Private(ClassDef *cd) : DefinitionContext<ClassContext::Private>(cd),
m_classDef(cd), m_usedFiles(cd)
{
addProperty("title", this,&Private::title);
addProperty("highlight", this,&Private::highlight);
......@@ -1139,7 +1270,6 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private>
addProperty("hasCollaborationDiagram", this,&Private::hasCollaborationDiagram);
addProperty("collaborationDiagram", this,&Private::collaborationDiagram);
addProperty("includeInfo", this,&Private::includeInfo);
addProperty("includeStatement", this,&Private::includeStatement);
addProperty("inherits", this,&Private::inherits);
addProperty("inheritedBy", this,&Private::inheritedBy);
addProperty("unoIDLServices", this,&Private::unoIDLServices);
......@@ -1182,7 +1312,7 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private>
addProperty("detailedVariables", this,&Private::detailedVariables);
addProperty("detailedProperties", this,&Private::detailedProperties);
addProperty("detailedEvents", this,&Private::detailedEvents);
addProperty("nestedClasses", this,&Private::nestedClasses);
addProperty("classes", this,&Private::classes);
addProperty("compoundType", this,&Private::compoundType);
addProperty("templateDecls", this,&Private::templateDecls);
addProperty("typeConstraints", this,&Private::typeConstraints);
......@@ -1317,19 +1447,19 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private>
TemplateVariant includeInfo() const
{
if (m_classDef->includeInfo())
if (!m_cache.includeInfo && m_classDef->includeInfo())
{
m_cache.includeInfo.reset(new IncludeInfoContext(m_classDef->includeInfo(),m_classDef->getLanguage()));
}
if (m_cache.includeInfo)
{
return TemplateVariant(&m_includeInfo);
return m_cache.includeInfo.get();
}
else
{
return TemplateVariant(FALSE);
}
}
TemplateVariant includeStatement() const
{
return m_classDef->includeStatement();
}
TemplateVariant inherits() const
{
if (!m_cache.inheritsList)
......@@ -1530,12 +1660,9 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private>
{
return getMemberList(m_cache.detailedEvents,MemberListType_eventMembers,theTranslator->trEventDocumentation(),TRUE);
}
TemplateVariant nestedClasses() const
TemplateVariant classes() const
{
static bool extractPrivate = Config_getBool("EXTRACT_PRIVATE");
static bool hideUndocClasses = Config_getBool("HIDE_UNDOC_CLASSES");
static bool extractLocalClasses = Config_getBool("EXTRACT_LOCAL_CLASSES");
if (!m_cache.nestedClasses)
if (!m_cache.classes)
{
NestedClassListContext *classList = new NestedClassListContext;
if (m_classDef->getClassSDict())
......@@ -1544,20 +1671,15 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private>
ClassDef *cd;
for (sdi.toFirst();(cd=sdi.current());++sdi)
{
bool linkable = cd->isLinkable();
if (cd->name().find('@')==-1 && !cd->isExtension() &&
(cd->protection()!=::Private || extractPrivate) &&
(linkable ||
(!hideUndocClasses && (!cd->isLocal() || extractLocalClasses)))
)
if (cd->visibleInParentsDeclList())
{
classList->append(cd);
}
}
}
m_cache.nestedClasses.reset(classList);
m_cache.classes.reset(classList);
}
return m_cache.nestedClasses.get();
return m_cache.classes.get();
}
TemplateVariant compoundType() const
{
......@@ -1764,71 +1886,70 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private>
private:
ClassDef *m_classDef;
UsedFilesContext m_usedFiles;
IncludeInfoContext m_includeInfo;
struct Cachable
{
Cachable() : inheritanceNodes(-1)
{
templateArgList.setAutoDelete(TRUE);
exampleList.setAutoDelete(TRUE);
allMembers.setAutoDelete(TRUE);
}
ScopedPtr<IncludeInfoContext> includeInfo;
ScopedPtr<InheritanceListContext> inheritsList;
ScopedPtr<InheritanceListContext> inheritedByList;
ScopedPtr<DotClassGraph> classGraph;
ScopedPtr<DotClassGraph> collaborationGraph;
ScopedPtr<NestedClassListContext> nestedClasses;
ScopedPtr<MemberListInfoContext> publicTypes;
ScopedPtr<MemberListInfoContext> publicMethods;
ScopedPtr<MemberListInfoContext> publicStaticMethods;
ScopedPtr<MemberListInfoContext> publicAttributes;
ScopedPtr<MemberListInfoContext> publicStaticAttributes;
ScopedPtr<MemberListInfoContext> publicSlots;
ScopedPtr<MemberListInfoContext> protectedTypes;
ScopedPtr<MemberListInfoContext> protectedMethods;
ScopedPtr<MemberListInfoContext> protectedStaticMethods;
ScopedPtr<MemberListInfoContext> protectedAttributes;
ScopedPtr<MemberListInfoContext> protectedStaticAttributes;
ScopedPtr<MemberListInfoContext> protectedSlots;
ScopedPtr<MemberListInfoContext> privateTypes;
ScopedPtr<MemberListInfoContext> privateMethods;
ScopedPtr<MemberListInfoContext> privateStaticMethods;
ScopedPtr<MemberListInfoContext> privateAttributes;
ScopedPtr<MemberListInfoContext> privateStaticAttributes;
ScopedPtr<MemberListInfoContext> privateSlots;
ScopedPtr<MemberListInfoContext> packageTypes;
ScopedPtr<MemberListInfoContext> packageMethods;
ScopedPtr<MemberListInfoContext> packageStaticMethods;
ScopedPtr<MemberListInfoContext> packageAttributes;
ScopedPtr<MemberListInfoContext> packageStaticAttributes;
ScopedPtr<MemberListInfoContext> unoIDLServices;
ScopedPtr<MemberListInfoContext> unoIDLInterfaces;
ScopedPtr<MemberListInfoContext> signals;
ScopedPtr<MemberListInfoContext> properties;
ScopedPtr<MemberListInfoContext> events;
ScopedPtr<MemberListInfoContext> friends;
ScopedPtr<MemberListInfoContext> related;
ScopedPtr<MemberListInfoContext> detailedTypedefs;
ScopedPtr<MemberListInfoContext> detailedEnums;
ScopedPtr<MemberListInfoContext> detailedServices;
ScopedPtr<MemberListInfoContext> detailedInterfaces;
ScopedPtr<MemberListInfoContext> detailedConstructors;
ScopedPtr<MemberListInfoContext> detailedMethods;
ScopedPtr<MemberListInfoContext> detailedRelated;
ScopedPtr<MemberListInfoContext> detailedVariables;
ScopedPtr<MemberListInfoContext> detailedProperties;
ScopedPtr<MemberListInfoContext> detailedEvents;
ScopedPtr<NestedClassListContext> classes;
ScopedPtr<MemberListInfoContext> publicTypes;
ScopedPtr<MemberListInfoContext> publicMethods;
ScopedPtr<MemberListInfoContext> publicStaticMethods;
ScopedPtr<MemberListInfoContext> publicAttributes;
ScopedPtr<MemberListInfoContext> publicStaticAttributes;
ScopedPtr<MemberListInfoContext> publicSlots;
ScopedPtr<MemberListInfoContext> protectedTypes;
ScopedPtr<MemberListInfoContext> protectedMethods;
ScopedPtr<MemberListInfoContext> protectedStaticMethods;
ScopedPtr<MemberListInfoContext> protectedAttributes;
ScopedPtr<MemberListInfoContext> protectedStaticAttributes;
ScopedPtr<MemberListInfoContext> protectedSlots;
ScopedPtr<MemberListInfoContext> privateTypes;
ScopedPtr<MemberListInfoContext> privateMethods;
ScopedPtr<MemberListInfoContext> privateStaticMethods;
ScopedPtr<MemberListInfoContext> privateAttributes;
ScopedPtr<MemberListInfoContext> privateStaticAttributes;
ScopedPtr<MemberListInfoContext> privateSlots;
ScopedPtr<MemberListInfoContext> packageTypes;
ScopedPtr<MemberListInfoContext> packageMethods;
ScopedPtr<MemberListInfoContext> packageStaticMethods;
ScopedPtr<MemberListInfoContext> packageAttributes;
ScopedPtr<MemberListInfoContext> packageStaticAttributes;
ScopedPtr<MemberListInfoContext> unoIDLServices;
ScopedPtr<MemberListInfoContext> unoIDLInterfaces;
ScopedPtr<MemberListInfoContext> signals;
ScopedPtr<MemberListInfoContext> properties;
ScopedPtr<MemberListInfoContext> events;
ScopedPtr<MemberListInfoContext> friends;
ScopedPtr<MemberListInfoContext> related;
ScopedPtr<MemberListInfoContext> detailedTypedefs;
ScopedPtr<MemberListInfoContext> detailedEnums;
ScopedPtr<MemberListInfoContext> detailedServices;
ScopedPtr<MemberListInfoContext> detailedInterfaces;
ScopedPtr<MemberListInfoContext> detailedConstructors;
ScopedPtr<MemberListInfoContext> detailedMethods;
ScopedPtr<MemberListInfoContext> detailedRelated;
ScopedPtr<MemberListInfoContext> detailedVariables;
ScopedPtr<MemberListInfoContext> detailedProperties;
ScopedPtr<MemberListInfoContext> detailedEvents;
ScopedPtr<MemberGroupListContext> memberGroups;
ScopedPtr<AllMembersListContext> allMembersList;
ScopedPtr<ArgumentListContext> typeConstraints;
ScopedPtr<TemplateList> examples;
ScopedPtr<TemplateList> templateDecls;
ScopedPtr<AllMembersListContext> allMembersList;
ScopedPtr<ArgumentListContext> typeConstraints;
ScopedPtr<TemplateList> examples;
ScopedPtr<TemplateList> templateDecls;
ScopedPtr<InheritedMemberInfoListContext> additionalInheritedMembers;
ScopedPtr<MemberListContext> members;
QList<ArgumentListContext> templateArgList;
int inheritanceNodes;
QList<TemplateStruct> exampleList;
MemberList allMembers;
ScopedPtr<MemberListContext> members;
QList<ArgumentListContext> templateArgList;
int inheritanceNodes;
QList<TemplateStruct> exampleList;
MemberList allMembers;
};
mutable Cachable m_cache;
};
......@@ -1862,6 +1983,7 @@ class NamespaceContext::Private : public DefinitionContext<NamespaceContext::Pri
addProperty("title",this,&Private::title);
addProperty("highlight",this,&Private::highlight);
addProperty("subhighlight",this,&Private::subHighlight);
addProperty("compoundType",this,&Private::compoundType);
}
TemplateVariant title() const
{
......@@ -1875,6 +1997,10 @@ class NamespaceContext::Private : public DefinitionContext<NamespaceContext::Pri
{
return TemplateVariant("");
}
TemplateVariant compoundType() const
{
return m_namespaceDef->compoundTypeString();
}
private:
NamespaceDef *m_namespaceDef;
};
......@@ -1904,10 +2030,34 @@ class FileContext::Private : public DefinitionContext<FileContext::Private>
public:
Private(FileDef *fd) : DefinitionContext<FileContext::Private>(fd) , m_fileDef(fd)
{
addProperty("title",this,&Private::title);
addProperty("highlight",this,&Private::highlight);
addProperty("subhighlight",this,&Private::subHighlight);
addProperty("versionInfo",this,&Private::versionInfo);
addProperty("title", this,&Private::title);
addProperty("highlight", this,&Private::highlight);
addProperty("subhighlight", this,&Private::subHighlight);
addProperty("versionInfo", this,&Private::versionInfo);
addProperty("includeList", this,&Private::includeList);
addProperty("hasIncludeGraph", this,&Private::hasIncludeGraph);
addProperty("hasIncludedByGraph", this,&Private::hasIncludedByGraph);
addProperty("includeGraph", this,&Private::includeGraph);
addProperty("includedByGraph", this,&Private::includedByGraph);
addProperty("hasDetails", this,&Private::hasDetails);
addProperty("hasSourceFile", this,&Private::hasSourceFile);
addProperty("sources", this,&Private::sources);
addProperty("version", this,&Private::version);
addProperty("classes", this,&Private::classes);
addProperty("namespaces", this,&Private::namespaces);
addProperty("constantgroups", this,&Private::constantgroups);
addProperty("macros", this,&Private::macros);
addProperty("typedefs", this,&Private::typedefs);
addProperty("enums", this,&Private::enums);
addProperty("functions", this,&Private::functions);
addProperty("variables", this,&Private::variables);
addProperty("memberGroups", this,&Private::memberGroups);
addProperty("detailedMacros", this,&Private::detailedMacros);
addProperty("detailedTypedefs", this,&Private::detailedTypedefs);
addProperty("detailedEnums", this,&Private::detailedEnums);
addProperty("detailedFunctions", this,&Private::detailedFunctions);
addProperty("detailedVariables", this,&Private::detailedVariables);
addProperty("inlineClasses", this,&Private::inlineClasses);
}
TemplateVariant title() const
{
......@@ -1925,8 +2075,302 @@ class FileContext::Private : public DefinitionContext<FileContext::Private>
{
return m_fileDef->getVersion();
}
TemplateVariant includeList() const
{
if (!m_cache.includeInfoList && m_fileDef->includeFileList())
{
m_cache.includeInfoList.reset(new IncludeInfoListContext(
*m_fileDef->includeFileList(),m_fileDef->getLanguage()));
}
if (m_cache.includeInfoList)
{
return m_cache.includeInfoList.get();
}
else
{
return TemplateVariant(FALSE);
}
}
DotInclDepGraph *getIncludeGraph() const
{
if (!m_cache.includeGraph)
{
m_cache.includeGraph.reset(new DotInclDepGraph(m_fileDef,FALSE));
}
return m_cache.includeGraph.get();
}
TemplateVariant hasIncludeGraph() const
{
static bool haveDot = Config_getBool("HAVE_DOT");
DotInclDepGraph *incGraph = getIncludeGraph();
return (haveDot && !incGraph->isTooBig() && !incGraph->isTrivial());
}
TemplateVariant includeGraph() const
{
static bool haveDot = Config_getBool("HAVE_DOT");
QGString result;
if (haveDot)
{
DotInclDepGraph *cg = getIncludeGraph();
FTextStream t(&result);
cg->writeGraph(t,BITMAP,
g_globals.outputDir,
g_globals.outputDir+portable_pathSeparator()+m_fileDef->getOutputFileBase()+Doxygen::htmlFileExtension,
relPathAsString(),TRUE,g_globals.dynSectionId
);
}
g_globals.dynSectionId++;
return TemplateVariant(result.data(),TRUE);
}
DotInclDepGraph *getIncludedByGraph() const
{
if (!m_cache.includedByGraph)
{
m_cache.includedByGraph.reset(new DotInclDepGraph(m_fileDef,TRUE));
}
return m_cache.includedByGraph.get();
}
TemplateVariant hasIncludedByGraph() const
{
static bool haveDot = Config_getBool("HAVE_DOT");
DotInclDepGraph *incGraph = getIncludedByGraph();
return (haveDot && !incGraph->isTooBig() && !incGraph->isTrivial());
}
TemplateVariant includedByGraph() const
{
static bool haveDot = Config_getBool("HAVE_DOT");
QGString result;
if (haveDot)
{
DotInclDepGraph *cg = getIncludedByGraph();
FTextStream t(&result);
cg->writeGraph(t,BITMAP,
g_globals.outputDir,
g_globals.outputDir+portable_pathSeparator()+m_fileDef->getOutputFileBase()+Doxygen::htmlFileExtension,
relPathAsString(),TRUE,g_globals.dynSectionId
);
}
g_globals.dynSectionId++;
return TemplateVariant(result.data(),TRUE);
}
TemplateVariant hasDetails() const
{
return m_fileDef->hasDetailedDescription();
}
TemplateVariant hasSourceFile() const
{
return m_fileDef->generateSourceFile();
}
TemplateVariant sources() const
{
if (!m_cache.sources)
{
if (m_fileDef->generateSourceFile())
{
m_cache.sources.reset(new TemplateVariant(parseCode(m_fileDef,relPathAsString())));
}
else
{
m_cache.sources.reset(new TemplateVariant(""));
}
}
return *m_cache.sources;
}
TemplateVariant version() const
{
return m_fileDef->fileVersion();
}
TemplateVariant classes() const
{
if (!m_cache.classes)
{
NestedClassListContext *classList = new NestedClassListContext;
if (m_fileDef->getClassSDict())
{
ClassSDict::Iterator sdi(*m_fileDef->getClassSDict());
ClassDef *cd;
for (sdi.toFirst();(cd=sdi.current());++sdi)
{
if (cd->visibleInParentsDeclList())
{
classList->append(cd);
}
}
}
m_cache.classes.reset(classList);
}
return m_cache.classes.get();
}
TemplateVariant namespaces() const
{
if (!m_cache.namespaces)
{
NestedNamespaceListContext *namespaceList = new NestedNamespaceListContext;
if (m_fileDef->getNamespaceSDict())
{
NamespaceSDict::Iterator sdi(*m_fileDef->getNamespaceSDict());
NamespaceDef *nd;
for (sdi.toFirst();(nd=sdi.current());++sdi)
{
if (nd->isLinkable() && !nd->isConstantGroup())
{
namespaceList->append(nd);
}
}
}
m_cache.namespaces.reset(namespaceList);
}
return m_cache.namespaces.get();
}
TemplateVariant constantgroups() const
{
if (!m_cache.constantgroups)
{
NestedNamespaceListContext *namespaceList = new NestedNamespaceListContext;
if (m_fileDef->getNamespaceSDict())
{
NamespaceSDict::Iterator sdi(*m_fileDef->getNamespaceSDict());
NamespaceDef *nd;
for (sdi.toFirst();(nd=sdi.current());++sdi)
{
if (nd->isLinkable() && nd->isConstantGroup())
{
namespaceList->append(nd);
}
}
}
m_cache.constantgroups.reset(namespaceList);
}
return m_cache.constantgroups.get();
}
TemplateVariant getMemberList(ScopedPtr<MemberListInfoContext> &list,
MemberListType type,const char *title,bool detailed=FALSE) const
{
if (!list)
{
MemberList *ml = m_fileDef->getMemberList(type);
if (ml)
{
list.reset(new MemberListInfoContext(m_fileDef,relPathAsString(),ml,title,detailed));
}
}
if (list)
{
return list.get();
}
else
{
return TemplateVariant(FALSE);
}
}
TemplateVariant macros() const
{
return getMemberList(m_cache.macros,MemberListType_decDefineMembers,theTranslator->trDefines());
}
TemplateVariant typedefs() const
{
return getMemberList(m_cache.typedefs,MemberListType_decTypedefMembers,theTranslator->trTypedefs());
}
TemplateVariant enums() const
{
return getMemberList(m_cache.enums,MemberListType_decEnumMembers,theTranslator->trEnumerations());
}
TemplateVariant functions() const
{
// TODO: Fortran: trSubprograms()
// TODO: VHDL: VhdlDocGen::trFunctionAndProc()
return getMemberList(m_cache.functions,MemberListType_decFuncMembers,theTranslator->trFunctions());
}
TemplateVariant variables() const
{
return getMemberList(m_cache.variables,MemberListType_decVarMembers,theTranslator->trVariables());
}
TemplateVariant memberGroups() const
{
if (!m_cache.memberGroups)
{
if (m_fileDef->getMemberGroupSDict())
{
m_cache.memberGroups.reset(new MemberGroupListContext(m_fileDef,relPathAsString(),m_fileDef->getMemberGroupSDict(),m_fileDef->subGrouping()));
}
else
{
m_cache.memberGroups.reset(new MemberGroupListContext);
}
}
return m_cache.memberGroups.get();
}
TemplateVariant detailedMacros() const
{
return getMemberList(m_cache.detailedMacros,MemberListType_docDefineMembers,theTranslator->trDefineDocumentation());
}
TemplateVariant detailedTypedefs() const
{
return getMemberList(m_cache.detailedTypedefs,MemberListType_docTypedefMembers,theTranslator->trTypedefDocumentation());
}
TemplateVariant detailedEnums() const
{
return getMemberList(m_cache.detailedEnums,MemberListType_docEnumMembers,theTranslator->trEnumerationTypeDocumentation());
}
TemplateVariant detailedFunctions() const
{
// TODO: Fortran: trSubprogramDocumentation()
return getMemberList(m_cache.detailedFunctions,MemberListType_docFuncMembers,theTranslator->trFunctionDocumentation());
}
TemplateVariant detailedVariables() const
{
return getMemberList(m_cache.detailedVariables,MemberListType_docVarMembers,theTranslator->trVariableDocumentation());
}
TemplateVariant inlineClasses() const
{
if (!m_cache.inlineClasses)
{
NestedClassListContext *classList = new NestedClassListContext;
if (m_fileDef->getClassSDict())
{
ClassSDict::Iterator sdi(*m_fileDef->getClassSDict());
ClassDef *cd;
for (sdi.toFirst();(cd=sdi.current());++sdi)
{
if (cd->name().find('@')==-1 &&
cd->isLinkableInProject() &&
cd->isEmbeddedInOuterScope() &&
cd->partOfGroups()==0)
{
classList->append(cd);
}
}
}
m_cache.inlineClasses.reset(classList);
}
return m_cache.inlineClasses.get();
}
private:
FileDef *m_fileDef;
struct Cachable
{
ScopedPtr<IncludeInfoListContext> includeInfoList;
ScopedPtr<DotInclDepGraph> includeGraph;
ScopedPtr<DotInclDepGraph> includedByGraph;
ScopedPtr<TemplateVariant> sources;
ScopedPtr<NestedClassListContext> classes;
ScopedPtr<NestedNamespaceListContext> namespaces;
ScopedPtr<NestedNamespaceListContext> constantgroups;
ScopedPtr<MemberListInfoContext> macros;
ScopedPtr<MemberListInfoContext> typedefs;
ScopedPtr<MemberListInfoContext> enums;
ScopedPtr<MemberListInfoContext> functions;
ScopedPtr<MemberListInfoContext> variables;
ScopedPtr<MemberGroupListContext> memberGroups;
ScopedPtr<MemberListInfoContext> detailedMacros;
ScopedPtr<MemberListInfoContext> detailedTypedefs;
ScopedPtr<MemberListInfoContext> detailedEnums;
ScopedPtr<MemberListInfoContext> detailedFunctions;
ScopedPtr<MemberListInfoContext> detailedVariables;
ScopedPtr<NestedClassListContext> inlineClasses;
};
mutable Cachable m_cache;
};
//%% }
......@@ -2160,21 +2604,70 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private>
public:
Private(MemberDef *md) : DefinitionContext<MemberContext::Private>(md) , m_memberDef(md)
{
addProperty("declType", this,&Private::declType);
addProperty("declArgs", this,&Private::declArgs);
addProperty("isSignal", this,&Private::isSignal);
addProperty("isSlot", this,&Private::isSlot);
addProperty("isVariable", this,&Private::isVariable);
addProperty("isEnumeration", this,&Private::isEnumeration);
addProperty("isEnumValue", this,&Private::isEnumValue);
addProperty("isTypedef", this,&Private::isTypedef);
addProperty("isFunction", this,&Private::isFunction);
addProperty("isFunctionPtr", this,&Private::isFunctionPtr);
addProperty("isDefine", this,&Private::isDefine);
addProperty("isFriend", this,&Private::isFriend);
addProperty("isProperty", this,&Private::isProperty);
addProperty("isEvent", this,&Private::isEvent);
addProperty("isRelated", this,&Private::isRelated);
addProperty("isForeign", this,&Private::isForeign);
addProperty("isStatic", this,&Private::isStatic);
addProperty("isInline", this,&Private::isInline);
addProperty("isExplicit", this,&Private::isExplicit);
addProperty("isMutable", this,&Private::isMutable);
addProperty("isGettable", this,&Private::isGettable);
addProperty("isSettable", this,&Private::isSettable);
addProperty("isReadable", this,&Private::isReadable);
addProperty("isWritable", this,&Private::isWritable);
addProperty("isAddable", this,&Private::isAddable);
addProperty("isRemovable", this,&Private::isRemovable);
addProperty("isRaisable", this,&Private::isRaisable);
addProperty("isFinal", this,&Private::isFinal);
addProperty("isAbstract", this,&Private::isAbstract);
addProperty("isOverride", this,&Private::isOverride);
addProperty("isInitonly", this,&Private::isInitonly);
addProperty("isOptional", this,&Private::isOptional);
addProperty("isRequired", this,&Private::isRequired);
addProperty("isNonAtomic", this,&Private::isNonAtomic);
addProperty("isCopy", this,&Private::isCopy);
addProperty("isAssign", this,&Private::isAssign);
addProperty("isRetain", this,&Private::isRetain);
addProperty("isWeak", this,&Private::isWeak);
addProperty("isStrong", this,&Private::isStrong);
addProperty("isUnretained", this,&Private::isUnretained);
addProperty("isNew", this,&Private::isNew);
addProperty("isSealed", this,&Private::isSealed);
addProperty("isImplementation", this,&Private::isImplementation);
addProperty("isExternal", this,&Private::isExternal);
addProperty("isAlias", this,&Private::isAlias);
addProperty("isDefault", this,&Private::isDefault);
addProperty("isDelete", this,&Private::isDelete);
addProperty("isNoExcept", this,&Private::isNoExcept);
addProperty("isAttribute", this,&Private::isAttribute);
addProperty("isUNOProperty", this,&Private::isUNOProperty);
addProperty("isReadonly", this,&Private::isReadonly);
addProperty("isBound", this,&Private::isBound);
addProperty("isConstrained", this,&Private::isConstrained);
addProperty("isTransient", this,&Private::isTransient);
addProperty("isMaybeVoid", this,&Private::isMaybeVoid);
addProperty("isMaybeDefault", this,&Private::isMaybeDefault);
addProperty("isMaybeAmbiguous", this,&Private::isMaybeAmbiguous);
addProperty("isPublished", this,&Private::isPublished);
addProperty("isTemplateSpecialization",this,&Private::isTemplateSpecialization);
addProperty("isObjCMethod", this,&Private::isObjCMethod);
addProperty("isObjCProperty", this,&Private::isObjCProperty);
addProperty("isDefine", this,&Private::isDefine);
addProperty("isImplementation", this,&Private::isImplementation);
addProperty("isEvent", this,&Private::isEvent);
addProperty("isProperty", this,&Private::isProperty);
addProperty("isEnumeration", this,&Private::isEnumeration);
addProperty("isEnumValue", this,&Private::isEnumValue);
addProperty("isAnonymous", this,&Private::isAnonymous);
addProperty("declType", this,&Private::declType);
addProperty("declArgs", this,&Private::declArgs);
addProperty("anonymousType", this,&Private::anonymousType);
addProperty("anonymousMember", this,&Private::anonymousMember);
addProperty("isRelated", this,&Private::isRelated);
addProperty("hasDetails", this,&Private::hasDetails);
addProperty("exception", this,&Private::exception);
addProperty("bitfields", this,&Private::bitfields);
......@@ -2214,6 +2707,7 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private>
addProperty("callGraph", this,&Private::callGraph);
addProperty("hasCallerGraph", this,&Private::hasCallerGraph);
addProperty("callerGraph", this,&Private::callerGraph);
addProperty("fieldType", this,&Private::fieldType);
if (md && md->isProperty())
{
......@@ -2227,6 +2721,10 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private>
if (md->isRaisable()) m_eventAttrs.append("raise");
}
}
TemplateVariant fieldType() const
{
return createLinkedText(m_memberDef,relPathAsString(),m_memberDef->fieldType());
}
TemplateVariant declType() const
{
return createLinkedText(m_memberDef,relPathAsString(),m_memberDef->getDeclType());
......@@ -2259,10 +2757,202 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private>
{
return m_memberDef->isImplementation();
}
TemplateVariant isSignal() const
{
return m_memberDef->isSignal();
}
TemplateVariant isSlot() const
{
return m_memberDef->isSlot();
}
TemplateVariant isTypedef() const
{
return m_memberDef->isTypedef();
}
TemplateVariant isFunction() const
{
return m_memberDef->isFunction();
}
TemplateVariant isFunctionPtr() const
{
return m_memberDef->isFunctionPtr();
}
TemplateVariant isFriend() const
{
return m_memberDef->isFriend();
}
TemplateVariant isForeign() const
{
return m_memberDef->isForeign();
}
TemplateVariant isEvent() const
{
return m_memberDef->isEvent();
}
TemplateVariant isInline() const
{
return m_memberDef->isInline();
}
TemplateVariant isExplicit() const
{
return m_memberDef->isExplicit();
}
TemplateVariant isMutable() const
{
return m_memberDef->isMutable();
}
TemplateVariant isGettable() const
{
return m_memberDef->isSettable();
}
TemplateVariant isSettable() const
{
return m_memberDef->isSettable();
}
TemplateVariant isReadable() const
{
return m_memberDef->isReadable();
}
TemplateVariant isWritable() const
{
return m_memberDef->isWritable();
}
TemplateVariant isAddable() const
{
return m_memberDef->isAddable();
}
TemplateVariant isRemovable() const
{
return m_memberDef->isRemovable();
}
TemplateVariant isRaisable() const
{
return m_memberDef->isRaisable();
}
TemplateVariant isFinal() const
{
return m_memberDef->isFinal();
}
TemplateVariant isAbstract() const
{
return m_memberDef->isAbstract();
}
TemplateVariant isOverride() const
{
return m_memberDef->isOverride();
}
TemplateVariant isInitonly() const
{
return m_memberDef->isInitonly();
}
TemplateVariant isOptional() const
{
return m_memberDef->isOptional();
}
TemplateVariant isRequired() const
{
return m_memberDef->isRequired();
}
TemplateVariant isNonAtomic() const
{
return m_memberDef->isNonAtomic();
}
TemplateVariant isCopy() const
{
return m_memberDef->isCopy();
}
TemplateVariant isAssign() const
{
return m_memberDef->isAssign();
}
TemplateVariant isRetain() const
{
return m_memberDef->isRetain();
}
TemplateVariant isWeak() const
{
return m_memberDef->isWeak();
}
TemplateVariant isStrong() const
{
return m_memberDef->isStrong();
}
TemplateVariant isUnretained() const
{
return m_memberDef->isUnretained();
}
TemplateVariant isNew() const
{
return m_memberDef->isNew();
}
TemplateVariant isSealed() const
{
return m_memberDef->isSealed();
}
TemplateVariant isExternal() const
{
return m_memberDef->isExternal();
}
TemplateVariant isAlias() const
{
return m_memberDef->isAlias();
}
TemplateVariant isDefault() const
{
return m_memberDef->isDefault();
}
TemplateVariant isDelete() const
{
return m_memberDef->isDelete();
}
TemplateVariant isNoExcept() const
{
return m_memberDef->isNoExcept();
}
TemplateVariant isAttribute() const
{
return m_memberDef->isAttribute();
}
TemplateVariant isUNOProperty() const
{
return m_memberDef->isUNOProperty();
}
TemplateVariant isReadonly() const
{
return m_memberDef->isReadonly();
}
TemplateVariant isBound() const
{
return m_memberDef->isBound();
}
TemplateVariant isConstrained() const
{
return m_memberDef->isConstrained();
}
TemplateVariant isTransient() const
{
return m_memberDef->isTransient();
}
TemplateVariant isMaybeVoid() const
{
return m_memberDef->isMaybeVoid();
}
TemplateVariant isMaybeDefault() const
{
return m_memberDef->isMaybeDefault();
}
TemplateVariant isMaybeAmbiguous() const
{
return m_memberDef->isMaybeAmbiguous();
}
TemplateVariant isPublished() const
{
return m_memberDef->isPublished();
}
TemplateVariant isTemplateSpecialization() const
{
return m_memberDef->isTemplateSpecialization();
}
TemplateVariant isProperty() const
{
return m_memberDef->isProperty();
......@@ -2271,6 +2961,10 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private>
{
return m_memberDef->isEnumValue();
}
TemplateVariant isVariable() const
{
return m_memberDef->isVariable();
}
TemplateVariant isEnumeration() const
{
return m_memberDef->isEnumerate();
......@@ -2717,10 +3411,10 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private>
TemplateVariant functionQualifier() const
{
if (!m_memberDef->isObjCMethod() &&
(m_memberDef->isFunction() || m_memberDef->isSlot() ||
(m_memberDef->isFunction() || m_memberDef->isSlot() ||
m_memberDef->isPrototype() || m_memberDef->isSignal()
)
)
)
{
return "()";
}
......@@ -3007,6 +3701,47 @@ void NestedClassListContext::append(ClassDef *cd)
//------------------------------------------------------------------------
//%% list NestedClassList[Class] : list of nested namespaces
class NestedNamespaceListContext::Private : public GenericNodeListContext<NamespaceContext>
{
};
NestedNamespaceListContext::NestedNamespaceListContext()
{
p = new Private;
}
NestedNamespaceListContext::~NestedNamespaceListContext()
{
delete p;
}
// TemplateListIntf
int NestedNamespaceListContext::count() const
{
return p->count();
}
TemplateVariant NestedNamespaceListContext::at(int index) const
{
return p->at(index);
}
TemplateListIntf::ConstIterator *NestedNamespaceListContext::createIterator() const
{
return p->createIterator();
}
void NestedNamespaceListContext::append(NamespaceDef *cd)
{
if (cd)
{
p->append(new NamespaceContext(cd));
}
}
//------------------------------------------------------------------------
//%% list ClassList[Class] : list of classes
class ClassListContext::Private : public GenericNodeListContext<ClassContext>
{
......@@ -5744,7 +6479,7 @@ void generateOutputViaTemplate()
ctx->set("exampleList",&exampleList);
// render HTML output
Template *tpl = e.loadByName("htmllayout.tpl");
Template *tpl = e.loadByName("htmllayout.tpl",1);
if (tpl)
{
g_globals.outputFormat = ContextGlobals::Html;
......@@ -5758,6 +6493,7 @@ void generateOutputViaTemplate()
FTextStream ts;
tpl->render(ts,ctx);
}
e.unload(tpl);
// TODO: render other outputs
}
......
......@@ -3,6 +3,7 @@
#include "types.h"
#include "template.h"
#include <qlist.h>
class Definition;
class ClassDef;
......@@ -108,7 +109,7 @@ class UsedFilesContext : public TemplateListIntf
class IncludeInfoContext : public TemplateStructIntf
{
public:
IncludeInfoContext(IncludeInfo *,SrcLangExt lang);
IncludeInfoContext(const IncludeInfo *,SrcLangExt lang);
~IncludeInfoContext();
// TemplateStructIntf methods
......@@ -119,6 +120,25 @@ class IncludeInfoContext : public TemplateStructIntf
Private *p;
};
//----------------------------------------------------
class IncludeInfoListContext : public TemplateListIntf
{
public:
IncludeInfoListContext(const QList<IncludeInfo> &list,SrcLangExt lang);
~IncludeInfoListContext();
// TemplateListIntf
virtual int count() const;
virtual TemplateVariant at(int index) const;
virtual TemplateListIntf::ConstIterator *createIterator() const;
private:
class Private;
Private *p;
};
//----------------------------------------------------
class ClassContext : public TemplateStructIntf
......@@ -254,6 +274,26 @@ class NestedClassListContext : public TemplateListIntf
//----------------------------------------------------
class NestedNamespaceListContext : public TemplateListIntf
{
public:
NestedNamespaceListContext();
~NestedNamespaceListContext();
// TemplateListIntf
virtual int count() const;
virtual TemplateVariant at(int index) const;
virtual TemplateListIntf::ConstIterator *createIterator() const;
void append(NamespaceDef *cd);
private:
class Private;
Private *p;
};
//----------------------------------------------------
class ClassListContext : public TemplateListIntf
{
public:
......
......@@ -170,12 +170,18 @@ void FileDef::findSectionsInDocumentation()
}
}
bool FileDef::hasDetailedDescription() const
{
static bool sourceBrowser = Config_getBool("SOURCE_BROWSER");
return ((!briefDescription().isEmpty() && Config_getBool("REPEAT_BRIEF")) ||
!documentation().stripWhiteSpace().isEmpty() || // avail empty section
(sourceBrowser && getStartBodyLine()!=-1 && getBodyDef())
);
}
void FileDef::writeDetailedDescription(OutputList &ol,const QCString &title)
{
if ((!briefDescription().isEmpty() && Config_getBool("REPEAT_BRIEF")) ||
!documentation().stripWhiteSpace().isEmpty() || // avail empty section
(Config_getBool("SOURCE_BROWSER") && getStartBodyLine()!=-1 && getBodyDef())
)
if (hasDetailedDescription())
{
ol.pushGeneratorState();
ol.disable(OutputGenerator::Html);
......@@ -379,7 +385,7 @@ void FileDef::writeIncludedByGraph(OutputList &ol)
{
warn_uncond("Included by graph for '%s' not generated, too many nodes. Consider increasing DOT_GRAPH_MAX_NODES.\n",name().data());
}
if (!incDepGraph.isTrivial())
else if (!incDepGraph.isTrivial())
{
ol.startTextBlock();
ol.disable(OutputGenerator::Man);
......@@ -1800,3 +1806,7 @@ QCString FileDef::title() const
return theTranslator->trFileReference(name());
}
QCString FileDef::fileVersion() const
{
return m_fileVersion;
}
......@@ -133,6 +133,10 @@ class FileDef : public Definition
ClassSDict *getClassSDict() const { return m_classSDict; }
QCString title() const;
bool hasDetailedDescription() const;
QCString fileVersion() const;
bool subGrouping() const { return m_subGrouping; }
//---------------------------------
......
......@@ -3036,6 +3036,18 @@ static Definition *getClassFromType(Definition *scope,const QCString &type,SrcLa
}
#endif
QCString MemberDef::fieldType() const
{
QCString type = m_impl->accessorType;
if (type.isEmpty())
{
type = m_impl->type;
}
if (isTypedef()) type.prepend("typedef ");
return simplifyTypeForTable(type);
}
void MemberDef::writeMemberDocSimple(OutputList &ol, Definition *container)
{
Definition *scope = getOuterScope();
......@@ -3056,15 +3068,7 @@ void MemberDef::writeMemberDocSimple(OutputList &ol, Definition *container)
ol.startInlineMemberType();
ol.startDoxyAnchor(cfname,cname,memAnchor,doxyName,doxyArgs);
QCString type = m_impl->accessorType;
if (type.isEmpty())
{
type = m_impl->type;
}
if (isTypedef()) type.prepend("typedef ");
QCString ts = simplifyTypeForTable(type);
QCString ts = fieldType();
if (cd) // cd points to an anonymous struct pointed to by this member
// so we add a link to it from the type column.
......@@ -3855,6 +3859,11 @@ void MemberDef::setAccessorType(ClassDef *cd,const char *t)
m_impl->accessorType = t;
}
ClassDef *MemberDef::accessorClass() const
{
return m_impl->accessorClass;
}
void MemberDef::findSectionsInDocumentation()
{
docFindSections(documentation(),this,0,docFile());
......
......@@ -81,6 +81,7 @@ class MemberDef : public Definition
ClassDef *getClassDef() const;
FileDef *getFileDef() const;
NamespaceDef* getNamespaceDef() const;
ClassDef *accessorClass() const;
// grabbing the property read/write accessor names
const char *getReadAccessor() const;
......@@ -251,7 +252,7 @@ class MemberDef : public Definition
// overrules
QCString documentation() const;
QCString briefDescription(bool abbr=FALSE) const;
QCString fieldType() const;
//-----------------------------------------------------------------------------------
......
......@@ -13,7 +13,6 @@
*
*/
#include <stdarg.h>
#include <stdio.h>
#include <qdatetime.h>
#include "config.h"
......@@ -22,6 +21,7 @@
#include "doxygen.h"
#include "portable.h"
#include "filedef.h"
#include "message.h"
static QCString outputFormat;
static const char *warning_str = "warning: ";
......@@ -110,7 +110,7 @@ void msg(const char *fmt, ...)
va_list args;
va_start(args, fmt);
vfprintf(stdout, fmt, args);
va_end(args);
va_end(args);
}
}
......@@ -172,6 +172,11 @@ void warn(const char *file,int line,const char *fmt, ...)
va_end(args);
}
void warn(const char *file,int line,const char *fmt,va_list args)
{
do_warn("WARNINGS", file, line, warning_str, fmt, args);
}
void warn_simple(const char *file,int line,const char *text)
{
if (!Config_getBool("WARNINGS")) return; // warning type disabled
......
......@@ -19,9 +19,11 @@
#define MESSAGE_H
#include <stdio.h>
#include <stdarg.h>
extern void msg(const char *fmt, ...);
extern void warn(const char *file,int line,const char *fmt, ...);
extern void warn(const char *file,int line,const char *fmt, va_list args);
extern void warn_simple(const char *file,int line,const char *text);
extern void warn_undoc(const char *file,int line,const char *fmt, ...);
extern void warn_doc_error(const char *file,int line,const char *fmt, ...);
......
......@@ -916,29 +916,9 @@ void NamespaceSDict::writeDeclaration(OutputList &ol,const char *title,
continue; // will be output in another pass, see layout_default.xml
ol.startMemberDeclaration();
ol.startMemberItem(nd->getOutputFileBase(),0);
if (lang==SrcLangExt_Java || lang==SrcLangExt_CSharp)
{
ol.docify("package ");
}
else if (lang==SrcLangExt_Fortran)
{
ol.docify("module ");
}
else if (lang==SrcLangExt_IDL)
{
if (nd->isModule())
{
ol.docify("module ");
}
else if (nd->isConstantGroup())
{
ol.docify("constants");
}
else
{
err("Internal inconsistency: namespace in IDL not module or cg\n");
}
}
QCString ct = nd->compoundTypeString();
ol.docify(ct);
ol.docify(" ");
ol.insertMemberAlign();
QCString name;
if (localName)
......@@ -1103,3 +1083,33 @@ QCString NamespaceDef::title() const
}
return pageTitle;
}
QCString NamespaceDef::compoundTypeString() const
{
SrcLangExt lang = getLanguage();
if (lang==SrcLangExt_Java || lang==SrcLangExt_CSharp)
{
return "package";
}
else if (lang==SrcLangExt_Fortran)
{
return "module";
}
else if (lang==SrcLangExt_IDL)
{
if (isModule())
{
return "module";
}
else if (isConstantGroup())
{
return "constants";
}
else
{
err("Internal inconsistency: namespace in IDL not module or constant group\n");
}
}
return "";
}
......@@ -94,6 +94,7 @@ class NamespaceDef : public Definition
NamespaceSDict *getNamespaceSDict() const { return namespaceSDict; }
QCString title() const;
QCString compoundTypeString() const;
bool visited;
......
......@@ -29,7 +29,8 @@ class TemplateToken;
//-------------------------------------------------------------------
static QValueList<QCString> split(const QCString &str,const QCString &sep,bool allowEmptyEntries=FALSE,bool cleanup=TRUE)
static QValueList<QCString> split(const QCString &str,const QCString &sep,
bool allowEmptyEntries=FALSE,bool cleanup=TRUE)
{
QValueList<QCString> lst;
......@@ -561,7 +562,7 @@ class TemplateBlockContext
class TemplateContextImpl : public TemplateContext
{
public:
TemplateContextImpl();
TemplateContextImpl(const TemplateEngine *e);
virtual ~TemplateContextImpl();
// TemplateContext methods
......@@ -589,8 +590,10 @@ class TemplateContextImpl : public TemplateContext
TemplateSpacelessIntf *spacelessIntf() const { return m_spacelessIntf; }
void enableSpaceless(bool b) { m_spacelessEnabled=b; }
bool spacelessEnabled() const { return m_spacelessEnabled && m_spacelessIntf; }
void warn(const char *fileName,int line,const char *fmt,...) const;
private:
const TemplateEngine *m_engine;
QCString m_templateName;
int m_line;
QCString m_outputDir;
......@@ -874,7 +877,7 @@ class ExprAstVariable : public ExprAst
TemplateVariant v = c->get(m_name);
if (!v.isValid())
{
warn(ci->templateName(),ci->line(),"undefined variable '%s' in expression",m_name.data());
ci->warn(ci->templateName(),ci->line(),"undefined variable '%s' in expression",m_name.data());
}
return v;
}
......@@ -928,7 +931,7 @@ class ExprAstFilter : public ExprAst
TemplateVariant result = TemplateFilterFactory::instance()->apply(m_name,v,arg,ok);
if (!ok)
{
warn(ci->templateName(),ci->line(),"unknown filter '%s'",m_name.data());
ci->warn(ci->templateName(),ci->line(),"unknown filter '%s'",m_name.data());
}
return result;
}
......@@ -1047,6 +1050,46 @@ class ExprAstBinary : public ExprAst
ExprAst *m_rhs;
};
//----------------------------------------------------------
/** @brief Base class of all nodes in a template's AST */
class TemplateNode
{
public:
TemplateNode(TemplateNode *parent) : m_parent(parent) {}
virtual ~TemplateNode() {}
virtual void render(FTextStream &ts, TemplateContext *c) = 0;
TemplateNode *parent() { return m_parent; }
private:
TemplateNode *m_parent;
};
//----------------------------------------------------------
/** @brief Parser for templates */
class TemplateParser
{
public:
TemplateParser(const TemplateEngine *engine,
const QCString &templateName,QList<TemplateToken> &tokens);
void parse(TemplateNode *parent,int line,const QStrList &stopAt,
QList<TemplateNode> &nodes);
bool hasNextToken() const;
TemplateToken *takeNextToken();
void removeNextToken();
void prependToken(const TemplateToken *token);
const TemplateToken *currentToken() const;
QCString templateName() const { return m_templateName; }
void warn(const char *fileName,int line,const char *fmt,...) const;
private:
const TemplateEngine *m_engine;
QCString m_templateName;
QList<TemplateToken> &m_tokens;
};
//--------------------------------------------------------------------
/** @brief Recursive decent parser for Django style template expressions.
......@@ -1054,8 +1097,8 @@ class ExprAstBinary : public ExprAst
class ExpressionParser
{
public:
ExpressionParser(const QCString &templateName,int line)
: m_templateName(templateName), m_line(line), m_tokenStream(0)
ExpressionParser(const TemplateParser *parser,int line)
: m_parser(parser), m_line(line), m_tokenStream(0)
{
}
virtual ~ExpressionParser()
......@@ -1153,7 +1196,7 @@ class ExpressionParser
ExprAst *expr = parseCompareExpression();
if (expr==0)
{
warn(m_templateName,m_line,"argument missing for not operator");
warn(m_parser->templateName(),m_line,"argument missing for not operator");
return 0;
}
result = new ExprAstNegate(expr);
......@@ -1210,12 +1253,12 @@ class ExpressionParser
default:
if (m_curToken.type==ExprToken::Operator)
{
warn(m_templateName,m_line,"unexpected operator '%s' in expression",
warn(m_parser->templateName(),m_line,"unexpected operator '%s' in expression",
Operator::toString(m_curToken.op));
}
else
{
warn(m_templateName,m_line,"unexpected token in expression");
warn(m_parser->templateName(),m_line,"unexpected token in expression");
}
}
TRACE(("}parsePrimary(%s)\n",m_tokenStream));
......@@ -1461,7 +1504,7 @@ class ExpressionParser
char s[2];
s[0]=c;
s[1]=0;
warn(m_templateName,m_line,"Found unknown token %s while parsing %s",s,m_tokenStream);
warn(m_parser->templateName(),m_line,"Found unknown token %s while parsing %s",s,m_tokenStream);
m_curToken.id = s;
p++;
}
......@@ -1472,51 +1515,14 @@ class ExpressionParser
return TRUE;
}
const TemplateParser *m_parser;
ExprToken m_curToken;
QCString m_templateName;
int m_line;
const char *m_tokenStream;
};
//----------------------------------------------------------
/** @brief Base class of all nodes in a template's AST */
class TemplateNode
{
public:
TemplateNode(TemplateNode *parent) : m_parent(parent) {}
virtual ~TemplateNode() {}
virtual void render(FTextStream &ts, TemplateContext *c) = 0;
TemplateNode *parent() { return m_parent; }
private:
TemplateNode *m_parent;
};
//----------------------------------------------------------
/** @brief Parser for templates */
class TemplateParser
{
public:
TemplateParser(const QCString &templateName,QList<TemplateToken> &tokens);
void parse(TemplateNode *parent,int line,const QStrList &stopAt,
QList<TemplateNode> &nodes);
bool hasNextToken() const;
TemplateToken *takeNextToken();
void removeNextToken();
void prependToken(const TemplateToken *token);
const TemplateToken *currentToken() const;
QCString templateName() const { return m_templateName; }
private:
QCString m_templateName;
QList<TemplateToken> &m_tokens;
};
//----------------------------------------------------------
/** @brief Class representing a lexical token in a template */
class TemplateToken
{
......@@ -1558,24 +1564,23 @@ class TemplateImpl : public TemplateNode, public Template
{
public:
TemplateImpl(TemplateEngine *e,const QCString &name,const QCString &data);
~TemplateImpl() {}
void render(FTextStream &ts, TemplateContext *c);
TemplateEngine *engine() const { return m_engine; }
TemplateBlockContext *blockContext() { return &m_blockContext; }
private:
TemplateEngine *m_engine;
QCString m_name;
TemplateNodeList m_nodes;
TemplateEngine *m_engine;
TemplateBlockContext m_blockContext;
};
//----------------------------------------------------------
TemplateContextImpl::TemplateContextImpl()
: m_templateName("<unknown>"), m_line(1), m_escapeIntf(0),
TemplateContextImpl::TemplateContextImpl(const TemplateEngine *e)
: m_engine(e), m_templateName("<unknown>"), m_line(1), m_escapeIntf(0),
m_spacelessIntf(0), m_spacelessEnabled(FALSE)
{
m_contextStack.setAutoDelete(TRUE);
......@@ -1704,6 +1709,15 @@ TemplateBlockContext *TemplateContextImpl::blockContext()
return &m_blockContext;
}
void TemplateContextImpl::warn(const char *fileName,int line,const char *fmt,...) const
{
va_list args;
va_start(args,fmt);
::warn(fileName,line,fmt,args);
va_end(args);
m_engine->printIncludeContext(fileName,line);
}
//----------------------------------------------------------
/** @brief Class representing a piece of plain text in a template */
......@@ -1743,7 +1757,7 @@ class TemplateNodeVariable : public TemplateNode
: TemplateNode(parent), m_templateName(parser->templateName()), m_line(line)
{
TRACE(("TemplateNodeVariable(%s)\n",var.data()));
ExpressionParser expParser(m_templateName,line);
ExpressionParser expParser(parser,line);
m_var = expParser.parseVariable(var);
}
~TemplateNodeVariable()
......@@ -1821,14 +1835,14 @@ class TemplateNodeIf : public TemplateNodeCreator<TemplateNodeIf>
TRACE(("{TemplateNodeIf(%s)\n",data.data()));
if (data.isEmpty())
{
warn(m_templateName,line,"missing argument for if tag");
parser->warn(m_templateName,line,"missing argument for if tag");
}
QStrList stopAt;
stopAt.append("endif");
stopAt.append("else");
parser->parse(this,line,stopAt,m_trueNodes);
TemplateToken *tok = parser->takeNextToken();
ExpressionParser ex(parser->templateName(),line);
ExpressionParser ex(parser,line);
m_guardAst = ex.parse(data);
if (tok && tok->data=="else")
......@@ -1847,7 +1861,8 @@ class TemplateNodeIf : public TemplateNodeCreator<TemplateNodeIf>
void render(FTextStream &ts, TemplateContext *c)
{
dynamic_cast<TemplateContextImpl*>(c)->setLocation(m_templateName,m_line);
TemplateContextImpl* ci = dynamic_cast<TemplateContextImpl*>(c);
ci->setLocation(m_templateName,m_line);
//printf("TemplateNodeIf::render #trueNodes=%d #falseNodes=%d\n",m_trueNodes.count(),m_falseNodes.count());
if (m_guardAst)
{
......@@ -1877,7 +1892,7 @@ class TemplateNodeRepeat : public TemplateNodeCreator<TemplateNodeRepeat>
: TemplateNodeCreator<TemplateNodeRepeat>(parser,parent,line)
{
TRACE(("{TemplateNodeRepeat(%s)\n",data.data()));
ExpressionParser expParser(parser->templateName(),line);
ExpressionParser expParser(parser,line);
m_expr = expParser.parseVariable(data);
QStrList stopAt;
stopAt.append("endrepeat");
......@@ -1891,7 +1906,8 @@ class TemplateNodeRepeat : public TemplateNodeCreator<TemplateNodeRepeat>
}
void render(FTextStream &ts, TemplateContext *c)
{
dynamic_cast<TemplateContextImpl*>(c)->setLocation(m_templateName,m_line);
TemplateContextImpl* ci = dynamic_cast<TemplateContextImpl*>(c);
ci->setLocation(m_templateName,m_line);
TemplateVariant v;
if (m_expr && (v=m_expr->resolve(c)).type()==TemplateVariant::Integer)
{
......@@ -1912,7 +1928,7 @@ class TemplateNodeRepeat : public TemplateNodeCreator<TemplateNodeRepeat>
}
else // simple type...
{
warn(m_templateName,m_line,"for requires a variable of list type!");
ci->warn(m_templateName,m_line,"for requires a variable of list type!");
}
}
private:
......@@ -1936,15 +1952,15 @@ class TemplateNodeFor : public TemplateNodeCreator<TemplateNodeFor>
{
if (data.right(3)==" in")
{
warn(m_templateName,line,"for is missing container after 'in' keyword");
parser->warn(m_templateName,line,"for is missing container after 'in' keyword");
}
else if (data=="in")
{
warn(m_templateName,line,"for needs at least one iterator variable");
parser->warn(m_templateName,line,"for needs at least one iterator variable");
}
else
{
warn(m_templateName,line,"for is missing 'in' keyword");
parser->warn(m_templateName,line,"for is missing 'in' keyword");
}
}
else
......@@ -1952,7 +1968,7 @@ class TemplateNodeFor : public TemplateNodeCreator<TemplateNodeFor>
m_vars = split(data.left(i),",");
if (m_vars.count()==0)
{
warn(m_templateName,line,"for needs at least one iterator variable");
parser->warn(m_templateName,line,"for needs at least one iterator variable");
}
int j = data.find(" reversed",i);
......@@ -1965,10 +1981,10 @@ class TemplateNodeFor : public TemplateNodeCreator<TemplateNodeFor>
}
if (exprStr.isEmpty())
{
warn(m_templateName,line,"for is missing container after 'in' keyword");
parser->warn(m_templateName,line,"for is missing container after 'in' keyword");
}
}
ExpressionParser expParser(parser->templateName(),line);
ExpressionParser expParser(parser,line);
m_expr = expParser.parseVariable(exprStr);
QStrList stopAt;
......@@ -1993,7 +2009,8 @@ class TemplateNodeFor : public TemplateNodeCreator<TemplateNodeFor>
void render(FTextStream &ts, TemplateContext *c)
{
dynamic_cast<TemplateContextImpl*>(c)->setLocation(m_templateName,m_line);
TemplateContextImpl* ci = dynamic_cast<TemplateContextImpl*>(c);
ci->setLocation(m_templateName,m_line);
//printf("TemplateNodeFor::render #loopNodes=%d #emptyNodes=%d\n",
// m_loopNodes.count(),m_emptyNodes.count());
if (m_expr)
......@@ -2058,7 +2075,7 @@ class TemplateNodeFor : public TemplateNodeCreator<TemplateNodeFor>
}
else // simple type...
{
warn(m_templateName,m_line,"for requires a variable of list type!");
ci->warn(m_templateName,m_line,"for requires a variable of list type!");
}
}
}
......@@ -2090,6 +2107,7 @@ class TemplateNodeMsg : public TemplateNodeCreator<TemplateNodeMsg>
void render(FTextStream &, TemplateContext *c)
{
TemplateContextImpl* ci = dynamic_cast<TemplateContextImpl*>(c);
ci->setLocation(m_templateName,m_line);
TemplateEscapeIntf *escIntf = ci->escapeIntf();
ci->setEscapeIntf(0); // avoid escaping things we send to standard out
bool enable = ci->spacelessEnabled();
......@@ -2118,7 +2136,7 @@ class TemplateNodeBlock : public TemplateNodeCreator<TemplateNodeBlock>
m_blockName = data;
if (m_blockName.isEmpty())
{
warn(parser->templateName(),line,"block tag without name");
parser->warn(parser->templateName(),line,"block tag without name");
}
QStrList stopAt;
stopAt.append("endblock");
......@@ -2156,14 +2174,18 @@ class TemplateNodeBlock : public TemplateNodeCreator<TemplateNodeBlock>
superBlock.set("super",TemplateVariant(super.data(),TRUE));
ci->set("block",&superBlock);
// render the overruled block contents
t->engine()->enterBlock(nb->m_templateName,nb->m_blockName,nb->m_line);
nb->m_nodes.render(ts,c);
t->engine()->leaveBlock();
ci->pop();
// re-add block to the context
ci->blockContext()->push(nb);
}
else // block has no overrule
{
t->engine()->enterBlock(m_templateName,m_blockName,m_line);
m_nodes.render(ts,c);
t->engine()->leaveBlock();
}
}
}
......@@ -2188,10 +2210,10 @@ class TemplateNodeExtend : public TemplateNodeCreator<TemplateNodeExtend>
: TemplateNodeCreator<TemplateNodeExtend>(parser,parent,line)
{
TRACE(("{TemplateNodeExtend(%s)\n",data.data()));
ExpressionParser ep(m_templateName,line);
ExpressionParser ep(parser,line);
if (data.isEmpty())
{
warn(m_templateName,line,"extend tag is missing template file argument");
parser->warn(m_templateName,line,"extend tag is missing template file argument");
}
m_extendExpr = ep.parsePrimary(data);
QStrList stopAt;
......@@ -2205,20 +2227,21 @@ class TemplateNodeExtend : public TemplateNodeCreator<TemplateNodeExtend>
void render(FTextStream &ts, TemplateContext *c)
{
dynamic_cast<TemplateContextImpl*>(c)->setLocation(m_templateName,m_line);
TemplateContextImpl* ci = dynamic_cast<TemplateContextImpl*>(c);
ci->setLocation(m_templateName,m_line);
if (m_extendExpr==0) return;
QCString extendFile = m_extendExpr->resolve(c).toString();
if (extendFile.isEmpty())
{
warn(m_templateName,m_line,"invalid parameter for extend command");
ci->warn(m_templateName,m_line,"invalid parameter for extend command");
}
// goto root of tree (template node)
TemplateImpl *t = getTemplate();
if (t)
{
Template *bt = t->engine()->loadByName(extendFile);
Template *bt = t->engine()->loadByName(extendFile,m_line);
TemplateImpl *baseTemplate = bt ? dynamic_cast<TemplateImpl*>(bt) : 0;
if (baseTemplate)
{
......@@ -2248,11 +2271,11 @@ class TemplateNodeExtend : public TemplateNodeCreator<TemplateNodeExtend>
// clean up
bc->clear();
//delete baseTemplate;
t->engine()->unload(t);
}
else
{
warn(m_templateName,m_line,"failed to load template %s for extend",extendFile.data());
ci->warn(m_templateName,m_line,"failed to load template %s for extend",extendFile.data());
}
}
}
......@@ -2270,10 +2293,10 @@ class TemplateNodeInclude : public TemplateNodeCreator<TemplateNodeInclude>
: TemplateNodeCreator<TemplateNodeInclude>(parser,parent,line)
{
TRACE(("TemplateNodeInclude(%s)\n",data.data()));
ExpressionParser ep(m_templateName,line);
ExpressionParser ep(parser,line);
if (data.isEmpty())
{
warn(m_templateName,line,"include tag is missing template file argument");
parser->warn(m_templateName,line,"include tag is missing template file argument");
}
m_includeExpr = ep.parsePrimary(data);
}
......@@ -2283,28 +2306,30 @@ class TemplateNodeInclude : public TemplateNodeCreator<TemplateNodeInclude>
}
void render(FTextStream &ts, TemplateContext *c)
{
dynamic_cast<TemplateContextImpl*>(c)->setLocation(m_templateName,m_line);
TemplateContextImpl* ci = dynamic_cast<TemplateContextImpl*>(c);
ci->setLocation(m_templateName,m_line);
if (m_includeExpr)
{
QCString includeFile = m_includeExpr->resolve(c).toString();
if (includeFile.isEmpty())
{
warn(m_templateName,m_line,"invalid parameter for include command\n");
ci->warn(m_templateName,m_line,"invalid parameter for include command\n");
}
else
{
TemplateImpl *t = getTemplate();
if (t)
{
Template *it = t->engine()->loadByName(includeFile);
Template *it = t->engine()->loadByName(includeFile,m_line);
TemplateImpl *incTemplate = it ? dynamic_cast<TemplateImpl*>(it) : 0;
if (incTemplate)
{
incTemplate->render(ts,c);
t->engine()->unload(t);
}
else
{
warn(m_templateName,m_line,"failed to load template '%s' for include",includeFile.data()?includeFile.data():"");
ci->warn(m_templateName,m_line,"failed to load template '%s' for include",includeFile.data()?includeFile.data():"");
}
}
}
......@@ -2325,30 +2350,30 @@ class TemplateNodeCreate : public TemplateNodeCreator<TemplateNodeCreate>
: TemplateNodeCreator<TemplateNodeCreate>(parser,parent,line)
{
TRACE(("TemplateNodeCreate(%s)\n",data.data()));
ExpressionParser ep(m_templateName,line);
ExpressionParser ep(parser,line);
if (data.isEmpty())
{
warn(m_templateName,line,"create tag is missing arguments");
parser->warn(m_templateName,line,"create tag is missing arguments");
}
int i = data.find(" from ");
if (i==-1)
{
if (data.right(3)==" from")
{
warn(m_templateName,line,"create is missing template name after 'from' keyword");
parser->warn(m_templateName,line,"create is missing template name after 'from' keyword");
}
else if (data=="from")
{
warn(m_templateName,line,"create needs a file name and a template name");
parser->warn(m_templateName,line,"create needs a file name and a template name");
}
else
{
warn(m_templateName,line,"create is missing 'from' keyword");
parser->warn(m_templateName,line,"create is missing 'from' keyword");
}
}
else
{
ExpressionParser ep(m_templateName,line);
ExpressionParser ep(parser,line);
m_fileExpr = ep.parsePrimary(data.left(i).stripWhiteSpace());
m_templateExpr = ep.parsePrimary(data.mid(i+6).stripWhiteSpace());
}
......@@ -2368,18 +2393,18 @@ class TemplateNodeCreate : public TemplateNodeCreator<TemplateNodeCreate>
QCString outputFile = m_fileExpr->resolve(c).toString();
if (templateFile.isEmpty())
{
warn(m_templateName,m_line,"empty template name parameter for create command\n");
ci->warn(m_templateName,m_line,"empty template name parameter for create command\n");
}
else if (outputFile.isEmpty())
{
warn(m_templateName,m_line,"empty file name parameter for create command\n");
ci->warn(m_templateName,m_line,"empty file name parameter for create command\n");
}
else
{
TemplateImpl *t = getTemplate();
if (t)
{
Template *ct = t->engine()->loadByName(templateFile);
Template *ct = t->engine()->loadByName(templateFile,m_line);
TemplateImpl *createTemplate = ct ? dynamic_cast<TemplateImpl*>(ct) : 0;
if (createTemplate)
{
......@@ -2392,16 +2417,16 @@ class TemplateNodeCreate : public TemplateNodeCreator<TemplateNodeCreate>
{
FTextStream ts(&f);
createTemplate->render(ts,c);
//delete createTemplate;
t->engine()->unload(t);
}
else
{
warn(m_templateName,m_line,"failed to open output file '%s' for create command",outputFile.data());
ci->warn(m_templateName,m_line,"failed to open output file '%s' for create command",outputFile.data());
}
}
else
{
warn(m_templateName,m_line,"failed to load template '%s' for include",templateFile.data());
ci->warn(m_templateName,m_line,"failed to load template '%s' for include",templateFile.data());
}
}
}
......@@ -2431,10 +2456,10 @@ class TemplateNodeTree : public TemplateNodeCreator<TemplateNodeTree>
: TemplateNodeCreator<TemplateNodeTree>(parser,parent,line)
{
TRACE(("{TemplateNodeTree(%s)\n",data.data()));
ExpressionParser ep(m_templateName,line);
ExpressionParser ep(parser,line);
if (data.isEmpty())
{
warn(m_templateName,line,"recursetree tag is missing data argument");
parser->warn(m_templateName,line,"recursetree tag is missing data argument");
}
m_treeExpr = ep.parsePrimary(data);
QStrList stopAt;
......@@ -2508,7 +2533,7 @@ class TemplateNodeTree : public TemplateNodeCreator<TemplateNodeTree>
}
else
{
warn(m_templateName,m_line,"recursetree's argument should be a list type");
ci->warn(m_templateName,m_line,"recursetree's argument should be a list type");
}
}
......@@ -2535,7 +2560,7 @@ class TemplateNodeWith : public TemplateNodeCreator<TemplateNodeWith>
{
TRACE(("{TemplateNodeWith(%s)\n",data.data()));
m_args.setAutoDelete(TRUE);
ExpressionParser expParser(parser->templateName(),line);
ExpressionParser expParser(parser,line);
QValueList<QCString> args = split(data," ");
QValueListIterator<QCString> it = args.begin();
while (it!=args.end())
......@@ -2552,7 +2577,7 @@ class TemplateNodeWith : public TemplateNodeCreator<TemplateNodeWith>
}
else
{
warn(parser->templateName(),line,"invalid argument '%s' for with tag",arg.data());
parser->warn(parser->templateName(),line,"invalid argument '%s' for with tag",arg.data());
}
++it;
}
......@@ -2568,6 +2593,7 @@ class TemplateNodeWith : public TemplateNodeCreator<TemplateNodeWith>
void render(FTextStream &ts, TemplateContext *c)
{
TemplateContextImpl *ci = dynamic_cast<TemplateContextImpl*>(c);
ci->setLocation(m_templateName,m_line);
c->push();
QListIterator<Mapping> it(m_args);
Mapping *mapping;
......@@ -2596,7 +2622,7 @@ class TemplateNodeCycle : public TemplateNodeCreator<TemplateNodeCycle>
TRACE(("{TemplateNodeCycle(%s)\n",data.data()));
m_args.setAutoDelete(TRUE);
m_index=0;
ExpressionParser expParser(parser->templateName(),line);
ExpressionParser expParser(parser,line);
QValueList<QCString> args = split(data," ");
QValueListIterator<QCString> it = args.begin();
while (it!=args.end())
......@@ -2610,13 +2636,14 @@ class TemplateNodeCycle : public TemplateNodeCreator<TemplateNodeCycle>
}
if (m_args.count()<2)
{
warn(parser->templateName(),line,"expected at least two arguments for cycle command, got %d",m_args.count());
parser->warn(parser->templateName(),line,"expected at least two arguments for cycle command, got %d",m_args.count());
}
TRACE(("}TemplateNodeCycle(%s)\n",data.data()));
}
void render(FTextStream &ts, TemplateContext *c)
{
TemplateContextImpl *ci = dynamic_cast<TemplateContextImpl*>(c);
ci->setLocation(m_templateName,m_line);
if (m_index<m_args.count())
{
TemplateVariant v = m_args.at(m_index)->resolve(c);
......@@ -2661,7 +2688,7 @@ class TemplateNodeSet : public TemplateNodeCreator<TemplateNodeSet>
{
TRACE(("{TemplateNodeSet(%s)\n",data.data()));
m_args.setAutoDelete(TRUE);
ExpressionParser expParser(parser->templateName(),line);
ExpressionParser expParser(parser,line);
QValueList<QCString> args = split(data," ");
QValueListIterator<QCString> it = args.begin();
while (it!=args.end())
......@@ -2678,7 +2705,7 @@ class TemplateNodeSet : public TemplateNodeCreator<TemplateNodeSet>
}
else
{
warn(parser->templateName(),line,"invalid argument '%s' for with tag",arg.data());
parser->warn(parser->templateName(),line,"invalid argument '%s' for with tag",arg.data());
}
++it;
}
......@@ -2687,6 +2714,7 @@ class TemplateNodeSet : public TemplateNodeCreator<TemplateNodeSet>
void render(FTextStream &, TemplateContext *c)
{
TemplateContextImpl *ci = dynamic_cast<TemplateContextImpl*>(c);
ci->setLocation(m_templateName,m_line);
QListIterator<Mapping> it(m_args);
Mapping *mapping;
for (it.toFirst();(mapping=it.current());++it)
......@@ -2718,6 +2746,7 @@ class TemplateNodeSpaceless : public TemplateNodeCreator<TemplateNodeSpaceless>
void render(FTextStream &ts, TemplateContext *c)
{
TemplateContextImpl *ci = dynamic_cast<TemplateContextImpl*>(c);
ci->setLocation(m_templateName,m_line);
bool wasSpaceless = ci->spacelessEnabled();
ci->enableSpaceless(TRUE);
m_nodes.render(ts,c);
......@@ -2741,11 +2770,11 @@ class TemplateNodeMarkers : public TemplateNodeCreator<TemplateNodeMarkers>
int w = data.find(" with ");
if (i==-1 || w==-1 || w<i)
{
warn(m_templateName,line,"markers tag as wrong format. Expected: markers <var> in <list> with <string_with_markers>");
parser->warn(m_templateName,line,"markers tag as wrong format. Expected: markers <var> in <list> with <string_with_markers>");
}
else
{
ExpressionParser expParser(parser->templateName(),line);
ExpressionParser expParser(parser,line);
m_var = data.left(i);
m_listExpr = expParser.parseVariable(data.mid(i+4,w-i-4));
m_patternExpr = expParser.parseVariable(data.right(data.length()-w-6));
......@@ -2796,11 +2825,11 @@ class TemplateNodeMarkers : public TemplateNodeCreator<TemplateNodeMarkers>
}
else if (!ok)
{
warn(m_templateName,m_line,"markers pattern string has invalid markers '%s'",str.data());
ci->warn(m_templateName,m_line,"markers pattern string has invalid markers '%s'",str.data());
}
else if (i<entryIndex)
{
warn(m_templateName,m_line,"markers list does not an element for marker position %d",i);
ci->warn(m_templateName,m_line,"markers list does not an element for marker position %d",i);
}
index=newIndex+matchLen; // set index just after marker
}
......@@ -2809,12 +2838,12 @@ class TemplateNodeMarkers : public TemplateNodeCreator<TemplateNodeMarkers>
}
else
{
warn(m_templateName,m_line,"markers requires a parameter of string type after 'with'!");
ci->warn(m_templateName,m_line,"markers requires a parameter of string type after 'with'!");
}
}
else
{
warn(m_templateName,m_line,"markers requires a parameter of list type after 'in'!");
ci->warn(m_templateName,m_line,"markers requires a parameter of list type after 'in'!");
}
}
}
......@@ -2970,19 +2999,20 @@ void TemplateBlockContext::push(TemplateNodeBlock *block)
class TemplateLexer
{
public:
TemplateLexer(const QCString &fileName,const QCString &data);
TemplateLexer(const TemplateEngine *engine,const QCString &fileName,const QCString &data);
void tokenize(QList<TemplateToken> &tokens);
private:
void addToken(QList<TemplateToken> &tokens,
const char *data,int line,int startPos,int endPos,
TemplateToken::Type type);
void reset();
const TemplateEngine *m_engine;
QCString m_fileName;
QCString m_data;
};
TemplateLexer::TemplateLexer(const QCString &fileName,const QCString &data) :
m_fileName(fileName), m_data(data)
TemplateLexer::TemplateLexer(const TemplateEngine *engine,const QCString &fileName,const QCString &data) :
m_engine(engine), m_fileName(fileName), m_data(data)
{
}
......@@ -3049,6 +3079,7 @@ void TemplateLexer::tokenize(QList<TemplateToken> &tokens)
if (c=='\n')
{
warn(m_fileName,line,"unexpected new line inside {%%...%%} block");
m_engine->printIncludeContext(m_fileName,line);
}
else if (c=='%') // %} or something else
{
......@@ -3072,6 +3103,7 @@ void TemplateLexer::tokenize(QList<TemplateToken> &tokens)
if (c=='\n')
{
warn(m_fileName,line,"unexpected new line inside {%%...%%} block");
m_engine->printIncludeContext(m_fileName,line);
}
state=StateTag;
}
......@@ -3080,6 +3112,7 @@ void TemplateLexer::tokenize(QList<TemplateToken> &tokens)
if (c=='\n')
{
warn(m_fileName,line,"unexpected new line inside {#...#} block");
m_engine->printIncludeContext(m_fileName,line);
}
else if (c=='#') // #} or something else
{
......@@ -3101,6 +3134,7 @@ void TemplateLexer::tokenize(QList<TemplateToken> &tokens)
if (c=='\n')
{
warn(m_fileName,line,"unexpected new line inside {#...#} block");
m_engine->printIncludeContext(m_fileName,line);
}
state=StateComment;
}
......@@ -3125,6 +3159,7 @@ void TemplateLexer::tokenize(QList<TemplateToken> &tokens)
if (c=='\n')
{
warn(m_fileName,line,"unexpected new line inside {{...}} block");
m_engine->printIncludeContext(m_fileName,line);
}
else if (c=='}') // }} or something else
{
......@@ -3148,6 +3183,7 @@ void TemplateLexer::tokenize(QList<TemplateToken> &tokens)
if (c=='\n')
{
warn(m_fileName,line,"unexpected new line inside {{...}} block");
m_engine->printIncludeContext(m_fileName,line);
}
state=StateVariable;
}
......@@ -3192,9 +3228,10 @@ void TemplateLexer::addToken(QList<TemplateToken> &tokens,
//----------------------------------------------------------
TemplateParser::TemplateParser(const QCString &templateName,
TemplateParser::TemplateParser(const TemplateEngine *engine,
const QCString &templateName,
QList<TemplateToken> &tokens) :
m_templateName(templateName), m_tokens(tokens)
m_engine(engine), m_templateName(templateName), m_tokens(tokens)
{
}
......@@ -3214,10 +3251,10 @@ void TemplateParser::parse(
case TemplateToken::Text:
nodes.append(new TemplateNodeText(this,parent,tok->line,tok->data));
break;
case TemplateToken::Variable:
case TemplateToken::Variable: // {{ var }}
nodes.append(new TemplateNodeVariable(this,parent,tok->line,tok->data));
break;
case TemplateToken::Block:
case TemplateToken::Block: // {% tag %}
{
QCString command = tok->data;
int sep = command.find(' ');
......@@ -3301,6 +3338,15 @@ void TemplateParser::prependToken(const TemplateToken *token)
m_tokens.prepend(token);
}
void TemplateParser::warn(const char *fileName,int line,const char *fmt,...) const
{
va_list args;
va_start(args,fmt);
::warn(fileName,line,fmt,args);
va_end(args);
m_engine->printIncludeContext(fileName,line);
}
//----------------------------------------------------------
......@@ -3311,11 +3357,11 @@ TemplateImpl::TemplateImpl(TemplateEngine *engine,const QCString &name,const QCS
{
m_name = name;
m_engine = engine;
TemplateLexer lexer(name,data);
TemplateLexer lexer(engine,name,data);
QList<TemplateToken> tokens;
tokens.setAutoDelete(TRUE);
lexer.tokenize(tokens);
TemplateParser parser(name,tokens);
TemplateParser parser(engine,name,tokens);
parser.parse(this,1,QStrList(),m_nodes);
}
......@@ -3348,11 +3394,35 @@ void TemplateImpl::render(FTextStream &ts, TemplateContext *c)
/** @brief Private data of the template engine */
class TemplateEngine::Private
{
class IncludeEntry
{
public:
enum Type { Template, Block };
IncludeEntry(Type type,const QCString &fileName,const QCString &blockName,int line)
: m_type(type), m_fileName(fileName), m_blockName(blockName), m_line(line) {}
Type type() const { return m_type; }
QCString fileName() const { return m_fileName; }
QCString blockName() const { return m_blockName; }
int line() const { return m_line; }
private:
Type m_type;
QCString m_fileName;
QCString m_blockName;
int m_line;
};
public:
Private(TemplateEngine *engine) : m_templateCache(17), m_engine(engine)
{ m_templateCache.setAutoDelete(TRUE); }
Template *loadByName(const QCString &fileName) const
Private(TemplateEngine *engine) : m_templateCache(17) /*, m_indent(0)*/, m_engine(engine)
{
m_templateCache.setAutoDelete(TRUE);
m_includeStack.setAutoDelete(TRUE);
}
Template *loadByName(const QCString &fileName,int line)
{
//for (int i=0;i<m_indent;i++) printf(" ");
//m_indent++;
//printf("loadByName(%s,%d) {\n",fileName.data(),line);
m_includeStack.append(new IncludeEntry(IncludeEntry::Template,fileName,QCString(),line));
Template *templ = m_templateCache.find(fileName);
if (templ==0)
{
......@@ -3379,10 +3449,60 @@ class TemplateEngine::Private
}
return templ;
}
void unload(Template * /*t*/)
{
//(void)t;
//m_indent--;
//for (int i=0;i<m_indent;i++) printf(" ");
//printf("}\n");
m_includeStack.removeLast();
}
void enterBlock(const QCString &fileName,const QCString &blockName,int line)
{
//for (int i=0;i<m_indent;i++) printf(" ");
//m_indent++;
//printf("enterBlock(%s,%s,%d) {\n",fileName.data(),blockName.data(),line);
m_includeStack.append(new IncludeEntry(IncludeEntry::Block,fileName,blockName,line));
}
void leaveBlock()
{
//m_indent--;
//for (int i=0;i<m_indent;i++) printf(" ");
//printf("}\n");
m_includeStack.removeLast();
}
void printIncludeContext(const char *fileName,int line) const
{
QListIterator<IncludeEntry> li(m_includeStack);
li.toLast();
IncludeEntry *ie=li.current();
while ((ie=li.current()))
{
--li;
IncludeEntry *next=li.current();
if (ie->type()==IncludeEntry::Template)
{
if (next)
{
warn(fileName,line," inside template '%s' included from template '%s' at line %d",ie->fileName().data(),next->fileName().data(),ie->line());
}
}
else // ie->type()==IncludeEntry::Block
{
warn(fileName,line," included by block '%s' inside template '%s' at line %d",ie->blockName().data(),
ie->fileName().data(),ie->line());
}
}
}
private:
mutable QDict<Template> m_templateCache;
QDict<Template> m_templateCache;
//mutable int m_indent;
TemplateEngine *m_engine;
QList<IncludeEntry> m_includeStack;
};
TemplateEngine::TemplateEngine()
......@@ -3397,11 +3517,31 @@ TemplateEngine::~TemplateEngine()
TemplateContext *TemplateEngine::createContext() const
{
return new TemplateContextImpl;
return new TemplateContextImpl(this);
}
Template *TemplateEngine::loadByName(const QCString &fileName,int line)
{
return p->loadByName(fileName,line);
}
void TemplateEngine::unload(Template *t)
{
p->unload(t);
}
void TemplateEngine::enterBlock(const QCString &fileName,const QCString &blockName,int line)
{
p->enterBlock(fileName,blockName,line);
}
void TemplateEngine::leaveBlock()
{
p->leaveBlock();
}
Template *TemplateEngine::loadByName(const QCString &fileName)
void TemplateEngine::printIncludeContext(const char *fileName,int line) const
{
return p->loadByName(fileName);
p->printIncludeContext(fileName,line);
}
......@@ -10,32 +10,32 @@ class TemplateListIntf;
class TemplateStructIntf;
class TemplateEngine;
/** @defgroup template_api Template API
/** @defgroup template_api Template API
*
* This is the API for a
* <a href="https://docs.djangoproject.com/en/1.6/topics/templates/">Django</a>
* This is the API for a
* <a href="https://docs.djangoproject.com/en/1.6/topics/templates/">Django</a>
* compatible template system written in C++.
* It is somewhat inspired by Stephen Kelly's
* It is somewhat inspired by Stephen Kelly's
* <a href="http://www.gitorious.org/grantlee/pages/Home">Grantlee</a>.
*
* A template is simply a text file.
* A template contains \b variables, which get replaced with values when the
* A template is simply a text file.
* A template contains \b variables, which get replaced with values when the
* template is evaluated, and \b tags, which control the logic of the template.
*
* Variables look like this: `{{ variable }}`
* When the template engine encounters a variable, it evaluates that variable and
* replaces it with the result. Variable names consist of any combination of
* When the template engine encounters a variable, it evaluates that variable and
* replaces it with the result. Variable names consist of any combination of
* alphanumeric characters and the underscore ("_").
* Use a dot (.) to access attributes of a structured variable.
*
*
* One can modify variables for display by using \b filters, for example:
* `{{ value|default:"nothing" }}`
*
* Tags look like this: `{% tag %}`. Tags are more complex than variables:
* Some create text in the output, some control flow by performing loops or logic,
* Tags look like this: `{% tag %}`. Tags are more complex than variables:
* Some create text in the output, some control flow by performing loops or logic,
* and some load external information into the template to be used by later variables.
*
* To comment-out part of a line in a template, use the comment syntax:
* To comment-out part of a line in a template, use the comment syntax:
* `{# comment text #}`.
*
* Supported Django tags:
......@@ -144,13 +144,13 @@ class TemplateVariant
/** Constructs a new variant with a string value \a s. */
TemplateVariant(const QCString &s,bool raw=FALSE);
/** Constructs a new variant with a struct value \a s.
/** Constructs a new variant with a struct value \a s.
* @note. Only a pointer to the struct is stored. The caller
* is responsible to manage the memory for the struct object.
*/
TemplateVariant(const TemplateStructIntf *s);
/** Constructs a new variant with a list value \a l.
/** Constructs a new variant with a list value \a l.
* @note. Only a pointer to the struct is stored. The caller
* is responsible to manage the memory for the list object.
*/
......@@ -168,7 +168,7 @@ class TemplateVariant
/** Destroys the Variant object */
~TemplateVariant();
/** Constructs a copy of the variant, \a v,
/** Constructs a copy of the variant, \a v,
* passed as the argument to this constructor.
*/
TemplateVariant(const TemplateVariant &v);
......@@ -176,7 +176,7 @@ class TemplateVariant
/** Assigns the value of the variant \a v to this variant. */
TemplateVariant &operator=(const TemplateVariant &v);
/** Compares this QVariant with v and returns true if they are equal;
/** Compares this QVariant with v and returns true if they are equal;
* otherwise returns false.
*/
bool operator==(TemplateVariant &other);
......@@ -190,13 +190,13 @@ class TemplateVariant
/** Returns the variant as an integer. */
int toInt() const;
/** Returns the pointer to list referenced by this variant
* or 0 if this variant does not have list type.
/** Returns the pointer to list referenced by this variant
* or 0 if this variant does not have list type.
*/
const TemplateListIntf *toList() const;
/** Returns the pointer to struct referenced by this variant
* or 0 if this variant does not have struct type.
/** Returns the pointer to struct referenced by this variant
* or 0 if this variant does not have struct type.
*/
const TemplateStructIntf *toStruct() const;
......@@ -205,7 +205,7 @@ class TemplateVariant
*/
TemplateVariant call(const QValueList<TemplateVariant> &args);
/** Sets whether or not the value of the Variant should be
/** Sets whether or not the value of the Variant should be
* escaped or written as-is (raw).
* @param[in] b TRUE means write as-is, FALSE means apply escaping.
*/
......@@ -223,7 +223,7 @@ class TemplateVariant
//------------------------------------------------------------------------
/** @brief Abstract read-only interface for a context value of type list.
/** @brief Abstract read-only interface for a context value of type list.
* @note The values of the list are TemplateVariants.
*/
class TemplateListIntf
......@@ -245,7 +245,7 @@ class TemplateListIntf
virtual void toPrev() = 0;
/* Returns TRUE if the iterator points to a valid element
* in the list, or FALSE otherwise.
* If TRUE is returned, the value pointed to be the
* If TRUE is returned, the value pointed to be the
* iterator is assigned to \a v.
*/
virtual bool current(TemplateVariant &v) const = 0;
......@@ -260,7 +260,7 @@ class TemplateListIntf
/** Returns the element at index position \a index. */
virtual TemplateVariant at(int index) const = 0;
/** Creates a new iterator for this list.
/** Creates a new iterator for this list.
* @note the user should call delete on the returned pointer.
*/
virtual TemplateListIntf::ConstIterator *createIterator() const = 0;
......@@ -279,7 +279,7 @@ class TemplateList : public TemplateListIntf
virtual int count() const;
virtual TemplateVariant at(int index) const;
virtual TemplateListIntf::ConstIterator *createIterator() const;
/** Appends element \a v to the end of the list */
virtual void append(const TemplateVariant &v);
......@@ -350,8 +350,8 @@ class TemplateSpacelessIntf
//------------------------------------------------------------------------
/** @brief Abstract interface for a template context.
*
/** @brief Abstract interface for a template context.
*
* A Context consists of a stack of dictionaries.
* A dictionary consists of a mapping of string keys onto TemplateVariant values.
* A key is searched starting with the dictionary at the top of the stack
......@@ -370,10 +370,10 @@ class TemplateContext
/** Pop the current scope from the stack. */
virtual void pop() = 0;
/** Sets a value in the current scope.
/** Sets a value in the current scope.
* @param[in] name The name of the value; the key in the dictionary.
* @param[in] v The value associated with the key.
* @note When a given key is already present,
* @note When a given key is already present,
* its value will be replaced by \a v
*/
virtual void set(const char *name,const TemplateVariant &v) = 0;
......@@ -409,8 +409,8 @@ class TemplateContext
//------------------------------------------------------------------------
/** @brief Abstract interface for a template.
* @note Must be created by TemplateEngine
/** @brief Abstract interface for a template.
* @note Must be created and is deleted by the TemplateEngine
*/
class Template
{
......@@ -418,7 +418,7 @@ class Template
/** Destructor */
virtual ~Template() {}
/** Renders a template instance to a stream.
/** Renders a template instance to a stream.
* @param[in] ts The text stream to write the results to.
* @param[in] c The context containing data that can be used
* when instantiating the template.
......@@ -444,13 +444,25 @@ class TemplateEngine
TemplateContext *createContext() const;
/** Creates a new template whole contents are in a file.
* @param[in] fileName The name of the file containing the
* @param[in] fileName The name of the file containing the
* template data
* @param[in] fromLine The line number of the statement that triggered the load
* @return the new template, the caller will be the owner.
*/
Template *loadByName(const QCString &fileName);
Template *loadByName(const QCString &fileName,int fromLine);
/** Indicates that template \a t is no longer needed. The engine
* may decide to delete it.
*/
void unload(Template *t);
void printIncludeContext(const char *fileName,int line) const;
private:
friend class TemplateNodeBlock;
void enterBlock(const QCString &fileName,const QCString &blockName,int line);
void leaveBlock();
class Private;
Private *p;
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment