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, relative); qcn)
647 if (
auto *qcn = m_forest.lookupQmlType(name, relative); qcn)
651 QStringList path(name);
652 return static_cast<QmlTypeNode *>(m_forest.findNodeByNameAndType(path, &Node::isQmlType));
656
657
658
659
669 if (!record.m_importId.isEmpty()) {
670 const QString namespacePrefix{
"%1."_L1.arg(record.m_importId)};
671 if (!type.startsWith(namespacePrefix))
673 type.remove(0, namespacePrefix.size());
676 const QString qmName = record.m_importUri.isEmpty() ? record.m_moduleName : record.m_importUri;
677 return m_forest.lookupQmlType(qmName + u"::"_s + type, relative);
681
682
683
684
685
686
690 return primaryTree()->lookupQmlType(qmid + u"::"_s + name);
695
696
697
698
699
700
713
714
715
716
717
720 Tree *t = m_forest.firstTree();
722 if (!m_completedFindFunctions.values(t).contains(func)) {
723 (
this->*(func))(t->root());
724 m_completedFindFunctions.insert(t, func);
726 t = m_forest.nextTree();
731
732
736 return m_legaleseTexts;
740
741
745 return s_classesWithObsoleteMembers;
749
750
754 return s_obsoleteQmlTypes;
758
759
763 return s_qmlTypesWithObsoleteMembers;
767
768
772 return s_qmlBasicTypes;
776
777
785
786
794
795
799 return m_attributions;
803
804
808 return s_obsoleteClasses;
812
813
821
822
823
827 return m_functionIndex;
831
832
833
836 for (
const auto &childNode : node->childNodes()) {
837 if (childNode->isPrivate())
839 if (!childNode->doc().legaleseText().isEmpty())
840 m_legaleseTexts.insert(childNode->doc().legaleseText(), childNode);
841 if (childNode->isAggregate())
842 findAllLegaleseTexts(
static_cast<Aggregate *>(childNode));
847
848
849
850
851
852
855
856
857
858
859
860
861
862
863
866
867
868
869
873 auto it = s_newClassMaps.constFind(key);
878
879
880
881
885 auto it = s_newQmlTypeMaps.constFind(key);
890
891
892
893
897 auto it = s_newSinceMaps.constFind(key);
902
903
904
905
908 const auto &config = Config::instance();
909 if (config.dualExec() || config.preparing()) {
925 if (config.singleExec() && config.generating()) {
932 if (!config.preparing()) {
938 if (config.dualExec())
944 Tree *t = m_forest.firstTree();
946 t->resolveBaseClasses(t->root());
949 t = m_forest.nextTree();
954
955
956
957
958
962 return m_namespaceIndex;
966
967
968
969
970
971
972
975 if (!m_namespaceIndex.isEmpty())
980 Tree *t = m_forest.firstTree();
983 t = m_forest.nextTree();
985 const QList<QString> keys = namespaceMultimap.uniqueKeys();
986 for (
const QString &key : keys) {
987 NamespaceNode *ns =
nullptr;
988 NamespaceNode *indexNamespace =
nullptr;
989 const NodeList namespaces = namespaceMultimap.values(key);
990 qsizetype count = namespaceMultimap.remove(key);
992 for (
auto *node : namespaces) {
993 ns =
static_cast<NamespaceNode *>(node);
994 if (ns->isDocumentedHere())
996 else if (ns->hadDoc())
1001 for (
auto *node : namespaces) {
1002 auto *nsNode =
static_cast<NamespaceNode *>(node);
1003 if (nsNode->hadDoc() && nsNode != ns) {
1004 ns->doc().location().warning(
1005 QStringLiteral(
"Namespace %1 documented more than once")
1006 .arg(nsNode->name()), QStringLiteral(
"also seen here: %1")
1007 .arg(nsNode->doc().location().toString()));
1010 }
else if (!indexNamespace) {
1015 for (
auto *node : namespaces) {
1016 if (!node->isIndexNode())
1017 static_cast<NamespaceNode *>(node)->reportDocumentedChildrenInUndocumentedNamespace();
1021 for (
auto *node : namespaces) {
1022 auto *nsNode =
static_cast<NamespaceNode *>(node);
1023 if (nsNode != indexNamespace)
1024 nsNode->setDocNode(indexNamespace);
1029
1030
1031
1032
1033
1034 if (ns && count > 1) {
1035 for (
auto *node : namespaces) {
1036 auto *nameSpaceNode =
static_cast<NamespaceNode *>(node);
1037 if (nameSpaceNode != ns) {
1038 for (
auto it = nameSpaceNode->constBegin(); it != nameSpaceNode->constEnd();
1040 Node *anotherNs = *it;
1041 if (anotherNs && anotherNs->isPublic() && !anotherNs->isInternal())
1042 ns->includeChild(anotherNs);
1048
1049
1050
1052 ns = indexNamespace ? indexNamespace :
static_cast<NamespaceNode *>(namespaces.last());
1053 m_namespaceIndex.insert(ns->name(), ns);
1058
1059
1060
1061
1062
1063
1064
1065
1066
1071 Tree *t = m_forest.firstTree();
1072 t = m_forest.nextTree();
1075 if (!proxies.isEmpty()) {
1076 for (
auto *node : proxies) {
1077 const auto *pn =
static_cast<ProxyNode *>(node);
1078 if (pn->count() > 0) {
1079 Aggregate *aggregate = primaryTree()->findAggregate(pn->name());
1080 if (aggregate !=
nullptr)
1081 aggregate->appendToRelatedByProxy(pn->childNodes());
1085 t = m_forest.nextTree();
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1106 QString function = target;
1107 qsizetype length = target.size();
1108 if (function.endsWith(
"()"))
1110 if (function.endsWith(QChar(
')'))) {
1111 qsizetype position = function.lastIndexOf(QChar(
'('));
1112 signature = function.mid(position + 1, length - position - 2);
1113 function = function.left(position);
1115 QStringList path = function.split(
"::");
1116 return m_forest.findFunctionNode(path, Parameters(signature), relative, genus);
1120
1121
1122
1123
1124
1125
1126
1127
1128
1132 if ((genus == Genus::QML || (relative && relative
->genus() == Genus::QML)) &&
1133 type.contains(
'.') && !type.contains(
"::")) {
1138 for (
const auto &import : imports) {
1139 if (QmlTypeNode *found = findQmlType(import, type)) {
1146 QStringList path = type.split(
".");
1147 if ((path.size() == 1) && (path.at(0)[0].isLower() || path.at(0) == QString(
"T"))) {
1148 auto it = s_typeNodeMap.find(path.at(0));
1149 if (it != s_typeNodeMap.end())
1154 const Node *node = m_forest.findTypeNode(path, relative, genus);
1161 if (path.size() > 1) {
1162 const Node *lastSegmentNode = m_forest.findTypeNode(QStringList{path.last()}, relative, genus);
1164 return lastSegmentNode;
1171 QStringList path = type.split(
"::");
1172 if ((path.size() == 1) && (path.at(0)[0].isLower() || path.at(0) == QString(
"T"))) {
1173 auto it = s_typeNodeMap.find(path.at(0));
1174 if (it != s_typeNodeMap.end())
1177 return m_forest.findTypeNode(path, relative, genus);
1181
1182
1183
1184
1185
1188 const Node *node =
nullptr;
1189 if (target.isEmpty())
1191 else if (target.endsWith(
".html"))
1192 node = findNodeByNameAndType(QStringList(target), &Node::isPageNode);
1194 QStringList path = target.split(
"::");
1196 for (
const auto *tree : searchOrder()) {
1197 const Node *n = tree->findNode(path, relative, flags, Genus::DontCare);
1202 node = findPageNodeByTitle(target);
1215 for (
auto it = m->cbegin(); it != m->cend(); ++it)
1216 if (it.value()->members().contains(node))
1223
1224
1227 QStringList filesToRead;
1228 for (
const QString &file : indexFiles) {
1229 QString fn = file.mid(file.lastIndexOf(QChar(
'/')) + 1);
1231 filesToRead << file;
1233 qCCritical(lcQdoc) <<
"Index file" << file <<
"is already in memory.";
1239
1240
1241
1242
1245 QString t = fileName.mid(fileName.lastIndexOf(QChar(
'/')) + 1);
1247 QDocIndexFiles::qdocIndexFiles()->generateIndex(fileName, url, title);
1252
1253
1254
1255
1264 moduleName = relative->physicalModuleName();
1268 moduleName = relative->logicalModuleName();
1273 if (moduleName.isEmpty())
1276 return primaryTree()->getCollection(moduleName, moduleType);
1280
1281
1282
1283
1288 for (
auto *tree : searchOrder()) {
1289 CNMap *m = tree->getCollectionMap(type);
1290 if (m && !m->isEmpty()) {
1291 for (
auto it = m->cbegin(); it != m->cend(); ++it) {
1292 if (!it.value()->isInternal())
1293 cnmm.insert(it.key(), it.value());
1299 static const QRegularExpression singleDigit(
"\\b([0-9])\\b");
1300 const QStringList keys = cnmm.uniqueKeys();
1301 for (
const auto &key : keys) {
1302 const QList<CollectionNode *> values = cnmm.values(key);
1303 CollectionNode *n =
nullptr;
1304 for (
auto *value : values) {
1305 if (value && value->wasSeen() && value != relative) {
1311 if (values.size() > 1) {
1312 for (CollectionNode *value : values) {
1315 if ((n->isQmlModule())
1316 && n->logicalModuleIdentifier() != value->logicalModuleIdentifier()) {
1317 if (value->wasSeen() && value != relative)
1318 cnm.insert(value->fullTitle().toLower(), value);
1321 for (Node *t : value->members())
1326 QString sortKey = n->fullTitle().toLower();
1327 if (sortKey.startsWith(
"the "))
1328 sortKey.remove(0, 4);
1329 sortKey.replace(singleDigit,
"0\\1");
1330 cnm.insert(sortKey, n);
1336
1337
1338
1339
1340
1341
1342
1343
1388 for (
auto *tree : searchOrder()) {
1389 CollectionNode *cn = tree->getCollection(c->name(), c->nodeType());
1390 if (cn && cn != c) {
1391 if ((cn->isQmlModule())
1392 && cn->logicalModuleIdentifier() != c->logicalModuleIdentifier())
1395 for (
auto *node : cn->members())
1455 if (!c->wasSeen() && cn->wasSeen()) {
1457 c->setTitle(cn->title());
1458 c->setUrl(cn->url());
1467
1468
1469
1470
1471
1472
1473
1474
1478 const Node *node =
nullptr;
1480 Atom *atom =
const_cast<
Atom *>(a);
1481 QStringList targetPath = atom->string().split(QLatin1Char(
'#'));
1482 QString first = targetPath.first().trimmed();
1484 Tree *domain =
nullptr;
1491 if (first.isEmpty())
1494 if (first.endsWith(
".html"))
1495 node = domain->findNodeByNameAndType(QStringList(first), &
Node::isPageNode);
1496 else if (first.endsWith(QChar(
')'))) {
1498 QString function = first;
1499 qsizetype length = first.size();
1500 if (function.endsWith(
"()"))
1502 if (function.endsWith(QChar(
')'))) {
1503 qsizetype position = function.lastIndexOf(QChar(
'('));
1504 signature = function.mid(position + 1, length - position - 2);
1505 function = function.left(position);
1507 QStringList path = function.split(
"::");
1508 node = domain->findFunctionNode(path,
Parameters(signature),
nullptr, genus);
1510 if (node ==
nullptr) {
1512 QStringList nodePath = first.split(
"::");
1514 targetPath.removeFirst();
1515 if (!targetPath.isEmpty())
1516 target = targetPath.takeFirst();
1517 if (relative && relative
->tree()->physicalModuleName() != domain->physicalModuleName())
1519 return domain->findNodeForTarget(nodePath, target, relative, flags, genus, ref);
1522 if (first.endsWith(
".html"))
1523 node = findNodeByNameAndType(QStringList(first), &Node::isPageNode);
1524 else if (first.endsWith(QChar(
')')))
1525 node = findFunctionNode(first, relative, genus);
1526 if (node ==
nullptr) {
1528 if (genus == Genus::QML && first.contains(
'.') && !first.contains(
"::")) {
1530 node = findTypeNode(first, relative, genus);
1533 targetPath.removeFirst();
1534 if (!targetPath.isEmpty()) {
1542 return findNodeForTarget(targetPath, relative, genus, ref);
1546 if (node !=
nullptr && ref.isEmpty()) {
1547 if (!node->url().isEmpty())
1549 targetPath.removeFirst();
1550 if (!targetPath.isEmpty()) {
1560
1561
1562
1563
1564
1565
1566
1567
1571 QList<Tree *> searchOrder =
this->searchOrder();
1590 bool inclusive{Config::instance().get(
1594 const auto tocTitles{Config::instance().get(configVar).asStringList()};
1596 for (
const auto &tocTitle : tocTitles) {
1597 if (
const auto candidateTarget = findNodeForTarget(tocTitle,
nullptr); candidateTarget && candidateTarget->isPageNode()) {
1598 auto tocPage{
static_cast<
const PageNode*>(candidateTarget)};
1600 Text body = tocPage->doc().body();
1602 auto *atom = body.firstAtom();
1604 std::pair<PageNode *, QString> prev {
nullptr, QString() };
1606 std::stack<
const PageNode *> tocStack;
1607 tocStack.push(inclusive ? tocPage :
nullptr);
1609 bool inItem =
false;
1616 switch (atom->type()) {
1617 case Atom::ListItemLeft:
1619 tocStack.push(
nullptr);
1622 case Atom::ListItemRight:
1662 auto candidatePage =
const_cast<Node *>(findNodeForAtom(atom,
nullptr, unused));
1663 if (!candidatePage || !candidatePage->isPageNode())
break;
1665 auto page{
static_cast<PageNode*>(candidatePage)};
1668 if (page == prev.first)
break;
1671 prev.first->setLink(
1712 prev.first->title(),
1717 if (page == tocPage)
1722 qsizetype popped = 0;
1723 while (tocStack.size() > 1 && !tocStack.top()) {
1728 page->setNavigationParent(tocStack.empty() ?
nullptr : tocStack.top());
1730 while (--popped > 0)
1731 tocStack.push(
nullptr);
1733 tocStack.push(page);
1735 prev = { page, atom->linkText() };
1739 case Atom::AnnotatedList:
1740 case Atom::GeneratedList: {
1741 if (
const auto *cn = getCollectionNode(atom->string(), NodeType::Group)) {
1742 const auto sortOrder{Generator::sortOrder(atom->strings().last())};
1743 NodeList members{cn->members()};
1746 members.erase(std::remove_if(members.begin(), members.end(),
1748 return n->isIndexNode() || !n->isPageNode() || n->isExternalPage();
1750 if (members.isEmpty())
1753 if (sortOrder == Qt::DescendingOrder)
1754 std::sort(members.rbegin(), members.rend(), Node::nodeSortKeyOrNameLessThan);
1756 std::sort(members.begin(), members.end(), Node::nodeSortKeyOrNameLessThan);
1761 for (
auto *m : members) {
1762 auto *page =
static_cast<PageNode *>(m);
1763 prev.first->setLink(Node::NextLink, page->title(), page->fullName());
1764 page->setLink(Node::PreviousLink, prev.first->title(), prev.second);
1765 prev = { page, page->fullName() };
1775 atom = atom->next();
1778 Config::instance().get(configVar).location()
1779 .warning(QStringLiteral(
"Failed to find table of contents with title '%1'")
1785 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.
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.
QmlTypeNode * findQmlType(const QString &qmid, const QString &name, const Node *relative=nullptr)
Returns the QML type node identified by the QML module id qmid and QML type name, or nullptr if no ty...
QmlTypeNode * findQmlType(const ImportRec &import, const QString &name, const Node *relative=nullptr)
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.
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.