diff --git a/platform/platform-impl/src/com/intellij/configurationStore/storeUtil.kt b/platform/platform-impl/src/com/intellij/configurationStore/storeUtil.kt index 59ae956eb882..dc2f40117e5e 100644 --- a/platform/platform-impl/src/com/intellij/configurationStore/storeUtil.kt +++ b/platform/platform-impl/src/com/intellij/configurationStore/storeUtil.kt @@ -190,6 +190,16 @@ fun getPerOsSettingsStorageFolderName(): String = when { else -> if (SystemInfoRt.isUnix) "unix" else "other_os" } +/** + * File names that are stored inside the options directory but may arrive with an environment-specific + * subdirectory prefix (e.g. "WSL-Ubuntu/jdk.table.xml"). Despite containing a path separator, they + * still need the "options/" prefix — unlike schema files which already carry their full relative path. + * + * Note: an identical set exists privately in OptionsDirectoryProcessor (intellij.java.compiler.impl), + * kept separate to avoid a cross-module dependency. + */ +private val ENVIRONMENT_SPECIFIC_OPTIONS_FILENAMES = setOf("jdk.table.xml", "applicationLibraries.xml") + /** * Converts fileSpec passed to [StreamProvider]'s methods to a relative path from the root config directory. */ @@ -197,7 +207,9 @@ fun getPerOsSettingsStorageFolderName(): String = when { fun getFileRelativeToRootConfig(fileSpecPassedToProvider: String): String = // For PersistentStateComponents the fileSpec is passed without the 'options' folder, e.g. 'editor.xml' or 'mac/keymaps.xml' // OTOH for schemas it is passed together with the containing folder, e.g. 'keymaps/my_keymap.xml' - if (!fileSpecPassedToProvider.contains("/") || fileSpecPassedToProvider.startsWith(getPerOsSettingsStorageFolderName() + "/")) { + if (!fileSpecPassedToProvider.contains("/") + || fileSpecPassedToProvider.startsWith(getPerOsSettingsStorageFolderName() + "/") + || ENVIRONMENT_SPECIFIC_OPTIONS_FILENAMES.any { fileSpecPassedToProvider.endsWith("/$it") }) { "${PathManager.OPTIONS_DIRECTORY}/${fileSpecPassedToProvider}" } else fileSpecPassedToProvider diff --git a/platform/settings-sync-core/tests/com/intellij/settingsSync/core/SettingsSyncIdeMediatorTest.kt b/platform/settings-sync-core/tests/com/intellij/settingsSync/core/SettingsSyncIdeMediatorTest.kt index e5596e462055..15e9d0b1fec9 100644 --- a/platform/settings-sync-core/tests/com/intellij/settingsSync/core/SettingsSyncIdeMediatorTest.kt +++ b/platform/settings-sync-core/tests/com/intellij/settingsSync/core/SettingsSyncIdeMediatorTest.kt @@ -2,6 +2,7 @@ package com.intellij.settingsSync.core import com.intellij.configurationStore.ComponentStoreImpl import com.intellij.configurationStore.StateStorageManager +import com.intellij.configurationStore.getFileRelativeToRootConfig import com.intellij.configurationStore.getStateSpec import com.intellij.ide.plugins.PluginManagerCore import com.intellij.idea.TestFor @@ -236,6 +237,22 @@ class SettingsSyncIdeMediatorTest : BasePlatformTestCase() { } } + @TestFor(issues = ["IJPL-222935"]) + @Test + fun `getFileRelativeToRootConfig prepends options for environment-specific file specs`() { + // Plain option files (no slash) → options/ prefix added + assertThat(getFileRelativeToRootConfig("jdk.table.xml")).isEqualTo("options/jdk.table.xml") + assertThat(getFileRelativeToRootConfig("applicationLibraries.xml")).isEqualTo("options/applicationLibraries.xml") + assertThat(getFileRelativeToRootConfig("editor.xml")).isEqualTo("options/editor.xml") + + // Environment-specific subdirectory prefix → options/ prefix must be added too + assertThat(getFileRelativeToRootConfig("WSL-Ubuntu/jdk.table.xml")).isEqualTo("options/WSL-Ubuntu/jdk.table.xml") + assertThat(getFileRelativeToRootConfig("WSL-Ubuntu/applicationLibraries.xml")).isEqualTo("options/WSL-Ubuntu/applicationLibraries.xml") + + // Schema paths (folder/file that is not an env-specific options file) → returned as-is + assertThat(getFileRelativeToRootConfig("keymaps/my_keymap.xml")).isEqualTo("keymaps/my_keymap.xml") + } + @State( name = "SecondComponent", storages = [Storage("second.xml")],