Misra: Integration of MISRA in the GUI. The misra addon can now extract the rule texts from the PDF.
This commit is contained in:
parent
0a70b8794c
commit
6f2d4361df
|
@ -4,7 +4,8 @@
|
||||||
#
|
#
|
||||||
# Example usage of this addon (scan a sourcefile main.cpp)
|
# Example usage of this addon (scan a sourcefile main.cpp)
|
||||||
# cppcheck --dump main.cpp
|
# cppcheck --dump main.cpp
|
||||||
# python misra.py main.cpp.dump
|
# python misra.py --rule-texts=<path-to-rule-texts> main.cpp.dump
|
||||||
|
# python misra.py --misra-pdf=<path-to-misra.pdf> main.cpp.dump
|
||||||
#
|
#
|
||||||
# Limitations: This addon is released as open source. Rule texts can't be freely
|
# Limitations: This addon is released as open source. Rule texts can't be freely
|
||||||
# distributed. https://www.misra.org.uk/forum/viewtopic.php?f=56&t=1189
|
# distributed. https://www.misra.org.uk/forum/viewtopic.php?f=56&t=1189
|
||||||
|
@ -14,6 +15,9 @@
|
||||||
import cppcheckdata
|
import cppcheckdata
|
||||||
import sys
|
import sys
|
||||||
import re
|
import re
|
||||||
|
import os
|
||||||
|
import tempfile
|
||||||
|
import subprocess
|
||||||
|
|
||||||
ruleTexts = {}
|
ruleTexts = {}
|
||||||
|
|
||||||
|
@ -31,8 +35,8 @@ def reportError(location, num1, num2):
|
||||||
if num in ruleTexts:
|
if num in ruleTexts:
|
||||||
errmsg = ruleTexts[num] + ' [' + id + ']'
|
errmsg = ruleTexts[num] + ' [' + id + ']'
|
||||||
else:
|
else:
|
||||||
errmsg = 'misra violation (use --rule-texts=<file> to get proper output) [' + id + ']'
|
errmsg = 'misra violation (use --misra-pdf=<file> or --rule-texts=<file> to get proper output) [' + id + ']'
|
||||||
sys.stderr.write('[' + location.file + ':' + str(location.linenr) + '] ' + errmsg + '\n')
|
sys.stderr.write('[' + location.file + ':' + str(location.linenr) + '] (style): ' + errmsg + '\n')
|
||||||
|
|
||||||
|
|
||||||
def simpleMatch(token, pattern):
|
def simpleMatch(token, pattern):
|
||||||
|
@ -1024,8 +1028,15 @@ def misra_21_11(data):
|
||||||
def loadRuleTexts(filename):
|
def loadRuleTexts(filename):
|
||||||
num1 = 0
|
num1 = 0
|
||||||
num2 = 0
|
num2 = 0
|
||||||
|
appendixA = False
|
||||||
for line in open(filename, 'rt'):
|
for line in open(filename, 'rt'):
|
||||||
line = line.replace('\r', '').replace('\n', '')
|
line = line.replace('\r', '').replace('\n', '')
|
||||||
|
if not appendixA:
|
||||||
|
if line.find('Appendix A') >= 0 and line.find('Summary of guidelines') >= 10:
|
||||||
|
appendixA = True
|
||||||
|
continue
|
||||||
|
if line.find('Appendix B') >= 0:
|
||||||
|
break
|
||||||
res = re.match(r'^Rule ([0-9]+).([0-9]+)', line)
|
res = re.match(r'^Rule ([0-9]+).([0-9]+)', line)
|
||||||
if res:
|
if res:
|
||||||
num1 = int(res.group(1))
|
num1 = int(res.group(1))
|
||||||
|
@ -1041,12 +1052,57 @@ def loadRuleTexts(filename):
|
||||||
num2 = num2 + 1
|
num2 = num2 + 1
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
def loadRuleTextsFromPdf(filename):
|
||||||
|
f = tempfile.NamedTemporaryFile(delete=False)
|
||||||
|
f.close()
|
||||||
|
print('tempfile:' + f.name)
|
||||||
|
subprocess.call(['pdftotext', filename, f.name])
|
||||||
|
loadRuleTexts(f.name)
|
||||||
|
try:
|
||||||
|
os.remove(f.name)
|
||||||
|
except OSError as err:
|
||||||
|
print('Failed to remove temporary file ' + f.name)
|
||||||
|
|
||||||
|
if len(sys.argv) == 1:
|
||||||
|
print("""
|
||||||
|
Syntax: misra.py [OPTIONS] <dumpfiles>
|
||||||
|
|
||||||
|
OPTIONS:
|
||||||
|
|
||||||
|
--rule-texts=<file> Load rule texts from plain text file.
|
||||||
|
|
||||||
|
You can more or less copy/paste the chapter:
|
||||||
|
Appendix A Summary of guidelines
|
||||||
|
from the MISRA pdf.
|
||||||
|
|
||||||
|
Format:
|
||||||
|
|
||||||
|
<..arbitrary text..>
|
||||||
|
Appendix A Summary of guidelines
|
||||||
|
Dir 1.1
|
||||||
|
Rule text for 1.1
|
||||||
|
Dir 1.2
|
||||||
|
Rule text for 1.2
|
||||||
|
<...>
|
||||||
|
|
||||||
|
--misra-pdf=<file> Misra PDF file that rule texts will be extracted from.
|
||||||
|
|
||||||
|
The tool 'pdftotext' from xpdf is used and must be installed.
|
||||||
|
Debian: sudo apt-get install xpdf
|
||||||
|
Windows: http://gnuwin32.sourceforge.net/packages/xpdf.htm
|
||||||
|
|
||||||
|
If you don't have 'pdftotext' and don't want to install it then
|
||||||
|
you can use --rule-texts=<file>.
|
||||||
|
""")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
for arg in sys.argv[1:]:
|
for arg in sys.argv[1:]:
|
||||||
if arg == '-verify':
|
if arg == '-verify':
|
||||||
VERIFY = True
|
VERIFY = True
|
||||||
elif arg.startswith('--rule-texts='):
|
elif arg.startswith('--rule-texts='):
|
||||||
loadRuleTexts(arg[13:])
|
loadRuleTexts(arg[13:])
|
||||||
|
elif arg.startswith('--misra-pdf='):
|
||||||
|
loadRuleTextsFromPdf(arg[12:])
|
||||||
|
|
||||||
for arg in sys.argv[1:]:
|
for arg in sys.argv[1:]:
|
||||||
if not arg.endswith('.dump'):
|
if not arg.endswith('.dump'):
|
||||||
|
|
|
@ -287,6 +287,12 @@ void CheckThread::runAddonsAndTools(const ImportProject::FileSettings *fileSetti
|
||||||
|
|
||||||
QStringList args;
|
QStringList args;
|
||||||
args << addonFilePath << dumpFile;
|
args << addonFilePath << dumpFile;
|
||||||
|
if (addon == "misra" && !mMisraFile.isEmpty() && QFileInfo(mMisraFile).exists()) {
|
||||||
|
if (mMisraFile.endsWith('.pdf', Qt::CaseInsensitive))
|
||||||
|
args << "--misra-pdf=" + mMisraFile;
|
||||||
|
else
|
||||||
|
args << "--rule-texts=" + mMisraFile;
|
||||||
|
}
|
||||||
qDebug() << python << args;
|
qDebug() << python << args;
|
||||||
|
|
||||||
QProcess process;
|
QProcess process;
|
||||||
|
|
|
@ -56,6 +56,10 @@ public:
|
||||||
mAddonsAndTools = addonsAndTools;
|
mAddonsAndTools = addonsAndTools;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setMisraFile(const QString &misraFile) {
|
||||||
|
mMisraFile = misraFile;
|
||||||
|
}
|
||||||
|
|
||||||
void setDataDir(const QString &dataDir) {
|
void setDataDir(const QString &dataDir) {
|
||||||
mDataDir = dataDir;
|
mDataDir = dataDir;
|
||||||
}
|
}
|
||||||
|
@ -148,6 +152,7 @@ private:
|
||||||
QString mDataDir;
|
QString mDataDir;
|
||||||
QStringList mClangIncludePaths;
|
QStringList mClangIncludePaths;
|
||||||
QStringList mSuppressions;
|
QStringList mSuppressions;
|
||||||
|
QString mMisraFile;
|
||||||
};
|
};
|
||||||
/// @}
|
/// @}
|
||||||
#endif // CHECKTHREAD_H
|
#endif // CHECKTHREAD_H
|
||||||
|
|
|
@ -84,6 +84,7 @@
|
||||||
#define SETTINGS_LANGUAGE "Application language"
|
#define SETTINGS_LANGUAGE "Application language"
|
||||||
#define SETTINGS_GLOBAL_INCLUDE_PATHS "Global include paths"
|
#define SETTINGS_GLOBAL_INCLUDE_PATHS "Global include paths"
|
||||||
#define SETTINGS_PYTHON_PATH "Python path"
|
#define SETTINGS_PYTHON_PATH "Python path"
|
||||||
|
#define SETTINGS_MISRA_FILE "MISRA C 2012 file"
|
||||||
#define SETTINGS_CLANG_PATH "Clang path"
|
#define SETTINGS_CLANG_PATH "Clang path"
|
||||||
#define SETTINGS_VS_INCLUDE_PATHS "VS include paths"
|
#define SETTINGS_VS_INCLUDE_PATHS "VS include paths"
|
||||||
#define SETTINGS_INLINE_SUPPRESSIONS "Inline suppressions"
|
#define SETTINGS_INLINE_SUPPRESSIONS "Inline suppressions"
|
||||||
|
|
|
@ -456,7 +456,7 @@ void MainWindow::doAnalyzeProject(ImportProject p)
|
||||||
|
|
||||||
//mThread->SetanalyzeProject(true);
|
//mThread->SetanalyzeProject(true);
|
||||||
if (mProjectFile) {
|
if (mProjectFile) {
|
||||||
mThread->setAddonsAndTools(mProjectFile->getAddonsAndTools());
|
mThread->setAddonsAndTools(mProjectFile->getAddonsAndTools(), mSettings->value(SETTINGS_MISRA_FILE).toString());
|
||||||
QString clangHeaders = mSettings->value(SETTINGS_VS_INCLUDE_PATHS).toString();
|
QString clangHeaders = mSettings->value(SETTINGS_VS_INCLUDE_PATHS).toString();
|
||||||
mThread->setClangIncludePaths(clangHeaders.split(";"));
|
mThread->setClangIncludePaths(clangHeaders.split(";"));
|
||||||
mThread->setSuppressions(mProjectFile->getSuppressions());
|
mThread->setSuppressions(mProjectFile->getSuppressions());
|
||||||
|
@ -498,6 +498,8 @@ void MainWindow::doAnalyzeFiles(const QStringList &files)
|
||||||
mUI.mResults->checkingStarted(fileNames.count());
|
mUI.mResults->checkingStarted(fileNames.count());
|
||||||
|
|
||||||
mThread->setFiles(fileNames);
|
mThread->setFiles(fileNames);
|
||||||
|
if (mProjectFile)
|
||||||
|
mThread->setAddonsAndTools(mProjectFile->getAddonsAndTools(), mSettings->value(SETTINGS_MISRA_FILE).toString());
|
||||||
QDir inf(mCurrentDirectory);
|
QDir inf(mCurrentDirectory);
|
||||||
const QString checkPath = inf.canonicalPath();
|
const QString checkPath = inf.canonicalPath();
|
||||||
setPath(SETTINGS_LAST_CHECK_PATH, checkPath);
|
setPath(SETTINGS_LAST_CHECK_PATH, checkPath);
|
||||||
|
@ -1428,7 +1430,7 @@ void MainWindow::analyzeProject(const ProjectFile *projectFile)
|
||||||
QFileInfo inf(projectFile->getFilename());
|
QFileInfo inf(projectFile->getFilename());
|
||||||
const QString rootpath = projectFile->getRootPath();
|
const QString rootpath = projectFile->getRootPath();
|
||||||
|
|
||||||
mThread->setAddonsAndTools(projectFile->getAddonsAndTools());
|
mThread->setAddonsAndTools(projectFile->getAddonsAndTools(), mSettings->value(SETTINGS_MISRA_FILE).toString());
|
||||||
mUI.mResults->setTags(projectFile->getTags());
|
mUI.mResults->setTags(projectFile->getTags());
|
||||||
|
|
||||||
// If the root path is not given or is not "current dir", use project
|
// If the root path is not given or is not "current dir", use project
|
||||||
|
|
|
@ -163,9 +163,11 @@ void ProjectFileDialog::loadFromProjectFile(const ProjectFile *projectFile)
|
||||||
updateAddonCheckBox(mUI.mAddonThreadSafety, projectFile, dataDir, "threadsafety");
|
updateAddonCheckBox(mUI.mAddonThreadSafety, projectFile, dataDir, "threadsafety");
|
||||||
updateAddonCheckBox(mUI.mAddonY2038, projectFile, dataDir, "y2038");
|
updateAddonCheckBox(mUI.mAddonY2038, projectFile, dataDir, "y2038");
|
||||||
updateAddonCheckBox(mUI.mAddonCert, projectFile, dataDir, "cert");
|
updateAddonCheckBox(mUI.mAddonCert, projectFile, dataDir, "cert");
|
||||||
|
updateAddonCheckBox(mUI.mAddonMisra, projectFile, dataDir, "misra");
|
||||||
|
|
||||||
mUI.mAddonY2038->setChecked(projectFile->getAddons().contains("y2038"));
|
mUI.mAddonY2038->setChecked(projectFile->getAddons().contains("y2038"));
|
||||||
mUI.mAddonCert->setChecked(projectFile->getAddons().contains("cert"));
|
mUI.mAddonCert->setChecked(projectFile->getAddons().contains("cert"));
|
||||||
|
mUI.mAddonMisra->setChecked(projectFile->getAddons().contains("misra"));
|
||||||
mUI.mToolClangAnalyzer->setChecked(projectFile->getClangAnalyzer());
|
mUI.mToolClangAnalyzer->setChecked(projectFile->getClangAnalyzer());
|
||||||
mUI.mToolClangTidy->setChecked(projectFile->getClangTidy());
|
mUI.mToolClangTidy->setChecked(projectFile->getClangTidy());
|
||||||
if (CheckThread::clangTidyCmd().isEmpty()) {
|
if (CheckThread::clangTidyCmd().isEmpty()) {
|
||||||
|
@ -202,6 +204,8 @@ void ProjectFileDialog::saveToProjectFile(ProjectFile *projectFile) const
|
||||||
list << "y2038";
|
list << "y2038";
|
||||||
if (mUI.mAddonCert->isChecked())
|
if (mUI.mAddonCert->isChecked())
|
||||||
list << "cert";
|
list << "cert";
|
||||||
|
if (mUI.mAddonMisra->isChecked())
|
||||||
|
list << "misra";
|
||||||
projectFile->setAddons(list);
|
projectFile->setAddons(list);
|
||||||
projectFile->setClangAnalyzer(mUI.mToolClangAnalyzer->isChecked());
|
projectFile->setClangAnalyzer(mUI.mToolClangAnalyzer->isChecked());
|
||||||
projectFile->setClangTidy(mUI.mToolClangTidy->isChecked());
|
projectFile->setClangTidy(mUI.mToolClangTidy->isChecked());
|
||||||
|
|
|
@ -493,6 +493,13 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="mAddonMisra">
|
||||||
|
<property name="text">
|
||||||
|
<string>MISRA C 2012</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="verticalSpacer_5">
|
<spacer name="verticalSpacer_5">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
|
|
|
@ -306,6 +306,46 @@
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox_4">
|
||||||
|
<property name="title">
|
||||||
|
<string>Misra addon: rule texts</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string><html><head/><body><p>The Misra addon can read the rule texts from a file; either a Misra PDF or a plaintext file.</p><p>PDF: To extract text from the MISRA PDF, the misra addon uses the tool 'pdftotext' available in xpdf (crossplatform open source tool). That tool must be installed.</p><p>Text: Copy/paste the text in the chapter &quot;Appendix A Summary of guidelines&quot; from the MISRA pdf into a text file.</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="text">
|
||||||
|
<string>Misra PDF/Text file</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="mEditMisraFile"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="mBtnBrowseMisraFile">
|
||||||
|
<property name="text">
|
||||||
|
<string>...</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="verticalSpacer_3">
|
<spacer name="verticalSpacer_3">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
|
|
|
@ -54,6 +54,7 @@ SettingsDialog::SettingsDialog(ApplicationList *list,
|
||||||
mUI.mShowStatistics->setCheckState(boolToCheckState(settings.value(SETTINGS_SHOW_STATISTICS, false).toBool()));
|
mUI.mShowStatistics->setCheckState(boolToCheckState(settings.value(SETTINGS_SHOW_STATISTICS, false).toBool()));
|
||||||
mUI.mShowErrorId->setCheckState(boolToCheckState(settings.value(SETTINGS_SHOW_ERROR_ID, false).toBool()));
|
mUI.mShowErrorId->setCheckState(boolToCheckState(settings.value(SETTINGS_SHOW_ERROR_ID, false).toBool()));
|
||||||
mUI.mEditPythonPath->setText(settings.value(SETTINGS_PYTHON_PATH, QString()).toString());
|
mUI.mEditPythonPath->setText(settings.value(SETTINGS_PYTHON_PATH, QString()).toString());
|
||||||
|
mUI.mEditMisraFile->setText(settings.value(SETTINGS_MISRA_FILE, QString()).toString());
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
//mUI.mTabClang->setVisible(true);
|
//mUI.mTabClang->setVisible(true);
|
||||||
|
@ -77,6 +78,7 @@ SettingsDialog::SettingsDialog(ApplicationList *list,
|
||||||
this, SLOT(editApplication()));
|
this, SLOT(editApplication()));
|
||||||
|
|
||||||
connect(mUI.mBtnBrowsePythonPath, &QPushButton::clicked, this, &SettingsDialog::browsePythonPath);
|
connect(mUI.mBtnBrowsePythonPath, &QPushButton::clicked, this, &SettingsDialog::browsePythonPath);
|
||||||
|
connect(mUI.mBtnBrowseMisraFile, &QPushButton::clicked, this, &SettingsDialog::browseMisraFile);
|
||||||
|
|
||||||
mUI.mListWidget->setSortingEnabled(false);
|
mUI.mListWidget->setSortingEnabled(false);
|
||||||
populateApplicationList();
|
populateApplicationList();
|
||||||
|
@ -161,6 +163,7 @@ void SettingsDialog::saveSettingValues() const
|
||||||
saveCheckboxValue(&settings, mUI.mShowStatistics, SETTINGS_SHOW_STATISTICS);
|
saveCheckboxValue(&settings, mUI.mShowStatistics, SETTINGS_SHOW_STATISTICS);
|
||||||
saveCheckboxValue(&settings, mUI.mShowErrorId, SETTINGS_SHOW_ERROR_ID);
|
saveCheckboxValue(&settings, mUI.mShowErrorId, SETTINGS_SHOW_ERROR_ID);
|
||||||
settings.setValue(SETTINGS_PYTHON_PATH, mUI.mEditPythonPath->text());
|
settings.setValue(SETTINGS_PYTHON_PATH, mUI.mEditPythonPath->text());
|
||||||
|
settings.setValue(SETTINGS_MISRA_FILE, mUI.mEditMisraFile->text());
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
settings.setValue(SETTINGS_CLANG_PATH, mUI.mEditClangPath->text());
|
settings.setValue(SETTINGS_CLANG_PATH, mUI.mEditClangPath->text());
|
||||||
|
@ -306,6 +309,13 @@ void SettingsDialog::browsePythonPath()
|
||||||
mUI.mEditPythonPath->setText(fileName);
|
mUI.mEditPythonPath->setText(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SettingsDialog::browseMisraFile()
|
||||||
|
{
|
||||||
|
const QString fileName = QFileDialog::getOpenFileName(this, tr("Select MISRA File"), QDir::homePath(), "Misra File (*.pdf *.txt)");
|
||||||
|
if (!fileName.isEmpty())
|
||||||
|
mUI.mEditMisraFile->setText(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
void SettingsDialog::browseClangPath()
|
void SettingsDialog::browseClangPath()
|
||||||
{
|
{
|
||||||
QString selectedDir = QFileDialog::getExistingDirectory(this,
|
QString selectedDir = QFileDialog::getExistingDirectory(this,
|
||||||
|
|
|
@ -129,6 +129,11 @@ protected slots:
|
||||||
|
|
||||||
/** @brief Slot for browsing for the clang binary */
|
/** @brief Slot for browsing for the clang binary */
|
||||||
void browseClangPath();
|
void browseClangPath();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Browse for MISRA file
|
||||||
|
*/
|
||||||
|
void browseMisraFile();
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* @brief Clear all applications from the list and re insert them from mTempApplications
|
* @brief Clear all applications from the list and re insert them from mTempApplications
|
||||||
|
|
|
@ -94,6 +94,7 @@ void ThreadHandler::check(const Settings &settings)
|
||||||
|
|
||||||
for (int i = 0; i < mRunningThreadCount; i++) {
|
for (int i = 0; i < mRunningThreadCount; i++) {
|
||||||
mThreads[i]->setAddonsAndTools(mAddonsAndTools);
|
mThreads[i]->setAddonsAndTools(mAddonsAndTools);
|
||||||
|
mThreads[i]->setMisraFile(mMisraFile);
|
||||||
mThreads[i]->setSuppressions(mSuppressions);
|
mThreads[i]->setSuppressions(mSuppressions);
|
||||||
mThreads[i]->setClangIncludePaths(mClangIncludePaths);
|
mThreads[i]->setClangIncludePaths(mClangIncludePaths);
|
||||||
mThreads[i]->setDataDir(mDataDir);
|
mThreads[i]->setDataDir(mDataDir);
|
||||||
|
|
|
@ -71,8 +71,9 @@ public:
|
||||||
*/
|
*/
|
||||||
void saveSettings(QSettings &settings) const;
|
void saveSettings(QSettings &settings) const;
|
||||||
|
|
||||||
void setAddonsAndTools(const QStringList &addonsAndTools) {
|
void setAddonsAndTools(const QStringList &addonsAndTools, const QString misraFile) {
|
||||||
mAddonsAndTools = addonsAndTools;
|
mAddonsAndTools = addonsAndTools;
|
||||||
|
mMisraFile = misraFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSuppressions(const QStringList &s) {
|
void setSuppressions(const QStringList &s) {
|
||||||
|
@ -258,6 +259,7 @@ protected:
|
||||||
QStringList mClangIncludePaths;
|
QStringList mClangIncludePaths;
|
||||||
|
|
||||||
QString mDataDir;
|
QString mDataDir;
|
||||||
|
QString mMisraFile;
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue