|
1 | 1 | use oxc_ast::{ |
2 | 2 | AstKind, |
3 | | - ast::{Expression, UnaryOperator, match_member_expression}, |
| 3 | + ast::{Expression, UnaryExpression, UnaryOperator, match_member_expression}, |
4 | 4 | }; |
5 | 5 | use oxc_diagnostics::OxcDiagnostic; |
6 | 6 | use oxc_macros::declare_oxc_lint; |
@@ -127,57 +127,38 @@ impl Rule for PreferNumberProperties { |
127 | 127 | || (matches!(ident_name, "isNaN" | "isFinite" | "parseFloat" | "parseInt") |
128 | 128 | && matches!(ctx.nodes().parent_kind(node.id()), AstKind::ObjectProperty(_))) |
129 | 129 | { |
130 | | - let mut replacement = "Number.POSITIVE_INFINITY"; |
131 | | - let mut replace_span = ident_ref.span; |
132 | | - let fixer = |fixer: RuleFixer<'_, 'a>| { |
133 | | - if ident_name == "Infinity" { |
134 | | - let unary_expr = |
135 | | - ctx.nodes().ancestor_kinds(node.id()).find_map(|ancestor| { |
136 | | - if let AstKind::UnaryExpression(unary_expr) = ancestor { |
137 | | - Some(unary_expr) |
138 | | - } else { |
139 | | - None |
140 | | - } |
141 | | - }); |
142 | | - |
143 | | - if let Some(unary_expr) = unary_expr { |
144 | | - replacement = if matches!( |
145 | | - unary_expr.operator, |
146 | | - UnaryOperator::UnaryNegation |
147 | | - ) { |
148 | | - // -(Infinity) -> Number.NEGATIVE_INFINITY |
149 | | - // +(Infinity) -> +(Number.POSITIVE_INFINITY) |
150 | | - replace_span = unary_expr.span; |
151 | | - "Number.NEGATIVE_INFINITY" |
152 | | - } else { |
153 | | - "Number.POSITIVE_INFINITY" |
154 | | - }; |
155 | | - } |
156 | | - } |
157 | | - match ctx.nodes().parent_kind(node.id()) { |
158 | | - AstKind::ObjectProperty(object_property) |
159 | | - if object_property.shorthand => |
160 | | - { |
161 | | - if ident_name == "Infinity" { |
162 | | - fixer.insert_text_after( |
163 | | - &ident_ref.span, |
164 | | - format!(": {replacement}"), |
165 | | - ) |
166 | | - } else { |
167 | | - fixer.insert_text_before( |
168 | | - &ident_ref.span, |
169 | | - format!("{}: Number.", ident_ref.name.as_str()), |
170 | | - ) |
171 | | - } |
172 | | - } |
173 | | - _ => { |
174 | | - if ident_name == "Infinity" { |
175 | | - fixer.replace(replace_span, replacement) |
176 | | - } else { |
177 | | - fixer.insert_text_before(&ident_ref.span, "Number.") |
| 130 | + let (replacement_span, replacement_text) = if ident_name == "Infinity" { |
| 131 | + if let Some(unary) = find_ancestor_unary(node, ctx) { |
| 132 | + match unary.operator { |
| 133 | + UnaryOperator::UnaryNegation => { |
| 134 | + (unary.span, "Number.NEGATIVE_INFINITY") |
178 | 135 | } |
| 136 | + _ => (ident_ref.span, "Number.POSITIVE_INFINITY"), |
179 | 137 | } |
| 138 | + } else { |
| 139 | + (ident_ref.span, "Number.POSITIVE_INFINITY") |
| 140 | + } |
| 141 | + } else { |
| 142 | + (ident_ref.span, "") |
| 143 | + }; |
| 144 | + |
| 145 | + let fixer = |fixer: RuleFixer<'_, 'a>| match ctx.nodes().parent_kind(node.id()) |
| 146 | + { |
| 147 | + AstKind::ObjectProperty(prop) |
| 148 | + if prop.shorthand && ident_name == "Infinity" => |
| 149 | + { |
| 150 | + fixer |
| 151 | + .insert_text_after(&ident_ref.span, format!(": {replacement_text}")) |
180 | 152 | } |
| 153 | + AstKind::ObjectProperty(prop) if prop.shorthand => fixer |
| 154 | + .insert_text_before( |
| 155 | + &ident_ref.span, |
| 156 | + format!("{}: Number.", ident_name), |
| 157 | + ), |
| 158 | + _ if ident_name == "Infinity" => { |
| 159 | + fixer.replace(replacement_span, replacement_text) |
| 160 | + } |
| 161 | + _ => fixer.insert_text_before(&ident_ref.span, "Number."), |
181 | 162 | }; |
182 | 163 |
|
183 | 164 | if ident_name == "isNaN" || ident_name == "isFinite" { |
@@ -241,6 +222,16 @@ impl Rule for PreferNumberProperties { |
241 | 222 | } |
242 | 223 | } |
243 | 224 |
|
| 225 | +/// Finds the nearest enclosing unary expression ancestor for `node`. |
| 226 | +fn find_ancestor_unary<'a>( |
| 227 | + node: &AstNode<'a>, |
| 228 | + ctx: &LintContext<'a>, |
| 229 | +) -> Option<&'a UnaryExpression<'a>> { |
| 230 | + ctx.nodes().ancestor_kinds(node.id()).find_map(|ancestor| { |
| 231 | + if let AstKind::UnaryExpression(unary_expr) = ancestor { Some(unary_expr) } else { None } |
| 232 | + }) |
| 233 | +} |
| 234 | + |
244 | 235 | fn extract_ident_from_expression<'b>(expr: &'b Expression<'_>) -> Option<&'b str> { |
245 | 236 | match expr { |
246 | 237 | Expression::Identifier(ident_name) => Some(ident_name.name.as_str()), |
|
0 commit comments