Skip to content

Commit

Permalink
feat(useExhaustiveDependencies): add option to useExhaustiveDependenc…
Browse files Browse the repository at this point in the history
…ies to enable errors when the dependencies array is missing (#4149)
  • Loading branch information
simon-paris authored Oct 1, 2024
1 parent 2670095 commit 3baa9fc
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 1 deletion.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,16 @@ our [guidelines for writing a good changelog entry](https://github.com/biomejs/b

- Add [noOctalEscape](https://biomejs.dev/linter/rules/no-octal-escape/). Contributed by @fireairforce

#### Enhancements

- Add an option `reportUnnecessaryDependencies` to [useExhaustiveDependencies](https://biomejs.dev/linter/rules/use-exhaustive-dependencies/).

Defaults to true. When set to false, errors will be suppressed for React hooks that declare dependencies but do not use them.

Contributed by @simon-paris

- Add an option `reportMissingDependenciesArray` to [useExhaustiveDependencies](https://biomejs.dev/linter/rules/use-exhaustive-dependencies/). Contributed by @simon-paris

#### Bug fixes

- [noControlCharactersInRegex](https://www.biomejs.dev/linter/rules/no-control-characters-in-regex) no longer panics on regexes with incomplete escape sequences. Contributed by @Conaclos
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,10 @@ pub struct UseExhaustiveDependenciesOptions {
#[serde(default = "report_unnecessary_dependencies_default")]
pub report_unnecessary_dependencies: bool,

/// Whether to report an error when a hook has no dependencies array.
#[serde(default)]
pub report_missing_dependencies_array: bool,

/// List of hooks of which the dependencies should be validated.
#[serde(default)]
#[deserializable(validate = "non_empty")]
Expand All @@ -307,6 +311,7 @@ impl Default for UseExhaustiveDependenciesOptions {
fn default() -> Self {
Self {
report_unnecessary_dependencies: report_unnecessary_dependencies_default(),
report_missing_dependencies_array: false,
hooks: vec![],
}
}
Expand Down Expand Up @@ -407,6 +412,8 @@ impl HookConfigMaps {

/// Flags the possible fixes that were found
pub enum Fix {
/// When the entire dependencies array is missing
MissingDependenciesArray { function_name_range: TextRange },
/// When a dependency needs to be added.
AddDependency {
function_name_range: TextRange,
Expand Down Expand Up @@ -749,7 +756,13 @@ impl Rule for UseExhaustiveDependencies {
};

if result.dependencies_node.is_none() {
return vec![];
if options.report_missing_dependencies_array {
return vec![Fix::MissingDependenciesArray {
function_name_range: result.function_name_range,
}];
} else {
return vec![];
}
}

let component_function_range = component_function.text_range();
Expand Down Expand Up @@ -904,6 +917,9 @@ impl Rule for UseExhaustiveDependencies {

fn instances_for_signal(signal: &Self::State) -> Vec<String> {
match signal {
Fix::MissingDependenciesArray {
function_name_range: _,
} => vec![],
Fix::AddDependency { captures, .. } => vec![captures.0.clone()],
Fix::RemoveDependency { dependencies, .. } => dependencies
.iter()
Expand All @@ -920,6 +936,15 @@ impl Rule for UseExhaustiveDependencies {

fn diagnostic(ctx: &RuleContext<Self>, dep: &Self::State) -> Option<RuleDiagnostic> {
match dep {
Fix::MissingDependenciesArray {
function_name_range,
} => {
return Some(RuleDiagnostic::new(
rule_category!(),
function_name_range,
markup! {"This hook does not have a dependencies array"},
))
}
Fix::AddDependency {
function_name_range,
captures,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import {useEffect} from "react";

// should not report errors for the unused `b` when the reportMissingDependenciesArray option is false
function ReportMissingDependenciesArray() {
const [a] = useState(1);

useEffect(() => {
console.log(a);
});

return a;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
source: crates/biome_js_analyze/tests/spec_tests.rs
expression: reportMissingDependenciesArray.js
---
# Input
```jsx
import {useEffect} from "react";

// should not report errors for the unused `b` when the reportMissingDependenciesArray option is false
function ReportMissingDependenciesArray() {
const [a] = useState(1);

useEffect(() => {
console.log(a);
});

return a;
}

```

# Diagnostics
```
reportMissingDependenciesArray.js:7:5 lint/correctness/useExhaustiveDependencies ━━━━━━━━━━━━━━━━━━━
! This hook does not have a dependencies array
5 │ const [a] = useState(1);
6 │
> 7 │ useEffect(() => {
│ ^^^^^^^^^
8 │ console.log(a);
9 │ });
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"$schema": "../../../../../../packages/@biomejs/biome/configuration_schema.json",
"linter": {
"rules": {
"correctness": {
"useExhaustiveDependencies": {
"level": "error",
"options": {
"reportMissingDependenciesArray": true
}
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ hooks_incorrect_options.json:9:7 deserialize ━━━━━━━━━━━
i Known keys:

- reportUnnecessaryDependencies
- reportMissingDependenciesArray
- hooks
4 changes: 4 additions & 0 deletions packages/@biomejs/backend-jsonrpc/src/workspace.ts

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

5 changes: 5 additions & 0 deletions 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 3baa9fc

Please sign in to comment.