[java-highlighting] Move JavaPlatformModuleSystem to codeserver.core and deprecate/merge with JavaModuleGraphHelper

We don't need both service and EP to support modules; one thing would be enough. JavaModuleSystem is still used from Kotlin compiler, so should be kept for a while.

GitOrigin-RevId: d55622468eea50cd60c99ada794b6c855dcc0079
This commit is contained in:
Tagir Valeev
2025-03-03 18:30:06 +00:00
committed by intellij-monorepo-bot
parent a4df5744b8
commit 8620b4d854
17 changed files with 167 additions and 105 deletions
@@ -1,6 +1,8 @@
<idea-plugin>
<extensions defaultExtensionNs="com.intellij">
<javaModuleSystem implementation="com.intellij.java.codeserver.core.JavaPlatformModuleSystem"/>
<applicationService serviceInterface="com.intellij.psi.JavaModuleGraphHelper"
serviceImplementation="com.intellij.java.codeserver.core.JavaPsiModuleUtil$Helper"/>
serviceImplementation="com.intellij.java.codeserver.core.JavaPsiModuleUtil$Helper"
overrides="true"/>
</extensions>
</idea-plugin>
@@ -0,0 +1,30 @@
// 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.java.codeserver.core;
import com.intellij.psi.*;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
/**
* Checks package accessibility according to JLS 7 "Packages and Modules".
*
* @see <a href="https://docs.oracle.com/javase/specs/jls/se9/html/jls-7.html">JLS 7 "Packages and Modules"</a>
* @see <a href="http://openjdk.org/jeps/261">JEP 261: Module System</a>
*/
@ApiStatus.Internal
final class JavaPlatformModuleSystem implements JavaModuleSystem {
@Override
public boolean isAccessible(@NotNull String targetPackageName, PsiFile targetFile, @NotNull PsiElement place) {
return JavaModuleGraphHelper.getInstance().isAccessible(targetPackageName, targetFile, place);
}
@Override
public boolean isAccessible(@NotNull PsiJavaModule targetModule, @NotNull PsiElement place) {
return JavaModuleGraphHelper.getInstance().isAccessible(targetModule, place);
}
@Override
public boolean isAccessible(@NotNull PsiClass target, @NotNull PsiElement place) {
return JavaModuleGraphHelper.getInstance().isAccessible(target, place);
}
}
@@ -619,5 +619,22 @@ public final class JavaPsiModuleUtil {
public @NotNull Set<PsiJavaModule> getAllTransitiveDependencies(@NotNull PsiJavaModule psiJavaModule) {
return JavaPsiModuleUtil.getAllTransitiveDependencies(psiJavaModule);
}
@Override
public boolean isAccessible(@NotNull String targetPackageName, PsiFile targetFile, @NotNull PsiElement place) {
PsiFile useFile = place.getContainingFile() != null ? place.getContainingFile().getOriginalFile() : null;
if (useFile == null) return true;
List<JpmsModuleInfo.TargetModuleInfo> infos = JpmsModuleInfo.findTargetModuleInfos(targetPackageName, targetFile, useFile);
if (infos == null) return true;
return !infos.isEmpty() && ContainerUtil.exists(
infos, info -> info.accessAt(useFile).checkAccess(useFile, JpmsModuleAccessInfo.JpmsModuleAccessMode.EXPORT) == null);
}
@Override
public boolean isAccessible(@NotNull PsiJavaModule targetModule, @NotNull PsiElement place) {
PsiFile useFile = place.getContainingFile() != null ? place.getContainingFile().getOriginalFile() : null;
if (useFile == null) return true;
return new JpmsModuleInfo.TargetModuleInfo(targetModule, "").accessAt(useFile).checkModuleAccess(place) == null;
}
}
}
@@ -262,7 +262,7 @@ data class JpmsModuleAccessInfo(val current: JpmsModuleInfo.CurrentModuleInfo, v
val options = JavaCompilerConfigurationProxy.getAdditionalOptions(module.project, module)
if (options.isEmpty()) return false
val prefix = "${targetName}/${packageName}="
return JavaCompilerConfigurationProxy.optionValues(options, JavaModuleSystem.ADD_EXPORTS_OPTION)
return JavaCompilerConfigurationProxy.optionValues(options, ADD_EXPORTS_OPTION)
.filter { it.startsWith(prefix) }
.map { it.substring(prefix.length) }
.flatMap { it.splitToSequence(",") }
@@ -271,22 +271,31 @@ data class JpmsModuleAccessInfo(val current: JpmsModuleInfo.CurrentModuleInfo, v
private fun inAddedModules(module: Module, moduleName: String): Boolean {
val options = JavaCompilerConfigurationProxy.getAdditionalOptions(module.project, module)
return JavaCompilerConfigurationProxy.optionValues(options, JavaModuleSystem.ADD_MODULES_OPTION)
return JavaCompilerConfigurationProxy.optionValues(options, ADD_MODULES_OPTION)
.flatMap { it.splitToSequence(",") }
.any { it == moduleName || it == JavaModuleSystem.ALL_SYSTEM || it == JavaModuleSystem.ALL_MODULE_PATH }
.any { it == moduleName || it == ALL_SYSTEM || it == ALL_MODULE_PATH }
}
private fun inAddedReads(fromJavaModule: PsiJavaModule, toJavaModule: PsiJavaModule?): Boolean {
val fromModule = ModuleUtilCore.findModuleForPsiElement(fromJavaModule) ?: return false
val options = JavaCompilerConfigurationProxy.getAdditionalOptions(fromModule.project, fromModule)
return JavaCompilerConfigurationProxy.optionValues(options, JavaModuleSystem.ADD_READS_OPTION)
return JavaCompilerConfigurationProxy.optionValues(options, ADD_READS_OPTION)
.flatMap { it.splitToSequence(",") }
.any {
val (optFromModuleName, optToModuleName) = it.split("=").apply { it.first() to it.last() }
fromJavaModule.name == optFromModuleName &&
(toJavaModule?.name == optToModuleName || (optToModuleName == JavaModuleSystem.ALL_UNNAMED && isUnnamedModule(toJavaModule)))
(toJavaModule?.name == optToModuleName || (optToModuleName == ALL_UNNAMED && isUnnamedModule(toJavaModule)))
}
}
private fun isUnnamedModule(module: PsiJavaModule?) = module == null || module is LightJavaModule
companion object {
const val ALL_UNNAMED: String = "ALL-UNNAMED"
const val ALL_SYSTEM: String = "ALL-SYSTEM"
const val ALL_MODULE_PATH: String = "ALL-MODULE-PATH"
const val ADD_EXPORTS_OPTION: String = "--add-exports"
const val ADD_MODULES_OPTION: String = "--add-modules"
const val ADD_READS_OPTION: String = "--add-reads"
}
}
@@ -27,7 +27,7 @@ sealed interface JpmsModuleInfo {
* @property jpsModule JPS module initialization.
*/
class CurrentModuleInfo(override val module: PsiJavaModule?, val name: String, jps: () -> Module? = { null }) : JpmsModuleInfo {
constructor(use: PsiJavaModule?, element: PsiElement) : this(use, use?.name ?: JavaModuleSystem.ALL_UNNAMED, {
constructor(use: PsiJavaModule?, element: PsiElement) : this(use, use?.name ?: JpmsModuleAccessInfo.ALL_UNNAMED, {
ModuleUtilCore.findModuleForPsiElement(element)
})