ClangTools: Generalize run control for multiple runners

No functional change at this point.

Change-Id: I537f9d8c9eed0b48056918809358a0a179b42eaa
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
Nikolai Kosjar
2019-08-01 14:50:59 +02:00
parent d471b6df90
commit c9c214057e
4 changed files with 57 additions and 29 deletions

View File

@@ -45,18 +45,23 @@ ClangTidyClazyRunControl::ClangTidyClazyRunControl(
init(); init();
} }
QList<RunnerCreator> ClangTidyClazyRunControl::runnerCreators()
{
return {
[this]() { return createRunner(); }
};
}
ClangToolRunner *ClangTidyClazyRunControl::createRunner() ClangToolRunner *ClangTidyClazyRunControl::createRunner()
{ {
QTC_ASSERT(!m_clangExecutable.isEmpty(), return nullptr);
auto runner = new ClangTidyClazyRunner(m_diagnosticConfig, auto runner = new ClangTidyClazyRunner(m_diagnosticConfig,
m_clangExecutable, m_clangExecutable,
m_temporaryDir.path(), m_temporaryDir.path(),
m_environment, m_environment,
this); this);
connect(runner, &ClangTidyClazyRunner::finishedWithSuccess, connect(runner, &ClangToolRunner::finishedWithSuccess,
this, &ClangTidyClazyRunControl::onRunnerFinishedWithSuccess); this, &ClangTidyClazyRunControl::onRunnerFinishedWithSuccess);
connect(runner, &ClangTidyClazyRunner::finishedWithFailure, connect(runner, &ClangToolRunner::finishedWithFailure,
this, &ClangTidyClazyRunControl::onRunnerFinishedWithFailure); this, &ClangTidyClazyRunControl::onRunnerFinishedWithFailure);
return runner; return runner;
} }

View File

@@ -43,9 +43,12 @@ public:
const FileInfos &fileInfos); const FileInfos &fileInfos);
protected: protected:
ClangToolRunner *createRunner() final; QList<RunnerCreator> runnerCreators() final;
ClangTool *tool() final; ClangTool *tool() final;
private:
ClangToolRunner *createRunner();
private: private:
CppTools::ClangDiagnosticConfig m_diagnosticConfig; CppTools::ClangDiagnosticConfig m_diagnosticConfig;
}; };

View File

@@ -319,10 +319,15 @@ void ClangToolRunControl::start()
// Collect files // Collect files
const AnalyzeUnits unitsToProcess = unitsToAnalyze(); const AnalyzeUnits unitsToProcess = unitsToAnalyze();
qCDebug(LOG) << "Files to process:" << unitsToProcess; qCDebug(LOG) << "Files to process:" << unitsToProcess;
m_unitsToProcess = unitsToProcess;
m_initialFilesToProcessSize = m_unitsToProcess.count(); m_queue.clear();
m_filesAnalyzed = 0; for (const AnalyzeUnit &unit : unitsToProcess) {
m_filesNotAnalyzed = 0; for (auto creator : runnerCreators())
m_queue << QueueItem{unit, creator};
}
m_initialQueueSize = m_queue.count();
m_filesAnalyzed.clear();
m_filesNotAnalyzed.clear();
// Set up progress information // Set up progress information
using namespace Core; using namespace Core;
@@ -333,7 +338,7 @@ void ClangToolRunControl::start()
futureProgress->setKeepOnFinish(FutureProgress::HideOnFinish); futureProgress->setKeepOnFinish(FutureProgress::HideOnFinish);
connect(futureProgress, &FutureProgress::canceled, connect(futureProgress, &FutureProgress::canceled,
this, &ClangToolRunControl::onProgressCanceled); this, &ClangToolRunControl::onProgressCanceled);
m_progress.setProgressRange(0, m_initialFilesToProcessSize); m_progress.setProgressRange(0, m_initialQueueSize);
m_progress.reportStarted(); m_progress.reportStarted();
// Start process(es) // Start process(es)
@@ -343,14 +348,14 @@ void ClangToolRunControl::start()
QTC_ASSERT(parallelRuns >= 1, reportFailure(); return); QTC_ASSERT(parallelRuns >= 1, reportFailure(); return);
m_success = true; m_success = true;
if (m_unitsToProcess.isEmpty()) { if (m_queue.isEmpty()) {
finalize(); finalize();
return; return;
} }
reportStarted(); reportStarted();
while (m_runners.size() < parallelRuns && !m_unitsToProcess.isEmpty()) while (m_runners.size() < parallelRuns && !m_queue.isEmpty())
analyzeNextFile(); analyzeNextFile();
} }
@@ -362,7 +367,7 @@ void ClangToolRunControl::stop()
} }
m_projectFiles.clear(); m_projectFiles.clear();
m_runners.clear(); m_runners.clear();
m_unitsToProcess.clear(); m_queue.clear();
m_progress.reportFinished(); m_progress.reportFinished();
reportStopped(); reportStopped();
@@ -373,16 +378,17 @@ void ClangToolRunControl::analyzeNextFile()
if (m_progress.isFinished()) if (m_progress.isFinished())
return; // The previous call already reported that we are finished. return; // The previous call already reported that we are finished.
if (m_unitsToProcess.isEmpty()) { if (m_queue.isEmpty()) {
if (m_runners.isEmpty()) if (m_runners.isEmpty())
finalize(); finalize();
return; return;
} }
const AnalyzeUnit unit = m_unitsToProcess.takeFirst(); const QueueItem queueItem = m_queue.takeFirst();
const AnalyzeUnit unit = queueItem.unit;
qCDebug(LOG) << "analyzeNextFile:" << unit.file; qCDebug(LOG) << "analyzeNextFile:" << unit.file;
ClangToolRunner *runner = createRunner(); ClangToolRunner *runner = queueItem.runnerCreator();
m_runners.insert(runner); m_runners.insert(runner);
QTC_ASSERT(runner->run(unit.file, unit.arguments), return); QTC_ASSERT(runner->run(unit.file, unit.arguments), return);
@@ -403,12 +409,15 @@ void ClangToolRunControl::onRunnerFinishedWithSuccess(const QString &filePath)
QFile::remove(logFilePath); // Clean-up. QFile::remove(logFilePath); // Clean-up.
if (!errorMessage.isEmpty()) { if (!errorMessage.isEmpty()) {
m_filesAnalyzed.remove(filePath);
m_filesNotAnalyzed.insert(filePath);
qCDebug(LOG) << "onRunnerFinishedWithSuccess: Error reading log file:" << errorMessage; qCDebug(LOG) << "onRunnerFinishedWithSuccess: Error reading log file:" << errorMessage;
const QString filePath = qobject_cast<ClangToolRunner *>(sender())->filePath(); const QString filePath = qobject_cast<ClangToolRunner *>(sender())->filePath();
appendMessage(tr("Failed to analyze \"%1\": %2").arg(filePath, errorMessage), appendMessage(tr("Failed to analyze \"%1\": %2").arg(filePath, errorMessage),
Utils::StdErrFormat); Utils::StdErrFormat);
} else { } else {
++m_filesAnalyzed; if (!m_filesNotAnalyzed.contains(filePath))
m_filesAnalyzed.insert(filePath);
if (!diagnostics.isEmpty()) if (!diagnostics.isEmpty())
tool()->onNewDiagnosticsAvailable(diagnostics); tool()->onNewDiagnosticsAvailable(diagnostics);
} }
@@ -429,10 +438,11 @@ void ClangToolRunControl::onRunnerFinishedWithFailure(const QString &errorMessag
// Even in the error case the log file was created, so clean it up here, too. // Even in the error case the log file was created, so clean it up here, too.
QFile::remove(logFilePath); QFile::remove(logFilePath);
const QString message = tr("Failed to analyze \"%1\": %2").arg(filePath, errorMessage); m_filesAnalyzed.remove(filePath);
m_filesNotAnalyzed.insert(filePath);
++m_filesNotAnalyzed;
m_success = false; m_success = false;
const QString message = tr("Failed to analyze \"%1\": %2").arg(filePath, errorMessage);
appendMessage(message, Utils::StdErrFormat); appendMessage(message, Utils::StdErrFormat);
appendMessage(errorDetails, Utils::StdErrFormat); appendMessage(errorDetails, Utils::StdErrFormat);
TaskHub::addTask(Task::Error, message, Debugger::Constants::ANALYZERTASK_ID); TaskHub::addTask(Task::Error, message, Debugger::Constants::ANALYZERTASK_ID);
@@ -455,7 +465,7 @@ void ClangToolRunControl::onProgressCanceled()
void ClangToolRunControl::updateProgressValue() void ClangToolRunControl::updateProgressValue()
{ {
m_progress.setProgressValue(m_initialFilesToProcessSize - m_unitsToProcess.size()); m_progress.setProgressValue(m_initialQueueSize - m_queue.size());
} }
void ClangToolRunControl::finalize() void ClangToolRunControl::finalize()
@@ -463,10 +473,12 @@ void ClangToolRunControl::finalize()
const QString toolName = tool()->name(); const QString toolName = tool()->name();
appendMessage(tr("%1 finished: " appendMessage(tr("%1 finished: "
"Processed %2 files successfully, %3 failed.") "Processed %2 files successfully, %3 failed.")
.arg(toolName).arg(m_filesAnalyzed).arg(m_filesNotAnalyzed), .arg(toolName)
.arg(m_filesAnalyzed.size())
.arg(m_filesNotAnalyzed.size()),
Utils::NormalMessageFormat); Utils::NormalMessageFormat);
if (m_filesNotAnalyzed != 0) { if (m_filesNotAnalyzed.size() != 0) {
QString msg = tr("%1: Not all files could be analyzed.").arg(toolName); QString msg = tr("%1: Not all files could be analyzed.").arg(toolName);
TaskHub::addTask(Task::Error, msg, Debugger::Constants::ANALYZERTASK_ID); TaskHub::addTask(Task::Error, msg, Debugger::Constants::ANALYZERTASK_ID);
if (m_target && !m_target->activeBuildConfiguration()->buildDirectory().exists() if (m_target && !m_target->activeBuildConfiguration()->buildDirectory().exists()

View File

@@ -33,6 +33,7 @@
#include <utils/temporarydirectory.h> #include <utils/temporarydirectory.h>
#include <QFutureInterface> #include <QFutureInterface>
#include <QSet>
#include <QStringList> #include <QStringList>
namespace ClangTools { namespace ClangTools {
@@ -40,7 +41,6 @@ namespace Internal {
class ClangTool; class ClangTool;
class ClangToolRunner; class ClangToolRunner;
class Diagnostic;
class ProjectBuilder; class ProjectBuilder;
struct AnalyzeUnit { struct AnalyzeUnit {
@@ -52,6 +52,14 @@ struct AnalyzeUnit {
}; };
using AnalyzeUnits = QList<AnalyzeUnit>; using AnalyzeUnits = QList<AnalyzeUnit>;
using RunnerCreator = std::function<ClangToolRunner*()>;
struct QueueItem {
AnalyzeUnit unit;
RunnerCreator runnerCreator;
};
using QueueItems = QList<QueueItem>;
class ClangToolRunControl : public ProjectExplorer::RunWorker class ClangToolRunControl : public ProjectExplorer::RunWorker
{ {
Q_OBJECT Q_OBJECT
@@ -68,7 +76,7 @@ public:
protected: protected:
void init(); void init();
virtual ClangToolRunner *createRunner() = 0; virtual QList<RunnerCreator> runnerCreators() = 0;
void onRunnerFinishedWithSuccess(const QString &filePath); void onRunnerFinishedWithSuccess(const QString &filePath);
void onRunnerFinishedWithFailure(const QString &errorMessage, const QString &errorDetails); void onRunnerFinishedWithFailure(const QString &errorMessage, const QString &errorDetails);
@@ -103,12 +111,12 @@ private:
Core::Id m_toolChainType; Core::Id m_toolChainType;
QFutureInterface<void> m_progress; QFutureInterface<void> m_progress;
AnalyzeUnits m_unitsToProcess; QueueItems m_queue;
QSet<Utils::FilePath> m_projectFiles; QSet<Utils::FilePath> m_projectFiles;
QSet<ClangToolRunner *> m_runners; QSet<ClangToolRunner *> m_runners;
int m_initialFilesToProcessSize = 0; int m_initialQueueSize = 0;
int m_filesAnalyzed = 0; QSet<QString> m_filesAnalyzed;
int m_filesNotAnalyzed = 0; QSet<QString> m_filesNotAnalyzed;
bool m_success = false; bool m_success = false;
}; };