diff --git a/src/plugins/clangcodemodel/clangcodemodel.pro b/src/plugins/clangcodemodel/clangcodemodel.pro
index 28b111b42eed6b10d2d3f76f1552ce350d8a7389..ebbb29c8e48bbc9debe2ed0c5fee52eb39efd722 100644
--- a/src/plugins/clangcodemodel/clangcodemodel.pro
+++ b/src/plugins/clangcodemodel/clangcodemodel.pro
@@ -17,18 +17,14 @@ contains(DEFINES, CLANG_COMPLETION) {
 }
 
 contains(DEFINES, CLANG_HIGHLIGHTING) {
-    HEADERS += cppcreatemarkers.h clanghighlightingsupport.h
-    SOURCES += cppcreatemarkers.cpp clanghighlightingsupport.cpp
+    HEADERS += cppcreatemarkers.h
+    SOURCES += cppcreatemarkers.cpp
 }
 
-HEADERS += clangutils.h \
-    cxprettyprinter.h
-
-SOURCES += clangutils.cpp \
-    cxprettyprinter.cpp
-
 SOURCES += \
     $$PWD/clangcodemodelplugin.cpp \
+    $$PWD/clangeditordocumentparser.cpp \
+    $$PWD/clangeditordocumentprocessor.cpp \
     $$PWD/sourcemarker.cpp \
     $$PWD/symbol.cpp \
     $$PWD/sourcelocation.cpp \
@@ -48,6 +44,8 @@ SOURCES += \
 
 HEADERS += \
     $$PWD/clangcodemodelplugin.h \
+    $$PWD/clangeditordocumentparser.h \
+    $$PWD/clangeditordocumentprocessor.h \
     $$PWD/clang_global.h \
     $$PWD/sourcemarker.h \
     $$PWD/constants.h \
@@ -68,6 +66,12 @@ HEADERS += \
     $$PWD/raii/scopedclangoptions.h \
     $$PWD/clangmodelmanagersupport.h
 
+HEADERS += clangutils.h \
+    cxprettyprinter.h
+
+SOURCES += clangutils.cpp \
+    cxprettyprinter.cpp
+
 contains(DEFINES, CLANG_INDEXING) {
     HEADERS += \
         $$PWD/clangindexer.h \
diff --git a/src/plugins/clangcodemodel/clangcodemodel.qbs b/src/plugins/clangcodemodel/clangcodemodel.qbs
index 499f2e04928cd6332cb325821582ea4e7bf47b26..1da1f421d6aa7ddd92af77c936fd0e6182f7b05d 100644
--- a/src/plugins/clangcodemodel/clangcodemodel.qbs
+++ b/src/plugins/clangcodemodel/clangcodemodel.qbs
@@ -94,8 +94,6 @@ QtcPlugin {
         name: "Highlighting support"
         condition: product.clangHighlighting
         files: [
-            "clanghighlightingsupport.cpp",
-            "clanghighlightingsupport.h",
             "cppcreatemarkers.cpp",
             "cppcreatemarkers.h",
         ]
@@ -156,6 +154,10 @@ QtcPlugin {
 
     files: [
         "clang_global.h",
+        "clangeditordocumentparser.cpp",
+        "clangeditordocumentparser.h",
+        "clangeditordocumentprocessor.cpp",
+        "clangeditordocumentprocessor.h",
         "clangmodelmanagersupport.cpp",
         "clangmodelmanagersupport.h",
         "clangcodemodelplugin.cpp",
diff --git a/src/plugins/clangcodemodel/clangcodemodelplugin.cpp b/src/plugins/clangcodemodel/clangcodemodelplugin.cpp
index f6297b84a5adc17292580193bab7d94c02c3901c..57e94003c205cf39039b18f1c5b6d46013d9f5c1 100644
--- a/src/plugins/clangcodemodel/clangcodemodelplugin.cpp
+++ b/src/plugins/clangcodemodel/clangcodemodelplugin.cpp
@@ -29,7 +29,6 @@
 
 #include "clangcodemodelplugin.h"
 #include "clangprojectsettingspropertiespage.h"
-#include "fastindexer.h"
 #include "pchmanager.h"
 #include "utils.h"
 
@@ -65,11 +64,9 @@ bool ClangCodeModelPlugin::initialize(const QStringList &arguments, QString *err
     ClangCodeModel::Internal::initializeClang();
 
     PchManager *pchManager = new PchManager(this);
-    FastIndexer *fastIndexer = 0;
 
 #ifdef CLANG_INDEXING
     m_indexer.reset(new ClangIndexer);
-    fastIndexer = m_indexer.data();
     CppTools::CppModelManagerInterface::instance()->setIndexingSupport(m_indexer->indexingSupport());
 #endif // CLANG_INDEXING
 
@@ -80,7 +77,7 @@ bool ClangCodeModelPlugin::initialize(const QStringList &arguments, QString *err
     connect(CppTools::CppModelManagerInterface::instance(), SIGNAL(projectPartsUpdated(ProjectExplorer::Project*)),
             pchManager, SLOT(onProjectPartsUpdated(ProjectExplorer::Project*)));
 
-    m_modelManagerSupport.reset(new ModelManagerSupport(fastIndexer));
+    m_modelManagerSupport.reset(new ModelManagerSupport);
     CppTools::CppModelManagerInterface::instance()->addModelManagerSupport(
                 m_modelManagerSupport.data());
 
diff --git a/src/plugins/clangcodemodel/clangcompletion.cpp b/src/plugins/clangcodemodel/clangcompletion.cpp
index b4456c61b362b5dc72ddcf273372d8a0cc57380f..9fbd1d0f29d0a2516bca38b4c9f96ccae63d2cff 100644
--- a/src/plugins/clangcodemodel/clangcompletion.cpp
+++ b/src/plugins/clangcodemodel/clangcompletion.cpp
@@ -203,15 +203,14 @@ IAssistProcessor *ClangCompletionAssistProvider::createProcessor() const
 }
 
 IAssistInterface *ClangCompletionAssistProvider::createAssistInterface(
-        ProjectExplorer::Project *project, TextEditor::BaseTextEditor *editor,
+        ProjectExplorer::Project *project, const QString &filePath,
         QTextDocument *document, bool isObjCEnabled, int position, AssistReason reason) const
 {
     Q_UNUSED(project);
     Q_UNUSED(isObjCEnabled);
 
-    QString fileName = editor->document()->filePath();
     CppModelManagerInterface *modelManager = CppModelManagerInterface::instance();
-    QList<ProjectPart::Ptr> parts = modelManager->projectPart(fileName);
+    QList<ProjectPart::Ptr> parts = modelManager->projectPart(filePath);
     if (parts.isEmpty())
         parts += modelManager->fallbackProjectPart();
     ProjectPart::HeaderPaths headerPaths;
@@ -220,7 +219,7 @@ IAssistInterface *ClangCompletionAssistProvider::createAssistInterface(
     foreach (ProjectPart::Ptr part, parts) {
         if (part.isNull())
             continue;
-        options = ClangCodeModel::Utils::createClangOptions(part, fileName);
+        options = ClangCodeModel::Utils::createClangOptions(part, filePath);
         pchInfo = PchManager::instance()->pchInfo(part);
         if (!pchInfo.isNull())
             options.append(ClangCodeModel::Utils::createPCHInclusionOptions(pchInfo->fileName()));
@@ -230,7 +229,7 @@ IAssistInterface *ClangCompletionAssistProvider::createAssistInterface(
 
     return new ClangCodeModel::ClangCompletionAssistInterface(
                 m_clangCompletionWrapper,
-                document, position, fileName, reason,
+                document, position, filePath, reason,
                 options, headerPaths, pchInfo);
 }
 
diff --git a/src/plugins/clangcodemodel/clangcompletion.h b/src/plugins/clangcodemodel/clangcompletion.h
index 180d7ec763e37425380b39a0cfe5436a0bc5d708..152439c54aea7a6706414fb18ebe908e8fdf03b4 100644
--- a/src/plugins/clangcodemodel/clangcompletion.h
+++ b/src/plugins/clangcodemodel/clangcompletion.h
@@ -58,7 +58,7 @@ public:
 
     virtual TextEditor::IAssistProcessor *createProcessor() const;
     virtual TextEditor::IAssistInterface *createAssistInterface(
-            ProjectExplorer::Project *project, TextEditor::BaseTextEditor *editor,
+            ProjectExplorer::Project *project, const QString &filePath,
             QTextDocument *document, bool isObjCEnabled, int position,
             TextEditor::AssistReason reason) const;
 
diff --git a/src/plugins/clangcodemodel/clangeditordocumentparser.cpp b/src/plugins/clangcodemodel/clangeditordocumentparser.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f5e40bf6e2843a2b31331c21249637f5fc7dadf1
--- /dev/null
+++ b/src/plugins/clangcodemodel/clangeditordocumentparser.cpp
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "clangeditordocumentparser.h"
+#include "clangutils.h"
+#include "pchinfo.h"
+#include "pchmanager.h"
+
+#include <cpptools/cppmodelmanagerinterface.h>
+#include <cpptools/cppprojects.h>
+#include <cpptools/cppworkingcopy.h>
+
+#include <utils/hostosinfo.h>
+#include <utils/qtcassert.h>
+
+static const bool DebugTiming = qgetenv("QTC_CLANG_VERBOSE") == "1";
+
+namespace {
+
+QStringList createOptions(const QString &filePath, const CppTools::ProjectPart::Ptr &part)
+{
+    using namespace ClangCodeModel;
+
+    QStringList options;
+    if (part.isNull())
+        return options;
+
+    options += QLatin1String("-fspell-checking");
+    options += ClangCodeModel::Utils::createClangOptions(part, filePath);
+
+    if (Internal::PchInfo::Ptr pchInfo = Internal::PchManager::instance()->pchInfo(part))
+        options.append(ClangCodeModel::Utils::createPCHInclusionOptions(pchInfo->fileName()));
+
+    return options;
+}
+
+QString commandLine(const QStringList &options, const QString &fileName)
+{
+    const QStringList allOptions = QStringList(options)
+        << QLatin1String("-fsyntax-only") << fileName;
+    QStringList allOptionsQuoted;
+    foreach (const QString &option, allOptions)
+        allOptionsQuoted.append(QLatin1Char('\'') + option + QLatin1Char('\''));
+    return ::Utils::HostOsInfo::withExecutableSuffix(QLatin1String("clang"))
+        + QLatin1Char(' ') + allOptionsQuoted.join(QLatin1Char(' '));
+}
+
+} // anonymous namespace
+
+namespace ClangCodeModel {
+
+ClangEditorDocumentParser::ClangEditorDocumentParser(const QString &filePath)
+    : BaseEditorDocumentParser(filePath)
+    , m_marker(new ClangCodeModel::SemanticMarker)
+{
+}
+
+void ClangEditorDocumentParser::update(CppTools::WorkingCopy workingCopy)
+{
+    QTC_ASSERT(m_marker, return);
+    QMutexLocker lock(m_marker->mutex());
+    QMutexLocker lock2(&m_mutex);
+
+    updateProjectPart();
+    const QStringList options = createOptions(filePath(), projectPart());
+
+    QTime t;
+    if (DebugTiming) {
+        qDebug("*** Reparse options (cmd line equivalent): %s",
+               commandLine(options, filePath()).toUtf8().constData());
+        t.start();
+    }
+
+    m_marker->setFileName(filePath());
+    m_marker->setCompilationOptions(options);
+    const Internal::UnsavedFiles unsavedFiles = Utils::createUnsavedFiles(workingCopy);
+    m_marker->reparse(unsavedFiles);
+
+    if (DebugTiming)
+        qDebug() << "*** Reparse took" << t.elapsed() << "ms.";
+}
+
+QList<Diagnostic> ClangEditorDocumentParser::diagnostics() const
+{
+    QTC_ASSERT(m_marker, return QList<Diagnostic>());
+    QMutexLocker(m_marker->mutex());
+    return m_marker->diagnostics();
+}
+
+QList<SemanticMarker::Range> ClangEditorDocumentParser::ifdefedOutBlocks() const
+{
+    QTC_ASSERT(m_marker, return QList<SemanticMarker::Range>());
+    QMutexLocker(m_marker->mutex());
+    return m_marker->ifdefedOutBlocks();
+}
+
+SemanticMarker::Ptr ClangEditorDocumentParser::semanticMarker() const
+{
+    return m_marker;
+}
+
+} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clanghighlightingsupport.h b/src/plugins/clangcodemodel/clangeditordocumentparser.h
similarity index 60%
rename from src/plugins/clangcodemodel/clanghighlightingsupport.h
rename to src/plugins/clangcodemodel/clangeditordocumentparser.h
index 69b525f9f59afaed4fe83bbd8c46087075c09402..98017b6512b11f09d8d9164b10d9b8167009d305 100644
--- a/src/plugins/clangcodemodel/clanghighlightingsupport.h
+++ b/src/plugins/clangcodemodel/clangeditordocumentparser.h
@@ -27,43 +27,42 @@
 **
 ****************************************************************************/
 
-#ifndef CLANG_CLANGHIGHLIGHTINGSUPPORT_H
-#define CLANG_CLANGHIGHLIGHTINGSUPPORT_H
 
-#include "clangutils.h"
-#include "cppcreatemarkers.h"
-#include "fastindexer.h"
+#ifndef CLANGEDITORDOCUMENTPARSER_H
+#define CLANGEDITORDOCUMENTPARSER_H
 
-#include <cpptools/cpphighlightingsupport.h>
+#include "semanticmarker.h"
 
-#include <QObject>
-#include <QScopedPointer>
+#include <cpptools/baseeditordocumentparser.h>
+
+#include <utils/qtcoverride.h>
+
+namespace CppTools { class WorkingCopy; }
 
 namespace ClangCodeModel {
 
-class ClangHighlightingSupport: public CppTools::CppHighlightingSupport
+class ClangEditorDocumentParser : public CppTools::BaseEditorDocumentParser
 {
-public:
-    ClangHighlightingSupport(TextEditor::BaseTextDocument *baseTextDocument,
-                             Internal::FastIndexer *fastIndexer);
-    ~ClangHighlightingSupport();
+    Q_OBJECT
 
-    virtual bool requiresSemanticInfo() const
-    { return false; }
+public:
+    typedef QSharedPointer<ClangEditorDocumentParser> Ptr;
 
-    virtual bool hightlighterHandlesDiagnostics() const
-    { return true; }
+public:
+    ClangEditorDocumentParser(const QString &filePath);
 
-    virtual bool hightlighterHandlesIfdefedOutBlocks() const;
+    void update(CppTools::WorkingCopy workingCopy) QTC_OVERRIDE;
 
-    virtual QFuture<TextEditor::HighlightingResult> highlightingFuture(
-            const CPlusPlus::Document::Ptr &doc, const CPlusPlus::Snapshot &snapshot) const;
+    QList<Diagnostic> diagnostics() const;
+    QList<SemanticMarker::Range> ifdefedOutBlocks() const;
+    SemanticMarker::Ptr semanticMarker() const;
 
 private:
-    Internal::FastIndexer *m_fastIndexer;
-    ClangCodeModel::SemanticMarker::Ptr m_semanticMarker;
+    SemanticMarker::Ptr m_marker;
+    QStringList m_options;
+    Internal::UnsavedFiles m_unsavedFiles;
 };
 
 } // namespace ClangCodeModel
 
-#endif // CLANG_CLANGHIGHLIGHTINGSUPPORT_H
+#endif // CLANGEDITORDOCUMENTPARSER_H
diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b73d1015c51a09df1477cb9216a3f5b888ed4cd7
--- /dev/null
+++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp
@@ -0,0 +1,184 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "clangeditordocumentprocessor.h"
+
+#include "cppcreatemarkers.h"
+#include "diagnostic.h"
+#include "pchinfo.h"
+
+#include <cpptools/cpptoolsplugin.h>
+#include <cpptools/cppworkingcopy.h>
+
+#include <cplusplus/CppDocument.h>
+
+#include <utils/qtcassert.h>
+#include <utils/QtConcurrentTools>
+
+static const bool DebugTiming = qgetenv("QTC_CLANG_VERBOSE") == "1";
+
+namespace {
+
+typedef CPlusPlus::Document::DiagnosticMessage CppToolsDiagnostic;
+QList<CppToolsDiagnostic> toCppToolsDiagnostics(
+        const QString &filePath,
+        const QList<ClangCodeModel::Diagnostic> &diagnostics)
+{
+    using namespace ClangCodeModel;
+
+    QList<CppToolsDiagnostic> converted;
+    foreach (const ClangCodeModel::Diagnostic &d, diagnostics) {
+        if (DebugTiming)
+            qDebug() << d.severityAsString() << d.location() << d.spelling();
+
+        if (d.location().fileName() != filePath)
+            continue;
+
+        // TODO: retrieve fix-its for this diagnostic
+
+        int level;
+        switch (d.severity()) {
+        case Diagnostic::Fatal: level = CppToolsDiagnostic::Fatal; break;
+        case Diagnostic::Error: level = CppToolsDiagnostic::Error; break;
+        case Diagnostic::Warning: level = CppToolsDiagnostic::Warning; break;
+        default: continue;
+        }
+        converted.append(CppToolsDiagnostic(level, d.location().fileName(), d.location().line(),
+                                           d.location().column(), d.spelling(), d.length()));
+    }
+
+    return converted;
+}
+
+QList<TextEditor::BlockRange> toTextEditorBlocks(
+        const QList<ClangCodeModel::SemanticMarker::Range> &ranges)
+{
+    QList<TextEditor::BlockRange> result;
+    result.reserve(ranges.size());
+    foreach (const ClangCodeModel::SemanticMarker::Range &range, ranges)
+        result.append(TextEditor::BlockRange(range.first, range.last));
+    return result;
+}
+
+} // anonymous namespace
+
+namespace ClangCodeModel {
+
+ClangEditorDocumentProcessor::ClangEditorDocumentProcessor(TextEditor::BaseTextDocument *document)
+    : BaseEditorDocumentProcessor(document)
+    , m_parser(new ClangEditorDocumentParser(document->filePath()))
+    , m_parserRevision(0)
+    , m_semanticHighlighter(document)
+    , m_builtinProcessor(document, /*enableSemanticHighlighter=*/ false)
+{
+    // Forwarding the semantic info from the builtin processor enables us to provide all
+    // editor (widget) related features that are not yet implemented by the clang plugin.
+    connect(&m_builtinProcessor, &CppTools::BuiltinEditorDocumentProcessor::cppDocumentUpdated,
+            this, &ClangEditorDocumentProcessor::cppDocumentUpdated);
+    connect(&m_builtinProcessor, &CppTools::BuiltinEditorDocumentProcessor::semanticInfoUpdated,
+            this, &ClangEditorDocumentProcessor::semanticInfoUpdated);
+
+    m_semanticHighlighter.setHighlightingRunner(
+        [this]() -> QFuture<TextEditor::HighlightingResult> {
+            const int firstLine = 1;
+            const int lastLine = baseTextDocument()->document()->blockCount();
+
+            CreateMarkers *createMarkers = CreateMarkers::create(m_parser->semanticMarker(),
+                                                                 baseTextDocument()->filePath(),
+                                                                 firstLine, lastLine);
+            return createMarkers->start();
+        });
+}
+
+ClangEditorDocumentProcessor::~ClangEditorDocumentProcessor()
+{
+    m_parserWatcher.cancel();
+    m_parserWatcher.waitForFinished();
+}
+
+void ClangEditorDocumentProcessor::run()
+{
+    // Run clang parser
+    const CppTools::WorkingCopy workingCopy
+        = CppTools::CppModelManagerInterface::instance()->workingCopy();
+
+    disconnect(&m_parserWatcher, &QFutureWatcher<void>::finished,
+               this, &ClangEditorDocumentProcessor::onParserFinished);
+    m_parserWatcher.cancel();
+    m_parserWatcher.setFuture(QFuture<void>());
+
+    m_parserRevision = revision();
+    connect(&m_parserWatcher, &QFutureWatcher<void>::finished,
+            this, &ClangEditorDocumentProcessor::onParserFinished);
+    const QFuture<void> future = QtConcurrent::run(&runParser, parser(), workingCopy);
+    m_parserWatcher.setFuture(future);
+
+    // Run builtin processor
+    m_builtinProcessor.run();
+}
+
+void ClangEditorDocumentProcessor::semanticRehighlight(bool force)
+{
+    m_builtinProcessor.semanticRehighlight(force);
+}
+
+CppTools::SemanticInfo ClangEditorDocumentProcessor::recalculateSemanticInfo()
+{
+    return m_builtinProcessor.recalculateSemanticInfo();
+}
+
+CppTools::BaseEditorDocumentParser *ClangEditorDocumentProcessor::parser()
+{
+    return m_parser.data();
+}
+
+bool ClangEditorDocumentProcessor::isParserRunning() const
+{
+    return m_parserWatcher.isRunning();
+}
+
+void ClangEditorDocumentProcessor::onParserFinished()
+{
+    if (revision() != m_parserRevision)
+        return;
+
+    // Emit ifdefed out blocks
+    const auto ifdefoutBlocks = toTextEditorBlocks(m_parser->ifdefedOutBlocks());
+    emit ifdefedOutBlocksUpdated(revision(), ifdefoutBlocks);
+
+    // Emit code warnings
+    const auto diagnostics = toCppToolsDiagnostics(filePath(), m_parser->diagnostics());
+    const auto codeWarnings = toTextEditorSelections(diagnostics, textDocument());
+    emit codeWarningsUpdated(revision(), codeWarnings);
+
+    // Run semantic highlighter
+    m_semanticHighlighter.run();
+}
+
+} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.h b/src/plugins/clangcodemodel/clangeditordocumentprocessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..cffddbffd5a5ca99da954e06d91e170ddef7e182
--- /dev/null
+++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef CLANGEDITORDOCUMENTPROCESSOR_H
+#define CLANGEDITORDOCUMENTPROCESSOR_H
+
+#include "clangeditordocumentparser.h"
+
+#include <cpptools/baseeditordocumentprocessor.h>
+#include <cpptools/builtineditordocumentprocessor.h>
+#include <cpptools/semantichighlighter.h>
+
+#include <utils/qtcoverride.h>
+
+#include <QFutureWatcher>
+
+namespace ClangCodeModel {
+
+class ClangEditorDocumentProcessor : public CppTools::BaseEditorDocumentProcessor
+{
+    Q_OBJECT
+
+public:
+    ClangEditorDocumentProcessor(TextEditor::BaseTextDocument *document);
+    ~ClangEditorDocumentProcessor();
+
+    // BaseEditorDocumentProcessor interface
+    void run() QTC_OVERRIDE;
+    void semanticRehighlight(bool force) QTC_OVERRIDE;
+    CppTools::SemanticInfo recalculateSemanticInfo() QTC_OVERRIDE;
+    CppTools::BaseEditorDocumentParser *parser() QTC_OVERRIDE;
+    bool isParserRunning() const QTC_OVERRIDE;
+
+private slots:
+    void onParserFinished();
+
+private:
+    QScopedPointer<ClangEditorDocumentParser> m_parser;
+    QFutureWatcher<void> m_parserWatcher;
+    unsigned m_parserRevision;
+
+    CppTools::SemanticHighlighter m_semanticHighlighter;
+    CppTools::BuiltinEditorDocumentProcessor m_builtinProcessor;
+};
+
+} // namespace ClangCodeModel
+
+#endif // CLANGEDITORDOCUMENTPROCESSOR_H
diff --git a/src/plugins/clangcodemodel/clanghighlightingsupport.cpp b/src/plugins/clangcodemodel/clanghighlightingsupport.cpp
deleted file mode 100644
index 85d2b559a3277b7c61b85b6d91f1c8a3d6abbefc..0000000000000000000000000000000000000000
--- a/src/plugins/clangcodemodel/clanghighlightingsupport.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.  For licensing terms and
-** conditions see http://qt.digia.com/licensing.  For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** 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.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights.  These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-****************************************************************************/
-
-#include "clanghighlightingsupport.h"
-
-#include <texteditor/basetextdocument.h>
-
-#include <QTextBlock>
-#include <QTextEdit>
-#include "pchmanager.h"
-
-using namespace ClangCodeModel;
-using namespace ClangCodeModel::Internal;
-using namespace CppTools;
-
-ClangHighlightingSupport::ClangHighlightingSupport(TextEditor::BaseTextDocument *baseTextDocument,
-                                                   FastIndexer *fastIndexer)
-    : CppHighlightingSupport(baseTextDocument)
-    , m_fastIndexer(fastIndexer)
-    , m_semanticMarker(new ClangCodeModel::SemanticMarker)
-{
-}
-
-ClangHighlightingSupport::~ClangHighlightingSupport()
-{
-}
-
-bool ClangHighlightingSupport::hightlighterHandlesIfdefedOutBlocks() const
-{
-#if CINDEX_VERSION_MINOR >= 21
-    return true;
-#else
-    return false;
-#endif
-}
-
-QFuture<TextEditor::HighlightingResult> ClangHighlightingSupport::highlightingFuture(
-        const CPlusPlus::Document::Ptr &doc,
-        const CPlusPlus::Snapshot &snapshot) const
-{
-    Q_UNUSED(doc);
-    Q_UNUSED(snapshot);
-
-    int firstLine = 1;
-    int lastLine = baseTextDocument()->document()->blockCount();
-
-    const QString fileName = baseTextDocument()->filePath();
-    CppModelManagerInterface *modelManager = CppModelManagerInterface::instance();
-    QList<ProjectPart::Ptr> parts = modelManager->projectPart(fileName);
-    if (parts.isEmpty())
-        parts += modelManager->fallbackProjectPart();
-    QStringList options;
-    PchInfo::Ptr pchInfo;
-    foreach (const ProjectPart::Ptr &part, parts) {
-        if (part.isNull())
-            continue;
-        options = Utils::createClangOptions(part, fileName);
-        pchInfo = PchManager::instance()->pchInfo(part);
-        if (!pchInfo.isNull())
-            options.append(ClangCodeModel::Utils::createPCHInclusionOptions(pchInfo->fileName()));
-        if (!options.isEmpty())
-            break;
-    }
-
-    CreateMarkers *createMarkers = CreateMarkers::create(m_semanticMarker,
-                                                         fileName, options,
-                                                         firstLine, lastLine,
-                                                         m_fastIndexer, pchInfo);
-    return createMarkers->start();
-}
diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp
index 4f7430ee5a13cfe995454d42bc9f5b962c2ce0f0..289ab8bde4efbbba4b799df818e9f1e9002a1a64 100644
--- a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp
+++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp
@@ -28,7 +28,7 @@
 ****************************************************************************/
 
 #include "clangcompletion.h"
-#include "clanghighlightingsupport.h"
+#include "clangeditordocumentprocessor.h"
 #include "clangmodelmanagersupport.h"
 
 #include <QCoreApplication>
@@ -36,9 +36,8 @@
 using namespace ClangCodeModel;
 using namespace ClangCodeModel::Internal;
 
-ModelManagerSupport::ModelManagerSupport(FastIndexer *fastIndexer)
+ModelManagerSupport::ModelManagerSupport()
     : m_completionAssistProvider(new ClangCompletionAssistProvider)
-    , m_fastIndexer(fastIndexer)
 {
 }
 
@@ -63,8 +62,8 @@ CppTools::CppCompletionAssistProvider *ModelManagerSupport::completionAssistProv
     return m_completionAssistProvider.data();
 }
 
-CppTools::CppHighlightingSupport *ModelManagerSupport::highlightingSupport(
+CppTools::BaseEditorDocumentProcessor *ModelManagerSupport::editorDocumentProcessor(
         TextEditor::BaseTextDocument *baseTextDocument)
 {
-    return new ClangHighlightingSupport(baseTextDocument, m_fastIndexer);
+    return new ClangCodeModel::ClangEditorDocumentProcessor(baseTextDocument);
 }
diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.h b/src/plugins/clangcodemodel/clangmodelmanagersupport.h
index ef1205be74bc131c01b08954ba764132f604e886..8855ecd5146591328aab382f24cb46866cb84e08 100644
--- a/src/plugins/clangcodemodel/clangmodelmanagersupport.h
+++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.h
@@ -37,26 +37,23 @@
 namespace ClangCodeModel {
 namespace Internal {
 
-class FastIndexer;
-
 class ModelManagerSupport: public CppTools::ModelManagerSupport
 {
     Q_DISABLE_COPY(ModelManagerSupport)
 
 public:
-    ModelManagerSupport(FastIndexer *fastIndexer);
+    ModelManagerSupport();
     virtual ~ModelManagerSupport();
 
     virtual QString id() const;
     virtual QString displayName() const;
 
     virtual CppTools::CppCompletionAssistProvider *completionAssistProvider();
-    virtual CppTools::CppHighlightingSupport *highlightingSupport(
-            TextEditor::BaseTextDocument *baseTextDocument);
+    virtual CppTools::BaseEditorDocumentProcessor *editorDocumentProcessor(
+                TextEditor::BaseTextDocument *baseTextDocument);
 
 private:
     QScopedPointer<CppTools::CppCompletionAssistProvider> m_completionAssistProvider;
-    FastIndexer *m_fastIndexer;
 };
 
 } // namespace Internal
diff --git a/src/plugins/clangcodemodel/cppcreatemarkers.cpp b/src/plugins/clangcodemodel/cppcreatemarkers.cpp
index b88849f3c5aa6d6268258fc33fa11f0eb139d3dd..2bfde48a8d9fa44c5a2a819018b10db5951c4211 100644
--- a/src/plugins/clangcodemodel/cppcreatemarkers.cpp
+++ b/src/plugins/clangcodemodel/cppcreatemarkers.cpp
@@ -30,11 +30,7 @@
 #include "clangutils.h"
 #include "cppcreatemarkers.h"
 
-#include <cpptools/cppmodelmanagerinterface.h>
-#include <cpptools/cppworkingcopy.h>
-
 #include <cplusplus/CppDocument.h>
-#include <utils/hostosinfo.h>
 #include <utils/runextensions.h>
 
 #include <QCoreApplication>
@@ -51,119 +47,52 @@ using namespace CppTools;
 
 CreateMarkers *CreateMarkers::create(SemanticMarker::Ptr semanticMarker,
                                      const QString &fileName,
-                                     const QStringList &options,
-                                     unsigned firstLine, unsigned lastLine,
-                                     FastIndexer *fastIndexer,
-                                     const Internal::PchInfo::Ptr &pchInfo)
+                                     unsigned firstLine, unsigned lastLine)
 {
     if (semanticMarker.isNull())
         return 0;
     else
-        return new CreateMarkers(semanticMarker, fileName, options, firstLine, lastLine, fastIndexer, pchInfo);
+        return new CreateMarkers(semanticMarker, fileName, firstLine, lastLine);
 }
 
 CreateMarkers::CreateMarkers(SemanticMarker::Ptr semanticMarker,
                              const QString &fileName,
-                             const QStringList &options,
-                             unsigned firstLine, unsigned lastLine,
-                             FastIndexer *fastIndexer,
-                             const Internal::PchInfo::Ptr &pchInfo)
+                             unsigned firstLine, unsigned lastLine)
     : m_marker(semanticMarker)
-    , m_pchInfo(pchInfo)
     , m_fileName(fileName)
-    , m_options(options)
     , m_firstLine(firstLine)
     , m_lastLine(lastLine)
-    , m_fastIndexer(fastIndexer)
 {
     Q_ASSERT(!semanticMarker.isNull());
 
     m_flushRequested = false;
     m_flushLine = 0;
-
-    m_unsavedFiles = Utils::createUnsavedFiles(CppModelManagerInterface::instance()->workingCopy());
 }
 
 CreateMarkers::~CreateMarkers()
 { }
 
-static QString commandLine(const QStringList &options, const QString &fileName)
-{
-    const QStringList allOptions = QStringList(options)
-        << QLatin1String("-fsyntax-only") << fileName;
-    QStringList allOptionsQuoted;
-    foreach (const QString &option, allOptions)
-        allOptionsQuoted.append(QLatin1Char('\'') + option + QLatin1Char('\''));
-    return ::Utils::HostOsInfo::withExecutableSuffix(QLatin1String("clang"))
-        + QLatin1Char(' ') + allOptionsQuoted.join(QLatin1Char(' '));
-}
-
 void CreateMarkers::run()
 {
     QMutexLocker lock(m_marker->mutex());
     if (isCanceled())
         return;
 
-    m_options += QLatin1String("-fspell-checking");
-
     QTime t;
     if (DebugTiming) {
         qDebug() << "*** Highlighting from" << m_firstLine << "to" << m_lastLine << "of" << m_fileName;
-        qDebug("***** Options (cmd line equivalent): %s",
-               commandLine(m_options, m_fileName).toUtf8().constData());
         t.start();
     }
 
     m_usages.clear();
-    m_marker->setFileName(m_fileName);
-    m_marker->setCompilationOptions(m_options);
-
-    m_marker->reparse(m_unsavedFiles);
-
-    if (DebugTiming)
-        qDebug() << "*** Reparse for highlighting took" << t.elapsed() << "ms.";
-
-    m_pchInfo.clear();
-
-    typedef CPlusPlus::Document::DiagnosticMessage OtherDiagnostic;
-    QList<OtherDiagnostic> msgs;
-    foreach (const ClangCodeModel::Diagnostic &d, m_marker->diagnostics()) {
-        if (DebugTiming)
-            qDebug() << d.severityAsString() << d.location() << d.spelling();
-
-        if (d.location().fileName() != m_marker->fileName())
-            continue;
 
-        // TODO: retrieve fix-its for this diagnostic
-
-        int level;
-        switch (d.severity()) {
-        case Diagnostic::Fatal: level = OtherDiagnostic::Fatal; break;
-        case Diagnostic::Error: level = OtherDiagnostic::Error; break;
-        case Diagnostic::Warning: level = OtherDiagnostic::Warning; break;
-        default: continue;
-        }
-        msgs.append(OtherDiagnostic(level, d.location().fileName(), d.location().line(),
-                                    d.location().column(), d.spelling(), d.length()));
-    }
     if (isCanceled()) {
         reportFinished();
         return;
     }
 
-    CppModelManagerInterface *mmi = CppModelManagerInterface::instance();
-    static const QString key = QLatin1String("ClangCodeModel.Diagnostics");
-    mmi->setExtraDiagnostics(m_marker->fileName(), key, msgs);
-#if CINDEX_VERSION_MINOR >= 21
-    mmi->setIfdefedOutBlocks(m_marker->fileName(), m_marker->ifdefedOutBlocks());
-#endif
-
-    if (isCanceled()) {
-        reportFinished();
-        return;
-    }
-
-    QList<ClangCodeModel::SourceMarker> markers = m_marker->sourceMarkersInRange(m_firstLine, m_lastLine);
+    const QList<ClangCodeModel::SourceMarker> markers
+        = m_marker->sourceMarkersInRange(m_firstLine, m_lastLine);
     foreach (const ClangCodeModel::SourceMarker &m, markers)
         addUse(SourceMarker(m.location().line(), m.location().column(), m.length(), m.kind()));
 
@@ -179,12 +108,6 @@ void CreateMarkers::run()
         qDebug() << "*** Highlighting took" << t.elapsed() << "ms in total.";
         t.restart();
     }
-
-    if (m_fastIndexer)
-        m_fastIndexer->indexNow(m_marker->unit());
-
-    if (DebugTiming)
-        qDebug() << "*** Fast re-indexing took" << t.elapsed() << "ms in total.";
 }
 
 void CreateMarkers::addUse(const SourceMarker &marker)
diff --git a/src/plugins/clangcodemodel/cppcreatemarkers.h b/src/plugins/clangcodemodel/cppcreatemarkers.h
index c372e4b08e4ea9549cc8812a5d8c753b06cf1be8..e602161302e0b1196011ac74c2dd24200d644470 100644
--- a/src/plugins/clangcodemodel/cppcreatemarkers.h
+++ b/src/plugins/clangcodemodel/cppcreatemarkers.h
@@ -37,7 +37,6 @@
 
 #include <texteditor/semantichighlighter.h>
 
-#include <QSet>
 #include <QFuture>
 #include <QtConcurrentRun>
 
@@ -70,35 +69,23 @@ public:
     }
 
     static CreateMarkers *create(ClangCodeModel::SemanticMarker::Ptr semanticMarker,
-                                 const QString &fileName,
-                                 const QStringList &options,
-                                 unsigned firstLine, unsigned lastLine,
-                                 Internal::FastIndexer *fastIndexer,
-                                 const Internal::PchInfo::Ptr &pchInfo);
+                                 const QString &fileName, unsigned firstLine, unsigned lastLine);
 
     void addUse(const SourceMarker &marker);
     void flush();
 
 protected:
     CreateMarkers(ClangCodeModel::SemanticMarker::Ptr semanticMarker,
-                  const QString &fileName, const QStringList &options,
-                  unsigned firstLine, unsigned lastLine,
-                  Internal::FastIndexer *fastIndexer,
-                  const Internal::PchInfo::Ptr &pchInfo);
+                  const QString &fileName, unsigned firstLine, unsigned lastLine);
 
 private:
     ClangCodeModel::SemanticMarker::Ptr m_marker;
-    Internal::PchInfo::Ptr m_pchInfo;
     QString m_fileName;
-    QStringList m_options;
     unsigned m_firstLine;
     unsigned m_lastLine;
-    Internal::FastIndexer *m_fastIndexer;
     QVector<SourceMarker> m_usages;
     bool m_flushRequested;
     unsigned m_flushLine;
-
-    ClangCodeModel::Internal::UnsavedFiles m_unsavedFiles;
 };
 
 } // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/semanticmarker.cpp b/src/plugins/clangcodemodel/semanticmarker.cpp
index f1b9a71a2507ad0228176ed1fa6777b4bcf74a2b..e367c3a0f700d0967abb2fcfdd2dc7a9e76b42ab 100644
--- a/src/plugins/clangcodemodel/semanticmarker.cpp
+++ b/src/plugins/clangcodemodel/semanticmarker.cpp
@@ -32,6 +32,8 @@
 #include "utils_p.h"
 #include "cxraii.h"
 
+#include <utils/qtcassert.h>
+
 using namespace ClangCodeModel;
 using namespace ClangCodeModel::Internal;
 
@@ -74,7 +76,7 @@ void SemanticMarker::setFileName(const QString &fileName)
 
 void SemanticMarker::setCompilationOptions(const QStringList &options)
 {
-    Q_ASSERT(m_unit);
+    QTC_ASSERT(m_unit, return);
 
     if (m_unit->compilationOptions() == options)
         return;
@@ -84,7 +86,7 @@ void SemanticMarker::setCompilationOptions(const QStringList &options)
 
 void SemanticMarker::reparse(const UnsavedFiles &unsavedFiles)
 {
-    Q_ASSERT(m_unit);
+    QTC_ASSERT(m_unit, return);
 
     m_unit->setUnsavedFiles(unsavedFiles);
     if (m_unit->isLoaded())
@@ -169,9 +171,9 @@ QList<Diagnostic> SemanticMarker::diagnostics() const
     return diagnostics;
 }
 
-QList<TextEditor::BlockRange> SemanticMarker::ifdefedOutBlocks() const
+QList<SemanticMarker::Range> SemanticMarker::ifdefedOutBlocks() const
 {
-    QList<TextEditor::BlockRange> blocks;
+    QList<Range> blocks;
 
     if (!m_unit || !m_unit->isLoaded())
         return blocks;
@@ -188,7 +190,7 @@ QList<TextEditor::BlockRange> SemanticMarker::ifdefedOutBlocks() const
         const SourceLocation &spellEnd = Internal::getSpellingLocation(clang_getRangeEnd(r));
         const int begin = spellBegin.offset() + 1;
         const int end = spellEnd.offset() - spellEnd.column();
-        blocks.append(TextEditor::BlockRange(begin, end));
+        blocks.append(Range(begin, end));
     }
     clang_disposeSourceRangeList(skippedRanges);
 #endif
@@ -322,9 +324,8 @@ static const QSet<QString> ObjcPseudoKeywords = QSet<QString>()
 QList<SourceMarker> SemanticMarker::sourceMarkersInRange(unsigned firstLine,
                                                          unsigned lastLine)
 {
-    Q_ASSERT(m_unit);
-
     QList<SourceMarker> result;
+    QTC_ASSERT(m_unit, return result);
 
     if (!m_unit->isLoaded())
         return result;
diff --git a/src/plugins/clangcodemodel/semanticmarker.h b/src/plugins/clangcodemodel/semanticmarker.h
index 744aece1c6021b2b6cfa271e19fed2e000d089b1..0ec3979ffcd205b98758925586f9ed612b011837 100644
--- a/src/plugins/clangcodemodel/semanticmarker.h
+++ b/src/plugins/clangcodemodel/semanticmarker.h
@@ -36,8 +36,6 @@
 #include "sourcemarker.h"
 #include "utils.h"
 
-#include <texteditor/basetexteditor.h>
-
 #include <QMutex>
 #include <QScopedPointer>
 #include <QSharedPointer>
@@ -53,6 +51,16 @@ class CLANG_EXPORT SemanticMarker
 public:
     typedef QSharedPointer<SemanticMarker> Ptr;
 
+    class Range
+    {
+        Range();
+    public:
+        Range(int first, int last) : first(first), last(last) {}
+
+        int first;
+        int last;
+    };
+
 public:
     SemanticMarker();
     ~SemanticMarker();
@@ -69,7 +77,7 @@ public:
 
     QList<Diagnostic> diagnostics() const;
 
-    QList<TextEditor::BlockRange> ifdefedOutBlocks() const;
+    QList<Range> ifdefedOutBlocks() const;
 
     QList<SourceMarker> sourceMarkersInRange(unsigned firstLine,
                                              unsigned lastLine);
diff --git a/src/plugins/cppeditor/cppcodemodelinspectordialog.cpp b/src/plugins/cppeditor/cppcodemodelinspectordialog.cpp
index 0cc424c567651dab07d6391c8427de4cbbf3b542..892df8b2460ddb85eb3c1df2c65bf801c06188b6 100644
--- a/src/plugins/cppeditor/cppcodemodelinspectordialog.cpp
+++ b/src/plugins/cppeditor/cppcodemodelinspectordialog.cpp
@@ -30,12 +30,13 @@
 #include "cppcodemodelinspectordialog.h"
 #include "ui_cppcodemodelinspectordialog.h"
 #include "cppeditor.h"
+#include "cppeditordocument.h"
 
 #include <coreplugin/editormanager/editormanager.h>
 #include <coreplugin/icore.h>
+#include <cpptools/builtineditordocumentparser.h>
 #include <cpptools/cppcodemodelinspectordumper.h>
 #include <cpptools/cppmodelmanager.h>
-#include <cpptools/cpptoolseditorsupport.h>
 #include <cpptools/cppworkingcopy.h>
 #include <projectexplorer/project.h>
 
@@ -1358,11 +1359,13 @@ void CppCodeModelInspectorDialog::refresh()
     dumper.dumpSnapshot(globalSnapshot, globalSnapshotTitle, /*isGlobalSnapshot=*/ true);
 
     TextEditor::BaseTextEditor *editor = currentEditor();
-    CppEditorSupport *editorSupport = 0;
+    EditorDocumentHandle *editorDocument = 0;
     if (editor) {
-        editorSupport = cmmi->cppEditorSupport(editor);
-        if (editorSupport) {
-            const CPlusPlus::Snapshot editorSnapshot = editorSupport->documentParser()->snapshot();
+        const QString editorFilePath = editor->document()->filePath();
+        editorDocument = cmmi->editorDocument(editorFilePath);
+        if (editorDocument) {
+            const CPlusPlus::Snapshot editorSnapshot
+                = BuiltinEditorDocumentParser::get(editorFilePath)->snapshot();
             m_snapshotInfos->append(SnapshotInfo(editorSnapshot, SnapshotInfo::EditorSnapshot));
             const QString editorSnapshotTitle
                 = QString::fromLatin1("Current Editor's Snapshot (%1 Documents)")
@@ -1412,8 +1415,8 @@ void CppCodeModelInspectorDialog::refresh()
     onSnapshotSelected(snapshotIndex);
 
     // Project Parts
-    const ProjectPart::Ptr editorsProjectPart = editorSupport
-        ? editorSupport->documentParser()->projectPart()
+    const ProjectPart::Ptr editorsProjectPart = editorDocument
+        ? editorDocument->processor()->parser()->projectPart()
         : ProjectPart::Ptr();
 
     const QList<ProjectInfo> projectInfos = cmmi->projectInfos();
diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp
index c832a334530dc18b5854b3c99185e370f184ba48..c133b3c3e3cf4212e092e185d22eaf968fb502b7 100644
--- a/src/plugins/cppeditor/cppeditor.cpp
+++ b/src/plugins/cppeditor/cppeditor.cpp
@@ -33,6 +33,7 @@
 #include "cppcanonicalsymbol.h"
 #include "cppdocumentationcommenthelper.h"
 #include "cppeditorconstants.h"
+#include "cppeditordocument.h"
 #include "cppeditoroutline.h"
 #include "cppeditorplugin.h"
 #include "cppfollowsymbolundercursor.h"
@@ -40,18 +41,18 @@
 #include "cpplocalrenaming.h"
 #include "cpppreprocessordialog.h"
 #include "cppquickfixassistant.h"
+#include "cppuseselectionsupdater.h"
 
 #include <coreplugin/actionmanager/actioncontainer.h>
 #include <coreplugin/actionmanager/actionmanager.h>
 
+#include <cpptools/cppchecksymbols.h>
 #include <cpptools/cppchecksymbols.h>
 #include <cpptools/cppcodeformatter.h>
 #include <cpptools/cppcompletionassistprovider.h>
-#include <cpptools/cpphighlightingsupport.h>
 #include <cpptools/cppmodelmanagerinterface.h>
 #include <cpptools/cppsemanticinfo.h>
 #include <cpptools/cpptoolsconstants.h>
-#include <cpptools/cpptoolseditorsupport.h>
 #include <cpptools/cpptoolsplugin.h>
 #include <cpptools/cpptoolsreuse.h>
 #include <cpptools/cppworkingcopy.h>
@@ -67,14 +68,11 @@
 #include <texteditor/fontsettings.h>
 #include <texteditor/refactoroverlay.h>
 
-#include <utils/qtcassert.h>
-
 #include <cplusplus/ASTPath.h>
-#include <cplusplus/BackwardsScanner.h>
-#include <cplusplus/ExpressionUnderCursor.h>
-#include <cplusplus/OverviewModel.h>
+#include <utils/qtcassert.h>
 
 #include <QAction>
+#include <QElapsedTimer>
 #include <QFutureWatcher>
 #include <QMenu>
 #include <QPointer>
@@ -83,10 +81,7 @@
 #include <QTimer>
 #include <QToolButton>
 
-enum {
-    UPDATE_USES_INTERVAL = 500,
-    UPDATE_FUNCTION_DECL_DEF_LINK_INTERVAL = 200
-};
+enum { UPDATE_FUNCTION_DECL_DEF_LINK_INTERVAL = 200 };
 
 using namespace CPlusPlus;
 using namespace CppTools;
@@ -103,7 +98,9 @@ CPPEditor::CPPEditor()
     setDuplicateSupported(true);
     setCommentStyle(Utils::CommentDefinition::CppStyle);
     setCompletionAssistProvider([this] () -> TextEditor::CompletionAssistProvider * {
-        return CppModelManagerInterface::instance()->cppEditorSupport(this)->completionAssistProvider();
+        if (CPPEditorDocument *document = qobject_cast<CPPEditorDocument *>(textDocument()))
+            return document->completionAssistProvider();
+        return 0;
     });
 }
 
@@ -122,21 +119,14 @@ public:
 
     CppDocumentationCommentHelper m_cppDocumentationCommentHelper;
 
-    QTimer m_updateUsesTimer;
     QTimer m_updateFunctionDeclDefLinkTimer;
-    QHash<int, QTextCharFormat> m_semanticHighlightFormatMap;
 
     CppLocalRenaming m_localRenaming;
 
     CppTools::SemanticInfo m_lastSemanticInfo;
     QList<TextEditor::QuickFixOperation::Ptr> m_quickFixes;
 
-    QScopedPointer<QFutureWatcher<TextEditor::HighlightingResult> > m_highlightWatcher;
-    unsigned m_highlightRevision; // the editor revision that requested the highlight
-
-    QScopedPointer<QFutureWatcher<QList<int> > > m_referencesWatcher;
-    unsigned m_referencesRevision;
-    int m_referencesCursorPosition;
+    CppUseSelectionsUpdater m_useSelectionsUpdater;
 
     FunctionDeclDefLinkFinder *m_declDefLinkFinder;
     QSharedPointer<FunctionDeclDefLink> m_declDefLink;
@@ -151,9 +141,7 @@ CppEditorWidgetPrivate::CppEditorWidgetPrivate(CppEditorWidget *q)
     , m_cppEditorOutline(new CppEditorOutline(q))
     , m_cppDocumentationCommentHelper(q)
     , m_localRenaming(q)
-    , m_highlightRevision(0)
-    , m_referencesRevision(0)
-    , m_referencesCursorPosition(0)
+    , m_useSelectionsUpdater(q)
     , m_declDefLinkFinder(new FunctionDeclDefLinkFinder(q))
     , m_followSymbolUnderCursor(new FollowSymbolUnderCursor(q))
     , m_preprocessorButton(0)
@@ -162,28 +150,27 @@ CppEditorWidgetPrivate::CppEditorWidgetPrivate(CppEditorWidget *q)
 
 CppEditorWidget::CppEditorWidget(TextEditor::BaseTextDocumentPtr doc, CPPEditor *editor)
 {
+    qRegisterMetaType<SemanticInfo>("CppTools::SemanticInfo");
+
     editor->setEditorWidget(this);
 
     setTextDocument(doc);
     d.reset(new CppEditorWidgetPrivate(this));
     setAutoCompleter(new CppAutoCompleter);
-
-    qRegisterMetaType<SemanticInfo>("CppTools::SemanticInfo");
-
-    setParenthesesMatchingEnabled(true);
-    setMarksVisible(true);
+    setLanguageSettingsId(CppTools::Constants::CPP_SETTINGS_ID);
     setCodeFoldingSupported(true);
+    setMarksVisible(true);
+    setParenthesesMatchingEnabled(true);
     setRevisionsVisible(true);
 
-    if (d->m_modelManager) {
-        CppEditorSupport *editorSupport = d->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>*,uint)),
-                this, SLOT(highlighterStarted(QFuture<TextEditor::HighlightingResult>*,uint)));
-    }
+    connect(d->m_cppEditorDocument, &CPPEditorDocument::codeWarningsUpdated,
+            this, &CppEditorWidget::onCodeWarningsUpdated);
+    connect(d->m_cppEditorDocument, &CPPEditorDocument::ifdefedOutBlocksUpdated,
+            this, &CppEditorWidget::onIfdefedOutBlocksUpdated);
+    connect(d->m_cppEditorDocument, SIGNAL(cppDocumentUpdated(CPlusPlus::Document::Ptr)),
+            this, SLOT(onCppDocumentUpdated()));
+    connect(d->m_cppEditorDocument, SIGNAL(semanticInfoUpdated(CppTools::SemanticInfo)),
+            this, SLOT(updateSemanticInfo(CppTools::SemanticInfo)));
 
     connect(d->m_declDefLinkFinder, SIGNAL(foundLink(QSharedPointer<FunctionDeclDefLink>)),
             this, SLOT(onFunctionDeclDefLinkFound(QSharedPointer<FunctionDeclDefLink>)));
@@ -191,39 +178,42 @@ CppEditorWidget::CppEditorWidget(TextEditor::BaseTextDocumentPtr doc, CPPEditor
     connect(textDocument(), SIGNAL(filePathChanged(QString,QString)),
             this, SLOT(onFilePathChanged()));
 
-    connect(&d->m_localRenaming, SIGNAL(finished()),
-            this, SLOT(onLocalRenamingFinished()));
-    connect(&d->m_localRenaming, SIGNAL(processKeyPressNormally(QKeyEvent*)),
-            this, SLOT(onLocalRenamingProcessKeyPressNormally(QKeyEvent*)));
-
-    // Tool bar creation
-    d->m_updateUsesTimer.setSingleShot(true);
-    d->m_updateUsesTimer.setInterval(UPDATE_USES_INTERVAL);
-
-    connect(&d->m_updateUsesTimer, &QTimer::timeout,
-            this, &CppEditorWidget::updateUsesNow);
+    connect(&d->m_useSelectionsUpdater,
+            SIGNAL(selectionsForVariableUnderCursorUpdated(QList<QTextEdit::ExtraSelection>)),
+            &d->m_localRenaming,
+            SLOT(updateSelectionsForVariableUnderCursor(QList<QTextEdit::ExtraSelection>)));
 
-    d->m_updateFunctionDeclDefLinkTimer.setSingleShot(true);
-    d->m_updateFunctionDeclDefLinkTimer.setInterval(UPDATE_FUNCTION_DECL_DEF_LINK_INTERVAL);
+    connect(&d->m_useSelectionsUpdater, &CppUseSelectionsUpdater::finished,
+            [this] (CppTools::SemanticInfo::LocalUseMap localUses) {
+                QTC_CHECK(isSemanticInfoValidExceptLocalUses());
+                d->m_lastSemanticInfo.localUsesUpdated = true;
+                d->m_lastSemanticInfo.localUses = localUses;
+    });
 
-    connect(&d->m_updateFunctionDeclDefLinkTimer, &QTimer::timeout,
-            this, &CppEditorWidget::updateFunctionDeclDefLinkNow);
+    connect(&d->m_localRenaming, &CppLocalRenaming::finished, [this] {
+        cppEditorDocument()->semanticRehighlight();
+    });
+    connect(&d->m_localRenaming, &CppLocalRenaming::processKeyPressNormally,
+            this, &CppEditorWidget::processKeyNormally);
 
     connect(this, SIGNAL(cursorPositionChanged()),
             d->m_cppEditorOutline, SLOT(updateIndex()));
 
-    // set up slots to document changes
-    connect(document(), SIGNAL(contentsChange(int,int,int)),
-            this, SLOT(onContentsChanged(int,int,int)));
-
     // set up function declaration - definition link
+    d->m_updateFunctionDeclDefLinkTimer.setSingleShot(true);
+    d->m_updateFunctionDeclDefLinkTimer.setInterval(UPDATE_FUNCTION_DECL_DEF_LINK_INTERVAL);
+    connect(&d->m_updateFunctionDeclDefLinkTimer, SIGNAL(timeout()),
+            this, SLOT(updateFunctionDeclDefLinkNow()));
     connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(updateFunctionDeclDefLink()));
     connect(this, SIGNAL(textChanged()), this, SLOT(updateFunctionDeclDefLink()));
 
-    // set up the semantic highlighter
-    connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(updateUses()));
-    connect(this, SIGNAL(textChanged()), this, SLOT(updateUses()));
+    // set up the use highlighitng
+    connect(this, &CppEditorWidget::cursorPositionChanged, [this]() {
+        if (!d->m_localRenaming.isActive())
+            d->m_useSelectionsUpdater.scheduleUpdate();
+    });
 
+    // Tool bar creation
     d->m_preprocessorButton = new QToolButton(this);
     d->m_preprocessorButton->setText(QLatin1String("#"));
     Core::Command *cmd = Core::ActionManager::command(Constants::OPEN_PREPROCESSOR_DIALOG);
@@ -232,13 +222,25 @@ CppEditorWidget::CppEditorWidget(TextEditor::BaseTextDocumentPtr doc, CPPEditor
     connect(d->m_preprocessorButton, SIGNAL(clicked()), this, SLOT(showPreProcessorWidget()));
     insertExtraToolBarWidget(TextEditor::BaseTextEditorWidget::Left, d->m_preprocessorButton);
     insertExtraToolBarWidget(TextEditor::BaseTextEditorWidget::Left, d->m_cppEditorOutline->widget());
-    setLanguageSettingsId(CppTools::Constants::CPP_SETTINGS_ID);
 }
 
 CppEditorWidget::~CppEditorWidget()
 {
-    if (d->m_modelManager)
-        d->m_modelManager->deleteCppEditorSupport(editor());
+    // non-inline destructor, see section "Forward Declared Pointers" of QScopedPointer.
+}
+
+CppEditorWidget *CppEditorWidget::duplicate(CPPEditor *editor) const
+{
+    QTC_ASSERT(editor, return 0);
+
+    CppEditorWidget *widget = new CppEditorWidget(textDocumentPtr(), editor);
+    widget->updateSemanticInfo(semanticInfo());
+    widget->updateFunctionDeclDefLink();
+    widget->d->m_cppEditorOutline->update();
+    const ExtraSelectionKind selectionKind = CodeWarningsSelection;
+    widget->setExtraSelections(selectionKind, extraSelections(selectionKind));
+
+    return widget;
 }
 
 CPPEditorDocument *CppEditorWidget::cppEditorDocument() const
@@ -266,7 +268,7 @@ void CppEditorWidget::paste()
 
 void CppEditorWidget::cut()
 {
-    if (d->m_localRenaming.handlePaste())
+    if (d->m_localRenaming.handleCut())
         return;
 
     BaseTextEditorWidget::cut();
@@ -280,13 +282,27 @@ void CppEditorWidget::selectAll()
     BaseTextEditorWidget::selectAll();
 }
 
-/// \brief Called by \c CppEditorSupport when the document corresponding to the
-///        file in this editor is updated.
-void CppEditorWidget::onDocumentUpdated()
+void CppEditorWidget::onCppDocumentUpdated()
 {
     d->m_cppEditorOutline->update();
 }
 
+void CppEditorWidget::onCodeWarningsUpdated(unsigned revision,
+                                            const QList<QTextEdit::ExtraSelection> selections)
+{
+    if (revision != documentRevision())
+        return;
+    setExtraSelections(BaseTextEditorWidget::CodeWarningsSelection, selections);
+}
+
+void CppEditorWidget::onIfdefedOutBlocksUpdated(unsigned revision,
+    const QList<TextEditor::BlockRange> ifdefedOutBlocks)
+{
+    if (revision != documentRevision())
+        return;
+    setIfdefedOutBlocks(ifdefedOutBlocks);
+}
+
 void CppEditorWidget::findUsages()
 {
     if (!d->m_modelManager)
@@ -325,140 +341,23 @@ void CppEditorWidget::renameUsages(const QString &replacement)
     }
 }
 
-void CppEditorWidget::markSymbolsNow()
-{
-    QTC_ASSERT(d->m_referencesWatcher, return);
-    if (!d->m_referencesWatcher->isCanceled()
-            && d->m_referencesCursorPosition == position()
-            && d->m_referencesRevision == editorRevision()) {
-        const SemanticInfo info = d->m_lastSemanticInfo;
-        TranslationUnit *unit = info.doc->translationUnit();
-        const QList<int> result = d->m_referencesWatcher->result();
-
-        QList<QTextEdit::ExtraSelection> selections;
-
-        foreach (int index, result) {
-            unsigned line, column;
-            unit->getTokenPosition(index, &line, &column);
-
-            if (column)
-                --column;  // adjust the column position.
-
-            const int len = unit->tokenAt(index).utf16chars();
-
-            QTextCursor cursor(document()->findBlockByNumber(line - 1));
-            cursor.setPosition(cursor.position() + column);
-            cursor.setPosition(cursor.position() + len, QTextCursor::KeepAnchor);
-
-            QTextEdit::ExtraSelection sel;
-            sel.format = textCharFormat(TextEditor::C_OCCURRENCES);
-            sel.cursor = cursor;
-            selections.append(sel);
-        }
-
-        setExtraSelections(CodeSemanticsSelection, selections);
-    }
-    d->m_referencesWatcher.reset();
-}
-
-static QList<int> lazyFindReferences(Scope *scope, QString code, Document::Ptr doc,
-                                     Snapshot snapshot)
-{
-    TypeOfExpression typeOfExpression;
-    snapshot.insert(doc);
-    typeOfExpression.init(doc, snapshot);
-    // make possible to instantiate templates
-    typeOfExpression.setExpandTemplates(true);
-    if (Symbol *canonicalSymbol = CanonicalSymbol::canonicalSymbol(scope, code, typeOfExpression))
-        return CppModelManagerInterface::instance()->references(canonicalSymbol,
-                                                                typeOfExpression.context());
-    return QList<int>();
-}
-
-void CppEditorWidget::markSymbols(const QTextCursor &tc, const SemanticInfo &info)
-{
-    d->m_localRenaming.stop();
-
-    if (!info.doc)
-        return;
-    const QTextCharFormat &occurrencesFormat = textCharFormat(TextEditor::C_OCCURRENCES);
-    if (const Macro *macro = CppTools::findCanonicalMacro(textCursor(), info.doc)) {
-        QList<QTextEdit::ExtraSelection> selections;
-
-        //Macro definition
-        if (macro->fileName() == info.doc->fileName()) {
-            QTextCursor cursor(document());
-            cursor.setPosition(macro->utf16CharOffset());
-            cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor,
-                                macro->nameToQString().size());
-
-            QTextEdit::ExtraSelection sel;
-            sel.format = occurrencesFormat;
-            sel.cursor = cursor;
-            selections.append(sel);
-        }
-
-        //Other macro uses
-        foreach (const Document::MacroUse &use, info.doc->macroUses()) {
-            const Macro &useMacro = use.macro();
-            if (useMacro.line() != macro->line()
-                    || useMacro.utf16CharOffset() != macro->utf16CharOffset()
-                    || useMacro.length() != macro->length()
-                    || useMacro.fileName() != macro->fileName())
-                continue;
-
-            QTextCursor cursor(document());
-            cursor.setPosition(use.utf16charsBegin());
-            cursor.setPosition(use.utf16charsEnd(), QTextCursor::KeepAnchor);
-
-            QTextEdit::ExtraSelection sel;
-            sel.format = occurrencesFormat;
-            sel.cursor = cursor;
-            selections.append(sel);
-        }
-
-        setExtraSelections(CodeSemanticsSelection, selections);
-    } else {
-        CanonicalSymbol cs(info.doc, info.snapshot);
-        QString expression;
-        if (Scope *scope = cs.getScopeAndExpression(tc, &expression)) {
-            if (d->m_referencesWatcher)
-                d->m_referencesWatcher->cancel();
-            d->m_referencesWatcher.reset(new QFutureWatcher<QList<int> >);
-            connect(d->m_referencesWatcher.data(), SIGNAL(finished()), SLOT(markSymbolsNow()));
-
-            d->m_referencesRevision = info.revision;
-            d->m_referencesCursorPosition = position();
-            d->m_referencesWatcher->setFuture(
-                QtConcurrent::run(&lazyFindReferences, scope, expression, info.doc, info.snapshot));
-        } else {
-            const QList<QTextEdit::ExtraSelection> selections = extraSelections(CodeSemanticsSelection);
-
-            if (!selections.isEmpty())
-                setExtraSelections(CodeSemanticsSelection, QList<QTextEdit::ExtraSelection>());
-        }
-    }
-}
-
 void CppEditorWidget::renameSymbolUnderCursor()
 {
-    if (!d->m_modelManager)
-        return;
+    updateSemanticInfo(d->m_cppEditorDocument->recalculateSemanticInfo());
 
-    CppEditorSupport *ces = d->m_modelManager->cppEditorSupport(editor());
-    updateSemanticInfo(ces->recalculateSemanticInfo());
+    d->m_useSelectionsUpdater.abortSchedule();
 
-    if (!d->m_localRenaming.start()) // Rename local symbol
-        renameUsages(); // Rename non-local symbol or macro
-}
-
-void CppEditorWidget::onContentsChanged(int position, int charsRemoved, int charsAdded)
-{
-    Q_UNUSED(position)
-    Q_UNUSED(charsAdded)
+    // Trigger once the use selections updater is finished and thus has updated
+    // the use selections for the local renaming
+    QSharedPointer<QMetaObject::Connection> connection(new QMetaObject::Connection);
+    *connection.data() = connect(&d->m_useSelectionsUpdater, &CppUseSelectionsUpdater::finished,
+        [this, connection] () {
+            QObject::disconnect(*connection);
+            if (!d->m_localRenaming.start()) // Rename local symbol
+                renameUsages(); // Rename non-local symbol or macro
+        });
 
-    if (charsRemoved > 0)
-        updateUses();
+    d->m_useSelectionsUpdater.update();
 }
 
 void CppEditorWidget::updatePreprocessorButtonTooltip()
@@ -469,80 +368,6 @@ void CppEditorWidget::updatePreprocessorButtonTooltip()
     d->m_preprocessorButton->setToolTip(cmd->action()->toolTip());
 }
 
-QList<QTextEdit::ExtraSelection> CppEditorWidget::createSelectionsFromUses(
-        const QList<SemanticInfo::Use> &uses)
-{
-    QList<QTextEdit::ExtraSelection> result;
-    const bool isUnused = uses.size() == 1;
-
-    foreach (const SemanticInfo::Use &use, uses) {
-        if (use.isInvalid())
-            continue;
-
-        QTextEdit::ExtraSelection sel;
-        if (isUnused)
-            sel.format = textCharFormat(TextEditor::C_OCCURRENCES_UNUSED);
-        else
-            sel.format = textCharFormat(TextEditor::C_OCCURRENCES);
-
-        const int position = document()->findBlockByNumber(use.line - 1).position() + use.column - 1;
-        const int anchor = position + use.length;
-
-        sel.cursor = QTextCursor(document());
-        sel.cursor.setPosition(anchor);
-        sel.cursor.setPosition(position, QTextCursor::KeepAnchor);
-
-        result.append(sel);
-    }
-
-    return result;
-}
-
-void CppEditorWidget::updateUses()
-{
-    // Block premature semantic info calculation when editor is created.
-    if (d->m_modelManager && d->m_modelManager->cppEditorSupport(editor())->initialized())
-        d->m_updateUsesTimer.start();
-}
-
-void CppEditorWidget::updateUsesNow()
-{
-    if (d->m_localRenaming.isActive())
-        return;
-
-    semanticRehighlight();
-}
-
-void CppEditorWidget::highlightSymbolUsages(int from, int to)
-{
-    if (editorRevision() != d->m_highlightRevision)
-        return; // outdated
-
-    else if (!d->m_highlightWatcher || d->m_highlightWatcher->isCanceled())
-        return; // aborted
-
-    TextEditor::SyntaxHighlighter *highlighter = textDocument()->syntaxHighlighter();
-    QTC_ASSERT(highlighter, return);
-
-    TextEditor::SemanticHighlighter::incrementalApplyExtraAdditionalFormats(
-                highlighter, d->m_highlightWatcher->future(), from, to, d->m_semanticHighlightFormatMap);
-}
-
-void CppEditorWidget::finishHighlightSymbolUsages()
-{
-    QTC_ASSERT(d->m_highlightWatcher, return);
-    if (!d->m_highlightWatcher->isCanceled()
-            && editorRevision() == d->m_highlightRevision
-            && !d->m_lastSemanticInfo.doc.isNull()) {
-        TextEditor::SyntaxHighlighter *highlighter = textDocument()->syntaxHighlighter();
-        QTC_CHECK(highlighter);
-        if (highlighter)
-            TextEditor::SemanticHighlighter::clearExtraAdditionalFormatsUntilEnd(highlighter,
-                d->m_highlightWatcher->future());
-    }
-    d->m_highlightWatcher.reset();
-}
-
 void CppEditorWidget::switchDeclarationDefinition(bool inNextSplit)
 {
     if (!d->m_modelManager)
@@ -624,17 +449,19 @@ CppEditorWidget::Link CppEditorWidget::findLinkAt(const QTextCursor &cursor, boo
                                                   inNextSplit);
 }
 
-unsigned CppEditorWidget::editorRevision() const
+unsigned CppEditorWidget::documentRevision() const
 {
     return document()->revision();
 }
 
-bool CppEditorWidget::isOutdated() const
+bool CppEditorWidget::isSemanticInfoValidExceptLocalUses() const
 {
-    if (d->m_lastSemanticInfo.revision != editorRevision())
-        return true;
+    return d->m_lastSemanticInfo.doc && d->m_lastSemanticInfo.revision == documentRevision();
+}
 
-    return false;
+bool CppEditorWidget::isSemanticInfoValid() const
+{
+    return isSemanticInfoValidExceptLocalUses() && d->m_lastSemanticInfo.localUsesUpdated;
 }
 
 SemanticInfo CppEditorWidget::semanticInfo() const
@@ -665,6 +492,11 @@ void CppEditorWidget::performQuickFix(int index)
     op->perform();
 }
 
+void CppEditorWidget::processKeyNormally(QKeyEvent *e)
+{
+    BaseTextEditorWidget::keyPressEvent(e);
+}
+
 void CppEditorWidget::contextMenuEvent(QContextMenuEvent *e)
 {
     // ### enable
@@ -681,7 +513,7 @@ void CppEditorWidget::contextMenuEvent(QContextMenuEvent *e)
 
     QSignalMapper mapper;
     connect(&mapper, SIGNAL(mapped(int)), this, SLOT(performQuickFix(int)));
-    if (!isOutdated()) {
+    if (isSemanticInfoValid()) {
         TextEditor::IAssistInterface *interface =
             createAssistInterface(TextEditor::QuickFix, TextEditor::ExplicitlyInvoked);
         if (interface) {
@@ -735,7 +567,7 @@ void CppEditorWidget::keyPressEvent(QKeyEvent *e)
 Core::IEditor *CPPEditor::duplicate()
 {
     CPPEditor *editor = new CPPEditor;
-    CppEditorWidget *widget = new CppEditorWidget(editorWidget()->textDocumentPtr(), editor);
+    CppEditorWidget *widget = qobject_cast<CppEditorWidget *>(editorWidget())->duplicate(editor);
     CppEditorPlugin::instance()->initializeEditor(widget);
     editor->configureCodeAssistant();
     return editor;
@@ -751,32 +583,8 @@ bool CPPEditor::open(QString *errorString, const QString &fileName, const QStrin
 
 void CppEditorWidget::applyFontSettings()
 {
-    const TextEditor::FontSettings &fs = textDocument()->fontSettings();
-
-    d->m_semanticHighlightFormatMap[CppHighlightingSupport::TypeUse] =
-            fs.toTextCharFormat(TextEditor::C_TYPE);
-    d->m_semanticHighlightFormatMap[CppHighlightingSupport::LocalUse] =
-            fs.toTextCharFormat(TextEditor::C_LOCAL);
-    d->m_semanticHighlightFormatMap[CppHighlightingSupport::FieldUse] =
-            fs.toTextCharFormat(TextEditor::C_FIELD);
-    d->m_semanticHighlightFormatMap[CppHighlightingSupport::EnumerationUse] =
-            fs.toTextCharFormat(TextEditor::C_ENUMERATION);
-    d->m_semanticHighlightFormatMap[CppHighlightingSupport::VirtualMethodUse] =
-            fs.toTextCharFormat(TextEditor::C_VIRTUAL_METHOD);
-    d->m_semanticHighlightFormatMap[CppHighlightingSupport::LabelUse] =
-            fs.toTextCharFormat(TextEditor::C_LABEL);
-    d->m_semanticHighlightFormatMap[CppHighlightingSupport::MacroUse] =
-            fs.toTextCharFormat(TextEditor::C_PREPROCESSOR);
-    d->m_semanticHighlightFormatMap[CppHighlightingSupport::FunctionUse] =
-            fs.toTextCharFormat(TextEditor::C_FUNCTION);
-    d->m_semanticHighlightFormatMap[CppHighlightingSupport::PseudoKeywordUse] =
-            fs.toTextCharFormat(TextEditor::C_KEYWORD);
-    d->m_semanticHighlightFormatMap[CppHighlightingSupport::StringUse] =
-            fs.toTextCharFormat(TextEditor::C_STRING);
-
-    // this also makes the document apply font settings
+    // This also makes the document apply font settings
     TextEditor::BaseTextEditorWidget::applyFontSettings();
-    semanticRehighlight(true);
 }
 
 void CppEditorWidget::slotCodeStyleSettingsChanged(const QVariant &)
@@ -820,84 +628,15 @@ bool CppEditorWidget::openCppEditorAt(const Link &link, bool inNextSplit)
                                              flags);
 }
 
-void CppEditorWidget::semanticRehighlight(bool force)
-{
-    if (d->m_modelManager) {
-        const CppEditorSupport::ForceReason forceReason = force
-                ? CppEditorSupport::ForceDueEditorRequest
-                : CppEditorSupport::NoForce;
-        d->m_modelManager->cppEditorSupport(editor())->recalculateSemanticInfoDetached(forceReason);
-    }
-}
-
-void CppEditorWidget::highlighterStarted(QFuture<TextEditor::HighlightingResult> *highlighter,
-                                         unsigned revision)
-{
-    d->m_highlightRevision = revision;
-
-    d->m_highlightWatcher.reset(new QFutureWatcher<TextEditor::HighlightingResult>);
-    connect(d->m_highlightWatcher.data(), SIGNAL(resultsReadyAt(int,int)),
-            SLOT(highlightSymbolUsages(int,int)));
-    connect(d->m_highlightWatcher.data(), SIGNAL(finished()),
-            SLOT(finishHighlightSymbolUsages()));
-
-    d->m_highlightWatcher->setFuture(QFuture<TextEditor::HighlightingResult>(*highlighter));
-}
-
 void CppEditorWidget::updateSemanticInfo(const SemanticInfo &semanticInfo)
 {
-    if (semanticInfo.revision != editorRevision()) {
-        // got outdated semantic info
-        semanticRehighlight();
+    if (semanticInfo.revision != documentRevision())
         return;
-    }
-
-    d->m_lastSemanticInfo = semanticInfo; // update the semantic info
-
-    int line = 0, column = 0;
-    convertPosition(position(), &line, &column);
 
-    QList<QTextEdit::ExtraSelection> unusedSelections;
-    QList<QTextEdit::ExtraSelection> selections;
+    d->m_lastSemanticInfo = semanticInfo;
 
-    // We can use the semanticInfo's snapshot (and avoid locking), but not its
-    // document, since it doesn't contain expanded macros.
-    LookupContext context(semanticInfo.snapshot.document(textDocument()->filePath()),
-                          semanticInfo.snapshot);
-
-    SemanticInfo::LocalUseIterator it(semanticInfo.localUses);
-    while (it.hasNext()) {
-        it.next();
-        const QList<SemanticInfo::Use> &uses = it.value();
-
-        bool good = false;
-        foreach (const SemanticInfo::Use &use, uses) {
-            unsigned l = line;
-            unsigned c = column + 1; // convertCursorPosition() returns a 0-based column number.
-            if (l == use.line && c >= use.column && c <= (use.column + use.length)) {
-                good = true;
-                break;
-            }
-        }
-
-        if (uses.size() == 1) {
-            if (!CppTools::isOwnershipRAIIType(it.key(), context))
-                unusedSelections << createSelectionsFromUses(uses); // unused declaration
-        } else if (good && selections.isEmpty()) {
-            selections << createSelectionsFromUses(uses);
-        }
-    }
-
-    setExtraSelections(UnusedSymbolSelection, unusedSelections);
-
-    if (!selections.isEmpty()) {
-        setExtraSelections(CodeSemanticsSelection, selections);
-        d->m_localRenaming.updateLocalUseSelections(selections);
-    }  else {
-        markSymbols(textCursor(), semanticInfo);
-    }
-
-    d->m_lastSemanticInfo.forced = false; // clear the forced flag
+    if (!d->m_localRenaming.isActive())
+        d->m_useSelectionsUpdater.update();
 
     // schedule a check for a decl/def link
     updateFunctionDeclDefLink();
@@ -908,16 +647,17 @@ TextEditor::IAssistInterface *CppEditorWidget::createAssistInterface(
     TextEditor::AssistReason reason) const
 {
     if (kind == TextEditor::Completion) {
-        CppEditorSupport *ces = CppModelManagerInterface::instance()->cppEditorSupport(editor());
-        CppCompletionAssistProvider *cap = ces->completionAssistProvider();
-        if (cap) {
+        if (CppCompletionAssistProvider *cap = cppEditorDocument()->completionAssistProvider()) {
             return cap->createAssistInterface(
                             ProjectExplorer::ProjectExplorerPlugin::currentProject(),
-                            editor(), document(), cppEditorDocument()->isObjCEnabled(), position(),
+                            textDocument()->filePath(),
+                            document(),
+                            cppEditorDocument()->isObjCEnabled(),
+                            position(),
                             reason);
         }
     } else if (kind == TextEditor::QuickFix) {
-        if (!semanticInfo().doc || isOutdated())
+        if (!isSemanticInfoValid())
             return 0;
         return new CppQuickFixAssistInterface(const_cast<CppEditorWidget *>(this), reason);
     } else {
@@ -967,8 +707,10 @@ void CppEditorWidget::updateFunctionDeclDefLinkNow()
 {
     if (Core::EditorManager::currentEditor() != editor())
         return;
+
     const Snapshot semanticSnapshot = d->m_lastSemanticInfo.snapshot;
     const Document::Ptr semanticDoc = d->m_lastSemanticInfo.doc;
+
     if (d->m_declDefLink) {
         // update the change marker
         const Utils::ChangeSet changes = d->m_declDefLink->changes(semanticSnapshot);
@@ -978,7 +720,8 @@ void CppEditorWidget::updateFunctionDeclDefLinkNow()
             d->m_declDefLink->showMarker(this);
         return;
     }
-    if (semanticDoc.isNull() || isOutdated())
+
+    if (!isSemanticInfoValidExceptLocalUses())
         return;
 
     Snapshot snapshot = CppModelManagerInterface::instance()->snapshot();
@@ -1012,8 +755,8 @@ void CppEditorWidget::onFilePathChanged()
         additionalDirectives = ProjectExplorer::SessionManager::value(
                     projectFile + QLatin1Char(',') + filePath).toString().toUtf8();
 
-        BuiltinEditorDocumentParser::Ptr parser
-                = d->m_modelManager->cppEditorSupport(editor())->documentParser();
+        BaseEditorDocumentParser *parser = BaseEditorDocumentParser::get(filePath);
+        QTC_ASSERT(parser, return);
         parser->setProjectPart(d->m_modelManager->projectPartForProjectFile(projectFile));
         parser->setEditorDefines(additionalDirectives);
     }
@@ -1052,21 +795,6 @@ void CppEditorWidget::abortDeclDefLink()
     d->m_declDefLink.clear();
 }
 
-void CppEditorWidget::onLocalRenamingFinished()
-{
-    semanticRehighlight(true);
-}
-
-void CppEditorWidget::onLocalRenamingProcessKeyPressNormally(QKeyEvent *e)
-{
-    BaseTextEditorWidget::keyPressEvent(e);
-}
-
-QTextCharFormat CppEditorWidget::textCharFormat(TextEditor::TextStyle category)
-{
-    return textDocument()->fontSettings().toTextCharFormat(category);
-}
-
 void CppEditorWidget::showPreProcessorWidget()
 {
     const QString &fileName = editor()->document()->filePath();
@@ -1080,8 +808,8 @@ void CppEditorWidget::showPreProcessorWidget()
 
     CppPreProcessorDialog preProcessorDialog(this, textDocument()->filePath(), projectParts);
     if (preProcessorDialog.exec() == QDialog::Accepted) {
-        BuiltinEditorDocumentParser::Ptr parser
-                = d->m_modelManager->cppEditorSupport(editor())->documentParser();
+        BaseEditorDocumentParser *parser = BaseEditorDocumentParser::get(fileName);
+        QTC_ASSERT(parser, return);
         const QString &additionals = preProcessorDialog.additionalPreProcessorDirectives();
         parser->setProjectPart(preProcessorDialog.projectPart());
         parser->setEditorDefines(additionals.toUtf8());
diff --git a/src/plugins/cppeditor/cppeditor.h b/src/plugins/cppeditor/cppeditor.h
index d7c6df96f35346689d040086a1feb3cad33921ab..fcf09325b597b704f8287d4820c06f81f3e3f197 100644
--- a/src/plugins/cppeditor/cppeditor.h
+++ b/src/plugins/cppeditor/cppeditor.h
@@ -30,16 +30,11 @@
 #ifndef CPPEDITOR_H
 #define CPPEDITOR_H
 
-#include "cppeditordocument.h"
-
 #include "cppfunctiondecldeflink.h"
 
 #include <texteditor/basetexteditor.h>
-#include <texteditor/semantichighlighter.h>
-#include <texteditor/texteditorconstants.h>
 
 #include <utils/qtcoverride.h>
-#include <utils/uncommentselection.h>
 
 #include <QScopedPointer>
 
@@ -49,9 +44,11 @@ namespace CppTools { class SemanticInfo; }
 namespace CppEditor {
 namespace Internal {
 
+class CPPEditorDocument;
 class CppEditorOutline;
 class CppEditorWidgetPrivate;
 class FollowSymbolUnderCursor;
+class FunctionDeclDefLink;
 
 class CPPEditor : public TextEditor::BaseTextEditor
 {
@@ -78,10 +75,14 @@ public:
     CppEditorWidget(TextEditor::BaseTextDocumentPtr doc, CPPEditor *editor);
     ~CppEditorWidget();
 
+    CppEditorWidget *duplicate(CPPEditor *editor) const;
+
     CPPEditorDocument *cppEditorDocument() const;
     CppEditorOutline *outline() const;
 
     CppTools::SemanticInfo semanticInfo() const;
+    bool isSemanticInfoValidExceptLocalUses() const;
+    bool isSemanticInfoValid() const;
 
     QSharedPointer<FunctionDeclDefLink> declDefLink() const;
     void applyDeclDefLinkChanges(bool jumpToMatch);
@@ -104,10 +105,6 @@ public slots:
     void renameSymbolUnderCursor();
     void renameUsages(const QString &replacement = QString());
 
-    void semanticRehighlight(bool force = false);
-    void highlighterStarted(QFuture<TextEditor::HighlightingResult> *highlighter,
-                            unsigned revision);
-
 protected:
     bool event(QEvent *e) QTC_OVERRIDE;
     void contextMenuEvent(QContextMenuEvent *) QTC_OVERRIDE;
@@ -126,40 +123,31 @@ protected slots:
     void slotCodeStyleSettingsChanged(const QVariant &) QTC_OVERRIDE;
 
 private slots:
-    void updateUses();
-    void updateUsesNow();
     void updateFunctionDeclDefLink();
     void updateFunctionDeclDefLinkNow();
+    void abortDeclDefLink();
+    void onRefactorMarkerClicked(const TextEditor::RefactorMarker &marker);
     void onFunctionDeclDefLinkFound(QSharedPointer<FunctionDeclDefLink> link);
+
     void onFilePathChanged();
-    void onDocumentUpdated();
-    void onContentsChanged(int position, int charsRemoved, int charsAdded);
-    void updatePreprocessorButtonTooltip();
+    void onCppDocumentUpdated();
+
+    void onCodeWarningsUpdated(unsigned revision,
+                               const QList<QTextEdit::ExtraSelection> selections);
+    void onIfdefedOutBlocksUpdated(unsigned revision,
+                                   const QList<TextEditor::BlockRange> ifdefedOutBlocks);
 
     void updateSemanticInfo(const CppTools::SemanticInfo &semanticInfo);
-    void highlightSymbolUsages(int from, int to);
-    void finishHighlightSymbolUsages();
+    void updatePreprocessorButtonTooltip();
 
-    void markSymbolsNow();
     void performQuickFix(int index);
-    void onRefactorMarkerClicked(const TextEditor::RefactorMarker &marker);
-    void abortDeclDefLink();
 
-    void onLocalRenamingFinished();
-    void onLocalRenamingProcessKeyPressNormally(QKeyEvent *e);
+    void processKeyNormally(QKeyEvent *e);
 
 private:
     static bool openCppEditorAt(const Link &, bool inNextSplit = false);
 
-    unsigned editorRevision() const;
-    bool isOutdated() const;
-
-    QTextCharFormat textCharFormat(TextEditor::TextStyle category);
-
-    void markSymbols(const QTextCursor &tc, const CppTools::SemanticInfo &info);
-
-    QList<QTextEdit::ExtraSelection> createSelectionsFromUses(
-            const QList<TextEditor::HighlightingResult> &uses);
+    unsigned documentRevision() const;
 
 private:
     QScopedPointer<CppEditorWidgetPrivate> d;
diff --git a/src/plugins/cppeditor/cppeditor.pro b/src/plugins/cppeditor/cppeditor.pro
index f85c581fb9b7d1b619a37c3558a870af37c3e351..cba69a39f38c0625e6d15f963659f7fc41c483c9 100644
--- a/src/plugins/cppeditor/cppeditor.pro
+++ b/src/plugins/cppeditor/cppeditor.pro
@@ -33,6 +33,7 @@ HEADERS += \
     cppquickfixes.h \
     cppsnippetprovider.h \
     cpptypehierarchy.h \
+    cppuseselectionsupdater.h \
     cppvirtualfunctionassistprovider.h \
     cppvirtualfunctionproposalitem.h
 
@@ -65,6 +66,7 @@ SOURCES += \
     cppquickfixes.cpp \
     cppsnippetprovider.cpp \
     cpptypehierarchy.cpp \
+    cppuseselectionsupdater.cpp \
     cppvirtualfunctionassistprovider.cpp \
     cppvirtualfunctionproposalitem.cpp
 
diff --git a/src/plugins/cppeditor/cppeditor.qbs b/src/plugins/cppeditor/cppeditor.qbs
index 5d6b52aa391ff7b3cfe1e8c16c0c25e6f44d65ed..ea5ae12f045a703f8a60555c9e9c93b351d2f682 100644
--- a/src/plugins/cppeditor/cppeditor.qbs
+++ b/src/plugins/cppeditor/cppeditor.qbs
@@ -52,6 +52,7 @@ QtcPlugin {
         "cppquickfixes.cpp", "cppquickfixes.h",
         "cppsnippetprovider.cpp", "cppsnippetprovider.h",
         "cpptypehierarchy.cpp", "cpptypehierarchy.h",
+        "cppuseselectionsupdater.cpp", "cppuseselectionsupdater.h",
         "cppvirtualfunctionassistprovider.cpp", "cppvirtualfunctionassistprovider.h",
         "cppvirtualfunctionproposalitem.cpp", "cppvirtualfunctionproposalitem.h",
     ]
diff --git a/src/plugins/cppeditor/cppeditordocument.cpp b/src/plugins/cppeditor/cppeditordocument.cpp
index d91126f84bc39c94971fb051299cf45236b383fd..2b79e2a99197bd6ab29028164028127b2f246b52 100644
--- a/src/plugins/cppeditor/cppeditordocument.cpp
+++ b/src/plugins/cppeditor/cppeditordocument.cpp
@@ -32,25 +32,87 @@
 #include "cppeditorconstants.h"
 #include "cpphighlighter.h"
 
+#include <cpptools/builtineditordocumentprocessor.h>
 #include <cpptools/cppcodeformatter.h>
+#include <cpptools/cppcodemodelsettings.h>
+#include <cpptools/cppmodelmanagerinterface.h>
 #include <cpptools/cppqtstyleindenter.h>
 #include <cpptools/cpptoolsconstants.h>
+#include <cpptools/cpptoolsplugin.h>
+
+#include <utils/qtcassert.h>
+#include <utils/runextensions.h>
 
 #include <QTextDocument>
 
+namespace {
+
+CppTools::CppModelManagerInterface *mm()
+{
+    return CppTools::CppModelManagerInterface::instance();
+}
+
+} // anonymous namespace
+
 namespace CppEditor {
 namespace Internal {
 
+enum { processDocumentIntervalInMs = 150 };
+
+class CppEditorDocumentHandle : public CppTools::EditorDocumentHandle
+{
+public:
+    CppEditorDocumentHandle(CppEditor::Internal::CPPEditorDocument *cppEditorDocument)
+        : m_cppEditorDocument(cppEditorDocument)
+        , m_registrationFilePath(cppEditorDocument->filePath())
+    {
+        mm()->registerEditorDocument(this);
+    }
+
+    ~CppEditorDocumentHandle() { mm()->unregisterEditorDocument(m_registrationFilePath); }
+
+    QString filePath() const { return m_cppEditorDocument->filePath(); }
+    QByteArray contents() const { return m_cppEditorDocument->contentsText(); }
+    unsigned revision() const { return m_cppEditorDocument->contentsRevision(); }
+
+    CppTools::BaseEditorDocumentProcessor *processor()
+    { return m_cppEditorDocument->processor(); }
+
+private:
+    CppEditor::Internal::CPPEditorDocument * const m_cppEditorDocument;
+    // The file path of the editor document can change (e.g. by "Save As..."), so make sure
+    // that un-registration happens with the path the document was registered.
+    const QString m_registrationFilePath;
+};
+
 CPPEditorDocument::CPPEditorDocument()
+    : m_fileIsBeingReloaded(false)
+    , m_isObjCEnabled(false)
+    , m_cachedContentsRevision(-1)
+    , m_processorRevision(0)
+    , m_completionAssistProvider(0)
 {
     setId(CppEditor::Constants::CPPEDITOR_ID);
-    connect(this, SIGNAL(tabSettingsChanged()),
-            this, SLOT(invalidateFormatterCache()));
-    connect(this, SIGNAL(mimeTypeChanged()),
-            this, SLOT(onMimeTypeChanged()));
     setSyntaxHighlighter(new CppHighlighter);
     setIndenter(new CppTools::CppQtStyleIndenter);
-    onMimeTypeChanged();
+
+    connect(this, SIGNAL(tabSettingsChanged()), this, SLOT(invalidateFormatterCache()));
+    connect(this, SIGNAL(mimeTypeChanged()), this, SLOT(onMimeTypeChanged()));
+
+    connect(this, SIGNAL(aboutToReload()), this, SLOT(onAboutToReload()));
+    connect(this, SIGNAL(reloadFinished(bool)), this, SLOT(onReloadFinished()));
+    connect(this, SIGNAL(filePathChanged(QString,QString)),
+            this, SLOT(onFilePathChanged(QString,QString)));
+
+    m_processorTimer.setSingleShot(true);
+    m_processorTimer.setInterval(processDocumentIntervalInMs);
+    connect(&m_processorTimer, SIGNAL(timeout()), this, SLOT(processDocument()));
+
+    // See also onFilePathChanged() for more initialization
+}
+
+CPPEditorDocument::~CPPEditorDocument()
+{
 }
 
 bool CPPEditorDocument::isObjCEnabled() const
@@ -58,6 +120,38 @@ bool CPPEditorDocument::isObjCEnabled() const
     return m_isObjCEnabled;
 }
 
+CppTools::CppCompletionAssistProvider *CPPEditorDocument::completionAssistProvider() const
+{
+    return m_completionAssistProvider;
+}
+
+void CPPEditorDocument::semanticRehighlight()
+{
+    CppTools::BaseEditorDocumentProcessor *p = processor();
+    QTC_ASSERT(p, return);
+    p->semanticRehighlight(true);
+}
+
+CppTools::SemanticInfo CPPEditorDocument::recalculateSemanticInfo()
+{
+    CppTools::BaseEditorDocumentProcessor *p = processor();
+    QTC_ASSERT(p, CppTools::SemanticInfo());
+    return p->recalculateSemanticInfo();
+}
+
+QByteArray CPPEditorDocument::contentsText() const
+{
+    QMutexLocker locker(&m_cachedContentsLock);
+
+    const int currentRevision = document()->revision();
+    if (m_cachedContentsRevision != currentRevision && !m_fileIsBeingReloaded) {
+        m_cachedContentsRevision = currentRevision;
+        m_cachedContents = plainText().toUtf8();
+    }
+
+    return m_cachedContents;
+}
+
 void CPPEditorDocument::applyFontSettings()
 {
     if (TextEditor::SyntaxHighlighter *highlighter = syntaxHighlighter()) {
@@ -82,7 +176,94 @@ void CPPEditorDocument::onMimeTypeChanged()
 {
     const QString &mt = mimeType();
     m_isObjCEnabled = (mt == QLatin1String(CppTools::Constants::OBJECTIVE_C_SOURCE_MIMETYPE)
-                   || mt == QLatin1String(CppTools::Constants::OBJECTIVE_CPP_SOURCE_MIMETYPE));
+                       || mt == QLatin1String(CppTools::Constants::OBJECTIVE_CPP_SOURCE_MIMETYPE));
+    m_completionAssistProvider = mm()->completionAssistProvider(mt);
+}
+
+void CPPEditorDocument::onAboutToReload()
+{
+    QTC_CHECK(!m_fileIsBeingReloaded);
+    m_fileIsBeingReloaded = true;
+}
+
+void CPPEditorDocument::onReloadFinished()
+{
+    QTC_CHECK(m_fileIsBeingReloaded);
+    m_fileIsBeingReloaded = false;
+}
+
+void CPPEditorDocument::onFilePathChanged(const QString &oldPath, const QString &newPath)
+{
+    Q_UNUSED(oldPath);
+
+    if (!newPath.isEmpty()) {
+        setMimeType(Core::MimeDatabase::findByFile(QFileInfo(newPath)).type());
+
+        disconnect(this, SIGNAL(contentsChanged()), this, SLOT(scheduleProcessDocument()));
+        connect(this, SIGNAL(contentsChanged()), this, SLOT(scheduleProcessDocument()));
+
+        // Un-Register/Register in ModelManager
+        m_editorDocumentHandle.reset(new CppEditorDocumentHandle(this));
+
+        resetProcessor();
+        m_processorRevision = document()->revision();
+        processDocument();
+    }
+}
+
+void CPPEditorDocument::scheduleProcessDocument()
+{
+    m_processorRevision = document()->revision();
+    m_processorTimer.start(processDocumentIntervalInMs);
+}
+
+void CPPEditorDocument::processDocument()
+{
+    if (processor()->isParserRunning() || m_processorRevision != contentsRevision()) {
+        m_processorTimer.start();
+        return;
+    }
+
+    m_processorTimer.stop();
+    if (m_fileIsBeingReloaded || filePath().isEmpty())
+        return;
+
+    processor()->run();
+}
+
+void CPPEditorDocument::resetProcessor()
+{
+    releaseResources();
+    processor(); // creates a new processor
+}
+
+unsigned CPPEditorDocument::contentsRevision() const
+{
+    return document()->revision();
+}
+
+void CPPEditorDocument::releaseResources()
+{
+    if (m_processor)
+        disconnect(m_processor.data(), 0, this, 0);
+    m_processor.reset();
+}
+
+CppTools::BaseEditorDocumentProcessor *CPPEditorDocument::processor()
+{
+    if (!m_processor) {
+        m_processor.reset(mm()->editorDocumentProcessor(this));
+        connect(m_processor.data(), &CppTools::BaseEditorDocumentProcessor::codeWarningsUpdated,
+                this, &CPPEditorDocument::codeWarningsUpdated);
+        connect(m_processor.data(), &CppTools::BaseEditorDocumentProcessor::ifdefedOutBlocksUpdated,
+                this, &CPPEditorDocument::ifdefedOutBlocksUpdated);
+        connect(m_processor.data(), &CppTools::BaseEditorDocumentProcessor::cppDocumentUpdated,
+                this, &CPPEditorDocument::cppDocumentUpdated);
+        connect(m_processor.data(), &CppTools::BaseEditorDocumentProcessor::semanticInfoUpdated,
+                this, &CPPEditorDocument::semanticInfoUpdated);
+    }
+
+    return m_processor.data();
 }
 
 } // namespace Internal
diff --git a/src/plugins/cppeditor/cppeditordocument.h b/src/plugins/cppeditor/cppeditordocument.h
index 8e2d8ec3f2281db4e87afc966e52d1f2b5232296..5db4c9375cdb527b0ee27e36b67933b228b0bb55 100644
--- a/src/plugins/cppeditor/cppeditordocument.h
+++ b/src/plugins/cppeditor/cppeditordocument.h
@@ -30,28 +30,85 @@
 #ifndef CPPEDITORDOCUMENT_H
 #define CPPEDITORDOCUMENT_H
 
+#include <cpptools/baseeditordocumentprocessor.h>
+#include <cpptools/cppcompletionassistprovider.h>
+#include <cpptools/cppmodelmanagerinterface.h>
+#include <cpptools/cppsemanticinfo.h>
+#include <cpptools/editordocumenthandle.h>
+
 #include <texteditor/basetextdocument.h>
 
+#include <QMutex>
+#include <QTimer>
+
 namespace CppEditor {
 namespace Internal {
 
 class CPPEditorDocument : public TextEditor::BaseTextDocument
 {
     Q_OBJECT
+
+    friend class CppEditorDocumentHandle;
+
 public:
     explicit CPPEditorDocument();
+    ~CPPEditorDocument();
 
     bool isObjCEnabled() const;
+    CppTools::CppCompletionAssistProvider *completionAssistProvider() const;
+
+    void semanticRehighlight();
+    CppTools::SemanticInfo recalculateSemanticInfo(); // TODO: Remove me
+
+signals:
+    void codeWarningsUpdated(unsigned contentsRevision,
+                             const QList<QTextEdit::ExtraSelection> selections);
+
+    void ifdefedOutBlocksUpdated(unsigned contentsRevision,
+                                 const QList<TextEditor::BlockRange> ifdefedOutBlocks);
+
+    void cppDocumentUpdated(const CPlusPlus::Document::Ptr document);    // TODO: Remove me
+    void semanticInfoUpdated(const CppTools::SemanticInfo semanticInfo); // TODO: Remove me
 
 protected:
     void applyFontSettings();
 
 private slots:
     void invalidateFormatterCache();
+    void onFilePathChanged(const QString &oldPath, const QString &newPath);
     void onMimeTypeChanged();
 
+    void onAboutToReload();
+    void onReloadFinished();
+
+    void scheduleProcessDocument();
+    void processDocument();
+
+private:
+    QByteArray contentsText() const;
+    unsigned contentsRevision() const;
+
+    CppTools::BaseEditorDocumentProcessor *processor();
+    void resetProcessor();
+    void releaseResources();
+
 private:
+    bool m_fileIsBeingReloaded;
     bool m_isObjCEnabled;
+
+    // Caching contents
+    mutable QMutex m_cachedContentsLock;
+    mutable QByteArray m_cachedContents;
+    mutable int m_cachedContentsRevision;
+
+    unsigned m_processorRevision;
+    QTimer m_processorTimer;
+    QScopedPointer<CppTools::BaseEditorDocumentProcessor> m_processor;
+
+    CppTools::CppCompletionAssistProvider *m_completionAssistProvider;
+
+    // (Un)Registration in CppModelManager
+    QScopedPointer<CppTools::EditorDocumentHandle> m_editorDocumentHandle;
 };
 
 } // namespace Internal
diff --git a/src/plugins/cppeditor/cppeditorplugin.cpp b/src/plugins/cppeditor/cppeditorplugin.cpp
index 81e5e816536c3bea6a4db5e5b1b6e4d9c8dec00f..f9d3c71a78c385b2f9ab53fbdf82cc74ea9999c8 100644
--- a/src/plugins/cppeditor/cppeditorplugin.cpp
+++ b/src/plugins/cppeditor/cppeditorplugin.cpp
@@ -32,6 +32,7 @@
 #include "cppclasswizard.h"
 #include "cppcodemodelinspectordialog.h"
 #include "cppeditorconstants.h"
+#include "cppeditordocument.h"
 #include "cppeditor.h"
 #include "cppeditoroutline.h"
 #include "cppfilewizard.h"
diff --git a/src/plugins/cppeditor/cppeditortestcase.cpp b/src/plugins/cppeditor/cppeditortestcase.cpp
index 4bb20eedcc2954b5f6599f9d0cbcbafc14c08271..5fca9581e8e7d4dcc94438a4822207a87f251068 100644
--- a/src/plugins/cppeditor/cppeditortestcase.cpp
+++ b/src/plugins/cppeditor/cppeditortestcase.cpp
@@ -31,8 +31,10 @@
 #include "cppeditortestcase.h"
 
 #include "cppeditor.h"
+#include "cppeditordocument.h"
 
 #include <coreplugin/editormanager/editormanager.h>
+#include <cpptools/baseeditordocumentprocessor.h>
 #include <cpptools/cppsemanticinfo.h>
 #include <cplusplus/CppDocument.h>
 
@@ -87,8 +89,10 @@ bool TestCase::openCppEditor(const QString &fileName,
 CPlusPlus::Document::Ptr TestCase::waitForRehighlightedSemanticDocument(
         Internal::CppEditorWidget *editorWidget)
 {
-    editorWidget->semanticRehighlight(true);
-    while (editorWidget->semanticInfo().doc.isNull())
+    const QString filePath = editorWidget->textDocument()->filePath();
+    auto processor = CppTools::BaseEditorDocumentProcessor::get(filePath);
+    processor->semanticRehighlight(false);
+    while (!editorWidget->isSemanticInfoValid())
         QCoreApplication::processEvents();
     return editorWidget->semanticInfo().doc;
 }
diff --git a/src/plugins/cppeditor/cppincludehierarchymodel.cpp b/src/plugins/cppeditor/cppincludehierarchymodel.cpp
index ac5e2e26e6e41ec2dd6dab864869a4564a844fb6..0dfde59238d549a27ef2ecbb4938f023cf70737a 100644
--- a/src/plugins/cppeditor/cppincludehierarchymodel.cpp
+++ b/src/plugins/cppeditor/cppincludehierarchymodel.cpp
@@ -32,8 +32,9 @@
 #include "cppincludehierarchyitem.h"
 
 #include <coreplugin/fileiconprovider.h>
+#include <cpptools/builtineditordocumentparser.h>
 #include <cpptools/cppmodelmanagerinterface.h>
-#include <cpptools/cpptoolseditorsupport.h>
+#include <cpptools/editordocumenthandle.h>
 #include <texteditor/basetexteditor.h>
 
 #include <cplusplus/CppDocument.h>
@@ -43,6 +44,15 @@
 using namespace CPlusPlus;
 using namespace CppTools;
 
+namespace {
+
+Snapshot globalSnapshot()
+{
+    return CppTools::CppModelManagerInterface::instance()->snapshot();
+}
+
+} // anonymous namespace
+
 namespace CppEditor {
 namespace Internal {
 
@@ -161,18 +171,24 @@ void CppIncludeHierarchyModel::fetchMore(const QModelIndex &parent)
         return;
 
     if (parentItem->needChildrenPopulate()) {
+        const QString editorFilePath = m_editor->document()->filePath();
         QSet<QString> cyclic;
-        cyclic << m_editor->document()->filePath();
+        cyclic << editorFilePath;
         CppIncludeHierarchyItem *item = parentItem->parent();
         while (!(item == m_includesItem || item == m_includedByItem)) {
             cyclic << item->filePath();
             item = item->parent();
         }
 
-        if (item == m_includesItem)
-            buildHierarchyIncludes_helper(parentItem->filePath(), parentItem, &cyclic);
-        else
-            buildHierarchyIncludedBy_helper(parentItem->filePath(), parentItem, &cyclic);
+        if (item == m_includesItem) {
+            const Snapshot editorDocumentSnapshot
+                = BuiltinEditorDocumentParser::get(editorFilePath)->snapshot();
+            buildHierarchyIncludes_helper(parentItem->filePath(), parentItem,
+                                          editorDocumentSnapshot, &cyclic);
+        } else {
+            buildHierarchyIncludedBy_helper(parentItem->filePath(), parentItem,
+                                            globalSnapshot(), &cyclic);
+        }
     }
 
 }
@@ -231,19 +247,21 @@ bool CppIncludeHierarchyModel::isEmpty() const
 
 void CppIncludeHierarchyModel::buildHierarchyIncludes(const QString &currentFilePath)
 {
+    if (!m_editor)
+        return;
+
+    const QString editorFilePath = m_editor->document()->filePath();
+    const Snapshot snapshot = BuiltinEditorDocumentParser::get(editorFilePath)->snapshot();
     QSet<QString> cyclic;
-    buildHierarchyIncludes_helper(currentFilePath, m_includesItem, &cyclic);
+    buildHierarchyIncludes_helper(currentFilePath, m_includesItem, snapshot, &cyclic);
 }
 
 void CppIncludeHierarchyModel::buildHierarchyIncludes_helper(const QString &filePath,
                                                              CppIncludeHierarchyItem *parent,
-                                                             QSet<QString> *cyclic, bool recursive)
+                                                             Snapshot snapshot,
+                                                             QSet<QString> *cyclic,
+                                                             bool recursive)
 {
-    if (!m_editor)
-        return;
-
-    CppModelManagerInterface *cppMM = CppModelManagerInterface::instance();
-    const Snapshot &snapshot = cppMM->cppEditorSupport(m_editor)->documentParser()->snapshot();
     Document::Ptr doc = snapshot.document(filePath);
     if (!doc)
         return;
@@ -265,7 +283,7 @@ void CppIncludeHierarchyModel::buildHierarchyIncludes_helper(const QString &file
         }
         item = new CppIncludeHierarchyItem(includedFilePath, parent);
         parent->appendChild(item);
-        buildHierarchyIncludes_helper(includedFilePath, item, cyclic, false);
+        buildHierarchyIncludes_helper(includedFilePath, item, snapshot, cyclic, false);
 
     }
     cyclic->remove(filePath);
@@ -274,16 +292,16 @@ void CppIncludeHierarchyModel::buildHierarchyIncludes_helper(const QString &file
 void CppIncludeHierarchyModel::buildHierarchyIncludedBy(const QString &currentFilePath)
 {
     QSet<QString> cyclic;
-    buildHierarchyIncludedBy_helper(currentFilePath, m_includedByItem, &cyclic);
+    buildHierarchyIncludedBy_helper(currentFilePath, m_includedByItem, globalSnapshot(), &cyclic);
 }
 
 void CppIncludeHierarchyModel::buildHierarchyIncludedBy_helper(const QString &filePath,
                                                                CppIncludeHierarchyItem *parent,
+                                                               Snapshot snapshot,
                                                                QSet<QString> *cyclic,
                                                                bool recursive)
 {
     cyclic->insert(filePath);
-    const Snapshot &snapshot = CppTools::CppModelManagerInterface::instance()->snapshot();
     Snapshot::const_iterator citEnd = snapshot.end();
     for (Snapshot::const_iterator cit = snapshot.begin(); cit != citEnd; ++cit) {
         const QString filePathFromSnapshot = cit.key();
@@ -307,8 +325,9 @@ void CppIncludeHierarchyModel::buildHierarchyIncludedBy_helper(const QString &fi
 
                 if (isCyclic)
                     continue;
-                else
-                    buildHierarchyIncludedBy_helper(filePathFromSnapshot, item, cyclic, false);
+
+                buildHierarchyIncludedBy_helper(filePathFromSnapshot, item, snapshot, cyclic,
+                                                false);
             }
         }
     }
diff --git a/src/plugins/cppeditor/cppincludehierarchymodel.h b/src/plugins/cppeditor/cppincludehierarchymodel.h
index 4a96cbe7a1eb71b97f440d8ce870c72b52c8bbbc..146c9fc03130403f6c7cf392ae5827c7e7a5ea28 100644
--- a/src/plugins/cppeditor/cppincludehierarchymodel.h
+++ b/src/plugins/cppeditor/cppincludehierarchymodel.h
@@ -41,6 +41,7 @@ enum ItemRole {
 
 } // Anonymous
 
+namespace CPlusPlus { class Snapshot; }
 namespace TextEditor { class BaseTextEditor; }
 
 namespace CppEditor {
@@ -72,10 +73,12 @@ public:
 private:
     void buildHierarchyIncludes(const QString &currentFilePath);
     void buildHierarchyIncludes_helper(const QString &filePath, CppIncludeHierarchyItem *parent,
+                                       CPlusPlus::Snapshot snapshot,
                                        QSet<QString> *cyclic, bool recursive = true);
     void buildHierarchyIncludedBy(const QString &currentFilePath);
     void buildHierarchyIncludedBy_helper(const QString &filePath, CppIncludeHierarchyItem *parent,
-                                         QSet<QString> *cyclic, bool recursive = true);
+                                         CPlusPlus::Snapshot snapshot, QSet<QString> *cyclic,
+                                         bool recursive = true);
 
     CppIncludeHierarchyItem *m_rootItem;
     CppIncludeHierarchyItem *m_includesItem;
diff --git a/src/plugins/cppeditor/cpplocalrenaming.cpp b/src/plugins/cppeditor/cpplocalrenaming.cpp
index d2a0c022826ced182cd1873cc8b90c0bd816a1f6..e81b8e66aecb89aae6f5d4ee1062296748530647 100644
--- a/src/plugins/cppeditor/cpplocalrenaming.cpp
+++ b/src/plugins/cppeditor/cpplocalrenaming.cpp
@@ -72,7 +72,8 @@ CppLocalRenaming::CppLocalRenaming(TextEditor::BaseTextEditorWidget *editorWidge
             this, SLOT(onContentsChangeOfEditorWidgetDocument(int,int,int)));
 }
 
-void CppLocalRenaming::updateLocalUseSelections(const QList<QTextEdit::ExtraSelection> &selections)
+void CppLocalRenaming::updateSelectionsForVariableUnderCursor(
+        const QList<QTextEdit::ExtraSelection> &selections)
 {
     QTC_ASSERT(!isActive(), return);
     m_selections = selections;
diff --git a/src/plugins/cppeditor/cpplocalrenaming.h b/src/plugins/cppeditor/cpplocalrenaming.h
index 0e246321eda8526a30aee7fdbf48209fd80c6c80..72d4f2c2d4de65dc1c165a075b47c5aa6146a3aa 100644
--- a/src/plugins/cppeditor/cpplocalrenaming.h
+++ b/src/plugins/cppeditor/cpplocalrenaming.h
@@ -47,8 +47,6 @@ class CppLocalRenaming : public QObject
 public:
     explicit CppLocalRenaming(TextEditor::BaseTextEditorWidget *editorWidget);
 
-    void updateLocalUseSelections(const QList<QTextEdit::ExtraSelection> &selections);
-
     bool start();
     bool isActive() const;
     void stop();
@@ -62,6 +60,9 @@ public:
     // to BaseTextEditorWidget::keyPressEvent()
     bool handleKeyPressEvent(QKeyEvent *e);
 
+public slots:
+    void updateSelectionsForVariableUnderCursor(const QList<QTextEdit::ExtraSelection> &selections);
+
 signals:
     void finished();
     void processKeyPressNormally(QKeyEvent *e);
diff --git a/src/plugins/cppeditor/cppquickfixassistant.cpp b/src/plugins/cppeditor/cppquickfixassistant.cpp
index 5ccf31b71fcacc59a9d2ab666ab22af528867c00..34a79a5f7096056fc9e35a558179fff44f08f57d 100644
--- a/src/plugins/cppeditor/cppquickfixassistant.cpp
+++ b/src/plugins/cppeditor/cppquickfixassistant.cpp
@@ -94,7 +94,9 @@ CppQuickFixAssistInterface::CppQuickFixAssistInterface(CppEditorWidget *editor,
     , m_currentFile(CppRefactoringChanges::file(editor, m_semanticInfo.doc))
     , m_context(m_semanticInfo.doc, m_snapshot)
 {
-    QTC_CHECK(!m_semanticInfo.doc.isNull());
+    QTC_CHECK(m_semanticInfo.doc);
+    QTC_CHECK(m_semanticInfo.doc->translationUnit());
+    QTC_CHECK(m_semanticInfo.doc->translationUnit()->ast());
     CPlusPlus::ASTPath astPath(m_semanticInfo.doc);
     m_path = astPath(editor->textCursor());
 }
diff --git a/src/plugins/cppeditor/cppquickfixes.cpp b/src/plugins/cppeditor/cppquickfixes.cpp
index 0165339b5a0787839c5b2271e2f08aa640a948e9..c6b8001b53d61dff83f143bc52656994a57fe604 100644
--- a/src/plugins/cppeditor/cppquickfixes.cpp
+++ b/src/plugins/cppeditor/cppquickfixes.cpp
@@ -30,6 +30,7 @@
 #include "cppquickfixes.h"
 
 #include "cppeditor.h"
+#include "cppeditordocument.h"
 #include "cppfunctiondecldeflink.h"
 #include "cppquickfixassistant.h"
 #include "cppvirtualfunctionassistprovider.h"
diff --git a/src/plugins/cppeditor/cppuseselections_test.cpp b/src/plugins/cppeditor/cppuseselections_test.cpp
index c99a7a4c2b861433fc4975bf3c9a2db81bc9af98..e1408c3adeb017af6a45fc48ca848b9b0b6a27cf 100644
--- a/src/plugins/cppeditor/cppuseselections_test.cpp
+++ b/src/plugins/cppeditor/cppuseselections_test.cpp
@@ -135,7 +135,7 @@ SelectionList UseSelectionsTestCase::waitForUseSelections(bool *hasTimedOut) con
 
     QList<QTextEdit::ExtraSelection> extraSelections = getExtraSelections();
     while (extraSelections.isEmpty()) {
-        if (timer.hasExpired(500)) {
+        if (timer.hasExpired(2500)) {
             if (hasTimedOut)
                 *hasTimedOut = true;
             break;
diff --git a/src/plugins/cppeditor/cppuseselectionsupdater.cpp b/src/plugins/cppeditor/cppuseselectionsupdater.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e292ac4bcd2dbc468ea34e0a15f175cf10cffcdc
--- /dev/null
+++ b/src/plugins/cppeditor/cppuseselectionsupdater.cpp
@@ -0,0 +1,451 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "cppuseselectionsupdater.h"
+
+#include "cppcanonicalsymbol.h"
+#include "cppeditor.h"
+
+#include <cpptools/cpplocalsymbols.h>
+#include <cpptools/cppmodelmanagerinterface.h>
+#include <cpptools/cpptoolsreuse.h>
+#include <texteditor/basetexteditor.h>
+#include <texteditor/fontsettings.h>
+
+#include <cplusplus/Macro.h>
+#include <cplusplus/TranslationUnit.h>
+
+#include <utils/qtcassert.h>
+
+#include <QtConcurrentRun>
+#include <QTextBlock>
+#include <QTextCursor>
+#include <QTextEdit>
+
+using namespace CPlusPlus;
+
+enum { updateUseSelectionsInternalInMs = 500 };
+
+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;
+
+        if (FunctionDefinitionAST *def = ast->asFunctionDefinition())
+            return checkDeclaration(def);
+
+        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;
+    }
+};
+
+QTextEdit::ExtraSelection extraSelection(const QTextCharFormat &format, const QTextCursor &cursor)
+{
+    QTextEdit::ExtraSelection selection;
+    selection.format = format;
+    selection.cursor = cursor;
+    return selection;
+}
+
+struct Params
+{
+    // Shared
+    Document::Ptr document;
+
+    // For local use calculation
+    int line;
+    int column;
+
+    // For references calculation
+    Scope *scope;
+    QString expression;
+    Snapshot snapshot;
+};
+
+using CppEditor::Internal::SemanticUses;
+
+void splitLocalUses(const CppTools::SemanticInfo::LocalUseMap &uses,
+                    const Params &p,
+                    SemanticUses *selectionsForLocalVariableUnderCursor,
+                    SemanticUses *selectionsForLocalUnusedVariables)
+{
+    QTC_ASSERT(selectionsForLocalVariableUnderCursor, return);
+    QTC_ASSERT(selectionsForLocalUnusedVariables, return);
+
+    LookupContext context(p.document, p.snapshot);
+
+    CppTools::SemanticInfo::LocalUseIterator it(uses);
+    while (it.hasNext()) {
+        it.next();
+        const SemanticUses &uses = it.value();
+
+        bool good = false;
+        foreach (const CppTools::SemanticInfo::Use &use, uses) {
+            unsigned l = p.line;
+            unsigned c = p.column + 1; // convertCursorPosition() returns a 0-based column number.
+            if (l == use.line && c >= use.column && c <= (use.column + use.length)) {
+                good = true;
+                break;
+            }
+        }
+
+        if (uses.size() == 1) {
+            if (!CppTools::isOwnershipRAIIType(it.key(), context))
+                selectionsForLocalUnusedVariables->append(uses); // unused declaration
+        } else if (good && selectionsForLocalVariableUnderCursor->isEmpty()) {
+            selectionsForLocalVariableUnderCursor->append(uses);
+        }
+    }
+}
+
+CppTools::SemanticInfo::LocalUseMap findLocalUses(const Params &p)
+{
+    AST *ast = p.document->translationUnit()->ast();
+    FunctionDefinitionUnderCursor functionDefinitionUnderCursor(p.document->translationUnit());
+    DeclarationAST *declaration = functionDefinitionUnderCursor(ast, p.line, p.column);
+    return CppTools::LocalSymbols(p.document, declaration).uses;
+}
+
+QList<int> findReferences(const Params &p)
+{
+    QList<int> result;
+    if (!p.scope || p.expression.isEmpty())
+        return result;
+
+    TypeOfExpression typeOfExpression;
+    Snapshot snapshot = p.snapshot;
+    snapshot.insert(p.document);
+    typeOfExpression.init(p.document, snapshot);
+    typeOfExpression.setExpandTemplates(true);
+
+    using CppEditor::Internal::CanonicalSymbol;
+    if (Symbol *s = CanonicalSymbol::canonicalSymbol(p.scope, p.expression, typeOfExpression)) {
+        CppTools::CppModelManagerInterface *mmi = CppTools::CppModelManagerInterface::instance();
+        result = mmi->references(s, typeOfExpression.context());
+    }
+
+    return result;
+}
+
+CppEditor::Internal::UseSelectionsResult findUses(const Params p)
+{
+    CppEditor::Internal::UseSelectionsResult result;
+
+    const CppTools::SemanticInfo::LocalUseMap localUses = findLocalUses(p);
+    result.localUses = localUses;
+    splitLocalUses(localUses, p, &result.selectionsForLocalVariableUnderCursor,
+                                 &result.selectionsForLocalUnusedVariables);
+
+    if (!result.selectionsForLocalVariableUnderCursor.isEmpty())
+        return result;
+
+    result.references = findReferences(p);
+    return result; // OK, result.selectionsForLocalUnusedVariables will be passed on
+}
+
+} // anonymous namespace
+
+namespace CppEditor {
+namespace Internal {
+
+CppUseSelectionsUpdater::CppUseSelectionsUpdater(TextEditor::BaseTextEditorWidget *editorWidget)
+    : m_editorWidget(editorWidget)
+    , m_findUsesRevision(-1)
+{
+    m_timer.setSingleShot(true);
+    m_timer.setInterval(updateUseSelectionsInternalInMs);
+    connect(&m_timer, SIGNAL(timeout()), this, SLOT(update()));
+}
+
+void CppUseSelectionsUpdater::scheduleUpdate()
+{
+    m_timer.start();
+}
+
+void CppUseSelectionsUpdater::abortSchedule()
+{
+    m_timer.stop();
+}
+
+void CppUseSelectionsUpdater::update()
+{
+    CppEditorWidget *cppEditorWidget = qobject_cast<CppEditorWidget *>(m_editorWidget);
+    QTC_ASSERT(cppEditorWidget, return);
+    QTC_CHECK(cppEditorWidget->isSemanticInfoValidExceptLocalUses());
+    const CppTools::SemanticInfo semanticInfo = cppEditorWidget->semanticInfo();
+    const Document::Ptr document = semanticInfo.doc;
+    const Snapshot snapshot = semanticInfo.snapshot;
+
+    if (!document || document->editorRevision() != static_cast<unsigned>(textDocument()->revision()))
+        return;
+
+    QTC_ASSERT(document->translationUnit(), return);
+    QTC_ASSERT(document->translationUnit()->ast(), return);
+    QTC_ASSERT(!snapshot.isEmpty(), return);
+
+    QTextCursor textCursor = m_editorWidget->textCursor();
+
+    if (handleMacroCase(textCursor, document)) {
+        emit finished(CppTools::SemanticInfo::LocalUseMap());
+        return;
+    }
+
+    handleSymbolCase(textCursor, document, snapshot);
+}
+
+void CppUseSelectionsUpdater::onFindUsesFinished()
+{
+    QTC_ASSERT(m_findUsesWatcher, return);
+    if (m_findUsesWatcher->isCanceled())
+        return;
+    if (m_findUsesRevision != textDocument()->revision())
+        return;
+    // Optimizable: If the cursor is still on the same identifier the results are valid.
+    if (m_findUsesCursorPosition != m_editorWidget->position())
+        return;
+
+    const UseSelectionsResult result = m_findUsesWatcher->result();
+    const bool hasUsesForLocalVariable = !result.selectionsForLocalVariableUnderCursor.isEmpty();
+    const bool hasReferences = !result.references.isEmpty();
+
+    ExtraSelections localVariableSelections;
+    if (hasUsesForLocalVariable) {
+        localVariableSelections = toExtraSelections(result.selectionsForLocalVariableUnderCursor,
+                                                    TextEditor::C_OCCURRENCES);
+        updateUseSelections(localVariableSelections);
+    } else if (hasReferences) {
+        const ExtraSelections selections = toExtraSelections(result.references,
+                                                             TextEditor::C_OCCURRENCES);
+        updateUseSelections(selections);
+    } else {
+        if (!currentUseSelections().isEmpty())
+            updateUseSelections(ExtraSelections());
+    }
+
+    updateUnusedSelections(toExtraSelections(result.selectionsForLocalUnusedVariables,
+                                             TextEditor::C_OCCURRENCES_UNUSED));
+
+    m_findUsesWatcher.reset();
+    m_document.reset();
+    m_snapshot = Snapshot();
+
+    emit selectionsForVariableUnderCursorUpdated(localVariableSelections);
+    emit finished(result.localUses);
+}
+
+bool CppUseSelectionsUpdater::handleMacroCase(const QTextCursor &textCursor,
+                                              const Document::Ptr document)
+{
+    const Macro *macro = CppTools::findCanonicalMacro(textCursor, document);
+    if (!macro)
+        return false;
+
+    const QTextCharFormat &occurrencesFormat = textCharFormat(TextEditor::C_OCCURRENCES);
+    ExtraSelections selections;
+
+    // Macro definition
+    if (macro->fileName() == document->fileName()) {
+        QTextCursor cursor(textDocument());
+        cursor.setPosition(macro->utf16CharOffset());
+        cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor,
+                            macro->nameToQString().size());
+
+        selections.append(extraSelection(occurrencesFormat, cursor));
+    }
+
+    // Other macro uses
+    foreach (const Document::MacroUse &use, document->macroUses()) {
+        const Macro &useMacro = use.macro();
+        if (useMacro.line() != macro->line()
+                || useMacro.utf16CharOffset() != macro->utf16CharOffset()
+                || useMacro.length() != macro->length()
+                || useMacro.fileName() != macro->fileName())
+            continue;
+
+        QTextCursor cursor(textDocument());
+        cursor.setPosition(use.utf16charsBegin());
+        cursor.setPosition(use.utf16charsEnd(), QTextCursor::KeepAnchor);
+
+        selections.append(extraSelection(occurrencesFormat, cursor));
+    }
+
+    updateUseSelections(selections);
+    return true;
+}
+
+void CppUseSelectionsUpdater::handleSymbolCase(const QTextCursor &textCursor,
+                                               const Document::Ptr document,
+                                               const Snapshot &snapshot)
+{
+    m_document = document;
+    m_snapshot = snapshot;
+
+    if (m_findUsesWatcher)
+        m_findUsesWatcher->cancel();
+    m_findUsesWatcher.reset(new QFutureWatcher<UseSelectionsResult>);
+    connect(m_findUsesWatcher.data(), SIGNAL(finished()), this, SLOT(onFindUsesFinished()));
+
+    m_findUsesRevision = textDocument()->revision();
+    m_findUsesCursorPosition = m_editorWidget->position();
+
+    Params params;
+    params.document = document;
+    m_editorWidget->convertPosition(m_findUsesCursorPosition, &params.line, &params.column);
+    CanonicalSymbol canonicalSymbol(document, snapshot);
+    params.scope = canonicalSymbol.getScopeAndExpression(textCursor, &params.expression);
+    params.snapshot = snapshot;
+
+    m_findUsesWatcher->setFuture(QtConcurrent::run(&findUses, params));
+}
+
+ExtraSelections CppUseSelectionsUpdater::toExtraSelections(const SemanticUses &uses,
+                                                           TextEditor::TextStyle style) const
+{
+    ExtraSelections result;
+
+    foreach (const CppTools::SemanticInfo::Use &use, uses) {
+        if (use.isInvalid())
+            continue;
+
+        QTextDocument *document = textDocument();
+        const int position = document->findBlockByNumber(use.line - 1).position() + use.column - 1;
+        const int anchor = position + use.length;
+
+        QTextEdit::ExtraSelection sel;
+        sel.format = textCharFormat(style);
+        sel.cursor = QTextCursor(document);
+        sel.cursor.setPosition(anchor);
+        sel.cursor.setPosition(position, QTextCursor::KeepAnchor);
+
+        result.append(sel);
+    }
+
+    return result;
+}
+
+ExtraSelections CppUseSelectionsUpdater::toExtraSelections(const QList<int> &references,
+                                                           TextEditor::TextStyle style) const
+{
+    ExtraSelections selections;
+    foreach (int index, references) {
+        unsigned line, column;
+        TranslationUnit *unit = m_document->translationUnit();
+        unit->getTokenPosition(index, &line, &column);
+
+        if (column)
+            --column;  // adjust the column position.
+
+        const int len = unit->tokenAt(index).utf16chars();
+
+        QTextCursor cursor(textDocument()->findBlockByNumber(line - 1));
+        cursor.setPosition(cursor.position() + column);
+        cursor.setPosition(cursor.position() + len, QTextCursor::KeepAnchor);
+
+        selections.append(extraSelection(textCharFormat(style), cursor));
+    }
+
+    return selections;
+}
+
+QTextCharFormat CppUseSelectionsUpdater::textCharFormat(TextEditor::TextStyle category) const
+{
+    return m_editorWidget->textDocument()->fontSettings().toTextCharFormat(category);
+}
+
+QTextDocument *CppUseSelectionsUpdater::textDocument() const
+{
+    return m_editorWidget->document();
+}
+
+ExtraSelections CppUseSelectionsUpdater::currentUseSelections() const
+{
+    return m_editorWidget->extraSelections(
+        TextEditor::BaseTextEditorWidget::CodeSemanticsSelection);
+}
+
+void CppUseSelectionsUpdater::updateUseSelections(const ExtraSelections &selections)
+{
+    m_editorWidget->setExtraSelections(TextEditor::BaseTextEditorWidget::CodeSemanticsSelection,
+                                       selections);
+}
+
+void CppUseSelectionsUpdater::updateUnusedSelections(const ExtraSelections &selections)
+{
+    m_editorWidget->setExtraSelections(TextEditor::BaseTextEditorWidget::UnusedSymbolSelection,
+                                       selections);
+}
+
+} // namespace Internal
+} // namespace CppEditor
diff --git a/src/plugins/cppeditor/cppuseselectionsupdater.h b/src/plugins/cppeditor/cppuseselectionsupdater.h
new file mode 100644
index 0000000000000000000000000000000000000000..277785afa2c009a74f4309e1eb146e7d9c8eee85
--- /dev/null
+++ b/src/plugins/cppeditor/cppuseselectionsupdater.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef CPPUSESELECTIONSUPDATER_H
+#define CPPUSESELECTIONSUPDATER_H
+
+#include <cpptools/cppsemanticinfo.h>
+#include <texteditor/texteditorconstants.h>
+
+#include <cplusplus/CppDocument.h>
+
+#include <QFutureWatcher>
+#include <QTextEdit>
+#include <QTimer>
+
+QT_BEGIN_NAMESPACE
+class QTextCharFormat;
+class QTextCursor;
+QT_END_NAMESPACE
+
+namespace TextEditor { class BaseTextEditorWidget; }
+
+namespace CppEditor {
+namespace Internal {
+
+typedef QList<QTextEdit::ExtraSelection> ExtraSelections;
+typedef QList<CppTools::SemanticInfo::Use> SemanticUses;
+
+struct UseSelectionsResult
+{
+    CppTools::SemanticInfo::LocalUseMap localUses;
+    SemanticUses selectionsForLocalVariableUnderCursor;
+    SemanticUses selectionsForLocalUnusedVariables;
+    QList<int> references;
+};
+
+class CppUseSelectionsUpdater : public QObject
+{
+    Q_OBJECT
+    Q_DISABLE_COPY(CppUseSelectionsUpdater)
+
+public:
+    explicit CppUseSelectionsUpdater(TextEditor::BaseTextEditorWidget *editorWidget);
+
+public slots:
+    void scheduleUpdate();
+    void abortSchedule();
+    void update();
+
+signals:
+    void finished(CppTools::SemanticInfo::LocalUseMap localUses);
+    void selectionsForVariableUnderCursorUpdated(const QList<QTextEdit::ExtraSelection> &);
+
+private slots:
+    void onFindUsesFinished();
+
+private:
+    CppUseSelectionsUpdater();
+
+    bool handleMacroCase(const QTextCursor &textCursor,
+                         const CPlusPlus::Document::Ptr document);
+    void handleSymbolCase(const QTextCursor &textCursor,
+                          const CPlusPlus::Document::Ptr document,
+                          const CPlusPlus::Snapshot &snapshot);
+
+    ExtraSelections toExtraSelections(const SemanticUses &uses, TextEditor::TextStyle style) const;
+    ExtraSelections toExtraSelections(const QList<int> &references,
+                                      TextEditor::TextStyle style) const;
+
+    // Convenience
+    ExtraSelections currentUseSelections() const;
+    void updateUseSelections(const ExtraSelections &selections);
+    void updateUnusedSelections(const ExtraSelections &selections);
+    QTextCharFormat textCharFormat(TextEditor::TextStyle category) const;
+    QTextDocument *textDocument() const;
+
+private:
+    TextEditor::BaseTextEditorWidget *m_editorWidget;
+
+    QTimer m_timer;
+
+    CPlusPlus::Document::Ptr m_document;
+    CPlusPlus::Snapshot m_snapshot;
+
+    QScopedPointer<QFutureWatcher<UseSelectionsResult>> m_findUsesWatcher;
+    int m_findUsesRevision;
+    int m_findUsesCursorPosition;
+};
+
+} // namespace Internal
+} // namespace CppEditor
+
+#endif // CPPUSESELECTIONSUPDATER_H
diff --git a/src/plugins/cpptools/baseeditordocumentparser.cpp b/src/plugins/cpptools/baseeditordocumentparser.cpp
index 058fae5b9935dcbdb2d1b80fdf1f4bea35b9afec..bcf740741589d8af04b35975813b15b8fa1fae42 100644
--- a/src/plugins/cpptools/baseeditordocumentparser.cpp
+++ b/src/plugins/cpptools/baseeditordocumentparser.cpp
@@ -29,6 +29,8 @@
 
 #include "baseeditordocumentparser.h"
 
+#include "editordocumenthandle.h"
+
 namespace CppTools {
 
 /*!
@@ -101,6 +103,16 @@ void BaseEditorDocumentParser::setEditorDefines(const QByteArray &editorDefines)
     }
 }
 
+BaseEditorDocumentParser *BaseEditorDocumentParser::get(const QString &filePath)
+{
+    CppModelManagerInterface *cmmi = CppModelManagerInterface::instance();
+    if (EditorDocumentHandle *editorDocument = cmmi->editorDocument(filePath)) {
+        if (BaseEditorDocumentProcessor *processor = editorDocument->processor())
+            return processor->parser();
+    }
+    return 0;
+}
+
 void BaseEditorDocumentParser::updateProjectPart()
 {
     if (m_manuallySetProjectPart) {
diff --git a/src/plugins/cpptools/baseeditordocumentparser.h b/src/plugins/cpptools/baseeditordocumentparser.h
index e62bbae4c6bac23c18ef31cf304a1707db943e4e..d33b88a8ab5c4d66db9f7a878827165409ba4f16 100644
--- a/src/plugins/cpptools/baseeditordocumentparser.h
+++ b/src/plugins/cpptools/baseeditordocumentparser.h
@@ -33,10 +33,13 @@
 #include "cppmodelmanagerinterface.h"
 #include "cpptools_global.h"
 
+#include <QObject>
+
 namespace CppTools {
 
-class CPPTOOLS_EXPORT BaseEditorDocumentParser
+class CPPTOOLS_EXPORT BaseEditorDocumentParser : public QObject
 {
+    Q_OBJECT
     Q_DISABLE_COPY(BaseEditorDocumentParser)
     BaseEditorDocumentParser();
 
@@ -57,6 +60,9 @@ public:
     QByteArray editorDefines() const;
     void setEditorDefines(const QByteArray &editorDefines);
 
+public:
+    static BaseEditorDocumentParser *get(const QString &filePath);
+
 protected:
     void updateProjectPart();
 
diff --git a/src/plugins/cpptools/baseeditordocumentprocessor.cpp b/src/plugins/cpptools/baseeditordocumentprocessor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e8992da58e4c574dbad1004fe43480d59e7dc90c
--- /dev/null
+++ b/src/plugins/cpptools/baseeditordocumentprocessor.cpp
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "baseeditordocumentprocessor.h"
+#include "cppworkingcopy.h"
+
+#include "editordocumenthandle.h"
+
+#include <utils/qtcassert.h>
+
+#include <QTextBlock>
+
+namespace CppTools {
+
+/*!
+    \class CppTools::BaseEditorDocumentProcessor
+
+    \brief The BaseEditorDocumentProcessor class controls and executes all
+           document relevant actions (reparsing, semantic highlighting, additional
+           semantic calculations) after a text document has changed.
+*/
+
+BaseEditorDocumentProcessor::BaseEditorDocumentProcessor(
+        TextEditor::BaseTextDocument *document)
+    : m_baseTextDocument(document)
+{
+    QTC_CHECK(document);
+}
+
+BaseEditorDocumentProcessor::~BaseEditorDocumentProcessor()
+{
+}
+
+TextEditor::BaseTextDocument *BaseEditorDocumentProcessor::baseTextDocument() const
+{
+    return m_baseTextDocument;
+}
+
+BaseEditorDocumentProcessor *BaseEditorDocumentProcessor::get(const QString &filePath)
+{
+    CppModelManagerInterface *cmmi = CppModelManagerInterface::instance();
+    if (EditorDocumentHandle *editorDocument = cmmi->editorDocument(filePath))
+        return editorDocument->processor();
+    return 0;
+}
+
+QList<QTextEdit::ExtraSelection> BaseEditorDocumentProcessor::toTextEditorSelections(
+        const QList<CPlusPlus::Document::DiagnosticMessage> &diagnostics,
+        QTextDocument *textDocument)
+{
+    // Format for errors
+    QTextCharFormat errorFormat;
+    errorFormat.setUnderlineStyle(QTextCharFormat::WaveUnderline);
+    errorFormat.setUnderlineColor(Qt::red);
+
+    // Format for warnings
+    QTextCharFormat warningFormat;
+    warningFormat.setUnderlineStyle(QTextCharFormat::WaveUnderline);
+    warningFormat.setUnderlineColor(Qt::darkYellow);
+
+    QList<QTextEdit::ExtraSelection> result;
+    foreach (const CPlusPlus::Document::DiagnosticMessage &m, diagnostics) {
+        QTextEdit::ExtraSelection sel;
+        if (m.isWarning())
+            sel.format = warningFormat;
+        else
+            sel.format = errorFormat;
+
+        QTextCursor c(textDocument->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());
+        result.append(sel);
+    }
+
+    return result;
+}
+
+void BaseEditorDocumentProcessor::runParser(QFutureInterface<void> &future,
+                                            BaseEditorDocumentParser *parser,
+                                            WorkingCopy workingCopy)
+{
+    future.setProgressRange(0, 1);
+    if (future.isCanceled()) {
+        future.setProgressValue(1);
+        return;
+    }
+
+    parser->update(workingCopy);
+    CppModelManagerInterface::instance()
+        ->finishedRefreshingSourceFiles(QStringList(parser->filePath()));
+
+    future.setProgressValue(1);
+}
+
+} // namespace CppTools
diff --git a/src/plugins/cpptools/baseeditordocumentprocessor.h b/src/plugins/cpptools/baseeditordocumentprocessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..a6ac2e8a316d481f26c0ed464169abeaae6e6fa9
--- /dev/null
+++ b/src/plugins/cpptools/baseeditordocumentprocessor.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef BASEEDITORDOCUMENTPROCESSOR_H
+#define BASEEDITORDOCUMENTPROCESSOR_H
+
+#include "baseeditordocumentparser.h"
+#include "cppsemanticinfo.h"
+#include "cpptools_global.h"
+
+#include <texteditor/basetexteditor.h>
+
+#include <cplusplus/CppDocument.h>
+
+#include <QTextEdit>
+
+namespace CppTools {
+
+class CPPTOOLS_EXPORT BaseEditorDocumentProcessor : public QObject
+{
+    Q_OBJECT
+    Q_DISABLE_COPY(BaseEditorDocumentProcessor)
+    BaseEditorDocumentProcessor();
+
+public:
+    BaseEditorDocumentProcessor(TextEditor::BaseTextDocument *document);
+    virtual ~BaseEditorDocumentProcessor();
+
+    TextEditor::BaseTextDocument *baseTextDocument() const;
+
+    // Function interface to implement
+    virtual void run() = 0;
+    virtual void semanticRehighlight(bool force) = 0;
+    virtual CppTools::SemanticInfo recalculateSemanticInfo() = 0;
+    virtual BaseEditorDocumentParser *parser() = 0;
+    virtual bool isParserRunning() const = 0;
+
+public:
+    static BaseEditorDocumentProcessor *get(const QString &filePath);
+
+signals:
+    // Signal interface to implement
+    void codeWarningsUpdated(unsigned revision,
+                             const QList<QTextEdit::ExtraSelection> selections);
+
+    void ifdefedOutBlocksUpdated(unsigned revision,
+                                 const QList<TextEditor::BlockRange> ifdefedOutBlocks);
+
+    void cppDocumentUpdated(const CPlusPlus::Document::Ptr document);    // TODO: Remove me
+    void semanticInfoUpdated(const CppTools::SemanticInfo semanticInfo); // TODO: Remove me
+
+protected:
+    static QList<QTextEdit::ExtraSelection> toTextEditorSelections(
+            const QList<CPlusPlus::Document::DiagnosticMessage> &diagnostics,
+            QTextDocument *textDocument);
+
+    static void runParser(QFutureInterface<void> &future,
+                          CppTools::BaseEditorDocumentParser *parser,
+                          CppTools::WorkingCopy workingCopy);
+
+    // Convenience
+    QString filePath() const { return m_baseTextDocument->filePath(); }
+    unsigned revision() const { return static_cast<unsigned>(textDocument()->revision()); }
+    QTextDocument *textDocument() const { return m_baseTextDocument->document(); }
+
+private:
+    TextEditor::BaseTextDocument *m_baseTextDocument;
+};
+
+} // namespace CppTools
+
+#endif // BASEEDITORDOCUMENTPROCESSOR_H
+
diff --git a/src/plugins/cpptools/builtineditordocumentparser.cpp b/src/plugins/cpptools/builtineditordocumentparser.cpp
index a52659d4c64238ea6ad4003ef3492e2571604d8b..526664dc1e5082815a2cd847f68fe1932d4abd54 100644
--- a/src/plugins/cpptools/builtineditordocumentparser.cpp
+++ b/src/plugins/cpptools/builtineditordocumentparser.cpp
@@ -29,6 +29,7 @@
 
 #include "builtineditordocumentparser.h"
 #include "cppsourceprocessor.h"
+#include "editordocumenthandle.h"
 
 #include <utils/qtcassert.h>
 
@@ -221,8 +222,15 @@ void BuiltinEditorDocumentParser::setReleaseSourceAndAST(bool onoff)
     m_releaseSourceAndAST = onoff;
 }
 
+BuiltinEditorDocumentParser *BuiltinEditorDocumentParser::get(const QString &filePath)
+{
+    if (BaseEditorDocumentParser *b = BaseEditorDocumentParser::get(filePath))
+        return qobject_cast<BuiltinEditorDocumentParser *>(b);
+    return 0;
+}
+
 void BuiltinEditorDocumentParser::addFileAndDependencies(QSet<QString> *toRemove,
-                                                            const QString &fileName) const
+                                                         const QString &fileName) const
 {
     toRemove->insert(fileName);
     if (fileName != filePath()) {
@@ -230,4 +238,3 @@ void BuiltinEditorDocumentParser::addFileAndDependencies(QSet<QString> *toRemove
         toRemove->unite(QSet<QString>::fromList(deps));
     }
 }
-
diff --git a/src/plugins/cpptools/builtineditordocumentparser.h b/src/plugins/cpptools/builtineditordocumentparser.h
index b52e6596db2fba0c88be094fd8f214981fd1ed2a..c7993c6a6b05ca86a44f123dfeebad3ee4a5bda8 100644
--- a/src/plugins/cpptools/builtineditordocumentparser.h
+++ b/src/plugins/cpptools/builtineditordocumentparser.h
@@ -45,8 +45,7 @@ namespace CppTools {
 
 class CPPTOOLS_EXPORT BuiltinEditorDocumentParser : public BaseEditorDocumentParser
 {
-public:
-    typedef QSharedPointer<BuiltinEditorDocumentParser> Ptr;
+    Q_OBJECT
 
 public:
     BuiltinEditorDocumentParser(const QString &filePath);
@@ -60,6 +59,9 @@ public:
 
     void setReleaseSourceAndAST(bool onoff);
 
+public:
+    static BuiltinEditorDocumentParser *get(const QString &filePath);
+
 private:
     void addFileAndDependencies(QSet<QString> *toRemove, const QString &fileName) const;
 
diff --git a/src/plugins/cpptools/builtineditordocumentprocessor.cpp b/src/plugins/cpptools/builtineditordocumentprocessor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..cd50c8660941595297c4ec0e7d9a6b2941ab08ec
--- /dev/null
+++ b/src/plugins/cpptools/builtineditordocumentprocessor.cpp
@@ -0,0 +1,253 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "builtineditordocumentprocessor.h"
+
+#include "cppchecksymbols.h"
+#include "cppcodemodelsettings.h"
+#include "cppmodelmanager.h"
+#include "cpptoolsplugin.h"
+#include "cpptoolsreuse.h"
+#include "cppworkingcopy.h"
+
+#include <texteditor/basetexteditor.h>
+#include <texteditor/convenience.h>
+
+#include <cplusplus/CppDocument.h>
+#include <cplusplus/SimpleLexer.h>
+
+#include <utils/QtConcurrentTools>
+#include <utils/qtcassert.h>
+
+enum { debug = 0 };
+
+namespace {
+
+CppTools::Internal::CppModelManager *cmm()
+{
+    return CppTools::Internal::CppModelManager::instance();
+}
+
+QFuture<TextEditor::HighlightingResult> runHighlighter(const CPlusPlus::Document::Ptr &doc,
+                                                       const CPlusPlus::Snapshot &snapshot,
+                                                       QTextDocument *textDocument)
+{
+    QFuture<TextEditor::HighlightingResult> failed;
+    QTC_ASSERT(doc, return failed);
+    QTC_ASSERT(doc->translationUnit(), return failed);
+    QTC_ASSERT(doc->translationUnit()->ast(), return failed);
+    QTC_ASSERT(textDocument, return failed);
+
+    using namespace CPlusPlus;
+    using namespace CppTools;
+    typedef TextEditor::HighlightingResult Result;
+    QList<Result> macroUses;
+
+    using TextEditor::Convenience::convertPosition;
+
+    // Get macro definitions
+    foreach (const CPlusPlus::Macro& macro, doc->definedMacros()) {
+        int line, column;
+        convertPosition(textDocument, macro.utf16CharOffset(), &line, &column);
+
+        ++column; //Highlighting starts at (column-1) --> compensate here
+        Result use(line, column, macro.nameToQString().size(), SemanticHighlighter::MacroUse);
+        macroUses.append(use);
+    }
+
+    // Get macro uses
+    foreach (const Document::MacroUse &macro, doc->macroUses()) {
+        const QString name = macro.macro().nameToQString();
+
+        //Filter out QtKeywords
+        if (isQtKeyword(QStringRef(&name)))
+            continue;
+
+        // Filter out C++ keywords
+        // FIXME: Check default values or get from document.
+        LanguageFeatures features;
+        features.cxx11Enabled = true;
+        features.c99Enabled = true;
+
+        SimpleLexer tokenize;
+        tokenize.setLanguageFeatures(features);
+
+        const QList<Token> tokens = tokenize(name);
+        if (tokens.length() && (tokens.at(0).isKeyword() || tokens.at(0).isObjCAtKeyword()))
+            continue;
+
+        int line, column;
+        convertPosition(textDocument, macro.utf16charsBegin(), &line, &column);
+        ++column; //Highlighting starts at (column-1) --> compensate here
+        Result use(line, column, name.size(), SemanticHighlighter::MacroUse);
+        macroUses.append(use);
+    }
+
+    LookupContext context(doc, snapshot);
+    return CheckSymbols::go(doc, context, macroUses);
+}
+
+QList<TextEditor::BlockRange> toTextEditorBlocks(
+        const QList<CPlusPlus::Document::Block> &skippedBlocks)
+{
+    QList<TextEditor::BlockRange> result;
+    result.reserve(skippedBlocks.size());
+    foreach (const CPlusPlus::Document::Block &block, skippedBlocks)
+        result.append(TextEditor::BlockRange(block.utf16charsBegin(), block.utf16charsEnd()));
+    return result;
+}
+
+} // anonymous namespace
+
+namespace CppTools {
+
+BuiltinEditorDocumentProcessor::BuiltinEditorDocumentProcessor(
+        TextEditor::BaseTextDocument *document,
+        bool enableSemanticHighlighter)
+    : BaseEditorDocumentProcessor(document)
+    , m_parser(new BuiltinEditorDocumentParser(document->filePath()))
+    , m_semanticInfoUpdater(m_parser.data())
+    , m_semanticHighlighter(enableSemanticHighlighter
+                            ? new CppTools::SemanticHighlighter(document)
+                            : 0)
+{
+    QSharedPointer<Internal::CppCodeModelSettings> cms
+            = Internal::CppToolsPlugin::instance()->codeModelSettings();
+    m_parser->setUsePrecompiledHeaders(
+                cms->pchUsage() != Internal::CppCodeModelSettings::PchUse_None);
+
+    if (m_semanticHighlighter) {
+        m_semanticHighlighter->setHighlightingRunner(
+            [this]() -> QFuture<TextEditor::HighlightingResult> {
+                const SemanticInfo semanticInfo = m_semanticInfoUpdater.semanticInfo();
+                return runHighlighter(semanticInfo.doc, semanticInfo.snapshot,
+                                      baseTextDocument()->document());
+            });
+    }
+
+    connect(cmm(), &Internal::CppModelManager::documentUpdated,
+            this, &BuiltinEditorDocumentProcessor::onDocumentUpdated);
+    connect(&m_semanticInfoUpdater, &SemanticInfoUpdater::updated,
+            this, &BuiltinEditorDocumentProcessor::onSemanticInfoUpdated);
+}
+
+BuiltinEditorDocumentProcessor::~BuiltinEditorDocumentProcessor()
+{
+    m_parserFuture.cancel();
+    m_parserFuture.waitForFinished();
+}
+
+void BuiltinEditorDocumentProcessor::run()
+{
+    m_parserFuture = QtConcurrent::run(&runParser, parser(), cmm()->workingCopy());
+}
+
+BaseEditorDocumentParser *BuiltinEditorDocumentProcessor::parser()
+{
+    return m_parser.data();
+}
+
+void BuiltinEditorDocumentProcessor::semanticRehighlight(bool force)
+{
+    const auto source = createSemanticInfoSource(force);
+    m_semanticInfoUpdater.updateDetached(source);
+}
+
+SemanticInfo BuiltinEditorDocumentProcessor::recalculateSemanticInfo()
+{
+    const auto source = createSemanticInfoSource(false);
+    return m_semanticInfoUpdater.update(source);
+}
+
+bool BuiltinEditorDocumentProcessor::isParserRunning() const
+{
+    return m_parserFuture.isRunning();
+}
+
+BuiltinEditorDocumentProcessor *BuiltinEditorDocumentProcessor::get(const QString &filePath)
+{
+    if (BaseEditorDocumentProcessor *b = BaseEditorDocumentProcessor::get(filePath))
+        return qobject_cast<BuiltinEditorDocumentProcessor *>(b);
+    return 0;
+}
+
+void BuiltinEditorDocumentProcessor::onDocumentUpdated(CPlusPlus::Document::Ptr document)
+{
+    if (document.isNull())
+        return;
+
+    if (document->fileName() != filePath())
+        return; // some other document got updated
+
+    if (document->editorRevision() != revision())
+        return; // outdated content, wait for a new document to be parsed
+
+    if (debug) {
+        qDebug() << "BuiltinEditorDocumentProcessor: document parsed" << document->fileName()
+                 << document->editorRevision();
+    }
+
+    // Emit ifdefed out blocks
+    const auto ifdefoutBlocks = toTextEditorBlocks(document->skippedBlocks());
+    emit ifdefedOutBlocksUpdated(revision(), ifdefoutBlocks);
+
+    // Emit code warnings
+    auto codeWarnings = toTextEditorSelections(document->diagnosticMessages(), textDocument());
+    emit codeWarningsUpdated(revision(), codeWarnings);
+
+    emit cppDocumentUpdated(document);
+
+    const auto source = createSemanticInfoSource(false);
+    m_semanticInfoUpdater.updateDetached(source);
+}
+
+void BuiltinEditorDocumentProcessor::onSemanticInfoUpdated(const SemanticInfo semanticInfo)
+{
+    if (debug) {
+        qDebug() << "BuiltinEditorDocumentProcessor: semantic info updated"
+                 << semanticInfo.doc->fileName() << semanticInfo.revision << semanticInfo.complete;
+    }
+
+    emit semanticInfoUpdated(semanticInfo);
+
+    if (m_semanticHighlighter)
+        m_semanticHighlighter->run();
+}
+
+SemanticInfo::Source BuiltinEditorDocumentProcessor::createSemanticInfoSource(bool force) const
+{
+    const WorkingCopy workingCopy = cmm()->workingCopy();
+    const QString path = filePath();
+    return SemanticInfo::Source(path,
+                                workingCopy.source(path),
+                                workingCopy.revision(path),
+                                force);
+}
+
+} // namespace CppTools
diff --git a/src/plugins/cpptools/builtineditordocumentprocessor.h b/src/plugins/cpptools/builtineditordocumentprocessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..402d5720ce0a197358dbd8291ead4d74d2e68d08
--- /dev/null
+++ b/src/plugins/cpptools/builtineditordocumentprocessor.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef BUILTINEDITORDOCUMENTPROCESSOR_H
+#define BUILTINEDITORDOCUMENTPROCESSOR_H
+
+#include "baseeditordocumentprocessor.h"
+#include "builtineditordocumentparser.h"
+#include "cppsemanticinfoupdater.h"
+#include "cpptools_global.h"
+#include "semantichighlighter.h"
+
+#include <utils/qtcoverride.h>
+
+namespace CppTools {
+
+class CPPTOOLS_EXPORT BuiltinEditorDocumentProcessor : public BaseEditorDocumentProcessor
+{
+    Q_OBJECT
+    BuiltinEditorDocumentProcessor();
+
+public:
+    BuiltinEditorDocumentProcessor(TextEditor::BaseTextDocument *document,
+                                   bool enableSemanticHighlighter = true);
+    ~BuiltinEditorDocumentProcessor();
+
+    // BaseEditorDocumentProcessor interface
+    void run() QTC_OVERRIDE;
+    void semanticRehighlight(bool force) QTC_OVERRIDE;
+    CppTools::SemanticInfo recalculateSemanticInfo() QTC_OVERRIDE;
+    BaseEditorDocumentParser *parser() QTC_OVERRIDE;
+    bool isParserRunning() const QTC_OVERRIDE;
+
+public:
+    static BuiltinEditorDocumentProcessor *get(const QString &filePath);
+
+private slots:
+    void onDocumentUpdated(CPlusPlus::Document::Ptr document);
+    void onSemanticInfoUpdated(const CppTools::SemanticInfo semanticInfo);
+
+private:
+    SemanticInfo::Source createSemanticInfoSource(bool force) const;
+
+private:
+    QScopedPointer<BuiltinEditorDocumentParser> m_parser;
+    QFuture<void> m_parserFuture;
+
+    SemanticInfoUpdater m_semanticInfoUpdater;
+    QScopedPointer<SemanticHighlighter> m_semanticHighlighter;
+};
+
+} // namespace CppTools
+
+#endif // BUILTINEDITORDOCUMENTPROCESSOR_H
diff --git a/src/plugins/cpptools/cppchecksymbols.cpp b/src/plugins/cpptools/cppchecksymbols.cpp
index 4f528d47d6f92dbecd534b4e0ed9d1f377b783de..eb6974c470be79494ecd3242831cbfc6a8f0f435 100644
--- a/src/plugins/cpptools/cppchecksymbols.cpp
+++ b/src/plugins/cpptools/cppchecksymbols.cpp
@@ -298,6 +298,8 @@ static bool acceptName(NameAST *ast, unsigned *referenceToken)
 CheckSymbols::Future CheckSymbols::go(Document::Ptr doc, const LookupContext &context, const QList<CheckSymbols::Result> &macroUses)
 {
     QTC_ASSERT(doc, return Future());
+    QTC_ASSERT(doc->translationUnit(), return Future());
+    QTC_ASSERT(doc->translationUnit()->ast(), return Future());
 
     return (new CheckSymbols(doc, context, macroUses))->start();
 }
@@ -477,7 +479,7 @@ bool CheckSymbols::visit(NamespaceAST *ast)
         if (!tok.generated()) {
             unsigned line, column;
             getTokenStartPosition(ast->identifier_token, &line, &column);
-            Result use(line, column, tok.utf16chars(), CppHighlightingSupport::TypeUse);
+            Result use(line, column, tok.utf16chars(), SemanticHighlighter::TypeUse);
             addUse(use);
         }
     }
@@ -492,13 +494,13 @@ bool CheckSymbols::visit(UsingDirectiveAST *)
 
 bool CheckSymbols::visit(EnumeratorAST *ast)
 {
-    addUse(ast->identifier_token, CppHighlightingSupport::EnumerationUse);
+    addUse(ast->identifier_token, SemanticHighlighter::EnumerationUse);
     return true;
 }
 
 bool CheckSymbols::visit(DotDesignatorAST *ast)
 {
-    addUse(ast->identifier_token, CppHighlightingSupport::FieldUse);
+    addUse(ast->identifier_token, SemanticHighlighter::FieldUse);
     return true;
 }
 
@@ -513,7 +515,7 @@ bool CheckSymbols::visit(SimpleDeclarationAST *ast)
                     if (funTy->isVirtual()
                             || (nameAST->asDestructorName()
                                 && hasVirtualDestructor(_context.lookupType(funTy->enclosingScope())))) {
-                        addUse(nameAST, CppHighlightingSupport::VirtualMethodUse);
+                        addUse(nameAST, SemanticHighlighter::VirtualMethodUse);
                         declrIdNameAST = nameAST;
                     } else if (maybeAddFunction(_context.lookup(decl->name(),
                                                                 decl->enclosingScope()),
@@ -521,7 +523,7 @@ bool CheckSymbols::visit(SimpleDeclarationAST *ast)
                         declrIdNameAST = nameAST;
 
                         // Add a diagnostic message if non-virtual function has override/final marker
-                        if ((_usages.back().kind != CppHighlightingSupport::VirtualMethodUse)) {
+                        if ((_usages.back().kind != SemanticHighlighter::VirtualMethodUse)) {
                             if (funTy->isOverride())
                                 warning(declrIdNameAST, QCoreApplication::translate(
                                             "CPlusplus::CheckSymbols", "Only virtual functions can be marked 'override'"));
@@ -559,7 +561,7 @@ bool CheckSymbols::visit(ElaboratedTypeSpecifierAST *ast)
 {
     accept(ast->attribute_list);
     accept(ast->name);
-    addUse(ast->name, CppHighlightingSupport::TypeUse);
+    addUse(ast->name, SemanticHighlighter::TypeUse);
     return false;
 }
 
@@ -796,14 +798,14 @@ void CheckSymbols::checkName(NameAST *ast, Scope *scope)
 
             if (klass) {
                 if (hasVirtualDestructor(_context.lookupType(klass))) {
-                    addUse(ast, CppHighlightingSupport::VirtualMethodUse);
+                    addUse(ast, SemanticHighlighter::VirtualMethodUse);
                 } else {
                     bool added = false;
                     if (highlightCtorDtorAsType && maybeType(ast->name))
                         added = maybeAddTypeOrStatic(_context.lookup(ast->name, klass), ast);
 
                     if (!added)
-                        addUse(ast, CppHighlightingSupport::FunctionUse);
+                        addUse(ast, SemanticHighlighter::FunctionUse);
                 }
             }
         } else if (maybeType(ast->name) || maybeStatic(ast->name)) {
@@ -853,14 +855,14 @@ bool CheckSymbols::visit(QualifiedNameAST *ast)
         if (binding && ast->unqualified_name) {
             if (ast->unqualified_name->asDestructorName() != 0) {
                 if (hasVirtualDestructor(binding)) {
-                    addUse(ast->unqualified_name, CppHighlightingSupport::VirtualMethodUse);
+                    addUse(ast->unqualified_name, SemanticHighlighter::VirtualMethodUse);
                 } else {
                     bool added = false;
                     if (highlightCtorDtorAsType && maybeType(ast->name))
                         added = maybeAddTypeOrStatic(binding->find(ast->unqualified_name->name),
                                                      ast->unqualified_name);
                     if (!added)
-                        addUse(ast->unqualified_name, CppHighlightingSupport::FunctionUse);
+                        addUse(ast->unqualified_name, SemanticHighlighter::FunctionUse);
                 }
             } else {
                 QList<LookupItem> items = binding->find(ast->unqualified_name->name);
@@ -904,7 +906,7 @@ ClassOrNamespace *CheckSymbols::checkNestedName(QualifiedNameAST *ast)
                     if (NameAST *class_or_namespace_name = nested_name_specifier->class_or_namespace_name) {
                         if (TemplateIdAST *template_id = class_or_namespace_name->asTemplateId()) {
                             if (template_id->template_token) {
-                                addUse(template_id, CppHighlightingSupport::TypeUse);
+                                addUse(template_id, SemanticHighlighter::TypeUse);
                                 binding = 0; // there's no way we can find a binding.
                             }
 
@@ -928,7 +930,7 @@ ClassOrNamespace *CheckSymbols::checkNestedName(QualifiedNameAST *ast)
 
 bool CheckSymbols::visit(TypenameTypeParameterAST *ast)
 {
-    addUse(ast->name, CppHighlightingSupport::TypeUse);
+    addUse(ast->name, SemanticHighlighter::TypeUse);
     accept(ast->type_id);
     return false;
 }
@@ -936,7 +938,7 @@ bool CheckSymbols::visit(TypenameTypeParameterAST *ast)
 bool CheckSymbols::visit(TemplateTypeParameterAST *ast)
 {
     accept(ast->template_parameter_list);
-    addUse(ast->name, CppHighlightingSupport::TypeUse);
+    addUse(ast->name, SemanticHighlighter::TypeUse);
     accept(ast->type_id);
     return false;
 }
@@ -988,7 +990,7 @@ bool CheckSymbols::visit(MemInitializerAST *ast)
 bool CheckSymbols::visit(GotoStatementAST *ast)
 {
     if (ast->identifier_token)
-        addUse(ast->identifier_token, CppHighlightingSupport::LabelUse);
+        addUse(ast->identifier_token, SemanticHighlighter::LabelUse);
 
     return false;
 }
@@ -996,7 +998,7 @@ bool CheckSymbols::visit(GotoStatementAST *ast)
 bool CheckSymbols::visit(LabeledStatementAST *ast)
 {
     if (ast->label_token && !tokenAt(ast->label_token).isKeyword())
-        addUse(ast->label_token, CppHighlightingSupport::LabelUse);
+        addUse(ast->label_token, SemanticHighlighter::LabelUse);
 
     accept(ast->statement);
     return false;
@@ -1017,7 +1019,7 @@ bool CheckSymbols::visit(SimpleSpecifierAST *ast)
             if (id.equalTo(_doc->control()->cpp11Override())
                     || id.equalTo(_doc->control()->cpp11Final()))
             {
-                addUse(ast->specifier_token, CppHighlightingSupport::PseudoKeywordUse);
+                addUse(ast->specifier_token, SemanticHighlighter::PseudoKeywordUse);
             }
         }
     }
@@ -1028,7 +1030,7 @@ bool CheckSymbols::visit(SimpleSpecifierAST *ast)
 bool CheckSymbols::visit(ClassSpecifierAST *ast)
 {
     if (ast->final_token)
-        addUse(ast->final_token, CppHighlightingSupport::PseudoKeywordUse);
+        addUse(ast->final_token, SemanticHighlighter::PseudoKeywordUse);
 
     return true;
 }
@@ -1053,7 +1055,7 @@ bool CheckSymbols::visit(FunctionDefinitionAST *ast)
             if (fun->isVirtual()
                     || (declId->asDestructorName()
                         && hasVirtualDestructor(_context.lookupType(fun->enclosingScope())))) {
-                addUse(declId, CppHighlightingSupport::VirtualMethodUse);
+                addUse(declId, SemanticHighlighter::VirtualMethodUse);
             } else if (!maybeAddFunction(_context.lookup(fun->name(),
                                                          fun->enclosingScope()),
                                          declId, fun->argumentCount())) {
@@ -1161,7 +1163,7 @@ void CheckSymbols::addType(ClassOrNamespace *b, NameAST *ast)
     unsigned line, column;
     getTokenStartPosition(startToken, &line, &column);
     const unsigned length = tok.utf16chars();
-    const Result use(line, column, length, CppHighlightingSupport::TypeUse);
+    const Result use(line, column, length, SemanticHighlighter::TypeUse);
     addUse(use);
 }
 
@@ -1203,12 +1205,12 @@ bool CheckSymbols::maybeAddTypeOrStatic(const QList<LookupItem> &candidates, Nam
             getTokenStartPosition(startToken, &line, &column);
             const unsigned length = tok.utf16chars();
 
-            Kind kind = CppHighlightingSupport::TypeUse;
+            Kind kind = SemanticHighlighter::TypeUse;
             if (c->enclosingEnum() != 0)
-                kind = CppHighlightingSupport::EnumerationUse;
+                kind = SemanticHighlighter::EnumerationUse;
             else if (c->isStatic())
                 // treat static variable as a field(highlighting)
-                kind = CppHighlightingSupport::FieldUse;
+                kind = SemanticHighlighter::FieldUse;
 
             const Result use(line, column, length, kind);
             addUse(use);
@@ -1245,7 +1247,7 @@ bool CheckSymbols::maybeAddField(const QList<LookupItem> &candidates, NameAST *a
         getTokenStartPosition(startToken, &line, &column);
         const unsigned length = tok.utf16chars();
 
-        const Result use(line, column, length, CppHighlightingSupport::FieldUse);
+        const Result use(line, column, length, SemanticHighlighter::FieldUse);
         addUse(use);
 
         return true;
@@ -1270,7 +1272,7 @@ bool CheckSymbols::maybeAddFunction(const QList<LookupItem> &candidates, NameAST
         return false;
 
     enum { Match_None, Match_TooManyArgs, Match_TooFewArgs, Match_Ok } matchType = Match_None;
-    Kind kind = CppHighlightingSupport::FunctionUse;
+    Kind kind = SemanticHighlighter::FunctionUse;
     foreach (const LookupItem &r, candidates) {
         Symbol *c = r.declaration();
 
@@ -1297,21 +1299,21 @@ bool CheckSymbols::maybeAddFunction(const QList<LookupItem> &candidates, NameAST
 
         if (argumentCount < funTy->minimumArgumentCount()) {
             if (matchType != Match_Ok) {
-                kind = funTy->isVirtual() ? CppHighlightingSupport::VirtualMethodUse : CppHighlightingSupport::FunctionUse;
+                kind = funTy->isVirtual() ? SemanticHighlighter::VirtualMethodUse : SemanticHighlighter::FunctionUse;
                 matchType = Match_TooFewArgs;
             }
         } else if (argumentCount > funTy->argumentCount() && !funTy->isVariadic()) {
             if (matchType != Match_Ok) {
                 matchType = Match_TooManyArgs;
-                kind = funTy->isVirtual() ? CppHighlightingSupport::VirtualMethodUse : CppHighlightingSupport::FunctionUse;
+                kind = funTy->isVirtual() ? SemanticHighlighter::VirtualMethodUse : SemanticHighlighter::FunctionUse;
             }
         } else if (!funTy->isVirtual()) {
             matchType = Match_Ok;
-            kind = CppHighlightingSupport::FunctionUse;
+            kind = SemanticHighlighter::FunctionUse;
             //continue, to check if there is a matching candidate which is virtual
         } else {
             matchType = Match_Ok;
-            kind = CppHighlightingSupport::VirtualMethodUse;
+            kind = SemanticHighlighter::VirtualMethodUse;
             break;
         }
     }
@@ -1321,7 +1323,7 @@ bool CheckSymbols::maybeAddFunction(const QList<LookupItem> &candidates, NameAST
         if (highlightCtorDtorAsType
                 && (isConstructor || isDestructor)
                 && maybeType(ast->name)
-                && kind == CppHighlightingSupport::FunctionUse) {
+                && kind == SemanticHighlighter::FunctionUse) {
             return false;
         }
 
diff --git a/src/plugins/cpptools/cppchecksymbols.h b/src/plugins/cpptools/cppchecksymbols.h
index 5ccd2fe4cf7c8d87fc2c52788a314787154766bf..6c61275b6e52cdefdb9fd148c1b6534a1d8376b6 100644
--- a/src/plugins/cpptools/cppchecksymbols.h
+++ b/src/plugins/cpptools/cppchecksymbols.h
@@ -31,8 +31,8 @@
 #define CPLUSPLUSCHECKSYMBOLS_H
 
 #include "cpptools_global.h"
-#include "cpphighlightingsupport.h"
 #include "cppsemanticinfo.h"
+#include "semantichighlighter.h"
 
 #include <cplusplus/TypeOfExpression.h>
 
@@ -51,7 +51,7 @@ public:
     virtual ~CheckSymbols();
 
     typedef TextEditor::HighlightingResult Result;
-    typedef CppHighlightingSupport::Kind Kind;
+    typedef SemanticHighlighter::Kind Kind;
 
     virtual void run();
 
diff --git a/src/plugins/cpptools/cppcompletion_test.cpp b/src/plugins/cpptools/cppcompletion_test.cpp
index 19d262ae69ee728e8db5196c9020b763a45c94f8..679e141b75ee55efebe3724cb8d5728468b16a8f 100644
--- a/src/plugins/cpptools/cppcompletion_test.cpp
+++ b/src/plugins/cpptools/cppcompletion_test.cpp
@@ -102,8 +102,8 @@ public:
     {
         QStringList completions;
         CppCompletionAssistInterface *ai
-            = new CppCompletionAssistInterface(m_editorWidget->document(), m_position,
-                                               m_editorWidget->textDocument()->filePath(),
+            = new CppCompletionAssistInterface(m_editorWidget->textDocument()->filePath(),
+                                               m_editorWidget->document(), m_position,
                                                ExplicitlyInvoked, m_snapshot,
                                                ProjectPart::HeaderPaths());
         CppCompletionAssistProcessor processor;
diff --git a/src/plugins/cpptools/cppcompletionassist.cpp b/src/plugins/cpptools/cppcompletionassist.cpp
index 90fce585f8cdcdefab6c8f76dd7f2062568add49..a4866da361b0d06222457139289d3a8bfea6b517 100644
--- a/src/plugins/cpptools/cppcompletionassist.cpp
+++ b/src/plugins/cpptools/cppcompletionassist.cpp
@@ -34,8 +34,8 @@
 #include "cppmodelmanager.h"
 #include "cppmodelmanagerinterface.h"
 #include "cpptoolsconstants.h"
-#include "cpptoolseditorsupport.h"
 #include "cpptoolsreuse.h"
+#include "editordocumenthandle.h"
 
 #include <coreplugin/icore.h>
 #include <cppeditor/cppeditorconstants.h>
@@ -421,15 +421,14 @@ IAssistProcessor *InternalCompletionAssistProvider::createProcessor() const
 }
 
 TextEditor::IAssistInterface *InternalCompletionAssistProvider::createAssistInterface(
-        ProjectExplorer::Project *project, BaseTextEditor *editor, QTextDocument *document,
+        ProjectExplorer::Project *project, const QString &filePath, QTextDocument *document,
         bool isObjCEnabled, int position, TextEditor::AssistReason reason) const
 {
     Q_UNUSED(project);
-    QTC_ASSERT(editor, return 0);
     QTC_ASSERT(document, return 0);
 
     CppModelManagerInterface *modelManager = CppModelManagerInterface::instance();
-    return new CppTools::Internal::CppCompletionAssistInterface(editor, document, isObjCEnabled,
+    return new CppTools::Internal::CppCompletionAssistInterface(filePath, document, isObjCEnabled,
                                                                 position, reason,
                                                                 modelManager->workingCopy());
 }
@@ -1957,12 +1956,9 @@ void CppCompletionAssistInterface::getCppSpecifics() const
         return;
     m_gotCppSpecifics = true;
 
-    CppModelManagerInterface *modelManager = CppModelManagerInterface::instance();
-    if (CppEditorSupport *supp = modelManager->cppEditorSupport(m_editor)) {
-        if (BuiltinEditorDocumentParser::Ptr parser = supp->documentParser()) {
-            parser->update(m_workingCopy);
-            m_snapshot = parser->snapshot();
-            m_headerPaths = parser->headerPaths();
-        }
+    if (BuiltinEditorDocumentParser *parser = BuiltinEditorDocumentParser::get(fileName())) {
+        parser->update(m_workingCopy);
+        m_snapshot = parser->snapshot();
+        m_headerPaths = parser->headerPaths();
     }
 }
diff --git a/src/plugins/cpptools/cppcompletionassist.h b/src/plugins/cpptools/cppcompletionassist.h
index a63ca76ad47dacdc93f86baa5ea3f007679e4435..7fa602b4a56cee58f74ec3cc668260098ef023b4 100644
--- a/src/plugins/cpptools/cppcompletionassist.h
+++ b/src/plugins/cpptools/cppcompletionassist.h
@@ -96,7 +96,7 @@ public:
     TextEditor::IAssistProcessor *createProcessor() const QTC_OVERRIDE;
 
     TextEditor::IAssistInterface *createAssistInterface(ProjectExplorer::Project *project,
-            TextEditor::BaseTextEditor *editor,
+            const QString &filePath,
             QTextDocument *document,
             bool isObjCEnabled,
             int position,
@@ -173,28 +173,25 @@ private:
 class CppCompletionAssistInterface : public TextEditor::DefaultAssistInterface
 {
 public:
-    CppCompletionAssistInterface(TextEditor::BaseTextEditor *editor,
+    CppCompletionAssistInterface(const QString &filePath,
                                  QTextDocument *textDocument,
                                  bool isObjCEnabled,
                                  int position,
                                  TextEditor::AssistReason reason,
                                  const WorkingCopy &workingCopy)
-        : TextEditor::DefaultAssistInterface(textDocument, position, editor->document()->filePath(),
-                                             reason)
-        , m_editor(editor)
+        : TextEditor::DefaultAssistInterface(textDocument, position, filePath, reason)
         , m_isObjCEnabled(isObjCEnabled)
         , m_gotCppSpecifics(false)
         , m_workingCopy(workingCopy)
     {}
 
-    CppCompletionAssistInterface(QTextDocument *textDocument,
+    CppCompletionAssistInterface(const QString &filePath,
+                                 QTextDocument *textDocument,
                                  int position,
-                                 const QString &fileName,
                                  TextEditor::AssistReason reason,
                                  const CPlusPlus::Snapshot &snapshot,
                                  const ProjectPart::HeaderPaths &headerPaths)
-        : TextEditor::DefaultAssistInterface(textDocument, position, fileName, reason)
-        , m_editor(0)
+        : TextEditor::DefaultAssistInterface(textDocument, position, filePath, reason)
         , m_isObjCEnabled(false)
         , m_gotCppSpecifics(true)
         , m_snapshot(snapshot)
@@ -210,7 +207,6 @@ public:
 private:
     void getCppSpecifics() const;
 
-    TextEditor::BaseTextEditor *m_editor;
     mutable bool m_isObjCEnabled;
     mutable bool m_gotCppSpecifics;
     WorkingCopy m_workingCopy;
diff --git a/src/plugins/cpptools/cppcompletionassistprovider.h b/src/plugins/cpptools/cppcompletionassistprovider.h
index 8873fd351841bbe050384a8ff1c8fbbdc3888053..f60c5bb102068ed42f926b06cc9156afd6f30c64 100644
--- a/src/plugins/cpptools/cppcompletionassistprovider.h
+++ b/src/plugins/cpptools/cppcompletionassistprovider.h
@@ -61,7 +61,7 @@ public:
     bool isContinuationChar(const QChar &c) const QTC_OVERRIDE;
 
     virtual TextEditor::IAssistInterface *createAssistInterface(
-            ProjectExplorer::Project *project, TextEditor::BaseTextEditor *editor,
+            ProjectExplorer::Project *project, const QString &filePath,
             QTextDocument *document, bool isObjCEnabled, int position,
             TextEditor::AssistReason reason) const = 0;
 
diff --git a/src/plugins/cpptools/cpphighlightingsupportinternal.cpp b/src/plugins/cpptools/cpphighlightingsupportinternal.cpp
deleted file mode 100644
index 852868cc7782dce0e443b6ff5afd3d87d17ca1e7..0000000000000000000000000000000000000000
--- a/src/plugins/cpptools/cpphighlightingsupportinternal.cpp
+++ /dev/null
@@ -1,104 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.  For licensing terms and
-** conditions see http://qt.digia.com/licensing.  For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** 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.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights.  These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-****************************************************************************/
-
-#include "cpphighlightingsupportinternal.h"
-
-#include "cppchecksymbols.h"
-#include "cpptoolsreuse.h"
-
-#include <texteditor/basetextdocument.h>
-#include <texteditor/convenience.h>
-
-#include <cplusplus/SimpleLexer.h>
-
-using namespace CPlusPlus;
-using namespace CppTools;
-using namespace CppTools::Internal;
-
-CppHighlightingSupportInternal::CppHighlightingSupportInternal(
-        TextEditor::BaseTextDocument *baseTextDocument)
-    : CppHighlightingSupport(baseTextDocument)
-{
-}
-
-CppHighlightingSupportInternal::~CppHighlightingSupportInternal()
-{
-}
-
-QFuture<TextEditor::HighlightingResult> CppHighlightingSupportInternal::highlightingFuture(
-        const Document::Ptr &doc,
-        const Snapshot &snapshot) const
-{
-    typedef TextEditor::HighlightingResult Result;
-    QList<Result> macroUses;
-
-    QTextDocument *textDocument = baseTextDocument()->document();
-    using TextEditor::Convenience::convertPosition;
-
-    // Get macro definitions
-    foreach (const CPlusPlus::Macro& macro, doc->definedMacros()) {
-        int line, column;
-        convertPosition(textDocument, macro.utf16CharOffset(), &line, &column);
-
-        ++column; //Highlighting starts at (column-1) --> compensate here
-        Result use(line, column, macro.nameToQString().size(), MacroUse);
-        macroUses.append(use);
-    }
-
-    // Get macro uses
-    foreach (const Document::MacroUse &macro, doc->macroUses()) {
-        const QString name = macro.macro().nameToQString();
-
-        //Filter out QtKeywords
-        if (isQtKeyword(QStringRef(&name)))
-            continue;
-
-        // Filter out C++ keywords
-        // FIXME: Check default values or get from document.
-        LanguageFeatures features;
-        features.cxx11Enabled = true;
-        features.c99Enabled = true;
-
-        SimpleLexer tokenize;
-        tokenize.setLanguageFeatures(features);
-
-        const QList<Token> tokens = tokenize(name);
-        if (tokens.length() && (tokens.at(0).isKeyword() || tokens.at(0).isObjCAtKeyword()))
-            continue;
-
-        int line, column;
-        convertPosition(textDocument, macro.utf16charsBegin(), &line, &column);
-        ++column; //Highlighting starts at (column-1) --> compensate here
-        Result use(line, column, name.size(), MacroUse);
-        macroUses.append(use);
-    }
-
-    LookupContext context(doc, snapshot);
-    return CheckSymbols::go(doc, context, macroUses);
-}
diff --git a/src/plugins/cpptools/cpplocalsymbols.cpp b/src/plugins/cpptools/cpplocalsymbols.cpp
index e491589fc6ec8023f5208878fab60957a33e2e06..f68fc9bdc77d446b6893f7592a3ba9760327dd2a 100644
--- a/src/plugins/cpptools/cpplocalsymbols.cpp
+++ b/src/plugins/cpptools/cpplocalsymbols.cpp
@@ -27,8 +27,8 @@
 **
 ****************************************************************************/
 
-#include "cpphighlightingsupport.h"
 #include "cpplocalsymbols.h"
+#include "semantichighlighter.h"
 
 #include "cppsemanticinfo.h"
 
@@ -86,7 +86,7 @@ protected:
                         getPosition(token.utf16charsBegin(), &line, &column);
                         localUses[member].append(
                                     HighlightingResult(line, column, token.utf16chars(),
-                                                       CppHighlightingSupport::LocalUse));
+                                                       SemanticHighlighter::LocalUse));
                     }
                 }
             }
@@ -110,7 +110,7 @@ protected:
                         getTokenStartPosition(simpleName->identifier_token, &line, &column);
                         localUses[member].append(
                                     HighlightingResult(line, column, token.utf16chars(),
-                                                       CppHighlightingSupport::LocalUse));
+                                                       SemanticHighlighter::LocalUse));
                         return false;
                     }
                 }
diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp
index 83c642b5b9e5ce1705da886e67e16ceb9896bf49..796a052b95e3a929aaca174aa878ac5332dec812 100644
--- a/src/plugins/cpptools/cppmodelmanager.cpp
+++ b/src/plugins/cpptools/cppmodelmanager.cpp
@@ -34,13 +34,12 @@
 #include "cppcodemodelinspectordumper.h"
 #include "cppcodemodelsettings.h"
 #include "cppfindreferences.h"
-#include "cpphighlightingsupport.h"
 #include "cppindexingsupport.h"
 #include "cppmodelmanagersupportinternal.h"
 #include "cppsourceprocessor.h"
 #include "cpptoolsconstants.h"
-#include "cpptoolseditorsupport.h"
 #include "cpptoolsplugin.h"
+#include "editordocumenthandle.h"
 
 #include <coreplugin/icore.h>
 #include <coreplugin/progressmanager/progressmanager.h>
@@ -399,47 +398,42 @@ void CppModelManager::removeExtraEditorSupport(AbstractEditorSupport *editorSupp
     m_extraEditorSupports.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 *textEditor)
+EditorDocumentHandle *CppModelManager::editorDocument(const QString &filePath)
 {
-    Q_ASSERT(textEditor);
+    QTC_ASSERT(!filePath.isEmpty(), return 0);
 
-    QMutexLocker locker(&m_cppEditorSupportsMutex);
-
-    CppEditorSupport *editorSupport = m_cppEditorSupports.value(textEditor, 0);
-    if (!editorSupport && isCppEditor(textEditor)) {
-        editorSupport = new CppEditorSupport(this, textEditor);
-        m_cppEditorSupports.insert(textEditor, editorSupport);
-    }
-    return editorSupport;
+    QMutexLocker locker(&m_cppEditorsMutex);
+    return m_cppEditors.value(filePath, 0);
 }
 
-/// \brief Removes the CppEditorSupport for the closed editor.
-void CppModelManager::deleteCppEditorSupport(TextEditor::BaseTextEditor *textEditor)
+void CppModelManager::registerEditorDocument(EditorDocumentHandle *editorDocument)
 {
-    static short numberOfClosedEditors = 0;
+    QTC_ASSERT(editorDocument, return);
+    const QString filePath = editorDocument->filePath();
+    QTC_ASSERT(!filePath.isEmpty(), return);
 
-    QTC_ASSERT(textEditor, return);
+    QMutexLocker locker(&m_cppEditorsMutex);
+    QTC_ASSERT(m_cppEditors.value(filePath, 0) == 0, return);
+    m_cppEditors.insert(filePath, editorDocument);
+}
 
-    if (!isCppEditor(textEditor))
-        return;
+void CppModelManager::unregisterEditorDocument(const QString &filePath)
+{
+    QTC_ASSERT(!filePath.isEmpty(), return);
 
-    CppEditorSupport *editorSupport;
-    int numberOfOpenEditors = 0;
+    static short closedCppDocuments = 0;
+    int openCppDocuments = 0;
 
-    { // Only lock the operations on m_cppEditorSupport
-        QMutexLocker locker(&m_cppEditorSupportsMutex);
-        editorSupport = m_cppEditorSupports.value(textEditor, 0);
-        m_cppEditorSupports.remove(textEditor);
-        numberOfOpenEditors = m_cppEditorSupports.size();
+    {
+        QMutexLocker locker(&m_cppEditorsMutex);
+        QTC_ASSERT(m_cppEditors.value(filePath, 0), return);
+        QTC_CHECK(m_cppEditors.remove(filePath) == 1);
+        openCppDocuments = m_cppEditors.size();
     }
 
-    delete editorSupport;
-
-    ++numberOfClosedEditors;
-    if (numberOfOpenEditors == 0 || numberOfClosedEditors == 5) {
-        numberOfClosedEditors = 0;
+    ++closedCppDocuments;
+    if (openCppDocuments == 0 || closedCppDocuments == 5) {
+        closedCppDocuments = 0;
         delayedGC();
     }
 }
@@ -483,10 +477,8 @@ WorkingCopy CppModelManager::buildWorkingCopyList()
 {
     WorkingCopy workingCopy;
 
-    foreach (const CppEditorSupport *editorSupport, cppEditorSupportList()) {
-        workingCopy.insert(editorSupport->fileName(), editorSupport->contents(),
-                           editorSupport->editorRevision());
-    }
+    foreach (const EditorDocumentHandle *cppEditor, cppEditors())
+        workingCopy.insert(cppEditor->filePath(), cppEditor->contents(), cppEditor->revision());
 
     QSetIterator<AbstractEditorSupport *> it(m_extraEditorSupports);
     while (it.hasNext()) {
@@ -551,10 +543,10 @@ void CppModelManager::removeProjectInfoFilesAndIncludesFromSnapshot(const Projec
     }
 }
 
-QList<CppEditorSupport *> CppModelManager::cppEditorSupportList() const
+QList<EditorDocumentHandle *> CppModelManager::cppEditors() const
 {
-    QMutexLocker locker(&m_cppEditorSupportsMutex);
-    return m_cppEditorSupports.values();
+    QMutexLocker locker(&m_cppEditorsMutex);
+    return m_cppEditors.values();
 }
 
 /// \brief Remove all given files from the snapshot.
@@ -832,8 +824,8 @@ void CppModelManager::GC()
 
     // Collect files of CppEditorSupport and AbstractEditorSupport.
     QStringList filesInEditorSupports;
-    foreach (const CppEditorSupport *cppEditorSupport, cppEditorSupportList())
-        filesInEditorSupports << cppEditorSupport->fileName();
+    foreach (const EditorDocumentHandle *cppEditor, cppEditors())
+        filesInEditorSupports << cppEditor->filePath();
 
     QSetIterator<AbstractEditorSupport *> jt(m_extraEditorSupports);
     while (jt.hasNext()) {
@@ -909,13 +901,13 @@ CppCompletionAssistProvider *CppModelManager::completionAssistProvider(const QSt
     return cms->completionAssistProvider();
 }
 
-CppHighlightingSupport *CppModelManager::highlightingSupport(
+BaseEditorDocumentProcessor *CppModelManager::editorDocumentProcessor(
         TextEditor::BaseTextDocument *baseTextDocument) const
 {
     QTC_ASSERT(baseTextDocument, return 0);
     ModelManagerSupport *cms = modelManagerSupportForMimeType(baseTextDocument->mimeType());
     QTC_ASSERT(cms, return 0);
-    return cms->highlightingSupport(baseTextDocument);
+    return cms->editorDocumentProcessor(baseTextDocument);
 }
 
 void CppModelManager::setIndexingSupport(CppIndexingSupport *indexingSupport)
@@ -934,27 +926,3 @@ void CppModelManager::enableGarbageCollector(bool enable)
     m_delayedGcTimer->stop();
     m_enableGC = enable;
 }
-
-bool CppModelManager::setExtraDiagnostics(const QString &fileName,
-                                          const QString &kind,
-                                          const QList<Document::DiagnosticMessage> &diagnostics)
-{
-    foreach (CppEditorSupport *editorSupport, cppEditorSupportList()) {
-        if (editorSupport->fileName() == fileName) {
-            editorSupport->setExtraDiagnostics(kind, diagnostics);
-            return true;
-        }
-    }
-    return false;
-}
-
-void CppModelManager::setIfdefedOutBlocks(const QString &fileName,
-                                          const QList<TextEditor::BlockRange> &ifdeffedOutBlocks)
-{
-    foreach (CppEditorSupport *editorSupport, cppEditorSupportList()) {
-        if (editorSupport->fileName() == fileName) {
-            editorSupport->setIfdefedOutBlocks(ifdeffedOutBlocks);
-            break;
-        }
-    }
-}
diff --git a/src/plugins/cpptools/cppmodelmanager.h b/src/plugins/cpptools/cppmodelmanager.h
index c029bcb67e0b05c7fd92505cae23335fab705798..490c9f803b216c1170887429edb1782a75933103 100644
--- a/src/plugins/cpptools/cppmodelmanager.h
+++ b/src/plugins/cpptools/cppmodelmanager.h
@@ -44,8 +44,6 @@ namespace TextEditor { class BaseTextEditorWidget; }
 
 namespace CppTools {
 
-class CppEditorSupport;
-
 namespace Internal {
 
 class CppFindReferences;
@@ -94,8 +92,10 @@ public:
 
     virtual void addExtraEditorSupport(AbstractEditorSupport *editorSupport);
     virtual void removeExtraEditorSupport(AbstractEditorSupport *editorSupport);
-    virtual CppEditorSupport *cppEditorSupport(TextEditor::BaseTextEditor *textEditor);
-    virtual void deleteCppEditorSupport(TextEditor::BaseTextEditor *textEditor);
+
+    virtual EditorDocumentHandle *editorDocument(const QString &filePath);
+    virtual void registerEditorDocument(EditorDocumentHandle *editorDocument);
+    virtual void unregisterEditorDocument(const QString &filePath);
 
     virtual QList<int> references(CPlusPlus::Symbol *symbol, const CPlusPlus::LookupContext &context);
 
@@ -106,18 +106,13 @@ public:
     virtual void findMacroUsages(const CPlusPlus::Macro &macro);
     virtual void renameMacroUsages(const CPlusPlus::Macro &macro, const QString &replacement);
 
-    virtual bool setExtraDiagnostics(const QString &fileName, const QString &key,
-                                     const QList<Document::DiagnosticMessage> &diagnostics);
-    virtual void setIfdefedOutBlocks(const QString &fileName,
-                                     const QList<TextEditor::BlockRange> &ifdeffedOutBlocks);
-
-    void finishedRefreshingSourceFiles(const QStringList &files);
+    virtual void finishedRefreshingSourceFiles(const QStringList &files);
 
     virtual void addModelManagerSupport(ModelManagerSupport *modelManagerSupport);
     virtual ModelManagerSupport *modelManagerSupportForMimeType(const QString &mimeType) const;
     virtual CppCompletionAssistProvider *completionAssistProvider(const QString &mimeType) const;
-    virtual CppHighlightingSupport *highlightingSupport(
-            TextEditor::BaseTextDocument *baseTextDocument) const;
+    virtual BaseEditorDocumentProcessor *editorDocumentProcessor(
+                TextEditor::BaseTextDocument *baseTextDocument) const;
 
     virtual void setIndexingSupport(CppIndexingSupport *indexingSupport);
     virtual CppIndexingSupport *indexingSupport();
@@ -176,7 +171,7 @@ private:
     void removeFilesFromSnapshot(const QSet<QString> &removedFiles);
     void removeProjectInfoFilesAndIncludesFromSnapshot(const ProjectInfo &projectInfo);
 
-    QList<CppEditorSupport *> cppEditorSupportList() const;
+    QList<EditorDocumentHandle *> cppEditors() const;
 
     WorkingCopy buildWorkingCopyList();
 
@@ -208,8 +203,8 @@ private:
     QByteArray m_definedMacros;
 
     // Editor integration
-    mutable QMutex m_cppEditorSupportsMutex;
-    QMap<TextEditor::BaseTextEditor *, CppEditorSupport *> m_cppEditorSupports;
+    mutable QMutex m_cppEditorsMutex;
+    QMap<QString, EditorDocumentHandle *> m_cppEditors;
     QSet<AbstractEditorSupport *> m_extraEditorSupports;
 
     // Completion & highlighting
diff --git a/src/plugins/cpptools/cppmodelmanager_test.cpp b/src/plugins/cpptools/cppmodelmanager_test.cpp
index b443f5ba5a268326ae8689fa7fb965ccecb60253..e4bce83d1debd97a180331edd859362f5fe6e0c8 100644
--- a/src/plugins/cpptools/cppmodelmanager_test.cpp
+++ b/src/plugins/cpptools/cppmodelmanager_test.cpp
@@ -27,10 +27,11 @@
 **
 ****************************************************************************/
 
+#include "builtineditordocumentparser.h"
 #include "cppsourceprocessor.h"
-#include "cpptoolseditorsupport.h"
 #include "cpptoolsplugin.h"
 #include "cpptoolstestcase.h"
+#include "editordocumenthandle.h"
 #include "modelmanagertesthelper.h"
 
 #include <coreplugin/editormanager/editormanager.h>
@@ -865,10 +866,10 @@ void CppToolsPlugin::test_modelmanager_defines_per_project()
         QCOMPARE(Core::DocumentModel::openedDocuments().size(), 1);
         QVERIFY(mm->isCppEditor(editor));
 
-        CppEditorSupport *sup = mm->cppEditorSupport(
-                    qobject_cast<TextEditor::BaseTextEditor *>(editor));
-        while (sup->lastSemanticInfoDocument().isNull())
-            QCoreApplication::processEvents();
+//        CppEditorSupport *sup = mm->cppEditorSupport(
+//                    qobject_cast<TextEditor::BaseTextEditor *>(editor));
+//        while (sup->lastSemanticInfoDocument().isNull())
+//            QCoreApplication::processEvents();
 
         Document::Ptr doc = mm->document(fileName);
         QCOMPARE(nameOfFirstDeclaration(doc), firstDeclarationName);
@@ -942,20 +943,16 @@ void CppToolsPlugin::test_modelmanager_precompiled_headers()
         QCOMPARE(Core::DocumentModel::openedDocuments().size(), 1);
         QVERIFY(mm->isCppEditor(editor));
 
-        CppEditorSupport *sup = mm->cppEditorSupport(
-                    qobject_cast<TextEditor::BaseTextEditor *>(editor));
-        while (sup->lastSemanticInfoDocument().isNull())
-            QCoreApplication::processEvents();
-
-        sup->documentParser()->setUsePrecompiledHeaders(true);
-        sup->documentParser()->update(mm->workingCopy());
+        BuiltinEditorDocumentParser *parser = BuiltinEditorDocumentParser::get(fileName);
+        parser->setUsePrecompiledHeaders(true);
+        parser->update(mm->workingCopy());
 
         // Check if defines from pch are considered
         Document::Ptr document = mm->document(fileName);
         QCOMPARE(nameOfFirstDeclaration(document), firstDeclarationName);
 
         // Check if declarations from pch are considered
-        CPlusPlus::LookupContext context(document, sup->documentParser()->snapshot());
+        CPlusPlus::LookupContext context(document, parser->snapshot());
         const CPlusPlus::Identifier *identifier
             = document->control()->identifier(firstClassInPchFile.data());
         const QList<CPlusPlus::LookupItem> results = context.lookup(identifier,
@@ -1025,13 +1022,10 @@ void CppToolsPlugin::test_modelmanager_defines_per_editor()
         QCOMPARE(Core::DocumentModel::openedDocuments().size(), 1);
         QVERIFY(mm->isCppEditor(editor));
 
-        CppEditorSupport *sup = mm->cppEditorSupport(
-                    qobject_cast<TextEditor::BaseTextEditor *>(editor));
-        while (sup->lastSemanticInfoDocument().isNull())
-            QCoreApplication::processEvents();
-
-        sup->documentParser()->setEditorDefines(editorDefines.toUtf8());
-        sup->documentParser()->update(mm->workingCopy());
+        const QString filePath = editor->document()->filePath();
+        BaseEditorDocumentParser *parser = BaseEditorDocumentParser::get(filePath);
+        parser->setEditorDefines(editorDefines.toUtf8());
+        parser->update(mm->workingCopy());
 
         Document::Ptr doc = mm->document(main1File);
         QCOMPARE(nameOfFirstDeclaration(doc), firstDeclarationName);
diff --git a/src/plugins/cpptools/cppmodelmanagerinterface.h b/src/plugins/cpptools/cppmodelmanagerinterface.h
index 53120715fd3cd4d9198a1672d461cee10828d1af..f48950499fea95da70244be2dbe297a0fff471d9 100644
--- a/src/plugins/cpptools/cppmodelmanagerinterface.h
+++ b/src/plugins/cpptools/cppmodelmanagerinterface.h
@@ -52,9 +52,9 @@ namespace Utils { class FileName; }
 namespace CppTools {
 
 class AbstractEditorSupport;
+class BaseEditorDocumentProcessor;
 class CppCompletionAssistProvider;
-class CppEditorSupport;
-class CppHighlightingSupport;
+class EditorDocumentHandle;
 class CppIndexingSupport;
 class ModelManagerSupport;
 class WorkingCopy;
@@ -95,8 +95,10 @@ public:
 
     virtual void addExtraEditorSupport(CppTools::AbstractEditorSupport *editorSupport) = 0;
     virtual void removeExtraEditorSupport(CppTools::AbstractEditorSupport *editorSupport) = 0;
-    virtual CppEditorSupport *cppEditorSupport(TextEditor::BaseTextEditor *textEditor) = 0;
-    virtual void deleteCppEditorSupport(TextEditor::BaseTextEditor *textEditor) = 0;
+
+    virtual EditorDocumentHandle *editorDocument(const QString &filePath) = 0;
+    virtual void registerEditorDocument(EditorDocumentHandle *editorDocument) = 0;
+    virtual void unregisterEditorDocument(const QString &filePath) = 0;
 
     virtual QList<int> references(CPlusPlus::Symbol *symbol,
                                   const CPlusPlus::LookupContext &context) = 0;
@@ -108,14 +110,13 @@ public:
     virtual void renameMacroUsages(const CPlusPlus::Macro &macro, const QString &replacement = QString()) = 0;
     virtual void findMacroUsages(const CPlusPlus::Macro &macro) = 0;
 
-    virtual void setIfdefedOutBlocks(const QString &fileName,
-                                     const QList<TextEditor::BlockRange> &ifdeffedOutBlocks) = 0;
+    virtual void finishedRefreshingSourceFiles(const QStringList &files) = 0;
 
     virtual void addModelManagerSupport(ModelManagerSupport *modelManagerSupport) = 0;
     virtual ModelManagerSupport *modelManagerSupportForMimeType(const QString &mimeType) const = 0;
     virtual CppCompletionAssistProvider *completionAssistProvider(const QString &mimeType) const = 0;
-    virtual CppHighlightingSupport *highlightingSupport(
-            TextEditor::BaseTextDocument *baseTextDocument) const = 0;
+    virtual BaseEditorDocumentProcessor *editorDocumentProcessor(
+                TextEditor::BaseTextDocument *baseTextDocument) const = 0;
 
     virtual void setIndexingSupport(CppTools::CppIndexingSupport *indexingSupport) = 0;
     virtual CppIndexingSupport *indexingSupport() = 0;
diff --git a/src/plugins/cpptools/cppmodelmanagersupport.h b/src/plugins/cpptools/cppmodelmanagersupport.h
index 556f34cbf8e2441a1ab450a428fa7bc8472975ec..423b096415d1095cd18fbd30ff58067c089a45b0 100644
--- a/src/plugins/cpptools/cppmodelmanagersupport.h
+++ b/src/plugins/cpptools/cppmodelmanagersupport.h
@@ -38,8 +38,8 @@ namespace TextEditor { class BaseTextDocument; }
 
 namespace CppTools {
 
+class BaseEditorDocumentProcessor;
 class CppCompletionAssistProvider;
-class CppHighlightingSupport;
 
 class CPPTOOLS_EXPORT ModelManagerSupport
 {
@@ -50,8 +50,8 @@ public:
     virtual QString displayName() const = 0;
 
     virtual CppCompletionAssistProvider *completionAssistProvider() = 0;
-    virtual CppHighlightingSupport *highlightingSupport(
-            TextEditor::BaseTextDocument *baseTextDocument) = 0;
+    virtual BaseEditorDocumentProcessor *editorDocumentProcessor(
+                TextEditor::BaseTextDocument *baseTextDocument) = 0;
 };
 
 } // CppTools namespace
diff --git a/src/plugins/cpptools/cppmodelmanagersupportinternal.cpp b/src/plugins/cpptools/cppmodelmanagersupportinternal.cpp
index bf43cf79080847813083a9c828e1b3dfd635f791..9074a499b2ba362fca252d18ebf4488c2634cd8a 100644
--- a/src/plugins/cpptools/cppmodelmanagersupportinternal.cpp
+++ b/src/plugins/cpptools/cppmodelmanagersupportinternal.cpp
@@ -28,8 +28,8 @@
 ****************************************************************************/
 
 #include "cppcompletionassist.h"
-#include "cpphighlightingsupportinternal.h"
 #include "cppmodelmanagersupportinternal.h"
+#include "builtineditordocumentprocessor.h"
 
 #include <QCoreApplication>
 
@@ -56,13 +56,13 @@ QString ModelManagerSupportInternal::displayName() const
                                        "Qt Creator Built-in");
 }
 
-CppCompletionAssistProvider *ModelManagerSupportInternal::completionAssistProvider()
+BaseEditorDocumentProcessor *ModelManagerSupportInternal::editorDocumentProcessor(
+        TextEditor::BaseTextDocument *baseTextDocument)
 {
-    return m_completionAssistProvider.data();
+    return new BuiltinEditorDocumentProcessor(baseTextDocument);
 }
 
-CppHighlightingSupport *ModelManagerSupportInternal::highlightingSupport(
-        TextEditor::BaseTextDocument *baseTextDocument)
+CppCompletionAssistProvider *ModelManagerSupportInternal::completionAssistProvider()
 {
-    return new CppHighlightingSupportInternal(baseTextDocument);
+    return m_completionAssistProvider.data();
 }
diff --git a/src/plugins/cpptools/cppmodelmanagersupportinternal.h b/src/plugins/cpptools/cppmodelmanagersupportinternal.h
index a55280af9d23d2304a228c635cebc5576dea0602..2e9a335ba5f662c28515a5178ec2d65671e8c079 100644
--- a/src/plugins/cpptools/cppmodelmanagersupportinternal.h
+++ b/src/plugins/cpptools/cppmodelmanagersupportinternal.h
@@ -49,8 +49,8 @@ public:
     virtual QString displayName() const;
 
     virtual CppCompletionAssistProvider *completionAssistProvider();
-    virtual CppHighlightingSupport *highlightingSupport(
-            TextEditor::BaseTextDocument *baseTextDocument);
+    virtual BaseEditorDocumentProcessor *editorDocumentProcessor(
+                TextEditor::BaseTextDocument *baseTextDocument);
 
 private:
     QScopedPointer<CppCompletionAssistProvider> m_completionAssistProvider;
diff --git a/src/plugins/cpptools/cppsemanticinfo.cpp b/src/plugins/cpptools/cppsemanticinfo.cpp
index 09407681c3a8926a188f100afae54d5f21def319..5ab57d0ca1b982fc0009db23ccf5d25c39b1d89a 100644
--- a/src/plugins/cpptools/cppsemanticinfo.cpp
+++ b/src/plugins/cpptools/cppsemanticinfo.cpp
@@ -32,6 +32,6 @@
 using namespace CppTools;
 
 SemanticInfo::SemanticInfo()
-    : revision(0), forced(false), complete(true)
+    : revision(0), complete(true), localUsesUpdated(false)
 {
 }
diff --git a/src/plugins/cpptools/cppsemanticinfo.h b/src/plugins/cpptools/cppsemanticinfo.h
index c0968edb3a3cb9abe4061525e75f3ee69985b69f..4066bfef4037d4b3e19f4fe3904f02f0d122f54b 100644
--- a/src/plugins/cpptools/cppsemanticinfo.h
+++ b/src/plugins/cpptools/cppsemanticinfo.h
@@ -45,28 +45,22 @@ class CPPTOOLS_EXPORT SemanticInfo
 public:
     struct Source
     {
-        const CPlusPlus::Snapshot snapshot;
         const QString fileName;
         const QByteArray code;
-        const int line;
-        const int column;
         const unsigned revision;
         const bool force;
 
-        Source()
-            : line(0), column(0), revision(0), force(false)
-        { }
+        Source() : revision(0), force(false) {}
 
-        Source(const CPlusPlus::Snapshot &snapshot,
-               const QString &fileName,
+        Source(const QString &fileName,
                const QByteArray &code,
-               int line, int column,
                unsigned revision,
                bool force)
-            : snapshot(snapshot), fileName(fileName),
-              code(code), line(line), column(column),
-              revision(revision), force(force)
-        { }
+            : fileName(fileName)
+            , code(code)
+            , revision(revision)
+            , force(force)
+        {}
     };
 
 public:
@@ -78,10 +72,12 @@ public:
     SemanticInfo();
 
     unsigned revision;
-    bool forced;
     bool complete;
     CPlusPlus::Snapshot snapshot;
     CPlusPlus::Document::Ptr doc;
+
+    // Widget specific (e.g. related to cursor position)
+    bool localUsesUpdated;
     LocalUseMap localUses;
 };
 
diff --git a/src/plugins/cpptools/cppsemanticinfoupdater.cpp b/src/plugins/cpptools/cppsemanticinfoupdater.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..71fbb16e464c39dba19d9b7b53c5ad99fad2d39a
--- /dev/null
+++ b/src/plugins/cpptools/cppsemanticinfoupdater.cpp
@@ -0,0 +1,226 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "builtineditordocumentparser.h"
+#include "cpplocalsymbols.h"
+#include "cppsemanticinfoupdater.h"
+
+#include <utils/qtcassert.h>
+#include <utils/qtcoverride.h>
+#include <utils/runextensions.h>
+
+#include <cplusplus/Control.h>
+#include <cplusplus/CppDocument.h>
+#include <cplusplus/TranslationUnit.h>
+
+enum { debug = 0 };
+
+using namespace CPlusPlus;
+using namespace CppTools;
+
+namespace CppTools {
+
+class SemanticInfoUpdaterPrivate
+{
+public:
+    class FuturizedTopLevelDeclarationProcessor: public CPlusPlus::TopLevelDeclarationProcessor
+    {
+    public:
+        FuturizedTopLevelDeclarationProcessor(QFutureInterface<void> &future): m_future(future) {}
+        bool processDeclaration(CPlusPlus::DeclarationAST *) { return !isCanceled(); }
+        bool isCanceled() { return m_future.isCanceled(); }
+    private:
+        QFutureInterface<void> m_future;
+    };
+
+public:
+    SemanticInfoUpdaterPrivate(SemanticInfoUpdater *q, BuiltinEditorDocumentParser *m_parser);
+    ~SemanticInfoUpdaterPrivate();
+
+    SemanticInfo semanticInfo() const;
+    void setSemanticInfo(const SemanticInfo &semanticInfo, bool emitSignal);
+
+    SemanticInfo update(const SemanticInfo::Source &source,
+                        bool emitSignalWhenFinished,
+                        FuturizedTopLevelDeclarationProcessor *processor);
+
+    bool reuseCurrentSemanticInfo(const SemanticInfo::Source &source, bool emitSignalWhenFinished);
+
+    void update_helper(QFutureInterface<void> &future, const SemanticInfo::Source source);
+
+public:
+    SemanticInfoUpdater *q;
+    mutable QMutex m_lock;
+    SemanticInfo m_semanticInfo;
+    QFuture<void> m_future;
+    BuiltinEditorDocumentParser *m_parser;
+};
+
+SemanticInfoUpdaterPrivate::SemanticInfoUpdaterPrivate(SemanticInfoUpdater *q,
+                                                       BuiltinEditorDocumentParser *parser)
+    : q(q)
+    , m_parser(parser)
+{
+}
+
+SemanticInfoUpdaterPrivate::~SemanticInfoUpdaterPrivate()
+{
+    m_future.cancel();
+    m_future.waitForFinished();
+}
+
+SemanticInfo SemanticInfoUpdaterPrivate::semanticInfo() const
+{
+    QMutexLocker locker(&m_lock);
+    return m_semanticInfo;
+}
+
+void SemanticInfoUpdaterPrivate::setSemanticInfo(const SemanticInfo &semanticInfo, bool emitSignal)
+{
+    {
+        QMutexLocker locker(&m_lock);
+        m_semanticInfo = semanticInfo;
+    }
+    if (emitSignal) {
+        if (debug)
+            qDebug() << "SemanticInfoUpdater: emiting new info";
+        emit q->updated(semanticInfo);
+    }
+}
+
+SemanticInfo SemanticInfoUpdaterPrivate::update(const SemanticInfo::Source &source,
+                                                bool emitSignalWhenFinished,
+                                                FuturizedTopLevelDeclarationProcessor *processor)
+{
+    if (debug)
+        qDebug() << "SemanticInfoUpdater: update() - source revision" << source.revision;
+
+    SemanticInfo newSemanticInfo;
+    newSemanticInfo.revision = source.revision;
+
+    QTC_ASSERT(m_parser, return newSemanticInfo);
+    newSemanticInfo.snapshot = m_parser->snapshot();
+    QTC_ASSERT(newSemanticInfo.snapshot.contains(source.fileName), return newSemanticInfo);
+
+    Document::Ptr doc = newSemanticInfo.snapshot.preprocessedDocument(source.code, source.fileName);
+    if (processor)
+        doc->control()->setTopLevelDeclarationProcessor(processor);
+    doc->check();
+    if (processor && processor->isCanceled())
+        newSemanticInfo.complete = false;
+    newSemanticInfo.doc = doc;
+
+    if (debug)
+        qDebug() << "SemanticInfoUpdater: update() - re-calculated document. Canceled ="
+                 << !newSemanticInfo.complete;
+
+    setSemanticInfo(newSemanticInfo, emitSignalWhenFinished);
+    return newSemanticInfo;
+}
+
+bool SemanticInfoUpdaterPrivate::reuseCurrentSemanticInfo(const SemanticInfo::Source &source,
+                                                          bool emitSignalWhenFinished)
+{
+    const SemanticInfo currentSemanticInfo = semanticInfo();
+
+    if (!source.force
+            && currentSemanticInfo.complete
+            && currentSemanticInfo.revision == source.revision
+            && currentSemanticInfo.doc
+            && currentSemanticInfo.doc->translationUnit()->ast()
+            && currentSemanticInfo.doc->fileName() == source.fileName) {
+        SemanticInfo newSemanticInfo;
+        newSemanticInfo.revision = source.revision;
+        newSemanticInfo.doc = currentSemanticInfo.doc;
+        newSemanticInfo.snapshot = currentSemanticInfo.snapshot; // ### TODO: use the new snapshot.
+        setSemanticInfo(newSemanticInfo, emitSignalWhenFinished);
+        if (debug)
+            qDebug() << "SemanticInfoUpdater: re-using current semantic info - source.revision"
+                     << source.revision;
+        return true;
+    }
+
+    return false;
+}
+
+void SemanticInfoUpdaterPrivate::update_helper(QFutureInterface<void> &future,
+                                               const SemanticInfo::Source source)
+{
+    FuturizedTopLevelDeclarationProcessor processor(future);
+    update(source, true, &processor);
+}
+
+SemanticInfoUpdater::SemanticInfoUpdater(BuiltinEditorDocumentParser *parser)
+    : d(new SemanticInfoUpdaterPrivate(this, parser))
+{
+}
+
+SemanticInfoUpdater::~SemanticInfoUpdater()
+{
+    d->m_future.cancel();
+    d->m_future.waitForFinished();
+}
+
+SemanticInfo SemanticInfoUpdater::update(const SemanticInfo::Source &source)
+{
+    if (debug)
+        qDebug() << "SemanticInfoUpdater: update() - synchronous";
+    d->m_future.cancel();
+
+    const bool emitSignalWhenFinished = false;
+    if (d->reuseCurrentSemanticInfo(source, emitSignalWhenFinished)) {
+        d->m_future = QFuture<void>();
+        return semanticInfo();
+    }
+
+    return d->update(source, emitSignalWhenFinished, 0);
+}
+
+void SemanticInfoUpdater::updateDetached(const SemanticInfo::Source source)
+{
+    if (debug)
+        qDebug() << "SemanticInfoUpdater: updateDetached() - asynchronous";
+    d->m_future.cancel();
+
+    const bool emitSignalWhenFinished = true;
+    if (d->reuseCurrentSemanticInfo(source, emitSignalWhenFinished)) {
+        d->m_future = QFuture<void>();
+        return;
+    }
+
+    d->m_future = QtConcurrent::run<SemanticInfoUpdaterPrivate, void, const SemanticInfo::Source>
+            (&SemanticInfoUpdaterPrivate::update_helper, d.data(), source);
+}
+
+SemanticInfo SemanticInfoUpdater::semanticInfo() const
+{
+    return d->semanticInfo();
+}
+
+} // namespace CppTools
diff --git a/src/plugins/cpptools/cpphighlightingsupportinternal.h b/src/plugins/cpptools/cppsemanticinfoupdater.h
similarity index 64%
rename from src/plugins/cpptools/cpphighlightingsupportinternal.h
rename to src/plugins/cpptools/cppsemanticinfoupdater.h
index 14fb8236ce526535d3cd3b8c00f06216e82061f3..0436bf184657ca26792934795b93a4de1e4fbcf4 100644
--- a/src/plugins/cpptools/cpphighlightingsupportinternal.h
+++ b/src/plugins/cpptools/cppsemanticinfoupdater.h
@@ -27,37 +27,40 @@
 **
 ****************************************************************************/
 
-#ifndef CPPTOOLS_CPPHIGHLIGHTINGSUPPORTINTERNAL_H
-#define CPPTOOLS_CPPHIGHLIGHTINGSUPPORTINTERNAL_H
+#ifndef CPPSEMANTICINFOUPDATER_H
+#define CPPSEMANTICINFOUPDATER_H
 
-#include "cpphighlightingsupport.h"
+#include "cppsemanticinfo.h"
 
-#include <QFuture>
+#include <QObject>
+#include <QScopedPointer>
 
 namespace CppTools {
-namespace Internal {
 
-class CppHighlightingSupportInternal: public CppHighlightingSupport
+class BuiltinEditorDocumentParser;
+class SemanticInfoUpdaterPrivate;
+
+class SemanticInfoUpdater : public QObject
 {
+    Q_OBJECT
+    Q_DISABLE_COPY(SemanticInfoUpdater)
+
 public:
-    CppHighlightingSupportInternal(TextEditor::BaseTextDocument *baseTextDocument);
-    virtual ~CppHighlightingSupportInternal();
+    explicit SemanticInfoUpdater(BuiltinEditorDocumentParser *parser);
+    ~SemanticInfoUpdater();
 
-    virtual bool requiresSemanticInfo() const
-    { return true; }
+    SemanticInfo semanticInfo() const;
 
-    virtual bool hightlighterHandlesDiagnostics() const
-    { return false; }
+    SemanticInfo update(const SemanticInfo::Source &source);
+    void updateDetached(const SemanticInfo::Source source);
 
-    virtual bool hightlighterHandlesIfdefedOutBlocks() const
-    { return false; }
+signals:
+    void updated(CppTools::SemanticInfo semanticInfo);
 
-    virtual QFuture<TextEditor::HighlightingResult> highlightingFuture(
-            const CPlusPlus::Document::Ptr &doc,
-            const CPlusPlus::Snapshot &snapshot) const;
+private:
+    QScopedPointer<SemanticInfoUpdaterPrivate> d;
 };
 
-} // namespace Internal
 } // namespace CppTools
 
-#endif // CPPTOOLS_CPPHIGHLIGHTINGSUPPORTINTERNAL_H
+#endif // CPPSEMANTICINFOUPDATER_H
diff --git a/src/plugins/cpptools/cppsourceprocessor_test.cpp b/src/plugins/cpptools/cppsourceprocessor_test.cpp
index af59cd8334c833d2de1dc662a650db83755eca7d..9b145949544642f173329d7e64403717d31827fc 100644
--- a/src/plugins/cpptools/cppsourceprocessor_test.cpp
+++ b/src/plugins/cpptools/cppsourceprocessor_test.cpp
@@ -33,8 +33,8 @@
 #include "cppmodelmanager.h"
 #include "cppsourceprocessertesthelper.h"
 #include "cppsourceprocessor.h"
-#include "cpptoolseditorsupport.h"
 #include "cpptoolstestcase.h"
+#include "editordocumenthandle.h"
 
 #include <texteditor/basetexteditor.h>
 
@@ -140,13 +140,11 @@ void CppToolsPlugin::test_cppsourceprocessor_includes_cyclic()
     QVERIFY(testCase.openBaseTextEditor(fileName1, &editor));
     testCase.closeEditorAtEndOfTestCase(editor);
 
-    // Get editor snapshot
-    CppEditorSupport *cppEditorSupport = CppModelManagerInterface::instance()
-        ->cppEditorSupport(editor);
-    QVERIFY(cppEditorSupport);
-    BuiltinEditorDocumentParser::Ptr documentParser = cppEditorSupport->documentParser();
-    QVERIFY(documentParser);
-    Snapshot snapshot = documentParser->snapshot();
+    // Check editor snapshot
+    const QString filePath = editor->document()->filePath();
+    BuiltinEditorDocumentParser *parser = BuiltinEditorDocumentParser::get(filePath);
+    QVERIFY(parser);
+    Snapshot snapshot = parser->snapshot();
     QCOMPARE(snapshot.size(), 3); // Configuration file included
 
     // Check includes
diff --git a/src/plugins/cpptools/cpptools.pro b/src/plugins/cpptools/cpptools.pro
index a0e45d600082af5ea6c4b61c5cd51dfd06d43437..941784703b35fbc8addeb9b08c53200e212dba88 100644
--- a/src/plugins/cpptools/cpptools.pro
+++ b/src/plugins/cpptools/cpptools.pro
@@ -5,7 +5,9 @@ include(../../qtcreatorplugin.pri)
 HEADERS += \
     abstracteditorsupport.h \
     baseeditordocumentparser.h \
+    baseeditordocumentprocessor.h \
     builtineditordocumentparser.h \
+    builtineditordocumentprocessor.h \
     builtinindexingsupport.h \
     commentssettings.h \
     completionsettingspage.h \
@@ -26,8 +28,6 @@ HEADERS += \
     cppfilesettingspage.h \
     cppfindreferences.h \
     cppfunctionsfilter.h \
-    cpphighlightingsupport.h \
-    cpphighlightingsupportinternal.h \
     cppindexingsupport.h \
     cpplocalsymbols.h \
     cpplocatordata.h \
@@ -42,20 +42,22 @@ HEADERS += \
     cppqtstyleindenter.h \
     cpprefactoringchanges.h \
     cppsemanticinfo.h \
+    cppsemanticinfoupdater.h \
     cppsourceprocessor.h \
     cpptools_global.h \
     cpptoolsconstants.h \
-    cpptoolseditorsupport.h \
     cpptoolsplugin.h \
     cpptoolsreuse.h \
     cpptoolssettings.h \
     cppworkingcopy.h \
     doxygengenerator.h \
+    editordocumenthandle.h \
     functionutils.h \
     includeutils.h \
     indexitem.h \
     insertionpointlocator.h \
     searchsymbols.h \
+    semantichighlighter.h \
     stringtable.h \
     symbolfinder.h \
     symbolsfindfilter.h \
@@ -64,7 +66,9 @@ HEADERS += \
 SOURCES += \
     abstracteditorsupport.cpp \
     baseeditordocumentparser.cpp \
+    baseeditordocumentprocessor.cpp \
     builtineditordocumentparser.cpp \
+    builtineditordocumentprocessor.cpp \
     builtinindexingsupport.cpp \
     commentssettings.cpp \
     completionsettingspage.cpp \
@@ -85,8 +89,6 @@ SOURCES += \
     cppfilesettingspage.cpp \
     cppfindreferences.cpp \
     cppfunctionsfilter.cpp \
-    cpphighlightingsupport.cpp \
-    cpphighlightingsupportinternal.cpp \
     cppindexingsupport.cpp \
     cpplocalsymbols.cpp \
     cpplocatordata.cpp \
@@ -101,18 +103,20 @@ SOURCES += \
     cppqtstyleindenter.cpp \
     cpprefactoringchanges.cpp \
     cppsemanticinfo.cpp \
+    cppsemanticinfoupdater.cpp \
     cppsourceprocessor.cpp \
-    cpptoolseditorsupport.cpp \
     cpptoolsplugin.cpp \
     cpptoolsreuse.cpp \
     cpptoolssettings.cpp \
     cppworkingcopy.cpp \
     doxygengenerator.cpp \
+    editordocumenthandle.cpp \
     functionutils.cpp \
     includeutils.cpp \
     indexitem.cpp \
     insertionpointlocator.cpp \
     searchsymbols.cpp \
+    semantichighlighter.cpp \
     stringtable.cpp \
     symbolfinder.cpp \
     symbolsfindfilter.cpp \
diff --git a/src/plugins/cpptools/cpptools.qbs b/src/plugins/cpptools/cpptools.qbs
index 1c47b7ab608c27dc55fd21f4cb1ee6fb5996498e..d3f8681b9daa854eb3263eb0e36e19c685bb796d 100644
--- a/src/plugins/cpptools/cpptools.qbs
+++ b/src/plugins/cpptools/cpptools.qbs
@@ -25,7 +25,9 @@ QtcPlugin {
     files: [
         "abstracteditorsupport.cpp", "abstracteditorsupport.h",
         "baseeditordocumentparser.cpp", "baseeditordocumentparser.h",
+        "baseeditordocumentprocessor.cpp", "baseeditordocumentprocessor.h",
         "builtineditordocumentparser.cpp", "builtineditordocumentparser.h",
+        "builtineditordocumentprocessor.cpp", "builtineditordocumentprocessor.h",
         "builtinindexingsupport.cpp", "builtinindexingsupport.h",
         "commentssettings.cpp", "commentssettings.h",
         "completionsettingspage.cpp", "completionsettingspage.h", "completionsettingspage.ui",
@@ -46,8 +48,6 @@ QtcPlugin {
         "cppfilesettingspage.cpp", "cppfilesettingspage.h", "cppfilesettingspage.ui",
         "cppfindreferences.cpp", "cppfindreferences.h",
         "cppfunctionsfilter.cpp", "cppfunctionsfilter.h",
-        "cpphighlightingsupport.cpp", "cpphighlightingsupport.h",
-        "cpphighlightingsupportinternal.cpp", "cpphighlightingsupportinternal.h",
         "cppindexingsupport.cpp", "cppindexingsupport.h",
         "cpplocalsymbols.cpp", "cpplocalsymbols.h",
         "cpplocatordata.cpp", "cpplocatordata.h",
@@ -62,21 +62,23 @@ QtcPlugin {
         "cppqtstyleindenter.cpp", "cppqtstyleindenter.h",
         "cpprefactoringchanges.cpp", "cpprefactoringchanges.h",
         "cppsemanticinfo.cpp", "cppsemanticinfo.h",
+        "cppsemanticinfoupdater.cpp", "cppsemanticinfoupdater.h",
         "cppsourceprocessor.cpp", "cppsourceprocessor.h",
         "cpptools.qrc",
         "cpptools_global.h",
         "cpptoolsconstants.h",
-        "cpptoolseditorsupport.cpp", "cpptoolseditorsupport.h",
         "cpptoolsplugin.cpp", "cpptoolsplugin.h",
         "cpptoolsreuse.cpp", "cpptoolsreuse.h",
         "cpptoolssettings.cpp", "cpptoolssettings.h",
         "cppworkingcopy.cpp", "cppworkingcopy.h",
         "doxygengenerator.cpp", "doxygengenerator.h",
+        "editordocumenthandle.cpp", "editordocumenthandle.h",
         "functionutils.cpp", "functionutils.h",
         "includeutils.cpp", "includeutils.h",
         "indexitem.cpp", "indexitem.h",
         "insertionpointlocator.cpp", "insertionpointlocator.h",
         "searchsymbols.cpp", "searchsymbols.h",
+        "semantichighlighter.cpp", "semantichighlighter.h",
         "stringtable.cpp", "stringtable.h",
         "symbolfinder.cpp", "symbolfinder.h",
         "symbolsfindfilter.cpp", "symbolsfindfilter.h",
diff --git a/src/plugins/cpptools/cppworkingcopy.h b/src/plugins/cpptools/cppworkingcopy.h
index 3775838885d753fc2468d7e007a51a373fc833ca..df20c57bb254a5875a7fe5921542fb51fe1a678c 100644
--- a/src/plugins/cpptools/cppworkingcopy.h
+++ b/src/plugins/cpptools/cppworkingcopy.h
@@ -52,6 +52,9 @@ public:
     QByteArray source(const QString &fileName) const
     { return _elements.value(fileName).first; }
 
+    unsigned revision(const QString &fileName) const
+    { return _elements.value(fileName).second; }
+
     QPair<QByteArray, unsigned> get(const QString &fileName) const
     { return _elements.value(fileName); }
 
diff --git a/src/plugins/cpptools/cpphighlightingsupport.cpp b/src/plugins/cpptools/editordocumenthandle.cpp
similarity index 81%
rename from src/plugins/cpptools/cpphighlightingsupport.cpp
rename to src/plugins/cpptools/editordocumenthandle.cpp
index 9c3bcd3dd59eee7df1a06a3cbf332c9fe3ea5407..d30e1c773d9d1317e6c12cb9ef6fcb9eccf63b80 100644
--- a/src/plugins/cpptools/cpphighlightingsupport.cpp
+++ b/src/plugins/cpptools/editordocumenthandle.cpp
@@ -27,16 +27,23 @@
 **
 ****************************************************************************/
 
-#include "cpphighlightingsupport.h"
+#include "editordocumenthandle.h"
 
-using namespace CppTools;
+namespace CppTools {
 
-CppHighlightingSupport::CppHighlightingSupport(TextEditor::BaseTextDocument *baseTextDocument)
-    : m_baseTextDocument(baseTextDocument)
+/*!
+    \class CppTools::EditorDocumentHandle
+
+    \brief The EditorDocumentHandle class provides an interface to an opened
+           C++ editor document.
+*/
+
+EditorDocumentHandle::EditorDocumentHandle()
 {
-    Q_ASSERT(baseTextDocument);
 }
 
-CppHighlightingSupport::~CppHighlightingSupport()
+EditorDocumentHandle::~EditorDocumentHandle()
 {
 }
+
+} // namespace CppTools
diff --git a/src/plugins/cpptools/editordocumenthandle.h b/src/plugins/cpptools/editordocumenthandle.h
new file mode 100644
index 0000000000000000000000000000000000000000..81ba8689226ce5f179f4bad38a5efe2021c399bf
--- /dev/null
+++ b/src/plugins/cpptools/editordocumenthandle.h
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef EDITORDOCUMENTHANDLE_H
+#define EDITORDOCUMENTHANDLE_H
+
+#include "baseeditordocumentprocessor.h"
+#include "cpptools_global.h"
+
+namespace CppTools {
+
+class CPPTOOLS_EXPORT EditorDocumentHandle
+{
+public:
+    EditorDocumentHandle();
+    virtual ~EditorDocumentHandle();
+
+    // For the Working Copy
+    virtual QString filePath() const = 0;
+    virtual QByteArray contents() const = 0;
+    virtual unsigned revision() const = 0;
+
+    // For updating if new project info is set
+    virtual BaseEditorDocumentProcessor *processor() = 0;
+};
+
+} // namespace CppTools
+
+#endif // EDITORDOCUMENTHANDLE_H
diff --git a/src/plugins/cpptools/semantichighlighter.cpp b/src/plugins/cpptools/semantichighlighter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..33a77261a6f52957ca5623c12d9141d97fa43e08
--- /dev/null
+++ b/src/plugins/cpptools/semantichighlighter.cpp
@@ -0,0 +1,165 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "semantichighlighter.h"
+
+#include <texteditor/fontsettings.h>
+#include <texteditor/syntaxhighlighter.h>
+
+#include <utils/qtcassert.h>
+
+enum { debug = 0 };
+
+using namespace CPlusPlus;
+using TextEditor::SemanticHighlighter::incrementalApplyExtraAdditionalFormats;
+using TextEditor::SemanticHighlighter::clearExtraAdditionalFormatsUntilEnd;
+
+namespace CppTools {
+
+SemanticHighlighter::SemanticHighlighter(TextEditor::BaseTextDocument *baseTextDocument)
+    : QObject(baseTextDocument)
+    , m_baseTextDocument(baseTextDocument)
+    , m_revision(0)
+{
+    QTC_CHECK(m_baseTextDocument);
+
+    connect(baseTextDocument, &TextEditor::BaseTextDocument::fontSettingsChanged,
+            this, &SemanticHighlighter::onDocumentFontSettingsChanged);
+
+    updateFormatMapFromFontSettings();
+}
+
+SemanticHighlighter::~SemanticHighlighter()
+{
+    if (m_watcher) {
+        disconnectWatcher();
+        m_watcher->cancel();
+        m_watcher->waitForFinished();
+    }
+}
+
+void SemanticHighlighter::setHighlightingRunner(HighlightingRunner highlightingRunner)
+{
+    m_highlightingRunner = highlightingRunner;
+}
+
+void SemanticHighlighter::run()
+{
+    QTC_ASSERT(m_highlightingRunner, return);
+
+    if (debug)
+        qDebug() << "SemanticHighlighter: run()";
+
+    if (m_watcher) {
+        disconnectWatcher();
+        m_watcher->cancel();
+    }
+    m_watcher.reset(new QFutureWatcher<TextEditor::HighlightingResult>);
+    connectWatcher();
+
+    m_revision = documentRevision();
+    m_watcher->setFuture(m_highlightingRunner());
+}
+
+void SemanticHighlighter::onDocumentFontSettingsChanged()
+{
+    updateFormatMapFromFontSettings();
+    run();
+}
+
+void SemanticHighlighter::onHighlighterResultAvailable(int from, int to)
+{
+    if (documentRevision() != m_revision)
+        return; // outdated
+    else if (!m_watcher || m_watcher->isCanceled())
+        return; // aborted
+
+    if (debug)
+        qDebug() << "SemanticHighlighter: onHighlighterResultAvailable()" << from << to;
+
+    TextEditor::SyntaxHighlighter *highlighter = m_baseTextDocument->syntaxHighlighter();
+    QTC_ASSERT(highlighter, return);
+    incrementalApplyExtraAdditionalFormats(highlighter, m_watcher->future(), from, to, m_formatMap);
+}
+
+void SemanticHighlighter::onHighlighterFinished()
+{
+    QTC_ASSERT(m_watcher, return);
+    if (!m_watcher->isCanceled() && documentRevision() == m_revision) {
+        TextEditor::SyntaxHighlighter *highlighter = m_baseTextDocument->syntaxHighlighter();
+        QTC_CHECK(highlighter);
+        if (highlighter) {
+            if (debug)
+                qDebug() << "SemanticHighlighter: onHighlighterFinished() - clearing formats";
+            clearExtraAdditionalFormatsUntilEnd(highlighter, m_watcher->future());
+        }
+    }
+    m_watcher.reset();
+}
+
+void SemanticHighlighter::connectWatcher()
+{
+    typedef QFutureWatcher<TextEditor::HighlightingResult> Watcher;
+    connect(m_watcher.data(), &Watcher::resultsReadyAt,
+            this, &SemanticHighlighter::onHighlighterResultAvailable);
+    connect(m_watcher.data(), &Watcher::finished,
+            this, &SemanticHighlighter::onHighlighterFinished);
+}
+
+void SemanticHighlighter::disconnectWatcher()
+{
+    typedef QFutureWatcher<TextEditor::HighlightingResult> Watcher;
+    disconnect(m_watcher.data(), &Watcher::resultsReadyAt,
+               this, &SemanticHighlighter::onHighlighterResultAvailable);
+    disconnect(m_watcher.data(), &Watcher::finished,
+               this, &SemanticHighlighter::onHighlighterFinished);
+}
+
+unsigned SemanticHighlighter::documentRevision() const
+{
+    return m_baseTextDocument->document()->revision();
+}
+
+void SemanticHighlighter::updateFormatMapFromFontSettings()
+{
+    const TextEditor::FontSettings &fs = m_baseTextDocument->fontSettings();
+
+    m_formatMap[TypeUse] = fs.toTextCharFormat(TextEditor::C_TYPE);
+    m_formatMap[LocalUse] = fs.toTextCharFormat(TextEditor::C_LOCAL);
+    m_formatMap[FieldUse] = fs.toTextCharFormat(TextEditor::C_FIELD);
+    m_formatMap[EnumerationUse] = fs.toTextCharFormat(TextEditor::C_ENUMERATION);
+    m_formatMap[VirtualMethodUse] = fs.toTextCharFormat(TextEditor::C_VIRTUAL_METHOD);
+    m_formatMap[LabelUse] = fs.toTextCharFormat(TextEditor::C_LABEL);
+    m_formatMap[MacroUse] = fs.toTextCharFormat(TextEditor::C_PREPROCESSOR);
+    m_formatMap[FunctionUse] = fs.toTextCharFormat(TextEditor::C_FUNCTION);
+    m_formatMap[PseudoKeywordUse] = fs.toTextCharFormat(TextEditor::C_KEYWORD);
+    m_formatMap[StringUse] = fs.toTextCharFormat(TextEditor::C_STRING);
+}
+
+} // namespace CppTools
diff --git a/src/plugins/cpptools/cpphighlightingsupport.h b/src/plugins/cpptools/semantichighlighter.h
similarity index 62%
rename from src/plugins/cpptools/cpphighlightingsupport.h
rename to src/plugins/cpptools/semantichighlighter.h
index d4be6b14169859ab916e7bb618fd1a0053355b39..fb12bf34e69d41b83090f1f5a4f193faf2dab7e3 100644
--- a/src/plugins/cpptools/cpphighlightingsupport.h
+++ b/src/plugins/cpptools/semantichighlighter.h
@@ -27,23 +27,28 @@
 **
 ****************************************************************************/
 
-#ifndef CPPTOOLS_CPPHIGHLIGHTINGSUPPORT_H
-#define CPPTOOLS_CPPHIGHLIGHTINGSUPPORT_H
+#ifndef SEMANTICHIGHLIGHTER_H
+#define SEMANTICHIGHLIGHTER_H
 
+#include "cppsemanticinfo.h"
 #include "cpptools_global.h"
 
+#include <texteditor/basetextdocument.h>
 #include <texteditor/semantichighlighter.h>
 
-#include <cplusplus/CppDocument.h>
+#include <QFutureWatcher>
+#include <QScopedPointer>
+#include <QTextEdit>
 
-#include <QFuture>
-
-namespace TextEditor { class BaseTextDocument; }
+#include <functional>
 
 namespace CppTools {
 
-class CPPTOOLS_EXPORT CppHighlightingSupport
+class CPPTOOLS_EXPORT SemanticHighlighter : public QObject
 {
+    Q_OBJECT
+    Q_DISABLE_COPY(SemanticHighlighter)
+
 public:
     enum Kind {
         Unknown = 0,
@@ -59,27 +64,39 @@ public:
         StringUse
     };
 
+    typedef std::function<QFuture<TextEditor::HighlightingResult> ()> HighlightingRunner;
+
 public:
-    CppHighlightingSupport(TextEditor::BaseTextDocument *baseTextDocument);
-    virtual ~CppHighlightingSupport() = 0;
+    explicit SemanticHighlighter(TextEditor::BaseTextDocument *baseTextDocument);
+    ~SemanticHighlighter();
+
+    void setHighlightingRunner(HighlightingRunner highlightingRunner);
 
-    virtual bool requiresSemanticInfo() const = 0;
+    void run();
 
-    virtual bool hightlighterHandlesDiagnostics() const = 0;
-    virtual bool hightlighterHandlesIfdefedOutBlocks() const = 0;
+private slots:
+    void onDocumentFontSettingsChanged();
 
-    virtual QFuture<TextEditor::HighlightingResult> highlightingFuture(
-            const CPlusPlus::Document::Ptr &doc,
-            const CPlusPlus::Snapshot &snapshot) const = 0;
+    void onHighlighterResultAvailable(int from, int to);
+    void onHighlighterFinished();
 
-protected:
-    TextEditor::BaseTextDocument *baseTextDocument() const
-    { return m_baseTextDocument; }
+private:
+    void connectWatcher();
+    void disconnectWatcher();
+
+    unsigned documentRevision() const;
+    void updateFormatMapFromFontSettings();
 
 private:
     TextEditor::BaseTextDocument *m_baseTextDocument;
+
+    unsigned m_revision;
+    QScopedPointer<QFutureWatcher<TextEditor::HighlightingResult>> m_watcher;
+    QHash<int, QTextCharFormat> m_formatMap;
+
+    HighlightingRunner m_highlightingRunner;
 };
 
 } // namespace CppTools
 
-#endif // CPPTOOLS_CPPHIGHLIGHTINGSUPPORT_H
+#endif // SEMANTICHIGHLIGHTER_H
diff --git a/src/plugins/designer/gotoslot_test.cpp b/src/plugins/designer/gotoslot_test.cpp
index def152e985793fd6ff635572b7bbdc24224c9f25..7814af028d3e02fcf833cf50e89cc65bef59c43f 100644
--- a/src/plugins/designer/gotoslot_test.cpp
+++ b/src/plugins/designer/gotoslot_test.cpp
@@ -33,9 +33,10 @@
 
 #include <coreplugin/editormanager/editormanager.h>
 #include <coreplugin/testdatadir.h>
+#include <cpptools/builtineditordocumentprocessor.h>
 #include <cpptools/cppmodelmanager.h>
-#include <cpptools/cpptoolseditorsupport.h>
 #include <cpptools/cpptoolstestcase.h>
+#include <cpptools/editordocumenthandle.h>
 
 #include <cplusplus/CppDocument.h>
 #include <cplusplus/Overview.h>
@@ -163,8 +164,6 @@ public:
             closeEditorAtEndOfTestCase(editor);
             editors << e;
         }
-        TextEditor::BaseTextEditor *cppFileEditor = editors.at(0);
-        TextEditor::BaseTextEditor *hFileEditor = editors.at(1);
 
         const QString cppFile = files.at(0);
         const QString hFile = files.at(1);
@@ -184,18 +183,22 @@ public:
 
         // Wait for updated documents
         foreach (TextEditor::BaseTextEditor *editor, editors) {
-            if (CppEditorSupport *editorSupport = m_modelManager->cppEditorSupport(editor)) {
-                while (editorSupport->isUpdatingDocument())
+            const QString filePath = editor->document()->filePath();
+            if (auto parser = BuiltinEditorDocumentParser::get(filePath)) {
+                forever {
+                    if (Document::Ptr document = parser->document()) {
+                        if (document->editorRevision() == 2)
+                            break;
+                    }
                     QApplication::processEvents();
+                }
             }
         }
 
         // Compare
-        const Document::Ptr cppDocument
-            = m_modelManager->cppEditorSupport(cppFileEditor)->documentParser()->document();
+        const Document::Ptr cppDocument = BuiltinEditorDocumentParser::get(cppFile)->document();
         QVERIFY(checkDiagsnosticMessages(cppDocument));
-        const Document::Ptr hDocument
-            = m_modelManager->cppEditorSupport(hFileEditor)->documentParser()->document();
+        const Document::Ptr hDocument = BuiltinEditorDocumentParser::get(hFile)->document();
         QVERIFY(checkDiagsnosticMessages(hDocument));
 
         QVERIFY(documentContainsFunctionDefinition(cppDocument,
diff --git a/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp b/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp
index 07cd07eb42e8d67ce918cc3c7296e4ae0eb392e9..13799083b4b810879c2e6471752a4dcc5756a1e8 100644
--- a/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp
+++ b/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp
@@ -34,7 +34,6 @@
 
 #include <cpptools/cppchecksymbols.h>
 #include <cpptools/cppsemanticinfo.h>
-#include <cpptools/cpphighlightingsupport.h>
 #include <texteditor/semantichighlighter.h>
 #include <utils/fileutils.h>
 
@@ -50,7 +49,7 @@
 typedef QByteArray _;
 typedef CppTools::CheckSymbols::Result Use;
 typedef CppTools::CheckSymbols::Kind UseKind;
-typedef CppTools::CppHighlightingSupport Highlighting;
+typedef CppTools::SemanticHighlighter Highlighting;
 typedef QList<Use> UseList;
 Q_DECLARE_METATYPE(UseList)
 
@@ -62,25 +61,25 @@ static QString useKindToString(UseKind useKind)
 {
     switch (useKind) {
     case Highlighting::Unknown:
-        return QLatin1String("CppHighlightingSupport::Unknown");
+        return QLatin1String("SemanticHighlighter::Unknown");
     case Highlighting::TypeUse:
-        return QLatin1String("CppHighlightingSupport::TypeUse");
+        return QLatin1String("SemanticHighlighter::TypeUse");
     case Highlighting::LocalUse:
-        return QLatin1String("CppHighlightingSupport::LocalUse");
+        return QLatin1String("SemanticHighlighter::LocalUse");
     case Highlighting::FieldUse:
-        return QLatin1String("CppHighlightingSupport::FieldUse");
+        return QLatin1String("SemanticHighlighter::FieldUse");
     case Highlighting::EnumerationUse:
-        return QLatin1String("CppHighlightingSupport::EnumerationUse");
+        return QLatin1String("SemanticHighlighter::EnumerationUse");
     case Highlighting::VirtualMethodUse:
-        return QLatin1String("CppHighlightingSupport::VirtualMethodUse");
+        return QLatin1String("SemanticHighlighter::VirtualMethodUse");
     case Highlighting::LabelUse:
-        return QLatin1String("CppHighlightingSupport::LabelUse");
+        return QLatin1String("SemanticHighlighter::LabelUse");
     case Highlighting::MacroUse:
-        return QLatin1String("CppHighlightingSupport::MacroUse");
+        return QLatin1String("SemanticHighlighter::MacroUse");
     case Highlighting::FunctionUse:
-        return QLatin1String("CppHighlightingSupport::FunctionUse");
+        return QLatin1String("SemanticHighlighter::FunctionUse");
     case Highlighting::PseudoKeywordUse:
-        return QLatin1String("CppHighlightingSupport::PseudoKeywordUse");
+        return QLatin1String("SemanticHighlighter::PseudoKeywordUse");
     default:
         QTest::qFail("Unknown UseKind", __FILE__, __LINE__);
         return QLatin1String("Unknown UseKind");
@@ -1608,13 +1607,13 @@ void tst_CheckSymbols::test_checksymbols_data()
                  "    Foo foo;\n"
                  "}\n")
             << (QList<Use>()
-                << Use(3, 15, 2, CppHighlightingSupport::TypeUse)
-                << Use(3, 27, 3, CppHighlightingSupport::TypeUse)
-                << Use(4, 11, 2, CppHighlightingSupport::TypeUse)
-                << Use(4, 15, 3, CppHighlightingSupport::TypeUse)
-                << Use(6, 6, 3, CppHighlightingSupport::FunctionUse)
-                << Use(8, 5, 3, CppHighlightingSupport::TypeUse)
-                << Use(8, 9, 3, CppHighlightingSupport::LocalUse)
+                << Use(3, 15, 2, Highlighting::TypeUse)
+                << Use(3, 27, 3, Highlighting::TypeUse)
+                << Use(4, 11, 2, Highlighting::TypeUse)
+                << Use(4, 15, 3, Highlighting::TypeUse)
+                << Use(6, 6, 3, Highlighting::FunctionUse)
+                << Use(8, 5, 3, Highlighting::TypeUse)
+                << Use(8, 9, 3, Highlighting::LocalUse)
                 );
 
     QTest::newRow("using_inside_different_block_of_scope_named_namespace_QTCREATORBUG12357")
@@ -1632,14 +1631,14 @@ void tst_CheckSymbols::test_checksymbols_data()
                  "}\n"
                  )
             << (QList<Use>()
-                << Use(1, 11, 3, CppHighlightingSupport::TypeUse)
-                << Use(3, 15, 2, CppHighlightingSupport::TypeUse)
-                << Use(3, 27, 3, CppHighlightingSupport::TypeUse)
-                << Use(4, 11, 2, CppHighlightingSupport::TypeUse)
-                << Use(4, 15, 3, CppHighlightingSupport::TypeUse)
-                << Use(6, 11, 3, CppHighlightingSupport::TypeUse)
-                << Use(8, 10, 3, CppHighlightingSupport::FunctionUse)
-                << Use(10, 13, 3, CppHighlightingSupport::LocalUse)
+                << Use(1, 11, 3, Highlighting::TypeUse)
+                << Use(3, 15, 2, Highlighting::TypeUse)
+                << Use(3, 27, 3, Highlighting::TypeUse)
+                << Use(4, 11, 2, Highlighting::TypeUse)
+                << Use(4, 15, 3, Highlighting::TypeUse)
+                << Use(6, 11, 3, Highlighting::TypeUse)
+                << Use(8, 10, 3, Highlighting::FunctionUse)
+                << Use(10, 13, 3, Highlighting::LocalUse)
                 );
 
     QTest::newRow("using_inside_different_namespace_QTCREATORBUG7978")
@@ -1660,13 +1659,13 @@ void tst_CheckSymbols::test_checksymbols_data()
              "void f(My" TEST_UNICODE_IDENTIFIER "Type var" TEST_UNICODE_IDENTIFIER ")\n"
              "{ var" TEST_UNICODE_IDENTIFIER "." TEST_UNICODE_IDENTIFIER "Member = 0; }\n")
         << (UseList()
-            << Use(1, 7, 10, CppHighlightingSupport::TypeUse)
-            << Use(1, 24, 10, CppHighlightingSupport::FieldUse)
-            << Use(2, 6, 1, CppHighlightingSupport::FunctionUse)
-            << Use(2, 8, 10, CppHighlightingSupport::TypeUse)
-            << Use(2, 19, 7, CppHighlightingSupport::LocalUse)
-            << Use(3, 3, 7, CppHighlightingSupport::LocalUse)
-            << Use(3, 11, 10, CppHighlightingSupport::FieldUse));
+            << Use(1, 7, 10, Highlighting::TypeUse)
+            << Use(1, 24, 10, Highlighting::FieldUse)
+            << Use(2, 6, 1, Highlighting::FunctionUse)
+            << Use(2, 8, 10, Highlighting::TypeUse)
+            << Use(2, 19, 7, Highlighting::LocalUse)
+            << Use(3, 3, 7, Highlighting::LocalUse)
+            << Use(3, 11, 10, Highlighting::FieldUse));
 
     QTest::newRow("unicodeIdentifier2")
         << _("class v" TEST_UNICODE_IDENTIFIER "\n"
@@ -1702,10 +1701,10 @@ void tst_CheckSymbols::test_checksymbols_data()
                  "Foo *x;\n"
              "};\n")
         << (UseList()
-            << Use(6, 7, 3, CppHighlightingSupport::TypeUse)
-            << Use(7, 8, 1, CppHighlightingSupport::FunctionUse)
-            << Use(8, 1, 3, CppHighlightingSupport::TypeUse)
-            << Use(8, 6, 1, CppHighlightingSupport::FieldUse));
+            << Use(6, 7, 3, Highlighting::TypeUse)
+            << Use(7, 8, 1, Highlighting::FunctionUse)
+            << Use(8, 1, 3, Highlighting::TypeUse)
+            << Use(8, 6, 1, Highlighting::FieldUse));
 #undef UC_U10302_12TIMES
 #undef UC_U10302_4TIMES
 }