forked from qt-creator/qt-creator
ClangTools: Run clang-tidy and clazy separately
They are two different tools and should not have been merged into a single runner in the first place. People can now actively decide to run clazy if they really want to, rather than getting confronted with its increasingly irrelevant complaints by default. We keep the common settings widget for now. Change-Id: I3c2b1db8c07ff5c128700d4a1deefd710967568a Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -66,8 +66,6 @@ using namespace Utils;
|
||||
namespace ClangTools {
|
||||
namespace Internal {
|
||||
|
||||
static ClangTool *s_instance;
|
||||
|
||||
static QString makeLink(const QString &text)
|
||||
{
|
||||
return QString("<a href=t>%1</a>").arg(text);
|
||||
@@ -355,23 +353,17 @@ static RunSettings runSettings()
|
||||
return ClangToolsSettings::instance()->runSettings();
|
||||
}
|
||||
|
||||
ClangTool *ClangTool::instance()
|
||||
ClangTool::ClangTool(const QString &name, Utils::Id id)
|
||||
: m_name(name), m_perspective{id.toString(), name}
|
||||
{
|
||||
return s_instance;
|
||||
}
|
||||
|
||||
ClangTool::ClangTool()
|
||||
: m_name("Clang-Tidy and Clazy")
|
||||
{
|
||||
setObjectName("ClangTidyClazyTool");
|
||||
s_instance = this;
|
||||
setObjectName(name);
|
||||
m_diagnosticModel = new ClangToolsDiagnosticModel(this);
|
||||
|
||||
auto action = new QAction(tr("Analyze Project..."), this);
|
||||
auto action = new QAction(tr("Analyze Project with %1...").arg(name), this);
|
||||
action->setIcon(Utils::Icons::RUN_SELECTED_TOOLBAR.icon());
|
||||
m_startAction = action;
|
||||
|
||||
action = new QAction(tr("Analyze Current File"), this);
|
||||
action = new QAction(tr("Analyze Current File with %1").arg(name), this);
|
||||
action->setIcon(Utils::Icons::RUN_FILE.icon());
|
||||
m_startOnCurrentFileAction = action;
|
||||
|
||||
@@ -536,9 +528,9 @@ ClangTool::ClangTool()
|
||||
|
||||
m_perspective.addWindow(mainWidget, Perspective::SplitVertical, nullptr);
|
||||
|
||||
action = new QAction(tr("Clang-Tidy and Clazy..."), this);
|
||||
action = new QAction(name, this);
|
||||
action->setToolTip(toolTip);
|
||||
menu->addAction(ActionManager::registerAction(action, "ClangTidyClazy.Action"),
|
||||
menu->addAction(ActionManager::registerAction(action, id),
|
||||
Debugger::Constants::G_ANALYZER_TOOLS);
|
||||
QObject::connect(action, &QAction::triggered, this, [this] {
|
||||
startTool(FileSelectionType::AskUser);
|
||||
@@ -645,12 +637,12 @@ void ClangTool::startTool(ClangTool::FileSelection fileSelection,
|
||||
|
||||
// Run control
|
||||
m_runControl = new RunControl(Constants::CLANGTIDYCLAZY_RUN_MODE);
|
||||
m_runControl->setDisplayName(tr("Clang-Tidy and Clazy"));
|
||||
m_runControl->setDisplayName(m_name);
|
||||
m_runControl->setIcon(ProjectExplorer::Icons::ANALYZER_START_SMALL_TOOLBAR);
|
||||
m_runControl->setTarget(project->activeTarget());
|
||||
m_stopAction->disconnect();
|
||||
connect(m_stopAction, &QAction::triggered, m_runControl, [this] {
|
||||
emit m_runControl->appendMessage(tr("Clang-Tidy and Clazy tool stopped by user."),
|
||||
emit m_runControl->appendMessage(tr("%1 tool stopped by user.").arg(m_name),
|
||||
NormalMessageFormat);
|
||||
m_runControl->initiateStop();
|
||||
setState(State::StoppedByUser);
|
||||
@@ -662,7 +654,8 @@ void ClangTool::startTool(ClangTool::FileSelection fileSelection,
|
||||
|| std::get<FileSelectionType>(fileSelection)
|
||||
== FileSelectionType::CurrentFile;
|
||||
const bool buildBeforeAnalysis = !preventBuild && runSettings.buildBeforeAnalysis();
|
||||
m_runWorker = new ClangToolRunWorker(m_runControl,
|
||||
m_runWorker = new ClangToolRunWorker(this,
|
||||
m_runControl,
|
||||
runSettings,
|
||||
diagnosticConfig,
|
||||
fileInfos,
|
||||
@@ -1202,6 +1195,15 @@ void ClangTool::updateForCurrentState()
|
||||
m_infoBarWidget->setDiagText(diagText);
|
||||
}
|
||||
|
||||
ClangTidyTool::ClangTidyTool() : ClangTool(tr("Clang-Tidy"), "ClangTidy.Perspective")
|
||||
{
|
||||
m_instance = this;
|
||||
}
|
||||
ClazyTool::ClazyTool() : ClangTool(tr("Clazy"), "Clazy.Perspective")
|
||||
{
|
||||
m_instance = this;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace ClangTools
|
||||
|
||||
|
@@ -46,17 +46,11 @@ class DiagnosticView;
|
||||
class RunSettings;
|
||||
class SelectFixitsCheckBox;
|
||||
|
||||
const char ClangTidyClazyPerspectiveId[] = "ClangTidyClazy.Perspective";
|
||||
|
||||
class ClangTool : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static ClangTool *instance();
|
||||
|
||||
ClangTool();
|
||||
|
||||
void selectPerspective();
|
||||
|
||||
enum class FileSelectionType {
|
||||
@@ -93,6 +87,9 @@ public:
|
||||
signals:
|
||||
void finished(const QString &errorText); // For testing.
|
||||
|
||||
protected:
|
||||
ClangTool(const QString &name, Utils::Id id);
|
||||
|
||||
private:
|
||||
enum class State {
|
||||
Initial,
|
||||
@@ -132,6 +129,7 @@ private:
|
||||
FileInfoProviders fileInfoProviders(ProjectExplorer::Project *project,
|
||||
const FileInfos &allFileInfos);
|
||||
|
||||
const QString m_name;
|
||||
ClangToolsDiagnosticModel *m_diagnosticModel = nullptr;
|
||||
ProjectExplorer::RunControl *m_runControl = nullptr;
|
||||
ClangToolRunWorker *m_runWorker = nullptr;
|
||||
@@ -161,11 +159,27 @@ private:
|
||||
QAction *m_clear = nullptr;
|
||||
QAction *m_expandCollapse = nullptr;
|
||||
|
||||
Utils::Perspective m_perspective{ClangTidyClazyPerspectiveId,
|
||||
::ClangTools::Internal::ClangTool::tr("Clang-Tidy and Clazy")};
|
||||
Utils::Perspective m_perspective;
|
||||
};
|
||||
|
||||
class ClangTidyTool : public ClangTool
|
||||
{
|
||||
public:
|
||||
ClangTidyTool();
|
||||
static ClangTool *instance() { return m_instance; }
|
||||
|
||||
private:
|
||||
const QString m_name;
|
||||
static inline ClangTool *m_instance = nullptr;
|
||||
};
|
||||
|
||||
class ClazyTool : public ClangTool
|
||||
{
|
||||
public:
|
||||
ClazyTool();
|
||||
static ClangTool *instance() { return m_instance; }
|
||||
|
||||
private:
|
||||
static inline ClangTool *m_instance = nullptr;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -55,11 +55,6 @@ static Q_LOGGING_CATEGORY(LOG, "qtc.clangtools.runcontrol", QtWarningMsg)
|
||||
namespace ClangTools {
|
||||
namespace Internal {
|
||||
|
||||
static ClangTool *tool()
|
||||
{
|
||||
return ClangTool::instance();
|
||||
}
|
||||
|
||||
class ProjectBuilder : public RunWorker
|
||||
{
|
||||
public:
|
||||
@@ -138,12 +133,13 @@ static QDebug operator<<(QDebug debug, const AnalyzeUnits &analyzeUnits)
|
||||
}
|
||||
|
||||
|
||||
ClangToolRunWorker::ClangToolRunWorker(RunControl *runControl,
|
||||
ClangToolRunWorker::ClangToolRunWorker(ClangTool *tool, RunControl *runControl,
|
||||
const RunSettings &runSettings,
|
||||
const CppEditor::ClangDiagnosticConfig &diagnosticConfig,
|
||||
const FileInfos &fileInfos,
|
||||
bool buildBeforeAnalysis)
|
||||
: RunWorker(runControl)
|
||||
, m_tool(tool)
|
||||
, m_runSettings(runSettings)
|
||||
, m_diagnosticConfig(diagnosticConfig)
|
||||
, m_fileInfos(fileInfos)
|
||||
@@ -174,15 +170,9 @@ ClangToolRunWorker::ClangToolRunWorker(RunControl *runControl,
|
||||
|
||||
QList<RunnerCreator> ClangToolRunWorker::runnerCreators()
|
||||
{
|
||||
QList<RunnerCreator> creators;
|
||||
|
||||
if (m_diagnosticConfig.isClangTidyEnabled())
|
||||
creators << [this] { return createRunner<ClangTidyRunner>(); };
|
||||
|
||||
if (m_diagnosticConfig.isClazyEnabled())
|
||||
creators << [this] { return createRunner<ClazyStandaloneRunner>(); };
|
||||
|
||||
return creators;
|
||||
if (m_tool == ClangTidyTool::instance())
|
||||
return {[this] { return createRunner<ClangTidyRunner>(); }};
|
||||
return {[this] { return createRunner<ClazyStandaloneRunner>(); }};
|
||||
}
|
||||
|
||||
void ClangToolRunWorker::start()
|
||||
@@ -195,7 +185,7 @@ void ClangToolRunWorker::start()
|
||||
return;
|
||||
}
|
||||
|
||||
const QString &toolName = tool()->name();
|
||||
const QString &toolName = m_tool->name();
|
||||
Project *project = runControl()->project();
|
||||
m_projectInfo = CppEditor::CppModelManager::instance()->projectInfo(project);
|
||||
if (!m_projectInfo) {
|
||||
@@ -334,7 +324,7 @@ void ClangToolRunWorker::onRunnerFinishedWithSuccess(ClangToolRunner *runner,
|
||||
emit runnerFinished();
|
||||
|
||||
QString errorMessage;
|
||||
const Diagnostics diagnostics = tool()->read(runner->outputFileFormat(),
|
||||
const Diagnostics diagnostics = m_tool->read(runner->outputFileFormat(),
|
||||
outputFilePath,
|
||||
m_projectFiles,
|
||||
&errorMessage);
|
||||
@@ -353,7 +343,7 @@ void ClangToolRunWorker::onRunnerFinishedWithSuccess(ClangToolRunner *runner,
|
||||
// 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();
|
||||
tool()->onNewDiagnosticsAvailable(diagnostics, generateMarks);
|
||||
m_tool->onNewDiagnosticsAvailable(diagnostics, generateMarks);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -401,7 +391,7 @@ void ClangToolRunWorker::updateProgressValue()
|
||||
|
||||
void ClangToolRunWorker::finalize()
|
||||
{
|
||||
const QString toolName = tool()->name();
|
||||
const QString toolName = m_tool->name();
|
||||
if (m_filesNotAnalyzed.size() != 0) {
|
||||
appendMessage(tr("Error: Failed to analyze %n files.", nullptr, m_filesNotAnalyzed.size()),
|
||||
ErrorMessageFormat);
|
||||
|
@@ -19,7 +19,7 @@
|
||||
|
||||
namespace ClangTools {
|
||||
namespace Internal {
|
||||
|
||||
class ClangTool;
|
||||
class ClangToolRunner;
|
||||
class ProjectBuilder;
|
||||
|
||||
@@ -46,7 +46,8 @@ class ClangToolRunWorker : public ProjectExplorer::RunWorker
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ClangToolRunWorker(ProjectExplorer::RunControl *runControl,
|
||||
ClangToolRunWorker(ClangTool *tool,
|
||||
ProjectExplorer::RunControl *runControl,
|
||||
const RunSettings &runSettings,
|
||||
const CppEditor::ClangDiagnosticConfig &diagnosticConfig,
|
||||
const FileInfos &fileInfos,
|
||||
@@ -85,6 +86,7 @@ private:
|
||||
void finalize();
|
||||
|
||||
private:
|
||||
ClangTool * const m_tool;
|
||||
RunSettings m_runSettings;
|
||||
CppEditor::ClangDiagnosticConfig m_diagnosticConfig;
|
||||
FileInfos m_fileInfos;
|
||||
|
@@ -8,8 +8,10 @@ namespace Constants {
|
||||
|
||||
const char PROJECT_PANEL_ID[] = "ClangTools";
|
||||
|
||||
const char RUN_ON_PROJECT[] = "ClangTools.RunOnProject";
|
||||
const char RUN_ON_CURRENT_FILE[] = "ClangTools.RunOnCurrentFile";
|
||||
const char RUN_CLANGTIDY_ON_PROJECT[] = "ClangTools.ClangTidy.RunOnProject";
|
||||
const char RUN_CLAZY_ON_PROJECT[] = "ClangTools.Clazy.RunOnProject";
|
||||
const char RUN_CLANGTIDY_ON_CURRENT_FILE[] = "ClangTools.ClangTidy.RunOnCurrentFile";
|
||||
const char RUN_CLAZY_ON_CURRENT_FILE[] = "ClangTools.Clazy.RunOnCurrentFile";
|
||||
|
||||
const char SETTINGS_PAGE_ID[] = "Analyzer.ClangTools.Settings";
|
||||
const char SETTINGS_ID[] = "ClangTools";
|
||||
|
@@ -75,7 +75,8 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ClangTool clangTool;
|
||||
ClangTidyTool clangTidyTool;
|
||||
ClazyTool clazyTool;
|
||||
ClangToolsOptionsPage optionsPage;
|
||||
QMap<Core::IDocument *, DocumentClangToolRunner *> documentRunners;
|
||||
DocumentQuickFixFactory quickFixFactory;
|
||||
@@ -133,22 +134,31 @@ void ClangToolsPlugin::onCurrentEditorChanged()
|
||||
|
||||
void ClangToolsPlugin::registerAnalyzeActions()
|
||||
{
|
||||
ActionManager::registerAction(d->clangTool.startAction(), Constants::RUN_ON_PROJECT);
|
||||
Command *cmd = ActionManager::registerAction(d->clangTool.startOnCurrentFileAction(),
|
||||
Constants::RUN_ON_CURRENT_FILE);
|
||||
ActionContainer *mtoolscpp = ActionManager::actionContainer(CppEditor::Constants::M_TOOLS_CPP);
|
||||
if (mtoolscpp)
|
||||
mtoolscpp->addAction(cmd);
|
||||
for (const auto &toolInfo : {std::make_tuple(ClangTidyTool::instance(),
|
||||
Constants::RUN_CLANGTIDY_ON_PROJECT,
|
||||
Constants::RUN_CLANGTIDY_ON_CURRENT_FILE),
|
||||
std::make_tuple(ClazyTool::instance(),
|
||||
Constants::RUN_CLAZY_ON_PROJECT,
|
||||
Constants::RUN_CLAZY_ON_CURRENT_FILE)}) {
|
||||
ClangTool * const tool = std::get<0>(toolInfo);
|
||||
ActionManager::registerAction(tool->startAction(), std::get<1>(toolInfo));
|
||||
Command *cmd = ActionManager::registerAction(tool->startOnCurrentFileAction(),
|
||||
std::get<2>(toolInfo));
|
||||
ActionContainer *mtoolscpp = ActionManager::actionContainer(CppEditor::Constants::M_TOOLS_CPP);
|
||||
if (mtoolscpp)
|
||||
mtoolscpp->addAction(cmd);
|
||||
|
||||
Core::ActionContainer *mcontext = Core::ActionManager::actionContainer(
|
||||
CppEditor::Constants::M_CONTEXT);
|
||||
if (mcontext)
|
||||
mcontext->addAction(cmd, CppEditor::Constants::G_CONTEXT_FIRST);
|
||||
Core::ActionContainer *mcontext = Core::ActionManager::actionContainer(
|
||||
CppEditor::Constants::M_CONTEXT);
|
||||
if (mcontext)
|
||||
mcontext->addAction(cmd, CppEditor::Constants::G_CONTEXT_FIRST);
|
||||
}
|
||||
|
||||
// add button to tool bar of C++ source files
|
||||
connect(EditorManager::instance(), &EditorManager::editorOpened, this, [this, cmd](IEditor *editor) {
|
||||
connect(EditorManager::instance(), &EditorManager::editorOpened, this,
|
||||
[this](IEditor *editor) {
|
||||
if (editor->document()->filePath().isEmpty()
|
||||
|| !Utils::mimeTypeForName(editor->document()->mimeType()).inherits("text/x-c++src"))
|
||||
|| !Utils::mimeTypeForName(editor->document()->mimeType()).inherits("text/x-c++src"))
|
||||
return;
|
||||
auto *textEditor = qobject_cast<TextEditor::BaseTextEditor *>(editor);
|
||||
if (!textEditor)
|
||||
@@ -157,12 +167,25 @@ void ClangToolsPlugin::registerAnalyzeActions()
|
||||
if (!widget)
|
||||
return;
|
||||
const QIcon icon = Utils::Icon({{":/debugger/images/debugger_singleinstructionmode.png",
|
||||
Utils::Theme::IconsBaseColor}})
|
||||
.icon();
|
||||
QAction *action = widget->toolBar()->addAction(icon, tr("Analyze File"), [this, editor] {
|
||||
d->clangTool.startTool(editor->document()->filePath());
|
||||
});
|
||||
cmd->augmentActionWithShortcutToolTip(action);
|
||||
Utils::Theme::IconsBaseColor}}).icon();
|
||||
const auto button = new QToolButton;
|
||||
button->setPopupMode(QToolButton::InstantPopup);
|
||||
button->setIcon(icon);
|
||||
button->setToolTip(tr("Analyze File..."));
|
||||
widget->toolBar()->addWidget(button);
|
||||
const auto toolsMenu = new QMenu(widget);
|
||||
button->setMenu(toolsMenu);
|
||||
for (const auto &toolInfo : {std::make_pair(ClangTidyTool::instance(),
|
||||
Constants::RUN_CLANGTIDY_ON_CURRENT_FILE),
|
||||
std::make_pair(ClazyTool::instance(),
|
||||
Constants::RUN_CLAZY_ON_CURRENT_FILE)}) {
|
||||
ClangTool * const tool = toolInfo.first;
|
||||
Command * const cmd = ActionManager::command(toolInfo.second);
|
||||
QAction * const action = toolsMenu->addAction(tool->name(), [this, editor, tool] {
|
||||
tool->startTool(editor->document()->filePath());
|
||||
});
|
||||
cmd->augmentActionWithShortcutToolTip(action);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@@ -99,13 +99,15 @@ void PreconfiguredSessionTests::testPreconfiguredSession()
|
||||
|
||||
QVERIFY(switchToProjectAndTarget(project, target));
|
||||
|
||||
ClangTool::instance()->startTool(ClangTool::FileSelectionType::AllFiles);
|
||||
QSignalSpy waitUntilAnalyzerFinished(ClangTool::instance(), SIGNAL(finished(bool)));
|
||||
QVERIFY(waitUntilAnalyzerFinished.wait(30000));
|
||||
const QList<QVariant> arguments = waitUntilAnalyzerFinished.takeFirst();
|
||||
const bool analyzerFinishedSuccessfully = arguments.first().toBool();
|
||||
QVERIFY(analyzerFinishedSuccessfully);
|
||||
QCOMPARE(ClangTool::instance()->diagnostics().count(), 0);
|
||||
for (ClangTool * const tool : {ClangTidyTool::instance(), ClazyTool::instance()}) {
|
||||
tool->startTool(ClangTool::FileSelectionType::AllFiles);
|
||||
QSignalSpy waitUntilAnalyzerFinished(tool, SIGNAL(finished(bool)));
|
||||
QVERIFY(waitUntilAnalyzerFinished.wait(30000));
|
||||
const QList<QVariant> arguments = waitUntilAnalyzerFinished.takeFirst();
|
||||
const bool analyzerFinishedSuccessfully = arguments.first().toBool();
|
||||
QVERIFY(analyzerFinishedSuccessfully);
|
||||
QCOMPARE(tool->diagnostics().count(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
static const QList<Project *> validProjects(const QList<Project *> projectsOfSession)
|
||||
|
@@ -54,8 +54,10 @@ ClangToolsProjectSettingsWidget::ClangToolsProjectSettingsWidget(ProjectExplorer
|
||||
setGlobalSettingsId(ClangTools::Constants::SETTINGS_PAGE_ID);
|
||||
m_restoreGlobal = new QPushButton(tr("Restore Global Settings"));
|
||||
|
||||
auto gotoAnalyzerModeLabel =
|
||||
new QLabel("<a href=\"target\">" + tr("Go to Analyzer") + "</a>");
|
||||
const auto gotoClangTidyModeLabel
|
||||
= new QLabel("<a href=\"target\">" + tr("Go to Clang-Tidy") + "</a>");
|
||||
const auto gotoClazyModeLabel
|
||||
= new QLabel("<a href=\"target\">" + tr("Go to Clazy") + "</a>");
|
||||
|
||||
m_runSettingsWidget = new ClangTools::Internal::RunSettingsWidget(this);
|
||||
|
||||
@@ -67,7 +69,7 @@ ClangToolsProjectSettingsWidget::ClangToolsProjectSettingsWidget(ProjectExplorer
|
||||
|
||||
using namespace Utils::Layouting;
|
||||
Column {
|
||||
Row { m_restoreGlobal, st, gotoAnalyzerModeLabel },
|
||||
Row { m_restoreGlobal, st, gotoClangTidyModeLabel, gotoClazyModeLabel },
|
||||
|
||||
m_runSettingsWidget,
|
||||
|
||||
@@ -96,8 +98,11 @@ ClangToolsProjectSettingsWidget::ClangToolsProjectSettingsWidget(ProjectExplorer
|
||||
m_runSettingsWidget->fromSettings(ClangToolsSettings::instance()->runSettings());
|
||||
});
|
||||
|
||||
connect(gotoAnalyzerModeLabel, &QLabel::linkActivated, [](const QString &) {
|
||||
ClangTool::instance()->selectPerspective();
|
||||
connect(gotoClangTidyModeLabel, &QLabel::linkActivated, [](const QString &) {
|
||||
ClangTidyTool::instance()->selectPerspective();
|
||||
});
|
||||
connect(gotoClazyModeLabel, &QLabel::linkActivated, [](const QString &) {
|
||||
ClazyTool::instance()->selectPerspective();
|
||||
});
|
||||
|
||||
// Run options
|
||||
|
@@ -86,7 +86,8 @@ static ClangDiagnosticConfig configFor(const QString &tidyChecks,
|
||||
void ClangToolsUnitTests::testProject()
|
||||
{
|
||||
QFETCH(QString, projectFilePath);
|
||||
QFETCH(int, expectedDiagCount);
|
||||
QFETCH(int, expectedDiagCountClangTidy);
|
||||
QFETCH(int, expectedDiagCountClazy);
|
||||
QFETCH(ClangDiagnosticConfig, diagnosticConfig);
|
||||
if (projectFilePath.contains("mingw")) {
|
||||
const auto toolchain = ToolChainKitAspect::cxxToolChain(m_kit);
|
||||
@@ -98,71 +99,75 @@ void ClangToolsUnitTests::testProject()
|
||||
Tests::ProjectOpenerAndCloser projectManager;
|
||||
QVERIFY(projectManager.open(projectFilePath, true, m_kit));
|
||||
|
||||
// Run tool
|
||||
ClangTool *tool = ClangTool::instance();
|
||||
tool->startTool(ClangTool::FileSelectionType::AllFiles,
|
||||
ClangToolsSettings::instance()->runSettings(),
|
||||
diagnosticConfig);
|
||||
QSignalSpy waitForFinishedTool(tool, &ClangTool::finished);
|
||||
QVERIFY(waitForFinishedTool.wait(m_timeout));
|
||||
// Run tools
|
||||
for (ClangTool * const tool : {ClangTidyTool::instance(), ClazyTool::instance()}) {
|
||||
tool->startTool(ClangTool::FileSelectionType::AllFiles,
|
||||
ClangToolsSettings::instance()->runSettings(),
|
||||
diagnosticConfig);
|
||||
QSignalSpy waitForFinishedTool(tool, &ClangTool::finished);
|
||||
QVERIFY(waitForFinishedTool.wait(m_timeout));
|
||||
|
||||
// Check for errors
|
||||
const QString errorText = waitForFinishedTool.takeFirst().constFirst().toString();
|
||||
const bool finishedSuccessfully = errorText.isEmpty();
|
||||
if (!finishedSuccessfully)
|
||||
qWarning("Error: %s", qPrintable(errorText));
|
||||
QVERIFY(finishedSuccessfully);
|
||||
QCOMPARE(tool->diagnostics().count(), expectedDiagCount);
|
||||
// Check for errors
|
||||
const QString errorText = waitForFinishedTool.takeFirst().constFirst().toString();
|
||||
const bool finishedSuccessfully = errorText.isEmpty();
|
||||
if (!finishedSuccessfully)
|
||||
qWarning("Error: %s", qPrintable(errorText));
|
||||
QVERIFY(finishedSuccessfully);
|
||||
QCOMPARE(tool->diagnostics().count(), tool == ClangTidyTool::instance()
|
||||
? expectedDiagCountClangTidy : expectedDiagCountClazy);
|
||||
}
|
||||
}
|
||||
|
||||
void ClangToolsUnitTests::testProject_data()
|
||||
{
|
||||
QTest::addColumn<QString>("projectFilePath");
|
||||
QTest::addColumn<int>("expectedDiagCount");
|
||||
QTest::addColumn<int>("expectedDiagCountClangTidy");
|
||||
QTest::addColumn<int>("expectedDiagCountClazy");
|
||||
QTest::addColumn<ClangDiagnosticConfig>("diagnosticConfig");
|
||||
|
||||
// Test simple C++ project.
|
||||
ClangDiagnosticConfig config = configFor("modernize-use-nullptr", QString());
|
||||
addTestRow("simple/simple.qbs", 1, config);
|
||||
addTestRow("simple/simple.pro", 1, config);
|
||||
addTestRow("simple/simple.qbs", 1, 0, config);
|
||||
addTestRow("simple/simple.pro", 1, 0, config);
|
||||
|
||||
// Test simple Qt project.
|
||||
config = configFor("readability-static-accessed-through-instance", QString());
|
||||
addTestRow("qt-widgets-app/qt-widgets-app.qbs", 1, config);
|
||||
addTestRow("qt-widgets-app/qt-widgets-app.pro", 1, config);
|
||||
addTestRow("qt-widgets-app/qt-widgets-app.qbs", 1, 0, config);
|
||||
addTestRow("qt-widgets-app/qt-widgets-app.pro", 1, 0, config);
|
||||
|
||||
// Test that libraries can be analyzed.
|
||||
config = configFor(QString(), QString());
|
||||
addTestRow("simple-library/simple-library.qbs", 0, config);
|
||||
addTestRow("simple-library/simple-library.pro", 0, config);
|
||||
addTestRow("simple-library/simple-library.qbs", 0, 0, config);
|
||||
addTestRow("simple-library/simple-library.pro", 0, 0, config);
|
||||
|
||||
// Test that standard headers can be parsed.
|
||||
addTestRow("stdc++11-includes/stdc++11-includes.qbs", 0, config);
|
||||
addTestRow("stdc++11-includes/stdc++11-includes.pro", 0, config);
|
||||
addTestRow("stdc++11-includes/stdc++11-includes.qbs", 0, 0, config);
|
||||
addTestRow("stdc++11-includes/stdc++11-includes.pro", 0, 0, config);
|
||||
|
||||
// Test that qt essential headers can be parsed.
|
||||
addTestRow("qt-essential-includes/qt-essential-includes.qbs", 0, config);
|
||||
addTestRow("qt-essential-includes/qt-essential-includes.pro", 0, config);
|
||||
addTestRow("qt-essential-includes/qt-essential-includes.qbs", 0, 0, config);
|
||||
addTestRow("qt-essential-includes/qt-essential-includes.pro", 0, 0, config);
|
||||
|
||||
// Test that mingw includes can be parsed.
|
||||
addTestRow("mingw-includes/mingw-includes.qbs", 0, config);
|
||||
addTestRow("mingw-includes/mingw-includes.pro", 0, config);
|
||||
addTestRow("mingw-includes/mingw-includes.qbs", 0, 0, config);
|
||||
addTestRow("mingw-includes/mingw-includes.pro", 0, 0, config);
|
||||
|
||||
// Test that tidy and clazy diagnostics are emitted for the same project.
|
||||
addTestRow("clangtidy_clazy/clangtidy_clazy.pro",
|
||||
1 /*tidy*/ + 1 /*clazy*/,
|
||||
configFor("misc-unconventional-assign-operator", "qgetenv"));
|
||||
1, 1, configFor("misc-unconventional-assign-operator", "qgetenv"));
|
||||
}
|
||||
|
||||
void ClangToolsUnitTests::addTestRow(const QByteArray &relativeFilePath,
|
||||
int expectedDiagCount,
|
||||
int expectedDiagCountClangTidy,
|
||||
int expectedDiagCountClazy,
|
||||
const ClangDiagnosticConfig &diagnosticConfig)
|
||||
{
|
||||
const QString absoluteFilePath = m_tmpDir->absolutePath(relativeFilePath);
|
||||
const QString fileName = QFileInfo(absoluteFilePath).fileName();
|
||||
|
||||
QTest::newRow(fileName.toUtf8().constData())
|
||||
<< absoluteFilePath << expectedDiagCount << diagnosticConfig;
|
||||
<< absoluteFilePath << expectedDiagCountClangTidy << expectedDiagCountClazy
|
||||
<< diagnosticConfig;
|
||||
}
|
||||
|
||||
int ClangToolsUnitTests::getTimeout()
|
||||
|
@@ -30,7 +30,7 @@ private slots:
|
||||
|
||||
private:
|
||||
void addTestRow(const QByteArray &relativeFilePath,
|
||||
int expectedDiagCount,
|
||||
int expectedDiagCountClangTidy, int expectedDiagCountClazy,
|
||||
const CppEditor::ClangDiagnosticConfig &diagnosticConfig);
|
||||
|
||||
private:
|
||||
|
Reference in New Issue
Block a user