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
281 auto &config = Config::instance();
290 if (Config::matchesInternalFilePattern(
292 config.getInternalFilePatternsCompiled()))
297 "No output generated for %1 '%2' because '%3' is undocumented"_L1
298 .arg(child->nodeTypeString(),
299 child->plainFullName(),
300 child->parent()->name()));
305
306
307
310 for (
auto *child : std::as_const(m_children)) {
311 if (!child->hasDoc() && !child->isDontDocument()) {
312 if (!child->docMustBeGenerated()) {
313 if (child->isFunction()) {
314 if (
static_cast<FunctionNode *>(child)->hasAssociatedProperties())
316 }
else if (child->isTypedef() && child->isInAPI()) {
317 if (
static_cast<TypedefNode *>(child)->hasAssociatedEnum())
320 child->setStatus(Status::Internal);
323 warnAboutDocumentedChildInUndocumentedParent(
this, child);
325 if (child->isAggregate()) {
326 static_cast<Aggregate *>(child)->markUndocumentedChildrenInternal();
332
333
334
335
336
337
338
339
344 for (
auto *node : m_children) {
345 if (node->genus() != Genus::CPP)
348 if (!node->isAggregate()) {
349 const auto &relates_args = node->doc().metaCommandArgs(
"relates"_L1);
350 if (relates_args.isEmpty())
358 if (node->isRelatedNonmember() && node->parent() !=
this)
361 auto *aggregate = database->findRelatesNode(relates_args[0].first.split(
"::"_L1));
363 Location().report(
"Failed to find \\relates target '%1' for %2"_L1
364 .arg(relates_args[0].first, node->fullName()));
366 if (!aggregate || aggregate->isIndexNode())
367 aggregate =
new ProxyNode(
this, relates_args[0].first);
368 else if (node->parent() == aggregate)
371 aggregate->adoptChild(node);
372 node->setRelatedNonmember(
true);
374 static_cast<Aggregate*>(node)->resolveRelates();
380
381
382
383
384
385
386
387
388
389
390
391
394 for (
auto &map_it : m_functionMap) {
395 if (map_it.size() == 1) {
396 map_it.front()->setOverloadNumber(0);
397 }
else if (map_it.size() > 1) {
399 std::vector<
const FunctionNode*> primaryOverloads;
400 for (
const auto *fn : map_it) {
401 if (!fn->isPrimaryOverload())
405 const auto *currentLocation = &(fn->doc().location());
406 for (
const auto *existingPrimary : primaryOverloads) {
407 const auto *existingLocation = &(existingPrimary->doc().location());
409 if (*currentLocation != *existingLocation) {
410 fn->doc().location().warning(
411 "Multiple primary overloads for '%1'. The previous primary is here: %2"_L1
412 .arg(fn->name(), existingPrimary->doc().location().toString()));
417 primaryOverloads.push_back(fn);
420 std::sort(map_it.begin(), map_it.end(),
421 [](
const FunctionNode *f1,
const FunctionNode *f2) ->
bool {
422 if (f1->isInternal() != f2->isInternal())
423 return f2->isInternal();
425 if (f1->isPrimaryOverload() != f2->isPrimaryOverload())
426 return f1->isPrimaryOverload();
427 if (f1->isOverload() != f2->isOverload())
428 return f2->isOverload();
430 if (f1->hasDoc() != f2->hasDoc())
432 return (compare(f1, f2) < 0);
437 for (
auto *fn : map_it) {
439 fn->setOverloadNumber(n++);
444 for (
auto *node : std::as_const(m_children)) {
445 if (node->isAggregate())
446 static_cast<Aggregate *>(node)->normalizeOverloads();
451
452
453
454
455
456
457
460 if (!m_nonfunctionList.isEmpty())
461 return m_nonfunctionList;
465 m_nonfunctionList.erase(
466 std::remove_if(m_nonfunctionList.begin(), m_nonfunctionList.end(),
467 [](
const Node* node) {
470 m_nonfunctionList.end());
473 return m_nonfunctionList;
477
478
479
482
483
484
485
486
489 for (
const auto *node : m_enumChildren) {
490 const auto *en =
static_cast<
const EnumNode *>(node);
491 if (en->hasItem(enumValue))
498
499
500
501
502
505 m_nonfunctionMap.insert(title, child);
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
530 child->setUrl(QString());
534 m_functionMap[child->name()].emplace_back(
static_cast<FunctionNode *>(child));
535 }
else if (!child->name().isEmpty()) {
536 m_nonfunctionMap.insert(child->name(), child);
538 m_enumChildren.append(child);
543
544
545
546
547
548
549
556 m_functionMap[child->name()].emplace_back(
static_cast<FunctionNode *>(child));
557 }
else if (!child->name().isEmpty()) {
558 m_nonfunctionMap.insert(child->name(), child);
560 m_enumChildren.append(child);
563 auto *scn =
static_cast<SharedCommentNode *>(child);
564 for (Node *n : scn->collective())
571
572
573
577 for (
auto *child : std::as_const(m_children)) {
578 if (child->nodeType() == goal) {
579 if (child->name() == n) {
580 if (attached == AnyProperties
581 || (child->isAttached() && attached == AttachedProperties)
582 || (!child->isAttached() && attached == UnattachedProperties))
583 return static_cast<QmlPropertyNode *>(child);
591
592
593
594
595
598 auto it = m_functionMap.find(fn->name());
599 return !(it == m_functionMap.end()) && (it.value().size() > 1);
603
604
605
606
607
608
609
618
619
620
621
622
623
624
627 for (
auto functions : m_functionMap) {
628 std::for_each(functions.begin(), functions.end(),
629 [&functionIndex](FunctionNode *fn) {
631 functionIndex[fn->name()].insert(fn->parent()->fullDocumentName(), fn);
636 for (Node *node : std::as_const(m_children)) {
637 if (node->isAggregate() && !node->isPrivate() && !node->isDontDocument())
638 static_cast<Aggregate *>(node)->findAllFunctions(functionIndex);
643
644
645
646
647
648
649
650
651
652
653
654
655
658 for (
auto *node : std::as_const(m_children)) {
659 if (node->isAggregate() && !node->isPrivate()) {
660 if (node->isNamespace() && !node->name().isEmpty())
661 namespaces.insert(node->name(), node);
662 static_cast<Aggregate *>(node)->findAllNamespaces(namespaces);
668
669
670
673 for (
const auto *node : m_children)
674 if (!node->isPrivate() && node->isDeprecated()) {
675 if (node->isFunction() || node->isProperty() || node->isEnumType() || node->isTypedef()
676 || node->isTypeAlias() || node->isVariable() || node->isQmlProperty())
683
684
685
686
687
690 for (
auto *node : std::as_const(m_children)) {
691 if (!node->isPrivate()) {
692 if (node->isDeprecated()) {
693 if (node->isClassNode())
694 QDocDatabase::obsoleteClasses().insert(node->qualifyCppName(), node);
695 else if (node->isQmlType())
696 QDocDatabase::obsoleteQmlTypes().insert(node->qualifyQmlName(), node);
697 }
else if (node->isClassNode()) {
698 auto *a =
static_cast<Aggregate *>(node);
699 if (a->hasObsoleteMembers())
700 QDocDatabase::classesWithObsoleteMembers().insert(node->qualifyCppName(), node);
701 }
else if (node->isQmlType()) {
702 auto *a =
static_cast<Aggregate *>(node);
703 if (a->hasObsoleteMembers())
704 QDocDatabase::qmlTypesWithObsoleteMembers().insert(node->qualifyQmlName(),
706 }
else if (node->isAggregate()) {
707 static_cast<Aggregate *>(node)->findAllObsoleteThings();
714
715
716
717
720 for (
auto *node : std::as_const(m_children)) {
721 if (!node->isPrivate() && !node->isInternal() && !node->isDontDocument()
722 && node->tree()->camelCaseModuleName() != QString(
"QDoc")) {
723 if (node->isClassNode()) {
724 QDocDatabase::cppClasses().insert(node->qualifyCppName().toLower(), node);
725 }
else if (node->isQmlType()) {
726 QString name = node->name().toLower();
727 QDocDatabase::qmlTypes().insert(name, node);
729 if (node->isQmlBasicType())
730 QDocDatabase::qmlBasicTypes().insert(name, node);
731 }
else if (node->isExample()) {
733 QString title = node->tree()->indexTitle();
734 if (!QDocDatabase::examples().contains(title, node))
735 QDocDatabase::examples().insert(title, node);
736 }
else if (node->isAggregate()) {
737 static_cast<Aggregate *>(node)->findAllClasses();
744
745
746
749 for (
auto *node : std::as_const(m_children)) {
750 if (!node->isPrivate()) {
751 if (node->isPageNode() &&
static_cast<PageNode*>(node)->isAttribution())
752 attributions.insert(node->tree()->indexTitle(), node);
753 else if (node->isAggregate())
754 static_cast<Aggregate *>(node)->findAllAttributions(attributions);
760
761
762
763
764
765
766
769 for (
auto *node : std::as_const(m_children)) {
770 if (node->isRelatedNonmember() && node->parent() !=
this)
772 QString sinceString = node->since();
774 if (node->isInAPI() && !sinceString.isEmpty()) {
777 auto &nsmap = QDocDatabase::newSinceMaps()[sinceString];
778 auto &ncmap = QDocDatabase::newClassMaps()[sinceString];
779 auto &nqcmap = QDocDatabase::newQmlTypeMaps()[sinceString];
781 if (node->isFunction()) {
783 auto *fn =
static_cast<FunctionNode *>(node);
784 if (!fn->isDeprecated() && !fn->isSomeCtor() && !fn->isDtor())
785 nsmap.insert(fn->name(), fn);
786 }
else if (node->isClassNode()) {
788 QString name = node->qualifyWithParentName();
789 nsmap.insert(name, node);
790 ncmap.insert(name, node);
791 }
else if (node->isQmlType()) {
793 QString name = node->qualifyWithParentName();
794 nsmap.insert(name, node);
795 nqcmap.insert(name, node);
796 }
else if (node->isQmlProperty()) {
798 nsmap.insert(node->name(), node);
801 QString name = node->qualifyWithParentName();
802 nsmap.insert(name, node);
806 if (node->isInAPI() && node->isEnumType()) {
807 for (
const auto &val :
static_cast<EnumNode *>(node)->items()) {
808 sinceString = val.since();
809 if (sinceString.isEmpty())
812 QDocDatabase::newEnumValueMaps()[sinceString].insert(
813 node->name() +
"::" + val.name(), node);
817 QDocDatabase::newSinceMaps()[sinceString].replace(QString(), node);
822 if (node->isAggregate())
823 static_cast<Aggregate *>(node)->findAllSince();
828
829
830
834 for (
auto *child : std::as_const(m_children)) {
835 if (!child->isQmlType())
837 static_cast<QmlTypeNode *>(child)->resolveInheritance(previousSearches);
841 for (
auto *child : std::as_const(m_children)) {
842 if (child->isQmlType())
843 static_cast<QmlTypeNode *>(child)->checkInheritance();
848
849
850
851
856 case NodeType::Class:
858 case NodeType::Struct:
860 case NodeType::Union:
862 case NodeType::Namespace:
863 return "Namespace"_L1;
869 case NodeType::Class:
871 case NodeType::Struct:
873 case NodeType::Union:
875 case NodeType::Namespace:
876 return "namespace"_L1;
885
886
889
890
893
894
897
898
901
902
903
904
905
908
909
910
911
914
915
916
917
918
921
922
923
924
925
926
927
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.
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...
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.
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.
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