refactor(codegen): improve print API (#4196)

This commit is contained in:
Boshen 2024-07-11 08:41:04 +00:00
parent 4f26e51b74
commit aa22073736
14 changed files with 470 additions and 469 deletions

File diff suppressed because it is too large Load diff

View file

@ -175,13 +175,15 @@ impl<'a, const MINIFY: bool> Codegen<'a, MINIFY> {
} }
/// Push a single character into the buffer /// Push a single character into the buffer
pub fn print(&mut self, ch: u8) { #[inline]
pub fn print_char(&mut self, ch: u8) {
self.code.push(ch); self.code.push(ch);
} }
/// Push a single character into the buffer /// Push a single character into the buffer
pub fn print_str<T: AsRef<[u8]>>(&mut self, s: T) { #[inline]
self.code.extend_from_slice(s.as_ref()); pub fn print_str(&mut self, s: &str) {
self.code.extend(s.as_bytes());
} }
} }
@ -198,30 +200,30 @@ impl<'a, const MINIFY: bool> Codegen<'a, MINIFY> {
#[inline] #[inline]
fn print_soft_space(&mut self) { fn print_soft_space(&mut self) {
if !MINIFY { if !MINIFY {
self.print(b' '); self.print_char(b' ');
} }
} }
#[inline] #[inline]
pub fn print_hard_space(&mut self) { pub fn print_hard_space(&mut self) {
self.print(b' '); self.print_char(b' ');
} }
#[inline] #[inline]
fn print_soft_newline(&mut self) { fn print_soft_newline(&mut self) {
if !MINIFY { if !MINIFY {
self.print(b'\n'); self.print_char(b'\n');
} }
} }
#[inline] #[inline]
fn print_semicolon(&mut self) { fn print_semicolon(&mut self) {
self.print(b';'); self.print_char(b';');
} }
#[inline] #[inline]
fn print_comma(&mut self) { fn print_comma(&mut self) {
self.print(b','); self.print_char(b',');
} }
#[inline] #[inline]
@ -273,7 +275,7 @@ impl<'a, const MINIFY: bool> Codegen<'a, MINIFY> {
if MINIFY { if MINIFY {
self.needs_semicolon = true; self.needs_semicolon = true;
} else { } else {
self.print_str(b";\n"); self.print_str(";\n");
} }
} }
@ -287,17 +289,17 @@ impl<'a, const MINIFY: bool> Codegen<'a, MINIFY> {
#[inline] #[inline]
fn print_ellipsis(&mut self) { fn print_ellipsis(&mut self) {
self.print_str(b"..."); self.print_str("...");
} }
#[inline] #[inline]
pub fn print_colon(&mut self) { pub fn print_colon(&mut self) {
self.print(b':'); self.print_char(b':');
} }
#[inline] #[inline]
fn print_equal(&mut self) { fn print_equal(&mut self) {
self.print(b'='); self.print_char(b'=');
} }
fn print_sequence<T: Gen<MINIFY>>(&mut self, items: &[T], ctx: Context) { fn print_sequence<T: Gen<MINIFY>>(&mut self, items: &[T], ctx: Context) {
@ -309,7 +311,7 @@ impl<'a, const MINIFY: bool> Codegen<'a, MINIFY> {
fn print_curly_braces<F: FnOnce(&mut Self)>(&mut self, span: Span, single_line: bool, op: F) { fn print_curly_braces<F: FnOnce(&mut Self)>(&mut self, span: Span, single_line: bool, op: F) {
self.add_source_mapping(span.start); self.add_source_mapping(span.start);
self.print(b'{'); self.print_char(b'{');
if !single_line { if !single_line {
self.print_soft_newline(); self.print_soft_newline();
self.indent(); self.indent();
@ -320,12 +322,12 @@ impl<'a, const MINIFY: bool> Codegen<'a, MINIFY> {
self.print_indent(); self.print_indent();
} }
self.add_source_mapping(span.end); self.add_source_mapping(span.end);
self.print(b'}'); self.print_char(b'}');
} }
fn print_block_start(&mut self, position: u32) { fn print_block_start(&mut self, position: u32) {
self.add_source_mapping(position); self.add_source_mapping(position);
self.print(b'{'); self.print_char(b'{');
self.print_soft_newline(); self.print_soft_newline();
self.indent(); self.indent();
} }
@ -334,7 +336,7 @@ impl<'a, const MINIFY: bool> Codegen<'a, MINIFY> {
self.dedent(); self.dedent();
self.print_indent(); self.print_indent();
self.add_source_mapping(position); self.add_source_mapping(position);
self.print(b'}'); self.print_char(b'}');
} }
fn print_body(&mut self, stmt: &Statement<'_>, need_space: bool, ctx: Context) { fn print_body(&mut self, stmt: &Statement<'_>, need_space: bool, ctx: Context) {
@ -400,12 +402,12 @@ impl<'a, const MINIFY: bool> Codegen<'a, MINIFY> {
// if let Some(mangler) = &self.mangler { // if let Some(mangler) = &self.mangler {
// if let Some(symbol_id) = symbol_id { // if let Some(symbol_id) = symbol_id {
// let name = mangler.get_symbol_name(symbol_id); // let name = mangler.get_symbol_name(symbol_id);
// self.print_str(name.clone().as_bytes()); // self.print_str(name.clone());
// return; // return;
// } // }
// } // }
self.add_source_mapping_for_name(span, fallback); self.add_source_mapping_for_name(span, fallback);
self.print_str(fallback.as_bytes()); self.print_str(fallback);
} }
fn print_space_before_operator(&mut self, next: Operator) { fn print_space_before_operator(&mut self, next: Operator) {
@ -454,9 +456,9 @@ impl<'a, const MINIFY: bool> Codegen<'a, MINIFY> {
#[inline] #[inline]
fn wrap_quote<F: FnMut(&mut Self, char)>(&mut self, s: &str, mut f: F) { fn wrap_quote<F: FnMut(&mut Self, char)>(&mut self, s: &str, mut f: F) {
let quote = Self::choose_quote(s); let quote = Self::choose_quote(s);
self.print(quote as u8); self.print_char(quote as u8);
f(self, quote); f(self, quote);
self.print(quote as u8); self.print_char(quote as u8);
} }
fn print_directives_and_statements( fn print_directives_and_statements(

View file

@ -83,13 +83,13 @@ impl NoUnsafeNegation {
// modify `!a instance of B` to `!(a instanceof B)` // modify `!a instance of B` to `!(a instanceof B)`
let modified_code = { let modified_code = {
let mut codegen = fixer.codegen(); let mut codegen = fixer.codegen();
codegen.print(b'!'); codegen.print_char(b'!');
let Expression::UnaryExpression(left) = &expr.left else { unreachable!() }; let Expression::UnaryExpression(left) = &expr.left else { unreachable!() };
codegen.print(b'('); codegen.print_char(b'(');
codegen.print_expression(&left.argument); codegen.print_expression(&left.argument);
expr.operator.gen(&mut codegen, Context::default()); expr.operator.gen(&mut codegen, Context::default());
codegen.print_expression(&expr.right); codegen.print_expression(&expr.right);
codegen.print(b')'); codegen.print_char(b')');
codegen.into_source_text() codegen.into_source_text()
}; };
fixer.replace(expr.span, modified_code) fixer.replace(expr.span, modified_code)

View file

@ -141,9 +141,9 @@ impl NoUntypedMockFactory {
), ),
|fixer| { |fixer| {
let mut content = fixer.codegen(); let mut content = fixer.codegen();
content.print_str(b"<typeof import('"); content.print_str("<typeof import('");
content.print_str(string_literal.value.as_bytes()); content.print_str(string_literal.value.as_str());
content.print_str(b"')>("); content.print_str("')>(");
let span = Span::sized(string_literal.span.start - 1, 1); let span = Span::sized(string_literal.span.start - 1, 1);
fixer.replace(span, content) fixer.replace(span, content)

View file

@ -127,7 +127,7 @@ impl PreferComparisonMatcher {
binary_expr, binary_expr,
call_span_end, call_span_end,
arg_span_end, arg_span_end,
parse_expect_jest_fn.local.as_bytes(), &parse_expect_jest_fn.local,
&parse_expect_jest_fn.modifiers(), &parse_expect_jest_fn.modifiers(),
prefer_matcher_name, prefer_matcher_name,
fixer, fixer,
@ -175,31 +175,31 @@ impl PreferComparisonMatcher {
binary_expr: &BinaryExpression<'a>, binary_expr: &BinaryExpression<'a>,
call_span_end: &str, call_span_end: &str,
arg_span_end: &str, arg_span_end: &str,
local_name: &[u8], local_name: &str,
modifiers: &[&KnownMemberExpressionProperty<'a>], modifiers: &[&KnownMemberExpressionProperty<'a>],
prefer_matcher_name: &str, prefer_matcher_name: &str,
fixer: RuleFixer<'_, 'a>, fixer: RuleFixer<'_, 'a>,
) -> String { ) -> String {
let mut content = fixer.codegen(); let mut content = fixer.codegen();
content.print_str(local_name); content.print_str(local_name);
content.print(b'('); content.print_char(b'(');
content.print_expression(&binary_expr.left); content.print_expression(&binary_expr.left);
content.print_str(call_span_end.as_bytes()); content.print_str(call_span_end);
content.print(b'.'); content.print_char(b'.');
for modifier in modifiers { for modifier in modifiers {
let Some(modifier_name) = modifier.name() else { let Some(modifier_name) = modifier.name() else {
continue; continue;
}; };
if !modifier_name.eq("not") { if !modifier_name.eq("not") {
content.print_str(modifier_name.as_bytes()); content.print_str(&modifier_name);
content.print(b'.'); content.print_char(b'.');
} }
} }
content.print_str(prefer_matcher_name.as_bytes()); content.print_str(prefer_matcher_name);
content.print(b'('); content.print_char(b'(');
content.print_expression(&binary_expr.right); content.print_expression(&binary_expr.right);
content.print_str(arg_span_end.as_bytes()); content.print_str(arg_span_end);
content.into_source_text() content.into_source_text()
} }
} }

View file

@ -135,12 +135,12 @@ impl PreferExpectResolves {
call_expr.span.end, call_expr.span.end,
); );
formatter.print_str(b"await"); formatter.print_str("await");
formatter.print_hard_space(); formatter.print_hard_space();
formatter.print_str(jest_expect_fn_call.local.as_bytes()); formatter.print_str(&jest_expect_fn_call.local);
formatter.print(b'('); formatter.print_char(b'(');
formatter.print_str(fixer.source_range(arg_span)); formatter.print_str(fixer.source_range(arg_span));
formatter.print_str(b".resolves"); formatter.print_str(".resolves");
fixer.replace(call_expr.span, formatter) fixer.replace(call_expr.span, formatter)
} }
} }

View file

@ -167,9 +167,9 @@ impl PreferMockPromiseShorthand {
) -> String { ) -> String {
let mut content = fixer.codegen(); let mut content = fixer.codegen();
content.print_str(prefer_name); content.print_str(prefer_name);
content.print(b'('); content.print_char(b'(');
if call_expr.arguments.is_empty() { if call_expr.arguments.is_empty() {
content.print_str(b"undefined"); content.print_str("undefined");
} else { } else {
for argument in &call_expr.arguments { for argument in &call_expr.arguments {
if let Some(expr) = argument.as_expression() { if let Some(expr) = argument.as_expression() {

View file

@ -139,38 +139,38 @@ impl PreferSpyOn {
fixer: RuleFixer<'_, 'a>, fixer: RuleFixer<'_, 'a>,
) -> String { ) -> String {
let mut formatter = fixer.codegen(); let mut formatter = fixer.codegen();
formatter.print_str(b"jest.spyOn("); formatter.print_str("jest.spyOn(");
match left_assign { match left_assign {
MemberExpression::ComputedMemberExpression(cmp_mem_expr) => { MemberExpression::ComputedMemberExpression(cmp_mem_expr) => {
formatter.print_expression(&cmp_mem_expr.object); formatter.print_expression(&cmp_mem_expr.object);
formatter.print(b','); formatter.print_char(b',');
formatter.print_hard_space(); formatter.print_hard_space();
formatter.print_expression(&cmp_mem_expr.expression); formatter.print_expression(&cmp_mem_expr.expression);
} }
MemberExpression::StaticMemberExpression(static_mem_expr) => { MemberExpression::StaticMemberExpression(static_mem_expr) => {
let name = &static_mem_expr.property.name; let name = &static_mem_expr.property.name;
formatter.print_expression(&static_mem_expr.object); formatter.print_expression(&static_mem_expr.object);
formatter.print(b','); formatter.print_char(b',');
formatter.print_hard_space(); formatter.print_hard_space();
formatter.print_str(format!("\'{name}\'").as_bytes()); formatter.print_str(format!("\'{name}\'").as_str());
} }
MemberExpression::PrivateFieldExpression(_) => (), MemberExpression::PrivateFieldExpression(_) => (),
} }
formatter.print(b')'); formatter.print_char(b')');
if has_mock_implementation { if has_mock_implementation {
return formatter.into_source_text(); return formatter.into_source_text();
} }
formatter.print_str(b".mockImplementation("); formatter.print_str(".mockImplementation(");
if let Some(expr) = Self::get_jest_fn_call(call_expr) { if let Some(expr) = Self::get_jest_fn_call(call_expr) {
formatter.print_expression(expr); formatter.print_expression(expr);
} }
formatter.print(b')'); formatter.print_char(b')');
formatter.into_source_text() formatter.into_source_text()
} }

View file

@ -167,24 +167,24 @@ impl PreferToHaveLength {
return formatter.into_source_text(); return formatter.into_source_text();
}; };
formatter.print_str(b"expect("); formatter.print_str("expect(");
formatter.print_str(prop_ident.name.as_bytes()); formatter.print_str(prop_ident.name.as_str());
formatter.print_str(b")"); formatter.print_str(")");
if let Some(kind_val) = kind { if let Some(kind_val) = kind {
if kind_val == "ComputedMember" { if kind_val == "ComputedMember" {
let property = property_name.unwrap(); let property = property_name.unwrap();
formatter.print_str(b"[\""); formatter.print_str("[\"");
formatter.print_str(property.as_bytes()); formatter.print_str(property);
formatter.print_str(b"\"]"); formatter.print_str("\"]");
} else if kind_val == "StaticMember" { } else if kind_val == "StaticMember" {
formatter.print_str(b"."); formatter.print_str(".");
let property = property_name.unwrap(); let property = property_name.unwrap();
formatter.print_str(property.as_bytes()); formatter.print_str(property);
} }
} }
formatter.print_str(b".toHaveLength"); formatter.print_str(".toHaveLength");
formatter.into_source_text() formatter.into_source_text()
} }
} }

View file

@ -142,21 +142,21 @@ fn build_code<'a>(fixer: RuleFixer<'_, 'a>, expr: &CallExpression<'a>) -> Fix<'a
match &expr.callee { match &expr.callee {
Expression::Identifier(ident) => { Expression::Identifier(ident) => {
formatter.print_str(ident.name.as_bytes()); formatter.print_str(ident.name.as_str());
formatter.print_str(b".todo("); formatter.print_str(".todo(");
} }
Expression::ComputedMemberExpression(expr) => { Expression::ComputedMemberExpression(expr) => {
if let Expression::Identifier(ident) = &expr.object { if let Expression::Identifier(ident) = &expr.object {
formatter.print_str(ident.name.as_bytes()); formatter.print_str(ident.name.as_str());
formatter.print_str(b"["); formatter.print_str("[");
formatter.print_str(b"'todo'"); formatter.print_str("'todo'");
formatter.print_str(b"]("); formatter.print_str("](");
} }
} }
Expression::StaticMemberExpression(expr) => { Expression::StaticMemberExpression(expr) => {
if let Expression::Identifier(ident) = &expr.object { if let Expression::Identifier(ident) = &expr.object {
formatter.print_str(ident.name.as_bytes()); formatter.print_str(ident.name.as_str());
formatter.print_str(b".todo("); formatter.print_str(".todo(");
} }
} }
_ => {} _ => {}
@ -164,17 +164,17 @@ fn build_code<'a>(fixer: RuleFixer<'_, 'a>, expr: &CallExpression<'a>) -> Fix<'a
if let Argument::StringLiteral(ident) = &expr.arguments[0] { if let Argument::StringLiteral(ident) = &expr.arguments[0] {
// Todo: this punctuation should read from the config // Todo: this punctuation should read from the config
formatter.print(b'\''); formatter.print_char(b'\'');
formatter.print_str(ident.value.as_bytes()); formatter.print_str(ident.value.as_str());
formatter.print(b'\''); formatter.print_char(b'\'');
formatter.print(b')'); formatter.print_char(b')');
} else if let Argument::TemplateLiteral(temp) = &expr.arguments[0] { } else if let Argument::TemplateLiteral(temp) = &expr.arguments[0] {
formatter.print(b'`'); formatter.print_char(b'`');
for q in &temp.quasis { for q in &temp.quasis {
formatter.print_str(q.value.raw.as_bytes()); formatter.print_str(q.value.raw.as_str());
} }
formatter.print(b'`'); formatter.print_char(b'`');
formatter.print(b')'); formatter.print_char(b')');
} }
fixer.replace(expr.span, formatter) fixer.replace(expr.span, formatter)

View file

@ -198,7 +198,7 @@ impl ExplicitLengthCheck {
let start = ctx.source_text().as_bytes()[span.start as usize - 1]; let start = ctx.source_text().as_bytes()[span.start as usize - 1];
need_pad_start = start.is_ascii_alphabetic() || !start.is_ascii(); need_pad_start = start.is_ascii_alphabetic() || !start.is_ascii();
} }
if (span.end as usize) < ctx.source_text().as_bytes().len() { if (span.end as usize) < ctx.source_text().len() {
let end = ctx.source_text().as_bytes()[span.end as usize]; let end = ctx.source_text().as_bytes()[span.end as usize];
need_pad_end = end.is_ascii_alphabetic() || !end.is_ascii(); need_pad_end = end.is_ascii_alphabetic() || !end.is_ascii();
} }

View file

@ -224,18 +224,18 @@ fn diagnose_array_in_array_spread<'a>(
// [ ...[a, b, c], ...[d, e, f] ] -> [a, b, c, d, e, f] // [ ...[a, b, c], ...[d, e, f] ] -> [a, b, c, d, e, f]
ctx.diagnostic_with_fix(diagnostic, |fixer| { ctx.diagnostic_with_fix(diagnostic, |fixer| {
let mut codegen = fixer.codegen(); let mut codegen = fixer.codegen();
codegen.print(b'['); codegen.print_char(b'[');
let elements = let elements =
spreads.iter().flat_map(|arr| arr.elements.iter()).collect::<Vec<_>>(); spreads.iter().flat_map(|arr| arr.elements.iter()).collect::<Vec<_>>();
let n = elements.len(); let n = elements.len();
for (i, el) in elements.into_iter().enumerate() { for (i, el) in elements.into_iter().enumerate() {
codegen.print_expression(el.to_expression()); codegen.print_expression(el.to_expression());
if i < n - 1 { if i < n - 1 {
codegen.print(b','); codegen.print_char(b',');
codegen.print_hard_space(); codegen.print_hard_space();
} }
} }
codegen.print(b']'); codegen.print_char(b']');
fixer.replace(outer_array.span, codegen) fixer.replace(outer_array.span, codegen)
}); });
} }

View file

@ -70,8 +70,8 @@ impl Rule for RequireNumberToFixedDigitsArgument {
let span_source_code = let span_source_code =
fixer.source_range(parenthesis_span_without_right_one); fixer.source_range(parenthesis_span_without_right_one);
formatter.print_str(span_source_code.as_bytes()); formatter.print_str(span_source_code);
formatter.print_str(b"0)"); formatter.print_str("0)");
formatter.into_source_text() formatter.into_source_text()
}; };

View file

@ -77,19 +77,19 @@ impl Rule for SwitchCaseBraces {
let mut formatter = fixer.codegen(); let mut formatter = fixer.codegen();
if let Some(case_test) = &case.test { if let Some(case_test) = &case.test {
formatter.print_str(b"case "); formatter.print_str("case ");
formatter.print_expression(case_test); formatter.print_expression(case_test);
} else { } else {
formatter.print_str(b"default"); formatter.print_str("default");
} }
formatter.print_colon(); formatter.print_colon();
formatter.print_hard_space(); formatter.print_hard_space();
formatter.print(b'{'); formatter.print_char(b'{');
case.consequent case.consequent
.iter() .iter()
.for_each(|x| x.gen(&mut formatter, Context::default())); .for_each(|x| x.gen(&mut formatter, Context::default()));
formatter.print(b'}'); formatter.print_char(b'}');
formatter.into_source_text() formatter.into_source_text()
}; };