static TreeHashResult computeElementHashForIndexing(AbstractTreeHasher base,
                                                      FragmentsCollector callBack,
                                                      PsiElement root,
                                                      PsiFragment upper,
                                                      NodeSpecificHasher hasher
  ) {
    final List<PsiElement> children = hasher.getNodeChildren(root);
    final PsiFragment fragment = base.buildFragment(hasher, root, base.getCost(root));

    if (upper != null) {
      fragment.setParent(upper);
    }

    final int size = children.size();
    if (size == 0 && !(root instanceof LeafElement)) {
      // contains only whitespaces and other unmeaning children
      return new TreeHashResult(0, hasher.getNodeCost(root), fragment);
    }

    final int discardCost = base.getDiscardCost(root);
    int c = hasher.getNodeCost(root);
    int h = hasher.getNodeHash(root);

    for (int i = 0; i < size; i++) {
      PsiElement child = children.get(i);
      final TreeHashResult res = base.hash(child, fragment, hasher);
      int childCost = res.getCost();
      c += childCost;
      if (childCost > discardCost || !base.ignoreChildHash(child)) {
        h += res.getHash();
      }
    }

    if (base.shouldAnonymize(root, hasher)) {
      h = 0;
    }

    if (callBack != null) {
      callBack.add(h, c, fragment);
    }

    return new TreeHashResult(h, c, fragment);
  }
static TreeHashResult computeElementHashForIndexing(AbstractTreeHasher base,
                                                      FragmentsCollector callBack,
                                                      PsiElement root,
                                                      PsiFragment upper,
                                                      NodeSpecificHasher hasher
  )