AST-based modification of turbo.json (#5509)
When we run `link` and `unlink` we want those commands to create the
smallest set of changes possible in the output while also accounting for
edge cases like multiple definition.
This PR adds an AST-aware JSON-rewriter that modifies the file contents
rather than attempting to deserialize and reserialize the entire
document (which would otherwise be lossy unless deserialized to a
concrete syntax tree).
The only implementation of a concrete syntax tree for JSON in the Rust
ecosystem appears to be
https://github.com/rome/tools/tree/main/crates/rome_json_parser which
presently lexes `jsonc`, but does not link it into the rest of the
parser. There is an open, abandoned PR for that effort:
https://github.com/rome/tools/pull/4382
After review, I decided that the additional complexity and size of
pulling in the entire Rome parsing toolchain was not going to be
worthwhile at this time for a task this small in scope.
I investigated `pest` as an alternative, but grammar correctness edge
cases for JSON are not great, and the whitespace and comment macros in
the `pest` grammar would have to be hand-implemented. I elected against
this for low confidence in a toy parser.
Eventually I chose to use `jsonc_parser` which doesn't actually create
all of the necessary tokens, but using conservative patterns on top of
the limited information I can ensure that it doesn't _fail_. However,
this greatly limits the formatting abilities that we can accomplish. I
decided this was an acceptable tradeoff for complexity, total effort,
dep size, scope of use (just `link` and `unlink` setting one property).
Additional output formatting improvements are out-of-scope for this PR.
This generates assuredly parseable content, but makes no guarantees as
to what the output format looks like.
---------
Co-authored-by: Nathan Hammond <Nathan Hammond>