matching method

Iterable<InspectNode> matching(
  1. String query
)

The node with id, or null.

Null rather than a nearest match on purpose. A structural id points at a position, and a caller that edited the demo between two calls is asking about a position that may now hold something else — answering with whatever moved into it would be a confident wrong answer. The caller re-reads the tree. Nodes whose type, description or semantics label contains query, case-insensitively.

What to reach for instead of reading a tree, and the measurement is lopsided enough to be worth stating: find "Watching" answers "what colour and size is that label" in 131 tokens where the whole tree is 19 500. It is also the way out of the treeRoot chicken-and-egg — an id is a position, so you needed a tree to get one, and now you do not.

The label is searched as well as the words, so find "Tab 1 of 2" reaches what Flutter says about a control rather than only what it draws.

Implementation

Iterable<InspectNode> matching(String query) sync* {
  var needle = query.toLowerCase();
  for (var node in nodes) {
    if (node.type.toLowerCase().contains(needle) ||
        (node.description?.toLowerCase().contains(needle) ?? false) ||
        (node.label?.toLowerCase().contains(needle) ?? false)) {
      yield node;
    }
  }
}