技术实现细节
Prettier 的打印器是基于 https://github.com/benjamn/recast 打印器的分支版本,其核心算法替换为 Wadler 在论文《https://homepages.inf.ed.ac.uk/wadler/papers/prettier/prettier.pdf》中描述的方案。目前仍保留部分 recast 的遗留代码待清理。
核心设计原理
中间表示(IR)架构
// 打印器输出示例
["(", line, arg, line, ")"]
- 抽象表示:打印器接收 AST 并生成中间表示(IR)
- 动态测量:运行时计算 IR 的行宽占用
- 智能折行:根据测量结果在
line
标记处自动折行
工作流程
深度探索工具
通过 https://prettier.io/playground 的 doc-explorer
模式可可视化 IR 处理过程:
- 打开侧边栏("Show options"按钮)
- 设置解析器为特殊值
doc-explorer
- 实时观察 IR 如何转换为最终输出
技术实现参考
更详细(尚不完善)的实现细节可查阅:
- https://github.com/prettier/prettier/blob/main/commands.md - 核心命令系统文档
- https://github.com/prettier/prettier/blob/main/src/document/printer.js - 打印器源码实现
关键源码片段
// 简化版打印逻辑
function printAst(ast) {
const doc = buildDoc(ast); // 生成中间表示
return formatDoc(doc); // 动态格式化输出
}
function buildDoc(node) {
// 递归构建IR
if (node.type === "CallExpression") {
return [
"(",
line, // 可折行点
...node.arguments.map(buildDoc),
line, // 可折行点
")"
];
}
// 其他节点处理...
}
算法优势
Wadler 算法相比传统方案的核心突破:
- 最优布局选择:在O(n)时间内找到最优折行方案
- 惰性计算:延迟折行决策直到必须执行时
- 布局组合子:通过基础操作符组合复杂布局
技术实现总结
Prettier 的打印系统采用三层架构设计:
- 解析层:将源代码转换为标准 AST
- 中间层:生成包含布局指令的中间表示(IR)
- 输出层:动态测量IR并决策最优输出格式
核心创新点在于:
- Wadler算法应用:解决代码格式化中的最优折行问题
- 布局组合子模型:通过基础命令(
line
,group
,indent
等)组合复杂格式 - 实时测量机制:运行时计算空间占用,实现智能折行
这种架构使 Prettier 能在保证输出质量的同时,维持O(n)时间复杂度,即使处理百万行级代码仍保持高效。通过https://prettier.io/playground的doc-explorer
模式,开发者可直观理解这一创新设计的工作机制。