GUI: configuration of premium features

This commit is contained in:
Daniel Marjamäki 2022-08-22 21:11:28 +02:00
parent 1262c98416
commit 5d267000e2
10 changed files with 224 additions and 28 deletions

View File

@ -946,6 +946,20 @@ Settings MainWindow::getCppcheckSettings()
json += " }";
result.addons.push_back(json.toStdString());
}
if (isCppcheckPremium()) {
QString premiumArgs;
if (mProjectFile->getBughunting())
premiumArgs += " --bughunting";
if (mProjectFile->getCertIntPrecision() > 0)
premiumArgs += " --cert-c-int-precision=" + QString::number(mProjectFile->getCertIntPrecision());
if (mProjectFile->getAddons().contains("misra"))
premiumArgs += " --misra-c-2012";
for (const QString& c: mProjectFile->getCodingStandards()) {
premiumArgs += " --" + c;
}
result.premiumArgs = premiumArgs.mid(1).toStdString();
}
}
// Include directories (and files) are searched in listed order.
@ -1664,7 +1678,7 @@ void MainWindow::newProjectFile()
mProjectFile->setFilename(filepath);
mProjectFile->setBuildDir(filename.left(filename.indexOf(".")) + "-cppcheck-build-dir");
ProjectFileDialog dlg(mProjectFile, this);
ProjectFileDialog dlg(mProjectFile, isCppcheckPremium(), this);
if (dlg.exec() == QDialog::Accepted) {
addProjectMRU(filepath);
analyzeProject(mProjectFile);
@ -1695,7 +1709,7 @@ void MainWindow::editProjectFile()
return;
}
ProjectFileDialog dlg(mProjectFile, this);
ProjectFileDialog dlg(mProjectFile, isCppcheckPremium(), this);
if (dlg.exec() == QDialog::Accepted) {
mProjectFile->write();
analyzeProject(mProjectFile);
@ -1864,3 +1878,7 @@ void MainWindow::suppressIds(QStringList ids)
mProjectFile->setSuppressions(suppressions);
mProjectFile->write();
}
bool MainWindow::isCppcheckPremium() const {
return mCppcheckCfgProductName.startsWith("Cppcheck Premium ");
}

View File

@ -230,6 +230,8 @@ protected slots:
private:
bool isCppcheckPremium() const;
/** Get filename for last results */
QString getLastResults() const;

View File

@ -74,6 +74,11 @@ void ProjectFile::clear()
mVsConfigurations.clear();
mTags.clear();
mWarningTags.clear();
// Premium
mBughunting = false;
mCertIntPrecision = 0;
mCodingStandards.clear();
}
bool ProjectFile::read(const QString &filename)
@ -195,6 +200,15 @@ bool ProjectFile::read(const QString &filename)
// VSConfiguration
if (xmlReader.name() == QString(CppcheckXml::VSConfigurationElementName))
readVsConfigurations(xmlReader);
// Cppcheck Premium
if (xmlReader.name() == QString(CppcheckXml::BughuntingElementName))
mBughunting = true;
if (xmlReader.name() == QString(CppcheckXml::CodingStandardsElementName))
readStringList(mAddons, xmlReader, CppcheckXml::CodingStandardElementName);
if (xmlReader.name() == QString(CppcheckXml::CertIntPrecisionElementName))
mCertIntPrecision = readInt(xmlReader, 0);
break;
case QXmlStreamReader::EndElement:
@ -928,6 +942,23 @@ bool ProjectFile::write(const QString &filename)
}
}
// Cppcheck Premium
if (mBughunting) {
xmlWriter.writeStartElement(CppcheckXml::BughuntingElementName);
xmlWriter.writeEndElement();
}
writeStringList(xmlWriter,
mCodingStandards,
CppcheckXml::CodingStandardsElementName,
CppcheckXml::CodingStandardElementName);
if (mCertIntPrecision > 0) {
xmlWriter.writeStartElement(CppcheckXml::CertIntPrecisionElementName);
xmlWriter.writeCharacters(QString::number(mCertIntPrecision));
xmlWriter.writeEndElement();
}
xmlWriter.writeEndDocument();
file.close();
return true;

View File

@ -333,6 +333,36 @@ public:
/** Get tags for a warning */
QString getWarningTags(std::size_t hash) const;
/** Bughunting (Cppcheck Premium) */
void setBughunting(bool bughunting) {
mBughunting = bughunting;
}
bool getBughunting() const {
return mBughunting;
}
/** @brief Get list of coding standards (checked by Cppcheck Premium). */
QStringList getCodingStandards() const {
return mCodingStandards;
}
/**
* @brief Set list of coding standards (checked by Cppcheck Premium).
* @param codingStandards List of coding standards.
*/
void setCodingStandards(QStringList codingStandards) {
mCodingStandards = std::move(codingStandards);
}
/** Cert C: int precision */
void setCertIntPrecision(int p) {
mCertIntPrecision = p;
}
int getCertIntPrecision() const {
return mCertIntPrecision;
}
/**
* @brief Write project file (to disk).
* @param filename Filename to use.
@ -543,6 +573,15 @@ private:
*/
QStringList mAddons;
bool mBughunting;
/**
* @brief List of coding standards, checked by Cppcheck Premium.
*/
QStringList mCodingStandards;
int mCertIntPrecision;
/** @brief Execute clang analyzer? */
bool mClangAnalyzer;

View File

@ -773,24 +773,26 @@
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<widget class="QGroupBox" name="groupBox_12">
<property name="title">
<string>Coding standards</string>
</property>
</widget>
</item>
<layout class="QVBoxLayout" name="verticalLayout_20">
<item>
<widget class="QCheckBox" name="mAddonMisra">
<widget class="QCheckBox" name="mMisraC2012">
<property name="text">
<string>MISRA C 2012</string>
<string>Misra C 2012</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<layout class="QHBoxLayout" name="mLayoutMisraRuleTexts">
<item>
<widget class="QLabel" name="label_2">
<widget class="QLabel" name="mLabelMisraFile">
<property name="text">
<string>MISRA rule texts</string>
</property>
@ -812,6 +814,57 @@
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="mPremiumCertC">
<property name="text">
<string>Cert C</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_10">
<item>
<widget class="QLabel" name="mLabelCertIntPrecision">
<property name="text">
<string>CERT-INT35-C: int precision (if size equals precision, you can leave empty)</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="mEditCertIntPrecision"/>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="mMisraCpp2008">
<property name="text">
<string>Misra C++ 2008</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="mAutosar">
<property name="text">
<string>Autosar</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="mGroupboxBughunting">
<property name="title">
<string>Bug hunting</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_21">
<item>
<widget class="QCheckBox" name="mBughunting">
<property name="text">
<string>Bug hunting</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>

View File

@ -40,6 +40,11 @@
#include <QRegularExpressionValidator>
#include <QSettings>
static const char ADDON_MISRA[] = "misra";
static const char CODING_STANDARD_MISRA_CPP_2008[] = "misra-cpp-2008";
static const char CODING_STANDARD_CERT_C[] = "cert-c-2016";
static const char CODING_STANDARD_AUTOSAR[] = "autosar";
class QModelIndex;
/** Return paths from QListWidget */
@ -79,10 +84,11 @@ QStringList ProjectFileDialog::getProjectConfigs(const QString &fileName)
return ret;
}
ProjectFileDialog::ProjectFileDialog(ProjectFile *projectFile, QWidget *parent)
ProjectFileDialog::ProjectFileDialog(ProjectFile *projectFile, bool premium, QWidget *parent)
: QDialog(parent)
, mUI(new Ui::ProjectFile)
, mProjectFile(projectFile)
, mPremium(premium)
{
mUI->setupUi(this);
@ -191,6 +197,9 @@ ProjectFileDialog::ProjectFileDialog(ProjectFile *projectFile, QWidget *parent)
platformFiles.sort();
mUI->mComboBoxPlatform->addItems(platformFiles);
// integer. allow empty.
mUI->mEditCertIntPrecision->setValidator(new QRegularExpressionValidator(QRegularExpression("[0-9]*"),this));
mUI->mEditTags->setValidator(new QRegularExpressionValidator(QRegularExpression("[a-zA-Z0-9 ;]*"),this));
const QRegularExpression undefRegExp("\\s*([a-zA-Z_][a-zA-Z0-9_]*[; ]*)*");
@ -340,15 +349,36 @@ void ProjectFileDialog::loadFromProjectFile(const ProjectFile *projectFile)
const QString dataDir = getDataDir();
updateAddonCheckBox(mUI->mAddonThreadSafety, projectFile, dataDir, "threadsafety");
updateAddonCheckBox(mUI->mAddonY2038, projectFile, dataDir, "y2038");
updateAddonCheckBox(mUI->mAddonMisra, projectFile, dataDir, "misra");
updateAddonCheckBox(mUI->mMisraC2012, projectFile, dataDir, ADDON_MISRA);
const QString &misraFile = settings.value(SETTINGS_MISRA_FILE, QString()).toString();
mUI->mEditMisraFile->setText(misraFile);
if (!mUI->mAddonMisra->isEnabled()) {
if (mPremium) {
mUI->mLabelMisraFile->setVisible(false);
mUI->mEditMisraFile->setVisible(false);
mUI->mBtnBrowseMisraFile->setVisible(false);
} else if (!mUI->mMisraC2012->isEnabled()) {
mUI->mEditMisraFile->setEnabled(false);
mUI->mBtnBrowseMisraFile->setEnabled(false);
}
mUI->mPremiumCertC->setChecked(projectFile->getCodingStandards().contains(CODING_STANDARD_CERT_C));
mUI->mMisraCpp2008->setChecked(projectFile->getCodingStandards().contains(CODING_STANDARD_MISRA_CPP_2008));
mUI->mAutosar->setChecked(projectFile->getCodingStandards().contains(CODING_STANDARD_AUTOSAR));
if (projectFile->getCertIntPrecision() <= 0)
mUI->mEditCertIntPrecision->setText(QString());
else
mUI->mEditCertIntPrecision->setText(QString::number(projectFile->getCertIntPrecision()));
mUI->mPremiumCertC->setVisible(mPremium);
mUI->mMisraCpp2008->setVisible(mPremium);
mUI->mAutosar->setVisible(mPremium);
mUI->mLabelCertIntPrecision->setVisible(mPremium);
mUI->mEditCertIntPrecision->setVisible(mPremium);
mUI->mBughunting->setChecked(projectFile->getBughunting());
mUI->mGroupboxBughunting->setVisible(mPremium);
mUI->mToolClangAnalyzer->setChecked(projectFile->getClangAnalyzer());
mUI->mToolClangTidy->setChecked(projectFile->getClangTidy());
if (CheckThread::clangTidyCmd().isEmpty()) {
@ -405,14 +435,23 @@ void ProjectFileDialog::saveToProjectFile(ProjectFile *projectFile) const
projectFile->setSafeChecks(safeChecks);
*/
// Addons
QStringList list;
QStringList addons;
if (mUI->mAddonThreadSafety->isChecked())
list << "threadsafety";
addons << "threadsafety";
if (mUI->mAddonY2038->isChecked())
list << "y2038";
if (mUI->mAddonMisra->isChecked())
list << "misra";
projectFile->setAddons(list);
addons << "y2038";
if (mUI->mMisraC2012->isChecked())
addons << ADDON_MISRA;
projectFile->setAddons(addons);
QStringList codingStandards;
if (mUI->mPremiumCertC->isChecked())
codingStandards << CODING_STANDARD_CERT_C;
if (mUI->mMisraCpp2008->isChecked())
codingStandards << CODING_STANDARD_MISRA_CPP_2008;
if (mUI->mAutosar->isChecked())
codingStandards << CODING_STANDARD_AUTOSAR;
projectFile->setCodingStandards(codingStandards);
projectFile->setCertIntPrecision(mUI->mEditCertIntPrecision->text().toInt());
projectFile->setClangAnalyzer(mUI->mToolClangAnalyzer->isChecked());
projectFile->setClangTidy(mUI->mToolClangTidy->isChecked());
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
@ -874,8 +913,8 @@ void ProjectFileDialog::browseMisraFile()
mUI->mEditMisraFile->setText(fileName);
settings.setValue(SETTINGS_MISRA_FILE, fileName);
mUI->mAddonMisra->setText("MISRA C 2012");
mUI->mAddonMisra->setEnabled(true);
updateAddonCheckBox(mUI->mAddonMisra, nullptr, getDataDir(), "misra");
mUI->mMisraC2012->setText("MISRA C 2012");
mUI->mMisraC2012->setEnabled(true);
updateAddonCheckBox(mUI->mMisraC2012, nullptr, getDataDir(), ADDON_MISRA);
}
}

View File

@ -44,7 +44,7 @@ class ProjectFile;
class ProjectFileDialog : public QDialog {
Q_OBJECT
public:
explicit ProjectFileDialog(ProjectFile *projectFile, QWidget *parent = nullptr);
explicit ProjectFileDialog(ProjectFile *projectFile, bool premium, QWidget *parent = nullptr);
~ProjectFileDialog() override;
private:
@ -325,6 +325,9 @@ private:
*/
ProjectFile *mProjectFile;
/** Is this Cppcheck Premium? */
bool mPremium;
QString getExistingDirectory(const QString &caption, bool trailingSlash);
QList<Suppressions::Suppression> mSuppressions;

View File

@ -89,7 +89,7 @@ namespace {
std::string args; // special extra arguments
std::string python; // script interpreter
bool ctu = false;
std::string runScript{};
std::string runScript;
static std::string getFullPath(const std::string &fileName, const std::string &exename) {
if (Path::fileExists(fileName))
@ -275,6 +275,7 @@ static void createDumpFile(const Settings& settings,
static std::string executeAddon(const AddonInfo &addonInfo,
const std::string &defaultPythonExe,
const std::string &file,
const std::string &premiumArgs,
std::function<bool(std::string,std::vector<std::string>,std::string,std::string*)> executeCommand)
{
const std::string redirect = "2>&1";
@ -308,6 +309,8 @@ static std::string executeAddon(const AddonInfo &addonInfo,
if (addonInfo.executable.empty())
args = cmdFileName(addonInfo.runScript) + " " + cmdFileName(addonInfo.scriptFile);
args += std::string(args.empty() ? "" : " ") + "--cli" + addonInfo.args;
if (!premiumArgs.empty() && !addonInfo.executable.empty())
args += " " + premiumArgs;
const std::string fileArg = (endsWith(file, FILELIST, sizeof(FILELIST)-1) ? " --file-list " : " ") + cmdFileName(file);
args += fileArg;
@ -1366,7 +1369,7 @@ void CppCheck::executeAddons(const std::vector<std::string>& files)
continue;
const std::string results =
executeAddon(addonInfo, mSettings.addonPython, fileList.empty() ? files[0] : fileList, mExecuteCommand);
executeAddon(addonInfo, mSettings.addonPython, fileList.empty() ? files[0] : fileList, mSettings.premiumArgs, mExecuteCommand);
std::istringstream istr(results);
std::string line;

View File

@ -178,6 +178,11 @@ namespace CppcheckXml {
const char Name[] = "name";
const char VSConfigurationElementName[] = "vs-configurations";
const char VSConfigurationName[] = "config";
// Cppcheck Premium
const char BughuntingElementName[] = "bug-hunting";
const char CodingStandardsElementName[] = "coding-standards";
const char CodingStandardElementName[] = "coding-standard";
const char CertIntPrecisionElementName[] = "cert-c-int-precision";
}
/// @}

View File

@ -239,6 +239,9 @@ public:
/** @brief plist output (--plist-output=&lt;dir&gt;) */
std::string plistOutput;
/** @brief Extra arguments for Cppcheck Premium addon */
std::string premiumArgs;
/** @brief Using -E for debugging purposes */
bool preprocessOnly;