Skip to content

Commit

Permalink
Merge pull request #3745 from nojaf/list-collector
Browse files Browse the repository at this point in the history
ListCollector
  • Loading branch information
MangelMaxime committed Feb 9, 2024
2 parents bb09d11 + 320819b commit e09608f
Show file tree
Hide file tree
Showing 8 changed files with 84 additions and 1 deletion.
8 changes: 8 additions & 0 deletions src/Fable.Cli/CHANGELOG.md
Expand Up @@ -27,6 +27,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* `Result.ToList`
* `Result.ToOption`

#### JavaScript

* [GH-3745](https://github.com/fable-compiler/Fable/pull/3745) Add support for `ListCollector` (by @nojaf)
* `instance.Add`
* `instance.AddMany`
* `instance.AddManyAndClose`
* `instance.Close`

### Removed

#### JavaScript
Expand Down
1 change: 0 additions & 1 deletion src/Fable.Transforms/Replacements.Util.fs
Expand Up @@ -322,7 +322,6 @@ let (|BuiltinDefinition|_|) =
| Types.dateOnly -> Some BclDateOnly
| Types.timeOnly -> Some BclTimeOnly
| "System.Timers.Timer" -> Some BclTimer
| Types.decimal
| Types.fsharpSet -> Some(FSharpSet(Any))
| Types.fsharpMap -> Some(FSharpMap(Any, Any))
| Types.hashset -> Some(BclHashSet(Any))
Expand Down
3 changes: 3 additions & 0 deletions src/Fable.Transforms/Replacements.fs
Expand Up @@ -1148,6 +1148,8 @@ let tryEntityIdent (com: Compiler) entFullName =
makeImportLib com Any "AsyncReplyChannel" "AsyncBuilder" |> Some
| "Microsoft.FSharp.Control.FSharpEvent`1" -> makeImportLib com Any "Event" "Event" |> Some
| "Microsoft.FSharp.Control.FSharpEvent`2" -> makeImportLib com Any "Event$2" "Event" |> Some
| "Microsoft.FSharp.Core.CompilerServices.ListCollector`1" ->
makeImportLib com Any "ListCollector$1" "FSharp.Core.CompilerServices" |> Some
| _ -> None

let tryConstructor com (ent: Entity) =
Expand Down Expand Up @@ -4566,6 +4568,7 @@ let private replacedModules =
"Microsoft.FSharp.Collections.ListModule", listModule
"Microsoft.FSharp.Collections.HashIdentity", fsharpModule
"Microsoft.FSharp.Collections.ComparisonIdentity", fsharpModule
"Microsoft.FSharp.Core.CompilerServices.ListCollector`1", bclType
"Microsoft.FSharp.Core.CompilerServices.RuntimeHelpers", seqModule
"Microsoft.FSharp.Collections.SeqModule", seqModule
Types.keyValuePair, keyValuePairs
Expand Down
17 changes: 17 additions & 0 deletions src/fable-library/FSharp.Core.CompilerServices.fs
@@ -0,0 +1,17 @@
namespace Microsoft.FSharp.Core.CompilerServices

[<NoEquality; NoComparison>]
type ListCollector<'T>() =
let collector = ResizeArray<'T>()

member this.Add(value: 'T) = collector.Add(value)

member this.AddMany(values: seq<'T>) = collector.AddRange(values)

// In the particular case of closing with a final add of an F# list
// we can simply stitch the list into the end of the resulting list
member this.AddManyAndClose(values: seq<'T>) =
collector.AddRange(values)
Seq.toList collector

member this.Close() = Seq.toList collector
1 change: 1 addition & 0 deletions src/fable-library/Fable.Library.fsproj
Expand Up @@ -33,6 +33,7 @@
<Compile Include="Random.fs" />
<Compile Include="Set.fs" />
<Compile Include="Map.fs" />
<Compile Include="FSharp.Core.CompilerServices.fs" />
<TypeScriptCompile Include="Async.ts" />
<TypeScriptCompile Include="AsyncBuilder.ts" />
<TypeScriptCompile Include="BitConverter.ts" />
Expand Down
1 change: 1 addition & 0 deletions tests/Js/Main/Fable.Tests.fsproj
Expand Up @@ -78,6 +78,7 @@
<Compile Include="UriTests.fs" />
<Compile Include="TimeOnlyTests.fs" />
<Compile Include="TimeSpanTests.fs" />
<Compile Include="ListCollectorTests.fs" />
<Compile Include="Main.fs" />
</ItemGroup>

Expand Down
53 changes: 53 additions & 0 deletions tests/Js/Main/ListCollectorTests.fs
@@ -0,0 +1,53 @@
module Fable.Tests.ListCollector

open Util.Testing
open Microsoft.FSharp.Core.CompilerServices

let cutOffLast list =
let mutable headList = ListCollector<'a>()

let rec visit list =
match list with
| []
| [ _ ] -> ()
| head :: tail ->
headList.Add(head)
visit tail

visit list
headList.Close()

let tests =
testList "ListCollector" [
testCase "ListCollector.Add and .Close" <| fun () ->
let result = cutOffLast [ 1; 2; 3 ]
result |> equal [ 1; 2 ]

testCase "ListCollector.Close works for empty list" <| fun () ->
let mutable l = ListCollector<_>()
let result = l.Close()

result |> equal []

testCase "ListCollector.AddMany works" <| fun () ->
let mutable l = ListCollector<_>()
l.AddMany([ 1; 2; 3 ])

let result = l.Close()

result |> equal [ 1; 2; 3 ]

testCase "ListCollector.AddMany works for empty list" <| fun () ->
let mutable l = ListCollector<_>()
l.AddMany([])

let result = l.Close()

result |> equal []

testCase "ListCollector.AddManyAndClose works" <| fun () ->
let mutable l = ListCollector<_>()
let result = l.AddManyAndClose([ 1; 2; 3 ])

result |> equal [ 1; 2; 3 ]
]
1 change: 1 addition & 0 deletions tests/Js/Main/Main.fs
Expand Up @@ -50,6 +50,7 @@ let allTests =
TypeTests.tests
UnionTypes.tests
Uri.tests
ListCollector.tests
|]

#if FABLE_COMPILER
Expand Down

0 comments on commit e09608f

Please sign in to comment.