Merge remote-tracking branch 'origin/master'

This commit is contained in:
Yaroslav Lepenkin
2015-09-02 13:01:14 +03:00
9 changed files with 51 additions and 20 deletions
@@ -33,6 +33,7 @@ import com.intellij.openapi.project.Project
import com.intellij.openapi.util
import com.intellij.openapi.util.*
import com.intellij.openapi.util.Pair
import com.intellij.openapi.util.registry.Registry
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess
import com.intellij.util.ArrayUtilRt
@@ -240,15 +241,14 @@ abstract class ComponentStoreImpl : IComponentStore {
val defaultState = if (stateSpec.defaultStateAsResource) getDefaultState(component, name, stateClass) else null
val storageSpecs = getStorageSpecs(component, stateSpec, StateStorageOperation.READ)
val stateStorageChooser = component as? StateStorageChooserEx
val storageChooser = component as? StateStorageChooserEx
for (storageSpec in storageSpecs) {
val resolution = if (stateStorageChooser == null) Resolution.DO else stateStorageChooser.getResolution(storageSpec, StateStorageOperation.READ)
if (resolution === Resolution.SKIP) {
if (storageChooser?.getResolution(storageSpec, StateStorageOperation.READ) == Resolution.SKIP) {
continue
}
val storage = storageManager.getStateStorage(storageSpec)
var stateGetter = (storage as? StorageBaseEx<*>)?.createGetSession(component, name, stateClass)
var stateGetter = if (isUseLoadedStateAsExisting(storageSpec) && Registry.`is`("use.loaded.state.as.existing", false)) (storage as? StorageBaseEx<*>)?.createGetSession(component, name, stateClass) else null
var state = if (stateGetter == null) storage.getState(component, name, stateClass, defaultState, reloadData) else stateGetter.getState(defaultState)
if (state == null) {
if (changedStorages != null && changedStorages.contains(storage)) {
@@ -261,7 +261,12 @@ abstract class ComponentStoreImpl : IComponentStore {
}
}
stateGetter?.use { component.loadState(state) }
try {
component.loadState(state)
}
finally {
stateGetter?.close()
}
return name
}
@@ -271,6 +276,8 @@ abstract class ComponentStoreImpl : IComponentStore {
return name
}
protected open fun isUseLoadedStateAsExisting(storageSpec: Storage): Boolean = true
protected open fun getPathMacroManagerForDefaults(): PathMacroManager? = null
private fun <T : Any> getDefaultState(component: Any, componentName: String, stateClass: Class<T>): T? {
@@ -62,7 +62,7 @@ open class DirectoryBasedStorage(private val myPathMacroSubstitutor: TrackingPat
}
}
override fun getState(storageData: Map<String, StateMap>, component: Any?, componentName: String) = getCompositeStateAndArchive(storageData, componentName, mySplitter)
override fun getState(storageData: Map<String, StateMap>, component: Any?, componentName: String, archive: Boolean) = getCompositeStateAndArchive(storageData, componentName, mySplitter)
override fun loadData(): MutableMap<String, StateMap> {
return fromMap(DirectoryStorageUtil.loadFrom(getVirtualFile(), myPathMacroSubstitutor))
@@ -288,6 +288,8 @@ open class ProjectStoreImpl(override val project: ProjectImpl, private val pathM
}
override fun selectDefaultStorages(storages: Array<Storage>, operation: StateStorageOperation) = selectDefaultStorages(storages, operation, scheme)
override fun isUseLoadedStateAsExisting(storageSpec: Storage) = storageSpec.file != StoragePathMacros.WORKSPACE_FILE
}
fun selectDefaultStorages(storages: Array<Storage>, operation: StateStorageOperation, scheme: StorageScheme): Array<Storage> {
@@ -15,12 +15,9 @@
*/
package com.intellij.configurationStore
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.PersistentStateComponent
import com.intellij.openapi.components.impl.stores.StateStorageBase
import com.intellij.openapi.util.registry.Registry
import org.jdom.Element
import java.io.Closeable
abstract class StorageBaseEx<T : Any> : StateStorageBase<T>() {
fun <S : Any> createGetSession(component: PersistentStateComponent<S>, componentName: String, stateClass: Class<S>, reload: Boolean = false) = StateGetter(component, componentName, getStorageData(reload), stateClass, this)
@@ -31,7 +28,7 @@ abstract class StorageBaseEx<T : Any> : StateStorageBase<T>() {
abstract fun archiveState(storageData: T, componentName: String, serializedState: Element?)
}
class StateGetter<S : Any, T : Any>(private val component: PersistentStateComponent<S>, private val componentName: String, private val storageData: T, private val stateClass: Class<S>, private val storage: StorageBaseEx<T>) : Closeable {
class StateGetter<S : Any, T : Any>(private val component: PersistentStateComponent<S>, private val componentName: String, private val storageData: T, private val stateClass: Class<S>, private val storage: StorageBaseEx<T>) {
var serializedState: Element? = null
fun getState(mergeInto: S? = null): S? {
@@ -44,7 +41,7 @@ class StateGetter<S : Any, T : Any>(private val component: PersistentStateCompon
return storage.deserializeState(serializedState, stateClass, mergeInto)
}
override fun close() {
fun close() {
if (serializedState == null) {
return
}
@@ -53,7 +50,7 @@ class StateGetter<S : Any, T : Any>(private val component: PersistentStateCompon
val stateAfterLoad: S?
try {
stateAfterLoad = if (ApplicationManager.getApplication().isUnitTestMode() || Registry.`is`("use.loaded.state.as.existing", false)) component.getState() else null
stateAfterLoad = component.getState()
}
catch(e: Throwable) {
LOG.error("Cannot get state after load", e)
@@ -37,7 +37,7 @@ abstract class XmlElementStorage protected constructor(protected val fileSpec: S
protected abstract fun loadLocalData(): Element?
override final fun getState(storageData: StateMap, component: Any?, componentName: String) = storageData.getState(componentName)
override final fun getState(storageData: StateMap, component: Any?, componentName: String, archive: Boolean) = storageData.getState(componentName)
override fun archiveState(storageData: StateMap, componentName: String, serializedState: Element?) {
storageData.archive(componentName, serializedState)
@@ -110,7 +110,7 @@ class ApplicationStoreTest {
}
@State(name = "A", storages = arrayOf(Storage(file = "a.xml")))
private class A : PersistentStateComponent<Element> {
private open class A : PersistentStateComponent<Element> {
data class State(@Attribute var foo: String = "", @Attribute var bar: String = "")
var state = State()
@@ -144,6 +144,24 @@ class ApplicationStoreTest {
assertThat(file).hasContent("<application>\n <component name=\"A\" foo=\"1\" bar=\"2\" />\n</application>")
}
@Test fun `do not apply to workspace storage - do not save if only format is changed`() {
@State(name = "A", storages = arrayOf(Storage(file = StoragePathMacros.WORKSPACE_FILE)))
class AWorkspace : A()
val oldContent = "<application><component name=\"A\" foo=\"old\" deprecated=\"old\"/></application>"
val file = writeConfig("workspace.xml", oldContent)
val oldModificationTime = file.getLastModifiedTime()
testAppConfig.refreshVfs()
val component = AWorkspace()
componentStore.initComponent(component, false)
assertThat(component.state).isEqualTo(A.State("old"))
saveStore()
assertThat(file).hasContent("<application>\n <component name=\"A\" foo=\"old\" />\n</application>")
}
private fun saveStore() {
runInEdtAndWait { componentStore.save(SmartList()) }
}
@@ -188,7 +206,10 @@ class ApplicationStoreTest {
override fun setPath(path: String) {
storageManager.addMacro(StoragePathMacros.APP_CONFIG, path)
storageManager.addMacro(StoragePathMacros.WORKSPACE_FILE, "$path/workspace.xml")
}
override fun isUseLoadedStateAsExisting(storageSpec: Storage) = storageSpec.file != StoragePathMacros.WORKSPACE_FILE
}
abstract class Foo {
@@ -24,7 +24,7 @@ import org.junit.Test
class XmlElementStorageTest {
@Test fun testGetStateSucceeded() {
val storage = MyXmlElementStorage(tag("root", tag("component", attr("name", "test"), tag("foo"))))
val state = storage.getState(this, "test", javaClass<Element>(), null, false)
val state = storage.getState(this, "test", javaClass<Element>())
assertThat(state).isNotNull()
assertThat(state!!.getName()).isEqualTo("component")
assertThat(state.getChild("foo")).isNotNull()
@@ -32,7 +32,7 @@ class XmlElementStorageTest {
@Test fun `get state not succeeded`() {
val storage = MyXmlElementStorage(tag("root"))
val state = storage.getState(this, "test", javaClass<Element>(), null, false)
val state = storage.getState(this, "test", javaClass<Element>())
assertThat(state).isNull()
}
@@ -135,7 +135,7 @@ public class ClasspathStorage extends StateStorageBase<Boolean> {
@Nullable
@Override
public Element getState(@NotNull Boolean storageData, Object component, @NotNull String componentName) {
public Element getState(@NotNull Boolean storageData, Object component, @NotNull String componentName, boolean archive) {
if (storageData) {
return null;
}
@@ -29,15 +29,19 @@ public abstract class StateStorageBase<T : Any> : StateStorage {
protected val storageDataRef: AtomicReference<T> = AtomicReference()
override fun <S> getState(component: Any?, componentName: String, stateClass: Class<S>, mergeInto: S?, reload: Boolean): S? {
return deserializeState(getState(getStorageData(reload), component, componentName), stateClass, mergeInto)
override final fun <S> getState(component: Any?, componentName: String, stateClass: Class<S>, mergeInto: S?, reload: Boolean): S? {
return getState(component, componentName, stateClass, true, reload, mergeInto)
}
fun <S : Any> getState(component: Any?, componentName: String, stateClass: Class<S>, archive: Boolean = true, reload: Boolean = false, mergeInto: S? = null): S? {
return deserializeState(getState(getStorageData(reload), component, componentName, archive), stateClass, mergeInto)
}
open fun <S> deserializeState(serializedState: Element?, stateClass: Class<S>, mergeInto: S?): S? {
return DefaultStateSerializer.deserializeState(serializedState, stateClass, mergeInto)
}
abstract fun getState(storageData: T, component: Any?, componentName: String): Element?
abstract fun getState(storageData: T, component: Any?, componentName: String, archive: Boolean = true): Element?
protected abstract fun hasState(storageData: T, componentName: String): Boolean