feat(prettier): implement is_next_line_empty_after_index (#1575)

This commit is contained in:
Boshen 2023-11-29 14:37:33 +08:00 committed by GitHub
parent a9f0206805
commit 7236368d5a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 60 additions and 39 deletions

View file

@ -74,7 +74,7 @@ impl<'a> Prettier<'a> {
}
if self
.skip_spaces(comment.end, false)
.skip_spaces(Some(comment.end), false)
.and_then(|idx| self.skip_newline(Some(idx), false))
.is_some_and(|i| self.has_newline(i, /* backwards */ false))
{

View file

@ -61,7 +61,7 @@ impl<'a> Format<'a> for Program<'a> {
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) {
if p.is_next_line_empty_after_index(hashbang.span.end - 1) {
parts.extend(hardline!());
}
}
@ -427,7 +427,7 @@ impl<'a> Format<'a> for SwitchStatement<'a> {
parts.push(format!(p, case));
Doc::Indent(parts)
});
if i != len - 1 && p.is_next_line_empty(case.span.end) {
if i != len - 1 && p.is_next_line_empty(case.span) {
cases_parts.extend(hardline!());
}
}
@ -467,7 +467,7 @@ impl<'a> Format<'a> for SwitchCase<'a> {
if i != 0 && matches!(stmt, Statement::BreakStatement(_)) {
let last_stmt = &consequent[i - 1];
if p.is_next_line_empty(last_stmt.span().end) {
if p.is_next_line_empty(last_stmt.span()) {
consequent_parts.extend(hardline!());
}
}

View file

@ -46,7 +46,7 @@ pub(super) fn print_statement_sequence<'a>(
if i < len - 1 {
parts.extend(hardline!());
if p.is_next_line_empty(stmt.span().end) {
if p.is_next_line_empty(stmt.span()) {
parts.extend(hardline!());
}
}

View file

@ -14,12 +14,12 @@ mod printer;
use std::{iter::Peekable, vec};
use doc::DocBuilder;
use oxc_allocator::Allocator;
use oxc_ast::{ast::Program, AstKind, CommentKind, Trivias};
use oxc_span::Span;
use oxc_syntax::identifier::is_line_terminator;
use crate::{doc::Doc, format::Format, printer::Printer};
use crate::{doc::Doc, doc::DocBuilder, format::Format, printer::Printer};
pub use crate::options::{ArrowParens, EndOfLine, PrettierOptions, QuoteProps, TrailingComma};
@ -135,8 +135,55 @@ impl<'a> Prettier<'a> {
trailing_comma.is_all() || (trailing_comma.is_es5() && !level_all)
}
fn is_next_line_empty(&self, end: u32) -> bool {
self.source_text[end as usize..].chars().nth(1).is_some_and(|c| c == '\n')
fn is_next_line_empty(&self, span: Span) -> bool {
self.is_next_line_empty_after_index(span.end)
}
fn is_next_line_empty_after_index(&self, start_index: u32) -> bool {
let mut old_idx = None;
let mut idx = Some(start_index);
while idx != old_idx {
old_idx = idx;
idx = self.skip_to_line_end(idx);
// idx = self.skip_inline_comment(idx);
idx = self.skip_spaces(idx, /* backwards */ false);
}
// idx = self.skip_trailing_comment(idx);
idx = self.skip_newline(idx, /* backwards */ false);
idx.is_some_and(|idx| self.has_newline(idx, /* backwards */ false))
// self.source_text[end as usize..].chars().nth(1).is_some_and(|c| c == '\n')
}
fn skip_to_line_end(&self, start_index: Option<u32>) -> Option<u32> {
self.skip(start_index, false, |c| matches!(c, ' ' | '\t' | ',' | ';'))
}
fn skip_spaces(&self, start_index: Option<u32>, backwards: bool) -> Option<u32> {
self.skip(start_index, backwards, |c| matches!(c, ' ' | '\t'))
}
fn skip<F>(&self, start_index: Option<u32>, backwards: bool, f: F) -> Option<u32>
where
F: Fn(char) -> bool,
{
let start_index = start_index?;
let mut index = start_index;
if backwards {
for c in self.source_text[..=start_index as usize].chars().rev() {
if !f(c) {
return Some(index);
}
index -= 1_u32;
}
} else {
for c in self.source_text[start_index as usize..].chars() {
if !f(c) {
return Some(index);
}
index += 1_u32;
}
}
None
}
#[allow(clippy::cast_possible_truncation)]
@ -154,26 +201,6 @@ impl<'a> Prettier<'a> {
Some(start_index)
}
fn skip_spaces(&self, start_index: u32, backwards: bool) -> Option<u32> {
let mut index = start_index;
if backwards {
for c in self.source_text[..=start_index as usize].chars().rev() {
if !matches!(c, ' ' | '\t') {
return Some(index);
}
index -= 1_u32;
}
} else {
for c in self.source_text[start_index as usize..].chars() {
if !matches!(c, ' ' | '\t') {
return Some(index);
}
index += 1_u32;
}
}
None
}
fn has_newline(&self, start_index: u32, backwards: bool) -> bool {
if (backwards && start_index == 0)
|| (!backwards && start_index as usize == self.source_text.len())
@ -181,15 +208,15 @@ impl<'a> Prettier<'a> {
return false;
}
let start_index = if backwards { start_index - 1 } else { start_index };
let idx = self.skip_spaces(start_index, backwards);
let idx = self.skip_spaces(Some(start_index), backwards);
let idx2 = self.skip_newline(idx, backwards);
idx != idx2
}
fn is_previous_line_empty(&self, start_index: u32) -> bool {
let idx = start_index - 1;
let idx = self.skip_spaces(idx, true);
let Some(idx) = self.skip_newline(idx, true) else { return false };
let idx = self.skip_spaces(Some(idx), true);
let idx = self.skip_newline(idx, true);
let idx = self.skip_spaces(idx, true);
let idx2 = self.skip_newline(idx, true);
idx != idx2

View file

@ -1,4 +1,4 @@
Compatibility: 194/580 (33.45%)
Compatibility: 196/580 (33.79%)
# Failed
@ -124,9 +124,6 @@ Compatibility: 194/580 (33.45%)
* class-extends/extends.js
* class-extends/tuple-and-record.js
### class-static-block
* class-static-block/class-static-block.js
### classes
* classes/assignment.js
* classes/empty.js
@ -300,9 +297,6 @@ Compatibility: 194/580 (33.45%)
* functional-composition/reselect_createselector.js
* functional-composition/rxjs_pipe.js
### generator
* generator/anonymous.js
### identifier/for-of
* identifier/for-of/await.js
* identifier/for-of/let.js