diff --git a/src/libs/qmljs/qmljsbind.cpp b/src/libs/qmljs/qmljsbind.cpp
index 7a580d18ce62d9ae71333a75405014bc12f9b451..9f95eb922a0aa8d2373972d2b79db66e8ed16d61 100644
--- a/src/libs/qmljs/qmljsbind.cpp
+++ b/src/libs/qmljs/qmljsbind.cpp
@@ -139,7 +139,7 @@ ObjectValue *Bind::bindObject(UiQualifiedId *qualifiedTypeNameId, UiObjectInitia
     }
 
     // normal component instance
-    ASTObjectValue *objectValue = new ASTObjectValue(qualifiedTypeNameId, initializer, &_interp);
+    ASTObjectValue *objectValue = new ASTObjectValue(qualifiedTypeNameId, initializer, _doc, &_interp);
     QmlPrototypeReference *prototypeReference =
             new QmlPrototypeReference(qualifiedTypeNameId, _doc, &_interp);
     objectValue->setPrototype(prototypeReference);
diff --git a/src/libs/qmljs/qmljscheck.cpp b/src/libs/qmljs/qmljscheck.cpp
index f25a7df52f0e68469b6f371f2420979237cd6555..0cb1e77b9a3d96e7e3174e74e2feff67bd7f8646 100644
--- a/src/libs/qmljs/qmljscheck.cpp
+++ b/src/libs/qmljs/qmljscheck.cpp
@@ -51,10 +51,18 @@ Check::~Check()
 
 const Interpreter::Value *Check::operator()(AST::Node *ast)
 {
-    return check(ast);
+    const Value *result = reference(ast);
+
+    if (const Reference *ref = value_cast<const Reference *>(result))
+        result = ref->value(_context);
+
+    if (! result)
+        result = _engine->undefinedValue();
+
+    return result;
 }
 
-const Interpreter::Value *Check::check(AST::Node *ast)
+const Interpreter::Value *Check::reference(AST::Node *ast)
 {
     // save the result
     const Value *previousResult = switchResult(0);
@@ -63,15 +71,7 @@ const Interpreter::Value *Check::check(AST::Node *ast)
     accept(ast);
 
     // restore the previous result
-    const Value *result = switchResult(previousResult);
-
-    if (const Reference *ref = value_cast<const Reference *>(result))
-        result = ref->value(_context);
-
-    if (! result)
-        result = _engine->undefinedValue();
-
-    return result;
+    return switchResult(previousResult);
 }
 
 Interpreter::Engine *Check::switchEngine(Interpreter::Engine *engine)
@@ -309,7 +309,7 @@ bool Check::visit(AST::FieldMemberExpression *ast)
     if (! ast->name)
         return false;
 
-    if (const Interpreter::Value *base = _engine->convertToObject(check(ast->base))) {
+    if (const Interpreter::Value *base = _engine->convertToObject(reference(ast->base))) {
         if (const Interpreter::ObjectValue *obj = base->asObjectValue()) {
             _result = obj->property(ast->name->asString(), _context);
         }
@@ -320,7 +320,7 @@ bool Check::visit(AST::FieldMemberExpression *ast)
 
 bool Check::visit(AST::NewMemberExpression *ast)
 {
-    if (const FunctionValue *ctor = value_cast<const FunctionValue *>(check(ast->base))) {
+    if (const FunctionValue *ctor = value_cast<const FunctionValue *>(reference(ast->base))) {
         _result = ctor->construct();
     }
     return false;
@@ -328,7 +328,7 @@ bool Check::visit(AST::NewMemberExpression *ast)
 
 bool Check::visit(AST::NewExpression *ast)
 {
-    if (const FunctionValue *ctor = value_cast<const FunctionValue *>(check(ast->expression))) {
+    if (const FunctionValue *ctor = value_cast<const FunctionValue *>(reference(ast->expression))) {
         _result = ctor->construct();
     }
     return false;
@@ -336,7 +336,7 @@ bool Check::visit(AST::NewExpression *ast)
 
 bool Check::visit(AST::CallExpression *ast)
 {
-    if (const Interpreter::Value *base = check(ast->base)) {
+    if (const Interpreter::Value *base = reference(ast->base)) {
         if (const Interpreter::FunctionValue *obj = base->asFunctionValue()) {
             _result = obj->returnValue();
         }
diff --git a/src/libs/qmljs/qmljscheck.h b/src/libs/qmljs/qmljscheck.h
index 14a56f8507d4a0c151abe3fe707f8df76eb9f59f..d0555f6754375f2ac5973d54e51cb9628fef1a49 100644
--- a/src/libs/qmljs/qmljscheck.h
+++ b/src/libs/qmljs/qmljscheck.h
@@ -52,10 +52,10 @@ public:
     virtual ~Check();
 
     const Interpreter::Value *operator()(AST::Node *ast);
+    const Interpreter::Value *reference(AST::Node *ast);
 
 protected:
     void accept(AST::Node *node);
-    const Interpreter::Value *check(AST::Node *ast);
 
     Interpreter::Engine *switchEngine(Interpreter::Engine *engine);
     const Interpreter::Value *switchResult(const Interpreter::Value *result);
diff --git a/src/libs/qmljs/qmljsinterpreter.cpp b/src/libs/qmljs/qmljsinterpreter.cpp
index b48e28e0bc4e57829127fa0c3dec236326c6a8b2..9ac782bccc154e48fee21670c639f75e5280308c 100644
--- a/src/libs/qmljs/qmljsinterpreter.cpp
+++ b/src/libs/qmljs/qmljsinterpreter.cpp
@@ -585,6 +585,11 @@ Value::~Value()
 {
 }
 
+bool Value::getSourceLocation(QString *, int *, int *) const
+{
+    return false;
+}
+
 const NullValue *Value::asNullValue() const
 {
     return 0;
@@ -1909,30 +1914,42 @@ QmlObjectValue *Engine::newQmlObject(const QString &name, const QString &prefix,
 
 
 
-ASTObjectValue::ASTObjectValue(UiQualifiedId *typeName, UiObjectInitializer *initializer, Engine *engine)
-    : ObjectValue(engine), _typeName(typeName), _initializer(initializer)
-{
-}
-
-ASTObjectValue::~ASTObjectValue()
-{
-}
-
-void ASTObjectValue::processMembers(MemberProcessor *processor) const
+ASTObjectValue::ASTObjectValue(UiQualifiedId *typeName,
+                               UiObjectInitializer *initializer,
+                               const Document *doc,
+                               Engine *engine)
+    : ObjectValue(engine), _typeName(typeName), _initializer(initializer), _doc(doc)
 {
     if (_initializer) {
         for (UiObjectMemberList *it = _initializer->members; it; it = it->next) {
             UiObjectMember *member = it->member;
             if (UiPublicMember *def = cast<UiPublicMember *>(member)) {
                 if (def->name && def->memberType) {
-                    const QString propName = def->name->asString();
-                    const QString propType = def->memberType->asString();
-
-                    processor->processProperty(propName, engine()->defaultValueForBuiltinType(propType));
+                    ASTPropertyReference *ref = new ASTPropertyReference(def, _doc, engine);
+                    _properties.append(ref);
                 }
             }
         }
     }
+}
+
+ASTObjectValue::~ASTObjectValue()
+{
+}
+
+bool ASTObjectValue::getSourceLocation(QString *fileName, int *line, int *column) const
+{
+    *fileName = _doc->fileName();
+    *line = _typeName->identifierToken.startLine;
+    *column = _typeName->identifierToken.startColumn;
+    return true;
+}
+
+void ASTObjectValue::processMembers(MemberProcessor *processor) const
+{
+    foreach (ASTPropertyReference *ref, _properties)
+        processor->processProperty(ref->ast()->name->asString(), ref);
+
     ObjectValue::processMembers(processor);
 }
 
@@ -2021,3 +2038,32 @@ const Value *QmlPrototypeReference::value(Context *context) const
     return context->lookupType(_doc, _qmlTypeName);
 }
 
+ASTPropertyReference::ASTPropertyReference(AST::UiPublicMember *ast, const Document *doc, Engine *engine)
+    : Reference(engine), _ast(ast), _doc(doc)
+{
+}
+
+ASTPropertyReference::~ASTPropertyReference()
+{
+}
+
+bool ASTPropertyReference::getSourceLocation(QString *fileName, int *line, int *column) const
+{
+    *fileName = _doc->fileName();
+    *line = _ast->identifierToken.startLine;
+    *column = _ast->identifierToken.startColumn;
+    return true;
+}
+
+const Value *ASTPropertyReference::value(Context *context) const
+{
+    if (_ast->expression) {
+        Check check(context);
+        return check(_ast->expression);
+    }
+
+    if (_ast->memberType)
+        return engine()->defaultValueForBuiltinType(_ast->memberType->asString());
+
+    return engine()->undefinedValue();
+}
diff --git a/src/libs/qmljs/qmljsinterpreter.h b/src/libs/qmljs/qmljsinterpreter.h
index 88a958a64fa88679f30139f97c2d59df9af06d71..3a03be7a642030c6df4e1abbfaee66e1b8405b25 100644
--- a/src/libs/qmljs/qmljsinterpreter.h
+++ b/src/libs/qmljs/qmljsinterpreter.h
@@ -104,6 +104,8 @@ public:
     virtual const Reference *asReference() const;
 
     virtual void accept(ValueVisitor *) const = 0;
+
+    virtual bool getSourceLocation(QString *fileName, int *line, int *column) const;
 };
 
 template <typename _RetTy> _RetTy value_cast(const Value *v);
@@ -225,7 +227,7 @@ public:
     Context(Engine *engine);
     ~Context();
 
-    void build(AST::Node *node, Document::Ptr doc, const Snapshot &snapshot);
+    void build(AST::Node *node, const Document::Ptr doc, const Snapshot &snapshot);
 
     Engine *engine() const;
     ScopeChain scopeChain() const;
@@ -642,18 +644,6 @@ private:
     const Document *_doc;
 };
 
-class QMLJS_EXPORT ASTObjectValue: public ObjectValue
-{
-    AST::UiQualifiedId *_typeName;
-    AST::UiObjectInitializer *_initializer;
-
-public:
-    ASTObjectValue(AST::UiQualifiedId *typeName, AST::UiObjectInitializer *initializer, Engine *engine);
-    virtual ~ASTObjectValue();
-
-    virtual void processMembers(MemberProcessor *processor) const;
-};
-
 class QMLJS_EXPORT ASTVariableReference: public Reference
 {
     AST::VariableDeclaration *_ast;
@@ -683,7 +673,38 @@ public:
     virtual bool isVariadic() const;
 };
 
+class QMLJS_EXPORT ASTPropertyReference: public Reference
+{
+    AST::UiPublicMember *_ast;
+    const Document *_doc;
+
+public:
+    ASTPropertyReference(AST::UiPublicMember *ast, const Document *doc, Engine *engine);
+    virtual ~ASTPropertyReference();
 
+    AST::UiPublicMember *ast() const { return _ast; }
+
+    virtual bool getSourceLocation(QString *fileName, int *line, int *column) const;
+    virtual const Value *value(Context *context) const;
+};
+
+class QMLJS_EXPORT ASTObjectValue: public ObjectValue
+{
+    AST::UiQualifiedId *_typeName;
+    AST::UiObjectInitializer *_initializer;
+    const Document *_doc;
+    QList<ASTPropertyReference *> _properties;
+
+public:
+    ASTObjectValue(AST::UiQualifiedId *typeName,
+                   AST::UiObjectInitializer *initializer,
+                   const Document *doc,
+                   Engine *engine);
+    virtual ~ASTObjectValue();
+
+    bool getSourceLocation(QString *fileName, int *line, int *column) const;
+    virtual void processMembers(MemberProcessor *processor) const;
+};
 
 } } // end of namespace QmlJS::Interpreter
 
diff --git a/src/plugins/qmljseditor/qmljseditor.cpp b/src/plugins/qmljseditor/qmljseditor.cpp
index 19c3d441dd1ff7f670568d2d47535290c253eb31..786d6e76418fb78ac1bdaca8b7230d2f384fb56e 100644
--- a/src/plugins/qmljseditor/qmljseditor.cpp
+++ b/src/plugins/qmljseditor/qmljseditor.cpp
@@ -910,10 +910,26 @@ TextEditor::BaseTextEditor::Link QmlJSTextEditor::findLinkAt(const QTextCursor &
 
     AST::Node *node = semanticInfo.nodeUnderCursor(cursorPosition);
 
+    Interpreter::Engine interp;
+    Interpreter::Context context(&interp);
+    context.build(semanticInfo.declaringMember(cursorPosition), semanticInfo.document, semanticInfo.snapshot);
+
+    Check check(&context);
+    const Interpreter::Value *value = check.reference(node);
+    QString fileName;
+    int line = 0, column = 0;
+
+    if (! (value && value->getSourceLocation(&fileName, &line, &column)))
+        return Link();
+
+    Link link;
+    link.fileName = fileName;
+    link.line = line;
+    link.column = column - 1; // adjust the column
+
     if (AST::UiQualifiedId *q = AST::cast<AST::UiQualifiedId *>(node)) {
         for (AST::UiQualifiedId *tail = q; tail; tail = tail->next) {
             if (! tail->next && cursorPosition <= tail->identifierToken.end()) {
-                Link link;
                 link.begin = tail->identifierToken.begin();
                 link.end = tail->identifierToken.end();
                 return link;
@@ -921,13 +937,11 @@ TextEditor::BaseTextEditor::Link QmlJSTextEditor::findLinkAt(const QTextCursor &
         }
 
     } else if (AST::IdentifierExpression *id = AST::cast<AST::IdentifierExpression *>(node)) {
-        Link link;
         link.begin = id->firstSourceLocation().begin();
         link.end = id->lastSourceLocation().end();
         return link;
 
     } else if (AST::FieldMemberExpression *mem = AST::cast<AST::FieldMemberExpression *>(node)) {
-        Link link;
         link.begin = mem->lastSourceLocation().begin();
         link.end = mem->lastSourceLocation().end();
         return link;
@@ -936,6 +950,11 @@ TextEditor::BaseTextEditor::Link QmlJSTextEditor::findLinkAt(const QTextCursor &
     return Link();
 }
 
+void QmlJSTextEditor::followSymbolUnderCursor()
+{
+    openLink(findLinkAt(textCursor()));
+}
+
 void QmlJSTextEditor::contextMenuEvent(QContextMenuEvent *e)
 {
     QMenu *menu = new QMenu();
diff --git a/src/plugins/qmljseditor/qmljseditor.h b/src/plugins/qmljseditor/qmljseditor.h
index c332cc66d698165b7256f1b7552588737fe0dd0f..da3458269cc968a8bf816351195329450167ee42 100644
--- a/src/plugins/qmljseditor/qmljseditor.h
+++ b/src/plugins/qmljseditor/qmljseditor.h
@@ -135,6 +135,7 @@ public:
     int documentRevision() const;
 
 public slots:
+    void followSymbolUnderCursor();
     virtual void setFontSettings(const TextEditor::FontSettings &);
 
 private slots:
diff --git a/src/plugins/qmljseditor/qmljseditorconstants.h b/src/plugins/qmljseditor/qmljseditorconstants.h
index 7996a6c9f96e4a546ffdc59dc7b4cbf012b9adab..8a9a99d7eb03687a090761e9d260e21b83dc6d1c 100644
--- a/src/plugins/qmljseditor/qmljseditorconstants.h
+++ b/src/plugins/qmljseditor/qmljseditorconstants.h
@@ -41,6 +41,8 @@ const char * const C_QMLJSEDITOR_ID = "QMLProjectManager.QMLJSEditor";
 const char * const C_QMLJSEDITOR_DISPLAY_NAME = QT_TRANSLATE_NOOP("OpenWith::Editors", "QMLJS Editor");
 const char * const TASK_INDEX = "QmlJSEditor.TaskIndex";
 
+const char * const FOLLOW_SYMBOL_UNDER_CURSOR = "QmlJSEditor.FollowSymbolUnderCursor";
+
 const char * const QML_MIMETYPE = "application/x-qml";
 const char * const JS_MIMETYPE = "application/javascript";
 
diff --git a/src/plugins/qmljseditor/qmljseditorplugin.cpp b/src/plugins/qmljseditor/qmljseditorplugin.cpp
index 894c5745073e27d35b344859c8a822f2aeecb2a3..7df0321ea7e57f2e718637d0e938f0e892834991 100644
--- a/src/plugins/qmljseditor/qmljseditorplugin.cpp
+++ b/src/plugins/qmljseditor/qmljseditorplugin.cpp
@@ -43,6 +43,7 @@
 #include <coreplugin/mimedatabase.h>
 #include <coreplugin/uniqueidmanager.h>
 #include <coreplugin/actionmanager/actionmanager.h>
+#include <coreplugin/editormanager/editormanager.h>
 #include <extensionsystem/pluginmanager.h>
 #include <texteditor/fontsettings.h>
 #include <texteditor/storagesettings.h>
@@ -114,9 +115,19 @@ bool QmlJSEditorPlugin::initialize(const QStringList & /*arguments*/, QString *e
     m_actionHandler->initializeActions();
 
     Core::ActionManager *am =  core->actionManager();
-    Core::ActionContainer *contextMenu= am->createMenu(QmlJSEditor::Constants::M_CONTEXT);
-    Core::Command *cmd = am->command(TextEditor::Constants::AUTO_INDENT_SELECTION);
+    Core::ActionContainer *contextMenu = am->createMenu(QmlJSEditor::Constants::M_CONTEXT);
+
+    Core::Command *cmd = 0;
+
+    QAction *followSymbolUnderCursorAction = new QAction(tr("Follow Symbol Under Cursor"), this);
+    cmd = am->registerAction(followSymbolUnderCursorAction, Constants::FOLLOW_SYMBOL_UNDER_CURSOR, context);
+    cmd->setDefaultKeySequence(QKeySequence(Qt::Key_F2));
+    connect(followSymbolUnderCursorAction, SIGNAL(triggered()), this, SLOT(followSymbolUnderCursor()));
     contextMenu->addAction(cmd);
+
+    cmd = am->command(TextEditor::Constants::AUTO_INDENT_SELECTION);
+    contextMenu->addAction(cmd);
+
     cmd = am->command(TextEditor::Constants::UN_COMMENT_SELECTION);
     contextMenu->addAction(cmd);
 
@@ -177,4 +188,12 @@ void QmlJSEditorPlugin::initializeEditor(QmlJSEditor::Internal::QmlJSTextEditor
             TextEditor::Internal::CompletionSupport::instance(), SLOT(autoComplete(TextEditor::ITextEditable*, bool)));
 }
 
+void QmlJSEditorPlugin::followSymbolUnderCursor()
+{
+    Core::EditorManager *em = Core::EditorManager::instance();
+
+    if (QmlJSTextEditor *editor = qobject_cast<QmlJSTextEditor*>(em->currentEditor()->widget()))
+        editor->followSymbolUnderCursor();
+}
+
 Q_EXPORT_PLUGIN(QmlJSEditorPlugin)
diff --git a/src/plugins/qmljseditor/qmljseditorplugin.h b/src/plugins/qmljseditor/qmljseditorplugin.h
index 660b118903be90d7e54016373de1e3276e0f48a8..700842898b60fd88a169fdcb0cf6b2a0af27ae63 100644
--- a/src/plugins/qmljseditor/qmljseditorplugin.h
+++ b/src/plugins/qmljseditor/qmljseditorplugin.h
@@ -64,6 +64,9 @@ public:
 
     void initializeEditor(QmlJSTextEditor *editor);
 
+public Q_SLOTS:
+    void followSymbolUnderCursor();
+
 private:
     static QmlJSEditorPlugin *m_instance;