diff --git a/src/libs/qmljs/qmljsinterpreter.cpp b/src/libs/qmljs/qmljsinterpreter.cpp
index c9e0c15f539ebad2dddc470f790f2d823f64fafc..ca317b6801f2bf8d014c0d982ca57e0f51801738 100644
--- a/src/libs/qmljs/qmljsinterpreter.cpp
+++ b/src/libs/qmljs/qmljsinterpreter.cpp
@@ -29,6 +29,7 @@
 
 #include "qmljsinterpreter.h"
 #include "qmljscheck.h"
+#include "qmljslink.h"
 #include "parser/qmljsast_p.h"
 #include <QtCore/QMetaObject>
 #include <QtCore/QMetaProperty>
@@ -688,6 +689,12 @@ Context::~Context()
 {
 }
 
+void Context::build(AST::Node *node, Document::Ptr doc, const Snapshot &snapshot)
+{
+    Link link(this, doc, snapshot);
+    link.scopeChainAt(doc, node);
+}
+
 Engine *Context::engine() const
 {
     return _engine;
diff --git a/src/libs/qmljs/qmljsinterpreter.h b/src/libs/qmljs/qmljsinterpreter.h
index feaf95e33f0f3a8b4c6bb5b15414075292e9ec41..88a958a64fa88679f30139f97c2d59df9af06d71 100644
--- a/src/libs/qmljs/qmljsinterpreter.h
+++ b/src/libs/qmljs/qmljsinterpreter.h
@@ -30,6 +30,7 @@
 #ifndef QMLJS_INTERPRETER_H
 #define QMLJS_INTERPRETER_H
 
+#include <qmljs/qmljsdocument.h>
 #include <qmljs/qmljs_global.h>
 #include <qmljs/qmljsmetatypesystem.h>
 #include <qmljs/parser/qmljsastfwd_p.h>
@@ -224,6 +225,8 @@ public:
     Context(Engine *engine);
     ~Context();
 
+    void build(AST::Node *node, Document::Ptr doc, const Snapshot &snapshot);
+
     Engine *engine() const;
     ScopeChain scopeChain() const;
 
diff --git a/src/libs/qmljs/qmljslink.cpp b/src/libs/qmljs/qmljslink.cpp
index 50cfc515432bb8795cc2df92e9077301821600f9..f39b91c04e3ce2d2ab2fbd773672033bf5bedcd7 100644
--- a/src/libs/qmljs/qmljslink.cpp
+++ b/src/libs/qmljs/qmljslink.cpp
@@ -12,12 +12,11 @@ using namespace QmlJS;
 using namespace QmlJS::Interpreter;
 using namespace QmlJS::AST;
 
-Link::Link(Document::Ptr currentDoc, const Snapshot &snapshot, Interpreter::Engine *interp)
+Link::Link(Context *context, Document::Ptr currentDoc, const Snapshot &snapshot)
     : _snapshot(snapshot)
-    , _context(interp)
+    , _context(context)
 {
     _docs = reachableDocuments(currentDoc, snapshot);
-
     linkImports();
 }
 
@@ -25,25 +24,20 @@ Link::~Link()
 {
 }
 
-Context *Link::context()
-{
-    return &_context;
-}
-
 Interpreter::Engine *Link::engine()
 {
-    return _context.engine();
+    return _context->engine();
 }
 
 void Link::scopeChainAt(Document::Ptr doc, Node *currentObject)
 {
-    _context.pushScope(engine()->globalObject());
+    _context->pushScope(engine()->globalObject());
 
     if (! doc)
         return;
 
     if (doc->qmlProgram() != 0)
-        _context.setLookupMode(Context::QmlLookup);
+        _context->setLookupMode(Context::QmlLookup);
 
     Bind *bind = doc->bind();
 
@@ -52,7 +46,7 @@ void Link::scopeChainAt(Document::Ptr doc, Node *currentObject)
     // ### FIXME: May want to link to instantiating components from here.
 
     if (bind->_rootObjectValue)
-        _context.pushScope(bind->_rootObjectValue);
+        _context->pushScope(bind->_rootObjectValue);
 
     ObjectValue *scopeObject = 0;
     if (UiObjectDefinition *definition = cast<UiObjectDefinition *>(currentObject))
@@ -61,7 +55,7 @@ void Link::scopeChainAt(Document::Ptr doc, Node *currentObject)
         scopeObject = bind->_qmlObjects.value(binding);
 
     if (scopeObject && scopeObject != bind->_rootObjectValue)
-        _context.pushScope(scopeObject);
+        _context->pushScope(scopeObject);
 
     const QStringList &includedScripts = bind->includedScripts();
     for (int index = includedScripts.size() - 1; index != -1; --index) {
@@ -69,19 +63,19 @@ void Link::scopeChainAt(Document::Ptr doc, Node *currentObject)
 
         if (Document::Ptr scriptDoc = _snapshot.document(scriptFile)) {
             if (scriptDoc->jsProgram()) {
-                _context.pushScope(scriptDoc->bind()->_rootObjectValue);
+                _context->pushScope(scriptDoc->bind()->_rootObjectValue);
             }
         }
     }
 
     if (bind->_functionEnvironment)
-        _context.pushScope(bind->_functionEnvironment);
+        _context->pushScope(bind->_functionEnvironment);
 
     if (bind->_idEnvironment)
-        _context.pushScope(bind->_idEnvironment);
+        _context->pushScope(bind->_idEnvironment);
 
-    if (const ObjectValue *typeEnvironment = _context.typeEnvironment(doc.data()))
-        _context.pushScope(typeEnvironment);
+    if (const ObjectValue *typeEnvironment = _context->typeEnvironment(doc.data()))
+        _context->pushScope(typeEnvironment);
 }
 
 void Link::linkImports()
@@ -92,7 +86,7 @@ void Link::linkImports()
         // Populate the _typeEnvironment with imports.
         populateImportedTypes(typeEnv, doc);
 
-        _context.setTypeEnvironment(doc.data(), typeEnv);
+        _context->setTypeEnvironment(doc.data(), typeEnv);
     }
 }
 
diff --git a/src/libs/qmljs/qmljslink.h b/src/libs/qmljs/qmljslink.h
index fd92fd06149d7aaf5c8135c6a45ec6c46f2ffa85..c6329fef324c0f24c78cb8dfe81cd429aacbd2df 100644
--- a/src/libs/qmljs/qmljslink.h
+++ b/src/libs/qmljs/qmljslink.h
@@ -2,34 +2,32 @@
 #define QMLJSLINK_H
 
 #include <qmljs/qmljsdocument.h>
-#include <qmljs/qmljsbind.h>
 #include <qmljs/qmljsinterpreter.h>
 #include <qmljs/parser/qmljsastfwd_p.h>
-#include <qmljs/parser/qmljsengine_p.h>
 
 #include <QtCore/QList>
 #include <QtCore/QHash>
 
 namespace QmlJS {
 
+class NameId;
+
 /*
-    Temporarily links a set of bound documents together to allow resolving cross-document
-    dependencies. The link is undone when this object is destoyed.
+    Helper for building a context.
 */
-class QMLJS_EXPORT Link
+class Link
 {
 public:
     // Link all documents in snapshot reachable from doc.
-    Link(Document::Ptr doc, const Snapshot &snapshot, Interpreter::Engine *interp);
+    Link(Interpreter::Context *context, Document::Ptr doc, const Snapshot &snapshot);
     ~Link();
 
-    Interpreter::Context *context();
-    Interpreter::Engine *engine();
-
     // Get the scope chain for the currentObject inside doc.
     void scopeChainAt(Document::Ptr doc, AST::Node *currentObject);
 
 private:
+    Interpreter::Engine *engine();
+
     static QList<Document::Ptr> reachableDocuments(Document::Ptr startDoc, const Snapshot &snapshot);
     static AST::UiQualifiedId *qualifiedTypeNameId(AST::Node *node);
 
@@ -44,7 +42,7 @@ private:
 
 private:
     Snapshot _snapshot;
-    Interpreter::Context _context;
+    Interpreter::Context *_context;
     QList<Document::Ptr> _docs;
 };
 
diff --git a/src/plugins/qmljseditor/qmlcodecompletion.cpp b/src/plugins/qmljseditor/qmlcodecompletion.cpp
index d76b6eebace3bbaeb858ba907641f81b537a2b97..92a29f42093b26dbd23f4b7f9475ba5eb3342c8b 100644
--- a/src/plugins/qmljseditor/qmlcodecompletion.cpp
+++ b/src/plugins/qmljseditor/qmlcodecompletion.cpp
@@ -653,12 +653,11 @@ int QmlCodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
     const QIcon symbolIcon = iconForColor(Qt::darkCyan);
 
     Interpreter::Engine interp;
+    Interpreter::Context context(&interp);
 
     // Set up the current scope chain.
-    Link link(document, snapshot, &interp);
-
     AST::Node *declaringMember = semanticInfo.declaringMember(editor->position());
-    link.scopeChainAt(document, declaringMember);
+    context.build(declaringMember, document, snapshot);
 
     // Search for the operator that triggered the completion.
     QChar completionOperator;
@@ -668,7 +667,7 @@ int QmlCodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
     if (completionOperator.isSpace() || completionOperator.isNull() || isDelimiter(completionOperator) ||
             (completionOperator == QLatin1Char('(') && m_startPosition != editor->position())) {
         // It's a global completion.
-        EnumerateProperties enumerateProperties(link.context());
+        EnumerateProperties enumerateProperties(&context);
         enumerateProperties.setGlobalCompletion(true);
         QHashIterator<QString, const Interpreter::Value *> it(enumerateProperties());
         while (it.hasNext()) {
@@ -691,14 +690,14 @@ int QmlCodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
         //qDebug() << "expression:" << expression;
 
         if (expression  != 0) {
-            Check evaluate(link.context());
+            Check evaluate(&context);
 
             // Evaluate the expression under cursor.
             const Interpreter::Value *value = interp.convertToObject(evaluate(expression));
             //qDebug() << "type:" << interp.typeId(value);
 
             if (value && completionOperator == QLatin1Char('.')) { // member completion
-                EnumerateProperties enumerateProperties(link.context());
+                EnumerateProperties enumerateProperties(&context);
                 QHashIterator<QString, const Interpreter::Value *> it(enumerateProperties(value));
                 while (it.hasNext()) {
                     it.next();
diff --git a/src/plugins/qmljseditor/qmlhoverhandler.cpp b/src/plugins/qmljseditor/qmlhoverhandler.cpp
index 5885be5383b4373e788912b45756bc5455147f8a..666b7ae92f0b35afd24841c7e4951af33fb0cc56 100644
--- a/src/plugins/qmljseditor/qmlhoverhandler.cpp
+++ b/src/plugins/qmljseditor/qmlhoverhandler.cpp
@@ -172,14 +172,14 @@ void QmlHoverHandler::updateHelpIdAndTooltip(TextEditor::ITextEditor *editor, in
             AST::Node *declaringMember = semanticInfo.declaringMember(pos);
 
             Interpreter::Engine interp;
-            Link link(qmlDocument, snapshot, &interp);
-            link.scopeChainAt(qmlDocument, declaringMember);
+            Interpreter::Context context(&interp);
+            context.build(declaringMember, qmlDocument, snapshot);
 
-            Check check(link.context());
+            Check check(&context);
             const Interpreter::Value *value = check(node);
 
             QStringList baseClasses;
-            m_toolTip = prettyPrint(value, link.context(), &baseClasses);
+            m_toolTip = prettyPrint(value, &context, &baseClasses);
 
             foreach (const QString &baseClass, baseClasses) {
                 QString helpId = QLatin1String("QML.");