forked from qt-creator/qt-creator
Cppcheck: Add cppcheck static analysis tool
Automatically checks currently opened documents and displays results via text marks/annotations. CppcheckTrigger detects when to check files or clear results. CppcheckTextMarkManager stores/clears text marks with checks' results. CppcheckTool generates run arguments and parses output. CppcheckRunner runs cppcheck binary. CppcheckOptions configures CppcheckTool. Task-number: QTCREATORBUG-20418 Change-Id: I8eafeac7af6137d2c9061ae75d4a56c85b3b5a2d Reviewed-by: Alessandro Portale <alessandro.portale@qt.io> Reviewed-by: Marco Bubke <marco.bubke@qt.io>
This commit is contained in:
20
src/plugins/cppcheck/Cppcheck.json.in
Normal file
20
src/plugins/cppcheck/Cppcheck.json.in
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
\"Name\" : \"Cppcheck\",
|
||||
\"Version\" : \"$$QTCREATOR_VERSION\",
|
||||
\"CompatVersion\" : \"$$QTCREATOR_COMPAT_VERSION\",
|
||||
\"Experimental\" : true,
|
||||
\"Vendor\" : \"Sergey Morozov\",
|
||||
\"Copyright\" : \"(C) 2018 Sergey Morozov, (C) $$QTCREATOR_COPYRIGHT_YEAR The Qt Company Ltd\",
|
||||
\"License\" : [ \"Commercial 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.\"
|
||||
],
|
||||
\"Category\" : \"Code Analyzer\",
|
||||
\"Description\" : \"Cppcheck static analyzer tool integration. See http://cppcheck.sourceforge.net.\",
|
||||
\"Url\" : \"http://www.qt.io\",
|
||||
$$dependencyList
|
||||
}
|
||||
21
src/plugins/cppcheck/cppcheck.pro
Normal file
21
src/plugins/cppcheck/cppcheck.pro
Normal file
@@ -0,0 +1,21 @@
|
||||
include(../../qtcreatorplugin.pri)
|
||||
|
||||
SOURCES += \
|
||||
cppcheckoptions.cpp \
|
||||
cppcheckplugin.cpp \
|
||||
cppcheckrunner.cpp \
|
||||
cppchecktextmark.cpp \
|
||||
cppchecktextmarkmanager.cpp \
|
||||
cppchecktool.cpp \
|
||||
cppchecktrigger.cpp
|
||||
|
||||
HEADERS += \
|
||||
cppcheckconstants.h \
|
||||
cppcheckdiagnostic.h \
|
||||
cppcheckoptions.h \
|
||||
cppcheckplugin.h \
|
||||
cppcheckrunner.h \
|
||||
cppchecktextmark.h \
|
||||
cppchecktextmarkmanager.h \
|
||||
cppchecktool.h \
|
||||
cppchecktrigger.h
|
||||
33
src/plugins/cppcheck/cppcheck.qbs
Normal file
33
src/plugins/cppcheck/cppcheck.qbs
Normal file
@@ -0,0 +1,33 @@
|
||||
import qbs
|
||||
|
||||
QtcPlugin {
|
||||
name: "Cppcheck"
|
||||
|
||||
Depends { name: "Core" }
|
||||
Depends { name: "CppTools" }
|
||||
Depends { name: "ExtensionSystem" }
|
||||
Depends { name: "ProjectExplorer" }
|
||||
Depends { name: "TextEditor" }
|
||||
Depends { name: "Utils" }
|
||||
|
||||
Depends { name: "Qt.widgets" }
|
||||
|
||||
files: [
|
||||
"cppcheckconstants.h",
|
||||
"cppcheckdiagnostic.h",
|
||||
"cppcheckoptions.cpp",
|
||||
"cppcheckoptions.h",
|
||||
"cppcheckplugin.cpp",
|
||||
"cppcheckplugin.h",
|
||||
"cppcheckrunner.cpp",
|
||||
"cppcheckrunner.h",
|
||||
"cppchecktextmark.cpp",
|
||||
"cppchecktextmark.h",
|
||||
"cppchecktextmarkmanager.cpp",
|
||||
"cppchecktextmarkmanager.h",
|
||||
"cppchecktool.cpp",
|
||||
"cppchecktool.h",
|
||||
"cppchecktrigger.cpp",
|
||||
"cppchecktrigger.h"
|
||||
]
|
||||
}
|
||||
8
src/plugins/cppcheck/cppcheck_dependencies.pri
Normal file
8
src/plugins/cppcheck/cppcheck_dependencies.pri
Normal file
@@ -0,0 +1,8 @@
|
||||
QTC_PLUGIN_NAME = Cppcheck
|
||||
QTC_LIB_DEPENDS += \
|
||||
extensionsystem \
|
||||
utils
|
||||
QTC_PLUGIN_DEPENDS += \
|
||||
cpptools \
|
||||
projectexplorer \
|
||||
texteditor
|
||||
55
src/plugins/cppcheck/cppcheckconstants.h
Normal file
55
src/plugins/cppcheck/cppcheckconstants.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 Sergey Morozov
|
||||
** 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
|
||||
|
||||
namespace Cppcheck {
|
||||
namespace Constants {
|
||||
|
||||
const char TEXTMARK_CATEGORY_ID[] = "Cppcheck";
|
||||
|
||||
const char OPTIONS_PAGE_ID[] = "Analyzer.Cppcheck.Settings";
|
||||
|
||||
const char SETTINGS_ID[] = "Cppcheck";
|
||||
const char SETTINGS_BINARY[] = "binary";
|
||||
const char SETTINGS_WARNING[] = "warning";
|
||||
const char SETTINGS_STYLE[] = "style";
|
||||
const char SETTINGS_PERFORMANCE[] = "performance";
|
||||
const char SETTINGS_PORTABILITY[] = "portability";
|
||||
const char SETTINGS_INFORMATION[] = "information";
|
||||
const char SETTINGS_UNUSED_FUNCTION[] = "unusedFunction";
|
||||
const char SETTINGS_MISSING_INCLUDE[] = "missingInclude";
|
||||
const char SETTINGS_INCONCLUSIVE[] = "inconclusive";
|
||||
const char SETTINGS_FORCE_DEFINES[] = "forceDefines";
|
||||
const char SETTINGS_CUSTOM_ARGUMENTS[] = "customArguments";
|
||||
const char SETTINGS_IGNORE_PATTERNS[] = "ignorePatterns";
|
||||
const char SETTINGS_SHOW_OUTPUT[] = "showOutput";
|
||||
const char SETTINGS_ADD_INCLUDE_PATHS[] = "addIncludePaths";
|
||||
const char SETTINGS_GUESS_ARGUMENTS[] = "guessArguments";
|
||||
|
||||
const char CHECK_PROGRESS_ID[] = "Cppcheck.Cppcheck.CheckingTask";
|
||||
|
||||
} // namespace Constants
|
||||
} // namespace Cppcheck
|
||||
52
src/plugins/cppcheck/cppcheckdiagnostic.h
Normal file
52
src/plugins/cppcheck/cppcheckdiagnostic.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 Sergey Morozov
|
||||
** 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 <utils/fileutils.h>
|
||||
|
||||
namespace Cppcheck {
|
||||
namespace Internal {
|
||||
|
||||
class Diagnostic final
|
||||
{
|
||||
public:
|
||||
enum class Severity {
|
||||
Error, Warning, Performance, Portability, Style, Information
|
||||
};
|
||||
bool isValid() const {
|
||||
return !fileName.isEmpty() && lineNumber > 0;
|
||||
}
|
||||
|
||||
Severity severity = Severity::Information;
|
||||
QString severityText;
|
||||
QString checkId;
|
||||
QString message;
|
||||
Utils::FileName fileName;
|
||||
int lineNumber = 0;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Cppcheck
|
||||
267
src/plugins/cppcheck/cppcheckoptions.cpp
Normal file
267
src/plugins/cppcheck/cppcheckoptions.cpp
Normal file
@@ -0,0 +1,267 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 Sergey Morozov
|
||||
** 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 "cppcheckconstants.h"
|
||||
#include "cppcheckoptions.h"
|
||||
#include "cppchecktool.h"
|
||||
#include "cppchecktrigger.h"
|
||||
|
||||
#include <utils/flowlayout.h>
|
||||
#include <utils/hostosinfo.h>
|
||||
#include <utils/pathchooser.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
#include <coreplugin/variablechooser.h>
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QDir>
|
||||
#include <QFormLayout>
|
||||
|
||||
namespace Cppcheck {
|
||||
namespace Internal {
|
||||
|
||||
class OptionsWidget final : public QWidget
|
||||
{
|
||||
public:
|
||||
explicit OptionsWidget(QWidget *parent = nullptr)
|
||||
: QWidget(parent),
|
||||
m_binary(new Utils::PathChooser(this)),
|
||||
m_customArguments(new QLineEdit(this)),
|
||||
m_ignorePatterns(new QLineEdit(this)),
|
||||
m_warning(new QCheckBox(tr("Warnings"), this)),
|
||||
m_style(new QCheckBox(tr("Style"), this)),
|
||||
m_performance(new QCheckBox(tr("Performance"), this)),
|
||||
m_portability(new QCheckBox(tr("Portability"), this)),
|
||||
m_information(new QCheckBox(tr("Information"), this)),
|
||||
m_unusedFunction(new QCheckBox(tr("Unused functions"), this)),
|
||||
m_missingInclude(new QCheckBox(tr("Missing include"), this)),
|
||||
m_inconclusive(new QCheckBox(tr("Inconclusive errors"), this)),
|
||||
m_forceDefines(new QCheckBox(tr("Check all define combinations"), this)),
|
||||
m_showOutput(new QCheckBox(tr("Show raw output"), this)),
|
||||
m_addIncludePaths(new QCheckBox(tr("Add include paths"), this)),
|
||||
m_guessArguments(new QCheckBox(tr("Calculate additional arguments"), this))
|
||||
{
|
||||
m_binary->setExpectedKind(Utils::PathChooser::ExistingCommand);
|
||||
m_binary->setCommandVersionArguments({"--version"});
|
||||
|
||||
const auto variableChooser = new Core::VariableChooser (this);
|
||||
variableChooser->addSupportedWidget (m_customArguments);
|
||||
|
||||
m_unusedFunction->setToolTip(tr("Disables multithreaded check."));
|
||||
m_ignorePatterns->setToolTip(tr("Comma-separated wildcards of full file paths."
|
||||
"Files still can be checked if others include them."));
|
||||
m_addIncludePaths->setToolTip(tr("Can find missing includes but makes "
|
||||
"checking slower. Use only when needed."));
|
||||
m_guessArguments->setToolTip(tr("Like C++ standard and language."));
|
||||
|
||||
const auto layout = new QFormLayout(this);
|
||||
layout->addRow(tr("Binary:"), m_binary);
|
||||
|
||||
const auto checks = new Utils::FlowLayout;
|
||||
layout->addRow(tr("Checks:"), checks);
|
||||
checks->addWidget(m_warning);
|
||||
checks->addWidget(m_style);
|
||||
checks->addWidget(m_performance);
|
||||
checks->addWidget(m_portability);
|
||||
checks->addWidget(m_information);
|
||||
checks->addWidget(m_unusedFunction);
|
||||
checks->addWidget(m_missingInclude);
|
||||
|
||||
layout->addRow(tr("Custom arguments:"), m_customArguments);
|
||||
layout->addRow(tr("Ignored file patterns:"), m_ignorePatterns);
|
||||
const auto flags = new Utils::FlowLayout;
|
||||
layout->addRow(flags);
|
||||
flags->addWidget(m_inconclusive);
|
||||
flags->addWidget(m_forceDefines);
|
||||
flags->addWidget(m_showOutput);
|
||||
flags->addWidget(m_addIncludePaths);
|
||||
flags->addWidget(m_guessArguments);
|
||||
}
|
||||
|
||||
void load(const CppcheckOptions &options)
|
||||
{
|
||||
m_binary->setPath(options.binary);
|
||||
m_customArguments->setText(options.customArguments);
|
||||
m_ignorePatterns->setText(options.ignoredPatterns);
|
||||
m_warning->setChecked(options.warning);
|
||||
m_style->setChecked(options.style);
|
||||
m_performance->setChecked(options.performance);
|
||||
m_portability->setChecked(options.portability);
|
||||
m_information->setChecked(options.information);
|
||||
m_unusedFunction->setChecked(options.unusedFunction);
|
||||
m_missingInclude->setChecked(options.missingInclude);
|
||||
m_inconclusive->setChecked(options.inconclusive);
|
||||
m_forceDefines->setChecked(options.forceDefines);
|
||||
m_showOutput->setChecked(options.showOutput);
|
||||
m_addIncludePaths->setChecked(options.addIncludePaths);
|
||||
m_guessArguments->setChecked(options.guessArguments);
|
||||
}
|
||||
|
||||
void save(CppcheckOptions &options) const
|
||||
{
|
||||
options.binary = m_binary->path();
|
||||
options.customArguments = m_customArguments->text();
|
||||
options.ignoredPatterns = m_ignorePatterns->text();
|
||||
options.warning = m_warning->isChecked();
|
||||
options.style = m_style->isChecked();
|
||||
options.performance = m_performance->isChecked();
|
||||
options.portability = m_portability->isChecked();
|
||||
options.information = m_information->isChecked();
|
||||
options.unusedFunction = m_unusedFunction->isChecked();
|
||||
options.missingInclude = m_missingInclude->isChecked();
|
||||
options.inconclusive = m_inconclusive->isChecked();
|
||||
options.forceDefines = m_forceDefines->isChecked();
|
||||
options.showOutput = m_showOutput->isChecked();
|
||||
options.addIncludePaths = m_addIncludePaths->isChecked();
|
||||
options.guessArguments = m_guessArguments->isChecked();
|
||||
}
|
||||
|
||||
private:
|
||||
Utils::PathChooser *m_binary = nullptr;
|
||||
QLineEdit *m_customArguments = nullptr;
|
||||
QLineEdit *m_ignorePatterns = nullptr;
|
||||
QCheckBox *m_warning = nullptr;
|
||||
QCheckBox *m_style = nullptr;
|
||||
QCheckBox *m_performance = nullptr;
|
||||
QCheckBox *m_portability = nullptr;
|
||||
QCheckBox *m_information = nullptr;
|
||||
QCheckBox *m_unusedFunction = nullptr;
|
||||
QCheckBox *m_missingInclude = nullptr;
|
||||
QCheckBox *m_inconclusive = nullptr;
|
||||
QCheckBox *m_forceDefines = nullptr;
|
||||
QCheckBox *m_showOutput = nullptr;
|
||||
QCheckBox *m_addIncludePaths = nullptr;
|
||||
QCheckBox *m_guessArguments = nullptr;
|
||||
};
|
||||
|
||||
CppcheckOptionsPage::CppcheckOptionsPage(CppcheckTool &tool, CppcheckTrigger &trigger):
|
||||
m_tool(tool),
|
||||
m_trigger(trigger)
|
||||
{
|
||||
setId(Constants::OPTIONS_PAGE_ID);
|
||||
setDisplayName(tr("Cppcheck"));
|
||||
setCategory("T.Analyzer");
|
||||
|
||||
CppcheckOptions options;
|
||||
if (Utils::HostOsInfo::isAnyUnixHost()) {
|
||||
options.binary = "cppcheck";
|
||||
} else {
|
||||
auto programFiles = QDir::fromNativeSeparators(
|
||||
QString::fromLocal8Bit(qgetenv("PROGRAMFILES")));
|
||||
if (programFiles.isEmpty())
|
||||
programFiles = "C:/Program Files";
|
||||
options.binary = programFiles + "/Cppcheck/cppcheck.exe";
|
||||
}
|
||||
|
||||
load(options);
|
||||
|
||||
m_tool.updateOptions(options);
|
||||
}
|
||||
|
||||
QWidget *CppcheckOptionsPage::widget()
|
||||
{
|
||||
if (!m_widget)
|
||||
m_widget = new OptionsWidget;
|
||||
m_widget->load(m_tool.options());
|
||||
return m_widget.data();
|
||||
}
|
||||
|
||||
void CppcheckOptionsPage::apply()
|
||||
{
|
||||
CppcheckOptions options;
|
||||
m_widget->save(options);
|
||||
save(options);
|
||||
m_tool.updateOptions(options);
|
||||
m_trigger.recheck();
|
||||
}
|
||||
|
||||
void CppcheckOptionsPage::finish()
|
||||
{
|
||||
}
|
||||
|
||||
void CppcheckOptionsPage::save(const CppcheckOptions &options) const
|
||||
{
|
||||
const auto s = Core::ICore::settings();
|
||||
QTC_ASSERT(s, return);
|
||||
s->beginGroup(Constants::SETTINGS_ID);
|
||||
s->setValue(Constants::SETTINGS_BINARY, options.binary);
|
||||
s->setValue(Constants::SETTINGS_CUSTOM_ARGUMENTS, options.customArguments);
|
||||
s->setValue(Constants::SETTINGS_IGNORE_PATTERNS, options.ignoredPatterns);
|
||||
s->setValue(Constants::SETTINGS_WARNING, options.warning);
|
||||
s->setValue(Constants::SETTINGS_STYLE, options.style);
|
||||
s->setValue(Constants::SETTINGS_PERFORMANCE, options.performance);
|
||||
s->setValue(Constants::SETTINGS_PORTABILITY, options.portability);
|
||||
s->setValue(Constants::SETTINGS_INFORMATION, options.information);
|
||||
s->setValue(Constants::SETTINGS_UNUSED_FUNCTION, options.unusedFunction);
|
||||
s->setValue(Constants::SETTINGS_MISSING_INCLUDE, options.missingInclude);
|
||||
s->setValue(Constants::SETTINGS_INCONCLUSIVE, options.inconclusive);
|
||||
s->setValue(Constants::SETTINGS_FORCE_DEFINES, options.forceDefines);
|
||||
s->setValue(Constants::SETTINGS_SHOW_OUTPUT, options.showOutput);
|
||||
s->setValue(Constants::SETTINGS_ADD_INCLUDE_PATHS, options.addIncludePaths);
|
||||
s->setValue(Constants::SETTINGS_GUESS_ARGUMENTS, options.guessArguments);
|
||||
s->endGroup();
|
||||
}
|
||||
|
||||
void CppcheckOptionsPage::load(CppcheckOptions &options) const
|
||||
{
|
||||
const auto s = Core::ICore::settings();
|
||||
QTC_ASSERT(s, return);
|
||||
s->beginGroup(Constants::SETTINGS_ID);
|
||||
options.binary = s->value(Constants::SETTINGS_BINARY,
|
||||
options.binary).toString();
|
||||
options.customArguments = s->value(Constants::SETTINGS_CUSTOM_ARGUMENTS,
|
||||
options.customArguments).toString();
|
||||
options.ignoredPatterns = s->value(Constants::SETTINGS_IGNORE_PATTERNS,
|
||||
options.ignoredPatterns).toString();
|
||||
options.warning = s->value(Constants::SETTINGS_WARNING,
|
||||
options.warning).toBool();
|
||||
options.style = s->value(Constants::SETTINGS_STYLE,
|
||||
options.style).toBool();
|
||||
options.performance = s->value(Constants::SETTINGS_PERFORMANCE,
|
||||
options.performance).toBool();
|
||||
options.portability = s->value(Constants::SETTINGS_PORTABILITY,
|
||||
options.portability).toBool();
|
||||
options.information = s->value(Constants::SETTINGS_INFORMATION,
|
||||
options.information).toBool();
|
||||
options.unusedFunction = s->value(Constants::SETTINGS_UNUSED_FUNCTION,
|
||||
options.unusedFunction).toBool();
|
||||
options.missingInclude = s->value(Constants::SETTINGS_MISSING_INCLUDE,
|
||||
options.missingInclude).toBool();
|
||||
options.inconclusive = s->value(Constants::SETTINGS_INCONCLUSIVE,
|
||||
options.inconclusive).toBool();
|
||||
options.forceDefines = s->value(Constants::SETTINGS_FORCE_DEFINES,
|
||||
options.forceDefines).toBool();
|
||||
options.showOutput = s->value(Constants::SETTINGS_SHOW_OUTPUT,
|
||||
options.showOutput).toBool();
|
||||
options.addIncludePaths = s->value(Constants::SETTINGS_ADD_INCLUDE_PATHS,
|
||||
options.addIncludePaths).toBool();
|
||||
options.guessArguments = s->value(Constants::SETTINGS_GUESS_ARGUMENTS,
|
||||
options.guessArguments).toBool();
|
||||
s->endGroup();
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Cppcheck
|
||||
81
src/plugins/cppcheck/cppcheckoptions.h
Normal file
81
src/plugins/cppcheck/cppcheckoptions.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 Sergey Morozov
|
||||
** 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 <coreplugin/dialogs/ioptionspage.h>
|
||||
|
||||
#include <QPointer>
|
||||
|
||||
namespace Cppcheck {
|
||||
namespace Internal {
|
||||
|
||||
class CppcheckTool;
|
||||
class CppcheckTrigger;
|
||||
class OptionsWidget;
|
||||
|
||||
class CppcheckOptions final
|
||||
{
|
||||
public:
|
||||
QString binary;
|
||||
|
||||
bool warning = true;
|
||||
bool style = true;
|
||||
bool performance = true;
|
||||
bool portability = true;
|
||||
bool information = true;
|
||||
bool unusedFunction = false;
|
||||
bool missingInclude = false;
|
||||
bool inconclusive = false;
|
||||
bool forceDefines = false;
|
||||
|
||||
QString customArguments;
|
||||
QString ignoredPatterns;
|
||||
bool showOutput = false;
|
||||
bool addIncludePaths = false;
|
||||
bool guessArguments = true;
|
||||
};
|
||||
|
||||
class CppcheckOptionsPage final : public Core::IOptionsPage
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit CppcheckOptionsPage(CppcheckTool &tool, CppcheckTrigger &trigger);
|
||||
|
||||
QWidget *widget() final;
|
||||
void apply() final;
|
||||
void finish() final;
|
||||
|
||||
private:
|
||||
void save(const CppcheckOptions &options) const;
|
||||
void load(CppcheckOptions &options) const;
|
||||
|
||||
CppcheckTool &m_tool;
|
||||
CppcheckTrigger &m_trigger;
|
||||
QPointer<OptionsWidget> m_widget;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Cppcheck
|
||||
67
src/plugins/cppcheck/cppcheckplugin.cpp
Normal file
67
src/plugins/cppcheck/cppcheckplugin.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 Sergey Morozov
|
||||
** 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 "cppcheckoptions.h"
|
||||
#include "cppcheckplugin.h"
|
||||
#include "cppchecktextmarkmanager.h"
|
||||
#include "cppchecktool.h"
|
||||
#include "cppchecktrigger.h"
|
||||
|
||||
namespace Cppcheck {
|
||||
namespace Internal {
|
||||
|
||||
class CppcheckPluginPrivate final
|
||||
{
|
||||
public:
|
||||
explicit CppcheckPluginPrivate();
|
||||
CppcheckTextMarkManager marks;
|
||||
CppcheckTool tool;
|
||||
CppcheckTrigger trigger;
|
||||
CppcheckOptionsPage options;
|
||||
};
|
||||
|
||||
CppcheckPluginPrivate::CppcheckPluginPrivate() :
|
||||
tool(marks),
|
||||
trigger(marks, tool),
|
||||
options(tool, trigger)
|
||||
{
|
||||
}
|
||||
|
||||
CppcheckPlugin::CppcheckPlugin() = default;
|
||||
|
||||
CppcheckPlugin::~CppcheckPlugin() = default;
|
||||
|
||||
bool CppcheckPlugin::initialize(const QStringList &arguments, QString *errorString)
|
||||
{
|
||||
Q_UNUSED(arguments);
|
||||
Q_UNUSED(errorString);
|
||||
|
||||
d.reset(new CppcheckPluginPrivate);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Cppcheck
|
||||
54
src/plugins/cppcheck/cppcheckplugin.h
Normal file
54
src/plugins/cppcheck/cppcheckplugin.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 Sergey Morozov
|
||||
** 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 <extensionsystem/iplugin.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace Cppcheck {
|
||||
namespace Internal {
|
||||
|
||||
class CppcheckPluginPrivate;
|
||||
|
||||
class CppcheckPlugin final : public ExtensionSystem::IPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "Cppcheck.json")
|
||||
|
||||
public:
|
||||
CppcheckPlugin();
|
||||
~CppcheckPlugin() override;
|
||||
|
||||
private:
|
||||
bool initialize(const QStringList &arguments, QString *errorString) final;
|
||||
void extensionsInitialized() final {}
|
||||
|
||||
std::unique_ptr<CppcheckPluginPrivate> d;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Cppcheck
|
||||
216
src/plugins/cppcheck/cppcheckrunner.cpp
Normal file
216
src/plugins/cppcheck/cppcheckrunner.cpp
Normal file
@@ -0,0 +1,216 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 Sergey Morozov
|
||||
** 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 "cppcheckrunner.h"
|
||||
#include "cppchecktool.h"
|
||||
|
||||
#include <utils/hostosinfo.h>
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/qtcprocess.h>
|
||||
|
||||
#include <coreplugin/messagemanager.h>
|
||||
|
||||
namespace Cppcheck {
|
||||
namespace Internal {
|
||||
|
||||
CppcheckRunner::CppcheckRunner(CppcheckTool &tool) :
|
||||
m_tool(tool),
|
||||
m_process(new Utils::QtcProcess(this))
|
||||
{
|
||||
if (Utils::HostOsInfo::hostOs() == Utils::OsTypeLinux) {
|
||||
QProcess getConf;
|
||||
getConf.start("getconf ARG_MAX");
|
||||
getConf.waitForFinished(2000);
|
||||
const auto argMax = getConf.readAllStandardOutput().replace("\n", "");
|
||||
m_maxArgumentsLength = std::max(argMax.toInt(), m_maxArgumentsLength);
|
||||
}
|
||||
|
||||
connect(m_process, &QProcess::readyReadStandardOutput,
|
||||
this, &CppcheckRunner::readOutput);
|
||||
connect(m_process, &QProcess::readyReadStandardOutput,
|
||||
this, &CppcheckRunner::readError);
|
||||
connect(m_process, &QProcess::started,
|
||||
this, &CppcheckRunner::handleStarted);
|
||||
connect(m_process, QOverload<int>::of(&QProcess::finished),
|
||||
this, &CppcheckRunner::handleFinished);
|
||||
|
||||
m_queueTimer.setSingleShot(true);
|
||||
const auto checkDelayInMs = 200;
|
||||
m_queueTimer.setInterval(checkDelayInMs);
|
||||
connect(&m_queueTimer, &QTimer::timeout,
|
||||
this, &CppcheckRunner::checkQueued);
|
||||
}
|
||||
|
||||
CppcheckRunner::~CppcheckRunner()
|
||||
{
|
||||
stop();
|
||||
m_queueTimer.stop();
|
||||
}
|
||||
|
||||
void CppcheckRunner::reconfigure(const QString &binary, const QString &arguments)
|
||||
{
|
||||
m_binary = binary;
|
||||
m_arguments = arguments;
|
||||
}
|
||||
|
||||
void CppcheckRunner::addToQueue(const Utils::FileNameList &files,
|
||||
const QString &additionalArguments)
|
||||
{
|
||||
auto &existing = m_queue[additionalArguments];
|
||||
if (existing.isEmpty()) {
|
||||
existing = files;
|
||||
} else {
|
||||
std::copy_if(files.cbegin(), files.cend(), std::back_inserter(existing),
|
||||
[&existing](const Utils::FileName &file) { return !existing.contains(file); });
|
||||
}
|
||||
|
||||
if (m_isRunning) {
|
||||
if (existing == m_currentFiles)
|
||||
m_process->kill(); // Further processing in handleFinished
|
||||
return;
|
||||
}
|
||||
|
||||
m_queueTimer.start();
|
||||
}
|
||||
|
||||
void CppcheckRunner::stop()
|
||||
{
|
||||
if (m_isRunning)
|
||||
m_process->kill();
|
||||
}
|
||||
|
||||
void CppcheckRunner::removeFromQueue(const Utils::FileNameList &files)
|
||||
{
|
||||
if (m_queue.isEmpty())
|
||||
return;
|
||||
|
||||
if (files.isEmpty()) {
|
||||
m_queue.clear();
|
||||
} else {
|
||||
for (auto it = m_queue.begin(), end = m_queue.end(); it != end;) {
|
||||
for (const auto &file : files)
|
||||
it.value().removeOne(file);
|
||||
it = !it.value().isEmpty() ? ++it : m_queue.erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const Utils::FileNameList &CppcheckRunner::currentFiles() const
|
||||
{
|
||||
return m_currentFiles;
|
||||
}
|
||||
|
||||
QString CppcheckRunner::currentCommand() const
|
||||
{
|
||||
return m_process->program() + ' ' +
|
||||
m_process->arguments().join(' ');
|
||||
}
|
||||
|
||||
void CppcheckRunner::checkQueued()
|
||||
{
|
||||
if (m_queue.isEmpty() || m_binary.isEmpty())
|
||||
return;
|
||||
|
||||
auto files = m_queue.begin().value();
|
||||
QString arguments = m_arguments + ' ' + m_queue.begin().key();
|
||||
m_currentFiles.clear();
|
||||
int argumentsLength = arguments.length();
|
||||
while (!files.isEmpty()) {
|
||||
argumentsLength += files.first().length() + 1; // +1 for separator
|
||||
if (argumentsLength >= m_maxArgumentsLength)
|
||||
break;
|
||||
m_currentFiles.push_back(files.first());
|
||||
arguments += ' ' + files.first().toString();
|
||||
files.pop_front();
|
||||
}
|
||||
|
||||
if (files.isEmpty())
|
||||
m_queue.erase(m_queue.begin());
|
||||
else
|
||||
m_queue.begin().value() = files;
|
||||
|
||||
m_process->setCommand(m_binary, arguments);
|
||||
m_process->start();
|
||||
}
|
||||
|
||||
void CppcheckRunner::readOutput()
|
||||
{
|
||||
if (!m_isRunning) // workaround for QTBUG-30929
|
||||
handleStarted();
|
||||
|
||||
m_process->setReadChannel(QProcess::StandardOutput);
|
||||
|
||||
while (!m_process->atEnd() && m_process->canReadLine()) {
|
||||
auto line = QString::fromUtf8(m_process->readLine());
|
||||
if (line.endsWith('\n'))
|
||||
line.chop(1);
|
||||
m_tool.parseOutputLine(line);
|
||||
}
|
||||
}
|
||||
|
||||
void CppcheckRunner::readError()
|
||||
{
|
||||
if (!m_isRunning) // workaround for QTBUG-30929
|
||||
handleStarted();
|
||||
|
||||
m_process->setReadChannel(QProcess::StandardError);
|
||||
|
||||
while (!m_process->atEnd() && m_process->canReadLine()) {
|
||||
auto line = QString::fromUtf8(m_process->readLine());
|
||||
if (line.endsWith('\n'))
|
||||
line.chop(1);
|
||||
m_tool.parseErrorLine(line);
|
||||
}
|
||||
}
|
||||
|
||||
void CppcheckRunner::handleStarted()
|
||||
{
|
||||
if (m_isRunning)
|
||||
return;
|
||||
|
||||
m_isRunning = true;
|
||||
m_tool.startParsing();
|
||||
}
|
||||
|
||||
void CppcheckRunner::handleFinished(int)
|
||||
{
|
||||
if (m_process->error() != QProcess::FailedToStart) {
|
||||
readOutput();
|
||||
readError();
|
||||
m_tool.finishParsing();
|
||||
} else {
|
||||
const QString message = tr("Cppcheck failed to start: \"%1\".").arg(currentCommand());
|
||||
Core::MessageManager::write(message, Core::MessageManager::Silent);
|
||||
}
|
||||
m_currentFiles.clear();
|
||||
m_process->close();
|
||||
m_isRunning = false;
|
||||
|
||||
if (!m_queue.isEmpty())
|
||||
checkQueued();
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Cppcheck
|
||||
78
src/plugins/cppcheck/cppcheckrunner.h
Normal file
78
src/plugins/cppcheck/cppcheckrunner.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 Sergey Morozov
|
||||
** 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 <QHash>
|
||||
#include <QTimer>
|
||||
|
||||
namespace Utils {
|
||||
class QtcProcess;
|
||||
class FileName;
|
||||
using FileNameList = QList<FileName>;
|
||||
}
|
||||
|
||||
namespace Cppcheck {
|
||||
namespace Internal {
|
||||
|
||||
class CppcheckTool;
|
||||
|
||||
class CppcheckRunner final : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CppcheckRunner(CppcheckTool &tool);
|
||||
~CppcheckRunner() override;
|
||||
|
||||
void reconfigure(const QString &binary, const QString &arguments);
|
||||
void addToQueue(const Utils::FileNameList &files,
|
||||
const QString &additionalArguments = {});
|
||||
void removeFromQueue(const Utils::FileNameList &files);
|
||||
void stop();
|
||||
|
||||
const Utils::FileNameList ¤tFiles() const;
|
||||
QString currentCommand() const;
|
||||
|
||||
private:
|
||||
void checkQueued();
|
||||
void readOutput();
|
||||
void readError();
|
||||
void handleStarted();
|
||||
void handleFinished(int);
|
||||
|
||||
CppcheckTool &m_tool;
|
||||
Utils::QtcProcess *m_process = nullptr;
|
||||
QString m_binary;
|
||||
QString m_arguments;
|
||||
QHash<QString, Utils::FileNameList> m_queue;
|
||||
Utils::FileNameList m_currentFiles;
|
||||
QTimer m_queueTimer;
|
||||
int m_maxArgumentsLength = 32767;
|
||||
bool m_isRunning = false;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Cppcheck
|
||||
96
src/plugins/cppcheck/cppchecktextmark.cpp
Normal file
96
src/plugins/cppcheck/cppchecktextmark.cpp
Normal file
@@ -0,0 +1,96 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 Sergey Morozov
|
||||
** 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 "cppcheckconstants.h"
|
||||
#include "cppcheckdiagnostic.h"
|
||||
#include "cppchecktextmark.h"
|
||||
|
||||
#include <utils/utilsicons.h>
|
||||
|
||||
#include <QMap>
|
||||
|
||||
namespace Cppcheck {
|
||||
namespace Internal {
|
||||
|
||||
struct Visual
|
||||
{
|
||||
Visual(Utils::Theme::Color color, TextEditor::TextMark::Priority priority,
|
||||
const QIcon &icon)
|
||||
: color(color),
|
||||
priority(priority),
|
||||
icon(icon)
|
||||
{}
|
||||
Utils::Theme::Color color;
|
||||
TextEditor::TextMark::Priority priority;
|
||||
QIcon icon;
|
||||
};
|
||||
|
||||
static Visual getVisual(Diagnostic::Severity type)
|
||||
{
|
||||
using Color = Utils::Theme::Color;
|
||||
using Priority = TextEditor::TextMark::Priority;
|
||||
|
||||
static const QMap<Diagnostic::Severity, Visual> visuals{
|
||||
{Diagnostic::Severity::Error, {Color::IconsErrorColor, Priority::HighPriority,
|
||||
Utils::Icons::CRITICAL.icon()}},
|
||||
{Diagnostic::Severity::Warning, {Color::IconsWarningColor, Priority::NormalPriority,
|
||||
Utils::Icons::WARNING.icon()}},
|
||||
};
|
||||
|
||||
return visuals.value(type, {Color::IconsInfoColor, Priority::LowPriority,
|
||||
Utils::Icons::INFO.icon()});
|
||||
}
|
||||
|
||||
CppcheckTextMark::CppcheckTextMark (const Diagnostic &diagnostic)
|
||||
: TextEditor::TextMark (diagnostic.fileName, diagnostic.lineNumber,
|
||||
Core::Id(Constants::TEXTMARK_CATEGORY_ID)),
|
||||
m_severity(diagnostic.severity),
|
||||
m_checkId(diagnostic.checkId),
|
||||
m_message(diagnostic.message)
|
||||
{
|
||||
const auto visual = getVisual(diagnostic.severity);
|
||||
setPriority(visual.priority);
|
||||
setColor(visual.color);
|
||||
setIcon(visual.icon);
|
||||
setToolTip(toolTipText(diagnostic.severityText));
|
||||
setLineAnnotation(diagnostic.message);
|
||||
}
|
||||
|
||||
QString CppcheckTextMark::toolTipText(const QString &severityText) const
|
||||
{
|
||||
return QString(
|
||||
"<table cellspacing='0' cellpadding='0' width='100%'>"
|
||||
" <tr>"
|
||||
" <td align='left'><b>Cppcheck</b></td>"
|
||||
" <td align='right'> <font color='gray'>%1: %2</font></td>"
|
||||
" </tr>"
|
||||
" <tr>"
|
||||
" <td colspan='2' align='left' style='padding-left:10px'>%3</td>"
|
||||
" </tr>"
|
||||
"</table>").arg(m_checkId, severityText, m_message);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Cppcheck
|
||||
55
src/plugins/cppcheck/cppchecktextmark.h
Normal file
55
src/plugins/cppcheck/cppchecktextmark.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 Sergey Morozov
|
||||
** 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 "cppcheckdiagnostic.h"
|
||||
|
||||
#include <texteditor/textmark.h>
|
||||
|
||||
namespace Cppcheck {
|
||||
namespace Internal {
|
||||
|
||||
class CppcheckTextMark final : public TextEditor::TextMark
|
||||
{
|
||||
public:
|
||||
explicit CppcheckTextMark(const Diagnostic &diagnostic);
|
||||
|
||||
bool operator==(const Diagnostic &r) const {
|
||||
return lineNumber() == r.lineNumber
|
||||
&& (std::tie(m_severity, m_checkId, m_message) ==
|
||||
std::tie(r.severity, r.checkId, r.message));
|
||||
}
|
||||
|
||||
private:
|
||||
QString toolTipText(const QString &severityText) const;
|
||||
|
||||
Diagnostic::Severity m_severity = Diagnostic::Severity::Information;
|
||||
QString m_checkId;
|
||||
QString m_message;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Cppcheck
|
||||
63
src/plugins/cppcheck/cppchecktextmarkmanager.cpp
Normal file
63
src/plugins/cppcheck/cppchecktextmarkmanager.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 Sergey Morozov
|
||||
** 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 "cppcheckdiagnostic.h"
|
||||
#include "cppchecktextmark.h"
|
||||
#include "cppchecktextmarkmanager.h"
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
|
||||
namespace Cppcheck {
|
||||
namespace Internal {
|
||||
|
||||
CppcheckTextMarkManager::CppcheckTextMarkManager() = default;
|
||||
|
||||
CppcheckTextMarkManager::~CppcheckTextMarkManager() = default;
|
||||
|
||||
void CppcheckTextMarkManager::add(const Diagnostic &diagnostic)
|
||||
{
|
||||
auto &fileMarks = m_marks[diagnostic.fileName];
|
||||
const auto finder = [diagnostic] (const MarkPtr &mark) {return *mark == diagnostic;};
|
||||
if (Utils::contains(fileMarks, finder))
|
||||
return;
|
||||
|
||||
fileMarks.push_back(std::make_unique<CppcheckTextMark>(diagnostic));
|
||||
}
|
||||
|
||||
void CppcheckTextMarkManager::clearFiles(const Utils::FileNameList &files)
|
||||
{
|
||||
if (m_marks.empty())
|
||||
return;
|
||||
|
||||
if (!files.empty()) {
|
||||
for (const auto &file: files)
|
||||
m_marks.erase(file);
|
||||
} else {
|
||||
m_marks.clear();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Cppcheck
|
||||
53
src/plugins/cppcheck/cppchecktextmarkmanager.h
Normal file
53
src/plugins/cppcheck/cppchecktextmarkmanager.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 Sergey Morozov
|
||||
** 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 <utils/fileutils.h>
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
namespace Cppcheck {
|
||||
namespace Internal {
|
||||
|
||||
class Diagnostic;
|
||||
class CppcheckTextMark;
|
||||
|
||||
class CppcheckTextMarkManager final
|
||||
{
|
||||
public:
|
||||
explicit CppcheckTextMarkManager();
|
||||
~CppcheckTextMarkManager();
|
||||
|
||||
void add(const Diagnostic &diagnostic);
|
||||
void clearFiles(const Utils::FileNameList &files);
|
||||
|
||||
private:
|
||||
using MarkPtr = std::unique_ptr<CppcheckTextMark>;
|
||||
std::unordered_map<Utils::FileName, std::vector<MarkPtr>> m_marks;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Cppcheck
|
||||
324
src/plugins/cppcheck/cppchecktool.cpp
Normal file
324
src/plugins/cppcheck/cppchecktool.cpp
Normal file
@@ -0,0 +1,324 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 Sergey Morozov
|
||||
** 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 "cppcheckconstants.h"
|
||||
#include "cppcheckdiagnostic.h"
|
||||
#include "cppcheckoptions.h"
|
||||
#include "cppcheckrunner.h"
|
||||
#include "cppchecktextmarkmanager.h"
|
||||
#include "cppchecktool.h"
|
||||
|
||||
#include <coreplugin/messagemanager.h>
|
||||
#include <coreplugin/progressmanager/futureprogress.h>
|
||||
#include <coreplugin/progressmanager/progressmanager.h>
|
||||
|
||||
#include <cpptools/cppmodelmanager.h>
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/macroexpander.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QThread>
|
||||
|
||||
namespace Cppcheck {
|
||||
namespace Internal {
|
||||
|
||||
CppcheckTool::CppcheckTool(CppcheckTextMarkManager &marks) :
|
||||
m_marks(marks),
|
||||
m_progressRegexp("^.* checked (\\d)% done$"),
|
||||
m_messageRegexp("^(.+),(\\d+),(\\w+),(\\w+),(.*)$")
|
||||
{
|
||||
m_runner = std::make_unique<CppcheckRunner>(*this);
|
||||
QTC_ASSERT(m_progressRegexp.isValid(), return);
|
||||
QTC_ASSERT(m_messageRegexp.isValid(), return);
|
||||
}
|
||||
|
||||
CppcheckTool::~CppcheckTool() = default;
|
||||
|
||||
void CppcheckTool::updateOptions(const CppcheckOptions &options)
|
||||
{
|
||||
m_options = options;
|
||||
m_filters.clear();
|
||||
const auto patterns = m_options.ignoredPatterns.split(',');
|
||||
for (const auto &pattern : patterns) {
|
||||
const auto trimmedPattern = pattern.trimmed();
|
||||
if (trimmedPattern.isEmpty())
|
||||
continue;
|
||||
|
||||
const QRegExp re(trimmedPattern, Qt::CaseSensitive, QRegExp::Wildcard);
|
||||
if (re.isValid())
|
||||
m_filters.push_back(re);
|
||||
}
|
||||
|
||||
updateArguments();
|
||||
}
|
||||
|
||||
void CppcheckTool::setProject(ProjectExplorer::Project *project)
|
||||
{
|
||||
m_project = project;
|
||||
updateArguments();
|
||||
}
|
||||
|
||||
void CppcheckTool::updateArguments()
|
||||
{
|
||||
if (!m_project)
|
||||
return;
|
||||
|
||||
m_cachedAdditionalArguments.clear();
|
||||
|
||||
QStringList arguments;
|
||||
if (!m_options.customArguments.isEmpty()) {
|
||||
auto expander = Utils::globalMacroExpander();
|
||||
const auto expanded = expander->expand(m_options.customArguments);
|
||||
arguments.push_back(expanded);
|
||||
}
|
||||
|
||||
if (m_options.warning)
|
||||
arguments.push_back("--enable=warning");
|
||||
if (m_options.style)
|
||||
arguments.push_back("--enable=style");
|
||||
if (m_options.performance)
|
||||
arguments.push_back("--enable=performance");
|
||||
if (m_options.portability)
|
||||
arguments.push_back("--enable=portability");
|
||||
if (m_options.information)
|
||||
arguments.push_back("--enable=information");
|
||||
if (m_options.unusedFunction)
|
||||
arguments.push_back("--enable=unusedFunction");
|
||||
if (m_options.missingInclude)
|
||||
arguments.push_back("--enable=missingInclude");
|
||||
if (m_options.inconclusive)
|
||||
arguments.push_back("--inconclusive");
|
||||
if (m_options.forceDefines)
|
||||
arguments.push_back("--force");
|
||||
|
||||
if (!m_options.unusedFunction && !m_options.customArguments.contains("-j "))
|
||||
arguments.push_back("-j " + QString::number(QThread::idealThreadCount()));
|
||||
|
||||
arguments.push_back("--template={file},{line},{severity},{id},{message}");
|
||||
|
||||
m_runner->reconfigure(m_options.binary, arguments.join(' '));
|
||||
}
|
||||
|
||||
QStringList CppcheckTool::additionalArguments(const CppTools::ProjectPart &part) const
|
||||
{
|
||||
QStringList result;
|
||||
|
||||
if (m_options.addIncludePaths) {
|
||||
for (const auto &path : qAsConst(part.headerPaths)) {
|
||||
const auto projectDir = m_project->projectDirectory().toString();
|
||||
if (path.type == ProjectExplorer::HeaderPathType::User
|
||||
&& path.path.startsWith(projectDir))
|
||||
result.push_back("-I " + path.path);
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_options.guessArguments)
|
||||
return result;
|
||||
|
||||
using Version = CppTools::ProjectPart::LanguageVersion;
|
||||
switch (part.languageVersion) {
|
||||
case Version::C89:
|
||||
result.push_back("--std=c89 --language=c");
|
||||
break;
|
||||
case Version::C99:
|
||||
result.push_back("--std=c99 --language=c");
|
||||
break;
|
||||
case Version::C11:
|
||||
result.push_back("--std=c11 --language=c");
|
||||
break;
|
||||
case Version::CXX03:
|
||||
result.push_back("--std=c++03 --language=c++");
|
||||
break;
|
||||
case Version::CXX11:
|
||||
result.push_back("--std=c++11 --language=c++");
|
||||
break;
|
||||
case Version::CXX14:
|
||||
result.push_back("--std=c++14 --language=c++");
|
||||
break;
|
||||
case Version::CXX98:
|
||||
case Version::CXX17:
|
||||
result.push_back("--language=c++");
|
||||
break;
|
||||
}
|
||||
|
||||
using QtVersion = CppTools::ProjectPart::QtVersion;
|
||||
if (part.qtVersion != QtVersion::NoQt)
|
||||
result.push_back("--library=qt");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const CppcheckOptions &CppcheckTool::options() const
|
||||
{
|
||||
return m_options;
|
||||
}
|
||||
|
||||
void CppcheckTool::check(const Utils::FileNameList &files)
|
||||
{
|
||||
QTC_ASSERT(m_project, return);
|
||||
|
||||
Utils::FileNameList filtered;
|
||||
if (m_filters.isEmpty()) {
|
||||
filtered = files;
|
||||
} else {
|
||||
std::copy_if(files.cbegin(), files.cend(), std::back_inserter(filtered),
|
||||
[this](const Utils::FileName &file) {
|
||||
const auto stringed = file.toString();
|
||||
const auto filter = [stringed](const QRegExp &re) {return re.exactMatch(stringed);};
|
||||
return !Utils::contains(m_filters, filter);
|
||||
});
|
||||
}
|
||||
|
||||
if (filtered.isEmpty())
|
||||
return;
|
||||
|
||||
const auto info = CppTools::CppModelManager::instance()->projectInfo(m_project);
|
||||
const auto parts = info.projectParts();
|
||||
if (parts.size() == 1) {
|
||||
QTC_ASSERT(parts.first(), return);
|
||||
addToQueue(filtered, *parts.first());
|
||||
return;
|
||||
}
|
||||
|
||||
std::map<CppTools::ProjectPart::Ptr, Utils::FileNameList> groups;
|
||||
for (const auto &file : qAsConst(filtered)) {
|
||||
const auto stringed = file.toString();
|
||||
for (const auto &part : parts) {
|
||||
QTC_ASSERT(part, continue);
|
||||
const auto &partFiles = part->files;
|
||||
using File = CppTools::ProjectFile;
|
||||
const auto match = [stringed](const File &file){return file.path == stringed;};
|
||||
if (Utils::contains(partFiles, match))
|
||||
groups[part].push_back(file);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &group : groups)
|
||||
addToQueue(group.second, *group.first);
|
||||
}
|
||||
|
||||
void CppcheckTool::addToQueue(const Utils::FileNameList &files, CppTools::ProjectPart &part)
|
||||
{
|
||||
const auto key = part.id();
|
||||
if (!m_cachedAdditionalArguments.contains(key))
|
||||
m_cachedAdditionalArguments.insert(key, additionalArguments(part).join(' '));
|
||||
m_runner->addToQueue(files, m_cachedAdditionalArguments[key]);
|
||||
}
|
||||
|
||||
void CppcheckTool::stop(const Utils::FileNameList &files)
|
||||
{
|
||||
m_runner->removeFromQueue(files);
|
||||
m_runner->stop();
|
||||
}
|
||||
|
||||
void CppcheckTool::startParsing()
|
||||
{
|
||||
if (m_options.showOutput) {
|
||||
const auto message = tr("Cppcheck started: \"%1\".").arg(m_runner->currentCommand());
|
||||
Core::MessageManager::write(message, Core::MessageManager::Silent);
|
||||
}
|
||||
|
||||
m_progress = std::make_unique<QFutureInterface<void>>();
|
||||
const auto progress = Core::ProgressManager::addTask(
|
||||
m_progress->future(), QObject::tr("Cppcheck"),
|
||||
Constants::CHECK_PROGRESS_ID);
|
||||
QObject::connect(progress, &Core::FutureProgress::canceled,
|
||||
this, [this]{stop({});});
|
||||
m_progress->setProgressRange(0, 100);
|
||||
m_progress->reportStarted();
|
||||
}
|
||||
|
||||
void CppcheckTool::parseOutputLine(const QString &line)
|
||||
{
|
||||
if (line.isEmpty())
|
||||
return;
|
||||
|
||||
if (m_options.showOutput)
|
||||
Core::MessageManager::write(line, Core::MessageManager::Silent);
|
||||
|
||||
enum Matches { Percentage = 1 };
|
||||
const auto match = m_progressRegexp.match(line);
|
||||
if (!match.hasMatch())
|
||||
return;
|
||||
|
||||
const auto done = match.captured(Percentage).toInt();
|
||||
QTC_ASSERT(m_progress, return);
|
||||
m_progress->setProgressValue(done);
|
||||
}
|
||||
|
||||
static Diagnostic::Severity toSeverity(const QString &text)
|
||||
{
|
||||
static const QMap<QString, Diagnostic::Severity> values{
|
||||
{"error", Diagnostic::Severity::Error},
|
||||
{"warning", Diagnostic::Severity::Warning},
|
||||
{"performance", Diagnostic::Severity::Performance},
|
||||
{"portability", Diagnostic::Severity::Portability},
|
||||
{"style", Diagnostic::Severity::Style},
|
||||
{"information", Diagnostic::Severity::Information}
|
||||
};
|
||||
return values.value(text, Diagnostic::Severity::Information);
|
||||
}
|
||||
|
||||
void CppcheckTool::parseErrorLine(const QString &line)
|
||||
{
|
||||
if (line.isEmpty())
|
||||
return;
|
||||
|
||||
if (m_options.showOutput)
|
||||
Core::MessageManager::write(line, Core::MessageManager::Silent);
|
||||
|
||||
enum Matches { File = 1, Line, Severity, Id, Message };
|
||||
const auto match = m_messageRegexp.match(line);
|
||||
if (!match.hasMatch())
|
||||
return;
|
||||
|
||||
const auto fileName = Utils::FileName::fromString(
|
||||
QDir::fromNativeSeparators(match.captured(File)));
|
||||
if (!m_runner->currentFiles().contains(fileName))
|
||||
return;
|
||||
|
||||
Diagnostic diagnostic;
|
||||
diagnostic.fileName = fileName;
|
||||
diagnostic.lineNumber = std::max(match.captured(Line).toInt(), 1);
|
||||
diagnostic.severityText = match.captured(Severity);
|
||||
diagnostic.severity = toSeverity(diagnostic.severityText);
|
||||
diagnostic.checkId = match.captured(Id);
|
||||
diagnostic.message = match.captured(Message);
|
||||
if (diagnostic.isValid())
|
||||
m_marks.add(diagnostic);
|
||||
}
|
||||
|
||||
void CppcheckTool::finishParsing()
|
||||
{
|
||||
if (m_options.showOutput)
|
||||
Core::MessageManager::write(tr("Cppcheck finished."), Core::MessageManager::Silent);
|
||||
|
||||
QTC_ASSERT(m_progress, return);
|
||||
m_progress->reportFinished();
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Cppcheck
|
||||
94
src/plugins/cppcheck/cppchecktool.h
Normal file
94
src/plugins/cppcheck/cppchecktool.h
Normal file
@@ -0,0 +1,94 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 Sergey Morozov
|
||||
** 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 <cppcheck/cppcheckoptions.h>
|
||||
|
||||
#include <QFuture>
|
||||
#include <QPointer>
|
||||
#include <QRegularExpression>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace Utils {
|
||||
class FileName;
|
||||
using FileNameList = QList<FileName>;
|
||||
}
|
||||
|
||||
namespace CppTools {
|
||||
class ProjectPart;
|
||||
}
|
||||
|
||||
namespace ProjectExplorer {
|
||||
class Project;
|
||||
}
|
||||
|
||||
namespace Cppcheck {
|
||||
namespace Internal {
|
||||
|
||||
class Diagnostic;
|
||||
class CppcheckRunner;
|
||||
class CppcheckTextMarkManager;
|
||||
class CppcheckOptions;
|
||||
|
||||
class CppcheckTool final : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CppcheckTool(CppcheckTextMarkManager &marks);
|
||||
~CppcheckTool() override;
|
||||
|
||||
void updateOptions(const CppcheckOptions &options);
|
||||
void setProject(ProjectExplorer::Project *project);
|
||||
void check(const Utils::FileNameList &files);
|
||||
void stop(const Utils::FileNameList &files);
|
||||
|
||||
void startParsing();
|
||||
void parseOutputLine(const QString &line);
|
||||
void parseErrorLine(const QString &line);
|
||||
void finishParsing();
|
||||
|
||||
const CppcheckOptions &options() const;
|
||||
|
||||
private:
|
||||
void updateArguments();
|
||||
void addToQueue(const Utils::FileNameList &files, CppTools::ProjectPart &part);
|
||||
QStringList additionalArguments(const CppTools::ProjectPart &part) const;
|
||||
|
||||
CppcheckTextMarkManager &m_marks;
|
||||
CppcheckOptions m_options;
|
||||
QPointer<ProjectExplorer::Project> m_project;
|
||||
std::unique_ptr<CppcheckRunner> m_runner;
|
||||
std::unique_ptr<QFutureInterface<void>> m_progress;
|
||||
QHash<QString, QString> m_cachedAdditionalArguments;
|
||||
QVector<QRegExp> m_filters;
|
||||
QRegularExpression m_progressRegexp;
|
||||
QRegularExpression m_messageRegexp;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Cppcheck
|
||||
198
src/plugins/cppcheck/cppchecktrigger.cpp
Normal file
198
src/plugins/cppcheck/cppchecktrigger.cpp
Normal file
@@ -0,0 +1,198 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 Sergey Morozov
|
||||
** 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 "cppchecktextmarkmanager.h"
|
||||
#include "cppchecktool.h"
|
||||
#include "cppchecktrigger.h"
|
||||
|
||||
#include <cpptools/cppmodelmanager.h>
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <coreplugin/editormanager/editormanager.h>
|
||||
#include <coreplugin/editormanager/ieditor.h>
|
||||
|
||||
#include <projectexplorer/project.h>
|
||||
#include <projectexplorer/session.h>
|
||||
|
||||
namespace Cppcheck {
|
||||
namespace Internal {
|
||||
|
||||
CppcheckTrigger::CppcheckTrigger(CppcheckTextMarkManager &marks, CppcheckTool &tool) :
|
||||
m_marks(marks),
|
||||
m_tool(tool)
|
||||
{
|
||||
using EditorManager = Core::EditorManager;
|
||||
using SessionManager = ProjectExplorer::SessionManager;
|
||||
using CppModelManager = CppTools::CppModelManager;
|
||||
|
||||
connect(EditorManager::instance(), &EditorManager::editorOpened,
|
||||
this, [this](Core::IEditor *editor) {checkEditors({editor});});
|
||||
connect(EditorManager::instance(), &EditorManager::editorsClosed,
|
||||
this, &CppcheckTrigger::removeEditors);
|
||||
connect(EditorManager::instance(), &EditorManager::aboutToSave,
|
||||
this, &CppcheckTrigger::checkChangedDocument);
|
||||
|
||||
connect(SessionManager::instance(), &SessionManager::startupProjectChanged,
|
||||
this, &CppcheckTrigger::changeCurrentProject);
|
||||
|
||||
connect(CppModelManager::instance(), &CppModelManager::projectPartsUpdated,
|
||||
this, &CppcheckTrigger::updateProjectFiles);
|
||||
}
|
||||
|
||||
CppcheckTrigger::~CppcheckTrigger() = default;
|
||||
|
||||
void CppcheckTrigger::recheck()
|
||||
{
|
||||
removeEditors();
|
||||
checkEditors();
|
||||
}
|
||||
|
||||
void CppcheckTrigger::checkEditors(const QList<Core::IEditor *> &editors)
|
||||
{
|
||||
if (!m_currentProject)
|
||||
return;
|
||||
|
||||
using CppModelManager = CppTools::CppModelManager;
|
||||
const auto info = CppModelManager::instance()->projectInfo(m_currentProject);
|
||||
if (!info.isValid())
|
||||
return;
|
||||
|
||||
const auto editorList = !editors.isEmpty()
|
||||
? editors : Core::DocumentModel::editorsForOpenedDocuments();
|
||||
|
||||
Utils::FileNameList toCheck;
|
||||
for (const auto editor: editorList) {
|
||||
QTC_ASSERT(editor, continue);
|
||||
const auto document = editor->document();
|
||||
QTC_ASSERT(document, continue);
|
||||
const auto &path = document->filePath();
|
||||
QTC_ASSERT(!path.isEmpty(), continue);
|
||||
|
||||
if (m_checkedFiles.contains(path))
|
||||
continue;
|
||||
|
||||
if (!m_currentProject->isKnownFile(path))
|
||||
continue;
|
||||
|
||||
const auto &pathString = path.toString();
|
||||
if (!info.sourceFiles().contains(pathString))
|
||||
continue;
|
||||
|
||||
connect(document, &Core::IDocument::aboutToReload,
|
||||
this, [this, document]{checkChangedDocument(document);});
|
||||
connect(document, &Core::IDocument::contentsChanged,
|
||||
this, [this, document] {
|
||||
if (!document->isModified())
|
||||
checkChangedDocument(document);
|
||||
});
|
||||
|
||||
m_checkedFiles.insert(path, QDateTime::currentDateTime());
|
||||
toCheck.push_back(path);
|
||||
}
|
||||
|
||||
if (!toCheck.isEmpty()) {
|
||||
remove(toCheck);
|
||||
check(toCheck);
|
||||
}
|
||||
}
|
||||
|
||||
void CppcheckTrigger::removeEditors(const QList<Core::IEditor *> &editors)
|
||||
{
|
||||
if (!m_currentProject)
|
||||
return;
|
||||
|
||||
const auto editorList = !editors.isEmpty()
|
||||
? editors : Core::DocumentModel::editorsForOpenedDocuments();
|
||||
|
||||
Utils::FileNameList toRemove;
|
||||
for (const auto editor: editorList) {
|
||||
QTC_ASSERT(editor, return);
|
||||
const auto document = editor->document();
|
||||
QTC_ASSERT(document, return);
|
||||
const auto &path = document->filePath();
|
||||
QTC_ASSERT(!path.isEmpty(), return);
|
||||
|
||||
if (!m_checkedFiles.contains(path))
|
||||
continue;
|
||||
|
||||
disconnect(document, nullptr, this, nullptr);
|
||||
m_checkedFiles.remove(path);
|
||||
toRemove.push_back(path);
|
||||
}
|
||||
|
||||
if (!toRemove.isEmpty())
|
||||
remove(toRemove);
|
||||
}
|
||||
|
||||
void CppcheckTrigger::checkChangedDocument(Core::IDocument *document)
|
||||
{
|
||||
QTC_ASSERT(document, return);
|
||||
|
||||
if (!m_currentProject)
|
||||
return;
|
||||
|
||||
const auto &path = document->filePath();
|
||||
QTC_ASSERT(!path.isEmpty(), return);
|
||||
if (!m_checkedFiles.contains(path))
|
||||
return;
|
||||
|
||||
remove({path});
|
||||
check({path});
|
||||
}
|
||||
|
||||
void CppcheckTrigger::changeCurrentProject(ProjectExplorer::Project *project)
|
||||
{
|
||||
m_currentProject = project;
|
||||
m_checkedFiles.clear();
|
||||
remove({});
|
||||
m_tool.setProject(project);
|
||||
checkEditors(Core::DocumentModel::editorsForOpenedDocuments());
|
||||
}
|
||||
|
||||
void CppcheckTrigger::updateProjectFiles(ProjectExplorer::Project *project)
|
||||
{
|
||||
if (project != m_currentProject)
|
||||
return;
|
||||
|
||||
m_checkedFiles.clear();
|
||||
remove({});
|
||||
m_tool.setProject(project);
|
||||
checkEditors(Core::DocumentModel::editorsForOpenedDocuments());
|
||||
}
|
||||
|
||||
void CppcheckTrigger::check(const Utils::FileNameList &files)
|
||||
{
|
||||
m_tool.check(files);
|
||||
}
|
||||
|
||||
void CppcheckTrigger::remove(const Utils::FileNameList &files)
|
||||
{
|
||||
m_marks.clearFiles(files);
|
||||
m_tool.stop(files);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Cppcheck
|
||||
81
src/plugins/cppcheck/cppchecktrigger.h
Normal file
81
src/plugins/cppcheck/cppchecktrigger.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 Sergey Morozov
|
||||
** 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 <QHash>
|
||||
#include <QPointer>
|
||||
|
||||
namespace Utils {
|
||||
class FileName;
|
||||
using FileNameList = QList<FileName>;
|
||||
}
|
||||
|
||||
namespace ProjectExplorer {
|
||||
class Project;
|
||||
}
|
||||
|
||||
namespace Core {
|
||||
class IDocument;
|
||||
class IEditor;
|
||||
}
|
||||
|
||||
namespace CppTools {
|
||||
class ProjectInfo;
|
||||
}
|
||||
|
||||
namespace Cppcheck {
|
||||
namespace Internal {
|
||||
|
||||
class CppcheckTextMarkManager;
|
||||
class CppcheckTool;
|
||||
|
||||
class CppcheckTrigger final : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CppcheckTrigger(CppcheckTextMarkManager &marks, CppcheckTool &tool);
|
||||
~CppcheckTrigger() override;
|
||||
|
||||
void recheck();
|
||||
|
||||
private:
|
||||
void checkEditors(const QList<Core::IEditor *> &editors = {});
|
||||
void removeEditors(const QList<Core::IEditor *> &editors = {});
|
||||
void checkChangedDocument(Core::IDocument *document);
|
||||
void changeCurrentProject(ProjectExplorer::Project *project);
|
||||
void updateProjectFiles(ProjectExplorer::Project *project);
|
||||
void check(const Utils::FileNameList &files);
|
||||
void remove(const Utils::FileNameList &files);
|
||||
|
||||
CppcheckTextMarkManager &m_marks;
|
||||
CppcheckTool &m_tool;
|
||||
QPointer<ProjectExplorer::Project> m_currentProject;
|
||||
QHash<Utils::FileName, QDateTime> m_checkedFiles;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Cppcheck
|
||||
Reference in New Issue
Block a user