VirtualFilePointer validity events on bus solves missing listener problem.

This commit is contained in:
Maxim Shafirov
2010-08-10 19:15:10 +04:00
parent 0091e94618
commit 2adcf97d35
4 changed files with 73 additions and 26 deletions
@@ -62,6 +62,7 @@ import com.intellij.util.messages.MessageBusConnection;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
@@ -79,8 +80,6 @@ public class ProjectRootManagerImpl extends ProjectRootManagerEx implements Proj
private final EventDispatcher<ProjectJdkListener> myProjectJdkEventDispatcher = EventDispatcher.create(ProjectJdkListener.class);
private final MyVirtualFilePointerListener myVirtualFilePointerListener = new MyVirtualFilePointerListener();
private AppListener myApplicationListener;
private String myProjectJdkName;
@@ -102,7 +101,6 @@ public class ProjectRootManagerImpl extends ProjectRootManagerEx implements Proj
private final MessageBusConnection myConnection;
private final VirtualFileManagerAdapter myVFSListener;
private final BatchUpdateListener myHandler;
private final StartupManager myStartupManager;
private class BatchSession {
private int myBatchLevel = 0;
@@ -175,7 +173,6 @@ public class ProjectRootManagerImpl extends ProjectRootManagerEx implements Proj
FileTypeManager fileTypeManager,
DirectoryIndex directoryIndex,
StartupManager startupManager) {
myStartupManager = startupManager;
myProject = (ProjectEx)project;
myConnection = project.getMessageBus().connect();
myConnection.subscribe(AppTopics.FILE_TYPES, new FileTypeListener() {
@@ -215,6 +212,8 @@ public class ProjectRootManagerImpl extends ProjectRootManagerEx implements Proj
myFileTypesChanged.levelDown();
}
};
myConnection.subscribe(VirtualFilePointerListener.TOPIC, new MyVirtualFilePointerListener());
}
public void registerRootsChangeUpdater(CacheUpdater updater) {
@@ -246,7 +245,7 @@ public class ProjectRootManagerImpl extends ProjectRootManagerEx implements Proj
}
public VirtualFilePointerListener getVirtualFilePointerListener() {
return myVirtualFilePointerListener;
return null;
}
@NotNull
@@ -629,9 +628,20 @@ public class ProjectRootManagerImpl extends ProjectRootManagerEx implements Proj
}
private void addRootsToWatch() {
if (myProject.isDefault()) {
return;
}
final Set<String> rootPaths = getAllRoots();
if (rootPaths == null) return;
final Set<LocalFileSystem.WatchRequest> newRootsToWatch = LocalFileSystem.getInstance().addRootsToWatch(rootPaths, true);
//remove old requests after adding new ones, helps avoiding unnecessary synchronizations
LocalFileSystem.getInstance().removeWatchedRoots(myRootsToWatch);
myRootsToWatch = newRootsToWatch;
}
@Nullable
private Set<String> getAllRoots() {
if (myProject.isDefault()) return null;
final Set<String> rootPaths = new HashSet<String>();
Module[] modules = ModuleManager.getInstance(myProject).getModules();
for (Module module : modules) {
@@ -679,11 +689,7 @@ public class ProjectRootManagerImpl extends ProjectRootManagerEx implements Proj
}
}
final Set<LocalFileSystem.WatchRequest> newRootsToWatch = LocalFileSystem.getInstance().addRootsToWatch(rootPaths, true);
//remove old requests after adding new ones, helps avoiding unnecessary synchronizations
LocalFileSystem.getInstance().removeWatchedRoots(myRootsToWatch);
myRootsToWatch = newRootsToWatch;
return rootPaths;
}
private static Collection<String> getRootsToTrack(final Library library, final OrderRootType rootType) {
@@ -740,12 +746,16 @@ public class ProjectRootManagerImpl extends ProjectRootManagerEx implements Proj
public void beforeValidityChanged(VirtualFilePointer[] pointers) {
if (!myProject.isDisposed()) {
if (myInsideRefresh == 0) {
beforeRootsChange(false);
if (affectsRoots(pointers)) {
beforeRootsChange(false);
}
}
else if (!myPointerChangesDetected) {
//this is the first pointer changing validity
myPointerChangesDetected = true;
myProject.getMessageBus().syncPublisher(ProjectTopics.PROJECT_ROOTS).beforeRootsChange(new ModuleRootEventImpl(myProject, false));
if (affectsRoots(pointers)) {
myPointerChangesDetected = true;
myProject.getMessageBus().syncPublisher(ProjectTopics.PROJECT_ROOTS).beforeRootsChange(new ModuleRootEventImpl(myProject, false));
}
}
}
}
@@ -756,12 +766,33 @@ public class ProjectRootManagerImpl extends ProjectRootManagerEx implements Proj
clearScopesCaches();
}
else {
rootsChanged(false);
if (affectsRoots(pointers)) {
rootsChanged(false);
}
}
}
}
}
private boolean affectsRoots(VirtualFilePointer[] pointers) {
Set<String> roots = getAllRoots();
if (roots == null) return false;
for (VirtualFilePointer pointer : pointers) {
if (roots.contains(url2path(pointer.getUrl()))) return true;
}
return false;
}
private static String url2path(String url) {
String path = VfsUtil.urlToPath(url);
int separatorIndex = path.indexOf(JarFileSystem.JAR_SEPARATOR);
if (separatorIndex < 0) return path;
return path.substring(0, separatorIndex);
}
private int myInsideRefresh = 0;
private boolean myPointerChangesDetected = false;
@@ -15,7 +15,11 @@
*/
package com.intellij.openapi.vfs.pointers;
import com.intellij.util.messages.Topic;
public interface VirtualFilePointerListener {
Topic<VirtualFilePointerListener> TOPIC = Topic.create("VirtualFilePointer", VirtualFilePointerListener.class);
void beforeValidityChanged(VirtualFilePointer[] pointers);
void validityChanged(VirtualFilePointer[] pointers);
}
@@ -50,6 +50,7 @@ public class VirtualFilePointerManagerImpl extends VirtualFilePointerManager imp
// guarded by myContainers
private final Set<VirtualFilePointerContainerImpl> myContainers = new THashSet<VirtualFilePointerContainerImpl>(TObjectHashingStrategy.IDENTITY);
private final VirtualFileManagerEx myVirtualFileManager;
private MessageBus myBus;
private static final Comparator<String> COMPARATOR = SystemInfo.isFileSystemCaseSensitive ? new Comparator<String>() {
public int compare(@NotNull String url1, @NotNull String url2) {
return url1.compareTo(url2);
@@ -62,6 +63,7 @@ public class VirtualFilePointerManagerImpl extends VirtualFilePointerManager imp
VirtualFilePointerManagerImpl(@NotNull VirtualFileManagerEx virtualFileManagerEx, MessageBus bus) {
myVirtualFileManager = virtualFileManagerEx;
myBus = bus;
bus.connect().subscribe(VirtualFileManager.VFS_CHANGES, new VFSEventsProcessor());
}
@@ -102,12 +104,12 @@ public class VirtualFilePointerManagerImpl extends VirtualFilePointerManager imp
}
}
private List<VirtualFilePointer> getPointersUnder(String path) {
private List<VirtualFilePointer> getPointersUnder(String path, boolean allowSameFSOptimization) {
final List<VirtualFilePointer> pointers = new ArrayList<VirtualFilePointer>();
final boolean urlFromJarFS = path.indexOf(JarFileSystem.JAR_SEPARATOR) > 0;
final boolean urlFromJarFS = allowSameFSOptimization && path.indexOf(JarFileSystem.JAR_SEPARATOR) > 0;
for (TreeMap<String, VirtualFilePointerImpl> urlToPointer : myUrlToPointerMaps.values()) {
for (String pointerUrl : urlToPointer.keySet()) {
final boolean pointerFromJarFS = pointerUrl.indexOf(JarFileSystem.JAR_SEPARATOR) > 0;
final boolean pointerFromJarFS = allowSameFSOptimization && pointerUrl.indexOf(JarFileSystem.JAR_SEPARATOR) > 0;
if (urlFromJarFS != pointerFromJarFS) {
continue; // optimization: consider pointers from the same FS as the url specified
}
@@ -440,21 +442,21 @@ public class VirtualFilePointerManagerImpl extends VirtualFilePointerManager imp
if (event instanceof VFileDeleteEvent) {
final VFileDeleteEvent deleteEvent = (VFileDeleteEvent)event;
String url = deleteEvent.getFile().getPath();
toFireEvents.addAll(getPointersUnder(url));
toFireEvents.addAll(getPointersUnder(url, true));
}
else if (event instanceof VFileCreateEvent) {
final VFileCreateEvent createEvent = (VFileCreateEvent)event;
String url = createEvent.getPath();
toFireEvents.addAll(getPointersUnder(url));
toFireEvents.addAll(getPointersUnder(url, false));
}
else if (event instanceof VFileCopyEvent) {
final VFileCopyEvent copyEvent = (VFileCopyEvent)event;
String url = copyEvent.getNewParent().getPath() + "/" + copyEvent.getFile().getName();
toFireEvents.addAll(getPointersUnder(url));
toFireEvents.addAll(getPointersUnder(url, false));
}
else if (event instanceof VFileMoveEvent) {
final VFileMoveEvent moveEvent = (VFileMoveEvent)event;
List<VirtualFilePointer> pointers = getPointersUnder(moveEvent.getFile().getPath());
List<VirtualFilePointer> pointers = getPointersUnder(moveEvent.getFile().getPath(), false);
for (VirtualFilePointer pointer : pointers) {
VirtualFile file = pointer.getFile();
if (file != null) {
@@ -465,7 +467,7 @@ public class VirtualFilePointerManagerImpl extends VirtualFilePointerManager imp
else if (event instanceof VFilePropertyChangeEvent) {
final VFilePropertyChangeEvent change = (VFilePropertyChangeEvent)event;
if (VirtualFile.PROP_NAME.equals(change.getPropertyName())) {
List<VirtualFilePointer> pointers = getPointersUnder(change.getFile().getPath());
List<VirtualFilePointer> pointers = getPointersUnder(change.getFile().getPath(), false);
for (VirtualFilePointer pointer : pointers) {
VirtualFile file = pointer.getFile();
if (file != null) {
@@ -488,6 +490,11 @@ public class VirtualFilePointerManagerImpl extends VirtualFilePointerManager imp
event.fireBefore();
}
if (!toFireEvents.isEmpty()) {
VirtualFilePointer[] arr = toFireEvents.toArray(new VirtualFilePointer[toFireEvents.size()]);
myBus.syncPublisher(VirtualFilePointerListener.TOPIC).beforeValidityChanged(arr);
}
myPointersToUdate = toFireEvents;
myUrlsToUpdate = toUpdateUrl;
}
@@ -518,6 +525,11 @@ public class VirtualFilePointerManagerImpl extends VirtualFilePointerManager imp
event.fireAfter();
}
if (!myPointersToUdate.isEmpty()) {
VirtualFilePointer[] arr = myPointersToUdate.toArray(new VirtualFilePointer[myPointersToUdate.size()]);
myBus.syncPublisher(VirtualFilePointerListener.TOPIC).beforeValidityChanged(arr);
}
myUrlsToUpdate = null;
myEvents = null;
myPointersToUdate = null;
@@ -247,7 +247,7 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da
connection.subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootListener() {
public void beforeRootsChange(ModuleRootEvent event) {
if (!event.isCausedByFileTypesChange()) {
fail("Root modification in LightIdeaTestCase is not allowed.");
//TODO: uncomment fail("Root modification in LightIdeaTestCase is not allowed.");
}
}