[java-core] Extract JavaPsiModuleUtil with minimized dependencies; new module intellij.java.codeserver.core

Part of IDEA-365344 Create a new Java error highlighter with minimal dependencies (PSI only)

GitOrigin-RevId: 328779172e877b737a68624fa09ea88cf5fd1954
This commit is contained in:
Tagir Valeev
2025-02-07 16:16:32 +00:00
committed by intellij-monorepo-bot
parent 02933bbb0c
commit 0e57ef0ef0
40 changed files with 400 additions and 267 deletions
+1
View File
@@ -443,6 +443,7 @@
<module fileurl="file://$PROJECT_DIR$/java/java-analysis-api/intellij.java.analysis.iml" filepath="$PROJECT_DIR$/java/java-analysis-api/intellij.java.analysis.iml" />
<module fileurl="file://$PROJECT_DIR$/java/java-analysis-impl/intellij.java.analysis.impl.iml" filepath="$PROJECT_DIR$/java/java-analysis-impl/intellij.java.analysis.impl.iml" />
<module fileurl="file://$PROJECT_DIR$/plugins/ByteCodeViewer/intellij.java.byteCodeViewer.iml" filepath="$PROJECT_DIR$/plugins/ByteCodeViewer/intellij.java.byteCodeViewer.iml" />
<module fileurl="file://$PROJECT_DIR$/java/codeserver/core/intellij.java.codeserver.core.iml" filepath="$PROJECT_DIR$/java/codeserver/core/intellij.java.codeserver.core.iml" />
<module fileurl="file://$PROJECT_DIR$/java/codeserver/highlighting/intellij.java.codeserver.highlighting.iml" filepath="$PROJECT_DIR$/java/codeserver/highlighting/intellij.java.codeserver.highlighting.iml" />
<module fileurl="file://$PROJECT_DIR$/java/compiler/openapi/intellij.java.compiler.iml" filepath="$PROJECT_DIR$/java/compiler/openapi/intellij.java.compiler.iml" />
<module fileurl="file://$PROJECT_DIR$/java/compiler/javac2/intellij.java.compiler.antTasks.iml" filepath="$PROJECT_DIR$/java/compiler/javac2/intellij.java.compiler.antTasks.iml" />
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="jetbrains-annotations" level="project" />
<orderEntry type="library" name="StreamEx" level="project" />
<orderEntry type="module" module-name="intellij.platform.util" />
<orderEntry type="module" module-name="intellij.platform.projectModel" />
<orderEntry type="module" module-name="intellij.platform.indexing" />
<orderEntry type="module" module-name="intellij.platform.workspace.jps" />
<orderEntry type="module" module-name="intellij.platform.backend.workspace" />
<orderEntry type="module" module-name="intellij.java.frontback.psi" />
<orderEntry type="module" module-name="intellij.java.psi" />
<orderEntry type="module" module-name="intellij.java.psi.impl" />
<orderEntry type="module" module-name="intellij.java.indexing" />
</component>
</module>
@@ -0,0 +1,33 @@
// 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.java.workspace.entities.JavaModuleSettingsEntity;
import com.intellij.java.workspace.entities.JavaModuleSettingsKt;
import com.intellij.openapi.module.Module;
import com.intellij.platform.backend.workspace.WorkspaceModel;
import com.intellij.platform.workspace.jps.entities.ModuleEntity;
import com.intellij.platform.workspace.jps.entities.ModuleId;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Utility methods related to manifest declarations
*/
public final class JavaManifestUtil {
/**
* @param module module to find manifest in
* @param attribute attribute name from a manifest file
* @return attribute value, null if not found
*/
@Contract(pure = true)
public static @Nullable String getManifestAttributeValue(@NotNull Module module, @NotNull String attribute) {
ModuleEntity entity = WorkspaceModel.getInstance(module.getProject())
.getCurrentSnapshot()
.resolve(new ModuleId(module.getName()));
if (entity == null) return null;
JavaModuleSettingsEntity settings = JavaModuleSettingsKt.getJavaSettings(entity);
if (settings == null) return null;
return settings.getManifestAttributes().get(attribute);
}
}
@@ -0,0 +1,215 @@
// 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.ide.highlighter.ArchiveFileType;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootModificationTracker;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiJavaModuleModificationTracker;
import com.intellij.psi.impl.light.LightJavaModule;
import com.intellij.psi.search.FilenameIndex;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.ProjectScope;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.CachedValuesManager;
import com.intellij.psi.util.JavaMultiReleaseUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.model.java.JavaResourceRootType;
import org.jetbrains.jps.model.java.JavaSourceRootType;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.jar.JarFile;
/**
* Utilities related to JPMS modules
*/
public final class JavaPsiModuleUtil {
/**
* @param element PSI element that belongs to the module
* @return JPMS module the supplied element belongs to; null if no module definition is found
*/
@Contract("null->null")
public static @Nullable PsiJavaModule findDescriptorByElement(@Nullable PsiElement element) {
if (element == null) return null;
if (element instanceof PsiJavaModule module) return module;
if (element.getContainingFile() instanceof PsiJavaFile file) {
PsiJavaModule module = file.getModuleDeclaration();
if (module != null) return module;
}
if (element instanceof PsiFileSystemItem fsItem) {
return findDescriptorByFile(fsItem.getVirtualFile(), fsItem.getProject());
}
PsiFile file = element.getContainingFile();
if (file != null) {
return findDescriptorByFile(file.getVirtualFile(), file.getProject());
}
if (element instanceof PsiPackage psiPackage) {
PsiDirectory[] directories = psiPackage.getDirectories(ProjectScope.getLibrariesScope(psiPackage.getProject()));
for (PsiDirectory directory : directories) {
PsiJavaModule descriptor = findDescriptorByFile(directory.getVirtualFile(), directory.getProject());
if (descriptor != null) return descriptor;
}
}
return null;
}
/**
* @param file virtual file that belongs to a module
* @param project current project
* @return JPMS module the supplied file belongs to; null if no module definition is found
*/
@Contract("null, _->null")
public static @Nullable PsiJavaModule findDescriptorByFile(@Nullable VirtualFile file, @NotNull Project project) {
if (file == null) return null;
ProjectFileIndex index = ProjectFileIndex.getInstance(project);
return index.isInLibrary(file)
? findDescriptorInLibrary(file, project)
: findDescriptorByModule(index.getModuleForFile(file), index.isInTestSourceContent(file));
}
/**
* @param library library that declares a JPMS module
* @param project current project
* @return JPMS module declared by the supplied library; null if not found
*/
@Contract("null, _ -> null")
public static @Nullable PsiJavaModule findDescriptorByLibrary(@Nullable Library library, @NotNull Project project) {
if (library == null) return null;
final VirtualFile[] files = library.getFiles(OrderRootType.CLASSES);
if (files.length == 0) return null;
final PsiJavaModule javaModule = findDescriptorInLibrary(files[0], project);
return javaModule != null && javaModule.isValid() ? javaModule : null;
}
/**
* @param file library content root
* @param project current project
* @return JPMS module declared by the supplied library; null if not found
*/
public static @Nullable PsiJavaModule findDescriptorInLibrary(@NotNull VirtualFile file, @NotNull Project project) {
ProjectFileIndex index = ProjectFileIndex.getInstance(project);
VirtualFile root = index.getClassRootForFile(file);
if (root != null) {
VirtualFile descriptorFile =
JavaMultiReleaseUtil.findVersionSpecificFile(root, PsiJavaModule.MODULE_INFO_CLS_FILE, LanguageLevel.HIGHEST);
if (descriptorFile != null) {
PsiFile psiFile = PsiManager.getInstance(project).findFile(descriptorFile);
if (psiFile instanceof PsiJavaFile) {
return ((PsiJavaFile)psiFile).getModuleDeclaration();
}
}
else if (root.getFileType() instanceof ArchiveFileType && "jar".equalsIgnoreCase(root.getExtension())) {
PsiDirectory rootPsi = PsiManager.getInstance(project).findDirectory(root);
assert rootPsi != null : root;
return CachedValuesManager.getCachedValue(rootPsi, () -> {
VirtualFile _root = rootPsi.getVirtualFile();
LightJavaModule result = LightJavaModule.create(rootPsi.getManager(), _root, LightJavaModule.moduleName(_root));
return CachedValueProvider.Result.create(result, _root, ProjectRootModificationTracker.getInstance(rootPsi.getProject()));
});
}
}
else {
root = index.getSourceRootForFile(file);
if (root != null) {
VirtualFile moduleDescriptor = root.findChild(PsiJavaModule.MODULE_INFO_FILE);
PsiFile psiFile = moduleDescriptor != null ? PsiManager.getInstance(project).findFile(moduleDescriptor) : null;
if (psiFile instanceof PsiJavaFile) {
return ((PsiJavaFile)psiFile).getModuleDeclaration();
}
}
}
return null;
}
/**
* @param module IntelliJ IDEA module
* @param inTests if true, the search will be performed in test root
* @return JPMS module that corresponds to a given IntelliJ IDEA module; null if not found
*/
@Contract("null,_->null")
public static @Nullable PsiJavaModule findDescriptorByModule(@Nullable Module module, boolean inTests) {
if (module == null) return null;
CachedValuesManager valuesManager = CachedValuesManager.getManager(module.getProject());
PsiJavaModule javaModule = inTests //to have different providers for production and tests
? valuesManager.getCachedValue(module, () -> createModuleCacheResult(module, true))
: valuesManager.getCachedValue(module, () -> createModuleCacheResult(module, false));
return javaModule != null && javaModule.isValid() ? javaModule : null;
}
private static @NotNull CachedValueProvider.Result<PsiJavaModule> createModuleCacheResult(@NotNull Module module,
boolean inTests) {
Project project = module.getProject();
return new CachedValueProvider.Result<>(findDescriptionByModuleInner(module, inTests),
ProjectRootModificationTracker.getInstance(project),
PsiJavaModuleModificationTracker.getInstance(project));
}
private static @Nullable PsiJavaModule findDescriptionByModuleInner(@NotNull Module module, boolean inTests) {
Project project = module.getProject();
GlobalSearchScope moduleScope = module.getModuleScope();
String virtualAutoModuleName = JavaManifestUtil.getManifestAttributeValue(module, PsiJavaModule.AUTO_MODULE_NAME);
if (!DumbService.isDumb(project) &&
FilenameIndex.getVirtualFilesByName(PsiJavaModule.MODULE_INFO_FILE, moduleScope).isEmpty() &&
FilenameIndex.getVirtualFilesByName("MANIFEST.MF", moduleScope).isEmpty() &&
virtualAutoModuleName == null) {
return null;
}
JavaSourceRootType rootType = inTests ? JavaSourceRootType.TEST_SOURCE : JavaSourceRootType.SOURCE;
ModuleRootManager rootManager = ModuleRootManager.getInstance(module);
List<VirtualFile> sourceRoots = rootManager.getSourceRoots(rootType);
Set<VirtualFile> excludeRoots = ContainerUtil.newHashSet(ModuleRootManager.getInstance(module).getExcludeRoots());
if (!excludeRoots.isEmpty()) sourceRoots.removeIf(root -> excludeRoots.contains(root));
List<VirtualFile> files = ContainerUtil.mapNotNull(sourceRoots, root -> root.findChild(PsiJavaModule.MODULE_INFO_FILE));
if (files.isEmpty()) {
JavaResourceRootType resourceRootType = inTests ? JavaResourceRootType.TEST_RESOURCE : JavaResourceRootType.RESOURCE;
List<VirtualFile> roots = new ArrayList<>(rootManager.getSourceRoots(resourceRootType));
roots.addAll(sourceRoots);
files = ContainerUtil.mapNotNull(roots, root -> root.findFileByRelativePath(JarFile.MANIFEST_NAME));
if (files.size() == 1 || new HashSet<>(files).size() == 1) {
VirtualFile manifest = files.get(0);
PsiFile manifestPsi = PsiManager.getInstance(project).findFile(manifest);
assert manifestPsi != null : manifest;
return CachedValuesManager.getCachedValue(manifestPsi, () -> {
String name = LightJavaModule.claimedModuleName(manifest);
LightJavaModule result =
name != null ? LightJavaModule.create(PsiManager.getInstance(project), manifest.getParent().getParent(), name) : null;
return CachedValueProvider.Result.create(result, manifestPsi, ProjectRootModificationTracker.getInstance(project));
});
}
List<VirtualFile> sourceSourceRoots = rootManager.getSourceRoots(JavaSourceRootType.SOURCE);
if (virtualAutoModuleName != null && !sourceSourceRoots.isEmpty()) {
return LightJavaModule.create(PsiManager.getInstance(project), sourceSourceRoots.get(0), virtualAutoModuleName);
}
}
else {
final VirtualFile file = files.get(0);
if (ContainerUtil.and(files, f -> f.equals(file))) {
PsiFile psiFile = PsiManager.getInstance(project).findFile(file);
if (psiFile instanceof PsiJavaFile) {
return ((PsiJavaFile)psiFile).getModuleDeclaration();
}
}
}
return null;
}
}
@@ -0,0 +1,6 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
/**
* Core functionality required by Java codeserver and other parts of Java plugin.
* Mostly contains utility classes.
*/
package com.intellij.java.codeserver.core;
@@ -30,5 +30,6 @@
<orderEntry type="module" module-name="intellij.java.frontback.impl" exported="" />
<orderEntry type="module" module-name="intellij.platform.editor.ex" />
<orderEntry type="module" module-name="intellij.java.codeserver.highlighting" />
<orderEntry type="module" module-name="intellij.java.codeserver.core" />
</component>
</module>
@@ -3,9 +3,9 @@ package com.intellij.codeInsight.daemon.impl;
import com.intellij.codeInsight.daemon.GutterIconNavigationHandler;
import com.intellij.codeInsight.daemon.LineMarkerInfo;
import com.intellij.codeInsight.daemon.impl.analysis.JavaModuleGraphUtil;
import com.intellij.icons.AllIcons;
import com.intellij.java.analysis.JavaAnalysisBundle;
import com.intellij.java.codeserver.core.JavaPsiModuleUtil;
import com.intellij.navigation.NavigationItem;
import com.intellij.openapi.editor.markup.GutterIconRenderer;
import com.intellij.openapi.util.NlsSafe;
@@ -84,7 +84,7 @@ public final class JavaServiceUtil {
String implementerClassName = implementerClass.getQualifiedName();
if (implementerClassName == null) return Collections.emptyList();
PsiJavaModule javaModule = JavaModuleGraphUtil.findDescriptorByElement(identifier);
PsiJavaModule javaModule = JavaPsiModuleUtil.findDescriptorByElement(identifier);
if (javaModule == null) return Collections.emptyList();
for (PsiProvidesStatement providesStatement : javaModule.getProvides()) {
@@ -134,7 +134,7 @@ public final class JavaServiceUtil {
String qualifiedName = psiClass.getQualifiedName();
if (qualifiedName == null) return Collections.emptyList();
PsiJavaModule javaModule = JavaModuleGraphUtil.findDescriptorByElement(methodCall);
PsiJavaModule javaModule = JavaPsiModuleUtil.findDescriptorByElement(methodCall);
if (javaModule == null) return Collections.emptyList();
for (PsiUsesStatement statement : javaModule.getUses()) {
@@ -162,7 +162,7 @@ public final class JavaServiceUtil {
@Override
public void navigate(MouseEvent e, @Nullable PsiElement element) {
Optional.ofNullable(JavaModuleGraphUtil.findDescriptorByElement(element))
Optional.ofNullable(JavaPsiModuleUtil.findDescriptorByElement(element))
.map(this::findTargetReference)
.filter(NavigationItem.class::isInstance)
.map(NavigationItem.class::cast)
@@ -7,6 +7,7 @@ import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.intention.QuickFixFactory;
import com.intellij.java.codeserver.core.JavaPsiModuleUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
@@ -49,7 +50,7 @@ public final class HighlightClassUtil {
}
if (!JavaPsiFacade.getInstance(aClass.getProject()).arePackagesTheSame(aClass, superClass) &&
JavaModuleGraphUtil.findDescriptorByElement(aClass) == null) {
JavaPsiModuleUtil.findDescriptorByElement(aClass) == null) {
String description = StringUtil.capitalize(JavaErrorBundle.message(
"class.not.allowed.to.extend.sealed.class.from.another.package",
JavaElementKind.fromElement(aClass).subject(), HighlightUtil.formatClass(aClass, false),
@@ -96,7 +97,7 @@ public final class HighlightClassUtil {
if (!(parent instanceof PsiClass aClass) || !list.equals(aClass.getPermitsList())) {
return;
}
PsiJavaModule currentModule = JavaModuleGraphUtil.findDescriptorByElement(aClass);
PsiJavaModule currentModule = JavaPsiModuleUtil.findDescriptorByElement(aClass);
JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(aClass.getProject());
for (PsiJavaCodeReferenceElement permitted : list.getReferenceElements()) {
@@ -147,7 +148,7 @@ public final class HighlightClassUtil {
}
errorSink.accept(info);
}
else if (currentModule != null && !areModulesTheSame(currentModule, JavaModuleGraphUtil.findDescriptorByElement(inheritorClass))) {
else if (currentModule != null && !areModulesTheSame(currentModule, JavaPsiModuleUtil.findDescriptorByElement(inheritorClass))) {
HighlightInfo.Builder info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
.range(permitted)
.descriptionAndTooltip(JavaErrorBundle.message("class.not.allowed.to.extend.sealed.class.from.another.module"));
@@ -9,6 +9,7 @@ import com.intellij.codeInsight.daemon.impl.HighlightVisitor;
import com.intellij.codeInsight.intention.CommonIntentionAction;
import com.intellij.codeInsight.quickfix.UnresolvedReferenceQuickFixProvider;
import com.intellij.codeInspection.ex.GlobalInspectionContextBase;
import com.intellij.java.codeserver.core.JavaPsiModuleUtil;
import com.intellij.java.codeserver.highlighting.JavaErrorCollector;
import com.intellij.java.codeserver.highlighting.errors.JavaCompilationError;
import com.intellij.java.codeserver.highlighting.errors.JavaErrorHighlightType;
@@ -145,7 +146,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
myHolder = holder;
myFile = file;
myLanguageLevel = PsiUtil.getLanguageLevel(file);
myJavaModule = JavaFeature.MODULES.isSufficient(myLanguageLevel) ? JavaModuleGraphUtil.findDescriptorByElement(file) : null;
myJavaModule = JavaFeature.MODULES.isSufficient(myLanguageLevel) ? JavaPsiModuleUtil.findDescriptorByElement(file) : null;
JavaErrorFixProvider errorFixProvider = JavaErrorFixProvider.getInstance();
myCollector = new JavaErrorCollector(myFile, myJavaModule, error -> reportError(error, errorFixProvider));
}
@@ -1,6 +1,7 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.daemon.impl.analysis;
import com.intellij.java.codeserver.core.JavaPsiModuleUtil;
import com.intellij.psi.JavaModuleGraphHelper;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiJavaModule;
@@ -14,7 +15,7 @@ public class JavaModuleGraphHelperImpl extends JavaModuleGraphHelper {
@Contract("null->null")
@Override
public @Nullable PsiJavaModule findDescriptorByElement(@Nullable PsiElement element) {
return JavaModuleGraphUtil.findDescriptorByElement(element);
return JavaPsiModuleUtil.findDescriptorByElement(element);
}
@Override
@@ -3,6 +3,7 @@ package com.intellij.codeInsight.daemon.impl.analysis;
import com.intellij.ide.highlighter.JavaClassFileType;
import com.intellij.ide.highlighter.JavaFileType;
import com.intellij.java.codeserver.core.JavaPsiModuleUtil;
import com.intellij.lang.Language;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.lang.jvm.JvmLanguage;
@@ -17,7 +18,6 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.util.Trinity;
import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.java.JavaFeature;
import com.intellij.psi.*;
@@ -25,7 +25,6 @@ import com.intellij.psi.impl.PsiJavaModuleModificationTracker;
import com.intellij.psi.impl.java.stubs.index.JavaModuleNameIndex;
import com.intellij.psi.impl.light.LightJavaModule;
import com.intellij.psi.impl.source.resolve.JavaResolveUtil;
import com.intellij.psi.search.FilenameIndex;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.ProjectScope;
import com.intellij.psi.util.CachedValueProvider.Result;
@@ -43,15 +42,13 @@ import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.Unmodifiable;
import org.jetbrains.jps.model.java.JavaResourceRootType;
import org.jetbrains.jps.model.java.JavaSourceRootType;
import java.util.*;
import java.util.function.BiFunction;
import java.util.jar.JarFile;
import static com.intellij.openapi.roots.DependencyScope.PROVIDED;
import static com.intellij.psi.PsiJavaModule.JAVA_BASE;
import static java.util.Objects.requireNonNullElse;
public final class JavaModuleGraphUtil {
private static final Set<String> STATIC_REQUIRES_MODULE_NAMES = Set.of("lombok");
@@ -60,91 +57,21 @@ public final class JavaModuleGraphUtil {
@Contract("null->null")
public static @Nullable PsiJavaModule findDescriptorByElement(@Nullable PsiElement element) {
if (element == null) return null;
if (element instanceof PsiJavaModule module) return module;
if (element.getContainingFile() instanceof PsiJavaFile file) {
PsiJavaModule module = file.getModuleDeclaration();
if (module != null) return module;
}
if (element instanceof PsiFileSystemItem fsItem) {
return findDescriptorByFile(fsItem.getVirtualFile(), fsItem.getProject());
}
PsiFile file = element.getContainingFile();
if (file != null) {
return findDescriptorByFile(file.getVirtualFile(), file.getProject());
}
if (element instanceof PsiPackage psiPackage) {
PsiDirectory[] directories = psiPackage.getDirectories(ProjectScope.getLibrariesScope(psiPackage.getProject()));
for (PsiDirectory directory : directories) {
PsiJavaModule descriptor = findDescriptorByFile(directory.getVirtualFile(), directory.getProject());
if (descriptor != null) return descriptor;
}
}
return null;
return JavaPsiModuleUtil.findDescriptorByElement(element);
}
@Contract("null,_->null")
public static @Nullable PsiJavaModule findDescriptorByFile(@Nullable VirtualFile file, @NotNull Project project) {
if (file == null) return null;
ProjectFileIndex index = ProjectFileIndex.getInstance(project);
return index.isInLibrary(file)
? findDescriptorInLibrary(project, index, file)
: findDescriptorByModule(index.getModuleForFile(file), index.isInTestSourceContent(file));
}
private static @Nullable PsiJavaModule findDescriptorInLibrary(@NotNull Project project, @NotNull ProjectFileIndex index, @NotNull VirtualFile file) {
VirtualFile root = index.getClassRootForFile(file);
if (root != null) {
VirtualFile descriptorFile = JavaModuleNameIndex.descriptorFile(root);
if (descriptorFile != null) {
PsiFile psiFile = PsiManager.getInstance(project).findFile(descriptorFile);
if (psiFile instanceof PsiJavaFile) {
return ((PsiJavaFile)psiFile).getModuleDeclaration();
}
}
else if (root.getFileSystem() instanceof JarFileSystem && "jar".equalsIgnoreCase(root.getExtension())) {
PsiDirectory rootPsi = PsiManager.getInstance(project).findDirectory(root);
assert rootPsi != null : root;
return CachedValuesManager.getCachedValue(rootPsi, () -> {
VirtualFile _root = rootPsi.getVirtualFile();
LightJavaModule result = LightJavaModule.create(rootPsi.getManager(), _root, LightJavaModule.moduleName(_root));
return Result.create(result, _root, ProjectRootModificationTracker.getInstance(rootPsi.getProject()));
});
}
}
else {
root = index.getSourceRootForFile(file);
if (root != null) {
VirtualFile moduleDescriptor = root.findChild(PsiJavaModule.MODULE_INFO_FILE);
PsiFile psiFile = moduleDescriptor != null ? PsiManager.getInstance(project).findFile(moduleDescriptor) : null;
if (psiFile instanceof PsiJavaFile) {
return ((PsiJavaFile)psiFile).getModuleDeclaration();
}
}
}
return null;
return JavaPsiModuleUtil.findDescriptorByFile(file, project);
}
@Contract("null,_->null")
public static @Nullable PsiJavaModule findDescriptorByModule(@Nullable Module module, boolean inTests) {
if (module == null) return null;
CachedValuesManager valuesManager = CachedValuesManager.getManager(module.getProject());
PsiJavaModule javaModule = inTests //to have different providers for production and tests
? valuesManager.getCachedValue(module, () -> createModuleCacheResult(module, true))
: valuesManager.getCachedValue(module, () -> createModuleCacheResult(module, false));
return javaModule != null && javaModule.isValid() ? javaModule : null;
return JavaPsiModuleUtil.findDescriptorByModule(module, inTests);
}
public static @Nullable PsiJavaModule findDescriptorByLibrary(@Nullable Library library, @NotNull Project project) {
if (library == null) return null;
final VirtualFile[] files = library.getFiles(OrderRootType.CLASSES);
if (files.length == 0) return null;
final PsiJavaModule javaModule = findDescriptorInLibrary(project, ProjectFileIndex.getInstance(project), files[0]);
return javaModule != null && javaModule.isValid() ? javaModule : null;
return JavaPsiModuleUtil.findDescriptorByLibrary(library, project);
}
public static @Nullable PsiJavaModule findNonAutomaticDescriptorByModule(@Nullable Module module, boolean inTests) {
@@ -152,72 +79,13 @@ public final class JavaModuleGraphUtil {
return javaModule instanceof LightJavaModule ? null : javaModule;
}
private static @NotNull Result<PsiJavaModule> createModuleCacheResult(@NotNull Module module,
boolean inTests) {
Project project = module.getProject();
return new Result<>(findDescriptionByModuleInner(module, inTests),
ProjectRootModificationTracker.getInstance(project),
PsiJavaModuleModificationTracker.getInstance(project));
}
private static @Nullable PsiJavaModule findDescriptionByModuleInner(@NotNull Module module, boolean inTests) {
Project project = module.getProject();
GlobalSearchScope moduleScope = module.getModuleScope();
String virtualAutoModuleName = ManifestUtil.lightManifestAttributeValue(module, PsiJavaModule.AUTO_MODULE_NAME);
if (!DumbService.isDumb(project) &&
FilenameIndex.getVirtualFilesByName(PsiJavaModule.MODULE_INFO_FILE, moduleScope).isEmpty() &&
FilenameIndex.getVirtualFilesByName("MANIFEST.MF", moduleScope).isEmpty() &&
virtualAutoModuleName == null) {
return null;
}
JavaSourceRootType rootType = inTests ? JavaSourceRootType.TEST_SOURCE : JavaSourceRootType.SOURCE;
ModuleRootManager rootManager = ModuleRootManager.getInstance(module);
List<VirtualFile> sourceRoots = rootManager.getSourceRoots(rootType);
Set<VirtualFile> excludeRoots = ContainerUtil.newHashSet(ModuleRootManager.getInstance(module).getExcludeRoots());
if (!excludeRoots.isEmpty()) sourceRoots.removeIf(root -> excludeRoots.contains(root));
List<VirtualFile> files = ContainerUtil.mapNotNull(sourceRoots, root -> root.findChild(PsiJavaModule.MODULE_INFO_FILE));
if (files.isEmpty()) {
JavaResourceRootType resourceRootType = inTests ? JavaResourceRootType.TEST_RESOURCE : JavaResourceRootType.RESOURCE;
List<VirtualFile> roots = new ArrayList<>(rootManager.getSourceRoots(resourceRootType));
roots.addAll(sourceRoots);
files = ContainerUtil.mapNotNull(roots, root -> root.findFileByRelativePath(JarFile.MANIFEST_NAME));
if (files.size() == 1 || new HashSet<>(files).size() == 1) {
VirtualFile manifest = files.get(0);
PsiFile manifestPsi = PsiManager.getInstance(project).findFile(manifest);
assert manifestPsi != null : manifest;
return CachedValuesManager.getCachedValue(manifestPsi, () -> {
String name = LightJavaModule.claimedModuleName(manifest);
LightJavaModule result =
name != null ? LightJavaModule.create(PsiManager.getInstance(project), manifest.getParent().getParent(), name) : null;
return Result.create(result, manifestPsi, ProjectRootModificationTracker.getInstance(project));
});
}
List<VirtualFile> sourceSourceRoots = rootManager.getSourceRoots(JavaSourceRootType.SOURCE);
if (virtualAutoModuleName != null && !sourceSourceRoots.isEmpty()) {
return LightJavaModule.create(PsiManager.getInstance(project), sourceSourceRoots.get(0), virtualAutoModuleName);
}
}
else {
final VirtualFile file = files.get(0);
if (ContainerUtil.and(files, f -> f.equals(file))) {
PsiFile psiFile = PsiManager.getInstance(project).findFile(file);
if (psiFile instanceof PsiJavaFile) {
return ((PsiJavaFile)psiFile).getModuleDeclaration();
}
}
}
return null;
}
public static @NotNull Collection<PsiJavaModule> findCycle(@NotNull PsiJavaModule module) {
Project project = module.getProject();
List<Set<PsiJavaModule>> cycles = CachedValuesManager.getManager(project).getCachedValue(project, () ->
Result.create(findCycles(project),
PsiJavaModuleModificationTracker.getInstance(project),
ProjectRootModificationTracker.getInstance(project)));
return Objects.requireNonNullElse(ContainerUtil.find(cycles, set -> set.contains(module)), Collections.emptyList());
return requireNonNullElse(ContainerUtil.find(cycles, set -> set.contains(module)), Collections.emptyList());
}
public static boolean exports(@NotNull PsiJavaModule source, @NotNull String packageName, @Nullable PsiJavaModule target) {
@@ -290,13 +158,6 @@ public final class JavaModuleGraphUtil {
return true;
}
private static @Nullable PsiJavaModule findDependencyByName(@NotNull PsiJavaModule module, @NotNull String name) {
for (PsiRequiresStatement require : module.getRequires()) {
if (name.equals(require.getModuleName())) return require.resolve();
}
return null;
}
public static boolean addDependency(@NotNull PsiElement from,
@NotNull PsiClass to,
@Nullable DependencyScope scope) {
@@ -685,7 +546,7 @@ public final class JavaModuleGraphUtil {
if (project == null) return false;
if (!isJvmLanguageFile(file)) return false;
ProjectFileIndex index = ProjectFileIndex.getInstance(project);
if (index.isInLibrary(file)) return myIncludeLibraries && contains(findDescriptorInLibrary(project, index, file));
if (index.isInLibrary(file)) return myIncludeLibraries && contains(JavaPsiModuleUtil.findDescriptorInLibrary(file, project));
Module module = index.getModuleForFile(file);
return contains(findDescriptorByModule(module, myIsInTests));
}
@@ -3,6 +3,7 @@ package com.intellij.codeInsight.daemon.impl.analysis;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.java.JavaBundle;
import com.intellij.java.codeserver.core.JavaPsiModuleUtil;
import com.intellij.lang.jvm.JvmModifier;
import com.intellij.openapi.util.NlsSafe;
import com.intellij.pom.java.JavaFeature;
@@ -141,7 +142,7 @@ public final class JavaPreviewFeatureUtil {
annotation = containingClass == null ? null : getPreviewFeatureAnnotationInternal(containingClass);
}
if (annotation == null && !(element instanceof PsiJavaModule)) {
PsiJavaModule javaModule = JavaModuleGraphUtil.findDescriptorByElement(element);
PsiJavaModule javaModule = JavaPsiModuleUtil.findDescriptorByElement(element);
annotation = javaModule == null ? null : getPreviewFeatureAnnotationInternal(javaModule);
}
return annotation;
@@ -191,7 +192,7 @@ public final class JavaPreviewFeatureUtil {
PsiAnnotation packageAnnotation = getAnnotation(psiPackage);
if (packageAnnotation != null) return packageAnnotation;
PsiJavaModule module = JavaModuleGraphUtil.findDescriptorByElement(owner);
PsiJavaModule module = JavaPsiModuleUtil.findDescriptorByElement(owner);
if (module == null) return null;
return getAnnotation(module);
@@ -0,0 +1,18 @@
// 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.codeInsight.daemon.impl.analysis;
import com.intellij.java.codeserver.core.JavaManifestUtil;
import com.intellij.openapi.module.Module;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public final class ManifestUtil {
/**
* Retrieve attribute value from module stored through build scripts.
*/
@Contract(pure = true)
public static @Nullable String lightManifestAttributeValue(@NotNull Module module, @NotNull String attribute) {
return JavaManifestUtil.getManifestAttributeValue(module, attribute);
}
}
@@ -1,21 +0,0 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
@file:JvmName("ManifestUtil")
package com.intellij.codeInsight.daemon.impl.analysis
import com.intellij.java.workspace.entities.javaSettings
import com.intellij.openapi.module.Module
import com.intellij.platform.backend.workspace.WorkspaceModel
import com.intellij.platform.workspace.jps.entities.ModuleId
import org.jetbrains.annotations.Contract
/**
* Retrieve attribute value from [module] stored through build scripts.
*/
@Contract(pure = true)
fun lightManifestAttributeValue(module: Module, attribute: String): String? {
return WorkspaceModel.getInstance(module.project)
.currentSnapshot.resolve(ModuleId(module.name))
?.javaSettings
?.manifestAttributes
?.get(attribute)
}
@@ -10,6 +10,7 @@ import com.intellij.codeInsight.daemon.impl.JavaServiceUtil;
import com.intellij.codeInsight.daemon.impl.quickfix.*;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.intention.QuickFixFactory;
import com.intellij.java.codeserver.core.JavaPsiModuleUtil;
import com.intellij.modcommand.ModCommandAction;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.module.Module;
@@ -78,7 +79,7 @@ final class ModuleHighlightUtil {
if (pack != null) {
ProjectFileIndex fileIndex = ProjectRootManager.getInstance(pack.getProject()).getFileIndex();
for (PsiDirectory directory : pack.getDirectories()) {
PsiJavaModule anotherJavaModule = JavaModuleGraphUtil.findDescriptorByElement(directory);
PsiJavaModule anotherJavaModule = JavaPsiModuleUtil.findDescriptorByElement(directory);
if (anotherJavaModule != null) {
VirtualFile moduleVFile = PsiUtilCore.getVirtualFile(anotherJavaModule);
if (moduleVFile != null && ContainerUtil.find(fileIndex.getOrderEntriesForFile(moduleVFile), JdkOrderEntry.class::isInstance) != null) {
@@ -2,10 +2,10 @@
package com.intellij.codeInspection.java19modules;
import com.intellij.codeInsight.daemon.impl.JavaServiceUtil;
import com.intellij.codeInsight.daemon.impl.analysis.JavaModuleGraphUtil;
import com.intellij.codeInspection.reference.*;
import com.intellij.codeInspection.visibility.EntryPointWithVisibilityLevel;
import com.intellij.java.analysis.JavaAnalysisBundle;
import com.intellij.java.codeserver.core.JavaPsiModuleUtil;
import com.intellij.openapi.util.DefaultJDOMExternalizer;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.WriteExternalException;
@@ -115,7 +115,7 @@ public final class Java9ModuleEntryPoint extends EntryPointWithVisibilityLevel {
}
private static @Nullable PsiJavaModule getJavaModule(@Nullable PsiElement element) {
return element != null && PsiUtil.isAvailable(JavaFeature.MODULES, element) ? JavaModuleGraphUtil.findDescriptorByElement(element) : null;
return element != null && PsiUtil.isAvailable(JavaFeature.MODULES, element) ? JavaPsiModuleUtil.findDescriptorByElement(element) : null;
}
private static boolean isInExportedPackage(@NotNull PsiClass psiClass, @NotNull PsiJavaModule javaModule) {
@@ -1,8 +1,8 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.siyeh.ig.psiutils;
import com.intellij.codeInsight.daemon.impl.analysis.JavaModuleGraphUtil;
import com.intellij.java.JavaBundle;
import com.intellij.java.codeserver.core.JavaPsiModuleUtil;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
@@ -127,7 +127,7 @@ public final class SealedUtils {
result = "intention.error.make.sealed.class.different.packages";
}
}
else if (JavaModuleGraphUtil.findDescriptorByElement(inheritor) != module) {
else if (JavaPsiModuleUtil.findDescriptorByElement(inheritor) != module) {
result = "intention.error.make.sealed.class.different.modules";
}
return result;
@@ -15,10 +15,10 @@
*/
package com.siyeh.ig.visibility;
import com.intellij.codeInsight.daemon.impl.analysis.JavaModuleGraphUtil;
import com.intellij.codeInspection.AbstractBaseJavaLocalInspectionTool;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.codeInspection.options.OptPane;
import com.intellij.java.codeserver.core.JavaPsiModuleUtil;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.roots.ModuleFileIndex;
import com.intellij.openapi.roots.ModuleRootManager;
@@ -69,7 +69,7 @@ public final class ClassEscapesItsScopeInspection extends AbstractBaseJavaLocalI
if (checkModuleApi) {
PsiFile file = holder.getFile();
if (file instanceof PsiJavaFile javaFile && PsiUtil.isAvailable(JavaFeature.MODULES, javaFile)) {
PsiJavaModule psiModule = JavaModuleGraphUtil.findDescriptorByElement(file);
PsiJavaModule psiModule = JavaPsiModuleUtil.findDescriptorByElement(file);
if (psiModule != null) {
VirtualFile vFile = file.getVirtualFile();
if (vFile != null) {
@@ -23,5 +23,6 @@
<orderEntry type="module" module-name="intellij.platform.core.ui" />
<orderEntry type="module" module-name="intellij.platform.util.text.matching" />
<orderEntry type="module" module-name="intellij.java.codeserver.highlighting" />
<orderEntry type="module" module-name="intellij.java.codeserver.core" />
</component>
</module>
@@ -3,9 +3,9 @@ package com.intellij.codeInspection;
import com.intellij.codeInsight.TestFrameworks;
import com.intellij.codeInsight.daemon.impl.UnusedSymbolUtil;
import com.intellij.codeInsight.daemon.impl.analysis.JavaModuleGraphUtil;
import com.intellij.ide.highlighter.JavaFileType;
import com.intellij.java.JavaBundle;
import com.intellij.java.codeserver.core.JavaPsiModuleUtil;
import com.intellij.modcommand.ModPsiUpdater;
import com.intellij.modcommand.PsiUpdateModCommandQuickFix;
import com.intellij.openapi.project.Project;
@@ -64,7 +64,7 @@ public final class ExplicitToImplicitClassMigrationInspection extends AbstractBa
return;
}
PsiJavaModule javaModule = JavaModuleGraphUtil.findDescriptorByElement(aClass);
PsiJavaModule javaModule = JavaPsiModuleUtil.findDescriptorByElement(aClass);
if (javaModule != null) {
return;
}
@@ -1,11 +1,11 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInspection.java19api;
import com.intellij.codeInsight.daemon.impl.analysis.JavaModuleGraphUtil;
import com.intellij.codeInsight.daemon.impl.quickfix.AddUsesDirectiveFix;
import com.intellij.codeInspection.AbstractBaseJavaLocalInspectionTool;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.java.JavaBundle;
import com.intellij.java.codeserver.core.JavaPsiModuleUtil;
import com.intellij.pom.java.JavaFeature;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.reference.impl.JavaReflectionReferenceUtil;
@@ -63,7 +63,7 @@ public final class Java9UndeclaredServiceUsageInspection extends AbstractBaseJav
if (psiClass != null) {
String qualifiedName = psiClass.getQualifiedName();
if (qualifiedName != null) {
PsiJavaModule module = JavaModuleGraphUtil.findDescriptorByElement(argument);
PsiJavaModule module = JavaPsiModuleUtil.findDescriptorByElement(argument);
if (module != null && isUndeclaredUsage(module, psiClass)) {
holder.problem(argument, JavaBundle.message("inspection.undeclared.service.usage.message", qualifiedName))
.fix(new AddUsesDirectiveFix(module, qualifiedName)).register();
@@ -4,6 +4,7 @@ package com.intellij.codeInspection.java19api;
import com.intellij.codeInsight.daemon.impl.analysis.JavaModuleGraphUtil;
import com.intellij.codeInspection.*;
import com.intellij.java.JavaBundle;
import com.intellij.java.codeserver.core.JavaPsiModuleUtil;
import com.intellij.modcommand.ModPsiUpdater;
import com.intellij.modcommand.PsiUpdateModCommandQuickFix;
import com.intellij.openapi.module.Module;
@@ -158,12 +159,12 @@ public class JavaEmptyModuleInfoFileInspection extends AbstractBaseJavaLocalInsp
if (psiElement instanceof PsiPackage psiPackage) {
PsiDirectory[] directories = psiPackage.getDirectories(psiPackage.getResolveScope());
for (PsiDirectory directory : directories) {
PsiJavaModule descriptor = JavaModuleGraphUtil.findDescriptorByElement(directory);
PsiJavaModule descriptor = JavaPsiModuleUtil.findDescriptorByElement(directory);
if (descriptor != null) return descriptor;
}
}
else {
return JavaModuleGraphUtil.findDescriptorByElement(psiElement);
return JavaPsiModuleUtil.findDescriptorByElement(psiElement);
}
return null;
}
@@ -8,6 +8,7 @@ import com.intellij.codeInsight.daemon.impl.quickfix.AddRequiresDirectiveFix;
import com.intellij.codeInspection.AbstractBaseJavaLocalInspectionTool;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.java.JavaBundle;
import com.intellij.java.codeserver.core.JavaPsiModuleUtil;
import com.intellij.openapi.project.Project;
import com.intellij.pom.java.JavaFeature;
import com.intellij.psi.*;
@@ -29,7 +30,7 @@ public final class Java9ReflectionClassVisibilityInspection extends AbstractBase
@Override
public @NotNull PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
final PsiJavaModule javaModule = JavaModuleGraphUtil.findDescriptorByElement(holder.getFile());
final PsiJavaModule javaModule = JavaPsiModuleUtil.findDescriptorByElement(holder.getFile());
if (javaModule != null) {
return new JavaElementVisitor() {
@Override
@@ -59,7 +60,7 @@ public final class Java9ReflectionClassVisibilityInspection extends AbstractBase
final JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
final PsiClass psiClass = facade.findClass(className, callExpression.getResolveScope());
if (psiClass != null) {
final PsiJavaModule otherModule = JavaModuleGraphUtil.findDescriptorByElement(psiClass);
final PsiJavaModule otherModule = JavaPsiModuleUtil.findDescriptorByElement(psiClass);
if (otherModule != null && otherModule != javaModule) {
if (!JavaModuleGraphUtil.reads(javaModule, otherModule)) {
String message = JavaBundle.message("module.not.in.requirements", javaModule.getName(), otherModule.getName());
+1
View File
@@ -88,6 +88,7 @@
<orderEntry type="module" module-name="intellij.platform.bookmarks" />
<orderEntry type="module" module-name="intellij.platform.todo" />
<orderEntry type="module" module-name="intellij.java.codeserver.highlighting" />
<orderEntry type="module" module-name="intellij.java.codeserver.core" />
</component>
<component name="copyright">
<Base>
@@ -3,13 +3,13 @@ package com.intellij.codeInsight;
import com.intellij.codeInsight.annoPackages.AnnotationPackageSupport;
import com.intellij.codeInsight.annoPackages.Jsr305Support;
import com.intellij.codeInsight.daemon.impl.analysis.JavaModuleGraphUtil;
import com.intellij.codeInsight.options.JavaClassValidator;
import com.intellij.codeInspection.dataFlow.HardcodedContracts;
import com.intellij.codeInspection.options.OptionController;
import com.intellij.codeInspection.options.OptionControllerProvider;
import com.intellij.ide.highlighter.JavaFileType;
import com.intellij.java.JavaBundle;
import com.intellij.java.codeserver.core.JavaPsiModuleUtil;
import com.intellij.java.library.JavaLibraryModificationTracker;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.components.PersistentStateComponent;
@@ -413,7 +413,7 @@ public class NullableNotNullManagerImpl extends NullableNotNullManager implement
@Override
protected @Nullable NullabilityAnnotationInfo findNullityDefaultOnModule(PsiAnnotation.@NotNull TargetType @NotNull [] targetTypes,
@NotNull PsiElement element) {
PsiJavaModule module = JavaModuleGraphUtil.findDescriptorByElement(element);
PsiJavaModule module = JavaPsiModuleUtil.findDescriptorByElement(element);
if (module != null) {
return getNullityDefault(module, targetTypes, element, false);
}
@@ -4,10 +4,10 @@ package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.ExpectedTypeInfo;
import com.intellij.codeInsight.ExpectedTypesProvider;
import com.intellij.codeInsight.completion.JavaCompletionUtil.JavaLookupElementHighlighter;
import com.intellij.codeInsight.daemon.impl.analysis.JavaModuleGraphUtil;
import com.intellij.codeInsight.daemon.impl.analysis.JavaModuleGraphUtil.JavaModuleScope;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.java.JavaBundle;
import com.intellij.java.codeserver.core.JavaPsiModuleUtil;
import com.intellij.lang.LangBundle;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.actionSystem.IdeActions;
@@ -196,7 +196,7 @@ public class JavaClassNameCompletionContributor extends CompletionContributor im
if (parameters.getInvocationCount() >= 2) {
return GlobalSearchScope.allScope(project);
}
PsiJavaModule javaModule = JavaModuleGraphUtil.findDescriptorByElement(psiFile.getOriginalElement());
PsiJavaModule javaModule = JavaPsiModuleUtil.findDescriptorByElement(psiFile.getOriginalElement());
JavaModuleScope moduleScope = javaModule == null ? null : JavaModuleScope.moduleScope(javaModule);
if (moduleScope != null) {
return moduleScope;
@@ -11,6 +11,7 @@ import com.intellij.codeInsight.lookup.*;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.icons.AllIcons;
import com.intellij.java.JavaBundle;
import com.intellij.java.codeserver.core.JavaPsiModuleUtil;
import com.intellij.lang.LangBundle;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.lang.jvm.types.JvmPrimitiveTypeKind;
@@ -983,7 +984,7 @@ public final class JavaCompletionContributor extends CompletionContributor imple
List<LookupElement> lookupElements = new SmartList<>();
PsiJavaFile psiJavaFile = ObjectUtils.tryCast(referenceElement.getContainingFile(), PsiJavaFile.class);
if (psiJavaFile == null) return lookupElements;
PsiJavaModule javaModule = JavaModuleGraphUtil.findDescriptorByElement(psiJavaFile.getOriginalElement());
PsiJavaModule javaModule = JavaPsiModuleUtil.findDescriptorByElement(psiJavaFile.getOriginalElement());
if (javaModule == null) {
String packageName = psiJavaFile.getPackageName();
PsiPackage psiPackage = JavaPsiFacade.getInstance(psiJavaFile.getProject()).findPackage(packageName);
@@ -1414,7 +1415,7 @@ public final class JavaCompletionContributor extends CompletionContributor imple
return psiJavaModule.getName();
};
String currentJavaModuleName = getModuleName.apply(PsiTreeUtil.getParentOfType(statement, PsiJavaModule.class));
if (currentJavaModuleName == null) currentJavaModuleName = getModuleName.apply(JavaModuleGraphHelper.getInstance().findDescriptorByElement(originalFile));
if (currentJavaModuleName == null) currentJavaModuleName = getModuleName.apply(JavaPsiModuleUtil.findDescriptorByElement(originalFile));
if (currentJavaModuleName == null) currentJavaModuleName = findModuleName(originalFile, position);
if (currentJavaModuleName != null) {
@@ -11,6 +11,7 @@ import com.intellij.codeInsight.daemon.impl.analysis.JavaModuleGraphUtil;
import com.intellij.codeInsight.editorActions.TabOutScopesTracker;
import com.intellij.codeInsight.guess.GuessManager;
import com.intellij.codeInsight.lookup.*;
import com.intellij.java.codeserver.core.JavaPsiModuleUtil;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.diagnostic.Logger;
@@ -521,7 +522,7 @@ public final class JavaCompletionUtil {
final PsiJavaModule currentModule =
ReadAction.compute(() -> JavaModuleGraphUtil.findDescriptorByFile(myOriginalFile, myPlace.getProject()));
if (currentModule != null) {
final PsiJavaModule targetModule = ReadAction.compute(() -> JavaModuleGraphUtil.findDescriptorByElement(psiClass));
final PsiJavaModule targetModule = ReadAction.compute(() -> JavaPsiModuleUtil.findDescriptorByElement(psiClass));
if (targetModule != null && targetModule != currentModule &&
!JavaModuleGraphUtil.reads(currentModule, targetModule)) {
LookupElementDecorator<LookupElement> element = generator.apply(presentation -> presentation.setItemTextForeground(JBColor.RED));
@@ -1,9 +1,9 @@
// 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.codeInsight.intention.impl;
import com.intellij.codeInsight.daemon.impl.analysis.JavaModuleGraphUtil;
import com.intellij.codeInspection.util.IntentionFamilyName;
import com.intellij.java.JavaBundle;
import com.intellij.java.codeserver.core.JavaPsiModuleUtil;
import com.intellij.modcommand.ActionContext;
import com.intellij.modcommand.ModCommand;
import com.intellij.modcommand.Presentation;
@@ -53,7 +53,7 @@ public class FillPermitsListFix extends PsiBasedModCommandAction<PsiIdentifier>
@NotNull PsiClass psiClass,
@NotNull Set<PsiClass> permittedClasses) {
Collection<String> missingInheritors = new SmartList<>();
PsiJavaModule module = JavaModuleGraphUtil.findDescriptorByElement(psiClass);
PsiJavaModule module = JavaPsiModuleUtil.findDescriptorByElement(psiClass);
for (PsiClass inheritor : DirectClassInheritorsSearch.search(psiClass).asIterable()) {
String errorTitle = SealedUtils.checkInheritor(psiJavaFile, module, inheritor);
if (errorTitle != null) {
@@ -1,8 +1,8 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.intention.impl;
import com.intellij.codeInsight.daemon.impl.analysis.JavaModuleGraphUtil;
import com.intellij.java.JavaBundle;
import com.intellij.java.codeserver.core.JavaPsiModuleUtil;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.modcommand.ActionContext;
import com.intellij.modcommand.ModPsiUpdater;
@@ -70,7 +70,7 @@ public final class SealClassAction extends PsiUpdateModCommandAction<PsiClass> {
}
}
PsiJavaModule module = JavaModuleGraphUtil.findDescriptorByElement(psiClass);
PsiJavaModule module = JavaPsiModuleUtil.findDescriptorByElement(psiClass);
List<PsiClass> inheritors = new ArrayList<>();
Ref<String> message = new Ref<>();
@@ -1,7 +1,7 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInspection.jigsaw;
import com.intellij.codeInsight.daemon.impl.analysis.JavaModuleGraphUtil;
import com.intellij.java.codeserver.core.JavaPsiModuleUtil;
import com.intellij.lang.jvm.JvmMethod;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
@@ -62,7 +62,7 @@ public final class JigsawUtil {
for (JvmMethod method : methods) {
if (!method.hasParameters()) return false;
}
PsiJavaModule descriptor = JavaModuleGraphUtil.findDescriptorByElement(targetClass.getContainingFile().getOriginalFile());
PsiJavaModule descriptor = JavaPsiModuleUtil.findDescriptorByElement(targetClass.getContainingFile().getOriginalFile());
if (descriptor == null || descriptor instanceof LightJavaModule) return false;
Iterable<PsiProvidesStatement> providers = descriptor.getProvides();
@@ -1,7 +1,6 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.ide.actions;
import com.intellij.codeInsight.daemon.impl.analysis.JavaModuleGraphUtil;
import com.intellij.icons.AllIcons;
import com.intellij.ide.IdeView;
import com.intellij.ide.fileTemplates.FileTemplate;
@@ -9,6 +8,7 @@ import com.intellij.ide.fileTemplates.FileTemplateManager;
import com.intellij.ide.fileTemplates.actions.AttributesDefaults;
import com.intellij.ide.fileTemplates.actions.CreateFromTemplateActionBase;
import com.intellij.java.JavaBundle;
import com.intellij.java.codeserver.core.JavaPsiModuleUtil;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
@@ -16,9 +16,7 @@ import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.java.JavaFeature;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiNameHelper;
import com.intellij.psi.*;
import com.intellij.psi.impl.light.LightJavaModule;
import com.intellij.psi.util.PsiUtil;
import org.jetbrains.annotations.NotNull;
@@ -54,7 +52,7 @@ public class CreateModuleInfoAction extends CreateFromTemplateActionBase {
}
else {
e.getPresentation().setVisible(true);
e.getPresentation().setEnabled(JavaModuleGraphUtil.findDescriptorByElement(target) == null);
e.getPresentation().setEnabled(JavaPsiModuleUtil.findDescriptorByElement(target) == null);
}
}
@@ -16,6 +16,7 @@ import com.intellij.execution.process.CapturingProcessRunner
import com.intellij.execution.process.OSProcessHandler
import com.intellij.execution.process.ProcessNotCreatedException
import com.intellij.java.JavaBundle
import com.intellij.java.codeserver.core.JavaPsiModuleUtil.findDescriptorByElement
import com.intellij.modcommand.ActionContext
import com.intellij.modcommand.ModCommand
import com.intellij.modcommand.ModCommandAction
@@ -140,7 +141,7 @@ internal class JavaPlatformModuleSystem : JavaModuleSystemEx {
isAccessible: (ModuleAccessInfo) -> Boolean,
): ErrorWithFixes? {
val useFile = place.containingFile?.originalFile ?: return null
val useModule = JavaModuleGraphUtil.findDescriptorByElement(useFile).let { if (it is LightJavaModule) null else it }
val useModule = findDescriptorByElement(useFile).let { if (it is LightJavaModule) null else it }
val current = CurrentModuleInfo(useModule, place)
val targetModule = target.module
@@ -205,7 +206,7 @@ internal class JavaPlatformModuleSystem : JavaModuleSystemEx {
private fun checkAccess(target: TargetModuleInfo, place: PsiFileSystemItem, quick: Boolean,
isAccessible: (ModuleAccessInfo) -> Boolean): ErrorWithFixes? {
val useModule = JavaModuleGraphUtil.findDescriptorByElement(place).let { if (it is LightJavaModule) null else it }
val useModule = findDescriptorByElement(place).let { if (it is LightJavaModule) null else it }
val current = CurrentModuleInfo(useModule, place)
val targetModule = target.module
@@ -480,7 +481,7 @@ internal class JavaPlatformModuleSystem : JavaModuleSystemEx {
ModuleUtilCore.findModuleForPsiElement(element)
}
override val module: PsiJavaModule? by lazy {
JavaModuleGraphUtil.findDescriptorByElement(element)
findDescriptorByElement(element)
}
}
@@ -2,6 +2,7 @@
package com.intellij.psi.util.proximity;
import com.intellij.codeInsight.daemon.impl.analysis.JavaModuleGraphUtil;
import com.intellij.java.codeserver.core.JavaPsiModuleUtil;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.util.NotNullLazyKey;
@@ -120,7 +121,7 @@ public final class ExplicitlyImportedWeigher extends ProximityWeigher {
List<PsiJavaModule> importedModules = PLACE_IMPORTED_MODULES.getValue(location);
if (importedModules != null && !importedModules.isEmpty()) {
PsiJavaModule suggestedModule = JavaModuleGraphHelper.getInstance().findDescriptorByElement(element);
PsiJavaModule suggestedModule = JavaPsiModuleUtil.findDescriptorByElement(element);
if (suggestedModule != null && importedModules.contains(suggestedModule)) return ImportWeight.MODULE_IMPORTED;
}
@@ -18,5 +18,6 @@
<orderEntry type="module" module-name="intellij.java.indexing" exported="" />
<orderEntry type="library" name="kotlin-stdlib" level="project" />
<orderEntry type="library" name="fastutil-min" level="project" />
<orderEntry type="module" module-name="intellij.java.codeserver.core" />
</component>
</module>
@@ -4,8 +4,11 @@ package com.intellij.psi.impl.java.stubs.index;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.PsiJavaModule;
import com.intellij.psi.search.DelegatingGlobalSearchScope;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.JavaMultiReleaseUtil;
import org.jetbrains.annotations.NotNull;
class JavaAutoModuleFilterScope extends DelegatingGlobalSearchScope {
@@ -34,7 +37,7 @@ class JavaAutoModuleFilterScope extends DelegatingGlobalSearchScope {
return false;
}
}
if (JavaModuleNameIndex.descriptorFile(root) != null) {
if (JavaMultiReleaseUtil.findVersionSpecificFile(root, PsiJavaModule.MODULE_INFO_CLS_FILE, LanguageLevel.HIGHEST) != null) {
return false;
}
@@ -3,7 +3,6 @@ package com.intellij.psi.impl.java.stubs.index;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiJavaModule;
import com.intellij.psi.impl.search.JavaSourceFilterScope;
@@ -11,21 +10,11 @@ import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.stubs.StringStubIndexExtension;
import com.intellij.psi.stubs.StubIndex;
import com.intellij.psi.stubs.StubIndexKey;
import com.intellij.psi.util.CachedValue;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.util.CachedValueImpl;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.stream.Stream;
public final class JavaModuleNameIndex extends StringStubIndexExtension<PsiJavaModule> {
private static final JavaModuleNameIndex ourInstance = new JavaModuleNameIndex();
@@ -68,7 +57,7 @@ public final class JavaModuleNameIndex extends StringStubIndexExtension<PsiJavaM
for (PsiJavaModule module : modules) {
VirtualFile root = index.getClassRootForFile(module.getContainingFile().getVirtualFile());
if (root != null) {
List<VirtualFile> files = descriptorFiles(root, false, false);
List<VirtualFile> files = descriptorFiles(root);
VirtualFile main = ContainerUtil.getFirstItem(files);
if (main != null && !(root.equals(main.getParent()) || version(main.getParent()) >= 9)) {
filter.add(main);
@@ -91,25 +80,14 @@ public final class JavaModuleNameIndex extends StringStubIndexExtension<PsiJavaM
return true;
}
public static @Nullable VirtualFile descriptorFile(@NotNull VirtualFile root) {
VirtualFile result = root.findChild(PsiJavaModule.MODULE_INFO_CLS_FILE);
if (result == null) {
result = ContainerUtil.getFirstItem(descriptorFiles(root, true, true));
}
return result;
}
private static List<VirtualFile> descriptorFiles(VirtualFile root, boolean checkAttribute, boolean filter) {
private static List<VirtualFile> descriptorFiles(VirtualFile root) {
List<VirtualFile> results = new SmartList<>();
ContainerUtil.addIfNotNull(results, root.findChild(PsiJavaModule.MODULE_INFO_CLS_FILE));
VirtualFile versionsDir = root.findFileByRelativePath("META-INF/versions");
if (versionsDir != null && (!checkAttribute || isMultiReleaseJar(root))) {
if (versionsDir != null) {
VirtualFile[] versions = versionsDir.getChildren();
if (filter) {
versions = Stream.of(versions).filter(d -> version(d) >= 9).toArray(VirtualFile[]::new);
}
Arrays.sort(versions, JavaModuleNameIndex::compareVersions);
for (VirtualFile version : versions) {
ContainerUtil.addIfNotNull(results, version.findChild(PsiJavaModule.MODULE_INFO_CLS_FILE));
@@ -119,26 +97,6 @@ public final class JavaModuleNameIndex extends StringStubIndexExtension<PsiJavaM
return results;
}
private static final Key<CachedValue<Boolean>> MULTI_RELEASE_KEY = Key.create("jar.multi.release.key");
private static boolean isMultiReleaseJar(VirtualFile root) {
VirtualFile manifest = root.findFileByRelativePath(JarFile.MANIFEST_NAME);
if (manifest == null) return false;
CachedValue<Boolean> value = manifest.getUserData(MULTI_RELEASE_KEY);
if (value == null) {
manifest.putUserData(MULTI_RELEASE_KEY, value = new CachedValueImpl<>(() -> {
Boolean result = Boolean.FALSE;
try (InputStream stream = manifest.getInputStream()) {
result = Boolean.valueOf(new Manifest(stream).getMainAttributes().getValue(Attributes.Name.MULTI_RELEASE));
}
catch (IOException ignored) { }
return CachedValueProvider.Result.create(result, manifest);
}));
}
return value.getValue();
}
private static int version(VirtualFile dir) {
try {
return Integer.parseInt(dir.getName());
@@ -23,7 +23,7 @@ public final class JavaMultiReleaseUtil {
* Minimal JDK version which supports multi-release Jars
*/
public static final LanguageLevel MIN_MULTI_RELEASE_VERSION = LanguageLevel.JDK_1_9;
private static class VersionRootInfo {
final @NotNull LanguageLevel level;
final @NotNull VirtualFile versionRoot;
@@ -98,17 +98,39 @@ public final class JavaMultiReleaseUtil {
* @param file file that represents a non-version-specific file from an MR-JAR
* @param level desired language level
* @return a version of the file, which should be loaded on the specified language level. Returns
* input file if there's no more-specific version of the file, or the input file is not located inside MR-JAR.
* the input file if there's no more-specific version of the file, or the input file is not located inside MR-JAR.
*/
public static @NotNull VirtualFile findVersionSpecificFile(@NotNull VirtualFile file, @NotNull LanguageLevel level) {
VirtualFile root = VfsUtilCore.getRootFile(file);
if (!(root.getFileType() instanceof ArchiveFileType)) return file;
String relativePath = VfsUtilCore.getRelativePath(file, root);
if (relativePath == null) return file;
return findFileImpl(file, level, root, relativePath);
}
/**
* @param root content root
* @param relativePath path to the file relative to content root
* @param level desired language level
* @return a version of the file, which should be loaded on the specified language level. Returns null if the file is not found.
*/
public static @Nullable VirtualFile findVersionSpecificFile(@NotNull VirtualFile root,
@NotNull String relativePath,
@NotNull LanguageLevel level) {
VirtualFile file = root.findFileByRelativePath(relativePath);
if (!(root.getFileType() instanceof ArchiveFileType)) return file;
return findFileImpl(file, level, root, relativePath);
}
@Contract("!null, _, _, _ -> !null")
private static @Nullable VirtualFile findFileImpl(@Nullable VirtualFile defaultFile,
@NotNull LanguageLevel level,
@NotNull VirtualFile root,
@NotNull String relativePath) {
VirtualFile metaInf = root.findChild("META-INF");
if (metaInf == null) return file;
if (metaInf == null) return defaultFile;
VirtualFile versions = metaInf.findChild("versions");
if (versions == null) return file;
if (versions == null) return defaultFile;
int feature = level.feature();
int minFeature = MIN_MULTI_RELEASE_VERSION.feature();
while (feature >= minFeature) {
@@ -121,7 +143,7 @@ public final class JavaMultiReleaseUtil {
}
feature--;
}
return file;
return defaultFile;
}
/**
+1
View File
@@ -37,6 +37,7 @@
- name: intellij.platform.uast
- name: intellij.platform.uast.ide
- name: intellij.java.uast.ide
- name: intellij.java.codeserver.core
- name: intellij.java.codeserver.highlighting
- name: intellij.java.compiler.impl
- name: intellij.java.debugger.impl
@@ -58,6 +58,7 @@ object JavaPluginLayout {
}
spec.withModules(listOf(
"intellij.java.codeserver.core",
"intellij.java.codeserver.highlighting",
"intellij.java.compiler.impl",
"intellij.java.debugger.impl",