Custom implementation of PsiDirectory to override navigate() called for the NavBar



I'm developing plugin for LDAP. I have custom ToolWindow with Tree, which dynamically loads entries from LDAP. Each entry is associated with custom LightVirtualFile, which is not currently associated with any Language and uses DummyFileSystem.

I wanted to support navigation in the NavBar, but it is tightly bound to Psi structure. In order to display correct path of opened file I dynamically return true/false from isDirectory() based on the fact, that the entry has children. If parent is a file, then it stops resolving parent nodes and displays only leaf.

Problem is with the navigation to directories, when user clicks on the NavBar item. I managed to correctly open the file and select it in my tool window (instead of project tool window) by providing custom PSI file implementation and returning it from createFile() of FileViewProvider (extending SingleRootFileViewProvider). But I can't return PsiDirectory from those methods (nor they are called by outer logic).

For directories, NavBar is populated with PsiJavaDirectoryImpl items (Java ?) and I didn't find the way, how to provide custom implementation in order to modify behavior of navigate() method for the PsiDirectory (by default it opens project tool window).

I found PsiDirectoryFactory and PsiNavigationSupport, but they are services, not extension points. Is there any way to supply custom PsiDirectory implementation based on a Filetype?

Or is there any way to have only PsiFiles (isDirectory() == false), but display all the files on the path in the NavBar?

I know it somehow works for Database plugin from Intellij IDEA Ultimate, since when debuged, it contains custom Psi elements and whole path is displayed (from db to table).

My PSI file could probably implement PsiDirectory interface, but I don't know if it would help any logic/decision behind it or it is just nonsense. Some kind of NavBarModelExtension, but supporting actions/navigation, not just presentation would be helpful.

It`s also more general question. In LDAP, almost every entry can contain child entries. Is it reasonable to implement full FileSystem support for it in the future? Should all nodes be directories or files? Since there are different methods for retrieving files within directories and subdirectories, for creating files in directories etc. It would probably had to return/work with "same" set of data for both files and directories. But how would rest of the IDE handle it ? I guess it would be confusing on many places, since many parts of IDE behave differently to files and directories.

Thank you for your suggestions.

1 comment
Comment actions Permalink

So, to answer to myself. I ended up with implementing custom class extending AbstractNavBarModelExtension. It has method

public PsiElement adjustElement(PsiElement psiElement)

where I can return any newly created PsiElement based on my VirtualFile, which is retrieved from passed PsiElement (created by IDE logic). So I can return my PsiDirectory if passed element is generic directory and virtual file is type of mine.

But again, devil is in the details. For empty directories, NavBarModel tries to resolve child elements. If there are none, for some reason it does not trust already present PsiDirectory element, but rather calls:

public PsiDirectory findDirectory(@NotNull VirtualFile file)

on PsiManager and only falls back to existing element, if not found. So you end up again with PsiJavaDirectoryImpl returned to the NavBarModel.

Only solution I found is to use custom class extending MockPsiManager in my PsiDirectory implementation, so that I can override its findDirectory() method (returning my PsiDirectory for my VirtualFile and pass rest of requests to the real PsiManager instance stored within).


Please sign in to leave a comment.