How to create directories for a package in a source root?

I have a PsiPackage instance for which I wish to create the corresponding directories in a source root, if they don't exist, so that I may create a Properties file in that package. The directories may not exist since our project requires that properties files are stored in a separate source root from the java files. Any hints on how to do this correctly?

What if I have multiple source roots in which these directories could be created? How do I show the source root chooser dialog that IDEA uses when creating a class in a package that spans multiple directories?

Thanks,
Gordon

12 comments
Comment actions Permalink

Unfortunately this API is not opened, but if you don't mind dirty work you might want to look at com.intellij.idea.util.PackageUtil:

public static PsiDirectory findOrCreateDirectoryForPackage(Module module,
String packageName,
PsiDirectory baseDir,
boolean askUserToCreate);

The parameters' names are self-explanatory, I guess.

HTH,
Eugene.

0
Comment actions Permalink

Thanks, that takes care of actually creating the directories. I still have to figure out how to choose which module and baseDir to use since there may be multiple modules and source roots in which the user can choose to create the resource bundle. I'm envisioning a dialog which allows the user to select from a list of directories grouped by module. Is there something like that in IDEA that I can reuse?

0
Comment actions Permalink

Yes there is, but again, in closed API. See com.intellij.ide.util.DirectoryChooser class.

0
Comment actions Permalink

Have you looked at PackageUtil.getOrChooseDirectory ?

0
Comment actions Permalink

Going by the name, I assume that selects an existing directory for a package. In my case, the directory may not exist yet so the user has to select the module and base directory in which the package will be created.

0
Comment actions Permalink

I have a similiar requisite in my plugin where i have to create a class in a package that might not exist and in a source root of choice. Here's what i do:

+SourceFolder[] sourceFolders = ModuleRootManager.getInstance(getModule()).getContentEntries()[0].getSourceFolders();

PsiDirectory sourceDirectory;
if (sourceFolders.length > 1)
sourceDirectory = PackageUtil.getOrChooseDirectory((IdeView)DataManager.getInstance().getDataContext().getData(DataConstants.IDE_VIEW));
else
sourceDirectory = PsiManager.getInstance(getModule().getProject()).findDirectory(sourceFolders[0].getFile());

PsiDirectory classDirectory;
classDirectory = PackageUtil.findOrCreateDirectoryForPackage(getModule(), rootPackage, sourceDirectory, false);

if (classDirectory != null)
classDirectory.createClass(className);+

Hope this helps...

0
Comment actions Permalink

Thanks, that was exactly what I wanted.

I'm having another problem though. I create the properties file file with the following code snippet:

PsiDirectory pkgDir = PackageUtil.findOrCreateDirectoryForPackage(module, mPackage.getQualifiedName(), dir, false);
mPropertiesFile = PropertiesElementFactory.createPropertiesFile(mProject, "");
mPropertiesFile.setName(LOG_RESOURCES_FILENAME);
pkgDir.add(mPropertiesFile);

After this my plugin is able to manipulate the properties and everything seems to work, except that mPropertiesFile.getVirtualFile() returns null and the actual properties file is empty when I open it in the editor. Is there some step that I'm missing?

0
Comment actions Permalink

Well, I'm not 100% sure, but it seems that the factory returns non-physical file, i.e. with dummy virtual file. It makes no sense to add it to PsiDirectory (moreover an assertion should be added). Instead you should call PsiDirectory.createFile() and modify the contents later.

0
Comment actions Permalink

Ah, I see. I must just use the correct ".properties" extension and it will magically work. Cool :)

0
Comment actions Permalink

Another question :)

I'd like to keep the properties file sorted, since I'm just compulsive-obsessive like that. Unfortunately, PropertiesFile.addProperty() just appends to the end of the file. I tried writing my own insertion method which finds an existing property after which the new one should be inserted and then used addAfter on the PropertiesList to add the new one after it, but that gave me an unsupported operation error.

I could just recreate the contents of the file from a sorted copy of the names map every time I add a new property, but that seems rather inelegant and brute force. Is there a better way to do it?

0
Comment actions Permalink

I guess no. Please submit an issue to JIRA for adding PropertiesFile.addPropertyAfter(Property anchorProperty)

0

Please sign in to leave a comment.