@@ -17,21 +17,33 @@ type internal RecursiveFunctionInfo =
1717 Attributes: SynAttributes
1818 }
1919
20- let internal (| RecursiveFunction | _ |) ( astNode : AstNode ) =
20+ let internal (| RecursiveFunctions | _ |) ( astNode : AstNode ) =
2121 match astNode with
2222 | AstNode.ModuleDeclaration ( SynModuleDecl.Let ( true , bindings, _)) ->
23- match bindings with
24- | SynBinding (_, _, _, _, attributes, _, _, SynPat.LongIdent ( SynLongIdent([ ident], _, _), _, _, _, _, range), _, body, _, _, _) :: _ ->
25- Some { Identifier = ident; Range = range; Body = body; Attributes = attributes }
26- | _ -> None
23+ let recursiveBindings =
24+ bindings
25+ |> List.choose
26+ ( fun binding ->
27+ match binding with
28+ | SynBinding (_, _, _, _, attributes, _, _, SynPat.LongIdent ( SynLongIdent([ ident], _, _), _, _, _, _, range), _, body, _, _, _) ->
29+ Some { Identifier = ident; Range = range; Body = body; Attributes = attributes }
30+ | _ -> None)
31+ match recursiveBindings with
32+ | [] -> None
33+ | _ -> Some recursiveBindings
2734 | _ -> None
2835
29- let internal functionCallsItself ( checkInfo : FSharpCheckFileResults ) ( func : RecursiveFunctionInfo ) =
30- let funcName = func.Identifier.idText
31- checkInfo.GetAllUsesOfAllSymbolsInFile()
32- |> Seq.exists ( fun usage ->
33- usage.Symbol.DisplayName = funcName
34- && ExpressionUtilities.rangeContainsOtherRange func.Body.Range usage.Range)
36+ let internal functionIsCalledInOneOf ( checkInfo : FSharpCheckFileResults )
37+ ( callee : RecursiveFunctionInfo )
38+ ( callers : list < RecursiveFunctionInfo >) =
39+ let calleeName = callee.Identifier.idText
40+ callers
41+ |> List.exists
42+ ( fun caller ->
43+ checkInfo.GetAllUsesOfAllSymbolsInFile()
44+ |> Seq.exists ( fun usage ->
45+ usage.Symbol.DisplayName = calleeName
46+ && ExpressionUtilities.rangeContainsOtherRange caller.Body.Range usage.Range))
3547
3648let private emitWarning ( func : RecursiveFunctionInfo ) =
3749 { Range = func.Range
@@ -45,8 +57,15 @@ let private emitWarning (func: RecursiveFunctionInfo) =
4557
4658let runner ( args : AstNodeRuleParams ) =
4759 match args.AstNode, args.CheckInfo with
48- | RecursiveFunction( func), Some checkInfo when not ( functionCallsItself checkInfo func) ->
49- emitWarning func |> Array.singleton
60+ | RecursiveFunctions( funcs), Some checkInfo ->
61+ funcs
62+ |> List.choose
63+ ( fun functionInfo ->
64+ if not ( functionIsCalledInOneOf checkInfo functionInfo funcs) then
65+ emitWarning functionInfo |> Some
66+ else
67+ None)
68+ |> List.toArray
5069 | _ -> Array.empty
5170
5271let rule =
0 commit comments