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 <projectService> 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
This commit is contained in:
Vitaly Legchilkin
2026-05-26 12:20:32 +00:00
committed by intellij-monorepo-bot
parent 3ba7cdeda1
commit 637a4c2078
5 changed files with 17 additions and 7 deletions
@@ -250,8 +250,6 @@
<applicationService serviceImplementation="com.jetbrains.python.packaging.PyPackageService"/>
<applicationService serviceInterface="com.jetbrains.python.sdk.add.v2.EelFileSystemFactory"
serviceImplementation="com.jetbrains.python.sdk.add.v2.EelFileSystemFactoryImpl"/>
<projectService serviceInterface="com.jetbrains.python.module.PyModuleService"
serviceImplementation="com.jetbrains.python.module.PyModuleServiceImpl"/>
<applicationService serviceInterface="com.jetbrains.python.psi.resolve.PackageAvailabilityService"
serviceImplementation="com.jetbrains.python.packaging.PackageAvailabilityServiceImpl"/>
<typedHandler implementation="com.jetbrains.python.codeInsight.PyMethodNameTypedHandler" id="pyMethodNameTypedHandler"/>
+6
View File
@@ -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
@@ -14,8 +14,10 @@
<orderEntry type="module" module-name="intellij.platform.jps.model" />
<orderEntry type="module" module-name="intellij.platform.projectModel" />
<orderEntry type="module" module-name="intellij.python.psi" />
<orderEntry type="module" module-name="intellij.python.community" />
<orderEntry type="module" module-name="intellij.platform.analysis.impl" />
<orderEntry type="module" module-name="intellij.platform.lang" />
<orderEntry type="module" module-name="intellij.platform.lang.core" />
<orderEntry type="module" module-name="intellij.platform.lang.impl" />
<orderEntry type="module" module-name="intellij.regexp" />
<orderEntry type="module" module-name="intellij.libraries.guava" />
@@ -23,5 +25,6 @@
<orderEntry type="module" module-name="intellij.python.sdk" />
<orderEntry type="library" name="kotlin-stdlib" level="project" />
<orderEntry type="module" module-name="intellij.platform.core.impl" />
<orderEntry type="module" module-name="intellij.libraries.kotlinx.coroutines.core" />
</component>
</module>
@@ -1,7 +1,13 @@
<idea-plugin visibility="public">
<dependencies>
<module name="intellij.python.community"/>
<module name="intellij.python.psi.impl"/>
<module name="intellij.python.sdk"/>
<module name="intellij.regexp"/>
</dependencies>
<extensions defaultExtensionNs="com.intellij">
<projectService serviceInterface="com.jetbrains.python.module.PyModuleService"
serviceImplementation="com.jetbrains.python.module.PyModuleServiceImpl"/>
</extensions>
</idea-plugin>
@@ -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 }
}
}