how to get module?
Hi,
How can I get the module which corresponds to a VirtualFile. For example if there is VirtualFile named dir then I can call dir.getProject() to obtain the respective project. Is there a similar getModule() method to obtain the respective Module object.
Please sign in to leave a comment.
com.intellij.openapi.roots.ProjectFileIndex#getModuleForFile or com.intellij.openapi.roots.FileIndexFacade#getModuleForFile.
BTW I just found that by using Go To Symbol and searching for getModuleForFile in the Community source. In this case I cheated because I knew the method already existed, but generally the methods in the platform are named very consistently and this is a really useful way of finding functionality. If the obvious name (getModuleForFile or maybe getModuleByFile) didn't work I might search for *module*file and see what comes up. You can find all sorts of interesting things this way.
VirtualFile doesn't have method getProject() and it can't have it because if several projects are open the same VirtualFile may be used in several projects.
See ModuleUtil class.
Thank you Colin. That's exactly what I've been looking for. And also thanks for the little trick :)
Hi Alexander,
Actually VirtualFile has a getProject() method. I was looking for getModule() method.
Check again, com.intellij.openapi.vfs.VirtualFile doesn't have getProject() and it can't have it because IntelliJ virtual file system is implemented at application level, it is not related to projects. It is impossible to implement getProject() for file.
My bad. You're right. VirtualFile doesn't have a getProject() method. I've confused it with a PsiDirectory. BTW I suppose there isn't a single method to find out the base dir of the module, from a PsiDirectory
'Base dir of the module' is a bad term. Module file (*.iml) may be stored anywhere (and unlikely you care). Module may have any amount of content roots and each content root may have any amount of source roots, test source roots, etc. I think you need one of those:
ProjectFileIndex.getSourceRootForFile()
ProjectFileIndex.getContentRootForFile()
The real scenario is that I have a module hierarch like below
\UntitledProject
\UntitledModule
\src
\main
\conf
settings.xml
\java (source root)
foo.java
When I add a new file template (a class) to java folder I need to add an entry to settings.xml file
I can get the 'java' folder as PsiDirectory and assume its name is 'javaPsiDir'
Then in order to find settings.xml I do following
final Module untitledModule = FileIndexFacade.getInstance(javaPsiDir.getProject()).getModuleForFile(javaPsiDir.getVirtualFile());
final VirtualFile untitledModuleDir = module.getModuleFile().getParent();
final VirtualFile settingsXmlFile = untitledModuleDir.findFileByRelativePath(
"src + File.separator + "main + File.separator + "conf + File.separator + "settings.xml");
Avoid using getModuleFile(). It is *.iml that can be stored anywhere.
No need in File.separator, IntelliJ virtual file system works with '/' on all OSes. Native slash must be used in UI only.
Better would be
final VirtualFile sourceRoot = ProjectFileIndex.SERVICE.getInstance(javaPsiDir.getProject()).getSourceRootForFile(javaPsiDir.getVirtualFile());
if (sourceRoot != null) {
final VirtualFile settingsXmlFile = sourceRoot.findFileByRelativePath("../conf/settings.xml");
}
// or
final VirtualFile contentRoot = ProjectFileIndex.SERVICE.getInstance(javaPsiDir.getProject()).getContentRootForFile(javaPsiDir.getVirtualFile());
if (contentRoot != null) {
final VirtualFile settingsXmlFile = contentRoot.findFileByRelativePath("src/main/conf/settings.xml");
}
Thank you very much Alexander,
final VirtualFile contentRoot = ProjectFileIndex.SERVICE.getInstance(javaPsiDir.getProject()).getContentRootForFile(javaPsiDir.getVirtualFile());
if (contentRoot != null) {
final VirtualFile settingsXmlFile = contentRoot.findFileByRelativePath("src/main/conf/settings.xml");
}
approach seems quite elegent and straight forward.