feat(linter/tree-shaking): support ArrayExpression and ArrayPattern (#2882)

This commit is contained in:
Wang Wenzhe 2024-04-02 10:33:07 +08:00 committed by GitHub
parent 23d3c4e0a4
commit 4a86dcb322
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 86 additions and 12 deletions

View file

@ -3,9 +3,10 @@ use std::cell::RefCell;
use oxc_ast::{
ast::{
Argument, ArrayExpressionElement, ArrowFunctionExpression, AssignmentTarget,
CallExpression, ComputedMemberExpression, Expression, FormalParameter, Function,
IdentifierReference, MemberExpression, ModuleDeclaration, ParenthesizedExpression,
PrivateFieldExpression, Program, SimpleAssignmentTarget, Statement, StaticMemberExpression,
BindingPattern, BindingPatternKind, CallExpression, ComputedMemberExpression, Declaration,
Expression, FormalParameter, Function, IdentifierReference, MemberExpression,
ModuleDeclaration, ParenthesizedExpression, PrivateFieldExpression, Program,
SimpleAssignmentTarget, Statement, StaticMemberExpression, VariableDeclarator,
},
AstKind,
};
@ -62,6 +63,9 @@ impl<'a> ListenerMap for Statement<'a> {
Self::BreakStatement(_) | Self::ContinueStatement(_) | Self::EmptyStatement(_) => {
no_effects();
}
Self::Declaration(decl) => {
decl.report_effects(options);
}
Self::ModuleDeclaration(decl) => {
if matches!(
decl.0,
@ -104,6 +108,52 @@ impl<'a> ListenerMap for AstNode<'a> {
}
}
impl<'a> ListenerMap for Declaration<'a> {
fn report_effects(&self, options: &NodeListenerOptions) {
#[allow(clippy::single_match)]
match self {
Self::VariableDeclaration(decl) => {
decl.declarations.iter().for_each(|decl| decl.report_effects(options));
}
_ => {}
}
}
}
impl<'a> ListenerMap for VariableDeclarator<'a> {
fn report_effects(&self, options: &NodeListenerOptions) {
self.id.report_effects(options);
if let Some(init) = &self.init {
init.report_effects(options);
}
}
}
impl<'a> ListenerMap for BindingPattern<'a> {
fn report_effects(&self, options: &NodeListenerOptions) {
match &self.kind {
BindingPatternKind::BindingIdentifier(_) => {}
BindingPatternKind::ArrayPattern(array) => {
array.elements.iter().for_each(|el| {
if let Some(el) = el {
el.report_effects(options);
}
});
}
BindingPatternKind::ObjectPattern(object) => {
object.properties.iter().for_each(|prop| {
prop.value.report_effects(options);
});
}
BindingPatternKind::AssignmentPattern(assign_p) => {
assign_p.left.report_effects(options);
assign_p.right.report_effects(options);
}
}
}
}
impl<'a> ListenerMap for Expression<'a> {
fn report_effects(&self, options: &NodeListenerOptions) {
match self {

View file

@ -84,12 +84,12 @@ fn test() {
let pass = vec![
// ArrayExpression
"[]",
// "const x = []",
// "const x = [ext,ext]",
// "const x = [1,,2,]",
"const x = []",
"const x = [ext,ext]",
"const x = [1,,2,]",
// // ArrayPattern
// "const [x] = []",
// "const [,x,] = []",
"const [x] = []",
"const [,x,] = []",
// // ArrowFunctionExpression
// "const x = a=>{a(); ext()}",
// // ArrowFunctionExpression when called
@ -354,11 +354,11 @@ fn test() {
let fail = vec![
// // ArrayExpression
// "const x = [ext()]",
// "const x = [,,ext(),]",
"const x = [ext()]",
"const x = [,,ext(),]",
// // ArrayPattern
// "const [x = ext()] = []",
// "const [,x = ext(),] = []",
"const [x = ext()] = []",
"const [,x = ext(),] = []",
// // ArrowFunctionExpression when called
// "(()=>{ext()})()",
// "(({a = ext()})=>{})()",

View file

@ -2,6 +2,30 @@
source: crates/oxc_linter/src/tester.rs
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:12]
1 │ const x = [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:14]
1 │ const x = [,,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:12]
1 │ const [x = 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:13]
1 │ const [,x = 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