2025-04-20

F# で command-line predictor を書いてる Part 7

GitHub Code Scanning

krymtkts/SnippetPredictor の開発をした。

Fsharp.Analyzers.SDK で作成した Code Scanning Alerts の解消をした。 #48

ただ Code Scanning Alerts が解消されたにも関わらず Open なままだった。 よくわからんなーと思っていたのだが、途中で Code Scanning の configuration を変えたらそうなるという仕様のようだった。なんてこったい。 解消するには以下の通り、古いのと新しい configuration とが競合してることによるようなので、古い方を消したら良いようだ。

消してみたら全部の alerts が解消されてスッキリした。

因みに alert の内容は妥当な感じのやつだったが 1 つ困ったのがあった。 このルール。

StructDiscriminatedUnionAnalyzer | ionide-analyzers

    [<RequireQualifiedAccess>]
[<NoEquality>]
[<NoComparison>]
type SearchCaseSensitive =
| CaseSensitive
| CaseInsensitive

こういう DU を作って、それに Interlocked を使って atomic な操作をしてるところがあった。 この DU を Struct Discriminated Unions にしてもいいよというヒント。 メモリが無駄なのでって文脈だろう。 構造体にすると Interlocked を使えなくなるし(参照型で wrap してもまじで意味ない)、どうしたもんかと。 個別の alert を無効化する方法がわからなかったし、ヒントなので対応しなくても良いのだけど、 alert は 0 の方が安心感ある。 この際なので Interlocked で DU を扱うのをやめて int に変換する形で mutable な変数に格納するように変えた。 こんなんを使う。

   module CaseSensitivity =
[<Literal>]
let sensitive = 1

[<Literal>]
let insensitive = 0

module SearchCaseSensitivity =
let ofBool =
function
| true -> CaseSensitivity.sensitive
| false -> CaseSensitivity.insensitive

let stringComparison =
function
| CaseSensitivity.sensitive -> StringComparison.Ordinal
| _ -> StringComparison.OrdinalIgnoreCase

因みにずっと知らずに生きてきたのだが、変数名が upper case で始まる場合 match expression の pattern に使えるみたい。 そうなんや...よく今まで生きてこれたな。 でも F# like な命名に即すると Upper camel case は違和感ある。 この場合上記のように module で修飾すれば良い。

やっぱこういう気付きがあることからも、 F# のような強力な言語でも linter の類はあった方がいいよな。 FSharpLint を使いこなせなくなって久しかったので助かった。

FSharpLint のメンテに関しては、 2 週間ほど前に追加のメンテナをコミュニティで募集しよか?と Don さんが issue 立ててた。なんか変化起こるかなー。 Checking on on maintainers status · Issue #721 · fsprojects/FSharpLint