こんにちは、ast-grepの作者Herringtonです。
正規表現でコードを検索したことがある方なら、複数行のマッチングや入れ子構造の処理、コメントの無視などに苦労したことがあるかもしれません。
そこで、ast-grep VSCodeという新しい拡張を紹介します。これは、構造的検索と置換(SSR)という技術を利用して、より正確で効率的な検索と置換を実現するツールです。
例えば、JavaScriptコードをリファクタリングして、lodash の_.filter
関数をネイティブのArray.prototype.filter
メソッド に置き換えたいとします。単純なテキスト検索と置換は次のようになります:
// 検索_.filter\((\.+),(.+)\)// 置換$1.filter($2)
これは一部のケースではうまくいくかもしれませんが、いくつかの問題があります。
検索アルゴリズムをもっと賢くし、コードをもっと理解しやすくし、使いやすくすることはできないでしょうか?はい!構造的検索と置換(SSR)が素晴らしい解決策となります!
構造検索と置換 (Structural Search/Replace) は、コードパターンをその構文と意味に基づいて検索および変更する技術です。単なるテキストとしてではなく、SSRは、タイプ、プロパティ、および関係を持つノードのコレクションとしてコードを扱います。
ast-grep は、SSRを実装したコマンドラインツールです。上記のlodashの例のクエリは非常にシンプルです。
// 検索パターン:_.filter($ARR, $FUNC)// 書き換え:$ARR.filter($FUNC)
このパターンは、ast-grepの基本的な使い方を示しています。$ARR
と$FUNC
はメタ変数です。メタ変数は、正規表現のドット.
と似ていますが、文字ではなくASTノードにマッチします。また、置換パターンでキャプチャされたメタ変数を使うこともできます。
メタ変数以外は、パターンと置換が自明であるとおもいます。
このクエリは、テキストベースの検索と置換に比べていくつかの利点があります。
ast-grepは、多くのプログラミング言語に対応した高速で堅牢なパーサーであるtree-sitterライブラリを使用しています。ast-grepでは、コードに似たシンプルなパターン構文を使ってクエリを書き、コードのファイルやディレクトリに適用することができます。ast-grepのユニークな機能の一部は以下の通りです。
しかし、ast-grepは今のところコマンドラインインターフェースしかありません。ターミナルとエディターを切り替えるのではなく、手元でその力を使えるようになることはできないでしょうか?
ast-grep VSCodeは、ast-grepをVisual Studio Codeという人気の高いコードエディターと統合する新しい拡張機能です。ast-grep VSCodeを使えば、エディター内でSSRを使うことができ、ワークフローから離れることなくコードを改善できます。
ast-grep VSCodeの機能の一部は以下の通りです。
機能 | スクリーンショット |
---|---|
検索パターン | ![]() |
フォルダ内検索 | ![]() |
置換プレビュー | ![]() |
置換コミット | ![]() |
コードリンティング | ![]() |
他にもSSRツールや拡張機能はあります。しかし、ast-grep VSCodeがVSCodeの中で最高のSSR拡張機能の一つだと思っています。なぜなら:
最後に、ast-grep VSCodeで使われているReactのテクニックのいくつかを紹介します。これらはast-grep VSCodeを高速でレスポンシブにするのに役立っています。
useSyncExternalStore
は、ast-grep CLIからのストリーミング結果を管理するのに使われました。このフックは、コンポーネントが外部の可変なデータソースにサブスクライブして、レンダリングを適切に更新することを可能にします。このようにして、拡張機能は結果をすぐに表示することができます。useDeferredValue
は、結果リストのレンダリングを遅延させました。このフックは、派生した状態の更新を次の並行レンダーまで遅らせることで、ユーザー入力をブロックすることを避け、UIのパフォーマンスを向上させることができます。memo
やCSSのテクニックを丁寧に多用しています。この記事がSSRのメリットやast-grep VSCodeの機能について理解するのに役立つと思います。もし試してみたいと思ったら、VSCode Marketplaceからインストールすることができます。ast-grep VSCodeはまだ開発中で、改善の余地がたくさんあります。フィードバックや提案を聞きたいので、GitHubでイシューやプルリクエストを気軽に開いてください。また、SoonIterさん、Steven Loveさん、Nyakku Shigureさん、ssr.nvimにも、貢献やインスピレーションをありがとうと言いたいです!
楽しく grep しましょう!
私も似たような拡張機能を作っているものです。(HTML Likeなファイルをターゲットにしてます。)
Typescriptで同じようなことがやりたかったのでぜひ今後使わせていただきます。
また、アプローチ自体は知っていたのですが、構造的検索と置換(SSR)
という名前があることを知ることができ大変勉強になりました。
最後にいくつか共有させてください。
・私の環境(Windows10)では導入する際、npm i @ast-grep/cli -gした後、(もしかするとvscode再起動も?)preference>Ast Grep: Server Pathをデフォルトからast-grep.cmdに変更する必要がありました。
ちなみに、cargoからのインストールは私の環境にgccがインストールされておらず失敗しました。
(tree-sitterのビルドで失敗してるようでした。)
・検索パターンには、通常の$METHOD($ARGS)
パターンとyamlで記載するパターンがあるようですが、拡張機能ではyamlサポートされていないのでしょうか。
・リポジトリを確認したのですが、l10n(ローカライズ)の対応はサポートされるのでしょうか。
先日Webviewへのl10nファイルの受け渡しを行うことができたので、もしよければ参考にしてください。
https://github.com/microsoft/vscode/issues/206547
・置換において、ネストされたパターンを置き換える際、親のみ置換、親と影響しない子を置換する方法があると考えているのですが、ast-grepではどのように考えていますでしょうか。
ちなみに私のほうは全件置き換える場合、親のみ置換する方向で進めていますが、将来的には後者の方法に移行したいと考えています。
長くなりましたが、とても良い拡張機能だと思います。
コメント頂きありがとうございます!とても思いやりのある詳しい返信で、感謝します🫰。
海外の開発者なので日本語が下手し、多数のmachine翻訳を利用し、言い間違いがあったら気にしないでください🙏
ありがとうございます!
Windowsのデフォルトコマンドはver0.1.1でast-grep.exeに変更しました。たぶん設定しないも動けるとおもいます。
ご報告ありがとう!
こんにちは、Herrintonと申します。ast-grepというツールの作者です。ast-grepは、抽象構文木(AST)を使ってコードを検索するコマンドラインツールです。PythonやJavaScriptなどの言語に対応しています。よろしくお願いします。