1 // Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 package com.intellij.execution.dashboard.actions;
4 import com.intellij.execution.*;
5 import com.intellij.execution.compound.CompoundRunConfiguration;
6 import com.intellij.execution.compound.SettingsAndEffectiveTarget;
7 import com.intellij.execution.configurations.RunConfiguration;
8 import com.intellij.execution.configurations.RuntimeConfigurationError;
9 import com.intellij.execution.configurations.RuntimeConfigurationException;
10 import com.intellij.execution.dashboard.RunDashboardRunConfigurationNode;
11 import com.intellij.execution.process.ProcessHandler;
12 import com.intellij.execution.runToolbar.RunToolbarProcessData;
13 import com.intellij.execution.runners.ExecutionEnvironment;
14 import com.intellij.execution.runners.ProgramRunner;
15 import com.intellij.execution.ui.RunContentDescriptor;
16 import com.intellij.execution.ui.RunContentManagerImpl;
17 import com.intellij.openapi.actionSystem.AnActionEvent;
18 import com.intellij.openapi.actionSystem.Presentation;
19 import com.intellij.openapi.actionSystem.UpdateInBackground;
20 import com.intellij.openapi.progress.ProgressManager;
21 import com.intellij.openapi.project.DumbAwareAction;
22 import com.intellij.openapi.project.DumbService;
23 import com.intellij.openapi.project.IndexNotReadyException;
24 import com.intellij.openapi.project.Project;
25 import com.intellij.openapi.util.Key;
26 import com.intellij.openapi.util.NlsActions;
27 import com.intellij.ui.content.Content;
28 import com.intellij.util.containers.JBIterable;
29 import org.jetbrains.annotations.NotNull;
30 import org.jetbrains.annotations.Nullable;
33 import java.util.List;
34 import java.util.function.Consumer;
36 import static com.intellij.execution.dashboard.actions.RunDashboardActionUtils.getLeafTargets;
39 * @author konstantin.aleev
41 public abstract class ExecutorAction extends DumbAwareAction implements UpdateInBackground {
42 private static final Key<List<RunDashboardRunConfigurationNode>> RUNNABLE_LEAVES_KEY =
43 Key.create("RUNNABLE_LEAVES_KEY");
45 protected ExecutorAction() {
48 protected ExecutorAction(@NlsActions.ActionText String text, @NlsActions.ActionDescription String description, Icon icon) {
49 super(text, description, icon);
53 public void update(@NotNull AnActionEvent e) {
54 Project project = e.getProject();
55 if (project == null) {
59 JBIterable<RunDashboardRunConfigurationNode> targetNodes = getLeafTargets(e);
60 boolean running = targetNodes.filter(node -> {
61 Content content = node.getContent();
62 return content != null && !RunContentManagerImpl.isTerminated(content);
65 List<RunDashboardRunConfigurationNode> runnableLeaves = targetNodes.filter(this::canRun).toList();
66 Presentation presentation = e.getPresentation();
67 if (!runnableLeaves.isEmpty()) {
68 presentation.putClientProperty(RUNNABLE_LEAVES_KEY, runnableLeaves);
70 presentation.setEnabled(!runnableLeaves.isEmpty());
73 private boolean canRun(@NotNull RunDashboardRunConfigurationNode node) {
74 ProgressManager.checkCanceled();
76 Project project = node.getProject();
77 return canRun(node.getConfigurationSettings(),
79 DumbService.isDumb(project));
82 private boolean canRun(RunnerAndConfigurationSettings settings, ExecutionTarget target, boolean isDumb) {
83 if (isDumb && !settings.getType().isDumbAware()) return false;
85 String executorId = getExecutor().getId();
86 RunConfiguration configuration = settings.getConfiguration();
87 Project project = configuration.getProject();
88 if (configuration instanceof CompoundRunConfiguration) {
89 if (ExecutionTargetManager.getInstance(project).getTargetsFor(configuration).isEmpty()) return false;
91 List<SettingsAndEffectiveTarget> subConfigurations =
92 ((CompoundRunConfiguration)configuration).getConfigurationsWithEffectiveRunTargets();
93 if (subConfigurations.isEmpty()) return false;
95 RunManager runManager = RunManager.getInstance(project);
96 for (SettingsAndEffectiveTarget subConfiguration : subConfigurations) {
97 RunnerAndConfigurationSettings subSettings = runManager.findSettings(subConfiguration.getConfiguration());
98 if (subSettings == null || !canRun(subSettings, subConfiguration.getTarget(), isDumb)) {
105 if (!isValid(settings)) return false;
107 ProgramRunner<?> runner = ProgramRunner.getRunner(executorId, configuration);
108 if (runner == null) return false;
110 if (target == null) {
111 target = ExecutionTargetManager.getInstance(project).findTarget(configuration);
112 if (target == null) return false;
114 else if (!ExecutionTargetManager.canRun(configuration, target)) {
117 return !ExecutionManager.getInstance(project).isStarting(executorId, runner.getRunnerId());
120 private static boolean isValid(RunnerAndConfigurationSettings settings) {
122 settings.checkSettings(null);
125 catch (RuntimeConfigurationError ex) {
128 catch (IndexNotReadyException | RuntimeConfigurationException ex) {
134 public void actionPerformed(@NotNull AnActionEvent e) {
135 Project project = e.getProject();
136 if (project == null) return;
138 List<RunDashboardRunConfigurationNode> runnableLeaves = e.getPresentation().getClientProperty(RUNNABLE_LEAVES_KEY);
139 if (runnableLeaves == null) return;
141 for (RunDashboardRunConfigurationNode node : runnableLeaves) {
142 run(node.getConfigurationSettings(), null, node.getDescriptor());
146 private void run(RunnerAndConfigurationSettings settings, ExecutionTarget target, RunContentDescriptor descriptor) {
147 runSubProcess(settings, target, descriptor, RunToolbarProcessData.prepareBaseSettingCustomization(settings, null));
150 private void runSubProcess(RunnerAndConfigurationSettings settings, ExecutionTarget target, RunContentDescriptor descriptor, @Nullable Consumer<ExecutionEnvironment> envCustomization) {
151 RunConfiguration configuration = settings.getConfiguration();
152 Project project = configuration.getProject();
153 RunManager runManager = RunManager.getInstance(project);
154 if (configuration instanceof CompoundRunConfiguration) {
155 List<SettingsAndEffectiveTarget> subConfigurations =
156 ((CompoundRunConfiguration)configuration).getConfigurationsWithEffectiveRunTargets();
157 for (SettingsAndEffectiveTarget subConfiguration : subConfigurations) {
158 RunnerAndConfigurationSettings subSettings = runManager.findSettings(subConfiguration.getConfiguration());
159 if (subSettings != null) {
160 runSubProcess(subSettings, subConfiguration.getTarget(), null, envCustomization);
165 if (target == null) {
166 target = ExecutionTargetManager.getInstance(project).findTarget(configuration);
167 assert target != null : "No target for configuration of type " + configuration.getType().getDisplayName();
169 ProcessHandler processHandler = descriptor == null ? null : descriptor.getProcessHandler();
171 ExecutionManager.getInstance(project).restartRunProfile(project, getExecutor(), target, settings, processHandler, RunToolbarProcessData.prepareSuppressMainSlotCustomization(project, envCustomization));
175 protected abstract Executor getExecutor();
177 protected abstract void update(@NotNull AnActionEvent e, boolean running);