Skip to content

Commit

Permalink
feat(noUnusedVariables): add option to ignore unused function arguments
Browse files Browse the repository at this point in the history
  • Loading branch information
printfn committed May 17, 2024
1 parent b1e7be6 commit 91d7d43
Show file tree
Hide file tree
Showing 7 changed files with 163 additions and 8 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,8 @@ our [guidelines for writing a good changelog entry](https://github.com/biomejs/b
- Add [nursery/useThrowNewError](https://biomejs.dev/linter/rules/use-throw-new-error/).
Contributed by @minht11
- Add [nursery/useTopLevelRegex](https://biomejs.dev/linter/rules/use-top-level-regex), which enforces defining regular expressions at the top level of a module. [#2148](https://github.com/biomejs/biome/issues/2148) Contributed by @dyc3.
- [noUnusedVariables](https://biomejs.dev/linter/rules/no-unused-variables/) now supports an option to ignore unused function arguments.
Contributed by @printfn

#### Enhancements

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use biome_analyze::{
context::RuleContext, declare_rule, ActionCategory, FixKind, Rule, RuleDiagnostic,
};
use biome_console::markup;
use biome_deserialize_macros::Deserializable;
use biome_diagnostics::Applicability;
use biome_js_semantic::ReferencesExtensions;
use biome_js_syntax::binding_ext::{
Expand All @@ -17,6 +18,9 @@ use biome_js_syntax::{
TsInferType,
};
use biome_rowan::{AstNode, BatchMutationExt, Direction, SyntaxResult};
#[cfg(feature = "schemars")]
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

declare_rule! {
/// Disallow unused variables.
Expand Down Expand Up @@ -66,7 +70,7 @@ declare_rule! {
/// export function f<T>() {}
/// ```
///
/// # Valid
/// ### Valid
///
/// ```js
/// function foo(b) {
Expand All @@ -87,6 +91,20 @@ declare_rule! {
/// }
/// used_overloaded();
/// ```
///
/// ## Options
///
/// ```json
/// {
/// "//": "...",
/// "options": {
/// "args": "all"
/// }
/// }
/// ```
///
/// The "args" option can be set to "none" to disable argument checking
///
pub NoUnusedVariables {
version: "1.0.0",
name: "noUnusedVariables",
Expand All @@ -100,6 +118,26 @@ declare_rule! {
}
}

#[derive(Clone, Debug, Default, Deserialize, Deserializable, Eq, PartialEq, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct NoUnusedVariablesOptions {
/// Whether to check function arguments
#[serde(default)]
args: ArgsBehavior,
}

#[derive(Clone, Debug, Default, Deserialize, Deserializable, Eq, PartialEq, Serialize)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
#[serde(rename_all = "camelCase")]
pub enum ArgsBehavior {
/// All named arguments must be used
#[default]
All,
/// Do not check function arguments
None,
}

/// Suggestion if the bindnig is unused
#[derive(Debug)]
pub enum SuggestedFix {
Expand Down Expand Up @@ -141,7 +179,10 @@ fn suggestion_for_binding(binding: &AnyJsIdentifierBinding) -> Option<SuggestedF

// It is ok in some Typescripts constructs for a parameter to be unused.
// Returning None means is ok to be unused
fn suggested_fix_if_unused(binding: &AnyJsIdentifierBinding) -> Option<SuggestedFix> {
fn suggested_fix_if_unused(
binding: &AnyJsIdentifierBinding,
options: &NoUnusedVariablesOptions,
) -> Option<SuggestedFix> {
let decl = binding.declaration()?;
// It is fine to ignore unused rest spread siblings
if let node @ (AnyJsBindingDeclaration::JsObjectBindingPatternShorthandProperty(_)
Expand Down Expand Up @@ -176,14 +217,14 @@ fn suggested_fix_if_unused(binding: &AnyJsIdentifierBinding) -> Option<Suggested
}
AnyJsBindingDeclaration::TsPropertyParameter(_) => None,
AnyJsBindingDeclaration::JsFormalParameter(parameter) => {
if is_function_that_is_ok_parameter_not_be_used(&parameter.parent_function()) {
if options.args == ArgsBehavior::None || is_function_that_is_ok_parameter_not_be_used(&parameter.parent_function()) {
None
} else {
suggestion_for_binding(binding)
}
}
AnyJsBindingDeclaration::JsRestParameter(parameter) => {
if is_function_that_is_ok_parameter_not_be_used(&parameter.parent_function()) {
if options.args == ArgsBehavior::None || is_function_that_is_ok_parameter_not_be_used(&parameter.parent_function()) {
None
} else {
suggestion_for_binding(binding)
Expand Down Expand Up @@ -266,7 +307,7 @@ impl Rule for NoUnusedVariables {
type Query = Semantic<AnyJsIdentifierBinding>;
type State = SuggestedFix;
type Signals = Option<Self::State>;
type Options = ();
type Options = NoUnusedVariablesOptions;

fn run(ctx: &RuleContext<Self>) -> Option<Self::State> {
if ctx
Expand All @@ -281,6 +322,7 @@ impl Rule for NoUnusedVariables {
}

let binding = ctx.query();
let options = ctx.options();
let name = binding.name_token().ok()?;
let name = name.text_trimmed();

Expand All @@ -295,7 +337,7 @@ impl Rule for NoUnusedVariables {
return None;
}

let suggestion = suggested_fix_if_unused(binding)?;
let suggestion = suggested_fix_if_unused(binding, options)?;

let model = ctx.model();
if model.is_exported(binding) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"$schema": "../../../../../../packages/@biomejs/biome/configuration_schema.json",
"linter": {
"rules": {
"correctness": {
"noUnusedVariables": {
"level": "error",
"options": {
"args": "none"
}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/* should not generate diagnostics because we're ignoring unused arguments */

export function foo(a: string) {
return 5;
}

export function bar({ a, b = 5 }: { a: number, b?: number }) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
source: crates/biome_js_analyze/tests/spec_tests.rs
expression: validIgnoredArguments.ts
---
# Input
```ts
/* should not generate diagnostics because we're ignoring unused arguments */

export function foo(a: string) {
return 5;
}

export function bar({ a, b = 5 }: { a: number, b?: number }) {}

```
26 changes: 25 additions & 1 deletion packages/@biomejs/backend-jsonrpc/src/workspace.ts

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

52 changes: 51 additions & 1 deletion packages/@biomejs/biome/configuration_schema.json

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

0 comments on commit 91d7d43

Please sign in to comment.