fslang-design icon indicating copy to clipboard operation
fslang-design copied to clipboard

[style-guide] Multiline type annotations

Open nojaf opened this issue 3 years ago • 0 comments

The current guidance doesn't explicitly state the best practice regarding multiline type annotations.

Abstractly put:

p: t

Where t is multiline or crossed the maximum line length.

I propose to simply indent t on the following line if these conditions are met.

p:
    t

Some examples to illustrate:

type ExprFolder<'State> =
    { exprIntercept: 
        ('State -> Expr -> 'State) -> ('State -> Expr -> 'State -> 'State -> Exp -> 'State }

let UpdateUI
    (theModel:
#if NETCOREAPP2_1
        ITreeModel
#else
        TreeModel
#endif
    )
    (info: FileInfo) =
    // code
    ()

let f
    (x:
        {|
            x: int
            y: AReallyLongTypeThatIsMuchLongerThan40Characters
        |})
    =
    x

I believe in practice, this won't show up that much. Nevertheless, the principle still holds and is consistent with other parts of the guide. It also does not introduce any vanity alignments.

Some further context can be found in https://github.com/fsprojects/fantomas/pull/2424#issuecomment-1230033101


Somewhat related, if t is placed on the next line, depending on what it is, it might still need alternate formatting to respect the max_line_length.

If t is a long tuple type, I would also split it onto multiline lines. Similar to how signature files are described in the guide.

p:
    a *
    b *
    c

Relevant example:

type Meh
  (
    input: 
        LongTupleItemTypeOneThing * 
        LongTupleItemTypeThingTwo * 
        LongTupleItemTypeThree * 
        LongThingFour * 
        LongThingFiveYow
  ) =
  class
  end

For lambda expression, in the bizarre case that the arguments cannot fit on the same line of the fun keyword, I would indent them on the next line.

fun 
   (a: t1)
   (b: t2) ->
    ()

Relevant example:

let useAddEntry () =
    fun
        (input:
            {| name: string
               amount: Amount
               isIncome: bool
               created: string |}) ->
         // foo
         bar ()

//cc @dsyme @josh-degraw

nojaf avatar Aug 30 '22 15:08 nojaf