@TestOnly
 public int countPointers() {
   int result = 0;
   for (TreeMap<String, VirtualFilePointerImpl> map : myUrlToPointerMaps.values()) {
     result += map.values().size();
   }
   return result;
 }
 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()) {
     myUrlToPointerMaps.remove(listener);
   }
 }
  public synchronized void assertPointersDisposed() {
    for (Map.Entry<VirtualFilePointerListener, TreeMap<String, VirtualFilePointerImpl>> entry :
        myUrlToPointerMaps.entrySet()) {
      VirtualFilePointerListener listener = entry.getKey();
      TreeMap<String, VirtualFilePointerImpl> map = entry.getValue();
      for (VirtualFilePointerImpl pointer : map.values()) {
        myUrlToPointerMaps.clear();
        pointer.throwNotDisposedError("Not disposed pointer: listener=" + listener);
      }
    }

    synchronized (myContainers) {
      if (!myContainers.isEmpty()) {
        VirtualFilePointerContainerImpl container = myContainers.iterator().next();
        myContainers.clear();
        throw new RuntimeException("Not disposed container " + container);
      }
    }
  }
  private synchronized VirtualFilePointerImpl getOrCreate(
      VirtualFile file,
      @NotNull String url,
      Disposable parentDisposable,
      @Nullable VirtualFilePointerListener listener,
      String path) {
    TreeMap<String, VirtualFilePointerImpl> urlToPointer = myUrlToPointerMaps.get(listener);
    if (urlToPointer == null) {
      urlToPointer = new TreeMap<String, VirtualFilePointerImpl>(COMPARATOR);
      myUrlToPointerMaps.put(listener, urlToPointer);
    }
    VirtualFilePointerImpl pointer = urlToPointer.get(path);

    if (pointer == null) {
      pointer =
          new VirtualFilePointerImpl(file, url, myVirtualFileManager, listener, parentDisposable);
      urlToPointer.put(path, pointer);
    }
    return pointer;
  }
 private void addPointersUnder(
     String path, boolean allowSameFSOptimization, List<VirtualFilePointer> pointers) {
   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 =
           allowSameFSOptimization && pointerUrl.indexOf(JarFileSystem.JAR_SEPARATOR) > 0;
       if (urlFromJarFS != pointerFromJarFS) {
         continue; // optimization: consider pointers from the same FS as the url specified
       }
       if (startsWith(path, pointerUrl)) {
         VirtualFilePointer pointer = urlToPointer.get(pointerUrl);
         if (pointer != null) {
           pointers.add(pointer);
         }
       }
     }
   }
 }
    @Override
    public void after(@NotNull final List<? extends VFileEvent> events) {
      cleanContainerCaches();

      if (myUrlsToUpdate == null) {
        return;
      }
      for (String url : myUrlsToUpdate) {
        synchronized (VirtualFilePointerManagerImpl.this) {
          for (TreeMap<String, VirtualFilePointerImpl> urlToPointer : myUrlToPointerMaps.values()) {
            VirtualFilePointerImpl pointer = urlToPointer.remove(url);
            if (pointer != null) {
              String path = VfsUtil.urlToPath(pointer.getUrl());
              urlToPointer.put(path, pointer);
            }
          }
        }
      }

      for (VirtualFilePointer pointer : myPointersToUpdate) {
        ((VirtualFilePointerImpl) pointer).update();
      }

      for (EventDescriptor event : myEvents) {
        event.fireAfter();
      }

      if (!myPointersToUpdate.isEmpty()) {
        VirtualFilePointer[] arr =
            myPointersToUpdate.toArray(new VirtualFilePointer[myPointersToUpdate.size()]);
        myBus.syncPublisher(VirtualFilePointerListener.TOPIC).validityChanged(arr);
      }

      myUrlsToUpdate = null;
      myEvents = null;
      myPointersToUpdate = null;
    }