OmniSharp-Vim で IDE0001 などのコードスタイルの分析結果を表示する

# 最初に結論

下記の設定をすると IDE**** のようなコードスタイルの分析結果を Vim 上から確認することができます。（OmniSharp-Vim と ALE を連携している前提です。）

```omnisharp.json
{
  "RoslynExtensionsOptions": {
    "enableAnalyzersSupport": true
  },
  "FormattingOptions": {
    "enableEditorConfigSupport": true
  }
}
```

注意点
* ソリューションの規模によっては解析に時間がかかりCPUに負荷がかかる可能性があります
* editorconfig で解析ルールを設定しない場合は `enableEditorConfigSupport` の設定は不要です

# 背景

最近、Roslyn-API について調べていまして自作のアナライザーの結果を Vim で見れるのかな？と色々やっていたところ偶然 `IDE****` の分析結果を Vim で表示する方法が分かりました。 

# 方法

## ALE と連携し分析結果を表示できるようにする

OmniSharp-Vim で分析結果を表示するために、まず、ALE と連携するように設定します。（ALE使わない方法は試してないので良く分かりません）

https://github.com/OmniSharp/omnisharp-vim#optional-install-ale

```init.vim
let g:ale_linters = {
\ 'cs': ['OmniSharp']
\}
```

ここで、動作確認用のコードを書きます。 `CS****` 系の指摘と `IDE****` 系の指摘がでるようなコードにします。

```class1.cs
namespace Sample
{
    internal class Class1
    {
        public Class1()
        {
            int hello = "hello";
            var a = hello;
            Console.WriteLine(hello);
        }
    }
}

```

このコードを VisualStudio で解析すると、`CS0029` と `IDE0059` が発生していることが分かります。

![Monosnap SyntaxQuickStart - Microsoft Visual Studi.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960076/f89f0c7e-d7a8-f065-3c2f-46b60a365009.png)

このコードを、ALE連携した Omnisharp-Vim を使ってみるとこのように見えます。（ガーター部分の表示はALEの設定によります）
![Monosnap ~_works_SyntaxQuickStart 2023-11-24 11.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960076/60f1b86c-7bf1-1288-1c07-c97b1e1a720c.png)

`CS0029` は表示されていますが、`IDE0059` が表示されていません。

## IDE**** の分析結果を表示する

IDE**** 系の分析結果を表示するには OmniSharp-Roslyn 側の設定が必要になります。

https://github.com/OmniSharp/omnisharp-roslyn/wiki/Configuration-Options#roslyn-extensions-options

↑を参考に `omnisharp.json` を作成し`enableAnalyzersSupport` に true を設定します。

```omnisharp.json
{
  "RoslynExtensionsOptions": {
    "enableAnalyzersSupport": true
  }
}
```

この状態で先ほどのコードを vim で確認すると、`IDE****` の分析結果が表示されるようになりました！

![Monosnap ~_works_SyntaxQuickStart 2023-11-24 11.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960076/aba2954b-dce8-20a7-f844-f1691487529a.png)


`enableAnalyzersSupport` に true を設定するとNugetからインストールしたアナライザーを含めた全てのアナライザーで解析が行われるようです。

## editorconfig でコードスタイルの設定を行う

さて、コードスタイルにはオプションなどの設定が存在します。例えば [IDE0011](https://learn.microsoft.com/ja-jp/dotnet/fundamentals/code-analysis/style-rules/ide0011) であれば中かっこを使用するかどうか、そして使用する場合は複数行のコード ブロックだけかどうかを指定できます。

![Monosnap IDE0011_ 中かっこを追加する - .NET _ Microsoft Lea.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960076/53560f38-c206-b2e8-904e-200d15dcbed0.png)

この設定は editorconfig で設定できます。
確認のため、 `IDE0011` が警告されるように中カッコが無い一行のコードを書きます。

```cs
public Class1()
{
    var a = "hello";

    if (a == "Hello") Console.WriteLine("hello");
}
```

`IDE0011` のデフォルトは `true` なので一行で中カッコを使っていない場合警告されます。
Vim 上で警告されることを確認しました。

![Monosnap ~_works_SyntaxQuickStart 2023-11-24 11.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960076/f25631e9-81d8-f1d1-253d-bc7d97516885.png)

次に、editorconfig で `IDE0011` のオプション設定を false に変更します。これにより中カッコを使用していないときに警告が出なくなるはずです。

```.editorconfig
[*.cs]
csharp_prefer_braces = false
```

vim 上でも確認します。あれ？変わっていません…
![Monosnap ~_works_SyntaxQuickStart 2023-11-24 11.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960076/0342577c-30c9-534a-a83f-126934a0f77c.png)

調べてみると、`editorconfig` を使う場合は omnisharp.json に `EnableEditorConfigSupport` を true にする必要がありました。

https://github.com/OmniSharp/omnisharp-roslyn/wiki/Configuration-Options#formatting-options

omnisharp.json を変更します。

```omnisharp.json
{
  "RoslynExtensionsOptions": {
    "enableAnalyzersSupport": true
  },
  "FormattingOptions": {
    "enableEditorConfigSupport": true
  }
}
```

この状態で Vim で確認すると `IDE0011` が消えていることを確認しました。
![Monosnap ~_works_SyntaxQuickStart 2023-11-24 11.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960076/da288bee-1738-0fda-31df-8dccc79c97db.png)

# 問題点

やったぜ！これで `IDE****` も表示できるぜ！と思って、担当しているプロジェクトをひらきました。
すると `IDE****` が表示されるまでに相当の時間がかかることが分かりました。そしてPCのファンが爆音で回ります。デフォルト設定だとCPU コア数の 75% をフルフルに使って解析をするようです。

https://github.com/OmniSharp/omnisharp-roslyn/wiki/Configuration-Options#roslyn-extensions-options

> If you want to run the analyzers sequentially instead of in parallel - set diagnosticWorkersThreadCount to 1. If no value is given for the thread count 75% of the cores will be used (i.e. 12 cores on a 16 core machine).

また OmniSharp のログを確認すると、解析が途中でタイムアウトしていることも分かりました。
タイムアウト自体を解決するには `documentAnalysisTimeoutMs` の設定時間を増やすことで解決はできましたが、Vim の軽量な動作は死にます。

ソリューション全体ではなく、開いでいるファイルだけ解析できるオプションはないか調べたところあるにはありました。

https://github.com/OmniSharp/omnisharp-roslyn/issues/2499

`analyzeOpenDocumentsOnly` を設定すれば開いているファイルだけ解析されます。
しかし、この場合は `IDE****` の表示はされないことが分かりました。

[`analyzeOpenDocumentsOnly` の機能が入ったときのPR](https://github.com/OmniSharp/omnisharp-roslyn/pull/2346) を見ると

> just the base diagnostics provided by syntaxTree.GetDiagnostics()

とコメントがありました。 どうやら `base diagnostics` の中には `IDE****` 系を出すコードアナライザーによる分析は含まれないようです。残念…

ということで担当プロジェクトについては、プロジェクトディレクトリに `omnisharp.json` をさらに追加して、`enableAnalyzersSupport` を false に設定し、基本的な分析のみ行うようにしました。なんだか負けた気分です。ぴえん。