IDEA-94341 Launch Multiple "Run/Debug Configurations" At Once

This commit is contained in:
Vassiliy.Kudryashov
2015-07-04 00:05:09 +03:00
parent 9712ae7820
commit 68aade1bf9
11 changed files with 348 additions and 19 deletions
@@ -0,0 +1,142 @@
/*
* Copyright 2000-2015 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.compound;
import com.intellij.execution.*;
import com.intellij.execution.configurations.*;
import com.intellij.execution.impl.RunManagerImpl;
import com.intellij.execution.impl.RunnerAndConfigurationSettingsImpl;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.runners.ExecutionEnvironmentBuilder;
import com.intellij.execution.runners.ProgramRunner;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.options.SettingsEditor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.WriteExternalException;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
public class CompoundRunConfiguration extends RunConfigurationBase implements WithoutOwnBeforeRunSteps {
static final Comparator<RunConfiguration> COMPARATOR = new Comparator<RunConfiguration>() {
@Override
public int compare(RunConfiguration o1, RunConfiguration o2) {
int i = o1.getType().getDisplayName().compareTo(o2.getType().getDisplayName());
return (i != 0) ? i : o1.getName().compareTo(o2.getName());
}
};
private final Set<Pair<String, String>> myPairs = new HashSet<Pair<String, String>>();
private final Set<RunConfiguration> mySetToRun = new TreeSet<RunConfiguration>(COMPARATOR);
private boolean myInitialized = false;
public CompoundRunConfiguration(Project project, @NotNull CompoundRunConfigurationType type, String name) {
super(project, type.getConfigurationFactories()[0], name);
}
public Set<RunConfiguration> getSetToRun() {
initIfNeed();
return mySetToRun;
}
private void initIfNeed() {
if (myInitialized) return;
mySetToRun.clear();
RunManagerImpl manager = RunManagerImpl.getInstanceImpl(getProject());
for (Pair<String, String> pair : myPairs) {
RunnerAndConfigurationSettings settings = manager.findConfigurationByTypeAndName(pair.first, pair.second);
if (settings != null) {
mySetToRun.add(settings.getConfiguration());
}
}
myInitialized = true;
}
@NotNull
@Override
public SettingsEditor<? extends RunConfiguration> getConfigurationEditor() {
return new CompoundRunConfigurationSettingsEditor(getProject());
}
@Override
public void checkConfiguration() throws RuntimeConfigurationException {
if (getSetToRun().isEmpty()) throw new RuntimeConfigurationException("There is nothing to run");
for (RunConfiguration configuration : getSetToRun()) {
configuration.checkConfiguration();
}
}
@Nullable
@Override
public RunProfileState getState(@NotNull Executor executor, @NotNull final ExecutionEnvironment environment) throws ExecutionException {
try {
checkConfiguration();
}
catch (RuntimeConfigurationException e) {
throw new ExecutionException(e.getMessage());
}
return new RunProfileState() {
@Nullable
@Override
public ExecutionResult execute(final Executor executor, @NotNull ProgramRunner runner) throws ExecutionException {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
RunManagerImpl manager = RunManagerImpl.getInstanceImpl(getProject());
for (RunConfiguration configuration : getSetToRun()) {
RunnerAndConfigurationSettings settings = new RunnerAndConfigurationSettingsImpl(manager, configuration, false);
ExecutionEnvironmentBuilder builder = ExecutionEnvironmentBuilder.createOrNull(executor, settings);
if (builder != null) {
ExecutionManager.getInstance(getProject())
.restartRunProfile(builder.activeTarget().dataContext(null).build());
}
}
}
});
return null;
}
};
}
@Override
public void readExternal(Element element) throws InvalidDataException {
super.readExternal(element);
myPairs.clear();
List<Element> children = element.getChildren("toRun");
for (Element child : children) {
String type = child.getAttributeValue("type");
String name = child.getAttributeValue("name");
if (type != null && name != null) {
myPairs.add(Pair.create(type, name));
}
}
}
@Override
public void writeExternal(Element element) throws WriteExternalException {
super.writeExternal(element);
initIfNeed();
for (RunConfiguration configuration : getSetToRun()) {
Element child = new Element("toRun");
child.setAttribute("type", configuration.getType().getId());
child.setAttribute("name", configuration.getName());
element.addContent(child);
}
}
}
@@ -0,0 +1,111 @@
/*
* Copyright 2000-2015 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.compound;
import com.intellij.execution.BeforeRunTask;
import com.intellij.execution.RunnerAndConfigurationSettings;
import com.intellij.execution.configurations.RunConfiguration;
import com.intellij.execution.impl.RunConfigurationBeforeRunProvider;
import com.intellij.execution.impl.RunManagerImpl;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.SettingsEditor;
import com.intellij.openapi.project.Project;
import com.intellij.ui.CheckBoxList;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.util.*;
public class CompoundRunConfigurationSettingsEditor extends SettingsEditor<CompoundRunConfiguration>{
@NotNull private final Project myProject;
private final CheckBoxList<RunConfiguration> myList;
private List<RunConfiguration> myChecked = new ArrayList<RunConfiguration>();
private final RunManagerImpl myRunManager;
public CompoundRunConfigurationSettingsEditor(@NotNull Project project) {
myProject = project;
myRunManager = RunManagerImpl.getInstanceImpl(myProject);
myList = new CheckBoxList<RunConfiguration>() {
@Override
protected void adjustRendering(JCheckBox checkBox, int index, boolean selected, boolean hasFocus) {
RunConfiguration configuration = getItemAt(index);
assert configuration != null;
checkBox.setText(configuration.getType().getDisplayName() + " '"+configuration.getName()+"'");
}
};
myList.setVisibleRowCount(100);
}
private void updateModel(@NotNull CompoundRunConfiguration s) {
List<RunConfiguration> list = myRunManager.getAllConfigurationsList();
Collections.sort(list, CompoundRunConfiguration.COMPARATOR);
for (RunConfiguration configuration : list) {
if (canBeAdded(configuration, s)) {
myList.addItem(configuration, configuration.getName(), myChecked.contains(configuration));
}
}
}
private boolean canBeAdded(@NotNull RunConfiguration candidate, @NotNull final CompoundRunConfiguration root) {
if (candidate == root) return false;
List<BeforeRunTask> tasks = myRunManager.getBeforeRunTasks(candidate);
for (BeforeRunTask task : tasks) {
if (task instanceof RunConfigurationBeforeRunProvider.RunConfigurableBeforeRunTask) {
RunConfigurationBeforeRunProvider.RunConfigurableBeforeRunTask runTask
= (RunConfigurationBeforeRunProvider.RunConfigurableBeforeRunTask)task;
RunnerAndConfigurationSettings settings = runTask.getSettings();
if (settings != null) {
if (!canBeAdded(settings.getConfiguration(), root)) return false;
}
}
}
if (candidate instanceof CompoundRunConfiguration) {
Set<RunConfiguration> set = ((CompoundRunConfiguration)candidate).getSetToRun();
for (RunConfiguration configuration : set) {
if (!canBeAdded(configuration, root)) return false;
}
}
return true;
}
@Override
protected void resetEditorFrom(CompoundRunConfiguration s) {
myChecked.clear();
myChecked.addAll(s.getSetToRun());
updateModel(s);
}
@Override
protected void applyEditorTo(CompoundRunConfiguration s) throws ConfigurationException {
Set<RunConfiguration> checked = new HashSet<RunConfiguration>();
for (int i = 0; i < myList.getItemsCount(); i++) {
RunConfiguration configuration = myList.getItemAt(i);
if (myList.isItemSelected(configuration)) {
checked.add(configuration);
}
}
Set<RunConfiguration> toRun = s.getSetToRun();
toRun.clear();
toRun.addAll(checked);
}
@NotNull
@Override
protected JComponent createEditor() {
return myList;//new JBScrollPane(myList, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
}
}
@@ -0,0 +1,51 @@
/*
* Copyright 2000-2015 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.compound;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.execution.configurations.ConfigurationTypeBase;
import com.intellij.execution.configurations.ConfigurationTypeUtil;
import com.intellij.execution.configurations.RunConfiguration;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.project.Project;
import com.intellij.ui.LayeredIcon;
public class CompoundRunConfigurationType extends ConfigurationTypeBase {
public static CompoundRunConfigurationType getInstance() {
return ConfigurationTypeUtil.findConfigurationType(CompoundRunConfigurationType.class);
}
public CompoundRunConfigurationType() {
super("CompoundRunConfigurationType",
"Compound Run Configuration",
"It runs batch of run configurations at once",
LayeredIcon.create(AllIcons.Nodes.Folder, AllIcons.Nodes.RunnableMark));
addFactory(new ConfigurationFactory(this) {
@Override
public RunConfiguration createTemplateConfiguration(Project project) {
return new CompoundRunConfiguration(project, CompoundRunConfigurationType.this, "Compound Run Configuration");
}
@Override
public String getName() {
return super.getName();
}
});
}
}
@@ -37,7 +37,7 @@ import java.util.concurrent.atomic.AtomicInteger;
/**
* @author spleaner
*/
public class UnknownRunConfiguration implements RunConfiguration {
public class UnknownRunConfiguration implements RunConfiguration, WithoutOwnBeforeRunSteps {
private final ConfigurationFactory myFactory;
private Element myStoredElement;
private String myName;
@@ -0,0 +1,22 @@
/*
* Copyright 2000-2015 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.configurations;
/**
* Marker interface to NOT show "Before launch" section in Run/Debug Configuration editor
*/
public interface WithoutOwnBeforeRunSteps {
}
@@ -18,6 +18,6 @@ package com.intellij.execution.configurations;
/**
* Allow to get before/after steps from wrapped configuration: e.g. to rerun tests with initial tests before options
*/
public interface WrappingRunConfiguration<T extends RunConfiguration> {
public interface WrappingRunConfiguration<T extends RunConfiguration> extends WithoutOwnBeforeRunSteps {
T getPeer();
}
@@ -18,7 +18,7 @@ package com.intellij.execution.impl;
import com.intellij.execution.BeforeRunTask;
import com.intellij.execution.RunnerAndConfigurationSettings;
import com.intellij.execution.configurations.RunConfiguration;
import com.intellij.execution.configurations.UnknownRunConfiguration;
import com.intellij.execution.configurations.WithoutOwnBeforeRunSteps;
import com.intellij.execution.runners.ProgramRunner;
import com.intellij.ide.DataManager;
import com.intellij.ide.util.PropertiesComponent;
@@ -92,7 +92,7 @@ public class ConfigurationSettingsEditorWrapper extends SettingsEditor<RunnerAnd
private void doReset(RunnerAndConfigurationSettings settings) {
final RunConfiguration runConfiguration = settings.getConfiguration();
myBeforeRunStepsPanel.doReset(settings);
myBeforeLaunchContainer.setVisible(!(runConfiguration instanceof UnknownRunConfiguration));
myBeforeLaunchContainer.setVisible(!(runConfiguration instanceof WithoutOwnBeforeRunSteps));
}
@Override
@@ -16,7 +16,6 @@
package com.intellij.execution.impl;
import com.intellij.execution.*;
import com.intellij.execution.configurations.ConfigurationType;
import com.intellij.execution.configurations.RunConfiguration;
import com.intellij.execution.executors.DefaultRunExecutor;
import com.intellij.execution.process.ProcessAdapter;
@@ -305,16 +304,8 @@ extends BeforeRunTaskProvider<RunConfigurationBeforeRunProvider.RunConfigurableB
if (myInitialized) {
return;
}
if (myConfigurationName != null && myConfigurationType != null) {
for (RunnerAndConfigurationSettings runConfiguration : RunManagerImpl.getInstanceImpl(myProject).getSortedConfigurations()) {
ConfigurationType type = runConfiguration.getType();
if (myConfigurationName.equals(runConfiguration.getName())
&& type != null
&& myConfigurationType.equals(type.getId())) {
setSettings(runConfiguration);
return;
}
}
if (myConfigurationType != null && myConfigurationName != null) {
setSettings(RunManagerImpl.getInstanceImpl(myProject).findConfigurationByTypeAndName(myConfigurationType, myConfigurationName));
}
}
@@ -323,7 +314,7 @@ extends BeforeRunTaskProvider<RunConfigurationBeforeRunProvider.RunConfigurableB
myInitialized = true;
}
RunnerAndConfigurationSettings getSettings() {
public RunnerAndConfigurationSettings getSettings() {
init();
return mySettings;
}
@@ -1135,6 +1135,17 @@ public class RunManagerImpl extends RunManagerEx implements PersistentStateCompo
return null;
}
@Nullable
public RunnerAndConfigurationSettings findConfigurationByTypeAndName(@NotNull String typeId, @NotNull String name) {
for (RunnerAndConfigurationSettings settings : getSortedConfigurations()) {
ConfigurationType t = settings.getType();
if (t != null && typeId.equals(t.getId()) && name.equals(settings.getName())) {
return settings;
}
}
return null;
}
@NotNull
@Override
public <T extends BeforeRunTask> List<T> getBeforeRunTasks(RunConfiguration settings, Key<T> taskProviderID) {
@@ -127,7 +127,7 @@ public class CheckBoxList<T> extends JBList {
}
public boolean isItemSelected(int index) {
return ((JCheckBox)getModel().getElementAt(index)).isSelected();
return ((JCheckBox)getModel().getElementAt(index)).isSelected();
}
public boolean isItemSelected(T item) {
@@ -163,7 +163,7 @@ public class CheckBoxList<T> extends JBList {
this.checkBoxListListener = checkBoxListListener;
}
protected void adjustRendering(final JCheckBox checkBox, final boolean selected, final boolean hasFocus) {
protected void adjustRendering(final JCheckBox checkBox, int index, final boolean selected, final boolean hasFocus) {
}
private class CellRenderer implements ListCellRenderer {
@@ -224,7 +224,7 @@ public class CheckBoxList<T> extends JBList {
rootComponent.setBorder(isSelected ? mySelectedBorder : myBorder);
adjustRendering(checkbox, isSelected, cellHasFocus);
adjustRendering(checkbox, index, isSelected, cellHasFocus);
return rootComponent;
}
}
+1
View File
@@ -1291,6 +1291,7 @@
<runConfigurationProducer implementation="com.intellij.execution.jar.JarApplicationConfigurationProducer"/>
<runConfigurationProducer implementation="com.intellij.execution.application.ApplicationConfigurationProducer"/>
<configurationType implementation="com.intellij.execution.remote.RemoteConfigurationType"/>
<configurationType implementation="com.intellij.execution.compound.CompoundRunConfigurationType"/>
<codeInsight.lineMarkerProvider language="JAVA" implementationClass="com.intellij.execution.application.ApplicationRunLineMarkerProvider"/>
<pathMacroFilter implementation="com.intellij.execution.configuration.JavaRunConfigurationPathMacroFilter"/>