willsam100 / FShaper

FShaper - a tool to make the process of converting C# to F# much easier
MIT License
44 stars 11 forks source link

Support async/await #2

Open willsam100 opened 5 years ago

willsam100 commented 5 years ago

C# has native support for async/await, F# has async computation expressions. It should be possible to get close:

Thorium commented 5 years ago

I also recommend generated async { ... } to end with |> Async.StartAsTask because some frameworks like WCF / SignalR / ... supports Task by default where as they don't await F# asyncs.

willsam100 commented 5 years ago

@Thorium very good point. I have done this with the tests below.

I do wonder if supporting conversion to TaskBuilder would be better as it should be better performance, or to wait for native task support

Passing tests (more coverage may be needed):

[<Test>]
member this.``async no await writes as normal method`` () = 
    let csharp = 
         """public async void Foo ()
            {
                return;
            }"""

    let fsharp = 
         """member this.Foo() = ()"""

    csharp |> Converter.run 
    |> should equal (formatFsharp fsharp)

[<Test>]
member this.``async with await writes as async computation method`` () = 
    let csharp = 
         """public async void Foo ()
            {
                await Bar.WriteAsync();
            }"""

    let fsharp = 
         """member this.Foo() = async { do! Bar.WriteAsync() |> Async.AwaitTask } |> Async.StartAsTask"""

    csharp |> Converter.run 
    |> should equal (formatFsharp fsharp)

[<Test>]
member this.``await writes as async with let! in async computation`` () = 
    let csharp = 
         """public async void Foo ()
            {
                var x = await Bar.WriteAsync();
                return x;
            }"""

    let fsharp = 
         """member this.Foo() = async { return Bar.WriteAsync() |> Async.AwaitTask } |> Async.StartAsTask"""

    csharp |> Converter.run 
    |> should equal (formatFsharp fsharp)

[<Test>]
member this.``await writes as async with multiple let!`` () = 
    let csharp = 
         """public async void Foo ()
            {
                var x = await Bar.GetX();
                var y = await Baz.GetY();
                return x + y;
            }"""

    let fsharp = 
         """member this.Foo() = async { let! x = Bar.GetX() |> Async.AwaitTask
                                        let! y = Baz.GetY() |> Async.AwaitTask
                                        return x + y } |> Async.StartAsTask"""

    csharp |> Converter.run 
    |> should equal (formatFsharp fsharp)