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));