$30 off During Our Annual Pro Sale. View Details »

Behind Biome

unvalley
January 20, 2024
3.1k

Behind Biome

Biomeの裏側 Parser/Linter
buirkaigi 2024の資料です。トークは20分を前提としています。

---
Behind Biome Parser/Linter
This is used at burikaigi 2024 (20 minutes)

unvalley

January 20, 2024
Tweet

Transcript

  1. About me - unvalley - A core contributor of Biome

    - TypeScript / Rust / Scala @unvalley_ unvalley 2
  2. Biome - One toolchain for your web project - パフォーマンスに優れたRust製のWebツールチェーン

    - Analyzer / Linter / Formatterを提供(CLI, LSP, WASMで利用可能) - Prettierと約97%の互換性(対象はJS, TS, JSX のフォーマット) - 190以上のLintルールを実装(ESLintなどからの移植や固有のもの) - Sponsored by: 時雨堂, トヨクモ, 要, nanabit, GitHub sponsors 3 Rome Biome
  3. Roadmap 2024 - Help users to move to Biome -

    Expand Biome’s language support so Biome tools can span more of the web ecosystem - Deepen Biome’s existing capabilities to offer more functionalities - Plugins - Transformations - Community and content https://biomejs.dev/blog/roadmap-2024/ 6
  4. Biomeを試す 7 - npm, yarn, pnpm, deno, bunで利用できます - Homebrewでもインストール可能:brew

    install biome - 業務で使ってるプロジェクトやOSSなどで試してみてください - Docs : https://biomejs.dev - Playground : https://biomejs.dev/playground npx @biomejs/biome check --apply . // format and lint with npx
  5. Biome Parser (crates/biome_parser) - BiomeのParserの基盤 - biome_{js/json/css}_parser から利用して、それぞれのparse処理を実装している - lex処理もbiome_parser

    crate内に実装されている - Green and Red Treeを利用する - Parseプロセスで、Green Tree(コードに忠実で不変なデータ構造)と Red Tree (Green Treeから構築される親子関係の情報を持つ可変な データ構造)を生成する手法 - Lossless: コードが不正な場合でも、Parserはツリーを正確に表現する - Resillient: コードが不正な場合でも、Parserは入力に含まれる構文の断 片を可能な限り見ようとする 11
  6. Rowan (rust-analyzer/rowan) - Rust AnalyzerチームによるGreen/Red Treeを実装したライブラリ - Biomeでは、biome_rowan crateを利用して、Green and

    Red Treeを作成し ている 12 解説:https://github.com/rust-lang/rust-analyzer/blob/master/docs/dev/syntax.md
  7. Green Tree (CST) - コード内のトリビア* を含むすべて の情報を持つ、不変なデータ構造 - SyntaxKindとテキスト長を持つ -

    コードが変更されたら、部分的に再 構築して既存のツリーと統合する - Biomeのコード上、直接アクセスは できない *スペース・タブ・コメントなど 13
  8. Red Tree - Green Treeから計算される可変な データ構造 - Green Treeから、Red Tree

    (SyntaxNodes)を生成し、それ を型定義されたAST Nodesに変換 - Lint Rule実装などにおいては、 AST Nodesに対して、クエリを行 い、処理する - 親子関係の走査も可能 (SyntaxNodesのメソッド参照) 14 Red Treeから変換して生成されるAST Node
  9. 16

  10. biome_js_analyze と biome_analyze の構造 21 biome_json_analyze biome_analyze biome_js_analyze biome_css_analyze 1.

    biome_js_analyze には、各種Ruleが実 装されている(n>=190) 2. biome_js_analyze で、 biome_analyze::Analyzer を用意し、 Analyzer::run を実行 3. 各種Lint Ruleの診断結果とコードアク ションを収集 (Analyzer::emit_signal) Lint Rule Lint Rule Lint Rule
  11. biome_analyze::Analyzer の処理 1. biome_js_analyze から biome_analyze::Analyzer instance を作成 2. Analyzer::run

    メソッドでanalyzeを開始 - biome_analyze::PhaseRunner が、各Phaseにおいて Visitor にAstNodeに対する 特定のanalyzeタスクを実行させ、診断結果・コードアクションなどを生成 - Suppression Comment (// biome-ignore) の解析と適用 23
  12. 24

  13. biome_js_analyze と biome_analyze の構造 25 biome_json_analyze biome_analyze biome_js_analyze biome_css_analyze 1.

    biome_js_analyze には、各種Ruleが実 装されている(n>=190) 2. biome_js_analyze で、 biome_analyze::Analyzer を用意し、 Analyzer::run を実行 3. 各種Lint Ruleの診断結果とコードアク ションを収集 (Analyzer::emit_signal) Lint Rule Lint Rule Lint Rule
  14. JS用Analyzerのsetup : biome_js_analyze::analyze 1. 解析に必要なデータを引数で受け取る - root: AnalyzeするJavaScriptコードのルートノード - filter:

    Analyzeを制限するためのフィルター(特定のルールやソース範囲を指定) - options: Analyzeオプション(biome.jsonの設定) - source_type: Analyzeするソースコード種類(例:JSX、モジュールなど) - emit_signal: Lint Ruleが診断やアクションを発行した際に呼ばれる関数 2. biome_analyze::RuleRegistry (ActiveなLint Ruleの管理者) の構築 3. biome_analyze::Analyzer の初期化 4. 解析Phaseごとのbiome_analyze::Visitor の追加 5. biome_analyze::AnalyzerContextに、引数で得たデータを渡して、Analyzer::run を 実行 27
  15. biome_js_analyze と biome_analyze の構造 34 biome_json_analyze biome_analyze biome_js_analyze biome_css_analyze 1.

    biome_js_analyze には、各種Ruleが実 装されている(n>=190) 2. biome_js_analyze で、 biome_analyze::Analyzer を用意し、 Analyzer::run を実行 3. 各種Lint Ruleの診断結果とコードアク ションを収集 (Analyzer::emit_signal) Lint Rule Lint Rule Lint Rule
  16. 35 Lint Rule: NoUselessTernary Disallow ternary operators when simpler alternatives

    exist. (単純な代替が存在する場合に、三項演算子を許可しない)
  17. 36 var a = x ? true : true; をどうやってLintする?

    Parser処理後に構築されたAST Node: JsConditionalExpressionに Queryすれば、三項演算子をチェックできる
  18. 処理のまとめ 38 Lexing Parse Analyze / Lint / Format Tree

    Source Code Result biome_parserでError ResillientなParseを行い、 biome_rowanでGreen and Red Treeを構築する
  19. 処理のまとめ 39 Lexing Parse Analyze / Lint / Format Tree

    Source Code Result Analyzerのコアであるbiome_analyzeを基盤として、Tree を元に、biome_js_analyzeなどで実装したLint Ruleを適用 して、診断結果やコードアクションを生成する
  20. 処理のまとめ 40 Lexing Parse Analyze / Lint / Format Tree

    Source Code Result biome_parserでError ResillientなParseを行い、 biome_rowanでGreen and Red Treeを構築する Analyzerのコアであるbiome_analyzeを基盤として、Tree を元に、biome_js_analyzeなどで実装したLint Ruleを適用 して、診断結果やコードアクションを生成する
  21. 41

  22. 余談:個人的に好きなLintルール - noExcessiveCognitiveComplexity: (v1.0.0) - 認知複雑度の高いコードを禁止するlint - useFilenamingConvention (v1.5.0) -

    ファイル名を一貫したものにするlint - useImportRestrictions (v1.0.0) - privateなpackageからのimportを禁止するlint - uhyoさんのeslint-plugin-import-accessにinspireされている 43
  23. 参考資料 - biomejs.dev (https://biomejs.dev) - Deep Dive into Biome (https://speakerdeck.com/nissydev/deep-dive-into-biome-in-jsconf-2023)

    - Rust Dublin October 2023 - Biome (https://youtu.be/stxiUYmHn0s?si=VyLdx33ZbK3Kq2iX) - Persistence, Facades and Roslyn's Red-Green Trees (https://learn.microsoft.com/en-us/archive/blogs/ericlippert/persistence-facades-and-roslyns-red-green-trees) - Syntax in rust-analyzer (https://github.com/rust-lang/rust-analyzer/blob/master/docs/dev/syntax.md) - LintオタクによるLint解説(https://speakerdeck.com/orgachem/lintotakuniyorulintjie-shuo) 44