diff --git a/java/idea-ui/src/com/intellij/util/descriptors/impl/ConfigFileContainerImpl.java b/java/idea-ui/src/com/intellij/util/descriptors/impl/ConfigFileContainerImpl.java index 6299468b345b..331db279750b 100644 --- a/java/idea-ui/src/com/intellij/util/descriptors/impl/ConfigFileContainerImpl.java +++ b/java/idea-ui/src/com/intellij/util/descriptors/impl/ConfigFileContainerImpl.java @@ -16,10 +16,11 @@ package com.intellij.util.descriptors.impl; +import com.intellij.openapi.Disposable; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.MultiValuesMap; import com.intellij.openapi.vfs.*; -import com.intellij.openapi.Disposable; import com.intellij.util.EventDispatcher; import com.intellij.util.descriptors.*; import org.jetbrains.annotations.Nullable; @@ -135,6 +136,7 @@ public class ConfigFileContainerImpl implements ConfigFileContainer { } for (ConfigFileInfo configuration : newDescriptors) { final ConfigFileImpl configFile = new ConfigFileImpl(this, configuration); + Disposer.register(this, configFile); myConfigFiles.put(metaData, configFile); added.add(configFile); } @@ -142,6 +144,7 @@ public class ConfigFileContainerImpl implements ConfigFileContainer { for (ConfigFile descriptor : toDelete) { myConfigFiles.remove(descriptor.getMetaData(), descriptor); + Disposer.dispose(descriptor); } myCachedConfigFiles = null; diff --git a/java/idea-ui/src/com/intellij/util/descriptors/impl/ConfigFileImpl.java b/java/idea-ui/src/com/intellij/util/descriptors/impl/ConfigFileImpl.java index fcee66b35973..a64cc6c8a313 100644 --- a/java/idea-ui/src/com/intellij/util/descriptors/impl/ConfigFileImpl.java +++ b/java/idea-ui/src/com/intellij/util/descriptors/impl/ConfigFileImpl.java @@ -1,4 +1,3 @@ - package com.intellij.util.descriptors.impl; import com.intellij.openapi.project.Project; @@ -22,43 +21,38 @@ import org.jetbrains.annotations.Nullable; */ public class ConfigFileImpl implements ConfigFile { @NotNull private ConfigFileInfo myInfo; - private VirtualFilePointer myFilePointer; - private PsiFile myPsiFile; + private final VirtualFilePointer myFilePointer; + private volatile PsiFile myPsiFile; private final ConfigFileContainerImpl myContainer; private final Project myProject; private long myModificationCount; - private final Object myPsiFileLock = new Object(); - private final VirtualFilePointerListener myListener = new VirtualFilePointerListener() { - public void beforeValidityChanged(final VirtualFilePointer[] pointers) { - } - - public void validityChanged(final VirtualFilePointer[] pointers) { - synchronized (myPsiFileLock) { - myPsiFile = null; - } - onChange(); - } - }; public ConfigFileImpl(@NotNull final ConfigFileContainerImpl container, @NotNull final ConfigFileInfo configuration) { myContainer = container; myInfo = configuration; - setUrl(configuration.getUrl()); + final VirtualFilePointerManager pointerManager = VirtualFilePointerManager.getInstance(); + myFilePointer = pointerManager.create(configuration.getUrl(), this, new VirtualFilePointerListener() { + @Override + public void beforeValidityChanged(final VirtualFilePointer[] pointers) { + } + + @Override + public void validityChanged(final VirtualFilePointer[] pointers) { + myPsiFile = null; + onChange(); + } + }); + onChange(); Disposer.register(container, this); myProject = myContainer.getProject(); } - private void setUrl(String url) { - final VirtualFilePointerManager pointerManager = VirtualFilePointerManager.getInstance(); - myFilePointer = pointerManager.create(url, this, myListener); - onChange(); - } - private void onChange() { myModificationCount++; myContainer.fireDescriptorChanged(this); } + @Override public String getUrl() { return myFilePointer.getUrl(); } @@ -67,17 +61,16 @@ public class ConfigFileImpl implements ConfigFile { myInfo = info; } + @Override @Nullable public VirtualFile getVirtualFile() { return myFilePointer.getFile(); } + @Override @Nullable public PsiFile getPsiFile() { - PsiFile psiFile; - synchronized (myPsiFileLock) { - psiFile = myPsiFile; - } + PsiFile psiFile = myPsiFile; if (psiFile != null && psiFile.isValid()) { return psiFile; @@ -88,27 +81,29 @@ public class ConfigFileImpl implements ConfigFile { psiFile = PsiManager.getInstance(myProject).findFile(virtualFile); - synchronized (myPsiFileLock) { - myPsiFile = psiFile; - } + myPsiFile = psiFile; return psiFile; } + @Override @Nullable public XmlFile getXmlFile() { final PsiFile file = getPsiFile(); return file instanceof XmlFile ? (XmlFile)file : null; } + @Override public void dispose() { } + @Override @NotNull public ConfigFileInfo getInfo() { return myInfo; } + @Override public boolean isValid() { final PsiFile psiFile = getPsiFile(); if (psiFile == null || !psiFile.isValid()) { @@ -122,12 +117,14 @@ public class ConfigFileImpl implements ConfigFile { } + @Override @NotNull public ConfigFileMetaData getMetaData() { return myInfo.getMetaData(); } + @Override public long getModificationCount() { return myModificationCount; } diff --git a/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java b/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java index 53f1c6b6583e..b3dc24ace4ae 100644 --- a/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java +++ b/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java @@ -109,7 +109,6 @@ public abstract class DaemonAnalyzerTestCase extends CodeInsightTestCase { @Override protected void setUp() throws Exception { super.setUp(); - ((VirtualFilePointerManagerImpl)VirtualFilePointerManager.getInstance()).cleanupForNextTest(); final LocalInspectionTool[] tools = configureLocalInspectionTools(); for (LocalInspectionTool tool : tools) { diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerImpl.java index c1b580603cbd..fa98c84c896e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerImpl.java @@ -219,11 +219,13 @@ public class VirtualFilePointerImpl extends UserDataHolderBase implements Virtua disposed = true; final Pair pair = myFileAndUrl; - if (pair.first != null) { - ((VirtualFilePointerManagerImpl)VirtualFilePointerManager.getInstance()).clearPointerCaches(pair.first.getUrl(), myListener); + VirtualFile file = pair.first; + if (file != null) { + ((VirtualFilePointerManagerImpl)VirtualFilePointerManager.getInstance()).clearPointerCaches(file.getUrl(), myListener); } - if (pair.second != null) { - ((VirtualFilePointerManagerImpl)VirtualFilePointerManager.getInstance()).clearPointerCaches(pair.second, myListener); + String url = pair.second; + if (url != null && (file == null || !url.equals(file.getUrl()))) { + ((VirtualFilePointerManagerImpl)VirtualFilePointerManager.getInstance()).clearPointerCaches(url, myListener); } } } diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerManagerImpl.java index 15ec1b998201..6b9ac8d5ab93 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerManagerImpl.java @@ -72,7 +72,6 @@ public class VirtualFilePointerManagerImpl extends VirtualFilePointerManager imp synchronized void clearPointerCaches(String url, VirtualFilePointerListener listener) { TreeMap urlToPointer = myUrlToPointerMaps.get(listener); - if (urlToPointer == null && ApplicationManager.getApplication().isUnitTestMode()) return; assert urlToPointer != null; urlToPointer.remove(VfsUtil.urlToPath(url)); if (urlToPointer.isEmpty()) { @@ -148,12 +147,6 @@ public class VirtualFilePointerManagerImpl extends VirtualFilePointerManager imp return url.substring(separatorIndex + JarFileSystem.JAR_SEPARATOR.length()); } - @TestOnly - public synchronized void cleanupForNextTest() { - myUrlToPointerMaps.clear(); - myContainers.clear(); - } - /** * @see #create(String, com.intellij.openapi.Disposable, com.intellij.openapi.vfs.pointers.VirtualFilePointerListener) */ @@ -339,7 +332,7 @@ public class VirtualFilePointerManagerImpl extends VirtualFilePointerManager imp VirtualFilePointerListener listener = entry.getKey(); TreeMap map = entry.getValue(); for (VirtualFilePointerImpl pointer : map.values()) { - myUrlToPointerMaps.clear(); + //myUrlToPointerMaps.clear(); pointer.throwNotDisposedError("Not disposed pointer: listener="+listener); } } diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/VirtualFilePointerTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/VirtualFilePointerTest.java index 116a6c59557c..ec9f7b074671 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/VirtualFilePointerTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/VirtualFilePointerTest.java @@ -424,6 +424,39 @@ public class VirtualFilePointerTest extends PlatformLangTestCase { }); } + public void testDoubleDispose() throws IOException { + final File tempDir = createTempDirectory(); + final File file = new File(tempDir, "f1"); + boolean created = file.createNewFile(); + assertTrue(created); + + final VirtualFile[] vFile = new VirtualFile[1]; + final String url = VirtualFileManager.constructUrl(LocalFileSystem.PROTOCOL, file.getCanonicalPath().replace(File.separatorChar, '/')); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + vFile[0] = VirtualFileManager.getInstance().refreshAndFindFileByUrl(url); + } + }); + + Disposable disposable = Disposer.newDisposable(); + final VirtualFilePointer pointer = myVirtualFilePointerManager.create(vFile[0], disposable, new VirtualFilePointerListener() { + @Override + public void beforeValidityChanged(VirtualFilePointer[] pointers) { + } + + @Override + public void validityChanged(VirtualFilePointer[] pointers) { + } + }); + + + assertTrue(pointer.isValid()); + + Disposer.dispose(disposable); + assertFalse(pointer.isValid()); + } + public void testThreads() throws IOException, InterruptedException { final File ioTempDir = createTempDirectory(); final File ioPtrBase = new File(ioTempDir, "parent"); diff --git a/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java b/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java index 2a853d4ea32f..6eaef6b87234 100644 --- a/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java @@ -53,11 +53,9 @@ import com.intellij.openapi.util.EmptyRunnable; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.vfs.impl.VirtualFilePointerManagerImpl; import com.intellij.openapi.vfs.impl.local.LocalFileSystemImpl; import com.intellij.openapi.vfs.newvfs.impl.VirtualDirectoryImpl; import com.intellij.openapi.vfs.newvfs.persistent.PersistentFS; -import com.intellij.openapi.vfs.pointers.VirtualFilePointerManager; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; @@ -339,10 +337,6 @@ public abstract class PlatformTestCase extends UsefulTestCase implements DataPro LocalHistoryImpl.getInstanceImpl().cleanupForNextTest(); - VirtualFilePointerManagerImpl virtualFilePointerManager = (VirtualFilePointerManagerImpl)VirtualFilePointerManager.getInstance(); - if (virtualFilePointerManager != null) { - virtualFilePointerManager.cleanupForNextTest(); - } PatchedWeakReference.clearAll(); }