Backward-incompatible change with MultiplePsiFilesPerDocumentFileViewProvider in 14.1?

My custom language plugin includes support for a markup language is embedded inside of HTML files a la JSP, PHP, etc.  I'm implemented it as a combination of a MultiplePsiFilesPerDocumentFileViewProvider and all the scaffolding that drags in with it.  Everything had been working pretty well overall, but yesterday I noticed that when I go into those files, it blows up with the following error as soon as I start editing:

[  38579]  ERROR - llij.ide.plugins.PluginManager - Copied view provider must be non-physical for reparse to deliver correct events: VisualforceFileViewProvider{myVirtualFile=file://path/to/markup-file, content=com.intellij.psi.SingleRootFileViewProvider$PsiFileContent@73f0621b}
java.lang.AssertionError: Copied view provider must be non-physical for reparse to deliver correct events:

                at com.intellij.psi.impl.source.text.BlockSupportImpl.makeFullParse(BlockSupportImpl.java:197)

                at com.intellij.psi.impl.source.text.BlockSupportImpl.reparseRange(BlockSupportImpl.java:86)

                at com.intellij.psi.impl.DocumentCommitProcessor.doCommit(DocumentCommitProcessor.java:124)

                at com.intellij.psi.impl.DocumentCommitThread$4.run(DocumentCommitThread.java:464)

                at com.intellij.psi.impl.DocumentCommitThread.commitUnderProgress(DocumentCommitThread.java:474)

                at com.intellij.psi.impl.DocumentCommitThread.commitSynchronously(DocumentCommitThread.java:413)

                at com.intellij.psi.impl.PsiDocumentManagerBase$5.run(PsiDocumentManagerBase.java:374)

                at com.intellij.openapi.application.impl.ApplicationImpl.runWriteAction(ApplicationImpl.java:937)

                at com.intellij.psi.impl.PsiDocumentManagerBase.doCommit(PsiDocumentManagerBase.java:366)

                at com.intellij.psi.impl.PsiDocumentManagerBase.commitDocument(PsiDocumentManagerBase.java:278)

                at com.intellij.psi.impl.PsiDocumentManagerBase.commitAllDocuments(PsiDocumentManagerBase.java:212)

                at com.intellij.codeInsight.editorActions.EnterHandler.executeWriteActionInner(EnterHandler.java:166)

                at com.intellij.codeInsight.editorActions.EnterHandler.access$000(EnterHandler.java:54)

                at com.intellij.codeInsight.editorActions.EnterHandler$1.run(EnterHandler.java:76)

                at com.intellij.psi.impl.source.PostprocessReformattingAspect$3.compute(PostprocessReformattingAspect.java:112)

                at com.intellij.psi.impl.source.PostprocessReformattingAspect.disablePostprocessFormattingInside(PostprocessReformattingAspect.java:121)

                at com.intellij.psi.impl.source.PostprocessReformattingAspect.disablePostprocessFormattingInside(PostprocessReformattingAspect.java:109)

In addition to the recent upgrade to 14.1 for my plugin development, I've also been making changes to my own plugin, but not in the area of this markup language.  I don't have IDEA 14.0 installed any longer since 14.1 replaced it, but I still have IDEA 12 and 13 installed for testing and the markup works fine in those versions, so my guess is that this is happening due to some change in the plugin SDK or IDE core.

Any thoughts on what's happening and whether there's a way for me to fix it in my plugin?

Thanks!

0
8 comments

This assertion was added to prevent pretty bad things from happening. The text says it all: cloned file view provider should not be isPhysical.
The fix should be easy: just pass false to the constructor of the view provider clone when creating it inside cloneInner.

0

Thanks for the reply.  Just so I understand, are you saying that I should always pass eventSystemEnabled=false when invoking the superclass constructor in my subclass of MultipleFilesPerDocumentFileViewProvider?  If so, I tried that and things got even worse!  If not, can you be more specific about the required change?

Just to be clear, when I say that "things got even worse", I mean that anytime I try to access these files I get:

java.lang.IllegalArgumentException: Argument for @NotNull parameter 'file' of com/intellij/openapi/roots/impl/DirectoryIndexImpl.getInfoForFile must not be null
 at com.intellij.openapi.roots.impl.DirectoryIndexImpl.getInfoForFile(DirectoryIndexImpl.java)
 at com.intellij.ide.projectView.impl.nodes.ProjectViewDirectoryHelper.shouldBeShown(ProjectViewDirectoryHelper.java:211)
 at com.intellij.ide.projectView.impl.nodes.ProjectViewDirectoryHelper.access$000(ProjectViewDirectoryHelper.java:53)
 at com.intellij.ide.projectView.impl.nodes.ProjectViewDirectoryHelper$1.execute(ProjectViewDirectoryHelper.java:181)
 at com.intellij.ide.projectView.impl.nodes.ProjectViewDirectoryHelper$1.execute(ProjectViewDirectoryHelper.java:178)
 at com.intellij.psi.impl.file.PsiDirectoryImpl.processChildren(PsiDirectoryImpl.java:201)
 at com.intellij.ide.projectView.impl.nodes.ProjectViewDirectoryHelper.directoryChildrenInProject(ProjectViewDirectoryHelper.java:178)

I apologize for being obtuse, but as I said, this all worked until I upgraded to 14.1.

Thanks in advance for any additional guidance!

0

Actually, the correct name for this flag is now "eventSystemEnabled". When creating the view provider in FileViewProviderFactory, you just pass it whatever the factory passed you. When inside cloneInner, always use false.

0

Thanks.  Yep, that's exactly what I did, and the behavior was as described above.  There must be something else I'm doing wrong since changing that to false all the time is causing other things to fail so badly.  Unfortunately there's very little documentation on MultiplePsiFilesPerDocumentFileViewProvider so I'm basing my implementation on what others have posted on this forum.  For the most part, it's a direct derivative of those posts, so I'm not entirely sure where to even start looking for why this is failing.  As always, any more informed guidance is greatly appreciated!

0

Is it possible for you to show the source code of your view provider class (and its factory) after the suggested changes?

0

The recommendation to pass eventSystemEnabled=false from cloneInner() fixed the issues.

For what it's worth, this is the most comprehensive documentation I could find on how to implement one of these:

https://devnet.jetbrains.com/message/5450284

and obviously it's not completely up-to-date since it recommends passing in the derived value for eventSystemEnabled.  It would be wonderful if you guys could put together some documentation on how to implement one similar to what you have for custom language plugins and such, especially since it's so heavily related to custom language plugins.

Thanks for the eyes on this!

0

Thanks. I don't understand the comments you put into this code, but it appears to not contain the changes I suggested: "boolean eventSystemEnabled" from the factory isn't passed to the super constructor.

0

That comment was an artfact of having IDEA remove the third parameter so I could hard-code eventSystemEnabled=false.  However, re-reading your most recent comment, I see that's not quite what you recommended.  Let me make those changes and I'll let you know how things look.  Sorry for the oversight!

UPDATE: Yep, that worked perfectly!  Ugh...that's what I get for reading what I expect to read and not what you actually wrote.  I've backed out my override of getVirtualFile() and now pass eventSystemEnabled=false only in cloneInner().  I'll update my comment above to reflect this solution.  I still recommend some additonal documentation on this feature, especially how you take advantage of the existing features of the outer langage such as syntax highlighting, code formatting, etc., as it doesn't seem like those things come 100% for free.

Thanks so much!!!

0

Please sign in to leave a comment.