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); -}