Skip to content

Commit 660a50a

Browse files
committed
CanBeReplacedWithComposition: implement suggestion
Implement suggested fix for CanBeReplacedWithComposition rule.
1 parent af49c01 commit 660a50a

File tree

1 file changed

+41
-19
lines changed

1 file changed

+41
-19
lines changed

src/FSharpLint.Core/Rules/Conventions/FunctionReimplementation/CanBeReplacedWithComposition.fs

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ open FSharpLint.Framework.Ast
88
open FSharpLint.Framework.Rules
99
open FSharpLint.Framework.ExpressionUtilities
1010

11-
let private validateLambdaCannotBeReplacedWithComposition _ lambda range =
12-
let canBeReplacedWithFunctionComposition expression =
11+
let private validateLambdaCannotBeReplacedWithComposition fileContents _ lambda range =
12+
let tryReplaceWithFunctionComposition expression =
1313
let getLastElement = List.rev >> List.head
1414

15-
let rec lambdaArgumentIsLastApplicationInFunctionCalls expression (lambdaArgument:Ident) numFunctionCalls =
15+
let rec lambdaArgumentIsLastApplicationInFunctionCalls expression (lambdaArgument:Ident) (calledFunctionIdents: List<string>) =
1616
let rec appliedValuesAreConstants appliedValues =
1717
match appliedValues with
1818
| (SynExpr.Const(_)| SynExpr.Null(_))::rest -> appliedValuesAreConstants rest
@@ -22,34 +22,56 @@ let private validateLambdaCannotBeReplacedWithComposition _ lambda range =
2222
match AstNode.Expression expression with
2323
| FuncApp(exprs, _) ->
2424
match List.map removeParens exprs with
25-
| (SynExpr.Ident(_) | SynExpr.LongIdent(_))::appliedValues
25+
| (ExpressionUtilities.Identifier(idents, _))::appliedValues
2626
when appliedValuesAreConstants appliedValues ->
27-
27+
28+
let funcName = String.Join(".", idents)
29+
let funcStringParts =
30+
Seq.append
31+
(Seq.singleton funcName)
32+
(appliedValues
33+
|> Seq.take (appliedValues.Length - 1)
34+
|> Seq.choose (fun value -> ExpressionUtilities.tryFindTextOfRange value.Range fileContents))
35+
let funcString = String.Join(" ", funcStringParts)
36+
2837
match getLastElement appliedValues with
29-
| SynExpr.Ident(lastArgument) when numFunctionCalls > 1 ->
30-
lastArgument.idText = lambdaArgument.idText
38+
| SynExpr.Ident(lastArgument) when calledFunctionIdents.Length > 1 ->
39+
if lastArgument.idText = lambdaArgument.idText then
40+
funcString :: calledFunctionIdents
41+
else
42+
[]
3143
| SynExpr.App(_, false, _, _, _) as nextFunction ->
32-
lambdaArgumentIsLastApplicationInFunctionCalls nextFunction lambdaArgument (numFunctionCalls + 1)
33-
| _ -> false
34-
| _ -> false
35-
| _ -> false
44+
lambdaArgumentIsLastApplicationInFunctionCalls
45+
nextFunction
46+
lambdaArgument
47+
(funcString :: calledFunctionIdents)
48+
| _ -> []
49+
| _ -> []
50+
| _ -> []
3651

3752
match lambda.Arguments with
3853
| [singleParameter] ->
39-
Helper.FunctionReimplementation.getLambdaParamIdent singleParameter
40-
|> Option.exists (fun paramIdent -> lambdaArgumentIsLastApplicationInFunctionCalls expression paramIdent 1)
41-
| _ -> false
54+
match Helper.FunctionReimplementation.getLambdaParamIdent singleParameter with
55+
| Some paramIdent ->
56+
match lambdaArgumentIsLastApplicationInFunctionCalls expression paramIdent [] with
57+
| [] -> None
58+
| funcStrings -> Some funcStrings
59+
| None -> None
60+
| _ -> None
4261

43-
if canBeReplacedWithFunctionComposition lambda.Body then
62+
match tryReplaceWithFunctionComposition lambda.Body with
63+
| None -> Array.empty
64+
| Some funcStrings ->
65+
let suggestedFix =
66+
lazy(
67+
Some { FromRange = range; FromText = fileContents; ToText = String.Join(" >> ", funcStrings) })
4468
{ Range = range
4569
Message = Resources.GetString("RulesCanBeReplacedWithComposition")
46-
SuggestedFix = None
70+
SuggestedFix = Some suggestedFix
4771
TypeChecks = [] } |> Array.singleton
48-
else
49-
Array.empty
5072

5173
let runner (args:AstNodeRuleParams) =
52-
Helper.FunctionReimplementation.checkLambda args validateLambdaCannotBeReplacedWithComposition
74+
Helper.FunctionReimplementation.checkLambda args (validateLambdaCannotBeReplacedWithComposition args.FileContent)
5375

5476
let rule =
5577
{ Name = "CanBeReplacedWithComposition"

0 commit comments

Comments
 (0)