Skip to content

Commit 6876490

Browse files
authoredJul 5, 2024··
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
1 parent bf04dee commit 6876490

File tree

3 files changed

+394
-0
lines changed

3 files changed

+394
-0
lines changed
 

‎crates/oxc_linter/src/rules.rs

+2
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ mod eslint {
9696
pub mod no_ternary;
9797
pub mod no_this_before_super;
9898
pub mod no_undef;
99+
pub mod no_undefined;
99100
pub mod no_unreachable;
100101
pub mod no_unsafe_finally;
101102
pub mod no_unsafe_negation;
@@ -495,6 +496,7 @@ oxc_macros::declare_all_lint_rules! {
495496
eslint::no_shadow_restricted_names,
496497
eslint::no_sparse_arrays,
497498
eslint::no_undef,
499+
eslint::no_undefined,
498500
eslint::no_unreachable,
499501
eslint::no_unsafe_finally,
500502
eslint::no_unsafe_negation,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
use oxc_ast::AstKind;
2+
use oxc_diagnostics::OxcDiagnostic;
3+
use oxc_macros::declare_oxc_lint;
4+
use oxc_span::Span;
5+
6+
use crate::{context::LintContext, rule::Rule, AstNode};
7+
8+
#[derive(Debug, Default, Clone)]
9+
pub struct NoUndefined;
10+
11+
fn no_undefined_diagnostic(span0: Span) -> OxcDiagnostic {
12+
OxcDiagnostic::warn("eslint(no-undefined): Disallow the use of `undefined` as an identifier")
13+
.with_help("Unexpected use of undefined.")
14+
.with_label(span0)
15+
}
16+
17+
declare_oxc_lint!(
18+
/// ### What it does
19+
/// Disallow the use of `undefined` as an identifier
20+
///
21+
/// ### Why is this bad?
22+
///
23+
///
24+
/// ### Example of bad code
25+
/// ```javascript
26+
///
27+
/// var foo = undefined;
28+
///
29+
/// var undefined = "foo";
30+
///
31+
/// if (foo === undefined) {
32+
/// ...
33+
/// }
34+
///
35+
/// function baz(undefined) {
36+
/// ...
37+
/// }
38+
///
39+
/// bar(undefined, "lorem");
40+
///
41+
/// ```
42+
///
43+
/// ### Example of good code
44+
/// ```javascript
45+
/// var foo = void 0;
46+
///
47+
/// var Undefined = "foo";
48+
///
49+
/// if (typeof foo === "undefined") {
50+
/// ...
51+
/// }
52+
///
53+
/// global.undefined = "foo";
54+
///
55+
/// bar(void 0, "lorem");
56+
/// ```
57+
///
58+
NoUndefined,
59+
restriction,
60+
);
61+
62+
fn diagnostic_undefined_keyword(name: &str, span0: Span, ctx: &LintContext) {
63+
if name == "undefined" {
64+
ctx.diagnostic(no_undefined_diagnostic(span0));
65+
}
66+
}
67+
68+
impl Rule for NoUndefined {
69+
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
70+
match node.kind() {
71+
AstKind::IdentifierReference(ident) => {
72+
diagnostic_undefined_keyword(ident.name.as_str(), ident.span, ctx);
73+
}
74+
AstKind::BindingIdentifier(ident) => {
75+
diagnostic_undefined_keyword(ident.name.as_str(), ident.span, ctx);
76+
}
77+
_ => {}
78+
}
79+
}
80+
}
81+
82+
#[test]
83+
fn test() {
84+
use crate::tester::Tester;
85+
86+
let pass = vec![
87+
"void 0",
88+
"void!0",
89+
"void-0",
90+
"void+0",
91+
"null",
92+
"undefine",
93+
"a.undefined",
94+
"this.undefined",
95+
"global['undefined']",
96+
"({ undefined: bar })",
97+
"({ undefined: bar } = foo)",
98+
"({ undefined() {} })",
99+
"class Foo { undefined() {} }",
100+
"(class { undefined() {} })",
101+
"import { undefined as a } from 'foo'", // ES6_MODULE,
102+
"export { undefined } from 'foo'", // ES6_MODULE,
103+
"export { undefined as a } from 'foo'", // ES6_MODULE,
104+
"export { a as undefined } from 'foo'", // ES6_MODULE
105+
];
106+
107+
let fail = vec![
108+
"undefined",
109+
"undefined.a",
110+
"a[undefined]",
111+
"undefined[0]",
112+
"f(undefined)",
113+
"function f(undefined) {}",
114+
"function f() { var undefined; }",
115+
"function f() { undefined = true; }",
116+
"var undefined;",
117+
"try {} catch(undefined) {}",
118+
"function undefined() {}",
119+
"(function undefined(){}())",
120+
"var foo = function undefined() {}",
121+
"foo = function undefined() {}",
122+
"undefined = true",
123+
"var undefined = true",
124+
"({ undefined })",
125+
"({ [undefined]: foo })",
126+
"({ bar: undefined })",
127+
"({ bar: undefined } = foo)",
128+
"var { undefined } = foo",
129+
"var { bar: undefined } = foo",
130+
"({ undefined: function undefined() {} })",
131+
"({ foo: function undefined() {} })",
132+
"class Foo { [undefined]() {} }",
133+
"(class { [undefined]() {} })",
134+
"var undefined = true; undefined = false;",
135+
"import undefined from 'foo'", // ES6_MODULE,
136+
"import * as undefined from 'foo'", // ES6_MODULE,
137+
"import { undefined } from 'foo'", // ES6_MODULE,
138+
"import { a as undefined } from 'foo'", // ES6_MODULE,
139+
"let a = [b, ...undefined]",
140+
"[a, ...undefined] = b",
141+
"[a = undefined] = b",
142+
];
143+
144+
Tester::new(NoUndefined::NAME, pass, fail).test_and_snapshot();
145+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
---
2+
source: crates/oxc_linter/src/tester.rs
3+
---
4+
eslint(no-undefined): Disallow the use of `undefined` as an identifier
5+
╭─[no_undefined.tsx:1:1]
6+
1undefined
7+
· ─────────
8+
╰────
9+
help: Unexpected use of undefined.
10+
11+
eslint(no-undefined): Disallow the use of `undefined` as an identifier
12+
╭─[no_undefined.tsx:1:1]
13+
1undefined.a
14+
· ─────────
15+
╰────
16+
help: Unexpected use of undefined.
17+
18+
eslint(no-undefined): Disallow the use of `undefined` as an identifier
19+
╭─[no_undefined.tsx:1:3]
20+
1a[undefined]
21+
· ─────────
22+
╰────
23+
help: Unexpected use of undefined.
24+
25+
eslint(no-undefined): Disallow the use of `undefined` as an identifier
26+
╭─[no_undefined.tsx:1:1]
27+
1undefined[0]
28+
· ─────────
29+
╰────
30+
help: Unexpected use of undefined.
31+
32+
eslint(no-undefined): Disallow the use of `undefined` as an identifier
33+
╭─[no_undefined.tsx:1:3]
34+
1f(undefined)
35+
· ─────────
36+
╰────
37+
help: Unexpected use of undefined.
38+
39+
eslint(no-undefined): Disallow the use of `undefined` as an identifier
40+
╭─[no_undefined.tsx:1:12]
41+
1function f(undefined) {}
42+
· ─────────
43+
╰────
44+
help: Unexpected use of undefined.
45+
46+
eslint(no-undefined): Disallow the use of `undefined` as an identifier
47+
╭─[no_undefined.tsx:1:20]
48+
1function f() { var undefined; }
49+
· ─────────
50+
╰────
51+
help: Unexpected use of undefined.
52+
53+
eslint(no-undefined): Disallow the use of `undefined` as an identifier
54+
╭─[no_undefined.tsx:1:16]
55+
1function f() { undefined = true; }
56+
· ─────────
57+
╰────
58+
help: Unexpected use of undefined.
59+
60+
eslint(no-undefined): Disallow the use of `undefined` as an identifier
61+
╭─[no_undefined.tsx:1:5]
62+
1var undefined;
63+
· ─────────
64+
╰────
65+
help: Unexpected use of undefined.
66+
67+
eslint(no-undefined): Disallow the use of `undefined` as an identifier
68+
╭─[no_undefined.tsx:1:14]
69+
1try {} catch(undefined) {}
70+
· ─────────
71+
╰────
72+
help: Unexpected use of undefined.
73+
74+
eslint(no-undefined): Disallow the use of `undefined` as an identifier
75+
╭─[no_undefined.tsx:1:10]
76+
1function undefined() {}
77+
· ─────────
78+
╰────
79+
help: Unexpected use of undefined.
80+
81+
eslint(no-undefined): Disallow the use of `undefined` as an identifier
82+
╭─[no_undefined.tsx:1:11]
83+
1 │ (function undefined(){}())
84+
· ─────────
85+
╰────
86+
help: Unexpected use of undefined.
87+
88+
eslint(no-undefined): Disallow the use of `undefined` as an identifier
89+
╭─[no_undefined.tsx:1:20]
90+
1var foo = function undefined() {}
91+
· ─────────
92+
╰────
93+
help: Unexpected use of undefined.
94+
95+
eslint(no-undefined): Disallow the use of `undefined` as an identifier
96+
╭─[no_undefined.tsx:1:16]
97+
1foo = function undefined() {}
98+
· ─────────
99+
╰────
100+
help: Unexpected use of undefined.
101+
102+
eslint(no-undefined): Disallow the use of `undefined` as an identifier
103+
╭─[no_undefined.tsx:1:1]
104+
1undefined = true
105+
· ─────────
106+
╰────
107+
help: Unexpected use of undefined.
108+
109+
eslint(no-undefined): Disallow the use of `undefined` as an identifier
110+
╭─[no_undefined.tsx:1:5]
111+
1var undefined = true
112+
· ─────────
113+
╰────
114+
help: Unexpected use of undefined.
115+
116+
eslint(no-undefined): Disallow the use of `undefined` as an identifier
117+
╭─[no_undefined.tsx:1:4]
118+
1 │ ({ undefined })
119+
· ─────────
120+
╰────
121+
help: Unexpected use of undefined.
122+
123+
eslint(no-undefined): Disallow the use of `undefined` as an identifier
124+
╭─[no_undefined.tsx:1:5]
125+
1 │ ({ [undefined]: foo })
126+
· ─────────
127+
╰────
128+
help: Unexpected use of undefined.
129+
130+
eslint(no-undefined): Disallow the use of `undefined` as an identifier
131+
╭─[no_undefined.tsx:1:9]
132+
1 │ ({ bar: undefined })
133+
· ─────────
134+
╰────
135+
help: Unexpected use of undefined.
136+
137+
eslint(no-undefined): Disallow the use of `undefined` as an identifier
138+
╭─[no_undefined.tsx:1:9]
139+
1 │ ({ bar: undefined } = foo)
140+
· ─────────
141+
╰────
142+
help: Unexpected use of undefined.
143+
144+
eslint(no-undefined): Disallow the use of `undefined` as an identifier
145+
╭─[no_undefined.tsx:1:7]
146+
1var { undefined } = foo
147+
· ─────────
148+
╰────
149+
help: Unexpected use of undefined.
150+
151+
eslint(no-undefined): Disallow the use of `undefined` as an identifier
152+
╭─[no_undefined.tsx:1:12]
153+
1var { bar: undefined } = foo
154+
· ─────────
155+
╰────
156+
help: Unexpected use of undefined.
157+
158+
eslint(no-undefined): Disallow the use of `undefined` as an identifier
159+
╭─[no_undefined.tsx:1:24]
160+
1 │ ({ undefined: function undefined() {} })
161+
· ─────────
162+
╰────
163+
help: Unexpected use of undefined.
164+
165+
eslint(no-undefined): Disallow the use of `undefined` as an identifier
166+
╭─[no_undefined.tsx:1:18]
167+
1 │ ({ foo: function undefined() {} })
168+
· ─────────
169+
╰────
170+
help: Unexpected use of undefined.
171+
172+
eslint(no-undefined): Disallow the use of `undefined` as an identifier
173+
╭─[no_undefined.tsx:1:14]
174+
1class Foo { [undefined]() {} }
175+
· ─────────
176+
╰────
177+
help: Unexpected use of undefined.
178+
179+
eslint(no-undefined): Disallow the use of `undefined` as an identifier
180+
╭─[no_undefined.tsx:1:11]
181+
1 │ (class { [undefined]() {} })
182+
· ─────────
183+
╰────
184+
help: Unexpected use of undefined.
185+
186+
eslint(no-undefined): Disallow the use of `undefined` as an identifier
187+
╭─[no_undefined.tsx:1:5]
188+
1var undefined = true; undefined = false;
189+
· ─────────
190+
╰────
191+
help: Unexpected use of undefined.
192+
193+
eslint(no-undefined): Disallow the use of `undefined` as an identifier
194+
╭─[no_undefined.tsx:1:23]
195+
1var undefined = true; undefined = false;
196+
· ─────────
197+
╰────
198+
help: Unexpected use of undefined.
199+
200+
eslint(no-undefined): Disallow the use of `undefined` as an identifier
201+
╭─[no_undefined.tsx:1:8]
202+
1import undefined from 'foo'
203+
· ─────────
204+
╰────
205+
help: Unexpected use of undefined.
206+
207+
eslint(no-undefined): Disallow the use of `undefined` as an identifier
208+
╭─[no_undefined.tsx:1:13]
209+
1import * as undefined from 'foo'
210+
· ─────────
211+
╰────
212+
help: Unexpected use of undefined.
213+
214+
eslint(no-undefined): Disallow the use of `undefined` as an identifier
215+
╭─[no_undefined.tsx:1:10]
216+
1import { undefined } from 'foo'
217+
· ─────────
218+
╰────
219+
help: Unexpected use of undefined.
220+
221+
eslint(no-undefined): Disallow the use of `undefined` as an identifier
222+
╭─[no_undefined.tsx:1:15]
223+
1import { a as undefined } from 'foo'
224+
· ─────────
225+
╰────
226+
help: Unexpected use of undefined.
227+
228+
eslint(no-undefined): Disallow the use of `undefined` as an identifier
229+
╭─[no_undefined.tsx:1:16]
230+
1let a = [b, ...undefined]
231+
· ─────────
232+
╰────
233+
help: Unexpected use of undefined.
234+
235+
eslint(no-undefined): Disallow the use of `undefined` as an identifier
236+
╭─[no_undefined.tsx:1:8]
237+
1 │ [a, ...undefined] = b
238+
· ─────────
239+
╰────
240+
help: Unexpected use of undefined.
241+
242+
eslint(no-undefined): Disallow the use of `undefined` as an identifier
243+
╭─[no_undefined.tsx:1:6]
244+
1 │ [a = undefined] = b
245+
· ─────────
246+
╰────
247+
help: Unexpected use of undefined.

0 commit comments

Comments
 (0)
Please sign in to comment.