From a13d36d067facf0fb7943e72e86f7a7b581b48b8 Mon Sep 17 00:00:00 2001 From: Luca Di Gianventura Date: Fri, 26 Apr 2024 12:18:12 +0200 Subject: [PATCH] feat: no useless undefined initialization (#2591) --- .../migrate/eslint_any_rule_to_biome.rs | 14 ++ .../biome_configuration/src/linter/rules.rs | 36 ++- .../src/categories.rs | 1 + crates/biome_js_analyze/src/lint/nursery.rs | 2 + .../no_useless_undefined_initialization.rs | 138 ++++++++++++ crates/biome_js_analyze/src/options.rs | 1 + .../invalid.js | 17 ++ .../invalid.js.snap | 213 ++++++++++++++++++ .../noUselessUndefinedInitialization/valid.js | 12 + .../valid.js.snap | 20 ++ .../@biomejs/backend-jsonrpc/src/workspace.ts | 5 + .../@biomejs/biome/configuration_schema.json | 7 + 12 files changed, 458 insertions(+), 8 deletions(-) create mode 100644 crates/biome_js_analyze/src/lint/nursery/no_useless_undefined_initialization.rs create mode 100644 crates/biome_js_analyze/tests/specs/nursery/noUselessUndefinedInitialization/invalid.js create mode 100644 crates/biome_js_analyze/tests/specs/nursery/noUselessUndefinedInitialization/invalid.js.snap create mode 100644 crates/biome_js_analyze/tests/specs/nursery/noUselessUndefinedInitialization/valid.js create mode 100644 crates/biome_js_analyze/tests/specs/nursery/noUselessUndefinedInitialization/valid.js.snap diff --git a/crates/biome_cli/src/execute/migrate/eslint_any_rule_to_biome.rs b/crates/biome_cli/src/execute/migrate/eslint_any_rule_to_biome.rs index f73445298448..ef30e0c3590b 100644 --- a/crates/biome_cli/src/execute/migrate/eslint_any_rule_to_biome.rs +++ b/crates/biome_cli/src/execute/migrate/eslint_any_rule_to_biome.rs @@ -973,6 +973,20 @@ pub(crate) fn migrate_eslint_any_rule( .get_or_insert(Default::default()); rule.set_level(rule_severity.into()); } + "no-undef-init" => { + if !options.include_inspired { + results.has_inspired_rules = true; + return false; + } + if !options.include_nursery { + return false; + } + let group = rules.nursery.get_or_insert_with(Default::default); + let rule = group + .no_useless_undefined_initialization + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } "no-unneeded-ternary" => { let group = rules.complexity.get_or_insert_with(Default::default); let rule = group.no_useless_ternary.get_or_insert(Default::default()); diff --git a/crates/biome_configuration/src/linter/rules.rs b/crates/biome_configuration/src/linter/rules.rs index f54c119e8c04..c1ba03b96309 100644 --- a/crates/biome_configuration/src/linter/rules.rs +++ b/crates/biome_configuration/src/linter/rules.rs @@ -2702,6 +2702,10 @@ pub struct Nursery { #[doc = "Disallow unknown CSS units."] #[serde(skip_serializing_if = "Option::is_none")] pub no_unknown_unit: Option>, + #[doc = "Disallow initializing variables to undefined."] + #[serde(skip_serializing_if = "Option::is_none")] + pub no_useless_undefined_initialization: + Option>, #[doc = "Disallow Array constructors."] #[serde(skip_serializing_if = "Option::is_none")] pub use_array_literals: Option>, @@ -2750,6 +2754,7 @@ impl Nursery { "noRestrictedImports", "noUndeclaredDependencies", "noUnknownUnit", + "noUselessUndefinedInitialization", "useArrayLiterals", "useConsistentNewBuiltin", "useImportRestrictions", @@ -2802,6 +2807,7 @@ impl Nursery { RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[19]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[20]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[21]), + RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[22]), ]; #[doc = r" Retrieves the recommended rules"] pub(crate) fn is_recommended_true(&self) -> bool { @@ -2908,26 +2914,31 @@ impl Nursery { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[17])); } } - if let Some(rule) = self.use_array_literals.as_ref() { + if let Some(rule) = self.no_useless_undefined_initialization.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[18])); } } - if let Some(rule) = self.use_consistent_new_builtin.as_ref() { + if let Some(rule) = self.use_array_literals.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[19])); } } - if let Some(rule) = self.use_import_restrictions.as_ref() { + if let Some(rule) = self.use_consistent_new_builtin.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[20])); } } - if let Some(rule) = self.use_sorted_classes.as_ref() { + if let Some(rule) = self.use_import_restrictions.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[21])); } } + if let Some(rule) = self.use_sorted_classes.as_ref() { + if rule.is_enabled() { + index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[22])); + } + } index_set } pub(crate) fn get_disabled_rules(&self) -> IndexSet { @@ -3022,26 +3033,31 @@ impl Nursery { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[17])); } } - if let Some(rule) = self.use_array_literals.as_ref() { + if let Some(rule) = self.no_useless_undefined_initialization.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[18])); } } - if let Some(rule) = self.use_consistent_new_builtin.as_ref() { + if let Some(rule) = self.use_array_literals.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[19])); } } - if let Some(rule) = self.use_import_restrictions.as_ref() { + if let Some(rule) = self.use_consistent_new_builtin.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[20])); } } - if let Some(rule) = self.use_sorted_classes.as_ref() { + if let Some(rule) = self.use_import_restrictions.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[21])); } } + if let Some(rule) = self.use_sorted_classes.as_ref() { + if rule.is_disabled() { + index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[22])); + } + } index_set } #[doc = r" Checks if, given a rule name, matches one of the rules contained in this category"] @@ -3150,6 +3166,10 @@ impl Nursery { .no_unknown_unit .as_ref() .map(|conf| (conf.level(), conf.get_options())), + "noUselessUndefinedInitialization" => self + .no_useless_undefined_initialization + .as_ref() + .map(|conf| (conf.level(), conf.get_options())), "useArrayLiterals" => self .use_array_literals .as_ref() diff --git a/crates/biome_diagnostics_categories/src/categories.rs b/crates/biome_diagnostics_categories/src/categories.rs index 6e3334302fc3..e2e39b135094 100644 --- a/crates/biome_diagnostics_categories/src/categories.rs +++ b/crates/biome_diagnostics_categories/src/categories.rs @@ -129,6 +129,7 @@ define_categories! { "lint/nursery/noRestrictedImports": "https://biomejs.dev/linter/rules/no-restricted-imports", "lint/nursery/noTypeOnlyImportAttributes": "https://biomejs.dev/linter/rules/no-type-only-import-attributes", "lint/nursery/noUndeclaredDependencies": "https://biomejs.dev/linter/rules/no-undeclared-dependencies", + "lint/nursery/noUselessUndefinedInitialization": "https://biomejs.dev/linter/rules/no-useless-undefined-initialization", "lint/nursery/noUnknownUnit": "https://biomejs.dev/linter/rules/no-unknown-unit", "lint/nursery/useBiomeSuppressionComment": "https://biomejs.dev/linter/rules/use-biome-suppression-comment", "lint/nursery/useConsistentNewBuiltin": "https://biomejs.dev/linter/rules/use-consistent-new-builtin", diff --git a/crates/biome_js_analyze/src/lint/nursery.rs b/crates/biome_js_analyze/src/lint/nursery.rs index c2abf3d3ef92..a52c3f728808 100644 --- a/crates/biome_js_analyze/src/lint/nursery.rs +++ b/crates/biome_js_analyze/src/lint/nursery.rs @@ -13,6 +13,7 @@ pub mod no_nodejs_modules; pub mod no_react_specific_props; pub mod no_restricted_imports; pub mod no_undeclared_dependencies; +pub mod no_useless_undefined_initialization; pub mod use_array_literals; pub mod use_consistent_new_builtin; pub mod use_import_restrictions; @@ -33,6 +34,7 @@ declare_group! { self :: no_react_specific_props :: NoReactSpecificProps , self :: no_restricted_imports :: NoRestrictedImports , self :: no_undeclared_dependencies :: NoUndeclaredDependencies , + self :: no_useless_undefined_initialization :: NoUselessUndefinedInitialization , self :: use_array_literals :: UseArrayLiterals , self :: use_consistent_new_builtin :: UseConsistentNewBuiltin , self :: use_import_restrictions :: UseImportRestrictions , diff --git a/crates/biome_js_analyze/src/lint/nursery/no_useless_undefined_initialization.rs b/crates/biome_js_analyze/src/lint/nursery/no_useless_undefined_initialization.rs new file mode 100644 index 000000000000..1f3658e2ae48 --- /dev/null +++ b/crates/biome_js_analyze/src/lint/nursery/no_useless_undefined_initialization.rs @@ -0,0 +1,138 @@ +use biome_analyze::{ + context::RuleContext, declare_rule, ActionCategory, Ast, FixKind, Rule, RuleDiagnostic, + RuleSource, RuleSourceKind, +}; +use biome_console::markup; +use biome_diagnostics::Applicability; +use biome_js_syntax::JsVariableDeclaration; +use biome_rowan::{AstNode, BatchMutationExt, TextRange}; + +use crate::JsRuleAction; + +declare_rule! { + /// Disallow initializing variables to `undefined`. + /// + /// A variable that is declared and not initialized to any value automatically gets the value of `undefined`. + /// It’s considered a best practice to avoid initializing variables to `undefined`. + /// Please note that any inline comments attached to the initialization value or variable will be removed on auto-fix. + /// Please be also aware that this differs from Eslint's behaviour and we are still discussing on how to properly handle this case. + /// + /// ## Examples + /// + /// ### Invalid + /// + /// ```js,expect_diagnostic + /// var a = undefined; + /// ``` + /// ```js,expect_diagnostic + /// let b = undefined, c = 1, d = undefined; + /// ``` + /// ```js,expect_diagnostic + /// for (let i = 0; i < 100; i++) { + /// let i = undefined; + /// } + /// ``` + /// ```js,expect_diagnostic + /// let f = /**/undefined/**/ ; + /// ``` + /// ### Valid + /// + /// ```js + /// var a = 1; + /// ``` + /// ```js + /// class Foo { + /// bar = undefined; + /// } + /// ``` + /// + pub NoUselessUndefinedInitialization { + version: "next", + name: "noUselessUndefinedInitialization", + sources: &[RuleSource::Eslint("no-undef-init")], + source_kind: RuleSourceKind::Inspired, + fix_kind: FixKind::Unsafe, + recommended: false, + } +} + +impl Rule for NoUselessUndefinedInitialization { + type Query = Ast; + type State = (String, TextRange); + type Signals = Vec; + type Options = (); + + fn run(ctx: &RuleContext) -> Self::Signals { + let node = ctx.query(); + let let_or_var_kind = node.is_let() || node.is_var(); + + let mut signals = vec![]; + + if !let_or_var_kind { + return signals; + } + + for declarator in node.declarators() { + let Ok(decl) = declarator else { continue }; + + let Some(initializer) = decl.initializer() else { + continue; + }; + + let Some(keyword) = initializer + .expression() + .ok() + .and_then(|expression| expression.as_js_reference_identifier()) + else { + continue; + }; + + if keyword.is_undefined() { + let decl_range = initializer.range(); + let Some(binding_name) = decl.id().ok().map(|id| id.text()) else { + continue; + }; + signals.push((binding_name, decl_range)); + } + } + + signals + } + + fn diagnostic(_ctx: &RuleContext, state: &Self::State) -> Option { + Some(RuleDiagnostic::new( + rule_category!(), + state.1, + markup! { + "It's not necessary to initialize "{state.0}" to undefined." + }).note("A variable that is declared and not initialized to any value automatically gets the value of undefined.") + ) + } + + fn action(ctx: &RuleContext, state: &Self::State) -> Option { + let declarators = ctx.query().declarators(); + + let initializer = declarators + .clone() + .into_iter() + .find(|el| { + el.as_ref() + .ok() + .and_then(|element| element.id().ok()) + .is_some_and(|id| id.text() == state.0) + }) + .map(|decl| decl.ok())? + .and_then(|declarator| declarator.initializer())?; + + let mut mutation = ctx.root().begin(); + // This will remove any comments attached to the initialization clause + mutation.remove_node(initializer); + + Some(JsRuleAction { + category: ActionCategory::QuickFix, + applicability: Applicability::MaybeIncorrect, + message: markup! { "Remove undefined initialization." }.to_owned(), + mutation, + }) + } +} diff --git a/crates/biome_js_analyze/src/options.rs b/crates/biome_js_analyze/src/options.rs index 031763693392..4f873250e96b 100644 --- a/crates/biome_js_analyze/src/options.rs +++ b/crates/biome_js_analyze/src/options.rs @@ -233,6 +233,7 @@ pub type NoUselessTernary = pub type NoUselessThisAlias = ::Options; pub type NoUselessTypeConstraint = < lint :: complexity :: no_useless_type_constraint :: NoUselessTypeConstraint as biome_analyze :: Rule > :: Options ; +pub type NoUselessUndefinedInitialization = < lint :: nursery :: no_useless_undefined_initialization :: NoUselessUndefinedInitialization as biome_analyze :: Rule > :: Options ; pub type NoVar = ::Options; pub type NoVoid = ::Options; pub type NoVoidElementsWithChildren = < lint :: correctness :: no_void_elements_with_children :: NoVoidElementsWithChildren as biome_analyze :: Rule > :: Options ; diff --git a/crates/biome_js_analyze/tests/specs/nursery/noUselessUndefinedInitialization/invalid.js b/crates/biome_js_analyze/tests/specs/nursery/noUselessUndefinedInitialization/invalid.js new file mode 100644 index 000000000000..c19399998c6f --- /dev/null +++ b/crates/biome_js_analyze/tests/specs/nursery/noUselessUndefinedInitialization/invalid.js @@ -0,0 +1,17 @@ +let test1, + test2 = undefined; +var c = undefined, + o = undefined; + +for (let i = 0; i < 100; i++) { + let i = undefined; +} + +let x = 1, y = undefined, z = 40 + +let /* comment */d = undefined; + +let e = undefined/**/ ; +let f = /**/undefined/**/ ; +let g + /**/= /**/undefined/**/ ; \ No newline at end of file diff --git a/crates/biome_js_analyze/tests/specs/nursery/noUselessUndefinedInitialization/invalid.js.snap b/crates/biome_js_analyze/tests/specs/nursery/noUselessUndefinedInitialization/invalid.js.snap new file mode 100644 index 000000000000..3edef2b9d8df --- /dev/null +++ b/crates/biome_js_analyze/tests/specs/nursery/noUselessUndefinedInitialization/invalid.js.snap @@ -0,0 +1,213 @@ +--- +source: crates/biome_js_analyze/tests/spec_tests.rs +expression: invalid.js +--- +# Input +```jsx +let test1, + test2 = undefined; +var c = undefined, + o = undefined; + +for (let i = 0; i < 100; i++) { + let i = undefined; +} + +let x = 1, y = undefined, z = 40 + +let /* comment */d = undefined; + +let e = undefined/**/ ; +let f = /**/undefined/**/ ; +let g + /**/= /**/undefined/**/ ; +``` + +# Diagnostics +``` +invalid.js:2:8 lint/nursery/noUselessUndefinedInitialization FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! It's not necessary to initialize test2 to undefined. + + 1 │ let test1, + > 2 │ test2 = undefined; + │ ^^^^^^^^^^^ + 3 │ var c = undefined, + 4 │ o = undefined; + + i A variable that is declared and not initialized to any value automatically gets the value of undefined. + + i Unsafe fix: Remove undefined initialization. + + 2 │ → test2·=·undefined; + │ ----------- + +``` + +``` +invalid.js:3:7 lint/nursery/noUselessUndefinedInitialization FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! It's not necessary to initialize c to undefined. + + 1 │ let test1, + 2 │ test2 = undefined; + > 3 │ var c = undefined, + │ ^^^^^^^^^^^ + 4 │ o = undefined; + 5 │ + + i A variable that is declared and not initialized to any value automatically gets the value of undefined. + + i Unsafe fix: Remove undefined initialization. + + 3 │ var·c·=·undefined, + │ ----------- + +``` + +``` +invalid.js:4:4 lint/nursery/noUselessUndefinedInitialization FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! It's not necessary to initialize o to undefined. + + 2 │ test2 = undefined; + 3 │ var c = undefined, + > 4 │ o = undefined; + │ ^^^^^^^^^^^ + 5 │ + 6 │ for (let i = 0; i < 100; i++) { + + i A variable that is declared and not initialized to any value automatically gets the value of undefined. + + i Unsafe fix: Remove undefined initialization. + + 4 │ → o·=·undefined; + │ ----------- + +``` + +``` +invalid.js:7:8 lint/nursery/noUselessUndefinedInitialization FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! It's not necessary to initialize i to undefined. + + 6 │ for (let i = 0; i < 100; i++) { + > 7 │ let i = undefined; + │ ^^^^^^^^^^^ + 8 │ } + 9 │ + + i A variable that is declared and not initialized to any value automatically gets the value of undefined. + + i Unsafe fix: Remove undefined initialization. + + 7 │ → let·i·=·undefined; + │ ----------- + +``` + +``` +invalid.js:10:14 lint/nursery/noUselessUndefinedInitialization FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! It's not necessary to initialize y to undefined. + + 8 │ } + 9 │ + > 10 │ let x = 1, y = undefined, z = 40 + │ ^^^^^^^^^^^ + 11 │ + 12 │ let /* comment */d = undefined; + + i A variable that is declared and not initialized to any value automatically gets the value of undefined. + + i Unsafe fix: Remove undefined initialization. + + 10 │ let·x·=·1,·y·=·undefined,·z·=·40 + │ ----------- + +``` + +``` +invalid.js:12:20 lint/nursery/noUselessUndefinedInitialization FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! It's not necessary to initialize d to undefined. + + 10 │ let x = 1, y = undefined, z = 40 + 11 │ + > 12 │ let /* comment */d = undefined; + │ ^^^^^^^^^^^ + 13 │ + 14 │ let e = undefined/**/ ; + + i A variable that is declared and not initialized to any value automatically gets the value of undefined. + + i Unsafe fix: Remove undefined initialization. + + 12 │ let·/*·comment·*/d·=·undefined; + │ ----------- + +``` + +``` +invalid.js:14:7 lint/nursery/noUselessUndefinedInitialization FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! It's not necessary to initialize e to undefined. + + 12 │ let /* comment */d = undefined; + 13 │ + > 14 │ let e = undefined/**/ ; + │ ^^^^^^^^^^^ + 15 │ let f = /**/undefined/**/ ; + 16 │ let g· + + i A variable that is declared and not initialized to any value automatically gets the value of undefined. + + i Unsafe fix: Remove undefined initialization. + + 14 │ let·e·=·undefined/**/·; + │ ---------------- + +``` + +``` +invalid.js:15:7 lint/nursery/noUselessUndefinedInitialization FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! It's not necessary to initialize f to undefined. + + 14 │ let e = undefined/**/ ; + > 15 │ let f = /**/undefined/**/ ; + │ ^^^^^^^^^^^^^^^ + 16 │ let g· + 17 │ /**/= /**/undefined/**/ ; + + i A variable that is declared and not initialized to any value automatically gets the value of undefined. + + i Unsafe fix: Remove undefined initialization. + + 15 │ let·f·=·/**/undefined/**/·; + │ -------------------- + +``` + +``` +invalid.js:17:7 lint/nursery/noUselessUndefinedInitialization FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! It's not necessary to initialize g to undefined. + + 15 │ let f = /**/undefined/**/ ; + 16 │ let g· + > 17 │ /**/= /**/undefined/**/ ; + │ ^^^^^^^^^^^^^^^ + + i A variable that is declared and not initialized to any value automatically gets the value of undefined. + + i Unsafe fix: Remove undefined initialization. + + 14 14 │ let e = undefined/**/ ; + 15 15 │ let f = /**/undefined/**/ ; + 16 │ - let·g· + 17 │ - ··/**/=·/**/undefined/**/·; + 16 │ + let·g·; + + +``` diff --git a/crates/biome_js_analyze/tests/specs/nursery/noUselessUndefinedInitialization/valid.js b/crates/biome_js_analyze/tests/specs/nursery/noUselessUndefinedInitialization/valid.js new file mode 100644 index 000000000000..e7960463c25d --- /dev/null +++ b/crates/biome_js_analyze/tests/specs/nursery/noUselessUndefinedInitialization/valid.js @@ -0,0 +1,12 @@ +/* should not generate diagnostics */ +const foo = undefined; + +const { bar = undefined } = baz; + +[quux = undefined] = quuux; + +(foo = undefined) => {}; + +class Foo { + bar = undefined; +} diff --git a/crates/biome_js_analyze/tests/specs/nursery/noUselessUndefinedInitialization/valid.js.snap b/crates/biome_js_analyze/tests/specs/nursery/noUselessUndefinedInitialization/valid.js.snap new file mode 100644 index 000000000000..d924cbed5b79 --- /dev/null +++ b/crates/biome_js_analyze/tests/specs/nursery/noUselessUndefinedInitialization/valid.js.snap @@ -0,0 +1,20 @@ +--- +source: crates/biome_js_analyze/tests/spec_tests.rs +expression: valid.js +--- +# Input +```jsx +/* should not generate diagnostics */ +const foo = undefined; + +const { bar = undefined } = baz; + +[quux = undefined] = quuux; + +(foo = undefined) => {}; + +class Foo { + bar = undefined; +} + +``` diff --git a/packages/@biomejs/backend-jsonrpc/src/workspace.ts b/packages/@biomejs/backend-jsonrpc/src/workspace.ts index 2b2c63fe0b35..997b8b4c6421 100644 --- a/packages/@biomejs/backend-jsonrpc/src/workspace.ts +++ b/packages/@biomejs/backend-jsonrpc/src/workspace.ts @@ -980,6 +980,10 @@ export interface Nursery { * Disallow unknown CSS units. */ noUnknownUnit?: RuleConfiguration_for_Null; + /** + * Disallow initializing variables to undefined. + */ + noUselessUndefinedInitialization?: RuleConfiguration_for_Null; /** * It enables the recommended rules for this group */ @@ -1984,6 +1988,7 @@ export type Category = | "lint/nursery/noRestrictedImports" | "lint/nursery/noTypeOnlyImportAttributes" | "lint/nursery/noUndeclaredDependencies" + | "lint/nursery/noUselessUndefinedInitialization" | "lint/nursery/noUnknownUnit" | "lint/nursery/useBiomeSuppressionComment" | "lint/nursery/useConsistentNewBuiltin" diff --git a/packages/@biomejs/biome/configuration_schema.json b/packages/@biomejs/biome/configuration_schema.json index 05cf5a6ee2ec..0919bafaa105 100644 --- a/packages/@biomejs/biome/configuration_schema.json +++ b/packages/@biomejs/biome/configuration_schema.json @@ -1559,6 +1559,13 @@ { "type": "null" } ] }, + "noUselessUndefinedInitialization": { + "description": "Disallow initializing variables to undefined.", + "anyOf": [ + { "$ref": "#/definitions/RuleConfiguration" }, + { "type": "null" } + ] + }, "recommended": { "description": "It enables the recommended rules for this group", "type": ["boolean", "null"]