summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTopi Reinio <topi.reinio@qt.io>2022-07-05 21:48:11 +0200
committerTopi Reinio <topi.reinio@qt.io>2022-08-23 23:31:15 +0200
commit9ebd62831f1d3b2c314aebf416ca69f98955af2a (patch)
treee3f66035b904f96d72ade0ede244480c0760fdc2
parentedf871eba1bd47c1616e4ace31ad5c6e60bd9e63 (diff)
qdoc: Store BINDABLE property members into PropertyNode
QDoc already recognized the BINDABLE attribute of Q_PROPERTY but did not store the name of the associated member. Store it in the list of a PropertyNode's access functions. This information will be useful later when deciding on whether to generate a warning for missing member functions; functions that are associated with properties can be left undocumented if the property itself is documented. Add a static helper function PropertyNode that returns the names of property access function roles. This is used when writing the access functions into an .index file. Convert access function-related enums to enum classes. Change-Id: Idd59622a965895883acf3ae297297ba3f3cca20e Reviewed-by: Luca Di Sera <luca.disera@qt.io>
-rw-r--r--src/qdoc/clangcodeparser.cpp11
-rw-r--r--src/qdoc/codemarker.cpp2
-rw-r--r--src/qdoc/docbookgenerator.cpp16
-rw-r--r--src/qdoc/functionnode.h6
-rw-r--r--src/qdoc/generator.cpp14
-rw-r--r--src/qdoc/htmlgenerator.cpp2
-rw-r--r--src/qdoc/propertynode.cpp34
-rw-r--r--src/qdoc/propertynode.h20
-rw-r--r--src/qdoc/qdocindexfiles.cpp45
-rw-r--r--src/qdoc/tree.cpp23
-rw-r--r--src/qdoc/xmlgenerator.cpp2
11 files changed, 88 insertions, 87 deletions
diff --git a/src/qdoc/clangcodeparser.cpp b/src/qdoc/clangcodeparser.cpp
index 4c46b8c53..7a2ea72a7 100644
--- a/src/qdoc/clangcodeparser.cpp
+++ b/src/qdoc/clangcodeparser.cpp
@@ -979,9 +979,9 @@ bool ClangVisitor::parseProperty(const QString &spelling, const Location &loc)
if (i < parts.size()) {
QString value = parts.at(i++);
if (key == "READ") {
- qdb_->addPropertyFunction(property, value, PropertyNode::Getter);
+ qdb_->addPropertyFunction(property, value, PropertyNode::FunctionRole::Getter);
} else if (key == "WRITE") {
- qdb_->addPropertyFunction(property, value, PropertyNode::Setter);
+ qdb_->addPropertyFunction(property, value, PropertyNode::FunctionRole::Setter);
property->setWritable(true);
} else if (key == "STORED") {
property->setStored(value.toLower() == "true");
@@ -995,11 +995,12 @@ bool ClangVisitor::parseProperty(const QString &spelling, const Location &loc)
property->setDesignable(false);
}
} else if (key == "BINDABLE") {
- property->setPropertyType(PropertyNode::Bindable);
+ property->setPropertyType(PropertyNode::PropertyType::BindableProperty);
+ qdb_->addPropertyFunction(property, value, PropertyNode::FunctionRole::Bindable);
} else if (key == "RESET") {
- qdb_->addPropertyFunction(property, value, PropertyNode::Resetter);
+ qdb_->addPropertyFunction(property, value, PropertyNode::FunctionRole::Resetter);
} else if (key == "NOTIFY") {
- qdb_->addPropertyFunction(property, value, PropertyNode::Notifier);
+ qdb_->addPropertyFunction(property, value, PropertyNode::FunctionRole::Notifier);
} else if (key == "SCRIPTABLE") {
QString v = value.toLower();
if (v == "true")
diff --git a/src/qdoc/codemarker.cpp b/src/qdoc/codemarker.cpp
index 9dbc23a6b..48e384f9d 100644
--- a/src/qdoc/codemarker.cpp
+++ b/src/qdoc/codemarker.cpp
@@ -171,7 +171,7 @@ QString CodeMarker::extraSynopsis(const Node *node, Section::Style style)
break;
case Node::Property: {
auto propertyNode = static_cast<const PropertyNode *>(node);
- if (propertyNode->propertyType() == PropertyNode::Bindable)
+ if (propertyNode->propertyType() == PropertyNode::PropertyType::BindableProperty)
extra << "bindable";
if (!propertyNode->isWritable())
extra << "read-only";
diff --git a/src/qdoc/docbookgenerator.cpp b/src/qdoc/docbookgenerator.cpp
index fcc75722e..07721296b 100644
--- a/src/qdoc/docbookgenerator.cpp
+++ b/src/qdoc/docbookgenerator.cpp
@@ -2280,7 +2280,7 @@ void DocBookGenerator::generateBody(const Node *node)
if (fn && !fn->overridesThis().isEmpty())
generateReimplementsClause(fn);
else if (node->isProperty()) {
- if (static_cast<const PropertyNode *>(node)->propertyType() != PropertyNode::Standard)
+ if (static_cast<const PropertyNode *>(node)->propertyType() != PropertyNode::PropertyType::StandardProperty)
generateAddendum(node, BindableProperty, nullptr, false);
}
if (!generateText(node->doc().body(), node)) {
@@ -2955,7 +2955,7 @@ void DocBookGenerator::generateDocBookSynopsis(const Node *node)
if (functionNode->hasAssociatedProperties()) {
QStringList associatedProperties;
- const NodeList &nodes = functionNode->associatedProperties();
+ const auto &nodes = functionNode->associatedProperties();
for (const Node *n : nodes) {
const auto pn = static_cast<const PropertyNode *>(n);
associatedProperties << pn->name();
@@ -3636,7 +3636,7 @@ void DocBookGenerator::generateAddendum(const Node *node, Addendum type, CodeMar
if (!node->isFunction())
return;
const auto *fn = static_cast<const FunctionNode *>(node);
- NodeList nodes = fn->associatedProperties();
+ auto nodes = fn->associatedProperties();
if (nodes.isEmpty())
return;
std::sort(nodes.begin(), nodes.end(), Node::nodeNameLessThan);
@@ -3644,16 +3644,16 @@ void DocBookGenerator::generateAddendum(const Node *node, Addendum type, CodeMar
QString msg;
const auto pn = static_cast<const PropertyNode *>(node);
switch (pn->role(fn)) {
- case PropertyNode::Getter:
+ case PropertyNode::FunctionRole::Getter:
msg = QStringLiteral("Getter function");
break;
- case PropertyNode::Setter:
+ case PropertyNode::FunctionRole::Setter:
msg = QStringLiteral("Setter function");
break;
- case PropertyNode::Resetter:
+ case PropertyNode::FunctionRole::Resetter:
msg = QStringLiteral("Resetter function");
break;
- case PropertyNode::Notifier:
+ case PropertyNode::FunctionRole::Notifier:
msg = QStringLiteral("Notifier signal");
break;
default:
@@ -3745,7 +3745,7 @@ void DocBookGenerator::generateDetailedMember(const Node *node, const PageNode *
if (node->isProperty()) {
const auto property = static_cast<const PropertyNode *>(node);
- if (property->propertyType() == PropertyNode::Standard) {
+ if (property->propertyType() == PropertyNode::PropertyType::StandardProperty) {
Section section(Section::Accessors, Section::Active);
section.appendMembers(property->getters().toVector());
diff --git a/src/qdoc/functionnode.h b/src/qdoc/functionnode.h
index 72b7edaec..0daeacc43 100644
--- a/src/qdoc/functionnode.h
+++ b/src/qdoc/functionnode.h
@@ -114,14 +114,12 @@ public:
bool templateParams = false) const override;
[[nodiscard]] const QString &overridesThis() const { return m_overridesThis; }
- [[nodiscard]] const NodeList &associatedProperties() const { return m_associatedProperties; }
+ [[nodiscard]] const QList<PropertyNode *> &associatedProperties() const { return m_associatedProperties; }
[[nodiscard]] bool hasAssociatedProperties() const { return !m_associatedProperties.isEmpty(); }
[[nodiscard]] bool hasOneAssociatedProperty() const
{
return (m_associatedProperties.size() == 1);
}
- [[nodiscard]] Node *firstAssociatedProperty() const { return m_associatedProperties[0]; }
-
[[nodiscard]] QString element() const override { return parent()->name(); }
[[nodiscard]] bool isAttached() const override { return m_attached; }
[[nodiscard]] bool isQtQuickNode() const override { return parent()->isQtQuickNode(); }
@@ -196,7 +194,7 @@ private:
QStringList m_parentPath {};
QString m_overridesThis {};
QString m_tag {};
- NodeList m_associatedProperties {};
+ QList<PropertyNode *> m_associatedProperties {};
Parameters m_parameters {};
};
diff --git a/src/qdoc/generator.cpp b/src/qdoc/generator.cpp
index 726ca313f..b6b2d6935 100644
--- a/src/qdoc/generator.cpp
+++ b/src/qdoc/generator.cpp
@@ -549,7 +549,7 @@ QString Generator::fullDocumentLocation(const Node *node, bool useSubdir)
if (fn->isDtor())
anchorRef = "#dtor." + fn->name().mid(1);
else if (fn->hasOneAssociatedProperty() && fn->doc().isEmpty())
- return fullDocumentLocation(fn->firstAssociatedProperty());
+ return fullDocumentLocation(fn->associatedProperties()[0]);
else if (fn->overloadNumber() > 0)
anchorRef = QLatin1Char('#') + cleanRef(fn->name()) + QLatin1Char('-')
+ QString::number(fn->overloadNumber());
@@ -749,7 +749,7 @@ void Generator::generateBody(const Node *node, CodeMarker *marker)
if (fn && !fn->overridesThis().isEmpty())
generateReimplementsClause(fn, marker);
else if (node->isProperty()) {
- if (static_cast<const PropertyNode *>(node)->propertyType() != PropertyNode::Standard)
+ if (static_cast<const PropertyNode *>(node)->propertyType() != PropertyNode::PropertyType::StandardProperty)
generateAddendum(node, BindableProperty, marker);
}
@@ -1299,7 +1299,7 @@ void Generator::generateAddendum(const Node *node, Addendum type, CodeMarker *ma
if (!node->isFunction())
return;
const auto *fn = static_cast<const FunctionNode *>(node);
- NodeList nodes = fn->associatedProperties();
+ auto nodes = fn->associatedProperties();
if (nodes.isEmpty())
return;
std::sort(nodes.begin(), nodes.end(), Node::nodeNameLessThan);
@@ -1307,16 +1307,16 @@ void Generator::generateAddendum(const Node *node, Addendum type, CodeMarker *ma
QString msg;
const auto *pn = static_cast<const PropertyNode *>(n);
switch (pn->role(fn)) {
- case PropertyNode::Getter:
+ case PropertyNode::FunctionRole::Getter:
msg = QStringLiteral("Getter function");
break;
- case PropertyNode::Setter:
+ case PropertyNode::FunctionRole::Setter:
msg = QStringLiteral("Setter function");
break;
- case PropertyNode::Resetter:
+ case PropertyNode::FunctionRole::Resetter:
msg = QStringLiteral("Resetter function");
break;
- case PropertyNode::Notifier:
+ case PropertyNode::FunctionRole::Notifier:
msg = QStringLiteral("Notifier signal");
break;
default:
diff --git a/src/qdoc/htmlgenerator.cpp b/src/qdoc/htmlgenerator.cpp
index 4772a589b..d5edaa0d2 100644
--- a/src/qdoc/htmlgenerator.cpp
+++ b/src/qdoc/htmlgenerator.cpp
@@ -3502,7 +3502,7 @@ void HtmlGenerator::generateDetailedMember(const Node *node, const PageNode *rel
if (node->isProperty()) {
const auto property = static_cast<const PropertyNode *>(node);
- if (property->propertyType() == PropertyNode::Standard) {
+ if (property->propertyType() == PropertyNode::PropertyType::StandardProperty) {
Section section(Section::Accessors, Section::Active);
section.appendMembers(property->getters().toVector());
diff --git a/src/qdoc/propertynode.cpp b/src/qdoc/propertynode.cpp
index 4b1cb3daf..f355608aa 100644
--- a/src/qdoc/propertynode.cpp
+++ b/src/qdoc/propertynode.cpp
@@ -22,6 +22,29 @@ PropertyNode::PropertyNode(Aggregate *parent, const QString &name) : Node(Proper
// nothing
}
+
+/*!
+ Returns a string representing an access function \a role.
+*/
+QString PropertyNode::roleName(FunctionRole role)
+{
+ switch (role) {
+ case FunctionRole::Getter:
+ return "getter";
+ case FunctionRole::Setter:
+ return "setter";
+ case FunctionRole::Resetter:
+ return "resetter";
+ case FunctionRole::Notifier:
+ return "notifier";
+ case FunctionRole::Bindable:
+ return "bindable";
+ default:
+ break;
+ }
+ return QString();
+}
+
/*!
Sets this property's \e {overridden from} property to
\a baseProperty, which indicates that this property
@@ -34,7 +57,7 @@ PropertyNode::PropertyNode(Aggregate *parent, const QString &name) : Node(Proper
*/
void PropertyNode::setOverriddenFrom(const PropertyNode *baseProperty)
{
- for (int i = 0; i < NumFunctionRoles; ++i) {
+ for (qsizetype i{0}; i < (qsizetype)FunctionRole::NumFunctionRoles; ++i) {
if (m_functions[i].isEmpty())
m_functions[i] = baseProperty->m_functions[i];
}
@@ -58,7 +81,7 @@ void PropertyNode::setOverriddenFrom(const PropertyNode *baseProperty)
*/
QString PropertyNode::qualifiedDataType() const
{
- if (m_propertyType != Standard || m_type.startsWith(QLatin1String("const ")))
+ if (m_propertyType != PropertyType::StandardProperty || m_type.startsWith(QLatin1String("const ")))
return m_type;
if (setters().isEmpty() && resetters().isEmpty()) {
@@ -102,16 +125,15 @@ bool PropertyNode::hasAccessFunction(const QString &name) const
}
/*!
- Returns true if function \a functionNode has role \a r for this
- property.
+ Returns the role of \a functionNode for this property.
*/
PropertyNode::FunctionRole PropertyNode::role(const FunctionNode *functionNode) const
{
- for (int i = 0; i < 4; i++) {
+ for (qsizetype i{0}; i < (qsizetype)FunctionRole::NumFunctionRoles; i++) {
if (m_functions[i].contains(const_cast<FunctionNode *>(functionNode)))
return (FunctionRole)i;
}
- return Notifier;
+ return FunctionRole::Notifier; // TODO: Figure out a better way to handle 'not found'.
}
QT_END_NAMESPACE
diff --git a/src/qdoc/propertynode.h b/src/qdoc/propertynode.h
index 4a077075c..b0a13d8d8 100644
--- a/src/qdoc/propertynode.h
+++ b/src/qdoc/propertynode.h
@@ -17,9 +17,9 @@ class Aggregate;
class PropertyNode : public Node
{
public:
- enum PropertyType { Standard, Bindable };
- enum FunctionRole { Getter, Setter, Resetter, Notifier };
- enum { NumFunctionRoles = Notifier + 1 };
+ enum class PropertyType { StandardProperty, BindableProperty };
+ enum class FunctionRole { Getter, Setter, Resetter, Notifier, Bindable, NumFunctionRoles };
+ static QString roleName(FunctionRole role);
PropertyNode(Aggregate *parent, const QString &name);
@@ -42,10 +42,10 @@ public:
{
return m_functions[(int)role];
}
- [[nodiscard]] const NodeList &getters() const { return functions(Getter); }
- [[nodiscard]] const NodeList &setters() const { return functions(Setter); }
- [[nodiscard]] const NodeList &resetters() const { return functions(Resetter); }
- [[nodiscard]] const NodeList &notifiers() const { return functions(Notifier); }
+ [[nodiscard]] const NodeList &getters() const { return functions(FunctionRole::Getter); }
+ [[nodiscard]] const NodeList &setters() const { return functions(FunctionRole::Setter); }
+ [[nodiscard]] const NodeList &resetters() const { return functions(FunctionRole::Resetter); }
+ [[nodiscard]] const NodeList &notifiers() const { return functions(FunctionRole::Notifier); }
[[nodiscard]] bool hasAccessFunction(const QString &name) const;
FunctionRole role(const FunctionNode *functionNode) const;
[[nodiscard]] bool isStored() const { return fromFlagValue(m_stored, storedDefault()); }
@@ -61,8 +61,8 @@ public:
private:
QString m_type {};
- PropertyType m_propertyType { Standard };
- NodeList m_functions[NumFunctionRoles] {};
+ PropertyType m_propertyType { PropertyType::StandardProperty };
+ NodeList m_functions[(qsizetype)FunctionRole::NumFunctionRoles] {};
FlagValue m_stored { FlagValueDefault };
FlagValue m_designable { FlagValueDefault };
FlagValue m_scriptable { FlagValueDefault };
@@ -88,7 +88,7 @@ inline void PropertyNode::addSignal(FunctionNode *function, FunctionRole role)
inline NodeList PropertyNode::functions() const
{
NodeList list;
- for (int i = 0; i < NumFunctionRoles; ++i)
+ for (qsizetype i{0}; i < (qsizetype)FunctionRole::NumFunctionRoles; ++i)
list += m_functions[i];
return list;
}
diff --git a/src/qdoc/qdocindexfiles.cpp b/src/qdoc/qdocindexfiles.cpp
index 3d899ffcc..cca624db8 100644
--- a/src/qdoc/qdocindexfiles.cpp
+++ b/src/qdoc/qdocindexfiles.cpp
@@ -466,7 +466,7 @@ void QDocIndexFiles::readIndexSection(QXmlStreamReader &reader, Node *current,
auto *propNode = new PropertyNode(parent, name);
node = propNode;
if (attributes.value(QLatin1String("bindable")) == QLatin1String("true"))
- propNode->setPropertyType(PropertyNode::Bindable);
+ propNode->setPropertyType(PropertyNode::PropertyType::BindableProperty);
if (!indexUrl.isEmpty())
location = Location(indexUrl + QLatin1Char('/') + parent->name().toLower() + ".html");
@@ -1107,45 +1107,18 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter &writer, Node *node,
case Node::Property: {
const auto *propertyNode = static_cast<const PropertyNode *>(node);
- if (propertyNode->propertyType() == PropertyNode::Bindable)
+ if (propertyNode->propertyType() == PropertyNode::PropertyType::BindableProperty)
writer.writeAttribute("bindable", "true");
if (!brief.isEmpty())
writer.writeAttribute("brief", brief);
- const auto &getters = propertyNode->getters();
- for (const auto *fnNode : getters) {
- if (fnNode) {
- const auto *functionNode = static_cast<const FunctionNode *>(fnNode);
- writer.writeStartElement("getter");
- writer.writeAttribute("name", functionNode->name());
- writer.writeEndElement(); // getter
- }
- }
- const auto &setters = propertyNode->setters();
- for (const auto *fnNode : setters) {
- if (fnNode) {
- const auto *functionNode = static_cast<const FunctionNode *>(fnNode);
- writer.writeStartElement("setter");
- writer.writeAttribute("name", functionNode->name());
- writer.writeEndElement(); // setter
- }
- }
- const auto &resetters = propertyNode->resetters();
- for (const auto *fnNode : resetters) {
- if (fnNode) {
- const auto *functionNode = static_cast<const FunctionNode *>(fnNode);
- writer.writeStartElement("resetter");
- writer.writeAttribute("name", functionNode->name());
- writer.writeEndElement(); // resetter
- }
- }
- const auto &notifiers = propertyNode->notifiers();
- for (const auto *fnNode : notifiers) {
- if (fnNode) {
- const auto *functionNode = static_cast<const FunctionNode *>(fnNode);
- writer.writeStartElement("notifier");
- writer.writeAttribute("name", functionNode->name());
- writer.writeEndElement(); // notifier
+ // Property access function names
+ for (qsizetype i{0}; i < (qsizetype)PropertyNode::FunctionRole::NumFunctionRoles; ++i) {
+ auto role{(PropertyNode::FunctionRole)i};
+ for (const auto *fnNode : propertyNode->functions(role)) {
+ writer.writeStartElement(PropertyNode::roleName(role));
+ writer.writeAttribute("name", fnNode->name());
+ writer.writeEndElement();
}
}
} break;
diff --git a/src/qdoc/tree.cpp b/src/qdoc/tree.cpp
index ae27ba175..ee0dc5e01 100644
--- a/src/qdoc/tree.cpp
+++ b/src/qdoc/tree.cpp
@@ -222,6 +222,10 @@ void Tree::resolvePropertyOverriddenFromPtrs(Aggregate *n)
}
/*!
+ Resolves access functions associated with each PropertyNode stored
+ in \c m_unresolvedPropertyMap, and adds them into the property node.
+ This allows the property node to list the access functions when
+ generating their documentation.
*/
void Tree::resolveProperties()
{
@@ -229,10 +233,11 @@ void Tree::resolveProperties()
propEntry != m_unresolvedPropertyMap.constEnd(); ++propEntry) {
PropertyNode *property = propEntry.key();
Aggregate *parent = property->parent();
- QString getterName = (*propEntry)[PropertyNode::Getter];
- QString setterName = (*propEntry)[PropertyNode::Setter];
- QString resetterName = (*propEntry)[PropertyNode::Resetter];
- QString notifierName = (*propEntry)[PropertyNode::Notifier];
+ QString getterName = (*propEntry)[PropertyNode::FunctionRole::Getter];
+ QString setterName = (*propEntry)[PropertyNode::FunctionRole::Setter];
+ QString resetterName = (*propEntry)[PropertyNode::FunctionRole::Resetter];
+ QString notifierName = (*propEntry)[PropertyNode::FunctionRole::Notifier];
+ QString bindableName = (*propEntry)[PropertyNode::FunctionRole::Bindable];
for (auto it = parent->constBegin(); it != parent->constEnd(); ++it) {
if ((*it)->isFunction()) {
@@ -240,13 +245,15 @@ void Tree::resolveProperties()
if (function->access() == property->access()
&& (function->status() == property->status() || function->doc().isEmpty())) {
if (function->name() == getterName) {
- property->addFunction(function, PropertyNode::Getter);
+ property->addFunction(function, PropertyNode::FunctionRole::Getter);
} else if (function->name() == setterName) {
- property->addFunction(function, PropertyNode::Setter);
+ property->addFunction(function, PropertyNode::FunctionRole::Setter);
} else if (function->name() == resetterName) {
- property->addFunction(function, PropertyNode::Resetter);
+ property->addFunction(function, PropertyNode::FunctionRole::Resetter);
} else if (function->name() == notifierName) {
- property->addSignal(function, PropertyNode::Notifier);
+ property->addSignal(function, PropertyNode::FunctionRole::Notifier);
+ } else if (function->name() == bindableName) {
+ property->addFunction(function, PropertyNode::FunctionRole::Bindable);
}
}
}
diff --git a/src/qdoc/xmlgenerator.cpp b/src/qdoc/xmlgenerator.cpp
index b3792a010..2ed23d549 100644
--- a/src/qdoc/xmlgenerator.cpp
+++ b/src/qdoc/xmlgenerator.cpp
@@ -265,7 +265,7 @@ QString XmlGenerator::refForNode(const Node *node)
break;
default:
if (fn->hasOneAssociatedProperty() && fn->doc().isEmpty()) {
- return refForNode(fn->firstAssociatedProperty());
+ return refForNode(fn->associatedProperties()[0]);
} else {
ref = fn->name();
if (fn->overloadNumber() != 0)