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->isRelatedNonmember())
347 if (node->genus() != Genus::CPP)
350 if (!node->isAggregate()) {
351 const auto &relates_args = node->doc().metaCommandArgs(
"relates"_L1);
352 if (relates_args.isEmpty())
355 auto *aggregate = database->findRelatesNode(relates_args[0].first.split(
"::"_L1));
357 Location().report(
"Failed to find \\relates target '%1' for %2"_L1
358 .arg(relates_args[0].first, node->fullName()));
360 if (!aggregate || aggregate->isIndexNode())
361 aggregate =
new ProxyNode(
this, relates_args[0].first);
362 else if (node->parent() == aggregate)
365 aggregate->adoptChild(node);
366 node->setRelatedNonmember(
true);
368 static_cast<Aggregate*>(node)->resolveRelates();
374
375
376
377
378
379
380
381
382
383
384
385
388 for (
auto &map_it : m_functionMap) {
389 if (map_it.size() == 1) {
390 map_it.front()->setOverloadNumber(0);
391 }
else if (map_it.size() > 1) {
393 std::vector<
const FunctionNode*> primaryOverloads;
394 for (
const auto *fn : map_it) {
395 if (!fn->isPrimaryOverload())
399 const auto *currentLocation = &(fn->doc().location());
400 for (
const auto *existingPrimary : primaryOverloads) {
401 const auto *existingLocation = &(existingPrimary->doc().location());
403 if (*currentLocation != *existingLocation) {
404 fn->doc().location().warning(
405 "Multiple primary overloads for '%1'. The previous primary is here: %2"_L1
406 .arg(fn->name(), existingPrimary->doc().location().toString()));
411 primaryOverloads.push_back(fn);
414 std::sort(map_it.begin(), map_it.end(),
415 [](
const FunctionNode *f1,
const FunctionNode *f2) ->
bool {
416 if (f1->isInternal() != f2->isInternal())
417 return f2->isInternal();
419 if (f1->isPrimaryOverload() != f2->isPrimaryOverload())
420 return f1->isPrimaryOverload();
421 if (f1->isOverload() != f2->isOverload())
422 return f2->isOverload();
424 if (f1->hasDoc() != f2->hasDoc())
426 return (compare(f1, f2) < 0);
431 for (
auto *fn : map_it) {
433 fn->setOverloadNumber(n++);
438 for (
auto *node : std::as_const(m_children)) {
439 if (node->isAggregate())
440 static_cast<Aggregate *>(node)->normalizeOverloads();
445
446
447
448
449
450
451
454 if (!m_nonfunctionList.isEmpty())
455 return m_nonfunctionList;
459 m_nonfunctionList.erase(
460 std::remove_if(m_nonfunctionList.begin(), m_nonfunctionList.end(),
461 [](
const Node* node) {
464 m_nonfunctionList.end());
467 return m_nonfunctionList;
471
472
473
476
477
478
479
480
483 for (
const auto *node : m_enumChildren) {
484 const auto *en =
static_cast<
const EnumNode *>(node);
485 if (en->hasItem(enumValue))
492
493
494
495
496
499 m_nonfunctionMap.insert(title, child);
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
524 child->setUrl(QString());
528 m_functionMap[child->name()].emplace_back(
static_cast<FunctionNode *>(child));
529 }
else if (!child->name().isEmpty()) {
530 m_nonfunctionMap.insert(child->name(), child);
532 m_enumChildren.append(child);
537
538
539
540
541
542
543
550 m_functionMap[child->name()].emplace_back(
static_cast<FunctionNode *>(child));
551 }
else if (!child->name().isEmpty()) {
552 m_nonfunctionMap.insert(child->name(), child);
554 m_enumChildren.append(child);
557 auto *scn =
static_cast<SharedCommentNode *>(child);
558 for (Node *n : scn->collective())
565
566
567
571 for (
auto *child : std::as_const(m_children)) {
572 if (child->nodeType() == goal) {
573 if (child->name() == n)
574 return static_cast<QmlPropertyNode *>(child);
581
582
583
587 for (
auto *child : std::as_const(m_children)) {
588 if (child->nodeType() == goal) {
589 if (child->name() == n && child->isAttached() == attached)
590 return static_cast<QmlPropertyNode *>(child);
597
598
599
600
601
604 auto it = m_functionMap.find(fn->name());
605 return !(it == m_functionMap.end()) && (it.value().size() > 1);
609
610
611
612
613
614
615
624
625
626
627
628
629
630
633 for (
auto functions : m_functionMap) {
634 std::for_each(functions.begin(), functions.end(),
635 [&functionIndex](FunctionNode *fn) {
637 functionIndex[fn->name()].insert(fn->parent()->fullDocumentName(), fn);
642 for (Node *node : std::as_const(m_children)) {
643 if (node->isAggregate() && !node->isPrivate() && !node->isDontDocument())
644 static_cast<Aggregate *>(node)->findAllFunctions(functionIndex);
649
650
651
652
653
654
655
656
657
658
659
660
661
664 for (
auto *node : std::as_const(m_children)) {
665 if (node->isAggregate() && !node->isPrivate()) {
666 if (node->isNamespace() && !node->name().isEmpty())
667 namespaces.insert(node->name(), node);
668 static_cast<Aggregate *>(node)->findAllNamespaces(namespaces);
674
675
676
679 for (
const auto *node : m_children)
680 if (!node->isPrivate() && node->isDeprecated()) {
681 if (node->isFunction() || node->isProperty() || node->isEnumType() || node->isTypedef()
682 || node->isTypeAlias() || node->isVariable() || node->isQmlProperty())
689
690
691
692
693
696 for (
auto *node : std::as_const(m_children)) {
697 if (!node->isPrivate()) {
698 if (node->isDeprecated()) {
699 if (node->isClassNode())
700 QDocDatabase::obsoleteClasses().insert(node->qualifyCppName(), node);
701 else if (node->isQmlType())
702 QDocDatabase::obsoleteQmlTypes().insert(node->qualifyQmlName(), node);
703 }
else if (node->isClassNode()) {
704 auto *a =
static_cast<Aggregate *>(node);
705 if (a->hasObsoleteMembers())
706 QDocDatabase::classesWithObsoleteMembers().insert(node->qualifyCppName(), node);
707 }
else if (node->isQmlType()) {
708 auto *a =
static_cast<Aggregate *>(node);
709 if (a->hasObsoleteMembers())
710 QDocDatabase::qmlTypesWithObsoleteMembers().insert(node->qualifyQmlName(),
712 }
else if (node->isAggregate()) {
713 static_cast<Aggregate *>(node)->findAllObsoleteThings();
720
721
722
723
726 for (
auto *node : std::as_const(m_children)) {
727 if (!node->isPrivate() && !node->isInternal() && !node->isDontDocument()
728 && node->tree()->camelCaseModuleName() != QString(
"QDoc")) {
729 if (node->isClassNode()) {
730 QDocDatabase::cppClasses().insert(node->qualifyCppName().toLower(), node);
731 }
else if (node->isQmlType()) {
732 QString name = node->name().toLower();
733 QDocDatabase::qmlTypes().insert(name, node);
735 if (node->isQmlBasicType())
736 QDocDatabase::qmlBasicTypes().insert(name, node);
737 }
else if (node->isExample()) {
739 QString title = node->tree()->indexTitle();
740 if (!QDocDatabase::examples().contains(title, node))
741 QDocDatabase::examples().insert(title, node);
742 }
else if (node->isAggregate()) {
743 static_cast<Aggregate *>(node)->findAllClasses();
750
751
752
755 for (
auto *node : std::as_const(m_children)) {
756 if (!node->isPrivate()) {
757 if (node->isPageNode() &&
static_cast<PageNode*>(node)->isAttribution())
758 attributions.insert(node->tree()->indexTitle(), node);
759 else if (node->isAggregate())
760 static_cast<Aggregate *>(node)->findAllAttributions(attributions);
766
767
768
769
770
771
772
775 for (
auto *node : std::as_const(m_children)) {
776 if (node->isRelatedNonmember() && node->parent() !=
this)
778 QString sinceString = node->since();
780 if (node->isInAPI() && !sinceString.isEmpty()) {
783 auto &nsmap = QDocDatabase::newSinceMaps()[sinceString];
784 auto &ncmap = QDocDatabase::newClassMaps()[sinceString];
785 auto &nqcmap = QDocDatabase::newQmlTypeMaps()[sinceString];
787 if (node->isFunction()) {
789 auto *fn =
static_cast<FunctionNode *>(node);
790 if (!fn->isDeprecated() && !fn->isSomeCtor() && !fn->isDtor())
791 nsmap.insert(fn->name(), fn);
792 }
else if (node->isClassNode()) {
794 QString name = node->qualifyWithParentName();
795 nsmap.insert(name, node);
796 ncmap.insert(name, node);
797 }
else if (node->isQmlType()) {
799 QString name = node->qualifyWithParentName();
800 nsmap.insert(name, node);
801 nqcmap.insert(name, node);
802 }
else if (node->isQmlProperty()) {
804 nsmap.insert(node->name(), 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)
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.
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