feat(linter/tree-shaking): support ArrowFunctionExpression (#2883)

This commit is contained in:
Wang Wenzhe 2024-04-02 10:34:32 +08:00 committed by GitHub
parent 4a86dcb322
commit 15d08f6635
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 105 additions and 18 deletions

View file

@ -11,7 +11,7 @@ use oxc_ast::{
AstKind, AstKind,
}; };
use oxc_semantic::{AstNode, SymbolId}; use oxc_semantic::{AstNode, SymbolId};
use oxc_span::GetSpan; use oxc_span::{GetSpan, Span};
use rustc_hash::FxHashSet; use rustc_hash::FxHashSet;
use crate::{ use crate::{
@ -66,6 +66,11 @@ impl<'a> ListenerMap for Statement<'a> {
Self::Declaration(decl) => { Self::Declaration(decl) => {
decl.report_effects(options); decl.report_effects(options);
} }
Self::ReturnStatement(stmt) => {
if let Some(arg) = &stmt.argument {
arg.report_effects(options);
}
}
Self::ModuleDeclaration(decl) => { Self::ModuleDeclaration(decl) => {
if matches!( if matches!(
decl.0, decl.0,
@ -92,6 +97,16 @@ impl<'a> ListenerMap for AstNode<'a> {
init.report_effects_when_called(options); 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); 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> { impl<'a> ListenerMap for FormalParameter<'a> {
fn report_effects(&self, _options: &NodeListenerOptions) { fn report_effects(&self, options: &NodeListenerOptions) {
// TODO: Not work now, need report side effects. self.pattern.report_effects(options);
} }
} }

View file

@ -30,6 +30,10 @@ enum NoSideEffectsDiagnostic {
#[diagnostic(severity(warning))] #[diagnostic(severity(warning))]
MutationOfFunctionReturnValue(#[label] Span), 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")] #[error("eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of calling")]
#[diagnostic(severity(warning))] #[diagnostic(severity(warning))]
Call(#[label] Span), 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}`")] #[error("eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of calling global function `{0}`")]
#[diagnostic(severity(warning))] #[diagnostic(severity(warning))]
CallGlobal(CompactStr, #[label] Span), 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),
} }
/// <https://github.com/lukastaegert/eslint-plugin-tree-shaking/blob/master/src/rules/no-side-effects-in-initialization.ts> /// <https://github.com/lukastaegert/eslint-plugin-tree-shaking/blob/master/src/rules/no-side-effects-in-initialization.ts>
@ -91,14 +99,14 @@ fn test() {
"const [x] = []", "const [x] = []",
"const [,x,] = []", "const [,x,] = []",
// // ArrowFunctionExpression // // ArrowFunctionExpression
// "const x = a=>{a(); ext()}", "const x = a=>{a(); ext()}",
// // ArrowFunctionExpression when called // // ArrowFunctionExpression when called
// "(()=>{})()", "(()=>{})()",
// "(a=>{})()", "(a=>{})()",
// "((...a)=>{})()", "((...a)=>{})()",
// "(({a})=>{})()", "(({a})=>{})()",
// // ArrowFunctionExpression when mutated // // ArrowFunctionExpression when mutated
// "const x = ()=>{}; x.y = 1", "const x = ()=>{}; x.y = 1",
// // AssignmentExpression // // AssignmentExpression
"var x;x = {}", "var x;x = {}",
"var x;x += 1", "var x;x += 1",
@ -360,15 +368,15 @@ fn test() {
"const [x = ext()] = []", "const [x = ext()] = []",
"const [,x = ext(),] = []", "const [,x = ext(),] = []",
// // ArrowFunctionExpression when called // // ArrowFunctionExpression when called
// "(()=>{ext()})()", "(()=>{ext()})()",
// "(({a = ext()})=>{})()", "(({a = ext()})=>{})()",
// "(a=>{a()})(ext)", "(a=>{a()})(ext)",
// "((...a)=>{a()})(ext)", "((...a)=>{a()})(ext)",
// "(({a})=>{a()})(ext)", "(({a})=>{a()})(ext)",
// "(a=>{a.x = 1})(ext)", "(a=>{a.x = 1})(ext)",
// "(a=>{const b = a;b.x = 1})(ext)", "(a=>{const b = a;b.x = 1})(ext)",
// "((...a)=>{a.x = 1})(ext)", "((...a)=>{a.x = 1})(ext)",
// "(({a})=>{a.x = 1})(ext)", "(({a})=>{a.x = 1})(ext)",
// // AssignmentExpression // // AssignmentExpression
"ext = 1", "ext = 1",
"ext += 1", "ext += 1",

View file

@ -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` ⚠ 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] ╭─[no_side_effects_in_initialization.tsx:1:1]
1 │ ext = 1 1 │ ext = 1