18using namespace Qt::Literals::StringLiterals;
23
24
27
28
29
30
31
34
35
36
37
38
41 for (
auto &child : m_children) {
44 if (child->parent() !=
this)
46 else if (child->isAggregate())
47 static_cast<Aggregate*>(child)->dropNonRelatedMembers();
52
53
57 if (isNamespace() && name().isEmpty())
58 dropNonRelatedMembers();
60 m_enumChildren.clear();
61 m_nonfunctionMap.clear();
62 m_functionMap.clear();
68
69
70
71
72
73
74
75
76
79 if (genus == Genus::DontCare) {
80 Node *node = m_nonfunctionMap.value(name);
84 const NodeList &nodes = m_nonfunctionMap.values(name);
85 for (
auto *node : nodes) {
86 if (node->isInternal())
88 if (hasCommonGenusType(genus, node->genus())) {
89 if (findFlags & TypesOnly) {
90 if (!node->isTypedef() && !node->isClassNode()
91 && !node->isQmlType() && !node->isEnumType())
93 }
else if (findFlags & IgnoreModules && node->isModule())
99 if (genus != Genus::DontCare && !(hasCommonGenusType(genus,
this->genus())))
105 auto it = m_functionMap.find(name);
106 return it != m_functionMap.end() ? (*(*it).begin()) :
nullptr;
110
111
112
116 const auto &functions = m_functionMap.value(name);
117 nodes.reserve(functions.size() + m_nonfunctionMap.count(name));
118 for (
auto f : functions)
119 nodes.emplace_back(f);
120 auto [it, end] = m_nonfunctionMap.equal_range(name);
122 nodes.emplace_back(*it);
128
129
130
131
132
133
136 const NodeList &nodes = m_nonfunctionMap.values(name);
137 for (
auto *node : nodes) {
138 if ((node->*(isMatch))())
145
146
147
148
149
150
151
152
155 auto map_it = m_functionMap.find(name);
156 if (map_it == m_functionMap.end())
165 for (
auto *fn : *map_it) {
167 if (fn->isPrimaryOverload() && !fn->isInternal())
171 if (!fallback && !fn->isInternal() && !fn->isDeprecated())
175 if (!lastResort && !fn->isInternal())
189 auto match_it =
std::find_if((*map_it).begin(), (*map_it).end(),
195 for (
int i = 0; i < parameters
.count(); ++i)
201 return (match_it != (*map_it).end()) ? *match_it :
nullptr;
205
206
207
208
209
210
213 auto funcs_it = m_functionMap.find(clone->name());
214 if (funcs_it == m_functionMap.end())
217 auto func_it =
std::find_if((*funcs_it).begin(), (*funcs_it).end(),
222 return func_it != (*funcs_it).end() ? *func_it :
nullptr;
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
256 const auto &config{Config::instance()};
257 const InclusionPolicy policy = config.createInclusionPolicy();
258 if (!config.get(
CONFIG_NOLINKERRORS).asBool() && !InclusionFilter::processInternalDocs(policy))
259 child->doc().location().warning(
260 "No output generated for %1 '%2' because '%3' is undocumented"_L1
261 .arg(child->nodeTypeString(),
262 child->plainFullName(),
263 child->parent()->name()));
268
269
270
273 for (
auto *child : std::as_const(m_children)) {
274 if (!child->hasDoc() && !child->isDontDocument()) {
275 if (!child->docMustBeGenerated()) {
276 if (child->isFunction()) {
277 if (
static_cast<FunctionNode *>(child)->hasAssociatedProperties())
279 }
else if (child->isTypedef() && child->isInAPI()) {
280 if (
static_cast<TypedefNode *>(child)->hasAssociatedEnum())
283 child->setStatus(Node::Internal);
286 warnAboutDocumentedChildInUndocumentedParent(
this, child);
288 if (child->isAggregate()) {
289 static_cast<Aggregate *>(child)->markUndocumentedChildrenInternal();
295
296
297
298
299
300
301
302
307 for (
auto *node : m_children) {
308 if (node->isRelatedNonmember())
310 if (node->genus() != Genus::CPP)
313 if (!node->isAggregate()) {
314 const auto &relates_args = node->doc().metaCommandArgs(
"relates"_L1);
315 if (relates_args.isEmpty())
318 auto *aggregate = database->findRelatesNode(relates_args[0].first.split(
"::"_L1));
320 Location().report(
"Failed to find \\relates target '%1' for %2"_L1
321 .arg(relates_args[0].first, node->fullName()));
323 if (!aggregate || aggregate->isIndexNode())
324 aggregate =
new ProxyNode(
this, relates_args[0].first);
325 else if (node->parent() == aggregate)
328 aggregate->adoptChild(node);
329 node->setRelatedNonmember(
true);
331 static_cast<Aggregate*>(node)->resolveRelates();
337
338
339
340
341
342
343
344
345
346
347
348
351 for (
auto &map_it : m_functionMap) {
352 if (map_it.size() == 1) {
353 map_it.front()->setOverloadNumber(0);
354 }
else if (map_it.size() > 1) {
356 std::vector<
const FunctionNode*> primaryOverloads;
357 for (
const auto *fn : map_it) {
358 if (!fn->isPrimaryOverload())
362 const auto *currentLocation = &(fn->doc().location());
363 for (
const auto *existingPrimary : primaryOverloads) {
364 const auto *existingLocation = &(existingPrimary->doc().location());
366 if (*currentLocation != *existingLocation) {
367 fn->doc().location().warning(
368 "Multiple primary overloads for '%1'. The previous primary is here: %2"_L1
369 .arg(fn->name(), existingPrimary->doc().location().toString()));
374 primaryOverloads.push_back(fn);
377 std::sort(map_it.begin(), map_it.end(),
378 [](
const FunctionNode *f1,
const FunctionNode *f2) ->
bool {
379 if (f1->isInternal() != f2->isInternal())
380 return f2->isInternal();
382 if (f1->isPrimaryOverload() != f2->isPrimaryOverload())
383 return f1->isPrimaryOverload();
384 if (f1->isOverload() != f2->isOverload())
385 return f2->isOverload();
387 if (f1->hasDoc() != f2->hasDoc())
389 return (compare(f1, f2) < 0);
394 for (
auto *fn : map_it) {
396 fn->setOverloadNumber(n++);
401 for (
auto *node : std::as_const(m_children)) {
402 if (node->isAggregate())
403 static_cast<Aggregate *>(node)->normalizeOverloads();
408
409
410
411
412
413
414
417 if (!m_nonfunctionList.isEmpty())
418 return m_nonfunctionList;
422 m_nonfunctionList.erase(
423 std::remove_if(m_nonfunctionList.begin(), m_nonfunctionList.end(),
424 [](
const Node* node) {
427 m_nonfunctionList.end());
430 return m_nonfunctionList;
434
435
436
439
440
441
442
443
446 for (
const auto *node : m_enumChildren) {
447 const auto *en =
static_cast<
const EnumNode *>(node);
448 if (en->hasItem(enumValue))
455
456
457
458
459
462 m_nonfunctionMap.insert(title, child);
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
487 child->setUrl(QString());
491 m_functionMap[child->name()].emplace_back(
static_cast<FunctionNode *>(child));
492 }
else if (!child->name().isEmpty()) {
493 m_nonfunctionMap.insert(child->name(), child);
495 m_enumChildren.append(child);
500
501
502
503
504
505
506
513 m_functionMap[child->name()].emplace_back(
static_cast<FunctionNode *>(child));
514 }
else if (!child->name().isEmpty()) {
515 m_nonfunctionMap.insert(child->name(), child);
517 m_enumChildren.append(child);
521 for (Node *n : scn->collective())
528
529
530
534 for (
auto *child : std::as_const(m_children)) {
535 if (child->nodeType() == goal) {
536 if (child->name() == n)
537 return static_cast<QmlPropertyNode *>(child);
544
545
546
550 for (
auto *child : std::as_const(m_children)) {
551 if (child->nodeType() == goal) {
552 if (child->name() == n && child->isAttached() == attached)
553 return static_cast<QmlPropertyNode *>(child);
560
561
562
563
564
567 auto it = m_functionMap.find(fn->name());
568 return !(it == m_functionMap.end()) && (it.value().size() > 1);
572
573
574
575
576
577
578
587
588
589
590
591
592
593
596 for (
auto functions : m_functionMap) {
597 std::for_each(functions.begin(), functions.end(),
598 [&functionIndex](FunctionNode *fn) {
600 functionIndex[fn->name()].insert(fn->parent()->fullDocumentName(), fn);
605 for (Node *node : std::as_const(m_children)) {
606 if (node->isAggregate() && !node->isPrivate() && !node->isDontDocument())
607 static_cast<Aggregate *>(node)->findAllFunctions(functionIndex);
612
613
614
615
616
617
618
619
620
621
622
623
624
627 for (
auto *node : std::as_const(m_children)) {
628 if (node->isAggregate() && !node->isPrivate()) {
629 if (node->isNamespace() && !node->name().isEmpty())
630 namespaces.insert(node->name(), node);
631 static_cast<Aggregate *>(node)->findAllNamespaces(namespaces);
637
638
639
642 for (
const auto *node : m_children)
643 if (!node->isPrivate() && node->isDeprecated()) {
644 if (node->isFunction() || node->isProperty() || node->isEnumType() || node->isTypedef()
645 || node->isTypeAlias() || node->isVariable() || node->isQmlProperty())
652
653
654
655
656
659 for (
auto *node : std::as_const(m_children)) {
660 if (!node->isPrivate()) {
661 if (node->isDeprecated()) {
662 if (node->isClassNode())
663 QDocDatabase::obsoleteClasses().insert(node->qualifyCppName(), node);
664 else if (node->isQmlType())
665 QDocDatabase::obsoleteQmlTypes().insert(node->qualifyQmlName(), node);
666 }
else if (node->isClassNode()) {
667 auto *a =
static_cast<Aggregate *>(node);
668 if (a->hasObsoleteMembers())
669 QDocDatabase::classesWithObsoleteMembers().insert(node->qualifyCppName(), node);
670 }
else if (node->isQmlType()) {
671 auto *a =
static_cast<Aggregate *>(node);
672 if (a->hasObsoleteMembers())
673 QDocDatabase::qmlTypesWithObsoleteMembers().insert(node->qualifyQmlName(),
675 }
else if (node->isAggregate()) {
676 static_cast<Aggregate *>(node)->findAllObsoleteThings();
683
684
685
686
689 for (
auto *node : std::as_const(m_children)) {
690 if (!node->isPrivate() && !node->isInternal() && !node->isDontDocument()
691 && node->tree()->camelCaseModuleName() != QString(
"QDoc")) {
692 if (node->isClassNode()) {
693 QDocDatabase::cppClasses().insert(node->qualifyCppName().toLower(), node);
694 }
else if (node->isQmlType()) {
695 QString name = node->name().toLower();
696 QDocDatabase::qmlTypes().insert(name, node);
698 if (node->isQmlBasicType())
699 QDocDatabase::qmlBasicTypes().insert(name, node);
700 }
else if (node->isExample()) {
702 QString title = node->tree()->indexTitle();
703 if (!QDocDatabase::examples().contains(title, node))
704 QDocDatabase::examples().insert(title, node);
705 }
else if (node->isAggregate()) {
706 static_cast<Aggregate *>(node)->findAllClasses();
713
714
715
718 for (
auto *node : std::as_const(m_children)) {
719 if (!node->isPrivate()) {
720 if (node->isPageNode() &&
static_cast<PageNode*>(node)->isAttribution())
721 attributions.insert(node->tree()->indexTitle(), node);
722 else if (node->isAggregate())
723 static_cast<Aggregate *>(node)->findAllAttributions(attributions);
729
730
731
732
733
734
735
738 for (
auto *node : std::as_const(m_children)) {
739 if (node->isRelatedNonmember() && node->parent() !=
this)
741 QString sinceString = node->since();
743 if (node->isInAPI() && !sinceString.isEmpty()) {
746 auto &nsmap = QDocDatabase::newSinceMaps()[sinceString];
747 auto &ncmap = QDocDatabase::newClassMaps()[sinceString];
748 auto &nqcmap = QDocDatabase::newQmlTypeMaps()[sinceString];
750 if (node->isFunction()) {
752 auto *fn =
static_cast<FunctionNode *>(node);
753 if (!fn->isDeprecated() && !fn->isSomeCtor() && !fn->isDtor())
754 nsmap.insert(fn->name(), fn);
755 }
else if (node->isClassNode()) {
757 QString name = node->qualifyWithParentName();
758 nsmap.insert(name, node);
759 ncmap.insert(name, node);
760 }
else if (node->isQmlType()) {
762 QString name = node->qualifyWithParentName();
763 nsmap.insert(name, node);
764 nqcmap.insert(name, node);
765 }
else if (node->isQmlProperty()) {
767 nsmap.insert(node->name(), node);
770 QString name = node->qualifyWithParentName();
771 nsmap.insert(name, node);
775 if (node->isInAPI() && node->isEnumType()) {
776 for (
const auto &val :
static_cast<EnumNode *>(node)->items()) {
777 sinceString = val.since();
778 if (sinceString.isEmpty())
781 QDocDatabase::newEnumValueMaps()[sinceString].insert(
782 node->name() +
"::" + val.name(), node);
786 QDocDatabase::newSinceMaps()[sinceString].replace(QString(), node);
791 if (node->isAggregate())
792 static_cast<Aggregate *>(node)->findAllSince();
797
798
799
803 for (
auto *child : std::as_const(m_children)) {
804 if (!child->isQmlType())
806 static_cast<QmlTypeNode *>(child)->resolveInheritance(previousSearches);
810 for (
auto *child : std::as_const(m_children)) {
811 if (child->isQmlType())
812 static_cast<QmlTypeNode *>(child)->checkInheritance();
817
818
819
820
825 case NodeType::Class:
827 case NodeType::Struct:
829 case NodeType::Union:
831 case NodeType::Namespace:
832 return "Namespace"_L1;
838 case NodeType::Class:
840 case NodeType::Struct:
842 case NodeType::Union:
844 case NodeType::Namespace:
845 return "namespace"_L1;
854
855
858
859
862
863
866
867
870
871
872
873
874
877
878
879
880
883
884
885
886
887
890
891
892
893
894
895
896
static void warnAboutDocumentedChildInUndocumentedParent(const Node *aggregate, const Node *child)
static bool keep(FunctionNode *fn)
void resolveRelates()
Adopts each non-aggregate C++ node (function/macro, typedef, enum, variable, or a shared comment node...
void adoptChild(Node *child)
This Aggregate becomes the adoptive parent of child.
QString typeWord(bool cap) const
Returns a word representing the kind of Aggregate this node is.
void resolveQmlInheritance()
Resolves the inheritance information for all QML type children of this aggregate.
void addChildByTitle(Node *child, const QString &title)
Adds the child to this node's child map using title as the key.
QmlPropertyNode * hasQmlProperty(const QString &) const
If this node has a child that is a QML property named n, return a pointer to that child.
bool hasOverloads(const FunctionNode *fn) const
Returns true if this aggregate has multiple function overloads matching the name of fn.
void findAllObsoleteThings()
Finds all the obsolete C++ classes and QML types in this aggregate and all the C++ classes and QML ty...
~Aggregate() override
Destroys this Aggregate; deletes each child.
void findChildren(const QString &name, NodeVector &nodes) const
Find all the child nodes of this node that are named name and return them in nodes.
bool hasObsoleteMembers() const
Returns true if this aggregate contains at least one child that is marked obsolete.
FunctionNode * findFunctionChild(const QString &name, const Parameters ¶meters)
Find a function node that is a child of this node, such that the function node has the specified name...
void findAllSince()
Finds all the nodes in this node where a {since} command appeared in the qdoc comment and sorts them ...
void normalizeOverloads()
Sorts the lists of overloads in the function map and assigns overload numbers.
Node * findNonfunctionChild(const QString &name, bool(Node::*)() const)
This function searches for a child node of this Aggregate, such that the child node has the spacified...
void findAllFunctions(NodeMapMap &functionIndex)
Insert all functions declared in this aggregate into the functionIndex.
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.
void addChild(Node *child)
Adds the child to this node's child list and sets the child's parent pointer to this Aggregate.
Node * findChildNode(const QString &name, Genus genus, int findFlags=0) const
If genus is {Node::DontCare}, find the first node in this node's child list that has the given name.
FunctionNode * findFunctionChild(const FunctionNode *clone)
Returns the function node that is a child of this node, such that the function described has the same...
QmlPropertyNode * hasQmlProperty(const QString &, bool attached) const
If this node has a child that is a QML property named n and that also matches attached,...
const NodeList & nonfunctionList()
Returns a const reference to the list of child nodes of this aggregate that are not function nodes.
void findAllClasses()
Finds all the C++ classes, QML types, QML basic types, and examples in this aggregate and inserts the...
void findAllAttributions(NodeMultiMap &attributions)
Find all the attribution pages in this node and insert them into attributions.
const EnumNode * findEnumNodeForValue(const QString &enumValue) const
Finds the enum type node that has enumValue as one of its enum values and returns a pointer to it.
This node is used to represent any kind of function being documented.
const Parameters & parameters() const
bool isDeprecated() const override
\reimp
friend int compare(const FunctionNode *f1, const FunctionNode *f2)
Compares FunctionNode f1 with f2, assumed to have identical names.
This class provides exclusive access to the qdoc database, which consists of a forrest of trees and a...
static QDocDatabase * qdocDB()
Creates the singleton.
#define CONFIG_NOLINKERRORS
QList< Node * > NodeVector
QMap< QString, Node * > NodeMap
QMap< QString, NodeMap > NodeMapMap
QMultiMap< QString, Node * > NodeMultiMap
The Node class is the base class for all the nodes in QDoc's parse tree.
bool isDontDocument() const
Returns true if this node's status is DontDocument.
bool isPrivate() const
Returns true if this node's access is Private.
void setIndexNodeFlag(bool isIndexNode=true)
Sets a flag in this Node that indicates the node was created for something in an index file.
bool isNamespace() const
Returns true if the node type is Namespace.
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.
NodeType nodeType() const override
Returns this node's type.
Genus genus() const override
Returns this node's Genus.
bool isEnumType() const
Returns true if the node type is Enum.
virtual Status status() const
Returns the node's status value.
Aggregate * parent() const
Returns the node's parent pointer.
bool isProxyNode() const
Returns true if the node type is Proxy.
bool isFunction(Genus g=Genus::DontCare) const
Returns true if this is a FunctionNode and its Genus is set to g.
bool hasDoc() const
Returns true if this node is documented, or it represents a documented node read from the index ('had...
void setParent(Aggregate *n)
Sets the node's parent pointer to n.
bool isIndexNode() const
Returns true if this node was created from something in an index file.
static bool nodeLessThan(const Node *first, const Node *second)
Returns true if the node n1 is less than node n2.
A class for parsing and managing a function parameter list.
const Parameter & at(int i) const