From f10f7460b6ff4574ec2d5e42c7c09e94d0fd5bc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Mon, 29 Jan 2024 20:16:00 +0100 Subject: [PATCH] Fix #12389 (GUI: premiumaddon is not executed properly anymore) --- gui/mainwindow.cpp | 43 +++++++++++++----------- gui/projectfile.cpp | 3 ++ gui/test/projectfile/testprojectfile.cpp | 19 +++++++++++ gui/test/projectfile/testprojectfile.h | 2 ++ lib/cppcheck.cpp | 20 +++++++++++ lib/cppcheck.h | 3 ++ lib/errorlogger.cpp | 1 + 7 files changed, 72 insertions(+), 19 deletions(-) diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index 3744f520c58f..a32736f1964e 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -907,34 +907,39 @@ bool MainWindow::tryLoadLibrary(Library *library, const QString& filename) void MainWindow::loadAddon(Settings &settings, const QString &filesDir, const QString &pythonCmd, const QString& addon) { - QString addonFilePath = ProjectFile::getAddonFilePath(filesDir, addon); - if (addonFilePath.isEmpty()) - return; // TODO: report an error - - addonFilePath.replace(QChar('\\'), QChar('/')); + const QString addonFilePath = fromNativePath(ProjectFile::getAddonFilePath(filesDir, addon)); picojson::object obj; - obj["script"] = picojson::value(addonFilePath.toStdString()); - if (!pythonCmd.isEmpty()) - obj["python"] = picojson::value(pythonCmd.toStdString()); - - if (!isCppcheckPremium() && addon == "misra") { - const QString misraFile = fromNativePath(mSettings->value(SETTINGS_MISRA_FILE).toString()); - if (!misraFile.isEmpty()) { - QString arg; - if (misraFile.endsWith(".pdf", Qt::CaseInsensitive)) - arg = "--misra-pdf=" + misraFile; - else - arg = "--rule-texts=" + misraFile; - obj["args"] = picojson::value(arg.toStdString()); + if (addonFilePath.isEmpty()) // Ensure there will be "fileNotFound" errors + obj["script"] = picojson::value(addon.toStdString()); + else { + obj["script"] = picojson::value(addonFilePath.toStdString()); + if (!pythonCmd.isEmpty()) + obj["python"] = picojson::value(pythonCmd.toStdString()); + + if (!isCppcheckPremium() && addon == "misra") { + const QString misraFile = fromNativePath(mSettings->value(SETTINGS_MISRA_FILE).toString()); + if (!misraFile.isEmpty()) { + QString arg; + if (misraFile.endsWith(".pdf", Qt::CaseInsensitive)) + arg = "--misra-pdf=" + misraFile; + else + arg = "--rule-texts=" + misraFile; + obj["args"] = picojson::value(arg.toStdString()); + } } } + picojson::value json; json.set(std::move(obj)); std::string json_str = json.serialize(); AddonInfo addonInfo; - addonInfo.getAddonInfo(json_str, settings.exename); // TODO: handle error + if (addonFilePath.isEmpty()) { + addonInfo.name = addon.toStdString(); + } else { + addonInfo.getAddonInfo(json_str, settings.exename); // TODO: handle error + } settings.addonInfos.emplace_back(std::move(addonInfo)); settings.addons.emplace(std::move(json_str)); diff --git a/gui/projectfile.cpp b/gui/projectfile.cpp index f24f6eece936..393063bb49da 100644 --- a/gui/projectfile.cpp +++ b/gui/projectfile.cpp @@ -1115,6 +1115,9 @@ void ProjectFile::SafeChecks::saveToXml(QXmlStreamWriter &xmlWriter) const QString ProjectFile::getAddonFilePath(QString filesDir, const QString &addon) { + if (QFile(addon).exists()) + return addon; + if (!filesDir.endsWith("/")) filesDir += "/"; diff --git a/gui/test/projectfile/testprojectfile.cpp b/gui/test/projectfile/testprojectfile.cpp index 6e5e73b0f063..13743244248a 100644 --- a/gui/test/projectfile/testprojectfile.cpp +++ b/gui/test/projectfile/testprojectfile.cpp @@ -28,6 +28,7 @@ #include #include +#include #include // Mock... @@ -116,4 +117,22 @@ void TestProjectFile::loadSimpleNoroot() const QCOMPARE(defines[0], QString("FOO")); } +void TestProjectFile::getAddonFilePath() const +{ + QTemporaryDir tempdir; + QVERIFY(tempdir.isValid()); + const QString filepath(tempdir.path() + "/addon.py"); + + QFile file(filepath); + QVERIFY(file.open(QIODevice::WriteOnly | QIODevice::Text)); + file.write(""); + file.close(); + + // Relative path to addon + QCOMPARE(ProjectFile::getAddonFilePath(tempdir.path(), "addon"), filepath); + + // Absolute path to addon + QCOMPARE(ProjectFile::getAddonFilePath("/not/exist", filepath), filepath); +} + QTEST_MAIN(TestProjectFile) diff --git a/gui/test/projectfile/testprojectfile.h b/gui/test/projectfile/testprojectfile.h index b0bc7d969691..47ed517f412a 100644 --- a/gui/test/projectfile/testprojectfile.h +++ b/gui/test/projectfile/testprojectfile.h @@ -27,4 +27,6 @@ private slots: void loadSimple() const; void loadSimpleWithIgnore() const; void loadSimpleNoroot() const; + + void getAddonFilePath() const; }; diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index d587cef15b55..0e43eb3f1898 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -1033,6 +1033,21 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string return mExitCode; } +void CppCheck::fileNotFoundError(const std::string &filename, const std::string& msg) +{ + const ErrorMessage::FileLocation loc1(filename, 0, 0); + std::list callstack(1, loc1); + + ErrorMessage errmsg(callstack, + emptyString, + Severity::error, + msg, + "fileNotFound", + Certainty::normal); + + mErrorLogger.reportErr(errmsg); +} + // TODO: replace with ErrorMessage::fromInternalError() void CppCheck::internalError(const std::string &filename, const std::string &msg) { @@ -1440,6 +1455,11 @@ void CppCheck::executeAddons(const std::vector& files, const std::s if (addonInfo.name != "misra" && !addonInfo.ctu && endsWith(files.back(), ".ctu-info")) continue; + if (addonInfo.scriptFile.empty() && addonInfo.executable.empty()) { + fileNotFoundError(file0, "Fail to execute addon " + addonInfo.name); + continue; + } + const std::vector results = executeAddon(addonInfo, mSettings.addonPython, fileList.empty() ? files[0] : fileList, mSettings.premiumArgs, mExecuteCommand); diff --git a/lib/cppcheck.h b/lib/cppcheck.h index f5ea60f23ed6..7519ae1ec1b0 100644 --- a/lib/cppcheck.h +++ b/lib/cppcheck.h @@ -158,6 +158,9 @@ class CPPCHECKLIB CppCheck : ErrorLogger { bool hasRule(const std::string &tokenlist) const; #endif + /** @brief A file is not found => report error message */ + void fileNotFoundError(const std::string &filename, const std::string& msg); + /** @brief There has been an internal error => Report information message */ void internalError(const std::string &filename, const std::string &msg); diff --git a/lib/errorlogger.cpp b/lib/errorlogger.cpp index fbb635c691df..112a2592f081 100644 --- a/lib/errorlogger.cpp +++ b/lib/errorlogger.cpp @@ -42,6 +42,7 @@ const std::set ErrorLogger::mCriticalErrorIds{ "cppcheckError", "cppcheckLimit", + "fileNotFound", "internalAstError", "instantiationError", "internalError",