Skip to content

Commit 0939e72

Browse files
authored
Merge PR #753 from webwarrior-ws/fix-rule-77
Add exception to AvoidSinglePipeOperator rule.
2 parents d703c55 + df8d631 commit 0939e72

File tree

3 files changed

+42
-5
lines changed

3 files changed

+42
-5
lines changed

docs/content/how-tos/rules/FL0077.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ Use of the pipe operator when only one invocation is employed.
1717
When the use of the pipe operator happens for a single invocation (instead of a multiple one, which would add a chain of them, usually staggered across
1818
many lines), it doesn't aid readibility.
1919

20+
This rule does not apply to functions with more than one argument. The reason for that is primarily application of higher-order functions
21+
such as `map` or `iter`, for which type inference may break without using pipe operator. And it also it helps to have the collection,
22+
which is iterated over, to be on top.
23+
2024
Example of single pipe operator usage:
2125

2226
```fsharp
@@ -34,6 +38,13 @@ let someFunc someParam =
3438
|> yetAnotherFunc
3539
```
3640

41+
Example of single pipe applied to function with several arguments:
42+
43+
```fsharp
44+
projectsInOrder
45+
|> Seq.map(fun proj -> proj.AbsolutePath |> FileInfo)
46+
```
47+
3748
## How To Fix
3849

3950
Just use a normal function call, without the need for any operator:

src/FSharpLint.Core/Rules/Conventions/AvoidSinglePipeOperator.fs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,13 @@ let runner (args: AstNodeRuleParams) =
5252

5353
let error =
5454
match args.AstNode with
55-
| AstNode.Expression(SynExpr.App(_exprAtomicFlag, _isInfix, funcExpr, _argExpr, _range)) ->
56-
checkExpr funcExpr (args.GetParents args.NodeIndex)
55+
| AstNode.Expression(SynExpr.App(_exprAtomicFlag, _isInfix, funcExpr, argExpr, _range)) ->
56+
match argExpr with
57+
| SynExpr.App(_) ->
58+
// function has extra arguments
59+
Array.empty
60+
| _ ->
61+
checkExpr funcExpr (args.GetParents args.NodeIndex)
5762
| _ ->
5863
Array.empty
5964

tests/FSharpLint.Core.Tests/Rules/Conventions/AvoidSinglePipeOperator.fs

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ let someFunc someParam =
145145
member this.``Use pipe operator once inside of an array``() =
146146
this.Parse """
147147
let someFunc () =
148-
[| "Foo" |> String.replicate 2 |]
148+
[| "Foo" |> String.length |]
149149
"""
150150

151151
Assert.IsTrue this.ErrorsExist
@@ -175,7 +175,7 @@ let someFunc someParam barParam =
175175
this.Parse """
176176
module Foo
177177
178-
-1.0 |> printf "%d"
178+
-1.0 |> abs
179179
"""
180180

181181
Assert.IsTrue this.ErrorsExist
@@ -185,7 +185,7 @@ module Foo
185185
this.Parse """
186186
module Foo
187187
188-
-1.0 |> printf "%d" |> ignore
188+
-1.0 |> abs |> ignore
189189
"""
190190

191191
Assert.IsTrue this.NoErrorsExist
@@ -199,3 +199,24 @@ module Foo
199199
"""
200200

201201
Assert.IsTrue this.NoErrorsExist
202+
203+
[<Test>]
204+
member this.``Use pipe operator for function with more than 1 argument``() =
205+
this.Parse """
206+
let someFunc someParam =
207+
someParam
208+
|> someOtherFunc someOtherParam
209+
"""
210+
211+
Assert.IsTrue this.NoErrorsExist
212+
213+
[<Test>]
214+
member this.``Use pipe operator for higher-order function with more than 1 argument``() =
215+
this.Parse """
216+
parsedSolution.ProjectsInOrder
217+
|> Seq.map(fun proj ->
218+
proj.AbsolutePath |> normalizeDirSeparatorsPaths |> FileInfo
219+
)
220+
"""
221+
222+
Assert.IsTrue this.NoErrorsExist

0 commit comments

Comments
 (0)