diff --git a/src/qdoc/cppcodeparser.cpp b/src/qdoc/cppcodeparser.cpp index 47f3f52a6678b6dc983ad736fedab6c406e33a9a..b05e2ab3c4c0f3c21b1a09453541ffd8d0556853 100644 --- a/src/qdoc/cppcodeparser.cpp +++ b/src/qdoc/cppcodeparser.cpp @@ -458,22 +458,11 @@ void CppCodeParser::processQmlProperties(const Doc &doc, NodeList &nodes, DocLis group = property.left(i); } + NodeList sharedNodes; QmlTypeNode *qmlType = qdb_->findQmlType(module, qmlTypeName); if (qmlType == nullptr) qmlType = new QmlTypeNode(qdb_->primaryTreeRoot(), qmlTypeName); - SharedCommentNode *scn = nullptr; - if (topics.size() > 1) { - scn = new SharedCommentNode(qmlType, topics.size(), group); - scn->setLocation(doc.startLocation()); - if (jsProps) - scn->setGenus(Node::JS); - else - scn->setGenus(Node::QML); - nodes.append(scn); - docs.append(doc); - } - for (int i=0; i<topics.size(); ++i) { QString cmd = topics.at(i).topic; arg = topics.at(i).args; @@ -492,20 +481,29 @@ void CppCodeParser::processQmlProperties(const Doc &doc, NodeList &nodes, DocLis continue; } QmlPropertyNode *qpn = new QmlPropertyNode(qmlType, property, type, attached); - if (scn != nullptr) - qpn->setSharedCommentNode(scn); qpn->setLocation(doc.startLocation()); - if (jsProps) - qpn->setGenus(Node::JS); - else - qpn->setGenus(Node::QML); + qpn->setGenus(jsProps ? Node::JS : Node::QML); nodes.append(qpn); docs.append(doc); + sharedNodes << qpn; } } else { doc.startLocation().warning(tr("Command '\\%1'; not allowed with QML/JS property commands").arg(cmd)); } } + + // Construct a SharedCommentNode (scn) if multiple topics generated + // valid nodes. Note that it's important to do this *after* constructing + // the topic nodes - which need to be written to index before the related + // scn. + if (sharedNodes.count() > 1) { + SharedCommentNode *scn = new SharedCommentNode(qmlType, sharedNodes.count(), group); + scn->setLocation(doc.startLocation()); + nodes.append(scn); + docs.append(doc); + for (const auto n : sharedNodes) + scn->append(n); + } } /*! @@ -1005,7 +1003,7 @@ void CppCodeParser::processTopicArgs(const Doc &doc, const QString &topic, NodeL bool found = false; for (SharedCommentNode *scn : sharedCommentNodes) { if (scn->parent() == node->parent()) { - node->setSharedCommentNode(scn); + scn->append(node); found = true; break; } diff --git a/src/qdoc/htmlgenerator.cpp b/src/qdoc/htmlgenerator.cpp index 6905483e91a0799482537cadae0c010e10d98058..0430e832fe3945951cdac304cb64b00e2e49d9db 100644 --- a/src/qdoc/htmlgenerator.cpp +++ b/src/qdoc/htmlgenerator.cpp @@ -2738,20 +2738,30 @@ QString HtmlGenerator::generateAllQmlMembersFile(const Sections §ions, CodeM } out() << "<ul>\n"; for (int j=0; j<keys.size(); j++) { - if (nodes[j]->access() == Node::Private || nodes[j]->isInternal()) { + Node *node = nodes[j]; + if (node->access() == Node::Private || node->isInternal()) continue; - } - out() << "<li class=\"fn\">"; - QString prefix; - if (!keys.isEmpty()) { - prefix = keys.at(j).mid(1); - prefix = prefix.left(keys.at(j).indexOf("::")+1); - } - generateQmlItem(nodes[j], aggregate, marker, true); - if (nodes[j]->isAttached()) - out() << " [attached]"; - //generateSynopsis(nodes[j], qcn, marker, Section::AllMembers, false, &prefix); - out() << "</li>\n"; + if (node->isSharingComment() && + node->sharedCommentNode()->isPropertyGroup()) + continue; + + std::function<void(Node *)> generate = [&](Node *n) { + out() << "<li class=\"fn\">"; + generateQmlItem(n, aggregate, marker, true); + if (n->isDefault()) + out() << " [default]"; + else if (n->isAttached()) + out() << " [attached]"; + // Indent property group members + if (n->isPropertyGroup()) { + out() << "<ul>\n"; + const QVector<Node *> &collective = static_cast<SharedCommentNode *>(n)->collective(); + std::for_each(collective.begin(), collective.end(), generate); + out() << "</ul>\n"; + } + out() << "</li>\n"; + }; + generate(node); } out() << "</ul>\n"; } @@ -4038,13 +4048,11 @@ void HtmlGenerator::generateDetailedMember(const Node *node, if (collective.size() > 1) out() << "<div class=\"fngroup\">\n"; for (const auto *node : collective) { - if (node->isFunction()) { - nodeRef = refForNode(node); - out() << "<h3 class=\"fn fngroupitem\" id=\"" << nodeRef << "\">"; - out() << "<a name=\"" + nodeRef + "\"></a>"; - generateSynopsis(node, relative, marker, Section::Details); - out() << "</h3>"; - } + nodeRef = refForNode(node); + out() << "<h3 class=\"fn fngroupitem\" id=\"" << nodeRef << "\">"; + out() << "<a name=\"" + nodeRef + "\"></a>"; + generateSynopsis(node, relative, marker, Section::Details); + out() << "</h3>"; } if (collective.size() > 1) out() << "</div>"; diff --git a/src/qdoc/node.cpp b/src/qdoc/node.cpp index 06f2d6bd66a5ba223f2888a1d1d20273fed87c20..839dd1336b6d27c61b61dedc5e2d1dc38af6431e 100644 --- a/src/qdoc/node.cpp +++ b/src/qdoc/node.cpp @@ -1238,15 +1238,6 @@ void Node::setLocation(const Location& t) } } -/*! - Adds this node to the shared comment node \a t. - */ -void Node::setSharedCommentNode(SharedCommentNode *t) -{ - sharedCommentNode_ = t; - t->append(this); -} - /*! Returns true if this node is sharing a comment and the shared comment is not empty. @@ -2455,10 +2446,10 @@ void Aggregate::addChild(Node *child) child->setOutputSubdirectory(this->outputSubdirectory()); child->setUrl(QString()); child->setIndexNodeFlag(isIndexNode()); + if (child->isFunction()) { addFunction(static_cast<FunctionNode *>(child)); - } - else { + } else if (!child->name().isEmpty()) { nonfunctionMap_.insertMulti(child->name(), child); if (child->isEnumType()) enumChildren_.append(child); @@ -2483,16 +2474,15 @@ void Aggregate::adoptChild(Node *child) child->setParent(this); if (child->isFunction()) { adoptFunction(static_cast<FunctionNode *>(child)); - } - else { + } else if (!child->name().isEmpty()) { nonfunctionMap_.insertMulti(child->name(), child); - if (child->isEnumType()) { + if (child->isEnumType()) enumChildren_.append(child); - } else if (child->isSharedCommentNode()) { - SharedCommentNode *scn = static_cast<SharedCommentNode *>(child); - for (Node *n : scn->collective()) - adoptChild(n); - } + } + if (child->isSharedCommentNode()) { + SharedCommentNode *scn = static_cast<SharedCommentNode *>(child); + for (Node *n : scn->collective()) + adoptChild(n); } } } diff --git a/src/qdoc/node.h b/src/qdoc/node.h index 71a603146dc42ac6e20e62e6dfedef2c9f1d3e2f..0b6eb9e6267f430e15d9d2504be3b6fee607d726 100644 --- a/src/qdoc/node.h +++ b/src/qdoc/node.h @@ -323,7 +323,8 @@ public: bool isSharingComment() const { return (sharedCommentNode_ != nullptr); } bool hasSharedDoc() const; - void setSharedCommentNode(SharedCommentNode *t); + void setSharedCommentNode(SharedCommentNode *t) { sharedCommentNode_ = t; } + SharedCommentNode *sharedCommentNode() { return sharedCommentNode_; } //QString guid() const; QString extractClassName(const QString &string) const; @@ -899,7 +900,8 @@ class SharedCommentNode : public Node public: SharedCommentNode(Node *n) : Node(Node::SharedComment, n->parent(), QString()) { - collective_.reserve(1); n->setSharedCommentNode(this); + collective_.reserve(1); + append(n); } SharedCommentNode(QmlTypeNode *parent, int count, QString &group) : Node(Node::SharedComment, parent, group) { @@ -907,11 +909,13 @@ public: } ~SharedCommentNode() override { collective_.clear(); } - bool isPropertyGroup() const override { return !collective_.isEmpty() && - (collective_.at(0)->isQmlProperty() || collective_.at(0)->isJsProperty()); + bool isPropertyGroup() const override { + return !name().isEmpty() && + !collective_.isEmpty() && + (collective_.at(0)->isQmlProperty() || collective_.at(0)->isJsProperty()); } int count() const { return collective_.size(); } - void append(Node *n) { collective_.append(n); } + void append(Node *n) { collective_.append(n); n->setSharedCommentNode(this); setGenus(n->genus()); } const QVector<Node *> &collective() const { return collective_; } void setOverloadFlags(); void setRelatedNonmember(bool b) override; diff --git a/src/qdoc/sections.cpp b/src/qdoc/sections.cpp index 4b47121806be25f1a5df1b781d1038dd124c02ec..8ba71f17ce29347349035d5fc442eb82a20988b7 100644 --- a/src/qdoc/sections.cpp +++ b/src/qdoc/sections.cpp @@ -904,9 +904,14 @@ void Sections::distributeQmlNodeInDetailsVector(SectionVector &dv, Node *n) } } -void Sections::distributeQmlNodeInSummaryVector(SectionVector &sv, Node *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->isSharedCommentNode()) + if (n->isSharingComment() && !sharing) return; if (n->isQmlProperty() || n->isJsProperty()) { QmlPropertyNode *pn = static_cast<QmlPropertyNode *>(n); @@ -929,6 +934,14 @@ void Sections::distributeQmlNodeInSummaryVector(SectionVector &sv, Node *n) else sv[QmlMethods].insert(fn); } + } else if (n->isSharedCommentNode()) { + SharedCommentNode *scn = static_cast<SharedCommentNode*>(n); + if (scn->isPropertyGroup()) { + sv[QmlProperties].insert(scn); + } else { + for (auto child : scn->collective()) + distributeQmlNodeInSummaryVector(sv, child, true); + } } } @@ -1023,7 +1036,9 @@ void Sections::buildStdQmlTypeRefPageSections() ++c; continue; } - allMembers.add(classMap, n); + if (!n->isSharedCommentNode() || n->isPropertyGroup()) + allMembers.add(classMap, n); + distributeQmlNodeInSummaryVector(sv, n); distributeQmlNodeInDetailsVector(dv, n); ++c; diff --git a/src/qdoc/sections.h b/src/qdoc/sections.h index c2f07cf6579e5ab75749cd9c976ae65ca8f9f2ea..92c2cdd2b9293fd814241676b768d0f9fe2c2e75 100644 --- a/src/qdoc/sections.h +++ b/src/qdoc/sections.h @@ -233,7 +233,7 @@ class Sections void distributeNodeInSummaryVector(SectionVector &sv, Node *n); void distributeNodeInDetailsVector(SectionVector &dv, Node *n); void distributeQmlNodeInDetailsVector(SectionVector &dv, Node *n); - void distributeQmlNodeInSummaryVector(SectionVector &sv, Node *n); + void distributeQmlNodeInSummaryVector(SectionVector &sv, Node *n, bool sharing = false); void initAggregate(SectionVector &v, Aggregate *aggregate); private: