18#include <QtCore/qregularexpression.h>
23using namespace Qt::StringLiterals;
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
61
64
65
66
67
68
69
72 for (
auto *entry : m_searchOrder)
75 m_searchOrder.clear();
76 m_indexSearchOrder.clear();
77 m_moduleNames.clear();
78 m_primaryTree =
nullptr;
82
83
84
85
89 return (!searchOrder().isEmpty() ? searchOrder()[0] :
nullptr);
93
94
95
96
100 return (m_currentIndex < searchOrder().size() ? searchOrder()[m_currentIndex] :
nullptr);
104
105
106
107
110
111
112
113
114
115
116
117
118void QDocForest::setPrimaryTree(
const QString &t)
120 QString T = t.toLower();
121 m_primaryTree = findTree(T);
123 if (m_primaryTree ==
nullptr)
124 qCCritical(lcQdoc) <<
"Error: Could not set primary tree to" << t;
128
129
130
131void QDocForest::setSearchOrder(
const QStringList &t)
133 if (!m_searchOrder.isEmpty())
137 m_searchOrder.reserve(m_forest.size() + 1);
138 m_searchOrder.clear();
139 m_moduleNames.reserve(m_forest.size() + 1);
140 m_moduleNames.clear();
143 QString primaryName = primaryTree()->physicalModuleName();
144 m_searchOrder.append(m_primaryTree);
145 m_moduleNames.append(primaryName);
146 m_forest.remove(primaryName);
148 for (
const QString &m : t) {
149 if (primaryName != m) {
150 auto it = m_forest.find(m);
151 if (it != m_forest.end()) {
152 m_searchOrder.append(it.value());
153 m_moduleNames.append(m);
159
160
161
162
163 if (!m_forest.isEmpty()) {
164 for (
auto it = m_forest.begin(); it != m_forest.end(); ++it) {
165 m_searchOrder.append(it.value());
166 m_moduleNames.append(it.key());
172
173
174
175
176
177
178
179 for (
int i = 0; i < m_searchOrder.size(); ++i) {
180 if (!m_forest.contains(m_moduleNames.at(i))) {
181 m_forest.insert(m_moduleNames.at(i), m_searchOrder.at(i));
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
213 if (m_searchOrder.isEmpty())
214 return indexSearchOrder();
215 return m_searchOrder;
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233const QList<Tree *> &
QDocForest::indexSearchOrder()
235 if (m_forest.size() > m_indexSearchOrder.size())
236 m_indexSearchOrder.prepend(m_primaryTree);
237 return m_indexSearchOrder;
241
242
243
244
247 m_primaryTree =
new Tree(module, m_qdb);
248 m_forest.insert(module.toLower(), m_primaryTree);
249 return m_primaryTree->root();
253
254
255
256void QDocForest::newPrimaryTree(
const QString &module)
258 m_primaryTree =
new Tree(module, m_qdb);
262
263
264
265
266
267
268
269
270
271
272
273
274
275const Node *
QDocForest::findNodeForTarget(QStringList &targetPath,
const Node *relative,
276 Genus genus, QString &ref,
int findFlags)
280 QString entity = targetPath.takeFirst();
281 QStringList entityPath = entity.split(
"::");
284 if (!targetPath.isEmpty())
285 target = targetPath.takeFirst();
288 const Node *tocNode =
nullptr;
289 for (
const auto *tree : searchOrder()) {
290 const Node *n = tree->findNodeForTarget(entityPath, target, relative, flags, genus, ref, &type);
293 if (type != TargetRec::Contents)
304
305
306
307
308
309
310
311
312
317 for (
const auto *tree : searchOrder()) {
318 const FunctionNode *fn = tree->findFunctionNode(path, parameters, relative, genus);
327
328
329
330
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
369
370
371
374 if (s_qdocDB ==
nullptr) {
382
383
386 if (s_qdocDB !=
nullptr) {
393
394
395
396
397
398
399
400
401
402
403
404
405
408 s_typeNodeMap.insert(
"accepted",
nullptr);
409 s_typeNodeMap.insert(
"actionPerformed",
nullptr);
410 s_typeNodeMap.insert(
"activated",
nullptr);
411 s_typeNodeMap.insert(
"alias",
nullptr);
412 s_typeNodeMap.insert(
"anchors",
nullptr);
413 s_typeNodeMap.insert(
"any",
nullptr);
414 s_typeNodeMap.insert(
"array",
nullptr);
415 s_typeNodeMap.insert(
"autoSearch",
nullptr);
416 s_typeNodeMap.insert(
"axis",
nullptr);
417 s_typeNodeMap.insert(
"backClicked",
nullptr);
418 s_typeNodeMap.insert(
"boomTime",
nullptr);
419 s_typeNodeMap.insert(
"border",
nullptr);
420 s_typeNodeMap.insert(
"buttonClicked",
nullptr);
421 s_typeNodeMap.insert(
"callback",
nullptr);
422 s_typeNodeMap.insert(
"char",
nullptr);
423 s_typeNodeMap.insert(
"clicked",
nullptr);
424 s_typeNodeMap.insert(
"close",
nullptr);
425 s_typeNodeMap.insert(
"closed",
nullptr);
426 s_typeNodeMap.insert(
"cond",
nullptr);
427 s_typeNodeMap.insert(
"data",
nullptr);
428 s_typeNodeMap.insert(
"dataReady",
nullptr);
429 s_typeNodeMap.insert(
"dateString",
nullptr);
430 s_typeNodeMap.insert(
"dateTimeString",
nullptr);
431 s_typeNodeMap.insert(
"datetime",
nullptr);
432 s_typeNodeMap.insert(
"day",
nullptr);
433 s_typeNodeMap.insert(
"deactivated",
nullptr);
434 s_typeNodeMap.insert(
"drag",
nullptr);
435 s_typeNodeMap.insert(
"easing",
nullptr);
436 s_typeNodeMap.insert(
"error",
nullptr);
437 s_typeNodeMap.insert(
"exposure",
nullptr);
438 s_typeNodeMap.insert(
"fatalError",
nullptr);
439 s_typeNodeMap.insert(
"fileSelected",
nullptr);
440 s_typeNodeMap.insert(
"flags",
nullptr);
441 s_typeNodeMap.insert(
"float",
nullptr);
442 s_typeNodeMap.insert(
"focus",
nullptr);
443 s_typeNodeMap.insert(
"focusZone",
nullptr);
444 s_typeNodeMap.insert(
"format",
nullptr);
445 s_typeNodeMap.insert(
"framePainted",
nullptr);
446 s_typeNodeMap.insert(
"from",
nullptr);
447 s_typeNodeMap.insert(
"frontClicked",
nullptr);
448 s_typeNodeMap.insert(
"function",
nullptr);
449 s_typeNodeMap.insert(
"hasOpened",
nullptr);
450 s_typeNodeMap.insert(
"hovered",
nullptr);
451 s_typeNodeMap.insert(
"hoveredTitle",
nullptr);
452 s_typeNodeMap.insert(
"hoveredUrl",
nullptr);
453 s_typeNodeMap.insert(
"imageCapture",
nullptr);
454 s_typeNodeMap.insert(
"imageProcessing",
nullptr);
455 s_typeNodeMap.insert(
"index",
nullptr);
456 s_typeNodeMap.insert(
"initialized",
nullptr);
457 s_typeNodeMap.insert(
"isLoaded",
nullptr);
458 s_typeNodeMap.insert(
"item",
nullptr);
459 s_typeNodeMap.insert(
"key",
nullptr);
460 s_typeNodeMap.insert(
"keysequence",
nullptr);
461 s_typeNodeMap.insert(
"listViewClicked",
nullptr);
462 s_typeNodeMap.insert(
"loadRequest",
nullptr);
463 s_typeNodeMap.insert(
"locale",
nullptr);
464 s_typeNodeMap.insert(
"location",
nullptr);
465 s_typeNodeMap.insert(
"long",
nullptr);
466 s_typeNodeMap.insert(
"message",
nullptr);
467 s_typeNodeMap.insert(
"messageReceived",
nullptr);
468 s_typeNodeMap.insert(
"mode",
nullptr);
469 s_typeNodeMap.insert(
"month",
nullptr);
470 s_typeNodeMap.insert(
"name",
nullptr);
471 s_typeNodeMap.insert(
"number",
nullptr);
472 s_typeNodeMap.insert(
"object",
nullptr);
473 s_typeNodeMap.insert(
"offset",
nullptr);
474 s_typeNodeMap.insert(
"ok",
nullptr);
475 s_typeNodeMap.insert(
"openCamera",
nullptr);
476 s_typeNodeMap.insert(
"openImage",
nullptr);
477 s_typeNodeMap.insert(
"openVideo",
nullptr);
478 s_typeNodeMap.insert(
"padding",
nullptr);
479 s_typeNodeMap.insert(
"parent",
nullptr);
480 s_typeNodeMap.insert(
"path",
nullptr);
481 s_typeNodeMap.insert(
"photoModeSelected",
nullptr);
482 s_typeNodeMap.insert(
"position",
nullptr);
483 s_typeNodeMap.insert(
"precision",
nullptr);
484 s_typeNodeMap.insert(
"presetClicked",
nullptr);
485 s_typeNodeMap.insert(
"preview",
nullptr);
486 s_typeNodeMap.insert(
"previewSelected",
nullptr);
487 s_typeNodeMap.insert(
"progress",
nullptr);
488 s_typeNodeMap.insert(
"puzzleLost",
nullptr);
489 s_typeNodeMap.insert(
"qmlSignal",
nullptr);
490 s_typeNodeMap.insert(
"rectangle",
nullptr);
491 s_typeNodeMap.insert(
"request",
nullptr);
492 s_typeNodeMap.insert(
"requestId",
nullptr);
493 s_typeNodeMap.insert(
"section",
nullptr);
494 s_typeNodeMap.insert(
"selected",
nullptr);
495 s_typeNodeMap.insert(
"send",
nullptr);
496 s_typeNodeMap.insert(
"settingsClicked",
nullptr);
497 s_typeNodeMap.insert(
"shoe",
nullptr);
498 s_typeNodeMap.insert(
"short",
nullptr);
499 s_typeNodeMap.insert(
"signed",
nullptr);
500 s_typeNodeMap.insert(
"sizeChanged",
nullptr);
501 s_typeNodeMap.insert(
"size_t",
nullptr);
502 s_typeNodeMap.insert(
"sockaddr",
nullptr);
503 s_typeNodeMap.insert(
"someOtherSignal",
nullptr);
504 s_typeNodeMap.insert(
"sourceSize",
nullptr);
505 s_typeNodeMap.insert(
"startButtonClicked",
nullptr);
506 s_typeNodeMap.insert(
"state",
nullptr);
507 s_typeNodeMap.insert(
"std::initializer_list",
nullptr);
508 s_typeNodeMap.insert(
"std::list",
nullptr);
509 s_typeNodeMap.insert(
"std::map",
nullptr);
510 s_typeNodeMap.insert(
"std::pair",
nullptr);
511 s_typeNodeMap.insert(
"std::string",
nullptr);
512 s_typeNodeMap.insert(
"std::vector",
nullptr);
513 s_typeNodeMap.insert(
"stringlist",
nullptr);
514 s_typeNodeMap.insert(
"swapPlayers",
nullptr);
515 s_typeNodeMap.insert(
"symbol",
nullptr);
516 s_typeNodeMap.insert(
"t",
nullptr);
517 s_typeNodeMap.insert(
"T",
nullptr);
518 s_typeNodeMap.insert(
"tagChanged",
nullptr);
519 s_typeNodeMap.insert(
"timeString",
nullptr);
520 s_typeNodeMap.insert(
"timeout",
nullptr);
521 s_typeNodeMap.insert(
"to",
nullptr);
522 s_typeNodeMap.insert(
"toggled",
nullptr);
523 s_typeNodeMap.insert(
"type",
nullptr);
524 s_typeNodeMap.insert(
"unsigned",
nullptr);
525 s_typeNodeMap.insert(
"urllist",
nullptr);
526 s_typeNodeMap.insert(
"va_list",
nullptr);
527 s_typeNodeMap.insert(
"value",
nullptr);
528 s_typeNodeMap.insert(
"valueEmitted",
nullptr);
529 s_typeNodeMap.insert(
"videoFramePainted",
nullptr);
530 s_typeNodeMap.insert(
"videoModeSelected",
nullptr);
531 s_typeNodeMap.insert(
"videoRecorder",
nullptr);
532 s_typeNodeMap.insert(
"void",
nullptr);
533 s_typeNodeMap.insert(
"volatile",
nullptr);
534 s_typeNodeMap.insert(
"wchar_t",
nullptr);
535 s_typeNodeMap.insert(
"x",
nullptr);
536 s_typeNodeMap.insert(
"y",
nullptr);
537 s_typeNodeMap.insert(
"zoom",
nullptr);
538 s_typeNodeMap.insert(
"zoomTo",
nullptr);
542
543
546
547
548
549
552
553
554
555
558
559
560
561
564
565
566
567
568
569
570
573
574
575
576
577
578
579
582
583
584
585
586
587
590
591
592
593
594
595
598
599
600
601
602
603
606
607
608
609
610
611
612
613
616
617
618
619
620
621
624
625
626
627
630
631
632
635
636
637
638
639
640
641
644 if (!qmid.isEmpty()) {
645 if (
auto *qcn = m_forest.lookupQmlType(qmid + u"::"_s + name, relative); qcn)
650 if (
auto *qcn = m_forest.lookupQmlType(name, relative); qcn)
654 QStringList path(name);
655 return static_cast<QmlTypeNode *>(m_forest.findNodeByNameAndType(path, &Node::isQmlType));
659
660
661
662
672 if (!record.m_importId.isEmpty()) {
673 const QString namespacePrefix{
"%1."_L1.arg(record.m_importId)};
674 if (!type.startsWith(namespacePrefix))
676 type.remove(0, namespacePrefix.size());
679 const QString qmName = record.m_importUri.isEmpty() ? record.m_moduleName : record.m_importUri;
680 return m_forest.lookupQmlType(qmName + u"::"_s + type, relative);
684
685
686
687
688
689
698
699
700
701
702
703
716
717
718
719
720
723 Tree *t = m_forest.firstTree();
725 if (!m_completedFindFunctions.values(t).contains(func)) {
726 (
this->*(func))(t->root());
727 m_completedFindFunctions.insert(t, func);
729 t = m_forest.nextTree();
734
735
739 return m_legaleseTexts;
743
744
748 return s_classesWithObsoleteMembers;
752
753
757 return s_obsoleteQmlTypes;
761
762
766 return s_qmlTypesWithObsoleteMembers;
770
771
775 return s_qmlBasicTypes;
779
780
788
789
797
798
802 return m_attributions;
806
807
811 return s_obsoleteClasses;
815
816
824
825
826
830 return m_functionIndex;
834
835
836
839 for (
const auto &childNode : node->childNodes()) {
840 if (childNode->isPrivate())
842 if (!childNode->doc().legaleseText().isEmpty())
843 m_legaleseTexts.insert(childNode->doc().legaleseText(), childNode);
844 if (childNode->isAggregate())
845 findAllLegaleseTexts(
static_cast<Aggregate *>(childNode));
850
851
852
853
854
855
858
859
860
861
862
863
864
865
866
869
870
871
872
873
874
875
878
879
880
881
885 auto it = s_newClassMaps.constFind(key);
890
891
892
893
897 auto it = s_newQmlTypeMaps.constFind(key);
902
903
904
905
909 auto it = s_newSinceMaps.constFind(key);
914
915
916
917
918
919
920
921
924 const auto &config = Config::instance();
925 if (config.dualExec() || config.preparing()) {
942 if (config.singleExec() && config.generating()) {
950 if (!config.preparing()) {
956 if (config.dualExec())
962 Tree *t = m_forest.firstTree();
964 t->resolveBaseClasses(t->root());
967 t = m_forest.nextTree();
972
973
974
975
976
980 for (
const auto &name : td->referenced_concepts)
981 refs.append(QString::fromStdString(name));
984 const auto *fn =
static_cast<
const FunctionNode *>(node);
985 refs += fn->referencedConcepts();
990
991
992
993
994
995
998 for (
auto *child : std::as_const(parent->childNodes())) {
1004 const bool registerChild =
1005 !child->isPrivate() && !child->isInternal() && !child->isDontDocument();
1007 if (registerChild) {
1009 collectConceptReferences(child, refs);
1011 refs.removeDuplicates();
1013 for (
const QString &conceptName : std::as_const(refs)) {
1026 if (
auto *cn = db.findMutableCollectionNode(conceptName, NodeType::Concept))
1027 cn->addMember(child);
1031 if (child->isAggregate())
1032 registerConceptUsersUnder(
static_cast<Aggregate *>(child), db);
1037
1038
1039
1040
1041
1042
1043
1044
1051
1052
1053
1054
1055
1059 return m_namespaceIndex;
1063
1064
1065
1066
1067
1068
1069
1072 if (!m_namespaceIndex.isEmpty())
1077 Tree *t = m_forest.firstTree();
1080 t = m_forest.nextTree();
1082 const QList<QString> keys = namespaceMultimap.uniqueKeys();
1083 for (
const QString &key : keys) {
1084 NamespaceNode *ns =
nullptr;
1085 NamespaceNode *indexNamespace =
nullptr;
1086 const NodeList namespaces = namespaceMultimap.values(key);
1087 qsizetype count = namespaceMultimap.remove(key);
1089 for (
auto *node : namespaces) {
1090 ns =
static_cast<NamespaceNode *>(node);
1091 if (ns->isDocumentedHere())
1093 else if (ns->hadDoc())
1094 indexNamespace = ns;
1098 for (
auto *node : namespaces) {
1099 auto *nsNode =
static_cast<NamespaceNode *>(node);
1100 if (nsNode->hadDoc() && nsNode != ns) {
1101 ns->doc().location().warning(
1102 QStringLiteral(
"Namespace %1 documented more than once")
1103 .arg(nsNode->name()), QStringLiteral(
"also seen here: %1")
1104 .arg(nsNode->doc().location().toString()));
1107 }
else if (!indexNamespace) {
1112 for (
auto *node : namespaces) {
1113 if (!node->isIndexNode())
1114 static_cast<NamespaceNode *>(node)->reportDocumentedChildrenInUndocumentedNamespace();
1118 for (
auto *node : namespaces) {
1119 auto *nsNode =
static_cast<NamespaceNode *>(node);
1120 if (nsNode != indexNamespace)
1121 nsNode->setDocNode(indexNamespace);
1126
1127
1128
1129
1130
1131 if (ns && count > 1) {
1132 for (
auto *node : namespaces) {
1133 auto *nameSpaceNode =
static_cast<NamespaceNode *>(node);
1134 if (nameSpaceNode != ns) {
1135 for (
auto it = nameSpaceNode->constBegin(); it != nameSpaceNode->constEnd();
1137 Node *anotherNs = *it;
1138 if (anotherNs && anotherNs->isPublic() && !anotherNs->isInternal())
1139 ns->includeChild(anotherNs);
1145
1146
1147
1149 ns = indexNamespace ? indexNamespace :
static_cast<NamespaceNode *>(namespaces.last());
1150 m_namespaceIndex.insert(ns->name(), ns);
1155
1156
1157
1158
1159
1160
1161
1162
1163
1168 Tree *t = m_forest.firstTree();
1169 t = m_forest.nextTree();
1172 if (!proxies.isEmpty()) {
1173 for (
auto *node : proxies) {
1174 const auto *pn =
static_cast<ProxyNode *>(node);
1175 if (pn->count() > 0) {
1176 Aggregate *aggregate = primaryTree()->findAggregate(pn->name());
1177 if (aggregate !=
nullptr)
1178 aggregate->appendToRelatedByProxy(pn->childNodes());
1182 t = m_forest.nextTree();
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1203 QString function = target;
1204 qsizetype length = target.size();
1205 if (function.endsWith(
"()"))
1207 if (function.endsWith(QChar(
')'))) {
1208 qsizetype position = function.lastIndexOf(QChar(
'('));
1209 signature = function.mid(position + 1, length - position - 2);
1210 function = function.left(position);
1212 QStringList path = function.split(
"::");
1213 return m_forest.findFunctionNode(path, Parameters(signature), relative, genus);
1217
1218
1219
1220
1221
1222
1223
1224
1225
1229 if ((genus == Genus::QML || (relative && relative
->genus() == Genus::QML)) &&
1230 type.contains(
'.') && !type.contains(
"::")) {
1232 const QmlTypeNode *qmlType =
static_cast<
const QmlTypeNode*>(relative);
1235 for (
const auto &import : imports) {
1236 if (QmlTypeNode *found = findQmlType(import, type)) {
1243 QStringList path = type.split(
".");
1244 if ((path.size() == 1) && (path.at(0)[0].isLower() || path.at(0) == QString(
"T"))) {
1245 auto it = s_typeNodeMap.find(path.at(0));
1246 if (it != s_typeNodeMap.end())
1251 const Node *node = m_forest.findTypeNode(path, relative, genus);
1258 if (path.size() > 1) {
1259 const Node *lastSegmentNode = m_forest.findTypeNode(QStringList{path.last()}, relative, genus);
1261 return lastSegmentNode;
1268 QStringList path = type.split(
"::");
1269 if ((path.size() == 1) && (path.at(0)[0].isLower() || path.at(0) == QString(
"T"))) {
1270 auto it = s_typeNodeMap.find(path.at(0));
1271 if (it != s_typeNodeMap.end())
1274 return m_forest.findTypeNode(path, relative, genus);
1278
1279
1280
1281
1282
1285 const Node *node =
nullptr;
1286 if (target.isEmpty())
1288 else if (target.endsWith(
".html"))
1289 node = findNodeByNameAndType(QStringList(target), &Node::isPageNode);
1291 QStringList path = target.split(
"::");
1293 for (
const auto *tree : searchOrder()) {
1294 const Node *n = tree->findNode(path, relative, flags, Genus::DontCare);
1299 node = findPageNodeByTitle(target);
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1319 Genus genus,
const QString &moduleName,
1322 if (target.isEmpty())
1325 Tree *domain = moduleName.isEmpty() ?
nullptr : findTree(moduleName);
1328 const Node *node =
nullptr;
1329 if (target.endsWith(
".html"_L1)) {
1330 node = domain->findNodeByNameAndType(QStringList(target), &
Node::isPageNode);
1331 }
else if (target.endsWith(
')'_L1)) {
1332 QString function = target;
1334 if (function.endsWith(
"()"_L1))
1336 if (function.endsWith(
')'_L1)) {
1337 qsizetype position = function.lastIndexOf(
'('_L1);
1338 signature = function.mid(position + 1, function.size() - position - 2);
1339 function = function.left(position);
1341 QStringList path = function.split(
"::"_L1);
1342 node = domain->findFunctionNode(path,
Parameters(signature),
nullptr, genus);
1347 if (genus == Genus::QML && target.contains(
'.'_L1) && !target.contains(
"::"_L1)) {
1349 QStringList path = target.split(
'.'_L1);
1350 node = domain->findNode(path, relative, typeFlags, genus);
1353 if (path.size() > 1) {
1354 node = domain->findNode(QStringList{path.last()}, relative, typeFlags, genus);
1361 QStringList nodePath = target.split(
"::"_L1);
1362 if (relative && relative
->tree()->physicalModuleName() != domain->physicalModuleName())
1365 const Node *result =
1366 domain->findNodeForTarget(nodePath, {}, relative, flags, genus, localRef);
1373 if (target.endsWith(
".html"_L1))
1374 return findNodeByNameAndType(QStringList(target), &Node::isPageNode);
1376 if (target.endsWith(
')'_L1)) {
1377 const Node *node = findFunctionNode(target, relative, genus);
1382 if (genus == Genus::QML && target.contains(
'.'_L1) && !target.contains(
"::"_L1)) {
1383 const Node *node = findTypeNode(target, relative, genus);
1388 QStringList targetPath = Utilities::pathAndFragment(target);
1391 const Node *node = findNodeForTarget(targetPath, relative, genus, localRef, flags);
1398 return findPageNodeByTitle(target);
1409 for (
auto it = m->cbegin(); it != m->cend(); ++it)
1410 if (it.value()->members().contains(node))
1417
1418
1421 QStringList filesToRead;
1422 for (
const QString &file : indexFiles) {
1423 QString fn = file.mid(file.lastIndexOf(QChar(
'/')) + 1);
1425 filesToRead << file;
1427 qCCritical(lcQdoc) <<
"Index file" << file <<
"is already in memory.";
1433
1434
1435
1436
1437
1441 QString t = fileName.mid(fileName.lastIndexOf(QChar(
'/')) + 1);
1443 QDocIndexFiles::qdocIndexFiles()->generateIndex(fileName, url, title, context);
1448
1449
1450
1451
1460 moduleName = relative->physicalModuleName();
1464 moduleName = relative->logicalModuleName();
1469 if (moduleName.isEmpty())
1472 return primaryTree()->getCollection(moduleName, moduleType);
1476
1477
1478
1479
1484 for (
auto *tree : searchOrder()) {
1485 CNMap *m = tree->getCollectionMap(type);
1486 if (m && !m->isEmpty()) {
1487 for (
auto it = m->cbegin(); it != m->cend(); ++it) {
1488 if (!it.value()->isInternal())
1489 cnmm.insert(it.key(), it.value());
1495 static const QRegularExpression singleDigit(
"\\b([0-9])\\b");
1496 const QStringList keys = cnmm.uniqueKeys();
1497 for (
const auto &key : keys) {
1498 const QList<CollectionNode *> values = cnmm.values(key);
1499 CollectionNode *n =
nullptr;
1500 for (
auto *value : values) {
1501 if (value && value->wasSeen() && value != relative) {
1507 if (values.size() > 1) {
1508 for (CollectionNode *value : values) {
1511 if ((n->isQmlModule())
1512 && n->logicalModuleIdentifier() != value->logicalModuleIdentifier()) {
1513 if (value->wasSeen() && value != relative)
1514 cnm.insert(value->fullTitle().toLower(), value);
1517 for (Node *t : value->members())
1522 QString sortKey = n->fullTitle().toLower();
1523 if (sortKey.startsWith(
"the "))
1524 sortKey.remove(0, 4);
1525 sortKey.replace(singleDigit,
"0\\1");
1526 cnm.insert(sortKey, n);
1532
1533
1534
1535
1536
1537
1538
1539
1584 for (
auto *tree : searchOrder()) {
1585 CollectionNode *cn = tree->getCollection(c->name(), c->nodeType());
1586 if (cn && cn != c) {
1587 if ((cn->isQmlModule())
1588 && cn->logicalModuleIdentifier() != c->logicalModuleIdentifier())
1591 for (
auto *node : cn->members())
1651 if (!c->wasSeen() && cn->wasSeen()) {
1653 c->setTitle(cn->title());
1654 c->setUrl(cn->url());
1655 c->setResolvedPhysicalModuleName(cn->tree()->physicalModuleName());
1664
1665
1666
1667
1668
1669
1670
1677 for (
auto &piece : path.split(
"."_L1)) {
1678 for (
auto &inner : piece.split(
"::"_L1)) {
1679 pieces.append(inner);
1684 QString modName{
""};
1685 QString tryName{
""};
1686 const Node *modNode{
nullptr};
1689 for (i = 0; i < pieces.count(); i++) {
1690 tryName += pieces.at(i);
1691 const Node *node = findNodeByNameAndType(QStringList(tryName), &Node::isQmlModule);
1703 if (i == pieces.count())
1709 pieces = pieces.mid(i);
1710 qtn = findQmlType(modName, pieces.takeFirst(), relative);
1712 qtn = findQmlType(pieces.takeFirst(), relative);
1715 if (!qtn || pieces.isEmpty())
1718 auto propertyName = pieces.join(
"."_L1);
1727 return qtn->findChildNode(propertyName, Genus::QML);
1731
1732
1733
1734
1735
1736
1737
1738
1742 const Node *node =
nullptr;
1744 Atom *atom =
const_cast<
Atom *>(a);
1745 QStringList targetPath = Utilities::pathAndFragment(atom->string());
1746 QString first = targetPath.first().trimmed();
1748 Tree *domain =
nullptr;
1752 domain = atomDomain;
1756 if (!first.contains(
"://"_L1) && !first.contains(
" "_L1) && !first.endsWith(
".html"_L1) && first.contains(
"."_L1)) {
1757 const Node *found = findQmlNode(first, relative);
1758 if (found)
return found;
1762 if (first.isEmpty())
1765 if (first.endsWith(
".html"))
1766 node = domain->findNodeByNameAndType(QStringList(first), &
Node::isPageNode);
1767 else if (first.endsWith(QChar(
')'))) {
1769 QString function = first;
1770 qsizetype length = first.size();
1771 if (function.endsWith(
"()"))
1773 if (function.endsWith(QChar(
')'))) {
1774 qsizetype position = function.lastIndexOf(QChar(
'('));
1775 signature = function.mid(position + 1, length - position - 2);
1776 function = function.left(position);
1778 QStringList path = function.split(
"::");
1779 node = domain->findFunctionNode(path,
Parameters(signature),
nullptr, genus);
1781 if (node ==
nullptr) {
1783 QStringList nodePath = first.split(
"::");
1785 targetPath.removeFirst();
1786 if (!targetPath.isEmpty())
1787 target = targetPath.takeFirst();
1788 if (relative && relative
->tree()->physicalModuleName() != domain->physicalModuleName())
1790 return domain->findNodeForTarget(nodePath, target, relative, flags, genus, ref);
1793 if (first.endsWith(
".html"))
1794 node = findNodeByNameAndType(QStringList(first), &Node::isPageNode);
1795 else if (first.endsWith(QChar(
')')))
1796 node = findFunctionNode(first, relative, genus);
1797 if (node ==
nullptr) {
1799 if (genus == Genus::QML && first.contains(
'.') && !first.contains(
"::")) {
1801 node = findTypeNode(first, relative, genus);
1804 targetPath.removeFirst();
1805 if (!targetPath.isEmpty()) {
1813 return findNodeForTarget(targetPath, relative, genus, ref, atom->flags());
1817 if (node !=
nullptr && ref.isEmpty()) {
1818 if (!node->url().isEmpty())
1820 targetPath.removeFirst();
1821 if (!targetPath.isEmpty()) {
1831
1832
1833
1834
1835
1836
1837
1838
1842 QList<Tree *> searchOrder =
this->searchOrder();
1861 bool inclusive{Config::instance().get(
1865 const auto tocTitles{Config::instance().get(configVar).asStringList()};
1867 for (
const auto &tocTitle : tocTitles) {
1868 if (
const auto candidateTarget = findNodeForTarget(tocTitle,
nullptr); candidateTarget && candidateTarget->isPageNode()) {
1869 auto tocPage{
static_cast<
const PageNode*>(candidateTarget)};
1871 Text body = tocPage->doc().body();
1873 auto *atom = body.firstAtom();
1875 std::pair<PageNode *, QString> prev {
nullptr, QString() };
1877 std::stack<
const PageNode *> tocStack;
1878 tocStack.push(inclusive ? tocPage :
nullptr);
1880 bool inItem =
false;
1887 switch (atom->type()) {
1888 case Atom::ListItemLeft:
1890 tocStack.push(
nullptr);
1893 case Atom::ListItemRight:
1933 auto candidatePage =
const_cast<Node *>(findNodeForAtom(atom,
nullptr, unused));
1934 if (!candidatePage || !candidatePage->isPageNode())
break;
1936 auto page{
static_cast<PageNode*>(candidatePage)};
1939 if (page == prev.first)
break;
1942 prev.first->setLink(
1983 prev.first->title(),
1988 if (page == tocPage)
1993 qsizetype popped = 0;
1994 while (tocStack.size() > 1 && !tocStack.top()) {
1999 page->setNavigationParent(tocStack.empty() ?
nullptr : tocStack.top());
2001 while (--popped > 0)
2002 tocStack.push(
nullptr);
2004 tocStack.push(page);
2006 prev = { page, atom->linkText() };
2010 case Atom::AnnotatedList:
2011 case Atom::GeneratedList: {
2012 if (
const auto *cn = getCollectionNode(atom->string(), NodeType::Group)) {
2013 const auto sortOrder{Generator::sortOrder(atom->strings().last())};
2014 NodeList members{cn->members()};
2017 members.erase(std::remove_if(members.begin(), members.end(),
2019 return n->isIndexNode() || !n->isPageNode() || n->isExternalPage();
2021 if (members.isEmpty())
2024 if (sortOrder == Qt::DescendingOrder)
2025 std::sort(members.rbegin(), members.rend(), Node::nodeSortKeyOrNameLessThan);
2027 std::sort(members.begin(), members.end(), Node::nodeSortKeyOrNameLessThan);
2032 for (
auto *m : members) {
2033 auto *page =
static_cast<PageNode *>(m);
2035 prev.first->setLink(Node::NextLink, page->title(), page->fullName());
2036 page->setLink(Node::PreviousLink, prev.first->title(), prev.second);
2038 prev = { page, page->fullName() };
2048 atom = atom->next();
2051 Config::instance().get(configVar).location()
2052 .warning(QStringLiteral(
"Failed to find table of contents with title '%1'")
2058 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 generateIndex(const QString &fileName, const QString &url, const QString &title, const IndexSerializationContext &context)
Generates a qdoc index file and writes it to fileName.
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.
void resolveConceptUsers()
Builds the concept-to-users reverse index after parsing finishes and before any generator runs.
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...
const Node * findNodeForTarget(const QString &target, const Node *relative, Genus genus, const QString &moduleName, QString *ref=nullptr)
Finds the node for target with genus and module scoping.
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 ...
const Node * findQmlNode(const QString &path, const Node *relative)
Returns the node to a piece of QML API documentation that corresponds to the given path,...
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 imports QDoc index files and serializes index sections for module indexes and WebXML outpu...
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 void collectConceptReferences(const Node *node, QStringList &refs)
Gathers the fully-qualified concept names referenced by node.
static void registerConceptUsersUnder(Aggregate *parent, QDocDatabase &db)
Walks every documented node under parent and registers each constrained item as a member of the conce...
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.
const std::optional< RelaxedTemplateDeclaration > & templateDecl() const
bool isFunction(Genus g=Genus::DontCare) const
Returns true if this is a FunctionNode and its Genus is set to g.
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.