double dispose

This commit is contained in:
Alexey Kudravtsev
2012-03-20 13:42:53 +04:00
parent a2493cd391
commit d67cbcc81b
7 changed files with 70 additions and 49 deletions
@@ -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;
@@ -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;
}
@@ -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) {
@@ -219,11 +219,13 @@ public class VirtualFilePointerImpl extends UserDataHolderBase implements Virtua
disposed = true;
final Pair<VirtualFile, String> 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);
}
}
}
@@ -72,7 +72,6 @@ public class VirtualFilePointerManagerImpl extends VirtualFilePointerManager imp
synchronized void clearPointerCaches(String url, VirtualFilePointerListener listener) {
TreeMap<String, VirtualFilePointerImpl> 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<String, VirtualFilePointerImpl> map = entry.getValue();
for (VirtualFilePointerImpl pointer : map.values()) {
myUrlToPointerMaps.clear();
//myUrlToPointerMaps.clear();
pointer.throwNotDisposedError("Not disposed pointer: listener="+listener);
}
}
@@ -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");
@@ -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();
}