Promise<Result> (@NotNull ProjectTaskContext context, @NotNull ProjectTask projectTask) { Tracer.Span buildSpan = Tracer.start("build"); AsyncPromise<Result> promiseResult = new AsyncPromise<>(); List<Pair<ProjectTaskRunner, Collection<? extends ProjectTask>>> toRun = groupByRunner(projectTask, context); buildSpan.complete(); context.putUserData(ProjectTaskScope.KEY, new ProjectTaskScope() { @Override public @NotNull <T extends ProjectTask> List<T> getRequestedTasks(@NotNull Class<T> instanceOf) { List<T> tasks = new ArrayList<>(); //noinspection unchecked toRun.forEach(pair -> pair.second.stream().filter(instanceOf::isInstance).map(task -> (T)task).forEach(tasks::add)); return tasks; } }); Pair<StructuredIdeActivity, List<EventPair<?>>> activity = reportBuildStart(projectTask, toRun); myEventPublisher.started(context); Runnable runnable = () -> { for (ProjectTaskManagerListener listener : myListeners) { try { listener.beforeRun(context); } catch (ExecutionException e) { sendAbortedEmptyResult(context, new ResultConsumer(promiseResult)); activity.first.finished(() -> activity.second); return; } } if (toRun.isEmpty()) { sendSuccessEmptyResult(context, new ResultConsumer(promiseResult)); activity.first.finished(() -> activity.second); return; } ProjectTaskResultsAggregator resultsCollector = new ProjectTaskResultsAggregator(context, new ResultConsumer(promiseResult), toRun.size(), activity); for (Pair<ProjectTaskRunner, Collection<? extends ProjectTask>> pair : toRun) { Consumer<ProjectTaskRunner.Result> runnerResultConsumer = result -> resultsCollector.add(result, pair.second); if (pair.second.isEmpty()) { runnerResultConsumer.accept(TaskRunnerResults.SUCCESS); } else { ProjectTaskRunner runner = pair.first; if (context.isCollectionOfGeneratedFilesEnabled() && !runner.isFileGeneratedEventsSupported()) { pair.second.stream() .filter(ModuleBuildTask.class::isInstance) .map(task -> ((ModuleBuildTask)task).getModule()) .forEach(module -> context.addDirtyOutputPathsProvider(moduleOutputPathsProvider(module))); } runner .run(myProject, context, pair.second.toArray(EMPTY_TASKS_ARRAY)) .onSuccess(runnerResultConsumer) .onError(throwable -> runnerResultConsumer.accept(TaskRunnerResults.ABORTED)); } } }; // do not run before tasks on EDT if (ApplicationManager.getApplication().isDispatchThread()) { ApplicationManager.getApplication().executeOnPooledThread(runnable); } else { runnable.run(); } promiseResult.onProcessed(result -> { buildSpan.complete(); }); return promiseResult; }