17#include <QtCore/qregularexpression.h>
22using namespace Qt::StringLiterals;
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
59
60
63
64
65
66
67
68
71 for (
auto *entry : m_searchOrder)
74 m_searchOrder.clear();
75 m_indexSearchOrder.clear();
76 m_moduleNames.clear();
77 m_primaryTree =
nullptr;
81
82
83
84
88 return (!searchOrder().isEmpty() ? searchOrder()[0] :
nullptr);
92
93
94
95
99 return (m_currentIndex < searchOrder().size() ? searchOrder()[m_currentIndex] :
nullptr);
103
104
105
106
109
110
111
112
113
114
115
116
117void QDocForest::setPrimaryTree(
const QString &t)
119 QString T = t.toLower();
120 m_primaryTree = findTree(T);
122 if (m_primaryTree ==
nullptr)
123 qCCritical(lcQdoc) <<
"Error: Could not set primary tree to" << t;
127
128
129
130void QDocForest::setSearchOrder(
const QStringList &t)
132 if (!m_searchOrder.isEmpty())
136 m_searchOrder.reserve(m_forest.size() + 1);
137 m_searchOrder.clear();
138 m_moduleNames.reserve(m_forest.size() + 1);
139 m_moduleNames.clear();
142 QString primaryName = primaryTree()->physicalModuleName();
143 m_searchOrder.append(m_primaryTree);
144 m_moduleNames.append(primaryName);
145 m_forest.remove(primaryName);
147 for (
const QString &m : t) {
148 if (primaryName != m) {
149 auto it = m_forest.find(m);
150 if (it != m_forest.end()) {
151 m_searchOrder.append(it.value());
152 m_moduleNames.append(m);
158
159
160
161
162 if (!m_forest.isEmpty()) {
163 for (
auto it = m_forest.begin(); it != m_forest.end(); ++it) {
164 m_searchOrder.append(it.value());
165 m_moduleNames.append(it.key());
171
172
173
174
175
176
177
178 for (
int i = 0; i < m_searchOrder.size(); ++i) {
179 if (!m_forest.contains(m_moduleNames.at(i))) {
180 m_forest.insert(m_moduleNames.at(i), m_searchOrder.at(i));
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
212 if (m_searchOrder.isEmpty())
213 return indexSearchOrder();
214 return m_searchOrder;
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232const QList<Tree *> &
QDocForest::indexSearchOrder()
234 if (m_forest.size() > m_indexSearchOrder.size())
235 m_indexSearchOrder.prepend(m_primaryTree);
236 return m_indexSearchOrder;
240
241
242
243
246 m_primaryTree =
new Tree(module, m_qdb);
247 m_forest.insert(module.toLower(), m_primaryTree);
248 return m_primaryTree->root();
252
253
254
255void QDocForest::newPrimaryTree(
const QString &module)
257 m_primaryTree =
new Tree(module, m_qdb);
261
262
263
264
265
266
267
268
269
270
271
272
273
274const Node *
QDocForest::findNodeForTarget(QStringList &targetPath,
const Node *relative,
275 Genus genus, QString &ref,
int findFlags)
279 QString entity = targetPath.takeFirst();
280 QStringList entityPath = entity.split(
"::");
283 if (!targetPath.isEmpty())
284 target = targetPath.takeFirst();
287 const Node *tocNode =
nullptr;
288 for (
const auto *tree : searchOrder()) {
289 const Node *n = tree->findNodeForTarget(entityPath, target, relative, flags, genus, ref, &type);
292 if (type != TargetRec::Contents)
303
304
305
306
307
308
309
310
311
316 for (
const auto *tree : searchOrder()) {
317 const FunctionNode *fn = tree->findFunctionNode(path, parameters, relative, genus);
326
327
328
329
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
368
369
370
373 if (s_qdocDB ==
nullptr) {
381
382
385 if (s_qdocDB !=
nullptr) {
392
393
394
395
396
397
398
399
400
401
402
403
404
407 s_typeNodeMap.insert(
"accepted",
nullptr);
408 s_typeNodeMap.insert(
"actionPerformed",
nullptr);
409 s_typeNodeMap.insert(
"activated",
nullptr);
410 s_typeNodeMap.insert(
"alias",
nullptr);
411 s_typeNodeMap.insert(
"anchors",
nullptr);
412 s_typeNodeMap.insert(
"any",
nullptr);
413 s_typeNodeMap.insert(
"array",
nullptr);
414 s_typeNodeMap.insert(
"autoSearch",
nullptr);
415 s_typeNodeMap.insert(
"axis",
nullptr);
416 s_typeNodeMap.insert(
"backClicked",
nullptr);
417 s_typeNodeMap.insert(
"boomTime",
nullptr);
418 s_typeNodeMap.insert(
"border",
nullptr);
419 s_typeNodeMap.insert(
"buttonClicked",
nullptr);
420 s_typeNodeMap.insert(
"callback",
nullptr);
421 s_typeNodeMap.insert(
"char",
nullptr);
422 s_typeNodeMap.insert(
"clicked",
nullptr);
423 s_typeNodeMap.insert(
"close",
nullptr);
424 s_typeNodeMap.insert(
"closed",
nullptr);
425 s_typeNodeMap.insert(
"cond",
nullptr);
426 s_typeNodeMap.insert(
"data",
nullptr);
427 s_typeNodeMap.insert(
"dataReady",
nullptr);
428 s_typeNodeMap.insert(
"dateString",
nullptr);
429 s_typeNodeMap.insert(
"dateTimeString",
nullptr);
430 s_typeNodeMap.insert(
"datetime",
nullptr);
431 s_typeNodeMap.insert(
"day",
nullptr);
432 s_typeNodeMap.insert(
"deactivated",
nullptr);
433 s_typeNodeMap.insert(
"drag",
nullptr);
434 s_typeNodeMap.insert(
"easing",
nullptr);
435 s_typeNodeMap.insert(
"error",
nullptr);
436 s_typeNodeMap.insert(
"exposure",
nullptr);
437 s_typeNodeMap.insert(
"fatalError",
nullptr);
438 s_typeNodeMap.insert(
"fileSelected",
nullptr);
439 s_typeNodeMap.insert(
"flags",
nullptr);
440 s_typeNodeMap.insert(
"float",
nullptr);
441 s_typeNodeMap.insert(
"focus",
nullptr);
442 s_typeNodeMap.insert(
"focusZone",
nullptr);
443 s_typeNodeMap.insert(
"format",
nullptr);
444 s_typeNodeMap.insert(
"framePainted",
nullptr);
445 s_typeNodeMap.insert(
"from",
nullptr);
446 s_typeNodeMap.insert(
"frontClicked",
nullptr);
447 s_typeNodeMap.insert(
"function",
nullptr);
448 s_typeNodeMap.insert(
"hasOpened",
nullptr);
449 s_typeNodeMap.insert(
"hovered",
nullptr);
450 s_typeNodeMap.insert(
"hoveredTitle",
nullptr);
451 s_typeNodeMap.insert(
"hoveredUrl",
nullptr);
452 s_typeNodeMap.insert(
"imageCapture",
nullptr);
453 s_typeNodeMap.insert(
"imageProcessing",
nullptr);
454 s_typeNodeMap.insert(
"index",
nullptr);
455 s_typeNodeMap.insert(
"initialized",
nullptr);
456 s_typeNodeMap.insert(
"isLoaded",
nullptr);
457 s_typeNodeMap.insert(
"item",
nullptr);
458 s_typeNodeMap.insert(
"key",
nullptr);
459 s_typeNodeMap.insert(
"keysequence",
nullptr);
460 s_typeNodeMap.insert(
"listViewClicked",
nullptr);
461 s_typeNodeMap.insert(
"loadRequest",
nullptr);
462 s_typeNodeMap.insert(
"locale",
nullptr);
463 s_typeNodeMap.insert(
"location",
nullptr);
464 s_typeNodeMap.insert(
"long",
nullptr);
465 s_typeNodeMap.insert(
"message",
nullptr);
466 s_typeNodeMap.insert(
"messageReceived",
nullptr);
467 s_typeNodeMap.insert(
"mode",
nullptr);
468 s_typeNodeMap.insert(
"month",
nullptr);
469 s_typeNodeMap.insert(
"name",
nullptr);
470 s_typeNodeMap.insert(
"number",
nullptr);
471 s_typeNodeMap.insert(
"object",
nullptr);
472 s_typeNodeMap.insert(
"offset",
nullptr);
473 s_typeNodeMap.insert(
"ok",
nullptr);
474 s_typeNodeMap.insert(
"openCamera",
nullptr);
475 s_typeNodeMap.insert(
"openImage",
nullptr);
476 s_typeNodeMap.insert(
"openVideo",
nullptr);
477 s_typeNodeMap.insert(
"padding",
nullptr);
478 s_typeNodeMap.insert(
"parent",
nullptr);
479 s_typeNodeMap.insert(
"path",
nullptr);
480 s_typeNodeMap.insert(
"photoModeSelected",
nullptr);
481 s_typeNodeMap.insert(
"position",
nullptr);
482 s_typeNodeMap.insert(
"precision",
nullptr);
483 s_typeNodeMap.insert(
"presetClicked",
nullptr);
484 s_typeNodeMap.insert(
"preview",
nullptr);
485 s_typeNodeMap.insert(
"previewSelected",
nullptr);
486 s_typeNodeMap.insert(
"progress",
nullptr);
487 s_typeNodeMap.insert(
"puzzleLost",
nullptr);
488 s_typeNodeMap.insert(
"qmlSignal",
nullptr);
489 s_typeNodeMap.insert(
"rectangle",
nullptr);
490 s_typeNodeMap.insert(
"request",
nullptr);
491 s_typeNodeMap.insert(
"requestId",
nullptr);
492 s_typeNodeMap.insert(
"section",
nullptr);
493 s_typeNodeMap.insert(
"selected",
nullptr);
494 s_typeNodeMap.insert(
"send",
nullptr);
495 s_typeNodeMap.insert(
"settingsClicked",
nullptr);
496 s_typeNodeMap.insert(
"shoe",
nullptr);
497 s_typeNodeMap.insert(
"short",
nullptr);
498 s_typeNodeMap.insert(
"signed",
nullptr);
499 s_typeNodeMap.insert(
"sizeChanged",
nullptr);
500 s_typeNodeMap.insert(
"size_t",
nullptr);
501 s_typeNodeMap.insert(
"sockaddr",
nullptr);
502 s_typeNodeMap.insert(
"someOtherSignal",
nullptr);
503 s_typeNodeMap.insert(
"sourceSize",
nullptr);
504 s_typeNodeMap.insert(
"startButtonClicked",
nullptr);
505 s_typeNodeMap.insert(
"state",
nullptr);
506 s_typeNodeMap.insert(
"std::initializer_list",
nullptr);
507 s_typeNodeMap.insert(
"std::list",
nullptr);
508 s_typeNodeMap.insert(
"std::map",
nullptr);
509 s_typeNodeMap.insert(
"std::pair",
nullptr);
510 s_typeNodeMap.insert(
"std::string",
nullptr);
511 s_typeNodeMap.insert(
"std::vector",
nullptr);
512 s_typeNodeMap.insert(
"stringlist",
nullptr);
513 s_typeNodeMap.insert(
"swapPlayers",
nullptr);
514 s_typeNodeMap.insert(
"symbol",
nullptr);
515 s_typeNodeMap.insert(
"t",
nullptr);
516 s_typeNodeMap.insert(
"T",
nullptr);
517 s_typeNodeMap.insert(
"tagChanged",
nullptr);
518 s_typeNodeMap.insert(
"timeString",
nullptr);
519 s_typeNodeMap.insert(
"timeout",
nullptr);
520 s_typeNodeMap.insert(
"to",
nullptr);
521 s_typeNodeMap.insert(
"toggled",
nullptr);
522 s_typeNodeMap.insert(
"type",
nullptr);
523 s_typeNodeMap.insert(
"unsigned",
nullptr);
524 s_typeNodeMap.insert(
"urllist",
nullptr);
525 s_typeNodeMap.insert(
"va_list",
nullptr);
526 s_typeNodeMap.insert(
"value",
nullptr);
527 s_typeNodeMap.insert(
"valueEmitted",
nullptr);
528 s_typeNodeMap.insert(
"videoFramePainted",
nullptr);
529 s_typeNodeMap.insert(
"videoModeSelected",
nullptr);
530 s_typeNodeMap.insert(
"videoRecorder",
nullptr);
531 s_typeNodeMap.insert(
"void",
nullptr);
532 s_typeNodeMap.insert(
"volatile",
nullptr);
533 s_typeNodeMap.insert(
"wchar_t",
nullptr);
534 s_typeNodeMap.insert(
"x",
nullptr);
535 s_typeNodeMap.insert(
"y",
nullptr);
536 s_typeNodeMap.insert(
"zoom",
nullptr);
537 s_typeNodeMap.insert(
"zoomTo",
nullptr);
541
542
545
546
547
548
551
552
553
554
557
558
559
560
563
564
565
566
567
568
569
572
573
574
575
576
577
578
581
582
583
584
585
586
589
590
591
592
593
594
597
598
599
600
601
602
605
606
607
608
609
610
611
612
615
616
617
618
619
620
623
624
625
626
629
630
631
634
635
636
637
638
639
640
643 if (!qmid.isEmpty()) {
644 if (
auto *qcn = m_forest.lookupQmlType(qmid + u"::"_s + name, relative); qcn)
649 if (
auto *qcn = m_forest.lookupQmlType(name, relative); qcn)
653 QStringList path(name);
654 return static_cast<QmlTypeNode *>(m_forest.findNodeByNameAndType(path, &Node::isQmlType));
658
659
660
661
671 if (!record.m_importId.isEmpty()) {
672 const QString namespacePrefix{
"%1."_L1.arg(record.m_importId)};
673 if (!type.startsWith(namespacePrefix))
675 type.remove(0, namespacePrefix.size());
678 const QString qmName = record.m_importUri.isEmpty() ? record.m_moduleName : record.m_importUri;
679 return m_forest.lookupQmlType(qmName + u"::"_s + type, relative);
683
684
685
686
687
688
697
698
699
700
701
702
715
716
717
718
719
722 Tree *t = m_forest.firstTree();
724 if (!m_completedFindFunctions.values(t).contains(func)) {
725 (
this->*(func))(t->root());
726 m_completedFindFunctions.insert(t, func);
728 t = m_forest.nextTree();
733
734
738 return m_legaleseTexts;
742
743
747 return s_classesWithObsoleteMembers;
751
752
756 return s_obsoleteQmlTypes;
760
761
765 return s_qmlTypesWithObsoleteMembers;
769
770
774 return s_qmlBasicTypes;
778
779
787
788
796
797
801 return m_attributions;
805
806
810 return s_obsoleteClasses;
814
815
823
824
825
829 return m_functionIndex;
833
834
835
838 for (
const auto &childNode : node->childNodes()) {
839 if (childNode->isPrivate())
841 if (!childNode->doc().legaleseText().isEmpty())
842 m_legaleseTexts.insert(childNode->doc().legaleseText(), childNode);
843 if (childNode->isAggregate())
844 findAllLegaleseTexts(
static_cast<Aggregate *>(childNode));
849
850
851
852
853
854
857
858
859
860
861
862
863
864
865
868
869
870
871
875 auto it = s_newClassMaps.constFind(key);
880
881
882
883
887 auto it = s_newQmlTypeMaps.constFind(key);
892
893
894
895
899 auto it = s_newSinceMaps.constFind(key);
904
905
906
907
910 const auto &config = Config::instance();
911 if (config.dualExec() || config.preparing()) {
927 if (config.singleExec() && config.generating()) {
934 if (!config.preparing()) {
940 if (config.dualExec())
946 Tree *t = m_forest.firstTree();
948 t->resolveBaseClasses(t->root());
951 t = m_forest.nextTree();
956
957
958
959
960
964 return m_namespaceIndex;
968
969
970
971
972
973
974
977 if (!m_namespaceIndex.isEmpty())
982 Tree *t = m_forest.firstTree();
985 t = m_forest.nextTree();
987 const QList<QString> keys = namespaceMultimap.uniqueKeys();
988 for (
const QString &key : keys) {
989 NamespaceNode *ns =
nullptr;
990 NamespaceNode *indexNamespace =
nullptr;
991 const NodeList namespaces = namespaceMultimap.values(key);
992 qsizetype count = namespaceMultimap.remove(key);
994 for (
auto *node : namespaces) {
995 ns =
static_cast<NamespaceNode *>(node);
996 if (ns->isDocumentedHere())
998 else if (ns->hadDoc())
1003 for (
auto *node : namespaces) {
1004 auto *nsNode =
static_cast<NamespaceNode *>(node);
1005 if (nsNode->hadDoc() && nsNode != ns) {
1006 ns->doc().location().warning(
1007 QStringLiteral(
"Namespace %1 documented more than once")
1008 .arg(nsNode->name()), QStringLiteral(
"also seen here: %1")
1009 .arg(nsNode->doc().location().toString()));
1012 }
else if (!indexNamespace) {
1017 for (
auto *node : namespaces) {
1018 if (!node->isIndexNode())
1019 static_cast<NamespaceNode *>(node)->reportDocumentedChildrenInUndocumentedNamespace();
1023 for (
auto *node : namespaces) {
1024 auto *nsNode =
static_cast<NamespaceNode *>(node);
1025 if (nsNode != indexNamespace)
1026 nsNode->setDocNode(indexNamespace);
1031
1032
1033
1034
1035
1036 if (ns && count > 1) {
1037 for (
auto *node : namespaces) {
1038 auto *nameSpaceNode =
static_cast<NamespaceNode *>(node);
1039 if (nameSpaceNode != ns) {
1040 for (
auto it = nameSpaceNode->constBegin(); it != nameSpaceNode->constEnd();
1042 Node *anotherNs = *it;
1043 if (anotherNs && anotherNs->isPublic() && !anotherNs->isInternal())
1044 ns->includeChild(anotherNs);
1050
1051
1052
1054 ns = indexNamespace ? indexNamespace :
static_cast<NamespaceNode *>(namespaces.last());
1055 m_namespaceIndex.insert(ns->name(), ns);
1060
1061
1062
1063
1064
1065
1066
1067
1068
1073 Tree *t = m_forest.firstTree();
1074 t = m_forest.nextTree();
1077 if (!proxies.isEmpty()) {
1078 for (
auto *node : proxies) {
1079 const auto *pn =
static_cast<ProxyNode *>(node);
1080 if (pn->count() > 0) {
1081 Aggregate *aggregate = primaryTree()->findAggregate(pn->name());
1082 if (aggregate !=
nullptr)
1083 aggregate->appendToRelatedByProxy(pn->childNodes());
1087 t = m_forest.nextTree();
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1108 QString function = target;
1109 qsizetype length = target.size();
1110 if (function.endsWith(
"()"))
1112 if (function.endsWith(QChar(
')'))) {
1113 qsizetype position = function.lastIndexOf(QChar(
'('));
1114 signature = function.mid(position + 1, length - position - 2);
1115 function = function.left(position);
1117 QStringList path = function.split(
"::");
1118 return m_forest.findFunctionNode(path, Parameters(signature), relative, genus);
1122
1123
1124
1125
1126
1127
1128
1129
1130
1134 if ((genus == Genus::QML || (relative && relative
->genus() == Genus::QML)) &&
1135 type.contains(
'.') && !type.contains(
"::")) {
1137 const QmlTypeNode *qmlType =
static_cast<
const QmlTypeNode*>(relative);
1140 for (
const auto &import : imports) {
1141 if (QmlTypeNode *found = findQmlType(import, type)) {
1148 QStringList path = type.split(
".");
1149 if ((path.size() == 1) && (path.at(0)[0].isLower() || path.at(0) == QString(
"T"))) {
1150 auto it = s_typeNodeMap.find(path.at(0));
1151 if (it != s_typeNodeMap.end())
1156 const Node *node = m_forest.findTypeNode(path, relative, genus);
1163 if (path.size() > 1) {
1164 const Node *lastSegmentNode = m_forest.findTypeNode(QStringList{path.last()}, relative, genus);
1166 return lastSegmentNode;
1173 QStringList path = type.split(
"::");
1174 if ((path.size() == 1) && (path.at(0)[0].isLower() || path.at(0) == QString(
"T"))) {
1175 auto it = s_typeNodeMap.find(path.at(0));
1176 if (it != s_typeNodeMap.end())
1179 return m_forest.findTypeNode(path, relative, genus);
1183
1184
1185
1186
1187
1190 const Node *node =
nullptr;
1191 if (target.isEmpty())
1193 else if (target.endsWith(
".html"))
1194 node = findNodeByNameAndType(QStringList(target), &Node::isPageNode);
1196 QStringList path = target.split(
"::");
1198 for (
const auto *tree : searchOrder()) {
1199 const Node *n = tree->findNode(path, relative, flags, Genus::DontCare);
1204 node = findPageNodeByTitle(target);
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1224 Genus genus,
const QString &moduleName)
1226 if (target.isEmpty())
1229 Tree *domain = moduleName.isEmpty() ?
nullptr : findTree(moduleName);
1232 const Node *node =
nullptr;
1233 if (target.endsWith(
".html"_L1)) {
1234 node = domain->findNodeByNameAndType(QStringList(target), &
Node::isPageNode);
1235 }
else if (target.endsWith(
')'_L1)) {
1236 QString function = target;
1238 if (function.endsWith(
"()"_L1))
1240 if (function.endsWith(
')'_L1)) {
1241 qsizetype position = function.lastIndexOf(
'('_L1);
1242 signature = function.mid(position + 1, function.size() - position - 2);
1243 function = function.left(position);
1245 QStringList path = function.split(
"::"_L1);
1246 node = domain->findFunctionNode(path,
Parameters(signature),
nullptr, genus);
1251 if (genus == Genus::QML && target.contains(
'.'_L1) && !target.contains(
"::"_L1)) {
1253 QStringList path = target.split(
'.'_L1);
1254 node = domain->findNode(path, relative, typeFlags, genus);
1257 if (path.size() > 1) {
1258 node = domain->findNode(QStringList{path.last()}, relative, typeFlags, genus);
1265 QStringList nodePath = target.split(
"::"_L1);
1266 if (relative && relative
->tree()->physicalModuleName() != domain->physicalModuleName())
1269 return domain->findNodeForTarget(nodePath, {}, relative, flags, genus, ref);
1273 if (target.endsWith(
".html"_L1))
1274 return findNodeByNameAndType(QStringList(target), &Node::isPageNode);
1276 if (target.endsWith(
')'_L1)) {
1277 const Node *node = findFunctionNode(target, relative, genus);
1282 if (genus == Genus::QML && target.contains(
'.'_L1) && !target.contains(
"::"_L1)) {
1283 const Node *node = findTypeNode(target, relative, genus);
1288 QStringList targetPath = target.split(
"::"_L1);
1291 const Node *node = findNodeForTarget(targetPath, relative, genus, ref, flags);
1295 return findPageNodeByTitle(target);
1306 for (
auto it = m->cbegin(); it != m->cend(); ++it)
1307 if (it.value()->members().contains(node))
1314
1315
1318 QStringList filesToRead;
1319 for (
const QString &file : indexFiles) {
1320 QString fn = file.mid(file.lastIndexOf(QChar(
'/')) + 1);
1322 filesToRead << file;
1324 qCCritical(lcQdoc) <<
"Index file" << file <<
"is already in memory.";
1330
1331
1332
1333
1334
1335
1336
1337
1338
1343 const Generator *generator = hrefGenerator;
1345 generator = Generator::generatorForFormat(u"HTML"_s);
1347 qCWarning(lcQdoc) <<
"Cannot generate index file: no href generator available"
1348 " (HTML generator missing)";
1352 QString t = fileName.mid(fileName.lastIndexOf(QChar(
'/')) + 1);
1354 QDocIndexFiles::qdocIndexFiles()->generateIndex(fileName, url, title, generator);
1359
1360
1361
1362
1371 moduleName = relative->physicalModuleName();
1375 moduleName = relative->logicalModuleName();
1380 if (moduleName.isEmpty())
1383 return primaryTree()->getCollection(moduleName, moduleType);
1387
1388
1389
1390
1395 for (
auto *tree : searchOrder()) {
1396 CNMap *m = tree->getCollectionMap(type);
1397 if (m && !m->isEmpty()) {
1398 for (
auto it = m->cbegin(); it != m->cend(); ++it) {
1399 if (!it.value()->isInternal())
1400 cnmm.insert(it.key(), it.value());
1406 static const QRegularExpression singleDigit(
"\\b([0-9])\\b");
1407 const QStringList keys = cnmm.uniqueKeys();
1408 for (
const auto &key : keys) {
1409 const QList<CollectionNode *> values = cnmm.values(key);
1410 CollectionNode *n =
nullptr;
1411 for (
auto *value : values) {
1412 if (value && value->wasSeen() && value != relative) {
1418 if (values.size() > 1) {
1419 for (CollectionNode *value : values) {
1422 if ((n->isQmlModule())
1423 && n->logicalModuleIdentifier() != value->logicalModuleIdentifier()) {
1424 if (value->wasSeen() && value != relative)
1425 cnm.insert(value->fullTitle().toLower(), value);
1428 for (Node *t : value->members())
1433 QString sortKey = n->fullTitle().toLower();
1434 if (sortKey.startsWith(
"the "))
1435 sortKey.remove(0, 4);
1436 sortKey.replace(singleDigit,
"0\\1");
1437 cnm.insert(sortKey, n);
1443
1444
1445
1446
1447
1448
1449
1450
1495 for (
auto *tree : searchOrder()) {
1496 CollectionNode *cn = tree->getCollection(c->name(), c->nodeType());
1497 if (cn && cn != c) {
1498 if ((cn->isQmlModule())
1499 && cn->logicalModuleIdentifier() != c->logicalModuleIdentifier())
1502 for (
auto *node : cn->members())
1562 if (!c->wasSeen() && cn->wasSeen()) {
1564 c->setTitle(cn->title());
1565 c->setUrl(cn->url());
1574
1575
1576
1577
1578
1579
1580
1581
1585 const Node *node =
nullptr;
1587 Atom *atom =
const_cast<
Atom *>(a);
1588 QStringList targetPath = Utilities::pathAndFragment(atom->string());
1589 QString first = targetPath.first().trimmed();
1591 Tree *domain =
nullptr;
1598 if (first.isEmpty())
1601 if (first.endsWith(
".html"))
1602 node = domain->findNodeByNameAndType(QStringList(first), &
Node::isPageNode);
1603 else if (first.endsWith(QChar(
')'))) {
1605 QString function = first;
1606 qsizetype length = first.size();
1607 if (function.endsWith(
"()"))
1609 if (function.endsWith(QChar(
')'))) {
1610 qsizetype position = function.lastIndexOf(QChar(
'('));
1611 signature = function.mid(position + 1, length - position - 2);
1612 function = function.left(position);
1614 QStringList path = function.split(
"::");
1615 node = domain->findFunctionNode(path,
Parameters(signature),
nullptr, genus);
1617 if (node ==
nullptr) {
1619 QStringList nodePath = first.split(
"::");
1621 targetPath.removeFirst();
1622 if (!targetPath.isEmpty())
1623 target = targetPath.takeFirst();
1624 if (relative && relative
->tree()->physicalModuleName() != domain->physicalModuleName())
1626 return domain->findNodeForTarget(nodePath, target, relative, flags, genus, ref);
1629 if (first.endsWith(
".html"))
1630 node = findNodeByNameAndType(QStringList(first), &Node::isPageNode);
1631 else if (first.endsWith(QChar(
')')))
1632 node = findFunctionNode(first, relative, genus);
1633 if (node ==
nullptr) {
1635 if (genus == Genus::QML && first.contains(
'.') && !first.contains(
"::")) {
1637 node = findTypeNode(first, relative, genus);
1640 targetPath.removeFirst();
1641 if (!targetPath.isEmpty()) {
1649 return findNodeForTarget(targetPath, relative, genus, ref, atom->flags());
1653 if (node !=
nullptr && ref.isEmpty()) {
1654 if (!node->url().isEmpty())
1656 targetPath.removeFirst();
1657 if (!targetPath.isEmpty()) {
1667
1668
1669
1670
1671
1672
1673
1674
1678 QList<Tree *> searchOrder =
this->searchOrder();
1697 bool inclusive{Config::instance().get(
1701 const auto tocTitles{Config::instance().get(configVar).asStringList()};
1703 for (
const auto &tocTitle : tocTitles) {
1704 if (
const auto candidateTarget = findNodeForTarget(tocTitle,
nullptr); candidateTarget && candidateTarget->isPageNode()) {
1705 auto tocPage{
static_cast<
const PageNode*>(candidateTarget)};
1707 Text body = tocPage->doc().body();
1709 auto *atom = body.firstAtom();
1711 std::pair<PageNode *, QString> prev {
nullptr, QString() };
1713 std::stack<
const PageNode *> tocStack;
1714 tocStack.push(inclusive ? tocPage :
nullptr);
1716 bool inItem =
false;
1723 switch (atom->type()) {
1724 case Atom::ListItemLeft:
1726 tocStack.push(
nullptr);
1729 case Atom::ListItemRight:
1769 auto candidatePage =
const_cast<Node *>(findNodeForAtom(atom,
nullptr, unused));
1770 if (!candidatePage || !candidatePage->isPageNode())
break;
1772 auto page{
static_cast<PageNode*>(candidatePage)};
1775 if (page == prev.first)
break;
1778 prev.first->setLink(
1819 prev.first->title(),
1824 if (page == tocPage)
1829 qsizetype popped = 0;
1830 while (tocStack.size() > 1 && !tocStack.top()) {
1835 page->setNavigationParent(tocStack.empty() ?
nullptr : tocStack.top());
1837 while (--popped > 0)
1838 tocStack.push(
nullptr);
1840 tocStack.push(page);
1842 prev = { page, atom->linkText() };
1846 case Atom::AnnotatedList:
1847 case Atom::GeneratedList: {
1848 if (
const auto *cn = getCollectionNode(atom->string(), NodeType::Group)) {
1849 const auto sortOrder{Generator::sortOrder(atom->strings().last())};
1850 NodeList members{cn->members()};
1853 members.erase(std::remove_if(members.begin(), members.end(),
1855 return n->isIndexNode() || !n->isPageNode() || n->isExternalPage();
1857 if (members.isEmpty())
1860 if (sortOrder == Qt::DescendingOrder)
1861 std::sort(members.rbegin(), members.rend(), Node::nodeSortKeyOrNameLessThan);
1863 std::sort(members.begin(), members.end(), Node::nodeSortKeyOrNameLessThan);
1868 for (
auto *m : members) {
1869 auto *page =
static_cast<PageNode *>(m);
1871 prev.first->setLink(Node::NextLink, page->title(), page->fullName());
1872 page->setLink(Node::PreviousLink, prev.first->title(), prev.second);
1874 prev = { page, page->fullName() };
1884 atom = atom->next();
1887 Config::instance().get(configVar).location()
1888 .warning(QStringLiteral(
"Failed to find table of contents with title '%1'")
1894 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.
const Node * findNodeForTarget(const QString &target, const Node *relative, Genus genus, const QString &moduleName)
Finds the node for target with genus and module scoping.
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 ...
void resolveProperties()
Resolves access functions associated with each PropertyNode stored in m_unresolvedPropertyMap,...
#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.