From 112df597dbff79b4e3b6f78460eb55ea9501a59d Mon Sep 17 00:00:00 2001
From: Erik Verbruggen <erik.verbruggen@nokia.com>
Date: Mon, 31 May 2010 12:21:12 +0200
Subject: [PATCH] Fixed default property discovery for custom QML components.

Reviewed-by: Christian Kamm
---
 src/libs/qmljs/qmljsinterpreter.cpp           | 28 +++++++++++++++++-
 src/libs/qmljs/qmljsinterpreter.h             |  5 ++++
 .../designercore/model/texttomodelmerger.cpp  |  3 +-
 .../qml/qmldesigner/coretests/testcore.cpp    | 29 -------------------
 4 files changed, 34 insertions(+), 31 deletions(-)

diff --git a/src/libs/qmljs/qmljsinterpreter.cpp b/src/libs/qmljs/qmljsinterpreter.cpp
index 76a77ac3954..a32cd10c9fc 100644
--- a/src/libs/qmljs/qmljsinterpreter.cpp
+++ b/src/libs/qmljs/qmljsinterpreter.cpp
@@ -1494,6 +1494,20 @@ void Context::setProperty(const ObjectValue *object, const QString &name, const
     _properties[object].insert(name, value);
 }
 
+QString Context::defaultPropertyName(const ObjectValue *object)
+{
+    for (const ObjectValue *o = object; o; o = o->prototype(this)) {
+        if (const ASTObjectValue *astObjValue = dynamic_cast<const ASTObjectValue *>(o)) {
+            QString defaultProperty = astObjValue->defaultPropertyName();
+            if (!defaultProperty.isEmpty())
+                return defaultProperty;
+        } else if (const QmlObjectValue *qmlValue = dynamic_cast<const QmlObjectValue *>(o)) {
+            return qmlValue->defaultPropertyName();
+        }
+    }
+    return QString();
+}
+
 bool Context::documentImportsPlugins(const QmlJS::Document *doc) const
 {
     return _documentsImportingPlugins.contains(doc->fileName());
@@ -2800,7 +2814,7 @@ ASTObjectValue::ASTObjectValue(UiQualifiedId *typeName,
                                UiObjectInitializer *initializer,
                                const QmlJS::Document *doc,
                                Engine *engine)
-    : ObjectValue(engine), _typeName(typeName), _initializer(initializer), _doc(doc)
+    : ObjectValue(engine), _typeName(typeName), _initializer(initializer), _doc(doc), _defaultPropertyRef(0)
 {
     if (_initializer) {
         for (UiObjectMemberList *it = _initializer->members; it; it = it->next) {
@@ -2809,6 +2823,8 @@ ASTObjectValue::ASTObjectValue(UiQualifiedId *typeName,
                 if (def->type == UiPublicMember::Property && def->name && def->memberType) {
                     ASTPropertyReference *ref = new ASTPropertyReference(def, _doc, engine);
                     _properties.append(ref);
+                    if (def->defaultToken.isValid())
+                        _defaultPropertyRef = ref;
                 } else if (def->type == UiPublicMember::Signal && def->name) {
                     ASTSignalReference *ref = new ASTSignalReference(def, _doc, engine);
                     _signals.append(ref);
@@ -2846,6 +2862,16 @@ void ASTObjectValue::processMembers(MemberProcessor *processor) const
     ObjectValue::processMembers(processor);
 }
 
+QString ASTObjectValue::defaultPropertyName() const
+{
+    if (_defaultPropertyRef) {
+        UiPublicMember *prop = _defaultPropertyRef->ast();
+        if (prop && prop->name)
+            return prop->name->asString();
+    }
+    return QString();
+}
+
 ASTVariableReference::ASTVariableReference(VariableDeclaration *ast, Engine *engine)
     : Reference(engine), _ast(ast)
 {
diff --git a/src/libs/qmljs/qmljsinterpreter.h b/src/libs/qmljs/qmljsinterpreter.h
index ba2ee534ab7..50254fda99c 100644
--- a/src/libs/qmljs/qmljsinterpreter.h
+++ b/src/libs/qmljs/qmljsinterpreter.h
@@ -297,6 +297,8 @@ public:
     const Value *property(const ObjectValue *object, const QString &name) const;
     void setProperty(const ObjectValue *object, const QString &name, const Value *value);
 
+    QString defaultPropertyName(const ObjectValue *object);
+
     bool documentImportsPlugins(const Document *doc) const;
     void setDocumentImportsPlugins(const Document *doc);
 
@@ -817,6 +819,7 @@ class QMLJS_EXPORT ASTObjectValue: public ObjectValue
     const Document *_doc;
     QList<ASTPropertyReference *> _properties;
     QList<ASTSignalReference *> _signals;
+    ASTPropertyReference *_defaultPropertyRef;
 
 public:
     ASTObjectValue(AST::UiQualifiedId *typeName,
@@ -827,6 +830,8 @@ public:
 
     bool getSourceLocation(QString *fileName, int *line, int *column) const;
     virtual void processMembers(MemberProcessor *processor) const;
+
+    QString defaultPropertyName() const;
 };
 
 } } // end of namespace QmlJS::Interpreter
diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
index d3590ce0258..cf5dd941500 100644
--- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
+++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
@@ -210,12 +210,13 @@ public:
                 int &minorVersion, QString &defaultPropertyName)
     {
         const Interpreter::ObjectValue *value = m_context->lookupType(m_doc.data(), astTypeNode);
+        defaultPropertyName = m_context->defaultPropertyName(value);
+
         const Interpreter::QmlObjectValue * qmlValue = dynamic_cast<const Interpreter::QmlObjectValue *>(value);
         if (qmlValue) {
             typeName = qmlValue->packageName() + QLatin1String("/") + qmlValue->className();
             majorVersion = qmlValue->majorVersion();
             minorVersion = qmlValue->minorVersion();
-            defaultPropertyName = qmlValue->defaultPropertyName();
         } else if (value) {
             for (UiQualifiedId *iter = astTypeNode; iter; iter = iter->next)
                 if (!iter->next && iter->name)
diff --git a/tests/auto/qml/qmldesigner/coretests/testcore.cpp b/tests/auto/qml/qmldesigner/coretests/testcore.cpp
index a0c502e10c2..e0ffeb88cf0 100644
--- a/tests/auto/qml/qmldesigner/coretests/testcore.cpp
+++ b/tests/auto/qml/qmldesigner/coretests/testcore.cpp
@@ -3343,35 +3343,6 @@ void TestCore::testSubComponentManager()
     QVERIFY(myButtonMetaInfo.property("border.width", true).isValid());
 }
 
-void TestCore::testComponentLoadingTabWidget()
-{
-
-//    QSKIP("TODO: fails", SkipAll);
-
-    QString fileName = QString(QTCREATORDIR) + "/tests/auto/qml/qmldesigner/data/fx/tabs.qml";
-    QFile file(fileName);
-    QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text));
-
-    QPlainTextEdit textEdit;
-    textEdit.setPlainText(file.readAll());
-    NotIndentingTextEditModifier modifier(&textEdit);
-
-    QScopedPointer<Model> model(Model::create("Qt/Item"));
-    model->setFileUrl(QUrl::fromLocalFile(fileName));
-    QScopedPointer<SubComponentManager> subComponentManager(new SubComponentManager(model->metaInfo(), 0));
-    subComponentManager->update(QUrl::fromLocalFile(fileName), modifier.text().toUtf8());
-
-    QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
-    testRewriterView->setTextModifier(&modifier);
-    model->attachView(testRewriterView.data());
-
-    QVERIFY(testRewriterView->errors().isEmpty());
-    QVERIFY(testRewriterView->rootModelNode().isValid());
-
-    ModelNode rootModelNode = testRewriterView->rootModelNode();
-    QCOMPARE(rootModelNode.type(), QLatin1String("TabWidget"));
-}
-
 void TestCore::testAnchorsAndRewriting()
 {
         const QString qmlString("import Qt 4.7\n"
-- 
GitLab