diff --git a/platform/configuration-store-impl/src/FileBasedStorage.kt b/platform/configuration-store-impl/src/FileBasedStorage.kt index 62b60d386f6a..e3f406d13484 100644 --- a/platform/configuration-store-impl/src/FileBasedStorage.kt +++ b/platform/configuration-store-impl/src/FileBasedStorage.kt @@ -203,7 +203,7 @@ fun writeFile(file: Path?, requestor: Any, virtualFile: VirtualFile?, element: E return result } -private val XML_PROLOG = """""".toByteArray() +internal val XML_PROLOG = """""".toByteArray() private fun isEqualContent(result: VirtualFile, lineSeparator: LineSeparator, content: BufferExposingByteArrayOutputStream, prependXmlProlog: Boolean): Boolean { val headerLength = if (!prependXmlProlog) 0 else XML_PROLOG.size + lineSeparator.separatorBytes.size diff --git a/platform/configuration-store-impl/src/ProjectStoreImpl.kt b/platform/configuration-store-impl/src/ProjectStoreImpl.kt index 62eff6a5e9db..eeb0827d81bd 100644 --- a/platform/configuration-store-impl/src/ProjectStoreImpl.kt +++ b/platform/configuration-store-impl/src/ProjectStoreImpl.kt @@ -422,58 +422,85 @@ private fun useOldWorkspaceContent(filePath: String, ws: File) { } } -private fun removeWorkspaceComponentConfiguration(defaultProject: Project, element: Element): List { +private fun moveComponentConfiguration(defaultProject: Project, element: Element, projectConfigDir: Path) { val componentElements = element.getChildren("component") if (componentElements.isEmpty()) { - return emptyList() + return } val workspaceComponentNames = THashSet(listOf("GradleLocalSettings")) + val compilerComponentNames = THashSet() + + fun processComponents(aClass: Class<*>) { + val stateAnnotation = StoreUtil.getStateSpec(aClass) + if (stateAnnotation == null || stateAnnotation.name.isEmpty()) { + return + } + + val storage = stateAnnotation.storages.sortByDeprecated().firstOrNull() ?: return + + when { + storage.path == StoragePathMacros.WORKSPACE_FILE -> workspaceComponentNames.add(stateAnnotation.name) + storage.path == "compiler.xml" -> compilerComponentNames.add(stateAnnotation.name) + } + } + @Suppress("DEPRECATION") val projectComponents = defaultProject.getComponents(PersistentStateComponent::class.java) projectComponents.forEachGuaranteed { - getNameIfWorkspaceStorage(it.javaClass)?.let { - workspaceComponentNames.add(it) - } + processComponents(it.javaClass) } ServiceManagerImpl.processAllImplementationClasses(defaultProject as ProjectImpl) { aClass, _ -> - getNameIfWorkspaceStorage(aClass)?.let { - workspaceComponentNames.add(it) - } + processComponents(aClass) true } - val result = SmartList() + @Suppress("RemoveExplicitTypeArguments") + val elements = mapOf(compilerComponentNames to SmartList(), workspaceComponentNames to SmartList()) val iterator = componentElements.iterator() for (componentElement in iterator) { val name = componentElement.getAttributeValue("name") ?: continue - if (workspaceComponentNames.contains(name)) { - iterator.remove() - result.add(componentElement) + for ((names, list) in elements) { + if (names.contains(name)) { + iterator.remove() + list.add(componentElement) + } } } - return result + + for ((names, list) in elements) { + writeConfigFile(list, projectConfigDir.resolve(if (names === workspaceComponentNames) "workspace.xml" else "compiler.xml")) + } +} + +private fun writeConfigFile(elements: List, file: Path) { + if (elements.isEmpty()) { + return + } + + var wrapper = Element("project").attribute("version", "4") + if (file.exists()) { + try { + wrapper = loadElement(file) + } + catch (e: Exception) { + LOG.warn(e) + } + } + elements.forEach { wrapper.addContent(it) } + // .idea component configuration files uses XML prolog due to historical reasons + file.outputStream().use { + it.write(XML_PROLOG) + it.write(LineSeparator.LF.separatorBytes) + wrapper.write(it) + } } // public only to test fun normalizeDefaultProjectElement(defaultProject: Project, element: Element, projectConfigDir: Path) { LOG.runAndLogException { - val workspaceElements = removeWorkspaceComponentConfiguration(defaultProject, element) - if (workspaceElements.isNotEmpty()) { - val workspaceFile = projectConfigDir.resolve("workspace.xml") - var wrapper = Element("project").attribute("version", "4") - if (workspaceFile.exists()) { - try { - wrapper = loadElement(workspaceFile) - } - catch (e: Exception) { - LOG.warn(e) - } - } - workspaceElements.forEach { wrapper.addContent(it) } - wrapper.write(workspaceFile) - } + moveComponentConfiguration(defaultProject, element, projectConfigDir) } LOG.runAndLogException { @@ -525,14 +552,4 @@ private fun convertProfiles(profileIterator: MutableIterator, component val path = schemeDir.resolve("${FileUtil.sanitizeFileName(schemeName, true)}.xml") JDOMUtil.write(wrapper, path.outputStream(), "\n") } -} - -private fun getNameIfWorkspaceStorage(aClass: Class<*>): String? { - val stateAnnotation = StoreUtil.getStateSpec(aClass) - if (stateAnnotation == null || stateAnnotation.name.isEmpty()) { - return null - } - - val storage = stateAnnotation.storages.sortByDeprecated().firstOrNull() ?: return null - return if (storage.path == StoragePathMacros.WORKSPACE_FILE) stateAnnotation.name else null } \ No newline at end of file diff --git a/platform/configuration-store-impl/testSrc/DefaultProjectStoreTest.kt b/platform/configuration-store-impl/testSrc/DefaultProjectStoreTest.kt index c0f0ef5c1dd3..2eef245e460b 100644 --- a/platform/configuration-store-impl/testSrc/DefaultProjectStoreTest.kt +++ b/platform/configuration-store-impl/testSrc/DefaultProjectStoreTest.kt @@ -116,6 +116,9 @@ internal class DefaultProjectStoreTest {