feat(linter) eslint plugin unicorn: no new array (#1160)

This commit is contained in:
Cameron 2023-11-06 01:57:48 +00:00 committed by GitHub
parent 013cfe9c44
commit 0635d7b740
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 533 additions and 0 deletions

View file

@ -146,6 +146,7 @@ mod unicorn {
pub mod no_empty_file;
pub mod no_instanceof_array;
pub mod no_invalid_remove_event_listener;
pub mod no_new_array;
pub mod no_thenable;
pub mod no_unnecessary_await;
pub mod prefer_array_flat_map;
@ -272,6 +273,7 @@ oxc_macros::declare_all_lint_rules! {
unicorn::no_empty_file,
unicorn::no_instanceof_array,
unicorn::no_invalid_remove_event_listener,
unicorn::no_new_array,
unicorn::no_thenable,
unicorn::no_unnecessary_await,
unicorn::prefer_array_flat_map,

View file

@ -0,0 +1,134 @@
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-array): Do not use `new Array()`.")]
#[diagnostic(severity(warning), help(r#"If the argument is the array's length, consider using `Array.from({{ length: n }})` instead. If the argument is the only element, use `[element]` instead."#))]
struct NoNewArrayDiagnostic(#[label] pub Span);
#[derive(Debug, Default, Clone)]
pub struct NoNewArray;
declare_oxc_lint!(
/// ### What it does
///
/// Disallow `new Array()`.
///
/// ### Why is this bad?
///
/// When using the `Array` constructor with one argument, it's not clear whether the argument is meant to be the length of the array or the only element.
///
/// ### Example
/// ```javascript
/// // bad
/// const array = new Array(1);
/// const array = new Array(42);
/// const array = new Array(foo);
///
/// // good
/// const array = Array.from({ length: 42 });
/// const array = [42];
/// ```
NoNewArray,
correctness
);
impl Rule for NoNewArray {
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 else { return };
if ident.name != "Array" {
return;
}
if new_expr.arguments.len() != 1 {
return;
}
ctx.diagnostic(NoNewArrayDiagnostic(new_expr.span));
}
}
#[test]
fn test() {
use crate::tester::Tester;
let pass = vec![
r#"const array = Array.from({length: 1})"#,
r#"const array = new Array()"#,
r#"const array = new Array"#,
r#"const array = new Array(1, 2)"#,
r#"const array = Array(1, 2)"#,
r#"const array = Array(1)"#,
];
let fail = vec![
r#"const array = new Array(1)"#,
r#"const array = new Array(1.5)"#,
r#"const array = new Array(Number("1"))"#,
r#"const array = new Array("1")"#,
r#"const array = new Array(null)"#,
r#"const array = new Array(("1"))"#,
r#"const array = new Array((0, 1))"#,
r#"new Array(0xff)"#,
r#"new Array(Math.PI | foo)"#,
r#"new Array(Math.min(foo, bar))"#,
r#"new Array(Number(foo))"#,
r#"new Array(Number.MAX_SAFE_INTEGER)"#,
r#"new Array(parseInt(foo))"#,
r#"new Array(Number.parseInt(foo))"#,
r#"new Array(+foo)"#,
r#"new Array(-Math.PI)"#,
r#"new Array(-"-2")"#,
r#"new Array(foo.length)"#,
r#"const foo = 1; new Array(foo + 2)"#,
r#"new Array(foo - 2)"#,
r#"new Array(foo -= 2)"#,
r#"new Array(foo ? 1 : 2)"#,
r#"const truthy = "truthy"; new Array(truthy ? 1 : foo)"#,
r#"const falsy = !"truthy"; new Array(falsy ? foo : 1)"#,
r#"new Array((1n, 2))"#,
r#"new Array(Number.NaN)"#,
r#"new Array(NaN)"#,
r#"new Array(foo >>> bar)"#,
r#"new Array(foo >>>= bar)"#,
r#"new Array(++bar.length)"#,
r#"new Array(bar.length++)"#,
r#"new Array(foo = bar.length)"#,
r#"new Array("0xff")"#,
r#"new Array(Math.NON_EXISTS_PROPERTY)"#,
r#"new Array(Math.NON_EXISTS_METHOD(foo))"#,
r#"new Array(Math[min](foo, bar))"#,
r#"new Array(Number[MAX_SAFE_INTEGER])"#,
r#"new Array(new Number(foo))"#,
r#"const foo = 1; new Array(foo + "2")"#,
r#"new Array(foo - 2n)"#,
r#"new Array(foo -= 2n)"#,
r#"new Array(foo instanceof 1)"#,
r#"new Array(foo || 1)"#,
r#"new Array(foo ||= 1)"#,
r#"new Array(foo ? 1n : 2)"#,
r#"new Array((1, 2n))"#,
r#"new Array(-foo)"#,
r#"new Array(~foo)"#,
r#"new Array(typeof 1)"#,
r#"const truthy = "truthy"; new Array(truthy ? foo : 1)"#,
r#"const falsy = !"truthy"; new Array(falsy ? 1 : foo)"#,
r#"new Array(unknown ? foo : 1)"#,
r#"new Array(unknown ? 1 : foo)"#,
r#"new Array(++foo)"#,
r#"const array = new Array(foo)"#,
r#"const array = new Array(length)"#,
];
Tester::new_without_config(NoNewArray::NAME, pass, fail).test_and_snapshot();
}

View file

@ -0,0 +1,397 @@
---
source: crates/oxc_linter/src/tester.rs
expression: no_new_array
---
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ const array = new Array(1)
· ────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ const array = new Array(1.5)
· ──────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ const array = new Array(Number("1"))
· ──────────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ const array = new Array("1")
· ──────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ const array = new Array(null)
· ───────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ const array = new Array(("1"))
· ────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ const array = new Array((0, 1))
· ─────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array(0xff)
· ───────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array(Math.PI | foo)
· ────────────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array(Math.min(foo, bar))
· ─────────────────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array(Number(foo))
· ──────────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array(Number.MAX_SAFE_INTEGER)
· ──────────────────────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array(parseInt(foo))
· ────────────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array(Number.parseInt(foo))
· ───────────────────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array(+foo)
· ───────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array(-Math.PI)
· ───────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array(-"-2")
· ────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array(foo.length)
· ─────────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ const foo = 1; new Array(foo + 2)
· ──────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array(foo - 2)
· ──────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array(foo -= 2)
· ───────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array(foo ? 1 : 2)
· ──────────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ const truthy = "truthy"; new Array(truthy ? 1 : foo)
· ───────────────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ const falsy = !"truthy"; new Array(falsy ? foo : 1)
· ──────────────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array((1n, 2))
· ──────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array(Number.NaN)
· ─────────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array(NaN)
· ──────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array(foo >>> bar)
· ──────────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array(foo >>>= bar)
· ───────────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array(++bar.length)
· ───────────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array(bar.length++)
· ───────────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array(foo = bar.length)
· ───────────────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array("0xff")
· ─────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array(Math.NON_EXISTS_PROPERTY)
· ───────────────────────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array(Math.NON_EXISTS_METHOD(foo))
· ──────────────────────────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array(Math[min](foo, bar))
· ──────────────────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array(Number[MAX_SAFE_INTEGER])
· ───────────────────────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array(new Number(foo))
· ──────────────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ const foo = 1; new Array(foo + "2")
· ────────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array(foo - 2n)
· ───────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array(foo -= 2n)
· ────────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array(foo instanceof 1)
· ───────────────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array(foo || 1)
· ───────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array(foo ||= 1)
· ────────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array(foo ? 1n : 2)
· ───────────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array((1, 2n))
· ──────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array(-foo)
· ───────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array(~foo)
· ───────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array(typeof 1)
· ───────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ const truthy = "truthy"; new Array(truthy ? foo : 1)
· ───────────────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ const falsy = !"truthy"; new Array(falsy ? 1 : foo)
· ──────────────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array(unknown ? foo : 1)
· ────────────────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array(unknown ? 1 : foo)
· ────────────────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ new Array(++foo)
· ────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ const array = new Array(foo)
· ──────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.
⚠ eslint-plugin-unicorn(no-new-array): Do not use `new Array()`.
╭─[no_new_array.tsx:1:1]
1 │ const array = new Array(length)
· ─────────────────
╰────
help: If the argument is the array's length, consider using `Array.from({ length: n })` instead. If the argument is the only element, use `[element]` instead.