diff --git a/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/ModuleInfoProvider.kt b/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/ModuleInfoProvider.kt index 1645c22e7ec7..ebe156a66a13 100644 --- a/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/ModuleInfoProvider.kt +++ b/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/ModuleInfoProvider.kt @@ -45,17 +45,17 @@ private annotation class ModuleInfoDsl @ModuleInfoDsl @K1ModeProjectStructureApi -fun SeqScope>.register(moduleInfo: IdeaModuleInfo) = yield { Result.success(moduleInfo) } +suspend fun SequenceScope>.register(moduleInfo: IdeaModuleInfo): Unit = yield(Result.success(moduleInfo)) @ModuleInfoDsl @K1ModeProjectStructureApi -fun SeqScope>.register(block: () -> IdeaModuleInfo?) = yield { - block()?.let(Result.Companion::success) +suspend fun SequenceScope>.register(block: () -> IdeaModuleInfo?) { + block()?.let { register(it) } } @ModuleInfoDsl @K1ModeProjectStructureApi -fun SeqScope>.reportError(error: Throwable) = yield { Result.failure(error) } +suspend fun SequenceScope>.reportError(error: Throwable): Unit = yield(Result.failure(error)) @K1ModeProjectStructureApi interface ModuleInfoProviderExtension { @@ -64,15 +64,15 @@ interface ModuleInfoProviderExtension { ExtensionPointName("org.jetbrains.kotlin.idea.base.projectStructure.moduleInfoProviderExtension") } - fun SeqScope>.collectByElement(element: PsiElement, file: PsiFile, virtualFile: VirtualFile) - fun SeqScope>.collectByFile( + suspend fun SequenceScope>.collectByElement(element: PsiElement, file: PsiFile, virtualFile: VirtualFile) + suspend fun SequenceScope>.collectByFile( project: Project, virtualFile: VirtualFile, isLibrarySource: Boolean, config: ModuleInfoProvider.Configuration, ) - fun SeqScope.findContainingModules(project: Project, virtualFile: VirtualFile) + suspend fun SequenceScope.findContainingModules(project: Project, virtualFile: VirtualFile) } @Service(Service.Level.PROJECT) @@ -110,7 +110,7 @@ class ModuleInfoProvider(private val project: Project) { private val libraryInfoCache by lazy { LibraryInfoCache.getInstance(project) } fun collect(element: PsiElement, config: Configuration = Configuration.Default): Sequence> { - return seq { + return sequence { collectByElement(element, config) } } @@ -120,12 +120,12 @@ class ModuleInfoProvider(private val project: Project) { isLibrarySource: Boolean = false, config: Configuration = Configuration.Default, ): Sequence> { - return seq { + return sequence { collectByFile(virtualFile, isLibrarySource, config) } } - private fun SeqScope>.collectByElement(element: PsiElement, config: Configuration) { + private suspend fun SequenceScope>.collectByElement(element: PsiElement, config: Configuration) { PsiUtilCore.ensureValid(element) val containingFile = element.containingFile @@ -229,7 +229,7 @@ class ModuleInfoProvider(private val project: Project) { return if (config.createSourceLibraryInfoForLibraryBinaries) isCompiled else !isCompiled } - private fun SeqScope>.collectByLightElement(element: KtLightElement<*, *>, config: Configuration) { + private suspend fun SequenceScope>.collectByLightElement(element: KtLightElement<*, *>, config: Configuration) { if (element.getNonStrictParentOfType() != null) { val virtualFile = element.containingFile.virtualFile ?: error("Decompiled class should be build from physical file") collectByFile(virtualFile, isLibrarySource = false, config) @@ -248,7 +248,7 @@ class ModuleInfoProvider(private val project: Project) { } } - private fun SeqScope>.collectByFile( + private suspend fun SequenceScope>.collectByFile( virtualFile: VirtualFile, isLibrarySource: Boolean, config: Configuration, @@ -263,14 +263,12 @@ class ModuleInfoProvider(private val project: Project) { val visited = hashSetOf() val collectionRequest = VirtualFileCollectionRequest(virtualFile, isLibrarySource, config, visited, project) - yield { - // Several libraries may include the same JAR files. - // Below, we use an index for getting order entries for a file, but entries come in an arbitrary order. - // So if we are already inside a library, we scan it first. + // Several libraries may include the same JAR files. + // Below, we use an index for getting order entries for a file, but entries come in an arbitrary order. + // So if we are already inside a library, we scan it first. - val contextualModuleResult = contextByContextualBinaryModule(collectionRequest) - contextualModuleResult?.let(Result.Companion::success) - } + val contextualModuleResult = contextByContextualBinaryModule(collectionRequest) + contextualModuleResult?.let { yield(Result.success(it)) } yieldAll(object : Iterable> { override fun iterator(): Iterator> { @@ -322,16 +320,16 @@ class ModuleInfoProvider(private val project: Project) { } } - private fun SeqScope>.collectSourceRelatedByFile(virtualFile: VirtualFile, config: Configuration) { + private suspend fun SequenceScope>.collectSourceRelatedByFile(virtualFile: VirtualFile, config: Configuration) { yieldAll(object : Iterable> { override fun iterator(): Iterator> { - val modules = seq { + val modules = sequence { withCallExtensions( config = config, extensionBlock = { findContainingModules(project, virtualFile) }, ) { runReadAction { fileIndex.getModuleForFile(virtualFile) }?.let { module -> - yield { module } + yield(module) } } } @@ -433,7 +431,7 @@ class ModuleInfoProvider(private val project: Project) { return service.hasDependentModule(this, contextualModuleInfo.module) } - private fun SeqScope>.collectByUserData(container: UserDataModuleContainer) { + private suspend fun SequenceScope>.collectByUserData(container: UserDataModuleContainer) { register { val sourceRootType = container.customSourceRootType if (sourceRootType == null) return@register null diff --git a/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/forwardDeclarations/KotlinForwardDeclarationsModuleInfoProviderExtension.kt b/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/forwardDeclarations/KotlinForwardDeclarationsModuleInfoProviderExtension.kt index bc2172131614..e73ee66f04f1 100644 --- a/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/forwardDeclarations/KotlinForwardDeclarationsModuleInfoProviderExtension.kt +++ b/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/projectStructure/forwardDeclarations/KotlinForwardDeclarationsModuleInfoProviderExtension.kt @@ -12,7 +12,6 @@ import org.jetbrains.kotlin.idea.base.projectStructure.ModuleInfoProviderExtensi import org.jetbrains.kotlin.idea.base.projectStructure.moduleInfo import org.jetbrains.kotlin.idea.base.projectStructure.moduleInfo.IdeaModuleInfo import org.jetbrains.kotlin.idea.base.projectStructure.register -import org.jetbrains.kotlin.idea.base.util.SeqScope /** * An extension to provide the correct [IdeaModuleInfo] for synthetic forward declaration files. @@ -21,7 +20,7 @@ import org.jetbrains.kotlin.idea.base.util.SeqScope * Results are tracked per-project by the [KotlinForwardDeclarationsFileOwnerTracker]. */ internal class KotlinForwardDeclarationsModuleInfoProviderExtension : ModuleInfoProviderExtension { - override fun SeqScope>.collectByElement( + override suspend fun SequenceScope>.collectByElement( element: PsiElement, file: PsiFile, virtualFile: VirtualFile @@ -29,7 +28,7 @@ internal class KotlinForwardDeclarationsModuleInfoProviderExtension : ModuleInfo registerByVirtualFile(file.project, virtualFile) } - override fun SeqScope>.collectByFile( + override suspend fun SequenceScope>.collectByFile( project: Project, virtualFile: VirtualFile, isLibrarySource: Boolean, @@ -39,9 +38,9 @@ internal class KotlinForwardDeclarationsModuleInfoProviderExtension : ModuleInfo } // Kotlin/Native forward declarations can't belong to a module - override fun SeqScope.findContainingModules(project: Project, virtualFile: VirtualFile) {} + override suspend fun SequenceScope.findContainingModules(project: Project, virtualFile: VirtualFile) {} - private fun SeqScope>.registerByVirtualFile(project: Project, virtualFile: VirtualFile) { + private suspend fun SequenceScope>.registerByVirtualFile(project: Project, virtualFile: VirtualFile) { if (!virtualFile.isValid) return KotlinForwardDeclarationsFileOwnerTracker.getInstance(project).getFileOwner(virtualFile)?.let { kaModule -> register(kaModule.moduleInfo) diff --git a/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/util/seq.kt b/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/util/seq.kt index aa3b147ca002..59fee155cbe6 100644 --- a/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/util/seq.kt +++ b/plugins/kotlin/base/project-structure/src/org/jetbrains/kotlin/idea/base/util/seq.kt @@ -1,39 +1,6 @@ // Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package org.jetbrains.kotlin.idea.base.util -import org.jetbrains.annotations.ApiStatus - - -@ApiStatus.Internal -fun seq(block: SeqScope.() -> Unit): Sequence = Sequence { - val secScope = DefaultSeqScope() - block(secScope) - val lazySequence = secScope.values - SeqIterator(lazySequence) -} - - -private class DefaultSeqScope : SeqScope() { - val values: MutableList> = mutableListOf() - override fun yield(value: () -> T?) { - values.add(object : Iterable { - override fun iterator(): Iterator = object : TransformingIterator() { - private var provider: (() -> T?)? = value - override fun calculateHasNext(): Boolean = provider != null - - override fun calculateNext(): T? { - val p = provider ?: throw NoSuchElementException() - provider = null - return p() - } - } - }) - } - - override fun yieldAll(value: Iterable) { - values.add(value) - } -} abstract class TransformingIterator : Iterator { protected var next: T? = null @@ -75,40 +42,3 @@ class MappingIterator( override fun calculateNext(): T? = mapping(iterator.next()) } -private class SeqIterator(providers: List>) : TransformingIterator() { - private var providersIterator: Iterator>? = providers.iterator() - private var iterator: Iterator? = null - override fun calculateHasNext(): Boolean { - while (providersIterator != null) { - if (iterator?.hasNext() == true) return true - val providersIt = providersIterator - if (providersIt?.hasNext() != true) { - return false - } - val next = providersIt.next() - val nextIterator = next.iterator() - iterator = nextIterator - if (nextIterator.hasNext()) return true - } - return false - } - - override fun calculateNext(): T? = iterator?.next() - - override fun hasNext(): Boolean { - val hasNext = super.hasNext() - if (!hasNext) { - iterator = null - providersIterator = null - } - return hasNext - } -} - -@ApiStatus.Internal -abstract class SeqScope internal constructor() { - abstract fun yield(value: () -> T?) - - abstract fun yieldAll(value: Iterable) - -} diff --git a/plugins/kotlin/base/scripting/src/org/jetbrains/kotlin/idea/base/scripting/ScriptingModuleInfoProviderExtension.kt b/plugins/kotlin/base/scripting/src/org/jetbrains/kotlin/idea/base/scripting/ScriptingModuleInfoProviderExtension.kt index bce5f8688ac8..6bf2d48a9339 100644 --- a/plugins/kotlin/base/scripting/src/org/jetbrains/kotlin/idea/base/scripting/ScriptingModuleInfoProviderExtension.kt +++ b/plugins/kotlin/base/scripting/src/org/jetbrains/kotlin/idea/base/scripting/ScriptingModuleInfoProviderExtension.kt @@ -21,16 +21,16 @@ import org.jetbrains.kotlin.idea.base.scripting.projectStructure.ScriptDependenc import org.jetbrains.kotlin.idea.base.scripting.projectStructure.ScriptModuleInfo import org.jetbrains.kotlin.idea.base.scripting.projectStructure.scriptLibraryDependencies import org.jetbrains.kotlin.idea.base.util.K1ModeProjectStructureApi -import org.jetbrains.kotlin.idea.base.util.SeqScope import org.jetbrains.kotlin.idea.core.script.ScriptDependencyAware import org.jetbrains.kotlin.idea.core.script.ScriptRelatedModuleNameFile import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition import org.jetbrains.kotlin.scripting.resolve.VirtualFileScriptSource +import org.jetbrains.kotlin.utils.yieldIfNotNull @OptIn(K1ModeProjectStructureApi::class) internal class ScriptingModuleInfoProviderExtension : ModuleInfoProviderExtension { - override fun SeqScope>.collectByElement( + override suspend fun SequenceScope>.collectByElement( element: PsiElement, file: PsiFile, virtualFile: VirtualFile @@ -46,7 +46,7 @@ internal class ScriptingModuleInfoProviderExtension : ModuleInfoProviderExtensio } } - override fun SeqScope>.collectByFile( + override suspend fun SequenceScope>.collectByFile( project: Project, virtualFile: VirtualFile, isLibrarySource: Boolean, @@ -57,7 +57,7 @@ internal class ScriptingModuleInfoProviderExtension : ModuleInfoProviderExtensio if (isBinary) { if (KotlinPluginModeProvider.isK2Mode()) { val scriptFile = (config.contextualModuleInfo as? ScriptModuleInfo)?.scriptFile - scriptFile?.scriptLibraryDependencies(project)?.filter { virtualFile in it.contentScope }?.forEach(::register) + scriptFile?.scriptLibraryDependencies(project)?.filter { virtualFile in it.contentScope }?.forEach { register(it) } } else if (ScriptDependencyAware.getInstance(project).getAllScriptsDependenciesClassFilesScope().contains(virtualFile)) { if (isLibrarySource) { register(ScriptDependenciesSourceInfo.ForProject(project)) @@ -92,15 +92,11 @@ internal class ScriptingModuleInfoProviderExtension : ModuleInfoProviderExtensio } } - override fun SeqScope.findContainingModules(project: Project, virtualFile: VirtualFile) { - yield { - if (ScratchFileService.getInstance().getRootType(virtualFile) is ScratchRootType) { - ScriptRelatedModuleNameFile[project, virtualFile]?.let { scratchModuleName -> - val moduleManager = ModuleManager.getInstance(project) - moduleManager.findModuleByName(scratchModuleName) - } - } else { - null + override suspend fun SequenceScope.findContainingModules(project: Project, virtualFile: VirtualFile) { + if (ScratchFileService.getInstance().getRootType(virtualFile) is ScratchRootType) { + ScriptRelatedModuleNameFile[project, virtualFile]?.let { scratchModuleName -> + val moduleManager = ModuleManager.getInstance(project) + yieldIfNotNull(moduleManager.findModuleByName(scratchModuleName)) } } }