C#で型によるSwitchの網羅漏れをRoslynで検出できる...かも

qiita.com

という記事をよんで、いやRoslynで良くね?と思ったのでちょっと調べてみた。

調べたところこのようなものがあり、

github.com

これをNugetForUnityで入れる。

そうすると既存のパッケージに対して大量のエラーを吐いてしまうので、StyleCopなるものを使って抑制する(参考:https://docs.unity3d.com/ja/2021.1/Manual/roslyn-analyzers.html)。以下のファイルをAssets下に書けばOK

<?xml version="1.0" encoding="utf-8"?>
<RuleSet Name="Default Rule Set" Description=" " ToolsVersion="10.0">
    <Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers">
        <Rule Id="EM0001" Action="None" />
    </Rules>
</RuleSet>

そして、asmdefを切って、そこには何も指定しないでルールセットファイルを追加

<?xml version="1.0" encoding="utf-8"?>
<RuleSet Name="Default Rule Set" Description=" " ToolsVersion="10.0">
    <Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers">
    </Rules>
</RuleSet>

警告を出してもらうにはcase文を以下のようにしなければいけない。このデザインはちょっとイマイチな気がするが理由はよくわからない

switch (character)
{
    default:
        throw ExhaustiveMatch.Failed(character);
}

そうするとこのようにエラーがでてくるので、

継承するクラスを指定してあげる。もし不足があったらちゃんとエラーになる

/// キャラクターの抽象クラス
[Closed(typeof(Hero), typeof(MagicCaster), typeof(Thief), typeof(Priest))]
public abstract class Character
{

}

そうするとエラーが出て、何の型が不足しているかも表示してくれる

使用感的にちょっとフィットしないが、やりたいことは実現できている気がする。

caseの列挙が漏れるみたいな事象は根本的な設計ミスというよりは、単なる人的ミスという印象で、デザインパターンでどうにか落とし込むよりは、Analyzerを使った方が分かりやすいんじゃないかなーと

throw ExhaustiveMatch.Failed(character);を書かなきゃいけないとか、それぞれClosed(Hoge)しないといけないとか、なんか使用感がしっくりこないので、暇があったらオレオレAnalyzerを作ってみる