GUI: Add cppcheck build dir
This commit is contained in:
parent
1235815ae9
commit
84e6163cb8
|
@ -37,14 +37,35 @@ CheckThread::~CheckThread()
|
|||
|
||||
void CheckThread::Check(const Settings &settings)
|
||||
{
|
||||
mFiles.clear();
|
||||
mCppcheck.settings() = settings;
|
||||
start();
|
||||
}
|
||||
|
||||
void CheckThread::AnalyseWholeProgram(const QStringList &files)
|
||||
{
|
||||
mFiles = files;
|
||||
start();
|
||||
}
|
||||
|
||||
void CheckThread::run()
|
||||
{
|
||||
mState = Running;
|
||||
|
||||
if (!mFiles.isEmpty()) {
|
||||
qDebug() << "Whole program analysis";
|
||||
const std::string &buildDir = mCppcheck.settings().buildDir;
|
||||
if (!buildDir.empty()) {
|
||||
std::map<std::string,std::size_t> files2;
|
||||
for (QString file : mFiles)
|
||||
files2[file.toStdString()] = 0;
|
||||
mCppcheck.analyseWholeProgram(buildDir, files2);
|
||||
}
|
||||
mFiles.clear();
|
||||
emit Done();
|
||||
return;
|
||||
}
|
||||
|
||||
QString file = mResult.GetNextFile();
|
||||
while (!file.isEmpty() && mState == Running) {
|
||||
qDebug() << "Checking file" << file;
|
||||
|
|
|
@ -46,6 +46,12 @@ public:
|
|||
*/
|
||||
void Check(const Settings &settings);
|
||||
|
||||
/**
|
||||
* @brief Run whole program analysis
|
||||
* @param files All files
|
||||
*/
|
||||
void AnalyseWholeProgram(const QStringList &files);
|
||||
|
||||
/**
|
||||
* @brief method that is run in a thread
|
||||
*
|
||||
|
@ -91,7 +97,9 @@ protected:
|
|||
*
|
||||
*/
|
||||
CppCheck mCppcheck;
|
||||
|
||||
private:
|
||||
QStringList mFiles;
|
||||
};
|
||||
/// @}
|
||||
#endif // CHECKTHREAD_H
|
||||
|
|
|
@ -438,6 +438,20 @@ void MainWindow::DoCheckFiles(const QStringList &files)
|
|||
if (mProject)
|
||||
qDebug() << "Checking project file" << mProject->GetProjectFile()->GetFilename();
|
||||
|
||||
if (!checkSettings.buildDir.empty()) {
|
||||
QString s = QString::fromStdString(checkSettings.buildDir);
|
||||
if (!s.endsWith('/'))
|
||||
s += '/';
|
||||
s += "files.txt";
|
||||
|
||||
std::ofstream fout(s.toStdString());
|
||||
if (fout.is_open()) {
|
||||
foreach (QString f, fileNames) {
|
||||
fout << f.toStdString() << '\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mThread->SetCheckFiles(true);
|
||||
mThread->Check(checkSettings, true);
|
||||
}
|
||||
|
@ -742,6 +756,12 @@ Settings MainWindow::GetCppcheckSettings()
|
|||
// Only check the given -D configuration
|
||||
if (!defines.isEmpty())
|
||||
result.maxConfigs = 1;
|
||||
|
||||
QString buildDir = pfile->GetBuildDir();
|
||||
if (!buildDir.isEmpty()) {
|
||||
QString prjpath = QFileInfo(pfile->GetFilename()).absolutePath();
|
||||
result.buildDir = (prjpath + '/' + buildDir).toStdString();
|
||||
}
|
||||
}
|
||||
|
||||
// Include directories (and files) are searched in listed order.
|
||||
|
@ -759,6 +779,8 @@ Settings MainWindow::GetCppcheckSettings()
|
|||
result.addEnabled("portability");
|
||||
result.addEnabled("information");
|
||||
result.addEnabled("missingInclude");
|
||||
if (!result.buildDir.empty())
|
||||
result.addEnabled("unusedFunction");
|
||||
result.debug = false;
|
||||
result.debugwarnings = mSettings->value(SETTINGS_SHOW_DEBUG_WARNINGS, false).toBool();
|
||||
result.quiet = false;
|
||||
|
|
|
@ -86,53 +86,40 @@ bool Project::Open()
|
|||
bool Project::Edit()
|
||||
{
|
||||
ProjectFileDialog dlg(mFilename, mParentWidget);
|
||||
QString root = mPFile->GetRootPath();
|
||||
dlg.SetRootPath(root);
|
||||
QStringList includes = mPFile->GetIncludeDirs();
|
||||
dlg.SetIncludepaths(includes);
|
||||
QStringList defines = mPFile->GetDefines();
|
||||
dlg.SetDefines(defines);
|
||||
QStringList paths = mPFile->GetCheckPaths();
|
||||
dlg.SetPaths(paths);
|
||||
QString importProject = mPFile->GetImportProject();
|
||||
dlg.SetImportProject(importProject);
|
||||
QStringList ignorepaths = mPFile->GetExcludedPaths();
|
||||
dlg.SetExcludedPaths(ignorepaths);
|
||||
QStringList libraries = mPFile->GetLibraries();
|
||||
dlg.SetLibraries(libraries);
|
||||
QStringList suppressions = mPFile->GetSuppressions();
|
||||
dlg.SetSuppressions(suppressions);
|
||||
dlg.SetRootPath(mPFile->GetRootPath());
|
||||
dlg.SetBuildDir(mPFile->GetBuildDir());
|
||||
dlg.SetIncludepaths(mPFile->GetIncludeDirs());
|
||||
dlg.SetDefines(mPFile->GetDefines());
|
||||
dlg.SetPaths(mPFile->GetCheckPaths());
|
||||
dlg.SetImportProject(mPFile->GetImportProject());
|
||||
dlg.SetExcludedPaths(mPFile->GetExcludedPaths());
|
||||
dlg.SetLibraries(mPFile->GetLibraries());
|
||||
dlg.SetSuppressions(mPFile->GetSuppressions());
|
||||
|
||||
int rv = dlg.exec();
|
||||
if (rv == QDialog::Accepted) {
|
||||
QString root = dlg.GetRootPath();
|
||||
mPFile->SetRootPath(root);
|
||||
if (dlg.exec() != QDialog::Accepted)
|
||||
return false;
|
||||
|
||||
mPFile->SetRootPath(dlg.GetRootPath());
|
||||
mPFile->SetBuildDir(dlg.GetBuildDir());
|
||||
mPFile->SetImportProject(dlg.GetImportProject());
|
||||
QStringList includes = dlg.GetIncludePaths();
|
||||
mPFile->SetIncludes(includes);
|
||||
QStringList defines = dlg.GetDefines();
|
||||
mPFile->SetDefines(defines);
|
||||
QStringList paths = dlg.GetPaths();
|
||||
mPFile->SetCheckPaths(paths);
|
||||
QStringList excludedpaths = dlg.GetExcludedPaths();
|
||||
mPFile->SetExcludedPaths(excludedpaths);
|
||||
QStringList libraries = dlg.GetLibraries();
|
||||
mPFile->SetLibraries(libraries);
|
||||
QStringList suppressions = dlg.GetSuppressions();
|
||||
mPFile->SetSuppressions(suppressions);
|
||||
mPFile->SetIncludes(dlg.GetIncludePaths());
|
||||
mPFile->SetDefines(dlg.GetDefines());
|
||||
mPFile->SetCheckPaths(dlg.GetPaths());
|
||||
mPFile->SetExcludedPaths(dlg.GetExcludedPaths());
|
||||
mPFile->SetLibraries(dlg.GetLibraries());
|
||||
mPFile->SetSuppressions(dlg.GetSuppressions());
|
||||
|
||||
bool writeSuccess = mPFile->Write();
|
||||
if (!writeSuccess) {
|
||||
if (!mPFile->Write()) {
|
||||
QMessageBox msg(QMessageBox::Critical,
|
||||
tr("Cppcheck"),
|
||||
tr("Could not write the project file."),
|
||||
QMessageBox::Ok,
|
||||
mParentWidget);
|
||||
msg.exec();
|
||||
}
|
||||
return writeSuccess;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Project::Create()
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
static const char ProjectElementName[] = "project";
|
||||
static const char ProjectVersionAttrib[] = "version";
|
||||
static const char ProjectFileVersion[] = "1";
|
||||
static const char BuildDirElementName[] = "builddir";
|
||||
static const char ImportProjectElementName[] = "importproject";
|
||||
static const char IncludeDirElementName[] = "includedir";
|
||||
static const char DirElementName[] = "dir";
|
||||
|
@ -84,6 +85,10 @@ bool ProjectFile::Read(const QString &filename)
|
|||
if (insideProject && xmlReader.name() == RootPathName)
|
||||
ReadRootPath(xmlReader);
|
||||
|
||||
// Read root path from inside project element
|
||||
if (insideProject && xmlReader.name() == BuildDirElementName)
|
||||
ReadBuildDir(xmlReader);
|
||||
|
||||
// Find paths to check from inside project element
|
||||
if (insideProject && xmlReader.name() == PathsElementName)
|
||||
ReadCheckPaths(xmlReader);
|
||||
|
@ -152,6 +157,31 @@ void ProjectFile::ReadRootPath(QXmlStreamReader &reader)
|
|||
mRootPath = name;
|
||||
}
|
||||
|
||||
void ProjectFile::ReadBuildDir(QXmlStreamReader &reader)
|
||||
{
|
||||
mBuildDir.clear();
|
||||
do {
|
||||
const QXmlStreamReader::TokenType type = reader.readNext();
|
||||
switch (type) {
|
||||
case QXmlStreamReader::Characters:
|
||||
mBuildDir = reader.text().toString();
|
||||
case QXmlStreamReader::EndElement:
|
||||
return;
|
||||
// Not handled
|
||||
case QXmlStreamReader::StartElement:
|
||||
case QXmlStreamReader::NoToken:
|
||||
case QXmlStreamReader::Invalid:
|
||||
case QXmlStreamReader::StartDocument:
|
||||
case QXmlStreamReader::EndDocument:
|
||||
case QXmlStreamReader::Comment:
|
||||
case QXmlStreamReader::DTD:
|
||||
case QXmlStreamReader::EntityReference:
|
||||
case QXmlStreamReader::ProcessingInstruction:
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
}
|
||||
|
||||
void ProjectFile::ReadImportProject(QXmlStreamReader &reader)
|
||||
{
|
||||
mImportProject.clear();
|
||||
|
@ -426,6 +456,12 @@ bool ProjectFile::Write(const QString &filename)
|
|||
xmlWriter.writeEndElement();
|
||||
}
|
||||
|
||||
if (!mBuildDir.isEmpty()) {
|
||||
xmlWriter.writeStartElement(BuildDirElementName);
|
||||
xmlWriter.writeCharacters(mBuildDir);
|
||||
xmlWriter.writeEndElement();
|
||||
}
|
||||
|
||||
if (!mImportProject.isEmpty()) {
|
||||
xmlWriter.writeStartElement(ImportProjectElementName);
|
||||
xmlWriter.writeCharacters(mImportProject);
|
||||
|
|
|
@ -54,6 +54,10 @@ public:
|
|||
return mRootPath;
|
||||
}
|
||||
|
||||
QString GetBuildDir() const {
|
||||
return mBuildDir;
|
||||
}
|
||||
|
||||
QString GetImportProject() const {
|
||||
return mImportProject;
|
||||
}
|
||||
|
@ -122,6 +126,11 @@ public:
|
|||
mRootPath = rootpath;
|
||||
}
|
||||
|
||||
|
||||
void SetBuildDir(const QString &buildDir) {
|
||||
mBuildDir = buildDir;
|
||||
}
|
||||
|
||||
void SetImportProject(const QString &importProject) {
|
||||
mImportProject = importProject;
|
||||
}
|
||||
|
@ -193,6 +202,8 @@ protected:
|
|||
*/
|
||||
void ReadRootPath(QXmlStreamReader &reader);
|
||||
|
||||
void ReadBuildDir(QXmlStreamReader &reader);
|
||||
|
||||
/**
|
||||
* @brief Read importproject from XML.
|
||||
* @param reader XML stream reader.
|
||||
|
@ -251,6 +262,10 @@ private:
|
|||
*/
|
||||
QString mRootPath;
|
||||
|
||||
/** Cppcheck build dir */
|
||||
QString mBuildDir;
|
||||
|
||||
/** Visual studio project/solution , compile database */
|
||||
QString mImportProject;
|
||||
|
||||
/**
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>615</width>
|
||||
<height>357</height>
|
||||
<width>635</width>
|
||||
<height>368</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -41,6 +41,27 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_9">
|
||||
<item>
|
||||
<widget class="QLabel" name="buildDirLabel">
|
||||
<property name="text">
|
||||
<string>Cppcheck build dir (optional)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="buildDirEdit"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buildDirBrowse">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_10">
|
||||
<property name="orientation">
|
||||
|
|
|
@ -83,6 +83,7 @@ ProjectFileDialog::ProjectFileDialog(const QString &path, QWidget *parent)
|
|||
}
|
||||
|
||||
connect(mUI.mButtons, SIGNAL(accepted()), this, SLOT(accept()));
|
||||
connect(mUI.buildDirBrowse, SIGNAL(clicked()), this, SLOT(BrowseBuildDir()));
|
||||
connect(mUI.mBrowseCompileDatabase, SIGNAL(clicked()), this, SLOT(BrowseCompileDatabase()));
|
||||
connect(mUI.mBrowseVisualStudio, SIGNAL(clicked()), this, SLOT(BrowseVisualStudio()));
|
||||
connect(mUI.mBtnAddInclude, SIGNAL(clicked()), this, SLOT(AddIncludeDir()));
|
||||
|
@ -119,6 +120,38 @@ void ProjectFileDialog::SaveSettings() const
|
|||
settings.setValue(SETTINGS_PROJECT_DIALOG_HEIGHT, size().height());
|
||||
}
|
||||
|
||||
|
||||
QString ProjectFileDialog::getExistingDirectory(const QString &caption, bool trailingSlash) {
|
||||
const QFileInfo inf(mFilePath);
|
||||
const QString rootpath = inf.absolutePath();
|
||||
QString selectedDir = QFileDialog::getExistingDirectory(this,
|
||||
caption,
|
||||
rootpath);
|
||||
|
||||
if (selectedDir.isEmpty())
|
||||
return QString();
|
||||
|
||||
// Check if the path is relative to project file's path and if so
|
||||
// make it a relative path instead of absolute path.
|
||||
const QDir dir(rootpath);
|
||||
const QString relpath(dir.relativeFilePath(selectedDir));
|
||||
if (!relpath.startsWith("."))
|
||||
selectedDir = relpath;
|
||||
|
||||
// Trailing slash..
|
||||
if (trailingSlash && !selectedDir.endsWith('/'))
|
||||
selectedDir += '/';
|
||||
|
||||
return selectedDir;
|
||||
}
|
||||
|
||||
void ProjectFileDialog::BrowseBuildDir()
|
||||
{
|
||||
const QString dir(getExistingDirectory(tr("Select Cppcheck build dir"), false));
|
||||
if (!dir.isEmpty())
|
||||
mUI.buildDirEdit->setText(dir);
|
||||
}
|
||||
|
||||
void ProjectFileDialog::BrowseCompileDatabase()
|
||||
{
|
||||
const QFileInfo inf(mFilePath);
|
||||
|
@ -180,6 +213,10 @@ QString ProjectFileDialog::GetRootPath() const
|
|||
return root;
|
||||
}
|
||||
|
||||
QString ProjectFileDialog::GetBuildDir() const {
|
||||
return mUI.buildDirEdit->text();
|
||||
}
|
||||
|
||||
QString ProjectFileDialog::GetImportProject() const
|
||||
{
|
||||
return mUI.mEditCompileDatabase->text() + mUI.mEditVisualStudio->text();
|
||||
|
@ -253,10 +290,12 @@ QStringList ProjectFileDialog::GetSuppressions() const
|
|||
return suppressions;
|
||||
}
|
||||
|
||||
void ProjectFileDialog::SetRootPath(const QString &root)
|
||||
{
|
||||
QString newroot = QDir::toNativeSeparators(root);
|
||||
mUI.mEditProjectRoot->setText(newroot);
|
||||
void ProjectFileDialog::SetRootPath(const QString &root) {
|
||||
mUI.mEditProjectRoot->setText(QDir::toNativeSeparators(root));
|
||||
}
|
||||
|
||||
void ProjectFileDialog::SetBuildDir(const QString &buildDir) {
|
||||
mUI.buildDirEdit->setText(buildDir);
|
||||
}
|
||||
|
||||
void ProjectFileDialog::SetImportProject(const QString &importProject)
|
||||
|
@ -321,38 +360,16 @@ void ProjectFileDialog::SetSuppressions(const QStringList &suppressions)
|
|||
|
||||
void ProjectFileDialog::AddIncludeDir()
|
||||
{
|
||||
const QFileInfo inf(mFilePath);
|
||||
const QString rootpath = inf.absolutePath();
|
||||
QString selectedDir = QFileDialog::getExistingDirectory(this,
|
||||
tr("Select include directory"),
|
||||
rootpath);
|
||||
|
||||
if (!selectedDir.isEmpty()) {
|
||||
// Check if the path is relative to project file's path and if so
|
||||
// make it a relative path instead of absolute path.
|
||||
const QDir dir(selectedDir);
|
||||
QString absPath = dir.absolutePath();
|
||||
if (absPath.startsWith(rootpath)) {
|
||||
// Remove also the slash from begin of new relative path
|
||||
selectedDir = absPath.remove(0, rootpath.length() + 1);
|
||||
}
|
||||
if (!selectedDir.endsWith("/"))
|
||||
selectedDir += '/';
|
||||
AddIncludeDir(selectedDir);
|
||||
}
|
||||
const QString dir = getExistingDirectory(tr("Select include directory"), true);
|
||||
if (!dir.isEmpty())
|
||||
AddIncludeDir(dir);
|
||||
}
|
||||
|
||||
void ProjectFileDialog::AddPath()
|
||||
{
|
||||
QFileInfo inf(mFilePath);
|
||||
const QString rootpath = inf.absolutePath();
|
||||
QString selectedDir = QFileDialog::getExistingDirectory(this,
|
||||
tr("Select a directory to check"),
|
||||
rootpath);
|
||||
|
||||
if (!selectedDir.isEmpty()) {
|
||||
AddPath(selectedDir);
|
||||
}
|
||||
QString dir = getExistingDirectory(tr("Select a directory to check"), false);
|
||||
if (!dir.isEmpty())
|
||||
AddPath(dir);
|
||||
}
|
||||
|
||||
void ProjectFileDialog::RemoveIncludeDir()
|
||||
|
@ -383,18 +400,9 @@ void ProjectFileDialog::RemovePath()
|
|||
|
||||
void ProjectFileDialog::AddExcludePath()
|
||||
{
|
||||
QFileInfo inf(mFilePath);
|
||||
const QString rootpath = inf.absolutePath();
|
||||
|
||||
QString selectedDir = QFileDialog::getExistingDirectory(this,
|
||||
tr("Select directory to ignore"),
|
||||
rootpath);
|
||||
|
||||
if (!selectedDir.isEmpty()) {
|
||||
if (!selectedDir.endsWith('/'))
|
||||
selectedDir += '/';
|
||||
AddExcludePath(selectedDir);
|
||||
}
|
||||
QString dir = getExistingDirectory(tr("Select directory to ignore"), true);
|
||||
if (!dir.isEmpty())
|
||||
AddExcludePath(dir);
|
||||
}
|
||||
|
||||
void ProjectFileDialog::EditExcludePath()
|
||||
|
|
|
@ -49,6 +49,9 @@ public:
|
|||
|
||||
QString GetImportProject() const;
|
||||
|
||||
/** Get Cppcheck build dir */
|
||||
QString GetBuildDir() const;
|
||||
|
||||
/**
|
||||
* @brief Return include paths from the dialog control.
|
||||
* @return List of include paths.
|
||||
|
@ -91,6 +94,9 @@ public:
|
|||
*/
|
||||
void SetRootPath(const QString &root);
|
||||
|
||||
/** Set build dir */
|
||||
void SetBuildDir(const QString &buildDir);
|
||||
|
||||
void SetImportProject(const QString &importProject);
|
||||
|
||||
/**
|
||||
|
@ -131,6 +137,11 @@ public:
|
|||
|
||||
protected slots:
|
||||
|
||||
/**
|
||||
* @brief Browse for build dir.
|
||||
*/
|
||||
void BrowseBuildDir();
|
||||
|
||||
/**
|
||||
* @brief Browse for Visual Studio solution/project.
|
||||
*/
|
||||
|
@ -247,6 +258,8 @@ private:
|
|||
|
||||
/** @brief Library checkboxes */
|
||||
QList<QCheckBox*> mLibraryCheckboxes;
|
||||
|
||||
QString getExistingDirectory(const QString &caption, bool trailingSlash);
|
||||
};
|
||||
|
||||
/// @}
|
||||
|
|
|
@ -29,7 +29,9 @@
|
|||
ThreadHandler::ThreadHandler(QObject *parent) :
|
||||
QObject(parent),
|
||||
mScanDuration(0),
|
||||
mRunningThreadCount(0)
|
||||
mRunningThreadCount(0),
|
||||
mAnalyseWholeProgram(false)
|
||||
|
||||
{
|
||||
SetThreadCount(1);
|
||||
}
|
||||
|
@ -43,6 +45,7 @@ void ThreadHandler::ClearFiles()
|
|||
{
|
||||
mLastFiles.clear();
|
||||
mResults.ClearFiles();
|
||||
mAnalyseWholeProgram = false;
|
||||
}
|
||||
|
||||
void ThreadHandler::SetFiles(const QStringList &files)
|
||||
|
@ -94,6 +97,8 @@ void ThreadHandler::Check(const Settings &settings, bool all)
|
|||
// Date and time when checking starts..
|
||||
mCheckStartTime = QDateTime::currentDateTime();
|
||||
|
||||
mAnalyseWholeProgram = true;
|
||||
|
||||
mTime.start();
|
||||
}
|
||||
|
||||
|
@ -137,10 +142,17 @@ void ThreadHandler::RemoveThreads()
|
|||
}
|
||||
|
||||
mThreads.clear();
|
||||
mAnalyseWholeProgram = false;
|
||||
}
|
||||
|
||||
void ThreadHandler::ThreadDone()
|
||||
{
|
||||
if (mRunningThreadCount == 1 && mAnalyseWholeProgram) {
|
||||
mThreads[0]->AnalyseWholeProgram(mLastFiles);
|
||||
mAnalyseWholeProgram = false;
|
||||
return;
|
||||
}
|
||||
|
||||
mRunningThreadCount--;
|
||||
if (mRunningThreadCount == 0) {
|
||||
emit Done();
|
||||
|
@ -158,6 +170,7 @@ void ThreadHandler::ThreadDone()
|
|||
void ThreadHandler::Stop()
|
||||
{
|
||||
mCheckStartTime = QDateTime();
|
||||
mAnalyseWholeProgram = false;
|
||||
for (int i = 0; i < mThreads.size(); i++) {
|
||||
mThreads[i]->stop();
|
||||
}
|
||||
|
|
|
@ -234,6 +234,8 @@ protected:
|
|||
*
|
||||
*/
|
||||
int mRunningThreadCount;
|
||||
|
||||
bool mAnalyseWholeProgram;
|
||||
private:
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue