From 8f93891dc7796baeae05835cff819276389e5559 Mon Sep 17 00:00:00 2001 From: Cameron Date: Tue, 7 Nov 2023 02:58:04 +0000 Subject: [PATCH] feat(linter) eslint plugin unicorn: no new buffer (#1174) --- crates/oxc_linter/src/rules.rs | 2 + .../src/rules/unicorn/no_new_buffer.rs | 88 +++++++++++++++ .../src/snapshots/no_new_buffer.snap | 103 ++++++++++++++++++ 3 files changed, 193 insertions(+) create mode 100644 crates/oxc_linter/src/rules/unicorn/no_new_buffer.rs create mode 100644 crates/oxc_linter/src/snapshots/no_new_buffer.snap diff --git a/crates/oxc_linter/src/rules.rs b/crates/oxc_linter/src/rules.rs index af77295cb..b2f452309 100644 --- a/crates/oxc_linter/src/rules.rs +++ b/crates/oxc_linter/src/rules.rs @@ -149,6 +149,7 @@ mod unicorn { pub mod no_instanceof_array; pub mod no_invalid_remove_event_listener; pub mod no_new_array; + pub mod no_new_buffer; pub mod no_object_as_default_parameter; pub mod no_static_only_class; pub mod no_thenable; @@ -282,6 +283,7 @@ oxc_macros::declare_all_lint_rules! { unicorn::no_instanceof_array, unicorn::no_invalid_remove_event_listener, unicorn::no_new_array, + unicorn::no_new_buffer, unicorn::no_object_as_default_parameter, unicorn::no_static_only_class, unicorn::no_thenable, diff --git a/crates/oxc_linter/src/rules/unicorn/no_new_buffer.rs b/crates/oxc_linter/src/rules/unicorn/no_new_buffer.rs new file mode 100644 index 000000000..312389e55 --- /dev/null +++ b/crates/oxc_linter/src/rules/unicorn/no_new_buffer.rs @@ -0,0 +1,88 @@ +use oxc_ast::{ast::Expression, AstKind}; +use oxc_diagnostics::{ + miette::{self, Diagnostic}, + thiserror::Error, +}; +use oxc_macros::declare_oxc_lint; +use oxc_span::Span; + +use crate::{context::LintContext, rule::Rule, AstNode}; + +#[derive(Debug, Error, Diagnostic)] +#[error("eslint-plugin-unicorn(no-new-buffer): Use `Buffer.alloc()` or `Buffer.from()` instead of the deprecated `new Buffer()` constructor.")] +#[diagnostic( + severity(warning), + help("`new Buffer()` is deprecated, use `Buffer.alloc()` or `Buffer.from()` instead.") +)] +struct NoNewBufferDiagnostic(#[label] pub Span); + +#[derive(Debug, Default, Clone)] +pub struct NoNewBuffer; + +declare_oxc_lint!( + /// ### What it does + /// + /// Disallows the deprecated `new Buffer()` constructor. + /// + /// ### Why is this bad? + /// + /// Enforces the use of [Buffer.from](https://nodejs.org/api/buffer.html#static-method-bufferfromarray) and [Buffer.alloc()](https://nodejs.org/api/buffer.html#static-method-bufferallocsize-fill-encoding) instead of [new Buffer()](https://nodejs.org/api/buffer.html#new-bufferarray), which has been deprecated since Node.js 4. + /// + /// ### Example + /// ```javascript + /// // Bad + /// const buffer = new Buffer(10); + /// + /// // Good + /// const buffer = Buffer.alloc(10); + /// ``` + NoNewBuffer, + pedantic +); + +impl Rule for NoNewBuffer { + fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { + let AstKind::NewExpression(new_expr) = node.kind() else { return }; + + let Expression::Identifier(ident) = &new_expr.callee.without_parenthesized() else { + return; + }; + if ident.name != "Buffer" { + return; + } + ctx.diagnostic(NoNewBufferDiagnostic(ident.span)); + } +} + +#[test] +fn test() { + use crate::tester::Tester; + + let pass = vec![ + r#"const buffer = Buffer"#, + r#"const buffer = new NotBuffer(1)"#, + r#"const buffer = Buffer.from('buf')"#, + r#"const buffer = Buffer.from('7468697320697320612074c3a97374', 'hex')"#, + r#"const buffer = Buffer.from([0x62, 0x75, 0x66, 0x66, 0x65, 0x72])"#, + r#"const buffer = Buffer.alloc(10)"#, + ]; + + let fail = vec![ + r#"const buffer = new Buffer([0x62, 0x75, 0x66, 0x66, 0x65, 0x72])"#, + r#"const buffer = new Buffer([0x62, bar])"#, + r#"const buffer = new Buffer(10);"#, + r#"new Buffer(foo.length)"#, + r#"new Buffer(Math.min(foo, bar))"#, + r#"const buffer = new Buffer("string");"#, + r#"const buffer = new Buffer("7468697320697320612074c3a97374", "hex")"#, + r#"const buffer = new Buffer(`${unknown}`)"#, + r#"const buffer = new (Buffer)(unknown)"#, + r#"const buffer = new Buffer(unknown, 2)"#, + r#"const buffer = new Buffer(...unknown)"#, + r#"const buffer = new /* comment */ Buffer()"#, + r#"const buffer = new /* comment */ Buffer"#, + r#"new Buffer(input, encoding);"#, + ]; + + Tester::new_without_config(NoNewBuffer::NAME, pass, fail).test_and_snapshot(); +} diff --git a/crates/oxc_linter/src/snapshots/no_new_buffer.snap b/crates/oxc_linter/src/snapshots/no_new_buffer.snap new file mode 100644 index 000000000..b5d45c420 --- /dev/null +++ b/crates/oxc_linter/src/snapshots/no_new_buffer.snap @@ -0,0 +1,103 @@ +--- +source: crates/oxc_linter/src/tester.rs +expression: no_new_buffer +--- + ⚠ eslint-plugin-unicorn(no-new-buffer): Use `Buffer.alloc()` or `Buffer.from()` instead of the deprecated `new Buffer()` constructor. + ╭─[no_new_buffer.tsx:1:1] + 1 │ const buffer = new Buffer([0x62, 0x75, 0x66, 0x66, 0x65, 0x72]) + · ────── + ╰──── + help: `new Buffer()` is deprecated, use `Buffer.alloc()` or `Buffer.from()` instead. + + ⚠ eslint-plugin-unicorn(no-new-buffer): Use `Buffer.alloc()` or `Buffer.from()` instead of the deprecated `new Buffer()` constructor. + ╭─[no_new_buffer.tsx:1:1] + 1 │ const buffer = new Buffer([0x62, bar]) + · ────── + ╰──── + help: `new Buffer()` is deprecated, use `Buffer.alloc()` or `Buffer.from()` instead. + + ⚠ eslint-plugin-unicorn(no-new-buffer): Use `Buffer.alloc()` or `Buffer.from()` instead of the deprecated `new Buffer()` constructor. + ╭─[no_new_buffer.tsx:1:1] + 1 │ const buffer = new Buffer(10); + · ────── + ╰──── + help: `new Buffer()` is deprecated, use `Buffer.alloc()` or `Buffer.from()` instead. + + ⚠ eslint-plugin-unicorn(no-new-buffer): Use `Buffer.alloc()` or `Buffer.from()` instead of the deprecated `new Buffer()` constructor. + ╭─[no_new_buffer.tsx:1:1] + 1 │ new Buffer(foo.length) + · ────── + ╰──── + help: `new Buffer()` is deprecated, use `Buffer.alloc()` or `Buffer.from()` instead. + + ⚠ eslint-plugin-unicorn(no-new-buffer): Use `Buffer.alloc()` or `Buffer.from()` instead of the deprecated `new Buffer()` constructor. + ╭─[no_new_buffer.tsx:1:1] + 1 │ new Buffer(Math.min(foo, bar)) + · ────── + ╰──── + help: `new Buffer()` is deprecated, use `Buffer.alloc()` or `Buffer.from()` instead. + + ⚠ eslint-plugin-unicorn(no-new-buffer): Use `Buffer.alloc()` or `Buffer.from()` instead of the deprecated `new Buffer()` constructor. + ╭─[no_new_buffer.tsx:1:1] + 1 │ const buffer = new Buffer("string"); + · ────── + ╰──── + help: `new Buffer()` is deprecated, use `Buffer.alloc()` or `Buffer.from()` instead. + + ⚠ eslint-plugin-unicorn(no-new-buffer): Use `Buffer.alloc()` or `Buffer.from()` instead of the deprecated `new Buffer()` constructor. + ╭─[no_new_buffer.tsx:1:1] + 1 │ const buffer = new Buffer("7468697320697320612074c3a97374", "hex") + · ────── + ╰──── + help: `new Buffer()` is deprecated, use `Buffer.alloc()` or `Buffer.from()` instead. + + ⚠ eslint-plugin-unicorn(no-new-buffer): Use `Buffer.alloc()` or `Buffer.from()` instead of the deprecated `new Buffer()` constructor. + ╭─[no_new_buffer.tsx:1:1] + 1 │ const buffer = new Buffer(`${unknown}`) + · ────── + ╰──── + help: `new Buffer()` is deprecated, use `Buffer.alloc()` or `Buffer.from()` instead. + + ⚠ eslint-plugin-unicorn(no-new-buffer): Use `Buffer.alloc()` or `Buffer.from()` instead of the deprecated `new Buffer()` constructor. + ╭─[no_new_buffer.tsx:1:1] + 1 │ const buffer = new (Buffer)(unknown) + · ────── + ╰──── + help: `new Buffer()` is deprecated, use `Buffer.alloc()` or `Buffer.from()` instead. + + ⚠ eslint-plugin-unicorn(no-new-buffer): Use `Buffer.alloc()` or `Buffer.from()` instead of the deprecated `new Buffer()` constructor. + ╭─[no_new_buffer.tsx:1:1] + 1 │ const buffer = new Buffer(unknown, 2) + · ────── + ╰──── + help: `new Buffer()` is deprecated, use `Buffer.alloc()` or `Buffer.from()` instead. + + ⚠ eslint-plugin-unicorn(no-new-buffer): Use `Buffer.alloc()` or `Buffer.from()` instead of the deprecated `new Buffer()` constructor. + ╭─[no_new_buffer.tsx:1:1] + 1 │ const buffer = new Buffer(...unknown) + · ────── + ╰──── + help: `new Buffer()` is deprecated, use `Buffer.alloc()` or `Buffer.from()` instead. + + ⚠ eslint-plugin-unicorn(no-new-buffer): Use `Buffer.alloc()` or `Buffer.from()` instead of the deprecated `new Buffer()` constructor. + ╭─[no_new_buffer.tsx:1:1] + 1 │ const buffer = new /* comment */ Buffer() + · ────── + ╰──── + help: `new Buffer()` is deprecated, use `Buffer.alloc()` or `Buffer.from()` instead. + + ⚠ eslint-plugin-unicorn(no-new-buffer): Use `Buffer.alloc()` or `Buffer.from()` instead of the deprecated `new Buffer()` constructor. + ╭─[no_new_buffer.tsx:1:1] + 1 │ const buffer = new /* comment */ Buffer + · ────── + ╰──── + help: `new Buffer()` is deprecated, use `Buffer.alloc()` or `Buffer.from()` instead. + + ⚠ eslint-plugin-unicorn(no-new-buffer): Use `Buffer.alloc()` or `Buffer.from()` instead of the deprecated `new Buffer()` constructor. + ╭─[no_new_buffer.tsx:1:1] + 1 │ new Buffer(input, encoding); + · ────── + ╰──── + help: `new Buffer()` is deprecated, use `Buffer.alloc()` or `Buffer.from()` instead. + +