web-dev-qa-db-ja.com

閉じたファイルでコード診断構文ノードアクションを機能させるにはどうすればよいですか?

Roslynを使用して一連のコード診断を構築しています(VS2015プレビュー)。理想的には、通常の言語ルールに違反しているかのように、エラーが発生しても永続的なエラーとして機能するようにしたいと思います。

たくさんのオプションがありますが、どれも一貫して機能させるのに苦労しています。初歩的な構文ノードアクション、つまり、

context.RegisterSyntaxNodeAction(AnalyzeSyntaxNode, SyntaxKind.InvocationExpression);

診断クラスのInitializeメソッド内。なんと、この診断に違反するファイルを開くと(VSIXプロジェクトの実行中に)、VS2015はエラーを表示します。

  • コードの適切な部分の下に赤い波線
  • マージンの赤いブロック
  • エラーリストのエラー

しかし、ファイルを閉じるとエラーは消えます。

私もcontext.RegisterCompilationEndActionを使用してみましたが、これには2つの問題があります。

  • 発火に一貫性がないようです。 通常ソリューションを開くと起動しますが、常に起動するとは限りません。奇妙に思われるクリーン/リビルドでは発火しません。
  • 診断は(直接)分析メソッドで作成されますが、診断を実装するために、次のようにビジターを使用しています。

    private static void AnalyzeEndCompilation(CompilationEndAnalysisContext context)
    {
        foreach (var tree in context.Compilation.SyntaxTrees)
        {
            var visitor = new ReportingVisitor(context.Compilation.GetSemanticModel(tree));
            visitor.Visit(tree.GetRoot());
            foreach (var diagnostic in visitor.Diagnostics)
            {
                context.ReportDiagnostic(diagnostic);
            }
        }
    }
    

    診断が作成されていることを知っています-ReportDiagnostic行のブレークポイントが数回ヒットしますが、エラーリストには何も表示されません。 (メソッドの開始時の同様のReportDiagnostic呼び出し、またはファイルパスを使用した構文ツリーごとに1つですが、doesが表示されます。)

ここで何が悪いのですか?最初のアプローチ(構文ノードアクション)は、実現可能であれば理想的です-必要なコンテキストを正確に提供します。プロジェクトのプロパティに、「完全なプロジェクト」のコンパイルだけでなく、インタラクティブな「IDE内」の処理だけで使用するように設定する必要があるプロジェクトプロパティの設定はありますか?これはおそらくまだ完成していないRoslyn統合のほんの少しですか?

(クラスの完全なコードを含めることができる場合は、それが役立つ場合があります。この場合は、シグナルよりもノイズが多いと思われます。)

72
Jon Skeet

閉じたファイルの問題については、開いたファイルまたは閉じたファイルのいずれかからすべての診断が報告されるのが私たちの意図です。 Tools\Options\Text Editor\C#\ Advancedのプレビューには、閉じたファイルに診断を含めるように切り替えることができるユーザーオプションがあります。 VS 2015がリリースされる前に、これをデフォルトにしたいと考えています。ただし、このオプションはVS内の分析にのみ適用されることに注意してください。アナライザーがコンパイラーに渡された場合(ソリューションエクスプローラーにアナライザーを追加するか、Visual StudioにVSIXをインストールするのではなく、アナライザーを含むパッケージにNuGetパッケージ参照を追加することにより)、コンパイラーはallファイルが開いているかどうかに関係なく、ユーザーがビルドしたときの診断。

RegisterCompilationEndedAnalyzerの2番目の問題については、VS 2015プレビューのVisual Studio内で確実に呼び出されるわけではありません。これは、メソッド本体内の「ローカル」変更のすべてを再分析しないように、いくつかの最適化を行うためです。同様の理由により、現在、場所inメソッド本体で報告されるエラーは報告していません。 VSがより長い遅延後に完全な再分析を開始するように、最近変更しました。将来のビルドではRegisterCompilationEndedAnalyzerを確実に呼び出す必要があり、場所に関係なくエラーを報告します。

ただし、あなたの場合、正しいことはSyntaxNodeAnalyzerを使い続け、VSオプションを切り替えて閉じたファイルで診断を有効にし、診断をプロジェクトのコンパイルオプションにアタッチします。

お役に立てれば!

44
Kevin Pilch