void (boolean fromRoot, @NotNull Set<? extends VirtualFile> updatedFiles) { boolean filtered = root.filter != null; SmartHashSet<Node> nodes = fromRoot || filtered ? null : new SmartHashSet<>(); root.children.forEach(child -> child.invalidateChildren(node -> { if (!updatedFiles.contains(node.file)) return true; if (filtered) { node.resetVisibility(); // because of moving within the same root for (Node parent = node.parent; parent != null; parent = parent.parent) { parent.visibility = null; } } if (nodes == null) return false; Node n = node.file.isDirectory() ? node : node.parent; if (n == null) return false; for (Node p = n.parent; p != null; p = p.parent) { if (nodes.contains(p)) return false; } nodes.add(n); return false; })); if (nodes != null) { nodes.forEach(node -> { TreePath path = pathToCustomNode(node, child -> child.parent); if (path != null) pathChanged(path); }); } else { root.valid = false; // need to reload content roots pathChanged(null); } }