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())
166 for (
auto *fn : *map_it) {
168 if (fn->isPrimaryOverload() && !fn->isInternal())
174 if (!fallback && !fn->isInternal() && !fn->isDeprecated()
175 && !fn->isDeletedAsWritten())
179 if (!lastResort && !fn->isInternal() && !fn->isDeletedAsWritten())
183 if (!deletedFallback && !fn->isInternal())
184 deletedFallback = fn;
194 return deletedFallback;
198 auto match_it =
std::find_if((*map_it).begin(), (*map_it).end(),
204 for (
int i = 0; i < parameters
.count(); ++i)
210 return (match_it != (*map_it).end()) ? *match_it :
nullptr;
214
215
216
217
218
219
222 auto funcs_it = m_functionMap.find(clone->name());
223 if (funcs_it == m_functionMap.end())
226 auto func_it =
std::find_if((*funcs_it).begin(), (*funcs_it).end(),
231 return func_it != (*funcs_it).end() ? *func_it :
nullptr;
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
282 auto &config = Config::instance();
291 if (Config::matchesInternalFilePattern(
293 config.getInternalFilePatternsCompiled()))
298 "No output generated for %1 '%2' because '%3' is undocumented"_L1
299 .arg(child->nodeTypeString(),
300 child->plainFullName(),
301 child->parent()->name()));
306
307
308
311 for (
auto *child : std::as_const(m_children)) {
312 if (!child->hasDoc() && !child->isDontDocument()) {
313 if (!child->docMustBeGenerated()) {
314 if (child->isFunction()) {
315 if (
static_cast<FunctionNode *>(child)->hasAssociatedProperties())
317 }
else if (child->isTypedef() && child->isInAPI()) {
318 if (
static_cast<TypedefNode *>(child)->hasAssociatedEnum())
321 child->setStatus(Status::InternalAuto);
324 warnAboutDocumentedChildInUndocumentedParent(
this, child);
326 if (child->isAggregate()) {
327 static_cast<Aggregate *>(child)->markUndocumentedChildrenInternal();
333
334
335
336
337
338
339
340
350 for (
auto *node : children) {
351 if (node->genus() != Genus::CPP)
354 if (!node->isAggregate()) {
355 const auto &relates_args = node->doc().metaCommandArgs(
"relates"_L1);
356 if (relates_args.isEmpty())
364 if (node->isRelatedNonmember() && node->parent() !=
this)
367 auto *aggregate = database->findRelatesNode(relates_args[0].first.split(
"::"_L1));
369 Location().report(
"Failed to find \\relates target '%1' for %2"_L1
370 .arg(relates_args[0].first, node->fullName()));
372 if (!aggregate || aggregate->isIndexNode())
373 aggregate =
new ProxyNode(
this, relates_args[0].first);
374 else if (node->parent() == aggregate)
377 aggregate->adoptChild(node);
378 node->setRelatedNonmember(
true);
380 static_cast<Aggregate*>(node)->resolveRelates();
386
387
388
389
390
391
392
393
394
395
396
397
400 for (
auto &map_it : m_functionMap) {
401 if (map_it.size() == 1) {
402 map_it.front()->setOverloadNumber(0);
403 }
else if (map_it.size() > 1) {
405 std::vector<
const FunctionNode*> primaryOverloads;
406 for (
const auto *fn : map_it) {
407 if (!fn->isPrimaryOverload())
411 const auto *currentLocation = &(fn->doc().location());
412 for (
const auto *existingPrimary : primaryOverloads) {
413 const auto *existingLocation = &(existingPrimary->doc().location());
415 if (*currentLocation != *existingLocation) {
416 fn->doc().location().warning(
417 "Multiple primary overloads for '%1'. The previous primary is here: %2"_L1
418 .arg(fn->name(), existingPrimary->doc().location().toString()));
423 primaryOverloads.push_back(fn);
426 std::sort(map_it.begin(), map_it.end(),
427 [](
const FunctionNode *f1,
const FunctionNode *f2) ->
bool {
428 if (f1->isInternal() != f2->isInternal())
429 return f2->isInternal();
431 if (f1->isPrimaryOverload() != f2->isPrimaryOverload())
432 return f1->isPrimaryOverload();
433 if (f1->isOverload() != f2->isOverload())
434 return f2->isOverload();
436 if (f1->hasDoc() != f2->hasDoc())
438 return (compare(f1, f2) < 0);
446 for (
auto *fn : map_it) {
447 if (fn->hasDoc() && fn->parent() ==
this)
448 fn->setOverloadNumber(n++);
453 for (
auto *node : std::as_const(m_children)) {
454 if (node->isAggregate())
455 static_cast<Aggregate *>(node)->normalizeOverloads();
460
461
462
463
464
465
466
471 std::remove_if(result.begin(), result.end(),
472 [](
const Node *node) {
480
481
482
485
486
487
488
489
492 for (
const auto *node : m_enumChildren) {
493 const auto *en =
static_cast<
const EnumNode *>(node);
494 if (en->hasItem(enumValue))
501
502
503
504
505
508 m_nonfunctionMap.insert(title, child);
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
533 child->setUrl(QString());
537 m_functionMap[child->name()].emplace_back(
static_cast<FunctionNode *>(child));
538 }
else if (!child->name().isEmpty()) {
539 m_nonfunctionMap.insert(child->name(), child);
541 m_enumChildren.append(child);
546
547
548
549
550
551
552
559 m_functionMap[child->name()].emplace_back(
static_cast<FunctionNode *>(child));
560 }
else if (!child->name().isEmpty()) {
561 m_nonfunctionMap.insert(child->name(), child);
563 m_enumChildren.append(child);
566 auto *scn =
static_cast<SharedCommentNode *>(child);
567 for (Node *n : scn->collective())
574
575
576
580 for (
auto *child : std::as_const(m_children)) {
581 if (child->nodeType() == goal) {
582 if (child->name() == n) {
583 if (attached == AnyProperties
584 || (child->isAttached() && attached == AttachedProperties)
585 || (!child->isAttached() && attached == UnattachedProperties))
586 return static_cast<QmlPropertyNode *>(child);
594
595
596
597
598
601 auto it = m_functionMap.find(fn->name());
602 return !(it == m_functionMap.end()) && (it.value().size() > 1);
606
607
608
609
610
611
612
621
622
623
624
625
626
627
630 for (
auto functions : m_functionMap) {
631 std::for_each(functions.begin(), functions.end(),
632 [&functionIndex](FunctionNode *fn) {
634 functionIndex[fn->name()].insert(fn->parent()->fullDocumentName(), fn);
639 for (Node *node : std::as_const(m_children)) {
640 if (node->isAggregate() && !node->isPrivate() && !node->isDontDocument())
641 static_cast<Aggregate *>(node)->findAllFunctions(functionIndex);
646
647
648
649
650
651
652
653
654
655
656
657
658
661 for (
auto *node : std::as_const(m_children)) {
662 if (node->isAggregate() && !node->isPrivate()) {
663 if (node->isNamespace() && !node->name().isEmpty())
664 namespaces.insert(node->name(), node);
665 static_cast<Aggregate *>(node)->findAllNamespaces(namespaces);
671
672
673
676 for (
const auto *node : m_children)
677 if (!node->isPrivate() && node->isDeprecated()) {
678 if (node->isFunction() || node->isProperty() || node->isEnumType() || node->isTypedef()
679 || node->isTypeAlias() || node->isVariable() || node->isQmlProperty())
686
687
688
689
690
693 for (
auto *node : std::as_const(m_children)) {
694 if (!node->isPrivate()) {
695 if (node->isDeprecated()) {
696 if (node->isClassNode())
697 QDocDatabase::obsoleteClasses().insert(node->qualifyCppName(), node);
698 else if (node->isQmlType())
699 QDocDatabase::obsoleteQmlTypes().insert(node->qualifyQmlName(), node);
700 }
else if (node->isClassNode()) {
701 auto *a =
static_cast<Aggregate *>(node);
702 if (a->hasObsoleteMembers())
703 QDocDatabase::classesWithObsoleteMembers().insert(node->qualifyCppName(), node);
704 }
else if (node->isQmlType()) {
705 auto *a =
static_cast<Aggregate *>(node);
706 if (a->hasObsoleteMembers())
707 QDocDatabase::qmlTypesWithObsoleteMembers().insert(node->qualifyQmlName(),
709 }
else if (node->isAggregate()) {
710 static_cast<Aggregate *>(node)->findAllObsoleteThings();
717
718
719
720
723 for (
auto *node : std::as_const(m_children)) {
724 if (!node->isPrivate() && !node->isInternal() && !node->isDontDocument()
725 && node->tree()->camelCaseModuleName() != QString(
"QDoc")) {
726 if (node->isClassNode()) {
727 QDocDatabase::cppClasses().insert(node->qualifyCppName().toLower(), node);
728 }
else if (node->isQmlType()) {
729 QString name = node->name().toLower();
730 QDocDatabase::qmlTypes().insert(name, node);
732 if (node->isQmlBasicType())
733 QDocDatabase::qmlBasicTypes().insert(name, node);
734 }
else if (node->isExample()) {
736 QString title = node->tree()->indexTitle();
737 if (!QDocDatabase::examples().contains(title, node))
738 QDocDatabase::examples().insert(title, node);
739 }
else if (node->isAggregate()) {
740 static_cast<Aggregate *>(node)->findAllClasses();
747
748
749
752 for (
auto *node : std::as_const(m_children)) {
753 if (!node->isPrivate()) {
754 if (node->isPageNode() &&
static_cast<PageNode*>(node)->isAttribution())
755 attributions.insert(node->tree()->indexTitle(), node);
756 else if (node->isAggregate())
757 static_cast<Aggregate *>(node)->findAllAttributions(attributions);
763
764
765
766
767
768
769
772 for (
auto *node : std::as_const(m_children)) {
773 if (node->isRelatedNonmember() && node->parent() !=
this)
775 QString sinceString = node->since();
777 if (node->isInAPI() && !sinceString.isEmpty()) {
780 auto &nsmap = QDocDatabase::newSinceMaps()[sinceString];
781 auto &ncmap = QDocDatabase::newClassMaps()[sinceString];
782 auto &nqcmap = QDocDatabase::newQmlTypeMaps()[sinceString];
784 if (node->isFunction()) {
786 auto *fn =
static_cast<FunctionNode *>(node);
787 if (!fn->isDeprecated() && !fn->isSomeCtor() && !fn->isDtor())
788 nsmap.insert(fn->name(), fn);
789 }
else if (node->isClassNode()) {
791 QString name = node->qualifyWithParentName();
792 nsmap.insert(name, node);
793 ncmap.insert(name, node);
794 }
else if (node->isQmlType()) {
796 QString name = node->qualifyWithParentName();
797 nsmap.insert(name, node);
798 nqcmap.insert(name, node);
799 }
else if (node->isQmlProperty()) {
801 nsmap.insert(node->name(), node);
802 }
else if (node->isConcept()) {
804 nsmap.insert(node->qualifyWithParentName(), node);
807 QString name = node->qualifyWithParentName();
808 nsmap.insert(name, node);
812 if (node->isInAPI() && node->isEnumType()) {
813 for (
const auto &val :
static_cast<EnumNode *>(node)->items()) {
814 sinceString = val.since();
815 if (sinceString.isEmpty())
818 QDocDatabase::newEnumValueMaps()[sinceString].insert(
819 node->name() +
"::" + val.name(), node);
823 QDocDatabase::newSinceMaps()[sinceString].replace(QString(), node);
828 if (node->isAggregate())
829 static_cast<Aggregate *>(node)->findAllSince();
834
835
836
840 for (
auto *child : std::as_const(m_children)) {
841 if (!child->isQmlType())
843 static_cast<QmlTypeNode *>(child)->resolveInheritance(previousSearches);
847 for (
auto *child : std::as_const(m_children)) {
848 if (child->isQmlType())
849 static_cast<QmlTypeNode *>(child)->checkInheritance();
854
855
856
857
862 case NodeType::Class:
864 case NodeType::Struct:
866 case NodeType::Union:
868 case NodeType::Namespace:
869 return "Namespace"_L1;
875 case NodeType::Class:
877 case NodeType::Struct:
879 case NodeType::Union:
881 case NodeType::Namespace:
882 return "namespace"_L1;
891
892
895
896
899
900
903
904
907
908
909
910
911
914
915
916
917
920
921
922
923
924
927
928
929
930
931
932
933
static void warnAboutDocumentedChildInUndocumentedParent(const Node *aggregate, const Node *child)
static bool keep(FunctionNode *fn)
NodeList nonFunctionChildren() const
Returns a copy of the child nodes of this aggregate that are not function nodes, in the order they ap...
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.
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.
QmlPropertyNode * hasQmlProperty(const QString &, PropertySearchType attached=AnyProperties) const
If this node has a child that is a QML property named n and that also matches attached,...
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...
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.
const Location & location() const
Returns the starting location of a qdoc comment.
bool isAutoGenerated() const
Returns true if this documentation was auto-generated by QDoc rather than written by an author.
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.
static bool processInternalDocs(const InclusionPolicy &policy)
bool isEmpty() const
Returns true if there is no file name set yet; returns false otherwise.
This class provides exclusive access to the qdoc database, which consists of a forrest of trees and a...
static QDocDatabase * qdocDB()
Creates the singleton.
Status
Specifies the status of the QQmlIncubator.
#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.
const Doc & doc() const
Returns a reference to the node's Doc data member.
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.
const Location & declLocation() const
Returns the Location where this node's declaration was seen.
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.
A class for parsing and managing a function parameter list.
const Parameter & at(int i) const