mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-05 01:50:56 +07:00
IJPL-191229 prepare to fix parallel blocking access to PathMacros (part 2 - rename old method to initComponentBlocking)
GitOrigin-RevId: 5bf201800edf138b10571ce12d40caa08b6039cd
This commit is contained in:
committed by
intellij-monorepo-bot
parent
add197a048
commit
ba405b64db
@@ -127,7 +127,11 @@ abstract class ComponentStoreImpl : IComponentStore {
|
||||
storageManager.clearStorages()
|
||||
}
|
||||
|
||||
override fun initComponent(component: Any, serviceDescriptor: ServiceDescriptor?, pluginId: PluginId) {
|
||||
override suspend fun initComponent(component: Any, serviceDescriptor: ServiceDescriptor?, pluginId: PluginId) {
|
||||
initComponentBlocking(component = component, serviceDescriptor = serviceDescriptor, pluginId = pluginId)
|
||||
}
|
||||
|
||||
override fun initComponentBlocking(component: Any, serviceDescriptor: ServiceDescriptor?, pluginId: PluginId) {
|
||||
var componentName: String? = null
|
||||
try {
|
||||
@Suppress("DEPRECATION")
|
||||
@@ -180,10 +184,14 @@ abstract class ComponentStoreImpl : IComponentStore {
|
||||
if (e is ControlFlowException) {
|
||||
throw e
|
||||
}
|
||||
LOG.error(PluginException("Cannot init component state (componentName=$componentName, componentClass=${component.javaClass.simpleName})", e, pluginId))
|
||||
error(PluginException("Cannot init component state (componentName=$componentName, componentClass=${component.javaClass.simpleName})", e, pluginId))
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun error(error: PluginException) {
|
||||
LOG.error(error)
|
||||
}
|
||||
|
||||
private fun initJdom(@Suppress("DEPRECATION") component: com.intellij.openapi.util.JDOMExternalizable, pluginId: PluginId): String {
|
||||
if (component.javaClass.name !in ignoredDeprecatedJDomExternalizableComponents) {
|
||||
LOG.error(PluginException("""
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.configurationStore
|
||||
|
||||
import com.intellij.openapi.application.EDT
|
||||
@@ -36,7 +36,14 @@ abstract class ComponentStoreWithExtraComponents : ComponentStoreImpl() {
|
||||
result
|
||||
}
|
||||
|
||||
final override fun initComponent(component: Any, serviceDescriptor: ServiceDescriptor?, pluginId: PluginId) {
|
||||
final override fun initComponentBlocking(component: Any, serviceDescriptor: ServiceDescriptor?, pluginId: PluginId) {
|
||||
if (component is SettingsSavingComponent) {
|
||||
asyncSettingsSavingComponents.drop()
|
||||
}
|
||||
super.initComponentBlocking(component = component, serviceDescriptor = serviceDescriptor, pluginId = pluginId)
|
||||
}
|
||||
|
||||
final override suspend fun initComponent(component: Any, serviceDescriptor: ServiceDescriptor?, pluginId: PluginId) {
|
||||
if (component is SettingsSavingComponent) {
|
||||
asyncSettingsSavingComponents.drop()
|
||||
}
|
||||
|
||||
@@ -12,7 +12,10 @@ object NonPersistentModuleStore : IComponentStore {
|
||||
override val storageManager: StateStorageManager
|
||||
get() = NonPersistentStateStorageManager
|
||||
|
||||
override fun initComponent(component: Any, serviceDescriptor: ServiceDescriptor?, pluginId: PluginId) {
|
||||
override fun initComponentBlocking(component: Any, serviceDescriptor: ServiceDescriptor?, pluginId: PluginId) {
|
||||
}
|
||||
|
||||
override suspend fun initComponent(component: Any, serviceDescriptor: ServiceDescriptor?, pluginId: PluginId) {
|
||||
}
|
||||
|
||||
override fun unloadComponent(component: Any) {}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
package com.intellij.configurationStore
|
||||
|
||||
import com.intellij.configurationStore.schemeManager.ROOT_CONFIG
|
||||
import com.intellij.diagnostic.PluginException
|
||||
import com.intellij.ide.plugins.PluginManagerCore
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.components.*
|
||||
@@ -19,7 +20,6 @@ import com.intellij.util.xmlb.XmlSerializerUtil
|
||||
import com.intellij.util.xmlb.annotations.Attribute
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||
import org.assertj.core.data.MapEntry
|
||||
import org.intellij.lang.annotations.Language
|
||||
import org.junit.Assert.*
|
||||
@@ -69,13 +69,13 @@ class ApplicationStoreTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `load from stream provider`() {
|
||||
fun `load from stream provider`(): Unit = runBlocking(Dispatchers.Default) {
|
||||
val component = SeveralStoragesConfigured()
|
||||
|
||||
val streamProvider = MyStreamProvider()
|
||||
val map = HashMap<String, String>()
|
||||
val fileSpec = "new.xml"
|
||||
map[fileSpec] = "<application>\n <component name=\"A\" foo=\"newValue\" />\n</application>"
|
||||
map.put(fileSpec, "<application>\n <component name=\"A\" foo=\"newValue\" />\n</application>")
|
||||
streamProvider.data.put(RoamingType.DEFAULT, map)
|
||||
|
||||
val storageManager = componentStore.storageManager
|
||||
@@ -141,7 +141,7 @@ class ApplicationStoreTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `import settings`() {
|
||||
fun `import settings`() = runBlocking<Unit>(Dispatchers.Default) {
|
||||
val component = A()
|
||||
componentStore.initComponent(component, null, PluginManagerCore.CORE_ID)
|
||||
|
||||
@@ -232,7 +232,7 @@ class ApplicationStoreTest {
|
||||
private fun createComponentData(fooValue: String, componentName: String = "A") = """<component name="$componentName" foo="$fooValue" />"""
|
||||
|
||||
@Test
|
||||
fun `remove data from deprecated storage if another component data exists`() = runBlocking<Unit> {
|
||||
fun `remove data from deprecated storage if another component data exists`() = runBlocking<Unit>(Dispatchers.Default) {
|
||||
val data = createComponentData("new")
|
||||
val oldFile = writeConfig("old.xml", """<application>
|
||||
<component name="OtherComponent" foo="old" />
|
||||
@@ -254,7 +254,7 @@ class ApplicationStoreTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `don't save if only format is changed`() = runBlocking<Unit> {
|
||||
fun `don't save if only format is changed`() = runBlocking<Unit>(Dispatchers.Default) {
|
||||
val oldContent = """<application><component name="A" foo="old" deprecated="old"/></application>"""
|
||||
val file = writeConfig("a.xml", oldContent)
|
||||
val oldModificationTime = file.getLastModifiedTime()
|
||||
@@ -280,15 +280,18 @@ class ApplicationStoreTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `loadState failed with exception it won't be called next time`() {
|
||||
fun `loadState failed with exception it won't be called next time`() = runBlocking<Unit>(Dispatchers.Default) {
|
||||
writeConfig("a.xml", """<application><component name="A" foo="old" deprecated="old"/></application>""")
|
||||
testAppConfig.refreshVfs()
|
||||
|
||||
val component = A()
|
||||
component.isThrowErrorOnLoadState = true
|
||||
assertThatThrownBy {
|
||||
try {
|
||||
componentStore.initComponent(component, null, PluginManagerCore.CORE_ID)
|
||||
}.isInstanceOf(ProcessCanceledException::class.java)
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
assertThat(e).isInstanceOf(ProcessCanceledException::class.java)
|
||||
}
|
||||
assertThat(component.options).isEqualTo(TestState())
|
||||
|
||||
component.isThrowErrorOnLoadState = false
|
||||
@@ -420,7 +423,7 @@ class ApplicationStoreTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `survive on error`() {
|
||||
fun `survive on error`() = runBlocking<Unit>(Dispatchers.Default) {
|
||||
@State(name = "Bad", storages = [Storage(value = "foo.xml")])
|
||||
class MyComponent : PersistentStateComponent<Foo> {
|
||||
override fun loadState(state: Foo) {
|
||||
@@ -437,16 +440,17 @@ class ApplicationStoreTest {
|
||||
}
|
||||
|
||||
val component = MyComponent()
|
||||
rethrowLoggedErrorsIn {
|
||||
assertThatThrownBy {
|
||||
componentStore.initComponent(component, null, PluginManagerCore.CORE_ID)
|
||||
}.hasMessage("Cannot init component state (componentName=Bad, componentClass=MyComponent) [Plugin: com.intellij]")
|
||||
try {
|
||||
componentStore.initComponent(component, null, PluginManagerCore.CORE_ID)
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
assertThat(e.message).contains("Cannot init component state (componentName=Bad, componentClass=MyComponent) [Plugin: com.intellij]")
|
||||
}
|
||||
assertThat(componentStore.getComponents()).doesNotContainKey("Bad")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test per-os components are stored in subfolder`() = runBlocking {
|
||||
fun `test per-os components are stored in subfolder`() = runBlocking(Dispatchers.Default) {
|
||||
val component = PerOsComponent()
|
||||
componentStore.initComponent(component, null, PluginManagerCore.CORE_ID)
|
||||
component.foo = "bar"
|
||||
@@ -478,7 +482,7 @@ class ApplicationStoreTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `per-os setting is preferred from os subfolder`() {
|
||||
fun `per-os setting is preferred from os subfolder`() = runBlocking<Unit>(Dispatchers.Default) {
|
||||
val osCode = getPerOsSettingsStorageFolderName()
|
||||
writeConfig("per-os.xml", "<application>${createComponentData("old")}</application>")
|
||||
writeConfig("${osCode}/per-os.xml", "<application>${createComponentData("new")}</application>")
|
||||
@@ -514,7 +518,7 @@ class ApplicationStoreTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `reload components`() {
|
||||
fun `reload components`() = runBlocking<Unit>(Dispatchers.Default) {
|
||||
@State(name = "A", storages = [Storage(value = "a.xml")])
|
||||
class Component : FooComponent()
|
||||
|
||||
@@ -655,6 +659,10 @@ class ApplicationStoreTest {
|
||||
// yes, in tests APP_CONFIG equals to ROOT_CONFIG (as ICS does)
|
||||
storageManager.setMacros(listOf(Macro(APP_CONFIG, path), Macro(ROOT_CONFIG, path), Macro(StoragePathMacros.CACHE_FILE, path)))
|
||||
}
|
||||
|
||||
override fun error(error: PluginException) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
private abstract class FooComponent : PersistentStateComponent<Foo> {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.configurationStore
|
||||
|
||||
import com.intellij.configurationStore.schemeManager.ROOT_CONFIG
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.configurationStore
|
||||
|
||||
import com.intellij.ide.highlighter.ProjectFileType
|
||||
@@ -6,8 +6,8 @@ import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.application.EDT
|
||||
import com.intellij.openapi.application.ex.PathManagerEx
|
||||
import com.intellij.openapi.components.Service
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.components.impl.stores.stateStore
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.project.ProjectManager
|
||||
import com.intellij.openapi.project.ex.ProjectManagerEx
|
||||
@@ -36,7 +36,7 @@ class DefaultProjectStoreTest {
|
||||
@JvmField @Rule val fsRule = InMemoryFsRule()
|
||||
|
||||
@Test
|
||||
fun `new project from default - file-based storage`() {
|
||||
fun `new project from default - file-based storage`() = runBlocking(Dispatchers.Default) {
|
||||
checkDefaultProjectAsTemplate { checkTask ->
|
||||
val project = openAsNewProjectAndUseDefaultSettings(fsRule.fs.getPath("/test${ProjectFileType.DOT_DEFAULT_EXTENSION}"))
|
||||
project.useProject {
|
||||
@@ -46,7 +46,7 @@ class DefaultProjectStoreTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `new project from default - directory-based storage`() {
|
||||
fun `new project from default - directory-based storage`() = runBlocking(Dispatchers.Default) {
|
||||
checkDefaultProjectAsTemplate { checkTask ->
|
||||
// obviously, the project must be directory-based also
|
||||
val project = openAsNewProjectAndUseDefaultSettings(fsRule.fs.getPath("/test"))
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.configurationStore
|
||||
|
||||
import com.intellij.ide.highlighter.ProjectFileType
|
||||
@@ -19,6 +19,7 @@ import com.intellij.project.stateStore
|
||||
import com.intellij.testFramework.*
|
||||
import com.intellij.testFramework.assertions.Assertions.assertThat
|
||||
import com.intellij.util.PathUtil
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.intellij.lang.annotations.Language
|
||||
import org.junit.ClassRule
|
||||
@@ -227,7 +228,7 @@ class ProjectStoreTest {
|
||||
|
||||
// heavy test that uses ProjectManagerImpl directly to test (opposite to DefaultProjectStoreTest)
|
||||
@Test
|
||||
fun `just created project must inherit settings from the default project`() {
|
||||
fun `just created project must inherit settings from the default project`() = runBlocking<Unit>(Dispatchers.Default) {
|
||||
val projectManager = ProjectManagerEx.getInstanceEx()
|
||||
|
||||
val testComponent = TestComponent()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.openapi.project
|
||||
|
||||
import com.intellij.ide.CommandLineProcessor
|
||||
@@ -10,6 +10,7 @@ import com.intellij.testFramework.*
|
||||
import com.intellij.testFramework.assertions.Assertions.assertThat
|
||||
import com.intellij.testFramework.rules.checkDefaultProjectAsTemplate
|
||||
import com.intellij.util.io.createDirectories
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.ClassRule
|
||||
import org.junit.Rule
|
||||
@@ -52,7 +53,7 @@ internal class OpenProjectTest(private val opener: Opener) {
|
||||
val disposableRule = DisposableRule()
|
||||
|
||||
@Test
|
||||
fun `open valid existing project dir with ability to attach`() {
|
||||
fun `open valid existing project dir with ability to attach`() = runBlocking(Dispatchers.Default) {
|
||||
ExtensionTestUtil.maskExtensions(ProjectAttachProcessor.EP_NAME, listOf(ModuleAttachProcessor()), disposableRule.disposable)
|
||||
val projectDir = tempDir.newPath("project")
|
||||
projectDir.resolve(".idea").createDirectories()
|
||||
@@ -60,7 +61,7 @@ internal class OpenProjectTest(private val opener: Opener) {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `open clean existing project dir with ability to attach`() {
|
||||
fun `open clean existing project dir with ability to attach`() = runBlocking(Dispatchers.Default) {
|
||||
ExtensionTestUtil.maskExtensions(ProjectAttachProcessor.EP_NAME, listOf(ModuleAttachProcessor()), disposableRule.disposable)
|
||||
val projectDir = tempDir.newPath("project")
|
||||
projectDir.createDirectories()
|
||||
@@ -68,7 +69,7 @@ internal class OpenProjectTest(private val opener: Opener) {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `open valid existing project dir with inability to attach`() {
|
||||
fun `open valid existing project dir with inability to attach`() = runBlocking(Dispatchers.Default) {
|
||||
// Regardless of product (Idea vs PhpStorm), if .idea directory exists, but no modules, we must run configurators to add some module.
|
||||
// Maybe not fully clear why it is performed as part of project opening and silently, but it is existing behaviour.
|
||||
// So, existing behaviour should be preserved and any changes should be done not as part of task "use unified API to open project", but separately later.
|
||||
@@ -79,14 +80,17 @@ internal class OpenProjectTest(private val opener: Opener) {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `open clean existing project dir with inability to attach`() {
|
||||
fun `open clean existing project dir with inability to attach`() = runBlocking(Dispatchers.Default) {
|
||||
ExtensionTestUtil.maskExtensions(ProjectAttachProcessor.EP_NAME, listOf(), disposableRule.disposable)
|
||||
val projectDir = tempDir.newPath("project")
|
||||
projectDir.createDirectories()
|
||||
openUsingOpenFileActionAndAssertThatProjectContainsOneModule(projectDir, defaultProjectTemplateShouldBeApplied = true)
|
||||
}
|
||||
|
||||
private fun openUsingOpenFileActionAndAssertThatProjectContainsOneModule(projectDir: Path, defaultProjectTemplateShouldBeApplied: Boolean) {
|
||||
private suspend fun openUsingOpenFileActionAndAssertThatProjectContainsOneModule(
|
||||
projectDir: Path,
|
||||
defaultProjectTemplateShouldBeApplied: Boolean,
|
||||
) {
|
||||
checkDefaultProjectAsTemplate { checkDefaultProjectAsTemplateTask ->
|
||||
val project = opener.opener(projectDir)!!
|
||||
project.useProject {
|
||||
|
||||
@@ -22,7 +22,9 @@ interface IComponentStore {
|
||||
fun setPath(path: Path) {
|
||||
}
|
||||
|
||||
fun initComponent(component: Any, serviceDescriptor: ServiceDescriptor?, pluginId: PluginId)
|
||||
fun initComponentBlocking(component: Any, serviceDescriptor: ServiceDescriptor?, pluginId: PluginId)
|
||||
|
||||
suspend fun initComponent(component: Any, serviceDescriptor: ServiceDescriptor?, pluginId: PluginId)
|
||||
|
||||
fun unloadComponent(component: Any)
|
||||
|
||||
|
||||
@@ -612,17 +612,17 @@ abstract class ComponentManagerImpl(
|
||||
}
|
||||
}
|
||||
|
||||
internal fun initializeService(component: Any, serviceDescriptor: ServiceDescriptor?, pluginId: PluginId) {
|
||||
internal suspend fun initializeService(component: Any, serviceDescriptor: ServiceDescriptor?, pluginId: PluginId) {
|
||||
initializeService(component = component, serviceDescriptor = serviceDescriptor, pluginId = pluginId) {
|
||||
it()
|
||||
}
|
||||
}
|
||||
|
||||
internal inline fun initializeService(
|
||||
internal suspend inline fun initializeService(
|
||||
component: Any,
|
||||
serviceDescriptor: ServiceDescriptor?,
|
||||
pluginId: PluginId,
|
||||
invocator: (() -> Unit) -> Unit,
|
||||
invocator: suspend (() -> Unit) -> Unit,
|
||||
) {
|
||||
@Suppress("DEPRECATION")
|
||||
if ((serviceDescriptor == null || !isPreInitialized(component)) &&
|
||||
@@ -633,7 +633,7 @@ abstract class ComponentManagerImpl(
|
||||
}
|
||||
|
||||
invocator {
|
||||
componentStore.initComponent(component = component, serviceDescriptor = serviceDescriptor, pluginId = pluginId)
|
||||
componentStore.initComponentBlocking(component = component, serviceDescriptor = serviceDescriptor, pluginId = pluginId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,10 @@ private class TestComponentStore : IComponentStore {
|
||||
override val storageManager: StateStorageManager
|
||||
get() = TODO("not implemented")
|
||||
|
||||
override fun initComponent(component: Any, serviceDescriptor: ServiceDescriptor?, pluginId: PluginId) {
|
||||
override fun initComponentBlocking(component: Any, serviceDescriptor: ServiceDescriptor?, pluginId: PluginId) {
|
||||
}
|
||||
|
||||
override suspend fun initComponent(component: Any, serviceDescriptor: ServiceDescriptor?, pluginId: PluginId) {
|
||||
}
|
||||
|
||||
override fun unloadComponent(component: Any) {
|
||||
|
||||
@@ -13,6 +13,7 @@ jvm_library(
|
||||
visibility = ["//visibility:public"],
|
||||
srcs = glob(["src/**/*.kt", "src/**/*.java"], allow_empty = True),
|
||||
deps = [
|
||||
"@lib//:kotlin-stdlib",
|
||||
"//platform/analysis-api:analysis",
|
||||
"//platform/util/concurrency",
|
||||
"//platform/diff-api:diff",
|
||||
@@ -57,6 +58,7 @@ jvm_library(
|
||||
srcs = glob(["tests/**/*.kt", "tests/**/*.java"], allow_empty = True),
|
||||
associates = [":settingsSync-core"],
|
||||
deps = [
|
||||
"@lib//:kotlin-stdlib",
|
||||
"//platform/analysis-api:analysis",
|
||||
"//platform/util/concurrency",
|
||||
"//platform/util/concurrency:concurrency_test_lib",
|
||||
@@ -106,6 +108,7 @@ jvm_library(
|
||||
"//platform/vcs-impl",
|
||||
"//platform/vcs-impl:vcs-impl_test_lib",
|
||||
"//platform/diff-impl",
|
||||
"@lib//:assert_j",
|
||||
],
|
||||
runtime_deps = [":settingsSync-core_resources"]
|
||||
)
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="kotlin-stdlib" level="project" />
|
||||
<orderEntry type="module" module-name="intellij.platform.analysis" />
|
||||
<orderEntry type="module" module-name="intellij.platform.concurrency" />
|
||||
<orderEntry type="module" module-name="intellij.platform.diff" />
|
||||
@@ -69,5 +70,6 @@
|
||||
<orderEntry type="module" module-name="intellij.platform.vcs.log" />
|
||||
<orderEntry type="module" module-name="intellij.platform.vcs.impl" />
|
||||
<orderEntry type="module" module-name="intellij.platform.diff.impl" />
|
||||
<orderEntry type="library" scope="TEST" name="assertJ" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -195,7 +195,7 @@ internal class SettingsSyncIdeMediatorImpl(private val componentStore: Component
|
||||
if (!folder.exists()) return true
|
||||
|
||||
Files.walkFileTree(folder, object : SimpleFileVisitor<Path>() {
|
||||
override fun visitFile(file: Path, attrs: BasicFileAttributes?): FileVisitResult {
|
||||
override fun visitFile(file: Path, attrs: BasicFileAttributes): FileVisitResult {
|
||||
if (!filter(file.name)) return FileVisitResult.CONTINUE
|
||||
if (!file.isRegularFile()) return FileVisitResult.CONTINUE
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ import com.intellij.testFramework.common.timeoutRunBlocking
|
||||
import com.intellij.testFramework.common.waitUntil
|
||||
import com.intellij.testFramework.registerExtension
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Assertions.assertNotNull
|
||||
@@ -27,7 +26,7 @@ internal class SettingsProviderTest : SettingsSyncRealIdeTestBase() {
|
||||
fun `settings from provider should be collected`() = timeoutRunBlockingAndStopBridge {
|
||||
val ideState = TestState("IDE value")
|
||||
settingsProvider.settings = ideState
|
||||
GeneralSettings.getInstance().initModifyAndSave {
|
||||
initModifyAndSave(GeneralSettings.getInstance()) {
|
||||
autoSaveFiles = false
|
||||
}
|
||||
|
||||
|
||||
@@ -10,12 +10,15 @@ import com.intellij.openapi.components.*
|
||||
import com.intellij.openapi.components.impl.stores.stateStore
|
||||
import com.intellij.testFramework.fixtures.BasePlatformTestCase
|
||||
import com.intellij.testFramework.rules.InMemoryFsRule
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.test.StandardTestDispatcher
|
||||
import kotlinx.coroutines.test.TestCoroutineScheduler
|
||||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.runCurrent
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Assert
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
@@ -25,14 +28,12 @@ import java.nio.file.Path
|
||||
import java.time.Instant
|
||||
import kotlin.io.path.createDirectories
|
||||
import kotlin.io.path.createFile
|
||||
import kotlin.io.path.div
|
||||
import kotlin.io.path.pathString
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
@RunWith(JUnit4::class)
|
||||
class SettingsSyncIdeMediatorTest : BasePlatformTestCase() {
|
||||
|
||||
protected lateinit var testScope: TestScope
|
||||
private lateinit var testScope: TestScope
|
||||
|
||||
override fun setUp() {
|
||||
super.setUp()
|
||||
@@ -44,7 +45,7 @@ class SettingsSyncIdeMediatorTest : BasePlatformTestCase() {
|
||||
|
||||
@Test
|
||||
fun `process children with subfolders`() {
|
||||
val rootConfig = memoryFs.fs.getPath("/appconfig")
|
||||
val rootConfig = memoryFs.fs.getPath("/appConfig")
|
||||
val componentStore = object : ComponentStoreImpl() {
|
||||
override val storageManager: StateStorageManager
|
||||
get() = TODO("Not yet implemented")
|
||||
@@ -55,17 +56,22 @@ class SettingsSyncIdeMediatorTest : BasePlatformTestCase() {
|
||||
}
|
||||
val mediator = SettingsSyncIdeMediatorImpl(componentStore, rootConfig, {true})
|
||||
|
||||
val fileTypes = rootConfig / "filetypes"
|
||||
val code = (fileTypes / "code").createDirectories()
|
||||
(code / "mytemplate.kt").createFile()
|
||||
val fileTypes = rootConfig.resolve("filetypes")
|
||||
val code = fileTypes.resolve("code").createDirectories()
|
||||
code.resolve("myTemplate.kt").createFile()
|
||||
|
||||
val visited = mutableSetOf<String>()
|
||||
mediator.processChildren(fileTypes.pathString, RoamingType.DEFAULT, {true}, processor = { name, _, _ ->
|
||||
visited += name
|
||||
true
|
||||
})
|
||||
val visited = HashSet<String>()
|
||||
mediator.processChildren(
|
||||
path = fileTypes.pathString,
|
||||
roamingType = RoamingType.DEFAULT,
|
||||
filter = { true },
|
||||
processor = { name, _, _ ->
|
||||
visited += name
|
||||
true
|
||||
},
|
||||
)
|
||||
|
||||
assertEquals(setOf("mytemplate.kt"), visited)
|
||||
assertThat(visited).containsExactlyInAnyOrder("myTemplate.kt")
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -133,12 +139,16 @@ true
|
||||
val callbackCalls = mutableListOf<String>()
|
||||
val firstComponent = FirstComponent({ callbackCalls.add("First") })
|
||||
componentManager.registerComponentInstance(FirstComponent::class.java, firstComponent)
|
||||
componentStore.initComponent(firstComponent, null, PluginManagerCore.CORE_ID)
|
||||
runBlocking(Dispatchers.Default) {
|
||||
componentStore.initComponent(firstComponent, null, PluginManagerCore.CORE_ID)
|
||||
}
|
||||
componentStore.storageManager.getStateStorage(getStateSpec(FirstComponent::class.java)!!.storages[0]).createSaveSessionProducer()
|
||||
|
||||
val secondComponent = SecondComponent({ callbackCalls.add("Second") })
|
||||
componentManager.registerComponentInstance(SecondComponent::class.java, secondComponent)
|
||||
componentStore.initComponent(secondComponent, null, PluginManagerCore.CORE_ID)
|
||||
runBlocking(Dispatchers.Default) {
|
||||
componentStore.initComponent(secondComponent, null, PluginManagerCore.CORE_ID)
|
||||
}
|
||||
componentStore.storageManager.getStateStorage(getStateSpec(SecondComponent::class.java)!!.storages[0]).createSaveSessionProducer()
|
||||
|
||||
val mediator = SettingsSyncIdeMediatorImpl(componentStore = componentStore, rootConfig = rootConfig) { true }
|
||||
|
||||
@@ -6,7 +6,8 @@ import com.intellij.ide.fileTemplates.FileTemplateManager
|
||||
import com.intellij.ide.ui.UISettings
|
||||
import com.intellij.idea.TestFor
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.components.*
|
||||
import com.intellij.openapi.components.SettingsCategory
|
||||
import com.intellij.openapi.components.State
|
||||
import com.intellij.openapi.editor.ex.EditorSettingsExternalizable
|
||||
import com.intellij.openapi.keymap.impl.KeymapImpl
|
||||
import com.intellij.openapi.keymap.impl.KeymapManagerImpl
|
||||
@@ -14,6 +15,7 @@ import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.settingsSync.core.SettingsSnapshot.MetaInfo
|
||||
import com.intellij.util.toByteArray
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.jupiter.api.Assertions
|
||||
import org.junit.jupiter.api.Test
|
||||
@@ -28,14 +30,16 @@ internal class SettingsSyncRealIdeTest : SettingsSyncRealIdeTestBase() {
|
||||
|
||||
@Test
|
||||
fun `settings are pushed`() = timeoutRunBlockingAndStopBridge {
|
||||
SettingsSyncSettings.getInstance().init()
|
||||
init(SettingsSyncSettings.getInstance())
|
||||
SettingsSyncSettings.getInstance().migrationFromOldStorageChecked = true
|
||||
saveComponentStore()
|
||||
componentStore.save()
|
||||
initSettingsSync(SettingsSyncBridge.InitMode.PushToServer)
|
||||
|
||||
executeAndWaitUntilPushed {
|
||||
GeneralSettings.getInstance().initModifyAndSave {
|
||||
autoSaveFiles = false
|
||||
runBlocking(Dispatchers.Default) {
|
||||
initModifyAndSave(GeneralSettings.getInstance()) {
|
||||
autoSaveFiles = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +59,7 @@ internal class SettingsSyncRealIdeTest : SettingsSyncRealIdeTestBase() {
|
||||
|
||||
val keymap = createKeymap()
|
||||
executeAndWaitUntilPushed {
|
||||
saveComponentStore()
|
||||
runBlocking(Dispatchers.IO) { componentStore.save() }
|
||||
}
|
||||
|
||||
assertServerSnapshot {
|
||||
@@ -76,7 +80,7 @@ internal class SettingsSyncRealIdeTest : SettingsSyncRealIdeTestBase() {
|
||||
fileTemplate.text= phpCode
|
||||
FileTemplateManager.getDefaultInstance().saveAllTemplates()
|
||||
executeAndWaitUntilPushed {
|
||||
saveComponentStore()
|
||||
runBlocking(Dispatchers.IO) { componentStore.save() }
|
||||
}
|
||||
|
||||
assertServerSnapshot {
|
||||
@@ -95,18 +99,14 @@ internal class SettingsSyncRealIdeTest : SettingsSyncRealIdeTestBase() {
|
||||
return keymap
|
||||
}
|
||||
|
||||
private fun saveComponentStore() {
|
||||
runBlocking { componentStore.save() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `quickly modified settings are pushed together`() = timeoutRunBlockingAndStopBridge {
|
||||
initSettingsSync(SettingsSyncBridge.InitMode.JustInit)
|
||||
|
||||
GeneralSettings.getInstance().initModifyAndSave {
|
||||
initModifyAndSave(GeneralSettings.getInstance()) {
|
||||
autoSaveFiles = false
|
||||
}
|
||||
EditorSettingsExternalizable.getInstance().initModifyAndSave {
|
||||
initModifyAndSave(EditorSettingsExternalizable.getInstance()) {
|
||||
SHOW_INTENTION_BULB = false
|
||||
}
|
||||
|
||||
@@ -128,15 +128,17 @@ internal class SettingsSyncRealIdeTest : SettingsSyncRealIdeTestBase() {
|
||||
|
||||
@Test
|
||||
fun `existing settings are copied on initialization`() = timeoutRunBlockingAndStopBridge {
|
||||
GeneralSettings.getInstance().initModifyAndSave {
|
||||
initModifyAndSave(GeneralSettings.getInstance()) {
|
||||
autoSaveFiles = false
|
||||
}
|
||||
|
||||
initSettingsSync(SettingsSyncBridge.InitMode.JustInit)
|
||||
|
||||
executeAndWaitUntilPushed {
|
||||
UISettings.getInstance().initModifyAndSave {
|
||||
recentFilesLimit = 1000
|
||||
runBlocking(Dispatchers.Default) {
|
||||
initModifyAndSave(UISettings.getInstance()) {
|
||||
recentFilesLimit = 1000
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,17 +158,17 @@ internal class SettingsSyncRealIdeTest : SettingsSyncRealIdeTestBase() {
|
||||
|
||||
@Test
|
||||
fun `disabled categories should be ignored when copying settings on initialization`() = timeoutRunBlockingAndStopBridge {
|
||||
GeneralSettings.getInstance().initModifyAndSave {
|
||||
initModifyAndSave(GeneralSettings.getInstance()) {
|
||||
autoSaveFiles = false
|
||||
}
|
||||
EditorSettingsExternalizable.getInstance().initModifyAndSave {
|
||||
initModifyAndSave(EditorSettingsExternalizable.getInstance()) {
|
||||
SHOW_INTENTION_BULB = false
|
||||
}
|
||||
//AppEditorFontOptions.getInstance().initModifyAndSave {
|
||||
// FONT_SIZE = FontPreferences.DEFAULT_FONT_SIZE - 5
|
||||
//}
|
||||
val keymap = createKeymap()
|
||||
saveComponentStore()
|
||||
componentStore.save()
|
||||
|
||||
val os = getPerOsSettingsStorageFolderName()
|
||||
SettingsSyncSettings.getInstance().setCategoryEnabled(SettingsCategory.KEYMAP, false)
|
||||
@@ -191,7 +193,7 @@ internal class SettingsSyncRealIdeTest : SettingsSyncRealIdeTestBase() {
|
||||
|
||||
@Test
|
||||
fun `settings from server are applied`() = timeoutRunBlockingAndStopBridge(5.seconds) {
|
||||
val generalSettings = GeneralSettings.getInstance().init()
|
||||
val generalSettings = init(GeneralSettings.getInstance())
|
||||
initSettingsSync(SettingsSyncBridge.InitMode.JustInit)
|
||||
|
||||
val fileState = GeneralSettings().apply {
|
||||
@@ -210,10 +212,10 @@ internal class SettingsSyncRealIdeTest : SettingsSyncRealIdeTestBase() {
|
||||
@Test
|
||||
fun `enabling category should copy existing settings from that category`() = timeoutRunBlockingAndStopBridge {
|
||||
SettingsSyncSettings.getInstance().setCategoryEnabled(SettingsCategory.CODE, isEnabled = false)
|
||||
GeneralSettings.getInstance().initModifyAndSave {
|
||||
initModifyAndSave(GeneralSettings.getInstance()) {
|
||||
autoSaveFiles = false
|
||||
}
|
||||
EditorSettingsExternalizable.getInstance().initModifyAndSave {
|
||||
initModifyAndSave(EditorSettingsExternalizable.getInstance()) {
|
||||
SHOW_INTENTION_BULB = false
|
||||
}
|
||||
val editorXmlContent = (configDir / "options" / "editor.xml").readText()
|
||||
@@ -249,8 +251,8 @@ internal class SettingsSyncRealIdeTest : SettingsSyncRealIdeTestBase() {
|
||||
|
||||
@Test
|
||||
fun `not enabling cross IDE sync initially works as expected`() = timeoutRunBlockingAndStopBridge {
|
||||
SettingsSyncSettings.getInstance().init()
|
||||
GeneralSettings.getInstance().initModifyAndSave { autoSaveFiles = false }
|
||||
init(SettingsSyncSettings.getInstance())
|
||||
initModifyAndSave(GeneralSettings.getInstance()) { autoSaveFiles = false }
|
||||
|
||||
assertIdeCrossSync(false)
|
||||
|
||||
@@ -270,8 +272,8 @@ internal class SettingsSyncRealIdeTest : SettingsSyncRealIdeTestBase() {
|
||||
|
||||
@Test
|
||||
fun `enabling cross IDE sync initially works as expected`() = timeoutRunBlockingAndStopBridge {
|
||||
SettingsSyncSettings.getInstance().init()
|
||||
GeneralSettings.getInstance().initModifyAndSave { autoSaveFiles = false }
|
||||
init(SettingsSyncSettings.getInstance())
|
||||
initModifyAndSave(GeneralSettings.getInstance()) { autoSaveFiles = false }
|
||||
|
||||
assertIdeCrossSync(false)
|
||||
|
||||
@@ -291,8 +293,8 @@ internal class SettingsSyncRealIdeTest : SettingsSyncRealIdeTestBase() {
|
||||
|
||||
@Test
|
||||
fun `sync settings are always uploaded even if system settings are disabled`() = timeoutRunBlockingAndStopBridge {
|
||||
SettingsSyncSettings.getInstance().init()
|
||||
GeneralSettings.getInstance().initModifyAndSave { autoSaveFiles = false }
|
||||
init(SettingsSyncSettings.getInstance())
|
||||
initModifyAndSave(GeneralSettings.getInstance()) { autoSaveFiles = false }
|
||||
|
||||
SettingsSyncSettings.getInstance().setCategoryEnabled(SettingsCategory.SYSTEM, false)
|
||||
|
||||
@@ -322,8 +324,8 @@ internal class SettingsSyncRealIdeTest : SettingsSyncRealIdeTestBase() {
|
||||
fun `don't sync non-roamable files`() = timeoutRunBlockingAndStopBridge {
|
||||
val nonRoamable = ExportableNonRoamable()
|
||||
|
||||
nonRoamable.init()
|
||||
val generalSettings = GeneralSettings.getInstance().init()
|
||||
init(nonRoamable)
|
||||
val generalSettings = init(GeneralSettings.getInstance())
|
||||
initSettingsSync(SettingsSyncBridge.InitMode.JustInit)
|
||||
|
||||
val generalSettingsState = GeneralSettings().apply {
|
||||
@@ -381,11 +383,11 @@ internal class SettingsSyncRealIdeTest : SettingsSyncRealIdeTestBase() {
|
||||
|
||||
@Test
|
||||
fun `local and remote changes in different files are both applied`() = timeoutRunBlockingAndStopBridge {
|
||||
val generalSettings = GeneralSettings.getInstance().init()
|
||||
val generalSettings = init(GeneralSettings.getInstance())
|
||||
initSettingsSync(SettingsSyncBridge.InitMode.JustInit)
|
||||
|
||||
// prepare local commit but don't allow it to be pushed
|
||||
UISettings.getInstance().initModifyAndSave {
|
||||
initModifyAndSave(UISettings.getInstance()) {
|
||||
compactTreeIndents = true
|
||||
}
|
||||
// at this point there is an unpushed local commit
|
||||
|
||||
@@ -39,7 +39,7 @@ internal abstract class SettingsSyncRealIdeTestBase : SettingsSyncTestBase() {
|
||||
application.registerService(Roamable::class.java, Roamable::class.java, testPluginDescriptor, false)
|
||||
//application.registerService(Roamable::class.java, Roamable::class.java, false)
|
||||
|
||||
application.processAllImplementationClasses { componentClass, plugin ->
|
||||
application.processAllImplementationClasses { _, _ ->
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
@@ -76,7 +76,7 @@ internal abstract class SettingsSyncRealIdeTestBase : SettingsSyncTestBase() {
|
||||
|
||||
protected fun CoroutineScope.initSettingsSync(initMode: SettingsSyncBridge.InitMode = SettingsSyncBridge.InitMode.JustInit, crossIdeSync: Boolean = false) {
|
||||
SettingsSyncSettings.getInstance().syncEnabled = true
|
||||
SettingsSyncLocalSettings.getInstance().state.crossIdeSyncEnabled = crossIdeSync;
|
||||
SettingsSyncLocalSettings.getInstance().state.crossIdeSyncEnabled = crossIdeSync
|
||||
val ideMediator = SettingsSyncIdeMediatorImpl(componentStore, configDir, enabledCondition = { true })
|
||||
val controls = SettingsSyncMain.init(this, disposable, settingsSyncStorage, configDir, ideMediator)
|
||||
updateChecker = controls.updateChecker
|
||||
@@ -105,21 +105,22 @@ internal abstract class SettingsSyncRealIdeTestBase : SettingsSyncTestBase() {
|
||||
}
|
||||
}
|
||||
|
||||
protected fun <T : PersistentStateComponent<*>> T.init(): T {
|
||||
componentStore.initComponent(component = this, serviceDescriptor = null, pluginId = PluginManagerCore.CORE_ID)
|
||||
val defaultConstructor: Constructor<T> = this::class.java.declaredConstructors.find { it.parameterCount == 0 } as Constructor<T>
|
||||
protected suspend fun <T : PersistentStateComponent<*>> init(component: T): T {
|
||||
componentStore.initComponent(component = component, serviceDescriptor = null, pluginId = PluginManagerCore.CORE_ID)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val defaultConstructor: Constructor<T> = component::class.java.declaredConstructors.find { it.parameterCount == 0 } as Constructor<T>
|
||||
val componentInstance: T = defaultConstructor.newInstance()
|
||||
componentStore.componentsAndDefaultStates[this] = componentInstance.state!!
|
||||
return this
|
||||
componentStore.componentsAndDefaultStates[component] = componentInstance.state!!
|
||||
return component
|
||||
}
|
||||
|
||||
protected fun <State, Component : PersistentStateComponent<State>> Component.initModifyAndSave(modifier: State.() -> Unit): Component {
|
||||
this.init()
|
||||
this.state!!.modifier()
|
||||
protected suspend fun <State, Component : PersistentStateComponent<State>> initModifyAndSave(component: Component, modifier: State.() -> Unit): Component {
|
||||
init(component)
|
||||
component.state!!.modifier()
|
||||
runBlocking {
|
||||
componentStore.save()
|
||||
}
|
||||
return this
|
||||
return component
|
||||
}
|
||||
|
||||
protected fun <State, Component : PersistentStateComponent<State>> Component.withState(stateApplier: State.() -> Unit): Component {
|
||||
@@ -150,8 +151,8 @@ internal abstract class SettingsSyncRealIdeTestBase : SettingsSyncTestBase() {
|
||||
|
||||
fun resetComponents() {
|
||||
for ((component, defaultState) in componentsAndDefaultStates) {
|
||||
val c = component as PersistentStateComponent<Any>
|
||||
c.loadState(defaultState)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
(component as PersistentStateComponent<Any>).loadState(defaultState)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,7 +161,7 @@ internal abstract class SettingsSyncRealIdeTestBase : SettingsSyncTestBase() {
|
||||
companion object {
|
||||
@JvmStatic
|
||||
@BeforeAll
|
||||
fun warmUp(): Unit {
|
||||
fun warmUp() {
|
||||
val tempDir = createTempDirectory("gitWarmup-${System.currentTimeMillis()}", "beforeAll")
|
||||
val parentDisposable = Disposer.newDisposable()
|
||||
val gitSettingsLog = GitSettingsLog(
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.testFramework.rules
|
||||
|
||||
import com.intellij.ide.plugins.PluginManagerCore
|
||||
@@ -28,7 +28,9 @@ private class TestComponent : SimplePersistentStateComponent<TestComponent.TestC
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
fun checkDefaultProjectAsTemplate(task: (checkTask: (project: Project, defaultProjectTemplateShouldBeApplied: Boolean) -> Unit) -> Unit) {
|
||||
suspend fun checkDefaultProjectAsTemplate(
|
||||
task: suspend (checkTask: suspend (project: Project, defaultProjectTemplateShouldBeApplied: Boolean) -> Unit) -> Unit,
|
||||
) {
|
||||
val defaultTestComponent = TestComponent()
|
||||
val defaultStateStore = ProjectManager.getInstance().defaultProject.service<IComponentStore>()
|
||||
defaultStateStore.initComponent(component = defaultTestComponent, serviceDescriptor = null, pluginId = PluginManagerCore.CORE_ID)
|
||||
@@ -50,6 +52,7 @@ fun checkDefaultProjectAsTemplate(task: (checkTask: (project: Project, defaultPr
|
||||
}
|
||||
finally {
|
||||
// clear state
|
||||
@Suppress("TestOnlyProblems")
|
||||
defaultStateStore.removeComponent(TEST_COMPONENT_NAME)
|
||||
}
|
||||
}
|
||||
@@ -329,7 +329,7 @@ inline fun <T> Project.runInLoadComponentStateMode(task: () -> T): T {
|
||||
/**
|
||||
* Closes a project after [action].
|
||||
*/
|
||||
fun <T> Project.useProject(save: Boolean = false, action: (Project) -> T): T {
|
||||
inline fun <T> Project.useProject(save: Boolean = false, action: (Project) -> T): T {
|
||||
try {
|
||||
return action(this)
|
||||
}
|
||||
@@ -394,7 +394,8 @@ private inline fun <R> closeOpenedProjectsIfFailImpl(closeProject: Project.() ->
|
||||
}
|
||||
}
|
||||
|
||||
private fun Project.closeProject(save: Boolean = false) {
|
||||
@PublishedApi
|
||||
internal fun Project.closeProject(save: Boolean = false) {
|
||||
invokeAndWaitIfNeeded {
|
||||
if (save) {
|
||||
saveWorkspaceModel()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.settingsRepository.test
|
||||
|
||||
import com.intellij.configurationStore.ApplicationStoreImpl
|
||||
@@ -140,10 +140,10 @@ class LoadTest : LoadTestBase() {
|
||||
val keymapXml = repositoryDir.resolve("keymap.xml")
|
||||
keymapXml.write(content)
|
||||
|
||||
val component = SeveralStoragesConfigured()
|
||||
componentStore.initComponent(component, null, PluginManagerCore.CORE_ID)
|
||||
component.flag = true
|
||||
runBlocking {
|
||||
val component = SeveralStoragesConfigured()
|
||||
componentStore.initComponent(component = component, serviceDescriptor = null, pluginId = PluginManagerCore.CORE_ID)
|
||||
component.flag = true
|
||||
componentStore.save(true)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user