Description
I propose we support annotations in code to ignore certain sections from formatting. This is helpful for code known to trigger soundness bugs in Fantomas or sections that benefit from unusual formatting.
Looking at other formatters for inspiration, I see different annotations we could use for this:
- Prettier (JS) uses comments like
// prettier-ignore
to exclude the next AST element from formatting. I think this is clever, although it can take more effort to get right. - Rider, IDEA and Eclipse exclude sections between comments
// @formatter:off/on
. - Roslyn excludes sections between
#pragma warning disable/restore format
. In F# this could be a directive#format disable/restore
, but it'd raise a warning at compile time unless a language suggestion was made so the compiler recognises it. - A crude alternative could also be
#if !FANTOMAS ... #endif
.
The existing way Fantomas deals with this problem is by ignoring the entire file with .fantomasignore.
Pros and Cons
The advantage of making this adjustment to Fantomas is having an escape hatch for excluding small sections of code, specially to work around soundness bugs.
The disadvantage of making this adjustment to Fantomas is having to scan comments for annotations and track which nodes should be formatted. It could also interfact badly with existing soundness bugs around comments.
Examples
Using Prettier-like annotations and default settings. Before:
// fantomas-ignore
module Ignored =
let bar=2
let baz x = [x,2,3]
module Formatted =
let bar=2
let baz x = [x,2,3]
let ignoredPoint x y=
(* fantomas-ignore *){|X=x; Y=y|}
let point x y=
{|X=x; Y=y|}
After:
// fantomas-ignore
module Ignored =
let bar=2
let baz x = [x,2,3]
module Formatted =
let bar = 2
let baz x = [ x, 2, 3 ]
let ignoredPoint x y =
(* fantomas-ignore *) {|X=x; Y=y|}
let point x y = {| X = x; Y = y |}
The formatting of the syntax elements following fantomas-ignore
comments has been ignored. Open questions are whether inner let
/use
are counted as an element or only their binding part and what precedence does it have respect to F# operators.
Using Rider-style annotations and default settings. Before:
let normalizeIgnored key xs =
// @formatter:off
let firstValue = xs |> Seq.find (fun (y,v) -> y = key) |> snd
xs |> Seq.map (fun (y,v) -> (y, float v / firstValue) )
// @formatter:on
let normalize key xs =
let firstValue = xs |> Seq.find (fun (y,v) -> y = key) |> snd
xs |> Seq.map (fun (y,v) -> (y, float v / firstValue) )
After:
let normalizeIgnored key xs =
// @formatter:off
let firstValue = xs |> Seq.find (fun (y,v) -> y = key) |> snd
xs |> Seq.map (fun (y,v) -> (y, float v / firstValue) )
// @formatter:on
let normalize key xs =
let firstValue =
xs |> Seq.find (fun (y, v) -> y = key) |> snd
xs
|> Seq.map (fun (y, v) -> (y, float v / firstValue))
(Fantomas currently moves // @formatter:on
to the first column.) The formatting of nodes between formatter:off
and formatter:on
comments has been ignored. #format disable/restore
would behave similarly.
Extra information
Estimated cost (XS, S, M, L, XL, XXL): M/L, probably depends on which annotation syntax is chosen.
Affidavit (please submit!)
Please tick this by placing a cross in the box:
- I have read the Contribution Guidelines.
- I have searched both open and closed suggestions on this site and believe this is not a duplicate
Please tick all that apply:
- This is not a breaking change to Fantomas
- I would be willing to help implement and/or test this
- This suggestion is part of the Microsoft style guide (please add a link to section if so)
- This suggestion is part of the G-Research style guide (please add a link to section if so)