From 05831a8ea5169e407cca6de1f207225e1a710ff1 Mon Sep 17 00:00:00 2001
From: Christian Kamm <christian.d.kamm@nokia.com>
Date: Wed, 24 Nov 2010 14:42:10 +0100
Subject: [PATCH] QmlJS: Fix binding and scoping function expressions.

Reviewed-by: Erik Verbruggen
---
 src/libs/qmljs/qmljsbind.cpp                    |  7 +++----
 src/libs/qmljs/qmljsscopebuilder.cpp            | 10 ++++++----
 src/plugins/qmljseditor/qmljsfindreferences.cpp | 17 +++++++++++++++--
 3 files changed, 24 insertions(+), 10 deletions(-)

diff --git a/src/libs/qmljs/qmljsbind.cpp b/src/libs/qmljs/qmljsbind.cpp
index 4bc2f193e71..802957f7d4d 100644
--- a/src/libs/qmljs/qmljsbind.cpp
+++ b/src/libs/qmljs/qmljsbind.cpp
@@ -346,19 +346,18 @@ bool Bind::visit(VariableDeclaration *ast)
 
     ASTVariableReference *ref = new ASTVariableReference(ast, &_engine);
     _currentObjectValue->setProperty(ast->name->asString(), ref);
-    return false;
+    return true;
 }
 
 bool Bind::visit(FunctionExpression *ast)
 {
-    if (!ast->name)
-        return false;
     // ### FIXME: the first declaration counts
     //if (_currentObjectValue->property(ast->name->asString(), 0))
     //    return false;
 
     ASTFunctionValue *function = new ASTFunctionValue(ast, _doc, &_engine);
-    _currentObjectValue->setProperty(ast->name->asString(), function);
+    if (ast->name && cast<FunctionDeclaration *>(ast))
+        _currentObjectValue->setProperty(ast->name->asString(), function);
 
     // build function scope
     ObjectValue *functionScope = _engine.newObject(/*prototype=*/0);
diff --git a/src/libs/qmljs/qmljsscopebuilder.cpp b/src/libs/qmljs/qmljsscopebuilder.cpp
index 77b6dcc5cbf..bd27cebab92 100644
--- a/src/libs/qmljs/qmljsscopebuilder.cpp
+++ b/src/libs/qmljs/qmljsscopebuilder.cpp
@@ -61,8 +61,8 @@ void ScopeBuilder::push(AST::Node *node)
     if (qmlObject)
         setQmlScopeObject(qmlObject);
 
-    // JS scopes
-    if (FunctionDeclaration *fun = cast<FunctionDeclaration *>(node)) {
+    // JS scopes (catch both, FunctionExpression and FunctionDeclaration)
+    if (FunctionExpression *fun = dynamic_cast<FunctionExpression *>(node)) {
         ObjectValue *functionScope = _doc->bind()->findFunctionScope(fun);
         if (functionScope)
             _context->scopeChain().jsScopes += functionScope;
@@ -83,8 +83,10 @@ void ScopeBuilder::pop()
     _nodes.removeLast();
 
     // JS scopes
-    if (cast<FunctionDeclaration *>(toRemove))
-        _context->scopeChain().jsScopes.removeLast();
+    if (FunctionExpression *fun = dynamic_cast<FunctionExpression *>(toRemove)) {
+        if (_doc->bind()->findFunctionScope(fun))
+            _context->scopeChain().jsScopes.removeLast();
+    }
 
     // QML scope object
     if (! _nodes.isEmpty()
diff --git a/src/plugins/qmljseditor/qmljsfindreferences.cpp b/src/plugins/qmljseditor/qmljsfindreferences.cpp
index 9771ea5280c..debbbac5ef1 100644
--- a/src/plugins/qmljseditor/qmljsfindreferences.cpp
+++ b/src/plugins/qmljseditor/qmljsfindreferences.cpp
@@ -201,6 +201,11 @@ protected:
     }
 
     virtual bool visit(AST::FunctionDeclaration *node)
+    {
+        return visit(static_cast<FunctionExpression *>(node));
+    }
+
+    virtual bool visit(AST::FunctionExpression *node)
     {
         if (node->name && node->name->asString() == _name) {
             if (checkLookup())
@@ -328,6 +333,11 @@ protected:
     }
 
     virtual bool visit(AST::FunctionDeclaration *node)
+    {
+        return visit(static_cast<FunctionExpression *>(node));
+    }
+
+    virtual bool visit(AST::FunctionExpression *node)
     {
         Node::accept(node->formals, this);
         _result.append(node);
@@ -422,9 +432,12 @@ protected:
         return true;
     }
 
-    // ### Misses function declaration, var declaration
-
     virtual bool visit(FunctionDeclaration *node)
+    {
+        return visit(static_cast<FunctionExpression *>(node));
+    }
+
+    virtual bool visit(FunctionExpression *node)
     {
         if (containsOffset(node->identifierToken)) {
             _result.second = node->name->asString();
-- 
GitLab