diff --git a/java/codeserver/core/src/com/intellij/java/codeserver/core/JpmsModuleAccessInfo.kt b/java/codeserver/core/src/com/intellij/java/codeserver/core/JpmsModuleAccessInfo.kt
index ee13a39ca1d3..b2c3a3f35d88 100644
--- a/java/codeserver/core/src/com/intellij/java/codeserver/core/JpmsModuleAccessInfo.kt
+++ b/java/codeserver/core/src/com/intellij/java/codeserver/core/JpmsModuleAccessInfo.kt
@@ -6,7 +6,7 @@ import com.intellij.openapi.module.ModuleUtilCore
import com.intellij.openapi.roots.JdkOrderEntry
import com.intellij.openapi.roots.ModuleRootManager
import com.intellij.openapi.roots.ProjectRootManager
-import com.intellij.pom.java.LanguageLevel
+import com.intellij.pom.java.JavaFeature
import com.intellij.psi.*
import com.intellij.psi.impl.light.LightJavaModule
import com.intellij.psi.search.GlobalSearchScope
@@ -164,9 +164,8 @@ data class JpmsModuleAccessInfo(val current: JpmsModuleInfo.CurrentModuleInfo, v
if (targetModule.name == PsiJavaModule.JAVA_BASE) return true
if (!isJdkModule(jpsModule, targetModule)) return false
- val languageLevel = PsiUtil.getLanguageLevel(place)
// https://bugs.openjdk.org/browse/JDK-8197532
- val jdkModulePred: (PsiJavaModule) -> Boolean = if (languageLevel >= LanguageLevel.JDK_11) {
+ val jdkModulePred: (PsiJavaModule) -> Boolean = if (PsiUtil.isAvailable(JavaFeature.AUTO_ROOT_MODULES, place)) {
{ module -> module.exports.any { e -> e.moduleNames.isEmpty() } }
}
else {
diff --git a/java/java-frontback-psi-api/resources/messages/JavaPsiBundle.properties b/java/java-frontback-psi-api/resources/messages/JavaPsiBundle.properties
index 6d69410a7165..9fea66e3366e 100644
--- a/java/java-frontback-psi-api/resources/messages/JavaPsiBundle.properties
+++ b/java/java-frontback-psi-api/resources/messages/JavaPsiBundle.properties
@@ -85,6 +85,7 @@ feature.static.interface.calls=Static interface method calls
feature.effectively.final=Effectively final variables
feature.try.with.resources.refs=Resource references
feature.modules=Modules
+feature.auto.root.modules=All API-exporting modules are implicitly root modules
feature.private.interface.methods=Private interface methods
feature.utf8.property.files=Property files in UTF-8 encoding
feature.collection.factories=Collection factory methods
diff --git a/java/java-frontback-psi-api/src/com/intellij/pom/java/JavaFeature.java b/java/java-frontback-psi-api/src/com/intellij/pom/java/JavaFeature.java
index 9e802e76d9e8..5f212b425835 100644
--- a/java/java-frontback-psi-api/src/com/intellij/pom/java/JavaFeature.java
+++ b/java/java-frontback-psi-api/src/com/intellij/pom/java/JavaFeature.java
@@ -1,4 +1,4 @@
-// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.pom.java;
import com.intellij.core.JavaPsiBundle;
@@ -56,6 +56,7 @@ public enum JavaFeature {
LVTI(LanguageLevel.JDK_10, "feature.lvti"),
VAR_LAMBDA_PARAMETER(LanguageLevel.JDK_11, "feature.var.lambda.parameter"),
NESTMATES(LanguageLevel.JDK_11, "feature.nestmates"),
+ AUTO_ROOT_MODULES(LanguageLevel.JDK_11, "feature.auto.root.modules"),
ENHANCED_SWITCH(LanguageLevel.JDK_14, "feature.enhanced.switch"),
SWITCH_EXPRESSION(LanguageLevel.JDK_14, "feature.switch.expressions"),
SERIAL_ANNOTATION(LanguageLevel.JDK_14, "feature.serial.annotation"),
diff --git a/java/java-psi-api/src/com/intellij/psi/PsiJavaModule.java b/java/java-psi-api/src/com/intellij/psi/PsiJavaModule.java
index aefcc4349db4..8a4b37d5b4c7 100644
--- a/java/java-psi-api/src/com/intellij/psi/PsiJavaModule.java
+++ b/java/java-psi-api/src/com/intellij/psi/PsiJavaModule.java
@@ -44,9 +44,45 @@ public interface PsiJavaModule extends NavigatablePsiElement, PsiNameIdentifierO
@Override @NotNull PsiJavaModuleReferenceElement getNameIdentifier();
@Override @NotNull String getName();
+ /**
+ * Checks whether the module should be excluded from automatic resolution when loaded from the classpath.
+ * This method reads the module resolution attributes from {@code module-info.class}, as specified in JEP 11.
+ *
+ * @return {@code true} if the module is marked with {@code DO_NOT_RESOLVE_BY_DEFAULT}, preventing automatic resolution;
+ * {@code false} otherwise.
+ * @see JEP 11: Incubator Modules
+ */
boolean doNotResolveByDefault();
+ /**
+ * Checks whether the module is marked as deprecated.
+ * This method reads the module resolution attributes from {@code module-info.class}, as specified in JEP 11.
+ *
+ * @return {@code true} if the module is marked with {@code WARN_DEPRECATED}, indicating that it is deprecated;
+ * {@code false} otherwise.
+ * @see JEP 11: Incubator Modules
+ */
boolean warnDeprecated();
+
+ /**
+ * Checks whether the module is deprecated and scheduled for removal in a future release.
+ * This method reads the module resolution attributes from {@code module-info.class}, as specified in JEP 11.
+ *
+ * @return {@code true} if the module is marked with {@code WARN_DEPRECATED_FOR_REMOVAL}, indicating that
+ * it is deprecated and will be removed in a future release;
+ * {@code false} otherwise.
+ * @see JEP 11: Incubator Modules
+ */
boolean warnDeprecatedForRemoval();
+
+ /**
+ * Checks whether the module is in incubating mode, meaning it is not yet standardized.
+ * This method reads the module resolution attributes from {@code module-info.class}, as specified in JEP 11.
+ *
+ * @return {@code true} if the module is marked with {@code WARN_INCUBATING}, indicating that it is an
+ * incubator module and subject to change in future releases;
+ * {@code false} otherwise.
+ * @see JEP 11: Incubator Modules
+ */
boolean warnIncubating();
@NotNull Iterable getRequires();