IDEA-48177 Run tab of already terminated process is not occupied with new process, if current tab is busy

This commit is contained in:
Vassiliy Kudryashov
2013-02-12 18:20:04 +04:00
parent c66a7b2baf
commit 2807bbc6bd
16 changed files with 314 additions and 58 deletions
@@ -33,8 +33,12 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import java.util.concurrent.atomic.AtomicLong;
public class ExecutionEnvironment extends UserDataHolderBase {
private static final AtomicLong myIdHolder = new AtomicLong(1L);
@Nullable private final Project myProject;
@NotNull private RunProfile myRunProfile;
@@ -44,6 +48,7 @@ public class ExecutionEnvironment extends UserDataHolderBase {
@Nullable private ConfigurationPerRunnerSettings myConfigurationSettings;
@Nullable private final RunnerAndConfigurationSettings myRunnerAndConfigurationSettings;
@Nullable private RunContentDescriptor myContentToReuse;
private long myExecutionId = 0;
@TestOnly
public ExecutionEnvironment() {
@@ -55,9 +60,18 @@ public class ExecutionEnvironment extends UserDataHolderBase {
public ExecutionEnvironment(@NotNull final ProgramRunner runner,
@NotNull final RunnerAndConfigurationSettings configuration,
@Nullable Project project) {
this(runner, DefaultExecutionTarget.INSTANCE, configuration, project);
this(configuration.getConfiguration(),
DefaultExecutionTarget.INSTANCE,
project,
configuration.getRunnerSettings(runner),
configuration.getConfigurationSettings(runner),
null,
null);
}
/**
* @deprecated, use {@link com.intellij.execution.runners.ExecutionEnvironmentBuilder} instead
*/
public ExecutionEnvironment(@NotNull final ProgramRunner runner,
@NotNull final ExecutionTarget target,
@NotNull final RunnerAndConfigurationSettings configuration,
@@ -72,6 +86,10 @@ public class ExecutionEnvironment extends UserDataHolderBase {
configuration);
}
/**
* @deprecated, use {@link com.intellij.execution.runners.ExecutionEnvironmentBuilder} instead
*/
@TestOnly
public ExecutionEnvironment(@NotNull final ProgramRunner runner,
@NotNull final ExecutionTarget target,
@NotNull final RunnerAndConfigurationSettings configuration,
@@ -85,14 +103,31 @@ public class ExecutionEnvironment extends UserDataHolderBase {
configuration);
}
/**
* @deprecated, use {@link com.intellij.execution.runners.ExecutionEnvironmentBuilder} instead
*/
@Deprecated
public ExecutionEnvironment(@NotNull final RunProfile runProfile,
@Nullable final RunnerSettings runnerSettings,
@Nullable final ConfigurationPerRunnerSettings configurationSettings,
@NotNull final DataContext dataContext) {
this(runProfile, DefaultExecutionTarget.INSTANCE, PlatformDataKeys.PROJECT.getData(dataContext), runnerSettings, configurationSettings, null, null);
}
/**
* @deprecated, use {@link com.intellij.execution.runners.ExecutionEnvironmentBuilder} instead
*/
public ExecutionEnvironment(@NotNull RunProfile runProfile,
@Nullable Project project,
@Nullable RunnerSettings runnerSettings,
@Nullable ConfigurationPerRunnerSettings configurationSettings,
@Nullable RunContentDescriptor contentToReuse) {
this(runProfile, project, runnerSettings, configurationSettings, contentToReuse, null);
this(runProfile, DefaultExecutionTarget.INSTANCE, project, runnerSettings, configurationSettings, contentToReuse, null);
}
/**
* @deprecated, use {@link com.intellij.execution.runners.ExecutionEnvironmentBuilder} instead
*/
public ExecutionEnvironment(@NotNull RunProfile runProfile,
@NotNull ExecutionTarget target,
@Nullable Project project,
@@ -102,6 +137,9 @@ public class ExecutionEnvironment extends UserDataHolderBase {
this(runProfile, target, project, runnerSettings, configurationSettings, contentToReuse, null);
}
/**
* @deprecated, use {@link com.intellij.execution.runners.ExecutionEnvironmentBuilder} instead
*/
public ExecutionEnvironment(@NotNull RunProfile runProfile,
@Nullable Project project,
@Nullable RunnerSettings runnerSettings,
@@ -136,13 +174,14 @@ public class ExecutionEnvironment extends UserDataHolderBase {
}
/**
* @deprecated use {@link #ExecutionEnvironment(ProgramRunner, com.intellij.execution.RunnerAndConfigurationSettings, com.intellij.openapi.project.Project)}
* @deprecated, use {@link com.intellij.execution.runners.ExecutionEnvironmentBuilder} instead
*/
@Deprecated
public ExecutionEnvironment(@NotNull final ProgramRunner runner,
@NotNull final RunnerAndConfigurationSettings configuration,
@NotNull final DataContext context) {
this(configuration.getConfiguration(),
DefaultExecutionTarget.INSTANCE,
PlatformDataKeys.PROJECT.getData(context),
configuration.getRunnerSettings(runner),
configuration.getConfigurationSettings(runner),
@@ -151,25 +190,13 @@ public class ExecutionEnvironment extends UserDataHolderBase {
}
/**
* @deprecated use {@link #ExecutionEnvironment(com.intellij.execution.configurations.RunProfile, com.intellij.openapi.project.Project, com.intellij.execution.configurations.RunnerSettings, com.intellij.execution.configurations.ConfigurationPerRunnerSettings, com.intellij.execution.ui.RunContentDescriptor)}
* @deprecated, use {@link com.intellij.execution.runners.ExecutionEnvironmentBuilder} instead
*/
@Deprecated
public ExecutionEnvironment(@NotNull final RunProfile profile,
@NotNull final DataContext dataContext) {
this(profile, PlatformDataKeys.PROJECT.getData(dataContext), null, null, null);
}
/**
* @deprecated use {@link #ExecutionEnvironment(com.intellij.execution.configurations.RunProfile, com.intellij.openapi.project.Project, com.intellij.execution.configurations.RunnerSettings, com.intellij.execution.configurations.ConfigurationPerRunnerSettings, com.intellij.execution.ui.RunContentDescriptor)}
*/
@Deprecated
public ExecutionEnvironment(@NotNull final RunProfile runProfile,
@Nullable final RunnerSettings runnerSettings,
@Nullable final ConfigurationPerRunnerSettings configurationSettings,
@NotNull final DataContext dataContext) {
this(runProfile, PlatformDataKeys.PROJECT.getData(dataContext), runnerSettings, configurationSettings, null);
}
@Nullable
public Project getProject() {
return myProject;
@@ -227,4 +254,29 @@ public class ExecutionEnvironment extends UserDataHolderBase {
public RunProfileState getState(final Executor executor) throws ExecutionException {
return myRunProfile.getState(executor, this);
}
public long assignNewExecutionId() {
myExecutionId = myIdHolder.incrementAndGet();
return myExecutionId;
}
public void setExecutionId(long executionId) {
myExecutionId = executionId;
}
public long getExecutionId() {
return myExecutionId;
}
@Override
public String toString() {
if (myRunnerAndConfigurationSettings != null) {
return myRunnerAndConfigurationSettings.getName();
} else if (myRunProfile != null) {
return myRunProfile.getName();
} else if (myContentToReuse != null) {
return myContentToReuse.getDisplayName();
}
return super.toString();
}
}
@@ -0,0 +1,113 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.execution.runners;
import com.intellij.execution.DefaultExecutionTarget;
import com.intellij.execution.ExecutionTarget;
import com.intellij.execution.RunnerAndConfigurationSettings;
import com.intellij.execution.configurations.ConfigurationPerRunnerSettings;
import com.intellij.execution.configurations.RunProfile;
import com.intellij.execution.configurations.RunnerSettings;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* User: Vassiliy.Kudryashov
*/
public final class ExecutionEnvironmentBuilder {
private static final Logger LOG = Logger.getInstance("#com.intellij.execution.runners.ExecutionEnvironmentBuilder");
@NotNull private RunProfile myRunProfile;
@NotNull private ExecutionTarget myTarget = DefaultExecutionTarget.INSTANCE;
@Nullable private Project myProject;
@Nullable private RunnerSettings myRunnerSettings;
@Nullable private ConfigurationPerRunnerSettings myConfigurationSettings;
@Nullable private RunContentDescriptor myContentToReuse;
@Nullable private RunnerAndConfigurationSettings myRunnerAndConfigurationSettings;
private boolean myAssignNewId;
public ExecutionEnvironmentBuilder() {
}
public ExecutionEnvironmentBuilder setTarget(@NotNull ExecutionTarget target) {
myTarget = target;
return this;
}
public ExecutionEnvironmentBuilder setProject(@Nullable Project project) {
check(myProject, "Project");
myProject = project;
return this;
}
public ExecutionEnvironmentBuilder setRunnerAndSettings(@NotNull ProgramRunner programRunner,
@NotNull RunnerAndConfigurationSettings settings) {
check(myRunnerAndConfigurationSettings, "RunnerAndConfigurationSettings");
myRunnerAndConfigurationSettings = settings;
setRunProfile(settings.getConfiguration());
setRunnerSettings(settings.getRunnerSettings(programRunner));
setConfigurationSettings(settings.getConfigurationSettings(programRunner));
return this;
}
public ExecutionEnvironmentBuilder setRunnerSettings(@Nullable RunnerSettings runnerSettings) {
check(myRunnerSettings, "RunnerSettings");
myRunnerSettings = runnerSettings;
return this;
}
public ExecutionEnvironmentBuilder setConfigurationSettings(@Nullable ConfigurationPerRunnerSettings configurationSettings) {
check(myConfigurationSettings, "ConfigurationPerRunnerSettings");
myConfigurationSettings = configurationSettings;
return this;
}
public ExecutionEnvironmentBuilder setContentToReuse(@Nullable RunContentDescriptor contentToReuse) {
check(myContentToReuse, "RunContentDescriptor");
myContentToReuse = contentToReuse;
return this;
}
public ExecutionEnvironmentBuilder setRunProfile(@NotNull RunProfile runProfile) {
check(myRunProfile, "RunProfile");
myRunProfile = runProfile;
return this;
}
public ExecutionEnvironmentBuilder assignNewId() {
myAssignNewId = true;
return this;
}
public ExecutionEnvironment build() {
ExecutionEnvironment environment =
new ExecutionEnvironment(myRunProfile, myTarget, myProject, myRunnerSettings, myConfigurationSettings, myContentToReuse,
myRunnerAndConfigurationSettings);
if (myAssignNewId) {
environment.assignNewExecutionId();
}
return environment;
}
private static void check(Object obj, String key) {
if (obj != null) LOG.warn("Value of " + key + " has been already set");
//throw new IllegalStateException("Value of " + key + " has been already set");
}
}
@@ -88,6 +88,9 @@ public abstract class GenericProgramRunner<Settings extends JDOMExternalizable>
@Nullable RunContentDescriptor contentToReuse,
@NotNull ExecutionEnvironment env) throws ExecutionException {
final RunContentDescriptor descriptor = doExecute(project, executor, state, contentToReuse, env);
if (descriptor != null) {
descriptor.setExecutionId(env.getExecutionId());
}
if (callback != null) callback.processStarted(descriptor);
return descriptor;
}
@@ -22,7 +22,6 @@ import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.DataProvider;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Key;
import com.intellij.ui.content.Content;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
@@ -30,7 +29,6 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
public class RunContentDescriptor implements Disposable {
public static final Key<Boolean> REUSE_CONTENT_PROHIBITED = Key.create("ReuseContentProhibited");
private static final Logger LOG = Logger.getInstance("#com.intellij.execution.ui.RunContentDescriptor");
private ExecutionConsole myExecutionConsole;
@@ -41,6 +39,7 @@ public class RunContentDescriptor implements Disposable {
private final String myHelpId;
private boolean myActivateToolWindowWhenAdded = true;
private long myExecutionId = 0;
/**
* Used to hack {@link com.intellij.execution.runners.RestartAction}
@@ -150,6 +149,14 @@ public class RunContentDescriptor implements Disposable {
myActivateToolWindowWhenAdded = activateToolWindowWhenAdded;
}
public long getExecutionId() {
return myExecutionId;
}
public void setExecutionId(long executionId) {
myExecutionId = executionId;
}
@Override
public String toString() {
return getClass().getName() + "#" + hashCode() + "(" + getDisplayName() + ")";
@@ -17,6 +17,7 @@ package com.intellij.execution.ui;
import com.intellij.execution.Executor;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.DataKey;
import com.intellij.openapi.wm.ToolWindow;
@@ -41,12 +42,16 @@ public interface RunContentManager {
* to reduce number of open contents RunContentManager reuses
* some of them during showRunContent (for ex. if a process was stopped)
* @return content that will be reused by showRunContent
* @deprecated use {@link #getReuseContent(com.intellij.execution.Executor, ExecutionEnvironment)}
*/
@Nullable
RunContentDescriptor getReuseContent(Executor requestor, @Nullable RunContentDescriptor contentToReuse);
@Nullable
RunContentDescriptor getReuseContent(Executor requestor, @NotNull ExecutionEnvironment executionEnvironment);
/**
* @deprecated use {@link #getReuseContent(com.intellij.execution.Executor, RunContentDescriptor)}
* @deprecated use {@link #getReuseContent(com.intellij.execution.Executor, ExecutionEnvironment)}
*/
@Deprecated
@Nullable
@@ -20,7 +20,7 @@ import com.intellij.execution.configurations.ConfigurationType;
import com.intellij.execution.configurations.RunConfiguration;
import com.intellij.execution.impl.RunDialog;
import com.intellij.execution.impl.RunManagerImpl;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.runners.ExecutionEnvironmentBuilder;
import com.intellij.execution.runners.ExecutionUtil;
import com.intellij.execution.runners.ProgramRunner;
import com.intellij.execution.ui.RunContentDescriptor;
@@ -97,7 +97,8 @@ public class ProgramRunnerUtil {
}
try {
runner.execute(executor, new ExecutionEnvironment(runner, target, configuration, contentToReuse, project));
runner.execute(executor, new ExecutionEnvironmentBuilder().setRunnerAndSettings(runner, configuration).setTarget(target)
.setContentToReuse(contentToReuse).setProject(project).assignNewId().build());
}
catch (ExecutionException e) {
ExecutionUtil.handleExecutionError(project, executor.getToolWindowId(), configuration.getConfiguration(), e);
@@ -120,6 +120,10 @@ public class ExecutionManagerImpl extends ExecutionManager implements ProjectCom
@NotNull final ExecutionEnvironment env,
@Nullable final RunProfileState state,
@Nullable final Runnable onCancelRunnable) {
long id = env.getExecutionId();
if (id == 0) {
id = env.assignNewExecutionId();
}
RunProfile profile = env.getRunProfile();
if (profile instanceof RunConfiguration) {
@@ -135,6 +139,7 @@ public class ExecutionManagerImpl extends ExecutionManager implements ProjectCom
.getSimpleContext(BeforeRunTaskProvider.RUNNER_ID, configurationSettings.getRunnerId(), projectContext) : projectContext;
if (!activeTasks.isEmpty()) {
final long finalId = id;
ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
/** @noinspection SSBasedInspection*/
@Override
@@ -152,8 +157,7 @@ public class ExecutionManagerImpl extends ExecutionManager implements ProjectCom
env.getConfigurationSettings(),
null,
env.getRunnerAndConfigurationSettings());
taskEnvironment
.putUserData(RunContentDescriptor.REUSE_CONTENT_PROHIBITED, RunConfigurationBeforeRunProvider.ID.equals(provider.getId()));
taskEnvironment.setExecutionId(finalId);
if (!provider.executeTask(dataContext, runConfiguration, taskEnvironment, task)) {
if (onCancelRunnable != null) {
SwingUtilities.invokeLater(onCancelRunnable);
@@ -187,7 +191,10 @@ public class ExecutionManagerImpl extends ExecutionManager implements ProjectCom
public void startRunProfile(@NotNull final RunProfileStarter starter, @NotNull final RunProfileState state,
@NotNull final Project project, @NotNull final Executor executor, @NotNull final ExecutionEnvironment env) {
final RunContentDescriptor reuseContent =
ExecutionManager.getInstance(project).getContentManager().getReuseContent(executor, env.getContentToReuse());
ExecutionManager.getInstance(project).getContentManager().getReuseContent(executor, env);
if (reuseContent != null) {
reuseContent.setExecutionId(env.getExecutionId());
}
final RunProfile profile = env.getRunProfile();
project.getMessageBus().syncPublisher(EXECUTION_TOPIC).processStartScheduled(executor.getId(), env);
@@ -180,7 +180,7 @@ extends BeforeRunTaskProvider<RunConfigurationBeforeRunProvider.RunConfigurableB
if (runner == null)
return false;
final ExecutionEnvironment environment = new ExecutionEnvironment(runner, settings, myProject);
environment.putUserData(RunContentDescriptor.REUSE_CONTENT_PROHIBITED, env.getUserData(RunContentDescriptor.REUSE_CONTENT_PROHIBITED));
environment.setExecutionId(env.getExecutionId());
if (!ExecutionTargetManager.canRun(settings, env.getExecutionTarget())) {
return false;
}
@@ -50,7 +50,6 @@ public class RunContentBuilder extends LogConsoleManagerBase {
private final ProgramRunner myRunner;
private final ArrayList<AnAction> myRunnerActions = new ArrayList<AnAction>();
private boolean myReuseProhibited = false;
private ExecutionResult myExecutionResult;
private final LogFilesManager myManager;
@@ -79,7 +78,6 @@ public class RunContentBuilder extends LogConsoleManagerBase {
if (profile instanceof RunConfigurationBase) {
myManager.registerFileMatcher((RunConfigurationBase)profile);
}
myReuseProhibited = Boolean.TRUE.equals(env.getUserData(RunContentDescriptor.REUSE_CONTENT_PROHIBITED));
}
public void addAction(@NotNull final AnAction action) {
@@ -110,7 +108,7 @@ public class RunContentBuilder extends LogConsoleManagerBase {
myUi.getOptions().setMoveToGridActionEnabled(false).setMinimizeActionEnabled(false);
if (ApplicationManager.getApplication().isUnitTestMode()) {
return new MyRunContentDescriptor(profile, myExecutionResult, myReuseProhibited, myUi.getComponent(), this);
return new MyRunContentDescriptor(profile, myExecutionResult, myUi.getComponent(), this);
}
if (console != null) {
@@ -125,7 +123,7 @@ public class RunContentBuilder extends LogConsoleManagerBase {
OutputFileUtil.attachDumpListener((RunConfigurationBase)profile, myExecutionResult.getProcessHandler(), console);
}
}
MyRunContentDescriptor contentDescriptor = new MyRunContentDescriptor(profile, myExecutionResult, myReuseProhibited, myUi.getComponent(), this);
MyRunContentDescriptor contentDescriptor = new MyRunContentDescriptor(profile, myExecutionResult, myUi.getComponent(), this);
myUi.getOptions().setLeftToolbar(createActionToolbar(contentDescriptor, myUi.getComponent()), ActionPlaces.UNKNOWN);
if (profile instanceof RunConfigurationBase) {
@@ -239,20 +237,13 @@ public class RunContentBuilder extends LogConsoleManagerBase {
}
private static class MyRunContentDescriptor extends RunContentDescriptor {
private final boolean myReuseProhibited;
private final Disposable myAdditionalDisposable;
public MyRunContentDescriptor(final RunProfile profile, final ExecutionResult executionResult, final boolean reuseProhibited, final JComponent component, @NotNull Disposable additionalDisposable) {
public MyRunContentDescriptor(final RunProfile profile, final ExecutionResult executionResult, final JComponent component, @NotNull Disposable additionalDisposable) {
super(executionResult.getExecutionConsole(), executionResult.getProcessHandler(), component, profile.getName(), profile.getIcon());
myReuseProhibited = reuseProhibited;
myAdditionalDisposable = additionalDisposable;
}
@Override
public boolean isContentReuseProhibited() {
return myReuseProhibited;
}
@Override
public void dispose() {
Disposer.dispose(myAdditionalDisposable);
@@ -19,6 +19,7 @@ import com.intellij.execution.*;
import com.intellij.execution.process.ProcessAdapter;
import com.intellij.execution.process.ProcessEvent;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.runners.GenericProgramRunner;
import com.intellij.execution.ui.layout.impl.DockableGridContainerFactory;
import com.intellij.ide.DataManager;
@@ -63,7 +64,6 @@ public class RunContentManagerImpl implements RunContentManager, Disposable {
public static final Key<Boolean> ALWAYS_USE_DEFAULT_STOPPING_BEHAVIOUR_KEY = Key.create("ALWAYS_USE_DEFAULT_STOPPING_BEHAVIOUR_KEY");
private static final Logger LOG = Logger.getInstance("#com.intellij.execution.ui.RunContentManagerImpl");
private static final Key<RunContentDescriptor> DESCRIPTOR_KEY = new Key<RunContentDescriptor>("Descriptor");
private static final Key<Boolean> MARKED_TO_BE_REUSED = Key.create("MarkedToBeReused");
private final Project myProject;
private DockableGridContainerFactory myContentFactory;
@@ -266,10 +266,15 @@ public class RunContentManagerImpl implements RunContentManager, Disposable {
}
public void showRunContent(@NotNull final Executor executor, final RunContentDescriptor descriptor) {
showRunContent(executor, descriptor, descriptor != null ? descriptor.getExecutionId() : 0L);
}
public void showRunContent(@NotNull final Executor executor, final RunContentDescriptor descriptor, long executionId) {
if (ApplicationManager.getApplication().isUnitTestMode()) return;
final ContentManager contentManager = getContentManagerForRunner(executor);
RunContentDescriptor oldDescriptor = chooseReuseContentForDescriptor(contentManager, descriptor);
RunContentDescriptor oldDescriptor =
chooseReuseContentForDescriptor(contentManager, descriptor, executionId, descriptor != null ? descriptor.getDisplayName() : null);
final Content content;
@@ -279,16 +284,16 @@ public class RunContentManagerImpl implements RunContentManager, Disposable {
getSyncPublisher().contentRemoved(oldDescriptor, executor);
Disposer.dispose(oldDescriptor); // is of the same category, can be reused
}
else if (oldAttachedContent == null || !oldAttachedContent.isValid() || oldAttachedContent.getUserData(MARKED_TO_BE_REUSED) != null ) {
else if (oldAttachedContent == null || !oldAttachedContent.isValid() /*|| oldAttachedContent.getUserData(MARKED_TO_BE_REUSED) != null */) {
content = createNewContent(contentManager, descriptor, executor);
final Icon icon = descriptor.getIcon();
content.setIcon(icon == null ? executor.getToolWindowIcon() : icon);
} else {
content = oldAttachedContent;
}
content.setExecutionId(executionId);
content.setComponent(descriptor.getComponent());
content.putUserData(DESCRIPTOR_KEY, descriptor);
content.putUserData(MARKED_TO_BE_REUSED, Boolean.TRUE);
final ProcessHandler processHandler = descriptor.getProcessHandler();
if (processHandler != null) {
final ProcessAdapter processAdapter = new ProcessAdapter() {
@@ -306,7 +311,6 @@ public class RunContentManagerImpl implements RunContentManager, Disposable {
public void run() {
final Icon icon = descriptor.getIcon();
content.setIcon(icon == null ? executor.getDisabledIcon() : IconLoader.getTransparentIcon(icon));
content.putUserData(MARKED_TO_BE_REUSED, null);
}
});
}
@@ -344,17 +348,32 @@ public class RunContentManagerImpl implements RunContentManager, Disposable {
}
@Nullable
@Deprecated
public RunContentDescriptor getReuseContent(final Executor requestor, DataContext dataContext) {
if (ApplicationManager.getApplication().isUnitTestMode()) return null;
return getReuseContent(requestor, GenericProgramRunner.CONTENT_TO_REUSE_DATA_KEY.getData(dataContext));
}
@Nullable
@Deprecated
public RunContentDescriptor getReuseContent(Executor requestor, @Nullable RunContentDescriptor contentToReuse) {
if (ApplicationManager.getApplication().isUnitTestMode()) return null;
if (contentToReuse != null) return contentToReuse;
final ContentManager contentManager = getContentManagerForRunner(requestor);
return chooseReuseContentForDescriptor(contentManager, contentToReuse);
return chooseReuseContentForDescriptor(contentManager, contentToReuse, 0L, null);
}
@Nullable
@Override
public RunContentDescriptor getReuseContent(Executor requestor, @NotNull ExecutionEnvironment executionEnvironment) {
if (ApplicationManager.getApplication().isUnitTestMode()) return null;
RunContentDescriptor contentToReuse = executionEnvironment.getContentToReuse();
if (contentToReuse != null) return contentToReuse;
final ContentManager contentManager = getContentManagerForRunner(requestor);
return chooseReuseContentForDescriptor(contentManager, contentToReuse, executionEnvironment.getExecutionId(),
executionEnvironment.toString());
}
public RunContentDescriptor findContentDescriptor(final Executor requestor, final ProcessHandler handler) {
@@ -368,35 +387,64 @@ public class RunContentManagerImpl implements RunContentManager, Disposable {
descriptor.setAttachedContent(attachedContent);
}
}
showRunContent(info, descriptor);
showRunContent(info, descriptor, descriptor != null ? descriptor.getExecutionId(): 0L);
}
@Nullable
private static RunContentDescriptor chooseReuseContentForDescriptor(final ContentManager contentManager,
final RunContentDescriptor descriptor) {
final RunContentDescriptor descriptor,
long executionId,
@Nullable String preferredName) {
Content content = null;
if (descriptor != null) {
//Stage one: some specific descriptors (like AnalyzeStacktrace) cannot be reused at all
if (descriptor.isContentReuseProhibited()) {
return null;
}
//Stage two: try to get content from descriptor itself
final Content attachedContent = descriptor.getAttachedContent();
if (attachedContent != null && attachedContent.isValid()) content = attachedContent;
}
//Stage three: choose the content with name we prefer
if (content == null && preferredName != null) {
content = getContentFromManager(contentManager, preferredName, executionId);
}
//Stage four: try to get current selected content
if (content == null) {
content = contentManager.getSelectedContent();
if (content != null && content.isPinned()) content = null;
}
if (content == null || !isTerminated(content) || content.getUserData(MARKED_TO_BE_REUSED) != null) {
//Stage five: content is still null and every "old good" content is acceptable
if (content == null) {
content = getContentFromManager(contentManager, null, executionId);
}
if (content == null || !isTerminated(content) || (content.getExecutionId() == executionId && executionId != 0)) {
return null;
}
final RunContentDescriptor oldDescriptor = getRunContentDescriptorByContent(content);
if (oldDescriptor != null && !oldDescriptor.isContentReuseProhibited()) {
if (oldDescriptor != null && !oldDescriptor.isContentReuseProhibited() ) {
//content.setExecutionId(executionId);
return oldDescriptor;
}
return null;
}
@Nullable
private static Content getContentFromManager(ContentManager contentManager, @Nullable String preferredName, long executionId) {
Content[] contents = contentManager.getContents();
for (Content c : contents) {
if (c == null || c.isPinned() || !isTerminated(c) || (c.getExecutionId() == executionId && executionId != 0))
continue;
if (preferredName == null) {
return c;
} else if (preferredName.equals(c.getDisplayName())) {
return c;
}
}
return null;
}
private ContentManager getContentManagerForRunner(final Executor executor) {
final ContentManager contentManager = myToolwindowIdToContentManagerMap.get(executor.getToolWindowId());
if (contentManager == null) {
@@ -22,6 +22,7 @@ import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.executors.DefaultRunExecutor;
import com.intellij.execution.process.OSProcessHandler;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.runners.ExecutionEnvironmentBuilder;
import com.intellij.execution.runners.ProgramRunner;
import com.intellij.execution.util.ExecutionErrorDialog;
import com.intellij.ide.macro.Macro;
@@ -260,7 +261,7 @@ public class Tool implements SchemeElement {
return name.toString();
}
public void execute(AnActionEvent event, DataContext dataContext) {
public void execute(AnActionEvent event, DataContext dataContext, long executionId) {
final Project project = PlatformDataKeys.PROJECT.getData(dataContext);
if (project == null) {
return;
@@ -272,7 +273,9 @@ public class Tool implements SchemeElement {
final ProgramRunner runner = RunnerRegistry.getInstance().getRunner(DefaultRunExecutor.EXECUTOR_ID, profile);
assert runner != null;
runner.execute(new DefaultRunExecutor(), new ExecutionEnvironment(profile, project, null, null, null));
ExecutionEnvironment executionEnvironment = new ExecutionEnvironmentBuilder().setRunProfile(profile).setProject(project).build();
executionEnvironment.setExecutionId(executionId);
runner.execute(new DefaultRunExecutor(), executionEnvironment);
}
else {
GeneralCommandLine commandLine = createCommandLine(dataContext);
@@ -37,7 +37,7 @@ public class ToolAction extends AnAction implements DumbAware {
}
public void actionPerformed(AnActionEvent e) {
runTool(myActionId, e.getDataContext(), e);
runTool(myActionId, e.getDataContext(), e, 0L);
}
@Override
@@ -62,14 +62,18 @@ public class ToolAction extends AnAction implements DumbAware {
return ToolsProvider.getAllTools();
}
static void runTool(String actionId, DataContext context) {
runTool(actionId, context, null);
static void runTool(String actionId, DataContext context, long executionId) {
runTool(actionId, context, null, executionId);
}
static void runTool(String actionId, DataContext context, AnActionEvent e) {
static void runTool(String actionId, DataContext context) {
runTool(actionId, context, null, 0L);
}
static void runTool(String actionId, DataContext context, AnActionEvent e, long executionId) {
Tool tool = findTool(actionId, context);
if (tool != null) {
tool.execute(e, new HackyDataContext(context, e));
tool.execute(e, new HackyDataContext(context, e), executionId);
}
}
}
@@ -64,12 +64,12 @@ public class ToolBeforeRunTask extends BeforeRunTask<ToolBeforeRunTask> {
return (ToolBeforeRunTask)super.clone();
}
public void execute(final DataContext context) {
public void execute(final DataContext context, final long executionId) {
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
ToolAction.runTool(myToolActionId, context);
ToolAction.runTool(myToolActionId, context, executionId);
}
});
}
@@ -101,7 +101,7 @@ public class ToolBeforeRunTaskProvider extends BeforeRunTaskProvider<ToolBeforeR
if (!task.isExecutable()) {
return false;
}
task.execute(context);
task.execute(context, env.getExecutionId());
return true;
}
}
@@ -121,4 +121,10 @@ public interface Content extends UserDataHolder, ComponentContainer {
void setPopupIcon(Icon icon);
Icon getPopupIcon();
/**
* @param executionId supposed to identify group of contents (for example "Before Launch" tasks and the main Run Configuration)
*/
void setExecutionId(long executionId);
long getExecutionId();
}
@@ -62,6 +62,7 @@ public class ContentImpl extends UserDataHolderBase implements Content {
private BusyObject myBusyObject;
private String mySeparator;
private Icon myPopupIcon;
private long myExecutionId;
public ContentImpl(JComponent component, String displayName, boolean isPinnable) {
myComponent = component;
@@ -276,7 +277,12 @@ public class ContentImpl extends UserDataHolderBase implements Content {
@NonNls
public String toString() {
return "Content name=" + myDisplayName;
StringBuilder sb = new StringBuilder("Content name=").append(myDisplayName);
if (myIsLocked)
sb.append(", pinned");
if (myExecutionId != 0)
sb.append(", executionId=").append(myExecutionId);
return sb.toString();
}
@Override
@@ -351,4 +357,14 @@ public class ContentImpl extends UserDataHolderBase implements Content {
public JComponent getSearchComponent() {
return mySearchComponent;
}
@Override
public void setExecutionId(long executionId) {
myExecutionId = executionId;
}
@Override
public long getExecutionId() {
return myExecutionId;
}
}