qdoc: Distinguish between QML property and attached property

A recent change in qtdeclarative (60ed6a43) added an attached
property 'Window' to Item type, with property names identical
to the ones already available in Window. This caused QDoc to
report warnings for duplicate documentation for QML properties,
because there was no distiction between a QML property and an
attached property.

This change fixes the issue by:
    - Allowing identical names for \qmlproperty and
      \qmlattachedproperty
    - Using distinct URLs/UUIDs/anchor references for them
    - Marking attached properties with '[attached]' qualifier
      in 'All Members' page.

This doesn't solve the issue of disambiguating between a
similarly named QML property and attached property when
linking from an external location. However, these can be
solved with the help of the \target command.

Task-number: QTBUG-40674
Change-Id: Icc74de237366e9897334689fe354ab83e4af0356
Reviewed-by: Martin Smith <martin.smith@digia.com>
Reviewed-by: Jerome Pasion <jerome.pasion@digia.com>
Reviewed-by: Shawn Rutledge <shawn.rutledge@digia.com>
This commit is contained in:
Topi Reinio 2014-08-11 11:58:44 +02:00 committed by Shawn Rutledge
parent 34198cedbe
commit 338f9c4f7c
6 changed files with 41 additions and 5 deletions

View File

@ -832,7 +832,7 @@ void CppCodeParser::processQmlProperties(const Doc& doc, NodeList& nodes, DocLis
if (splitQmlPropertyArg(arg, type, module, qmlType, property)) {
qmlClass = qdb_->findQmlType(module, qmlType);
if (qmlClass) {
if (qmlClass->hasQmlProperty(property) != 0) {
if (qmlClass->hasQmlProperty(property, attached) != 0) {
QString msg = tr("QML property documented multiple times: '%1'").arg(arg);
doc.startLocation().warning(msg);
}

View File

@ -545,7 +545,10 @@ QString Generator::fullDocumentLocation(const Node *node, bool useSubdir)
anchorRef = QLatin1Char('#') + node->name() + "-prop";
break;
case Node::QmlProperty:
anchorRef = QLatin1Char('#') + node->name() + "-prop";
if (node->isAttached())
anchorRef = QLatin1Char('#') + node->name() + "-attached-prop";
else
anchorRef = QLatin1Char('#') + node->name() + "-prop";
break;
case Node::QmlSignal:
anchorRef = QLatin1Char('#') + node->name() + "-signal";

View File

@ -2477,6 +2477,8 @@ QString HtmlGenerator::generateAllQmlMembersFile(QmlClassNode* qml_cn, CodeMarke
prefix = prefix.left(keys.at(j).indexOf("::")+1);
}
generateQmlItem(nodes[j], qcn, marker, true);
if (nodes[j]->isAttached())
out() << " [attached]";
//generateSynopsis(nodes[j], qcn, marker, CodeMarker::Subpage, false, &prefix);
out() << "</li>\n";
}
@ -3627,8 +3629,13 @@ QString HtmlGenerator::refForNode(const Node *node)
break;
case Node::Document:
break;
case Node::QmlPropertyGroup:
case Node::QmlProperty:
if (node->isAttached())
ref = node->name() + "-attached-prop";
else
ref = node->name() + "-prop";
break;
case Node::QmlPropertyGroup:
case Node::Property:
ref = node->name() + "-prop";
break;

View File

@ -1338,6 +1338,27 @@ QmlPropertyNode* InnerNode::hasQmlProperty(const QString& n) const
return 0;
}
/*!
If this node has a child that is a QML property named \a n
whose type (attached or normal property) matches \a attached,
return the pointer to that child.
*/
QmlPropertyNode* InnerNode::hasQmlProperty(const QString& n, bool attached) const
{
foreach (Node* child, childNodes()) {
if (child->type() == Node::QmlProperty) {
if (child->name() == n && child->isAttached() == attached)
return static_cast<QmlPropertyNode*>(child);
}
else if (child->isQmlPropertyGroup()) {
QmlPropertyNode* t = child->hasQmlProperty(n, attached);
if (t)
return t;
}
}
return 0;
}
/*!
\class LeafNode
*/
@ -2797,7 +2818,10 @@ QString Node::idForNode() const
str = "qml-module-" + name();
break;
case Node::QmlProperty:
str = "qml-property-" + name();
if (isAttached())
str = "qml-attached-property-" + name();
else
str = "qml-property-" + name();
break;
case Node::QmlPropertyGroup:
{

View File

@ -239,6 +239,7 @@ public:
virtual void setTitle(const QString& ) { }
virtual void setSubTitle(const QString& ) { }
virtual QmlPropertyNode* hasQmlProperty(const QString& ) const { return 0; }
virtual QmlPropertyNode* hasQmlProperty(const QString&, bool ) const { return 0; }
virtual void getMemberNamespaces(NodeMap& ) { }
virtual void getMemberClasses(NodeMap& ) { }
virtual bool isInternal() const;
@ -391,6 +392,7 @@ public:
virtual void setOutputFileName(const QString& f) { outputFileName_ = f; }
virtual QString outputFileName() const { return outputFileName_; }
virtual QmlPropertyNode* hasQmlProperty(const QString& ) const;
virtual QmlPropertyNode* hasQmlProperty(const QString&, bool attached) const;
void addChild(Node* child, const QString& title);
const QStringList& groupNames() const { return groupNames_; }
virtual void appendGroupName(const QString& t) { groupNames_.append(t); }

View File

@ -266,7 +266,7 @@ bool QmlDocVisitor::applyDocumentation(QQmlJS::AST::SourceLocation location, Nod
}
else {
bool isAttached = (topic == COMMAND_QMLATTACHEDPROPERTY);
QmlPropertyNode* n = parent->hasQmlProperty(qpa.name_);
QmlPropertyNode* n = parent->hasQmlProperty(qpa.name_, isAttached);
if (n == 0)
n = new QmlPropertyNode(parent, qpa.name_, qpa.type_, isAttached);
n->setLocation(doc.location());