mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 04:08:41 +00:00
fix(linter): support rest params for prefer_promise_reject_errors (#8468)
fixed: https://github.com/oxc-project/oxc/pull/8254#issuecomment-2587461210
This commit is contained in:
parent
de5b28809a
commit
c6260c278b
2 changed files with 64 additions and 12 deletions
|
|
@ -1,4 +1,5 @@
|
|||
use oxc_allocator::Box;
|
||||
use oxc_ast::ast::MemberExpression;
|
||||
use oxc_ast::{
|
||||
ast::{Argument, CallExpression, Expression, FormalParameters},
|
||||
AstKind,
|
||||
|
|
@ -136,31 +137,65 @@ fn check_reject_call(call_expr: &CallExpression, ctx: &LintContext, allow_empty_
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::float_cmp, clippy::cast_precision_loss)]
|
||||
fn check_reject_in_function(
|
||||
params: &Box<'_, FormalParameters<'_>>,
|
||||
ctx: &LintContext,
|
||||
allow_empty_reject: bool,
|
||||
) {
|
||||
if params.parameters_count() <= 1 {
|
||||
if params.items.len() >= 2 {
|
||||
let Some(reject_arg) = params.items[1].pattern.get_binding_identifier() else {
|
||||
return;
|
||||
};
|
||||
|
||||
ctx.symbol_references(reject_arg.symbol_id()).for_each(|reference| {
|
||||
let Some(node) = ctx.nodes().parent_node(reference.node_id()) else {
|
||||
return;
|
||||
};
|
||||
if let AstKind::CallExpression(call_expr) = node.kind() {
|
||||
check_reject_call(call_expr, ctx, allow_empty_reject);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
let Some(reject_arg) = params.items[1].pattern.get_binding_identifier() else {
|
||||
return;
|
||||
};
|
||||
let Some(rest_param) = ¶ms.rest else { return };
|
||||
let Some(rest_arg) = rest_param.argument.get_binding_identifier() else { return };
|
||||
let rest_index = (1 - params.items.len()) as f64;
|
||||
for reference in ctx.symbol_references(rest_arg.symbol_id()) {
|
||||
let node = ctx.nodes().get_node(reference.node_id());
|
||||
|
||||
ctx.symbol_references(reject_arg.symbol_id()).for_each(|reference| {
|
||||
let Some(node) = ctx.nodes().parent_node(reference.node_id()) else {
|
||||
return;
|
||||
if !matches!(node.kind(), AstKind::IdentifierReference(_)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let Some(parent) = ctx.nodes().parent_node(reference.node_id()) else { continue };
|
||||
let AstKind::MemberExpression(MemberExpression::ComputedMemberExpression(member_expr)) =
|
||||
parent.kind()
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let Expression::NumericLiteral(literal) = &member_expr.expression else {
|
||||
continue;
|
||||
};
|
||||
|
||||
if literal.value != rest_index {
|
||||
continue;
|
||||
}
|
||||
|
||||
let Some(node) = ctx.nodes().parent_node(parent.id()) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
if let AstKind::CallExpression(call_expr) = node.kind() {
|
||||
check_reject_call(call_expr, ctx, allow_empty_reject);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn is_undefined(arg: &Argument) -> bool {
|
||||
match arg.as_expression().map(oxc_ast::ast::Expression::get_inner_expression) {
|
||||
match arg.as_expression().map(Expression::get_inner_expression) {
|
||||
Some(Expression::Identifier(ident)) => ident.name == "undefined",
|
||||
_ => false,
|
||||
}
|
||||
|
|
@ -196,7 +231,12 @@ fn test() {
|
|||
("Promise.reject(foo.bar ??= 5)", None),
|
||||
("Promise.reject(foo[bar] ??= 5)", None),
|
||||
("class C { #reject; foo() { Promise.#reject(5); } }", None),
|
||||
("class C { #error; foo() { Promise.reject(this.#error); } }", None)
|
||||
("class C { #error; foo() { Promise.reject(this.#error); } }", None),
|
||||
("new Promise(function (resolve, ...rest) { rest[0](new Error('')); });", None),
|
||||
("new Promise(function (...rest) { rest[0](new Error('')); });", None),
|
||||
("new Promise(function (...rest) { rest[1](new Error('')); });", None),
|
||||
// This is fundamentally false, but we can not recognize the value of `i`.
|
||||
("new Promise(function (resolve, ...rest) { rest[i](5); });", None),
|
||||
];
|
||||
|
||||
let fail = vec; });", None),
|
||||
("new Promise(function (...rest) { rest[1](5); });", None),
|
||||
];
|
||||
|
||||
Tester::new(PreferPromiseRejectErrors::NAME, PreferPromiseRejectErrors::PLUGIN, pass, fail)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
---
|
||||
source: crates/oxc_linter/src/tester.rs
|
||||
assertion_line: 356
|
||||
snapshot_kind: text
|
||||
---
|
||||
⚠ eslint(prefer-promise-reject-errors): Expected the Promise rejection reason to be an Error
|
||||
╭─[prefer_promise_reject_errors.tsx:1:1]
|
||||
|
|
@ -240,3 +238,15 @@ snapshot_kind: text
|
|||
1 │ Promise.reject(foo &&= 5)
|
||||
· ─────────────────────────
|
||||
╰────
|
||||
|
||||
⚠ eslint(prefer-promise-reject-errors): Expected the Promise rejection reason to be an Error
|
||||
╭─[prefer_promise_reject_errors.tsx:1:43]
|
||||
1 │ new Promise(function (resolve, ...rest) { rest[0](5); });
|
||||
· ──────────
|
||||
╰────
|
||||
|
||||
⚠ eslint(prefer-promise-reject-errors): Expected the Promise rejection reason to be an Error
|
||||
╭─[prefer_promise_reject_errors.tsx:1:34]
|
||||
1 │ new Promise(function (...rest) { rest[1](5); });
|
||||
· ──────────
|
||||
╰────
|
||||
|
|
|
|||
Loading…
Reference in a new issue