diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewInitNotifier.kt b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewInitNotifier.kt index 8ef2ac452765..c0a135fc4e68 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewInitNotifier.kt +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewInitNotifier.kt @@ -12,12 +12,14 @@ import io.opentelemetry.api.trace.Span import io.opentelemetry.api.trace.Tracer import io.opentelemetry.context.Context import org.jetbrains.annotations.ApiStatus.Internal +import org.jetbrains.annotations.TestOnly import java.util.concurrent.atomic.AtomicBoolean private val projectViewInit: Scope = Scope("projectViewInit") @Service(Service.Level.PROJECT) -internal class ProjectViewInitNotifier(private val project: Project) { +@Internal +class ProjectViewInitNotifier(private val project: Project) { private val startedOccurred = AtomicBoolean() private val cachedNodesLoadedOccurred = AtomicBoolean() private val completedOccurred = AtomicBoolean() @@ -45,6 +47,9 @@ internal class ProjectViewInitNotifier(private val project: Project) { project.messageBus.syncPublisher(ProjectViewListener.TOPIC).initCompleted() } + @TestOnly + fun isInitCompleted(): Boolean = completedOccurred.get() + private inner class TracingHelper { private val mainSpan = Ref() private val cachedNodesSpan = Ref() diff --git a/plugins/performanceTesting/core/src/com/jetbrains/performancePlugin/commands/WaitForProjectViewCommand.kt b/plugins/performanceTesting/core/src/com/jetbrains/performancePlugin/commands/WaitForProjectViewCommand.kt index 13fe9f4f1934..95f1e8ec4cc2 100644 --- a/plugins/performanceTesting/core/src/com/jetbrains/performancePlugin/commands/WaitForProjectViewCommand.kt +++ b/plugins/performanceTesting/core/src/com/jetbrains/performancePlugin/commands/WaitForProjectViewCommand.kt @@ -1,15 +1,17 @@ // Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.jetbrains.performancePlugin.commands +import com.intellij.ide.projectView.impl.ProjectViewInitNotifier import com.intellij.ide.projectView.impl.ProjectViewListener import com.intellij.openapi.ui.playback.PlaybackContext import com.intellij.openapi.ui.playback.commands.PlaybackCommandCoroutineAdapter import kotlinx.coroutines.sync.Mutex +import org.jetbrains.annotations.TestOnly /** * Wait till a project tree is fully initialized. - * Command should be executed as soon as possible since project view initialization happens very early and the command might hang. */ +@TestOnly class WaitForProjectViewCommand(text: String, line: Int) : PlaybackCommandCoroutineAdapter(text, line) { companion object { @@ -17,6 +19,9 @@ class WaitForProjectViewCommand(text: String, line: Int) : PlaybackCommandCorout } override suspend fun doExecute(context: PlaybackContext) { + val notifier = context.project.getService(ProjectViewInitNotifier::class.java) + if (notifier.isInitCompleted()) return + val connection = context.project.messageBus.connect() val mutex = Mutex(true) connection.subscribe(ProjectViewListener.TOPIC, object : ProjectViewListener { @@ -24,6 +29,9 @@ class WaitForProjectViewCommand(text: String, line: Int) : PlaybackCommandCorout mutex.unlock() } }) + + if (notifier.isInitCompleted()) mutex.unlock() + mutex.lock() connection.disconnect() }