forked from qt-creator/qt-creator
ClangTools: Add tool that runs clang-tidy and clazy
... over the whole project. Generate and read serialized files to get diagnostics. Change-Id: Iafc25fc70443107a040a995efc038aed35102bbf Reviewed-by: Nikolai Kosjar <nikolai.kosjar@qt.io>
This commit is contained in:
@@ -528,17 +528,12 @@ private:
|
|||||||
if (tidyMode == Mode::Disabled)
|
if (tidyMode == Mode::Disabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QString checks;
|
|
||||||
if (tidyMode == Mode::ChecksPrefixList) {
|
|
||||||
checks = QStringLiteral("-*") + diagnosticConfig.clangTidyChecksPrefixes();
|
|
||||||
} else if (tidyMode == Mode::ChecksString) {
|
|
||||||
checks = diagnosticConfig.clangTidyChecksString();
|
|
||||||
checks = checks.simplified();
|
|
||||||
checks.replace(" ", "");
|
|
||||||
}
|
|
||||||
|
|
||||||
addXclangArg("-add-plugin", "clang-tidy");
|
addXclangArg("-add-plugin", "clang-tidy");
|
||||||
|
|
||||||
|
if (tidyMode == Mode::File)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const QString checks = diagnosticConfig.clangTidyChecks();
|
||||||
if (!checks.isEmpty())
|
if (!checks.isEmpty())
|
||||||
addXclangArg("-plugin-arg-clang-tidy", "-checks=" + checks);
|
addXclangArg("-plugin-arg-clang-tidy", "-checks=" + checks);
|
||||||
}
|
}
|
||||||
|
@@ -226,10 +226,11 @@ void ClangStaticAnalyzerTool::handleStateUpdate()
|
|||||||
Debugger::showPermanentStatusMessage(message);
|
Debugger::showPermanentStatusMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<Diagnostic> ClangStaticAnalyzerTool::read(const QString &filePath,
|
QList<Diagnostic> ClangStaticAnalyzerTool::read(const QString &,
|
||||||
|
const QString &logFilePath,
|
||||||
QString *errorMessage) const
|
QString *errorMessage) const
|
||||||
{
|
{
|
||||||
return LogFileReader::readPlist(filePath, errorMessage);
|
return LogFileReader::readPlist(logFilePath, errorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
@@ -49,7 +49,8 @@ public:
|
|||||||
|
|
||||||
void startTool() final;
|
void startTool() final;
|
||||||
|
|
||||||
QList<Diagnostic> read(const QString &filePath,
|
QList<Diagnostic> read(const QString &,
|
||||||
|
const QString &logFilePath,
|
||||||
QString *errorMessage) const final;
|
QString *errorMessage) const final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
66
src/plugins/clangtools/clangtidyclazyruncontrol.cpp
Normal file
66
src/plugins/clangtools/clangtidyclazyruncontrol.cpp
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2016 The Qt Company Ltd.
|
||||||
|
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "clangtidyclazyruncontrol.h"
|
||||||
|
|
||||||
|
#include "clangtidyclazyrunner.h"
|
||||||
|
#include "clangtidyclazytool.h"
|
||||||
|
|
||||||
|
using namespace ProjectExplorer;
|
||||||
|
|
||||||
|
namespace ClangTools {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
ClangTidyClazyRunControl::ClangTidyClazyRunControl(RunControl *runControl, Target *target)
|
||||||
|
: ClangToolRunControl(runControl, target)
|
||||||
|
{
|
||||||
|
setDisplayName("ClangTidyClazyRunner");
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
ClangToolRunner *ClangTidyClazyRunControl::createRunner()
|
||||||
|
{
|
||||||
|
QTC_ASSERT(!m_clangExecutable.isEmpty(), return 0);
|
||||||
|
QTC_ASSERT(!m_clangLogFileDir.isEmpty(), return 0);
|
||||||
|
|
||||||
|
auto runner = new ClangTidyClazyRunner(m_clangExecutable,
|
||||||
|
m_clangLogFileDir,
|
||||||
|
m_environment,
|
||||||
|
this);
|
||||||
|
connect(runner, &ClangTidyClazyRunner::finishedWithSuccess,
|
||||||
|
this, &ClangTidyClazyRunControl::onRunnerFinishedWithSuccess);
|
||||||
|
connect(runner, &ClangTidyClazyRunner::finishedWithFailure,
|
||||||
|
this, &ClangTidyClazyRunControl::onRunnerFinishedWithFailure);
|
||||||
|
return runner;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClangTool *ClangTidyClazyRunControl::tool()
|
||||||
|
{
|
||||||
|
return ClangTidyClazyTool::instance();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace ClangTools
|
||||||
|
|
47
src/plugins/clangtools/clangtidyclazyruncontrol.h
Normal file
47
src/plugins/clangtools/clangtidyclazyruncontrol.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2016 The Qt Company Ltd.
|
||||||
|
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "clangtoolruncontrol.h"
|
||||||
|
|
||||||
|
namespace ClangTools {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class ClangTidyClazyRunControl final : public ClangToolRunControl
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
ClangTidyClazyRunControl(ProjectExplorer::RunControl *runControl,
|
||||||
|
ProjectExplorer::Target *target);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ClangToolRunner *createRunner() final;
|
||||||
|
ClangTool *tool() final;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace ClangTools
|
101
src/plugins/clangtools/clangtidyclazyrunner.cpp
Normal file
101
src/plugins/clangtools/clangtidyclazyrunner.cpp
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2016 The Qt Company Ltd.
|
||||||
|
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "clangtidyclazyrunner.h"
|
||||||
|
|
||||||
|
#include <cpptools/cppcodemodelsettings.h>
|
||||||
|
#include <cpptools/cpptoolsreuse.h>
|
||||||
|
|
||||||
|
#include <utils/synchronousprocess.h>
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QLoggingCategory>
|
||||||
|
|
||||||
|
static Q_LOGGING_CATEGORY(LOG, "qtc.clangtools.runner")
|
||||||
|
|
||||||
|
namespace ClangTools {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
ClangTidyClazyRunner::ClangTidyClazyRunner(const QString &clangExecutable,
|
||||||
|
const QString &clangLogFileDir,
|
||||||
|
const Utils::Environment &environment,
|
||||||
|
QObject *parent)
|
||||||
|
: ClangToolRunner(clangExecutable,
|
||||||
|
clangLogFileDir,
|
||||||
|
environment,
|
||||||
|
tr("Clang-Tidy and Clazy"),
|
||||||
|
parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void addXclangArg(QStringList &arguments,
|
||||||
|
const QString &argName,
|
||||||
|
const QString &argValue = QString())
|
||||||
|
{
|
||||||
|
arguments << QString("-Xclang")
|
||||||
|
<< argName;
|
||||||
|
if (!argValue.isEmpty()) {
|
||||||
|
arguments << QString("-Xclang")
|
||||||
|
<< argValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList ClangTidyClazyRunner::constructCommandLineArguments(const QStringList &options)
|
||||||
|
{
|
||||||
|
using namespace CppTools;
|
||||||
|
QStringList arguments;
|
||||||
|
|
||||||
|
if (LOG().isDebugEnabled())
|
||||||
|
arguments << QString("-v");
|
||||||
|
|
||||||
|
arguments << QString("-fsyntax-only")
|
||||||
|
<< QString("-serialize-diagnostics")
|
||||||
|
<< QString(m_logFile);
|
||||||
|
|
||||||
|
const ClangDiagnosticConfig config = CppTools::codeModelSettings()->clangDiagnosticConfig();
|
||||||
|
|
||||||
|
const ClangDiagnosticConfig::TidyMode tidyMode = config.clangTidyMode();
|
||||||
|
if (tidyMode != ClangDiagnosticConfig::TidyMode::Disabled) {
|
||||||
|
addXclangArg(arguments, QString("-add-plugin"), QString("clang-tidy"));
|
||||||
|
if (tidyMode != ClangDiagnosticConfig::TidyMode::File) {
|
||||||
|
const QString tidyChecks = config.clangTidyChecks();
|
||||||
|
addXclangArg(arguments, QString("-plugin-arg-clang-tidy"), "-checks=" + tidyChecks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString clazyChecks = config.clazyChecks();
|
||||||
|
if (!clazyChecks.isEmpty()) {
|
||||||
|
addXclangArg(arguments, QString("-add-plugin"), QString("clang-lazy"));
|
||||||
|
addXclangArg(arguments, QString("-plugin-arg-clang-lazy"), config.clazyChecks());
|
||||||
|
}
|
||||||
|
|
||||||
|
arguments += options;
|
||||||
|
arguments << QDir::toNativeSeparators(filePath());
|
||||||
|
return arguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace ClangTools
|
47
src/plugins/clangtools/clangtidyclazyrunner.h
Normal file
47
src/plugins/clangtools/clangtidyclazyrunner.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2016 The Qt Company Ltd.
|
||||||
|
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "clangtoolrunner.h"
|
||||||
|
|
||||||
|
namespace ClangTools {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class ClangTidyClazyRunner final : public ClangToolRunner
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
ClangTidyClazyRunner(const QString &clangExecutable,
|
||||||
|
const QString &clangLogFileDir,
|
||||||
|
const Utils::Environment &environment,
|
||||||
|
QObject *parent = nullptr);
|
||||||
|
protected:
|
||||||
|
QStringList constructCommandLineArguments(const QStringList &options) final;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace ClangTools
|
196
src/plugins/clangtools/clangtidyclazytool.cpp
Normal file
196
src/plugins/clangtools/clangtidyclazytool.cpp
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2016 The Qt Company Ltd.
|
||||||
|
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "clangtidyclazytool.h"
|
||||||
|
|
||||||
|
#include "clangtoolsconstants.h"
|
||||||
|
#include "clangtoolsdiagnosticmodel.h"
|
||||||
|
#include "clangtoolslogfilereader.h"
|
||||||
|
#include "clangtidyclazyruncontrol.h"
|
||||||
|
|
||||||
|
#include <coreplugin/actionmanager/actioncontainer.h>
|
||||||
|
#include <coreplugin/actionmanager/actionmanager.h>
|
||||||
|
|
||||||
|
#include <debugger/analyzer/analyzermanager.h>
|
||||||
|
|
||||||
|
#include <projectexplorer/kitinformation.h>
|
||||||
|
#include <projectexplorer/projectexplorer.h>
|
||||||
|
#include <projectexplorer/projectexplorericons.h>
|
||||||
|
#include <projectexplorer/target.h>
|
||||||
|
#include <projectexplorer/session.h>
|
||||||
|
|
||||||
|
#include <utils/utilsicons.h>
|
||||||
|
|
||||||
|
#include <QAction>
|
||||||
|
|
||||||
|
using namespace Core;
|
||||||
|
using namespace Debugger;
|
||||||
|
using namespace ProjectExplorer;
|
||||||
|
using namespace Utils;
|
||||||
|
|
||||||
|
namespace ClangTools {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
static ClangTidyClazyTool *s_instance;
|
||||||
|
|
||||||
|
ClangTidyClazyTool::ClangTidyClazyTool()
|
||||||
|
: ClangTool("Clang-Tidy and Clazy")
|
||||||
|
{
|
||||||
|
setObjectName("ClangTidyClazyTool");
|
||||||
|
s_instance = this;
|
||||||
|
|
||||||
|
m_diagnosticView = new Debugger::DetailedErrorView;
|
||||||
|
initDiagnosticView();
|
||||||
|
m_diagnosticView->setModel(m_diagnosticModel);
|
||||||
|
m_diagnosticView->setObjectName(QLatin1String("ClangTidyClazyIssuesView"));
|
||||||
|
m_diagnosticView->setWindowTitle(tr("Clang-Tidy and Clazy Issues"));
|
||||||
|
|
||||||
|
ActionContainer *menu = ActionManager::actionContainer(Debugger::Constants::M_DEBUG_ANALYZER);
|
||||||
|
const QString toolTip = tr("Clang-Tidy and Clazy use a customized Clang executable from the "
|
||||||
|
"Clang project to search for errors and warnings.");
|
||||||
|
|
||||||
|
Debugger::registerPerspective(ClangTidyClazyPerspectiveId, new Perspective(
|
||||||
|
tr("Clang-Tidy and Clazy"),
|
||||||
|
{{ClangTidyClazyDockId, m_diagnosticView, {}, Perspective::SplitVertical}}
|
||||||
|
));
|
||||||
|
|
||||||
|
auto *action = new QAction(tr("Clang-Tidy and Clazy"), this);
|
||||||
|
action->setToolTip(toolTip);
|
||||||
|
menu->addAction(ActionManager::registerAction(action, "ClangTidyClazy.Action"),
|
||||||
|
Debugger::Constants::G_ANALYZER_TOOLS);
|
||||||
|
QObject::connect(action, &QAction::triggered, this, &ClangTidyClazyTool::startTool);
|
||||||
|
QObject::connect(m_startAction, &QAction::triggered, action, &QAction::triggered);
|
||||||
|
QObject::connect(m_startAction, &QAction::changed, action, [action, this] {
|
||||||
|
action->setEnabled(m_startAction->isEnabled());
|
||||||
|
});
|
||||||
|
|
||||||
|
ToolbarDescription tidyClazyToolbar;
|
||||||
|
tidyClazyToolbar.addAction(m_startAction);
|
||||||
|
tidyClazyToolbar.addAction(m_stopAction);
|
||||||
|
Debugger::registerToolbar(ClangTidyClazyPerspectiveId, tidyClazyToolbar);
|
||||||
|
|
||||||
|
updateRunActions();
|
||||||
|
|
||||||
|
connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::updateRunActions,
|
||||||
|
this, &ClangTidyClazyTool::updateRunActions);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ClangTidyClazyTool *ClangTidyClazyTool::instance()
|
||||||
|
{
|
||||||
|
return s_instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClangTidyClazyTool::startTool()
|
||||||
|
{
|
||||||
|
auto runControl = new RunControl(nullptr, Constants::CLANGTIDYCLAZY_RUN_MODE);
|
||||||
|
runControl->setDisplayName(tr("Clang-Tidy and Clazy"));
|
||||||
|
runControl->setIcon(ProjectExplorer::Icons::ANALYZER_START_SMALL_TOOLBAR);
|
||||||
|
|
||||||
|
Project *project = SessionManager::startupProject();
|
||||||
|
QTC_ASSERT(project, return);
|
||||||
|
|
||||||
|
auto clangTool = new ClangTidyClazyRunControl(runControl, project->activeTarget());
|
||||||
|
|
||||||
|
m_stopAction->disconnect();
|
||||||
|
connect(m_stopAction, &QAction::triggered, runControl, [runControl] {
|
||||||
|
runControl->appendMessage(tr("Clang-Tidy and Clazy tool stopped by user."),
|
||||||
|
NormalMessageFormat);
|
||||||
|
runControl->initiateStop();
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(runControl, &RunControl::stopped, this, [this, clangTool] {
|
||||||
|
bool success = clangTool->success();
|
||||||
|
setToolBusy(false);
|
||||||
|
m_running = false;
|
||||||
|
handleStateUpdate();
|
||||||
|
updateRunActions();
|
||||||
|
emit finished(success);
|
||||||
|
});
|
||||||
|
|
||||||
|
Debugger::selectPerspective(ClangTidyClazyPerspectiveId);
|
||||||
|
|
||||||
|
m_diagnosticModel->clear();
|
||||||
|
setToolBusy(true);
|
||||||
|
m_running = true;
|
||||||
|
handleStateUpdate();
|
||||||
|
updateRunActions();
|
||||||
|
|
||||||
|
ProjectExplorerPlugin::startRunControl(runControl);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClangTidyClazyTool::updateRunActions()
|
||||||
|
{
|
||||||
|
if (m_toolBusy) {
|
||||||
|
m_startAction->setEnabled(false);
|
||||||
|
QString tooltipText = tr("Clang-Tidy and Clazy are still running.");
|
||||||
|
m_startAction->setToolTip(tooltipText);
|
||||||
|
m_stopAction->setEnabled(true);
|
||||||
|
} else {
|
||||||
|
QString toolTip = tr("Start Clang-Tidy and Clazy.");
|
||||||
|
Project *project = SessionManager::startupProject();
|
||||||
|
Target *target = project ? project->activeTarget() : nullptr;
|
||||||
|
const Core::Id cxx = ProjectExplorer::Constants::CXX_LANGUAGE_ID;
|
||||||
|
bool canRun = target && project->projectLanguages().contains(cxx)
|
||||||
|
&& ToolChainKitInformation::toolChain(target->kit(), cxx);
|
||||||
|
if (!canRun)
|
||||||
|
toolTip = tr("This is not a C++ project.");
|
||||||
|
|
||||||
|
m_startAction->setToolTip(toolTip);
|
||||||
|
m_startAction->setEnabled(canRun);
|
||||||
|
m_stopAction->setEnabled(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClangTidyClazyTool::handleStateUpdate()
|
||||||
|
{
|
||||||
|
QTC_ASSERT(m_diagnosticModel, return);
|
||||||
|
|
||||||
|
const int issuesFound = m_diagnosticModel->diagnostics().count();
|
||||||
|
QString message;
|
||||||
|
if (m_running)
|
||||||
|
message = tr("Clang-Tidy and Clazy are running.");
|
||||||
|
else
|
||||||
|
message = tr("Clang-Tidy and Clazy finished.");
|
||||||
|
|
||||||
|
message += QLatin1Char(' ');
|
||||||
|
if (issuesFound == 0)
|
||||||
|
message += tr("No issues found.");
|
||||||
|
else
|
||||||
|
message += tr("%n issues found.", nullptr, issuesFound);
|
||||||
|
|
||||||
|
Debugger::showPermanentStatusMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<Diagnostic> ClangTidyClazyTool::read(const QString &filePath,
|
||||||
|
const QString &logFilePath,
|
||||||
|
QString *errorMessage) const
|
||||||
|
{
|
||||||
|
return LogFileReader::readSerialized(filePath, logFilePath, errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace ClangTools
|
||||||
|
|
58
src/plugins/clangtools/clangtidyclazytool.h
Normal file
58
src/plugins/clangtools/clangtidyclazytool.h
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2016 The Qt Company Ltd.
|
||||||
|
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "clangtool.h"
|
||||||
|
|
||||||
|
namespace ClangTools {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
const char ClangTidyClazyPerspectiveId[] = "ClangTidyClazy.Perspective";
|
||||||
|
const char ClangTidyClazyDockId[] = "ClangTidyClazy.Dock";
|
||||||
|
|
||||||
|
class ClangTidyClazyTool final : public ClangTool
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
ClangTidyClazyTool();
|
||||||
|
|
||||||
|
static ClangTidyClazyTool *instance();
|
||||||
|
|
||||||
|
void startTool() final;
|
||||||
|
|
||||||
|
QList<Diagnostic> read(const QString &filePath,
|
||||||
|
const QString &logFilePath,
|
||||||
|
QString *errorMessage) const final;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void handleStateUpdate() final;
|
||||||
|
|
||||||
|
void updateRunActions();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace ClangTools
|
@@ -47,6 +47,7 @@ public:
|
|||||||
virtual void startTool() = 0;
|
virtual void startTool() = 0;
|
||||||
|
|
||||||
virtual QList<Diagnostic> read(const QString &filePath,
|
virtual QList<Diagnostic> read(const QString &filePath,
|
||||||
|
const QString &logFilePath,
|
||||||
QString *errorMessage) const = 0;
|
QString *errorMessage) const = 0;
|
||||||
|
|
||||||
// For testing.
|
// For testing.
|
||||||
|
@@ -351,12 +351,13 @@ void ClangToolRunControl::analyzeNextFile()
|
|||||||
Utils::StdOutFormat);
|
Utils::StdOutFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClangToolRunControl::onRunnerFinishedWithSuccess(const QString &logFilePath)
|
void ClangToolRunControl::onRunnerFinishedWithSuccess(const QString &filePath,
|
||||||
|
const QString &logFilePath)
|
||||||
{
|
{
|
||||||
qCDebug(LOG) << "onRunnerFinishedWithSuccess:" << logFilePath;
|
qCDebug(LOG) << "onRunnerFinishedWithSuccess:" << logFilePath;
|
||||||
|
|
||||||
QString errorMessage;
|
QString errorMessage;
|
||||||
const QList<Diagnostic> diagnostics = tool()->read(logFilePath, &errorMessage);
|
const QList<Diagnostic> diagnostics = tool()->read(filePath, logFilePath, &errorMessage);
|
||||||
if (!errorMessage.isEmpty()) {
|
if (!errorMessage.isEmpty()) {
|
||||||
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();
|
||||||
|
@@ -73,7 +73,7 @@ protected:
|
|||||||
|
|
||||||
virtual ClangToolRunner *createRunner() = 0;
|
virtual ClangToolRunner *createRunner() = 0;
|
||||||
|
|
||||||
void onRunnerFinishedWithSuccess(const QString &logFilePath);
|
void onRunnerFinishedWithSuccess(const QString &filePath, const QString &logFilePath);
|
||||||
void onRunnerFinishedWithFailure(const QString &errorMessage, const QString &errorDetails);
|
void onRunnerFinishedWithFailure(const QString &errorMessage, const QString &errorDetails);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@@ -121,7 +121,7 @@ void ClangToolRunner::onProcessFinished(int exitCode, QProcess::ExitStatus exitS
|
|||||||
if (exitCode == 0) {
|
if (exitCode == 0) {
|
||||||
qCDebug(LOG).noquote() << "Output:\n" << Utils::SynchronousProcess::normalizeNewlines(
|
qCDebug(LOG).noquote() << "Output:\n" << Utils::SynchronousProcess::normalizeNewlines(
|
||||||
QString::fromLocal8Bit(m_processOutput));
|
QString::fromLocal8Bit(m_processOutput));
|
||||||
emit finishedWithSuccess(actualLogFile());
|
emit finishedWithSuccess(m_filePath, actualLogFile());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
emit finishedWithFailure(finishedWithBadExitCode(m_name, exitCode), processCommandlineAndOutput());
|
emit finishedWithFailure(finishedWithBadExitCode(m_name, exitCode), processCommandlineAndOutput());
|
||||||
|
@@ -56,7 +56,7 @@ public:
|
|||||||
|
|
||||||
signals:
|
signals:
|
||||||
void started();
|
void started();
|
||||||
void finishedWithSuccess(const QString &logFilePath);
|
void finishedWithSuccess(const QString &filePath, const QString &logFilePath);
|
||||||
void finishedWithFailure(const QString &errorMessage, const QString &errorDetails);
|
void finishedWithFailure(const QString &errorMessage, const QString &errorDetails);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@@ -1,4 +1,8 @@
|
|||||||
include(../../qtcreatorplugin.pri)
|
include(../../qtcreatorplugin.pri)
|
||||||
|
include(../../shared/clang/clang_installation.pri)
|
||||||
|
|
||||||
|
LIBS += $$LIBCLANG_LIBS
|
||||||
|
INCLUDEPATH += $$LLVM_INCLUDEPATH
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
clangstaticanalyzerconfigwidget.cpp \
|
clangstaticanalyzerconfigwidget.cpp \
|
||||||
@@ -9,6 +13,9 @@ SOURCES += \
|
|||||||
clangstaticanalyzerruncontrol.cpp \
|
clangstaticanalyzerruncontrol.cpp \
|
||||||
clangstaticanalyzerrunner.cpp \
|
clangstaticanalyzerrunner.cpp \
|
||||||
clangstaticanalyzertool.cpp \
|
clangstaticanalyzertool.cpp \
|
||||||
|
clangtidyclazyruncontrol.cpp \
|
||||||
|
clangtidyclazyrunner.cpp \
|
||||||
|
clangtidyclazytool.cpp \
|
||||||
clangtool.cpp \
|
clangtool.cpp \
|
||||||
clangtoolruncontrol.cpp \
|
clangtoolruncontrol.cpp \
|
||||||
clangtoolrunner.cpp \
|
clangtoolrunner.cpp \
|
||||||
@@ -28,6 +35,9 @@ HEADERS += \
|
|||||||
clangstaticanalyzerruncontrol.h \
|
clangstaticanalyzerruncontrol.h \
|
||||||
clangstaticanalyzerrunner.h \
|
clangstaticanalyzerrunner.h \
|
||||||
clangstaticanalyzertool.h \
|
clangstaticanalyzertool.h \
|
||||||
|
clangtidyclazyruncontrol.h \
|
||||||
|
clangtidyclazyrunner.h \
|
||||||
|
clangtidyclazytool.h \
|
||||||
clangtool.h \
|
clangtool.h \
|
||||||
clangtoolruncontrol.h \
|
clangtoolruncontrol.h \
|
||||||
clangtoolrunner.h \
|
clangtoolrunner.h \
|
||||||
|
@@ -10,6 +10,7 @@ QtcPlugin {
|
|||||||
Depends { name: "ProjectExplorer" }
|
Depends { name: "ProjectExplorer" }
|
||||||
Depends { name: "QtcSsh" }
|
Depends { name: "QtcSsh" }
|
||||||
Depends { name: "Utils" }
|
Depends { name: "Utils" }
|
||||||
|
Depends { name: "libclang"; required: false }
|
||||||
|
|
||||||
Depends { name: "Qt.widgets" }
|
Depends { name: "Qt.widgets" }
|
||||||
|
|
||||||
@@ -18,6 +19,13 @@ QtcPlugin {
|
|||||||
"QmakeProjectManager",
|
"QmakeProjectManager",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
condition: libclang.present
|
||||||
|
|
||||||
|
cpp.includePaths: base.concat(libclang.llvmIncludeDir)
|
||||||
|
cpp.libraryPaths: base.concat(libclang.llvmLibDir)
|
||||||
|
cpp.dynamicLibraries: base.concat(libclang.llvmLibs)
|
||||||
|
cpp.rpaths: base.concat(libclang.llvmLibDir)
|
||||||
|
|
||||||
files: [
|
files: [
|
||||||
"clangstaticanalyzerconfigwidget.cpp",
|
"clangstaticanalyzerconfigwidget.cpp",
|
||||||
"clangstaticanalyzerconfigwidget.h",
|
"clangstaticanalyzerconfigwidget.h",
|
||||||
@@ -37,6 +45,12 @@ QtcPlugin {
|
|||||||
"clangstaticanalyzerrunner.h",
|
"clangstaticanalyzerrunner.h",
|
||||||
"clangstaticanalyzertool.cpp",
|
"clangstaticanalyzertool.cpp",
|
||||||
"clangstaticanalyzertool.h",
|
"clangstaticanalyzertool.h",
|
||||||
|
"clangtidyclazyruncontrol.cpp",
|
||||||
|
"clangtidyclazyruncontrol.h",
|
||||||
|
"clangtidyclazyrunner.cpp",
|
||||||
|
"clangtidyclazyrunner.h",
|
||||||
|
"clangtidyclazytool.cpp",
|
||||||
|
"clangtidyclazytool.h",
|
||||||
"clangtool.cpp",
|
"clangtool.cpp",
|
||||||
"clangtool.h",
|
"clangtool.h",
|
||||||
"clangtoolruncontrol.cpp",
|
"clangtoolruncontrol.cpp",
|
||||||
|
@@ -298,6 +298,8 @@ QVariant ExplainingStepItem::data(int column, int role) const
|
|||||||
}
|
}
|
||||||
case Qt::ToolTipRole:
|
case Qt::ToolTipRole:
|
||||||
return createExplainingStepToolTipString(m_step);
|
return createExplainingStepToolTipString(m_step);
|
||||||
|
case Qt::DecorationRole:
|
||||||
|
return (m_step.message.startsWith("fix-it:")) ? iconData("fix-it") : QVariant();
|
||||||
default:
|
default:
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
@@ -33,8 +33,13 @@
|
|||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
#include <QXmlStreamReader>
|
#include <QXmlStreamReader>
|
||||||
|
|
||||||
|
#include <utils/executeondestruction.h>
|
||||||
|
#include <utils/fileutils.h>
|
||||||
|
#include <utils/hostosinfo.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
|
#include <clang-c/Index.h>
|
||||||
|
|
||||||
namespace ClangTools {
|
namespace ClangTools {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
@@ -74,6 +79,12 @@ private:
|
|||||||
QList<Diagnostic> m_diagnostics;
|
QList<Diagnostic> m_diagnostics;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ClangSerializedDiagnosticsReader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QList<Diagnostic> read(const QString &filePath, const QString &logFilePath);
|
||||||
|
};
|
||||||
|
|
||||||
static bool checkFilePath(const QString &filePath, QString *errorMessage)
|
static bool checkFilePath(const QString &filePath, QString *errorMessage)
|
||||||
{
|
{
|
||||||
QFileInfo fi(filePath);
|
QFileInfo fi(filePath);
|
||||||
@@ -133,6 +144,16 @@ QList<Diagnostic> LogFileReader::readPlist(const QString &filePath, QString *err
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<Diagnostic> LogFileReader::readSerialized(const QString &filePath, const QString &logFilePath,
|
||||||
|
QString *errorMessage)
|
||||||
|
{
|
||||||
|
if (!checkFilePath(filePath, errorMessage))
|
||||||
|
return QList<Diagnostic>();
|
||||||
|
|
||||||
|
ClangSerializedDiagnosticsReader reader;
|
||||||
|
return reader.read(filePath, logFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
ClangStaticAnalyzerLogFileReader::ClangStaticAnalyzerLogFileReader(const QString &filePath)
|
ClangStaticAnalyzerLogFileReader::ClangStaticAnalyzerLogFileReader(const QString &filePath)
|
||||||
: m_filePath(filePath)
|
: m_filePath(filePath)
|
||||||
{
|
{
|
||||||
@@ -390,5 +411,157 @@ int ClangStaticAnalyzerLogFileReader::readInteger(bool *convertedSuccessfully)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QString fromCXString(CXString &&cxString)
|
||||||
|
{
|
||||||
|
QString result = QString::fromUtf8(clang_getCString(cxString));
|
||||||
|
clang_disposeString(cxString);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Debugger::DiagnosticLocation diagLocationFromSourceLocation(CXSourceLocation cxLocation)
|
||||||
|
{
|
||||||
|
CXFile file;
|
||||||
|
unsigned line;
|
||||||
|
unsigned column;
|
||||||
|
clang_getSpellingLocation(cxLocation, &file, &line, &column, nullptr);
|
||||||
|
|
||||||
|
Debugger::DiagnosticLocation location;
|
||||||
|
location.filePath = fromCXString(clang_getFileName(file));
|
||||||
|
location.line = line;
|
||||||
|
location.column = column;
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
|
||||||
|
static QString cxDiagnosticType(const CXDiagnostic cxDiagnostic)
|
||||||
|
{
|
||||||
|
const CXDiagnosticSeverity severity = clang_getDiagnosticSeverity(cxDiagnostic);
|
||||||
|
switch (severity) {
|
||||||
|
case CXDiagnostic_Note:
|
||||||
|
return QString("note");
|
||||||
|
case CXDiagnostic_Warning:
|
||||||
|
return QString("warning");
|
||||||
|
case CXDiagnostic_Error:
|
||||||
|
return QString("error");
|
||||||
|
case CXDiagnostic_Fatal:
|
||||||
|
return QString("fatal");
|
||||||
|
case CXDiagnostic_Ignored:
|
||||||
|
return QString("ignored");
|
||||||
|
}
|
||||||
|
return QString("ignored");
|
||||||
|
}
|
||||||
|
|
||||||
|
static ExplainingStep buildChildDiagnostic(const CXDiagnostic cxDiagnostic)
|
||||||
|
{
|
||||||
|
ExplainingStep diagnosticStep;
|
||||||
|
QString type = cxDiagnosticType(cxDiagnostic);
|
||||||
|
if (type == QStringLiteral("ignored"))
|
||||||
|
return diagnosticStep;
|
||||||
|
|
||||||
|
const CXSourceLocation cxLocation = clang_getDiagnosticLocation(cxDiagnostic);
|
||||||
|
diagnosticStep.location = diagLocationFromSourceLocation(cxLocation);
|
||||||
|
diagnosticStep.message = type + ": " + fromCXString(clang_getDiagnosticSpelling(cxDiagnostic));
|
||||||
|
return diagnosticStep;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isInvalidDiagnosticLocation(const Diagnostic &diagnostic, const ExplainingStep &child,
|
||||||
|
const QString &nativeFilePath)
|
||||||
|
{
|
||||||
|
// When main file is considered included by itself - this diagnostic has invalid location.
|
||||||
|
// This case usually happens when original diagnostic comes from system header but
|
||||||
|
// has main file name set in the source location instead (which is incorrect).
|
||||||
|
return child.message.indexOf(nativeFilePath) >= 0
|
||||||
|
&& child.message.indexOf("in file included from") >= 0
|
||||||
|
&& diagnostic.location.filePath == nativeFilePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ExplainingStep buildFixIt(const CXDiagnostic cxDiagnostic, unsigned index)
|
||||||
|
{
|
||||||
|
ExplainingStep fixItStep;
|
||||||
|
CXSourceRange cxFixItRange;
|
||||||
|
fixItStep.message = "fix-it: " + fromCXString(clang_getDiagnosticFixIt(cxDiagnostic, index,
|
||||||
|
&cxFixItRange));
|
||||||
|
fixItStep.location = diagLocationFromSourceLocation(clang_getRangeStart(cxFixItRange));
|
||||||
|
fixItStep.ranges.push_back(fixItStep.location);
|
||||||
|
fixItStep.ranges.push_back(diagLocationFromSourceLocation(clang_getRangeEnd(cxFixItRange)));
|
||||||
|
return fixItStep;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Diagnostic buildDiagnostic(const CXDiagnostic cxDiagnostic, const QString &nativeFilePath)
|
||||||
|
{
|
||||||
|
Diagnostic diagnostic;
|
||||||
|
diagnostic.type = cxDiagnosticType(cxDiagnostic);
|
||||||
|
if (diagnostic.type == QStringLiteral("ignored"))
|
||||||
|
return diagnostic;
|
||||||
|
|
||||||
|
const CXSourceLocation cxLocation = clang_getDiagnosticLocation(cxDiagnostic);
|
||||||
|
if (clang_Location_isInSystemHeader(cxLocation))
|
||||||
|
return diagnostic;
|
||||||
|
|
||||||
|
diagnostic.location = diagLocationFromSourceLocation(cxLocation);
|
||||||
|
if (diagnostic.location.filePath != nativeFilePath)
|
||||||
|
return diagnostic;
|
||||||
|
|
||||||
|
CXDiagnosticSet cxChildDiagnostics = clang_getChildDiagnostics(cxDiagnostic);
|
||||||
|
Utils::ExecuteOnDestruction onBuildExit([&]() {
|
||||||
|
clang_disposeDiagnosticSet(cxChildDiagnostics);
|
||||||
|
});
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < clang_getNumDiagnosticsInSet(cxChildDiagnostics); ++i) {
|
||||||
|
CXDiagnostic cxDiagnostic = clang_getDiagnosticInSet(cxChildDiagnostics, i);
|
||||||
|
Utils::ExecuteOnDestruction cleanUpDiagnostic([&]() {
|
||||||
|
clang_disposeDiagnostic(cxDiagnostic);
|
||||||
|
});
|
||||||
|
const ExplainingStep diagnosticStep = buildChildDiagnostic(cxDiagnostic);
|
||||||
|
if (diagnosticStep.isValid())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (isInvalidDiagnosticLocation(diagnostic, diagnosticStep, nativeFilePath))
|
||||||
|
return diagnostic;
|
||||||
|
|
||||||
|
diagnostic.explainingSteps.push_back(diagnosticStep);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < clang_getDiagnosticNumFixIts(cxDiagnostic); ++i)
|
||||||
|
diagnostic.explainingSteps.push_back(buildFixIt(cxDiagnostic, i));
|
||||||
|
|
||||||
|
diagnostic.description = fromCXString(clang_getDiagnosticSpelling(cxDiagnostic));
|
||||||
|
diagnostic.category = fromCXString(clang_getDiagnosticCategoryText(cxDiagnostic));
|
||||||
|
|
||||||
|
return diagnostic;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<Diagnostic> ClangSerializedDiagnosticsReader::read(const QString &filePath,
|
||||||
|
const QString &logFilePath)
|
||||||
|
{
|
||||||
|
QList<Diagnostic> list;
|
||||||
|
CXLoadDiag_Error error;
|
||||||
|
CXString errorString;
|
||||||
|
|
||||||
|
CXDiagnosticSet diagnostics = clang_loadDiagnostics(logFilePath.toStdString().c_str(),
|
||||||
|
&error,
|
||||||
|
&errorString);
|
||||||
|
if (error != CXLoadDiag_None || !diagnostics)
|
||||||
|
return list;
|
||||||
|
|
||||||
|
Utils::ExecuteOnDestruction onReadExit([&]() {
|
||||||
|
clang_disposeDiagnosticSet(diagnostics);
|
||||||
|
});
|
||||||
|
|
||||||
|
const QString nativeFilePath = QDir::toNativeSeparators(filePath);
|
||||||
|
for (unsigned i = 0; i < clang_getNumDiagnosticsInSet(diagnostics); ++i) {
|
||||||
|
CXDiagnostic cxDiagnostic = clang_getDiagnosticInSet(diagnostics, i);
|
||||||
|
Utils::ExecuteOnDestruction cleanUpDiagnostic([&]() {
|
||||||
|
clang_disposeDiagnostic(cxDiagnostic);
|
||||||
|
});
|
||||||
|
const Diagnostic diagnostic = buildDiagnostic(cxDiagnostic, nativeFilePath);
|
||||||
|
if (!diagnostic.isValid())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
list.push_back(diagnostic);
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace ClangTools
|
} // namespace ClangTools
|
||||||
|
@@ -30,6 +30,8 @@
|
|||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
|
|
||||||
|
namespace Utils { class FileName; }
|
||||||
|
|
||||||
namespace ClangTools {
|
namespace ClangTools {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
@@ -38,6 +40,9 @@ class LogFileReader
|
|||||||
Q_DECLARE_TR_FUNCTIONS(ClangTools::Internal::LogFileReader)
|
Q_DECLARE_TR_FUNCTIONS(ClangTools::Internal::LogFileReader)
|
||||||
public:
|
public:
|
||||||
static QList<Diagnostic> readPlist(const QString &filePath, QString *errorMessage);
|
static QList<Diagnostic> readPlist(const QString &filePath, QString *errorMessage);
|
||||||
|
static QList<Diagnostic> readSerialized(const QString &filePath,
|
||||||
|
const QString &logFilePath,
|
||||||
|
QString *errorMessage);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
#include "clangstaticanalyzerprojectsettingswidget.h"
|
#include "clangstaticanalyzerprojectsettingswidget.h"
|
||||||
#include "clangstaticanalyzerruncontrol.h"
|
#include "clangstaticanalyzerruncontrol.h"
|
||||||
#include "clangstaticanalyzertool.h"
|
#include "clangstaticanalyzertool.h"
|
||||||
|
#include "clangtidyclazytool.h"
|
||||||
|
|
||||||
#ifdef WITH_TESTS
|
#ifdef WITH_TESTS
|
||||||
#include "clangstaticanalyzerpreconfiguredsessiontests.h"
|
#include "clangstaticanalyzerpreconfiguredsessiontests.h"
|
||||||
@@ -104,6 +105,7 @@ class ClangToolsPluginPrivate
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ClangStaticAnalyzerTool staticAnalyzerTool;
|
ClangStaticAnalyzerTool staticAnalyzerTool;
|
||||||
|
ClangTidyClazyTool clangTidyClazyTool;
|
||||||
ClangStaticAnalyzerOptionsPage optionsPage;
|
ClangStaticAnalyzerOptionsPage optionsPage;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -94,6 +94,19 @@ void ClangDiagnosticConfig::setClangTidyMode(TidyMode mode)
|
|||||||
m_clangTidyMode = mode;
|
m_clangTidyMode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString ClangDiagnosticConfig::clangTidyChecks() const
|
||||||
|
{
|
||||||
|
QString checks;
|
||||||
|
if (m_clangTidyMode == TidyMode::ChecksPrefixList) {
|
||||||
|
checks = QStringLiteral("-*") + clangTidyChecksPrefixes();
|
||||||
|
} else if (m_clangTidyMode == TidyMode::ChecksString) {
|
||||||
|
checks = clangTidyChecksString();
|
||||||
|
checks = checks.simplified();
|
||||||
|
checks.replace(" ", "");
|
||||||
|
}
|
||||||
|
return checks;
|
||||||
|
}
|
||||||
|
|
||||||
QString ClangDiagnosticConfig::clangTidyChecksPrefixes() const
|
QString ClangDiagnosticConfig::clangTidyChecksPrefixes() const
|
||||||
{
|
{
|
||||||
return m_clangTidyChecksPrefixes;
|
return m_clangTidyChecksPrefixes;
|
||||||
|
@@ -54,6 +54,8 @@ public:
|
|||||||
QStringList clangOptions() const;
|
QStringList clangOptions() const;
|
||||||
void setClangOptions(const QStringList &options);
|
void setClangOptions(const QStringList &options);
|
||||||
|
|
||||||
|
QString clangTidyChecks() const;
|
||||||
|
|
||||||
QString clangTidyChecksPrefixes() const;
|
QString clangTidyChecksPrefixes() const;
|
||||||
void setClangTidyChecksPrefixes(const QString &checks);
|
void setClangTidyChecksPrefixes(const QString &checks);
|
||||||
|
|
||||||
|
@@ -4,6 +4,9 @@ TARGET = tst_clangtoolslogfilereader
|
|||||||
|
|
||||||
DEFINES += SRCDIR=\\\"$$PWD/\\\"
|
DEFINES += SRCDIR=\\\"$$PWD/\\\"
|
||||||
|
|
||||||
|
LIBS += $$LIBCLANG_LIBS
|
||||||
|
INCLUDEPATH += $$LLVM_INCLUDEPATH
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
tst_clangtoolslogfilereader.cpp \
|
tst_clangtoolslogfilereader.cpp \
|
||||||
$$PLUGINDIR/clangtoolsdiagnostic.cpp \
|
$$PLUGINDIR/clangtoolsdiagnostic.cpp \
|
||||||
|
@@ -3,8 +3,18 @@ import "../clangtoolsautotest.qbs" as ClangToolsAutotest
|
|||||||
|
|
||||||
ClangToolsAutotest {
|
ClangToolsAutotest {
|
||||||
name: "ClangToolsLogFileReader Autotest"
|
name: "ClangToolsLogFileReader Autotest"
|
||||||
|
|
||||||
|
Depends { name: "libclang"; required: false }
|
||||||
|
|
||||||
cpp.defines: base.concat('SRCDIR="' + sourceDirectory + '"')
|
cpp.defines: base.concat('SRCDIR="' + sourceDirectory + '"')
|
||||||
|
|
||||||
|
condition: libclang.present
|
||||||
|
|
||||||
|
cpp.includePaths: base.concat(libclang.llvmIncludeDir)
|
||||||
|
cpp.libraryPaths: base.concat(libclang.llvmLibDir)
|
||||||
|
cpp.dynamicLibraries: base.concat(libclang.llvmLibs)
|
||||||
|
cpp.rpaths: base.concat(libclang.llvmLibDir)
|
||||||
|
|
||||||
Group {
|
Group {
|
||||||
name: "sources from plugin"
|
name: "sources from plugin"
|
||||||
prefix: pluginDir + '/'
|
prefix: pluginDir + '/'
|
||||||
|
Reference in New Issue
Block a user