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 <casper.vandonderen@nokia.com>
This commit is contained in:
Martin Smith 2012-04-11 12:50:22 +02:00 committed by Qt by Nokia
parent 3ddd768504
commit b1addf36c1
7 changed files with 154 additions and 179 deletions

View File

@ -1258,8 +1258,20 @@ QList<Section> 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<const QmlPropGroupNode*>(*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<const QmlPropertyNode*>(*C);
if (pn->isAttached()) {
attached = true;
break;
}
}
++C;
}
if (attached)
insert(qmlattachedproperties,*c,style,Okay);
else
insert(qmlproperties,*c,style,Okay);

View File

@ -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<QmlPropGroupNode*>(node);
qpgn->setDefault();
NodeList::ConstIterator p = qpgn->childNodes().begin();
while (p != qpgn->childNodes().end()) {
if ((*p)->type() == Node::QmlProperty) {
QmlPropertyNode* qpn = static_cast<QmlPropertyNode*>(*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<QmlPropGroupNode*>(node);
qpgn->setReadOnly(1);
NodeList::ConstIterator p = qpgn->childNodes().begin();
while (p != qpgn->childNodes().end()) {
if ((*p)->type() == Node::QmlProperty) {

View File

@ -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())

View File

@ -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(

View File

@ -4072,16 +4072,11 @@ void HtmlGenerator::generateDetailedQmlMember(Node *node,
out() << "<td class=\"tblQmlPropNode\"><p>";
out() << "<a name=\"" + refForNode(qpn) + "\"></a>";
int ro = qpn->getReadOnly();
if (ro < 0) {
if (!qpn->isWritable(tree_)) {
out() << "<span class=\"qmlreadonly\">read-only</span>";
}
}
else if (ro > 0) {
if (!qpn->isReadOnlySet())
qpn->setReadOnly(!qpn->isWritable(tree_));
if (qpn->isReadOnly())
out() << "<span class=\"qmlreadonly\">read-only</span>";
}
if (qpgn->isDefault())
if (qpn->isDefault())
out() << "<span class=\"qmldefault\">default</span>";
generateQmlItem(qpn, relative, marker, false);
out() << "</p></td></tr>";
@ -4113,16 +4108,12 @@ void HtmlGenerator::generateDetailedQmlMember(Node *node,
out() << "<tr valign=\"top\" class=\"odd\">";
out() << "<td class=\"tblQmlPropNode\"><p>";
out() << "<a name=\"" + refForNode(qpn) + "\"></a>";
int ro = qpn->getReadOnly();
if (ro < 0) {
const ClassNode* cn = qpn->declarativeCppNode();
if (cn && !qpn->isWritable(tree_)) {
out() << "<span class=\"qmlreadonly\">read-only</span>";
}
if (!qpn->isReadOnlySet()) {
if (qpn->declarativeCppNode())
qpn->setReadOnly(!qpn->isWritable(tree_));
}
else if (ro > 0) {
if (qpn->isReadOnly())
out() << "<span class=\"qmlreadonly\">read-only</span>";
}
if (qpn->isDefault())
out() << "<span class=\"qmldefault\">default</span>";
generateQmlItem(qpn, relative, marker, false);
@ -4145,16 +4136,10 @@ void HtmlGenerator::generateDetailedQmlMember(Node *node,
out() << "<tr valign=\"top\" class=\"odd\">";
out() << "<td class=\"tblQmlPropNode\"><p>";
out() << "<a name=\"" + refForNode(q) + "\"></a>";
int ro = qpn->getReadOnly();
if (ro < 0) {
if (!qpn->isWritable(tree_)) {
out() << "<span class=\"qmlreadonly\">read-only</span>";
}
}
else if (ro > 0) {
if (!qpn->isReadOnlySet())
qpn->setReadOnly(!qpn->isWritable(tree_));
if (qpn->isReadOnly())
out() << "<span class=\"qmlreadonly\">read-only</span>";
}
if (qpn->isDefault())
out() << "<span class=\"qmldefault\">default</span>";
generateQmlItem(q, relative, marker, false);

View File

@ -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<QString,Node*> QmlClassNode::inheritedBy;
QMap<QString, QmlClassNode*> 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,38 +2253,15 @@ 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
@ -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;
}
}

View File

@ -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;