@@ -10,54 +10,52 @@ open FSharpLint.Framework.Rules
1010let mutable moduleIdentifiers = Set.empty
1111let mutable letIdentifiers = Set.empty
1212
13- let private isStringFormat ( identifiers : List < Ident >) =
14- " String" = identifiers.[ 0 ]. idText && " Format" = identifiers.[ 1 ]. idText
13+ [<TailCall>]
14+ let rec isVisible ( id : Ident ) asts =
15+ let isNamedBinding binding =
16+ match binding with
17+ | SynBinding(_, _, _, _, _, _, _, SynPat.Named( SynIdent.SynIdent( ident, _), _, _, _), _, _, _, _, _) ->
18+ id.idText = ident.idText
19+ | _ -> false
1520
16- let private genereateErrorMessage range =
17- { Range = range
18- Message = Resources.GetString " RulesPreferStringInterpolationWithSprintf"
19- SuggestedFix = None
20- TypeChecks = List.empty }
21- |> Array.singleton
21+ match asts with
22+ | AstNode.Expression ( SynExpr.LetOrUse (_, _, [ binding], _, _, _)) :: rest ->
23+ isNamedBinding binding || isVisible id rest
24+ | _ :: rest -> isVisible id rest
25+ | [] -> false
26+
27+ [<TailCall>]
28+ let rec getTopLevelParent args index =
29+ let parents = List.rev ( args.GetParents index)
30+ match parents with
31+ | AstNode.ModuleDeclaration ( SynModuleDecl.Let _) :: rest -> rest
32+ | _ -> getTopLevelParent args ( index + 1 )
2233
2334let runner args =
35+ let isStringFormat ( identifiers : List < Ident >) =
36+ " String" = identifiers.[ 0 ]. idText && " Format" = identifiers.[ 1 ]. idText
37+
38+ let emitViolation range =
39+ { Range = range
40+ Message = Resources.GetString " RulesPreferStringInterpolationWithSprintf"
41+ SuggestedFix = None
42+ TypeChecks = List.empty }
43+ |> Array.singleton
44+
2445 match args.AstNode with
2546 | AstNode.Expression( SynExpr.App(_, _, SynExpr.LongIdent(_, SynLongIdent( ids, _, _), _, _), paren, range)) when ids.Length = 2 && isStringFormat ids ->
2647 let isTopMember ( text : string ) =
2748 moduleIdentifiers.Contains text
2849 match paren with
2950 | SynExpr.Paren( SynExpr.Tuple(_, [ SynExpr.Const( SynConst.String(_), _); _], _, _), _, _, _) ->
30- genereateErrorMessage range
51+ emitViolation range
3152 | SynExpr.Paren( SynExpr.Tuple(_, [ SynExpr.Ident identifier; _], _, _), _, _, range) ->
3253
3354 if isTopMember identifier.idText then
34- genereateErrorMessage range
55+ emitViolation range
3556 else
36- let isNamedBinding binding =
37- match binding with
38- | SynBinding(_, _, _, _, _, _, _, SynPat.Named( SynIdent.SynIdent( ident, _), _, _, _), _, _, _, _, _) ->
39- identifier.idText = ident.idText
40- | _ -> false
41-
42- let isVisible asts =
43- let rec loop asts =
44- match asts with
45- | AstNode.Expression ( SynExpr.LetOrUse (_, _, [ binding], _, _, _)) :: rest ->
46- isNamedBinding binding || loop rest
47- | _ :: rest -> loop rest
48- | [] -> false
49- loop asts
50-
51- let getTopLevelParent index =
52- let rec loop index =
53- let parents = List.rev ( args.GetParents index)
54- match parents with
55- | AstNode.ModuleDeclaration ( SynModuleDecl.Let _) :: rest -> rest
56- | _ -> loop ( index + 1 )
57- loop index
58-
59- if letIdentifiers.Contains identifier.idText && isVisible ( getTopLevelParent 2 ) then
60- genereateErrorMessage range
57+ if letIdentifiers.Contains identifier.idText && isVisible identifier ( getTopLevelParent args 2 ) then
58+ emitViolation range
6159 else
6260 Array.empty
6361 | _ -> Array.empty
0 commit comments