Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,25 @@ name: ci-build
on: [pull_request]

jobs:
verify_formatting:
runs-on: ubuntu-latest
name: Verify code formatting

steps:
- name: checkout-code
uses: actions/checkout@v3
with:
fetch-depth: 0

- name: setup-dotnet
uses: actions/setup-dotnet@v3

- name: tool restore
run: dotnet tool restore

- name: validate formatting
run: dotnet fantomas . --check

build:
name: Build
runs-on: windows-latest
Expand All @@ -12,9 +31,11 @@ jobs:
uses: actions/checkout@v3
with:
fetch-depth: 0

# setup dotnet based on global.json
- name: setup-dotnet
uses: actions/setup-dotnet@v3

# build it, test it, pack it
- name: Run dotnet build (release)
# see issue #105
Expand Down
10 changes: 7 additions & 3 deletions src/.editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ indent_size=4

# line length before it gets broken down into multiple lines
# default 120
max_line_length=120
max_line_length=140

# Either crlf | lf, default is system-dependent (when not specified at all)
# end_of_line=crlf
Expand Down Expand Up @@ -180,7 +180,7 @@ fsharp_array_or_list_multiline_formatter=character_width

# maximum with of a value binding, does not include keyword "let"
# default 80
fsharp_max_value_binding_width=100
fsharp_max_value_binding_width=140

# maximum width for function and member binding (rh-side)
# default 40
Expand Down Expand Up @@ -260,6 +260,10 @@ fsharp_bar_before_discriminated_union_declaration=false
# To work reliably, fsharp_multiline_block_brackets_on_same_column must be "true"
fsharp_experimental_stroustrup_style=true

# above setting is for Fantomas 5.x. The new version uses these two
fsharp_multiline_bracket_style = stroustrup
fsharp_newline_before_multiline_computation_expression = false

# from docs: Please do not use this setting for formatting hand written code!
# default false
fsharp_strict_mode=false
fsharp_strict_mode=false
12 changes: 2 additions & 10 deletions src/FSharp.Control.TaskSeq.Test/Nunit.Extensions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,7 @@ module ExtraCustomMatchers =
let private baseResultTypeTest value =
match value with
| null ->
EqualException.ForMismatchedValues(
"Result type",
"<null>",
"Value <null> or None is never Result.Ok or Result.Error"
)
EqualException.ForMismatchedValues("Result type", "<null>", "Value <null> or None is never Result.Ok or Result.Error")
|> raise

| _ ->
Expand All @@ -53,11 +49,7 @@ module ExtraCustomMatchers =
| "None" -> None
| _ ->
raise
<| EqualException.ForMismatchedValues(
"Option type",
ty.Name,
"Unexpected field name for F# option type"
)
<| EqualException.ForMismatchedValues("Option type", ty.Name, "Unexpected field name for F# option type")
else
EqualException.ForMismatchedValues("Option type", ty.Name, "Type must be Option<_>")
|> raise
Expand Down
2 changes: 1 addition & 1 deletion src/FSharp.Control.TaskSeq.Test/TaskSeq.Let.Tests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ let ``CE taskSeq: use 'let!' with all kinds of overloads at once`` () =
return value
}

let! b = // eq 2
let! b = // eq 2
task {
do! Task.Delay 50
do value <- value + 1
Expand Down
8 changes: 2 additions & 6 deletions src/FSharp.Control.TaskSeq.Test/TestUtils.fs
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,7 @@ type DummyTaskFactory(µsecMin: int64<µs>, µsecMax: int64<µs>) =
let rnd = Random()
let rnd () = rnd.NextInt64(int64 µsecMin, int64 µsecMax) * 1L<µs>

let runTaskDelayed () = backgroundTask {
return! DelayHelper.delayTask µsecMin µsecMax (fun _ -> Interlocked.Increment &x)
}
let runTaskDelayed () = backgroundTask { return! DelayHelper.delayTask µsecMin µsecMax (fun _ -> Interlocked.Increment &x) }

let runTaskDelayedImmutable i = backgroundTask { return! DelayHelper.delayTask µsecMin µsecMax (fun _ -> i + 1) }

Expand Down Expand Up @@ -513,9 +511,7 @@ module TestUtils =
yield! taskSeq {
yield! taskSeq {
yield! taskSeq {
yield! taskSeq {
yield! taskSeq { yield! taskSeq { yield! taskSeq { yield! nestedTaskSeq } } }
}
yield! taskSeq { yield! taskSeq { yield! taskSeq { yield! taskSeq { yield! nestedTaskSeq } } } }
}
}
}
Expand Down
6 changes: 1 addition & 5 deletions src/FSharp.Control.TaskSeq/TaskExtensions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,7 @@ module TaskExtensions =

/// Used by `For`. F# currently doesn't support `while!`, so this cannot be called directly from the task CE
/// This code is mostly a copy of TaskSeq.WhileAsync.
member inline _.WhileAsync
(
[<InlineIfLambda>] condition: unit -> ValueTask<bool>,
body: TaskCode<_, unit>
) : TaskCode<_, _> =
member inline _.WhileAsync([<InlineIfLambda>] condition: unit -> ValueTask<bool>, body: TaskCode<_, unit>) : TaskCode<_, _> =
let mutable condition_res = true

// note that this While itself has both a dynamic and static implementation
Expand Down
5 changes: 1 addition & 4 deletions src/FSharp.Control.TaskSeq/TaskSeq.fs
Original file line number Diff line number Diff line change
Expand Up @@ -265,10 +265,7 @@ module TaskSeq =

let exactlyOne source =
Internal.tryExactlyOne source
|> Task.map (
Option.defaultWith (fun () ->
invalidArg (nameof source) "The input sequence contains more than one element.")
)
|> Task.map (Option.defaultWith (fun () -> invalidArg (nameof source) "The input sequence contains more than one element."))

let indexed (source: taskSeq<'T>) =
Internal.checkNonNull (nameof source) source
Expand Down
7 changes: 2 additions & 5 deletions src/FSharp.Control.TaskSeq/TaskSeqBuilder.fs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ type TaskSeqStateMachineData<'T>() =
member data.PushDispose(disposer: unit -> Task) =
if isNull data.disposalStack then
data.disposalStack <- ResizeArray()

data.disposalStack.Add disposer

member data.PopDispose() =
Expand Down Expand Up @@ -389,11 +390,7 @@ type TaskSeqBuilder() =
ResumableCode.Combine(task1, task2)

/// Used by `For`. F# currently doesn't support `while!`, so this cannot be called directly from the CE
member inline _.WhileAsync
(
[<InlineIfLambda>] condition: unit -> ValueTask<bool>,
body: ResumableTSC<'T>
) : ResumableTSC<'T> =
member inline _.WhileAsync([<InlineIfLambda>] condition: unit -> ValueTask<bool>, body: ResumableTSC<'T>) : ResumableTSC<'T> =
let mutable condition_res = true

ResumableCode.While(
Expand Down
3 changes: 3 additions & 0 deletions src/FSharp.Control.TaskSeq/TaskSeqBuilder.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,10 @@ type TaskSeqBuilder =
member inline TryFinally: body: ResumableTSC<'T> * compensationAction: (unit -> unit) -> ResumableTSC<'T>
member inline TryFinallyAsync: body: ResumableTSC<'T> * compensationAction: (unit -> Task) -> ResumableTSC<'T>
member inline TryWith: body: ResumableTSC<'T> * catch: (exn -> ResumableTSC<'T>) -> ResumableTSC<'T>

member inline Using:
disp: 'Disp * body: ('Disp -> ResumableTSC<'T>) -> ResumableTSC<'T> when 'Disp :> IAsyncDisposable

member inline While: condition: (unit -> bool) * body: ResumableTSC<'T> -> ResumableTSC<'T>
/// Used by `For`. F# currently doesn't support `while!`, so this cannot be called directly from the CE
member inline WhileAsync: condition: (unit -> ValueTask<bool>) * body: ResumableTSC<'T> -> ResumableTSC<'T>
Expand Down Expand Up @@ -179,6 +181,7 @@ module MediumPriority =
// NOTE: syntax with '#Disposable' won't work properly in FSI
member inline Using:
dispensation: 'Disp * body: ('Disp -> ResumableTSC<'T>) -> ResumableTSC<'T> when 'Disp :> IDisposable

member inline For: sequence: seq<'TElement> * body: ('TElement -> ResumableTSC<'T>) -> ResumableTSC<'T>
member inline YieldFrom: source: seq<'T> -> ResumableTSC<'T>
member inline For: source: #taskSeq<'TElement> * body: ('TElement -> ResumableTSC<'T>) -> ResumableTSC<'T>
Expand Down
6 changes: 3 additions & 3 deletions src/FSharp.Control.TaskSeq/TaskSeqInternal.fs
Original file line number Diff line number Diff line change
Expand Up @@ -120,15 +120,15 @@ module internal TaskSeqInternal =
i <- i + 1 // update before moving: we are counting, not indexing
go <- step

| Some (Predicate predicate) ->
| Some(Predicate predicate) ->
while go do
if predicate e.Current then
i <- i + 1

let! step = e.MoveNextAsync()
go <- step

| Some (PredicateAsync predicate) ->
| Some(PredicateAsync predicate) ->
while go do
match! predicate e.Current with
| true -> i <- i + 1
Expand Down Expand Up @@ -197,7 +197,7 @@ module internal TaskSeqInternal =
// multiple threads access the same item through the same enumerator (which is
// bad practice, but hey, who're we to judge).
if isNull value then
value <- Lazy<_>.Create (fun () -> init i)
value <- Lazy<_>.Create(fun () -> init i)

yield value.Force()
value <- Unchecked.defaultof<_>
Expand Down
27 changes: 12 additions & 15 deletions src/FSharp.Control.TaskSeq/Utils.fs
Original file line number Diff line number Diff line change
Expand Up @@ -74,18 +74,16 @@ module Task =
:> Task

/// Map a Task<'T>
let inline map mapper (task: Task<'T>) : Task<'U> =
TaskBuilder.task {
let! result = task
return mapper result
}
let inline map mapper (task: Task<'T>) : Task<'U> = TaskBuilder.task {
let! result = task
return mapper result
}

/// Bind a Task<'T>
let inline bind binder (task: Task<'T>) : Task<'U> =
TaskBuilder.task {
let! t = task
return! binder t
}
let inline bind binder (task: Task<'T>) : Task<'U> = TaskBuilder.task {
let! t = task
return! binder t
}

/// Create a task from a value
let inline fromResult (value: 'U) : Task<'U> = TaskBuilder.task { return value }
Expand All @@ -107,11 +105,10 @@ module Async =
}

/// Map an Async<'T>
let inline map mapper (async: Async<'T>) : Async<'U> =
ExtraTopLevelOperators.async {
let! result = async
return mapper result
}
let inline map mapper (async: Async<'T>) : Async<'U> = ExtraTopLevelOperators.async {
let! result = async
return mapper result
}

/// Bind an Async<'T>
let inline bind binder (task: Async<'T>) : Async<'U> = ExtraTopLevelOperators.async { return! binder task }