diff --git a/platform/analysis-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtilBase.java b/platform/analysis-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtilBase.java index 51ea14c36bdd..256c24cde28f 100644 --- a/platform/analysis-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtilBase.java +++ b/platform/analysis-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtilBase.java @@ -444,7 +444,7 @@ public class InjectedLanguageUtilBase { PsiManagerEx psiManagerEx = PsiManagerEx.getInstanceEx(project); DebugUtil.performPsiModification("injected clearCaches", () -> - psiManagerEx.getFileManager().setViewProvider(virtualFile, null)); + psiManagerEx.getFileManager().dropViewProviders(virtualFile)); VirtualFile delegate = virtualFile.getDelegate(); if (!delegate.isValid()) return; diff --git a/platform/analysis-impl/src/com/intellij/psi/impl/source/tree/injected/MultipleRootsInjectedFileViewProvider.java b/platform/analysis-impl/src/com/intellij/psi/impl/source/tree/injected/MultipleRootsInjectedFileViewProvider.java index 69b0e0e8705f..6d1bc12848c8 100644 --- a/platform/analysis-impl/src/com/intellij/psi/impl/source/tree/injected/MultipleRootsInjectedFileViewProvider.java +++ b/platform/analysis-impl/src/com/intellij/psi/impl/source/tree/injected/MultipleRootsInjectedFileViewProvider.java @@ -102,7 +102,7 @@ class MultipleRootsInjectedFileViewProvider extends MultiplePsiFilesPerDocumentF @Override public final void forceCachedPsi(@NotNull PsiFile psiFile) { myRoots.put(psiFile.getLanguage(), (PsiFileImpl)psiFile); - getManager().getFileManager().setViewProvider(getVirtualFile(), this); + getManager().getFileManager().changeViewProvider(getVirtualFile(), this); } public void doNotInterruptMeWhileImPatchingLeaves(@NotNull Runnable runnable) { diff --git a/platform/core-impl/api-dump-experimental.txt b/platform/core-impl/api-dump-experimental.txt index df96ba8a6315..cdea176fabe3 100644 --- a/platform/core-impl/api-dump-experimental.txt +++ b/platform/core-impl/api-dump-experimental.txt @@ -102,7 +102,9 @@ f:com.intellij.psi.impl.PsiModificationTrackerImpl f:com.intellij.psi.impl.file.PsiFileImplUtil - *s:setNonPhysicalFileDeleteHandler(com.intellij.psi.PsiFile,java.util.function.Consumer):V com.intellij.psi.impl.file.impl.FileManager +- *a:changeViewProvider(com.intellij.openapi.vfs.VirtualFile,com.intellij.psi.FileViewProvider):V - *a:createFileViewProvider(com.intellij.openapi.vfs.VirtualFile,com.intellij.codeInsight.multiverse.CodeInsightContext,Z):com.intellij.psi.FileViewProvider +- *a:dropViewProviders(com.intellij.openapi.vfs.VirtualFile):V - *a:findCachedViewProvider(com.intellij.openapi.vfs.VirtualFile,com.intellij.codeInsight.multiverse.CodeInsightContext):com.intellij.psi.FileViewProvider - *a:findCachedViewProviders(com.intellij.openapi.vfs.VirtualFile):java.util.List - *a:findFile(com.intellij.openapi.vfs.VirtualFile,com.intellij.codeInsight.multiverse.CodeInsightContext):com.intellij.psi.PsiFile diff --git a/platform/core-impl/src/com/intellij/psi/AbstractFileViewProvider.java b/platform/core-impl/src/com/intellij/psi/AbstractFileViewProvider.java index 5c749cc1ac75..82d5b0bdad2f 100644 --- a/platform/core-impl/src/com/intellij/psi/AbstractFileViewProvider.java +++ b/platform/core-impl/src/com/intellij/psi/AbstractFileViewProvider.java @@ -182,9 +182,8 @@ public abstract class AbstractFileViewProvider extends UserDataHolderBase implem if (!isPhysical()) { FileManager fileManager = getManager().getFileManager(); VirtualFile virtualFile = getVirtualFile(); - // todo IJPL-339 check no real context is used here??? if (fileManager.findCachedViewProvider(virtualFile) == null && getCachedPsiFiles().isEmpty()) { - fileManager.setViewProvider(virtualFile, this); + fileManager.changeViewProvider(virtualFile, this); } } return getPsiInner(target); @@ -399,7 +398,7 @@ public abstract class AbstractFileViewProvider extends UserDataHolderBase implem public final void markInvalidated() { invalidateCachedPsi(); for (AbstractFileViewProvider copy : getKnownCopies()) { - myManager.getFileManager().setViewProvider(copy.getVirtualFile(), null); + myManager.getFileManager().dropViewProviders(copy.getVirtualFile()); } } diff --git a/platform/core-impl/src/com/intellij/psi/DummyHolderViewProvider.java b/platform/core-impl/src/com/intellij/psi/DummyHolderViewProvider.java index f6d2dad41aeb..f0636fdfa90b 100644 --- a/platform/core-impl/src/com/intellij/psi/DummyHolderViewProvider.java +++ b/platform/core-impl/src/com/intellij/psi/DummyHolderViewProvider.java @@ -48,7 +48,7 @@ public class DummyHolderViewProvider extends AbstractFileViewProvider { @Override public PsiFile getCachedPsi(@NotNull Language target) { - getManager().getFileManager().setViewProvider(getVirtualFile(), this); + getManager().getFileManager().changeViewProvider(getVirtualFile(), this); return target == getBaseLanguage() ? myHolder : null; } diff --git a/platform/core-impl/src/com/intellij/psi/SingleRootFileViewProvider.java b/platform/core-impl/src/com/intellij/psi/SingleRootFileViewProvider.java index 9a7585498784..eac08fb7351f 100644 --- a/platform/core-impl/src/com/intellij/psi/SingleRootFileViewProvider.java +++ b/platform/core-impl/src/com/intellij/psi/SingleRootFileViewProvider.java @@ -254,6 +254,6 @@ public class SingleRootFileViewProvider extends AbstractFileViewProvider impleme if (prev != psiFile && prev instanceof PsiFileEx) { DebugUtil.performPsiModification(getClass().getName() + " PSI change", () -> ((PsiFileEx)prev).markInvalidated()); } - getManager().getFileManager().setViewProvider(getVirtualFile(), this); + getManager().getFileManager().changeViewProvider(getVirtualFile(), this); } } diff --git a/platform/core-impl/src/com/intellij/psi/impl/file/impl/FileManager.java b/platform/core-impl/src/com/intellij/psi/impl/file/impl/FileManager.java index c15c1da03f03..fa724946dcd7 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/file/impl/FileManager.java +++ b/platform/core-impl/src/com/intellij/psi/impl/file/impl/FileManager.java @@ -63,10 +63,23 @@ public interface FileManager { @Nullable FileViewProvider findCachedViewProvider(@NotNull VirtualFile vFile, @NotNull CodeInsightContext context); + /** @deprecated use {@link #changeViewProvider(VirtualFile, FileViewProvider)} or {@link #dropViewProviders(VirtualFile)} instead. */ + @Deprecated + void setViewProvider(@NotNull VirtualFile vFile, @Nullable FileViewProvider viewProvider); + + /** + * Requires write lock for physical files, and usually does not require a write lock for non-physical files. + *

+ * If a file has several view providers, all of them will be invalidated. + */ + @ApiStatus.Experimental + void changeViewProvider(@NotNull VirtualFile vFile, @NotNull FileViewProvider viewProvider); + /** * Requires write lock for physical files, and usually does not require a write lock for non-physical files. */ - void setViewProvider(@NotNull VirtualFile vFile, @Nullable FileViewProvider viewProvider); + @ApiStatus.Experimental + void dropViewProviders(@NotNull VirtualFile vFile); @NotNull List getAllCachedFiles(); diff --git a/platform/core-impl/src/com/intellij/psi/impl/file/impl/FileManagerImpl.java b/platform/core-impl/src/com/intellij/psi/impl/file/impl/FileManagerImpl.java index dbf2eae31dbc..6e9356e88239 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/file/impl/FileManagerImpl.java +++ b/platform/core-impl/src/com/intellij/psi/impl/file/impl/FileManagerImpl.java @@ -145,7 +145,7 @@ public final class FileManagerImpl implements FileManagerEx { return; } if (!CodeInsightContextUtil.isEventSystemEnabled(viewProviders)) { - setViewProvider(vFile, null); + dropViewProviders(vFile); return; } @@ -159,13 +159,13 @@ public final class FileManagerImpl implements FileManagerEx { event.setPropertyName(PsiTreeChangeEvent.PROP_UNLOADED_PSI); myManager.beforePropertyChange(event); - setViewProvider(vFile, null); + dropViewProviders(vFile); myManager.propertyChanged(event); } else { event.setParent(parentDir); myManager.beforeChildrenChange(event); - setViewProvider(vFile, null); + dropViewProviders(vFile); myManager.childrenChanged(event); } } @@ -316,21 +316,16 @@ public final class FileManagerImpl implements FileManagerEx { @Override public void setViewProvider(@NotNull VirtualFile vFile, @Nullable FileViewProvider viewProvider) { - // todo IJPL-339 investigate if we need a context here if (viewProvider == null) { - // Let's drop all providers. - // Please add a new method if you need to drop only a single provider. But this seems to be a suspicious idea, - // because shouldn't you drop other providers as well? - dropAllProviders(vFile); + dropViewProviders(vFile); } else { - changeFileProvider(vFile, viewProvider); + changeViewProvider(vFile, viewProvider); } } - private void changeFileProvider(@NotNull VirtualFile vFile, - @NotNull FileViewProvider viewProvider) { - + @Override + public void changeViewProvider(@NotNull VirtualFile vFile, @NotNull FileViewProvider viewProvider) { if (vFile instanceof LightVirtualFile) { FileViewProvider prev = getRawCachedViewProvider(vFile, CodeInsightContexts.anyContext()); if (prev == viewProvider) return; @@ -359,7 +354,8 @@ public final class FileManagerImpl implements FileManagerEx { } } - private void dropAllProviders(@NotNull VirtualFile vFile) { + @Override + public void dropViewProviders(@NotNull VirtualFile vFile) { if (vFile instanceof LightVirtualFile) { FileViewProvider oldProvider = vFile.getUserData(myPsiHardRefKey); if (oldProvider != null) { diff --git a/platform/lang-impl/src/com/intellij/mock/MockFileManager.java b/platform/lang-impl/src/com/intellij/mock/MockFileManager.java index bc7bcbd6c888..d9250f5988e2 100644 --- a/platform/lang-impl/src/com/intellij/mock/MockFileManager.java +++ b/platform/lang-impl/src/com/intellij/mock/MockFileManager.java @@ -110,6 +110,16 @@ public final class MockFileManager implements FileManager { myViewProviders.put(vFile, viewProvider); } + @Override + public void changeViewProvider(@NotNull VirtualFile vFile, @NotNull FileViewProvider viewProvider) { + myViewProviders.put(vFile, viewProvider); + } + + @Override + public void dropViewProviders(@NotNull VirtualFile vFile) { + myViewProviders.remove(vFile); + } + @Override public @NotNull List getAllCachedFiles() { throw new UnsupportedOperationException("Method getAllCachedFiles is not yet implemented in " + getClass().getName()); diff --git a/platform/lang-impl/src/com/intellij/psi/impl/file/impl/PsiVFSListener.kt b/platform/lang-impl/src/com/intellij/psi/impl/file/impl/PsiVFSListener.kt index e2b83bb0c9cd..f8a8f7bbef0f 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/file/impl/PsiVFSListener.kt +++ b/platform/lang-impl/src/com/intellij/psi/impl/file/impl/PsiVFSListener.kt @@ -107,7 +107,7 @@ private class PsiVFSListener(private val project: Project) { val psiFile = fileManager.getCachedPsiFileInner(vFile, anyContext()) var element: PsiElement? if (psiFile != null) { - fileManager.setViewProvider(vFile, null) + fileManager.dropViewProviders(vFile) element = psiFile } else { @@ -141,7 +141,7 @@ private class PsiVFSListener(private val project: Project) { private fun clearViewProvider(vFile: VirtualFile, why: String) { DebugUtil.performPsiModification(why) { - fileManager.setViewProvider(vFile, null) + fileManager.dropViewProviders(vFile) } } @@ -305,7 +305,7 @@ private class PsiVFSListener(private val project: Project) { manager.childRemoved(treeEvent) } else if (!FileManagerImpl.areViewProvidersEquivalent(fileViewProvider, oldFileViewProvider!!)) { - fileManager.setViewProvider(vFile, fileViewProvider) + fileManager.changeViewProvider(vFile, fileViewProvider) treeEvent.oldChild = oldPsiFile treeEvent.newChild = newPsiFile @@ -322,7 +322,7 @@ private class PsiVFSListener(private val project: Project) { } } else if (newPsiFile != null) { - fileManager.setViewProvider(vFile, fileViewProvider) + fileManager.changeViewProvider(vFile, fileViewProvider) if (parentDir != null) { treeEvent.child = newPsiFile manager.childAdded(treeEvent) @@ -455,7 +455,9 @@ private class PsiVFSListener(private val project: Project) { ApplicationManager.getApplication().runWriteAction(ExternalChangeActionUtil.externalChangeAction { val treeEvent = PsiTreeChangeEventImpl(manager) if (oldElement == null) { - fileManager.setViewProvider(vFile, newViewProvider) + if (newViewProvider != null) { + fileManager.changeViewProvider(vFile, newViewProvider) + } treeEvent.parent = newParentDir treeEvent.child = newElement manager.childAdded(treeEvent) @@ -476,7 +478,7 @@ private class PsiVFSListener(private val project: Project) { manager.childMoved(treeEvent) } else { - fileManager.setViewProvider(vFile, newViewProvider) + fileManager.changeViewProvider(vFile, newViewProvider) val treeRemoveEvent = PsiTreeChangeEventImpl(manager) treeRemoveEvent.parent = oldParentDir treeRemoveEvent.child = oldElement diff --git a/platform/lang-impl/testSources/com/intellij/psi/impl/file/impl/FileContextTest.kt b/platform/lang-impl/testSources/com/intellij/psi/impl/file/impl/FileContextTest.kt index 98ed93bbb3a2..4308b690dbde 100644 --- a/platform/lang-impl/testSources/com/intellij/psi/impl/file/impl/FileContextTest.kt +++ b/platform/lang-impl/testSources/com/intellij/psi/impl/file/impl/FileContextTest.kt @@ -118,7 +118,7 @@ internal class FileContextTest { } writeAction { - psiManager.fileManager.setViewProvider(virtualFile, null) + psiManager.fileManager.dropViewProviders(virtualFile) } } while (true)