2b9981a2

By: Tom Sydney Kerckhove <syd@cs-syd.eu>

Typed paths, so a path that names nothing cannot be built

packageFactsDir serialised as hopinion/. because a package directory was
joined out of two strings, and it was then handed to wholeFileSpan, which
wants a file. Both mistakes are now type errors.

RelPath wraps Path Rel File. SourceRoot carries Path Abs Dir and Maybe (Path
Rel Dir), where Nothing is a repository whose paths are already relative to it
rather than an empty string that gets joined in anyway. Discovery, module
resolution and the stray-file walk all work in typed paths, and the one place
that turns what a person typed into a path the tool can join is the command
layer, where the IO to resolve it belongs.

packageFactsDir becomes packageFactsCabal. A package has no single file, so
the no-gen-package abstention used to point at a directory; it points at the
cabal file now, which is both a real file and where a reader would look for
the gen package that is not there.

Zero-width spans are widened to their line at render time, which is where the
line length is known. A whole-file span used to render as a marker with
nothing under it, sitting in a committed golden looking broken.

The refactor found a bug the typing did not: walking a source directory a
cabal file declares and the tree does not have used to be an exception rather
than an empty answer, which killed the run on sydtest. There is a resource and
a test for it now, and the test fails without the guard.

factsForFile splits into itself and factsForSource, so the ormolu invariance
test can ask what a reformatted module attaches to without writing it to a
temporary file first.

TemplateHaskell joins the hlint allowlist for path's mkRelFile, which is how a
path literal is checked at compile time rather than parsed at runtime and
hoped about.

Suite timing

Time to Start Worker time Duration Time to finish Idle
Config 0s 1s 1s 1s 0s
Eval 1s 24s 24s 25s 0s
Build 4s 42s 23s 27s 0s
Suite 0s 1m08s 27s 27s 0s

Timeline

0s10s20s