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
469 if (!m_nonfunctionList.isEmpty())
470 return m_nonfunctionList;
474 m_nonfunctionList.erase(
475 std::remove_if(m_nonfunctionList.begin(), m_nonfunctionList.end(),
476 [](
const Node* node) {
479 m_nonfunctionList.end());
482 return m_nonfunctionList;
486
487
488
491
492
493
494
495
498 for (
const auto *node : m_enumChildren) {
499 const auto *en =
static_cast<
const EnumNode *>(node);
500 if (en->hasItem(enumValue))
507
508
509
510
511
514 m_nonfunctionMap.insert(title, child);
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
539 child->setUrl(QString());
543 m_functionMap[child->name()].emplace_back(
static_cast<FunctionNode *>(child));
544 }
else if (!child->name().isEmpty()) {
545 m_nonfunctionMap.insert(child->name(), child);
547 m_enumChildren.append(child);
552
553
554
555
556
557
558
565 m_functionMap[child->name()].emplace_back(
static_cast<FunctionNode *>(child));
566 }
else if (!child->name().isEmpty()) {
567 m_nonfunctionMap.insert(child->name(), child);
569 m_enumChildren.append(child);
572 auto *scn =
static_cast<SharedCommentNode *>(child);
573 for (Node *n : scn->collective())
580
581
582
586 for (
auto *child : std::as_const(m_children)) {
587 if (child->nodeType() == goal) {
588 if (child->name() == n) {
589 if (attached == AnyProperties
590 || (child->isAttached() && attached == AttachedProperties)
591 || (!child->isAttached() && attached == UnattachedProperties))
592 return static_cast<QmlPropertyNode *>(child);
600
601
602
603
604
607 auto it = m_functionMap.find(fn->name());
608 return !(it == m_functionMap.end()) && (it.value().size() > 1);
612
613
614
615
616
617
618
627
628
629
630
631
632
633
636 for (
auto functions : m_functionMap) {
637 std::for_each(functions.begin(), functions.end(),
638 [&functionIndex](FunctionNode *fn) {
640 functionIndex[fn->name()].insert(fn->parent()->fullDocumentName(), fn);
645 for (Node *node : std::as_const(m_children)) {
646 if (node->isAggregate() && !node->isPrivate() && !node->isDontDocument())
647 static_cast<Aggregate *>(node)->findAllFunctions(functionIndex);
652
653
654
655
656
657
658
659
660
661
662
663
664
667 for (
auto *node : std::as_const(m_children)) {
668 if (node->isAggregate() && !node->isPrivate()) {
669 if (node->isNamespace() && !node->name().isEmpty())
670 namespaces.insert(node->name(), node);
671 static_cast<Aggregate *>(node)->findAllNamespaces(namespaces);
677
678
679
682 for (
const auto *node : m_children)
683 if (!node->isPrivate() && node->isDeprecated()) {
684 if (node->isFunction() || node->isProperty() || node->isEnumType() || node->isTypedef()
685 || node->isTypeAlias() || node->isVariable() || node->isQmlProperty())
692
693
694
695
696
699 for (
auto *node : std::as_const(m_children)) {
700 if (!node->isPrivate()) {
701 if (node->isDeprecated()) {
702 if (node->isClassNode())
703 QDocDatabase::obsoleteClasses().insert(node->qualifyCppName(), node);
704 else if (node->isQmlType())
705 QDocDatabase::obsoleteQmlTypes().insert(node->qualifyQmlName(), node);
706 }
else if (node->isClassNode()) {
707 auto *a =
static_cast<Aggregate *>(node);
708 if (a->hasObsoleteMembers())
709 QDocDatabase::classesWithObsoleteMembers().insert(node->qualifyCppName(), node);
710 }
else if (node->isQmlType()) {
711 auto *a =
static_cast<Aggregate *>(node);
712 if (a->hasObsoleteMembers())
713 QDocDatabase::qmlTypesWithObsoleteMembers().insert(node->qualifyQmlName(),
715 }
else if (node->isAggregate()) {
716 static_cast<Aggregate *>(node)->findAllObsoleteThings();
723
724
725
726
729 for (
auto *node : std::as_const(m_children)) {
730 if (!node->isPrivate() && !node->isInternal() && !node->isDontDocument()
731 && node->tree()->camelCaseModuleName() != QString(
"QDoc")) {
732 if (node->isClassNode()) {
733 QDocDatabase::cppClasses().insert(node->qualifyCppName().toLower(), node);
734 }
else if (node->isQmlType()) {
735 QString name = node->name().toLower();
736 QDocDatabase::qmlTypes().insert(name, node);
738 if (node->isQmlBasicType())
739 QDocDatabase::qmlBasicTypes().insert(name, node);
740 }
else if (node->isExample()) {
742 QString title = node->tree()->indexTitle();
743 if (!QDocDatabase::examples().contains(title, node))
744 QDocDatabase::examples().insert(title, node);
745 }
else if (node->isAggregate()) {
746 static_cast<Aggregate *>(node)->findAllClasses();
753
754
755
758 for (
auto *node : std::as_const(m_children)) {
759 if (!node->isPrivate()) {
760 if (node->isPageNode() &&
static_cast<PageNode*>(node)->isAttribution())
761 attributions.insert(node->tree()->indexTitle(), node);
762 else if (node->isAggregate())
763 static_cast<Aggregate *>(node)->findAllAttributions(attributions);
769
770
771
772
773
774
775
778 for (
auto *node : std::as_const(m_children)) {
779 if (node->isRelatedNonmember() && node->parent() !=
this)
781 QString sinceString = node->since();
783 if (node->isInAPI() && !sinceString.isEmpty()) {
786 auto &nsmap = QDocDatabase::newSinceMaps()[sinceString];
787 auto &ncmap = QDocDatabase::newClassMaps()[sinceString];
788 auto &nqcmap = QDocDatabase::newQmlTypeMaps()[sinceString];
790 if (node->isFunction()) {
792 auto *fn =
static_cast<FunctionNode *>(node);
793 if (!fn->isDeprecated() && !fn->isSomeCtor() && !fn->isDtor())
794 nsmap.insert(fn->name(), fn);
795 }
else if (node->isClassNode()) {
797 QString name = node->qualifyWithParentName();
798 nsmap.insert(name, node);
799 ncmap.insert(name, node);
800 }
else if (node->isQmlType()) {
802 QString name = node->qualifyWithParentName();
803 nsmap.insert(name, node);
804 nqcmap.insert(name, node);
805 }
else if (node->isQmlProperty()) {
807 nsmap.insert(node->name(), node);
808 }
else if (node->isConcept()) {
810 nsmap.insert(node->qualifyWithParentName(), node);
813 QString name = node->qualifyWithParentName();
814 nsmap.insert(name, node);
818 if (node->isInAPI() && node->isEnumType()) {
819 for (
const auto &val :
static_cast<EnumNode *>(node)->items()) {
820 sinceString = val.since();
821 if (sinceString.isEmpty())
824 QDocDatabase::newEnumValueMaps()[sinceString].insert(
825 node->name() +
"::" + val.name(), node);
829 QDocDatabase::newSinceMaps()[sinceString].replace(QString(), node);
834 if (node->isAggregate())
835 static_cast<Aggregate *>(node)->findAllSince();
840
841
842
846 for (
auto *child : std::as_const(m_children)) {
847 if (!child->isQmlType())
849 static_cast<QmlTypeNode *>(child)->resolveInheritance(previousSearches);
853 for (
auto *child : std::as_const(m_children)) {
854 if (child->isQmlType())
855 static_cast<QmlTypeNode *>(child)->checkInheritance();
860
861
862
863
868 case NodeType::Class:
870 case NodeType::Struct:
872 case NodeType::Union:
874 case NodeType::Namespace:
875 return "Namespace"_L1;
881 case NodeType::Class:
883 case NodeType::Struct:
885 case NodeType::Union:
887 case NodeType::Namespace:
888 return "namespace"_L1;
897
898
901
902
905
906
909
910
913
914
915
916
917
920
921
922
923
926
927
928
929
930
933
934
935
936
937
938
939
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