BeforeRunTask — ability to use PersistentStateComponent

This commit is contained in:
Vladimir Krivosheev
2017-09-01 15:11:21 +02:00
parent e304fa5c18
commit 270691cbc5
8 changed files with 81 additions and 29 deletions
@@ -16,6 +16,7 @@
package com.intellij.execution;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.util.Key;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
@@ -27,6 +28,9 @@ import org.jetbrains.annotations.NotNull;
public abstract class BeforeRunTask<T extends BeforeRunTask> implements Cloneable {
@NotNull
protected final Key<T> myProviderId;
// cannot be set to true by default, because RunManager.getHardcodedBeforeRunTasks creates before run task for each provider
// and some providers set enabled to true in the constructor to indicate, that before run task should be added to RC by default (on create)
private boolean myIsEnabled;
protected BeforeRunTask(@NotNull Key<T> providerId) {
@@ -47,7 +51,12 @@ public abstract class BeforeRunTask<T extends BeforeRunTask> implements Cloneabl
}
public void writeExternal(@NotNull Element element) {
element.setAttribute("enabled", String.valueOf(myIsEnabled));
if (this instanceof PersistentStateComponent) {
((PersistentStateComponent)this).getState();
}
else {
element.setAttribute("enabled", String.valueOf(myIsEnabled));
}
}
public void readExternal(@NotNull Element element) {
@@ -16,9 +16,7 @@
package com.intellij.execution.impl
import com.intellij.ProjectTopics
import com.intellij.configurationStore.OLD_NAME_CONVERTER
import com.intellij.configurationStore.SchemeManagerIprProvider
import com.intellij.configurationStore.save
import com.intellij.configurationStore.*
import com.intellij.execution.*
import com.intellij.execution.compound.CompoundRunConfiguration
import com.intellij.execution.configurations.*
@@ -58,6 +56,7 @@ import kotlin.concurrent.write
private val SELECTED_ATTR = "selected"
internal val METHOD = "method"
private val OPTION = "option"
private val RECENT = "recent_temporary"
// open for Upsource (UpsourceRunManager overrides to disable loadState (empty impl))
@State(name = "RunManager", defaultStateAsResource = true, storages = arrayOf(Storage(StoragePathMacros.WORKSPACE_FILE)))
@@ -65,7 +64,6 @@ open class RunManagerImpl(internal val project: Project) : RunManagerEx(), Persi
companion object {
@JvmField
val CONFIGURATION = "configuration"
private val RECENT = "recent_temporary"
@JvmField
val NAME_ATTR = "name"
@@ -607,7 +605,15 @@ open class RunManagerImpl(internal val project: Project) : RunManagerEx(), Persi
for (task in tasks) {
val child = Element(OPTION)
child.setAttribute(NAME_ATTR, task.providerId.toString())
task.writeExternal(child)
if (task is PersistentStateComponent<*>) {
if (!task.isEnabled) {
child.setAttribute("enabled", "false")
}
task.serializeStateInto(child)
}
else {
task.writeExternal(child)
}
methodElement.addContent(child)
}
return methodElement
@@ -800,7 +806,14 @@ open class RunManagerImpl(internal val project: Project) : RunManagerEx(), Persi
val key = methodElement.getAttributeValue(NAME_ATTR)
val provider = stringIdToBeforeRunProvider.getOrPut(key) { UnknownBeforeRunTaskProvider(key) }
val beforeRunTask = (if (provider is RunConfigurationBeforeRunProvider) provider.createTask(settings.configuration, this) else provider.createTask(settings.configuration)) ?: continue
beforeRunTask.readExternal(methodElement)
if (beforeRunTask is PersistentStateComponent<*>) {
// for PersistentStateComponent we don't write default value for enabled, so, set it to true explicitly
beforeRunTask.isEnabled = true
beforeRunTask.deserializeAndLoadState(methodElement)
}
else {
beforeRunTask.readExternal(methodElement)
}
if (result == null) {
result = SmartList()
}
@@ -996,8 +1009,8 @@ open class RunManagerImpl(internal val project: Project) : RunManagerEx(), Persi
private fun getHardcodedBeforeRunTasks(configuration: RunConfiguration): List<BeforeRunTask<*>> {
var result: MutableList<BeforeRunTask<*>>? = null
for (provider in Extensions.getExtensions(BeforeRunTaskProvider.EXTENSION_POINT_NAME, project)) {
val task = provider.createTask(configuration)
if (task != null && task.isEnabled) {
val task = provider.createTask(configuration) ?: continue
if (task.isEnabled) {
configuration.factory.configureBeforeRunTaskDefaults(provider.id, task)
if (task.isEnabled) {
if (result == null) {
@@ -17,7 +17,7 @@ package com.intellij.execution.impl
import com.intellij.configurationStore.SerializableScheme
import com.intellij.configurationStore.deserializeAndLoadState
import com.intellij.configurationStore.serializeInto
import com.intellij.configurationStore.serializeStateInto
import com.intellij.execution.*
import com.intellij.execution.configurations.*
import com.intellij.execution.runners.ProgramRunner
@@ -282,7 +282,7 @@ class RunnerAndConfigurationSettingsImpl @JvmOverloads constructor(private val m
private fun serializeConfigurationInto(configuration: RunConfiguration, element: Element) {
if (configuration is PersistentStateComponent<*>) {
configuration.state!!.serializeInto(element)
configuration.serializeStateInto(element)
}
else {
configuration.writeExternal(element)
@@ -119,15 +119,24 @@ fun PersistentStateComponent<*>.deserializeAndLoadState(element: Element) {
(this as PersistentStateComponent<Any>).loadState(state)
}
fun PersistentStateComponent<*>.serializeStateInto(element: Element) {
state?.let { serializeObjectInto(it, element) }
}
@Deprecated("")
fun <T : Any> T.serializeInto(target: Element) {
if (this is Element) {
val iterator = children.iterator()
serializeObjectInto(this, target)
}
fun serializeObjectInto(o: Any, target: Element) {
if (o is Element) {
val iterator = o.children.iterator()
for (child in iterator) {
iterator.remove()
target.addContent(child)
}
val attributeIterator = attributes.iterator()
val attributeIterator = o.attributes.iterator()
for (attribute in attributeIterator) {
attributeIterator.remove()
target.setAttribute(attribute)
@@ -135,8 +144,8 @@ fun <T : Any> T.serializeInto(target: Element) {
return
}
val binding = serializer.getClassBinding(javaClass)
(binding as BeanBinding).serializeInto(this, target, null)
val binding = serializer.getClassBinding(o.javaClass)
(binding as BeanBinding).serializeInto(o, target, getDefaultSerializationFilter())
}
private val serializer = object : XmlSerializerImpl.XmlSerializerBase() {
@@ -455,7 +455,7 @@ public class RootModelImpl extends RootModelBase implements ModifiableRootModel
for (ModuleExtension extension : myExtensions) {
if (extension instanceof PersistentStateComponent) {
//noinspection ConstantConditions
XmlSerializer.serializeInto(((PersistentStateComponent)extension).getState(), element);
XmlSerializer.serializeStateInto(((PersistentStateComponent)extension), element);
}
else {
//noinspection deprecation
@@ -16,7 +16,7 @@
package com.maddyhome.idea.copyright
import com.intellij.configurationStore.SerializableScheme
import com.intellij.configurationStore.serializeInto
import com.intellij.configurationStore.serializeObjectInto
import com.intellij.openapi.components.BaseState
import com.intellij.openapi.options.ExternalizableScheme
import com.intellij.util.xmlb.annotations.OptionTag
@@ -36,7 +36,7 @@ class CopyrightProfile @JvmOverloads constructor(profileName: String? = null) :
// ugly name to preserve compatibility
// must be not private because otherwise binding is not created for private accessor
@get:OptionTag("myName")
internal var profileName by string()
private var profileName by string()
var notice by string(DEFAULT_COPYRIGHT_NOTICE)
var keyword by string(EntityUtil.encode("Copyright"))
@@ -61,7 +61,7 @@ class CopyrightProfile @JvmOverloads constructor(profileName: String? = null) :
override fun writeScheme(): Element {
val element = Element("copyright")
serializeInto(element)
serializeObjectInto(this, element)
return element
}
}
@@ -261,7 +261,7 @@ public class IdeaSpecificSettings extends AbstractIdeaSpecificSettings<Modifiabl
LanguageLevelModuleExtensionImpl languageLevelModuleExtension = model.getModuleExtension(LanguageLevelModuleExtensionImpl.class);
if (languageLevelModuleExtension.getLanguageLevel() != null) {
//noinspection ConstantConditions
XmlSerializer.serializeInto(languageLevelModuleExtension.getState(), root);
XmlSerializer.serializeStateInto(languageLevelModuleExtension, root);
isModified = true;
}
@@ -22,6 +22,7 @@ import com.intellij.execution.runners.ExecutionEnvironment
import com.intellij.icons.AllIcons
import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.components.BaseState
import com.intellij.openapi.components.PersistentStateComponent
import com.intellij.openapi.ui.TextFieldWithBrowseButton
import com.intellij.openapi.util.Key
import com.intellij.ui.components.CheckBox
@@ -49,18 +50,27 @@ internal class LaunchBrowserBeforeRunTaskProvider : BeforeRunTaskProvider<Launch
override fun createTask(runConfiguration: RunConfiguration) = LaunchBrowserBeforeRunTask()
override fun configureTask(runConfiguration: RunConfiguration, task: LaunchBrowserBeforeRunTask): Boolean {
val state = task.state
val modificationCount = state.modificationCount
val browserSelector = BrowserSelector()
val browserComboBox = browserSelector.mainComponent
if (UIUtil.isUnderAquaLookAndFeel()) {
browserComboBox.border = EmptyBorder(3, 0, 0, 0)
}
state.browser?.let {
browserSelector.selected = it
}
val url = TextFieldWithBrowseButton()
state.url?.let {
url.text = it
}
StartBrowserPanel.setupUrlField(url, runConfiguration.project)
val startJavaScriptDebuggerCheckBox = if (JavaScriptDebuggerStarter.Util.hasStarters()) CheckBox(XmlBundle.message("start.browser.with.js.debugger")) else null
val startJavaScriptDebuggerCheckBox = if (JavaScriptDebuggerStarter.Util.hasStarters()) CheckBox(XmlBundle.message("start.browser.with.js.debugger"), state.withDebugger) else null
val modificationCount = task.state.modificationCount
val panel = panel {
row("Browser:") {
browserComboBox()
@@ -70,14 +80,15 @@ internal class LaunchBrowserBeforeRunTaskProvider : BeforeRunTaskProvider<Launch
url(growPolicy = GrowPolicy.MEDIUM_TEXT)
}
}
dialog("Launch Web Browser", panel = panel, resizable = true)
dialog("Launch Web Browser", panel = panel, resizable = true, focusedComponent = url)
.show()
task.state.browser = browserSelector.selected
state.browser = browserSelector.selected
state.url = url.text
if (startJavaScriptDebuggerCheckBox != null) {
task.state.withDebugger = startJavaScriptDebuggerCheckBox.isSelected
state.withDebugger = startJavaScriptDebuggerCheckBox.isSelected
}
return modificationCount != task.state.modificationCount
return modificationCount != state.modificationCount
}
override fun executeTask(context: DataContext?,
@@ -91,9 +102,19 @@ internal class LaunchBrowserBeforeRunTaskProvider : BeforeRunTaskProvider<Launch
internal class LaunchBrowserBeforeRunTaskState : BaseState() {
@get:Attribute(value = "browser", converter = WebBrowserReferenceConverter::class)
var browser by storedProperty<WebBrowser>()
@get:Attribute()
var url by string()
@get:Attribute()
var withDebugger by storedProperty(false)
}
internal class LaunchBrowserBeforeRunTask : BeforeRunTask<LaunchBrowserBeforeRunTask>(LaunchBrowserBeforeRunTaskProvider.ID) {
val state = LaunchBrowserBeforeRunTaskState()
internal class LaunchBrowserBeforeRunTask : BeforeRunTask<LaunchBrowserBeforeRunTask>(LaunchBrowserBeforeRunTaskProvider.ID), PersistentStateComponent<LaunchBrowserBeforeRunTaskState> {
private var state = LaunchBrowserBeforeRunTaskState()
override fun loadState(state: LaunchBrowserBeforeRunTaskState) {
state.resetModificationCount()
this.state = state
}
override fun getState() = state
}