なつねこメモ

主にプログラミング関連のメモ帳 ♪(✿╹ヮ╹)ノ 書いてあるコードは自己責任でご自由にどうぞ。記事本文の無断転載は禁止です。

Roslyn で ISymbol から SyntaxNode を得たい

みなさん Roslyn いじってますか? Roslyn(正式名称:.NET Compiler Platform)は、C# をはじめとする .NET 系言語のコンパイラであり、同時に強力なコード解析 API でもあります。JavaScript/TypeScript エコシステムでいえば、ESLint や Prettier のような静的解析ツールを、言語機能として簡単に作成できる優れたプラットフォームです。

www.wikiwand.com

Roslyn では、ソースコードを以下の2つの主要な概念で扱います:

例えば、次のシンプルな C# プログラムを見てみましょう:

void Main()
{
    Console.WriteLine("Hello, World");
}

このコードは、以下の画像のような SyntaxNode 群と Main というシンボルで構成されています。

SyntaxNode 群

通常の開発では、SyntaxNode から Semantic Model を介して ISymbol を取得するケースが多いでしょう。 しかし、今回は その逆のパターン を扱います。つまり、ISymbol からその定義元となる SyntaxNode を特定したい という場面です。 この問題は、ISymbol の DeclaringSyntaxReferences プロパティを使用することで解決できます。

var symbol = ... // ISymbol
var declaringSyntax = symbol.DeclaringSyntaxReferences
    .FirstOrDefault()?
    .GetSyntax(context.CancellationToken);

// declaringSyntax は対応する SyntaxNode を返す

ISymbol.DeclaringSyntaxReferences プロパティは、そのシンボルが宣言された構文ノードの参照リストを返します。 ちなみに単一の値ではなくリストが返ってくる理由としては、partial クラスや partial メソッドのように、複数の場所で定義される可能性があるシンボルが存在するためです。 基本的には1つめのものを利用すればよく、場合に応じて2つめ以降を見ればよい、というイメージで使えます。

ということで、久々の Roslyn 記事でした。Roslyn の豊富な API を活用して、より良い開発体験を実現していきましょう!