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,
int findFlags)
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
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(
"::")) {
1135 const QmlTypeNode *qmlType =
static_cast<
const QmlTypeNode*>(relative);
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
1243
1244
1245
1246
1247
1252 const Generator *generator = hrefGenerator;
1254 generator = Generator::generatorForFormat(u"HTML"_s);
1256 qCWarning(lcQdoc) <<
"Cannot generate index file: no href generator available"
1257 " (HTML generator missing)";
1261 QString t = fileName.mid(fileName.lastIndexOf(QChar(
'/')) + 1);
1263 QDocIndexFiles::qdocIndexFiles()->generateIndex(fileName, url, title, generator);
1268
1269
1270
1271
1280 moduleName = relative->physicalModuleName();
1284 moduleName = relative->logicalModuleName();
1289 if (moduleName.isEmpty())
1292 return primaryTree()->getCollection(moduleName, moduleType);
1296
1297
1298
1299
1304 for (
auto *tree : searchOrder()) {
1305 CNMap *m = tree->getCollectionMap(type);
1306 if (m && !m->isEmpty()) {
1307 for (
auto it = m->cbegin(); it != m->cend(); ++it) {
1308 if (!it.value()->isInternal())
1309 cnmm.insert(it.key(), it.value());
1315 static const QRegularExpression singleDigit(
"\\b([0-9])\\b");
1316 const QStringList keys = cnmm.uniqueKeys();
1317 for (
const auto &key : keys) {
1318 const QList<CollectionNode *> values = cnmm.values(key);
1319 CollectionNode *n =
nullptr;
1320 for (
auto *value : values) {
1321 if (value && value->wasSeen() && value != relative) {
1327 if (values.size() > 1) {
1328 for (CollectionNode *value : values) {
1331 if ((n->isQmlModule())
1332 && n->logicalModuleIdentifier() != value->logicalModuleIdentifier()) {
1333 if (value->wasSeen() && value != relative)
1334 cnm.insert(value->fullTitle().toLower(), value);
1337 for (Node *t : value->members())
1342 QString sortKey = n->fullTitle().toLower();
1343 if (sortKey.startsWith(
"the "))
1344 sortKey.remove(0, 4);
1345 sortKey.replace(singleDigit,
"0\\1");
1346 cnm.insert(sortKey, n);
1352
1353
1354
1355
1356
1357
1358
1359
1404 for (
auto *tree : searchOrder()) {
1405 CollectionNode *cn = tree->getCollection(c->name(), c->nodeType());
1406 if (cn && cn != c) {
1407 if ((cn->isQmlModule())
1408 && cn->logicalModuleIdentifier() != c->logicalModuleIdentifier())
1411 for (
auto *node : cn->members())
1471 if (!c->wasSeen() && cn->wasSeen()) {
1473 c->setTitle(cn->title());
1474 c->setUrl(cn->url());
1483
1484
1485
1486
1487
1488
1489
1490
1494 const Node *node =
nullptr;
1496 Atom *atom =
const_cast<
Atom *>(a);
1497 QStringList targetPath = Utilities::pathAndFragment(atom->string());
1498 QString first = targetPath.first().trimmed();
1500 Tree *domain =
nullptr;
1507 if (first.isEmpty())
1510 if (first.endsWith(
".html"))
1511 node = domain->findNodeByNameAndType(QStringList(first), &
Node::isPageNode);
1512 else if (first.endsWith(QChar(
')'))) {
1514 QString function = first;
1515 qsizetype length = first.size();
1516 if (function.endsWith(
"()"))
1518 if (function.endsWith(QChar(
')'))) {
1519 qsizetype position = function.lastIndexOf(QChar(
'('));
1520 signature = function.mid(position + 1, length - position - 2);
1521 function = function.left(position);
1523 QStringList path = function.split(
"::");
1524 node = domain->findFunctionNode(path,
Parameters(signature),
nullptr, genus);
1526 if (node ==
nullptr) {
1528 QStringList nodePath = first.split(
"::");
1530 targetPath.removeFirst();
1531 if (!targetPath.isEmpty())
1532 target = targetPath.takeFirst();
1533 if (relative && relative
->tree()->physicalModuleName() != domain->physicalModuleName())
1535 return domain->findNodeForTarget(nodePath, target, relative, flags, genus, ref);
1538 if (first.endsWith(
".html"))
1539 node = findNodeByNameAndType(QStringList(first), &Node::isPageNode);
1540 else if (first.endsWith(QChar(
')')))
1541 node = findFunctionNode(first, relative, genus);
1542 if (node ==
nullptr) {
1544 if (genus == Genus::QML && first.contains(
'.') && !first.contains(
"::")) {
1546 node = findTypeNode(first, relative, genus);
1549 targetPath.removeFirst();
1550 if (!targetPath.isEmpty()) {
1558 return findNodeForTarget(targetPath, relative, genus, ref, atom->flags());
1562 if (node !=
nullptr && ref.isEmpty()) {
1563 if (!node->url().isEmpty())
1565 targetPath.removeFirst();
1566 if (!targetPath.isEmpty()) {
1576
1577
1578
1579
1580
1581
1582
1583
1587 QList<Tree *> searchOrder =
this->searchOrder();
1606 bool inclusive{Config::instance().get(
1610 const auto tocTitles{Config::instance().get(configVar).asStringList()};
1612 for (
const auto &tocTitle : tocTitles) {
1613 if (
const auto candidateTarget = findNodeForTarget(tocTitle,
nullptr); candidateTarget && candidateTarget->isPageNode()) {
1614 auto tocPage{
static_cast<
const PageNode*>(candidateTarget)};
1616 Text body = tocPage->doc().body();
1618 auto *atom = body.firstAtom();
1620 std::pair<PageNode *, QString> prev {
nullptr, QString() };
1622 std::stack<
const PageNode *> tocStack;
1623 tocStack.push(inclusive ? tocPage :
nullptr);
1625 bool inItem =
false;
1632 switch (atom->type()) {
1633 case Atom::ListItemLeft:
1635 tocStack.push(
nullptr);
1638 case Atom::ListItemRight:
1678 auto candidatePage =
const_cast<Node *>(findNodeForAtom(atom,
nullptr, unused));
1679 if (!candidatePage || !candidatePage->isPageNode())
break;
1681 auto page{
static_cast<PageNode*>(candidatePage)};
1684 if (page == prev.first)
break;
1687 prev.first->setLink(
1728 prev.first->title(),
1733 if (page == tocPage)
1738 qsizetype popped = 0;
1739 while (tocStack.size() > 1 && !tocStack.top()) {
1744 page->setNavigationParent(tocStack.empty() ?
nullptr : tocStack.top());
1746 while (--popped > 0)
1747 tocStack.push(
nullptr);
1749 tocStack.push(page);
1751 prev = { page, atom->linkText() };
1755 case Atom::AnnotatedList:
1756 case Atom::GeneratedList: {
1757 if (
const auto *cn = getCollectionNode(atom->string(), NodeType::Group)) {
1758 const auto sortOrder{Generator::sortOrder(atom->strings().last())};
1759 NodeList members{cn->members()};
1762 members.erase(std::remove_if(members.begin(), members.end(),
1764 return n->isIndexNode() || !n->isPageNode() || n->isExternalPage();
1766 if (members.isEmpty())
1769 if (sortOrder == Qt::DescendingOrder)
1770 std::sort(members.rbegin(), members.rend(), Node::nodeSortKeyOrNameLessThan);
1772 std::sort(members.begin(), members.end(), Node::nodeSortKeyOrNameLessThan);
1777 for (
auto *m : members) {
1778 auto *page =
static_cast<PageNode *>(m);
1780 prev.first->setLink(Node::NextLink, page->title(), page->fullName());
1781 page->setLink(Node::PreviousLink, prev.first->title(), prev.second);
1783 prev = { page, page->fullName() };
1793 atom = atom->next();
1796 Config::instance().get(configVar).location()
1797 .warning(QStringLiteral(
"Failed to find table of contents with title '%1'")
1803 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.
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...
void generateIndex(const QString &fileName, const QString &url, const QString &title, const Generator *hrefGenerator)
Generates a qdoc index file and writes it to fileName.
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.