[java] PackageIndex: a separate method for getPackageName not only by directory but also by file (IDEA-368975)

GitOrigin-RevId: b1d18ecde7b5d9759e3edd196d3b7baf0d49da00
This commit is contained in:
Tagir Valeev
2025-05-19 15:56:41 +00:00
committed by intellij-monorepo-bot
parent 0af7361c24
commit 1d9df9dd02
16 changed files with 60 additions and 30 deletions
@@ -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);
}
}
@@ -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);
@@ -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);
}
@@ -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
@@ -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);
}
}
@@ -68,10 +68,24 @@ public abstract class PackageIndex {
public abstract @NotNull Query<VirtualFile> 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);
}
@@ -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);
}
@@ -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;
}
@@ -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<OrderEntry> getOrderEntries(@NotNull VirtualFile fileOrDir);
@@ -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
@@ -35,7 +35,7 @@ class EmptyWorkspaceFileIndexData private constructor(private val debugName: Str
override fun markDirty(entityPointers: Collection<EntityPointer<WorkspaceEntity>>, filesToInvalidate: Collection<VirtualFile>) {}
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<VirtualFile> = EmptyQuery.getEmptyQuery()
override fun getFilesByPackageName(packageName: String): Query<VirtualFile> = EmptyQuery.getEmptyQuery()
override fun resetCustomContributors() {}
@@ -50,10 +50,10 @@ interface WorkspaceFileIndexData {
fun analyzeVfsChanges(events: List<VFileEvent>): 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].
@@ -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 {
@@ -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].
@@ -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<VirtualFile> {
@@ -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 {