ClangToolRunner: Flatten the class hierarchy

Instead of creating subclasses of ClangToolRunner configure
the base class according to the tool specifics.

Change-Id: I51b611b2375571453c7f9690499d744582f035c1
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
Jarek Kobus
2023-01-10 17:51:34 +01:00
parent 0139690c29
commit c7b60e7d6b
10 changed files with 84 additions and 159 deletions

View File

@@ -17,7 +17,6 @@ add_qtc_plugin(ClangTools
clangfileinfo.h clangfileinfo.h
clangfixitsrefactoringchanges.cpp clangfixitsrefactoringchanges.h clangfixitsrefactoringchanges.cpp clangfixitsrefactoringchanges.h
clangselectablefilesdialog.cpp clangselectablefilesdialog.h clangselectablefilesdialog.cpp clangselectablefilesdialog.h
clangtidyclazyrunner.cpp clangtidyclazyrunner.h
clangtool.cpp clangtool.h clangtool.cpp clangtool.h
clangtoolruncontrol.cpp clangtoolruncontrol.h clangtoolruncontrol.cpp clangtoolruncontrol.h
clangtoolrunner.cpp clangtoolrunner.h clangtoolrunner.cpp clangtoolrunner.h

View File

@@ -1,93 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "clangtidyclazyrunner.h"
#include "clangtoolsutils.h"
#include <coreplugin/icore.h>
#include <cppeditor/clangdiagnosticconfigsmodel.h>
#include <cppeditor/compileroptionsbuilder.h>
#include <cppeditor/cpptoolsreuse.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
#include <QDebug>
#include <QLoggingCategory>
static Q_LOGGING_CATEGORY(LOG, "qtc.clangtools.runner", QtWarningMsg)
using namespace CppEditor;
namespace ClangTools {
namespace Internal {
static bool isClMode(const QStringList &options)
{
return options.contains("--driver-mode=cl");
}
static QStringList tidyChecksArguments(const ClangDiagnosticConfig diagnosticConfig)
{
const ClangDiagnosticConfig::TidyMode tidyMode = diagnosticConfig.clangTidyMode();
// The argument "-config={}" stops stating/evaluating the .clang-tidy file.
if (tidyMode == ClangDiagnosticConfig::TidyMode::UseDefaultChecks)
return {"-config={}", "-checks=-clang-diagnostic-*"};
if (tidyMode == ClangDiagnosticConfig::TidyMode::UseCustomChecks)
return {"-config=" + diagnosticConfig.clangTidyChecksAsJson()};
return {"--warnings-as-errors=-*", "-checks=-clang-diagnostic-*"};
}
static QStringList clazyChecksArguments(const ClangDiagnosticConfig diagnosticConfig)
{
const QString clazyChecks = diagnosticConfig.checks(ClangToolType::Clazy);
if (!clazyChecks.isEmpty())
return {"-checks=" + diagnosticConfig.checks(ClangToolType::Clazy)};
return {};
}
static QStringList clangArguments(const ClangDiagnosticConfig &diagnosticConfig,
const QStringList &baseOptions)
{
QStringList arguments;
arguments << ClangDiagnosticConfigsModel::globalDiagnosticOptions()
<< (isClMode(baseOptions) ? CppEditor::clangArgsForCl(diagnosticConfig.clangOptions())
: diagnosticConfig.clangOptions())
<< baseOptions;
if (LOG().isDebugEnabled())
arguments << QLatin1String("-v");
return arguments;
}
ClangTidyRunner::ClangTidyRunner(const ClangDiagnosticConfig &config, QObject *parent)
: ClangToolRunner(parent)
{
setName(tr("Clang-Tidy"));
setExecutable(toolExecutable(ClangToolType::Tidy));
setArgsCreator([this, config](const QStringList &baseOptions) {
return QStringList() << tidyChecksArguments(config)
<< mainToolArguments()
<< "--"
<< clangArguments(config, baseOptions);
});
}
ClazyStandaloneRunner::ClazyStandaloneRunner(const ClangDiagnosticConfig &config, QObject *parent)
: ClangToolRunner(parent)
{
setName(tr("Clazy"));
setExecutable(toolExecutable(ClangToolType::Clazy));
setArgsCreator([this, config](const QStringList &baseOptions) {
return QStringList() << clazyChecksArguments(config)
<< mainToolArguments()
<< "--"
<< clangArguments(config, baseOptions);
});
}
} // namespace Internal
} // namespace ClangTools

View File

@@ -1,30 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#pragma once
#include <cppeditor/clangdiagnosticconfig.h>
#include "clangtoolrunner.h"
namespace ClangTools {
namespace Internal {
class ClangTidyRunner final : public ClangToolRunner
{
Q_OBJECT
public:
ClangTidyRunner(const CppEditor::ClangDiagnosticConfig &config, QObject *parent = nullptr);
};
class ClazyStandaloneRunner final : public ClangToolRunner
{
Q_OBJECT
public:
ClazyStandaloneRunner(const CppEditor::ClangDiagnosticConfig &config, QObject *parent = nullptr);
};
} // namespace Internal
} // namespace ClangTools

View File

@@ -3,8 +3,8 @@
#include "clangtoolruncontrol.h" #include "clangtoolruncontrol.h"
#include "clangtidyclazyrunner.h"
#include "clangtool.h" #include "clangtool.h"
#include "clangtoolrunner.h"
#include "clangtoolssettings.h" #include "clangtoolssettings.h"
#include "clangtoolsutils.h" #include "clangtoolsutils.h"
#include "executableinfo.h" #include "executableinfo.h"
@@ -169,8 +169,8 @@ ClangToolRunWorker::ClangToolRunWorker(ClangTool *tool, RunControl *runControl,
QList<RunnerCreator> ClangToolRunWorker::runnerCreators() QList<RunnerCreator> ClangToolRunWorker::runnerCreators()
{ {
if (m_tool == ClangTidyTool::instance()) if (m_tool == ClangTidyTool::instance())
return {[this] { return createRunner<ClangTidyRunner>(); }}; return {[this] { return createRunner(ClangToolType::Tidy); }};
return {[this] { return createRunner<ClazyStandaloneRunner>(); }}; return {[this] { return createRunner(ClangToolType::Clazy); }};
} }
void ClangToolRunWorker::start() void ClangToolRunWorker::start()
@@ -410,12 +410,11 @@ void ClangToolRunWorker::finalize()
runControl()->initiateStop(); runControl()->initiateStop();
} }
template<class T> ClangToolRunner *ClangToolRunWorker::createRunner(ClangToolType tool)
ClangToolRunner *ClangToolRunWorker::createRunner()
{ {
using namespace std::placeholders; using namespace std::placeholders;
auto runner = new T(m_diagnosticConfig, this); auto runner = new ClangToolRunner(
runner->init(m_temporaryDir.path(), m_environment); {tool, m_diagnosticConfig, m_temporaryDir.path(), m_environment}, this);
connect(runner, &ClangToolRunner::finishedWithSuccess, this, connect(runner, &ClangToolRunner::finishedWithSuccess, this,
std::bind(&ClangToolRunWorker::onRunnerFinishedWithSuccess, this, runner, _1)); std::bind(&ClangToolRunWorker::onRunnerFinishedWithSuccess, this, runner, _1));
connect(runner, &ClangToolRunner::finishedWithFailure, this, connect(runner, &ClangToolRunner::finishedWithFailure, this,

View File

@@ -72,7 +72,7 @@ private:
void stop() final; void stop() final;
QList<RunnerCreator> runnerCreators(); QList<RunnerCreator> runnerCreators();
template <class T> ClangToolRunner *createRunner(); ClangToolRunner *createRunner(CppEditor::ClangToolType tool);
AnalyzeUnits unitsToAnalyze(const Utils::FilePath &clangIncludeDir, AnalyzeUnits unitsToAnalyze(const Utils::FilePath &clangIncludeDir,
const QString &clangVersion); const QString &clangVersion);

View File

@@ -3,6 +3,11 @@
#include "clangtoolrunner.h" #include "clangtoolrunner.h"
#include "clangtoolsutils.h"
#include <cppeditor/clangdiagnosticconfigsmodel.h>
#include <cppeditor/compileroptionsbuilder.h>
#include <utils/environment.h> #include <utils/environment.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/qtcprocess.h> #include <utils/qtcprocess.h>
@@ -15,11 +20,50 @@
static Q_LOGGING_CATEGORY(LOG, "qtc.clangtools.runner", QtWarningMsg) static Q_LOGGING_CATEGORY(LOG, "qtc.clangtools.runner", QtWarningMsg)
using namespace CppEditor;
using namespace Utils; using namespace Utils;
namespace ClangTools { namespace ClangTools {
namespace Internal { namespace Internal {
static bool isClMode(const QStringList &options)
{
return options.contains("--driver-mode=cl");
}
static QStringList checksArguments(ClangToolType tool,
const ClangDiagnosticConfig &diagnosticConfig)
{
if (tool == ClangToolType::Tidy) {
const ClangDiagnosticConfig::TidyMode tidyMode = diagnosticConfig.clangTidyMode();
// The argument "-config={}" stops stating/evaluating the .clang-tidy file.
if (tidyMode == ClangDiagnosticConfig::TidyMode::UseDefaultChecks)
return {"-config={}", "-checks=-clang-diagnostic-*"};
if (tidyMode == ClangDiagnosticConfig::TidyMode::UseCustomChecks)
return {"-config=" + diagnosticConfig.clangTidyChecksAsJson()};
return {"--warnings-as-errors=-*", "-checks=-clang-diagnostic-*"};
}
const QString clazyChecks = diagnosticConfig.checks(ClangToolType::Clazy);
if (!clazyChecks.isEmpty())
return {"-checks=" + diagnosticConfig.checks(ClangToolType::Clazy)};
return {};
}
static QStringList clangArguments(const ClangDiagnosticConfig &diagnosticConfig,
const QStringList &baseOptions)
{
QStringList arguments;
arguments << ClangDiagnosticConfigsModel::globalDiagnosticOptions()
<< (isClMode(baseOptions) ? clangArgsForCl(diagnosticConfig.clangOptions())
: diagnosticConfig.clangOptions())
<< baseOptions;
if (LOG().isDebugEnabled())
arguments << QLatin1String("-v");
return arguments;
}
static QString generalProcessError(const QString &name) static QString generalProcessError(const QString &name)
{ {
return ClangToolRunner::tr("An error occurred with the %1 process.").arg(name); return ClangToolRunner::tr("An error occurred with the %1 process.").arg(name);
@@ -35,16 +79,21 @@ static QString finishedWithBadExitCode(const QString &name, int exitCode)
return ClangToolRunner::tr("%1 finished with exit code: %2.").arg(name).arg(exitCode); return ClangToolRunner::tr("%1 finished with exit code: %2.").arg(name).arg(exitCode);
} }
ClangToolRunner::ClangToolRunner(QObject *parent) ClangToolRunner::ClangToolRunner(const AnalyzeInputData &input, QObject *parent)
: QObject(parent) : QObject(parent)
{}
void ClangToolRunner::init(const FilePath &outputDirPath, const Environment &environment)
{ {
m_outputDirPath = outputDirPath; m_name = input.tool == ClangToolType::Tidy ? tr("Clang-Tidy") : tr("Clazy");
m_executable = toolExecutable(input.tool);
m_argsCreator = [this, input](const QStringList &baseOptions) {
return QStringList() << checksArguments(input.tool, input.config)
<< mainToolArguments()
<< "--"
<< clangArguments(input.config, baseOptions);
};
m_outputDirPath = input.outputDirPath;
QTC_CHECK(!m_outputDirPath.isEmpty()); QTC_CHECK(!m_outputDirPath.isEmpty());
m_process.setEnvironment(environment); m_process.setEnvironment(input.environment);
m_process.setUseCtrlCStub(true); m_process.setUseCtrlCStub(true);
m_process.setWorkingDirectory(m_outputDirPath); // Current clang-cl puts log file into working dir. m_process.setWorkingDirectory(m_outputDirPath); // Current clang-cl puts log file into working dir.
connect(&m_process, &QtcProcess::done, this, &ClangToolRunner::onProcessDone); connect(&m_process, &QtcProcess::done, this, &ClangToolRunner::onProcessDone);
@@ -85,7 +134,7 @@ static QString createOutputFilePath(const FilePath &dirPath, const QString &file
temporaryFile.close(); temporaryFile.close();
return temporaryFile.fileName(); return temporaryFile.fileName();
} }
return QString(); return {};
} }
bool ClangToolRunner::run(const QString &fileToAnalyze, const QStringList &compilerOptions) bool ClangToolRunner::run(const QString &fileToAnalyze, const QStringList &compilerOptions)

View File

@@ -3,7 +3,10 @@
#pragma once #pragma once
#include <cppeditor/clangdiagnosticconfig.h>
#include <utils/commandline.h> #include <utils/commandline.h>
#include <utils/environment.h>
#include <utils/qtcprocess.h> #include <utils/qtcprocess.h>
#include <memory> #include <memory>
@@ -13,14 +16,20 @@ namespace Internal {
using ArgsCreator = std::function<QStringList(const QStringList &baseOptions)>; using ArgsCreator = std::function<QStringList(const QStringList &baseOptions)>;
struct AnalyzeInputData
{
CppEditor::ClangToolType tool = CppEditor::ClangToolType::Tidy;
CppEditor::ClangDiagnosticConfig config;
Utils::FilePath outputDirPath;
Utils::Environment environment;
};
class ClangToolRunner : public QObject class ClangToolRunner : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
ClangToolRunner(QObject *parent = nullptr); ClangToolRunner(const AnalyzeInputData &input, QObject *parent = nullptr);
void init(const Utils::FilePath &outputDirPath, const Utils::Environment &environment);
void setVFSOverlay(const QString overlayFilePath) { m_overlayFilePath = overlayFilePath; } void setVFSOverlay(const QString overlayFilePath) { m_overlayFilePath = overlayFilePath; }
QString name() const { return m_name; } QString name() const { return m_name; }
@@ -32,22 +41,17 @@ public:
// compilerOptions is expected to contain everything except: // compilerOptions is expected to contain everything except:
// (1) file to analyze // (1) file to analyze
// (2) -o output-file // (2) -o output-file
bool run(const QString &fileToAnalyze, const QStringList &compilerOptions = QStringList()); bool run(const QString &fileToAnalyze, const QStringList &compilerOptions = {});
signals: signals:
void finishedWithSuccess(const QString &fileToAnalyze); void finishedWithSuccess(const QString &fileToAnalyze);
void finishedWithFailure(const QString &errorMessage, const QString &errorDetails); void finishedWithFailure(const QString &errorMessage, const QString &errorDetails);
protected:
void setName(const QString &name) { m_name = name; }
void setExecutable(const Utils::FilePath &executable) { m_executable = executable; }
void setArgsCreator(const ArgsCreator &argsCreator) { m_argsCreator = argsCreator; }
QStringList mainToolArguments() const;
private: private:
void onProcessOutput(); void onProcessOutput();
void onProcessDone(); void onProcessDone();
QStringList mainToolArguments() const;
QString commandlineAndOutput() const; QString commandlineAndOutput() const;
QString m_overlayFilePath; QString m_overlayFilePath;

View File

@@ -28,8 +28,6 @@ QtcPlugin {
"clangfixitsrefactoringchanges.h", "clangfixitsrefactoringchanges.h",
"clangselectablefilesdialog.cpp", "clangselectablefilesdialog.cpp",
"clangselectablefilesdialog.h", "clangselectablefilesdialog.h",
"clangtidyclazyrunner.cpp",
"clangtidyclazyrunner.h",
"clangtool.cpp", "clangtool.cpp",
"clangtool.h", "clangtool.h",
"clangtoolruncontrol.cpp", "clangtoolruncontrol.cpp",

View File

@@ -4,11 +4,11 @@
#include "documentclangtoolrunner.h" #include "documentclangtoolrunner.h"
#include "clangfileinfo.h" #include "clangfileinfo.h"
#include "clangtidyclazyrunner.h"
#include "clangtoolruncontrol.h" #include "clangtoolruncontrol.h"
#include "clangtoolsconstants.h" #include "clangtoolsconstants.h"
#include "clangtoolslogfilereader.h" #include "clangtoolslogfilereader.h"
#include "clangtoolsprojectsettings.h" #include "clangtoolsprojectsettings.h"
#include "clangtoolrunner.h"
#include "clangtoolsutils.h" #include "clangtoolsutils.h"
#include "diagnosticmark.h" #include "diagnosticmark.h"
#include "executableinfo.h" #include "executableinfo.h"
@@ -200,12 +200,12 @@ void DocumentClangToolRunner::run()
Environment env = projectBuildEnvironment(project); Environment env = projectBuildEnvironment(project);
if (config.isEnabled(ClangToolType::Tidy)) { if (config.isEnabled(ClangToolType::Tidy)) {
m_runnerCreators << [this, env, config] { m_runnerCreators << [this, env, config] {
return createRunner<ClangTidyRunner>(config, env); return createRunner(ClangToolType::Tidy, config, env);
}; };
} }
if (config.isEnabled(ClangToolType::Clazy)) { if (config.isEnabled(ClangToolType::Clazy)) {
m_runnerCreators << [this, env, config] { m_runnerCreators << [this, env, config] {
return createRunner<ClazyStandaloneRunner>(config, env); return createRunner(ClangToolType::Clazy, config, env);
}; };
} }
} }
@@ -364,12 +364,11 @@ const ClangDiagnosticConfig DocumentClangToolRunner::getDiagnosticConfig(Project
return diagnosticConfig(id); return diagnosticConfig(id);
} }
template<class T> ClangToolRunner *DocumentClangToolRunner::createRunner(ClangToolType tool,
ClangToolRunner *DocumentClangToolRunner::createRunner(const ClangDiagnosticConfig &config, const ClangDiagnosticConfig &config,
const Environment &env) const Environment &env)
{ {
auto runner = new T(config, this); auto runner = new ClangToolRunner({tool, config, m_temporaryDir.path(), env}, this);
runner->init(m_temporaryDir.path(), env);
connect(runner, &ClangToolRunner::finishedWithSuccess, connect(runner, &ClangToolRunner::finishedWithSuccess,
this, &DocumentClangToolRunner::onSuccess); this, &DocumentClangToolRunner::onSuccess);
connect(runner, &ClangToolRunner::finishedWithFailure, connect(runner, &ClangToolRunner::finishedWithFailure,

View File

@@ -49,8 +49,8 @@ private:
bool isSuppressed(const Diagnostic &diagnostic) const; bool isSuppressed(const Diagnostic &diagnostic) const;
const CppEditor::ClangDiagnosticConfig getDiagnosticConfig(ProjectExplorer::Project *project); const CppEditor::ClangDiagnosticConfig getDiagnosticConfig(ProjectExplorer::Project *project);
template<class T> ClangToolRunner *createRunner(CppEditor::ClangToolType tool,
ClangToolRunner *createRunner(const CppEditor::ClangDiagnosticConfig &config, const CppEditor::ClangDiagnosticConfig &config,
const Utils::Environment &env); const Utils::Environment &env);
QTimer m_runTimer; QTimer m_runTimer;