summaryrefslogtreecommitdiffstats
path: root/src/qdoc/qdoc/src/qdoc/aggregate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qdoc/qdoc/src/qdoc/aggregate.cpp')
-rw-r--r--src/qdoc/qdoc/src/qdoc/aggregate.cpp762
1 files changed, 762 insertions, 0 deletions
diff --git a/src/qdoc/qdoc/src/qdoc/aggregate.cpp b/src/qdoc/qdoc/src/qdoc/aggregate.cpp
new file mode 100644
index 000000000..bf210ba17
--- /dev/null
+++ b/src/qdoc/qdoc/src/qdoc/aggregate.cpp
@@ -0,0 +1,762 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "aggregate.h"
+
+#include "functionnode.h"
+#include "parameters.h"
+#include "typedefnode.h"
+#include "qdocdatabase.h"
+#include "qmlpropertynode.h"
+#include "qmltypenode.h"
+#include "sharedcommentnode.h"
+#include <vector>
+
+using namespace Qt::Literals::StringLiterals;
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class Aggregate
+ */
+
+/*! \fn Aggregate::Aggregate(NodeType type, Aggregate *parent, const QString &name)
+ The constructor should never be called directly. It is only called
+ by the constructors of subclasses of Aggregate. Those constructors
+ pass the node \a type they want to create, the \a parent of the new
+ node, and its \a name.
+ */
+
+/*!
+ Recursively set all non-related members in the list of children to
+ \nullptr, after which each aggregate can safely delete all children
+ in their list. Aggregate's destructor calls this only on the root
+ namespace node.
+ */
+void Aggregate::dropNonRelatedMembers()
+{
+ for (auto &child : m_children) {
+ if (!child)
+ continue;
+ if (child->parent() != this)
+ child = nullptr;
+ else if (child->isAggregate())
+ static_cast<Aggregate*>(child)->dropNonRelatedMembers();
+ }
+}
+
+/*!
+ Destroys this Aggregate; deletes each child.
+ */
+Aggregate::~Aggregate()
+{
+ // If this is the root, clear non-related children first
+ if (isNamespace() && name().isEmpty())
+ dropNonRelatedMembers();
+
+ m_enumChildren.clear();
+ m_nonfunctionMap.clear();
+ m_functionMap.clear();
+ qDeleteAll(m_children.begin(), m_children.end());
+ m_children.clear();
+}
+
+/*!
+ If \a genus is \c{Node::DontCare}, find the first node in
+ this node's child list that has the given \a name. If this
+ node is a QML type, be sure to also look in the children
+ of its property group nodes. Return the matching node or \c nullptr.
+
+ If \a genus is either \c{Node::CPP} or \c {Node::QML}, then
+ find all this node's children that have the given \a name,
+ and return the one that satisfies the \a genus requirement.
+ */
+Node *Aggregate::findChildNode(const QString &name, Node::Genus genus, int findFlags) const
+{
+ if (genus == Node::DontCare) {
+ Node *node = m_nonfunctionMap.value(name);
+ if (node)
+ return node;
+ } else {
+ const NodeList &nodes = m_nonfunctionMap.values(name);
+ for (auto *node : nodes) {
+ if (genus & node->genus()) {
+ if (findFlags & TypesOnly) {
+ if (!node->isTypedef() && !node->isClassNode()
+ && !node->isQmlType() && !node->isEnumType())
+ continue;
+ } else if (findFlags & IgnoreModules && node->isModule())
+ continue;
+ return node;
+ }
+ }
+ }
+ if (genus != Node::DontCare && !(genus & this->genus()))
+ return nullptr;
+
+ auto it = m_functionMap.find(name);
+ return it != m_functionMap.end() ? (*(*it).begin()) : nullptr;
+}
+
+/*!
+ Find all the child nodes of this node that are named
+ \a name and return them in \a nodes.
+ */
+void Aggregate::findChildren(const QString &name, NodeVector &nodes) const
+{
+ nodes.clear();
+ const auto &functions = m_functionMap.value(name);
+ nodes.reserve(functions.size() + m_nonfunctionMap.count(name));
+ for (auto f : functions)
+ nodes.emplace_back(f);
+ auto [it, end] = m_nonfunctionMap.equal_range(name);
+ while (it != end) {
+ nodes.emplace_back(*it);
+ ++it;
+ }
+}
+
+/*!
+ This function searches for a child node of this Aggregate,
+ such that the child node has the spacified \a name and the
+ function \a isMatch returns true for the node. The function
+ passed must be one of the isXxx() functions in class Node
+ that tests the node type.
+ */
+Node *Aggregate::findNonfunctionChild(const QString &name, bool (Node::*isMatch)() const)
+{
+ const NodeList &nodes = m_nonfunctionMap.values(name);
+ for (auto *node : nodes) {
+ if ((node->*(isMatch))())
+ return node;
+ }
+ return nullptr;
+}
+
+/*!
+ Find a function node that is a child of this node, such that
+ the function node has the specified \a name and \a parameters.
+ If \a parameters is empty but no matching function is found
+ that has no parameters, return the first non-internal primary
+ function or overload, whether it has parameters or not.
+
+ \sa normalizeOverloads()
+ */
+FunctionNode *Aggregate::findFunctionChild(const QString &name, const Parameters &parameters)
+{
+ auto map_it = m_functionMap.find(name);
+ if (map_it == m_functionMap.end())
+ return nullptr;
+
+ auto match_it = std::find_if((*map_it).begin(), (*map_it).end(),
+ [&parameters](const FunctionNode *fn) {
+ if (fn->isInternal())
+ return false;
+ if (parameters.count() != fn->parameters().count())
+ return false;
+ for (int i = 0; i < parameters.count(); ++i)
+ if (parameters.at(i).type() != fn->parameters().at(i).type())
+ return false;
+ return true;
+ });
+
+ if (match_it != (*map_it).end())
+ return *match_it;
+
+ // Assumes that overloads are already normalized; i.e, if there's
+ // an active function, it'll be found at the start of the list.
+ auto *fn = (*(*map_it).begin());
+ return (parameters.isEmpty() && !fn->isInternal()) ? fn : nullptr;
+}
+
+/*!
+ Returns the function node that is a child of this node, such
+ that the function described has the same name and signature
+ as the function described by the function node \a clone.
+
+ Returns \nullptr if no matching function was found.
+ */
+FunctionNode *Aggregate::findFunctionChild(const FunctionNode *clone)
+{
+ auto funcs_it = m_functionMap.find(clone->name());
+ if (funcs_it == m_functionMap.end())
+ return nullptr;
+
+ auto func_it = std::find_if((*funcs_it).begin(), (*funcs_it).end(),
+ [clone](const FunctionNode *fn) {
+ return compare(clone, fn) == 0;
+ });
+
+ return func_it != (*funcs_it).end() ? *func_it : nullptr;
+}
+
+/*!
+ Mark all child nodes that have no documentation as having
+ private access and internal status. qdoc will then ignore
+ them for documentation purposes.
+ */
+void Aggregate::markUndocumentedChildrenInternal()
+{
+ for (auto *child : std::as_const(m_children)) {
+ if (!child->hasDoc() && !child->isDontDocument()) {
+ if (!child->docMustBeGenerated()) {
+ if (child->isFunction()) {
+ if (static_cast<FunctionNode *>(child)->hasAssociatedProperties())
+ continue;
+ } else if (child->isTypedef()) {
+ if (static_cast<TypedefNode *>(child)->hasAssociatedEnum())
+ continue;
+ }
+ child->setAccess(Access::Private);
+ child->setStatus(Node::Internal);
+ }
+ }
+ if (child->isAggregate()) {
+ static_cast<Aggregate *>(child)->markUndocumentedChildrenInternal();
+ }
+ }
+}
+
+/*!
+ Adopts each non-aggregate C++ node (function/macro, typedef, enum, variable,
+ or a shared comment node with genus Node::CPP) in the global scope to the
+ aggregate specified in the node's documentation using the \\relates command.
+
+ If the target Aggregate is not found in the primary tree, creates a new
+ ProxyNode to use as the parent.
+*/
+void Aggregate::resolveRelates()
+{
+ Q_ASSERT(name().isEmpty()); // Must be called on the root namespace
+ auto *database = QDocDatabase::qdocDB();
+
+ for (auto *node : m_children) {
+ if (node->isRelatedNonmember() || node->isAggregate())
+ continue;
+ if (node->genus() != Node::CPP)
+ continue;
+
+ const auto &relates_args = node->doc().metaCommandArgs("relates"_L1);
+ if (relates_args.isEmpty())
+ continue;
+
+ auto *aggregate = database->findRelatesNode(relates_args[0].first.split("::"_L1));
+ if (!aggregate)
+ aggregate = new ProxyNode(this, relates_args[0].first);
+ else if (node->parent() == aggregate)
+ continue;
+
+ aggregate->adoptChild(node);
+ node->setRelatedNonmember(true);
+ }
+}
+
+/*!
+ Sorts the lists of overloads in the function map and assigns overload
+ numbers.
+
+ For sorting, active functions take precedence over internal ones, as well
+ as ones marked as \\overload - the latter ones typically do not contain
+ full documentation, so selecting them as the \e primary function
+ would cause unnecessary warnings to be generated.
+
+ Otherwise, the order is set as determined by FunctionNode::compare().
+ */
+void Aggregate::normalizeOverloads()
+{
+ for (auto map_it = m_functionMap.begin(); map_it != m_functionMap.end(); ++map_it) {
+ if ((*map_it).size() > 1) {
+ std::sort((*map_it).begin(), (*map_it).end(),
+ [](const FunctionNode *f1, const FunctionNode *f2) -> bool {
+ if (f1->isInternal() != f2->isInternal())
+ return f2->isInternal();
+ if (f1->isOverload() != f2->isOverload())
+ return f2->isOverload();
+ // Prioritize documented over undocumented
+ if (f1->hasDoc() != f2->hasDoc())
+ return f1->hasDoc();
+ return (compare(f1, f2) < 0);
+ });
+ // Set overload numbers
+ signed short n{0};
+ for (auto *fn : (*map_it))
+ fn->setOverloadNumber(n++);
+ }
+ }
+
+ for (auto *node : std::as_const(m_children)) {
+ if (node->isAggregate())
+ static_cast<Aggregate *>(node)->normalizeOverloads();
+ }
+}
+
+/*!
+ Returns a const reference to the list of child nodes of this
+ aggregate that are not function nodes. Duplicate nodes are
+ removed from the list.
+ */
+const NodeList &Aggregate::nonfunctionList()
+{
+ m_nonfunctionList = m_nonfunctionMap.values();
+ std::sort(m_nonfunctionList.begin(), m_nonfunctionList.end(), Node::nodeNameLessThan);
+ m_nonfunctionList.erase(std::unique(m_nonfunctionList.begin(), m_nonfunctionList.end()),
+ m_nonfunctionList.end());
+ return m_nonfunctionList;
+}
+
+/*! \fn bool Aggregate::isAggregate() const
+ Returns \c true because this node is an instance of Aggregate,
+ which means it can have children.
+ */
+
+/*!
+ Finds the enum type node that has \a enumValue as one of
+ its enum values and returns a pointer to it. Returns 0 if
+ no enum type node is found that has \a enumValue as one
+ of its values.
+ */
+const EnumNode *Aggregate::findEnumNodeForValue(const QString &enumValue) const
+{
+ for (const auto *node : m_enumChildren) {
+ const auto *en = static_cast<const EnumNode *>(node);
+ if (en->hasItem(enumValue))
+ return en;
+ }
+ return nullptr;
+}
+
+/*!
+ Adds the \a child to this node's child map using \a title
+ as the key. The \a child is not added to the child list
+ again, because it is presumed to already be there. We just
+ want to be able to find the child by its \a title.
+ */
+void Aggregate::addChildByTitle(Node *child, const QString &title)
+{
+ m_nonfunctionMap.insert(title, child);
+}
+
+/*!
+ Adds the \a child to this node's child list and sets the child's
+ parent pointer to this Aggregate. It then mounts the child with
+ mountChild().
+
+ The \a child is then added to this Aggregate's searchable maps
+ and lists.
+
+ \note This function does not test the child's parent pointer
+ for null before changing it. If the child's parent pointer
+ is not null, then it is being reparented. The child becomes
+ a child of this Aggregate, but it also remains a child of
+ the Aggregate that is it's old parent. But the child will
+ only have one parent, and it will be this Aggregate. The is
+ because of the \c relates command.
+
+ \sa mountChild(), dismountChild()
+ */
+void Aggregate::addChild(Node *child)
+{
+ m_children.append(child);
+ child->setParent(this);
+ child->setUrl(QString());
+ child->setIndexNodeFlag(isIndexNode());
+
+ if (child->isFunction()) {
+ m_functionMap[child->name()].emplace_back(static_cast<FunctionNode *>(child));
+ } else if (!child->name().isEmpty()) {
+ m_nonfunctionMap.insert(child->name(), child);
+ if (child->isEnumType())
+ m_enumChildren.append(child);
+ }
+}
+
+/*!
+ This Aggregate becomes the adoptive parent of \a child. The
+ \a child knows this Aggregate as its parent, but its former
+ parent continues to have pointers to the child in its child
+ list and in its searchable data structures. But the child is
+ also added to the child list and searchable data structures
+ of this Aggregate.
+ */
+void Aggregate::adoptChild(Node *child)
+{
+ if (child->parent() != this) {
+ m_children.append(child);
+ child->setParent(this);
+ if (child->isFunction()) {
+ m_functionMap[child->name()].emplace_back(static_cast<FunctionNode *>(child));
+ } else if (!child->name().isEmpty()) {
+ m_nonfunctionMap.insert(child->name(), child);
+ if (child->isEnumType())
+ m_enumChildren.append(child);
+ }
+ if (child->isSharedCommentNode()) {
+ auto *scn = static_cast<SharedCommentNode *>(child);
+ for (Node *n : scn->collective())
+ adoptChild(n);
+ }
+ }
+}
+
+/*!
+ If this node has a child that is a QML property named \a n, return a
+ pointer to that child. Otherwise, return \nullptr.
+ */
+QmlPropertyNode *Aggregate::hasQmlProperty(const QString &n) const
+{
+ NodeType goal = Node::QmlProperty;
+ for (auto *child : std::as_const(m_children)) {
+ if (child->nodeType() == goal) {
+ if (child->name() == n)
+ return static_cast<QmlPropertyNode *>(child);
+ }
+ }
+ return nullptr;
+}
+
+/*!
+ If this node has a child that is a QML property named \a n and that
+ also matches \a attached, return a pointer to that child.
+ */
+QmlPropertyNode *Aggregate::hasQmlProperty(const QString &n, bool attached) const
+{
+ NodeType goal = Node::QmlProperty;
+ for (auto *child : std::as_const(m_children)) {
+ if (child->nodeType() == goal) {
+ if (child->name() == n && child->isAttached() == attached)
+ return static_cast<QmlPropertyNode *>(child);
+ }
+ }
+ return nullptr;
+}
+
+/*!
+ Returns \c true if this aggregate has multiple function
+ overloads matching the name of \a fn.
+
+ \note Assumes \a fn is a member of this aggregate.
+*/
+bool Aggregate::hasOverloads(const FunctionNode *fn) const
+{
+ auto it = m_functionMap.find(fn->name());
+ return !(it == m_functionMap.end()) && (it.value().size() > 1);
+}
+
+/*
+ When deciding whether to include a function in the function
+ index, if the function is marked private, don't include it.
+ If the function is marked obsolete, don't include it. If the
+ function is marked internal, don't include it. Or if the
+ function is a destructor or any kind of constructor, don't
+ include it. Otherwise include it.
+ */
+static bool keep(FunctionNode *fn)
+{
+ if (fn->isPrivate() || fn->isDeprecated() || fn->isInternal() || fn->isSomeCtor() || fn->isDtor())
+ return false;
+ return true;
+}
+
+/*!
+ Insert all functions declared in this aggregate into the
+ \a functionIndex. Call the function recursively for each
+ child that is an aggregate.
+
+ Only include functions that are in the public API and
+ that are not constructors or destructors.
+ */
+void Aggregate::findAllFunctions(NodeMapMap &functionIndex)
+{
+ for (auto functions : m_functionMap) {
+ std::for_each(functions.begin(), functions.end(),
+ [&functionIndex](FunctionNode *fn) {
+ if (keep(fn))
+ functionIndex[fn->name()].insert(fn->parent()->fullDocumentName(), fn);
+ }
+ );
+ }
+
+ for (Node *node : std::as_const(m_children)) {
+ if (node->isAggregate() && !node->isPrivate() && !node->isDontDocument())
+ static_cast<Aggregate *>(node)->findAllFunctions(functionIndex);
+ }
+}
+
+/*!
+ For each child of this node, if the child is a namespace node,
+ insert the child into the \a namespaces multimap. If the child
+ is an aggregate, call this function recursively for that child.
+
+ When the function called with the root node of a tree, it finds
+ all the namespace nodes in that tree and inserts them into the
+ \a namespaces multimap.
+
+ The root node of a tree is a namespace, but it has no name, so
+ it is not inserted into the map. So, if this function is called
+ for each tree in the qdoc database, it finds all the namespace
+ nodes in the database.
+ */
+void Aggregate::findAllNamespaces(NodeMultiMap &namespaces)
+{
+ for (auto *node : std::as_const(m_children)) {
+ if (node->isAggregate() && !node->isPrivate()) {
+ if (node->isNamespace() && !node->name().isEmpty())
+ namespaces.insert(node->name(), node);
+ static_cast<Aggregate *>(node)->findAllNamespaces(namespaces);
+ }
+ }
+}
+
+/*!
+ Returns true if this aggregate contains at least one child
+ that is marked obsolete. Otherwise returns false.
+ */
+bool Aggregate::hasObsoleteMembers() const
+{
+ for (const auto *node : m_children)
+ if (!node->isPrivate() && node->isDeprecated()) {
+ if (node->isFunction() || node->isProperty() || node->isEnumType() || node->isTypedef()
+ || node->isTypeAlias() || node->isVariable() || node->isQmlProperty())
+ return true;
+ }
+ return false;
+}
+
+/*!
+ Finds all the obsolete C++ classes and QML types in this
+ aggregate and all the C++ classes and QML types with obsolete
+ members, and inserts them into maps used elsewhere for
+ generating documentation.
+ */
+void Aggregate::findAllObsoleteThings()
+{
+ for (auto *node : std::as_const(m_children)) {
+ if (!node->isPrivate()) {
+ if (node->isDeprecated()) {
+ if (node->isClassNode())
+ QDocDatabase::obsoleteClasses().insert(node->qualifyCppName(), node);
+ else if (node->isQmlType())
+ QDocDatabase::obsoleteQmlTypes().insert(node->qualifyQmlName(), node);
+ } else if (node->isClassNode()) {
+ auto *a = static_cast<Aggregate *>(node);
+ if (a->hasObsoleteMembers())
+ QDocDatabase::classesWithObsoleteMembers().insert(node->qualifyCppName(), node);
+ } else if (node->isQmlType()) {
+ auto *a = static_cast<Aggregate *>(node);
+ if (a->hasObsoleteMembers())
+ QDocDatabase::qmlTypesWithObsoleteMembers().insert(node->qualifyQmlName(),
+ node);
+ } else if (node->isAggregate()) {
+ static_cast<Aggregate *>(node)->findAllObsoleteThings();
+ }
+ }
+ }
+}
+
+/*!
+ Finds all the C++ classes, QML types, QML basic types, and examples
+ in this aggregate and inserts them into appropriate maps for later
+ use in generating documentation.
+ */
+void Aggregate::findAllClasses()
+{
+ for (auto *node : std::as_const(m_children)) {
+ if (!node->isPrivate() && !node->isInternal() && !node->isDontDocument()
+ && node->tree()->camelCaseModuleName() != QString("QDoc")) {
+ if (node->isClassNode()) {
+ QDocDatabase::cppClasses().insert(node->qualifyCppName().toLower(), node);
+ } else if (node->isQmlType()) {
+ QString name = node->name().toLower();
+ QDocDatabase::qmlTypes().insert(name, node);
+ // also add to the QML basic type map
+ if (node->isQmlBasicType())
+ QDocDatabase::qmlBasicTypes().insert(name, node);
+ } else if (node->isExample()) {
+ // use the module index title as key for the example map
+ QString title = node->tree()->indexTitle();
+ if (!QDocDatabase::examples().contains(title, node))
+ QDocDatabase::examples().insert(title, node);
+ } else if (node->isAggregate()) {
+ static_cast<Aggregate *>(node)->findAllClasses();
+ }
+ }
+ }
+}
+
+/*!
+ Find all the attribution pages in this node and insert them
+ into \a attributions.
+ */
+void Aggregate::findAllAttributions(NodeMultiMap &attributions)
+{
+ for (auto *node : std::as_const(m_children)) {
+ if (!node->isPrivate()) {
+ if (node->isPageNode() && static_cast<PageNode*>(node)->isAttribution())
+ attributions.insert(node->tree()->indexTitle(), node);
+ else if (node->isAggregate())
+ static_cast<Aggregate *>(node)->findAllAttributions(attributions);
+ }
+ }
+}
+
+/*!
+ Finds all the nodes in this node where a \e{since} command appeared
+ in the qdoc comment and sorts them into maps according to the kind
+ of node.
+
+ This function is used for generating the "New Classes... in x.y"
+ section on the \e{What's New in Qt x.y} page.
+ */
+void Aggregate::findAllSince()
+{
+ for (auto *node : std::as_const(m_children)) {
+ if (node->isRelatedNonmember() && node->parent() != this)
+ continue;
+ QString sinceString = node->since();
+ // Insert a new entry into each map for each new since string found.
+ if (node->isInAPI() && !sinceString.isEmpty()) {
+ // operator[] will insert a default-constructed value into the
+ // map if key is not found, which is what we want here.
+ auto &nsmap = QDocDatabase::newSinceMaps()[sinceString];
+ auto &ncmap = QDocDatabase::newClassMaps()[sinceString];
+ auto &nqcmap = QDocDatabase::newQmlTypeMaps()[sinceString];
+
+ if (node->isFunction()) {
+ // Insert functions into the general since map.
+ auto *fn = static_cast<FunctionNode *>(node);
+ if (!fn->isDeprecated() && !fn->isSomeCtor() && !fn->isDtor())
+ nsmap.insert(fn->name(), fn);
+ } else if (node->isClassNode()) {
+ // Insert classes into the since and class maps.
+ QString name = node->qualifyWithParentName();
+ nsmap.insert(name, node);
+ ncmap.insert(name, node);
+ } else if (node->isQmlType()) {
+ // Insert QML elements into the since and element maps.
+ QString name = node->qualifyWithParentName();
+ nsmap.insert(name, node);
+ nqcmap.insert(name, node);
+ } else if (node->isQmlProperty()) {
+ // Insert QML properties into the since map.
+ nsmap.insert(node->name(), node);
+ } else {
+ // Insert external documents into the general since map.
+ QString name = node->qualifyWithParentName();
+ nsmap.insert(name, node);
+ }
+ }
+ // Enum values - a special case as EnumItem is not a Node subclass
+ if (node->isInAPI() && node->isEnumType()) {
+ for (const auto &val : static_cast<EnumNode *>(node)->items()) {
+ sinceString = val.since();
+ if (sinceString.isEmpty())
+ continue;
+ // Insert to enum value map
+ QDocDatabase::newEnumValueMaps()[sinceString].insert(
+ node->name() + "::" + val.name(), node);
+ // Ugly hack: Insert into general map with an empty key -
+ // we need something in there to mark the corresponding
+ // section populated. See Sections class constructor.
+ QDocDatabase::newSinceMaps()[sinceString].replace(QString(), node);
+ }
+ }
+
+ // Recursively find child nodes with since commands.
+ if (node->isAggregate())
+ static_cast<Aggregate *>(node)->findAllSince();
+ }
+}
+
+/*!
+ Resolves the inheritance information for all QML type children
+ of this aggregate.
+*/
+void Aggregate::resolveQmlInheritance()
+{
+ NodeMap previousSearches;
+ for (auto *child : std::as_const(m_children)) {
+ if (!child->isQmlType())
+ continue;
+ static_cast<QmlTypeNode *>(child)->resolveInheritance(previousSearches);
+ }
+}
+
+/*!
+ Returns a word representing the kind of Aggregate this node is.
+ Currently only works for class, struct, and union, but it can
+ easily be extended. If \a cap is true, the word is capitalised.
+ */
+QString Aggregate::typeWord(bool cap) const
+{
+ if (cap) {
+ switch (nodeType()) {
+ case Node::Class:
+ return QLatin1String("Class");
+ case Node::Struct:
+ return QLatin1String("Struct");
+ case Node::Union:
+ return QLatin1String("Union");
+ default:
+ break;
+ }
+ } else {
+ switch (nodeType()) {
+ case Node::Class:
+ return QLatin1String("class");
+ case Node::Struct:
+ return QLatin1String("struct");
+ case Node::Union:
+ return QLatin1String("union");
+ default:
+ break;
+ }
+ }
+ return QString();
+}
+
+/*! \fn int Aggregate::count() const
+ Returns the number of children in the child list.
+ */
+
+/*! \fn const NodeList &Aggregate::childNodes() const
+ Returns a const reference to the child list.
+ */
+
+/*! \fn NodeList::ConstIterator Aggregate::constBegin() const
+ Returns a const iterator pointing at the beginning of the child list.
+ */
+
+/*! \fn NodeList::ConstIterator Aggregate::constEnd() const
+ Returns a const iterator pointing at the end of the child list.
+ */
+
+/*! \fn QmlTypeNode *Aggregate::qmlBaseNode() const
+ If this Aggregate is a QmlTypeNode, this function returns a pointer to
+ the QmlTypeNode that is its base type. Otherwise it returns \c nullptr.
+ A QmlTypeNode doesn't always have a base type, so even when this Aggregate
+ is aQmlTypeNode, the pointer returned can be \c nullptr.
+ */
+
+/*! \fn FunctionMap &Aggregate::functionMap()
+ Returns a reference to this Aggregate's function map, which
+ is a map of all the children of this Aggregate that are
+ FunctionNodes.
+ */
+
+/*! \fn void Aggregate::appendToRelatedByProxy(const NodeList &t)
+ Appends the list of node pointers to the list of elements that are
+ related to this Aggregate but are documented in a different module.
+
+ \sa relatedByProxy()
+ */
+
+/*! \fn NodeList &Aggregate::relatedByProxy()
+ Returns a reference to a list of node pointers where each element
+ points to a node in an index file for some other module, such that
+ whatever the node represents was documented in that other module,
+ but it is related to this Aggregate, so when the documentation for
+ this Aggregate is written, it will contain links to elements in the
+ other module.
+ */
+
+QT_END_NAMESPACE