forked from qt-creator/qt-creator
ClangTools: Utilize TaskTree to parse diagnostics from file
This reduces the time the main thread is blocked for reading the diagnostics from the result file. Change-Id: If6cc5671c709cb519b651c2b7ce3e8067e0b5f39 Reviewed-by: Jarek Kobus <jaroslaw.kobus@qt.io>
This commit is contained in:
@@ -242,26 +242,15 @@ void ClangToolRunWorker::onDone(const AnalyzeOutputData &output)
|
||||
|
||||
qCDebug(LOG) << "onRunnerFinishedWithSuccess:" << output.outputFilePath;
|
||||
|
||||
QString errorMessage;
|
||||
const Diagnostics diagnostics = m_tool->read(output.outputFilePath, m_projectFiles,
|
||||
&errorMessage);
|
||||
const Diagnostics diagnostics = output.diagnostics;
|
||||
|
||||
if (!errorMessage.isEmpty()) {
|
||||
m_filesAnalyzed.remove(output.fileToAnalyze);
|
||||
m_filesNotAnalyzed.insert(output.fileToAnalyze);
|
||||
qCDebug(LOG) << "onRunnerFinishedWithSuccess: Error reading log file:" << errorMessage;
|
||||
appendMessage(Tr::tr("Failed to analyze \"%1\": %2")
|
||||
.arg(output.fileToAnalyze.toUserOutput(), errorMessage),
|
||||
Utils::StdErrFormat);
|
||||
} else {
|
||||
if (!m_filesNotAnalyzed.contains(output.fileToAnalyze))
|
||||
m_filesAnalyzed.insert(output.fileToAnalyze);
|
||||
if (!diagnostics.isEmpty()) {
|
||||
// do not generate marks when we always analyze open files since marks from that
|
||||
// analysis should be more up to date
|
||||
const bool generateMarks = !m_runSettings.analyzeOpenFiles();
|
||||
m_tool->onNewDiagnosticsAvailable(diagnostics, generateMarks);
|
||||
}
|
||||
if (!m_filesNotAnalyzed.contains(output.fileToAnalyze))
|
||||
m_filesAnalyzed.insert(output.fileToAnalyze);
|
||||
if (!diagnostics.isEmpty()) {
|
||||
// do not generate marks when we always analyze open files since marks from that
|
||||
// analysis should be more up to date
|
||||
const bool generateMarks = !m_runSettings.analyzeOpenFiles();
|
||||
m_tool->onNewDiagnosticsAvailable(diagnostics, generateMarks);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "clangtoolrunner.h"
|
||||
|
||||
#include "clangtoolslogfilereader.h"
|
||||
#include "clangtoolstr.h"
|
||||
#include "clangtoolsutils.h"
|
||||
|
||||
@@ -11,6 +12,9 @@
|
||||
#include <cppeditor/clangdiagnosticconfigsmodel.h>
|
||||
#include <cppeditor/cpptoolsreuse.h>
|
||||
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
|
||||
#include <utils/async.h>
|
||||
#include <utils/process.h>
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/temporaryfile.h>
|
||||
@@ -20,6 +24,7 @@
|
||||
#include <QFileInfo>
|
||||
#include <QLoggingCategory>
|
||||
|
||||
|
||||
static Q_LOGGING_CATEGORY(LOG, "qtc.clangtools.runner", QtWarningMsg)
|
||||
|
||||
using namespace CppEditor;
|
||||
@@ -109,6 +114,7 @@ GroupItem clangToolTask(const AnalyzeInputData &input,
|
||||
QString name;
|
||||
FilePath executable;
|
||||
FilePath outputFilePath;
|
||||
QString errorMessage;
|
||||
};
|
||||
const TreeStorage<ClangToolStorage> storage;
|
||||
|
||||
@@ -160,9 +166,6 @@ GroupItem clangToolTask(const AnalyzeInputData &input,
|
||||
};
|
||||
const auto onProcessDone = [=](const Process &process) {
|
||||
qCDebug(LOG).noquote() << "Output:\n" << process.cleanedStdOut();
|
||||
if (!outputHandler)
|
||||
return;
|
||||
outputHandler({true, input.unit.file, storage->outputFilePath, input.tool});
|
||||
};
|
||||
const auto onProcessError = [=](const Process &process) {
|
||||
if (!outputHandler)
|
||||
@@ -179,15 +182,38 @@ GroupItem clangToolTask(const AnalyzeInputData &input,
|
||||
message = Tr::tr("%1 finished with exit code: %2.").arg(data.name).arg(process.exitCode());
|
||||
else
|
||||
message = Tr::tr("%1 crashed.").arg(data.name);
|
||||
outputHandler({false, input.unit.file, data.outputFilePath, input.tool, message, details});
|
||||
outputHandler(
|
||||
{false, input.unit.file, data.outputFilePath, {}, input.tool, message, details});
|
||||
};
|
||||
|
||||
const auto onReadSetup = [=](Async<Diagnostics> &data) {
|
||||
data.setConcurrentCallData(&readExportedDiagnostics,
|
||||
storage->outputFilePath,
|
||||
input.diagnosticsFilter,
|
||||
&storage->errorMessage);
|
||||
data.setFutureSynchronizer(ExtensionSystem::PluginManager::futureSynchronizer());
|
||||
};
|
||||
const auto onReadDone = [=](const Async<Diagnostics> &data) {
|
||||
if (!outputHandler)
|
||||
return;
|
||||
outputHandler(
|
||||
{true, input.unit.file, storage->outputFilePath, data.result(), input.tool});
|
||||
};
|
||||
const auto onReadError = [=](const Async<Diagnostics> &) {
|
||||
if (!outputHandler)
|
||||
return;
|
||||
outputHandler(
|
||||
{false, input.unit.file, storage->outputFilePath, {}, input.tool, storage->errorMessage});
|
||||
};
|
||||
|
||||
const Group group {
|
||||
Storage(storage),
|
||||
onGroupSetup(onSetup),
|
||||
Group {
|
||||
sequential,
|
||||
finishAllAndDone,
|
||||
ProcessTask(onProcessSetup, onProcessDone, onProcessError)
|
||||
ProcessTask(onProcessSetup, onProcessDone, onProcessError),
|
||||
AsyncTask<Diagnostics>(onReadSetup, onReadDone, onReadError)
|
||||
}
|
||||
};
|
||||
return group;
|
||||
|
@@ -4,6 +4,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "clangfileinfo.h"
|
||||
#include "clangtoolsdiagnostic.h"
|
||||
#include "clangtoolslogfilereader.h"
|
||||
#include "clangtoolssettings.h"
|
||||
|
||||
#include <cppeditor/clangdiagnosticconfig.h>
|
||||
@@ -35,6 +37,7 @@ struct AnalyzeInputData
|
||||
Utils::Environment environment;
|
||||
AnalyzeUnit unit;
|
||||
QString overlayFilePath = {};
|
||||
AcceptDiagsFromFilePath diagnosticsFilter = {};
|
||||
};
|
||||
|
||||
struct AnalyzeOutputData
|
||||
@@ -42,6 +45,7 @@ struct AnalyzeOutputData
|
||||
bool success = true;
|
||||
Utils::FilePath fileToAnalyze;
|
||||
Utils::FilePath outputFilePath;
|
||||
Diagnostics diagnostics;
|
||||
CppEditor::ClangToolType toolType;
|
||||
QString errorMessage = {};
|
||||
QString errorDetails = {};
|
||||
|
@@ -201,8 +201,16 @@ void DocumentClangToolRunner::run()
|
||||
if (includeDir.isEmpty() || clangVersion.isEmpty())
|
||||
return;
|
||||
const AnalyzeUnit unit(m_fileInfo, includeDir, clangVersion);
|
||||
const AnalyzeInputData input{tool, runSettings, config, m_temporaryDir.path(), env, unit,
|
||||
vfso().overlayFilePath().toString()};
|
||||
auto diagnosticFilter = [mappedPath = vfso().autoSavedFilePath(m_document)](
|
||||
const FilePath &path) { return path == mappedPath; };
|
||||
const AnalyzeInputData input{tool,
|
||||
runSettings,
|
||||
config,
|
||||
m_temporaryDir.path(),
|
||||
env,
|
||||
unit,
|
||||
vfso().overlayFilePath().toString(),
|
||||
diagnosticFilter};
|
||||
const auto setupHandler = [this, executable] {
|
||||
return !m_document->isModified() || isVFSOverlaySupported(executable);
|
||||
};
|
||||
@@ -234,11 +242,7 @@ void DocumentClangToolRunner::onDone(const AnalyzeOutputData &output)
|
||||
return;
|
||||
}
|
||||
|
||||
const FilePath mappedPath = vfso().autoSavedFilePath(m_document);
|
||||
Diagnostics diagnostics = readExportedDiagnostics(
|
||||
output.outputFilePath,
|
||||
[&](const FilePath &path) { return path == mappedPath; });
|
||||
|
||||
Diagnostics diagnostics = output.diagnostics;
|
||||
for (Diagnostic &diag : diagnostics) {
|
||||
updateLocation(diag.location);
|
||||
for (ExplainingStep &explainingStep : diag.explainingSteps) {
|
||||
|
Reference in New Issue
Block a user