IDEA-98563 isAllowRunningInParallel DSL property if someone wants to set old behavior on a factory level

This commit is contained in:
Vladimir Krivosheev
2018-09-09 00:48:19 +02:00
parent 84a2b25d62
commit 2068d76294
21 changed files with 121 additions and 88 deletions
@@ -12,7 +12,7 @@ import org.jetbrains.annotations.Nullable;
* settings.
*
* @author anna
* @see RunManager#createConfiguration(String, com.intellij.execution.configurations.ConfigurationFactory)
* @see RunManager#createConfiguration(String, ConfigurationFactory)
*/
public interface RunnerAndConfigurationSettings {
/**
@@ -129,7 +129,7 @@ public interface RunnerAndConfigurationSettings {
/**
* @deprecated
* @see ExecutionTargetManager#canRun(com.intellij.execution.RunnerAndConfigurationSettings, com.intellij.execution.ExecutionTarget)
* @see ExecutionTargetManager#canRun(RunnerAndConfigurationSettings, ExecutionTarget)
*/
@Deprecated
@SuppressWarnings({"DeprecatedIsStillUsed", "unused"})
@@ -172,16 +172,20 @@ public interface RunnerAndConfigurationSettings {
boolean isActivateToolWindowBeforeRun();
/**
* Returns the "Single instance only" flag (meaning that only one instance of this run configuration can be run at the same time).
* @deprecated Use {@link RunConfiguration#isAllowRunningInParallel()}
*/
boolean isSingleton();
@Deprecated
default boolean isSingleton() {
return !getConfiguration().isAllowRunningInParallel();
}
/**
* Sets the "Single instance only" flag (meaning that only one instance of this run configuration can be run at the same time).
*
* @param singleton the "Single instance" flag.
* @deprecated Use {@link RunConfiguration#setAllowRunningInParallel(boolean)}}
*/
void setSingleton(boolean singleton);
@Deprecated
default void setSingleton(boolean value) {
getConfiguration().setAllowRunningInParallel(!value);
}
/**
* Sets the name of the folder under which the configuration is displayed in the "Run/Debug Configurations" dialog.
@@ -134,6 +134,14 @@ public abstract class ModuleBasedConfiguration<ConfigurationModule extends RunCo
RunConfigurationModule configurationModule = configuration.getConfigurationModule();
String moduleName = StringUtil.nullize(configurationModule.getModuleName());
configuration.readExternal(element);
// we don't call super.clone(), but writeExternal doesn't copy transient fields in the options like isAllowRunningInParallel
// so, we have to call copyFrom to ensure that state is fully cloned
// MUST BE AFTER readExternal because readExternal set options to a new instance
ModuleBasedConfigurationOptions clonedOptions = configuration.getOptions();
clonedOptions.copyFrom(getOptions());
clonedOptions.resetModificationCount();
if (moduleName != null && StringUtil.nullize(configurationModule.getModuleName()) == null) {
configurationModule.setModuleName(moduleName);
}
@@ -161,4 +161,11 @@ public interface RunConfiguration extends RunProfile, Cloneable {
default void setBeforeRunTasks(@NotNull List<BeforeRunTask<?>> value) {
}
default boolean isAllowRunningInParallel() {
return false;
}
default void setAllowRunningInParallel(boolean value) {
}
}
@@ -137,6 +137,7 @@ public abstract class RunConfigurationBase extends UserDataHolderBase implements
runConfiguration.myOptions = createOptions();
runConfiguration.myOptions.copyFrom(myOptions);
runConfiguration.myOptions.resetModificationCount();
copyCopyableDataTo(runConfiguration);
myBeforeRunTasks = myBeforeRunTasks.isEmpty() ? Collections.emptyList() : new SmartList<>(myBeforeRunTasks);
@@ -324,6 +325,16 @@ public abstract class RunConfigurationBase extends UserDataHolderBase implements
return false;
}
@Override
public final boolean isAllowRunningInParallel() {
return getOptions().isAllowRunningInParallel();
}
@Override
public final void setAllowRunningInParallel(boolean value) {
getOptions().setAllowRunningInParallel(value);
}
/**
* Called when configuration created via UI (Add Configuration).
* Suitable to perform some initialization tasks (in most cases it is indicator that you do something wrong, so, please override this method with care and only if really need).
@@ -25,6 +25,10 @@ open class RunConfigurationOptions : BaseState() {
@get:Property(surroundWithTag = false)
@get:XCollection
var logFiles by list<LogFileOptions>()
@com.intellij.configurationStore.Property(description = "Allow running in parallel")
@get:Transient
var isAllowRunningInParallel by property(false)
}
open class LocatableRunConfigurationOptions : RunConfigurationOptions() {
@@ -18,8 +18,8 @@ enum class RunConfigurationSingletonPolicy {
val isPolicyConfigurable: Boolean
get() = this != SINGLE_INSTANCE_ONLY && this != MULTIPLE_INSTANCE_ONLY
val isSingleton: Boolean
get() = this == SINGLE_INSTANCE || this == SINGLE_INSTANCE_ONLY
val isAllowRunningInParallel: Boolean
get() = this == MULTIPLE_INSTANCE || this == MULTIPLE_INSTANCE_ONLY
}
inline fun <reified T : ConfigurationType> runConfigurationType(): T = ConfigurationTypeUtil.findConfigurationType(T::class.java)
@@ -286,7 +286,7 @@ public class ExecutorRegistryImpl extends ExecutorRegistry implements Disposable
return contentDescriptor != null && executionManager.getExecutors(contentDescriptor).contains(myExecutor);
});
if (!runningDescriptors.isEmpty() && DefaultRunExecutor.EXECUTOR_ID.equals(myExecutor.getId()) && selectedConfiguration.isSingleton()) {
if (!configuration.isAllowRunningInParallel() && !runningDescriptors.isEmpty() && DefaultRunExecutor.EXECUTOR_ID.equals(myExecutor.getId())) {
return AllIcons.Actions.Restart;
}
if (runningDescriptors.isEmpty()) {
@@ -194,7 +194,7 @@ class CompoundRunConfiguration @JvmOverloads constructor(project: Project, name:
}
val settings = manager.findConfigurationByTypeAndName(configuration.type, configuration.name)
if (settings != null && settings.isSingleton && configuration == s.configuration) {
if (settings != null && !settings.configuration.isAllowRunningInParallel && configuration == s.configuration) {
return@getRunningDescriptors true
}
}
@@ -1,25 +1,11 @@
/*
* 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.
*/
// 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.dashboard.actions;
import com.intellij.execution.*;
import com.intellij.execution.configurations.RuntimeConfigurationError;
import com.intellij.execution.configurations.RuntimeConfigurationException;
import com.intellij.execution.dashboard.RunDashboardRunConfigurationNode;
import com.intellij.execution.dashboard.RunDashboardManager;
import com.intellij.execution.dashboard.RunDashboardRunConfigurationNode;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.runners.ProgramRunner;
import com.intellij.execution.ui.RunContentDescriptor;
@@ -81,9 +67,13 @@ public abstract class ExecutorAction extends RunDashboardTreeLeafAction<RunDashb
private static boolean isStarting(Project project, RunnerAndConfigurationSettings configurationSettings, String executorId, String runnerId) {
ExecutorRegistry executorRegistry = ExecutorRegistry.getInstance();
if (executorRegistry.isStarting(project, executorId, runnerId)) return true;
if (executorRegistry.isStarting(project, executorId, runnerId)) {
return true;
}
if (!configurationSettings.isSingleton()) return false;
if (configurationSettings.getConfiguration().isAllowRunningInParallel()) {
return false;
}
for (Executor executor : executorRegistry.getRegisteredExecutors()) {
if (executor.getId().equals(executorId)) continue;
@@ -365,7 +365,7 @@ public abstract class ExecutionManagerImpl extends ExecutionManager implements D
RunContentDescriptor contentToReuse = environment.getContentToReuse();
final List<RunContentDescriptor> runningOfTheSameType = new SmartList<>();
if (configuration != null && configuration.isSingleton()) {
if (configuration != null && !configuration.getConfiguration().isAllowRunningInParallel()) {
runningOfTheSameType.addAll(getRunningDescriptorsOfTheSameConfigType(configuration));
}
else if (isProcessRunning(contentToReuse)) {
@@ -292,9 +292,8 @@ open class RunManagerImpl @JvmOverloads constructor(val project: Project, shared
internal fun createTemplateSettings(factory: ConfigurationFactory): RunnerAndConfigurationSettingsImpl {
val configuration = factory.createTemplateConfiguration(project, this)
val template = RunnerAndConfigurationSettingsImpl(this, configuration,
isTemplate = true,
isSingleton = factory.singletonPolicy.isSingleton)
configuration.isAllowRunningInParallel = factory.singletonPolicy.isAllowRunningInParallel
val template = RunnerAndConfigurationSettingsImpl(this, configuration, isTemplate = true)
if (configuration is UnknownRunConfiguration) {
configuration.isDoNotStore = true
}
@@ -51,7 +51,6 @@ enum class RunConfigurationLevel {
class RunnerAndConfigurationSettingsImpl @JvmOverloads constructor(val manager: RunManagerImpl,
private var _configuration: RunConfiguration? = null,
private var isTemplate: Boolean = false,
private var isSingleton: Boolean = true,
var level: RunConfigurationLevel = RunConfigurationLevel.WORKSPACE) : Cloneable, RunnerAndConfigurationSettings, Comparable<Any>, SerializableScheme {
companion object {
@JvmStatic
@@ -141,25 +140,19 @@ class RunnerAndConfigurationSettingsImpl @JvmOverloads constructor(val manager:
isEditBeforeRun = value
}
override fun isEditBeforeRun(): Boolean = isEditBeforeRun
override fun isEditBeforeRun() = isEditBeforeRun
override fun setActivateToolWindowBeforeRun(value: Boolean) {
isActivateToolWindowBeforeRun = value
}
override fun isActivateToolWindowBeforeRun(): Boolean = isActivateToolWindowBeforeRun
override fun setSingleton(value: Boolean) {
isSingleton = value
}
override fun isSingleton(): Boolean = isSingleton
override fun isActivateToolWindowBeforeRun() = isActivateToolWindowBeforeRun
override fun setFolderName(value: String?) {
folderName = value
}
override fun getFolderName(): String? = folderName
override fun getFolderName() = folderName
fun readExternal(element: Element, isShared: Boolean) {
isTemplate = element.getAttributeBooleanValue(TEMPLATE_FLAG_ATTRIBUTE)
@@ -178,21 +171,6 @@ class RunnerAndConfigurationSettingsImpl @JvmOverloads constructor(val manager:
folderName = element.getAttributeValue(FOLDER_NAME)
val factory = manager.getFactory(element.getAttributeValue(CONFIGURATION_TYPE_ATTRIBUTE), element.getAttributeValue(FACTORY_NAME_ATTRIBUTE), !isTemplate) ?: return
wasSingletonSpecifiedExplicitly = false
if (isTemplate) {
isSingleton = factory.singletonPolicy.isSingleton
}
else {
val singletonStr = element.getAttributeValue(SINGLETON)
if (singletonStr.isNullOrEmpty()) {
isSingleton = factory.singletonPolicy.isSingleton
}
else {
wasSingletonSpecifiedExplicitly = true
isSingleton = singletonStr!!.toBoolean()
}
}
val configuration = factory.createTemplateConfiguration(manager.project, manager)
if (!isTemplate) {
// shouldn't call createConfiguration since it calls StepBeforeRunProviders that
@@ -200,6 +178,21 @@ class RunnerAndConfigurationSettingsImpl @JvmOverloads constructor(val manager:
configuration.name = element.getAttributeValue(NAME_ATTR) ?: return
}
wasSingletonSpecifiedExplicitly = false
if (isTemplate) {
configuration.isAllowRunningInParallel = factory.singletonPolicy.isAllowRunningInParallel
}
else {
val singletonStr = element.getAttributeValue(SINGLETON)
if (singletonStr.isNullOrEmpty()) {
configuration.isAllowRunningInParallel = factory.singletonPolicy.isAllowRunningInParallel
}
else {
wasSingletonSpecifiedExplicitly = true
configuration.isAllowRunningInParallel = !singletonStr!!.toBoolean()
}
}
_configuration = configuration
uniqueId = null
@@ -259,8 +252,8 @@ class RunnerAndConfigurationSettingsImpl @JvmOverloads constructor(val manager:
if (!isActivateToolWindowBeforeRun) {
element.setAttribute(ACTIVATE_TOOLWINDOW_BEFORE_RUN, "false")
}
if (wasSingletonSpecifiedExplicitly || isSingleton != factory.singletonPolicy.isSingleton) {
element.setAttribute(SINGLETON, isSingleton.toString())
if (wasSingletonSpecifiedExplicitly || configuration.isAllowRunningInParallel != factory.singletonPolicy.isAllowRunningInParallel) {
element.setAttribute(SINGLETON, (!configuration.isAllowRunningInParallel).toString())
}
if (isTemporary) {
element.setAttribute(TEMPORARY_ATTRIBUTE, "true")
@@ -352,7 +345,6 @@ class RunnerAndConfigurationSettingsImpl @JvmOverloads constructor(val manager:
importFromTemplate(template.runnerSettings, runnerSettings)
importFromTemplate(template.configurationPerRunnerSettings, configurationPerRunnerSettings)
isSingleton = template.isSingleton
isEditBeforeRun = template.isEditBeforeRun
isActivateToolWindowBeforeRun = template.isActivateToolWindowBeforeRun
level = template.level
@@ -3,7 +3,7 @@
<grid id="cae26" binding="myWholePanel" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="13" y="24" width="427" height="174"/>
<xy x="13" y="24" width="611" height="174"/>
</constraints>
<properties/>
<border type="none"/>
@@ -95,12 +95,12 @@
<text resource-bundle="messages/ExecutionBundle" key="run.configuration.store.place.option"/>
</properties>
</component>
<component id="d7b04" class="com.intellij.ui.components.JBCheckBox" binding="myIsAllowMultipleInstances">
<component id="d7b04" class="com.intellij.ui.components.JBCheckBox" binding="myIsAllowRunningInParallelCheckBox">
<constraints>
<grid row="0" column="4" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="messages/ExecutionBundle" key="run.configuration.singleton"/>
<text resource-bundle="messages/ExecutionBundle" key="run.configuration.allow.running.parallel"/>
</properties>
</component>
<hspacer id="e4047">
@@ -48,7 +48,7 @@ public final class SingleConfigurationConfigurable<Config extends RunConfigurati
private final String myHelpTopic;
private final boolean myBrokenConfiguration;
private boolean myStoreProjectConfiguration;
private boolean mySingleton = true;
private boolean myIsAllowRunningInParallel = false;
private String myFolderName;
private boolean myChangingNameFromCode;
@@ -97,7 +97,7 @@ public final class SingleConfigurationConfigurable<Config extends RunConfigurati
void applySnapshotToComparison(RunnerAndConfigurationSettings original, RunnerAndConfigurationSettings snapshot) {
snapshot.setTemporary(original.isTemporary());
snapshot.setName(getNameText());
snapshot.setSingleton(mySingleton);
snapshot.getConfiguration().setAllowRunningInParallel(myIsAllowRunningInParallel);
snapshot.setFolderName(myFolderName);
}
@@ -112,7 +112,7 @@ public final class SingleConfigurationConfigurable<Config extends RunConfigurati
RunConfiguration runConfiguration = settings.getConfiguration();
settings.setName(getNameText());
settings.setSingleton(mySingleton);
runConfiguration.setAllowRunningInParallel(myIsAllowRunningInParallel);
settings.setFolderName(myFolderName);
settings.setShared(myStoreProjectConfiguration);
super.apply();
@@ -282,7 +282,7 @@ public final class SingleConfigurationConfigurable<Config extends RunConfigurati
@NotNull
public RunnerAndConfigurationSettings createSnapshot(boolean cloneBeforeRunTasks) throws ConfigurationException {
RunnerAndConfigurationSettings snapshot = getEditor().getSnapshot();
snapshot.setSingleton(mySingleton);
snapshot.getConfiguration().setAllowRunningInParallel(myIsAllowRunningInParallel);
if (cloneBeforeRunTasks) {
RunManagerImplKt.cloneBeforeRunTasks(snapshot.getConfiguration());
}
@@ -315,7 +315,7 @@ public final class SingleConfigurationConfigurable<Config extends RunConfigurati
private JButton myFixButton;
private JSeparator mySeparator;
private JCheckBox myCbStoreProjectConfiguration;
private JBCheckBox myIsAllowMultipleInstances;
private JBCheckBox myIsAllowRunningInParallelCheckBox;
private JPanel myValidationPanel;
private Runnable myQuickFix = null;
@@ -351,11 +351,11 @@ public final class SingleConfigurationConfigurable<Config extends RunConfigurati
public void actionPerformed(ActionEvent e) {
setModified(true);
myStoreProjectConfiguration = myCbStoreProjectConfiguration.isSelected();
mySingleton = !myIsAllowMultipleInstances.isSelected();
myIsAllowRunningInParallel = myIsAllowRunningInParallelCheckBox.isSelected();
}
};
myCbStoreProjectConfiguration.addActionListener(actionListener);
myIsAllowMultipleInstances.addActionListener(actionListener);
myIsAllowRunningInParallelCheckBox.addActionListener(actionListener);
}
private void doReset(RunnerAndConfigurationSettings settings) {
@@ -365,10 +365,10 @@ public final class SingleConfigurationConfigurable<Config extends RunConfigurati
myCbStoreProjectConfiguration.setSelected(myStoreProjectConfiguration);
myCbStoreProjectConfiguration.setVisible(!settings.isTemplate());
mySingleton = settings.isSingleton();
myIsAllowMultipleInstances.setEnabled(!isUnknownRunConfiguration);
myIsAllowMultipleInstances.setSelected(!mySingleton);
myIsAllowMultipleInstances.setVisible(settings.getFactory().getSingletonPolicy().isPolicyConfigurable());
myIsAllowRunningInParallel = settings.getConfiguration().isAllowRunningInParallel();
myIsAllowRunningInParallelCheckBox.setEnabled(!isUnknownRunConfiguration);
myIsAllowRunningInParallelCheckBox.setSelected(myIsAllowRunningInParallel);
myIsAllowRunningInParallelCheckBox.setVisible(settings.getFactory().getSingletonPolicy().isPolicyConfigurable());
}
public final JComponent getWholePanel() {
@@ -312,7 +312,7 @@ show.swing.inspector=&Enable capturing form snapshots
show.swing.inspector.disabled=&Enable capturing form snapshots (requires JRE 5.0 or higher)
before.run.property.make=Make
run.configuration.store.place.option=&Share
run.configuration.singleton=Allow multiple &instances
run.configuration.allow.running.parallel=Allow running in &parallel
run.configuration.default.type.description=configuration
#GeneralCommandLine
@@ -2,6 +2,7 @@ package com.intellij.configurationScript
import com.intellij.execution.configurations.ConfigurationFactory
import com.intellij.execution.configurations.ConfigurationType
import com.intellij.openapi.components.JsonSchemaType
import com.intellij.openapi.diagnostic.debug
import com.intellij.openapi.util.text.StringUtil
import com.intellij.util.ReflectionUtil
@@ -175,6 +176,12 @@ internal class RunConfigurationJsonSchemaGenerator {
"description" toUnescaped description
}
map("properties") {
map("isAllowRunningInParallel") {
"type" to JsonSchemaType.BOOLEAN.jsonName
// we don't specify default value ("default") because it is tricky - not value from factory, but from RC template maybe used,
// and on time when schema is generated, we cannot compute efficient default value
}
buildJsonSchema(state, this)
}
}
@@ -2,9 +2,11 @@ package com.intellij.configurationScript
import com.intellij.execution.configurations.ConfigurationFactory
import com.intellij.execution.configurations.ConfigurationType
import com.intellij.execution.configurations.RunConfigurationOptions
import com.intellij.openapi.components.BaseState
import com.intellij.openapi.diagnostic.debug
import com.intellij.openapi.diagnostic.runAndLogException
import com.intellij.util.ReflectionUtil
import gnu.trove.THashMap
import org.yaml.snakeyaml.nodes.MappingNode
import org.yaml.snakeyaml.nodes.Node
@@ -105,6 +107,11 @@ internal class RunConfigurationListReader(private val processor: (factory: Confi
}
private fun readRunConfiguration(optionsClass: Class<out BaseState>, node: MappingNode, factory: ConfigurationFactory) {
processor(factory, readObject(optionsClass, node))
val instance = ReflectionUtil.newInstance(optionsClass)
if (instance is RunConfigurationOptions) {
// very important - set BEFORE read to ensure that user can set any value for isAllowRunningInParallel and it will be not overridden by us later
instance.isAllowRunningInParallel = factory.singletonPolicy.isAllowRunningInParallel
}
processor(factory, readObject(instance, node))
}
}
@@ -4,14 +4,12 @@ import com.intellij.configurationStore.properties.CollectionStoredProperty
import com.intellij.configurationStore.properties.MapStoredProperty
import com.intellij.openapi.components.BaseState
import com.intellij.openapi.components.ScalarProperty
import com.intellij.util.ReflectionUtil
import org.yaml.snakeyaml.nodes.MappingNode
import org.yaml.snakeyaml.nodes.ScalarNode
import org.yaml.snakeyaml.nodes.SequenceNode
internal fun readObject(optionsClass: Class<out BaseState>, node: MappingNode): BaseState {
val state = ReflectionUtil.newInstance(optionsClass)
val properties = state.__getProperties()
internal fun readObject(instance: BaseState, node: MappingNode): BaseState {
val properties = instance.__getProperties()
for (tuple in node.value) {
val valueNode = tuple.valueNode
val key = (tuple.keyNode as ScalarNode).value
@@ -40,7 +38,7 @@ internal fun readObject(optionsClass: Class<out BaseState>, node: MappingNode):
}
}
}
return state
return instance
}
private fun readCollection(property: CollectionStoredProperty<*, *>, valueNode: SequenceNode) {
@@ -40,8 +40,9 @@ private class MyRunConfigurationTemplateProvider(private val project: Project) :
}
val configuration = factory.createTemplateConfiguration(runManager.project, runManager)
// see readRunConfiguration about how do we set isAllowRunningInParallel
(configuration as RunConfigurationBase).setState(item.state as BaseState)
settings = RunnerAndConfigurationSettingsImpl(runManager, configuration, isTemplate = true, isSingleton = factory.singletonPolicy.isSingleton)
settings = RunnerAndConfigurationSettingsImpl(runManager, configuration, isTemplate = true)
item.state = null
item.settings = settings
return settings
@@ -33,7 +33,7 @@ internal fun readPluginsConfiguration(rootNode: MappingNode): PluginsConfigurati
val keyNode = tuple.keyNode
if (keyNode is ScalarNode && keyNode.value == Keys.plugins) {
val valueNode = tuple.valueNode as? MappingNode ?: continue
return readObject(PluginsConfiguration::class.java, valueNode) as PluginsConfiguration
return readObject(PluginsConfiguration(), valueNode) as PluginsConfiguration
}
}
return null
@@ -12,7 +12,7 @@ import com.jetbrains.jsonSchema.impl.JsonSchemaReader
import org.intellij.lang.annotations.Language
import java.nio.charset.StandardCharsets
class IntelliJConfigurationSchemaTest : CompletionTestCase() {
internal class IntelliJConfigurationSchemaTest : CompletionTestCase() {
companion object {
private val schemaFile by lazy {
LightVirtualFile("scheme.json", JsonFileType.INSTANCE, generateConfigurationSchema(), StandardCharsets.UTF_8, 0)
@@ -26,10 +26,15 @@ class IntelliJConfigurationSchemaTest : CompletionTestCase() {
<caret>
""".trimIndent())
val variant = variants.first { it.lookupString == "env" }
checkDescription(variants, "env", "Environment variables")
checkDescription(variants, "isAllowRunningInParallel", "Allow running in parallel")
}
private fun checkDescription(variants: List<LookupElement>, name: String, expectedDescription: String) {
val variant = variants.first { it.lookupString == name }
val presentation = LookupElementPresentation()
variant.renderElement(presentation)
assertThat(presentation.typeText).isEqualTo("Environment variables")
assertThat(presentation.typeText).isEqualTo(expectedDescription)
}
private fun test(@Language("YAML") text: String): List<LookupElement> {