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) ...@@ -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) void ClassDef::writeDeclarationLink(OutputList &ol,bool &found,const char *header,bool localNames)
{ {
//static bool fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN"); //static bool fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN");
//static bool vhdlOpt = Config_getBool("OPTIMIZE_OUTPUT_VHDL"); //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(); SrcLangExt lang = getLanguage();
if (isLink || if (visibleInParentsDeclList())
(!hideUndocClasses &&
(!isLocal() || extractLocalClasses)
)
)
{ {
if (!found) // first class if (!found) // first class
{ {
...@@ -1820,7 +1824,7 @@ void ClassDef::writeDeclarationLink(OutputList &ol,bool &found,const char *heade ...@@ -1820,7 +1824,7 @@ void ClassDef::writeDeclarationLink(OutputList &ol,bool &found,const char *heade
ol.writeString(" "); ol.writeString(" ");
ol.insertMemberAlign(); ol.insertMemberAlign();
} }
if (isLink) if (isLinkable())
{ {
ol.writeObjectLink(getReference(), ol.writeObjectLink(getReference(),
getOutputFileBase(), getOutputFileBase(),
......
...@@ -168,6 +168,9 @@ class ClassDef : public Definition ...@@ -168,6 +168,9 @@ class ClassDef : public Definition
/** the class is visible in a class diagram, or class hierarchy */ /** the class is visible in a class diagram, or class hierarchy */
bool isVisibleInHierarchy(); bool isVisibleInHierarchy();
/** show this class in the declaration section of its parent? */
bool visibleInParentsDeclList() const;
/** Returns the template arguments of this class /** Returns the template arguments of this class
* Will return 0 if not applicable. * Will return 0 if not applicable.
*/ */
...@@ -310,14 +313,13 @@ class ClassDef : public Definition ...@@ -310,14 +313,13 @@ class ClassDef : public Definition
QCString generatedFromFiles() const; QCString generatedFromFiles() const;
const FileList &usedFiles() const; const FileList &usedFiles() const;
QCString includeStatement() const;
const ArgumentList *typeConstraints() const; const ArgumentList *typeConstraints() const;
const ExampleSDict *exampleList() const; const ExampleSDict *exampleList() const;
bool hasExamples() const; bool hasExamples() const;
QCString getMemberListFileName() const; QCString getMemberListFileName() const;
bool subGrouping() const; bool subGrouping() const;
//----------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------
// --- setters ---- // --- setters ----
//----------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------
...@@ -432,6 +434,8 @@ class ClassDef : public Definition ...@@ -432,6 +434,8 @@ class ClassDef : public Definition
QPtrDict<void> *visitedClasses); QPtrDict<void> *visitedClasses);
void getTitleForMemberListType(MemberListType type, void getTitleForMemberListType(MemberListType type,
QCString &title,QCString &subtitle); QCString &title,QCString &subtitle);
QCString includeStatement() const;
ClassDefImpl *m_impl; ClassDefImpl *m_impl;
......
...@@ -27,6 +27,8 @@ ...@@ -27,6 +27,8 @@
// TODO: pass the current file to Dot*::writeGraph, so the user can put dot graphs in other // TODO: pass the current file to Dot*::writeGraph, so the user can put dot graphs in other
// files as well // files as well
#define ADD_PROPERTY(name) addProperty(#name,this,&Private::name);
struct ContextGlobals struct ContextGlobals
{ {
enum OutputFormat enum OutputFormat
...@@ -453,6 +455,18 @@ class TranslateContext::Private : public PropertyMapper ...@@ -453,6 +455,18 @@ class TranslateContext::Private : public PropertyMapper
} }
return TemplateVariant(); 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 ...@@ -483,6 +497,8 @@ class TranslateContext::Private : public PropertyMapper
TemplateVariant classes() const TemplateVariant classes() const
{ {
return theTranslator->trClasses(); return theTranslator->trClasses();
// TODO: VHDL: trVhdlType(VhdlDocGen::ENTITY,FALSE)
// TODO: Fortran: trDataTypes()
} }
TemplateVariant classList() const TemplateVariant classList() const
{ {
...@@ -669,6 +685,34 @@ class TranslateContext::Private : public PropertyMapper ...@@ -669,6 +685,34 @@ class TranslateContext::Private : public PropertyMapper
{ {
return theTranslator->trAdditionalInheritedMembers(); 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() Private()
{ {
//%% string generatedBy //%% string generatedBy
...@@ -761,6 +805,20 @@ class TranslateContext::Private : public PropertyMapper ...@@ -761,6 +805,20 @@ class TranslateContext::Private : public PropertyMapper
addProperty("inheritedFrom", this,&Private::inheritedFrom); addProperty("inheritedFrom", this,&Private::inheritedFrom);
//%% string addtionalInheritedMembers //%% string addtionalInheritedMembers
addProperty("additionalInheritedMembers",this,&Private::additionalInheritedMembers); 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_javaOpt = Config_getBool("OPTIMIZE_OUTPUT_JAVA");
m_fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN"); m_fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN");
...@@ -823,6 +881,31 @@ static TemplateVariant parseCode(MemberDef *md,const QCString &scopeName,const Q ...@@ -823,6 +881,31 @@ static TemplateVariant parseCode(MemberDef *md,const QCString &scopeName,const Q
return TemplateVariant(s.data(),TRUE); 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 //%% struct Symbol: shared info for all symbols
...@@ -1027,7 +1110,10 @@ class DefinitionContext : public PropertyMapper ...@@ -1027,7 +1110,10 @@ class DefinitionContext : public PropertyMapper
if (!m_cache.navPath) if (!m_cache.navPath)
{ {
TemplateList *list = new TemplateList; 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); m_cache.navPath.reset(list);
} }
return m_cache.navPath.get(); return m_cache.navPath.get();
...@@ -1058,7 +1144,7 @@ class DefinitionContext : public PropertyMapper ...@@ -1058,7 +1144,7 @@ class DefinitionContext : public PropertyMapper
class IncludeInfoContext::Private : public PropertyMapper class IncludeInfoContext::Private : public PropertyMapper
{ {
public: public:
Private(IncludeInfo *info,SrcLangExt lang) : Private(const IncludeInfo *info,SrcLangExt lang) :
m_info(info), m_info(info),
m_fileContext(info && info->fileDef ? info->fileDef : 0), m_fileContext(info && info->fileDef ? info->fileDef : 0),
m_lang(lang) m_lang(lang)
...@@ -1096,12 +1182,12 @@ class IncludeInfoContext::Private : public PropertyMapper ...@@ -1096,12 +1182,12 @@ class IncludeInfoContext::Private : public PropertyMapper
return m_info->includeName; return m_info->includeName;
} }
private: private:
IncludeInfo *m_info; const IncludeInfo *m_info;
FileContext m_fileContext; FileContext m_fileContext;
SrcLangExt m_lang; SrcLangExt m_lang;
}; };
IncludeInfoContext::IncludeInfoContext(IncludeInfo *info,SrcLangExt lang) IncludeInfoContext::IncludeInfoContext(const IncludeInfo *info,SrcLangExt lang)
{ {
p = new Private(info,lang); p = new Private(info,lang);
} }
...@@ -1119,14 +1205,59 @@ TemplateVariant IncludeInfoContext::get(const char *n) const ...@@ -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 //%% struct Class(Symbol): class information
//%% { //%% {
class ClassContext::Private : public DefinitionContext<ClassContext::Private> class ClassContext::Private : public DefinitionContext<ClassContext::Private>
{ {
public: public:
Private(ClassDef *cd) : DefinitionContext<ClassContext::Private>(cd) , Private(ClassDef *cd) : DefinitionContext<ClassContext::Private>(cd),
m_classDef(cd), m_usedFiles(cd), m_classDef(cd), m_usedFiles(cd)
m_includeInfo(cd ? cd->includeInfo() : 0, cd ? cd->getLanguage() : SrcLangExt_Unknown)
{ {
addProperty("title", this,&Private::title); addProperty("title", this,&Private::title);
addProperty("highlight", this,&Private::highlight); addProperty("highlight", this,&Private::highlight);
...@@ -1139,7 +1270,6 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private> ...@@ -1139,7 +1270,6 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private>
addProperty("hasCollaborationDiagram", this,&Private::hasCollaborationDiagram); addProperty("hasCollaborationDiagram", this,&Private::hasCollaborationDiagram);
addProperty("collaborationDiagram", this,&Private::collaborationDiagram); addProperty("collaborationDiagram", this,&Private::collaborationDiagram);
addProperty("includeInfo", this,&Private::includeInfo); addProperty("includeInfo", this,&Private::includeInfo);
addProperty("includeStatement", this,&Private::includeStatement);
addProperty("inherits", this,&Private::inherits); addProperty("inherits", this,&Private::inherits);
addProperty("inheritedBy", this,&Private::inheritedBy); addProperty("inheritedBy", this,&Private::inheritedBy);
addProperty("unoIDLServices", this,&Private::unoIDLServices); addProperty("unoIDLServices", this,&Private::unoIDLServices);
...@@ -1182,7 +1312,7 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private> ...@@ -1182,7 +1312,7 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private>
addProperty("detailedVariables", this,&Private::detailedVariables); addProperty("detailedVariables", this,&Private::detailedVariables);
addProperty("detailedProperties", this,&Private::detailedProperties); addProperty("detailedProperties", this,&Private::detailedProperties);
addProperty("detailedEvents", this,&Private::detailedEvents); addProperty("detailedEvents", this,&Private::detailedEvents);
addProperty("nestedClasses", this,&Private::nestedClasses); addProperty("classes", this,&Private::classes);
addProperty("compoundType", this,&Private::compoundType); addProperty("compoundType", this,&Private::compoundType);
addProperty("templateDecls", this,&Private::templateDecls); addProperty("templateDecls", this,&Private::templateDecls);
addProperty("typeConstraints", this,&Private::typeConstraints); addProperty("typeConstraints", this,&Private::typeConstraints);
...@@ -1317,19 +1447,19 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private> ...@@ -1317,19 +1447,19 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private>
TemplateVariant includeInfo() const 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 else
{ {
return TemplateVariant(FALSE); return TemplateVariant(FALSE);
} }
} }
TemplateVariant includeStatement() const
{
return m_classDef->includeStatement();
}
TemplateVariant inherits() const TemplateVariant inherits() const
{ {
if (!m_cache.inheritsList) if (!m_cache.inheritsList)
...@@ -1530,12 +1660,9 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private> ...@@ -1530,12 +1660,9 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private>
{ {
return getMemberList(m_cache.detailedEvents,MemberListType_eventMembers,theTranslator->trEventDocumentation(),TRUE); return getMemberList(m_cache.detailedEvents,MemberListType_eventMembers,theTranslator->trEventDocumentation(),TRUE);
} }
TemplateVariant nestedClasses() const TemplateVariant classes() const
{ {
static bool extractPrivate = Config_getBool("EXTRACT_PRIVATE"); if (!m_cache.classes)
static bool hideUndocClasses = Config_getBool("HIDE_UNDOC_CLASSES");
static bool extractLocalClasses = Config_getBool("EXTRACT_LOCAL_CLASSES");
if (!m_cache.nestedClasses)
{ {
NestedClassListContext *classList = new NestedClassListContext; NestedClassListContext *classList = new NestedClassListContext;
if (m_classDef->getClassSDict()) if (m_classDef->getClassSDict())
...@@ -1544,20 +1671,15 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private> ...@@ -1544,20 +1671,15 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private>
ClassDef *cd; ClassDef *cd;
for (sdi.toFirst();(cd=sdi.current());++sdi) for (sdi.toFirst();(cd=sdi.current());++sdi)
{ {
bool linkable = cd->isLinkable(); if (cd->visibleInParentsDeclList())
if (cd->name().find('@')==-1 && !cd->isExtension() &&
(cd->protection()!=::Private || extractPrivate) &&
(linkable ||
(!hideUndocClasses && (!cd->isLocal() || extractLocalClasses)))
)
{ {
classList->append(cd); 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 TemplateVariant compoundType() const
{ {
...@@ -1764,71 +1886,70 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private> ...@@ -1764,71 +1886,70 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private>
private: private:
ClassDef *m_classDef; ClassDef *m_classDef;
UsedFilesContext m_usedFiles; UsedFilesContext m_usedFiles;
IncludeInfoContext m_includeInfo;
struct Cachable struct Cachable
{ {
Cachable() : inheritanceNodes(-1) Cachable() : inheritanceNodes(-1)
{ {
templateArgList.setAutoDelete(TRUE); templateArgList.setAutoDelete(TRUE);
exampleList.setAutoDelete(TRUE); exampleList.setAutoDelete(TRUE);
allMembers.setAutoDelete(TRUE);
} }
ScopedPtr<IncludeInfoContext> includeInfo;
ScopedPtr<InheritanceListContext> inheritsList; ScopedPtr<InheritanceListContext> inheritsList;
ScopedPtr<InheritanceListContext> inheritedByList; ScopedPtr<InheritanceListContext> inheritedByList;
ScopedPtr<DotClassGraph> classGraph; ScopedPtr<DotClassGraph> classGraph;
ScopedPtr<DotClassGraph> collaborationGraph; ScopedPtr<DotClassGraph> collaborationGraph;
ScopedPtr<NestedClassListContext> nestedClasses; ScopedPtr<NestedClassListContext> classes;
ScopedPtr<MemberListInfoContext> publicTypes; ScopedPtr<MemberListInfoContext> publicTypes;
ScopedPtr<MemberListInfoContext> publicMethods; ScopedPtr<MemberListInfoContext> publicMethods;
ScopedPtr<MemberListInfoContext> publicStaticMethods; ScopedPtr<MemberListInfoContext> publicStaticMethods;
ScopedPtr<MemberListInfoContext> publicAttributes; ScopedPtr<MemberListInfoContext> publicAttributes;
ScopedPtr<MemberListInfoContext> publicStaticAttributes; ScopedPtr<MemberListInfoContext> publicStaticAttributes;
ScopedPtr<MemberListInfoContext> publicSlots; ScopedPtr<MemberListInfoContext> publicSlots;
ScopedPtr<MemberListInfoContext> protectedTypes; ScopedPtr<MemberListInfoContext> protectedTypes;
ScopedPtr<MemberListInfoContext> protectedMethods; ScopedPtr<MemberListInfoContext> protectedMethods;
ScopedPtr<MemberListInfoContext> protectedStaticMethods; ScopedPtr<MemberListInfoContext> protectedStaticMethods;
ScopedPtr<MemberListInfoContext> protectedAttributes; ScopedPtr<MemberListInfoContext> protectedAttributes;
ScopedPtr<MemberListInfoContext> protectedStaticAttributes; ScopedPtr<MemberListInfoContext> protectedStaticAttributes;
ScopedPtr<MemberListInfoContext> protectedSlots; ScopedPtr<MemberListInfoContext> protectedSlots;
ScopedPtr<MemberListInfoContext> privateTypes; ScopedPtr<MemberListInfoContext> privateTypes;
ScopedPtr<MemberListInfoContext> privateMethods; ScopedPtr<MemberListInfoContext> privateMethods;
ScopedPtr<MemberListInfoContext> privateStaticMethods; ScopedPtr<MemberListInfoContext> privateStaticMethods;
ScopedPtr<MemberListInfoContext> privateAttributes; ScopedPtr<MemberListInfoContext> privateAttributes;
ScopedPtr<MemberListInfoContext> privateStaticAttributes; ScopedPtr<MemberListInfoContext> privateStaticAttributes;
ScopedPtr<MemberListInfoContext> privateSlots; ScopedPtr<MemberListInfoContext> privateSlots;
ScopedPtr<MemberListInfoContext> packageTypes; ScopedPtr<MemberListInfoContext> packageTypes;
ScopedPtr<MemberListInfoContext> packageMethods; ScopedPtr<MemberListInfoContext> packageMethods;
ScopedPtr<MemberListInfoContext> packageStaticMethods; ScopedPtr<MemberListInfoContext> packageStaticMethods;
ScopedPtr<MemberListInfoContext> packageAttributes; ScopedPtr<MemberListInfoContext> packageAttributes;
ScopedPtr<MemberListInfoContext> packageStaticAttributes; ScopedPtr<MemberListInfoContext> packageStaticAttributes;
ScopedPtr<MemberListInfoContext> unoIDLServices; ScopedPtr<MemberListInfoContext> unoIDLServices;
ScopedPtr<MemberListInfoContext> unoIDLInterfaces; ScopedPtr<MemberListInfoContext> unoIDLInterfaces;
ScopedPtr<MemberListInfoContext> signals; ScopedPtr<MemberListInfoContext> signals;
ScopedPtr<MemberListInfoContext> properties; ScopedPtr<MemberListInfoContext> properties;
ScopedPtr<MemberListInfoContext> events; ScopedPtr<MemberListInfoContext> events;
ScopedPtr<MemberListInfoContext> friends; ScopedPtr<MemberListInfoContext> friends;
ScopedPtr<MemberListInfoContext> related; ScopedPtr<MemberListInfoContext> related;
ScopedPtr<MemberListInfoContext> detailedTypedefs; ScopedPtr<MemberListInfoContext> detailedTypedefs;
ScopedPtr<MemberListInfoContext> detailedEnums; ScopedPtr<MemberListInfoContext> detailedEnums;
ScopedPtr<MemberListInfoContext> detailedServices; ScopedPtr<MemberListInfoContext> detailedServices;
ScopedPtr<MemberListInfoContext> detailedInterfaces; ScopedPtr<MemberListInfoContext> detailedInterfaces;
ScopedPtr<MemberListInfoContext> detailedConstructors; ScopedPtr<MemberListInfoContext> detailedConstructors;
ScopedPtr<MemberListInfoContext> detailedMethods; ScopedPtr<MemberListInfoContext> detailedMethods;
ScopedPtr<MemberListInfoContext> detailedRelated; ScopedPtr<MemberListInfoContext> detailedRelated;
ScopedPtr<MemberListInfoContext> detailedVariables; ScopedPtr<MemberListInfoContext> detailedVariables;
ScopedPtr<MemberListInfoContext> detailedProperties; ScopedPtr<MemberListInfoContext> detailedProperties;
ScopedPtr<MemberListInfoContext> detailedEvents; ScopedPtr<MemberListInfoContext> detailedEvents;
ScopedPtr<MemberGroupListContext> memberGroups; ScopedPtr<MemberGroupListContext> memberGroups;
ScopedPtr<AllMembersListContext> allMembersList; ScopedPtr<AllMembersListContext> allMembersList;
ScopedPtr<ArgumentListContext> typeConstraints; ScopedPtr<ArgumentListContext> typeConstraints;
ScopedPtr<TemplateList> examples; ScopedPtr<TemplateList> examples;
ScopedPtr<TemplateList> templateDecls; ScopedPtr<TemplateList> templateDecls;
ScopedPtr<InheritedMemberInfoListContext> additionalInheritedMembers; ScopedPtr<InheritedMemberInfoListContext> additionalInheritedMembers;
ScopedPtr<MemberListContext> members; ScopedPtr<MemberListContext> members;
QList<ArgumentListContext> templateArgList; QList<ArgumentListContext> templateArgList;
int inheritanceNodes; int inheritanceNodes;
QList<TemplateStruct> exampleList; QList<TemplateStruct> exampleList;
MemberList allMembers; MemberList allMembers;
}; };
mutable Cachable m_cache; mutable Cachable m_cache;
}; };
...@@ -1862,6 +1983,7 @@ class NamespaceContext::Private : public DefinitionContext<NamespaceContext::Pri ...@@ -1862,6 +1983,7 @@ class NamespaceContext::Private : public DefinitionContext<NamespaceContext::Pri
addProperty("title",this,&Private::title); addProperty("title",this,&Private::title);
addProperty("highlight",this,&Private::highlight); addProperty("highlight",this,&Private::highlight);
addProperty("subhighlight",this,&Private::subHighlight); addProperty("subhighlight",this,&Private::subHighlight);
addProperty("compoundType",this,&Private::compoundType);
} }
TemplateVariant title() const TemplateVariant title() const
{ {
...@@ -1875,6 +1997,10 @@ class NamespaceContext::Private : public DefinitionContext<NamespaceContext::Pri ...@@ -1875,6 +1997,10 @@ class NamespaceContext::Private : public DefinitionContext<NamespaceContext::Pri
{ {
return TemplateVariant(""); return TemplateVariant("");
} }
TemplateVariant compoundType() const
{
return m_namespaceDef->compoundTypeString();
}
private: private:
NamespaceDef *m_namespaceDef; NamespaceDef *m_namespaceDef;
}; };
...@@ -1904,10 +2030,34 @@ class FileContext::Private : public DefinitionContext<FileContext::Private> ...@@ -1904,10 +2030,34 @@ class FileContext::Private : public DefinitionContext<FileContext::Private>
public: public:
Private(FileDef *fd) : DefinitionContext<FileContext::Private>(fd) , m_fileDef(fd) Private(FileDef *fd) : DefinitionContext<FileContext::Private>(fd) , m_fileDef(fd)
{ {
addProperty("title",this,&Private::title); addProperty("title", this,&Private::title);
addProperty("highlight",this,&Private::highlight); addProperty("highlight", this,&Private::highlight);
addProperty("subhighlight",this,&Private::subHighlight); addProperty("subhighlight", this,&Private::subHighlight);
addProperty("versionInfo",this,&Private::versionInfo); 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 TemplateVariant title() const
{ {
...@@ -1925,8 +2075,302 @@ class FileContext::Private : public DefinitionContext<FileContext::Private> ...@@ -1925,8 +2075,302 @@ class FileContext::Private : public DefinitionContext<FileContext::Private>
{ {
return m_fileDef->getVersion(); 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: private:
FileDef *m_fileDef; 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> ...@@ -2160,21 +2604,70 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private>
public: public:
Private(MemberDef *md) : DefinitionContext<MemberContext::Private>(md) , m_memberDef(md) Private(MemberDef *md) : DefinitionContext<MemberContext::Private>(md) , m_memberDef(md)
{ {
addProperty("declType", this,&Private::declType); addProperty("isSignal", this,&Private::isSignal);
addProperty("declArgs", this,&Private::declArgs); 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("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("isObjCMethod", this,&Private::isObjCMethod);
addProperty("isObjCProperty", this,&Private::isObjCProperty); 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("isAnonymous", this,&Private::isAnonymous);
addProperty("declType", this,&Private::declType);
addProperty("declArgs", this,&Private::declArgs);
addProperty("anonymousType", this,&Private::anonymousType); addProperty("anonymousType", this,&Private::anonymousType);
addProperty("anonymousMember", this,&Private::anonymousMember); addProperty("anonymousMember", this,&Private::anonymousMember);
addProperty("isRelated", this,&Private::isRelated);
addProperty("hasDetails", this,&Private::hasDetails); addProperty("hasDetails", this,&Private::hasDetails);
addProperty("exception", this,&Private::exception); addProperty("exception", this,&Private::exception);
addProperty("bitfields", this,&Private::bitfields); addProperty("bitfields", this,&Private::bitfields);
...@@ -2214,6 +2707,7 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private> ...@@ -2214,6 +2707,7 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private>
addProperty("callGraph", this,&Private::callGraph); addProperty("callGraph", this,&Private::callGraph);
addProperty("hasCallerGraph", this,&Private::hasCallerGraph); addProperty("hasCallerGraph", this,&Private::hasCallerGraph);
addProperty("callerGraph", this,&Private::callerGraph); addProperty("callerGraph", this,&Private::callerGraph);
addProperty("fieldType", this,&Private::fieldType);
if (md && md->isProperty()) if (md && md->isProperty())
{ {
...@@ -2227,6 +2721,10 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private> ...@@ -2227,6 +2721,10 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private>
if (md->isRaisable()) m_eventAttrs.append("raise"); if (md->isRaisable()) m_eventAttrs.append("raise");
} }
} }
TemplateVariant fieldType() const
{
return createLinkedText(m_memberDef,relPathAsString(),m_memberDef->fieldType());
}
TemplateVariant declType() const TemplateVariant declType() const
{ {
return createLinkedText(m_memberDef,relPathAsString(),m_memberDef->getDeclType()); return createLinkedText(m_memberDef,relPathAsString(),m_memberDef->getDeclType());
...@@ -2259,10 +2757,202 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private> ...@@ -2259,10 +2757,202 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private>
{ {
return m_memberDef->isImplementation(); 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 TemplateVariant isEvent() const
{ {
return m_memberDef->isEvent(); 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 TemplateVariant isProperty() const
{ {
return m_memberDef->isProperty(); return m_memberDef->isProperty();
...@@ -2271,6 +2961,10 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private> ...@@ -2271,6 +2961,10 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private>
{ {
return m_memberDef->isEnumValue(); return m_memberDef->isEnumValue();
} }
TemplateVariant isVariable() const
{
return m_memberDef->isVariable();
}
TemplateVariant isEnumeration() const TemplateVariant isEnumeration() const
{ {
return m_memberDef->isEnumerate(); return m_memberDef->isEnumerate();
...@@ -2717,10 +3411,10 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private> ...@@ -2717,10 +3411,10 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private>
TemplateVariant functionQualifier() const TemplateVariant functionQualifier() const
{ {
if (!m_memberDef->isObjCMethod() && if (!m_memberDef->isObjCMethod() &&
(m_memberDef->isFunction() || m_memberDef->isSlot() || (m_memberDef->isFunction() || m_memberDef->isSlot() ||
m_memberDef->isPrototype() || m_memberDef->isSignal() m_memberDef->isPrototype() || m_memberDef->isSignal()
) )
) )
{ {
return "()"; return "()";
} }
...@@ -3007,6 +3701,47 @@ void NestedClassListContext::append(ClassDef *cd) ...@@ -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 //%% list ClassList[Class] : list of classes
class ClassListContext::Private : public GenericNodeListContext<ClassContext> class ClassListContext::Private : public GenericNodeListContext<ClassContext>
{ {
...@@ -5744,7 +6479,7 @@ void generateOutputViaTemplate() ...@@ -5744,7 +6479,7 @@ void generateOutputViaTemplate()
ctx->set("exampleList",&exampleList); ctx->set("exampleList",&exampleList);
// render HTML output // render HTML output
Template *tpl = e.loadByName("htmllayout.tpl"); Template *tpl = e.loadByName("htmllayout.tpl",1);
if (tpl) if (tpl)
{ {
g_globals.outputFormat = ContextGlobals::Html; g_globals.outputFormat = ContextGlobals::Html;
...@@ -5758,6 +6493,7 @@ void generateOutputViaTemplate() ...@@ -5758,6 +6493,7 @@ void generateOutputViaTemplate()
FTextStream ts; FTextStream ts;
tpl->render(ts,ctx); tpl->render(ts,ctx);
} }
e.unload(tpl);
// TODO: render other outputs // TODO: render other outputs
} }
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include "types.h" #include "types.h"
#include "template.h" #include "template.h"
#include <qlist.h>
class Definition; class Definition;
class ClassDef; class ClassDef;
...@@ -108,7 +109,7 @@ class UsedFilesContext : public TemplateListIntf ...@@ -108,7 +109,7 @@ class UsedFilesContext : public TemplateListIntf
class IncludeInfoContext : public TemplateStructIntf class IncludeInfoContext : public TemplateStructIntf
{ {
public: public:
IncludeInfoContext(IncludeInfo *,SrcLangExt lang); IncludeInfoContext(const IncludeInfo *,SrcLangExt lang);
~IncludeInfoContext(); ~IncludeInfoContext();
// TemplateStructIntf methods // TemplateStructIntf methods
...@@ -119,6 +120,25 @@ class IncludeInfoContext : public TemplateStructIntf ...@@ -119,6 +120,25 @@ class IncludeInfoContext : public TemplateStructIntf
Private *p; 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 class ClassContext : public TemplateStructIntf
...@@ -254,6 +274,26 @@ class NestedClassListContext : public TemplateListIntf ...@@ -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 class ClassListContext : public TemplateListIntf
{ {
public: public:
......
...@@ -170,12 +170,18 @@ void FileDef::findSectionsInDocumentation() ...@@ -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) void FileDef::writeDetailedDescription(OutputList &ol,const QCString &title)
{ {
if ((!briefDescription().isEmpty() && Config_getBool("REPEAT_BRIEF")) || if (hasDetailedDescription())
!documentation().stripWhiteSpace().isEmpty() || // avail empty section
(Config_getBool("SOURCE_BROWSER") && getStartBodyLine()!=-1 && getBodyDef())
)
{ {
ol.pushGeneratorState(); ol.pushGeneratorState();
ol.disable(OutputGenerator::Html); ol.disable(OutputGenerator::Html);
...@@ -379,7 +385,7 @@ void FileDef::writeIncludedByGraph(OutputList &ol) ...@@ -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()); 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.startTextBlock();
ol.disable(OutputGenerator::Man); ol.disable(OutputGenerator::Man);
...@@ -1800,3 +1806,7 @@ QCString FileDef::title() const ...@@ -1800,3 +1806,7 @@ QCString FileDef::title() const
return theTranslator->trFileReference(name()); return theTranslator->trFileReference(name());
} }
QCString FileDef::fileVersion() const
{
return m_fileVersion;
}
...@@ -133,6 +133,10 @@ class FileDef : public Definition ...@@ -133,6 +133,10 @@ class FileDef : public Definition
ClassSDict *getClassSDict() const { return m_classSDict; } ClassSDict *getClassSDict() const { return m_classSDict; }
QCString title() const; 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 ...@@ -3036,6 +3036,18 @@ static Definition *getClassFromType(Definition *scope,const QCString &type,SrcLa
} }
#endif #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) void MemberDef::writeMemberDocSimple(OutputList &ol, Definition *container)
{ {
Definition *scope = getOuterScope(); Definition *scope = getOuterScope();
...@@ -3056,15 +3068,7 @@ void MemberDef::writeMemberDocSimple(OutputList &ol, Definition *container) ...@@ -3056,15 +3068,7 @@ void MemberDef::writeMemberDocSimple(OutputList &ol, Definition *container)
ol.startInlineMemberType(); ol.startInlineMemberType();
ol.startDoxyAnchor(cfname,cname,memAnchor,doxyName,doxyArgs); ol.startDoxyAnchor(cfname,cname,memAnchor,doxyName,doxyArgs);
QCString type = m_impl->accessorType; QCString ts = fieldType();
if (type.isEmpty())
{
type = m_impl->type;
}
if (isTypedef()) type.prepend("typedef ");
QCString ts = simplifyTypeForTable(type);
if (cd) // cd points to an anonymous struct pointed to by this member if (cd) // cd points to an anonymous struct pointed to by this member
// so we add a link to it from the type column. // so we add a link to it from the type column.
...@@ -3855,6 +3859,11 @@ void MemberDef::setAccessorType(ClassDef *cd,const char *t) ...@@ -3855,6 +3859,11 @@ void MemberDef::setAccessorType(ClassDef *cd,const char *t)
m_impl->accessorType = t; m_impl->accessorType = t;
} }
ClassDef *MemberDef::accessorClass() const
{
return m_impl->accessorClass;
}
void MemberDef::findSectionsInDocumentation() void MemberDef::findSectionsInDocumentation()
{ {
docFindSections(documentation(),this,0,docFile()); docFindSections(documentation(),this,0,docFile());
......
...@@ -81,6 +81,7 @@ class MemberDef : public Definition ...@@ -81,6 +81,7 @@ class MemberDef : public Definition
ClassDef *getClassDef() const; ClassDef *getClassDef() const;
FileDef *getFileDef() const; FileDef *getFileDef() const;
NamespaceDef* getNamespaceDef() const; NamespaceDef* getNamespaceDef() const;
ClassDef *accessorClass() const;
// grabbing the property read/write accessor names // grabbing the property read/write accessor names
const char *getReadAccessor() const; const char *getReadAccessor() const;
...@@ -251,7 +252,7 @@ class MemberDef : public Definition ...@@ -251,7 +252,7 @@ class MemberDef : public Definition
// overrules // overrules
QCString documentation() const; QCString documentation() const;
QCString briefDescription(bool abbr=FALSE) const; QCString briefDescription(bool abbr=FALSE) const;
QCString fieldType() const;
//----------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------
......
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
* *
*/ */
#include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <qdatetime.h> #include <qdatetime.h>
#include "config.h" #include "config.h"
...@@ -22,6 +21,7 @@ ...@@ -22,6 +21,7 @@
#include "doxygen.h" #include "doxygen.h"
#include "portable.h" #include "portable.h"
#include "filedef.h" #include "filedef.h"
#include "message.h"
static QCString outputFormat; static QCString outputFormat;
static const char *warning_str = "warning: "; static const char *warning_str = "warning: ";
...@@ -110,7 +110,7 @@ void msg(const char *fmt, ...) ...@@ -110,7 +110,7 @@ void msg(const char *fmt, ...)
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
vfprintf(stdout, fmt, args); vfprintf(stdout, fmt, args);
va_end(args); va_end(args);
} }
} }
...@@ -172,6 +172,11 @@ void warn(const char *file,int line,const char *fmt, ...) ...@@ -172,6 +172,11 @@ void warn(const char *file,int line,const char *fmt, ...)
va_end(args); 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) void warn_simple(const char *file,int line,const char *text)
{ {
if (!Config_getBool("WARNINGS")) return; // warning type disabled if (!Config_getBool("WARNINGS")) return; // warning type disabled
......
...@@ -19,9 +19,11 @@ ...@@ -19,9 +19,11 @@
#define MESSAGE_H #define MESSAGE_H
#include <stdio.h> #include <stdio.h>
#include <stdarg.h>
extern void msg(const char *fmt, ...); 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, ...);
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_simple(const char *file,int line,const char *text);
extern void warn_undoc(const char *file,int line,const char *fmt, ...); 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, ...); 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, ...@@ -916,29 +916,9 @@ void NamespaceSDict::writeDeclaration(OutputList &ol,const char *title,
continue; // will be output in another pass, see layout_default.xml continue; // will be output in another pass, see layout_default.xml
ol.startMemberDeclaration(); ol.startMemberDeclaration();
ol.startMemberItem(nd->getOutputFileBase(),0); ol.startMemberItem(nd->getOutputFileBase(),0);
if (lang==SrcLangExt_Java || lang==SrcLangExt_CSharp) QCString ct = nd->compoundTypeString();
{ ol.docify(ct);
ol.docify("package "); ol.docify(" ");
}
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");
}
}
ol.insertMemberAlign(); ol.insertMemberAlign();
QCString name; QCString name;
if (localName) if (localName)
...@@ -1103,3 +1083,33 @@ QCString NamespaceDef::title() const ...@@ -1103,3 +1083,33 @@ QCString NamespaceDef::title() const
} }
return pageTitle; 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 ...@@ -94,6 +94,7 @@ class NamespaceDef : public Definition
NamespaceSDict *getNamespaceSDict() const { return namespaceSDict; } NamespaceSDict *getNamespaceSDict() const { return namespaceSDict; }
QCString title() const; QCString title() const;
QCString compoundTypeString() const;
bool visited; bool visited;
......
...@@ -29,7 +29,8 @@ class TemplateToken; ...@@ -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; QValueList<QCString> lst;
...@@ -561,7 +562,7 @@ class TemplateBlockContext ...@@ -561,7 +562,7 @@ class TemplateBlockContext
class TemplateContextImpl : public TemplateContext class TemplateContextImpl : public TemplateContext
{ {
public: public:
TemplateContextImpl(); TemplateContextImpl(const TemplateEngine *e);
virtual ~TemplateContextImpl(); virtual ~TemplateContextImpl();
// TemplateContext methods // TemplateContext methods
...@@ -589,8 +590,10 @@ class TemplateContextImpl : public TemplateContext ...@@ -589,8 +590,10 @@ class TemplateContextImpl : public TemplateContext
TemplateSpacelessIntf *spacelessIntf() const { return m_spacelessIntf; } TemplateSpacelessIntf *spacelessIntf() const { return m_spacelessIntf; }
void enableSpaceless(bool b) { m_spacelessEnabled=b; } void enableSpaceless(bool b) { m_spacelessEnabled=b; }
bool spacelessEnabled() const { return m_spacelessEnabled && m_spacelessIntf; } bool spacelessEnabled() const { return m_spacelessEnabled && m_spacelessIntf; }
void warn(const char *fileName,int line,const char *fmt,...) const;
private: private:
const TemplateEngine *m_engine;
QCString m_templateName; QCString m_templateName;
int m_line; int m_line;
QCString m_outputDir; QCString m_outputDir;
...@@ -874,7 +877,7 @@ class ExprAstVariable : public ExprAst ...@@ -874,7 +877,7 @@ class ExprAstVariable : public ExprAst
TemplateVariant v = c->get(m_name); TemplateVariant v = c->get(m_name);
if (!v.isValid()) 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; return v;
} }
...@@ -928,7 +931,7 @@ class ExprAstFilter : public ExprAst ...@@ -928,7 +931,7 @@ class ExprAstFilter : public ExprAst
TemplateVariant result = TemplateFilterFactory::instance()->apply(m_name,v,arg,ok); TemplateVariant result = TemplateFilterFactory::instance()->apply(m_name,v,arg,ok);
if (!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; return result;
} }
...@@ -1047,6 +1050,46 @@ class ExprAstBinary : public ExprAst ...@@ -1047,6 +1050,46 @@ class ExprAstBinary : public ExprAst
ExprAst *m_rhs; 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. /** @brief Recursive decent parser for Django style template expressions.
...@@ -1054,8 +1097,8 @@ class ExprAstBinary : public ExprAst ...@@ -1054,8 +1097,8 @@ class ExprAstBinary : public ExprAst
class ExpressionParser class ExpressionParser
{ {
public: public:
ExpressionParser(const QCString &templateName,int line) ExpressionParser(const TemplateParser *parser,int line)
: m_templateName(templateName), m_line(line), m_tokenStream(0) : m_parser(parser), m_line(line), m_tokenStream(0)
{ {
} }
virtual ~ExpressionParser() virtual ~ExpressionParser()
...@@ -1153,7 +1196,7 @@ class ExpressionParser ...@@ -1153,7 +1196,7 @@ class ExpressionParser
ExprAst *expr = parseCompareExpression(); ExprAst *expr = parseCompareExpression();
if (expr==0) 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; return 0;
} }
result = new ExprAstNegate(expr); result = new ExprAstNegate(expr);
...@@ -1210,12 +1253,12 @@ class ExpressionParser ...@@ -1210,12 +1253,12 @@ class ExpressionParser
default: default:
if (m_curToken.type==ExprToken::Operator) 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)); Operator::toString(m_curToken.op));
} }
else 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)); TRACE(("}parsePrimary(%s)\n",m_tokenStream));
...@@ -1461,7 +1504,7 @@ class ExpressionParser ...@@ -1461,7 +1504,7 @@ class ExpressionParser
char s[2]; char s[2];
s[0]=c; s[0]=c;
s[1]=0; 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; m_curToken.id = s;
p++; p++;
} }
...@@ -1472,51 +1515,14 @@ class ExpressionParser ...@@ -1472,51 +1515,14 @@ class ExpressionParser
return TRUE; return TRUE;
} }
const TemplateParser *m_parser;
ExprToken m_curToken; ExprToken m_curToken;
QCString m_templateName;
int m_line; int m_line;
const char *m_tokenStream; 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 */ /** @brief Class representing a lexical token in a template */
class TemplateToken class TemplateToken
{ {
...@@ -1558,24 +1564,23 @@ class TemplateImpl : public TemplateNode, public Template ...@@ -1558,24 +1564,23 @@ class TemplateImpl : public TemplateNode, public Template
{ {
public: public:
TemplateImpl(TemplateEngine *e,const QCString &name,const QCString &data); TemplateImpl(TemplateEngine *e,const QCString &name,const QCString &data);
~TemplateImpl() {}
void render(FTextStream &ts, TemplateContext *c); void render(FTextStream &ts, TemplateContext *c);
TemplateEngine *engine() const { return m_engine; } TemplateEngine *engine() const { return m_engine; }
TemplateBlockContext *blockContext() { return &m_blockContext; } TemplateBlockContext *blockContext() { return &m_blockContext; }
private: private:
TemplateEngine *m_engine;
QCString m_name; QCString m_name;
TemplateNodeList m_nodes; TemplateNodeList m_nodes;
TemplateEngine *m_engine;
TemplateBlockContext m_blockContext; TemplateBlockContext m_blockContext;
}; };
//---------------------------------------------------------- //----------------------------------------------------------
TemplateContextImpl::TemplateContextImpl() TemplateContextImpl::TemplateContextImpl(const TemplateEngine *e)
: m_templateName("<unknown>"), m_line(1), m_escapeIntf(0), : m_engine(e), m_templateName("<unknown>"), m_line(1), m_escapeIntf(0),
m_spacelessIntf(0), m_spacelessEnabled(FALSE) m_spacelessIntf(0), m_spacelessEnabled(FALSE)
{ {
m_contextStack.setAutoDelete(TRUE); m_contextStack.setAutoDelete(TRUE);
...@@ -1704,6 +1709,15 @@ TemplateBlockContext *TemplateContextImpl::blockContext() ...@@ -1704,6 +1709,15 @@ TemplateBlockContext *TemplateContextImpl::blockContext()
return &m_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 */ /** @brief Class representing a piece of plain text in a template */
...@@ -1743,7 +1757,7 @@ class TemplateNodeVariable : public TemplateNode ...@@ -1743,7 +1757,7 @@ class TemplateNodeVariable : public TemplateNode
: TemplateNode(parent), m_templateName(parser->templateName()), m_line(line) : TemplateNode(parent), m_templateName(parser->templateName()), m_line(line)
{ {
TRACE(("TemplateNodeVariable(%s)\n",var.data())); TRACE(("TemplateNodeVariable(%s)\n",var.data()));
ExpressionParser expParser(m_templateName,line); ExpressionParser expParser(parser,line);
m_var = expParser.parseVariable(var); m_var = expParser.parseVariable(var);
} }
~TemplateNodeVariable() ~TemplateNodeVariable()
...@@ -1821,14 +1835,14 @@ class TemplateNodeIf : public TemplateNodeCreator<TemplateNodeIf> ...@@ -1821,14 +1835,14 @@ class TemplateNodeIf : public TemplateNodeCreator<TemplateNodeIf>
TRACE(("{TemplateNodeIf(%s)\n",data.data())); TRACE(("{TemplateNodeIf(%s)\n",data.data()));
if (data.isEmpty()) if (data.isEmpty())
{ {
warn(m_templateName,line,"missing argument for if tag"); parser->warn(m_templateName,line,"missing argument for if tag");
} }
QStrList stopAt; QStrList stopAt;
stopAt.append("endif"); stopAt.append("endif");
stopAt.append("else"); stopAt.append("else");
parser->parse(this,line,stopAt,m_trueNodes); parser->parse(this,line,stopAt,m_trueNodes);
TemplateToken *tok = parser->takeNextToken(); TemplateToken *tok = parser->takeNextToken();
ExpressionParser ex(parser->templateName(),line); ExpressionParser ex(parser,line);
m_guardAst = ex.parse(data); m_guardAst = ex.parse(data);
if (tok && tok->data=="else") if (tok && tok->data=="else")
...@@ -1847,7 +1861,8 @@ class TemplateNodeIf : public TemplateNodeCreator<TemplateNodeIf> ...@@ -1847,7 +1861,8 @@ class TemplateNodeIf : public TemplateNodeCreator<TemplateNodeIf>
void render(FTextStream &ts, TemplateContext *c) 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()); //printf("TemplateNodeIf::render #trueNodes=%d #falseNodes=%d\n",m_trueNodes.count(),m_falseNodes.count());
if (m_guardAst) if (m_guardAst)
{ {
...@@ -1877,7 +1892,7 @@ class TemplateNodeRepeat : public TemplateNodeCreator<TemplateNodeRepeat> ...@@ -1877,7 +1892,7 @@ class TemplateNodeRepeat : public TemplateNodeCreator<TemplateNodeRepeat>
: TemplateNodeCreator<TemplateNodeRepeat>(parser,parent,line) : TemplateNodeCreator<TemplateNodeRepeat>(parser,parent,line)
{ {
TRACE(("{TemplateNodeRepeat(%s)\n",data.data())); TRACE(("{TemplateNodeRepeat(%s)\n",data.data()));
ExpressionParser expParser(parser->templateName(),line); ExpressionParser expParser(parser,line);
m_expr = expParser.parseVariable(data); m_expr = expParser.parseVariable(data);
QStrList stopAt; QStrList stopAt;
stopAt.append("endrepeat"); stopAt.append("endrepeat");
...@@ -1891,7 +1906,8 @@ class TemplateNodeRepeat : public TemplateNodeCreator<TemplateNodeRepeat> ...@@ -1891,7 +1906,8 @@ class TemplateNodeRepeat : public TemplateNodeCreator<TemplateNodeRepeat>
} }
void render(FTextStream &ts, TemplateContext *c) 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; TemplateVariant v;
if (m_expr && (v=m_expr->resolve(c)).type()==TemplateVariant::Integer) if (m_expr && (v=m_expr->resolve(c)).type()==TemplateVariant::Integer)
{ {
...@@ -1912,7 +1928,7 @@ class TemplateNodeRepeat : public TemplateNodeCreator<TemplateNodeRepeat> ...@@ -1912,7 +1928,7 @@ class TemplateNodeRepeat : public TemplateNodeCreator<TemplateNodeRepeat>
} }
else // simple type... 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: private:
...@@ -1936,15 +1952,15 @@ class TemplateNodeFor : public TemplateNodeCreator<TemplateNodeFor> ...@@ -1936,15 +1952,15 @@ class TemplateNodeFor : public TemplateNodeCreator<TemplateNodeFor>
{ {
if (data.right(3)==" in") 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") 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 else
{ {
warn(m_templateName,line,"for is missing 'in' keyword"); parser->warn(m_templateName,line,"for is missing 'in' keyword");
} }
} }
else else
...@@ -1952,7 +1968,7 @@ class TemplateNodeFor : public TemplateNodeCreator<TemplateNodeFor> ...@@ -1952,7 +1968,7 @@ class TemplateNodeFor : public TemplateNodeCreator<TemplateNodeFor>
m_vars = split(data.left(i),","); m_vars = split(data.left(i),",");
if (m_vars.count()==0) 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); int j = data.find(" reversed",i);
...@@ -1965,10 +1981,10 @@ class TemplateNodeFor : public TemplateNodeCreator<TemplateNodeFor> ...@@ -1965,10 +1981,10 @@ class TemplateNodeFor : public TemplateNodeCreator<TemplateNodeFor>
} }
if (exprStr.isEmpty()) 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); m_expr = expParser.parseVariable(exprStr);
QStrList stopAt; QStrList stopAt;
...@@ -1993,7 +2009,8 @@ class TemplateNodeFor : public TemplateNodeCreator<TemplateNodeFor> ...@@ -1993,7 +2009,8 @@ class TemplateNodeFor : public TemplateNodeCreator<TemplateNodeFor>
void render(FTextStream &ts, TemplateContext *c) 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", //printf("TemplateNodeFor::render #loopNodes=%d #emptyNodes=%d\n",
// m_loopNodes.count(),m_emptyNodes.count()); // m_loopNodes.count(),m_emptyNodes.count());
if (m_expr) if (m_expr)
...@@ -2058,7 +2075,7 @@ class TemplateNodeFor : public TemplateNodeCreator<TemplateNodeFor> ...@@ -2058,7 +2075,7 @@ class TemplateNodeFor : public TemplateNodeCreator<TemplateNodeFor>
} }
else // simple type... 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> ...@@ -2090,6 +2107,7 @@ class TemplateNodeMsg : public TemplateNodeCreator<TemplateNodeMsg>
void render(FTextStream &, TemplateContext *c) void render(FTextStream &, TemplateContext *c)
{ {
TemplateContextImpl* ci = dynamic_cast<TemplateContextImpl*>(c); TemplateContextImpl* ci = dynamic_cast<TemplateContextImpl*>(c);
ci->setLocation(m_templateName,m_line);
TemplateEscapeIntf *escIntf = ci->escapeIntf(); TemplateEscapeIntf *escIntf = ci->escapeIntf();
ci->setEscapeIntf(0); // avoid escaping things we send to standard out ci->setEscapeIntf(0); // avoid escaping things we send to standard out
bool enable = ci->spacelessEnabled(); bool enable = ci->spacelessEnabled();
...@@ -2118,7 +2136,7 @@ class TemplateNodeBlock : public TemplateNodeCreator<TemplateNodeBlock> ...@@ -2118,7 +2136,7 @@ class TemplateNodeBlock : public TemplateNodeCreator<TemplateNodeBlock>
m_blockName = data; m_blockName = data;
if (m_blockName.isEmpty()) if (m_blockName.isEmpty())
{ {
warn(parser->templateName(),line,"block tag without name"); parser->warn(parser->templateName(),line,"block tag without name");
} }
QStrList stopAt; QStrList stopAt;
stopAt.append("endblock"); stopAt.append("endblock");
...@@ -2156,14 +2174,18 @@ class TemplateNodeBlock : public TemplateNodeCreator<TemplateNodeBlock> ...@@ -2156,14 +2174,18 @@ class TemplateNodeBlock : public TemplateNodeCreator<TemplateNodeBlock>
superBlock.set("super",TemplateVariant(super.data(),TRUE)); superBlock.set("super",TemplateVariant(super.data(),TRUE));
ci->set("block",&superBlock); ci->set("block",&superBlock);
// render the overruled block contents // render the overruled block contents
t->engine()->enterBlock(nb->m_templateName,nb->m_blockName,nb->m_line);
nb->m_nodes.render(ts,c); nb->m_nodes.render(ts,c);
t->engine()->leaveBlock();
ci->pop(); ci->pop();
// re-add block to the context // re-add block to the context
ci->blockContext()->push(nb); ci->blockContext()->push(nb);
} }
else // block has no overrule else // block has no overrule
{ {
t->engine()->enterBlock(m_templateName,m_blockName,m_line);
m_nodes.render(ts,c); m_nodes.render(ts,c);
t->engine()->leaveBlock();
} }
} }
} }
...@@ -2188,10 +2210,10 @@ class TemplateNodeExtend : public TemplateNodeCreator<TemplateNodeExtend> ...@@ -2188,10 +2210,10 @@ class TemplateNodeExtend : public TemplateNodeCreator<TemplateNodeExtend>
: TemplateNodeCreator<TemplateNodeExtend>(parser,parent,line) : TemplateNodeCreator<TemplateNodeExtend>(parser,parent,line)
{ {
TRACE(("{TemplateNodeExtend(%s)\n",data.data())); TRACE(("{TemplateNodeExtend(%s)\n",data.data()));
ExpressionParser ep(m_templateName,line); ExpressionParser ep(parser,line);
if (data.isEmpty()) 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); m_extendExpr = ep.parsePrimary(data);
QStrList stopAt; QStrList stopAt;
...@@ -2205,20 +2227,21 @@ class TemplateNodeExtend : public TemplateNodeCreator<TemplateNodeExtend> ...@@ -2205,20 +2227,21 @@ class TemplateNodeExtend : public TemplateNodeCreator<TemplateNodeExtend>
void render(FTextStream &ts, TemplateContext *c) 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; if (m_extendExpr==0) return;
QCString extendFile = m_extendExpr->resolve(c).toString(); QCString extendFile = m_extendExpr->resolve(c).toString();
if (extendFile.isEmpty()) 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) // goto root of tree (template node)
TemplateImpl *t = getTemplate(); TemplateImpl *t = getTemplate();
if (t) if (t)
{ {
Template *bt = t->engine()->loadByName(extendFile); Template *bt = t->engine()->loadByName(extendFile,m_line);
TemplateImpl *baseTemplate = bt ? dynamic_cast<TemplateImpl*>(bt) : 0; TemplateImpl *baseTemplate = bt ? dynamic_cast<TemplateImpl*>(bt) : 0;
if (baseTemplate) if (baseTemplate)
{ {
...@@ -2248,11 +2271,11 @@ class TemplateNodeExtend : public TemplateNodeCreator<TemplateNodeExtend> ...@@ -2248,11 +2271,11 @@ class TemplateNodeExtend : public TemplateNodeCreator<TemplateNodeExtend>
// clean up // clean up
bc->clear(); bc->clear();
//delete baseTemplate; t->engine()->unload(t);
} }
else 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> ...@@ -2270,10 +2293,10 @@ class TemplateNodeInclude : public TemplateNodeCreator<TemplateNodeInclude>
: TemplateNodeCreator<TemplateNodeInclude>(parser,parent,line) : TemplateNodeCreator<TemplateNodeInclude>(parser,parent,line)
{ {
TRACE(("TemplateNodeInclude(%s)\n",data.data())); TRACE(("TemplateNodeInclude(%s)\n",data.data()));
ExpressionParser ep(m_templateName,line); ExpressionParser ep(parser,line);
if (data.isEmpty()) 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); m_includeExpr = ep.parsePrimary(data);
} }
...@@ -2283,28 +2306,30 @@ class TemplateNodeInclude : public TemplateNodeCreator<TemplateNodeInclude> ...@@ -2283,28 +2306,30 @@ class TemplateNodeInclude : public TemplateNodeCreator<TemplateNodeInclude>
} }
void render(FTextStream &ts, TemplateContext *c) 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) if (m_includeExpr)
{ {
QCString includeFile = m_includeExpr->resolve(c).toString(); QCString includeFile = m_includeExpr->resolve(c).toString();
if (includeFile.isEmpty()) 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 else
{ {
TemplateImpl *t = getTemplate(); TemplateImpl *t = getTemplate();
if (t) if (t)
{ {
Template *it = t->engine()->loadByName(includeFile); Template *it = t->engine()->loadByName(includeFile,m_line);
TemplateImpl *incTemplate = it ? dynamic_cast<TemplateImpl*>(it) : 0; TemplateImpl *incTemplate = it ? dynamic_cast<TemplateImpl*>(it) : 0;
if (incTemplate) if (incTemplate)
{ {
incTemplate->render(ts,c); incTemplate->render(ts,c);
t->engine()->unload(t);
} }
else 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> ...@@ -2325,30 +2350,30 @@ class TemplateNodeCreate : public TemplateNodeCreator<TemplateNodeCreate>
: TemplateNodeCreator<TemplateNodeCreate>(parser,parent,line) : TemplateNodeCreator<TemplateNodeCreate>(parser,parent,line)
{ {
TRACE(("TemplateNodeCreate(%s)\n",data.data())); TRACE(("TemplateNodeCreate(%s)\n",data.data()));
ExpressionParser ep(m_templateName,line); ExpressionParser ep(parser,line);
if (data.isEmpty()) 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 "); int i = data.find(" from ");
if (i==-1) if (i==-1)
{ {
if (data.right(3)==" from") 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") 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 else
{ {
warn(m_templateName,line,"create is missing 'from' keyword"); parser->warn(m_templateName,line,"create is missing 'from' keyword");
} }
} }
else else
{ {
ExpressionParser ep(m_templateName,line); ExpressionParser ep(parser,line);
m_fileExpr = ep.parsePrimary(data.left(i).stripWhiteSpace()); m_fileExpr = ep.parsePrimary(data.left(i).stripWhiteSpace());
m_templateExpr = ep.parsePrimary(data.mid(i+6).stripWhiteSpace()); m_templateExpr = ep.parsePrimary(data.mid(i+6).stripWhiteSpace());
} }
...@@ -2368,18 +2393,18 @@ class TemplateNodeCreate : public TemplateNodeCreator<TemplateNodeCreate> ...@@ -2368,18 +2393,18 @@ class TemplateNodeCreate : public TemplateNodeCreator<TemplateNodeCreate>
QCString outputFile = m_fileExpr->resolve(c).toString(); QCString outputFile = m_fileExpr->resolve(c).toString();
if (templateFile.isEmpty()) 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()) 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 else
{ {
TemplateImpl *t = getTemplate(); TemplateImpl *t = getTemplate();
if (t) if (t)
{ {
Template *ct = t->engine()->loadByName(templateFile); Template *ct = t->engine()->loadByName(templateFile,m_line);
TemplateImpl *createTemplate = ct ? dynamic_cast<TemplateImpl*>(ct) : 0; TemplateImpl *createTemplate = ct ? dynamic_cast<TemplateImpl*>(ct) : 0;
if (createTemplate) if (createTemplate)
{ {
...@@ -2392,16 +2417,16 @@ class TemplateNodeCreate : public TemplateNodeCreator<TemplateNodeCreate> ...@@ -2392,16 +2417,16 @@ class TemplateNodeCreate : public TemplateNodeCreator<TemplateNodeCreate>
{ {
FTextStream ts(&f); FTextStream ts(&f);
createTemplate->render(ts,c); createTemplate->render(ts,c);
//delete createTemplate; t->engine()->unload(t);
} }
else 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 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> ...@@ -2431,10 +2456,10 @@ class TemplateNodeTree : public TemplateNodeCreator<TemplateNodeTree>
: TemplateNodeCreator<TemplateNodeTree>(parser,parent,line) : TemplateNodeCreator<TemplateNodeTree>(parser,parent,line)
{ {
TRACE(("{TemplateNodeTree(%s)\n",data.data())); TRACE(("{TemplateNodeTree(%s)\n",data.data()));
ExpressionParser ep(m_templateName,line); ExpressionParser ep(parser,line);
if (data.isEmpty()) 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); m_treeExpr = ep.parsePrimary(data);
QStrList stopAt; QStrList stopAt;
...@@ -2508,7 +2533,7 @@ class TemplateNodeTree : public TemplateNodeCreator<TemplateNodeTree> ...@@ -2508,7 +2533,7 @@ class TemplateNodeTree : public TemplateNodeCreator<TemplateNodeTree>
} }
else 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> ...@@ -2535,7 +2560,7 @@ class TemplateNodeWith : public TemplateNodeCreator<TemplateNodeWith>
{ {
TRACE(("{TemplateNodeWith(%s)\n",data.data())); TRACE(("{TemplateNodeWith(%s)\n",data.data()));
m_args.setAutoDelete(TRUE); m_args.setAutoDelete(TRUE);
ExpressionParser expParser(parser->templateName(),line); ExpressionParser expParser(parser,line);
QValueList<QCString> args = split(data," "); QValueList<QCString> args = split(data," ");
QValueListIterator<QCString> it = args.begin(); QValueListIterator<QCString> it = args.begin();
while (it!=args.end()) while (it!=args.end())
...@@ -2552,7 +2577,7 @@ class TemplateNodeWith : public TemplateNodeCreator<TemplateNodeWith> ...@@ -2552,7 +2577,7 @@ class TemplateNodeWith : public TemplateNodeCreator<TemplateNodeWith>
} }
else 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; ++it;
} }
...@@ -2568,6 +2593,7 @@ class TemplateNodeWith : public TemplateNodeCreator<TemplateNodeWith> ...@@ -2568,6 +2593,7 @@ class TemplateNodeWith : public TemplateNodeCreator<TemplateNodeWith>
void render(FTextStream &ts, TemplateContext *c) void render(FTextStream &ts, TemplateContext *c)
{ {
TemplateContextImpl *ci = dynamic_cast<TemplateContextImpl*>(c); TemplateContextImpl *ci = dynamic_cast<TemplateContextImpl*>(c);
ci->setLocation(m_templateName,m_line);
c->push(); c->push();
QListIterator<Mapping> it(m_args); QListIterator<Mapping> it(m_args);
Mapping *mapping; Mapping *mapping;
...@@ -2596,7 +2622,7 @@ class TemplateNodeCycle : public TemplateNodeCreator<TemplateNodeCycle> ...@@ -2596,7 +2622,7 @@ class TemplateNodeCycle : public TemplateNodeCreator<TemplateNodeCycle>
TRACE(("{TemplateNodeCycle(%s)\n",data.data())); TRACE(("{TemplateNodeCycle(%s)\n",data.data()));
m_args.setAutoDelete(TRUE); m_args.setAutoDelete(TRUE);
m_index=0; m_index=0;
ExpressionParser expParser(parser->templateName(),line); ExpressionParser expParser(parser,line);
QValueList<QCString> args = split(data," "); QValueList<QCString> args = split(data," ");
QValueListIterator<QCString> it = args.begin(); QValueListIterator<QCString> it = args.begin();
while (it!=args.end()) while (it!=args.end())
...@@ -2610,13 +2636,14 @@ class TemplateNodeCycle : public TemplateNodeCreator<TemplateNodeCycle> ...@@ -2610,13 +2636,14 @@ class TemplateNodeCycle : public TemplateNodeCreator<TemplateNodeCycle>
} }
if (m_args.count()<2) 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())); TRACE(("}TemplateNodeCycle(%s)\n",data.data()));
} }
void render(FTextStream &ts, TemplateContext *c) void render(FTextStream &ts, TemplateContext *c)
{ {
TemplateContextImpl *ci = dynamic_cast<TemplateContextImpl*>(c); TemplateContextImpl *ci = dynamic_cast<TemplateContextImpl*>(c);
ci->setLocation(m_templateName,m_line);
if (m_index<m_args.count()) if (m_index<m_args.count())
{ {
TemplateVariant v = m_args.at(m_index)->resolve(c); TemplateVariant v = m_args.at(m_index)->resolve(c);
...@@ -2661,7 +2688,7 @@ class TemplateNodeSet : public TemplateNodeCreator<TemplateNodeSet> ...@@ -2661,7 +2688,7 @@ class TemplateNodeSet : public TemplateNodeCreator<TemplateNodeSet>
{ {
TRACE(("{TemplateNodeSet(%s)\n",data.data())); TRACE(("{TemplateNodeSet(%s)\n",data.data()));
m_args.setAutoDelete(TRUE); m_args.setAutoDelete(TRUE);
ExpressionParser expParser(parser->templateName(),line); ExpressionParser expParser(parser,line);
QValueList<QCString> args = split(data," "); QValueList<QCString> args = split(data," ");
QValueListIterator<QCString> it = args.begin(); QValueListIterator<QCString> it = args.begin();
while (it!=args.end()) while (it!=args.end())
...@@ -2678,7 +2705,7 @@ class TemplateNodeSet : public TemplateNodeCreator<TemplateNodeSet> ...@@ -2678,7 +2705,7 @@ class TemplateNodeSet : public TemplateNodeCreator<TemplateNodeSet>
} }
else 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; ++it;
} }
...@@ -2687,6 +2714,7 @@ class TemplateNodeSet : public TemplateNodeCreator<TemplateNodeSet> ...@@ -2687,6 +2714,7 @@ class TemplateNodeSet : public TemplateNodeCreator<TemplateNodeSet>
void render(FTextStream &, TemplateContext *c) void render(FTextStream &, TemplateContext *c)
{ {
TemplateContextImpl *ci = dynamic_cast<TemplateContextImpl*>(c); TemplateContextImpl *ci = dynamic_cast<TemplateContextImpl*>(c);
ci->setLocation(m_templateName,m_line);
QListIterator<Mapping> it(m_args); QListIterator<Mapping> it(m_args);
Mapping *mapping; Mapping *mapping;
for (it.toFirst();(mapping=it.current());++it) for (it.toFirst();(mapping=it.current());++it)
...@@ -2718,6 +2746,7 @@ class TemplateNodeSpaceless : public TemplateNodeCreator<TemplateNodeSpaceless> ...@@ -2718,6 +2746,7 @@ class TemplateNodeSpaceless : public TemplateNodeCreator<TemplateNodeSpaceless>
void render(FTextStream &ts, TemplateContext *c) void render(FTextStream &ts, TemplateContext *c)
{ {
TemplateContextImpl *ci = dynamic_cast<TemplateContextImpl*>(c); TemplateContextImpl *ci = dynamic_cast<TemplateContextImpl*>(c);
ci->setLocation(m_templateName,m_line);
bool wasSpaceless = ci->spacelessEnabled(); bool wasSpaceless = ci->spacelessEnabled();
ci->enableSpaceless(TRUE); ci->enableSpaceless(TRUE);
m_nodes.render(ts,c); m_nodes.render(ts,c);
...@@ -2741,11 +2770,11 @@ class TemplateNodeMarkers : public TemplateNodeCreator<TemplateNodeMarkers> ...@@ -2741,11 +2770,11 @@ class TemplateNodeMarkers : public TemplateNodeCreator<TemplateNodeMarkers>
int w = data.find(" with "); int w = data.find(" with ");
if (i==-1 || w==-1 || w<i) 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 else
{ {
ExpressionParser expParser(parser->templateName(),line); ExpressionParser expParser(parser,line);
m_var = data.left(i); m_var = data.left(i);
m_listExpr = expParser.parseVariable(data.mid(i+4,w-i-4)); m_listExpr = expParser.parseVariable(data.mid(i+4,w-i-4));
m_patternExpr = expParser.parseVariable(data.right(data.length()-w-6)); m_patternExpr = expParser.parseVariable(data.right(data.length()-w-6));
...@@ -2796,11 +2825,11 @@ class TemplateNodeMarkers : public TemplateNodeCreator<TemplateNodeMarkers> ...@@ -2796,11 +2825,11 @@ class TemplateNodeMarkers : public TemplateNodeCreator<TemplateNodeMarkers>
} }
else if (!ok) 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) 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 index=newIndex+matchLen; // set index just after marker
} }
...@@ -2809,12 +2838,12 @@ class TemplateNodeMarkers : public TemplateNodeCreator<TemplateNodeMarkers> ...@@ -2809,12 +2838,12 @@ class TemplateNodeMarkers : public TemplateNodeCreator<TemplateNodeMarkers>
} }
else 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 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) ...@@ -2970,19 +2999,20 @@ void TemplateBlockContext::push(TemplateNodeBlock *block)
class TemplateLexer class TemplateLexer
{ {
public: public:
TemplateLexer(const QCString &fileName,const QCString &data); TemplateLexer(const TemplateEngine *engine,const QCString &fileName,const QCString &data);
void tokenize(QList<TemplateToken> &tokens); void tokenize(QList<TemplateToken> &tokens);
private: private:
void addToken(QList<TemplateToken> &tokens, void addToken(QList<TemplateToken> &tokens,
const char *data,int line,int startPos,int endPos, const char *data,int line,int startPos,int endPos,
TemplateToken::Type type); TemplateToken::Type type);
void reset(); void reset();
const TemplateEngine *m_engine;
QCString m_fileName; QCString m_fileName;
QCString m_data; QCString m_data;
}; };
TemplateLexer::TemplateLexer(const QCString &fileName,const QCString &data) : TemplateLexer::TemplateLexer(const TemplateEngine *engine,const QCString &fileName,const QCString &data) :
m_fileName(fileName), m_data(data) m_engine(engine), m_fileName(fileName), m_data(data)
{ {
} }
...@@ -3049,6 +3079,7 @@ void TemplateLexer::tokenize(QList<TemplateToken> &tokens) ...@@ -3049,6 +3079,7 @@ void TemplateLexer::tokenize(QList<TemplateToken> &tokens)
if (c=='\n') if (c=='\n')
{ {
warn(m_fileName,line,"unexpected new line inside {%%...%%} block"); warn(m_fileName,line,"unexpected new line inside {%%...%%} block");
m_engine->printIncludeContext(m_fileName,line);
} }
else if (c=='%') // %} or something else else if (c=='%') // %} or something else
{ {
...@@ -3072,6 +3103,7 @@ void TemplateLexer::tokenize(QList<TemplateToken> &tokens) ...@@ -3072,6 +3103,7 @@ void TemplateLexer::tokenize(QList<TemplateToken> &tokens)
if (c=='\n') if (c=='\n')
{ {
warn(m_fileName,line,"unexpected new line inside {%%...%%} block"); warn(m_fileName,line,"unexpected new line inside {%%...%%} block");
m_engine->printIncludeContext(m_fileName,line);
} }
state=StateTag; state=StateTag;
} }
...@@ -3080,6 +3112,7 @@ void TemplateLexer::tokenize(QList<TemplateToken> &tokens) ...@@ -3080,6 +3112,7 @@ void TemplateLexer::tokenize(QList<TemplateToken> &tokens)
if (c=='\n') if (c=='\n')
{ {
warn(m_fileName,line,"unexpected new line inside {#...#} block"); warn(m_fileName,line,"unexpected new line inside {#...#} block");
m_engine->printIncludeContext(m_fileName,line);
} }
else if (c=='#') // #} or something else else if (c=='#') // #} or something else
{ {
...@@ -3101,6 +3134,7 @@ void TemplateLexer::tokenize(QList<TemplateToken> &tokens) ...@@ -3101,6 +3134,7 @@ void TemplateLexer::tokenize(QList<TemplateToken> &tokens)
if (c=='\n') if (c=='\n')
{ {
warn(m_fileName,line,"unexpected new line inside {#...#} block"); warn(m_fileName,line,"unexpected new line inside {#...#} block");
m_engine->printIncludeContext(m_fileName,line);
} }
state=StateComment; state=StateComment;
} }
...@@ -3125,6 +3159,7 @@ void TemplateLexer::tokenize(QList<TemplateToken> &tokens) ...@@ -3125,6 +3159,7 @@ void TemplateLexer::tokenize(QList<TemplateToken> &tokens)
if (c=='\n') if (c=='\n')
{ {
warn(m_fileName,line,"unexpected new line inside {{...}} block"); warn(m_fileName,line,"unexpected new line inside {{...}} block");
m_engine->printIncludeContext(m_fileName,line);
} }
else if (c=='}') // }} or something else else if (c=='}') // }} or something else
{ {
...@@ -3148,6 +3183,7 @@ void TemplateLexer::tokenize(QList<TemplateToken> &tokens) ...@@ -3148,6 +3183,7 @@ void TemplateLexer::tokenize(QList<TemplateToken> &tokens)
if (c=='\n') if (c=='\n')
{ {
warn(m_fileName,line,"unexpected new line inside {{...}} block"); warn(m_fileName,line,"unexpected new line inside {{...}} block");
m_engine->printIncludeContext(m_fileName,line);
} }
state=StateVariable; state=StateVariable;
} }
...@@ -3192,9 +3228,10 @@ void TemplateLexer::addToken(QList<TemplateToken> &tokens, ...@@ -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) : 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( ...@@ -3214,10 +3251,10 @@ void TemplateParser::parse(
case TemplateToken::Text: case TemplateToken::Text:
nodes.append(new TemplateNodeText(this,parent,tok->line,tok->data)); nodes.append(new TemplateNodeText(this,parent,tok->line,tok->data));
break; break;
case TemplateToken::Variable: case TemplateToken::Variable: // {{ var }}
nodes.append(new TemplateNodeVariable(this,parent,tok->line,tok->data)); nodes.append(new TemplateNodeVariable(this,parent,tok->line,tok->data));
break; break;
case TemplateToken::Block: case TemplateToken::Block: // {% tag %}
{ {
QCString command = tok->data; QCString command = tok->data;
int sep = command.find(' '); int sep = command.find(' ');
...@@ -3301,6 +3338,15 @@ void TemplateParser::prependToken(const TemplateToken *token) ...@@ -3301,6 +3338,15 @@ void TemplateParser::prependToken(const TemplateToken *token)
m_tokens.prepend(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 ...@@ -3311,11 +3357,11 @@ TemplateImpl::TemplateImpl(TemplateEngine *engine,const QCString &name,const QCS
{ {
m_name = name; m_name = name;
m_engine = engine; m_engine = engine;
TemplateLexer lexer(name,data); TemplateLexer lexer(engine,name,data);
QList<TemplateToken> tokens; QList<TemplateToken> tokens;
tokens.setAutoDelete(TRUE); tokens.setAutoDelete(TRUE);
lexer.tokenize(tokens); lexer.tokenize(tokens);
TemplateParser parser(name,tokens); TemplateParser parser(engine,name,tokens);
parser.parse(this,1,QStrList(),m_nodes); parser.parse(this,1,QStrList(),m_nodes);
} }
...@@ -3348,11 +3394,35 @@ void TemplateImpl::render(FTextStream &ts, TemplateContext *c) ...@@ -3348,11 +3394,35 @@ void TemplateImpl::render(FTextStream &ts, TemplateContext *c)
/** @brief Private data of the template engine */ /** @brief Private data of the template engine */
class TemplateEngine::Private 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: public:
Private(TemplateEngine *engine) : m_templateCache(17), m_engine(engine) Private(TemplateEngine *engine) : m_templateCache(17) /*, m_indent(0)*/, m_engine(engine)
{ m_templateCache.setAutoDelete(TRUE); }
Template *loadByName(const QCString &fileName) const
{ {
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); Template *templ = m_templateCache.find(fileName);
if (templ==0) if (templ==0)
{ {
...@@ -3379,10 +3449,60 @@ class TemplateEngine::Private ...@@ -3379,10 +3449,60 @@ class TemplateEngine::Private
} }
return templ; 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: private:
mutable QDict<Template> m_templateCache; QDict<Template> m_templateCache;
//mutable int m_indent;
TemplateEngine *m_engine; TemplateEngine *m_engine;
QList<IncludeEntry> m_includeStack;
}; };
TemplateEngine::TemplateEngine() TemplateEngine::TemplateEngine()
...@@ -3397,11 +3517,31 @@ TemplateEngine::~TemplateEngine() ...@@ -3397,11 +3517,31 @@ TemplateEngine::~TemplateEngine()
TemplateContext *TemplateEngine::createContext() const 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; ...@@ -10,32 +10,32 @@ class TemplateListIntf;
class TemplateStructIntf; class TemplateStructIntf;
class TemplateEngine; class TemplateEngine;
/** @defgroup template_api Template API /** @defgroup template_api Template API
* *
* This is the API for a * This is the API for a
* <a href="https://docs.djangoproject.com/en/1.6/topics/templates/">Django</a> * <a href="https://docs.djangoproject.com/en/1.6/topics/templates/">Django</a>
* compatible template system written in C++. * 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 href="http://www.gitorious.org/grantlee/pages/Home">Grantlee</a>.
* *
* A template is simply a text file. * A template is simply a text file.
* A template contains \b variables, which get replaced with values when the * 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. * template is evaluated, and \b tags, which control the logic of the template.
* *
* Variables look like this: `{{ variable }}` * Variables look like this: `{{ variable }}`
* When the template engine encounters a variable, it evaluates that variable and * When the template engine encounters a variable, it evaluates that variable and
* replaces it with the result. Variable names consist of any combination of * replaces it with the result. Variable names consist of any combination of
* alphanumeric characters and the underscore ("_"). * alphanumeric characters and the underscore ("_").
* Use a dot (.) to access attributes of a structured variable. * Use a dot (.) to access attributes of a structured variable.
* *
* One can modify variables for display by using \b filters, for example: * One can modify variables for display by using \b filters, for example:
* `{{ value|default:"nothing" }}` * `{{ value|default:"nothing" }}`
* *
* Tags look like this: `{% tag %}`. Tags are more complex than variables: * 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, * 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. * 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 #}`. * `{# comment text #}`.
* *
* Supported Django tags: * Supported Django tags:
...@@ -144,13 +144,13 @@ class TemplateVariant ...@@ -144,13 +144,13 @@ class TemplateVariant
/** Constructs a new variant with a string value \a s. */ /** Constructs a new variant with a string value \a s. */
TemplateVariant(const QCString &s,bool raw=FALSE); 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 * @note. Only a pointer to the struct is stored. The caller
* is responsible to manage the memory for the struct object. * is responsible to manage the memory for the struct object.
*/ */
TemplateVariant(const TemplateStructIntf *s); 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 * @note. Only a pointer to the struct is stored. The caller
* is responsible to manage the memory for the list object. * is responsible to manage the memory for the list object.
*/ */
...@@ -168,7 +168,7 @@ class TemplateVariant ...@@ -168,7 +168,7 @@ class TemplateVariant
/** Destroys the Variant object */ /** Destroys the Variant object */
~TemplateVariant(); ~TemplateVariant();
/** Constructs a copy of the variant, \a v, /** Constructs a copy of the variant, \a v,
* passed as the argument to this constructor. * passed as the argument to this constructor.
*/ */
TemplateVariant(const TemplateVariant &v); TemplateVariant(const TemplateVariant &v);
...@@ -176,7 +176,7 @@ class TemplateVariant ...@@ -176,7 +176,7 @@ class TemplateVariant
/** Assigns the value of the variant \a v to this variant. */ /** Assigns the value of the variant \a v to this variant. */
TemplateVariant &operator=(const TemplateVariant &v); 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. * otherwise returns false.
*/ */
bool operator==(TemplateVariant &other); bool operator==(TemplateVariant &other);
...@@ -190,13 +190,13 @@ class TemplateVariant ...@@ -190,13 +190,13 @@ class TemplateVariant
/** Returns the variant as an integer. */ /** Returns the variant as an integer. */
int toInt() const; int toInt() const;
/** Returns the pointer to list referenced by this variant /** Returns the pointer to list referenced by this variant
* or 0 if this variant does not have list type. * or 0 if this variant does not have list type.
*/ */
const TemplateListIntf *toList() const; const TemplateListIntf *toList() const;
/** Returns the pointer to struct referenced by this variant /** Returns the pointer to struct referenced by this variant
* or 0 if this variant does not have struct type. * or 0 if this variant does not have struct type.
*/ */
const TemplateStructIntf *toStruct() const; const TemplateStructIntf *toStruct() const;
...@@ -205,7 +205,7 @@ class TemplateVariant ...@@ -205,7 +205,7 @@ class TemplateVariant
*/ */
TemplateVariant call(const QValueList<TemplateVariant> &args); 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). * escaped or written as-is (raw).
* @param[in] b TRUE means write as-is, FALSE means apply escaping. * @param[in] b TRUE means write as-is, FALSE means apply escaping.
*/ */
...@@ -223,7 +223,7 @@ class TemplateVariant ...@@ -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. * @note The values of the list are TemplateVariants.
*/ */
class TemplateListIntf class TemplateListIntf
...@@ -245,7 +245,7 @@ class TemplateListIntf ...@@ -245,7 +245,7 @@ class TemplateListIntf
virtual void toPrev() = 0; virtual void toPrev() = 0;
/* Returns TRUE if the iterator points to a valid element /* Returns TRUE if the iterator points to a valid element
* in the list, or FALSE otherwise. * 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. * iterator is assigned to \a v.
*/ */
virtual bool current(TemplateVariant &v) const = 0; virtual bool current(TemplateVariant &v) const = 0;
...@@ -260,7 +260,7 @@ class TemplateListIntf ...@@ -260,7 +260,7 @@ class TemplateListIntf
/** Returns the element at index position \a index. */ /** Returns the element at index position \a index. */
virtual TemplateVariant at(int index) const = 0; 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. * @note the user should call delete on the returned pointer.
*/ */
virtual TemplateListIntf::ConstIterator *createIterator() const = 0; virtual TemplateListIntf::ConstIterator *createIterator() const = 0;
...@@ -279,7 +279,7 @@ class TemplateList : public TemplateListIntf ...@@ -279,7 +279,7 @@ class TemplateList : public TemplateListIntf
virtual int count() const; virtual int count() const;
virtual TemplateVariant at(int index) const; virtual TemplateVariant at(int index) const;
virtual TemplateListIntf::ConstIterator *createIterator() const; virtual TemplateListIntf::ConstIterator *createIterator() const;
/** Appends element \a v to the end of the list */ /** Appends element \a v to the end of the list */
virtual void append(const TemplateVariant &v); virtual void append(const TemplateVariant &v);
...@@ -350,8 +350,8 @@ class TemplateSpacelessIntf ...@@ -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 Context consists of a stack of dictionaries.
* A dictionary consists of a mapping of string keys onto TemplateVariant values. * 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 * A key is searched starting with the dictionary at the top of the stack
...@@ -370,10 +370,10 @@ class TemplateContext ...@@ -370,10 +370,10 @@ class TemplateContext
/** Pop the current scope from the stack. */ /** Pop the current scope from the stack. */
virtual void pop() = 0; 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] name The name of the value; the key in the dictionary.
* @param[in] v The value associated with the key. * @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 * its value will be replaced by \a v
*/ */
virtual void set(const char *name,const TemplateVariant &v) = 0; virtual void set(const char *name,const TemplateVariant &v) = 0;
...@@ -409,8 +409,8 @@ class TemplateContext ...@@ -409,8 +409,8 @@ class TemplateContext
//------------------------------------------------------------------------ //------------------------------------------------------------------------
/** @brief Abstract interface for a template. /** @brief Abstract interface for a template.
* @note Must be created by TemplateEngine * @note Must be created and is deleted by the TemplateEngine
*/ */
class Template class Template
{ {
...@@ -418,7 +418,7 @@ class Template ...@@ -418,7 +418,7 @@ class Template
/** Destructor */ /** Destructor */
virtual ~Template() {} 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] ts The text stream to write the results to.
* @param[in] c The context containing data that can be used * @param[in] c The context containing data that can be used
* when instantiating the template. * when instantiating the template.
...@@ -444,13 +444,25 @@ class TemplateEngine ...@@ -444,13 +444,25 @@ class TemplateEngine
TemplateContext *createContext() const; TemplateContext *createContext() const;
/** Creates a new template whole contents are in a file. /** 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 * 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. * @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: private:
friend class TemplateNodeBlock;
void enterBlock(const QCString &fileName,const QCString &blockName,int line);
void leaveBlock();
class Private; class Private;
Private *p; 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