public synchronized void addChild(@NotNull VirtualFileSystemEntry child) {
    VirtualFileSystemEntry[] array = myChildren;
    final String childName = child.getName();
    final boolean ignoreCase = !getFileSystem().isCaseSensitive();
    long r = findIndexInBoth(array, getComparator(childName, ignoreCase));
    int indexInReal = (int) (r >> 32);
    int indexInAdopted = (int) r;

    if (indexInAdopted >= 0) {
      // remove Adopted first
      removeFromArray(indexInAdopted);
    }
    if (indexInReal < 0) {
      insertChildAt(child, indexInReal);
    }
    // else already stored
    assertConsistency(myChildren, ignoreCase, child);
  }
 @Override
 public String fun(VirtualFileSystemEntry file) {
   //noinspection HardCodedStringLiteral
   return file
       + " (name: '"
       + file.getName()
       + "', "
       + file.getClass()
       + ", parent: "
       + file.getParent()
       + "; id: "
       + file.getId()
       + "; FS: "
       + file.getFileSystem()
       + "; delegate.attrs: "
       + file.getFileSystem().getAttributes(file)
       + "; caseSensitive: "
       + file.getFileSystem().isCaseSensitive()
       + "; canonical: "
       + file.getFileSystem().getCanonicallyCasedName(file)
       + ") ";
 }
  private void assertConsistency(
      @NotNull VirtualFileSystemEntry[] array, boolean ignoreCase, @NotNull Object... details) {
    if (!CHECK) return;
    boolean allChildrenLoaded = allChildrenLoaded();
    for (int i = 0; i < array.length; i++) {
      VirtualFileSystemEntry file = array[i];
      boolean isAdopted = isAdoptedChild(file);
      assert !isAdopted || !allChildrenLoaded;
      if (isAdopted && i != array.length - 1) {
        assert isAdoptedChild(array[i + 1]);
      }
      if (i != 0) {
        VirtualFileSystemEntry prev = array[i - 1];
        String prevName = prev.getName();
        int cmp = file.compareNameTo(prevName, ignoreCase);
        if (cmp == 0) {
          error(
              verboseToString.fun(prev) + " equals to " + verboseToString.fun(file),
              array,
              details);
        }

        if (isAdopted == isAdoptedChild(prev)) {
          if (cmp <= 0) {
            error(
                "Not sorted: "
                    + verboseToString.fun(prev)
                    + " is not less than "
                    + verboseToString.fun(file),
                array,
                details);
          }
        }
      }
    }
  }
  private void assertConsistency(
      @NotNull VirtualFileSystemEntry[] array, boolean ignoreCase, @NotNull Object... details) {
    if (!CHECK) return;
    boolean allChildrenLoaded = allChildrenLoaded();
    for (int i = 0; i < array.length; i++) {
      VirtualFileSystemEntry file = array[i];
      boolean isAdopted = isAdoptedChild(file);
      assert !isAdopted || !allChildrenLoaded;
      if (isAdopted && i != array.length - 1) {
        assert isAdoptedChild(array[i + 1]);
      }
      if (i != 0) {
        VirtualFileSystemEntry prev = array[i - 1];
        String prevName = prev.getName();
        int cmp = file.compareNameTo(prevName, ignoreCase);
        if (cmp == 0) {
          Function<VirtualFileSystemEntry, String> verboseToString =
              new Function<VirtualFileSystemEntry, String>() {
                @Override
                public String fun(VirtualFileSystemEntry entry) {
                  return entry
                      + " (name: '"
                      + entry.getName()
                      + "', "
                      + entry.getClass()
                      + ", parent:"
                      + entry.getParent()
                      + "; id:"
                      + entry.getId()
                      + "; FS:"
                      + entry.getFileSystem()
                      + "; delegate.attrs:"
                      + entry.getFileSystem().getAttributes(entry)
                      + "; caseSensitive:"
                      + entry.getFileSystem().isCaseSensitive()
                      + "; canonical:"
                      + entry.getFileSystem().getCanonicallyCasedName(entry)
                      + ") ";
                }
              };
          String children = StringUtil.join(array, verboseToString, ",");
          throw new AssertionError(
              verboseToString.fun(prev)
                  + " equals to "
                  + verboseToString.fun(file)
                  + "; children: "
                  + children
                  + "\nDetails: "
                  + ContainerUtil.map(
                      details,
                      new Function<Object, Object>() {
                        @Override
                        public Object fun(Object o) {
                          return o instanceof Object[] ? Arrays.toString((Object[]) o) : o;
                        }
                      }));
        }

        if (isAdopted == isAdoptedChild(prev)) {
          assert cmp > 0 : "Not sorted. " + Arrays.toString(details);
        }
      }
    }
  }