mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
feat(prettier): init project and infrastructure (#1260)
> [!NOTE] > This is going to be a community project because I don't have the time and energy to work on this alone. # Prettier Background: 22.5K USD bounty for prettier written in Rust?! See https://console.algora.io/challenges/prettier > [!WARNING] > ## Contribution Agreement > > You hereby agree that you contribute for fun and for the purpose of learning, not for the goal of winning the challenge. > > In the unlikely event of winning the challenge, @boshen will ultimately decide on how to spend the money. > > [!IMPORTANT] Please talk to me on [discord](https://discord.com/invite/9uXCAwqQZW) and indicate that you are willing to contribute and agree to the contribution agreement. ## Getting started Create a `test.js` and run the example `just example prettier` from `crates/oxc_prettier/examples/prettier.rs`, follow the code structure and read the references documented at the top of the files. # Tasks - [x] Have the basic infrastructure ready for contribution - [ ] Implement a test runner in Rust which extracts the snapshots and do a comparison over it - [ ] Establish a way to pass all the tests by manually porting code - [ ] Pass as many tests as possible in https://github.com/prettier/prettier/tree/main/tests/format/js
This commit is contained in:
parent
f3788eec31
commit
65be4acdd4
9 changed files with 1256 additions and 0 deletions
11
Cargo.lock
generated
11
Cargo.lock
generated
|
|
@ -1768,6 +1768,17 @@ dependencies = [
|
|||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "oxc_prettier"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"oxc_allocator",
|
||||
"oxc_ast",
|
||||
"oxc_parser",
|
||||
"oxc_span",
|
||||
"oxc_syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "oxc_query"
|
||||
version = "0.0.0"
|
||||
|
|
|
|||
25
crates/oxc_prettier/Cargo.toml
Normal file
25
crates/oxc_prettier/Cargo.toml
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
[package]
|
||||
name = "oxc_prettier"
|
||||
version = "0.0.0"
|
||||
publish = false
|
||||
authors.workspace = true
|
||||
description.workspace = true
|
||||
edition.workspace = true
|
||||
homepage.workspace = true
|
||||
keywords.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
rust-version.workspace = true
|
||||
categories.workspace = true
|
||||
|
||||
[lib]
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
oxc_allocator = { workspace = true }
|
||||
oxc_ast = { workspace = true }
|
||||
oxc_syntax = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
oxc_parser = { workspace = true }
|
||||
oxc_span = { workspace = true }
|
||||
30
crates/oxc_prettier/README.md
Normal file
30
crates/oxc_prettier/README.md
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
> [!NOTE]
|
||||
> This is going to be a community project because I don't have the time and energy to work on this alone.
|
||||
|
||||
# Prettier
|
||||
|
||||
Background: 22.5K USD bounty for prettier written in Rust?!
|
||||
|
||||
See https://console.algora.io/challenges/prettier
|
||||
|
||||
> [!WARNING]
|
||||
> ## Contribution Agreement
|
||||
>
|
||||
> You hereby agree that you contribute for fun and for the purpose of learning, not for the goal of winning the challenge.
|
||||
>
|
||||
> In the unlikely event of winning the challenge, @boshen will ultimately decide on how to spend the money.
|
||||
>
|
||||
|
||||
> [!IMPORTANT]
|
||||
Please talk to me on [discord](https://discord.com/invite/9uXCAwqQZW) and indicate that you are willing to contribute and agree to the contribution agreement.
|
||||
|
||||
## Getting started
|
||||
|
||||
Create a `test.js` and run the example `just example prettier` from `crates/oxc_prettier/examples/prettier.rs`, follow the code structure and read the references documented at the top of the files.
|
||||
|
||||
# Tasks
|
||||
|
||||
- [x] Have the basic infrastructure ready for contribution
|
||||
- [ ] Implement a test runner in Rust which extracts the snapshots and do a comparison over it
|
||||
- [ ] Establish a way to pass all the tests by manually porting code
|
||||
- [ ] Pass as many tests as possible in https://github.com/prettier/prettier/tree/main/tests/format/js
|
||||
23
crates/oxc_prettier/examples/prettier.rs
Normal file
23
crates/oxc_prettier/examples/prettier.rs
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
use std::{env, path::Path};
|
||||
|
||||
use oxc_allocator::Allocator;
|
||||
use oxc_parser::Parser;
|
||||
use oxc_span::SourceType;
|
||||
|
||||
use oxc_prettier::{Prettier, PrettierOptions};
|
||||
|
||||
// Instruction:
|
||||
// create a `test.js`,
|
||||
// run `cargo run -p oxc_prettier --example prettier`
|
||||
// or `just example prettier`
|
||||
|
||||
fn main() {
|
||||
let name = env::args().nth(1).unwrap_or_else(|| "test.js".to_string());
|
||||
let path = Path::new(&name);
|
||||
let source_text = std::fs::read_to_string(path).unwrap_or_else(|_| panic!("{name} not found"));
|
||||
let allocator = Allocator::default();
|
||||
let source_type = SourceType::from_path(path).unwrap();
|
||||
let ret = Parser::new(&allocator, &source_text, source_type).parse();
|
||||
let output = Prettier::new(&allocator, PrettierOptions).build(&ret.program);
|
||||
println!("{output}");
|
||||
}
|
||||
34
crates/oxc_prettier/src/document.rs
Normal file
34
crates/oxc_prettier/src/document.rs
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
//! Prettier IR
|
||||
//!
|
||||
//! References:
|
||||
//! * <https://github.com/prettier/prettier/blob/main/commands.md>
|
||||
|
||||
use oxc_allocator::{String, Vec};
|
||||
|
||||
use crate::Prettier;
|
||||
|
||||
pub enum Doc<'a> {
|
||||
Str(&'a str),
|
||||
// perf: can we use &[Doc] here?
|
||||
Array(Vec<'a, Doc<'a>>),
|
||||
Indent(Vec<'a, Doc<'a>>),
|
||||
Group(Vec<'a, Doc<'a>>),
|
||||
/// Specify a line break.
|
||||
/// If an expression fits on one line, the line break will be replaced with a space.
|
||||
/// Line breaks always indent the next line with the current level of indentation.
|
||||
Line,
|
||||
Softline,
|
||||
}
|
||||
|
||||
/// Doc Builder
|
||||
impl<'a> Prettier<'a> {
|
||||
#[inline]
|
||||
pub fn vec<T>(&self) -> Vec<'a, T> {
|
||||
Vec::new_in(self.allocator)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn str(&self, s: &str) -> Doc<'a> {
|
||||
Doc::Str(String::from_str_in(s, self.allocator).into_bump_str())
|
||||
}
|
||||
}
|
||||
967
crates/oxc_prettier/src/format.rs
Normal file
967
crates/oxc_prettier/src/format.rs
Normal file
|
|
@ -0,0 +1,967 @@
|
|||
//! Formatting logic
|
||||
//!
|
||||
//! References:
|
||||
//! * <https://github.com/prettier/prettier/blob/main/src/language-js/print/estree.js>
|
||||
|
||||
#![allow(unused_variables)]
|
||||
|
||||
use oxc_allocator::{Box, Vec};
|
||||
#[allow(clippy::wildcard_imports)]
|
||||
use oxc_ast::ast::*;
|
||||
use oxc_syntax::operator::BinaryOperator;
|
||||
|
||||
use crate::{document::Doc, format, group, indent, softline, string, Prettier};
|
||||
|
||||
pub trait Format<'a> {
|
||||
#[must_use]
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a>;
|
||||
}
|
||||
|
||||
impl<'a, T> Format<'a> for Box<'a, T>
|
||||
where
|
||||
T: Format<'a>,
|
||||
{
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
(**self).format(p)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for Program<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
let mut parts = p.vec();
|
||||
parts.extend(self.body.iter().map(|stmt| stmt.format(p)));
|
||||
Doc::Array(parts)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for Directive {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for Statement<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
match self {
|
||||
Self::BlockStatement(stmt) => stmt.format(p),
|
||||
Self::BreakStatement(stmt) => stmt.format(p),
|
||||
Self::ContinueStatement(stmt) => stmt.format(p),
|
||||
Self::DebuggerStatement(stmt) => stmt.format(p),
|
||||
Self::DoWhileStatement(stmt) => stmt.format(p),
|
||||
Self::EmptyStatement(stmt) => stmt.format(p),
|
||||
Self::ExpressionStatement(stmt) => stmt.format(p),
|
||||
Self::ForInStatement(stmt) => stmt.format(p),
|
||||
Self::ForOfStatement(stmt) => stmt.format(p),
|
||||
Self::ForStatement(stmt) => stmt.format(p),
|
||||
Self::IfStatement(stmt) => stmt.format(p),
|
||||
Self::LabeledStatement(stmt) => stmt.format(p),
|
||||
Self::ModuleDeclaration(decl) => decl.format(p),
|
||||
Self::ReturnStatement(stmt) => stmt.format(p),
|
||||
Self::SwitchStatement(stmt) => stmt.format(p),
|
||||
Self::ThrowStatement(stmt) => stmt.format(p),
|
||||
Self::TryStatement(stmt) => stmt.format(p),
|
||||
Self::WhileStatement(stmt) => stmt.format(p),
|
||||
Self::WithStatement(stmt) => stmt.format(p),
|
||||
Self::Declaration(decl) => decl.format(p),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for ExpressionStatement<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
self.expression.format(p)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for EmptyStatement {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for IfStatement<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
let mut parts = p.vec();
|
||||
|
||||
let opening = group![
|
||||
p,
|
||||
string!(p, "if ("),
|
||||
group!(p, indent!(p, softline!(), format!(p, self.test), softline!())),
|
||||
string!(p, ")"),
|
||||
format!(p, self.consequent)
|
||||
];
|
||||
parts.push(opening);
|
||||
|
||||
if let Some(alternate) = &self.alternate {
|
||||
parts.push(string!(p, "else"));
|
||||
parts.push(group!(p, format!(p, alternate)));
|
||||
}
|
||||
|
||||
Doc::Array(parts)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for BlockStatement<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
let mut parts = p.vec();
|
||||
parts.push(p.str("{"));
|
||||
parts.push(Doc::Softline);
|
||||
parts.extend(self.body.iter().map(|stmt| stmt.format(p)));
|
||||
parts.push(Doc::Softline);
|
||||
parts.push(p.str("}"));
|
||||
Doc::Array(parts)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for ForStatement<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for ForInStatement<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for ForOfStatement<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for ForStatementLeft<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for WhileStatement<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for DoWhileStatement<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for ContinueStatement {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for BreakStatement {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for SwitchStatement<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for SwitchCase<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for ReturnStatement<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
string!(p, "return")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for LabeledStatement<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for TryStatement<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for ThrowStatement<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for WithStatement<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for DebuggerStatement {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for ModuleDeclaration<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for Declaration<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
match self {
|
||||
Self::VariableDeclaration(stmt) => stmt.format(p),
|
||||
Self::FunctionDeclaration(stmt) => stmt.format(p),
|
||||
Self::ClassDeclaration(decl) => decl.format(p),
|
||||
Self::UsingDeclaration(decl) => decl.format(p),
|
||||
Self::TSTypeAliasDeclaration(decl) => decl.format(p),
|
||||
Self::TSInterfaceDeclaration(decl) => decl.format(p),
|
||||
Self::TSEnumDeclaration(decl) => decl.format(p),
|
||||
Self::TSModuleDeclaration(decl) => decl.format(p),
|
||||
Self::TSImportEqualsDeclaration(decl) => decl.format(p),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for VariableDeclaration<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for UsingDeclaration<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for TSTypeAliasDeclaration<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for TSInterfaceDeclaration<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for TSEnumDeclaration<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for TSModuleDeclaration<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for TSImportEqualsDeclaration<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for VariableDeclarator<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for Function<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
let mut parts = p.vec();
|
||||
parts.push(p.str("function "));
|
||||
if let Some(id) = &self.id {
|
||||
parts.push(p.str(id.name.as_str()));
|
||||
}
|
||||
parts.push(self.params.format(p));
|
||||
if let Some(body) = &self.body {
|
||||
parts.push(p.str(" "));
|
||||
parts.push(body.format(p));
|
||||
}
|
||||
Doc::Array(parts)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for FunctionBody<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
let mut parts = p.vec();
|
||||
parts.push(p.str("{"));
|
||||
parts.push(Doc::Softline);
|
||||
parts.extend(self.statements.iter().map(|stmt| stmt.format(p)));
|
||||
parts.push(Doc::Softline);
|
||||
parts.push(p.str("}"));
|
||||
Doc::Array(parts)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for FormalParameters<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
let mut parts = p.vec();
|
||||
parts.push(p.str("("));
|
||||
parts.extend(self.items.iter().map(|stmt| stmt.format(p)));
|
||||
if let Some(rest) = &self.rest {
|
||||
parts.push(rest.format(p));
|
||||
}
|
||||
parts.push(p.str(")"));
|
||||
Doc::Array(parts)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for FormalParameter<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for ImportDeclaration<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for Option<Vec<'a, ImportAttribute>> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for ImportAttribute {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for ExportNamedDeclaration<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for ExportSpecifier {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for ModuleExportName {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for ExportAllDeclaration<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for ExportDefaultDeclaration<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
impl<'a> Format<'a> for ExportDefaultDeclarationKind<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for Expression<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
match self {
|
||||
Self::BooleanLiteral(lit) => lit.format(p),
|
||||
Self::NullLiteral(lit) => lit.format(p),
|
||||
Self::NumberLiteral(lit) => lit.format(p),
|
||||
Self::BigintLiteral(lit) => lit.format(p),
|
||||
Self::RegExpLiteral(lit) => lit.format(p),
|
||||
Self::StringLiteral(lit) => lit.format(p),
|
||||
Self::Identifier(ident) => ident.format(p),
|
||||
Self::ThisExpression(expr) => expr.format(p),
|
||||
Self::MemberExpression(expr) => expr.format(p),
|
||||
Self::CallExpression(expr) => expr.format(p),
|
||||
Self::ArrayExpression(expr) => expr.format(p),
|
||||
Self::ObjectExpression(expr) => expr.format(p),
|
||||
Self::FunctionExpression(expr) => expr.format(p),
|
||||
Self::ArrowExpression(expr) => expr.format(p),
|
||||
Self::YieldExpression(expr) => expr.format(p),
|
||||
Self::UpdateExpression(expr) => expr.format(p),
|
||||
Self::UnaryExpression(expr) => expr.format(p),
|
||||
Self::BinaryExpression(expr) => expr.format(p),
|
||||
Self::PrivateInExpression(expr) => expr.format(p),
|
||||
Self::LogicalExpression(expr) => expr.format(p),
|
||||
Self::ConditionalExpression(expr) => expr.format(p),
|
||||
Self::AssignmentExpression(expr) => expr.format(p),
|
||||
Self::SequenceExpression(expr) => expr.format(p),
|
||||
Self::ParenthesizedExpression(expr) => expr.format(p),
|
||||
Self::ImportExpression(expr) => expr.format(p),
|
||||
Self::TemplateLiteral(literal) => literal.format(p),
|
||||
Self::TaggedTemplateExpression(expr) => expr.format(p),
|
||||
Self::Super(sup) => sup.format(p),
|
||||
Self::AwaitExpression(expr) => expr.format(p),
|
||||
Self::ChainExpression(expr) => expr.format(p),
|
||||
Self::NewExpression(expr) => expr.format(p),
|
||||
Self::MetaProperty(expr) => expr.format(p),
|
||||
Self::ClassExpression(expr) => expr.format(p),
|
||||
Self::JSXElement(el) => el.format(p),
|
||||
Self::JSXFragment(fragment) => fragment.format(p),
|
||||
Self::TSAsExpression(expr) => expr.expression.format(p),
|
||||
Self::TSSatisfiesExpression(expr) => expr.expression.format(p),
|
||||
Self::TSTypeAssertion(expr) => expr.expression.format(p),
|
||||
Self::TSNonNullExpression(expr) => expr.expression.format(p),
|
||||
Self::TSInstantiationExpression(expr) => expr.expression.format(p),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for IdentifierReference {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
p.str(self.name.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for IdentifierName {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
p.str(self.name.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for BindingIdentifier {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
p.str(self.name.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for LabelIdentifier {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
p.str(self.name.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for BooleanLiteral {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for NullLiteral {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for NumberLiteral<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for BigintLiteral {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for RegExpLiteral {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for StringLiteral {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for ThisExpression {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for MemberExpression<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for ComputedMemberExpression<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for StaticMemberExpression<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for PrivateFieldExpression<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for CallExpression<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for Argument<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for ArrayExpressionElement<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for SpreadElement<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for ArrayExpression<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for ObjectExpression<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for ObjectPropertyKind<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for ObjectProperty<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for PropertyKey<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for ArrowExpression<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for YieldExpression<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for UpdateExpression<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for UnaryExpression<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for BinaryExpression<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for BinaryOperator {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for PrivateInExpression<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for LogicalExpression<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for ConditionalExpression<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for AssignmentExpression<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for AssignmentTarget<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for SimpleAssignmentTarget<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for AssignmentTargetPattern<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for ArrayAssignmentTarget<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for Option<AssignmentTargetMaybeDefault<'a>> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for ObjectAssignmentTarget<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for AssignmentTargetMaybeDefault<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for AssignmentTargetWithDefault<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for AssignmentTargetProperty<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for AssignmentTargetPropertyIdentifier<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for AssignmentTargetPropertyProperty<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for SequenceExpression<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for ParenthesizedExpression<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for ImportExpression<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for TemplateLiteral<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for TaggedTemplateExpression<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for Super {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for AwaitExpression<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for ChainExpression<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for NewExpression<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for MetaProperty {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for Class<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for ClassElement<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for JSXIdentifier {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for JSXMemberExpressionObject<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for JSXMemberExpression<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for JSXElementName<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for JSXNamespacedName {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for JSXAttributeName<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for JSXAttribute<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for JSXEmptyExpression {
|
||||
fn format(&self, _: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for JSXExpression<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for JSXExpressionContainer<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for JSXAttributeValue<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for JSXSpreadAttribute<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for JSXAttributeItem<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for JSXOpeningElement<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for JSXClosingElement<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for JSXElement<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for JSXOpeningFragment {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for JSXClosingFragment {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for JSXText {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for JSXSpreadChild<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for JSXChild<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for JSXFragment<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for StaticBlock<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for MethodDefinition<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for PropertyDefinition<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for AccessorProperty<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for PrivateIdentifier {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for BindingPattern<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for ObjectPattern<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for BindingProperty<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for RestElement<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for ArrayPattern<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Format<'a> for AssignmentPattern<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
Doc::Line
|
||||
}
|
||||
}
|
||||
32
crates/oxc_prettier/src/lib.rs
Normal file
32
crates/oxc_prettier/src/lib.rs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
//! Prettier
|
||||
//!
|
||||
//! A port of <https://github.com/prettier/prettier>
|
||||
|
||||
mod document;
|
||||
mod format;
|
||||
mod macros;
|
||||
mod printer;
|
||||
|
||||
use oxc_allocator::Allocator;
|
||||
use oxc_ast::ast::Program;
|
||||
|
||||
use crate::{format::Format, printer::Printer};
|
||||
|
||||
pub struct PrettierOptions;
|
||||
|
||||
pub struct Prettier<'a> {
|
||||
allocator: &'a Allocator,
|
||||
|
||||
_options: PrettierOptions,
|
||||
}
|
||||
|
||||
impl<'a> Prettier<'a> {
|
||||
pub fn new(allocator: &'a Allocator, _options: PrettierOptions) -> Self {
|
||||
Self { allocator, _options }
|
||||
}
|
||||
|
||||
pub fn build(mut self, program: &Program<'a>) -> String {
|
||||
let doc = program.format(&mut self);
|
||||
Printer::new(doc).build()
|
||||
}
|
||||
}
|
||||
48
crates/oxc_prettier/src/macros.rs
Normal file
48
crates/oxc_prettier/src/macros.rs
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
//! Utility macros for constructing the IR
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! format {
|
||||
($p:ident, $s:expr) => {{
|
||||
$s.format($p)
|
||||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! string {
|
||||
($p:ident, $s:expr) => {{
|
||||
$p.str($s)
|
||||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! group {
|
||||
($p:ident, $( $x:expr ),* ) => {
|
||||
{
|
||||
let mut temp_vec = $p.vec();
|
||||
$(
|
||||
temp_vec.push($x);
|
||||
)*
|
||||
Doc::Group(temp_vec)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! indent {
|
||||
($p:ident, $( $x:expr ),* ) => {
|
||||
{
|
||||
let mut temp_vec = $p.vec();
|
||||
$(
|
||||
temp_vec.push($x);
|
||||
)*
|
||||
Doc::Indent(temp_vec)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! softline {
|
||||
() => {
|
||||
Doc::Softline
|
||||
};
|
||||
}
|
||||
86
crates/oxc_prettier/src/printer.rs
Normal file
86
crates/oxc_prettier/src/printer.rs
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
//! [Doc] Printer
|
||||
//!
|
||||
//! References:
|
||||
//! * <https://github.com/prettier/prettier/blob/main/src/document/printer.js>
|
||||
|
||||
#![allow(unused)]
|
||||
|
||||
use crate::document::Doc;
|
||||
|
||||
struct Command<'a> {
|
||||
indent: Indent,
|
||||
mode: Mode,
|
||||
doc: Doc<'a>,
|
||||
}
|
||||
|
||||
impl<'a> Command<'a> {
|
||||
fn new(indent: Indent, mode: Mode, doc: Doc<'a>) -> Self {
|
||||
Self { indent, mode, doc }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
enum Mode {
|
||||
Break,
|
||||
Flat,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct Indent {
|
||||
value: &'static str,
|
||||
length: u8,
|
||||
}
|
||||
|
||||
impl Indent {
|
||||
fn root() -> Self {
|
||||
Self { value: "", length: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Printer<'a> {
|
||||
doc: Doc<'a>,
|
||||
}
|
||||
|
||||
impl<'a> Printer<'a> {
|
||||
pub fn new(doc: Doc<'a>) -> Self {
|
||||
Self { doc }
|
||||
}
|
||||
|
||||
pub fn build(self) -> String {
|
||||
self.print_doc_to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Printer<'a> {
|
||||
/// Turn Doc into a string
|
||||
///
|
||||
/// Reference:
|
||||
/// * <https://github.com/prettier/prettier/blob/0176a33db442e498fdb577784deaa77d7c9ae723/src/document/printer.js#L302>
|
||||
fn print_doc_to_string(self) -> String {
|
||||
let mut out = vec![];
|
||||
let mut cmds: Vec<Command> = vec![Command::new(Indent::root(), Mode::Break, self.doc)];
|
||||
|
||||
while let Some(Command { indent, doc, mode }) = cmds.pop() {
|
||||
match doc {
|
||||
Doc::Str(string) => {
|
||||
out.extend(string.as_bytes());
|
||||
}
|
||||
Doc::Array(docs) => {
|
||||
cmds.extend(docs.into_iter().rev().map(|doc| Command::new(indent, mode, doc)));
|
||||
}
|
||||
Doc::Indent(docs) => {
|
||||
cmds.extend(docs.into_iter().rev().map(|doc| Command::new(indent, mode, doc)));
|
||||
}
|
||||
Doc::Group(docs) => {
|
||||
cmds.extend(docs.into_iter().rev().map(|doc| Command::new(indent, mode, doc)));
|
||||
}
|
||||
Doc::Line | Doc::Softline => {
|
||||
out.push(b'\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SAFETY: We should have constructed valid UTF8 strings
|
||||
unsafe { String::from_utf8_unchecked(out) }
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue