diff --git a/platform/lang-api/src/com/intellij/execution/runners/ExecutionEnvironment.java b/platform/lang-api/src/com/intellij/execution/runners/ExecutionEnvironment.java index a790caada2be..e35609712c52 100644 --- a/platform/lang-api/src/com/intellij/execution/runners/ExecutionEnvironment.java +++ b/platform/lang-api/src/com/intellij/execution/runners/ExecutionEnvironment.java @@ -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(); + } } diff --git a/platform/lang-api/src/com/intellij/execution/runners/ExecutionEnvironmentBuilder.java b/platform/lang-api/src/com/intellij/execution/runners/ExecutionEnvironmentBuilder.java new file mode 100644 index 000000000000..378f4063d8fb --- /dev/null +++ b/platform/lang-api/src/com/intellij/execution/runners/ExecutionEnvironmentBuilder.java @@ -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"); + } +} diff --git a/platform/lang-api/src/com/intellij/execution/runners/GenericProgramRunner.java b/platform/lang-api/src/com/intellij/execution/runners/GenericProgramRunner.java index 1605124ffcbf..c16363ba2d35 100644 --- a/platform/lang-api/src/com/intellij/execution/runners/GenericProgramRunner.java +++ b/platform/lang-api/src/com/intellij/execution/runners/GenericProgramRunner.java @@ -88,6 +88,9 @@ public abstract class GenericProgramRunner @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; } diff --git a/platform/lang-api/src/com/intellij/execution/ui/RunContentDescriptor.java b/platform/lang-api/src/com/intellij/execution/ui/RunContentDescriptor.java index c5c074539161..a2e52b74409f 100644 --- a/platform/lang-api/src/com/intellij/execution/ui/RunContentDescriptor.java +++ b/platform/lang-api/src/com/intellij/execution/ui/RunContentDescriptor.java @@ -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 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() + ")"; diff --git a/platform/lang-api/src/com/intellij/execution/ui/RunContentManager.java b/platform/lang-api/src/com/intellij/execution/ui/RunContentManager.java index f58ef2b6f313..8028144ba84c 100644 --- a/platform/lang-api/src/com/intellij/execution/ui/RunContentManager.java +++ b/platform/lang-api/src/com/intellij/execution/ui/RunContentManager.java @@ -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 diff --git a/platform/lang-impl/src/com/intellij/execution/ProgramRunnerUtil.java b/platform/lang-impl/src/com/intellij/execution/ProgramRunnerUtil.java index 64229d5dca41..76dea54e0d13 100644 --- a/platform/lang-impl/src/com/intellij/execution/ProgramRunnerUtil.java +++ b/platform/lang-impl/src/com/intellij/execution/ProgramRunnerUtil.java @@ -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); diff --git a/platform/lang-impl/src/com/intellij/execution/impl/ExecutionManagerImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/ExecutionManagerImpl.java index e0003161ef6e..333683dcb07a 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/ExecutionManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/ExecutionManagerImpl.java @@ -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); diff --git a/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java b/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java index 9ac0b1877c0c..7404360892ea 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java @@ -180,7 +180,7 @@ extends BeforeRunTaskProvider myRunnerActions = new ArrayList(); - 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); diff --git a/platform/lang-impl/src/com/intellij/execution/ui/RunContentManagerImpl.java b/platform/lang-impl/src/com/intellij/execution/ui/RunContentManagerImpl.java index 2a3257b7947f..c044e5b8c97b 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/RunContentManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/RunContentManagerImpl.java @@ -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 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 DESCRIPTOR_KEY = new Key("Descriptor"); - private static final Key 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) { diff --git a/platform/lang-impl/src/com/intellij/tools/Tool.java b/platform/lang-impl/src/com/intellij/tools/Tool.java index dae8d0840f7e..26be341b6fae 100644 --- a/platform/lang-impl/src/com/intellij/tools/Tool.java +++ b/platform/lang-impl/src/com/intellij/tools/Tool.java @@ -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); diff --git a/platform/lang-impl/src/com/intellij/tools/ToolAction.java b/platform/lang-impl/src/com/intellij/tools/ToolAction.java index caa2b6124c5b..c47b0a5405aa 100644 --- a/platform/lang-impl/src/com/intellij/tools/ToolAction.java +++ b/platform/lang-impl/src/com/intellij/tools/ToolAction.java @@ -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); } } } diff --git a/platform/lang-impl/src/com/intellij/tools/ToolBeforeRunTask.java b/platform/lang-impl/src/com/intellij/tools/ToolBeforeRunTask.java index ffeb1a4660c8..9008262ea6b9 100644 --- a/platform/lang-impl/src/com/intellij/tools/ToolBeforeRunTask.java +++ b/platform/lang-impl/src/com/intellij/tools/ToolBeforeRunTask.java @@ -64,12 +64,12 @@ public class ToolBeforeRunTask extends BeforeRunTask { 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); } }); } diff --git a/platform/lang-impl/src/com/intellij/tools/ToolBeforeRunTaskProvider.java b/platform/lang-impl/src/com/intellij/tools/ToolBeforeRunTaskProvider.java index 0154f63f2c00..e6f8879a2f97 100644 --- a/platform/lang-impl/src/com/intellij/tools/ToolBeforeRunTaskProvider.java +++ b/platform/lang-impl/src/com/intellij/tools/ToolBeforeRunTaskProvider.java @@ -101,7 +101,7 @@ public class ToolBeforeRunTaskProvider extends BeforeRunTaskProvider