summaryrefslogtreecommitdiff
path: root/src/plugins/cpptools/builtineditordocumentprocessor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/cpptools/builtineditordocumentprocessor.cpp')
-rw-r--r--src/plugins/cpptools/builtineditordocumentprocessor.cpp253
1 files changed, 253 insertions, 0 deletions
diff --git a/src/plugins/cpptools/builtineditordocumentprocessor.cpp b/src/plugins/cpptools/builtineditordocumentprocessor.cpp
new file mode 100644
index 0000000000..cd50c86609
--- /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