はじめに
GritQLはソースコードの検索・修正を行う宣言型クエリ言語です。
GritQL is a declarative query language for searching and modifying source code.
GitHub - honeycombio/gritql: GritQL is a query language for searching, linting, and modifying code.
具体的な例を見たほうが分かりやすいと思うので載せると、以下のようなC#コードがあったとします。
// Bad : Console.WriteLineをできれば使いたくないモチベがある Console.WriteLine("Hello, World!"); // Good logger.LogInformation("Hello, World!");
例えばConsole.WriteLineの使用を禁止したいみたいなモチベがあったとき、今回紹介するGritQLを用いるとtree-sitterというパーサーを用いてコードから構文木(Syntax Tree)を生成し、検出や修正を行うことができます。
GitHub - tree-sitter/tree-sitter: An incremental parsing system for programming tools
# 初期化 $ grit init # コードに変更を加える $ grit apply --language csharp '`Console.WriteLine($msg)` => `logger.LogInformation($msg)`'
実際に実行するとちゃんとコードが変更されていることが確認できます。
// Bad : Console.WriteLineをできれば使いたくない logger.LogInformation("Hello, World!"); // Good logger.LogInformation("Hello, World!");
補足ですが、上記のモチベであればC#ならRoslyn Analyzerを利用する事がまず思い浮かぶかなと思います。それも非常良い選択肢です。一応Roslyn Analyzerとは実行タイミングや構文木以上の解析(意味解析)を行えるかどうかなどの違いがあります。
個人的には(開発体験を損なわない範囲で)Roslyn Analyzerを用意できればbetterですが、それ相応の実装コストと知識が求められるので、コスパよく対応するのにはGritQLも選択肢にあがるかなと思っています。
AIが結構RoslynAnalyzerやSourceGeneratorの実装得意説があるので、今後変わってくるのかもしれませんが。
C#をサポートした
公式ドキュメントのTarget Languagesに記載はないのですが、C#自体は対応しています。この記事で一番伝えたい点です。
docs.grit.io
といってもかなり発展途上なようで、ドキュメントには全く記載がありませんので注意です。(grit listやgrit apply、grit patterns listの-languageにcsharpを渡せるよくらい)
リポジトリを見た感じ、内部的にはtree-sitter-c-sharpを利用っぽいですね。
github.com
具体的には以下のIssueで進行していた奴です。話逸れますが、この機能実装したら$250みたいな投げ銭が行われていて凄い世界だなと感心してしまいました。
github.com
使い方
細かい文法や使い方は公式ドキュメントや他の方の記事を参照していただきたいですが、軽くだけ触れておきます。
インストール方法
$ npm install --location=global @getgrit/cli or $ curl -fsSL https://docs.grit.io/install | bash
文法
Patterns
$ grit apply --language csharp '`Console.WriteLine`'
Metavariables
完全に一致しているではなく、引数は任意の文字列でみたいな場合は$を接頭辞に変数を活用します。
$ grit apply --language csharp '`Console.WriteLine($msg)`'
Rewrites
検出だけでなく書き換えたいときは=>を利用します。
$ grit apply --language csharp '`Console.WriteLine($msg)` => `logger.LogInformation($msg)`'
Conditions
whereを利用することで条件を追加できます。!やandやnotなどもあります。
$ grit apply --language csharp '`Console.WriteLine($msg)` => `logger.LogInformation($msg)` where { $msg <: `"Hello, World!"` } '
詳細は以下参照。
Conditional Operators
ただ私の環境だとうまく動作しませんでした。ここら辺以降、C#なせいか私のミスのせいかは後で要調査。
GritQL Tutorial
設定ファイル
.grit/grit.yamlを用いることでパターンの設定を保存することができます。テスト(grit patterns test)もできたりと、結構使いやすかったです。
version: 0.0.1 patterns: - name: avoid_only tags: ["style", "debugging"] level: error body: | `$testlike.only` => `$testlike` where { `$testlike` <: or { `describe` `it` `test` } } description: | .only is usually a mistake left over from local debugging. Pushing it to main risks false negatives on CI. samples: - input: | describe.only('this is a test', () => { // ... }); output: | describe('this is a test', () => { // ... }); - name: disabled_pattern level: none # This pattern is disabled body: | `something` => `somewhere` - file: ../other/doc/file.md
またマークダウンで記述もできるっぽいです。
さいごに
おそらくGritQLでC#を活用している方はかなり少数派だと思います。というか情報がドキュメントも含めて全くありません。
是非皆さんも一度手に取ってみて、情報共有してくださると嬉しいです。