Skip to content

Commit a9017ae

Browse files
committed
refacotr(linter): improve unicorn/throw-new-error
1 parent c91697e commit a9017ae

File tree

2 files changed

+38
-53
lines changed

2 files changed

+38
-53
lines changed

crates/oxc_linter/src/rules/unicorn/throw_new_error.rs

Lines changed: 16 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
use lazy_regex::{Lazy, Regex, lazy_regex};
2-
use oxc_ast::{
3-
AstKind,
4-
ast::{Expression, match_member_expression},
5-
};
1+
use oxc_ast::{AstKind, ast::Expression};
62
use oxc_diagnostics::OxcDiagnostic;
73
use oxc_macros::declare_oxc_lint;
84
use oxc_span::Span;
@@ -16,7 +12,7 @@ use crate::{
1612

1713
fn throw_new_error_diagnostic(span: Span) -> OxcDiagnostic {
1814
OxcDiagnostic::warn("Require `new` when throwing an error.")
19-
.with_help("While it's possible to create a new error without using the `new` keyword, it's better to be explicit.")
15+
.with_help("Using `new` ensures the error is correctly initialized.")
2016
.with_label(span)
2117
}
2218

@@ -26,11 +22,14 @@ pub struct ThrowNewError;
2622
declare_oxc_lint!(
2723
/// ### What it does
2824
///
29-
/// Require `new` when throwing an error.`
25+
/// This rule makes sure you always use `new` when throwing an error.
3026
///
3127
/// ### Why is this bad?
3228
///
33-
/// While it's possible to create a new error without using the `new` keyword, it's better to be explicit.
29+
/// In JavaScript, omitting `new` (e.g., `throw Error('message')`) is allowed,
30+
/// but it does not properly initialize the error object. This can lead to missing
31+
/// stack traces or incorrect prototype chains. Using `new` makes the intent clear,
32+
/// ensures consistent behavior, and helps avoid subtle bugs.
3433
///
3534
/// ### Examples
3635
///
@@ -53,8 +52,6 @@ declare_oxc_lint!(
5352
fix
5453
);
5554

56-
static CUSTOM_ERROR_REGEX_PATTERN: Lazy<Regex> = lazy_regex!(r"^(?:[A-Z][\da-z]*)*Error$");
57-
5855
impl Rule for ThrowNewError {
5956
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
6057
let AstKind::CallExpression(call_expr) = node.kind() else {
@@ -69,29 +66,17 @@ impl Rule for ThrowNewError {
6966
return;
7067
};
7168

72-
match call_expr.callee.without_parentheses() {
73-
Expression::Identifier(v) => {
74-
if !CUSTOM_ERROR_REGEX_PATTERN.is_match(&v.name) {
75-
return;
76-
}
77-
}
78-
callee @ match_member_expression!(Expression) => {
79-
let member_expr = callee.to_member_expression();
80-
if member_expr.is_computed() {
81-
return;
82-
}
83-
if let Some(v) = member_expr.static_property_name() {
84-
if !CUSTOM_ERROR_REGEX_PATTERN.is_match(v) {
85-
return;
86-
}
87-
}
88-
}
69+
let name = match call_expr.callee.without_parentheses() {
70+
Expression::Identifier(v) => v.name,
71+
Expression::StaticMemberExpression(v) => v.property.name,
8972
_ => return,
90-
}
73+
};
9174

92-
ctx.diagnostic_with_fix(throw_new_error_diagnostic(call_expr.span), |fixer| {
93-
fixer.insert_text_before_range(call_expr.span, "new ")
94-
});
75+
if name.len() >= 5 && name.as_bytes()[0].is_ascii_uppercase() && name.ends_with("Error") {
76+
ctx.diagnostic_with_fix(throw_new_error_diagnostic(call_expr.span), |fixer| {
77+
fixer.insert_text_before_range(call_expr.span, "new ")
78+
});
79+
}
9580
}
9681
}
9782

crates/oxc_linter/src/snapshots/unicorn_throw_new_error.snap

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,151 +6,151 @@ source: crates/oxc_linter/src/tester.rs
66
1throw Error()
77
· ───────
88
╰────
9-
help: While it's possible to create a new error without using the `new` keyword, it's better to be explicit.
9+
help: Using `new` ensures the error is correctly initialized.
1010

1111
eslint-plugin-unicorn(throw-new-error): Require `new` when throwing an error.
1212
╭─[throw_new_error.tsx:1:7]
1313
1throw (Error)()
1414
· ─────────
1515
╰────
16-
help: While it's possible to create a new error without using the `new` keyword, it's better to be explicit.
16+
help: Using `new` ensures the error is correctly initialized.
1717

1818
eslint-plugin-unicorn(throw-new-error): Require `new` when throwing an error.
1919
╭─[throw_new_error.tsx:1:7]
2020
1throw lib.Error()
2121
· ───────────
2222
╰────
23-
help: While it's possible to create a new error without using the `new` keyword, it's better to be explicit.
23+
help: Using `new` ensures the error is correctly initialized.
2424

2525
eslint-plugin-unicorn(throw-new-error): Require `new` when throwing an error.
2626
╭─[throw_new_error.tsx:1:7]
2727
1throw lib.mod.Error()
2828
· ───────────────
2929
╰────
30-
help: While it's possible to create a new error without using the `new` keyword, it's better to be explicit.
30+
help: Using `new` ensures the error is correctly initialized.
3131

3232
eslint-plugin-unicorn(throw-new-error): Require `new` when throwing an error.
3333
╭─[throw_new_error.tsx:1:7]
3434
1throw lib[mod].Error()
3535
· ────────────────
3636
╰────
37-
help: While it's possible to create a new error without using the `new` keyword, it's better to be explicit.
37+
help: Using `new` ensures the error is correctly initialized.
3838

3939
eslint-plugin-unicorn(throw-new-error): Require `new` when throwing an error.
4040
╭─[throw_new_error.tsx:1:7]
4141
1throw (lib.mod).Error()
4242
· ─────────────────
4343
╰────
44-
help: While it's possible to create a new error without using the `new` keyword, it's better to be explicit.
44+
help: Using `new` ensures the error is correctly initialized.
4545

4646
eslint-plugin-unicorn(throw-new-error): Require `new` when throwing an error.
4747
╭─[throw_new_error.tsx:1:7]
4848
1throw Error('foo')
4949
· ────────────
5050
╰────
51-
help: While it's possible to create a new error without using the `new` keyword, it's better to be explicit.
51+
help: Using `new` ensures the error is correctly initialized.
5252

5353
eslint-plugin-unicorn(throw-new-error): Require `new` when throwing an error.
5454
╭─[throw_new_error.tsx:1:7]
5555
1throw CustomError('foo')
5656
· ──────────────────
5757
╰────
58-
help: While it's possible to create a new error without using the `new` keyword, it's better to be explicit.
58+
help: Using `new` ensures the error is correctly initialized.
5959

6060
eslint-plugin-unicorn(throw-new-error): Require `new` when throwing an error.
6161
╭─[throw_new_error.tsx:1:7]
6262
1throw FooBarBazError('foo')
6363
· ─────────────────────
6464
╰────
65-
help: While it's possible to create a new error without using the `new` keyword, it's better to be explicit.
65+
help: Using `new` ensures the error is correctly initialized.
6666

6767
eslint-plugin-unicorn(throw-new-error): Require `new` when throwing an error.
6868
╭─[throw_new_error.tsx:1:7]
6969
1throw ABCError('foo')
7070
· ───────────────
7171
╰────
72-
help: While it's possible to create a new error without using the `new` keyword, it's better to be explicit.
72+
help: Using `new` ensures the error is correctly initialized.
7373

7474
eslint-plugin-unicorn(throw-new-error): Require `new` when throwing an error.
7575
╭─[throw_new_error.tsx:1:7]
7676
1throw Abc3Error('foo')
7777
· ────────────────
7878
╰────
79-
help: While it's possible to create a new error without using the `new` keyword, it's better to be explicit.
79+
help: Using `new` ensures the error is correctly initialized.
8080

8181
eslint-plugin-unicorn(throw-new-error): Require `new` when throwing an error.
8282
╭─[throw_new_error.tsx:1:7]
8383
1throw TypeError()
8484
· ───────────
8585
╰────
86-
help: While it's possible to create a new error without using the `new` keyword, it's better to be explicit.
86+
help: Using `new` ensures the error is correctly initialized.
8787

8888
eslint-plugin-unicorn(throw-new-error): Require `new` when throwing an error.
8989
╭─[throw_new_error.tsx:1:7]
9090
1throw EvalError()
9191
· ───────────
9292
╰────
93-
help: While it's possible to create a new error without using the `new` keyword, it's better to be explicit.
93+
help: Using `new` ensures the error is correctly initialized.
9494

9595
eslint-plugin-unicorn(throw-new-error): Require `new` when throwing an error.
9696
╭─[throw_new_error.tsx:1:7]
9797
1throw RangeError()
9898
· ────────────
9999
╰────
100-
help: While it's possible to create a new error without using the `new` keyword, it's better to be explicit.
100+
help: Using `new` ensures the error is correctly initialized.
101101

102102
eslint-plugin-unicorn(throw-new-error): Require `new` when throwing an error.
103103
╭─[throw_new_error.tsx:1:7]
104104
1throw ReferenceError()
105105
· ────────────────
106106
╰────
107-
help: While it's possible to create a new error without using the `new` keyword, it's better to be explicit.
107+
help: Using `new` ensures the error is correctly initialized.
108108

109109
eslint-plugin-unicorn(throw-new-error): Require `new` when throwing an error.
110110
╭─[throw_new_error.tsx:1:7]
111111
1throw SyntaxError()
112112
· ─────────────
113113
╰────
114-
help: While it's possible to create a new error without using the `new` keyword, it's better to be explicit.
114+
help: Using `new` ensures the error is correctly initialized.
115115

116116
eslint-plugin-unicorn(throw-new-error): Require `new` when throwing an error.
117117
╭─[throw_new_error.tsx:1:7]
118118
1throw URIError()
119119
· ──────────
120120
╰────
121-
help: While it's possible to create a new error without using the `new` keyword, it's better to be explicit.
121+
help: Using `new` ensures the error is correctly initialized.
122122

123123
eslint-plugin-unicorn(throw-new-error): Require `new` when throwing an error.
124124
╭─[throw_new_error.tsx:1:10]
125125
1throw (( URIError() ))
126126
· ──────────
127127
╰────
128-
help: While it's possible to create a new error without using the `new` keyword, it's better to be explicit.
128+
help: Using `new` ensures the error is correctly initialized.
129129

130130
eslint-plugin-unicorn(throw-new-error): Require `new` when throwing an error.
131131
╭─[throw_new_error.tsx:1:7]
132132
1throw (( URIError ))()
133133
· ────────────────
134134
╰────
135-
help: While it's possible to create a new error without using the `new` keyword, it's better to be explicit.
135+
help: Using `new` ensures the error is correctly initialized.
136136

137137
eslint-plugin-unicorn(throw-new-error): Require `new` when throwing an error.
138138
╭─[throw_new_error.tsx:1:7]
139139
1throw getGlobalThis().Error()
140140
· ───────────────────────
141141
╰────
142-
help: While it's possible to create a new error without using the `new` keyword, it's better to be explicit.
142+
help: Using `new` ensures the error is correctly initialized.
143143

144144
eslint-plugin-unicorn(throw-new-error): Require `new` when throwing an error.
145145
╭─[throw_new_error.tsx:1:7]
146146
1throw utils.getGlobalThis().Error()
147147
· ─────────────────────────────
148148
╰────
149-
help: While it's possible to create a new error without using the `new` keyword, it's better to be explicit.
149+
help: Using `new` ensures the error is correctly initialized.
150150

151151
eslint-plugin-unicorn(throw-new-error): Require `new` when throwing an error.
152152
╭─[throw_new_error.tsx:1:7]
153153
1throw (( getGlobalThis().Error ))()
154154
· ─────────────────────────────
155155
╰────
156-
help: While it's possible to create a new error without using the `new` keyword, it's better to be explicit.
156+
help: Using `new` ensures the error is correctly initialized.

0 commit comments

Comments
 (0)