diff --git a/CMakeLists.txt b/CMakeLists.txt index f5d708a..f268818 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,57 +1,61 @@ project(cppcheck) set(VERSION_MAJOR 1) set(VERSION_MINOR 90) set(VERSION_PATCH 90) # KDevplatform dependency version set(KDEVPLATFORM_VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}") cmake_minimum_required(VERSION 2.8.12) find_package (ECM 0.0.9 REQUIRED NO_MODULE) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH}) include(ECMAddTests) include(KDEInstallDirs) include(KDECMakeSettings) include(KDECompilerSettings) find_package(Qt5 REQUIRED Core Widgets Test) find_package(KF5 REQUIRED COMPONENTS IconThemes ItemModels ThreadWeaver TextEditor I18n) 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 ) set(kdevcppcheck_PART_SRCS debug.cpp job.cpp plugin.cpp config/genericconfigpage.cpp config/cppcheckpreferences.cpp parsers/cppcheckparser.cpp ) 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) install(FILES kdevcppcheck.rc DESTINATION ${KXMLGUI_INSTALL_DIR}/kdevcppcheck) + +ecm_add_test(parsers/test_cppcheckparser.cpp parsers/cppcheckparser.cpp debug.cpp + TEST_NAME test_cppcheckparser + LINK_LIBRARIES Qt5::Test KDev::Tests) diff --git a/parsers/cppcheckparser.cpp b/parsers/cppcheckparser.cpp index 0a28d57..aad0dca 100644 --- a/parsers/cppcheckparser.cpp +++ b/parsers/cppcheckparser.cpp @@ -1,207 +1,197 @@ /* 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, 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 "cppcheckparser.h" #include #include #include #include #include #include #include #include "debug.h" #include #include namespace cppcheck { CppcheckParser::CppcheckParser(QObject* parent) : ErrorLine(0), Severity(Unknown) { Q_UNUSED(parent) } CppcheckParser::~CppcheckParser() { } void CppcheckParser::clear() { m_stateStack.clear(); m_buffer.clear(); cppcheckArgs.clear(); programArgs.clear(); } bool CppcheckParser::startElement() { m_buffer.clear(); State newState = Unknown; qCDebug(KDEV_CPPCHECK) << "CppcheckParser::startElement: elem: " << qPrintable(name().toString()); if (name() == "results") newState = Results; else if (name() == "cppcheck") newState = CppCheck; else if (name() == "errors") newState = Errors; else if (name() == "location") { newState = Location; if (attributes().hasAttribute("line")) ErrorLine = attributes().value("line").toString().toInt(); - if (attributes().hasAttribute("file")) { + if (attributes().hasAttribute("file")) ErrorFile = attributes().value("file").toString(); - /* get project path */ - ProjectPath = ""; - for (int i = 0; i < KDevelop::ICore::self()->projectController()->projects().count(); i++) { - if (KDevelop::ICore::self()->projectController()->findProjectForUrl(QUrl::fromLocalFile(ErrorFile)) != nullptr) { - ProjectPath = KDevelop::ICore::self()->projectController()->projects().at(i)->path().toUrl().toLocalFile(); - } - } - ErrorFile.remove(ProjectPath); - } } else if (name() == "error") { newState = Error; ErrorLine = -1; ErrorFile.clear(); Message.clear(); MessageVerbose.clear(); - ProjectPath.clear(); Severity = "unknown"; if (attributes().hasAttribute("msg")) Message = attributes().value("msg").toString(); if (attributes().hasAttribute("verbose")) MessageVerbose = attributes().value("verbose").toString(); if (attributes().hasAttribute("severity")) Severity = attributes().value("severity").toString(); } else { m_stateStack.push(m_stateStack.top()); return true; } m_stateStack.push(newState); return true; } bool CppcheckParser::endElement() { qCDebug(KDEV_CPPCHECK) << "CppcheckParser::endElement: elem: " << qPrintable(name().toString()); State state = m_stateStack.pop(); switch (state) { case CppCheck: if (attributes().hasAttribute("version")) qCDebug(KDEV_CPPCHECK) << "Cppcheck report version: " << attributes().value("version"); break; case Errors: // errors finished break; case Error: qCDebug(KDEV_CPPCHECK) << "CppcheckParser::endElement: new error elem: line: " << ErrorLine << " at " << ErrorFile << ", msg: " << Message; storeError(); break; case Results: // results finished break; case Location: break; default: break; } return true; } void CppcheckParser::parse() { qCDebug(KDEV_CPPCHECK) << "CppcheckParser::parse!"; while (!atEnd()) { int readNextVal = readNext(); switch (readNextVal) { case StartDocument: clear(); break; case StartElement: startElement(); break; case EndElement: endElement(); break; case Characters: m_buffer += text().toString(); break; default: qCDebug(KDEV_CPPCHECK) << "CppcheckParser::startElement: case: " << readNextVal; break; } } qCDebug(KDEV_CPPCHECK) << "CppcheckParser::parse: end"; if (hasError()) { switch (error()) { case CustomError: case UnexpectedElementError: case NotWellFormedError: KMessageBox::error(qApp->activeWindow(), i18n("Cppcheck XML Parsing: error at line %1, column %2: %3", lineNumber(), columnNumber(), errorString()), i18n("Cppcheck Error")); break; case NoError: case PrematureEndOfDocumentError: break; } } } void CppcheckParser::storeError() { KDevelop::IProblem::Ptr problem(new KDevelop::DetectedProblem()); problem->setDescription(Message); problem->setExplanation(MessageVerbose); KDevelop::DocumentRange range; - range.document = KDevelop::IndexedString(ProjectPath + ErrorFile); + range.document = KDevelop::IndexedString(ErrorFile); range.setBothLines(ErrorLine - 1); problem->setFinalLocation(range); if (Severity == "error") problem->setSeverity(KDevelop::IProblem::Error); else if (Severity == "warning") problem->setSeverity(KDevelop::IProblem::Warning); else problem->setSeverity(KDevelop::IProblem::Hint); problem->setSource(KDevelop::IProblem::Plugin); m_problems.push_back(problem); } } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..e7e2a59 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,3 @@ +ecm_add_test(test_cppcheckparser.cpp ../parsers/cppcheckparser.cpp ../debug.cpp + TEST_NAME test_cppcheckparser + LINK_LIBRARIES Qt5::Test KDev::Tests) diff --git a/tests/test_cppcheckparser.cpp b/tests/test_cppcheckparser.cpp new file mode 100644 index 0000000..ff017e6 --- /dev/null +++ b/tests/test_cppcheckparser.cpp @@ -0,0 +1,72 @@ +/************************************************************************************* + * Copyright 2016 (C) Peje Nilsson * + * * + * 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, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * + *************************************************************************************/ + +#include "test_cppcheckparser.h" + +#include +#include +#include + +#include "kdevplatform/shell/problem.h" +#include "cppcheckparser.h" + +using namespace KDevelop; +using namespace cppcheck; + +void TestCppcheckParser::initTestCase() +{ + AutoTestShell::init(); + TestCore::initialize(Core::NoUi); +} + +void TestCppcheckParser::cleanupTestCase() +{ + TestCore::shutdown(); +} + +void TestCppcheckParser::testParser() +{ + const QString cppcheck_example_output = QStringLiteral( + "\n" + "\n" + " " + " " + " " + " " + " " + " " + ""); + + cppcheck::CppcheckParser parser; + + parser.addData(cppcheck_example_output); + parser.parse(); + + auto problems = parser.problems(); + QVERIFY(!problems.empty()); + + KDevelop::IProblem::Ptr p = problems.front(); + QCOMPARE(p->description(), QStringLiteral("Memory leak: ej")); + QCOMPARE(p->explanation(), QStringLiteral("Memory leak: ej")); + QCOMPARE(p->finalLocation().document.str(), QStringLiteral("/kdesrc/kdev-cppcheck/plugin.cpp")); + QCOMPARE(p->finalLocation().start().line()+1, 169); + QCOMPARE(p->severity(), KDevelop::IProblem::Error); + QCOMPARE(p->source(), KDevelop::IProblem::Plugin); +} + +QTEST_GUILESS_MAIN(TestCppcheckParser); diff --git a/tests/test_cppcheckparser.h b/tests/test_cppcheckparser.h new file mode 100644 index 0000000..c77c80b --- /dev/null +++ b/tests/test_cppcheckparser.h @@ -0,0 +1,34 @@ +/************************************************************************************* + * Copyright 2016 (C) Peje Nilsson * + * * + * 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, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * + *************************************************************************************/ + +#ifndef TEST_CPPCHECKPARSER_H +#define TEST_CPPCHECKPARSER_H + +#include + +class TestCppcheckParser : public QObject +{ + Q_OBJECT +private slots: + void initTestCase(); + void cleanupTestCase(); + + void testParser(); +}; + +#endif // TEST_CPPCHECKPARSER_H