Biome JS 格式化器 Prettier 兼容性测试报告解读:96.92% 相似度背后的指标体系与差异全景 📅 发布时间:2026/9/20 11:04:06 👁 浏览次数: Biome JS 格式化器 Prettier 兼容性测试报告解读96.92% 相似度背后的指标体系与差异全景【免费下载链接】biomeA toolchain for web projects, aimed to provide functionalities to maintain them. Biome offers formatter and linter, usable via CLI and LSP.项目地址: https://gitcode.com/gh_mirrors/bi/biome本篇技术指南以 Biome 仓库中 crates/biome_js_formatter/report.md 的实测报告为骨架系统讲解 Biome 的 JavaScript/TypeScript/JSX 格式化器如何通过 Prettier 官方测试语料库量化自身的Prettier 相似度包括平均兼容性与兼容行数两大指标的定义、1291 个测试用例的组织与评分机制、以及全部未达 100% 差异用例的分类与成因。读完本文你将掌握这套兼容性报告体系的完整读法能够自行复现报告并理解每一类 diff 背后对应的源码实现与刻意取舍。报告是什么一份可量化的格式化器兼容性体检单Biome 的 JavaScript 格式化器crate 名为biome_js_formatter仓库内说明见 crates/biome_js_formatter/README.md从诞生之初就把与 Prettier 输出兼容作为核心工程目标之一。report.md正是这一目标的数字化体检单它逐条运行 Prettier 官方测试套件位于crates/biome_js_formatter/tests/specs/prettier/下的js/、jsx/、typescript/三个目录将 Biome 的格式化输出与 Prettier 的输出逐文件做 diff为每个文件打出 0~100 的相似度分数并在文件级和行级两个维度上汇总出总体指标。整个报告共 10420 行覆盖1291 个测试用例其中1183 个用例达到 100.00% 的完美相似度约 91.6%剩余约 108 个用例附带了逐行 diff 以供排查。与它配套的还有 report-es2015.md、report-es2024.md按语法时代分别统计的挑战版报告与 report_incompatible.md仅含不兼容用例的精简报告其背景与口径在 report-challenge.md 中有详细说明。指标体系平均兼容性与兼容行数是怎么算出来的报告开头的 Overall Metrics 定义了两个总体指标本文原样保留其公式平均兼容性Average compatibility96.92$$\average \frac{\sum_{file}^{files}compatibility_{file}}{files}$$即每个测试文件的 Prettier 相似度得分compatibility_file相加后除以文件总数得到所有测试文件的算术平均相似度。兼容行数Compatible lines97.67$$\average \frac{\sum_{file}^{files}matching_lines_{file}}{max(lines_{rome}, lines_{prettier})}$$即对每个文件统计 Biome 与 Prettier 输出中逐行匹配的行数matching_lines_file以两个输出中行数较大者为分母逐文件求和后相除。注意公式中仍保留了项目前身 Rome 的命名lines_rome是历史命名遗留现行实现中对应 Biome 自身。源码级的指标实现这两个指标的落盘实现位于 crates/biome_formatter_test/src/diff_report.rs是整个报告体系的公共基础设施不仅 JSCSS 等语言的格式化器共用同一套SingleFileMetricData结构体记录每个文件的filename与single_file_compatibility即报告正文中每个用例的Prettier Similarity其is_compatible()方法以(compatibility * 100.0) 100.00判定该文件是否完美兼容这正是1183 个 100.00%的判定逻辑文本 diff 依赖similarcrate 的diff_lines做逐行比较并在输出时以-Prettier 独有行与Biome 独有行标注差异PrettierCompatibilityMetricData汇总file_based_average_prettier_similarity与line_based_average_prettier_similarity两个平均值分别对应报告中的两项 Overall Metrics。一个值得注意的实现细节报告的生成由进程退出钩子驱动。DiffReport::get()通过Once注册一个atexit回调在测试进程退出时统一打印/落盘报告且只有设置了环境变量REPORT_PRETTIER1才会收集数据。这意味着兼容性报告是测试基础设施的按需开关日常跑测试不会产生额外 IO。测试用例的组织方式Prettier 官方语料库的镜像报告第三部分 Test cases 按js/目录/文件.js的路径逐条罗列用例例如js/arrays/numbers1.js、js/arrows/currying-4.js、js/comments/return-statement.js、typescript/union/union-parens.ts等。这些路径与测试输入文件一一对应语料本身来自 Prettier 官方测试套件被镜像进仓库的crates/biome_js_formatter/tests/specs/prettier/目录顶层分为js/、jsx/、typescript/三个分支js下又细分arrays、arrows、assignment、async、comments、decorators、for、range等几十个专题子目录。测试入口与执行机制报告所对应的测试由 crates/biome_js_formatter/tests/prettier_tests.rs 驱动其核心逻辑值得关注tests_macros::gen_tests! {tests/specs/prettier/{js,typescript,jsx}/**/*.{js,ts,jsx,tsx}, crate::test_snapshot, script}gen_tests!宏在编译期展开为每个输入文件生成一个独立测试函数test_snapshot中PrettierTestFile负责读取输入并定位同名的 Prettier 期望输出源文件类型推断有特殊处理js文件一律按JsFileSource::jsx()解析因为 Prettier 测试套件中 JS 文件可能含 JSX 标签文件名含jsx的ts文件按tsx解析格式化选项统一为IndentStyle::Space 默认IndentWidth即 Prettier 的默认风格PrettierSnapshot::new(...)组装出JsFormatLanguage后执行snapshot.test()该流程同时做两件事与 Prettier 输出比对打分进入报告以及用 Biome 自身对输出做二次格式化校验CheckReformat用于捕获格式化不稳定问题。测试范围与口径哪些用例被排除、为什么报告正文只给出了结果而其边界条件哪些用例不算数在 report-challenge.md 中写得非常清楚。理解这四类边界才能正确解读 96.92 这个数字。被忽略的测试用例Ignored test casesreport.md与两份 challenge 报告对以下三类用例不计分JSX 相关用例js/binary-expressions/inline-jsx.js、js/comments/jsx.js、js/last-argument-expansion/jsx.js、js/trailing-comma/jsx.js、js/yield/jsx.js等十余个但在report.md中它们仍被列出并打分只是 challenge 统计时剔除模板字符串内的嵌入语言格式化js/multiparser-comments/、js/multiparser-css/、js/multiparser-graphql/、js/multiparser-html/、js/multiparser-markdown/、js/template-literals/styled-components-with-expressions.js等——Prettier 会在模板字面量中嵌入格式化 CSS/GraphQL/HTML 等Biome 的对应机制尚不完整非标准与实验性语法js/v8_intrinsic、js/babel-plugins/、js/async-do-expressions/、js/do/、export X from mod、module id {}module blocks、元组/记录#[]#{}、管道运算符|、绑定运算符::、js/destructuring-private-fields/、js/deferred-import-evaluation/、js/source-phase-imports/、js/import-reflection/等。此外ES2015 版报告report-es2015.md还额外忽略 ES2016 语法装饰器、js/import-assertions/、js/import-attributes/、显式资源管理using、幂等运算符**、async/await、函数调用尾逗号、对象展开{...x}、for await、私有字段#field、可选链?.、空值合并??、BigInt、数字分隔符1_000、逻辑赋值??、静态块static {}、顶层await、shebang、正则d/v标志等。非严格模式用例Non-strict test casesjs/with/、js/sloppy-mode/、js/identifier/三组用例以非严格sloppy/script模式解析对应测试代码中is_non_strict_mode()检查后调用source_type.with_module_kind(ModuleKind::Script)的逻辑。不稳定用例Unstable test casesPrettier 自身对部分输入存在重复格式化两次结果不同的不稳定问题。Biome 的测试基础设施即上文提到的CheckReformat会捕获这类问题并选择稳定化后的版本通常第二次运行即稳定作为比对基准。受影响用例包括js/sequence-expression/parenthesized.js、js/comments/tagged-template-literal.js、js/comments/return-statement.js、js/last-argument-expansion/embed.js、js/for/continue-and-break-comment-without-blocks.js、js/class-comment/misc.js、js/range/boundary.js、js/range/class-declaration.js、js/range/multiple-statements2.js。刻意分歧Deliberate formatting divergences部分差异是有意为之要么源于 Biome 解析阶段的严格性要么是 Biome 团队认为自身输出可读性更好而保留。这意味着 100% 相似度并非项目的唯一追求个别低分用例反而是设计决策的体现。选项支持说明report-challenge.md还明确声明Biome 实现了 Prettier 提供的全部 JavaScript 格式化选项唯一例外是quoteProps选项只提供as-needed与preserve两个取值不提供 Prettier 的consistent这是刻意选择。未达 100% 的差异用例全景通过统计报告中的 Prettier Similarity 字段1291 个用例中 1183 个为 100.00%其余约 108 个分布在 60~98% 与 0% 两个区间。综合各用例附带的 diff 与上文的边界说明可将其归为以下几类每类都指向明确的源码或设计因素注释位置与注释排版占比最大的一类注释是格式化器中最难对齐的部分绝大多数低分用例都与之相关js/arrays/numbers-with-holes.js96.43%稀疏数组[,,]中数组空洞前后注释的归属位置不同const numberWithHoles2 [ 0x234932941, 0x234932722, 0x234932312, - , // comment before a hole 2 0x234932841, , 0x234932843, , // comment after a hole 2 0x234932436, ];js/arrows/currying-4.js98.17%多层柯里化箭头函数的尾注释顺序/* b */ /* c */vs/* c */ /* b */js/comments/empty-statements.js13.33%相邻多行注释被合并为单行// first // second属于注释密集场景下的显著排版分歧js/comments/export.js97.37%export关键字后悬挂注释的归属js/comments/tagged-template-literal.js85.71%标签模板字面量中注释与反引号之间的空白处理-foo/* comment */ foo /* comment */ ;js/comments/multi-comments-on-same-line.js96.67%、js/comments/return-statement.js96.41%、js/conditional/comments.js97.56%、js/if/expr_and_same_line_comments.js97.73%、js/template-literals/expressions.js93.65%、jsx/comments/in-attributes.js73.33%、jsx/comments/in-end-tag.js96.55%TypeScript 侧typescript/comments/16065.ts63.64%、typescript/comments/16065-2.ts62.96%、typescript/comments/type-parameters.ts87.10%、typescript/union/union-parens.ts92.59%类型别名type A /*1*/ C中注释前移等。函数调用与参数展开启发式js/break-calls/react.js61.17%useImperativeHandle(ref, () {...}, [deps])这类三参调用Biome 选择将三个参数全部展开成多行break 所有参数策略而 Prettier 保持单行——这是对 React Hooks 长依赖数组场景的不同取舍同组js/break-calls/break.js、js/break-calls/parent.js则达到 100.00%说明分歧集中在具体参数形态js/last-argument-expansion/dangling-comment-in-arrow-function.js20.00%末参展开时箭头函数内悬挂注释的处理js/objects/assignment-expression/object-property.js66.67%对象属性值为赋值表达式时的括号/换行策略。语法错误或非法输入0.00% 的主因这类用例输入本身不是合法程序格式化结果没有可比性0 分属于预期行为js/arrows/newline-before-arrow/newline-before-arrow.js解析失败后输出被拆成async; x; x的碎片js/return-outside-function/return-outside-function.js函数外returnjs/sloppy-mode/function-declaration-in-while.jswhile 循环内的函数声明js/test-declarations/optional.js。实验性语法import assertions / attributesjs/import-assertions/bracket-spacing/empty.js、js/import-assertions/empty.js0.00%~42.86%、js/import-attributes/empty.js0.00%、js/import-attributes/keyword-detect.js20.00%、js/import-attributes/long-sources.js61.54%assert { type: json }/with { type: json }这类新语法在括号换行与关键字检测上尚未完全对齐。范围格式化Range Formattingjs/range/boundary.js60.00%、js/range/boundary-2.js33.33%、js/range/boundary-3.js50.00%、js/range/class-declaration.js57.14%、js/range/multiple-statements2.js72.73%、js/range/nested3.js42.86%、js/range/whitespace.js0.00%编辑器仅格式化选区场景涉及上下文截断本就是格式化器公认难点且其中数个用例同时属于上文不稳定用例清单。控制流与语法结构细节js/for/for-in-with-initializer.js37.50%for (const x in y 1)这类带初始化器的for-in非严格模式产物js/for/continue-and-break-comment-without-blocks.js98.55%无块continue/break后注释js/for/parentheses.js94.12%for头部的括号处理js/ignore/issue-14404.js28.57%// biome-ignore/// prettier-ignore与 async 语法组合js/quotes/objects.js80.00%对象键的引号策略。TypeScript 专属差异typescript/chain-expression/test.ts0.00%、typescript/assignment/issue-5370.ts0.00%、typescript/union/single-type/single-type.ts0.00%分别涉及链式表达式、赋值与单一成员联合类型是 TS 侧少数完全未对齐的用例typescript/prettier-ignore/issue-14238.ts0.00%与typescript/prettier-ignore/prettier-ignore-nested-unions.ts62.96%// prettier-ignore指令在 TS 类型上下文中的行为差异typescript/definite/without-annotation.ts25.00%definite assignment 断言!的注解处理typescript/intersection/consistent-with-flow/intersection-parens.ts69.77%、typescript/conditional-types/parentheses.ts64.00%交叉类型与条件类型的括号策略typescript/arrow/16067.ts80.39%、typescript/arrow/comments.ts88.89%、typescript/class/quoted-property.ts66.67%、typescript/class/empty-method-body.ts80.00%、typescript/decorators-ts/angular.ts87.50%、typescript/decorators-ts/typeorm.ts82.61%、typescript/last-argument-expansion/decorated-function.tsx27.87%装饰器与末参展开叠加、typescript/type-alias/conditional.ts41.67%等。如何复现这份报告报告不是手工整理的静态文档而是测试基础设施的产物。想要在当前仓库复现需要确认环境满足仓库的 Rust 工具链要求见根目录 rust-toolchain.toml运行 JS 格式化器的 Prettier 兼容性测试并开启报告收集开关。根据 crates/biome_formatter_test/src/diff_report.rs 的源码核心环境变量如下环境变量取值作用REPORT_PRETTIER1启用报告数据收集唯一总开关未设置则不生成报告REPORT_TYPEmarkdown默认/json输出格式INCOMPATIBLE_ONLY1仅输出未达 100% 的用例对应report_incompatible.md系列REPORT_FILENAME自定义文件名覆盖默认文件名默认按类型与INCOMPATIBLE_ONLY组合为report.md/report.json/report_incompatible.md/report_incompatible.json例如生成与仓库内report.md相同的 Markdown 报告REPORT_PRETTIER1 cargo test -p biome_js_formatter --test prettier_tests生成仅含不兼容用例的报告REPORT_PRETTIER1 INCOMPATIBLE_ONLY1 REPORT_FILENAMEreport_incompatible.md cargo test -p biome_js_formatter --test prettier_tests生成 JSON 格式报告REPORT_PRETTIER1 REPORT_TYPEjson cargo test -p biome_js_formatter --test prettier_tests需要说明的是报告数值是随代码演进动态变化的仓库中提交的report.md快照只是某一时刻的结果实际数字会因测试语料的增删与格式化器实现的迭代而波动。总结如何正确理解 96.92 这个数字综合全文对这份报告应形成以下判断框架96.92文件级平均兼容性与 97.67行级兼容比例是两个互补的视角前者体现有多少文件完全一致后者体现在不完全一致的文件里逐行重合度有多高——两者都超过 96%且 91.6% 的用例拿到满分 100.00%说明与 Prettier 的兼容是大面积精确、局部有界分歧的状态低分用例不等于缺陷约 108 个未满分用例中相当一部分来自注释排版策略差异、Prettier 自身不稳定的输入、语法错误的非法程序、实验性语法以及 Range 格式化的固有难点还有被 report-challenge.md 明确标注的刻意分歧这是一套可复现、可量化的工程方法论依托 tests/prettier_tests.rs 的宏驱动测试与 diff_report.rs 的REPORT_PRETTIER报告管线任何一次格式化器改动都能立即得到与 Prettier 的兼容性体检结果这正是 Biome 将兼容 Prettier这一目标工程化、持续化的核心机制。【免费下载链接】biomeA toolchain for web projects, aimed to provide functionalities to maintain them. Biome offers formatter and linter, usable via CLI and LSP.项目地址: https://gitcode.com/gh_mirrors/bi/biome创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考