diff --git a/java/java-impl/src/com/intellij/openapi/roots/impl/ModulePackageIndexImpl.java b/java/java-impl/src/com/intellij/openapi/roots/impl/ModulePackageIndexImpl.java index 58fdec099d55..7537971e0931 100644 --- a/java/java-impl/src/com/intellij/openapi/roots/impl/ModulePackageIndexImpl.java +++ b/java/java-impl/src/com/intellij/openapi/roots/impl/ModulePackageIndexImpl.java @@ -41,8 +41,16 @@ public final class ModulePackageIndexImpl extends ModulePackageIndex { return new FilteredQuery<>(myDirectoryIndex.getFilesByPackageName(packageName), myDirCondition); } + @Override + public @Nullable String getPackageName(@NotNull VirtualFile fileOrDir) { + return myDirectoryIndex.getPackageName(fileOrDir); + } + @Override public @Nullable String getPackageNameByDirectory(@NotNull VirtualFile dir) { + if (!dir.isDirectory()) { + LOG.error(dir.getPresentableUrl() + " is not a directory"); + } return myDirectoryIndex.getPackageName(dir); } } diff --git a/java/java-impl/src/com/intellij/packageDependencies/ui/PackagePatternProvider.java b/java/java-impl/src/com/intellij/packageDependencies/ui/PackagePatternProvider.java index 169b2d5920fe..895592781dab 100644 --- a/java/java-impl/src/com/intellij/packageDependencies/ui/PackagePatternProvider.java +++ b/java/java-impl/src/com/intellij/packageDependencies/ui/PackagePatternProvider.java @@ -77,8 +77,7 @@ public final class PackagePatternProvider extends PatternDialectProvider { if (element instanceof PsiClassOwner javaFile) { final VirtualFile virtualFile = javaFile.getVirtualFile(); LOG.assertTrue(virtualFile != null); - final String packageName = - PackageIndex.getInstance(element.getProject()).getPackageNameByDirectory(virtualFile.getParent()); + final String packageName = PackageIndex.getInstance(element.getProject()).getPackageName(virtualFile); final String name = virtualFile.getNameWithoutExtension(); if (!PsiNameHelper.getInstance(element.getProject()).isIdentifier(name)) return null; qName = StringUtil.getQualifiedName(packageName, name); diff --git a/java/java-impl/src/com/intellij/packageDependencies/ui/TreeModelBuilder.java b/java/java-impl/src/com/intellij/packageDependencies/ui/TreeModelBuilder.java index f86601a80c4d..c757b185fe66 100644 --- a/java/java-impl/src/com/intellij/packageDependencies/ui/TreeModelBuilder.java +++ b/java/java-impl/src/com/intellij/packageDependencies/ui/TreeModelBuilder.java @@ -279,10 +279,8 @@ public class TreeModelBuilder { public @Nullable PackageDependenciesNode getFileParentNode(VirtualFile vFile) { LOG.assertTrue(vFile != null); - final VirtualFile containingDirectory = vFile.getParent(); - LOG.assertTrue(containingDirectory != null); PsiPackage aPackage = null; - final String packageName = PackageIndex.getInstance(myProject).getPackageNameByDirectory(containingDirectory); + final String packageName = PackageIndex.getInstance(myProject).getPackageName(vFile); if (packageName != null) { aPackage = myJavaPsiFacade.findPackage(packageName); } diff --git a/java/java-impl/src/com/intellij/psi/search/scope/packageSet/PatternPackageSet.java b/java/java-impl/src/com/intellij/psi/search/scope/packageSet/PatternPackageSet.java index 99d1815dd56d..4f8d448a71d2 100644 --- a/java/java-impl/src/com/intellij/psi/search/scope/packageSet/PatternPackageSet.java +++ b/java/java-impl/src/com/intellij/psi/search/scope/packageSet/PatternPackageSet.java @@ -77,9 +77,8 @@ public class PatternPackageSet extends PatternBasedPackageSet { } private static String getPackageName(@NotNull VirtualFile file, @NotNull Project project) { - VirtualFile dir = file.isDirectory() ? file : file.getParent(); - if (dir == null) return null; - return StringUtil.getQualifiedName(PackageIndex.getInstance(project).getPackageNameByDirectory(dir), file.getNameWithoutExtension()); + String name = PackageIndex.getInstance(project).getPackageName(file); + return name == null ? null : StringUtil.getQualifiedName(name, file.getNameWithoutExtension()); } @Override diff --git a/java/java-indexing-impl/src/com/intellij/openapi/roots/impl/ProjectPackageIndexImpl.java b/java/java-indexing-impl/src/com/intellij/openapi/roots/impl/ProjectPackageIndexImpl.java index de80e2cb66ca..7cd06b258b8d 100644 --- a/java/java-indexing-impl/src/com/intellij/openapi/roots/impl/ProjectPackageIndexImpl.java +++ b/java/java-indexing-impl/src/com/intellij/openapi/roots/impl/ProjectPackageIndexImpl.java @@ -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.openapi.roots.impl; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.PackageIndex; import com.intellij.openapi.util.NlsSafe; @@ -13,6 +14,8 @@ import org.jetbrains.annotations.Nullable; @ApiStatus.Internal public final class ProjectPackageIndexImpl extends PackageIndex { + private static final Logger LOG = Logger.getInstance(ProjectPackageIndexImpl.class); + private final DirectoryIndex myDirectoryIndex; @ApiStatus.Internal @@ -36,8 +39,16 @@ public final class ProjectPackageIndexImpl extends PackageIndex { return myDirectoryIndex.getDirectoriesByPackageName(packageName, includeLibrarySources); } + @Override + public @Nullable String getPackageName(@NotNull VirtualFile fileOrDir) { + return myDirectoryIndex.getPackageName(fileOrDir); + } + @Override public @Nullable String getPackageNameByDirectory(@NotNull VirtualFile dir) { + if (!dir.isDirectory()) { + LOG.error(dir.getPresentableUrl() + " is not a directory"); + } return myDirectoryIndex.getPackageName(dir); } } diff --git a/java/java-psi-api/src/com/intellij/openapi/roots/PackageIndex.java b/java/java-psi-api/src/com/intellij/openapi/roots/PackageIndex.java index ebd758abe97f..9e3579cd883d 100644 --- a/java/java-psi-api/src/com/intellij/openapi/roots/PackageIndex.java +++ b/java/java-psi-api/src/com/intellij/openapi/roots/PackageIndex.java @@ -68,10 +68,24 @@ public abstract class PackageIndex { public abstract @NotNull Query getDirsByPackageName(@NotNull @NlsSafe String packageName, boolean includeLibrarySources); /** - * Returns the name of the package corresponding to the specified directory or a specific file if the file is a single-file root. + * Returns the name of the package corresponding to the specified directory or a specific file, including the files + * that are single file source roots. * - * @return the package name, or null if the supplied directory does not correspond to any package, - * or the supplied file is not a single-file root. + * @return the package name, or null if the supplied directory or file does not correspond to any package. + */ + public @Nullable String getPackageName(@NotNull VirtualFile fileOrDir) { + if (fileOrDir.isDirectory()) { + return getPackageNameByDirectory(fileOrDir); + } + VirtualFile parent = fileOrDir.getParent(); + return parent == null || !parent.isDirectory() ? null : getPackageNameByDirectory(parent); + } + + /** + * Returns the name of the package corresponding to the specified directory. + * Prefer using {@link #getPackageName(VirtualFile)} if single-file source roots are possible. + * + * @return the package name, or null if the supplied directory does not correspond to any package. */ public abstract @Nullable String getPackageNameByDirectory(@NotNull VirtualFile dir); } diff --git a/java/java-tests/testSrc/com/intellij/java/psi/resolve/SingleFileRootResolveTest.java b/java/java-tests/testSrc/com/intellij/java/psi/resolve/SingleFileRootResolveTest.java index a7315a0a49d0..539ca985a6f5 100644 --- a/java/java-tests/testSrc/com/intellij/java/psi/resolve/SingleFileRootResolveTest.java +++ b/java/java-tests/testSrc/com/intellij/java/psi/resolve/SingleFileRootResolveTest.java @@ -71,7 +71,7 @@ public final class SingleFileRootResolveTest extends LightJavaCodeInsightFixture PsiClass aClass = JavaPsiFacade.getInstance(getProject()).findClass("com.example.A", GlobalSearchScope.projectScope(getProject())); assertNotNull(aClass); // Works for single-file roots as well - String pkg = PackageIndex.getInstance(getProject()).getPackageNameByDirectory(aClass.getContainingFile().getVirtualFile()); + String pkg = PackageIndex.getInstance(getProject()).getPackageName(aClass.getContainingFile().getVirtualFile()); assertEquals("com.example", pkg); } diff --git a/platform/platform-impl/src/com/intellij/ide/lightEdit/project/LightEditDirectoryIndex.java b/platform/platform-impl/src/com/intellij/ide/lightEdit/project/LightEditDirectoryIndex.java index 43df0c00c880..5cd23e2380e9 100644 --- a/platform/platform-impl/src/com/intellij/ide/lightEdit/project/LightEditDirectoryIndex.java +++ b/platform/platform-impl/src/com/intellij/ide/lightEdit/project/LightEditDirectoryIndex.java @@ -21,7 +21,7 @@ final class LightEditDirectoryIndex extends DirectoryIndex { } @Override - public @Nullable String getPackageName(@NotNull VirtualFile dir) { + public @Nullable String getPackageName(@NotNull VirtualFile fileOrDir) { return null; } diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndex.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndex.java index 7edf80b5213c..2c938f188cb0 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndex.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndex.java @@ -45,7 +45,7 @@ public abstract class DirectoryIndex { return getDirectoriesByPackageName(packageName, true).filtering(scope::contains); } - public abstract @Nullable String getPackageName(@NotNull VirtualFile dir); + public abstract @Nullable String getPackageName(@NotNull VirtualFile fileOrDir); public abstract @NotNull List getOrderEntries(@NotNull VirtualFile fileOrDir); diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexImpl.java index 01136d137f8a..139a26645f12 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexImpl.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexImpl.java @@ -122,9 +122,9 @@ public final class DirectoryIndexImpl extends DirectoryIndex implements Disposab } @Override - public String getPackageName(@NotNull VirtualFile dir) { + public String getPackageName(@NotNull VirtualFile fileOrDir) { checkAvailability(); - return myWorkspaceFileIndex.getPackageName(dir); + return myWorkspaceFileIndex.getPackageName(fileOrDir); } @Override diff --git a/platform/projectModel-impl/src/com/intellij/workspaceModel/core/fileIndex/impl/EmptyWorkspaceFileIndexData.kt b/platform/projectModel-impl/src/com/intellij/workspaceModel/core/fileIndex/impl/EmptyWorkspaceFileIndexData.kt index 25bf0c7cf3c6..a8719d0eaa4a 100644 --- a/platform/projectModel-impl/src/com/intellij/workspaceModel/core/fileIndex/impl/EmptyWorkspaceFileIndexData.kt +++ b/platform/projectModel-impl/src/com/intellij/workspaceModel/core/fileIndex/impl/EmptyWorkspaceFileIndexData.kt @@ -35,7 +35,7 @@ class EmptyWorkspaceFileIndexData private constructor(private val debugName: Str override fun markDirty(entityPointers: Collection>, filesToInvalidate: Collection) {} override fun onEntitiesChanged(event: VersionedStorageChange, storageKind: EntityStorageKind) {} override fun updateDirtyEntities() {} - override fun getPackageName(dir: VirtualFile): String? = null + override fun getPackageName(dirOrFile: VirtualFile): String? = null override fun getDirectoriesByPackageName(packageName: String, includeLibrarySources: Boolean): Query = EmptyQuery.getEmptyQuery() override fun getFilesByPackageName(packageName: String): Query = EmptyQuery.getEmptyQuery() override fun resetCustomContributors() {} diff --git a/platform/projectModel-impl/src/com/intellij/workspaceModel/core/fileIndex/impl/WorkspaceFileIndexData.kt b/platform/projectModel-impl/src/com/intellij/workspaceModel/core/fileIndex/impl/WorkspaceFileIndexData.kt index 6b5aa11b978e..1d95d68ad1fb 100644 --- a/platform/projectModel-impl/src/com/intellij/workspaceModel/core/fileIndex/impl/WorkspaceFileIndexData.kt +++ b/platform/projectModel-impl/src/com/intellij/workspaceModel/core/fileIndex/impl/WorkspaceFileIndexData.kt @@ -50,10 +50,10 @@ interface WorkspaceFileIndexData { fun analyzeVfsChanges(events: List): VfsChangeApplier? /** - * Returns package name for [directory] if it's located under source root or classes root of Java library, or `null` otherwise. + * Returns package name for [dirOrFile] if it's located under source root or classes root of Java library, or `null` otherwise. * This is an internal function, plugins must use [com.intellij.openapi.roots.PackageIndex.getPackageNameByDirectory] instead. */ - fun getPackageName(dir: VirtualFile): String? + fun getPackageName(dirOrFile: VirtualFile): String? /** * Returns a query producing directories which correspond to [packageName]. diff --git a/platform/projectModel-impl/src/com/intellij/workspaceModel/core/fileIndex/impl/WorkspaceFileIndexDataImpl.kt b/platform/projectModel-impl/src/com/intellij/workspaceModel/core/fileIndex/impl/WorkspaceFileIndexDataImpl.kt index 227b2e8a1bbe..94f81dd9f736 100644 --- a/platform/projectModel-impl/src/com/intellij/workspaceModel/core/fileIndex/impl/WorkspaceFileIndexDataImpl.kt +++ b/platform/projectModel-impl/src/com/intellij/workspaceModel/core/fileIndex/impl/WorkspaceFileIndexDataImpl.kt @@ -380,14 +380,17 @@ internal class WorkspaceFileIndexDataImpl( return root } - override fun getPackageName(dir: VirtualFile): String? = WorkspaceFileIndexDataMetrics.getPackageNameTimeNanosec.addMeasuredTime { - val fileSet = when (val info = getFileInfo(dir, true, true, true, true, true, true)) { + override fun getPackageName(dirOrFile: VirtualFile): String? = WorkspaceFileIndexDataMetrics.getPackageNameTimeNanosec.addMeasuredTime { + val fileSet = when (val info = getFileInfo(dirOrFile, true, true, true, true, true, true)) { is WorkspaceFileSetWithCustomData<*> -> info.takeIf { it.data is JvmPackageRootDataInternal } is MultipleWorkspaceFileSets -> info.find(JvmPackageRootDataInternal::class.java) else -> null } ?: return@addMeasuredTime null val packagePrefix = (fileSet.data as JvmPackageRootDataInternal).packagePrefix + if (!fileSet.root.isDirectory) return@addMeasuredTime packagePrefix + val dir = if (dirOrFile.isDirectory) dirOrFile else dirOrFile.parent + if (!dir.isDirectory) return@addMeasuredTime null val packageName = VfsUtilCore.getRelativePath(dir, correctRoot(fileSet.root, dir), '.') ?: error("${dir.presentableUrl} is not under ${fileSet.root.presentableUrl}") return@addMeasuredTime when { diff --git a/platform/projectModel-impl/src/com/intellij/workspaceModel/core/fileIndex/impl/WorkspaceFileIndexEx.kt b/platform/projectModel-impl/src/com/intellij/workspaceModel/core/fileIndex/impl/WorkspaceFileIndexEx.kt index dadb906e209c..a7325ce97e82 100644 --- a/platform/projectModel-impl/src/com/intellij/workspaceModel/core/fileIndex/impl/WorkspaceFileIndexEx.kt +++ b/platform/projectModel-impl/src/com/intellij/workspaceModel/core/fileIndex/impl/WorkspaceFileIndexEx.kt @@ -81,10 +81,11 @@ interface WorkspaceFileIndexEx : WorkspaceFileIndex { fileSetFilter: (WorkspaceFileSetWithCustomData<*>) -> Boolean): Boolean /** - * Returns package name for [directory] if it's located under source root or classes root of Java library, or `null` otherwise. + * Returns package name for [fileOrDir] if it's a single file source root, or a directory located under source root or + * classes root of a Java library. Returns `null` otherwise. * This is an internal function, plugins must use [com.intellij.openapi.roots.PackageIndex.getPackageNameByDirectory] instead. */ - fun getPackageName(directory: VirtualFile): String? + fun getPackageName(fileOrDir: VirtualFile): String? /** * Returns a query producing directories which correspond to [packageName]. diff --git a/platform/projectModel-impl/src/com/intellij/workspaceModel/core/fileIndex/impl/WorkspaceFileIndexImpl.kt b/platform/projectModel-impl/src/com/intellij/workspaceModel/core/fileIndex/impl/WorkspaceFileIndexImpl.kt index 67c5e957c779..76b9e5bc0ec7 100644 --- a/platform/projectModel-impl/src/com/intellij/workspaceModel/core/fileIndex/impl/WorkspaceFileIndexImpl.kt +++ b/platform/projectModel-impl/src/com/intellij/workspaceModel/core/fileIndex/impl/WorkspaceFileIndexImpl.kt @@ -370,8 +370,8 @@ class WorkspaceFileIndexImpl(private val project: Project) : WorkspaceFileIndexE getMainIndexData().visitFileSets(visitor) } - override fun getPackageName(directory: VirtualFile): String? { - return getMainIndexData().getPackageName(directory) + override fun getPackageName(fileOrDir: VirtualFile): String? { + return getMainIndexData().getPackageName(fileOrDir) } override fun getDirectoriesByPackageName(packageName: String, includeLibrarySources: Boolean): Query { diff --git a/plugins/search-everywhere-ml/ranking/java/src/com/intellij/searchEverywhereMl/ranking/java/features/SearchEverywhereJavaPsiElementFeatureProvider.kt b/plugins/search-everywhere-ml/ranking/java/src/com/intellij/searchEverywhereMl/ranking/java/features/SearchEverywhereJavaPsiElementFeatureProvider.kt index 9d3de80e43f7..faf37f9ce1d2 100644 --- a/plugins/search-everywhere-ml/ranking/java/src/com/intellij/searchEverywhereMl/ranking/java/features/SearchEverywhereJavaPsiElementFeatureProvider.kt +++ b/plugins/search-everywhere-ml/ranking/java/src/com/intellij/searchEverywhereMl/ranking/java/features/SearchEverywhereJavaPsiElementFeatureProvider.kt @@ -61,11 +61,8 @@ internal class SearchEverywhereJavaPsiElementFeatureProvider : SearchEverywhereE val packageIndex = PackageIndex.getInstance(project) // Parents of some files may still not be directories - val openedFileDirectory = openedFile.parent?.takeIf { it.isDirectory } - val foundFileDirectory = if (file.isDirectory) file else file.parent?.takeIf { it.isDirectory } - - val openedFilePackageName = openedFileDirectory?.let { packageIndex.getPackageNameByDirectory(it) } - val foundFilePackageName = foundFileDirectory?.let { packageIndex.getPackageNameByDirectory(it) } + val openedFilePackageName = packageIndex.getPackageName(openedFile) + val foundFilePackageName = packageIndex.getPackageName(file) Pair(openedFilePackageName, foundFilePackageName) }.run {