From 13cbfecced7c6b72e6f4b1f442ed74247386fc3f Mon Sep 17 00:00:00 2001
From: Erik Verbruggen <erik.verbruggen@nokia.com>
Date: Wed, 23 Sep 2009 16:40:41 +0200
Subject: [PATCH] Small fixes to property lookups.

---
 src/plugins/duieditor/qmllookupcontext.cpp    | 88 ++++++++++++++++++-
 src/plugins/duieditor/qmllookupcontext.h      | 11 ++-
 .../duieditor/qmlresolveexpression.cpp        | 19 +---
 3 files changed, 95 insertions(+), 23 deletions(-)

diff --git a/src/plugins/duieditor/qmllookupcontext.cpp b/src/plugins/duieditor/qmllookupcontext.cpp
index 8694959c1c8..1847f355361 100644
--- a/src/plugins/duieditor/qmllookupcontext.cpp
+++ b/src/plugins/duieditor/qmllookupcontext.cpp
@@ -26,7 +26,10 @@ QmlLookupContext::~QmlLookupContext()
 
 QmlSymbol *QmlLookupContext::resolve(const QString &name)
 {
-    // ### TODO: look at property definitions
+    // look at property definitions
+    if (QmlSymbol *propertySymbol = resolveProperty(name, _scopes.top(), _doc->fileName()))
+        return propertySymbol;
+
     if (name == "parent") {
         for (int i = _scopes.size() - 2; i >= 0; --i) {
             Node *scope = _scopes.at(i);
@@ -56,9 +59,14 @@ QmlSymbol *QmlLookupContext::createSymbol(const QString &fileName, QmlJS::AST::U
     return symbol;
 }
 
-QmlSymbol *QmlLookupContext::resolveType(const QString &name)
+QmlSymbol *QmlLookupContext::resolveType(const QString &name, const QString &fileName)
 {
-    UiProgram *prog = _doc->program();
+    // TODO: handle import-as.
+    DuiDocument::Ptr document = _snapshot[fileName];
+    if (document.isNull())
+        return 0;
+
+    UiProgram *prog = document->program();
     if (!prog)
         return 0;
 
@@ -76,7 +84,7 @@ QmlSymbol *QmlLookupContext::resolveType(const QString &name)
 
         const QString path = import->fileName->asString();
 
-        const QMap<QString, DuiDocument::Ptr> importedTypes = _snapshot.componentsDefinedByImportedDocuments(_doc, path);
+        const QMap<QString, DuiDocument::Ptr> importedTypes = _snapshot.componentsDefinedByImportedDocuments(document, path);
         if (importedTypes.contains(name)) {
             DuiDocument::Ptr importedDoc = importedTypes.value(name);
 
@@ -88,3 +96,75 @@ QmlSymbol *QmlLookupContext::resolveType(const QString &name)
 
     return 0;
 }
+
+QmlSymbol *QmlLookupContext::resolveProperty(const QString &name, Node *scope, const QString &fileName)
+{
+    UiQualifiedId *typeName = 0;
+
+    if (UiObjectBinding *binding = cast<UiObjectBinding*>(scope)) {
+        if (QmlSymbol *symbol = resolveProperty(name, binding->initializer, fileName))
+            return symbol;
+        else
+            typeName = binding->qualifiedTypeNameId;
+    } else if (UiObjectDefinition *definition = cast<UiObjectDefinition*>(scope)) {
+        if (QmlSymbol *symbol = resolveProperty(name, definition->initializer, fileName))
+            return symbol;
+        else
+            typeName = definition->qualifiedTypeNameId;
+    } // TODO: extend this to handle (JavaScript) block scopes.
+
+    if (typeName == 0)
+        return 0;
+
+    QmlSymbol *typeSymbol = resolveType(toString(typeName), fileName);
+    if (typeSymbol && typeSymbol->isSymbolFromFile()) {
+        return resolveProperty(name, typeSymbol->asSymbolFromFile()->node(), typeSymbol->asSymbolFromFile()->fileName());
+    }
+
+    return 0;
+}
+
+QmlSymbol *QmlLookupContext::resolveProperty(const QString &name, QmlJS::AST::UiObjectInitializer *initializer, const QString &fileName)
+{
+    if (!initializer)
+        return 0;
+
+    for (UiObjectMemberList *iter = initializer->members; iter; iter = iter->next) {
+        UiObjectMember *member = iter->member;
+        if (!member)
+            continue;
+
+        if (UiPublicMember *publicMember = cast<UiPublicMember*>(member)) {
+            if (name == publicMember->name->asString())
+                return createSymbol(fileName, publicMember);
+        } else if (UiObjectBinding *objectBinding = cast<UiObjectBinding*>(member)) {
+            if (name == toString(objectBinding->qualifiedId))
+                return createSymbol(fileName, objectBinding);
+        } else if (UiArrayBinding *arrayBinding = cast<UiArrayBinding*>(member)) {
+            if (name == toString(arrayBinding->qualifiedId))
+                return createSymbol(fileName, arrayBinding);
+        } else if (UiScriptBinding *scriptBinding = cast<UiScriptBinding*>(member)) {
+            if (name == toString(scriptBinding->qualifiedId))
+                return createSymbol(fileName, scriptBinding);
+        }
+    }
+
+    return 0;
+}
+
+QString QmlLookupContext::toString(UiQualifiedId *id)
+{
+    QString str;
+
+    for (UiQualifiedId *iter = id; iter; iter = iter->next) {
+        if (!(iter->name))
+            continue;
+
+        str.append(iter->name->asString());
+
+        if (iter->next)
+            str.append('.');
+    }
+
+    return str;
+}
diff --git a/src/plugins/duieditor/qmllookupcontext.h b/src/plugins/duieditor/qmllookupcontext.h
index 3c98e056344..4813f37e30c 100644
--- a/src/plugins/duieditor/qmllookupcontext.h
+++ b/src/plugins/duieditor/qmllookupcontext.h
@@ -19,7 +19,10 @@ public:
     ~QmlLookupContext();
 
     QmlSymbol *resolve(const QString &name);
-    QmlSymbol *resolveType(const QString &name);
+    QmlSymbol *resolveType(const QString &name)
+    { return resolveType(name, _doc->fileName()); }
+    QmlSymbol *resolveType(QmlJS::AST::UiQualifiedId *name)
+    { return resolveType(toString(name), _doc->fileName()); }
 
     DuiDocument::Ptr document() const
     { return _doc; }
@@ -27,6 +30,12 @@ public:
 private:
     QmlSymbol *createSymbol(const QString &fileName, QmlJS::AST::UiObjectMember *node);
 
+    QmlSymbol *resolveType(const QString &name, const QString &fileName);
+    QmlSymbol *resolveProperty(const QString &name, QmlJS::AST::Node *scope, const QString &fileName);
+    QmlSymbol *resolveProperty(const QString &name, QmlJS::AST::UiObjectInitializer *initializer, const QString &fileName);
+
+    static QString toString(QmlJS::AST::UiQualifiedId *id);
+
 private:
     QStack<QmlJS::AST::Node *> _scopes;
     DuiDocument::Ptr _doc;
diff --git a/src/plugins/duieditor/qmlresolveexpression.cpp b/src/plugins/duieditor/qmlresolveexpression.cpp
index 390ca5586b5..02fc21daa7f 100644
--- a/src/plugins/duieditor/qmlresolveexpression.cpp
+++ b/src/plugins/duieditor/qmlresolveexpression.cpp
@@ -108,26 +108,9 @@ bool QmlResolveExpression::visit(FieldMemberExpression *ast)
     return false;
 }
 
-static inline QString toString(UiQualifiedId *id)
-{
-    QString str;
-
-    for (UiQualifiedId *iter = id; iter; iter = iter->next) {
-        if (!(iter->name))
-            continue;
-
-        str.append(iter->name->asString());
-
-        if (iter->next)
-            str.append('.');
-    }
-
-    return str;
-}
-
 bool QmlResolveExpression::visit(QmlJS::AST::UiQualifiedId *ast)
 {
-    _value = _context.resolveType(toString(ast));
+    _value = _context.resolveType(ast);
 
     return false;
 }
-- 
GitLab