From 637a4c2078e6ff3a15b09b9bbf9d0bbdf7ad54cc Mon Sep 17 00:00:00 2001 From: Vitaly Legchilkin Date: Tue, 26 May 2026 09:50:34 +0200 Subject: [PATCH] PY-89898 register PyModuleService in an always-loaded content module PythonCore content module intellij.python.community.impl was changed to loading="optional" in PY-85882 so that PythonCore can load in JetBrains Client, where some of its descriptor dependencies (externalSystem.impl, json, toml.core, yaml, ...) are not present. In non-PyCharm IDEs (GoLand, CLion, DataGrip, IDEA, WebStorm, JetBrains Client) the same optional content module also silently fails to load, leaving the PyModuleService interface in intellij.python.community on the classpath but no implementation registered. PythonSdkUtil.findPythonSdk (in the always-loaded intellij.python.sdk) calls PyModuleService.getInstance(project) unconditionally during stub indexing, which then throws "Cannot find service ... PyModuleService" and aborts the index update for every .py file. Diogen reports 5312 events across 49 users on 2026.2 EAP1/2/3. Move PyModuleServiceImpl and its registration into intellij.python.community.core.impl, which is a required content module of PythonCore (no loading="optional") and only depends on basic modules (psi.impl, sdk, regexp) available wherever PythonCore loads. Drop the "type is PythonModuleTypeBase" check in isPythonModule: it is fully subsumed by the existing type.id == PYTHON_MODULE_ID check (PythonModuleTypeBase's sole constructor passes that id to super), and removing it avoids a circular dep on intellij.python.community.impl from core.impl. Add the needed compile/runtime deps to core.impl (intellij.python.community, intellij.platform.lang.core, intellij.libraries.kotlinx.coroutines.core) and declare intellij.python.community explicitly in the plugin descriptor so the classloader wiring does not rely on transitive deps elsewhere. GitOrigin-RevId: 7fb2a70e557c22409ea6f36f577faa59ec4cf6d9 --- python/pluginResources/intellij.python.community.impl.xml | 2 -- python/python-core-impl/BUILD.bazel | 6 ++++++ .../intellij.python.community.core.impl.iml | 3 +++ .../resources/intellij.python.community.core.impl.xml | 6 ++++++ .../src/com/jetbrains/python/module/PyModuleServiceImpl.kt | 7 ++----- 5 files changed, 17 insertions(+), 7 deletions(-) rename python/{ => python-core-impl}/src/com/jetbrains/python/module/PyModuleServiceImpl.kt (90%) diff --git a/python/pluginResources/intellij.python.community.impl.xml b/python/pluginResources/intellij.python.community.impl.xml index f9524743de4d..5e152f6142ba 100644 --- a/python/pluginResources/intellij.python.community.impl.xml +++ b/python/pluginResources/intellij.python.community.impl.xml @@ -250,8 +250,6 @@ - diff --git a/python/python-core-impl/BUILD.bazel b/python/python-core-impl/BUILD.bazel index 2588841a9b88..9a9c081e021f 100644 --- a/python/python-core-impl/BUILD.bazel +++ b/python/python-core-impl/BUILD.bazel @@ -15,8 +15,10 @@ jvm_library( "//jps/model-api:model", "//platform/projectModel-api:projectModel", "//python/python-psi-api:psi", + "//python/openapi:community", "//platform/analysis-impl", "//platform/lang-api:lang", + "//platform/lang-core", "//platform/lang-impl", "//RegExpSupport:regexp", "//libraries/guava", @@ -24,6 +26,7 @@ jvm_library( "//python/python-sdk:sdk", "@lib//:kotlin-stdlib", "//platform/core-impl", + "//libraries/kotlinx/coroutines/core", ] ) @@ -41,14 +44,17 @@ jvm_library( "//jps/model-api:model_test_lib", "//platform/projectModel-api:projectModel_test_lib", "//python/python-psi-api:psi_test_lib", + "//python/openapi:community_test_lib", "//platform/analysis-impl:analysis-impl_test_lib", "//platform/lang-api:lang_test_lib", + "//platform/lang-core:lang-core_test_lib", "//platform/lang-impl:lang-impl_test_lib", "//RegExpSupport:regexp_test_lib", "//libraries/guava:guava_test_lib", "//python/python-psi-impl:psi-impl_test_lib", "//python/python-sdk:sdk_test_lib", "//platform/core-impl:core-impl_test_lib", + "//libraries/kotlinx/coroutines/core:core_test_lib", ] ) ### auto-generated section `build intellij.python.community.core.impl` end diff --git a/python/python-core-impl/intellij.python.community.core.impl.iml b/python/python-core-impl/intellij.python.community.core.impl.iml index 8b40b9610e39..d3429388a803 100644 --- a/python/python-core-impl/intellij.python.community.core.impl.iml +++ b/python/python-core-impl/intellij.python.community.core.impl.iml @@ -14,8 +14,10 @@ + + @@ -23,5 +25,6 @@ + \ No newline at end of file diff --git a/python/python-core-impl/resources/intellij.python.community.core.impl.xml b/python/python-core-impl/resources/intellij.python.community.core.impl.xml index 2adbf347f19e..d10fd749ff45 100644 --- a/python/python-core-impl/resources/intellij.python.community.core.impl.xml +++ b/python/python-core-impl/resources/intellij.python.community.core.impl.xml @@ -1,7 +1,13 @@ + + + + + diff --git a/python/src/com/jetbrains/python/module/PyModuleServiceImpl.kt b/python/python-core-impl/src/com/jetbrains/python/module/PyModuleServiceImpl.kt similarity index 90% rename from python/src/com/jetbrains/python/module/PyModuleServiceImpl.kt rename to python/python-core-impl/src/com/jetbrains/python/module/PyModuleServiceImpl.kt index e5b69517d8c7..d515f00bf897 100644 --- a/python/src/com/jetbrains/python/module/PyModuleServiceImpl.kt +++ b/python/python-core-impl/src/com/jetbrains/python/module/PyModuleServiceImpl.kt @@ -11,7 +11,6 @@ import com.intellij.openapi.projectRoots.Sdk import com.intellij.openapi.roots.ModuleRootManager import com.intellij.util.Consumer import com.jetbrains.python.PyNames -import com.jetbrains.python.PythonModuleTypeBase import com.jetbrains.python.facet.PythonFacetSettings import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.CoroutineScope @@ -52,9 +51,7 @@ internal class PyModuleServiceImpl(val project: Project, coroutineScope: Corouti override fun isPythonModule(module: Module): Boolean { val type = ModuleType.get(module) - if (type is PythonModuleTypeBase || type.id == PyNames.PYTHON_MODULE_ID) { - return true - } - return FacetManager.getInstance(module).allFacets.any { it.configuration is PythonFacetSettings } + return type.id == PyNames.PYTHON_MODULE_ID || + FacetManager.getInstance(module).allFacets.any { it.configuration is PythonFacetSettings } } }