From 6dbf32d505d5c9e628474fb83e379b2646d24d3f Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Thu, 5 Dec 2013 23:54:38 +0100 Subject: More template and context enhancements --- src/context.cpp | 649 ++++++++++++++++++++++++++++++++++++++++++++++++----- src/context.h | 2 + src/definition.cpp | 11 +- src/definition.h | 9 +- src/htmlgen.h | 2 +- src/memberdef.cpp | 51 +++-- src/memberdef.h | 8 + src/template.cpp | 24 +- src/template.h | 82 +++++-- src/util.cpp | 23 ++ src/util.h | 2 +- 11 files changed, 752 insertions(+), 111 deletions(-) diff --git a/src/context.cpp b/src/context.cpp index 1881147..c73c715 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -21,6 +21,7 @@ #include "diagram.h" #include "example.h" #include "membername.h" +#include "parserintf.h" struct ContextGlobals { @@ -328,31 +329,7 @@ class TranslateContext::Private : public PropertyMapper { public: - static TemplateVariant generatedAtFunc(const void *obj,const QValueList &args) - { - return ((TranslateContext::Private*)obj)->generatedAt(args); - } - static TemplateVariant inheritanceDiagramForFunc(const void *obj,const QValueList &args) - { - return ((TranslateContext::Private*)obj)->inheritanceDiagramFor(args); - } - static TemplateVariant inheritsListFunc(const void *obj,const QValueList &args) - { - return ((TranslateContext::Private*)obj)->inheritsList(args); - } - static TemplateVariant inheritedByListFunc(const void *obj,const QValueList &args) - { - return ((TranslateContext::Private*)obj)->inheritedByList(args); - } - static TemplateVariant collaborationDiagramForFunc(const void *obj,const QValueList &args) - { - return ((TranslateContext::Private*)obj)->collaborationDiagramFor(args); - } - static TemplateVariant writeListFunc(const void *obj,const QValueList &args) - { - return ((TranslateContext::Private*)obj)->writeList(args); - } - TemplateVariant generatedAt(const QValueList &args) const + TemplateVariant handleGeneratedAt(const QValueList &args) const { if (args.count()==2) { @@ -364,7 +341,7 @@ class TranslateContext::Private : public PropertyMapper } return TemplateVariant(); } - TemplateVariant inheritanceDiagramFor(const QValueList &args) const + TemplateVariant handleInheritanceDiagramFor(const QValueList &args) const { if (args.count()==1) { @@ -376,7 +353,7 @@ class TranslateContext::Private : public PropertyMapper } return TemplateVariant(); } - TemplateVariant collaborationDiagramFor(const QValueList &args) const + TemplateVariant handleCollaborationDiagramFor(const QValueList &args) const { if (args.count()==1) { @@ -388,7 +365,7 @@ class TranslateContext::Private : public PropertyMapper } return TemplateVariant(); } - TemplateVariant inheritsList(const QValueList &args) const + TemplateVariant handleInheritsList(const QValueList &args) const { if (args.count()==1) { @@ -400,7 +377,7 @@ class TranslateContext::Private : public PropertyMapper } return TemplateVariant(); } - QCString inheritedByList(const QValueList &args) const + TemplateVariant handleInheritedByList(const QValueList &args) const { if (args.count()==1) { @@ -410,9 +387,9 @@ class TranslateContext::Private : public PropertyMapper { err("tr.inheritedByList should take one integer parameter, got %d!\n",args.count()); } - return QCString(); + return TemplateVariant(); } - QCString writeList(const QValueList &args) const + TemplateVariant handleWriteList(const QValueList &args) const { if (args.count()==1) { @@ -422,7 +399,55 @@ class TranslateContext::Private : public PropertyMapper { err("tr.*List should take one integer parameter, got %d!\n",args.count()); } - return QCString(); + return TemplateVariant(); + } + TemplateVariant handleImplementedBy(const QValueList &args) const + { + if (args.count()==1) + { + return theTranslator->trImplementedInList(args[0].toInt()); + } + else + { + err("tr.implementedBy should take one integer parameter, got %d!\n",args.count()); + } + return TemplateVariant(); + } + TemplateVariant handleReimplementedBy(const QValueList &args) const + { + if (args.count()==1) + { + return theTranslator->trReimplementedInList(args[0].toInt()); + } + else + { + err("tr.reimplementedBy should take one integer parameter, got %d!\n",args.count()); + } + return TemplateVariant(); + } + TemplateVariant handleSourceRefs(const QValueList &args) const + { + if (args.count()==1) + { + return theTranslator->trReferences()+" "+theTranslator->trWriteList(args[0].toInt())+"."; + } + else + { + err("tr.sourceRefs should take one integer parameter, got %d\n",args.count()); + } + return TemplateVariant(); + } + TemplateVariant handleSourceRefBys(const QValueList &args) const + { + if (args.count()==1) + { + return theTranslator->trReferencedBy()+" "+theTranslator->trWriteList(args[0].toInt())+"."; + } + else + { + err("tr.sourceRefBys should take one integer parameter, got %d\n",args.count()); + } + return TemplateVariant(); } @@ -433,15 +458,15 @@ class TranslateContext::Private : public PropertyMapper } TemplateVariant generatedAt() const { - return TemplateVariant(this,&Private::generatedAtFunc); + return TemplateVariant::Delegate::fromMethod(this); } TemplateVariant inheritanceDiagramFor() const { - return TemplateVariant(this,&Private::inheritanceDiagramForFunc); + return TemplateVariant::Delegate::fromMethod(this); } TemplateVariant collaborationDiagramFor() const { - return TemplateVariant(this,&Private::collaborationDiagramForFunc); + return TemplateVariant::Delegate::fromMethod(this); } TemplateVariant search() const { @@ -554,11 +579,11 @@ class TranslateContext::Private : public PropertyMapper } TemplateVariant inheritsList() const { - return TemplateVariant(this,&Private::inheritsListFunc); + return TemplateVariant::Delegate::fromMethod(this); } TemplateVariant inheritedByList() const { - return TemplateVariant(this,&Private::inheritedByListFunc); + return TemplateVariant::Delegate::fromMethod(this); } TemplateVariant definedAtLineInSourceFile() const { @@ -570,7 +595,7 @@ class TranslateContext::Private : public PropertyMapper } TemplateVariant exampleList() const { - return TemplateVariant(this,&Private::writeListFunc); + return TemplateVariant::Delegate::fromMethod(this); } TemplateVariant listOfAllMembers() const { @@ -588,6 +613,50 @@ class TranslateContext::Private : public PropertyMapper { return theTranslator->trIncludingInheritedMembers(); } + TemplateVariant defineValue() const + { + return theTranslator->trDefineValue(); + } + TemplateVariant initialValue() const + { + return theTranslator->trInitialValue(); + } + TemplateVariant enumerationValues() const + { + return theTranslator->trEnumerationValues(); + } + TemplateVariant implements() const + { + return theTranslator->trImplementedFromList(1); + } + TemplateVariant reimplements() const + { + return theTranslator->trReimplementedFromList(1); + } + TemplateVariant implementedBy() const + { + return TemplateVariant::Delegate::fromMethod(this); + } + TemplateVariant reimplementedBy() const + { + return TemplateVariant::Delegate::fromMethod(this); + } + TemplateVariant sourceRefs() const + { + return TemplateVariant::Delegate::fromMethod(this); + } + TemplateVariant sourceRefBys() const + { + return TemplateVariant::Delegate::fromMethod(this); + } + TemplateVariant callGraph() const + { + return theTranslator->trCallGraph(); + } + TemplateVariant callerGraph() const + { + return theTranslator->trCallerGraph(); + } Private() { //%% string generatedBy @@ -654,6 +723,28 @@ class TranslateContext::Private : public PropertyMapper addProperty("theListOfAllMembers",this,&Private::theListOfAllMembers); //%% string incInheritedMembers addProperty("incInheritedMembers",this,&Private::incInheritedMembers); + //%% string defineValue + addProperty("defineValue", this,&Private::defineValue); + //%% string initialValue + addProperty("initialValue", this,&Private::initialValue); + //%% string enumerationValues + addProperty("enumerationValues", this,&Private::enumerationValues); + //%% markerstring implements + addProperty("implements", this,&Private::implements); + //%% markerstring reimplements + addProperty("reimplements", this,&Private::reimplements); + //%% markerstring implementedBy + addProperty("implementedBy", this,&Private::implementedBy); + //%% markerstring reimplementedBy + addProperty("reimplementedBy", this,&Private::reimplementedBy); + //%% markerstring sourceRefs + addProperty("sourceRefs", this,&Private::sourceRefs); + //%% markerstring sourceRefBys + addProperty("sourceRefBys", this,&Private::sourceRefBys); + //%% string callGraph + addProperty("callGraph", this,&Private::callGraph); + //%% string callerGraph + addProperty("callerGraph", this,&Private::callerGraph); m_javaOpt = Config_getBool("OPTIMIZE_OUTPUT_JAVA"); m_fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN"); @@ -703,6 +794,19 @@ static TemplateVariant parseDoc(Definition *def,const QCString &file,int line, return result; } +static TemplateVariant parseCode(MemberDef *md,const QCString &scopeName,const QCString &relPath, + const QCString &code,int startLine=-1,int endLine=-1,bool showLineNumbers=FALSE) +{ + ParserInterface *pIntf = Doxygen::parserManager->getParser(md->getDefFileExtension()); + pIntf->resetCodeParserState(); + QGString s; + FTextStream t(&s); + HtmlCodeGenerator codeGen(t,relPath); + pIntf->parseCode(codeGen,scopeName,code,md->getLanguage(),FALSE,0,md->getBodyDef(), + startLine,endLine,TRUE,md,showLineNumbers,md); + return TemplateVariant(s.data(),TRUE); +} + //------------------------------------------------------------------------ //%% struct Symbol: shared info for all symbols @@ -727,6 +831,8 @@ class DefinitionContext : public PropertyMapper addProperty("details",this,&DefinitionContext::details); //%% string brief: the brief description for this symbol addProperty("brief",this,&DefinitionContext::brief); + //%% string inbodyDocs: the documentation found in the body + addProperty("inbodyDocs",this,&DefinitionContext::inbodyDocs); //%% string sourceFileName: the file name of the source file (without extension) addProperty("sourceFileName",this,&DefinitionContext::sourceFileName); //%% bool isLinkable: can the symbol be linked to? @@ -745,7 +851,7 @@ class DefinitionContext : public PropertyMapper m_sourceDef.append(&m_lineLink); m_sourceDef.append(&m_fileLink); m_lineLink.set("text",m_def->getStartBodyLine()); - m_lineLink.set("isLinkable",m_def->isLinkable()); + m_lineLink.set("isLinkable",TRUE); m_lineLink.set("fileName",m_def->getSourceFileBase()); m_lineLink.set("anchor",m_def->getSourceAnchor()); if (m_def->definitionType()==Definition::TypeFile) @@ -760,7 +866,7 @@ class DefinitionContext : public PropertyMapper { m_fileLink.set("text",name()); } - m_fileLink.set("isLinkable",m_def->isLinkable()); + m_fileLink.set("isLinkable",TRUE); m_fileLink.set("fileName",m_def->getSourceFileBase()); m_fileLink.set("anchor",QCString()); } @@ -827,6 +933,22 @@ class DefinitionContext : public PropertyMapper } return *m_cache.brief; } + TemplateVariant inbodyDocs() const + { + if (!m_cache.inbodyDocs) + { + if (!m_def->inbodyDocumentation().isEmpty()) + { + m_cache.inbodyDocs.reset(new TemplateVariant(parseDoc(m_def,m_def->inbodyFile(),m_def->inbodyLine(), + relPathAsString(),m_def->inbodyDocumentation(),FALSE))); + } + else + { + m_cache.inbodyDocs.reset(new TemplateVariant("")); + } + } + return *m_cache.inbodyDocs; + } TemplateVariant dynSectionId() const { return g_globals.dynSectionId; @@ -873,6 +995,7 @@ class DefinitionContext : public PropertyMapper { ScopedPtr details; ScopedPtr brief; + ScopedPtr inbodyDocs; }; mutable Cachable m_cache; TemplateList m_sourceDef; @@ -1002,11 +1125,10 @@ class ClassContext::Private : public DefinitionContext addProperty("events", this,&Private::events); addProperty("friends", this,&Private::friends); addProperty("relatedDecls", this,&Private::relatedDecls); - addProperty("typedefs", this,&Private::typedefs); + addProperty("enums", this,&Private::enums); addProperty("methods", this,&Private::methods); addProperty("relatedDefs", this,&Private::relatedDefs); - addProperty("nestedClasses", this,&Private::nestedClasses); addProperty("compoundType", this,&Private::compoundType); addProperty("templateDecls", this,&Private::templateDecls); @@ -1316,6 +1438,10 @@ class ClassContext::Private : public DefinitionContext { return getMemberList(m_cache.typedefs,MemberListType_typedefMembers,theTranslator->trMemberTypedefDocumentation()); } + TemplateVariant enums() const + { + return getMemberList(m_cache.enums,MemberListType_enumMembers,theTranslator->trMemberEnumerationDocumentation()); + } TemplateVariant methods() const { return getMemberList(m_cache.methods,MemberListType_functionMembers,theTranslator->trMemberFunctionDocumentation()); @@ -1519,6 +1645,7 @@ class ClassContext::Private : public DefinitionContext ScopedPtr friends; ScopedPtr relatedDecls; ScopedPtr typedefs; + ScopedPtr enums; ScopedPtr methods; ScopedPtr relatedDefs; ScopedPtr allMembersList; @@ -1871,11 +1998,14 @@ class MemberContext::Private : public DefinitionContext addProperty("isEnumeration", this,&Private::isEnumeration); addProperty("isEnumValue", this,&Private::isEnumValue); addProperty("isAnonymous", this,&Private::isAnonymous); + addProperty("isRelated", this,&Private::isRelated); addProperty("hasDetails", this,&Private::hasDetails); addProperty("exception", this,&Private::exception); addProperty("bitfields", this,&Private::bitfields); addProperty("initializer", this,&Private::initializer); - addProperty("oneLineInitializer", this,&Private::oneLineInitializer); + addProperty("initializerAsCode", this,&Private::initializerAsCode); + addProperty("hasOneLineInitializer", this,&Private::hasOneLineInitializer); + addProperty("hasMultiLineInitializer", this,&Private::hasMultiLineInitializer); addProperty("templateArgs", this,&Private::templateArgs); addProperty("templateAlias", this,&Private::templateAlias); addProperty("propertyAttrs", this,&Private::propertyAttrs); @@ -1892,6 +2022,22 @@ class MemberContext::Private : public DefinitionContext addProperty("labels", this,&Private::labels); addProperty("enumBaseType", this,&Private::enumBaseType); addProperty("enumValues", this,&Private::enumValues); + addProperty("paramDocs", this,&Private::paramDocs); + addProperty("reimplements", this,&Private::reimplements); + addProperty("implements", this,&Private::implements); + addProperty("reimplementedBy", this,&Private::reimplementedBy); + addProperty("implementedBy", this,&Private::implementedBy); + addProperty("examples", this,&Private::examples); + addProperty("typeConstraints", this,&Private::typeConstraints); + addProperty("functionQualifier", this,&Private::functionQualifier); + addProperty("sourceRefs", this,&Private::sourceRefs); + addProperty("sourceRefBys", this,&Private::sourceRefBys); + addProperty("hasSources", this,&Private::hasSources); + addProperty("sourceCode", this,&Private::sourceCode); + addProperty("hasCallGraph", this,&Private::hasCallGraph); + addProperty("callGraph", this,&Private::callGraph); + addProperty("hasCallerGraph", this,&Private::hasCallerGraph); + addProperty("callerGraph", this,&Private::callerGraph); if (md && md->isProperty()) { @@ -1961,6 +2107,25 @@ class MemberContext::Private : public DefinitionContext { return createLinkedText(m_memberDef,relPathAsString(),m_memberDef->initializer()); } + TemplateVariant initializerAsCode() const + { + if (!m_cache.initializerParsed) + { + QCString scopeName; + if (m_memberDef->getClassDef()) + { + scopeName = m_memberDef->getClassDef()->name(); + } + else if (m_memberDef->getNamespaceDef()) + { + scopeName = m_memberDef->getNamespaceDef()->name(); + } + m_cache.initializer = parseCode(m_memberDef,scopeName,relPathAsString(), + m_memberDef->initializer()); + m_cache.initializerParsed = TRUE; + } + return m_cache.initializer; + } TemplateVariant isDefine() const { return m_memberDef->isDefine(); @@ -1970,14 +2135,22 @@ class MemberContext::Private : public DefinitionContext QCString name = m_memberDef->name(); return !name.isEmpty() && name.at(0)=='@'; } + TemplateVariant isRelated() const + { + return m_memberDef->isRelated(); + } TemplateVariant enumBaseType() const { return m_memberDef->enumBaseType(); } - TemplateVariant oneLineInitializer() const + TemplateVariant hasOneLineInitializer() const { return m_memberDef->hasOneLineInitializer(); } + TemplateVariant hasMultiLineInitializer() const + { + return m_memberDef->hasMultiLineInitializer(); + } TemplateVariant enumValues() const { if (!m_cache.enumValues) @@ -2109,8 +2282,6 @@ class MemberContext::Private : public DefinitionContext if (tal->count()>0) { ArgumentListContext *al = new ArgumentListContext(tal,m_memberDef,relPathAsString()); - // since a TemplateVariant does take ownership of the object, we add it - // a separate list just to be able to delete it and avoid a memory leak m_cache.templateArgList.append(al); tl->append(al); } @@ -2118,7 +2289,7 @@ class MemberContext::Private : public DefinitionContext } else { - if (cd && !m_memberDef->isTemplateSpecialization()) + if (cd && !m_memberDef->isRelated() && !m_memberDef->isTemplateSpecialization()) { QList tempParamLists; cd->getTemplateParameterLists(tempParamLists); @@ -2130,8 +2301,6 @@ class MemberContext::Private : public DefinitionContext if (tal->count()>0) { ArgumentListContext *al = new ArgumentListContext(tal,m_memberDef,relPathAsString()); - // since a TemplateVariant does take ownership of the object, we add it - // a separate list just to be able to delete it and avoid a memory leak m_cache.templateArgList.append(al); tl->append(al); } @@ -2141,8 +2310,6 @@ class MemberContext::Private : public DefinitionContext { ArgumentListContext *al = new ArgumentListContext( m_memberDef->templateArguments(),m_memberDef,relPathAsString()); - // since a TemplateVariant does take ownership of the object, we add it - // a separate list just to be able to delete it and avoid a memory leak m_cache.templateArgList.append(al); tl->append(al); } @@ -2191,17 +2358,379 @@ class MemberContext::Private : public DefinitionContext return TemplateVariant(FALSE); } } + TemplateVariant paramDocs() const + { + if (!m_cache.paramDocs) + { + if (m_memberDef->argumentList() && m_memberDef->argumentList()->hasDocumentation()) + { + QCString paramDocs; + ArgumentListIterator ali(*m_memberDef->argumentList()); + Argument *a; + // convert the parameter documentation into a list of @param commands + for (ali.toFirst();(a=ali.current());++ali) + { + if (a->hasDocumentation()) + { + QCString direction = extractDirection(a->docs); + paramDocs+="@param"+direction+" "+a->name+" "+a->docs; + } + } + m_cache.paramDocs.reset(new TemplateVariant(parseDoc(m_memberDef, + m_memberDef->docFile(),m_memberDef->docLine(), + relPathAsString(),paramDocs,FALSE))); + } + else + { + m_cache.paramDocs.reset(new TemplateVariant("")); + } + } + return *m_cache.paramDocs; + } + TemplateVariant implements() const + { + if (!m_cache.implements) + { + MemberDef *md = m_memberDef->reimplements(); + if (md) + { + ClassDef *cd = md->getClassDef(); + if (cd && (md->virtualness()==Pure || cd->compoundType()==ClassDef::Interface)) + { + m_cache.implements.reset(new TemplateList); + MemberContext *mc = new MemberContext(md); + m_cache.implementsMember.reset(mc); + m_cache.implements->append(mc); + } + } + } + if (m_cache.implements) + { + return m_cache.implements.get(); + } + else + { + return TemplateVariant(FALSE); + } + } + TemplateVariant reimplements() const + { + if (!m_cache.reimplements) + { + MemberDef *md = m_memberDef->reimplements(); + if (md) + { + ClassDef *cd = md->getClassDef(); + if (cd && md->virtualness()!=Pure && cd->compoundType()!=ClassDef::Interface) + { + m_cache.reimplements.reset(new TemplateList); + MemberContext *mc = new MemberContext(md); + m_cache.reimplementsMember.reset(mc); + m_cache.reimplements->append(mc); + } + } + } + if (m_cache.reimplements) + { + return m_cache.reimplements.get(); + } + else + { + return TemplateVariant(FALSE); + } + } + TemplateVariant implementedBy() const + { + if (!m_cache.implementedBy) + { + MemberList *ml = m_memberDef->reimplementedBy(); + if (ml) + { + MemberListIterator mli(*ml); + MemberDef *md=0; + m_cache.implementedBy.reset(new TemplateList); + for (mli.toFirst();(md=mli.current());++mli) + { + ClassDef *cd = md->getClassDef(); + if (cd && (md->virtualness()==Pure || cd->compoundType()==ClassDef::Interface)) + { + MemberContext *mc = new MemberContext(md); + m_cache.implementedByMembers.append(mc); + m_cache.implementedBy->append(mc); + } + } + } + } + if (m_cache.implementedBy) + { + return m_cache.implementedBy.get(); + } + else + { + return TemplateVariant(FALSE); + } + } + TemplateVariant reimplementedBy() const + { + if (!m_cache.reimplementedBy) + { + MemberList *ml = m_memberDef->reimplementedBy(); + if (ml) + { + MemberListIterator mli(*ml); + MemberDef *md=0; + m_cache.reimplementedBy.reset(new TemplateList); + for (mli.toFirst();(md=mli.current());++mli) + { + ClassDef *cd = md->getClassDef(); + if (cd && md->virtualness()!=Pure && cd->compoundType()!=ClassDef::Interface) + { + MemberContext *mc = new MemberContext(md); + m_cache.reimplementedByMembers.append(mc); + m_cache.reimplementedBy->append(mc); + } + } + } + } + if (m_cache.reimplementedBy) + { + return m_cache.reimplementedBy.get(); + } + else + { + return TemplateVariant(FALSE); + } + } + void addExamples(TemplateList *list) const + { + if (m_memberDef->hasExamples()) + { + ExampleSDict::Iterator it(*m_memberDef->getExamples()); + Example *ex; + for (it.toFirst();(ex=it.current());++it) + { + TemplateStruct *s = new TemplateStruct; + m_cache.exampleList.append(s); + s->set("text",ex->name); + s->set("isLinkable",TRUE); + s->set("anchor",ex->anchor); + s->set("fileName",ex->file); + list->append(s); + } + } + } + TemplateVariant examples() const + { + if (!m_cache.examples) + { + TemplateList *exampleList = new TemplateList; + addExamples(exampleList); + m_cache.examples.reset(exampleList); + } + if (m_cache.examples) + { + return m_cache.examples.get(); + } + else + { + return TemplateVariant(FALSE); + } + } + TemplateVariant typeConstraints() const + { + if (!m_cache.typeConstraints && m_memberDef->typeConstraints()) + { + m_cache.typeConstraints.reset(new ArgumentListContext(m_memberDef->typeConstraints(),m_memberDef,relPathAsString())); + } + if (m_cache.typeConstraints) + { + return m_cache.typeConstraints.get(); + } + else + { + return TemplateVariant(FALSE); + } + } + TemplateVariant functionQualifier() const + { + if (!m_memberDef->isObjCMethod() && + (m_memberDef->isFunction() || m_memberDef->isSlot() || + m_memberDef->isPrototype() || m_memberDef->isSignal() + ) + ) + { + return "()"; + } + else + { + return ""; + } + } + TemplateVariant sourceRefs() const + { + if (!m_cache.sourceRefs) + { + m_cache.sourceRefs.reset(new MemberListContext(m_memberDef->getReferencesMembers(),TRUE)); + } + return m_cache.sourceRefs.get(); + } + TemplateVariant sourceRefBys() const + { + if (!m_cache.sourceRefBys) + { + m_cache.sourceRefBys.reset(new MemberListContext(m_memberDef->getReferencedByMembers(),TRUE)); + } + return m_cache.sourceRefBys.get(); + } + TemplateVariant hasSources() const + { + return TemplateVariant(m_memberDef->hasSources()); + } + TemplateVariant sourceCode() const + { + if (!m_cache.sourceCodeParsed) + { + QCString codeFragment; + FileDef *fd = m_memberDef->getBodyDef(); + int startLine = m_memberDef->getStartBodyLine(); + int endLine = m_memberDef->getEndBodyLine(); + if (fd && readCodeFragment(fd->absFilePath(), + startLine,endLine,codeFragment) + ) + { + QCString scopeName; + if (m_memberDef->getClassDef()) + { + scopeName = m_memberDef->getClassDef()->name(); + } + else if (m_memberDef->getNamespaceDef()) + { + scopeName = m_memberDef->getNamespaceDef()->name(); + } + m_cache.sourceCode = parseCode(m_memberDef,scopeName,relPathAsString(),codeFragment,startLine,endLine,TRUE); + m_cache.sourceCodeParsed = TRUE; + } + } + return m_cache.sourceCode; + } + DotCallGraph *getCallGraph() const + { + if (!m_cache.callGraph) + { + m_cache.callGraph.reset(new DotCallGraph(m_memberDef,FALSE)); + } + return m_cache.callGraph.get(); + } + TemplateVariant hasCallGraph() const + { + static bool haveDot = Config_getBool("HAVE_DOT"); + static bool callGraph = Config_getBool("CALL_GRAPH"); + if ((callGraph || m_memberDef->hasCallGraph()) && haveDot && + (m_memberDef->isFunction() || m_memberDef->isSlot() || m_memberDef->isSignal())) + { + DotCallGraph *cg = getCallGraph(); + return !cg->isTooBig() && !cg->isTrivial(); + } + return TemplateVariant(FALSE); + } + TemplateVariant callGraph() const + { + if (hasCallGraph().toBool()) + { + DotCallGraph *cg = getCallGraph(); + QGString result; + FTextStream t(&result); + cg->writeGraph(t,BITMAP, + g_globals.outputDir, + m_memberDef->getOutputFileBase()+Doxygen::htmlFileExtension, + relPathAsString(),TRUE,g_globals.dynSectionId + ); + g_globals.dynSectionId++; + return TemplateVariant(result.data(),TRUE); + } + else + { + return TemplateVariant(""); + } + } + DotCallGraph *getCallerGraph() const + { + if (!m_cache.callerGraph) + { + m_cache.callerGraph.reset(new DotCallGraph(m_memberDef,TRUE)); + } + return m_cache.callerGraph.get(); + } + TemplateVariant hasCallerGraph() const + { + static bool haveDot = Config_getBool("HAVE_DOT"); + static bool callerGraph = Config_getBool("CALLER_GRAPH"); + if ((callerGraph || m_memberDef->hasCallerGraph()) && haveDot && + (m_memberDef->isFunction() || m_memberDef->isSlot() || m_memberDef->isSignal())) + { + DotCallGraph *cg = getCallerGraph(); + return !cg->isTooBig() && !cg->isTrivial(); + } + return TemplateVariant(FALSE); + } + TemplateVariant callerGraph() const + { + if (hasCallerGraph().toBool()) + { + DotCallGraph *cg = getCallerGraph(); + QGString result; + FTextStream t(&result); + cg->writeGraph(t,BITMAP, + g_globals.outputDir, + m_memberDef->getOutputFileBase()+Doxygen::htmlFileExtension, + relPathAsString(),TRUE,g_globals.dynSectionId + ); + g_globals.dynSectionId++; + return TemplateVariant(result.data(),TRUE); + } + else + { + return TemplateVariant(""); + } + } private: MemberDef *m_memberDef; struct Cachable { + Cachable() : initializerParsed(FALSE), sourceCodeParsed(FALSE) + { + implementedByMembers.setAutoDelete(TRUE); + reimplementedByMembers.setAutoDelete(TRUE); + templateArgList.setAutoDelete(TRUE); + exampleList.setAutoDelete(TRUE); + } ScopedPtr templateArgs; ScopedPtr arguments; ScopedPtr enumValues; ScopedPtr classDef; ScopedPtr templateDecls; + ScopedPtr paramDocs; + ScopedPtr implements; + ScopedPtr implementsMember; + ScopedPtr reimplements; + ScopedPtr reimplementsMember; + ScopedPtr implementedBy; + ScopedPtr sourceRefs; + ScopedPtr sourceRefBys; + ScopedPtr callGraph; + ScopedPtr callerGraph; + QList implementedByMembers; + ScopedPtr reimplementedBy; + QList reimplementedByMembers; QList templateArgList; ScopedPtr labels; + TemplateVariant initializer; + bool initializerParsed; + TemplateVariant sourceCode; + bool sourceCodeParsed; + ScopedPtr examples; + QList exampleList; + ScopedPtr typeConstraints; }; mutable Cachable m_cache; TemplateList m_propertyAttrs; @@ -4021,6 +4550,24 @@ MemberListContext::MemberListContext(const MemberList *list) } } +MemberListContext::MemberListContext(MemberSDict *list,bool doSort) +{ + p = new Private; + if (list) + { + if (doSort) + { + list->sort(); + } + MemberSDict::Iterator it(*list); + MemberDef *md; + for (it.toFirst();(md=it.current());++it) + { + p->addMember(md); + } + } +} + MemberListContext::~MemberListContext() { delete p; diff --git a/src/context.h b/src/context.h index 75f1579..9f88b69 100644 --- a/src/context.h +++ b/src/context.h @@ -25,6 +25,7 @@ class GroupDef; class GroupList; struct IncludeInfo; class MemberList; +class MemberSDict; class MemberDef; struct Argument; class ArgumentList; @@ -650,6 +651,7 @@ class MemberListContext : public TemplateListIntf { public: MemberListContext(const MemberList *ml); + MemberListContext(MemberSDict *ml,bool doSort); ~MemberListContext(); // TemplateListIntf diff --git a/src/definition.cpp b/src/definition.cpp index 2c05f29..46147fc 100644 --- a/src/definition.cpp +++ b/src/definition.cpp @@ -1050,6 +1050,13 @@ void Definition::setBodyDef(FileDef *fd) m_impl->body->fileDef=fd; } +bool Definition::hasSources() const +{ + return m_impl->body && m_impl->body->startLine!=-1 && + m_impl->body->endLine>=m_impl->body->startLine && + m_impl->body->fileDef; +} + /*! Write code of this definition into the documentation */ void Definition::writeInlineCode(OutputList &ol,const char *scopeName) { @@ -1057,9 +1064,7 @@ void Definition::writeInlineCode(OutputList &ol,const char *scopeName) ol.pushGeneratorState(); //printf("Source Fragment %s: %d-%d bodyDef=%p\n",name().data(), // m_startBodyLine,m_endBodyLine,m_bodyDef); - if (inlineSources && - m_impl->body && m_impl->body->startLine!=-1 && - m_impl->body->endLine>=m_impl->body->startLine && m_impl->body->fileDef) + if (inlineSources && hasSources()) { QCString codeFragment; int actualStart=m_impl->body->startLine,actualEnd=m_impl->body->endLine; diff --git a/src/definition.h b/src/definition.h index 9de08fd..f444cc5 100644 --- a/src/definition.h +++ b/src/definition.h @@ -137,18 +137,18 @@ class Definition : public DefinitionIntf virtual QCString getSourceAnchor() const; /*! Returns the detailed description of this definition */ - QCString documentation() const; - + virtual QCString documentation() const; + /*! Returns the line number at which the detailed documentation was found. */ int docLine() const; - /*! Returns the file in which the detailed documentation block was found. + /*! Returns the file in which the detailed documentation block was found. * This can differ from getDefFileName(). */ QCString docFile() const; /*! Returns the brief description of this definition. This can include commands. */ - QCString briefDescription(bool abbreviate=FALSE) const; + virtual QCString briefDescription(bool abbreviate=FALSE) const; /*! Returns a plain text version of the brief description suitable for use * as a tool tip. @@ -259,6 +259,7 @@ class Definition : public DefinitionIntf MemberSDict *getReferencedByMembers() const; bool hasSections() const; + bool hasSources() const; /** returns TRUE if this class has a brief description */ bool hasBriefDescription() const; diff --git a/src/htmlgen.h b/src/htmlgen.h index 6fb168b..366027d 100644 --- a/src/htmlgen.h +++ b/src/htmlgen.h @@ -282,7 +282,7 @@ class HtmlGenerator : public OutputGenerator //{ t << ""; } { t << ""; } void endDescTableTitle() - { t << " "; } + { t << " "; } void startDescTableData() //{ t << "" << endl; } { t << "" << endl; } diff --git a/src/memberdef.cpp b/src/memberdef.cpp index 2059341..5d88d4a 100644 --- a/src/memberdef.cpp +++ b/src/memberdef.cpp @@ -449,27 +449,6 @@ static void writeTemplatePrefix(OutputList &ol,ArgumentList *al) ol.docify("> "); } -QCString extractDirection(QCString &docs) -{ - QRegExp re("\\[[^\\]]+\\]"); // [...] - int l=0; - if (re.match(docs,0,&l)==0) - { - int inPos = docs.find("in", 1,FALSE); - int outPos = docs.find("out",1,FALSE); - bool input = inPos!=-1 && inPostemplateMaster) + { + return m_impl->templateMaster->briefDescription(abbr); + } + else + { + return Definition::briefDescription(abbr); + } +} + +QCString MemberDef::documentation() const +{ + if (m_impl->templateMaster) + { + return m_impl->templateMaster->documentation(); + } + else + { + return Definition::documentation(); + } +} + +const ArgumentList *MemberDef::typeConstraints() const +{ + return m_impl->typeConstraints; +} + + diff --git a/src/memberdef.h b/src/memberdef.h index aa17798..926906c 100644 --- a/src/memberdef.h +++ b/src/memberdef.h @@ -245,6 +245,14 @@ class MemberDef : public Definition QCString getDeclType() const; void getLabels(QStrList &sl,Definition *container) const; + const ArgumentList *typeConstraints() const; + + // overrules + QCString documentation() const; + QCString briefDescription(bool abbr=FALSE) const; + + + //----------------------------------------------------------------------------------- // ---- setters ----- //----------------------------------------------------------------------------------- diff --git a/src/template.cpp b/src/template.cpp index e3eecf9..75596f2 100644 --- a/src/template.cpp +++ b/src/template.cpp @@ -104,8 +104,7 @@ class TemplateVariant::Private bool boolVal; const TemplateStructIntf *strukt; const TemplateListIntf *list; - FuncType func; - const void *obj; + Delegate delegate; bool raw; }; @@ -158,12 +157,11 @@ TemplateVariant::TemplateVariant(const TemplateListIntf *l) p->list = l; } -TemplateVariant::TemplateVariant(const void *obj,FuncType f) +TemplateVariant::TemplateVariant(const TemplateVariant::Delegate &delegate) { p = new Private; p->type = Function; - p->func = f; - p->obj = obj; + p->delegate = delegate; } TemplateVariant::~TemplateVariant() @@ -184,8 +182,7 @@ TemplateVariant::TemplateVariant(const TemplateVariant &v) case String: p->strVal = v.p->strVal; break; case Struct: p->strukt = v.p->strukt; break; case List: p->list = v.p->list; break; - case Function: p->func = v.p->func; - p->obj = v.p->obj; break; + case Function: p->delegate= v.p->delegate;break; } } @@ -201,8 +198,7 @@ TemplateVariant &TemplateVariant::operator=(const TemplateVariant &v) case String: p->strVal = v.p->strVal; break; case Struct: p->strukt = v.p->strukt; break; case List: p->list = v.p->list; break; - case Function: p->func = v.p->func; - p->obj = v.p->obj; break; + case Function: p->delegate= v.p->delegate;break; } return *this; } @@ -305,7 +301,7 @@ const TemplateListIntf *TemplateVariant::toList() const TemplateVariant TemplateVariant::call(const QValueList &args) { - if (p->type==Function) return p->func(p->obj,args); + if (p->type==Function) return p->delegate(args); return TemplateVariant(); } @@ -766,14 +762,12 @@ class FilterDivisibleBy public: static TemplateVariant apply(const TemplateVariant &v,const TemplateVariant &n) { - printf("FilterDivisibleBy::apply()\n"); if (!v.isValid() || !n.isValid()) { return TemplateVariant(); } if (v.type()==TemplateVariant::Integer && n.type()==TemplateVariant::Integer) { - printf("FilterDivisibleBy(%d,%d)=%d",v.toInt(),n.toInt(),(v.toInt()%n.toInt())==0); return TemplateVariant((v.toInt()%n.toInt())==0); } else @@ -2045,10 +2039,13 @@ class TemplateNodeMsg : public TemplateNodeCreator TemplateContextImpl* ci = dynamic_cast(c); TemplateEscapeIntf *escIntf = ci->escapeIntf(); ci->setEscapeIntf(0); // avoid escaping things we send to standard out + bool enable = ci->spacelessEnabled(); + ci->enableSpaceless(FALSE); FTextStream ts(stdout); m_nodes.render(ts,c); ts << endl; ci->setEscapeIntf(escIntf); + ci->enableSpaceless(enable); } private: TemplateNodeList m_nodes; @@ -2423,7 +2420,8 @@ class TemplateNodeTree : public TemplateNodeCreator if (list && list->count()>0) // non-empty list { TreeContext childCtx(this,list,ctx->templateCtx); - TemplateVariant children(&childCtx,renderChildrenStub); +// TemplateVariant children(&childCtx,renderChildrenStub); + TemplateVariant children(TemplateVariant::Delegate::fromFunction(&childCtx,renderChildrenStub)); children.setRaw(TRUE); c->set("children",children); m_treeNodes.render(ss,c); diff --git a/src/template.h b/src/template.h index f5598f1..22dca13 100644 --- a/src/template.h +++ b/src/template.h @@ -26,7 +26,7 @@ class TemplateEngine; * 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 variable. + * 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" }}` @@ -40,28 +40,33 @@ class TemplateEngine; * * Supported Django tags: * - `for ... empty ... endfor` - * - `if ... else ... endif` - * - `block ... endblock` + * - `if ... else ... endif` + * - `block ... endblock` * - `extend` * - `include` * - `with ... endwith` * - `spaceless ... endspaceless` + * - `cycle` + * + * Extension tags: + * - `create` which instantiates a template and writes the result to a file. + * The syntax is `{% create 'filename' from 'template' %}`. + * - `recursetree` + * - `markers` + * - `msg` ... `endmsg` + * - `set` * * Supported Django filters: * - `default` * - `length` * - `add` - * - * Extension tags: - * - `create` which instantiates a template and writes the result to a file. - * The syntax is `{% create 'filename' from 'template' %}`. - * - `recursetree` - * - `markers` + * - `divisibleby` * * Extension filters: * - `stripPath` * - `nowrap` * - `prepend` + * - `append` * * @{ */ @@ -70,8 +75,50 @@ class TemplateEngine; class TemplateVariant { public: - /** Signature of the callback function, used for function type variants */ - typedef TemplateVariant (*FuncType)(const void *obj, const QValueList &args); + /** @brief Helper class to create a delegate that can store a function/method call. */ + class Delegate + { + public: + /** Callback type to use when creating a delegate from a function. */ + typedef TemplateVariant (*StubType)(const void *obj, const QValueList &args); + + Delegate() : m_objectPtr(0) , m_stubPtr(0) {} + + /** Creates a delegate given an object. The method to call is passed as a template parameter */ + template &) const> + static Delegate fromMethod(const T* objectPtr) + { + Delegate d; + d.m_objectPtr = objectPtr; + d.m_stubPtr = &methodStub; + return d; + } + /** Creates a delegate given an object, and a plain function. */ + static Delegate fromFunction(const void *obj,StubType func) + { + Delegate d; + d.m_objectPtr = obj; + d.m_stubPtr = func; + return d; + } + + /** Invokes the function/method stored in the delegate */ + TemplateVariant operator()(const QValueList &args) const + { + return (*m_stubPtr)(m_objectPtr, args); + } + + private: + const void* m_objectPtr; + StubType m_stubPtr; + + template &) const> + static TemplateVariant methodStub(const void* objectPtr, const QValueList &args) + { + T* p = (T*)(objectPtr); + return (p->*TMethod)(args); + } + }; /** Types of data that can be stored in a TemplateVariant */ enum Type { None, Bool, Integer, String, Struct, List, Function }; @@ -109,13 +156,14 @@ class TemplateVariant */ TemplateVariant(const TemplateListIntf *l); - /** Constructs a new variant which represents a function - * @param[in] obj Opaque user defined pointer, which - * is passed back when call() is invoked. - * @param[in] func Callback function to invoke when + /** Constructs a new variant which represents a method call + * @param[in] delegate Delegate object to invoke when * calling call() on this variant. + * @note Use TemplateVariant::Delegate::fromMethod() and + * TemplateVariant::Delegate::fromFunction() to create + * Delegate objects. */ - TemplateVariant(const void *obj,FuncType func); + TemplateVariant(const Delegate &delegate); /** Destroys the Variant object */ ~TemplateVariant(); @@ -167,7 +215,7 @@ class TemplateVariant * @see setRaw() */ bool raw() const; - + private: class Private; Private *p; diff --git a/src/util.cpp b/src/util.cpp index 202ba82..42bf819 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -8057,3 +8057,26 @@ bool classVisibleInIndex(ClassDef *cd) return (allExternals && cd->isLinkable()) || cd->isLinkableInProject(); } +//---------------------------------------------------------------------------- + +QCString extractDirection(QCString &docs) +{ + QRegExp re("\\[[^\\]]+\\]"); // [...] + int l=0; + if (re.match(docs,0,&l)==0) + { + int inPos = docs.find("in", 1,FALSE); + int outPos = docs.find("out",1,FALSE); + bool input = inPos!=-1 && inPos