mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +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_ternary;
|
||||||
pub mod no_this_before_super;
|
pub mod no_this_before_super;
|
||||||
pub mod no_undef;
|
pub mod no_undef;
|
||||||
|
pub mod no_undefined;
|
||||||
pub mod no_unreachable;
|
pub mod no_unreachable;
|
||||||
pub mod no_unsafe_finally;
|
pub mod no_unsafe_finally;
|
||||||
pub mod no_unsafe_negation;
|
pub mod no_unsafe_negation;
|
||||||
|
|
@ -495,6 +496,7 @@ oxc_macros::declare_all_lint_rules! {
|
||||||
eslint::no_shadow_restricted_names,
|
eslint::no_shadow_restricted_names,
|
||||||
eslint::no_sparse_arrays,
|
eslint::no_sparse_arrays,
|
||||||
eslint::no_undef,
|
eslint::no_undef,
|
||||||
|
eslint::no_undefined,
|
||||||
eslint::no_unreachable,
|
eslint::no_unreachable,
|
||||||
eslint::no_unsafe_finally,
|
eslint::no_unsafe_finally,
|
||||||
eslint::no_unsafe_negation,
|
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