From b1addf36c19748a29bd9f901579a23355b081fe9 Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Wed, 11 Apr 2012 12:50:22 +0200 Subject: [PATCH] qdoc: Fixed to report read-only QML properties correctly Now the default for a QML property is writable. If qdoc can't detect the actual read-only status, writable is assumed. There were some cases where qdoc could not determine the actual read-only/writable status for a QML property. In these cases, qdoc reported read-only because the default was read-only, which was not optimal. Change-Id: I55aeb2bedcde92a414f4d48a8d995e5e9dbca5da Reviewed-by: Casper van Donderen --- src/tools/qdoc/cppcodemarker.cpp | 14 +++- src/tools/qdoc/cppcodeparser.cpp | 16 ++-- src/tools/qdoc/ditaxmlgenerator.cpp | 30 +++---- src/tools/qdoc/generator.cpp | 2 + src/tools/qdoc/htmlgenerator.cpp | 37 +++------ src/tools/qdoc/node.cpp | 154 ++++++++++++++++-------------------- src/tools/qdoc/node.h | 80 +++++++++---------- 7 files changed, 154 insertions(+), 179 deletions(-) diff --git a/src/tools/qdoc/cppcodemarker.cpp b/src/tools/qdoc/cppcodemarker.cpp index aea8ed2..165a235 100644 --- a/src/tools/qdoc/cppcodemarker.cpp +++ b/src/tools/qdoc/cppcodemarker.cpp @@ -1258,8 +1258,20 @@ QList
CppCodeMarker::qmlSections(const QmlClassNode* qmlClassNode, NodeList::ConstIterator c = qcn->childNodes().begin(); while (c != qcn->childNodes().end()) { if ((*c)->subType() == Node::QmlPropertyGroup) { + bool attached = false; const QmlPropGroupNode* pgn = static_cast(*c); - if (pgn->isAttached()) + NodeList::ConstIterator C = pgn->childNodes().begin(); + while (C != pgn->childNodes().end()) { + if ((*C)->type() == Node::QmlProperty) { + const QmlPropertyNode* pn = static_cast(*C); + if (pn->isAttached()) { + attached = true; + break; + } + } + ++C; + } + if (attached) insert(qmlattachedproperties,*c,style,Okay); else insert(qmlproperties,*c,style,Okay); diff --git a/src/tools/qdoc/cppcodeparser.cpp b/src/tools/qdoc/cppcodeparser.cpp index b08c6f9..d0822fe 100644 --- a/src/tools/qdoc/cppcodeparser.cpp +++ b/src/tools/qdoc/cppcodeparser.cpp @@ -937,7 +937,7 @@ Node *CppCodeParser::processTopicCommandGroup(const Doc& doc, if (splitQmlPropertyArg(doc,(*arg),type,module,element,property)) { QmlClassNode* qmlClass = tree_->findQmlClassNode(module,element); if (qmlClass) { - qmlPropGroup = new QmlPropGroupNode(qmlClass,property,attached); + qmlPropGroup = new QmlPropGroupNode(qmlClass,property); //,attached); } } if (qmlPropGroup) { @@ -950,7 +950,7 @@ Node *CppCodeParser::processTopicCommandGroup(const Doc& doc, } if (correspondingProperty) { bool writableList = type.startsWith("list") && correspondingProperty->dataType().endsWith('*'); - qmlPropNode->setWritable(writableList || correspondingProperty->isWritable()); + qmlPropNode->setReadOnly(!(writableList || correspondingProperty->isWritable())); } ++arg; while (arg != args.end()) { @@ -961,7 +961,7 @@ Node *CppCodeParser::processTopicCommandGroup(const Doc& doc, attached); if (correspondingProperty) { bool writableList = type.startsWith("list") && correspondingProperty->dataType().endsWith('*'); - qmlPropNode->setWritable(writableList || correspondingProperty->isWritable()); + qmlPropNode->setReadOnly(!(writableList || correspondingProperty->isWritable())); } } ++arg; @@ -1117,7 +1117,14 @@ void CppCodeParser::processOtherMetaCommand(const Doc& doc, } else if (node->type() == Node::Fake && node->subType() == Node::QmlPropertyGroup) { QmlPropGroupNode* qpgn = static_cast(node); - qpgn->setDefault(); + NodeList::ConstIterator p = qpgn->childNodes().begin(); + while (p != qpgn->childNodes().end()) { + if ((*p)->type() == Node::QmlProperty) { + QmlPropertyNode* qpn = static_cast(*p); + qpn->setDefault(); + } + ++p; + } } } else if (command == COMMAND_QMLREADONLY) { @@ -1127,7 +1134,6 @@ void CppCodeParser::processOtherMetaCommand(const Doc& doc, } else if (node->type() == Node::Fake && node->subType() == Node::QmlPropertyGroup) { QmlPropGroupNode* qpgn = static_cast(node); - qpgn->setReadOnly(1); NodeList::ConstIterator p = qpgn->childNodes().begin(); while (p != qpgn->childNodes().end()) { if ((*p)->type() == Node::QmlProperty) { diff --git a/src/tools/qdoc/ditaxmlgenerator.cpp b/src/tools/qdoc/ditaxmlgenerator.cpp index 3f1e8c0..88a5888 100644 --- a/src/tools/qdoc/ditaxmlgenerator.cpp +++ b/src/tools/qdoc/ditaxmlgenerator.cpp @@ -4420,14 +4420,11 @@ void DitaXmlGenerator::generateDetailedQmlMember(Node* node, writeStartTag(DT_li); writeGuidAttribute((Node*)qpn); QString attr; - int ro = qpn->getReadOnly(); - if (ro < 0) { - if (!qpn->isWritable(tree_)) - attr = "read-only"; - } - else if (ro > 0) + if (!qpn->isReadOnlySet()) + qpn->setReadOnly(!qpn->isWritable(tree_)); + if (qpn->isReadOnly()) attr = "read-only"; - if (qpgn->isDefault()) { + if (qpn->isDefault()) { if (!attr.isEmpty()) attr += QLatin1Char(' '); attr += "default"; @@ -4462,13 +4459,11 @@ void DitaXmlGenerator::generateDetailedQmlMember(Node* node, writeStartTag(DT_li); writeGuidAttribute((Node*)qpn); QString attr; - int ro = qpn->getReadOnly(); - if (ro < 0) { - const ClassNode* cn = qpn->declarativeCppNode(); - if (cn && !qpn->isWritable(tree_)) - attr = "read-only"; + if (!qpn->isReadOnlySet()) { + if (qpn->declarativeCppNode()) + qpn->setReadOnly(!qpn->isWritable(tree_)); } - else if (ro > 0) + if (qpn->isReadOnly()) attr = "read-only"; if (qpn->isDefault()) { if (!attr.isEmpty()) @@ -4495,12 +4490,9 @@ void DitaXmlGenerator::generateDetailedQmlMember(Node* node, writeStartTag(DT_li); writeGuidAttribute((Node*)q); QString attr; - int ro = qpn->getReadOnly(); - if (ro < 0) { - if (!qpn->isWritable(tree_)) - attr = "read-only"; - } - else if (ro > 0) + if (!qpn->isReadOnlySet()) + qpn->setReadOnly(!qpn->isWritable(tree_)); + if (qpn->isReadOnly()) attr = "read-only"; if (qpn->isDefault()) { if (!attr.isEmpty()) diff --git a/src/tools/qdoc/generator.cpp b/src/tools/qdoc/generator.cpp index 8cda8b7..4258bc6 100644 --- a/src/tools/qdoc/generator.cpp +++ b/src/tools/qdoc/generator.cpp @@ -611,6 +611,8 @@ void Generator::generateBody(const Node *node, CodeMarker *marker) node->doc().location().warning( tr("No such enum item '%1' in %2").arg(*a).arg(marker->plainFullName(node)), details); + if (*a == "Void") + qDebug() << "VOID:" << node->name() << definedItems; } else if (!documentedItems.contains(*a)) { node->doc().location().warning( diff --git a/src/tools/qdoc/htmlgenerator.cpp b/src/tools/qdoc/htmlgenerator.cpp index 9434ced..8a54d63 100644 --- a/src/tools/qdoc/htmlgenerator.cpp +++ b/src/tools/qdoc/htmlgenerator.cpp @@ -4072,16 +4072,11 @@ void HtmlGenerator::generateDetailedQmlMember(Node *node, out() << "

"; out() << ""; - int ro = qpn->getReadOnly(); - if (ro < 0) { - if (!qpn->isWritable(tree_)) { - out() << "read-only"; - } - } - else if (ro > 0) { + if (!qpn->isReadOnlySet()) + qpn->setReadOnly(!qpn->isWritable(tree_)); + if (qpn->isReadOnly()) out() << "read-only"; - } - if (qpgn->isDefault()) + if (qpn->isDefault()) out() << "default"; generateQmlItem(qpn, relative, marker, false); out() << "

"; @@ -4113,16 +4108,12 @@ void HtmlGenerator::generateDetailedQmlMember(Node *node, out() << ""; out() << "

"; out() << ""; - int ro = qpn->getReadOnly(); - if (ro < 0) { - const ClassNode* cn = qpn->declarativeCppNode(); - if (cn && !qpn->isWritable(tree_)) { - out() << "read-only"; - } + if (!qpn->isReadOnlySet()) { + if (qpn->declarativeCppNode()) + qpn->setReadOnly(!qpn->isWritable(tree_)); } - else if (ro > 0) { + if (qpn->isReadOnly()) out() << "read-only"; - } if (qpn->isDefault()) out() << "default"; generateQmlItem(qpn, relative, marker, false); @@ -4145,16 +4136,10 @@ void HtmlGenerator::generateDetailedQmlMember(Node *node, out() << ""; out() << "

"; out() << ""; - - int ro = qpn->getReadOnly(); - if (ro < 0) { - if (!qpn->isWritable(tree_)) { - out() << "read-only"; - } - } - else if (ro > 0) { + if (!qpn->isReadOnlySet()) + qpn->setReadOnly(!qpn->isWritable(tree_)); + if (qpn->isReadOnly()) out() << "read-only"; - } if (qpn->isDefault()) out() << "default"; generateQmlItem(q, relative, marker, false); diff --git a/src/tools/qdoc/node.cpp b/src/tools/qdoc/node.cpp index 703c073..1ee4719 100644 --- a/src/tools/qdoc/node.cpp +++ b/src/tools/qdoc/node.cpp @@ -327,6 +327,38 @@ void Node::setPageType(const QString& t) pageType_ = DitaMapPage; } +/*! Converts the boolean value \a b to an enum representation + of the boolean type, which includes an enum value for the + \e {default value} of the item, i.e. true, false, or default. + */ +Node::FlagValue Node::toFlagValue(bool b) +{ + return b ? FlagValueTrue : FlagValueFalse; +} + +/*! + Converts the enum \a fv back to a boolean value. + If \a fv is neither the true enum value nor the + false enum value, the boolean value returned is + \a defaultValue. + + Note that runtimeDesignabilityFunction() should be called + first. If that function returns the name of a function, it + means the function must be called at runtime to determine + whether the property is Designable. + */ +bool Node::fromFlagValue(FlagValue fv, bool defaultValue) +{ + switch (fv) { + case FlagValueTrue: + return true; + case FlagValueFalse: + return false; + default: + return defaultValue; + } +} + /*! Sets the pointer to the node that this node relates to. */ @@ -1876,11 +1908,11 @@ void FunctionNode::debug() const */ PropertyNode::PropertyNode(InnerNode *parent, const QString& name) : LeafNode(Property, parent, name), - sto(Trool_Default), - des(Trool_Default), - scr(Trool_Default), - wri(Trool_Default), - usr(Trool_Default), + stored_(FlagValueDefault), + designable_(FlagValueDefault), + scriptable_(FlagValueDefault), + writable_(FlagValueDefault), + user_(FlagValueDefault), cst(false), fnl(false), rev(-1), @@ -1905,16 +1937,16 @@ void PropertyNode::setOverriddenFrom(const PropertyNode* baseProperty) if (funcs[i].isEmpty()) funcs[i] = baseProperty->funcs[i]; } - if (sto == Trool_Default) - sto = baseProperty->sto; - if (des == Trool_Default) - des = baseProperty->des; - if (scr == Trool_Default) - scr = baseProperty->scr; - if (wri == Trool_Default) - wri = baseProperty->wri; - if (usr == Trool_Default) - usr = baseProperty->usr; + if (stored_ == FlagValueDefault) + stored_ = baseProperty->stored_; + if (designable_ == FlagValueDefault) + designable_ = baseProperty->designable_; + if (scriptable_ == FlagValueDefault) + scriptable_ = baseProperty->scriptable_; + if (writable_ == FlagValueDefault) + writable_ = baseProperty->writable_; + if (user_ == FlagValueDefault) + user_ = baseProperty->user_; overrides = baseProperty; } @@ -1940,38 +1972,6 @@ QString PropertyNode::qualifiedDataType() const } } -/*! Converts the \a boolean value to an enum representation - of the boolean type, which includes an enum value for the - \e {default value} of the item, i.e. true, false, or default. - */ -PropertyNode::Trool PropertyNode::toTrool(bool boolean) -{ - return boolean ? Trool_True : Trool_False; -} - -/*! - Converts the enum \a troolean back to a boolean value. - If \a troolean is neither the true enum value nor the - false enum value, the boolean value returned is - \a defaultValue. - - Note that runtimeDesignabilityFunction() should be called - first. If that function returns the name of a function, it - means the function must be called at runtime to determine - whether the property is Designable. - */ -bool PropertyNode::fromTrool(Trool troolean, bool defaultValue) -{ - switch (troolean) { - case Trool_True: - return true; - case Trool_False: - return false; - default: - return defaultValue; - } -} - bool QmlClassNode::qmlOnly = false; QMultiMap QmlClassNode::inheritedBy; QMap QmlClassNode::moduleMap; @@ -2181,13 +2181,14 @@ QmlBasicTypeNode::QmlBasicTypeNode(InnerNode *parent, Constructor for the Qml property group node. \a parent is always a QmlClassNode. */ -QmlPropGroupNode::QmlPropGroupNode(QmlClassNode* parent, - const QString& name, - bool attached) - : FakeNode(parent, name, QmlPropertyGroup, Node::ApiPage), +QmlPropGroupNode::QmlPropGroupNode(QmlClassNode* parent, const QString& name) + //bool attached) + : FakeNode(parent, name, QmlPropertyGroup, Node::ApiPage) +#if 0 isdefault_(false), attached_(attached), readOnly_(-1) +#endif { // nothing. } @@ -2207,11 +2208,11 @@ QmlPropertyNode::QmlPropertyNode(QmlPropGroupNode *parent, bool attached) : LeafNode(QmlProperty, parent, name), type_(type), - sto(Trool_Default), - des(Trool_Default), + stored_(FlagValueDefault), + designable_(FlagValueDefault), isdefault_(false), attached_(attached), - readOnly_(-1) + readOnly_(FlagValueDefault) { setPageType(ApiPage); } @@ -2226,11 +2227,11 @@ QmlPropertyNode::QmlPropertyNode(QmlClassNode *parent, bool attached) : LeafNode(QmlProperty, parent, name), type_(type), - sto(Trool_Default), - des(Trool_Default), + stored_(FlagValueDefault), + designable_(FlagValueDefault), isdefault_(false), attached_(attached), - readOnly_(-1) + readOnly_(FlagValueDefault) { setPageType(ApiPage); } @@ -2252,39 +2253,16 @@ QmlPropertyNode::QmlPropertyNode(QmlPropertyNode* parent, bool attached) : LeafNode(parent->parent(), QmlProperty, name), type_(type), - sto(Trool_Default), - des(Trool_Default), + stored_(FlagValueDefault), + designable_(FlagValueDefault), isdefault_(false), attached_(attached), - readOnly_(-1) + readOnly_(FlagValueDefault) { setPageType(ApiPage); } /*! - I don't know what this is. - */ -QmlPropertyNode::Trool QmlPropertyNode::toTrool(bool boolean) -{ - return boolean ? Trool_True : Trool_False; -} - -/*! - I don't know what this is either. - */ -bool QmlPropertyNode::fromTrool(Trool troolean, bool defaultValue) -{ - switch (troolean) { - case Trool_True: - return true; - case Trool_False: - return false; - default: - return defaultValue; - } -} - -/*! Returns true if a QML property or attached property is read-only. The algorithm for figuring this out is long amd tedious and almost certainly will break. It currently @@ -2293,14 +2271,16 @@ bool QmlPropertyNode::fromTrool(Trool troolean, bool defaultValue) */ bool QmlPropertyNode::isWritable(Tree* tree) { - if (wri != Trool_Default) - return fromTrool(wri, false); + if (readOnly_ != FlagValueDefault) { + return !fromFlagValue(readOnly_, false); + } PropertyNode* pn = correspondingProperty(tree); - if (pn) + if (pn) { return pn->isWritable(); + } else { - location().warning(tr("Can't determine read-only status of QML property %1; writable assumed.").arg(name())); + location().warning(tr("Can't detect if QML property %1 isread-only; writable assumed.").arg(name())); return true; } } diff --git a/src/tools/qdoc/node.h b/src/tools/qdoc/node.h index cfd446d..45b5ded 100644 --- a/src/tools/qdoc/node.h +++ b/src/tools/qdoc/node.h @@ -156,6 +156,12 @@ public: OnBeyondZebra }; + enum FlagValue { + FlagValueDefault = -1, + FlagValueFalse = 0, + FlagValueTrue = 1 + }; + virtual ~Node(); void setAccess(Access access) { access_ = access; } @@ -239,6 +245,9 @@ public: static QString cleanId(QString str); QString idForNode() const; + static FlagValue toFlagValue(bool b); + static bool fromFlagValue(FlagValue fv, bool defaultValue); + static QString pageTypeString(unsigned t); static QString nodeTypeString(unsigned t); static QString nodeSubtypeString(unsigned t); @@ -553,9 +562,8 @@ public: class QmlPropGroupNode : public FakeNode { public: - QmlPropGroupNode(QmlClassNode* parent, - const QString& name, - bool attached); + QmlPropGroupNode(QmlClassNode* parent, const QString& name); + //bool attached); virtual ~QmlPropGroupNode() { } virtual bool isQmlNode() const { return true; } virtual bool isQtQuickNode() const { return parent()->isQtQuickNode(); } @@ -564,6 +572,7 @@ public: virtual QString qmlModuleIdentifier() const { return parent()->qmlModuleIdentifier(); } const QString& element() const { return parent()->name(); } +#if 0 void setDefault() { isdefault_ = true; } void setReadOnly(int ro) { readOnly_ = ro; } int getReadOnly() const { return readOnly_; } @@ -575,6 +584,7 @@ private: bool isdefault_; bool attached_; int readOnly_; +#endif }; class QmlPropertyNode; @@ -597,21 +607,20 @@ public: virtual ~QmlPropertyNode() { } void setDataType(const QString& dataType) { type_ = dataType; } - void setStored(bool stored) { sto = toTrool(stored); } - void setDesignable(bool designable) { des = toTrool(designable); } - void setWritable(bool writable) { wri = toTrool(writable); } + void setStored(bool stored) { stored_ = toFlagValue(stored); } + void setDesignable(bool designable) { designable_ = toFlagValue(designable); } + void setReadOnly(bool ro) { readOnly_ = toFlagValue(ro); } + void setDefault() { isdefault_ = true; } const QString &dataType() const { return type_; } QString qualifiedDataType() const { return type_; } - void setDefault() { isdefault_ = true; } - void setReadOnly(int ro) { readOnly_ = ro; } - int getReadOnly() const { return readOnly_; } + bool isReadOnlySet() const { return (readOnly_ != FlagValueDefault); } bool isDefault() const { return isdefault_; } - bool isStored() const { return fromTrool(sto,true); } - bool isDesignable() const { return fromTrool(des,false); } + bool isStored() const { return fromFlagValue(stored_,true); } + bool isDesignable() const { return fromFlagValue(designable_,false); } bool isWritable(Tree* tree); bool isAttached() const { return attached_; } - bool isReadOnly() const { return (readOnly_ > 0); } + bool isReadOnly() const { return fromFlagValue(readOnly_,false); } virtual bool isQmlNode() const { return true; } virtual bool isQtQuickNode() const { return parent()->isQtQuickNode(); } virtual QString qmlModuleName() const { return parent()->qmlModuleName(); } @@ -625,18 +634,12 @@ public: const NodeList& qmlPropNodes() const { return qmlPropNodes_; } private: - enum Trool { Trool_True, Trool_False, Trool_Default }; - - static Trool toTrool(bool boolean); - static bool fromTrool(Trool troolean, bool defaultValue); - QString type_; - Trool sto; - Trool des; - Trool wri; + FlagValue stored_; + FlagValue designable_; bool isdefault_; bool attached_; - int readOnly_; + FlagValue readOnly_; NodeList qmlPropNodes_; }; @@ -842,11 +845,11 @@ public: void setDataType(const QString& dataType) { type_ = dataType; } void addFunction(FunctionNode* function, FunctionRole role); void addSignal(FunctionNode* function, FunctionRole role); - void setStored(bool stored) { sto = toTrool(stored); } - void setDesignable(bool designable) { des = toTrool(designable); } - void setScriptable(bool scriptable) { scr = toTrool(scriptable); } - void setWritable(bool writable) { wri = toTrool(writable); } - void setUser(bool user) { usr = toTrool(user); } + void setStored(bool stored) { stored_ = toFlagValue(stored); } + void setDesignable(bool designable) { designable_ = toFlagValue(designable); } + void setScriptable(bool scriptable) { scriptable_ = toFlagValue(scriptable); } + void setWritable(bool writable) { writable_ = toFlagValue(writable); } + void setUser(bool user) { user_ = toFlagValue(user); } void setOverriddenFrom(const PropertyNode* baseProperty); void setRuntimeDesFunc(const QString& rdf) { runtimeDesFunc = rdf; } void setRuntimeScrFunc(const QString& scrf) { runtimeScrFunc = scrf; } @@ -862,13 +865,13 @@ public: NodeList setters() const { return functions(Setter); } NodeList resetters() const { return functions(Resetter); } NodeList notifiers() const { return functions(Notifier); } - bool isStored() const { return fromTrool(sto, storedDefault()); } - bool isDesignable() const { return fromTrool(des, designableDefault()); } - bool isScriptable() const { return fromTrool(scr, scriptableDefault()); } + bool isStored() const { return fromFlagValue(stored_, storedDefault()); } + bool isDesignable() const { return fromFlagValue(designable_, designableDefault()); } + bool isScriptable() const { return fromFlagValue(scriptable_, scriptableDefault()); } const QString& runtimeDesignabilityFunction() const { return runtimeDesFunc; } const QString& runtimeScriptabilityFunction() const { return runtimeScrFunc; } - bool isWritable() const { return fromTrool(wri, writableDefault()); } - bool isUser() const { return fromTrool(usr, userDefault()); } + bool isWritable() const { return fromFlagValue(writable_, writableDefault()); } + bool isUser() const { return fromFlagValue(user_, userDefault()); } bool isConstant() const { return cst; } bool isFinal() const { return fnl; } const PropertyNode* overriddenFrom() const { return overrides; } @@ -880,20 +883,15 @@ public: bool writableDefault() const { return !setters().isEmpty(); } private: - enum Trool { Trool_True, Trool_False, Trool_Default }; - - static Trool toTrool(bool boolean); - static bool fromTrool(Trool troolean, bool defaultValue); - QString type_; QString runtimeDesFunc; QString runtimeScrFunc; NodeList funcs[NumFunctionRoles]; - Trool sto; - Trool des; - Trool scr; - Trool wri; - Trool usr; + FlagValue stored_; + FlagValue designable_; + FlagValue scriptable_; + FlagValue writable_; + FlagValue user_; bool cst; bool fnl; int rev; -- 2.7.4