diff --git a/src/plugins/autotest/autotest.qrc b/src/plugins/autotest/autotest.qrc index f4f6892d47d..0c3a24d7ace 100644 --- a/src/plugins/autotest/autotest.qrc +++ b/src/plugins/autotest/autotest.qrc @@ -17,5 +17,7 @@ images/text@2x.png images/visual.png images/visual@2x.png + images/run_file.png + images/run_file@2x.png diff --git a/src/plugins/autotest/autotestconstants.h b/src/plugins/autotest/autotestconstants.h index 2de0fe43abc..1f92aba915e 100644 --- a/src/plugins/autotest/autotestconstants.h +++ b/src/plugins/autotest/autotestconstants.h @@ -33,6 +33,7 @@ namespace Constants { const char ACTION_SCAN_ID[] = "AutoTest.ScanAction"; const char ACTION_RUN_ALL_ID[] = "AutoTest.RunAll"; const char ACTION_RUN_SELECTED_ID[] = "AutoTest.RunSelected"; +const char ACTION_RUN_FILE_ID[] = "AutoTest.RunFile"; const char ACTION_RUN_UCURSOR[] = "AutoTest.RunUnderCursor"; const char ACTION_RUN_DBG_UCURSOR[] = "AutoTest.RunDebugUnderCursor"; const char MENU_ID[] = "AutoTest.Menu"; diff --git a/src/plugins/autotest/autotesticons.h b/src/plugins/autotest/autotesticons.h index 07a8f86875a..30f5a0d424d 100644 --- a/src/plugins/autotest/autotesticons.h +++ b/src/plugins/autotest/autotesticons.h @@ -37,6 +37,8 @@ const Utils::Icon SORT_NATURALLY({ 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 RESULT_PASS({ {":/utils/images/filledcircle.png", Utils::Theme::OutputPanes_TestPassTextColor}}, diff --git a/src/plugins/autotest/autotestplugin.cpp b/src/plugins/autotest/autotestplugin.cpp index d7bb68cdec6..e3b48316c7c 100644 --- a/src/plugins/autotest/autotestplugin.cpp +++ b/src/plugins/autotest/autotestplugin.cpp @@ -127,6 +127,18 @@ void AutotestPlugin::initializeMenuEntries() action->setEnabled(false); menu->addAction(command); + action = new QAction(tr("Run Tests for Current &File"), this); + Utils::Icon runFileIcon = Utils::Icons::RUN_SMALL_TOOLBAR; + for (const Utils::IconMaskAndColor &maskAndColor : Icons::RUN_FILE_OVERLAY) + runFileIcon.append(maskAndColor); + action->setIcon(runFileIcon.icon()); + action->setToolTip(tr("Run Tests for Current File")); + command = ActionManager::registerAction(action, Constants::ACTION_RUN_FILE_ID); + command->setDefaultKeySequence(QKeySequence(tr("Alt+Shift+T,Alt+F"))); + connect(action, &QAction::triggered, this, &AutotestPlugin::onRunFileTriggered); + action->setEnabled(false); + menu->addAction(command); + action = new QAction(tr("Re&scan Tests"), this); command = ActionManager::registerAction(action, Constants::ACTION_SCAN_ID); command->setDefaultKeySequence(QKeySequence(tr("Alt+Shift+T,Alt+S"))); @@ -219,6 +231,26 @@ void AutotestPlugin::onRunSelectedTriggered() runner->prepareToRunTests(TestRunMode::Run); } +void AutotestPlugin::onRunFileTriggered() +{ + const IDocument *document = EditorManager::currentDocument(); + if (!document) + return; + + const Utils::FileName &fileName = document->filePath(); + if (fileName.isEmpty()) + return; + + TestTreeModel *model = TestTreeModel::instance(); + const QList tests = model->getTestsForFile(fileName); + if (tests.isEmpty()) + return; + + TestRunner *runner = TestRunner::instance(); + runner->setSelectedTests(tests); + runner->prepareToRunTests(TestRunMode::Run); +} + void AutotestPlugin::onRunUnderCursorTriggered(TestRunMode mode) { QTextCursor cursor = Utils::Text::wordStartCursor( @@ -263,6 +295,7 @@ void AutotestPlugin::updateMenuItemsEnabledState() ActionManager::command(Constants::ACTION_RUN_ALL_ID)->action()->setEnabled(canRun); ActionManager::command(Constants::ACTION_RUN_SELECTED_ID)->action()->setEnabled(canRun); + ActionManager::command(Constants::ACTION_RUN_FILE_ID)->action()->setEnabled(canRun); ActionManager::command(Constants::ACTION_SCAN_ID)->action()->setEnabled(canScan); ActionContainer *contextMenu = ActionManager::actionContainer(CppEditor::Constants::M_CONTEXT); diff --git a/src/plugins/autotest/autotestplugin.h b/src/plugins/autotest/autotestplugin.h index cbd85937eb6..efd8d31e77f 100644 --- a/src/plugins/autotest/autotestplugin.h +++ b/src/plugins/autotest/autotestplugin.h @@ -60,6 +60,7 @@ private: void initializeMenuEntries(); void onRunAllTriggered(); void onRunSelectedTriggered(); + void onRunFileTriggered(); void onRunUnderCursorTriggered(TestRunMode mode); QList createTestObjects() const override; const QSharedPointer m_settings; diff --git a/src/plugins/autotest/gtest/gtesttreeitem.cpp b/src/plugins/autotest/gtest/gtesttreeitem.cpp index b24f57f6943..8f7c56dab97 100644 --- a/src/plugins/autotest/gtest/gtesttreeitem.cpp +++ b/src/plugins/autotest/gtest/gtesttreeitem.cpp @@ -268,6 +268,39 @@ QList GTestTreeItem::getSelectedTestConfigurations() const return getTestConfigurations(false); } +QList GTestTreeItem::getTestConfigurationsForFile(const Utils::FileName &fileName) const +{ + QList result; + ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject(); + if (!project || type() != Root) + return result; + + QHash testCases; + const QString &file = fileName.toString(); + forAllChildren([&testCases, &file](TestTreeItem *node) { + if (node->type() == Type::TestFunctionOrSet && node->filePath() == file) { + QTC_ASSERT(node->parentItem(), return); + const GTestTreeItem *testCase = static_cast(node->parentItem()); + QTC_ASSERT(testCase->type() == Type::TestCase, return); + TestCases &cases = testCases[testCase->proFile()]; + cases.filters.append( + gtestFilter(testCase->state()).arg(testCase->name(), node->name())); + cases.internalTargets.unite(node->internalTargets()); + } + }); + for (auto it = testCases.begin(), end = testCases.end(); it != end; ++it) { + for (const QString &target : qAsConst(it.value().internalTargets)) { + GTestConfiguration *tc = new GTestConfiguration; + tc->setTestCases(it.value().filters); + tc->setProjectFile(it.key()); + tc->setProject(project); + tc->setInternalTarget(target); + result << tc; + } + } + return result; +} + TestTreeItem *GTestTreeItem::find(const TestParseResult *result) { QTC_ASSERT(result, return nullptr); diff --git a/src/plugins/autotest/gtest/gtesttreeitem.h b/src/plugins/autotest/gtest/gtesttreeitem.h index c3ff8dba71f..22225ae7f5d 100644 --- a/src/plugins/autotest/gtest/gtesttreeitem.h +++ b/src/plugins/autotest/gtest/gtesttreeitem.h @@ -57,6 +57,7 @@ public: TestConfiguration *debugConfiguration() const override; QList getAllTestConfigurations() const override; QList getSelectedTestConfigurations() const override; + QList getTestConfigurationsForFile(const Utils::FileName &fileName) const override; TestTreeItem *find(const TestParseResult *result) override; TestTreeItem *findChild(const TestTreeItem *other) override; bool modify(const TestParseResult *result) override; diff --git a/src/plugins/autotest/images/run_file.png b/src/plugins/autotest/images/run_file.png new file mode 100644 index 00000000000..6a3bfc766f3 Binary files /dev/null and b/src/plugins/autotest/images/run_file.png differ diff --git a/src/plugins/autotest/images/run_file@2x.png b/src/plugins/autotest/images/run_file@2x.png new file mode 100644 index 00000000000..4b386818c99 Binary files /dev/null and b/src/plugins/autotest/images/run_file@2x.png differ diff --git a/src/plugins/autotest/qtest/qttesttreeitem.cpp b/src/plugins/autotest/qtest/qttesttreeitem.cpp index 46a2ca03e92..2f375a484e7 100644 --- a/src/plugins/autotest/qtest/qttesttreeitem.cpp +++ b/src/plugins/autotest/qtest/qttesttreeitem.cpp @@ -235,6 +235,35 @@ QList QtTestTreeItem::getSelectedTestConfigurations() const return result; } +QList QtTestTreeItem::getTestConfigurationsForFile(const Utils::FileName &fileName) const +{ + QList result; + + ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject(); + if (!project || type() != Root) + return result; + + QHash testFunctions; + const QString &file = fileName.toString(); + forAllChildren([&testFunctions, &file](TestTreeItem *node) { + if (node->type() == Type::TestFunctionOrSet && node->filePath() == file) { + QTC_ASSERT(node->parentItem(), return); + TestTreeItem *testCase = node->parentItem(); + QTC_ASSERT(testCase->type() == Type::TestCase, return); + testFunctions[testCase] << node->name(); + } + }); + + for (auto it = testFunctions.cbegin(), end = testFunctions.cend(); it != end; ++it) { + TestConfiguration *tc = it.key()->testConfiguration(); + QTC_ASSERT(tc, continue); + tc->setTestCases(it.value()); + result << tc; + } + + return result; +} + TestTreeItem *QtTestTreeItem::find(const TestParseResult *result) { QTC_ASSERT(result, return nullptr); diff --git a/src/plugins/autotest/qtest/qttesttreeitem.h b/src/plugins/autotest/qtest/qttesttreeitem.h index 9b70b735fad..2de8eb8f821 100644 --- a/src/plugins/autotest/qtest/qttesttreeitem.h +++ b/src/plugins/autotest/qtest/qttesttreeitem.h @@ -45,6 +45,7 @@ public: TestConfiguration *debugConfiguration() const override; QList getAllTestConfigurations() const override; QList getSelectedTestConfigurations() const override; + QList getTestConfigurationsForFile(const Utils::FileName &fileName) const override; TestTreeItem *find(const TestParseResult *result) override; TestTreeItem *findChild(const TestTreeItem *other) override; bool modify(const TestParseResult *result) override; diff --git a/src/plugins/autotest/quick/quicktesttreeitem.cpp b/src/plugins/autotest/quick/quicktesttreeitem.cpp index 6c0c4b4feb9..dc17be469b7 100644 --- a/src/plugins/autotest/quick/quicktesttreeitem.cpp +++ b/src/plugins/autotest/quick/quicktesttreeitem.cpp @@ -279,6 +279,36 @@ QList QuickTestTreeItem::getSelectedTestConfigurations() co return result; } +QList QuickTestTreeItem::getTestConfigurationsForFile(const Utils::FileName &fileName) const +{ + QList result; + ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject(); + if (!project || type() != Root) + return result; + + QHash testFunctions; + const QString &file = fileName.toString(); + forAllChildren([&testFunctions, &file](TestTreeItem *node) { + if (node->type() == Type::TestFunctionOrSet && node->filePath() == file) { + QTC_ASSERT(node->parentItem(), return); + TestTreeItem *testCase = node->parentItem(); + QTC_ASSERT(testCase->type() == Type::TestCase, return); + if (testCase->name().isEmpty()) + return; + testFunctions[testCase] << testCase->name() + "::" + node->name(); + } + }); + + for (auto it = testFunctions.cbegin(), end = testFunctions.cend(); it != end; ++it) { + TestConfiguration *tc = it.key()->testConfiguration(); + QTC_ASSERT(tc, continue); + tc->setTestCases(it.value()); + result << tc; + } + + return result; +} + TestTreeItem *QuickTestTreeItem::find(const TestParseResult *result) { QTC_ASSERT(result, return nullptr); diff --git a/src/plugins/autotest/quick/quicktesttreeitem.h b/src/plugins/autotest/quick/quicktesttreeitem.h index 48c2467de98..e00afc434b2 100644 --- a/src/plugins/autotest/quick/quicktesttreeitem.h +++ b/src/plugins/autotest/quick/quicktesttreeitem.h @@ -45,6 +45,7 @@ public: TestConfiguration *debugConfiguration() const override; QList getAllTestConfigurations() const override; QList getSelectedTestConfigurations() const override; + QList getTestConfigurationsForFile(const Utils::FileName &fileName) const override; TestTreeItem *find(const TestParseResult *result) override; TestTreeItem *findChild(const TestTreeItem *other) override; bool modify(const TestParseResult *result) override; diff --git a/src/plugins/autotest/testresultspane.cpp b/src/plugins/autotest/testresultspane.cpp index d2b3ec97dd1..3047e6d7107 100644 --- a/src/plugins/autotest/testresultspane.cpp +++ b/src/plugins/autotest/testresultspane.cpp @@ -178,6 +178,9 @@ void TestResultsPane::createToolButtons() m_runSelected = new QToolButton(m_treeView); m_runSelected->setDefaultAction(Core::ActionManager::command(Constants::ACTION_RUN_SELECTED_ID)->action()); + m_runFile = new QToolButton(m_treeView); + m_runFile->setDefaultAction(Core::ActionManager::command(Constants::ACTION_RUN_FILE_ID)->action()); + m_stopTestRun = new QToolButton(m_treeView); m_stopTestRun->setIcon(Utils::Icons::STOP_SMALL_TOOLBAR.icon()); m_stopTestRun->setToolTip(tr("Stop Test Run")); @@ -248,8 +251,8 @@ QWidget *TestResultsPane::outputWidget(QWidget *parent) QList TestResultsPane::toolBarWidgets() const { - return {m_expandCollapse, m_runAll, m_runSelected, m_stopTestRun, m_outputToggleButton, - m_filterButton}; + return {m_expandCollapse, m_runAll, m_runSelected, m_runFile, m_stopTestRun, + m_outputToggleButton, m_filterButton}; } QString TestResultsPane::displayName() const diff --git a/src/plugins/autotest/testresultspane.h b/src/plugins/autotest/testresultspane.h index 7156cd1c859..285b5baf0f4 100644 --- a/src/plugins/autotest/testresultspane.h +++ b/src/plugins/autotest/testresultspane.h @@ -132,6 +132,7 @@ private: QToolButton *m_expandCollapse; QToolButton *m_runAll; QToolButton *m_runSelected; + QToolButton *m_runFile; QToolButton *m_stopTestRun; QToolButton *m_filterButton; QToolButton *m_outputToggleButton; diff --git a/src/plugins/autotest/testtreeitem.cpp b/src/plugins/autotest/testtreeitem.cpp index 3d07c8076d4..c136ed30ab2 100644 --- a/src/plugins/autotest/testtreeitem.cpp +++ b/src/plugins/autotest/testtreeitem.cpp @@ -259,6 +259,11 @@ QList TestTreeItem::getSelectedTestConfigurations() const return QList(); } +QList TestTreeItem::getTestConfigurationsForFile(const Utils::FileName &) const +{ + return QList(); +} + bool TestTreeItem::lessThan(const TestTreeItem *other, SortMode mode) const { const QString &lhs = data(0, Qt::DisplayRole).toString(); diff --git a/src/plugins/autotest/testtreeitem.h b/src/plugins/autotest/testtreeitem.h index 0180c88fefe..dbb82f486a3 100644 --- a/src/plugins/autotest/testtreeitem.h +++ b/src/plugins/autotest/testtreeitem.h @@ -42,6 +42,7 @@ namespace { } namespace CppTools { class CppModelManager; } +namespace Utils { class FileName; } namespace Autotest { namespace Internal { @@ -113,6 +114,7 @@ public: TestConfiguration *asConfiguration(TestRunMode mode) const; virtual QList getAllTestConfigurations() const; virtual QList getSelectedTestConfigurations() const; + virtual QList getTestConfigurationsForFile(const Utils::FileName &fileName) const; virtual bool lessThan(const TestTreeItem *other, SortMode mode) const; virtual TestTreeItem *find(const TestParseResult *result) = 0; virtual TestTreeItem *findChild(const TestTreeItem *other) = 0; diff --git a/src/plugins/autotest/testtreemodel.cpp b/src/plugins/autotest/testtreemodel.cpp index ef7a30c4c91..48e32240328 100644 --- a/src/plugins/autotest/testtreemodel.cpp +++ b/src/plugins/autotest/testtreemodel.cpp @@ -158,6 +158,14 @@ QList TestTreeModel::getSelectedTests() const return result; } +QList TestTreeModel::getTestsForFile(const Utils::FileName &fileName) const +{ + QList result; + for (Utils::TreeItem *frameworkRoot : *rootItem()) + result.append(static_cast(frameworkRoot)->getTestConfigurationsForFile(fileName)); + return result; +} + QList TestTreeModel::testItemsByName(TestTreeItem *root, const QString &testName) { QList result; diff --git a/src/plugins/autotest/testtreemodel.h b/src/plugins/autotest/testtreemodel.h index b9f4d5ea13d..78974e67bdd 100644 --- a/src/plugins/autotest/testtreemodel.h +++ b/src/plugins/autotest/testtreemodel.h @@ -54,6 +54,7 @@ public: bool hasTests() const; QList getAllTestCases() const; QList getSelectedTests() const; + QList getTestsForFile(const Utils::FileName &fileName) const; QList testItemsByName(const QString &testName); void syncTestFrameworks(); void rebuild(const QList &frameworkIds);