From 04f9c41432bfa580103a9b6badd1a81a2bbec983 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Fri, 23 Aug 2019 15:25:57 +0200 Subject: [PATCH] ClangTools: Add action for running on current file Ideally, we would build the particular file before running the analyzer, but not every project manager supports that. For now, skip building the project for this action. Change-Id: Ibc516c41dd0dbeb7b17b44c0ac35ae4b46ae801d Reviewed-by: Cristian Adam Reviewed-by: Nikolai Kosjar --- .../utils}/images/run_file.png | Bin .../utils}/images/run_file@2x.png | Bin .../utils}/images/runselected_boxes.png | Bin .../utils}/images/runselected_boxes@2x.png | Bin .../utils}/images/runselected_tickmarks.png | Bin .../images/runselected_tickmarks@2x.png | Bin src/libs/utils/utils.qrc | 6 +++ src/plugins/autotest/autotest.qrc | 6 --- src/plugins/autotest/autotesticons.h | 10 ++-- .../clangtools/clangtidyclazyruncontrol.cpp | 10 ++-- .../clangtools/clangtidyclazyruncontrol.h | 3 +- src/plugins/clangtools/clangtidyclazytool.cpp | 36 ++++++++++--- src/plugins/clangtools/clangtidyclazytool.h | 2 +- src/plugins/clangtools/clangtool.cpp | 48 ++++++++++++++++-- src/plugins/clangtools/clangtool.h | 13 ++++- .../clangtools/clangtoolruncontrol.cpp | 11 ++-- src/plugins/clangtools/clangtoolruncontrol.h | 5 +- src/plugins/clangtools/clangtoolsconstants.h | 3 ++ src/plugins/clangtools/clangtoolsplugin.cpp | 8 ++- .../clangtoolspreconfiguredsessiontests.cpp | 2 +- .../clangtools/clangtoolsunittests.cpp | 2 +- 21 files changed, 124 insertions(+), 41 deletions(-) rename src/{plugins/autotest => libs/utils}/images/run_file.png (100%) rename src/{plugins/autotest => libs/utils}/images/run_file@2x.png (100%) rename src/{plugins/autotest => libs/utils}/images/runselected_boxes.png (100%) rename src/{plugins/autotest => libs/utils}/images/runselected_boxes@2x.png (100%) rename src/{plugins/autotest => libs/utils}/images/runselected_tickmarks.png (100%) rename src/{plugins/autotest => libs/utils}/images/runselected_tickmarks@2x.png (100%) diff --git a/src/plugins/autotest/images/run_file.png b/src/libs/utils/images/run_file.png similarity index 100% rename from src/plugins/autotest/images/run_file.png rename to src/libs/utils/images/run_file.png diff --git a/src/plugins/autotest/images/run_file@2x.png b/src/libs/utils/images/run_file@2x.png similarity index 100% rename from src/plugins/autotest/images/run_file@2x.png rename to src/libs/utils/images/run_file@2x.png diff --git a/src/plugins/autotest/images/runselected_boxes.png b/src/libs/utils/images/runselected_boxes.png similarity index 100% rename from src/plugins/autotest/images/runselected_boxes.png rename to src/libs/utils/images/runselected_boxes.png diff --git a/src/plugins/autotest/images/runselected_boxes@2x.png b/src/libs/utils/images/runselected_boxes@2x.png similarity index 100% rename from src/plugins/autotest/images/runselected_boxes@2x.png rename to src/libs/utils/images/runselected_boxes@2x.png diff --git a/src/plugins/autotest/images/runselected_tickmarks.png b/src/libs/utils/images/runselected_tickmarks.png similarity index 100% rename from src/plugins/autotest/images/runselected_tickmarks.png rename to src/libs/utils/images/runselected_tickmarks.png diff --git a/src/plugins/autotest/images/runselected_tickmarks@2x.png b/src/libs/utils/images/runselected_tickmarks@2x.png similarity index 100% rename from src/plugins/autotest/images/runselected_tickmarks@2x.png rename to src/libs/utils/images/runselected_tickmarks@2x.png diff --git a/src/libs/utils/utils.qrc b/src/libs/utils/utils.qrc index 1a1edbef5af..180c5e5b43b 100644 --- a/src/libs/utils/utils.qrc +++ b/src/libs/utils/utils.qrc @@ -142,8 +142,14 @@ images/Desktop.png images/interrupt_small.png images/interrupt_small@2x.png + images/run_file.png + images/run_file@2x.png images/run_small.png images/run_small@2x.png + images/runselected_boxes.png + images/runselected_boxes@2x.png + images/runselected_tickmarks.png + images/runselected_tickmarks@2x.png images/stop_small.png images/stop_small@2x.png images/boundingrect.png diff --git a/src/plugins/autotest/autotest.qrc b/src/plugins/autotest/autotest.qrc index 51d19022da5..c7b86214e75 100644 --- a/src/plugins/autotest/autotest.qrc +++ b/src/plugins/autotest/autotest.qrc @@ -6,18 +6,12 @@ images/leafsort@2x.png images/benchmark.png images/benchmark@2x.png - images/runselected_boxes.png - images/runselected_boxes@2x.png - images/runselected_tickmarks.png - images/runselected_tickmarks@2x.png images/data.png images/data@2x.png images/text.png images/text@2x.png images/visual.png images/visual@2x.png - images/run_file.png - images/run_file@2x.png images/suite.png images/suite@2x.png diff --git a/src/plugins/autotest/autotesticons.h b/src/plugins/autotest/autotesticons.h index c8bfb63bbf8..7b6714d8616 100644 --- a/src/plugins/autotest/autotesticons.h +++ b/src/plugins/autotest/autotesticons.h @@ -32,12 +32,12 @@ namespace Icons { const Utils::Icon SORT_NATURALLY({ {":/autotest/images/leafsort.png", Utils::Theme::IconsBaseColor}}); -const Utils::Icon RUN_SELECTED_OVERLAY({ - {":/autotest/images/runselected_boxes.png", Utils::Theme::BackgroundColorDark}, - {":/autotest/images/runselected_tickmarks.png", Utils::Theme::IconsBaseColor}}); -const Utils::Icon RUN_FILE_OVERLAY({ - {":/autotest/images/run_file.png", Utils::Theme::IconsBaseColor}}); +const Utils::Icon RUN_SELECTED_OVERLAY({ + {":/utils/images/runselected_boxes.png", Utils::Theme::BackgroundColorDark}, + {":/utils/images/runselected_tickmarks.png", Utils::Theme::IconsBaseColor}}); +const Utils::Icon RUN_FILE_OVERLAY({ + {":/utils/images/run_file.png", Utils::Theme::IconsBaseColor}}); const Utils::Icon RESULT_PASS({ {":/utils/images/filledcircle.png", Utils::Theme::OutputPanes_TestPassTextColor}}, Utils::Icon::Tint); diff --git a/src/plugins/clangtools/clangtidyclazyruncontrol.cpp b/src/plugins/clangtools/clangtidyclazyruncontrol.cpp index 6064686951c..ad6b5d9ca15 100644 --- a/src/plugins/clangtools/clangtidyclazyruncontrol.cpp +++ b/src/plugins/clangtools/clangtidyclazyruncontrol.cpp @@ -33,10 +33,12 @@ using namespace ProjectExplorer; namespace ClangTools { namespace Internal { -ClangTidyClazyRunWorker::ClangTidyClazyRunWorker(RunControl *runControl, - const CppTools::ClangDiagnosticConfig &diagnosticConfig, - const FileInfos &fileInfos) - : ClangToolRunWorker(runControl, fileInfos) +ClangTidyClazyRunWorker::ClangTidyClazyRunWorker( + RunControl *runControl, + const CppTools::ClangDiagnosticConfig &diagnosticConfig, + const FileInfos &fileInfos, + bool preventBuild) + : ClangToolRunWorker(runControl, fileInfos, preventBuild) , m_diagnosticConfig(diagnosticConfig) { setId("ClangTidyClazyRunner"); diff --git a/src/plugins/clangtools/clangtidyclazyruncontrol.h b/src/plugins/clangtools/clangtidyclazyruncontrol.h index 75b265dc531..5897127a9d1 100644 --- a/src/plugins/clangtools/clangtidyclazyruncontrol.h +++ b/src/plugins/clangtools/clangtidyclazyruncontrol.h @@ -39,7 +39,8 @@ class ClangTidyClazyRunWorker final : public ClangToolRunWorker public: ClangTidyClazyRunWorker(ProjectExplorer::RunControl *runControl, const CppTools::ClangDiagnosticConfig &diagnosticConfig, - const FileInfos &fileInfos); + const FileInfos &fileInfos, + bool preventBuild); protected: QList runnerCreators() final; diff --git a/src/plugins/clangtools/clangtidyclazytool.cpp b/src/plugins/clangtools/clangtidyclazytool.cpp index 3ca68b55051..d87f54b2466 100644 --- a/src/plugins/clangtools/clangtidyclazytool.cpp +++ b/src/plugins/clangtools/clangtidyclazytool.cpp @@ -327,13 +327,20 @@ ClangTidyClazyTool::ClangTidyClazyTool() action->setToolTip(toolTip); menu->addAction(ActionManager::registerAction(action, "ClangTidyClazy.Action"), Debugger::Constants::G_ANALYZER_TOOLS); - QObject::connect(action, &QAction::triggered, this, [this]() { startTool(true); }); + QObject::connect(action, &QAction::triggered, this, [this]() { + startTool(ClangTidyClazyTool::FileSelection::AskUser); + }); QObject::connect(m_startAction, &QAction::triggered, action, &QAction::triggered); QObject::connect(m_startAction, &QAction::changed, action, [action, this] { action->setEnabled(m_startAction->isEnabled()); }); + QObject::connect(m_startOnCurrentFileAction, &QAction::triggered, this, [this] { + startTool(ClangTidyClazyTool::FileSelection::CurrentFile); + }); + m_perspective.addToolBarAction(m_startAction); + m_perspective.addToolBarAction(m_startOnCurrentFileAction); m_perspective.addToolBarAction(m_stopAction); m_perspective.addToolBarAction(m_loadExported); m_perspective.addToolBarAction(m_clear); @@ -373,7 +380,7 @@ static ClangDiagnosticConfig getDiagnosticConfig(Project *project) return configsModel.configWithId(diagnosticConfigId); } -void ClangTidyClazyTool::startTool(bool askUserForFileSelection) +void ClangTidyClazyTool::startTool(FileSelection fileSelection) { Project *project = SessionManager::startupProject(); QTC_ASSERT(project, return); @@ -384,13 +391,15 @@ void ClangTidyClazyTool::startTool(bool askUserForFileSelection) runControl->setIcon(ProjectExplorer::Icons::ANALYZER_START_SMALL_TOOLBAR); runControl->setTarget(project->activeTarget()); - const FileInfos fileInfos = collectFileInfos(project, askUserForFileSelection); + const FileInfos fileInfos = collectFileInfos(project, fileSelection); if (fileInfos.empty()) return; + const bool preventBuild = fileSelection == FileSelection::CurrentFile; auto clangTool = new ClangTidyClazyRunWorker(runControl, getDiagnosticConfig(project), - fileInfos); + fileInfos, + preventBuild); m_stopAction->disconnect(); connect(m_stopAction, &QAction::triggered, runControl, [runControl] { @@ -424,24 +433,35 @@ void ClangTidyClazyTool::startTool(bool askUserForFileSelection) void ClangTidyClazyTool::updateRunActions() { if (m_toolBusy) { - m_startAction->setEnabled(false); QString tooltipText = tr("Clang-Tidy and Clazy are still running."); + + m_startAction->setEnabled(false); m_startAction->setToolTip(tooltipText); + + m_startOnCurrentFileAction->setEnabled(false); + m_startOnCurrentFileAction->setToolTip(tooltipText); + m_stopAction->setEnabled(true); m_loadExported->setEnabled(false); m_clear->setEnabled(false); } else { - QString toolTip = tr("Start Clang-Tidy and Clazy."); + QString toolTipStart = m_startAction->text(); + QString toolTipStartOnCurrentFile = m_startOnCurrentFileAction->text(); + Project *project = SessionManager::startupProject(); Target *target = project ? project->activeTarget() : nullptr; const Core::Id cxx = ProjectExplorer::Constants::CXX_LANGUAGE_ID; bool canRun = target && project->projectLanguages().contains(cxx) && ToolChainKitAspect::toolChain(target->kit(), cxx); if (!canRun) - toolTip = tr("This is not a C++ project."); + toolTipStart = toolTipStartOnCurrentFile = tr("This is not a C/C++ project."); - m_startAction->setToolTip(toolTip); m_startAction->setEnabled(canRun); + m_startAction->setToolTip(toolTipStart); + + m_startOnCurrentFileAction->setEnabled(canRun); + m_startOnCurrentFileAction->setToolTip(toolTipStartOnCurrentFile); + m_stopAction->setEnabled(false); m_loadExported->setEnabled(true); m_clear->setEnabled(m_diagnosticModel->diagnostics().count()); diff --git a/src/plugins/clangtools/clangtidyclazytool.h b/src/plugins/clangtools/clangtidyclazytool.h index 21472da5ebd..be964381174 100644 --- a/src/plugins/clangtools/clangtidyclazytool.h +++ b/src/plugins/clangtools/clangtidyclazytool.h @@ -51,7 +51,7 @@ public: static ClangTidyClazyTool *instance(); - void startTool(bool askUserForFileSelection) final; + void startTool(FileSelection fileSelection) final; Diagnostics read(OutputFileFormat outputFileFormat, const QString &logFilePath, diff --git a/src/plugins/clangtools/clangtool.cpp b/src/plugins/clangtools/clangtool.cpp index 570420cf5c6..a2ffb83c7b0 100644 --- a/src/plugins/clangtools/clangtool.cpp +++ b/src/plugins/clangtools/clangtool.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -97,7 +98,27 @@ ClangTool::ClangTool(const QString &name) { m_diagnosticModel = new ClangToolsDiagnosticModel(this); - m_startAction = Debugger::createStartAction(); + const Utils::Icon RUN_FILE_OVERLAY( + {{":/utils/images/run_file.png", Utils::Theme::IconsBaseColor}}); + + const Utils::Icon RUN_SELECTED_OVERLAY( + {{":/utils/images/runselected_boxes.png", Utils::Theme::BackgroundColorDark}, + {":/utils/images/runselected_tickmarks.png", Utils::Theme::IconsBaseColor}}); + + auto action = new QAction(tr("Analyze Project..."), this); + Utils::Icon runSelectedIcon = Utils::Icons::RUN_SMALL_TOOLBAR; + for (const Utils::IconMaskAndColor &maskAndColor : RUN_SELECTED_OVERLAY) + runSelectedIcon.append(maskAndColor); + action->setIcon(runSelectedIcon.icon()); + m_startAction = action; + + action = new QAction(tr("Analyze Current File"), this); + Utils::Icon runFileIcon = Utils::Icons::RUN_SMALL_TOOLBAR; + for (const Utils::IconMaskAndColor &maskAndColor : RUN_FILE_OVERLAY) + runFileIcon.append(maskAndColor); + action->setIcon(runFileIcon.icon()); + m_startOnCurrentFileAction = action; + m_stopAction = Debugger::createStopAction(); } @@ -106,21 +127,38 @@ ClangTool::~ClangTool() delete m_diagnosticView; } -FileInfos ClangTool::collectFileInfos(Project *project, bool askUserForFileSelection) const +FileInfos ClangTool::collectFileInfos(Project *project, FileSelection fileSelection) const { auto projectInfo = CppTools::CppModelManager::instance()->projectInfo(project); QTC_ASSERT(projectInfo.isValid(), return FileInfos()); const FileInfos allFileInfos = sortedFileInfos(projectInfo.projectParts()); - if (askUserForFileSelection) { + if (fileSelection == FileSelection::AllFiles) + return allFileInfos; + + if (fileSelection == FileSelection::AskUser) { SelectableFilesDialog dialog(projectInfo, allFileInfos); if (dialog.exec() == QDialog::Rejected) return FileInfos(); return dialog.filteredFileInfos(); - } else { - return allFileInfos; } + + if (fileSelection == FileSelection::CurrentFile) { + if (const IDocument *document = EditorManager::currentDocument()) { + const Utils::FilePath filePath = document->filePath(); + if (!filePath.isEmpty()) { + const FileInfo fileInfo = Utils::findOrDefault(allFileInfos, + [&](const FileInfo &fi) { + return fi.file == filePath; + }); + if (!fileInfo.file.isEmpty()) + return {fileInfo}; + } + } + } + + return {}; } const QString &ClangTool::name() const diff --git a/src/plugins/clangtools/clangtool.h b/src/plugins/clangtools/clangtool.h index 39e1bbb4645..c0b1565260f 100644 --- a/src/plugins/clangtools/clangtool.h +++ b/src/plugins/clangtools/clangtool.h @@ -49,7 +49,12 @@ public: ClangTool(const QString &name); ~ClangTool() override; - virtual void startTool(bool askUserForFileSelection) = 0; + enum class FileSelection { + AllFiles, + CurrentFile, + AskUser, + }; + virtual void startTool(FileSelection fileSelection) = 0; virtual Diagnostics read(OutputFileFormat outputFileFormat, const QString &logFilePath, @@ -58,7 +63,7 @@ public: QString *errorMessage) const = 0; FileInfos collectFileInfos(ProjectExplorer::Project *project, - bool askUserForFileSelection) const; + FileSelection fileSelection) const; // For testing. QSet diagnostics() const; @@ -67,6 +72,9 @@ public: virtual void onNewDiagnosticsAvailable(const Diagnostics &diagnostics); + QAction *startAction() const { return m_startAction; } + QAction *startOnCurrentFileAction() const { return m_startOnCurrentFileAction; } + signals: void finished(bool success); // For testing. @@ -80,6 +88,7 @@ protected: QPointer m_diagnosticView; QAction *m_startAction = nullptr; + QAction *m_startOnCurrentFileAction = nullptr; QAction *m_stopAction = nullptr; bool m_running = false; bool m_toolBusy = false; diff --git a/src/plugins/clangtools/clangtoolruncontrol.cpp b/src/plugins/clangtools/clangtoolruncontrol.cpp index eed06d58417..30c3edf68e2 100644 --- a/src/plugins/clangtools/clangtoolruncontrol.cpp +++ b/src/plugins/clangtools/clangtoolruncontrol.cpp @@ -229,12 +229,16 @@ static QDebug operator<<(QDebug debug, const AnalyzeUnits &analyzeUnits) } ClangToolRunWorker::ClangToolRunWorker(RunControl *runControl, - const FileInfos &fileInfos) + const FileInfos &fileInfos, + bool preventBuild) : RunWorker(runControl) - , m_projectBuilder(new ProjectBuilder(runControl, this)) , m_temporaryDir("clangtools-XXXXXX") , m_fileInfos(fileInfos) { + if (preventBuild) + return; + + m_projectBuilder = new ProjectBuilder(runControl, this); addStartDependency(m_projectBuilder); ClangToolsProjectSettings *projectSettings = ClangToolsProjectSettingsManager::getSettings( @@ -267,8 +271,7 @@ void ClangToolRunWorker::start() TaskHub::clearTasks(Debugger::Constants::ANALYZERTASK_ID); if (ClangToolsSettings::instance()->savedBuildBeforeAnalysis()) { - QTC_ASSERT(m_projectBuilder, return;); - if (!m_projectBuilder->success()) { + if (m_projectBuilder && !m_projectBuilder->success()) { reportFailure(); return; } diff --git a/src/plugins/clangtools/clangtoolruncontrol.h b/src/plugins/clangtools/clangtoolruncontrol.h index 28734cdb024..16a07b2d850 100644 --- a/src/plugins/clangtools/clangtoolruncontrol.h +++ b/src/plugins/clangtools/clangtoolruncontrol.h @@ -66,7 +66,8 @@ class ClangToolRunWorker : public ProjectExplorer::RunWorker public: ClangToolRunWorker(ProjectExplorer::RunControl *runControl, - const FileInfos &fileInfos); + const FileInfos &fileInfos, + bool preventBuild); bool success() const { return m_success; } // For testing. @@ -95,7 +96,7 @@ private: void finalize(); protected: - ProjectBuilder *m_projectBuilder; + ProjectBuilder *m_projectBuilder = nullptr; Utils::Environment m_environment; Utils::TemporaryDirectory m_temporaryDir; diff --git a/src/plugins/clangtools/clangtoolsconstants.h b/src/plugins/clangtools/clangtoolsconstants.h index 0b711162c9a..f19ffc068a8 100644 --- a/src/plugins/clangtools/clangtoolsconstants.h +++ b/src/plugins/clangtools/clangtoolsconstants.h @@ -28,6 +28,9 @@ namespace ClangTools { namespace Constants { +const char RUN_ON_PROJECT[] = "ClangTools.RunOnProject"; +const char RUN_ON_CURRENT_FILE[] = "ClangTools.RunOnCurrentFile"; + const char SETTINGS_PAGE_ID[] = "Analyzer.ClangTools.Settings"; const char SETTINGS_ID[] = "ClangTools"; const char CLANGTIDYCLAZY_RUN_MODE[] = "ClangTidyClazy.RunMode"; diff --git a/src/plugins/clangtools/clangtoolsplugin.cpp b/src/plugins/clangtools/clangtoolsplugin.cpp index c99c0d2ccd0..fed9cb21506 100644 --- a/src/plugins/clangtools/clangtoolsplugin.cpp +++ b/src/plugins/clangtools/clangtoolsplugin.cpp @@ -61,12 +61,13 @@ #include #include +using namespace Core; using namespace ProjectExplorer; namespace ClangTools { namespace Internal { -class ClangToolsOptionsPage : public Core::IOptionsPage +class ClangToolsOptionsPage : public IOptionsPage { public: ClangToolsOptionsPage() @@ -121,6 +122,11 @@ bool ClangToolsPlugin::initialize(const QStringList &arguments, QString *errorSt d = new ClangToolsPluginPrivate; + ActionManager::registerAction(d->clangTidyClazyTool.startAction(), + Constants::RUN_ON_PROJECT); + ActionManager::registerAction(d->clangTidyClazyTool.startOnCurrentFileAction(), + Constants::RUN_ON_CURRENT_FILE); + auto panelFactory = new ProjectPanelFactory(); panelFactory->setPriority(100); panelFactory->setDisplayName(tr("Clang Tools")); diff --git a/src/plugins/clangtools/clangtoolspreconfiguredsessiontests.cpp b/src/plugins/clangtools/clangtoolspreconfiguredsessiontests.cpp index d4b4e032726..5d711a8aef2 100644 --- a/src/plugins/clangtools/clangtoolspreconfiguredsessiontests.cpp +++ b/src/plugins/clangtools/clangtoolspreconfiguredsessiontests.cpp @@ -121,7 +121,7 @@ void PreconfiguredSessionTests::testPreconfiguredSession() QVERIFY(switchToProjectAndTarget(project, target)); - ClangTidyClazyTool::instance()->startTool(false); + ClangTidyClazyTool::instance()->startTool(ClangTidyClazyTool::FileSelection::AllFiles); QSignalSpy waitUntilAnalyzerFinished(ClangTidyClazyTool::instance(), SIGNAL(finished(bool))); QVERIFY(waitUntilAnalyzerFinished.wait(30000)); const QList arguments = waitUntilAnalyzerFinished.takeFirst(); diff --git a/src/plugins/clangtools/clangtoolsunittests.cpp b/src/plugins/clangtools/clangtoolsunittests.cpp index a4d300c8441..b8546c58bdd 100644 --- a/src/plugins/clangtools/clangtoolsunittests.cpp +++ b/src/plugins/clangtools/clangtoolsunittests.cpp @@ -131,7 +131,7 @@ void ClangToolsUnitTests::testProject() clangToolsSettings->setDiagnosticConfigId(diagnosticConfig.id()); clangToolsSettings->writeSettings(); - tool->startTool(false); + tool->startTool(ClangTidyClazyTool::FileSelection::AllFiles); QSignalSpy waiter(tool, SIGNAL(finished(bool))); QVERIFY(waiter.wait(30000));