From d3c05eb7e943ca8d4bd55e5eea236eaf08ce5cf5 Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Tue, 15 Oct 2019 14:44:06 +0200 Subject: qdoc: Fix issues with shared comment nodes QDoc stores elements to the .index correctly, but the nodes that were sharing a comment were added after the shared comment. This meant that a shared comment node (SCN) could not find any of its members as they hadn't been read in yet. Fix this by delaying the creation of a new SCN until we have a list of sharing nodes. Also fix other related issues: - Generate content also for non-function SCN members. - Make SCN adopt the genus of a member when adding one. - Fix Node::isPropertyGroup() to return true for actual property groups (not all QML properties that share a comment) and fix usage of that method. - Fix linking to property groups when searching by the group name. - Restore indentation of property group members both in the summary section and in the All Members file. Fixes: QTBUG-79204 Change-Id: I1702f39b178f52444436b800d4fe9cb99f976a60 Reviewed-by: Paul Wicking Reviewed-by: Martin Smith --- src/qdoc/cppcodeparser.cpp | 36 ++++++++++++++++------------------ src/qdoc/htmlgenerator.cpp | 48 +++++++++++++++++++++++++++------------------- src/qdoc/node.cpp | 28 +++++++++------------------ src/qdoc/node.h | 14 +++++++++----- src/qdoc/sections.cpp | 21 +++++++++++++++++--- src/qdoc/sections.h | 2 +- 6 files changed, 82 insertions(+), 67 deletions(-) diff --git a/src/qdoc/cppcodeparser.cpp b/src/qdoc/cppcodeparser.cpp index 47f3f52a6..b05e2ab3c 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; isetSharedCommentNode(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 6905483e9..0430e832f 100644 --- a/src/qdoc/htmlgenerator.cpp +++ b/src/qdoc/htmlgenerator.cpp @@ -2738,20 +2738,30 @@ QString HtmlGenerator::generateAllQmlMembersFile(const Sections §ions, CodeM } out() << "
    \n"; for (int j=0; jaccess() == Node::Private || nodes[j]->isInternal()) { + Node *node = nodes[j]; + if (node->access() == Node::Private || node->isInternal()) continue; - } - out() << "
  • "; - 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() << "
  • \n"; + if (node->isSharingComment() && + node->sharedCommentNode()->isPropertyGroup()) + continue; + + std::function generate = [&](Node *n) { + out() << "
  • "; + generateQmlItem(n, aggregate, marker, true); + if (n->isDefault()) + out() << " [default]"; + else if (n->isAttached()) + out() << " [attached]"; + // Indent property group members + if (n->isPropertyGroup()) { + out() << "
      \n"; + const QVector &collective = static_cast(n)->collective(); + std::for_each(collective.begin(), collective.end(), generate); + out() << "
    \n"; + } + out() << "
  • \n"; + }; + generate(node); } out() << "
\n"; } @@ -4038,13 +4048,11 @@ void HtmlGenerator::generateDetailedMember(const Node *node, if (collective.size() > 1) out() << "
\n"; for (const auto *node : collective) { - if (node->isFunction()) { - nodeRef = refForNode(node); - out() << "

"; - out() << ""; - generateSynopsis(node, relative, marker, Section::Details); - out() << "

"; - } + nodeRef = refForNode(node); + out() << "

"; + out() << ""; + generateSynopsis(node, relative, marker, Section::Details); + out() << "

"; } if (collective.size() > 1) out() << "
"; diff --git a/src/qdoc/node.cpp b/src/qdoc/node.cpp index 06f2d6bd6..839dd1336 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(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(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(child); - for (Node *n : scn->collective()) - adoptChild(n); - } + } + if (child->isSharedCommentNode()) { + SharedCommentNode *scn = static_cast(child); + for (Node *n : scn->collective()) + adoptChild(n); } } } diff --git a/src/qdoc/node.h b/src/qdoc/node.h index 71a603146..0b6eb9e62 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 &collective() const { return collective_; } void setOverloadFlags(); void setRelatedNonmember(bool b) override; diff --git a/src/qdoc/sections.cpp b/src/qdoc/sections.cpp index 4b4712180..8ba71f17c 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(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(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 c2f07cf65..92c2cdd2b 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: -- cgit v1.2.3