From 8ff7a4164ec6becb62be2ebd568c04c462686961 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Tue, 23 Jan 2018 18:01:56 +0100 Subject: [PATCH] read artifacts and libraries data from both external and in-project sources Problem is that both artifacts and libraries still don't use SchemeManager and so, we still need to use deprecated DirectoryBasedStorage --- .../model/serialization/JpsProjectLoader.java | 32 +++++++++---- .../src/ComponentStoreImpl.kt | 31 ++++++------ .../src/DefaultProjectStoreImpl.kt | 5 +- .../src/DirectoryBasedStorage.kt | 2 +- .../src/ExportSettingsAction.kt | 2 +- .../src/FileStorageAnnotation.java | 13 ++--- .../src/ModuleStoreImpl.kt | 2 +- .../src/ProjectStoreImpl.kt | 18 +++---- .../src/SchemeManagerFactoryImpl.kt | 4 +- .../src/StateStorageManagerImpl.kt | 26 +++++----- .../src/StorageBaseEx.kt | 44 +++++++++++++---- .../testSrc/ApplicationStoreTest.kt | 2 +- .../testSrc/DefaultProjectStoreTest.kt | 2 +- .../testSrc/DoNotSaveDefaults.kt | 2 +- .../testSrc/ModuleStoreRenameTest.kt | 6 +-- .../testSrc/ModuleStoreTest.kt | 2 +- .../testSrc/ProjectStoreTest.kt | 4 +- .../ExternalStorageSpec.java | 48 +++++++++++++++++++ .../ExternalSystemStorage.kt | 11 ++++- .../ExternalSystemStreamProviderFactory.kt | 40 ++++++++++++---- .../openapi/module/impl/ModuleImpl.java | 4 +- .../roots/impl/storage/ClasspathStorage.java | 2 +- .../configurationStore/storageUtil.kt | 8 ++-- .../configurationStore/StateStorageManager.kt | 29 ++++------- .../StreamProviderFactory.kt | 4 +- .../components/impl/stores/IComponentStore.kt | 11 ++--- .../src/com/intellij/project/project.kt | 18 +------ .../com/intellij/openapi/util/JDOMUtil.java | 25 +++++----- .../src/CommitToIcsDialog.java | 18 +------ plugins/settings-repository/src/IcsManager.kt | 22 ++------- .../src/actions/SyncAction.kt | 18 +------ .../src/copyAppSettingsToRepository.kt | 18 +------ 32 files changed, 247 insertions(+), 226 deletions(-) create mode 100644 platform/external-system-impl/src/com/intellij/openapi/externalSystem/configurationStore/ExternalStorageSpec.java diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsProjectLoader.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsProjectLoader.java index c8a625e956b5..ff7b1c0a3af7 100644 --- a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsProjectLoader.java +++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsProjectLoader.java @@ -1,6 +1,4 @@ -/* - * Copyright 2000-2017 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. - */ +// 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 org.jetbrains.jps.model.serialization; import com.intellij.openapi.diagnostic.Logger; @@ -123,15 +121,26 @@ public class JpsProjectLoader extends JpsLoaderBase { protected Element loadComponentData(@NotNull JpsElementExtensionSerializerBase serializer, @NotNull Path configFile) { Path externalConfigDir = resolveExternalProjectConfig("project"); Element data = super.loadComponentData(serializer, configFile); - if (externalConfigDir != null && serializer.getComponentName().equals("CompilerConfiguration")) { - Element externalData = JDomSerializationUtil.findComponent(loadRootElement(externalConfigDir.resolve(configFile.getFileName())), "External" + serializer.getComponentName()); - if (data == null) { - return externalData; - } - else if (externalData != null) { - return JDOMUtil.deepMerge(data, externalData); + String componentName = serializer.getComponentName(); + if (externalConfigDir == null || !(componentName.equals("CompilerConfiguration"))) { + return data; + } + + String prefixedComponentName = "External" + componentName; + Element externalData = null; + for (Element child : (JDOMUtil.getChildren(loadRootElement(externalConfigDir.resolve(configFile.getFileName()))))) { + // be ready to handle both original name and prefixed + if (child.getName().equals(prefixedComponentName) || child.getName().equals(componentName)) { + externalData = child; + break; } } + if (data == null) { + return externalData; + } + else if (externalData != null) { + return JDOMUtil.deepMerge(data, externalData); + } return data; } @@ -201,6 +210,9 @@ public class JpsProjectLoader extends JpsLoaderBase { for (Path artifactFile : listXmlFiles(dir.resolve("artifacts"))) { loadArtifacts(loadRootElement(artifactFile)); } + if (externalConfigDir != null) { + loadArtifacts(loadRootElement(externalConfigDir.resolve("artifacts.xml"))); + } artifactsTimingLog.run(); if (hasRunConfigurationSerializers()) { diff --git a/platform/configuration-store-impl/src/ComponentStoreImpl.kt b/platform/configuration-store-impl/src/ComponentStoreImpl.kt index 994778e002d7..a2be45be8e31 100644 --- a/platform/configuration-store-impl/src/ComponentStoreImpl.kt +++ b/platform/configuration-store-impl/src/ComponentStoreImpl.kt @@ -25,15 +25,18 @@ import com.intellij.openapi.components.StateStorage.SaveSession import com.intellij.openapi.components.StateStorageChooserEx.Resolution import com.intellij.openapi.components.impl.ComponentManagerImpl import com.intellij.openapi.components.impl.stores.IComponentStore +import com.intellij.openapi.components.impl.stores.SaveSessionAndFile import com.intellij.openapi.components.impl.stores.StoreUtil import com.intellij.openapi.components.impl.stores.UnknownMacroNotification import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.diagnostic.debug import com.intellij.openapi.progress.ProcessCanceledException import com.intellij.openapi.project.Project -import com.intellij.openapi.util.* +import com.intellij.openapi.util.InvalidDataException +import com.intellij.openapi.util.JDOMExternalizable +import com.intellij.openapi.util.JDOMUtil +import com.intellij.openapi.util.ModificationTracker import com.intellij.openapi.util.registry.Registry -import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess import com.intellij.project.isDirectoryBased import com.intellij.ui.AppUIUtil @@ -80,9 +83,7 @@ abstract class ComponentStoreImpl : IComponentStore { open val loadPolicy: StateLoadPolicy get() = StateLoadPolicy.LOAD - abstract val storageManager: StateStorageManager - - override final fun getStateStorageManager() = storageManager + override abstract val storageManager: StateStorageManager override final fun initComponent(component: Any, isService: Boolean) { if (component is SettingsSavingComponent) { @@ -129,7 +130,7 @@ abstract class ComponentStoreImpl : IComponentStore { return componentName } - override fun save(readonlyFiles: MutableList>) { + override fun save(readonlyFiles: MutableList) { var errors: MutableList? = null // component state uses scheme manager in an ipr project, so, we must save it before @@ -251,7 +252,7 @@ abstract class ComponentStoreImpl : IComponentStore { } } - protected open fun doSave(saveSessions: List, readonlyFiles: MutableList> = arrayListOf(), prevErrors: MutableList? = null): MutableList? { + protected open fun doSave(saveSessions: List, readonlyFiles: MutableList = arrayListOf(), prevErrors: MutableList? = null): MutableList? { var errors = prevErrors for (session in saveSessions) { errors = executeSave(session, readonlyFiles, prevErrors) @@ -331,8 +332,8 @@ abstract class ComponentStoreImpl : IComponentStore { } val storage = storageManager.getStateStorage(storageSpec) - val stateGetter = if (isUseLoadedStateAsExisting(storage, name)) (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) + val stateGetter = createStateGetter(isUseLoadedStateAsExisting(storage), storage, component, name, stateClass, reloadData = reloadData) + var state = stateGetter.getState(defaultState) if (state == null) { if (changedStorages != null && changedStorages.contains(storage)) { // state will be null if file deleted @@ -348,7 +349,7 @@ abstract class ComponentStoreImpl : IComponentStore { component.loadState(state) } finally { - stateGetter?.close() + stateGetter.close() } return true } @@ -410,7 +411,7 @@ abstract class ComponentStoreImpl : IComponentStore { return storages.sortByDeprecated() } - final override fun isReloadPossible(componentNames: MutableSet) = !componentNames.any { isNotReloadable(it) } + final override fun isReloadPossible(componentNames: Set) = !componentNames.any { isNotReloadable(it) } private fun isNotReloadable(name: String): Boolean { val component = components.get(name)?.component ?: return false @@ -430,7 +431,7 @@ abstract class ComponentStoreImpl : IComponentStore { return notReloadableComponents ?: emptySet() } - override final fun reloadStates(componentNames: MutableSet, messageBus: MessageBus) { + override final fun reloadStates(componentNames: Set, messageBus: MessageBus) { runBatchUpdate(messageBus) { reinitComponents(componentNames) } @@ -503,14 +504,14 @@ abstract class ComponentStoreImpl : IComponentStore { } } -internal fun executeSave(session: SaveSession, readonlyFiles: MutableList>, previousErrors: MutableList?): MutableList? { +internal fun executeSave(session: SaveSession, readonlyFiles: MutableList, previousErrors: MutableList?): MutableList? { var errors = previousErrors try { session.save() } catch (e: ReadOnlyModificationException) { LOG.warn(e) - readonlyFiles.add(JBPair.create(e.session ?: session, e.file)) + readonlyFiles.add(SaveSessionAndFile(e.session ?: session, e.file)) } catch (e: Exception) { if (errors == null) { @@ -544,7 +545,7 @@ internal fun Array.sortByDeprecated(): List { } private fun notifyUnknownMacros(store: IComponentStore, project: Project, componentName: String) { - val substitutor = store.stateStorageManager.macroSubstitutor ?: return + val substitutor = store.storageManager.macroSubstitutor ?: return val immutableMacros = substitutor.getUnknownMacros(componentName) if (immutableMacros.isEmpty()) { diff --git a/platform/configuration-store-impl/src/DefaultProjectStoreImpl.kt b/platform/configuration-store-impl/src/DefaultProjectStoreImpl.kt index d09eac5f06c4..7b66dd014419 100644 --- a/platform/configuration-store-impl/src/DefaultProjectStoreImpl.kt +++ b/platform/configuration-store-impl/src/DefaultProjectStoreImpl.kt @@ -56,9 +56,12 @@ internal class DefaultProjectStoreImpl(override val project: ProjectImpl, privat service().project = project } - private val storage by lazy { DefaultProjectStorage(Paths.get(ApplicationManager.getApplication().stateStore.stateStorageManager.expandMacros(FILE_SPEC)), FILE_SPEC, pathMacroManager) } + private val storage by lazy { DefaultProjectStorage(Paths.get(ApplicationManager.getApplication().stateStore.storageManager.expandMacros(FILE_SPEC)), FILE_SPEC, pathMacroManager) } override val storageManager = object : StateStorageManager { + override val componentManager: ComponentManager? + get() = null + override fun addStreamProvider(provider: StreamProvider, first: Boolean) { } diff --git a/platform/configuration-store-impl/src/DirectoryBasedStorage.kt b/platform/configuration-store-impl/src/DirectoryBasedStorage.kt index 40a98cb96c35..c888b1cc6d41 100644 --- a/platform/configuration-store-impl/src/DirectoryBasedStorage.kt +++ b/platform/configuration-store-impl/src/DirectoryBasedStorage.kt @@ -44,7 +44,7 @@ abstract class DirectoryBasedStorageBase(@Suppress("DEPRECATION") protected val protected abstract val virtualFile: VirtualFile? - override fun loadData() = StateMap.fromMap(DirectoryStorageUtil.loadFrom(virtualFile, pathMacroSubstitutor)) + override public fun loadData() = StateMap.fromMap(DirectoryStorageUtil.loadFrom(virtualFile, pathMacroSubstitutor)) override fun startExternalization(): StateStorage.ExternalizationSession? = null diff --git a/platform/configuration-store-impl/src/ExportSettingsAction.kt b/platform/configuration-store-impl/src/ExportSettingsAction.kt index fe45fd723220..4b78c762dbb1 100644 --- a/platform/configuration-store-impl/src/ExportSettingsAction.kt +++ b/platform/configuration-store-impl/src/ExportSettingsAction.kt @@ -148,7 +148,7 @@ private fun exportInstalledPlugins(zipOut: MyZipOutputStream) { // onlyPaths - include only specified paths (relative to config dir, ends with "/" if directory) fun getExportableComponentsMap(onlyExisting: Boolean, computePresentableNames: Boolean, - storageManager: StateStorageManager = ApplicationManager.getApplication().stateStore.stateStorageManager, + storageManager: StateStorageManager = ApplicationManager.getApplication().stateStore.storageManager, onlyPaths: Set? = null): Map> { val result = LinkedHashMap>() @Suppress("DEPRECATION") diff --git a/platform/configuration-store-impl/src/FileStorageAnnotation.java b/platform/configuration-store-impl/src/FileStorageAnnotation.java index 238d0eb3eb61..adc44913fe48 100644 --- a/platform/configuration-store-impl/src/FileStorageAnnotation.java +++ b/platform/configuration-store-impl/src/FileStorageAnnotation.java @@ -2,25 +2,18 @@ package com.intellij.configurationStore; import com.intellij.openapi.components.*; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.lang.annotation.Annotation; @SuppressWarnings("ClassExplicitlyAnnotation") -public final class FileStorageAnnotation implements Storage { - private String path; +public class FileStorageAnnotation implements Storage { + protected final String path; private boolean deprecated; - private final Class storageClass; public FileStorageAnnotation(@NotNull String path, boolean deprecated) { - this(path, deprecated, StateStorage.class); - } - - public FileStorageAnnotation(@NotNull String path, boolean deprecated, @Nullable Class storageClass) { this.path = path; this.deprecated = deprecated; - this.storageClass = storageClass; } @Override @@ -60,7 +53,7 @@ public final class FileStorageAnnotation implements Storage { @Override public Class storageClass() { - return storageClass; + return StateStorage.class; } @Override diff --git a/platform/configuration-store-impl/src/ModuleStoreImpl.kt b/platform/configuration-store-impl/src/ModuleStoreImpl.kt index 3ddcd88e3ef3..9ada928cf333 100644 --- a/platform/configuration-store-impl/src/ModuleStoreImpl.kt +++ b/platform/configuration-store-impl/src/ModuleStoreImpl.kt @@ -36,7 +36,7 @@ private open class ModuleStoreImpl(module: Module, private val pathMacroManager: override fun getStorageSpecs(component: PersistentStateComponent, stateSpec: State, operation: StateStorageOperation): List { val result = super.getStorageSpecs(component, stateSpec, operation) return StreamProviderFactory.EP_NAME.getExtensions(project).computeIfAny { - LOG.runAndLogException { it.customizeStorageSpecs(component, storageManager.componentManager!!, stateSpec, result, operation) } + LOG.runAndLogException { it.customizeStorageSpecs(component, storageManager, stateSpec, result, operation) } } ?: result } } diff --git a/platform/configuration-store-impl/src/ProjectStoreImpl.kt b/platform/configuration-store-impl/src/ProjectStoreImpl.kt index 08ef32b86176..54e62384e4bb 100644 --- a/platform/configuration-store-impl/src/ProjectStoreImpl.kt +++ b/platform/configuration-store-impl/src/ProjectStoreImpl.kt @@ -26,6 +26,7 @@ import com.intellij.openapi.components.* import com.intellij.openapi.components.StateStorage.SaveSession import com.intellij.openapi.components.impl.stores.IComponentStore import com.intellij.openapi.components.impl.stores.IProjectStore +import com.intellij.openapi.components.impl.stores.SaveSessionAndFile import com.intellij.openapi.diagnostic.runAndLogException import com.intellij.openapi.module.Module import com.intellij.openapi.module.ModuleManager @@ -35,7 +36,6 @@ import com.intellij.openapi.project.ex.ProjectNameProvider import com.intellij.openapi.project.impl.ProjectImpl import com.intellij.openapi.project.impl.ProjectManagerImpl.UnableToSaveProjectNotification import com.intellij.openapi.project.impl.ProjectStoreClassProvider -import com.intellij.openapi.util.Pair import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.io.FileUtilRt import com.intellij.openapi.util.registry.Registry @@ -200,7 +200,7 @@ internal abstract class ProjectStoreBase(override final val project: ProjectImpl else { result!!.sortWith(deprecatedComparator) StreamProviderFactory.EP_NAME.getExtensions(project).computeIfAny { - LOG.runAndLogException { it.customizeStorageSpecs(component, project, stateSpec, result!!, operation) } + LOG.runAndLogException { it.customizeStorageSpecs(component, storageManager, stateSpec, result!!, operation) } }?.let { // yes, DEPRECATED_PROJECT_FILE_STORAGE_ANNOTATION is not added in this case return it @@ -271,8 +271,8 @@ private open class ProjectStoreImpl(project: ProjectImpl, private val pathMacroM override val storageManager = ProjectStateStorageManager(pathMacroManager.createTrackingSubstitutor(), project) - override fun setPath(filePath: String) { - setPath(filePath, true, true) + override fun setPath(path: String) { + setPath(path, true, true) } override fun getProjectName(): String { @@ -320,7 +320,7 @@ private open class ProjectStoreImpl(project: ProjectImpl, private val pathMacroM } } - override fun doSave(saveSessions: List, readonlyFiles: MutableList>, prevErrors: MutableList?): MutableList? { + override fun doSave(saveSessions: List, readonlyFiles: MutableList, prevErrors: MutableList?): MutableList? { try { saveProjectName() } @@ -354,7 +354,7 @@ private open class ProjectStoreImpl(project: ProjectImpl, private val pathMacroM val oldList = readonlyFiles.toTypedArray() readonlyFiles.clear() for (entry in oldList) { - errors = executeSave(entry.first, readonlyFiles, errors) + errors = executeSave(entry.session, readonlyFiles, errors) } CompoundRuntimeException.throwIfNotEmpty(errors) @@ -367,7 +367,7 @@ private open class ProjectStoreImpl(project: ProjectImpl, private val pathMacroM return errors } - protected open fun beforeSave(readonlyFiles: List>) { + protected open fun beforeSave(readonlyFiles: MutableList) { } } @@ -381,10 +381,10 @@ private fun dropUnableToSaveProjectNotification(project: Project, readOnlyFiles: } } -private fun getFilesList(readonlyFiles: List>) = Array(readonlyFiles.size) { readonlyFiles[it].second } +private fun getFilesList(readonlyFiles: List) = Array(readonlyFiles.size) { readonlyFiles[it].file } private class ProjectWithModulesStoreImpl(project: ProjectImpl, pathMacroManager: PathMacroManager) : ProjectStoreImpl(project, pathMacroManager) { - override fun beforeSave(readonlyFiles: List>) { + override fun beforeSave(readonlyFiles: MutableList) { super.beforeSave(readonlyFiles) for (module in (ModuleManager.getInstance(project)?.modules ?: Module.EMPTY_ARRAY)) { diff --git a/platform/configuration-store-impl/src/SchemeManagerFactoryImpl.kt b/platform/configuration-store-impl/src/SchemeManagerFactoryImpl.kt index c32522f26502..d533aac4e5b2 100644 --- a/platform/configuration-store-impl/src/SchemeManagerFactoryImpl.kt +++ b/platform/configuration-store-impl/src/SchemeManagerFactoryImpl.kt @@ -51,7 +51,7 @@ sealed class SchemeManagerFactoryBase : SchemeManagerFactory(), SettingsSavingCo val path = checkPath(directoryName) val manager = SchemeManagerImpl(path, processor, - streamProvider ?: (componentManager?.stateStore?.stateStorageManager as? StateStorageManagerImpl)?.compoundStreamProvider, + streamProvider ?: (componentManager?.stateStore?.storageManager as? StateStorageManagerImpl)?.compoundStreamProvider, directoryPath ?: pathToFile(path), roamingType, presentableName, @@ -122,7 +122,7 @@ sealed class SchemeManagerFactoryBase : SchemeManagerFactory(), SettingsSavingCo return path } - override fun pathToFile(path: String) = Paths.get(ApplicationManager.getApplication().stateStore.stateStorageManager.expandMacros(ROOT_CONFIG), path)!! + override fun pathToFile(path: String) = Paths.get(ApplicationManager.getApplication().stateStore.storageManager.expandMacros(ROOT_CONFIG), path)!! } @Suppress("unused") diff --git a/platform/configuration-store-impl/src/StateStorageManagerImpl.kt b/platform/configuration-store-impl/src/StateStorageManagerImpl.kt index 0bf60ea7dba4..42a96fa29663 100644 --- a/platform/configuration-store-impl/src/StateStorageManagerImpl.kt +++ b/platform/configuration-store-impl/src/StateStorageManagerImpl.kt @@ -51,7 +51,7 @@ private val MACRO_PATTERN = Pattern.compile("(\\$[^$]*\\$)") */ open class StateStorageManagerImpl(private val rootTagName: String, override final val macroSubstitutor: TrackingPathMacroSubstitutor? = null, - val componentManager: ComponentManager? = null, + override val componentManager: ComponentManager? = null, private val virtualFileTracker: StorageVirtualFileTracker? = StateStorageManagerImpl.createDefaultVirtualTracker(componentManager) ) : StateStorageManager { private val macros: MutableList = ContainerUtil.createLockFreeCopyOnWriteList() private val storageLock = ReentrantReadWriteLock() @@ -73,6 +73,7 @@ open class StateStorageManagerImpl(private val rootTagName: String, } // access under storageLock + @Suppress("LeakingThis") private var isUseVfsListener = if (componentManager == null) ThreeState.NO else ThreeState.UNSURE // unsure because depends on stream provider state protected open val isUseXmlProlog: Boolean @@ -88,7 +89,7 @@ open class StateStorageManagerImpl(private val rootTagName: String, StorageVirtualFileTracker(componentManager.messageBus) } else -> { - val tracker = (ApplicationManager.getApplication().stateStore.stateStorageManager as? StateStorageManagerImpl)?.virtualFileTracker ?: return null + val tracker = (ApplicationManager.getApplication().stateStore.storageManager as? StateStorageManagerImpl)?.virtualFileTracker ?: return null Disposer.register(componentManager, Disposable { tracker.remove { it.storageManager.componentManager == componentManager } }) @@ -144,12 +145,14 @@ open class StateStorageManagerImpl(private val rootTagName: String, } } + @Suppress("CAST_NEVER_SUCCEEDS") override final fun getStateStorage(storageSpec: Storage) = getOrCreateStorage( storageSpec.path, storageSpec.roamingType, storageSpec.storageClass.java, storageSpec.stateSplitter.java, - storageSpec.exclusive + storageSpec.exclusive, + storageCreator = storageSpec as? StorageCreator ) protected open fun normalizeFileSpec(fileSpec: String): String { @@ -164,29 +167,24 @@ open class StateStorageManagerImpl(private val rootTagName: String, storageClass: Class = StateStorage::class.java, @Suppress("DEPRECATION") stateSplitter: Class = StateSplitterEx::class.java, exclusive: Boolean = false, - storageCustomizer: (StateStorage.() -> Unit)? = null): StateStorage { + storageCustomizer: (StateStorage.() -> Unit)? = null, + storageCreator: StorageCreator? = null): StateStorage { val normalizedCollapsedPath = normalizeFileSpec(collapsedPath) val key: String if (storageClass == StateStorage::class.java) { if (normalizedCollapsedPath.isEmpty()) { throw Exception("Normalized path is empty, raw path '$collapsedPath'") } - key = normalizedCollapsedPath + key = storageCreator?.key ?: normalizedCollapsedPath } else { - val storageClassName = storageClass.name!! - // we cannot change this ancient logic for now, so, detect this case manually - if (storageClassName === "com.intellij.openapi.externalSystem.configurationStore.ExternalProjectStorage") { - key = "$normalizedCollapsedPath@ExternalProjectStorage" - } - else { - key = storageClassName - } + key = storageClass.name!! } val storage = storageLock.read { storages.get(key) } ?: return storageLock.write { storages.getOrPut(key) { - val storage = createStateStorage(storageClass, normalizedCollapsedPath, roamingType, stateSplitter, exclusive) + @Suppress("IfThenToElvis") + val storage = if (storageCreator == null) createStateStorage(storageClass, normalizedCollapsedPath, roamingType, stateSplitter, exclusive) else storageCreator.create(this) storageCustomizer?.let { storage.it() } storage } diff --git a/platform/configuration-store-impl/src/StorageBaseEx.kt b/platform/configuration-store-impl/src/StorageBaseEx.kt index 0fe8ff6390e3..3d8d5c64654e 100644 --- a/platform/configuration-store-impl/src/StorageBaseEx.kt +++ b/platform/configuration-store-impl/src/StorageBaseEx.kt @@ -17,12 +17,15 @@ package com.intellij.configurationStore import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.components.PersistentStateComponent +import com.intellij.openapi.components.StateStorage import com.intellij.openapi.util.JDOMUtil import com.intellij.util.isEmpty import org.jdom.Element abstract class StorageBaseEx : StateStorageBase() { - fun createGetSession(component: PersistentStateComponent, componentName: String, stateClass: Class, reload: Boolean = false) = StateGetter(component, componentName, getStorageData(reload), stateClass, this) + fun createGetSession(component: PersistentStateComponent, componentName: String, stateClass: Class, reload: Boolean = false): StateGetter { + return StateGetterImpl(component, componentName, getStorageData(reload), stateClass, this) + } /** * serializedState is null if state equals to default (see XmlSerializer.serializeIfNotDefault) @@ -30,21 +33,42 @@ abstract class StorageBaseEx : StateStorageBase() { abstract fun archiveState(storageData: T, componentName: String, serializedState: Element?) } -class StateGetter(private val component: PersistentStateComponent, - private val componentName: String, - private val storageData: T, - private val stateClass: Class, - private val storage: StorageBaseEx) { - var serializedState: Element? = null +fun createStateGetter(isUseLoadedStateAsExisting: Boolean, storage: StateStorage, component: PersistentStateComponent, componentName: String, stateClass: Class, reloadData: Boolean): StateGetter { + if (isUseLoadedStateAsExisting && storage is StorageBaseEx<*>) { + return storage.createGetSession(component, componentName, stateClass, reloadData) + } - fun getState(mergeInto: S? = null): S? { + return object : StateGetter { + override fun getState(mergeInto: S?): S? { + return storage.getState(component, componentName, stateClass, mergeInto, reloadData) + } + + override fun close() { + } + } +} + +interface StateGetter { + fun getState(mergeInto: S? = null): S? + + fun close() +} + +private class StateGetterImpl(private val component: PersistentStateComponent, + private val componentName: String, + private val storageData: T, + private val stateClass: Class, + private val storage: StorageBaseEx) : StateGetter { + private var serializedState: Element? = null + + override fun getState(mergeInto: S?): S? { LOG.assertTrue(serializedState == null) - serializedState = storage.getSerializedState(storageData, component, componentName, false) + serializedState = storage.getSerializedState(storageData, component, componentName, archive = false) return storage.deserializeState(serializedState, stateClass, mergeInto) } - fun close() { + override fun close() { if (serializedState == null) { return } diff --git a/platform/configuration-store-impl/testSrc/ApplicationStoreTest.kt b/platform/configuration-store-impl/testSrc/ApplicationStoreTest.kt index cc529fc7efb7..61cbbbca68f1 100644 --- a/platform/configuration-store-impl/testSrc/ApplicationStoreTest.kt +++ b/platform/configuration-store-impl/testSrc/ApplicationStoreTest.kt @@ -127,7 +127,7 @@ internal class ApplicationStoreTest { @Test fun `export settings`() { testAppConfig.refreshVfs() - val storageManager = ApplicationManager.getApplication().stateStore.stateStorageManager + val storageManager = ApplicationManager.getApplication().stateStore.storageManager val optionsPath = storageManager.expandMacros(APP_CONFIG) val rootConfigPath = storageManager.expandMacros(ROOT_CONFIG) val map = getExportableComponentsMap(false, true, storageManager) diff --git a/platform/configuration-store-impl/testSrc/DefaultProjectStoreTest.kt b/platform/configuration-store-impl/testSrc/DefaultProjectStoreTest.kt index 60240d9cb263..641dfeb35aac 100644 --- a/platform/configuration-store-impl/testSrc/DefaultProjectStoreTest.kt +++ b/platform/configuration-store-impl/testSrc/DefaultProjectStoreTest.kt @@ -55,7 +55,7 @@ internal class DefaultProjectStoreTest { tempDirManager, WrapRule { val app = ApplicationManagerEx.getApplicationEx() - val path = Paths.get(app.stateStore.stateStorageManager.expandMacros(APP_CONFIG)) + val path = Paths.get(app.stateStore.storageManager.expandMacros(APP_CONFIG)) // dream about using in memory fs per test as ICS partially does and avoid such hacks path.refreshVfs() diff --git a/platform/configuration-store-impl/testSrc/DoNotSaveDefaults.kt b/platform/configuration-store-impl/testSrc/DoNotSaveDefaults.kt index b99a35e003de..a84d7364771a 100644 --- a/platform/configuration-store-impl/testSrc/DoNotSaveDefaults.kt +++ b/platform/configuration-store-impl/testSrc/DoNotSaveDefaults.kt @@ -99,7 +99,7 @@ class DoNotSaveDefaultsTest { } val directoryTree = printDirectoryTree(Paths.get( - componentManager.stateStore.stateStorageManager.expandMacros(APP_CONFIG)), setOf( + componentManager.stateStore.storageManager.expandMacros(APP_CONFIG)), setOf( "path.macros.xml" /* todo EP to register (provide) macro dynamically */, "stubIndex.xml" /* low-level non-roamable stuff */, "usage.statistics.xml" /* SHOW_NOTIFICATION_ATTR in internal mode */, diff --git a/platform/configuration-store-impl/testSrc/ModuleStoreRenameTest.kt b/platform/configuration-store-impl/testSrc/ModuleStoreRenameTest.kt index c8fb95883096..635a5a89184e 100644 --- a/platform/configuration-store-impl/testSrc/ModuleStoreRenameTest.kt +++ b/platform/configuration-store-impl/testSrc/ModuleStoreRenameTest.kt @@ -30,7 +30,7 @@ import java.util.* import kotlin.properties.Delegates private val Module.storage: FileBasedStorage - get() = (stateStore.stateStorageManager as StateStorageManagerImpl).getCachedFileStorages(listOf(StoragePathMacros.MODULE_FILE)).first() + get() = (stateStore.storageManager as StateStorageManagerImpl).getCachedFileStorages(listOf(StoragePathMacros.MODULE_FILE)).first() internal class ModuleStoreRenameTest { companion object { @@ -71,7 +71,7 @@ internal class ModuleStoreRenameTest { // should be invoked after project tearDown override fun after() { - (ApplicationManager.getApplication().stateStore.stateStorageManager as StateStorageManagerImpl).getVirtualFileTracker()!!.remove { + (ApplicationManager.getApplication().stateStore.storageManager as StateStorageManagerImpl).getVirtualFileTracker()!!.remove { if (it.storageManager.componentManager == module) { throw AssertionError("Storage manager is not disposed, module $module, storage $it") } @@ -127,7 +127,7 @@ internal class ModuleStoreRenameTest { assertThat(newFile).isRegularFile // ensure that macro value updated - assertThat(module.stateStore.stateStorageManager.expandMacros(StoragePathMacros.MODULE_FILE)).isEqualTo(newFile.systemIndependentPath) + assertThat(module.stateStore.storageManager.expandMacros(StoragePathMacros.MODULE_FILE)).isEqualTo(newFile.systemIndependentPath) runInEdtAndWait { dependentModule.saveStore() diff --git a/platform/configuration-store-impl/testSrc/ModuleStoreTest.kt b/platform/configuration-store-impl/testSrc/ModuleStoreTest.kt index c058e33504d9..ea67dfacc14c 100644 --- a/platform/configuration-store-impl/testSrc/ModuleStoreTest.kt +++ b/platform/configuration-store-impl/testSrc/ModuleStoreTest.kt @@ -117,7 +117,7 @@ class ModuleStoreTest { } fun Module.removeContentRoot() { - val modulePath = stateStore.stateStorageManager.expandMacros(StoragePathMacros.MODULE_FILE) + val modulePath = stateStore.storageManager.expandMacros(StoragePathMacros.MODULE_FILE) val moduleFile = Paths.get(modulePath) assertThat(moduleFile).isRegularFile diff --git a/platform/configuration-store-impl/testSrc/ProjectStoreTest.kt b/platform/configuration-store-impl/testSrc/ProjectStoreTest.kt index d6ddc55e937a..1418836fb4f3 100644 --- a/platform/configuration-store-impl/testSrc/ProjectStoreTest.kt +++ b/platform/configuration-store-impl/testSrc/ProjectStoreTest.kt @@ -75,7 +75,7 @@ internal class ProjectStoreTest { assertThat(project.basePath).isEqualTo(PathUtil.getParentPath((PathUtil.getParentPath(project.projectFilePath!!)))) // test reload on external change - val file = Paths.get(project.stateStore.stateStorageManager.expandMacros(PROJECT_FILE)) + val file = Paths.get(project.stateStore.storageManager.expandMacros(PROJECT_FILE)) file.write(file.readText().replace("""