(#21307) Pull apart many parts of logic for WatchedFile

The WatchedFile class had several intertwined pieces of logic: when to
update, what a changed file is, when a changed isn't yet known. This
unravels it into individual parts. Overall the code got larger, but the
pieces are more specialized now and have a name that calls out what is
being done.

Because WatchedFile has been stripped down to a simple integration of
components it is no longer tested by itself.