diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -project(cppcheck) +project(kdevcppcheck) set(VERSION_MAJOR 1) set(VERSION_MINOR 90) @@ -17,43 +17,47 @@ include(FeatureSummary) find_package(Qt5 REQUIRED Core Widgets Test) -find_package(KF5 REQUIRED COMPONENTS IconThemes ItemModels ThreadWeaver TextEditor I18n) +find_package(KF5 REQUIRED COMPONENTS ItemModels ItemViews) find_package(KDevPlatform ${KDEVPLATFORM_VERSION} REQUIRED) -set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH}) - include_directories( - ${cppcheck_BINARY_DIR} - ${cppcheck_SOURCE_DIR} - ${cppcheck_SOURCE_DIR}/config - ${cppcheck_SOURCE_DIR}/parsers + ${kdevcppcheck_BINARY_DIR} + ${kdevcppcheck_SOURCE_DIR} ) -set(kdevcppcheck_PART_SRCS +set(kdevcppcheck_SRCS debug.cpp job.cpp + parameters.cpp + parser.cpp plugin.cpp - config/genericconfigpage.cpp - config/cppcheckpreferences.cpp - parsers/cppcheckparser.cpp + + config/globalconfigpage.cpp + config/projectconfigpage.cpp +) + +ki18n_wrap_ui(kdevcppcheck_UI_SRCS + config/globalconfigpage.ui + config/projectconfigpage.ui +) + +kconfig_add_kcfg_files(kdevcppcheck_CONFIG_SRCS + config/globalsettings.kcfgc + config/projectsettings.kcfgc +) + +kdevplatform_add_plugin(kdevcppcheck + JSON kdevcppcheck.json + SOURCES ${kdevcppcheck_SRCS} ${kdevcppcheck_UI_SRCS} ${kdevcppcheck_CONFIG_SRCS} ) -ki18n_wrap_ui(kdevcppcheck_PART_SRCS ${kdevcppcheck_PART_UI} config/ui/genericconfig.ui config/ui/cppchecksettings.ui) -kconfig_add_kcfg_files(kdevcppcheck_PART_SRCS config/cppcheckconfig.kcfgc) -kdevplatform_add_plugin(kdevcppcheck JSON kdevcppcheck.json SOURCES ${kdevcppcheck_PART_SRCS} ${kdevcppcheck_CONFIG_SRCS}) target_link_libraries(kdevcppcheck - KDev::Interfaces KDev::Project KDev::Language KDev::OutputView - KDev::Util KDev::Shell - KF5::ConfigCore - KF5::IconThemes - KF5::KIOCore - KF5::WidgetsAddons - KF5::TextEditor - Qt5::Network) + KF5::ItemViews +) install(FILES kdevcppcheck.rc DESTINATION ${KXMLGUI_INSTALL_DIR}/kdevcppcheck) diff --git a/config/cppcheckconfig.kcfg b/config/cppcheckconfig.kcfg deleted file mode 100644 --- a/config/cppcheckconfig.kcfg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - file:///usr/bin/cppcheck - - The full path to the Cppcheck executable - The full path to the Cppcheck executable. - - - diff --git a/config/cppcheckconfig.kcfgc b/config/cppcheckconfig.kcfgc deleted file mode 100644 --- a/config/cppcheckconfig.kcfgc +++ /dev/null @@ -1,6 +0,0 @@ -File=cppcheckconfig.kcfg -ClassName=CppCheckSettings -Singleton=true -UseEnumTypes=true -SetUserTexts=true -ItemAccessors=true diff --git a/config/cppcheckpreferences.cpp b/config/cppcheckpreferences.cpp deleted file mode 100644 --- a/config/cppcheckpreferences.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2015 Laszlo Kis-Adam - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cppcheckpreferences.h" - -#include - -#include "cppcheckconfig.h" - -#include "ui_cppchecksettings.h" - -using namespace KDevelop; - -CppCheckPreferences::CppCheckPreferences(IPlugin *plugin, QWidget* parent) - : ConfigPage(plugin, CppCheckSettings::self(), parent) -{ - QVBoxLayout* layout = new QVBoxLayout(this); - QWidget* widget = new QWidget(this); - Ui::CppCheckSettings ui; - ui.setupUi(widget); - layout->addWidget(widget); -} - -CppCheckPreferences::~CppCheckPreferences() -{ -} - -ConfigPage::ConfigPageType CppCheckPreferences::configPageType() const -{ - return ConfigPage::AnalyzerConfigPage; -} -QString CppCheckPreferences::name() const -{ - return i18n("Cppcheck"); -} - -QString CppCheckPreferences::fullName() const -{ - return i18n("Configure Cppcheck settings"); -} - -QIcon CppCheckPreferences::icon() const -{ - return QIcon::fromTheme(QStringLiteral("kdevelop")); -} diff --git a/config/genericconfigpage.cpp b/config/genericconfigpage.cpp deleted file mode 100644 --- a/config/genericconfigpage.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* This file is part of KDevelop - Copyright 2013 Christoph Thielecke - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public - License as published by the Free Software Foundation; either - version 2 of the License, o (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include - -#include "debug.h" -#include "genericconfigpage.h" -#include "plugin.h" - -#include "ui_genericconfig.h" - -#include - -#include -#include - -namespace cppcheck -{ - -GenericConfigPage::GenericConfigPage(KDevelop::IProject *project, QWidget* parent) - : ConfigPage(nullptr, nullptr, parent) - , m_project(project) -{ - - ui = new Ui::GenericConfig(); - ui->setupUi(this); -} -GenericConfigPage::~GenericConfigPage(void) -{ - delete ui; -} - -QString GenericConfigPage::name() const -{ - return i18n("Cppcheck"); -} - -void GenericConfigPage::apply() -{ - KSharedConfigPtr ptr = m_project->projectConfiguration(); - KConfigGroup group = ptr->group("Cppcheck"); - - group.writeEntry("cppcheckParameters", ui->cppcheckParameters->text()); - group.writeEntry("AdditionalCheckStyle", ui->styleCheckBox->isChecked()); - group.writeEntry("AdditionalCheckPerformance", ui->performanceCheckBox->isChecked()); - group.writeEntry("AdditionalCheckPortability", ui->portabilityCheckBox->isChecked()); - group.writeEntry("AdditionalCheckInformation", ui->informationCheckBox->isChecked()); - group.writeEntry("AdditionalCheckUnusedFunction", ui->unusedFunctionCheckBox->isChecked()); - group.writeEntry("AdditionalCheckMissingInclude", ui->missingIncludeCheckBox->isChecked()); -} - -void GenericConfigPage::defaults() -{ - reset(); -} - -void GenericConfigPage::reset() -{ - KSharedConfigPtr ptr = m_project->projectConfiguration(); - KConfigGroup group = ptr->group("Cppcheck"); - if (!group.isValid()) - return; - - bool wasBlocked = signalsBlocked(); - blockSignals(true); - - ui->cppcheckParameters->setText(group.readEntry("cppcheckParameters", QString(""))); - ui->styleCheckBox->setChecked(group.readEntry("AdditionalCheckStyle", false)); - ui->performanceCheckBox->setChecked(group.readEntry("AdditionalCheckPerformance", false)); - ui->portabilityCheckBox->setChecked(group.readEntry("AdditionalCheckPortability", false)); - ui->informationCheckBox->setChecked(group.readEntry("AdditionalCheckInformation", false)); - ui->unusedFunctionCheckBox->setChecked(group.readEntry("AdditionalCheckUnusedFunction", false)); - ui->missingIncludeCheckBox->setChecked(group.readEntry("AdditionalCheckMissingInclude", false)); - - blockSignals(wasBlocked); -} - -} diff --git a/config/cppcheckpreferences.h b/config/globalconfigpage.h rename from config/cppcheckpreferences.h rename to config/globalconfigpage.h --- a/config/cppcheckpreferences.h +++ b/config/globalconfigpage.h @@ -1,5 +1,6 @@ /* * Copyright 2015 Laszlo Kis-Adam + * Copyright 2016 Anton Anikin * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -15,23 +16,29 @@ * along with this program. If not, see . */ -#ifndef CPPCHECKPREFERENCES_H -#define CPPCHECKPREFERENCES_H +#ifndef CPPCHECK_GLOBAL_CONFIG_PAGE_H +#define CPPCHECK_GLOBAL_CONFIG_PAGE_H #include -class CppCheckSettings; +namespace cppcheck +{ + +class GlobalConfigPage: public KDevelop::ConfigPage +{ + Q_OBJECT -class CppCheckPreferences: public KDevelop::ConfigPage { -Q_OBJECT public: - explicit CppCheckPreferences(KDevelop::IPlugin *plugin = nullptr, QWidget* parent = nullptr); - ~CppCheckPreferences() override; - ConfigPage::ConfigPageType configPageType() const override; + GlobalConfigPage(KDevelop::IPlugin* plugin, QWidget* parent); + ~GlobalConfigPage() override; + + KDevelop::ConfigPage::ConfigPageType configPageType() const override; + QString name() const override; QString fullName() const override; QIcon icon() const override; - }; +} + #endif diff --git a/config/globalconfigpage.cpp b/config/globalconfigpage.cpp new file mode 100644 --- /dev/null +++ b/config/globalconfigpage.cpp @@ -0,0 +1,61 @@ +/* + * Copyright 2015 Laszlo Kis-Adam + * Copyright 2016 Anton Anikin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "globalconfigpage.h" +#include "ui_globalconfigpage.h" + +#include "globalsettings.h" + +#include + +namespace cppcheck +{ + +GlobalConfigPage::GlobalConfigPage(KDevelop::IPlugin* plugin, QWidget* parent) + : ConfigPage(plugin, GlobalSettings::self(), parent) +{ + Ui::GlobalConfigPage ui; + ui.setupUi(this); +} + +GlobalConfigPage::~GlobalConfigPage() +{ +} + +KDevelop::ConfigPage::ConfigPageType GlobalConfigPage::configPageType() const +{ + return KDevelop::ConfigPage::AnalyzerConfigPage; +} + +QString GlobalConfigPage::name() const +{ + return i18n("Cppcheck"); +} + +QString GlobalConfigPage::fullName() const +{ + return i18n("Configure Cppcheck settings"); +} + +QIcon GlobalConfigPage::icon() const +{ +// return QIcon::fromTheme(QStringLiteral("emblem-checked")); + return QIcon::fromTheme(QStringLiteral("kdevelop")); +} + +} diff --git a/config/globalconfigpage.ui b/config/globalconfigpage.ui new file mode 100644 --- /dev/null +++ b/config/globalconfigpage.ui @@ -0,0 +1,90 @@ + + + cppcheck::GlobalConfigPage + + + + 0 + 0 + 757 + 397 + + + + Cppcheck Settings + + + + + + Paths + + + + + + Cppchec&k executable + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + kcfg_executablePath + + + + + + + + + + + + + Output + + + + + + Hide output view during check + + + + + + + Show cppcheck XML output in the output view + + + + + + + + + + Qt::Vertical + + + + 20 + 149 + + + + + + + + + KUrlRequester + QWidget +
kurlrequester.h
+ 1 +
+
+ + +
diff --git a/config/globalsettings.kcfg b/config/globalsettings.kcfg new file mode 100644 --- /dev/null +++ b/config/globalsettings.kcfg @@ -0,0 +1,21 @@ + + + + + + /usr/bin/cppcheck + + + + true + + + + false + + + + diff --git a/config/globalsettings.kcfgc b/config/globalsettings.kcfgc new file mode 100644 --- /dev/null +++ b/config/globalsettings.kcfgc @@ -0,0 +1,4 @@ +File=globalsettings.kcfg +NameSpace=cppcheck +ClassName=GlobalSettings +Singleton=true diff --git a/config/genericconfigpage.h b/config/projectconfigpage.h rename from config/genericconfigpage.h rename to config/projectconfigpage.h --- a/config/genericconfigpage.h +++ b/config/projectconfigpage.h @@ -1,5 +1,6 @@ /* This file is part of KDevelop Copyright 2013 Christoph Thielecke + Copyright 2016 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public @@ -17,15 +18,11 @@ Boston, MA 02110-1301, USA. */ -#ifndef CPPCHECKGENERICCONFIGPAGE_H_ -#define CPPCHECKGENERICCONFIGPAGE_H_ - -#include +#ifndef CPPCHECK_PROJECT_CONFIG_PAGE_H +#define CPPCHECK_PROJECT_CONFIG_PAGE_H #include -class QIcon; - namespace KDevelop { class IProject; @@ -33,36 +30,37 @@ namespace cppcheck { -class Plugin; namespace Ui { -class GenericConfig; +class ProjectConfigPage; } -class GenericConfigPage : public KDevelop::ConfigPage +class Parameters; + +class ProjectConfigPage : public KDevelop::ConfigPage { Q_OBJECT public: - GenericConfigPage(KDevelop::IProject *project, QWidget* parent); - ~GenericConfigPage() override; + ProjectConfigPage(KDevelop::IPlugin* plugin, KDevelop::IProject* project, QWidget* parent); + ~ProjectConfigPage() override; + QIcon icon() const override; QString name() const override; -signals: - public slots: - void apply() override; void defaults() override; void reset() override; private: - KDevelop::IProject *m_project; - Ui::GenericConfig* ui; + void updateCommandLine(); + + QScopedPointer ui; + QScopedPointer m_parameters; }; } -#endif /* CPPCHECKGENERICCONFIGPAGE_H_ */ +#endif diff --git a/config/projectconfigpage.cpp b/config/projectconfigpage.cpp new file mode 100644 --- /dev/null +++ b/config/projectconfigpage.cpp @@ -0,0 +1,126 @@ +/* This file is part of KDevelop + Copyright 2013 Christoph Thielecke + Copyright 2016 Anton Anikin + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, o (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "projectconfigpage.h" +#include "ui_projectconfigpage.h" + +#include "parameters.h" +#include "projectsettings.h" + +#include + +namespace cppcheck +{ + +ProjectConfigPage::ProjectConfigPage(KDevelop::IPlugin* plugin, KDevelop::IProject* project, QWidget* parent) + : ConfigPage(plugin, new ProjectSettings, parent) + , ui(new Ui::ProjectConfigPage) + , m_parameters(new Parameters(project)) +{ + configSkeleton()->setSharedConfig(project->projectConfiguration()); + configSkeleton()->load(); + + ui->setupUi(this); + + ui->commandLine->setFontFamily("Monospace"); + + connect(this, &ProjectConfigPage::changed, this, &ProjectConfigPage::updateCommandLine); + connect(ui->commandLineFilter->lineEdit(), &QLineEdit::textChanged, this, &ProjectConfigPage::updateCommandLine); + connect(ui->commandLineBreaks, &QCheckBox::stateChanged, this, &ProjectConfigPage::updateCommandLine); +} + +ProjectConfigPage::~ProjectConfigPage() +{ +} + +QIcon ProjectConfigPage::icon() const +{ + return QIcon::fromTheme(QStringLiteral("emblem-checked")); +} + +void ProjectConfigPage::defaults() +{ + ConfigPage::defaults(); + updateCommandLine(); +} + +void ProjectConfigPage::reset() +{ + ConfigPage::reset(); + updateCommandLine(); +} + +QString ProjectConfigPage::name() const +{ + return i18n("Cppcheck"); +} + +void ProjectConfigPage::updateCommandLine() +{ + m_parameters->useProjectIncludes = ui->kcfg_useProjectIncludes->isChecked(); + m_parameters->useSystemIncludes = ui->kcfg_useSystemIncludes->isChecked(); + m_parameters->ignoredIncludes = ui->kcfg_ignoredIncludes->text(); + m_parameters->checkStyle = ui->kcfg_checkStyle->isChecked(); + m_parameters->checkPerformance = ui->kcfg_checkPerformance->isChecked(); + m_parameters->checkPortability = ui->kcfg_checkPortability->isChecked(); + m_parameters->checkInformation = ui->kcfg_checkInformation->isChecked(); + m_parameters->checkUnusedFunction = ui->kcfg_checkUnusedFunction->isChecked(); + m_parameters->checkMissingInclude = ui->kcfg_checkMissingInclude->isChecked(); + m_parameters->inconclusiveAnalysis = ui->kcfg_inconclusiveAnalysis->isChecked(); + m_parameters->forceCheck = ui->kcfg_forceCheck->isChecked(); + m_parameters->checkConfig = ui->kcfg_checkConfig->isChecked(); + m_parameters->extraParameters = ui->kcfg_extraParameters->text().trimmed(); + + QString message; + QString commandLine = m_parameters->commandLine(message).join(' '); + + if (message.isEmpty()) + ui->messageWidget->hide(); + else { + ui->messageWidget->setText(message); + ui->messageWidget->show(); + } + + if (!ui->commandLineBreaks->isChecked()) { + ui->commandLine->setText(commandLine); + return; + } + + commandLine.replace(" -", "\n-"); + QString filterText = ui->commandLineFilter->lineEdit()->text(); + if (filterText.isEmpty()) { + ui->commandLine->setText(commandLine); + ui->commandLineBreaks->setEnabled(true); + return; + } + + QStringList lines = commandLine.split('\n'); + QMutableStringListIterator i(lines); + + while (i.hasNext()) { + if (!i.next().contains(filterText)) + i.remove(); + } + + ui->commandLine->setText(lines.join('\n')); + ui->commandLineBreaks->setEnabled(false); +} + +} diff --git a/config/projectconfigpage.ui b/config/projectconfigpage.ui new file mode 100644 --- /dev/null +++ b/config/projectconfigpage.ui @@ -0,0 +1,399 @@ + + + cppcheck::ProjectConfigPage + + + + 0 + 0 + 443 + 502 + + + + + + + + 0 + 0 + + + + 0 + + + + Checks + + + + + + + + <html><head/><body><p>Check for unused functions. It is recommend to only enable this when the whole program is scanned</p></body></html> + + + Unused function + + + false + + + + + + + <html><head/><body><p>Allow that Cppcheck reports even though the analysis is inconclusive. There are false positives with this option. Each result must be carefully investigated before you know if it is good or bad.</p></body></html> + + + Inconclusive analysis + + + + + + + <html><head/><body><p>Enable information messages</p></body></html> + + + Information + + + false + + + + + + + <html><head/><body><p>Warn if there are missing includes. For detailed information use 'check-config'</p></body></html> + + + Missing include + + + false + + + + + + + <html><head/><body><p>Enable performance messages</p></body></html> + + + Performance + + + false + + + + + + + <html><head/><body><p>Force checking of files that have a lot of configurations. Error is printed if such a file is found so there is no reason to use this by default. If used together with '--max-configs=', the last option is the one that is effective.</p><p>Be careful with using this option - it can dramatically slow checking.</p></body></html> + + + Force checking + + + + + + + <html><head/><body><p>Enable portability messages</p></body></html> + + + Portability + + + false + + + + + + + <html><head/><body><p>Enable all coding style checks. All messages with the severities 'style', 'performance' and 'portability' are enabled.</p></body></html> + + + Style + + + false + + + + + + + <html><head/><body><p>Check Cppcheck configuration. The normal code analysis is disabled by this flag.</p></body></html> + + + Check config + + + + + + + + + + Include directories + + + + + + <html><head/><body><p>Add 'project' include directories to cppcheck arguments. This option adds only paths related with project's root and build directories.</p></body></html> + + + Use 'project' include dirs + + + false + + + + + + + false + + + <html><head/><body><p>Add other, 'system' include directories to cppcheck arguments. </p><p>Be careful with using this option - it can dramatically slow checking.</p></body></html> + + + Use 'system' include dirs + + + true + + + false + + + + + + + + + &Ignored includes: + + + kcfg_ignoredIncludes + + + + + + + <html> + +<p>Defines semicolon-separated list of ignored include directories.</p> + +<p>You can use the following placeholders:</p> + +<p><b><tt>%p</tt></b> - Gets replaced by the URL of the project's root directory.</p> + +<p><b><tt>%b</tt></b> - Gets replaced by the URL of the project's build directory.</p> + +</html> + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + Extra parameters + + + + + + + + QLayout::SetDefaultConstraint + + + + + &Extra parameters: + + + kcfg_extraParameters + + + + + + + <html> + +<p>Defines additional parameters for cppcheck (see documentation).</p> + +<p>You can use the following placeholders:</p> + +<p><b><tt>%p</tt></b> - Gets replaced by the URL of the project's root directory.</p> + +<p><b><tt>%b</tt></b> - Gets replaced by the URL of the project's build directory.</p> + +</html> + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + 0 + 0 + + + + Command line + + + + + + + + + + + Break lines + + + true + + + + + + + + + true + + + true + + + false + + + + + + + + + + + + + true + + + false + + + KMessageWidget::Error + + + + + + + + KFilterProxySearchLine + QWidget +
kfilterproxysearchline.h
+
+ + KMessageWidget + QFrame +
kmessagewidget.h
+
+
+ + tabWidget + kcfg_checkStyle + kcfg_checkPerformance + kcfg_checkPortability + kcfg_checkInformation + kcfg_checkUnusedFunction + kcfg_checkMissingInclude + kcfg_inconclusiveAnalysis + kcfg_forceCheck + kcfg_checkConfig + kcfg_useProjectIncludes + kcfg_useSystemIncludes + kcfg_ignoredIncludes + kcfg_extraParameters + commandLineBreaks + commandLine + + + + + kcfg_useProjectIncludes + toggled(bool) + kcfg_useSystemIncludes + setEnabled(bool) + + + 226 + 58 + + + 665 + 58 + + + + +
diff --git a/config/projectsettings.kcfg b/config/projectsettings.kcfg new file mode 100644 --- /dev/null +++ b/config/projectsettings.kcfg @@ -0,0 +1,62 @@ + + + + + + true + + + + false + + + + + + + + false + + + + false + + + + false + + + + false + + + + false + + + + false + + + + false + + + + false + + + + + false + + + + + + + + diff --git a/config/projectsettings.kcfgc b/config/projectsettings.kcfgc new file mode 100644 --- /dev/null +++ b/config/projectsettings.kcfgc @@ -0,0 +1,3 @@ +File=projectsettings.kcfg +NameSpace=cppcheck +ClassName=ProjectSettings diff --git a/config/ui/cppchecksettings.ui b/config/ui/cppchecksettings.ui deleted file mode 100644 --- a/config/ui/cppchecksettings.ui +++ /dev/null @@ -1,75 +0,0 @@ - - - CppCheckSettings - - - - 0 - 0 - 400 - 300 - - - - Cppcheck Settings - - - - - - Paths - - - - - - - - Cppchec&k executable - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - kcfg_cppcheckPath - - - - - - - - - - - - - - - - - - - Qt::Vertical - - - - 20 - 186 - - - - - - - - - KUrlRequester - QFrame -
kurlrequester.h
- 1 -
-
- - -
diff --git a/config/ui/genericconfig.ui b/config/ui/genericconfig.ui deleted file mode 100644 --- a/config/ui/genericconfig.ui +++ /dev/null @@ -1,137 +0,0 @@ - - - cppcheck::GenericConfig - - - - 0 - 0 - 567 - 303 - - - - - - - - - - Extra &Parameters: - - - cppcheckParameters - - - - - - - - - - Qt::Vertical - - - - 20 - 88 - - - - - - - - Enable additional checks - - - Additional checks - - - - - - Check coding style - - - style - - - true - - - - - - - Enable performance messages - - - performance - - - true - - - - - - - Enable portability messages - - - portability - - - true - - - - - - - Enable information messages - - - information - - - true - - - - - - - Check for unused functions - - - unused function - - - true - - - - - - - Warn if there are missing includes - - - missingInclude - - - true - - - - - - - - - - - diff --git a/debug.h b/debug.h --- a/debug.h +++ b/debug.h @@ -16,8 +16,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * *************************************************************************************/ -#ifndef DEBUG_H -#define DEBUG_H +#ifndef CPPCHECK_DEBUG_H +#define CPPCHECK_DEBUG_H #include diff --git a/job.h b/job.h --- a/job.h +++ b/job.h @@ -1,11 +1,12 @@ /* This file is part of KDevelop - * Copyright 2006-2008 Hamish Rodda - * Copyright 2002 Harald Fernengel - * Copyright 2011 Mathieu Lornac - * Copyright 2011 Damien Coppel - * Copyright 2011 Lionel Duc - * Copyright 2013 Christoph Thielecke - * Copyright 2015 Anton Anikin + + Copyright 2006-2008 Hamish Rodda + Copyright 2002 Harald Fernengel + Copyright 2011 Mathieu Lornac + Copyright 2011 Damien Coppel + Copyright 2011 Lionel Duc + Copyright 2013 Christoph Thielecke + Copyright 2016 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public @@ -23,56 +24,51 @@ Boston, MA 02110-1301, USA. */ -#ifndef JOB_H -#define JOB_H +#ifndef CPPCHECK_JOB_H +#define CPPCHECK_JOB_H + + +#include "parameters.h" -#include #include +#include + +class QElapsedTimer; namespace cppcheck { +class CppcheckParser; + class Job : public KDevelop::OutputExecuteJob { Q_OBJECT public: - struct Parameters - { - QString parameters; - bool checkStyle = false; - bool checkPerformance = false; - bool checkPortability = false; - bool checkInformation = false; - bool checkUnusedFunction = false; - bool checkMissingInclude = false; - QString path; - QString executable; - }; - - Job(const Parameters ¶ms, QObject* parent = nullptr); + explicit Job(const Parameters& params); ~Job() override; void start() override; - QVector problems() const; +Q_SIGNALS: + void problemsDetected(const QVector& problems); protected slots: - void postProcessStdout( const QStringList& lines ) override; - void postProcessStderr( const QStringList& lines ) override; + void postProcessStdout(const QStringList& lines) override; + void postProcessStderr(const QStringList& lines) override; - void childProcessExited( int exitCode, QProcess::ExitStatus exitStatus ) override; - void childProcessError( QProcess::ProcessError processError ) override; + void childProcessExited(int exitCode, QProcess::ExitStatus exitStatus) override; + void childProcessError(QProcess::ProcessError processError) override; protected: - void buildCommandLine(); - void processStdoutLines( const QStringList& lines ); - void processStderrLines( const QStringList& lines ); + QScopedPointer m_parser; + + QScopedPointer m_timer; QStringList m_standardOutput; QStringList m_xmlOutput; - QVector m_problems; + bool m_showXmlOutput; }; } diff --git a/job.cpp b/job.cpp --- a/job.cpp +++ b/job.cpp @@ -1,4 +1,5 @@ /* This file is part of KDevelop + Copyright 2011 Mathieu Lornac Copyright 2011 Damien Coppel Copyright 2011 Lionel Duc @@ -7,7 +8,7 @@ Copyright 2006-2008 Hamish Rodda Copyright 2002 Harald Fernengel Copyright 2013 Christoph Thielecke - Copyright 2015 Anton Anikin + Copyright 2016 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public @@ -25,104 +26,118 @@ Boston, MA 02110-1301, USA. */ -#include +#include "job.h" + +#include "parser.h" +#include "debug.h" + +#include #include +#include + #include -#include +#include #include -#include "cppcheckparser.h" -#include "debug.h" -#include "job.h" - namespace cppcheck { -Job::Job(const Parameters ¶ms, QObject* parent) - : KDevelop::OutputExecuteJob(parent) +Job::Job(const Parameters ¶ms) + : OutputExecuteJob(nullptr) + , m_parser(new CppcheckParser) + , m_timer(new QElapsedTimer) + , m_showXmlOutput(params.showXmlOutput) { + setToolTitle("Cppcheck"); setJobName(i18n("Cppcheck output")); setCapabilities(KJob::Killable); setStandardToolView(KDevelop::IOutputView::TestView); setBehaviours(KDevelop::IOutputView::AutoScroll); - setProperties(KDevelop::OutputExecuteJob::JobProperty::DisplayStdout); - setProperties(KDevelop::OutputExecuteJob::JobProperty::DisplayStderr); - setProperties(KDevelop::OutputExecuteJob::JobProperty::PostProcessOutput); - - *this << params.executable; - - *this << "--force"; - *this << "--xml-version=2"; - - if (!params.parameters.isEmpty()) - *this << KShell::splitArgs(params.parameters); - - if (params.checkStyle) - *this << "--enable=style"; + setProperties(OutputExecuteJob::JobProperty::DisplayStdout); + setProperties(OutputExecuteJob::JobProperty::DisplayStderr); + setProperties(OutputExecuteJob::JobProperty::PostProcessOutput); - if (params.checkPerformance) - *this << "--enable=performance"; + *this << params.commandLine(); - if (params.checkPortability) - *this << "--enable=portability"; - - if (params.checkInformation) - *this << "--enable=information"; - - if (params.checkUnusedFunction) - *this << "--enable=unusedFunction"; - - if (params.checkMissingInclude) - *this << "--enable=missingInclude"; - - *this << params.path; - qCDebug(KDEV_CPPCHECK) << "checking path" << params.path; + qCDebug(KDEV_CPPCHECK) << "checking path" << params.checkPath; } Job::~Job() { - doKill(); } -void Job::processStdoutLines(const QStringList& lines) +void Job::postProcessStdout(const QStringList& lines) { + static const auto fileNameRegex = QRegularExpression("Checking ([^:]*)\\.{3}"); + static const auto percentRegex = QRegularExpression("(\\d+)% done"); + + QRegularExpressionMatch match; + + foreach (const QString & line, lines) { + match = fileNameRegex.match(line); + if (match.hasMatch()) { + emit infoMessage(this, match.captured(1)); + continue; + } + + match = percentRegex.match(line); + if (match.hasMatch()) { + setPercent(match.captured(1).toULong()); + continue; + } + } + m_standardOutput << lines; + + if (status() == KDevelop::OutputExecuteJob::JobStatus::JobRunning) + OutputExecuteJob::postProcessStdout(lines); } -void Job::processStderrLines(const QStringList& lines) +void Job::postProcessStderr(const QStringList& lines) { static const auto xmlStartRegex = QRegularExpression("\\s*<"); - for (const QString & line : lines) { + foreach (const QString & line, lines) { // unfortunately sometime cppcheck send non-XML messages to stderr. - // For example, if we pass '-I /missing_include_dir' to the argument list, + // For example, if we pass '-I missing_include_dir' to the argument list, // then stderr output will contains such line (tested on cppcheck 1.72): // // (information) Couldn't find path given by -I '/missing_include_dir' // - // Therefore we must 'move' such messages to m_standardOutput. + // Therefore we must 'move' such messages to m_standardOutput and + // create new corresponding problem. - if (line.indexOf(xmlStartRegex) != -1) // the line contains XML + if (line.indexOf(xmlStartRegex) != -1) { // the line contains XML m_xmlOutput << line; - else - m_standardOutput << line; - } -} -void Job::postProcessStdout(const QStringList& lines) -{ - processStdoutLines(lines); + m_parser->addData(line); - KDevelop::OutputExecuteJob::postProcessStdout(lines); -} + auto problems = m_parser->parse(); -void Job::postProcessStderr(const QStringList& lines) -{ - processStderrLines(lines); + if (!problems.isEmpty()) + emit problemsDetected(problems); + } + else { + KDevelop::IProblem::Ptr problem(new KDevelop::DetectedProblem); + + problem->setSource(KDevelop::IProblem::Plugin); + problem->setSeverity(KDevelop::IProblem::Error); + problem->setDescription(line); + problem->setExplanation("Check your cppcheck settings"); + + emit problemsDetected({problem}); + + if (m_showXmlOutput) + m_standardOutput << line; + else + postProcessStdout({line}); + } + } - KDevelop::OutputExecuteJob::postProcessStderr(lines); + if (status() == KDevelop::OutputExecuteJob::JobStatus::JobRunning && m_showXmlOutput) + OutputExecuteJob::postProcessStderr(lines); } void Job::start() @@ -132,12 +147,8 @@ qCDebug(KDEV_CPPCHECK) << "executing:" << commandLine().join(' '); - KDevelop::OutputExecuteJob::start(); -} - -QVector Job::problems() const -{ - return m_problems; + m_timer->restart(); + OutputExecuteJob::start(); } void Job::childProcessError(QProcess::ProcessError e) @@ -150,7 +161,8 @@ break; case QProcess::Crashed: - message = i18n("Cppcheck crashed."); + if (status() != KDevelop::OutputExecuteJob::JobStatus::JobCanceled) + message = i18n("Cppcheck crashed."); break; case QProcess::Timedout: @@ -179,18 +191,17 @@ void Job::childProcessExited(int exitCode, QProcess::ExitStatus exitStatus) { + setPercent(100); + qCDebug(KDEV_CPPCHECK) << "Process Finished, exitCode" << exitCode << "process exit status" << exitStatus; + postProcessStdout({QString("Elapsed time: %1 sec.").arg(m_timer->elapsed()/1000.0)}); + if (exitCode != 0) { qCDebug(KDEV_CPPCHECK) << "cppcheck failed, standard output: "; qCDebug(KDEV_CPPCHECK) << m_standardOutput.join('\n'); qCDebug(KDEV_CPPCHECK) << "cppcheck failed, XML output: "; qCDebug(KDEV_CPPCHECK) << m_xmlOutput.join('\n'); - } else { - CppcheckParser parser; - parser.addData(m_xmlOutput.join('\n')); - parser.parse(); - m_problems = parser.problems(); } KDevelop::OutputExecuteJob::childProcessExited(exitCode, exitStatus); diff --git a/kdevcppcheck.json b/kdevcppcheck.json --- a/kdevcppcheck.json +++ b/kdevcppcheck.json @@ -1,78 +1,38 @@ { - "GenericName": "Syntax check", - "GenericName[bs]": "Provjera sintakse", - "GenericName[ca@valencia]": "Comprova la sintaxi", - "GenericName[ca]": "Comprova la sintaxi", - "GenericName[cs]": "Kontrola syntaxe", - "GenericName[de]": "Syntaxprüfung", - "GenericName[es]": "Comprobación de sintaxis", - "GenericName[fr]": "Vérification de la syntaxe", - "GenericName[hu]": "Szintaxis-ellenőrzés", - "GenericName[nl]": "Controle op syntaxis", - "GenericName[pl]": "Sprawdzanie składni", - "GenericName[pt]": "Verificação de sintaxe", - "GenericName[pt_BR]": "Verificação de sintaxe", - "GenericName[sk]": "Kontrola syntaxe", - "GenericName[sv]": "Syntaxkontroll", - "GenericName[uk]": "Перевірка синтаксису", - "GenericName[x-test]": "xxSyntax checkxx", "KPlugin": { - "Authors": [ - { - "Name": "Christoph Thielecke", - "Name[x-test]": "xxChristoph Thieleckexx" - } - ], - "Description": "Cppcheck is a tool that helps you find syntax problems in programs. http://cppcheck.sf.net/", - "Description[ast]": "Cppcheck ye una ferramienta que t'ayuda a alcontrar problemes de sintaxis en programes. http://cppcheck.sf.net/", - "Description[ca@valencia]": "El Cppcheck és una eina que vos ajudarà a trobar problemes de sintaxi en els programes. http://cppcheck.sf.net/", - "Description[ca]": "El Cppcheck és una eina que us ajudarà a trobar problemes de sintaxi en els programes. http://cppcheck.sf.net/", - "Description[cs]": "Cppcheck je nástroj jenž pomáhá s nalezením problémů se syntaxí v programech. http://cppcheck.sf.net/", - "Description[de]": "Cppcheck ist ein Werkzeug, das Ihnen hilft, Syntaxprobleme in Programmen zu finden. http://cppcheck.sf.net/", - "Description[es]": "Cppcheck es una herramienta que le ayuda a encontrar problemas de sintaxis en los programas. http://cppcheck.sf.net/", - "Description[fi]": "Cppcheck on työkalu, joka auttaa sinua etsimään ohjelmista syntaksivirheitä. http://cppcheck.sf.net/", - "Description[gl]": "Cppcheck é unha ferramenta que lle axuda a atopar problemas de sintaxe en programas. http://cppcheck.sf.net/", - "Description[hu]": "A Cppcheck egy olyan eszköz, amely segít megtalálni a szintaktikai hibákat a programokban. http://cppcheck.sf.net/", - "Description[nl]": "Cppcheck is een hulpmiddel dat helpt u bij het vinden van problemen in de syntaxis in programma's. http://cppcheck.sf.net/", - "Description[pl]": "Cppcheck jest narzędziem, które pomaga znaleźć problemy w składni twoich programów. http://cppcheck.sf.net/", - "Description[pt]": "O CppCheck é uma ferramenta que o ajuda a detectar problemas de sintaxe nos programas. http://cppcheck.sf.net/", - "Description[pt_BR]": "O Cppcheck é uma ferramenta que auxilia a detecção de problemas de sintaxe nos programas. http://cppcheck.sf.net/", - "Description[sk]": "CPPCheck je nástroj, ktorý vám pomôže nájsť problémy so syntaxou v programoch. http://cppcheck.sf.net/", - "Description[sv]": "Cppcheck är ett verktyg som hjälper till att hitta syntaxproblem i program. http://cppcheck.sf.net/", - "Description[tr]": "Cppcheck programlardaki söz dizimi hatalarını bulmanıza yardım eden bir araçtır. http://cppcheck.sf.net/", - "Description[uk]": "Cppcheck — це інструмент, що допомагатиме вам знаходити проблеми з синтаксичними конструкціями, що виникають у програмах. http://cppcheck.sf.net/", - "Description[x-test]": "xxCppcheck is a tool that helps you find syntax problems in programs. http://cppcheck.sf.net/xx", - "Description[zh_CN]": "Cppcheck 是帮助您找到程序中语法问题的工具。http://cppcheck.sf.net/", - "Icon": "kdevelop", - "Id": "kdevcppcheck", - "License": "GPL", - "Name": "Cppcheck Support", - "Name[ast]": "Sofitu Cppcheck", - "Name[bs]": "Cppcheck podrška", - "Name[ca@valencia]": "Implementació del Cppcheck", - "Name[ca]": "Implementació del Cppcheck", - "Name[cs]": "Podpora Cppcheck", - "Name[de]": "Cppcheck-Unterstützung", - "Name[es]": "Uso de Cppcheck", - "Name[fi]": "Cppcheck-tuki", - "Name[fr]": "Prise en charge de Cppcheck", - "Name[gl]": "Integración de Cppcheck", - "Name[hu]": "Cppcheck támogatás", - "Name[nl]": "Ondersteuning van CPPCheck", - "Name[pl]": "Obsługa Cppcheck", - "Name[pt]": "Suporte para o Cppcheck", - "Name[pt_BR]": "Suporte ao Cppcheck", - "Name[sk]": "Podpora Cppcheck", - "Name[sv]": "Stöd för Cppcheck", - "Name[tr]": "Cppcheck Desteği", - "Name[uk]": "Підтримка Cppcheck", - "Name[x-test]": "xxCppcheck Supportxx", - "Name[zh_CN]": "Cppcheck 支持", + "Category": "Analyzers", + "Description": "This plugin integrates Cppcheck (static analysis tool) to KDevelop", + "Description[x-test]": "xxThis plugin integrates Cppcheck (static analysis tool) to KDevelopkxx", + "Icon": "kdevelop", + "Id": "kdevcppcheck", + "License": "GPL", + "Name": "Cppcheck Support", + "Name[ast]": "Sofitu Cppcheck", + "Name[bs]": "Cppcheck podrška", + "Name[ca@valencia]": "Implementació del Cppcheck", + "Name[ca]": "Implementació del Cppcheck", + "Name[cs]": "Podpora Cppcheck", + "Name[de]": "Cppcheck-Unterstützung", + "Name[es]": "Uso de Cppcheck", + "Name[fi]": "Cppcheck-tuki", + "Name[fr]": "Prise en charge de Cppcheck", + "Name[gl]": "Integración de Cppcheck", + "Name[hu]": "Cppcheck támogatás", + "Name[nl]": "Ondersteuning van CPPCheck", + "Name[pl]": "Obsługa Cppcheck", + "Name[pt]": "Suporte para o Cppcheck", + "Name[pt_BR]": "Suporte ao Cppcheck", + "Name[sk]": "Podpora Cppcheck", + "Name[sv]": "Stöd för Cppcheck", + "Name[tr]": "Cppcheck Desteği", + "Name[uk]": "Підтримка Cppcheck", + "Name[x-test]": "xxCppcheck Supportxx", + "Name[zh_CN]": "Cppcheck 支持", "ServiceTypes": [ "KDevelop/Plugin" ] - }, - "X-KDevelop-Category": "Global", + }, + "X-KDevelop-Category": "Global", "X-KDevelop-IRequired": [ "org.kdevelop.IExecutePlugin" ], diff --git a/kdevcppcheck.rc b/kdevcppcheck.rc --- a/kdevcppcheck.rc +++ b/kdevcppcheck.rc @@ -1,10 +1,17 @@ - + - - Run - - - + + Run + + Analyse current file with + + + + + Analyse current project with + + + diff --git a/parameters.h b/parameters.h new file mode 100644 --- /dev/null +++ b/parameters.h @@ -0,0 +1,78 @@ +/* This file is part of KDevelop + + Copyright 2016 Anton Anikin + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef CPPCHECK_PARAMETERS_H +#define CPPCHECK_PARAMETERS_H + +#include + +namespace KDevelop +{ +class IProject; +} + +namespace cppcheck +{ + +class Parameters +{ +public: + explicit Parameters(KDevelop::IProject* project = nullptr); + + QStringList commandLine() const; + QStringList commandLine(QString& infoMessage) const; + + // global settings + QString executablePath; + bool hideOutputView; + bool showXmlOutput; + + // project settings + bool useProjectIncludes; + bool useSystemIncludes; + QString ignoredIncludes; + + bool checkStyle; + bool checkPerformance; + bool checkPortability; + bool checkInformation; + bool checkUnusedFunction; + bool checkMissingInclude; + bool inconclusiveAnalysis; + bool forceCheck; + bool checkConfig; + + QString extraParameters; + + QString checkPath; + +private: + QString applyPlaceholders(const QString& text) const; + + KDevelop::IProject* m_project; + + KDevelop::Path m_projectRootPath; + KDevelop::Path m_projectBuildPath; + + QList m_includeDirectories; +}; + +} +#endif diff --git a/parameters.cpp b/parameters.cpp new file mode 100644 --- /dev/null +++ b/parameters.cpp @@ -0,0 +1,226 @@ +/* This file is part of KDevelop + + Copyright 2016 Anton Anikin + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "parameters.h" + +#include "globalsettings.h" +#include "projectsettings.h" + +#include +#include +#include + +#include +#include +#include + +#include +#include + +namespace cppcheck +{ + +using ItemsList = QList; + +void includesForItem(KDevelop::ProjectBaseItem* parent, QSet& includes) +{ + foreach (auto child, parent->children()) { + if (child->type() == KDevelop::ProjectBaseItem::ProjectItemType::File) + continue; + + else if (child->type() == KDevelop::ProjectBaseItem::ProjectItemType::ExecutableTarget || + child->type() == KDevelop::ProjectBaseItem::ProjectItemType::LibraryTarget || + child->type() == KDevelop::ProjectBaseItem::ProjectItemType::Target) { + + foreach (auto dir, child->project()->buildSystemManager()->includeDirectories(child)) + includes.insert(dir); + } + + includesForItem(child, includes); + } +} + +QList includesForProject(KDevelop::IProject* project) +{ + QSet includesSet; + includesForItem(project->projectItem(), includesSet); + + return includesSet.toList(); +} + +Parameters::Parameters(KDevelop::IProject* project) + : m_project(project) +{ + ProjectSettings projectSettings; + + if (m_project) { + projectSettings.setSharedConfig(m_project->projectConfiguration()); + projectSettings.load(); + + m_projectRootPath = m_project->path(); + m_projectBuildPath = m_project->buildSystemManager()->buildDirectory(m_project->projectItem()); + m_includeDirectories = includesForProject(project); + } + + executablePath = KDevelop::Path(GlobalSettings::executablePath()).toLocalFile(); + hideOutputView = GlobalSettings::hideOutputView(); + showXmlOutput = GlobalSettings::showXmlOutput(); + + useProjectIncludes = projectSettings.useProjectIncludes(); + useSystemIncludes = projectSettings.useSystemIncludes(); + ignoredIncludes = projectSettings.ignoredIncludes(); + + checkStyle = projectSettings.checkStyle(); + checkPerformance = projectSettings.checkPerformance(); + checkPortability = projectSettings.checkPortability(); + checkInformation = projectSettings.checkInformation(); + checkUnusedFunction = projectSettings.checkUnusedFunction(); + checkMissingInclude = projectSettings.checkMissingInclude(); + + inconclusiveAnalysis = projectSettings.inconclusiveAnalysis(); + forceCheck = projectSettings.forceCheck(); + checkConfig = projectSettings.checkConfig(); + + extraParameters = projectSettings.extraParameters().trimmed(); +} + +QString Parameters::applyPlaceholders(const QString& text) const +{ + QString result(text); + + if (m_project) { + result.replace("%p", m_projectRootPath.toLocalFile()); + result.replace("%b", m_projectBuildPath.toLocalFile()); + } + + return result; +} + +QStringList Parameters::commandLine() const +{ + QString temp; + return commandLine(temp); +} + +QStringList Parameters::commandLine(QString& infoMessage) const +{ + static const auto mocHeaderRegex = QRegularExpression("#define\\s+Q_MOC_OUTPUT_REVISION\\s+(.+)"); + static const auto mocParametersRegex = QRegularExpression("-DQ_MOC_OUTPUT_REVISION=\\d{2,}"); + + const QString mocMessage = i18n( + "It seems that this project uses Qt library. For correctly work of cppcheck " + "the value for define Q_MOC_OUTPUT_REVISION must be set. Unfortunatly, the plugin is unable " + "to find this value automatically - you should set it manually by adding " + "'-DQ_MOC_OUTPUT_REVISION=XX' to extra parameters. The 'XX' value can be found in any project's " + "moc-generated file or at header file."); + + QStringList arguments; + + infoMessage.clear(); + + arguments << executablePath; + arguments << QStringLiteral("--xml-version=2"); + + if (checkStyle) + arguments << QStringLiteral("--enable=style"); + + if (checkPerformance) + arguments << QStringLiteral("--enable=performance"); + + if (checkPortability) + arguments << QStringLiteral("--enable=portability"); + + if (checkInformation) + arguments << QStringLiteral("--enable=information"); + + if (checkUnusedFunction) + arguments << QStringLiteral("--enable=unusedFunction"); + + if (checkMissingInclude) + arguments << QStringLiteral("--enable=missingInclude"); + + if (inconclusiveAnalysis) + arguments << QStringLiteral("--inconclusive"); + + if (forceCheck) + arguments << QStringLiteral("--force"); + + if (checkConfig) + arguments << QStringLiteral("--check-config"); + + // Try to automatically get value of Q_MOC_OUTPUT_REVISION for Qt-projects. + // If such define is not correctly set, cppcheck 'fails' on files with moc-includes + // and not return any errors, even if the file contains them. + if (!mocParametersRegex.match(extraParameters).hasMatch()) { + bool mocDefineFinded = false; + foreach (auto dir, m_includeDirectories) { + if (dir.path().endsWith("QtCore")) { + QFile qtHeader(dir.path() + QStringLiteral("/qobjectdefs.h")); + if (!qtHeader.open(QIODevice::ReadOnly)) { + break; + } + + while(!qtHeader.atEnd()) { + auto match = mocHeaderRegex.match(qtHeader.readLine()); + if (match.hasMatch()) { + mocDefineFinded = true; + arguments << QStringLiteral("-DQ_MOC_OUTPUT_REVISION=") + match.captured(1); + break; + } + } + break; + } + } + + if (!mocDefineFinded) + infoMessage = mocMessage; + } + + if (!extraParameters.isEmpty()) + arguments << KShell::splitArgs(applyPlaceholders(extraParameters)); + + if (m_project && useProjectIncludes) { + QList ignored; + + foreach (QString element, applyPlaceholders(ignoredIncludes).split(';')) { + if (!element.trimmed().isEmpty()) + ignored.append(KDevelop::Path(element)); + } + + foreach (auto dir, m_includeDirectories) { + if (ignored.contains(dir)) + continue; + + else if (useSystemIncludes || + dir == m_projectRootPath || m_projectRootPath.isParentOf(dir) || + dir == m_projectBuildPath || m_projectBuildPath.isParentOf(dir)) { + + arguments << QStringLiteral("-I"); + arguments << dir.toLocalFile(); + } + } + } + + arguments << checkPath; + + return arguments; +} + +} diff --git a/parsers/cppcheckparser.h b/parser.h rename from parsers/cppcheckparser.h rename to parser.h --- a/parsers/cppcheckparser.h +++ b/parser.h @@ -1,6 +1,7 @@ /* This file is part of KDevelop - * Copyright 2013 Christoph Thielecke - * Copyright 2015 Anton Anikin + + Copyright 2013 Christoph Thielecke + Copyright 2016 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public @@ -18,33 +19,33 @@ Boston, MA 02110-1301, USA. */ -#ifndef _CPPCHECKPARSER_H_ -#define _CPPCHECKPARSER_H_ - -#include -#include +#ifndef CPPCHECK_PARSER_H +#define CPPCHECK_PARSER_H #include +#include +#include + namespace cppcheck { /// A class which parses cppcheck's XML output -class CppcheckParser : public QXmlStreamReader +class CppcheckParser : protected QXmlStreamReader { public: - explicit CppcheckParser(QObject* parent = nullptr); + CppcheckParser(); ~CppcheckParser(); - QVector problems() const { return m_problems; } + using QXmlStreamReader::addData; - void parse(); + QVector parse(); private: - void storeError(); + void storeError(QVector& problems); // XML parsing - bool endElement(); + bool endElement(QVector& problems); bool startElement(); void clear(); @@ -60,14 +61,12 @@ QStack m_stateStack; // error info - int m_errorLine; - bool m_errorInconclusive; - QString m_errorFile; + QString m_errorSeverity; QString m_errorMessage; QString m_errorVerboseMessage; - QString m_errorSeverity; - - QVector m_problems; + QString m_errorFile; + int m_errorLine; + bool m_errorInconclusive; }; } diff --git a/parsers/cppcheckparser.cpp b/parser.cpp rename from parsers/cppcheckparser.cpp rename to parser.cpp --- a/parsers/cppcheckparser.cpp +++ b/parser.cpp @@ -1,6 +1,7 @@ /* This file is part of KDevelop - * Copyright 2013 Christoph Thielecke - * Copyright 2015 Anton Anikin + + Copyright 2013 Christoph Thielecke + Copyright 2016 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public @@ -18,15 +19,18 @@ Boston, MA 02110-1301, USA. */ -#include +#include "parser.h" + +#include "debug.h" + #include #include #include -#include "debug.h" -#include "cppcheckparser.h" +#include -namespace cppcheck { +namespace cppcheck +{ /** * Convert the value of attribute of element from cppcheck's @@ -58,10 +62,9 @@ return output; } -CppcheckParser::CppcheckParser(QObject*) : - m_errorLine(0), - m_errorInconclusive(false), - m_errorSeverity(Unknown) +CppcheckParser::CppcheckParser() : + m_errorLine(-1) + , m_errorInconclusive(false) { } @@ -132,7 +135,7 @@ return true; } -bool CppcheckParser::endElement() +bool CppcheckParser::endElement(QVector& problems) { qCDebug(KDEV_CPPCHECK) << "CppcheckParser::endElement: elem: " << qPrintable(name().toString()); @@ -153,7 +156,7 @@ << m_errorLine << " at " << m_errorFile << ", msg: " << m_errorMessage; - storeError(); + storeError(problems); break; case Results: @@ -170,8 +173,9 @@ return true; } -void CppcheckParser::parse() +QVector CppcheckParser::parse() { + QVector problems; qCDebug(KDEV_CPPCHECK) << "CppcheckParser::parse!"; while (!atEnd()) { @@ -187,7 +191,7 @@ break; case EndElement: - endElement(); + endElement(problems); break; case Characters: @@ -217,9 +221,11 @@ break; } } + + return problems; } -void CppcheckParser::storeError() +void CppcheckParser::storeError(QVector& problems) { KDevelop::IProblem::Ptr problem(new KDevelop::DetectedProblem()); QStringList messagePrefix; @@ -250,9 +256,10 @@ KDevelop::DocumentRange range; range.document = KDevelop::IndexedString(m_errorFile); range.setBothLines(m_errorLine - 1); + range.setBothColumns(0); problem->setFinalLocation(range); - m_problems.push_back(problem); + problems.push_back(problem); } } diff --git a/plugin.h b/plugin.h --- a/plugin.h +++ b/plugin.h @@ -1,5 +1,7 @@ /* This file is part of KDevelop - * Copyright 2013 Christoph Thielecke + + Copyright 2013 Christoph Thielecke + Copyright 2016 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public @@ -15,40 +17,34 @@ along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#ifndef CPPCHECKPLUGIN_H -#define CPPCHECKPLUGIN_H +#ifndef CPPCHECK_PLUGIN_H +#define CPPCHECK_PLUGIN_H -#include -#include +#include "job.h" -#include #include -#include - -#include -#include class KJob; -class QTreeView; +class QMenu; namespace KDevelop { -class ProblemModel; + class IProject; + class IDocument; + class ProblemModel; } namespace cppcheck { -class Control; class Plugin : public KDevelop::IPlugin { Q_OBJECT public: - Plugin(QObject *parent, const QVariantList & = QVariantList()); + Plugin(QObject* parent, const QVariantList& = QVariantList()); ~Plugin() override; @@ -57,26 +53,45 @@ KDevelop::ContextMenuExtension contextMenuExtension(KDevelop::Context* context) override; int configPages() const override { return 1; } - KDevelop::ConfigPage* configPage(int number, QWidget *parent) override; + KDevelop::ConfigPage* configPage(int number, QWidget* parent) override; int perProjectConfigPages() const override { return 1; } - KDevelop::ConfigPage* perProjectConfigPage(int number, const KDevelop::ProjectConfigOptions &options, QWidget *parent) override; - -private slots: - void loadOutput(); - void runCppcheck(bool allFiles); - void runCppcheckFile(); - void runCppcheckAll(); - void result(KJob *job); + KDevelop::ConfigPage* perProjectConfigPage(int number, const KDevelop::ProjectConfigOptions& options, QWidget* parent) override; private: - QString m_lastExec, m_lastParams, m_lastValExec, m_lastValParams, - m_lastCtExec, m_lastCtParams, m_lastKcExec; + void raiseProblemsView(); + void raiseOutputView(); + + void updateActions(); + void updateProblemsView(bool force = false); + + void problemsDetected(const QVector& problems); + void jobResult(KJob* job); + + void checkFile(); + void checkProject(); + void checkPath(const QString& path); - QScopedPointer m_model; + Job* m_job; + + KDevelop::IProject* m_currentProject; + KDevelop::IProject* m_checkedProject; + + KDevelop::IDocument* m_currentDocument; + + QHash> m_problems; + + KDevelop::ProblemModel* m_problemModel; + + QAction* m_actionAnalyseFile; + QAction* m_actionAnalyseProject; + QAction* m_actionAnalyseProjectItem; + + QMenu* m_editorContextMenuFile; + QMenu* m_editorContextMenuProject; + QMenu* m_projectItemContextMenu; }; } - -#endif // CPPCHECKPLUGIN_H +#endif diff --git a/plugin.cpp b/plugin.cpp --- a/plugin.cpp +++ b/plugin.cpp @@ -1,5 +1,7 @@ /* This file is part of KDevelop - * Copyright 2013 Christoph Thielecke + + Copyright 2013 Christoph Thielecke + Copyright 2016 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public @@ -15,213 +17,307 @@ along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include +#include "plugin.h" -#include +#include "config/globalconfigpage.h" +#include "config/projectconfigpage.h" +#include "debug.h" +#include #include -#include -#include -#include -#include -#include -#include -#include #include -#include #include -#include - -#include -#include - +#include +#include +#include +#include +#include +#include #include - -#include "debug.h" -#include "plugin.h" -#include "job.h" - -#include - -#include "./config/genericconfigpage.h" -#include "./config/cppcheckpreferences.h" #include +#include +#include +#include +#include -#include - -using namespace KDevelop; +#include +#include K_PLUGIN_FACTORY_WITH_JSON(CppcheckFactory, "kdevcppcheck.json", registerPlugin();) namespace cppcheck { -Plugin::Plugin(QObject *parent, const QVariantList&) +static const QString problemModelName("Cppcheck"); +static const QIcon analyseIcon(QIcon::fromTheme(QStringLiteral("dialog-ok"))); + +Plugin::Plugin(QObject* parent, const QVariantList&) : IPlugin("kdevcppcheck", parent) - , m_model(new KDevelop::ProblemModel(parent)) + , m_job(nullptr) + , m_currentProject(nullptr) + , m_checkedProject(nullptr) + , m_problemModel(new KDevelop::ProblemModel(this)) { + m_problemModel->setFeatures( + KDevelop::ProblemModel::SeverityFilter | + KDevelop::ProblemModel::Grouping | + KDevelop::ProblemModel::CanByPassScopeFilter); + qCDebug(KDEV_CPPCHECK) << "setting cppcheck rc file"; setXMLFile("kdevcppcheck.rc"); - QAction* act_checkfile; - act_checkfile = actionCollection()->addAction("cppcheck_file", this, SLOT(runCppcheckFile())); - act_checkfile->setStatusTip(i18n("Launches Cppcheck for current file")); - act_checkfile->setText(i18n("Cppcheck")); + m_actionAnalyseFile = new QAction("Cppcheck", this); + connect(m_actionAnalyseFile, &QAction::triggered, this, &Plugin::checkFile); + actionCollection()->addAction("cppcheck_analyse_file", m_actionAnalyseFile); + + m_actionAnalyseProject = new QAction("Cppcheck", this); + connect(m_actionAnalyseProject, &QAction::triggered, this, &Plugin::checkProject); + actionCollection()->addAction("cppcheck_analyse_project", m_actionAnalyseProject); - QAction* act_check_all_files; - act_check_all_files = actionCollection()->addAction("cppcheck_all", this, SLOT(runCppcheckAll())); - act_check_all_files->setStatusTip(i18n("Launches Cppcheck for all files")); - act_check_all_files->setText(i18n("Cppcheck (all Files)")); + m_editorContextMenuFile = new QMenu(i18n("Analyse currrent file with")); + m_editorContextMenuFile->setIcon(analyseIcon); + m_editorContextMenuFile->addAction(m_actionAnalyseFile); - IExecutePlugin* iface = KDevelop::ICore::self()->pluginController()->pluginForExtension("org.kdevelop.IExecutePlugin")->extension(); - Q_ASSERT(iface); + m_editorContextMenuProject = new QMenu(i18n("Analyse currrent project with")); + m_editorContextMenuProject->setIcon(analyseIcon); + m_editorContextMenuProject->addAction(m_actionAnalyseProject); - ProblemModelSet *pms = core()->languageController()->problemModelSet(); - pms->addModel(QStringLiteral("Cppcheck"), m_model.data()); + m_actionAnalyseProjectItem = new QAction("Cppcheck", this); + + m_projectItemContextMenu = new QMenu(i18n("Analyse with")); + m_projectItemContextMenu->setIcon(analyseIcon); + m_projectItemContextMenu->addAction(m_actionAnalyseProjectItem); + + auto updateSlot = [this](){ updateActions(); updateProblemsView(); }; + + connect(core()->documentController(), &KDevelop::IDocumentController::documentClosed, updateSlot); + connect(core()->documentController(), &KDevelop::IDocumentController::documentActivated, updateSlot); + + connect(core()->projectController(), &KDevelop::IProjectController::projectOpened, updateSlot); + connect(core()->projectController(), &KDevelop::IProjectController::projectClosed, + [this](KDevelop::IProject* project) { + if (m_job && m_job->status() == KDevelop::OutputExecuteJob::JobRunning) { + m_job->kill(KJob::EmitResult); + return; + } + + m_problems.remove(project); + updateProblemsView(true); + }); + + KDevelop::ProblemModelSet* pms = core()->languageController()->problemModelSet(); + pms->addModel(problemModelName, m_problemModel); + + updateActions(); } void Plugin::unload() { - ProblemModelSet *pms = core()->languageController()->problemModelSet(); - pms->removeModel(QStringLiteral("Cppcheck")); + KDevelop::ProblemModelSet* pms = core()->languageController()->problemModelSet(); + pms->removeModel(problemModelName); } Plugin::~Plugin() { } -void Plugin::runCppcheck(bool allFiles) +void Plugin::raiseProblemsView() { - KDevelop::IDocument *doc = core()->documentController()->activeDocument(); - if (!doc) { - QMessageBox::critical(nullptr, - i18n("Error starting Cppcheck"), - i18n("No active file, unable to deduce project.")); - return; - } + core()->languageController()->problemModelSet()->showModel(problemModelName); +} - KDevelop::IProject *project = core()->projectController()->findProjectForUrl(doc->url()); - if (!project) { - QMessageBox::critical(nullptr, - i18n("Error starting Cppcheck"), - i18n("Active file isn't in a project")); - return; - } +void Plugin::raiseOutputView() +{ + core()->uiController()->findToolView( + i18ndc("kdevstandardoutputview", "@title:window", "Test"), + nullptr, + KDevelop::IUiController::FindFlags::Raise); +} - KSharedConfigPtr ptr = project->projectConfiguration(); - KConfigGroup group = ptr->group("Cppcheck"); - if (!group.isValid()) { - QMessageBox::critical(nullptr, - i18n("Error starting Cppcheck"), - i18n("Can't load parameters. They must be set in the project settings.")); - return; - } +void Plugin::updateActions() +{ + m_currentProject = nullptr; + m_currentDocument = nullptr; - KConfigGroup group2 = KSharedConfig::openConfig()->group("Cppcheck"); - QUrl cppcheckPath = group2.readEntry("Cppcheck Path"); + m_actionAnalyseFile->setEnabled(false); + m_actionAnalyseProject->setEnabled(false); + if (m_job && m_job->status() == KDevelop::OutputExecuteJob::JobRunning) + return; - Job::Parameters params; - params.parameters = group.readEntry("cppcheckParameters", QString("")); - params.checkStyle = group.readEntry("AdditionalCheckStyle", false); - params.checkPerformance = group.readEntry("AdditionalCheckPerformance", false); - params.checkPortability = group.readEntry("AdditionalCheckPortability", false); - params.checkInformation = group.readEntry("AdditionalCheckInformation", false); - params.checkUnusedFunction = group.readEntry("AdditionalCheckUnusedFunction", false); - params.checkMissingInclude = group.readEntry("AdditionalCheckMissingInclude", false); + m_currentDocument = core()->documentController()->activeDocument(); + if (!m_currentDocument) + return; - if (cppcheckPath.toLocalFile().isEmpty()) - params.executable = QStringLiteral("/usr/bin/cppcheck"); - else - params.executable = cppcheckPath.toLocalFile(); + QUrl url = m_currentDocument->url(); - if (allFiles) - params.path = project->path().toUrl().toLocalFile(); - else - params.path = doc->url().toLocalFile(); + m_currentProject = core()->projectController()->findProjectForUrl(url); + if (!m_currentProject) + return; - Job* job = new cppcheck::Job(params, this); - connect(job, SIGNAL(finished(KJob*)), this, SLOT(result(KJob*))); - core()->runController()->registerJob( job ); + m_actionAnalyseFile->setEnabled(true); + m_actionAnalyseProject->setEnabled(true); } -void Plugin::runCppcheckFile() +void Plugin::updateProblemsView(bool force) { - bool allFiles = false; - runCppcheck(allFiles); + static KDevelop::IProject* previousProject = nullptr; + + if (force || (m_currentProject != previousProject && (!m_job || m_job->status() != KDevelop::OutputExecuteJob::JobRunning))) + { + previousProject = m_currentProject; + m_problemModel->setProblems(m_problems[m_currentProject]); + } } -void Plugin::runCppcheckAll() +void Plugin::checkFile() { - bool allFiles = true; - runCppcheck(allFiles); + if (m_currentDocument) + checkPath(m_currentDocument->url().toLocalFile()); } +void Plugin::checkProject() +{ + if (m_currentProject) + checkPath(m_currentProject->path().toLocalFile()); +} -void Plugin::loadOutput() +void Plugin::checkPath(const QString& path) { + m_checkedProject = m_currentProject; + + m_problems[m_checkedProject].clear(); + m_problemModel->clearProblems(); + + Parameters params(m_checkedProject); + params.checkPath = path; + + m_job = new cppcheck::Job(params); + + connect(m_job, &Job::problemsDetected, this, &Plugin::problemsDetected); + connect(m_job, &Job::finished, this, &Plugin::jobResult); + + core()->uiController()->registerStatus(new KDevelop::JobStatus(m_job, "cppcheck")); + core()->runController()->registerJob(m_job); + + if (params.hideOutputView) + raiseProblemsView(); + + updateActions(); } -void Plugin::result(KJob *job) +void Plugin::problemsDetected(const QVector& problems) { - Job *aj = dynamic_cast(job); - if (!aj) - return; + static int maxLength = 0; + + if (m_problems[m_checkedProject].isEmpty()) + maxLength = 0; + + // Fix problems with incorrect range, which produced by cppcheck's errors + // without element. In this case location automaticlly gets "/" + // which entails showing file dialog after selecting such problem in + // ProblemsView. To avoid this we set project's root path as problem location. + foreach (auto problem, problems) { + auto range = problem->finalLocation(); + if (range.document.isEmpty()) { + range.document = KDevelop::IndexedString(m_checkedProject->path().toLocalFile()); + problem->setFinalLocation(range); + } + } + + m_problems[m_checkedProject].append(problems); - if (aj->status() == KDevelop::OutputExecuteJob::JobStatus::JobSucceeded) { - m_model->setProblems(aj->problems()); + foreach (auto p, problems) { + m_problemModel->addProblem(p); - core()->uiController()->findToolView( - i18nd("kdevproblemreporter", "Problems"), - 0, - KDevelop::IUiController::FindFlags::Raise); + // This performs adjusing of columns width in the ProblemsView. + // Should be fixed in ProblemsView ? + if (maxLength < p->description().length()) { + maxLength = p->description().length(); + m_problemModel->setProblems(m_problems[m_checkedProject]); + } } } +void Plugin::jobResult(KJob*) +{ + updateActions(); + + if (!core()->projectController()->projects().contains(m_checkedProject)) { + m_problems.remove(m_checkedProject); + updateProblemsView(true); + } else { + m_problemModel->setProblems(m_problems[m_checkedProject]); + + if (m_job->status() == KDevelop::OutputExecuteJob::JobStatus::JobSucceeded) + raiseProblemsView(); + else + raiseOutputView(); + } + + m_job = nullptr; // job is automatically deleted later + m_checkedProject = nullptr; +} + KDevelop::ContextMenuExtension Plugin::contextMenuExtension(KDevelop::Context* context) { - KDevelop::ContextMenuExtension extension = KDevelop::IPlugin::contextMenuExtension(context); + KDevelop::ContextMenuExtension extension; + + if (context->hasType(KDevelop::Context::EditorContext)) { + if (m_currentProject) { + extension.addAction(KDevelop::ContextMenuExtension::ExtensionGroup, m_editorContextMenuFile->menuAction()); + extension.addAction(KDevelop::ContextMenuExtension::ExtensionGroup, m_editorContextMenuProject->menuAction()); + } - if ( context->type() == KDevelop::Context::EditorContext ) { - QAction* action = new QAction(QIcon::fromTheme("document-new"), i18n("Cppcheck for current file"), this); - connect(action, SIGNAL(triggered(bool)), this, SLOT(runCppcheckFile())); - extension.addAction(KDevelop::ContextMenuExtension::ExtensionGroup, action); + return extension; } + + if (context->hasType(KDevelop::Context::ProjectItemContext)) { + auto pContext = dynamic_cast(context); + if (pContext->items().size() != 1) + return extension; + + auto item = pContext->items().first(); + + switch (item->type()) { + case KDevelop::ProjectBaseItem::File: + case KDevelop::ProjectBaseItem::Folder: + case KDevelop::ProjectBaseItem::BuildFolder: + break; + + default: + return extension; + } + + m_currentProject = item->project(); + + m_actionAnalyseProjectItem->disconnect(); + connect(m_actionAnalyseProjectItem, &QAction::triggered, [this, item](bool){ checkPath(item->path().toLocalFile()); }); + + extension.addAction(KDevelop::ContextMenuExtension::ExtensionGroup, m_projectItemContextMenu->menuAction()); + } + return extension; } -KDevelop::ConfigPage* Plugin::perProjectConfigPage(int number, const ProjectConfigOptions &options, QWidget *parent) +KDevelop::ConfigPage* Plugin::perProjectConfigPage(int number, const KDevelop::ProjectConfigOptions& options, QWidget* parent) { if (number != 0) return nullptr; else - return new GenericConfigPage(options.project, parent); + return new ProjectConfigPage(this, options.project, parent); } -KDevelop::ConfigPage* Plugin::configPage(int number, QWidget *parent) +KDevelop::ConfigPage* Plugin::configPage(int number, QWidget* parent) { if (number != 0) return nullptr; else - return new CppCheckPreferences(this, parent); + return new GlobalConfigPage(this, parent); } } + #include "plugin.moc" diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,7 +1,22 @@ -ecm_add_test(test_cppcheckparser.cpp ../parsers/cppcheckparser.cpp ../debug.cpp +ecm_add_test( + test_cppcheckparser.cpp + ../debug.cpp + ../parser.cpp + TEST_NAME test_cppcheckparser - LINK_LIBRARIES Qt5::Test KDev::Tests) + LINK_LIBRARIES Qt5::Test KDev::Tests +) + +set_source_files_properties(${kdevcppcheck_CONFIG_SRCS} PROPERTIES GENERATED ON) + +ecm_add_test( + test_cppcheckjob.cpp + ../debug.cpp + ../job.cpp + ../parser.cpp + ../parameters.cpp + ${kdevcppcheck_CONFIG_SRCS} -ecm_add_test(test_cppcheckjob.cpp ../job.cpp ../parsers/cppcheckparser.cpp ../debug.cpp TEST_NAME test_cppcheckjob - LINK_LIBRARIES Qt5::Test KDev::Tests) + LINK_LIBRARIES Qt5::Test KDev::Tests +) diff --git a/tests/test_cppcheckjob.h b/tests/test_cppcheckjob.h --- a/tests/test_cppcheckjob.h +++ b/tests/test_cppcheckjob.h @@ -16,8 +16,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * *************************************************************************************/ -#ifndef TEST_CPPCHECKJOB_H -#define TEST_CPPCHECKJOB_H +#ifndef TEST_CPPCHECK_JOB_H +#define TEST_CPPCHECK_JOB_H #include diff --git a/tests/test_cppcheckjob.cpp b/tests/test_cppcheckjob.cpp --- a/tests/test_cppcheckjob.cpp +++ b/tests/test_cppcheckjob.cpp @@ -16,12 +16,14 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * *************************************************************************************/ -#include -#include -#include +#include "test_cppcheckjob.h" #include "job.h" -#include "test_cppcheckjob.h" + +#include +#include + +#include using namespace KDevelop; using namespace cppcheck; @@ -29,10 +31,10 @@ class JobTester : public Job { public: - JobTester(Job::Parameters params) : Job(params) {} + explicit JobTester(const Parameters& params) : Job(params) {} - using Job::processStdoutLines; - using Job::processStderrLines; + using Job::postProcessStdout; + using Job::postProcessStderr; QString standardOutput() const { return m_standardOutput.join('\n'); } QString xmlOutput() const { return m_xmlOutput.join('\n'); } @@ -70,11 +72,11 @@ "" }; - Job::Parameters jobParams; + Parameters jobParams; JobTester jobTester(jobParams); - jobTester.processStderrLines(stderrOutput); - jobTester.processStdoutLines(stdoutOutput); + jobTester.postProcessStderr(stderrOutput); + jobTester.postProcessStdout(stdoutOutput); // move non-XML elements from stderrOutput stdoutOutput.push_front(stderrOutput[1]); diff --git a/tests/test_cppcheckparser.h b/tests/test_cppcheckparser.h --- a/tests/test_cppcheckparser.h +++ b/tests/test_cppcheckparser.h @@ -16,8 +16,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * *************************************************************************************/ -#ifndef TEST_CPPCHECKPARSER_H -#define TEST_CPPCHECKPARSER_H +#ifndef TEST_CPPCHECK_PARSER_H +#define TEST_CPPCHECK_PARSER_H #include diff --git a/tests/test_cppcheckparser.cpp b/tests/test_cppcheckparser.cpp --- a/tests/test_cppcheckparser.cpp +++ b/tests/test_cppcheckparser.cpp @@ -18,12 +18,13 @@ #include "test_cppcheckparser.h" -#include -#include +#include "parser.h" + +#include #include +#include -#include "kdevplatform/shell/problem.h" -#include "cppcheckparser.h" +#include using namespace KDevelop; using namespace cppcheck; @@ -64,9 +65,8 @@ cppcheck::CppcheckParser parser; parser.addData(cppcheck_example_output); - parser.parse(); - const auto problems = parser.problems(); + const auto problems = parser.parse(); QVERIFY(!problems.empty()); IProblem::Ptr p = problems[0];