diff --git a/crates/oxc_prettier/src/format/mod.rs b/crates/oxc_prettier/src/format/mod.rs index c4f22cf7d..e664f1528 100644 --- a/crates/oxc_prettier/src/format/mod.rs +++ b/crates/oxc_prettier/src/format/mod.rs @@ -54,8 +54,25 @@ where impl<'a> Format<'a> for Program<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { - block::print_block_body(p, &self.body, Some(&self.directives), false, true) - .unwrap_or(ss!("")) + let mut parts = p.vec(); + if let Some(hashbang) = &self.hashbang { + parts.push(hashbang.format(p)); + if p.is_next_line_empty(hashbang.span.end - 1) { + parts.push(hardline!()); + } + } + if let Some(doc) = + block::print_block_body(p, &self.body, Some(&self.directives), false, true) + { + parts.push(doc); + } + Doc::Array(parts) + } +} + +impl<'a> Format<'a> for Hashbang { + fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { + Doc::Str(self.span.source_text(p.source_text)) } } diff --git a/crates/oxc_prettier/src/format/statement.rs b/crates/oxc_prettier/src/format/statement.rs index 933a2dbdf..0607e4865 100644 --- a/crates/oxc_prettier/src/format/statement.rs +++ b/crates/oxc_prettier/src/format/statement.rs @@ -4,7 +4,6 @@ use crate::{doc::Doc, hardline, Prettier}; use oxc_span::GetSpan; use super::Format; -use crate::util::is_next_line_empty; pub(super) fn print_statement_sequence<'a, F: Format<'a> + GetSpan>( p: &mut Prettier<'a>, @@ -32,7 +31,7 @@ pub(super) fn print_statement_sequence<'a, F: Format<'a> + GetSpan>( if i < stmts.len() - 1 { parts.push(hardline!()); - if is_next_line_empty(p.source_text, stmt.span()) { + if p.is_next_line_empty(stmt.span().end) { parts.push(hardline!()); } } diff --git a/crates/oxc_prettier/src/lib.rs b/crates/oxc_prettier/src/lib.rs index 7cb4f875d..d49ef6c35 100644 --- a/crates/oxc_prettier/src/lib.rs +++ b/crates/oxc_prettier/src/lib.rs @@ -8,7 +8,6 @@ mod format; mod macros; mod options; mod printer; -mod util; use std::{iter::Peekable, vec}; @@ -63,4 +62,8 @@ impl<'a> Prettier<'a> { let trailing_comma = self.options.trailing_comma; trailing_comma.is_all() || (trailing_comma.is_es5() && !level_all) } + + pub(crate) fn is_next_line_empty(&self, end: u32) -> bool { + self.source_text[end as usize..].chars().nth(1).is_some_and(|c| c == '\n') + } } diff --git a/crates/oxc_prettier/src/util.rs b/crates/oxc_prettier/src/util.rs deleted file mode 100644 index 595712861..000000000 --- a/crates/oxc_prettier/src/util.rs +++ /dev/null @@ -1,5 +0,0 @@ -use oxc_span::Span; - -pub fn is_next_line_empty(source_text: &str, span: Span) -> bool { - source_text.chars().nth((span.end as usize) + 1).is_some_and(|c| c == '\n') -} diff --git a/tasks/prettier_conformance/prettier.snap.md b/tasks/prettier_conformance/prettier.snap.md index 3029d2462..b2d4ec9cb 100644 --- a/tasks/prettier_conformance/prettier.snap.md +++ b/tasks/prettier_conformance/prettier.snap.md @@ -1,4 +1,4 @@ -Compatibility: 98/881 (11.12%) +Compatibility: 100/881 (11.35%) # Failed @@ -939,10 +939,6 @@ Compatibility: 98/881 (11.12%) * sequence-expression/ignore.js * sequence-expression/parenthesized.js -### shebang -* shebang/shebang-newline.js -* shebang/shebang.js - ### source-phase-imports * source-phase-imports/default-binding.js * source-phase-imports/import-source-attributes-declaration.js