From 4a0503bd8cf8a7fb08e933c4e52f9122057aabd6 Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Fri, 23 Apr 2021 13:33:58 +0200 Subject: qdoc: Fix linking to scoped enums The code that resolved qualified names of enum values did not expect the name of the enum to appear in the path, as is the case for enum classes. Fixes: QTBUG-92355 Change-Id: I74246158f7c5ca7c5c1712bc642905bc267cb7e1 Reviewed-by: Paul Wicking (cherry picked from commit ce05219da0750a3be429b396ea0d13980aa14d70) Reviewed-by: Qt Cherry-pick Bot --- src/qdoc/tree.cpp | 71 +++++++++++++++------- src/qdoc/tree.h | 1 + .../scopedenum-docbook/scoped-enum-linking.xml | 12 ++++ .../scopedenum-docbook/testqdoc-test.xml | 46 ++++++++++++++ .../scopedenum/scoped-enum-linking.html | 19 ++++++ .../expected_output/scopedenum/testqdoc-test.html | 10 +++ .../testdata/configs/scopedenum.qdocconf | 2 - .../testdata/scopedenum/scopedenum.qdoc | 19 ++++++ .../generatedoutput/testdata/testcpp/testcpp.h | 2 + .../qdoc/generatedoutput/tst_generatedoutput.cpp | 2 + 10 files changed, 159 insertions(+), 25 deletions(-) create mode 100644 tests/auto/qdoc/generatedoutput/expected_output/scopedenum-docbook/scoped-enum-linking.xml create mode 100644 tests/auto/qdoc/generatedoutput/expected_output/scopedenum/scoped-enum-linking.html diff --git a/src/qdoc/tree.cpp b/src/qdoc/tree.cpp index 9d220d9d7..775c4326a 100644 --- a/src/qdoc/tree.cpp +++ b/src/qdoc/tree.cpp @@ -594,21 +594,20 @@ const Node *Tree::matchPathAndTarget(const QStringList &path, int idx, const QSt if (node->isAggregate()) { NodeVector nodes; static_cast(node)->findChildren(name, nodes); - for (const auto *node : qAsConst(nodes)) { - if (genus != Node::DontCare && !(genus & node->genus())) + for (const auto *child : qAsConst(nodes)) { + if (genus != Node::DontCare && !(genus & child->genus())) continue; - const Node *t = matchPathAndTarget(path, idx + 1, target, node, flags, genus, ref); + const Node *t = matchPathAndTarget(path, idx + 1, target, child, flags, genus, ref); if (t && !t->isPrivate()) return t; } } - if (target.isEmpty()) { - if ((idx) == (path.size() - 1) && node->isAggregate() && (flags & SearchEnumValues)) { - const Node *t = - static_cast(node)->findEnumNodeForValue(path.at(idx)); - if (t) - return t; - } + if (target.isEmpty() && (flags & SearchEnumValues)) { + const auto *enumNode = node->isAggregate() ? + findEnumNode(nullptr, node, path, idx) : + findEnumNode(node, nullptr, path, idx); + if (enumNode) + return enumNode; } if (((genus == Node::CPP) || (genus == Node::DontCare)) && node->isClassNode() && (flags & SearchBaseClasses)) { @@ -617,12 +616,9 @@ const Node *Tree::matchPathAndTarget(const QStringList &path, int idx, const QSt const Node *t = matchPathAndTarget(path, idx, target, base, flags, genus, ref); if (t && !t->isPrivate()) return t; - if (target.isEmpty()) { - if ((idx) == (path.size() - 1) && (flags & SearchEnumValues)) { - t = base->findEnumNodeForValue(path.at(idx)); - if (t) - return t; - } + if (target.isEmpty() && (flags & SearchEnumValues)) { + if ((t = findEnumNode(base->findChildNode(path.at(idx), genus, flags), base, path, idx))) + return t; } } } @@ -677,17 +673,22 @@ const Node *Tree::findNode(const QStringList &path, const Node *start, int flags const Node *next = static_cast(node)->findChildNode(path.at(i), genus, tmpFlags); - if ((next == nullptr) && (flags & SearchEnumValues) && i == path.size() - 1) { - next = static_cast(node)->findEnumNodeForValue(path.at(i)); - } - if ((next == nullptr) && ((genus == Node::CPP) || (genus == Node::DontCare)) + const Node *enumNode = (flags & SearchEnumValues) ? + findEnumNode(next, node, path, i) : nullptr; + + if (enumNode) + return enumNode; + + + if (!next && ((genus == Node::CPP) || (genus == Node::DontCare)) && node->isClassNode() && (flags & SearchBaseClasses)) { const ClassList bases = allBaseClasses(static_cast(node)); for (const auto *base : bases) { next = base->findChildNode(path.at(i), genus, tmpFlags); - if ((next == nullptr) && (flags & SearchEnumValues) && i == path.size() - 1) - next = base->findEnumNodeForValue(path.at(i)); - if (next != nullptr) + if (flags & SearchEnumValues) + if ((enumNode = findEnumNode(next, base, path, i))) + return enumNode; + if (next) break; } } @@ -701,6 +702,30 @@ const Node *Tree::findNode(const QStringList &path, const Node *start, int flags return nullptr; } + +/*! + \internal + + Helper function to return an enum that matches the \a path at a specified \a offset. + If \a node is a valid enum node, the enum name is assumed to be included in the path + (i.e, a scoped enum). Otherwise, query the \a aggregate (typically, the class node) + for enum node that includes the value at the last position in \a path. + */ +const Node *Tree::findEnumNode(const Node *node, const Node *aggregate, const QStringList &path, int offset) const +{ + // Scoped enum (path ends in enum_name :: enum_value) + if (node && node->isEnumType() && offset == path.size() - 1) { + const auto *en = static_cast(node); + if (en->isScoped() && en->hasItem(path.last())) + return en; + } + + // Standard enum (path ends in class_name :: enum_value) + return (!node && aggregate && offset == path.size() - 1) ? + static_cast(aggregate)->findEnumNodeForValue(path.last()) : + nullptr; +} + /*! This function searches for a node with a canonical title constructed from \a target. If the node it finds is \a node, diff --git a/src/qdoc/tree.h b/src/qdoc/tree.h index 0a2352903..97949314c 100644 --- a/src/qdoc/tree.h +++ b/src/qdoc/tree.h @@ -143,6 +143,7 @@ private: // The rest of the class is private. Node *findNodeByNameAndType(const QStringList &path, bool (Node::*isMatch)() const) const; Aggregate *findRelatesNode(const QStringList &path); + const Node *findEnumNode(const Node *node, const Node *aggregate, const QStringList &path, int offset) const; QString getRef(const QString &target, const Node *node) const; void insertTarget(const QString &name, const QString &title, TargetRec::TargetType type, Node *node, int priority); diff --git a/tests/auto/qdoc/generatedoutput/expected_output/scopedenum-docbook/scoped-enum-linking.xml b/tests/auto/qdoc/generatedoutput/expected_output/scopedenum-docbook/scoped-enum-linking.xml new file mode 100644 index 000000000..f5c4a05cd --- /dev/null +++ b/tests/auto/qdoc/generatedoutput/expected_output/scopedenum-docbook/scoped-enum-linking.xml @@ -0,0 +1,12 @@ + + + +Enum Linking +TestCPP +TestCPP Reference Documentation + +TestCPP Reference Documentation. + +Linking to All. +TestQDoc::Test::ClassicEnum::Howdy does not link, but TestQDoc::Test::Howdy might. + 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 9db4ebb75..f7cee4513 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 @@ -41,6 +41,52 @@ Member Type Documentation + +Test::enum ClassicEnum + +ClassicEnum +public +active +unspecified +TestCPP + + + + + + + + +Constant +Description + + + + +TestQDoc::Test::Yee + +0 + + + +TestQDoc::Test::Haw + +1 + + + +TestQDoc::Test::Howdy + +2 + + + +TestQDoc::Test::Partner + +3 + + + Test::enum ScopedEnum diff --git a/tests/auto/qdoc/generatedoutput/expected_output/scopedenum/scoped-enum-linking.html b/tests/auto/qdoc/generatedoutput/expected_output/scopedenum/scoped-enum-linking.html new file mode 100644 index 000000000..f07306f1e --- /dev/null +++ b/tests/auto/qdoc/generatedoutput/expected_output/scopedenum/scoped-enum-linking.html @@ -0,0 +1,19 @@ + + + + + + Enum Linking | TestCPP + + + +

Enum Linking

+ + +
+

Linking to All.

+

TestQDoc::Test::ClassicEnum::Howdy does not link, but TestQDoc::Test::Howdy might.

+
+ + + 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 6f2e048aa..69dd5eb15 100644 --- a/tests/auto/qdoc/generatedoutput/expected_output/scopedenum/testqdoc-test.html +++ b/tests/auto/qdoc/generatedoutput/expected_output/scopedenum/testqdoc-test.html @@ -36,6 +36,7 @@ target_link_libraries(mytarget PRIVATE Qt6::QDocTest)

Public Types

+
enum ClassicEnum { Yee, Haw, Howdy, Partner }
enum class ScopedEnum { This, That, All }
SomeType
@@ -74,6 +75,15 @@ target_link_libraries(mytarget PRIVATE Qt6::QDocTest)

Member Type Documentation

+ +

enum Test::ClassicEnum

+
+ + + + +
ConstantValue
TestQDoc::Test::Yee0
TestQDoc::Test::Haw1
TestQDoc::Test::Howdy2
TestQDoc::Test::Partner3
+

enum class Test::ScopedEnum

diff --git a/tests/auto/qdoc/generatedoutput/testdata/configs/scopedenum.qdocconf b/tests/auto/qdoc/generatedoutput/testdata/configs/scopedenum.qdocconf index 0c1501213..d142e07fe 100644 --- a/tests/auto/qdoc/generatedoutput/testdata/configs/scopedenum.qdocconf +++ b/tests/auto/qdoc/generatedoutput/testdata/configs/scopedenum.qdocconf @@ -9,5 +9,3 @@ outputformats = HTML DocBook {HTML.nosubdirs,DocBook.nosubdirs} = true HTML.outputsubdir = scopedenum DocBook.outputsubdir = scopedenum-docbook - -warninglimit += 2 diff --git a/tests/auto/qdoc/generatedoutput/testdata/scopedenum/scopedenum.qdoc b/tests/auto/qdoc/generatedoutput/testdata/scopedenum/scopedenum.qdoc index 4262c1ce6..fdef9dd18 100644 --- a/tests/auto/qdoc/generatedoutput/testdata/scopedenum/scopedenum.qdoc +++ b/tests/auto/qdoc/generatedoutput/testdata/scopedenum/scopedenum.qdoc @@ -25,6 +25,15 @@ ** ****************************************************************************/ +/*! + \enum TestQDoc::Test::ClassicEnum + + \value Yee + \value Haw + \value Howdy + \value Partner +*/ + /*! \enum TestQDoc::Test::ScopedEnum @@ -33,3 +42,13 @@ \value All Everything \omitvalue OmittedValue */ + +/*! + \page scoped-enum-linking.html + \title Enum Linking + + Linking to \l {TestQDoc::Test::ScopedEnum::}{All}. + + TestQDoc::Test::ClassicEnum::Howdy does not link, + but TestQDoc::Test::Howdy might. +*/ diff --git a/tests/auto/qdoc/generatedoutput/testdata/testcpp/testcpp.h b/tests/auto/qdoc/generatedoutput/testdata/testcpp/testcpp.h index af2165d07..5fb323eed 100644 --- a/tests/auto/qdoc/generatedoutput/testdata/testcpp/testcpp.h +++ b/tests/auto/qdoc/generatedoutput/testdata/testcpp/testcpp.h @@ -48,6 +48,8 @@ using Specialized = Struct; #endif #ifdef test_scopedenum + enum ClassicEnum { Yee, Haw, Howdy, Partner }; + enum class ScopedEnum : unsigned char { This = 0x01, That = 0x02, diff --git a/tests/auto/qdoc/generatedoutput/tst_generatedoutput.cpp b/tests/auto/qdoc/generatedoutput/tst_generatedoutput.cpp index 31885fec2..9bfe6ed35 100644 --- a/tests/auto/qdoc/generatedoutput/tst_generatedoutput.cpp +++ b/tests/auto/qdoc/generatedoutput/tst_generatedoutput.cpp @@ -379,6 +379,8 @@ void tst_generatedOutput::scopedEnum() { testAndCompare("testdata/configs/scopedenum.qdocconf", "scopedenum/testqdoc-test.html " + "scopedenum/scoped-enum-linking.html " + "scopedenum-docbook/scoped-enum-linking.xml " "scopedenum-docbook/testqdoc-test.xml"); } -- cgit v1.2.1
ConstantValueDescription