はじめに
この記事は株式会社ラグザイア Advent Calendar 2023の記事です。
前回は Roslyn API のざっくりした概要の紹介とフィールドの名称を取得してみました。
今回はRoslyn API でフィールドとプロパティの型と名称を取得してみます。
先に忙しい方向けに、Roslyn API でフィールドとプロパティの型と名称を取得するコードを貼っておきます。
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace SyntaxQuickStart
{
class Program
{
const string programText =
@"namespace DummyNamespace
{
internal class Dummy
{
public string DummyField = ""フィールドです"";
public int DummyProperty => 123;
}
}";
static void Main()
{
SyntaxTree tree = CSharpSyntaxTree.ParseText(programText);
CompilationUnitSyntax root = tree.GetCompilationUnitRoot();
// フィールドを取得
FieldDeclarationSyntax field = root.DescendantNodes().OfType<FieldDeclarationSyntax>().First();
Console.WriteLine("------------------ フィールドの情報 ------------------");
// フィールドの名称を表示
Console.WriteLine(field.Declaration.Variables.First().Identifier.ValueText);
// フィールドの型を表示
Console.WriteLine(field.Declaration.Type.ToString());
// プロパティを取得
PropertyDeclarationSyntax property = root.DescendantNodes().OfType<PropertyDeclarationSyntax>().First();
Console.WriteLine("------------------ プロパティの情報 ------------------");
// プロパティの名称を表示
Console.WriteLine(property.Identifier.ValueText);
// プロパティの型を表示
Console.WriteLine(property.Type.ToString());
}
}
}
フィールドの型を取得する
前回は Roslyn API を使ってフィールドの名称を表示するところまで行いました。同様に Roslyn API を使ってフィールドの型を表示してみましょう。
フィールドの名称の場合、コード解析後のツリーから FieldDeclarationSyntax
を OfType
を使って絞り込み、 field.Declaration.Variables.First().Identifier.ValueText
のような形で名称を取りだしていました。コードはこんな感じでした。
var tree = CSharpSyntaxTree.ParseText(programText);
var root = tree.GetCompilationUnitRoot();
// フィールドを取得
var field = root.DescendantNodes().OfType<FieldDeclarationSyntax>().First();
// フィールドの名称を標準出力に表示
Console.WriteLine(field.Declaration.Variables.First().Identifier.ValueText);
Declaration
プロパティがフィールドに関するあれこれの情報をもっていそうです。 Declaration
の正体である VariableDeclarationSyntax を見ると Type
プロパティを発見しました。これが使えそうです。
// フィールドを取得
FieldDeclarationSyntax field = root.DescendantNodes().OfType<FieldDeclarationSyntax>().First();
// フィールドの型を表示
Console.WriteLine(field.Declaration.Type.ToString());
これを前回のコードに追加して表示してみます。
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace SyntaxQuickStart
{
class Program
{
const string programText =
@"namespace DummyNamespace
{
internal class Dummy
{
public string DummyField = ""フィールドです"";
}
}";
static void Main()
{
SyntaxTree tree = CSharpSyntaxTree.ParseText(programText);
CompilationUnitSyntax root = tree.GetCompilationUnitRoot();
// フィールドを取得
FieldDeclarationSyntax field = root.DescendantNodes().OfType<FieldDeclarationSyntax>().First();
Console.WriteLine("------------------ フィールドの情報 ------------------");
// フィールドの名称を表示
Console.WriteLine(field.Declaration.Variables.First().Identifier.ValueText);
// フィールドの型を表示
Console.WriteLine(field.Declaration.Type.ToString());
}
}
}
実行結果です。無事にフィールドの型である string
が表示できました。
プロパティの情報を取得する
フィールドの名称と型の情報は取得できました。同様にプロパティの情報も取得していきましょう。
プロパティの名称を取得する
フィールドの場合↓のような形で名称 = 識別子を取得できていました。
var tree = CSharpSyntaxTree.ParseText(programText);
var root = tree.GetCompilationUnitRoot();
// フィールドを取得
var field = root.DescendantNodes().OfType<FieldDeclarationSyntax>().First();
// フィールドの名称を標準出力に表示
Console.WriteLine(field.Declaration.Variables.First().Identifier.ValueText);
↑でいけるのであれば FieldDeclarationSyntax
の部分を PropertyDeclarationSyntax
に変えるだけでいけるのでは?と予想してみました。やってみましょう。こうです!えいや!
// フィールドを取得して名称を表示(ネタバレ:エラーになります)
PropertyDeclarationSyntax property = root.DescendantNodes().OfType<PropertyDeclarationSyntax>().First();
Console.WriteLine(property.Declaration.Variables.First().Identifier.ValueText);
すると残念なことにエラーになりました。PropertyDeclarationSyntax
は Declaration
というプロパティは持たないようです。ちくしょう…
PropertyDeclarationSyntax の解説ページを見ると Identifier
プロパティがありました。
property.Identifer
で一気に識別子(名称)の値が取れるみたいです。つまり、こうです。
PropertyDeclarationSyntax property = root.DescendantNodes().OfType<PropertyDeclarationSyntax>().First();
Console.WriteLine(property.Identifier.ValueText);
前回のコードに加えて出力させてみましょう。
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace SyntaxQuickStart
{
class Program
{
const string programText =
@"namespace DummyNamespace
{
internal class Dummy
{
public string DummyField = ""フィールドです"";
public int DummyProperty => 123;
}
}";
static void Main()
{
SyntaxTree tree = CSharpSyntaxTree.ParseText(programText);
CompilationUnitSyntax root = tree.GetCompilationUnitRoot();
// フィールドを取得
FieldDeclarationSyntax field = root.DescendantNodes().OfType<FieldDeclarationSyntax>().First();
Console.WriteLine("------------------ フィールドの情報 ------------------");
// フィールドの名称を表示
Console.WriteLine(field.Declaration.Variables.First().Identifier.ValueText);
// フィールドの型を表示
Console.WriteLine(field.Declaration.Type.ToString());
// プロパティを取得
PropertyDeclarationSyntax property = root.DescendantNodes().OfType<PropertyDeclarationSyntax>().First();
Console.WriteLine("------------------ プロパティの情報 ------------------");
// プロパティの名称を表示
Console.WriteLine(property.Identifier.ValueText);
}
}
}
実行結果です。プロパティの名称である DummyProperty
が表示されました。いえーい。
プロパティの型を取得する
プロパティの名称と同じようにPropertyDeclarationSyntax から何かできないかと見てみると、 Type
プロパティがありました。これは勝ち確定パターンです。
こう書けそうです。
// プロパティを取得
PropertyDeclarationSyntax property = root.DescendantNodes().OfType<PropertyDeclarationSyntax>().First();
// プロパティの型を表示
Console.WriteLine(property.Type.ToString());
今までのコードに追加してみます。
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace SyntaxQuickStart
{
class Program
{
const string programText =
@"namespace DummyNamespace
{
internal class Dummy
{
public string DummyField = ""フィールドです"";
public int DummyProperty => 123;
}
}";
static void Main()
{
SyntaxTree tree = CSharpSyntaxTree.ParseText(programText);
CompilationUnitSyntax root = tree.GetCompilationUnitRoot();
// フィールドを取得
FieldDeclarationSyntax field = root.DescendantNodes().OfType<FieldDeclarationSyntax>().First();
Console.WriteLine("------------------ フィールドの情報 ------------------");
// フィールドの名称を表示
Console.WriteLine(field.Declaration.Variables.First().Identifier.ValueText);
// フィールドの型を表示
Console.WriteLine(field.Declaration.Type.ToString());
// プロパティを取得
PropertyDeclarationSyntax property = root.DescendantNodes().OfType<PropertyDeclarationSyntax>().First();
Console.WriteLine("------------------ プロパティの情報 ------------------");
// プロパティの名称を表示
Console.WriteLine(property.Identifier.ValueText);
// プロパティの型を表示
Console.WriteLine(property.Type.ToString());
}
}
}
次回予告
ということで Roslyn API を使ってフィールドとプロパティの型と名称を取得することができました。次回は Roslyn API を使おうと思ったきっかけの「コメント」の取得に挑みます。乞うご期待。