feat(prettier): add infra for need_parens (#1450)

This commit is contained in:
Boshen 2023-11-20 17:18:39 +08:00 committed by GitHub
parent 719ed744e0
commit 0bf3dbfde4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 192 additions and 114 deletions

View file

@ -1,7 +1,7 @@
use std::{cell::Cell, fmt, hash::Hash};
use oxc_allocator::{Box, Vec};
use oxc_span::{Atom, GetSpan, SourceType, Span};
use oxc_span::{Atom, SourceType, Span};
use oxc_syntax::{
operator::{
AssignmentOperator, BinaryOperator, LogicalOperator, UnaryOperator, UpdateOperator,
@ -919,15 +919,6 @@ pub enum AssignmentTargetProperty<'a> {
AssignmentTargetPropertyProperty(Box<'a, AssignmentTargetPropertyProperty<'a>>),
}
impl<'a> GetSpan for AssignmentTargetProperty<'a> {
fn span(&self) -> Span {
match self {
Self::AssignmentTargetPropertyIdentifier(identifier) => identifier.span,
Self::AssignmentTargetPropertyProperty(literal) => literal.span,
}
}
}
/// Assignment Property - Identifier Reference
#[derive(Debug, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))]
@ -1456,12 +1447,6 @@ pub struct BindingProperty<'a> {
pub computed: bool,
}
impl<'a> GetSpan for BindingProperty<'a> {
fn span(&self) -> Span {
self.span
}
}
#[derive(Debug, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))]
pub struct ArrayPattern<'a> {

View file

@ -75,6 +75,8 @@ pub enum AstKind<'a> {
UnaryExpression(&'a UnaryExpression<'a>),
UpdateExpression(&'a UpdateExpression<'a>),
YieldExpression(&'a YieldExpression<'a>),
ImportExpression(&'a ImportExpression<'a>),
PrivateInExpression(&'a PrivateInExpression<'a>),
ObjectProperty(&'a ObjectProperty<'a>),
PropertyKey(&'a PropertyKey<'a>),
@ -328,6 +330,8 @@ impl<'a> GetSpan for AstKind<'a> {
Self::UnaryExpression(x) => x.span,
Self::UpdateExpression(x) => x.span,
Self::YieldExpression(x) => x.span,
Self::ImportExpression(x) => x.span,
Self::PrivateInExpression(x) => x.span,
Self::ObjectProperty(x) => x.span,
Self::PropertyKey(x) => x.span(),
@ -488,6 +492,8 @@ impl<'a> AstKind<'a> {
Self::UnaryExpression(expr) => format!("UnaryExpression({:?})", expr.operator).into(),
Self::UpdateExpression(_) => "UpdateExpression".into(),
Self::YieldExpression(_) => "YieldExpression".into(),
Self::ImportExpression(_) => "ImportExpression".into(),
Self::PrivateInExpression(_) => "PrivateInExpression".into(),
Self::ObjectProperty(_) => "ObjectProperty".into(),
Self::PropertyKey(_) => "PropertyKey".into(),

View file

@ -104,6 +104,12 @@ impl<'a> GetSpan for BindingPattern<'a> {
}
}
impl<'a> GetSpan for BindingProperty<'a> {
fn span(&self) -> Span {
self.span
}
}
impl<'a> GetSpan for ClassElement<'a> {
fn span(&self) -> Span {
match self {
@ -217,6 +223,15 @@ impl<'a> GetSpan for AssignmentTarget<'a> {
}
}
impl<'a> GetSpan for AssignmentTargetProperty<'a> {
fn span(&self) -> Span {
match self {
Self::AssignmentTargetPropertyIdentifier(identifier) => identifier.span,
Self::AssignmentTargetPropertyProperty(literal) => literal.span,
}
}
}
impl<'a> GetSpan for Argument<'a> {
fn span(&self) -> Span {
match self {

View file

@ -525,11 +525,13 @@ impl<'a> Format<'a> for DebuggerStatement {
impl<'a> Format<'a> for ModuleDeclaration<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
if let ModuleDeclaration::ImportDeclaration(decl) = self {
decl.format(p)
} else {
module::print_export_declaration(p, self)
}
wrap!(p, self, ModuleDeclaration, {
if let ModuleDeclaration::ImportDeclaration(decl) = self {
decl.format(p)
} else {
module::print_export_declaration(p, self)
}
})
}
}
@ -1331,14 +1333,16 @@ impl<'a> Format<'a> for PrivateFieldExpression<'a> {
impl<'a> Format<'a> for CallExpression<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
call_expression::print_call_expression(
p,
&self.callee,
&self.arguments,
self.optional,
&self.type_parameters,
/* is_new */ false,
)
wrap!(p, self, CallExpression, {
call_expression::print_call_expression(
p,
&self.callee,
&self.arguments,
self.optional,
&self.type_parameters,
/* is_new */ false,
)
})
}
}
@ -1369,13 +1373,19 @@ impl<'a> Format<'a> for SpreadElement<'a> {
impl<'a> Format<'a> for ArrayExpression<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
array::print_array(p, &Array::ArrayExpression(self))
wrap!(p, self, ArrayExpression, { array::print_array(p, &Array::ArrayExpression(self)) })
}
}
impl<'a> Format<'a> for ObjectExpression<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
object::print_object_properties(p, &ObjectLike::ObjectExpression(self), &self.properties)
wrap!(p, self, ObjectExpression, {
object::print_object_properties(
p,
&ObjectLike::ObjectExpression(self),
&self.properties,
)
})
}
}
@ -1409,13 +1419,13 @@ impl<'a> Format<'a> for ObjectProperty<'a> {
}
if method {
if let Expression::FunctionExpression(func_expr) = &self.value {
wrap!(p, func_expr, Function, {
parts.push(function::print_function(
parts.push(wrap!(p, func_expr, Function, {
function::print_function(
p,
func_expr,
Some(self.key.span().source_text(p.source_text)),
));
});
)
}));
}
} else {
parts.push(format!(p, self.key));
@ -1474,77 +1484,89 @@ impl<'a> Format<'a> for YieldExpression<'a> {
impl<'a> Format<'a> for UpdateExpression<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
if self.prefix {
array![p, ss!(self.operator.as_str()), format!(p, self.argument)]
} else {
array![p, format!(p, self.argument), ss!(self.operator.as_str())]
}
wrap!(p, self, UpdateExpression, {
if self.prefix {
array![p, ss!(self.operator.as_str()), format!(p, self.argument)]
} else {
array![p, format!(p, self.argument), ss!(self.operator.as_str())]
}
})
}
}
impl<'a> Format<'a> for UnaryExpression<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
let mut parts = p.vec();
parts.push(string!(p, self.operator.as_str()));
if self.operator.is_keyword() {
parts.push(ss!(" "));
}
parts.push(format!(p, self.argument));
Doc::Array(parts)
wrap!(p, self, UnaryExpression, {
let mut parts = p.vec();
parts.push(string!(p, self.operator.as_str()));
if self.operator.is_keyword() {
parts.push(ss!(" "));
}
parts.push(format!(p, self.argument));
Doc::Array(parts)
})
}
}
impl<'a> Format<'a> for BinaryExpression<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
let doc = binaryish::print_binaryish_expression(
p,
&BinaryishLeft::Expression(&self.left),
BinaryishOperator::BinaryOperator(self.operator),
&self.right,
);
group!(p, indent!(p, softline!(), doc), softline!())
wrap!(p, self, BinaryExpression, {
let doc = binaryish::print_binaryish_expression(
p,
&BinaryishLeft::Expression(&self.left),
BinaryishOperator::BinaryOperator(self.operator),
&self.right,
);
group!(p, indent!(p, softline!(), doc), softline!())
})
}
}
impl<'a> Format<'a> for PrivateInExpression<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
binaryish::print_binaryish_expression(
p,
&BinaryishLeft::PrivateIdentifier(&self.left),
BinaryishOperator::BinaryOperator(self.operator),
&self.right,
)
wrap!(p, self, PrivateInExpression, {
binaryish::print_binaryish_expression(
p,
&BinaryishLeft::PrivateIdentifier(&self.left),
BinaryishOperator::BinaryOperator(self.operator),
&self.right,
)
})
}
}
impl<'a> Format<'a> for LogicalExpression<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
let doc = binaryish::print_binaryish_expression(
p,
&BinaryishLeft::Expression(&self.left),
BinaryishOperator::LogicalOperator(self.operator),
&self.right,
);
group!(p, indent!(p, softline!(), doc), softline!())
wrap!(p, self, LogicalExpression, {
let doc = binaryish::print_binaryish_expression(
p,
&BinaryishLeft::Expression(&self.left),
BinaryishOperator::LogicalOperator(self.operator),
&self.right,
);
group!(p, indent!(p, softline!(), doc), softline!())
})
}
}
impl<'a> Format<'a> for ConditionalExpression<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
ternary::print_ternary(p, self)
wrap!(p, self, ConditionalExpression, { ternary::print_ternary(p, self) })
}
}
impl<'a> Format<'a> for AssignmentExpression<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
array![
p,
format!(p, self.left),
ss!(" "),
string!(p, self.operator.as_str()),
ss!(" "),
format!(p, self.right)
]
wrap!(p, self, AssignmentExpression, {
array![
p,
format!(p, self.left),
ss!(" "),
string!(p, self.operator.as_str()),
ss!(" "),
format!(p, self.right)
]
})
}
}
@ -1643,42 +1665,39 @@ impl<'a> Format<'a> for AssignmentTargetPropertyProperty<'a> {
impl<'a> Format<'a> for SequenceExpression<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
let docs = self.expressions.iter().map(|expr| expr.format(p)).collect::<std::vec::Vec<_>>();
group![p, Doc::Array(p.join(Separator::CommaLine, docs))]
wrap!(p, self, SequenceExpression, {
let docs =
self.expressions.iter().map(|expr| expr.format(p)).collect::<std::vec::Vec<_>>();
group![p, Doc::Array(p.join(Separator::CommaLine, docs))]
})
}
}
impl<'a> Format<'a> for ParenthesizedExpression<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
// TODO: if shouldHug
// array![p, ss!("("), format!(p, self.expression), ss!(")")]
array![
p,
ss!("("),
format!(p, self.expression),
// indent!(p, array![p, softline!(), ]),
// softline!(),
ss!(")")
]
// TODO: This wrap need to be removed and all logic should go into `need_parens`.
wrap!(p, self, ParenthesizedExpression, { self.expression.format(p) })
}
}
impl<'a> Format<'a> for ImportExpression<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
let mut parts = p.vec();
parts.push(ss!("import"));
parts.push(ss!("("));
parts.push(format!(p, self.source));
if !self.arguments.is_empty() {
for arg in &self.arguments {
parts.push(ss!(","));
parts.push(Doc::Line);
parts.push(format!(p, arg));
wrap!(p, self, ImportExpression, {
let mut parts = p.vec();
parts.push(ss!("import"));
parts.push(ss!("("));
parts.push(format!(p, self.source));
if !self.arguments.is_empty() {
for arg in &self.arguments {
parts.push(ss!(","));
parts.push(Doc::Line);
parts.push(format!(p, arg));
}
}
}
parts.push(ss!(")"));
parts.push(ss!(")"));
Doc::Group(Group::new(parts, false))
Doc::Group(Group::new(parts, false))
})
}
}
@ -1709,16 +1728,18 @@ impl<'a> Format<'a> for Super {
impl<'a> Format<'a> for AwaitExpression<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
let mut parts = p.vec();
parts.push(ss!("await "));
parts.push(format!(p, self.argument));
Doc::Array(parts)
wrap!(p, self, AwaitExpression, {
let mut parts = p.vec();
parts.push(ss!("await "));
parts.push(format!(p, self.argument));
Doc::Array(parts)
})
}
}
impl<'a> Format<'a> for ChainExpression<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
format!(p, self.expression)
wrap!(p, self, ChainExpression, { format!(p, self.expression) })
}
}
@ -1733,14 +1754,16 @@ impl<'a> Format<'a> for ChainElement<'a> {
impl<'a> Format<'a> for NewExpression<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
call_expression::print_call_expression(
p,
&self.callee,
&self.arguments,
false,
&self.type_parameters,
/* is_new */ true,
)
wrap!(p, self, NewExpression, {
call_expression::print_call_expression(
p,
&self.callee,
&self.arguments,
false,
&self.type_parameters,
/* is_new */ true,
)
})
}
}

View file

@ -8,6 +8,7 @@ mod comment;
mod doc;
mod format;
mod macros;
mod need_parens;
mod options;
mod printer;

View file

@ -105,8 +105,10 @@ macro_rules! if_break {
#[macro_export]
macro_rules! wrap {
($p:ident, $self:expr, $kind:ident, $block:block) => {{
$p.enter_node(AstKind::$kind($p.alloc($self)));
let kind = AstKind::$kind($p.alloc($self));
$p.enter_node(kind);
let doc = $block;
let doc = $p.wrap_parens(doc, kind);
$p.leave_node();
doc
}};

View file

@ -0,0 +1,46 @@
use oxc_ast::AstKind;
use crate::{array, doc::Doc, ss, Prettier};
impl<'a> Prettier<'a> {
pub(crate) fn wrap_parens(&self, doc: Doc<'a>, kind: AstKind<'a>) -> Doc<'a> {
if self.need_parens(kind) {
array![self, ss!("("), doc, ss!(")")]
} else {
doc
}
}
fn need_parens(&self, kind: AstKind<'a>) -> bool {
match kind {
// Only statements don't need parentheses.
kind if kind.is_statement() => return false,
AstKind::SequenceExpression(_) => {
let parent = self.parent_kind();
if matches!(parent, AstKind::Program(_)) {
return false;
}
}
AstKind::ObjectExpression(_) => {
let parent = self.parent_kind();
if matches!(parent, AstKind::Program(_)) {
return true;
}
}
AstKind::AssignmentExpression(_) => {
let parent = self.parent_kind();
if matches!(parent, AstKind::ArrowExpression(arrow_expr) if arrow_expr.expression) {
return true;
}
}
// NOTE: This is a fallback which should be removed when all code are ported.
AstKind::ParenthesizedExpression(_) => return true,
_ => {}
}
false
}
}