diff --git a/src/libs/utils/tasktree.h b/src/libs/utils/tasktree.h index 8e9c0a6c17b..0c1b5e7a33d 100644 --- a/src/libs/utils/tasktree.h +++ b/src/libs/utils/tasktree.h @@ -306,11 +306,28 @@ public: // Synchronous invocation. Similarly to Group - isn't counted as a task inside taskCount() class QTCREATOR_UTILS_EXPORT Sync : public Group { + public: - using SynchronousMethod = std::function; - Sync(const SynchronousMethod &sync) - : Group({OnGroupSetup([sync] { return sync() ? TaskAction::StopWithDone - : TaskAction::StopWithError; })}) {} + template + Sync(Function &&function) : Group(init(std::forward(function))) {} + +private: + template + static QList init(Function &&function) { + constexpr bool isInvocable = std::is_invocable_v>; + static_assert(isInvocable, + "Sync element: The synchronous function can't take any arguments."); + constexpr bool isBool = std::is_same_v>>; + constexpr bool isVoid = std::is_same_v>>; + static_assert(isBool || isVoid, + "Sync element: The synchronous function has to return void or bool."); + if constexpr (isBool) { + return {OnGroupSetup([function] { return function() ? TaskAction::StopWithDone + : TaskAction::StopWithError; })}; + } + return {OnGroupSetup([function] { function(); return TaskAction::StopWithDone; })}; + }; + }; QTCREATOR_UTILS_EXPORT extern ParallelLimit sequential; diff --git a/tests/auto/utils/tasktree/tst_tasktree.cpp b/tests/auto/utils/tasktree/tst_tasktree.cpp index a360752fa36..c0bb7839ec3 100644 --- a/tests/auto/utils/tasktree/tst_tasktree.cpp +++ b/tests/auto/utils/tasktree/tst_tasktree.cpp @@ -122,6 +122,32 @@ void tst_TaskTree::validConstructs() OnGroupDone([] {}), OnGroupError([] {}) }; + + // When turning each of below blocks on, you should see the specific compiler error message. + +#if 0 + { + // "Sync element: The synchronous function has to return void or bool." + const auto setupSync = [] { return 3; }; + const Sync sync(setupSync); + } +#endif + +#if 0 + { + // "Sync element: The synchronous function can't take any arguments." + const auto setupSync = [](int) { }; + const Sync sync(setupSync); + } +#endif + +#if 0 + { + // "Sync element: The synchronous function can't take any arguments." + const auto setupSync = [](int) { return true; }; + const Sync sync(setupSync); + } +#endif } void tst_TaskTree::processTree_data() @@ -174,7 +200,10 @@ void tst_TaskTree::processTree_data() const auto groupError = [storage](int groupId) { return [=] { storage->m_log.append({groupId, Handler::GroupError}); }; }; - const auto setupSync = [storage](int syncId, bool success) { + const auto setupSync = [storage](int syncId) { + return [=] { storage->m_log.append({syncId, Handler::Sync}); }; + }; + const auto setupSyncWithReturn = [storage](int syncId, bool success) { return [=] { storage->m_log.append({syncId, Handler::Sync}); return success; }; }; @@ -997,11 +1026,11 @@ void tst_TaskTree::processTree_data() { const Group root { Storage(storage), - Sync(setupSync(1, true)), - Sync(setupSync(2, true)), - Sync(setupSync(3, true)), - Sync(setupSync(4, true)), - Sync(setupSync(5, true)) + Sync(setupSync(1)), + Sync(setupSync(2)), + Sync(setupSync(3)), + Sync(setupSync(4)), + Sync(setupSync(5)) }; const Log log { {1, Handler::Sync}, @@ -1014,15 +1043,35 @@ void tst_TaskTree::processTree_data() << TestData{storage, root, log, 0, OnStart::NotRunning, OnDone::Success}; } + { + const Group root { + Storage(storage), + Sync(setupSyncWithReturn(1, true)), + Sync(setupSyncWithReturn(2, true)), + Sync(setupSyncWithReturn(3, true)), + Sync(setupSyncWithReturn(4, true)), + Sync(setupSyncWithReturn(5, true)) + }; + const Log log { + {1, Handler::Sync}, + {2, Handler::Sync}, + {3, Handler::Sync}, + {4, Handler::Sync}, + {5, Handler::Sync} + }; + QTest::newRow("SyncWithReturn") + << TestData{storage, root, log, 0, OnStart::NotRunning, OnDone::Success}; + } + { const Group root { Storage(storage), parallel, - Sync(setupSync(1, true)), - Sync(setupSync(2, true)), - Sync(setupSync(3, true)), - Sync(setupSync(4, true)), - Sync(setupSync(5, true)) + Sync(setupSync(1)), + Sync(setupSync(2)), + Sync(setupSync(3)), + Sync(setupSync(4)), + Sync(setupSync(5)) }; const Log log { {1, Handler::Sync}, @@ -1039,11 +1088,11 @@ void tst_TaskTree::processTree_data() const Group root { Storage(storage), parallel, - Sync(setupSync(1, true)), - Sync(setupSync(2, true)), - Sync(setupSync(3, false)), - Sync(setupSync(4, true)), - Sync(setupSync(5, true)) + Sync(setupSync(1)), + Sync(setupSync(2)), + Sync(setupSyncWithReturn(3, false)), + Sync(setupSync(4)), + Sync(setupSync(5)) }; const Log log { {1, Handler::Sync}, @@ -1057,11 +1106,11 @@ void tst_TaskTree::processTree_data() { const Group root { Storage(storage), - Sync(setupSync(1, true)), + Sync(setupSync(1)), Process(setupProcess(2)), - Sync(setupSync(3, true)), + Sync(setupSync(3)), Process(setupProcess(4)), - Sync(setupSync(5, true)), + Sync(setupSync(5)), OnGroupDone(groupDone(0)) }; const Log log { @@ -1076,6 +1125,26 @@ void tst_TaskTree::processTree_data() << TestData{storage, root, log, 2, OnStart::Running, OnDone::Success}; } + { + const Group root { + Storage(storage), + Sync(setupSync(1)), + Process(setupProcess(2)), + Sync(setupSyncWithReturn(3, false)), + Process(setupProcess(4)), + Sync(setupSync(5)), + OnGroupError(groupError(0)) + }; + const Log log { + {1, Handler::Sync}, + {2, Handler::Setup}, + {3, Handler::Sync}, + {0, Handler::GroupError} + }; + QTest::newRow("SyncAndAsyncError") + << TestData{storage, root, log, 2, OnStart::Running, OnDone::Failure}; + } + { Condition condition;