1 /******************************************************************************
2  *
3  * Copyright (C) 1997-2015 by Dimitri van Heesch.
4  *
5  * Permission to use, copy, modify, and distribute this software and its
6  * documentation under the terms of the GNU General Public License is hereby
7  * granted. No representations are made about the suitability of this software
8  * for any purpose. It is provided "as is" without express or implied warranty.
9  * See the GNU General Public License for more details.
10  *
11  * Documents produced by Doxygen are derivative works derived from the
12  * input used in their production; they are not affected by this license.
13  *
14  */
15 
16 #include <assert.h>
17 #include <sstream>
18 
19 #include "context.h"
20 #include "config.h"
21 #include "index.h"
22 #include "classlist.h"
23 #include "doxygen.h"
24 #include "namespacedef.h"
25 #include "filedef.h"
26 #include "pagedef.h"
27 #include "groupdef.h"
28 #include "util.h"
29 #include "version.h"
30 #include "language.h"
31 #include "message.h"
32 #include "vhdldocgen.h"
33 #include "filename.h"
34 #include "dirdef.h"
35 #include "docparser.h"
36 #include "htmlgen.h"
37 #include "htmldocvisitor.h"
38 #include "htmlhelp.h"
39 #include "latexgen.h"
40 #include "latexdocvisitor.h"
41 #include "dot.h"
42 #include "dotcallgraph.h"
43 #include "dotclassgraph.h"
44 #include "dotdirdeps.h"
45 #include "dotgfxhierarchytable.h"
46 #include "dotgroupcollaboration.h"
47 #include "dotincldepgraph.h"
48 #include "diagram.h"
49 #include "example.h"
50 #include "membername.h"
51 #include "parserintf.h"
52 #include "portable.h"
53 #include "arguments.h"
54 #include "groupdef.h"
55 #include "searchindex.h"
56 #include "resourcemgr.h"
57 #include "dir.h"
58 
59 // TODO: pass the current file to Dot*::writeGraph, so the user can put dot graphs in other
60 //       files as well
61 
62 enum ContextOutputFormat
63 {
64   ContextOutputFormat_Unspecified=0,
65   ContextOutputFormat_Html,
66   ContextOutputFormat_Latex,
67   ContextOutputFormat_Rtf,
68   ContextOutputFormat_ManPage,
69   ContextOutputFormat_DocBook,
70   ContextOutputFormat_Xml,
71   ContextOutputFormat_TagFile
72 };
73 
74 struct ContextGlobals
75 {
76   int                 dynSectionId;
77   QCString            outputDir;
78   ContextOutputFormat outputFormat;
79 } g_globals;
80 
81 
82 /** Wrapper for data that needs to be cached.
83  *  The cached data can be accessed via the get() method from multiple threads.
84  *  The first thread that calls get() will trigger creation of the data item via
85  *  the creator method, blocking other threads until the item is available in the cache.
86  *  @tparam T       the type of the data item in the cache.
87  *  @tparam TOwner  the class containing the cached item.
88  *  @tparam creator the method of TOwner to call in order to create the data item to be cached.
89  */
90 template<typename T, typename TOwner, T(TOwner::*creator)() const>
91 class CachedItem
92 {
93   public:
94     /** Returns a reference to the cached data.
95      *  Conceptually this is a const method, i.e. it will always return the same data
96      *  The first time it is called, the owner will be asked to create the data.
97      */
get(const TOwner * owner) const98     T &get(const TOwner *owner) const
99     {
100       // create a lamda function to create the cached data
101       auto creatorFunc = [this,owner]() { m_item = (owner->*creator)(); };
102       // use std::call_once to let one thread invoke the creator func
103       std::call_once(m_cache_flag, creatorFunc);
104       // return the cached results
105       return m_item;
106     }
107   private:
108     mutable std::once_flag m_cache_flag; // flag to keep track if the item is already cached
109     mutable T              m_item;       // the cached data item
110 };
111 
112 //------------------------------------------------------------------------
113 
114 /** Class representing a mapping of properties and the corresponding getter function.
115  *  The map should be initialized at initialization time.
116  */
117 template<class T>
118 class PropertyMap
119 {
120   public:
121     using Map = std::map< std::string, TemplateVariant(T::*)() const >;
122 
PropertyMap(std::initializer_list<typename Map::value_type> init)123     PropertyMap(std::initializer_list<typename Map::value_type> init)
124       : m_map(init) {}
125 
get(const T * obj,const QCString & n) const126     TemplateVariant get(const T *obj,const QCString &n) const
127     {
128       auto it = m_map.find(n.str());
129       return it!=m_map.end() ? (obj->*(it->second))() : TemplateVariant();
130     }
fields() const131     StringVector fields() const
132     {
133       StringVector result;
134       result.reserve(m_map.size());
135       for (const auto &imap : m_map) result.push_back(imap.first);
136       return result;
137     }
138 
map()139     Map &map() { return m_map; }
140 
141   private:
142     const Map m_map;
143 };
144 
145 //------------------------------------------------------------------------
146 
147 /** @brief Template List iterator support */
148 class GenericConstIterator : public TemplateListIntf::ConstIterator
149 {
150   public:
GenericConstIterator(const TemplateVariantList & list)151     GenericConstIterator(const TemplateVariantList &list) : m_list(list) {}
~GenericConstIterator()152     virtual ~GenericConstIterator() {}
toFirst()153     void toFirst()
154     {
155       m_index=0;
156     }
toLast()157     void toLast()
158     {
159       m_index=static_cast<int>(m_list.size())-1;
160     }
toNext()161     void toNext()
162     {
163       if (m_index < static_cast<int>(m_list.size())) ++m_index;
164     }
toPrev()165     void toPrev()
166     {
167       if (m_index>=0) --m_index;
168     }
current(TemplateVariant & v) const169     bool current(TemplateVariant &v) const
170     {
171       if (m_index>=0 && m_index < static_cast<int>(m_list.size()))
172       {
173         v = m_list[m_index];
174         return true;
175       }
176       else
177       {
178         v = TemplateVariant();
179         return false;
180       }
181     }
182   private:
183     const TemplateVariantList &m_list;
184     int m_index=0;
185 };
186 
187 //------------------------------------------------------------------------
188 
189 /** @brief standard template list implementation */
190 class GenericNodeListContext : public TemplateListIntf
191 {
192   public:
GenericNodeListContext()193     GenericNodeListContext()
194     {
195     }
alloc()196     static TemplateListIntfPtr alloc()
197     {
198       return std::static_pointer_cast<TemplateListIntf>(std::make_shared<GenericNodeListContext>());
199     }
200 
201     // TemplateListIntf methods
count() const202     uint count() const
203     {
204       return static_cast<uint>(m_children.size());
205     }
at(uint index) const206     TemplateVariant at(uint index) const
207     {
208       TemplateVariant result;
209       if (index<count())
210       {
211         result = m_children[index];
212       }
213       return result;
214     }
createIterator() const215     TemplateListIntf::ConstIteratorPtr createIterator() const
216     {
217       return std::make_unique<GenericConstIterator>(m_children);
218     }
219 
append(const TemplateVariant & ctn)220     void append(const TemplateVariant &ctn)
221     {
222       m_children.emplace_back(ctn);
223     }
isEmpty() const224     bool isEmpty() const
225     {
226       return m_children.empty();
227     }
228   private:
229     std::vector< TemplateVariant > m_children;
230 };
231 
232 //------------------------------------------------------------------------
233 
234 //%% struct Config : configuration options
235 //%% {
236 class ConfigContext::Private
237 {
238   public:
239     // TemplateStructIntf methods
fields() const240     StringVector fields() const
241     {
242       return m_fields.get(this);
243     }
get(const QCString & name) const244     TemplateVariant get(const QCString &name) const
245     {
246       auto &data = m_configData.get(this);
247       auto it = data.find(name.str());
248       return (it!=data.end()) ? it->second : TemplateVariant();
249     }
250   private:
251     using ConfigData = std::map<std::string,TemplateVariant>;
252 
createConfigData() const253     ConfigData createConfigData() const
254     {
255       std::map<std::string,TemplateVariant> map;
256       for (auto name : ConfigValues::instance().fields())
257       {
258         const ConfigValues::Info *option = ConfigValues::instance().get(QCString(name));
259         if (option)
260         {
261           switch (option->type)
262           {
263             case ConfigValues::Info::Bool:
264               {
265                 bool b = ConfigValues::instance().*(option->value.b);
266                 map.insert(std::make_pair(name,TemplateVariant(b)));
267               }
268               break;
269             case ConfigValues::Info::Int:
270               {
271                 int i = ConfigValues::instance().*(option->value.i);
272                 map.insert(std::make_pair(name,TemplateVariant(i)));
273               }
274               break;
275             case ConfigValues::Info::String:
276               {
277                 QCString s = ConfigValues::instance().*(option->value.s);
278                 map.insert(std::make_pair(name,TemplateVariant(s)));
279               }
280               break;
281             case ConfigValues::Info::List:
282               {
283                 auto fetchList = [](const StringVector &list) -> TemplateVariant
284                 {
285                   TemplateVariantList elements;
286                   elements.reserve(list.size());
287                   for (const auto &s : list)
288                   {
289                     elements.push_back(TemplateVariant(s));
290                   }
291                   return TemplateImmutableList::alloc(elements);
292                 };
293                 const StringVector &l = ConfigValues::instance().*(option->value.l);
294                 map.insert(std::make_pair(name,fetchList(l)));
295               }
296               break;
297             default:
298               break;
299           }
300         }
301       }
302       return map;
303     }
304 
createFields() const305     StringVector createFields() const
306     {
307       return ConfigValues::instance().fields();
308     }
309 
310     CachedItem<StringVector, Private, &Private::createFields    > m_fields;
311     CachedItem<ConfigData,   Private, &Private::createConfigData> m_configData;
312 };
313 //%% }
314 
ConfigContext()315 ConfigContext::ConfigContext() : p(std::make_unique<Private>())
316 {
317 }
318 
~ConfigContext()319 ConfigContext::~ConfigContext()
320 {
321 }
322 
get(const QCString & name) const323 TemplateVariant ConfigContext::get(const QCString &name) const
324 {
325   return p->get(name);
326 }
327 
fields() const328 StringVector ConfigContext::fields() const
329 {
330   return p->fields();
331 }
332 
333 //------------------------------------------------------------------------
334 
335 class DoxygenContext::Private
336 {
337   public:
338     // TemplateStructIntf methods
get(const QCString & n) const339     TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
fields() const340     StringVector fields() const                  { return s_inst.fields(); }
341 
342   private:
343     // Property getters
version() const344     TemplateVariant version() const         { return getDoxygenVersion(); }
date() const345     TemplateVariant date() const            { return dateToString(TRUE); }
mathJaxCodeFile() const346     TemplateVariant mathJaxCodeFile() const { return m_mathJaxCodeFile.get(this); }
mathJaxMacros() const347     TemplateVariant mathJaxMacros() const   { return m_mathJaxMacros.get(this); }
348 
349   private:
createMathJaxCodeFile() const350     QCString createMathJaxCodeFile() const { return fileToString(Config_getString(MATHJAX_CODEFILE)); }
createMathJaxMacros() const351     QCString createMathJaxMacros() const   { return HtmlGenerator::getMathJaxMacros(); }
352     CachedItem<QCString, Private, &Private::createMathJaxCodeFile> m_mathJaxCodeFile;
353     CachedItem<QCString, Private, &Private::createMathJaxMacros>   m_mathJaxMacros;
354     static const PropertyMap<DoxygenContext::Private> s_inst;
355 };
356 
357 //%% struct Doxygen: global information
358 //%% {
359 const PropertyMap<DoxygenContext::Private> DoxygenContext::Private::s_inst {
360 {
361   //%% string version
362   { "version",         &Private::version         },
363   //%% string date
364   { "date",            &Private::date            },
365   //%% string maxJaxCodeFile
366   { "mathJaxCodeFile", &Private::mathJaxCodeFile },
367   //%% string maxJaxMacros
368   { "mathJaxMacros",   &Private::mathJaxMacros   }
369 } };
370 //%% }
371 
DoxygenContext()372 DoxygenContext::DoxygenContext() : p(std::make_unique<Private>())
373 {
374 }
375 
~DoxygenContext()376 DoxygenContext::~DoxygenContext()
377 {
378 }
379 
get(const QCString & n) const380 TemplateVariant DoxygenContext::get(const QCString &n) const
381 {
382   return p->get(n);
383 }
384 
fields() const385 StringVector DoxygenContext::fields() const
386 {
387   return p->fields();
388 }
389 
390 //------------------------------------------------------------------------
391 
392 class TranslateContext::Private
393 {
394   public:
395 
Private()396     Private()
397     {
398       m_javaOpt    = Config_getBool(OPTIMIZE_OUTPUT_JAVA);
399       m_fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN);
400       m_vhdlOpt    = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
401       m_sliceOpt   = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
402     }
403 
404     // TemplateStructIntf methods
get(const QCString & n) const405     TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
fields() const406     StringVector fields() const                  { return s_inst.fields(); }
407   private:
408 
409     // Handlers for properties with parameters
handleGeneratedAt(const TemplateVariantList & args) const410     TemplateVariant handleGeneratedAt(const TemplateVariantList &args) const
411     {
412       if (args.size()==2)
413       {
414         return theTranslator->trGeneratedAt(args[0].toString(),args[1].toString());
415       }
416       else
417       {
418         err("tr.generateAt should take two arguments, got %zu!\n",args.size());
419       }
420       return TemplateVariant();
421     }
handleInheritanceDiagramFor(const TemplateVariantList & args) const422     TemplateVariant handleInheritanceDiagramFor(const TemplateVariantList &args) const
423     {
424       if (args.size()==1)
425       {
426         return theTranslator->trClassDiagram(args[0].toString());
427       }
428       else
429       {
430         err("tr.inheritanceDiagramFor should take one argument, got %zu!\n",args.size());
431       }
432       return TemplateVariant();
433     }
handleCollaborationDiagramFor(const TemplateVariantList & args) const434     TemplateVariant handleCollaborationDiagramFor(const TemplateVariantList &args) const
435     {
436       if (args.size()==1)
437       {
438         return theTranslator->trCollaborationDiagram(args[0].toString());
439       }
440       else
441       {
442         err("tr.collaborationDiagramFor should take one argument, got %zu!\n",args.size());
443       }
444       return TemplateVariant();
445     }
handleDirDependencyGraphFor(const TemplateVariantList & args) const446     TemplateVariant handleDirDependencyGraphFor(const TemplateVariantList &args) const
447     {
448       if (args.size()==1)
449       {
450         return theTranslator->trDirDepGraph(args[0].toString());
451       }
452       else
453       {
454         err("tr.dirDependencyGraphFor should take one argument, got %zu!\n",args.size());
455       }
456       return TemplateVariant();
457     }
handleInheritsList(const TemplateVariantList & args) const458     TemplateVariant handleInheritsList(const TemplateVariantList &args) const
459     {
460       if (args.size()==1)
461       {
462         return theTranslator->trInheritsList(args[0].toInt());
463       }
464       else
465       {
466         err("tr.inheritsList should take one integer argument, got %zu!\n",args.size());
467       }
468       return TemplateVariant();
469     }
handleInheritedByList(const TemplateVariantList & args) const470     TemplateVariant handleInheritedByList(const TemplateVariantList &args) const
471     {
472       if (args.size()==1)
473       {
474         return theTranslator->trInheritedByList(args[0].toInt());
475       }
476       else
477       {
478         err("tr.inheritedByList should take one integer argument, got %zu!\n",args.size());
479       }
480       return TemplateVariant();
481     }
handleWriteList(const TemplateVariantList & args) const482     TemplateVariant handleWriteList(const TemplateVariantList &args) const
483     {
484       if (args.size()==1)
485       {
486         return theTranslator->trWriteList(args[0].toInt());
487       }
488       else
489       {
490         err("tr.*List should take one integer argument, got %zu!\n",args.size());
491       }
492       return TemplateVariant();
493     }
handleImplementedBy(const TemplateVariantList & args) const494     TemplateVariant handleImplementedBy(const TemplateVariantList &args) const
495     {
496       if (args.size()==1)
497       {
498         return theTranslator->trImplementedInList(args[0].toInt());
499       }
500       else
501       {
502         err("tr.implementedBy should take one integer argument, got %zu!\n",args.size());
503       }
504       return TemplateVariant();
505     }
handleReimplementedBy(const TemplateVariantList & args) const506     TemplateVariant handleReimplementedBy(const TemplateVariantList &args) const
507     {
508       if (args.size()==1)
509       {
510         return theTranslator->trReimplementedInList(args[0].toInt());
511       }
512       else
513       {
514         err("tr.reimplementedBy should take one integer argument, got %zu!\n",args.size());
515       }
516       return TemplateVariant();
517     }
handleSourceRefs(const TemplateVariantList & args) const518     TemplateVariant handleSourceRefs(const TemplateVariantList &args) const
519     {
520       if (args.size()==1)
521       {
522         return theTranslator->trReferences()+" "+theTranslator->trWriteList(args[0].toInt())+".";
523       }
524       else
525       {
526         err("tr.sourceRefs should take one integer argument, got %zu\n",args.size());
527       }
528       return TemplateVariant();
529     }
handleSourceRefBys(const TemplateVariantList & args) const530     TemplateVariant handleSourceRefBys(const TemplateVariantList &args) const
531     {
532       if (args.size()==1)
533       {
534         return theTranslator->trReferencedBy()+" "+theTranslator->trWriteList(args[0].toInt())+".";
535       }
536       else
537       {
538         err("tr.sourceRefBys should take one integer argument, got %zu\n",args.size());
539       }
540       return TemplateVariant();
541     }
handleIncludeDependencyGraph(const TemplateVariantList & args) const542     TemplateVariant handleIncludeDependencyGraph(const TemplateVariantList &args) const
543     {
544       if (args.size()==1)
545       {
546         return theTranslator->trInclDepGraph(args[0].toString());
547       }
548       else
549       {
550         err("tr.includeDependencyGraph should take one string argument, got %zu\n",args.size());
551       }
552       return TemplateVariant();
553     }
554 
555     // Property getters
generatedBy() const556     TemplateVariant generatedBy() const
557     {
558       return theTranslator->trGeneratedBy();
559     }
generatedAt() const560     TemplateVariant generatedAt() const
561     {
562       return TemplateVariant(std::bind(&Private::handleGeneratedAt,this,std::placeholders::_1));
563     }
inheritanceDiagramFor() const564     TemplateVariant inheritanceDiagramFor() const
565     {
566       return TemplateVariant(std::bind(&Private::handleInheritanceDiagramFor,this,std::placeholders::_1));
567     }
collaborationDiagramFor() const568     TemplateVariant collaborationDiagramFor() const
569     {
570       return TemplateVariant(std::bind(&Private::handleCollaborationDiagramFor,this,std::placeholders::_1));
571     }
dirDependencyGraphFor() const572     TemplateVariant dirDependencyGraphFor() const
573     {
574       return TemplateVariant(std::bind(&Private::handleDirDependencyGraphFor,this,std::placeholders::_1));
575     }
search() const576     TemplateVariant search() const
577     {
578       return theTranslator->trSearch();
579     }
mainPage() const580     TemplateVariant mainPage() const
581     {
582       return theTranslator->trMainPage();
583     }
classes() const584     TemplateVariant classes() const
585     {
586       return theTranslator->trClasses();
587       // TODO: VHDL: theTranslator->trVhdlType(VhdlDocGen::ENTITY,FALSE)
588       // TODO: Fortran: trDataTypes()
589     }
concepts() const590     TemplateVariant concepts() const
591     {
592       return theTranslator->trConcept(true,false);
593     }
conceptDefinition() const594     TemplateVariant conceptDefinition() const
595     {
596       return theTranslator->trConceptDefinition();
597     }
classList() const598     TemplateVariant classList() const
599     {
600       return theTranslator->trCompoundList();
601     }
classListDescription() const602     TemplateVariant classListDescription() const
603     {
604       return theTranslator->trCompoundListDescription();
605     }
classIndex() const606     TemplateVariant classIndex() const
607     {
608       return theTranslator->trCompoundIndex();
609     }
namespaceIndex() const610     TemplateVariant namespaceIndex() const
611     {
612       return theTranslator->trNamespaceIndex();
613     }
classHierarchy() const614     TemplateVariant classHierarchy() const
615     {
616       return theTranslator->trClassHierarchy();
617     }
classMembers() const618     TemplateVariant classMembers() const
619     {
620       return theTranslator->trCompoundMembers();
621     }
modules() const622     TemplateVariant modules() const
623     {
624       return theTranslator->trModules();
625     }
moduleIndex() const626     TemplateVariant moduleIndex() const
627     {
628       return theTranslator->trModuleIndex();
629     }
namespaces() const630     TemplateVariant namespaces() const
631     {
632       if (m_javaOpt || m_vhdlOpt)
633       {
634         return theTranslator->trPackages();
635       }
636       else if (m_fortranOpt || m_sliceOpt)
637       {
638         return theTranslator->trModules();
639       }
640       else
641       {
642         return theTranslator->trNamespaces();
643       }
644     }
files() const645     TemplateVariant files() const
646     {
647       return theTranslator->trFile(TRUE,FALSE);
648     }
fileIndex() const649     TemplateVariant fileIndex() const
650     {
651       return theTranslator->trFileIndex();
652     }
pages() const653     TemplateVariant pages() const
654     {
655       return theTranslator->trRelatedPages();
656     }
examples() const657     TemplateVariant examples() const
658     {
659       return theTranslator->trExamples();
660     }
namespaceList() const661     TemplateVariant namespaceList() const
662     {
663       if (m_javaOpt || m_vhdlOpt)
664       {
665         return theTranslator->trPackages();
666       }
667       else if (m_fortranOpt || m_sliceOpt)
668       {
669         return theTranslator->trModulesList();
670       }
671       else
672       {
673         return theTranslator->trNamespaceList();
674       }
675     }
namespaceMembers() const676     TemplateVariant namespaceMembers() const
677     {
678       if (m_javaOpt || m_vhdlOpt)
679       {
680         return theTranslator->trPackageMembers();
681       }
682       else if (m_fortranOpt || m_sliceOpt)
683       {
684         return theTranslator->trModulesMembers();
685       }
686       else
687       {
688         return theTranslator->trNamespaceMembers();
689       }
690     }
moduleDocumentation() const691     TemplateVariant moduleDocumentation() const
692     {
693       return theTranslator->trModuleDocumentation();
694     }
fileDocumentation() const695     TemplateVariant fileDocumentation() const
696     {
697       return theTranslator->trFileDocumentation();
698     }
fileList() const699     TemplateVariant fileList() const
700     {
701       return theTranslator->trFileList();
702     }
fileMembers() const703     TemplateVariant fileMembers() const
704     {
705       return theTranslator->trFileMembers();
706     }
fileMembersDescription() const707     TemplateVariant fileMembersDescription() const
708     {
709       static bool extractAll = Config_getBool(EXTRACT_ALL);
710       return theTranslator->trFileMembersDescription(extractAll);
711     }
namespaceMembersDescription() const712     TemplateVariant namespaceMembersDescription() const
713     {
714       static bool extractAll = Config_getBool(EXTRACT_ALL);
715       return theTranslator->trNamespaceMemberDescription(extractAll);
716     }
classHierarchyDescription() const717     TemplateVariant classHierarchyDescription() const
718     {
719       return theTranslator->trClassHierarchyDescription();
720     }
gotoGraphicalHierarchy() const721     TemplateVariant gotoGraphicalHierarchy() const
722     {
723       return theTranslator->trGotoGraphicalHierarchy();
724     }
gotoTextualHierarchy() const725     TemplateVariant gotoTextualHierarchy() const
726     {
727       return theTranslator->trGotoTextualHierarchy();
728     }
classMembersDescription() const729     TemplateVariant classMembersDescription() const
730     {
731       static bool extractAll = Config_getBool(EXTRACT_ALL);
732       static bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN);
733       if (fortranOpt)
734       {
735         return theTranslator->trCompoundMembersDescriptionFortran(extractAll);
736       }
737       else
738       {
739         return theTranslator->trCompoundMembersDescription(extractAll);
740       }
741     }
relatedPagesDesc() const742     TemplateVariant relatedPagesDesc() const
743     {
744       return theTranslator->trRelatedPagesDescription();
745     }
more() const746     TemplateVariant more() const
747     {
748       return theTranslator->trMore();
749     }
detailedDesc() const750     TemplateVariant detailedDesc() const
751     {
752       return theTranslator->trDetailedDescription();
753     }
inheritsList() const754     TemplateVariant inheritsList() const
755     {
756       return TemplateVariant(std::bind(&Private::handleInheritsList,this,std::placeholders::_1));
757     }
inheritedByList() const758     TemplateVariant inheritedByList() const
759     {
760       return TemplateVariant(std::bind(&Private::handleInheritedByList,this,std::placeholders::_1));
761     }
definedAtLineInSourceFile() const762     TemplateVariant definedAtLineInSourceFile() const
763     {
764       return theTranslator->trDefinedAtLineInSourceFile();
765     }
typeConstraints() const766     TemplateVariant typeConstraints() const
767     {
768       return theTranslator->trTypeConstraints();
769     }
exampleList() const770     TemplateVariant exampleList() const
771     {
772       return TemplateVariant(std::bind(&Private::handleWriteList,this,std::placeholders::_1));
773     }
listOfAllMembers() const774     TemplateVariant listOfAllMembers() const
775     {
776       return theTranslator->trListOfAllMembers();
777     }
memberList() const778     TemplateVariant memberList() const
779     {
780       return theTranslator->trMemberList();
781     }
theListOfAllMembers() const782     TemplateVariant theListOfAllMembers() const
783     {
784       return theTranslator->trThisIsTheListOfAllMembers();
785     }
incInheritedMembers() const786     TemplateVariant incInheritedMembers() const
787     {
788       return theTranslator->trIncludingInheritedMembers();
789     }
defineValue() const790     TemplateVariant defineValue() const
791     {
792       return theTranslator->trDefineValue();
793     }
initialValue() const794     TemplateVariant initialValue() const
795     {
796       return theTranslator->trInitialValue();
797     }
enumerationValues() const798     TemplateVariant enumerationValues() const
799     {
800       return theTranslator->trEnumerationValues();
801     }
implements() const802     TemplateVariant implements() const
803     {
804       return theTranslator->trImplementedFromList(1);
805     }
reimplements() const806     TemplateVariant reimplements() const
807     {
808       return theTranslator->trReimplementedFromList(1);
809     }
implementedBy() const810     TemplateVariant implementedBy() const
811     {
812       return TemplateVariant(std::bind(&Private::handleImplementedBy,this,std::placeholders::_1));
813     }
reimplementedBy() const814     TemplateVariant reimplementedBy() const
815     {
816       return TemplateVariant(std::bind(&Private::handleReimplementedBy,this,std::placeholders::_1));
817     }
sourceRefs() const818     TemplateVariant sourceRefs() const
819     {
820       return TemplateVariant(std::bind(&Private::handleSourceRefs,this,std::placeholders::_1));
821     }
sourceRefBys() const822     TemplateVariant sourceRefBys() const
823     {
824       return TemplateVariant(std::bind(&Private::handleSourceRefBys,this,std::placeholders::_1));
825     }
callGraph() const826     TemplateVariant callGraph() const
827     {
828       return theTranslator->trCallGraph();
829     }
callerGraph() const830     TemplateVariant callerGraph() const
831     {
832       return theTranslator->trCallerGraph();
833     }
referencedByRelation() const834     TemplateVariant referencedByRelation() const
835     {
836       return theTranslator->trReferencedBy();
837     }
referencesRelation() const838     TemplateVariant referencesRelation() const
839     {
840       return theTranslator->trReferences();
841     }
inheritedFrom() const842     TemplateVariant inheritedFrom() const
843     {
844       return theTranslator->trInheritedFrom("@0","@1");
845     }
additionalInheritedMembers() const846     TemplateVariant additionalInheritedMembers() const
847     {
848       return theTranslator->trAdditionalInheritedMembers();
849     }
includeDependencyGraph() const850     TemplateVariant includeDependencyGraph() const
851     {
852       return TemplateVariant(std::bind(&Private::handleIncludeDependencyGraph,this,std::placeholders::_1));
853     }
includedByDependencyGraph() const854     TemplateVariant includedByDependencyGraph() const
855     {
856       return theTranslator->trInclByDepGraph();
857     }
gotoSourceCode() const858     TemplateVariant gotoSourceCode() const
859     {
860       return theTranslator->trGotoSourceCode();
861     }
gotoDocumentation() const862     TemplateVariant gotoDocumentation() const
863     {
864       return theTranslator->trGotoDocumentation();
865     }
constantgroups() const866     TemplateVariant constantgroups() const
867     {
868       return theTranslator->trConstantGroups();
869     }
classDocumentation() const870     TemplateVariant classDocumentation() const
871     {
872       return theTranslator->trClassDocumentation();
873     }
namespaceDocumentation() const874     TemplateVariant namespaceDocumentation() const
875     {
876       return theTranslator->trNamespaceDocumentation();
877     }
compoundMembers() const878     TemplateVariant compoundMembers() const
879     {
880       return theTranslator->trCompoundMembers();
881     }
detailLevel() const882     TemplateVariant detailLevel() const
883     {
884       return theTranslator->trDetailLevel();
885     }
fileListDescription() const886     TemplateVariant fileListDescription() const
887     {
888       bool extractAll = Config_getBool(EXTRACT_ALL);
889       return theTranslator->trFileListDescription(extractAll);
890     }
modulesDescription() const891     TemplateVariant modulesDescription() const
892     {
893       bool extractAll = Config_getBool(EXTRACT_ALL);
894       return theTranslator->trModulesListDescription(extractAll);
895     }
namespaceListDescription() const896     TemplateVariant namespaceListDescription() const
897     {
898       bool extractAll = Config_getBool(EXTRACT_ALL);
899       return theTranslator->trNamespaceListDescription(extractAll);
900     }
conceptListDescription() const901     TemplateVariant conceptListDescription() const
902     {
903       bool extractAll = Config_getBool(EXTRACT_ALL);
904       return theTranslator->trConceptListDescription(extractAll);
905     }
directories() const906     TemplateVariant directories() const
907     {
908       return theTranslator->trDirectories();
909     }
all() const910     TemplateVariant all() const
911     {
912       return theTranslator->trAll();
913     }
functions() const914     TemplateVariant functions() const
915     {
916       static bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN);
917       static bool vhdlOpt    = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
918       return fortranOpt ? theTranslator->trSubprograms()     :
919              vhdlOpt    ? theTranslator->trFunctionAndProc() :
920                           theTranslator->trFunctions();
921     }
variables() const922     TemplateVariant variables() const
923     {
924       static bool sliceOpt   = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
925       return sliceOpt ? theTranslator->trConstants() : theTranslator->trVariables();
926     }
typedefs() const927     TemplateVariant typedefs() const
928     {
929       return theTranslator->trTypedefs();
930     }
enums() const931     TemplateVariant enums() const
932     {
933       return theTranslator->trEnumerations();
934     }
properties() const935     TemplateVariant properties() const
936     {
937       return theTranslator->trProperties();
938     }
events() const939     TemplateVariant events() const
940     {
941       return theTranslator->trEvents();
942     }
related() const943     TemplateVariant related() const
944     {
945       return theTranslator->trRelatedFunctions();
946     }
macros() const947     TemplateVariant macros() const
948     {
949       return theTranslator->trDefines();
950     }
loading() const951     TemplateVariant loading() const
952     {
953       return theTranslator->trLoading();
954     }
searching() const955     TemplateVariant searching() const
956     {
957       return theTranslator->trSearching();
958     }
noMatches() const959     TemplateVariant noMatches() const
960     {
961       return theTranslator->trNoMatches();
962     }
enumName() const963     TemplateVariant enumName() const
964     {
965       return theTranslator->trEnumName();
966     }
enumValue() const967     TemplateVariant enumValue() const
968     {
969       return theTranslator->trEnumValue();
970     }
referenceManual() const971     TemplateVariant referenceManual() const
972     {
973       return theTranslator->trReferenceManual();
974     }
index() const975     TemplateVariant index() const
976     {
977       return theTranslator->trRTFGeneralIndex();
978     }
panelSyncOn() const979     TemplateVariant panelSyncOn() const
980     {
981       return theTranslator->trPanelSynchronisationTooltip(FALSE);
982     }
panelSyncOff() const983     TemplateVariant panelSyncOff() const
984     {
985       return theTranslator->trPanelSynchronisationTooltip(TRUE);
986     }
providedByCategory() const987     TemplateVariant providedByCategory() const
988     {
989       return theTranslator->trProvidedByCategory();
990     }
extendsClass() const991     TemplateVariant extendsClass() const
992     {
993       return theTranslator->trExtendsClass();
994     }
examplesDescription() const995     TemplateVariant examplesDescription() const
996     {
997       return theTranslator->trExamplesDescription();
998     }
langString() const999     TemplateVariant langString() const
1000     {
1001       return HtmlHelp::getLanguageString();
1002     }
code() const1003     TemplateVariant code() const
1004     {
1005       return theTranslator->trCode();
1006     }
1007 
1008   private:
1009     bool m_javaOpt;
1010     bool m_fortranOpt;
1011     bool m_vhdlOpt;
1012     bool m_sliceOpt;
1013     static const PropertyMap<TranslateContext::Private> s_inst;
1014 };
1015 
1016 //%% struct Translator: translation methods
1017 //%% {
1018 const PropertyMap<TranslateContext::Private> TranslateContext::Private::s_inst {
1019 {
1020   //%% string generatedBy
1021   {  "generatedBy",       &Private::generatedBy },
1022   //%% string generatedAt
1023   {  "generatedAt",       &Private::generatedAt },
1024   //%% string search
1025   {  "search",            &Private::search },
1026   //%% string mainPage
1027   {  "mainPage",          &Private::mainPage },
1028   //%% string classes
1029   {  "classes",           &Private::classes },
1030   //%% string classList
1031   {  "classList",         &Private::classList },
1032   //%% string classListDescription
1033   {  "classListDescription", &Private::classListDescription },
1034   //%% string classIndex
1035   {  "classIndex",        &Private::classIndex },
1036   //%% string concepts
1037   {  "concepts",          &Private::concepts },
1038   //%% string conceptDefintion
1039   {  "conceptDefinition", &Private::conceptDefinition },
1040   //%% string namespaceIndex
1041   {  "namespaceIndex",    &Private::namespaceIndex },
1042   //%% string classHierarchy
1043   {  "classHierarchy",    &Private::classHierarchy },
1044   //%% string classMembers
1045   {  "classMembers",      &Private::classMembers },
1046   //%% string classMembersDescription
1047   {  "classMembersDescription",&Private::classMembersDescription },
1048   //%% string modules
1049   {  "modules",           &Private::modules },
1050   //%% string moduleIndex
1051   {  "moduleIndex",       &Private::moduleIndex },
1052   //%% string namespaces
1053   {  "namespaces",        &Private::namespaces },
1054   //%% string fileIndex
1055   {  "fileIndex",         &Private::fileIndex },
1056   //%% string files
1057   {  "files",             &Private::files },
1058   //%% string pages
1059   {  "pages",             &Private::pages },
1060   //%% string examples
1061   {  "examples",          &Private::examples },
1062   //%% string namespaceList
1063   {  "namespaceList",     &Private::namespaceList },
1064   //%% string namespaceMembers
1065   {  "namespaceMembers",  &Private::namespaceMembers },
1066   //%% string fileList
1067   {  "fileList",          &Private::fileList },
1068   //%% string fileMembers
1069   {  "fileMembers",       &Private::fileMembers },
1070   //%% string fileMembersDescription
1071   {  "fileMembersDescription", &Private::fileMembersDescription },
1072   //%% string relatedPagesDescription
1073   {  "relatedPagesDesc",  &Private::relatedPagesDesc },
1074   //%% string more
1075   {  "more",              &Private::more },
1076   //%% string detailedDescription
1077   {  "detailedDesc",      &Private::detailedDesc },
1078   //%% string inheritanceDiagramFor
1079   {  "inheritanceDiagramFor", &Private::inheritanceDiagramFor },
1080   //%% string collaborationDiagramFor
1081   {  "collaborationDiagramFor", &Private::collaborationDiagramFor },
1082   //%% markerstring inheritsList
1083   {  "inheritsList",      &Private::inheritsList },
1084   //%% markerstring inheritedByList
1085   {  "inheritedByList",   &Private::inheritedByList },
1086   //%% markerstring definedAtLineInSourceFile
1087   {  "definedAtLineInSourceFile", &Private::definedAtLineInSourceFile },
1088   //%% string typeConstraints
1089   {  "typeConstraints",   &Private::typeConstraints },
1090   //%% string exampleList
1091   {  "exampleList",       &Private::exampleList },
1092   //%% string listOfAllMembers
1093   {  "listOfAllMembers",  &Private::listOfAllMembers },
1094   //%% string memberList
1095   {  "memberList",        &Private::memberList },
1096   //%% string theListOfAllMembers
1097   {  "theListOfAllMembers",&Private::theListOfAllMembers },
1098   //%% string incInheritedMembers
1099   {  "incInheritedMembers",&Private::incInheritedMembers },
1100   //%% string defineValue
1101   {  "defineValue",        &Private::defineValue },
1102   //%% string initialValue
1103   {  "initialValue",       &Private::initialValue },
1104   //%% markerstring implements
1105   {  "implements",         &Private::implements },
1106   //%% markerstring reimplements
1107   {  "reimplements",       &Private::reimplements },
1108   //%% markerstring implementedBy
1109   {  "implementedBy",      &Private::implementedBy },
1110   //%% markerstring reimplementedBy
1111   {  "reimplementedBy",    &Private::reimplementedBy },
1112   //%% markerstring sourceRefs
1113   {  "sourceRefs",         &Private::sourceRefs },
1114   //%% markerstring sourceRefBys
1115   {  "sourceRefBys",       &Private::sourceRefBys },
1116   //%% string callGraph
1117   {  "callGraph",          &Private::callGraph },
1118   //%% string callerGraph
1119   {  "callerGraph",        &Private::callerGraph },
1120   //%% string referencedByRelation
1121   {  "referencedByRelation", &Private::referencedByRelation },
1122   //%% string referencesRelation
1123   {  "referencesRelation",   &Private::referencesRelation },
1124   //%% markerstring inheritedFrom
1125   {  "inheritedFrom",      &Private::inheritedFrom },
1126   //%% string additionalInheritedMembers
1127   {  "additionalInheritedMembers",&Private::additionalInheritedMembers },
1128   //%% string includeDependencyGraph:container_name
1129   {  "includeDependencyGraph",&Private::includeDependencyGraph },
1130   //%% string includedByDependencyGraph
1131   {  "includedByDependencyGraph",&Private::includedByDependencyGraph },
1132   //%% string gotoSourceCode
1133   {  "gotoSourceCode",     &Private::gotoSourceCode },
1134   //%% string gotoDocumentation
1135   {  "gotoDocumentation",  &Private::gotoDocumentation },
1136   //%% string constantgroups
1137   {  "constantgroups",     &Private::constantgroups },
1138   //%% string classDocumentation
1139   {  "classDocumentation", &Private::classDocumentation },
1140   //%% string namespaceDocumentation
1141   {  "namespaceDocumentation", &Private::namespaceDocumentation },
1142   //%% string moduleDocumentation
1143   {  "moduleDocumentation",&Private::moduleDocumentation },
1144   //%% string fileDocumentation
1145   {  "fileDocumentation",  &Private::fileDocumentation },
1146   //%% string compoundMembers
1147   {  "compoundMembers",    &Private::compoundMembers },
1148   //%% string detailLevel
1149   {  "detailLevel",        &Private::detailLevel },
1150   //%% string fileListDescription
1151   {  "fileListDescription",&Private::fileListDescription },
1152   //%% string namespaceListDescription
1153   {  "namespaceListDescription",&Private::namespaceListDescription },
1154   //%% string conceptListDescription
1155   {  "conceptListDescription",&Private::conceptListDescription },
1156   //%% string directories
1157   {  "directories",        &Private::directories },
1158   //%% string moduleDescription
1159   {  "modulesDescription", &Private::modulesDescription },
1160   //%% string all
1161   {  "all",                &Private::all },
1162   //%% string functions
1163   {  "functions",          &Private::functions },
1164   //%% string variables
1165   {  "variables",          &Private::variables },
1166   //%% string typedefs
1167   {  "typedefs",           &Private::typedefs },
1168   //%% string enums
1169   {  "enums",              &Private::enums },
1170   //%% string enumValues
1171   {  "enumValues",         &Private::enumerationValues },
1172   //%% string properties
1173   {  "properties",         &Private::properties },
1174   //%% string events
1175   {  "events",             &Private::events },
1176   //%% string related
1177   {  "related",            &Private::related },
1178   //%% string macros
1179   {  "macros",             &Private::macros },
1180   //%% string namespaceMembersDescription
1181   {  "namespaceMembersDescription",&Private::namespaceMembersDescription },
1182   //%% string classHierarchyDescription
1183   {  "classHierarchyDescription",&Private::classHierarchyDescription },
1184   //%% string gotoGraphicalHierarchy
1185   {  "gotoGraphicalHierarchy",&Private::gotoGraphicalHierarchy },
1186   //%% string gotoTextualHierarchy
1187   {  "gotoTextualHierarchy",&Private::gotoTextualHierarchy },
1188   //%% string loading
1189   {  "loading",            &Private::loading },
1190   //%% string searching
1191   {  "searching",          &Private::searching },
1192   //%% string noMatches
1193   {  "noMatches",          &Private::noMatches },
1194   //%% string enumValue
1195   {  "enumValue",          &Private::enumValue },
1196   //%% string enumName
1197   {  "enumName",           &Private::enumName },
1198   //%% string referenceManual
1199   {  "referenceManual",    &Private::referenceManual },
1200   //%% string index
1201   {  "index",              &Private::index },
1202   //%% string panelSyncOn
1203   {  "panelSyncOn",        &Private::panelSyncOn },
1204   //%% string panelSyncOff
1205   {  "panelSyncOff",       &Private::panelSyncOff },
1206   //%% string dirDependencyGraph
1207   {  "dirDependencyGraphFor", &Private::dirDependencyGraphFor },
1208   //%% string providedByCategory
1209   {  "providedByCategory", &Private::providedByCategory },
1210   //%% string extendsClass
1211   {  "extendsClass",       &Private::extendsClass },
1212   //%% string examplesDescription
1213   {  "examplesDescription",&Private::examplesDescription },
1214   //%% string langstring
1215   {  "langString",         &Private::langString },
1216   //%% string code
1217   {  "code",               &Private::code }
1218 } };
1219 //%% }
1220 
TranslateContext()1221 TranslateContext::TranslateContext() : p(std::make_unique<Private>())
1222 {
1223 }
1224 
~TranslateContext()1225 TranslateContext::~TranslateContext()
1226 {
1227 }
1228 
get(const QCString & n) const1229 TemplateVariant TranslateContext::get(const QCString &n) const
1230 {
1231   return p->get(n);
1232 }
1233 
fields() const1234 StringVector TranslateContext::fields() const
1235 {
1236   return p->fields();
1237 }
1238 
1239 //------------------------------------------------------------------------------------------
1240 
parseDoc(const Definition * def,const QCString & file,int line,const QCString & relPath,const QCString & docStr,bool isBrief)1241 static TemplateVariant parseDoc(const Definition *def,const QCString &file,int line,
1242                                 const QCString &relPath,const QCString &docStr,bool isBrief)
1243 {
1244   TemplateVariant result;
1245   std::unique_ptr<IDocParser> parser { createDocParser() };
1246   std::unique_ptr<DocRoot>    root   { validatingParseDoc(
1247                                        *parser.get(),file,line,def,0,docStr,TRUE,FALSE,
1248                                        QCString(),isBrief,FALSE,Config_getBool(MARKDOWN_SUPPORT))
1249                                      };
1250   TextStream ts;
1251   switch (g_globals.outputFormat)
1252   {
1253     case ContextOutputFormat_Html:
1254       {
1255         HtmlCodeGenerator codeGen(ts,relPath);
1256         HtmlDocVisitor visitor(ts,codeGen,def);
1257         root->accept(&visitor);
1258       }
1259       break;
1260     case ContextOutputFormat_Latex:
1261       {
1262         LatexCodeGenerator codeGen(ts,relPath,file);
1263         LatexDocVisitor visitor(ts,codeGen,def->getDefFileExtension(),FALSE);
1264         root->accept(&visitor);
1265       }
1266       break;
1267     // TODO: support other generators
1268     default:
1269       err("context.cpp: output format not yet supported\n");
1270       break;
1271   }
1272   bool isEmpty = root->isEmpty();
1273   if (isEmpty)
1274     result = "";
1275   else
1276     result = TemplateVariant(ts.str().c_str(),TRUE);
1277   return result;
1278 }
1279 
parseCode(const Definition * d,const QCString & scopeName,const QCString & relPath,const QCString & code,int startLine=-1,int endLine=-1,bool showLineNumbers=FALSE)1280 static TemplateVariant parseCode(const Definition *d,const QCString &scopeName,const QCString &relPath,
1281                                  const QCString &code,int startLine=-1,int endLine=-1,bool showLineNumbers=FALSE)
1282 {
1283   auto intf = Doxygen::parserManager->getCodeParser(d->getDefFileExtension());
1284   intf->resetCodeParserState();
1285   TextStream t;
1286   switch (g_globals.outputFormat)
1287   {
1288     case ContextOutputFormat_Html:
1289       {
1290         HtmlCodeGenerator codeGen(t,relPath);
1291         intf->parseCode(codeGen,scopeName,code,d->getLanguage(),FALSE,QCString(),d->getBodyDef(),
1292             startLine,endLine,TRUE,toMemberDef(d),showLineNumbers,d);
1293       }
1294       break;
1295     case ContextOutputFormat_Latex:
1296       {
1297         LatexCodeGenerator codeGen(t,relPath,d->docFile());
1298         intf->parseCode(codeGen,scopeName,code,d->getLanguage(),FALSE,QCString(),d->getBodyDef(),
1299             startLine,endLine,TRUE,toMemberDef(d),showLineNumbers,d);
1300       }
1301       break;
1302     // TODO: support other generators
1303     default:
1304       err("context.cpp: output format not yet supported\n");
1305       break;
1306   }
1307   return TemplateVariant(t.str(),TRUE);
1308 }
1309 
parseCode(const FileDef * fd,const QCString & relPath)1310 static TemplateVariant parseCode(const FileDef *fd,const QCString &relPath)
1311 {
1312   static bool filterSourceFiles = Config_getBool(FILTER_SOURCE_FILES);
1313   auto intf = Doxygen::parserManager->getCodeParser(fd->getDefFileExtension());
1314   intf->resetCodeParserState();
1315   TextStream t;
1316   switch (g_globals.outputFormat)
1317   {
1318     case ContextOutputFormat_Html:
1319       {
1320         HtmlCodeGenerator codeGen(t,relPath);
1321         intf->parseCode(codeGen,QCString(),
1322               fileToString(fd->absFilePath(),filterSourceFiles,TRUE), // the sources
1323               fd->getLanguage(),  // lang
1324               FALSE,              // isExampleBlock
1325               QCString(),         // exampleName
1326               const_cast<FileDef*>(fd),  // fileDef, TODO: should be const
1327               -1,                 // startLine
1328               -1,                 // endLine
1329               FALSE,              // inlineFragment
1330               0,                  // memberDef
1331               TRUE,               // showLineNumbers
1332               0,                  // searchCtx
1333               TRUE                // collectXRefs, TODO: should become FALSE
1334               );
1335       }
1336       break;
1337     case ContextOutputFormat_Latex:
1338       {
1339         LatexCodeGenerator codeGen(t,relPath,fd->docFile());
1340         intf->parseCode(codeGen,QCString(),
1341               fileToString(fd->absFilePath(),filterSourceFiles,TRUE), // the sources
1342               fd->getLanguage(),  // lang
1343               FALSE,              // isExampleBlock
1344               QCString(),         // exampleName
1345               const_cast<FileDef*>(fd),  // fileDef, TODO: should be const
1346               -1,                 // startLine
1347               -1,                 // endLine
1348               FALSE,              // inlineFragment
1349               0,                  // memberDef
1350               TRUE,               // showLineNumbers
1351               0,                  // searchCtx
1352               TRUE                // collectXRefs, TODO: should become FALSE
1353               );
1354       }
1355       break;
1356     // TODO: support other generators
1357     default:
1358       err("context.cpp: output format not yet supported\n");
1359       break;
1360   }
1361   return TemplateVariant(t.str().c_str(),TRUE);
1362 }
1363 
1364 //------------------------------------------------------------------------
1365 
1366 template<typename T>
1367 class DefinitionContext
1368 {
1369   public:
DefinitionContext(const Definition * d)1370     DefinitionContext(const Definition *d) : m_def(d)
1371     {
1372       assert(d!=0);
1373 
1374       if (m_def && !m_def->getSourceFileBase().isEmpty())
1375       {
1376         TemplateStructIntfPtr lineLink = TemplateImmutableStruct::alloc(
1377         {
1378           { "text",              TemplateVariant(m_def->getStartBodyLine())  },
1379           { "isLinkable",        TemplateVariant(TRUE)                       },
1380           { "fileName",          TemplateVariant(m_def->getSourceFileBase()) },
1381           { "anchor",            TemplateVariant(m_def->getSourceAnchor())   },
1382           { "isReference",       TemplateVariant(FALSE)                      },
1383           { "externalReference", TemplateVariant("")                         }
1384         });
1385 
1386         QCString text = m_def->definitionType()==Definition::TypeFile ? m_def->name() :
1387                                                   m_def->getBodyDef() ? m_def->getBodyDef()->name() :
1388                                                                         m_def->displayName(TRUE);
1389 
1390         TemplateStructIntfPtr fileLink = TemplateImmutableStruct::alloc(
1391         {
1392           { "text",              TemplateVariant(text)                       },
1393           { "isLinkable",        TemplateVariant(TRUE)                       },
1394           { "fileName",          TemplateVariant(m_def->getSourceFileBase()) },
1395           { "anchor",            TemplateVariant("")                         },
1396           { "isReference",       TemplateVariant(FALSE)                      },
1397           { "externalReference", TemplateVariant("")                         }
1398         });
1399 
1400         m_sourceDef = TemplateImmutableList::alloc( { lineLink, fileLink });
1401       }
1402       else
1403       {
1404         m_sourceDef = TemplateImmutableList::alloc( {} );
1405       }
1406     }
~DefinitionContext()1407     virtual ~DefinitionContext() {}
1408 
1409   protected:
1410     // Property getters
fileName() const1411     TemplateVariant fileName() const            { return m_def->getOutputFileBase(); }
anchor() const1412     TemplateVariant anchor() const              { return m_def->anchor(); }
sourceFileName() const1413     TemplateVariant sourceFileName() const      { return m_def->getSourceFileBase(); }
isLinkable() const1414     TemplateVariant isLinkable() const          { return m_def->isLinkable(); }
isLinkableInProject() const1415     TemplateVariant isLinkableInProject() const { return m_def->isLinkableInProject(); }
name() const1416     TemplateVariant name() const                { return m_def->displayName(TRUE); }
bareName() const1417     TemplateVariant bareName() const            { return m_def->displayName(FALSE); }
details() const1418     TemplateVariant details() const             { return m_cachable.details.get(this); }
brief() const1419     TemplateVariant brief() const               { return m_cachable.brief.get(this); }
inbodyDocs() const1420     TemplateVariant inbodyDocs() const          { return m_cachable.inbodyDocs.get(this); }
dynSectionId() const1421     TemplateVariant dynSectionId() const        { return g_globals.dynSectionId; }
sourceDef() const1422     TemplateVariant sourceDef() const           { return std::static_pointer_cast<TemplateListIntf>(m_sourceDef); }
navigationPath() const1423     TemplateVariant navigationPath() const      { return m_cachable.navPath.get(this); }
partOfGroups() const1424     TemplateVariant partOfGroups() const        { return m_cachable.partOfGroups.get(this); }
isReference() const1425     TemplateVariant isReference() const         { return m_def->isReference(); }
externalReference() const1426     TemplateVariant externalReference() const   { return m_def->externalReference(relPathAsString()); }
language() const1427     TemplateVariant language() const
1428     {
1429       SrcLangExt lang = m_def->getLanguage();
1430       QCString result = "unknown";
1431       switch (lang)
1432       {
1433         case SrcLangExt_Unknown:  break;
1434         case SrcLangExt_IDL:      result="idl";      break;
1435         case SrcLangExt_Java:     result="java";     break;
1436         case SrcLangExt_CSharp:   result="csharp";   break;
1437         case SrcLangExt_D:        result="d";        break;
1438         case SrcLangExt_PHP:      result="php";      break;
1439         case SrcLangExt_ObjC:     result="objc";     break;
1440         case SrcLangExt_Cpp:      result="cpp";      break;
1441         case SrcLangExt_JS:       result="js";       break;
1442         case SrcLangExt_Python:   result="python";   break;
1443         case SrcLangExt_Fortran:  result="fortran";  break;
1444         case SrcLangExt_VHDL:     result="vhdl";     break;
1445         case SrcLangExt_XML:      result="xml";      break;
1446         case SrcLangExt_SQL:      result="sql";      break;
1447         case SrcLangExt_Markdown: result="markdown"; break;
1448         case SrcLangExt_Slice:    result="slice";    break;
1449         case SrcLangExt_Lex:      result="lex";      break;
1450       }
1451       return result;
1452     }
compoundKind() const1453     TemplateVariant compoundKind() const
1454     {
1455       QCString result = "unspecified";
1456       switch (m_def->definitionType())
1457       {
1458         case Definition::TypeClass:     result="class";     break;
1459         case Definition::TypeFile:      result="file";      break;
1460         case Definition::TypeNamespace: result="namespace"; break;
1461         case Definition::TypeGroup:     result="module";    break;
1462         case Definition::TypePackage:   result="package";   break;
1463         case Definition::TypePage:      result="page";      break;
1464         case Definition::TypeDir:       result="dir";       break;
1465         case Definition::TypeConcept:   result="concept";   break;
1466         case Definition::TypeMember:                        break;
1467       }
1468       return result;
1469     }
1470 
1471   protected:
1472 
relPathAsString() const1473     QCString relPathAsString() const
1474     {
1475       static bool createSubdirs = Config_getBool(CREATE_SUBDIRS);
1476       return createSubdirs ? QCString("../../") : QCString("");
1477     }
relPath() const1478     virtual TemplateVariant relPath() const     { return relPathAsString(); }
1479 
1480 
1481   private:
1482 
createDetails() const1483     TemplateVariant createDetails() const
1484     {
1485       return TemplateVariant(parseDoc(m_def,m_def->docFile(),m_def->docLine(),
1486                                       relPathAsString(),m_def->documentation(),FALSE));
1487     }
createBrief() const1488     TemplateVariant createBrief() const
1489     {
1490       if (m_def->hasBriefDescription())
1491       {
1492         return TemplateVariant(parseDoc(m_def,m_def->briefFile(),m_def->briefLine(),
1493                                relPathAsString(),m_def->briefDescription(),TRUE));
1494       }
1495       else
1496       {
1497         return TemplateVariant("");
1498       }
1499     }
createInbodyDocs() const1500     TemplateVariant createInbodyDocs() const
1501     {
1502       if (!m_def->inbodyDocumentation().isEmpty())
1503       {
1504         return TemplateVariant(parseDoc(m_def,m_def->inbodyFile(),m_def->inbodyLine(),
1505                                         relPathAsString(),m_def->inbodyDocumentation(),FALSE));
1506       }
1507       else
1508       {
1509         return TemplateVariant("");
1510       }
1511     }
fillPath(const Definition * def,TemplateVariantList & list) const1512     void fillPath(const Definition *def,TemplateVariantList &list) const
1513     {
1514       const Definition *outerScope = def->getOuterScope();
1515       Definition::DefType type = def->definitionType();
1516       if (outerScope && outerScope!=Doxygen::globalScope)
1517       {
1518         fillPath(outerScope,list);
1519       }
1520       else if (type==Definition::TypeFile && (toFileDef(def))->getDirDef())
1521       {
1522         fillPath((toFileDef(def))->getDirDef(),list);
1523       }
1524       list.push_back(NavPathElemContext::alloc(def));
1525     }
createNavigationPath() const1526     TemplateListIntfPtr createNavigationPath() const
1527     {
1528       TemplateVariantList list;
1529       if (m_def->getOuterScope() && m_def->getOuterScope()!=Doxygen::globalScope)
1530       {
1531         fillPath(m_def,list);
1532       }
1533       else if (m_def->definitionType()==Definition::TypeFile && (toFileDef(m_def))->getDirDef())
1534       {
1535         fillPath((toFileDef(m_def))->getDirDef(),list);
1536       }
1537       return TemplateImmutableList::alloc(list);
1538     }
createPartOfGroups() const1539     TemplateListIntfPtr createPartOfGroups() const
1540     {
1541       TemplateVariantList list;
1542       list.reserve(m_def->partOfGroups().size());
1543       for (const auto &gd : m_def->partOfGroups())
1544       {
1545         list.push_back(ModuleContext::alloc(gd));
1546       }
1547       return TemplateImmutableList::alloc(list);
1548     }
1549 
1550   protected:
1551     struct Cachable : public Definition::Cookie
1552     {
1553       using DC = DefinitionContext<T>;
1554       CachedItem<TemplateVariant,     DC, &DC::createDetails>        details;
1555       CachedItem<TemplateVariant,     DC, &DC::createBrief>          brief;
1556       CachedItem<TemplateVariant,     DC, &DC::createInbodyDocs>     inbodyDocs;
1557       CachedItem<TemplateListIntfPtr, DC, &DC::createNavigationPath> navPath;
1558       CachedItem<TemplateListIntfPtr, DC, &DC::createPartOfGroups>   partOfGroups;
1559     };
1560 
1561   private:
1562     Cachable m_cachable;
1563     const Definition *m_def;
1564     TemplateListIntfPtr m_sourceDef;
1565     static const PropertyMap< DefinitionContext<T> > s_baseProperties;
1566 };
1567 
1568 //%% struct Definition: shared info for all symbols
1569 //%% {
1570 #define BASE_PROPERTIES                                     \
1571   {  "name",               &Private::name                }, \
1572   {  "bareName",           &Private::bareName            }, \
1573   {  "relPath",            &Private::relPath             }, \
1574   {  "fileName",           &Private::fileName            }, \
1575   {  "anchor",             &Private::anchor              }, \
1576   {  "details",            &Private::details             }, \
1577   {  "brief",              &Private::brief               }, \
1578   {  "inbodyDocs",         &Private::inbodyDocs          }, \
1579   {  "sourceFileName",     &Private::sourceFileName      }, \
1580   {  "isLinkable",         &Private::isLinkable          }, \
1581   {  "isLinkableInProject",&Private::isLinkableInProject }, \
1582   {  "dynSectionId",       &Private::dynSectionId        }, \
1583   {  "language",           &Private::language            }, \
1584   {  "sourceDef",          &Private::sourceDef           }, \
1585   {  "navigationPath",     &Private::navigationPath      }, \
1586   {  "partOfGroups",       &Private::partOfGroups        }, \
1587   {  "compoundKind",       &Private::compoundKind        }, \
1588   {  "isReference",        &Private::isReference         }, \
1589   {  "externalReference",  &Private::externalReference   }
1590 //%% }
1591 
1592 
1593 //------------------------------------------------------------------------
1594 
1595 class IncludeInfoContext::Private
1596 {
1597   public:
Private(const IncludeInfo * info,SrcLangExt lang)1598     Private(const IncludeInfo *info,SrcLangExt lang) :
1599       m_info(info),
1600       m_lang(lang)
1601     {
1602     }
get(const QCString & n) const1603     TemplateVariant get(const QCString &n) const
1604     {
1605       return s_inst.get(this,n);
1606     }
fields() const1607     StringVector fields() const
1608     {
1609       return s_inst.fields();
1610     }
isLocal() const1611     TemplateVariant isLocal() const
1612     {
1613       bool isIDLorJava = m_lang==SrcLangExt_IDL || m_lang==SrcLangExt_Java;
1614       return m_info->local || isIDLorJava;
1615     }
isImport() const1616     TemplateVariant isImport() const
1617     {
1618       return m_info->imported || m_lang==SrcLangExt_ObjC;
1619     }
file() const1620     TemplateVariant file() const
1621     {
1622       return m_fileContext.get(this);
1623     }
name() const1624     TemplateVariant name() const
1625     {
1626       return m_info->includeName;
1627     }
1628   private:
1629     const IncludeInfo *m_info;
createFileContext() const1630     TemplateVariant createFileContext() const
1631     {
1632       return m_info && m_info->fileDef ?
1633              TemplateVariant(FileContext::alloc(m_info->fileDef)) :
1634              TemplateVariant(false);
1635     }
1636     CachedItem<TemplateVariant, Private, &Private::createFileContext> m_fileContext;
1637     SrcLangExt m_lang;
1638     static const PropertyMap<IncludeInfoContext::Private> s_inst;
1639 };
1640 
1641 //%% struct IncludeInfo: include file information
1642 //%% {
1643 const PropertyMap<IncludeInfoContext::Private> IncludeInfoContext::Private::s_inst {
1644   {  "file",&Private::file },
1645   {  "name",&Private::name },
1646   {  "isImport",&Private::isImport },
1647   {  "isLocal",&Private::isLocal }
1648 };
1649 //%% }
1650 
IncludeInfoContext(const IncludeInfo * info,SrcLangExt lang)1651 IncludeInfoContext::IncludeInfoContext(const IncludeInfo *info,SrcLangExt lang) : p(std::make_unique<Private>(info,lang))
1652 {
1653 }
1654 
~IncludeInfoContext()1655 IncludeInfoContext::~IncludeInfoContext()
1656 {
1657 }
1658 
get(const QCString & n) const1659 TemplateVariant IncludeInfoContext::get(const QCString &n) const
1660 {
1661   return p->get(n);
1662 }
1663 
fields() const1664 StringVector IncludeInfoContext::fields() const
1665 {
1666   return p->fields();
1667 }
1668 
1669 //%% }
1670 
1671 //------------------------------------------------------------------------
1672 
1673 //%% list IncludeInfoList[Class] : list of nested classes
1674 class IncludeInfoListContext::Private : public GenericNodeListContext
1675 {
1676   public:
Private(const IncludeInfoList & list,SrcLangExt lang)1677     Private(const IncludeInfoList &list,SrcLangExt lang)
1678     {
1679       for (const auto &ii : list)
1680       {
1681         append(IncludeInfoContext::alloc(&ii,lang));
1682       }
1683     }
1684 };
1685 
IncludeInfoListContext(const IncludeInfoList & list,SrcLangExt lang)1686 IncludeInfoListContext::IncludeInfoListContext(const IncludeInfoList &list,SrcLangExt lang) : p(std::make_unique<Private>(list,lang))
1687 {
1688 }
1689 
~IncludeInfoListContext()1690 IncludeInfoListContext::~IncludeInfoListContext()
1691 {
1692 }
1693 
1694 // TemplateListIntf
count() const1695 uint IncludeInfoListContext::count() const
1696 {
1697   return p->count();
1698 }
1699 
at(uint index) const1700 TemplateVariant IncludeInfoListContext::at(uint index) const
1701 {
1702   return p->at(index);
1703 }
1704 
createIterator() const1705 TemplateListIntf::ConstIteratorPtr IncludeInfoListContext::createIterator() const
1706 {
1707   return p->createIterator();
1708 }
1709 
1710 //------------------------------------------------------------------------
1711 
1712 class ClassContext::Private : public DefinitionContext<ClassContext::Private>
1713 {
1714   public:
Private(const ClassDef * cd)1715     Private(const ClassDef *cd) : DefinitionContext<ClassContext::Private>(cd),
1716        m_classDef(cd)
1717     {
1718     }
~Private()1719     virtual ~Private() {}
1720 
1721     // TemplateStructIntf methods
get(const QCString & n) const1722     TemplateVariant get(const QCString &n) const       { return s_inst.get(this,n); }
fields() const1723     StringVector fields() const                        { return s_inst.fields(); }
1724 
1725   private:
1726     // Property getters
title() const1727     TemplateVariant title() const                      { return TemplateVariant(m_classDef->title()); }
highlight() const1728     TemplateVariant highlight() const                  { return TemplateVariant("classes"); }
subHighlight() const1729     TemplateVariant subHighlight() const               { return TemplateVariant(""); }
hasDetails() const1730     TemplateVariant hasDetails() const                 { return m_classDef->hasDetailedDescription(); }
generatedFromFiles() const1731     TemplateVariant generatedFromFiles() const         { return m_classDef->generatedFromFiles(); }
usedFiles() const1732     TemplateVariant usedFiles() const                  { return m_cachable.usedFiles.get(this); }
getClassGraph() const1733     DotClassGraphPtr getClassGraph() const             { return m_cachable.classGraph.get(this); }
numInheritanceNodes() const1734     int numInheritanceNodes() const                    { return m_cachable.numInheritanceNodes.get(this); }
includeInfo() const1735     TemplateVariant includeInfo() const                { return m_cachable.includeInfo.get(this); }
inherits() const1736     TemplateVariant inherits() const                   { return m_cachable.inheritsList.get(this); }
inheritedBy() const1737     TemplateVariant inheritedBy() const                { return m_cachable.inheritedByList.get(this); }
unoIDLServices() const1738     TemplateVariant unoIDLServices() const             { return m_cachable.unoIDLServices.get(this); }
unoIDLInterfaces() const1739     TemplateVariant unoIDLInterfaces() const           { return m_cachable.unoIDLInterfaces.get(this); }
signals() const1740     TemplateVariant signals() const                    { return m_cachable.signals.get(this); }
publicTypes() const1741     TemplateVariant publicTypes() const                { return m_cachable.publicTypes.get(this); }
publicMethods() const1742     TemplateVariant publicMethods() const              { return m_cachable.publicMethods.get(this); }
publicStaticMethods() const1743     TemplateVariant publicStaticMethods() const        { return m_cachable.publicStaticMethods.get(this); }
publicAttributes() const1744     TemplateVariant publicAttributes() const           { return m_cachable.publicAttributes.get(this); }
publicStaticAttributes() const1745     TemplateVariant publicStaticAttributes() const     { return m_cachable.publicStaticAttributes.get(this); }
publicSlots() const1746     TemplateVariant publicSlots() const                { return m_cachable.publicSlots.get(this); }
protectedTypes() const1747     TemplateVariant protectedTypes() const             { return m_cachable.protectedTypes.get(this); }
protectedMethods() const1748     TemplateVariant protectedMethods() const           { return m_cachable.protectedMethods.get(this); }
protectedStaticMethods() const1749     TemplateVariant protectedStaticMethods() const     { return m_cachable.protectedStaticMethods.get(this); }
protectedAttributes() const1750     TemplateVariant protectedAttributes() const        { return m_cachable.protectedAttributes.get(this); }
protectedStaticAttributes() const1751     TemplateVariant protectedStaticAttributes() const  { return m_cachable.protectedStaticAttributes.get(this); }
protectedSlots() const1752     TemplateVariant protectedSlots() const             { return m_cachable.protectedSlots.get(this); }
privateTypes() const1753     TemplateVariant privateTypes() const               { return m_cachable.privateTypes.get(this); }
privateSlots() const1754     TemplateVariant privateSlots() const               { return m_cachable.privateSlots.get(this); }
privateMethods() const1755     TemplateVariant privateMethods() const             { return m_cachable.privateMethods.get(this); }
privateStaticMethods() const1756     TemplateVariant privateStaticMethods() const       { return m_cachable.privateStaticMethods.get(this); }
privateAttributes() const1757     TemplateVariant privateAttributes() const          { return m_cachable.privateAttributes.get(this); }
privateStaticAttributes() const1758     TemplateVariant privateStaticAttributes() const    { return m_cachable.privateStaticAttributes.get(this); }
packageTypes() const1759     TemplateVariant packageTypes() const               { return m_cachable.packageTypes.get(this); }
packageMethods() const1760     TemplateVariant packageMethods() const             { return m_cachable.packageMethods.get(this); }
packageStaticMethods() const1761     TemplateVariant packageStaticMethods() const       { return m_cachable.packageStaticMethods.get(this); }
packageAttributes() const1762     TemplateVariant packageAttributes() const          { return m_cachable.packageAttributes.get(this); }
packageStaticAttributes() const1763     TemplateVariant packageStaticAttributes() const    { return m_cachable.packageStaticAttributes.get(this); }
properties() const1764     TemplateVariant properties() const                 { return m_cachable.properties.get(this); }
events() const1765     TemplateVariant events() const                     { return m_cachable.events.get(this); }
friends() const1766     TemplateVariant friends() const                    { return m_cachable.friends.get(this); }
related() const1767     TemplateVariant related() const                    { return m_cachable.related.get(this); }
detailedTypedefs() const1768     TemplateVariant detailedTypedefs() const           { return m_cachable.detailedTypedefs.get(this); }
detailedEnums() const1769     TemplateVariant detailedEnums() const              { return m_cachable.detailedEnums.get(this); }
detailedServices() const1770     TemplateVariant detailedServices() const           { return m_cachable.detailedServices.get(this); }
detailedInterfaces() const1771     TemplateVariant detailedInterfaces() const         { return m_cachable.detailedInterfaces.get(this); }
detailedConstructors() const1772     TemplateVariant detailedConstructors() const       { return m_cachable.detailedConstructors.get(this); }
detailedMethods() const1773     TemplateVariant detailedMethods() const            { return m_cachable.detailedMethods.get(this); }
detailedRelated() const1774     TemplateVariant detailedRelated() const            { return m_cachable.detailedRelated.get(this); }
detailedVariables() const1775     TemplateVariant detailedVariables() const          { return m_cachable.detailedVariables.get(this); }
detailedProperties() const1776     TemplateVariant detailedProperties() const         { return m_cachable.detailedProperties.get(this); }
detailedEvents() const1777     TemplateVariant detailedEvents() const             { return m_cachable.detailedEvents.get(this); }
classes() const1778     TemplateVariant classes() const                    { return m_cachable.classes.get(this); }
innerClasses() const1779     TemplateVariant innerClasses() const               { return m_cachable.innerClasses.get(this); }
compoundType() const1780     TemplateVariant compoundType() const               { return m_classDef->compoundTypeString(); }
templateDecls() const1781     TemplateVariant templateDecls() const              { return m_cachable.templateDecls.get(this); }
typeConstraints() const1782     TemplateVariant typeConstraints() const            { return m_cachable.typeConstraints.get(this); }
examples() const1783     TemplateVariant examples() const                   { return m_cachable.examples.get(this); }
members() const1784     TemplateVariant members() const                    { return m_cachable.members.get(this); }
allMembersList() const1785     TemplateVariant allMembersList() const             { return m_cachable.allMembersList.get(this); }
allMembersFileName() const1786     TemplateVariant allMembersFileName() const         { return m_classDef->getMemberListFileName(); }
memberGroups() const1787     TemplateVariant memberGroups() const               { return m_cachable.memberGroups.get(this); }
additionalInheritedMembers() const1788     TemplateVariant additionalInheritedMembers() const { return m_cachable.additionalInheritedMembers.get(this); }
isSimple() const1789     TemplateVariant isSimple() const                   { return m_classDef->isSimple(); }
categoryOf() const1790     TemplateVariant categoryOf() const                 { return m_cachable.categoryOf.get(this); }
1791 
hasInheritanceDiagram() const1792     TemplateVariant hasInheritanceDiagram() const
1793     {
1794       bool result=FALSE;
1795       static bool haveDot    = Config_getBool(HAVE_DOT);
1796       static auto classGraph = Config_getEnum(CLASS_GRAPH);
1797       bool classGraphEnabled = classGraph==CLASS_GRAPH_t::YES || classGraph==CLASS_GRAPH_t::GRAPH;
1798 
1799       if (haveDot && classGraphEnabled)
1800       {
1801         DotClassGraphPtr cg = getClassGraph();
1802         result = !cg->isTrivial() && !cg->isTooBig();
1803       }
1804       else if (classGraphEnabled)
1805       {
1806         result = numInheritanceNodes()>0;
1807       }
1808       return result;
1809     }
inheritanceDiagram() const1810     TemplateVariant inheritanceDiagram() const
1811     {
1812       TextStream t;
1813       static bool haveDot    = Config_getBool(HAVE_DOT);
1814       static auto classGraph = Config_getEnum(CLASS_GRAPH);
1815       bool classGraphEnabled = classGraph==CLASS_GRAPH_t::YES || classGraph==CLASS_GRAPH_t::GRAPH;
1816 
1817       if (haveDot && classGraphEnabled)
1818       {
1819         DotClassGraphPtr cg = getClassGraph();
1820         switch (g_globals.outputFormat)
1821         {
1822           case ContextOutputFormat_Html:
1823             {
1824               cg->writeGraph(t,GOF_BITMAP,EOF_Html,
1825                              g_globals.outputDir,
1826                              g_globals.outputDir+Portable::pathSeparator()+addHtmlExtensionIfMissing(m_classDef->getOutputFileBase()),
1827                              relPathAsString(),TRUE,TRUE,g_globals.dynSectionId
1828                             );
1829             }
1830             break;
1831           case ContextOutputFormat_Latex:
1832             {
1833               cg->writeGraph(t,GOF_EPS,EOF_LaTeX,
1834                              g_globals.outputDir,
1835                              g_globals.outputDir+Portable::pathSeparator()+m_classDef->getOutputFileBase()+".tex",
1836                              relPathAsString(),TRUE,TRUE,g_globals.dynSectionId
1837                             );
1838             }
1839             break;
1840             // TODO: support other generators
1841           default:
1842             err("context.cpp: output format not yet supported\n");
1843             break;
1844         }
1845         g_globals.dynSectionId++;
1846       }
1847       else if (classGraphEnabled)
1848       {
1849         ClassDiagram d(m_classDef);
1850         switch (g_globals.outputFormat)
1851         {
1852           case ContextOutputFormat_Html:
1853             {
1854               TextStream tt;
1855 
1856               QCString name = convertToHtml(m_classDef->displayName());
1857               d.writeImage(tt,g_globals.outputDir,
1858                            relPathAsString(),
1859                            m_classDef->getOutputFileBase());
1860               if (!tt.empty())
1861               {
1862                 t << "<div class=\"center\">\n";
1863                 t << "  <img src=\"";
1864                 t << relPathAsString() << m_classDef->getOutputFileBase();
1865                 t << ".png\" usemap=\"#" << convertToId(name) << "_map\" alt=\"\"/>\n";
1866                 t << "  <map id=\"" << convertToId(name) << "_map\" name=\"" << convertToId(name) << "_map\">\n";
1867 	        t << tt.str();
1868 	        t << "  </map>\n";
1869                 t << "</div>";
1870               }
1871               else
1872               {
1873                 t << "<div class=\"center\">\n";
1874                 t << "  <img src=\"";
1875                 t << relPathAsString() << m_classDef->getOutputFileBase();
1876                 t << ".png\" alt=\"\"/>\n";
1877                 t << "</div>";
1878               }
1879             }
1880             break;
1881           case ContextOutputFormat_Latex:
1882             {
1883               d.writeFigure(t,g_globals.outputDir,m_classDef->getOutputFileBase());
1884             }
1885             break;
1886             // TODO: support other generators
1887           default:
1888             err("context.cpp: output format not yet supported\n");
1889             break;
1890         }
1891         g_globals.dynSectionId++;
1892       }
1893       return TemplateVariant(t.str().c_str(),TRUE);
1894     }
getCollaborationGraph() const1895     DotClassGraphPtr getCollaborationGraph() const
1896     {
1897       return m_cachable.collaborationGraph.get(this);
1898     }
hasCollaborationDiagram() const1899     TemplateVariant hasCollaborationDiagram() const
1900     {
1901       static bool haveDot = Config_getBool(HAVE_DOT);
1902       return haveDot && !getCollaborationGraph()->isTrivial();
1903     }
collaborationDiagram() const1904     TemplateVariant collaborationDiagram() const
1905     {
1906       static bool haveDot = Config_getBool(HAVE_DOT);
1907       TextStream t;
1908       if (haveDot)
1909       {
1910         DotClassGraphPtr cg = getCollaborationGraph();
1911         switch (g_globals.outputFormat)
1912         {
1913           case ContextOutputFormat_Html:
1914             {
1915               cg->writeGraph(t,GOF_BITMAP,EOF_Html,
1916                              g_globals.outputDir,
1917                              g_globals.outputDir+Portable::pathSeparator()+addHtmlExtensionIfMissing(m_classDef->getOutputFileBase()),
1918                              relPathAsString(),TRUE,TRUE,g_globals.dynSectionId
1919                             );
1920             }
1921             break;
1922           case ContextOutputFormat_Latex:
1923             {
1924               cg->writeGraph(t,GOF_EPS,EOF_LaTeX,
1925                              g_globals.outputDir,
1926                              g_globals.outputDir+Portable::pathSeparator()+m_classDef->getOutputFileBase()+".tex",
1927                              relPathAsString(),TRUE,TRUE,g_globals.dynSectionId
1928                             );
1929             }
1930             break;
1931             // TODO: support other generators
1932           default:
1933             err("context.cpp: output format not yet supported\n");
1934             break;
1935         }
1936         g_globals.dynSectionId++;
1937       }
1938       return TemplateVariant(t.str().c_str(),TRUE);
1939     }
1940 
1941 
1942   private:
1943 
createIncludeInfo() const1944     TemplateVariant createIncludeInfo() const
1945     {
1946       return m_classDef->includeInfo() ?
1947              IncludeInfoContext::alloc(m_classDef->includeInfo(),m_classDef->getLanguage()) :
1948              TemplateVariant(false);
1949     }
createInheritsList() const1950     TemplateVariant createInheritsList() const
1951     {
1952       return InheritanceListContext::alloc(m_classDef->baseClasses(),TRUE);
1953     }
createInheritedByList() const1954     TemplateVariant createInheritedByList() const
1955     {
1956       return InheritanceListContext::alloc(m_classDef->subClasses(),FALSE);
1957     }
createClassGraph() const1958     DotClassGraphPtr createClassGraph() const
1959     {
1960       return std::make_shared<DotClassGraph>(m_classDef,Inheritance);
1961     }
createCollaborationGraph() const1962     DotClassGraphPtr createCollaborationGraph() const
1963     {
1964       return std::make_shared<DotClassGraph>(m_classDef,Collaboration);
1965     }
createClasses() const1966     TemplateVariant createClasses() const
1967     {
1968       TemplateVariantList classList;
1969       classList.reserve(m_classDef->getClasses().size());
1970       for (const auto &cd : m_classDef->getClasses())
1971       {
1972         if (cd->visibleInParentsDeclList())
1973         {
1974           classList.push_back(ClassContext::alloc(cd));
1975         }
1976       }
1977       return TemplateImmutableList::alloc(classList);
1978     }
createInnerClasses() const1979     TemplateVariant createInnerClasses() const
1980     {
1981       TemplateVariantList classList;
1982       classList.reserve(m_classDef->getClasses().size());
1983       for (const auto &cd : m_classDef->getClasses())
1984       {
1985         if (!cd->isAnonymous() &&
1986             cd->isLinkableInProject() &&
1987             cd->isEmbeddedInOuterScope() &&
1988             cd->partOfGroups().empty()
1989            )
1990         {
1991           classList.push_back(ClassContext::alloc(cd));
1992         }
1993       }
1994       return TemplateImmutableList::alloc(classList);
1995     }
createMemberList(MemberListType type,const QCString & title) const1996     TemplateVariant createMemberList(MemberListType type,const QCString &title) const
1997     {
1998       const MemberList *ml = m_classDef->getMemberList(type);
1999       return ml ? TemplateVariant(MemberListInfoContext::alloc(m_classDef,relPathAsString(),ml,title,""))
2000                 : TemplateVariant(false);
2001     }
createPublicTypes() const2002     TemplateVariant createPublicTypes() const
2003     {
2004       return createMemberList(MemberListType_pubTypes,theTranslator->trPublicTypes());
2005     }
createPublicMethods() const2006     TemplateVariant createPublicMethods() const
2007     {
2008       return createMemberList(MemberListType_pubMethods,
2009           m_classDef->getLanguage()==SrcLangExt_ObjC ? theTranslator->trInstanceMethods()
2010                                                      : theTranslator->trPublicMembers());
2011     }
createPublicStaticMethods() const2012     TemplateVariant createPublicStaticMethods() const
2013     {
2014       return createMemberList(MemberListType_pubStaticMethods,
2015           m_classDef->getLanguage()==SrcLangExt_ObjC ? theTranslator->trClassMethods()
2016                                                      : theTranslator->trStaticPublicMembers());
2017     }
createPublicAttributes() const2018     TemplateVariant createPublicAttributes() const
2019     {
2020       return createMemberList(MemberListType_pubAttribs,theTranslator->trPublicAttribs());
2021     }
createPublicStaticAttributes() const2022     TemplateVariant createPublicStaticAttributes() const
2023     {
2024       return createMemberList(MemberListType_pubStaticAttribs,theTranslator->trStaticPublicAttribs());
2025     }
createPublicSlots() const2026     TemplateVariant createPublicSlots() const
2027     {
2028       return createMemberList(MemberListType_pubSlots,theTranslator->trPublicSlots());
2029     }
createUnoIDLServices() const2030     TemplateVariant createUnoIDLServices() const
2031     {
2032       return createMemberList(MemberListType_services,theTranslator->trServices());
2033     }
createUnoIDLInterfaces() const2034     TemplateVariant createUnoIDLInterfaces() const
2035     {
2036       return createMemberList(MemberListType_interfaces,theTranslator->trInterfaces());
2037     }
createSignals() const2038     TemplateVariant createSignals() const
2039     {
2040       return createMemberList(MemberListType_signals,theTranslator->trSignals());
2041     }
createProtectedTypes() const2042     TemplateVariant createProtectedTypes() const
2043     {
2044       return createMemberList(MemberListType_proTypes,theTranslator->trProtectedTypes());
2045     }
createProtectedMethods() const2046     TemplateVariant createProtectedMethods() const
2047     {
2048       return createMemberList(MemberListType_proMethods,theTranslator->trProtectedMembers());
2049     }
createProtectedStaticMethods() const2050     TemplateVariant createProtectedStaticMethods() const
2051     {
2052       return createMemberList(MemberListType_proStaticMethods,theTranslator->trStaticProtectedMembers());
2053     }
createProtectedAttributes() const2054     TemplateVariant createProtectedAttributes() const
2055     {
2056       return createMemberList(MemberListType_proAttribs,theTranslator->trProtectedAttribs());
2057     }
createProtectedStaticAttributes() const2058     TemplateVariant createProtectedStaticAttributes() const
2059     {
2060       return createMemberList(MemberListType_proStaticAttribs,theTranslator->trStaticProtectedAttribs());
2061     }
createProtectedSlots() const2062     TemplateVariant createProtectedSlots() const
2063     {
2064       return createMemberList(MemberListType_proSlots,theTranslator->trProtectedSlots());
2065     }
createPrivateTypes() const2066     TemplateVariant createPrivateTypes() const
2067     {
2068       return createMemberList(MemberListType_priTypes,theTranslator->trPrivateTypes());
2069     }
createPrivateSlots() const2070     TemplateVariant createPrivateSlots() const
2071     {
2072       return createMemberList(MemberListType_priSlots,theTranslator->trPrivateSlots());
2073     }
createPrivateMethods() const2074     TemplateVariant createPrivateMethods() const
2075     {
2076       return createMemberList(MemberListType_priMethods,theTranslator->trPrivateMembers());
2077     }
createPrivateStaticMethods() const2078     TemplateVariant createPrivateStaticMethods() const
2079     {
2080       return createMemberList(MemberListType_priStaticMethods,theTranslator->trStaticPrivateMembers());
2081     }
createPrivateAttributes() const2082     TemplateVariant createPrivateAttributes() const
2083     {
2084       return createMemberList(MemberListType_priAttribs,theTranslator->trPrivateAttribs());
2085     }
createPrivateStaticAttributes() const2086     TemplateVariant createPrivateStaticAttributes() const
2087     {
2088       return createMemberList(MemberListType_priStaticAttribs,theTranslator->trStaticPrivateAttribs());
2089     }
createPackageTypes() const2090     TemplateVariant createPackageTypes() const
2091     {
2092       return createMemberList(MemberListType_pacTypes,theTranslator->trPackageTypes());
2093     }
createPackageMethods() const2094     TemplateVariant createPackageMethods() const
2095     {
2096       return createMemberList(MemberListType_pacMethods,theTranslator->trPackageMembers());
2097     }
createPackageStaticMethods() const2098     TemplateVariant createPackageStaticMethods() const
2099     {
2100       return createMemberList(MemberListType_pacStaticMethods,theTranslator->trStaticPackageMembers());
2101     }
createPackageAttributes() const2102     TemplateVariant createPackageAttributes() const
2103     {
2104       return createMemberList(MemberListType_pacAttribs,theTranslator->trPackageAttribs());
2105     }
createPackageStaticAttributes() const2106     TemplateVariant createPackageStaticAttributes() const
2107     {
2108       return createMemberList(MemberListType_pacStaticAttribs,theTranslator->trStaticPackageAttribs());
2109     }
createProperties() const2110     TemplateVariant createProperties() const
2111     {
2112       return createMemberList(MemberListType_properties,theTranslator->trProperties());
2113     }
createEvents() const2114     TemplateVariant createEvents() const
2115     {
2116       return createMemberList(MemberListType_events,theTranslator->trEvents());
2117     }
createFriends() const2118     TemplateVariant createFriends() const
2119     {
2120       return createMemberList(MemberListType_friends,theTranslator->trFriends());
2121     }
createRelated() const2122     TemplateVariant createRelated() const
2123     {
2124       return createMemberList(MemberListType_related,theTranslator->trRelatedFunctions());
2125     }
createDetailedTypedefs() const2126     TemplateVariant createDetailedTypedefs() const
2127     {
2128       return createMemberList(MemberListType_typedefMembers,theTranslator->trMemberTypedefDocumentation());
2129     }
createDetailedEnums() const2130     TemplateVariant createDetailedEnums() const
2131     {
2132       return createMemberList(MemberListType_enumMembers,theTranslator->trMemberEnumerationDocumentation());
2133     }
createDetailedServices() const2134     TemplateVariant createDetailedServices() const
2135     {
2136       return createMemberList(MemberListType_serviceMembers,theTranslator->trServices());
2137     }
createDetailedInterfaces() const2138     TemplateVariant createDetailedInterfaces() const
2139     {
2140       return createMemberList(MemberListType_interfaceMembers,theTranslator->trInterfaces());
2141     }
createDetailedConstructors() const2142     TemplateVariant createDetailedConstructors() const
2143     {
2144       return createMemberList(MemberListType_constructors,theTranslator->trConstructorDocumentation());
2145     }
createDetailedMethods() const2146     TemplateVariant createDetailedMethods() const
2147     {
2148       return createMemberList(MemberListType_functionMembers,theTranslator->trMemberFunctionDocumentation());
2149     }
createDetailedRelated() const2150     TemplateVariant createDetailedRelated() const
2151     {
2152       return createMemberList(MemberListType_relatedMembers,theTranslator->trRelatedFunctionDocumentation());
2153     }
createDetailedVariables() const2154     TemplateVariant createDetailedVariables() const
2155     {
2156       return createMemberList(MemberListType_variableMembers,theTranslator->trMemberDataDocumentation());
2157     }
createDetailedProperties() const2158     TemplateVariant createDetailedProperties() const
2159     {
2160       return createMemberList(MemberListType_propertyMembers,theTranslator->trPropertyDocumentation());
2161     }
createDetailedEvents() const2162     TemplateVariant createDetailedEvents() const
2163     {
2164       return createMemberList(MemberListType_eventMembers,theTranslator->trEventDocumentation());
2165     }
createMemberGroups() const2166     TemplateVariant createMemberGroups() const
2167     {
2168       return !m_classDef->getMemberGroups().empty() ?
2169         MemberGroupListContext::alloc(m_classDef,relPathAsString(),m_classDef->getMemberGroups(),m_classDef->subGrouping()) :
2170         MemberGroupListContext::alloc();
2171     }
createAllMembersList() const2172     TemplateVariant createAllMembersList() const
2173     {
2174        return AllMembersListContext::alloc(m_classDef->memberNameInfoLinkedMap());
2175     }
createTypeConstraints() const2176     TemplateVariant createTypeConstraints() const
2177     {
2178       return !m_classDef->typeConstraints().empty() ?
2179           TemplateVariant(ArgumentListContext::alloc(m_classDef->typeConstraints(),m_classDef,relPathAsString())) :
2180           TemplateVariant(false);
2181     }
createExamples() const2182     TemplateVariant createExamples() const
2183     {
2184       TemplateVariantList list;
2185       list.reserve(m_classDef->getExamples().size());
2186       if (m_classDef->hasExamples())
2187       {
2188         for (const auto &ex : m_classDef->getExamples())
2189         {
2190           TemplateStructIntfPtr s = TemplateImmutableStruct::alloc(
2191           {
2192             { "text",              TemplateVariant(ex.name)   },
2193             { "isLinkable",        TemplateVariant(TRUE)      },
2194             { "anchor",            TemplateVariant(ex.anchor) },
2195             { "fileName",          TemplateVariant(ex.file)   },
2196             { "isReference",       TemplateVariant(FALSE)     },
2197             { "externalReference", TemplateVariant("")        }
2198           });
2199           list.push_back(s);
2200         }
2201       }
2202       return TemplateImmutableList::alloc(list);
2203     }
addTemplateDecls(const Definition * d,TemplateVariantList & tl) const2204     void addTemplateDecls(const Definition *d,TemplateVariantList &tl) const
2205     {
2206       if (d->definitionType()==Definition::TypeClass)
2207       {
2208         const Definition *parent = d->getOuterScope();
2209         if (parent)
2210         {
2211           addTemplateDecls(parent,tl);
2212         }
2213         const ClassDef *cd=toClassDef(d);
2214         if (!cd->templateArguments().empty())
2215         {
2216           TemplateListIntfPtr al = ArgumentListContext::alloc(cd->templateArguments(),cd,relPathAsString());
2217           // since a TemplateVariant does take ownership of the object, we add it
2218           // a separate list just to be able to delete it and avoid a memory leak
2219           tl.push_back(al);
2220         }
2221       }
2222     }
createTemplateDecls() const2223     TemplateVariant createTemplateDecls() const
2224     {
2225       TemplateVariantList tl;
2226       addTemplateDecls(m_classDef,tl);
2227       return TemplateImmutableList::alloc(tl);
2228     }
createAdditionalInheritedMembers() const2229     TemplateVariant createAdditionalInheritedMembers() const
2230     {
2231       TemplateListIntfPtr list = InheritedMemberInfoListContext::alloc();
2232       auto ctx = std::dynamic_pointer_cast<InheritedMemberInfoListContext>(list);
2233       ctx->addMemberList(m_classDef,MemberListType_pubTypes,theTranslator->trPublicTypes());
2234       ctx->addMemberList(m_classDef,MemberListType_services,theTranslator->trServices());
2235       ctx->addMemberList(m_classDef,MemberListType_interfaces,theTranslator->trInterfaces());
2236       ctx->addMemberList(m_classDef,MemberListType_pubSlots,theTranslator->trPublicSlots());
2237       ctx->addMemberList(m_classDef,MemberListType_signals,theTranslator->trSignals());
2238       ctx->addMemberList(m_classDef,MemberListType_pubMethods,
2239         m_classDef->getLanguage()==SrcLangExt_ObjC ? theTranslator->trInstanceMethods()
2240                                                    : theTranslator->trPublicMembers());
2241       ctx->addMemberList(m_classDef,MemberListType_pubStaticMethods,
2242         m_classDef->getLanguage()==SrcLangExt_ObjC ? theTranslator->trClassMethods()
2243                                                    : theTranslator->trStaticPublicMembers());
2244       ctx->addMemberList(m_classDef,MemberListType_pubAttribs,theTranslator->trPublicAttribs());
2245       ctx->addMemberList(m_classDef,MemberListType_pubStaticAttribs,theTranslator->trStaticPublicAttribs());
2246       ctx->addMemberList(m_classDef,MemberListType_proTypes,theTranslator->trProtectedTypes());
2247       ctx->addMemberList(m_classDef,MemberListType_proSlots,theTranslator->trProtectedSlots());
2248       ctx->addMemberList(m_classDef,MemberListType_proMethods,theTranslator->trProtectedMembers());
2249       ctx->addMemberList(m_classDef,MemberListType_proStaticMethods,theTranslator->trStaticProtectedMembers());
2250       ctx->addMemberList(m_classDef,MemberListType_proAttribs,theTranslator->trProtectedAttribs());
2251       ctx->addMemberList(m_classDef,MemberListType_proStaticAttribs,theTranslator->trStaticProtectedAttribs());
2252       ctx->addMemberList(m_classDef,MemberListType_pacTypes,theTranslator->trPackageTypes());
2253       ctx->addMemberList(m_classDef,MemberListType_pacMethods,theTranslator->trPackageMembers());
2254       ctx->addMemberList(m_classDef,MemberListType_pacStaticMethods,theTranslator->trStaticPackageMembers());
2255       ctx->addMemberList(m_classDef,MemberListType_pacAttribs,theTranslator->trPackageAttribs());
2256       ctx->addMemberList(m_classDef,MemberListType_pacStaticAttribs,theTranslator->trStaticPackageAttribs());
2257       ctx->addMemberList(m_classDef,MemberListType_properties,theTranslator->trProperties());
2258       ctx->addMemberList(m_classDef,MemberListType_events,theTranslator->trEvents());
2259       ctx->addMemberList(m_classDef,MemberListType_priTypes,theTranslator->trPrivateTypes());
2260       ctx->addMemberList(m_classDef,MemberListType_priSlots,theTranslator->trPrivateSlots());
2261       ctx->addMemberList(m_classDef,MemberListType_priMethods,theTranslator->trPrivateMembers());
2262       ctx->addMemberList(m_classDef,MemberListType_priStaticMethods,theTranslator->trStaticPrivateMembers());
2263       ctx->addMemberList(m_classDef,MemberListType_priAttribs,theTranslator->trPrivateAttribs());
2264       ctx->addMemberList(m_classDef,MemberListType_priStaticAttribs,theTranslator->trStaticPrivateAttribs());
2265       ctx->addMemberList(m_classDef,MemberListType_related,theTranslator->trRelatedFunctions());
2266       return list;
2267     }
addMembers(MemberList & list,const ClassDef * cd,MemberListType lt) const2268     void addMembers(MemberList &list,const ClassDef *cd,MemberListType lt) const
2269     {
2270       const MemberList *ml = cd->getMemberList(lt);
2271       if (ml)
2272       {
2273         for (const auto &md : *ml)
2274         {
2275           if (md->isBriefSectionVisible())
2276           {
2277             list.push_back(md);
2278           }
2279         }
2280       }
2281     }
createMembers() const2282     TemplateVariant createMembers() const
2283     {
2284       MemberList list(MemberListType_allMembersList,MemberListContainer::Class);
2285       addMembers(list,m_classDef,MemberListType_pubTypes);
2286       addMembers(list,m_classDef,MemberListType_services);
2287       addMembers(list,m_classDef,MemberListType_interfaces);
2288       addMembers(list,m_classDef,MemberListType_pubSlots);
2289       addMembers(list,m_classDef,MemberListType_signals);
2290       addMembers(list,m_classDef,MemberListType_pubMethods);
2291       addMembers(list,m_classDef,MemberListType_pubStaticMethods);
2292       addMembers(list,m_classDef,MemberListType_pubAttribs);
2293       addMembers(list,m_classDef,MemberListType_pubStaticAttribs);
2294       addMembers(list,m_classDef,MemberListType_proTypes);
2295       addMembers(list,m_classDef,MemberListType_proSlots);
2296       addMembers(list,m_classDef,MemberListType_proMethods);
2297       addMembers(list,m_classDef,MemberListType_proStaticMethods);
2298       addMembers(list,m_classDef,MemberListType_proAttribs);
2299       addMembers(list,m_classDef,MemberListType_proStaticAttribs);
2300       addMembers(list,m_classDef,MemberListType_pacTypes);
2301       addMembers(list,m_classDef,MemberListType_pacMethods);
2302       addMembers(list,m_classDef,MemberListType_pacStaticMethods);
2303       addMembers(list,m_classDef,MemberListType_pacAttribs);
2304       addMembers(list,m_classDef,MemberListType_pacStaticAttribs);
2305       addMembers(list,m_classDef,MemberListType_properties);
2306       addMembers(list,m_classDef,MemberListType_events);
2307       addMembers(list,m_classDef,MemberListType_priTypes);
2308       addMembers(list,m_classDef,MemberListType_priSlots);
2309       addMembers(list,m_classDef,MemberListType_priMethods);
2310       addMembers(list,m_classDef,MemberListType_priStaticMethods);
2311       addMembers(list,m_classDef,MemberListType_priAttribs);
2312       addMembers(list,m_classDef,MemberListType_priStaticAttribs);
2313       addMembers(list,m_classDef,MemberListType_related);
2314       return MemberListContext::alloc(list);
2315     }
createUsedFiles() const2316     TemplateVariant createUsedFiles() const
2317     {
2318       return UsedFilesContext::alloc(m_classDef);
2319     }
createCategoryOf() const2320     TemplateVariant createCategoryOf() const
2321     {
2322       return m_classDef->categoryOf() ?
2323          TemplateVariant(ClassContext::alloc(m_classDef->categoryOf())) :
2324          TemplateVariant(FALSE);
2325     }
createNumInheritanceNodes() const2326     int createNumInheritanceNodes() const
2327     {
2328       return m_classDef->countInheritanceNodes();
2329     }
2330 
2331     const ClassDef *m_classDef;
2332     struct Cachable : public DefinitionContext<ClassContext::Private>::Cachable
2333     {
2334       CachedItem<TemplateVariant,  Private, &Private::createIncludeInfo>                includeInfo;
2335       CachedItem<TemplateVariant,  Private, &Private::createInheritsList>               inheritsList;
2336       CachedItem<TemplateVariant,  Private, &Private::createInheritedByList>            inheritedByList;
2337       CachedItem<DotClassGraphPtr, Private, &Private::createClassGraph>                 classGraph;
2338       CachedItem<DotClassGraphPtr, Private, &Private::createCollaborationGraph>         collaborationGraph;
2339       CachedItem<TemplateVariant,  Private, &Private::createClasses>                    classes;
2340       CachedItem<TemplateVariant,  Private, &Private::createInnerClasses>               innerClasses;
2341       CachedItem<TemplateVariant,  Private, &Private::createPublicTypes>                publicTypes;
2342       CachedItem<TemplateVariant,  Private, &Private::createPublicMethods>              publicMethods;
2343       CachedItem<TemplateVariant,  Private, &Private::createPublicStaticMethods>        publicStaticMethods;
2344       CachedItem<TemplateVariant,  Private, &Private::createPublicAttributes>           publicAttributes;
2345       CachedItem<TemplateVariant,  Private, &Private::createPublicStaticAttributes>     publicStaticAttributes;
2346       CachedItem<TemplateVariant,  Private, &Private::createPublicSlots>                publicSlots;
2347       CachedItem<TemplateVariant,  Private, &Private::createProtectedTypes>             protectedTypes;
2348       CachedItem<TemplateVariant,  Private, &Private::createProtectedMethods>           protectedMethods;
2349       CachedItem<TemplateVariant,  Private, &Private::createProtectedStaticMethods>     protectedStaticMethods;
2350       CachedItem<TemplateVariant,  Private, &Private::createProtectedAttributes>        protectedAttributes;
2351       CachedItem<TemplateVariant,  Private, &Private::createProtectedStaticAttributes>  protectedStaticAttributes;
2352       CachedItem<TemplateVariant,  Private, &Private::createProtectedSlots>             protectedSlots;
2353       CachedItem<TemplateVariant,  Private, &Private::createPrivateTypes>               privateTypes;
2354       CachedItem<TemplateVariant,  Private, &Private::createPrivateMethods>             privateMethods;
2355       CachedItem<TemplateVariant,  Private, &Private::createPrivateStaticMethods>       privateStaticMethods;
2356       CachedItem<TemplateVariant,  Private, &Private::createPrivateAttributes>          privateAttributes;
2357       CachedItem<TemplateVariant,  Private, &Private::createPrivateStaticAttributes>    privateStaticAttributes;
2358       CachedItem<TemplateVariant,  Private, &Private::createPrivateSlots>               privateSlots;
2359       CachedItem<TemplateVariant,  Private, &Private::createPackageTypes>               packageTypes;
2360       CachedItem<TemplateVariant,  Private, &Private::createPackageMethods>             packageMethods;
2361       CachedItem<TemplateVariant,  Private, &Private::createPackageStaticMethods>       packageStaticMethods;
2362       CachedItem<TemplateVariant,  Private, &Private::createPackageAttributes>          packageAttributes;
2363       CachedItem<TemplateVariant,  Private, &Private::createPackageStaticAttributes>    packageStaticAttributes;
2364       CachedItem<TemplateVariant,  Private, &Private::createUnoIDLServices>             unoIDLServices;
2365       CachedItem<TemplateVariant,  Private, &Private::createUnoIDLInterfaces>           unoIDLInterfaces;
2366       CachedItem<TemplateVariant,  Private, &Private::createSignals>                    signals;
2367       CachedItem<TemplateVariant,  Private, &Private::createProperties>                 properties;
2368       CachedItem<TemplateVariant,  Private, &Private::createEvents>                     events;
2369       CachedItem<TemplateVariant,  Private, &Private::createFriends>                    friends;
2370       CachedItem<TemplateVariant,  Private, &Private::createRelated>                    related;
2371       CachedItem<TemplateVariant,  Private, &Private::createDetailedTypedefs>           detailedTypedefs;
2372       CachedItem<TemplateVariant,  Private, &Private::createDetailedEnums>              detailedEnums;
2373       CachedItem<TemplateVariant,  Private, &Private::createDetailedServices>           detailedServices;
2374       CachedItem<TemplateVariant,  Private, &Private::createDetailedInterfaces>         detailedInterfaces;
2375       CachedItem<TemplateVariant,  Private, &Private::createDetailedConstructors>       detailedConstructors;
2376       CachedItem<TemplateVariant,  Private, &Private::createDetailedMethods>            detailedMethods;
2377       CachedItem<TemplateVariant,  Private, &Private::createDetailedRelated>            detailedRelated;
2378       CachedItem<TemplateVariant,  Private, &Private::createDetailedVariables>          detailedVariables;
2379       CachedItem<TemplateVariant,  Private, &Private::createDetailedProperties>         detailedProperties;
2380       CachedItem<TemplateVariant,  Private, &Private::createDetailedEvents>             detailedEvents;
2381       CachedItem<TemplateVariant,  Private, &Private::createMemberGroups>               memberGroups;
2382       CachedItem<TemplateVariant,  Private, &Private::createAllMembersList>             allMembersList;
2383       CachedItem<TemplateVariant,  Private, &Private::createTypeConstraints>            typeConstraints;
2384       CachedItem<TemplateVariant,  Private, &Private::createExamples>                   examples;
2385       CachedItem<TemplateVariant,  Private, &Private::createTemplateDecls>              templateDecls;
2386       CachedItem<TemplateVariant,  Private, &Private::createAdditionalInheritedMembers> additionalInheritedMembers;
2387       CachedItem<TemplateVariant,  Private, &Private::createMembers>                    members;
2388       CachedItem<TemplateVariant,  Private, &Private::createUsedFiles>                  usedFiles;
2389       CachedItem<TemplateVariant,  Private, &Private::createCategoryOf>                 categoryOf;
2390       CachedItem<int,              Private, &Private::createNumInheritanceNodes>        numInheritanceNodes;
2391     };
2392     Cachable m_cachable;
2393    static const PropertyMap<ClassContext::Private> s_inst;
2394 };
2395 
2396 //%% struct Class(Symbol): class information
2397 //%% {
2398 const PropertyMap<ClassContext::Private> ClassContext::Private::s_inst {
2399   BASE_PROPERTIES,
2400   {  "title",                     &Private::title },
2401   {  "highlight",                 &Private::highlight },
2402   {  "subhighlight",              &Private::subHighlight },
2403   {  "hasDetails",                &Private::hasDetails },
2404   {  "generatedFromFiles",        &Private::generatedFromFiles },
2405   {  "usedFiles",                 &Private::usedFiles },
2406   {  "hasInheritanceDiagram",     &Private::hasInheritanceDiagram },
2407   {  "inheritanceDiagram",        &Private::inheritanceDiagram },
2408   {  "hasCollaborationDiagram",   &Private::hasCollaborationDiagram },
2409   {  "collaborationDiagram",      &Private::collaborationDiagram },
2410   {  "includeInfo",               &Private::includeInfo },
2411   {  "inherits",                  &Private::inherits },
2412   {  "inheritedBy",               &Private::inheritedBy },
2413   {  "unoIDLServices",            &Private::unoIDLServices },
2414   {  "unoIDLInterfaces",          &Private::unoIDLInterfaces },
2415   {  "signals",                   &Private::signals },
2416   {  "publicTypes",               &Private::publicTypes },
2417   {  "publicMethods",             &Private::publicMethods },
2418   {  "publicStaticMethods",       &Private::publicStaticMethods },
2419   {  "publicAttributes",          &Private::publicAttributes },
2420   {  "publicStaticAttributes",    &Private::publicStaticAttributes },
2421   {  "publicSlots",               &Private::publicSlots },
2422   {  "protectedTypes",            &Private::protectedTypes },
2423   {  "protectedMethods",          &Private::protectedMethods },
2424   {  "protectedStaticMethods",    &Private::protectedStaticMethods },
2425   {  "protectedAttributes",       &Private::protectedAttributes },
2426   {  "protectedStaticAttributes", &Private::protectedStaticAttributes },
2427   {  "protectedSlots",            &Private::protectedSlots },
2428   {  "privateTypes",              &Private::privateTypes },
2429   {  "privateMethods",            &Private::privateMethods },
2430   {  "privateStaticMethods",      &Private::privateStaticMethods },
2431   {  "privateAttributes",         &Private::privateAttributes },
2432   {  "privateStaticAttributes",   &Private::privateStaticAttributes },
2433   {  "privateSlots",              &Private::privateSlots },
2434   {  "packageTypes",              &Private::packageTypes },
2435   {  "packageMethods",            &Private::packageMethods },
2436   {  "packageStaticMethods",      &Private::packageStaticMethods },
2437   {  "packageAttributes",         &Private::packageAttributes },
2438   {  "packageStaticAttributes",   &Private::packageStaticAttributes },
2439   {  "properties",                &Private::properties },
2440   {  "events",                    &Private::events },
2441   {  "friends",                   &Private::friends },
2442   {  "related",                   &Private::related },
2443   {  "detailedTypedefs",          &Private::detailedTypedefs },
2444   {  "detailedEnums",             &Private::detailedEnums },
2445   {  "detailedServices",          &Private::detailedServices },
2446   {  "detailedInterfaces",        &Private::detailedInterfaces },
2447   {  "detailedConstructors",      &Private::detailedConstructors },
2448   {  "detailedMethods",           &Private::detailedMethods },
2449   {  "detailedRelated",           &Private::detailedRelated },
2450   {  "detailedVariables",         &Private::detailedVariables },
2451   {  "detailedProperties",        &Private::detailedProperties },
2452   {  "detailedEvents",            &Private::detailedEvents },
2453   {  "classes",                   &Private::classes },
2454   {  "innerClasses",              &Private::innerClasses },
2455   {  "compoundType",              &Private::compoundType },
2456   {  "templateDecls",             &Private::templateDecls },
2457   {  "typeConstraints",           &Private::typeConstraints },
2458   {  "examples",                  &Private::examples },
2459   {  "members",                   &Private::members },
2460   {  "allMembersList",            &Private::allMembersList },
2461   {  "allMembersFileName",        &Private::allMembersFileName },
2462   {  "memberGroups",              &Private::memberGroups },
2463   {  "additionalInheritedMembers",&Private::additionalInheritedMembers },
2464   {  "isSimple",                  &Private::isSimple },
2465   {  "categoryOf",                &Private::categoryOf }
2466 };
2467 //%% }
2468 
2469 //PropertyMapper<ClassContext::Private> ClassContext::Private::s_inst;
2470 
ClassContext(const ClassDef * cd)2471 ClassContext::ClassContext(const ClassDef *cd) : p(std::make_unique<Private>(cd))
2472 {
2473 }
2474 
~ClassContext()2475 ClassContext::~ClassContext()
2476 {
2477 }
2478 
get(const QCString & n) const2479 TemplateVariant ClassContext::get(const QCString &n) const
2480 {
2481   return p->get(n);
2482 }
2483 
fields() const2484 StringVector ClassContext::fields() const
2485 {
2486   return p->fields();
2487 }
2488 
2489 //------------------------------------------------------------------------
2490 
2491 class NamespaceContext::Private : public DefinitionContext<NamespaceContext::Private>
2492 {
2493   public:
Private(const NamespaceDef * nd)2494     Private(const NamespaceDef *nd) : DefinitionContext<NamespaceContext::Private>(nd),
2495                                 m_namespaceDef(nd)
2496     {
2497     }
~Private()2498     virtual ~Private() {}
2499 
2500     // TemplateStructIntf methods
get(const QCString & n) const2501     TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
fields() const2502     StringVector fields() const                  { return s_inst.fields(); }
2503 
2504   private:
2505     // Property getters
title() const2506     TemplateVariant title() const                { return TemplateVariant(m_namespaceDef->title()); }
highlight() const2507     TemplateVariant highlight() const            { return TemplateVariant("namespaces"); }
subHighlight() const2508     TemplateVariant subHighlight() const         { return TemplateVariant(""); }
compoundType() const2509     TemplateVariant compoundType() const         { return m_namespaceDef->compoundTypeString(); }
hasDetails() const2510     TemplateVariant hasDetails() const           { return m_namespaceDef->hasDetailedDescription(); }
classes() const2511     TemplateVariant classes() const              { return m_cachable.classes.get(this); }
namespaces() const2512     TemplateVariant namespaces() const           { return m_cachable.namespaces.get(this); }
constantgroups() const2513     TemplateVariant constantgroups() const       { return m_cachable.constantgroups.get(this); }
typedefs() const2514     TemplateVariant typedefs() const             { return m_cachable.typedefs.get(this); }
sequences() const2515     TemplateVariant sequences() const            { return m_cachable.sequences.get(this); }
dictionaries() const2516     TemplateVariant dictionaries() const         { return m_cachable.dictionaries.get(this); }
enums() const2517     TemplateVariant enums() const                { return m_cachable.enums.get(this); }
functions() const2518     TemplateVariant functions() const            { return m_cachable.functions.get(this); }
variables() const2519     TemplateVariant variables() const            { return m_cachable.variables.get(this); }
memberGroups() const2520     TemplateVariant memberGroups() const         { return m_cachable.memberGroups.get(this); }
detailedTypedefs() const2521     TemplateVariant detailedTypedefs() const     { return m_cachable.detailedTypedefs.get(this); }
detailedSequences() const2522     TemplateVariant detailedSequences() const    { return m_cachable.detailedSequences.get(this); }
detailedDictionaries() const2523     TemplateVariant detailedDictionaries() const { return m_cachable.detailedDictionaries.get(this); }
detailedEnums() const2524     TemplateVariant detailedEnums() const        { return m_cachable.detailedEnums.get(this); }
detailedFunctions() const2525     TemplateVariant detailedFunctions() const    { return m_cachable.detailedFunctions.get(this); }
detailedVariables() const2526     TemplateVariant detailedVariables() const    { return m_cachable.detailedVariables.get(this); }
inlineClasses() const2527     TemplateVariant inlineClasses() const        { return m_cachable.inlineClasses.get(this); }
2528 
2529   private:
createClasses() const2530     TemplateVariant createClasses() const
2531     {
2532       static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
2533       TemplateVariantList classList;
2534       classList.reserve(m_namespaceDef->getClasses().size());
2535       for (const auto &cd : m_namespaceDef->getClasses())
2536       {
2537         if (sliceOpt && (cd->compoundType()==ClassDef::Struct    ||
2538                          cd->compoundType()==ClassDef::Interface ||
2539                          cd->compoundType()==ClassDef::Exception))
2540         {
2541           continue; // These types appear in their own sections.
2542         }
2543         if (cd->visibleInParentsDeclList())
2544         {
2545           classList.push_back(ClassContext::alloc(cd));
2546         }
2547       }
2548       return TemplateImmutableList::alloc(classList);
2549     }
createNamespaces() const2550     TemplateVariant createNamespaces() const
2551     {
2552       TemplateVariantList list;
2553       list.reserve(m_namespaceDef->getNamespaces().size());
2554       for (const auto &nd : m_namespaceDef->getNamespaces())
2555       {
2556         if (nd->isLinkable() && !nd->isConstantGroup())
2557         {
2558           list.push_back(NamespaceContext::alloc(nd));
2559         }
2560       }
2561       return TemplateImmutableList::alloc(list);
2562     }
createConstantgroups() const2563     TemplateVariant createConstantgroups() const
2564     {
2565       TemplateVariantList list;
2566       list.reserve(m_namespaceDef->getNamespaces().size());
2567       for (const auto &nd : m_namespaceDef->getNamespaces())
2568       {
2569         if (nd->isLinkable() && nd->isConstantGroup())
2570         {
2571           list.push_back(NamespaceContext::alloc(nd));
2572         }
2573       }
2574       return TemplateImmutableList::alloc(list);
2575     }
createMemberList(MemberListType type,const QCString & title) const2576     TemplateVariant createMemberList(MemberListType type,const QCString &title) const
2577     {
2578       const MemberList *ml = m_namespaceDef->getMemberList(type);
2579       return ml ? TemplateVariant(MemberListInfoContext::alloc(m_namespaceDef,relPathAsString(),ml,title,""))
2580                 : TemplateVariant(false);
2581     }
createTypedefs() const2582     TemplateVariant createTypedefs() const
2583     {
2584       return createMemberList(MemberListType_decTypedefMembers,theTranslator->trTypedefs());
2585     }
createSequences() const2586     TemplateVariant createSequences() const
2587     {
2588       return createMemberList(MemberListType_decSequenceMembers,theTranslator->trSequences());
2589     }
createDictionaries() const2590     TemplateVariant createDictionaries() const
2591     {
2592       return createMemberList(MemberListType_decDictionaryMembers,theTranslator->trDictionaries());
2593     }
createEnums() const2594     TemplateVariant createEnums() const
2595     {
2596       return createMemberList(MemberListType_decEnumMembers,theTranslator->trEnumerations());
2597     }
createFunctions() const2598     TemplateVariant createFunctions() const
2599     {
2600       SrcLangExt lang = m_namespaceDef->getLanguage();
2601       return createMemberList(MemberListType_decFuncMembers,lang==SrcLangExt_Fortran ? theTranslator->trSubprograms() :
2602                                                             lang==SrcLangExt_VHDL    ? theTranslator->trFunctionAndProc() :
2603                                                                                        theTranslator->trFunctions());
2604     }
createVariables() const2605     TemplateVariant createVariables() const
2606     {
2607       static bool sliceOpt   = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
2608       return createMemberList(MemberListType_decVarMembers, sliceOpt ? theTranslator->trConstants() :
2609                                                                        theTranslator->trVariables());
2610     }
createDetailedTypedefs() const2611     TemplateVariant createDetailedTypedefs() const
2612     {
2613       return createMemberList(MemberListType_docTypedefMembers,theTranslator->trTypedefDocumentation());
2614     }
createDetailedSequences() const2615     TemplateVariant createDetailedSequences() const
2616     {
2617       return createMemberList(MemberListType_docSequenceMembers,theTranslator->trSequenceDocumentation());
2618     }
createDetailedDictionaries() const2619     TemplateVariant createDetailedDictionaries() const
2620     {
2621       return createMemberList(MemberListType_docDictionaryMembers,theTranslator->trDictionaryDocumentation());
2622     }
createDetailedEnums() const2623     TemplateVariant createDetailedEnums() const
2624     {
2625       return createMemberList(MemberListType_docEnumMembers,theTranslator->trEnumerationTypeDocumentation());
2626     }
createDetailedFunctions() const2627     TemplateVariant createDetailedFunctions() const
2628     {
2629       SrcLangExt lang = m_namespaceDef->getLanguage();
2630       return createMemberList(MemberListType_docFuncMembers, lang==SrcLangExt_Fortran ? theTranslator->trSubprogramDocumentation() :
2631                                                                                         theTranslator->trFunctionDocumentation());
2632     }
createDetailedVariables() const2633     TemplateVariant createDetailedVariables() const
2634     {
2635       static bool sliceOpt   = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
2636       return createMemberList(MemberListType_docVarMembers, sliceOpt ? theTranslator->trConstantDocumentation() :
2637                                                                        theTranslator->trVariableDocumentation());
2638     }
createMemberGroups() const2639     TemplateVariant createMemberGroups() const
2640     {
2641       return !m_namespaceDef->getMemberGroups().empty() ?
2642               MemberGroupListContext::alloc(m_namespaceDef,relPathAsString(),
2643                                                             m_namespaceDef->getMemberGroups(),
2644                                                             m_namespaceDef->subGrouping()) :
2645               MemberGroupListContext::alloc();
2646     }
createInlineClasses() const2647     TemplateVariant createInlineClasses() const
2648     {
2649       TemplateVariantList list;
2650       list.reserve(m_namespaceDef->getClasses().size());
2651       for (const auto &cd : m_namespaceDef->getClasses())
2652       {
2653         if (!cd->isAnonymous() &&
2654             cd->isLinkableInProject() &&
2655             cd->isEmbeddedInOuterScope() &&
2656             cd->partOfGroups().empty())
2657         {
2658           list.push_back(ClassContext::alloc(cd));
2659         }
2660       }
2661       return TemplateImmutableList::alloc(list);
2662     }
2663 
2664     const NamespaceDef *m_namespaceDef;
2665     struct Cachable : public DefinitionContext<NamespaceContext::Private>::Cachable
2666     {
2667       CachedItem<TemplateVariant,  Private, &Private::createClasses>              classes;
2668       CachedItem<TemplateVariant,  Private, &Private::createNamespaces>           namespaces;
2669       CachedItem<TemplateVariant,  Private, &Private::createConstantgroups>       constantgroups;
2670       CachedItem<TemplateVariant,  Private, &Private::createTypedefs>             typedefs;
2671       CachedItem<TemplateVariant,  Private, &Private::createSequences>            sequences;
2672       CachedItem<TemplateVariant,  Private, &Private::createDictionaries>         dictionaries;
2673       CachedItem<TemplateVariant,  Private, &Private::createEnums>                enums;
2674       CachedItem<TemplateVariant,  Private, &Private::createFunctions>            functions;
2675       CachedItem<TemplateVariant,  Private, &Private::createVariables>            variables;
2676       CachedItem<TemplateVariant,  Private, &Private::createMemberGroups>         memberGroups;
2677       CachedItem<TemplateVariant,  Private, &Private::createDetailedTypedefs>     detailedTypedefs;
2678       CachedItem<TemplateVariant,  Private, &Private::createDetailedSequences>    detailedSequences;
2679       CachedItem<TemplateVariant,  Private, &Private::createDetailedDictionaries> detailedDictionaries;
2680       CachedItem<TemplateVariant,  Private, &Private::createDetailedEnums>        detailedEnums;
2681       CachedItem<TemplateVariant,  Private, &Private::createDetailedFunctions>    detailedFunctions;
2682       CachedItem<TemplateVariant,  Private, &Private::createDetailedVariables>    detailedVariables;
2683       CachedItem<TemplateVariant,  Private, &Private::createInlineClasses>        inlineClasses;
2684     };
2685     Cachable m_cachable;
2686     static const PropertyMap<NamespaceContext::Private> s_inst;
2687 };
2688 
2689 //%% struct Namespace(Symbol): namespace information
2690 //%% {
2691 const PropertyMap<NamespaceContext::Private> NamespaceContext::Private::s_inst {
2692   BASE_PROPERTIES,
2693   {  "title",                &Private::title },
2694   {  "highlight",            &Private::highlight },
2695   {  "subhighlight",         &Private::subHighlight },
2696   {  "compoundType",         &Private::compoundType },
2697   {  "hasDetails",           &Private::hasDetails },
2698   {  "classes",              &Private::classes },
2699   {  "namespaces",           &Private::namespaces },
2700   {  "constantgroups",       &Private::constantgroups },
2701   {  "typedefs",             &Private::typedefs },
2702   {  "sequences",            &Private::sequences },
2703   {  "dictionaries",         &Private::dictionaries },
2704   {  "enums",                &Private::enums },
2705   {  "functions",            &Private::functions },
2706   {  "variables",            &Private::variables },
2707   {  "memberGroups",         &Private::memberGroups },
2708   {  "detailedTypedefs",     &Private::detailedTypedefs },
2709   {  "detailedSequences",    &Private::detailedSequences },
2710   {  "detailedDictionaries", &Private::detailedDictionaries },
2711   {  "detailedEnums",        &Private::detailedEnums },
2712   {  "detailedFunctions",    &Private::detailedFunctions },
2713   {  "detailedVariables",    &Private::detailedVariables },
2714   {  "inlineClasses",        &Private::inlineClasses }
2715 };
2716 //%% }
2717 
NamespaceContext(const NamespaceDef * nd)2718 NamespaceContext::NamespaceContext(const NamespaceDef *nd) : p(std::make_unique<Private>(nd))
2719 {
2720 }
2721 
~NamespaceContext()2722 NamespaceContext::~NamespaceContext()
2723 {
2724 }
2725 
get(const QCString & n) const2726 TemplateVariant NamespaceContext::get(const QCString &n) const
2727 {
2728   return p->get(n);
2729 }
2730 
fields() const2731 StringVector NamespaceContext::fields() const
2732 {
2733   return p->fields();
2734 }
2735 
2736 //------------------------------------------------------------------------
2737 
2738 class FileContext::Private : public DefinitionContext<FileContext::Private>
2739 {
2740   public:
Private(const FileDef * fd)2741     Private(const FileDef *fd) : DefinitionContext<FileContext::Private>(fd) , m_fileDef(fd)
2742     {
2743       if (fd==0) abort();
2744     }
~Private()2745     virtual ~Private() {}
2746 
2747     // TemplateStructIntf methods
get(const QCString & n) const2748     TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
fields() const2749     StringVector fields() const { return s_inst.fields(); }
2750 
2751     // Property getters
title() const2752     TemplateVariant title() const                 { return m_fileDef->title(); }
highlight() const2753     TemplateVariant highlight() const             { return TemplateVariant("files"); }
subHighlight() const2754     TemplateVariant subHighlight() const          { return TemplateVariant(""); }
versionInfo() const2755     TemplateVariant versionInfo() const           { return m_fileDef->getVersion(); }
includeList() const2756     TemplateVariant includeList() const           { return m_cachable.includeList.get(this); }
hasDetails() const2757     TemplateVariant hasDetails() const            { return m_fileDef->hasDetailedDescription(); }
hasSourceFile() const2758     TemplateVariant hasSourceFile() const         { return m_fileDef->generateSourceFile(); }
sources() const2759     TemplateVariant sources() const               { return m_cachable.sources.get(this); }
version() const2760     TemplateVariant version() const               { return m_fileDef->fileVersion(); }
classes() const2761     TemplateVariant classes() const               { return m_cachable.classes.get(this); }
namespaces() const2762     TemplateVariant namespaces() const            { return m_cachable.namespaces.get(this); }
constantgroups() const2763     TemplateVariant constantgroups() const        { return m_cachable.constantgroups.get(this); }
macros() const2764     TemplateVariant macros() const                { return m_cachable.macros.get(this); }
typedefs() const2765     TemplateVariant typedefs() const              { return m_cachable.typedefs.get(this); }
sequences() const2766     TemplateVariant sequences() const             { return m_cachable.sequences.get(this); }
dictionaries() const2767     TemplateVariant dictionaries() const          { return m_cachable.dictionaries.get(this); }
enums() const2768     TemplateVariant enums() const                 { return m_cachable.enums.get(this); }
functions() const2769     TemplateVariant functions() const             { return m_cachable.functions.get(this); }
variables() const2770     TemplateVariant variables() const             { return m_cachable.variables.get(this); }
memberGroups() const2771     TemplateVariant memberGroups() const          { return m_cachable.memberGroups.get(this); }
detailedMacros() const2772     TemplateVariant detailedMacros() const        { return m_cachable.detailedMacros.get(this); }
detailedTypedefs() const2773     TemplateVariant detailedTypedefs() const      { return m_cachable.detailedTypedefs.get(this); }
detailedSequences() const2774     TemplateVariant detailedSequences() const     { return m_cachable.detailedSequences.get(this); }
detailedDictionaries() const2775     TemplateVariant detailedDictionaries() const  { return m_cachable.detailedDictionaries.get(this); }
detailedEnums() const2776     TemplateVariant detailedEnums() const         { return m_cachable.detailedEnums.get(this); }
detailedFunctions() const2777     TemplateVariant detailedFunctions() const     { return m_cachable.detailedFunctions.get(this); }
detailedVariables() const2778     TemplateVariant detailedVariables() const     { return m_cachable.detailedVariables.get(this); }
inlineClasses() const2779     TemplateVariant inlineClasses() const         { return m_cachable.inlineClasses.get(this); }
compoundType() const2780     TemplateVariant compoundType() const          { return theTranslator->trFile(FALSE,TRUE); }
getIncludeGraph() const2781     DotInclDepGraphPtr getIncludeGraph() const    { return m_cachable.includeGraph.get(this); }
getIncludedByGraph() const2782     DotInclDepGraphPtr getIncludedByGraph() const { return m_cachable.includedByGraph.get(this); }
2783 
hasIncludeGraph() const2784     TemplateVariant hasIncludeGraph() const
2785     {
2786       static bool haveDot = Config_getBool(HAVE_DOT);
2787       DotInclDepGraphPtr incGraph = getIncludeGraph();
2788       return (haveDot && !incGraph->isTooBig() && !incGraph->isTrivial());
2789     }
includeGraph() const2790     TemplateVariant includeGraph() const
2791     {
2792       static bool haveDot = Config_getBool(HAVE_DOT);
2793       TextStream t;
2794       if (haveDot)
2795       {
2796         DotInclDepGraphPtr cg = getIncludeGraph();
2797         switch (g_globals.outputFormat)
2798         {
2799           case ContextOutputFormat_Html:
2800             {
2801               cg->writeGraph(t,GOF_BITMAP,EOF_Html,
2802                   g_globals.outputDir,
2803                   g_globals.outputDir+Portable::pathSeparator()+addHtmlExtensionIfMissing(m_fileDef->getOutputFileBase()),
2804                   relPathAsString(),TRUE,g_globals.dynSectionId
2805                   );
2806             }
2807             break;
2808           case ContextOutputFormat_Latex:
2809             {
2810               cg->writeGraph(t,GOF_EPS,EOF_LaTeX,
2811                   g_globals.outputDir,
2812                   g_globals.outputDir+Portable::pathSeparator()+m_fileDef->getOutputFileBase()+".tex",
2813                   relPathAsString(),TRUE,g_globals.dynSectionId
2814                   );
2815             }
2816             break;
2817             // TODO: support other generators
2818           default:
2819             err("context.cpp: output format not yet supported\n");
2820             break;
2821         }
2822         g_globals.dynSectionId++;
2823       }
2824       return TemplateVariant(t.str().c_str(),TRUE);
2825     }
hasIncludedByGraph() const2826     TemplateVariant hasIncludedByGraph() const
2827     {
2828       static bool haveDot = Config_getBool(HAVE_DOT);
2829       DotInclDepGraphPtr incGraph = getIncludedByGraph();
2830       return (haveDot && !incGraph->isTooBig() && !incGraph->isTrivial());
2831     }
includedByGraph() const2832     TemplateVariant includedByGraph() const
2833     {
2834       static bool haveDot = Config_getBool(HAVE_DOT);
2835       TextStream t;
2836       if (haveDot)
2837       {
2838         DotInclDepGraphPtr cg = getIncludedByGraph();
2839         switch (g_globals.outputFormat)
2840         {
2841           case ContextOutputFormat_Html:
2842             {
2843               cg->writeGraph(t,GOF_BITMAP,EOF_Html,
2844                   g_globals.outputDir,
2845                   g_globals.outputDir+Portable::pathSeparator()+addHtmlExtensionIfMissing(m_fileDef->getOutputFileBase()),
2846                   relPathAsString(),TRUE,g_globals.dynSectionId
2847                   );
2848             }
2849             break;
2850           case ContextOutputFormat_Latex:
2851             {
2852               cg->writeGraph(t,GOF_EPS,EOF_LaTeX,
2853                   g_globals.outputDir,
2854                   g_globals.outputDir+Portable::pathSeparator()+m_fileDef->getOutputFileBase()+".tex",
2855                   relPathAsString(),TRUE,g_globals.dynSectionId
2856                   );
2857             }
2858             break;
2859             // TODO: support other generators
2860           default:
2861             err("context.cpp: output format not yet supported\n");
2862             break;
2863         }
2864         g_globals.dynSectionId++;
2865       }
2866       return TemplateVariant(t.str().c_str(),TRUE);
2867     }
2868 
2869   private:
2870 
createIncludeList() const2871     TemplateVariant createIncludeList() const
2872     {
2873       return !m_fileDef->includeFileList().empty() ?
2874         TemplateVariant(IncludeInfoListContext::alloc(m_fileDef->includeFileList(),m_fileDef->getLanguage())) :
2875         TemplateVariant(false);
2876     }
createIncludeGraph() const2877     DotInclDepGraphPtr createIncludeGraph() const
2878     {
2879       return std::make_shared<DotInclDepGraph>(m_fileDef,FALSE);
2880     }
createIncludedByGraph() const2881     DotInclDepGraphPtr createIncludedByGraph() const
2882     {
2883       return std::make_shared<DotInclDepGraph>(m_fileDef,TRUE);
2884     }
createSources() const2885     TemplateVariant createSources() const
2886     {
2887       return m_fileDef->generateSourceFile() ?
2888           TemplateVariant(parseCode(m_fileDef,relPathAsString())) :
2889           TemplateVariant("");
2890     }
createClasses() const2891     TemplateVariant createClasses() const
2892     {
2893       TemplateVariantList list;
2894       list.reserve(m_fileDef->getClasses().size());
2895       for (const auto &cd : m_fileDef->getClasses())
2896       {
2897         if (cd->visibleInParentsDeclList())
2898         {
2899           list.push_back(ClassContext::alloc(cd));
2900         }
2901       }
2902       return TemplateImmutableList::alloc(list);
2903     }
createNamespaces() const2904     TemplateVariant createNamespaces() const
2905     {
2906       TemplateVariantList list;
2907       list.reserve(m_fileDef->getNamespaces().size());
2908       for (const auto &nd : m_fileDef->getNamespaces())
2909       {
2910         if (nd->isLinkable() && !nd->isConstantGroup())
2911         {
2912           list.push_back(NamespaceContext::alloc(nd));
2913         }
2914       }
2915       return TemplateImmutableList::alloc(list);
2916     }
createConstantgroups() const2917     TemplateVariant createConstantgroups() const
2918     {
2919       TemplateVariantList list;
2920       list.reserve(m_fileDef->getNamespaces().size());
2921       for (const auto &nd : m_fileDef->getNamespaces())
2922       {
2923         if (nd->isLinkable() && nd->isConstantGroup())
2924         {
2925           list.push_back(NamespaceContext::alloc(nd));
2926         }
2927       }
2928       return TemplateImmutableList::alloc(list);
2929     }
createMemberList(MemberListType type,const QCString & title) const2930     TemplateVariant createMemberList(MemberListType type,const QCString &title) const
2931     {
2932       const MemberList *ml = m_fileDef->getMemberList(type);
2933       return ml ? TemplateVariant(MemberListInfoContext::alloc(m_fileDef,relPathAsString(),ml,title,""))
2934                 : TemplateVariant(false);
2935     }
createMacros() const2936     TemplateVariant createMacros() const
2937     {
2938       return createMemberList(MemberListType_decDefineMembers,theTranslator->trDefines());
2939     }
createTypedefs() const2940     TemplateVariant createTypedefs() const
2941     {
2942       return createMemberList(MemberListType_decTypedefMembers,theTranslator->trTypedefs());
2943     }
createSequences() const2944     TemplateVariant createSequences() const
2945     {
2946       return createMemberList(MemberListType_decSequenceMembers,theTranslator->trSequences());
2947     }
createDictionaries() const2948     TemplateVariant createDictionaries() const
2949     {
2950       return createMemberList(MemberListType_decDictionaryMembers,theTranslator->trDictionaries());
2951     }
createEnums() const2952     TemplateVariant createEnums() const
2953     {
2954       return createMemberList(MemberListType_decEnumMembers,theTranslator->trEnumerations());
2955     }
createFunctions() const2956     TemplateVariant createFunctions() const
2957     {
2958       SrcLangExt lang = m_fileDef->getLanguage();
2959       return createMemberList(MemberListType_decFuncMembers, lang==SrcLangExt_Fortran ? theTranslator->trSubprograms() :
2960                                                              lang==SrcLangExt_VHDL    ? theTranslator->trFunctionAndProc() :
2961                                                                                         theTranslator->trFunctions());
2962     }
createVariables() const2963     TemplateVariant createVariables() const
2964     {
2965       static bool sliceOpt   = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
2966       return createMemberList(MemberListType_decVarMembers, sliceOpt ? theTranslator->trConstants() :
2967                                                                        theTranslator->trVariables());
2968     }
createDetailedMacros() const2969     TemplateVariant createDetailedMacros() const
2970     {
2971       return createMemberList(MemberListType_docDefineMembers,theTranslator->trDefineDocumentation());
2972     }
createDetailedTypedefs() const2973     TemplateVariant createDetailedTypedefs() const
2974     {
2975       return createMemberList(MemberListType_docTypedefMembers,theTranslator->trTypedefDocumentation());
2976     }
createDetailedSequences() const2977     TemplateVariant createDetailedSequences() const
2978     {
2979       return createMemberList(MemberListType_docSequenceMembers,theTranslator->trSequenceDocumentation());
2980     }
createDetailedDictionaries() const2981     TemplateVariant createDetailedDictionaries() const
2982     {
2983       return createMemberList(MemberListType_docDictionaryMembers,theTranslator->trDictionaryDocumentation());
2984     }
createDetailedEnums() const2985     TemplateVariant createDetailedEnums() const
2986     {
2987       return createMemberList(MemberListType_docEnumMembers,theTranslator->trEnumerationTypeDocumentation());
2988     }
createDetailedFunctions() const2989     TemplateVariant createDetailedFunctions() const
2990     {
2991       SrcLangExt lang = m_fileDef->getLanguage();
2992       return createMemberList(MemberListType_docFuncMembers, lang==SrcLangExt_Fortran ? theTranslator->trSubprogramDocumentation() :
2993                                                                                         theTranslator->trFunctionDocumentation());
2994     }
createDetailedVariables() const2995     TemplateVariant createDetailedVariables() const
2996     {
2997       return createMemberList(MemberListType_docVarMembers,theTranslator->trVariableDocumentation());
2998     }
createMemberGroups() const2999     TemplateVariant createMemberGroups() const
3000     {
3001       return !m_fileDef->getMemberGroups().empty() ?
3002           MemberGroupListContext::alloc(m_fileDef,relPathAsString(),m_fileDef->getMemberGroups(),m_fileDef->subGrouping()) :
3003           MemberGroupListContext::alloc();
3004     }
createInlineClasses() const3005     TemplateVariant createInlineClasses() const
3006     {
3007       TemplateVariantList list;
3008       list.reserve(m_fileDef->getClasses().size());
3009       for (const auto &cd : m_fileDef->getClasses())
3010       {
3011         if (!cd->isAnonymous() &&
3012             cd->isLinkableInProject() &&
3013             cd->isEmbeddedInOuterScope() &&
3014             cd->partOfGroups().empty())
3015         {
3016           list.push_back(ClassContext::alloc(cd));
3017         }
3018       }
3019       return TemplateImmutableList::alloc(list);
3020     }
3021 
3022     const FileDef *m_fileDef;
3023     struct Cachable : public DefinitionContext<FileContext::Private>::Cachable
3024     {
3025       CachedItem<TemplateVariant,    Private, &Private::createIncludeList>          includeList;
3026       CachedItem<DotInclDepGraphPtr, Private, &Private::createIncludeGraph>         includeGraph;
3027       CachedItem<DotInclDepGraphPtr, Private, &Private::createIncludedByGraph>      includedByGraph;
3028       CachedItem<TemplateVariant,    Private, &Private::createSources>              sources;
3029       CachedItem<TemplateVariant,    Private, &Private::createClasses>              classes;
3030       CachedItem<TemplateVariant,    Private, &Private::createNamespaces>           namespaces;
3031       CachedItem<TemplateVariant,    Private, &Private::createConstantgroups>       constantgroups;
3032       CachedItem<TemplateVariant,    Private, &Private::createMacros>               macros;
3033       CachedItem<TemplateVariant,    Private, &Private::createTypedefs>             typedefs;
3034       CachedItem<TemplateVariant,    Private, &Private::createSequences>            sequences;
3035       CachedItem<TemplateVariant,    Private, &Private::createDictionaries>         dictionaries;
3036       CachedItem<TemplateVariant,    Private, &Private::createEnums>                enums;
3037       CachedItem<TemplateVariant,    Private, &Private::createFunctions>            functions;
3038       CachedItem<TemplateVariant,    Private, &Private::createVariables>            variables;
3039       CachedItem<TemplateVariant,    Private, &Private::createMemberGroups>         memberGroups;
3040       CachedItem<TemplateVariant,    Private, &Private::createDetailedMacros>       detailedMacros;
3041       CachedItem<TemplateVariant,    Private, &Private::createDetailedTypedefs>     detailedTypedefs;
3042       CachedItem<TemplateVariant,    Private, &Private::createDetailedSequences>    detailedSequences;
3043       CachedItem<TemplateVariant,    Private, &Private::createDetailedDictionaries> detailedDictionaries;
3044       CachedItem<TemplateVariant,    Private, &Private::createDetailedEnums>        detailedEnums;
3045       CachedItem<TemplateVariant,    Private, &Private::createDetailedFunctions>    detailedFunctions;
3046       CachedItem<TemplateVariant,    Private, &Private::createDetailedVariables>    detailedVariables;
3047       CachedItem<TemplateVariant,    Private, &Private::createInlineClasses>        inlineClasses;
3048     };
3049     Cachable m_cachable;
3050     static const PropertyMap<FileContext::Private> s_inst;
3051 };
3052 
3053 //%% struct File(Symbol): file information
3054 //%% {
3055 const PropertyMap<FileContext::Private> FileContext::Private::s_inst {
3056   BASE_PROPERTIES,
3057   {  "title",                     &Private::title },
3058   {  "highlight",                 &Private::highlight },
3059   {  "subhighlight",              &Private::subHighlight },
3060   {  "versionInfo",               &Private::versionInfo },
3061   {  "includeList",               &Private::includeList },
3062   {  "hasIncludeGraph",           &Private::hasIncludeGraph },
3063   {  "hasIncludedByGraph",        &Private::hasIncludedByGraph },
3064   {  "includeGraph",              &Private::includeGraph },
3065   {  "includedByGraph",           &Private::includedByGraph },
3066   {  "hasDetails",                &Private::hasDetails },
3067   {  "hasSourceFile",             &Private::hasSourceFile },
3068   {  "sources",                   &Private::sources },
3069   {  "version",                   &Private::version },
3070   {  "classes",                   &Private::classes },
3071   {  "namespaces",                &Private::namespaces },
3072   {  "constantgroups",            &Private::constantgroups },
3073   {  "macros",                    &Private::macros },
3074   {  "typedefs",                  &Private::typedefs },
3075   {  "sequences",                 &Private::sequences },
3076   {  "dictionaries",              &Private::dictionaries },
3077   {  "enums",                     &Private::enums },
3078   {  "functions",                 &Private::functions },
3079   {  "variables",                 &Private::variables },
3080   {  "memberGroups",              &Private::memberGroups },
3081   {  "detailedMacros",            &Private::detailedMacros },
3082   {  "detailedTypedefs",          &Private::detailedTypedefs },
3083   {  "detailedSequences",         &Private::detailedSequences },
3084   {  "detailedDictionaries",      &Private::detailedDictionaries },
3085   {  "detailedEnums",             &Private::detailedEnums },
3086   {  "detailedFunctions",         &Private::detailedFunctions },
3087   {  "detailedVariables",         &Private::detailedVariables },
3088   {  "inlineClasses",             &Private::inlineClasses },
3089   {  "compoundType",              &Private::compoundType }
3090 };
3091 //%% }
3092 
3093 //PropertyMapper<FileContext::Private> FileContext::Private::s_inst;
3094 
FileContext(const FileDef * fd)3095 FileContext::FileContext(const FileDef *fd) : p(std::make_unique<Private>(fd))
3096 {
3097 }
3098 
~FileContext()3099 FileContext::~FileContext()
3100 {
3101 }
3102 
get(const QCString & n) const3103 TemplateVariant FileContext::get(const QCString &n) const
3104 {
3105   return p->get(n);
3106 }
3107 
fields() const3108 StringVector FileContext::fields() const
3109 {
3110   return p->fields();
3111 }
3112 
3113 //------------------------------------------------------------------------
3114 
3115 class DirContext::Private : public DefinitionContext<DirContext::Private>
3116 {
3117   public:
Private(const DirDef * dd)3118     Private(const DirDef *dd) : DefinitionContext<DirContext::Private>(dd) , m_dirDef(dd)
3119     {
3120     }
~Private()3121     virtual ~Private() {}
3122 
3123     // TemplateStructIntf methods
get(const QCString & n) const3124     TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
fields() const3125     StringVector fields() const                  { return s_inst.fields(); }
3126 
3127     // Property getters
title() const3128     TemplateVariant title() const                { return TemplateVariant(m_dirDef->shortTitle()); }
highlight() const3129     TemplateVariant highlight() const            { return TemplateVariant("files"); }
subHighlight() const3130     TemplateVariant subHighlight() const         { return TemplateVariant(""); }
dirName() const3131     TemplateVariant dirName() const              { return TemplateVariant(m_dirDef->shortName()); }
dirs() const3132     TemplateVariant dirs() const                 { return m_cachable.dirs.get(this); }
files() const3133     TemplateVariant files() const                { return m_cachable.files.get(this); }
hasDetails() const3134     TemplateVariant hasDetails() const           { return m_dirDef->hasDetailedDescription(); }
compoundType() const3135     TemplateVariant compoundType() const         { return theTranslator->trDir(FALSE,TRUE); }
relPath() const3136     TemplateVariant relPath() const              { return ""; }
getDirDepsGraph() const3137     DotDirDepsPtr   getDirDepsGraph() const      { return m_cachable.dirDepsGraph.get(this); }
3138 
hasDirGraph() const3139     TemplateVariant hasDirGraph() const
3140     {
3141       bool result=FALSE;
3142       static bool haveDot  = Config_getBool(HAVE_DOT);
3143       static bool dirGraph = Config_getBool(DIRECTORY_GRAPH);
3144       if (haveDot && dirGraph)
3145       {
3146         DotDirDepsPtr graph = getDirDepsGraph();
3147         result = !graph->isTrivial();
3148       }
3149       return result;
3150     }
dirGraph() const3151     TemplateVariant dirGraph() const
3152     {
3153       TextStream t;
3154       static bool haveDot  = Config_getBool(HAVE_DOT);
3155       static bool dirGraph = Config_getBool(DIRECTORY_GRAPH);
3156       if (haveDot && dirGraph)
3157       {
3158         DotDirDepsPtr graph = getDirDepsGraph();
3159         switch (g_globals.outputFormat)
3160         {
3161           case ContextOutputFormat_Html:
3162             {
3163               graph->writeGraph(t,GOF_BITMAP,
3164                                 EOF_Html,
3165                                 g_globals.outputDir,
3166                                 g_globals.outputDir+Portable::pathSeparator()+addHtmlExtensionIfMissing(m_dirDef->getOutputFileBase()),
3167                                 relPathAsString(),
3168                                 TRUE,
3169                                 g_globals.dynSectionId,
3170                                 FALSE);
3171             }
3172             break;
3173           case ContextOutputFormat_Latex:
3174             {
3175               graph->writeGraph(t,GOF_EPS,
3176                                 EOF_LaTeX,
3177                                 g_globals.outputDir,
3178                                 g_globals.outputDir+Portable::pathSeparator()+m_dirDef->getOutputFileBase()+".tex",
3179                                 relPathAsString(),
3180                                 TRUE,
3181                                 g_globals.dynSectionId,
3182                                 FALSE);
3183             }
3184             break;
3185             // TODO: support other generators
3186           default:
3187             err("context.cpp: output format not yet supported\n");
3188             break;
3189         }
3190         g_globals.dynSectionId++;
3191       }
3192       return TemplateVariant(t.str().c_str(),TRUE);
3193     }
3194 
3195   private:
createDirs() const3196     TemplateVariant createDirs() const
3197     {
3198       TemplateVariantList list;
3199       list.reserve(m_dirDef->subDirs().size());
3200       for(const auto dd : m_dirDef->subDirs())
3201       {
3202         list.push_back(DirContext::alloc(dd));
3203       }
3204       return TemplateImmutableList::alloc(list);
3205     }
createFiles() const3206     TemplateVariant createFiles() const
3207     {
3208       TemplateVariantList list;
3209       list.reserve(m_dirDef->getFiles().size());
3210       for (const auto &fd : m_dirDef->getFiles())
3211       {
3212         list.push_back(FileContext::alloc(fd));
3213       }
3214       return TemplateImmutableList::alloc(list);
3215     }
createDirDepsGraph() const3216     DotDirDepsPtr createDirDepsGraph() const
3217     {
3218       return std::make_shared<DotDirDeps>(m_dirDef);
3219     }
3220     const DirDef *m_dirDef;
3221     struct Cachable : public DefinitionContext<DirContext::Private>::Cachable
3222     {
3223       CachedItem<TemplateVariant,  Private, &Private::createDirs>         dirs;
3224       CachedItem<TemplateVariant,  Private, &Private::createFiles>        files;
3225       CachedItem<DotDirDepsPtr,    Private, &Private::createDirDepsGraph> dirDepsGraph;
3226     };
3227     Cachable m_cachable;
3228     static const PropertyMap<DirContext::Private> s_inst;
3229 };
3230 
3231 //%% struct Dir(Symbol): directory information
3232 //%% {
3233 const PropertyMap<DirContext::Private> DirContext::Private::s_inst {
3234   BASE_PROPERTIES,
3235   {  "title",         &Private::title },
3236   {  "highlight",     &Private::highlight },
3237   {  "subhighlight",  &Private::subHighlight },
3238   {  "dirName",       &Private::dirName },
3239   {  "dirs",          &Private::dirs },
3240   {  "files",         &Private::files },
3241   {  "hasDetails",    &Private::hasDetails },
3242   {  "hasDirGraph",   &Private::hasDirGraph },
3243   {  "dirGraph",      &Private::dirGraph },
3244   {  "compoundType",  &Private::compoundType }
3245 };
3246 //%% }
3247 
3248 //PropertyMapper<DirContext::Private> DirContext::Private::s_inst;
3249 
DirContext(const DirDef * fd)3250 DirContext::DirContext(const DirDef *fd) : p(std::make_unique<Private>(fd))
3251 {
3252 }
3253 
~DirContext()3254 DirContext::~DirContext()
3255 {
3256 }
3257 
get(const QCString & n) const3258 TemplateVariant DirContext::get(const QCString &n) const
3259 {
3260   return p->get(n);
3261 }
3262 
fields() const3263 StringVector DirContext::fields() const
3264 {
3265   return p->fields();
3266 }
3267 
3268 //------------------------------------------------------------------------
3269 
3270 class PageContext::Private : public DefinitionContext<PageContext::Private>
3271 {
3272   public:
Private(const PageDef * pd,bool isMainPage,bool isExample)3273     Private(const PageDef *pd,bool isMainPage,bool isExample)
3274       : DefinitionContext<PageContext::Private>(pd) , m_pageDef(pd), m_isMainPage(isMainPage),
3275         m_isExample(isExample)
3276     {
3277     }
~Private()3278     virtual ~Private() {}
3279 
3280     // TemplateStructIntf methods
get(const QCString & n) const3281     TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
fields() const3282     StringVector fields() const                  { return s_inst.fields(); }
3283 
3284     // Property getters
title() const3285     TemplateVariant title() const
3286     {
3287       if (m_isMainPage)
3288       {
3289         QCString projectName = Config_getString(PROJECT_NAME);
3290         if (Doxygen::mainPage && !Doxygen::mainPage->title().isEmpty())
3291         {
3292           if (Doxygen::mainPage->title().lower()!="notitle")
3293           {
3294             return m_pageDef->title();
3295           }
3296           else
3297           {
3298             return "";
3299           }
3300         }
3301         else if (!projectName.isEmpty())
3302         {
3303           return projectName+" "+theTranslator->trDocumentation();
3304         }
3305         else
3306         {
3307           return theTranslator->trMainPage();
3308         }
3309       }
3310       else if (m_isExample)
3311       {
3312         return m_pageDef->name();
3313       }
3314       else
3315       {
3316         return m_pageDef->title();
3317       }
3318     }
relPath() const3319     TemplateVariant relPath() const
3320     {
3321       return m_isMainPage ? TemplateVariant("") :
3322                             TemplateVariant(DefinitionContext<PageContext::Private>::relPath());
3323     }
highlight() const3324     TemplateVariant highlight() const
3325     {
3326       if (m_isMainPage)
3327       {
3328         return "main";
3329       }
3330       else
3331       {
3332         return "pages";
3333       }
3334     }
subHighlight() const3335     TemplateVariant subHighlight() const
3336     {
3337       return "";
3338     }
example() const3339     TemplateVariant example() const
3340     {
3341       return m_cachable.example.get(this);
3342     }
3343   private:
createExample() const3344     TemplateVariant createExample() const
3345     {
3346       return m_isExample ?
3347           TemplateVariant(parseDoc(m_pageDef,m_pageDef->docFile(),m_pageDef->docLine(),
3348                   relPathAsString(),"\\include "+m_pageDef->name(),FALSE)) :
3349           TemplateVariant("");
3350     }
3351 
3352     const PageDef *m_pageDef;
3353     struct Cachable : public DefinitionContext<PageContext::Private>::Cachable
3354     {
3355       CachedItem<TemplateVariant,  Private, &Private::createExample> example;
3356     };
3357     Cachable m_cachable;
3358     bool m_isMainPage;
3359     bool m_isExample;
3360     static const PropertyMap<PageContext::Private> s_inst;
3361 };
3362 
3363 //%% struct Page(Symbol): page information
3364 //%% {
3365 const PropertyMap<PageContext::Private> PageContext::Private::s_inst {
3366   BASE_PROPERTIES,
3367   {  "title",       &Private::title },
3368   {  "highlight",   &Private::highlight },
3369   {  "subhighlight",&Private::subHighlight },
3370   {  "example",     &Private::example }
3371 };
3372 //%% }
3373 
PageContext(const PageDef * pd,bool isMainPage,bool isExample)3374 PageContext::PageContext(const PageDef *pd,bool isMainPage,bool isExample) : p(std::make_unique<Private>(pd,isMainPage,isExample))
3375 {
3376 }
3377 
~PageContext()3378 PageContext::~PageContext()
3379 {
3380 }
3381 
get(const QCString & n) const3382 TemplateVariant PageContext::get(const QCString &n) const
3383 {
3384   return p->get(n);
3385 }
3386 
fields() const3387 StringVector PageContext::fields() const
3388 {
3389   return p->fields();
3390 }
3391 
3392 //------------------------------------------------------------------------
3393 
3394 class TextGeneratorHtml : public TextGeneratorIntf
3395 {
3396   public:
TextGeneratorHtml(TextStream & ts,const QCString & relPath)3397     TextGeneratorHtml(TextStream &ts,const QCString &relPath)
3398        : m_ts(ts), m_relPath(relPath) {}
writeString(const QCString & s,bool keepSpaces) const3399     void writeString(const QCString &s,bool keepSpaces) const
3400     {
3401       static const char *hex="0123456789ABCDEF";
3402       if (s.isEmpty()) return;
3403       if (keepSpaces)
3404       {
3405         const char *p=s.data();
3406         char c;
3407         while ((c=*p++))
3408         {
3409           switch(c)
3410           {
3411             case '<':  m_ts << "&lt;"; break;
3412             case '>':  m_ts << "&gt;"; break;
3413             case '\'': m_ts << "&#39;"; break;
3414             case '"':  m_ts << "&quot;"; break;
3415             case '&':  m_ts << "&amp;"; break;
3416             case ' ':  m_ts << "&#160;"; break;
3417             default:
3418               {
3419                 uchar uc = static_cast<uchar>(c);
3420                 if (uc<32 && !isspace(c)) // non-printable control characters
3421                 {
3422                   m_ts << "&#x24" << hex[uc>>4] << hex[uc&0xF] << ";";
3423                 }
3424                 else
3425                 {
3426                   m_ts << c;
3427                 }
3428               }
3429               break;
3430           }
3431         }
3432       }
3433       else
3434       {
3435         m_ts << convertToHtml(s);
3436       }
3437     }
3438 
writeBreak(int indent) const3439     void writeBreak(int indent) const
3440     {
3441       m_ts << "<br />";
3442       for (int i=0;i<indent;i++)
3443       {
3444         m_ts << "&#160;";
3445       }
3446     }
3447 
writeLink(const QCString & ref,const QCString & f,const QCString & anchor,const QCString & name) const3448     void writeLink(const QCString &ref,const QCString &f,
3449                    const QCString &anchor,const QCString &name
3450                   ) const
3451     {
3452       if (!ref.isEmpty())
3453       {
3454         m_ts << "<a class=\"elRef\" ";
3455         m_ts << externalLinkTarget();
3456       }
3457       else
3458       {
3459         m_ts << "<a class=\"el\" ";
3460       }
3461       m_ts << "href=\"";
3462       m_ts << externalRef(m_relPath,ref,TRUE);
3463       if (!f.isEmpty()) m_ts << addHtmlExtensionIfMissing(f);
3464       if (!anchor.isEmpty()) m_ts << "#" << anchor;
3465       m_ts << "\">";
3466       m_ts << convertToHtml(name);
3467       m_ts << "</a>";
3468     }
3469 
3470   private:
3471     TextStream &m_ts;
3472     QCString m_relPath;
3473 };
3474 
3475 //------------------------------------------------------------------------
3476 
3477 class TextGeneratorLatex : public TextGeneratorIntf
3478 {
3479   public:
TextGeneratorLatex(TextStream & ts)3480     TextGeneratorLatex(TextStream &ts) : m_ts(ts) {}
writeString(const QCString & s,bool keepSpaces) const3481     void writeString(const QCString &s,bool keepSpaces) const
3482     {
3483       if (s==0) return;
3484       m_ts << convertToLaTeX(s,FALSE,keepSpaces);
3485     }
writeBreak(int indent) const3486     void writeBreak(int indent) const
3487     {
3488       m_ts << "\\\\*\n";
3489       for (int i=0;i<indent;i++)
3490       {
3491         m_ts << "~";
3492       }
3493     }
writeLink(const QCString & ref,const QCString & f,const QCString & anchor,const QCString & text) const3494     void writeLink(const QCString &ref,const QCString &f,
3495                    const QCString &anchor,const QCString &text
3496                   ) const
3497     {
3498       static bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS);
3499       if (ref.isEmpty() && pdfHyperlinks)
3500       {
3501         m_ts << "\\mbox{\\hyperlink{";
3502         if (!f.isEmpty()) m_ts << stripPath(f);
3503         if (!f.isEmpty() && !anchor.isEmpty()) m_ts << "_";
3504         if (!anchor.isEmpty()) m_ts << anchor;
3505         m_ts << "}{";
3506         filterLatexString(m_ts,text,
3507                           false, // insideTabbing
3508                           false, // insidePre
3509                           false, // insideItem
3510                           false, // insideTable
3511                           false  // keepSpaces
3512                          );
3513         m_ts << "}}";
3514       }
3515       else
3516       {
3517         m_ts << "\\textbf{ ";
3518         filterLatexString(m_ts,text,
3519                           false, // insideTabbing
3520                           false, // insidePre
3521                           false, // insideItem
3522                           false, // insideTable
3523                           false  // keepSpaces
3524                          );
3525         m_ts << "}";
3526       }
3527     }
3528 
3529   private:
3530     TextStream &m_ts;
3531 };
3532 
3533 //------------------------------------------------------------------------
3534 
3535 class TextGeneratorFactory
3536 {
3537   public:
instance()3538     static TextGeneratorFactory *instance()
3539     {
3540       static TextGeneratorFactory *instance = new TextGeneratorFactory;
3541       return instance;
3542     }
create(TextStream & ts,const QCString & relPath)3543     TextGeneratorIntf *create(TextStream &ts,const QCString &relPath)
3544     {
3545       switch (g_globals.outputFormat)
3546       {
3547         case ContextOutputFormat_Html:
3548           return new TextGeneratorHtml(ts,relPath);
3549         case ContextOutputFormat_Latex:
3550           return new TextGeneratorLatex(ts);
3551         default:
3552           break;
3553       }
3554       return 0;
3555     }
3556   private:
TextGeneratorFactory()3557     TextGeneratorFactory() {}
~TextGeneratorFactory()3558     virtual ~TextGeneratorFactory() {}
3559 };
3560 
createLinkedText(const Definition * def,const QCString & relPath,const QCString & text)3561 TemplateVariant createLinkedText(const Definition *def,const QCString &relPath,const QCString &text)
3562 {
3563   TextStream ts;
3564   TextGeneratorIntf *tg = TextGeneratorFactory::instance()->create(ts,relPath);
3565   if (tg)
3566   {
3567     linkifyText(*tg,def->getOuterScope(),def->getBodyDef(),def,text);
3568     delete tg;
3569     return TemplateVariant(ts.str().c_str(),true);
3570   }
3571   else
3572   {
3573     return text;
3574   }
3575 }
3576 
3577 class MemberContext::Private : public DefinitionContext<MemberContext::Private>
3578 {
3579   public:
Private(const MemberDef * md)3580     Private(const MemberDef *md) : DefinitionContext<MemberContext::Private>(md) , m_memberDef(md)
3581     {
3582     }
~Private()3583     virtual ~Private() {}
3584 
3585     // TemplateStructIntf methods
get(const QCString & n) const3586     TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
fields() const3587     StringVector fields() const                  { return s_inst.fields(); }
3588 
3589     // Property getters
isStatic() const3590     TemplateVariant isStatic() const                 { return m_memberDef->isStatic(); }
isObjCMethod() const3591     TemplateVariant isObjCMethod() const             { return m_memberDef->isObjCMethod(); }
isObjCProperty() const3592     TemplateVariant isObjCProperty() const           { return m_memberDef->isObjCProperty(); }
isCSharpProperty() const3593     TemplateVariant isCSharpProperty() const         { return m_memberDef->isCSharpProperty(); }
isImplementation() const3594     TemplateVariant isImplementation() const         { return m_memberDef->isImplementation(); }
isSignal() const3595     TemplateVariant isSignal() const                 { return m_memberDef->isSignal(); }
isSlot() const3596     TemplateVariant isSlot() const                   { return m_memberDef->isSlot(); }
isTypedef() const3597     TemplateVariant isTypedef() const                { return m_memberDef->isTypedef(); }
isFunction() const3598     TemplateVariant isFunction() const               { return m_memberDef->isFunction(); }
isFunctionPtr() const3599     TemplateVariant isFunctionPtr() const            { return m_memberDef->isFunctionPtr(); }
isFriend() const3600     TemplateVariant isFriend() const                 { return m_memberDef->isFriend(); }
isForeign() const3601     TemplateVariant isForeign() const                { return m_memberDef->isForeign(); }
isEvent() const3602     TemplateVariant isEvent() const                  { return m_memberDef->isEvent(); }
isInline() const3603     TemplateVariant isInline() const                 { return m_memberDef->isInline(); }
isExplicit() const3604     TemplateVariant isExplicit() const               { return m_memberDef->isExplicit(); }
isMutable() const3605     TemplateVariant isMutable() const                { return m_memberDef->isMutable(); }
isGettable() const3606     TemplateVariant isGettable() const               { return m_memberDef->isGettable(); }
isPrivateGettable() const3607     TemplateVariant isPrivateGettable() const        { return m_memberDef->isPrivateGettable(); }
isProtectedGettable() const3608     TemplateVariant isProtectedGettable() const      { return m_memberDef->isProtectedGettable(); }
isSettable() const3609     TemplateVariant isSettable() const               { return m_memberDef->isSettable(); }
isPrivateSettable() const3610     TemplateVariant isPrivateSettable() const        { return m_memberDef->isPrivateSettable(); }
isProtectedSettable() const3611     TemplateVariant isProtectedSettable() const      { return m_memberDef->isProtectedSettable(); }
isReadable() const3612     TemplateVariant isReadable() const               { return m_memberDef->isReadable(); }
isWritable() const3613     TemplateVariant isWritable() const               { return m_memberDef->isWritable(); }
isAddable() const3614     TemplateVariant isAddable() const                { return m_memberDef->isAddable(); }
isRemovable() const3615     TemplateVariant isRemovable() const              { return m_memberDef->isRemovable(); }
isRaisable() const3616     TemplateVariant isRaisable() const               { return m_memberDef->isRaisable(); }
isFinal() const3617     TemplateVariant isFinal() const                  { return m_memberDef->isFinal(); }
isAbstract() const3618     TemplateVariant isAbstract() const               { return m_memberDef->isAbstract(); }
isOverride() const3619     TemplateVariant isOverride() const               { return m_memberDef->isOverride(); }
isInitonly() const3620     TemplateVariant isInitonly() const               { return m_memberDef->isInitonly(); }
isOptional() const3621     TemplateVariant isOptional() const               { return m_memberDef->isOptional(); }
isRequired() const3622     TemplateVariant isRequired() const               { return m_memberDef->isRequired(); }
isNonAtomic() const3623     TemplateVariant isNonAtomic() const              { return m_memberDef->isNonAtomic(); }
isCopy() const3624     TemplateVariant isCopy() const                   { return m_memberDef->isCopy(); }
isAssign() const3625     TemplateVariant isAssign() const                 { return m_memberDef->isAssign(); }
isRetain() const3626     TemplateVariant isRetain() const                 { return m_memberDef->isRetain(); }
isWeak() const3627     TemplateVariant isWeak() const                   { return m_memberDef->isWeak(); }
isStrong() const3628     TemplateVariant isStrong() const                 { return m_memberDef->isStrong(); }
isEnumStruct() const3629     TemplateVariant isEnumStruct() const             { return m_memberDef->isEnumStruct(); }
isUnretained() const3630     TemplateVariant isUnretained() const             { return m_memberDef->isUnretained(); }
isNew() const3631     TemplateVariant isNew() const                    { return m_memberDef->isNew(); }
isSealed() const3632     TemplateVariant isSealed() const                 { return m_memberDef->isSealed(); }
isExternal() const3633     TemplateVariant isExternal() const               { return m_memberDef->isExternal(); }
isTypeAlias() const3634     TemplateVariant isTypeAlias() const              { return m_memberDef->isTypeAlias(); }
isDefault() const3635     TemplateVariant isDefault() const                { return m_memberDef->isDefault(); }
isDelete() const3636     TemplateVariant isDelete() const                 { return m_memberDef->isDelete(); }
isNoExcept() const3637     TemplateVariant isNoExcept() const               { return m_memberDef->isNoExcept(); }
isAttribute() const3638     TemplateVariant isAttribute() const              { return m_memberDef->isAttribute(); }
isUNOProperty() const3639     TemplateVariant isUNOProperty() const            { return m_memberDef->isUNOProperty(); }
isReadonly() const3640     TemplateVariant isReadonly() const               { return m_memberDef->isReadonly(); }
isBound() const3641     TemplateVariant isBound() const                  { return m_memberDef->isBound(); }
isConstrained() const3642     TemplateVariant isConstrained() const            { return m_memberDef->isConstrained(); }
isTransient() const3643     TemplateVariant isTransient() const              { return m_memberDef->isTransient(); }
isMaybeVoid() const3644     TemplateVariant isMaybeVoid() const              { return m_memberDef->isMaybeVoid(); }
isMaybeDefault() const3645     TemplateVariant isMaybeDefault() const           { return m_memberDef->isMaybeDefault(); }
isMaybeAmbiguous() const3646     TemplateVariant isMaybeAmbiguous() const         { return m_memberDef->isMaybeAmbiguous(); }
isPublished() const3647     TemplateVariant isPublished() const              { return m_memberDef->isPublished(); }
isTemplateSpecialization() const3648     TemplateVariant isTemplateSpecialization() const { return m_memberDef->isTemplateSpecialization(); }
isProperty() const3649     TemplateVariant isProperty() const               { return m_memberDef->isProperty(); }
isEnumValue() const3650     TemplateVariant isEnumValue() const              { return m_memberDef->isEnumValue(); }
isVariable() const3651     TemplateVariant isVariable() const               { return m_memberDef->isVariable(); }
isEnumeration() const3652     TemplateVariant isEnumeration() const            { return m_memberDef->isEnumerate(); }
hasDetails() const3653     TemplateVariant hasDetails() const               { return m_memberDef->hasDetailedDescription(); }
isDefine() const3654     TemplateVariant isDefine() const                 { return m_memberDef->isDefine(); }
isAnonymous() const3655     TemplateVariant isAnonymous() const              { return m_memberDef->isAnonymous(); }
isRelated() const3656     TemplateVariant isRelated() const                { return m_memberDef->isRelated(); }
enumBaseType() const3657     TemplateVariant enumBaseType() const             { return m_memberDef->enumBaseType(); }
hasOneLineInitializer() const3658     TemplateVariant hasOneLineInitializer() const    { return m_memberDef->hasOneLineInitializer(); }
hasMultiLineInitializer() const3659     TemplateVariant hasMultiLineInitializer() const  { return m_memberDef->hasMultiLineInitializer(); }
extraTypeChars() const3660     TemplateVariant extraTypeChars() const           { return m_memberDef->extraTypeChars(); }
type() const3661     TemplateVariant type() const                     { return m_memberDef->typeString(); }
fieldType() const3662     TemplateVariant fieldType() const                { return m_cachable.fieldType.get(this); }
declType() const3663     TemplateVariant declType() const                 { return m_cachable.declType.get(this); }
declArgs() const3664     TemplateVariant declArgs() const                 { return m_cachable.declArgs.get(this); }
exception() const3665     TemplateVariant exception() const                { return m_cachable.exception.get(this); }
bitfields() const3666     TemplateVariant bitfields() const                { return m_cachable.bitfields.get(this); }
initializer() const3667     TemplateVariant initializer() const              { return m_cachable.initializer.get(this); }
initializerAsCode() const3668     TemplateVariant initializerAsCode() const        { return m_cachable.initializerAsCode.get(this); }
anonymousType() const3669     TemplateVariant anonymousType() const            { return m_cachable.anonymousType.get(this); }
anonymousMember() const3670     TemplateVariant anonymousMember() const          { return m_cachable.anonymousMember.get(this); }
enumValues() const3671     TemplateVariant enumValues() const               { return m_cachable.enumValues.get(this); }
templateArgs() const3672     TemplateVariant templateArgs() const             { return m_cachable.templateArgs.get(this); }
templateAlias() const3673     TemplateVariant templateAlias() const            { return m_cachable.templateAlias.get(this); }
propertyAttrs() const3674     TemplateVariant propertyAttrs() const            { return m_cachable.propertyAttrs.get(this); }
eventAttrs() const3675     TemplateVariant eventAttrs() const               { return m_cachable.eventAttrs.get(this); }
getClass() const3676     TemplateVariant getClass() const                 { return m_cachable.classDef.get(this); }
category() const3677     TemplateVariant category() const                 { return m_cachable.category.get(this); }
categoryRelation() const3678     TemplateVariant categoryRelation() const         { return m_cachable.categoryRelation.get(this); }
getFile() const3679     TemplateVariant getFile() const                  { return m_cachable.fileDef.get(this); }
getNamespace() const3680     TemplateVariant getNamespace() const             { return m_cachable.namespaceDef.get(this); }
definition() const3681     TemplateVariant definition() const               { return m_cachable.definition.get(this); }
parameters() const3682     TemplateVariant parameters() const               { return m_cachable.parameters.get(this); }
hasParameters() const3683     TemplateVariant hasParameters() const            { return !getDefArgList().empty(); }
hasConstQualifier() const3684     TemplateVariant hasConstQualifier() const        { return getDefArgList().constSpecifier(); }
hasVolatileQualifier() const3685     TemplateVariant hasVolatileQualifier() const     { return getDefArgList().volatileSpecifier(); }
hasRefQualifierLValue() const3686     TemplateVariant hasRefQualifierLValue() const    { return getDefArgList().refQualifier()==RefQualifierLValue; }
hasRefQualifierRValue() const3687     TemplateVariant hasRefQualifierRValue() const    { return getDefArgList().refQualifier()==RefQualifierRValue; }
trailingReturnType() const3688     TemplateVariant trailingReturnType() const       { return m_cachable.trailingReturnType.get(this); }
templateDecls() const3689     TemplateVariant templateDecls() const            { return m_cachable.templateDecls.get(this); }
labels() const3690     TemplateVariant labels() const                   { return m_cachable.labels.get(this); }
paramDocs() const3691     TemplateVariant paramDocs() const                { return m_cachable.paramDocs.get(this); }
implements() const3692     TemplateVariant implements() const               { return m_cachable.implements.get(this); }
reimplements() const3693     TemplateVariant reimplements() const             { return m_cachable.reimplements.get(this); }
implementedBy() const3694     TemplateVariant implementedBy() const            { return m_cachable.implementedBy.get(this); }
reimplementedBy() const3695     TemplateVariant reimplementedBy() const          { return m_cachable.reimplementedBy.get(this); }
examples() const3696     TemplateVariant examples() const                 { return m_cachable.examples.get(this); }
typeConstraints() const3697     TemplateVariant typeConstraints() const          { return m_cachable.typeConstraints.get(this); }
sourceRefs() const3698     TemplateVariant sourceRefs() const               { return m_cachable.sourceRefs.get(this); }
sourceRefBys() const3699     TemplateVariant sourceRefBys() const             { return m_cachable.sourceRefBys.get(this); }
sourceCode() const3700     TemplateVariant sourceCode() const               { return m_cachable.sourceCode.get(this); }
getCallGraph() const3701     DotCallGraphPtr getCallGraph() const             { return m_cachable.callGraph.get(this); }
getCallerGraph() const3702     DotCallGraphPtr getCallerGraph() const           { return m_cachable.callerGraph.get(this); }
hasSources() const3703     TemplateVariant hasSources() const               { return TemplateVariant(m_memberDef->hasSources()); }
hasReferencedByRelation() const3704     TemplateVariant hasReferencedByRelation() const  { return TemplateVariant(m_memberDef->hasReferencedByRelation()); }
hasReferencesRelation() const3705     TemplateVariant hasReferencesRelation() const    { return TemplateVariant(m_memberDef->hasReferencesRelation()); }
3706 
getDefArgList() const3707     const ArgumentList &getDefArgList() const
3708     {
3709       return (m_memberDef->isDocsForDefinition()) ?
3710               m_memberDef->argumentList() : m_memberDef->declArgumentList();
3711     }
3712 
functionQualifier() const3713     TemplateVariant functionQualifier() const
3714     {
3715       if (!m_memberDef->isObjCMethod() &&
3716           (m_memberDef->isFunction()  || m_memberDef->isSlot() ||
3717            m_memberDef->isPrototype() || m_memberDef->isSignal()
3718           )
3719          )
3720       {
3721         return "()";
3722       }
3723       else
3724       {
3725         return "";
3726       }
3727     }
hasCallGraph() const3728     TemplateVariant hasCallGraph() const
3729     {
3730       static bool haveDot = Config_getBool(HAVE_DOT);
3731       if (m_memberDef->hasCallGraph() && haveDot &&
3732           (m_memberDef->isFunction() || m_memberDef->isSlot() || m_memberDef->isSignal()))
3733       {
3734         DotCallGraphPtr cg = getCallGraph();
3735         return !cg->isTooBig() && !cg->isTrivial();
3736       }
3737       return TemplateVariant(FALSE);
3738     }
callGraph() const3739     TemplateVariant callGraph() const
3740     {
3741       if (hasCallGraph().toBool())
3742       {
3743         DotCallGraphPtr cg = getCallGraph();
3744         TextStream t;
3745         switch (g_globals.outputFormat)
3746         {
3747           case ContextOutputFormat_Html:
3748             {
3749               cg->writeGraph(t,GOF_BITMAP,EOF_Html,
3750                   g_globals.outputDir,
3751                   g_globals.outputDir+Portable::pathSeparator()+addHtmlExtensionIfMissing(m_memberDef->getOutputFileBase()),
3752                   relPathAsString(),TRUE,g_globals.dynSectionId
3753                   );
3754             }
3755             break;
3756           case ContextOutputFormat_Latex:
3757             {
3758               cg->writeGraph(t,GOF_EPS,EOF_LaTeX,
3759                   g_globals.outputDir,
3760                   g_globals.outputDir+Portable::pathSeparator()+m_memberDef->getOutputFileBase()+".tex",
3761                   relPathAsString(),TRUE,g_globals.dynSectionId
3762                   );
3763             }
3764             break;
3765             // TODO: support other generators
3766           default:
3767             err("context.cpp: output format not yet supported\n");
3768             break;
3769         }
3770         g_globals.dynSectionId++;
3771         return TemplateVariant(t.str().c_str(),TRUE);
3772       }
3773       else
3774       {
3775         return TemplateVariant("");
3776       }
3777     }
referencedByRelation() const3778     TemplateVariant referencedByRelation() const
3779     {
3780       if (hasReferencedByRelation().toBool())
3781       {
3782         err("context.cpp: referencedByRelation not yet implemented\n");
3783       }
3784       return TemplateVariant("");
3785     }
hasCallerGraph() const3786     TemplateVariant hasCallerGraph() const
3787     {
3788       static bool haveDot = Config_getBool(HAVE_DOT);
3789       if (m_memberDef->hasCallerGraph() && haveDot &&
3790           (m_memberDef->isFunction() || m_memberDef->isSlot() || m_memberDef->isSignal()))
3791       {
3792         DotCallGraphPtr cg = getCallerGraph();
3793         return !cg->isTooBig() && !cg->isTrivial();
3794       }
3795       return TemplateVariant(FALSE);
3796     }
callerGraph() const3797     TemplateVariant callerGraph() const
3798     {
3799       if (hasCallerGraph().toBool())
3800       {
3801         DotCallGraphPtr cg = getCallerGraph();
3802         TextStream t;
3803         switch (g_globals.outputFormat)
3804         {
3805           case ContextOutputFormat_Html:
3806             {
3807               cg->writeGraph(t,GOF_BITMAP,EOF_Html,
3808                   g_globals.outputDir,
3809                   g_globals.outputDir+Portable::pathSeparator()+addHtmlExtensionIfMissing(m_memberDef->getOutputFileBase()),
3810                   relPathAsString(),TRUE,g_globals.dynSectionId
3811                   );
3812             }
3813             break;
3814           case ContextOutputFormat_Latex:
3815             {
3816               cg->writeGraph(t,GOF_EPS,EOF_LaTeX,
3817                   g_globals.outputDir,
3818                   g_globals.outputDir+Portable::pathSeparator()+m_memberDef->getOutputFileBase()+".tex",
3819                   relPathAsString(),TRUE,g_globals.dynSectionId
3820                   );
3821             }
3822             break;
3823             // TODO: support other generators
3824           default:
3825             err("context.cpp: output format not yet supported\n");
3826             break;
3827         }
3828         g_globals.dynSectionId++;
3829         return TemplateVariant(t.str().c_str(),TRUE);
3830       }
3831       else
3832       {
3833         return TemplateVariant("");
3834       }
3835     }
referencesRelation() const3836     TemplateVariant referencesRelation() const
3837     {
3838       if (hasReferencesRelation().toBool())
3839       {
3840          err("context.cpp: referencesRelation not yet implemented\n");
3841       }
3842       return TemplateVariant("");
3843     }
handleDetailsVisibleFor(const TemplateVariantList & args) const3844     TemplateVariant handleDetailsVisibleFor(const TemplateVariantList &args) const
3845     {
3846       if (args.size()==1)
3847       {
3848         QCString containerStr = args[0].toString();
3849         MemberListContainer                 container = MemberListContainer::Class;
3850         if      (containerStr=="module")    container = MemberListContainer::Group;
3851         else if (containerStr=="file")      container = MemberListContainer::File;
3852         else if (containerStr=="namespace") container = MemberListContainer::Namespace;
3853         return m_memberDef->isDetailedSectionVisible(container);
3854       }
3855       else
3856       {
3857         err(".detailsVisibleFor should take one string argument, got %zu\n",args.size());
3858       }
3859       return TemplateVariant();
3860     }
detailsVisibleFor() const3861     TemplateVariant detailsVisibleFor() const
3862     {
3863       return TemplateVariant(std::bind(&Private::handleDetailsVisibleFor,this,std::placeholders::_1));
3864     }
handleNameWithContextFor(const TemplateVariantList & args) const3865     TemplateVariant handleNameWithContextFor(const TemplateVariantList &args) const
3866     {
3867       if (args.size()==1)
3868       {
3869         SrcLangExt lang = m_memberDef->getLanguage();
3870         QCString n = m_memberDef->name();
3871         QCString ctx = args[0].toString();
3872         QCString sep = getLanguageSpecificSeparator(lang,TRUE);
3873         if (m_memberDef->getEnumScope() && m_memberDef->livesInsideEnum())
3874         {
3875           n.prepend(m_memberDef->getEnumScope()->displayName()+sep);
3876         }
3877         if (ctx=="module" && m_memberDef->getClassDef() && !m_memberDef->isRelated())
3878         {
3879           n.prepend(m_memberDef->getClassDef()->displayName()+sep);
3880         }
3881         else if ((ctx=="module" || ctx=="file") && m_memberDef->getNamespaceDef())
3882         {
3883           n.prepend(m_memberDef->getNamespaceDef()->displayName()+sep);
3884         }
3885         return n;
3886       }
3887       else
3888       {
3889         err(".nameWithContextFor should take one string argument, got %zu\n",args.size());
3890       }
3891       return TemplateVariant();
3892     }
nameWithContextFor() const3893     TemplateVariant nameWithContextFor() const
3894     {
3895       return TemplateVariant(std::bind(&Private::handleNameWithContextFor,this,std::placeholders::_1));
3896     }
3897 
3898   private:
3899 
createTemplateArgs() const3900     TemplateVariant createTemplateArgs() const
3901     {
3902       return !m_memberDef->templateArguments().empty() ?
3903          TemplateVariant(ArgumentListContext::alloc(m_memberDef->templateArguments(),m_memberDef,relPathAsString())) :
3904          TemplateVariant(false);
3905     }
createTemplateAlias() const3906     TemplateVariant createTemplateAlias() const
3907     {
3908       return m_memberDef->isTypeAlias() ?
3909          TemplateVariant(createLinkedText(m_memberDef,relPathAsString(),
3910                                 QCString(" = ")+m_memberDef->typeString())) :
3911          TemplateVariant("");
3912     }
createPropertyAttrs() const3913     TemplateVariant createPropertyAttrs() const
3914     {
3915       TemplateVariantList list;
3916       list.reserve(6);
3917       if (m_memberDef->isProperty())
3918       {
3919         if (m_memberDef->isGettable())           list.push_back("get");
3920         if (m_memberDef->isPrivateGettable())    list.push_back("private get");
3921         if (m_memberDef->isProtectedGettable())  list.push_back("protected get");
3922         if (m_memberDef->isSettable())           list.push_back("set");
3923         if (m_memberDef->isPrivateSettable())    list.push_back("private set");
3924         if (m_memberDef->isProtectedSettable())  list.push_back("protected set");
3925       }
3926       return TemplateImmutableList::alloc(list);
3927     }
createEventAttrs() const3928     TemplateVariant createEventAttrs() const
3929     {
3930       TemplateVariantList list;
3931       list.reserve(3);
3932       if (m_memberDef->isEvent())
3933       {
3934         if (m_memberDef->isAddable())   list.push_back("add");
3935         if (m_memberDef->isRemovable()) list.push_back("remove");
3936         if (m_memberDef->isRaisable())  list.push_back("raise");
3937       }
3938       return TemplateImmutableList::alloc(list);
3939     }
createParameters() const3940     TemplateVariant createParameters() const
3941     {
3942       const ArgumentList &defArgList = getDefArgList();
3943       return !m_memberDef->isProperty() ?
3944           ArgumentListContext::alloc(defArgList,m_memberDef,relPathAsString()) :
3945           ArgumentListContext::alloc();
3946     }
createEnumValues() const3947     TemplateVariant createEnumValues() const
3948     {
3949       return m_memberDef->isEnumerate() ?
3950           TemplateVariant(MemberListContext::alloc(m_memberDef->enumFieldList())) :
3951           TemplateVariant(false);
3952     }
createFileDef() const3953     TemplateVariant createFileDef() const
3954     {
3955       return m_memberDef->getFileDef() ?
3956           TemplateVariant(FileContext::alloc(m_memberDef->getFileDef())) :
3957           TemplateVariant(false);
3958     }
createNamespaceDef() const3959     TemplateVariant createNamespaceDef() const
3960     {
3961       return m_memberDef->getNamespaceDef() ?
3962           TemplateVariant(NamespaceContext::alloc(m_memberDef->getNamespaceDef())) :
3963           TemplateVariant(false);
3964     }
createClassDef() const3965     TemplateVariant createClassDef() const
3966     {
3967       return m_memberDef->getClassDef() ?
3968           TemplateVariant(ClassContext::alloc(m_memberDef->getClassDef())) :
3969           TemplateVariant(false);
3970     }
createCategory() const3971     TemplateVariant createCategory() const
3972     {
3973       return m_memberDef->category() ?
3974           TemplateVariant(ClassContext::alloc(m_memberDef->category())) :
3975           TemplateVariant(false);
3976     }
createCategoryRelation() const3977     TemplateVariant createCategoryRelation() const
3978     {
3979       return m_memberDef->categoryRelation() ?
3980           TemplateVariant(MemberContext::alloc(m_memberDef->categoryRelation())) :
3981           TemplateVariant(false);
3982     }
createDefinition() const3983     TemplateVariant createDefinition() const
3984     {
3985       return createLinkedText(m_memberDef,relPathAsString(),
3986                               m_memberDef->displayDefinition());
3987     }
createTrailingReturnType() const3988     TemplateVariant createTrailingReturnType() const
3989     {
3990       const ArgumentList &al = getDefArgList();
3991       return !al.trailingReturnType().isEmpty() ?
3992           TemplateVariant(createLinkedText(m_memberDef,relPathAsString(), al.trailingReturnType())) :
3993           TemplateVariant("");
3994     }
createTemplateDecls() const3995     TemplateVariant createTemplateDecls() const
3996     {
3997       TemplateVariantList list;
3998       const ClassDef *cd=m_memberDef->getClassDef();
3999       if (!m_memberDef->definitionTemplateParameterLists().empty())
4000       {
4001         for (const ArgumentList &tal : m_memberDef->definitionTemplateParameterLists())
4002         {
4003           if (!tal.empty())
4004           {
4005             list.push_back(ArgumentListContext::alloc(tal,m_memberDef,relPathAsString()));
4006           }
4007         }
4008       }
4009       else
4010       {
4011         if (cd && !m_memberDef->isRelated() && !m_memberDef->isTemplateSpecialization())
4012         {
4013           for (const ArgumentList &tal : cd->getTemplateParameterLists())
4014           {
4015             if (!tal.empty())
4016             {
4017               list.push_back(ArgumentListContext::alloc(tal,m_memberDef,relPathAsString()));
4018             }
4019           }
4020         }
4021         if (!m_memberDef->templateArguments().empty()) // function template prefix
4022         {
4023           list.push_back(ArgumentListContext::alloc(
4024                        m_memberDef->templateArguments(),m_memberDef,relPathAsString()));
4025         }
4026       }
4027       return TemplateImmutableList::alloc(list);
4028     }
createAnonymousType() const4029     TemplateVariant createAnonymousType() const
4030     {
4031       const ClassDef *cd = m_memberDef->getClassDefOfAnonymousType();
4032       return cd ? TemplateVariant(ClassContext::alloc(cd)) : TemplateVariant(false);
4033     }
createParamDocs() const4034     TemplateVariant createParamDocs() const
4035     {
4036       if (m_memberDef->argumentList().hasDocumentation())
4037       {
4038         QCString paramDocs;
4039         for (const Argument &a : m_memberDef->argumentList())
4040         {
4041           if (a.hasDocumentation())
4042           {
4043             QCString docs = a.docs;
4044             QCString direction = extractDirection(docs);
4045             paramDocs+="@param"+direction+" "+a.name+" "+docs;
4046           }
4047         }
4048         return TemplateVariant(parseDoc(m_memberDef,
4049                                         m_memberDef->docFile(),m_memberDef->docLine(),
4050                                         relPathAsString(),paramDocs,FALSE));
4051       }
4052       return TemplateVariant("");
4053     }
createImplements() const4054     TemplateVariant createImplements() const
4055     {
4056       const MemberDef *md = m_memberDef->reimplements();
4057       TemplateVariantList list;
4058       if (md)
4059       {
4060         const ClassDef *cd = md->getClassDef();
4061         // filter on pure virtual/interface methods
4062         if (cd && (md->virtualness()==Pure || cd->compoundType()==ClassDef::Interface))
4063         {
4064           list.push_back(MemberContext::alloc(md));
4065         }
4066       }
4067       return TemplateImmutableList::alloc(list);
4068     }
createReimplements() const4069     TemplateVariant createReimplements() const
4070     {
4071       const MemberDef *md = m_memberDef->reimplements();
4072       TemplateVariantList list;
4073       if (md)
4074       {
4075         const ClassDef *cd = md->getClassDef();
4076         // filter on non-pure virtual & non interface methods
4077         if (cd && md->virtualness()!=Pure && cd->compoundType()!=ClassDef::Interface)
4078         {
4079           list.push_back(MemberContext::alloc(md));
4080         }
4081       }
4082       return TemplateImmutableList::alloc(list);
4083     }
createImplementedBy() const4084     TemplateVariant createImplementedBy() const
4085     {
4086       TemplateVariantList list;
4087       list.reserve(m_memberDef->reimplementedBy().size());
4088       for (const auto &md : m_memberDef->reimplementedBy())
4089       {
4090         const ClassDef *cd = md->getClassDef();
4091         // filter on pure virtual/interface methods
4092         if (cd && md->virtualness()==Pure && cd->compoundType()==ClassDef::Interface)
4093         {
4094           list.push_back(MemberContext::alloc(md));
4095         }
4096       }
4097       return TemplateImmutableList::alloc(list);
4098     }
createReimplementedBy() const4099     TemplateVariant createReimplementedBy() const
4100     {
4101       TemplateVariantList list;
4102       list.reserve(m_memberDef->reimplementedBy().size());
4103       for (const auto &md : m_memberDef->reimplementedBy())
4104       {
4105         const ClassDef *cd = md->getClassDef();
4106         // filter on non-pure virtual & non interface methods
4107         if (cd && md->virtualness()!=Pure && cd->compoundType()!=ClassDef::Interface)
4108         {
4109           list.push_back(MemberContext::alloc(md));
4110         }
4111       }
4112       return TemplateImmutableList::alloc(list);
4113     }
createExamples() const4114     TemplateVariant createExamples() const
4115     {
4116       TemplateVariantList list;
4117       if (m_memberDef->hasExamples())
4118       {
4119         list.reserve(m_memberDef->getExamples().size());
4120         for (const auto &ex : m_memberDef->getExamples())
4121         {
4122           TemplateStructIntfPtr s = TemplateImmutableStruct::alloc(
4123           {
4124             { "text",             TemplateVariant(ex.name)   },
4125             { "isLinkable",       TemplateVariant(TRUE)      },
4126             { "anchor",           TemplateVariant(ex.anchor) },
4127             { "fileName",         TemplateVariant(ex.file)   },
4128             { "isReference",      TemplateVariant(FALSE)     },
4129             { "externalReference",TemplateVariant("")        }
4130           });
4131           list.push_back(s);
4132         }
4133       }
4134       return TemplateImmutableList::alloc(list);
4135     }
createSourceRefs() const4136     TemplateVariant createSourceRefs() const
4137     {
4138       return MemberListContext::alloc(m_memberDef->getReferencesMembers());
4139     }
createSourceRefBys() const4140     TemplateVariant createSourceRefBys() const
4141     {
4142       return MemberListContext::alloc(m_memberDef->getReferencedByMembers());
4143     }
createCallGraph() const4144     DotCallGraphPtr createCallGraph() const
4145     {
4146       return std::make_shared<DotCallGraph>(m_memberDef,FALSE);
4147     }
createCallerGraph() const4148     DotCallGraphPtr createCallerGraph() const
4149     {
4150       return std::make_shared<DotCallGraph>(m_memberDef,TRUE);
4151     }
createAnonymousMember() const4152     TemplateVariant createAnonymousMember() const
4153     {
4154       return m_memberDef->fromAnonymousMember() ?
4155           TemplateVariant(MemberContext::alloc(m_memberDef)) :
4156           TemplateVariant(false);
4157     }
createLabels() const4158     TemplateVariant createLabels() const
4159     {
4160       StringVector sl = m_memberDef->getLabels(m_memberDef->getOuterScope());
4161       TemplateVariantList list;
4162       list.reserve(sl.size());
4163       for (const auto &s : sl)
4164       {
4165         list.push_back(s.c_str());
4166       }
4167       return TemplateImmutableList::alloc(list);
4168     }
createTypeConstraints() const4169     TemplateVariant createTypeConstraints() const
4170     {
4171       return !m_memberDef->typeConstraints().empty() ?
4172           TemplateVariant(ArgumentListContext::alloc(m_memberDef->typeConstraints(),m_memberDef,relPathAsString())) :
4173           TemplateVariant(ArgumentListContext::alloc());
4174     }
createInitializerAsCode() const4175     TemplateVariant createInitializerAsCode() const
4176     {
4177       QCString scopeName;
4178       if (m_memberDef->getClassDef())
4179       {
4180         scopeName = m_memberDef->getClassDef()->name();
4181       }
4182       else if (m_memberDef->getNamespaceDef())
4183       {
4184         scopeName = m_memberDef->getNamespaceDef()->name();
4185       }
4186       return TemplateVariant(parseCode(m_memberDef,
4187                                        scopeName,relPathAsString(),
4188                                        m_memberDef->initializer()));
4189     }
createInitializer() const4190     TemplateVariant createInitializer() const
4191     {
4192       return createLinkedText(m_memberDef,relPathAsString(),m_memberDef->initializer());
4193     }
createSourceCode() const4194     TemplateVariant createSourceCode() const
4195     {
4196       QCString codeFragment;
4197       const FileDef *fd = m_memberDef->getBodyDef();
4198       int startLine = m_memberDef->getStartBodyLine();
4199       int endLine   = m_memberDef->getEndBodyLine();
4200       if (fd && readCodeFragment(fd->absFilePath(),startLine,endLine,codeFragment))
4201       {
4202         QCString scopeName;
4203         if (m_memberDef->getClassDef())
4204         {
4205           scopeName = m_memberDef->getClassDef()->name();
4206         }
4207         else if (m_memberDef->getNamespaceDef())
4208         {
4209           scopeName = m_memberDef->getNamespaceDef()->name();
4210         }
4211         return parseCode(m_memberDef,
4212                          scopeName,relPathAsString(),
4213                          codeFragment,startLine,endLine,TRUE);
4214       }
4215       return TemplateVariant("");
4216     }
createDeclType() const4217     TemplateVariant createDeclType() const
4218     {
4219       return createLinkedText(m_memberDef,relPathAsString(),m_memberDef->getDeclType());
4220     }
createDeclArgs() const4221     TemplateVariant createDeclArgs() const
4222     {
4223       return createLinkedText(m_memberDef,relPathAsString(),m_memberDef->argsString());
4224     }
createFieldType() const4225     TemplateVariant createFieldType() const
4226     {
4227       return createLinkedText(m_memberDef,relPathAsString(),m_memberDef->fieldType());
4228     }
createException() const4229     TemplateVariant createException() const
4230     {
4231       return createLinkedText(m_memberDef,relPathAsString(),m_memberDef->excpString());
4232     }
createBitfields() const4233     TemplateVariant createBitfields() const
4234     {
4235       return createLinkedText(m_memberDef,relPathAsString(),m_memberDef->bitfieldString());
4236     }
4237 
4238     const MemberDef *m_memberDef;
4239     struct Cachable : public DefinitionContext<MemberContext::Private>::Cachable
4240     {
4241       CachedItem<TemplateVariant,  Private, &Private::createTemplateArgs>       templateArgs;
4242       CachedItem<TemplateVariant,  Private, &Private::createTemplateAlias>      templateAlias;
4243       CachedItem<TemplateVariant,  Private, &Private::createPropertyAttrs>      propertyAttrs;
4244       CachedItem<TemplateVariant,  Private, &Private::createEventAttrs>         eventAttrs;
4245       CachedItem<TemplateVariant,  Private, &Private::createParameters>         parameters;
4246       CachedItem<TemplateVariant,  Private, &Private::createEnumValues>         enumValues;
4247       CachedItem<TemplateVariant,  Private, &Private::createFileDef>            fileDef;
4248       CachedItem<TemplateVariant,  Private, &Private::createNamespaceDef>       namespaceDef;
4249       CachedItem<TemplateVariant,  Private, &Private::createCategory>           category;
4250       CachedItem<TemplateVariant,  Private, &Private::createCategoryRelation>   categoryRelation;
4251       CachedItem<TemplateVariant,  Private, &Private::createDefinition>         definition;
4252       CachedItem<TemplateVariant,  Private, &Private::createTrailingReturnType> trailingReturnType;
4253       CachedItem<TemplateVariant,  Private, &Private::createTemplateDecls>      templateDecls;
4254       CachedItem<TemplateVariant,  Private, &Private::createClassDef>           classDef;
4255       CachedItem<TemplateVariant,  Private, &Private::createAnonymousType>      anonymousType;
4256       CachedItem<TemplateVariant,  Private, &Private::createParamDocs>          paramDocs;
4257       CachedItem<TemplateVariant,  Private, &Private::createImplements>         implements;
4258       CachedItem<TemplateVariant,  Private, &Private::createReimplements>       reimplements;
4259       CachedItem<TemplateVariant,  Private, &Private::createImplementedBy>      implementedBy;
4260       CachedItem<TemplateVariant,  Private, &Private::createReimplementedBy>    reimplementedBy;
4261       CachedItem<TemplateVariant,  Private, &Private::createExamples>           examples;
4262       CachedItem<TemplateVariant,  Private, &Private::createSourceRefs>         sourceRefs;
4263       CachedItem<TemplateVariant,  Private, &Private::createSourceRefBys>       sourceRefBys;
4264       CachedItem<DotCallGraphPtr,  Private, &Private::createCallGraph>          callGraph;
4265       CachedItem<DotCallGraphPtr,  Private, &Private::createCallerGraph>        callerGraph;
4266       CachedItem<TemplateVariant,  Private, &Private::createAnonymousMember>    anonymousMember;
4267       CachedItem<TemplateVariant,  Private, &Private::createLabels>             labels;
4268       CachedItem<TemplateVariant,  Private, &Private::createTypeConstraints>    typeConstraints;
4269       CachedItem<TemplateVariant,  Private, &Private::createInitializer>        initializer;
4270       CachedItem<TemplateVariant,  Private, &Private::createInitializerAsCode>  initializerAsCode;
4271       CachedItem<TemplateVariant,  Private, &Private::createSourceCode>         sourceCode;
4272       CachedItem<TemplateVariant,  Private, &Private::createDeclArgs>           declArgs;
4273       CachedItem<TemplateVariant,  Private, &Private::createDeclType>           declType;
4274       CachedItem<TemplateVariant,  Private, &Private::createFieldType>          fieldType;
4275       CachedItem<TemplateVariant,  Private, &Private::createException>          exception;
4276       CachedItem<TemplateVariant,  Private, &Private::createBitfields>          bitfields;
4277     };
4278     Cachable m_cachable;
4279     static const PropertyMap<MemberContext::Private> s_inst;
4280 };
4281 
4282 //%% struct Member(Symbol): member information
4283 //%% {
4284 const PropertyMap<MemberContext::Private> MemberContext::Private::s_inst {
4285   BASE_PROPERTIES,
4286   {  "isSignal",            &Private::isSignal },
4287   {  "isSlot",              &Private::isSlot },
4288   {  "isVariable",          &Private::isVariable },
4289   {  "isEnumeration",       &Private::isEnumeration },
4290   {  "isEnumValue",         &Private::isEnumValue },
4291   {  "isTypedef",           &Private::isTypedef },
4292   {  "isFunction",          &Private::isFunction },
4293   {  "isFunctionPtr",       &Private::isFunctionPtr },
4294   {  "isDefine",            &Private::isDefine },
4295   {  "isFriend",            &Private::isFriend },
4296   {  "isProperty",          &Private::isProperty },
4297   {  "isEvent",             &Private::isEvent },
4298   {  "isRelated",           &Private::isRelated },
4299   {  "isForeign",           &Private::isForeign },
4300   {  "isStatic",            &Private::isStatic },
4301   {  "isInline",            &Private::isInline },
4302   {  "isExplicit",          &Private::isExplicit },
4303   {  "isMutable",           &Private::isMutable },
4304   {  "isGettable",          &Private::isGettable },
4305   {  "isPrivateGettable",   &Private::isPrivateGettable },
4306   {  "isProtectedGettable", &Private::isProtectedGettable },
4307   {  "isSettable",          &Private::isSettable },
4308   {  "isPrivateSettable",   &Private::isPrivateSettable },
4309   {  "isProtectedSettable", &Private::isProtectedSettable },
4310   {  "isReadable",          &Private::isReadable },
4311   {  "isWritable",          &Private::isWritable },
4312   {  "isAddable",           &Private::isAddable },
4313   {  "isRemovable",         &Private::isRemovable },
4314   {  "isRaisable",          &Private::isRaisable },
4315   {  "isFinal",             &Private::isFinal },
4316   {  "isAbstract",          &Private::isAbstract },
4317   {  "isOverride",          &Private::isOverride },
4318   {  "isInitonly",          &Private::isInitonly },
4319   {  "isOptional",          &Private::isOptional },
4320   {  "isRequired",          &Private::isRequired },
4321   {  "isNonAtomic",         &Private::isNonAtomic },
4322   {  "isCopy",              &Private::isCopy },
4323   {  "isAssign",            &Private::isAssign },
4324   {  "isRetain",            &Private::isRetain },
4325   {  "isWeak",              &Private::isWeak },
4326   {  "isStrong",            &Private::isStrong },
4327   {  "isEnumStruct",        &Private::isEnumStruct },
4328   {  "isUnretained",        &Private::isUnretained },
4329   {  "isNew",               &Private::isNew },
4330   {  "isSealed",            &Private::isSealed },
4331   {  "isImplementation",    &Private::isImplementation },
4332   {  "isExternal",          &Private::isExternal },
4333   {  "isTypeAlias",         &Private::isTypeAlias },
4334   {  "isDefault",           &Private::isDefault },
4335   {  "isDelete",            &Private::isDelete },
4336   {  "isNoExcept",          &Private::isNoExcept },
4337   {  "isAttribute",         &Private::isAttribute },
4338   {  "isUNOProperty",       &Private::isUNOProperty },
4339   {  "isReadonly",          &Private::isReadonly },
4340   {  "isBound",             &Private::isBound },
4341   {  "isConstrained",       &Private::isConstrained },
4342   {  "isTransient",         &Private::isTransient },
4343   {  "isMaybeVoid",         &Private::isMaybeVoid },
4344   {  "isMaybeDefault",      &Private::isMaybeDefault },
4345   {  "isMaybeAmbiguous",    &Private::isMaybeAmbiguous },
4346   {  "isPublished",         &Private::isPublished },
4347   {  "isTemplateSpecialization",&Private::isTemplateSpecialization },
4348   {  "isObjCMethod",        &Private::isObjCMethod },
4349   {  "isObjCProperty",      &Private::isObjCProperty },
4350   {  "isCSharpProperty",    &Private::isCSharpProperty },
4351   {  "isAnonymous",         &Private::isAnonymous },
4352   {  "hasParameters",       &Private::hasParameters },
4353   {  "declType",            &Private::declType },
4354   {  "declArgs",            &Private::declArgs },
4355   {  "anonymousType",       &Private::anonymousType },
4356   {  "anonymousMember",     &Private::anonymousMember },
4357   {  "hasDetails",          &Private::hasDetails },
4358   {  "exception",           &Private::exception },
4359   {  "bitfields",           &Private::bitfields },
4360   {  "initializer",         &Private::initializer },
4361   {  "initializerAsCode",   &Private::initializerAsCode },
4362   {  "hasOneLineInitializer",   &Private::hasOneLineInitializer },
4363   {  "hasMultiLineInitializer", &Private::hasMultiLineInitializer },
4364   {  "templateArgs",        &Private::templateArgs },
4365   {  "templateAlias",       &Private::templateAlias },
4366   {  "propertyAttrs",       &Private::propertyAttrs },
4367   {  "eventAttrs",          &Private::eventAttrs },
4368   {  "category",            &Private::category },
4369   {  "categoryRelation",    &Private::categoryRelation },
4370   {  "class",               &Private::getClass },
4371   {  "file",                &Private::getFile },
4372   {  "namespace",           &Private::getNamespace },
4373   {  "definition",          &Private::definition },
4374   {  "parameters",          &Private::parameters },
4375   {  "hasConstQualifier",   &Private::hasConstQualifier },
4376   {  "hasVolatileQualifier",&Private::hasVolatileQualifier },
4377   {  "hasRefQualifierLValue", &Private::hasRefQualifierLValue },
4378   {  "hasRefQualifierRValue", &Private::hasRefQualifierRValue },
4379   {  "trailingReturnType",  &Private::trailingReturnType },
4380   {  "extraTypeChars",      &Private::extraTypeChars },
4381   {  "templateDecls",       &Private::templateDecls },
4382   {  "labels",              &Private::labels },
4383   {  "enumBaseType",        &Private::enumBaseType },
4384   {  "enumValues",          &Private::enumValues },
4385   {  "paramDocs",           &Private::paramDocs },
4386   {  "reimplements",        &Private::reimplements },
4387   {  "implements",          &Private::implements },
4388   {  "reimplementedBy",     &Private::reimplementedBy },
4389   {  "implementedBy",       &Private::implementedBy },
4390   {  "examples",            &Private::examples },
4391   {  "typeConstraints",     &Private::typeConstraints },
4392   {  "functionQualifier",   &Private::functionQualifier },
4393   {  "sourceRefs",          &Private::sourceRefs },
4394   {  "sourceRefBys",        &Private::sourceRefBys },
4395   {  "hasSources",          &Private::hasSources },
4396   {  "sourceCode",          &Private::sourceCode },
4397   {  "hasCallGraph",        &Private::hasCallGraph },
4398   {  "callGraph",           &Private::callGraph },
4399   {  "hasCallerGraph",      &Private::hasCallerGraph },
4400   {  "callerGraph",         &Private::callerGraph },
4401   {  "hasReferencedByRelation", &Private::hasReferencedByRelation },
4402   {  "referencedByRelation",    &Private::referencedByRelation },
4403   {  "hasReferencesRelation",   &Private::hasReferencesRelation },
4404   {  "referencesRelation",      &Private::referencesRelation },
4405   {  "fieldType",           &Private::fieldType },
4406   {  "type",                &Private::type },
4407   {  "detailsVisibleFor",   &Private::detailsVisibleFor },
4408   {  "nameWithContextFor",  &Private::nameWithContextFor }
4409 };
4410 //%% }
4411 
4412 //PropertyMapper<MemberContext::Private> MemberContext::Private::s_inst;
4413 
MemberContext(const MemberDef * md)4414 MemberContext::MemberContext(const MemberDef *md) : p(std::make_unique<Private>(md))
4415 {
4416 }
4417 
~MemberContext()4418 MemberContext::~MemberContext()
4419 {
4420 }
4421 
get(const QCString & n) const4422 TemplateVariant MemberContext::get(const QCString &n) const
4423 {
4424   return p->get(n);
4425 }
4426 
fields() const4427 StringVector MemberContext::fields() const
4428 {
4429   return p->fields();
4430 }
4431 
4432 //------------------------------------------------------------------------
4433 
4434 class ConceptContext::Private : public DefinitionContext<ConceptContext::Private>
4435 {
4436   public:
Private(const ConceptDef * cd)4437     Private(const ConceptDef *cd) : DefinitionContext<ConceptContext::Private>(cd),
4438        m_conceptDef(cd)
4439     {
4440     }
~Private()4441     virtual ~Private() {}
4442 
4443     // TemplateStructIntf methods
get(const QCString & n) const4444     TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
fields() const4445     StringVector fields() const                  { return s_inst.fields(); }
4446 
4447     // Property getters
title() const4448     TemplateVariant title() const                { return TemplateVariant(m_conceptDef->title()); }
highlight() const4449     TemplateVariant highlight() const            { return TemplateVariant("concepts"); }
subHighlight() const4450     TemplateVariant subHighlight() const         { return TemplateVariant(""); }
hasDetails() const4451     TemplateVariant hasDetails() const           { return m_conceptDef->hasDetailedDescription(); }
includeInfo() const4452     TemplateVariant includeInfo() const          { return m_cachable.includeInfo.get(this); }
templateDecls() const4453     TemplateVariant templateDecls() const        { return m_cachable.templateDecls.get(this); }
initializer() const4454     TemplateVariant initializer() const          { return m_cachable.initializer.get(this); }
initializerAsCode() const4455     TemplateVariant initializerAsCode() const    { return m_cachable.initializerAsCode.get(this); }
4456 
4457   private:
createIncludeInfo() const4458     TemplateVariant createIncludeInfo() const
4459     {
4460       return m_conceptDef->includeInfo() ?
4461           TemplateVariant(IncludeInfoContext::alloc(m_conceptDef->includeInfo(),m_conceptDef->getLanguage())) :
4462           TemplateVariant(false);
4463     }
createTemplateDecls() const4464     TemplateVariant createTemplateDecls() const
4465     {
4466       TemplateVariantList list;
4467       if (!m_conceptDef->getTemplateParameterList().empty())
4468       {
4469         list.push_back(ArgumentListContext::alloc(m_conceptDef->getTemplateParameterList(),m_conceptDef,relPathAsString()));
4470       }
4471       return TemplateImmutableList::alloc(list);
4472     }
createInitializer() const4473     TemplateVariant createInitializer() const
4474     {
4475       return createLinkedText(m_conceptDef,relPathAsString(),m_conceptDef->initializer());
4476     }
createInitializerAsCode() const4477     TemplateVariant createInitializerAsCode() const
4478     {
4479       QCString scopeName;
4480       if (m_conceptDef->getOuterScope()!=Doxygen::globalScope)
4481       {
4482         scopeName = m_conceptDef->getOuterScope()->name();
4483       }
4484       return parseCode(m_conceptDef,
4485                        scopeName,relPathAsString(),
4486                        m_conceptDef->initializer());
4487     }
4488 
4489     const ConceptDef *m_conceptDef;
4490     struct Cachable : public DefinitionContext<ConceptContext::Private>::Cachable
4491     {
4492       CachedItem<TemplateVariant,  Private, &Private::createIncludeInfo>       includeInfo;
4493       CachedItem<TemplateVariant,  Private, &Private::createTemplateDecls>     templateDecls;
4494       CachedItem<TemplateVariant,  Private, &Private::createInitializer>       initializer;
4495       CachedItem<TemplateVariant,  Private, &Private::createInitializerAsCode> initializerAsCode;
4496     };
4497     Cachable m_cachable;
4498     static const PropertyMap<ConceptContext::Private> s_inst;
4499 };
4500 
4501 //%% struct Concept(Symbol): class information
4502 //%% {
4503 const PropertyMap<ConceptContext::Private> ConceptContext::Private::s_inst {
4504   BASE_PROPERTIES,
4505   {  "title",                     &Private::title },
4506   {  "highlight",                 &Private::highlight },
4507   {  "subhighlight",              &Private::subHighlight },
4508   {  "hasDetails",                &Private::hasDetails },
4509   {  "includeInfo",               &Private::includeInfo },
4510   {  "templateDecls",             &Private::templateDecls },
4511   {  "initializer",               &Private::initializer },
4512   {  "initializerAsCode",         &Private::initializerAsCode }
4513 };
4514 //%% }
4515 
ConceptContext(const ConceptDef * cd)4516 ConceptContext::ConceptContext(const ConceptDef *cd) : p(std::make_unique<Private>(cd))
4517 {
4518 }
4519 
~ConceptContext()4520 ConceptContext::~ConceptContext()
4521 {
4522 }
4523 
get(const QCString & n) const4524 TemplateVariant ConceptContext::get(const QCString &n) const
4525 {
4526   return p->get(n);
4527 }
4528 
fields() const4529 StringVector ConceptContext::fields() const
4530 {
4531   return p->fields();
4532 }
4533 
4534 //------------------------------------------------------------------------
4535 
4536 class ModuleContext::Private : public DefinitionContext<ModuleContext::Private>
4537 {
4538   public:
Private(const GroupDef * gd)4539     Private(const GroupDef *gd) : DefinitionContext<ModuleContext::Private>(gd) , m_groupDef(gd)
4540     {
4541     }
4542 
4543     // TemplateStructIntf methods
get(const QCString & n) const4544     TemplateVariant get(const QCString &n) const     { return s_inst.get(this,n); }
fields() const4545     StringVector fields() const                      { return s_inst.fields(); }
4546 
4547   private:
4548     // Property getters
title() const4549     TemplateVariant title() const                    { return TemplateVariant(m_groupDef->groupTitle()); }
highlight() const4550     TemplateVariant highlight() const                { return TemplateVariant("modules"); }
subHighlight() const4551     TemplateVariant subHighlight() const             { return TemplateVariant(""); }
compoundType() const4552     TemplateVariant compoundType() const             { return TemplateVariant("module"); }
hasDetails() const4553     TemplateVariant hasDetails() const               { return m_groupDef->hasDetailedDescription(); }
modules() const4554     TemplateVariant modules() const                  { return m_cachable.modules.get(this); }
examples() const4555     TemplateVariant examples() const                 { return m_cachable.examples.get(this); }
pages() const4556     TemplateVariant pages() const                    { return m_cachable.pages.get(this); }
dirs() const4557     TemplateVariant dirs() const                     { return m_cachable.dirs.get(this); }
files() const4558     TemplateVariant files() const                    { return m_cachable.files.get(this); }
classes() const4559     TemplateVariant classes() const                  { return m_cachable.classes.get(this); }
namespaces() const4560     TemplateVariant namespaces() const               { return m_cachable.namespaces.get(this); }
constantgroups() const4561     TemplateVariant constantgroups() const           { return m_cachable.constantgroups.get(this); }
macros() const4562     TemplateVariant macros() const                   { return m_cachable.macros.get(this); }
typedefs() const4563     TemplateVariant typedefs() const                 { return m_cachable.typedefs.get(this); }
enums() const4564     TemplateVariant enums() const                    { return m_cachable.enums.get(this); }
enumValues() const4565     TemplateVariant enumValues() const               { return m_cachable.enums.get(this); }
functions() const4566     TemplateVariant functions() const                { return m_cachable.functions.get(this); }
variables() const4567     TemplateVariant variables() const                { return m_cachable.variables.get(this); }
signals() const4568     TemplateVariant signals() const                  { return m_cachable.signals.get(this); }
publicSlots() const4569     TemplateVariant publicSlots() const              { return m_cachable.publicSlots.get(this); }
protectedSlots() const4570     TemplateVariant protectedSlots() const           { return m_cachable.protectedSlots.get(this); }
privateSlots() const4571     TemplateVariant privateSlots() const             { return m_cachable.privateSlots.get(this); }
events() const4572     TemplateVariant events() const                   { return m_cachable.events.get(this); }
properties() const4573     TemplateVariant properties() const               { return m_cachable.properties.get(this); }
friends() const4574     TemplateVariant friends() const                  { return m_cachable.friends.get(this); }
memberGroups() const4575     TemplateVariant memberGroups() const             { return m_cachable.memberGroups.get(this); }
detailedMacros() const4576     TemplateVariant detailedMacros() const           { return m_cachable.detailedMacros.get(this); }
detailedTypedefs() const4577     TemplateVariant detailedTypedefs() const         { return m_cachable.detailedTypedefs.get(this); }
detailedEnums() const4578     TemplateVariant detailedEnums() const            { return m_cachable.detailedEnums.get(this); }
detailedEnumValues() const4579     TemplateVariant detailedEnumValues() const       { return m_cachable.detailedEnumValues.get(this); }
detailedFunctions() const4580     TemplateVariant detailedFunctions() const        { return m_cachable.detailedFunctions.get(this); }
detailedVariables() const4581     TemplateVariant detailedVariables() const        { return m_cachable.detailedVariables.get(this); }
detailedSignals() const4582     TemplateVariant detailedSignals() const          { return m_cachable.detailedSignals.get(this); }
detailedPublicSlots() const4583     TemplateVariant detailedPublicSlots() const      { return m_cachable.detailedPublicSlots.get(this); }
detailedProtectedSlots() const4584     TemplateVariant detailedProtectedSlots() const   { return m_cachable.detailedProtectedSlots.get(this); }
detailedPrivateSlots() const4585     TemplateVariant detailedPrivateSlots() const     { return m_cachable.detailedPrivateSlots.get(this); }
detailedEvents() const4586     TemplateVariant detailedEvents() const           { return m_cachable.detailedEvents.get(this); }
detailedProperties() const4587     TemplateVariant detailedProperties() const       { return m_cachable.detailedProperties.get(this); }
detailedFriends() const4588     TemplateVariant detailedFriends() const          { return m_cachable.detailedFriends.get(this); }
inlineClasses() const4589     TemplateVariant inlineClasses() const            { return m_cachable.inlineClasses.get(this); }
getGroupGraph() const4590     DotGroupCollaborationPtr getGroupGraph() const   { return m_cachable.groupGraph.get(this); }
4591 
hasGroupGraph() const4592     TemplateVariant hasGroupGraph() const
4593     {
4594       bool result=FALSE;
4595       static bool haveDot     = Config_getBool(HAVE_DOT);
4596       static bool groupGraphs = Config_getBool(GROUP_GRAPHS);
4597       if (haveDot && groupGraphs)
4598       {
4599         DotGroupCollaborationPtr graph = getGroupGraph();
4600         result = !graph->isTrivial();
4601       }
4602       return result;
4603     }
groupGraph() const4604     TemplateVariant groupGraph() const
4605     {
4606       TextStream t;
4607       static bool haveDot     = Config_getBool(HAVE_DOT);
4608       static bool groupGraphs = Config_getBool(GROUP_GRAPHS);
4609       if (haveDot && groupGraphs)
4610       {
4611         DotGroupCollaborationPtr graph = getGroupGraph();
4612         switch (g_globals.outputFormat)
4613         {
4614           case ContextOutputFormat_Html:
4615             {
4616               graph->writeGraph(t,GOF_BITMAP,
4617                                 EOF_Html,
4618                                 g_globals.outputDir,
4619                                 g_globals.outputDir+Portable::pathSeparator()+addHtmlExtensionIfMissing(m_groupDef->getOutputFileBase()),
4620                                 relPathAsString(),
4621                                 TRUE,
4622                                 g_globals.dynSectionId);
4623             }
4624             break;
4625           case ContextOutputFormat_Latex:
4626             {
4627               graph->writeGraph(t,GOF_EPS,
4628                                 EOF_LaTeX,
4629                                 g_globals.outputDir,
4630                                 g_globals.outputDir+Portable::pathSeparator()+m_groupDef->getOutputFileBase()+".tex",
4631                                 relPathAsString(),
4632                                 TRUE,
4633                                 g_globals.dynSectionId);
4634             }
4635             break;
4636             // TODO: support other generators
4637           default:
4638             err("context.cpp: output format not yet supported\n");
4639             break;
4640         }
4641         g_globals.dynSectionId++;
4642       }
4643       return TemplateVariant(t.str().c_str(),TRUE);
4644     }
4645 
4646   private:
4647 
createModules() const4648     TemplateVariant createModules() const
4649     {
4650       TemplateVariantList list;
4651       list.reserve(m_groupDef->getSubGroups().size());
4652       for (const auto &gd : m_groupDef->getSubGroups())
4653       {
4654         if (gd->isVisible())
4655         {
4656           list.push_back(ModuleContext::alloc(gd));
4657         }
4658       }
4659       return TemplateImmutableList::alloc(list);
4660     }
createDirs() const4661     TemplateVariant createDirs() const
4662     {
4663       TemplateVariantList list;
4664       list.reserve(m_groupDef->getDirs().size());
4665       for(const auto dd : m_groupDef->getDirs())
4666       {
4667         list.push_back(DirContext::alloc(dd));
4668       }
4669       return TemplateImmutableList::alloc(list);
4670     }
createFiles() const4671     TemplateVariant createFiles() const
4672     {
4673       TemplateVariantList list;
4674       list.reserve(m_groupDef->getFiles().size());
4675       for (const auto &fd : m_groupDef->getFiles())
4676       {
4677         list.push_back(FileContext::alloc(fd));
4678       }
4679       return TemplateImmutableList::alloc(list);
4680     }
createClasses() const4681     TemplateVariant createClasses() const
4682     {
4683       TemplateVariantList list;
4684       list.reserve(m_groupDef->getClasses().size());
4685       for (const auto &cd : m_groupDef->getClasses())
4686       {
4687         if (cd->visibleInParentsDeclList())
4688         {
4689           list.push_back(ClassContext::alloc(cd));
4690         }
4691       }
4692       return TemplateImmutableList::alloc(list);
4693     }
createNamespaces() const4694     TemplateVariant createNamespaces() const
4695     {
4696       TemplateVariantList list;
4697       list.reserve(m_groupDef->getNamespaces().size());
4698       for (const auto &nd : m_groupDef->getNamespaces())
4699       {
4700         if (nd->isLinkable() && !nd->isConstantGroup())
4701         {
4702           list.push_back(NamespaceContext::alloc(nd));
4703         }
4704       }
4705       return TemplateImmutableList::alloc(list);
4706     }
createConstantgroups() const4707     TemplateVariant createConstantgroups() const
4708     {
4709       TemplateVariantList list;
4710       list.reserve(m_groupDef->getNamespaces().size());
4711       for (const auto &nd : m_groupDef->getNamespaces())
4712       {
4713         if (nd->isLinkable() && nd->isConstantGroup())
4714         {
4715           list.push_back(NamespaceContext::alloc(nd));
4716         }
4717       }
4718       return TemplateImmutableList::alloc(list);
4719     }
createExamples() const4720     TemplateVariant createExamples() const
4721     {
4722       TemplateVariantList list;
4723       list.reserve(m_groupDef->getExamples().size());
4724       for (const auto &ex : m_groupDef->getExamples())
4725       {
4726         list.push_back(PageContext::alloc(ex,FALSE,TRUE));
4727       }
4728       return TemplateImmutableList::alloc(list);
4729     }
createPages() const4730     TemplateVariant createPages() const
4731     {
4732       TemplateVariantList list;
4733       list.reserve(m_groupDef->getPages().size());
4734       for (const auto &ex : m_groupDef->getPages())
4735       {
4736         list.push_back(PageContext::alloc(ex,FALSE,TRUE));
4737       }
4738       return TemplateImmutableList::alloc(list);
4739     }
createMemberList(MemberListType type,const QCString & title) const4740     TemplateVariant createMemberList(MemberListType type,const QCString &title) const
4741     {
4742       const MemberList *ml = m_groupDef->getMemberList(type);
4743       return ml ? TemplateVariant(MemberListInfoContext::alloc(m_groupDef,relPathAsString(),ml,title,""))
4744                 : TemplateVariant(false);
4745     }
createMacros() const4746     TemplateVariant createMacros() const
4747     {
4748       return createMemberList(MemberListType_decDefineMembers,theTranslator->trDefines());
4749     }
createTypedefs() const4750     TemplateVariant createTypedefs() const
4751     {
4752       return createMemberList(MemberListType_decTypedefMembers,theTranslator->trTypedefs());
4753     }
createEnums() const4754     TemplateVariant createEnums() const
4755     {
4756       return createMemberList(MemberListType_decEnumMembers,theTranslator->trEnumerations());
4757     }
createEnumValues() const4758     TemplateVariant createEnumValues() const
4759     {
4760       return createMemberList(MemberListType_decEnumValMembers,theTranslator->trEnumerationValues());
4761     }
createFunctions() const4762     TemplateVariant createFunctions() const
4763     {
4764       SrcLangExt lang = m_groupDef->getLanguage();
4765       return createMemberList(MemberListType_decFuncMembers, lang==SrcLangExt_Fortran ? theTranslator->trSubprograms() :
4766                                                              lang==SrcLangExt_VHDL    ? theTranslator->trFunctionAndProc() :
4767                                                                                         theTranslator->trFunctions());
4768     }
createVariables() const4769     TemplateVariant createVariables() const
4770     {
4771       static bool sliceOpt   = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
4772       return createMemberList(MemberListType_decVarMembers, sliceOpt ? theTranslator->trConstants() :
4773                                                                        theTranslator->trVariables());
4774     }
createSignals() const4775     TemplateVariant createSignals() const
4776     {
4777       return createMemberList(MemberListType_signals,theTranslator->trSignals());
4778     }
createPublicSlots() const4779     TemplateVariant createPublicSlots() const
4780     {
4781       return createMemberList(MemberListType_pubSlots,theTranslator->trPublicSlots());
4782     }
createProtectedSlots() const4783     TemplateVariant createProtectedSlots() const
4784     {
4785       return createMemberList(MemberListType_proSlots,theTranslator->trProtectedSlots());
4786     }
createPrivateSlots() const4787     TemplateVariant createPrivateSlots() const
4788     {
4789       return createMemberList(MemberListType_priSlots,theTranslator->trPrivateSlots());
4790     }
createEvents() const4791     TemplateVariant createEvents() const
4792     {
4793       return createMemberList(MemberListType_events,theTranslator->trEvents());
4794     }
createProperties() const4795     TemplateVariant createProperties() const
4796     {
4797       return createMemberList(MemberListType_properties,theTranslator->trProperties());
4798     }
createFriends() const4799     TemplateVariant createFriends() const
4800     {
4801       return createMemberList(MemberListType_friends,theTranslator->trFriends());
4802     }
createDetailedMacros() const4803     TemplateVariant createDetailedMacros() const
4804     {
4805       return createMemberList(MemberListType_docDefineMembers,theTranslator->trDefineDocumentation());
4806     }
createDetailedTypedefs() const4807     TemplateVariant createDetailedTypedefs() const
4808     {
4809       return createMemberList(MemberListType_docTypedefMembers,theTranslator->trTypedefDocumentation());
4810     }
createDetailedEnums() const4811     TemplateVariant createDetailedEnums() const
4812     {
4813       return createMemberList(MemberListType_docEnumMembers,theTranslator->trEnumerationTypeDocumentation());
4814     }
createDetailedEnumValues() const4815     TemplateVariant createDetailedEnumValues() const
4816     {
4817       return createMemberList(MemberListType_docEnumValMembers,theTranslator->trEnumerationValueDocumentation());
4818     }
createDetailedFunctions() const4819     TemplateVariant createDetailedFunctions() const
4820     {
4821       SrcLangExt lang = m_groupDef->getLanguage();
4822       return createMemberList(MemberListType_docFuncMembers, lang==SrcLangExt_Fortran ? theTranslator->trSubprogramDocumentation() :
4823                                                                                         theTranslator->trFunctionDocumentation());
4824     }
createDetailedVariables() const4825     TemplateVariant createDetailedVariables() const
4826     {
4827       return createMemberList(MemberListType_docVarMembers,theTranslator->trVariableDocumentation());
4828     }
createDetailedSignals() const4829     TemplateVariant createDetailedSignals() const
4830     {
4831       return createMemberList(MemberListType_docSignalMembers,theTranslator->trSignals());
4832     }
createDetailedPublicSlots() const4833     TemplateVariant createDetailedPublicSlots() const
4834     {
4835       return createMemberList(MemberListType_docPubSlotMembers,theTranslator->trPublicSlots());
4836     }
createDetailedProtectedSlots() const4837     TemplateVariant createDetailedProtectedSlots() const
4838     {
4839       return createMemberList(MemberListType_docProSlotMembers,theTranslator->trProtectedSlots());
4840     }
createDetailedPrivateSlots() const4841     TemplateVariant createDetailedPrivateSlots() const
4842     {
4843       return createMemberList(MemberListType_docPriSlotMembers,theTranslator->trPrivateSlots());
4844     }
createDetailedEvents() const4845     TemplateVariant createDetailedEvents() const
4846     {
4847       return createMemberList(MemberListType_docEventMembers,theTranslator->trEventDocumentation());
4848     }
createDetailedProperties() const4849     TemplateVariant createDetailedProperties() const
4850     {
4851       return createMemberList(MemberListType_docPropMembers,theTranslator->trPropertyDocumentation());
4852     }
createDetailedFriends() const4853     TemplateVariant createDetailedFriends() const
4854     {
4855       return createMemberList(MemberListType_docFriendMembers,theTranslator->trFriends());
4856     }
createInlineClasses() const4857     TemplateVariant createInlineClasses() const
4858     {
4859       TemplateVariantList list;
4860       for (const auto &cd : m_groupDef->getClasses())
4861       {
4862         if (!cd->isAnonymous() &&
4863             cd->isLinkableInProject() &&
4864             cd->isEmbeddedInOuterScope() &&
4865             cd->partOfGroups().empty())
4866         {
4867           list.push_back(ClassContext::alloc(cd));
4868         }
4869       }
4870       return TemplateImmutableList::alloc(list);
4871     }
createMemberGroups() const4872     TemplateVariant createMemberGroups() const
4873     {
4874       return !m_groupDef->getMemberGroups().empty() ?
4875           MemberGroupListContext::alloc(m_groupDef,relPathAsString(),m_groupDef->getMemberGroups(),m_groupDef->subGrouping()) :
4876           MemberGroupListContext::alloc();
4877     }
createGroupGraph() const4878     DotGroupCollaborationPtr createGroupGraph() const
4879     {
4880       return std::make_shared<DotGroupCollaboration>(m_groupDef);
4881     }
4882 
4883     const GroupDef *m_groupDef;
4884     struct Cachable : public DefinitionContext<ModuleContext::Private>::Cachable
4885     {
4886       CachedItem<TemplateVariant,  Private, &Private::createModules>                modules;
4887       CachedItem<TemplateVariant,  Private, &Private::createDirs>                   dirs;
4888       CachedItem<TemplateVariant,  Private, &Private::createFiles>                  files;
4889       CachedItem<TemplateVariant,  Private, &Private::createClasses>                classes;
4890       CachedItem<TemplateVariant,  Private, &Private::createNamespaces>             namespaces;
4891       CachedItem<TemplateVariant,  Private, &Private::createConstantgroups>         constantgroups;
4892       CachedItem<TemplateVariant,  Private, &Private::createExamples>               examples;
4893       CachedItem<TemplateVariant,  Private, &Private::createPages>                  pages;
4894       CachedItem<TemplateVariant,  Private, &Private::createMacros>                 macros;
4895       CachedItem<TemplateVariant,  Private, &Private::createTypedefs>               typedefs;
4896       CachedItem<TemplateVariant,  Private, &Private::createEnums>                  enums;
4897       CachedItem<TemplateVariant,  Private, &Private::createEnumValues>             enumValues;
4898       CachedItem<TemplateVariant,  Private, &Private::createFunctions>              functions;
4899       CachedItem<TemplateVariant,  Private, &Private::createVariables>              variables;
4900       CachedItem<TemplateVariant,  Private, &Private::createSignals>                signals;
4901       CachedItem<TemplateVariant,  Private, &Private::createPublicSlots>            publicSlots;
4902       CachedItem<TemplateVariant,  Private, &Private::createProtectedSlots>         protectedSlots;
4903       CachedItem<TemplateVariant,  Private, &Private::createPrivateSlots>           privateSlots;
4904       CachedItem<TemplateVariant,  Private, &Private::createEvents>                 events;
4905       CachedItem<TemplateVariant,  Private, &Private::createProperties>             properties;
4906       CachedItem<TemplateVariant,  Private, &Private::createFriends>                friends;
4907       CachedItem<TemplateVariant,  Private, &Private::createMemberGroups>           memberGroups;
4908       CachedItem<TemplateVariant,  Private, &Private::createDetailedMacros>         detailedMacros;
4909       CachedItem<TemplateVariant,  Private, &Private::createDetailedTypedefs>       detailedTypedefs;
4910       CachedItem<TemplateVariant,  Private, &Private::createDetailedEnums>          detailedEnums;
4911       CachedItem<TemplateVariant,  Private, &Private::createDetailedEnumValues>     detailedEnumValues;
4912       CachedItem<TemplateVariant,  Private, &Private::createDetailedFunctions>      detailedFunctions;
4913       CachedItem<TemplateVariant,  Private, &Private::createDetailedVariables>      detailedVariables;
4914       CachedItem<TemplateVariant,  Private, &Private::createDetailedSignals>        detailedSignals;
4915       CachedItem<TemplateVariant,  Private, &Private::createDetailedPublicSlots>    detailedPublicSlots;
4916       CachedItem<TemplateVariant,  Private, &Private::createDetailedProtectedSlots> detailedProtectedSlots;
4917       CachedItem<TemplateVariant,  Private, &Private::createDetailedPrivateSlots>   detailedPrivateSlots;
4918       CachedItem<TemplateVariant,  Private, &Private::createDetailedEvents>         detailedEvents;
4919       CachedItem<TemplateVariant,  Private, &Private::createDetailedProperties>     detailedProperties;
4920       CachedItem<TemplateVariant,  Private, &Private::createDetailedFriends>        detailedFriends;
4921       CachedItem<TemplateVariant,  Private, &Private::createInlineClasses>          inlineClasses;
4922       CachedItem<DotGroupCollaborationPtr, Private, &Private::createGroupGraph>     groupGraph;
4923     };
4924     Cachable m_cachable;
4925     static const PropertyMap<ModuleContext::Private> s_inst;
4926 };
4927 
4928 //%% struct Module(Symbol): group information
4929 //%% {
4930 const PropertyMap<ModuleContext::Private> ModuleContext::Private::s_inst {
4931   BASE_PROPERTIES,
4932   {  "title",                     &Private::title },
4933   {  "highlight",                 &Private::highlight },
4934   {  "subhighlight",              &Private::subHighlight },
4935   {  "hasGroupGraph",             &Private::hasGroupGraph },
4936   {  "groupGraph",                &Private::groupGraph },
4937   {  "hasDetails",                &Private::hasDetails },
4938   {  "modules",                   &Private::modules },
4939   {  "dirs",                      &Private::dirs },
4940   {  "files",                     &Private::files },
4941   {  "namespaces",                &Private::namespaces },
4942   {  "classes",                   &Private::classes },
4943   {  "constantgroups",            &Private::constantgroups },
4944   {  "examples",                  &Private::examples },
4945   {  "macros",                    &Private::macros },
4946   {  "typedefs",                  &Private::typedefs },
4947   {  "enums",                     &Private::enums },
4948   {  "enumvalues",                &Private::enumValues },
4949   {  "functions",                 &Private::functions },
4950   {  "variables",                 &Private::variables },
4951   {  "signals",                   &Private::signals },
4952   {  "publicSlots",               &Private::publicSlots },
4953   {  "protectedSlots",            &Private::protectedSlots },
4954   {  "privateSlots",              &Private::privateSlots },
4955   {  "events",                    &Private::events },
4956   {  "properties",                &Private::properties },
4957   {  "friends",                   &Private::friends },
4958   {  "memberGroups",              &Private::memberGroups },
4959   {  "detailedMacros",            &Private::detailedMacros },
4960   {  "detailedTypedefs",          &Private::detailedTypedefs },
4961   {  "detailedEnums",             &Private::detailedEnums },
4962   {  "detailedEnumValues",        &Private::detailedEnumValues },
4963   {  "detailedFunctions",         &Private::detailedFunctions },
4964   {  "detailedVariables",         &Private::detailedVariables },
4965   {  "detailedSignals",           &Private::detailedSignals },
4966   {  "detailedPublicSlots",       &Private::detailedPublicSlots },
4967   {  "detailedProtectedSlots",    &Private::detailedProtectedSlots },
4968   {  "detailedPrivateSlots",      &Private::detailedPrivateSlots },
4969   {  "detailedEvents",            &Private::detailedEvents },
4970   {  "detailedProperties",        &Private::detailedProperties },
4971   {  "detailedFriends",           &Private::detailedFriends },
4972   {  "inlineClasses",             &Private::inlineClasses },
4973   {  "compoundType",              &Private::compoundType }
4974 };
4975 //%% }
4976 
ModuleContext(const GroupDef * gd)4977 ModuleContext::ModuleContext(const GroupDef *gd) : p(std::make_unique<Private>(gd))
4978 {
4979 }
4980 
~ModuleContext()4981 ModuleContext::~ModuleContext()
4982 {
4983 }
4984 
get(const QCString & n) const4985 TemplateVariant ModuleContext::get(const QCString &n) const
4986 {
4987   return p->get(n);
4988 }
4989 
fields() const4990 StringVector ModuleContext::fields() const
4991 {
4992   return p->fields();
4993 }
4994 
4995 //------------------------------------------------------------------------
4996 
4997 //%% list ClassList[Class] : list of classes
4998 class ClassListContext::Private : public GenericNodeListContext
4999 {
5000   public:
addClasses(const ClassLinkedMap & classLinkedMap)5001     void addClasses(const ClassLinkedMap &classLinkedMap)
5002     {
5003       for (const auto &cd : classLinkedMap)
5004       {
5005         if (cd->getLanguage()==SrcLangExt_VHDL &&
5006             ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKAGECLASS ||
5007              (VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKBODYCLASS)
5008            ) // no architecture
5009         {
5010           continue;
5011         }
5012         if (cd->isLinkableInProject() && cd->templateMaster()==0 &&
5013             !cd->isHidden() && !cd->isEmbeddedInOuterScope())
5014         {
5015           append(ClassContext::alloc(cd.get()));
5016         }
5017       }
5018     }
5019 };
5020 
ClassListContext()5021 ClassListContext::ClassListContext() : p(std::make_unique<Private>())
5022 {
5023   p->addClasses(*Doxygen::classLinkedMap);
5024   p->addClasses(*Doxygen::hiddenClassLinkedMap);
5025 }
5026 
~ClassListContext()5027 ClassListContext::~ClassListContext()
5028 {
5029 }
5030 
5031 // TemplateListIntf
count() const5032 uint ClassListContext::count() const
5033 {
5034   return p->count();
5035 }
5036 
at(uint index) const5037 TemplateVariant ClassListContext::at(uint index) const
5038 {
5039   return p->at(index);
5040 }
5041 
createIterator() const5042 TemplateListIntf::ConstIteratorPtr ClassListContext::createIterator() const
5043 {
5044   return p->createIterator();
5045 }
5046 
5047 //------------------------------------------------------------------------
5048 
5049 class ClassIndexContext::Private
5050 {
5051   public:
5052     // TemplateStructIntf methods
get(const QCString & n) const5053     TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
fields() const5054     StringVector fields() const                  { return s_inst.fields(); }
5055 
5056   private:
5057     // Property getters
list() const5058     TemplateVariant list() const                 { return m_classes.get(this); }
fileName() const5059     TemplateVariant fileName() const             { return "classes"; }
relPath() const5060     TemplateVariant relPath() const              { return ""; }
highlight() const5061     TemplateVariant highlight() const            { return "classes"; }
subhighlight() const5062     TemplateVariant subhighlight() const         { return "classindex"; }
title() const5063     TemplateVariant title() const
5064     {
5065       return Config_getBool(OPTIMIZE_FOR_FORTRAN) ? theTranslator->trDataTypes()   :
5066              Config_getBool(OPTIMIZE_OUTPUT_VHDL) ? theTranslator->trDesignUnits() :
5067                                                     theTranslator->trCompoundIndex();
5068     }
5069   private:
createClasses() const5070     TemplateVariant createClasses() const
5071     {
5072       TemplateVariantList list;
5073       list.reserve(Doxygen::classLinkedMap->size());
5074       if (Doxygen::classLinkedMap)
5075       {
5076         for (const auto &cd : *Doxygen::classLinkedMap)
5077         {
5078           if (cd->getLanguage()==SrcLangExt_VHDL &&
5079               ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKAGECLASS ||
5080                (VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKBODYCLASS)
5081              ) // no architecture
5082           {
5083             continue;
5084           }
5085           if (cd->isLinkableInProject() && cd->templateMaster()==0)
5086           {
5087             list.push_back(ClassContext::alloc(cd.get()));
5088           }
5089         }
5090       }
5091       return TemplateImmutableList::alloc(list);
5092     }
5093 
5094     CachedItem<TemplateVariant,  Private, &Private::createClasses> m_classes;
5095     static const PropertyMap<ClassIndexContext::Private> s_inst;
5096 };
5097 
5098 //%% struct ClassIndex
5099 //%% {
5100 const PropertyMap<ClassIndexContext::Private> ClassIndexContext::Private::s_inst {
5101   {  "list",        &Private::list },
5102   {  "fileName",    &Private::fileName },
5103   {  "relPath",     &Private::relPath },
5104   {  "highlight",   &Private::highlight },
5105   {  "subhighlight",&Private::subhighlight },
5106   {  "title",       &Private::title }
5107 };
5108 //%% }
5109 
ClassIndexContext()5110 ClassIndexContext::ClassIndexContext() : p(std::make_unique<Private>())
5111 {
5112 }
5113 
~ClassIndexContext()5114 ClassIndexContext::~ClassIndexContext()
5115 {
5116 }
5117 
5118 // TemplateStructIntf
get(const QCString & n) const5119 TemplateVariant ClassIndexContext::get(const QCString &n) const
5120 {
5121   return p->get(n);
5122 }
5123 
fields() const5124 StringVector ClassIndexContext::fields() const
5125 {
5126   return p->fields();
5127 }
5128 
5129 //------------------------------------------------------------------------
5130 
computeMaxDepth(const TemplateListIntfPtr list)5131 static int computeMaxDepth(const TemplateListIntfPtr list)
5132 {
5133   int maxDepth=0;
5134   if (list)
5135   {
5136     TemplateListIntf::ConstIteratorPtr it = list->createIterator();
5137     TemplateVariant v;
5138     for (it->toFirst();it->current(v);it->toNext())
5139     {
5140       const TemplateStructIntfPtr s = v.toStruct();
5141       TemplateVariant child = s->get("children");
5142       int d = computeMaxDepth(child.toList())+1;
5143       if (d>maxDepth) maxDepth=d;
5144     }
5145   }
5146   return maxDepth;
5147 }
5148 
computeNumNodesAtLevel(const TemplateStructIntfPtr s,int level,int maxLevel)5149 static int computeNumNodesAtLevel(const TemplateStructIntfPtr s,int level,int maxLevel)
5150 {
5151   int num=0;
5152   if (level<maxLevel)
5153   {
5154     num++;
5155     TemplateVariant child = s->get("children");
5156     if (child.toList())
5157     {
5158       TemplateListIntf::ConstIteratorPtr it = child.toList()->createIterator();
5159       TemplateVariant v;
5160       for (it->toFirst();it->current(v);it->toNext())
5161       {
5162         num+=computeNumNodesAtLevel(v.toStruct(),level+1,maxLevel);
5163       }
5164     }
5165   }
5166   return num;
5167 }
5168 
computePreferredDepth(const TemplateListIntfPtr list,int maxDepth)5169 static int computePreferredDepth(const TemplateListIntfPtr list,int maxDepth)
5170 {
5171   int preferredNumEntries = Config_getInt(HTML_INDEX_NUM_ENTRIES);
5172   int preferredDepth=1;
5173   if (preferredNumEntries>0)
5174   {
5175     int depth = maxDepth;
5176     for (int i=1;i<=depth;i++)
5177     {
5178       int num=0;
5179       TemplateListIntf::ConstIteratorPtr it = list->createIterator();
5180       TemplateVariant v;
5181       for (it->toFirst();it->current(v);it->toNext())
5182       {
5183         num+=computeNumNodesAtLevel(v.toStruct(),0,i);
5184       }
5185       if (num<=preferredNumEntries)
5186       {
5187         preferredDepth=i;
5188       }
5189       else
5190       {
5191         break;
5192       }
5193     }
5194   }
5195   return preferredDepth;
5196 }
5197 
5198 //------------------------------------------------------------------------
5199 
5200 class ClassHierarchyContext::Private
5201 {
5202   public:
Private()5203     Private()
5204     {
5205       m_classTree = NestingContext::alloc(0,ContextTreeType::ClassInheritance,0);
5206       auto ctx = std::dynamic_pointer_cast<NestingContext>(m_classTree);
5207       ClassDefSet visitedClasses;
5208       ctx->addClassHierarchy(*Doxygen::classLinkedMap,visitedClasses);
5209       ctx->addClassHierarchy(*Doxygen::hiddenClassLinkedMap,visitedClasses);
5210     }
5211 
5212     // TemplateStructIntf methods
get(const QCString & n) const5213     TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
fields() const5214     StringVector fields() const                  { return s_inst.fields(); }
5215 
5216   private:
5217     // Property getters
tree() const5218     TemplateVariant tree() const                 { return TemplateVariant(m_classTree); }
fileName() const5219     TemplateVariant fileName() const             { return "hierarchy"; }
relPath() const5220     TemplateVariant relPath() const              { return ""; }
highlight() const5221     TemplateVariant highlight() const            { return "classes"; }
subhighlight() const5222     TemplateVariant subhighlight() const         { return "classhierarchy"; }
diagrams() const5223     TemplateVariant diagrams() const             { return m_diagrams.get(this); }
maxDepth() const5224     TemplateVariant maxDepth() const             { return m_maxDepth.get(this); }
preferredDepth() const5225     TemplateVariant preferredDepth() const       { return m_preferredDepth.get(this); }
title() const5226     TemplateVariant title() const
5227     {
5228       return Config_getBool(OPTIMIZE_OUTPUT_VHDL) ? theTranslator->trDesignUnitHierarchy() :
5229                                                     theTranslator->trClassHierarchy();
5230     }
5231   private:
createMaxDepth() const5232     int createMaxDepth() const
5233     {
5234       return computeMaxDepth(m_classTree);
5235     }
createPreferredDepth() const5236     int createPreferredDepth() const
5237     {
5238       return computePreferredDepth(m_classTree,m_maxDepth.get(this));
5239     }
createDiagrams() const5240     TemplateVariant createDiagrams() const
5241     {
5242       TemplateVariantList diagrams;
5243       DotGfxHierarchyTablePtr hierarchy = std::make_shared<DotGfxHierarchyTable>();
5244       diagrams.reserve(hierarchy->subGraphs().size());
5245       int id=0;
5246       for (auto n : hierarchy->subGraphs())
5247       {
5248         diagrams.push_back(InheritanceGraphContext::alloc(hierarchy,n,id++));
5249       }
5250       return TemplateImmutableList::alloc(diagrams);
5251     }
5252 
5253     TemplateListIntfPtr m_classTree;
5254     CachedItem<int,                     Private, &Private::createMaxDepth>       m_maxDepth;
5255     CachedItem<int,                     Private, &Private::createPreferredDepth> m_preferredDepth;
5256     CachedItem<TemplateVariant,         Private, &Private::createDiagrams>       m_diagrams;
5257     static const PropertyMap<ClassHierarchyContext::Private> s_inst;
5258 };
5259 
5260 //%% struct ClassHierarchy: inheritance tree
5261 //%% {
5262 const PropertyMap<ClassHierarchyContext::Private> ClassHierarchyContext::Private::s_inst {
5263   {  "tree",            &Private::tree },
5264   {  "fileName",        &Private::fileName },
5265   {  "relPath",         &Private::relPath },
5266   {  "highlight",       &Private::highlight },
5267   {  "subhighlight",    &Private::subhighlight },
5268   {  "diagrams",        &Private::diagrams },
5269   {  "maxDepth",        &Private::maxDepth },
5270   {  "preferredDepth",  &Private::preferredDepth },
5271   {  "title",           &Private::title },
5272 };
5273 //%% }
5274 
ClassHierarchyContext()5275 ClassHierarchyContext::ClassHierarchyContext() : p(std::make_unique<Private>())
5276 {
5277 }
5278 
~ClassHierarchyContext()5279 ClassHierarchyContext::~ClassHierarchyContext()
5280 {
5281 }
5282 
get(const QCString & name) const5283 TemplateVariant ClassHierarchyContext::get(const QCString &name) const
5284 {
5285   return p->get(name);
5286 }
5287 
fields() const5288 StringVector ClassHierarchyContext::fields() const
5289 {
5290   return p->fields();
5291 }
5292 
5293 //------------------------------------------------------------------------
5294 
5295 class NestingNodeContext::Private
5296 {
5297   public:
Private(const NestingNodeContext * parent,const NestingNodeContext * thisNode,ContextTreeType type,const Definition * d,int index,int level,bool addCls,bool addCps,bool inherit,bool hideSuper,ClassDefSet & visitedClasses)5298     Private(const NestingNodeContext *parent,const NestingNodeContext *thisNode,
5299         ContextTreeType type,
5300         const Definition *d,int index,int level,
5301         bool addCls,bool addCps,bool inherit, bool hideSuper,
5302         ClassDefSet &visitedClasses)
5303       : m_parent(parent), m_type(type), m_def(d), m_level(level), m_index(index)
5304     {
5305       m_children = std::dynamic_pointer_cast<NestingContext>(NestingContext::alloc(thisNode,m_type,level+1));
5306       m_members = std::dynamic_pointer_cast<NestingContext>(NestingContext::alloc(thisNode,m_type,level+1));
5307       addNamespaces(addCls,addCps,visitedClasses);
5308       addClasses(inherit,hideSuper,visitedClasses);
5309       addDirFiles(visitedClasses);
5310       addPages(visitedClasses);
5311       addModules(visitedClasses);
5312       addMembers(visitedClasses);
5313     }
5314 
5315     // TemplateStructIntf methods
get(const QCString & n) const5316     TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
fields() const5317     StringVector fields() const                  { return s_inst.fields(); }
5318 
id() const5319     TemplateVariant id() const
5320     {
5321       QCString result;
5322       if (m_parent) result=m_parent->id();
5323       result+=QCString().setNum(m_index)+"_";
5324       return result;
5325     }
5326 
5327   private:
5328     // Property getters
isLeafNode() const5329     TemplateVariant isLeafNode() const        { return m_children->count()==0; }
children() const5330     TemplateVariant children() const          { return std::static_pointer_cast<TemplateListIntf>(m_children); }
members() const5331     TemplateVariant members() const           { return std::static_pointer_cast<TemplateListIntf>(m_members); }
getClass() const5332     TemplateVariant getClass() const          { return m_class.get(this); }
getNamespace() const5333     TemplateVariant getNamespace() const      { return m_namespace.get(this); }
getDir() const5334     TemplateVariant getDir() const            { return m_dir.get(this); }
getFile() const5335     TemplateVariant getFile() const           { return m_file.get(this); }
getPage() const5336     TemplateVariant getPage() const           { return m_page.get(this); }
getModule() const5337     TemplateVariant getModule() const         { return m_module.get(this); }
getMember() const5338     TemplateVariant getMember() const         { return m_member.get(this); }
level() const5339     TemplateVariant level() const             { return m_level; }
brief() const5340     TemplateVariant brief() const             { return m_brief.get(this); }
isLinkable() const5341     TemplateVariant isLinkable() const        { return m_def->isLinkable(); }
anchor() const5342     TemplateVariant anchor() const            { return m_def->anchor(); }
fileName() const5343     TemplateVariant fileName() const          { return m_def->getOutputFileBase(); }
isReference() const5344     TemplateVariant isReference() const       { return m_def->isReference(); }
externalReference() const5345     TemplateVariant externalReference() const { return m_def->externalReference(relPathAsString()); }
name() const5346     TemplateVariant name() const
5347     {
5348       if (m_def->definitionType()==Definition::TypeMember && m_type==ContextTreeType::Module)
5349       {
5350         return toMemberDef(m_def)->qualifiedName();
5351       }
5352       else
5353       {
5354         return m_def->displayName(m_type==ContextTreeType::Module);
5355       }
5356     }
partOfGroup() const5357     TemplateVariant partOfGroup() const
5358     {
5359       return m_def->definitionType()==Definition::TypeMember ? toMemberDef(m_def)->getGroupDef()!=0 :
5360              !m_def->partOfGroups().empty();
5361     }
relPathAsString() const5362     QCString relPathAsString() const
5363     {
5364       static bool createSubdirs = Config_getBool(CREATE_SUBDIRS);
5365       return createSubdirs ? QCString("../../") : QCString("");
5366     }
5367 
5368     //------------------------------------------------------------------
5369 
addClasses(bool inherit,bool hideSuper,ClassDefSet & visitedClasses)5370     void addClasses(bool inherit, bool hideSuper,ClassDefSet &visitedClasses)
5371     {
5372       const ClassDef *cd = toClassDef(m_def);
5373       if (cd)
5374       {
5375         if (inherit)
5376         {
5377           bool hasChildren = visitedClasses.find(cd)==visitedClasses.end() &&
5378             !hideSuper && classHasVisibleChildren(cd);
5379           if (hasChildren)
5380           {
5381             visitedClasses.insert(cd);
5382             if (cd->getLanguage()==SrcLangExt_VHDL)
5383             {
5384               m_children->addDerivedClasses(cd->baseClasses(),false,visitedClasses);
5385             }
5386             else
5387             {
5388               m_children->addDerivedClasses(cd->subClasses(),false,visitedClasses);
5389             }
5390           }
5391         }
5392         else
5393         {
5394           m_children->addClasses(cd->getClasses(),FALSE,visitedClasses);
5395         }
5396       }
5397       const GroupDef *gd = toGroupDef(m_def);
5398       if (gd)
5399       {
5400         m_children->addClasses(gd->getClasses(),FALSE,visitedClasses);
5401       }
5402     }
addConcepts(ClassDefSet & visitedClasses)5403     void addConcepts(ClassDefSet &visitedClasses)
5404     {
5405       const GroupDef *gd = toGroupDef(m_def);
5406       if (gd)
5407       {
5408         m_children->addConcepts(gd->getConcepts(),FALSE,visitedClasses);
5409       }
5410     }
addNamespaces(bool addClasses,bool addConcepts,ClassDefSet & visitedClasses)5411     void addNamespaces(bool addClasses,bool addConcepts,ClassDefSet &visitedClasses)
5412     {
5413       const NamespaceDef *nd = toNamespaceDef(m_def);
5414       if (nd)
5415       {
5416         if (!nd->getNamespaces().empty())
5417         {
5418           m_children->addNamespaces(nd->getNamespaces(),FALSE,addClasses,addConcepts,visitedClasses);
5419         }
5420         if (addClasses)
5421         {
5422           m_children->addClasses(nd->getClasses(),FALSE,visitedClasses);
5423         }
5424         if (addConcepts)
5425         {
5426           m_children->addConcepts(nd->getConcepts(),FALSE,visitedClasses);
5427         }
5428       }
5429       const GroupDef *gd = toGroupDef(m_def);
5430       if (gd)
5431       {
5432         m_children->addConcepts(gd->getConcepts(),false,visitedClasses);
5433       }
5434     }
addDirFiles(ClassDefSet & visitedClasses)5435     void addDirFiles(ClassDefSet &visitedClasses)
5436     {
5437       const DirDef *dd = toDirDef(m_def);
5438       if (dd)
5439       {
5440         m_children->addDirs(dd->subDirs(),visitedClasses);
5441         m_children->addFiles(dd->getFiles(),visitedClasses);
5442       }
5443       const GroupDef *gd = toGroupDef(m_def);
5444       if (gd)
5445       {
5446         m_children->addDirs(gd->getDirs(),visitedClasses);
5447       }
5448     }
addPages(ClassDefSet & visitedClasses)5449     void addPages(ClassDefSet &visitedClasses)
5450     {
5451       const PageDef *pd = toPageDef(m_def);
5452       if (pd && !pd->getSubPages().empty())
5453       {
5454         m_children->addPages(pd->getSubPages(),FALSE,visitedClasses);
5455       }
5456       const GroupDef *gd = toGroupDef(m_def);
5457       if (gd)
5458       {
5459         m_children->addPages(gd->getPages(),FALSE,visitedClasses);
5460       }
5461     }
addModules(ClassDefSet & visitedClasses)5462     void addModules(ClassDefSet &visitedClasses)
5463     {
5464       const GroupDef *gd = toGroupDef(m_def);
5465       if (gd && !gd->getSubGroups().empty())
5466       {
5467         m_children->addModules(gd->getSubGroups(),visitedClasses);
5468       }
5469     }
addMembers(ClassDefSet & visitedClasses)5470     void addMembers(ClassDefSet &visitedClasses)
5471     {
5472       if (m_type!=ContextTreeType::Module && m_def->partOfGroups().empty()) // show outside of group
5473       {
5474         if (m_def->definitionType()==Definition::TypeNamespace)
5475         {
5476           // add namespace members
5477           for (const auto &lde : LayoutDocManager::instance().docEntries(LayoutDocManager::Namespace))
5478           {
5479             if (lde->kind()==LayoutDocEntry::MemberDef)
5480             {
5481               const LayoutDocEntryMemberDef *lmd = (const LayoutDocEntryMemberDef*)lde.get();
5482               const MemberList *ml = toNamespaceDef(m_def)->getMemberList(lmd->type);
5483               if (ml)
5484               {
5485                 m_members->addMembers(*ml,visitedClasses);
5486               }
5487             }
5488           }
5489         }
5490         else if (m_def->definitionType()==Definition::TypeClass)
5491         {
5492           // add class members
5493           for (const auto &lde : LayoutDocManager::instance().docEntries(LayoutDocManager::Class))
5494           {
5495             if (lde->kind()==LayoutDocEntry::MemberDef)
5496             {
5497               const LayoutDocEntryMemberDef *lmd = (const LayoutDocEntryMemberDef*)lde.get();
5498               const MemberList *ml = toClassDef(m_def)->getMemberList(lmd->type);
5499               if (ml)
5500               {
5501                 m_members->addMembers(*ml,visitedClasses);
5502               }
5503             }
5504           }
5505         }
5506         else if (m_def->definitionType()==Definition::TypeFile)
5507         {
5508           // add class members
5509           for (const auto &lde : LayoutDocManager::instance().docEntries(LayoutDocManager::File))
5510           {
5511             if (lde->kind()==LayoutDocEntry::MemberDef)
5512             {
5513               const LayoutDocEntryMemberDef *lmd = (const LayoutDocEntryMemberDef*)lde.get();
5514               const MemberList *ml = toFileDef(m_def)->getMemberList(lmd->type);
5515               if (ml)
5516               {
5517                 m_members->addMembers(*ml,visitedClasses);
5518               }
5519             }
5520           }
5521         }
5522       }
5523       else if (m_def->definitionType()==Definition::TypeGroup && m_type==ContextTreeType::Module) // show as part of group
5524       {
5525         // add class members
5526         for (const auto &lde : LayoutDocManager::instance().docEntries(LayoutDocManager::Group))
5527         {
5528           if (lde->kind()==LayoutDocEntry::MemberDef)
5529           {
5530             const LayoutDocEntryMemberDef *lmd = (const LayoutDocEntryMemberDef*)lde.get();
5531             const MemberList *ml = toGroupDef(m_def)->getMemberList(lmd->type);
5532             if (ml)
5533             {
5534               m_members->addMembers(*ml,visitedClasses);
5535             }
5536           }
5537         }
5538       }
5539       if (m_def->definitionType()==Definition::TypeMember)
5540       {
5541         const MemberDef *md = toMemberDef(m_def);
5542         if (md->isEnumerate() && md->isStrong())
5543         {
5544           m_members->addMembers(md->enumFieldList(),visitedClasses);
5545         }
5546       }
5547     }
5548   private:
createClass() const5549     TemplateVariant createClass() const
5550     {
5551       return m_def->definitionType()==Definition::TypeClass ?
5552           TemplateVariant(ClassContext::alloc(toClassDef(m_def))) :
5553           TemplateVariant(false);
5554     }
createNamespace() const5555     TemplateVariant createNamespace() const
5556     {
5557       return m_def->definitionType()==Definition::TypeNamespace ?
5558           TemplateVariant(NamespaceContext::alloc(toNamespaceDef(m_def))) :
5559           TemplateVariant(false);
5560     }
createDir() const5561     TemplateVariant createDir() const
5562     {
5563       return m_def->definitionType()==Definition::TypeDir ?
5564           TemplateVariant(DirContext::alloc(toDirDef(m_def))) :
5565           TemplateVariant(false);
5566     }
createFile() const5567     TemplateVariant createFile() const
5568     {
5569       return m_def->definitionType()==Definition::TypeFile ?
5570           TemplateVariant(FileContext::alloc(toFileDef(m_def))) :
5571           TemplateVariant(false);
5572     }
createPage() const5573     TemplateVariant createPage() const
5574     {
5575       return m_def->definitionType()==Definition::TypePage ?
5576           TemplateVariant(PageContext::alloc(toPageDef(m_def),FALSE,FALSE)) :
5577           TemplateVariant(false);
5578     }
createModule() const5579     TemplateVariant createModule() const
5580     {
5581       return m_def->definitionType()==Definition::TypeGroup ?
5582           TemplateVariant(ModuleContext::alloc(toGroupDef(m_def))) :
5583           TemplateVariant(false);
5584     }
createMember() const5585     TemplateVariant createMember() const
5586     {
5587       return m_def->definitionType()==Definition::TypeMember ?
5588           TemplateVariant(MemberContext::alloc(toMemberDef(m_def))) :
5589           TemplateVariant(false);
5590     }
createBrief() const5591     TemplateVariant createBrief() const
5592     {
5593       return m_def->hasBriefDescription() ?
5594           TemplateVariant(parseDoc(m_def,m_def->briefFile(),m_def->briefLine(),
5595                           "",m_def->briefDescription(),TRUE)) :
5596           TemplateVariant("");
5597     }
5598 
5599     const NestingNodeContext *m_parent;
5600     ContextTreeType m_type;
5601     const Definition *m_def;
5602     std::shared_ptr<NestingContext> m_children;
5603     std::shared_ptr<NestingContext> m_members;
5604     int m_level;
5605     int m_index;
5606     CachedItem<TemplateVariant,  Private, &Private::createClass>     m_class;
5607     CachedItem<TemplateVariant,  Private, &Private::createNamespace> m_namespace;
5608     CachedItem<TemplateVariant,  Private, &Private::createDir>       m_dir;
5609     CachedItem<TemplateVariant,  Private, &Private::createFile>      m_file;
5610     CachedItem<TemplateVariant,  Private, &Private::createPage>      m_page;
5611     CachedItem<TemplateVariant,  Private, &Private::createModule>    m_module;
5612     CachedItem<TemplateVariant,  Private, &Private::createMember>    m_member;
5613     CachedItem<TemplateVariant,  Private, &Private::createBrief>     m_brief;
5614     static const PropertyMap<NestingNodeContext::Private> s_inst;
5615 };
5616 
5617 //%% struct NestingNode: node is a nesting relation tree
5618 //%% {
5619 const PropertyMap<NestingNodeContext::Private> NestingNodeContext::Private::s_inst {
5620   //%% bool is_leaf_node: true if this node does not have any children
5621   {  "is_leaf_node",&Private::isLeafNode },
5622   //%% Nesting children: list of nested classes/namespaces
5623   {  "children",&Private::children },
5624   //%% Nesting children: list of nested classes/namespaces
5625   {  "members",&Private::members },
5626   //%% [optional] Class class: class info (if this node represents a class)
5627   {  "class",&Private::getClass },
5628   //%% [optional] Namespace namespace: namespace info (if this node represents a namespace)
5629   {  "namespace",&Private::getNamespace },
5630   //%% [optional] File file: file info (if this node represents a file)
5631   {  "file",&Private::getFile },
5632   //%% [optional] Dir dir: directory info (if this node represents a directory)
5633   {  "dir",&Private::getDir },
5634   //%% [optional] Page page: page info (if this node represents a page)
5635   {  "page",&Private::getPage },
5636   //%% [optional] Module module: module info (if this node represents a module)
5637   {  "module",&Private::getModule },
5638   //%% [optional] Member member: member info (if this node represents a member)
5639   {  "member",&Private::getMember },
5640   //%% int id
5641   {  "id",&Private::id },
5642   //%% string level
5643   {  "level",&Private::level },
5644   //%% string name
5645   {  "name",&Private::name },
5646   //%% string brief
5647   {  "brief",&Private::brief },
5648   //%% bool isLinkable
5649   {  "isLinkable",&Private::isLinkable },
5650   {  "partOfGroup",&Private::partOfGroup },
5651   {  "anchor",&Private::anchor },
5652   {  "fileName",&Private::fileName },
5653   {  "isReference",&Private::isReference },
5654   {  "externalReference",&Private::externalReference }
5655 };
5656 //%% }
5657 
5658 
NestingNodeContext(const NestingNodeContext * parent,ContextTreeType type,const Definition * d,int index,int level,bool addClass,bool addConcepts,bool inherit,bool hideSuper,ClassDefSet & visitedClasses)5659 NestingNodeContext::NestingNodeContext(const NestingNodeContext *parent,
5660                                        ContextTreeType type,
5661                                        const Definition *d,int index,int level,
5662                                        bool addClass,bool addConcepts,
5663                                        bool inherit,bool hideSuper,
5664                                        ClassDefSet &visitedClasses)
5665   : p(std::make_unique<Private>(parent,this,type,d,index,level,addClass,addConcepts,inherit,hideSuper,visitedClasses))
5666 {
5667 }
5668 
~NestingNodeContext()5669 NestingNodeContext::~NestingNodeContext()
5670 {
5671 }
5672 
get(const QCString & n) const5673 TemplateVariant NestingNodeContext::get(const QCString &n) const
5674 {
5675   return p->get(n);
5676 }
5677 
fields() const5678 StringVector NestingNodeContext::fields() const
5679 {
5680   return p->fields();
5681 }
5682 
id() const5683 QCString NestingNodeContext::id() const
5684 {
5685   return p->id().toString();
5686 }
5687 
5688 //------------------------------------------------------------------------
5689 
5690 //%% list Nesting[NestingNode]: namespace and class nesting relations
5691 class NestingContext::Private : public GenericNodeListContext
5692 {
5693   public:
Private(const NestingNodeContext * parent,ContextTreeType type,int level)5694     Private(const NestingNodeContext *parent,ContextTreeType type,int level)
5695       : m_parent(parent), m_type(type), m_level(level) {}
5696 
addNamespace(const NamespaceDef * nd,bool rootOnly,bool addClasses,bool addConcepts,ClassDefSet & visitedClasses)5697     void addNamespace(const NamespaceDef *nd,bool rootOnly,bool addClasses,bool addConcepts,
5698                       ClassDefSet &visitedClasses)
5699     {
5700       if (!nd->isAnonymous() &&
5701           (!rootOnly || nd->getOuterScope()==Doxygen::globalScope))
5702       {
5703         bool hasChildren = namespaceHasNestedNamespace(nd) ||
5704                            (addClasses  && namespaceHasNestedClass(nd,false,ClassDef::Class)) ||
5705                            (addConcepts && namespaceHasNestedConcept(nd)) ||
5706                            (m_type==ContextTreeType::Namespace && countVisibleMembers(nd));
5707         bool isLinkable  = nd->isLinkableInProject();
5708         if (isLinkable && hasChildren)
5709         {
5710           append(NestingNodeContext::alloc(m_parent,m_type,nd,m_index,m_level,
5711                                            addClasses,addConcepts,FALSE,FALSE,visitedClasses));
5712           m_index++;
5713         }
5714       }
5715     }
addNamespaces(const NamespaceLinkedMap & nsLinkedMap,bool rootOnly,bool addClasses,bool addConcepts,ClassDefSet & visitedClasses)5716     void addNamespaces(const NamespaceLinkedMap &nsLinkedMap,bool rootOnly,bool addClasses,bool addConcepts,ClassDefSet &visitedClasses)
5717     {
5718       for (const auto &nd : nsLinkedMap)
5719       {
5720         addNamespace(nd.get(),rootOnly,addClasses,addConcepts,visitedClasses);
5721       }
5722     }
addNamespaces(const NamespaceLinkedRefMap & nsLinkedMap,bool rootOnly,bool addClasses,bool addConcepts,ClassDefSet & visitedClasses)5723     void addNamespaces(const NamespaceLinkedRefMap &nsLinkedMap,bool rootOnly,bool addClasses,bool addConcepts,ClassDefSet &visitedClasses)
5724     {
5725       for (const auto &nd : nsLinkedMap)
5726       {
5727         addNamespace(nd,rootOnly,addClasses,addConcepts,visitedClasses);
5728       }
5729     }
addClass(const ClassDef * cd,bool rootOnly,ClassDefSet & visitedClasses)5730     void addClass(const ClassDef *cd,bool rootOnly,ClassDefSet &visitedClasses)
5731     {
5732       if (cd->getLanguage()==SrcLangExt_VHDL)
5733       {
5734         if ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKAGECLASS ||
5735             (VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKBODYCLASS
5736            )// no architecture
5737         {
5738           return;
5739         }
5740       }
5741       if (!rootOnly ||
5742           cd->getOuterScope()==0 ||
5743           cd->getOuterScope()==Doxygen::globalScope
5744          )
5745       {
5746         if (classVisibleInIndex(cd) && cd->templateMaster()==0)
5747         {
5748           append(NestingNodeContext::alloc(m_parent,m_type,cd,m_index,m_level,
5749                                            TRUE,FALSE,FALSE,FALSE,visitedClasses));
5750           m_index++;
5751         }
5752       }
5753     }
addConcept(const ConceptDef * cd,bool rootOnly,ClassDefSet & visitedClasses)5754     void addConcept(const ConceptDef *cd,bool rootOnly,ClassDefSet &visitedClasses)
5755     {
5756       if (!rootOnly || cd->getOuterScope()==0 || cd->getOuterScope()==Doxygen::globalScope)
5757       {
5758         if (cd->isLinkable())
5759         {
5760           append(NestingNodeContext::alloc(m_parent,m_type,cd,m_index,m_level,
5761                                            FALSE,TRUE,FALSE,FALSE,visitedClasses));
5762           m_index++;
5763         }
5764       }
5765     }
addClasses(const ClassLinkedRefMap & clLinkedMap,bool rootOnly,ClassDefSet & visitedClasses)5766     void addClasses(const ClassLinkedRefMap &clLinkedMap,bool rootOnly,ClassDefSet &visitedClasses)
5767     {
5768       for (const auto &cd : clLinkedMap)
5769       {
5770         addClass(cd,rootOnly,visitedClasses);
5771       }
5772     }
addClasses(const ClassLinkedMap & clLinkedMap,bool rootOnly,ClassDefSet & visitedClasses)5773     void addClasses(const ClassLinkedMap &clLinkedMap,bool rootOnly,ClassDefSet &visitedClasses)
5774     {
5775       for (const auto &cd : clLinkedMap)
5776       {
5777         addClass(cd.get(),rootOnly,visitedClasses);
5778       }
5779     }
addConcepts(const ConceptLinkedRefMap & cpLinkedMap,bool rootOnly,ClassDefSet & visitedClasses)5780     void addConcepts(const ConceptLinkedRefMap &cpLinkedMap,bool rootOnly,ClassDefSet &visitedClasses)
5781     {
5782       for (const auto &cd : cpLinkedMap)
5783       {
5784         addConcept(cd,rootOnly,visitedClasses);
5785       }
5786     }
addConcepts(const ConceptLinkedMap & cpLinkedMap,bool rootOnly,ClassDefSet & visitedClasses)5787     void addConcepts(const ConceptLinkedMap &cpLinkedMap,bool rootOnly,ClassDefSet &visitedClasses)
5788     {
5789       for (const auto &cd : cpLinkedMap)
5790       {
5791         addConcept(cd.get(),rootOnly,visitedClasses);
5792       }
5793     }
addDirs(const DirLinkedMap & dirLinkedMap,ClassDefSet & visitedClasses)5794     void addDirs(const DirLinkedMap &dirLinkedMap,ClassDefSet &visitedClasses)
5795     {
5796       for (const auto &dd : dirLinkedMap)
5797       {
5798         if (dd->getOuterScope()==Doxygen::globalScope)
5799         {
5800           append(NestingNodeContext::alloc(m_parent,m_type,dd.get(),m_index,m_level,
5801                                            FALSE,FALSE,FALSE,FALSE,visitedClasses));
5802           m_index++;
5803         }
5804       }
5805     }
addDirs(const DirList & dirList,ClassDefSet & visitedClasses)5806     void addDirs(const DirList &dirList,ClassDefSet &visitedClasses)
5807     {
5808       for(const auto dd : dirList)
5809       {
5810         append(NestingNodeContext::alloc(m_parent,m_type,dd,m_index,m_level,
5811                                          FALSE,FALSE,FALSE,FALSE,visitedClasses));
5812         m_index++;
5813       }
5814     }
addFiles(const FileNameLinkedMap & fnList,ClassDefSet & visitedClasses)5815     void addFiles(const FileNameLinkedMap &fnList,ClassDefSet &visitedClasses)
5816     {
5817       for (const FileNameLinkedMap::Ptr &fn : fnList)
5818       {
5819         for (const auto &fd : *fn)
5820         {
5821           if (fd->getDirDef()==0) // top level file
5822           {
5823             append(NestingNodeContext::alloc(m_parent,m_type,fd.get(),m_index,m_level,
5824                                              FALSE,FALSE,FALSE,FALSE,visitedClasses));
5825             m_index++;
5826           }
5827         }
5828       }
5829     }
addFiles(const FileList & fList,ClassDefSet & visitedClasses)5830     void addFiles(const FileList &fList,ClassDefSet &visitedClasses)
5831     {
5832       for (const auto &fd : fList)
5833       {
5834         append(NestingNodeContext::alloc(m_parent,m_type,fd,m_index,m_level,
5835                                          FALSE,FALSE,FALSE,FALSE,visitedClasses));
5836         m_index++;
5837       }
5838     }
addPage(const PageDef * pd,bool rootOnly,ClassDefSet & visitedClasses)5839     void addPage(const PageDef *pd,bool rootOnly,ClassDefSet &visitedClasses)
5840     {
5841       if (!rootOnly ||
5842           pd->getOuterScope()==0 ||
5843           pd->getOuterScope()->definitionType()!=Definition::TypePage)
5844       {
5845         append(NestingNodeContext::alloc(m_parent,m_type,pd,m_index,m_level,
5846                                           FALSE,FALSE,FALSE,FALSE,visitedClasses));
5847         m_index++;
5848       }
5849     }
addPages(const PageLinkedMap & pages,bool rootOnly,ClassDefSet & visitedClasses)5850     void addPages(const PageLinkedMap &pages,bool rootOnly,ClassDefSet &visitedClasses)
5851     {
5852       for (const auto &pd : pages)
5853       {
5854         addPage(pd.get(),rootOnly,visitedClasses);
5855       }
5856     }
addPages(const PageLinkedRefMap & pages,bool rootOnly,ClassDefSet & visitedClasses)5857     void addPages(const PageLinkedRefMap &pages,bool rootOnly,ClassDefSet &visitedClasses)
5858     {
5859       for (const auto &pd : pages)
5860       {
5861         addPage(pd,rootOnly,visitedClasses);
5862       }
5863     }
addModules(const GroupLinkedMap & groups,ClassDefSet & visitedClasses)5864     void addModules(const GroupLinkedMap &groups,ClassDefSet &visitedClasses)
5865     {
5866       for (const auto &gd : groups)
5867       {
5868         bool externalGroups = Config_getBool(EXTERNAL_GROUPS);
5869         if (!gd->isASubGroup() && gd->isVisible() &&
5870             (!gd->isReference() || externalGroups)
5871            )
5872         {
5873           append(NestingNodeContext::alloc(m_parent,m_type,gd.get(),m_index,m_level,
5874                                            FALSE,FALSE,FALSE,FALSE,visitedClasses));
5875           m_index++;
5876         }
5877       }
5878     }
addModules(const GroupList & groups,ClassDefSet & visitedClasses)5879     void addModules(const GroupList &groups,ClassDefSet &visitedClasses)
5880     {
5881       for (const auto &gd : groups)
5882       {
5883         if (gd->isVisible())
5884         {
5885           append(NestingNodeContext::alloc(m_parent,m_type,gd,m_index,m_level,
5886                                            FALSE,FALSE,FALSE,FALSE,visitedClasses));
5887           m_index++;
5888         }
5889       }
5890     }
addDerivedClasses(const BaseClassList & bcl,bool hideSuper,ClassDefSet & visitedClasses)5891     void addDerivedClasses(const BaseClassList &bcl,bool hideSuper,ClassDefSet &visitedClasses)
5892     {
5893       for (const auto &bcd : bcl)
5894       {
5895         const ClassDef *cd=bcd.classDef;
5896         if (cd->getLanguage()==SrcLangExt_VHDL && (VhdlDocGen::VhdlClasses)cd->protection()!=VhdlDocGen::ENTITYCLASS)
5897         {
5898           continue;
5899         }
5900 
5901         bool b;
5902         if (cd->getLanguage()==SrcLangExt_VHDL)
5903         {
5904           b=hasVisibleRoot(cd->subClasses());
5905         }
5906         else
5907         {
5908           b=hasVisibleRoot(cd->baseClasses());
5909         }
5910 
5911         if (cd->isVisibleInHierarchy() && b)
5912         {
5913           append(NestingNodeContext::alloc(m_parent,m_type,cd,m_index,m_level,
5914                                            TRUE,FALSE,TRUE,hideSuper,visitedClasses));
5915           m_index++;
5916         }
5917       }
5918     }
addClassHierarchy(const ClassLinkedMap & classLinkedMap,ClassDefSet & visitedClasses)5919     void addClassHierarchy(const ClassLinkedMap &classLinkedMap,ClassDefSet &visitedClasses)
5920     {
5921       for (const auto &cd : classLinkedMap)
5922       {
5923         bool b;
5924         if (cd->getLanguage()==SrcLangExt_VHDL)
5925         {
5926           if ((VhdlDocGen::VhdlClasses)cd->protection()!=VhdlDocGen::ENTITYCLASS)
5927           {
5928             continue;
5929           }
5930           b=!hasVisibleRoot(cd->subClasses());
5931         }
5932         else
5933         {
5934           b=!hasVisibleRoot(cd->baseClasses());
5935         }
5936         if (b)
5937         {
5938           if (cd->isVisibleInHierarchy()) // should it be visible
5939           {
5940             // new root level class
5941             append(NestingNodeContext::alloc(m_parent,m_type,cd.get(),m_index,m_level,
5942                                              TRUE,FALSE,TRUE,FALSE,visitedClasses));
5943             m_index++;
5944           }
5945         }
5946       }
5947     }
addMembers(const MemberVector & mv,ClassDefSet & visitedClasses)5948     void addMembers(const MemberVector &mv,ClassDefSet &visitedClasses)
5949     {
5950       for (const auto &md : mv)
5951       {
5952         if (md->visibleInIndex())
5953         {
5954           append(NestingNodeContext::alloc(m_parent,m_type,md,m_index,m_level+1,
5955                                            TRUE,FALSE,TRUE,FALSE,visitedClasses));
5956           m_index++;
5957         }
5958       }
5959     }
5960 
5961   private:
5962     const NestingNodeContext *m_parent;
5963     ContextTreeType m_type;
5964     int m_level;
5965     int m_index = 0;
5966 };
5967 
NestingContext(const NestingNodeContext * parent,ContextTreeType type,int level)5968 NestingContext::NestingContext(const NestingNodeContext *parent,ContextTreeType type,int level) : p(std::make_unique<Private>(parent,type,level))
5969 {
5970 }
5971 
~NestingContext()5972 NestingContext::~NestingContext()
5973 {
5974 }
5975 
5976 // TemplateListIntf
count() const5977 uint NestingContext::count() const
5978 {
5979   return p->count();
5980 }
5981 
at(uint index) const5982 TemplateVariant NestingContext::at(uint index) const
5983 {
5984   return p->at(index);
5985 }
5986 
createIterator() const5987 TemplateListIntf::ConstIteratorPtr NestingContext::createIterator() const
5988 {
5989   return p->createIterator();
5990 }
5991 
addClasses(const ClassLinkedRefMap & clLinkedRefMap,bool rootOnly,ClassDefSet & visitedClasses)5992 void NestingContext::addClasses(const ClassLinkedRefMap &clLinkedRefMap,bool rootOnly,ClassDefSet &visitedClasses)
5993 {
5994   p->addClasses(clLinkedRefMap,rootOnly,visitedClasses);
5995 }
5996 
addClasses(const ClassLinkedMap & clLinkedMap,bool rootOnly,ClassDefSet & visitedClasses)5997 void NestingContext::addClasses(const ClassLinkedMap &clLinkedMap,bool rootOnly,ClassDefSet &visitedClasses)
5998 {
5999   p->addClasses(clLinkedMap,rootOnly,visitedClasses);
6000 }
6001 
addConcepts(const ConceptLinkedRefMap & cpLinkedRefMap,bool rootOnly,ClassDefSet & visitedClasses)6002 void NestingContext::addConcepts(const ConceptLinkedRefMap &cpLinkedRefMap,bool rootOnly,ClassDefSet &visitedClasses)
6003 {
6004   p->addConcepts(cpLinkedRefMap,rootOnly,visitedClasses);
6005 }
6006 
addConcepts(const ConceptLinkedMap & cpLinkedMap,bool rootOnly,ClassDefSet & visitedClasses)6007 void NestingContext::addConcepts(const ConceptLinkedMap &cpLinkedMap,bool rootOnly,ClassDefSet &visitedClasses)
6008 {
6009   p->addConcepts(cpLinkedMap,rootOnly,visitedClasses);
6010 }
6011 
addNamespaces(const NamespaceLinkedMap & nsLinkedMap,bool rootOnly,bool addClasses,bool addConcepts,ClassDefSet & visitedClasses)6012 void NestingContext::addNamespaces(const NamespaceLinkedMap &nsLinkedMap,bool rootOnly,bool addClasses,bool addConcepts,ClassDefSet &visitedClasses)
6013 {
6014   p->addNamespaces(nsLinkedMap,rootOnly,addClasses,addConcepts,visitedClasses);
6015 }
6016 
addNamespaces(const NamespaceLinkedRefMap & nsLinkedRefMap,bool rootOnly,bool addClasses,bool addConcepts,ClassDefSet & visitedClasses)6017 void NestingContext::addNamespaces(const NamespaceLinkedRefMap &nsLinkedRefMap,bool rootOnly,bool addClasses,bool addConcepts,ClassDefSet &visitedClasses)
6018 {
6019   p->addNamespaces(nsLinkedRefMap,rootOnly,addClasses,addConcepts,visitedClasses);
6020 }
6021 
addDirs(const DirLinkedMap & dirs,ClassDefSet & visitedClasses)6022 void NestingContext::addDirs(const DirLinkedMap &dirs,ClassDefSet &visitedClasses)
6023 {
6024   p->addDirs(dirs,visitedClasses);
6025 }
6026 
addDirs(const DirList & dirs,ClassDefSet & visitedClasses)6027 void NestingContext::addDirs(const DirList &dirs,ClassDefSet &visitedClasses)
6028 {
6029   p->addDirs(dirs,visitedClasses);
6030 }
6031 
addFiles(const FileNameLinkedMap & files,ClassDefSet & visitedClasses)6032 void NestingContext::addFiles(const FileNameLinkedMap &files,ClassDefSet &visitedClasses)
6033 {
6034   p->addFiles(files,visitedClasses);
6035 }
6036 
addFiles(const FileList & files,ClassDefSet & visitedClasses)6037 void NestingContext::addFiles(const FileList &files,ClassDefSet &visitedClasses)
6038 {
6039   p->addFiles(files,visitedClasses);
6040 }
6041 
addPages(const PageLinkedMap & pages,bool rootOnly,ClassDefSet & visitedClasses)6042 void NestingContext::addPages(const PageLinkedMap &pages,bool rootOnly,ClassDefSet &visitedClasses)
6043 {
6044   p->addPages(pages,rootOnly,visitedClasses);
6045 }
6046 
addPages(const PageLinkedRefMap & pages,bool rootOnly,ClassDefSet & visitedClasses)6047 void NestingContext::addPages(const PageLinkedRefMap &pages,bool rootOnly,ClassDefSet &visitedClasses)
6048 {
6049   p->addPages(pages,rootOnly,visitedClasses);
6050 }
6051 
addModules(const GroupLinkedMap & modules,ClassDefSet & visitedClasses)6052 void NestingContext::addModules(const GroupLinkedMap &modules,ClassDefSet &visitedClasses)
6053 {
6054   p->addModules(modules,visitedClasses);
6055 }
6056 
addModules(const GroupList & modules,ClassDefSet & visitedClasses)6057 void NestingContext::addModules(const GroupList &modules,ClassDefSet &visitedClasses)
6058 {
6059   p->addModules(modules,visitedClasses);
6060 }
6061 
addClassHierarchy(const ClassLinkedMap & classLinkedMap,ClassDefSet & visitedClasses)6062 void NestingContext::addClassHierarchy(const ClassLinkedMap &classLinkedMap,ClassDefSet &visitedClasses)
6063 {
6064   p->addClassHierarchy(classLinkedMap,visitedClasses);
6065 }
6066 
addDerivedClasses(const BaseClassList & bcl,bool hideSuper,ClassDefSet & visitedClasses)6067 void NestingContext::addDerivedClasses(const BaseClassList &bcl,bool hideSuper,ClassDefSet &visitedClasses)
6068 {
6069   p->addDerivedClasses(bcl,hideSuper,visitedClasses);
6070 }
6071 
addMembers(const MemberVector & mv,ClassDefSet & visitedClasses)6072 void NestingContext::addMembers(const MemberVector &mv,ClassDefSet &visitedClasses)
6073 {
6074   p->addMembers(mv,visitedClasses);
6075 }
6076 
6077 
6078 //------------------------------------------------------------------------
6079 
6080 class ClassTreeContext::Private
6081 {
6082   public:
Private()6083     Private()
6084     {
6085       m_classTree = NestingContext::alloc(0,ContextTreeType::ClassNesting,0);
6086       auto ctx = std::dynamic_pointer_cast<NestingContext>(m_classTree);
6087       ClassDefSet visitedClasses;
6088       ctx->addNamespaces(*Doxygen::namespaceLinkedMap,TRUE,TRUE,FALSE,visitedClasses);
6089       ctx->addClasses(*Doxygen::classLinkedMap,TRUE,visitedClasses);
6090     }
6091 
6092     // TemplateStructIntf methods
get(const QCString & n) const6093     TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
fields() const6094     StringVector fields() const                  { return s_inst.fields(); }
6095 
6096   private:
6097     // Property getters
tree() const6098     TemplateVariant tree() const                 { return TemplateVariant(m_classTree); }
fileName() const6099     TemplateVariant fileName() const             { return "annotated"; }
relPath() const6100     TemplateVariant relPath() const              { return ""; }
highlight() const6101     TemplateVariant highlight() const            { return "classes"; }
subhighlight() const6102     TemplateVariant subhighlight() const         { return "classlist"; }
maxDepth() const6103     TemplateVariant maxDepth() const             { return m_maxDepth.get(this); }
preferredDepth() const6104     TemplateVariant preferredDepth() const       { return m_preferredDepth.get(this); }
title() const6105     TemplateVariant title() const
6106     {
6107       return Config_getBool(OPTIMIZE_FOR_FORTRAN) ? theTranslator->trCompoundListFortran() :
6108              Config_getBool(OPTIMIZE_OUTPUT_VHDL) ? theTranslator->trDesignUnitList()      :
6109                                                     theTranslator->trClasses();
6110     }
6111   private:
createMaxDepth() const6112     int createMaxDepth() const
6113     {
6114       return computeMaxDepth(m_classTree);
6115     }
createPreferredDepth() const6116     int createPreferredDepth() const
6117     {
6118       return computePreferredDepth(m_classTree,m_maxDepth.get(this));
6119     }
6120     TemplateListIntfPtr m_classTree;
6121     CachedItem<int, Private, &Private::createMaxDepth>       m_maxDepth;
6122     CachedItem<int, Private, &Private::createPreferredDepth> m_preferredDepth;
6123     static const PropertyMap<ClassTreeContext::Private> s_inst;
6124 };
6125 
6126 //%% struct ClassTree: Class nesting relations
6127 //%% {
6128 const PropertyMap<ClassTreeContext::Private> ClassTreeContext::Private::s_inst {
6129   {  "tree",          &Private::tree },
6130   {  "fileName",      &Private::fileName },
6131   {  "relPath",       &Private::relPath },
6132   {  "highlight",     &Private::highlight },
6133   {  "subhighlight",  &Private::subhighlight },
6134   {  "title",         &Private::title },
6135   {  "preferredDepth",&Private::preferredDepth },
6136   {  "maxDepth",      &Private::maxDepth }
6137 };
6138 //%% }
6139 
6140 
ClassTreeContext()6141 ClassTreeContext::ClassTreeContext() : p(std::make_unique<Private>())
6142 {
6143 }
6144 
~ClassTreeContext()6145 ClassTreeContext::~ClassTreeContext()
6146 {
6147 }
6148 
get(const QCString & name) const6149 TemplateVariant ClassTreeContext::get(const QCString &name) const
6150 {
6151   return p->get(name);
6152 }
6153 
fields() const6154 StringVector ClassTreeContext::fields() const
6155 {
6156   return p->fields();
6157 }
6158 
6159 //------------------------------------------------------------------------
6160 
6161 //%% list ConceptList[Concept] : list of namespaces
6162 class ConceptListContext::Private : public GenericNodeListContext
6163 {
6164   public:
addConcepts(const ConceptLinkedMap & nsLinkedMap)6165     void addConcepts(const ConceptLinkedMap &nsLinkedMap)
6166     {
6167       for (const auto &cd : nsLinkedMap)
6168       {
6169         if (cd->isLinkableInProject())
6170         {
6171           append(ConceptContext::alloc(cd.get()));
6172         }
6173       }
6174     }
6175 };
6176 
ConceptListContext()6177 ConceptListContext::ConceptListContext() : p(std::make_unique<Private>())
6178 {
6179   p->addConcepts(*Doxygen::conceptLinkedMap);
6180 }
6181 
~ConceptListContext()6182 ConceptListContext::~ConceptListContext()
6183 {
6184 }
6185 
6186 // TemplateListIntf
count() const6187 uint ConceptListContext::count() const
6188 {
6189   return p->count();
6190 }
6191 
at(uint index) const6192 TemplateVariant ConceptListContext::at(uint index) const
6193 {
6194   return p->at(index);
6195 }
6196 
createIterator() const6197 TemplateListIntf::ConstIteratorPtr ConceptListContext::createIterator() const
6198 {
6199   return p->createIterator();
6200 }
6201 
6202 //------------------------------------------------------------------------
6203 
6204 //%% list NamespaceList[Namespace] : list of namespaces
6205 class NamespaceListContext::Private : public GenericNodeListContext
6206 {
6207   public:
addNamespaces(const NamespaceLinkedMap & nsLinkedMap)6208     void addNamespaces(const NamespaceLinkedMap &nsLinkedMap)
6209     {
6210       for (const auto &nd : nsLinkedMap)
6211       {
6212         if (nd->isLinkableInProject())
6213         {
6214           append(NamespaceContext::alloc(nd.get()));
6215         }
6216       }
6217     }
6218 };
6219 
NamespaceListContext()6220 NamespaceListContext::NamespaceListContext() : p(std::make_unique<Private>())
6221 {
6222   p->addNamespaces(*Doxygen::namespaceLinkedMap);
6223 }
6224 
~NamespaceListContext()6225 NamespaceListContext::~NamespaceListContext()
6226 {
6227 }
6228 
6229 // TemplateListIntf
count() const6230 uint NamespaceListContext::count() const
6231 {
6232   return p->count();
6233 }
6234 
at(uint index) const6235 TemplateVariant NamespaceListContext::at(uint index) const
6236 {
6237   return p->at(index);
6238 }
6239 
createIterator() const6240 TemplateListIntf::ConstIteratorPtr NamespaceListContext::createIterator() const
6241 {
6242   return p->createIterator();
6243 }
6244 
6245 //------------------------------------------------------------------------
6246 
6247 class NamespaceTreeContext::Private
6248 {
6249   public:
Private()6250     Private()
6251     {
6252       m_namespaceTree = NestingContext::alloc(0,ContextTreeType::Namespace,0);
6253       auto ctx = std::dynamic_pointer_cast<NestingContext>(m_namespaceTree);
6254       ClassDefSet visitedClasses;
6255       ctx->addNamespaces(*Doxygen::namespaceLinkedMap,TRUE,FALSE,TRUE,visitedClasses);
6256     }
6257 
6258     // TemplateStructIntf methods
get(const QCString & n) const6259     TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
fields() const6260     StringVector fields() const                  { return s_inst.fields(); }
6261 
6262   private:
6263     // Property getters
tree() const6264     TemplateVariant tree() const                 { return TemplateVariant(m_namespaceTree); }
fileName() const6265     TemplateVariant fileName() const             { return "namespaces"; }
relPath() const6266     TemplateVariant relPath() const              { return ""; }
highlight() const6267     TemplateVariant highlight() const            { return "namespaces"; }
subhighlight() const6268     TemplateVariant subhighlight() const         { return "namespacelist"; }
maxDepth() const6269     TemplateVariant maxDepth() const             { return m_maxDepth.get(this); }
preferredDepth() const6270     TemplateVariant preferredDepth() const       { return m_preferredDepth.get(this); }
title() const6271     TemplateVariant title() const
6272     {
6273       return Config_getBool(OPTIMIZE_OUTPUT_JAVA)  ? theTranslator->trPackages()     :
6274              Config_getBool(OPTIMIZE_OUTPUT_VHDL)  ? theTranslator->trPackages()     :
6275              Config_getBool(OPTIMIZE_FOR_FORTRAN)  ? theTranslator->trModulesList()  :
6276              Config_getBool(OPTIMIZE_OUTPUT_SLICE) ? theTranslator->trModulesList()  :
6277                                                      theTranslator->trNamespaceList();
6278     }
6279 
6280   private:
createMaxDepth() const6281     int createMaxDepth() const
6282     {
6283       return computeMaxDepth(m_namespaceTree);
6284     }
createPreferredDepth() const6285     int createPreferredDepth() const
6286     {
6287       return computePreferredDepth(m_namespaceTree,m_maxDepth.get(this));
6288     }
6289     TemplateListIntfPtr m_namespaceTree;
6290     CachedItem<int, Private, &Private::createMaxDepth>       m_maxDepth;
6291     CachedItem<int, Private, &Private::createPreferredDepth> m_preferredDepth;
6292     static const PropertyMap<NamespaceTreeContext::Private> s_inst;
6293 };
6294 
6295 //%% struct NamespaceTree: tree of nested namespace
6296 //%% {
6297 const PropertyMap<NamespaceTreeContext::Private> NamespaceTreeContext::Private::s_inst {
6298   {  "tree",          &Private::tree },
6299   {  "fileName",      &Private::fileName },
6300   {  "relPath",       &Private::relPath },
6301   {  "highlight",     &Private::highlight },
6302   {  "subhighlight",  &Private::subhighlight },
6303   {  "title",         &Private::title },
6304   {  "preferredDepth",&Private::preferredDepth },
6305   {  "maxDepth",      &Private::maxDepth }
6306 };
6307 //%% }
6308 
NamespaceTreeContext()6309 NamespaceTreeContext::NamespaceTreeContext() : p(std::make_unique<Private>())
6310 {
6311 }
6312 
~NamespaceTreeContext()6313 NamespaceTreeContext::~NamespaceTreeContext()
6314 {
6315 }
6316 
get(const QCString & name) const6317 TemplateVariant NamespaceTreeContext::get(const QCString &name) const
6318 {
6319   return p->get(name);
6320 }
6321 
fields() const6322 StringVector NamespaceTreeContext::fields() const
6323 {
6324   return p->fields();
6325 }
6326 
6327 
6328 //------------------------------------------------------------------------
6329 
6330 //%% list FileList[File] : list of files
6331 class FileListContext::Private : public GenericNodeListContext
6332 {
6333   public:
addFiles(const FileNameLinkedMap & fnMap)6334     void addFiles(const FileNameLinkedMap &fnMap)
6335     {
6336       // TODO: if FULL_PATH_NAMES is enabled, the ordering should be dir+file
6337       for (const auto &fn : fnMap)
6338       {
6339         for (const auto &fd : *fn)
6340         {
6341           bool doc = fd->isLinkableInProject();
6342           bool src = fd->generateSourceFile();
6343           bool nameOk = !fd->isDocumentationFile();
6344           if (nameOk && (doc || src) && !fd->isReference())
6345           {
6346             append(FileContext::alloc(fd.get()));
6347           }
6348         }
6349       }
6350     }
6351 };
6352 
FileListContext()6353 FileListContext::FileListContext() : p(std::make_unique<Private>())
6354 {
6355   if (Doxygen::inputNameLinkedMap) p->addFiles(*Doxygen::inputNameLinkedMap);
6356 }
6357 
~FileListContext()6358 FileListContext::~FileListContext()
6359 {
6360 }
6361 
6362 // TemplateListIntf
count() const6363 uint FileListContext::count() const
6364 {
6365   return p->count();
6366 }
6367 
at(uint index) const6368 TemplateVariant FileListContext::at(uint index) const
6369 {
6370   return p->at(index);
6371 }
6372 
createIterator() const6373 TemplateListIntf::ConstIteratorPtr FileListContext::createIterator() const
6374 {
6375   return p->createIterator();
6376 }
6377 
6378 //------------------------------------------------------------------------
6379 
6380 //%% list DirList[Dir] : list of files
6381 class DirListContext::Private : public GenericNodeListContext
6382 {
6383   public:
Private()6384     Private()
6385     {
6386       for (const auto &dir : *Doxygen::dirLinkedMap)
6387       {
6388         append(DirContext::alloc(dir.get()));
6389       }
6390     }
6391 };
6392 
DirListContext()6393 DirListContext::DirListContext() : p(std::make_unique<Private>())
6394 {
6395 }
6396 
~DirListContext()6397 DirListContext::~DirListContext()
6398 {
6399 }
6400 
6401 // TemplateListIntf
count() const6402 uint DirListContext::count() const
6403 {
6404   return p->count();
6405 }
6406 
at(uint index) const6407 TemplateVariant DirListContext::at(uint index) const
6408 {
6409   return p->at(index);
6410 }
6411 
createIterator() const6412 TemplateListIntf::ConstIteratorPtr DirListContext::createIterator() const
6413 {
6414   return p->createIterator();
6415 }
6416 
6417 
6418 //------------------------------------------------------------------------
6419 
6420 //%% list UsedFiles[File] : list of files
6421 class UsedFilesContext::Private : public GenericNodeListContext
6422 {
6423   public:
addFile(const FileDef * fd)6424     void addFile(const FileDef *fd)
6425     {
6426       append(FileContext::alloc(fd));
6427     }
6428 };
6429 
UsedFilesContext(const ClassDef * cd)6430 UsedFilesContext::UsedFilesContext(const ClassDef *cd) : p(std::make_unique<Private>())
6431 {
6432   if (cd)
6433   {
6434     for (const auto &fd : cd->usedFiles())
6435     {
6436       p->addFile(fd);
6437     }
6438   }
6439 }
6440 
~UsedFilesContext()6441 UsedFilesContext::~UsedFilesContext()
6442 {
6443 }
6444 
6445 // TemplateListIntf
count() const6446 uint UsedFilesContext::count() const
6447 {
6448   return p->count();
6449 }
6450 
at(uint index) const6451 TemplateVariant UsedFilesContext::at(uint index) const
6452 {
6453   return p->at(index);
6454 }
6455 
createIterator() const6456 TemplateListIntf::ConstIteratorPtr UsedFilesContext::createIterator() const
6457 {
6458   return p->createIterator();
6459 }
6460 
addFile(const FileDef * fd)6461 void UsedFilesContext::addFile(const FileDef *fd)
6462 {
6463   p->addFile(fd);
6464 }
6465 
6466 //------------------------------------------------------------------------
6467 
6468 class FileTreeContext::Private
6469 {
6470   public:
Private()6471     Private()
6472     {
6473       // Add dirs tree
6474       m_dirFileTree = NestingContext::alloc(0,ContextTreeType::File,0);
6475       auto ctx = std::dynamic_pointer_cast<NestingContext>(m_dirFileTree);
6476       ClassDefSet visitedClasses;
6477       ctx->addDirs(*Doxygen::dirLinkedMap,visitedClasses);
6478       if (Doxygen::inputNameLinkedMap)
6479       {
6480         ctx->addFiles(*Doxygen::inputNameLinkedMap,visitedClasses);
6481       }
6482     }
6483 
6484     // TemplateStructIntf methods
get(const QCString & n) const6485     TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
fields() const6486     StringVector fields() const                  { return s_inst.fields(); }
6487 
6488   private:
6489     // Property getters
tree() const6490     TemplateVariant tree() const                 { return TemplateVariant(m_dirFileTree); }
fileName() const6491     TemplateVariant fileName() const             { return "files"; }
relPath() const6492     TemplateVariant relPath() const              { return ""; }
highlight() const6493     TemplateVariant highlight() const            { return "files"; }
subhighlight() const6494     TemplateVariant subhighlight() const         { return "filelist"; }
maxDepth() const6495     TemplateVariant maxDepth() const             { return m_maxDepth.get(this); }
preferredDepth() const6496     TemplateVariant preferredDepth() const       { return m_preferredDepth.get(this); }
title() const6497     TemplateVariant title() const                { return theTranslator->trFileList(); }
6498 
6499   private:
createMaxDepth() const6500     int createMaxDepth() const
6501     {
6502       return computeMaxDepth(m_dirFileTree);
6503     }
createPreferredDepth() const6504     int createPreferredDepth() const
6505     {
6506       return computePreferredDepth(m_dirFileTree,m_maxDepth.get(this));
6507     }
6508     TemplateListIntfPtr m_dirFileTree;
6509     CachedItem<int, Private, &Private::createMaxDepth>       m_maxDepth;
6510     CachedItem<int, Private, &Private::createPreferredDepth> m_preferredDepth;
6511     static const PropertyMap<FileTreeContext::Private> s_inst;
6512 };
6513 
6514 //%% struct FileTree: tree of directories and files
6515 //%% {
6516 const PropertyMap<FileTreeContext::Private> FileTreeContext::Private::s_inst {
6517   {  "tree",          &Private::tree },
6518   {  "fileName",      &Private::fileName },
6519   {  "relPath",       &Private::relPath },
6520   {  "highlight",     &Private::highlight },
6521   {  "subhighlight",  &Private::subhighlight },
6522   {  "title",         &Private::title },
6523   {  "preferredDepth",&Private::preferredDepth },
6524   {  "maxDepth",      &Private::maxDepth }
6525 };
6526 //%% }
6527 
6528 //PropertyMapper<FileTreeContext::Private> FileTreeContext::Private::s_inst;
6529 
FileTreeContext()6530 FileTreeContext::FileTreeContext() : p(std::make_unique<Private>())
6531 {
6532 }
6533 
~FileTreeContext()6534 FileTreeContext::~FileTreeContext()
6535 {
6536 }
6537 
get(const QCString & name) const6538 TemplateVariant FileTreeContext::get(const QCString &name) const
6539 {
6540   return p->get(name);
6541 }
6542 
fields() const6543 StringVector FileTreeContext::fields() const
6544 {
6545   return p->fields();
6546 }
6547 
6548 //------------------------------------------------------------------------
6549 
6550 class PageTreeContext::Private
6551 {
6552   public:
Private(const PageLinkedMap & pages)6553     Private(const PageLinkedMap &pages)
6554     {
6555       m_pageTree = NestingContext::alloc(0,ContextTreeType::Page,0);
6556       auto ctx = std::dynamic_pointer_cast<NestingContext>(m_pageTree);
6557       ClassDefSet visitedClasses;
6558       // Add pages
6559       ctx->addPages(pages,TRUE,visitedClasses);
6560     }
6561 
6562     // TemplateStructIntf methods
get(const QCString & n) const6563     TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
fields() const6564     StringVector fields() const                  { return s_inst.fields(); }
6565 
6566   private:
6567     // Property getters
tree() const6568     TemplateVariant tree() const                 { return TemplateVariant(m_pageTree); }
fileName() const6569     TemplateVariant fileName() const             { return "pages"; }
relPath() const6570     TemplateVariant relPath() const              { return ""; }
highlight() const6571     TemplateVariant highlight() const            { return "pages"; }
subhighlight() const6572     TemplateVariant subhighlight() const         { return ""; }
maxDepth() const6573     TemplateVariant maxDepth() const             { return m_maxDepth.get(this); }
preferredDepth() const6574     TemplateVariant preferredDepth() const       { return m_preferredDepth.get(this); }
title() const6575     TemplateVariant title() const                { return theTranslator->trRelatedPages(); }
6576 
6577   private:
createMaxDepth() const6578     int createMaxDepth() const
6579     {
6580       return computeMaxDepth(m_pageTree);
6581     }
createPreferredDepth() const6582     int createPreferredDepth() const
6583     {
6584       return computePreferredDepth(m_pageTree,m_maxDepth.get(this));
6585     }
6586     TemplateListIntfPtr m_pageTree;
6587     CachedItem<int, Private, &Private::createMaxDepth>       m_maxDepth;
6588     CachedItem<int, Private, &Private::createPreferredDepth> m_preferredDepth;
6589     static const PropertyMap<PageTreeContext::Private> s_inst;
6590 };
6591 
6592 //%% struct PageTree: tree of related pages
6593 //%% {
6594 const PropertyMap<PageTreeContext::Private> PageTreeContext::Private::s_inst {
6595   {  "tree",          &Private::tree },
6596   {  "fileName",      &Private::fileName },
6597   {  "relPath",       &Private::relPath },
6598   {  "highlight",     &Private::highlight },
6599   {  "subhighlight",  &Private::subhighlight },
6600   {  "title",         &Private::title },
6601   {  "preferredDepth",&Private::preferredDepth },
6602   {  "maxDepth",      &Private::maxDepth }
6603 };
6604 //%% }
6605 
6606 
PageTreeContext(const PageLinkedMap & pages)6607 PageTreeContext::PageTreeContext(const PageLinkedMap &pages) : p(std::make_unique<Private>(pages))
6608 {
6609 }
6610 
~PageTreeContext()6611 PageTreeContext::~PageTreeContext()
6612 {
6613 }
6614 
get(const QCString & name) const6615 TemplateVariant PageTreeContext::get(const QCString &name) const
6616 {
6617   return p->get(name);
6618 }
6619 
fields() const6620 StringVector PageTreeContext::fields() const
6621 {
6622   return p->fields();
6623 }
6624 
6625 //------------------------------------------------------------------------
6626 
6627 //%% list PageList[Page]: list of pages
6628 class PageListContext::Private : public GenericNodeListContext
6629 {
6630   public:
addPages(const PageLinkedMap & pages)6631     void addPages(const PageLinkedMap &pages)
6632     {
6633       for (const auto &pd : pages)
6634       {
6635         if (!pd->getGroupDef() && !pd->isReference())
6636         {
6637           append(PageContext::alloc(pd.get(),FALSE,FALSE));
6638         }
6639       }
6640     }
6641 };
6642 
PageListContext(const PageLinkedMap & pages)6643 PageListContext::PageListContext(const PageLinkedMap &pages) : p(std::make_unique<Private>())
6644 {
6645   p->addPages(pages);
6646 }
6647 
~PageListContext()6648 PageListContext::~PageListContext()
6649 {
6650 }
6651 
6652 // TemplateListIntf
count() const6653 uint PageListContext::count() const
6654 {
6655   return p->count();
6656 }
6657 
at(uint index) const6658 TemplateVariant PageListContext::at(uint index) const
6659 {
6660   return p->at(index);
6661 }
6662 
createIterator() const6663 TemplateListIntf::ConstIteratorPtr PageListContext::createIterator() const
6664 {
6665   return p->createIterator();
6666 }
6667 
6668 //------------------------------------------------------------------------
6669 
6670 //%% list ExampleList[Page]: list of pages
6671 class ExampleListContext::Private : public GenericNodeListContext
6672 {
6673   public:
Private()6674     Private()
6675     {
6676       for (const auto &pd : *Doxygen::exampleLinkedMap)
6677       {
6678         if (!pd->getGroupDef() && !pd->isReference())
6679         {
6680           append(PageContext::alloc(pd.get(),FALSE,TRUE));
6681         }
6682       }
6683     }
6684 };
6685 
ExampleListContext()6686 ExampleListContext::ExampleListContext() : p(std::make_unique<Private>())
6687 {
6688 }
6689 
~ExampleListContext()6690 ExampleListContext::~ExampleListContext()
6691 {
6692 }
6693 
6694 // TemplateListIntf
count() const6695 uint ExampleListContext::count() const
6696 {
6697   return p->count();
6698 }
6699 
at(uint index) const6700 TemplateVariant ExampleListContext::at(uint index) const
6701 {
6702   return p->at(index);
6703 }
6704 
createIterator() const6705 TemplateListIntf::ConstIteratorPtr ExampleListContext::createIterator() const
6706 {
6707   return p->createIterator();
6708 }
6709 
6710 //------------------------------------------------------------------------
6711 
6712 //%% list ModuleList[ModuleNode]: list of directories and/or files
6713 class ModuleListContext::Private : public GenericNodeListContext
6714 {
6715   public:
addModules()6716     void addModules()
6717     {
6718       for (const auto &gd : *Doxygen::groupLinkedMap)
6719       {
6720         if (!gd->isReference())
6721         {
6722           append(ModuleContext::alloc(gd.get()));
6723         }
6724       }
6725     }
6726 };
6727 
ModuleListContext()6728 ModuleListContext::ModuleListContext() : p(std::make_unique<Private>())
6729 {
6730   p->addModules();
6731 }
6732 
~ModuleListContext()6733 ModuleListContext::~ModuleListContext()
6734 {
6735 }
6736 
6737 // TemplateListIntf
count() const6738 uint ModuleListContext::count() const
6739 {
6740   return p->count();
6741 }
6742 
at(uint index) const6743 TemplateVariant ModuleListContext::at(uint index) const
6744 {
6745   return p->at(index);
6746 }
6747 
createIterator() const6748 TemplateListIntf::ConstIteratorPtr ModuleListContext::createIterator() const
6749 {
6750   return p->createIterator();
6751 }
6752 
6753 //------------------------------------------------------------------------
6754 
6755 class ConceptTreeContext::Private
6756 {
6757   public:
Private()6758     Private()
6759     {
6760       m_conceptTree = NestingContext::alloc(0,ContextTreeType::Concept,0);
6761       auto ctx = std::dynamic_pointer_cast<NestingContext>(m_conceptTree);
6762       ClassDefSet visitedClasses;
6763       // Add concepts
6764       ctx->addNamespaces(*Doxygen::namespaceLinkedMap,TRUE,FALSE,TRUE,visitedClasses);
6765       ctx->addConcepts(*Doxygen::conceptLinkedMap,TRUE,visitedClasses);
6766     }
6767 
6768     // TemplateStructIntf methods
get(const QCString & n) const6769     TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
fields() const6770     StringVector fields() const                  { return s_inst.fields(); }
6771 
6772   private:
6773     // Property getters
tree() const6774     TemplateVariant tree() const                 { return TemplateVariant(m_conceptTree); }
fileName() const6775     TemplateVariant fileName() const             { return "concepts"; }
relPath() const6776     TemplateVariant relPath() const              { return ""; }
highlight() const6777     TemplateVariant highlight() const            { return "concepts"; }
subhighlight() const6778     TemplateVariant subhighlight() const         { return ""; }
maxDepth() const6779     TemplateVariant maxDepth() const             { return m_maxDepth.get(this); }
preferredDepth() const6780     TemplateVariant preferredDepth() const       { return m_preferredDepth.get(this); }
title() const6781     TemplateVariant title() const                { return theTranslator->trConcept(true,false); }
6782 
6783   private:
createMaxDepth() const6784     int createMaxDepth() const
6785     {
6786       return computeMaxDepth(m_conceptTree);
6787     }
createPreferredDepth() const6788     int createPreferredDepth() const
6789     {
6790       return computePreferredDepth(m_conceptTree,m_maxDepth.get(this));
6791     }
6792     TemplateListIntfPtr m_conceptTree;
6793     CachedItem<int, Private, &Private::createMaxDepth>       m_maxDepth;
6794     CachedItem<int, Private, &Private::createPreferredDepth> m_preferredDepth;
6795     static const PropertyMap<ConceptTreeContext::Private> s_inst;
6796 };
6797 
6798 //%% struct ConceptTree: tree of modules
6799 //%% {
6800 const PropertyMap<ConceptTreeContext::Private> ConceptTreeContext::Private::s_inst {
6801   {  "tree",          &Private::tree },
6802   {  "fileName",      &Private::fileName },
6803   {  "relPath",       &Private::relPath },
6804   {  "highlight",     &Private::highlight },
6805   {  "subhighlight",  &Private::subhighlight },
6806   {  "title",         &Private::title },
6807   {  "preferredDepth",&Private::preferredDepth },
6808   {  "maxDepth",      &Private::maxDepth }
6809 };
6810 //%% }
6811 
6812 
ConceptTreeContext()6813 ConceptTreeContext::ConceptTreeContext() : p(std::make_unique<Private>())
6814 {
6815 }
6816 
~ConceptTreeContext()6817 ConceptTreeContext::~ConceptTreeContext()
6818 {
6819 }
6820 
get(const QCString & name) const6821 TemplateVariant ConceptTreeContext::get(const QCString &name) const
6822 {
6823   return p->get(name);
6824 }
6825 
fields() const6826 StringVector ConceptTreeContext::fields() const
6827 {
6828   return p->fields();
6829 }
6830 
6831 //------------------------------------------------------------------------
6832 
6833 class ModuleTreeContext::Private
6834 {
6835   public:
Private()6836     Private()
6837     {
6838       m_moduleTree = NestingContext::alloc(0,ContextTreeType::Module,0);
6839       auto ctx = std::dynamic_pointer_cast<NestingContext>(m_moduleTree);
6840       ClassDefSet visitedClasses;
6841       // Add modules
6842       ctx->addModules(*Doxygen::groupLinkedMap,visitedClasses);
6843     }
6844 
6845     // TemplateStructIntf methods
get(const QCString & n) const6846     TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
fields() const6847     StringVector fields() const                  { return s_inst.fields(); }
6848 
6849   private:
6850     // Property getters
tree() const6851     TemplateVariant tree() const                 { return TemplateVariant(m_moduleTree); }
fileName() const6852     TemplateVariant fileName() const             { return "modules"; }
relPath() const6853     TemplateVariant relPath() const              { return ""; }
highlight() const6854     TemplateVariant highlight() const            { return "modules"; }
subhighlight() const6855     TemplateVariant subhighlight() const         { return ""; }
maxDepth() const6856     TemplateVariant maxDepth() const             { return m_maxDepth.get(this); }
preferredDepth() const6857     TemplateVariant preferredDepth() const       { return m_preferredDepth.get(this); }
title() const6858     TemplateVariant title() const                { return theTranslator->trModules(); }
6859   private:
createMaxDepth() const6860     int createMaxDepth() const
6861     {
6862       return computeMaxDepth(m_moduleTree);
6863     }
createPreferredDepth() const6864     int createPreferredDepth() const
6865     {
6866       return computePreferredDepth(m_moduleTree,m_maxDepth.get(this));
6867     }
6868     TemplateListIntfPtr m_moduleTree;
6869     CachedItem<int, Private, &Private::createMaxDepth>       m_maxDepth;
6870     CachedItem<int, Private, &Private::createPreferredDepth> m_preferredDepth;
6871     static const PropertyMap<ModuleTreeContext::Private> s_inst;
6872 };
6873 
6874 //%% struct ModuleTree: tree of modules
6875 //%% {
6876 const PropertyMap<ModuleTreeContext::Private> ModuleTreeContext::Private::s_inst {
6877   {  "tree",          &Private::tree },
6878   {  "fileName",      &Private::fileName },
6879   {  "relPath",       &Private::relPath },
6880   {  "highlight",     &Private::highlight },
6881   {  "subhighlight",  &Private::subhighlight },
6882   {  "title",         &Private::title },
6883   {  "preferredDepth",&Private::preferredDepth },
6884   {  "maxDepth",      &Private::maxDepth }
6885 };
6886 //%% }
6887 
6888 //PropertyMapper<ModuleTreeContext::Private> ModuleTreeContext::Private::s_inst;
6889 
ModuleTreeContext()6890 ModuleTreeContext::ModuleTreeContext() : p(std::make_unique<Private>())
6891 {
6892 }
6893 
~ModuleTreeContext()6894 ModuleTreeContext::~ModuleTreeContext()
6895 {
6896 }
6897 
get(const QCString & name) const6898 TemplateVariant ModuleTreeContext::get(const QCString &name) const
6899 {
6900   return p->get(name);
6901 }
6902 
fields() const6903 StringVector ModuleTreeContext::fields() const
6904 {
6905   return p->fields();
6906 }
6907 
6908 //------------------------------------------------------------------------
6909 
6910 class ExampleTreeContext::Private
6911 {
6912   public:
Private()6913     Private()
6914     {
6915       m_exampleTree = NestingContext::alloc(0,ContextTreeType::Example,0);
6916       auto ctx = std::dynamic_pointer_cast<NestingContext>(m_exampleTree);
6917       ClassDefSet visitedClasses;
6918       // Add pages
6919       ctx->addPages(*Doxygen::exampleLinkedMap,TRUE,visitedClasses);
6920     }
6921 
6922     // TemplateStructIntf methods
get(const QCString & n) const6923     TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
fields() const6924     StringVector fields() const                  { return s_inst.fields(); }
6925 
6926   private:
6927     // Property getters
tree() const6928     TemplateVariant tree() const                 { return TemplateVariant(m_exampleTree); }
fileName() const6929     TemplateVariant fileName() const             { return "examples"; }
relPath() const6930     TemplateVariant relPath() const              { return ""; }
highlight() const6931     TemplateVariant highlight() const            { return "examples"; }
subhighlight() const6932     TemplateVariant subhighlight() const         { return ""; }
maxDepth() const6933     TemplateVariant maxDepth() const             { return m_maxDepth.get(this); }
preferredDepth() const6934     TemplateVariant preferredDepth() const       { return m_preferredDepth.get(this); }
title() const6935     TemplateVariant title() const                { return theTranslator->trExamples(); }
6936 
6937   private:
createMaxDepth() const6938     int createMaxDepth() const
6939     {
6940       return computeMaxDepth(m_exampleTree);
6941     }
createPreferredDepth() const6942     int createPreferredDepth() const
6943     {
6944       return computePreferredDepth(m_exampleTree,m_maxDepth.get(this));
6945     }
6946     TemplateListIntfPtr m_exampleTree;
6947     CachedItem<int, Private, &Private::createMaxDepth>       m_maxDepth;
6948     CachedItem<int, Private, &Private::createPreferredDepth> m_preferredDepth;
6949     static const PropertyMap<ExampleTreeContext::Private> s_inst;
6950 };
6951 
6952 //%% struct ExampleTree: tree of examples page
6953 //%% {
6954 const PropertyMap<ExampleTreeContext::Private> ExampleTreeContext::Private::s_inst {
6955   {  "tree",          &Private::tree },
6956   {  "fileName",      &Private::fileName },
6957   {  "relPath",       &Private::relPath },
6958   {  "highlight",     &Private::highlight },
6959   {  "subhighlight",  &Private::subhighlight },
6960   {  "title",         &Private::title },
6961   {  "preferredDepth",&Private::preferredDepth },
6962   {  "maxDepth",      &Private::maxDepth }
6963 };
6964 //%% }
6965 
6966 
ExampleTreeContext()6967 ExampleTreeContext::ExampleTreeContext() : p(std::make_unique<Private>())
6968 {
6969 }
6970 
~ExampleTreeContext()6971 ExampleTreeContext::~ExampleTreeContext()
6972 {
6973 }
6974 
get(const QCString & name) const6975 TemplateVariant ExampleTreeContext::get(const QCString &name) const
6976 {
6977   return p->get(name);
6978 }
6979 
fields() const6980 StringVector ExampleTreeContext::fields() const
6981 {
6982   return p->fields();
6983 }
6984 
6985 
6986 //------------------------------------------------------------------------
6987 
6988 class NavPathElemContext::Private
6989 {
6990   public:
Private(const Definition * def)6991     Private(const Definition *def) : m_def(def) {}
6992 
6993     // TemplateStructIntf methods
get(const QCString & n) const6994     TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
fields() const6995     StringVector fields() const                  { return s_inst.fields(); }
6996 
6997   private:
6998     // Property getters
isLinkable() const6999     TemplateVariant isLinkable() const           { return m_def->isLinkable(); }
anchor() const7000     TemplateVariant anchor() const               { return m_def->anchor(); }
fileName() const7001     TemplateVariant fileName() const             { return m_def->getOutputFileBase(); }
isReference() const7002     TemplateVariant isReference() const          { return m_def->isReference(); }
externalReference() const7003     TemplateVariant externalReference() const    { return m_def->externalReference(relPathAsString()); }
text() const7004     TemplateVariant text() const
7005     {
7006       Definition::DefType type = m_def->definitionType();
7007       QCString text = m_def->localName();
7008       if (type==Definition::TypeGroup)
7009       {
7010         text = (toGroupDef(m_def))->groupTitle();
7011       }
7012       else if (type==Definition::TypePage && ((toPageDef(m_def))->hasTitle()))
7013       {
7014         text = (toPageDef(m_def))->title();
7015       }
7016       else if (type==Definition::TypeClass)
7017       {
7018         if (text.right(2)=="-p")
7019         {
7020           text = text.left(text.length()-2);
7021         }
7022       }
7023       return text;
7024     }
relPathAsString() const7025     QCString relPathAsString() const
7026     {
7027       static bool createSubdirs = Config_getBool(CREATE_SUBDIRS);
7028       return createSubdirs ? QCString("../../") : QCString("");
7029     }
7030   private:
7031     const Definition *m_def;
7032     static const PropertyMap<NavPathElemContext::Private> s_inst;
7033 };
7034 
7035 //%% struct NavPathElem: list of examples page
7036 //%% {
7037 const PropertyMap<NavPathElemContext::Private> NavPathElemContext::Private::s_inst {
7038   {  "isLinkable",       &Private::isLinkable },
7039   {  "fileName",         &Private::fileName },
7040   {  "anchor",           &Private::anchor },
7041   {  "text",             &Private::text },
7042   {  "isReference",      &Private::isReference },
7043   {  "externalReference",&Private::externalReference }
7044 };
7045 //%% }
7046 
7047 
NavPathElemContext(const Definition * def)7048 NavPathElemContext::NavPathElemContext(const Definition *def) : p(std::make_unique<Private>(def))
7049 {
7050 }
7051 
~NavPathElemContext()7052 NavPathElemContext::~NavPathElemContext()
7053 {
7054 }
7055 
get(const QCString & name) const7056 TemplateVariant NavPathElemContext::get(const QCString &name) const
7057 {
7058   return p->get(name);
7059 }
7060 
fields() const7061 StringVector NavPathElemContext::fields() const
7062 {
7063   return p->fields();
7064 }
7065 
7066 //------------------------------------------------------------------------
7067 
7068 class GlobalsIndexContext::Private
7069 {
7070   public:
7071     // TemplateStructIntf methods
get(const QCString & n) const7072     TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
fields() const7073     StringVector fields() const                  { return s_inst.fields(); }
7074 
7075   private:
7076     // Property getters
all() const7077     TemplateVariant all() const                  { return m_all.get(this); }
functions() const7078     TemplateVariant functions() const            { return m_functions.get(this); }
variables() const7079     TemplateVariant variables() const            { return m_variables.get(this); }
typedefs() const7080     TemplateVariant typedefs() const             { return m_typedefs.get(this); }
enums() const7081     TemplateVariant enums() const                { return m_enums.get(this); }
enumValues() const7082     TemplateVariant enumValues() const           { return m_enumValues.get(this); }
macros() const7083     TemplateVariant macros() const               { return m_macros.get(this); }
properties() const7084     TemplateVariant properties() const           { return FALSE; }
events() const7085     TemplateVariant events() const               { return FALSE; }
related() const7086     TemplateVariant related() const              { return FALSE; }
fileName() const7087     TemplateVariant fileName() const             { return "globals"; }
relPath() const7088     TemplateVariant relPath() const              { return ""; }
highlight() const7089     TemplateVariant highlight() const            { return "files"; }
subhighlight() const7090     TemplateVariant subhighlight() const         { return "filemembers"; }
title() const7091     TemplateVariant title() const                { return theTranslator->trFileMembers(); }
7092 
7093   private:
7094     using MemberFilter = bool (MemberDef::*)() const;
createMembersFiltered(MemberFilter filter) const7095     TemplateVariant createMembersFiltered(MemberFilter filter) const
7096     {
7097       TemplateVariantList list;
7098       for (const auto &mn : *Doxygen::functionNameLinkedMap)
7099       {
7100         for (const auto &md : *mn)
7101         {
7102           const FileDef *fd=md->getFileDef();
7103           if (fd && fd->isLinkableInProject() &&
7104               !md->name().isEmpty() && !md->getNamespaceDef() && md->isLinkableInProject())
7105           {
7106             if (filter==0 || (md.get()->*filter)())
7107             {
7108               list.push_back(MemberContext::alloc(md.get()));
7109             }
7110           }
7111         }
7112       }
7113       return TemplateImmutableList::alloc(list);
7114     }
createAll() const7115     TemplateVariant createAll() const        { return createMembersFiltered(0); }
createFunctions() const7116     TemplateVariant createFunctions() const  { return createMembersFiltered(&MemberDef::isFunction); }
createVariables() const7117     TemplateVariant createVariables() const  { return createMembersFiltered(&MemberDef::isVariable); }
createTypedefs() const7118     TemplateVariant createTypedefs() const   { return createMembersFiltered(&MemberDef::isTypedef); }
createEnums() const7119     TemplateVariant createEnums() const      { return createMembersFiltered(&MemberDef::isEnumerate); }
createEnumValues() const7120     TemplateVariant createEnumValues() const { return createMembersFiltered(&MemberDef::isEnumValue); }
createMacros() const7121     TemplateVariant createMacros() const     { return createMembersFiltered(&MemberDef::isDefine); }
7122 
7123     CachedItem<TemplateVariant,  Private, &Private::createAll>        m_all;
7124     CachedItem<TemplateVariant,  Private, &Private::createFunctions>  m_functions;
7125     CachedItem<TemplateVariant,  Private, &Private::createVariables>  m_variables;
7126     CachedItem<TemplateVariant,  Private, &Private::createTypedefs>   m_typedefs;
7127     CachedItem<TemplateVariant,  Private, &Private::createEnums>      m_enums;
7128     CachedItem<TemplateVariant,  Private, &Private::createEnumValues> m_enumValues;
7129     CachedItem<TemplateVariant,  Private, &Private::createMacros>     m_macros;
7130     static const PropertyMap<GlobalsIndexContext::Private> s_inst;
7131 };
7132 
7133 //%% struct GlobalsIndex: list of examples page
7134 //%% {
7135 const PropertyMap<GlobalsIndexContext::Private> GlobalsIndexContext::Private::s_inst {
7136   {  "all",         &Private::all },
7137   {  "functions",   &Private::functions },
7138   {  "variables",   &Private::variables },
7139   {  "typedefs",    &Private::typedefs },
7140   {  "enums",       &Private::enums },
7141   {  "enumValues",  &Private::enumValues },
7142   {  "macros",      &Private::macros },
7143   {  "properties",  &Private::properties },
7144   {  "events",      &Private::events },
7145   {  "related",     &Private::related },
7146   {  "fileName",    &Private::fileName },
7147   {  "relPath",     &Private::relPath },
7148   {  "highlight",   &Private::highlight },
7149   {  "subhighlight",&Private::subhighlight },
7150   {  "title",       &Private::title }
7151 };
7152 //%% }
7153 
GlobalsIndexContext()7154 GlobalsIndexContext::GlobalsIndexContext() : p(std::make_unique<Private>())
7155 {
7156 }
7157 
~GlobalsIndexContext()7158 GlobalsIndexContext::~GlobalsIndexContext()
7159 {
7160 }
7161 
get(const QCString & name) const7162 TemplateVariant GlobalsIndexContext::get(const QCString &name) const
7163 {
7164   return p->get(name);
7165 }
7166 
fields() const7167 StringVector GlobalsIndexContext::fields() const
7168 {
7169   return p->fields();
7170 }
7171 
7172 
7173 //------------------------------------------------------------------------
7174 
7175 class ClassMembersIndexContext::Private
7176 {
7177   public:
7178     // TemplateStructIntf methods
get(const QCString & n) const7179     TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
fields() const7180     StringVector fields() const                  { return s_inst.fields(); }
7181 
7182   private:
7183     // Property getters
all() const7184     TemplateVariant all() const                  { return m_all.get(this); }
functions() const7185     TemplateVariant functions() const            { return m_functions.get(this); }
variables() const7186     TemplateVariant variables() const            { return m_variables.get(this); }
typedefs() const7187     TemplateVariant typedefs() const             { return m_typedefs.get(this); }
enums() const7188     TemplateVariant enums() const                { return m_enums.get(this); }
enumValues() const7189     TemplateVariant enumValues() const           { return m_enumValues.get(this); }
macros() const7190     TemplateVariant macros() const               { return FALSE; }
properties() const7191     TemplateVariant properties() const           { return m_properties.get(this); }
events() const7192     TemplateVariant events() const               { return m_events.get(this); }
related() const7193     TemplateVariant related() const              { return m_related.get(this); }
fileName() const7194     TemplateVariant fileName() const             { return "functions"; }
relPath() const7195     TemplateVariant relPath() const              { return ""; }
highlight() const7196     TemplateVariant highlight() const            { return "classes"; }
subhighlight() const7197     TemplateVariant subhighlight() const         { return "classmembers"; }
title() const7198     TemplateVariant title() const                { return theTranslator->trCompoundMembers(); }
7199 
7200   private:
7201     using MemberFilter = bool (MemberDef::*)() const;
createMembersFiltered(MemberFilter filter) const7202     TemplateVariant createMembersFiltered(MemberFilter filter) const
7203     {
7204       TemplateVariantList list;
7205       for (const auto &mn : *Doxygen::memberNameLinkedMap)
7206       {
7207         for (const auto &md : *mn)
7208         {
7209           const ClassDef *cd = md->getClassDef();
7210           if (cd && cd->isLinkableInProject() && cd->templateMaster()==0 &&
7211               md->isLinkableInProject() && !md->name().isEmpty())
7212           {
7213             if (filter==0 || (md.get()->*filter)())
7214             {
7215               list.push_back(MemberContext::alloc(md.get()));
7216             }
7217           }
7218         }
7219       }
7220       return TemplateImmutableList::alloc(list);
7221     }
createAll() const7222     TemplateVariant createAll() const        { return createMembersFiltered(&MemberDef::isNotFriend); }
createFunctions() const7223     TemplateVariant createFunctions() const  { return createMembersFiltered(&MemberDef::isFunctionOrSignalSlot); }
createVariables() const7224     TemplateVariant createVariables() const  { return createMembersFiltered(&MemberDef::isVariable); }
createTypedefs() const7225     TemplateVariant createTypedefs() const   { return createMembersFiltered(&MemberDef::isTypedef); }
createEnums() const7226     TemplateVariant createEnums() const      { return createMembersFiltered(&MemberDef::isEnumerate); }
createEnumValues() const7227     TemplateVariant createEnumValues() const { return createMembersFiltered(&MemberDef::isEnumValue); }
createProperties() const7228     TemplateVariant createProperties() const { return createMembersFiltered(&MemberDef::isProperty); }
createEvents() const7229     TemplateVariant createEvents() const     { return createMembersFiltered(&MemberDef::isEvent); }
createRelated() const7230     TemplateVariant createRelated() const    { return createMembersFiltered(&MemberDef::isRelated); }
7231 
7232     CachedItem<TemplateVariant,  Private, &Private::createAll>        m_all;
7233     CachedItem<TemplateVariant,  Private, &Private::createFunctions>  m_functions;
7234     CachedItem<TemplateVariant,  Private, &Private::createVariables>  m_variables;
7235     CachedItem<TemplateVariant,  Private, &Private::createTypedefs>   m_typedefs;
7236     CachedItem<TemplateVariant,  Private, &Private::createEnums>      m_enums;
7237     CachedItem<TemplateVariant,  Private, &Private::createEnumValues> m_enumValues;
7238     CachedItem<TemplateVariant,  Private, &Private::createProperties> m_properties;
7239     CachedItem<TemplateVariant,  Private, &Private::createEvents>     m_events;
7240     CachedItem<TemplateVariant,  Private, &Private::createRelated>    m_related;
7241     static const PropertyMap<ClassMembersIndexContext::Private> s_inst;
7242 };
7243 
7244 //%% struct ClassMembersIndex: list of examples page
7245 //%% {
7246 const PropertyMap<ClassMembersIndexContext::Private> ClassMembersIndexContext::Private::s_inst {
7247   {  "all",         &Private::all },
7248   {  "functions",   &Private::functions },
7249   {  "variables",   &Private::variables },
7250   {  "typedefs",    &Private::typedefs },
7251   {  "enums",       &Private::enums },
7252   {  "enumValues",  &Private::enumValues },
7253   {  "macros",      &Private::macros },
7254   {  "properties",  &Private::properties },
7255   {  "events",      &Private::events },
7256   {  "related",     &Private::related },
7257   {  "fileName",    &Private::fileName },
7258   {  "relPath",     &Private::relPath },
7259   {  "highlight",   &Private::highlight },
7260   {  "subhighlight",&Private::subhighlight },
7261   {  "title",       &Private::title }
7262 };
7263 //%% }
7264 
7265 
ClassMembersIndexContext()7266 ClassMembersIndexContext::ClassMembersIndexContext() : p(std::make_unique<Private>())
7267 {
7268 }
7269 
~ClassMembersIndexContext()7270 ClassMembersIndexContext::~ClassMembersIndexContext()
7271 {
7272 }
7273 
get(const QCString & name) const7274 TemplateVariant ClassMembersIndexContext::get(const QCString &name) const
7275 {
7276   return p->get(name);
7277 }
7278 
fields() const7279 StringVector ClassMembersIndexContext::fields() const
7280 {
7281   return p->fields();
7282 }
7283 
7284 //------------------------------------------------------------------------
7285 
7286 class NamespaceMembersIndexContext::Private
7287 {
7288   public:
7289     // TemplateStructIntf methods
get(const QCString & n) const7290     TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
fields() const7291     StringVector fields() const                  { return s_inst.fields(); }
7292 
7293   private:
7294     // Property getters
all() const7295     TemplateVariant all() const                  { return m_all.get(this); }
functions() const7296     TemplateVariant functions() const            { return m_functions.get(this); }
variables() const7297     TemplateVariant variables() const            { return m_variables.get(this); }
typedefs() const7298     TemplateVariant typedefs() const             { return m_typedefs.get(this); }
enums() const7299     TemplateVariant enums() const                { return m_enums.get(this); }
enumValues() const7300     TemplateVariant enumValues() const           { return m_enumValues.get(this); }
macros() const7301     TemplateVariant macros() const               { return FALSE; }
properties() const7302     TemplateVariant properties() const           { return FALSE; }
events() const7303     TemplateVariant events() const               { return FALSE; }
related() const7304     TemplateVariant related() const              { return FALSE; }
fileName() const7305     TemplateVariant fileName() const             { return "namespacemembers"; }
relPath() const7306     TemplateVariant relPath() const              { return ""; }
highlight() const7307     TemplateVariant highlight() const            { return "namespaces"; }
subhighlight() const7308     TemplateVariant subhighlight() const         { return "namespacemembers"; }
title() const7309     TemplateVariant title() const                { return theTranslator->trNamespaceMembers(); }
7310 
7311   private:
7312     using MemberFilter = bool (MemberDef::*)() const;
createMembersFiltered(MemberFilter filter) const7313     TemplateVariant createMembersFiltered(MemberFilter filter) const
7314     {
7315       TemplateVariantList list;
7316       for (const auto &mn : *Doxygen::functionNameLinkedMap)
7317       {
7318         for (const auto &md : *mn)
7319         {
7320           const NamespaceDef *nd=md->getNamespaceDef();
7321           if (nd && nd->isLinkableInProject() &&
7322               !md->name().isEmpty() && md->isLinkableInProject())
7323           {
7324             if (filter==0 || (md.get()->*filter)())
7325             {
7326               list.push_back(MemberContext::alloc(md.get()));
7327             }
7328           }
7329         }
7330       }
7331       return TemplateImmutableList::alloc(list);
7332     }
7333 
createAll() const7334     TemplateVariant createAll() const        { return createMembersFiltered(0); }
createFunctions() const7335     TemplateVariant createFunctions() const  { return createMembersFiltered(&MemberDef::isFunction); }
createVariables() const7336     TemplateVariant createVariables() const  { return createMembersFiltered(&MemberDef::isVariable); }
createTypedefs() const7337     TemplateVariant createTypedefs() const   { return createMembersFiltered(&MemberDef::isTypedef); }
createEnums() const7338     TemplateVariant createEnums() const      { return createMembersFiltered(&MemberDef::isEnumerate); }
createEnumValues() const7339     TemplateVariant createEnumValues() const { return createMembersFiltered(&MemberDef::isEnumValue); }
7340 
7341     CachedItem<TemplateVariant,  Private, &Private::createAll>        m_all;
7342     CachedItem<TemplateVariant,  Private, &Private::createFunctions>  m_functions;
7343     CachedItem<TemplateVariant,  Private, &Private::createVariables>  m_variables;
7344     CachedItem<TemplateVariant,  Private, &Private::createTypedefs>   m_typedefs;
7345     CachedItem<TemplateVariant,  Private, &Private::createEnums>      m_enums;
7346     CachedItem<TemplateVariant,  Private, &Private::createEnumValues> m_enumValues;
7347     static const PropertyMap<NamespaceMembersIndexContext::Private> s_inst;
7348 };
7349 
7350 //%% struct NamespaceMembersIndex: list of examples page
7351 //%% {
7352 const PropertyMap<NamespaceMembersIndexContext::Private> NamespaceMembersIndexContext::Private::s_inst {
7353   {  "all",         &Private::all },
7354   {  "functions",   &Private::functions },
7355   {  "variables",   &Private::variables },
7356   {  "typedefs",    &Private::typedefs },
7357   {  "enums",       &Private::enums },
7358   {  "enumValues",  &Private::enumValues },
7359   {  "macros",      &Private::macros },
7360   {  "properties",  &Private::properties },
7361   {  "events",      &Private::events },
7362   {  "related",     &Private::related },
7363   {  "fileName",    &Private::fileName },
7364   {  "relPath",     &Private::relPath },
7365   {  "highlight",   &Private::highlight },
7366   {  "subhighlight",&Private::subhighlight },
7367   {  "title",       &Private::title }
7368 };
7369 //%% }
7370 
7371 
NamespaceMembersIndexContext()7372 NamespaceMembersIndexContext::NamespaceMembersIndexContext() : p(std::make_unique<Private>())
7373 {
7374 }
7375 
~NamespaceMembersIndexContext()7376 NamespaceMembersIndexContext::~NamespaceMembersIndexContext()
7377 {
7378 }
7379 
get(const QCString & name) const7380 TemplateVariant NamespaceMembersIndexContext::get(const QCString &name) const
7381 {
7382   return p->get(name);
7383 }
7384 
fields() const7385 StringVector NamespaceMembersIndexContext::fields() const
7386 {
7387   return p->fields();
7388 }
7389 
7390 //------------------------------------------------------------------------
7391 
7392 class InheritanceGraphContext::Private
7393 {
7394   public:
Private(DotGfxHierarchyTablePtr hierarchy,DotNode * n,int id)7395     Private(DotGfxHierarchyTablePtr hierarchy,DotNode *n,int id)
7396       : m_hierarchy(hierarchy), m_node(n), m_id(id) { }
7397 
7398     // TemplateStructIntf methods
get(const QCString & n) const7399     TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
fields() const7400     StringVector fields() const                  { return s_inst.fields(); }
7401 
7402   private:
7403     // Property getters
graph() const7404     TemplateVariant graph() const                { return m_graph.get(this); }
7405 
7406   private:
createGraph() const7407     TemplateVariant createGraph() const
7408     {
7409       TextStream t;
7410       static bool haveDot            = Config_getBool(HAVE_DOT);
7411       static bool graphicalHierarchy = Config_getBool(GRAPHICAL_HIERARCHY);
7412       if (haveDot && graphicalHierarchy)
7413       {
7414         m_hierarchy->createGraph(m_node,t,
7415                           /*GOF_BITMAP,
7416                           EOF_Html,*/
7417                           g_globals.outputDir,
7418                           g_globals.outputDir+Portable::pathSeparator()+"inherits"+Doxygen::htmlFileExtension,
7419                           m_id);
7420       }
7421       return TemplateVariant(t.str().c_str(),TRUE);
7422     }
7423     DotGfxHierarchyTablePtr m_hierarchy;
7424     DotNode *m_node;
7425     CachedItem<TemplateVariant,Private,&Private::createGraph> m_graph;
7426     int m_id;
7427     static const PropertyMap<InheritanceGraphContext::Private> s_inst;
7428 };
7429 
7430 //%% struct InheritanceGraph: a connected graph representing part of the overall inheritance tree
7431 //%% {
7432 const PropertyMap<InheritanceGraphContext::Private> InheritanceGraphContext::Private::s_inst {
7433   {  "graph",&Private::graph }
7434 };
7435 //%% }
7436 
InheritanceGraphContext(DotGfxHierarchyTablePtr hierarchy,DotNode * n,int id)7437 InheritanceGraphContext::InheritanceGraphContext(DotGfxHierarchyTablePtr hierarchy,DotNode *n,int id) : p(std::make_unique<Private>(hierarchy,n,id))
7438 {
7439 }
7440 
~InheritanceGraphContext()7441 InheritanceGraphContext::~InheritanceGraphContext()
7442 {
7443 }
7444 
get(const QCString & name) const7445 TemplateVariant InheritanceGraphContext::get(const QCString &name) const
7446 {
7447   return p->get(name);
7448 }
7449 
fields() const7450 StringVector InheritanceGraphContext::fields() const
7451 {
7452   return p->fields();
7453 }
7454 
7455 //------------------------------------------------------------------------
7456 
7457 class InheritanceNodeContext::Private
7458 {
7459   public:
Private(const ClassDef * cd,const QCString & name)7460     Private(const ClassDef *cd,const QCString &name)
7461       : m_classDef(cd), m_name(name) {}
7462 
7463     // TemplateStructIntf methods
get(const QCString & n) const7464     TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
fields() const7465     StringVector fields() const                  { return s_inst.fields(); }
7466 
7467   private:
7468     // Property getters
getClass() const7469     TemplateVariant getClass() const             { return m_classContext.get(this); }
name() const7470     TemplateVariant name() const                 { return m_name; }
7471 
7472   private:
createClass() const7473     TemplateVariant createClass() const
7474     {
7475       return ClassContext::alloc(m_classDef);
7476     }
7477     const ClassDef *m_classDef;
7478     CachedItem<TemplateVariant, Private, &Private::createClass> m_classContext;
7479     QCString m_name;
7480     static const PropertyMap<InheritanceNodeContext::Private> s_inst;
7481 };
7482 
7483 //%% struct InheritanceNode: a class in the inheritance list
7484 //%% {
7485 const PropertyMap<InheritanceNodeContext::Private> InheritanceNodeContext::Private::s_inst {
7486   {  "class",&Private::getClass },
7487   {  "name", &Private::name }
7488 };
7489 //%% }
7490 
InheritanceNodeContext(const ClassDef * cd,const QCString & name)7491 InheritanceNodeContext::InheritanceNodeContext(const ClassDef *cd,const QCString &name) : p(std::make_unique<Private>(cd,name))
7492 {
7493 }
7494 
~InheritanceNodeContext()7495 InheritanceNodeContext::~InheritanceNodeContext()
7496 {
7497 }
7498 
get(const QCString & name) const7499 TemplateVariant InheritanceNodeContext::get(const QCString &name) const
7500 {
7501   return p->get(name);
7502 }
7503 
fields() const7504 StringVector InheritanceNodeContext::fields() const
7505 {
7506   return p->fields();
7507 }
7508 
7509 //------------------------------------------------------------------------
7510 
7511 //%% list InheritanceList[InheritanceNode] : list of inherited classes
7512 class InheritanceListContext::Private : public GenericNodeListContext
7513 {
7514   public:
addClass(const ClassDef * cd,const QCString & name)7515     void addClass(const ClassDef *cd,const QCString &name)
7516     {
7517       append(InheritanceNodeContext::alloc(cd,name));
7518     }
7519 };
7520 
InheritanceListContext(const BaseClassList & list,bool baseClasses)7521 InheritanceListContext::InheritanceListContext(const BaseClassList &list, bool baseClasses) : p(std::make_unique<Private>())
7522 {
7523   for (const auto &bcd : list)
7524   {
7525     const ClassDef *cd=bcd.classDef;
7526     QCString name;
7527     if (baseClasses)
7528     {
7529       name = insertTemplateSpecifierInScope(
7530           cd->displayName(),bcd.templSpecifiers);
7531     }
7532     else
7533     {
7534       name = cd->displayName();
7535     }
7536     //printf("InheritanceListContext: adding %s baseClass=%d\n",qPrint(name),baseClasses);
7537     p->addClass(cd,name);
7538   }
7539 }
7540 
~InheritanceListContext()7541 InheritanceListContext::~InheritanceListContext()
7542 {
7543 }
7544 
7545 // TemplateListIntf
count() const7546 uint InheritanceListContext::count() const
7547 {
7548   return p->count();
7549 }
7550 
at(uint index) const7551 TemplateVariant InheritanceListContext::at(uint index) const
7552 {
7553   return p->at(index);
7554 }
7555 
createIterator() const7556 TemplateListIntf::ConstIteratorPtr InheritanceListContext::createIterator() const
7557 {
7558   return p->createIterator();
7559 }
7560 
7561 //------------------------------------------------------------------------
7562 
7563 //%% list MemberList[Member] : list of inherited classes
7564 class MemberListContext::Private : public GenericNodeListContext
7565 {
7566   public:
addMember(const MemberDef * md)7567     void addMember(const MemberDef *md)
7568     {
7569       append(MemberContext::alloc(md));
7570     }
7571 };
7572 
MemberListContext()7573 MemberListContext::MemberListContext() : p(std::make_unique<Private>())
7574 {
7575 }
7576 
MemberListContext(const MemberList * list)7577 MemberListContext::MemberListContext(const MemberList *list) : p(std::make_unique<Private>())
7578 {
7579   if (list)
7580   {
7581     bool details = list->listType()&MemberListType_detailedLists;
7582     for (const auto &md : *list)
7583     {
7584       if ((md->isBriefSectionVisible() && !details) ||
7585           (md->hasDetailedDescription() && details)
7586          )
7587       {
7588         p->addMember(md);
7589       }
7590     }
7591   }
7592 }
7593 
MemberListContext(const MemberVector & ml)7594 MemberListContext::MemberListContext(const MemberVector &ml) : p(std::make_unique<Private>())
7595 {
7596   for (const auto &md : ml)
7597   {
7598     p->addMember(md);
7599   }
7600 }
7601 
~MemberListContext()7602 MemberListContext::~MemberListContext()
7603 {
7604 }
7605 
7606 // TemplateListIntf
count() const7607 uint MemberListContext::count() const
7608 {
7609   return p->count();
7610 }
7611 
at(uint index) const7612 TemplateVariant MemberListContext::at(uint index) const
7613 {
7614   return p->at(index);
7615 }
7616 
createIterator() const7617 TemplateListIntf::ConstIteratorPtr MemberListContext::createIterator() const
7618 {
7619   return p->createIterator();
7620 }
7621 
7622 //------------------------------------------------------------------------
7623 
7624 class MemberInfoContext::Private
7625 {
7626   public:
Private(const MemberInfo * mi)7627     Private(const MemberInfo *mi) : m_memberInfo(mi) {}
7628 
7629     // TemplateStructIntf methods
get(const QCString & n) const7630     TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
fields() const7631     StringVector fields() const                  { return s_inst.fields(); }
7632 
7633   private:
7634     // Property getters
protection() const7635     TemplateVariant protection() const
7636     {
7637       switch (m_memberInfo->prot())
7638       {
7639         case ::Public:    return "public";
7640         case ::Protected: return "protected";
7641         case ::Private:   return "private";
7642         case ::Package:   return "package";
7643       }
7644       return "";
7645     }
virtualness() const7646     TemplateVariant virtualness() const
7647     {
7648       switch (m_memberInfo->virt())
7649       {
7650         case ::Normal:   return "normal";
7651         case ::Virtual:  return "virtual";
7652         case ::Pure:     return "pure";
7653       }
7654       return "";
7655     }
ambiguityScope() const7656     TemplateVariant ambiguityScope() const
7657     {
7658       return m_memberInfo->ambiguityResolutionScope();
7659     }
member() const7660     TemplateVariant member() const
7661     {
7662       return m_member.get(this);
7663     }
7664 
7665   private:
createMember() const7666     TemplateVariant createMember() const
7667     {
7668       return m_memberInfo->memberDef() ?
7669         TemplateVariant(MemberContext::alloc(m_memberInfo->memberDef())) :
7670         TemplateVariant(false);
7671     }
7672     const MemberInfo *m_memberInfo;
7673     CachedItem<TemplateVariant, Private, &Private::createMember> m_member;
7674     static const PropertyMap<MemberInfoContext::Private> s_inst;
7675 };
7676 
7677 //%% struct MemberInfo: member information
7678 //%% {
7679 const PropertyMap<MemberInfoContext::Private> MemberInfoContext::Private::s_inst {
7680   //%% string protection
7681   {  "protection",    &Private::protection },
7682   //%% string virtualness
7683   {  "virtualness",   &Private::virtualness },
7684   //%% string ambiguityScope
7685   {  "ambiguityScope",&Private::ambiguityScope },
7686   //%% Member member
7687   {  "member",        &Private::member }
7688 };
7689 //%% }
7690 
MemberInfoContext(const MemberInfo * mi)7691 MemberInfoContext::MemberInfoContext(const MemberInfo *mi) : p(std::make_unique<Private>(mi))
7692 {
7693 }
7694 
~MemberInfoContext()7695 MemberInfoContext::~MemberInfoContext()
7696 {
7697 }
7698 
get(const QCString & name) const7699 TemplateVariant MemberInfoContext::get(const QCString &name) const
7700 {
7701   return p->get(name);
7702 }
7703 
fields() const7704 StringVector MemberInfoContext::fields() const
7705 {
7706   return p->fields();
7707 }
7708 
7709 //------------------------------------------------------------------------
7710 
7711 //%% list AllMembersList[MemberList] : list of inherited classes
7712 class AllMembersListContext::Private : public GenericNodeListContext
7713 {
7714   public:
Private(const MemberNameInfoLinkedMap & ml)7715     Private(const MemberNameInfoLinkedMap &ml)
7716     {
7717       static bool hideUndocMembers = Config_getBool(HIDE_UNDOC_MEMBERS);
7718       for (auto &mni : ml)
7719       {
7720         for (auto &mi : *mni)
7721         {
7722           const MemberDef *md=mi->memberDef();
7723           const ClassDef  *cd=md->getClassDef();
7724           if (cd && !md->isAnonymous())
7725           {
7726             if ((cd->isLinkable() && md->isLinkable()) ||
7727                 (!cd->isArtificial() && !hideUndocMembers &&
7728                  (protectionLevelVisible(md->protection()) || md->isFriend())
7729                 )
7730                )
7731             {
7732               append(MemberInfoContext::alloc(mi.get()));
7733             }
7734           }
7735         }
7736       }
7737     }
7738 };
7739 
AllMembersListContext(const MemberNameInfoLinkedMap & ml)7740 AllMembersListContext::AllMembersListContext(const MemberNameInfoLinkedMap &ml) : p(std::make_unique<Private>(ml))
7741 {
7742 }
7743 
~AllMembersListContext()7744 AllMembersListContext::~AllMembersListContext()
7745 {
7746 }
7747 
7748 // TemplateListIntf
count() const7749 uint AllMembersListContext::count() const
7750 {
7751   return p->count();
7752 }
7753 
at(uint index) const7754 TemplateVariant AllMembersListContext::at(uint index) const
7755 {
7756   return p->at(index);
7757 }
7758 
createIterator() const7759 TemplateListIntf::ConstIteratorPtr AllMembersListContext::createIterator() const
7760 {
7761   return p->createIterator();
7762 }
7763 
7764 //------------------------------------------------------------------------
7765 
7766 class MemberGroupInfoContext::Private
7767 {
7768   public:
Private(const Definition * def,const QCString & relPath,const MemberGroup * mg)7769     Private(const Definition *def,const QCString &relPath,const MemberGroup *mg)
7770       : m_def(def), m_relPath(relPath), m_memberGroup(mg) {}
7771 
7772     // TemplateStructIntf methods
get(const QCString & n) const7773     TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
fields() const7774     StringVector fields() const                  { return s_inst.fields(); }
7775 
7776   private:
7777     // Property getters
members() const7778     TemplateVariant members() const              { return m_members.get(this); }
groupTitle() const7779     TemplateVariant groupTitle() const           { return m_memberGroup->header(); }
groupSubtitle() const7780     TemplateVariant groupSubtitle() const        { return ""; }
groupAnchor() const7781     TemplateVariant groupAnchor() const          { return m_memberGroup->anchor(); }
memberGroups() const7782     TemplateVariant memberGroups() const         { return m_memberGroups.get(this); }
docs() const7783     TemplateVariant docs() const                 { return m_docs.get(this); }
inherited() const7784     TemplateVariant inherited() const            { return FALSE; }
7785 
7786   private:
createMembers() const7787     TemplateVariant createMembers() const
7788     {
7789       return MemberListContext::alloc(&m_memberGroup->members());
7790     }
createMemberGroups() const7791     TemplateVariant createMemberGroups() const
7792     {
7793       return MemberGroupListContext::alloc();
7794     }
createDocs() const7795     TemplateVariant createDocs() const
7796     {
7797       return !m_memberGroup->documentation().isEmpty() ?
7798           TemplateVariant(parseDoc(m_def,"[@name docs]",-1, // TODO store file & line
7799                                    m_relPath,
7800                                    m_memberGroup->documentation(),FALSE)) :
7801           TemplateVariant("");
7802     }
7803     const Definition *m_def;
7804     QCString m_relPath;
7805     const MemberGroup *m_memberGroup;
7806     CachedItem<TemplateVariant,Private,&Private::createDocs>         m_docs;
7807     CachedItem<TemplateVariant,Private,&Private::createMembers>      m_members;
7808     CachedItem<TemplateVariant,Private,&Private::createMemberGroups> m_memberGroups;
7809     static const PropertyMap<MemberGroupInfoContext::Private> s_inst;
7810 };
7811 
7812 //%% struct MemberGroupInfo: member group information
7813 //%% {
7814 const PropertyMap<MemberGroupInfoContext::Private> MemberGroupInfoContext::Private::s_inst {
7815   {  "members",      &Private::members },
7816   {  "title",        &Private::groupTitle },
7817   {  "subtitle",     &Private::groupSubtitle },
7818   {  "anchor",       &Private::groupAnchor },
7819   {  "memberGroups", &Private::memberGroups },
7820   {  "docs",         &Private::docs },
7821   {  "inherited",    &Private::inherited }
7822 };
7823 //%% }
7824 
MemberGroupInfoContext(const Definition * def,const QCString & relPath,const MemberGroup * mg)7825 MemberGroupInfoContext::MemberGroupInfoContext(const Definition *def,
7826        const QCString &relPath,const MemberGroup *mg) : p(std::make_unique<Private>(def,relPath,mg))
7827 {
7828 }
7829 
~MemberGroupInfoContext()7830 MemberGroupInfoContext::~MemberGroupInfoContext()
7831 {
7832 }
7833 
get(const QCString & name) const7834 TemplateVariant MemberGroupInfoContext::get(const QCString &name) const
7835 {
7836   return p->get(name);
7837 }
7838 
fields() const7839 StringVector MemberGroupInfoContext::fields() const
7840 {
7841   return p->fields();
7842 }
7843 
7844 //------------------------------------------------------------------------
7845 
7846 //%% list MemberGroupList[MemberGroupInfo] : list of member groups
7847 class MemberGroupListContext::Private : public GenericNodeListContext
7848 {
7849   public:
addMemberGroup(const Definition * def,const QCString & relPath,const MemberGroup * mg)7850     void addMemberGroup(const Definition *def,const QCString &relPath,const MemberGroup *mg)
7851     {
7852       append(MemberGroupInfoContext::alloc(def,relPath,mg));
7853     }
7854 };
7855 
MemberGroupListContext()7856 MemberGroupListContext::MemberGroupListContext() : p(std::make_unique<Private>())
7857 {
7858 }
7859 
MemberGroupListContext(const Definition * def,const QCString & relPath,const MemberGroupRefList & list)7860 MemberGroupListContext::MemberGroupListContext(const Definition *def,const QCString &relPath,const MemberGroupRefList &list) : p(std::make_unique<Private>())
7861 {
7862   for (const auto &mg : list)
7863   {
7864     p->addMemberGroup(def,relPath,mg);
7865   }
7866 }
7867 
MemberGroupListContext(const Definition * def,const QCString & relPath,const MemberGroupList & list,bool subGrouping)7868 MemberGroupListContext::MemberGroupListContext(const Definition *def,const QCString &relPath,const MemberGroupList &list,bool subGrouping) : p(std::make_unique<Private>())
7869 {
7870   for (const auto &mg : list)
7871   {
7872     if (!mg->allMembersInSameSection() || !subGrouping)
7873     {
7874       p->addMemberGroup(def,relPath,mg.get());
7875     }
7876   }
7877 }
7878 
~MemberGroupListContext()7879 MemberGroupListContext::~MemberGroupListContext()
7880 {
7881 }
7882 
7883 // TemplateListIntf
count() const7884 uint MemberGroupListContext::count() const
7885 {
7886   return p->count();
7887 }
7888 
at(uint index) const7889 TemplateVariant MemberGroupListContext::at(uint index) const
7890 {
7891   return p->at(index);
7892 }
7893 
createIterator() const7894 TemplateListIntf::ConstIteratorPtr MemberGroupListContext::createIterator() const
7895 {
7896   return p->createIterator();
7897 }
7898 
7899 
7900 //------------------------------------------------------------------------
7901 
7902 class MemberListInfoContext::Private
7903 {
7904   public:
Private(const Definition * def,const QCString & relPath,const MemberList * ml,const QCString & title,const QCString & subtitle)7905     Private(const Definition *def,const QCString &relPath,const MemberList *ml,const QCString &title,const QCString &subtitle)
7906       : m_def(def), m_memberList(ml), m_relPath(relPath), m_title(title), m_subtitle(subtitle) {}
7907 
7908     // TemplateStructIntf methods
get(const QCString & n) const7909     TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
fields() const7910     StringVector fields() const                  { return s_inst.fields(); }
7911 
7912   private:
7913     // Property getters
members() const7914     TemplateVariant members() const              { return m_memberListCtx.get(this); }
title() const7915     TemplateVariant title() const                { return m_title; }
subtitle() const7916     TemplateVariant subtitle() const             { return m_subtitle; }
anchor() const7917     TemplateVariant anchor() const               { return MemberList::listTypeAsString(m_memberList->listType()); }
memberGroups() const7918     TemplateVariant memberGroups() const         { return m_memberGroups.get(this); }
inherited() const7919     TemplateVariant inherited() const            { return m_inherited.get(this); }
7920 
7921   private:
7922 
createMemberList() const7923     TemplateVariant createMemberList() const
7924     {
7925       return MemberListContext::alloc(m_memberList);
7926     }
createMemberGroups() const7927     TemplateVariant createMemberGroups() const
7928     {
7929       return MemberGroupListContext::alloc(m_def,m_relPath,m_memberList->getMemberGroupList());
7930     }
createInherited() const7931     TemplateVariant createInherited() const
7932     {
7933       if ((m_memberList->listType()&MemberListType_detailedLists)==0 &&
7934           m_def->definitionType()==Definition::TypeClass)
7935       {
7936         TemplateListIntfPtr list = InheritedMemberInfoListContext::alloc();
7937         auto ctx = std::dynamic_pointer_cast<InheritedMemberInfoListContext>(list);
7938         ctx->addMemberList(toClassDef(m_def),m_memberList->listType(),m_title,FALSE);
7939         return list;
7940       }
7941       else
7942       {
7943         return TemplateVariant(false);
7944       }
7945     }
7946     const Definition *m_def;
7947     const MemberList *m_memberList;
7948     QCString m_relPath;
7949     QCString m_title;
7950     QCString m_subtitle;
7951     CachedItem<TemplateVariant,  Private, &Private::createMemberList>    m_memberListCtx;
7952     CachedItem<TemplateVariant,  Private, &Private::createMemberGroups>  m_memberGroups;
7953     CachedItem<TemplateVariant,  Private, &Private::createInherited>     m_inherited;
7954     static const PropertyMap<MemberListInfoContext::Private> s_inst;
7955 };
7956 
7957 //%% struct MemberListInfo: member list information
7958 //%% {
7959 const PropertyMap<MemberListInfoContext::Private> MemberListInfoContext::Private::s_inst {
7960   {  "members",      &Private::members },
7961   {  "title",        &Private::title },
7962   {  "subtitle",     &Private::subtitle },
7963   {  "anchor",       &Private::anchor },
7964   {  "memberGroups", &Private::memberGroups },
7965   {  "inherited",    &Private::inherited }
7966 };
7967 //%% }
7968 
MemberListInfoContext(const Definition * def,const QCString & relPath,const MemberList * ml,const QCString & title,const QCString & subtitle)7969 MemberListInfoContext::MemberListInfoContext(
7970            const Definition *def,const QCString &relPath,const MemberList *ml,
7971            const QCString &title,const QCString &subtitle) : p(std::make_unique<Private>(def,relPath,ml,title,subtitle))
7972 {
7973 }
7974 
~MemberListInfoContext()7975 MemberListInfoContext::~MemberListInfoContext()
7976 {
7977 }
7978 
get(const QCString & name) const7979 TemplateVariant MemberListInfoContext::get(const QCString &name) const
7980 {
7981   return p->get(name);
7982 }
7983 
fields() const7984 StringVector MemberListInfoContext::fields() const
7985 {
7986   return p->fields();
7987 }
7988 
7989 //------------------------------------------------------------------------
7990 
7991 class InheritedMemberInfoContext::Private
7992 {
7993   public:
Private(const ClassDef * cd,std::unique_ptr<MemberList> && ml,const QCString & title)7994     Private(const ClassDef *cd,std::unique_ptr<MemberList> &&ml,const QCString &title)
7995       : m_class(cd), m_memberList(std::move(ml)), m_title(title) {}
7996 
7997     // TemplateStructIntf methods
get(const QCString & n) const7998     TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
fields() const7999     StringVector fields() const                  { return s_inst.fields(); }
8000 
8001   private:
8002     // Property getters
getClass() const8003     TemplateVariant getClass() const             { return m_classCtx.get(this); }
title() const8004     TemplateVariant title() const                { return m_title; }
members() const8005     TemplateVariant members() const              { return m_memberListCtx.get(this); }
inheritedFrom() const8006     TemplateVariant inheritedFrom() const        { return m_inheritedFrom.get(this); }
id() const8007     TemplateVariant id() const
8008     {
8009       return substitute(MemberList::listTypeAsString(m_memberList->listType()),"-","_")+"_"+
8010                         stripPath(m_class->getOutputFileBase());
8011     }
8012 
8013   private:
createClass() const8014     TemplateVariant createClass() const
8015     {
8016       return ClassContext::alloc(m_class);
8017     }
createMemberList() const8018     TemplateVariant createMemberList() const
8019     {
8020       return MemberListContext::alloc(m_memberList.get());
8021     }
createInheritedFrom() const8022     TemplateVariant createInheritedFrom() const
8023     {
8024       return TemplateImmutableList::alloc({ TemplateVariant(title()), TemplateVariant(getClass()) });
8025     }
8026 
8027     const ClassDef *  m_class;
8028     std::unique_ptr<const MemberList> m_memberList;
8029     QCString    m_title;
8030     CachedItem<TemplateVariant, Private, &Private::createClass>         m_classCtx;
8031     CachedItem<TemplateVariant, Private, &Private::createMemberList>    m_memberListCtx;
8032     CachedItem<TemplateVariant, Private, &Private::createInheritedFrom> m_inheritedFrom;
8033     static const PropertyMap<InheritedMemberInfoContext::Private> s_inst;
8034 };
8035 
8036 //%% struct InheritedMemberInfo: inherited member information
8037 //%% {
8038 const PropertyMap<InheritedMemberInfoContext::Private> InheritedMemberInfoContext::Private::s_inst {
8039   {  "class",         &Private::getClass },
8040   {  "title",         &Private::title },
8041   {  "members",       &Private::members },
8042   {  "id",            &Private::id },
8043   {  "inheritedFrom", &Private::inheritedFrom }
8044 };
8045 //%% }
8046 
InheritedMemberInfoContext(const ClassDef * cd,std::unique_ptr<MemberList> && ml,const QCString & title)8047 InheritedMemberInfoContext::InheritedMemberInfoContext(const ClassDef *cd,std::unique_ptr<MemberList> &&ml,const QCString &title)
8048   : p(std::make_unique<Private>(cd,std::move(ml),title))
8049 {
8050 }
8051 
~InheritedMemberInfoContext()8052 InheritedMemberInfoContext::~InheritedMemberInfoContext()
8053 {
8054 }
8055 
get(const QCString & name) const8056 TemplateVariant InheritedMemberInfoContext::get(const QCString &name) const
8057 {
8058   return p->get(name);
8059 }
8060 
fields() const8061 StringVector InheritedMemberInfoContext::fields() const
8062 {
8063   return p->fields();
8064 }
8065 
8066 //------------------------------------------------------------------------
8067 
8068 //%% list InheritedMemberList[InheritedMemberInfo] : list of inherited classes
8069 class InheritedMemberInfoListContext::Private : public GenericNodeListContext
8070 {
8071   public:
addMemberList(const ClassDef * inheritedFrom,const MemberList & ml,MemberList * combinedList)8072     void addMemberList(const ClassDef *inheritedFrom,const MemberList &ml,MemberList *combinedList)
8073     {
8074       for (const auto &md : ml)
8075       {
8076         if (md->isBriefSectionVisible() && !md->isReimplementedBy(inheritedFrom))
8077         {
8078           combinedList->push_back(md);
8079         }
8080       }
8081     }
addMemberListIncludingGrouped(const ClassDef * inheritedFrom,const MemberList * ml,MemberList * combinedList)8082     void addMemberListIncludingGrouped(const ClassDef *inheritedFrom,const MemberList *ml,MemberList *combinedList)
8083     {
8084       if (ml)
8085       {
8086         addMemberList(inheritedFrom,*ml,combinedList);
8087         for (const auto *mg : ml->getMemberGroupList())
8088         {
8089           addMemberList(inheritedFrom,mg->members(),combinedList);
8090         }
8091       }
8092     }
addMemberGroupsOfClass(const ClassDef * inheritedFrom,const ClassDef * cd,MemberListType lt,MemberList * combinedList)8093     void addMemberGroupsOfClass(const ClassDef *inheritedFrom,
8094                                 const ClassDef *cd,MemberListType lt,MemberList *combinedList)
8095     {
8096       // TODO: why this there no addMemberGroupsOfNamespace, addMembersGroupsOfFile,
8097       // addMemberGroupsOfGroup?
8098       for (const auto &mg: cd->getMemberGroups())
8099       {
8100         if (!mg->members().empty() && (!mg->allMembersInSameSection() || !cd->subGrouping())) // group is in its own section
8101         {
8102           for (const auto &md : mg->members())
8103           {
8104             if (lt==md->getSectionList(mg->container())->listType() &&
8105                 !md->isReimplementedBy(inheritedFrom) &&
8106                 md->isBriefSectionVisible())
8107             {
8108               combinedList->push_back(md);
8109             }
8110           }
8111         }
8112       }
8113     }
addInheritedMembers(const ClassDef * inheritedFrom,const ClassDef * cd,MemberListType lt,MemberListType lt1,int lt2,const QCString & title,bool additionalList)8114     void addInheritedMembers(const ClassDef *inheritedFrom,const ClassDef *cd,MemberListType lt,
8115                              MemberListType lt1,int lt2,const QCString &title,bool additionalList)
8116     {
8117       int count = cd->countMembersIncludingGrouped(lt1,inheritedFrom,additionalList);
8118       if (lt2!=-1) count += cd->countMembersIncludingGrouped((MemberListType)lt2,inheritedFrom,additionalList);
8119       if (count>0)
8120       {
8121         const MemberList *ml  = cd->getMemberList(lt1);
8122         const MemberList *ml2 = lt2!=-1 ? cd->getMemberList((MemberListType)lt2) : 0;
8123         std::unique_ptr<MemberList> combinedList = std::make_unique<MemberList>(lt,MemberListContainer::Class);
8124         addMemberListIncludingGrouped(inheritedFrom,ml,combinedList.get());
8125         addMemberListIncludingGrouped(inheritedFrom,ml2,combinedList.get());
8126         addMemberGroupsOfClass(inheritedFrom,cd,lt,combinedList.get());
8127         if (lt2!=-1) addMemberGroupsOfClass(inheritedFrom,cd,(MemberListType)lt2,combinedList.get());
8128         append(InheritedMemberInfoContext::alloc(cd,std::move(combinedList),title));
8129       }
8130     }
findInheritedMembers(const ClassDef * inheritedFrom,const ClassDef * cd,MemberListType lt,int lt2,const QCString & title,bool additionalList,ClassDefSet & visitedClasses)8131     void findInheritedMembers(const ClassDef *inheritedFrom,const ClassDef *cd,MemberListType lt,
8132                               int lt2, const QCString &title,bool additionalList,
8133                               ClassDefSet &visitedClasses)
8134     {
8135       for (const auto &ibcd : cd->baseClasses())
8136       {
8137         ClassDef *icd=ibcd.classDef;
8138         if (icd->isLinkable())
8139         {
8140           int lt1,lt3;
8141           convertProtectionLevel(lt,ibcd.prot,&lt1,&lt3);
8142           if (lt2==-1 && lt3!=-1)
8143           {
8144             lt2=lt3;
8145           }
8146           if (visitedClasses.find(icd)==visitedClasses.end())
8147           {
8148             visitedClasses.insert(icd); // guard for multiple virtual inheritance
8149             if (lt1!=-1)
8150             {
8151               // add member info for members of cd with list type lt
8152               addInheritedMembers(inheritedFrom,icd,lt,(MemberListType)lt1,lt2,title,additionalList);
8153               // recurse down the inheritance tree
8154               findInheritedMembers(inheritedFrom,icd,(MemberListType)lt1,lt2,title,additionalList,visitedClasses);
8155             }
8156           }
8157         }
8158       }
8159     }
8160 };
8161 
InheritedMemberInfoListContext()8162 InheritedMemberInfoListContext::InheritedMemberInfoListContext() : p(std::make_unique<Private>())
8163 {
8164 }
8165 
addMemberList(const ClassDef * cd,MemberListType lt,const QCString & title,bool additionalList)8166 void InheritedMemberInfoListContext::addMemberList(
8167     const ClassDef *cd,MemberListType lt,const QCString &title,bool additionalList)
8168 {
8169   ClassDefSet visited;
8170   bool memberInSection = cd->countMembersIncludingGrouped(lt,cd,FALSE)>0;
8171   bool show = (additionalList && !memberInSection) || // inherited member to show in the additional inherited members list
8172               (!additionalList && memberInSection);   // inherited member to show in a member list of the class
8173   //printf("%s:%s show=%d\n",qPrint(cd->name()),qPrint(MemberList::listTypeAsString(lt)),show);
8174   if (show)
8175   {
8176     p->findInheritedMembers(cd,cd,lt,-1,title,additionalList,visited);
8177   }
8178 }
8179 
~InheritedMemberInfoListContext()8180 InheritedMemberInfoListContext::~InheritedMemberInfoListContext()
8181 {
8182 }
8183 
8184 // TemplateListIntf
count() const8185 uint InheritedMemberInfoListContext::count() const
8186 {
8187   return p->count();
8188 }
8189 
at(uint index) const8190 TemplateVariant InheritedMemberInfoListContext::at(uint index) const
8191 {
8192   return p->at(index);
8193 }
8194 
createIterator() const8195 TemplateListIntf::ConstIteratorPtr InheritedMemberInfoListContext::createIterator() const
8196 {
8197   return p->createIterator();
8198 }
8199 
8200 //------------------------------------------------------------------------
8201 
8202 class ArgumentContext::Private
8203 {
8204   public:
Private(const Argument & arg,const Definition * def,const QCString & relPath)8205     Private(const Argument &arg,const Definition *def,const QCString &relPath)
8206       : m_argument(arg), m_def(def), m_relPath(relPath) {}
8207 
8208     // TemplateStructIntf methods
get(const QCString & n) const8209     TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
fields() const8210     StringVector fields() const                  { return s_inst.fields(); }
8211 
8212   private:
8213     // Property getters
type() const8214     TemplateVariant type() const                 { return m_type.get(this); }
attrib() const8215     TemplateVariant attrib() const               { return m_argument.attrib; }
name() const8216     TemplateVariant name() const                 { return m_argument.name; }
defVal() const8217     TemplateVariant defVal() const               { return m_defval.get(this); }
array() const8218     TemplateVariant array() const                { return m_argument.array; }
docs() const8219     TemplateVariant docs() const                 { return m_docs.get(this); }
namePart() const8220     TemplateVariant namePart() const
8221     {
8222       QCString result = m_argument.attrib;
8223       uint l = result.length();
8224       if (l>2 && result.at(0)=='[' && result.at(l-1)==']')
8225       {
8226         result = result.mid(1,l-2);
8227         if (result!=",") result+=":"; // for normal keywords add colon
8228       }
8229       return result;
8230     }
8231 
8232   private:
createType() const8233     TemplateVariant createType() const
8234     {
8235       return createLinkedText(m_def,m_relPath,m_argument.type);
8236     }
createDefval() const8237     TemplateVariant createDefval() const
8238     {
8239       return createLinkedText(m_def,m_relPath,m_argument.defval);
8240     }
createDocs() const8241     TemplateVariant createDocs() const
8242     {
8243       return !m_argument.docs.isEmpty() ?
8244           TemplateVariant(parseDoc(m_def,m_def->docFile(),m_def->docLine(),m_relPath,m_argument.docs,TRUE)) :
8245           TemplateVariant("");
8246     }
8247     Argument m_argument;
8248     const Definition *m_def;
8249     QCString m_relPath;
8250     CachedItem<TemplateVariant, Private, &Private::createType>   m_type;
8251     CachedItem<TemplateVariant, Private, &Private::createDefval> m_defval;
8252     CachedItem<TemplateVariant, Private, &Private::createDocs>   m_docs;
8253     static const PropertyMap<ArgumentContext::Private> s_inst;
8254 };
8255 
8256 //%% struct Argument: parameter information
8257 //%% {
8258 const PropertyMap<ArgumentContext::Private> ArgumentContext::Private::s_inst {
8259   {  "type",     &Private::type },
8260   {  "name",     &Private::name },
8261   {  "defVal",   &Private::defVal },
8262   {  "docs",     &Private::docs },
8263   {  "attrib",   &Private::attrib },
8264   {  "array",    &Private::array },
8265   {  "namePart", &Private::namePart }
8266 };
8267 //%% }
8268 
8269 
ArgumentContext(const Argument & al,const Definition * def,const QCString & relPath)8270 ArgumentContext::ArgumentContext(const Argument &al,const Definition *def,const QCString &relPath) : p(std::make_unique<Private>(al,def,relPath))
8271 {
8272 }
8273 
~ArgumentContext()8274 ArgumentContext::~ArgumentContext()
8275 {
8276 }
8277 
get(const QCString & name) const8278 TemplateVariant ArgumentContext::get(const QCString &name) const
8279 {
8280   return p->get(name);
8281 }
8282 
fields() const8283 StringVector ArgumentContext::fields() const
8284 {
8285   return p->fields();
8286 }
8287 
8288 //------------------------------------------------------------------------
8289 
8290 //%% list ArgumentList[Argument] : list of inherited classes
8291 class ArgumentListContext::Private : public GenericNodeListContext
8292 {
8293   public:
addArgument(const Argument & arg,const Definition * def,const QCString & relPath)8294     void addArgument(const Argument &arg,const Definition *def,const QCString &relPath)
8295     {
8296       append(ArgumentContext::alloc(arg,def,relPath));
8297     }
8298 };
8299 
ArgumentListContext()8300 ArgumentListContext::ArgumentListContext() : p(std::make_unique<Private>())
8301 {
8302 }
8303 
ArgumentListContext(const ArgumentList & list,const Definition * def,const QCString & relPath)8304 ArgumentListContext::ArgumentListContext(const ArgumentList &list,
8305                         const Definition *def,const QCString &relPath) : p(std::make_unique<Private>())
8306 {
8307   for (const Argument &arg : list)
8308   {
8309     p->addArgument(arg,def,relPath);
8310   }
8311 }
8312 
~ArgumentListContext()8313 ArgumentListContext::~ArgumentListContext()
8314 {
8315 }
8316 
8317 // TemplateListIntf
count() const8318 uint ArgumentListContext::count() const
8319 {
8320   return p->count();
8321 }
8322 
at(uint index) const8323 TemplateVariant ArgumentListContext::at(uint index) const
8324 {
8325   return p->at(index);
8326 }
8327 
createIterator() const8328 TemplateListIntf::ConstIteratorPtr ArgumentListContext::createIterator() const
8329 {
8330   return p->createIterator();
8331 }
8332 
8333 //------------------------------------------------------------------------
8334 
8335 // SymbolIndex
8336 //  - name: string
8337 //  - letter: string
8338 //  - symbolGroups: SymbolGroupList
8339 // SymbolGroupList: list of SymbolGroups
8340 // SymbolGroup
8341 //  - id
8342 //  - name
8343 //  - symbols: SymbolList
8344 // SymbolList: list of Symbols
8345 // Symbol
8346 //  - obj
8347 //  - scope
8348 //  - relPath
8349 
8350 //------------------------------------------------------------------------
8351 
8352 class SymbolContext::Private
8353 {
8354   public:
Private(const Definition * d,const Definition * prev,const Definition * next)8355     Private(const Definition *d,const Definition *prev, const Definition *next)
8356       : m_def(d), m_prevDef(prev), m_nextDef(next) {}
8357 
8358     // TemplateStructIntf methods
get(const QCString & n) const8359     TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
fields() const8360     StringVector fields() const                  { return s_inst.fields(); }
8361 
8362   private:
8363     // Property getters
fileName() const8364     TemplateVariant fileName() const             { return m_def->getOutputFileBase(); }
anchor() const8365     TemplateVariant anchor() const               { return m_def->anchor(); }
scope() const8366     TemplateVariant scope() const                { return m_scope.get(this); }
relPath() const8367     TemplateVariant relPath() const              { return externalRef("../",m_def->getReference(),TRUE); }
8368 
8369   private:
createScope() const8370     TemplateVariant createScope() const
8371     {
8372       const Definition *scope     = m_def->getOuterScope();
8373       const Definition *next      = m_nextDef;
8374       const Definition *prev      = m_prevDef;
8375       const Definition *nextScope = next ? next->getOuterScope() : 0;
8376       const Definition *prevScope = prev ? prev->getOuterScope() : 0;
8377       const MemberDef  *md        = toMemberDef(m_def);
8378       bool isFunctionLike   = md && (md->isFunction() || md->isSlot() || md->isSignal());
8379       bool overloadedFunction = ((prevScope!=0 && scope==prevScope) || (scope && scope==nextScope)) &&
8380                                 md && (md->isFunction() || md->isSlot());
8381 
8382       QCString name;
8383       if (prev==0 && next==0) // unique name
8384       {
8385         if (scope!=Doxygen::globalScope)
8386         {
8387           name = scope->name();
8388         }
8389         else if (md)
8390         {
8391           const FileDef *fd = md->getBodyDef();
8392           if (fd==0) fd = md->getFileDef();
8393           if (fd)
8394           {
8395             name = fd->localName();
8396           }
8397         }
8398       }
8399       else
8400       {
8401         QCString prefix;
8402         if (md) prefix=md->localName();
8403         if (overloadedFunction) // overloaded member function
8404         {
8405           prefix+=md->argsString();
8406           // show argument list to disambiguate overloaded functions
8407         }
8408         else if (md && isFunctionLike) // unique member function
8409         {
8410           prefix+="()"; // only to show it is a function
8411         }
8412         bool found=FALSE;
8413         if (m_def->definitionType()==Definition::TypeClass)
8414         {
8415           name = m_def->displayName();
8416           found = TRUE;
8417         }
8418         else if (m_def->definitionType()==Definition::TypeNamespace)
8419         {
8420           name = m_def->displayName();
8421           found = TRUE;
8422         }
8423         else if (scope==0 || scope==Doxygen::globalScope) // in global scope
8424         {
8425           if (md)
8426           {
8427             const FileDef *fd = md->getBodyDef();
8428             if (fd==0) fd = md->getFileDef();
8429             if (fd)
8430             {
8431               if (!prefix.isEmpty()) prefix+=": ";
8432               name = prefix + convertToXML(fd->localName());
8433               found = TRUE;
8434             }
8435           }
8436         }
8437         else if (md && (md->resolveAlias()->getClassDef() || md->resolveAlias()->getNamespaceDef()))
8438           // member in class or namespace scope
8439         {
8440           SrcLangExt lang = md->getLanguage();
8441           name = m_def->getOuterScope()->qualifiedName()
8442             + getLanguageSpecificSeparator(lang) + prefix;
8443           found = TRUE;
8444         }
8445         else if (scope) // some thing else? -> show scope
8446         {
8447           name = prefix + convertToXML(scope->name());
8448           found = TRUE;
8449         }
8450         if (!found) // fallback
8451         {
8452           name = prefix + "("+theTranslator->trGlobalNamespace()+")";
8453         }
8454       }
8455       return name;
8456     }
8457     const Definition *m_def;
8458     const Definition *m_prevDef;
8459     const Definition *m_nextDef;
8460     CachedItem<TemplateVariant,Private,&Private::createScope> m_scope;
8461     static const PropertyMap<SymbolContext::Private> s_inst;
8462 };
8463 
8464 //%% struct Symbol: specific search item
8465 //%% {
8466 const PropertyMap<SymbolContext::Private> SymbolContext::Private::s_inst {
8467   {  "fileName",&Private::fileName },
8468   {  "anchor",  &Private::anchor },
8469   {  "scope",   &Private::scope },
8470   {  "relPath", &Private::relPath }
8471 };
8472 //%% }
8473 
SymbolContext(const Definition * def,const Definition * prevDef,const Definition * nextDef)8474 SymbolContext::SymbolContext(const Definition *def,const Definition *prevDef,const Definition *nextDef) : p(std::make_unique<Private>(def,prevDef,nextDef))
8475 {
8476 }
8477 
~SymbolContext()8478 SymbolContext::~SymbolContext()
8479 {
8480 }
8481 
get(const QCString & name) const8482 TemplateVariant SymbolContext::get(const QCString &name) const
8483 {
8484   return p->get(name);
8485 }
8486 
fields() const8487 StringVector SymbolContext::fields() const
8488 {
8489   return p->fields();
8490 }
8491 
8492 //------------------------------------------------------------------------
8493 
8494 //%% list SymbolList[Symbol] : list of search symbols with the same name
8495 class SymbolListContext::Private : public GenericNodeListContext
8496 {
8497   public:
Private(const SearchIndexList::const_iterator & start,const SearchIndexList::const_iterator & end)8498     Private(const SearchIndexList::const_iterator &start,
8499             const SearchIndexList::const_iterator &end)
8500     {
8501       const Definition *prev = 0;
8502       for (auto it = start; it!=end;)
8503       {
8504         const Definition *def = *it;
8505         ++it;
8506         const Definition *next = it!=end ? *it : 0;
8507         append(SymbolContext::alloc(def,prev,next));
8508         prev = def;
8509       }
8510     }
8511 };
8512 
SymbolListContext(const SearchIndexList::const_iterator & start,const SearchIndexList::const_iterator & end)8513 SymbolListContext::SymbolListContext(const SearchIndexList::const_iterator &start,
8514                                      const SearchIndexList::const_iterator &end) : p(std::make_unique<Private>(start,end))
8515 {
8516 }
8517 
~SymbolListContext()8518 SymbolListContext::~SymbolListContext()
8519 {
8520 }
8521 
8522 // TemplateListIntf
count() const8523 uint SymbolListContext::count() const
8524 {
8525   return p->count();
8526 }
8527 
at(uint index) const8528 TemplateVariant SymbolListContext::at(uint index) const
8529 {
8530   return p->at(index);
8531 }
8532 
createIterator() const8533 TemplateListIntf::ConstIteratorPtr SymbolListContext::createIterator() const
8534 {
8535   return p->createIterator();
8536 }
8537 
8538 //------------------------------------------------------------------------
8539 
8540 class SymbolGroupContext::Private
8541 {
8542   public:
Private(const SearchIndexList::const_iterator & start,const SearchIndexList::const_iterator & end)8543     Private(const SearchIndexList::const_iterator &start, const SearchIndexList::const_iterator &end)
8544       : m_start(start), m_end(end) {}
8545 
8546     // TemplateStructIntf methods
get(const QCString & n) const8547     TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
fields() const8548     StringVector fields() const                  { return s_inst.fields(); }
8549 
8550   private:
8551     // Property getters
id() const8552     TemplateVariant id() const                   { return searchId(*m_start); }
name() const8553     TemplateVariant name() const                 { return searchName(*m_start); }
symbolList() const8554     TemplateVariant symbolList() const           { return m_symbolList.get(this); }
8555 
8556   private:
8557 
createSymbolList() const8558     TemplateVariant createSymbolList() const
8559     {
8560       return SymbolListContext::alloc(m_start,m_end);
8561     }
8562 
8563     SearchIndexList::const_iterator m_start;
8564     SearchIndexList::const_iterator m_end;
8565     CachedItem<TemplateVariant,Private,&Private::createSymbolList> m_symbolList;
8566     static const PropertyMap<SymbolGroupContext::Private> s_inst;
8567 };
8568 
8569 //%% struct SymbolGroup: search group of similar symbols
8570 //%% {
8571 const PropertyMap<SymbolGroupContext::Private> SymbolGroupContext::Private::s_inst {
8572   {  "id",     &Private::id },
8573   {  "name",   &Private::name },
8574   {  "symbols",&Private::symbolList }
8575 };
8576 //%% }
8577 
SymbolGroupContext(const SearchIndexList::const_iterator & start,const SearchIndexList::const_iterator & end)8578 SymbolGroupContext::SymbolGroupContext(const SearchIndexList::const_iterator &start,
8579                                        const SearchIndexList::const_iterator &end) : p(std::make_unique<Private>(start,end))
8580 {
8581 }
8582 
~SymbolGroupContext()8583 SymbolGroupContext::~SymbolGroupContext()
8584 {
8585 }
8586 
get(const QCString & name) const8587 TemplateVariant SymbolGroupContext::get(const QCString &name) const
8588 {
8589   return p->get(name);
8590 }
8591 
fields() const8592 StringVector SymbolGroupContext::fields() const
8593 {
8594   return p->fields();
8595 }
8596 
8597 //------------------------------------------------------------------------
8598 
8599 //%% list SymbolGroupList[SymbolGroup] : list of search groups one per by name
8600 class SymbolGroupListContext::Private : public GenericNodeListContext
8601 {
8602   public:
Private(const SearchIndexList & sil)8603     Private(const SearchIndexList &sil)
8604     {
8605       QCString lastName;
8606       auto it = sil.begin();
8607       auto it_begin = it;
8608       while (it!=sil.end())
8609       {
8610         QCString name = searchName(*it);
8611         if (name!=lastName)
8612         {
8613           if (it!=it_begin)
8614           {
8615             append(SymbolGroupContext::alloc(it_begin,it));
8616           }
8617           it_begin = it;
8618           lastName = name;
8619         }
8620         ++it;
8621       }
8622       if (it_begin!=sil.end())
8623       {
8624         append(SymbolGroupContext::alloc(it_begin,sil.end()));
8625       }
8626     }
8627 };
8628 
SymbolGroupListContext(const SearchIndexList & sil)8629 SymbolGroupListContext::SymbolGroupListContext(const SearchIndexList &sil) : p(std::make_unique<Private>(sil))
8630 {
8631 }
8632 
~SymbolGroupListContext()8633 SymbolGroupListContext::~SymbolGroupListContext()
8634 {
8635 }
8636 
8637 // TemplateListIntf
count() const8638 uint SymbolGroupListContext::count() const
8639 {
8640   return p->count();
8641 }
8642 
at(uint index) const8643 TemplateVariant SymbolGroupListContext::at(uint index) const
8644 {
8645   return p->at(index);
8646 }
8647 
createIterator() const8648 TemplateListIntf::ConstIteratorPtr SymbolGroupListContext::createIterator() const
8649 {
8650   return p->createIterator();
8651 }
8652 
8653 //------------------------------------------------------------------------
8654 
8655 class SymbolIndexContext::Private
8656 {
8657   public:
Private(const std::string & letter,const SearchIndexList & sl,const QCString & name)8658     Private(const std::string &letter, const SearchIndexList &sl, const QCString &name)
8659       : m_letter(letter), m_searchList(sl), m_name(name) {}
8660     // TemplateStructIntf methods
get(const QCString & n) const8661     TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
fields() const8662     StringVector fields() const                  { return s_inst.fields(); }
8663 
8664   private:
8665     // Property getters
name() const8666     TemplateVariant name() const                 { return m_name; }
letter() const8667     TemplateVariant letter() const               { return m_letter; }
symbolGroups() const8668     TemplateVariant symbolGroups() const         { return m_symbolGroups.get(this); }
8669 
8670   private:
8671 
createSymbolGroups() const8672     TemplateVariant createSymbolGroups() const
8673     {
8674       return SymbolGroupListContext::alloc(m_searchList);
8675     }
8676     QCString m_letter;
8677     const SearchIndexList &m_searchList;
8678     QCString m_name;
8679     CachedItem<TemplateVariant,Private,&Private::createSymbolGroups> m_symbolGroups;
8680     static const PropertyMap<SymbolIndexContext::Private> s_inst;
8681 };
8682 
8683 //%% struct SymbolIndex: search index
8684 //%% {
8685 const PropertyMap<SymbolIndexContext::Private> SymbolIndexContext::Private::s_inst {
8686   {  "name",        &Private::name },
8687   {  "letter",      &Private::letter },
8688   {  "symbolGroups",&Private::symbolGroups },
8689 };
8690 //%% }
8691 
SymbolIndexContext(const std::string & letter,const SearchIndexList & sl,const QCString & name)8692 SymbolIndexContext::SymbolIndexContext(const std::string &letter,const SearchIndexList &sl,const QCString &name) : p(std::make_unique<Private>(letter,sl,name))
8693 {
8694 }
8695 
~SymbolIndexContext()8696 SymbolIndexContext::~SymbolIndexContext()
8697 {
8698 }
8699 
get(const QCString & name) const8700 TemplateVariant SymbolIndexContext::get(const QCString &name) const
8701 {
8702   return p->get(name);
8703 }
8704 
fields() const8705 StringVector SymbolIndexContext::fields() const
8706 {
8707   return p->fields();
8708 }
8709 
8710 //------------------------------------------------------------------------
8711 
8712 //%% list SymbolIndices[SymbolIndex] : list of search indices one per by type
8713 class SymbolIndicesContext::Private : public GenericNodeListContext
8714 {
8715   public:
Private(const SearchIndexInfo & info)8716     Private(const SearchIndexInfo &info)
8717     {
8718       // use info->symbolList to populate the list
8719       for (const auto &kv : info.symbolMap)
8720       {
8721         append(SymbolIndexContext::alloc(kv.first,kv.second,info.name));
8722       }
8723     }
8724 };
8725 
SymbolIndicesContext(const SearchIndexInfo & info)8726 SymbolIndicesContext::SymbolIndicesContext(const SearchIndexInfo &info) : p(std::make_unique<Private>(info))
8727 {
8728 }
8729 
~SymbolIndicesContext()8730 SymbolIndicesContext::~SymbolIndicesContext()
8731 {
8732 }
8733 
8734 // TemplateListIntf
count() const8735 uint SymbolIndicesContext::count() const
8736 {
8737   return p->count();
8738 }
8739 
at(uint index) const8740 TemplateVariant SymbolIndicesContext::at(uint index) const
8741 {
8742   return p->at(index);
8743 }
8744 
createIterator() const8745 TemplateListIntf::ConstIteratorPtr SymbolIndicesContext::createIterator() const
8746 {
8747   return p->createIterator();
8748 }
8749 
8750 //------------------------------------------------------------------------
8751 
8752 class SearchIndexContext::Private
8753 {
8754   public:
Private(const SearchIndexInfo & info)8755     Private(const SearchIndexInfo &info) : m_info(info) {}
8756 
8757     // TemplateStructIntf methods
get(const QCString & n) const8758     TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
fields() const8759     StringVector fields() const                  { return s_inst.fields(); }
8760 
8761   private:
8762     // Property getters
name() const8763     TemplateVariant name() const                 { return m_info.name; }
text() const8764     TemplateVariant text() const                 { return m_info.getText(); }
symbolIndices() const8765     TemplateVariant symbolIndices() const        { return m_symbolIndices.get(this); }
8766 
8767   private:
createSymbolIndices() const8768     TemplateVariant createSymbolIndices() const
8769     {
8770       return SymbolIndicesContext::alloc(m_info);
8771     }
8772 
8773     const SearchIndexInfo &m_info;
8774     CachedItem<TemplateVariant, Private, &Private::createSymbolIndices> m_symbolIndices;
8775     static const PropertyMap<SearchIndexContext::Private> s_inst;
8776 };
8777 
8778 //%% struct SearchIndex: search index
8779 //%% {
8780 const PropertyMap<SearchIndexContext::Private> SearchIndexContext::Private::s_inst {
8781   {  "name",         &Private::name },
8782   {  "text",         &Private::text },
8783   {  "symbolIndices",&Private::symbolIndices }
8784 };
8785 //%% }
8786 
SearchIndexContext(const SearchIndexInfo & info)8787 SearchIndexContext::SearchIndexContext(const SearchIndexInfo &info) : p(std::make_unique<Private>(info))
8788 {
8789 }
8790 
~SearchIndexContext()8791 SearchIndexContext::~SearchIndexContext()
8792 {
8793 }
8794 
get(const QCString & name) const8795 TemplateVariant SearchIndexContext::get(const QCString &name) const
8796 {
8797   return p->get(name);
8798 }
8799 
fields() const8800 StringVector SearchIndexContext::fields() const
8801 {
8802   return p->fields();
8803 }
8804 
8805 
8806 //------------------------------------------------------------------------
8807 
8808 //%% list SearchIndices[SearchIndex] : list of search indices one per by type
8809 class SearchIndicesContext::Private : public GenericNodeListContext
8810 {
8811   public:
Private()8812     Private()
8813     {
8814       for (const auto &si : getSearchIndices())
8815       {
8816         append(SearchIndexContext::alloc(si));
8817       }
8818     }
8819 };
8820 
SearchIndicesContext()8821 SearchIndicesContext::SearchIndicesContext() : p(std::make_unique<Private>())
8822 {
8823 }
8824 
~SearchIndicesContext()8825 SearchIndicesContext::~SearchIndicesContext()
8826 {
8827 }
8828 
8829 // TemplateListIntf
count() const8830 uint SearchIndicesContext::count() const
8831 {
8832   return p->count();
8833 }
8834 
at(uint index) const8835 TemplateVariant SearchIndicesContext::at(uint index) const
8836 {
8837   return p->at(index);
8838 }
8839 
createIterator() const8840 TemplateListIntf::ConstIteratorPtr SearchIndicesContext::createIterator() const
8841 {
8842   return p->createIterator();
8843 }
8844 
8845 
8846 //------------------------------------------------------------------------
8847 
8848 class HtmlEscaper : public TemplateEscapeIntf
8849 {
8850   public:
clone()8851     std::unique_ptr<TemplateEscapeIntf> clone()
8852     {
8853       return std::make_unique<HtmlEscaper>(*this);
8854     }
escape(const QCString & s)8855     QCString escape(const QCString &s)
8856     {
8857       return convertToHtml(s,TRUE);
8858     }
enableTabbing(bool)8859     void enableTabbing(bool) {}
8860 };
8861 
8862 //------------------------------------------------------------------------
8863 
8864 class LatexSpaceless : public TemplateSpacelessIntf
8865 {
8866   public:
LatexSpaceless()8867     LatexSpaceless() { reset(); }
clone()8868     std::unique_ptr<TemplateSpacelessIntf> clone()
8869     {
8870       return std::make_unique<LatexSpaceless>(*this);
8871     }
reset()8872     void reset() { }
remove(const QCString & s)8873     QCString remove(const QCString &s)
8874     {
8875       if (s.isEmpty()) return s;
8876       TextStream result;
8877       const char *p = s.data();
8878       char c;
8879       while ((c=*p++))
8880       {
8881         switch(c)
8882         {
8883           case '\t': case ' ': case '\n':
8884             break;
8885           default:
8886             result << c;
8887             break;
8888         }
8889       }
8890       return result.str();
8891     }
8892   private:
8893 };
8894 
8895 //------------------------------------------------------------------------
8896 
8897 class HtmlSpaceless : public TemplateSpacelessIntf
8898 {
8899   public:
HtmlSpaceless()8900     HtmlSpaceless() { reset(); }
clone()8901     std::unique_ptr<TemplateSpacelessIntf> clone()
8902     {
8903       return std::make_unique<HtmlSpaceless>(*this);
8904     }
reset()8905     void reset()
8906     {
8907       m_insideTag = FALSE;
8908       m_insideString = '\0';
8909       m_removeSpaces = TRUE;
8910     }
remove(const QCString & s)8911     QCString remove(const QCString &s)
8912     {
8913       if (s.isEmpty()) return s;
8914       TextStream result;
8915       const char *p = s.data();
8916       char c;
8917       while ((c=*p++))
8918       {
8919         switch(c)
8920         {
8921           case '<': // start of a tag
8922             if (!m_insideString) m_insideTag=TRUE,m_removeSpaces=FALSE;
8923             result << c;
8924             break;
8925           case '>': // end of a tag
8926             if (!m_insideString) m_insideTag=FALSE,m_removeSpaces=TRUE;
8927             result << c;
8928             break;
8929           case '\\': // escaped character in a string
8930             result << c;
8931             if (m_insideString && *p) result << *p++;
8932             break;
8933           case '"': case '\'':
8934             if (m_insideTag)
8935             {
8936               if (m_insideString==c) // end of string
8937               {
8938                 m_insideString='\0';
8939               }
8940               else if (m_insideString=='\0') // start of string
8941               {
8942                 m_insideString=c;
8943               }
8944             }
8945             result << c;
8946             break;
8947           case ' ': case '\t': case '\n': // whitespace
8948             if (!m_insideTag) // outside tags strip consecutive whitespace
8949             {
8950               m_removeSpaces=TRUE;
8951             }
8952             else
8953             {
8954               result << ' ';
8955             }
8956             break;
8957           default:
8958             //if (m_removeSpaces) result+=' ';
8959             result << c;
8960             m_removeSpaces=FALSE;
8961             break;
8962         }
8963       }
8964       //printf("HtmlSpaceless::remove({%s})={%s} m_insideTag=%d m_insideString=%c (%d) removeSpaces=%d\n",qPrint(s),qPrint(result),
8965       //    m_insideTag,m_insideString,m_insideString,m_removeSpaces);
8966       return result.str();
8967     }
8968   private:
8969     bool m_insideTag;
8970     char m_insideString;
8971     bool m_removeSpaces;
8972 };
8973 
8974 //------------------------------------------------------------------------
8975 
8976 class LatexEscaper : public TemplateEscapeIntf
8977 {
8978   public:
clone()8979     std::unique_ptr<TemplateEscapeIntf> clone()
8980     {
8981       return std::make_unique<LatexEscaper>(*this);
8982     }
LatexEscaper()8983     LatexEscaper() : m_tabbing(FALSE) {}
escape(const QCString & s)8984     QCString escape(const QCString &s)
8985     {
8986       return convertToLaTeX(s,m_tabbing);
8987     }
enableTabbing(bool b)8988     void enableTabbing(bool b) { m_tabbing=b; }
8989   private:
8990     bool m_tabbing;
8991 };
8992 
8993 
8994 //------------------------------------------------------------------------
8995 
generateOutputViaTemplate()8996 void generateOutputViaTemplate()
8997 {
8998   {
8999     auto e = std::make_unique<TemplateEngine>();
9000     auto ctx = e->createContext();
9001     if (ctx)
9002     {
9003       TemplateStructIntfPtr doxygen              (DoxygenContext::alloc());
9004       TemplateStructIntfPtr config               (ConfigContext::alloc());
9005       TemplateStructIntfPtr tr                   (TranslateContext::alloc());
9006       TemplateListIntfPtr   classList            (ClassListContext::alloc());
9007       TemplateStructIntfPtr classIndex           (ClassIndexContext::alloc());
9008       TemplateStructIntfPtr classTree            (ClassTreeContext::alloc());
9009       TemplateStructIntfPtr classHierarchy       (ClassHierarchyContext::alloc());
9010       TemplateListIntfPtr   conceptList          (ConceptListContext::alloc());
9011       TemplateStructIntfPtr conceptTree          (ConceptTreeContext::alloc());
9012       TemplateListIntfPtr   namespaceList        (NamespaceListContext::alloc());
9013       TemplateStructIntfPtr namespaceTree        (NamespaceTreeContext::alloc());
9014       TemplateListIntfPtr   dirList              (DirListContext::alloc());
9015       TemplateListIntfPtr   fileList             (FileListContext::alloc());
9016       TemplateStructIntfPtr fileTree             (FileTreeContext::alloc());
9017       TemplateStructIntfPtr pageTree             (PageTreeContext::alloc(*Doxygen::pageLinkedMap));
9018       TemplateListIntfPtr   pageList             (PageListContext::alloc(*Doxygen::pageLinkedMap));
9019       TemplateStructIntfPtr exampleTree          (ExampleTreeContext::alloc());
9020       TemplateListIntfPtr   exampleList          (ExampleListContext::alloc());
9021       TemplateStructIntfPtr moduleTree           (ModuleTreeContext::alloc());
9022       TemplateListIntfPtr   moduleList           (ModuleListContext::alloc());
9023       TemplateStructIntfPtr globalsIndex         (GlobalsIndexContext::alloc());
9024       TemplateStructIntfPtr classMembersIndex    (ClassMembersIndexContext::alloc());
9025       TemplateStructIntfPtr namespaceMembersIndex(NamespaceMembersIndexContext::alloc());
9026       TemplateListIntfPtr   searchIndices        (SearchIndicesContext::alloc());
9027 
9028       //%% Doxygen doxygen:
9029       ctx->set("doxygen",doxygen);
9030       //%% Translator tr:
9031       ctx->set("tr",tr);
9032       //%% Config config:
9033       ctx->set("config",config);
9034       //%% ClassList classList:
9035       ctx->set("classList",classList); // not used for standard HTML
9036       //%% ClassTree classTree:
9037       ctx->set("classTree",classTree);
9038       //%% ClassIndex classIndex:
9039       ctx->set("classIndex",classIndex);
9040       //%% ClassHierarchy classHierarchy:
9041       ctx->set("classHierarchy",classHierarchy);
9042       //%% ConceptList conceptList:
9043       ctx->set("conceptList",conceptList);
9044       //%% ConceptTree conceptTree:
9045       ctx->set("conceptTree",conceptTree);
9046       //%% NamespaceList namespaceList:
9047       ctx->set("namespaceList",namespaceList);
9048       //%% NamespaceTree namespaceTree:
9049       ctx->set("namespaceTree",namespaceTree);
9050       //%% FileList fileList:
9051       ctx->set("fileList",fileList);
9052       //%% FileTree fileTree:
9053       ctx->set("fileTree",fileTree);
9054       //%% PageList pageList
9055       ctx->set("pageList",pageList);
9056       //%% PageTree pageTree
9057       ctx->set("pageTree",pageTree);
9058       //%% ExampleTree exampleTree
9059       ctx->set("exampleTree",exampleTree);
9060       //%% ExampleList exampleList
9061       ctx->set("exampleList",exampleList);
9062       //%% ModuleTree moduleTree
9063       ctx->set("moduleTree",moduleTree);
9064       //%% ModuleList moduleList
9065       ctx->set("moduleList",moduleList);
9066       //%% DirList dirList
9067       ctx->set("dirList",dirList);
9068       //%% Page mainPage
9069       if (Doxygen::mainPage)
9070       {
9071         TemplateStructIntfPtr mainPage = PageContext::alloc(Doxygen::mainPage.get(),TRUE,FALSE);
9072         ctx->set("mainPage",mainPage);
9073       }
9074       else
9075       {
9076         // TODO: for LaTeX output index should be main... => solve in template
9077         Doxygen::mainPage.reset(createPageDef("[generated]",1,"index","",Config_getString(PROJECT_NAME)));
9078         Doxygen::mainPage->setFileName("index");
9079         TemplateStructIntfPtr mainPage = PageContext::alloc(Doxygen::mainPage.get(),TRUE,FALSE);
9080         ctx->set("mainPage",mainPage);
9081       }
9082       //%% GlobalsIndex globalsIndex:
9083       ctx->set("globalsIndex",globalsIndex);
9084       //%% ClassMembersIndex classMembersIndex:
9085       ctx->set("classMembersIndex",classMembersIndex);
9086       //%% NamespaceMembersIndex namespaceMembersIndex:
9087       ctx->set("namespaceMembersIndex",namespaceMembersIndex);
9088       //%% SearchIndices searchIndices
9089       ctx->set("searchIndices",searchIndices);
9090       //%% string space
9091       ctx->set("space"," ");
9092 
9093       //if (Config_getBool(GENERATE_HTML))
9094       { // render HTML output
9095         e->setTemplateDir("templates/html"); // TODO: make template part user configurable
9096         Template *tpl = e->loadByName("htmllayout.tpl",1);
9097         if (tpl)
9098         {
9099           g_globals.outputFormat = ContextOutputFormat_Html;
9100           g_globals.dynSectionId = 0;
9101           g_globals.outputDir    = Config_getString(HTML_OUTPUT);
9102           Dir dir(g_globals.outputDir.str());
9103           createSubDirs(dir);
9104           ctx->setEscapeIntf(Config_getString(HTML_FILE_EXTENSION),std::make_unique<HtmlEscaper>());
9105           ctx->setSpacelessIntf(std::make_unique<HtmlSpaceless>());
9106           ctx->setOutputDirectory(g_globals.outputDir);
9107           TextStream ts;
9108           tpl->render(ts,ctx.get());
9109         }
9110         e->unload(tpl);
9111       }
9112 
9113       // TODO: clean index before each run...
9114 
9115       //if (Config_getBool(GENERATE_LATEX))
9116       if (0)
9117       { // render LaTeX output
9118         e->setTemplateDir("templates/latex"); // TODO: make template part user configurable
9119         Template *tpl = e->loadByName("latexlayout.tpl",1);
9120         if (tpl)
9121         {
9122           g_globals.outputFormat = ContextOutputFormat_Latex;
9123           g_globals.dynSectionId = 0;
9124           g_globals.outputDir    = Config_getString(LATEX_OUTPUT);
9125           Dir dir(g_globals.outputDir.str());
9126           createSubDirs(dir);
9127           ctx->setEscapeIntf(".tex",std::make_unique<LatexEscaper>());
9128           ctx->setSpacelessIntf(std::make_unique<LatexSpaceless>());
9129           ctx->setOutputDirectory(g_globals.outputDir);
9130           TextStream ts;
9131           tpl->render(ts,ctx.get());
9132         }
9133         e->unload(tpl);
9134       }
9135     }
9136   }
9137 }
9138 
generateTemplateFiles(const QCString & templateDir)9139 void generateTemplateFiles(const QCString &templateDir)
9140 {
9141   if (templateDir.isEmpty()) return;
9142   Dir thisDir;
9143   if (!thisDir.exists(templateDir.str()) && !thisDir.mkdir(templateDir.str()))
9144   {
9145     err("Failed to create output directory '%s'\n",qPrint(templateDir));
9146     return;
9147   }
9148   std::string outDir = templateDir.str()+"/html";
9149   if (!thisDir.exists(outDir) && !thisDir.mkdir(outDir))
9150   {
9151     err("Failed to create output directory '%s'\n",outDir.c_str());
9152     return;
9153   }
9154   ResourceMgr::instance().writeCategory("html",outDir.c_str());
9155 }
9156