From 6b12d781faf3802e336923ddc43a822da7546989 Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Tue, 19 Aug 2014 15:27:27 +0200 Subject: [PATCH] qdoc: Generate obsolete members page for QML types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Generation of the obsolete members page, for QML types that have obsolete members, had not been implemented. This update implements that missing feature. The link to the page appears right below the link to the "All Members" page. Change-Id: I3e4bb2a68d5c8ef2bbe2e0c431eccf94ecb1fd3c Task-number: QTBUG-40214 Reviewed-by: Mitch Curtis Reviewed-by: Topi Reiniƶ --- src/tools/qdoc/codemarker.cpp | 2 +- src/tools/qdoc/codemarker.h | 4 +- src/tools/qdoc/codeparser.cpp | 3 +- src/tools/qdoc/cppcodemarker.cpp | 34 ++++++------ src/tools/qdoc/cppcodemarker.h | 4 +- src/tools/qdoc/htmlgenerator.cpp | 91 ++++++++++++++++++++++++++++++-- src/tools/qdoc/htmlgenerator.h | 3 ++ src/tools/qdoc/qmlvisitor.cpp | 3 +- 8 files changed, 117 insertions(+), 27 deletions(-) diff --git a/src/tools/qdoc/codemarker.cpp b/src/tools/qdoc/codemarker.cpp index 235b3c3f04..66721c31e7 100644 --- a/src/tools/qdoc/codemarker.cpp +++ b/src/tools/qdoc/codemarker.cpp @@ -649,7 +649,7 @@ QString CodeMarker::macName(const Node *node, const QString &name) /*! Returns an empty list of documentation sections. */ -QList
CodeMarker::qmlSections(QmlClassNode* , SynopsisStyle ) +QList
CodeMarker::qmlSections(QmlClassNode* , SynopsisStyle , Status ) { return QList
(); } diff --git a/src/tools/qdoc/codemarker.h b/src/tools/qdoc/codemarker.h index aa38b82e24..efb2700717 100644 --- a/src/tools/qdoc/codemarker.h +++ b/src/tools/qdoc/codemarker.h @@ -154,7 +154,9 @@ public: virtual QList
sections(const InnerNode *inner, SynopsisStyle style, Status status) = 0; - virtual QList
qmlSections(QmlClassNode* qmlClassNode, SynopsisStyle style); + virtual QList
qmlSections(QmlClassNode* qmlClassNode, + SynopsisStyle style, + Status status = Okay); virtual QStringList macRefsForNode(Node* node); static void initialize(const Config& config); diff --git a/src/tools/qdoc/codeparser.cpp b/src/tools/qdoc/codeparser.cpp index 3b0a650a74..616087ed82 100644 --- a/src/tools/qdoc/codeparser.cpp +++ b/src/tools/qdoc/codeparser.cpp @@ -261,8 +261,7 @@ void CodeParser::processCommonMetaCommand(const Location& location, node->setStatus(Node::Main); } else if (command == COMMAND_OBSOLETE) { - if (node->status() != Node::Compat) - node->setStatus(Node::Obsolete); + node->setStatus(Node::Obsolete); } else if (command == COMMAND_NONREENTRANT) { node->setThreadSafeness(Node::NonReentrant); diff --git a/src/tools/qdoc/cppcodemarker.cpp b/src/tools/qdoc/cppcodemarker.cpp index d3cb111873..af2ff76405 100644 --- a/src/tools/qdoc/cppcodemarker.cpp +++ b/src/tools/qdoc/cppcodemarker.cpp @@ -1094,7 +1094,7 @@ QString CppCodeMarker::addMarkUp(const QString &in, the list of documentation sections for the children of the \a qmlClassNode. */ -QList
CppCodeMarker::qmlSections(QmlClassNode* qmlClassNode, SynopsisStyle style) +QList
CppCodeMarker::qmlSections(QmlClassNode* qmlClassNode, SynopsisStyle style, Status status) { QList
sections; if (qmlClassNode) { @@ -1144,32 +1144,32 @@ QList
CppCodeMarker::qmlSections(QmlClassNode* qmlClassNode, SynopsisSt continue; } if ((*c)->type() == Node::QmlPropertyGroup) { - insert(qmlproperties, *c, style, Okay); + insert(qmlproperties, *c, style, status); } else if ((*c)->type() == Node::QmlProperty) { const QmlPropertyNode* pn = static_cast(*c); if (pn->isAttached()) - insert(qmlattachedproperties,*c,style,Okay); + insert(qmlattachedproperties,*c,style, status); else { - insert(qmlproperties,*c,style,Okay); + insert(qmlproperties,*c,style, status); } } else if ((*c)->type() == Node::QmlSignal) { const FunctionNode* sn = static_cast(*c); if (sn->isAttached()) - insert(qmlattachedsignals,*c,style,Okay); + insert(qmlattachedsignals,*c,style, status); else - insert(qmlsignals,*c,style,Okay); + insert(qmlsignals,*c,style, status); } else if ((*c)->type() == Node::QmlSignalHandler) { - insert(qmlsignalhandlers,*c,style,Okay); + insert(qmlsignalhandlers,*c,style, status); } else if ((*c)->type() == Node::QmlMethod) { const FunctionNode* mn = static_cast(*c); if (mn->isAttached()) - insert(qmlattachedmethods,*c,style,Okay); + insert(qmlattachedmethods,*c,style, status); else - insert(qmlmethods,*c,style,Okay); + insert(qmlmethods,*c,style, status); } ++c; } @@ -1209,31 +1209,31 @@ QList
CppCodeMarker::qmlSections(QmlClassNode* qmlClassNode, SynopsisSt continue; } if ((*c)->type() == Node::QmlPropertyGroup) { - insert(qmlproperties,*c,style,Okay); + insert(qmlproperties,*c,style, status); } else if ((*c)->type() == Node::QmlProperty) { const QmlPropertyNode* pn = static_cast(*c); if (pn->isAttached()) - insert(qmlattachedproperties,*c,style,Okay); + insert(qmlattachedproperties,*c,style, status); else - insert(qmlproperties,*c,style,Okay); + insert(qmlproperties,*c,style, status); } else if ((*c)->type() == Node::QmlSignal) { const FunctionNode* sn = static_cast(*c); if (sn->isAttached()) - insert(qmlattachedsignals,*c,style,Okay); + insert(qmlattachedsignals,*c,style, status); else - insert(qmlsignals,*c,style,Okay); + insert(qmlsignals,*c,style, status); } else if ((*c)->type() == Node::QmlSignalHandler) { - insert(qmlsignalhandlers,*c,style,Okay); + insert(qmlsignalhandlers,*c,style, status); } else if ((*c)->type() == Node::QmlMethod) { const FunctionNode* mn = static_cast(*c); if (mn->isAttached()) - insert(qmlattachedmethods,*c,style,Okay); + insert(qmlattachedmethods,*c,style, status); else - insert(qmlmethods,*c,style,Okay); + insert(qmlmethods,*c,style, status); } ++c; } diff --git a/src/tools/qdoc/cppcodemarker.h b/src/tools/qdoc/cppcodemarker.h index 74faf1ca57..0b920a8b39 100644 --- a/src/tools/qdoc/cppcodemarker.h +++ b/src/tools/qdoc/cppcodemarker.h @@ -78,7 +78,9 @@ public: virtual QList
sections(const InnerNode *innerNode, SynopsisStyle style, Status status); - virtual QList
qmlSections(QmlClassNode* qmlClassNode, SynopsisStyle style); + virtual QList
qmlSections(QmlClassNode* qmlClassNode, + SynopsisStyle style, + Status status = Okay); private: QString addMarkUp(const QString& protectedCode, diff --git a/src/tools/qdoc/htmlgenerator.cpp b/src/tools/qdoc/htmlgenerator.cpp index 44de7e1154..92b0378e00 100644 --- a/src/tools/qdoc/htmlgenerator.cpp +++ b/src/tools/qdoc/htmlgenerator.cpp @@ -1352,10 +1352,17 @@ void HtmlGenerator::generateQmlTypePage(QmlClassNode* qcn, CodeMarker* marker) generateQmlRequisites(qcn, marker); QString allQmlMembersLink = generateAllQmlMembersFile(qcn, marker); - if (!allQmlMembersLink.isEmpty()) { + QString obsoleteLink = generateQmlMemberFile(qcn, marker, CodeMarker::Obsolete); + if (!allQmlMembersLink.isEmpty() || !obsoleteLink.isEmpty()) { out() << "\n"; } @@ -2572,6 +2579,84 @@ QString HtmlGenerator::generateLowStatusMemberFile(InnerNode *inner, return fileName; } +/*! + Generates a separate file where certain members of the QML + type \a qcn are listed. The \a marker is used to generate + the section lists, which are then traversed and output here. + + Note that this function currently only handles correctly the + case where \a status is \c {CodeMarker::Obsolete}. + */ +QString HtmlGenerator::generateQmlMemberFile(QmlClassNode* qcn, + CodeMarker *marker, + CodeMarker::Status status) +{ + QList
sections = marker->qmlSections(qcn, CodeMarker::Summary, status); + QMutableListIterator
j(sections); + while (j.hasNext()) { + if (j.next().members.size() == 0) + j.remove(); + } + if (sections.isEmpty()) + return QString(); + + QString title = "Obsolete Members for " + qcn->name(); + QString fileName = fileBase(qcn) + "-obsolete." + fileExtension(); + + if (status == CodeMarker::Obsolete) { + QString link; + if (useOutputSubdirs() && !Generator::outputSubdir().isEmpty()) + link = QString("../" + Generator::outputSubdir() + QLatin1Char('/')); + link += fileName; + qcn->setObsoleteLink(link); + } + + beginSubPage(qcn, fileName); + generateHeader(title, qcn, marker); + generateTitle(title, Text(), SmallSubTitle, qcn, marker); + + out() << "

The following members of QML type " + << "" + << protectEnc(qcn->name()) << "" + << " are obsolete. " + << "They are provided to keep old source code working. " + << "We strongly advise against using them in new code.

\n"; + + QList
::const_iterator s = sections.constBegin(); + while (s != sections.constEnd()) { + out() << "" << divNavTop << '\n'; + out() << "

" << protectEnc((*s).name) << "

\n"; + generateQmlSummary(*s, qcn, marker); + ++s; + } + + sections = marker->qmlSections(qcn, CodeMarker::Detailed, status); + QMutableListIterator
k(sections); + while (k.hasNext()) { + if (k.next().members.size() == 0) + k.remove(); + } + if (sections.isEmpty()) + return QString(); + + s = sections.constBegin(); + while (s != sections.constEnd()) { + out() << "

" << protectEnc((*s).name) << "

\n"; + NodeList::ConstIterator m = (*s).members.constBegin(); + while (m != (*s).members.constEnd()) { + generateDetailedQmlMember(*m, qcn, marker); + out() << "
\n"; + ++m; + } + ++s; + } + + generateFooter(); + endSubPage(); + return fileName; +} + void HtmlGenerator::generateClassHierarchy(const Node *relative, NodeMap& classMap) { if (classMap.isEmpty()) diff --git a/src/tools/qdoc/htmlgenerator.h b/src/tools/qdoc/htmlgenerator.h index ef569b38ce..3f76baf191 100644 --- a/src/tools/qdoc/htmlgenerator.h +++ b/src/tools/qdoc/htmlgenerator.h @@ -159,6 +159,9 @@ private: QString generateLowStatusMemberFile(InnerNode *inner, CodeMarker *marker, CodeMarker::Status status); + QString generateQmlMemberFile(QmlClassNode* qcn, + CodeMarker *marker, + CodeMarker::Status status); void generateClassHierarchy(const Node *relative, NodeMap &classMap); void generateAnnotatedList(const Node* relative, CodeMarker* marker, const NodeMap& nodeMap); void generateAnnotatedList(const Node* relative, CodeMarker* marker, const NodeList& nodes); diff --git a/src/tools/qdoc/qmlvisitor.cpp b/src/tools/qdoc/qmlvisitor.cpp index 026f3bd0a2..3f4384dfd6 100644 --- a/src/tools/qdoc/qmlvisitor.cpp +++ b/src/tools/qdoc/qmlvisitor.cpp @@ -407,8 +407,7 @@ void QmlDocVisitor::applyMetacommands(QQmlJS::AST::SourceLocation, node->setStatus(Node::Internal); } else if (command == COMMAND_OBSOLETE) { - if (node->status() != Node::Compat) - node->setStatus(Node::Obsolete); + node->setStatus(Node::Obsolete); } else if (command == COMMAND_PAGEKEYWORDS) { // Not done yet. Do we need this?