Skip to content

Commit

Permalink
Fix #12389 (GUI: premiumaddon is not executed properly anymore)
Browse files Browse the repository at this point in the history
  • Loading branch information
danmar committed Feb 1, 2024
1 parent 485df98 commit 1f0b8ba
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 27 deletions.
81 changes: 56 additions & 25 deletions gui/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,10 @@ void MainWindow::saveSettings() const

void MainWindow::doAnalyzeProject(ImportProject p, const bool checkLibrary, const bool checkConfiguration)
{
Settings checkSettings = getCppcheckSettings();
if (Settings::terminated())
return;

clearResults();

mIsLogfileLoaded = false;
Expand Down Expand Up @@ -522,7 +526,6 @@ void MainWindow::doAnalyzeProject(ImportProject p, const bool checkLibrary, cons
checkLockDownUI(); // lock UI while checking

mUI->mResults->setCheckDirectory(checkPath);
Settings checkSettings = getCppcheckSettings();
checkSettings.force = false;
checkSettings.checkLibrary = checkLibrary;
checkSettings.checkConfiguration = checkConfiguration;
Expand Down Expand Up @@ -550,9 +553,13 @@ void MainWindow::doAnalyzeProject(ImportProject p, const bool checkLibrary, cons

void MainWindow::doAnalyzeFiles(const QStringList &files, const bool checkLibrary, const bool checkConfiguration)
{
if (files.isEmpty()) {
if (files.isEmpty())
return;
}

Settings checkSettings = getCppcheckSettings();
if (Settings::terminated())
return;

clearResults();

mIsLogfileLoaded = false;
Expand Down Expand Up @@ -591,7 +598,6 @@ void MainWindow::doAnalyzeFiles(const QStringList &files, const bool checkLibrar
checkLockDownUI(); // lock UI while checking

mUI->mResults->setCheckDirectory(checkPath);
Settings checkSettings = getCppcheckSettings();
checkSettings.checkLibrary = checkLibrary;
checkSettings.checkConfiguration = checkConfiguration;

Expand All @@ -614,6 +620,10 @@ void MainWindow::doAnalyzeFiles(const QStringList &files, const bool checkLibrar

void MainWindow::analyzeCode(const QString& code, const QString& filename)
{
Settings checkSettings = getCppcheckSettings();
if (Settings::terminated())
return;

// Initialize dummy ThreadResult as ErrorLogger
ThreadResult result;
result.setFiles(QStringList(filename));
Expand All @@ -628,7 +638,7 @@ void MainWindow::analyzeCode(const QString& code, const QString& filename)

// Create CppCheck instance
CppCheck cppcheck(result, true, nullptr);
cppcheck.settings() = getCppcheckSettings();
cppcheck.settings() = checkSettings;

// Check
checkLockDownUI();
Expand Down Expand Up @@ -905,13 +915,12 @@ bool MainWindow::tryLoadLibrary(Library *library, const QString& filename)
return true;
}

void MainWindow::loadAddon(Settings &settings, const QString &filesDir, const QString &pythonCmd, const QString& addon)
QString 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
const QString addonFilePath = fromNativePath(ProjectFile::getAddonFilePath(filesDir, addon));

addonFilePath.replace(QChar('\\'), QChar('/'));
if (addonFilePath.isEmpty())
return tr("File not found: '%1'").arg(addon);

picojson::object obj;
obj["script"] = picojson::value(addonFilePath.toStdString());
Expand All @@ -929,42 +938,56 @@ void MainWindow::loadAddon(Settings &settings, const QString &filesDir, const QS
obj["args"] = picojson::value(arg.toStdString());
}
}
picojson::value json;
json.set(std::move(obj));
std::string json_str = json.serialize();

const std::string& json_str = picojson::value(obj).serialize();

AddonInfo addonInfo;
addonInfo.getAddonInfo(json_str, settings.exename); // TODO: handle error
const std::string errmsg = addonInfo.getAddonInfo(json_str, settings.exename);
if (!errmsg.empty())
return tr("Failed to load/setup addon %1: %2").arg(addon, QString::fromStdString(errmsg));
settings.addonInfos.emplace_back(std::move(addonInfo));

settings.addons.emplace(std::move(json_str));
settings.addons.emplace(json_str);

return "";
}

Settings MainWindow::getCppcheckSettings()
{
saveSettings(); // Save settings

Settings result;
Settings::terminate(false);

result.exename = QCoreApplication::applicationFilePath().toStdString();

const bool std = tryLoadLibrary(&result.library, "std.cfg");
if (!std)
QMessageBox::critical(this, tr("Error"), tr("Failed to load %1. Your Cppcheck installation is broken. You can use --data-dir=<directory> at the command line to specify where this file is located. Please note that --data-dir is supposed to be used by installation scripts and therefore the GUI does not start when it is used, all that happens is that the setting is configured.").arg("std.cfg"));
if (!std) {
QMessageBox::critical(this, tr("Error"), tr("Failed to load %1. Your Cppcheck installation is broken. You can use --data-dir=<directory> at the command line to specify where this file is located. Please note that --data-dir is supposed to be used by installation scripts and therefore the GUI does not start when it is used, all that happens is that the setting is configured.\n\nAnalysis is aborted.").arg("std.cfg"));
Settings::terminate(true);
return result;
}

const QString filesDir(getDataDir());
const QString pythonCmd = fromNativePath(mSettings->value(SETTINGS_PYTHON_PATH).toString());

{
const QString cfgErr = QString::fromStdString(result.loadCppcheckCfg());
if (!cfgErr.isEmpty())
QMessageBox::critical(this, tr("Error"), tr("Failed to load %1 - %2").arg("cppcheck.cfg").arg(cfgErr));
if (!cfgErr.isEmpty()) {
QMessageBox::critical(this, tr("Error"), tr("Failed to load %1 - %2\n\nAnalysis is aborted.").arg("cppcheck.cfg").arg(cfgErr));
Settings::terminate(true);
return result;
}

const auto cfgAddons = result.addons;
result.addons.clear();
for (const std::string& addon : cfgAddons) {
// TODO: support addons which are a script and not a file
loadAddon(result, filesDir, pythonCmd, QString::fromStdString(addon));
const QString addonError = loadAddon(result, filesDir, pythonCmd, QString::fromStdString(addon));
if (!addonError.isEmpty()) {
QMessageBox::critical(this, tr("Error"), tr("%1\n\nAnalysis is aborted.").arg(addonError));
Settings::terminate(true);
}
}
}

Expand Down Expand Up @@ -1045,7 +1068,11 @@ Settings MainWindow::getCppcheckSettings()
result.checkUnknownFunctionReturn.insert(s.toStdString());

for (const QString& addon : mProjectFile->getAddons()) {
loadAddon(result, filesDir, pythonCmd, addon);
const QString addonError = loadAddon(result, filesDir, pythonCmd, addon);
if (!addonError.isEmpty()) {
QMessageBox::critical(this, tr("Error"), tr("%1\n\nAnalysis is aborted.").arg(addonError));
Settings::terminate(true);
}
}

if (isCppcheckPremium()) {
Expand Down Expand Up @@ -1097,8 +1124,6 @@ Settings MainWindow::getCppcheckSettings()
result.jobs = 1;
}

Settings::terminate(false);

return result;
}

Expand Down Expand Up @@ -1223,6 +1248,10 @@ void MainWindow::reAnalyzeSelected(const QStringList& files)
if (mThread->isChecking())
return;

const Settings& checkSettings = getCppcheckSettings();
if (Settings::terminated())
return;

// Clear details, statistics and progress
mUI->mResults->clear(false);
for (int i = 0; i < files.size(); ++i)
Expand All @@ -1242,7 +1271,6 @@ void MainWindow::reAnalyzeSelected(const QStringList& files)
// considered in "Modified Files Check" performed after "Selected Files Check"
// TODO: Should we store per file CheckStartTime?
QDateTime saveCheckStartTime = mThread->getCheckStartTime();
const Settings& checkSettings = getCppcheckSettings();
mThread->check(checkSettings);
mUI->mResults->setCheckSettings(checkSettings);
mThread->setCheckStartTime(saveCheckStartTime);
Expand All @@ -1254,6 +1282,10 @@ void MainWindow::reAnalyze(bool all)
if (files.empty())
return;

const Settings& checkSettings = getCppcheckSettings();
if (Settings::terminated())
return;

// Clear details, statistics and progress
mUI->mResults->clear(all);

Expand All @@ -1268,7 +1300,6 @@ void MainWindow::reAnalyze(bool all)
qDebug() << "Rechecking project file" << mProjectFile->getFilename();

mThread->setCheckFiles(all);
const Settings& checkSettings = getCppcheckSettings();
mThread->check(checkSettings);
mUI->mResults->setCheckSettings(checkSettings);
}
Expand Down
2 changes: 1 addition & 1 deletion gui/mainwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ private slots:
*/
bool tryLoadLibrary(Library *library, const QString& filename);

void loadAddon(Settings &settings, const QString &filesDir, const QString &pythonCmd, const QString& addon);
QString loadAddon(Settings &settings, const QString &filesDir, const QString &pythonCmd, const QString& addon);

/**
* @brief Update project MRU items in File-menu.
Expand Down
3 changes: 3 additions & 0 deletions gui/projectfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 += "/";

Expand Down
20 changes: 20 additions & 0 deletions gui/test/projectfile/testprojectfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

#include <QList>
#include <QStringList>
#include <QTemporaryDir>
#include <QtTest>

// Mock...
Expand Down Expand Up @@ -116,4 +117,23 @@ 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.close();

// Relative path to addon
QCOMPARE(ProjectFile::getAddonFilePath(tempdir.path(), "addon"), filepath);
QCOMPARE(ProjectFile::getAddonFilePath(tempdir.path(), "not exist"), QString());

// Absolute path to addon
QCOMPARE(ProjectFile::getAddonFilePath("/not/exist", filepath), filepath);
QCOMPARE(ProjectFile::getAddonFilePath(tempdir.path(), filepath), filepath);
}

QTEST_MAIN(TestProjectFile)
2 changes: 2 additions & 0 deletions gui/test/projectfile/testprojectfile.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,6 @@ private slots:
void loadSimple() const;
void loadSimpleWithIgnore() const;
void loadSimpleNoroot() const;

void getAddonFilePath() const;
};
2 changes: 1 addition & 1 deletion lib/addoninfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ static std::string parseAddonInfo(AddonInfo& addoninfo, const picojson::value &j
if (!val.is<std::string>())
return "Loading " + fileName + " failed. 'executable' must be a string.";
addoninfo.executable = getFullPath(val.get<std::string>(), fileName);
return ""; // TODO: why bail out?
return ""; // <- do not load both "executable" and "script".
}
}

Expand Down

0 comments on commit 1f0b8ba

Please sign in to comment.