diff --git a/crates/oxc_linter/src/rules/unicorn/no_useless_spread/const_eval.rs b/crates/oxc_linter/src/rules/unicorn/no_useless_spread/const_eval.rs index f3572859bbb17..7e0ca4405f8e3 100644 --- a/crates/oxc_linter/src/rules/unicorn/no_useless_spread/const_eval.rs +++ b/crates/oxc_linter/src/rules/unicorn/no_useless_spread/const_eval.rs @@ -8,6 +8,10 @@ use crate::ast_util::{is_method_call, is_new_expression}; pub(super) enum ValueHint { NewObject, NewArray, + /// A non-array iterable. + /// + /// Note that typed arrays are considered arrays, not iterables. + NewIterable, Promise(Box), Unknown, } @@ -34,9 +38,12 @@ impl ValueHint { impl std::ops::BitAnd for ValueHint { type Output = Self; fn bitand(self, rhs: Self) -> Self::Output { + // NOTE: what about (NewArray, NewIterable), e.g. in + // `foo ? new Set() : []` match (self, rhs) { (Self::NewArray, Self::NewArray) => Self::NewArray, (Self::NewObject, Self::NewObject) => Self::NewObject, + (Self::NewIterable, Self::NewIterable) => Self::NewIterable, _ => Self::Unknown, } } @@ -81,8 +88,10 @@ impl<'a> ConstEval for Argument<'a> { impl<'a> ConstEval for NewExpression<'a> { fn const_eval(&self) -> ValueHint { - if is_new_array(self) || is_new_map_or_set(self) || is_new_typed_array(self) { + if is_new_array(self) || is_new_typed_array(self) { ValueHint::NewArray + } else if is_new_map_or_set(self) { + ValueHint::NewIterable } else if is_new_object(self) { ValueHint::NewObject } else { diff --git a/crates/oxc_linter/src/rules/unicorn/no_useless_spread/mod.rs b/crates/oxc_linter/src/rules/unicorn/no_useless_spread/mod.rs index 1610507489229..8129c54e1827e 100644 --- a/crates/oxc_linter/src/rules/unicorn/no_useless_spread/mod.rs +++ b/crates/oxc_linter/src/rules/unicorn/no_useless_spread/mod.rs @@ -492,23 +492,6 @@ fn get_method_name(call_expr: &CallExpression) -> Option { Some(format!("{}.{}", object_name, callee.static_property_name().unwrap())) } -#[test] -fn test_debug() { - use crate::tester::Tester; - - let pass = vec![]; - - let fail = vec![ - // "[...arr.reduce(f, new Set())]", - "const obj = { a, ...{ b, c } }", - // "const promise = Promise.all([...iterable])", - // "const obj = { ...(foo ? { a: 1 } : { a: 2 }) }", - // "const array = [...[a]]", - ]; - - Tester::new(NoUselessSpread::NAME, pass, fail).test(); -} - #[test] fn test() { use crate::tester::Tester; @@ -578,6 +561,7 @@ fn test() { // r"[...Int8Array.from(foo)]", // r"[...Int8Array.of()]", // r"[...new Int8Array(3)]", + r"[...new Set(iter)]", r"[...Promise.all(foo)]", r"[...Promise.allSettled(foo)]", r"[...await Promise.all(foo, extraArgument)]", @@ -585,6 +569,10 @@ fn test() { r"const obj = { ...obj, ...(addFoo ? { foo: 'foo' } : {}) }", r"