diff options
-rw-r--r-- | src/qdoc/aggregate.cpp | 16 | ||||
-rw-r--r-- | src/qdoc/enumitem.h | 8 | ||||
-rw-r--r-- | src/qdoc/enumnode.cpp | 13 | ||||
-rw-r--r-- | src/qdoc/enumnode.h | 1 | ||||
-rw-r--r-- | src/qdoc/htmlgenerator.cpp | 9 | ||||
-rw-r--r-- | src/qdoc/qdocdatabase.cpp | 1 | ||||
-rw-r--r-- | src/qdoc/qdocdatabase.h | 2 | ||||
-rw-r--r-- | src/qdoc/qdocindexfiles.cpp | 7 | ||||
-rw-r--r-- | src/qdoc/sections.cpp | 42 | ||||
-rw-r--r-- | src/qdoc/sections.h | 17 | ||||
-rw-r--r-- | src/qdoc/tree.cpp | 36 | ||||
-rw-r--r-- | src/qdoc/tree.h | 1 | ||||
-rw-r--r-- | tests/auto/qdoc/generatedoutput/expected_output/scopedenum-docbook/testqdoc-test.xml | 2 | ||||
-rw-r--r-- | tests/auto/qdoc/generatedoutput/expected_output/scopedenum/testqdoc-test.html | 2 | ||||
-rw-r--r-- | tests/auto/qdoc/generatedoutput/expected_output/scopedenum/whatsnew.html | 39 | ||||
-rw-r--r-- | tests/auto/qdoc/generatedoutput/testdata/scopedenum/scopedenum.qdoc | 9 | ||||
-rw-r--r-- | tests/auto/qdoc/generatedoutput/tst_generatedoutput.cpp | 5 |
17 files changed, 177 insertions, 33 deletions
diff --git a/src/qdoc/aggregate.cpp b/src/qdoc/aggregate.cpp index 0ecc6d337..9931d9d4f 100644 --- a/src/qdoc/aggregate.cpp +++ b/src/qdoc/aggregate.cpp @@ -781,6 +781,22 @@ void Aggregate::findAllSince() nsmap.value().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(); diff --git a/src/qdoc/enumitem.h b/src/qdoc/enumitem.h index 041c18284..06e9d42a9 100644 --- a/src/qdoc/enumitem.h +++ b/src/qdoc/enumitem.h @@ -15,14 +15,20 @@ class EnumItem { public: EnumItem() = default; - EnumItem(QString name, QString value) : m_name(std::move(name)), m_value(std::move(value)) { } + EnumItem(QString name, QString value, QString since = QString()) + : m_name(std::move(name)), + m_value(std::move(value)), + m_since(std::move(since)) {} [[nodiscard]] const QString &name() const { return m_name; } [[nodiscard]] const QString &value() const { return m_value; } + [[nodiscard]] const QString &since() const { return m_since; } + void setSince(const QString &since) { m_since = since; } private: QString m_name {}; QString m_value {}; + QString m_since {}; }; QT_END_NAMESPACE diff --git a/src/qdoc/enumnode.cpp b/src/qdoc/enumnode.cpp index f948b02d6..48a2f81aa 100644 --- a/src/qdoc/enumnode.cpp +++ b/src/qdoc/enumnode.cpp @@ -46,6 +46,19 @@ QString EnumNode::itemValue(const QString &name) const } /*! + Sets \a since information to a named enum \a value, if it + exists in this enum. +*/ +void EnumNode::setSince(const QString &value, const QString &since) +{ + auto it = std::find_if(m_items.begin(), m_items.end(), [value](EnumItem ev) { + return ev.name() == value; + }); + if (it != m_items.end()) + it->setSince(since); +} + +/*! Clone this node on the heap and make the clone a child of \a parent. diff --git a/src/qdoc/enumnode.h b/src/qdoc/enumnode.h index f85647540..47139ae4d 100644 --- a/src/qdoc/enumnode.h +++ b/src/qdoc/enumnode.h @@ -35,6 +35,7 @@ public: const TypedefNode *flagsType() const { return m_flagsType; } QString itemValue(const QString &name) const; Node *clone(Aggregate *parent) override; + void setSince(const QString &value, const QString &since); private: QList<EnumItem> m_items {}; diff --git a/src/qdoc/htmlgenerator.cpp b/src/qdoc/htmlgenerator.cpp index 2266c69e4..829950615 100644 --- a/src/qdoc/htmlgenerator.cpp +++ b/src/qdoc/htmlgenerator.cpp @@ -562,6 +562,15 @@ qsizetype HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, Co generateSection(nv, relative, marker); out() << "<br/>"; } + } else if (index == Sections::SinceEnumValues) { + out() << "<div class=\"table\"><table class=\"alignedsummary\" translate=\"no\">\n"; + const auto map_it = m_qdb->newEnumValueMaps().constFind(atom->string()); + for (auto it = map_it->cbegin(); it != map_it->cend(); ++it) { + out() << "<tr><td class=\"memItemLeft\"> enum value </td><td class=\"memItemRight\">" + << "<b><a href=\"" << linkForNode(it.value(), nullptr) << "\">" + << it.key() << "</a></b></td></tr>\n"; + } + out() << "</table></div>\n"; } else { generateSection(section.members(), relative, marker); } diff --git a/src/qdoc/qdocdatabase.cpp b/src/qdoc/qdocdatabase.cpp index de099b881..91f625dbd 100644 --- a/src/qdoc/qdocdatabase.cpp +++ b/src/qdoc/qdocdatabase.cpp @@ -335,6 +335,7 @@ NodeMultiMap QDocDatabase::s_qmlTypes; NodeMultiMap QDocDatabase::s_examples; NodeMultiMapMap QDocDatabase::s_newClassMaps; NodeMultiMapMap QDocDatabase::s_newQmlTypeMaps; +NodeMultiMapMap QDocDatabase::s_newEnumValueMaps; NodeMultiMapMap QDocDatabase::s_newSinceMaps; /*! diff --git a/src/qdoc/qdocdatabase.h b/src/qdoc/qdocdatabase.h index 02ab28e8f..30885566d 100644 --- a/src/qdoc/qdocdatabase.h +++ b/src/qdoc/qdocdatabase.h @@ -211,6 +211,7 @@ public: static NodeMultiMap &examples() { return s_examples; } static NodeMultiMapMap &newClassMaps() { return s_newClassMaps; } static NodeMultiMapMap &newQmlTypeMaps() { return s_newQmlTypeMaps; } + static NodeMultiMapMap &newEnumValueMaps() { return s_newEnumValueMaps; } static NodeMultiMapMap &newSinceMaps() { return s_newSinceMaps; } private: @@ -375,6 +376,7 @@ private: static NodeMultiMap s_examples; static NodeMultiMapMap s_newClassMaps; static NodeMultiMapMap s_newQmlTypeMaps; + static NodeMultiMapMap s_newEnumValueMaps; static NodeMultiMapMap s_newSinceMaps; QString m_version {}; diff --git a/src/qdoc/qdocindexfiles.cpp b/src/qdoc/qdocindexfiles.cpp index 3f79c8fbf..70720a1b1 100644 --- a/src/qdoc/qdocindexfiles.cpp +++ b/src/qdoc/qdocindexfiles.cpp @@ -369,9 +369,10 @@ void QDocIndexFiles::readIndexSection(QXmlStreamReader &reader, Node *current, while (reader.readNextStartElement()) { QXmlStreamAttributes childAttributes = reader.attributes(); if (reader.name() == QLatin1String("value")) { - EnumItem item(childAttributes.value(QLatin1String("name")).toString(), - childAttributes.value(QLatin1String("value")).toString()); + childAttributes.value(QLatin1String("value")).toString(), + childAttributes.value(QLatin1String("since")).toString() + ); enumNode->addItem(item); } else if (reader.name() == QLatin1String("keyword")) { insertTarget(TargetRec::Keyword, childAttributes, enumNode); @@ -1043,6 +1044,8 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter &writer, Node *node, writer.writeStartElement("value"); writer.writeAttribute("name", item.name()); writer.writeAttribute("value", item.value()); + if (!item.since().isEmpty()) + writer.writeAttribute("since", item.since()); writer.writeEndElement(); // value } } break; diff --git a/src/qdoc/sections.cpp b/src/qdoc/sections.cpp index f2be10de2..34fc9b372 100644 --- a/src/qdoc/sections.cpp +++ b/src/qdoc/sections.cpp @@ -92,21 +92,22 @@ QList<Section> Sections::s_stdQmlTypeDetailsSections { }; QList<Section> Sections::s_sinceSections { - { " New Namespaces", "", "", "", Section::Details }, - { " New Classes", "", "", "", Section::Details }, - { " New Member Functions", "", "", "", Section::Details }, - { " New Functions in Namespaces", "", "", "", Section::Details }, - { " New Global Functions", "", "", "", Section::Details }, - { " New Macros", "", "", "", Section::Details }, - { " New Enum Types", "", "", "", Section::Details }, - { " New Type Aliases", "", "", "", Section::Details }, - { " New Properties", "", "", "", Section::Details }, - { " New Variables", "", "", "", Section::Details }, - { " New QML Types", "", "", "", Section::Details }, - { " New QML Properties", "", "", "", Section::Details }, - { " New QML Signals", "", "", "", Section::Details }, - { " New QML Signal Handlers", "", "", "", Section::Details }, - { " New QML Methods", "", "", "", Section::Details }, + { "New Namespaces", "", "", "", Section::Details }, + { "New Classes", "", "", "", Section::Details }, + { "New Member Functions", "", "", "", Section::Details }, + { "New Functions in Namespaces", "", "", "", Section::Details }, + { "New Global Functions", "", "", "", Section::Details }, + { "New Macros", "", "", "", Section::Details }, + { "New Enum Types", "", "", "", Section::Details }, + { "New Enum Values", "", "", "", Section::Details }, + { "New Type Aliases", "", "", "", Section::Details }, + { "New Properties", "", "", "", Section::Details }, + { "New Variables", "", "", "", Section::Details }, + { "New QML Types", "", "", "", Section::Details }, + { "New QML Properties", "", "", "", Section::Details }, + { "New QML Signals", "", "", "", Section::Details }, + { "New QML Signal Handlers", "", "", "", Section::Details }, + { "New QML Methods", "", "", "", Section::Details }, }; QList<Section> Sections::s_allMembers{ { "", "member", "members", "", Section::AllMembers } }; @@ -391,9 +392,16 @@ Sections::Sections(const NodeMultiMap &nsmap) : m_aggregate(nullptr) case Node::Union: sections[SinceClasses].appendMember(node); break; - case Node::Enum: - sections[SinceEnumTypes].appendMember(node); + case Node::Enum: { + // The map can contain an enum node with \since, or an enum node + // with \value containing a since-clause. In the latter case, + // key() is an empty string. + if (!it.key().isEmpty()) + sections[SinceEnumTypes].appendMember(node); + else + sections[SinceEnumValues].appendMember(node); break; + } case Node::Typedef: case Node::TypeAlias: sections[SinceTypeAliases].appendMember(node); diff --git a/src/qdoc/sections.h b/src/qdoc/sections.h index 13afa07f6..70c73a91c 100644 --- a/src/qdoc/sections.h +++ b/src/qdoc/sections.h @@ -116,22 +116,23 @@ public: SinceEnumTypes = 6, StdMacros = 6, QmlAttachedMethods = 6, + SinceEnumValues = 7, ProtectedTypes = 7, - SinceTypeAliases = 7, + SinceTypeAliases = 8, ProtectedFunctions = 8, - SinceProperties = 8, + SinceProperties = 9, ProtectedSlots = 9, - SinceVariables = 9, + SinceVariables = 10, ProtectedVariables = 10, - SinceQmlTypes = 10, + SinceQmlTypes = 11, StaticProtectedMembers = 11, - SinceQmlProperties = 11, + SinceQmlProperties = 12, PrivateTypes = 12, - SinceQmlSignals = 12, + SinceQmlSignals = 13, PrivateFunctions = 13, - SinceQmlSignalHandlers = 13, + SinceQmlSignalHandlers = 14, PrivateSlots = 14, - SinceQmlMethods = 14, + SinceQmlMethods = 15, StaticPrivateMembers = 15, RelatedNonmembers = 16, Macros = 17 diff --git a/src/qdoc/tree.cpp b/src/qdoc/tree.cpp index f0b588e1b..02f422061 100644 --- a/src/qdoc/tree.cpp +++ b/src/qdoc/tree.cpp @@ -293,10 +293,17 @@ void Tree::resolveCppToQmlLinks() \\since information from the associated physical or logical module. That is, C++ and QML types inherit the \\since of their module, unless that command is explicitly used in the type documentation. + + In addition, resolve the since information for individual enum + values. */ void Tree::resolveSince(Aggregate &aggregate) { for (auto *child : aggregate.childNodes()) { + // Order matters; resolve since-clauses in enum values + // first as EnumNode is not an Aggregate + if (child->isEnumType()) + resolveEnumValueSince(static_cast<EnumNode&>(*child)); if (!child->isAggregate()) continue; if (!child->since().isEmpty()) @@ -310,6 +317,35 @@ void Tree::resolveSince(Aggregate &aggregate) } /*! + Resolve since information for values of enum node \a en. + + Enum values are not derived from Node, but they can have + 'since' information associated with them. Since-strings + for each enum item are initially stored in the Doc + instance of EnumNode as SinceTag atoms; parse the doc + and store them into each EnumItem. +*/ +void Tree::resolveEnumValueSince(EnumNode &en) +{ + auto findNextAtom = [](const Atom *a, Atom::AtomType t) { + while (a && a->type() != t) + a = a->next(); + return a; + }; + + const QStringList enumItems{en.doc().enumItemNames()}; + const Atom *atom = en.doc().body().firstAtom(); + while ((atom = findNextAtom(atom, Atom::ListTagLeft))) { + if (atom = atom->next(); !atom) + break; + if (auto val = atom->string(); enumItems.contains(val)) { + if (atom = atom->next(); atom && atom->next(Atom::SinceTagLeft)) + en.setSince(val, atom->next()->next()->string()); + } + } +} + +/*! Traverse this Tree and for each ClassNode found, remove from its list of base classes any that are marked private or internal. When a class is removed from a base class diff --git a/src/qdoc/tree.h b/src/qdoc/tree.h index 7905b9fe3..00c65a787 100644 --- a/src/qdoc/tree.h +++ b/src/qdoc/tree.h @@ -109,6 +109,7 @@ private: // The rest of the class is private. void resolveProperties(); void resolveCppToQmlLinks(); void resolveSince(Aggregate &aggregate); + void resolveEnumValueSince(EnumNode &en); void removePrivateAndInternalBases(NamespaceNode *rootNode); NamespaceNode *root() { return &m_root; } [[nodiscard]] const NamespaceNode *root() const { return &m_root; } diff --git a/tests/auto/qdoc/generatedoutput/expected_output/scopedenum-docbook/testqdoc-test.xml b/tests/auto/qdoc/generatedoutput/expected_output/scopedenum-docbook/testqdoc-test.xml index b0b7d13bf..5c3cef465 100644 --- a/tests/auto/qdoc/generatedoutput/expected_output/scopedenum-docbook/testqdoc-test.xml +++ b/tests/auto/qdoc/generatedoutput/expected_output/scopedenum-docbook/testqdoc-test.xml @@ -171,7 +171,7 @@ </db:tr> <db:tr> <db:td> -<db:para><db:code><db:emphasis role="bold"><db:link xlink:href="testqdoc.xml">TestQDoc</db:link></db:emphasis>::<db:emphasis role="bold"><db:link xlink:href="testqdoc-test.xml">Test</db:link></db:emphasis>::<db:emphasis role="bold"><db:link xlink:href="">ScopedEnum</db:link></db:emphasis>::All</db:code></db:para> +<db:para><db:code><db:emphasis role="bold"><db:link xlink:href="testqdoc.xml">TestQDoc</db:link></db:emphasis>::<db:emphasis role="bold"><db:link xlink:href="testqdoc-test.xml">Test</db:link></db:emphasis>::<db:emphasis role="bold"><db:link xlink:href="">ScopedEnum</db:link></db:emphasis>::All (since Qt 2.0)</db:code></db:para> </db:td> <db:td><db:code>This | That</db:code></db:td> <db:td> diff --git a/tests/auto/qdoc/generatedoutput/expected_output/scopedenum/testqdoc-test.html b/tests/auto/qdoc/generatedoutput/expected_output/scopedenum/testqdoc-test.html index 66bb69623..c6f837f78 100644 --- a/tests/auto/qdoc/generatedoutput/expected_output/scopedenum/testqdoc-test.html +++ b/tests/auto/qdoc/generatedoutput/expected_output/scopedenum/testqdoc-test.html @@ -93,7 +93,7 @@ target_link_libraries(mytarget PRIVATE Qt6::QDocTest)</td></tr> <div class="table"><table class="valuelist"><tr valign="top" class="odd"><th class="tblConst">Constant</th><th class="tblval">Value</th><th class="tbldscr">Description</th></tr> <tr><td class="topAlign"><code translate="no">TestQDoc::Test::ScopedEnum::This</code></td><td class="topAlign tblval"><code translate="no">0x01</code></td><td class="topAlign">Something</td></tr> <tr><td class="topAlign"><code translate="no">TestQDoc::Test::ScopedEnum::That</code></td><td class="topAlign tblval"><code translate="no">0x02</code></td><td class="topAlign">Something else</td></tr> -<tr><td class="topAlign"><code translate="no">TestQDoc::Test::ScopedEnum::All</code></td><td class="topAlign tblval"><code translate="no">This | That</code></td><td class="topAlign">Everything</td></tr> +<tr><td class="topAlign"><code translate="no">TestQDoc::Test::ScopedEnum::All (since Qt 2.0)</code></td><td class="topAlign tblval"><code translate="no">This | That</code></td><td class="topAlign">Everything</td></tr> </table></div> <p>A scoped enum.</p> <!-- @@@ScopedEnum --> diff --git a/tests/auto/qdoc/generatedoutput/expected_output/scopedenum/whatsnew.html b/tests/auto/qdoc/generatedoutput/expected_output/scopedenum/whatsnew.html new file mode 100644 index 000000000..6d6989f49 --- /dev/null +++ b/tests/auto/qdoc/generatedoutput/expected_output/scopedenum/whatsnew.html @@ -0,0 +1,39 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="utf-8"> +<!-- scopedenum.qdoc --> + <title>New Classes and Functions | TestCPP</title> +</head> +<body> +<div class="sidebar"><div class="sidebar-content" id="sidebar-content"></div></div> +<h1 class="title">New Classes and Functions</h1> +<!-- $$$whatsnew.html-description --> +<div class="descr" id="details"> +<ul> +<li><a href="#new-namespaces">New Namespaces</a></li> +<li><a href="#new-classes">New Classes</a></li> +<li><a href="#new-enum-values">New Enum Values</a></li> +</ul> +<h3 id="new-namespaces">New Namespaces</h3> +<div class="table"><table class="alignedsummary" translate="no"> +<tr><td class="memItemLeft rightAlign topAlign"> namespace </td><td class="memItemRight bottomAlign"><b><a href="testqdoc.html" translate="no">TestQDoc</a></b></td></tr> +</table></div> +<h3 id="new-classes">New Classes</h3> +<div class="flowListDiv" translate="no"> +<dl class="flowList odd"><dt class="alphaChar"><b>D</b></dt> +<dd><a href="">DontLinkToMe</a></dd> +</dl> +<dl class="flowList even"><dt class="alphaChar"><b>T</b></dt> +<dd><a href="testqdoc-test.html">Test</a> (<a href="testqdoc.html">TestQDoc</a>)</dd> +<dd><a href="testqdoc-testderived.html">TestDerived</a> (<a href="testqdoc.html">TestQDoc</a>)</dd> +</dl> +</div> +<h3 id="new-enum-values">New Enum Values</h3> +<div class="table"><table class="alignedsummary" translate="no"> +<tr><td class="memItemLeft"> enum value </td><td class="memItemRight"><b><a href="testqdoc-test.html#ScopedEnum-enum">ScopedEnum::All</a></b></td></tr> +</table></div> +</div> +<!-- @@@whatsnew.html --> +</body> +</html> diff --git a/tests/auto/qdoc/generatedoutput/testdata/scopedenum/scopedenum.qdoc b/tests/auto/qdoc/generatedoutput/testdata/scopedenum/scopedenum.qdoc index 625252486..775e5f81e 100644 --- a/tests/auto/qdoc/generatedoutput/testdata/scopedenum/scopedenum.qdoc +++ b/tests/auto/qdoc/generatedoutput/testdata/scopedenum/scopedenum.qdoc @@ -17,7 +17,7 @@ \value That Something else \omitvalue OmittedValue \omit Unused - This decription is omitted \endomit - \value All Everything + \value [since 2.0] All Everything \omitvalue VeryLastValue Nothing here \omitvalue UselessValue @@ -34,3 +34,10 @@ TestQDoc::Test::ClassicEnum::Howdy does not link, but TestQDoc::Test::Howdy might. */ + +/*! + \page whatsnew.html + \title New Classes and Functions + + \sincelist 2.0 +*/ diff --git a/tests/auto/qdoc/generatedoutput/tst_generatedoutput.cpp b/tests/auto/qdoc/generatedoutput/tst_generatedoutput.cpp index e8aadeffd..3f280e948 100644 --- a/tests/auto/qdoc/generatedoutput/tst_generatedoutput.cpp +++ b/tests/auto/qdoc/generatedoutput/tst_generatedoutput.cpp @@ -132,12 +132,12 @@ void tst_generatedOutput::compareLineByLine(const QStringList &expectedFiles) QFile expectedFile(expected); if (!expectedFile.open(QIODevice::ReadOnly)) - QFAIL("Cannot open expected data file!"); + QFAIL(qPrintable(QString("Cannot open expected data file: %1").arg(expected))); QTextStream expectedIn(&expectedFile); QFile actualFile(actual); if (!actualFile.open(QIODevice::ReadOnly)) - QFAIL("Cannot open actual data file!"); + QFAIL(qPrintable(QString("Cannot open actual data file: %1").arg(actual))); QTextStream actualIn(&actualFile); const QLatin1String delim(": "); @@ -379,6 +379,7 @@ void tst_generatedOutput::scopedEnum() testAndCompare("testdata/configs/scopedenum.qdocconf", "scopedenum/testqdoc-test.html " "scopedenum/scoped-enum-linking.html " + "scopedenum/whatsnew.html " "scopedenum-docbook/scoped-enum-linking.xml " "scopedenum-docbook/testqdoc-test.xml"); } |