Skip to content

Commit 38e0d2f

Browse files
committed
InterpolatedStringWithNoSubstitution: impl rule
Implemented InterpolatedStringWithNoSubstitution rule.
1 parent fcdcf0c commit 38e0d2f

File tree

2 files changed

+30
-2
lines changed

2 files changed

+30
-2
lines changed

src/FSharpLint.Core/Rules/Smells/InterpolatedStringWithNoSubstitution.fs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,38 @@ open FSharp.Compiler.Syntax
77
open FSharpLint.Framework.Ast
88
open FSharpLint.Framework.Rules
99

10-
let checkInterpolatedString (contents: list<SynInterpolatedStringPart>) range =
11-
failwith "Not yet implemented"
10+
let private makeWarning range =
11+
{
12+
Range = range
13+
Message = Resources.GetString "InterpolatedStringWithNoSubstitution"
14+
SuggestedFix = None
15+
TypeChecks = List.Empty
16+
}
1217

18+
let checkInterpolatedString (contents: List<SynInterpolatedStringPart>) range =
19+
if contents |> List.exists (fun part -> part.IsFillExpr) then
20+
Array.empty
21+
else
22+
Array.singleton (makeWarning range)
23+
24+
let stringFormattingFunctionNames = [ "sprintf"; "failwithf" ]
25+
26+
// https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/plaintext-formatting#format-specifiers-for-printf
27+
let formatSpecifierRegex = Text.RegularExpressions.Regex(@"($|[^\%])\%[^\s\%]")
28+
29+
let checkFormattingFunctionApplication (formatString: string) range =
30+
if formatSpecifierRegex.IsMatch formatString then
31+
Array.empty
32+
else
33+
Array.singleton (makeWarning range)
34+
1335
let runner (args: AstNodeRuleParams) =
1436
match args.AstNode with
1537
| AstNode.Expression(SynExpr.InterpolatedString(contents, _synStringKind, range)) ->
1638
checkInterpolatedString contents range
39+
| AstNode.Expression(SynExpr.App(_, false, SynExpr.Ident(ident), SynExpr.Const(SynConst.String(text, _, _stringRange),_), range))
40+
when stringFormattingFunctionNames |> List.contains ident.idText ->
41+
checkFormattingFunctionApplication text range
1742
| _ -> Array.empty
1843

1944
let rule =

src/FSharpLint.Core/Text.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,4 +381,7 @@
381381
<data name="RulesFavourAsKeyword" xml:space="preserve">
382382
<value>Prefer using the 'as' pattern to match a constant and bind it to a variable.</value>
383383
</data>
384+
<data name="InterpolatedStringWithNoSubstitution" xml:space="preserve">
385+
<value>Use interpolated string (with $ prefix) only when embedding F# expression in that string using {}.</value>
386+
</data>
384387
</root>

0 commit comments

Comments
 (0)