Skip to content

Commit

Permalink
feat(prettier): improve ts compatibility (#5900)
Browse files Browse the repository at this point in the history
  • Loading branch information
Sysix committed Sep 20, 2024
1 parent 9192e5a commit 65c337a
Show file tree
Hide file tree
Showing 6 changed files with 189 additions and 103 deletions.
9 changes: 9 additions & 0 deletions crates/oxc_ast/src/ast/ts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1073,6 +1073,15 @@ pub enum TSModuleDeclarationBody<'a> {
TSModuleBlock(Box<'a, TSModuleBlock<'a>>) = 1,
}

impl TSModuleDeclarationBody<'_> {
pub fn is_empty(&self) -> bool {
match self {
TSModuleDeclarationBody::TSModuleDeclaration(declaration) => declaration.body.is_none(),
TSModuleDeclarationBody::TSModuleBlock(block) => block.body.len() == 0,
}
}
}

// See serializer in serialize.rs
#[ast(visit)]
#[derive(Debug)]
Expand Down
13 changes: 13 additions & 0 deletions crates/oxc_prettier/src/format/call_expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,15 @@ impl<'a, 'b> CallExpressionLike<'a, 'b> {
CallExpressionLike::NewExpression(new) => &new.arguments,
}
}

pub fn type_parameters(
&self,
) -> &Option<oxc_allocator::Box<'a, TSTypeParameterInstantiation<'a>>> {
match self {
CallExpressionLike::CallExpression(call) => &call.type_parameters,
CallExpressionLike::NewExpression(new) => &new.type_parameters,
}
}
}

impl GetSpan for CallExpressionLike<'_, '_> {
Expand All @@ -61,6 +70,10 @@ pub(super) fn print_call_expression<'a>(

parts.push(expression.callee().format(p));

if let Some(type_parameters) = expression.type_parameters() {
parts.push(type_parameters.format(p));
}

if expression.optional() {
parts.push(ss!("?."));
}
Expand Down
25 changes: 23 additions & 2 deletions crates/oxc_prettier/src/format/function_parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,26 @@ pub(super) fn print_function_parameters<'a>(
let mut printed = p.vec();
let len = params.items.len();
let has_rest = params.rest.is_some();

if let AstKind::Function(function) = p.parent_kind() {
if let Some(this_param) = &function.this_param {
parts.push(this_param.format(p));

if params.items.len() > 0 {
printed.push(ss!(","));

if should_hug_the_only_function_parameter {
printed.push(space!());
} else if p.is_next_line_empty(this_param.span) {
printed.extend(hardline!());
printed.extend(hardline!());
} else {
printed.push(line!());
}
}
}
}

for (i, param) in params.items.iter().enumerate() {
if let Some(accessibility) = &param.accessibility {
printed.push(ss!(accessibility.as_str()));
Expand Down Expand Up @@ -119,8 +139,9 @@ pub(super) fn print_function_parameters<'a>(
indented.extend(printed);
let indented = indent!(p, Doc::Array(indented));
parts.push(indented);
let has_rest_parameter = params.rest.is_some();
parts.push(if_break!(p, if has_rest_parameter { "" } else { "," }));
let skip_dangling_comma = params.rest.is_some()
|| matches!(p.parent_kind(), AstKind::Function(func) if func.this_param.is_some());
parts.push(if_break!(p, if skip_dangling_comma { "" } else { "," }));
parts.push(softline!());
if need_parens {
parts.push(ss!(")"));
Expand Down
169 changes: 139 additions & 30 deletions crates/oxc_prettier/src/format/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -797,7 +797,17 @@ impl<'a> Format<'a> for TSArrayType<'a> {

impl<'a> Format<'a> for TSConditionalType<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
line!()
let mut parts = p.vec();

parts.push(self.check_type.format(p));
parts.push(ss!(" extends "));
parts.push(self.extends_type.format(p));
parts.push(ss!(" ? "));
parts.push(self.true_type.format(p));
parts.push(ss!(" : "));
parts.push(self.false_type.format(p));

Doc::Array(parts)
}
}

Expand All @@ -822,11 +832,6 @@ impl<'a> Format<'a> for TSFunctionType<'a> {
parts.push(type_parameters.format(p));
}

if let Some(this_param) = &self.this_param {
parts.push(this_param.format(p));
parts.push(ss!(", "));
}

parts.push(self.params.format(p));

parts.push(ss!(" => "));
Expand All @@ -835,6 +840,7 @@ impl<'a> Format<'a> for TSFunctionType<'a> {
Doc::Array(parts)
}
}

impl<'a> Format<'a> for TSThisParameter<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
let mut parts = p.vec();
Expand All @@ -851,7 +857,27 @@ impl<'a> Format<'a> for TSThisParameter<'a> {

impl<'a> Format<'a> for TSImportType<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
line!()
let mut parts = p.vec();

if self.is_type_of {
parts.push(ss!("typeof "));
}

parts.push(ss!("import("));
parts.push(self.parameter.format(p));
// ToDo: attributes
parts.push(ss!(")"));

if let Some(qualifier) = &self.qualifier {
parts.push(ss!("."));
parts.push(qualifier.format(p));
}

if let Some(type_parameters) = &self.type_parameters {
parts.push(type_parameters.format(p));
}

Doc::Array(parts)
}
}

Expand Down Expand Up @@ -1040,7 +1066,28 @@ impl<'a> Format<'a> for TSTypeOperator<'a> {

impl<'a> Format<'a> for TSTypePredicate<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
line!()
let mut parts = p.vec();

if self.asserts {
parts.push(ss!("asserts "));
}
parts.push(self.parameter_name.format(p));

if let Some(type_annotation) = &self.type_annotation {
parts.push(ss!(" is "));
parts.push(type_annotation.type_annotation.format(p));
}

Doc::Array(parts)
}
}

impl<'a> Format<'a> for TSTypePredicateName<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
match self {
TSTypePredicateName::Identifier(it) => it.format(p),
TSTypePredicateName::This(it) => it.format(p),
}
}
}

Expand Down Expand Up @@ -1251,14 +1298,17 @@ impl<'a> Format<'a> for TSModuleDeclaration<'a> {
parts.push(ss!(" {"));

if let Some(body) = &self.body {
let mut indent_parts = p.vec();
if !body.is_empty() {
let mut indent_parts = p.vec();

indent_parts.extend(hardline!());
indent_parts.push(body.format(p));
parts.push(Doc::Indent(indent_parts));
indent_parts.extend(hardline!());
indent_parts.push(body.format(p));

parts.push(Doc::Indent(indent_parts));
parts.extend(hardline!());
}
}

parts.extend(hardline!());
parts.push(ss!("}"));

Doc::Array(parts)
Expand Down Expand Up @@ -1288,8 +1338,15 @@ impl<'a> Format<'a> for TSModuleDeclarationBody<'a> {
impl<'a> Format<'a> for TSModuleBlock<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
let mut parts = p.vec();
let mut add_line = false;

for body_part in &self.body {
if add_line {
parts.push(line!());
} else {
add_line = true;
}

parts.push(body_part.format(p));
}

Expand Down Expand Up @@ -1616,7 +1673,7 @@ impl<'a> Format<'a> for TSExportAssignment<'a> {

impl<'a> Format<'a> for TSNamespaceExportDeclaration<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
line!()
array!(p, ss!(" as namespace "), self.id.format(p), ss!(";"))
}
}

Expand Down Expand Up @@ -1707,10 +1764,10 @@ impl<'a> Format<'a> for Expression<'a> {
Self::JSXElement(el) => el.format(p),
Self::JSXFragment(fragment) => fragment.format(p),
Self::TSAsExpression(expr) => expr.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),
Self::TSSatisfiesExpression(expr) => expr.format(p),
Self::TSTypeAssertion(expr) => expr.format(p),
Self::TSNonNullExpression(expr) => expr.format(p),
Self::TSInstantiationExpression(expr) => expr.format(p),
}
}
}
Expand Down Expand Up @@ -2222,11 +2279,11 @@ impl<'a> Format<'a> for SimpleAssignmentTarget<'a> {
match self {
Self::AssignmentTargetIdentifier(ident) => ident.format(p),
match_member_expression!(Self) => self.to_member_expression().format(p),
Self::TSAsExpression(expr) => expr.expression.format(p),
Self::TSSatisfiesExpression(expr) => expr.expression.format(p),
Self::TSNonNullExpression(expr) => expr.expression.format(p),
Self::TSTypeAssertion(expr) => expr.expression.format(p),
Self::TSInstantiationExpression(expr) => expr.expression.format(p),
Self::TSAsExpression(expr) => expr.format(p),
Self::TSSatisfiesExpression(expr) => expr.format(p),
Self::TSNonNullExpression(expr) => expr.format(p),
Self::TSTypeAssertion(expr) => expr.format(p),
Self::TSInstantiationExpression(expr) => expr.format(p),
}
}
}
Expand Down Expand Up @@ -2465,25 +2522,25 @@ impl<'a> Format<'a> for TSClassImplements<'a> {

impl<'a> Format<'a> for TSTypeAssertion<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
line!()
array!(p, ss!("<"), self.type_annotation.format(p), ss!(">"), self.expression.format(p))
}
}

impl<'a> Format<'a> for TSSatisfiesExpression<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
line!()
array!(p, self.expression.format(p), ss!(" satisfies "), self.type_annotation.format(p))
}
}

impl<'a> Format<'a> for TSInstantiationExpression<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
line!()
array!(p, self.expression.format(p), self.type_parameters.format(p))
}
}

impl<'a> Format<'a> for TSNonNullExpression<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
line!()
array!(p, self.expression.format(p), ss!("!"))
}
}

Expand Down Expand Up @@ -2868,7 +2925,31 @@ impl<'a> Format<'a> for RegExpFlags {

impl<'a> Format<'a> for TSIndexSignature<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
line!()
let mut parts = p.vec();

if self.readonly {
parts.push(ss!("readonly "));
}

parts.push(ss!("["));
for param in &self.parameters {
parts.push(param.format(p));
}
parts.push(ss!("]: "));
parts.push(self.type_annotation.type_annotation.format(p));

Doc::Array(parts)
}
}

impl<'a> Format<'a> for TSIndexSignatureName<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
array!(
p,
ss!(self.name.as_str()),
ss!(": "),
self.type_annotation.type_annotation.format(p)
)
}
}

Expand All @@ -2893,13 +2974,41 @@ impl<'a> Format<'a> for TSPropertySignature<'a> {

impl<'a> Format<'a> for TSCallSignatureDeclaration<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
line!()
let mut parts = p.vec();

if let Some(type_parameters) = &self.type_parameters {
parts.push(type_parameters.format(p));
}

parts.push(self.params.format(p));

if let Some(return_type) = &self.return_type {
parts.push(ss!(": "));
parts.push(return_type.type_annotation.format(p));
}

Doc::Array(parts)
}
}

impl<'a> Format<'a> for TSConstructSignatureDeclaration<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
line!()
let mut parts = p.vec();

parts.push(ss!("new "));

if let Some(type_parameters) = &self.type_parameters {
parts.push(type_parameters.format(p));
}

parts.push(self.params.format(p));

if let Some(return_type) = &self.return_type {
parts.push(ss!(": "));
parts.push(return_type.type_annotation.format(p));
}

Doc::Array(parts)
}
}

Expand Down
7 changes: 4 additions & 3 deletions crates/oxc_prettier/src/format/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,10 @@ fn print_semicolon_after_export_declaration<'a>(
};

match declaration {
Declaration::TSInterfaceDeclaration(_) | Declaration::VariableDeclaration(_) => {
None
}
Declaration::TSInterfaceDeclaration(_)
| Declaration::VariableDeclaration(_)
| Declaration::ClassDeclaration(_)
| Declaration::TSModuleDeclaration(_) => None,
_ => Some(ss!(";")),
}
}
Expand Down
Loading

0 comments on commit 65c337a

Please sign in to comment.