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())
159 auto match_it =
std::find_if((*map_it).begin(), (*map_it).end(),
165 for (
int i = 0; i < parameters
.count(); ++i)
171 if (match_it != (*map_it).end())
178 auto best_it =
std::find_if((*map_it).begin(), (*map_it).end(),
180 return !fn->isInternal() && !fn->isDeprecated();
183 if (best_it != (*map_it).end())
187 auto fallback_it =
std::find_if((*map_it).begin(), (*map_it).end(),
189 return !fn->isInternal();
192 if (fallback_it != (*map_it).end())
200
201
202
203
204
205
208 auto funcs_it = m_functionMap.find(clone->name());
209 if (funcs_it == m_functionMap.end())
212 auto func_it =
std::find_if((*funcs_it).begin(), (*funcs_it).end(),
217 return func_it != (*funcs_it).end() ? *func_it :
nullptr;
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
251 const auto &config{Config::instance()};
252 const InclusionPolicy policy = config.createInclusionPolicy();
253 if (!config.get(
CONFIG_NOLINKERRORS).asBool() && !InclusionFilter::processInternalDocs(policy))
254 child->doc().location().warning(
255 "No output generated for %1 '%2' because '%3' is undocumented"_L1
256 .arg(child->nodeTypeString(),
257 child->plainFullName(),
258 child->parent()->name()));
263
264
265
268 for (
auto *child : std::as_const(m_children)) {
269 if (!child->hasDoc() && !child->isDontDocument()) {
270 if (!child->docMustBeGenerated()) {
271 if (child->isFunction()) {
272 if (
static_cast<FunctionNode *>(child)->hasAssociatedProperties())
274 }
else if (child->isTypedef() && child->isInAPI()) {
275 if (
static_cast<TypedefNode *>(child)->hasAssociatedEnum())
278 child->setStatus(Node::Internal);
281 warnAboutDocumentedChildInUndocumentedParent(
this, child);
283 if (child->isAggregate()) {
284 static_cast<Aggregate *>(child)->markUndocumentedChildrenInternal();
290
291
292
293
294
295
296
301 for (
auto *node : m_children) {
302 if (node->isRelatedNonmember())
304 if (node->genus() != Genus::CPP)
307 if (!node->isAggregate()) {
308 const auto &relates_args = node->doc().metaCommandArgs(
"relates"_L1);
309 if (relates_args.isEmpty())
312 auto *aggregate = database->findRelatesNode(relates_args[0].first.split(
"::"_L1));
314 aggregate =
new ProxyNode(
this, relates_args[0].first);
315 else if (node->parent() == aggregate)
318 aggregate->adoptChild(node);
319 node->setRelatedNonmember(
true);
321 static_cast<Aggregate*>(node)->resolveRelates();
327
328
329
330
331
332
333
334
335
336
337
338
341 for (
auto &map_it : m_functionMap) {
342 if (map_it.size() == 1) {
343 map_it.front()->setOverloadNumber(0);
344 }
else if (map_it.size() > 1) {
346 QStringList primaryOverloads;
347 for (
const auto *fn : map_it) {
348 if (fn->isPrimaryOverload()) {
349 const auto &location =
"%1:%2"_L1.arg(
350 fn->doc().location().fileName(),
351 QString::number(fn->doc().location().lineNo()));
352 primaryOverloads.append(
"%1 (%2)"_L1.arg(fn->signature(Node::SignaturePlain),
357 if (primaryOverloads.size() > 1) {
358 const QString functionName = map_it.front()->name();
359 const QString message =
"Multiple primary overload definitions for '%1': %2"_L1.arg(
360 functionName, primaryOverloads.join(
", "));
361 const QString description =
"The primary overload will be determined "
362 "by lexicographic comparison "
363 "(alphabetical ordering of function signatures)."_L1;
364 map_it.front()->doc().location().warning(message, description);
367 std::sort(map_it.begin(), map_it.end(),
368 [](
const FunctionNode *f1,
const FunctionNode *f2) ->
bool {
369 if (f1->isInternal() != f2->isInternal())
370 return f2->isInternal();
372 if (f1->isPrimaryOverload() != f2->isPrimaryOverload())
373 return f1->isPrimaryOverload();
374 if (f1->isOverload() != f2->isOverload())
375 return f2->isOverload();
377 if (f1->hasDoc() != f2->hasDoc())
379 return (compare(f1, f2) < 0);
384 for (
auto *fn : map_it) {
386 fn->setOverloadNumber(n++);
391 for (
auto *node : std::as_const(m_children)) {
392 if (node->isAggregate())
393 static_cast<Aggregate *>(node)->normalizeOverloads();
398
399
400
401
404 m_nonfunctionList = m_nonfunctionMap.values();
408 m_nonfunctionList.erase(
std::unique(m_nonfunctionList.begin(), m_nonfunctionList.end()),
409 m_nonfunctionList.end());
410 return m_nonfunctionList;
414
415
416
419
420
421
422
423
426 for (
const auto *node : m_enumChildren) {
427 const auto *en =
static_cast<
const EnumNode *>(node);
428 if (en->hasItem(enumValue))
435
436
437
438
439
442 m_nonfunctionMap.insert(title, child);
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
467 child->setUrl(QString());
471 m_functionMap[child->name()].emplace_back(
static_cast<FunctionNode *>(child));
472 }
else if (!child->name().isEmpty()) {
473 m_nonfunctionMap.insert(child->name(), child);
475 m_enumChildren.append(child);
480
481
482
483
484
485
486
493 m_functionMap[child->name()].emplace_back(
static_cast<FunctionNode *>(child));
494 }
else if (!child->name().isEmpty()) {
495 m_nonfunctionMap.insert(child->name(), child);
497 m_enumChildren.append(child);
501 for (Node *n : scn->collective())
508
509
510
514 for (
auto *child : std::as_const(m_children)) {
515 if (child->nodeType() == goal) {
516 if (child->name() == n)
517 return static_cast<QmlPropertyNode *>(child);
524
525
526
530 for (
auto *child : std::as_const(m_children)) {
531 if (child->nodeType() == goal) {
532 if (child->name() == n && child->isAttached() == attached)
533 return static_cast<QmlPropertyNode *>(child);
540
541
542
543
544
547 auto it = m_functionMap.find(fn->name());
548 return !(it == m_functionMap.end()) && (it.value().size() > 1);
552
553
554
555
556
557
558
567
568
569
570
571
572
573
576 for (
auto functions : m_functionMap) {
577 std::for_each(functions.begin(), functions.end(),
578 [&functionIndex](FunctionNode *fn) {
580 functionIndex[fn->name()].insert(fn->parent()->fullDocumentName(), fn);
585 for (Node *node : std::as_const(m_children)) {
586 if (node->isAggregate() && !node->isPrivate() && !node->isDontDocument())
587 static_cast<Aggregate *>(node)->findAllFunctions(functionIndex);
592
593
594
595
596
597
598
599
600
601
602
603
604
607 for (
auto *node : std::as_const(m_children)) {
608 if (node->isAggregate() && !node->isPrivate()) {
609 if (node->isNamespace() && !node->name().isEmpty())
610 namespaces.insert(node->name(), node);
611 static_cast<Aggregate *>(node)->findAllNamespaces(namespaces);
617
618
619
622 for (
const auto *node : m_children)
623 if (!node->isPrivate() && node->isDeprecated()) {
624 if (node->isFunction() || node->isProperty() || node->isEnumType() || node->isTypedef()
625 || node->isTypeAlias() || node->isVariable() || node->isQmlProperty())
632
633
634
635
636
639 for (
auto *node : std::as_const(m_children)) {
640 if (!node->isPrivate()) {
641 if (node->isDeprecated()) {
642 if (node->isClassNode())
643 QDocDatabase::obsoleteClasses().insert(node->qualifyCppName(), node);
644 else if (node->isQmlType())
645 QDocDatabase::obsoleteQmlTypes().insert(node->qualifyQmlName(), node);
646 }
else if (node->isClassNode()) {
647 auto *a =
static_cast<Aggregate *>(node);
648 if (a->hasObsoleteMembers())
649 QDocDatabase::classesWithObsoleteMembers().insert(node->qualifyCppName(), node);
650 }
else if (node->isQmlType()) {
651 auto *a =
static_cast<Aggregate *>(node);
652 if (a->hasObsoleteMembers())
653 QDocDatabase::qmlTypesWithObsoleteMembers().insert(node->qualifyQmlName(),
655 }
else if (node->isAggregate()) {
656 static_cast<Aggregate *>(node)->findAllObsoleteThings();
663
664
665
666
669 for (
auto *node : std::as_const(m_children)) {
670 if (!node->isPrivate() && !node->isInternal() && !node->isDontDocument()
671 && node->tree()->camelCaseModuleName() != QString(
"QDoc")) {
672 if (node->isClassNode()) {
673 QDocDatabase::cppClasses().insert(node->qualifyCppName().toLower(), node);
674 }
else if (node->isQmlType()) {
675 QString name = node->name().toLower();
676 QDocDatabase::qmlTypes().insert(name, node);
678 if (node->isQmlBasicType())
679 QDocDatabase::qmlBasicTypes().insert(name, node);
680 }
else if (node->isExample()) {
682 QString title = node->tree()->indexTitle();
683 if (!QDocDatabase::examples().contains(title, node))
684 QDocDatabase::examples().insert(title, node);
685 }
else if (node->isAggregate()) {
686 static_cast<Aggregate *>(node)->findAllClasses();
693
694
695
698 for (
auto *node : std::as_const(m_children)) {
699 if (!node->isPrivate()) {
700 if (node->isPageNode() &&
static_cast<PageNode*>(node)->isAttribution())
701 attributions.insert(node->tree()->indexTitle(), node);
702 else if (node->isAggregate())
703 static_cast<Aggregate *>(node)->findAllAttributions(attributions);
709
710
711
712
713
714
715
718 for (
auto *node : std::as_const(m_children)) {
719 if (node->isRelatedNonmember() && node->parent() !=
this)
721 QString sinceString = node->since();
723 if (node->isInAPI() && !sinceString.isEmpty()) {
726 auto &nsmap = QDocDatabase::newSinceMaps()[sinceString];
727 auto &ncmap = QDocDatabase::newClassMaps()[sinceString];
728 auto &nqcmap = QDocDatabase::newQmlTypeMaps()[sinceString];
730 if (node->isFunction()) {
732 auto *fn =
static_cast<FunctionNode *>(node);
733 if (!fn->isDeprecated() && !fn->isSomeCtor() && !fn->isDtor())
734 nsmap.insert(fn->name(), fn);
735 }
else if (node->isClassNode()) {
737 QString name = node->qualifyWithParentName();
738 nsmap.insert(name, node);
739 ncmap.insert(name, node);
740 }
else if (node->isQmlType()) {
742 QString name = node->qualifyWithParentName();
743 nsmap.insert(name, node);
744 nqcmap.insert(name, node);
745 }
else if (node->isQmlProperty()) {
747 nsmap.insert(node->name(), node);
750 QString name = node->qualifyWithParentName();
751 nsmap.insert(name, node);
755 if (node->isInAPI() && node->isEnumType()) {
756 for (
const auto &val :
static_cast<EnumNode *>(node)->items()) {
757 sinceString = val.since();
758 if (sinceString.isEmpty())
761 QDocDatabase::newEnumValueMaps()[sinceString].insert(
762 node->name() +
"::" + val.name(), node);
766 QDocDatabase::newSinceMaps()[sinceString].replace(QString(), node);
771 if (node->isAggregate())
772 static_cast<Aggregate *>(node)->findAllSince();
777
778
779
783 for (
auto *child : std::as_const(m_children)) {
784 if (!child->isQmlType())
786 static_cast<QmlTypeNode *>(child)->resolveInheritance(previousSearches);
790 for (
auto *child : std::as_const(m_children)) {
791 if (child->isQmlType())
792 static_cast<QmlTypeNode *>(child)->checkInheritance();
797
798
799
800
805 case NodeType::Class:
807 case NodeType::Struct:
809 case NodeType::Union:
811 case NodeType::Namespace:
812 return "Namespace"_L1;
818 case NodeType::Class:
820 case NodeType::Struct:
822 case NodeType::Union:
824 case NodeType::Namespace:
825 return "namespace"_L1;
834
835
838
839
842
843
846
847
850
851
852
853
854
857
858
859
860
863
864
865
866
867
870
871
872
873
874
875
876
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.
static bool nodeNameLessThan(const Node *first, const Node *second)
Returns true if the node n1 is less than node n2.
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.
A class for parsing and managing a function parameter list.
const Parameter & at(int i) const