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
345 for (
auto *node : m_children) {
346 if (node->genus() != Genus::CPP)
349 if (!node->isAggregate()) {
350 const auto &relates_args = node->doc().metaCommandArgs(
"relates"_L1);
351 if (relates_args.isEmpty())
359 if (node->isRelatedNonmember() && node->parent() !=
this)
362 auto *aggregate = database->findRelatesNode(relates_args[0].first.split(
"::"_L1));
364 Location().report(
"Failed to find \\relates target '%1' for %2"_L1
365 .arg(relates_args[0].first, node->fullName()));
367 if (!aggregate || aggregate->isIndexNode())
368 aggregate =
new ProxyNode(
this, relates_args[0].first);
369 else if (node->parent() == aggregate)
372 aggregate->adoptChild(node);
373 node->setRelatedNonmember(
true);
375 static_cast<Aggregate*>(node)->resolveRelates();
381
382
383
384
385
386
387
388
389
390
391
392
395 for (
auto &map_it : m_functionMap) {
396 if (map_it.size() == 1) {
397 map_it.front()->setOverloadNumber(0);
398 }
else if (map_it.size() > 1) {
400 std::vector<
const FunctionNode*> primaryOverloads;
401 for (
const auto *fn : map_it) {
402 if (!fn->isPrimaryOverload())
406 const auto *currentLocation = &(fn->doc().location());
407 for (
const auto *existingPrimary : primaryOverloads) {
408 const auto *existingLocation = &(existingPrimary->doc().location());
410 if (*currentLocation != *existingLocation) {
411 fn->doc().location().warning(
412 "Multiple primary overloads for '%1'. The previous primary is here: %2"_L1
413 .arg(fn->name(), existingPrimary->doc().location().toString()));
418 primaryOverloads.push_back(fn);
421 std::sort(map_it.begin(), map_it.end(),
422 [](
const FunctionNode *f1,
const FunctionNode *f2) ->
bool {
423 if (f1->isInternal() != f2->isInternal())
424 return f2->isInternal();
426 if (f1->isPrimaryOverload() != f2->isPrimaryOverload())
427 return f1->isPrimaryOverload();
428 if (f1->isOverload() != f2->isOverload())
429 return f2->isOverload();
431 if (f1->hasDoc() != f2->hasDoc())
433 return (compare(f1, f2) < 0);
438 for (
auto *fn : map_it) {
440 fn->setOverloadNumber(n++);
445 for (
auto *node : std::as_const(m_children)) {
446 if (node->isAggregate())
447 static_cast<Aggregate *>(node)->normalizeOverloads();
452
453
454
455
456
457
458
461 if (!m_nonfunctionList.isEmpty())
462 return m_nonfunctionList;
466 m_nonfunctionList.erase(
467 std::remove_if(m_nonfunctionList.begin(), m_nonfunctionList.end(),
468 [](
const Node* node) {
471 m_nonfunctionList.end());
474 return m_nonfunctionList;
478
479
480
483
484
485
486
487
490 for (
const auto *node : m_enumChildren) {
491 const auto *en =
static_cast<
const EnumNode *>(node);
492 if (en->hasItem(enumValue))
499
500
501
502
503
506 m_nonfunctionMap.insert(title, child);
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
531 child->setUrl(QString());
535 m_functionMap[child->name()].emplace_back(
static_cast<FunctionNode *>(child));
536 }
else if (!child->name().isEmpty()) {
537 m_nonfunctionMap.insert(child->name(), child);
539 m_enumChildren.append(child);
544
545
546
547
548
549
550
557 m_functionMap[child->name()].emplace_back(
static_cast<FunctionNode *>(child));
558 }
else if (!child->name().isEmpty()) {
559 m_nonfunctionMap.insert(child->name(), child);
561 m_enumChildren.append(child);
564 auto *scn =
static_cast<SharedCommentNode *>(child);
565 for (Node *n : scn->collective())
572
573
574
578 for (
auto *child : std::as_const(m_children)) {
579 if (child->nodeType() == goal) {
580 if (child->name() == n) {
581 if (attached == AnyProperties
582 || (child->isAttached() && attached == AttachedProperties)
583 || (!child->isAttached() && attached == UnattachedProperties))
584 return static_cast<QmlPropertyNode *>(child);
592
593
594
595
596
599 auto it = m_functionMap.find(fn->name());
600 return !(it == m_functionMap.end()) && (it.value().size() > 1);
604
605
606
607
608
609
610
619
620
621
622
623
624
625
628 for (
auto functions : m_functionMap) {
629 std::for_each(functions.begin(), functions.end(),
630 [&functionIndex](FunctionNode *fn) {
632 functionIndex[fn->name()].insert(fn->parent()->fullDocumentName(), fn);
637 for (Node *node : std::as_const(m_children)) {
638 if (node->isAggregate() && !node->isPrivate() && !node->isDontDocument())
639 static_cast<Aggregate *>(node)->findAllFunctions(functionIndex);
644
645
646
647
648
649
650
651
652
653
654
655
656
659 for (
auto *node : std::as_const(m_children)) {
660 if (node->isAggregate() && !node->isPrivate()) {
661 if (node->isNamespace() && !node->name().isEmpty())
662 namespaces.insert(node->name(), node);
663 static_cast<Aggregate *>(node)->findAllNamespaces(namespaces);
669
670
671
674 for (
const auto *node : m_children)
675 if (!node->isPrivate() && node->isDeprecated()) {
676 if (node->isFunction() || node->isProperty() || node->isEnumType() || node->isTypedef()
677 || node->isTypeAlias() || node->isVariable() || node->isQmlProperty())
684
685
686
687
688
691 for (
auto *node : std::as_const(m_children)) {
692 if (!node->isPrivate()) {
693 if (node->isDeprecated()) {
694 if (node->isClassNode())
695 QDocDatabase::obsoleteClasses().insert(node->qualifyCppName(), node);
696 else if (node->isQmlType())
697 QDocDatabase::obsoleteQmlTypes().insert(node->qualifyQmlName(), node);
698 }
else if (node->isClassNode()) {
699 auto *a =
static_cast<Aggregate *>(node);
700 if (a->hasObsoleteMembers())
701 QDocDatabase::classesWithObsoleteMembers().insert(node->qualifyCppName(), node);
702 }
else if (node->isQmlType()) {
703 auto *a =
static_cast<Aggregate *>(node);
704 if (a->hasObsoleteMembers())
705 QDocDatabase::qmlTypesWithObsoleteMembers().insert(node->qualifyQmlName(),
707 }
else if (node->isAggregate()) {
708 static_cast<Aggregate *>(node)->findAllObsoleteThings();
715
716
717
718
721 for (
auto *node : std::as_const(m_children)) {
722 if (!node->isPrivate() && !node->isInternal() && !node->isDontDocument()
723 && node->tree()->camelCaseModuleName() != QString(
"QDoc")) {
724 if (node->isClassNode()) {
725 QDocDatabase::cppClasses().insert(node->qualifyCppName().toLower(), node);
726 }
else if (node->isQmlType()) {
727 QString name = node->name().toLower();
728 QDocDatabase::qmlTypes().insert(name, node);
730 if (node->isQmlBasicType())
731 QDocDatabase::qmlBasicTypes().insert(name, node);
732 }
else if (node->isExample()) {
734 QString title = node->tree()->indexTitle();
735 if (!QDocDatabase::examples().contains(title, node))
736 QDocDatabase::examples().insert(title, node);
737 }
else if (node->isAggregate()) {
738 static_cast<Aggregate *>(node)->findAllClasses();
745
746
747
750 for (
auto *node : std::as_const(m_children)) {
751 if (!node->isPrivate()) {
752 if (node->isPageNode() &&
static_cast<PageNode*>(node)->isAttribution())
753 attributions.insert(node->tree()->indexTitle(), node);
754 else if (node->isAggregate())
755 static_cast<Aggregate *>(node)->findAllAttributions(attributions);
761
762
763
764
765
766
767
770 for (
auto *node : std::as_const(m_children)) {
771 if (node->isRelatedNonmember() && node->parent() !=
this)
773 QString sinceString = node->since();
775 if (node->isInAPI() && !sinceString.isEmpty()) {
778 auto &nsmap = QDocDatabase::newSinceMaps()[sinceString];
779 auto &ncmap = QDocDatabase::newClassMaps()[sinceString];
780 auto &nqcmap = QDocDatabase::newQmlTypeMaps()[sinceString];
782 if (node->isFunction()) {
784 auto *fn =
static_cast<FunctionNode *>(node);
785 if (!fn->isDeprecated() && !fn->isSomeCtor() && !fn->isDtor())
786 nsmap.insert(fn->name(), fn);
787 }
else if (node->isClassNode()) {
789 QString name = node->qualifyWithParentName();
790 nsmap.insert(name, node);
791 ncmap.insert(name, node);
792 }
else if (node->isQmlType()) {
794 QString name = node->qualifyWithParentName();
795 nsmap.insert(name, node);
796 nqcmap.insert(name, node);
797 }
else if (node->isQmlProperty()) {
799 nsmap.insert(node->name(), node);
802 QString name = node->qualifyWithParentName();
803 nsmap.insert(name, node);
807 if (node->isInAPI() && node->isEnumType()) {
808 for (
const auto &val :
static_cast<EnumNode *>(node)->items()) {
809 sinceString = val.since();
810 if (sinceString.isEmpty())
813 QDocDatabase::newEnumValueMaps()[sinceString].insert(
814 node->name() +
"::" + val.name(), node);
818 QDocDatabase::newSinceMaps()[sinceString].replace(QString(), node);
823 if (node->isAggregate())
824 static_cast<Aggregate *>(node)->findAllSince();
829
830
831
835 for (
auto *child : std::as_const(m_children)) {
836 if (!child->isQmlType())
838 static_cast<QmlTypeNode *>(child)->resolveInheritance(previousSearches);
842 for (
auto *child : std::as_const(m_children)) {
843 if (child->isQmlType())
844 static_cast<QmlTypeNode *>(child)->checkInheritance();
849
850
851
852
857 case NodeType::Class:
859 case NodeType::Struct:
861 case NodeType::Union:
863 case NodeType::Namespace:
864 return "Namespace"_L1;
870 case NodeType::Class:
872 case NodeType::Struct:
874 case NodeType::Union:
876 case NodeType::Namespace:
877 return "namespace"_L1;
886
887
890
891
894
895
898
899
902
903
904
905
906
909
910
911
912
915
916
917
918
919
922
923
924
925
926
927
928
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