IJPL-797 intellij.platform.warmup review internal API

GitOrigin-RevId: 583147f4bf0041e5db35e8d7742aee129ba4cfad
This commit is contained in:
Konstantin Nisht
2024-05-19 21:15:00 +02:00
committed by intellij-monorepo-bot
parent 5d6ff37216
commit 686ad64d53
10 changed files with 23 additions and 119 deletions

View File

@@ -4,7 +4,6 @@ f:com.intellij.warmup.WarmupBuildStatus$Companion
- f:currentStatus():com.intellij.warmup.WarmupBuildStatus
f:com.intellij.warmup.WarmupBuildStatus$Failure
- com.intellij.warmup.WarmupBuildStatus$InvocationStatus
- <init>(java.lang.String):V
a:com.intellij.warmup.WarmupBuildStatus$InvocationStatus
- com.intellij.warmup.WarmupBuildStatus
- f:getMessage():java.lang.String
@@ -13,12 +12,6 @@ f:com.intellij.warmup.WarmupBuildStatus$NotInvoked
- sf:INSTANCE:com.intellij.warmup.WarmupBuildStatus$NotInvoked
f:com.intellij.warmup.WarmupBuildStatus$Success
- com.intellij.warmup.WarmupBuildStatus$InvocationStatus
- <init>(java.lang.String):V
f:com.intellij.warmup.WarmupUtilsKt
- sf:waitIndexInitialization(kotlin.coroutines.Continuation):java.lang.Object
- sf:waitUntilProgressTasksAreFinishedOrFail(kotlin.coroutines.Continuation):java.lang.Object
f:com.intellij.warmup.util.ActivityBasedWarmupKt
- sf:configureProjectByActivities(com.intellij.warmup.util.OpenProjectArgs,kotlin.coroutines.Continuation):java.lang.Object
f:com.intellij.warmup.util.ConsoleLog
- sf:INSTANCE:com.intellij.warmup.util.ConsoleLog
- f:error(java.lang.String,java.lang.Throwable):V
@@ -49,25 +42,11 @@ c:com.intellij.warmup.util.OpenProjectArgsImpl
- getDisabledConfigurators():java.util.Set
- getProjectDir():java.nio.file.Path
f:com.intellij.warmup.util.ProjectUtilKt
- sf:importOrOpenProject(com.intellij.warmup.util.OpenProjectArgs):com.intellij.openapi.project.Project
- sf:importOrOpenProjectAsync(com.intellij.warmup.util.OpenProjectArgs,kotlin.coroutines.Continuation):java.lang.Object
f:com.intellij.warmup.util.TimeCookie
- <init>():V
- f:formatDuration():java.lang.String
f:com.intellij.warmup.util.UtilsKt
- sf:callProjectConversion(com.intellij.warmup.util.OpenProjectArgs,kotlin.coroutines.Continuation):java.lang.Object
- sf:checkProjectRoots(com.intellij.openapi.project.Project,kotlin.coroutines.Continuation):java.lang.Object
- sf:getProjectFile(com.intellij.warmup.util.OpenProjectArgs,kotlin.coroutines.Continuation):java.lang.Object
- sf:runAndCatchNotNull(java.lang.String,kotlin.jvm.functions.Function0):java.lang.Object
- sf:yieldAndWaitForDumbModeEnd(com.intellij.openapi.project.Project,kotlin.coroutines.Continuation):java.lang.Object
- sf:yieldThroughInvokeLater(kotlin.coroutines.Continuation):java.lang.Object
f:com.intellij.warmup.util.Utils_time_loggerKt
- sf:runTaskAndLogTime(java.lang.String,kotlin.jvm.functions.Function3,kotlin.coroutines.Continuation):java.lang.Object
f:com.intellij.warmup.util.WarmupLogger
- sf:INSTANCE:com.intellij.warmup.util.WarmupLogger
- f:logError(java.lang.String,java.lang.Throwable):V
- bs:logError$default(com.intellij.warmup.util.WarmupLogger,java.lang.String,java.lang.Throwable,I,java.lang.Object):V
- f:logInfo(java.lang.String):V
- sf:runTaskAndLogTime(java.lang.String,kotlin.jvm.functions.Function2,kotlin.coroutines.Continuation):java.lang.Object
com.intellij.warmup.util.WarmupProjectArgs
- com.intellij.warmup.util.OpenProjectArgs
- a:getBuild():Z

View File

@@ -59,7 +59,6 @@ internal class ProjectCachesWarmup : ModernApplicationStarter() {
runWarmupActivity {
val loggingJob = initLogger(args)
waitIndexInitialization()
val project = try {
importOrOpenProjectAsync(commandArgs)
}
@@ -75,7 +74,6 @@ internal class ProjectCachesWarmup : ModernApplicationStarter() {
buildProject(project, commandArgs)
if (!isPredicateBasedWarmup()) {
waitUntilProgressTasksAreFinishedOrFail()
waitForRefreshQueue()
}
ProjectManagerEx.getInstanceEx().forceCloseProjectAsync(project, save = true)

View File

@@ -3,7 +3,6 @@ package com.intellij.warmup
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.util.Key
import org.jetbrains.annotations.Nls
import org.jetbrains.annotations.NonNls
sealed interface WarmupBuildStatus {
@@ -21,7 +20,7 @@ sealed interface WarmupBuildStatus {
object NotInvoked : WarmupBuildStatus
sealed class InvocationStatus(val message: @NonNls String) : WarmupBuildStatus
class Success(message: @NonNls String) : InvocationStatus(message)
class Failure(message: @NonNls String) : InvocationStatus(message)
sealed class InvocationStatus protected constructor(val message: @NonNls String) : WarmupBuildStatus
class Success internal constructor(message: @NonNls String) : InvocationStatus(message)
class Failure internal constructor(message: @NonNls String) : InvocationStatus(message)
}

View File

@@ -12,7 +12,7 @@ import kotlinx.coroutines.async
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.selects.select
suspend fun configureProjectByActivities(args: OpenProjectArgs) : Project {
internal suspend fun configureProjectByActivities(args: OpenProjectArgs): Project {
val projectFile = getProjectFile(args)
callProjectConversion(args)

View File

@@ -1,50 +1,28 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.warmup.util
import com.intellij.conversion.ConversionListener
import com.intellij.conversion.ConversionService
import com.intellij.ide.CommandLineInspectionProjectConfigurator
import com.intellij.ide.CommandLineProgressReporterElement
import com.intellij.ide.impl.OpenProjectTask
import com.intellij.ide.impl.PatchProjectUtil
import com.intellij.ide.impl.ProjectUtil
import com.intellij.ide.impl.runUnderModalProgressIfIsEdt
import com.intellij.ide.warmup.WarmupConfigurator
import com.intellij.ide.warmup.WarmupStatus
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.EDT
import com.intellij.openapi.application.readAction
import com.intellij.openapi.progress.blockingContext
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.JdkOrderEntry
import com.intellij.openapi.roots.OrderRootType
import com.intellij.openapi.roots.ProjectRootManager
import com.intellij.openapi.util.registry.Registry
import com.intellij.openapi.vfs.VfsUtil
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.platform.util.progress.reportProgress
import com.intellij.util.asSafely
import com.intellij.util.indexing.FileBasedIndex
import com.intellij.util.indexing.FileBasedIndexImpl
import com.intellij.warmup.impl.WarmupConfiguratorOfCLIConfigurator
import com.intellij.warmup.impl.getCommandLineReporter
import com.intellij.warmup.waitIndexInitialization
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.nio.file.Path
import java.util.*
fun importOrOpenProject(args: OpenProjectArgs): Project {
WarmupLogger.logInfo("Opening project from ${args.projectDir}...")
// most of the sensible operations would run in the same thread
return runUnderModalProgressIfIsEdt {
runTaskAndLogTime("open project") {
importOrOpenProjectImpl0(args)
}
}
}
suspend fun importOrOpenProjectAsync(args: OpenProjectArgs): Project {
WarmupLogger.logInfo("Opening project from ${args.projectDir}...")
// most of the sensible operations would run in the same thread
@@ -56,6 +34,7 @@ suspend fun importOrOpenProjectAsync(args: OpenProjectArgs): Project {
private suspend fun importOrOpenProjectImpl0(args: OpenProjectArgs): Project {
val currentStatus = WarmupStatus.currentStatus()
WarmupStatus.statusChanged(WarmupStatus.InProgress)
waitIndexInitialization()
try {
return if (isPredicateBasedWarmup()) {
configureProjectByActivities(args)

View File

@@ -25,14 +25,13 @@ import java.io.IOException
import java.nio.file.Path
import java.text.SimpleDateFormat
import java.util.*
import java.util.concurrent.ConcurrentHashMap
import java.util.logging.Level
import java.util.logging.LogRecord
import kotlin.io.path.div
import kotlin.io.path.writeText
import kotlin.time.Duration.Companion.milliseconds
object WarmupLogger {
internal object WarmupLogger {
fun logInfo(message: String) {
ConsoleLog.info(message)
}

View File

@@ -12,7 +12,7 @@ import java.util.*
import kotlin.coroutines.CoroutineContext
import kotlin.math.max
class TimeCookie {
internal class TimeCookie {
private val now = System.currentTimeMillis()
fun formatDuration(): String {
val duration = max(0L, TimeCookie().now - this.now)
@@ -49,7 +49,7 @@ private class TaskAndLogTimeElement : CoroutineContext.Element {
@OptIn(DelicateCoroutinesApi::class)
suspend fun <Y> runTaskAndLogTime(
progressName: String,
action: suspend CoroutineScope.(TimeCookie) -> Y
action: suspend CoroutineScope.() -> Y
): Y = coroutineScope {
val cookie = TimeCookie()
WarmupLogger.logInfo("Started waiting for '$progressName'...")
@@ -91,7 +91,7 @@ suspend fun <Y> runTaskAndLogTime(
try {
withContext(stackElement + CoroutineName(progressName)) {
action(cookie)
action()
}
}
finally {

View File

@@ -21,6 +21,7 @@ import com.intellij.openapi.vfs.VirtualFileManager
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.coroutines.yield
import org.jetbrains.annotations.ApiStatus
import java.nio.file.Path
import java.util.TreeSet
@@ -40,6 +41,7 @@ private fun assertInnocentThreadToWait() {
ApplicationManager.getApplication().assertReadAccessNotAllowed()
}
@ApiStatus.Internal
suspend fun yieldThroughInvokeLater() {
assertInnocentThreadToWait()
@@ -59,7 +61,7 @@ private suspend fun completeJustSubmittedDumbServiceTasks(project: Project) {
}
}
suspend fun yieldAndWaitForDumbModeEnd(project: Project) {
internal suspend fun yieldAndWaitForDumbModeEnd(project: Project) {
assertInnocentThreadToWait()
completeJustSubmittedDumbServiceTasks(project)
@@ -70,7 +72,7 @@ suspend fun yieldAndWaitForDumbModeEnd(project: Project) {
yieldThroughInvokeLater()
}
suspend fun checkProjectRoots(project: Project) {
internal suspend fun checkProjectRoots(project: Project) {
runTaskAndLogTime("check project roots") {
val errors = TreeSet<String>()
val missingSDKs = TreeSet<String>()
@@ -102,7 +104,7 @@ suspend fun checkProjectRoots(project: Project) {
}
suspend fun getProjectFile(args: OpenProjectArgs): VirtualFile {
internal suspend fun getProjectFile(args: OpenProjectArgs): VirtualFile {
val vfsProject = blockingContext {
VirtualFileManager.getInstance().refreshAndFindFileByNioPath(args.projectDir)
?: throw RuntimeException("Project path ${args.projectDir} is not found")
@@ -117,7 +119,7 @@ suspend fun getProjectFile(args: OpenProjectArgs): VirtualFile {
return vfsProject
}
suspend fun callProjectConversion(projectArgs: OpenProjectArgs) {
internal suspend fun callProjectConversion(projectArgs: OpenProjectArgs) {
if (!projectArgs.convertProject) {
return
}

View File

@@ -1,67 +1,12 @@
// 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.warmup
import com.intellij.openapi.application.EDT
import com.intellij.openapi.components.serviceAsync
import com.intellij.openapi.progress.blockingContext
import com.intellij.openapi.progress.impl.CoreProgressManager
import com.intellij.util.indexing.FileBasedIndex
import com.intellij.util.indexing.FileBasedIndexEx
import com.intellij.util.ui.update.MergingUpdateQueue
import com.intellij.warmup.util.ConsoleLog
import com.intellij.warmup.util.runTaskAndLogTime
import com.intellij.warmup.util.yieldThroughInvokeLater
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.time.delay
import kotlinx.coroutines.withContext
import java.time.Duration
import kotlin.system.exitProcess
suspend fun waitIndexInitialization() {
internal suspend fun waitIndexInitialization() {
val fileBasedIndex = serviceAsync<FileBasedIndex>() as FileBasedIndexEx
fileBasedIndex.loadIndexes()
fileBasedIndex.waitUntilIndicesAreInitialized()
}
suspend fun waitUntilProgressTasksAreFinishedOrFail() {
try {
waitUntilProgressTasksAreFinished()
}
catch (e: IllegalStateException) {
ConsoleLog.info(e.message ?: e.toString())
exitProcess(2)
}
}
private suspend fun waitUntilProgressTasksAreFinished() {
runTaskAndLogTime("Awaiting for progress tasks") {
while (true) {
withContext(Dispatchers.EDT) {
blockingContext {
MergingUpdateQueue.flushAllQueues()
}
}
yieldThroughInvokeLater()
if (CoreProgressManager.getCurrentIndicators().isEmpty()) {
return@runTaskAndLogTime
}
waitCurrentProgressIndicators()
}
}
}
private suspend fun waitCurrentProgressIndicators() {
val timeout = System.getProperty("ide.progress.tasks.awaiting.timeout.min", "60").toLongOrNull() ?: 60
val startTime = System.currentTimeMillis()
while (CoreProgressManager.getCurrentIndicators().isNotEmpty()) {
if (System.currentTimeMillis() - startTime > Duration.ofMinutes(timeout).toMillis()) {
val timeoutMessage = StringBuilder("Progress tasks awaiting timeout.\n")
timeoutMessage.appendLine("Not finished tasks:")
for (indicator in CoreProgressManager.getCurrentIndicators()) {
timeoutMessage.appendLine(" - ${indicator.text}")
}
error(timeoutMessage)
}
delay(Duration.ofMillis(1000))
}
}

View File

@@ -18,10 +18,11 @@ import com.intellij.cce.evaluation.EvaluationRootInfo
import com.intellij.cce.util.ExceptionsUtil.stackTraceToString
import com.intellij.cce.workspace.ConfigFactory
import com.intellij.cce.workspace.EvaluationWorkspace
import com.intellij.ide.impl.runUnderModalProgressIfIsEdt
import com.intellij.openapi.application.ApplicationStarter
import com.intellij.openapi.project.Project
import com.intellij.platform.ide.bootstrap.commandNameFromExtension
import com.intellij.warmup.util.importOrOpenProject
import com.intellij.warmup.util.importOrOpenProjectAsync
import java.nio.file.FileSystems
import java.nio.file.Path
import java.nio.file.Paths
@@ -74,7 +75,9 @@ internal class CompletionEvaluationStarter : ApplicationStarter {
try {
println("Open and load project $projectPath. Operation may take a few minutes.")
@Suppress("SSBasedInspection")
project = importOrOpenProject(OpenProjectArgsData(FileSystems.getDefault().getPath(projectPath)))
project = runUnderModalProgressIfIsEdt {
importOrOpenProjectAsync(OpenProjectArgsData(FileSystems.getDefault().getPath(projectPath)))
}
println("Project loaded!")
try {