GUI: Updated handling of clang and clang-tidy

This commit is contained in:
Daniel Marjamäki 2017-09-22 15:41:27 +02:00
parent 5993c40d5b
commit 6ddcfc3d1c
11 changed files with 96 additions and 33 deletions

View File

@ -25,9 +25,7 @@
#include "erroritem.h" #include "erroritem.h"
#include "threadresult.h" #include "threadresult.h"
#include "cppcheck.h" #include "cppcheck.h"
#include "common.h"
static const char CLANG[] = "clang";
static const char CLANGTIDY[] = "clang-tidy";
CheckThread::CheckThread(ThreadResult &result) : CheckThread::CheckThread(ThreadResult &result) :
mState(Ready), mState(Ready),
@ -82,7 +80,7 @@ void CheckThread::run()
while (!file.isEmpty() && mState == Running) { while (!file.isEmpty() && mState == Running) {
qDebug() << "Checking file" << file; qDebug() << "Checking file" << file;
mCppcheck.check(file.toStdString()); mCppcheck.check(file.toStdString());
runAddons(addonPath, nullptr, file); runAddonsAndTools(addonPath, nullptr, file);
emit fileChecked(file); emit fileChecked(file);
if (mState == Running) if (mState == Running)
@ -94,7 +92,7 @@ void CheckThread::run()
file = QString::fromStdString(fileSettings.filename); file = QString::fromStdString(fileSettings.filename);
qDebug() << "Checking file" << file; qDebug() << "Checking file" << file;
mCppcheck.check(fileSettings); mCppcheck.check(fileSettings);
runAddons(addonPath, &fileSettings, QString::fromStdString(fileSettings.filename)); runAddonsAndTools(addonPath, &fileSettings, QString::fromStdString(fileSettings.filename));
emit fileChecked(file); emit fileChecked(file);
if (mState == Running) if (mState == Running)
@ -109,12 +107,12 @@ void CheckThread::run()
emit done(); emit done();
} }
void CheckThread::runAddons(const QString &addonPath, const ImportProject::FileSettings *fileSettings, const QString &fileName) void CheckThread::runAddonsAndTools(const QString &addonPath, const ImportProject::FileSettings *fileSettings, const QString &fileName)
{ {
QString dumpFile; QString dumpFile;
foreach (const QString addon, mAddons) { foreach (const QString addon, mAddonsAndTools) {
if (addon == CLANG || addon == CLANGTIDY) { if (addon == CLANG_ANALYZER || addon == CLANG_TIDY) {
if (!fileSettings) if (!fileSettings)
continue; continue;
@ -195,7 +193,7 @@ void CheckThread::runAddons(const QString &addonPath, const ImportProject::FileS
QFile::remove(analyzerInfoFile + '.' + addon + "-results"); QFile::remove(analyzerInfoFile + '.' + addon + "-results");
} }
if (addon == CLANG) { if (addon == CLANG_ANALYZER) {
args.insert(0,"--analyze"); args.insert(0,"--analyze");
args.insert(1, "-Xanalyzer"); args.insert(1, "-Xanalyzer");
args.insert(2, "-analyzer-output=text"); args.insert(2, "-analyzer-output=text");
@ -206,7 +204,13 @@ void CheckThread::runAddons(const QString &addonPath, const ImportProject::FileS
args.insert(2, "--"); args.insert(2, "--");
} }
const QString cmd(mClangPath.isEmpty() ? addon : (mClangPath + '/' + addon + ".exe")); #ifdef Q_OS_WIN
const QString ext = ".exe";
#else
const QString ext = "";
#endif
const QString exename(addon == CLANG_ANALYZER ? ("clang" + ext) : ("clang-tidy" + ext));
const QString cmd(mClangPath.isEmpty() ? exename : (mClangPath + '/' + exename));
{ {
QString debug(cmd.contains(" ") ? ('\"' + cmd + '\"') : cmd); QString debug(cmd.contains(" ") ? ('\"' + cmd + '\"') : cmd);
foreach (QString arg, args) { foreach (QString arg, args) {
@ -383,7 +387,7 @@ void CheckThread::parseClangErrors(const QString &tool, const QString &file0, QS
errorItem.severity = Severity::SeverityType::style; errorItem.severity = Severity::SeverityType::style;
} else { } else {
message = r1.cap(5); message = r1.cap(5);
id = CLANG; id = CLANG_ANALYZER;
} }
if (errorItem.errorPath.size() == 1) { if (errorItem.errorPath.size() == 1) {

View File

@ -52,8 +52,8 @@ public:
*/ */
void analyseWholeProgram(const QStringList &files); void analyseWholeProgram(const QStringList &files);
void setAddons(const QStringList &addons) { void setAddonsAndTools(const QStringList &addonsAndTools) {
mAddons = addons; mAddonsAndTools = addonsAndTools;
} }
void setPythonPath(const QString &p) { void setPythonPath(const QString &p) {
@ -124,14 +124,14 @@ protected:
private: private:
QString getAddonPath() const; QString getAddonPath() const;
void runAddons(const QString &addonPath, const ImportProject::FileSettings *fileSettings, const QString &fileName); void runAddonsAndTools(const QString &addonPath, const ImportProject::FileSettings *fileSettings, const QString &fileName);
void parseAddonErrors(QString err, QString tool); void parseAddonErrors(QString err, QString tool);
void parseClangErrors(const QString &tool, const QString &file0, QString err); void parseClangErrors(const QString &tool, const QString &file0, QString err);
QStringList mFiles; QStringList mFiles;
bool mAnalyseWholeProgram; bool mAnalyseWholeProgram;
QStringList mAddons; QStringList mAddonsAndTools;
QString mPythonPath; QString mPythonPath;
QString mDataDir; QString mDataDir;
QString mClangPath; QString mClangPath;

View File

@ -24,6 +24,8 @@
/// @addtogroup GUI /// @addtogroup GUI
/// @{ /// @{
#define CLANG_ANALYZER "clang-analyzer"
#define CLANG_TIDY "clang-tidy"
/** /**
* QSetting value names * QSetting value names

View File

@ -17,6 +17,7 @@
*/ */
#include "erroritem.h" #include "erroritem.h"
#include "common.h"
QErrorPathItem::QErrorPathItem(const ErrorLogger::ErrorMessage::FileLocation &loc) QErrorPathItem::QErrorPathItem(const ErrorLogger::ErrorMessage::FileLocation &loc)
: file(QString::fromStdString(loc.getfile(false))) : file(QString::fromStdString(loc.getfile(false)))
@ -55,10 +56,10 @@ ErrorItem::ErrorItem(const ErrorLogger::ErrorMessage &errmsg)
QString ErrorItem::tool() const QString ErrorItem::tool() const
{ {
if (errorId == "clang") if (errorId == CLANG_ANALYZER)
return "clang"; return CLANG_ANALYZER;
if (errorId.startsWith("clang-tidy")) if (errorId.startsWith(CLANG_TIDY))
return "clang-tidy"; return CLANG_TIDY;
if (errorId.startsWith("clang-")) if (errorId.startsWith("clang-"))
return "clang"; return "clang";
return "cppcheck"; return "cppcheck";

View File

@ -445,7 +445,7 @@ void MainWindow::doAnalyzeProject(ImportProject p)
//mThread->SetanalyzeProject(true); //mThread->SetanalyzeProject(true);
if (mProjectFile) { if (mProjectFile) {
mThread->setAddons(mProjectFile->getAddons()); mThread->setAddonsAndTools(mProjectFile->getAddonsAndTools());
mThread->setPythonPath(mSettings->value(SETTINGS_PYTHON_PATH).toString()); mThread->setPythonPath(mSettings->value(SETTINGS_PYTHON_PATH).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(";"));
@ -1417,7 +1417,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->setAddons(projectFile->getAddons()); mThread->setAddonsAndTools(projectFile->getAddonsAndTools());
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

View File

@ -23,6 +23,7 @@
#include <QFile> #include <QFile>
#include <QDir> #include <QDir>
#include "projectfile.h" #include "projectfile.h"
#include "common.h"
static const char ProjectElementName[] = "project"; static const char ProjectElementName[] = "project";
static const char ProjectVersionAttrib[] = "version"; static const char ProjectVersionAttrib[] = "version";
@ -53,6 +54,8 @@ static const char SuppressionsElementName[] = "suppressions";
static const char SuppressionElementName[] = "suppression"; static const char SuppressionElementName[] = "suppression";
static const char AddonElementName[] = "addon"; static const char AddonElementName[] = "addon";
static const char AddonsElementName[] = "addons"; static const char AddonsElementName[] = "addons";
static const char ToolElementName[] = "tool";
static const char ToolsElementName[] = "tools";
static const char TagsElementName[] = "tags"; static const char TagsElementName[] = "tags";
static const char TagElementName[] = "tag"; static const char TagElementName[] = "tag";
@ -83,6 +86,7 @@ void ProjectFile::clear()
mLibraries.clear(); mLibraries.clear();
mSuppressions.clear(); mSuppressions.clear();
mAddons.clear(); mAddons.clear();
mClangAnalyzer = mClangTidy = false;
} }
bool ProjectFile::read(const QString &filename) bool ProjectFile::read(const QString &filename)
@ -153,6 +157,14 @@ bool ProjectFile::read(const QString &filename)
if (insideProject && xmlReader.name() == AddonsElementName) if (insideProject && xmlReader.name() == AddonsElementName)
readStringList(mAddons, xmlReader, AddonElementName); readStringList(mAddons, xmlReader, AddonElementName);
// Tools
if (insideProject && xmlReader.name() == ToolsElementName) {
QStringList tools;
readStringList(tools, xmlReader, ToolElementName);
mClangAnalyzer = tools.contains(CLANG_ANALYZER);
mClangTidy = tools.contains(CLANG_TIDY);
}
if (insideProject && xmlReader.name() == TagsElementName) if (insideProject && xmlReader.name() == TagsElementName)
readStringList(mTags, xmlReader, TagElementName); readStringList(mTags, xmlReader, TagElementName);
@ -588,6 +600,16 @@ bool ProjectFile::write(const QString &filename)
AddonsElementName, AddonsElementName,
AddonElementName); AddonElementName);
QStringList tools;
if (mClangAnalyzer)
tools << CLANG_ANALYZER;
if (mClangTidy)
tools << CLANG_TIDY;
writeStringList(xmlWriter,
tools,
ToolsElementName,
ToolElementName);
writeStringList(xmlWriter, mTags, TagsElementName, TagElementName); writeStringList(xmlWriter, mTags, TagsElementName, TagElementName);
xmlWriter.writeEndDocument(); xmlWriter.writeEndDocument();
@ -616,3 +638,12 @@ QStringList ProjectFile::fromNativeSeparators(const QStringList &paths)
ret << QDir::fromNativeSeparators(path); ret << QDir::fromNativeSeparators(path);
return ret; return ret;
} }
QStringList ProjectFile::getAddonsAndTools() const {
QStringList ret(mAddons);
if (mClangAnalyzer)
ret << CLANG_ANALYZER;
if (mClangTidy)
ret << CLANG_TIDY;
return ret;
}

View File

@ -122,12 +122,26 @@ public:
return mAddons; return mAddons;
} }
/**
* @brief Get list of addons and tools.
* @return list of addons and tools.
*/
QStringList getAddonsAndTools() const;
bool getClangAnalyzer() const { bool getClangAnalyzer() const {
return mAddons.contains("clang-analyzer"); return mClangAnalyzer;
}
void setClangAnalyzer(bool c) {
mClangAnalyzer = c;
} }
bool getClangTidy() const { bool getClangTidy() const {
return mAddons.contains("clang-tidy"); return mClangTidy;
}
void setClangTidy(bool c) {
mClangTidy = c;
} }
QStringList getTags() const { QStringList getTags() const {
@ -355,6 +369,12 @@ private:
*/ */
QStringList mAddons; QStringList mAddons;
/** @brief Execute clang analyzer? */
bool mClangAnalyzer;
/** @brief Execute clang-tidy? */
bool mClangTidy;
/** /**
* @brief Warning tags * @brief Warning tags
*/ */

View File

@ -134,7 +134,6 @@ void ProjectFileDialog::saveSettings() const
void ProjectFileDialog::loadFromProjectFile(const ProjectFile *projectFile) void ProjectFileDialog::loadFromProjectFile(const ProjectFile *projectFile)
{ {
mUI.mToolClangTidy->setChecked(projectFile->getAddons().contains("clang-tidy"));
setRootPath(projectFile->getRootPath()); setRootPath(projectFile->getRootPath());
setBuildDir(projectFile->getBuildDir()); setBuildDir(projectFile->getBuildDir());
setIncludepaths(projectFile->getIncludeDirs()); setIncludepaths(projectFile->getIncludeDirs());
@ -148,6 +147,8 @@ void ProjectFileDialog::loadFromProjectFile(const ProjectFile *projectFile)
mUI.mAddonThreadSafety->setChecked(projectFile->getAddons().contains("threadsafety")); mUI.mAddonThreadSafety->setChecked(projectFile->getAddons().contains("threadsafety"));
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.mToolClangAnalyzer->setChecked(projectFile->getClangAnalyzer());
mUI.mToolClangTidy->setChecked(projectFile->getClangTidy());
QString tags; QString tags;
foreach (const QString tag, projectFile->getTags()) { foreach (const QString tag, projectFile->getTags()) {
if (tags.isEmpty()) if (tags.isEmpty())
@ -172,8 +173,6 @@ void ProjectFileDialog::saveToProjectFile(ProjectFile *projectFile) const
projectFile->setLibraries(getLibraries()); projectFile->setLibraries(getLibraries());
projectFile->setSuppressions(getSuppressions()); projectFile->setSuppressions(getSuppressions());
QStringList list; QStringList list;
if (mUI.mToolClangTidy->isChecked())
list << "clang-tidy";
if (mUI.mAddonThreadSafety->isChecked()) if (mUI.mAddonThreadSafety->isChecked())
list << "threadsafety"; list << "threadsafety";
if (mUI.mAddonY2038->isChecked()) if (mUI.mAddonY2038->isChecked())
@ -181,6 +180,8 @@ void ProjectFileDialog::saveToProjectFile(ProjectFile *projectFile) const
if (mUI.mAddonCert->isChecked()) if (mUI.mAddonCert->isChecked())
list << "cert"; list << "cert";
projectFile->setAddons(list); projectFile->setAddons(list);
//projectFile->setClangAnalyzer(mUI.mToolClangAnalyzer->isChecked());
projectFile->setClangTidy(mUI.mToolClangTidy->isChecked());
QStringList tags(mUI.mEditTags->text().split(";")); QStringList tags(mUI.mEditTags->text().split(";"));
tags.removeAll(QString()); tags.removeAll(QString());
projectFile->setTags(tags); projectFile->setTags(tags);

View File

@ -65,8 +65,12 @@ void StatsDialog::setProject(const ProjectFile* projectFile)
QChartView *chartView; QChartView *chartView;
chartView = createChart(statsFile, "cppcheck"); chartView = createChart(statsFile, "cppcheck");
mUI.mTabHistory->layout()->addWidget(chartView); mUI.mTabHistory->layout()->addWidget(chartView);
if (projectFile->getAddons().contains("clang-tidy")) { if (projectFile->getClangAnalyzer()) {
chartView = createChart(statsFile, "clang-tidy"); chartView = createChart(statsFile, CLANG_ANALYZER);
mUI.mTabHistory->layout()->addWidget(chartView);
}
if (projectFile->getClangTidy()) {
chartView = createChart(statsFile, CLANG_TIDY);
mUI.mTabHistory->layout()->addWidget(chartView); mUI.mTabHistory->layout()->addWidget(chartView);
} }
} }

View File

@ -46,7 +46,7 @@ void ThreadHandler::clearFiles()
mLastFiles.clear(); mLastFiles.clear();
mResults.clearFiles(); mResults.clearFiles();
mAnalyseWholeProgram = false; mAnalyseWholeProgram = false;
mAddons.clear(); mAddonsAndTools.clear();
mSuppressions.clear(); mSuppressions.clear();
} }
@ -93,7 +93,7 @@ void ThreadHandler::check(const Settings &settings)
} }
for (int i = 0; i < mRunningThreadCount; i++) { for (int i = 0; i < mRunningThreadCount; i++) {
mThreads[i]->setAddons(mAddons); mThreads[i]->setAddonsAndTools(mAddonsAndTools);
mThreads[i]->setPythonPath(mPythonPath); mThreads[i]->setPythonPath(mPythonPath);
mThreads[i]->setSuppressions(mSuppressions); mThreads[i]->setSuppressions(mSuppressions);
mThreads[i]->setClangPath(mClangPath); mThreads[i]->setClangPath(mClangPath);

View File

@ -71,8 +71,8 @@ public:
*/ */
void saveSettings(QSettings &settings) const; void saveSettings(QSettings &settings) const;
void setAddons(const QStringList &addons) { void setAddonsAndTools(const QStringList &addonsAndTools) {
mAddons = addons; mAddonsAndTools = addonsAndTools;
} }
void setSuppressions(const QStringList &s) { void setSuppressions(const QStringList &s) {
@ -261,7 +261,7 @@ protected:
bool mAnalyseWholeProgram; bool mAnalyseWholeProgram;
QStringList mAddons; QStringList mAddonsAndTools;
QStringList mSuppressions; QStringList mSuppressions;
QString mPythonPath; QString mPythonPath;
QString mClangPath; QString mClangPath;