forked from qt-creator/qt-creator
Clang: Integrate highlighting results from backend
Change-Id: I2c3fb69aabfe075bde76d63eafc2ca370f17493c Reviewed-by: Marco Bubke <marco.bubke@theqtcompany.com>
This commit is contained in:
committed by
Nikolai Kosjar
parent
eb2457869d
commit
7ce9ef9db4
@@ -48,6 +48,7 @@
|
||||
#include <texteditor/texteditor.h>
|
||||
|
||||
#include <clangbackendipc/diagnosticschangedmessage.h>
|
||||
#include <clangbackendipc/highlightingchangedmessage.h>
|
||||
|
||||
#include <utils/hostosinfo.h>
|
||||
#include <utils/qtcassert.h>
|
||||
@@ -62,6 +63,7 @@
|
||||
#include <clangbackendipc/cmbmessages.h>
|
||||
#include <clangbackendipc/registerunsavedfilesforeditormessage.h>
|
||||
#include <clangbackendipc/requestdiagnosticsmessage.h>
|
||||
#include <clangbackendipc/requesthighlightingmessage.h>
|
||||
#include <clangbackendipc/filecontainer.h>
|
||||
#include <clangbackendipc/projectpartsdonotexistmessage.h>
|
||||
#include <clangbackendipc/translationunitdoesnotexistmessage.h>
|
||||
@@ -174,6 +176,24 @@ void IpcReceiver::diagnosticsChanged(const DiagnosticsChangedMessage &message)
|
||||
}
|
||||
}
|
||||
|
||||
void IpcReceiver::highlightingChanged(const HighlightingChangedMessage &message)
|
||||
{
|
||||
qCDebug(log) << "<<< HighlightingChangedMessage with"
|
||||
<< message.highlightingMarks().size() << "items";
|
||||
|
||||
auto processor = ClangEditorDocumentProcessor::get(message.file().filePath());
|
||||
|
||||
if (processor && processor->projectPart()) {
|
||||
const QString highlightingProjectPartId = message.file().projectPartId();
|
||||
const QString documentProjectPartId = processor->projectPart()->id();
|
||||
if (highlightingProjectPartId == documentProjectPartId) {
|
||||
processor->updateHighlighting(message.highlightingMarks(),
|
||||
message.skippedPreprocessorRanges(),
|
||||
message.file().documentRevision());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IpcReceiver::translationUnitDoesNotExist(const TranslationUnitDoesNotExistMessage &message)
|
||||
{
|
||||
QTC_CHECK(!"Got TranslationUnitDoesNotExistMessage");
|
||||
@@ -203,6 +223,7 @@ public:
|
||||
void unregisterUnsavedFilesForEditor(const ClangBackEnd::UnregisterUnsavedFilesForEditorMessage &message) override;
|
||||
void completeCode(const ClangBackEnd::CompleteCodeMessage &message) override;
|
||||
void requestDiagnostics(const ClangBackEnd::RequestDiagnosticsMessage &message) override;
|
||||
void requestHighlighting(const ClangBackEnd::RequestHighlightingMessage &message) override;
|
||||
|
||||
private:
|
||||
ClangBackEnd::ConnectionClient &m_connection;
|
||||
@@ -268,6 +289,12 @@ void IpcSender::requestDiagnostics(const RequestDiagnosticsMessage &message)
|
||||
m_connection.serverProxy().requestDiagnostics(message);
|
||||
}
|
||||
|
||||
void IpcSender::requestHighlighting(const RequestHighlightingMessage &message)
|
||||
{
|
||||
QTC_CHECK(m_connection.isConnected());
|
||||
m_connection.serverProxy().requestHighlighting(message);
|
||||
}
|
||||
|
||||
IpcCommunicator::IpcCommunicator()
|
||||
: m_connection(&m_ipcReceiver)
|
||||
, m_ipcSender(new IpcSender(m_connection))
|
||||
@@ -446,33 +473,50 @@ void IpcCommunicator::updateUnsavedFile(const QString &filePath, const QByteArra
|
||||
documentRevision}});
|
||||
}
|
||||
|
||||
void IpcCommunicator::requestDiagnostics(const FileContainer &fileContainer)
|
||||
void IpcCommunicator::requestDiagnosticsAndHighlighting(const FileContainer &fileContainer,
|
||||
DocumentChangedCheck documentChangedCheck)
|
||||
{
|
||||
if (m_sendMode == IgnoreSendRequests)
|
||||
return;
|
||||
|
||||
if (documentHasChanged(fileContainer.filePath())) {
|
||||
updateTranslationUnitsForEditor({fileContainer});
|
||||
|
||||
const RequestDiagnosticsMessage message(fileContainer);
|
||||
qCDebug(log) << ">>>" << message;
|
||||
m_ipcSender->requestDiagnostics(message);
|
||||
|
||||
setLastSentDocumentRevision(fileContainer.filePath(),
|
||||
fileContainer.documentRevision());
|
||||
if (documentChangedCheck == DocumentChangedCheck::RevisionCheck) {
|
||||
if (documentHasChanged(fileContainer.filePath())) {
|
||||
updateTranslationUnitsForEditor({fileContainer});
|
||||
requestDiagnostics(fileContainer);
|
||||
requestHighlighting(fileContainer);
|
||||
setLastSentDocumentRevision(fileContainer.filePath(),
|
||||
fileContainer.documentRevision());
|
||||
}
|
||||
} else {
|
||||
requestDiagnostics(fileContainer);
|
||||
requestHighlighting(fileContainer);
|
||||
}
|
||||
}
|
||||
|
||||
void IpcCommunicator::requestDiagnostics(Core::IDocument *document)
|
||||
void IpcCommunicator::requestDiagnostics(const FileContainer &fileContainer)
|
||||
{
|
||||
const RequestDiagnosticsMessage message(fileContainer);
|
||||
qCDebug(log) << ">>>" << message;
|
||||
m_ipcSender->requestDiagnostics(message);
|
||||
}
|
||||
|
||||
void IpcCommunicator::requestHighlighting(const FileContainer &fileContainer)
|
||||
{
|
||||
const RequestHighlightingMessage message(fileContainer);
|
||||
qCDebug(log) << ">>>" << message;
|
||||
m_ipcSender->requestHighlighting(message);
|
||||
}
|
||||
|
||||
void IpcCommunicator::requestDiagnosticsAndHighlighting(Core::IDocument *document)
|
||||
{
|
||||
const auto textDocument = qobject_cast<TextDocument*>(document);
|
||||
const auto filePath = textDocument->filePath().toString();
|
||||
const QString projectPartId = Utils::projectPartIdForFile(filePath);
|
||||
|
||||
requestDiagnostics(FileContainer(filePath,
|
||||
projectPartId,
|
||||
Utf8StringVector(),
|
||||
textDocument->document()->revision()));
|
||||
requestDiagnosticsAndHighlighting(FileContainer(filePath,
|
||||
projectPartId,
|
||||
Utf8StringVector(),
|
||||
textDocument->document()->revision()));
|
||||
}
|
||||
|
||||
void IpcCommunicator::updateChangeContentStartPosition(const QString &filePath, int position)
|
||||
|
||||
@@ -81,6 +81,7 @@ private:
|
||||
void echo(const ClangBackEnd::EchoMessage &message) override;
|
||||
void codeCompleted(const ClangBackEnd::CodeCompletedMessage &message) override;
|
||||
void diagnosticsChanged(const ClangBackEnd::DiagnosticsChangedMessage &message) override;
|
||||
void highlightingChanged(const ClangBackEnd::HighlightingChangedMessage &message) override;
|
||||
|
||||
void translationUnitDoesNotExist(const ClangBackEnd::TranslationUnitDoesNotExistMessage &message) override;
|
||||
void projectPartsDoNotExist(const ClangBackEnd::ProjectPartsDoNotExistMessage &message) override;
|
||||
@@ -105,6 +106,7 @@ public:
|
||||
virtual void unregisterUnsavedFilesForEditor(const ClangBackEnd::UnregisterUnsavedFilesForEditorMessage &message) = 0;
|
||||
virtual void completeCode(const ClangBackEnd::CompleteCodeMessage &message) = 0;
|
||||
virtual void requestDiagnostics(const ClangBackEnd::RequestDiagnosticsMessage &message) = 0;
|
||||
virtual void requestHighlighting(const ClangBackEnd::RequestHighlightingMessage &message) = 0;
|
||||
};
|
||||
|
||||
class IpcCommunicator : public QObject
|
||||
@@ -116,6 +118,8 @@ public:
|
||||
using FileContainers = QVector<ClangBackEnd::FileContainer>;
|
||||
using ProjectPartContainers = QVector<ClangBackEnd::ProjectPartContainer>;
|
||||
|
||||
enum class DocumentChangedCheck { NoCheck, RevisionCheck };
|
||||
|
||||
public:
|
||||
IpcCommunicator();
|
||||
|
||||
@@ -140,8 +144,9 @@ public:
|
||||
void updateUnsavedFileFromCppEditorDocument(const QString &filePath);
|
||||
void updateTranslationUnit(const QString &filePath, const QByteArray &contents, uint documentRevision);
|
||||
void updateUnsavedFile(const QString &filePath, const QByteArray &contents, uint documentRevision);
|
||||
void requestDiagnostics(const ClangBackEnd::FileContainer &fileContainer);
|
||||
void requestDiagnostics(Core::IDocument *document);
|
||||
void requestDiagnosticsAndHighlighting(const ClangBackEnd::FileContainer &fileContainer,
|
||||
DocumentChangedCheck documentChangedCheck = DocumentChangedCheck::RevisionCheck);
|
||||
void requestDiagnosticsAndHighlighting(Core::IDocument *document);
|
||||
void updateChangeContentStartPosition(const QString &filePath, int position);
|
||||
|
||||
void registerFallbackProjectPart();
|
||||
@@ -162,6 +167,9 @@ private:
|
||||
void registerCurrentCppEditorDocuments();
|
||||
void registerCurrentCodeModelUiHeaders();
|
||||
|
||||
void requestHighlighting(const ClangBackEnd::FileContainer &fileContainer);
|
||||
void requestDiagnostics(const ClangBackEnd::FileContainer &fileContainer);
|
||||
|
||||
void onBackendRestarted();
|
||||
void onEditorAboutToClose(Core::IEditor *editor);
|
||||
void onCoreAboutToClose();
|
||||
|
||||
@@ -41,6 +41,7 @@ SOURCES += \
|
||||
cxprettyprinter.cpp \
|
||||
diagnostic.cpp \
|
||||
fastindexer.cpp \
|
||||
highlightingmarksreporter.cpp \
|
||||
pchinfo.cpp \
|
||||
pchmanager.cpp \
|
||||
raii/scopedclangoptions.cpp \
|
||||
@@ -86,6 +87,7 @@ HEADERS += \
|
||||
cxraii.h \
|
||||
diagnostic.h \
|
||||
fastindexer.h \
|
||||
highlightingmarksreporter.h \
|
||||
pchinfo.h \
|
||||
pchmanager.h \
|
||||
raii/scopedclangoptions.h \
|
||||
|
||||
@@ -81,6 +81,8 @@ QtcPlugin {
|
||||
files: [
|
||||
"cppcreatemarkers.cpp",
|
||||
"cppcreatemarkers.h",
|
||||
"highlightingmarksreporter.cpp",
|
||||
"highlightingmarksreporter.h",
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -58,11 +58,6 @@ static void initializeTextMarks()
|
||||
Utils::Theme::ClangCodeModel_Error_TextMarkColor);
|
||||
}
|
||||
|
||||
ClangCodeModelPlugin::ClangCodeModelPlugin()
|
||||
{
|
||||
qRegisterMetaType<CppTools::ProjectPart::Ptr>();
|
||||
}
|
||||
|
||||
bool ClangCodeModelPlugin::initialize(const QStringList &arguments, QString *errorMessage)
|
||||
{
|
||||
Q_UNUSED(arguments)
|
||||
|
||||
@@ -50,8 +50,6 @@ class ClangCodeModelPlugin: public ExtensionSystem::IPlugin
|
||||
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "ClangCodeModel.json")
|
||||
|
||||
public:
|
||||
ClangCodeModelPlugin();
|
||||
|
||||
bool initialize(const QStringList &arguments, QString *errorMessage);
|
||||
void extensionsInitialized();
|
||||
|
||||
|
||||
@@ -5,11 +5,13 @@ SOURCES += $$PWD/completionchunkstotextconverter.cpp \
|
||||
$$PWD/activationsequencecontextprocessor.cpp \
|
||||
$$PWD/clangcompletioncontextanalyzer.cpp \
|
||||
$$PWD/clangdiagnosticfilter.cpp \
|
||||
$$PWD/clangfixitoperation.cpp
|
||||
$$PWD/clangfixitoperation.cpp \
|
||||
$$PWD/highlightingmarksreporter.cpp
|
||||
|
||||
HEADERS += $$PWD/completionchunkstotextconverter.h \
|
||||
$$PWD/activationsequenceprocessor.h \
|
||||
$$PWD/activationsequencecontextprocessor.h \
|
||||
$$PWD/clangcompletioncontextanalyzer.h \
|
||||
$$PWD/clangdiagnosticfilter.h \
|
||||
$$PWD/clangfixitoperation.h
|
||||
$$PWD/clangfixitoperation.h \
|
||||
$$PWD/highlightingmarksreporter.h
|
||||
|
||||
@@ -29,111 +29,22 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "clangeditordocumentparser.h"
|
||||
#include "clangutils.h"
|
||||
#include "pchinfo.h"
|
||||
#include "pchmanager.h"
|
||||
|
||||
#include <cpptools/cppmodelmanager.h>
|
||||
#include <cpptools/cppprojects.h>
|
||||
#include <cpptools/cppworkingcopy.h>
|
||||
|
||||
#include <utils/hostosinfo.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QLoggingCategory>
|
||||
|
||||
static Q_LOGGING_CATEGORY(log, "qtc.clangcodemodel.clangeditordocumentparser")
|
||||
|
||||
namespace {
|
||||
|
||||
QStringList createOptions(const QString &filePath,
|
||||
const CppTools::ProjectPart::Ptr &part,
|
||||
bool includeSpellCheck = false)
|
||||
{
|
||||
using namespace ClangCodeModel;
|
||||
|
||||
QStringList options;
|
||||
if (part.isNull())
|
||||
return options;
|
||||
|
||||
if (includeSpellCheck)
|
||||
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 messageLine(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)
|
||||
{
|
||||
BaseEditorDocumentParser::Configuration config = configuration();
|
||||
config.stickToPreviousProjectPart = false;
|
||||
setConfiguration(config);
|
||||
}
|
||||
|
||||
void ClangEditorDocumentParser::updateHelper(const BaseEditorDocumentParser::InMemoryInfo &info)
|
||||
void ClangEditorDocumentParser::updateHelper(const BaseEditorDocumentParser::InMemoryInfo &)
|
||||
{
|
||||
QTC_ASSERT(m_marker, return);
|
||||
|
||||
// Determine project part
|
||||
State state_ = state();
|
||||
state_.projectPart = determineProjectPart(filePath(), configuration(), state_);
|
||||
setState(state_);
|
||||
emit projectPartDetermined(state_.projectPart);
|
||||
|
||||
// Determine message line arguments
|
||||
const QStringList options = createOptions(filePath(), state_.projectPart, true);
|
||||
qCDebug(log, "Reparse options (cmd line equivalent): %s",
|
||||
messageLine(options, filePath()).toUtf8().constData());
|
||||
|
||||
// Run
|
||||
QTime t; t.start();
|
||||
QMutexLocker lock(m_marker->mutex());
|
||||
m_marker->setFileName(filePath());
|
||||
m_marker->setCompilationOptions(options);
|
||||
const Internal::UnsavedFiles unsavedFiles = Utils::createUnsavedFiles(info.workingCopy,
|
||||
info.modifiedFiles);
|
||||
m_marker->reparse(unsavedFiles);
|
||||
qCDebug(log) << "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
|
||||
|
||||
@@ -31,12 +31,8 @@
|
||||
#ifndef CLANGEDITORDOCUMENTPARSER_H
|
||||
#define CLANGEDITORDOCUMENTPARSER_H
|
||||
|
||||
#include "semanticmarker.h"
|
||||
|
||||
#include <cpptools/baseeditordocumentparser.h>
|
||||
|
||||
namespace CppTools { class WorkingCopy; }
|
||||
|
||||
namespace ClangCodeModel {
|
||||
|
||||
class ClangEditorDocumentParser : public CppTools::BaseEditorDocumentParser
|
||||
@@ -46,17 +42,8 @@ class ClangEditorDocumentParser : public CppTools::BaseEditorDocumentParser
|
||||
public:
|
||||
ClangEditorDocumentParser(const QString &filePath);
|
||||
|
||||
QList<Diagnostic> diagnostics() const;
|
||||
QList<SemanticMarker::Range> ifdefedOutBlocks() const;
|
||||
SemanticMarker::Ptr semanticMarker() const;
|
||||
|
||||
signals:
|
||||
void projectPartDetermined(CppTools::ProjectPart::Ptr projectPart);
|
||||
|
||||
private:
|
||||
void updateHelper(const BaseEditorDocumentParser::InMemoryInfo &info) override;
|
||||
|
||||
SemanticMarker::Ptr m_marker;
|
||||
void updateHelper(const BaseEditorDocumentParser::InMemoryInfo &) override;
|
||||
};
|
||||
|
||||
} // namespace ClangCodeModel
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "clangutils.h"
|
||||
#include "cppcreatemarkers.h"
|
||||
#include "diagnostic.h"
|
||||
#include "highlightingmarksreporter.h"
|
||||
#include "pchinfo.h"
|
||||
|
||||
#include <diagnosticcontainer.h>
|
||||
@@ -59,22 +60,6 @@
|
||||
|
||||
#include <QTextBlock>
|
||||
|
||||
namespace {
|
||||
|
||||
typedef CPlusPlus::Document::DiagnosticMessage CppToolsDiagnostic;
|
||||
|
||||
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 {
|
||||
namespace Internal {
|
||||
|
||||
@@ -89,26 +74,12 @@ ClangEditorDocumentProcessor::ClangEditorDocumentProcessor(
|
||||
, m_semanticHighlighter(document)
|
||||
, m_builtinProcessor(document, /*enableSemanticHighlighter=*/ false)
|
||||
{
|
||||
connect(m_parser.data(), &ClangEditorDocumentParser::projectPartDetermined,
|
||||
this, &ClangEditorDocumentProcessor::onParserDeterminedProjectPart);
|
||||
|
||||
// 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().toString(),
|
||||
firstLine, lastLine);
|
||||
return createMarkers->start();
|
||||
});
|
||||
}
|
||||
|
||||
ClangEditorDocumentProcessor::~ClangEditorDocumentProcessor()
|
||||
@@ -125,7 +96,7 @@ ClangEditorDocumentProcessor::~ClangEditorDocumentProcessor()
|
||||
|
||||
void ClangEditorDocumentProcessor::run()
|
||||
{
|
||||
requestDiagnostics();
|
||||
requestDiagnosticsAndHighlighting();
|
||||
|
||||
// Run clang parser
|
||||
disconnect(&m_parserWatcher, &QFutureWatcher<void>::finished,
|
||||
@@ -153,7 +124,7 @@ void ClangEditorDocumentProcessor::recalculateSemanticInfoDetached(bool force)
|
||||
void ClangEditorDocumentProcessor::semanticRehighlight()
|
||||
{
|
||||
m_semanticHighlighter.updateFormatMapFromFontSettings();
|
||||
m_semanticHighlighter.run();
|
||||
requestDiagnosticsAndHighlighting(DocumentChangedCheck::NoCheck);
|
||||
}
|
||||
|
||||
CppTools::SemanticInfo ClangEditorDocumentProcessor::recalculateSemanticInfo()
|
||||
@@ -201,6 +172,36 @@ void ClangEditorDocumentProcessor::updateCodeWarnings(const QVector<ClangBackEnd
|
||||
}
|
||||
}
|
||||
|
||||
static QList<TextEditor::BlockRange>
|
||||
toTextEditorBlocks(const QVector<ClangBackEnd::SourceRangeContainer> &ifdefedOutRanges)
|
||||
{
|
||||
QList<TextEditor::BlockRange> blockRanges;
|
||||
blockRanges.reserve(ifdefedOutRanges.size());
|
||||
|
||||
for (const auto &range : ifdefedOutRanges)
|
||||
blockRanges.append(TextEditor::BlockRange(range.start().offset(),range.end().offset()));
|
||||
|
||||
return blockRanges;
|
||||
}
|
||||
|
||||
void ClangEditorDocumentProcessor::updateHighlighting(
|
||||
const QVector<ClangBackEnd::HighlightingMarkContainer> &highlightingMarks,
|
||||
const QVector<ClangBackEnd::SourceRangeContainer> &skippedPreprocessorRanges,
|
||||
uint documentRevision)
|
||||
{
|
||||
if (documentRevision == revision()) {
|
||||
const auto skippedPreprocessorBlocks = toTextEditorBlocks(skippedPreprocessorRanges);
|
||||
emit ifdefedOutBlocksUpdated(documentRevision, skippedPreprocessorBlocks);
|
||||
|
||||
m_semanticHighlighter.setHighlightingRunner(
|
||||
[highlightingMarks]() {
|
||||
auto *reporter = new HighlightingMarksReporter(highlightingMarks);
|
||||
return reporter->start();
|
||||
});
|
||||
m_semanticHighlighter.run();
|
||||
}
|
||||
}
|
||||
|
||||
static int currentLine(const TextEditor::AssistInterface &assistInterface)
|
||||
{
|
||||
int line, column;
|
||||
@@ -240,36 +241,24 @@ static bool isProjectPartLoadedOrIsFallback(CppTools::ProjectPart::Ptr projectPa
|
||||
&& (projectPart->id().isEmpty() || ClangCodeModel::Utils::isProjectPartLoaded(projectPart));
|
||||
}
|
||||
|
||||
void ClangEditorDocumentProcessor::updateProjectPartAndTranslationUnitForEditor(
|
||||
CppTools::ProjectPart::Ptr projectPart)
|
||||
void ClangEditorDocumentProcessor::updateProjectPartAndTranslationUnitForEditor()
|
||||
{
|
||||
QTC_ASSERT(projectPart, return);
|
||||
const CppTools::ProjectPart::Ptr projectPart = m_parser->projectPart();
|
||||
|
||||
if (isProjectPartLoadedOrIsFallback(projectPart)) {
|
||||
updateTranslationUnitForEditor(projectPart.data());
|
||||
requestDiagnostics(projectPart.data());
|
||||
requestDiagnosticsAndHighlighting(projectPart.data());
|
||||
|
||||
m_projectPart = projectPart;
|
||||
}
|
||||
}
|
||||
|
||||
void ClangEditorDocumentProcessor::onParserDeterminedProjectPart(
|
||||
CppTools::ProjectPart::Ptr projectPart)
|
||||
{
|
||||
updateProjectPartAndTranslationUnitForEditor(projectPart);
|
||||
}
|
||||
|
||||
void ClangEditorDocumentProcessor::onParserFinished()
|
||||
{
|
||||
if (revision() != m_parserRevision)
|
||||
return;
|
||||
|
||||
// Emit ifdefed out blocks
|
||||
const auto ifdefoutBlocks = toTextEditorBlocks(m_parser->ifdefedOutBlocks());
|
||||
emit ifdefedOutBlocksUpdated(revision(), ifdefoutBlocks);
|
||||
|
||||
// Run semantic highlighter
|
||||
m_semanticHighlighter.run();
|
||||
updateProjectPartAndTranslationUnitForEditor();
|
||||
}
|
||||
|
||||
void ClangEditorDocumentProcessor::updateTranslationUnitForEditor(CppTools::ProjectPart *projectPart)
|
||||
@@ -287,25 +276,38 @@ void ClangEditorDocumentProcessor::updateTranslationUnitForEditor(CppTools::Proj
|
||||
}
|
||||
}
|
||||
|
||||
void ClangEditorDocumentProcessor::requestDiagnostics(CppTools::ProjectPart *projectPart)
|
||||
void ClangEditorDocumentProcessor::requestDiagnosticsAndHighlighting(CppTools::ProjectPart *projectPart)
|
||||
{
|
||||
if (!m_projectPart || projectPart->id() != m_projectPart->id()) {
|
||||
IpcCommunicator &ipcCommunicator = m_modelManagerSupport->ipcCommunicator();
|
||||
|
||||
ipcCommunicator.requestDiagnostics({fileContainer(projectPart)});
|
||||
const ClangBackEnd::FileContainer fileContainer_ = fileContainer(projectPart);
|
||||
ipcCommunicator.requestDiagnosticsAndHighlighting(fileContainer_);
|
||||
}
|
||||
}
|
||||
|
||||
void ClangEditorDocumentProcessor::requestDiagnostics()
|
||||
IpcCommunicator::DocumentChangedCheck
|
||||
toIpcCommunicatorDocumentChangedCheck(ClangEditorDocumentProcessor::DocumentChangedCheck condition)
|
||||
{
|
||||
return condition == ClangEditorDocumentProcessor::DocumentChangedCheck::RevisionCheck
|
||||
? IpcCommunicator::DocumentChangedCheck::RevisionCheck
|
||||
: IpcCommunicator::DocumentChangedCheck::NoCheck;
|
||||
}
|
||||
|
||||
void ClangEditorDocumentProcessor::requestDiagnosticsAndHighlighting(DocumentChangedCheck documentChangedCheck)
|
||||
{
|
||||
// Get diagnostics
|
||||
if (m_projectPart) {
|
||||
auto &ipcCommunicator = m_modelManagerSupport->ipcCommunicator();
|
||||
ipcCommunicator.requestDiagnostics({filePath(),
|
||||
m_projectPart->id(),
|
||||
baseTextDocument()->plainText(),
|
||||
true,
|
||||
revision()});
|
||||
|
||||
const ClangBackEnd::FileContainer fileContainer(filePath(),
|
||||
m_projectPart->id(),
|
||||
baseTextDocument()->plainText(),
|
||||
true,
|
||||
revision());
|
||||
|
||||
const auto documentCheck = toIpcCommunicatorDocumentChangedCheck(documentChangedCheck);
|
||||
|
||||
ipcCommunicator.requestDiagnosticsAndHighlighting(fileContainer, documentCheck);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
|
||||
namespace ClangBackEnd {
|
||||
class DiagnosticContainer;
|
||||
class HighlightingMarkContainer;
|
||||
class FileContainer;
|
||||
}
|
||||
|
||||
@@ -75,6 +76,9 @@ public:
|
||||
|
||||
void updateCodeWarnings(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
|
||||
uint documentRevision);
|
||||
void updateHighlighting(const QVector<ClangBackEnd::HighlightingMarkContainer> &highlightingMarks,
|
||||
const QVector<ClangBackEnd::SourceRangeContainer> &skippedPreprocessorRanges,
|
||||
uint documentRevision);
|
||||
|
||||
TextEditor::QuickFixOperations
|
||||
extraRefactoringOperations(const TextEditor::AssistInterface &assistInterface) override;
|
||||
@@ -84,17 +88,17 @@ public:
|
||||
void clearDiagnosticsWithFixIts();
|
||||
|
||||
public:
|
||||
enum class DocumentChangedCheck { NoCheck, RevisionCheck };
|
||||
static ClangEditorDocumentProcessor *get(const QString &filePath);
|
||||
|
||||
private slots:
|
||||
void onParserDeterminedProjectPart(CppTools::ProjectPart::Ptr projectPart);
|
||||
void onParserFinished();
|
||||
|
||||
private:
|
||||
void updateProjectPartAndTranslationUnitForEditor(CppTools::ProjectPart::Ptr projectPart);
|
||||
void updateProjectPartAndTranslationUnitForEditor();
|
||||
void updateTranslationUnitForEditor(CppTools::ProjectPart *projectPart);
|
||||
void requestDiagnostics(CppTools::ProjectPart *projectPart);
|
||||
void requestDiagnostics();
|
||||
void requestDiagnosticsAndHighlighting(CppTools::ProjectPart *projectPart);
|
||||
void requestDiagnosticsAndHighlighting(DocumentChangedCheck documentChangedCheck = DocumentChangedCheck::RevisionCheck);
|
||||
ClangBackEnd::FileContainer fileContainer(CppTools::ProjectPart *projectPart) const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -193,7 +193,7 @@ void ModelManagerSupportClang::onCppDocumentReloadFinishedOnTranslationUnit(bool
|
||||
if (success) {
|
||||
TextEditor::TextDocument *textDocument = qobject_cast<TextEditor::TextDocument *>(sender());
|
||||
connectToTextDocumentContentsChangedForTranslationUnit(textDocument);
|
||||
m_ipcCommunicator.requestDiagnostics(textDocument);
|
||||
m_ipcCommunicator.requestDiagnosticsAndHighlighting(textDocument);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
155
src/plugins/clangcodemodel/highlightingmarksreporter.cpp
Normal file
155
src/plugins/clangcodemodel/highlightingmarksreporter.cpp
Normal file
@@ -0,0 +1,155 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2015 The Qt Company Ltd.
|
||||
** Contact: http://www.qt.io/licensing
|
||||
**
|
||||
** 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 The Qt Company. For licensing terms and
|
||||
** conditions see http://www.qt.io/terms-conditions. For further information
|
||||
** use the contact form at http://www.qt.io/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 or version 3 as published by the Free
|
||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||
** following information to ensure the GNU Lesser General Public License
|
||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, The Qt Company gives you certain additional
|
||||
** rights. These rights are described in The Qt Company LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "highlightingmarksreporter.h"
|
||||
|
||||
#include <cpptools/semantichighlighter.h>
|
||||
|
||||
#include <QFuture>
|
||||
|
||||
namespace {
|
||||
|
||||
CppTools::SemanticHighlighter::Kind toCppToolsSemanticHighlighterKind(
|
||||
ClangBackEnd::HighlightingType type)
|
||||
{
|
||||
using ClangBackEnd::HighlightingType;
|
||||
using CppTools::SemanticHighlighter;
|
||||
|
||||
switch (type) {
|
||||
case HighlightingType::Keyword:
|
||||
return SemanticHighlighter::PseudoKeywordUse;
|
||||
case HighlightingType::Function:
|
||||
return SemanticHighlighter::FunctionUse;
|
||||
case HighlightingType::VirtualFunction:
|
||||
return SemanticHighlighter::VirtualMethodUse;
|
||||
case HighlightingType::Type:
|
||||
return SemanticHighlighter::TypeUse;
|
||||
case HighlightingType::LocalVariable:
|
||||
return SemanticHighlighter::LocalUse;
|
||||
case HighlightingType::Field:
|
||||
return SemanticHighlighter::FieldUse;
|
||||
case HighlightingType::GlobalVariable:
|
||||
return SemanticHighlighter::Unknown;
|
||||
case HighlightingType::Enumeration:
|
||||
return SemanticHighlighter::EnumerationUse;
|
||||
case HighlightingType::Label:
|
||||
return SemanticHighlighter::LabelUse;
|
||||
case HighlightingType::Preprocessor:
|
||||
return SemanticHighlighter::MacroUse;
|
||||
default:
|
||||
return SemanticHighlighter::Unknown;
|
||||
}
|
||||
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
|
||||
TextEditor::HighlightingResult toHighlightingResult(
|
||||
const ClangBackEnd::HighlightingMarkContainer &highlightingMark)
|
||||
{
|
||||
const auto highlighterKind = toCppToolsSemanticHighlighterKind(highlightingMark.type());
|
||||
|
||||
return TextEditor::HighlightingResult(highlightingMark.line(),
|
||||
highlightingMark.column(),
|
||||
highlightingMark.length(),
|
||||
highlighterKind);
|
||||
}
|
||||
|
||||
} // anonymous
|
||||
|
||||
namespace ClangCodeModel {
|
||||
|
||||
HighlightingMarksReporter::HighlightingMarksReporter(
|
||||
const QVector<ClangBackEnd::HighlightingMarkContainer> &highlightingMarks)
|
||||
: m_highlightingMarks(highlightingMarks)
|
||||
{
|
||||
m_chunksToReport.reserve(m_chunkSize + 1);
|
||||
}
|
||||
|
||||
void HighlightingMarksReporter::reportChunkWise(
|
||||
const TextEditor::HighlightingResult &highlightingResult)
|
||||
{
|
||||
if (m_chunksToReport.size() >= m_chunkSize) {
|
||||
if (m_flushRequested && highlightingResult.line != m_flushLine) {
|
||||
reportAndClearCurrentChunks();
|
||||
} else if (!m_flushRequested) {
|
||||
m_flushRequested = true;
|
||||
m_flushLine = highlightingResult.line;
|
||||
}
|
||||
}
|
||||
|
||||
m_chunksToReport.append(highlightingResult);
|
||||
}
|
||||
|
||||
void HighlightingMarksReporter::reportAndClearCurrentChunks()
|
||||
{
|
||||
m_flushRequested = false;
|
||||
m_flushLine = 0;
|
||||
|
||||
if (!m_chunksToReport.isEmpty()) {
|
||||
reportResults(m_chunksToReport);
|
||||
m_chunksToReport.erase(m_chunksToReport.begin(), m_chunksToReport.end());
|
||||
}
|
||||
}
|
||||
|
||||
void HighlightingMarksReporter::setChunkSize(int chunkSize)
|
||||
{
|
||||
m_chunkSize = chunkSize;
|
||||
}
|
||||
|
||||
void HighlightingMarksReporter::run()
|
||||
{
|
||||
run_internal();
|
||||
reportFinished();
|
||||
}
|
||||
|
||||
void HighlightingMarksReporter::run_internal()
|
||||
{
|
||||
if (isCanceled())
|
||||
return;
|
||||
|
||||
for (const auto &highlightingMark : m_highlightingMarks)
|
||||
reportChunkWise(toHighlightingResult(highlightingMark));
|
||||
|
||||
if (isCanceled())
|
||||
return;
|
||||
|
||||
reportAndClearCurrentChunks();
|
||||
}
|
||||
|
||||
QFuture<TextEditor::HighlightingResult> HighlightingMarksReporter::start()
|
||||
{
|
||||
this->setRunnable(this);
|
||||
this->reportStarted();
|
||||
QFuture<TextEditor::HighlightingResult> future = this->future();
|
||||
QThreadPool::globalInstance()->start(this, QThread::LowestPriority);
|
||||
return future;
|
||||
}
|
||||
|
||||
} // namespace ClangCodeModel
|
||||
80
src/plugins/clangcodemodel/highlightingmarksreporter.h
Normal file
80
src/plugins/clangcodemodel/highlightingmarksreporter.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2015 The Qt Company Ltd.
|
||||
** Contact: http://www.qt.io/licensing
|
||||
**
|
||||
** 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 The Qt Company. For licensing terms and
|
||||
** conditions see http://www.qt.io/terms-conditions. For further information
|
||||
** use the contact form at http://www.qt.io/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 or version 3 as published by the Free
|
||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||
** following information to ensure the GNU Lesser General Public License
|
||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, The Qt Company gives you certain additional
|
||||
** rights. These rights are described in The Qt Company LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CLANGCODEMODEL_HIGHLIGHTINGMARKSREPORTER_H
|
||||
#define CLANGCODEMODEL_HIGHLIGHTINGMARKSREPORTER_H
|
||||
|
||||
#include "clang_global.h"
|
||||
|
||||
#include <QFutureInterface>
|
||||
#include <QObject>
|
||||
#include <QRunnable>
|
||||
#include <QThreadPool>
|
||||
|
||||
#include <texteditor/semantichighlighter.h>
|
||||
|
||||
#include <clangbackendipc/highlightingmarkcontainer.h>
|
||||
|
||||
namespace ClangCodeModel {
|
||||
|
||||
class HighlightingMarksReporter:
|
||||
public QObject,
|
||||
public QRunnable,
|
||||
public QFutureInterface<TextEditor::HighlightingResult>
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
HighlightingMarksReporter(const QVector<ClangBackEnd::HighlightingMarkContainer> &highlightingMarks);
|
||||
|
||||
void setChunkSize(int chunkSize);
|
||||
|
||||
QFuture<TextEditor::HighlightingResult> start();
|
||||
|
||||
private:
|
||||
void run() override;
|
||||
void run_internal();
|
||||
|
||||
void reportChunkWise(const TextEditor::HighlightingResult &highlightingResult);
|
||||
void reportAndClearCurrentChunks();
|
||||
|
||||
private:
|
||||
QVector<ClangBackEnd::HighlightingMarkContainer> m_highlightingMarks;
|
||||
QVector<TextEditor::HighlightingResult> m_chunksToReport;
|
||||
|
||||
int m_chunkSize = 100;
|
||||
|
||||
bool m_flushRequested = false;
|
||||
unsigned m_flushLine = 0;
|
||||
};
|
||||
|
||||
} // namespace ClangCodeModel
|
||||
|
||||
#endif // CLANGCODEMODEL_HIGHLIGHTINGMARKSREPORTER_H
|
||||
@@ -380,6 +380,11 @@ QString toString(const RequestDiagnosticsMessage &)
|
||||
return QStringLiteral("RequestDiagnosticsMessage\n");
|
||||
}
|
||||
|
||||
QString toString(const RequestHighlightingMessage &)
|
||||
{
|
||||
return QStringLiteral("RequestHighlightingMessage\n");
|
||||
}
|
||||
|
||||
class IpcSenderSpy : public IpcSenderInterface
|
||||
{
|
||||
public:
|
||||
@@ -413,6 +418,8 @@ public:
|
||||
void requestDiagnostics(const RequestDiagnosticsMessage &message) override
|
||||
{ senderLog.append(toString(message)); }
|
||||
|
||||
void requestHighlighting(const RequestHighlightingMessage &message) override
|
||||
{ senderLog.append(toString(message)); }
|
||||
|
||||
public:
|
||||
QString senderLog;
|
||||
|
||||
Reference in New Issue
Block a user