diff --git a/src/libs/qmljs/qmljs-lib.pri b/src/libs/qmljs/qmljs-lib.pri
index a5e154a0eb0c285468aa1c76519ccba1e07e7847..e79c071181c1acd970297c53a0b2307aae6232cf 100644
--- a/src/libs/qmljs/qmljs-lib.pri
+++ b/src/libs/qmljs/qmljs-lib.pri
@@ -17,7 +17,8 @@ HEADERS += \
     $$PWD/qmljsscanner.h \
     $$PWD/qmljsinterpreter.h \
     $$PWD/qmljslink.h \
-    $$PWD/qmljscheck.h
+    $$PWD/qmljscheck.h \
+    $$PWD/qmljsscopebuilder.h
 
 SOURCES += \
     $$PWD/qmljsbind.cpp \
@@ -27,7 +28,8 @@ SOURCES += \
     $$PWD/qmljsinterpreter.cpp \
     $$PWD/qmljsmetatypesystem.cpp \
     $$PWD/qmljslink.cpp \
-    $$PWD/qmljscheck.cpp
+    $$PWD/qmljscheck.cpp \
+    $$PWD/qmljsscopebuilder.cpp
 
 contains(QT_CONFIG, declarative) {
     QT += declarative
diff --git a/src/libs/qmljs/qmljscheck.cpp b/src/libs/qmljs/qmljscheck.cpp
index 383ab9ee0082c5ac52d644ef6dc98862c4700101..c8dcc6db638cf6cff1fef1d262fb0b7efd6bfaef 100644
--- a/src/libs/qmljs/qmljscheck.cpp
+++ b/src/libs/qmljs/qmljscheck.cpp
@@ -61,7 +61,7 @@ Check::Check(Document::Ptr doc, const Snapshot &snapshot)
     , _snapshot(snapshot)
     , _context(&_engine)
     , _link(&_context, doc, snapshot)
-    , _allowAnyProperty(false)
+    , _scopeBuilder(doc, &_context)
 {
 }
 
@@ -109,71 +109,20 @@ void Check::visitQmlObject(Node *ast, UiQualifiedId *typeId,
         return;
     }
 
-    const bool oldAllowAnyProperty = _allowAnyProperty;
+    _scopeBuilder.push(ast);
 
     if (! _context.lookupType(_doc.data(), typeId)) {
         warning(typeId->identifierToken, tr(Messages::unknown_type));
-        _allowAnyProperty = true; // suppress subsequent "unknown property" errors
+        // suppress subsequent errors about scope object lookup by clearing
+        // the scope object list
+        // ### todo: better way?
+        _context.scopeChain().qmlScopeObjects.clear();
+        _context.scopeChain().update();
     }
 
-    QList<const ObjectValue *> oldScopeObjects = _context.scopeChain().qmlScopeObjects;
-
-    _context.scopeChain().qmlScopeObjects.clear();
-    const ObjectValue *scopeObject = _doc->bind()->findQmlObject(ast);
-    _context.scopeChain().qmlScopeObjects += scopeObject;
-    _context.scopeChain().update();
-
-#ifndef NO_DECLARATIVE_BACKEND
-    // check if the object has a Qt.ListElement ancestor
-    const ObjectValue *prototype = scopeObject->prototype(&_context);
-    while (prototype) {
-        if (const QmlObjectValue *qmlMetaObject = dynamic_cast<const QmlObjectValue *>(prototype)) {
-            // ### Also check for Qt package. Involves changes in QmlObjectValue.
-            if (qmlMetaObject->qmlTypeName() == QLatin1String("ListElement")) {
-                _allowAnyProperty = true;
-                break;
-            }
-        }
-        prototype = prototype->prototype(&_context);
-    }
-
-    // check if the object has a Qt.PropertyChanges ancestor
-    prototype = scopeObject->prototype(&_context);
-    while (prototype) {
-        if (const QmlObjectValue *qmlMetaObject = dynamic_cast<const QmlObjectValue *>(prototype)) {
-            // ### Also check for Qt package. Involves changes in QmlObjectValue.
-            if (qmlMetaObject->qmlTypeName() == QLatin1String("PropertyChanges"))
-                break;
-        }
-        prototype = prototype->prototype(&_context);
-    }
-    // find the target script binding
-    if (prototype && initializer) {
-        for (UiObjectMemberList *m = initializer->members; m; m = m->next) {
-            if (UiScriptBinding *scriptBinding = cast<UiScriptBinding *>(m->member)) {
-                if (scriptBinding->qualifiedId
-                        && scriptBinding->qualifiedId->name->asString() == QLatin1String("target")
-                        && ! scriptBinding->qualifiedId->next) {
-                    if (ExpressionStatement *expStmt = cast<ExpressionStatement *>(scriptBinding->statement)) {
-                        Evaluate evaluator(&_context);
-                        const Value *targetValue = evaluator(expStmt->expression);
-
-                        if (const ObjectValue *target = value_cast<const ObjectValue *>(targetValue)) {
-                            _context.scopeChain().qmlScopeObjects.prepend(target);
-                        } else {
-                            _allowAnyProperty = true;
-                        }
-                    }
-                }
-            }
-        }
-    }
-#endif
-
     Node::accept(initializer, this);
 
-    _context.scopeChain().qmlScopeObjects = oldScopeObjects;
-    _allowAnyProperty = oldAllowAnyProperty;
+    _scopeBuilder.pop();
 }
 
 bool Check::visit(UiScriptBinding *ast)
@@ -231,10 +180,9 @@ bool Check::visit(UiArrayBinding *ast)
 
 const Value *Check::checkScopeObjectMember(const UiQualifiedId *id)
 {
-    if (_allowAnyProperty)
-        return 0;
-
     QList<const ObjectValue *> scopeObjects = _context.scopeChain().qmlScopeObjects;
+    if (scopeObjects.isEmpty())
+        return 0;
 
     if (! id)
         return 0; // ### error?
diff --git a/src/libs/qmljs/qmljscheck.h b/src/libs/qmljs/qmljscheck.h
index 8810865f46ea4260f5f5a1ca359111135621e223..778952bf939a3308d028ad78c978aed362f8ba81 100644
--- a/src/libs/qmljs/qmljscheck.h
+++ b/src/libs/qmljs/qmljscheck.h
@@ -33,6 +33,7 @@
 #include <qmljs/qmljsdocument.h>
 #include <qmljs/qmljsinterpreter.h>
 #include <qmljs/qmljslink.h>
+#include <qmljs/qmljsscopebuilder.h>
 #include <qmljs/parser/qmljsastvisitor_p.h>
 
 namespace QmlJS {
@@ -72,10 +73,9 @@ private:
     Interpreter::Engine _engine;
     Interpreter::Context _context;
     Link _link;
+    ScopeBuilder _scopeBuilder;
 
     QList<DiagnosticMessage> _messages;
-
-    bool _allowAnyProperty;
 };
 
 } // namespace QmlJS
diff --git a/src/libs/qmljs/qmljslink.cpp b/src/libs/qmljs/qmljslink.cpp
index b41c7b11ccd283456c4162a13416c8c5a3026ba5..07762a94b095e7257bc20a65e1574e3ca8bfc275 100644
--- a/src/libs/qmljs/qmljslink.cpp
+++ b/src/libs/qmljs/qmljslink.cpp
@@ -3,6 +3,7 @@
 #include "parser/qmljsast_p.h"
 #include "qmljsdocument.h"
 #include "qmljsbind.h"
+#include "qmljsscopebuilder.h"
 
 #include <QtCore/QFileInfo>
 #include <QtCore/QDir>
@@ -44,37 +45,16 @@ void Link::scopeChainAt(Document::Ptr doc, const QList<Node *> &astPath)
     Bind *bind = doc->bind();
     QHash<Document *, ScopeChain::QmlComponentChain *> componentScopes;
 
-    int qmlScopeObjectIndex = -1;
-
     if (doc->qmlProgram()) {
         _context->setLookupMode(Context::QmlLookup);
 
         makeComponentChain(doc, &scopeChain.qmlComponentScope, &componentScopes);
 
-        // find the last object definition or object binding: that is the scope object
-        for (int i = astPath.size() - 1; i >= 0; --i) {
-            Node *node = astPath.at(i);
-
-            ObjectValue *scopeObject = 0;
-            if (UiObjectDefinition *definition = cast<UiObjectDefinition *>(node))
-                scopeObject = bind->findQmlObject(definition);
-            else if (UiObjectBinding *binding = cast<UiObjectBinding *>(node))
-                scopeObject = bind->findQmlObject(binding);
-
-            if (scopeObject) {
-                if (scopeObject != scopeChain.qmlComponentScope.rootObject)
-                    scopeChain.qmlScopeObjects += scopeObject;
-                qmlScopeObjectIndex = i;
-                break;
-            }
-        }
-
         if (const ObjectValue *typeEnvironment = _context->typeEnvironment(doc.data()))
             scopeChain.qmlTypes = typeEnvironment;
     } else {
         // the global scope of a js file does not see the instantiating component
-        qDebug() << "ast path length: " << astPath.size();
-        if (astPath.size() != 0) {
+        if (astPath.size() > 0) {
             // add scope chains for all components that source this document
             foreach (Document::Ptr otherDoc, _docs) {
                 if (otherDoc->bind()->includedScripts().contains(doc->fileName())) {
@@ -91,20 +71,9 @@ void Link::scopeChainAt(Document::Ptr doc, const QList<Node *> &astPath)
         scopeChain.jsScopes += bind->rootObjectValue();
     }
 
-    for (int i = qmlScopeObjectIndex + 1; i < astPath.size(); ++i) {
-        Node *node = astPath.at(i);
-
-        if (FunctionDeclaration *fun = cast<FunctionDeclaration *>(node)) {
-            ObjectValue *activation = engine()->newObject(/*prototype = */ 0);
-            for (FormalParameterList *it = fun->formals; it; it = it->next) {
-                if (it->name)
-                    activation->setProperty(it->name->asString(), engine()->undefinedValue());
-            }
-            scopeChain.jsScopes += activation;
-        }
-    }
-
-    scopeChain.update();
+    ScopeBuilder scopeBuilder(doc, _context);
+    foreach (Node *node, astPath)
+        scopeBuilder.push(node);
 }
 
 void Link::makeComponentChain(
diff --git a/src/libs/qmljs/qmljsscopebuilder.cpp b/src/libs/qmljs/qmljsscopebuilder.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4f3f6fa1233145143957465c716849d5693aea12
--- /dev/null
+++ b/src/libs/qmljs/qmljsscopebuilder.cpp
@@ -0,0 +1,129 @@
+#include "qmljsscopebuilder.h"
+
+#include "qmljsbind.h"
+#include "qmljsinterpreter.h"
+#include "qmljsevaluate.h"
+#include "parser/qmljsast_p.h"
+
+using namespace QmlJS;
+using namespace QmlJS::Interpreter;
+using namespace QmlJS::AST;
+
+ScopeBuilder::ScopeBuilder(Document::Ptr doc, Interpreter::Context *context)
+    : _doc(doc)
+    , _context(context)
+{
+}
+
+ScopeBuilder::~ScopeBuilder()
+{
+}
+
+void ScopeBuilder::push(AST::Node *node)
+{
+    _nodes += node;
+
+    // QML scope object
+    Node *qmlObject = cast<UiObjectDefinition *>(node);
+    if (! qmlObject)
+        qmlObject = cast<UiObjectBinding *>(node);
+    if (qmlObject)
+        setQmlScopeObject(qmlObject);
+
+    // JS scopes
+    if (FunctionDeclaration *fun = cast<FunctionDeclaration *>(node)) {
+        ObjectValue *activation = _context->engine()->newObject(/*prototype = */ 0);
+        for (FormalParameterList *it = fun->formals; it; it = it->next) {
+            if (it->name)
+                activation->setProperty(it->name->asString(), _context->engine()->undefinedValue());
+        }
+        _context->scopeChain().jsScopes += activation;
+    }
+
+    _context->scopeChain().update();
+}
+
+void ScopeBuilder::pop()
+{
+    Node *toRemove = _nodes.last();
+    _nodes.removeLast();
+
+    // JS scopes
+    if (cast<FunctionDeclaration *>(toRemove))
+        _context->scopeChain().jsScopes.removeLast();
+
+    // QML scope object
+    if (! _nodes.isEmpty()
+        && (cast<UiObjectDefinition *>(toRemove) || cast<UiObjectBinding *>(toRemove)))
+        setQmlScopeObject(_nodes.last());
+
+    _context->scopeChain().update();
+}
+
+void ScopeBuilder::setQmlScopeObject(Node *node)
+{
+    ScopeChain &scopeChain = _context->scopeChain();
+
+    scopeChain.qmlScopeObjects.clear();
+
+    const ObjectValue *scopeObject = _doc->bind()->findQmlObject(node);
+    if (scopeObject) {
+        if (scopeObject != scopeChain.qmlComponentScope.rootObject)
+            scopeChain.qmlScopeObjects += scopeObject;
+    }
+
+#ifndef NO_DECLARATIVE_BACKEND
+    // check if the object has a Qt.ListElement ancestor
+    const ObjectValue *prototype = scopeObject->prototype(_context);
+    while (prototype) {
+        if (const QmlObjectValue *qmlMetaObject = dynamic_cast<const QmlObjectValue *>(prototype)) {
+            // ### Also check for Qt package. Involves changes in QmlObjectValue.
+            if (qmlMetaObject->qmlTypeName() == QLatin1String("ListElement")) {
+                scopeChain.qmlScopeObjects.clear();
+                break;
+            }
+        }
+        prototype = prototype->prototype(_context);
+    }
+
+    // check if the object has a Qt.PropertyChanges ancestor
+    prototype = scopeObject->prototype(_context);
+    while (prototype) {
+        if (const QmlObjectValue *qmlMetaObject = dynamic_cast<const QmlObjectValue *>(prototype)) {
+            // ### Also check for Qt package. Involves changes in QmlObjectValue.
+            if (qmlMetaObject->qmlTypeName() == QLatin1String("PropertyChanges"))
+                break;
+        }
+        prototype = prototype->prototype(_context);
+    }
+    // find the target script binding
+    if (prototype) {
+        UiObjectInitializer *initializer = 0;
+        if (UiObjectDefinition *definition = cast<UiObjectDefinition *>(node))
+            initializer = definition->initializer;
+        if (UiObjectBinding *binding = cast<UiObjectBinding *>(node))
+            initializer = binding->initializer;
+        if (initializer) {
+            for (UiObjectMemberList *m = initializer->members; m; m = m->next) {
+                if (UiScriptBinding *scriptBinding = cast<UiScriptBinding *>(m->member)) {
+                    if (scriptBinding->qualifiedId
+                            && scriptBinding->qualifiedId->name->asString() == QLatin1String("target")
+                            && ! scriptBinding->qualifiedId->next) {
+                        // ### make Evaluate understand statements.
+                        if (ExpressionStatement *expStmt = cast<ExpressionStatement *>(scriptBinding->statement)) {
+                            Evaluate evaluator(_context);
+                            const Value *targetValue = evaluator(expStmt->expression);
+
+                            if (const ObjectValue *target = value_cast<const ObjectValue *>(targetValue)) {
+                                scopeChain.qmlScopeObjects.prepend(target);
+                            } else {
+                                scopeChain.qmlScopeObjects.clear();
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+#endif
+}
diff --git a/src/libs/qmljs/qmljsscopebuilder.h b/src/libs/qmljs/qmljsscopebuilder.h
new file mode 100644
index 0000000000000000000000000000000000000000..cec9268dcf57ea0d7f2c490e4b9a0bb900232df2
--- /dev/null
+++ b/src/libs/qmljs/qmljsscopebuilder.h
@@ -0,0 +1,37 @@
+#ifndef QMLJSSCOPEBUILDER_H
+#define QMLJSSCOPEBUILDER_H
+
+#include <qmljs/qmljsdocument.h>
+
+#include <QtCore/QList>
+
+namespace QmlJS {
+
+namespace AST {
+    class Node;
+}
+
+namespace Interpreter {
+    class Context;
+}
+
+class ScopeBuilder
+{
+public:
+    ScopeBuilder(Document::Ptr doc, Interpreter::Context *context);
+    ~ScopeBuilder();
+
+    void push(AST::Node *node);
+    void pop();
+
+private:
+    void setQmlScopeObject(AST::Node *node);
+
+    Document::Ptr _doc;
+    Interpreter::Context *_context;
+    QList<AST::Node *> _nodes;
+};
+
+} // namespace QmlJS
+
+#endif // QMLJSSCOPEBUILDER_H