From 99f702865ca71ca6c77c9c2e2918d37b39aafaf2 Mon Sep 17 00:00:00 2001 From: "Ilya.Kazakevich" Date: Wed, 27 Aug 2025 22:27:48 +0200 Subject: [PATCH] Python: make functions suspend to obey the threading policy GitOrigin-RevId: 90864b29bb9d986aa44717bdf178bbbfe4910f73 --- .../python/projectModel/BaseProjectModelService.kt | 8 +++++--- .../com/jetbrains/python/projectModel/projectModel.kt | 9 +++++++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/python/src/com/jetbrains/python/projectModel/BaseProjectModelService.kt b/python/src/com/jetbrains/python/projectModel/BaseProjectModelService.kt index 80fac4afaa49..126106b2bf91 100644 --- a/python/src/com/jetbrains/python/projectModel/BaseProjectModelService.kt +++ b/python/src/com/jetbrains/python/projectModel/BaseProjectModelService.kt @@ -11,6 +11,8 @@ import com.intellij.platform.workspace.storage.EntityStorage import com.intellij.platform.workspace.storage.MutableEntityStorage import com.intellij.platform.workspace.storage.impl.url.toVirtualFileUrl import com.jetbrains.python.PyBundle +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext import org.jetbrains.annotations.NonNls import org.jetbrains.annotations.SystemIndependent import java.nio.file.Path @@ -92,11 +94,11 @@ abstract class BaseProjectModelService { } } - private fun createProjectModel( + private suspend fun createProjectModel( project: Project, graph: List, source: EntitySource, - ): EntityStorage { + ): EntityStorage = withContext(Dispatchers.Default) { val fileUrlManager = project.workspaceModel.getVirtualFileUrlManager() val storage = MutableEntityStorage.create() for (extProject in graph) { @@ -128,7 +130,7 @@ abstract class BaseProjectModelService { } } } - return storage + return@withContext storage } /** diff --git a/python/src/com/jetbrains/python/projectModel/projectModel.kt b/python/src/com/jetbrains/python/projectModel/projectModel.kt index 2889cd5c1da6..06aacc81e7a5 100644 --- a/python/src/com/jetbrains/python/projectModel/projectModel.kt +++ b/python/src/com/jetbrains/python/projectModel/projectModel.kt @@ -2,6 +2,9 @@ package com.jetbrains.python.projectModel import com.intellij.openapi.util.io.FileUtil +import com.intellij.util.concurrency.annotations.RequiresBackgroundThread +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext import java.nio.file.FileVisitResult import java.nio.file.Path import kotlin.io.path.ExperimentalPathApi @@ -53,6 +56,7 @@ interface PythonProjectModelResolver

{ * this method should return `null` for `libs/` but module graphs containing *only* modules `project1` and `project2` * for the directories `project1/` and `project2` respectively, even if there is a dependency between them. */ + @RequiresBackgroundThread fun discoverProjectRootSubgraph(root: Path): ExternalProjectGraph

? /** @@ -73,7 +77,7 @@ interface PythonProjectModelResolver

{ * If these two projects are independents, there will be two graphs for `project1` and `project2` respectively. */ @OptIn(ExperimentalPathApi::class) - fun discoverIndependentProjectGraphs(root: Path): List> { + suspend fun discoverIndependentProjectGraphs(root: Path): List> = withContext(Dispatchers.IO) { val graphs = mutableListOf>() root.visitFileTree { onPreVisitDirectory { dir, _ -> @@ -87,7 +91,7 @@ interface PythonProjectModelResolver

{ } // TODO make sure that roots doesn't leave ijProjectRoot boundaries - return mergeRootsReferringToEachOther(graphs) + return@withContext mergeRootsReferringToEachOther(graphs) } } @@ -103,6 +107,7 @@ interface ProjectModelSyncListener { fun onFinish(projectRoot: Path): Unit = Unit } +@RequiresBackgroundThread private fun

mergeRootsReferringToEachOther(roots: List>): List> { fun commonAncestorPath(paths: Iterable): Path { val normalized = paths.map { it.normalize() }