private synchronized void assertAllPointersDisposed() { for (Map.Entry<VirtualFilePointerListener, FilePointerPartNode> entry : myPointers.entrySet()) { FilePointerPartNode root = entry.getValue(); ArrayList<FilePointerPartNode> left = new ArrayList<FilePointerPartNode>(); root.getPointersUnder(null, false, "", left); if (!left.isEmpty()) { VirtualFilePointerImpl p = left.get(0).leaf; try { p.throwDisposalError("Not disposed pointer: " + p); } finally { for (FilePointerPartNode pair : left) { VirtualFilePointerImpl pointer = pair.leaf; pointer.dispose(); } } } } synchronized (myContainers) { if (!myContainers.isEmpty()) { VirtualFilePointerContainerImpl container = myContainers.iterator().next(); container.throwDisposalError("Not disposed container"); } } }
@Override public void after(@NotNull final List<? extends VFileEvent> events) { incModificationCount(); for (FilePointerPartNode node : myPointersToUpdateUrl) { synchronized (this) { VirtualFilePointerImpl pointer = node.leaf; String urlBefore = pointer.getUrlNoUpdate(); Pair<VirtualFile, String> after = node.update(); String urlAfter = after.second; if (URL_COMPARATOR.compare(urlBefore, urlAfter) != 0) { // url has changed, reinsert FilePointerPartNode root = myPointers.get(pointer.getListener()); int useCount = node.useCount; node.remove(); FilePointerPartNode newNode = root.findPointerOrCreate(VfsUtilCore.urlToPath(urlAfter), 0, after); VirtualFilePointerImpl existingPointer = newNode.leaf; if (existingPointer != null) { // can happen when e.g. file renamed to the existing file // merge two pointers pointer.myNode = newNode; } else { newNode.associate(pointer, after); } newNode.incrementUsageCount(useCount); } } } VirtualFilePointer[] pointersToFireArray = toPointers(myPointersToFire); for (VirtualFilePointer pointer : pointersToFireArray) { ((VirtualFilePointerImpl) pointer).myNode.update(); } for (EventDescriptor event : myEvents) { event.fireAfter(); } if (pointersToFireArray.length != 0) { myBus.syncPublisher(VirtualFilePointerListener.TOPIC).validityChanged(pointersToFireArray); } myPointersToUpdateUrl = Collections.emptyList(); myEvents = Collections.emptyList(); myPointersToFire = Collections.emptyList(); for (FilePointerPartNode root : myPointers.values()) { root.checkConsistency(); } }
@TestOnly public void assertPointersAreDisposed() { List<VirtualFilePointerImpl> pointers = new ArrayList<VirtualFilePointerImpl>(); addAllPointers(pointers); try { for (VirtualFilePointerImpl pointer : pointers) { if (!myStoredPointers.contains(pointer)) { pointer.throwDisposalError("Virtual pointer hasn't been disposed: " + pointer); } } } finally { myStoredPointers.clear(); } }
@Override public void dispose() { synchronized (ourInstances) { ourInstances.remove(myParent); for (Object o : myCounts.keys()) { VirtualFilePointerImpl pointer = (VirtualFilePointerImpl) o; int disposeCount = myCounts.get(pointer); int after = pointer.myNode.incrementUsageCount(-disposeCount + 1); LOG.assertTrue(after > 0, after); pointer.dispose(); } } }