find virtual file for relative path under content roots

Answered

Given a relative path, eg foo/bar.java, is it possible to search each content root in the project for that relative path and thus arrive at a VirtualFile? This will be a complete path under a content entry, so FileNameIndex etc I don't think is useful here, as that's for searching by name.

I can iterate the content roots of course, but I imagined there must be some utility method already written for this.

cheers, jamie

5 comments
Comment actions Permalink

I extracted the code I use in my plugin to find files.

It compiles but you will need to debug it for specific conditions like fileType not found or invalid parameters:

public class PsiUtils {
    public static List<VirtualFile> findFileByRelativePath(@NotNull Project project, @NotNull String fileRelativePath) {
       String relativePath = fileRelativePath.startsWith("/") ? fileRelativePath : "/" + fileRelativePath;
       Set<FileType> fileTypes = Collections.singleton(FileTypeManager.getInstance().getFileTypeByFileName(relativePath));
       final List<VirtualFile> fileList = new ArrayList<>();
       FileBasedIndex.getInstance().processFilesContainingAllKeys(FileTypeIndex.NAME, fileTypes, GlobalSearchScope.projectScope(project), null, virtualFile -> {
          if (virtualFile.getPath().endsWith(relativePath)) {
             fileList.add(virtualFile);
          }
          return true;
       });
       return fileList;
    }
}
 
1
Comment actions Permalink

Thanks Vladimir... I iterated the content entries for each module, which works ok.

Your way may well be better... I'll bear it in mind.

Thanks again.

0
Comment actions Permalink

I think u need use java.io.File.separator than "/" for support other platforms like Mac OS.

0
Comment actions Permalink

VirtualFile uses '/' as the separator:

from VirtualFile.java:131-141:

 /**
* Gets the path of this file. Path is a string which uniquely identifies file within given
* <code>{@link VirtualFileSystem}</code>. Format of the path depends on the concrete file system.
* For <code>{@link com.intellij.openapi.vfs.LocalFileSystem}</code> it is an absolute file path with file separator characters
* (File.separatorChar) replaced to the forward slash ('/').
*
* @return the path
*/
@SuppressWarnings("JavadocReference")
@NotNull
public abstract String getPath();

 

 

0
Comment actions Permalink

Just chiming in to say this was super useful. Thanks Vladimir!

0

Please sign in to leave a comment.