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