diff --git a/crates/oxc_linter/src/rules/tree_shaking/no_side_effects_in_initialization/listener_map.rs b/crates/oxc_linter/src/rules/tree_shaking/no_side_effects_in_initialization/listener_map.rs index 8ac7df58b33cc..3ffa4fdea580f 100644 --- a/crates/oxc_linter/src/rules/tree_shaking/no_side_effects_in_initialization/listener_map.rs +++ b/crates/oxc_linter/src/rules/tree_shaking/no_side_effects_in_initialization/listener_map.rs @@ -11,7 +11,7 @@ use oxc_ast::{ AstKind, }; use oxc_semantic::{AstNode, SymbolId}; -use oxc_span::GetSpan; +use oxc_span::{GetSpan, Span}; use rustc_hash::FxHashSet; use crate::{ @@ -66,6 +66,11 @@ impl<'a> ListenerMap for Statement<'a> { Self::Declaration(decl) => { decl.report_effects(options); } + Self::ReturnStatement(stmt) => { + if let Some(arg) = &stmt.argument { + arg.report_effects(options); + } + } Self::ModuleDeclaration(decl) => { if matches!( decl.0, @@ -92,6 +97,16 @@ impl<'a> ListenerMap for AstNode<'a> { init.report_effects_when_called(options); } } + AstKind::FormalParameter(param) => { + options.ctx.diagnostic(NoSideEffectsDiagnostic::CallParameter(param.span)); + } + AstKind::BindingRestElement(rest) => { + let start = rest.span.start + 3; + let end = rest.span.end; + options + .ctx + .diagnostic(NoSideEffectsDiagnostic::CallParameter(Span::new(start, end))); + } _ => {} } } @@ -103,6 +118,16 @@ impl<'a> ListenerMap for AstNode<'a> { init.report_effects_when_mutated(options); } } + AstKind::FormalParameter(param) => { + options.ctx.diagnostic(NoSideEffectsDiagnostic::MutationOfParameter(param.span)); + } + AstKind::BindingRestElement(rest) => { + let start = rest.span.start + 3; + let end = rest.span.end; + options.ctx.diagnostic(NoSideEffectsDiagnostic::MutationOfParameter(Span::new( + start, end, + ))); + } _ => {} } } @@ -272,8 +297,8 @@ impl<'a> ListenerMap for Function<'a> { } impl<'a> ListenerMap for FormalParameter<'a> { - fn report_effects(&self, _options: &NodeListenerOptions) { - // TODO: Not work now, need report side effects. + fn report_effects(&self, options: &NodeListenerOptions) { + self.pattern.report_effects(options); } } diff --git a/crates/oxc_linter/src/rules/tree_shaking/no_side_effects_in_initialization/mod.rs b/crates/oxc_linter/src/rules/tree_shaking/no_side_effects_in_initialization/mod.rs index 76f42820fec56..2631800c66645 100644 --- a/crates/oxc_linter/src/rules/tree_shaking/no_side_effects_in_initialization/mod.rs +++ b/crates/oxc_linter/src/rules/tree_shaking/no_side_effects_in_initialization/mod.rs @@ -30,6 +30,10 @@ enum NoSideEffectsDiagnostic { #[diagnostic(severity(warning))] MutationOfFunctionReturnValue(#[label] Span), + #[error("eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of mutating function parameter")] + #[diagnostic(severity(warning))] + MutationOfParameter(#[label] Span), + #[error("eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of calling")] #[diagnostic(severity(warning))] Call(#[label] Span), @@ -41,6 +45,10 @@ enum NoSideEffectsDiagnostic { #[error("eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of calling global function `{0}`")] #[diagnostic(severity(warning))] CallGlobal(CompactStr, #[label] Span), + + #[error("eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of calling function parameter")] + #[diagnostic(severity(warning))] + CallParameter(#[label] Span), } /// @@ -91,14 +99,14 @@ fn test() { "const [x] = []", "const [,x,] = []", // // ArrowFunctionExpression - // "const x = a=>{a(); ext()}", + "const x = a=>{a(); ext()}", // // ArrowFunctionExpression when called - // "(()=>{})()", - // "(a=>{})()", - // "((...a)=>{})()", - // "(({a})=>{})()", + "(()=>{})()", + "(a=>{})()", + "((...a)=>{})()", + "(({a})=>{})()", // // ArrowFunctionExpression when mutated - // "const x = ()=>{}; x.y = 1", + "const x = ()=>{}; x.y = 1", // // AssignmentExpression "var x;x = {}", "var x;x += 1", @@ -360,15 +368,15 @@ fn test() { "const [x = ext()] = []", "const [,x = ext(),] = []", // // ArrowFunctionExpression when called - // "(()=>{ext()})()", - // "(({a = ext()})=>{})()", - // "(a=>{a()})(ext)", - // "((...a)=>{a()})(ext)", - // "(({a})=>{a()})(ext)", - // "(a=>{a.x = 1})(ext)", - // "(a=>{const b = a;b.x = 1})(ext)", - // "((...a)=>{a.x = 1})(ext)", - // "(({a})=>{a.x = 1})(ext)", + "(()=>{ext()})()", + "(({a = ext()})=>{})()", + "(a=>{a()})(ext)", + "((...a)=>{a()})(ext)", + "(({a})=>{a()})(ext)", + "(a=>{a.x = 1})(ext)", + "(a=>{const b = a;b.x = 1})(ext)", + "((...a)=>{a.x = 1})(ext)", + "(({a})=>{a.x = 1})(ext)", // // AssignmentExpression "ext = 1", "ext += 1", diff --git a/crates/oxc_linter/src/snapshots/no_side_effects_in_initialization.snap b/crates/oxc_linter/src/snapshots/no_side_effects_in_initialization.snap index 82dff9cdbc632..2439e939d62d4 100644 --- a/crates/oxc_linter/src/snapshots/no_side_effects_in_initialization.snap +++ b/crates/oxc_linter/src/snapshots/no_side_effects_in_initialization.snap @@ -26,6 +26,60 @@ expression: no_side_effects_in_initialization · ─── ╰──── + ⚠ eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of calling global function `ext` + ╭─[no_side_effects_in_initialization.tsx:1:7] + 1 │ (()=>{ext()})() + · ─── + ╰──── + + ⚠ eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of calling global function `ext` + ╭─[no_side_effects_in_initialization.tsx:1:8] + 1 │ (({a = ext()})=>{})() + · ─── + ╰──── + + ⚠ eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of calling function parameter + ╭─[no_side_effects_in_initialization.tsx:1:2] + 1 │ (a=>{a()})(ext) + · ─ + ╰──── + + ⚠ eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of calling function parameter + ╭─[no_side_effects_in_initialization.tsx:1:6] + 1 │ ((...a)=>{a()})(ext) + · ─ + ╰──── + + ⚠ eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of calling function parameter + ╭─[no_side_effects_in_initialization.tsx:1:3] + 1 │ (({a})=>{a()})(ext) + · ─── + ╰──── + + ⚠ eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of mutating function parameter + ╭─[no_side_effects_in_initialization.tsx:1:2] + 1 │ (a=>{a.x = 1})(ext) + · ─ + ╰──── + + ⚠ eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of mutating function parameter + ╭─[no_side_effects_in_initialization.tsx:1:2] + 1 │ (a=>{const b = a;b.x = 1})(ext) + · ─ + ╰──── + + ⚠ eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of mutating function parameter + ╭─[no_side_effects_in_initialization.tsx:1:6] + 1 │ ((...a)=>{a.x = 1})(ext) + · ─ + ╰──── + + ⚠ eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of mutating function parameter + ╭─[no_side_effects_in_initialization.tsx:1:3] + 1 │ (({a})=>{a.x = 1})(ext) + · ─── + ╰──── + ⚠ eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of assignment to `ext` ╭─[no_side_effects_in_initialization.tsx:1:1] 1 │ ext = 1