diff --git a/src/plugins/qmldesigner/designercore/model/basetexteditmodifier.cpp b/src/plugins/qmldesigner/designercore/model/basetexteditmodifier.cpp
index 113ee3b471e8964113639a2f3bf48b60e6578ab8..7575d7dcee2ea06adfb33a251c9f5c364ff8a078 100644
--- a/src/plugins/qmldesigner/designercore/model/basetexteditmodifier.cpp
+++ b/src/plugins/qmldesigner/designercore/model/basetexteditmodifier.cpp
@@ -70,7 +70,7 @@ int BaseTextEditModifier::indentDepth() const
 
 bool BaseTextEditModifier::renameId(const QString &oldId, const QString &newId)
 {
-    if (QmlJSEditor::Internal::QmlJSTextEditor *qmljse = qobject_cast<QmlJSEditor::Internal::QmlJSTextEditor*>(plainTextEdit())) {
+    if (QmlJSEditor::QmlJSTextEditor *qmljse = qobject_cast<QmlJSEditor::QmlJSTextEditor*>(plainTextEdit())) {
         qmljse->renameId(oldId, newId);
         return true;
     } else {
diff --git a/src/plugins/qmljseditor/qmljseditor.cpp b/src/plugins/qmljseditor/qmljseditor.cpp
index 54cf860b63545c511f7ab9919c2cc3793a9015f7..f399b32ed0e654f402170b356ad896aad18909e4 100644
--- a/src/plugins/qmljseditor/qmljseditor.cpp
+++ b/src/plugins/qmljseditor/qmljseditor.cpp
@@ -28,6 +28,7 @@
 **************************************************************************/
 
 #include "qmljseditor.h"
+#include "qmljseditoreditable.h"
 #include "qmljseditorconstants.h"
 #include "qmljshighlighter.h"
 #include "qmljseditorplugin.h"
@@ -36,13 +37,12 @@
 #include "qmljsquickfix.h"
 #include "qmloutlinemodel.h"
 #include "qmljsfindreferences.h"
+#include "qmljssemantichighlighter.h"
 
 #include <qmljs/qmljsbind.h>
-#include <qmljs/qmljscheck.h>
 #include <qmljs/qmljsdocument.h>
 #include <qmljs/qmljsicontextpane.h>
 #include <qmljs/qmljslookupcontext.h>
-#include <qmljs/qmljslink.h>
 #include <qmljs/parser/qmljsastvisitor_p.h>
 #include <qmljs/parser/qmljsast_p.h>
 #include <qmljs/parser/qmljsengine_p.h>
@@ -52,9 +52,6 @@
 #include <coreplugin/actionmanager/command.h>
 #include <coreplugin/editormanager/editormanager.h>
 #include <coreplugin/icore.h>
-#include <coreplugin/coreconstants.h>
-#include <coreplugin/modemanager.h>
-#include <coreplugin/designmode.h>
 #include <coreplugin/mimedatabase.h>
 #include <extensionsystem/pluginmanager.h>
 #include <texteditor/basetextdocument.h>
@@ -89,6 +86,7 @@ enum {
 
 using namespace QmlJS;
 using namespace QmlJS::AST;
+using namespace QmlJSEditor;
 using namespace QmlJSEditor::Internal;
 
 static int blockStartState(const QTextBlock &block)
@@ -628,51 +626,6 @@ int SemanticInfo::revision() const
     return 0;
 }
 
-QmlJSEditorEditable::QmlJSEditorEditable(QmlJSTextEditor *editor)
-    : BaseTextEditorEditable(editor)
-{
-    m_context.add(QmlJSEditor::Constants::C_QMLJSEDITOR_ID);
-    m_context.add(TextEditor::Constants::C_TEXTEDITOR);
-}
-
-// Use preferred mode from Bauhaus settings
-static bool openInDesignMode()
-{
-    static bool bauhausDetected = false;
-    static bool bauhausPresent = false;
-    // Check if Bauhaus is loaded, that is, a Design mode widget is
-    // registered for the QML mime type.
-    if (!bauhausDetected) {
-        if (const Core::IMode *dm = Core::ModeManager::instance()->mode(QLatin1String(Core::Constants::MODE_DESIGN)))
-            if (const Core::DesignMode *designMode = qobject_cast<const Core::DesignMode *>(dm))
-                bauhausPresent = designMode->registeredMimeTypes().contains(QLatin1String(QmlJSEditor::Constants::QML_MIMETYPE));
-        bauhausDetected =  true;
-    }
-    if (!bauhausPresent)
-        return false;
-
-    return bool(QmlDesigner::Constants::QML_OPENDESIGNMODE_DEFAULT);
-}
-
-QString QmlJSEditorEditable::preferredModeType() const
-{
-    Core::ModeManager *modeManager = Core::ModeManager::instance();
-    if (modeManager->currentMode()
-            && (modeManager->currentMode()->type() == Core::Constants::MODE_DESIGN_TYPE
-                || modeManager->currentMode()->type() == Core::Constants::MODE_EDIT_TYPE))
-    {
-        return modeManager->currentMode()->type();
-    }
-
-    // if we are in other mode than edit or design, use the hard-coded default.
-    // because the editor opening decision is modal, it would be confusing to
-    // have the user also access to this failsafe setting.
-    if (editor()->mimeType() == QLatin1String(QmlJSEditor::Constants::QML_MIMETYPE)
-        && openInDesignMode())
-        return QLatin1String(Core::Constants::MODE_DESIGN_TYPE);
-    return QString();
-}
-
 QmlJSTextEditor::QmlJSTextEditor(QWidget *parent) :
     TextEditor::BaseTextEditor(parent),
     m_outlineCombo(0),
@@ -682,7 +635,7 @@ QmlJSTextEditor::QmlJSTextEditor(QWidget *parent) :
     m_updateSelectedElements(false),
     m_findReferences(new FindReferences(this))
 {
-    qRegisterMetaType<QmlJSEditor::Internal::SemanticInfo>("QmlJSEditor::Internal::SemanticInfo");
+    qRegisterMetaType<QmlJSEditor::SemanticInfo>("QmlJSEditor::SemanticInfo");
 
     m_semanticHighlighter = new SemanticHighlighter(this);
     m_semanticHighlighter->start();
@@ -748,8 +701,8 @@ QmlJSTextEditor::QmlJSTextEditor(QWidget *parent) :
         connect(this->document(), SIGNAL(modificationChanged(bool)), this, SLOT(modificationChanged(bool)));
     }
 
-    connect(m_semanticHighlighter, SIGNAL(changed(QmlJSEditor::Internal::SemanticInfo)),
-            this, SLOT(updateSemanticInfo(QmlJSEditor::Internal::SemanticInfo)));
+    connect(m_semanticHighlighter, SIGNAL(changed(QmlJSEditor::SemanticInfo)),
+            this, SLOT(updateSemanticInfo(QmlJSEditor::SemanticInfo)));
 
     connect(this, SIGNAL(refactorMarkerClicked(TextEditor::RefactorMarker)),
             SLOT(onRefactorMarkerClicked(TextEditor::RefactorMarker)));
@@ -885,7 +838,7 @@ void QmlJSTextEditor::onDocumentUpdated(QmlJS::Document::Ptr doc)
     if (doc->ast()) {
         // got a correctly parsed (or recovered) file.
 
-        const SemanticHighlighter::Source source = currentSource(/*force = */ true);
+        const SemanticHighlighterSource source = currentSource(/*force = */ true);
         m_semanticHighlighter->rehighlight(source);
     } else {
         // show parsing errors
@@ -1857,7 +1810,7 @@ bool QmlJSTextEditor::hideContextPane()
     return b;
 }
 
-SemanticHighlighter::Source QmlJSTextEditor::currentSource(bool force)
+SemanticHighlighterSource QmlJSTextEditor::currentSource(bool force)
 {
     int line = 0, column = 0;
     convertPosition(position(), &line, &column);
@@ -1870,119 +1823,8 @@ SemanticHighlighter::Source QmlJSTextEditor::currentSource(bool force)
         code = toPlainText(); // get the source code only when needed.
 
     const unsigned revision = document()->revision();
-    SemanticHighlighter::Source source(snapshot, fileName, code,
+    SemanticHighlighterSource source(snapshot, fileName, code,
                                        line, column, revision);
     source.force = force;
     return source;
 }
-
-SemanticHighlighter::SemanticHighlighter(QObject *parent)
-        : QThread(parent),
-          m_done(false),
-          m_modelManager(0)
-{
-}
-
-SemanticHighlighter::~SemanticHighlighter()
-{
-}
-
-void SemanticHighlighter::abort()
-{
-    QMutexLocker locker(&m_mutex);
-    m_done = true;
-    m_condition.wakeOne();
-}
-
-void SemanticHighlighter::rehighlight(const Source &source)
-{
-    QMutexLocker locker(&m_mutex);
-    m_source = source;
-    m_condition.wakeOne();
-}
-
-bool SemanticHighlighter::isOutdated()
-{
-    QMutexLocker locker(&m_mutex);
-    const bool outdated = ! m_source.fileName.isEmpty() || m_done;
-    return outdated;
-}
-
-void SemanticHighlighter::run()
-{
-    setPriority(QThread::LowestPriority);
-
-    forever {
-        m_mutex.lock();
-
-        while (! (m_done || ! m_source.fileName.isEmpty()))
-            m_condition.wait(&m_mutex);
-
-        const bool done = m_done;
-        const Source source = m_source;
-        m_source.clear();
-
-        m_mutex.unlock();
-
-        if (done)
-            break;
-
-        const SemanticInfo info = semanticInfo(source);
-
-        if (! isOutdated()) {
-            m_mutex.lock();
-            m_lastSemanticInfo = info;
-            m_mutex.unlock();
-
-            emit changed(info);
-        }
-    }
-}
-
-SemanticInfo SemanticHighlighter::semanticInfo(const Source &source)
-{
-    m_mutex.lock();
-    const int revision = m_lastSemanticInfo.revision();
-    m_mutex.unlock();
-
-    Snapshot snapshot;
-    Document::Ptr doc;
-
-    if (! source.force && revision == source.revision) {
-        m_mutex.lock();
-        snapshot = m_lastSemanticInfo.snapshot;
-        doc = m_lastSemanticInfo.document;
-        m_mutex.unlock();
-    }
-
-    if (! doc) {
-        snapshot = source.snapshot;
-        doc = snapshot.documentFromSource(source.code, source.fileName);
-        doc->setEditorRevision(source.revision);
-        doc->parse();
-        snapshot.insert(doc);
-    }
-
-    SemanticInfo semanticInfo;
-    semanticInfo.snapshot = snapshot;
-    semanticInfo.document = doc;
-
-    Interpreter::Context *ctx = new Interpreter::Context;
-    Link link(ctx, doc, snapshot, ModelManagerInterface::instance()->importPaths());
-    semanticInfo.m_context = QSharedPointer<const QmlJS::Interpreter::Context>(ctx);
-    semanticInfo.semanticMessages = link.diagnosticMessages();
-
-    QStringList importPaths;
-    if (m_modelManager)
-        importPaths = m_modelManager->importPaths();
-    Check checker(doc, snapshot, ctx);
-    semanticInfo.semanticMessages.append(checker());
-
-    return semanticInfo;
-}
-
-void SemanticHighlighter::setModelManager(QmlJS::ModelManagerInterface *modelManager)
-{
-    m_modelManager = modelManager;
-}
-
diff --git a/src/plugins/qmljseditor/qmljseditor.h b/src/plugins/qmljseditor/qmljseditor.h
index 4c625cf60c6c0dc7808e171e7b1e1dbf5efe3989..f22336a4dbd74c78099c98a55b718e11f2fbcc34 100644
--- a/src/plugins/qmljseditor/qmljseditor.h
+++ b/src/plugins/qmljseditor/qmljseditor.h
@@ -38,10 +38,8 @@
 #include <texteditor/basetexteditor.h>
 #include <texteditor/quickfix.h>
 
-#include <QtCore/QWaitCondition>
+#include <QtCore/QSharedPointer>
 #include <QtCore/QModelIndex>
-#include <QtCore/QMutex>
-#include <QtCore/QThread>
 
 QT_BEGIN_NAMESPACE
 class QComboBox;
@@ -62,34 +60,16 @@ namespace QmlJS {
     The top-level namespace of the QmlJSEditor plug-in.
  */
 namespace QmlJSEditor {
-class Highlighter;
 class FindReferences;
 
 namespace Internal {
-
-class QmlJSTextEditor;
 class QmlOutlineModel;
+class QmlJSEditorEditable;
+class SemanticHighlighter;
+struct SemanticHighlighterSource;
+} // namespace Internal
 
-class QmlJSEditorEditable : public TextEditor::BaseTextEditorEditable
-{
-    Q_OBJECT
-
-public:
-    QmlJSEditorEditable(QmlJSTextEditor *);
-    Core::Context context() const;
-
-    bool duplicateSupported() const { return true; }
-    Core::IEditor *duplicate(QWidget *parent);
-    QString id() const;
-    bool isTemporary() const { return false; }
-    virtual bool open(const QString & fileName);
-    virtual QString preferredModeType() const;
-
-private:
-    Core::Context m_context;
-};
-
-struct Declaration
+struct QMLJSEDITOR_EXPORT Declaration
 {
     QString text;
     int startLine;
@@ -105,7 +85,7 @@ struct Declaration
     { }
 };
 
-class Range
+class QMLJSEDITOR_EXPORT Range
 {
 public:
     Range(): ast(0) {}
@@ -116,8 +96,6 @@ public: // attributes
     QTextCursor end;
 };
 
-class SemanticHighlighter;
-
 class QMLJSEDITOR_EXPORT SemanticInfo
 {
 public:
@@ -152,75 +130,7 @@ public: // attributes
 private:
     QSharedPointer<const QmlJS::Interpreter::Context> m_context;
 
-    friend class SemanticHighlighter;
-};
-
-class SemanticHighlighter: public QThread
-{
-    Q_OBJECT
-
-public:
-    SemanticHighlighter(QObject *parent = 0);
-    virtual ~SemanticHighlighter();
-
-    void abort();
-
-    struct Source
-    {
-        QmlJS::Snapshot snapshot;
-        QString fileName;
-        QString code;
-        int line;
-        int column;
-        int revision;
-        bool force;
-
-        Source()
-            : line(0), column(0), revision(0), force(false)
-        { }
-
-        Source(const QmlJS::Snapshot &snapshot,
-               const QString &fileName,
-               const QString &code,
-               int line, int column,
-               int revision)
-            : snapshot(snapshot), fileName(fileName),
-              code(code), line(line), column(column),
-              revision(revision), force(false)
-        { }
-
-        void clear()
-        {
-            snapshot = QmlJS::Snapshot();
-            fileName.clear();
-            code.clear();
-            line = 0;
-            column = 0;
-            revision = 0;
-            force = false;
-        }
-    };
-
-    void rehighlight(const Source &source);
-    void setModelManager(QmlJS::ModelManagerInterface *modelManager);
-
-Q_SIGNALS:
-    void changed(const QmlJSEditor::Internal::SemanticInfo &semanticInfo);
-
-protected:
-    virtual void run();
-
-private:
-    bool isOutdated();
-    SemanticInfo semanticInfo(const Source &source);
-
-private:
-    QMutex m_mutex;
-    QWaitCondition m_condition;
-    bool m_done;
-    Source m_source;
-    SemanticInfo m_lastSemanticInfo;
-    QmlJS::ModelManagerInterface *m_modelManager;
+    friend class Internal::SemanticHighlighter;
 };
 
 class QMLJSEDITOR_EXPORT QmlJSTextEditor : public TextEditor::BaseTextEditor
@@ -237,7 +147,7 @@ public:
     int editorRevision() const;
     bool isOutdated() const;
 
-    QmlOutlineModel *outlineModel() const;
+    Internal::QmlOutlineModel *outlineModel() const;
     QModelIndex outlineModelIndex();
 
     bool updateSelectedElements() const;
@@ -276,7 +186,7 @@ private slots:
 
     void semanticRehighlight();
     void forceSemanticRehighlight();
-    void updateSemanticInfo(const QmlJSEditor::Internal::SemanticInfo &semanticInfo);
+    void updateSemanticInfo(const QmlJSEditor::SemanticInfo &semanticInfo);
     void onCursorPositionChanged();
     void onRefactorMarkerClicked(const TextEditor::RefactorMarker &marker);
 
@@ -289,7 +199,7 @@ protected:
     void resizeEvent(QResizeEvent *event);
     void scrollContentsBy(int dx, int dy);
     TextEditor::BaseTextEditorEditable *createEditableInterface();
-    void createToolBar(QmlJSEditorEditable *editable);
+    void createToolBar(Internal::QmlJSEditorEditable *editable);
     TextEditor::BaseTextEditor::Link findLinkAt(const QTextCursor &cursor, bool resolveTarget = true);
 
     //// brace matching
@@ -307,7 +217,7 @@ private:
     void setSelectedElements();
     QString wordUnderCursor() const;
 
-    SemanticHighlighter::Source currentSource(bool force = false);
+    Internal::SemanticHighlighterSource currentSource(bool force = false);
     QModelIndex indexForPosition(unsigned cursorPosition, const QModelIndex &rootIndex = QModelIndex()) const;
     bool hideContextPane();
 
@@ -320,14 +230,14 @@ private:
     QTimer *m_updateOutlineIndexTimer;
     QTimer *m_cursorPositionTimer;
     QComboBox *m_outlineCombo;
-    QmlOutlineModel *m_outlineModel;
+    Internal::QmlOutlineModel *m_outlineModel;
     QModelIndex m_outlineModelIndex;
     QmlJS::ModelManagerInterface *m_modelManager;
     QTextCharFormat m_occurrencesFormat;
     QTextCharFormat m_occurrencesUnusedFormat;
     QTextCharFormat m_occurrenceRenameFormat;
 
-    SemanticHighlighter *m_semanticHighlighter;
+    Internal::SemanticHighlighter *m_semanticHighlighter;
     SemanticInfo m_semanticInfo;
 
     QList<TextEditor::QuickFixOperation::Ptr> m_quickFixes;
@@ -339,7 +249,6 @@ private:
     FindReferences *m_findReferences;
 };
 
-} // namespace Internal
 } // namespace QmlJSEditor
 
 #endif // QMLJSEDITOR_H
diff --git a/src/plugins/qmljseditor/qmljseditor.pro b/src/plugins/qmljseditor/qmljseditor.pro
index 8a6c725379cc8819d7bcb6d21fbd3ae5b6613e01..2c3c302e2953e2ecf3708f64acba0c179210c49f 100644
--- a/src/plugins/qmljseditor/qmljseditor.pro
+++ b/src/plugins/qmljseditor/qmljseditor.pro
@@ -32,7 +32,9 @@ HEADERS += \
     quicktoolbarsettingspage.h \
     quicktoolbar.h \
     qmljscomponentnamedialog.h \
-    qmljsfindreferences.h
+    qmljsfindreferences.h \
+    qmljseditoreditable.h \
+    qmljssemantichighlighter.h
 
 SOURCES += \
     qmljscodecompletion.cpp \
@@ -58,7 +60,9 @@ SOURCES += \
     quicktoolbarsettingspage.cpp \
     quicktoolbar.cpp \
     qmljscomponentnamedialog.cpp \
-    qmljsfindreferences.cpp
+    qmljsfindreferences.cpp \
+    qmljseditoreditable.cpp \
+    qmljssemantichighlighter.cpp
 
 RESOURCES += qmljseditor.qrc
 OTHER_FILES += QmlJSEditor.pluginspec QmlJSEditor.mimetypes.xml
diff --git a/src/plugins/qmljseditor/qmljseditoreditable.cpp b/src/plugins/qmljseditor/qmljseditoreditable.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0013fc9277b7eab6d2c58a4026549944d63da9df
--- /dev/null
+++ b/src/plugins/qmljseditor/qmljseditoreditable.cpp
@@ -0,0 +1,92 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "qmljseditoreditable.h"
+#include "qmljseditor.h"
+#include "qmljseditorconstants.h"
+
+#include <texteditor/texteditorconstants.h>
+#include <qmldesigner/qmldesignerconstants.h>
+
+#include <coreplugin/mimedatabase.h>
+#include <coreplugin/icore.h>
+#include <coreplugin/designmode.h>
+#include <coreplugin/modemanager.h>
+#include <coreplugin/coreconstants.h>
+
+namespace QmlJSEditor {
+namespace Internal {
+
+QmlJSEditorEditable::QmlJSEditorEditable(QmlJSTextEditor *editor)
+    : BaseTextEditorEditable(editor)
+{
+    m_context.add(QmlJSEditor::Constants::C_QMLJSEDITOR_ID);
+    m_context.add(TextEditor::Constants::C_TEXTEDITOR);
+}
+
+// Use preferred mode from Bauhaus settings
+static bool openInDesignMode()
+{
+    static bool bauhausDetected = false;
+    static bool bauhausPresent = false;
+    // Check if Bauhaus is loaded, that is, a Design mode widget is
+    // registered for the QML mime type.
+    if (!bauhausDetected) {
+        if (const Core::IMode *dm = Core::ModeManager::instance()->mode(QLatin1String(Core::Constants::MODE_DESIGN)))
+            if (const Core::DesignMode *designMode = qobject_cast<const Core::DesignMode *>(dm))
+                bauhausPresent = designMode->registeredMimeTypes().contains(QLatin1String(QmlJSEditor::Constants::QML_MIMETYPE));
+        bauhausDetected =  true;
+    }
+    if (!bauhausPresent)
+        return false;
+
+    return bool(QmlDesigner::Constants::QML_OPENDESIGNMODE_DEFAULT);
+}
+
+QString QmlJSEditorEditable::preferredModeType() const
+{
+    Core::ModeManager *modeManager = Core::ModeManager::instance();
+    if (modeManager->currentMode()
+            && (modeManager->currentMode()->type() == Core::Constants::MODE_DESIGN_TYPE
+                || modeManager->currentMode()->type() == Core::Constants::MODE_EDIT_TYPE))
+    {
+        return modeManager->currentMode()->type();
+    }
+
+    // if we are in other mode than edit or design, use the hard-coded default.
+    // because the editor opening decision is modal, it would be confusing to
+    // have the user also access to this failsafe setting.
+    if (editor()->mimeType() == QLatin1String(QmlJSEditor::Constants::QML_MIMETYPE)
+        && openInDesignMode())
+        return QLatin1String(Core::Constants::MODE_DESIGN_TYPE);
+    return QString();
+}
+
+} // namespace Internal
+} // namespace QmlJSEditor
diff --git a/src/plugins/qmljseditor/qmljseditoreditable.h b/src/plugins/qmljseditor/qmljseditoreditable.h
new file mode 100644
index 0000000000000000000000000000000000000000..86253b5c9956e23a39b809d7170f630abc069eb5
--- /dev/null
+++ b/src/plugins/qmljseditor/qmljseditoreditable.h
@@ -0,0 +1,62 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef QMLJSEDITOREDITABLE_H
+#define QMLJSEDITOREDITABLE_H
+
+#include <texteditor/basetexteditor.h>
+
+namespace QmlJSEditor {
+class QmlJSTextEditor;
+
+namespace Internal {
+
+class QmlJSEditorEditable : public TextEditor::BaseTextEditorEditable
+{
+    Q_OBJECT
+
+public:
+    explicit QmlJSEditorEditable(QmlJSTextEditor *);
+    Core::Context context() const;
+
+    bool duplicateSupported() const { return true; }
+    Core::IEditor *duplicate(QWidget *parent);
+    QString id() const;
+    bool isTemporary() const { return false; }
+    virtual bool open(const QString & fileName);
+    virtual QString preferredModeType() const;
+
+private:
+    Core::Context m_context;
+};
+
+} // namespace Internal
+} // namespace QmlJSEditor
+
+#endif // QMLJSEDITOREDITABLE_H
diff --git a/src/plugins/qmljseditor/qmljseditorfactory.cpp b/src/plugins/qmljseditor/qmljseditorfactory.cpp
index 61d30e9247e97987b1061574c8db808706d0dfa9..dbdafac49758d4901c376682875408003d63ffc3 100644
--- a/src/plugins/qmljseditor/qmljseditorfactory.cpp
+++ b/src/plugins/qmljseditor/qmljseditorfactory.cpp
@@ -28,6 +28,7 @@
 **************************************************************************/
 
 #include "qmljseditorfactory.h"
+#include "qmljseditoreditable.h"
 #include "qmljseditor.h"
 #include "qmljseditoractionhandler.h"
 #include "qmljseditorconstants.h"
@@ -124,7 +125,7 @@ Core::IEditor *QmlJSEditorFactory::createEditor(QWidget *parent)
                      SLOT(updateEditorInfoBar(Core::IEditor*)));
         }
     }
-    QmlJSTextEditor *rc = new QmlJSTextEditor(parent);
+    QmlJSEditor::QmlJSTextEditor *rc = new QmlJSEditor::QmlJSTextEditor(parent);
     QmlJSEditorPlugin::instance()->initializeEditor(rc);
     return rc->editableInterface();
 }
diff --git a/src/plugins/qmljseditor/qmljseditorplugin.cpp b/src/plugins/qmljseditor/qmljseditorplugin.cpp
index 0b1cc3f39a718fea0e68f743b237fba9a35ce1d1..4aae75e28a59fdfd52561ee8382c481b6d225854 100644
--- a/src/plugins/qmljseditor/qmljseditorplugin.cpp
+++ b/src/plugins/qmljseditor/qmljseditorplugin.cpp
@@ -247,7 +247,7 @@ ExtensionSystem::IPlugin::ShutdownFlag QmlJSEditorPlugin::aboutToShutdown()
     return IPlugin::aboutToShutdown();
 }
 
-void QmlJSEditorPlugin::initializeEditor(QmlJSEditor::Internal::QmlJSTextEditor *editor)
+void QmlJSEditorPlugin::initializeEditor(QmlJSEditor::QmlJSTextEditor *editor)
 {
     QTC_ASSERT(m_instance, /**/);
 
diff --git a/src/plugins/qmljseditor/qmljseditorplugin.h b/src/plugins/qmljseditor/qmljseditorplugin.h
index b45c867dbc76afe3a9e68d7e58885fd193dca9d0..786a2f2675527b680f32f7bc45b6987208039420 100644
--- a/src/plugins/qmljseditor/qmljseditorplugin.h
+++ b/src/plugins/qmljseditor/qmljseditorplugin.h
@@ -58,11 +58,11 @@ namespace QmlJS {
 namespace QmlJSEditor {
 
 class QmlFileWizard;
+class QmlJSTextEditor;
 
 namespace Internal {
 
 class QmlJSEditorFactory;
-class QmlJSTextEditor;
 class QmlJSPreviewRunner;
 class QmlJSQuickFixCollector;
 class QmlTaskManager;
@@ -85,7 +85,7 @@ public:
 
     QmlJSQuickFixCollector *quickFixCollector() const;
 
-    void initializeEditor(QmlJSTextEditor *editor);
+    void initializeEditor(QmlJSEditor::QmlJSTextEditor *editor);
 
 public Q_SLOTS:
     void followSymbolUnderCursor();
diff --git a/src/plugins/qmljseditor/qmljshoverhandler.cpp b/src/plugins/qmljseditor/qmljshoverhandler.cpp
index 5e7f24ddf0cf1a4343f5017b4a3e7e2bbea0ac7f..b2ac1eb457410e55d1cd78f7ead1b2db3da58ac2 100644
--- a/src/plugins/qmljseditor/qmljshoverhandler.cpp
+++ b/src/plugins/qmljseditor/qmljshoverhandler.cpp
@@ -28,6 +28,7 @@
 **************************************************************************/
 
 #include "qmljseditor.h"
+#include "qmljseditoreditable.h"
 #include "qmlexpressionundercursor.h"
 #include "qmljshoverhandler.h"
 
@@ -104,12 +105,12 @@ void HoverHandler::identifyMatch(TextEditor::ITextEditor *editor, int pos)
     if (!m_modelManager)
         return;
 
-    QmlJSTextEditor *qmlEditor = qobject_cast<QmlJSTextEditor *>(editor->widget());
+    QmlJSEditor::QmlJSTextEditor *qmlEditor = qobject_cast<QmlJSEditor::QmlJSTextEditor *>(editor->widget());
     if (!qmlEditor)
         return;
 
     if (!matchDiagnosticMessage(qmlEditor, pos)) {
-        const SemanticInfo &semanticInfo = qmlEditor->semanticInfo();
+        const QmlJSEditor::SemanticInfo &semanticInfo = qmlEditor->semanticInfo();
         if (! semanticInfo.isValid() || semanticInfo.revision() != qmlEditor->editorRevision())
             return;
 
@@ -129,7 +130,7 @@ void HoverHandler::identifyMatch(TextEditor::ITextEditor *editor, int pos)
     }
 }
 
-bool HoverHandler::matchDiagnosticMessage(QmlJSTextEditor *qmlEditor, int pos)
+bool HoverHandler::matchDiagnosticMessage(QmlJSEditor::QmlJSTextEditor *qmlEditor, int pos)
 {
     foreach (const QTextEdit::ExtraSelection &sel,
              qmlEditor->extraSelections(TextEditor::BaseTextEditor::CodeWarningsSelection)) {
diff --git a/src/plugins/qmljseditor/qmljshoverhandler.h b/src/plugins/qmljseditor/qmljshoverhandler.h
index 77e967e39dff915a6ae0bcd247b9941d9ebab34f..ea59ccdb79f1f6ea6867ebca6b051bfe973d5eec 100644
--- a/src/plugins/qmljseditor/qmljshoverhandler.h
+++ b/src/plugins/qmljseditor/qmljshoverhandler.h
@@ -49,10 +49,11 @@ class ITextEditor;
 }
 
 namespace QmlJSEditor {
+class QmlJSTextEditor;
+
 namespace Internal {
 
 class SemanticInfo;
-class QmlJSTextEditor;
 
 class HoverHandler : public TextEditor::BaseHoverHandler
 {
@@ -67,7 +68,7 @@ private:
     virtual void identifyMatch(TextEditor::ITextEditor *editor, int pos);
     virtual void operateTooltip(TextEditor::ITextEditor *editor, const QPoint &point);
 
-    bool matchDiagnosticMessage(QmlJSTextEditor *qmlEditor, int pos);
+    bool matchDiagnosticMessage(QmlJSEditor::QmlJSTextEditor *qmlEditor, int pos);
     bool matchColorItem(const QmlJS::LookupContext::Ptr &lookupContext,
                         const QmlJS::Document::Ptr &qmlDocument,
                         const QList<QmlJS::AST::Node *> &astPath,
diff --git a/src/plugins/qmljseditor/qmljsoutline.cpp b/src/plugins/qmljseditor/qmljsoutline.cpp
index b1465819dee035146e6fad825e419fa154549797..fcfdb885fc77e200a0bb7a03d71b87158720e624 100644
--- a/src/plugins/qmljseditor/qmljsoutline.cpp
+++ b/src/plugins/qmljseditor/qmljsoutline.cpp
@@ -1,5 +1,6 @@
 #include "qmljsoutline.h"
 #include "qmloutlinemodel.h"
+#include "qmljseditoreditable.h"
 #include "qmljsoutlinetreeview.h"
 
 #include <coreplugin/icore.h>
diff --git a/src/plugins/qmljseditor/qmljsquickfix.h b/src/plugins/qmljseditor/qmljsquickfix.h
index 57e6b2521f6868ed357d1551267520fd440d62f6..b316e117e04c04ffc7a4b9b6ef9d9166f0aa7760 100644
--- a/src/plugins/qmljseditor/qmljsquickfix.h
+++ b/src/plugins/qmljseditor/qmljsquickfix.h
@@ -65,7 +65,7 @@ public:
     /// Creates a new state for the given editor.
     QmlJSQuickFixState(TextEditor::BaseTextEditor *editor);
 
-    Internal::SemanticInfo semanticInfo() const;
+    SemanticInfo semanticInfo() const;
 
     /// \returns the snapshot holding the document of the editor.
     QmlJS::Snapshot snapshot() const;
@@ -76,7 +76,7 @@ public:
     const QmlJSRefactoringFile currentFile() const;
 
 private:
-    Internal::SemanticInfo _semanticInfo;
+    SemanticInfo _semanticInfo;
 };
 
 /*!
diff --git a/src/plugins/qmljseditor/qmljssemantichighlighter.cpp b/src/plugins/qmljseditor/qmljssemantichighlighter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0881ee879b93de12905cb8df7b6babbf904a130f
--- /dev/null
+++ b/src/plugins/qmljseditor/qmljssemantichighlighter.cpp
@@ -0,0 +1,152 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "qmljssemantichighlighter.h"
+#include "qmljsmodelmanager.h"
+
+#include <qmljs/qmljsdocument.h>
+#include <qmljs/qmljscheck.h>
+#include <qmljs/qmljsinterpreter.h>
+#include <qmljs/qmljslink.h>
+
+namespace QmlJSEditor {
+namespace Internal {
+
+SemanticHighlighter::SemanticHighlighter(QObject *parent)
+        : QThread(parent),
+          m_done(false),
+          m_modelManager(0)
+{
+}
+
+SemanticHighlighter::~SemanticHighlighter()
+{
+}
+
+void SemanticHighlighter::abort()
+{
+    QMutexLocker locker(&m_mutex);
+    m_done = true;
+    m_condition.wakeOne();
+}
+
+void SemanticHighlighter::rehighlight(const SemanticHighlighterSource &source)
+{
+    QMutexLocker locker(&m_mutex);
+    m_source = source;
+    m_condition.wakeOne();
+}
+
+bool SemanticHighlighter::isOutdated()
+{
+    QMutexLocker locker(&m_mutex);
+    const bool outdated = ! m_source.fileName.isEmpty() || m_done;
+    return outdated;
+}
+
+void SemanticHighlighter::run()
+{
+    setPriority(QThread::LowestPriority);
+
+    forever {
+        m_mutex.lock();
+
+        while (! (m_done || ! m_source.fileName.isEmpty()))
+            m_condition.wait(&m_mutex);
+
+        const bool done = m_done;
+        const SemanticHighlighterSource source = m_source;
+        m_source.clear();
+
+        m_mutex.unlock();
+
+        if (done)
+            break;
+
+        const SemanticInfo info = semanticInfo(source);
+
+        if (! isOutdated()) {
+            m_mutex.lock();
+            m_lastSemanticInfo = info;
+            m_mutex.unlock();
+
+            emit changed(info);
+        }
+    }
+}
+
+SemanticInfo SemanticHighlighter::semanticInfo(const SemanticHighlighterSource &source)
+{
+    m_mutex.lock();
+    const int revision = m_lastSemanticInfo.revision();
+    m_mutex.unlock();
+
+    QmlJS::Snapshot snapshot;
+    QmlJS::Document::Ptr doc;
+
+    if (! source.force && revision == source.revision) {
+        m_mutex.lock();
+        snapshot = m_lastSemanticInfo.snapshot;
+        doc = m_lastSemanticInfo.document;
+        m_mutex.unlock();
+    }
+
+    if (! doc) {
+        snapshot = source.snapshot;
+        doc = snapshot.documentFromSource(source.code, source.fileName);
+        doc->setEditorRevision(source.revision);
+        doc->parse();
+        snapshot.insert(doc);
+    }
+
+    SemanticInfo semanticInfo;
+    semanticInfo.snapshot = snapshot;
+    semanticInfo.document = doc;
+
+    QmlJS::Interpreter::Context *ctx = new QmlJS::Interpreter::Context;
+    QmlJS::Link link(ctx, doc, snapshot, QmlJS::ModelManagerInterface::instance()->importPaths());
+    semanticInfo.m_context = QSharedPointer<const QmlJS::Interpreter::Context>(ctx);
+    semanticInfo.semanticMessages = link.diagnosticMessages();
+
+    QStringList importPaths;
+    if (m_modelManager)
+        importPaths = m_modelManager->importPaths();
+    QmlJS::Check checker(doc, snapshot, ctx);
+    semanticInfo.semanticMessages.append(checker());
+
+    return semanticInfo;
+}
+
+void SemanticHighlighter::setModelManager(QmlJS::ModelManagerInterface *modelManager)
+{
+    m_modelManager = modelManager;
+}
+
+} // namespace Internal
+} // namespace QmlJSEditor
diff --git a/src/plugins/qmljseditor/qmljssemantichighlighter.h b/src/plugins/qmljseditor/qmljssemantichighlighter.h
new file mode 100644
index 0000000000000000000000000000000000000000..dff097ba7f2ad03abbb490599733acbf9c283179
--- /dev/null
+++ b/src/plugins/qmljseditor/qmljssemantichighlighter.h
@@ -0,0 +1,113 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef SEMANTICHIGHLIGHTER_H
+#define SEMANTICHIGHLIGHTER_H
+
+#include "qmljseditor.h"
+
+#include <QtCore/QWaitCondition>
+#include <QtCore/QModelIndex>
+#include <QtCore/QMutex>
+#include <QtCore/QThread>
+
+namespace QmlJSEditor {
+namespace Internal {
+
+struct SemanticHighlighterSource
+{
+    QmlJS::Snapshot snapshot;
+    QString fileName;
+    QString code;
+    int line;
+    int column;
+    int revision;
+    bool force;
+
+    SemanticHighlighterSource()
+        : line(0), column(0), revision(0), force(false)
+    { }
+
+    SemanticHighlighterSource(const QmlJS::Snapshot &snapshot,
+           const QString &fileName,
+           const QString &code,
+           int line, int column,
+           int revision)
+        : snapshot(snapshot), fileName(fileName),
+          code(code), line(line), column(column),
+          revision(revision), force(false)
+    { }
+
+    void clear()
+    {
+        snapshot = QmlJS::Snapshot();
+        fileName.clear();
+        code.clear();
+        line = 0;
+        column = 0;
+        revision = 0;
+        force = false;
+    }
+};
+
+class SemanticHighlighter: public QThread
+{
+    Q_OBJECT
+
+public:
+    SemanticHighlighter(QObject *parent = 0);
+    virtual ~SemanticHighlighter();
+
+    void abort();
+    void rehighlight(const SemanticHighlighterSource &source);
+    void setModelManager(QmlJS::ModelManagerInterface *modelManager);
+
+Q_SIGNALS:
+    void changed(const QmlJSEditor::SemanticInfo &semanticInfo);
+
+protected:
+    virtual void run();
+
+private:
+    bool isOutdated();
+    SemanticInfo semanticInfo(const SemanticHighlighterSource &source);
+
+private:
+    QMutex m_mutex;
+    QWaitCondition m_condition;
+    bool m_done;
+    SemanticHighlighterSource m_source;
+    SemanticInfo m_lastSemanticInfo;
+    QmlJS::ModelManagerInterface *m_modelManager;
+};
+
+} // namespace Internal
+} // namespace QmlJSEditor
+
+#endif // SEMANTICHIGHLIGHTER_H
diff --git a/src/plugins/qmljsinspector/qmljsinspector.cpp b/src/plugins/qmljsinspector/qmljsinspector.cpp
index 997be7ee553529125ef523ce758bb6b6d4dde38c..66c9b4333a664bfb593db10df7c94f113f6da522 100644
--- a/src/plugins/qmljsinspector/qmljsinspector.cpp
+++ b/src/plugins/qmljsinspector/qmljsinspector.cpp
@@ -187,7 +187,7 @@ void InspectorUi::showDebuggerTooltip(const QPoint &mousePos, TextEditor::ITextE
 {
     Q_UNUSED(mousePos);
     if (m_clientProxy && editor->id() == QmlJSEditor::Constants::C_QMLJSEDITOR_ID) {
-        QmlJSEditor::Internal::QmlJSTextEditor *qmlEditor = static_cast<QmlJSEditor::Internal::QmlJSTextEditor*>(editor->widget());
+        QmlJSEditor::QmlJSTextEditor *qmlEditor = static_cast<QmlJSEditor::QmlJSTextEditor*>(editor->widget());
 
         QTextCursor tc(qmlEditor->document());
         tc.setPosition(cursorPos);
diff --git a/src/plugins/qmljsinspector/qmljslivetextpreview.cpp b/src/plugins/qmljsinspector/qmljslivetextpreview.cpp
index 7dca4c4e428717c656e9a9969668cc47ca9f2d83..966ac15e8f098137d3554458d99ff22a890dea61 100644
--- a/src/plugins/qmljsinspector/qmljslivetextpreview.cpp
+++ b/src/plugins/qmljsinspector/qmljslivetextpreview.cpp
@@ -128,7 +128,7 @@ QmlJS::ModelManagerInterface *QmlJSLiveTextPreview::modelManager()
 void QmlJSLiveTextPreview::associateEditor(Core::IEditor *editor)
 {
     if (editor->id() == QmlJSEditor::Constants::C_QMLJSEDITOR_ID) {
-        QmlJSEditor::Internal::QmlJSTextEditor* qmljsEditor = qobject_cast<QmlJSEditor::Internal::QmlJSTextEditor*>(editor->widget());
+        QmlJSEditor::QmlJSTextEditor* qmljsEditor = qobject_cast<QmlJSEditor::QmlJSTextEditor*>(editor->widget());
         if (qmljsEditor && !m_editors.contains(qmljsEditor)) {
             qmljsEditor->setUpdateSelectedElements(true);
             m_editors << qmljsEditor;
@@ -142,7 +142,7 @@ void QmlJSLiveTextPreview::associateEditor(Core::IEditor *editor)
 void QmlJSLiveTextPreview::unassociateEditor(Core::IEditor *oldEditor)
 {
     if (oldEditor && oldEditor->id() == QmlJSEditor::Constants::C_QMLJSEDITOR_ID) {
-        QmlJSEditor::Internal::QmlJSTextEditor* qmljsEditor = qobject_cast<QmlJSEditor::Internal::QmlJSTextEditor*>(oldEditor->widget());
+        QmlJSEditor::QmlJSTextEditor* qmljsEditor = qobject_cast<QmlJSEditor::QmlJSTextEditor*>(oldEditor->widget());
         if (qmljsEditor && m_editors.contains(qmljsEditor)) {
             m_editors.removeOne(qmljsEditor);
             qmljsEditor->setUpdateSelectedElements(false);
@@ -630,12 +630,12 @@ void QmlJSLiveTextPreview::setClientProxy(ClientProxy *clientProxy)
         connect(m_clientProxy.data(), SIGNAL(objectTreeUpdated()),
                    SLOT(updateDebugIds()));
 
-        foreach(QWeakPointer<QmlJSEditor::Internal::QmlJSTextEditor> qmlEditor, m_editors) {
+        foreach(QWeakPointer<QmlJSEditor::QmlJSTextEditor> qmlEditor, m_editors) {
             if (qmlEditor)
                 qmlEditor.data()->setUpdateSelectedElements(true);
         }
     } else {
-        foreach(QWeakPointer<QmlJSEditor::Internal::QmlJSTextEditor> qmlEditor, m_editors) {
+        foreach(QWeakPointer<QmlJSEditor::QmlJSTextEditor> qmlEditor, m_editors) {
             if (qmlEditor)
                 qmlEditor.data()->setUpdateSelectedElements(false);
         }
diff --git a/src/plugins/qmljsinspector/qmljslivetextpreview.h b/src/plugins/qmljsinspector/qmljslivetextpreview.h
index 0681e6e2cba8c1eb3ac0085c8a06748f832f2867..da25d594208e33beb4b68356eda4a49256ba090d 100644
--- a/src/plugins/qmljsinspector/qmljslivetextpreview.h
+++ b/src/plugins/qmljsinspector/qmljslivetextpreview.h
@@ -48,10 +48,8 @@ namespace QmlJS {
 }
 
 namespace QmlJSEditor {
-namespace Internal {
     class QmlJSTextEditor;
 }
-}
 
 namespace QmlJSInspector {
 namespace Internal {
@@ -114,7 +112,7 @@ private:
     QmlJS::Document::Ptr m_initialDoc; //the document that was loaded by the server
     QString m_filename;
 
-    QList<QWeakPointer<QmlJSEditor::Internal::QmlJSTextEditor> > m_editors;
+    QList<QWeakPointer<QmlJSEditor::QmlJSTextEditor> > m_editors;
 
     bool m_applyChangesToQmlObserver;
     QmlJS::Document::Ptr m_docWithUnappliedChanges;