Skip to content

Commit

Permalink
feat(biome_js_analyze): useArrayLiterals (#2541)
Browse files Browse the repository at this point in the history
Co-authored-by: Emanuele Stoppa <[email protected]>
  • Loading branch information
Kazuhiro-Mimaki and ematipico authored Apr 26, 2024
1 parent 2db7d05 commit ce4979d
Show file tree
Hide file tree
Showing 12 changed files with 335 additions and 6 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 25 additions & 6 deletions crates/biome_configuration/src/linter/rules.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/biome_diagnostics_categories/src/categories.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ define_categories! {
"lint/correctness/useValidForDirection": "https://biomejs.dev/linter/rules/use-valid-for-direction",
"lint/correctness/useYield": "https://biomejs.dev/linter/rules/use-yield",
"lint/nursery/colorNoInvalidHex": "https://biomejs.dev/linter/rules/color-no-invalid-hex",
"lint/nursery/useArrayLiterals": "https://biomejs.dev/linter/rules/use-array-literals",
"lint/nursery/noColorInvalidHex": "https://biomejs.dev/linter/rules/no-color-invalid-hex",
"lint/nursery/noConsole": "https://biomejs.dev/linter/rules/no-console",
"lint/nursery/noConstantMathMinMaxClamp": "https://biomejs.dev/linter/rules/no-constant-math-min-max-clamp",
Expand Down
2 changes: 2 additions & 0 deletions crates/biome_js_analyze/src/lint/nursery.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

113 changes: 113 additions & 0 deletions crates/biome_js_analyze/src/lint/nursery/use_array_literals.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
use biome_analyze::{
context::RuleContext, declare_rule, Ast, FixKind, Rule, RuleDiagnostic, RuleSource,
};
use biome_console::markup;
use biome_js_syntax::{AnyJsCallArgument, AnyJsExpression, JsCallArguments, JsExpressionStatement};
use biome_rowan::AstNode;

declare_rule! {
/// Disallow Array constructors.
///
/// Use of the Array constructor to construct a new array is generally discouraged in favor of array literal notation because of the single-argument pitfall and because the Array global may be redefined.
/// The exception is when the Array constructor intentionally creates sparse arrays of a specified size by giving the constructor a single numeric argument.
///
/// ## Examples
///
/// ### Invalid
///
/// ```js,expect_diagnostic
/// Array();
/// ```
///
/// ```js,expect_diagnostic
/// Array(0, 1, 2);
/// ```
///
/// ```js,expect_diagnostic
/// new Array(0, 1, 2);
/// ```
///
/// ```js,expect_diagnostic
/// Array(...args);
/// ```
///
/// ### Valid
///
/// ```js
/// Array(500);
/// ```
///
/// ```js
/// [0, 1, 2];
/// ```
///
pub UseArrayLiterals {
version: "next",
name: "useArrayLiterals",
sources: &[RuleSource::Eslint("no-array-constructor")],
recommended: false,
fix_kind: FixKind::Unsafe,
}
}

impl Rule for UseArrayLiterals {
type Query = Ast<JsExpressionStatement>;
type State = ();
type Signals = Option<Self::State>;
type Options = ();

fn run(ctx: &RuleContext<Self>) -> 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,
}
}

fn diagnostic(ctx: &RuleContext<Self>, _state: &Self::State) -> Option<RuleDiagnostic> {
let node = ctx.query();
Some(
RuleDiagnostic::new(
rule_category!(),
node.range(),
markup! {
"Don't use Array constructors."
},
)
.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."
}),
)
}
}

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;
}
Some(())
}
2 changes: 2 additions & 0 deletions crates/biome_js_analyze/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,8 @@ pub type UseAnchorContent =
pub type UseAriaActivedescendantWithTabindex = < lint :: a11y :: use_aria_activedescendant_with_tabindex :: UseAriaActivedescendantWithTabindex as biome_analyze :: Rule > :: Options ;
pub type UseAriaPropsForRole =
<lint::a11y::use_aria_props_for_role::UseAriaPropsForRole as biome_analyze::Rule>::Options;
pub type UseArrayLiterals =
<lint::nursery::use_array_literals::UseArrayLiterals as biome_analyze::Rule>::Options;
pub type UseArrowFunction =
<lint::complexity::use_arrow_function::UseArrowFunction as biome_analyze::Rule>::Options;
pub type UseAsConstAssertion =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Array();

Array(0, 1, 2);

Array(...args);

new Array();

new Array(0, 1, 2);

new Array(...args);
Loading

0 comments on commit ce4979d

Please sign in to comment.