ScriptDom のデバッグ用 Visitor
クエリが SQL Database でサポートされているかを ScriptDom で判定する(作成中) - お だ のスペース を実装してるんですが、どの構文が何の TSqlFragment クラス (Microsoft.SqlServer.TransactSql.ScriptDom) を継承してるか分かりにくいのが難点です。
というわけで、確認用の Visitor を T4 で用意してみました。
<#@ template debug="false" hostspecific="false" language="C#" #> <#@ assembly name="System.Core" #> <#@ assembly name="C:\Program Files (x86)\Microsoft SQL Server\120\SDK\Assemblies\Microsoft.SqlServer.TransactSql.ScriptDom.dll"#> <#@ import namespace="System.Linq" #> <#@ import namespace="System.Text" #> <#@ import namespace="System.Collections.Generic" #> <#@ import namespace=" Microsoft.SqlServer.TransactSql.ScriptDom" #> <#@ output extension=".cs" #> using System; using System.Collections.Generic; using Microsoft.SqlServer.TransactSql.ScriptDom; using ScriptDom.SqlDatabase.Test; namespace ScriptDom.SqlDatabase.Test { public partial class DebugVisitor : TSqlConcreteFragmentVisitor { <# foreach (var name in typeof(TSqlConcreteFragmentVisitor).GetMethods() .Where(m => m.Name == "Visit") .Where(m => m.IsVirtual) .Where(m => m.IsPublic) .Where(m => !m.IsFinal) .Select(m => m.GetParameters()) .Where(ps => ps.Length == 1) .Select(ps => ps[0]) .Select(p => p.ParameterType.Name)) { #> public override void Visit(<#= name #> node) { Console.WriteLine("<#= name #>"); Debug(node); base.Visit(node); } <# } #> } }
これでこんな感じの cs が吐かれます。
using System; using System.Collections.Generic; using Microsoft.SqlServer.TransactSql.ScriptDom; using ScriptDom.SqlDatabase.Test; namespace ScriptDom.SqlDatabase.Test { public partial class DebugVisitor : TSqlConcreteFragmentVisitor { public override void Visit(EventDeclaration node) { Console.WriteLine("EventDeclaration"); Debug(node); base.Visit(node); } ... } }
TSqlConcreteFragmentVisitor クラス (Microsoft.SqlServer.TransactSql.ScriptDom) を継承して、最下層のクラスだけ処理します。
で、partial で必要なとこだけ拡張していきます。
using Microsoft.SqlServer.TransactSql.ScriptDom; using System; namespace ScriptDom.SqlDatabase.Test { public partial class DebugVisitor { public void Debug(TSqlFragment node) { } public void Debug(FunctionCall node) { Console.WriteLine(node.FunctionName.Value.ToUpper()); } } }
T4 久しぶりで書き方忘れてる。。