mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 12:19:15 +00:00
feat(linter): add rule no-undefined (#4041)
Implementing rule https://eslint.org/docs/latest/rules/no-undefined This is my first time contributing here, I wanted to started with a simple rule before contributing more. related to #479
This commit is contained in:
parent
bf04dee861
commit
6876490baa
3 changed files with 394 additions and 0 deletions
|
|
@ -96,6 +96,7 @@ mod eslint {
|
|||
pub mod no_ternary;
|
||||
pub mod no_this_before_super;
|
||||
pub mod no_undef;
|
||||
pub mod no_undefined;
|
||||
pub mod no_unreachable;
|
||||
pub mod no_unsafe_finally;
|
||||
pub mod no_unsafe_negation;
|
||||
|
|
@ -495,6 +496,7 @@ oxc_macros::declare_all_lint_rules! {
|
|||
eslint::no_shadow_restricted_names,
|
||||
eslint::no_sparse_arrays,
|
||||
eslint::no_undef,
|
||||
eslint::no_undefined,
|
||||
eslint::no_unreachable,
|
||||
eslint::no_unsafe_finally,
|
||||
eslint::no_unsafe_negation,
|
||||
|
|
|
|||
145
crates/oxc_linter/src/rules/eslint/no_undefined.rs
Normal file
145
crates/oxc_linter/src/rules/eslint/no_undefined.rs
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
use oxc_ast::AstKind;
|
||||
use oxc_diagnostics::OxcDiagnostic;
|
||||
use oxc_macros::declare_oxc_lint;
|
||||
use oxc_span::Span;
|
||||
|
||||
use crate::{context::LintContext, rule::Rule, AstNode};
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct NoUndefined;
|
||||
|
||||
fn no_undefined_diagnostic(span0: Span) -> OxcDiagnostic {
|
||||
OxcDiagnostic::warn("eslint(no-undefined): Disallow the use of `undefined` as an identifier")
|
||||
.with_help("Unexpected use of undefined.")
|
||||
.with_label(span0)
|
||||
}
|
||||
|
||||
declare_oxc_lint!(
|
||||
/// ### What it does
|
||||
/// Disallow the use of `undefined` as an identifier
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
///
|
||||
///
|
||||
/// ### Example of bad code
|
||||
/// ```javascript
|
||||
///
|
||||
/// var foo = undefined;
|
||||
///
|
||||
/// var undefined = "foo";
|
||||
///
|
||||
/// if (foo === undefined) {
|
||||
/// ...
|
||||
/// }
|
||||
///
|
||||
/// function baz(undefined) {
|
||||
/// ...
|
||||
/// }
|
||||
///
|
||||
/// bar(undefined, "lorem");
|
||||
///
|
||||
/// ```
|
||||
///
|
||||
/// ### Example of good code
|
||||
/// ```javascript
|
||||
/// var foo = void 0;
|
||||
///
|
||||
/// var Undefined = "foo";
|
||||
///
|
||||
/// if (typeof foo === "undefined") {
|
||||
/// ...
|
||||
/// }
|
||||
///
|
||||
/// global.undefined = "foo";
|
||||
///
|
||||
/// bar(void 0, "lorem");
|
||||
/// ```
|
||||
///
|
||||
NoUndefined,
|
||||
restriction,
|
||||
);
|
||||
|
||||
fn diagnostic_undefined_keyword(name: &str, span0: Span, ctx: &LintContext) {
|
||||
if name == "undefined" {
|
||||
ctx.diagnostic(no_undefined_diagnostic(span0));
|
||||
}
|
||||
}
|
||||
|
||||
impl Rule for NoUndefined {
|
||||
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
|
||||
match node.kind() {
|
||||
AstKind::IdentifierReference(ident) => {
|
||||
diagnostic_undefined_keyword(ident.name.as_str(), ident.span, ctx);
|
||||
}
|
||||
AstKind::BindingIdentifier(ident) => {
|
||||
diagnostic_undefined_keyword(ident.name.as_str(), ident.span, ctx);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
use crate::tester::Tester;
|
||||
|
||||
let pass = vec![
|
||||
"void 0",
|
||||
"void!0",
|
||||
"void-0",
|
||||
"void+0",
|
||||
"null",
|
||||
"undefine",
|
||||
"a.undefined",
|
||||
"this.undefined",
|
||||
"global['undefined']",
|
||||
"({ undefined: bar })",
|
||||
"({ undefined: bar } = foo)",
|
||||
"({ undefined() {} })",
|
||||
"class Foo { undefined() {} }",
|
||||
"(class { undefined() {} })",
|
||||
"import { undefined as a } from 'foo'", // ES6_MODULE,
|
||||
"export { undefined } from 'foo'", // ES6_MODULE,
|
||||
"export { undefined as a } from 'foo'", // ES6_MODULE,
|
||||
"export { a as undefined } from 'foo'", // ES6_MODULE
|
||||
];
|
||||
|
||||
let fail = vec![
|
||||
"undefined",
|
||||
"undefined.a",
|
||||
"a[undefined]",
|
||||
"undefined[0]",
|
||||
"f(undefined)",
|
||||
"function f(undefined) {}",
|
||||
"function f() { var undefined; }",
|
||||
"function f() { undefined = true; }",
|
||||
"var undefined;",
|
||||
"try {} catch(undefined) {}",
|
||||
"function undefined() {}",
|
||||
"(function undefined(){}())",
|
||||
"var foo = function undefined() {}",
|
||||
"foo = function undefined() {}",
|
||||
"undefined = true",
|
||||
"var undefined = true",
|
||||
"({ undefined })",
|
||||
"({ [undefined]: foo })",
|
||||
"({ bar: undefined })",
|
||||
"({ bar: undefined } = foo)",
|
||||
"var { undefined } = foo",
|
||||
"var { bar: undefined } = foo",
|
||||
"({ undefined: function undefined() {} })",
|
||||
"({ foo: function undefined() {} })",
|
||||
"class Foo { [undefined]() {} }",
|
||||
"(class { [undefined]() {} })",
|
||||
"var undefined = true; undefined = false;",
|
||||
"import undefined from 'foo'", // ES6_MODULE,
|
||||
"import * as undefined from 'foo'", // ES6_MODULE,
|
||||
"import { undefined } from 'foo'", // ES6_MODULE,
|
||||
"import { a as undefined } from 'foo'", // ES6_MODULE,
|
||||
"let a = [b, ...undefined]",
|
||||
"[a, ...undefined] = b",
|
||||
"[a = undefined] = b",
|
||||
];
|
||||
|
||||
Tester::new(NoUndefined::NAME, pass, fail).test_and_snapshot();
|
||||
}
|
||||
247
crates/oxc_linter/src/snapshots/no_undefined.snap
Normal file
247
crates/oxc_linter/src/snapshots/no_undefined.snap
Normal file
|
|
@ -0,0 +1,247 @@
|
|||
---
|
||||
source: crates/oxc_linter/src/tester.rs
|
||||
---
|
||||
⚠ eslint(no-undefined): Disallow the use of `undefined` as an identifier
|
||||
╭─[no_undefined.tsx:1:1]
|
||||
1 │ undefined
|
||||
· ─────────
|
||||
╰────
|
||||
help: Unexpected use of undefined.
|
||||
|
||||
⚠ eslint(no-undefined): Disallow the use of `undefined` as an identifier
|
||||
╭─[no_undefined.tsx:1:1]
|
||||
1 │ undefined.a
|
||||
· ─────────
|
||||
╰────
|
||||
help: Unexpected use of undefined.
|
||||
|
||||
⚠ eslint(no-undefined): Disallow the use of `undefined` as an identifier
|
||||
╭─[no_undefined.tsx:1:3]
|
||||
1 │ a[undefined]
|
||||
· ─────────
|
||||
╰────
|
||||
help: Unexpected use of undefined.
|
||||
|
||||
⚠ eslint(no-undefined): Disallow the use of `undefined` as an identifier
|
||||
╭─[no_undefined.tsx:1:1]
|
||||
1 │ undefined[0]
|
||||
· ─────────
|
||||
╰────
|
||||
help: Unexpected use of undefined.
|
||||
|
||||
⚠ eslint(no-undefined): Disallow the use of `undefined` as an identifier
|
||||
╭─[no_undefined.tsx:1:3]
|
||||
1 │ f(undefined)
|
||||
· ─────────
|
||||
╰────
|
||||
help: Unexpected use of undefined.
|
||||
|
||||
⚠ eslint(no-undefined): Disallow the use of `undefined` as an identifier
|
||||
╭─[no_undefined.tsx:1:12]
|
||||
1 │ function f(undefined) {}
|
||||
· ─────────
|
||||
╰────
|
||||
help: Unexpected use of undefined.
|
||||
|
||||
⚠ eslint(no-undefined): Disallow the use of `undefined` as an identifier
|
||||
╭─[no_undefined.tsx:1:20]
|
||||
1 │ function f() { var undefined; }
|
||||
· ─────────
|
||||
╰────
|
||||
help: Unexpected use of undefined.
|
||||
|
||||
⚠ eslint(no-undefined): Disallow the use of `undefined` as an identifier
|
||||
╭─[no_undefined.tsx:1:16]
|
||||
1 │ function f() { undefined = true; }
|
||||
· ─────────
|
||||
╰────
|
||||
help: Unexpected use of undefined.
|
||||
|
||||
⚠ eslint(no-undefined): Disallow the use of `undefined` as an identifier
|
||||
╭─[no_undefined.tsx:1:5]
|
||||
1 │ var undefined;
|
||||
· ─────────
|
||||
╰────
|
||||
help: Unexpected use of undefined.
|
||||
|
||||
⚠ eslint(no-undefined): Disallow the use of `undefined` as an identifier
|
||||
╭─[no_undefined.tsx:1:14]
|
||||
1 │ try {} catch(undefined) {}
|
||||
· ─────────
|
||||
╰────
|
||||
help: Unexpected use of undefined.
|
||||
|
||||
⚠ eslint(no-undefined): Disallow the use of `undefined` as an identifier
|
||||
╭─[no_undefined.tsx:1:10]
|
||||
1 │ function undefined() {}
|
||||
· ─────────
|
||||
╰────
|
||||
help: Unexpected use of undefined.
|
||||
|
||||
⚠ eslint(no-undefined): Disallow the use of `undefined` as an identifier
|
||||
╭─[no_undefined.tsx:1:11]
|
||||
1 │ (function undefined(){}())
|
||||
· ─────────
|
||||
╰────
|
||||
help: Unexpected use of undefined.
|
||||
|
||||
⚠ eslint(no-undefined): Disallow the use of `undefined` as an identifier
|
||||
╭─[no_undefined.tsx:1:20]
|
||||
1 │ var foo = function undefined() {}
|
||||
· ─────────
|
||||
╰────
|
||||
help: Unexpected use of undefined.
|
||||
|
||||
⚠ eslint(no-undefined): Disallow the use of `undefined` as an identifier
|
||||
╭─[no_undefined.tsx:1:16]
|
||||
1 │ foo = function undefined() {}
|
||||
· ─────────
|
||||
╰────
|
||||
help: Unexpected use of undefined.
|
||||
|
||||
⚠ eslint(no-undefined): Disallow the use of `undefined` as an identifier
|
||||
╭─[no_undefined.tsx:1:1]
|
||||
1 │ undefined = true
|
||||
· ─────────
|
||||
╰────
|
||||
help: Unexpected use of undefined.
|
||||
|
||||
⚠ eslint(no-undefined): Disallow the use of `undefined` as an identifier
|
||||
╭─[no_undefined.tsx:1:5]
|
||||
1 │ var undefined = true
|
||||
· ─────────
|
||||
╰────
|
||||
help: Unexpected use of undefined.
|
||||
|
||||
⚠ eslint(no-undefined): Disallow the use of `undefined` as an identifier
|
||||
╭─[no_undefined.tsx:1:4]
|
||||
1 │ ({ undefined })
|
||||
· ─────────
|
||||
╰────
|
||||
help: Unexpected use of undefined.
|
||||
|
||||
⚠ eslint(no-undefined): Disallow the use of `undefined` as an identifier
|
||||
╭─[no_undefined.tsx:1:5]
|
||||
1 │ ({ [undefined]: foo })
|
||||
· ─────────
|
||||
╰────
|
||||
help: Unexpected use of undefined.
|
||||
|
||||
⚠ eslint(no-undefined): Disallow the use of `undefined` as an identifier
|
||||
╭─[no_undefined.tsx:1:9]
|
||||
1 │ ({ bar: undefined })
|
||||
· ─────────
|
||||
╰────
|
||||
help: Unexpected use of undefined.
|
||||
|
||||
⚠ eslint(no-undefined): Disallow the use of `undefined` as an identifier
|
||||
╭─[no_undefined.tsx:1:9]
|
||||
1 │ ({ bar: undefined } = foo)
|
||||
· ─────────
|
||||
╰────
|
||||
help: Unexpected use of undefined.
|
||||
|
||||
⚠ eslint(no-undefined): Disallow the use of `undefined` as an identifier
|
||||
╭─[no_undefined.tsx:1:7]
|
||||
1 │ var { undefined } = foo
|
||||
· ─────────
|
||||
╰────
|
||||
help: Unexpected use of undefined.
|
||||
|
||||
⚠ eslint(no-undefined): Disallow the use of `undefined` as an identifier
|
||||
╭─[no_undefined.tsx:1:12]
|
||||
1 │ var { bar: undefined } = foo
|
||||
· ─────────
|
||||
╰────
|
||||
help: Unexpected use of undefined.
|
||||
|
||||
⚠ eslint(no-undefined): Disallow the use of `undefined` as an identifier
|
||||
╭─[no_undefined.tsx:1:24]
|
||||
1 │ ({ undefined: function undefined() {} })
|
||||
· ─────────
|
||||
╰────
|
||||
help: Unexpected use of undefined.
|
||||
|
||||
⚠ eslint(no-undefined): Disallow the use of `undefined` as an identifier
|
||||
╭─[no_undefined.tsx:1:18]
|
||||
1 │ ({ foo: function undefined() {} })
|
||||
· ─────────
|
||||
╰────
|
||||
help: Unexpected use of undefined.
|
||||
|
||||
⚠ eslint(no-undefined): Disallow the use of `undefined` as an identifier
|
||||
╭─[no_undefined.tsx:1:14]
|
||||
1 │ class Foo { [undefined]() {} }
|
||||
· ─────────
|
||||
╰────
|
||||
help: Unexpected use of undefined.
|
||||
|
||||
⚠ eslint(no-undefined): Disallow the use of `undefined` as an identifier
|
||||
╭─[no_undefined.tsx:1:11]
|
||||
1 │ (class { [undefined]() {} })
|
||||
· ─────────
|
||||
╰────
|
||||
help: Unexpected use of undefined.
|
||||
|
||||
⚠ eslint(no-undefined): Disallow the use of `undefined` as an identifier
|
||||
╭─[no_undefined.tsx:1:5]
|
||||
1 │ var undefined = true; undefined = false;
|
||||
· ─────────
|
||||
╰────
|
||||
help: Unexpected use of undefined.
|
||||
|
||||
⚠ eslint(no-undefined): Disallow the use of `undefined` as an identifier
|
||||
╭─[no_undefined.tsx:1:23]
|
||||
1 │ var undefined = true; undefined = false;
|
||||
· ─────────
|
||||
╰────
|
||||
help: Unexpected use of undefined.
|
||||
|
||||
⚠ eslint(no-undefined): Disallow the use of `undefined` as an identifier
|
||||
╭─[no_undefined.tsx:1:8]
|
||||
1 │ import undefined from 'foo'
|
||||
· ─────────
|
||||
╰────
|
||||
help: Unexpected use of undefined.
|
||||
|
||||
⚠ eslint(no-undefined): Disallow the use of `undefined` as an identifier
|
||||
╭─[no_undefined.tsx:1:13]
|
||||
1 │ import * as undefined from 'foo'
|
||||
· ─────────
|
||||
╰────
|
||||
help: Unexpected use of undefined.
|
||||
|
||||
⚠ eslint(no-undefined): Disallow the use of `undefined` as an identifier
|
||||
╭─[no_undefined.tsx:1:10]
|
||||
1 │ import { undefined } from 'foo'
|
||||
· ─────────
|
||||
╰────
|
||||
help: Unexpected use of undefined.
|
||||
|
||||
⚠ eslint(no-undefined): Disallow the use of `undefined` as an identifier
|
||||
╭─[no_undefined.tsx:1:15]
|
||||
1 │ import { a as undefined } from 'foo'
|
||||
· ─────────
|
||||
╰────
|
||||
help: Unexpected use of undefined.
|
||||
|
||||
⚠ eslint(no-undefined): Disallow the use of `undefined` as an identifier
|
||||
╭─[no_undefined.tsx:1:16]
|
||||
1 │ let a = [b, ...undefined]
|
||||
· ─────────
|
||||
╰────
|
||||
help: Unexpected use of undefined.
|
||||
|
||||
⚠ eslint(no-undefined): Disallow the use of `undefined` as an identifier
|
||||
╭─[no_undefined.tsx:1:8]
|
||||
1 │ [a, ...undefined] = b
|
||||
· ─────────
|
||||
╰────
|
||||
help: Unexpected use of undefined.
|
||||
|
||||
⚠ eslint(no-undefined): Disallow the use of `undefined` as an identifier
|
||||
╭─[no_undefined.tsx:1:6]
|
||||
1 │ [a = undefined] = b
|
||||
· ─────────
|
||||
╰────
|
||||
help: Unexpected use of undefined.
|
||||
Loading…
Reference in a new issue