NoArgFormatStringAnalyzer
Applying a printf-style function (sprintf, failwithf, printf, printfn, eprintf, eprintfn, fprintf, fprintfn, bprintf) to a format string that has no format specifiers still goes through the F# format parsing machinery on every call.
When the string is a constant, the same result can be obtained with the plain string literal.
Problem
// Analyzer will trigger
let header = sprintf "<pre><code>"
let fail () = failwithf "boom"
printfn "hello"
fprintfn tw "hello"
Printf.bprintf sb "hello"
Fix
let header = "<pre><code>"
let fail () = failwith "boom"
stdout.WriteLine "hello"
tw.WriteLine "hello"
sb.Append "hello" |> ignore
An escaped percent sign (%%) is not a format specifier, so sprintf "100%%" is also reported and the fix unescapes it to "100%".
Format strings with at least one specifier, interpolated strings and non-constant format values are not reported:
// Does not trigger analyzer
let langCode = sprintf "language-%s" "fsharp"
let greet name = sprintf $"hello %s{name}"
Code fix
This analyzer has a code fix for Ionide.
val header: string
val sprintf: format: Printf.StringFormat<'T> -> 'T
val fail: unit -> 'a
val failwithf: format: Printf.StringFormat<'T,'Result> -> 'T
val printfn: format: Printf.TextWriterFormat<'T> -> 'T
val fprintfn: textWriter: System.IO.TextWriter -> format: Printf.TextWriterFormat<'T> -> 'T
module Printf
from Microsoft.FSharp.Core
val bprintf: builder: System.Text.StringBuilder -> format: Printf.BuilderFormat<'T> -> 'T
val failwith: message: string -> 'T
val stdout<'T> : System.IO.TextWriter
val ignore: value: 'T -> unit
val langCode: string
val greet: name: string -> string
val name: string
ionide-analyzers