Build tool window: debugger integration

This commit is contained in:
Vladislav.Soroka
2017-09-03 09:38:41 +03:00
parent a25c7a3aa2
commit bd557870d0
12 changed files with 386 additions and 121 deletions
@@ -16,17 +16,19 @@
package com.intellij.build;
import com.intellij.build.events.*;
import com.intellij.execution.actions.StopAction;
import com.intellij.execution.actions.StopProcessAction;
import com.intellij.execution.console.DuplexConsoleView;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.ui.ConsoleView;
import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.execution.ui.ExecutionConsole;
import com.intellij.execution.runners.FakeRerunAction;
import com.intellij.execution.ui.*;
import com.intellij.execution.ui.actions.CloseAction;
import com.intellij.execution.ui.layout.impl.RunnerLayoutUiImpl;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.ComponentContainer;
import com.intellij.openapi.ui.ThreeComponentsSplitter;
import com.intellij.openapi.util.Disposer;
import com.intellij.ui.SimpleColoredComponent;
@@ -35,17 +37,21 @@ import com.intellij.ui.components.JBList;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.ui.content.Content;
import com.intellij.ui.content.impl.ContentImpl;
import com.intellij.util.*;
import com.intellij.ui.content.tabs.PinToolwindowTabAction;
import com.intellij.util.Alarm;
import com.intellij.util.Consumer;
import com.intellij.util.ObjectUtils;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.text.DateFormatUtil;
import com.intellij.util.ui.EdtInvocationManager;
import com.intellij.util.ui.EmptyIcon;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
@@ -55,6 +61,7 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Supplier;
/**
* @author Vladislav.Soroka
@@ -69,7 +76,7 @@ public abstract class AbstractViewManager implements BuildProgressListener, Disp
@Nullable
private final JBList<BuildInfo> myBuildsList;
private final Map<Object, BuildInfo> myBuildsMap;
private final Map<BuildInfo, DuplexConsoleView<BuildConsoleView, ConsoleView>> myViewMap;
private final Map<BuildInfo, BuildView> myViewMap;
private volatile Content myContent;
private volatile DefaultActionGroup myToolbarActions;
@@ -131,8 +138,7 @@ public abstract class AbstractViewManager implements BuildProgressListener, Disp
}
}
if (shouldBeCleared) {
for (DuplexConsoleView<BuildConsoleView, ConsoleView> view : myViewMap.values()) {
view.clear();
for (BuildView view : myViewMap.values()) {
Disposer.dispose(view);
}
listModel.clear();
@@ -166,40 +172,80 @@ public abstract class AbstractViewManager implements BuildProgressListener, Disp
}
ProcessHandler processHandler = ((StartBuildEvent)event).getProcessHandler();
DuplexConsoleView<BuildConsoleView, ConsoleView> view = myViewMap.computeIfAbsent(buildInfo, info -> {
ExecutionConsole executionConsole = ((StartBuildEvent)event).getExecutionConsole();
if (executionConsole == null) {
executionConsole = new BuildTextConsoleView(myProject);
BuildView view = myViewMap.computeIfAbsent(buildInfo, info -> {
ExecutionConsole executionConsole = null;
ComponentContainer componentContainer = null;
Supplier<RunContentDescriptor> contentDescriptorSupplier = ((StartBuildEvent)event).getContentDescriptorSupplier();
if (contentDescriptorSupplier != null) {
RunContentDescriptor contentDescriptor = contentDescriptorSupplier.get();
if (contentDescriptor != null) {
executionConsole = contentDescriptor.getExecutionConsole();
List<AnAction> leftToolbarActions = ContainerUtil.newArrayList();
RunnerLayoutUi layoutUi = contentDescriptor.getRunnerLayoutUi();
if (layoutUi instanceof RunnerLayoutUiImpl) {
RunnerLayoutUiImpl layoutUiImpl = (RunnerLayoutUiImpl)layoutUi;
layoutUiImpl.setLeftToolbarVisible(false);
layoutUiImpl.setContentToolbarBefore(false);
leftToolbarActions.addAll(layoutUiImpl.getActions());
}
JComponent component = contentDescriptor.getComponent();
AnAction[] leftToolbarActionsArray = leftToolbarActions.toArray(new AnAction[leftToolbarActions.size()]);
componentContainer = new BuildConsoleView() {
@Override
public void onEvent(BuildEvent event) {
}
@Override
public AnAction[] createConsoleActions() {
return leftToolbarActionsArray;
}
@Override
public JComponent getComponent() {
return component;
}
@Override
public JComponent getPreferredFocusableComponent() {
return component;
}
@Override
public void dispose() {
}
};
}
}
final DuplexConsoleView<BuildConsoleView, ConsoleView> duplexConsoleView =
new BuildDuplexConsoleView(executionConsole, ((StartBuildEvent)event));
duplexConsoleView.setDisableSwitchConsoleActionOnProcessEnd(false);
duplexConsoleView.getSwitchConsoleActionPresentation().setIcon(AllIcons.Actions.ChangeView);
duplexConsoleView.getSwitchConsoleActionPresentation().setText("Toggle view");
duplexConsoleView.enableConsole(!isConsoleEnabledByDefault());
if (componentContainer == null) {
componentContainer = executionConsole = new BuildTextConsoleView(myProject);
}
final BuildView buildView = new BuildView(myProject, componentContainer, ((StartBuildEvent)event));
buildView.enableView(!isConsoleEnabledByDefault());
if (processHandler != null) {
if (executionConsole instanceof ConsoleView) {
((ConsoleView)executionConsole).attachToProcess(processHandler);
Consumer<ConsoleView> attachedConsoleConsumer = ((StartBuildEvent)event).getAttachedConsoleConsumer();
if (attachedConsoleConsumer != null) {
attachedConsoleConsumer.consume((ConsoleView)executionConsole);
}
}
if (!processHandler.isStartNotified()) {
processHandler.startNotify();
}
((ConsoleView)executionConsole).attachToProcess(processHandler);
Consumer<ConsoleView> attachedConsoleConsumer = ((StartBuildEvent)event).getAttachedConsoleConsumer();
if (attachedConsoleConsumer != null) {
attachedConsoleConsumer.consume((ConsoleView)executionConsole);
}
}
Disposer.register(myThreeComponentsSplitter, duplexConsoleView);
Disposer.register(myThreeComponentsSplitter, buildView);
if (isTabbedView()) {
final JComponent consoleComponent = new JPanel(new BorderLayout());
consoleComponent.add(duplexConsoleView, BorderLayout.CENTER);
consoleComponent.add(buildView, BorderLayout.CENTER);
DefaultActionGroup toolbarActions = new DefaultActionGroup();
consoleComponent.add(ActionManager.getInstance().createActionToolbar(
"", toolbarActions, false).getComponent(), BorderLayout.WEST);
toolbarActions.addAll(duplexConsoleView.createConsoleActions());
toolbarActions.addAll(buildView.createConsoleActions());
myBuildContentManager.addTabbedContent(
consoleComponent, getViewName(), buildInfo.title + ", " + DateFormatUtil.formatDateTime(System.currentTimeMillis()) + " ",
true, AllIcons.CodeStyle.Gear, duplexConsoleView);
true, AllIcons.CodeStyle.Gear, buildView);
}
return duplexConsoleView;
return buildView;
});
if (!isTabbedView() && myThreeComponentsSplitter.getLastComponent() == null) {
@@ -212,15 +258,15 @@ public abstract class AbstractViewManager implements BuildProgressListener, Disp
myBuildsList.getModel().getSize() > 1 &&
myThreeComponentsSplitter.getFirstComponent() == null) {
JBScrollPane scrollPane = new JBScrollPane();
scrollPane.setBorder(new EmptyBorder(0, 0, 0, 0));
scrollPane.setBorder(JBUI.Borders.empty());
scrollPane.setViewportView(myBuildsList);
myThreeComponentsSplitter.setFirstComponent(scrollPane);
myBuildsList.setVisible(true);
myBuildsList.setSelectedIndex(0);
myThreeComponentsSplitter.repaint();
for (DuplexConsoleView<BuildConsoleView, ConsoleView> consoleView : myViewMap.values()) {
BuildConsoleView buildConsoleView = consoleView.getPrimaryConsoleView();
for (BuildView consoleView : myViewMap.values()) {
BuildConsoleView buildConsoleView = consoleView.getPrimaryView();
if (buildConsoleView instanceof BuildTreeConsoleView) {
((BuildTreeConsoleView)buildConsoleView).hideRootNode();
}
@@ -230,7 +276,7 @@ public abstract class AbstractViewManager implements BuildProgressListener, Disp
myThreeComponentsSplitter.setFirstComponent(null);
}
myProgressWatcher.addBuild(buildInfo);
view.getPrimaryConsoleView().print("\r", ConsoleViewContentType.SYSTEM_OUTPUT);
//view.getPrimaryView().print("\r", ConsoleViewContentType.SYSTEM_OUTPUT);
}
else {
if (event instanceof FinishBuildEvent) {
@@ -247,18 +293,18 @@ public abstract class AbstractViewManager implements BuildProgressListener, Disp
runnables.add(() -> {
final BuildInfo buildInfo = myBuildsMap.get(event.getId());
DuplexConsoleView<BuildConsoleView, ConsoleView> view = myViewMap.get(buildInfo);
BuildView view = myViewMap.get(buildInfo);
if (event instanceof OutputBuildEvent) {
ConsoleView consoleView = view.getSecondaryConsoleView();
ComponentContainer consoleView = view.getSecondaryView();
if (consoleView instanceof BuildConsoleView) {
((BuildConsoleView)consoleView).onEvent(event);
}
else {
consoleView.print(event.getMessage(), ConsoleViewContentType.NORMAL_OUTPUT);
else if ((consoleView instanceof ConsoleView)) {
((ConsoleView)consoleView).print(event.getMessage(), ConsoleViewContentType.NORMAL_OUTPUT);
}
}
else {
view.getPrimaryConsoleView().onEvent(event);
view.getPrimaryView().onEvent(event);
}
});
@@ -275,7 +321,7 @@ public abstract class AbstractViewManager implements BuildProgressListener, Disp
BuildInfo selectedBuild = myBuildsList.getSelectedValue();
if (selectedBuild == null) return;
DuplexConsoleView<BuildConsoleView, ConsoleView> view = myViewMap.get(selectedBuild);
BuildView view = myViewMap.get(selectedBuild);
JComponent lastComponent = myThreeComponentsSplitter.getLastComponent();
if (view != null && lastComponent != view.getComponent()) {
myThreeComponentsSplitter.setLastComponent(view.getComponent());
@@ -392,49 +438,61 @@ public abstract class AbstractViewManager implements BuildProgressListener, Disp
}
}
private class BuildDuplexConsoleView extends DuplexConsoleView<BuildConsoleView, ConsoleView> implements DataProvider {
private final ExecutionConsole myExecutionConsole;
private static class BuildView extends CompositeView<BuildConsoleView, ComponentContainer> implements DataProvider {
private final ComponentContainer myComponentContainer;
private final StartBuildEvent myEvent;
public BuildDuplexConsoleView(ExecutionConsole executionConsole, StartBuildEvent event) {
super(new BuildTreeConsoleView(AbstractViewManager.this.myProject), (ConsoleView)executionConsole);
myExecutionConsole = executionConsole;
public BuildView(Project project, ComponentContainer componentContainer, StartBuildEvent event) {
super(new BuildTreeConsoleView(project), componentContainer);
myComponentContainer = componentContainer;
myEvent = event;
}
@NotNull
@Override
public AnAction[] createConsoleActions() {
final DefaultActionGroup textActionGroup = new DefaultActionGroup() {
final DefaultActionGroup rerunActionGroup = new DefaultActionGroup();
AnAction stopAction = null;
if (myEvent.getProcessHandler() != null) {
stopAction = new StopProcessAction("Stop", "Stop", myEvent.getProcessHandler());
}
final DefaultActionGroup consoleActionGroup = new DefaultActionGroup() {
@Override
public void update(AnActionEvent e) {
super.update(e);
e.getPresentation().setVisible(!BuildDuplexConsoleView.this.isPrimaryConsoleEnabled());
e.getPresentation().setVisible(!BuildView.this.isPrimaryConsoleEnabled());
}
};
final AnAction[] consoleActions = ((ConsoleView)myExecutionConsole).createConsoleActions();
for (AnAction anAction : consoleActions) {
textActionGroup.add(anAction);
if (myComponentContainer instanceof BuildConsoleView) {
final AnAction[] consoleActions = ((BuildConsoleView)myComponentContainer).createConsoleActions();
for (AnAction anAction : consoleActions) {
if (anAction instanceof StopAction) {
if (stopAction == null) {
stopAction = anAction;
}
}
else if (!(anAction instanceof FakeRerunAction ||
anAction instanceof PinToolwindowTabAction ||
anAction instanceof CloseAction)) {
consoleActionGroup.add(anAction);
}
}
}
final List<AnAction> anActions = ContainerUtil.newArrayList();
final DefaultActionGroup actionGroup = new DefaultActionGroup();
AnAction[] restartActions = myEvent.getRestartActions();
for (AnAction anAction : restartActions) {
actionGroup.add(anAction);
for (AnAction anAction : myEvent.getRestartActions()) {
rerunActionGroup.add(anAction);
}
if (myEvent.getProcessHandler() != null) {
actionGroup.add(new StopProcessAction("Stop", "Stop", myEvent.getProcessHandler()));
if (stopAction != null) {
rerunActionGroup.add(stopAction);
}
actionGroup.add(rerunActionGroup);
actionGroup.addSeparator();
AnAction[] actions = super.createConsoleActions();
actionGroup.addAll(actions);
if (actions.length > 0) {
actionGroup.addSeparator();
}
anActions.add(actionGroup);
anActions.add(textActionGroup);
return ArrayUtil.toObjectArray(anActions, AnAction.class);
return new AnAction[]{actionGroup, consoleActionGroup};
}
@Nullable
@@ -15,13 +15,14 @@
*/
package com.intellij.build;
import com.intellij.execution.ui.ConsoleView;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.ui.ComponentContainer;
import org.jetbrains.annotations.ApiStatus;
/**
* @author Vladislav.Soroka
*/
@ApiStatus.Experimental
public interface BuildConsoleView extends ConsoleView, BuildProgressListener {
String getViewId();
public interface BuildConsoleView extends ComponentContainer, BuildProgressListener {
AnAction[] createConsoleActions();
}
@@ -38,11 +38,6 @@ public class BuildTextConsoleView extends ConsoleViewImpl implements BuildConsol
super(project, viewer);
}
@Override
public String getViewId() {
return "console";
}
@Override
public void onEvent(BuildEvent event) {
myAnsiEscapeDecoder.escapeText(event.getMessage(), ProcessOutputTypes.STDOUT, this);
@@ -266,11 +266,6 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon
public void dispose() {
}
@Override
public String getViewId() {
return "TREE";
}
@Override
public void onEvent(BuildEvent event) {
ExecutionNode parentNode = event.getParentId() == null ? null : nodesMap.get(event.getParentId());
@@ -0,0 +1,153 @@
/*
* Copyright 2000-2017 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.build;
import com.intellij.execution.console.ConsoleHistoryController;
import com.intellij.execution.console.LanguageConsoleView;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DataProvider;
import com.intellij.openapi.actionSystem.ToggleAction;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.ui.ComponentContainer;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.util.Arrays;
import java.util.List;
/**
* @author Vladislav.Soroka
*/
public class CompositeView<S extends ComponentContainer, T extends ComponentContainer> extends JPanel
implements ComponentContainer, DataProvider {
private final static String PRIMARY_PANEL = "PRIMARY_PANEL";
private final static String SECONDARY_PANEL = "SECONDARY_PANEL";
@NotNull
private final S myPrimaryView;
@NotNull
private final T mySecondaryView;
private boolean myPrimary;
@NotNull
private final SwitchViewAction mySwitchViewAction;
public CompositeView(@NotNull S primaryView, @NotNull T secondaryView) {
super(new CardLayout());
myPrimaryView = primaryView;
mySecondaryView = secondaryView;
add(myPrimaryView.getComponent(), PRIMARY_PANEL);
add(mySecondaryView.getComponent(), SECONDARY_PANEL);
mySwitchViewAction = new SwitchViewAction();
myPrimary = true;
enableView(true);
Disposer.register(this, myPrimaryView);
Disposer.register(this, mySecondaryView);
}
public void enableView(boolean primary) {
if (primary == myPrimary) return;
CardLayout cl = (CardLayout)(getLayout());
cl.show(this, primary ? PRIMARY_PANEL : SECONDARY_PANEL);
IdeFocusManager.getGlobalInstance().doWhenFocusSettlesDown(() -> {
IdeFocusManager.getGlobalInstance().requestFocus(getView(primary).getComponent(), true);
});
myPrimary = primary;
}
public boolean isPrimaryConsoleEnabled() {
return myPrimary;
}
@NotNull
public S getPrimaryView() {
return myPrimaryView;
}
@NotNull
public T getSecondaryView() {
return mySecondaryView;
}
public ComponentContainer getView(boolean primary) {
return primary ? getPrimaryView() : getSecondaryView();
}
@NotNull
public AnAction[] createConsoleActions() {
List<AnAction> actions = ContainerUtil.newArrayList();
actions.add(mySwitchViewAction);
LanguageConsoleView langConsole =
ContainerUtil.findInstance(Arrays.asList(myPrimaryView, mySecondaryView), LanguageConsoleView.class);
ConsoleHistoryController controller = langConsole != null ? ConsoleHistoryController.getController(langConsole) : null;
if (controller != null) actions.add(controller.getBrowseHistory());
return ArrayUtil.toObjectArray(actions, AnAction.class);
}
@Override
public JComponent getComponent() {
return this;
}
@Override
public JComponent getPreferredFocusableComponent() {
return this;
}
@Override
public void dispose() {
}
@Nullable
@Override
public Object getData(@NonNls String dataId) {
final ComponentContainer consoleView = getView(isPrimaryConsoleEnabled());
return consoleView instanceof DataProvider ? ((DataProvider)consoleView).getData(dataId) : null;
}
private class SwitchViewAction extends ToggleAction implements DumbAware {
public SwitchViewAction() {
super("Toggle view", null,
AllIcons.Actions.ChangeView);
}
@Override
public boolean isSelected(final AnActionEvent event) {
return !isPrimaryConsoleEnabled();
}
@Override
public void setSelected(final AnActionEvent event, final boolean flag) {
enableView(!flag);
ApplicationManager.getApplication().invokeLater(() -> update(event));
}
}
}
@@ -18,13 +18,15 @@ package com.intellij.build.events;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.ui.ConsoleView;
import com.intellij.execution.ui.ExecutionConsole;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.util.Consumer;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.function.Supplier;
/**
* @author Vladislav.Soroka
*/
@@ -42,7 +44,7 @@ public interface StartBuildEvent extends StartEvent {
AnAction[] getRestartActions();
@Nullable
ExecutionConsole getExecutionConsole();
Supplier<RunContentDescriptor> getContentDescriptorSupplier();
@Nullable
Consumer<ConsoleView> getAttachedConsoleConsumer();
@@ -19,7 +19,7 @@ import com.intellij.build.events.StartBuildEvent;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.ui.ConsoleView;
import com.intellij.execution.ui.ExecutionConsole;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.util.Consumer;
import com.intellij.util.SmartList;
@@ -28,6 +28,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.List;
import java.util.function.Supplier;
/**
* @author Vladislav.Soroka
@@ -41,9 +42,9 @@ public class StartBuildEventImpl extends StartEventImpl implements StartBuildEve
@NotNull
private List<AnAction> myRestartActions = new SmartList<>();
@Nullable
private ExecutionConsole myExecutionConsole;
@Nullable
private ExecutionEnvironment myExecutionEnvironment;
@Nullable
private Supplier<RunContentDescriptor> myContentDescriptorSupplier;
public StartBuildEventImpl(@NotNull Object eventId,
@NotNull String buildTitle,
@@ -78,8 +79,8 @@ public class StartBuildEventImpl extends StartEventImpl implements StartBuildEve
@Nullable
@Override
public ExecutionConsole getExecutionConsole() {
return myExecutionConsole;
public Supplier<RunContentDescriptor> getContentDescriptorSupplier() {
return myContentDescriptorSupplier;
}
@Nullable
@@ -105,13 +106,13 @@ public class StartBuildEventImpl extends StartEventImpl implements StartBuildEve
return this;
}
public StartBuildEventImpl withConsoleView(ExecutionConsole executionConsole) {
myExecutionConsole = executionConsole;
return this;
}
public StartBuildEventImpl withExecutionEnvironment(ExecutionEnvironment env) {
myExecutionEnvironment = env;
return this;
}
public StartBuildEventImpl withContentDescriptorSupplier(Supplier<RunContentDescriptor> contentDescriptorSupplier) {
myContentDescriptorSupplier = contentDescriptorSupplier;
return this;
}
}
@@ -91,10 +91,10 @@ run.configuration.settings.label.project={0} project:
run.configuration.settings.label.tasks=Tasks:
run.configuration.settings.label.vmoptions=VM options:
run.configuration.settings.label.arguments=Arguments:
run.text.starting.multiple.task={0}: Executing tasks ''{1}''...\n
run.text.starting.single.task={0}: Executing task ''{1}''...\n
run.text.ended.multiple.task={0}: Tasks execution finished ''{1}''.\n
run.text.ended.single.task={0}: Task execution finished ''{1}''.\n
run.text.starting.multiple.task={0}: Executing tasks ''{1}''...
run.text.starting.single.task={0}: Executing task ''{1}''...
run.text.ended.multiple.task={0}: Tasks execution finished ''{1}''.
run.text.ended.single.task={0}: Task execution finished ''{1}''.
run.error.undefined.task=No task to execute is specified
run.invalid.jvm.agent.configuration=Invalid JVM agent configuration used ''{0}''
@@ -16,6 +16,7 @@
package com.intellij.openapi.externalSystem.service.execution;
import com.intellij.build.BuildProgressListener;
import com.intellij.build.BuildViewManager;
import com.intellij.build.TasksViewManager;
import com.intellij.build.events.BuildEvent;
import com.intellij.build.events.impl.FailureResultImpl;
@@ -28,11 +29,14 @@ import com.intellij.execution.configurations.*;
import com.intellij.execution.console.DuplexConsoleView;
import com.intellij.execution.executors.DefaultDebugExecutor;
import com.intellij.execution.impl.ConsoleViewImpl;
import com.intellij.execution.impl.ExecutionManagerImpl;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.process.ProcessOutputTypes;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.runners.FakeRerunAction;
import com.intellij.execution.runners.ProgramRunner;
import com.intellij.execution.ui.ExecutionConsole;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
@@ -76,6 +80,7 @@ import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
@@ -157,7 +162,7 @@ public class ExternalSystemRunConfiguration extends LocatableConfigurationBase i
@Nullable
@Override
public RunProfileState getState(@NotNull Executor executor, @NotNull ExecutionEnvironment env) throws ExecutionException {
public RunProfileState getState(@NotNull Executor executor, @NotNull ExecutionEnvironment env) {
MyRunnableState runnableState =
new MyRunnableState(mySettings, getProject(), DefaultDebugExecutor.EXECUTOR_ID.equals(executor.getId()), this, env);
copyUserDataTo(runnableState);
@@ -188,6 +193,7 @@ public class ExternalSystemRunConfiguration extends LocatableConfigurationBase i
@NotNull private final Project myProject;
@NotNull private final ExternalSystemRunConfiguration myConfiguration;
@NotNull private final ExecutionEnvironment myEnv;
@Nullable private RunContentDescriptor myContentDescriptor;
private final int myDebugPort;
@@ -288,36 +294,16 @@ public class ExternalSystemRunConfiguration extends LocatableConfigurationBase i
public void onStart(@NotNull ExternalSystemTaskId id, String workingDir) {
if (progressListener != null) {
long eventTime = System.currentTimeMillis();
AnAction rerunTaskAction = new AnAction() {
@Override
public void update(@NotNull AnActionEvent e) {
super.update(e);
Presentation p = e.getPresentation();
p.setEnabled(processHandler.isProcessTerminated());
}
@Override
public void actionPerformed(AnActionEvent e) {
try {
MyRunnableState.this.execute(executor, runner);
}
catch (ExecutionException ex) {
LOG.warn(ex);
}
}
};
rerunTaskAction.getTemplatePresentation().setText("Rerun");
rerunTaskAction.getTemplatePresentation().setDescription("Rerun");
rerunTaskAction.getTemplatePresentation().setIcon(AllIcons.Actions.Restart);
AnAction rerunTaskAction = new MyTaskRerunAction(progressListener, myEnv, myContentDescriptor);
progressListener.onEvent(
new StartBuildEventImpl(id, executionName, eventTime, "running...")
.withProcessHandler(processHandler, view -> {
processHandler.notifyTextAvailable(greeting, ProcessOutputTypes.SYSTEM);
processHandler.notifyTextAvailable(greeting + "\n\n", ProcessOutputTypes.SYSTEM);
foldGreetingOrFarewell(consoleView, greeting, true);
})
.withContentDescriptorSupplier(() -> myContentDescriptor)
.withRestartAction(rerunTaskAction)
.withRestartActions(restartActions)
.withConsoleView(consoleView)
.withExecutionEnvironment(myEnv));
}
}
@@ -371,14 +357,18 @@ public class ExternalSystemRunConfiguration extends LocatableConfigurationBase i
farewell =
ExternalSystemBundle.message("run.text.ended.single.task", endDateTime, mySettings.toString());
}
processHandler.notifyTextAvailable(farewell, ProcessOutputTypes.SYSTEM);
processHandler.notifyTextAvailable(farewell + "\n", ProcessOutputTypes.SYSTEM);
foldGreetingOrFarewell(consoleView, farewell, false);
processHandler.notifyProcessTerminated(0);
}
};
task.execute(ArrayUtil.prepend(taskListener, ExternalSystemTaskNotificationListener.EP_NAME.getExtensions()));
});
return new DefaultExecutionResult(null, processHandler);
return new DefaultExecutionResult(consoleView, processHandler);
}
public void setContentDescriptor(@Nullable RunContentDescriptor contentDescriptor) {
myContentDescriptor = contentDescriptor;
}
}
@@ -439,4 +429,49 @@ public class ExternalSystemRunConfiguration extends LocatableConfigurationBase i
});
}
}
private static class MyTaskRerunAction extends FakeRerunAction {
private final BuildProgressListener myProgressListener;
private final RunContentDescriptor myContentDescriptor;
private final ExecutionEnvironment myEnvironment;
public MyTaskRerunAction(BuildProgressListener progressListener,
ExecutionEnvironment environment,
RunContentDescriptor contentDescriptor) {
myProgressListener = progressListener;
myContentDescriptor = contentDescriptor;
myEnvironment = environment;
}
@Override
public void update(@NotNull AnActionEvent event) {
Presentation presentation = event.getPresentation();
ExecutionEnvironment environment = getEnvironment(event);
if (environment != null) {
presentation.setText(ExecutionBundle.message("rerun.configuration.action.name",
StringUtil.escapeMnemonics(environment.getRunProfile().getName())));
Icon icon = ExecutionManagerImpl.isProcessRunning(getDescriptor(event))
? AllIcons.Actions.Restart
: myProgressListener instanceof BuildViewManager
? AllIcons.Actions.Compile
: environment.getExecutor().getIcon();
presentation.setIcon(icon);
presentation.setEnabled(isEnabled(event));
return;
}
presentation.setEnabled(false);
}
@Nullable
@Override
protected RunContentDescriptor getDescriptor(AnActionEvent event) {
return myContentDescriptor != null ? myContentDescriptor : super.getDescriptor(event);
}
@Override
protected ExecutionEnvironment getEnvironment(@NotNull AnActionEvent event) {
return myEnvironment;
}
}
}
@@ -53,7 +53,22 @@ public class ExternalSystemTaskDebugRunner extends GenericDebuggerRunner {
int port = ((ExternalSystemRunConfiguration.MyRunnableState)state).getDebugPort();
if (port > 0) {
RemoteConnection connection = new RemoteConnection(true, "127.0.0.1", String.valueOf(port), true);
return attachVirtualMachine(state, environment, connection, true);
RunContentDescriptor runContentDescriptor = attachVirtualMachine(state, environment, connection, true);
if (runContentDescriptor == null) return null;
((ExternalSystemRunConfiguration.MyRunnableState)state).setContentDescriptor(runContentDescriptor);
RunContentDescriptor descriptor =
new RunContentDescriptor(runContentDescriptor.getExecutionConsole(), runContentDescriptor.getProcessHandler(),
runContentDescriptor.getComponent(), runContentDescriptor.getDisplayName(),
runContentDescriptor.getIcon(), runContentDescriptor.getActivationCallback(),
runContentDescriptor.getRestartActions()) {
@Override
public boolean isHiddenContent() {
return true;
}
};
descriptor.setRunnerLayoutUi(runContentDescriptor.getRunnerLayoutUi());
return descriptor;
}
else {
LOG.warn("Can't attach debugger to external system task execution. Reason: target debug port is unknown");
@@ -22,6 +22,7 @@ import com.intellij.execution.configurations.RunnerSettings
import com.intellij.execution.executors.DefaultRunExecutor
import com.intellij.execution.runners.ExecutionEnvironment
import com.intellij.execution.runners.GenericProgramRunner
import com.intellij.execution.runners.RunContentBuilder
import com.intellij.execution.ui.RunContentDescriptor
import com.intellij.openapi.externalSystem.util.ExternalSystemConstants
import javax.swing.JComponent
@@ -41,12 +42,22 @@ class ExternalSystemTaskRunner : GenericProgramRunner<RunnerSettings>() {
@Throws(ExecutionException::class)
override fun doExecute(state: RunProfileState, environment: ExecutionEnvironment): RunContentDescriptor? {
val executionResult = state.execute(environment.executor, this) ?: return null
if (state !is ExternalSystemRunConfiguration.MyRunnableState) return null
return object : RunContentDescriptor(executionResult.executionConsole, executionResult.processHandler,
EMPTY_COMPONENT, environment.runProfile.name, null) {
override fun isHiddenContent() = true
val executionResult = state.execute(environment.executor, this) ?: return null
val runContentDescriptor = RunContentBuilder(executionResult, environment).showRunContent(environment.contentToReuse) ?: return null
state.setContentDescriptor(runContentDescriptor)
val descriptor = object : RunContentDescriptor(runContentDescriptor.executionConsole, runContentDescriptor.processHandler,
runContentDescriptor.component, runContentDescriptor.displayName,
runContentDescriptor.icon, runContentDescriptor.activationCallback,
runContentDescriptor.restartActions) {
override fun isHiddenContent(): Boolean {
return true
}
}
descriptor.runnerLayoutUi = runContentDescriptor.runnerLayoutUi
return descriptor
}
companion object {
@@ -567,8 +567,7 @@ public class ExternalSystemUtil {
}
public void cancellImport() {
ApplicationManager.getApplication().executeOnPooledThread(
(Runnable)() -> myTask.cancel(ExternalSystemTaskNotificationListener.EP_NAME.getExtensions()));
myTask.cancel(ExternalSystemTaskNotificationListener.EP_NAME.getExtensions());
}
};