mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-06 11:50:54 +07:00
revert "[PKGS] fixing IDEA-309218 Dependencies toolwindow present in CLion" because it led to leaking thread errors in tests
GitOrigin-RevId: 9890ae45540ce45a9e4a3ee51395d4b54e67d208
This commit is contained in:
committed by
intellij-monorepo-bot
parent
a41576fea1
commit
8624385827
@@ -40,8 +40,10 @@ val <T : Any> ExtensionPointName<T>.extensionsFlow: Flow<List<T>>
|
||||
@Service(Service.Level.PROJECT)
|
||||
internal class DependencyToolwindowLifecycleScope : CoroutineScope, Disposable {
|
||||
|
||||
val dispatcher = AppExecutorUtil.getAppExecutorService().asCoroutineDispatcher()
|
||||
|
||||
override val coroutineContext =
|
||||
SupervisorJob() + CoroutineName(this::class.qualifiedName!!) + AppExecutorUtil.getAppExecutorService().asCoroutineDispatcher()
|
||||
SupervisorJob() + CoroutineName(this::class.qualifiedName!!) + dispatcher
|
||||
|
||||
override fun dispose() {
|
||||
cancel("Disposing ${this::class.simpleName}")
|
||||
@@ -51,7 +53,7 @@ internal class DependencyToolwindowLifecycleScope : CoroutineScope, Disposable {
|
||||
internal val Project.lifecycleScope: DependencyToolwindowLifecycleScope
|
||||
get() = service()
|
||||
|
||||
internal fun <L : Any, K> Project.messageBusFlow(
|
||||
fun <L : Any, K> Project.messageBusFlow(
|
||||
topic: Topic<L>,
|
||||
initialValue: (suspend () -> K)? = null,
|
||||
listener: suspend ProducerScope<K>.() -> L
|
||||
|
||||
@@ -5,19 +5,15 @@ package com.intellij.dependencytoolwindow
|
||||
|
||||
import com.intellij.openapi.application.EDT
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.startup.StartupActivity
|
||||
import com.intellij.openapi.wm.RegisterToolWindowTask
|
||||
import com.intellij.openapi.wm.ToolWindow
|
||||
import com.intellij.openapi.wm.ToolWindowFactory
|
||||
import com.intellij.openapi.wm.ToolWindowManager
|
||||
import com.intellij.openapi.wm.ex.ToolWindowEx
|
||||
import com.intellij.util.PlatformUtils.*
|
||||
import icons.PlatformDependencyToolwindowIcons
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
|
||||
|
||||
class DependencyToolWindowFactory : StartupActivity {
|
||||
class DependencyToolWindowFactory : ToolWindowFactory {
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -33,83 +29,53 @@ class DependencyToolWindowFactory : StartupActivity {
|
||||
?.provideTab(project)
|
||||
?.let { toolWindow.contentManager.setSelectedContent(it) }
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
override fun runActivity(project: Project) {
|
||||
project.lifecycleScope.launch {
|
||||
DependenciesToolWindowTabProvider.availableTabsFlow(project)
|
||||
.filter { it.isNotEmpty() }
|
||||
.first()
|
||||
withContext(Dispatchers.toolWindowManager(project)) {
|
||||
val messagePointer = DependencyToolWindowBundle.messagePointer("toolwindow.stripe.Dependencies")
|
||||
val toolWindowTask = RegisterToolWindowTask.closable(
|
||||
id = messagePointer.get(),
|
||||
stripeTitle = messagePointer,
|
||||
icon = PlatformDependencyToolwindowIcons.ArtifactSmall
|
||||
)
|
||||
val toolWindow = ToolWindowManager.getInstance(project).registerToolWindow(toolWindowTask)
|
||||
override fun createToolWindowContent(project: Project, toolWindow: ToolWindow) {
|
||||
|
||||
toolWindow.contentManager.removeAllContents(true)
|
||||
toolWindow.isAvailable = false
|
||||
|
||||
toolWindow.contentManager.addSelectionChangedListener { event ->
|
||||
val actionToolWindow = event.content.component as? HasToolWindowActions
|
||||
if (toolWindow is ToolWindowEx) {
|
||||
toolWindow.setAdditionalGearActions(null)
|
||||
actionToolWindow?.also { toolWindow.setAdditionalGearActions(it.gearActions) }
|
||||
}
|
||||
toolWindow.setTitleActions(emptyList())
|
||||
actionToolWindow?.titleActions
|
||||
?.also { toolWindow.setTitleActions(it.toList()) }
|
||||
}
|
||||
|
||||
val tabsFlow = DependenciesToolWindowTabProvider.availableTabsFlow(project)
|
||||
.shareIn(project.lifecycleScope, SharingStarted.Eagerly, 1)
|
||||
|
||||
tabsFlow.onEach { toolWindow.isAvailable = it.isNotEmpty() }
|
||||
.flowOn(Dispatchers.EDT)
|
||||
.launchIn(project.lifecycleScope)
|
||||
|
||||
toolWindow.isVisibleFlow
|
||||
.filter { it }
|
||||
.take(1)
|
||||
.flatMapLatest { tabsFlow }
|
||||
.map { it.map { provider -> provider.provideTab(project) } }
|
||||
.onEach { change ->
|
||||
val removedContent = toolWindow.contentManager.contents.filter { it !in change }.toSet()
|
||||
val newContent = change.filter { it !in toolWindow.contentManager.contents }
|
||||
val contentOrder = toolWindow.contentManager
|
||||
.contents
|
||||
.toList()
|
||||
.minus(removedContent)
|
||||
.plus(newContent)
|
||||
.sortedBy { it.toolwindowTitle }
|
||||
.mapIndexed { index, content -> content to index }
|
||||
.toMap()
|
||||
removedContent.forEach { toolWindow.contentManager.removeContent(it, true) }
|
||||
newContent.forEach { content ->
|
||||
contentOrder[content]?.let { order -> toolWindow.contentManager.addContent(content, order) }
|
||||
?: toolWindow.contentManager.addContent(content)
|
||||
}
|
||||
}
|
||||
.flowOn(Dispatchers.EDT)
|
||||
.launchIn(project.lifecycleScope)
|
||||
|
||||
project.lookAndFeelFlow
|
||||
.onEach { toolWindow.contentManager.component.invalidate() }
|
||||
.onEach { toolWindow.contentManager.component.repaint() }
|
||||
.flowOn(Dispatchers.EDT)
|
||||
.launchIn(project.lifecycleScope)
|
||||
toolWindow.contentManager.addSelectionChangedListener { event ->
|
||||
val actionToolWindow = event.content.component as? HasToolWindowActions
|
||||
if (toolWindow is ToolWindowEx) {
|
||||
toolWindow.setAdditionalGearActions(null)
|
||||
actionToolWindow?.also { toolWindow.setAdditionalGearActions(it.gearActions) }
|
||||
}
|
||||
toolWindow.setTitleActions(emptyList())
|
||||
actionToolWindow?.titleActions
|
||||
?.also { toolWindow.setTitleActions(it.toList()) }
|
||||
}
|
||||
|
||||
toolWindow.contentManager.removeAllContents(true)
|
||||
|
||||
DependenciesToolWindowTabProvider.availableTabsFlow(project)
|
||||
.flowOn(project.lifecycleScope.dispatcher)
|
||||
.map { it.map { provider -> provider.provideTab(project) } }
|
||||
.onEach { change ->
|
||||
val removedContent = toolWindow.contentManager.contents.filter { it !in change }.toSet()
|
||||
val newContent = change.filter { it !in toolWindow.contentManager.contents }
|
||||
val contentOrder = toolWindow.contentManager
|
||||
.contents
|
||||
.toList()
|
||||
.minus(removedContent)
|
||||
.plus(newContent)
|
||||
.sortedBy { it.toolwindowTitle }
|
||||
.mapIndexed { index, content -> content to index }
|
||||
.toMap()
|
||||
removedContent.forEach { toolWindow.contentManager.removeContent(it, true) }
|
||||
newContent.forEach { content ->
|
||||
contentOrder[content]?.let { order -> toolWindow.contentManager.addContent(content, order) }
|
||||
?: toolWindow.contentManager.addContent(content)
|
||||
}
|
||||
}
|
||||
.flowOn(Dispatchers.EDT)
|
||||
.launchIn(project.lifecycleScope)
|
||||
|
||||
project.lookAndFeelFlow
|
||||
.onEach { toolWindow.contentManager.component.invalidate() }
|
||||
.onEach { toolWindow.contentManager.component.repaint() }
|
||||
.flowOn(Dispatchers.EDT)
|
||||
.launchIn(project.lifecycleScope)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal val ToolWindow.isVisibleFlow
|
||||
get() = flow {
|
||||
while (currentCoroutineContext().isActive) {
|
||||
emit(isVisible)
|
||||
delay(50.milliseconds)
|
||||
}
|
||||
}
|
||||
@@ -1018,7 +1018,8 @@
|
||||
<toolWindow id="Project" anchor="left" icon="AllIcons.Toolwindows.ToolWindowProject"
|
||||
factoryClass="com.intellij.ide.projectView.impl.ProjectViewToolWindowFactory"/>
|
||||
|
||||
<postStartupActivity implementation="com.intellij.dependencytoolwindow.DependencyToolWindowFactory"/>
|
||||
<toolWindow id="Dependencies" anchor="bottom" icon="PlatformDependencyToolwindowIcons.ArtifactSmall"
|
||||
factoryClass="com.intellij.dependencytoolwindow.DependencyToolWindowFactory"/>
|
||||
|
||||
<toolWindowExtractor implementation="com.intellij.dependencytoolwindow.DependencyToolWindowViewModelExtractor"/>
|
||||
|
||||
|
||||
@@ -20,7 +20,10 @@ import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.application.EDT
|
||||
import com.intellij.openapi.application.appSystemDir
|
||||
import com.intellij.openapi.application.readAction
|
||||
import com.intellij.openapi.components.Service
|
||||
import com.intellij.openapi.components.Service.*
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiManager
|
||||
@@ -30,6 +33,7 @@ import com.jetbrains.packagesearch.intellij.plugin.getInstalledDependencies
|
||||
import com.jetbrains.packagesearch.intellij.plugin.ui.toolwindow.models.InstalledDependenciesUsages
|
||||
import com.jetbrains.packagesearch.intellij.plugin.ui.toolwindow.models.ProjectDataProvider
|
||||
import com.jetbrains.packagesearch.intellij.plugin.ui.toolwindow.models.RepositoryModel
|
||||
import com.jetbrains.packagesearch.intellij.plugin.ui.toolwindow.models.TargetModules
|
||||
import com.jetbrains.packagesearch.intellij.plugin.util.BackgroundLoadingBarController
|
||||
import com.jetbrains.packagesearch.intellij.plugin.util.PowerSaveModeState
|
||||
import com.jetbrains.packagesearch.intellij.plugin.util.TraceInfo
|
||||
@@ -37,7 +41,6 @@ import com.jetbrains.packagesearch.intellij.plugin.util.TraceInfo.TraceSource.SE
|
||||
import com.jetbrains.packagesearch.intellij.plugin.util.catchAndLog
|
||||
import com.jetbrains.packagesearch.intellij.plugin.util.combineLatest
|
||||
import com.jetbrains.packagesearch.intellij.plugin.util.debounceBatch
|
||||
import com.jetbrains.packagesearch.intellij.plugin.util.fileOpenedFlow
|
||||
import com.jetbrains.packagesearch.intellij.plugin.util.filesChangedEventFlow
|
||||
import com.jetbrains.packagesearch.intellij.plugin.util.lifecycleScope
|
||||
import com.jetbrains.packagesearch.intellij.plugin.util.loadingContainer
|
||||
@@ -62,17 +65,15 @@ import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.asFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.consumeAsFlow
|
||||
import kotlinx.coroutines.flow.emptyFlow
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.flatMapMerge
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.mapNotNull
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.receiveAsFlow
|
||||
import kotlinx.coroutines.flow.shareIn
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.flow.take
|
||||
import org.jetbrains.idea.packagesearch.api.PackageSearchApiClient
|
||||
@@ -87,22 +88,20 @@ internal class PackageSearchProjectService(private val project: Project) : Dispo
|
||||
)
|
||||
|
||||
private val restartChannel = Channel<Unit>()
|
||||
private val restartFlow = restartChannel.receiveAsFlow()
|
||||
.shareIn(project.lifecycleScope, SharingStarted.Lazily)
|
||||
|
||||
val allKnownRepositoriesFlow by timer(1.hours)
|
||||
.map(project.loadingContainer) {
|
||||
dataProvider.fetchKnownRepositories()
|
||||
.map { RepositoryModel(it.id, it.friendlyName, it.url, it) }
|
||||
}
|
||||
.stateInAndCatchAndLog(project.lifecycleScope, SharingStarted.Lazily, emptyList())
|
||||
.stateInAndCatchAndLog(project.lifecycleScope, SharingStarted.Eagerly, emptyList())
|
||||
|
||||
private val packageSearchModulesFlow by combine(
|
||||
project.trustedProjectFlow,
|
||||
ApplicationManager.getApplication().powerSaveModeFlow.map { it == PowerSaveModeState.DISABLED }
|
||||
) { results: Array<Boolean> -> results.all { it } }
|
||||
.flatMapLatest { isPkgsEnabled -> if (isPkgsEnabled) project.nativeModulesFlow else emptyFlow() }
|
||||
.replayOn(project.moduleChangesSignalFlow, restartFlow)
|
||||
.replayOn(project.moduleChangesSignalFlow)
|
||||
.map(project.loadingContainer) { nativeModules ->
|
||||
project.moduleTransformers.parallelMap { it.transformModules(project, nativeModules) }
|
||||
.flatten()
|
||||
@@ -110,7 +109,7 @@ internal class PackageSearchProjectService(private val project: Project) : Dispo
|
||||
.catchAndLog()
|
||||
|
||||
val packageSearchModulesStateFlow = packageSearchModulesFlow
|
||||
.stateIn(project.lifecycleScope, SharingStarted.Lazily, emptyList())
|
||||
.stateIn(project.lifecycleScope, SharingStarted.Eagerly, emptyList())
|
||||
|
||||
val isAvailable
|
||||
get() = packageSearchModulesStateFlow.value.isNotEmpty()
|
||||
@@ -144,7 +143,7 @@ internal class PackageSearchProjectService(private val project: Project) : Dispo
|
||||
repositoriesDeclarationsByModule.toMutableMap()
|
||||
.apply { putAll(changes.associateWith { it.getDeclaredRepositories(knownRepositories) }) }
|
||||
}
|
||||
.stateInAndCatchAndLog(project.lifecycleScope, SharingStarted.Lazily, emptyMap())
|
||||
.stateInAndCatchAndLog(project.lifecycleScope, SharingStarted.Eagerly, emptyMap())
|
||||
|
||||
private val declarationsChanges by moduleChangesFlow
|
||||
.map { it.associateWith { it.getDependencies() } }
|
||||
@@ -158,7 +157,7 @@ internal class PackageSearchProjectService(private val project: Project) : Dispo
|
||||
) { declaredDependenciesByModule, changes ->
|
||||
declaredDependenciesByModule.toMutableMap().apply { putAll(changes) }
|
||||
}
|
||||
.stateInAndCatchAndLog(project.lifecycleScope, SharingStarted.Lazily, emptyMap())
|
||||
.stateInAndCatchAndLog(project.lifecycleScope, SharingStarted.Eagerly, emptyMap())
|
||||
|
||||
private val remoteData by declaredDependenciesByModuleFlow
|
||||
.filter { it.isNotEmpty() }
|
||||
@@ -182,23 +181,19 @@ internal class PackageSearchProjectService(private val project: Project) : Dispo
|
||||
loadingContainer = project.loadingContainer
|
||||
) { packageSearchModules, remoteData ->
|
||||
installedDependenciesUsages(project, packageSearchModules, remoteData)
|
||||
}.stateInAndCatchAndLog(project.lifecycleScope, SharingStarted.Lazily, InstalledDependenciesUsages.EMPTY)
|
||||
}.stateInAndCatchAndLog(project.lifecycleScope, SharingStarted.Eagerly, InstalledDependenciesUsages.EMPTY)
|
||||
|
||||
init {
|
||||
|
||||
val openedBuildFilesFlow = combine(
|
||||
project.fileOpenedFlow,
|
||||
packageSearchModulesFlow.map { it.mapNotNull { it.buildFile }.toSet() }
|
||||
) { openedFiles, buildFiles ->
|
||||
openedFiles intersect buildFiles
|
||||
}.shareIn(project.lifecycleScope, SharingStarted.Eagerly, 1)
|
||||
|
||||
openedBuildFilesFlow
|
||||
// allows rerunning PKGS inspections on already opened files
|
||||
// when the data is finally available or changes for PackageUpdateInspection
|
||||
// or when a build file changes
|
||||
installedDependenciesFlow.flatMapLatest { packageSearchModulesFlow }
|
||||
.map { it.mapNotNull { it.buildFile?.path } }
|
||||
.filter { it.isNotEmpty() }
|
||||
.take(1)
|
||||
.flatMapLatest { installedDependenciesFlow }
|
||||
.flatMapLatest { openedBuildFilesFlow }
|
||||
.flatMapMerge { it.asFlow() }
|
||||
.flatMapLatest { knownBuildFiles ->
|
||||
FileEditorManager.getInstance(project).openFiles
|
||||
.filter { it.path in knownBuildFiles }.asFlow()
|
||||
}
|
||||
.mapNotNull { readAction { PsiManager.getInstance(project).findFile(it) } }
|
||||
.onEach { readAction { DaemonCodeAnalyzer.getInstance(project).restart(it) } }
|
||||
.flowOn(Dispatchers.EDT)
|
||||
|
||||
@@ -57,7 +57,6 @@ import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.merge
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.scan
|
||||
import kotlinx.coroutines.flow.shareIn
|
||||
@@ -322,9 +321,9 @@ suspend fun ProducerScope<Unit>.send() = send(Unit)
|
||||
internal fun <T> Flow<T>.collectIn(coroutineScope: CoroutineScope, sendChannel: SendChannel<T>) =
|
||||
onEach { sendChannel.send(it) }.launchIn(coroutineScope)
|
||||
|
||||
internal fun <T> Flow<T>.replayOn(vararg replayFlows: Flow<*>) = channelFlow {
|
||||
internal fun <T> Flow<T>.replayOn(replayFlow: Flow<*>) = channelFlow {
|
||||
val mutex = Mutex()
|
||||
var last: T? = null
|
||||
onEach { mutex.withLock { last = it } }.collectIn(this, this)
|
||||
merge(*replayFlows).collect { mutex.withLock { last?.let { send(it) } } }
|
||||
replayFlow.collect { mutex.withLock { last?.let { send(it) } } }
|
||||
}
|
||||
@@ -10,17 +10,16 @@ import com.intellij.ide.ui.LafManager
|
||||
import com.intellij.ide.ui.LafManagerListener
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager
|
||||
import com.intellij.openapi.fileEditor.FileEditorManagerListener
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.module.ModuleManager
|
||||
import com.intellij.openapi.project.DumbService
|
||||
import com.intellij.openapi.project.ModuleListener
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.openapi.vfs.VirtualFileManager
|
||||
import com.intellij.openapi.vfs.newvfs.BulkFileListener
|
||||
import com.intellij.openapi.vfs.newvfs.events.VFileEvent
|
||||
import com.intellij.openapi.wm.ToolWindow
|
||||
import com.intellij.openapi.wm.ex.ToolWindowManagerListener
|
||||
import com.intellij.util.Function
|
||||
import com.intellij.util.messages.Topic
|
||||
import com.jetbrains.packagesearch.intellij.plugin.data.LoadingContainer
|
||||
@@ -28,21 +27,21 @@ import com.jetbrains.packagesearch.intellij.plugin.data.PackageSearchCachesServi
|
||||
import com.jetbrains.packagesearch.intellij.plugin.data.PackageSearchProjectCachesService
|
||||
import com.jetbrains.packagesearch.intellij.plugin.data.PackageSearchProjectService
|
||||
import com.jetbrains.packagesearch.intellij.plugin.extensibility.AsyncModuleTransformer
|
||||
import com.jetbrains.packagesearch.intellij.plugin.extensibility.ModuleTransformer
|
||||
import com.jetbrains.packagesearch.intellij.plugin.extensibility.FlowModuleChangesSignalProvider
|
||||
import com.jetbrains.packagesearch.intellij.plugin.extensibility.ModuleChangesSignalProvider
|
||||
import com.jetbrains.packagesearch.intellij.plugin.extensibility.ModuleTransformer
|
||||
import com.jetbrains.packagesearch.intellij.plugin.extensibility.PackageSearchModule
|
||||
import com.jetbrains.packagesearch.intellij.plugin.lifecycle.PackageSearchLifecycleScope
|
||||
import com.jetbrains.packagesearch.intellij.plugin.ui.PkgsUiCommandsService
|
||||
import com.jetbrains.packagesearch.intellij.plugin.ui.toolwindow.models.UiStateModifier
|
||||
import com.jetbrains.packagesearch.intellij.plugin.ui.toolwindow.models.versions.PackageVersionNormalizer
|
||||
import com.jetbrains.packagesearch.intellij.plugin.ui.toolwindow.panels.management.PackageManagementOperationExecutor
|
||||
import com.jetbrains.packagesearch.intellij.plugin.ui.toolwindow.panels.management.PackageManagementPanel
|
||||
import kotlinx.coroutines.channels.ProducerScope
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.callbackFlow
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.merge
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.coroutines.resume
|
||||
@@ -60,6 +59,15 @@ internal val packageVersionNormalizer: PackageVersionNormalizer
|
||||
internal val Project.packageSearchProjectCachesService: PackageSearchProjectCachesService
|
||||
get() = service()
|
||||
|
||||
internal val Project.toolWindowManagerFlow: Flow<ToolWindow>
|
||||
get() = messageBusFlow(ToolWindowManagerListener.TOPIC) {
|
||||
object : ToolWindowManagerListener {
|
||||
override fun toolWindowShown(toolWindow: ToolWindow) {
|
||||
trySend(toolWindow)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun <L : Any, K> Project.messageBusFlow(
|
||||
topic: Topic<L>,
|
||||
initialValue: (suspend () -> K)? = null,
|
||||
@@ -169,42 +177,4 @@ val Project.dependencyModifierService
|
||||
get() = DependencyModifierService.getInstance(this)
|
||||
|
||||
internal val Project.loadingContainer
|
||||
get() = service<LoadingContainer>()
|
||||
|
||||
internal sealed interface FileEditorEvent {
|
||||
|
||||
val file: VirtualFile
|
||||
|
||||
@JvmInline
|
||||
value class FileOpened(override val file: VirtualFile) : FileEditorEvent
|
||||
|
||||
@JvmInline
|
||||
value class FileClosed(override val file: VirtualFile) : FileEditorEvent
|
||||
}
|
||||
|
||||
private val Project.project
|
||||
get() = this
|
||||
|
||||
internal val Project.fileOpenedFlow
|
||||
get() = flow {
|
||||
val buffer: MutableList<VirtualFile> = FileEditorManager.getInstance(project).openFiles
|
||||
.toMutableList()
|
||||
emit(buffer.toList())
|
||||
messageBusFlow(FileEditorManagerListener.FILE_EDITOR_MANAGER) {
|
||||
object : FileEditorManagerListener {
|
||||
override fun fileOpened(source: FileEditorManager, file: VirtualFile) {
|
||||
trySend(FileEditorEvent.FileOpened(file))
|
||||
}
|
||||
|
||||
override fun fileClosed(source: FileEditorManager, file: VirtualFile) {
|
||||
trySend(FileEditorEvent.FileClosed(file))
|
||||
}
|
||||
}
|
||||
}.collect {
|
||||
when (it) {
|
||||
is FileEditorEvent.FileClosed -> buffer.remove(it.file)
|
||||
is FileEditorEvent.FileOpened -> buffer.add(it.file)
|
||||
}
|
||||
emit(buffer.toList())
|
||||
}
|
||||
}
|
||||
get() = service<LoadingContainer>()
|
||||
Reference in New Issue
Block a user