ClangTools: Prompt for files to analyze

If the run button is clicked, the user is prompted to select the files
for analysis.

Change-Id: I21e4ee6b7c14392a8c1a901ac7aa1c9c16e30f0d
Reviewed-by: Ivan Donchevskii <ivan.donchevskii@qt.io>
This commit is contained in:
Nikolai Kosjar
2018-05-02 14:51:05 +02:00
parent ef528e1801
commit 1bc605d050
22 changed files with 546 additions and 61 deletions

View File

@@ -0,0 +1,47 @@
/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include <cpptools/cppprojectfile.h>
#include <cpptools/projectpart.h>
#include <utils/fileutils.h>
namespace ClangTools {
namespace Internal {
class FileInfo
{
public:
Utils::FileName file;
CppTools::ProjectFile::Kind kind;
CppTools::ProjectPart::Ptr projectPart;
};
using FileInfos = QVector<FileInfo>;
} // namespace Internal
} // namespace ClangTools

View File

@@ -0,0 +1,233 @@
/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "clangselectablefilesdialog.h"
#include "ui_clangselectablefilesdialog.h"
#include "clangtoolsutils.h"
#include <cpptools/compileroptionsbuilder.h>
#include <cpptools/cppmodelmanager.h>
#include <cpptools/projectinfo.h>
#include <cpptools/projectpart.h>
#include <projectexplorer/selectablefilesmodel.h>
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
#include <QPushButton>
using namespace CppTools;
using namespace Utils;
using namespace ProjectExplorer;
namespace ClangTools {
namespace Internal {
class TreeWithFileInfo : public Tree
{
public:
FileInfo info;
};
static void linkDirNode(Tree *parentNode, Tree *childNode)
{
parentNode->childDirectories.append(childNode);
childNode->parent = parentNode;
}
static void linkFileNode(Tree *parentNode, Tree *childNode)
{
childNode->parent = parentNode;
parentNode->files.append(childNode);
parentNode->visibleFiles.append(childNode);
}
static Tree *createDirNode(const QString &name, const FileName &filePath = FileName())
{
auto node = new Tree;
node->name = name;
node->fullPath = filePath;
node->isDir = true;
return node;
}
static Tree *createFileNode(const FileInfo &fileInfo, bool displayFullPath = false)
{
auto node = new TreeWithFileInfo;
node->name = displayFullPath ? fileInfo.file.toString() : fileInfo.file.fileName();
node->fullPath = fileInfo.file;
node->info = fileInfo;
return node;
}
class SelectableFilesModel : public ProjectExplorer::SelectableFilesModel
{
Q_OBJECT
public:
SelectableFilesModel(const CppTools::ProjectInfo &projectInfo, const FileInfos &allFileInfos)
: ProjectExplorer::SelectableFilesModel(nullptr)
{
buildTree(projectInfo.project(), allFileInfos);
}
void buildTree(ProjectExplorer::Project *project, const FileInfos &fileInfos)
{
m_root->fullPath = project->projectFilePath();
m_root->name = project->projectFilePath().fileName();
m_root->isDir = true;
FileInfos outOfBaseDirFiles;
Tree *projectDirTree = buildProjectDirTree(project->projectDirectory(),
fileInfos,
outOfBaseDirFiles);
if (outOfBaseDirFiles.isEmpty()) {
// Showing the project file and beneath the project dir is pointless in this case,
// so get rid of the root node and modify the project dir node as the new root node.
projectDirTree->name = m_root->name;
projectDirTree->fullPath = m_root->fullPath;
projectDirTree->parent = m_root->parent;
delete m_root; // OK, it has no files / child dirs.
m_root = projectDirTree;
} else {
// Set up project dir node as sub node of the project file node
linkDirNode(m_root, projectDirTree);
// Add files outside of the base directory to a separate node
Tree *externalFilesNode = createDirNode(SelectableFilesDialog::tr(
"Files outside of the base directory"),
FileName::fromString("/"));
linkDirNode(m_root, externalFilesNode);
for (const FileInfo &fileInfo : outOfBaseDirFiles)
linkFileNode(externalFilesNode, createFileNode(fileInfo, true));
}
}
static Tree *buildProjectDirTree(const FileName &projectDir,
const FileInfos &fileInfos,
FileInfos &outOfBaseDirFiles)
{
Tree *projectDirNode = createDirNode(projectDir.fileName(), projectDir);
QHash<FileName, Tree *> dirsToNode;
dirsToNode.insert(projectDirNode->fullPath, projectDirNode);
for (const FileInfo &fileInfo : fileInfos) {
if (!fileInfo.file.isChildOf(projectDirNode->fullPath)) {
outOfBaseDirFiles += fileInfo;
continue; // Handle these separately.
}
// Find or create parent nodes
FileName parentDir = fileInfo.file.parentDir();
Tree *parentNode = dirsToNode[parentDir];
if (!parentNode) {
// Find nearest existing node
QStringList dirsToCreate;
while (!parentNode) {
dirsToCreate.prepend(parentDir.fileName());
parentDir = parentDir.parentDir();
parentNode = dirsToNode[parentDir];
}
// Create needed extra dir nodes
FileName currentDirPath = parentDir;
for (const QString &dirName : dirsToCreate) {
currentDirPath.appendPath(dirName);
Tree *newDirNode = createDirNode(dirName, currentDirPath);
linkDirNode(parentNode, newDirNode);
dirsToNode.insert(currentDirPath, newDirNode);
parentNode = newDirNode;
}
}
// Create and link file node to dir node
linkFileNode(parentNode, createFileNode(fileInfo));
}
return projectDirNode;
}
FileInfos selectedFileInfos() const
{
FileInfos result;
collectFileInfos(m_root, &result);
return result;
}
private:
void collectFileInfos(ProjectExplorer::Tree *root, FileInfos *result) const
{
if (root->checked == Qt::Unchecked)
return;
for (Tree *t : root->childDirectories)
collectFileInfos(t, result);
for (Tree *t : root->visibleFiles) {
if (t->checked == Qt::Checked)
result->append(static_cast<TreeWithFileInfo *>(t)->info);
}
}
};
SelectableFilesDialog::SelectableFilesDialog(const ProjectInfo &projectInfo,
const FileInfos &allFileInfos)
: QDialog(nullptr)
, m_ui(new Ui::SelectableFilesDialog)
, m_filesModel(new SelectableFilesModel(projectInfo, allFileInfos))
, m_analyzeButton(new QPushButton(tr("Analyze"), this))
{
m_ui->setupUi(this);
m_ui->filesView->setModel(m_filesModel.get());
m_ui->filesView->expandToDepth(2);
m_ui->buttons->setStandardButtons(QDialogButtonBox::Cancel);
m_ui->buttons->addButton(m_analyzeButton, QDialogButtonBox::AcceptRole);
m_analyzeButton->setEnabled(m_filesModel->hasCheckedFiles());
connect(m_filesModel.get(), &QAbstractItemModel::dataChanged, [this]() {
m_analyzeButton->setEnabled(m_filesModel->hasCheckedFiles());
});
}
SelectableFilesDialog::~SelectableFilesDialog() {}
FileInfos SelectableFilesDialog::filteredFileInfos() const
{
return m_filesModel->selectedFileInfos();
}
} // namespace Internal
} // namespace ClangTools
#include "clangselectablefilesdialog.moc"

View File

@@ -0,0 +1,65 @@
/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include "clangfileinfo.h"
#include <QDialog>
#include <memory>
QT_BEGIN_NAMESPACE
class QPushButton;
QT_END_NAMESPACE
namespace CppTools { class ProjectInfo; }
namespace ClangTools {
namespace Internal {
namespace Ui { class SelectableFilesDialog; }
class SelectableFilesModel;
class SelectableFilesDialog : public QDialog
{
Q_OBJECT
public:
explicit SelectableFilesDialog(const CppTools::ProjectInfo &projectInfo,
const FileInfos &allFileInfos);
~SelectableFilesDialog() override;
FileInfos filteredFileInfos() const;
private:
std::unique_ptr<Ui::SelectableFilesDialog> m_ui;
std::unique_ptr<SelectableFilesModel> m_filesModel;
QPushButton *m_analyzeButton = nullptr;
};
} // namespace Internal
} // namespace ClangTools

View File

@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ClangTools::Internal::SelectableFilesDialog</class>
<widget class="QDialog" name="ClangTools::Internal::SelectableFilesDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>700</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>Select the Files to Analyze</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTreeView" name="filesView">
<property name="headerHidden">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttons">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttons</sender>
<signal>accepted()</signal>
<receiver>ClangTools::Internal::SelectableFilesDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttons</sender>
<signal>rejected()</signal>
<receiver>ClangTools::Internal::SelectableFilesDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -120,7 +120,7 @@ void ClangStaticAnalyzerPreconfiguredSessionTests::testPreconfiguredSession()
QVERIFY(switchToProjectAndTarget(project, target));
ClangStaticAnalyzerTool::instance()->startTool();
ClangStaticAnalyzerTool::instance()->startTool(false);
QSignalSpy waitUntilAnalyzerFinished(ClangStaticAnalyzerTool::instance(), SIGNAL(finished(bool)));
QVERIFY(waitUntilAnalyzerFinished.wait(30000));
const QList<QVariant> arguments = waitUntilAnalyzerFinished.takeFirst();

View File

@@ -71,8 +71,10 @@ using namespace ProjectExplorer;
namespace ClangTools {
namespace Internal {
ClangStaticAnalyzerRunControl::ClangStaticAnalyzerRunControl(RunControl *runControl, Target *target)
: ClangToolRunControl(runControl, target)
ClangStaticAnalyzerRunControl::ClangStaticAnalyzerRunControl(RunControl *runControl,
Target *target,
const FileInfos &fileInfos)
: ClangToolRunControl(runControl, target, fileInfos)
{
setDisplayName("ClangStaticAnalyzerRunner");

View File

@@ -25,6 +25,7 @@
#pragma once
#include "clangfileinfo.h"
#include "clangtoolruncontrol.h"
namespace ClangTools {
@@ -36,7 +37,8 @@ class ClangStaticAnalyzerRunControl final : public ClangToolRunControl
public:
ClangStaticAnalyzerRunControl(ProjectExplorer::RunControl *runControl,
ProjectExplorer::Target *target);
ProjectExplorer::Target *target,
const FileInfos &fileInfos);
protected:
ClangToolRunner *createRunner() final;

View File

@@ -108,11 +108,11 @@ ClangStaticAnalyzerTool::ClangStaticAnalyzerTool()
{{ClangStaticAnalyzerDockId, m_diagnosticView, {}, Perspective::SplitVertical}}
));
action = new QAction(tr("Clang Static Analyzer"), this);
action = new QAction(tr("Clang Static Analyzer..."), this);
action->setToolTip(toolTip);
menu->addAction(ActionManager::registerAction(action, "ClangStaticAnalyzer.Action"),
Debugger::Constants::G_ANALYZER_TOOLS);
QObject::connect(action, &QAction::triggered, this, &ClangStaticAnalyzerTool::startTool);
QObject::connect(action, &QAction::triggered, this, [this]() { startTool(true); });
QObject::connect(m_startAction, &QAction::triggered, action, &QAction::triggered);
QObject::connect(m_startAction, &QAction::changed, action, [action, this] {
action->setEnabled(m_startAction->isEnabled());
@@ -136,7 +136,7 @@ ClangStaticAnalyzerTool *ClangStaticAnalyzerTool::instance()
return s_instance;
}
void ClangStaticAnalyzerTool::startTool()
void ClangStaticAnalyzerTool::startTool(bool askUserForFileSelection)
{
auto runControl = new RunControl(nullptr, Constants::CLANGSTATICANALYZER_RUN_MODE);
runControl->setDisplayName(tr("Clang Static Analyzer"));
@@ -146,7 +146,13 @@ void ClangStaticAnalyzerTool::startTool()
QTC_ASSERT(project, return);
QTC_ASSERT(project->activeTarget(), return);
auto clangTool = new ClangStaticAnalyzerRunControl(runControl, project->activeTarget());
const FileInfos fileInfos = collectFileInfos(project, askUserForFileSelection);
if (fileInfos.isEmpty())
return;
auto clangTool = new ClangStaticAnalyzerRunControl(runControl,
project->activeTarget(),
fileInfos);
m_stopAction->disconnect();
connect(m_stopAction, &QAction::triggered, runControl, [runControl] {

View File

@@ -47,7 +47,7 @@ public:
static ClangStaticAnalyzerTool *instance();
void startTool() final;
void startTool(bool askUserForFileSelection) final;
QList<Diagnostic> read(const QString &,
const QString &logFilePath,

View File

@@ -33,8 +33,10 @@ using namespace ProjectExplorer;
namespace ClangTools {
namespace Internal {
ClangTidyClazyRunControl::ClangTidyClazyRunControl(RunControl *runControl, Target *target)
: ClangToolRunControl(runControl, target)
ClangTidyClazyRunControl::ClangTidyClazyRunControl(RunControl *runControl,
Target *target,
const FileInfos &fileInfos)
: ClangToolRunControl(runControl, target, fileInfos)
{
setDisplayName("ClangTidyClazyRunner");
init();

View File

@@ -36,7 +36,8 @@ class ClangTidyClazyRunControl final : public ClangToolRunControl
public:
ClangTidyClazyRunControl(ProjectExplorer::RunControl *runControl,
ProjectExplorer::Target *target);
ProjectExplorer::Target *target,
const FileInfos &fileInfos);
protected:
ClangToolRunner *createRunner() final;

View File

@@ -25,6 +25,7 @@
#include "clangtidyclazytool.h"
#include "clangselectablefilesdialog.h"
#include "clangtoolsconstants.h"
#include "clangtoolsdiagnosticmodel.h"
#include "clangtoolslogfilereader.h"
@@ -33,6 +34,8 @@
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <cpptools/cppmodelmanager.h>
#include <debugger/analyzer/analyzermanager.h>
#include <projectexplorer/kitinformation.h>
@@ -76,11 +79,11 @@ ClangTidyClazyTool::ClangTidyClazyTool()
{{ClangTidyClazyDockId, m_diagnosticView, {}, Perspective::SplitVertical}}
));
auto *action = new QAction(tr("Clang-Tidy and Clazy"), this);
auto *action = new QAction(tr("Clang-Tidy and Clazy..."), this);
action->setToolTip(toolTip);
menu->addAction(ActionManager::registerAction(action, "ClangTidyClazy.Action"),
Debugger::Constants::G_ANALYZER_TOOLS);
QObject::connect(action, &QAction::triggered, this, &ClangTidyClazyTool::startTool);
QObject::connect(action, &QAction::triggered, this, [this]() { startTool(true); });
QObject::connect(m_startAction, &QAction::triggered, action, &QAction::triggered);
QObject::connect(m_startAction, &QAction::changed, action, [action, this] {
action->setEnabled(m_startAction->isEnabled());
@@ -103,7 +106,7 @@ ClangTidyClazyTool *ClangTidyClazyTool::instance()
return s_instance;
}
void ClangTidyClazyTool::startTool()
void ClangTidyClazyTool::startTool(bool askUserForFileSelection)
{
auto runControl = new RunControl(nullptr, Constants::CLANGTIDYCLAZY_RUN_MODE);
runControl->setDisplayName(tr("Clang-Tidy and Clazy"));
@@ -112,7 +115,11 @@ void ClangTidyClazyTool::startTool()
Project *project = SessionManager::startupProject();
QTC_ASSERT(project, return);
auto clangTool = new ClangTidyClazyRunControl(runControl, project->activeTarget());
const FileInfos fileInfos = collectFileInfos(project, askUserForFileSelection);
if (fileInfos.isEmpty())
return;
auto clangTool = new ClangTidyClazyRunControl(runControl, project->activeTarget(), fileInfos);
m_stopAction->disconnect();
connect(m_stopAction, &QAction::triggered, runControl, [runControl] {

View File

@@ -42,7 +42,7 @@ public:
static ClangTidyClazyTool *instance();
void startTool() final;
void startTool(bool askUserForFileSelection) final;
QList<Diagnostic> read(const QString &filePath,
const QString &logFilePath,

View File

@@ -25,15 +25,19 @@
#include "clangtool.h"
#include "clangselectablefilesdialog.h"
#include "clangtoolsconstants.h"
#include "clangtoolsdiagnostic.h"
#include "clangtoolsdiagnosticmodel.h"
#include "clangtoolsutils.h"
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/icore.h>
#include <cpptools/cppmodelmanager.h>
#include <debugger/analyzer/analyzermanager.h>
#include <projectexplorer/kitinformation.h>
@@ -58,6 +62,33 @@ using namespace Utils;
namespace ClangTools {
namespace Internal {
static FileInfos sortedFileInfos(const QVector<CppTools::ProjectPart::Ptr> &projectParts)
{
FileInfos fileInfos;
for (CppTools::ProjectPart::Ptr projectPart : projectParts) {
QTC_ASSERT(projectPart, continue);
if (!projectPart->selectedForBuilding)
continue;
for (const CppTools::ProjectFile &file : projectPart->files) {
QTC_ASSERT(file.kind != CppTools::ProjectFile::Unclassified, continue);
QTC_ASSERT(file.kind != CppTools::ProjectFile::Unsupported, continue);
if (file.path == CppTools::CppModelManager::configurationFileName())
continue;
if (CppTools::ProjectFile::isSource(file.kind)) {
const FileInfo info{Utils::FileName::fromString(file.path), file.kind, projectPart};
fileInfos.append(info);
}
}
}
Utils::sort(fileInfos, &FileInfo::file);
return fileInfos;
}
ClangTool::ClangTool(const QString &name)
: m_name(name)
{
@@ -67,6 +98,23 @@ ClangTool::ClangTool(const QString &name)
m_stopAction = Debugger::createStopAction();
}
FileInfos ClangTool::collectFileInfos(Project *project, bool askUserForFileSelection) const
{
auto projectInfo = CppTools::CppModelManager::instance()->projectInfo(project);
QTC_ASSERT(projectInfo.isValid(), return FileInfos());
const FileInfos allFileInfos = sortedFileInfos(projectInfo.projectParts());
if (askUserForFileSelection) {
SelectableFilesDialog dialog(projectInfo, allFileInfos);
if (dialog.exec() == QDialog::Rejected)
return FileInfos();
return dialog.filteredFileInfos();
} else {
return allFileInfos;
}
}
const QString &ClangTool::name() const
{
return m_name;

View File

@@ -25,6 +25,8 @@
#pragma once
#include "clangfileinfo.h"
#include <projectexplorer/runconfiguration.h>
#include <cpptools/projectinfo.h>
@@ -44,12 +46,15 @@ public:
ClangTool(const QString &name);
virtual ~ClangTool() = default;
virtual void startTool() = 0;
virtual void startTool(bool askUserForFileSelection) = 0;
virtual QList<Diagnostic> read(const QString &filePath,
const QString &logFilePath,
QString *errorMessage) const = 0;
FileInfos collectFileInfos(ProjectExplorer::Project *project,
bool askUserForFileSelection) const;
// For testing.
QList<Diagnostic> diagnostics() const;

View File

@@ -185,48 +185,31 @@ private:
bool m_success = false;
};
static AnalyzeUnits unitsToAnalyzeFromProjectParts(const QVector<ProjectPart::Ptr> projectParts,
const QString &clangVersion,
const QString &clangResourceDirectory)
static AnalyzeUnits toAnalyzeUnits(const FileInfos &fileInfos,
const QString &clangVersion,
const QString &clangResourceDirectory)
{
qCDebug(LOG) << "Taking arguments for analyzing from ProjectParts.";
AnalyzeUnits unitsToAnalyze;
foreach (const ProjectPart::Ptr &projectPart, projectParts) {
if (!projectPart->selectedForBuilding || !projectPart.data())
continue;
foreach (const ProjectFile &file, projectPart->files) {
if (file.path == CppModelManager::configurationFileName())
continue;
QTC_CHECK(file.kind != ProjectFile::Unclassified);
QTC_CHECK(file.kind != ProjectFile::Unsupported);
if (ProjectFile::isSource(file.kind)) {
const CompilerOptionsBuilder::PchUsage pchUsage = CppTools::getPchUsage();
CompilerOptionsBuilder optionsBuilder(*projectPart, clangVersion,
clangResourceDirectory);
QStringList arguments = extraClangToolsPrependOptions();
arguments.append(optionsBuilder.build(file.kind, pchUsage));
arguments.append(extraClangToolsAppendOptions());
unitsToAnalyze << AnalyzeUnit(file.path, arguments);
}
}
const CompilerOptionsBuilder::PchUsage pchUsage = CppTools::getPchUsage();
for (const FileInfo &fileInfo : fileInfos) {
CompilerOptionsBuilder optionsBuilder(*fileInfo.projectPart,
clangVersion,
clangResourceDirectory);
QStringList arguments = extraClangToolsPrependOptions();
arguments.append(optionsBuilder.build(fileInfo.kind, pchUsage));
arguments.append(extraClangToolsAppendOptions());
unitsToAnalyze << AnalyzeUnit(fileInfo.file.toString(), arguments);
}
return unitsToAnalyze;
}
AnalyzeUnits ClangToolRunControl::sortedUnitsToAnalyze(const QString &clangVersion)
AnalyzeUnits ClangToolRunControl::unitsToAnalyze(const QString &clangVersion)
{
QTC_ASSERT(m_projectInfo.isValid(), return AnalyzeUnits());
const QString clangResourceDirectory = clangIncludeDirectory(m_clangExecutable, clangVersion);
AnalyzeUnits units = unitsToAnalyzeFromProjectParts(m_projectInfo.projectParts(), clangVersion,
clangResourceDirectory);
Utils::sort(units, &AnalyzeUnit::file);
return units;
return toAnalyzeUnits(m_fileInfos, clangVersion, clangResourceDirectory);
}
static QDebug operator<<(QDebug debug, const Utils::Environment &environment)
@@ -243,11 +226,14 @@ static QDebug operator<<(QDebug debug, const AnalyzeUnits &analyzeUnits)
return debug;
}
ClangToolRunControl::ClangToolRunControl(RunControl *runControl, Target *target)
ClangToolRunControl::ClangToolRunControl(RunControl *runControl,
Target *target,
const FileInfos &fileInfos)
: RunWorker(runControl)
, m_projectBuilder(new ProjectBuilder(runControl, target->project(), this))
, m_clangExecutable(CppTools::clangExecutable(CLANG_BINDIR))
, m_target(target)
, m_fileInfos(fileInfos)
{
addStartDependency(m_projectBuilder);
@@ -327,7 +313,7 @@ void ClangToolRunControl::start()
m_clangLogFileDir = temporaryDir.path();
// Collect files
const AnalyzeUnits unitsToProcess = sortedUnitsToAnalyze(CLANG_VERSION);
const AnalyzeUnits unitsToProcess = unitsToAnalyze(CLANG_VERSION);
qCDebug(LOG) << "Files to process:" << unitsToProcess;
m_unitsToProcess = unitsToProcess;
m_initialFilesToProcessSize = m_unitsToProcess.count();

View File

@@ -25,6 +25,8 @@
#pragma once
#include "clangfileinfo.h"
#include <projectexplorer/runconfiguration.h>
#include <cpptools/projectinfo.h>
#include <utils/environment.h>
@@ -55,7 +57,8 @@ class ClangToolRunControl : public ProjectExplorer::RunWorker
public:
ClangToolRunControl(ProjectExplorer::RunControl *runControl,
ProjectExplorer::Target *target);
ProjectExplorer::Target *target,
const FileInfos &fileInfos);
bool success() const { return m_success; } // For testing.
@@ -73,7 +76,7 @@ private:
void start() final;
void stop() final;
AnalyzeUnits sortedUnitsToAnalyze(const QString &clangVersion);
AnalyzeUnits unitsToAnalyze(const QString &clangVersion);
void analyzeNextFile();
void handleFinished();
@@ -91,6 +94,7 @@ protected:
private:
QPointer<ProjectExplorer::Target> m_target;
FileInfos m_fileInfos;
CppTools::ProjectInfo m_projectInfoBeforeBuild;
CppTools::ProjectInfo m_projectInfo;

View File

@@ -9,6 +9,7 @@ LIBS += $$LIBCLANG_LIBS
INCLUDEPATH += $$LLVM_INCLUDEPATH
SOURCES += \
clangselectablefilesdialog.cpp \
clangstaticanalyzerdiagnosticview.cpp \
clangstaticanalyzerprojectsettings.cpp \
clangstaticanalyzerprojectsettingsmanager.cpp \
@@ -31,6 +32,8 @@ SOURCES += \
clangtoolsconfigwidget.cpp
HEADERS += \
clangfileinfo.h \
clangselectablefilesdialog.h \
clangstaticanalyzerdiagnosticview.h \
clangstaticanalyzerprojectsettings.h \
clangstaticanalyzerprojectsettingsmanager.h \
@@ -57,6 +60,7 @@ HEADERS += \
FORMS += \
clangstaticanalyzerprojectsettingswidget.ui \
clangtoolsconfigwidget.ui
clangselectablefilesdialog.ui
equals(TEST, 1) {
HEADERS += \

View File

@@ -41,6 +41,10 @@ QtcPlugin {
}
files: [
"clangfileinfo.h",
"clangselectablefilesdialog.cpp",
"clangselectablefilesdialog.h",
"clangselectablefilesdialog.ui",
"clangstaticanalyzerdiagnosticview.cpp",
"clangstaticanalyzerdiagnosticview.h",
"clangstaticanalyzerprojectsettings.cpp",

View File

@@ -131,7 +131,7 @@ void ClangToolsUnitTests::testProject()
settings->setClangDiagnosticConfigId(clangTidyConfig.id());
}
tool->startTool();
tool->startTool(false);
QSignalSpy waiter(tool, SIGNAL(finished(bool)));
QVERIFY(waiter.wait(30000));

View File

@@ -47,12 +47,6 @@ const char HIDE_FILE_FILTER_DEFAULT[] = "Makefile*; *.o; *.lo; *.la; *.obj; *~;
" *.config; *.creator; *.user*; *.includes; *.autosave";
const char SHOW_FILE_FILTER_DEFAULT[] = "*.c; *.cc; *.cpp; *.cp; *.cxx; *.c++; *.h; *.hh; *.hpp; *.hxx;";
Tree::~Tree()
{
qDeleteAll(childDirectories);
qDeleteAll(files);
}
SelectableFilesModel::SelectableFilesModel(QObject *parent) : QAbstractItemModel(parent)
{
m_root = new Tree;

View File

@@ -47,7 +47,11 @@ namespace ProjectExplorer {
class Tree
{
public:
~Tree();
virtual ~Tree()
{
qDeleteAll(childDirectories);
qDeleteAll(files);
}
QString name;
Qt::CheckState checked = Qt::Unchecked;