-
-
Notifications
You must be signed in to change notification settings - Fork 502
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(linter): implement eslint-plugin-unicorn/no-instanceof-array (#752)
implement [eslint-plugin-unicorn/no-instanceof-array](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-instanceof-array.md). Related issue: #684
- Loading branch information
Showing
6 changed files
with
185 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
107 changes: 107 additions & 0 deletions
107
crates/oxc_linter/src/rules/unicorn/no_instanceof_array.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
use oxc_ast::ast::Expression; | ||
use oxc_ast::AstKind; | ||
use oxc_diagnostics::{ | ||
miette::{self, Diagnostic}, | ||
thiserror::Error, | ||
}; | ||
use oxc_formatter::Gen; | ||
use oxc_macros::declare_oxc_lint; | ||
use oxc_span::Span; | ||
use oxc_syntax::operator::BinaryOperator; | ||
|
||
use crate::{context::LintContext, fixer::Fix, rule::Rule, AstNode}; | ||
|
||
#[derive(Debug, Error, Diagnostic)] | ||
#[error("Use `Array.isArray()` instead of `instanceof Array`.")] | ||
#[diagnostic(severity(warning), help("The instanceof Array check doesn't work across realms/contexts, for example, frames/windows in browsers or the vm module in Node.js."))] | ||
struct NoInstanceofArrayDiagnostic(#[label] pub Span); | ||
|
||
#[derive(Debug, Default, Clone)] | ||
pub struct NoInstanceofArray; | ||
|
||
declare_oxc_lint!( | ||
/// ### What it does | ||
/// Require `Array.isArray()` instead of `instanceof Array`. | ||
/// | ||
/// ### Why is this bad? | ||
/// The instanceof Array check doesn't work across realms/contexts, for example, frames/windows in browsers or the vm module in Node.js. | ||
/// | ||
/// ### Example | ||
/// ```javascript | ||
/// array instanceof Array; | ||
/// [1,2,3] instanceof Array; | ||
/// ``` | ||
NoInstanceofArray, | ||
correctness | ||
); | ||
|
||
impl Rule for NoInstanceofArray { | ||
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { | ||
let AstKind::BinaryExpression(expr) = node.kind() else { return }; | ||
if expr.operator != BinaryOperator::Instanceof { | ||
return; | ||
} | ||
|
||
match &expr.right { | ||
Expression::Identifier(identifier) if identifier.name == "Array" => { | ||
ctx.diagnostic_with_fix(NoInstanceofArrayDiagnostic(expr.span), || { | ||
let modified_code = { | ||
let mut formatter = ctx.formatter(); | ||
formatter.print_str(b"Array.isArray("); | ||
expr.left.gen(&mut formatter); | ||
formatter.print(b')'); | ||
formatter.into_code() | ||
}; | ||
Fix::new(modified_code, expr.span) | ||
}); | ||
} | ||
_ => {} | ||
} | ||
} | ||
} | ||
|
||
#[test] | ||
fn test() { | ||
use crate::tester::Tester; | ||
|
||
let pass = vec![ | ||
("Array.isArray(arr)", None), | ||
("arr instanceof Object", None), | ||
("arr instanceof array", None), | ||
("a instanceof 'array'", None), | ||
("a instanceof ArrayA", None), | ||
("a.x[2] instanceof foo()", None), | ||
("Array.isArray([1,2,3]) === true", None), | ||
("\"arr instanceof Array\"", None), | ||
]; | ||
|
||
let fail = vec![ | ||
("arr instanceof Array", None), | ||
("[] instanceof Array", None), | ||
("[1,2,3] instanceof Array === true", None), | ||
("fun.call(1, 2, 3) instanceof Array", None), | ||
("obj.arr instanceof Array", None), | ||
("foo.bar[2] instanceof Array", None), | ||
("(0, array) instanceof Array", None), | ||
("function foo(){return [] instanceof Array}", None), | ||
]; | ||
|
||
let fix = vec![ | ||
("arr instanceof Array", "Array.isArray(arr)", None), | ||
("[] instanceof Array", "Array.isArray([])", None), | ||
("[1,2,3] instanceof Array === true", "Array.isArray([1, 2, 3]) === true", None), | ||
("fun.call(1, 2, 3) instanceof Array", "Array.isArray(fun.call(1, 2, 3))", None), | ||
("obj.arr instanceof Array", "Array.isArray(obj.arr)", None), | ||
("foo.bar[2] instanceof Array", "Array.isArray(foo.bar[2])", None), | ||
("(0, array) instanceof Array", "Array.isArray((0, array))", None), | ||
( | ||
"function foo(){return [] instanceof Array}", | ||
"function foo(){return Array.isArray([])}", | ||
None, | ||
), | ||
]; | ||
|
||
let mut tester = Tester::new(NoInstanceofArray::NAME, pass, fail); | ||
tester.test_and_snapshot(); | ||
tester.test_fix(fix); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
--- | ||
source: crates/oxc_linter/src/tester.rs | ||
assertion_line: 80 | ||
expression: no_instanceof_array | ||
--- | ||
⚠ Use `Array.isArray()` instead of `instanceof Array`. | ||
╭─[no_instanceof_array.tsx:1:1] | ||
1 │ arr instanceof Array | ||
· ──────────────────── | ||
╰──── | ||
help: The instanceof Array check doesn't work across realms/contexts, for example, frames/windows in browsers or the vm module in Node.js. | ||
|
||
⚠ Use `Array.isArray()` instead of `instanceof Array`. | ||
╭─[no_instanceof_array.tsx:1:1] | ||
1 │ [] instanceof Array | ||
· ─────────────────── | ||
╰──── | ||
help: The instanceof Array check doesn't work across realms/contexts, for example, frames/windows in browsers or the vm module in Node.js. | ||
|
||
⚠ Use `Array.isArray()` instead of `instanceof Array`. | ||
╭─[no_instanceof_array.tsx:1:1] | ||
1 │ [1,2,3] instanceof Array === true | ||
· ──────────────────────── | ||
╰──── | ||
help: The instanceof Array check doesn't work across realms/contexts, for example, frames/windows in browsers or the vm module in Node.js. | ||
|
||
⚠ Use `Array.isArray()` instead of `instanceof Array`. | ||
╭─[no_instanceof_array.tsx:1:1] | ||
1 │ fun.call(1, 2, 3) instanceof Array | ||
· ────────────────────────────────── | ||
╰──── | ||
help: The instanceof Array check doesn't work across realms/contexts, for example, frames/windows in browsers or the vm module in Node.js. | ||
|
||
⚠ Use `Array.isArray()` instead of `instanceof Array`. | ||
╭─[no_instanceof_array.tsx:1:1] | ||
1 │ obj.arr instanceof Array | ||
· ──────────────────────── | ||
╰──── | ||
help: The instanceof Array check doesn't work across realms/contexts, for example, frames/windows in browsers or the vm module in Node.js. | ||
|
||
⚠ Use `Array.isArray()` instead of `instanceof Array`. | ||
╭─[no_instanceof_array.tsx:1:1] | ||
1 │ foo.bar[2] instanceof Array | ||
· ─────────────────────────── | ||
╰──── | ||
help: The instanceof Array check doesn't work across realms/contexts, for example, frames/windows in browsers or the vm module in Node.js. | ||
|
||
⚠ Use `Array.isArray()` instead of `instanceof Array`. | ||
╭─[no_instanceof_array.tsx:1:1] | ||
1 │ (0, array) instanceof Array | ||
· ─────────────────────────── | ||
╰──── | ||
help: The instanceof Array check doesn't work across realms/contexts, for example, frames/windows in browsers or the vm module in Node.js. | ||
|
||
⚠ Use `Array.isArray()` instead of `instanceof Array`. | ||
╭─[no_instanceof_array.tsx:1:1] | ||
1 │ function foo(){return [] instanceof Array} | ||
· ─────────────────── | ||
╰──── | ||
help: The instanceof Array check doesn't work across realms/contexts, for example, frames/windows in browsers or the vm module in Node.js. | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters