CsprojModifier × BannedApiAnalyzer を使ってカスタムな静的解析を作る【Unity 静的解析】

約1か月振りの記事….今改めて思ったけど記事書くのって労力半端ないですね….

Intro

こういうのをやりたかった.

CsprojModifier

幸い日本語のDocがあるので読みましょう.

github.com

CsprojModifier は Unity Editor が .csproj を生成する際に追加の処理を行うことで、Visual Studio や Rider のような IDE での開発体験を向上させます。

BannedApiAnalyzer

github.com

まだ軽く触った程度の認識ですが,指定したクラス,フィールド,
プロパティ,メソッドをコードに書くと警告が出るようになります.呼び出し禁止.

How To Use

Tested Environment

  • Unity 2020.4.8f1 (Unity 2019 ではまだ未確認)
  • Visual Studio Community 2019 (16.10.0 Preview 3.0)
  • CsprojModifier 1.1.0

Install

CsprojModifier は Add package from git URL

https://github.com/Cysharp/CsprojModifier.git?path=src/CsprojModifier/Assets/CsprojModifier

IDEVisual Studio Community 2019 (16.10.0 Preview) で試す必要があります.
未インストールの場合はインストールしてください.

docs.microsoft.com

インストール後 Preference で IDEVisual Studio 16.10.0 Preview にしておいてください.

Project Settings > Editor > C# Project Modifier という項目が現れます.
以下の画像です.(すでに諸々の準備が終わった後の画像ですが)

f:id:xrdnk:20210517225135p:plain

上に載っている .dll ファイル群を手に入れます.やり方は色々ありますがNuGetからいきます.

Rosyln Analyzer 用のdllファイル群,
ErrorProne.NET.Core.dll ErrorProne.Net.CoreAnalyzer.dll RUntimeContracts.dll は以下から,
www.nuget.org

BannedApiAnalyzer 用のdllファイル群,
MS.CodeAnalysis.BannedApiAnalyzers.dll MS.CodeAnalysis.CSharp.BannedApiAnalyzers.dll は以下から,
www.nuget.org

脳死方法ですが,Download Packages からダウンロードして解凍します.

microsoft.codeanalysis.bannedapianalyzers.3.3.2\analyzers\dotnet\cs
errorprone.net.coreanalyzers.0.1.2\analyzers\dotnet\cs
に目的のdllがあるのでそれをUnityのAssetsフォルダへコピペあるいは移動.
一応 Editor フォルダ内に配置するといいかもしれない.

移動後にエラーが出ると思われるので,全てのdllの Import Settings に対して,以下の設定を行う.

  • Select platforms for plugin の設定全てチェックを外す
  • Asset Labels に RosylnAnalyzer のラベルを設定する

f:id:xrdnk:20210517225926p:plain

C# Project Modifier の Info マークに英語でも書かれているが,
Analyzer must be labeled as 'RoslynAnalyzer' とあるので守りましょう.

Add analyzer references to generated .csproj

C# Project Modifier の Rosyln Analyzer の Add Roslyn Analyzer references to .csproj にチェックすると,
自動的に先ほど Rosyln Analyzer のラベルを付けたdllが表示されるはず.

ここで一応 Unity 上で Rosyln Analyzer が利用できるようになっているはずなので,
Unity Console 上でも コンパイルが走った時に静的解析が走る はずです.

一応確認用のソースコードをば.

using System;
using UnityEngine;

public class RethrowError : MonoBehaviour
{
    void Update()
    {
        try
        {
            DoSomethingInteresting();
        }
        catch (Exception e)
        {
            Debug.Log(e.Message);
            throw e;
        }

        var Test = GameObject.Find("Sample");
    }

    private void DoSomethingInteresting()
    {
        throw new System.NotImplementedException();
    }
}

これでやってみると,こんなエラーが出るはずです.

f:id:xrdnk:20210517231013p:plain

IDE ではリアタイでエラーが出ます.

f:id:xrdnk:20210517231117p:plain

ここまでの機能は CsprojModifier の 生成された .csproj に Analzyer の参照を追加する ですね.

github.com

こちらの注意は目を通しておきましょう.

注意: Rider または Visual Studio Code を Unity 2020.2 以降で使用している場合にはこの機能は無効となります。IDE での Roslyn Analyzer は Unity Editor によってサポートされます。

ここで,Assembly-CSharp.csproj の中身の最後を見てみると参照が加わっているのがわかりますね.
f:id:xrdnk:20210517231503p:plain

Insert additional projects as Import elements into generated .csproj

BannedApiAnalyzer を例に作ってみましょう.
BannedApiAnalyzer を使い方はこちらの Doc に書かれてます.英語ですがわかるかと.

github.com

わからない方にも一応メモを書いておきます.
.props ファイルを作成します.Visual Studioで作るのもよし,単純にファイル作成から作るのもよし.
ただ Assets フォルダ内で作らずに,Assetsフォルダと同じ階層のところに配置してください.
Assets フォルダ内に .props を作るのはまあエラーが出ます(というより機能的になし)

仮に DeniUnitySandbox.props としましょう.

以下を記述してください.プロジェクト名は各自よしなに.

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <Analyzer Include="Assets/99_ThirdParty/Editor/Analyzers/Microsoft.CodeAnalysis.BannedApiAnalyzers.dll" />
    <Analyzer Include="Assets/99_ThirdParty/Editor/Analyzers/Microsoft.CodeAnalysis.CSharp.BannedApiAnalyzers.dll" />
  </ItemGroup>
  <ItemGroup>
    <AdditionalFiles Include="Assets/99_ThirdParty/Editor/Analyzers/BannedSymbols.txt" />
  </ItemGroup>
</Project>

BannedApiAnalyzer を利用する際は BannedSymbols.txt を作る必要があります.

では,例として,今回 GameObject.Find() を禁止する設定を作りましょう.

BannedSymbols.txt にはこう書いてください.

M:UnityEngine.GameObject.Find(System.String); GameObject.Find()使ったらおこだぞ

Doc を読めばわかりますが,法則性としては 種類:シグネチャ;警告に出すメッセージ です.
今回はメソッド(Method)だから M
シグネチャUnityEngine.GameObject.Find(System.String)
警告に出すメッセージは今回は GameObject.Find()使ったらおこだぞ にしてます.

詳細を知りたい方はやはり BannedApiAnalyzer の Doc の英語読んでください.

Additional project imports に 上の .props を設定してください.

ここまでの設定が終わったら Regenerate project files を押してください.

するとどうでしょう.

f:id:xrdnk:20210517233925p:plain

f:id:xrdnk:20210517232524p:plain

IDE側でエラーが出るようになりました.やったね. これでUnityでパフォーマンス下がってしまうメソッドを設定できたり,
各プロジェクトで禁則事項を作ったりすることができます.

ここまでが 生成された .csproj に追加のプロジェクトを Import 要素で追加する です.

注意を再度読みましょう.

注意: .csproj は Visual Studio や Rider のような IDE でのみ使用され、 Unity Editor での実際のビルドには使用されません

IDEでしかこのエラーは表示されません.Unity Console上では表示されず.

Outro

現在 Rider マンになっているので,Rider の方でも全機能利用できるようになると嬉しいな.
Unity 2019 の方では未確認なので余力あれば,検証後に記事に付け加えておきます.
JavaでWeb開発業務に従事してた時に使ってたSpotBugsみたいなのを内心Unityでやりたかったのでまあ出来てうれPってことで.

Referenced Materials

docs.unity3d.com

neue.cc