15#include <QtCore/qregularexpression.h>
20using namespace Qt::StringLiterals;
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
61
62
63
64
65
66
69 for (
auto *entry : m_searchOrder)
72 m_searchOrder.clear();
73 m_indexSearchOrder.clear();
74 m_moduleNames.clear();
75 m_primaryTree =
nullptr;
79
80
81
82
86 return (!searchOrder().isEmpty() ? searchOrder()[0] :
nullptr);
90
91
92
93
97 return (m_currentIndex < searchOrder().size() ? searchOrder()[m_currentIndex] :
nullptr);
101
102
103
104
107
108
109
110
111
112
113
114
115void QDocForest::setPrimaryTree(
const QString &t)
117 QString T = t.toLower();
118 m_primaryTree = findTree(T);
120 if (m_primaryTree ==
nullptr)
121 qCCritical(lcQdoc) <<
"Error: Could not set primary tree to" << t;
125
126
127
128void QDocForest::setSearchOrder(
const QStringList &t)
130 if (!m_searchOrder.isEmpty())
134 m_searchOrder.reserve(m_forest.size() + 1);
135 m_searchOrder.clear();
136 m_moduleNames.reserve(m_forest.size() + 1);
137 m_moduleNames.clear();
140 QString primaryName = primaryTree()->physicalModuleName();
141 m_searchOrder.append(m_primaryTree);
142 m_moduleNames.append(primaryName);
143 m_forest.remove(primaryName);
145 for (
const QString &m : t) {
146 if (primaryName != m) {
147 auto it = m_forest.find(m);
148 if (it != m_forest.end()) {
149 m_searchOrder.append(it.value());
150 m_moduleNames.append(m);
156
157
158
159
160 if (!m_forest.isEmpty()) {
161 for (
auto it = m_forest.begin(); it != m_forest.end(); ++it) {
162 m_searchOrder.append(it.value());
163 m_moduleNames.append(it.key());
169
170
171
172
173
174
175
176 for (
int i = 0; i < m_searchOrder.size(); ++i) {
177 if (!m_forest.contains(m_moduleNames.at(i))) {
178 m_forest.insert(m_moduleNames.at(i), m_searchOrder.at(i));
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
210 if (m_searchOrder.isEmpty())
211 return indexSearchOrder();
212 return m_searchOrder;
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230const QList<Tree *> &
QDocForest::indexSearchOrder()
232 if (m_forest.size() > m_indexSearchOrder.size())
233 m_indexSearchOrder.prepend(m_primaryTree);
234 return m_indexSearchOrder;
238
239
240
241
244 m_primaryTree =
new Tree(module, m_qdb);
245 m_forest.insert(module.toLower(), m_primaryTree);
246 return m_primaryTree->root();
250
251
252
253void QDocForest::newPrimaryTree(
const QString &module)
255 m_primaryTree =
new Tree(module, m_qdb);
259
260
261
262
263
264
265
266
267
268
269
270
271
272const Node *
QDocForest::findNodeForTarget(QStringList &targetPath,
const Node *relative,
273 Genus genus, QString &ref)
277 QString entity = targetPath.takeFirst();
278 QStringList entityPath = entity.split(
"::");
281 if (!targetPath.isEmpty())
282 target = targetPath.takeFirst();
285 const Node *tocNode =
nullptr;
286 for (
const auto *tree : searchOrder()) {
287 const Node *n = tree->findNodeForTarget(entityPath, target, relative, flags, genus, ref, &type);
290 if (type != TargetRec::Contents)
301
302
303
304
305
306
307
308
309
314 for (
const auto *tree : searchOrder()) {
315 const FunctionNode *fn = tree->findFunctionNode(path, parameters, relative, genus);
324
325
326
327
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
366
367
368
371 if (s_qdocDB ==
nullptr) {
379
380
383 if (s_qdocDB !=
nullptr) {
390
391
392
393
394
395
396
397
398
399
400
401
402
405 s_typeNodeMap.insert(
"accepted",
nullptr);
406 s_typeNodeMap.insert(
"actionPerformed",
nullptr);
407 s_typeNodeMap.insert(
"activated",
nullptr);
408 s_typeNodeMap.insert(
"alias",
nullptr);
409 s_typeNodeMap.insert(
"anchors",
nullptr);
410 s_typeNodeMap.insert(
"any",
nullptr);
411 s_typeNodeMap.insert(
"array",
nullptr);
412 s_typeNodeMap.insert(
"autoSearch",
nullptr);
413 s_typeNodeMap.insert(
"axis",
nullptr);
414 s_typeNodeMap.insert(
"backClicked",
nullptr);
415 s_typeNodeMap.insert(
"boomTime",
nullptr);
416 s_typeNodeMap.insert(
"border",
nullptr);
417 s_typeNodeMap.insert(
"buttonClicked",
nullptr);
418 s_typeNodeMap.insert(
"callback",
nullptr);
419 s_typeNodeMap.insert(
"char",
nullptr);
420 s_typeNodeMap.insert(
"clicked",
nullptr);
421 s_typeNodeMap.insert(
"close",
nullptr);
422 s_typeNodeMap.insert(
"closed",
nullptr);
423 s_typeNodeMap.insert(
"cond",
nullptr);
424 s_typeNodeMap.insert(
"data",
nullptr);
425 s_typeNodeMap.insert(
"dataReady",
nullptr);
426 s_typeNodeMap.insert(
"dateString",
nullptr);
427 s_typeNodeMap.insert(
"dateTimeString",
nullptr);
428 s_typeNodeMap.insert(
"datetime",
nullptr);
429 s_typeNodeMap.insert(
"day",
nullptr);
430 s_typeNodeMap.insert(
"deactivated",
nullptr);
431 s_typeNodeMap.insert(
"drag",
nullptr);
432 s_typeNodeMap.insert(
"easing",
nullptr);
433 s_typeNodeMap.insert(
"error",
nullptr);
434 s_typeNodeMap.insert(
"exposure",
nullptr);
435 s_typeNodeMap.insert(
"fatalError",
nullptr);
436 s_typeNodeMap.insert(
"fileSelected",
nullptr);
437 s_typeNodeMap.insert(
"flags",
nullptr);
438 s_typeNodeMap.insert(
"float",
nullptr);
439 s_typeNodeMap.insert(
"focus",
nullptr);
440 s_typeNodeMap.insert(
"focusZone",
nullptr);
441 s_typeNodeMap.insert(
"format",
nullptr);
442 s_typeNodeMap.insert(
"framePainted",
nullptr);
443 s_typeNodeMap.insert(
"from",
nullptr);
444 s_typeNodeMap.insert(
"frontClicked",
nullptr);
445 s_typeNodeMap.insert(
"function",
nullptr);
446 s_typeNodeMap.insert(
"hasOpened",
nullptr);
447 s_typeNodeMap.insert(
"hovered",
nullptr);
448 s_typeNodeMap.insert(
"hoveredTitle",
nullptr);
449 s_typeNodeMap.insert(
"hoveredUrl",
nullptr);
450 s_typeNodeMap.insert(
"imageCapture",
nullptr);
451 s_typeNodeMap.insert(
"imageProcessing",
nullptr);
452 s_typeNodeMap.insert(
"index",
nullptr);
453 s_typeNodeMap.insert(
"initialized",
nullptr);
454 s_typeNodeMap.insert(
"isLoaded",
nullptr);
455 s_typeNodeMap.insert(
"item",
nullptr);
456 s_typeNodeMap.insert(
"key",
nullptr);
457 s_typeNodeMap.insert(
"keysequence",
nullptr);
458 s_typeNodeMap.insert(
"listViewClicked",
nullptr);
459 s_typeNodeMap.insert(
"loadRequest",
nullptr);
460 s_typeNodeMap.insert(
"locale",
nullptr);
461 s_typeNodeMap.insert(
"location",
nullptr);
462 s_typeNodeMap.insert(
"long",
nullptr);
463 s_typeNodeMap.insert(
"message",
nullptr);
464 s_typeNodeMap.insert(
"messageReceived",
nullptr);
465 s_typeNodeMap.insert(
"mode",
nullptr);
466 s_typeNodeMap.insert(
"month",
nullptr);
467 s_typeNodeMap.insert(
"name",
nullptr);
468 s_typeNodeMap.insert(
"number",
nullptr);
469 s_typeNodeMap.insert(
"object",
nullptr);
470 s_typeNodeMap.insert(
"offset",
nullptr);
471 s_typeNodeMap.insert(
"ok",
nullptr);
472 s_typeNodeMap.insert(
"openCamera",
nullptr);
473 s_typeNodeMap.insert(
"openImage",
nullptr);
474 s_typeNodeMap.insert(
"openVideo",
nullptr);
475 s_typeNodeMap.insert(
"padding",
nullptr);
476 s_typeNodeMap.insert(
"parent",
nullptr);
477 s_typeNodeMap.insert(
"path",
nullptr);
478 s_typeNodeMap.insert(
"photoModeSelected",
nullptr);
479 s_typeNodeMap.insert(
"position",
nullptr);
480 s_typeNodeMap.insert(
"precision",
nullptr);
481 s_typeNodeMap.insert(
"presetClicked",
nullptr);
482 s_typeNodeMap.insert(
"preview",
nullptr);
483 s_typeNodeMap.insert(
"previewSelected",
nullptr);
484 s_typeNodeMap.insert(
"progress",
nullptr);
485 s_typeNodeMap.insert(
"puzzleLost",
nullptr);
486 s_typeNodeMap.insert(
"qmlSignal",
nullptr);
487 s_typeNodeMap.insert(
"rectangle",
nullptr);
488 s_typeNodeMap.insert(
"request",
nullptr);
489 s_typeNodeMap.insert(
"requestId",
nullptr);
490 s_typeNodeMap.insert(
"section",
nullptr);
491 s_typeNodeMap.insert(
"selected",
nullptr);
492 s_typeNodeMap.insert(
"send",
nullptr);
493 s_typeNodeMap.insert(
"settingsClicked",
nullptr);
494 s_typeNodeMap.insert(
"shoe",
nullptr);
495 s_typeNodeMap.insert(
"short",
nullptr);
496 s_typeNodeMap.insert(
"signed",
nullptr);
497 s_typeNodeMap.insert(
"sizeChanged",
nullptr);
498 s_typeNodeMap.insert(
"size_t",
nullptr);
499 s_typeNodeMap.insert(
"sockaddr",
nullptr);
500 s_typeNodeMap.insert(
"someOtherSignal",
nullptr);
501 s_typeNodeMap.insert(
"sourceSize",
nullptr);
502 s_typeNodeMap.insert(
"startButtonClicked",
nullptr);
503 s_typeNodeMap.insert(
"state",
nullptr);
504 s_typeNodeMap.insert(
"std::initializer_list",
nullptr);
505 s_typeNodeMap.insert(
"std::list",
nullptr);
506 s_typeNodeMap.insert(
"std::map",
nullptr);
507 s_typeNodeMap.insert(
"std::pair",
nullptr);
508 s_typeNodeMap.insert(
"std::string",
nullptr);
509 s_typeNodeMap.insert(
"std::vector",
nullptr);
510 s_typeNodeMap.insert(
"stringlist",
nullptr);
511 s_typeNodeMap.insert(
"swapPlayers",
nullptr);
512 s_typeNodeMap.insert(
"symbol",
nullptr);
513 s_typeNodeMap.insert(
"t",
nullptr);
514 s_typeNodeMap.insert(
"T",
nullptr);
515 s_typeNodeMap.insert(
"tagChanged",
nullptr);
516 s_typeNodeMap.insert(
"timeString",
nullptr);
517 s_typeNodeMap.insert(
"timeout",
nullptr);
518 s_typeNodeMap.insert(
"to",
nullptr);
519 s_typeNodeMap.insert(
"toggled",
nullptr);
520 s_typeNodeMap.insert(
"type",
nullptr);
521 s_typeNodeMap.insert(
"unsigned",
nullptr);
522 s_typeNodeMap.insert(
"urllist",
nullptr);
523 s_typeNodeMap.insert(
"va_list",
nullptr);
524 s_typeNodeMap.insert(
"value",
nullptr);
525 s_typeNodeMap.insert(
"valueEmitted",
nullptr);
526 s_typeNodeMap.insert(
"videoFramePainted",
nullptr);
527 s_typeNodeMap.insert(
"videoModeSelected",
nullptr);
528 s_typeNodeMap.insert(
"videoRecorder",
nullptr);
529 s_typeNodeMap.insert(
"void",
nullptr);
530 s_typeNodeMap.insert(
"volatile",
nullptr);
531 s_typeNodeMap.insert(
"wchar_t",
nullptr);
532 s_typeNodeMap.insert(
"x",
nullptr);
533 s_typeNodeMap.insert(
"y",
nullptr);
534 s_typeNodeMap.insert(
"zoom",
nullptr);
535 s_typeNodeMap.insert(
"zoomTo",
nullptr);
539
540
543
544
545
546
549
550
551
552
555
556
557
558
561
562
563
564
565
566
567
570
571
572
573
574
575
576
579
580
581
582
583
584
587
588
589
590
591
592
595
596
597
598
599
600
603
604
605
606
607
608
609
610
613
614
615
616
617
618
621
622
623
624
627
628
629
632
633
634
635
636
637
638
641 if (!qmid.isEmpty()) {
642 if (
auto *qcn = m_forest.lookupQmlType(qmid + u"::"_s + name); qcn)
646 QStringList path(name);
647 return static_cast<QmlTypeNode *>(m_forest.findNodeByNameAndType(path, &Node::isQmlType));
651
652
653
654
664 if (!record.m_importId.isEmpty()) {
665 const QString namespacePrefix{
"%1."_L1.arg(record.m_importId)};
666 if (!type.startsWith(namespacePrefix))
668 type.remove(0, namespacePrefix.size());
671 const QString qmName = record.m_importUri.isEmpty() ? record.m_moduleName : record.m_importUri;
672 return m_forest.lookupQmlType(qmName + u"::"_s + type);
676
677
678
679
680
681
685 return primaryTree()->lookupQmlType(qmid + u"::"_s + name);
690
691
692
693
694
695
708
709
710
711
712
715 Tree *t = m_forest.firstTree();
717 if (!m_completedFindFunctions.values(t).contains(func)) {
718 (
this->*(func))(t->root());
719 m_completedFindFunctions.insert(t, func);
721 t = m_forest.nextTree();
726
727
731 return m_legaleseTexts;
735
736
740 return s_classesWithObsoleteMembers;
744
745
749 return s_obsoleteQmlTypes;
753
754
758 return s_qmlTypesWithObsoleteMembers;
762
763
767 return s_qmlBasicTypes;
771
772
780
781
789
790
794 return m_attributions;
798
799
803 return s_obsoleteClasses;
807
808
816
817
818
822 return m_functionIndex;
826
827
828
831 for (
const auto &childNode : node->childNodes()) {
832 if (childNode->isPrivate())
834 if (!childNode->doc().legaleseText().isEmpty())
835 m_legaleseTexts.insert(childNode->doc().legaleseText(), childNode);
836 if (childNode->isAggregate())
837 findAllLegaleseTexts(
static_cast<Aggregate *>(childNode));
842
843
844
845
846
847
850
851
852
853
854
855
856
857
858
861
862
863
864
868 auto it = s_newClassMaps.constFind(key);
873
874
875
876
880 auto it = s_newQmlTypeMaps.constFind(key);
885
886
887
888
892 auto it = s_newSinceMaps.constFind(key);
897
898
899
900
903 const auto &config = Config::instance();
904 if (config.dualExec() || config.preparing()) {
919 if (config.singleExec() && config.generating()) {
926 if (!config.preparing()) {
932 if (config.dualExec())
938 Tree *t = m_forest.firstTree();
940 t->resolveBaseClasses(t->root());
941 t = m_forest.nextTree();
946
947
948
949
950
954 return m_namespaceIndex;
958
959
960
961
962
963
964
967 if (!m_namespaceIndex.isEmpty())
972 Tree *t = m_forest.firstTree();
975 t = m_forest.nextTree();
977 const QList<QString> keys = namespaceMultimap.uniqueKeys();
978 for (
const QString &key : keys) {
979 NamespaceNode *ns =
nullptr;
980 NamespaceNode *indexNamespace =
nullptr;
981 const NodeList namespaces = namespaceMultimap.values(key);
982 qsizetype count = namespaceMultimap.remove(key);
984 for (
auto *node : namespaces) {
985 ns =
static_cast<NamespaceNode *>(node);
986 if (ns->isDocumentedHere())
988 else if (ns->hadDoc())
993 for (
auto *node : namespaces) {
994 auto *nsNode =
static_cast<NamespaceNode *>(node);
995 if (nsNode->hadDoc() && nsNode != ns) {
996 ns->doc().location().warning(
997 QStringLiteral(
"Namespace %1 documented more than once")
998 .arg(nsNode->name()), QStringLiteral(
"also seen here: %1")
999 .arg(nsNode->doc().location().toString()));
1002 }
else if (!indexNamespace) {
1007 for (
auto *node : namespaces) {
1008 if (!node->isIndexNode())
1009 static_cast<NamespaceNode *>(node)->reportDocumentedChildrenInUndocumentedNamespace();
1013 for (
auto *node : namespaces) {
1014 auto *nsNode =
static_cast<NamespaceNode *>(node);
1015 if (nsNode != indexNamespace)
1016 nsNode->setDocNode(indexNamespace);
1021
1022
1023
1024
1025
1026 if (ns && count > 1) {
1027 for (
auto *node : namespaces) {
1028 auto *nameSpaceNode =
static_cast<NamespaceNode *>(node);
1029 if (nameSpaceNode != ns) {
1030 for (
auto it = nameSpaceNode->constBegin(); it != nameSpaceNode->constEnd();
1032 Node *anotherNs = *it;
1033 if (anotherNs && anotherNs->isPublic() && !anotherNs->isInternal())
1034 ns->includeChild(anotherNs);
1040
1041
1042
1044 ns = indexNamespace ? indexNamespace :
static_cast<NamespaceNode *>(namespaces.last());
1045 m_namespaceIndex.insert(ns->name(), ns);
1050
1051
1052
1053
1054
1055
1056
1057
1058
1063 Tree *t = m_forest.firstTree();
1064 t = m_forest.nextTree();
1067 if (!proxies.isEmpty()) {
1068 for (
auto *node : proxies) {
1069 const auto *pn =
static_cast<ProxyNode *>(node);
1070 if (pn->count() > 0) {
1071 Aggregate *aggregate = primaryTree()->findAggregate(pn->name());
1072 if (aggregate !=
nullptr)
1073 aggregate->appendToRelatedByProxy(pn->childNodes());
1077 t = m_forest.nextTree();
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1098 QString function = target;
1099 qsizetype length = target.size();
1100 if (function.endsWith(
"()"))
1102 if (function.endsWith(QChar(
')'))) {
1103 qsizetype position = function.lastIndexOf(QChar(
'('));
1104 signature = function.mid(position + 1, length - position - 2);
1105 function = function.left(position);
1107 QStringList path = function.split(
"::");
1108 return m_forest.findFunctionNode(path, Parameters(signature), relative, genus);
1112
1113
1114
1115
1116
1117
1118
1119
1120
1124 if ((genus == Genus::QML || (relative && relative
->genus() == Genus::QML)) &&
1125 type.contains(
'.') && !type.contains(
"::")) {
1130 for (
const auto &import : imports) {
1131 if (QmlTypeNode *found = findQmlType(import, type)) {
1138 QStringList path = type.split(
".");
1139 if ((path.size() == 1) && (path.at(0)[0].isLower() || path.at(0) == QString(
"T"))) {
1140 auto it = s_typeNodeMap.find(path.at(0));
1141 if (it != s_typeNodeMap.end())
1146 const Node *node = m_forest.findTypeNode(path, relative, genus);
1153 if (path.size() > 1) {
1154 const Node *lastSegmentNode = m_forest.findTypeNode(QStringList{path.last()}, relative, genus);
1156 return lastSegmentNode;
1163 QStringList path = type.split(
"::");
1164 if ((path.size() == 1) && (path.at(0)[0].isLower() || path.at(0) == QString(
"T"))) {
1165 auto it = s_typeNodeMap.find(path.at(0));
1166 if (it != s_typeNodeMap.end())
1169 return m_forest.findTypeNode(path, relative, genus);
1173
1174
1175
1176
1177
1180 const Node *node =
nullptr;
1181 if (target.isEmpty())
1183 else if (target.endsWith(
".html"))
1184 node = findNodeByNameAndType(QStringList(target), &Node::isPageNode);
1186 QStringList path = target.split(
"::");
1188 for (
const auto *tree : searchOrder()) {
1189 const Node *n = tree->findNode(path, relative, flags, Genus::DontCare);
1194 node = findPageNodeByTitle(target);
1207 for (
auto it = m->cbegin(); it != m->cend(); ++it)
1208 if (it.value()->members().contains(node))
1215
1216
1219 QStringList filesToRead;
1220 for (
const QString &file : indexFiles) {
1221 QString fn = file.mid(file.lastIndexOf(QChar(
'/')) + 1);
1223 filesToRead << file;
1225 qCCritical(lcQdoc) <<
"Index file" << file <<
"is already in memory.";
1231
1232
1233
1234
1237 QString t = fileName.mid(fileName.lastIndexOf(QChar(
'/')) + 1);
1239 QDocIndexFiles::qdocIndexFiles()->generateIndex(fileName, url, title);
1244
1245
1246
1247
1256 moduleName = relative->physicalModuleName();
1260 moduleName = relative->logicalModuleName();
1265 if (moduleName.isEmpty())
1268 return primaryTree()->getCollection(moduleName, moduleType);
1272
1273
1274
1275
1280 for (
auto *tree : searchOrder()) {
1281 CNMap *m = tree->getCollectionMap(type);
1282 if (m && !m->isEmpty()) {
1283 for (
auto it = m->cbegin(); it != m->cend(); ++it) {
1284 if (!it.value()->isInternal())
1285 cnmm.insert(it.key(), it.value());
1291 static const QRegularExpression singleDigit(
"\\b([0-9])\\b");
1292 const QStringList keys = cnmm.uniqueKeys();
1293 for (
const auto &key : keys) {
1294 const QList<CollectionNode *> values = cnmm.values(key);
1295 CollectionNode *n =
nullptr;
1296 for (
auto *value : values) {
1297 if (value && value->wasSeen() && value != relative) {
1303 if (values.size() > 1) {
1304 for (CollectionNode *value : values) {
1307 if ((n->isQmlModule())
1308 && n->logicalModuleIdentifier() != value->logicalModuleIdentifier()) {
1309 if (value->wasSeen() && value != relative)
1310 cnm.insert(value->fullTitle().toLower(), value);
1313 for (Node *t : value->members())
1318 QString sortKey = n->fullTitle().toLower();
1319 if (sortKey.startsWith(
"the "))
1320 sortKey.remove(0, 4);
1321 sortKey.replace(singleDigit,
"0\\1");
1322 cnm.insert(sortKey, n);
1328
1329
1330
1331
1332
1333
1334
1335
1380 for (
auto *tree : searchOrder()) {
1381 CollectionNode *cn = tree->getCollection(c->name(), c->nodeType());
1382 if (cn && cn != c) {
1383 if ((cn->isQmlModule())
1384 && cn->logicalModuleIdentifier() != c->logicalModuleIdentifier())
1387 for (
auto *node : cn->members())
1447 if (!c->wasSeen() && cn->wasSeen()) {
1449 c->setTitle(cn->title());
1450 c->setUrl(cn->url());
1459
1460
1461
1462
1463
1464
1465
1466
1470 const Node *node =
nullptr;
1472 Atom *atom =
const_cast<
Atom *>(a);
1473 QStringList targetPath = atom->string().split(QLatin1Char(
'#'));
1474 QString first = targetPath.first().trimmed();
1476 Tree *domain =
nullptr;
1483 if (first.isEmpty())
1486 if (first.endsWith(
".html"))
1487 node = domain->findNodeByNameAndType(QStringList(first), &
Node::isPageNode);
1488 else if (first.endsWith(QChar(
')'))) {
1490 QString function = first;
1491 qsizetype length = first.size();
1492 if (function.endsWith(
"()"))
1494 if (function.endsWith(QChar(
')'))) {
1495 qsizetype position = function.lastIndexOf(QChar(
'('));
1496 signature = function.mid(position + 1, length - position - 2);
1497 function = function.left(position);
1499 QStringList path = function.split(
"::");
1500 node = domain->findFunctionNode(path,
Parameters(signature),
nullptr, genus);
1502 if (node ==
nullptr) {
1504 QStringList nodePath = first.split(
"::");
1506 targetPath.removeFirst();
1507 if (!targetPath.isEmpty())
1508 target = targetPath.takeFirst();
1509 if (relative && relative
->tree()->physicalModuleName() != domain->physicalModuleName())
1511 return domain->findNodeForTarget(nodePath, target, relative, flags, genus, ref);
1514 if (first.endsWith(
".html"))
1515 node = findNodeByNameAndType(QStringList(first), &Node::isPageNode);
1516 else if (first.endsWith(QChar(
')')))
1517 node = findFunctionNode(first, relative, genus);
1518 if (node ==
nullptr) {
1520 if (genus == Genus::QML && first.contains(
'.') && !first.contains(
"::")) {
1522 node = findTypeNode(first, relative, genus);
1525 targetPath.removeFirst();
1526 if (!targetPath.isEmpty()) {
1534 return findNodeForTarget(targetPath, relative, genus, ref);
1538 if (node !=
nullptr && ref.isEmpty()) {
1539 if (!node->url().isEmpty())
1541 targetPath.removeFirst();
1542 if (!targetPath.isEmpty()) {
1552
1553
1554
1555
1556
1557
1558
1559
1563 QList<Tree *> searchOrder =
this->searchOrder();
1582 bool inclusive{Config::instance().get(
1586 const auto tocTitles{Config::instance().get(configVar).asStringList()};
1588 for (
const auto &tocTitle : tocTitles) {
1589 if (
const auto candidateTarget = findNodeForTarget(tocTitle,
nullptr); candidateTarget && candidateTarget->isPageNode()) {
1590 auto tocPage{
static_cast<
const PageNode*>(candidateTarget)};
1592 Text body = tocPage->doc().body();
1594 auto *atom = body.firstAtom();
1596 std::pair<PageNode *, QString> prev {
nullptr, QString() };
1598 std::stack<
const PageNode *> tocStack;
1599 tocStack.push(inclusive ? tocPage :
nullptr);
1601 bool inItem =
false;
1608 switch (atom->type()) {
1609 case Atom::ListItemLeft:
1611 tocStack.push(
nullptr);
1614 case Atom::ListItemRight:
1654 auto candidatePage =
const_cast<Node *>(findNodeForAtom(atom,
nullptr, unused));
1655 if (!candidatePage || !candidatePage->isPageNode())
break;
1657 auto page{
static_cast<PageNode*>(candidatePage)};
1660 if (page == prev.first)
break;
1663 prev.first->setLink(
1704 prev.first->title(),
1709 if (page == tocPage)
1714 qsizetype popped = 0;
1715 while (tocStack.size() > 1 && !tocStack.top()) {
1720 page->setNavigationParent(tocStack.empty() ?
nullptr : tocStack.top());
1722 while (--popped > 0)
1723 tocStack.push(
nullptr);
1725 tocStack.push(page);
1727 prev = { page, atom->linkText() };
1731 case Atom::AnnotatedList:
1732 case Atom::GeneratedList: {
1733 if (
const auto *cn = getCollectionNode(atom->string(), NodeType::Group)) {
1734 const auto sortOrder{Generator::sortOrder(atom->strings().last())};
1735 NodeList members{cn->members()};
1738 members.erase(std::remove_if(members.begin(), members.end(),
1740 return n->isIndexNode() || !n->isPageNode() || n->isExternalPage();
1742 if (members.isEmpty())
1745 if (sortOrder == Qt::DescendingOrder)
1746 std::sort(members.rbegin(), members.rend(), Node::nodeSortKeyOrNameLessThan);
1748 std::sort(members.begin(), members.end(), Node::nodeSortKeyOrNameLessThan);
1753 for (
auto *m : members) {
1754 auto *page =
static_cast<PageNode *>(m);
1755 prev.first->setLink(Node::NextLink, page->title(), page->fullName());
1756 page->setLink(Node::PreviousLink, prev.first->title(), prev.second);
1757 prev = { page, page->fullName() };
1767 atom = atom->next();
1770 Config::instance().get(configVar).location()
1771 .warning(QStringLiteral(
"Failed to find table of contents with title '%1'")
1777 setSearchOrder(searchOrder);
void resolveRelates()
Adopts each non-aggregate C++ node (function/macro, typedef, enum, variable, or a shared comment node...
void resolveQmlInheritance()
Resolves the inheritance information for all QML type children of this aggregate.
void normalizeOverloads()
Sorts the lists of overloads in the function map and assigns overload numbers.
void findAllNamespaces(NodeMultiMap &namespaces)
For each child of this node, if the child is a namespace node, insert the child into the namespaces m...
void markUndocumentedChildrenInternal()
Mark all child nodes that have no documentation as having internal status.
The Atom class is the fundamental unit for representing documents internally.
virtual bool isLinkAtom() const
A class for holding the members of a collection of doc pages.
This node is used to represent any kind of function being documented.
This class represents a C++ namespace.
This class provides exclusive access to the qdoc database, which consists of a forrest of trees and a...
const Node * findTypeNode(const QString &type, const Node *relative, Genus genus)
This function is called for autolinking to a type, which could be a function return type or a paramet...
NodeMapMap & getFunctionIndex()
Returns the function index.
const NodeMultiMap & getClassMap(const QString &key)
Find the key in the map of new class maps, and return a reference to the value, which is a NodeMap.
const NodeMultiMap & getQmlTypeMap(const QString &key)
Find the key in the map of new QML type maps, and return a reference to the value,...
void resolveNamespaces()
Multiple namespace nodes for namespace X can exist in the qdoc database in different trees.
TextToNodeMap & getLegaleseTexts()
Returns a reference to the collection of legalese texts.
QmlTypeNode * findQmlType(const QString &qmid, const QString &name)
Returns the QML type node identified by the QML module id qmid and QML type name, or nullptr if no ty...
NodeMultiMap & getAttributions()
Returns a reference to the multimap of attribution nodes.
static void destroyQdocDB()
Destroys the singleton.
NodeMultiMap & getQmlTypesWithObsoleteMembers()
Returns a reference to the map of QML types with obsolete members.
NodeMultiMap & getObsoleteQmlTypes()
Returns a reference to the map of obsolete QML types.
const FunctionNode * findFunctionNode(const QString &target, const Node *relative, Genus genus)
Finds the function node for the qualified function path in target and returns a pointer to it.
static QDocDatabase * qdocDB()
Creates the singleton.
void resolveBaseClasses()
NodeMultiMap & getQmlTypes()
Returns a reference to the multimap of QML types.
NodeMultiMap & getClassesWithObsoleteMembers()
Returns a reference to the map of C++ classes with obsolete members.
QmlTypeNode * findQmlType(const ImportRec &import, const QString &name)
Returns the QML type node identified by the QML module id constructed from the strings in the import ...
NodeMultiMap & getQmlValueTypes()
Returns a reference to the map of QML basic types.
void generateIndex(const QString &fileName, const QString &url, const QString &title)
Generates a qdoc index file and write it to fileName.
NodeMultiMap & getCppClasses()
Returns a reference to the map of all C++ classes.
QStringList groupNamesForNode(Node *node)
NamespaceNode * primaryTreeRoot()
Returns a pointer to the root node of the primary tree.
void readIndexes(const QStringList &indexFiles)
Reads and parses the qdoc index files listed in indexFiles.
const Node * findNodeForTarget(const QString &target, const Node *relative)
Finds the node that will generate the documentation that contains the target and returns a pointer to...
const Node * findNodeForAtom(const Atom *atom, const Node *relative, QString &ref, Genus genus=Genus::DontCare)
Searches for the node that matches the path in atom and the specified genus.
void mergeCollections(NodeType type, CNMap &cnm, const Node *relative)
Finds all the collection nodes of the specified type and merges them into the collection node map cnm...
NodeMultiMap & getNamespaces()
Returns a reference to the namespace map.
QmlTypeNode * findQmlTypeInPrimaryTree(const QString &qmid, const QString &name)
Returns the QML node identified by the QML module id qmid and name, searching in the primary tree onl...
const NodeMultiMap & getSinceMap(const QString &key)
Find the key in the map of new {since} maps, and return a reference to the value, which is a NodeMult...
NodeMultiMap & getExamples()
Returns a reference to the multimap of example nodes.
void processForest()
This function calls a set of functions for each tree in the forest that has not already been analyzed...
void(QDocDatabase::*)(Aggregate *) FindFunctionPtr
void updateNavigation()
Updates navigation (previous/next page links and the navigation parent) for pages listed in the TOC,...
void resolveStuff()
Performs several housekeeping tasks prior to generating the documentation.
NodeMultiMap & getObsoleteClasses()
Returns a reference to the map of obsolete C++ clases.
const CollectionNode * getModuleNode(const Node *relative)
Returns the collection node representing the module that relative node belongs to,...
void resolveProxies()
Each instance of class Tree that represents an index file must be traversed to find all instances of ...
void mergeCollections(CollectionNode *c)
Finds all the collection nodes with the same name and type as c and merges their members into the mem...
A class representing a forest of Tree objects.
This class handles qdoc index files.
const ImportList & importList() const
This class constructs and maintains a tree of instances of the subclasses of Node.
void markDontDocumentNodes()
The {don't document} map has been loaded with the names of classes and structs in the current module ...
#define CONFIG_NOLINKERRORS
#define CONFIG_NAVIGATION
QMultiMap< QString, CollectionNode * > CNMultiMap
QMap< QString, NodeMultiMap > NodeMultiMapMap
QMap< QString, Node * > NodeMap
QMap< QString, NodeMap > NodeMapMap
QMap< QString, CollectionNode * > CNMap
static NodeMultiMap emptyNodeMultiMap_
QT_BEGIN_NAMESPACE typedef QMultiMap< Text, const Node * > TextToNodeMap
QList< ImportRec > ImportList
The Node class is the base class for all the nodes in QDoc's parse tree.
bool isQmlType() const
Returns true if the node type is QmlType or QmlValueType.
Genus genus() const override
Returns this node's Genus.
virtual bool isPageNode() const
Returns true if this node represents something that generates a documentation page.
virtual Tree * tree() const
Returns a pointer to the Tree this node is in.
A class for parsing and managing a function parameter list.
A record of a linkable target within the documentation.
TargetType
A type of a linkable target record.