diff --git a/.changeset/shaggy-grapes-act.md b/.changeset/shaggy-grapes-act.md new file mode 100644 index 000000000000..a054cb9332a7 --- /dev/null +++ b/.changeset/shaggy-grapes-act.md @@ -0,0 +1,16 @@ +--- +"@biomejs/biome": minor +--- + +Added `ignore` option to the [noUnusedVariables](https://biomejs.dev/linter/rules/no-unused-variables/) rule. The option allows excluding identifiers by providing a list of ignored names. It also allows excluding kinds of identifiers from this rule entirely, which may be useful when loading classes dynamically. + +For example, unused classes as well as all unused variables, functions, etc. called "unused" may be ignored entirely with the following configuration: + +```json +{ + "ignore": { + "*": ["unused"], + "class": ["*"] + } +} +``` diff --git a/crates/biome_js_analyze/src/lint/correctness/no_unused_variables.rs b/crates/biome_js_analyze/src/lint/correctness/no_unused_variables.rs index 3a358f33a5db..7870c6a2355d 100644 --- a/crates/biome_js_analyze/src/lint/correctness/no_unused_variables.rs +++ b/crates/biome_js_analyze/src/lint/correctness/no_unused_variables.rs @@ -9,14 +9,9 @@ use biome_diagnostics::Severity; use biome_js_semantic::{ReferencesExtensions, SemanticModel}; use biome_js_syntax::binding_ext::{AnyJsBindingDeclaration, AnyJsIdentifierBinding}; use biome_js_syntax::declaration_ext::is_in_ambient_context; -use biome_js_syntax::{ - AnyJsExpression, EmbeddingKind, JsClassExpression, JsFileSource, JsForStatement, - JsFunctionExpression, JsIdentifierExpression, JsModuleItemList, JsSequenceExpression, - JsSyntaxKind, JsSyntaxNode, TsConditionalType, TsDeclarationModule, TsInferType, - TsInterfaceDeclaration, TsTypeAliasDeclaration, -}; +use biome_js_syntax::{AnyJsExpression, EmbeddingKind, JsClassExpression, JsFileSource, JsForStatement, JsFunctionExpression, JsIdentifierExpression, JsModuleItemList, JsSequenceExpression, JsSyntaxKind, JsSyntaxNode, TsConditionalType, TsDeclarationModule, TsInferType, TsInterfaceDeclaration, TsTypeAliasDeclaration}; use biome_rowan::{AstNode, BatchMutationExt, Direction, SyntaxResult}; -use biome_rule_options::no_unused_variables::NoUnusedVariablesOptions; +use biome_rule_options::no_unused_variables::{NoUnusedVariablesOptions, NoUnusedVariablesOptionsIgnore}; declare_lint_rule! { /// Disallow unused variables. @@ -117,7 +112,7 @@ declare_lint_rule! { /// /// Default: `true` /// - /// #### Example + /// If this option is set to `false`, unused rest siblings either have to be renamed or removed. /// /// ```json,options /// { @@ -138,6 +133,57 @@ declare_lint_rule! { /// const { brand: _, ...other } = car; /// console.log(other); /// ``` + /// + /// ### `ignore` + /// + /// An object that allows excluding matching identifiers from this rule. + /// + /// Each key may specify an array of identifiers to ignore which are case-sensitive matches. + /// + /// The special string `"*"` can serve two purposes: + /// - As a **key** it refers to every kind of identifier. + /// - As a **value** it may be used to match all identifiers in the respective group, effectively disabling this rule for that group. + /// + /// Allowed keys: + /// + /// - `"*"`: Applies to all identifiers + /// - `"class"`: Applies to class names + /// - `"function"`: Applies to function names + /// - `"interface"`: Applies to interface names + /// - `"typeAlias"`: Applies to type aliases + /// - `"typeParameter"`: Applies to type parameters + /// - `"variable"`: Applies to variable names + /// + /// Default: `{}` (no variables are excluded) + /// + /// For example, you can exclude all unused identifiers named `ignored` regardless of their kind, + /// all unused classes named `IgnoredClass`, and all unused functions with the following + /// configuration. + /// + /// A variable named `unusedVariable` is still flagged as unused, and so is a class named + /// `UnusedClass` since they don't fall under the exceptions. + /// + /// ```json,options + /// { + /// "options": { + /// "ignore": { + /// "*": ["ignored"], + /// "class": ["IgnoredClass"], + /// "function": ["*"] + /// } + /// } + /// } + /// ``` + /// + /// ```js,expect_diagnostic,ignore,use_options + /// const ignored = 0; + /// class IgnoredClass {} + /// function ignoredFunction() {} + /// + /// const unusedVariable = 0; + /// class UnusedClass {} + /// ``` + /// pub NoUnusedVariables { version: "1.0.0", name: "noUnusedVariables", @@ -326,7 +372,7 @@ impl Rule for NoUnusedVariables { .find_map(JsModuleItemList::cast) { // A declaration file without top-level exports and imports is a global declaration file. - // All top-level types and variables are available in every files of the project. + // All top-level types and variables are available in every file of the project. // Thus, it is ok if top-level types are not used locally. let is_top_level = items.parent::().is_some(); if is_top_level && items.into_iter().all(|x| x.as_any_js_statement().is_some()) { @@ -334,6 +380,10 @@ impl Rule for NoUnusedVariables { } } + if is_ignored(binding, ctx.options()).unwrap_or_default() { + return None; + } + let binding_name = binding.name_token().ok()?; let binding_name = binding_name.text_trimmed(); @@ -471,6 +521,32 @@ impl Rule for NoUnusedVariables { } } +/// Returns `true` if `binding` is considered as ignored by the user. +pub fn is_ignored(binding: &AnyJsIdentifierBinding, options: &NoUnusedVariablesOptions) -> Option { + let binding_name = binding.name_token().ok()?; + let binding_name = binding_name.text_trimmed(); + + let ignore_options = options.ignore(); + let is_all_ignored = ignore_options.all.unwrap_or_default().iter().any(|ignore| &**ignore == NoUnusedVariablesOptionsIgnore::IGNORE_ALL || &**ignore == binding_name); + + if is_all_ignored { + return Some(true); + } + + let specific_ignores = match binding.syntax().parent()?.kind() { + JsSyntaxKind::JS_FUNCTION_DECLARATION => ignore_options.function, + JsSyntaxKind::JS_CLASS_DECLARATION => ignore_options.class, + JsSyntaxKind::TS_INTERFACE_DECLARATION => ignore_options.interface, + JsSyntaxKind::TS_TYPE_ALIAS_DECLARATION => ignore_options.type_alias, + JsSyntaxKind::TS_TYPE_PARAMETER => ignore_options.type_parameter, + _ => ignore_options.variable, + }; + + let is_specific_ignored = specific_ignores.unwrap_or_default().iter().any(|ignore| &**ignore == NoUnusedVariablesOptionsIgnore::IGNORE_ALL || &**ignore == binding_name); + + Some(is_specific_ignored) +} + /// Returns `true` if `binding` is considered as unused. pub fn is_unused(model: &SemanticModel, binding: &AnyJsIdentifierBinding) -> bool { if matches!(binding, AnyJsIdentifierBinding::TsLiteralEnumMemberName(_)) { diff --git a/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/invalidIgnoreAllPattern.js b/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/invalidIgnoreAllPattern.js new file mode 100644 index 000000000000..d5b0154bc192 --- /dev/null +++ b/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/invalidIgnoreAllPattern.js @@ -0,0 +1,2 @@ +// With ignore: { "*": ["Ignored"] }, variables should be reported that don't match the pattern +const unusedVariable = 0; diff --git a/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/invalidIgnoreAllPattern.js.snap b/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/invalidIgnoreAllPattern.js.snap new file mode 100644 index 000000000000..8c55da04af1e --- /dev/null +++ b/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/invalidIgnoreAllPattern.js.snap @@ -0,0 +1,34 @@ +--- +source: crates/biome_js_analyze/tests/spec_tests.rs +assertion_line: 155 +expression: invalidIgnoreAllPattern.js +--- +# Input +```js +// With ignore: { "*": ["Ignored"] }, variables should be reported that don't match the pattern +const unusedVariable = 0; + +``` + +# Diagnostics +``` +invalidIgnoreAllPattern.js:2:7 lint/correctness/noUnusedVariables FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━ + + ! This variable unusedVariable is unused. + + 1 │ // With ignore: { "*": ["Ignored"] }, variables should be reported that don't match the pattern + > 2 │ const unusedVariable = 0; + │ ^^^^^^^^^^^^^^ + 3 │ + + i Unused variables are often the result of typos, incomplete refactors, or other sources of bugs. + + i Unsafe fix: If this is intentional, prepend unusedVariable with an underscore. + + 1 1 │ // With ignore: { "*": ["Ignored"] }, variables should be reported that don't match the pattern + 2 │ - const·unusedVariable·=·0; + 2 │ + const·_unusedVariable·=·0; + 3 3 │ + + +``` diff --git a/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/invalidIgnoreAllPattern.options.json b/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/invalidIgnoreAllPattern.options.json new file mode 100644 index 000000000000..4ca629c48c78 --- /dev/null +++ b/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/invalidIgnoreAllPattern.options.json @@ -0,0 +1,13 @@ +{ + "$schema": "../../../../../../packages/@biomejs/biome/configuration_schema.json", + "linter": { + "rules": { + "correctness": { + "noUnusedVariables": { + "level": "error", + "options": {"ignore": {"*": ["Ignored"]}} + } + } + } + } +} \ No newline at end of file diff --git a/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/invalidIgnoreClassPattern.js b/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/invalidIgnoreClassPattern.js new file mode 100644 index 000000000000..b2f642dfe70b --- /dev/null +++ b/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/invalidIgnoreClassPattern.js @@ -0,0 +1,2 @@ +// With ignore: { "class": ["ignored"] }, variables should still be reported even if they match the pattern +const ignored = 0; diff --git a/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/invalidIgnoreClassPattern.js.snap b/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/invalidIgnoreClassPattern.js.snap new file mode 100644 index 000000000000..21303203006a --- /dev/null +++ b/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/invalidIgnoreClassPattern.js.snap @@ -0,0 +1,34 @@ +--- +source: crates/biome_js_analyze/tests/spec_tests.rs +assertion_line: 155 +expression: invalidIgnoreClassPattern.js +--- +# Input +```js +// With ignore: { "class": ["ignored"] }, variables should still be reported even if they match the pattern +const ignored = 0; + +``` + +# Diagnostics +``` +invalidIgnoreClassPattern.js:2:7 lint/correctness/noUnusedVariables FIXABLE ━━━━━━━━━━━━━━━━━━━━━━ + + ! This variable ignored is unused. + + 1 │ // With ignore: { "class": ["ignored"] }, variables should still be reported even if they match the pattern + > 2 │ const ignored = 0; + │ ^^^^^^^ + 3 │ + + i Unused variables are often the result of typos, incomplete refactors, or other sources of bugs. + + i Unsafe fix: If this is intentional, prepend ignored with an underscore. + + 1 1 │ // With ignore: { "class": ["ignored"] }, variables should still be reported even if they match the pattern + 2 │ - const·ignored·=·0; + 2 │ + const·_ignored·=·0; + 3 3 │ + + +``` diff --git a/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/invalidIgnoreClassPattern.options.json b/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/invalidIgnoreClassPattern.options.json new file mode 100644 index 000000000000..e9b7dfd3e32d --- /dev/null +++ b/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/invalidIgnoreClassPattern.options.json @@ -0,0 +1,13 @@ +{ + "$schema": "../../../../../../packages/@biomejs/biome/configuration_schema.json", + "linter": { + "rules": { + "correctness": { + "noUnusedVariables": { + "level": "error", + "options": {"ignore": {"class": ["ignored"]}} + } + } + } + } +} \ No newline at end of file diff --git a/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/invalidIgnoreWildcardPattern.js b/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/invalidIgnoreWildcardPattern.js new file mode 100644 index 000000000000..f6dab7d0337b --- /dev/null +++ b/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/invalidIgnoreWildcardPattern.js @@ -0,0 +1,4 @@ +// With ignore: { "class": ["*"] }, all other language constructs should still be reported if they are unused +const unusedVariable = 0; +function unusedFunction(unusedParameter) {} +class UnusedClass {} diff --git a/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/invalidIgnoreWildcardPattern.js.snap b/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/invalidIgnoreWildcardPattern.js.snap new file mode 100644 index 000000000000..df8db6840859 --- /dev/null +++ b/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/invalidIgnoreWildcardPattern.js.snap @@ -0,0 +1,64 @@ +--- +source: crates/biome_js_analyze/tests/spec_tests.rs +assertion_line: 155 +expression: invalidIgnoreWildcardPattern.js +--- +# Input +```js +// With ignore: { "class": ["*"] }, all other language constructs should still be reported if they are unused +const unusedVariable = 0; +function unusedFunction(unusedParameter) {} +class UnusedClass {} + +``` + +# Diagnostics +``` +invalidIgnoreWildcardPattern.js:2:7 lint/correctness/noUnusedVariables FIXABLE ━━━━━━━━━━━━━━━━━━━ + + ! This variable unusedVariable is unused. + + 1 │ // With ignore: { "class": ["*"] }, all other language constructs should still be reported if they are unused + > 2 │ const unusedVariable = 0; + │ ^^^^^^^^^^^^^^ + 3 │ function unusedFunction(unusedParameter) {} + 4 │ class UnusedClass {} + + i Unused variables are often the result of typos, incomplete refactors, or other sources of bugs. + + i Unsafe fix: If this is intentional, prepend unusedVariable with an underscore. + + 1 1 │ // With ignore: { "class": ["*"] }, all other language constructs should still be reported if they are unused + 2 │ - const·unusedVariable·=·0; + 2 │ + const·_unusedVariable·=·0; + 3 3 │ function unusedFunction(unusedParameter) {} + 4 4 │ class UnusedClass {} + + +``` + +``` +invalidIgnoreWildcardPattern.js:3:10 lint/correctness/noUnusedVariables FIXABLE ━━━━━━━━━━━━━━━━━━ + + ! This function unusedFunction is unused. + + 1 │ // With ignore: { "class": ["*"] }, all other language constructs should still be reported if they are unused + 2 │ const unusedVariable = 0; + > 3 │ function unusedFunction(unusedParameter) {} + │ ^^^^^^^^^^^^^^ + 4 │ class UnusedClass {} + 5 │ + + i Unused variables are often the result of typos, incomplete refactors, or other sources of bugs. + + i Unsafe fix: If this is intentional, prepend unusedFunction with an underscore. + + 1 1 │ // With ignore: { "class": ["*"] }, all other language constructs should still be reported if they are unused + 2 2 │ const unusedVariable = 0; + 3 │ - function·unusedFunction(unusedParameter)·{} + 3 │ + function·_unusedFunction(unusedParameter)·{} + 4 4 │ class UnusedClass {} + 5 5 │ + + +``` diff --git a/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/invalidIgnoreWildcardPattern.options.json b/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/invalidIgnoreWildcardPattern.options.json new file mode 100644 index 000000000000..6ab409b75e49 --- /dev/null +++ b/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/invalidIgnoreWildcardPattern.options.json @@ -0,0 +1,13 @@ +{ + "$schema": "../../../../../../packages/@biomejs/biome/configuration_schema.json", + "linter": { + "rules": { + "correctness": { + "noUnusedVariables": { + "level": "error", + "options": {"ignore": {"class": ["*"]}} + } + } + } + } +} \ No newline at end of file diff --git a/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/validFunctionParameter.ts b/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/validFunctionParameter.ts new file mode 100644 index 000000000000..958cb79dd7be --- /dev/null +++ b/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/validFunctionParameter.ts @@ -0,0 +1,7 @@ +/* should not generate diagnostics */ + +function a(a: number) {} +a(1); + +function b({a, b}: {a: number, b: string}) {} +b({a: 1, b: "2"}); diff --git a/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/validFunctionParameter.ts.snap b/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/validFunctionParameter.ts.snap new file mode 100644 index 000000000000..c78b7b105db0 --- /dev/null +++ b/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/validFunctionParameter.ts.snap @@ -0,0 +1,16 @@ +--- +source: crates/biome_js_analyze/tests/spec_tests.rs +assertion_line: 155 +expression: validFunctionParameter.ts +--- +# Input +```ts +/* should not generate diagnostics */ + +function a(a: number) {} +a(1); + +function b({a, b}: {a: number, b: string}) {} +b({a: 1, b: "2"}); + +``` diff --git a/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/validIgnoredPattern.js b/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/validIgnoredPattern.js new file mode 100644 index 000000000000..dc5f786c2127 --- /dev/null +++ b/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/validIgnoredPattern.js @@ -0,0 +1,13 @@ +/* should not generate diagnostics */ + +// With ignore: { "*": ["ignored"] }, unused variables named ignored should be ignored +const ignored = 1; +const secondVar = 2; +console.log(secondVar); + +// With ignore: { "class": ["IgnoredClass"] }, unused classes named IgnoredClass should be ignored +class IgnoredClass {} + +// With ignore: { "function": ["*"] }, all unused functions should be ignored +function unusedFunction() {} +function anotherUnusedFunction() {} diff --git a/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/validIgnoredPattern.js.snap b/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/validIgnoredPattern.js.snap new file mode 100644 index 000000000000..eb9d6ce2ab14 --- /dev/null +++ b/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/validIgnoredPattern.js.snap @@ -0,0 +1,22 @@ +--- +source: crates/biome_js_analyze/tests/spec_tests.rs +assertion_line: 155 +expression: validIgnoredPattern.js +--- +# Input +```js +/* should not generate diagnostics */ + +// With ignore: { "*": ["ignored"] }, unused variables named ignored should be ignored +const ignored = 1; +const secondVar = 2; +console.log(secondVar); + +// With ignore: { "class": ["IgnoredClass"] }, unused classes named IgnoredClass should be ignored +class IgnoredClass {} + +// With ignore: { "function": ["*"] }, all unused functions should be ignored +function unusedFunction() {} +function anotherUnusedFunction() {} + +``` diff --git a/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/validIgnoredPattern.options.json b/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/validIgnoredPattern.options.json new file mode 100644 index 000000000000..3dc783dee886 --- /dev/null +++ b/crates/biome_js_analyze/tests/specs/correctness/noUnusedVariables/validIgnoredPattern.options.json @@ -0,0 +1,19 @@ +{ + "$schema": "../../../../../../packages/@biomejs/biome/configuration_schema.json", + "linter": { + "rules": { + "correctness": { + "noUnusedVariables": { + "level": "error", + "options": { + "ignore": { + "*": ["ignored"], + "class": ["IgnoredClass"], + "function": ["*"] + } + } + } + } + } + } +} diff --git a/crates/biome_rule_options/src/no_unused_variables.rs b/crates/biome_rule_options/src/no_unused_variables.rs index 367ab314dea1..bf14d7037d0d 100644 --- a/crates/biome_rule_options/src/no_unused_variables.rs +++ b/crates/biome_rule_options/src/no_unused_variables.rs @@ -7,6 +7,10 @@ pub struct NoUnusedVariablesOptions { /// Whether to ignore unused variables from an object destructuring with a spread. #[serde(skip_serializing_if = "Option::<_>::is_none")] pub ignore_rest_siblings: Option, + + /// An object defining ignored identifiers for different language constructs. + #[serde(skip_serializing_if = "Option::<_>::is_none")] + pub ignore: Option, } impl NoUnusedVariablesOptions { @@ -18,4 +22,47 @@ impl NoUnusedVariablesOptions { self.ignore_rest_siblings .unwrap_or(Self::DEFAULT_IGNORE_REST_SIBLINGS) } + + /// Returns [`Self::ignore`] if it is set. + /// Otherwise, returns an empty ignore object not matching anything. + pub fn ignore(&self) -> NoUnusedVariablesOptionsIgnore { + self.ignore.clone().unwrap_or_default() + } +} + +#[derive(Default, Clone, Debug, Deserialize, Deserializable, Merge, Eq, PartialEq, Serialize)] +#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] +#[serde(rename_all = "camelCase", deny_unknown_fields, default)] +pub struct NoUnusedVariablesOptionsIgnore { + /// An array of identifiers to ignore. Use "*" to ignore all identifiers. + #[serde(skip_serializing_if = "Option::<_>::is_none", rename = "*")] + pub all: Option]>>, + + /// An array of class names to ignore. Use "*" to ignore all identifiers. + #[serde(skip_serializing_if = "Option::<_>::is_none")] + pub class: Option]>>, + + /// An array of function names to ignore. Use "*" to ignore all identifiers. + #[serde(skip_serializing_if = "Option::<_>::is_none")] + pub function: Option]>>, + + /// An array of interface names to ignore. Use "*" to ignore all identifiers. + #[serde(skip_serializing_if = "Option::<_>::is_none")] + pub interface: Option]>>, + + /// An array of type aliases to ignore. Use "*" to ignore all identifiers. + #[serde(skip_serializing_if = "Option::<_>::is_none")] + pub type_alias: Option]>>, + + /// An array of type parameters to ignore. Use "*" to ignore all identifiers. + #[serde(skip_serializing_if = "Option::<_>::is_none")] + pub type_parameter: Option]>>, + + /// An array of variable names to ignore. Use "*" to ignore all identifiers. + #[serde(skip_serializing_if = "Option::<_>::is_none")] + pub variable: Option]>>, +} + +impl NoUnusedVariablesOptionsIgnore { + pub const IGNORE_ALL: &'static str = "*"; } diff --git a/packages/@biomejs/backend-jsonrpc/src/workspace.ts b/packages/@biomejs/backend-jsonrpc/src/workspace.ts index f67c4554d983..d04e5f6ef4ec 100644 --- a/packages/@biomejs/backend-jsonrpc/src/workspace.ts +++ b/packages/@biomejs/backend-jsonrpc/src/workspace.ts @@ -7353,6 +7353,10 @@ export type NoUnusedImportsOptions = {}; export type NoUnusedLabelsOptions = {}; export type NoUnusedPrivateClassMembersOptions = {}; export interface NoUnusedVariablesOptions { + /** + * An object defining ignored identifiers for different language constructs. + */ + ignore?: NoUnusedVariablesOptionsIgnore; /** * Whether to ignore unused variables from an object destructuring with a spread. */ @@ -8098,6 +8102,36 @@ export type Visibility = "public" | "package" | "private"; */ export type CustomRestrictedElements = Record; export type DependencyAvailability = boolean | string[]; +export interface NoUnusedVariablesOptionsIgnore { + /** + * An array of identifiers to ignore. Use "*" to ignore all identifiers. + */ + *?: string[]; + /** + * An array of class names to ignore. Use "*" to ignore all identifiers. + */ + class?: string[]; + /** + * An array of function names to ignore. Use "*" to ignore all identifiers. + */ + function?: string[]; + /** + * An array of interface names to ignore. Use "*" to ignore all identifiers. + */ + interface?: string[]; + /** + * An array of type aliases to ignore. Use "*" to ignore all identifiers. + */ + typeAlias?: string[]; + /** + * An array of type parameters to ignore. Use "*" to ignore all identifiers. + */ + typeParameter?: string[]; + /** + * An array of variable names to ignore. Use "*" to ignore all identifiers. + */ + variable?: string[]; +} export interface Hook { /** * The "position" of the closure function, starting from zero. diff --git a/packages/@biomejs/biome/configuration_schema.json b/packages/@biomejs/biome/configuration_schema.json index 7c3f5cfc67ff..37b4d5fbdf4c 100644 --- a/packages/@biomejs/biome/configuration_schema.json +++ b/packages/@biomejs/biome/configuration_schema.json @@ -5424,6 +5424,13 @@ "NoUnusedVariablesOptions": { "type": "object", "properties": { + "ignore": { + "description": "An object defining ignored identifiers for different language constructs.", + "anyOf": [ + { "$ref": "#/$defs/NoUnusedVariablesOptionsIgnore" }, + { "type": "null" } + ] + }, "ignoreRestSiblings": { "description": "Whether to ignore unused variables from an object destructuring with a spread.", "type": ["boolean", "null"] @@ -5431,6 +5438,47 @@ }, "additionalProperties": false }, + "NoUnusedVariablesOptionsIgnore": { + "type": "object", + "properties": { + "*": { + "description": "An array of identifiers to ignore. Use \"*\" to ignore all identifiers.", + "type": ["array", "null"], + "items": { "type": "string" } + }, + "class": { + "description": "An array of class names to ignore. Use \"*\" to ignore all identifiers.", + "type": ["array", "null"], + "items": { "type": "string" } + }, + "function": { + "description": "An array of function names to ignore. Use \"*\" to ignore all identifiers.", + "type": ["array", "null"], + "items": { "type": "string" } + }, + "interface": { + "description": "An array of interface names to ignore. Use \"*\" to ignore all identifiers.", + "type": ["array", "null"], + "items": { "type": "string" } + }, + "typeAlias": { + "description": "An array of type aliases to ignore. Use \"*\" to ignore all identifiers.", + "type": ["array", "null"], + "items": { "type": "string" } + }, + "typeParameter": { + "description": "An array of type parameters to ignore. Use \"*\" to ignore all identifiers.", + "type": ["array", "null"], + "items": { "type": "string" } + }, + "variable": { + "description": "An array of variable names to ignore. Use \"*\" to ignore all identifiers.", + "type": ["array", "null"], + "items": { "type": "string" } + } + }, + "additionalProperties": false + }, "NoUnwantedPolyfillioConfiguration": { "oneOf": [ { "$ref": "#/$defs/RulePlainConfiguration" },