From 2cf143b85a2ee63350da982db95bfcabaead7d97 Mon Sep 17 00:00:00 2001 From: Victorien Elvinger Date: Mon, 28 Oct 2024 22:37:51 +0100 Subject: [PATCH] fix(useArrayLiterals): check all expressions and add a fix --- CHANGELOG.md | 26 ++ .../lint/correctness/use_array_literals.rs | 133 ++++--- .../correctness/useArrayLiterals/invalid.js | 31 +- .../useArrayLiterals/invalid.js.snap | 344 +++++++++++++++--- .../correctness/useArrayLiterals/valid.js | 2 + .../useArrayLiterals/valid.js.snap | 3 + crates/biome_js_syntax/src/expr_ext.rs | 25 +- 7 files changed, 457 insertions(+), 107 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fad0a944e1c2..c1b0926a9db4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -82,6 +82,32 @@ our [guidelines for writing a good changelog entry](https://github.com/biomejs/b #### Enhancements - `useExportType` and `useImportType` now ignore TypeScript declaration files ([#4416](https://github.com/biomejs/biome/pull/4416)). Contributed by @Conaclos +- [useArrayLiterals](https://biomejs.dev/linter/rules/use-array-literals/) now provides a code fix. + + ```diff + - const xs = new Array(); + + const xs = []; + ``` + + The code fix is currently marked as unsafe. + We plan to make it safe in a future release of Biome. + + Contributed by @Conaclos + +#### Bug fixes + +- [useArrayLiterals](https://biomejs.dev/linter/rules/use-array-literals/) now reports all expressions using the `Array` constructors. + + Previously, the rule reported only use of the `Array` constructor in expressions statements. + + ```js + // This was reported + new Array(); + // This was not reported + const xs = new Array(); + ``` + + Contributed by @Conaclos ### Parser diff --git a/crates/biome_js_analyze/src/lint/correctness/use_array_literals.rs b/crates/biome_js_analyze/src/lint/correctness/use_array_literals.rs index 404d49bd973b..fc359428d1b0 100644 --- a/crates/biome_js_analyze/src/lint/correctness/use_array_literals.rs +++ b/crates/biome_js_analyze/src/lint/correctness/use_array_literals.rs @@ -1,9 +1,15 @@ use biome_analyze::{ - context::RuleContext, declare_lint_rule, Ast, FixKind, Rule, RuleDiagnostic, RuleSource, + context::RuleContext, declare_lint_rule, ActionCategory, FixKind, Rule, RuleDiagnostic, + RuleSource, }; use biome_console::markup; -use biome_js_syntax::{AnyJsCallArgument, AnyJsExpression, JsCallArguments, JsExpressionStatement}; -use biome_rowan::AstNode; +use biome_js_factory::make; +use biome_js_syntax::{ + global_identifier, AnyJsCallArgument, AnyJsExpression, JsNewOrCallExpression, JsSyntaxKind, T, +}; +use biome_rowan::{AstNode, AstSeparatedList, BatchMutationExt}; + +use crate::{services::semantic::Semantic, JsRuleAction}; declare_lint_rule! { /// Disallow Array constructors. @@ -16,29 +22,29 @@ declare_lint_rule! { /// ### Invalid /// /// ```js,expect_diagnostic - /// Array(); + /// const xs = Array(); /// ``` /// /// ```js,expect_diagnostic - /// Array(0, 1, 2); + /// const xs = Array(0, 1, 2); /// ``` /// /// ```js,expect_diagnostic - /// new Array(0, 1, 2); + /// const xs = new Array(0, 1, 2); /// ``` /// /// ```js,expect_diagnostic - /// Array(...args); + /// const xs = Array(...args); /// ``` /// /// ### Valid /// /// ```js - /// Array(500); + /// const xs = Array(65000); /// ``` /// /// ```js - /// [0, 1, 2]; + /// const xs = [0, 1, 2]; /// ``` /// pub UseArrayLiterals { @@ -52,29 +58,41 @@ declare_lint_rule! { } impl Rule for UseArrayLiterals { - type Query = Ast; + type Query = Semantic; type State = (); type Signals = Option; type Options = (); fn run(ctx: &RuleContext) -> Self::Signals { - let expression_statement = ctx.query(); - - let expression = expression_statement.expression().ok()?; - - match expression { - AnyJsExpression::JsCallExpression(call_expression) => { - let callee = call_expression.callee().ok()?; - let arguments = call_expression.arguments().ok()?; - validate(&callee, &arguments) - } - AnyJsExpression::JsNewExpression(new_expression) => { - let callee = new_expression.callee().ok()?; - let arguments = new_expression.arguments()?; - validate(&callee, &arguments) - } - _ => None, + let node = ctx.query(); + let callee = node.callee().ok()?.omit_parentheses(); + let (reference, name) = global_identifier(&callee)?; + if name.text() != "Array" || ctx.model().binding(&reference).is_some() { + return None; + } + if callee.syntax() != reference.syntax() + && !reference + .value_token() + .is_ok_and(|name| matches!(name.text_trimmed(), "globalThis" | "window" | "Array")) + { + return None; + } + let Some(arguments) = node.arguments() else { + return if matches!(node, JsNewOrCallExpression::JsNewExpression(_)) { + // Report `new Array` + Some(()) + } else { + // ignore `Array` + None + }; + }; + let [arg1, arg2] = arguments.get_arguments_by_index([0, 1]); + if arg1.is_some() && arg2.is_none() && !matches!(arg1?, AnyJsCallArgument::JsSpread(_)) { + // Ignore `Array(length)` + return None; } + // Report `Array()`, `Array(x, y)`, and `Array(...xs)` + Some(()) } fn diagnostic(ctx: &RuleContext, _state: &Self::State) -> Option { @@ -84,31 +102,56 @@ impl Rule for UseArrayLiterals { rule_category!(), node.range(), markup! { - "Don't use Array constructors." + "Use an array literal instead of the ""Array"" constructor." }, ) .note(markup! { - "Use of the Array constructor is not allowed except creating sparse arrays of a specified size by giving a single numeric argument." - }) - .note(markup! { - "The array literal notation [] is preferable." + "The ""Array"" constructor is misleading because it can be used to preallocate an array of a given length or to create an array with a given list of elements." }), ) } -} -fn validate(callee: &AnyJsExpression, arguments: &JsCallArguments) -> Option<()> { - if callee.text() != "Array" { - return None; - } - let mut args_iter = arguments.args().into_iter(); - let first_arg = args_iter.next(); - let second_arg = args_iter.next(); - if first_arg.is_some() - && second_arg.is_none() - && !matches!(first_arg?.ok()?, AnyJsCallArgument::JsSpread(_)) - { - return None; + fn action(ctx: &RuleContext, _: &Self::State) -> Option { + let node = ctx.query(); + if node + .syntax() + .parent() + .is_some_and(|parent| parent.kind() == JsSyntaxKind::JS_EXPRESSION_STATEMENT) + { + // Ignore useless expression statements. + // This avoids issues with missing semicolons. + return None; + } + let mut mutation = ctx.root().begin(); + let new_node = if let Some(args) = node.arguments() { + let l_paren_trailing_trivia = args.l_paren_token().ok()?.trailing_trivia().pieces(); + let r_paren_leading_trivia = args.r_paren_token().ok()?.leading_trivia().pieces(); + let args = args.args(); + let items = args + .elements() + .flat_map(|item| item.into_node()) + .map(|item| item.into()) + .collect::>(); + let separators = args.separators().flatten().collect::>(); + make::js_array_expression( + make::token(T!['[']).append_trivia_pieces(l_paren_trailing_trivia), + make::js_array_element_list(items, separators), + make::token(T![']']).prepend_trivia_pieces(r_paren_leading_trivia), + ) + } else { + // `new Array` -> `[]` + make::js_array_expression( + make::token(T!['[']), + make::js_array_element_list([], []), + make::token(T![']']), + ) + }; + mutation.replace_node::(node.clone().into(), new_node.into()); + Some(JsRuleAction::new( + ActionCategory::QuickFix, + ctx.metadata().applicability(), + markup! { "Use an array literal." }.to_owned(), + mutation, + )) } - Some(()) } diff --git a/crates/biome_js_analyze/tests/specs/correctness/useArrayLiterals/invalid.js b/crates/biome_js_analyze/tests/specs/correctness/useArrayLiterals/invalid.js index 24ff1f4ee511..dbe160d13a55 100644 --- a/crates/biome_js_analyze/tests/specs/correctness/useArrayLiterals/invalid.js +++ b/crates/biome_js_analyze/tests/specs/correctness/useArrayLiterals/invalid.js @@ -1,11 +1,30 @@ -Array(); +var xs = Array(); -Array(0, 1, 2); +var xs = Array(0, 1, 2); -Array(...args); +var xs = Array(...args); -new Array(); +var xs = new Array; -new Array(0, 1, 2); +var xs = new Array(); -new Array(...args); +var xs = new Array(0, 1, 2); + +var xs = new Array(...args); + +var xs = /**A*/ new /**B*/ Array /**C*/ ( /**D*/ 0 /**E*/, /**F*/ 1 /**G*/) /**H*/; + +var xs = (Array)( + /* foo */ a, + b = c() // bar +); + +var xs = Array?.(); + +// ASI +foo +new Array + +var xs = globalThis.Array(); + +var xs = window.Array(); diff --git a/crates/biome_js_analyze/tests/specs/correctness/useArrayLiterals/invalid.js.snap b/crates/biome_js_analyze/tests/specs/correctness/useArrayLiterals/invalid.js.snap index 6c34575e8f17..4420c15a7a5c 100644 --- a/crates/biome_js_analyze/tests/specs/correctness/useArrayLiterals/invalid.js.snap +++ b/crates/biome_js_analyze/tests/specs/correctness/useArrayLiterals/invalid.js.snap @@ -1,131 +1,371 @@ --- source: crates/biome_js_analyze/tests/spec_tests.rs expression: invalid.js +snapshot_kind: text --- # Input ```jsx -Array(); +var xs = Array(); -Array(0, 1, 2); +var xs = Array(0, 1, 2); -Array(...args); +var xs = Array(...args); -new Array(); +var xs = new Array; -new Array(0, 1, 2); +var xs = new Array(); -new Array(...args); +var xs = new Array(0, 1, 2); + +var xs = new Array(...args); + +var xs = /**A*/ new /**B*/ Array /**C*/ ( /**D*/ 0 /**E*/, /**F*/ 1 /**G*/) /**H*/; + +var xs = (Array)( + /* foo */ a, + b = c() // bar +); + +var xs = Array?.(); + +// ASI +foo +new Array + +var xs = globalThis.Array(); + +var xs = window.Array(); ``` # Diagnostics ``` -invalid.js:1:1 lint/correctness/useArrayLiterals ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:1:10 lint/correctness/useArrayLiterals FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! Don't use Array constructors. + ! Use an array literal instead of the Array constructor. - > 1 │ Array(); - │ ^^^^^^^^ + > 1 │ var xs = Array(); + │ ^^^^^^^ 2 │ - 3 │ Array(0, 1, 2); + 3 │ var xs = Array(0, 1, 2); + + i The Array constructor is misleading because it can be used to preallocate an array of a given length or to create an array with a given list of elements. - i Use of the Array constructor is not allowed except creating sparse arrays of a specified size by giving a single numeric argument. + i Unsafe fix: Use an array literal. - i The array literal notation [] is preferable. + 1 │ - var·xs·=·Array(); + 1 │ + var·xs·=·[]; + 2 2 │ + 3 3 │ var xs = Array(0, 1, 2); ``` ``` -invalid.js:3:1 lint/correctness/useArrayLiterals ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:3:10 lint/correctness/useArrayLiterals FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! Don't use Array constructors. + ! Use an array literal instead of the Array constructor. - 1 │ Array(); + 1 │ var xs = Array(); 2 │ - > 3 │ Array(0, 1, 2); - │ ^^^^^^^^^^^^^^^ + > 3 │ var xs = Array(0, 1, 2); + │ ^^^^^^^^^^^^^^ 4 │ - 5 │ Array(...args); + 5 │ var xs = Array(...args); + + i The Array constructor is misleading because it can be used to preallocate an array of a given length or to create an array with a given list of elements. - i Use of the Array constructor is not allowed except creating sparse arrays of a specified size by giving a single numeric argument. + i Unsafe fix: Use an array literal. - i The array literal notation [] is preferable. + 1 1 │ var xs = Array(); + 2 2 │ + 3 │ - var·xs·=·Array(0,·1,·2); + 3 │ + var·xs·=·[0,·1,·2]; + 4 4 │ + 5 5 │ var xs = Array(...args); ``` ``` -invalid.js:5:1 lint/correctness/useArrayLiterals ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:5:10 lint/correctness/useArrayLiterals FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! Don't use Array constructors. + ! Use an array literal instead of the Array constructor. - 3 │ Array(0, 1, 2); + 3 │ var xs = Array(0, 1, 2); 4 │ - > 5 │ Array(...args); - │ ^^^^^^^^^^^^^^^ + > 5 │ var xs = Array(...args); + │ ^^^^^^^^^^^^^^ 6 │ - 7 │ new Array(); + 7 │ var xs = new Array; - i Use of the Array constructor is not allowed except creating sparse arrays of a specified size by giving a single numeric argument. + i The Array constructor is misleading because it can be used to preallocate an array of a given length or to create an array with a given list of elements. - i The array literal notation [] is preferable. + i Unsafe fix: Use an array literal. + + 3 3 │ var xs = Array(0, 1, 2); + 4 4 │ + 5 │ - var·xs·=·Array(...args); + 5 │ + var·xs·=·[...args]; + 6 6 │ + 7 7 │ var xs = new Array; ``` ``` -invalid.js:7:1 lint/correctness/useArrayLiterals ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:7:10 lint/correctness/useArrayLiterals FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! Don't use Array constructors. + ! Use an array literal instead of the Array constructor. - 5 │ Array(...args); + 5 │ var xs = Array(...args); 6 │ - > 7 │ new Array(); - │ ^^^^^^^^^^^^ + > 7 │ var xs = new Array; + │ ^^^^^^^^^ 8 │ - 9 │ new Array(0, 1, 2); + 9 │ var xs = new Array(); + + i The Array constructor is misleading because it can be used to preallocate an array of a given length or to create an array with a given list of elements. - i Use of the Array constructor is not allowed except creating sparse arrays of a specified size by giving a single numeric argument. + i Unsafe fix: Use an array literal. - i The array literal notation [] is preferable. + 5 5 │ var xs = Array(...args); + 6 6 │ + 7 │ - var·xs·=·new·Array; + 7 │ + var·xs·=·[]; + 8 8 │ + 9 9 │ var xs = new Array(); ``` ``` -invalid.js:9:1 lint/correctness/useArrayLiterals ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:9:10 lint/correctness/useArrayLiterals FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! Don't use Array constructors. + ! Use an array literal instead of the Array constructor. - 7 │ new Array(); + 7 │ var xs = new Array; 8 │ - > 9 │ new Array(0, 1, 2); - │ ^^^^^^^^^^^^^^^^^^^ + > 9 │ var xs = new Array(); + │ ^^^^^^^^^^^ 10 │ - 11 │ new Array(...args); + 11 │ var xs = new Array(0, 1, 2); - i Use of the Array constructor is not allowed except creating sparse arrays of a specified size by giving a single numeric argument. + i The Array constructor is misleading because it can be used to preallocate an array of a given length or to create an array with a given list of elements. - i The array literal notation [] is preferable. + i Unsafe fix: Use an array literal. + + 7 7 │ var xs = new Array; + 8 8 │ + 9 │ - var·xs·=·new·Array(); + 9 │ + var·xs·=·[]; + 10 10 │ + 11 11 │ var xs = new Array(0, 1, 2); ``` ``` -invalid.js:11:1 lint/correctness/useArrayLiterals ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:11:10 lint/correctness/useArrayLiterals FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! Don't use Array constructors. + ! Use an array literal instead of the Array constructor. - 9 │ new Array(0, 1, 2); + 9 │ var xs = new Array(); 10 │ - > 11 │ new Array(...args); - │ ^^^^^^^^^^^^^^^^^^^ + > 11 │ var xs = new Array(0, 1, 2); + │ ^^^^^^^^^^^^^^^^^^ 12 │ + 13 │ var xs = new Array(...args); + + i The Array constructor is misleading because it can be used to preallocate an array of a given length or to create an array with a given list of elements. + + i Unsafe fix: Use an array literal. + + 9 9 │ var xs = new Array(); + 10 10 │ + 11 │ - var·xs·=·new·Array(0,·1,·2); + 11 │ + var·xs·=·[0,·1,·2]; + 12 12 │ + 13 13 │ var xs = new Array(...args); + + +``` + +``` +invalid.js:13:10 lint/correctness/useArrayLiterals FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Use an array literal instead of the Array constructor. + + 11 │ var xs = new Array(0, 1, 2); + 12 │ + > 13 │ var xs = new Array(...args); + │ ^^^^^^^^^^^^^^^^^^ + 14 │ + 15 │ var xs = /**A*/ new /**B*/ Array /**C*/ ( /**D*/ 0 /**E*/, /**F*/ 1 /**G*/) /**H*/; + + i The Array constructor is misleading because it can be used to preallocate an array of a given length or to create an array with a given list of elements. + + i Unsafe fix: Use an array literal. + + 11 11 │ var xs = new Array(0, 1, 2); + 12 12 │ + 13 │ - var·xs·=·new·Array(...args); + 13 │ + var·xs·=·[...args]; + 14 14 │ + 15 15 │ var xs = /**A*/ new /**B*/ Array /**C*/ ( /**D*/ 0 /**E*/, /**F*/ 1 /**G*/) /**H*/; + + +``` + +``` +invalid.js:15:17 lint/correctness/useArrayLiterals FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Use an array literal instead of the Array constructor. + + 13 │ var xs = new Array(...args); + 14 │ + > 15 │ var xs = /**A*/ new /**B*/ Array /**C*/ ( /**D*/ 0 /**E*/, /**F*/ 1 /**G*/) /**H*/; + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 16 │ + 17 │ var xs = (Array)( + + i The Array constructor is misleading because it can be used to preallocate an array of a given length or to create an array with a given list of elements. + + i Unsafe fix: Use an array literal. + + 13 13 │ var xs = new Array(...args); + 14 14 │ + 15 │ - var·xs·=·/**A*/·new·/**B*/·Array·/**C*/·(·/**D*/·0·/**E*/,·/**F*/·1·/**G*/)·/**H*/; + 15 │ + var·xs·=·/**A*/·[·/**D*/·0·/**E*/,·/**F*/·1·/**G*/]·/**H*/; + 16 16 │ + 17 17 │ var xs = (Array)( + + +``` + +``` +invalid.js:17:10 lint/correctness/useArrayLiterals FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Use an array literal instead of the Array constructor. + + 15 │ var xs = /**A*/ new /**B*/ Array /**C*/ ( /**D*/ 0 /**E*/, /**F*/ 1 /**G*/) /**H*/; + 16 │ + > 17 │ var xs = (Array)( + │ ^^^^^^^^ + > 18 │ /* foo */ a, + > 19 │ b = c() // bar + > 20 │ ); + │ ^ + 21 │ + 22 │ var xs = Array?.(); + + i The Array constructor is misleading because it can be used to preallocate an array of a given length or to create an array with a given list of elements. + + i Unsafe fix: Use an array literal. + + 15 15 │ var xs = /**A*/ new /**B*/ Array /**C*/ ( /**D*/ 0 /**E*/, /**F*/ 1 /**G*/) /**H*/; + 16 16 │ + 17 │ - var·xs·=·(Array)( + 17 │ + var·xs·=·[ + 18 18 │ /* foo */ a, + 19 19 │ b = c() // bar + 20 │ - ); + 20 │ + ]; + 21 21 │ + 22 22 │ var xs = Array?.(); + + +``` + +``` +invalid.js:22:10 lint/correctness/useArrayLiterals FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Use an array literal instead of the Array constructor. + + 20 │ ); + 21 │ + > 22 │ var xs = Array?.(); + │ ^^^^^^^^^ + 23 │ + 24 │ // ASI + + i The Array constructor is misleading because it can be used to preallocate an array of a given length or to create an array with a given list of elements. + + i Unsafe fix: Use an array literal. + + 20 20 │ ); + 21 21 │ + 22 │ - var·xs·=·Array?.(); + 22 │ + var·xs·=·[]; + 23 23 │ + 24 24 │ // ASI + + +``` + +``` +invalid.js:26:1 lint/correctness/useArrayLiterals ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Use an array literal instead of the Array constructor. + + 24 │ // ASI + 25 │ foo + > 26 │ new Array + │ ^^^^^^^^^ + 27 │ + 28 │ var xs = globalThis.Array(); + + i The Array constructor is misleading because it can be used to preallocate an array of a given length or to create an array with a given list of elements. + + +``` + +``` +invalid.js:28:10 lint/correctness/useArrayLiterals FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Use an array literal instead of the Array constructor. + + 26 │ new Array + 27 │ + > 28 │ var xs = globalThis.Array(); + │ ^^^^^^^^^^^^^^^^^^ + 29 │ + 30 │ var xs = window.Array(); + + i The Array constructor is misleading because it can be used to preallocate an array of a given length or to create an array with a given list of elements. + + i Unsafe fix: Use an array literal. + + 26 26 │ new Array + 27 27 │ + 28 │ - var·xs·=·globalThis.Array(); + 28 │ + var·xs·=·[]; + 29 29 │ + 30 30 │ var xs = window.Array(); + + +``` + +``` +invalid.js:30:10 lint/correctness/useArrayLiterals FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Use an array literal instead of the Array constructor. + + 28 │ var xs = globalThis.Array(); + 29 │ + > 30 │ var xs = window.Array(); + │ ^^^^^^^^^^^^^^ + 31 │ + + i The Array constructor is misleading because it can be used to preallocate an array of a given length or to create an array with a given list of elements. - i Use of the Array constructor is not allowed except creating sparse arrays of a specified size by giving a single numeric argument. + i Unsafe fix: Use an array literal. - i The array literal notation [] is preferable. + 28 28 │ var xs = globalThis.Array(); + 29 29 │ + 30 │ - var·xs·=·window.Array(); + 30 │ + var·xs·=·[]; + 31 31 │ ``` diff --git a/crates/biome_js_analyze/tests/specs/correctness/useArrayLiterals/valid.js b/crates/biome_js_analyze/tests/specs/correctness/useArrayLiterals/valid.js index b192682b7caa..5b2067538600 100644 --- a/crates/biome_js_analyze/tests/specs/correctness/useArrayLiterals/valid.js +++ b/crates/biome_js_analyze/tests/specs/correctness/useArrayLiterals/valid.js @@ -9,3 +9,5 @@ new Array(someOtherArray.length); [0, 1, 2]; const createArray = (Array) => new Array(); + +Array.foo(); diff --git a/crates/biome_js_analyze/tests/specs/correctness/useArrayLiterals/valid.js.snap b/crates/biome_js_analyze/tests/specs/correctness/useArrayLiterals/valid.js.snap index c32e2cfbae03..b803117a5e07 100644 --- a/crates/biome_js_analyze/tests/specs/correctness/useArrayLiterals/valid.js.snap +++ b/crates/biome_js_analyze/tests/specs/correctness/useArrayLiterals/valid.js.snap @@ -1,6 +1,7 @@ --- source: crates/biome_js_analyze/tests/spec_tests.rs expression: valid.js +snapshot_kind: text --- # Input ```jsx @@ -16,4 +17,6 @@ new Array(someOtherArray.length); const createArray = (Array) => new Array(); +Array.foo(); + ``` diff --git a/crates/biome_js_syntax/src/expr_ext.rs b/crates/biome_js_syntax/src/expr_ext.rs index 8ed55c3833dc..c065cbea4bc8 100644 --- a/crates/biome_js_syntax/src/expr_ext.rs +++ b/crates/biome_js_syntax/src/expr_ext.rs @@ -2,10 +2,10 @@ use crate::numbers::parse_js_number; use crate::static_value::StaticValue; use crate::{ - inner_string_text, AnyJsArrowFunctionParameters, AnyJsCallArgument, AnyJsClassMemberName, - AnyJsExpression, AnyJsFunctionBody, AnyJsLiteralExpression, AnyJsName, AnyJsObjectMemberName, - AnyJsTemplateElement, AnyTsEnumMemberName, JsArrayExpression, JsArrayHole, - JsAssignmentExpression, JsBinaryExpression, JsCallArgumentList, JsCallArguments, + inner_string_text, AnyJsArrayElement, AnyJsArrowFunctionParameters, AnyJsCallArgument, + AnyJsClassMemberName, AnyJsExpression, AnyJsFunctionBody, AnyJsLiteralExpression, AnyJsName, + AnyJsObjectMemberName, AnyJsTemplateElement, AnyTsEnumMemberName, JsArrayExpression, + JsArrayHole, JsAssignmentExpression, JsBinaryExpression, JsCallArgumentList, JsCallArguments, JsCallExpression, JsComputedMemberAssignment, JsComputedMemberExpression, JsConditionalExpression, JsDoWhileStatement, JsForStatement, JsIfStatement, JsLiteralMemberName, JsLogicalExpression, JsNewExpression, JsNumberLiteralExpression, @@ -43,6 +43,23 @@ impl JsNewOrCallExpression { } } } +impl From for AnyJsExpression { + fn from(value: JsNewOrCallExpression) -> Self { + match value { + JsNewOrCallExpression::JsNewExpression(expr) => Self::JsNewExpression(expr), + JsNewOrCallExpression::JsCallExpression(expr) => Self::JsCallExpression(expr), + } + } +} + +impl From for AnyJsArrayElement { + fn from(value: AnyJsCallArgument) -> Self { + match value { + AnyJsCallArgument::AnyJsExpression(expr) => Self::AnyJsExpression(expr), + AnyJsCallArgument::JsSpread(spread) => Self::JsSpread(spread), + } + } +} impl JsReferenceIdentifier { /// Returns `true` if this identifier refers to the `undefined` symbol.