29using namespace Qt::StringLiterals;
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
49
50
51
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
71
72
73
74
75
76
77
79 : m_camelCaseModuleName(camelCaseModuleName),
80 m_physicalModuleName(camelCaseModuleName.toLower()),
82 m_root(
nullptr, QString())
84 m_root.setPhysicalModuleName(m_physicalModuleName);
89
90
91
92
93
94
95
96
97
98
101 qDeleteAll(m_nodesByTargetRef);
102 m_nodesByTargetRef.clear();
103 m_nodesByTargetTitle.clear();
109
110
111
112
113
114Node *
Tree::findNodeForInclude(
const QStringList &path)
const
116 Node *n = findClassNode(path);
118 n = findNamespaceNode(path);
123
124
125
126
127
128
129
132 QStringList path = name.split(QLatin1String(
"::"));
133 return static_cast<Aggregate *>(findNodeRecursive(path, 0,
const_cast<NamespaceNode *>(root()),
134 &Node::isFirstClassAggregate));
138
139
140
141
142
145 if (start ==
nullptr)
147 return static_cast<ClassNode *>(findNodeRecursive(path, 0, start, &Node::isClassNode));
151
152
153
154
158 return static_cast<NamespaceNode *>(findNodeRecursive(path, 0, start, &Node::isNamespace));
162
163
164
165
166
167
168
169
170
171
172
175 Node *n = findNodeRecursive(path, 0, root(), &Node::isRelatableType);
176 return (((n !=
nullptr) && n->isAggregate()) ?
static_cast<Aggregate *>(n) :
nullptr);
180
181
182
186 m_unresolvedPropertyMap[property].insert(funcRole, funcName);
190
191
192
193
194
195
196
199 for (
auto it = n->constBegin(); it != n->constEnd(); ++it) {
200 if ((*it)->isClassNode()) {
201 auto *cn =
static_cast<
ClassNode *>(*it);
202 QList<RelatedClass> &bases = cn->baseClasses_mutable();
203 for (
auto &base : bases) {
204 if (base.m_node ==
nullptr) {
205 Node *n = m_qdb->findClassNode(base.m_path);
207
208
209
210
211
212
213
214
215
217 Aggregate *parent = cn->parent();
218 if (parent !=
nullptr)
220 if (parent->isNamespace() && !parent->name().isEmpty())
221 n = findClassNode(base.m_path, parent);
224 auto *bcn =
static_cast<ClassNode *>(n);
226 bcn->addDerivedClass(base.m_access, cn);
230 resolveBaseClasses(cn);
231 }
else if ((*it)->isNamespace()) {
238
241 for (
auto node = n->constBegin(); node != n->constEnd(); ++node) {
242 if ((*node)->isClassNode()) {
243 auto *cn =
static_cast<
ClassNode *>(*node);
244 for (
auto property = cn->constBegin(); property != cn->constEnd(); ++property) {
245 if ((*property)->isProperty())
246 cn->resolvePropertyOverriddenFromPtrs(
static_cast<
PropertyNode *>(*property));
248 resolvePropertyOverriddenFromPtrs(cn);
249 }
else if ((*node)->isNamespace()) {
250 resolvePropertyOverriddenFromPtrs(
static_cast<
NamespaceNode *>(*node));
256
257
258
259
260
263 for (
auto propEntry = m_unresolvedPropertyMap.constBegin();
264 propEntry != m_unresolvedPropertyMap.constEnd(); ++propEntry) {
273 for (
auto it = parent->constBegin(); it != parent->constEnd(); ++it) {
274 if ((*it)->isFunction()) {
276 if (function->access() == property
->access()
277 && (function->status() == property
->status() || function->doc().isEmpty())) {
278 if (function->name() == getterName) {
280 }
else if (function->name() == setterName) {
282 }
else if (function->name() == resetterName) {
284 }
else if (function->name() == notifierName) {
286 }
else if (function->name() == bindableName) {
294 for (
auto propEntry = m_unresolvedPropertyMap.constBegin();
295 propEntry != m_unresolvedPropertyMap.constEnd(); ++propEntry) {
302 m_unresolvedPropertyMap.clear();
306
307
308
309
310
311
312
313
314
315
316
317void Tree::validatePropertyDocumentation(
const Aggregate *aggregate)
const
319 const auto &config = Config::instance();
320 const InclusionPolicy policy = config.createInclusionPolicy();
321 validatePropertyDocumentation(aggregate, policy);
325
326
327
328
329
330
331void Tree::validatePropertyDocumentation(
const Aggregate *aggregate,
const InclusionPolicy &policy)
const
333 for (
auto it = aggregate->constBegin(); it != aggregate->constEnd(); ++it) {
339 node
->location().warning(u"Undocumented property '%1'"_s.arg(node->plainFullName()));
343 validatePropertyDocumentation(
static_cast<Aggregate *>(node), policy);
348
349
350
351
352void Tree::resolveCppToQmlLinks()
355 const NodeList &children = m_root.childNodes();
356 for (
auto *child : children) {
357 if (child->isQmlType()) {
358 auto *qcn =
static_cast<QmlTypeNode *>(child);
359 auto *cn =
const_cast<ClassNode *>(qcn->classNode());
361 cn->insertQmlNativeType(qcn);
367
368
369
370
371
372
373
374
377 for (
auto *child : aggregate.childNodes()) {
380 if (child->isEnumType())
381 resolveEnumValueSince(
static_cast<EnumNode&>(*child));
382 if (!child->isAggregate())
384 if (!child->since().isEmpty())
387 if (
const auto collectionNode = m_qdb->getModuleNode(child))
388 child->setSince(collectionNode->since());
390 resolveSince(
static_cast<Aggregate&>(*child));
395
396
397
398
399
400
401
402
405 const QStringList enumItems{en
.doc().enumItemNames()};
406 const Atom *atom = en
.doc().body().firstAtom();
412 if (
const auto &val = atom->string(); enumItems.contains(val)) {
420
421
422
423
424
425
426
427
430 if (rootNode ==
nullptr)
433 for (
auto node = rootNode->constBegin(); node != rootNode->constEnd(); ++node) {
434 if ((*node)->isClassNode())
436 else if ((*node)->isNamespace())
437 removePrivateAndInternalBases(
static_cast<
NamespaceNode *>(*node));
442
446 const auto &baseClasses = classNode->baseClasses();
447 for (
const auto &relatedClass : baseClasses) {
448 if (relatedClass.m_node !=
nullptr) {
449 result += relatedClass.m_node;
450 result += allBaseClasses(relatedClass.m_node);
457
458
459
460
461
462
465 return findNodeRecursive(path, 0, root(), isMatch);
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484Node *
Tree::findNodeRecursive(
const QStringList &path,
int pathIndex,
const Node *start,
485 bool (Node::*isMatch)()
const)
const
487 if (start ==
nullptr || path.isEmpty())
489 Node *node =
const_cast<
Node *>(start);
491 return ((pathIndex >= path.size()) ? node :
nullptr);
492 auto *current =
static_cast<Aggregate *>(node);
493 const NodeList &children = current->childNodes();
494 const QString &name = path.at(pathIndex);
495 for (
auto *node : children) {
498 if (node->name() == name) {
499 if (pathIndex + 1 >= path.size()) {
500 if ((node->*(isMatch))())
504 node = findNodeRecursive(path, pathIndex + 1, node, isMatch);
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529const Node *
Tree::findNodeForTarget(
const QStringList &path,
const QString &target,
530 const Node *start,
int flags, Genus genus,
533 const Node *node =
nullptr;
537 auto set_ref_from_target = [
this, &ref, &target](
const Node *n) ->
const Node* {
538 if (!target.isEmpty()) {
539 if (ref = getRef(target, n); ref.isEmpty())
545 if (genus == Genus::DontCare || genus == Genus::DOC) {
546 if (node = findPageNodeByTitle(path.at(0)); node) {
547 if (node = set_ref_from_target(node); node)
553
554
555
556
557
558
559
560
561
563 const bool prioritizeHierarchy = scope &&
564 ((scope
->isClassNode() && (genus == Genus::CPP || genus == Genus::DontCare)) ||
565 (scope
->isQmlType() && (genus == Genus::QML || genus == Genus::DontCare)));
568 if (!prioritizeHierarchy) {
569 result = findUnambiguousTarget(path.join(QLatin1String(
"::")), genus, start);
572 if (node = set_ref_from_target(result
->m_node); node) {
585 const Node *current = start ? start : root();
587
588
589
590
591
593 if ((genus == Genus::QML || genus == Genus::DontCare)
594 && path.size() >= 2 && !path[0].isEmpty()) {
595 if (
auto *qcn = lookupQmlType(path.sliced(0, 2).join(QLatin1String(
"::")), start); qcn) {
598 if (path.size() == 2)
599 return set_ref_from_target(qcn);
606 if (
const Node *match = matchPathAndTarget(
607 path, path_idx, target, current, flags, genus, ref);
616 if (prioritizeHierarchy) {
617 result = findUnambiguousTarget(path.join(QLatin1String(
"::")), genus, start);
620 if (node = set_ref_from_target(result
->m_node); node) {
628 if (node && result) {
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657const Node *
Tree::matchPathAndTarget(
const QStringList &path,
int idx,
const QString &target,
658 const Node *node,
int flags, Genus genus,
659 QString &ref,
int duplicates)
const
662
663
664
665
666
667 if (idx == path.size()) {
668 if (!target.isEmpty()) {
669 ref = getRef(target, node);
694 QString name = path.at(idx);
697 static_cast<
const Aggregate *>(node)->findChildren(name, nodes);
698 for (
const auto *child : std::as_const(nodes)) {
699 if (genus != Genus::DontCare && !(hasCommonGenusType(genus, child->genus())))
701 const Node *t = matchPathAndTarget(path, idx + 1, target, child, flags, genus, ref, nodes.count() - 1);
702 if (t && !t->isPrivate() && !t->isInternal())
707 const auto *enumNode = node->isAggregate() ?
708 findEnumNode(
nullptr, node, path, idx) :
709 findEnumNode(node,
nullptr, path, idx);
713 if (((genus == Genus::CPP) || (genus == Genus::DontCare)) && node
->isClassNode()
715 const ClassList bases = allBaseClasses(
static_cast<
const ClassNode *>(node));
716 for (
const auto *base : bases) {
717 const Node *t = matchPathAndTarget(path, idx, target, base, flags, genus, ref);
718 if (t && !t->isPrivate() && !t->isInternal())
720 if (target.isEmpty() && (flags & SearchEnumValues)) {
721 if ((t = findEnumNode(base->findChildNode(path.at(idx), genus, flags), base, path, idx)))
726 if (((genus == Genus::QML) || (genus == Genus::DontCare)) && node
->isQmlType()
728 const QmlTypeNode *qtn =
static_cast<
const QmlTypeNode *>(node);
731 const Node *t = matchPathAndTarget(path, idx, target, qtn, flags, genus, ref);
740
741
742
743
744
745const Node *
Tree::findNode(
const QStringList &path,
const Node *start,
int flags,
748 const Node *current = start;
749 if (current ==
nullptr)
753 const Node *node = current;
758
759
760
761
762
763
764
765 if (((genus == Genus::QML) || (genus == Genus::DontCare)) && (path.size() >= 2)
766 && !path[0].isEmpty()) {
767 QmlTypeNode *qcn = lookupQmlType(QString(path[0] +
"::" + path[1]), start);
768 if (qcn !=
nullptr) {
770 if (path.size() == 2)
776 for (i = start_idx; i < path.size(); ++i) {
785 const Node *next =
static_cast<
const Aggregate *>(node)->findChildNode(path.at(i),
787 const Node *enumNode = (flags & SearchEnumValues) ?
788 findEnumNode(next, node, path, i) :
nullptr;
794 if (!next && ((genus == Genus::CPP) || (genus == Genus::DontCare))
796 const ClassList bases = allBaseClasses(
static_cast<
const ClassNode *>(node));
797 for (
const auto *base : bases) {
798 next = base->findChildNode(path.at(i), genus, tmpFlags);
799 if (flags & SearchEnumValues)
800 if ((enumNode = findEnumNode(next, base, path, i)))
806 if (!next && ((genus == Genus::QML) || (genus == Genus::DontCare))
808 const QmlTypeNode *qtn =
static_cast<
const QmlTypeNode *>(node);
811 next = qtn->findChildNode(path.at(i), genus, tmpFlags);
816 if ((node !=
nullptr) && i == path.size())
819 }
while (current !=
nullptr);
826
827
828
829
830
831
832
833const Node *
Tree::findEnumNode(
const Node *node,
const Node *aggregate,
const QStringList &path,
int offset)
const
837 const auto *en =
static_cast<
const EnumNode*>(node);
838 if (en->hasItem(path.last()))
843 return (!node && aggregate && offset == path.size() - 1) ?
844 static_cast<
const Aggregate *>(aggregate)->findEnumNodeForValue(path.last()) :
849
850
851
852
853
854QString
Tree::getRef(
const QString &target,
const Node *node)
const
856 auto it = m_nodesByTargetTitle.constFind(target);
857 if (it != m_nodesByTargetTitle.constEnd()) {
859 if (it.value()->m_node == node)
860 return it.value()->m_ref;
862 }
while (it != m_nodesByTargetTitle.constEnd() && it.key() == target);
864 QString key = TextUtils::asAsciiPrintable(target);
865 it = m_nodesByTargetRef.constFind(key);
866 if (it != m_nodesByTargetRef.constEnd()) {
868 if (it.value()->m_node == node)
869 return it.value()->m_ref;
871 }
while (it != m_nodesByTargetRef.constEnd() && it.key() == key);
877
878
879
880
881
883 Node *node,
int priority)
885 auto *target =
new TargetRec(name, type, node, priority);
886 m_nodesByTargetRef.insert(name, target);
887 m_nodesByTargetTitle.insert(title, target);
891
892
893
894
895
896
897
900 for (
auto *child : root->childNodes()) {
901 addToPageNodeByTitleMap(child);
902 populateTocSectionTargetMap(child);
903 addKeywordsToTargetMaps(child);
904 addTargetsToTargetMap(child);
906 if (child->isAggregate())
907 resolveTargets(
static_cast<Aggregate *>(child));
914
915
916
917
918void Tree::addTargetsToTargetMap(
Node *node) {
922 QSet<QString> usedRefs;
923 for (
const Atom *heading : node->doc().tableOfContents())
924 usedRefs.insert(refForAtom(heading));
926 usedRefs.insert(
"details"_L1);
928 for (Atom *i : std::as_const(node->doc().targets())) {
929 QString ref = refForAtom(i);
930 const QString title = i->string();
931 if (!ref.isEmpty() && !title.isEmpty()) {
932 const QString rawRef = TextUtils::asAsciiPrintable(title);
935 if (i->count() == 1 && usedRefs.contains(rawRef)
936 && (!nextSection(i) || ref != rawRef)) {
937 const QString base = rawRef +
"-target"_L1;
939 for (
int n = 2; usedRefs.contains(ref); ++n)
940 ref = base +
'-'_L1 + QString::number(n);
943 usedRefs.insert(ref);
944 QString key = TextUtils::asAsciiPrintable(title);
945 auto *target =
new TargetRec(std::move(ref), TargetRec::Target, node, 2);
946 m_nodesByTargetRef.insert(key, target);
947 m_nodesByTargetTitle.insert(title, target);
953
954
955
956
965
966
967
968
969void Tree::addKeywordsToTargetMaps(
Node *node) {
973 for (Atom *i : std::as_const(node->doc().keywords())) {
974 QString ref = refForAtom(i);
975 QString title = i->string();
976 if (!ref.isEmpty() && !title.isEmpty()) {
977 auto *target =
new TargetRec(ref, nextSection(i) ? TargetRec::ContentsKeyword : TargetRec::Keyword, node, 1);
978 m_nodesByTargetRef.insert(TextUtils::asAsciiPrintable(title), target);
979 m_nodesByTargetTitle.insert(title, target);
980 if (!target->isEmpty())
981 i->append(target->m_ref);
987
988
989
990
991
992void Tree::populateTocSectionTargetMap(
Node *node) {
996 QStack<Atom *> tocLevels;
997 QSet<QString> anchors;
1000 QString memberRef = node->isPageNode() ? QString() : computeAnchorId(node);
1002 const auto *shared =
static_cast<
const SharedCommentNode *>(node);
1003 if (!shared->collective().isEmpty())
1004 memberRef = computeAnchorId(shared->collective().first());
1007 qsizetype index = 0;
1009 for (Atom *atom: std::as_const(node->doc().tableOfContents())) {
1010 while (!tocLevels.isEmpty() && tocLevels.top()->string().toInt() >= atom->string().toInt())
1013 tocLevels.push(atom);
1015 QString ref = refForAtom(atom);
1016 const QString &title = Text::sectionHeading(atom).toString();
1017 if (ref.isEmpty() || title.isEmpty())
1020 if (!memberRef.isEmpty() && node->parent() && node->parent()->isAggregate()) {
1021 const auto *page =
static_cast<
const Aggregate *>(node->parent());
1022 bool collides =
false;
1023 for (
const Node *sibling : page->childNodes()) {
1024 if (sibling == node)
1026 for (
const Atom *heading : sibling->doc().tableOfContents()) {
1027 if (TextUtils::asAsciiPrintable(Text::sectionHeading(heading).toString()) == ref) {
1036 ref = memberRef +
'-'_L1 + ref;
1037 }
else if (node->isAggregate()) {
1039 const auto *aggregate =
static_cast<
const Aggregate *>(node);
1040 for (
const Node *child : aggregate->childNodes()) {
1041 if (computeAnchorId(child) == ref) {
1042 ref +=
"-section"_L1;
1050 if (ref ==
"details"_L1 && node->isPageNode()) {
1051 ref +=
"-section"_L1;
1052 }
else if (ref ==
"signals"_L1 && node->isAggregate()) {
1053 const auto *aggregate =
static_cast<
const Aggregate *>(node);
1054 for (
const Node *child : aggregate->childNodes()) {
1055 if (child->isFunction() &&
static_cast<
const FunctionNode *>(child)->isSignal()) {
1056 ref +=
"-section"_L1;
1062 if (anchors.contains(ref)) {
1063 QStringList refParts;
1064 for (
const auto tocLevel : tocLevels)
1065 refParts << refForAtom(tocLevel);
1067 refParts << QString::number(index);
1068 ref = refParts.join(QLatin1Char(
'-'));
1071 anchors.insert(ref);
1072 if (atom->next(Atom::SectionHeadingLeft) && atom->next()->count() == 1)
1073 atom->next()->append(ref);
1076 const QString &key = TextUtils::asAsciiPrintable(title);
1077 auto *target =
new TargetRec(ref, TargetRec::Contents, node, 3);
1078 m_nodesByTargetRef.insert(key, target);
1079 m_nodesByTargetTitle.insert(title, target);
1084
1085
1086
1087
1088
1089void Tree::addToPageNodeByTitleMap(
Node *node) {
1093 auto *pageNode =
static_cast<PageNode *>(node);
1094 QString key = pageNode->title();
1098 if (key.contains(QChar(
' ')))
1099 key = TextUtils::asAsciiPrintable(key);
1100 const QList<PageNode *> nodes = m_pageNodesByTitle.values(key);
1102 bool alreadyThere =
std::any_of(nodes.cbegin(), nodes.cend(), [&](
const auto &knownNode) {
1103 return knownNode->isExternalPage() && knownNode->name() == pageNode->name();
1107 m_pageNodesByTitle.insert(key, pageNode);
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127const TargetRec *
Tree::findUnambiguousTarget(
const QString &target, Genus genus,
const Node *start)
const
1130 auto closelyRelated = [](
const Node *n1,
const Node *n2) {
1133 return (n1 == n2) || (n1->parent() == n2) || (n1 == n2->parent());
1136 enum class TargetCategory { Keyword, Nearby, Other };
1138 auto rank = [&](
const TargetRec *candidate) {
1139 auto category = TargetCategory::Other;
1141 category = TargetCategory::Keyword;
1142 }
else if (closelyRelated(candidate
->m_node, start)) {
1143 category = TargetCategory::Nearby;
1146 return std::pair{category, candidate->m_priority};
1149 auto findBestCandidate = [&](
const TargetMap &tgtMap,
const QString &key) {
1151 auto [it, end] = tgtMap.equal_range(key);
1154 if ((genus == Genus::DontCare) || hasCommonGenusType(genus, candidate
->genus())) {
1155 if (!best || rank(candidate) < rank(best))
1163 TargetRec *bestTarget = findBestCandidate(m_nodesByTargetTitle, target);
1165 bestTarget = findBestCandidate(m_nodesByTargetRef, TextUtils::asAsciiPrintable(target));
1171
1172
1173const PageNode *
Tree::findPageNodeByTitle(
const QString &title)
const
1175 PageNodeMultiMap::const_iterator it;
1176 if (title.contains(QChar(
' ')))
1177 it = m_pageNodesByTitle.constFind(TextUtils::asAsciiPrintable(title));
1179 it = m_pageNodesByTitle.constFind(title);
1180 if (it != m_pageNodesByTitle.constEnd()) {
1182
1183
1184
1185
1186 PageNodeMultiMap::const_iterator j = it;
1188 if (j != m_pageNodesByTitle.constEnd() && j.key() == it.key()) {
1189 while (j != m_pageNodesByTitle.constEnd()) {
1190 if (j.key() == it.key() && j.value()->url().isEmpty()) {
1195 if (j != m_pageNodesByTitle.cend()) {
1196 it.value()->location().warning(
"This page title exists in more than one file: "
1198 j.value()->location().warning(
"[It also exists here]");
1207
1208
1209
1210
1211
1212
1222 if (atom->count() >= 2)
1223 return atom->string(1);
1228 if (atom->count() >= 2)
1229 return atom->string(1);
1230 if (
const auto *section = nextSection(atom))
1231 return refForAtom(section);
1232 return TextUtils::asAsciiPrintable(atom->string());
1239
1240
1241
1242
1245
1246
1247
1248
1251
1252
1253
1254
1257
1258
1259
1268 return &m_qmlModules;
1278
1279
1280
1281
1282
1285 CNMap *map = getCollectionMap(type);
1287 auto it = map->constFind(name);
1288 if (it != map->cend())
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1310 CNMap *m = getCollectionMap(type);
1313 auto it = m->constFind(name);
1314 if (it != m->cend())
1318 m->insert(name, cn);
1323
1324
1325
1326
1327
1328
1329
1332
1333
1334
1335
1336
1337
1338
1341
1342
1343
1344
1345
1346
1347
1350
1351
1352
1353
1354
1355
1358
1359
1360
1361
1362
1363
1366
1367
1368
1369
1370
1371
1374
1375
1376
1377
1378
1379
1380
1381
1387 node->appendGroupName(name);
1393
1394
1395
1396
1397
1398
1403 node->setPhysicalModuleName(name);
1408
1409
1410
1411
1412
1416 QStringList dotSplit;
1417 QStringList blankSplit = name.split(QLatin1Char(
' '));
1418 qmid.append(blankSplit[0]);
1419 if (blankSplit.size() > 1) {
1420 qmid.append(blankSplit[0] + blankSplit[1]);
1421 dotSplit = blankSplit[1].split(QLatin1Char(
'.'));
1422 qmid.append(blankSplit[0] + dotSplit[0]);
1429 QmlTypeNode *n =
static_cast<QmlTypeNode *>(node);
1430 for (
int i = 0; i < qmid.size(); ++i) {
1431 QString key = qmid[i] +
"::" + node->name();
1432 insertQmlType(key, n);
1435 insertQmlType(node->name(), n);
1441
1442
1443
1444
1447 m_qmlTypeMap.insert(key, n);
1451
1452
1453
1454
1455
1458 auto values = m_qmlTypeMap.values(name);
1459 if (values.isEmpty())
1463 if (!relative || values.size() == 1)
1464 return values.first();
1468 const auto *relativeQmlType =
static_cast<
const QmlTypeNode *>(relative);
1469 const CollectionNode *relativeModule = relativeQmlType->logicalModule();
1471 for (
auto *candidate : values) {
1472 if (candidate->logicalModule() == relativeModule)
1478 return values.first();
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1494 const Node *relative, Genus genus)
const
1496 if (path.size() == 3 && !path[0].isEmpty()
1497 && ((genus == Genus::QML) || (genus == Genus::DontCare))) {
1498 QmlTypeNode *qcn = lookupQmlType(QString(path[0] +
"::" + path[1]), relative);
1499 if (qcn ==
nullptr) {
1500 QStringList p(path[1]);
1501 Node *n = findNodeByNameAndType(p, &Node::isQmlType);
1502 if ((n !=
nullptr) && n->isQmlType())
1503 qcn =
static_cast<QmlTypeNode *>(n);
1509 if (relative ==
nullptr)
1511 else if (genus != Genus::DontCare) {
1512 if (!(hasCommonGenusType(genus, relative
->genus())))
1517 Node *node =
const_cast<
Node *>(relative);
1520 for (i = 0; i < path.size(); ++i) {
1524 Aggregate *aggregate =
static_cast<Aggregate *>(node);
1525 Node *next =
nullptr;
1526 if (i == path.size() - 1)
1529 next = aggregate->findChildNode(path.at(i), genus);
1532 const ClassList bases = allBaseClasses(
static_cast<
const ClassNode *>(aggregate));
1533 for (
auto *base : bases) {
1534 if (i == path.size() - 1)
1535 next = base->findFunctionChild(path.at(i), parameters);
1537 next = base->findChildNode(path.at(i), genus);
1539 if (next !=
nullptr)
1555 const FunctionNode *fn =
static_cast<
const FunctionNode *>(node);
1557 while (FN
->isPrivate() && !FN->overridesThis().isEmpty()) {
1558 QStringList path = FN->overridesThis().split(
"::");
1559 FN = m_qdb->findFunctionNode(path, parameters, relative, genus);
1573
1574
1575
1576
1579 if (parent ==
nullptr)
1582 for (Node *n : children) {
1583 if (n !=
nullptr && n->isFunction() && n->hasTag(tag))
1584 return static_cast<FunctionNode *>(n);
1586 for (Node *n : children) {
1587 if (n !=
nullptr && n->isAggregate()) {
1588 n = findFunctionNodeForTag(tag,
static_cast<Aggregate *>(n));
1590 return static_cast<FunctionNode *>(n);
1597
1598
1599
1602 if (parent ==
nullptr)
1605 for (Node *n : children) {
1606 if (n !=
nullptr && (n->isMacro() || n->isFunction()) && n->name() == t)
1607 return static_cast<FunctionNode *>(n);
1609 for (Node *n : children) {
1610 if (n !=
nullptr && n->isAggregate()) {
1611 FunctionNode *fn = findMacroNode(t,
static_cast<Aggregate *>(n));
1620
1621
1622
1625 arg.remove(QChar(
'('));
1626 arg.remove(QChar(
')'));
1627 QString t = arg.simplified();
1628 QStringList sl = t.split(QChar(
' '));
1631 for (
const QString &s : sl) {
1632 if (!m_dontDocumentMap.contains(s))
1633 m_dontDocumentMap.insert(s,
nullptr);
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1652 for (
auto it = m_dontDocumentMap.begin(); it != m_dontDocumentMap.end(); ++it) {
1653 Aggregate *node = findAggregate(it.key());
1654 if (node !=
nullptr)
FunctionNode * findFunctionChild(const FunctionNode *clone)
Returns the function node that is a child of this node, such that the function described has the same...
const NodeList & childNodes() const
Returns a const reference to the child list.
The Atom class is the fundamental unit for representing documents internally.
AtomType type() const
Return the type of this atom.
const Atom * next() const
Return the next atom in the atom list.
const Atom * next(AtomType t) const
Return the next Atom in the list if it is of AtomType t.
The ClassNode represents a C++ class.
void removePrivateAndInternalBases()
Remove private and internal bases classes from this class's list of base classes.
A class for holding the members of a collection of doc pages.
void addMember(Node *node) override
Appends node to the collection node's member list and updates the new member's status.
bool hasTableOfContents() const
This node is used to represent any kind of function being documented.
static bool requiresDocumentation(const InclusionPolicy &policy, const NodeContext &context)
This class represents a C++ namespace.
A PageNode is a Node that generates a documentation page.
This class describes one instance of using the Q_PROPERTY macro.
const PropertyNode * overriddenFrom() const
void addFunction(FunctionNode *function, FunctionRole role)
void setOverriddenFrom(const PropertyNode *baseProperty)
Sets this property's {overridden from} property to baseProperty, which indicates that this property o...
void addSignal(FunctionNode *function, FunctionRole role)
This class provides exclusive access to the qdoc database, which consists of a forrest of trees and a...
Status
Specifies the status of the QQmlIncubator.
QmlTypeNode * qmlBaseNode() const override
If this Aggregate is a QmlTypeNode, this function returns a pointer to the QmlTypeNode that is its ba...
static Text sectionHeading(const Atom *sectionBegin)
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 addToDontDocumentMap(QString &arg)
Add the class and struct names in arg to the {don't document} map.
Node * findNodeByNameAndType(const QStringList &path, bool(Node::*isMatch)() const) const
Find the node with the specified path name that is of the specified type and subtype.
void resolveProperties()
Resolves access functions associated with each PropertyNode stored in m_unresolvedPropertyMap,...
void addPropertyFunction(PropertyNode *property, const QString &funcName, PropertyNode::FunctionRole funcRole)
Inserts function name funcName and function role funcRole into the property function map for the spec...
Combined button and popup list for selecting options.
QList< ClassNode * > ClassList
QList< Node * > NodeVector
QMap< QString, CollectionNode * > CNMap
The Node class is the base class for all the nodes in QDoc's parse tree.
const Doc & doc() const
Returns a reference to the node's Doc data member.
virtual bool isWrapper() const
Returns true if the node is a class node or a QML type node that is marked as being a wrapper class o...
bool isPrivate() const
Returns true if this node's access is Private.
virtual void setQmlModule(CollectionNode *)
If this is a QmlTypeNode, this function sets the QML type's QML module pointer to the CollectionNode ...
bool isQmlType() const
Returns true if the node type is QmlType or QmlValueType.
bool isSharedCommentNode() const
Returns true if the node type is SharedComment.
virtual bool isInternal() const
Returns true if the node's status is Internal, or if its parent is a class with Internal status.
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.
bool isEnumType() const
Returns true if the node type is Enum.
virtual Status status() const
Returns the node's status value.
virtual bool isTextPageNode() const
Returns true if the node is a PageNode but not an Aggregate.
virtual bool isAttached() const
Returns true if the QML property or QML method node is marked as attached.
Aggregate * parent() const
Returns the node's parent pointer, that is, the aggregate under which the node is documented.
virtual bool isAggregate() const
Returns true if this node is an aggregate, which means it inherits Aggregate and can therefore have c...
const Location & location() const
If this node's definition location is empty, this function returns this node's declaration location.
Access access() const
Returns the node's Access setting, which can be Public, Protected, or Private.
bool isFunction(Genus g=Genus::DontCare) const
Returns true if this is a FunctionNode and its Genus is set to g.
bool isProperty() const
Returns true if the node type is Property.
NodeContext createContext() const
bool hasDoc() const
Returns true if this node is documented, or it represents a documented node read from the index ('had...
virtual bool isClassNode() const
Returns true if this is an instance of ClassNode.
virtual void setStatus(Status t)
Sets the node's status to t.
bool isQmlProperty() const
Returns true if the node type is QmlProperty.
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.
static const Atom * nextSection(const Atom *a)
QMultiMap< QString, TargetRec * > TargetMap