diff --git a/crates/oxc_linter/src/ast_util.rs b/crates/oxc_linter/src/ast_util.rs index 501c7d77e..14ecb3590 100644 --- a/crates/oxc_linter/src/ast_util.rs +++ b/crates/oxc_linter/src/ast_util.rs @@ -1,26 +1,24 @@ use oxc_ast::{ast::BindingIdentifier, AstKind}; use oxc_ecmascript::ToBoolean; -use oxc_semantic::{AstNode, IsGlobalReference, NodeId, SymbolId}; +use oxc_semantic::{AstNode, IsGlobalReference, NodeId, Semantic, SymbolId}; use oxc_span::{GetSpan, Span}; use oxc_syntax::operator::{AssignmentOperator, BinaryOperator, LogicalOperator, UnaryOperator}; #[allow(clippy::wildcard_imports)] use oxc_ast::ast::*; -use crate::context::LintContext; - /// Test if an AST node is a boolean value that never changes. Specifically we /// test for: /// 1. Literal booleans (`true` or `false`) /// 2. Unary `!` expressions with a constant value /// 3. Constant booleans created via the `Boolean` global function -pub fn is_static_boolean<'a>(expr: &Expression<'a>, ctx: &LintContext<'a>) -> bool { +pub fn is_static_boolean<'a>(expr: &Expression<'a>, semantic: &Semantic<'a>) -> bool { match expr { Expression::BooleanLiteral(_) => true, - Expression::CallExpression(call_expr) => call_expr.is_constant(true, ctx), + Expression::CallExpression(call_expr) => call_expr.is_constant(true, semantic), Expression::UnaryExpression(unary_expr) => { unary_expr.operator == UnaryOperator::LogicalNot - && unary_expr.argument.is_constant(true, ctx) + && unary_expr.argument.is_constant(true, semantic) } _ => false, } @@ -64,11 +62,11 @@ fn is_logical_identity(op: LogicalOperator, expr: &Expression) -> bool { /// When `false`, checks if -- for both string and number -- /// if coerced to that type, the value will be constant. pub trait IsConstant<'a, 'b> { - fn is_constant(&self, in_boolean_position: bool, ctx: &LintContext<'a>) -> bool; + fn is_constant(&self, in_boolean_position: bool, semantic: &Semantic<'a>) -> bool; } impl<'a, 'b> IsConstant<'a, 'b> for Expression<'a> { - fn is_constant(&self, in_boolean_position: bool, ctx: &LintContext<'a>) -> bool { + fn is_constant(&self, in_boolean_position: bool, semantic: &Semantic<'a>) -> bool { match self { Self::ArrowFunctionExpression(_) | Self::FunctionExpression(_) @@ -80,29 +78,29 @@ impl<'a, 'b> IsConstant<'a, 'b> for Expression<'a> { quasi.value.cooked.as_ref().map_or(false, |cooked| !cooked.is_empty()) }); let test_expressions = - template.expressions.iter().all(|expr| expr.is_constant(false, ctx)); + template.expressions.iter().all(|expr| expr.is_constant(false, semantic)); test_quasis || test_expressions } Self::ArrayExpression(expr) => { if in_boolean_position { return true; } - expr.elements.iter().all(|element| element.is_constant(false, ctx)) + expr.elements.iter().all(|element| element.is_constant(false, semantic)) } Self::UnaryExpression(expr) => match expr.operator { UnaryOperator::Void => true, UnaryOperator::Typeof if in_boolean_position => true, - UnaryOperator::LogicalNot => expr.argument.is_constant(true, ctx), - _ => expr.argument.is_constant(false, ctx), + UnaryOperator::LogicalNot => expr.argument.is_constant(true, semantic), + _ => expr.argument.is_constant(false, semantic), }, Self::BinaryExpression(expr) => { expr.operator != BinaryOperator::In - && expr.left.is_constant(false, ctx) - && expr.right.is_constant(false, ctx) + && expr.left.is_constant(false, semantic) + && expr.right.is_constant(false, semantic) } Self::LogicalExpression(expr) => { - let is_left_constant = expr.left.is_constant(in_boolean_position, ctx); - let is_right_constant = expr.right.is_constant(in_boolean_position, ctx); + let is_left_constant = expr.left.is_constant(in_boolean_position, semantic); + let is_right_constant = expr.right.is_constant(in_boolean_position, semantic); let is_left_short_circuit = is_left_constant && is_logical_identity(expr.operator, &expr.left); let is_right_short_circuit = in_boolean_position @@ -114,7 +112,7 @@ impl<'a, 'b> IsConstant<'a, 'b> for Expression<'a> { } Self::NewExpression(_) => in_boolean_position, Self::AssignmentExpression(expr) => match expr.operator { - AssignmentOperator::Assign => expr.right.is_constant(in_boolean_position, ctx), + AssignmentOperator::Assign => expr.right.is_constant(in_boolean_position, semantic), AssignmentOperator::LogicalAnd if in_boolean_position => { is_logical_identity(LogicalOperator::And, &expr.right) } @@ -127,13 +125,13 @@ impl<'a, 'b> IsConstant<'a, 'b> for Expression<'a> { .expressions .iter() .last() - .map_or(false, |last| last.is_constant(in_boolean_position, ctx)), - Self::CallExpression(call_expr) => call_expr.is_constant(in_boolean_position, ctx), + .map_or(false, |last| last.is_constant(in_boolean_position, semantic)), + Self::CallExpression(call_expr) => call_expr.is_constant(in_boolean_position, semantic), Self::ParenthesizedExpression(paren_expr) => { - paren_expr.expression.is_constant(in_boolean_position, ctx) + paren_expr.expression.is_constant(in_boolean_position, semantic) } Self::Identifier(ident) => { - ident.name == "undefined" && ctx.semantic().is_reference_to_global_variable(ident) + ident.name == "undefined" && semantic.is_reference_to_global_variable(ident) } _ if self.is_literal() => true, _ => false, @@ -142,12 +140,16 @@ impl<'a, 'b> IsConstant<'a, 'b> for Expression<'a> { } impl<'a, 'b> IsConstant<'a, 'b> for CallExpression<'a> { - fn is_constant(&self, _in_boolean_position: bool, ctx: &LintContext<'a>) -> bool { + fn is_constant(&self, _in_boolean_position: bool, semantic: &Semantic<'a>) -> bool { if let Expression::Identifier(ident) = &self.callee { if ident.name == "Boolean" - && self.arguments.iter().next().map_or(true, |first| first.is_constant(true, ctx)) + && self + .arguments + .iter() + .next() + .map_or(true, |first| first.is_constant(true, semantic)) { - return ctx.semantic().is_reference_to_global_variable(ident); + return semantic.is_reference_to_global_variable(ident); } } false @@ -155,27 +157,31 @@ impl<'a, 'b> IsConstant<'a, 'b> for CallExpression<'a> { } impl<'a, 'b> IsConstant<'a, 'b> for Argument<'a> { - fn is_constant(&self, in_boolean_position: bool, ctx: &LintContext<'a>) -> bool { + fn is_constant(&self, in_boolean_position: bool, semantic: &Semantic<'a>) -> bool { match self { - Self::SpreadElement(element) => element.is_constant(in_boolean_position, ctx), - match_expression!(Self) => self.to_expression().is_constant(in_boolean_position, ctx), + Self::SpreadElement(element) => element.is_constant(in_boolean_position, semantic), + match_expression!(Self) => { + self.to_expression().is_constant(in_boolean_position, semantic) + } } } } impl<'a, 'b> IsConstant<'a, 'b> for ArrayExpressionElement<'a> { - fn is_constant(&self, in_boolean_position: bool, ctx: &LintContext<'a>) -> bool { + fn is_constant(&self, in_boolean_position: bool, semantic: &Semantic<'a>) -> bool { match self { - Self::SpreadElement(element) => element.is_constant(in_boolean_position, ctx), - match_expression!(Self) => self.to_expression().is_constant(in_boolean_position, ctx), + Self::SpreadElement(element) => element.is_constant(in_boolean_position, semantic), + match_expression!(Self) => { + self.to_expression().is_constant(in_boolean_position, semantic) + } Self::Elision(_) => true, } } } impl<'a, 'b> IsConstant<'a, 'b> for SpreadElement<'a> { - fn is_constant(&self, in_boolean_position: bool, ctx: &LintContext<'a>) -> bool { - self.argument.is_constant(in_boolean_position, ctx) + fn is_constant(&self, in_boolean_position: bool, semantic: &Semantic<'a>) -> bool { + self.argument.is_constant(in_boolean_position, semantic) } } @@ -183,7 +189,7 @@ impl<'a, 'b> IsConstant<'a, 'b> for SpreadElement<'a> { /// enclosing the specified node pub fn get_enclosing_function<'a, 'b>( node: &'b AstNode<'a>, - ctx: &'b LintContext<'a>, + semantic: &'b Semantic<'a>, ) -> Option<&'b AstNode<'a>> { let mut current_node = node; loop { @@ -194,7 +200,7 @@ pub fn get_enclosing_function<'a, 'b>( { return Some(current_node); } - current_node = ctx.nodes().parent_node(current_node.id())?; + current_node = semantic.nodes().parent_node(current_node.id())?; } } @@ -205,11 +211,14 @@ pub fn is_nth_argument<'a>(call: &CallExpression<'a>, arg: &Argument<'a>, n: usi } /// Jump to the outer most of chained parentheses if any -pub fn outermost_paren<'a, 'b>(node: &'b AstNode<'a>, ctx: &'b LintContext<'a>) -> &'b AstNode<'a> { +pub fn outermost_paren<'a, 'b>( + node: &'b AstNode<'a>, + semantic: &'b Semantic<'a>, +) -> &'b AstNode<'a> { let mut node = node; loop { - if let Some(parent) = ctx.nodes().parent_node(node.id()) { + if let Some(parent) = semantic.nodes().parent_node(node.id()) { if let AstKind::ParenthesizedExpression(_) = parent.kind() { node = parent; continue; @@ -224,9 +233,10 @@ pub fn outermost_paren<'a, 'b>(node: &'b AstNode<'a>, ctx: &'b LintContext<'a>) pub fn outermost_paren_parent<'a, 'b>( node: &'b AstNode<'a>, - ctx: &'b LintContext<'a>, + semantic: &'b Semantic<'a>, ) -> Option<&'b AstNode<'a>> { - ctx.nodes() + semantic + .nodes() .iter_parents(node.id()) .skip(1) .find(|parent| !matches!(parent.kind(), AstKind::ParenthesizedExpression(_))) @@ -234,10 +244,11 @@ pub fn outermost_paren_parent<'a, 'b>( pub fn nth_outermost_paren_parent<'a, 'b>( node: &'b AstNode<'a>, - ctx: &'b LintContext<'a>, + semantic: &'b Semantic<'a>, n: usize, ) -> Option<&'b AstNode<'a>> { - ctx.nodes() + semantic + .nodes() .iter_parents(node.id()) .skip(1) .filter(|parent| !matches!(parent.kind(), AstKind::ParenthesizedExpression(_))) @@ -245,11 +256,11 @@ pub fn nth_outermost_paren_parent<'a, 'b>( } /// Iterate over parents of `node`, skipping nodes that are also ignored by /// [`Expression::get_inner_expression`]. -pub fn iter_outer_expressions<'a, 'ctx>( - ctx: &'ctx LintContext<'a>, +pub fn iter_outer_expressions<'a, 's>( + semantic: &'s Semantic<'a>, node_id: NodeId, -) -> impl Iterator> + 'ctx { - ctx.nodes().iter_parents(node_id).skip(1).filter(|parent| { +) -> impl Iterator> + 's { + semantic.nodes().iter_parents(node_id).skip(1).filter(|parent| { !matches!( parent.kind(), AstKind::ParenthesizedExpression(_) @@ -263,19 +274,19 @@ pub fn iter_outer_expressions<'a, 'ctx>( } pub fn get_declaration_of_variable<'a, 'b>( - ident: &IdentifierReference, - ctx: &'b LintContext<'a>, + ident: &IdentifierReference<'a>, + semantic: &'b Semantic<'a>, ) -> Option<&'b AstNode<'a>> { - let symbol_id = get_symbol_id_of_variable(ident, ctx)?; - let symbol_table = ctx.semantic().symbols(); - Some(ctx.nodes().get_node(symbol_table.get_declaration(symbol_id))) + let symbol_id = get_symbol_id_of_variable(ident, semantic)?; + let symbol_table = semantic.symbols(); + Some(semantic.nodes().get_node(symbol_table.get_declaration(symbol_id))) } pub fn get_symbol_id_of_variable( ident: &IdentifierReference, - ctx: &LintContext<'_>, + semantic: &Semantic<'_>, ) -> Option { - let symbol_table = ctx.semantic().symbols(); + let symbol_table = semantic.symbols(); let reference_id = ident.reference_id.get()?; let reference = symbol_table.get_reference(reference_id); reference.symbol_id() @@ -389,7 +400,7 @@ pub fn get_new_expr_ident_name<'a>(new_expr: &'a NewExpression<'a>) -> Option<&' Some(ident.name.as_str()) } -pub fn is_global_require_call(call_expr: &CallExpression, ctx: &LintContext) -> bool { +pub fn is_global_require_call(call_expr: &CallExpression, ctx: &Semantic) -> bool { if call_expr.arguments.len() != 1 { return false; } @@ -407,7 +418,7 @@ pub fn is_function_node(node: &AstNode) -> bool { pub fn get_function_like_declaration<'b>( node: &AstNode<'b>, - ctx: &LintContext<'b>, + ctx: &Semantic<'b>, ) -> Option<&'b BindingIdentifier<'b>> { let parent = outermost_paren_parent(node, ctx)?; let decl = parent.kind().as_variable_declarator()?; 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 f382f8091..0e898d1fa 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 @@ -29,24 +29,24 @@ use crate::{ }, }; -pub trait ListenerMap { - fn report_effects(&self, _options: &NodeListenerOptions) {} - fn report_effects_when_assigned(&self, _options: &NodeListenerOptions) {} - fn report_effects_when_called(&self, _options: &NodeListenerOptions) {} - fn report_effects_when_mutated(&self, _options: &NodeListenerOptions) {} - fn get_value_and_report_effects(&self, _options: &NodeListenerOptions) -> Value { +pub trait ListenerMap<'a> { + fn report_effects(&self, _options: &NodeListenerOptions<'a, '_>) {} + fn report_effects_when_assigned(&self, _options: &NodeListenerOptions<'a, '_>) {} + fn report_effects_when_called(&self, _options: &NodeListenerOptions<'a, '_>) {} + fn report_effects_when_mutated(&self, _options: &NodeListenerOptions<'a, '_>) {} + fn get_value_and_report_effects(&self, _options: &NodeListenerOptions<'a, '_>) -> Value { Value::Unknown } } -impl<'a> ListenerMap for Program<'a> { - fn report_effects(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for Program<'a> { + fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { self.body.iter().for_each(|stmt| stmt.report_effects(options)); } } -impl<'a> ListenerMap for Statement<'a> { - fn report_effects(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for Statement<'a> { + fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { match self { Self::ExpressionStatement(expr_stmt) => { expr_stmt.expression.report_effects(options); @@ -179,8 +179,8 @@ impl<'a> ListenerMap for Statement<'a> { } } -impl<'a> ListenerMap for ForStatementInit<'a> { - fn report_effects(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for ForStatementInit<'a> { + fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { match self { match_expression!(Self) => self.to_expression().report_effects(options), Self::VariableDeclaration(decl) => { @@ -190,8 +190,8 @@ impl<'a> ListenerMap for ForStatementInit<'a> { } } -impl<'a> ListenerMap for ExportSpecifier<'a> { - fn report_effects(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for ExportSpecifier<'a> { + fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { let ctx = options.ctx; let symbol_table = ctx.symbols(); if has_comment_about_side_effect_check(self.exported.span(), ctx) { @@ -220,8 +220,8 @@ impl<'a> ListenerMap for ExportSpecifier<'a> { // we don't need implement all AstNode // it's same as `reportSideEffectsInDefinitionWhenCalled` in eslint-plugin-tree-shaking // -impl<'a> ListenerMap for AstNode<'a> { - fn report_effects_when_called(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for AstNode<'a> { + fn report_effects_when_called(&self, options: &NodeListenerOptions<'a, '_>) { match self.kind() { AstKind::VariableDeclarator(decl) => { if let Some(init) = &decl.init { @@ -273,7 +273,7 @@ impl<'a> ListenerMap for AstNode<'a> { } } - fn report_effects_when_mutated(&self, options: &NodeListenerOptions) { + fn report_effects_when_mutated(&self, options: &NodeListenerOptions<'a, '_>) { match self.kind() { AstKind::VariableDeclarator(decl) => { if let Some(init) = &decl.init { @@ -315,8 +315,8 @@ fn report_on_imported_call(span: Span, name: &str, node_id: NodeId, options: &No options.ctx.diagnostic(super::call_import(span)); } -impl<'a> ListenerMap for Declaration<'a> { - fn report_effects(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for Declaration<'a> { + fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { match self { Self::VariableDeclaration(decl) => { decl.declarations.iter().for_each(|decl| decl.report_effects(options)); @@ -336,15 +336,15 @@ impl<'a> ListenerMap for Declaration<'a> { } } -impl<'a> ListenerMap for Class<'a> { - fn report_effects(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for Class<'a> { + fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { if let Some(super_class) = &self.super_class { super_class.report_effects(options); } self.body.report_effects(options); } - fn report_effects_when_called(&self, options: &NodeListenerOptions) { + fn report_effects_when_called(&self, options: &NodeListenerOptions<'a, '_>) { if let Some(super_class) = &self.super_class { super_class.report_effects_when_called(options); } @@ -352,14 +352,14 @@ impl<'a> ListenerMap for Class<'a> { } } -impl<'a> ListenerMap for ClassBody<'a> { - fn report_effects(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for ClassBody<'a> { + fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { self.body.iter().for_each(|class_element| { class_element.report_effects(options); }); } - fn report_effects_when_called(&self, options: &NodeListenerOptions) { + fn report_effects_when_called(&self, options: &NodeListenerOptions<'a, '_>) { let constructor = self.body.iter().find(|class_element| { if let ClassElement::MethodDefinition(definition) = class_element { return definition.kind.is_constructor(); @@ -383,8 +383,8 @@ impl<'a> ListenerMap for ClassBody<'a> { } } -impl<'a> ListenerMap for ClassElement<'a> { - fn report_effects(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for ClassElement<'a> { + fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { match self { Self::MethodDefinition(method) => { method.key.report_effects(options); @@ -396,7 +396,7 @@ impl<'a> ListenerMap for ClassElement<'a> { } } - fn report_effects_when_called(&self, options: &NodeListenerOptions) { + fn report_effects_when_called(&self, options: &NodeListenerOptions<'a, '_>) { match self { Self::MethodDefinition(method) => { method.value.report_effects_when_called(options); @@ -411,8 +411,8 @@ impl<'a> ListenerMap for ClassElement<'a> { } } -impl<'a> ListenerMap for PropertyKey<'a> { - fn report_effects(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for PropertyKey<'a> { + fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { match self.as_expression() { Some(expr) => expr.report_effects(options), None => no_effects(), @@ -420,8 +420,8 @@ impl<'a> ListenerMap for PropertyKey<'a> { } } -impl<'a> ListenerMap for VariableDeclarator<'a> { - fn report_effects(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for VariableDeclarator<'a> { + fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { self.id.report_effects(options); if has_comment_about_side_effect_check(self.id.span(), options.ctx) { self.id.report_effects_when_called(options); @@ -433,8 +433,8 @@ impl<'a> ListenerMap for VariableDeclarator<'a> { } } -impl<'a> ListenerMap for BindingPattern<'a> { - fn report_effects(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for BindingPattern<'a> { + fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { match &self.kind { BindingPatternKind::BindingIdentifier(_) => {} BindingPatternKind::ArrayPattern(array) => { @@ -457,19 +457,19 @@ impl<'a> ListenerMap for BindingPattern<'a> { } } - fn report_effects_when_called(&self, options: &NodeListenerOptions) { + fn report_effects_when_called(&self, options: &NodeListenerOptions<'a, '_>) { if let BindingPatternKind::BindingIdentifier(ident) = &self.kind { ident.report_effects_when_called(options); } } } -impl<'a> ListenerMap for BindingIdentifier<'a> { - fn report_effects(&self, _options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for BindingIdentifier<'a> { + fn report_effects(&self, _options: &NodeListenerOptions<'a, '_>) { no_effects(); } - fn report_effects_when_called(&self, options: &NodeListenerOptions) { + fn report_effects_when_called(&self, options: &NodeListenerOptions<'a, '_>) { let ctx = options.ctx; if let Some(symbol_id) = self.symbol_id.get() { let symbol_table = ctx.semantic().symbols(); @@ -487,8 +487,8 @@ impl<'a> ListenerMap for BindingIdentifier<'a> { } } -impl<'a> ListenerMap for Expression<'a> { - fn report_effects(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for Expression<'a> { + fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { match self { Self::ArrayExpression(array_expr) => { array_expr.elements.iter().for_each(|el| el.report_effects(options)); @@ -569,7 +569,7 @@ impl<'a> ListenerMap for Expression<'a> { } } - fn report_effects_when_mutated(&self, options: &NodeListenerOptions) { + fn report_effects_when_mutated(&self, options: &NodeListenerOptions<'a, '_>) { match self { Self::Identifier(ident) => { ident.report_effects_when_mutated(options); @@ -591,7 +591,7 @@ impl<'a> ListenerMap for Expression<'a> { } } - fn report_effects_when_called(&self, options: &NodeListenerOptions) { + fn report_effects_when_called(&self, options: &NodeListenerOptions<'a, '_>) { match self { Self::CallExpression(expr) => { expr.report_effects_when_called(options); @@ -631,7 +631,7 @@ impl<'a> ListenerMap for Expression<'a> { } } - fn get_value_and_report_effects(&self, options: &NodeListenerOptions) -> Value { + fn get_value_and_report_effects(&self, options: &NodeListenerOptions<'a, '_>) -> Value { match self { Self::BooleanLiteral(_) | Self::StringLiteral(_) @@ -665,8 +665,8 @@ fn defined_custom_report_effects_when_called(expr: &Expression) -> bool { ) } -impl<'a> ListenerMap for SwitchCase<'a> { - fn report_effects(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for SwitchCase<'a> { + fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { if let Some(test) = &self.test { test.report_effects(options); } @@ -676,8 +676,8 @@ impl<'a> ListenerMap for SwitchCase<'a> { } } -impl<'a> ListenerMap for SequenceExpression<'a> { - fn get_value_and_report_effects(&self, options: &NodeListenerOptions) -> Value { +impl<'a> ListenerMap<'a> for SequenceExpression<'a> { + fn get_value_and_report_effects(&self, options: &NodeListenerOptions<'a, '_>) -> Value { let mut val = Value::Unknown; for expr in &self.expressions { val = expr.get_value_and_report_effects(options); @@ -686,8 +686,8 @@ impl<'a> ListenerMap for SequenceExpression<'a> { } } -impl<'a> ListenerMap for UnaryExpression<'a> { - fn get_value_and_report_effects(&self, options: &NodeListenerOptions) -> Value { +impl<'a> ListenerMap<'a> for UnaryExpression<'a> { + fn get_value_and_report_effects(&self, options: &NodeListenerOptions<'a, '_>) -> Value { if self.operator == UnaryOperator::Delete { match &self.argument { Expression::StaticMemberExpression(expr) => { @@ -709,8 +709,8 @@ impl<'a> ListenerMap for UnaryExpression<'a> { } } -impl<'a> ListenerMap for LogicalExpression<'a> { - fn get_value_and_report_effects(&self, options: &NodeListenerOptions) -> Value { +impl<'a> ListenerMap<'a> for LogicalExpression<'a> { + fn get_value_and_report_effects(&self, options: &NodeListenerOptions<'a, '_>) -> Value { let left = self.left.get_value_and_report_effects(options); // `false && foo` if self.operator == LogicalOperator::And @@ -729,8 +729,8 @@ impl<'a> ListenerMap for LogicalExpression<'a> { } } -impl<'a> ListenerMap for ObjectExpression<'a> { - fn report_effects(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for ObjectExpression<'a> { + fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { self.properties.iter().for_each(|property| match property { ObjectPropertyKind::ObjectProperty(p) => { p.key.report_effects(options); @@ -743,8 +743,8 @@ impl<'a> ListenerMap for ObjectExpression<'a> { } } -impl<'a> ListenerMap for JSXElement<'a> { - fn report_effects(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for JSXElement<'a> { + fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { self.opening_element.report_effects(options); self.children.iter().for_each(|child| { child.report_effects(options); @@ -752,8 +752,8 @@ impl<'a> ListenerMap for JSXElement<'a> { } } -impl<'a> ListenerMap for JSXChild<'a> { - fn report_effects(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for JSXChild<'a> { + fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { match self { JSXChild::Element(element) => { element.report_effects(options); @@ -774,15 +774,15 @@ impl<'a> ListenerMap for JSXChild<'a> { } } -impl<'a> ListenerMap for JSXOpeningElement<'a> { - fn report_effects(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for JSXOpeningElement<'a> { + fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { self.name.report_effects_when_called(options); self.attributes.iter().for_each(|attr| attr.report_effects(options)); } } -impl<'a> ListenerMap for JSXElementName<'a> { - fn report_effects_when_called(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for JSXElementName<'a> { + fn report_effects_when_called(&self, options: &NodeListenerOptions<'a, '_>) { match self { Self::Identifier(_) | Self::NamespacedName(_) => {} Self::IdentifierReference(ident) => ident.report_effects_when_called(options), @@ -792,14 +792,14 @@ impl<'a> ListenerMap for JSXElementName<'a> { } } -impl<'a> ListenerMap for JSXMemberExpression<'a> { - fn report_effects_when_called(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for JSXMemberExpression<'a> { + fn report_effects_when_called(&self, options: &NodeListenerOptions<'a, '_>) { options.ctx.diagnostic(super::call_member(self.property.span())); } } -impl<'a> ListenerMap for JSXAttributeItem<'a> { - fn report_effects(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for JSXAttributeItem<'a> { + fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { match self { Self::Attribute(attribute) => { attribute.report_effects(options); @@ -811,8 +811,8 @@ impl<'a> ListenerMap for JSXAttributeItem<'a> { } } -impl<'a> ListenerMap for JSXAttribute<'a> { - fn report_effects(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for JSXAttribute<'a> { + fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { if let Some(value) = &self.value { match value { JSXAttributeValue::ExpressionContainer(container) => { @@ -832,14 +832,14 @@ impl<'a> ListenerMap for JSXAttribute<'a> { } } -impl<'a> ListenerMap for JSXExpressionContainer<'a> { - fn report_effects(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for JSXExpressionContainer<'a> { + fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { self.expression.report_effects(options); } } -impl<'a> ListenerMap for JSXExpression<'a> { - fn report_effects(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for JSXExpression<'a> { + fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { match self { Self::ArrayExpression(array_expr) => { array_expr.elements.iter().for_each(|el| el.report_effects(options)); @@ -902,14 +902,14 @@ impl<'a> ListenerMap for JSXExpression<'a> { } } -impl<'a> ListenerMap for JSXFragment<'a> { - fn report_effects(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for JSXFragment<'a> { + fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { self.children.iter().for_each(|child| child.report_effects(options)); } } -impl<'a> ListenerMap for ConditionalExpression<'a> { - fn get_value_and_report_effects(&self, options: &NodeListenerOptions) -> Value { +impl<'a> ListenerMap<'a> for ConditionalExpression<'a> { + fn get_value_and_report_effects(&self, options: &NodeListenerOptions<'a, '_>) -> Value { let test_result = self.test.get_value_and_report_effects(options); if let Some(is_falsy) = test_result.get_falsy_value() { @@ -925,7 +925,7 @@ impl<'a> ListenerMap for ConditionalExpression<'a> { } } - fn report_effects_when_called(&self, options: &NodeListenerOptions) { + fn report_effects_when_called(&self, options: &NodeListenerOptions<'a, '_>) { let test_result = self.test.get_value_and_report_effects(options); if let Some(falsy) = test_result.get_falsy_value() { @@ -941,24 +941,24 @@ impl<'a> ListenerMap for ConditionalExpression<'a> { } } -impl<'a> ListenerMap for BinaryExpression<'a> { - fn get_value_and_report_effects(&self, options: &NodeListenerOptions) -> Value { +impl<'a> ListenerMap<'a> for BinaryExpression<'a> { + fn get_value_and_report_effects(&self, options: &NodeListenerOptions<'a, '_>) -> Value { let left = self.left.get_value_and_report_effects(options); let right = self.right.get_value_and_report_effects(options); calculate_binary_operation(self.operator, left, right) } } -impl ListenerMap for ThisExpression { - fn report_effects_when_mutated(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for ThisExpression { + fn report_effects_when_mutated(&self, options: &NodeListenerOptions<'a, '_>) { if !options.has_valid_this.get() { options.ctx.diagnostic(super::mutate_of_this(self.span)); } } } -impl<'a> ListenerMap for NewExpression<'a> { - fn report_effects(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for NewExpression<'a> { + fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { if has_pure_notation(self.span, options.ctx) { return; } @@ -970,37 +970,37 @@ impl<'a> ListenerMap for NewExpression<'a> { } } -impl<'a> ListenerMap for ParenthesizedExpression<'a> { - fn report_effects(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for ParenthesizedExpression<'a> { + fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { self.expression.report_effects(options); } - fn report_effects_when_assigned(&self, options: &NodeListenerOptions) { + fn report_effects_when_assigned(&self, options: &NodeListenerOptions<'a, '_>) { self.expression.report_effects_when_assigned(options); } - fn report_effects_when_called(&self, options: &NodeListenerOptions) { + fn report_effects_when_called(&self, options: &NodeListenerOptions<'a, '_>) { self.expression.report_effects_when_called(options); } - fn report_effects_when_mutated(&self, options: &NodeListenerOptions) { + fn report_effects_when_mutated(&self, options: &NodeListenerOptions<'a, '_>) { self.expression.report_effects_when_mutated(options); } - fn get_value_and_report_effects(&self, options: &NodeListenerOptions) -> Value { + fn get_value_and_report_effects(&self, options: &NodeListenerOptions<'a, '_>) -> Value { self.expression.get_value_and_report_effects(options) } } -impl<'a> ListenerMap for ArrowFunctionExpression<'a> { - fn report_effects_when_called(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for ArrowFunctionExpression<'a> { + fn report_effects_when_called(&self, options: &NodeListenerOptions<'a, '_>) { self.params.items.iter().for_each(|param| param.report_effects(options)); self.body.statements.iter().for_each(|stmt| stmt.report_effects(options)); } } -impl<'a> ListenerMap for Function<'a> { - fn report_effects_when_called(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for Function<'a> { + fn report_effects_when_called(&self, options: &NodeListenerOptions<'a, '_>) { self.params.items.iter().for_each(|param| param.report_effects(options)); if let Some(body) = &self.body { @@ -1009,14 +1009,14 @@ impl<'a> ListenerMap for Function<'a> { } } -impl<'a> ListenerMap for FormalParameter<'a> { - fn report_effects(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for FormalParameter<'a> { + fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { self.pattern.report_effects(options); } } -impl<'a> ListenerMap for CallExpression<'a> { - fn report_effects(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for CallExpression<'a> { + fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { self.arguments.iter().for_each(|arg| arg.report_effects(options)); if defined_custom_report_effects_when_called(&self.callee) { let old_value = options.called_with_new.get(); @@ -1028,7 +1028,7 @@ impl<'a> ListenerMap for CallExpression<'a> { } } - fn report_effects_when_called(&self, options: &NodeListenerOptions) { + fn report_effects_when_called(&self, options: &NodeListenerOptions<'a, '_>) { let ctx = options.ctx; if let Expression::Identifier(ident) = &self.callee { if let Some(node) = get_declaration_of_variable(ident, ctx) { @@ -1042,13 +1042,13 @@ impl<'a> ListenerMap for CallExpression<'a> { } } - fn report_effects_when_mutated(&self, options: &NodeListenerOptions) { + fn report_effects_when_mutated(&self, options: &NodeListenerOptions<'a, '_>) { options.ctx.diagnostic(super::mutate_function_return_value(self.span)); } } -impl<'a> ListenerMap for Argument<'a> { - fn report_effects(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for Argument<'a> { + fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { match self { match_expression!(Self) => self.to_expression().report_effects(options), Self::SpreadElement(spread) => { @@ -1058,8 +1058,8 @@ impl<'a> ListenerMap for Argument<'a> { } } -impl<'a> ListenerMap for AssignmentTarget<'a> { - fn report_effects_when_assigned(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for AssignmentTarget<'a> { + fn report_effects_when_assigned(&self, options: &NodeListenerOptions<'a, '_>) { match self { match_simple_assignment_target!(Self) => { self.to_simple_assignment_target().report_effects_when_assigned(options); @@ -1069,8 +1069,8 @@ impl<'a> ListenerMap for AssignmentTarget<'a> { } } -impl<'a> ListenerMap for SimpleAssignmentTarget<'a> { - fn report_effects_when_assigned(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for SimpleAssignmentTarget<'a> { + fn report_effects_when_assigned(&self, options: &NodeListenerOptions<'a, '_>) { match self { Self::AssignmentTargetIdentifier(ident) => { ident.report_effects_when_assigned(options); @@ -1088,14 +1088,14 @@ impl<'a> ListenerMap for SimpleAssignmentTarget<'a> { } } -impl<'a> ListenerMap for IdentifierReference<'a> { - fn report_effects_when_assigned(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for IdentifierReference<'a> { + fn report_effects_when_assigned(&self, options: &NodeListenerOptions<'a, '_>) { if get_symbol_id_of_variable(self, options.ctx).is_none() { options.ctx.diagnostic(super::assignment(self.name.as_str(), self.span)); } } - fn report_effects_when_called(&self, options: &NodeListenerOptions) { + fn report_effects_when_called(&self, options: &NodeListenerOptions<'a, '_>) { if is_pure_function(&FunctionName::Identifier(self), options) { return; } @@ -1150,7 +1150,7 @@ impl<'a> ListenerMap for IdentifierReference<'a> { } } - fn report_effects_when_mutated(&self, options: &NodeListenerOptions) { + fn report_effects_when_mutated(&self, options: &NodeListenerOptions<'a, '_>) { let ctx = options.ctx; if let Some(symbol_id) = get_symbol_id_of_variable(self, ctx) { if options.insert_mutated_node(symbol_id) { @@ -1173,8 +1173,8 @@ impl<'a> ListenerMap for IdentifierReference<'a> { } } -impl<'a> ListenerMap for MemberExpression<'a> { - fn report_effects(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for MemberExpression<'a> { + fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { match self { Self::ComputedMemberExpression(expr) => { expr.report_effects(options); @@ -1188,7 +1188,7 @@ impl<'a> ListenerMap for MemberExpression<'a> { } } - fn report_effects_when_assigned(&self, options: &NodeListenerOptions) { + fn report_effects_when_assigned(&self, options: &NodeListenerOptions<'a, '_>) { match self { Self::ComputedMemberExpression(expr) => { expr.report_effects_when_assigned(options); @@ -1202,7 +1202,7 @@ impl<'a> ListenerMap for MemberExpression<'a> { } } - fn report_effects_when_called(&self, options: &NodeListenerOptions) { + fn report_effects_when_called(&self, options: &NodeListenerOptions<'a, '_>) { match self { Self::ComputedMemberExpression(expr) => { expr.report_effects_when_called(options); @@ -1217,13 +1217,13 @@ impl<'a> ListenerMap for MemberExpression<'a> { } } -impl<'a> ListenerMap for ComputedMemberExpression<'a> { - fn report_effects(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for ComputedMemberExpression<'a> { + fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { self.expression.report_effects(options); self.object.report_effects(options); } - fn report_effects_when_called(&self, options: &NodeListenerOptions) { + fn report_effects_when_called(&self, options: &NodeListenerOptions<'a, '_>) { self.report_effects(options); let mut node = &self.object; @@ -1247,18 +1247,18 @@ impl<'a> ListenerMap for ComputedMemberExpression<'a> { } } - fn report_effects_when_assigned(&self, options: &NodeListenerOptions) { + fn report_effects_when_assigned(&self, options: &NodeListenerOptions<'a, '_>) { self.report_effects(options); self.object.report_effects_when_mutated(options); } } -impl<'a> ListenerMap for StaticMemberExpression<'a> { - fn report_effects(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for StaticMemberExpression<'a> { + fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { self.object.report_effects(options); } - fn report_effects_when_called(&self, options: &NodeListenerOptions) { + fn report_effects_when_called(&self, options: &NodeListenerOptions<'a, '_>) { self.report_effects(options); let mut root_member_expr = &self.object; @@ -1300,18 +1300,18 @@ impl<'a> ListenerMap for StaticMemberExpression<'a> { options.ctx.diagnostic(super::call_member(self.span)); } - fn report_effects_when_assigned(&self, options: &NodeListenerOptions) { + fn report_effects_when_assigned(&self, options: &NodeListenerOptions<'a, '_>) { self.report_effects(options); self.object.report_effects_when_mutated(options); } } -impl<'a> ListenerMap for PrivateFieldExpression<'a> { - fn report_effects(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for PrivateFieldExpression<'a> { + fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { self.object.report_effects(options); } - fn report_effects_when_called(&self, options: &NodeListenerOptions) { + fn report_effects_when_called(&self, options: &NodeListenerOptions<'a, '_>) { self.report_effects(options); let mut node = &self.object; @@ -1335,14 +1335,14 @@ impl<'a> ListenerMap for PrivateFieldExpression<'a> { } } - fn report_effects_when_assigned(&self, options: &NodeListenerOptions) { + fn report_effects_when_assigned(&self, options: &NodeListenerOptions<'a, '_>) { self.report_effects(options); self.object.report_effects_when_mutated(options); } } -impl<'a> ListenerMap for ArrayExpressionElement<'a> { - fn report_effects(&self, options: &NodeListenerOptions) { +impl<'a> ListenerMap<'a> for ArrayExpressionElement<'a> { + fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { match self { match_expression!(Self) => self.to_expression().report_effects(options), Self::SpreadElement(spreed) => { diff --git a/crates/oxc_linter/src/rules/unicorn/no_typeof_undefined.rs b/crates/oxc_linter/src/rules/unicorn/no_typeof_undefined.rs index 3728e0df0..de4f6bf6d 100644 --- a/crates/oxc_linter/src/rules/unicorn/no_typeof_undefined.rs +++ b/crates/oxc_linter/src/rules/unicorn/no_typeof_undefined.rs @@ -85,7 +85,7 @@ impl Rule for NoTypeofUndefined { } } -fn is_global_variable(ident: &Expression, ctx: &LintContext) -> bool { +fn is_global_variable<'a>(ident: &Expression<'a>, ctx: &LintContext<'a>) -> bool { let Expression::Identifier(ident) = ident else { return false; }; diff --git a/crates/oxc_linter/src/rules/unicorn/prefer_set_size.rs b/crates/oxc_linter/src/rules/unicorn/prefer_set_size.rs index f379ba70b..80f3bfbb4 100644 --- a/crates/oxc_linter/src/rules/unicorn/prefer_set_size.rs +++ b/crates/oxc_linter/src/rules/unicorn/prefer_set_size.rs @@ -91,7 +91,7 @@ impl Rule for PreferSetSize { } } -fn is_set(maybe_set: &Expression, ctx: &LintContext) -> bool { +fn is_set<'a>(maybe_set: &Expression<'a>, ctx: &LintContext<'a>) -> bool { if let Expression::NewExpression(new_expr) = maybe_set { if let Expression::Identifier(identifier) = &new_expr.callee { return identifier.name == "Set";