int removeUsagesBulk(@NotNull Set<? extends UsageNode> usages, @NotNull DefaultTreeModel treeModel) {
    ThreadingAssertions.assertEventDispatchThread();
    int removed = 0;
    synchronized (this) {
      List<MutableTreeNode> removedNodes = new SmartList<>();
      for (UsageNode usage : usages) {
        if (myChildren.remove(usage)) {
          removedNodes.add(usage);
          removed++;
        }
      }

      if (removed == 0) {
        for (GroupNode groupNode : getSubGroups()) {
          int delta = groupNode.removeUsagesBulk(usages, treeModel);
          if (delta > 0) {
            if (groupNode.getRecursiveUsageCount() == 0) {
              myChildren.remove(groupNode);
              removedNodes.add(groupNode);
            }
            removed += delta;
            if (removed == usages.size()) break;
          }
        }
      }
      if (!myChildren.isEmpty()) {
        removeNodesFromParent(treeModel, this, removedNodes);
      }
    }

    if (removed > 0) {
      myRecursiveUsageCount -= removed;
      if (myRecursiveUsageCount != 0) {
        treeModel.nodeChanged(this);
      }
    }

    return removed;
  }
int removeUsagesBulk(@NotNull Set<? extends UsageNode> usages, @NotNull DefaultTreeModel treeModel)