simplify ChooseRunConfigurationPopup sort logic and fix .ArrayIndexOutOfBoundsException: -1 (if result is empty)

add test
This commit is contained in:
Vladimir Krivosheev
2018-11-28 18:40:38 +01:00
parent 69fbc1552a
commit def7238ea8
2 changed files with 127 additions and 63 deletions
@@ -1,6 +1,8 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.execution.impl
import com.intellij.execution.actions.ChooseRunConfigurationPopup
import com.intellij.execution.actions.ExecutorProvider
import com.intellij.execution.application.ApplicationConfigurationType
import com.intellij.execution.impl.RunConfigurableNodeKind.*
import com.intellij.execution.junit.JUnitConfigurationType
@@ -195,25 +197,26 @@ internal class RunConfigurableTest {
model.drop(2, 14, ABOVE)
assertThat(configurable.isModified).isTrue()
configurable.apply()
assertThat(configurable.runManager.allSettings.map { it.name }).containsExactly("Renamer",
"UI",
"AuTest",
"Simples",
"OutAndErr",
"C148C_TersePrincess",
"Periods",
"C148E_Porcelain",
"ErrAndOut",
"CodeGenerator",
"All in titled",
"All in titled2",
"All in titled3",
"All in titled4",
"All in titled5")
val runManager = configurable.runManager
assertThat(runManager.allSettings.map { it.name }).containsExactly("Renamer",
"UI",
"AuTest",
"Simples",
"OutAndErr",
"C148C_TersePrincess",
"Periods",
"C148E_Porcelain",
"ErrAndOut",
"CodeGenerator",
"All in titled",
"All in titled2",
"All in titled3",
"All in titled4",
"All in titled5")
assertThat(configurable.isModified).isFalse()
model.drop(4, 8, BELOW)
configurable.apply()
assertThat(configurable.runManager.allSettings.joinToString("\n") { "[${it.type.displayName}] [${it.folderName ?: ""}] ${it.name}" }).isEqualTo("""
assertThat(runManager.allSettings.joinToString("\n") { "[${it.type.displayName}] [${it.folderName ?: ""}] ${it.name}" }).isEqualTo("""
[Application] [1] Renamer
[Application] [1] UI
[Application] [1] Simples
@@ -230,5 +233,41 @@ internal class RunConfigurableTest {
[JUnit] [5] All in titled4
[JUnit] [] All in titled5
""".trimIndent())
val executorProvider = ExecutorProvider { throw UnsupportedOperationException() }
assertThat(ChooseRunConfigurationPopup.createSettingsList(runManager, executorProvider, false, false).joinToString("\n") {
val value = it.value
if (value is String) {
"[$value]"
}
else {
it.value!!.toString()
}
}).isEqualTo("""
[1]
[2 (mnemonic is to "AuTest")]
[3]
Application: CodeGenerator (level: WORKSPACE)
[4]
[5]
JUnit: All in titled5 (level: TEMPORARY)
""".trimIndent())
assertThat(ChooseRunConfigurationPopup.createSettingsList(runManager, executorProvider, false, true).joinToString("\n") {
val value = it.value
if (value is String) {
"[$value]"
}
else {
it.value!!.toString()
}
}).isEqualTo("""
[1]
[2 (mnemonic is to "AuTest")]
[3]
[4]
[5]
Application: CodeGenerator (level: WORKSPACE)
JUnit: All in titled5 (level: TEMPORARY)
""".trimIndent())
}
}
@@ -4,7 +4,6 @@ package com.intellij.execution.actions;
import com.intellij.execution.*;
import com.intellij.execution.configurations.ConfigurationType;
import com.intellij.execution.configurations.UnknownConfigurationType;
import com.intellij.execution.impl.EditConfigurationsDialog;
import com.intellij.execution.impl.RunDialog;
import com.intellij.execution.impl.RunManagerImpl;
@@ -33,11 +32,12 @@ import com.intellij.ui.popup.WizardPopup;
import com.intellij.ui.popup.list.ListPopupImpl;
import com.intellij.ui.popup.list.PopupListElementRenderer;
import com.intellij.ui.speedSearch.SpeedSearch;
import com.intellij.util.ObjectUtils;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import javax.swing.*;
import java.awt.*;
@@ -47,8 +47,6 @@ import java.awt.event.MouseEvent;
import java.util.List;
import java.util.*;
import static com.intellij.execution.impl.RunConfigurationListManagerHelperKt.compareTypesForUi;
public class ChooseRunConfigurationPopup implements ExecutorProvider {
private final Project myProject;
@@ -917,14 +915,26 @@ public class ChooseRunConfigurationPopup implements ExecutorProvider {
}
@NotNull
public static List<ItemWrapper> createSettingsList(@NotNull Project project, @NotNull ExecutorProvider executorProvider, boolean isCreateEditAction) {
public static List<ItemWrapper> createSettingsList(@NotNull Project project,
@NotNull ExecutorProvider executorProvider,
boolean isCreateEditAction) {
//noinspection TestOnlyProblems
return createSettingsList(RunManagerImpl.getInstanceImpl(project), executorProvider, isCreateEditAction, Registry.is("run.popup.move.folders.to.top", false));
}
@TestOnly
@NotNull
public static List<ItemWrapper> createSettingsList(@NotNull RunManagerImpl runManager,
@NotNull ExecutorProvider executorProvider,
boolean isCreateEditAction,
boolean isMoveFoldersToTop) {
List<ItemWrapper> result = new ArrayList<>();
if (isCreateEditAction) {
result.add(createEditAction());
}
RunManagerImpl runManager = RunManagerImpl.getInstanceImpl(project);
Project project = runManager.getProject();
final RunnerAndConfigurationSettings selectedConfiguration = runManager.getSelectedConfiguration();
if (selectedConfiguration != null) {
addActionsForSelected(selectedConfiguration, project, result);
@@ -933,65 +943,80 @@ public class ChooseRunConfigurationPopup implements ExecutorProvider {
Map<RunnerAndConfigurationSettings, ItemWrapper> wrappedExisting = new LinkedHashMap<>();
List<FolderWrapper> folderWrappers = new SmartList<>();
for (Map<String, List<RunnerAndConfigurationSettings>> folderToConfigurations : runManager.getConfigurationsGroupedByTypeAndFolder(false).values()) {
for (Map.Entry<String, List<RunnerAndConfigurationSettings>> entry : folderToConfigurations.entrySet()) {
final String folderName = entry.getKey();
List<RunnerAndConfigurationSettings> configurations = entry.getValue();
if (folderName != null) {
boolean isSelected = configurations.contains(selectedConfiguration);
if (isSelected) {
assert selectedConfiguration != null;
if (isMoveFoldersToTop) {
for (Map.Entry<String, List<RunnerAndConfigurationSettings>> entry : folderToConfigurations.entrySet()) {
final String folderName = entry.getKey();
List<RunnerAndConfigurationSettings> configurations = entry.getValue();
if (folderName != null) {
folderWrappers.add(createFolderItem(project, executorProvider, selectedConfiguration, folderName, configurations));
}
FolderWrapper folderWrapper = new FolderWrapper(project, executorProvider,
folderName + (isSelected ? " (mnemonic is to \"" + selectedConfiguration.getName() + "\")" : ""),
configurations);
if (isSelected) {
folderWrapper.setMnemonic(1);
}
folderWrappers.add(folderWrapper);
}
else {
for (RunnerAndConfigurationSettings configuration : configurations) {
final ItemWrapper wrapped = ItemWrapper.wrap(project, configuration);
if (configuration == selectedConfiguration) {
wrapped.setMnemonic(1);
else {
for (RunnerAndConfigurationSettings configuration : configurations) {
wrapAndAdd(project, configuration, selectedConfiguration, wrappedExisting);
}
wrappedExisting.put(configuration, wrapped);
}
}
}
else {
// add only folders
for (Map.Entry<String, List<RunnerAndConfigurationSettings>> entry : folderToConfigurations.entrySet()) {
final String folderName = entry.getKey();
if (folderName != null) {
result.add(createFolderItem(project, executorProvider, selectedConfiguration, folderName, entry.getValue()));
}
}
// add configurations
List<RunnerAndConfigurationSettings> configurations = folderToConfigurations.get(null);
if (!ContainerUtil.isEmpty(configurations)) {
for (RunnerAndConfigurationSettings configuration : configurations) {
result.add(wrapAndAdd(project, configuration, selectedConfiguration, wrappedExisting));
}
}
}
}
boolean isMoveFoldersToTop = Registry.is("run.popup.move.folders.to.top", false);
if (isMoveFoldersToTop) {
result.addAll(folderWrappers);
}
if (!DumbService.isDumb(project)) {
populateWithDynamicRunners(result, wrappedExisting, project, RunManagerEx.getInstanceEx(project), selectedConfiguration);
}
result.addAll(wrappedExisting.values());
if (!isMoveFoldersToTop) {
addFolders(result, folderWrappers);
if (isMoveFoldersToTop) {
result.addAll(wrappedExisting.values());
}
return result;
}
private static void addFolders(@NotNull List<ItemWrapper> result, @NotNull List<FolderWrapper> folderWrappers) {
final int topIndex = result.size() - 1;
for (FolderWrapper folderWrapper : folderWrappers) {
int bestIndex = topIndex;
for (int index = topIndex; index < result.size(); index++) {
bestIndex = index;
ItemWrapper item = result.get(index);
ConfigurationType currentType = item.getType();
int m = currentType == null
? 1
: compareTypesForUi(ObjectUtils.notNull(folderWrapper.getType(), UnknownConfigurationType.getInstance()), currentType);
if (m < 0 || (m == 0 && !(item instanceof FolderWrapper))) {
break;
}
}
result.add(bestIndex, folderWrapper);
@NotNull
private static ItemWrapper wrapAndAdd(@NotNull Project project,
@NotNull RunnerAndConfigurationSettings configuration,
@Nullable RunnerAndConfigurationSettings selectedConfiguration,
@NotNull Map<RunnerAndConfigurationSettings, ItemWrapper> wrappedExisting) {
ItemWrapper wrapped = ItemWrapper.wrap(project, configuration);
if (configuration == selectedConfiguration) {
wrapped.setMnemonic(1);
}
wrappedExisting.put(configuration, wrapped);
return wrapped;
}
@NotNull
private static FolderWrapper createFolderItem(@NotNull Project project,
@NotNull ExecutorProvider executorProvider,
@Nullable RunnerAndConfigurationSettings selectedConfiguration,
@NotNull String folderName,
@NotNull List<RunnerAndConfigurationSettings> configurations) {
boolean isSelected = selectedConfiguration != null && configurations.contains(selectedConfiguration);
String value = folderName;
if (isSelected) {
value += " (mnemonic is to \"" + selectedConfiguration.getName() + "\")";
}
FolderWrapper result = new FolderWrapper(project, executorProvider, value, configurations);
if (isSelected) {
result.setMnemonic(1);
}
return result;
}
private static void addActionsForSelected(@NotNull RunnerAndConfigurationSettings selectedConfiguration, @NotNull Project project, @NotNull List<ItemWrapper> result) {