1 /****************************************************************************
2 **
3 ** Copyright (C) 2019 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the tools applications of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21 ** included in the packaging of this file. Please review the following
22 ** information to ensure the GNU General Public License requirements will
23 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24 **
25 ** $QT_END_LICENSE$
26 **
27 ****************************************************************************/
28 
29 #ifndef QDOCDATABASE_H
30 #define QDOCDATABASE_H
31 
32 #include "config.h"
33 #include "text.h"
34 #include "tree.h"
35 
36 #include <QtCore/qdebug.h>
37 #include <QtCore/qmap.h>
38 #include <QtCore/qstring.h>
39 
40 QT_BEGIN_NAMESPACE
41 
42 typedef QMultiMap<Text, const Node *> TextToNodeMap;
43 
44 class Atom;
45 class Generator;
46 class QDocDatabase;
47 
48 enum FindFlag {
49     SearchBaseClasses = 0x1,
50     SearchEnumValues = 0x2,
51     TypesOnly = 0x4,
52     IgnoreModules = 0x8
53 };
54 
55 class QDocForest
56 {
57 private:
58     friend class QDocDatabase;
QDocForest(QDocDatabase * qdb)59     QDocForest(QDocDatabase *qdb) : qdb_(qdb), primaryTree_(nullptr), currentIndex_(0) {}
60     ~QDocForest();
61 
62     NamespaceNode *firstRoot();
63     NamespaceNode *nextRoot();
64     Tree *firstTree();
65     Tree *nextTree();
primaryTree()66     Tree *primaryTree() { return primaryTree_; }
findTree(const QString & t)67     Tree *findTree(const QString &t) { return forest_.value(t); }
keys()68     QStringList keys() { return forest_.keys(); }
primaryTreeRoot()69     NamespaceNode *primaryTreeRoot() { return (primaryTree_ ? primaryTree_->root() : nullptr); }
isEmpty()70     bool isEmpty() { return searchOrder().isEmpty(); }
done()71     bool done() { return (currentIndex_ >= searchOrder().size()); }
72     const QVector<Tree *> &searchOrder();
73     const QVector<Tree *> &indexSearchOrder();
74     void setSearchOrder(const QStringList &t);
isLoaded(const QString & fn)75     bool isLoaded(const QString &fn)
76     {
77         for (const auto *tree : searchOrder()) {
78             if (fn == tree->indexFileName())
79                 return true;
80         }
81         return false;
82     }
83 
findNode(const QStringList & path,const Node * relative,int findFlags,Node::Genus genus)84     const Node *findNode(const QStringList &path, const Node *relative, int findFlags,
85                          Node::Genus genus)
86     {
87         for (const auto *tree : searchOrder()) {
88             const Node *n = tree->findNode(path, relative, findFlags, genus);
89             if (n)
90                 return n;
91             relative = nullptr;
92         }
93         return nullptr;
94     }
95 
findNodeByNameAndType(const QStringList & path,bool (Node::* isMatch)()const)96     Node *findNodeByNameAndType(const QStringList &path, bool (Node::*isMatch)() const)
97     {
98         for (const auto *tree : searchOrder()) {
99             Node *n = tree->findNodeByNameAndType(path, isMatch);
100             if (n)
101                 return n;
102         }
103         return nullptr;
104     }
105 
findClassNode(const QStringList & path)106     ClassNode *findClassNode(const QStringList &path)
107     {
108         for (const auto *tree : searchOrder()) {
109             ClassNode *n = tree->findClassNode(path);
110             if (n)
111                 return n;
112         }
113         return nullptr;
114     }
115 
findNodeForInclude(const QStringList & path)116     Node *findNodeForInclude(const QStringList &path)
117     {
118         for (const auto *tree : searchOrder()) {
119             Node *n = tree->findNodeForInclude(path);
120             if (n)
121                 return n;
122         }
123         return nullptr;
124     }
125 
126     const FunctionNode *findFunctionNode(const QStringList &path, const Parameters &parameters,
127                                          const Node *relative, Node::Genus genus);
128     const Node *findNodeForTarget(QStringList &targetPath, const Node *relative, Node::Genus genus,
129                                   QString &ref);
130 
findTypeNode(const QStringList & path,const Node * relative,Node::Genus genus)131     const Node *findTypeNode(const QStringList &path, const Node *relative, Node::Genus genus)
132     {
133         int flags = SearchBaseClasses | SearchEnumValues | TypesOnly;
134         if (relative && genus == Node::DontCare && relative->genus() != Node::DOC)
135             genus = relative->genus();
136         for (const auto *tree : searchOrder()) {
137             const Node *n = tree->findNode(path, relative, flags, genus);
138             if (n)
139                 return n;
140             relative = nullptr;
141         }
142         return nullptr;
143     }
144 
findPageNodeByTitle(const QString & title)145     const PageNode *findPageNodeByTitle(const QString &title)
146     {
147         for (const auto *tree : searchOrder()) {
148             const PageNode *n = tree->findPageNodeByTitle(title);
149             if (n)
150                 return n;
151         }
152         return nullptr;
153     }
154 
getCollectionNode(const QString & name,Node::NodeType type)155     const CollectionNode *getCollectionNode(const QString &name, Node::NodeType type)
156     {
157         for (auto *tree : searchOrder()) {
158             const CollectionNode *cn = tree->getCollection(name, type);
159             if (cn)
160                 return cn;
161         }
162         return nullptr;
163     }
164 
lookupQmlType(const QString & name)165     QmlTypeNode *lookupQmlType(const QString &name)
166     {
167         for (const auto *tree : searchOrder()) {
168             QmlTypeNode *qcn = tree->lookupQmlType(name);
169             if (qcn)
170                 return qcn;
171         }
172         return nullptr;
173     }
174 
lookupQmlBasicType(const QString & name)175     Aggregate *lookupQmlBasicType(const QString &name)
176     {
177         for (const auto *tree : searchOrder()) {
178             Aggregate *a = tree->lookupQmlBasicType(name);
179             if (a)
180                 return a;
181         }
182         return nullptr;
183     }
clearSearchOrder()184     void clearSearchOrder() { searchOrder_.clear(); }
clearLinkCounts()185     void clearLinkCounts()
186     {
187         for (auto *tree : searchOrder())
188             tree->clearLinkCount();
189     }
190     void printLinkCounts(const QString &project);
191     QString getLinkCounts(QStringList &strings, QVector<int> &counts);
192     void newPrimaryTree(const QString &module);
193     void setPrimaryTree(const QString &t);
194     NamespaceNode *newIndexTree(const QString &module);
195 
196 private:
197     QDocDatabase *qdb_;
198     Tree *primaryTree_;
199     int currentIndex_;
200     QMap<QString, Tree *> forest_;
201     QVector<Tree *> searchOrder_;
202     QVector<Tree *> indexSearchOrder_;
203     QVector<QString> moduleNames_;
204 };
205 
206 class QDocDatabase
207 {
208     Q_DECLARE_TR_FUNCTIONS(QDoc::QDocDatabase)
209 
210 public:
211     static QDocDatabase *qdocDB();
212     static void destroyQdocDB();
213     ~QDocDatabase();
214 
findTree(const QString & t)215     Tree *findTree(const QString &t) { return forest_.findTree(t); }
216 
groups()217     const CNMap &groups() { return primaryTree()->groups(); }
modules()218     const CNMap &modules() { return primaryTree()->modules(); }
qmlModules()219     const CNMap &qmlModules() { return primaryTree()->qmlModules(); }
jsModules()220     const CNMap &jsModules() { return primaryTree()->jsModules(); }
221 
addGroup(const QString & name)222     CollectionNode *addGroup(const QString &name) { return primaryTree()->addGroup(name); }
addModule(const QString & name)223     CollectionNode *addModule(const QString &name) { return primaryTree()->addModule(name); }
addQmlModule(const QString & name)224     CollectionNode *addQmlModule(const QString &name) { return primaryTree()->addQmlModule(name); }
addJsModule(const QString & name)225     CollectionNode *addJsModule(const QString &name) { return primaryTree()->addJsModule(name); }
226 
addToGroup(const QString & name,Node * node)227     CollectionNode *addToGroup(const QString &name, Node *node)
228     {
229         return primaryTree()->addToGroup(name, node);
230     }
addToModule(const QString & name,Node * node)231     CollectionNode *addToModule(const QString &name, Node *node)
232     {
233         return primaryTree()->addToModule(name, node);
234     }
addToQmlModule(const QString & name,Node * node)235     CollectionNode *addToQmlModule(const QString &name, Node *node)
236     {
237         return primaryTree()->addToQmlModule(name, node);
238     }
addToJsModule(const QString & name,Node * node)239     CollectionNode *addToJsModule(const QString &name, Node *node)
240     {
241         return primaryTree()->addToJsModule(name, node);
242     }
243 
addExampleNode(ExampleNode * n)244     void addExampleNode(ExampleNode *n) { primaryTree()->addExampleNode(n); }
exampleNodeMap()245     ExampleNodeMap &exampleNodeMap() { return primaryTree()->exampleNodeMap(); }
246 
247     QmlTypeNode *findQmlType(const QString &name);
248     QmlTypeNode *findQmlType(const QString &qmid, const QString &name);
249     QmlTypeNode *findQmlType(const ImportRec &import, const QString &name);
250     Aggregate *findQmlBasicType(const QString &qmid, const QString &name);
251 
obsoleteClasses()252     static NodeMultiMap &obsoleteClasses() { return obsoleteClasses_; }
obsoleteQmlTypes()253     static NodeMultiMap &obsoleteQmlTypes() { return obsoleteQmlTypes_; }
classesWithObsoleteMembers()254     static NodeMultiMap &classesWithObsoleteMembers() { return classesWithObsoleteMembers_; }
qmlTypesWithObsoleteMembers()255     static NodeMultiMap &qmlTypesWithObsoleteMembers() { return qmlTypesWithObsoleteMembers_; }
cppClasses()256     static NodeMultiMap &cppClasses() { return cppClasses_; }
qmlBasicTypes()257     static NodeMultiMap &qmlBasicTypes() { return qmlBasicTypes_; }
qmlTypes()258     static NodeMultiMap &qmlTypes() { return qmlTypes_; }
examples()259     static NodeMultiMap &examples() { return examples_; }
newClassMaps()260     static NodeMapMap &newClassMaps() { return newClassMaps_; }
newQmlTypeMaps()261     static NodeMapMap &newQmlTypeMaps() { return newQmlTypeMaps_; }
newSinceMaps()262     static NodeMultiMapMap &newSinceMaps() { return newSinceMaps_; }
263 
264 private:
findAllClasses(Aggregate * node)265     void findAllClasses(Aggregate *node) { node->findAllClasses(); }
findAllFunctions(Aggregate * node)266     void findAllFunctions(Aggregate *node) { node->findAllFunctions(functionIndex_); }
findAllAttributions(Aggregate * node)267     void findAllAttributions(Aggregate *node) { node->findAllAttributions(attributions_); }
268     void findAllLegaleseTexts(Aggregate *node);
findAllObsoleteThings(Aggregate * node)269     void findAllObsoleteThings(Aggregate *node) { node->findAllObsoleteThings(); }
findAllSince(Aggregate * node)270     void findAllSince(Aggregate *node) { node->findAllSince(); }
271 
272 public:
273     /*******************************************************************
274      special collection access functions
275     ********************************************************************/
276     NodeMultiMap &getCppClasses();
277     NodeMultiMap &getObsoleteClasses();
278     NodeMultiMap &getClassesWithObsoleteMembers();
279     NodeMultiMap &getObsoleteQmlTypes();
280     NodeMultiMap &getQmlTypesWithObsoleteMembers();
281     NodeMultiMap &getNamespaces();
282     NodeMultiMap &getQmlBasicTypes();
283     NodeMultiMap &getQmlTypes();
284     NodeMultiMap &getExamples();
285     NodeMultiMap &getAttributions();
286     NodeMapMap &getFunctionIndex();
287     TextToNodeMap &getLegaleseTexts();
288     const NodeMap &getClassMap(const QString &key);
289     const NodeMap &getQmlTypeMap(const QString &key);
290     const NodeMap &getSinceMap(const QString &key);
291 
292     /*******************************************************************
293       Many of these will be either eliminated or replaced.
294     ********************************************************************/
295     void resolveStuff();
insertTarget(const QString & name,const QString & title,TargetRec::TargetType type,Node * node,int priority)296     void insertTarget(const QString &name, const QString &title, TargetRec::TargetType type,
297                       Node *node, int priority)
298     {
299         primaryTree()->insertTarget(name, title, type, node, priority);
300     }
301 
302     /*******************************************************************
303       The functions declared below are called for the current tree only.
304     ********************************************************************/
findRelatesNode(const QStringList & path)305     Aggregate *findRelatesNode(const QStringList &path)
306     {
307         return primaryTree()->findRelatesNode(path);
308     }
309     Node *findNodeInOpenNamespace(QStringList &path, bool (Node::*)() const);
310     /*******************************************************************/
311 
312     /*****************************************************************************
313       This function can handle parameters enclosed in '[' ']' (domanin and genus).
314     ******************************************************************************/
315     const Node *findNodeForAtom(const Atom *atom, const Node *relative, QString &ref);
316     /*******************************************************************/
317 
318     /*******************************************************************
319       The functions declared below are called for all trees.
320     ********************************************************************/
findClassNode(const QStringList & path)321     ClassNode *findClassNode(const QStringList &path) { return forest_.findClassNode(path); }
findNodeForInclude(const QStringList & path)322     Node *findNodeForInclude(const QStringList &path) { return forest_.findNodeForInclude(path); }
323     const FunctionNode *findFunctionNode(const QString &target, const Node *relative,
324                                          Node::Genus genus);
325     const Node *findTypeNode(const QString &type, const Node *relative, Node::Genus genus);
326     const Node *findNodeForTarget(const QString &target, const Node *relative);
findPageNodeByTitle(const QString & title)327     const PageNode *findPageNodeByTitle(const QString &title)
328     {
329         return forest_.findPageNodeByTitle(title);
330     }
findNodeByNameAndType(const QStringList & path,bool (Node::* isMatch)()const)331     Node *findNodeByNameAndType(const QStringList &path, bool (Node::*isMatch)() const)
332     {
333         return forest_.findNodeByNameAndType(path, isMatch);
334     }
getCollectionNode(const QString & name,Node::NodeType type)335     const CollectionNode *getCollectionNode(const QString &name, Node::NodeType type)
336     {
337         return forest_.getCollectionNode(name, type);
338     }
findFunctionNodeForTag(QString tag)339     FunctionNode *findFunctionNodeForTag(QString tag)
340     {
341         return primaryTree()->findFunctionNodeForTag(tag);
342     }
findMacroNode(const QString & t)343     FunctionNode *findMacroNode(const QString &t) { return primaryTree()->findMacroNode(t); }
344 
345 private:
findNodeForTarget(QStringList & targetPath,const Node * relative,Node::Genus genus,QString & ref)346     const Node *findNodeForTarget(QStringList &targetPath, const Node *relative, Node::Genus genus,
347                                   QString &ref)
348     {
349         return forest_.findNodeForTarget(targetPath, relative, genus, ref);
350     }
findFunctionNode(const QStringList & path,const Parameters & parameters,const Node * relative,Node::Genus genus)351     const FunctionNode *findFunctionNode(const QStringList &path, const Parameters &parameters,
352                                          const Node *relative, Node::Genus genus)
353     {
354         return forest_.findFunctionNode(path, parameters, relative, genus);
355     }
356 
357     /*******************************************************************/
358 public:
addPropertyFunction(PropertyNode * property,const QString & funcName,PropertyNode::FunctionRole funcRole)359     void addPropertyFunction(PropertyNode *property, const QString &funcName,
360                              PropertyNode::FunctionRole funcRole)
361     {
362         primaryTree()->addPropertyFunction(property, funcName, funcRole);
363     }
364 
setVersion(const QString & v)365     void setVersion(const QString &v) { version_ = v; }
version()366     QString version() const { return version_; }
367 
368     void generateTagFile(const QString &name, Generator *g);
369     void readIndexes(const QStringList &indexFiles);
370     void generateIndex(const QString &fileName, const QString &url, const QString &title,
371                        Generator *g);
372 
clearOpenNamespaces()373     void clearOpenNamespaces() { openNamespaces_.clear(); }
insertOpenNamespace(const QString & path)374     void insertOpenNamespace(const QString &path) { openNamespaces_.insert(path); }
setShowInternal(bool value)375     void setShowInternal(bool value) { showInternal_ = value; }
setSingleExec(bool value)376     void setSingleExec(bool value) { singleExec_ = value; }
377     void processForest();
378 
379     // Try to make this function private.
forest()380     QDocForest &forest() { return forest_; }
primaryTreeRoot()381     NamespaceNode *primaryTreeRoot() { return forest_.primaryTreeRoot(); }
newPrimaryTree(const QString & module)382     void newPrimaryTree(const QString &module) { forest_.newPrimaryTree(module); }
setPrimaryTree(const QString & t)383     void setPrimaryTree(const QString &t) { forest_.setPrimaryTree(t); }
newIndexTree(const QString & module)384     NamespaceNode *newIndexTree(const QString &module) { return forest_.newIndexTree(module); }
searchOrder()385     const QVector<Tree *> &searchOrder() { return forest_.searchOrder(); }
setLocalSearch()386     void setLocalSearch() { forest_.searchOrder_ = QVector<Tree *>(1, primaryTree()); }
setSearchOrder(const QVector<Tree * > & searchOrder)387     void setSearchOrder(const QVector<Tree *> &searchOrder) { forest_.searchOrder_ = searchOrder; }
setSearchOrder(QStringList & t)388     void setSearchOrder(QStringList &t) { forest_.setSearchOrder(t); }
389     void mergeCollections(Node::NodeType type, CNMap &cnm, const Node *relative);
390     void mergeCollections(CollectionNode *c);
clearSearchOrder()391     void clearSearchOrder() { forest_.clearSearchOrder(); }
incrementLinkCount(const Node * t)392     void incrementLinkCount(const Node *t) { t->tree()->incrementLinkCount(); }
clearLinkCounts()393     void clearLinkCounts() { forest_.clearLinkCounts(); }
printLinkCounts(const QString & t)394     void printLinkCounts(const QString &t) { forest_.printLinkCounts(t); }
getLinkCounts(QStringList & strings,QVector<int> & counts)395     QString getLinkCounts(QStringList &strings, QVector<int> &counts)
396     {
397         return forest_.getLinkCounts(strings, counts);
398     }
399     QString getNewLinkTarget(const Node *locNode, const Node *t, const QString &fileName,
400                              QString &text, bool broken = false)
401     {
402         return primaryTree()->getNewLinkTarget(locNode, t, fileName, text, broken);
403     }
getTargetList(const QString & t)404     TargetList *getTargetList(const QString &t) { return primaryTree()->getTargetList(t); }
getTargetListKeys()405     QStringList getTargetListKeys() { return primaryTree()->getTargetListKeys(); }
keys()406     QStringList keys() { return forest_.keys(); }
407     void resolveNamespaces();
408     void resolveProxies();
409     void resolveBaseClasses();
410 
411 private:
412     friend class Tree;
413 
findNode(const QStringList & path,const Node * relative,int findFlags,Node::Genus genus)414     const Node *findNode(const QStringList &path, const Node *relative, int findFlags,
415                          Node::Genus genus)
416     {
417         return forest_.findNode(path, relative, findFlags, genus);
418     }
419     void processForest(void (QDocDatabase::*)(Aggregate *));
isLoaded(const QString & t)420     bool isLoaded(const QString &t) { return forest_.isLoaded(t); }
421     static void initializeDB();
422 
423 private:
424     QDocDatabase();
QDocDatabase(QDocDatabase const &)425     QDocDatabase(QDocDatabase const &) : showInternal_(false), forest_(this) {}
426     QDocDatabase &operator=(QDocDatabase const &);
427 
428 public:
429     static bool debug;
primaryTree()430     Tree *primaryTree() { return forest_.primaryTree(); }
431 
432 private:
433     static QDocDatabase *qdocDB_;
434     static NodeMap typeNodeMap_;
435     static NodeMultiMap obsoleteClasses_;
436     static NodeMultiMap classesWithObsoleteMembers_;
437     static NodeMultiMap obsoleteQmlTypes_;
438     static NodeMultiMap qmlTypesWithObsoleteMembers_;
439     static NodeMultiMap cppClasses_;
440     static NodeMultiMap qmlBasicTypes_;
441     static NodeMultiMap qmlTypes_;
442     static NodeMultiMap examples_;
443     static NodeMapMap newClassMaps_;
444     static NodeMapMap newQmlTypeMaps_;
445     static NodeMultiMapMap newSinceMaps_;
446 
447     bool showInternal_;
448     bool singleExec_;
449     QString version_;
450     QDocForest forest_;
451 
452     NodeMultiMap namespaceIndex_;
453     NodeMultiMap attributions_;
454     NodeMapMap functionIndex_;
455     TextToNodeMap legaleseTexts_;
456     QSet<QString> openNamespaces_;
457 };
458 
459 QT_END_NAMESPACE
460 
461 #endif
462