diff --git a/java/java-impl/src/META-INF/JavaPlugin.xml b/java/java-impl/src/META-INF/JavaPlugin.xml
index d88d5bc277f9..8ab8d0674528 100644
--- a/java/java-impl/src/META-INF/JavaPlugin.xml
+++ b/java/java-impl/src/META-INF/JavaPlugin.xml
@@ -2445,7 +2445,7 @@
-
+
diff --git a/java/java-impl/src/com/intellij/java/frameworks/MavenDictionaryChecker.kt b/java/java-impl/src/com/intellij/java/frameworks/MavenDictionaryChecker.kt
new file mode 100644
index 000000000000..b71c441b52a2
--- /dev/null
+++ b/java/java-impl/src/com/intellij/java/frameworks/MavenDictionaryChecker.kt
@@ -0,0 +1,61 @@
+package com.intellij.java.frameworks
+
+import com.intellij.java.library.JavaLibraryUtil
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.roots.OrderEnumerator
+import com.intellij.openapi.roots.ProjectRootManager
+import com.intellij.openapi.roots.libraries.Library
+import com.intellij.openapi.util.Key
+import com.intellij.psi.util.CachedValueProvider.Result
+import com.intellij.psi.util.CachedValuesManager
+import com.intellij.psi.util.ParameterizedCachedValue
+import com.intellij.psi.util.ParameterizedCachedValueProvider
+import com.intellij.spellchecker.dictionary.DictionaryChecker
+import com.intellij.util.containers.CollectionFactory.createSmallMemoryFootprintSet
+
+internal class MavenDictionaryChecker : DictionaryChecker {
+ override fun isCorrect(project: Project, word: String): Boolean {
+ return getWords(project).contains(word)
+ }
+
+ private val CACHE_KEY: Key, Project>> = Key.create("MAVEN_SPELLING_WORDS")
+ private val PROVIDER: ParameterizedCachedValueProvider, Project> = ParameterizedCachedValueProvider {
+ Result.create(collectWords(it), ProjectRootManager.getInstance(it))
+ }
+
+ private fun getWords(project: Project): Set {
+ return CachedValuesManager.getManager(project)
+ .getParameterizedCachedValue(project, CACHE_KEY, PROVIDER, false, project)
+ }
+
+ private val splitWordsRegex: Regex = Regex("[._-]")
+
+ private fun collectWords(project: Project): Set {
+ val allStrings = createSmallMemoryFootprintSet(1000)
+ val visited = mutableSetOf()
+
+ OrderEnumerator.orderEntries(project)
+ .recursively()
+ .forEachLibrary {
+ if (visited.contains(it)) return@forEachLibrary true
+
+ val mavenCoordinates = JavaLibraryUtil.getMavenCoordinates(it)
+ if (mavenCoordinates != null) {
+ allStrings.add(mavenCoordinates.groupId)
+ allStrings.add(mavenCoordinates.artifactId)
+ }
+
+ visited.add(it)
+ true
+ }
+
+ val allWords = createSmallMemoryFootprintSet(100)
+
+ allStrings.asSequence()
+ .flatMap { it.split(splitWordsRegex) }
+ .filter { it.length > 3 }
+ .forEach { allWords.add(it) }
+
+ return allWords
+ }
+}
\ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/java/frameworks/MavenDictionaryCheckerProvider.kt b/java/java-impl/src/com/intellij/java/frameworks/MavenDictionaryCheckerProvider.kt
deleted file mode 100644
index 83a433503222..000000000000
--- a/java/java-impl/src/com/intellij/java/frameworks/MavenDictionaryCheckerProvider.kt
+++ /dev/null
@@ -1,90 +0,0 @@
-package com.intellij.java.frameworks
-
-import com.intellij.java.library.JavaLibraryUtil
-import com.intellij.openapi.Disposable
-import com.intellij.openapi.components.Service
-import com.intellij.openapi.components.service
-import com.intellij.openapi.module.Module
-import com.intellij.openapi.project.DumbService
-import com.intellij.openapi.project.ModuleListener
-import com.intellij.openapi.project.Project
-import com.intellij.openapi.roots.ModuleRootEvent
-import com.intellij.openapi.roots.ModuleRootListener
-import com.intellij.openapi.roots.OrderEnumerator
-import com.intellij.openapi.roots.libraries.Library
-import com.intellij.spellchecker.dictionary.DictionaryChecker
-import com.intellij.spellchecker.dictionary.DictionaryCheckerProvider
-import com.intellij.util.containers.CollectionFactory.createSmallMemoryFootprintSet
-
-internal class MavenDictionaryCheckerProvider : DictionaryCheckerProvider {
- override fun getChecker(project: Project): DictionaryChecker {
- return project.service()
- }
-}
-
-@Service(Service.Level.PROJECT)
-internal class AllMavenDependenciesDictionary(private val project: Project) : DictionaryChecker, Disposable {
- init {
- val messageBusConnection = project.messageBus.connect(this)
- messageBusConnection.subscribe(DumbService.DUMB_MODE, object : DumbService.DumbModeListener {
- override fun exitDumbMode() = reset()
- })
- messageBusConnection.subscribe(ModuleRootListener.TOPIC, object : ModuleRootListener {
- override fun rootsChanged(event: ModuleRootEvent) = reset()
- })
- messageBusConnection.subscribe(ModuleListener.TOPIC, object : ModuleListener {
- override fun modulesAdded(project: Project, modules: List) = reset()
- override fun moduleRemoved(project: Project, module: Module) = reset()
- })
- }
-
- @Volatile
- private var allMavenWords: Set? = null
-
- override fun isCorrect(word: String): Boolean {
- var current = allMavenWords
- if (current == null) {
- current = collectWords(project)
- allMavenWords = current
- }
- return current.contains(word)
- }
-
- fun reset() {
- allMavenWords = null
- }
-
- override fun dispose() {
- // do nothing
- }
-}
-
-private val splitWordsRegex: Regex = Regex("[._-]")
-
-private fun collectWords(project: Project): Set {
- val allStrings = createSmallMemoryFootprintSet(1000)
- val visited = mutableSetOf()
-
- OrderEnumerator.orderEntries(project)
- .recursively()
- .forEachLibrary {
- if (visited.contains(it)) return@forEachLibrary true
-
- val mavenCoordinates = JavaLibraryUtil.getMavenCoordinates(it)
- if (mavenCoordinates != null) {
- allStrings.add(mavenCoordinates.groupId)
- allStrings.add(mavenCoordinates.artifactId)
- }
-
- visited.add(it)
- true
- }
-
- val allWords = createSmallMemoryFootprintSet(100)
- for (allString in allStrings) {
- val parts = allString.split(splitWordsRegex)
- allWords.addAll(parts)
- }
-
- return allWords
-}
\ No newline at end of file
diff --git a/spellchecker/src/META-INF/SpellCheckerPlugin.xml b/spellchecker/src/META-INF/SpellCheckerPlugin.xml
index 2aaaccd9bdf7..43277b52fbbb 100644
--- a/spellchecker/src/META-INF/SpellCheckerPlugin.xml
+++ b/spellchecker/src/META-INF/SpellCheckerPlugin.xml
@@ -6,7 +6,7 @@
-
+
diff --git a/spellchecker/src/com/intellij/spellchecker/SpellCheckerManager.kt b/spellchecker/src/com/intellij/spellchecker/SpellCheckerManager.kt
index 446d84274155..883fd4ede6b6 100644
--- a/spellchecker/src/com/intellij/spellchecker/SpellCheckerManager.kt
+++ b/spellchecker/src/com/intellij/spellchecker/SpellCheckerManager.kt
@@ -62,15 +62,6 @@ class SpellCheckerManager(val project: Project) : Disposable {
private val userDictionaryListenerEventDispatcher = EventDispatcher.create(DictionaryStateListener::class.java)
- @Volatile
- private var dictionaryCheckers: List? = null
-
- init {
- DictionaryCheckerProvider.EP_NAME.addChangeListener(Runnable {
- dictionaryCheckers = null
- }, this)
- }
-
// used in Rider
@get:Suppress("unused")
var spellChecker: SpellCheckerEngine? = null
@@ -243,13 +234,7 @@ class SpellCheckerManager(val project: Project) : Disposable {
}
private fun isCorrectExtensionWord(word: String): Boolean {
- var currentCheckers = dictionaryCheckers
- if (currentCheckers == null) {
- currentCheckers = DictionaryCheckerProvider.EP_NAME.extensionList.map { it.getChecker(project) }
- dictionaryCheckers = currentCheckers
- }
-
- return currentCheckers.any { it.isCorrect(word) }
+ return DictionaryChecker.EP_NAME.extensionList.any { it.isCorrect(project, word) }
}
fun acceptWordAsCorrect(word: String, project: Project) {
diff --git a/spellchecker/src/com/intellij/spellchecker/dictionary/DictionaryChecker.java b/spellchecker/src/com/intellij/spellchecker/dictionary/DictionaryChecker.java
index cf4d6d0d63e4..be70b4339e5b 100644
--- a/spellchecker/src/com/intellij/spellchecker/dictionary/DictionaryChecker.java
+++ b/spellchecker/src/com/intellij/spellchecker/dictionary/DictionaryChecker.java
@@ -1,13 +1,16 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.spellchecker.dictionary;
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
/**
* Checks if words are correct in the context of Project.
- *
- * @see DictionaryCheckerProvider
*/
public interface DictionaryChecker {
- boolean isCorrect(@NotNull String word);
+ ExtensionPointName EP_NAME =
+ new ExtensionPointName<>("com.intellij.spellchecker.dictionary.checker");
+
+ boolean isCorrect(@NotNull Project project, @NotNull String word);
}
diff --git a/spellchecker/src/com/intellij/spellchecker/dictionary/DictionaryCheckerProvider.java b/spellchecker/src/com/intellij/spellchecker/dictionary/DictionaryCheckerProvider.java
deleted file mode 100644
index 17d8396ebb58..000000000000
--- a/spellchecker/src/com/intellij/spellchecker/dictionary/DictionaryCheckerProvider.java
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
-package com.intellij.spellchecker.dictionary;
-
-import com.intellij.openapi.extensions.ExtensionPointName;
-import com.intellij.openapi.project.Project;
-import org.jetbrains.annotations.NotNull;
-
-/**
- * Provides dictionaries that are always project-bound, e.g. provide names of libraries used in the Project.
- */
-public interface DictionaryCheckerProvider {
- ExtensionPointName EP_NAME =
- new ExtensionPointName<>("com.intellij.spellchecker.dictionary.checker");
-
- @NotNull DictionaryChecker getChecker(@NotNull Project project);
-}