diff options
Diffstat (limited to 'src/qdoc/sections.cpp')
-rw-r--r-- | src/qdoc/sections.cpp | 1071 |
1 files changed, 0 insertions, 1071 deletions
diff --git a/src/qdoc/sections.cpp b/src/qdoc/sections.cpp deleted file mode 100644 index c4029514d..000000000 --- a/src/qdoc/sections.cpp +++ /dev/null @@ -1,1071 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the tools applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "sections.h" - -#include "aggregate.h" -#include "classnode.h" -#include "config.h" -#include "enumnode.h" -#include "functionnode.h" -#include "generator.h" -#include "loggingcategory.h" -#include "namespacenode.h" -#include "qmlpropertynode.h" -#include "qmltypenode.h" -#include "sharedcommentnode.h" -#include "typedefnode.h" -#include "variablenode.h" - -#include <QtCore/qobjectdefs.h> - -QT_BEGIN_NAMESPACE - -// Aggregate *Sections::aggregate_ = nullptr; - -static bool sectionsInitialized = false; -QList<Section> Sections::stdSummarySections_(7, Section(Section::Summary, Section::Active)); -QList<Section> Sections::stdDetailsSections_(7, Section(Section::Details, Section::Active)); -QList<Section> Sections::stdCppClassSummarySections_(18, - Section(Section::Summary, Section::Active)); -QList<Section> Sections::stdCppClassDetailsSections_(6, Section(Section::Details, Section::Active)); -QList<Section> Sections::sinceSections_(15, Section(Section::Details, Section::Active)); -QList<Section> Sections::allMembers_(1, Section(Section::AllMembers, Section::Active)); -QList<Section> Sections::stdQmlTypeSummarySections_(7, Section(Section::Summary, Section::Active)); -QList<Section> Sections::stdQmlTypeDetailsSections_(7, Section(Section::Details, Section::Active)); - -/*! - \class Section - \brief A class for containing the elements of one documentation section - */ - -/*! - The constructor used when the \a style and \a status must - be provided. - */ -Section::Section(Style style, Status status) : style_(style), status_(status), aggregate_(nullptr) -{ - // members_.reserve(100); - // obsoleteMembers_.reserve(50); - // reimplementedMembers_.reserve(50); -} - -/*! - The destructor must delete the members of collections - when the members are allocated on the heap. - */ -Section::~Section() -{ - clear(); -} - -/*! - A Section is now an element in a static vector, so we - don't have to repeatedly construct and destroy them. But - we do need to clear them before each call to build the - sections for a C++ or QML entity. - */ -void Section::clear() -{ - memberMap_.clear(); - obsoleteMemberMap_.clear(); - reimplementedMemberMap_.clear(); - if (!classMapList_.isEmpty()) { - for (int i = 0; i < classMapList_.size(); i++) { - ClassMap *cm = classMapList_[i]; - classMapList_[i] = nullptr; - delete cm; - } - classMapList_.clear(); - } - keys_.clear(); - obsoleteKeys_.clear(); - members_.clear(); - obsoleteMembers_.clear(); - reimplementedMembers_.clear(); - inheritedMembers_.clear(); - if (!classKeysNodesList_.isEmpty()) { - for (int i = 0; i < classKeysNodesList_.size(); i++) { - ClassKeysNodes *ckn = classKeysNodesList_[i]; - classKeysNodesList_[i] = nullptr; - delete ckn; - } - classKeysNodesList_.clear(); - } - aggregate_ = nullptr; -} - -/*! - Construct a name for the \a node that can be used for sorting - a set of nodes into equivalence classes. If \a name is provided, - start with that name. Itherwise start with the name in \a node. - */ -QString Section::sortName(const Node *node, const QString *name) -{ - QString nodeName; - if (name != nullptr) - nodeName = *name; - else - nodeName = node->name(); - int numDigits = 0; - for (int i = nodeName.size() - 1; i > 0; --i) { - if (nodeName.at(i).digitValue() == -1) - break; - ++numDigits; - } - - // we want 'qint8' to appear before 'qint16' - if (numDigits > 0) { - for (int i = 0; i < 4 - numDigits; ++i) - nodeName.insert(nodeName.size() - numDigits - 1, QLatin1Char('0')); - } - - if (node->isFunction()) { - const FunctionNode *fn = static_cast<const FunctionNode *>(node); - if (fn->isCppFunction()) { - QString sortNo; - if (fn->isSomeCtor()) - sortNo = QLatin1String("C"); - else if (fn->isDtor()) - sortNo = QLatin1String("D"); - else if (nodeName.startsWith(QLatin1String("operator")) && nodeName.length() > 8 - && !nodeName[8].isLetterOrNumber()) - sortNo = QLatin1String("F"); - else - sortNo = QLatin1String("E"); - return sortNo + nodeName + QLatin1Char(' ') + QString::number(fn->overloadNumber(), 36); - } - if (fn->isQmlMethod() || fn->isQmlSignal() || fn->isQmlSignalHandler()) - return QLatin1Char('E') + nodeName; - - if (fn->isJsMethod() || fn->isJsSignal() || fn->isJsSignalHandler()) - return QLatin1Char('E') + nodeName; - } - if (node->isClassNode()) - return QLatin1Char('A') + nodeName; - - if (node->isProperty() || node->isVariable()) - return QLatin1Char('E') + nodeName; - - return QLatin1Char('B') + nodeName; -} - -/*! - Inserts the \a node into this section if it is appropriate - for this section. - */ -void Section::insert(Node *node) -{ - bool irrelevant = false; - bool inherited = false; - if (!node->isRelatedNonmember()) { - Aggregate *p = node->parent(); - if (!p->isNamespace() && p != aggregate_) { - if ((!p->isQmlType() && !p->isJsType()) || !p->isAbstract()) - inherited = true; - } - } - - if (node->isPrivate() || node->isInternal()) { - irrelevant = true; - } else if (node->isFunction()) { - FunctionNode *func = static_cast<FunctionNode *>(node); - irrelevant = (inherited && (func->isSomeCtor() || func->isDtor())); - } else if (node->isClassNode() || node->isEnumType() || node->isTypedef() - || node->isVariable()) { - irrelevant = (inherited && style_ != AllMembers); - if (!irrelevant && style_ == Details && node->isTypedef()) { - const TypedefNode *tdn = static_cast<const TypedefNode *>(node); - if (tdn->associatedEnum()) - irrelevant = true; - } - } - - if (!irrelevant) { - QString key = sortName(node); - if (node->isObsolete()) { - obsoleteMemberMap_.insert(key, node); - } else { - if (!inherited) - memberMap_.insert(key, node); - else if (style_ == AllMembers) { - if (!memberMap_.contains(key)) - memberMap_.insert(key, node); - } - if (inherited && (node->parent()->isClassNode() || node->parent()->isNamespace())) { - if (inheritedMembers_.isEmpty() - || inheritedMembers_.last().first != node->parent()) { - QPair<Aggregate *, int> p(node->parent(), 0); - inheritedMembers_.append(p); - } - inheritedMembers_.last().second++; - } - } - } -} - -/*! - Returns \c true if the \a node is a reimplemented member - function of the current class. If true, the \a node is - inserted into the reimplemented member map. The test is - performed only when the section status is \e Active. True - is returned only if \a node is inserted into the map. - That is, false is returned if the \a node is already in - the map. - */ -bool Section::insertReimplementedMember(Node *node) -{ - if (!node->isPrivate() && !node->isRelatedNonmember()) { - const FunctionNode *fn = static_cast<const FunctionNode *>(node); - if (!fn->overridesThis().isEmpty() && (status_ == Active)) { - if (fn->parent() == aggregate_) { - QString key = sortName(fn); - if (!reimplementedMemberMap_.contains(key)) { - reimplementedMemberMap_.insert(key, node); - return true; - } - } - } - } - return false; -} - -/*! - Allocate a new ClassMap on the heap for the \a aggregate - node, append it to the list of class maps, and return a - pointer to the new class map. - */ -ClassMap *Section::newClassMap(const Aggregate *aggregate) -{ - ClassMap *classMap = new ClassMap; - classMap->first = static_cast<const QmlTypeNode *>(aggregate); - classMapList_.append(classMap); - return classMap; -} - -/*! - Add node \a n to the \a classMap and to the member map. - */ -void Section::add(ClassMap *classMap, Node *n) -{ - QString key = n->name(); - key = sortName(n, &key); - memberMap_.insert(key, n); - classMap->second.insert(key, n); -} - -/*! - If this section is not empty, convert its maps to sequential - structures for better traversal during doc generation. - */ -void Section::reduce() -{ - if (!isEmpty()) { - keys_ = memberMap_.keys(); - obsoleteKeys_ = obsoleteMemberMap_.keys(); - members_ = memberMap_.values().toVector(); - obsoleteMembers_ = obsoleteMemberMap_.values().toVector(); - reimplementedMembers_ = reimplementedMemberMap_.values().toVector(); - for (int i = 0; i < classMapList_.size(); i++) { - ClassMap *cm = classMapList_[i]; - ClassKeysNodes *ckn = new ClassKeysNodes; - ckn->first = cm->first; - ckn->second.second = cm->second.values().toVector(); - ckn->second.first = cm->second.keys(); - classKeysNodesList_.append(ckn); - } - } -} - -/*! - \class Sections - \brief A class for creating vectors of collections for documentation - - Each element in a vector is an instance of Section, which - contains all the elements that will be documented in one - section of a reference documentation page. - */ - -/*! - This constructor builds the vectors of sections based on the - type of the \a aggregate node. - */ -Sections::Sections(Aggregate *aggregate) : aggregate_(aggregate) -{ - initSections(); - initAggregate(allMembers_, aggregate_); - switch (aggregate_->nodeType()) { - case Node::Class: - case Node::Struct: - case Node::Union: - initAggregate(stdCppClassSummarySections_, aggregate_); - initAggregate(stdCppClassDetailsSections_, aggregate_); - buildStdCppClassRefPageSections(); - break; - case Node::JsType: - case Node::JsBasicType: - case Node::QmlType: - case Node::QmlBasicType: - initAggregate(stdQmlTypeSummarySections_, aggregate_); - initAggregate(stdQmlTypeDetailsSections_, aggregate_); - buildStdQmlTypeRefPageSections(); - break; - case Node::Namespace: - case Node::HeaderFile: - case Node::Proxy: - default: - initAggregate(stdSummarySections_, aggregate_); - initAggregate(stdDetailsSections_, aggregate_); - buildStdRefPageSections(); - break; - } -} - -/*! - This constructor builds a vector of sections from the \e since - node map, \a nsmap - */ -Sections::Sections(const NodeMultiMap &nsmap) : aggregate_(nullptr) -{ - initSections(); - if (nsmap.isEmpty()) - return; - SectionVector §ions = sinceSections(); - for (auto it = nsmap.constBegin(); it != nsmap.constEnd(); ++it) { - Node *node = it.value(); - switch (node->nodeType()) { - case Node::JsType: - case Node::QmlType: - sections[SinceQmlTypes].appendMember(node); - break; - case Node::Namespace: - sections[SinceNamespaces].appendMember(node); - break; - case Node::Class: - case Node::Struct: - case Node::Union: - sections[SinceClasses].appendMember(node); - break; - case Node::Enum: - sections[SinceEnumTypes].appendMember(node); - break; - case Node::Typedef: - sections[SinceTypedefs].appendMember(node); - break; - case Node::TypeAlias: - sections[SinceTypeAliases].appendMember(node); - break; - case Node::Function: { - const FunctionNode *fn = static_cast<const FunctionNode *>(node); - switch (fn->metaness()) { - case FunctionNode::JsSignal: - case FunctionNode::QmlSignal: - sections[SinceQmlSignals].appendMember(node); - break; - case FunctionNode::JsSignalHandler: - case FunctionNode::QmlSignalHandler: - sections[SinceQmlSignalHandlers].appendMember(node); - break; - case FunctionNode::JsMethod: - case FunctionNode::QmlMethod: - sections[SinceQmlMethods].appendMember(node); - break; - default: - if (fn->isMacro()) - sections[SinceMacros].appendMember(node); - else { - Node *p = fn->parent(); - if (p) { - if (p->isClassNode()) - sections[SinceMemberFunctions].appendMember(node); - else if (p->isNamespace()) { - if (p->name().isEmpty()) - sections[SinceGlobalFunctions].appendMember(node); - else - sections[SinceNamespaceFunctions].appendMember(node); - } else - sections[SinceGlobalFunctions].appendMember(node); - } else - sections[SinceGlobalFunctions].appendMember(node); - } - break; - } - break; - } - case Node::Property: - sections[SinceProperties].appendMember(node); - break; - case Node::Variable: - sections[SinceVariables].appendMember(node); - break; - case Node::JsProperty: - case Node::QmlProperty: - sections[SinceQmlProperties].appendMember(node); - break; - default: - break; - } - } -} - -/*! - The behavior of the destructor depends on the type of the - Aggregate node that was passed to the constructor. If the - constructor was passed a multimap, the destruction is a - bit different because there was no Aggregate node. - */ -Sections::~Sections() -{ - if (aggregate_) { - switch (aggregate_->nodeType()) { - case Node::Class: - case Node::Struct: - case Node::Union: - clear(stdCppClassSummarySections()); - clear(stdCppClassDetailsSections()); - allMembersSection().clear(); - break; - case Node::JsType: - case Node::JsBasicType: - case Node::QmlType: - case Node::QmlBasicType: - clear(stdQmlTypeSummarySections()); - clear(stdQmlTypeDetailsSections()); - allMembersSection().clear(); - break; - default: - clear(stdSummarySections()); - clear(stdDetailsSections()); - allMembersSection().clear(); - break; - } - aggregate_ = nullptr; - } else { - clear(sinceSections()); - } -} - -/*! - Initialize the Aggregate in each Section of vector \a v with \a aggregate. - */ -void Sections::initAggregate(SectionVector &v, Aggregate *aggregate) -{ - for (int i = 0; i < v.size(); ++i) - v[i].setAggregate(aggregate); -} - -/*! - This function is called once to initialize all the instances - of QList<Section>. The lists have already been constructed - with the correct number of Section entries in each. Each Section - entry has already been constructed with the correct values of - Style and Status for the list it is in. This function adds the - correct text strings to each section in each vector. - */ -void Sections::initSections() -{ - if (sectionsInitialized) - return; - sectionsInitialized = true; - - allMembers_[0].init("member", "members"); - { - QList<Section> &v = stdCppClassSummarySections_; - v[0].init("Public Types", "public type", "public types"); - v[1].init("Properties", "property", "properties"); - v[2].init("Public Functions", "public function", "public functions"); - v[3].init("Public Slots", "public slot", "public slots"); - v[4].init("Signals", "signal", "signals"); - v[5].init("Public Variables", "public variable", "public variables"); - v[6].init("Static Public Members", "static public member", "static public members"); - v[7].init("Protected Types", "protected type", "protected types"); - v[8].init("Protected Functions", "protected function", "protected functions"); - v[9].init("Protected Slots", "protected slot", "protected slots"); - v[10].init("Protected Variables", "protected type", "protected variables"); - v[11].init("Static Protected Members", "static protected member", - "static protected members"); - v[12].init("Private Types", "private type", "private types"); - v[13].init("Private Functions", "private function", "private functions"); - v[14].init("Private Slots", "private slot", "private slots"); - v[15].init("Static Private Members", "static private member", "static private members"); - v[16].init("Related Non-Members", "related non-member", "related non-members"); - v[17].init("Macros", "macro", "macros"); - } - - { - QList<Section> &v = stdCppClassDetailsSections_; - v[0].init("Member Type Documentation", "types", "member", "members"); - v[1].init("Property Documentation", "prop", "member", "members"); - v[2].init("Member Function Documentation", "func", "member", "members"); - v[3].init("Member Variable Documentation", "vars", "member", "members"); - v[4].init("Related Non-Members", "relnonmem", "member", "members"); - v[5].init("Macro Documentation", "macros", "member", "members"); - } - - { - QList<Section> &v = stdSummarySections_; - v[0].init("Namespaces", "namespace", "namespaces"); - v[1].init("Classes", "class", "classes"); - v[2].init("Types", "type", "types"); - v[3].init("Variables", "variable", "variables"); - v[4].init("Static Variables", "static variable", "static variables"); - v[5].init("Functions", "function", "functions"); - v[6].init("Macros", "macro", "macros"); - } - - { - QList<Section> &v = stdDetailsSections_; - v[0].init("Namespaces", "nmspace", "namespace", "namespaces"); - v[1].init("Classes", "classes", "class", "classes"); - v[2].init("Type Documentation", "types", "type", "types"); - v[3].init("Variable Documentation", "vars", "variable", "variables"); - v[4].init("Static Variables", QString(), "static variable", "static variables"); - v[5].init("Function Documentation", "func", "function", "functions"); - v[6].init("Macro Documentation", "macros", "macro", "macros"); - } - - { - QList<Section> &v = sinceSections_; - v[SinceNamespaces].init(" New Namespaces"); - v[SinceClasses].init(" New Classes"); - v[SinceMemberFunctions].init(" New Member Functions"); - v[SinceNamespaceFunctions].init(" New Functions in Namespaces"); - v[SinceGlobalFunctions].init(" New Global Functions"); - v[SinceMacros].init(" New Macros"); - v[SinceEnumTypes].init(" New Enum Types"); - v[SinceTypedefs].init(" New Typedefs"); - v[SinceTypeAliases].init(" New Type Aliases"); - v[SinceProperties].init(" New Properties"); - v[SinceVariables].init(" New Variables"); - v[SinceQmlTypes].init(" New QML Types"); - v[SinceQmlProperties].init(" New QML Properties"); - v[SinceQmlSignals].init(" New QML Signals"); - v[SinceQmlSignalHandlers].init(" New QML Signal Handlers"); - v[SinceQmlMethods].init(" New QML Methods"); - } - - { - QList<Section> &v = stdQmlTypeSummarySections_; - v[0].init("Properties", "property", "properties"); - v[1].init("Attached Properties", "attached property", "attached properties"); - v[2].init("Signals", "signal", "signals"); - v[3].init("Signal Handlers", "signal handler", "signal handlers"); - v[4].init("Attached Signals", "attached signal", "attached signals"); - v[5].init("Methods", "method", "methods"); - v[6].init("Attached Methods", "attached method", "attached methods"); - } - - { - QList<Section> &v = stdQmlTypeDetailsSections_; - v[0].init("Property Documentation", "qmlprop", "member", "members"); - v[1].init("Attached Property Documentation", "qmlattprop", "member", "members"); - v[2].init("Signal Documentation", "qmlsig", "signal", "signals"); - v[3].init("Signal Handler Documentation", "qmlsighan", "signal handler", "signal handlers"); - v[4].init("Attached Signal Documentation", "qmlattsig", "signal", "signals"); - v[5].init("Method Documentation", "qmlmeth", "member", "members"); - v[6].init("Attached Method Documentation", "qmlattmeth", "member", "members"); - } -} - -/*! - Reset each Section in vector \a v to its initialized state. - */ -void Sections::clear(QList<Section> &v) -{ - for (int i = 0; i < v.size(); ++i) - v[i].clear(); -} - -/*! - Linearize the maps in each Section in \a v. - */ -void Sections::reduce(QList<Section> &v) -{ - for (int i = 0; i < v.size(); ++i) - v[i].reduce(); -} - -/*! - This is a private helper function for buildStdRefPageSections(). - */ -void Sections::stdRefPageSwitch(SectionVector &v, Node *n, Node *t) -{ - // t is the reference node to be tested, n is the node to be distributed. - // t differs from n only for shared comment nodes. - if (!t) - t = n; - - switch (t->nodeType()) { - case Node::Namespace: - v[StdNamespaces].insert(n); - return; - case Node::Class: - case Node::Struct: - case Node::Union: - v[StdClasses].insert(n); - return; - case Node::Enum: - case Node::Typedef: - case Node::TypeAlias: - v[StdTypes].insert(n); - return; - case Node::Function: { - FunctionNode *func = static_cast<FunctionNode *>(t); - if (func->isMacro()) - v[StdMacros].insert(n); - else - v[StdFunctions].insert(n); - } - return; - case Node::Variable: { - const VariableNode *var = static_cast<const VariableNode *>(t); - if (!var->doc().isEmpty()) { - if (var->isStatic()) - v[StdStaticVariables].insert(n); - else - v[StdVariables].insert(n); - } - } - return; - case Node::SharedComment: { - SharedCommentNode *scn = static_cast<SharedCommentNode *>(t); - if (!scn->doc().isEmpty() && scn->collective().count()) - stdRefPageSwitch( - v, scn, - scn->collective().first()); // TODO: warn about mixed node types in collective? - } - return; - default: - return; - } -} - -/*! - Build the section vectors for a standard reference page, - when the aggregate node is not a C++ class or a QML type. - - If this is for a namespace page then if the namespace node - itself does not have documentation, only its children that - have documentation should be documented. In other words, - there are cases where a namespace is declared but does not - have documentation, but some of the elements declared in - that namespace do have documentation. - - This special processing of namespaces that do not have a - documentation comment is meant to allow documenting its - members that do have documentation while avoiding posting - error messages for its members that are not documented. - */ -void Sections::buildStdRefPageSections() -{ - const NamespaceNode *ns = nullptr; - bool documentAll = true; // document all the children - if (aggregate_->isNamespace()) { - ns = static_cast<const NamespaceNode *>(aggregate_); - if (!ns->hasDoc()) - documentAll = false; // only document children that have documentation - } - for (auto it = aggregate_->constBegin(); it != aggregate_->constEnd(); ++it) { - Node *n = *it; - if (documentAll || n->hasDoc()) { - stdRefPageSwitch(stdSummarySections(), n); - stdRefPageSwitch(stdDetailsSections(), n); - } - } - if (!aggregate_->relatedByProxy().isEmpty()) { - const QList<Node *> &relatedBy = aggregate_->relatedByProxy(); - for (const auto &node : relatedBy) - stdRefPageSwitch(stdSummarySections(), node); - } - /* - If we are building the sections for the reference page - for a namespace node, include all the namespace node's - included children in the sections. - */ - if (ns && !ns->includedChildren().isEmpty()) { - const QList<Node *> &children = ns->includedChildren(); - for (const auto &child : children) { - if (documentAll || child->hasDoc()) - stdRefPageSwitch(stdSummarySections(), child); - } - } - reduce(stdSummarySections()); - reduce(stdDetailsSections()); - allMembersSection().reduce(); -} - -/*! - Inserts the node \a n in one of the entries in the vector \a v - depending on the node's type, access attribute, and a few other - attributes if the node is a signal, slot, or function. - */ -void Sections::distributeNodeInSummaryVector(SectionVector &sv, Node *n) -{ - if (n->isSharedCommentNode()) - return; - if (n->isFunction()) { - FunctionNode *fn = static_cast<FunctionNode *>(n); - if (fn->isRelatedNonmember()) { - if (fn->isMacro()) - sv[Macros].insert(n); - else - sv[RelatedNonmembers].insert(n); - return; - } - if (fn->isIgnored()) - return; - if (fn->isSlot()) { - if (fn->isPublic()) - sv[PublicSlots].insert(fn); - else if (fn->isPrivate()) - sv[PrivateSlots].insert(fn); - else - sv[ProtectedSlots].insert(fn); - } else if (fn->isSignal()) { - if (fn->isPublic()) - sv[Signals].insert(fn); - } else if (fn->isPublic()) { - if (fn->isStatic()) - sv[StaticPublicMembers].insert(fn); - else if (!sv[PublicFunctions].insertReimplementedMember(fn)) - sv[PublicFunctions].insert(fn); - } else if (fn->isPrivate()) { - if (fn->isStatic()) - sv[StaticPrivateMembers].insert(fn); - else if (!sv[PrivateFunctions].insertReimplementedMember(fn)) - sv[PrivateFunctions].insert(fn); - } else { // protected - if (fn->isStatic()) - sv[StaticProtectedMembers].insert(fn); - else if (!sv[ProtectedFunctions].insertReimplementedMember(fn)) - sv[ProtectedFunctions].insert(fn); - } - return; - } - if (n->isRelatedNonmember()) { - sv[RelatedNonmembers].insert(n); - return; - } - if (n->isVariable()) { - if (n->isStatic()) { - if (n->isPublic()) - sv[StaticPublicMembers].insert(n); - else if (n->isPrivate()) - sv[StaticPrivateMembers].insert(n); - else - sv[StaticProtectedMembers].insert(n); - } else { - if (n->isPublic()) - sv[PublicVariables].insert(n); - else if (!n->isPrivate()) - sv[ProtectedVariables].insert(n); - } - return; - } - /* - Getting this far means the node is either a property - or some kind of type, like an enum or a typedef. - */ - if (n->isTypedef() && (n->name() == QLatin1String("QtGadgetHelper"))) - return; - if (n->isProperty()) - sv[Properties].insert(n); - else if (n->isPublic()) - sv[PublicTypes].insert(n); - else if (n->isPrivate()) - sv[PrivateTypes].insert(n); - else - sv[ProtectedTypes].insert(n); -} - -/*! - Inserts the node \a n in one of the entries in the vector \a v - depending on the node's type, access attribute, and a few other - attributes if the node is a signal, slot, or function. - */ -void Sections::distributeNodeInDetailsVector(SectionVector &dv, Node *n) -{ - if (n->isSharingComment()) - return; - - // t is the reference node to be tested - typically it's this node (n), but for - // shared comment nodes we need to distribute based on the nodes in its collective. - Node *t = n; - - if (n->isSharedCommentNode() && n->hasDoc()) { - SharedCommentNode *scn = static_cast<SharedCommentNode *>(n); - if (scn->collective().count()) - t = scn->collective().first(); // TODO: warn about mixed node types in collective? - } - - if (t->isFunction()) { - FunctionNode *fn = static_cast<FunctionNode *>(t); - if (fn->isRelatedNonmember()) { - if (fn->isMacro()) - dv[DetailsMacros].insert(n); - else - dv[DetailsRelatedNonmembers].insert(n); - return; - } - if (fn->isIgnored()) - return; - if (!fn->hasAssociatedProperties() || !fn->doc().isEmpty()) - dv[DetailsMemberFunctions].insert(n); - return; - } - if (t->isRelatedNonmember()) { - dv[DetailsRelatedNonmembers].insert(n); - return; - } - if (t->isEnumType() || t->isTypedef()) { - if (t->name() != QLatin1String("QtGadgetHelper")) - dv[DetailsMemberTypes].insert(n); - return; - } - if (t->isProperty()) - dv[DetailsProperties].insert(n); - else if (t->isVariable() && !t->doc().isEmpty()) - dv[DetailsMemberVariables].insert(n); -} - -void Sections::distributeQmlNodeInDetailsVector(SectionVector &dv, Node *n) -{ - if (n->isSharingComment()) - return; - - // t is the reference node to be tested - typically it's this node (n), but for - // shared comment nodes we need to distribute based on the nodes in its collective. - Node *t = n; - - if (n->isSharedCommentNode() && n->hasDoc()) { - if (n->isPropertyGroup()) { - dv[QmlProperties].insert(n); - return; - } - SharedCommentNode *scn = static_cast<SharedCommentNode *>(n); - if (scn->collective().count()) - t = scn->collective().first(); // TODO: warn about mixed node types in collective? - } - - if (t->isQmlProperty() || t->isJsProperty()) { - QmlPropertyNode *pn = static_cast<QmlPropertyNode *>(t); - if (pn->isAttached()) - dv[QmlAttachedProperties].insert(n); - else - dv[QmlProperties].insert(n); - } else if (t->isFunction()) { - FunctionNode *fn = static_cast<FunctionNode *>(t); - if (fn->isQmlSignal() || fn->isJsSignal()) { - if (fn->isAttached()) - dv[QmlAttachedSignals].insert(n); - else - dv[QmlSignals].insert(n); - } else if (fn->isQmlSignalHandler() || fn->isJsSignalHandler()) { - dv[QmlSignalHandlers].insert(n); - } else if (fn->isQmlMethod() || fn->isJsMethod()) { - if (fn->isAttached()) - dv[QmlAttachedMethods].insert(n); - else - dv[QmlMethods].insert(n); - } - } -} - -/*! - Distributes a node \a n into the correct place in the summary section vector \a sv. - Nodes that are sharing a comment are handled recursively - for recursion, the \a - sharing parameter is set to \c true. - */ -void Sections::distributeQmlNodeInSummaryVector(SectionVector &sv, Node *n, bool sharing) -{ - if (n->isSharingComment() && !sharing) - return; - if (n->isQmlProperty() || n->isJsProperty()) { - QmlPropertyNode *pn = static_cast<QmlPropertyNode *>(n); - if (pn->isAttached()) - sv[QmlAttachedProperties].insert(pn); - else - sv[QmlProperties].insert(pn); - } else if (n->isFunction()) { - FunctionNode *fn = static_cast<FunctionNode *>(n); - if (fn->isQmlSignal() || fn->isJsSignal()) { - if (fn->isAttached()) - sv[QmlAttachedSignals].insert(fn); - else - sv[QmlSignals].insert(fn); - } else if (fn->isQmlSignalHandler() || fn->isJsSignalHandler()) { - sv[QmlSignalHandlers].insert(fn); - } else if (fn->isQmlMethod() || fn->isJsMethod()) { - if (fn->isAttached()) - sv[QmlAttachedMethods].insert(fn); - else - sv[QmlMethods].insert(fn); - } - } else if (n->isSharedCommentNode()) { - SharedCommentNode *scn = static_cast<SharedCommentNode *>(n); - if (scn->isPropertyGroup()) { - sv[QmlProperties].insert(scn); - } else { - for (const auto &child : scn->collective()) - distributeQmlNodeInSummaryVector(sv, child, true); - } - } -} - -static void pushBaseClasses(QStack<ClassNode *> &stack, ClassNode *cn) -{ - const QList<RelatedClass> baseClasses = cn->baseClasses(); - for (const auto &cls : baseClasses) { - if (cls.m_node) - stack.prepend(cls.m_node); - } -} - -/*! - Build the section vectors for a standard reference page, - when the aggregate node is a C++. - */ -void Sections::buildStdCppClassRefPageSections() -{ - SectionVector &summarySections = stdCppClassSummarySections(); - SectionVector &detailsSections = stdCppClassDetailsSections(); - Section &allMembers = allMembersSection(); - bool documentAll = true; - if (aggregate_->parent() && !aggregate_->name().isEmpty() && !aggregate_->hasDoc()) - documentAll = false; - for (auto it = aggregate_->constBegin(); it != aggregate_->constEnd(); ++it) { - Node *n = *it; - if (!n->isPrivate() && !n->isProperty() && !n->isRelatedNonmember() - && !n->isSharedCommentNode()) - allMembers.insert(n); - if (!documentAll && !n->hasDoc()) - continue; - - distributeNodeInSummaryVector(summarySections, n); - distributeNodeInDetailsVector(detailsSections, n); - } - if (!aggregate_->relatedByProxy().isEmpty()) { - const QList<Node *> relatedBy = aggregate_->relatedByProxy(); - for (const auto &node : relatedBy) - distributeNodeInSummaryVector(summarySections, node); - } - - QStack<ClassNode *> stack; - ClassNode *cn = static_cast<ClassNode *>(aggregate_); - pushBaseClasses(stack, cn); - while (!stack.isEmpty()) { - ClassNode *cn = stack.pop(); - for (auto it = cn->constBegin(); it != cn->constEnd(); ++it) { - Node *n = *it; - if (!n->isPrivate() && !n->isProperty() && !n->isRelatedNonmember() - && !n->isSharedCommentNode()) - allMembers.insert(n); - if (!documentAll && !n->hasDoc()) - continue; - } - pushBaseClasses(stack, cn); - } - reduce(summarySections); - reduce(detailsSections); - allMembers.reduce(); -} - -/*! - Build the section vectors for a standard reference page, - when the aggregate node is a QML type. - */ -void Sections::buildStdQmlTypeRefPageSections() -{ - ClassMap *classMap = nullptr; - SectionVector &summarySections = stdQmlTypeSummarySections(); - SectionVector &detailsSections = stdQmlTypeDetailsSections(); - Section &allMembers = allMembersSection(); - - const Aggregate *qtn = aggregate_; - while (qtn) { - if (!qtn->isAbstract() || !classMap) - classMap = allMembers.newClassMap(qtn); - for (const auto n : qtn->childNodes()) { - if (n->isInternal()) - continue; - - if (!n->isSharedCommentNode() || n->isPropertyGroup()) - allMembers.add(classMap, n); - - if (qtn == aggregate_ || qtn->isAbstract()) { - distributeQmlNodeInSummaryVector(summarySections, n); - distributeQmlNodeInDetailsVector(detailsSections, n); - } - } - if (qtn->qmlBaseNode() == qtn) { - qCDebug(lcQdoc, "error: circular type definition: '%s' inherits itself", - qPrintable(qtn->name())); - break; - } - qtn = static_cast<QmlTypeNode *>(qtn->qmlBaseNode()); - } - - reduce(summarySections); - reduce(detailsSections); - allMembers.reduce(); -} - -/*! - Returns true if any sections in this object contain obsolete - members. If it returns false, then \a summary_spv and \a details_spv - have not been modified. Otherwise, both vectors will contain pointers - to the sections that contain obsolete members. - */ -bool Sections::hasObsoleteMembers(SectionPtrVector *summary_spv, - SectionPtrVector *details_spv) const -{ - const SectionVector *sections = nullptr; - if (aggregate_->isClassNode()) - sections = &stdCppClassSummarySections(); - else if (aggregate_->isQmlType() || aggregate_->isQmlBasicType()) - sections = &stdQmlTypeSummarySections(); - else - sections = &stdSummarySections(); - for (const auto §ion : *sections) { - if (!section.obsoleteMembers().isEmpty()) - summary_spv->append(§ion); - } - if (aggregate_->isClassNode()) - sections = &stdCppClassDetailsSections(); - else if (aggregate_->isQmlType() || aggregate_->isQmlBasicType()) - sections = &stdQmlTypeDetailsSections(); - else - sections = &stdDetailsSections(); - for (const auto &it : *sections) { - if (!it.obsoleteMembers().isEmpty()) - details_spv->append(&it); - } - return !summary_spv->isEmpty(); -} - -QT_END_NAMESPACE |