diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp
index 83bd1ef5423e02dd21522be4bf2d2a76f0c74c10..2b31c7bebe08d9a7fead675abbb2ec8e47692b7f 100644
--- a/src/plugins/cppeditor/cppeditor.cpp
+++ b/src/plugins/cppeditor/cppeditor.cpp
@@ -38,6 +38,7 @@
 #include <coreplugin/actionmanager/actioncontainer.h>
 #include <coreplugin/actionmanager/actionmanager.h>
 #include <coreplugin/icore.h>
+#include <cpptools/cpptoolseditorsupport.h>
 #include <cpptools/cpptoolsplugin.h>
 #include <cpptools/cpptoolsconstants.h>
 #include <cpptools/cppchecksymbols.h>
@@ -176,64 +177,6 @@ private:
     CPlusPlus::OverviewModel *m_sourceModel;
 };
 
-class FunctionDefinitionUnderCursor: protected ASTVisitor
-{
-    unsigned _line;
-    unsigned _column;
-    DeclarationAST *_functionDefinition;
-
-public:
-    FunctionDefinitionUnderCursor(TranslationUnit *translationUnit)
-        : ASTVisitor(translationUnit),
-          _line(0), _column(0)
-    { }
-
-    DeclarationAST *operator()(AST *ast, unsigned line, unsigned column)
-    {
-        _functionDefinition = 0;
-        _line = line;
-        _column = column;
-        accept(ast);
-        return _functionDefinition;
-    }
-
-protected:
-    virtual bool preVisit(AST *ast)
-    {
-        if (_functionDefinition)
-            return false;
-
-        else if (FunctionDefinitionAST *def = ast->asFunctionDefinition()) {
-            return checkDeclaration(def);
-        }
-
-        else if (ObjCMethodDeclarationAST *method = ast->asObjCMethodDeclaration()) {
-            if (method->function_body)
-                return checkDeclaration(method);
-        }
-
-        return true;
-    }
-
-private:
-    bool checkDeclaration(DeclarationAST *ast)
-    {
-        unsigned startLine, startColumn;
-        unsigned endLine, endColumn;
-        getTokenStartPosition(ast->firstToken(), &startLine, &startColumn);
-        getTokenEndPosition(ast->lastToken() - 1, &endLine, &endColumn);
-
-        if (_line > startLine || (_line == startLine && _column >= startColumn)) {
-            if (_line < endLine || (_line == endLine && _column < endColumn)) {
-                _functionDefinition = ast;
-                return false;
-            }
-        }
-
-        return true;
-    }
-};
-
 class FindFunctionDefinitions: protected SymbolVisitor
 {
     const Name *_declarationName;
@@ -573,14 +516,9 @@ CPPEditorWidget::CPPEditorWidget(QWidget *parent)
     , m_objcEnabled(false)
     , m_commentsSettings(CppTools::CppToolsSettings::instance()->commentsSettings())
     , m_completionSupport(0)
-    , m_highlightingSupport(0)
 {
-    m_initialized = false;
     qRegisterMetaType<SemanticInfo>("CppTools::SemanticInfo");
 
-    m_semanticHighlighter = new SemanticHighlighter(this);
-    m_semanticHighlighter->start();
-
     setParenthesesMatchingEnabled(true);
     setMarksVisible(true);
     setCodeFoldingSupported(true);
@@ -591,10 +529,15 @@ CPPEditorWidget::CPPEditorWidget(QWidget *parent)
 
     m_modelManager = CppModelManagerInterface::instance();
     if (m_modelManager) {
-        connect(m_modelManager, SIGNAL(documentUpdated(CPlusPlus::Document::Ptr)),
-                this, SLOT(onDocumentUpdated(CPlusPlus::Document::Ptr)));
+        CppEditorSupport *editorSupport = m_modelManager->cppEditorSupport(editor());
+        connect(editorSupport, SIGNAL(documentUpdated()),
+                this, SLOT(onDocumentUpdated()));
+        connect(editorSupport, SIGNAL(semanticInfoUpdated(CppTools::SemanticInfo)),
+                this, SLOT(updateSemanticInfo(CppTools::SemanticInfo)));
+        connect(editorSupport, SIGNAL(highlighterStarted(QFuture<TextEditor::HighlightingResult>, unsigned)),
+                this, SLOT(highlighterStarted(QFuture<TextEditor::HighlightingResult>, unsigned)));
+
         m_completionSupport = m_modelManager->completionSupport(editor());
-        m_highlightingSupport = m_modelManager->highlightingSupport(editor());
     }
 
     m_highlightRevision = 0;
@@ -620,16 +563,12 @@ CPPEditorWidget::CPPEditorWidget(QWidget *parent)
 
 CPPEditorWidget::~CPPEditorWidget()
 {
-    m_semanticHighlighter->abort();
-    m_semanticHighlighter->wait();
-
     ++numberOfClosedEditors;
     if (numberOfClosedEditors == 5) {
         m_modelManager->GC();
         numberOfClosedEditors = 0;
     }
 
-    delete m_highlightingSupport;
     delete m_completionSupport;
 }
 
@@ -710,9 +649,6 @@ void CPPEditorWidget::createToolBar(CPPEditor *editor)
     connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(updateUses()));
     connect(this, SIGNAL(textChanged()), this, SLOT(updateUses()));
 
-    connect(m_semanticHighlighter, SIGNAL(changed(CppTools::SemanticInfo)),
-            this, SLOT(updateSemanticInfo(CppTools::SemanticInfo)));
-
     editor->insertExtraToolBarWidget(TextEditor::BaseTextEditor::Left, m_outlineCombo);
 }
 
@@ -829,23 +765,10 @@ void CPPEditorWidget::abortRename()
     semanticRehighlight(/* force = */ true);
 }
 
-void CPPEditorWidget::onDocumentUpdated(Document::Ptr doc)
+/// \brief Called by \c CppEditorSupport when the document corresponding to the
+///        file in this editor is updated.
+void CPPEditorWidget::onDocumentUpdated()
 {
-    if (doc->fileName() != editorDocument()->fileName())
-        return;
-
-    if (doc->editorRevision() != editorRevision())
-        return;
-
-    if (! m_initialized ||
-            (Core::EditorManager::currentEditor() == editor()
-             && (!m_lastSemanticInfo.doc
-                 || !m_lastSemanticInfo.doc->translationUnit()->ast()
-                 || m_lastSemanticInfo.doc->fileName() != editorDocument()->fileName()))) {
-        m_initialized = true;
-        semanticRehighlight(/* force = */ true);
-    }
-
     m_updateOutlineTimer->start();
 }
 
@@ -1018,7 +941,8 @@ void CPPEditorWidget::markSymbols(const QTextCursor &tc, const SemanticInfo &inf
 
 void CPPEditorWidget::renameSymbolUnderCursor()
 {
-    updateSemanticInfo(m_semanticHighlighter->semanticInfo(currentSource()));
+    CppEditorSupport *edSup = m_modelManager->cppEditorSupport(editor());
+    updateSemanticInfo(edSup->recalculateSemanticInfo(/* emitSignalWhenFinished = */ false));
     abortRename();
 
     QTextCursor c = textCursor();
@@ -1246,7 +1170,7 @@ void CPPEditorWidget::finishHighlightSymbolUsages()
 
     if (m_modelManager)
         m_modelManager->setExtraDiagnostics(m_lastSemanticInfo.doc->fileName(),
-                                            CppTools::CppModelManagerInterface::CppSemanticsDiagnostic,
+                                            QLatin1String("CppEditor.SemanticsDiagnostics"),
                                             m_lastSemanticInfo.doc->diagnosticMessages());
 }
 
@@ -2051,7 +1975,15 @@ bool CPPEditorWidget::openCppEditorAt(const Link &link, bool inNextSplit)
 
 void CPPEditorWidget::semanticRehighlight(bool force)
 {
-    m_semanticHighlighter->rehighlight(currentSource(force));
+    m_modelManager->cppEditorSupport(editor())->recalculateSemanticInfoDetached(force);
+}
+
+void CPPEditorWidget::highlighterStarted(QFuture<TextEditor::HighlightingResult> highlighter,
+                                         unsigned revision)
+{
+    m_highlighter = highlighter;
+    m_highlightRevision = revision;
+    m_highlightWatcher.setFuture(m_highlighter);
 }
 
 void CPPEditorWidget::updateSemanticInfo(const SemanticInfo &semanticInfo)
@@ -2062,7 +1994,6 @@ void CPPEditorWidget::updateSemanticInfo(const SemanticInfo &semanticInfo)
         return;
     }
 
-    const SemanticInfo previousSemanticInfo = m_lastSemanticInfo;
     m_lastSemanticInfo = semanticInfo; // update the semantic info
 
     int line = 0, column = 0;
@@ -2103,20 +2034,6 @@ void CPPEditorWidget::updateSemanticInfo(const SemanticInfo &semanticInfo)
         }
     }
 
-    if (m_lastSemanticInfo.forced || previousSemanticInfo.revision != semanticInfo.revision) {
-        m_highlighter.cancel();
-
-        if (! semanticHighlighterDisabled && semanticInfo.doc) {
-            if (isVisible()) {
-                if (m_highlightingSupport) {
-                    m_highlighter = m_highlightingSupport->highlightingFuture(semanticInfo.doc, semanticInfo.snapshot);
-                    m_highlightRevision = semanticInfo.revision;
-                    m_highlightWatcher.setFuture(m_highlighter);
-                }
-            }
-        }
-    }
-
     setExtraSelections(UnusedSymbolSelection, unusedSelections);
 
     if (! m_renameSelections.isEmpty())
@@ -2131,129 +2048,6 @@ void CPPEditorWidget::updateSemanticInfo(const SemanticInfo &semanticInfo)
     updateFunctionDeclDefLink();
 }
 
-SemanticHighlighter::Source CPPEditorWidget::currentSource(bool force)
-{
-    int line = 0, column = 0;
-    convertPosition(position(), &line, &column);
-
-    const Snapshot snapshot = m_modelManager->snapshot();
-    const QString fileName = editorDocument()->fileName();
-
-    QString code;
-    if (force || m_lastSemanticInfo.revision != editorRevision())
-        code = toPlainText(); // get the source code only when needed.
-
-    const unsigned revision = editorRevision();
-    SemanticHighlighter::Source source(snapshot, fileName, code,
-                                       line, column, revision);
-    source.force = force;
-    return source;
-}
-
-SemanticHighlighter::SemanticHighlighter(QObject *parent)
-        : QThread(parent),
-          m_done(false)
-{
-}
-
-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)
-{
-    SemanticInfo semanticInfo;
-    semanticInfo.revision = m_lastSemanticInfo.revision;
-    semanticInfo.forced = source.force;
-
-    m_mutex.lock();
-    if (! source.force
-            && m_lastSemanticInfo.revision == source.revision
-            && m_lastSemanticInfo.doc
-            && m_lastSemanticInfo.doc->translationUnit()->ast()
-            && m_lastSemanticInfo.doc->fileName() == source.fileName) {
-        semanticInfo.snapshot = m_lastSemanticInfo.snapshot; // ### TODO: use the new snapshot.
-        semanticInfo.doc = m_lastSemanticInfo.doc;
-    }
-    m_mutex.unlock();
-
-    if (! semanticInfo.doc) {
-        semanticInfo.snapshot = source.snapshot;
-        if (source.snapshot.contains(source.fileName)) {
-            Document::Ptr doc = source.snapshot.preprocessedDocument(source.code, source.fileName);
-            doc->control()->setTopLevelDeclarationProcessor(this);
-            doc->check();
-            semanticInfo.doc = doc;
-        }
-    }
-
-    if (semanticInfo.doc) {
-        TranslationUnit *translationUnit = semanticInfo.doc->translationUnit();
-        AST * ast = translationUnit->ast();
-
-        FunctionDefinitionUnderCursor functionDefinitionUnderCursor(semanticInfo.doc->translationUnit());
-        DeclarationAST *currentFunctionDefinition = functionDefinitionUnderCursor(ast, source.line, source.column);
-
-        const LocalSymbols useTable(semanticInfo.doc, currentFunctionDefinition);
-        semanticInfo.revision = source.revision;
-        semanticInfo.localUses = useTable.uses;
-    }
-
-    return semanticInfo;
-}
-
 QModelIndex CPPEditorWidget::indexForPosition(int line, int column, const QModelIndex &rootIndex) const
 {
     QModelIndex lastIndex = rootIndex;
diff --git a/src/plugins/cppeditor/cppeditor.h b/src/plugins/cppeditor/cppeditor.h
index 20c4ef7f611d7a2efaef2d67e3c1577d5470af1f..679bcb9c55ddafa2f32271a55af7ccd561bd8c2b 100644
--- a/src/plugins/cppeditor/cppeditor.h
+++ b/src/plugins/cppeditor/cppeditor.h
@@ -69,75 +69,6 @@ namespace Internal {
 
 class CPPEditorWidget;
 
-class SemanticHighlighter: public QThread, CPlusPlus::TopLevelDeclarationProcessor
-{
-    Q_OBJECT
-
-public:
-    SemanticHighlighter(QObject *parent = 0);
-    virtual ~SemanticHighlighter();
-
-    virtual bool processDeclaration(CPlusPlus::DeclarationAST *) { return m_done; }
-
-    void abort();
-
-    struct Source
-    {
-        CPlusPlus::Snapshot snapshot;
-        QString fileName;
-        QString code;
-        int line;
-        int column;
-        unsigned revision;
-        bool force;
-
-        Source()
-            : line(0), column(0), revision(0), force(false)
-        { }
-
-        Source(const CPlusPlus::Snapshot &snapshot,
-               const QString &fileName,
-               const QString &code,
-               int line, int column,
-               unsigned revision)
-            : snapshot(snapshot), fileName(fileName),
-              code(code), line(line), column(column),
-              revision(revision), force(false)
-        { }
-
-        void clear()
-        {
-            snapshot = CPlusPlus::Snapshot();
-            fileName.clear();
-            code.clear();
-            line = 0;
-            column = 0;
-            revision = 0;
-            force = false;
-        }
-    };
-
-    CppTools::SemanticInfo semanticInfo(const Source &source);
-
-    void rehighlight(const Source &source);
-
-Q_SIGNALS:
-    void changed(const CppTools::SemanticInfo &semanticInfo);
-
-protected:
-    virtual void run();
-
-private:
-    bool isOutdated();
-
-private:
-    QMutex m_mutex;
-    QWaitCondition m_condition;
-    bool m_done;
-    Source m_source;
-    CppTools::SemanticInfo m_lastSemanticInfo;
-};
-
 class CPPEditor : public TextEditor::BaseTextEditor
 {
     Q_OBJECT
@@ -210,6 +141,7 @@ public Q_SLOTS:
     void findUsages();
     void renameUsagesNow(const QString &replacement = QString());
     void semanticRehighlight(bool force = false);
+    void highlighterStarted(QFuture<TextEditor::HighlightingResult> highlighter, unsigned revision);
 
 protected:
     bool event(QEvent *e);
@@ -235,7 +167,7 @@ private Q_SLOTS:
     void updateFunctionDeclDefLink();
     void updateFunctionDeclDefLinkNow();
     void onFunctionDeclDefLinkFound(QSharedPointer<FunctionDeclDefLink> link);
-    void onDocumentUpdated(CPlusPlus::Document::Ptr doc);
+    void onDocumentUpdated();
     void onContentsChanged(int position, int charsRemoved, int charsAdded);
 
     void updateSemanticInfo(const CppTools::SemanticInfo &semanticInfo);
@@ -258,8 +190,6 @@ private:
     TextEditor::ITextEditor *openCppEditorAt(const QString &fileName, int line,
                                              int column = 0);
 
-    SemanticHighlighter::Source currentSource(bool force = false);
-
     void highlightUses(const QList<TextEditor::HighlightingResult> &uses,
                        QList<QTextEdit::ExtraSelection> *selections);
 
@@ -310,11 +240,9 @@ private:
     QTextCursor m_currentRenameSelectionBegin;
     QTextCursor m_currentRenameSelectionEnd;
 
-    SemanticHighlighter *m_semanticHighlighter;
     CppTools::SemanticInfo m_lastSemanticInfo;
     QList<TextEditor::QuickFixOperation::Ptr> m_quickFixes;
     bool m_objcEnabled;
-    bool m_initialized;
 
     QFuture<TextEditor::HighlightingResult> m_highlighter;
     QFutureWatcher<TextEditor::HighlightingResult> m_highlightWatcher;
@@ -331,7 +259,6 @@ private:
     CppTools::CommentsSettings m_commentsSettings;
 
     CppTools::CppCompletionSupport *m_completionSupport;
-    CppTools::CppHighlightingSupport *m_highlightingSupport;
 };
 
 
diff --git a/src/plugins/cpptools/cpphighlightingsupport.h b/src/plugins/cpptools/cpphighlightingsupport.h
index 037c50e5ad5c14091ed803fefca2a66682ef06e0..7fd77898c24c423b2c2009681cde18abc40fec98 100644
--- a/src/plugins/cpptools/cpphighlightingsupport.h
+++ b/src/plugins/cpptools/cpphighlightingsupport.h
@@ -64,6 +64,10 @@ public:
     CppHighlightingSupport(TextEditor::ITextEditor *editor);
     virtual ~CppHighlightingSupport() = 0;
 
+    virtual bool requiresSemanticInfo() const = 0;
+
+    virtual bool hightlighterHandlesDiagnostics() const = 0;
+
     virtual QFuture<TextEditor::HighlightingResult> highlightingFuture(
             const CPlusPlus::Document::Ptr &doc,
             const CPlusPlus::Snapshot &snapshot) const = 0;
@@ -82,8 +86,6 @@ public:
     virtual ~CppHighlightingSupportFactory() = 0;
 
     virtual CppHighlightingSupport *highlightingSupport(TextEditor::ITextEditor *editor) = 0;
-
-    virtual bool hightlighterHandlesDiagnostics() const = 0;
 };
 
 } // namespace CppTools
diff --git a/src/plugins/cpptools/cpphighlightingsupportinternal.h b/src/plugins/cpptools/cpphighlightingsupportinternal.h
index 9ca1cf7713f325d88253d8e4874347b29bbca6e8..a2b5d4db7397cf8702d2493cd1c9d2ed48e7c059 100644
--- a/src/plugins/cpptools/cpphighlightingsupportinternal.h
+++ b/src/plugins/cpptools/cpphighlightingsupportinternal.h
@@ -43,6 +43,12 @@ public:
     CppHighlightingSupportInternal(TextEditor::ITextEditor *editor);
     virtual ~CppHighlightingSupportInternal();
 
+    virtual bool requiresSemanticInfo() const
+    { return true; }
+
+    virtual bool hightlighterHandlesDiagnostics() const
+    { return false; }
+
     virtual QFuture<TextEditor::HighlightingResult> highlightingFuture(
             const CPlusPlus::Document::Ptr &doc,
             const CPlusPlus::Snapshot &snapshot) const;
@@ -54,9 +60,6 @@ public:
     virtual ~CppHighlightingSupportInternalFactory();
 
     virtual CppHighlightingSupport *highlightingSupport(TextEditor::ITextEditor *editor);
-
-    virtual bool hightlighterHandlesDiagnostics() const
-    { return false; }
 };
 
 } // namespace Internal
diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp
index b79f57e5c801aa8f2b2d5375a26a89954f360edf..07067d9e5641fb2c602d8c6ca9a9c75f31fe2b8c 100644
--- a/src/plugins/cpptools/cppmodelmanager.cpp
+++ b/src/plugins/cpptools/cppmodelmanager.cpp
@@ -643,12 +643,6 @@ CppModelManager::CppModelManager(QObject *parent)
     QTC_ASSERT(pe, return);
 
     ProjectExplorer::SessionManager *session = pe->session();
-    m_updateEditorSelectionsTimer = new QTimer(this);
-    m_updateEditorSelectionsTimer->setInterval(500);
-    m_updateEditorSelectionsTimer->setSingleShot(true);
-    connect(m_updateEditorSelectionsTimer, SIGNAL(timeout()),
-            this, SLOT(updateEditorSelections()));
-
     connect(session, SIGNAL(projectAdded(ProjectExplorer::Project*)),
             this, SLOT(onProjectAdded(ProjectExplorer::Project*)));
 
@@ -663,16 +657,7 @@ CppModelManager::CppModelManager(QObject *parent)
 
     qRegisterMetaType<CPlusPlus::Document::Ptr>("CPlusPlus::Document::Ptr");
 
-    // thread connections
-    connect(this, SIGNAL(documentUpdated(CPlusPlus::Document::Ptr)),
-            this, SLOT(onDocumentUpdated(CPlusPlus::Document::Ptr)));
-    connect(this, SIGNAL(extraDiagnosticsUpdated(QString)),
-            this, SLOT(onExtraDiagnosticsUpdated(QString)));
-
-    // Listen for editor closed and opened events so that we can keep track of changing files
-    connect(Core::ICore::editorManager(), SIGNAL(editorOpened(Core::IEditor*)),
-        this, SLOT(editorOpened(Core::IEditor*)));
-
+    // Listen for editor closed events so that we can keep track of changing files
     connect(Core::ICore::editorManager(), SIGNAL(editorAboutToClose(Core::IEditor*)),
         this, SLOT(editorAboutToClose(Core::IEditor*)));
 
@@ -868,6 +853,22 @@ void CppModelManager::removeEditorSupport(AbstractEditorSupport *editorSupport)
     m_addtionalEditorSupport.remove(editorSupport);
 }
 
+/// \brief Returns the \c CppEditorSupport for the given text editor. It will
+///        create one when none exists yet.
+CppEditorSupport *CppModelManager::cppEditorSupport(TextEditor::BaseTextEditor *editor)
+{
+    Q_ASSERT(editor);
+
+    QMutexLocker locker(&m_editorSupportMutex);
+
+    CppEditorSupport *editorSupport = m_editorSupport.value(editor, 0);
+    if (!editorSupport) {
+        editorSupport = new CppEditorSupport(this, editor);
+        m_editorSupport.insert(editor, editorSupport);
+    }
+    return editorSupport;
+}
+
 QList<int> CppModelManager::references(CPlusPlus::Symbol *symbol, const LookupContext &context)
 {
     return m_findReferences->references(symbol, context);
@@ -904,14 +905,17 @@ void CppModelManager::replaceSnapshot(const CPlusPlus::Snapshot &newSnapshot)
 
 CppModelManager::WorkingCopy CppModelManager::buildWorkingCopyList()
 {
+    QList<CppEditorSupport *> supporters;
+
+    {
+        QMutexLocker locker(&m_editorSupportMutex);
+        supporters = m_editorSupport.values();
+    }
+
     WorkingCopy workingCopy;
-    QMapIterator<TextEditor::ITextEditor *, CppEditorSupport *> it(m_editorSupport);
-    while (it.hasNext()) {
-        it.next();
-        TextEditor::ITextEditor *textEditor = it.key();
-        CppEditorSupport *editorSupport = it.value();
-        QString fileName = textEditor->document()->fileName();
-        workingCopy.insert(fileName, editorSupport->contents(), editorSupport->editorRevision());
+    foreach (const CppEditorSupport *editorSupport, supporters) {
+        workingCopy.insert(editorSupport->fileName(), editorSupport->contents(),
+                           editorSupport->editorRevision());
     }
 
     QSetIterator<AbstractEditorSupport *> jt(m_addtionalEditorSupport);
@@ -1009,36 +1013,19 @@ QList<ProjectPart::Ptr> CppModelManager::projectPart(const QString &fileName) co
     return parts;
 }
 
-/*!
-    \fn    void CppModelManager::editorOpened(Core::IEditor *editor)
-    \brief If a C++ editor is opened, the model manager listens to content changes
-           in order to update the CppCodeModel accordingly. It also updates the
-           CppCodeModel for the first time with this editor.
-
-    \sa    void CppModelManager::editorContentsChanged()
- */
-void CppModelManager::editorOpened(Core::IEditor *editor)
-{
-    if (isCppEditor(editor)) {
-        TextEditor::ITextEditor *textEditor = qobject_cast<TextEditor::ITextEditor *>(editor);
-        QTC_ASSERT(textEditor, return);
-
-        CppEditorSupport *editorSupport = new CppEditorSupport(this);
-        editorSupport->setTextEditor(textEditor);
-        m_editorSupport[textEditor] = editorSupport;
-    }
-}
-
+/// \brief Removes the CppEditorSupport for the closed editor.
 void CppModelManager::editorAboutToClose(Core::IEditor *editor)
 {
-    if (isCppEditor(editor)) {
-        TextEditor::ITextEditor *textEditor = qobject_cast<TextEditor::ITextEditor *>(editor);
-        QTC_ASSERT(textEditor, return);
+    if (!isCppEditor(editor))
+        return;
 
-        CppEditorSupport *editorSupport = m_editorSupport.value(textEditor);
-        m_editorSupport.remove(textEditor);
-        delete editorSupport;
-    }
+    TextEditor::BaseTextEditor *textEditor = qobject_cast<TextEditor::BaseTextEditor *>(editor);
+    QTC_ASSERT(textEditor, return);
+
+    QMutexLocker locker(&m_editorSupportMutex);
+    CppEditorSupport *editorSupport = m_editorSupport.value(textEditor, 0);
+    m_editorSupport.remove(textEditor);
+    delete editorSupport;
 }
 
 bool CppModelManager::isCppEditor(Core::IEditor *editor) const
@@ -1047,141 +1034,9 @@ bool CppModelManager::isCppEditor(Core::IEditor *editor) const
 }
 
 void CppModelManager::emitDocumentUpdated(Document::Ptr doc)
-{
-    emit documentUpdated(doc);
-}
-
-void CppModelManager::onDocumentUpdated(Document::Ptr doc)
 {
     if (replaceDocument(doc))
-        updateEditor(doc);
-}
-
-void CppModelManager::onExtraDiagnosticsUpdated(const QString &fileName)
-{
-    if (Document::Ptr doc = document(fileName))
-        updateEditor(doc);
-}
-
-void CppModelManager::updateEditor(Document::Ptr doc)
-{
-    const QString fileName = doc->fileName();
-
-    QList<Core::IEditor *> openedEditors = Core::ICore::editorManager()->openedEditors();
-    foreach (Core::IEditor *editor, openedEditors) {
-        if (editor->document()->fileName() == fileName) {
-            TextEditor::ITextEditor *textEditor = qobject_cast<TextEditor::ITextEditor *>(editor);
-            if (! textEditor)
-                continue;
-
-            TextEditor::BaseTextEditorWidget *ed = qobject_cast<TextEditor::BaseTextEditorWidget *>(textEditor->widget());
-            if (! ed)
-                continue;
-
-            QList<TextEditor::BaseTextEditorWidget::BlockRange> blockRanges;
-
-            foreach (const Document::Block &block, doc->skippedBlocks()) {
-                blockRanges.append(TextEditor::BaseTextEditorWidget::BlockRange(block.begin(), block.end()));
-            }
-
-            // set up the format for the errors
-            QTextCharFormat errorFormat;
-            errorFormat.setUnderlineStyle(QTextCharFormat::WaveUnderline);
-            errorFormat.setUnderlineColor(Qt::red);
-
-            // set up the format for the warnings.
-            QTextCharFormat warningFormat;
-            warningFormat.setUnderlineStyle(QTextCharFormat::WaveUnderline);
-            warningFormat.setUnderlineColor(Qt::darkYellow);
-
-            QList<Editor> todo;
-            foreach (const Editor &e, m_todo) {
-                if (e.textEditor != textEditor)
-                    todo.append(e);
-            }
-            Editor e;
-
-            if (m_highlightingFactory->hightlighterHandlesDiagnostics()) {
-                e.updateSelections = false;
-            } else {
-                QSet<int> lines;
-                QList<Document::DiagnosticMessage> messages = doc->diagnosticMessages();
-                messages += extraDiagnostics(doc->fileName());
-                foreach (const Document::DiagnosticMessage &m, messages) {
-                    if (m.fileName() != fileName)
-                        continue;
-                    else if (lines.contains(m.line()))
-                        continue;
-
-                    lines.insert(m.line());
-
-                    QTextEdit::ExtraSelection sel;
-                    if (m.isWarning())
-                        sel.format = warningFormat;
-                    else
-                        sel.format = errorFormat;
-
-                    QTextCursor c(ed->document()->findBlockByNumber(m.line() - 1));
-                    const QString text = c.block().text();
-                    if (m.length() > 0 && m.column() + m.length() < (unsigned)text.size()) {
-                        int column = m.column() > 0 ? m.column() - 1 : 0;
-                        c.setPosition(c.position() + column);
-                        c.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, m.length());
-                    } else {
-                        for (int i = 0; i < text.size(); ++i) {
-                            if (! text.at(i).isSpace()) {
-                                c.setPosition(c.position() + i);
-                                break;
-                            }
-                        }
-                        c.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
-                    }
-                    sel.cursor = c;
-                    sel.format.setToolTip(m.text());
-                    e.selections.append(sel);
-                }
-            }
-
-
-            e.revision = ed->document()->revision();
-            e.textEditor = textEditor;
-            e.ifdefedOutBlocks = blockRanges;
-            todo.append(e);
-            m_todo = todo;
-            postEditorUpdate();
-            break;
-        }
-    }
-}
-
-void CppModelManager::postEditorUpdate()
-{
-    m_updateEditorSelectionsTimer->start(500);
-}
-
-void CppModelManager::updateEditorSelections()
-{
-    foreach (const Editor &ed, m_todo) {
-        if (! ed.textEditor)
-            continue;
-
-        TextEditor::ITextEditor *textEditor = ed.textEditor;
-        TextEditor::BaseTextEditorWidget *editor = qobject_cast<TextEditor::BaseTextEditorWidget *>(textEditor->widget());
-
-        if (! editor)
-            continue;
-        else if (editor->document()->revision() != ed.revision)
-            continue; // outdated
-
-        if (ed.updateSelections)
-            editor->setExtraSelections(TextEditor::BaseTextEditorWidget::CodeWarningsSelection,
-                                       ed.selections);
-
-        editor->setIfdefedOutBlocks(ed.ifdefedOutBlocks);
-    }
-
-    m_todo.clear();
-
+        emit documentUpdated(doc);
 }
 
 void CppModelManager::onProjectAdded(ProjectExplorer::Project *)
@@ -1308,26 +1163,20 @@ CppIndexingSupport *CppModelManager::indexingSupport()
     return m_indexingSupporter ? m_indexingSupporter : m_internalIndexingSupport;
 }
 
-void CppModelManager::setExtraDiagnostics(const QString &fileName, int kind,
+void CppModelManager::setExtraDiagnostics(const QString &fileName, const QString &kind,
                                           const QList<Document::DiagnosticMessage> &diagnostics)
 {
+    QList<CppEditorSupport *> supporters;
+
     {
-        QMutexLocker locker(&m_protectExtraDiagnostics);
-        if (m_extraDiagnostics[fileName][kind] == diagnostics)
-            return;
-        m_extraDiagnostics[fileName].insert(kind, diagnostics);
+        QMutexLocker locker(&m_editorSupportMutex);
+        supporters = m_editorSupport.values();
     }
-    emit extraDiagnosticsUpdated(fileName);
-}
 
-QList<Document::DiagnosticMessage> CppModelManager::extraDiagnostics(const QString &fileName, int kind) const
-{
-    QMutexLocker locker(&m_protectExtraDiagnostics);
-    if (kind == -1) {
-        QList<Document::DiagnosticMessage> messages;
-        foreach (const QList<Document::DiagnosticMessage> &list, m_extraDiagnostics.value(fileName))
-            messages += list;
-        return messages;
+    foreach (CppEditorSupport *supporter, supporters) {
+        if (supporter->fileName() == fileName) {
+            supporter->setExtraDiagnostics(kind, diagnostics);
+            break;
+        }
     }
-    return m_extraDiagnostics.value(fileName).value(kind);
 }
diff --git a/src/plugins/cpptools/cppmodelmanager.h b/src/plugins/cpptools/cppmodelmanager.h
index f77e4fae0f72cd7da0f093dd38cbcc590797c3c3..5ae585d0d4eff756f849a58bd901b1ede70f1b9e 100644
--- a/src/plugins/cpptools/cppmodelmanager.h
+++ b/src/plugins/cpptools/cppmodelmanager.h
@@ -59,11 +59,11 @@ namespace CPlusPlus { class ParseManager; }
 namespace CppTools {
 
 class CppCompletionSupportFactory;
+class CppEditorSupport;
 class CppHighlightingSupportFactory;
 
 namespace Internal {
 
-class CppEditorSupport;
 class CppPreprocessor;
 class CppFindReferences;
 
@@ -95,16 +95,11 @@ public:
 
     virtual bool isCppEditor(Core::IEditor *editor) const;
 
-    CppEditorSupport *editorSupport(TextEditor::ITextEditor *editor) const
-    { return m_editorSupport.value(editor); }
-
     void emitDocumentUpdated(CPlusPlus::Document::Ptr doc);
 
-    void stopEditorSelectionsUpdate()
-    { m_updateEditorSelectionsTimer->stop(); }
-
     virtual void addEditorSupport(AbstractEditorSupport *editorSupport);
     virtual void removeEditorSupport(AbstractEditorSupport *editorSupport);
+    virtual CppEditorSupport *cppEditorSupport(TextEditor::BaseTextEditor *editor);
 
     virtual QList<int> references(CPlusPlus::Symbol *symbol, const CPlusPlus::LookupContext &context);
 
@@ -115,10 +110,8 @@ public:
     virtual void findMacroUsages(const CPlusPlus::Macro &macro);
     virtual void renameMacroUsages(const CPlusPlus::Macro &macro, const QString &replacement);
 
-    virtual void setExtraDiagnostics(const QString &fileName, int key,
+    virtual void setExtraDiagnostics(const QString &fileName, const QString &key,
                                      const QList<Document::DiagnosticMessage> &diagnostics);
-    virtual QList<Document::DiagnosticMessage> extraDiagnostics(
-            const QString &fileName, int key = AllExtraDiagnostics) const;
 
     void finishedRefreshingSourceFiles(const QStringList &files);
 
@@ -161,24 +154,17 @@ Q_SIGNALS:
     void aboutToRemoveFiles(const QStringList &files);
 
 public Q_SLOTS:
-    void editorOpened(Core::IEditor *editor);
     void editorAboutToClose(Core::IEditor *editor);
     virtual void updateModifiedSourceFiles();
 
 private Q_SLOTS:
     // this should be executed in the GUI thread.
-    void onDocumentUpdated(CPlusPlus::Document::Ptr doc);
-    void onExtraDiagnosticsUpdated(const QString &fileName);
     void onAboutToRemoveProject(ProjectExplorer::Project *project);
     void onAboutToUnloadSession();
     void onCoreAboutToClose();
     void onProjectAdded(ProjectExplorer::Project *project);
-    void postEditorUpdate();
-    void updateEditorSelections();
 
 private:
-    void updateEditor(Document::Ptr doc);
-
     void replaceSnapshot(const CPlusPlus::Snapshot &newSnapshot);
     WorkingCopy buildWorkingCopyList();
 
@@ -206,7 +192,8 @@ private:
     QByteArray m_definedMacros;
 
     // editor integration
-    QMap<TextEditor::ITextEditor *, CppEditorSupport *> m_editorSupport;
+    mutable QMutex m_editorSupportMutex;
+    QMap<TextEditor::BaseTextEditor *, CppEditorSupport *> m_editorSupport;
 
     QSet<AbstractEditorSupport *> m_addtionalEditorSupport;
 
@@ -216,28 +203,9 @@ private:
     mutable QMutex m_mutex;
     mutable QMutex m_protectSnapshot;
 
-    struct Editor {
-        Editor()
-            : revision(-1)
-            , updateSelections(true)
-        {}
-        int revision;
-        bool updateSelections;
-        QPointer<TextEditor::ITextEditor> textEditor;
-        QList<QTextEdit::ExtraSelection> selections;
-        QList<TextEditor::BaseTextEditorWidget::BlockRange> ifdefedOutBlocks;
-    };
-
-    QList<Editor> m_todo;
-
-    QTimer *m_updateEditorSelectionsTimer;
-
     CppFindReferences *m_findReferences;
     bool m_indexerEnabled;
 
-    mutable QMutex m_protectExtraDiagnostics;
-    QHash<QString, QHash<int, QList<Document::DiagnosticMessage> > > m_extraDiagnostics;
-
     QMap<QString, QList<CppTools::ProjectPart::Ptr> > m_srcToProjectPart;
 
     CppCompletionAssistProvider *m_completionAssistProvider;
diff --git a/src/plugins/cpptools/cppmodelmanagerinterface.h b/src/plugins/cpptools/cppmodelmanagerinterface.h
index aa25ab5d061411eb933029ac0cc30d6312443235..ebcc1ea5f8922f35cfa79a7cd95495ca570682f5 100644
--- a/src/plugins/cpptools/cppmodelmanagerinterface.h
+++ b/src/plugins/cpptools/cppmodelmanagerinterface.h
@@ -44,11 +44,13 @@
 namespace Core { class IEditor; }
 namespace CPlusPlus { class LookupContext; }
 namespace ProjectExplorer { class Project; }
+namespace TextEditor { class BaseTextEditor; }
 
 namespace CppTools {
 class AbstractEditorSupport;
 class CppCompletionSupport;
 class CppCompletionAssistProvider;
+class CppEditorSupport;
 class CppHighlightingSupport;
 class CppHighlightingSupportFactory;
 class CppIndexingSupport;
@@ -187,13 +189,6 @@ public:
         Table _elements;
     };
 
-    enum ExtraDiagnosticKind
-    {
-        AllExtraDiagnostics = -1,
-        ExportedQmlTypesDiagnostic,
-        CppSemanticsDiagnostic
-    };
-
 public:
     static const QString configurationFileName();
 
@@ -215,6 +210,7 @@ public:
 
     virtual void addEditorSupport(CppTools::AbstractEditorSupport *editorSupport) = 0;
     virtual void removeEditorSupport(CppTools::AbstractEditorSupport *editorSupport) = 0;
+    virtual CppEditorSupport *cppEditorSupport(TextEditor::BaseTextEditor *editor) = 0;
 
     virtual QList<int> references(CPlusPlus::Symbol *symbol,
                                   const CPlusPlus::LookupContext &context) = 0;
@@ -226,10 +222,8 @@ public:
     virtual void renameMacroUsages(const CPlusPlus::Macro &macro, const QString &replacement = QString()) = 0;
     virtual void findMacroUsages(const CPlusPlus::Macro &macro) = 0;
 
-    virtual void setExtraDiagnostics(const QString &fileName, int key,
+    virtual void setExtraDiagnostics(const QString &fileName, const QString &kind,
                                      const QList<CPlusPlus::Document::DiagnosticMessage> &diagnostics) = 0;
-    virtual QList<CPlusPlus::Document::DiagnosticMessage> extraDiagnostics(
-            const QString &fileName, int key = AllExtraDiagnostics) const = 0;
 
     virtual CppTools::CppCompletionSupport *completionSupport(Core::IEditor *editor) const = 0;
     virtual void setCppCompletionAssistProvider(CppTools::CppCompletionAssistProvider *completionAssistProvider) = 0;
@@ -243,7 +237,6 @@ public:
 Q_SIGNALS:
     void documentUpdated(CPlusPlus::Document::Ptr doc);
     void sourceFilesRefreshed(const QStringList &files);
-    void extraDiagnosticsUpdated(QString fileName);
 
     /// \brief Emitted after updateProjectInfo method is called on the model-manager.
     ///
diff --git a/src/plugins/cpptools/cppsemanticinfo.h b/src/plugins/cpptools/cppsemanticinfo.h
index afa3c20f6b6234701e3fad432b16d9ddfcf083a1..5f7e8b302d609aada45dcf60f635a42879162e03 100644
--- a/src/plugins/cpptools/cppsemanticinfo.h
+++ b/src/plugins/cpptools/cppsemanticinfo.h
@@ -42,6 +42,33 @@ namespace CppTools {
 
 class CPPTOOLS_EXPORT SemanticInfo
 {
+public:
+    struct Source
+    {
+        const CPlusPlus::Snapshot snapshot;
+        const QString fileName;
+        const QString code;
+        const int line;
+        const int column;
+        const unsigned revision;
+        const bool force;
+
+        Source()
+            : line(0), column(0), revision(0), force(false)
+        { }
+
+        Source(const CPlusPlus::Snapshot &snapshot,
+               const QString &fileName,
+               const QString &code,
+               int line, int column,
+               unsigned revision,
+               bool force)
+            : snapshot(snapshot), fileName(fileName),
+              code(code), line(line), column(column),
+              revision(revision), force(force)
+        { }
+    };
+
 public:
     typedef TextEditor::HighlightingResult Use;
 
diff --git a/src/plugins/cpptools/cpptoolseditorsupport.cpp b/src/plugins/cpptools/cpptoolseditorsupport.cpp
index 32f1eac904e81b60fff7075c535e42bee0642cc3..bc2e91b56c692bfc94e99f6d383233ac2199fefd 100644
--- a/src/plugins/cpptools/cpptoolseditorsupport.cpp
+++ b/src/plugins/cpptools/cpptoolseditorsupport.cpp
@@ -28,92 +28,439 @@
 ****************************************************************************/
 
 #include "cpptoolseditorsupport.h"
-
 #include "cppmodelmanager.h"
+#include "cpplocalsymbols.h"
+
+#include <utils/runextensions.h>
 
+#include <QList>
+#include <QMutexLocker>
+#include <QTextBlock>
 #include <QTimer>
 
 using namespace CppTools;
 using namespace CppTools::Internal;
 using namespace CPlusPlus;
+using namespace TextEditor;
+
+namespace {
+class FunctionDefinitionUnderCursor: protected ASTVisitor
+{
+    unsigned _line;
+    unsigned _column;
+    DeclarationAST *_functionDefinition;
+
+public:
+    FunctionDefinitionUnderCursor(TranslationUnit *translationUnit)
+        : ASTVisitor(translationUnit),
+          _line(0), _column(0)
+    { }
+
+    DeclarationAST *operator()(AST *ast, unsigned line, unsigned column)
+    {
+        _functionDefinition = 0;
+        _line = line;
+        _column = column;
+        accept(ast);
+        return _functionDefinition;
+    }
+
+protected:
+    virtual bool preVisit(AST *ast)
+    {
+        if (_functionDefinition)
+            return false;
+
+        else if (FunctionDefinitionAST *def = ast->asFunctionDefinition()) {
+            return checkDeclaration(def);
+        }
+
+        else if (ObjCMethodDeclarationAST *method = ast->asObjCMethodDeclaration()) {
+            if (method->function_body)
+                return checkDeclaration(method);
+        }
+
+        return true;
+    }
+
+private:
+    bool checkDeclaration(DeclarationAST *ast)
+    {
+        unsigned startLine, startColumn;
+        unsigned endLine, endColumn;
+        getTokenStartPosition(ast->firstToken(), &startLine, &startColumn);
+        getTokenEndPosition(ast->lastToken() - 1, &endLine, &endColumn);
 
-CppEditorSupport::CppEditorSupport(CppModelManager *modelManager)
-    : QObject(modelManager),
-      _modelManager(modelManager),
-      _updateDocumentInterval(UPDATE_DOCUMENT_DEFAULT_INTERVAL)
+        if (_line > startLine || (_line == startLine && _column >= startColumn)) {
+            if (_line < endLine || (_line == endLine && _column < endColumn)) {
+                _functionDefinition = ast;
+                return false;
+            }
+        }
+
+        return true;
+    }
+};
+
+} // anonymous namespace
+
+CppEditorSupport::CppEditorSupport(CppModelManager *modelManager, BaseTextEditor *textEditor)
+    : QObject(modelManager)
+    , m_modelManager(modelManager)
+    , m_textEditor(textEditor)
+    , m_updateDocumentInterval(UpdateDocumentDefaultInterval)
+    , m_revision(0)
+    , m_cachedContentsEditorRevision(-1)
+    , m_initialized(false)
+    , m_lastHighlightRevision(0)
+    , m_highlightingSupport(modelManager->highlightingSupport(textEditor))
 {
-    _revision = 0;
+    connect(m_modelManager, SIGNAL(documentUpdated(CPlusPlus::Document::Ptr)),
+            this, SLOT(onDocumentUpdated(CPlusPlus::Document::Ptr)));
+
+    if (m_highlightingSupport->requiresSemanticInfo()) {
+        connect(this, SIGNAL(semanticInfoUpdated(CppTools::SemanticInfo)),
+                this, SLOT(startHighlighting()));
+    }
+
+    m_updateDocumentTimer = new QTimer(this);
+    m_updateDocumentTimer->setSingleShot(true);
+    m_updateDocumentTimer->setInterval(m_updateDocumentInterval);
+    connect(m_updateDocumentTimer, SIGNAL(timeout()), this, SLOT(updateDocumentNow()));
 
-    _updateDocumentTimer = new QTimer(this);
-    _updateDocumentTimer->setSingleShot(true);
-    _updateDocumentTimer->setInterval(_updateDocumentInterval);
-    connect(_updateDocumentTimer, SIGNAL(timeout()), this, SLOT(updateDocumentNow()));
+    m_updateEditorTimer = new QTimer(this);
+    m_updateEditorTimer->setInterval(UpdateEditorInterval);
+    m_updateEditorTimer->setSingleShot(true);
+    connect(m_updateEditorTimer, SIGNAL(timeout()),
+            this, SLOT(updateEditorNow()));
+
+    connect(m_textEditor, SIGNAL(contentsChanged()), this, SLOT(updateDocument()));
+    connect(this, SIGNAL(diagnosticsChanged()), this, SLOT(onDiagnosticsChanged()));
+
+    updateDocument();
 }
 
 CppEditorSupport::~CppEditorSupport()
 { }
 
-TextEditor::ITextEditor *CppEditorSupport::textEditor() const
-{ return _textEditor; }
+QString CppEditorSupport::fileName() const
+{
+    return m_textEditor->document()->fileName();
+}
 
-void CppEditorSupport::setTextEditor(TextEditor::ITextEditor *textEditor)
+QString CppEditorSupport::contents() const
 {
-    _textEditor = textEditor;
+    const int editorRev = editorRevision();
+    if (m_cachedContentsEditorRevision != editorRev) {
+        m_cachedContentsEditorRevision = editorRev;
+        m_cachedContents = m_textEditor->textDocument()->contents();
+    }
 
-    if (_textEditor) {
-        connect(_textEditor, SIGNAL(contentsChanged()), this, SIGNAL(contentsChanged()));
-        connect(this, SIGNAL(contentsChanged()), this, SLOT(updateDocument()));
+    return m_cachedContents;
+}
 
-        updateDocument();
-    }
+unsigned CppEditorSupport::editorRevision() const
+{
+    return m_textEditor->editorWidget()->document()->revision();
 }
 
-QString CppEditorSupport::contents()
+void CppEditorSupport::setExtraDiagnostics(const QString &key,
+                                           const QList<Document::DiagnosticMessage> &messages)
 {
-    if (! _textEditor)
-        return QString();
-    else if (! _cachedContents.isEmpty())
-        _cachedContents = _textEditor->textDocument()->contents();
+    {
+        QMutexLocker locker(&m_diagnosticsMutex);
+        m_allDiagnostics.insert(key, messages);
+    }
 
-    return _cachedContents;
+    emit diagnosticsChanged();
 }
 
-unsigned CppEditorSupport::editorRevision() const
+SemanticInfo CppEditorSupport::recalculateSemanticInfo(bool emitSignalWhenFinished)
 {
-    if (_textEditor) {
-        if (TextEditor::BaseTextEditorWidget *ed = qobject_cast<TextEditor::BaseTextEditorWidget *>(_textEditor->widget()))
-            return ed->document()->revision();
-    }
+    m_futureSemanticInfo.cancel();
 
-    return 0;
+    SemanticInfo::Source source = currentSource(false);
+    recalculateSemanticInfoNow(source, emitSignalWhenFinished);
+    return m_lastSemanticInfo;
 }
 
-int CppEditorSupport::updateDocumentInterval() const
-{ return _updateDocumentInterval; }
+void CppEditorSupport::recalculateSemanticInfoDetached(bool force)
+{
+    m_futureSemanticInfo.cancel();
+    SemanticInfo::Source source = currentSource(force);
+    m_futureSemanticInfo = QtConcurrent::run<CppEditorSupport, void>(
+                &CppEditorSupport::recalculateSemanticInfoDetached_helper, this, source);
 
-void CppEditorSupport::setUpdateDocumentInterval(int updateDocumentInterval)
-{ _updateDocumentInterval = updateDocumentInterval; }
+    if (force && !m_highlightingSupport->requiresSemanticInfo())
+        startHighlighting();
+}
 
 void CppEditorSupport::updateDocument()
 {
-    _revision = editorRevision();
+    m_revision = editorRevision();
 
-    if (qobject_cast<TextEditor::BaseTextEditorWidget*>(_textEditor->widget()) != 0)
-        _modelManager->stopEditorSelectionsUpdate();
+    if (qobject_cast<BaseTextEditorWidget*>(m_textEditor->widget()) != 0)
+        m_updateEditorTimer->stop();
 
-    _updateDocumentTimer->start(_updateDocumentInterval);
+    m_updateDocumentTimer->start(m_updateDocumentInterval);
 }
 
 void CppEditorSupport::updateDocumentNow()
 {
-    if (_documentParser.isRunning() || _revision != editorRevision()) {
-        _updateDocumentTimer->start(_updateDocumentInterval);
+    if (m_documentParser.isRunning() || m_revision != editorRevision()) {
+        m_updateDocumentTimer->start(m_updateDocumentInterval);
+    } else {
+        m_updateDocumentTimer->stop();
+
+        if (!m_highlightingSupport->requiresSemanticInfo()) {
+            startHighlighting();
+        }
+
+        const QStringList sourceFiles(m_textEditor->document()->fileName());
+        m_documentParser = m_modelManager->updateSourceFiles(sourceFiles);
+    }
+}
+
+void CppEditorSupport::onDocumentUpdated(Document::Ptr doc)
+{
+    if (doc.isNull())
+        return;
+
+    if (doc->fileName() != fileName())
+        return; // some other document got updated
+
+    if (doc->editorRevision() != editorRevision())
+        return; // outdated content, wait for a new document to be parsed
+
+    // Update the ifdeffed-out blocks:
+    QList<Document::Block> skippedBlocks = doc->skippedBlocks();
+    m_editorUpdates.ifdefedOutBlocks.clear();
+    m_editorUpdates.ifdefedOutBlocks.reserve(skippedBlocks.size());
+    foreach (const Document::Block &block, skippedBlocks) {
+        m_editorUpdates.ifdefedOutBlocks.append(BlockRange(block.begin(), block.end()));
+    }
+
+    if (m_highlightingSupport && !m_highlightingSupport->hightlighterHandlesDiagnostics()) {
+        // Update the parser errors/warnings:
+        static const QString key = QLatin1String("CppTools.ParserDiagnostics");
+        setExtraDiagnostics(key, doc->diagnosticMessages());
+    }
+
+    // update semantic info in a future
+    if (! m_initialized ||
+            (m_textEditor->widget()->isVisible()
+             && (m_lastSemanticInfo.doc.isNull()
+                 || m_lastSemanticInfo.doc->translationUnit()->ast() == 0
+                 || m_lastSemanticInfo.doc->fileName() != fileName()))) {
+        m_initialized = true;
+        recalculateSemanticInfoDetached(/* force = */ true);
+    }
+
+    // notify the editor that the document is updated
+    emit documentUpdated();
+}
+
+void CppEditorSupport::startHighlighting()
+{
+    if (!m_highlightingSupport)
+        return;
+
+    if (!m_textEditor->widget()->isVisible())
+        return;
+
+    if (m_highlightingSupport->requiresSemanticInfo()) {
+        Snapshot snapshot;
+        Document::Ptr doc;
+        unsigned revision;
+        bool forced;
+
+        {
+            QMutexLocker locker(&m_lastSemanticInfoLock);
+            snapshot = m_lastSemanticInfo.snapshot;
+            doc = m_lastSemanticInfo.doc;
+            revision = m_lastSemanticInfo.revision;
+            forced = m_lastSemanticInfo.forced;
+        }
+
+        if (doc.isNull())
+            return;
+        if (!forced && m_lastHighlightRevision == revision)
+            return;
+        m_highlighter.cancel();
+
+        m_highlighter = m_highlightingSupport->highlightingFuture(doc, snapshot);
+        m_lastHighlightRevision = revision;
+        emit highlighterStarted(m_highlighter, m_lastHighlightRevision);
     } else {
-        _updateDocumentTimer->stop();
+        static const Document::Ptr dummyDoc;
+        static const Snapshot dummySnapshot;
+        m_highlighter = m_highlightingSupport->highlightingFuture(dummyDoc, dummySnapshot);
+        m_lastHighlightRevision = editorRevision();
+        emit highlighterStarted(m_highlighter, m_lastHighlightRevision);
+    }
+}
+
+/// \brief This slot puts the new diagnostics into the editorUpdates. This method has to be called
+///        on the UI thread.
+void CppEditorSupport::onDiagnosticsChanged()
+{
+    QList<Document::DiagnosticMessage> allDiagnostics;
+    {
+        QMutexLocker locker(&m_diagnosticsMutex);
+        foreach (const QList<Document::DiagnosticMessage> &msgs, m_allDiagnostics.values())
+            allDiagnostics.append(msgs);
+    }
+
+    if (!m_textEditor)
+        return;
 
-        QStringList sourceFiles(_textEditor->document()->fileName());
-        _cachedContents = _textEditor->textDocument()->contents();
-        _documentParser = _modelManager->updateSourceFiles(sourceFiles);
+    // set up the format for the errors
+    QTextCharFormat errorFormat;
+    errorFormat.setUnderlineStyle(QTextCharFormat::WaveUnderline);
+    errorFormat.setUnderlineColor(Qt::red);
+
+    // set up the format for the warnings.
+    QTextCharFormat warningFormat;
+    warningFormat.setUnderlineStyle(QTextCharFormat::WaveUnderline);
+    warningFormat.setUnderlineColor(Qt::darkYellow);
+
+    QTextDocument *doc = m_textEditor->editorWidget()->document();
+
+    m_editorUpdates.selections.clear();
+    foreach (const Document::DiagnosticMessage &m, allDiagnostics) {
+        QTextEdit::ExtraSelection sel;
+        if (m.isWarning())
+            sel.format = warningFormat;
+        else
+            sel.format = errorFormat;
+
+        QTextCursor c(doc->findBlockByNumber(m.line() - 1));
+        const QString text = c.block().text();
+        if (m.length() > 0 && m.column() + m.length() < (unsigned)text.size()) {
+            int column = m.column() > 0 ? m.column() - 1 : 0;
+            c.setPosition(c.position() + column);
+            c.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, m.length());
+        } else {
+            for (int i = 0; i < text.size(); ++i) {
+                if (! text.at(i).isSpace()) {
+                    c.setPosition(c.position() + i);
+                    break;
+                }
+            }
+            c.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
+        }
+        sel.cursor = c;
+        sel.format.setToolTip(m.text());
+        m_editorUpdates.selections.append(sel);
     }
+
+    m_editorUpdates.revision = doc->revision();
+
+    updateEditor();
+}
+void CppEditorSupport::updateEditor()
+{
+    m_updateEditorTimer->start(UpdateEditorInterval);
+}
+
+void CppEditorSupport::updateEditorNow()
+{
+    if (!m_textEditor)
+        return;
+
+    BaseTextEditorWidget *editorWidget = m_textEditor->editorWidget();
+    if (editorWidget->document()->revision() != m_editorUpdates.revision)
+        return; // outdated
+
+    editorWidget->setExtraSelections(BaseTextEditorWidget::CodeWarningsSelection,
+                                     m_editorUpdates.selections);
+    editorWidget->setIfdefedOutBlocks(m_editorUpdates.ifdefedOutBlocks);
 }
 
+SemanticInfo::Source CppEditorSupport::currentSource(bool force)
+{
+    int line = 0, column = 0;
+    m_textEditor->convertPosition(m_textEditor->editorWidget()->position(), &line, &column);
+
+    const Snapshot snapshot = m_modelManager->snapshot();
+
+    QString code;
+    if (force || m_lastSemanticInfo.revision != editorRevision())
+        code = contents(); // get the source code only when needed.
+
+    const unsigned revision = editorRevision();
+    SemanticInfo::Source source(snapshot, fileName(), code, line, column, revision, force);
+    return source;
+}
+
+void CppEditorSupport::recalculateSemanticInfoNow(const SemanticInfo::Source &source,
+                                                  bool emitSignalWhenFinished,
+                                                  TopLevelDeclarationProcessor *processor)
+{
+    SemanticInfo semanticInfo;
+
+    {
+        QMutexLocker locker(&m_lastSemanticInfoLock);
+        semanticInfo.revision = m_lastSemanticInfo.revision;
+        semanticInfo.forced = source.force;
+
+        if (!source.force
+                && m_lastSemanticInfo.revision == source.revision
+                && m_lastSemanticInfo.doc
+                && m_lastSemanticInfo.doc->translationUnit()->ast()
+                && m_lastSemanticInfo.doc->fileName() == source.fileName) {
+            semanticInfo.snapshot = m_lastSemanticInfo.snapshot; // ### TODO: use the new snapshot.
+            semanticInfo.doc = m_lastSemanticInfo.doc;
+        }
+    }
+
+    if (semanticInfo.doc.isNull()) {
+        semanticInfo.snapshot = source.snapshot;
+        if (source.snapshot.contains(source.fileName)) {
+            Document::Ptr doc = source.snapshot.preprocessedDocument(source.code, source.fileName);
+            if (processor)
+                doc->control()->setTopLevelDeclarationProcessor(processor);
+            doc->check();
+            semanticInfo.doc = doc;
+        }
+    }
+
+    if (semanticInfo.doc) {
+        TranslationUnit *translationUnit = semanticInfo.doc->translationUnit();
+        AST * ast = translationUnit->ast();
+
+        FunctionDefinitionUnderCursor functionDefinitionUnderCursor(semanticInfo.doc->translationUnit());
+        DeclarationAST *currentFunctionDefinition = functionDefinitionUnderCursor(ast, source.line, source.column);
+
+        const LocalSymbols useTable(semanticInfo.doc, currentFunctionDefinition);
+        semanticInfo.revision = source.revision;
+        semanticInfo.localUses = useTable.uses;
+    }
+
+    {
+        QMutexLocker locker(&m_lastSemanticInfoLock);
+        m_lastSemanticInfo = semanticInfo;
+    }
+
+    if (emitSignalWhenFinished)
+        emit semanticInfoUpdated(semanticInfo);
+}
+
+void CppEditorSupport::recalculateSemanticInfoDetached_helper(QFutureInterface<void> &future, SemanticInfo::Source source)
+{
+    class TLDProc: public TopLevelDeclarationProcessor
+    {
+        QFutureInterface<void> m_theFuture;
+
+    public:
+        TLDProc(QFutureInterface<void> &aFuture): m_theFuture(aFuture) {}
+        virtual ~TLDProc() {}
+        virtual bool processDeclaration(DeclarationAST *ast) {
+            Q_UNUSED(ast);
+            return m_theFuture.isCanceled();
+        }
+    };
+
+    TLDProc tldProc(future);
+    recalculateSemanticInfoNow(source, true, &tldProc);
+}
diff --git a/src/plugins/cpptools/cpptoolseditorsupport.h b/src/plugins/cpptools/cpptoolseditorsupport.h
index b6e297abec1291d670e381458d700a12405a1328..c36951c1b388499306f9ad98d76e6f54bb8211da 100644
--- a/src/plugins/cpptools/cpptoolseditorsupport.h
+++ b/src/plugins/cpptools/cpptoolseditorsupport.h
@@ -30,63 +30,154 @@
 #ifndef CPPTOOLSEDITORSUPPORT_H
 #define CPPTOOLSEDITORSUPPORT_H
 
+#include "cpphighlightingsupport.h"
+#include "cppmodelmanager.h"
+#include "cppsemanticinfo.h"
+
+#include <cplusplus/CppDocument.h>
+
+#include <QFuture>
 #include <QObject>
 #include <QPointer>
-#include <QFuture>
-
-QT_BEGIN_NAMESPACE
-class QTimer;
-QT_END_NAMESPACE
+#include <QTimer>
 
 namespace CPlusPlus { class AST; }
 
 namespace TextEditor {
-class ITextEditor;
+class BaseTextEditor;
 class ITextMark;
 } // namespace TextEditor
 
 namespace CppTools {
-namespace Internal {
 
-class CppModelManager;
-
-class CppEditorSupport: public QObject
+/**
+ * \brief The CppEditorSupport class oversees the actions that happen when a C++ text editor updates
+ *        its document.
+ *
+ * The following steps are taken:
+ * 1. the text editor fires a contentsChanged() signal that triggers updateDocument
+ * 2. update document will start a timer, or reset the timer if it was already running. This way
+ *    subsequent updates (e.g. keypresses) get bunched together instead of running the subsequent
+ *    actions for every key press
+ * 3. when the timer from step 2 fires, updateDocumentNow() is triggered. That tells the
+ *    model-manager to update the CPlusPlus::Document by re-indexing it.
+ * 4. when the model-manager finishes, it fires a documentUpdated(CPlusPlus::Document::Ptr) signal,
+ *    that is connected to onDocumentUpdated(CPlusPlus::Document::Ptr), which does 4 things:
+ *    a) updates the ifdeffed-out blocks in the EditorUpdate
+ *    b) calls setExtraDiagnostics with the diagnostics from the parser, which in turn calls
+ *       onDiagnosticsChanged on the UI thread, and that schedules an editor update timer. When this
+ *       timer fires, updateEditorNow() is called, which will apply the updates to the editor.
+ *    c) a semantic-info recalculation is started in a future
+ *    d) the documentUpdated() signal is emitted, which can be used by a widget to do things
+ * 5. semantic-info calculation from 4c is done by a future that calls recalculateSemanticInfoNow(),
+ *    which emits semanticInfoUpdated() when it is finished. Editors can also listen in on this
+ *    signal to do things like highlighting the local usages.
+ * 6. the semanticInfoUpdated() is connected to the startHighlighting() slot, which will start
+ *    another future for doing the semantic highlighting. The highlighterStarted signal is emitted,
+ *    with the highlighting future as a parameter, so editors can hook it up to a QFutureWatcher
+ *    and get notifications.
+ *
+ * Both the semantic info calculation and the highlighting calculation will cancel an already running
+ * future. They will also check that the result of a previous step is not already outdated, meaning
+ * that they check the revision of the editor document to see if a user changed the document while
+ * the calculation was running.
+ */
+class CPPTOOLS_EXPORT CppEditorSupport: public QObject
 {
     Q_OBJECT
 
 public:
-    CppEditorSupport(CppModelManager *modelManager);
+    CppEditorSupport(Internal::CppModelManager *modelManager, TextEditor::BaseTextEditor *textEditor);
     virtual ~CppEditorSupport();
 
-    TextEditor::ITextEditor *textEditor() const;
-    void setTextEditor(TextEditor::ITextEditor *textEditor);
-
-    int updateDocumentInterval() const;
-    void setUpdateDocumentInterval(int updateDocumentInterval);
+    QString fileName() const;
 
-    QString contents();
+    QString contents() const;
     unsigned editorRevision() const;
 
-Q_SIGNALS:
-    void contentsChanged();
+    void setExtraDiagnostics(const QString &key,
+                             const QList<CPlusPlus::Document::DiagnosticMessage> &messages);
+
+    /// Retrieve the semantic info, which will get recalculated on the current
+    /// thread if it is outdate.
+    SemanticInfo recalculateSemanticInfo(bool emitSignalWhenFinished = true);
+
+    /// Recalculates the semantic info in a future, and will emit the semanticInfoUpdated() signal
+    /// when finished.
+    /// \param force do not check if the old semantic info is still valid
+    void recalculateSemanticInfoDetached(bool force = false);
 
-private Q_SLOTS:
+signals:
+    void documentUpdated();
+    void diagnosticsChanged();
+    void semanticInfoUpdated(CppTools::SemanticInfo);
+    void highlighterStarted(QFuture<TextEditor::HighlightingResult>, unsigned revision);
+
+private slots:
     void updateDocument();
     void updateDocumentNow();
 
+    void onDocumentUpdated(CPlusPlus::Document::Ptr doc);
+    void startHighlighting();
+
+    void onDiagnosticsChanged();
+
+    void updateEditor();
+    void updateEditorNow();
+
+private:
+    typedef TextEditor::BaseTextEditorWidget::BlockRange BlockRange;
+    struct EditorUpdates {
+        EditorUpdates()
+            : revision(-1)
+        {}
+        int revision;
+        QList<QTextEdit::ExtraSelection> selections;
+        QList<BlockRange> ifdefedOutBlocks;
+    };
+
+    enum {
+        UpdateDocumentDefaultInterval = 150,
+        UpdateEditorInterval = 300
+    };
+
+private:
+    SemanticInfo::Source currentSource(bool force);
+    void recalculateSemanticInfoNow(const SemanticInfo::Source &source, bool emitSignalWhenFinished,
+                                    CPlusPlus::TopLevelDeclarationProcessor *processor = 0);
+    void recalculateSemanticInfoDetached_helper(QFutureInterface<void> &future,
+                                                SemanticInfo::Source source);
+
 private:
-    enum { UPDATE_DOCUMENT_DEFAULT_INTERVAL = 150 };
-
-    CppModelManager *_modelManager;
-    QPointer<TextEditor::ITextEditor> _textEditor;
-    QTimer *_updateDocumentTimer;
-    int _updateDocumentInterval;
-    unsigned _revision;
-    QFuture<void> _documentParser;
-    QString _cachedContents;
+    Internal::CppModelManager *m_modelManager;
+    QPointer<TextEditor::BaseTextEditor> m_textEditor;
+    QTimer *m_updateDocumentTimer;
+    int m_updateDocumentInterval;
+    unsigned m_revision;
+    QFuture<void> m_documentParser;
+
+    // content caching
+    mutable QString m_cachedContents;
+    mutable int m_cachedContentsEditorRevision;
+
+    QTimer *m_updateEditorTimer;
+    EditorUpdates m_editorUpdates;
+
+    QMutex m_diagnosticsMutex;
+    QHash<QString, QList<CPlusPlus::Document::DiagnosticMessage> > m_allDiagnostics;
+
+    // Semantic info:
+    bool m_initialized;
+    mutable QMutex m_lastSemanticInfoLock;
+    SemanticInfo m_lastSemanticInfo;
+    QFuture<void> m_futureSemanticInfo;
+
+    // Highlighting:
+    unsigned m_lastHighlightRevision;
+    QFuture<TextEditor::HighlightingResult> m_highlighter;
+    QScopedPointer<CppTools::CppHighlightingSupport> m_highlightingSupport;
 };
 
-} // namespace Internal
 } // namespace CppTools
 
 #endif // CPPTOOLSEDITORSUPPORT_H
diff --git a/src/plugins/qmljstools/qmljsfindexportedcpptypes.cpp b/src/plugins/qmljstools/qmljsfindexportedcpptypes.cpp
index 5bbe9e61bd1f59906a115c5a0e4f2ea2bbb7dcc6..74078654db198b4978a8b3a0504f308a59ce6748 100644
--- a/src/plugins/qmljstools/qmljsfindexportedcpptypes.cpp
+++ b/src/plugins/qmljstools/qmljsfindexportedcpptypes.cpp
@@ -703,9 +703,9 @@ void FindExportedCppTypes::operator()(const CPlusPlus::Document::Ptr &document)
     FindExportsVisitor finder(document);
     finder();
     if (CppTools::CppModelManagerInterface *cppModelManager = CppTools::CppModelManagerInterface::instance()) {
-        cppModelManager->setExtraDiagnostics(
-                    document->fileName(), CppTools::CppModelManagerInterface::ExportedQmlTypesDiagnostic,
-                    finder.messages());
+        static const QString kindKey = QLatin1String("QmlJSTools.ExportedQmlTypesDiagnostic");
+        cppModelManager->setExtraDiagnostics(document->fileName(), kindKey,
+                                             finder.messages());
     }
 
     // if nothing was found, done