diff --git a/spellchecker/src/com/intellij/spellchecker/SpellCheckerManager.kt b/spellchecker/src/com/intellij/spellchecker/SpellCheckerManager.kt index 1ac0dc7adfd0..024d67df8f4b 100644 --- a/spellchecker/src/com/intellij/spellchecker/SpellCheckerManager.kt +++ b/spellchecker/src/com/intellij/spellchecker/SpellCheckerManager.kt @@ -1,4 +1,4 @@ -// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. @file:Suppress("ReplaceGetOrSet") package com.intellij.spellchecker @@ -8,12 +8,12 @@ import com.intellij.ide.SaveAndSyncHandler import com.intellij.openapi.Disposable import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.application.PathManager -import com.intellij.openapi.application.runReadAction import com.intellij.openapi.command.WriteCommandAction import com.intellij.openapi.command.undo.BasicUndoableAction import com.intellij.openapi.command.undo.UndoManager import com.intellij.openapi.components.Service import com.intellij.openapi.components.service +import com.intellij.openapi.components.serviceAsync import com.intellij.openapi.diagnostic.logger import com.intellij.openapi.extensions.ExtensionPointName import com.intellij.openapi.fileEditor.FileEditorManager @@ -39,9 +39,11 @@ import com.intellij.spellchecker.state.DictionaryStateListener import com.intellij.spellchecker.state.ProjectDictionaryState import com.intellij.spellchecker.util.SpellCheckerBundle import com.intellij.util.EventDispatcher -import com.intellij.util.application import kotlinx.coroutines.CancellationException +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.runBlocking +import org.jetbrains.annotations.ApiStatus.Internal +import org.jetbrains.annotations.TestOnly import java.io.File import java.util.function.Consumer @@ -49,7 +51,7 @@ private val LOG = logger() private val BUNDLED_EP_NAME = ExtensionPointName("com.intellij.spellchecker.bundledDictionaryProvider") @Service(Service.Level.PROJECT) -class SpellCheckerManager(val project: Project) : Disposable { +class SpellCheckerManager @Internal constructor(@Internal val project: Project, coroutineScope: CoroutineScope) : Disposable { private var projectDictionary: ProjectDictionary? = null private var appDictionary: EditableDictionary? = null @@ -58,15 +60,18 @@ class SpellCheckerManager(val project: Project) : Disposable { private val userDictionaryListenerEventDispatcher = EventDispatcher.create(DictionaryStateListener::class.java) - // used in Rider - @get:Suppress("unused") + @Internal var spellChecker: SpellCheckerEngine? = null private set private var suggestionProvider: SuggestionProvider? = null init { - ensureSpellerIsLoaded() + if (ApplicationManager.getApplication().isUnitTestMode) { + @Suppress("TestOnlyProblems") + ensureSpellerIsLoaded() + } + fullConfigurationReload() @Suppress("DEPRECATION") val projectStoreDir = project.baseDir?.let { getProjectStoreDirectory(it) } @@ -74,22 +79,16 @@ class SpellCheckerManager(val project: Project) : Disposable { appDictionaryPath = PathManager.getOptionsPath() + File.separator + CACHED_DICTIONARY_FILE LocalFileSystem.getInstance().addVirtualFileListener(CustomDictFileListener(project = project, manager = this), this) BUNDLED_EP_NAME.addChangeListener({ fillEngineDictionary(spellChecker!!) }, this) - RuntimeDictionaryProvider.EP_NAME.addChangeListener({ fillEngineDictionary(spellChecker!!) }, this) - CustomDictionaryProvider.EP_NAME.addChangeListener({ fillEngineDictionary(spellChecker!!) }, this) + RuntimeDictionaryProvider.EP_NAME.addChangeListener(coroutineScope) { fillEngineDictionary(spellChecker!!) } + CustomDictionaryProvider.EP_NAME.addChangeListener(coroutineScope) { fillEngineDictionary(spellChecker!!) } } + @TestOnly private fun ensureSpellerIsLoaded() { - if (application.isUnitTestMode) { - when { - application.isReadAccessAllowed -> waitForSpeller() - else -> runReadAction(this::waitForSpeller) - } - } - } - - private fun waitForSpeller() { + assert(ApplicationManager.getApplication().isUnitTestMode) + @Suppress("SSBasedInspection") runBlocking { - project.service().waitForSpeller() + project.serviceAsync().waitForSpeller() } }