fsprojects / fantomas

FSharp source code formatter
https://fsprojects.github.io/fantomas
Other
772 stars 194 forks source link

Question: Custom computation expressions sometimes formatted incorrectly #315

Closed zakaluka closed 4 years ago

zakaluka commented 6 years ago

Hello,

I am trying the latest Fantomas on the default SAFE stack template, using Saturn. For the most part, it is formatting the code well. However, Saturn uses a number of custom computation expressions, and Fantomas is behaving very oddly.

I am seeing 2 issues.

First question has to do with how the following code block is reformatted. By default, Server.fs contains the following block of code:

let webApp = router {
    get "/api/init" (fun next ctx ->
        task {
            let! counter = getInitCounter()
            return! Successful.OK counter next ctx
        })
}

I ran the file through the Fantomas command-line utility (no options), and it changed to the following:

let webApp =
    router
        {
        get "/api/init"
            (fun next ctx -> task { let! counter = getInitCounter()
                                    return! Successful.OK counter next ctx }) }

While I understand some of the behavior, I don't understand why router and { are on separate lines. From looking at the computation expression tests https://github.com/fsprojects/fantomas/blob/master/src/Fantomas.Tests/ComputationExpressionTests.fs, it should have looked like router {.

On a positive note, it didn't indent the get call any further.

PLEASE SEE #339 FOR MORE INFORMATION ABOUT THE FOLLOWING ISSUE. Second question is about when I format through the Fantomas library and FAKE. I am seeing the following error message when I try to run the Server.fs file through checkCode.

D:\projects\ZenCase\src\Client\Client.fs:
Unable to cast object of type 'YieldOrReturn' to type 'YieldOrReturnFrom'.

D:\projects\ZenCase\src\Server\Server.fs:
Unable to cast object of type 'YieldOrReturn' to type 'YieldOrReturnFrom'.

The following files aren't formatted properly:
- D:\projects\ZenCase\src\Client\AssemblyInfo.fs
- D:\projects\ZenCase\src\Client\Client.fs !
- D:\projects\ZenCase\src\Migration\AssemblyInfo.fs
- D:\projects\ZenCase\src\Migration\Constants.fs
- D:\projects\ZenCase\src\Migration\Migration.fs
- D:\projects\ZenCase\src\Server\AssemblyInfo.fs
- D:\projects\ZenCase\src\Server\Server.fs !
- D:\projects\ZenCase\src\Shared\Shared.fs
- D:\projects\ZenCase\src\Shared\Utility.fs)

If I comment out all the computation expressions in Server.fs, then that error goes away. However, any computation express in Server.fs causes the error to be printed out. Because of this, I'm concerned about running Server.fs through formatCode.

I even tried leaving only one computation expression Server.fs:

let getInitCounter() : Task<Counter> = task { return 42 }

Based on what I saw in Fantomas, this is a YieldOrReturn. I still get the same error message. Why is Fantomas trying to change this to YieldOrReturnFrom (aka return!)?

jindraivanek commented 6 years ago

1) I can confirm this, @zakaluka please create seperate issue with this snippet. It doesn't happen for each CE, my guess is it is connected to multiline expr as first thing in CE.

2) Also confirmed. It can be reproduced wtih this FAKE5 script:

#r "paket: nuget Fantomas"
#load ".fake/test-FAKE5.fsx/intellisense.fsx"

let mkTempFile source =
    let fileName = System.IO.Path.GetTempFileName() + ".fs"
    System.IO.File.WriteAllText(fileName, source)
    fileName

let source = "let getInitCounter() : Task<Counter> = task { return 42 }"

let path = mkTempFile source

Fantomas.CodeFormatter.FormatDocument(path, System.IO.File.ReadAllText(path), Fantomas.FormatConfig.FormatConfig.Default)

System.IO.File.Delete path

It's weird because with CLI this code will be formatted without problem.

jindraivanek commented 6 years ago

While working on http://ratatosk.dynu.net/fantomas/, I encounter second issue. Turns out it is caused by different versions of FSharp.Compiler.Service. Fantomas use 23.0.3, but when you use Fantomas as lib dependency, newer one is used (25.0.1) and it cause these issues.

Workaround is to use matching version of FSharp.Compiler.Service, this header of above script works:

#r "paket: nuget Fantomas
nuget FSharp.Compiler.Service 23.0.3"

Another option is to use

#r "paket: strategy: min 
nuget Fantomas"

I think we have two options how to fix this:

1) upgrade FSharp.Compiler.Service to 25.0.1. That will force everyone who is using Fantomas as lib to also upgrade. Not sure if that is OK. 2) change FSharp.Compiler.Service dependency in nuget to be exactly 23.0.3 (now is >=23.0.3). That would probably needs to change way of how we are creating nuget package, I wasn't able to find a way how to do it by dotnet pack parameter. It should be doable with paket pack.

I would prefer option 1.

zakaluka commented 6 years ago

I have created a separate issue #339 to deal with the second issue presented above (YieldOrReturn to YieldOrReturnFrom).

zakaluka commented 5 years ago

Link to incorrect formatting: http://ratatosk.dynu.net/fantomas/#?code=DYUwLgBA7iBGCCAHREC8EBOB7ArmEGEA3gLABQElEA5uBAEQD0AhogJaNsB2bY9EACgBmOLhC4gAHpADGYSRAC0APnJV1EMMwDOAa2JqNR0GACEEGbi75C6WmACSPMAGErNgQEpDR9RnA4GFzmAMo4MjIg2toiwAB0APIA0hbuBOJSsvI+GgC+3mS55EA&config=N4IgkgdgJgphAuBlADgQwMYwHIFcC2IAXACwA0IACqgOYwDqAllPABZEAcADORQE4wBnGLwBuMAKLQA8gDMAMgwgwiM1ABsh5RDDwN0AezX6IAQXiSoshUpXrNIFBhgAhGDP38Tvavjjwi8Lw4MFpomK7u-ADChsYBQSEOYTAmMvDCMXh4qPHBoU6p6bzaugZGELmJkLAIUhAAKrwAnoysthqJAEowHrC8UshwACIw6GqovKjwDHGEqh35mF76ONAjagy6RZVagXrwALL6sO1CAL5AA

nojaf commented 4 years ago

I think this is no longer an issue (see example). Please open a new issue if this is not the case.